From: Serhiy Storchaka Date: Mon, 25 Sep 2017 11:41:34 +0000 (+0300) Subject: bpo-25732: Make functools.total_ordering implementing __ne__. (#3748) X-Git-Tag: v2.7.15rc1~191 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d94a65a0694a188713f91ba7c9fffded090247dc;p=python bpo-25732: Make functools.total_ordering implementing __ne__. (#3748) Patch by Raymond Hettinger. --- diff --git a/Lib/functools.py b/Lib/functools.py index 53680b8946..5d755d4726 100644 --- a/Lib/functools.py +++ b/Lib/functools.py @@ -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) diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py index 62d60296bc..b3372ea7c3 100644 --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -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, diff --git a/Misc/NEWS.d/next/Library/2017-09-25-13-10-08.bpo-25732.RWWgzg.rst b/Misc/NEWS.d/next/Library/2017-09-25-13-10-08.bpo-25732.RWWgzg.rst new file mode 100644 index 0000000000..1d807b1b5f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-09-25-13-10-08.bpo-25732.RWWgzg.rst @@ -0,0 +1 @@ +`functools.total_ordering()` now implements the `__ne__` method.