diff options
author | Jason Madden <jamadden@gmail.com> | 2021-03-18 12:20:03 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-03-18 12:20:03 -0500 |
commit | 7e868363ded67a31bb930da7bf3fb7ea45832d19 (patch) | |
tree | d1bfcc6c50cf92cb2ee026234db18ce5eb4d7092 | |
parent | 5fd805db518f978dba1498a759dd796791dd4d1f (diff) | |
parent | f81a7f8448225f45bad51ed8aa52b0f27640d625 (diff) | |
download | zope-component-7e868363ded67a31bb930da7bf3fb7ea45832d19.tar.gz |
Merge pull request #58 from zopefoundation/issue9
Fix the subscriber directive when a factory is given that implements an interface and no provides= attribute is specified.
-rw-r--r-- | CHANGES.rst | 6 | ||||
-rw-r--r-- | docs/zcml.rst | 3 | ||||
-rw-r--r-- | src/zope/component/tests/test_zcml.py | 23 | ||||
-rw-r--r-- | src/zope/component/zcml.py | 4 |
4 files changed, 34 insertions, 2 deletions
diff --git a/CHANGES.rst b/CHANGES.rst index 1f36963..b83b913 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -19,6 +19,12 @@ - Add support for Python 3.9 +- Fix the ``<subscriber>`` ZCML directive to allow a missing + ``provides=`` attribute when a ``factory=`` is given and the Python + object has been decorated with ``@implementer`` and implements a + single interface. This has been documented, but hasn't worked + before. See `issue 9 + <https://github.com/zopefoundation/zope.component/issues/9>`_. 4.6.2 (2020-07-03) ================== diff --git a/docs/zcml.rst b/docs/zcml.rst index 18afc81..6bcd786 100644 --- a/docs/zcml.rst +++ b/docs/zcml.rst @@ -690,13 +690,12 @@ subscriber should be registered for: >>> clearZCML() >>> runSnippet(''' ... <subscriber - ... provides="zope.component.testfiles.adapter.IS" ... factory="zope.component.testfiles.adapter.A3" ... />''') >>> content = Content() >>> a2 = A2() - >>> subscribers = zope.component.subscribers((content, a1, a2), IS) + >>> subscribers = zope.component.subscribers((content, a1, a2), I3) >>> a3 = subscribers[0] >>> a3.__class__ is A3 diff --git a/src/zope/component/tests/test_zcml.py b/src/zope/component/tests/test_zcml.py index bb92da4..0bf4591 100644 --- a/src/zope/component/tests/test_zcml.py +++ b/src/zope/component/tests/test_zcml.py @@ -598,6 +598,29 @@ class Test_subscriber(unittest.TestCase): self.assertEqual(action['discriminator'], None) self.assertEqual(action['args'], ('', Interface)) + def test_no_for__no_provides_subscriber_adapts_subscriber_implements(self): + from zope.interface import Interface + from zope.interface import implementer + from zope.component._declaration import adapter + from zope.component.zcml import handler + class IFoo(Interface): + pass + @adapter(Interface) + @implementer(IFoo) + class _Factory(object): + def __init__(self, context): + self.context = context + _cfg_ctx = _makeConfigContext() + self._callFUT(_cfg_ctx, factory=_Factory) + self.assertEqual(len(_cfg_ctx._actions), 3) + self.assertEqual(_cfg_ctx._actions[0][0], ()) + # Register the subscriber + action = _cfg_ctx._actions[0][1] + self.assertEqual(action['callable'], handler) + self.assertIsNone(action['discriminator']) + self.assertEqual(action['args'], + ('registerSubscriptionAdapter', _Factory, (Interface,), IFoo, + '', 'TESTING')) class Test_utility(unittest.TestCase): diff --git a/src/zope/component/zcml.py b/src/zope/component/zcml.py index e3d040b..bc02c9f 100644 --- a/src/zope/component/zcml.py +++ b/src/zope/component/zcml.py @@ -304,6 +304,10 @@ def subscriber(_context, for_=None, factory=None, handler=None, provides=None, if handler is not None: raise TypeError("Cannot use handler with factory") if provides is None: + p = list(implementedBy(factory)) + if len(p) == 1: + provides = p[0] + if provides is None: raise TypeError( "You must specify a provided interface when registering " "a factory") |