[pypy-svn] r2744 - pypy/trunk/src/pypy/objspace/std

arigo at codespeak.net arigo at codespeak.net
Thu Jan 8 13:27:13 CET 2004


Author: arigo
Date: Thu Jan  8 13:27:13 2004
New Revision: 2744

Added:
   pypy/trunk/src/pypy/objspace/std/mro.py   (contents, props changed)
Log:
For reference, the MRO algorithm of Python 2.3.


Added: pypy/trunk/src/pypy/objspace/std/mro.py
==============================================================================
--- (empty file)
+++ pypy/trunk/src/pypy/objspace/std/mro.py	Thu Jan  8 13:27:13 2004
@@ -0,0 +1,80 @@
+"""
+For reference, the MRO algorithm of Python 2.3.
+"""
+
+
+def MRO(cls):
+
+    def register(cls):
+        try:
+            blocklist = blocking[cls]
+        except KeyError:
+            blocklist = blocking[cls] = [0]
+            prevlist = blocklist
+            for base in cls.__bases__:
+                prevlist.append(base)
+                prevlist = register(base)
+        blocklist[0] += 1
+        return blocklist
+
+    order = []
+    blocking = {}
+    register(cls)
+    
+    unblock = [cls]
+    while unblock:
+        cls = unblock.pop()
+        blocklist = blocking[cls]
+        assert blocklist[0] > 0
+        blocklist[0] -= 1
+        if blocklist[0] == 0:
+            order.append(cls)
+            unblock += blocklist[:0:-1]
+
+    if len(order) < len(blocking):
+        mro_error(blocking)
+    return order
+
+
+def mro_error(blocking):
+    # look for a cycle
+
+    def find_cycle(cls):
+        path.append(cls)
+        blocklist = blocking[cls]   # raise KeyError when we complete the path
+        if blocklist[0] > 0:
+            del blocking[cls]
+            for cls2 in blocklist[1:]:
+                find_cycle(cls2)
+            blocking[cls] = blocklist
+        del path[-1]
+
+    #import pprint; pprint.pprint(blocking)
+    path = []
+    try:
+        for cls in blocking.keys():
+            find_cycle(cls)
+    except KeyError:
+        i = path.index(path[-1])
+        names = [cls.__name__ for cls in path[i:]]
+        raise TypeError, "Cycle among base classes: " + ' < '.join(names)
+    else:
+        # should not occur
+        raise TypeError, "Cannot create a consistent method resolution order (MRO)"
+
+
+if __name__ == '__main__':
+    class ex_9:
+        class O: pass
+        class A(O): pass
+        class B(O): pass
+        class C(O): pass
+        class D(O): pass
+        class E(O): pass
+        class F(O): pass
+        class K1(A,B,C): pass
+        class K2(D,F,B,E): pass
+        class K3(D,A): pass
+        class Z(K1,K2,F,K3): pass
+
+    print MRO(ex_9.Z)


More information about the Pypy-commit mailing list