summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTim Peters <tim.peters@gmail.com>2001-09-22 06:10:55 (GMT)
committerTim Peters <tim.peters@gmail.com>2001-09-22 06:10:55 (GMT)
commite0b2d7ac9aea548d0bee1cdabd5d7b1254a6569d (patch)
tree277d3df4bdf475df490eb652e387707951c945ab
parentc377b16d12ba325bb108eca575447d66f19294c0 (diff)
downloadcpython-e0b2d7ac9aea548d0bee1cdabd5d7b1254a6569d.zip
cpython-e0b2d7ac9aea548d0bee1cdabd5d7b1254a6569d.tar.gz
cpython-e0b2d7ac9aea548d0bee1cdabd5d7b1254a6569d.tar.bz2
Add a function to compute a class's method resolution order. This is
easy for 2.2 new-style classes, but trickier for classic classes, and different approaches are needed "depending". The function will allow later code to treat all flavors of classes uniformly.
-rw-r--r--Doc/lib/libinspect.tex10
-rw-r--r--Lib/inspect.py18
-rw-r--r--Lib/test/test_inspect.py20
3 files changed, 47 insertions, 1 deletions
diff --git a/Doc/lib/libinspect.tex b/Doc/lib/libinspect.tex
index e5ec9ca..24a181a 100644
--- a/Doc/lib/libinspect.tex
+++ b/Doc/lib/libinspect.tex
@@ -238,7 +238,7 @@ you can expect to find the following special attributes:
\begin{funcdesc}{formatargspec}{args\optional{, varargs, varkw, defaults,
argformat, varargsformat, varkwformat, defaultformat}}
-
+
Format a pretty argument spec from the four values returned by
\function{getargspec()}. The other four arguments are the
corresponding optional formatting functions that are called to turn
@@ -253,6 +253,14 @@ you can expect to find the following special attributes:
names and values into strings.
\end{funcdesc}
+\begin{funcdesc}{getmro}{cls}
+ Return a tuple of class cls's base classes, including cls, in
+ method resolution order. No class appears more than once in this tuple.
+ Note that the method resolution order depends on cls's type. Unless a
+ very peculiar user-defined metatype is in use, cls will be the first
+ element of the tuple.
+\end{funcdesc}
+
\subsection{The interpreter stack
\label{inspect-stack}}
diff --git a/Lib/inspect.py b/Lib/inspect.py
index 1102c3b..3febf18 100644
--- a/Lib/inspect.py
+++ b/Lib/inspect.py
@@ -163,6 +163,24 @@ def getmembers(object, predicate=None):
results.sort()
return results
+# ----------------------------------------------------------- class helpers
+def _searchbases(cls, accum):
+ # Simulate the "classic class" search order.
+ if cls in accum:
+ return
+ accum.append(cls)
+ for base in cls.__bases__:
+ _searchbases(base, accum)
+
+def getmro(cls):
+ "Return tuple of base classes (including cls) in method resolution order."
+ if hasattr(cls, "__mro__"):
+ return cls.__mro__
+ else:
+ result = []
+ _searchbases(cls, result)
+ return tuple(result)
+
# -------------------------------------------------- source code extraction
def indentsize(line):
"""Return the indent size, in spaces, at the start of a line of text."""
diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py
index 130fa8e..dbb6609 100644
--- a/Lib/test/test_inspect.py
+++ b/Lib/test/test_inspect.py
@@ -213,3 +213,23 @@ for fname in files_to_clean_up:
os.unlink(fname)
except:
pass
+
+# Test classic-class method resolution order.
+class A: pass
+class B(A): pass
+class C(A): pass
+class D(B, C): pass
+
+expected = (D, B, A, C)
+got = inspect.getmro(D)
+test(expected == got, "expected %r mro, got %r", expected, got)
+
+# The same w/ new-class MRO.
+class A(object): pass
+class B(A): pass
+class C(A): pass
+class D(B, C): pass
+
+expected = (D, B, C, A, object)
+got = inspect.getmro(D)
+test(expected == got, "expected %r mro, got %r", expected, got)