Issue 9732: remove use of __class__ in inspect.getattr_static and note the mro exception to code execution

This commit is contained in:
Michael Foord 2010-11-20 16:20:16 +00:00
parent 45ec426157
commit cc7ebb8f69
3 changed files with 18 additions and 4 deletions

View File

@ -598,11 +598,13 @@ any of these then you deserve to have everything break anyway):
member deleted from the class, or a fake `__slots__` attribute member deleted from the class, or a fake `__slots__` attribute
attached to the instance, or any other monkeying with attached to the instance, or any other monkeying with
`__slots__` `__slots__`
* objects that lie about their type by having `__class__` as a
descriptor (`getattr_static` traverses the :term:`MRO` of whatever type
`obj.__class__` returns instead of the real type)
* type objects that lie about their :term:`MRO` * type objects that lie about their :term:`MRO`
.. note::
Classes that override :data:`~object.__mro__` as a property will have this
code executed by `getattr_static`.
Descriptors are not resolved (for example slot descriptors or Descriptors are not resolved (for example slot descriptors or
getset descriptors on objects implemented in C). The descriptor getset descriptors on objects implemented in C). The descriptor
is returned instead of the underlying attribute. is returned instead of the underlying attribute.

View File

@ -1092,7 +1092,7 @@ def getattr_static(obj, attr, default=_sentinel):
instance_result = _sentinel instance_result = _sentinel
if not isinstance(obj, type): if not isinstance(obj, type):
instance_result = _check_instance(obj, attr) instance_result = _check_instance(obj, attr)
klass = obj.__class__ klass = type(obj)
else: else:
klass = obj klass = obj

View File

@ -855,6 +855,18 @@ class TestGetattrStatic(unittest.TestCase):
self.assertEqual(inspect.getattr_static(Thing, 'd'), meta.__dict__['d']) self.assertEqual(inspect.getattr_static(Thing, 'd'), meta.__dict__['d'])
def test_class_as_property(self):
class Base(object):
foo = 3
class Something(Base):
@property
def __class__(self):
return object
self.assertEqual(inspect.getattr_static(Something(), 'foo'), 3)
self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
def test_main(): def test_main():
run_unittest( run_unittest(
TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases, TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,