Esempio n. 1
0
class PooledFactory(object):
    """A factory which pools the objects produced by an independent function

    Instances of this class should be used when it is preferrable to
    use an existing function as a constructor.

    Produced instances are stored in a pool keyed by their construction
    argument signature.  If an instance has already been created with a
    particular set of arguments, invoking the factory with the same
    arguments will produce a reference to the already-existing instance.
    The constructor will only create new instances when an appropriate
    one is not found in the pool.
    """
    def __init__(self, construct):
        """Create a factory to produce instances using a given constructor."""
        self.pool = WeakValueDictionary()
        self.construct = construct

    def __call__(self, *args):
        """Produce an instance constructed from the given arguments.

        Retrieve an appropriate instance from the pool if it exists,
        Otherwise, construct a new instance and store it.
        """
        if self.pool.has_key(args):
            return self.pool[args]
        self.pool[args] = obj = self.construct(*args)
        return obj
Esempio n. 2
0
class Server(socket):
   def openConnection(self,host='',port=7777):
      self.clients = WeakValueDictionary()
      self.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
      self.bind((host,port))
      self.listen(7)
      self.handlerConnections()

   def accept(self):
      con, addr =super(Server, self).accept()
      connection = Client(con,addr,self)
      return connection
      
   def close(self):
      super(Server, self).close()

   def handlerConnections(self):
      while 1:
         connection = self.accept()
         ThreadPoolManager.getInstance().scheduleGeneral(ConnectionHandler(connection),0)

   def register(self, client, conn):
      self.clients[client] = conn
      print self.clients.data
   
   def hasClient(self, client):
      if self.clients.has_key(client):
         self.clients[client].writePacket(Disconnected())
         return True
      return False
Esempio n. 3
0
class UDPDemux(object):
    """Explicitly routing UDP demux

    This class implements a demux that forwards packets from the root
    socket to sockets belonging to connections. It does this whenever its
    service method is invoked.

    Methods:

      remove_connection -- remove an existing connection
      service -- distribute datagrams from the root socket to connections
      forward -- forward a stored datagram to a connection
    """

    _forwarding_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    _forwarding_socket.bind(('127.0.0.1', 0))

    def __init__(self, datagram_socket):
        """Constructor

        Arguments:
        datagram_socket -- the root socket; this must be a bound, unconnected
                           datagram socket
        """

        if datagram_socket.type != socket.SOCK_DGRAM:
            raise InvalidSocketError("datagram_socket is not of " +
                                     "type SOCK_DGRAM")
        try:
            datagram_socket.getsockname()
        except:
            raise InvalidSocketError("datagram_socket is unbound")
        try:
            datagram_socket.getpeername()
        except:
            pass
        else:
            raise InvalidSocketError("datagram_socket is connected")

        self.datagram_socket = datagram_socket
        self.payload = ""
        self.payload_peer_address = None
        self.connections = WeakValueDictionary()

    def get_connection(self, address):
        """Create or retrieve a muxed connection

        Arguments:
        address -- a peer endpoint in IPv4/v6 address format; None refers
                   to the connection for unknown peers

        Return:
        a bound, connected datagram socket instance
        """

        if self.connections.has_key(address):
            return self.connections[address]
        
        # We need a new datagram socket on a dynamically assigned ephemeral port
        conn = socket.socket(self._forwarding_socket.family,
                             self._forwarding_socket.type,
                             self._forwarding_socket.proto)
        conn.bind((self._forwarding_socket.getsockname()[0], 0))
        conn.connect(self._forwarding_socket.getsockname())
        if not address:
            conn.setblocking(0)
        self.connections[address] = conn
        _logger.debug("Created new connection for address: %s", address)
        return conn

    def remove_connection(self, address):
        """Remove a muxed connection

        Arguments:
        address -- an address that was previously returned by the service
                   method and whose connection has not yet been removed

        Return:
        the socket object whose connection has been removed
        """

        return self.connections.pop(address)

    def service(self):
        """Service the root socket

        Read from the root socket and forward one datagram to a
        connection. The call will return without forwarding data
        if any of the following occurs:

          * An error is encountered while reading from the root socket
          * Reading from the root socket times out
          * The root socket is non-blocking and has no data available
          * An empty payload is received
          * A non-empty payload is received from an unknown peer (a peer
            for which get_connection has not yet been called); in this case,
            the payload is held by this instance and will be forwarded when
            the forward method is called

        Return:
        if the datagram received was from a new peer, then the peer's
        address; otherwise None
        """

        self.payload, self.payload_peer_address = \
          self.datagram_socket.recvfrom(UDP_MAX_DGRAM_LENGTH)
        _logger.debug("Received datagram from peer: %s",
                      self.payload_peer_address)
        if not self.payload:
            self.payload_peer_address = None
            return
        if self.connections.has_key(self.payload_peer_address):
            self.forward()
        else:
            return self.payload_peer_address

    def forward(self):
        """Forward a stored datagram

        When the service method returns the address of a new peer, it holds
        the datagram from that peer in this instance. In this case, this
        method will perform the forwarding step. The target connection is the
        one associated with address None if get_connection has not been called
        since the service method returned the new peer's address, and the
        connection associated with the new peer's address if it has.
        """

        assert self.payload
        assert self.payload_peer_address
        if self.connections.has_key(self.payload_peer_address):
            conn = self.connections[self.payload_peer_address]
            default = False
        else:
            conn = self.connections[None]  # propagate exception if not created
            default = True
        _logger.debug("Forwarding datagram from peer: %s, default: %s",
                      self.payload_peer_address, default)
        self._forwarding_socket.sendto(self.payload, conn.getsockname())
        self.payload = ""
        self.payload_peer_address = None
