<commit_before># MyGeom.py - API for easier Salome geompy usage
#
# Copyright (C) year  Stefan Reiterer - stefan.reiterer@magnasteyr.com
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

from __future__ import print_function

import salome
import geompy
import GEOM

from numpy import array
from numpy import float64 as data_type

# For future Versions of salome!
# from salome.geom import geomBuilder
# geompy = geomBuilder.New(salome.myStudy)

# Define help classes for more structured programming
class MyGeomObject(object):
    """
    Base class for all custom geometrical objects
    """
    def __init__(self,geomObject):
        self.geomObject = geomObject

    def addToStudy(self,studyName):
        """
        Adds Vertex to study and adds
        the name in the study
        """
        geompy.addToStudy(self.geomObject,studyName)
        self.studyName = studyName

    def getStudyName(self):
        return self.studyName

    def getGeomObject(self):
        return self.geomObject

    def setGeomObject(self,geom_object):
        self.geomObject = geom_object

class MyVertex(MyGeomObject):
    """
    Help class for storing vertices.
    Additionally stores coordinate of
    the Vertex

    """

    def __init__(self,x, y = 0.0, z = 0.0):

        if isinstance(x,GEOM._objref_GEOM_Object):
            if x.GetShapeType() == GEOM.VERTEX:
                self.setCoord(geompy.GetPosition(x)[:3])
                self.setGeomObject(x)
            else:
                raise ValueError("Error: This is no vertex!")
        elif isinstance(x,MyVertex):
            self.setCoord(x.getCoord())
            self.setGeomObject(x.getGeomObject())
        else:
            self.setCoord((x,y,z))
            self.setGeomObject(geompy.MakeVertex(x,y,z))

    def __eq__(self,q):
        """
        Two points are considered equal iff
        the coordinates are the same
        """
        if all(self.getCoord() == q.getCoord()):
            return True
        else:
            return False

    def setCoord(self,coord):
        self.coord = array(coord,dtype=data_type)

    def getCoord(self):
        return self.coord

class MyLine(MyGeomObject):
    """
    Help class for storing lines
    Holds two instances of MyVertex
    """
    def __init__(self,line_or_point,q = None):

        type = None

        if isinstance(line_or_point,MyVertex):
            self.p = line_or_point

        elif isinstance(line_or_point,GEOM._objref_GEOM_Object):
            type = geompy.ShapeIdToType(line_or_point.GetType())
            if type == 'LINE':
                subshapes = geompy.SubShapeAll(line_or_point,geompy.ShapeType['VERTEX'])
                self.p = MyVertex(subshapes[0])
                self.q = MyVertex(subshapes[-1])
            elif type == 'POINT':
                self.p = MyVertex(line_or_point)
        else:
            raise ValueError("This constructor does not support that option!")

        if q is None and (type != 'LINE' or type is None):
            raise ValueError("Second argument missing!")
        elif q is None and type == 'LINE':
            pass
        elif isinstance(q,GEOM._objref_GEOM_Object):
            type_q = geompy.ShapeIdToType(q.GetType())
            if type_q == 'POINT':
                self.q = MyVertex(q)
            else:
                raise ValueError("Error: second point is wrong type")
        elif isinstance(q,MyVertex):
                self.q = q
        else:
            raise ValueError("Error: second point is wrong type")

        self.geomObject = geompy.MakeLineTwoPnt(self.p.geomObject,self.q.geomObject)

    def getP(self):
        return self.p

    def setP(self,p):
        if isinstance(p,MyVertex):
            self.p = p
        elif isinstance(p,GEOM._objref_GEOM_Object):
            type = geompy.ShapeIdToType(line_or_point.GetType())

            if type == 'POINT':
                self.p = MyVertex(p)
            else:
                raise ValueError("Error: Point is wrong type!")

        else:
            raise ValueError("Error: Point is wrong type!")

    def getQ(self):
        return self.q

    def setQ(self,q):
        if isinstance(q,MyVertex):
            self.q = q
        elif isinstance(p,GEOM._objref_GEOM_Object):
            type = geompy.ShapeIdToType(line_or_point.GetType())

            if type == 'POINT':
                self.q = MyVertex(q)
            else:
                raise ValueError("Error: Point is wrong type!")

        else:
            raise ValueError("Error: Point is wrong type!")

    def __eq__(self,other):
        """
        Two Lines are considered to be the same iff they have the same endpoints
        (without order)
        """
        if (self.getP() == other.getP() and self.getQ() == other.getQ()) or (self.getQ() == other.getP() and self.getP() == other.getQ()):
            return True
        else:
            False
# Perhaps deprecate this and replace it by face construction and
# explosion

class MyVector(MyGeomObject):
    """
    Help class for vectors
    """
    def __init__(self,vec_or_point,q = None):

        if isinstance(vec_or_point,MyVertex):
            p_type = 'MyVertex'
        elif isinstance(vec_or_point,GEOM._objref_GEOM_Object):
            p_type = geompy.ShapeIdToType(vec_or_point.GetType())
        else:
            raise ValueError("This constructor does not support that option!")

        if isinstance(q,MyVertex):
            q_type = 'MyVertex'
        elif isinstance(q,GEOM._objref_GEOM_Object):
            q_type = geompy.ShapeIdToType(vec_or_point.GetType())
        elif q is None:
            pass
        else:
            raise ValueError("This constructor does not support that option!")

        if q is None:
            if p_type == 'MyVertex':
                self.q = vec_or_point
                self.p = MyVertex(0.0)
            elif p_type == 'POINT':
                self.q = MyVertex(vec_or_point)
                self.p = MyVertex(0.0)
            elif p_type == 'VECTOR':
                subshapes = geompy.SubShapeAll(vec_or_point,geompy.ShapeType['VERTEX'])
                self.p = MyVertex(subshapes[0])
                self.q = MyVertex(subshapes[-1])
            else:
                raise ValueError('Error: Wrong Type!')
        elif q_type == 'POINT':
            self.q = MyVertex(q)
            if p_type == 'MyVertex':
                self.p = vec_or_point
            elif  p_type == 'POINT':
                self.p = MyVertex(vec_or_point)
            else:
                raise ValueError('Error: Wrong Type!')
        elif q_type == 'MyVertex':
            self.q = q
            if p_type == 'MyVertex':
                self.p = vec_or_point
            elif  p_type == 'POINT':
                self.p = MyVertex(vec_or_point)
            else:
                raise ValueError('Error: Wrong Type!')
        else:
            raise ValueError('Error: Wrong Type!')

        self.geomObject = geompy.MakeVector(self.p.geomObject,self.q.geomObject)

    def getP(self):
        return self.p

    def getQ(self):
        return self.q

    def __eq__(self,other):
        """
        Two Vectors are considered to be the same iff they have the same startpoints and endpoints. Thats the only difference between a vector and a line.
        (without order)
        """
        if (self.getP() == other.getP() and self.getQ() == other.getQ()):
            return True
        else:
            False

class MyFace(MyGeomObject):
    """
    Help class for faces, and face related stuff
    """

    def __init__(self,face):
        """
        This init is a stub! It will be extended Later!
        """

        if face.GetShapeType() == GEOM.FACE:
            self.geomObject = face
        elif isinstance(face,MyFace):
            self.geomObject = face.getGeomObject()
        else:
            raise ValueError("Error: Shape is not a Face!")

    def ChangeOrientation(self,make_copy = False):
        if make_copy:
            return MyFace(geompy.ChangeOrientation(self.geomObject))
        else:
            self.geomObject = geompy.ChangeOrientation(self.geomObject)

class MyQuadrangleFromLines(MyGeomObject):
    """
    Help class for Quadrangles built from
    Lines.
    """

    def __init__(self,edges):
        self.geomObject = geompy.MakeFaceWires(
            [edge.geomObject for edge in edges],1)
        self.edges = edges

def addListToStudy(liste,string):
    """
    Function to add list of geom objects to a study,
    with numbered name
    """
    i = 0
    for object in liste:
        object.addToStudy(string + str(i))
        i+=1

def ExplodeSubShape(my_geom_object,type,add_to_study = True):
    """
    Explode Sub Shapes of certain Type. If add_to_study is
    True add all objects to study
    """
    geom_object = my_geom_object.geomObject
    subshapes = geompy.SubShapeAll(geom_object,geompy.ShapeType[type])
    if add_to_study:
        for sub in subshapes:
            name = geompy.SubShapeName(sub,geom_object)
            geompy.addToStudyInFather(geom_object,sub,name)

    return subshapes
<commit_msg>getter and setter of line<commit_after># MyGeom.py - API for easier Salome geompy usage
#
# Copyright (C) year  Stefan Reiterer - stefan.reiterer@magnasteyr.com
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

from __future__ import print_function

import salome
import geompy
import GEOM

from numpy import array
from numpy import float64 as data_type

# For future Versions of salome!
# from salome.geom import geomBuilder
# geompy = geomBuilder.New(salome.myStudy)

# Define help classes for more structured programming
class MyGeomObject(object):
    """
    Base class for all custom geometrical objects
    """
    def __init__(self,geomObject):
        self.geomObject = geomObject

    def addToStudy(self,studyName):
        """
        Adds Vertex to study and adds
        the name in the study
        """
        geompy.addToStudy(self.geomObject,studyName)
        self.studyName = studyName

    def getStudyName(self):
        return self.studyName

    def getGeomObject(self):
        return self.geomObject

    def setGeomObject(self,geom_object):
        self.geomObject = geom_object

class MyVertex(MyGeomObject):
    """
    Help class for storing vertices.
    Additionally stores coordinate of
    the Vertex

    """

    def __init__(self,x, y = 0.0, z = 0.0):

        if isinstance(x,GEOM._objref_GEOM_Object):
            if x.GetShapeType() == GEOM.VERTEX:
                self.setCoord(geompy.GetPosition(x)[:3])
                self.setGeomObject(x)
            else:
                raise ValueError("Error: This is no vertex!")
        elif isinstance(x,MyVertex):
            self.setCoord(x.getCoord())
            self.setGeomObject(x.getGeomObject())
        else:
            self.setCoord((x,y,z))
            self.setGeomObject(geompy.MakeVertex(x,y,z))

    def __eq__(self,q):
        """
        Two points are considered equal iff
        the coordinates are the same
        """
        if all(self.getCoord() == q.getCoord()):
            return True
        else:
            return False

    def setCoord(self,coord):
        self.coord = array(coord,dtype=data_type)

    def getCoord(self):
        return self.coord

