[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