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.
This commit is contained in:
Serhiy Storchaka 2018-07-31 09:18:24 +03:00 committed by GitHub
parent c48e26dcad
commit ac20e0f98d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 112 additions and 73 deletions

View file

@ -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...