summaryrefslogtreecommitdiff
path: root/src/zope/interface
diff options
context:
space:
mode:
authorJason Madden <jamadden@gmail.com>2020-04-07 07:04:44 -0500
committerJason Madden <jamadden@gmail.com>2020-04-07 07:04:44 -0500
commitb1807049d47afef711c467b785fae6aab7be851a (patch)
treeb2cd6f93ab0ec6dd7b4dad040367611289f4e3af /src/zope/interface
parent10eadd6305ee57910dbcc508b293f4bf0364fd84 (diff)
downloadzope-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__.py2
-rw-r--r--src/zope/interface/interface.py5
-rw-r--r--src/zope/interface/interfaces.py30
-rw-r--r--src/zope/interface/tests/test_interface.py39
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