Commit d94a65a0 authored by Serhiy Storchaka's avatar Serhiy Storchaka Committed by GitHub

bpo-25732: Make functools.total_ordering implementing __ne__. (#3748)

Patch by Raymond Hettinger.
parent 5f5da728
......@@ -55,23 +55,28 @@ def total_ordering(cls):
convert = {
'__lt__': [('__gt__', lambda self, other: not (self < other or self == other)),
('__le__', lambda self, other: self < other or self == other),
('__ne__', lambda self, other: not self == other),
('__ge__', lambda self, other: not self < other)],
'__le__': [('__ge__', lambda self, other: not self <= other or self == other),
('__lt__', lambda self, other: self <= other and not self == other),
('__ne__', lambda self, other: not self == other),
('__gt__', lambda self, other: not self <= other)],
'__gt__': [('__lt__', lambda self, other: not (self > other or self == other)),
('__ge__', lambda self, other: self > other or self == other),
('__ne__', lambda self, other: not self == other),
('__le__', lambda self, other: not self > other)],
'__ge__': [('__le__', lambda self, other: (not self >= other) or self == other),
('__gt__', lambda self, other: self >= other and not self == other),
('__ne__', lambda self, other: not self == other),
('__lt__', lambda self, other: not self >= other)]
}
roots = set(dir(cls)) & set(convert)
defined_methods = set(dir(cls))
roots = defined_methods & set(convert)
if not roots:
raise ValueError('must define at least one ordering operation: < > <= >=')
root = max(roots) # prefer __lt__ to __le__ to __gt__ to __ge__
for opname, opfunc in convert[root]:
if opname not in roots:
if opname not in defined_methods:
opfunc.__name__ = opname
opfunc.__doc__ = getattr(int, opname).__doc__
setattr(cls, opname, opfunc)
......
......@@ -600,6 +600,59 @@ class TestTotalOrdering(unittest.TestCase):
with self.assertRaises(TypeError):
TestTO(8) <= ()
def test_bug_25732(self):
@functools.total_ordering
class A:
def __init__(self, value):
self.value = value
def __gt__(self, other):
return self.value > other.value
def __eq__(self, other):
return self.value == other.value
self.assertTrue(A(1) != A(2))
self.assertFalse(A(1) != A(1))
@functools.total_ordering
class A(object):
def __init__(self, value):
self.value = value
def __gt__(self, other):
return self.value > other.value
def __eq__(self, other):
return self.value == other.value
self.assertTrue(A(1) != A(2))
self.assertFalse(A(1) != A(1))
@functools.total_ordering
class A:
def __init__(self, value):
self.value = value
def __gt__(self, other):
return self.value > other.value
def __eq__(self, other):
return self.value == other.value
def __ne__(self, other):
raise RuntimeError(self, other)
with self.assertRaises(RuntimeError):
A(1) != A(2)
with self.assertRaises(RuntimeError):
A(1) != A(1)
@functools.total_ordering
class A(object):
def __init__(self, value):
self.value = value
def __gt__(self, other):
return self.value > other.value
def __eq__(self, other):
return self.value == other.value
def __ne__(self, other):
raise RuntimeError(self, other)
with self.assertRaises(RuntimeError):
A(1) != A(2)
with self.assertRaises(RuntimeError):
A(1) != A(1)
def test_main(verbose=None):
test_classes = (
TestPartial,
......
`functools.total_ordering()` now implements the `__ne__` method.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment