summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarius Gedminas <marius@gedmin.as>2016-09-05 09:10:12 +0300
committerGitHub <noreply@github.com>2016-09-05 09:10:11 +0300
commitfe670a2df4634804a31ad8446b6e42f61a31694d (patch)
tree1e503365140693acc601b17b7d9f7435b1a1daa4
parent69cacf26ff8f49a66b1396b8effe3f22e0e4d1a5 (diff)
parentc0e980b4b986a95a7699d0f417d6f8ff185f48d7 (diff)
downloadzope-interface-fe670a2df4634804a31ad8446b6e42f61a31694d.tar.gz
Merge pull request #56 from zopefoundation/fix-55
Fix equality testing of implementedBy objects that have been proxied.
-rw-r--r--CHANGES.rst6
-rw-r--r--src/zope/interface/declarations.py11
-rw-r--r--src/zope/interface/tests/test_declarations.py40
3 files changed, 50 insertions, 7 deletions
diff --git a/CHANGES.rst b/CHANGES.rst
index 3f562dc..2fbabbe 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -1,10 +1,11 @@
Changes
=======
-4.4.0 (unreleased)
+4.3.2 (unreleased)
------------------
-- Nothing changed yet.
+- Fix equality testing of ``implementedBy`` objects and proxies.
+ (https://github.com/zopefoundation/zope.interface/issues/55)
4.3.1 (2016-08-31)
@@ -31,6 +32,7 @@ Changes
manipulate utilities in large registries at the cost of some
additional memory usage. (https://github.com/zopefoundation/zope.interface/issues/46)
+
4.2.0 (2016-06-10)
------------------
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):