diff options
author | Tres Seaver <tseaver@palladion.com> | 2015-10-17 14:41:01 -0400 |
---|---|---|
committer | Tres Seaver <tseaver@palladion.com> | 2015-10-17 14:41:01 -0400 |
commit | 57ad3f9ed99243c1f060964289b543ddcebc48e9 (patch) | |
tree | 0cea8d607772e913957603c041d390b9310d6a73 | |
parent | 2d56e36f354fd69b47e90f1b8367d206aba5273e (diff) | |
parent | d1c63c2ae399d3d2be8b6d2f8536129ac5d5d0d8 (diff) | |
download | zope-event-57ad3f9ed99243c1f060964289b543ddcebc48e9.tar.gz |
Merge pull request #2 from zopefoundation/classhandler
Classhandler
-rw-r--r-- | CHANGES.rst | 4 | ||||
-rw-r--r-- | docs/classhandler.rst | 42 | ||||
-rw-r--r-- | docs/index.rst | 1 | ||||
-rw-r--r-- | src/zope/event/classhandler.py | 70 | ||||
-rw-r--r-- | src/zope/event/tests.py | 12 |
5 files changed, 127 insertions, 2 deletions
diff --git a/CHANGES.rst b/CHANGES.rst index ebb773e..81120c5 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,11 +1,11 @@ ``zope.event`` Changelog ======================== -4.0.4 (unreleased) +4.1.0 (unreleased) ------------------ - Require 100% branch (as well as statement) coverage. - +- Added a simple class-based handler implementation. 4.0.3 (2014-03-19) ------------------ 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/docs/index.rst b/docs/index.rst index 6fd6e4b..0d5be8b 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -19,6 +19,7 @@ Contents: usage theory api + classhandler hacking Indices and tables 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) diff --git a/src/zope/event/tests.py b/src/zope/event/tests.py index a7b045d..eed5562 100644 --- a/src/zope/event/tests.py +++ b/src/zope/event/tests.py @@ -13,6 +13,7 @@ ############################################################################## """ Test the event system """ +import doctest import unittest class Test_notify(unittest.TestCase): @@ -42,7 +43,18 @@ class Test_notify(unittest.TestCase): self._callFUT(event) self.assertEqual(dummy, [event]) +def setUpClassHandlers(test): + import zope.event + test.globs['old_subs'] = zope.event.subscribers + +def tearDownClassHandlers(test): + import zope.event + zope.event.subscribers = test.globs['old_subs'] + def test_suite(): return unittest.TestSuite(( unittest.makeSuite(Test_notify), + doctest.DocTestSuite( + 'zope.event.classhandler', + setUp=setUpClassHandlers, tearDown=tearDownClassHandlers) )) |