mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	Issue 9732: addition of getattr_static to the inspect module
This commit is contained in:
		
							parent
							
								
									89197fe93c
								
							
						
					
					
						commit
						95fc51dfda
					
				
					 6 changed files with 295 additions and 2 deletions
				
			
		|  | @ -706,12 +706,162 @@ def _getAssertEqualParams(self, func, call_params_string, locs=None): | |||
|         locs = dict(locs or {}, inst=self.inst) | ||||
|         return (func, 'inst,' + call_params_string, locs) | ||||
| 
 | ||||
| 
 | ||||
| class TestGetattrStatic(unittest.TestCase): | ||||
| 
 | ||||
|     def test_basic(self): | ||||
|         class Thing(object): | ||||
|             x = object() | ||||
| 
 | ||||
|         thing = Thing() | ||||
|         self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x) | ||||
|         self.assertEqual(inspect.getattr_static(thing, 'x', None), Thing.x) | ||||
|         with self.assertRaises(AttributeError): | ||||
|             inspect.getattr_static(thing, 'y') | ||||
| 
 | ||||
|         self.assertEqual(inspect.getattr_static(thing, 'y', 3), 3) | ||||
| 
 | ||||
|     def test_inherited(self): | ||||
|         class Thing(object): | ||||
|             x = object() | ||||
|         class OtherThing(Thing): | ||||
|             pass | ||||
| 
 | ||||
|         something = OtherThing() | ||||
|         self.assertEqual(inspect.getattr_static(something, 'x'), Thing.x) | ||||
| 
 | ||||
|     def test_instance_attr(self): | ||||
|         class Thing(object): | ||||
|             x = 2 | ||||
|             def __init__(self, x): | ||||
|                 self.x = x | ||||
|         thing = Thing(3) | ||||
|         self.assertEqual(inspect.getattr_static(thing, 'x'), 3) | ||||
|         del thing.x | ||||
|         self.assertEqual(inspect.getattr_static(thing, 'x'), 2) | ||||
| 
 | ||||
|     def test_property(self): | ||||
|         class Thing(object): | ||||
|             @property | ||||
|             def x(self): | ||||
|                 raise AttributeError("I'm pretending not to exist") | ||||
|         thing = Thing() | ||||
|         self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x) | ||||
| 
 | ||||
|     def test_descriptor(self): | ||||
|         class descriptor(object): | ||||
|             def __get__(*_): | ||||
|                 raise AttributeError("I'm pretending not to exist") | ||||
|         desc = descriptor() | ||||
|         class Thing(object): | ||||
|             x = desc | ||||
|         thing = Thing() | ||||
|         self.assertEqual(inspect.getattr_static(thing, 'x'), desc) | ||||
| 
 | ||||
|     def test_classAttribute(self): | ||||
|         class Thing(object): | ||||
|             x = object() | ||||
| 
 | ||||
|         self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.x) | ||||
| 
 | ||||
|     def test_inherited_classattribute(self): | ||||
|         class Thing(object): | ||||
|             x = object() | ||||
|         class OtherThing(Thing): | ||||
|             pass | ||||
| 
 | ||||
|         self.assertEqual(inspect.getattr_static(OtherThing, 'x'), Thing.x) | ||||
| 
 | ||||
|     def test_slots(self): | ||||
|         class Thing(object): | ||||
|             y = 'bar' | ||||
|             __slots__ = ['x'] | ||||
|             def __init__(self): | ||||
|                 self.x = 'foo' | ||||
|         thing = Thing() | ||||
|         self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x) | ||||
|         self.assertEqual(inspect.getattr_static(thing, 'y'), 'bar') | ||||
| 
 | ||||
|         del thing.x | ||||
|         self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x) | ||||
| 
 | ||||
|     def test_metaclass(self): | ||||
|         class meta(type): | ||||
|             attr = 'foo' | ||||
|         class Thing(object, metaclass=meta): | ||||
|             pass | ||||
|         self.assertEqual(inspect.getattr_static(Thing, 'attr'), 'foo') | ||||
| 
 | ||||
|         class sub(meta): | ||||
|             pass | ||||
|         class OtherThing(object, metaclass=sub): | ||||
|             x = 3 | ||||
|         self.assertEqual(inspect.getattr_static(OtherThing, 'attr'), 'foo') | ||||
| 
 | ||||
|         class OtherOtherThing(OtherThing): | ||||
|             pass | ||||
|         # this test is odd, but it was added as it exposed a bug | ||||
|         self.assertEqual(inspect.getattr_static(OtherOtherThing, 'x'), 3) | ||||
| 
 | ||||
|     def test_no_dict_no_slots(self): | ||||
|         self.assertEqual(inspect.getattr_static(1, 'foo', None), None) | ||||
|         self.assertNotEqual(inspect.getattr_static('foo', 'lower'), None) | ||||
| 
 | ||||
|     def test_no_dict_no_slots_instance_member(self): | ||||
|         # returns descriptor | ||||
|         with open(__file__) as handle: | ||||
|             self.assertEqual(inspect.getattr_static(handle, 'name'), type(handle).name) | ||||
| 
 | ||||
|     def test_inherited_slots(self): | ||||
|         # returns descriptor | ||||
|         class Thing(object): | ||||
|             __slots__ = ['x'] | ||||
|             def __init__(self): | ||||
|                 self.x = 'foo' | ||||
| 
 | ||||
|         class OtherThing(Thing): | ||||
|             pass | ||||
|         # it would be nice if this worked... | ||||
|         # we get the descriptor instead of the instance attribute | ||||
|         self.assertEqual(inspect.getattr_static(OtherThing(), 'x'), Thing.x) | ||||
| 
 | ||||
|     def test_descriptor(self): | ||||
|         class descriptor(object): | ||||
|             def __get__(self, instance, owner): | ||||
|                 return 3 | ||||
|         class Foo(object): | ||||
|             d = descriptor() | ||||
| 
 | ||||
|         foo = Foo() | ||||
| 
 | ||||
|         # for a non data descriptor we return the instance attribute | ||||
|         foo.__dict__['d'] = 1 | ||||
|         self.assertEqual(inspect.getattr_static(foo, 'd'), 1) | ||||
| 
 | ||||
|         # if the descriptor is a data-desciptor we should return the | ||||
|         # descriptor | ||||
|         descriptor.__set__ = lambda s, i, v: None | ||||
|         self.assertEqual(inspect.getattr_static(foo, 'd'), Foo.__dict__['d']) | ||||
| 
 | ||||
| 
 | ||||
|     def test_metaclass_with_descriptor(self): | ||||
|         class descriptor(object): | ||||
|             def __get__(self, instance, owner): | ||||
|                 return 3 | ||||
|         class meta(type): | ||||
|             d = descriptor() | ||||
|         class Thing(object, metaclass=meta): | ||||
|             pass | ||||
|         self.assertEqual(inspect.getattr_static(Thing, 'd'), meta.__dict__['d']) | ||||
| 
 | ||||
| 
 | ||||
| def test_main(): | ||||
|     run_unittest( | ||||
|         TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases, | ||||
|         TestInterpreterStack, TestClassesAndFunctions, TestPredicates, | ||||
|         TestGetcallargsFunctions, TestGetcallargsMethods, | ||||
|         TestGetcallargsUnboundMethods) | ||||
|         TestGetcallargsUnboundMethods, TestGetattrStatic | ||||
|     ) | ||||
| 
 | ||||
| if __name__ == "__main__": | ||||
|     test_main() | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Michael Foord
						Michael Foord