class MyLine(MyGeomObject):
    """
    Help class for storing lines
    Holds two instances of MyVertex
    """
    def __init__(self,line_or_point,q = None):

        if isinstance(line_or_point,GEOM._objref_GEOM_Object):
            type = geompy.ShapeIdToType(line_or_point.GetType())
            if type == 'LINE' and q is None:
                subshapes = geompy.SubShapeAll(line_or_point,geompy.ShapeType['VERTEX'])
                line_or_point = subshapes[0]
                q = subshapes[-1]
            elif type == 'LINE' and q is not None:
                raise ValueError("Wrong Type!")

        self.setP(line_or_point)
        self.setQ(q)

        self.geomObject = geompy.MakeLineTwoPnt(self.getP().getGeomObject(),self.getQ().getGeomObject())

    def getP(self):
        return self.p

    def setP(self,p):
        if isinstance(p,MyVertex):
            self.p = p
        elif isinstance(p,GEOM._objref_GEOM_Object):
            type = p.GetShapeType()

            if type == GEOM.VERTEX:
                self.p = MyVertex(p)
            else:
                raise ValueError("Error: Point is wrong type!")

        else:
            raise ValueError("Error: Point is wrong type!")

    def getQ(self):
        return self.q

    def setQ(self,q):
        if isinstance(q,MyVertex):
            self.q = q
        elif isinstance(q,GEOM._objref_GEOM_Object):
            type = q.GetShapeType()

            if type == GEOM.VERTEX:
                self.q = MyVertex(q)
            else:
                raise ValueError("Error: Point is wrong type!")

        else:
            raise ValueError("Error: Point is wrong type!")

    def __eq__(self,other):
        """
        Two Lines are considered to be the same iff they have the same endpoints
        (without order)
        """
        if (self.getP() == other.getP() and self.getQ() == other.getQ()) or (self.getQ() == other.getP() and self.getP() == other.getQ()):
            return True
        else:
            False
# Perhaps deprecate this and replace it by face construction and
# explosion

class MyVector(MyGeomObject):
    """
    Help class for vectors
    """
    def __init__(self,vec_or_point,q = None):

        if isinstance(vec_or_point,MyVertex):
            p_type = 'MyVertex'
        elif isinstance(vec_or_point,GEOM._objref_GEOM_Object):
            p_type = geompy.ShapeIdToType(vec_or_point.GetType())
        else:
            raise ValueError("This constructor does not support that option!")

        if isinstance(q,MyVertex):
            q_type = 'MyVertex'
        elif isinstance(q,GEOM._objref_GEOM_Object):
            q_type = geompy.ShapeIdToType(vec_or_point.GetType())
        elif q is None:
            pass
        else:
            raise ValueError("This constructor does not support that option!")

        if q is None:
            if p_type == 'MyVertex':
                self.q = vec_or_point
                self.p = MyVertex(0.0)
            elif p_type == 'POINT':
                self.q = MyVertex(vec_or_point)
                self.p = MyVertex(0.0)
            elif p_type == 'VECTOR':
                subshapes = geompy.SubShapeAll(vec_or_point,geompy.ShapeType['VERTEX'])
                self.p = MyVertex(subshapes[0])
                self.q = MyVertex(subshapes[-1])
            else:
                raise ValueError('Error: Wrong Type!')
        elif q_type == 'POINT':
            self.q = MyVertex(q)
            if p_type == 'MyVertex':
                self.p = vec_or_point
            elif  p_type == 'POINT':
                self.p = MyVertex(vec_or_point)
            else:
                raise ValueError('Error: Wrong Type!')
        elif q_type == 'MyVertex':
            self.q = q
            if p_type == 'MyVertex':
                self.p = vec_or_point
            elif  p_type == 'POINT':
                self.p = MyVertex(vec_or_point)
            else:
                raise ValueError('Error: Wrong Type!')
        else:
            raise ValueError('Error: Wrong Type!')

        self.geomObject = geompy.MakeVector(self.p.geomObject,self.q.geomObject)

    def getP(self):
        return self.p

    def setP(self,p):
        if isinstance(p,MyVertex):
            self.p = p
        elif isinstance(p,GEOM._objref_GEOM_Object):
            type = p.GetShapeType()

            if type == GEOM.VERTEX:
                self.p = MyVertex(p)
            else:
                raise ValueError("Error: Point is wrong type!")

        else:
            raise ValueError("Error: Point is wrong type!")

    def getQ(self):
        return self.q

    def setQ(self,q):
        if isinstance(q,MyVertex):
            self.q = q
        elif isinstance(q,GEOM._objref_GEOM_Object):
            type = q.GetShapeType()

            if type == GEOM.VERTEX:
                self.q = MyVertex(q)
            else:
                raise ValueError("Error: Point is wrong type!")

        else:
            raise ValueError("Error: Point is wrong type!")

    def __eq__(self,other):
        """
        Two Vectors are considered to be the same iff they have the same startpoints and endpoints. Thats the only difference between a vector and a line.
        (without order)
        """
        if (self.getP() == other.getP() and self.getQ() == other.getQ()):
            return True
        else:
            False

class MyFace(MyGeomObject):
    """
    Help class for faces, and face related stuff
    """

    def __init__(self,face):
        """
        This init is a stub! It will be extended Later!
        """

        if face.GetShapeType() == GEOM.FACE:
            self.geomObject = face
        elif isinstance(face,MyFace):
            self.geomObject = face.getGeomObject()
        else:
            raise ValueError("Error: Shape is not a Face!")

    def ChangeOrientation(self,make_copy = False):
        if make_copy:
            return MyFace(geompy.ChangeOrientation(self.geomObject))
        else:
            self.geomObject = geompy.ChangeOrientation(self.geomObject)

class MyQuadrangleFromLines(MyGeomObject):
    """
    Help class for Quadrangles built from
    Lines.
    """

    def __init__(self,edges):
        self.geomObject = geompy.MakeFaceWires(
            [edge.geomObject for edge in edges],1)
        self.edges = edges

def addListToStudy(liste,string):
    """
    Function to add list of geom objects to a study,
    with numbered name
    """
    i = 0
    for object in liste:
        object.addToStudy(string + str(i))
        i+=1

def ExplodeSubShape(my_geom_object,type,add_to_study = True):
    """
    Explode Sub Shapes of certain Type. If add_to_study is
    True add all objects to study
    """
    geom_object = my_geom_object.geomObject
    subshapes = geompy.SubShapeAll(geom_object,geompy.ShapeType[type])
    if add_to_study:
        for sub in subshapes:
            name = geompy.SubShapeName(sub,geom_object)
            geompy.addToStudyInFather(geom_object,sub,name)

    return subshapes
<|endoftext|>


<commit_before>#!/usr/bin/env python
#coding: utf-8

"""
mdfmonitor - Monitor the file moification
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The **mdfmonitor** is Python module about monitoring files modification using timestamp and body.

How to use:

It's simple.
1. Import this module.
2. Create `ModificationMonitor` class's instance.
3. Append file or files to instance using add_file method.
4. using Python for sentence, You can write anything under for sentence.

    >>> from mdfmonitor import ModificationMonitor
    >>> monitor = ModificationMonitor()
    >>> monitor.add_file("README.md")
    >>> for mdf in monitor.monitor():
    ...     print "Old timestamp: %s" % mdf.old_mtime
    ...     print "New timestamp: %s" % mdf.new_mtime
    ...     print "manager: %s" % str(mdf.manager.o_repository)
    ...     print "Diff".center(30,"=")
    ...     print mdf.diff

"""

import os
import sys
import time
import difflib

__version__ = "0.1.1b"

class DuplicationError(BaseException):
    """Raise this Error if you add duplication file."""

    pass

class ModificationMonitor(object):
    """The ModificationMonitor can monitoring file modification.
    usage:

    it's simple.
    1. Create instance (call this instance `monitor` from now).
    2. Append file to instance using `add_file` or `add_files` method.
       Monitor has a file repository, monitor append file to repository using
       `add_file` method. Please put a file name to argument. If you use
       `add_files` method and put list of file to argument, Monitor append
       files to repository.
    3. Run monitor uring `monitor` method.
       The `monitor` method is generator, return FileModificationObject.

    """

    def __init__(self):

        self.f_repository = []

    def add_file(self, file, **kwargs):
        """Append a file to file repository.

        For file monitoring, monitor instance needs file.
        Please put the name of file to `file` argument.

        :param file: the name of file you want monitor.

        """

        if os.access(file, os.F_OK):

            if file in self.f_repository:
                raise DuplicationError("file already added.")

            self.f_repository.append(file)

        else:
            raise IOError("file not found.")

    def add_files(self, filelist, **kwargs):
        """Append files to file repository.

        ModificationMonitor can append files to repository using this.
        Please put the list of file names to `filelist` argument.

        :param filelist: the list of file nmaes
        """

        # check filelist is list type
        if not isinstance(filelist, list):
            raise TypeError("request the list type.")

        for file in filelist:
            self.add_file(file)

    def monitor(self, sleep=5):
        """Run file modification monitor.

        The monitor can catch file modification using timestamp and file body.
        Monitor has timestamp data and file body data. And insert timestamp
        data and file body data before into while roop. In while roop, monitor
        get new timestamp and file body, and then monitor compare new timestamp
        to originaltimestamp. If new timestamp and file body differ original,
        monitor regard thease changes as `modification`. Then monitor create
        FileModificationObject, yield this object.

        :param sleep: How times do you sleep in while roop.
        """

        manager = FileModificationObjectManager()

        timestamps = {}
        filebodies = {}

        # register original timestamp and filebody to dict
        for file in self.f_repository:
            timestamps[file] = self._get_mtime(file)
            filebodies[file] = open(file).read()

        while True:

            # file modification to object
            for file in self.f_repository:

                mtime = timestamps[file]
                fbody = filebodies[file]

                checker = self._check_modify(file, mtime, fbody)

                # file not modify -> continue
                if not checker:
                    continue

                # file modifies -> create the modification object

                new_mtime = self._get_mtime(file)
                new_fbody = open(file).read()

                obj = FileModificationObject(
                        file,
                        (mtime, new_mtime),
                        (fbody, new_fbody) )

                # overwrite new timestamp and filebody
                timestamps[file] = new_mtime
                filebodies[file] = new_fbody

                # append file modification object to manager
                manager.add_object(obj)

             # return new modification object
                yield obj

            time.sleep(sleep)

    def _get_mtime(self, file):

        return os.stat(file).st_mtime

    def _check_modify(self, file, o_mtime, o_fbody):

        n_mtime = self._get_mtime(file)
        n_fbody = open(file).read()

        if n_mtime == o_mtime:
            return False

        else:

            if n_fbody == o_fbody:
                return False

            else:

                return True

