summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Foord <fuzzyman@voidspace.org.uk>2010-11-20 16:40:44 (GMT)
committerMichael Foord <fuzzyman@voidspace.org.uk>2010-11-20 16:40:44 (GMT)
commite516265bbc75e4bb7fc2ab6eaeb7ad3aef86a938 (patch)
tree0436a95d2a4ca7b01c238eb6df780798388321df
parent6bb9989ae38cd2610e661d6e8899ef58dd9562e3 (diff)
downloadcpython-e516265bbc75e4bb7fc2ab6eaeb7ad3aef86a938.zip
cpython-e516265bbc75e4bb7fc2ab6eaeb7ad3aef86a938.tar.gz
cpython-e516265bbc75e4bb7fc2ab6eaeb7ad3aef86a938.tar.bz2
Issue 9732: fetch the method resolution order from the type metaclass directly in getattr_static
-rw-r--r--Doc/library/inspect.rst28
-rw-r--r--Lib/inspect.py7
-rw-r--r--Lib/test/test_inspect.py16
3 files changed, 29 insertions, 22 deletions
diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst
index 32e56e5..9a068da 100644
--- a/Doc/library/inspect.rst
+++ b/Doc/library/inspect.rst
@@ -587,26 +587,14 @@ but avoids executing code when it fetches attributes.
that raise AttributeError). It can also return descriptors objects
instead of instance members.
-There are several cases that will break `getattr_static` or be handled
-incorrectly. These are pathological enough not to worry about (i.e. if you do
-any of these then you deserve to have everything break anyway):
-
-* :data:`~object.__dict__` existing (e.g. as a property) but returning the
- wrong dictionary or even returning something other than a
- dictionary
-* classes created with :data:`~object.__slots__` that have the `__slots__`
- member deleted from the class, or a fake `__slots__` attribute
- attached to the instance, or any other monkeying with
- `__slots__`
-* 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
+The only known case that can cause `getattr_static` to trigger code execution,
+and cause it to return incorrect results (or even break), is where a class uses
+:data:`~object.__slots__` and provides a `__dict__` member using a property or
+descriptor. If you find other cases please report them so they can be fixed
+or documented.
+
+`getattr_static` does not resolve descriptors, for example slot descriptors or
+getset descriptors on objects implemented in C. The descriptor object
is returned instead of the underlying attribute.
You can handle these with code like the following. Note that
diff --git a/Lib/inspect.py b/Lib/inspect.py
index 97e99aa..2f05829 100644
--- a/Lib/inspect.py
+++ b/Lib/inspect.py
@@ -1060,6 +1060,9 @@ def trace(context=1):
_sentinel = object()
+def _static_getmro(klass):
+ return type.__dict__['__mro__'].__get__(klass)
+
def _check_instance(obj, attr):
instance_dict = {}
try:
@@ -1070,7 +1073,7 @@ def _check_instance(obj, attr):
def _check_class(klass, attr):
- for entry in getmro(klass):
+ for entry in _static_getmro(klass):
try:
return entry.__dict__[attr]
except KeyError:
@@ -1110,7 +1113,7 @@ def getattr_static(obj, attr, default=_sentinel):
if obj is klass:
# for types we check the metaclass too
- for entry in getmro(type(klass)):
+ for entry in _static_getmro(type(klass)):
try:
return entry.__dict__[attr]
except KeyError:
diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py
index e320c68..b3e131c 100644
--- a/Lib/test/test_inspect.py
+++ b/Lib/test/test_inspect.py
@@ -867,6 +867,22 @@ class TestGetattrStatic(unittest.TestCase):
self.assertEqual(inspect.getattr_static(Something(), 'foo'), 3)
self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
+ def test_mro_as_property(self):
+ class Meta(type):
+ @property
+ def __mro__(self):
+ return (object,)
+
+ class Base(object):
+ foo = 3
+
+ class Something(Base, metaclass=Meta):
+ pass
+
+ 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,