diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/zope/interface/declarations.py | 11 | ||||
| -rw-r--r-- | src/zope/interface/tests/test_declarations.py | 40 |
2 files changed, 46 insertions, 5 deletions
diff --git a/src/zope/interface/declarations.py b/src/zope/interface/declarations.py index d770fa0..48e459a 100644 --- a/src/zope/interface/declarations.py +++ b/src/zope/interface/declarations.py @@ -176,11 +176,12 @@ class Implements(Declaration): def __hash__(self): return Declaration.__hash__(self) - def __eq__(self, other): - return self is other - - def __ne__(self, other): - return self is not other + # We want equality to be based on identity. However, we can't actually + # implement __eq__/__ne__ to do this because sometimes we get wrapped in a proxy. + # We need to let the proxy types implement these methods so they can handle unwrapping + # and then rely on: (1) the interpreter automatically changing `implements == proxy` into + # `proxy == implements` (which will call proxy.__eq__ to do the unwrapping) and then + # (2) the default equality semantics being identity based. def __lt__(self, other): c = self.__cmp(other) diff --git a/src/zope/interface/tests/test_declarations.py b/src/zope/interface/tests/test_declarations.py index 83da6fa..702a677 100644 --- a/src/zope/interface/tests/test_declarations.py +++ b/src/zope/interface/tests/test_declarations.py @@ -283,6 +283,46 @@ class TestImplements(unittest.TestCase): self.assertTrue(implementedBy(A) >= IFoo) self.assertTrue(implementedBy(A) != IFoo) + def test_proxy_equality(self): + # https://github.com/zopefoundation/zope.interface/issues/55 + class Proxy(object): + def __init__(self, wrapped): + self._wrapped = wrapped + + def __getattr__(self, name): + return getattr(self._wrapped, name) + + def __eq__(self, other): + return self._wrapped == other + + def __ne__(self, other): + return self._wrapped != other + + from zope.interface.declarations import implementedBy + class A(object): + pass + + class B(object): + pass + + implementedByA = implementedBy(A) + implementedByB = implementedBy(B) + proxy = Proxy(implementedByA) + + # The order of arguments to the operators matters, + # test both + self.assertTrue(implementedByA == implementedByA) + self.assertTrue(implementedByA != implementedByB) + self.assertTrue(implementedByB != implementedByA) + + self.assertTrue(proxy == implementedByA) + self.assertTrue(implementedByA == proxy) + self.assertFalse(proxy != implementedByA) + self.assertFalse(implementedByA != proxy) + + self.assertTrue(proxy != implementedByB) + self.assertTrue(implementedByB != proxy) + class Test_implementedByFallback(unittest.TestCase): |
