Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions Lib/functools.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
53 changes: 53 additions & 0 deletions Lib/test/test_functools.py
Original file line number Diff line number Diff line change
Expand Up @@ -600,6 +600,59 @@ def __lt__(self, other):
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,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
`functools.total_ordering()` now implements the `__ne__` method.