mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 21:51:50 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			145 lines
		
	
	
	
		
			5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			145 lines
		
	
	
	
		
			5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| from test.test_json import PyTest
 | |
| import pickle
 | |
| import sys
 | |
| import unittest
 | |
| 
 | |
| kepler_dict = {
 | |
|     "orbital_period": {
 | |
|         "mercury": 88,
 | |
|         "venus": 225,
 | |
|         "earth": 365,
 | |
|         "mars": 687,
 | |
|         "jupiter": 4331,
 | |
|         "saturn": 10_756,
 | |
|         "uranus": 30_687,
 | |
|         "neptune": 60_190,
 | |
|     },
 | |
|     "dist_from_sun": {
 | |
|         "mercury": 58,
 | |
|         "venus": 108,
 | |
|         "earth": 150,
 | |
|         "mars": 228,
 | |
|         "jupiter": 778,
 | |
|         "saturn": 1_400,
 | |
|         "uranus": 2_900,
 | |
|         "neptune": 4_500,
 | |
|     }
 | |
| }
 | |
| 
 | |
| class TestAttrDict(PyTest):
 | |
| 
 | |
|     def test_dict_subclass(self):
 | |
|         self.assertTrue(issubclass(self.AttrDict, dict))
 | |
| 
 | |
|     def test_slots(self):
 | |
|         d = self.AttrDict(x=1, y=2)
 | |
|         with self.assertRaises(TypeError):
 | |
|             vars(d)
 | |
| 
 | |
|     def test_constructor_signatures(self):
 | |
|         AttrDict = self.AttrDict
 | |
|         target = dict(x=1, y=2)
 | |
|         self.assertEqual(AttrDict(x=1, y=2), target)                   # kwargs
 | |
|         self.assertEqual(AttrDict(dict(x=1, y=2)), target)             # mapping
 | |
|         self.assertEqual(AttrDict(dict(x=1, y=0), y=2), target)        # mapping, kwargs
 | |
|         self.assertEqual(AttrDict([('x', 1), ('y', 2)]), target)       # iterable
 | |
|         self.assertEqual(AttrDict([('x', 1), ('y', 0)], y=2), target)  # iterable, kwargs
 | |
| 
 | |
|     def test_getattr(self):
 | |
|         d = self.AttrDict(x=1, y=2)
 | |
|         self.assertEqual(d.x, 1)
 | |
|         with self.assertRaises(AttributeError):
 | |
|             d.z
 | |
| 
 | |
|     def test_setattr(self):
 | |
|         d = self.AttrDict(x=1, y=2)
 | |
|         d.x = 3
 | |
|         d.z = 5
 | |
|         self.assertEqual(d, dict(x=3, y=2, z=5))
 | |
| 
 | |
|     def test_delattr(self):
 | |
|         d = self.AttrDict(x=1, y=2)
 | |
|         del d.x
 | |
|         self.assertEqual(d, dict(y=2))
 | |
|         with self.assertRaises(AttributeError):
 | |
|             del d.z
 | |
| 
 | |
|     def test_dir(self):
 | |
|         d = self.AttrDict(x=1, y=2)
 | |
|         self.assertTrue(set(dir(d)), set(dir(dict)).union({'x', 'y'}))
 | |
| 
 | |
|     def test_repr(self):
 | |
|         # This repr is doesn't round-trip.  It matches a regular dict.
 | |
|         # That seems to be the norm for AttrDict recipes being used
 | |
|         # in the wild.  Also it supports the design concept that an
 | |
|         # AttrDict is just like a regular dict but has optional
 | |
|         # attribute style lookup.
 | |
|         self.assertEqual(repr(self.AttrDict(x=1, y=2)),
 | |
|                          repr(dict(x=1, y=2)))
 | |
| 
 | |
|     def test_overlapping_keys_and_methods(self):
 | |
|         d = self.AttrDict(items=50)
 | |
|         self.assertEqual(d['items'], 50)
 | |
|         self.assertEqual(d.items(), dict(d).items())
 | |
| 
 | |
|     def test_invalid_attribute_names(self):
 | |
|         d = self.AttrDict({
 | |
|             'control': 'normal case',
 | |
|             'class': 'keyword',
 | |
|             'two words': 'contains space',
 | |
|             'hypen-ate': 'contains a hyphen'
 | |
|         })
 | |
|         self.assertEqual(d.control, dict(d)['control'])
 | |
|         self.assertEqual(d['class'], dict(d)['class'])
 | |
|         self.assertEqual(d['two words'], dict(d)['two words'])
 | |
|         self.assertEqual(d['hypen-ate'], dict(d)['hypen-ate'])
 | |
| 
 | |
|     def test_object_hook_use_case(self):
 | |
|         AttrDict = self.AttrDict
 | |
|         json_string = self.dumps(kepler_dict)
 | |
|         kepler_ad = self.loads(json_string, object_hook=AttrDict)
 | |
| 
 | |
|         self.assertEqual(kepler_ad, kepler_dict)     # Match regular dict
 | |
|         self.assertIsInstance(kepler_ad, AttrDict)   # Verify conversion
 | |
|         self.assertIsInstance(kepler_ad.orbital_period, AttrDict)  # Nested
 | |
| 
 | |
|         # Exercise dotted lookups
 | |
|         self.assertEqual(kepler_ad.orbital_period, kepler_dict['orbital_period'])
 | |
|         self.assertEqual(kepler_ad.orbital_period.earth,
 | |
|                          kepler_dict['orbital_period']['earth'])
 | |
|         self.assertEqual(kepler_ad['orbital_period'].earth,
 | |
|                          kepler_dict['orbital_period']['earth'])
 | |
| 
 | |
|         # Dict style error handling and Attribute style error handling
 | |
|         with self.assertRaises(KeyError):
 | |
|             kepler_ad.orbital_period['pluto']
 | |
|         with self.assertRaises(AttributeError):
 | |
|             kepler_ad.orbital_period.Pluto
 | |
| 
 | |
|         # Order preservation
 | |
|         self.assertEqual(list(kepler_ad.items()), list(kepler_dict.items()))
 | |
|         self.assertEqual(list(kepler_ad.orbital_period.items()),
 | |
|                              list(kepler_dict['orbital_period'].items()))
 | |
| 
 | |
|         # Round trip
 | |
|         self.assertEqual(self.dumps(kepler_ad), json_string)
 | |
| 
 | |
|     def test_pickle(self):
 | |
|         AttrDict = self.AttrDict
 | |
|         json_string = self.dumps(kepler_dict)
 | |
|         kepler_ad = self.loads(json_string, object_hook=AttrDict)
 | |
| 
 | |
|         # Pickling requires the cached module to be the real module
 | |
|         cached_module = sys.modules.get('json')
 | |
|         sys.modules['json'] = self.json
 | |
|         try:
 | |
|             for protocol in range(pickle.HIGHEST_PROTOCOL + 1):
 | |
|                 kepler_ad2 = pickle.loads(pickle.dumps(kepler_ad, protocol))
 | |
|                 self.assertEqual(kepler_ad2, kepler_ad)
 | |
|                 self.assertEqual(type(kepler_ad2), AttrDict)
 | |
|         finally:
 | |
|             sys.modules['json'] = cached_module
 | |
| 
 | |
| 
 | |
| if __name__ == "__main__":
 | |
|     unittest.main()
 | 
