diff options
| author | Jason Madden <jamadden@gmail.com> | 2020-04-07 07:04:44 -0500 |
|---|---|---|
| committer | Jason Madden <jamadden@gmail.com> | 2020-04-07 07:04:44 -0500 |
| commit | b1807049d47afef711c467b785fae6aab7be851a (patch) | |
| tree | b2cd6f93ab0ec6dd7b4dad040367611289f4e3af /src/zope/interface | |
| parent | 10eadd6305ee57910dbcc508b293f4bf0364fd84 (diff) | |
| download | zope-interface-b1807049d47afef711c467b785fae6aab7be851a.tar.gz | |
Feedback from review: whitespace, doc clarification, and a unit test showing the precedence of __conform__ vs __adapt__.
Diffstat (limited to 'src/zope/interface')
| -rw-r--r-- | src/zope/interface/common/__init__.py | 2 | ||||
| -rw-r--r-- | src/zope/interface/interface.py | 5 | ||||
| -rw-r--r-- | src/zope/interface/interfaces.py | 30 | ||||
| -rw-r--r-- | src/zope/interface/tests/test_interface.py | 39 |
4 files changed, 58 insertions, 18 deletions
diff --git a/src/zope/interface/common/__init__.py b/src/zope/interface/common/__init__.py index b40c317..01f0bd3 100644 --- a/src/zope/interface/common/__init__.py +++ b/src/zope/interface/common/__init__.py @@ -259,5 +259,5 @@ class ABCInterfaceClass(InterfaceClass): return set(itertools.chain(registered, self.__extra_classes)) -ABCInterface = ABCInterfaceClass.__new__(ABCInterfaceClass, 'ABCInterfaceClass', (), {}) +ABCInterface = ABCInterfaceClass.__new__(ABCInterfaceClass, 'ABCInterface', (), {}) InterfaceClass.__init__(ABCInterface, 'ABCInterface', (Interface,), {}) diff --git a/src/zope/interface/interface.py b/src/zope/interface/interface.py index ff26d33..f819441 100644 --- a/src/zope/interface/interface.py +++ b/src/zope/interface/interface.py @@ -662,7 +662,10 @@ def interfacemethod(func): This is a decorator that functions like `staticmethod` et al. The primary use of this decorator is to allow interface definitions to - define the ``__adapt__`` method. + define the ``__adapt__`` method, but other interface methods can be + overridden this way too. + + .. seealso:: `zope.interface.interfaces.IInterfaceDeclaration.interfacemethod` """ f_locals = sys._getframe(1).f_locals methods = f_locals.setdefault(INTERFACE_METHODS, {}) diff --git a/src/zope/interface/interfaces.py b/src/zope/interface/interfaces.py index 6321d0c..9334374 100644 --- a/src/zope/interface/interfaces.py +++ b/src/zope/interface/interfaces.py @@ -490,7 +490,7 @@ class IInterfaceDeclaration(Interface): This is a way of executing :meth:`IElement.setTaggedValue` from the definition of the interface. For example:: - class IFoo(Interface): + class IFoo(Interface): taggedValue('key', 'value') .. seealso:: `zope.interface.taggedValue` @@ -505,15 +505,15 @@ class IInterfaceDeclaration(Interface): For example:: - def check_range(ob): - if ob.max < ob.min: - range ValueError + def check_range(ob): + if ob.max < ob.min: + raise ValueError("max value is less than min value") - class IRange(Interface): - min = Attribute("The min value") - max = Attribute("The max value") + class IRange(Interface): + min = Attribute("The min value") + max = Attribute("The max value") - invariant(check_range) + invariant(check_range) .. seealso:: `zope.interface.invariant` """ @@ -530,13 +530,13 @@ class IInterfaceDeclaration(Interface): For example:: - class IRange(Interface): - @interfacemethod - def __adapt__(self, obj): - if isinstance(obj, range): - # Return the builtin ``range`` as-is - return obj - return super(type(IRange), self).__adapt__(obj) + class IRange(Interface): + @interfacemethod + def __adapt__(self, obj): + if isinstance(obj, range): + # Return the builtin ``range`` as-is + return obj + return super(type(IRange), self).__adapt__(obj) You can use ``super`` to call the parent class functionality. Note that the zero-argument version (``super().__adapt__``) works on Python 3.6 and above, but diff --git a/src/zope/interface/tests/test_interface.py b/src/zope/interface/tests/test_interface.py index 4bbed1a..036e858 100644 --- a/src/zope/interface/tests/test_interface.py +++ b/src/zope/interface/tests/test_interface.py @@ -2177,9 +2177,46 @@ class InterfaceTests(unittest.TestCase): pass self.assertEqual(42, I(object())) - # __adapt__ supercedes providedBy() if defined. + # __adapt__ can ignore the fact that the object provides + # the interface if it chooses. self.assertEqual(42, I(O())) + def test___call___w_overridden_adapt_and_conform(self): + # Conform is first, taking precedence over __adapt__, + # *if* it returns non-None + from zope.interface import Interface + from zope.interface import interfacemethod + from zope.interface import implementer + + class IAdapt(Interface): + @interfacemethod + def __adapt__(self, obj): + return 42 + + class ISimple(Interface): + """Nothing special.""" + + @implementer(IAdapt) + class Conform24(object): + def __conform__(self, iface): + return 24 + + @implementer(IAdapt) + class ConformNone(object): + def __conform__(self, iface): + return None + + self.assertEqual(42, IAdapt(object())) + + self.assertEqual(24, ISimple(Conform24())) + self.assertEqual(24, IAdapt(Conform24())) + + with self.assertRaises(TypeError): + ISimple(ConformNone()) + + self.assertEqual(42, IAdapt(ConformNone())) + + def test___call___w_overridden_adapt_call_super(self): import sys from zope.interface import Interface |
