[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