[z3-checkins] r5148 - z3/Five/trunk

faassen at codespeak.net faassen at codespeak.net
Thu Jun 17 19:00:19 MEST 2004


Author: faassen
Date: Thu Jun 17 19:00:18 2004
New Revision: 5148

Added:
   z3/Five/trunk/metaclass.py
Modified:
   z3/Five/trunk/LICENSES.txt
Log:
Add metaclass.py which does deep magic which I do not pretend to understand.
It seems to be making things work together a bit more peacefully,
however. Taken from PEAK.


Modified: z3/Five/trunk/LICENSES.txt
==============================================================================
--- z3/Five/trunk/LICENSES.txt	(original)
+++ z3/Five/trunk/LICENSES.txt	Thu Jun 17 19:00:18 2004
@@ -16,7 +16,8 @@
 FOR A PARTICULAR PURPOSE.
 """
 
+metaclass.py is derived from PEAK, copyright (C) 1996-2004 by Phillip
+J. Eby and Tyler C. Sarna. PEAK may be used under the same terms as Zope.
+
 The rest of the software falls under the BSD license and is copyright
 Infrae. This license is listed in BSD.txt.
-
-

Added: z3/Five/trunk/metaclass.py
==============================================================================
--- (empty file)
+++ z3/Five/trunk/metaclass.py	Thu Jun 17 19:00:18 2004
@@ -0,0 +1,93 @@
+# metaclass taken from PEAK.
+# Martijn doesn't pretend to understand this.
+from weakref import WeakValueDictionary
+from types import ClassType
+
+def makeClass(name,bases,dict):
+    """makeClass(name, bases, dict) - enhanced class creation
+    """
+
+    # Create either a "classic" Python class, an ExtensionClass, or a new-style
+    # class with autogenerated metaclass, based on the nature of the base
+    # classes involved
+
+    name = str(name)  # De-unicode
+
+    metaclasses = [getattr(b,'__class__',type(b)) for b in bases]
+
+    if dict.has_key('__metaclass__'):
+        metaclasses.insert(0,dict['__metaclass__'])
+
+    if dict.has_key('__metaclasses__'):
+        metaclasses[0:0] = list(dict['__metaclasses__'])
+
+    metaclasses = normalizeBases(metaclasses)
+
+    if metaclasses:
+
+        # If we have metaclasses, it's not a classic class, so derive a
+        # single metaclass, and ask it to create the class.
+
+        if len(metaclasses)==1:
+            metaclass = metaclasses[0]
+        else:
+            metaclass = derivedMeta(metaclasses)
+
+        return metaclass(name,bases,dict)
+
+    # No metaclasses, it's a classic class, so use 'new.classobj'
+
+    from new import classobj; return classobj(name,bases,dict)
+
+def normalizeBases(allBases):
+    return minimalBases([b for b in allBases if b is not makeClass])
+
+def minimalBases(classes):
+    """Reduce a list of base classes to its ordered minimum equivalent"""
+
+    classes = [c for c in classes if c is not ClassType]
+    candidates = []
+
+    for m in classes:
+        for n in classes:
+            if issubclass(n,m) and m is not n:
+                break
+        else:
+            # m has no subclasses in 'classes'
+            if m in candidates:
+                candidates.remove(m)    # ensure that we're later in the list
+            candidates.append(m)
+
+    return candidates
+
+metaReg = WeakValueDictionary()
+
+def derivedMeta(metaclasses):
+    metaclasses = tuple(metaclasses)
+    derived = metaReg.get(metaclasses)
+
+    if derived is None:
+        normalized = tuple(normalizeBases(metaclasses))
+        derived = metaReg.get(normalized)
+
+        if derived is None:
+            if len(normalized)==1:
+                derived = normalized[0]
+            else:
+                derived = metaFromBases(normalized)(
+                    '_'.join([n.__name__ for n in normalized]),
+                    metaclasses, {}
+                )
+            try: metaReg[normalized] = derived
+            except TypeError: pass  # Some metatypes can't be weakref'd
+
+        try: metaReg[metaclasses] = derived
+        except TypeError: pass
+
+    return derived
+
+def metaFromBases(bases):
+    meta = tuple([getattr(b,'__class__',type(b)) for b in bases])
+    if meta==bases: raise TypeError("Incompatible root metatypes",bases)
+    return derivedMeta(meta)
+


More information about the z3-checkins mailing list