]> granicus.if.org Git - python/commitdiff
Add a function to compute a class's method resolution order. This is
authorTim Peters <tim.peters@gmail.com>
Sat, 22 Sep 2001 06:10:55 +0000 (06:10 +0000)
committerTim Peters <tim.peters@gmail.com>
Sat, 22 Sep 2001 06:10:55 +0000 (06:10 +0000)
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.

Doc/lib/libinspect.tex
Lib/inspect.py
Lib/test/test_inspect.py

index e5ec9ca6204fd18719250b5aa508a38ee7211b9a..24a181a7a39710f6405f3f2879de65fedc70d22e 100644 (file)
@@ -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}}
 
index 1102c3b2580909cbd078a859287b475dbdecf773..3febf1826d19b59a84185bda767cde38e1591446 100644 (file)
@@ -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."""
index 130fa8ef7350b5c243e2a34e0d66d5ddb87b1c09..dbb66094e9ea5ca81fd2e805fbfc0ae0e0261a26 100644 (file)
@@ -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)