class FileModificationObjectManager(object):
    """

    """

    def __init__(self):

        self.o_repository = []

        self.__is_iterable = False
        self.__r_pointer = 0

    def add_object(self, obj):

        self.o_repository.append(obj)

        obj._set_manager(self)

        if not self.__is_iterable:
            self.__is_iterable = True

        return self

    def __iter__(self):

        if not self.__is_iterable:
            raise TypeError(
                    "'%s' object is not iterable" % self.__class__.__name__)
            return self

    def next(self):

        if not self.__is_iterable:
            raise TypeError(
                    "'%s' object is not iterable" % self.__class__.__name__)

            if self.__r_pointer == len(self.o_repository):
                raise StopIteration

        result = self.o_repository[self.__r_pointer]
        self.__r_pointer += 1
        return result

    def __next__(self):

        return self.next()

    def seek(self, offset):

        self.__r_pointer = offset

class FileModificationObject(object):

    def __init__(self, file, t_mtime, t_fbody):

        self.file = file

        self.new_mtime, self.old_mtime = t_mtime
        self.new_fbody, self.old_fbody = t_fbody

        self.manager = None
        self.diff = self._diffgen()

    def _set_manager(self, manager):

        self.manager = manager

    def _diffgen(self):

        contents = []

        for line  in difflib.unified_diff(
                self.old_fbody.splitlines(),
                self.new_fbody.splitlines(),
                "old/"+self.file, "new/"+self.file,
                self._strftime(self.old_mtime),
                self._strftime(self.new_mtime)):

            contents.append(line)

        return "\n".join(contents)

    def _strftime(self, etime):
        return time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(etime))

<commit_msg>write FileModificationManager document<commit_after>#!/usr/bin/env python
#coding: utf-8

"""
mdfmonitor - Monitor the file moification
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The **mdfmonitor** is Python module about monitoring files modification using timestamp and body.

How to use:

It's simple.
1. Import this module.
2. Create `ModificationMonitor` class's instance.
3. Append file or files to instance using add_file method.
4. using Python for sentence, You can write anything under for sentence.

    >>> from mdfmonitor import ModificationMonitor
    >>> monitor = ModificationMonitor()
    >>> monitor.add_file("README.md")
    >>> for mdf in monitor.monitor():
    ...     print "Old timestamp: %s" % mdf.old_mtime
    ...     print "New timestamp: %s" % mdf.new_mtime
    ...     print "manager: %s" % str(mdf.manager.o_repository)
    ...     print "Diff".center(30,"=")
    ...     print mdf.diff

"""

import os
import sys
import time
import difflib

__version__ = "0.1.1b"

class DuplicationError(BaseException):
    """Raise this Error if you add duplication file."""

    pass

class ModificationMonitor(object):
    """The ModificationMonitor can monitoring file modification.
    usage:

    it's simple.
    1. Create instance (call this instance `monitor` from now).
    2. Append file to instance using `add_file` or `add_files` method.
       Monitor has a file repository, monitor append file to repository using
       `add_file` method. Please put a file name to argument. If you use
       `add_files` method and put list of file to argument, Monitor append
       files to repository.
    3. Run monitor uring `monitor` method.
       The `monitor` method is generator, return FileModificationObject.

    """

    def __init__(self):

        self.f_repository = []

    def add_file(self, file, **kwargs):
        """Append a file to file repository.

        For file monitoring, monitor instance needs file.
        Please put the name of file to `file` argument.

        :param file: the name of file you want monitor.

        """

        if os.access(file, os.F_OK):

            if file in self.f_repository:
                raise DuplicationError("file already added.")

            self.f_repository.append(file)

        else:
            raise IOError("file not found.")

    def add_files(self, filelist, **kwargs):
        """Append files to file repository.

        ModificationMonitor can append files to repository using this.
        Please put the list of file names to `filelist` argument.

        :param filelist: the list of file nmaes
        """

        # check filelist is list type
        if not isinstance(filelist, list):
            raise TypeError("request the list type.")

        for file in filelist:
            self.add_file(file)

    def monitor(self, sleep=5):
        """Run file modification monitor.

        The monitor can catch file modification using timestamp and file body.
        Monitor has timestamp data and file body data. And insert timestamp
        data and file body data before into while roop. In while roop, monitor
        get new timestamp and file body, and then monitor compare new timestamp
        to originaltimestamp. If new timestamp and file body differ original,
        monitor regard thease changes as `modification`. Then monitor create
        instance of FileModificationObjectManager and FileModificationObject,
        and monitor insert FileModificationObject to FileModificationObject-
        Manager. Then, yield this object.

        :param sleep: How times do you sleep in while roop.
        """

        manager = FileModificationObjectManager()

        timestamps = {}
        filebodies = {}

        # register original timestamp and filebody to dict
        for file in self.f_repository:
            timestamps[file] = self._get_mtime(file)
            filebodies[file] = open(file).read()

        while True:

            # file modification to object
            for file in self.f_repository:

                mtime = timestamps[file]
                fbody = filebodies[file]

                checker = self._check_modify(file, mtime, fbody)

                # file not modify -> continue
                if not checker:
                    continue

                # file modifies -> create the modification object

                new_mtime = self._get_mtime(file)
                new_fbody = open(file).read()

                obj = FileModificationObject(
                        file,
                        (mtime, new_mtime),
                        (fbody, new_fbody) )

                # overwrite new timestamp and filebody
                timestamps[file] = new_mtime
                filebodies[file] = new_fbody

                # append file modification object to manager
                manager.add_object(obj)

             # return new modification object
                yield obj

            time.sleep(sleep)

    def _get_mtime(self, file):

        return os.stat(file).st_mtime

    def _check_modify(self, file, o_mtime, o_fbody):

        n_mtime = self._get_mtime(file)
        n_fbody = open(file).read()

        if n_mtime == o_mtime:
            return False

        else:

            if n_fbody == o_fbody:
                return False

            else:

                return True

class FileModificationObjectManager(object):
    """This manager manages file modification objects.

    Manager has a history list of FileModificationObject. Object can refer to
    any object what above or below position. Maager is iterable if manager was
    added object. If manager has not any object, manager is not iterable.
    """

    def __init__(self):

        self.o_repository = []

        self.__is_iterable = False
        self.__r_pointer = 0

    def add_object(self, obj):

        self.o_repository.append(obj)

        obj._set_manager(self)

        if not self.__is_iterable:
            self.__is_iterable = True

        return self

    def __iter__(self):

        if not self.__is_iterable:
            raise TypeError(
                    "'%s' object is not iterable" % self.__class__.__name__)
            return self

    def next(self):

        if not self.__is_iterable:
            raise TypeError(
                    "'%s' object is not iterable" % self.__class__.__name__)

            if self.__r_pointer == len(self.o_repository):
                raise StopIteration

        result = self.o_repository[self.__r_pointer]
        self.__r_pointer += 1
        return result

    def __next__(self):

        return self.next()

    def seek(self, offset):

        self.__r_pointer = offset

class FileModificationObject(object):

    def __init__(self, file, t_mtime, t_fbody):

        self.file = file

        self.new_mtime, self.old_mtime = t_mtime
        self.new_fbody, self.old_fbody = t_fbody

        self.manager = None
        self.diff = self._diffgen()

    def _set_manager(self, manager):

        self.manager = manager

    def _diffgen(self):

        contents = []

        for line  in difflib.unified_diff(
                self.old_fbody.splitlines(),
                self.new_fbody.splitlines(),
                "old/"+self.file, "new/"+self.file,
                self._strftime(self.old_mtime),
                self._strftime(self.new_mtime)):

            contents.append(line)

        return "\n".join(contents)

    def _strftime(self, etime):
        return time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(etime))

<|endoftext|>


<commit_before>from django.dispatch import receiver

from foodsaving.groups.models import Group
from foodsaving.invitations.signals import invitation_accepted
from foodsaving.users.api import pre_user_delete

@receiver(pre_user_delete)
def delete_user_handler(sender, **kwargs):
    user = kwargs.get('user')
    for _ in Group.objects.filter(members__in=[user, ]):
        _.members.remove(user)

@receiver(invitation_accepted)
def handle_invitation_accepted(sender, **kwargs):
    # TODO add invited_by to group membership
    group = kwargs.get('group')
    user = kwargs.get('accepted_user')
    group.members.add(user)
<commit_msg>remove todo<commit_after>from django.dispatch import receiver

from foodsaving.groups.models import Group
from foodsaving.invitations.signals import invitation_accepted
from foodsaving.users.api import pre_user_delete

@receiver(pre_user_delete)
def delete_user_handler(sender, **kwargs):
    user = kwargs.get('user')
    for _ in Group.objects.filter(members__in=[user, ]):
        _.members.remove(user)

@receiver(invitation_accepted)
def handle_invitation_accepted(sender, **kwargs):
    group = kwargs.get('group')
    user = kwargs.get('accepted_user')
    group.members.add(user)
<|endoftext|>


<commit_before>"""Prowl notification service."""
import asyncio
import logging

import async_timeout
import voluptuous as vol

from homeassistant.components.notify import (
    ATTR_DATA,
    ATTR_TITLE,
    ATTR_TITLE_DEFAULT,
    PLATFORM_SCHEMA,
    BaseNotificationService,
)
from homeassistant.const import CONF_API_KEY, HTTP_OK
from homeassistant.helpers.aiohttp_client import async_get_clientsession
import homeassistant.helpers.config_validation as cv

_LOGGER = logging.getLogger(__name__)
_RESOURCE = "https://api.prowlapp.com/publicapi/"

PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({vol.Required(CONF_API_KEY): cv.string})

async def async_get_service(hass, config, discovery_info=None):
    """Get the Prowl notification service."""
    return ProwlNotificationService(hass, config[CONF_API_KEY])

