summaryrefslogtreecommitdiff
path: root/src/zope/event/classhandler.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/zope/event/classhandler.py')
-rw-r--r--src/zope/event/classhandler.py70
1 files changed, 70 insertions, 0 deletions
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)