From 2ea5c1fbe9fef8fc6a1f16f98368abe68100783d Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Fri, 1 Jul 2011 03:18:03 -0400 Subject: - The ``pyramid.events.subscriber`` directive behaved contrary to the documentation when passed more than one interface object to its constructor. For example, when the following listener was registered:: @subscriber(IFoo, IBar) def expects_ifoo_events_and_ibar_events(event): print event The Events chapter docs claimed that the listener would be registered and listening for both ``IFoo`` and ``IBar`` events. Instead, it registered an "object event" subscriber which would only be called if an IObjectEvent was emitted where the object interface was ``IFoo`` and the event interface was ``IBar``. The behavior now matches the documentation. If you were relying on the buggy behavior of the 1.0 ``subscriber`` directive in order to register an object event subscriber, you must now pass a sequence to indicate you'd like to register a subscriber for an object event. e.g.: @subscriber([IFoo, IBar]) def expects_object_event(object, event): print object, event --- CHANGES.txt | 23 +++++++++++++++++++++++ pyramid/events.py | 3 ++- pyramid/registry.py | 1 - pyramid/tests/test_events.py | 28 ++++++++++++++++++++++++++-- 4 files changed, 51 insertions(+), 4 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 2779f905a..3f8fd5049 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -10,6 +10,29 @@ Bug Fixes tests which use DummyRequest instead of a "real" request, so they know things are deprecated without necessarily needing a functional test suite. +- The ``pyramid.events.subscriber`` directive behaved contrary to the + documentation when passed more than one interface object to its + constructor. For example, when the following listener was registered:: + + @subscriber(IFoo, IBar) + def expects_ifoo_events_and_ibar_events(event): + print event + + The Events chapter docs claimed that the listener would be registered and + listening for both ``IFoo`` and ``IBar`` events. Instead, it registered an + "object event" subscriber which would only be called if an IObjectEvent was + emitted where the object interface was ``IFoo`` and the event interface was + ``IBar``. + + The behavior now matches the documentation. If you were relying on the + buggy behavior of the 1.0 ``subscriber`` directive in order to register an + object event subscriber, you must now pass a sequence to indicate you'd + like to register a subscriber for an object event. e.g.: + + @subscriber([IFoo, IBar]) + def expects_object_event(object, event): + print object, event + Features -------- diff --git a/pyramid/events.py b/pyramid/events.py index f7cb7d706..68e400550 100644 --- a/pyramid/events.py +++ b/pyramid/events.py @@ -63,7 +63,8 @@ class subscriber(object): def register(self, scanner, name, wrapped): config = scanner.config - config.add_subscriber(wrapped, self.ifaces) + for iface in self.ifaces: + config.add_subscriber(wrapped, iface) def __call__(self, wrapped): self.venusian.attach(wrapped, self.register, category='pyramid') diff --git a/pyramid/registry.py b/pyramid/registry.py index 5db0a11e2..6aaf44c2f 100644 --- a/pyramid/registry.py +++ b/pyramid/registry.py @@ -1,5 +1,4 @@ from zope.component.registry import Components -from zope.interface import providedBy from pyramid.interfaces import ISettings diff --git a/pyramid/tests/test_events.py b/pyramid/tests/test_events.py index 22a42758a..09f5f17ab 100644 --- a/pyramid/tests/test_events.py +++ b/pyramid/tests/test_events.py @@ -133,7 +133,19 @@ class TestSubscriber(unittest.TestCase): from pyramid.events import subscriber return subscriber(*ifaces) - def test_register(self): + def test_register_single(self): + from zope.interface import Interface + class IFoo(Interface): pass + class IBar(Interface): pass + dec = self._makeOne(IFoo) + def foo(): pass + config = DummyConfigurator() + scanner = Dummy() + scanner.config = config + dec.register(scanner, None, foo) + self.assertEqual(config.subscribed, [(foo, IFoo)]) + + def test_register_multi(self): from zope.interface import Interface class IFoo(Interface): pass class IBar(Interface): pass @@ -143,7 +155,19 @@ class TestSubscriber(unittest.TestCase): scanner = Dummy() scanner.config = config dec.register(scanner, None, foo) - self.assertEqual(config.subscribed, [(foo, (IFoo, IBar))]) + self.assertEqual(config.subscribed, [(foo, IFoo), (foo, IBar)]) + + def test_register_objectevent(self): + from zope.interface import Interface + class IFoo(Interface): pass + class IBar(Interface): pass + dec = self._makeOne([IFoo, IBar]) + def foo(): pass + config = DummyConfigurator() + scanner = Dummy() + scanner.config = config + dec.register(scanner, None, foo) + self.assertEqual(config.subscribed, [(foo, [IFoo, IBar])]) def test___call__(self): dec = self._makeOne() -- cgit v1.2.3