From cc7ebb8f69b84bc48ab2bcccf4f7a30f5e7479d2 Mon Sep 17 00:00:00 2001 From: Michael Foord Date: Sat, 20 Nov 2010 16:20:16 +0000 Subject: Issue 9732: remove use of __class__ in inspect.getattr_static and note the mro exception to code execution --- Doc/library/inspect.rst | 8 +++++--- Lib/inspect.py | 2 +- Lib/test/test_inspect.py | 12 ++++++++++++ 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst index 2f09348..32e56e5 100644 --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -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 attached to the instance, or any other monkeying with `__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` +.. 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 getset descriptors on objects implemented in C). The descriptor is returned instead of the underlying attribute. diff --git a/Lib/inspect.py b/Lib/inspect.py index 57d8c72..97e99aa 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -1092,7 +1092,7 @@ def getattr_static(obj, attr, default=_sentinel): instance_result = _sentinel if not isinstance(obj, type): instance_result = _check_instance(obj, attr) - klass = obj.__class__ + klass = type(obj) else: klass = obj diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py index 88c57d3..e320c68 100644 --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -855,6 +855,18 @@ class TestGetattrStatic(unittest.TestCase): 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(): run_unittest( TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases, -- cgit v0.12