Esempio n. 4
0
class Data(object):
    """
    Class to handle Data, especailly Users:
      Data[item] -> returns a item object.
    If item is a string, it is case insensitive, but item can be anything.
    The item is stored as "handle" into the Item object, probably often
    just flying around, sometimes meaning you have double entries (with db).
      
    You can change self.main_key to change the default item to a name 
    different from 'handle'. For example the ID in the database, or whatever.
      
    AS USER IS THE MAIN INTEREST, ALL HELP MAY REFER TO Users==Data
    and User == Item!
    
    Other things (ie, users.online) are added from outside.
      
    NOTES:
        o Use Registered functions to add functionality to user class.
           The registered function can change the items value by directly
           editing the User.items dictionary.
        o Registered functions are executed in the order that they are
           gotten. Classes ones are executed before Instance ones, so that
           they could modify the value before the instance thinks it changed.
           Instance ones _will_ also be executed if old == new.
    
    TIPS:
        o Instead of registering say "rating" which would be set when a
           function parsed the finger of a user, have it set
           "finger_update" = time.time() and register to that. That way you
           get notified even if the rating does not change AND always know
           when it was last updated.
        o For the same example, you might have a loader regestration for your
           database backend. The status module will set the items, but if a
           user is not connected, he does not have it set, so that loader
           gets called when you cannot get it through FICS. Yes, that means
           that you will need the dummy "finger_update" to force a reload
           through the finger function. (Of course this is rather
           hypethetical, afterall finger is always more up to date ;))
           
    Maybe the buffer should be improved ...
    """

    def __init__(self, main_key='handle', buffer_size = 20):
        # Define a dummy class and self.Item to make sure that each Users class
        # has its own child User class.
        class Items(_Item):
            _on_update = {}
            _loader = {}

        self.main_key = main_key
        Items.main_key = main_key
        self.Item = Items

        # Buffer to make sure we don't discard items that often ...
        # As long as the item has a reference stored here or ANYWHERE else
        # he will not be discarted.
        if buffer_size < 1:
            self._buffer = None
        else:
            self._buffer = [None]*buffer_size

        # dictionary mapping item_name -> item object. This is a WEAKREF!
        from weakref import WeakValueDictionary
        self._loaded_items = WeakValueDictionary()
    

    def register(self, item, function, persistent=True, loader=False):
        """
        register(item, function, persistent=True)
        Register a function to be executed when item gets updated next time.
        Multiple functions can be registered, all will update when this happens.
        NOTES:
            o Function must take (item_object, item_name, old, new) as arguments.
            o Do not mass use this, otherwise its probably better to
               add it to the _item_set()/_item_load() special function.
            o loader keyword: The funciton is not called on set, but on a
               get event. (First time load). Only one function can be
               assigned. quietly overwrites all existing ones.
               Always persistent. The function MUST set the item.
        This will register for ALL items.
        """
        if loader == True:
            self.Item._loader[item] = function
            return
            
        if self.Item._on_update.has_key(item):
            self.Item._on_update[item].append([function, persistent])
            return
        self.Item._on_update[item] = [[function, persistent]]

    
    def unregister(self, item, function, loader):
        """
        Unregister a function again ...
        """
        if loader:
            del self.Item._loader[item]
            return
        try:
            self.Item._on_update[item].remove([function, True])
        except ValueError:
            self.Item._on_update[item].remove([function, False])


    def __getitem__(self, handle):
        try:
            ident = handle.lower()
        except AttributeError:
            ident = handle
        if not self._loaded_items.has_key(ident):
            return self._load(handle)
        #print handle, ident, self._loaded_items[ident].items
        return self._loaded_items[ident]


    def _load(self, handle):
        new_item = self.Item(handle)
        try:
            ident = handle.lower()
        except AttributeError:
            ident = handle
        
        self._loaded_items[ident] = new_item
        if self._buffer is not None:
            del self._buffer[0]
            self._buffer += [new_item]
        return new_item        


    def iteritems(self):
        """Iterator over all stored items.
        """
        return self._loaded_items.iteritems()
        
    def iterkeys(self):
        """Iterator over all stored keys.
        """
        return self._loaded_items.iterkeys()

    def itervalues(self):
        """Iterator over all stored items.
        """
        return self._loaded_items.itervalues()

    def __iter__(self):
        return self._loaded_items.__iter__()