class ProwlNotificationService(BaseNotificationService):
    """Implement the notification service for Prowl."""

    def __init__(self, hass, api_key):
        """Initialize the service."""
        self._hass = hass
        self._api_key = api_key

    async def async_send_message(self, message, **kwargs):
        """Send the message to the user."""
        response = None
        session = None
        url = f"{_RESOURCE}add"
        data = kwargs.get(ATTR_DATA)
        payload = {
            "apikey": self._api_key,
            "application": "Home-Assistant",
            "event": kwargs.get(ATTR_TITLE, ATTR_TITLE_DEFAULT),
            "description": message,
            "priority": data["priority"] if data and "priority" in data else 0,
        }
        if data.get("url"):
            payload["url"] = data["url"]

        _LOGGER.debug("Attempting call Prowl service at %s", url)
        session = async_get_clientsession(self._hass)

        try:
            with async_timeout.timeout(10):
                response = await session.post(url, data=payload)
                result = await response.text()

            if response.status != HTTP_OK or "error" in result:
                _LOGGER.error(
                    "Prowl service returned http status %d, response %s",
                    response.status,
                    result,
                )
        except asyncio.TimeoutError:
            _LOGGER.error("Timeout accessing Prowl at %s", url)
<commit_msg>Fix optional data payload in Prowl messaging service (#48868)<commit_after>"""Prowl notification service."""
import asyncio
import logging

import async_timeout
import voluptuous as vol

from homeassistant.components.notify import (
    ATTR_DATA,
    ATTR_TITLE,
    ATTR_TITLE_DEFAULT,
    PLATFORM_SCHEMA,
    BaseNotificationService,
)
from homeassistant.const import CONF_API_KEY, HTTP_OK
from homeassistant.helpers.aiohttp_client import async_get_clientsession
import homeassistant.helpers.config_validation as cv

_LOGGER = logging.getLogger(__name__)
_RESOURCE = "https://api.prowlapp.com/publicapi/"

PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({vol.Required(CONF_API_KEY): cv.string})

async def async_get_service(hass, config, discovery_info=None):
    """Get the Prowl notification service."""
    return ProwlNotificationService(hass, config[CONF_API_KEY])

class ProwlNotificationService(BaseNotificationService):
    """Implement the notification service for Prowl."""

    def __init__(self, hass, api_key):
        """Initialize the service."""
        self._hass = hass
        self._api_key = api_key

    async def async_send_message(self, message, **kwargs):
        """Send the message to the user."""
        response = None
        session = None
        url = f"{_RESOURCE}add"
        data = kwargs.get(ATTR_DATA)
        payload = {
            "apikey": self._api_key,
            "application": "Home-Assistant",
            "event": kwargs.get(ATTR_TITLE, ATTR_TITLE_DEFAULT),
            "description": message,
            "priority": data["priority"] if data and "priority" in data else 0,
        }
        if data and data.get("url"):
            payload["url"] = data["url"]

        _LOGGER.debug("Attempting call Prowl service at %s", url)
        session = async_get_clientsession(self._hass)

        try:
            with async_timeout.timeout(10):
                response = await session.post(url, data=payload)
                result = await response.text()

            if response.status != HTTP_OK or "error" in result:
                _LOGGER.error(
                    "Prowl service returned http status %d, response %s",
                    response.status,
                    result,
                )
        except asyncio.TimeoutError:
            _LOGGER.error("Timeout accessing Prowl at %s", url)
<|endoftext|>


<commit_before>"""
.. module:: elements
    :platform: Unix, Windows
    :synopsis: Provides classes representing geometry and topology elements

.. moduleauthor:: Onur Rauf Bingol <orbingol@gmail.com>

"""

import copy

# Abstract class for geometric entities
class AbstractElement(object):
    """ Abstract base class for all geometric entities. """
    def __init__(self):
        self._id = 0  # element ID
        self._data = []  # data storage array

    def __copy__(self):
        cls = self.__class__
        result = cls.__new__(cls)
        result.__dict__.update(self.__dict__)
        return result

    def __deepcopy__(self, memo):
        # Don't copy self reference
        cls = self.__class__
        result = cls.__new__(cls)
        memo[id(self)] = result
        # Copy all other attributes
        for k, v in self.__dict__.items():
            setattr(result, k, copy.deepcopy(v, memo))
        return result

    def __len__(self):
        return len(self._data)

    def __getitem__(self, key):
        return self._data[key]

    def __iter__(self):
        return iter(self._data)

    def __reversed__(self):
        return reversed(self._data)

    @property
    def id(self):
        """ Identifier for the geometric entity.

        It must be an integer number, otherwise the setter will raise a *ValueError*.

        :getter: Gets the identifier
        :setter: Sets the identifier
        """
        return self._id

    @id.setter
    def id(self, value):
        if not isinstance(value, int):
            raise ValueError("Identifier value must be an integer")
        self._id = value

# Vertex class
class Vertex(AbstractElement):
    """ Representation of a 3-dimensional vertex entity with its parametric position. """
    def __init__(self):
        super(Vertex, self).__init__()
        self._data = [0.0, 0.0, 0.0]  # spatial coordinates
        self._uv = [0.0, 0.0]  # parametric coordinates
        self._inside = False  # flag for trimming

    def __str__(self):
        return "Vertex " + str(self._id) + " " + str(self._data)

    __repr__ = __str__

    def __cmp__(self, other):
        return (self.id > other.id) - (self.id < other.id)

    def __eq__(self, other):
        return self.id == other.id

    def __ne__(self, other):
        return self.id != other.id

    def __lt__(self, other):
        return self.id < other.id

    def __le__(self, other):
        return self.id <= other.id

    def __gt__(self, other):
        return self.id > other.id

    def __ge__(self, other):
        return self.id >= other.id

    def __nonzero__(self):
        # For Python 2 compatibility
        return self.__bool__()

    def __bool__(self):
        # For Python 3 compatibility
        return self.inside

    def __add__(self, other):
        if not isinstance(other, self.__class__):
            raise TypeError("Can only add Vertex objects")
        res_data = [0.0 for _ in range(3)]
        for idx in range(3):
            res_data[idx] = self.data[idx] + other.data[idx]
        res_uv = [0.0 for _ in range(2)]
        for idx in range(2):
            res_uv[idx] = self.uv[idx] + other.uv[idx]
        res_val = self.__class__()
        res_val.data = res_data
        res_val.uv = res_uv
        return res_val

    def __sub__(self, other):
        if not isinstance(other, self.__class__):
            raise TypeError("Can only subtract Vertex objects")
        res_data = [0.0 for _ in range(3)]
        for idx in range(3):
            res_data[idx] = self.data[idx] - other.data[idx]
        res_uv = [0.0 for _ in range(2)]
        for idx in range(2):
            res_uv[idx] = self.uv[idx] - other.uv[idx]
        res_val = self.__class__()
        res_val.data = res_data
        res_val.uv = res_uv
        return res_val

    def __div__(self, other):
        return self.__truediv__(other)

    def __truediv__(self, other):
        if not isinstance(other, (float, int)):
            raise TypeError("Can only divide by a float or an integer")
        res_data = [0.0 for _ in range(3)]
        for idx in range(3):
            res_data[idx] = self.data[idx] / float(other)
        res_uv = [0.0 for _ in range(2)]
        for idx in range(2):
            res_uv[idx] = self.uv[idx] / float(other)
        res_val = self.__class__()
        res_val.data = res_data
        res_val.uv = res_uv
        return res_val

    @property
    def x(self):
        """ x-component of the vertex

        :getter: Gets the x-component of the vertex
        :setter: Sets the x-component of the vertex
        :type: float
        """
        return self._data[0]

    @x.setter
    def x(self, value):
        self._data[0] = float(value)

    @property
    def y(self):
        """ y-component of the vertex

        :getter: Gets the y-component of the vertex
        :setter: Sets the y-component of the vertex
        :type: float
        """
        return self._data[1]

    @y.setter
    def y(self, value):
        self._data[1] = float(value)

    @property
    def z(self):
        """ z-component of the vertex

        :getter: Gets the z-component of the vertex
        :setter: Sets the z-component of the vertex
        :type: float
        """
        return self._data[2]

    @z.setter
    def z(self, value):
        self._data[2] = float(value)

    @property
    def u(self):
        """ Parametric u-component of the vertex

        :getter: Gets the u-component of the vertex
        :setter: Sets the u-component of the vertex
        :type: float
        """
        return self._uv[0]

    @u.setter
    def u(self, value):
        self._uv[0] = float(value)

    @property
    def v(self):
        """ Parametric v-component of the vertex

        :getter: Gets the v-component of the vertex
        :setter: Sets the v-component of the vertex
        :type: float
        """
        return self._uv[1]

    @v.setter
    def v(self, value):
        self._uv[1] = float(value)

    @property
    def uv(self):
        """ Parametric (u,v) pair of the vertex

        :getter: Gets the uv-component of the vertex
        :setter: Sets the uv-component of the vertex
        :type: list, tuple
        """
        return tuple(self._uv)

    @uv.setter
    def uv(self, value):
        if not isinstance(value, (list, tuple)):
            raise TypeError("UV data input must be a list or tuple")
        if len(value) != 2:
            raise ValueError("UV must have 2 components")
        self._uv = list(value)

    @property
    def inside(self):
        """ Inside-outside flag

        :getter: Gets the flag
        :setter: Sets the flag
        :type: bool
        """
        return self._inside

    @inside.setter
    def inside(self, value):
        self._inside = bool(value)

    @property
    def data(self):
        """ (x,y,z) components of the vertex.

        :getter: Gets the 3-dimensional components
        :setter: Sets the 3-dimensional components
        """
        return tuple(self._data)

    @data.setter
    def data(self, value):
        if not isinstance(value, (list, tuple)):
            raise TypeError("Vertex data must be a list or tuple")
        if len(value) != 3:
            raise ValueError("Vertex can only store 3 components")
        self._data = list(value)

# Triangle class
class Triangle(AbstractElement):
    """ Representation of a triangular geometric entity composed of vertices. """
    def __init__(self):
        super(Triangle, self).__init__()
        self._inside = False  # flag for trimming

    def __str__(self):
        return "Triangle " + str(self._id)

    __repr__ = __str__

    @property
    def vertices(self):
        """ Vertices of the triangle

        :getter: Gets the list of vertices
        :type: tuple
        """
        return tuple(self._data)

    @property
    def vertices_raw(self):
        """ Vertices which generates a closed triangle

        Adds the first vertex as a last element of the return value (good for plotting)

        :getter: Gets the list of vertices
        :type: list
        """
        v_raw = []
        for v in self._data:
            v_raw.append(v.data)
        # Add the first vertex data as a last element (for plotting modules)
        if len(self._data) > 0:
            v_raw.append(self._data[0].data)
        return v_raw

    @property
    def vertices_uv(self):
        """ Parametric coordinates of the triangle vertices

        :getter: Gets the parametric coordinates of the vertices
        :type: list
        """
        data = self.vertices
        res = [data[idx].uv for idx in range(3)]
        return res

    @property
    def edges(self):
        """ Edges of the triangle

        :getter: Gets the list of vertices that generates the edges of the triangle
        :type: list
        """
        data = self.vertices_raw
        res = [[] for _ in range(3)]
        for idx in range(3):
            res[idx] = [data[idx], data[idx + 1]]
        return res

    @property
    def vertex_ids(self):
        """ Gets vertex number list.

        Vertex numbering starts from 1.
        """
        v_idx = []
        for v in self._data:
            v_idx.append(v.id)
        return v_idx

    @property
    def vertex_ids_zero(self):
        """ Gets zero-indexed vertex number list.

        Vertex numbering starts from 0.
        """
        v_idx = []
        for v in self._data:
            v_idx.append(v.id - 1)
        return v_idx

    @property
    def inside(self):
        """ Inside-outside flag

        :getter: Gets the flag
        :setter: Sets the flag
        :type: bool
        """
        return self._inside

    @inside.setter
    def inside(self, value):
        self._inside = bool(value)

    def add_vertex(self, *args):
        """ Adds vertices to the Triangle object. """
        if len(self._data) > 2:
            raise ValueError("Cannot add more vertices")
        res = []
        for arg in args:
            if isinstance(arg, Vertex):
                res.append(arg)
            else:
                raise TypeError("Input must be a Vertex object")
        self._data = res

# Face class
class Face(AbstractElement):
    """ Representation of a face geometric entity composed of triangles. """
    def __init__(self):
        super(Face, self).__init__()

    def __str__(self):
        return "Face " + str(self._id)

    __repr__ = __str__

    @property
    def triangles(self):
        """ Triangles of the face

        :getter: Gets the list of triangles
        :type: tuple
        """
        return tuple(self._data)

    def add_triangle(self, *args):
        """ Adds triangles to the Face object. """
        res = []
        for arg in args:
            if isinstance(arg, Triangle):
                res.append(arg)
            else:
                raise TypeError("Input must be a Triangle object")
        self._data = res

# Body class
class Body(AbstractElement):
    """ Representation of a geometric body composed of faces. """
    def __init__(self):
        super(Body, self).__init__()

    def __str__(self):
        return "Body " + str(self._id)

    __repr__ = __str__

    @property
    def faces(self):
        """ Faces of the body

        :getter: Gets the list of faces
        :type: tuple
        """
        return tuple(self._data)

    def add_face(self, *args):
        """ Adds faces to the Body object. """
        res = []
        for arg in args:
            if isinstance(arg, Face):
                res.append(arg)
            else:
                raise TypeError("Input must be a Face object")
        self._data = res
<commit_msg>More docstring updates in elements.py<commit_after>"""
.. module:: elements
    :platform: Unix, Windows
    :synopsis: Provides classes representing geometry and topology elements

.. moduleauthor:: Onur Rauf Bingol <orbingol@gmail.com>

"""

import copy

# Abstract class for geometric entities
class AbstractElement(object):
    """ Abstract base class for all geometric entities. """
    def __init__(self):
        self._id = 0  # element ID
        self._data = []  # data storage array

    def __copy__(self):
        cls = self.__class__
        result = cls.__new__(cls)
        result.__dict__.update(self.__dict__)
        return result

    def __deepcopy__(self, memo):
        # Don't copy self reference
        cls = self.__class__
        result = cls.__new__(cls)
        memo[id(self)] = result
        # Copy all other attributes
        for k, v in self.__dict__.items():
            setattr(result, k, copy.deepcopy(v, memo))
        return result

    def __len__(self):
        return len(self._data)

    def __getitem__(self, key):
        return self._data[key]

    def __iter__(self):
        return iter(self._data)

    def __reversed__(self):
        return reversed(self._data)

    @property
    def id(self):
        """ Identifier for the geometric entity.

        It must be an integer number, otherwise the setter will raise a *ValueError*.

        :getter: Gets the identifier
        :setter: Sets the identifier
        :type: int
        """
        return self._id

    @id.setter
    def id(self, value):
        if not isinstance(value, int):
            raise ValueError("Identifier value must be an integer")
        self._id = value

# Vertex class
class Vertex(AbstractElement):
    """ Representation of a 3-dimensional vertex entity with its parametric position. """
    def __init__(self):
        super(Vertex, self).__init__()
        self._data = [0.0, 0.0, 0.0]  # spatial coordinates
        self._uv = [0.0, 0.0]  # parametric coordinates
        self._inside = False  # flag for trimming

    def __str__(self):
        return "Vertex " + str(self._id) + " " + str(self._data)

    __repr__ = __str__

    def __cmp__(self, other):
        return (self.id > other.id) - (self.id < other.id)

    def __eq__(self, other):
        return self.id == other.id

    def __ne__(self, other):
        return self.id != other.id

    def __lt__(self, other):
        return self.id < other.id

    def __le__(self, other):
        return self.id <= other.id

    def __gt__(self, other):
        return self.id > other.id

    def __ge__(self, other):
        return self.id >= other.id

    def __nonzero__(self):
        # For Python 2 compatibility
        return self.__bool__()

    def __bool__(self):
        # For Python 3 compatibility
        return self.inside

    def __add__(self, other):
        if not isinstance(other, self.__class__):
            raise TypeError("Can only add Vertex objects")
        res_data = [0.0 for _ in range(3)]
        for idx in range(3):
            res_data[idx] = self.data[idx] + other.data[idx]
        res_uv = [0.0 for _ in range(2)]
        for idx in range(2):
            res_uv[idx] = self.uv[idx] + other.uv[idx]
        res_val = self.__class__()
        res_val.data = res_data
        res_val.uv = res_uv
        return res_val

    def __sub__(self, other):
        if not isinstance(other, self.__class__):
            raise TypeError("Can only subtract Vertex objects")
        res_data = [0.0 for _ in range(3)]
        for idx in range(3):
            res_data[idx] = self.data[idx] - other.data[idx]
        res_uv = [0.0 for _ in range(2)]
        for idx in range(2):
            res_uv[idx] = self.uv[idx] - other.uv[idx]
        res_val = self.__class__()
        res_val.data = res_data
        res_val.uv = res_uv
        return res_val

    def __div__(self, other):
        return self.__truediv__(other)

    def __truediv__(self, other):
        if not isinstance(other, (float, int)):
            raise TypeError("Can only divide by a float or an integer")
        res_data = [0.0 for _ in range(3)]
        for idx in range(3):
            res_data[idx] = self.data[idx] / float(other)
        res_uv = [0.0 for _ in range(2)]
        for idx in range(2):
            res_uv[idx] = self.uv[idx] / float(other)
        res_val = self.__class__()
        res_val.data = res_data
        res_val.uv = res_uv
        return res_val

    @property
    def x(self):
        """ x-component of the vertex

        :getter: Gets the x-component of the vertex
        :setter: Sets the x-component of the vertex
        :type: float
        """
        return self._data[0]

    @x.setter
    def x(self, value):
        self._data[0] = float(value)

    @property
    def y(self):
        """ y-component of the vertex

        :getter: Gets the y-component of the vertex
        :setter: Sets the y-component of the vertex
        :type: float
        """
        return self._data[1]

    @y.setter
    def y(self, value):
        self._data[1] = float(value)

    @property
    def z(self):
        """ z-component of the vertex

        :getter: Gets the z-component of the vertex
        :setter: Sets the z-component of the vertex
        :type: float
        """
        return self._data[2]

    @z.setter
    def z(self, value):
        self._data[2] = float(value)

    @property
    def u(self):
        """ Parametric u-component of the vertex

        :getter: Gets the u-component of the vertex
        :setter: Sets the u-component of the vertex
        :type: float
        """
        return self._uv[0]

    @u.setter
    def u(self, value):
        self._uv[0] = float(value)

    @property
    def v(self):
        """ Parametric v-component of the vertex

        :getter: Gets the v-component of the vertex
        :setter: Sets the v-component of the vertex
        :type: float
        """
        return self._uv[1]

    @v.setter
    def v(self, value):
        self._uv[1] = float(value)

    @property
    def uv(self):
        """ Parametric (u,v) pair of the vertex

        :getter: Gets the uv-component of the vertex
        :setter: Sets the uv-component of the vertex
        :type: list, tuple
        """
        return tuple(self._uv)

    @uv.setter
    def uv(self, value):
        if not isinstance(value, (list, tuple)):
            raise TypeError("UV data input must be a list or tuple")
        if len(value) != 2:
            raise ValueError("UV must have 2 components")
        self._uv = list(value)

    @property
    def inside(self):
        """ Inside-outside flag

        :getter: Gets the flag
        :setter: Sets the flag
        :type: bool
        """
        return self._inside

    @inside.setter
    def inside(self, value):
        self._inside = bool(value)

    @property
    def data(self):
        """ (x,y,z) components of the vertex.

        :getter: Gets the 3-dimensional components
        :setter: Sets the 3-dimensional components
        """
        return tuple(self._data)

    @data.setter
    def data(self, value):
        if not isinstance(value, (list, tuple)):
            raise TypeError("Vertex data must be a list or tuple")
        if len(value) != 3:
            raise ValueError("Vertex can only store 3 components")
        self._data = list(value)

# Triangle class
class Triangle(AbstractElement):
    """ Representation of a triangular geometric entity composed of vertices. """
    def __init__(self):
        super(Triangle, self).__init__()
        self._inside = False  # flag for trimming

    def __str__(self):
        return "Triangle " + str(self._id)

    __repr__ = __str__

    @property
    def vertices(self):
        """ Vertices of the triangle

        :getter: Gets the list of vertices
        :type: tuple
        """
        return tuple(self._data)

    @property
    def vertices_raw(self):
        """ Vertices which generates a closed triangle

        Adds the first vertex as a last element of the return value (good for plotting)

        :getter: Gets the list of vertices
        :type: list
        """
        v_raw = []
        for v in self._data:
            v_raw.append(v.data)
        # Add the first vertex data as a last element (for plotting modules)
        if len(self._data) > 0:
            v_raw.append(self._data[0].data)
        return v_raw

    @property
    def vertices_uv(self):
        """ Parametric coordinates of the triangle vertices

        :getter: Gets the parametric coordinates of the vertices
        :type: list
        """
        data = self.vertices
        res = [data[idx].uv for idx in range(3)]
        return res

    @property
    def edges(self):
        """ Edges of the triangle

        :getter: Gets the list of vertices that generates the edges of the triangle
        :type: list
        """
        data = self.vertices_raw
        res = [[] for _ in range(3)]
        for idx in range(3):
            res[idx] = [data[idx], data[idx + 1]]
        return res

    @property
    def vertex_ids(self):
        """ Vertex indices

        Vertex numbering starts from 1.

        :getter: Gets the vertex indices
        :type: list
        """
        v_idx = []
        for v in self._data:
            v_idx.append(v.id)
        return v_idx

    @property
    def vertex_ids_zero(self):
        """ Zero-indexed vertex indices

        Vertex numbering starts from 0.

        :getter: Gets the vertex indices
        :type: list
        """
        v_idx = []
        for v in self._data:
            v_idx.append(v.id - 1)
        return v_idx

    @property
    def inside(self):
        """ Inside-outside flag

        :getter: Gets the flag
        :setter: Sets the flag
        :type: bool
        """
        return self._inside

    @inside.setter
    def inside(self, value):
        self._inside = bool(value)

    def add_vertex(self, *args):
        """ Adds vertices to the Triangle object. """
        if len(self._data) > 2:
            raise ValueError("Cannot add more vertices")
        res = []
        for arg in args:
            if isinstance(arg, Vertex):
                res.append(arg)
            else:
                raise TypeError("Input must be a Vertex object")
        self._data = res

# Face class
class Face(AbstractElement):
    """ Representation of a face geometric entity composed of triangles. """
    def __init__(self):
        super(Face, self).__init__()

    def __str__(self):
        return "Face " + str(self._id)

    __repr__ = __str__

    @property
    def triangles(self):
        """ Triangles of the face

        :getter: Gets the list of triangles
        :type: tuple
        """
        return tuple(self._data)

    def add_triangle(self, *args):
        """ Adds triangles to the Face object. """
        res = []
        for arg in args:
            if isinstance(arg, Triangle):
                res.append(arg)
            else:
                raise TypeError("Input must be a Triangle object")
        self._data = res

# Body class
class Body(AbstractElement):
    """ Representation of a geometric body composed of faces. """
    def __init__(self):
        super(Body, self).__init__()

    def __str__(self):
        return "Body " + str(self._id)

    __repr__ = __str__

    @property
    def faces(self):
        """ Faces of the body

        :getter: Gets the list of faces
        :type: tuple
        """
        return tuple(self._data)

    def add_face(self, *args):
        """ Adds faces to the Body object. """
        res = []
        for arg in args:
            if isinstance(arg, Face):
                res.append(arg)
            else:
                raise TypeError("Input must be a Face object")
        self._data = res
<|endoftext|>


<commit_before>from setuptools import setup, find_packages

def _is_requirement(line):
    """Returns whether the line is a valid package requirement."""
    line = line.strip()
    return line and not (line.startswith("-r") or line.startswith("#"))

def _read_requirements(filename):
    """Returns a list of package requirements read from the file."""
    requirements_file = open(filename).read()
    return [line.strip() for line in requirements_file.splitlines()
            if _is_requirement(line)]

required_packages = _read_requirements("requirements/base.txt")
test_packages = _read_requirements("requirements/tests.txt")

setup(
    name='rapidpro-expressions',
    version='1.0',
    description='Python implementation of the RapidPro expression and templating system',
    url='https://github.com/rapidpro/flows',

    author='Nyaruka',
    author_email='code@nyaruka.com',

    license='BSD',

    classifiers=[
        'Development Status :: 5 - Production/Stable',
        'Intended Audience :: Developers',
        'Topic :: Software Development :: Libraries',
        'License :: OSI Approved :: BSD License',
        'Programming Language :: Python :: 2',
    ],

    keywords='rapidpro templating',
    packages=find_packages(),
    package_data={'expressions': ['month.aliases']},
    install_requires=required_packages,

    test_suite='nose.collector',
    tests_require=required_packages + test_packages,
)
<commit_msg>Increment version to 1.0.1<commit_after>from setuptools import setup, find_packages

def _is_requirement(line):
    """Returns whether the line is a valid package requirement."""
    line = line.strip()
    return line and not (line.startswith("-r") or line.startswith("#"))

def _read_requirements(filename):
    """Returns a list of package requirements read from the file."""
    requirements_file = open(filename).read()
    return [line.strip() for line in requirements_file.splitlines()
            if _is_requirement(line)]

required_packages = _read_requirements("requirements/base.txt")
test_packages = _read_requirements("requirements/tests.txt")

setup(
    name='rapidpro-expressions',
    version='1.0.1',
    description='Python implementation of the RapidPro expression and templating system',
    url='https://github.com/rapidpro/flows',

    author='Nyaruka',
    author_email='code@nyaruka.com',

    license='BSD',

    classifiers=[
        'Development Status :: 5 - Production/Stable',
        'Intended Audience :: Developers',
        'Topic :: Software Development :: Libraries',
        'License :: OSI Approved :: BSD License',
        'Programming Language :: Python :: 2',
    ],

    keywords='rapidpro templating',
    packages=find_packages(),
    package_data={'expressions': ['month.aliases']},
    install_requires=required_packages,

    test_suite='nose.collector',
    tests_require=required_packages + test_packages,
)
<|endoftext|>


<commit_before>import mock
import signal
import unittest2 as unittest

from akanda.rug import main

class TestMain(unittest.TestCase):

    def test_shuffle_notifications(self):
        queue = mock.Mock()
        queue.get.side_effect = [
            ('9306bbd8-f3cc-11e2-bd68-080027e60b25', 'message'),
            KeyboardInterrupt,
        ]
        sched = mock.Mock()
        main.shuffle_notifications(queue, sched)
        sched.handle_message.assert_called_once('message')
        sched.stop.assert_called_once()

    @mock.patch('akanda.rug.main.cfg')
    @mock.patch('akanda.rug.main.quantum_api')
    @mock.patch('akanda.rug.main.multiprocessing')
    @mock.patch('akanda.rug.main.notifications')
    @mock.patch('akanda.rug.main.scheduler')
    @mock.patch('akanda.rug.main.populate')
    @mock.patch('akanda.rug.main.health')
    @mock.patch('akanda.rug.main.shuffle_notifications')
    @mock.patch('akanda.rug.main.signal.signal')
    def test_sigusr1_handler(self, mock_signal, shuffle_notifications, health,
                             populate, scheduler, notifications,
                             multiprocessing, quantum_api, cfg):
        main.main()
        mock_signal.assert_called_once_with(signal.SIGUSR1, mock.ANY)
<commit_msg>Add unit test for the mgt tap interface<commit_after>import mock
import signal
import unittest2 as unittest

from akanda.rug import main

@mock.patch('akanda.rug.main.cfg')
@mock.patch('akanda.rug.main.quantum_api')
@mock.patch('akanda.rug.main.multiprocessing')
@mock.patch('akanda.rug.main.notifications')
@mock.patch('akanda.rug.main.scheduler')
@mock.patch('akanda.rug.main.populate')
@mock.patch('akanda.rug.main.health')
@mock.patch('akanda.rug.main.shuffle_notifications')
@mock.patch('akanda.rug.main.signal.signal')
class TestMainPippo(unittest.TestCase):

    def test_shuffle_notifications(self, mock_signal, shuffle_notifications,
                                   health, populate, scheduler, notifications,
                                   multiprocessing, quantum_api, cfg):
        queue = mock.Mock()
        queue.get.side_effect = [
            ('9306bbd8-f3cc-11e2-bd68-080027e60b25', 'message'),
            KeyboardInterrupt,
        ]
        sched = scheduler.Scheduler.return_value
        main.shuffle_notifications(queue, sched)
        sched.handle_message.assert_called_once('message')
        sched.stop.assert_called_once()

    def test_sigusr1_handler(self, mock_signal, shuffle_notifications, health,
                             populate, scheduler, notifications,
                             multiprocessing, quantum_api, cfg):
        main.main()
        mock_signal.assert_called_once_with(signal.SIGUSR1, mock.ANY)

    def test_ensure_local_service_port(self, mock_signal,
                                       shuffle_notifications, health,
                                       populate, scheduler, notifications,
                                       multiprocessing, quantum_api, cfg):
        main.main()
        quantum = quantum_api.Quantum.return_value
        quantum.ensure_local_service_port.assert_called_once_with()
<|endoftext|>


<commit_before>"""PCSC Smartcard request.

__author__ = "http://www.gemalto.com"

Copyright 2001-2012 gemalto
Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com

This file is part of pyscard.

pyscard is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.

pyscard is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with pyscard; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
"""

import threading
import time

from smartcard.AbstractCardRequest import AbstractCardRequest
from smartcard.Exceptions import CardRequestTimeoutException
from smartcard.Exceptions import CardRequestException, ListReadersException
from smartcard.pcsc.PCSCReader import PCSCReader
from smartcard.pcsc.PCSCContext import PCSCContext
from smartcard import Card

from smartcard.scard import *

def signalEvent(evt, isInfinite):
    if not isInfinite:
        evt.set()

class PCSCCardRequest(AbstractCardRequest):
    """PCSC CardRequest class."""

    def __init__(self, newcardonly=False, readers=None,
                 cardType=None, cardServiceClass=None, timeout=1):
        """Construct new PCSCCardRequest.

        @param newcardonly: if True, request a new card default is
        False, i.e. accepts cards already inserted

        @param readers: the list of readers to consider for requesting a
        card default is to consider all readers

        @param cardType: the CardType class to wait for; default is
        AnyCardType, i.e.  the request will returns with new or already
        inserted cards

        @param cardServiceClass: the specific card service class to
        create and bind to the card default is to create and bind a
        PassThruCardService

        @param timeout: the time in seconds we are ready to wait for
        connecting to the requested card.  default is to wait one second
        to wait forever, set timeout to None
        """
        AbstractCardRequest.__init__(
            self, newcardonly, readers, cardType, cardServiceClass, timeout)

        # polling interval in s for SCardGetStatusChange
        self.pollinginterval = 0.1

        # if timeout is None, translate to scard.INFINITE
        if None == self.timeout:
            self.timeout = INFINITE
        # otherwise, from seconds to milliseconds
        else:
            self.timeout = int(self.timeout)

        self.hcontext = PCSCContext().getContext()

    def getReaderNames(self):
        """Returns the list of PCSC readers on which to wait for cards."""

        # renew the context in case PC/SC was stopped
        # this happens on Windows when the last reader is disconnected
        self.hcontext = PCSCContext().getContext()

        # get inserted readers
        hresult, pcscreaders = SCardListReaders(self.hcontext, [])
        if hresult in [SCARD_E_NO_READERS_AVAILABLE, SCARD_E_SERVICE_STOPPED]:
            return []
        if SCARD_S_SUCCESS != hresult:
            raise ListReadersException(hresult)

        readers = []

        # if no readers asked, use all inserted readers
        if None == self.readersAsked:
            readers = pcscreaders

        # otherwise use only the asked readers that are inserted
        else:
            for reader in self.readersAsked:
                if not isinstance(reader, type("")):
                    reader = str(reader)
                if reader in pcscreaders:
                    readers = readers + [reader]

        return readers

    def waitforcard(self):
        """Wait for card insertion and returns a card service."""
        AbstractCardRequest.waitforcard(self)
        cardfound = False

        # for non infinite timeout, a timer will signal
        # the end of the time-out by setting the evt event
        evt = threading.Event()
        if INFINITE == self.timeout:
            timertimeout = 1
        else:
            timertimeout = self.timeout
        timer = threading.Timer(
            timertimeout, signalEvent, [evt, INFINITE == self.timeout])

        # create a dictionary entry for new readers
        readerstates = {}
        readernames = self.getReaderNames()
        for reader in readernames:
            if not reader in readerstates:
                readerstates[reader] = (reader, SCARD_STATE_UNAWARE)

        # remove dictionary entry for readers that disappeared
        for oldreader in list(readerstates.keys()):
            if oldreader not in readernames:
                del readerstates[oldreader]

        # call SCardGetStatusChange only if we have some readers
        if {} != readerstates:
            hresult, newstates = SCardGetStatusChange(
                self.hcontext, 0, list(readerstates.values()))
        else:
            hresult = 0
            newstates = []

        # we can expect normally time-outs or reader
        # disappearing just before the call
        # otherwise, raise execption on error
        if 0 != hresult and \
            SCARD_E_TIMEOUT != hresult and \
            SCARD_E_UNKNOWN_READER != hresult:
                raise CardRequestException(
                    'Failed to SCardGetStatusChange ' + \
                    SCardGetErrorMessage(hresult))

        # in case of timeout or reader disappearing,
        # the content of the states is useless
        # in which case we clear the changed bit
        if SCARD_E_TIMEOUT == hresult or SCARD_E_UNKNOWN_READER == hresult:
            for state in newstates:
                state[1] = state[1] & (0xFFFFFFFF ^ SCARD_STATE_CHANGED)

        # update readerstate
        for state in newstates:
            readername, eventstate, atr = state
            readerstates[readername] = (readername, eventstate)

        # if a new card is not requested, just return the first available
        if not self.newcardonly:
            for state in newstates:
                readername, eventstate, atr = state
                if eventstate & SCARD_STATE_PRESENT:
                    reader = PCSCReader(readername)
                    if self.cardType.matches(atr, reader):
                        if self.cardServiceClass.supports('dummy'):
                            cardfound = True
                            return self.cardServiceClass(
                                    reader.createConnection())

        timerstarted = False
        while not evt.isSet() and not cardfound:

            if not timerstarted:
                timerstarted = True
                timer.start()

            time.sleep(self.pollinginterval)

            # create a dictionary entry for new readers
            readernames = self.getReaderNames()
            for reader in readernames:
                if not reader in readerstates:
                    readerstates[reader] = (reader, SCARD_STATE_UNAWARE)

            # remove dictionary entry for readers that disappeared
            for oldreader in list(readerstates.keys()):
                if oldreader not in readernames:
                    del readerstates[oldreader]

            # wait for card insertion
            if {} != readerstates:
                hresult, newstates = SCardGetStatusChange(
                    self.hcontext, 0, list(readerstates.values()))
            else:
                hresult = SCARD_E_TIMEOUT
                newstates = []

            # time-out
            if SCARD_E_TIMEOUT == hresult:
                if evt.isSet():
                    raise CardRequestTimeoutException()

            # reader vanished before or during the call
            elif SCARD_E_UNKNOWN_READER == hresult:
                pass

            # some error happened
            elif 0 != hresult:
                timer.cancel()
                raise CardRequestException(
                    'Failed to get status change ' + \
                    SCardGetErrorMessage(hresult))

            # something changed!
            else:

                # check if we have to return a match, i.e.
                # if no new card in inserted and there is a card found
                # or if a new card is requested, and there is a change+present
                for state in newstates:
                    readername, eventstate, atr = state
                    r, oldstate = readerstates[readername]

                    # the status can change on a card already inserted, e.g.
                    # unpowered, in use, ...
                    # if a new card is requested, clear the state changed bit
                    # if the card was already inserted and is still inserted
                    if self.newcardonly:
                        if oldstate & SCARD_STATE_PRESENT and \
                            eventstate & \
                                (SCARD_STATE_CHANGED | SCARD_STATE_PRESENT):
                            eventstate = eventstate & \
                                (0xFFFFFFFF ^ SCARD_STATE_CHANGED)

                    if (self.newcardonly and \
                            eventstate & SCARD_STATE_PRESENT and \
                            eventstate & SCARD_STATE_CHANGED) or \
                        (not self.newcardonly and \
                         eventstate & SCARD_STATE_PRESENT):
                        reader = PCSCReader(readername)
                        if self.cardType.matches(atr, reader):
                            if self.cardServiceClass.supports('dummy'):
                                cardfound = True
                                timer.cancel()
                                return self.cardServiceClass(
                                        reader.createConnection())

                    # update state dictionary
                    readerstates[readername] = (readername, eventstate)

            if evt.isSet():
                raise CardRequestTimeoutException()

    def waitforcardevent(self):
        """Wait for card insertion or removal."""
        AbstractCardRequest.waitforcardevent(self)
        presentcards = []
        evt = threading.Event()

        # for non infinite timeout, a timer will signal the end of the time-out
        if INFINITE == self.timeout:
            timertimeout = 1
        else:
            timertimeout = self.timeout
        timer = threading.Timer(
            timertimeout, signalEvent, [evt, INFINITE == self.timeout])

        # get status change until time-out, e.g. evt is set
        readerstates = {}
        timerstarted = False

        while not evt.isSet():

            if not timerstarted:
                timerstarted = True
                timer.start()

            time.sleep(self.pollinginterval)

            # reinitialize at each iteration just in case a new reader appeared
            readernames = self.getReaderNames()
            for reader in readernames:
                # create a dictionary entry for new readers
                if not reader in readerstates:
                    readerstates[reader] = (reader, SCARD_STATE_UNAWARE)
            # remove dictionary entry for readers that disappeared
            for oldreader in list(readerstates.keys()):
                if oldreader not in readernames:
                    del readerstates[oldreader]

            # get status change
            if {} != readerstates:
                hresult, newstates = SCardGetStatusChange(
                    self.hcontext, 0, list(readerstates.values()))
            else:
                hresult = 0
                newstates = []

            # time-out
            if SCARD_E_TIMEOUT == hresult:
                if evt.isSet():
                    raise CardRequestTimeoutException()

            # the reader was unplugged during the loop
            elif SCARD_E_UNKNOWN_READER == hresult:
                pass

            # some error happened
            elif 0 != hresult:
                timer.cancel()
                raise CardRequestException(
                    'Failed to get status change ' + \
                    SCardGetErrorMessage(hresult))

            # something changed!
            else:
                timer.cancel()
                for state in newstates:
                    readername, eventstate, atr = state
                    r, oldstate = readerstates[readername]

                    # the status can change on a card already inserted, e.g.
                    # unpowered, in use, ... Clear the state changed bit if
                    # the card was already inserted and is still inserted
                    if oldstate & SCARD_STATE_PRESENT and \
                        eventstate & \
                            (SCARD_STATE_CHANGED | SCARD_STATE_PRESENT):
                        eventstate = eventstate & \
                            (0xFFFFFFFF ^ SCARD_STATE_CHANGED)

                    if eventstate & SCARD_STATE_PRESENT and \
                       eventstate & SCARD_STATE_CHANGED:
                        presentcards.append(Card.Card(readername, atr))
                return presentcards

        if evt.isSet():
            raise CardRequestTimeoutException()

if __name__ == '__main__':
    """Small sample illustrating the use of PCSCCardRequest.py."""

    from smartcard.util import toHexString
    print('Insert a new card within 10 seconds')
    cr = PCSCCardRequest(timeout=10, newcardonly=True)
    cs = cr.waitforcard()
    cs.connection.connect()
    print(cs.connection.getReader() + ' ' + toHexString(cs.connection.getATR()))
    cs.connection.disconnect()
<commit_msg>getReaderNames(): fix Windows 10 issue<commit_after>"""PCSC Smartcard request.

__author__ = "http://www.gemalto.com"

Copyright 2001-2012 gemalto
Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com

This file is part of pyscard.

pyscard is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.

pyscard is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with pyscard; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
"""

import threading
import time

from smartcard.AbstractCardRequest import AbstractCardRequest
from smartcard.Exceptions import CardRequestTimeoutException
from smartcard.Exceptions import CardRequestException, ListReadersException
from smartcard.pcsc.PCSCReader import PCSCReader
from smartcard.pcsc.PCSCContext import PCSCContext
from smartcard import Card

from smartcard.scard import *

def signalEvent(evt, isInfinite):
    if not isInfinite:
        evt.set()

class PCSCCardRequest(AbstractCardRequest):
    """PCSC CardRequest class."""

    def __init__(self, newcardonly=False, readers=None,
                 cardType=None, cardServiceClass=None, timeout=1):
        """Construct new PCSCCardRequest.

        @param newcardonly: if True, request a new card default is
        False, i.e. accepts cards already inserted

        @param readers: the list of readers to consider for requesting a
        card default is to consider all readers

        @param cardType: the CardType class to wait for; default is
        AnyCardType, i.e.  the request will returns with new or already
        inserted cards

        @param cardServiceClass: the specific card service class to
        create and bind to the card default is to create and bind a
        PassThruCardService

        @param timeout: the time in seconds we are ready to wait for
        connecting to the requested card.  default is to wait one second
        to wait forever, set timeout to None
        """
        AbstractCardRequest.__init__(
            self, newcardonly, readers, cardType, cardServiceClass, timeout)

        # polling interval in s for SCardGetStatusChange
        self.pollinginterval = 0.1

        # if timeout is None, translate to scard.INFINITE
        if None == self.timeout:
            self.timeout = INFINITE
        # otherwise, from seconds to milliseconds
        else:
            self.timeout = int(self.timeout)

        self.hcontext = PCSCContext().getContext()

    def getReaderNames(self):
        """Returns the list of PCSC readers on which to wait for cards."""

        # renew the context in case PC/SC was stopped
        # this happens on Windows when the last reader is disconnected
        self.hcontext = PCSCContext().getContext()

        # get inserted readers
        hresult, pcscreaders = SCardListReaders(self.hcontext, [])
        if SCARD_E_SERVICE_STOPPED == hresult:
            self.hcontext = PCSCContext().renewContext()
            hresult, pcscreaders = SCardListReaders(self.hcontext, [])
        if SCARD_E_NO_READERS_AVAILABLE == hresult:
            return []
        if SCARD_S_SUCCESS != hresult:
            raise ListReadersException(hresult)

        readers = []

        # if no readers asked, use all inserted readers
        if None == self.readersAsked:
            readers = pcscreaders

        # otherwise use only the asked readers that are inserted
        else:
            for reader in self.readersAsked:
                if not isinstance(reader, type("")):
                    reader = str(reader)
                if reader in pcscreaders:
                    readers = readers + [reader]

        return readers

    def waitforcard(self):
        """Wait for card insertion and returns a card service."""
        AbstractCardRequest.waitforcard(self)
        cardfound = False

        # for non infinite timeout, a timer will signal
        # the end of the time-out by setting the evt event
        evt = threading.Event()
        if INFINITE == self.timeout:
            timertimeout = 1
        else:
            timertimeout = self.timeout
        timer = threading.Timer(
            timertimeout, signalEvent, [evt, INFINITE == self.timeout])

        # create a dictionary entry for new readers
        readerstates = {}
        readernames = self.getReaderNames()
        for reader in readernames:
            if not reader in readerstates:
                readerstates[reader] = (reader, SCARD_STATE_UNAWARE)

        # remove dictionary entry for readers that disappeared
        for oldreader in list(readerstates.keys()):
            if oldreader not in readernames:
                del readerstates[oldreader]

        # call SCardGetStatusChange only if we have some readers
        if {} != readerstates:
            hresult, newstates = SCardGetStatusChange(
                self.hcontext, 0, list(readerstates.values()))
        else:
            hresult = 0
            newstates = []

        # we can expect normally time-outs or reader
        # disappearing just before the call
        # otherwise, raise execption on error
        if 0 != hresult and \
            SCARD_E_TIMEOUT != hresult and \
            SCARD_E_UNKNOWN_READER != hresult:
                raise CardRequestException(
                    'Failed to SCardGetStatusChange ' + \
                    SCardGetErrorMessage(hresult))

        # in case of timeout or reader disappearing,
        # the content of the states is useless
        # in which case we clear the changed bit
        if SCARD_E_TIMEOUT == hresult or SCARD_E_UNKNOWN_READER == hresult:
            for state in newstates:
                state[1] = state[1] & (0xFFFFFFFF ^ SCARD_STATE_CHANGED)

        # update readerstate
        for state in newstates:
            readername, eventstate, atr = state
            readerstates[readername] = (readername, eventstate)

        # if a new card is not requested, just return the first available
        if not self.newcardonly:
            for state in newstates:
                readername, eventstate, atr = state
                if eventstate & SCARD_STATE_PRESENT:
                    reader = PCSCReader(readername)
                    if self.cardType.matches(atr, reader):
                        if self.cardServiceClass.supports('dummy'):
                            cardfound = True
                            return self.cardServiceClass(
                                    reader.createConnection())

        timerstarted = False
        while not evt.isSet() and not cardfound:

            if not timerstarted:
                timerstarted = True
                timer.start()

            time.sleep(self.pollinginterval)

            # create a dictionary entry for new readers
            readernames = self.getReaderNames()
            for reader in readernames:
                if not reader in readerstates:
                    readerstates[reader] = (reader, SCARD_STATE_UNAWARE)

            # remove dictionary entry for readers that disappeared
            for oldreader in list(readerstates.keys()):
                if oldreader not in readernames:
                    del readerstates[oldreader]

            # wait for card insertion
            if {} != readerstates:
                hresult, newstates = SCardGetStatusChange(
                    self.hcontext, 0, list(readerstates.values()))
            else:
                hresult = SCARD_E_TIMEOUT
                newstates = []

            # time-out
            if SCARD_E_TIMEOUT == hresult:
                if evt.isSet():
                    raise CardRequestTimeoutException()

            # reader vanished before or during the call
            elif SCARD_E_UNKNOWN_READER == hresult:
                pass

            # some error happened
            elif 0 != hresult:
                timer.cancel()
                raise CardRequestException(
                    'Failed to get status change ' + \
                    SCardGetErrorMessage(hresult))

            # something changed!
            else:

                # check if we have to return a match, i.e.
                # if no new card in inserted and there is a card found
                # or if a new card is requested, and there is a change+present
                for state in newstates:
                    readername, eventstate, atr = state
                    r, oldstate = readerstates[readername]

                    # the status can change on a card already inserted, e.g.
                    # unpowered, in use, ...
                    # if a new card is requested, clear the state changed bit
                    # if the card was already inserted and is still inserted
                    if self.newcardonly:
                        if oldstate & SCARD_STATE_PRESENT and \
                            eventstate & \
                                (SCARD_STATE_CHANGED | SCARD_STATE_PRESENT):
                            eventstate = eventstate & \
                                (0xFFFFFFFF ^ SCARD_STATE_CHANGED)

                    if (self.newcardonly and \
                            eventstate & SCARD_STATE_PRESENT and \
                            eventstate & SCARD_STATE_CHANGED) or \
                        (not self.newcardonly and \
                         eventstate & SCARD_STATE_PRESENT):
                        reader = PCSCReader(readername)
                        if self.cardType.matches(atr, reader):
                            if self.cardServiceClass.supports('dummy'):
                                cardfound = True
                                timer.cancel()
                                return self.cardServiceClass(
                                        reader.createConnection())

                    # update state dictionary
                    readerstates[readername] = (readername, eventstate)

            if evt.isSet():
                raise CardRequestTimeoutException()

    def waitforcardevent(self):
        """Wait for card insertion or removal."""
        AbstractCardRequest.waitforcardevent(self)
        presentcards = []
        evt = threading.Event()

        # for non infinite timeout, a timer will signal the end of the time-out
        if INFINITE == self.timeout:
            timertimeout = 1
        else:
            timertimeout = self.timeout
        timer = threading.Timer(
            timertimeout, signalEvent, [evt, INFINITE == self.timeout])

        # get status change until time-out, e.g. evt is set
        readerstates = {}
        timerstarted = False

        while not evt.isSet():

            if not timerstarted:
                timerstarted = True
                timer.start()

            time.sleep(self.pollinginterval)

            # reinitialize at each iteration just in case a new reader appeared
            readernames = self.getReaderNames()
            for reader in readernames:
                # create a dictionary entry for new readers
                if not reader in readerstates:
                    readerstates[reader] = (reader, SCARD_STATE_UNAWARE)
            # remove dictionary entry for readers that disappeared
            for oldreader in list(readerstates.keys()):
                if oldreader not in readernames:
                    del readerstates[oldreader]

            # get status change
            if {} != readerstates:
                hresult, newstates = SCardGetStatusChange(
                    self.hcontext, 0, list(readerstates.values()))
            else:
                hresult = 0
                newstates = []

            # time-out
            if SCARD_E_TIMEOUT == hresult:
                if evt.isSet():
                    raise CardRequestTimeoutException()

            # the reader was unplugged during the loop
            elif SCARD_E_UNKNOWN_READER == hresult:
                pass

            # some error happened
            elif 0 != hresult:
                timer.cancel()
                raise CardRequestException(
                    'Failed to get status change ' + \
                    SCardGetErrorMessage(hresult))

            # something changed!
            else:
                timer.cancel()
                for state in newstates:
                    readername, eventstate, atr = state
                    r, oldstate = readerstates[readername]

                    # the status can change on a card already inserted, e.g.
                    # unpowered, in use, ... Clear the state changed bit if
                    # the card was already inserted and is still inserted
                    if oldstate & SCARD_STATE_PRESENT and \
                        eventstate & \
                            (SCARD_STATE_CHANGED | SCARD_STATE_PRESENT):
                        eventstate = eventstate & \
                            (0xFFFFFFFF ^ SCARD_STATE_CHANGED)

                    if eventstate & SCARD_STATE_PRESENT and \
                       eventstate & SCARD_STATE_CHANGED:
                        presentcards.append(Card.Card(readername, atr))
                return presentcards

        if evt.isSet():
            raise CardRequestTimeoutException()

if __name__ == '__main__':
    """Small sample illustrating the use of PCSCCardRequest.py."""

    from smartcard.util import toHexString
    print('Insert a new card within 10 seconds')
    cr = PCSCCardRequest(timeout=10, newcardonly=True)
    cs = cr.waitforcard()
    cs.connection.connect()
    print(cs.connection.getReader() + ' ' + toHexString(cs.connection.getATR()))
    cs.connection.disconnect()
<|endoftext|>