diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2018-07-31 06:18:24 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-07-31 06:18:24 (GMT) |
commit | ac20e0f98d6727ba97a9575bfa2a11b2f6247c35 (patch) | |
tree | 3b7938d610796051659b1b6fff27387a731c934c /Lib | |
parent | c48e26dcadbff8620bb5881d3bd148fc8894d0ef (diff) | |
download | cpython-ac20e0f98d6727ba97a9575bfa2a11b2f6247c35.zip cpython-ac20e0f98d6727ba97a9575bfa2a11b2f6247c35.tar.gz cpython-ac20e0f98d6727ba97a9575bfa2a11b2f6247c35.tar.bz2 |
bpo-1617161: Make the hash and equality of methods not depending on the value of self. (GH-7848)
* The hash of BuiltinMethodType instances no longer depends on the hash
of __self__. It depends now on the hash of id(__self__).
* The hash and equality of ModuleType and MethodWrapperType instances no
longer depend on the hash and equality of __self__. They depend now on
the hash and equality of id(__self__).
* MethodWrapperType instances no longer support ordering.
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/test/test_class.py | 38 | ||||
-rw-r--r-- | Lib/test/test_descr.py | 83 |
2 files changed, 85 insertions, 36 deletions
diff --git a/Lib/test/test_class.py b/Lib/test/test_class.py index 841cac9..998452a 100644 --- a/Lib/test/test_class.py +++ b/Lib/test/test_class.py @@ -534,6 +534,16 @@ class ClassTests(unittest.TestCase): else: self.fail("attribute error for I.__init__ got masked") + def assertNotOrderable(self, a, b): + with self.assertRaises(TypeError): + a < b + with self.assertRaises(TypeError): + a > b + with self.assertRaises(TypeError): + a <= b + with self.assertRaises(TypeError): + a >= b + def testHashComparisonOfMethods(self): # Test comparison and hash of methods class A: @@ -544,24 +554,30 @@ class ClassTests(unittest.TestCase): def g(self): pass def __eq__(self, other): - return self.x == other.x + return True def __hash__(self): - return self.x + raise TypeError class B(A): pass a1 = A(1) - a2 = A(2) - self.assertEqual(a1.f, a1.f) - self.assertNotEqual(a1.f, a2.f) - self.assertNotEqual(a1.f, a1.g) - self.assertEqual(a1.f, A(1).f) + a2 = A(1) + self.assertTrue(a1.f == a1.f) + self.assertFalse(a1.f != a1.f) + self.assertFalse(a1.f == a2.f) + self.assertTrue(a1.f != a2.f) + self.assertFalse(a1.f == a1.g) + self.assertTrue(a1.f != a1.g) + self.assertNotOrderable(a1.f, a1.f) self.assertEqual(hash(a1.f), hash(a1.f)) - self.assertEqual(hash(a1.f), hash(A(1).f)) - self.assertNotEqual(A.f, a1.f) - self.assertNotEqual(A.f, A.g) - self.assertEqual(B.f, A.f) + self.assertFalse(A.f == a1.f) + self.assertTrue(A.f != a1.f) + self.assertFalse(A.f == A.g) + self.assertTrue(A.f != A.g) + self.assertTrue(B.f == A.f) + self.assertFalse(B.f != A.f) + self.assertNotOrderable(A.f, A.f) self.assertEqual(hash(B.f), hash(A.f)) # the following triggers a SystemError in 2.4 diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index 0e7728e..b96d35c 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -4350,38 +4350,71 @@ order (MRO) for bases """ else: self.fail("did not test __init__() for None return") + def assertNotOrderable(self, a, b): + with self.assertRaises(TypeError): + a < b + with self.assertRaises(TypeError): + a > b + with self.assertRaises(TypeError): + a <= b + with self.assertRaises(TypeError): + a >= b + def test_method_wrapper(self): # Testing method-wrapper objects... # <type 'method-wrapper'> did not support any reflection before 2.5 - - # XXX should methods really support __eq__? - l = [] - self.assertEqual(l.__add__, l.__add__) - self.assertEqual(l.__add__, [].__add__) - self.assertNotEqual(l.__add__, [5].__add__) - self.assertNotEqual(l.__add__, l.__mul__) + self.assertTrue(l.__add__ == l.__add__) + self.assertFalse(l.__add__ != l.__add__) + self.assertFalse(l.__add__ == [].__add__) + self.assertTrue(l.__add__ != [].__add__) + self.assertFalse(l.__add__ == l.__mul__) + self.assertTrue(l.__add__ != l.__mul__) + self.assertNotOrderable(l.__add__, l.__add__) self.assertEqual(l.__add__.__name__, '__add__') - if hasattr(l.__add__, '__self__'): - # CPython - self.assertIs(l.__add__.__self__, l) - self.assertIs(l.__add__.__objclass__, list) - else: - # Python implementations where [].__add__ is a normal bound method - self.assertIs(l.__add__.im_self, l) - self.assertIs(l.__add__.im_class, list) + self.assertIs(l.__add__.__self__, l) + self.assertIs(l.__add__.__objclass__, list) self.assertEqual(l.__add__.__doc__, list.__add__.__doc__) - try: - hash(l.__add__) - except TypeError: - pass - else: - self.fail("no TypeError from hash([].__add__)") + # hash([].__add__) should not be based on hash([]) + hash(l.__add__) - t = () - t += (7,) - self.assertEqual(t.__add__, (7,).__add__) - self.assertEqual(hash(t.__add__), hash((7,).__add__)) + def test_builtin_function_or_method(self): + # Not really belonging to test_descr, but introspection and + # comparison on <type 'builtin_function_or_method'> seems not + # to be tested elsewhere + l = [] + self.assertTrue(l.append == l.append) + self.assertFalse(l.append != l.append) + self.assertFalse(l.append == [].append) + self.assertTrue(l.append != [].append) + self.assertFalse(l.append == l.pop) + self.assertTrue(l.append != l.pop) + self.assertNotOrderable(l.append, l.append) + self.assertEqual(l.append.__name__, 'append') + self.assertIs(l.append.__self__, l) + # self.assertIs(l.append.__objclass__, list) --- could be added? + self.assertEqual(l.append.__doc__, list.append.__doc__) + # hash([].append) should not be based on hash([]) + hash(l.append) + + def test_special_unbound_method_types(self): + # Testing objects of <type 'wrapper_descriptor'>... + self.assertTrue(list.__add__ == list.__add__) + self.assertFalse(list.__add__ != list.__add__) + self.assertFalse(list.__add__ == list.__mul__) + self.assertTrue(list.__add__ != list.__mul__) + self.assertNotOrderable(list.__add__, list.__add__) + self.assertEqual(list.__add__.__name__, '__add__') + self.assertIs(list.__add__.__objclass__, list) + + # Testing objects of <type 'method_descriptor'>... + self.assertTrue(list.append == list.append) + self.assertFalse(list.append != list.append) + self.assertFalse(list.append == list.pop) + self.assertTrue(list.append != list.pop) + self.assertNotOrderable(list.append, list.append) + self.assertEqual(list.append.__name__, 'append') + self.assertIs(list.append.__objclass__, list) def test_not_implemented(self): # Testing NotImplemented... |