Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- from __future__ import unicode_literals
- from Queue import Queue, Empty
- class EventLoop(object):
- def __init__(self, setup):
- """Sets up a Firefly event loop.
- setup must be a callable that performs application-specific loop
- initializations.
- """
- self._eventqueue = Queue(0)
- setup(self)
- def add(self, event, args):
- e = (event, args)
- self._eventqueue.put(e, block=False)
- def process_data(self):
- try:
- event = self._eventqueue.get()
- except Empty:
- return
- while event is not None:
- event[1].handle(*event[2])
- class Event(object):
- """A Firefly event.
- Firefly events are maintained as a partially-dynamic heirarchy. This allows
- for a very fine-grained level of control, as events' parents can respond to
- the same events their children do.
- Handlers are called parent-first, in case a parent event handler asks for a
- halt.
- """
- _forbidden = [
- '__hash__',
- '__init__',
- '__new__',
- '__setattr__',
- '__str__',
- '__unicode__',
- '_name',
- 'attach',
- 'detach',
- 'handle',
- 'emit'
- ]
- def __new__(cls, name, doc=''):
- _dict = {
- '_name': name,
- '_handlers': [],
- '_parent': None,
- '__doc__': doc if doc else '<undocumented>'
- }
- obj = type(cls.__name__, (Event,), _dict)
- return obj
- def __hash__(self):
- return hash(self._name)
- def __setattr__(self, attr, value):
- if attr in self._forbidden:
- error.event.emit(self, 'invalid child event')
- elif attr == '_parent':
- object.__setattr(self, attr, value)
- object.__setattr(self, '_name', '.'.join(value._name, self._name))
- else:
- object.__setattr__(self, attr, value)
- value._parent = self
- def __unicode__(self):
- return unicode(self._name)
- def attach(self, func):
- self._handlers.append(func)
- event.attached.emit(self)
- def detach(self, func):
- if isinstance(func, int):
- try:
- self._handlers.pop(func)
- except IndexError:
- error.event.emit(self, 'no handler at index %s')
- return
- else:
- try:
- self._handlers.remove(func)
- except ValueError:
- error.event.emit(self, 'cannot detach unattached handler')
- return
- event.detached.emit(self)
- def handle(self, *args):
- if self._parent is not None:
- halt = self._parent.handle(*args)
- if halt:
- return halt
- for handle in self._handlers:
- halt = handle(self, *args)
- if halt:
- break
- def emit(self, *args, **kwargs):
- process = False if 'process' not in kwargs else kwargs['process']
- obj = args.pop(0)
- emitter = unicode(obj)
- if process:
- eventloop.add(emitter, obj, args)
- event = Event('event', 'event system root')
- event.attached = Event('event.attached', 'handler attached to event')
- event.detached = Event('event.detached', 'handler detached from event')
- error = Event('error', 'error system root')
- error.event = Event('event', 'event system error')
- error.handler = Event('handler', 'event handler error')
- protocols = Event('protocols', 'protocols system root')
Add Comment
Please, Sign In to add comment