From: Éric Araujo Date: Sat, 19 Mar 2011 03:29:36 +0000 (+0100) Subject: Fix the total_ordering decorator to handle cross-type comparisons X-Git-Tag: v2.7.2rc1~238 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=374274db7f7536836d0acd598ff6001aa5ed06c8;p=python Fix the total_ordering decorator to handle cross-type comparisons that could lead to infinite recursion (closes #10042). --- diff --git a/Lib/functools.py b/Lib/functools.py index 1a1f22ed00..01889cb0c3 100644 --- a/Lib/functools.py +++ b/Lib/functools.py @@ -53,17 +53,17 @@ def wraps(wrapped, def total_ordering(cls): """Class decorator that fills in missing ordering methods""" convert = { - '__lt__': [('__gt__', lambda self, other: other < self), - ('__le__', lambda self, other: not other < self), + '__lt__': [('__gt__', lambda self, other: not (self < other or self == other)), + ('__le__', lambda self, other: self < other or self == other), ('__ge__', lambda self, other: not self < other)], - '__le__': [('__ge__', lambda self, other: other <= self), - ('__lt__', lambda self, other: not other <= self), + '__le__': [('__ge__', lambda self, other: not self <= other or self == other), + ('__lt__', lambda self, other: self <= other and not self == other), ('__gt__', lambda self, other: not self <= other)], - '__gt__': [('__lt__', lambda self, other: other > self), - ('__ge__', lambda self, other: not other > self), + '__gt__': [('__lt__', lambda self, other: not (self > other or self == other)), + ('__ge__', lambda self, other: self > other or self == other), ('__le__', lambda self, other: not self > other)], - '__ge__': [('__le__', lambda self, other: other >= self), - ('__gt__', lambda self, other: not other >= self), + '__ge__': [('__le__', lambda self, other: (not self >= other) or self == other), + ('__gt__', lambda self, other: self >= other and not self == other), ('__lt__', lambda self, other: not self >= other)] } roots = set(dir(cls)) & set(convert) diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py index 6bc7b2b8ac..a713314f16 100644 --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -361,6 +361,8 @@ class TestTotalOrdering(unittest.TestCase): self.value = value def __lt__(self, other): return self.value < other.value + def __eq__(self, other): + return self.value == other.value self.assertTrue(A(1) < A(2)) self.assertTrue(A(2) > A(1)) self.assertTrue(A(1) <= A(2)) @@ -375,6 +377,8 @@ class TestTotalOrdering(unittest.TestCase): self.value = value def __le__(self, other): return self.value <= other.value + def __eq__(self, other): + return self.value == other.value self.assertTrue(A(1) < A(2)) self.assertTrue(A(2) > A(1)) self.assertTrue(A(1) <= A(2)) @@ -389,6 +393,8 @@ class TestTotalOrdering(unittest.TestCase): 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.assertTrue(A(2) > A(1)) self.assertTrue(A(1) <= A(2)) @@ -403,6 +409,8 @@ class TestTotalOrdering(unittest.TestCase): self.value = value def __ge__(self, other): return self.value >= other.value + def __eq__(self, other): + return self.value == other.value self.assertTrue(A(1) < A(2)) self.assertTrue(A(2) > A(1)) self.assertTrue(A(1) <= A(2)) @@ -428,6 +436,22 @@ class TestTotalOrdering(unittest.TestCase): class A: pass + def test_bug_10042(self): + @functools.total_ordering + class TestTO: + def __init__(self, value): + self.value = value + def __eq__(self, other): + if isinstance(other, TestTO): + return self.value == other.value + return False + def __lt__(self, other): + if isinstance(other, TestTO): + return self.value < other.value + raise TypeError + with self.assertRaises(TypeError): + TestTO(8) <= () + def test_main(verbose=None): test_classes = ( TestPartial, diff --git a/Misc/ACKS b/Misc/ACKS index 5d617daa36..66ace9a393 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -669,6 +669,7 @@ Bernhard Reiter Steven Reiz Roeland Rengelink Tim Rice +Francesco Ricciardi Jan Pieter Riegel Armin Rigo Nicholas Riley diff --git a/Misc/NEWS b/Misc/NEWS index 9c136aa943..c42d89b908 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -43,6 +43,9 @@ Core and Builtins Library ------- +- Issue #10042: Fixed the total_ordering decorator to handle cross-type + comparisons that could lead to infinite recursion. + - Issue #10979: unittest stdout buffering now works with class and module setup and teardown.