summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2018-07-31 06:18:24 (GMT)
committerGitHub <noreply@github.com>2018-07-31 06:18:24 (GMT)
commitac20e0f98d6727ba97a9575bfa2a11b2f6247c35 (patch)
tree3b7938d610796051659b1b6fff27387a731c934c /Lib
parentc48e26dcadbff8620bb5881d3bd148fc8894d0ef (diff)
downloadcpython-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.py38
-rw-r--r--Lib/test/test_descr.py83
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...