| 
									
										
										
										
											2023-05-20 12:07:40 -04:00
										 |  |  | """Test equality and order comparisons.""" | 
					
						
							| 
									
										
										
										
											2006-04-21 10:40:58 +00:00
										 |  |  | import unittest | 
					
						
							| 
									
										
										
										
											2019-08-08 08:43:18 +03:00
										 |  |  | from test.support import ALWAYS_EQ | 
					
						
							| 
									
										
										
										
											2023-05-20 12:07:40 -04:00
										 |  |  | from fractions import Fraction | 
					
						
							|  |  |  | from decimal import Decimal | 
					
						
							| 
									
										
										
										
											2001-01-02 16:30:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-20 12:07:40 -04:00
										 |  |  | class ComparisonSimpleTest(unittest.TestCase): | 
					
						
							|  |  |  |     """Test equality and order comparisons for some simple cases.""" | 
					
						
							| 
									
										
										
										
											2001-01-02 16:30:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-20 12:07:40 -04:00
										 |  |  |     class Empty: | 
					
						
							|  |  |  |         def __repr__(self): | 
					
						
							|  |  |  |             return '<Empty>' | 
					
						
							| 
									
										
										
										
											2001-01-02 16:30:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-20 12:07:40 -04:00
										 |  |  |     class Cmp: | 
					
						
							|  |  |  |         def __init__(self, arg): | 
					
						
							|  |  |  |             self.arg = arg | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def __repr__(self): | 
					
						
							|  |  |  |             return '<Cmp %s>' % self.arg | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def __eq__(self, other): | 
					
						
							|  |  |  |             return self.arg == other | 
					
						
							| 
									
										
										
										
											2001-01-02 16:30:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-01-15 16:59:06 +00:00
										 |  |  |     set1 = [2, 2.0, 2, 2+0j, Cmp(2.0)] | 
					
						
							| 
									
										
										
										
											2006-04-21 10:40:58 +00:00
										 |  |  |     set2 = [[1], (3,), None, Empty()] | 
					
						
							|  |  |  |     candidates = set1 + set2 | 
					
						
							| 
									
										
										
										
											2001-01-02 16:30:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-21 10:40:58 +00:00
										 |  |  |     def test_comparisons(self): | 
					
						
							|  |  |  |         for a in self.candidates: | 
					
						
							|  |  |  |             for b in self.candidates: | 
					
						
							|  |  |  |                 if ((a in self.set1) and (b in self.set1)) or a is b: | 
					
						
							|  |  |  |                     self.assertEqual(a, b) | 
					
						
							| 
									
										
										
										
											2001-01-03 02:13:26 +00:00
										 |  |  |                 else: | 
					
						
							| 
									
										
										
										
											2006-04-21 10:40:58 +00:00
										 |  |  |                     self.assertNotEqual(a, b) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_id_comparisons(self): | 
					
						
							|  |  |  |         # Ensure default comparison compares id() of args | 
					
						
							|  |  |  |         L = [] | 
					
						
							|  |  |  |         for i in range(10): | 
					
						
							| 
									
										
										
										
											2023-05-20 12:07:40 -04:00
										 |  |  |             L.insert(len(L)//2, self.Empty()) | 
					
						
							| 
									
										
										
										
											2006-04-21 10:40:58 +00:00
										 |  |  |         for a in L: | 
					
						
							|  |  |  |             for b in L: | 
					
						
							| 
									
										
										
										
											2023-05-20 12:07:40 -04:00
										 |  |  |                 self.assertEqual(a == b, a is b, 'a=%r, b=%r' % (a, b)) | 
					
						
							| 
									
										
										
										
											2006-04-21 10:40:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-03-27 22:37:34 +00:00
										 |  |  |     def test_ne_defaults_to_not_eq(self): | 
					
						
							| 
									
										
										
										
											2023-05-20 12:07:40 -04:00
										 |  |  |         a = self.Cmp(1) | 
					
						
							|  |  |  |         b = self.Cmp(1) | 
					
						
							|  |  |  |         c = self.Cmp(2) | 
					
						
							| 
									
										
										
										
											2015-01-26 09:57:07 +02:00
										 |  |  |         self.assertIs(a == b, True) | 
					
						
							|  |  |  |         self.assertIs(a != b, False) | 
					
						
							|  |  |  |         self.assertIs(a != c, True) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_ne_high_priority(self): | 
					
						
							|  |  |  |         """object.__ne__() should allow reflected __ne__() to be tried""" | 
					
						
							|  |  |  |         calls = [] | 
					
						
							|  |  |  |         class Left: | 
					
						
							|  |  |  |             # Inherits object.__ne__() | 
					
						
							|  |  |  |             def __eq__(*args): | 
					
						
							|  |  |  |                 calls.append('Left.__eq__') | 
					
						
							|  |  |  |                 return NotImplemented | 
					
						
							|  |  |  |         class Right: | 
					
						
							|  |  |  |             def __eq__(*args): | 
					
						
							|  |  |  |                 calls.append('Right.__eq__') | 
					
						
							|  |  |  |                 return NotImplemented | 
					
						
							|  |  |  |             def __ne__(*args): | 
					
						
							|  |  |  |                 calls.append('Right.__ne__') | 
					
						
							|  |  |  |                 return NotImplemented | 
					
						
							|  |  |  |         Left() != Right() | 
					
						
							|  |  |  |         self.assertSequenceEqual(calls, ['Left.__eq__', 'Right.__ne__']) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_ne_low_priority(self): | 
					
						
							|  |  |  |         """object.__ne__() should not invoke reflected __eq__()""" | 
					
						
							|  |  |  |         calls = [] | 
					
						
							|  |  |  |         class Base: | 
					
						
							|  |  |  |             # Inherits object.__ne__() | 
					
						
							|  |  |  |             def __eq__(*args): | 
					
						
							|  |  |  |                 calls.append('Base.__eq__') | 
					
						
							|  |  |  |                 return NotImplemented | 
					
						
							|  |  |  |         class Derived(Base):  # Subclassing forces higher priority | 
					
						
							|  |  |  |             def __eq__(*args): | 
					
						
							|  |  |  |                 calls.append('Derived.__eq__') | 
					
						
							|  |  |  |                 return NotImplemented | 
					
						
							|  |  |  |             def __ne__(*args): | 
					
						
							|  |  |  |                 calls.append('Derived.__ne__') | 
					
						
							|  |  |  |                 return NotImplemented | 
					
						
							|  |  |  |         Base() != Derived() | 
					
						
							|  |  |  |         self.assertSequenceEqual(calls, ['Derived.__ne__', 'Base.__eq__']) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_other_delegation(self): | 
					
						
							|  |  |  |         """No default delegation between operations except __ne__()""" | 
					
						
							|  |  |  |         ops = ( | 
					
						
							|  |  |  |             ('__eq__', lambda a, b: a == b), | 
					
						
							|  |  |  |             ('__lt__', lambda a, b: a < b), | 
					
						
							|  |  |  |             ('__le__', lambda a, b: a <= b), | 
					
						
							|  |  |  |             ('__gt__', lambda a, b: a > b), | 
					
						
							|  |  |  |             ('__ge__', lambda a, b: a >= b), | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         for name, func in ops: | 
					
						
							|  |  |  |             with self.subTest(name): | 
					
						
							|  |  |  |                 def unexpected(*args): | 
					
						
							|  |  |  |                     self.fail('Unexpected operator method called') | 
					
						
							|  |  |  |                 class C: | 
					
						
							|  |  |  |                     __ne__ = unexpected | 
					
						
							|  |  |  |                 for other, _ in ops: | 
					
						
							|  |  |  |                     if other != name: | 
					
						
							|  |  |  |                         setattr(C, other, unexpected) | 
					
						
							|  |  |  |                 if name == '__eq__': | 
					
						
							|  |  |  |                     self.assertIs(func(C(), object()), False) | 
					
						
							|  |  |  |                 else: | 
					
						
							|  |  |  |                     self.assertRaises(TypeError, func, C(), object()) | 
					
						
							| 
									
										
										
										
											2007-03-27 22:37:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-01-06 00:09:11 +00:00
										 |  |  |     def test_issue_1393(self): | 
					
						
							|  |  |  |         x = lambda: None | 
					
						
							| 
									
										
										
										
											2019-08-08 08:43:18 +03:00
										 |  |  |         self.assertEqual(x, ALWAYS_EQ) | 
					
						
							|  |  |  |         self.assertEqual(ALWAYS_EQ, x) | 
					
						
							| 
									
										
										
										
											2008-01-06 00:09:11 +00:00
										 |  |  |         y = object() | 
					
						
							| 
									
										
										
										
											2019-08-08 08:43:18 +03:00
										 |  |  |         self.assertEqual(y, ALWAYS_EQ) | 
					
						
							|  |  |  |         self.assertEqual(ALWAYS_EQ, y) | 
					
						
							| 
									
										
										
										
											2008-01-06 00:09:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-20 12:07:40 -04:00
										 |  |  | class ComparisonFullTest(unittest.TestCase): | 
					
						
							|  |  |  |     """Test equality and ordering comparisons for built-in types and
 | 
					
						
							|  |  |  |     user-defined classes that implement relevant combinations of rich | 
					
						
							|  |  |  |     comparison methods. | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     class CompBase: | 
					
						
							|  |  |  |         """Base class for classes with rich comparison methods.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         The "x" attribute should be set to an underlying value to compare. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Derived classes have a "meth" tuple attribute listing names of | 
					
						
							|  |  |  |         comparison methods implemented. See assert_total_order(). | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Class without any rich comparison methods. | 
					
						
							|  |  |  |     class CompNone(CompBase): | 
					
						
							|  |  |  |         meth = () | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Classes with all combinations of value-based equality comparison methods. | 
					
						
							|  |  |  |     class CompEq(CompBase): | 
					
						
							|  |  |  |         meth = ("eq",) | 
					
						
							|  |  |  |         def __eq__(self, other): | 
					
						
							|  |  |  |             return self.x == other.x | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     class CompNe(CompBase): | 
					
						
							|  |  |  |         meth = ("ne",) | 
					
						
							|  |  |  |         def __ne__(self, other): | 
					
						
							|  |  |  |             return self.x != other.x | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     class CompEqNe(CompBase): | 
					
						
							|  |  |  |         meth = ("eq", "ne") | 
					
						
							|  |  |  |         def __eq__(self, other): | 
					
						
							|  |  |  |             return self.x == other.x | 
					
						
							|  |  |  |         def __ne__(self, other): | 
					
						
							|  |  |  |             return self.x != other.x | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Classes with all combinations of value-based less/greater-than order | 
					
						
							|  |  |  |     # comparison methods. | 
					
						
							|  |  |  |     class CompLt(CompBase): | 
					
						
							|  |  |  |         meth = ("lt",) | 
					
						
							|  |  |  |         def __lt__(self, other): | 
					
						
							|  |  |  |             return self.x < other.x | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     class CompGt(CompBase): | 
					
						
							|  |  |  |         meth = ("gt",) | 
					
						
							|  |  |  |         def __gt__(self, other): | 
					
						
							|  |  |  |             return self.x > other.x | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     class CompLtGt(CompBase): | 
					
						
							|  |  |  |         meth = ("lt", "gt") | 
					
						
							|  |  |  |         def __lt__(self, other): | 
					
						
							|  |  |  |             return self.x < other.x | 
					
						
							|  |  |  |         def __gt__(self, other): | 
					
						
							|  |  |  |             return self.x > other.x | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Classes with all combinations of value-based less/greater-or-equal-than | 
					
						
							|  |  |  |     # order comparison methods | 
					
						
							|  |  |  |     class CompLe(CompBase): | 
					
						
							|  |  |  |         meth = ("le",) | 
					
						
							|  |  |  |         def __le__(self, other): | 
					
						
							|  |  |  |             return self.x <= other.x | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     class CompGe(CompBase): | 
					
						
							|  |  |  |         meth = ("ge",) | 
					
						
							|  |  |  |         def __ge__(self, other): | 
					
						
							|  |  |  |             return self.x >= other.x | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     class CompLeGe(CompBase): | 
					
						
							|  |  |  |         meth = ("le", "ge") | 
					
						
							|  |  |  |         def __le__(self, other): | 
					
						
							|  |  |  |             return self.x <= other.x | 
					
						
							|  |  |  |         def __ge__(self, other): | 
					
						
							|  |  |  |             return self.x >= other.x | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # It should be sufficient to combine the comparison methods only within | 
					
						
							|  |  |  |     # each group. | 
					
						
							|  |  |  |     all_comp_classes = ( | 
					
						
							|  |  |  |             CompNone, | 
					
						
							|  |  |  |             CompEq, CompNe, CompEqNe,  # equal group | 
					
						
							|  |  |  |             CompLt, CompGt, CompLtGt,  # less/greater-than group | 
					
						
							|  |  |  |             CompLe, CompGe, CompLeGe)  # less/greater-or-equal group | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def create_sorted_instances(self, class_, values): | 
					
						
							|  |  |  |         """Create objects of type `class_` and return them in a list.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         `values` is a list of values that determines the value of data | 
					
						
							|  |  |  |         attribute `x` of each object. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Objects in the returned list are sorted by their identity.  They | 
					
						
							|  |  |  |         assigned values in `values` list order.  By assign decreasing | 
					
						
							|  |  |  |         values to objects with increasing identities, testcases can assert | 
					
						
							|  |  |  |         that order comparison is performed by value and not by identity. | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         instances = [class_() for __ in range(len(values))] | 
					
						
							|  |  |  |         instances.sort(key=id) | 
					
						
							|  |  |  |         # Assign the provided values to the instances. | 
					
						
							|  |  |  |         for inst, value in zip(instances, values): | 
					
						
							|  |  |  |             inst.x = value | 
					
						
							|  |  |  |         return instances | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def assert_equality_only(self, a, b, equal): | 
					
						
							|  |  |  |         """Assert equality result and that ordering is not implemented.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         a, b: Instances to be tested (of same or different type). | 
					
						
							|  |  |  |         equal: Boolean indicating the expected equality comparison results. | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         self.assertEqual(a == b, equal) | 
					
						
							|  |  |  |         self.assertEqual(b == a, equal) | 
					
						
							|  |  |  |         self.assertEqual(a != b, not equal) | 
					
						
							|  |  |  |         self.assertEqual(b != a, not equal) | 
					
						
							|  |  |  |         with self.assertRaisesRegex(TypeError, "not supported"): | 
					
						
							|  |  |  |             a < b | 
					
						
							|  |  |  |         with self.assertRaisesRegex(TypeError, "not supported"): | 
					
						
							|  |  |  |             a <= b | 
					
						
							|  |  |  |         with self.assertRaisesRegex(TypeError, "not supported"): | 
					
						
							|  |  |  |             a > b | 
					
						
							|  |  |  |         with self.assertRaisesRegex(TypeError, "not supported"): | 
					
						
							|  |  |  |             a >= b | 
					
						
							|  |  |  |         with self.assertRaisesRegex(TypeError, "not supported"): | 
					
						
							|  |  |  |             b < a | 
					
						
							|  |  |  |         with self.assertRaisesRegex(TypeError, "not supported"): | 
					
						
							|  |  |  |             b <= a | 
					
						
							|  |  |  |         with self.assertRaisesRegex(TypeError, "not supported"): | 
					
						
							|  |  |  |             b > a | 
					
						
							|  |  |  |         with self.assertRaisesRegex(TypeError, "not supported"): | 
					
						
							|  |  |  |             b >= a | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def assert_total_order(self, a, b, comp, a_meth=None, b_meth=None): | 
					
						
							|  |  |  |         """Test total ordering comparison of two instances.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         a, b: Instances to be tested (of same or different type). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         comp: -1, 0, or 1 indicates that the expected order comparison | 
					
						
							|  |  |  |            result for operations that are supported by the classes is | 
					
						
							|  |  |  |            a <, ==, or > b. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         a_meth, b_meth: Either None, indicating that all rich comparison | 
					
						
							|  |  |  |            methods are available, aa for builtins, or the tuple (subset) | 
					
						
							|  |  |  |            of "eq", "ne", "lt", "le", "gt", and "ge" that are available | 
					
						
							|  |  |  |            for the corresponding instance (of a user-defined class). | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         self.assert_eq_subtest(a, b, comp, a_meth, b_meth) | 
					
						
							|  |  |  |         self.assert_ne_subtest(a, b, comp, a_meth, b_meth) | 
					
						
							|  |  |  |         self.assert_lt_subtest(a, b, comp, a_meth, b_meth) | 
					
						
							|  |  |  |         self.assert_le_subtest(a, b, comp, a_meth, b_meth) | 
					
						
							|  |  |  |         self.assert_gt_subtest(a, b, comp, a_meth, b_meth) | 
					
						
							|  |  |  |         self.assert_ge_subtest(a, b, comp, a_meth, b_meth) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # The body of each subtest has form: | 
					
						
							|  |  |  |     # | 
					
						
							|  |  |  |     #     if value-based comparison methods: | 
					
						
							|  |  |  |     #         expect what the testcase defined for a op b and b rop a; | 
					
						
							|  |  |  |     #     else:  no value-based comparison | 
					
						
							|  |  |  |     #         expect default behavior of object for a op b and b rop a. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def assert_eq_subtest(self, a, b, comp, a_meth, b_meth): | 
					
						
							|  |  |  |         if a_meth is None or "eq" in a_meth or "eq" in b_meth: | 
					
						
							|  |  |  |             self.assertEqual(a == b, comp == 0) | 
					
						
							|  |  |  |             self.assertEqual(b == a, comp == 0) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             self.assertEqual(a == b, a is b) | 
					
						
							|  |  |  |             self.assertEqual(b == a, a is b) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def assert_ne_subtest(self, a, b, comp, a_meth, b_meth): | 
					
						
							|  |  |  |         if a_meth is None or not {"ne", "eq"}.isdisjoint(a_meth + b_meth): | 
					
						
							|  |  |  |             self.assertEqual(a != b, comp != 0) | 
					
						
							|  |  |  |             self.assertEqual(b != a, comp != 0) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             self.assertEqual(a != b, a is not b) | 
					
						
							|  |  |  |             self.assertEqual(b != a, a is not b) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def assert_lt_subtest(self, a, b, comp, a_meth, b_meth): | 
					
						
							|  |  |  |         if a_meth is None or "lt" in a_meth or "gt" in b_meth: | 
					
						
							|  |  |  |             self.assertEqual(a < b, comp < 0) | 
					
						
							|  |  |  |             self.assertEqual(b > a, comp < 0) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             with self.assertRaisesRegex(TypeError, "not supported"): | 
					
						
							|  |  |  |                 a < b | 
					
						
							|  |  |  |             with self.assertRaisesRegex(TypeError, "not supported"): | 
					
						
							|  |  |  |                 b > a | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def assert_le_subtest(self, a, b, comp, a_meth, b_meth): | 
					
						
							|  |  |  |         if a_meth is None or "le" in a_meth or "ge" in b_meth: | 
					
						
							|  |  |  |             self.assertEqual(a <= b, comp <= 0) | 
					
						
							|  |  |  |             self.assertEqual(b >= a, comp <= 0) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             with self.assertRaisesRegex(TypeError, "not supported"): | 
					
						
							|  |  |  |                 a <= b | 
					
						
							|  |  |  |             with self.assertRaisesRegex(TypeError, "not supported"): | 
					
						
							|  |  |  |                 b >= a | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def assert_gt_subtest(self, a, b, comp, a_meth, b_meth): | 
					
						
							|  |  |  |         if a_meth is None or "gt" in a_meth or "lt" in b_meth: | 
					
						
							|  |  |  |             self.assertEqual(a > b, comp > 0) | 
					
						
							|  |  |  |             self.assertEqual(b < a, comp > 0) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             with self.assertRaisesRegex(TypeError, "not supported"): | 
					
						
							|  |  |  |                 a > b | 
					
						
							|  |  |  |             with self.assertRaisesRegex(TypeError, "not supported"): | 
					
						
							|  |  |  |                 b < a | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def assert_ge_subtest(self, a, b, comp, a_meth, b_meth): | 
					
						
							|  |  |  |         if a_meth is None or "ge" in a_meth or "le" in b_meth: | 
					
						
							|  |  |  |             self.assertEqual(a >= b, comp >= 0) | 
					
						
							|  |  |  |             self.assertEqual(b <= a, comp >= 0) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             with self.assertRaisesRegex(TypeError, "not supported"): | 
					
						
							|  |  |  |                 a >= b | 
					
						
							|  |  |  |             with self.assertRaisesRegex(TypeError, "not supported"): | 
					
						
							|  |  |  |                 b <= a | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_objects(self): | 
					
						
							|  |  |  |         """Compare instances of type 'object'.""" | 
					
						
							|  |  |  |         a = object() | 
					
						
							|  |  |  |         b = object() | 
					
						
							|  |  |  |         self.assert_equality_only(a, a, True) | 
					
						
							|  |  |  |         self.assert_equality_only(a, b, False) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_comp_classes_same(self): | 
					
						
							|  |  |  |         """Compare same-class instances with comparison methods.""" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for cls in self.all_comp_classes: | 
					
						
							|  |  |  |             with self.subTest(cls): | 
					
						
							|  |  |  |                 instances = self.create_sorted_instances(cls, (1, 2, 1)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 # Same object. | 
					
						
							|  |  |  |                 self.assert_total_order(instances[0], instances[0], 0, | 
					
						
							|  |  |  |                                         cls.meth, cls.meth) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 # Different objects, same value. | 
					
						
							|  |  |  |                 self.assert_total_order(instances[0], instances[2], 0, | 
					
						
							|  |  |  |                                         cls.meth, cls.meth) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 # Different objects, value ascending for ascending identities. | 
					
						
							|  |  |  |                 self.assert_total_order(instances[0], instances[1], -1, | 
					
						
							|  |  |  |                                         cls.meth, cls.meth) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 # different objects, value descending for ascending identities. | 
					
						
							|  |  |  |                 # This is the interesting case to assert that order comparison | 
					
						
							|  |  |  |                 # is performed based on the value and not based on the identity. | 
					
						
							|  |  |  |                 self.assert_total_order(instances[1], instances[2], +1, | 
					
						
							|  |  |  |                                         cls.meth, cls.meth) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_comp_classes_different(self): | 
					
						
							|  |  |  |         """Compare different-class instances with comparison methods.""" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for cls_a in self.all_comp_classes: | 
					
						
							|  |  |  |             for cls_b in self.all_comp_classes: | 
					
						
							|  |  |  |                 with self.subTest(a=cls_a, b=cls_b): | 
					
						
							|  |  |  |                     a1 = cls_a() | 
					
						
							|  |  |  |                     a1.x = 1 | 
					
						
							|  |  |  |                     b1 = cls_b() | 
					
						
							|  |  |  |                     b1.x = 1 | 
					
						
							|  |  |  |                     b2 = cls_b() | 
					
						
							|  |  |  |                     b2.x = 2 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     self.assert_total_order( | 
					
						
							|  |  |  |                         a1, b1, 0, cls_a.meth, cls_b.meth) | 
					
						
							|  |  |  |                     self.assert_total_order( | 
					
						
							|  |  |  |                         a1, b2, -1, cls_a.meth, cls_b.meth) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_str_subclass(self): | 
					
						
							|  |  |  |         """Compare instances of str and a subclass.""" | 
					
						
							|  |  |  |         class StrSubclass(str): | 
					
						
							|  |  |  |             pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         s1 = str("a") | 
					
						
							|  |  |  |         s2 = str("b") | 
					
						
							|  |  |  |         c1 = StrSubclass("a") | 
					
						
							|  |  |  |         c2 = StrSubclass("b") | 
					
						
							|  |  |  |         c3 = StrSubclass("b") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assert_total_order(s1, s1,   0) | 
					
						
							|  |  |  |         self.assert_total_order(s1, s2, -1) | 
					
						
							|  |  |  |         self.assert_total_order(c1, c1,   0) | 
					
						
							|  |  |  |         self.assert_total_order(c1, c2, -1) | 
					
						
							|  |  |  |         self.assert_total_order(c2, c3,   0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assert_total_order(s1, c2, -1) | 
					
						
							|  |  |  |         self.assert_total_order(s2, c3,   0) | 
					
						
							|  |  |  |         self.assert_total_order(c1, s2, -1) | 
					
						
							|  |  |  |         self.assert_total_order(c2, s2,   0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_numbers(self): | 
					
						
							|  |  |  |         """Compare number types.""" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Same types. | 
					
						
							|  |  |  |         i1 = 1001 | 
					
						
							|  |  |  |         i2 = 1002 | 
					
						
							|  |  |  |         self.assert_total_order(i1, i1, 0) | 
					
						
							|  |  |  |         self.assert_total_order(i1, i2, -1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         f1 = 1001.0 | 
					
						
							|  |  |  |         f2 = 1001.1 | 
					
						
							|  |  |  |         self.assert_total_order(f1, f1, 0) | 
					
						
							|  |  |  |         self.assert_total_order(f1, f2, -1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         q1 = Fraction(2002, 2) | 
					
						
							|  |  |  |         q2 = Fraction(2003, 2) | 
					
						
							|  |  |  |         self.assert_total_order(q1, q1, 0) | 
					
						
							|  |  |  |         self.assert_total_order(q1, q2, -1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         d1 = Decimal('1001.0') | 
					
						
							|  |  |  |         d2 = Decimal('1001.1') | 
					
						
							|  |  |  |         self.assert_total_order(d1, d1, 0) | 
					
						
							|  |  |  |         self.assert_total_order(d1, d2, -1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         c1 = 1001+0j | 
					
						
							|  |  |  |         c2 = 1001+1j | 
					
						
							|  |  |  |         self.assert_equality_only(c1, c1, True) | 
					
						
							|  |  |  |         self.assert_equality_only(c1, c2, False) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Mixing types. | 
					
						
							|  |  |  |         for n1, n2 in ((i1,f1), (i1,q1), (i1,d1), (f1,q1), (f1,d1), (q1,d1)): | 
					
						
							|  |  |  |             self.assert_total_order(n1, n2, 0) | 
					
						
							|  |  |  |         for n1 in (i1, f1, q1, d1): | 
					
						
							|  |  |  |             self.assert_equality_only(n1, c1, True) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_sequences(self): | 
					
						
							|  |  |  |         """Compare list, tuple, and range.""" | 
					
						
							|  |  |  |         l1 = [1, 2] | 
					
						
							|  |  |  |         l2 = [2, 3] | 
					
						
							|  |  |  |         self.assert_total_order(l1, l1, 0) | 
					
						
							|  |  |  |         self.assert_total_order(l1, l2, -1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         t1 = (1, 2) | 
					
						
							|  |  |  |         t2 = (2, 3) | 
					
						
							|  |  |  |         self.assert_total_order(t1, t1, 0) | 
					
						
							|  |  |  |         self.assert_total_order(t1, t2, -1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         r1 = range(1, 2) | 
					
						
							|  |  |  |         r2 = range(2, 2) | 
					
						
							|  |  |  |         self.assert_equality_only(r1, r1, True) | 
					
						
							|  |  |  |         self.assert_equality_only(r1, r2, False) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assert_equality_only(t1, l1, False) | 
					
						
							|  |  |  |         self.assert_equality_only(l1, r1, False) | 
					
						
							|  |  |  |         self.assert_equality_only(r1, t1, False) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_bytes(self): | 
					
						
							|  |  |  |         """Compare bytes and bytearray.""" | 
					
						
							|  |  |  |         bs1 = b'a1' | 
					
						
							|  |  |  |         bs2 = b'b2' | 
					
						
							|  |  |  |         self.assert_total_order(bs1, bs1, 0) | 
					
						
							|  |  |  |         self.assert_total_order(bs1, bs2, -1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         ba1 = bytearray(b'a1') | 
					
						
							|  |  |  |         ba2 = bytearray(b'b2') | 
					
						
							|  |  |  |         self.assert_total_order(ba1, ba1,  0) | 
					
						
							|  |  |  |         self.assert_total_order(ba1, ba2, -1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assert_total_order(bs1, ba1, 0) | 
					
						
							|  |  |  |         self.assert_total_order(bs1, ba2, -1) | 
					
						
							|  |  |  |         self.assert_total_order(ba1, bs1, 0) | 
					
						
							|  |  |  |         self.assert_total_order(ba1, bs2, -1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_sets(self): | 
					
						
							|  |  |  |         """Compare set and frozenset.""" | 
					
						
							|  |  |  |         s1 = {1, 2} | 
					
						
							|  |  |  |         s2 = {1, 2, 3} | 
					
						
							|  |  |  |         self.assert_total_order(s1, s1, 0) | 
					
						
							|  |  |  |         self.assert_total_order(s1, s2, -1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         f1 = frozenset(s1) | 
					
						
							|  |  |  |         f2 = frozenset(s2) | 
					
						
							|  |  |  |         self.assert_total_order(f1, f1,  0) | 
					
						
							|  |  |  |         self.assert_total_order(f1, f2, -1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assert_total_order(s1, f1, 0) | 
					
						
							|  |  |  |         self.assert_total_order(s1, f2, -1) | 
					
						
							|  |  |  |         self.assert_total_order(f1, s1, 0) | 
					
						
							|  |  |  |         self.assert_total_order(f1, s2, -1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_mappings(self): | 
					
						
							|  |  |  |         """ Compare dict.
 | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         d1 = {1: "a", 2: "b"} | 
					
						
							|  |  |  |         d2 = {2: "b", 3: "c"} | 
					
						
							|  |  |  |         d3 = {3: "c", 2: "b"} | 
					
						
							|  |  |  |         self.assert_equality_only(d1, d1, True) | 
					
						
							|  |  |  |         self.assert_equality_only(d1, d2, False) | 
					
						
							|  |  |  |         self.assert_equality_only(d2, d3, True) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-21 10:40:58 +00:00
										 |  |  | if __name__ == '__main__': | 
					
						
							| 
									
										
										
										
											2015-04-13 15:00:43 -05:00
										 |  |  |     unittest.main() |