summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim Fulton <jim@zope.com>2015-10-17 11:13:49 -0400
committerJim Fulton <jim@zope.com>2015-10-17 11:13:49 -0400
commitd1c63c2ae399d3d2be8b6d2f8536129ac5d5d0d8 (patch)
tree0cea8d607772e913957603c041d390b9310d6a73
parentcfc5a87890fb5886976c6ce640a0f4840a91b9c6 (diff)
downloadzope-event-d1c63c2ae399d3d2be8b6d2f8536129ac5d5d0d8.tar.gz
Added a simple class-based handler implementation.classhandler
-rw-r--r--docs/classhandler.rst42
-rw-r--r--src/zope/event/classhandler.py70
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)