mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	Exhaustively test dataclass hashing when no hash= value is provided. This is in anticipation of changing how non-default hashing is handled. (#5834)
This commit is contained in:
		
							parent
							
								
									98f42aac23
								
							
						
					
					
						commit
						718070db26
					
				
					 1 changed files with 73 additions and 0 deletions
				
			
		|  | @ -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() | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Eric V. Smith
						Eric V. Smith