Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 34af502

Browse files
Issue #21408: The default __ne__() now returns NotImplemented if __eq__()
returned NotImplemented. Removed incorrect implementations of __ne__().
2 parents 4e1942b + f4b7a02 commit 34af502

11 files changed

Lines changed: 77 additions & 47 deletions

File tree

Lib/_collections_abc.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -224,9 +224,6 @@ def __eq__(self, other):
224224
return NotImplemented
225225
return len(self) == len(other) and self.__le__(other)
226226

227-
def __ne__(self, other):
228-
return not (self == other)
229-
230227
@classmethod
231228
def _from_iterable(cls, it):
232229
'''Construct an instance of the class from any iterable input.
@@ -451,9 +448,6 @@ def __eq__(self, other):
451448
return NotImplemented
452449
return dict(self.items()) == dict(other.items())
453450

454-
def __ne__(self, other):
455-
return not (self == other)
456-
457451
Mapping.register(mappingproxy)
458452

459453

Lib/doctest.py

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -481,9 +481,6 @@ def __eq__(self, other):
481481
self.options == other.options and \
482482
self.exc_msg == other.exc_msg
483483

484-
def __ne__(self, other):
485-
return not self == other
486-
487484
def __hash__(self):
488485
return hash((self.source, self.want, self.lineno, self.indent,
489486
self.exc_msg))
@@ -548,9 +545,6 @@ def __eq__(self, other):
548545
self.filename == other.filename and \
549546
self.lineno == other.lineno
550547

551-
def __ne__(self, other):
552-
return not self == other
553-
554548
def __hash__(self):
555549
return hash((self.docstring, self.name, self.filename, self.lineno))
556550

@@ -2291,9 +2285,6 @@ def __eq__(self, other):
22912285
self._dt_tearDown == other._dt_tearDown and \
22922286
self._dt_checker == other._dt_checker
22932287

2294-
def __ne__(self, other):
2295-
return not self == other
2296-
22972288
def __hash__(self):
22982289
return hash((self._dt_optionflags, self._dt_setUp, self._dt_tearDown,
22992290
self._dt_checker))

Lib/lib2to3/pytree.py

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -64,16 +64,6 @@ def __eq__(self, other):
6464

6565
__hash__ = None # For Py3 compatibility.
6666

67-
def __ne__(self, other):
68-
"""
69-
Compare two nodes for inequality.
70-
71-
This calls the method _eq().
72-
"""
73-
if self.__class__ is not other.__class__:
74-
return NotImplemented
75-
return not self._eq(other)
76-
7767
def _eq(self, other):
7868
"""
7969
Compare two nodes for equality.

Lib/numbers.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -141,11 +141,6 @@ def __eq__(self, other):
141141
"""self == other"""
142142
raise NotImplementedError
143143

144-
def __ne__(self, other):
145-
"""self != other"""
146-
# The default __ne__ doesn't negate __eq__ until 3.0.
147-
return not (self == other)
148-
149144
Complex.register(complex)
150145

151146

Lib/pathlib.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -710,9 +710,6 @@ def __eq__(self, other):
710710
return NotImplemented
711711
return self._cparts == other._cparts and self._flavour is other._flavour
712712

713-
def __ne__(self, other):
714-
return not self == other
715-
716713
def __hash__(self):
717714
try:
718715
return self._hash

Lib/test/test_binop.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -194,10 +194,6 @@ def __eq__(self, other):
194194
return float(self) == other
195195
return NotImplemented
196196

197-
def __ne__(self, other):
198-
"""Compare two Rats for inequality."""
199-
return not self == other
200-
201197
class RatTestCase(unittest.TestCase):
202198
"""Unit tests for Rat class and its support utilities."""
203199

Lib/test/test_compare.py

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,69 @@ def test_id_comparisons(self):
4848
def test_ne_defaults_to_not_eq(self):
4949
a = Cmp(1)
5050
b = Cmp(1)
51-
self.assertTrue(a == b)
52-
self.assertFalse(a != b)
51+
c = Cmp(2)
52+
self.assertIs(a == b, True)
53+
self.assertIs(a != b, False)
54+
self.assertIs(a != c, True)
55+
56+
def test_ne_high_priority(self):
57+
"""object.__ne__() should allow reflected __ne__() to be tried"""
58+
calls = []
59+
class Left:
60+
# Inherits object.__ne__()
61+
def __eq__(*args):
62+
calls.append('Left.__eq__')
63+
return NotImplemented
64+
class Right:
65+
def __eq__(*args):
66+
calls.append('Right.__eq__')
67+
return NotImplemented
68+
def __ne__(*args):
69+
calls.append('Right.__ne__')
70+
return NotImplemented
71+
Left() != Right()
72+
self.assertSequenceEqual(calls, ['Left.__eq__', 'Right.__ne__'])
73+
74+
def test_ne_low_priority(self):
75+
"""object.__ne__() should not invoke reflected __eq__()"""
76+
calls = []
77+
class Base:
78+
# Inherits object.__ne__()
79+
def __eq__(*args):
80+
calls.append('Base.__eq__')
81+
return NotImplemented
82+
class Derived(Base): # Subclassing forces higher priority
83+
def __eq__(*args):
84+
calls.append('Derived.__eq__')
85+
return NotImplemented
86+
def __ne__(*args):
87+
calls.append('Derived.__ne__')
88+
return NotImplemented
89+
Base() != Derived()
90+
self.assertSequenceEqual(calls, ['Derived.__ne__', 'Base.__eq__'])
91+
92+
def test_other_delegation(self):
93+
"""No default delegation between operations except __ne__()"""
94+
ops = (
95+
('__eq__', lambda a, b: a == b),
96+
('__lt__', lambda a, b: a < b),
97+
('__le__', lambda a, b: a <= b),
98+
('__gt__', lambda a, b: a > b),
99+
('__ge__', lambda a, b: a >= b),
100+
)
101+
for name, func in ops:
102+
with self.subTest(name):
103+
def unexpected(*args):
104+
self.fail('Unexpected operator method called')
105+
class C:
106+
__ne__ = unexpected
107+
for other, _ in ops:
108+
if other != name:
109+
setattr(C, other, unexpected)
110+
if name == '__eq__':
111+
self.assertIs(func(C(), object()), False)
112+
else:
113+
self.assertRaises(TypeError, func, C(), object())
53114

54115
def test_issue_1393(self):
55116
x = lambda: None

Lib/unittest/case.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1342,9 +1342,6 @@ def __eq__(self, other):
13421342
self._testFunc == other._testFunc and \
13431343
self._description == other._description
13441344

1345-
def __ne__(self, other):
1346-
return not self == other
1347-
13481345
def __hash__(self):
13491346
return hash((type(self), self._setUpFunc, self._tearDownFunc,
13501347
self._testFunc, self._description))

Lib/unittest/suite.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,6 @@ def __eq__(self, other):
3131
return NotImplemented
3232
return list(self) == list(other)
3333

34-
def __ne__(self, other):
35-
return not self == other
36-
3734
def __iter__(self):
3835
return iter(self._tests)
3936

Misc/NEWS

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ Release date: TBA
1010
Core and Builtins
1111
-----------------
1212

13+
- Issue #21408: The default __ne__() now returns NotImplemented if __eq__()
14+
returned NotImplemented.
15+
1316
- Issue #23321: Fixed a crash in str.decode() when error handler returned
1417
replacment string longer than mailformed input data.
1518

@@ -215,6 +218,10 @@ Core and Builtins
215218
Library
216219
-------
217220

221+
- Issue #21408: Removed incorrect implementations of __ne__() which didn't
222+
returned NotImplemented if __eq__() returned NotImplemented. The default
223+
__ne__() now works correctly.
224+
218225
- Issue #19996: :class:`email.feedparser.FeedParser` now handles (malformed)
219226
headers with no key rather than amusing the body has started.
220227

0 commit comments

Comments
 (0)