diff options
author | Jim Fulton <jim@zope.com> | 2015-10-17 11:13:49 -0400 |
---|---|---|
committer | Jim Fulton <jim@zope.com> | 2015-10-17 11:13:49 -0400 |
commit | d1c63c2ae399d3d2be8b6d2f8536129ac5d5d0d8 (patch) | |
tree | 0cea8d607772e913957603c041d390b9310d6a73 | |
parent | cfc5a87890fb5886976c6ce640a0f4840a91b9c6 (diff) | |
download | zope-event-classhandler.tar.gz |
Added a simple class-based handler implementation.classhandler
-rw-r--r-- | docs/classhandler.rst | 42 | ||||
-rw-r--r-- | src/zope/event/classhandler.py | 70 |
2 files changed, 112 insertions, 0 deletions
diff --git a/docs/classhandler.rst b/docs/classhandler.rst new file mode 100644 index 0000000..5385b68 --- /dev/null +++ b/docs/classhandler.rst @@ -0,0 +1,42 @@ +Class-based event handlers +========================== + +A light-weight event-handler framework based on event classes is +provided by the ``zope.event.classhandler`` module. + +Handlers are registered for event classes: + + >>> import zope.event.classhandler + + >>> class MyEvent(object): + ... def __repr__(self): + ... return self.class.__name__ + + >>> def handler1(event): + ... print("handler1 %r" % event) + + >>> zope.event.classhandler.handler(MyEvent, handler1) + +Descriptor syntax: + + >>> @zope.event.classhandler.handler(MyEvent) + ... def handler2(event): + ... print("handler2 %r" % event) + + >>> class MySubEvent(MyEvent): + ... pass + + >>> @zope.event.classhandler.handler(MySubEvent) + ... def handler3(event): + ... print("handler3 %r" % event) + + +Subscribers are called in class method-resolution order, so only +new-style event classes are supported, and then by order of registry. + + >>> import zope.event + >>> zope.event.notify(MySubEvent()) + handler3 MySubEvent + handler1 MySubEvent + handler2 MySubEvent + diff --git a/src/zope/event/classhandler.py b/src/zope/event/classhandler.py new file mode 100644 index 0000000..0a1df59 --- /dev/null +++ b/src/zope/event/classhandler.py @@ -0,0 +1,70 @@ +"""Class-based event handlers + + +A light-weight event-handler framework based on event classes. + +Handlers are registered for event classes: + + >>> import zope.event.classhandler + + >>> class MyEvent(object): + ... def __repr__(self): + ... return self.__class__.__name__ + + >>> def handler1(event): + ... print("handler1 %r" % event) + + >>> zope.event.classhandler.handler(MyEvent, handler1) + +Descriptor syntax: + + >>> @zope.event.classhandler.handler(MyEvent) + ... def handler2(event): + ... print("handler2 %r" % event) + + >>> class MySubEvent(MyEvent): + ... pass + + >>> @zope.event.classhandler.handler(MySubEvent) + ... def handler3(event): + ... print("handler3 %r" % event) + + +Subscribers are called in class method-resolution order, so only +new-style event classes are supported, and then by order of registry. + + >>> import zope.event + >>> zope.event.notify(MySubEvent()) + handler3 MySubEvent + handler1 MySubEvent + handler2 MySubEvent + +""" +import zope.event + +registry = {} + +def handler(event_class, handler_=None, decorator=False): + """Define an event handler for a (new-style) class. + + This can be called with a class and a handler, or with just a + class and the result used as a handler decorator. + """ + if handler_ is None: + return lambda func: handler(event_class, func, True) + + if not registry: + zope.event.subscribers.append(dispatch) + + if event_class not in registry: + registry[event_class] = [handler_] + else: + registry[event_class].append(handler_) + + if decorator: + return handler + +def dispatch(event): + for event_class in event.__class__.__mro__: + for handler in registry.get(event_class, ()): + handler(event) |