[Python-checkins] Exhaustively test dataclass hashing when no hash= value is provided. This is in anticipation of changing how non-default hashing is handled. (GH-5834) (GH-5889)
Eric V. Smith
webhook-mailer at python.org
Sun Feb 25 11:56:33 EST 2018
https://github.com/python/cpython/commit/b6b6669cfd186f3ed1706c6d65ed83c31759a0ea
commit: b6b6669cfd186f3ed1706c6d65ed83c31759a0ea
branch: 3.7
author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com>
committer: Eric V. Smith <ericvsmith at users.noreply.github.com>
date: 2018-02-25T11:56:30-05:00
summary:
Exhaustively test dataclass hashing when no hash= value is provided. This is in anticipation of changing how non-default hashing is handled. (GH-5834) (GH-5889)
(cherry picked from commit 718070db26b35da4aedc03088c58558a833ccf6e)
Co-authored-by: Eric V. Smith <ericvsmith at users.noreply.github.com>
files:
M Lib/test/test_dataclasses.py
diff --git a/Lib/test/test_dataclasses.py b/Lib/test/test_dataclasses.py
index 736bc490867b..9752f5502c7d 100755
--- a/Lib/test/test_dataclasses.py
+++ b/Lib/test/test_dataclasses.py
@@ -2393,6 +2393,79 @@ def __eq__(self, other):
self.assertNotEqual(C(1), C(1))
self.assertEqual(hash(C(1)), hash(C(1.0)))
+ def test_hash_no_args(self):
+ # Test dataclasses with no hash= argument. This exists to
+ # make sure that when hash is changed, the default hashability
+ # keeps working.
+
+ class Base:
+ def __hash__(self):
+ return 301
+
+ # If frozen or eq is None, then use the default value (do not
+ # specify any value in the deecorator).
+ for frozen, eq, base, expected in [
+ (None, None, object, 'unhashable'),
+ (None, None, Base, 'unhashable'),
+ (None, False, object, 'object'),
+ (None, False, Base, 'base'),
+ (None, True, object, 'unhashable'),
+ (None, True, Base, 'unhashable'),
+ (False, None, object, 'unhashable'),
+ (False, None, Base, 'unhashable'),
+ (False, False, object, 'object'),
+ (False, False, Base, 'base'),
+ (False, True, object, 'unhashable'),
+ (False, True, Base, 'unhashable'),
+ (True, None, object, 'tuple'),
+ (True, None, Base, 'tuple'),
+ (True, False, object, 'object'),
+ (True, False, Base, 'base'),
+ (True, True, object, 'tuple'),
+ (True, True, Base, 'tuple'),
+ ]:
+
+ with self.subTest(frozen=frozen, eq=eq, base=base, expected=expected):
+ # First, create the class.
+ if frozen is None and eq is None:
+ @dataclass
+ class C(base):
+ i: int
+ elif frozen is None:
+ @dataclass(eq=eq)
+ class C(base):
+ i: int
+ elif eq is None:
+ @dataclass(frozen=frozen)
+ class C(base):
+ i: int
+ else:
+ @dataclass(frozen=frozen, eq=eq)
+ class C(base):
+ i: int
+
+ # Now, make sure it hashes as expected.
+ if expected == 'unhashable':
+ c = C(10)
+ with self.assertRaisesRegex(TypeError, 'unhashable type'):
+ hash(c)
+
+ elif expected == 'base':
+ self.assertEqual(hash(C(10)), 301)
+
+ elif expected == 'object':
+ # I'm not sure what test to use here. object's
+ # hash isn't based on id(), so calling hash()
+ # won't tell us much. So, just check the function
+ # used is object's.
+ self.assertIs(C.__hash__, object.__hash__)
+
+ elif expected == 'tuple':
+ self.assertEqual(hash(C(42)), hash((42,)))
+
+ else:
+ assert False, f'unknown value for expected={expected!r}'
+
if __name__ == '__main__':
unittest.main()
More information about the Python-checkins
mailing list