[pypy-commit] pypy py3.5: python Issue #21408: The default __ne__() now returns NotImplemented if __eq__() returned NotImplemented.

amauryfa pypy.commits at gmail.com
Sun Oct 9 10:50:25 EDT 2016


Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch: py3.5
Changeset: r87665:0fd09e396a7c
Date: 2016-10-09 16:46 +0200
http://bitbucket.org/pypy/pypy/changeset/0fd09e396a7c/

Log:	python Issue #21408: The default __ne__() now returns NotImplemented
	if __eq__() returned NotImplemented.

diff --git a/pypy/objspace/descroperation.py b/pypy/objspace/descroperation.py
--- a/pypy/objspace/descroperation.py
+++ b/pypy/objspace/descroperation.py
@@ -589,7 +589,10 @@
             else:
                 return space.w_False
         elif left == '__ne__':
-            return space.not_(space.eq(w_obj1, w_obj2))
+            if space.is_w(w_obj1, w_obj2):
+                return space.w_False
+            else:
+                return space.w_True
         #
         # if we arrived here, they are unorderable
         raise oefmt(space.w_TypeError,
diff --git a/pypy/objspace/std/objectobject.py b/pypy/objspace/std/objectobject.py
--- a/pypy/objspace/std/objectobject.py
+++ b/pypy/objspace/std/objectobject.py
@@ -207,7 +207,13 @@
     return space.w_NotImplemented
 
 def descr__ne__(space, w_self, w_other):
-    return space.not_(space.eq(w_self, w_other))
+    # By default, __ne__() delegates to __eq__() and inverts the result,
+    # unless the latter returns NotImplemented.
+    w_eq = space.lookup(w_self, '__eq__')
+    w_res = space.get_and_call_function(w_eq, w_self, w_other)
+    if space.is_w(w_res, space.w_NotImplemented):
+        return w_res
+    return space.not_(w_res)
 
 def descr_richcompare(space, w_self, w_other):
     return space.w_NotImplemented
diff --git a/pypy/objspace/std/test/test_obj.py b/pypy/objspace/std/test/test_obj.py
--- a/pypy/objspace/std/test/test_obj.py
+++ b/pypy/objspace/std/test/test_obj.py
@@ -276,7 +276,7 @@
         assert o.__eq__(o) is True
         assert o.__eq__(o2) is NotImplemented
         assert o.__ne__(o) is False
-        assert o.__ne__(o2) is True
+        assert o.__ne__(o2) is NotImplemented
         assert o.__le__(o2) is NotImplemented
         assert o.__lt__(o2) is NotImplemented
         assert o.__ge__(o2) is NotImplemented
diff --git a/pypy/objspace/test/test_descroperation.py b/pypy/objspace/test/test_descroperation.py
--- a/pypy/objspace/test/test_descroperation.py
+++ b/pypy/objspace/test/test_descroperation.py
@@ -464,6 +464,42 @@
         assert not(A(1) != B(1))
         assert not(B(1) != A(1))
 
+    def test_ne_high_priority(self):
+        """object.__ne__() should allow reflected __ne__() to be tried"""
+        calls = []
+        class Left:
+            # Inherits object.__ne__()
+            def __eq__(*args):
+                calls.append('Left.__eq__')
+                return NotImplemented
+        class Right:
+            def __eq__(*args):
+                calls.append('Right.__eq__')
+                return NotImplemented
+            def __ne__(*args):
+                calls.append('Right.__ne__')
+                return NotImplemented
+        Left() != Right()
+        assert calls == ['Left.__eq__', 'Right.__ne__']
+
+    def test_ne_low_priority(self):
+        """object.__ne__() should not invoke reflected __eq__()"""
+        calls = []
+        class Base:
+            # Inherits object.__ne__()
+            def __eq__(*args):
+                calls.append('Base.__eq__')
+                return NotImplemented
+        class Derived(Base):  # Subclassing forces higher priority
+            def __eq__(*args):
+                calls.append('Derived.__eq__')
+                return NotImplemented
+            def __ne__(*args):
+                calls.append('Derived.__ne__')
+                return NotImplemented
+        Base() != Derived()
+        assert calls == ['Derived.__ne__', 'Base.__eq__']
+
     def test_partial_ordering(self):
         class A(object):
             def __lt__(self, other):


More information about the pypy-commit mailing list