Esempio n. 5
0
class Data(object):
    """
    Class to handle Data, especailly Users:
      Data[item] -> returns a item object.
    If item is a string, it is case insensitive, but item can be anything.
    The item is stored as "handle" into the Item object, probably often
    just flying around, sometimes meaning you have double entries (with db).
      
    You can change self.main_key to change the default item to a name 
    different from 'handle'. For example the ID in the database, or whatever.
      
    AS USER IS THE MAIN INTEREST, ALL HELP MAY REFER TO Users==Data
    and User == Item!
    
    Other things (ie, users.online) are added from outside.
      
    NOTES:
        o Use Registered functions to add functionality to user class.
           The registered function can change the items value by directly
           editing the User.items dictionary.
        o Registered functions are executed in the order that they are
           gotten. Classes ones are executed before Instance ones, so that
           they could modify the value before the instance thinks it changed.
           Instance ones _will_ also be executed if old == new.
    
    TIPS:
        o Instead of registering say "rating" which would be set when a
           function parsed the finger of a user, have it set
           "finger_update" = time.time() and register to that. That way you
           get notified even if the rating does not change AND always know
           when it was last updated.
        o For the same example, you might have a loader regestration for your
           database backend. The status module will set the items, but if a
           user is not connected, he does not have it set, so that loader
           gets called when you cannot get it through FICS. Yes, that means
           that you will need the dummy "finger_update" to force a reload
           through the finger function. (Of course this is rather
           hypethetical, afterall finger is always more up to date ;))
           
    Maybe the buffer should be improved ...
    """
    def __init__(self, main_key='handle', buffer_size=20):
        # Define a dummy class and self.Item to make sure that each Users class
        # has its own child User class.
        class Items(_Item):
            _on_update = {}
            _loader = {}

        self.main_key = main_key
        Items.main_key = main_key
        self.Item = Items

        # Buffer to make sure we don't discard items that often ...
        # As long as the item has a reference stored here or ANYWHERE else
        # he will not be discarted.
        if buffer_size < 1:
            self._buffer = None
        else:
            self._buffer = [None] * buffer_size

        # dictionary mapping item_name -> item object. This is a WEAKREF!
        from weakref import WeakValueDictionary
        self._loaded_items = WeakValueDictionary()

    def register(self, item, function, persistent=True, loader=False):
        """
        register(item, function, persistent=True)
        Register a function to be executed when item gets updated next time.
        Multiple functions can be registered, all will update when this happens.
        NOTES:
            o Function must take (item_object, item_name, old, new) as arguments.
            o Do not mass use this, otherwise its probably better to
               add it to the _item_set()/_item_load() special function.
            o loader keyword: The funciton is not called on set, but on a
               get event. (First time load). Only one function can be
               assigned. quietly overwrites all existing ones.
               Always persistent. The function MUST set the item.
        This will register for ALL items.
        """
        if loader == True:
            self.Item._loader[item] = function
            return

        if self.Item._on_update.has_key(item):
            self.Item._on_update[item].append([function, persistent])
            return
        self.Item._on_update[item] = [[function, persistent]]

    def unregister(self, item, function, loader):
        """
        Unregister a function again ...
        """
        if loader:
            del self.Item._loader[item]
            return
        try:
            self.Item._on_update[item].remove([function, True])
        except ValueError:
            self.Item._on_update[item].remove([function, False])

    def __getitem__(self, handle):
        try:
            ident = handle.lower()
        except AttributeError:
            ident = handle
        if not self._loaded_items.has_key(ident):
            return self._load(handle)
        #print handle, ident, self._loaded_items[ident].items
        return self._loaded_items[ident]

    def _load(self, handle):
        new_item = self.Item(handle)
        try:
            ident = handle.lower()
        except AttributeError:
            ident = handle

        self._loaded_items[ident] = new_item
        if self._buffer is not None:
            del self._buffer[0]
            self._buffer += [new_item]
        return new_item

    def iteritems(self):
        """Iterator over all stored items.
        """
        return self._loaded_items.iteritems()

    def iterkeys(self):
        """Iterator over all stored keys.
        """
        return self._loaded_items.iterkeys()

    def itervalues(self):
        """Iterator over all stored items.
        """
        return self._loaded_items.itervalues()

    def __iter__(self):
        return self._loaded_items.__iter__()
