Commit b0583ad2 authored by Michael Foord's avatar Michael Foord

Issue 9732: remove use of __class__ in inspect.getattr_static and note the mro...

Issue 9732: remove use of __class__ in inspect.getattr_static and note the mro exception to code execution
parent 84f50960
...@@ -598,11 +598,13 @@ any of these then you deserve to have everything break anyway): ...@@ -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.
......
...@@ -1092,7 +1092,7 @@ def getattr_static(obj, attr, default=_sentinel): ...@@ -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
......
...@@ -855,6 +855,18 @@ class TestGetattrStatic(unittest.TestCase): ...@@ -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,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment