Skip to content

Commit

Permalink
Merge pull request #2 from zopefoundation/classhandler
Browse files Browse the repository at this point in the history
Classhandler
  • Loading branch information
tseaver committed Oct 17, 2015
2 parents 2d56e36 + d1c63c2 commit 57ad3f9
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 2 deletions.
4 changes: 2 additions & 2 deletions 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)
------------------
Expand Down
42 changes: 42 additions & 0 deletions 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

1 change: 1 addition & 0 deletions docs/index.rst
Expand Up @@ -19,6 +19,7 @@ Contents:
usage
theory
api
classhandler
hacking

Indices and tables
Expand Down
70 changes: 70 additions & 0 deletions 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)
12 changes: 12 additions & 0 deletions src/zope/event/tests.py
Expand Up @@ -13,6 +13,7 @@
##############################################################################
""" Test the event system
"""
import doctest
import unittest

class Test_notify(unittest.TestCase):
Expand Down Expand Up @@ -42,7 +43,18 @@ def test_not_empty(self):
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)
))

0 comments on commit 57ad3f9

Please sign in to comment.