Esempio n. 6
0
class MidiInput(PySeq):
    def __init__(self):
        PySeq.__init__(self, "topot_midi_in")
        self.inport = self.createInPort('')
        self.notes = WeakValueDictionary()
        self.controllers = WeakValueDictionary()
        self.pgmchanges = WeakValueDictionary()
        self.queue = Queue()
        self.pin, self.pout = os.pipe()
        self.thread = MidiThread(self)

    def start(self, topot):
        topot.registerInput("note", self.note)
        topot.registerInput("controller", self.controller)
        topot.registerInput("pgmchange", self.pgmchange)
        self.thread.start()
        return self.run()

    def callback(self, event):
        self.queue.put(event)
        os.write(self.pout, "!")
        return 1

    def run(self):
        while True:
            yield ("in", self.pin)
            os.read(self.pin, 1)
            self.signal(self.queue.get(True))

    def note(self, id):
        if self.notes.has_key(id):
            return self.notes[id]
        else:
            note = InputSignal(0)
            self.notes[id] = note
            return note

    def controller(self, id):
        if self.controllers.has_key(id):
            return self.controllers[id]
        else:
            controller = InputSignal(0)
            self.controllers[id] = controller
            return controller

    def pgmchange(self, id):
        if self.pgmchanges.has_key(id):
            return self.pgmchanges[id]
        else:
            pgmchange = InputSignal(0)
            self.pgmchanges[id] = pgmchange
            return pgmchange

    def signal(self, event):
        def sendNote(note, value):
            if self.notes.has_key(note):
                self.notes[note].value = value

        def sendController(controller, value):
            if self.controllers.has_key(controller):
                self.controllers[controller].value = value

        def sendPgmChange(pgmchange, value):
            if self.pgmchanges.has_key(pgmchange):
                self.pgmchanges[pgmchange].value = value

        data = event.getData()
        if event.type == SND_SEQ_EVENT_NOTEON:
            sendNote(data.note, data.velocity)
        elif event.type == SND_SEQ_EVENT_NOTEOFF:
            sendNote(data.note, 0)
        elif event.type == SND_SEQ_EVENT_CONTROLLER:
            sendController(data.param, data.value)
        elif event.type == SND_SEQ_EVENT_PGMCHANGE:
            sendPgmChange(data.value, random.randint(
                0, 1000))  # randomize values so pgmchange will be fired up
Esempio n. 7
0
class UDPDemux(object):
    """Explicitly routing UDP demux

    This class implements a demux that forwards packets from the root
    socket to sockets belonging to connections. It does this whenever its
    service method is invoked.

    Methods:

      remove_connection -- remove an existing connection
      service -- distribute datagrams from the root socket to connections
      forward -- forward a stored datagram to a connection
    """

    _forwarding_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    _forwarding_socket.bind(('127.0.0.1', 0))

    def __init__(self, datagram_socket):
        """Constructor

        Arguments:
        datagram_socket -- the root socket; this must be a bound, unconnected
                           datagram socket
        """

        if datagram_socket.type != socket.SOCK_DGRAM:
            raise InvalidSocketError("datagram_socket is not of " +
                                     "type SOCK_DGRAM")
        try:
            datagram_socket.getsockname()
        except:
            raise InvalidSocketError("datagram_socket is unbound")
        try:
            datagram_socket.getpeername()
        except:
            pass
        else:
            raise InvalidSocketError("datagram_socket is connected")

        self.datagram_socket = datagram_socket
        self.payload = ""
        self.payload_peer_address = None
        self.connections = WeakValueDictionary()

    def get_connection(self, address):
        """Create or retrieve a muxed connection

        Arguments:
        address -- a peer endpoint in IPv4/v6 address format; None refers
                   to the connection for unknown peers

        Return:
        a bound, connected datagram socket instance
        """

        if self.connections.has_key(address):
            return self.connections[address]

        # We need a new datagram socket on a dynamically assigned ephemeral port
        conn = socket.socket(self._forwarding_socket.family,
                             self._forwarding_socket.type,
                             self._forwarding_socket.proto)
        conn.bind((self._forwarding_socket.getsockname()[0], 0))
        conn.connect(self._forwarding_socket.getsockname())
        if not address:
            conn.setblocking(0)
        self.connections[address] = conn
        _logger.debug("Created new connection for address: %s", address)
        return conn

    def remove_connection(self, address):
        """Remove a muxed connection

        Arguments:
        address -- an address that was previously returned by the service
                   method and whose connection has not yet been removed

        Return:
        the socket object whose connection has been removed
        """

        return self.connections.pop(address)

    def service(self):
        """Service the root socket

        Read from the root socket and forward one datagram to a
        connection. The call will return without forwarding data
        if any of the following occurs:

          * An error is encountered while reading from the root socket
          * Reading from the root socket times out
          * The root socket is non-blocking and has no data available
          * An empty payload is received
          * A non-empty payload is received from an unknown peer (a peer
            for which get_connection has not yet been called); in this case,
            the payload is held by this instance and will be forwarded when
            the forward method is called

        Return:
        if the datagram received was from a new peer, then the peer's
        address; otherwise None
        """

        self.payload, self.payload_peer_address = \
          self.datagram_socket.recvfrom(UDP_MAX_DGRAM_LENGTH)
        _logger.debug("Received datagram from peer: %s",
                      self.payload_peer_address)
        if not self.payload:
            self.payload_peer_address = None
            return
        if self.connections.has_key(self.payload_peer_address):
            self.forward()
        else:
            return self.payload_peer_address

    def forward(self):
        """Forward a stored datagram

        When the service method returns the address of a new peer, it holds
        the datagram from that peer in this instance. In this case, this
        method will perform the forwarding step. The target connection is the
        one associated with address None if get_connection has not been called
        since the service method returned the new peer's address, and the
        connection associated with the new peer's address if it has.
        """

        assert self.payload
        assert self.payload_peer_address
        if self.connections.has_key(self.payload_peer_address):
            conn = self.connections[self.payload_peer_address]
            default = False
        else:
            conn = self.connections[None]  # propagate exception if not created
            default = True
        _logger.debug("Forwarding datagram from peer: %s, default: %s",
                      self.payload_peer_address, default)
        self._forwarding_socket.sendto(self.payload, conn.getsockname())
        self.payload = ""
        self.payload_peer_address = None