Examples of metaprogramming in pure Python.
diff --git a/Demo/metaclasses/Enum.py b/Demo/metaclasses/Enum.py
new file mode 100644
index 0000000..71a8e52
--- /dev/null
+++ b/Demo/metaclasses/Enum.py
@@ -0,0 +1,165 @@
+"""Enumeration metaclass."""
+
+import string
+
+class EnumMetaClass:
+    """Metaclass for enumeration.
+
+    To define your own enumeration, do something like
+
+    class Color(Enum):
+	red = 1
+	green = 2
+	blue = 3
+
+    Now, Color.red, Color.green and Color.blue behave totally
+    different: they are enumerated values, not integers.
+
+    Enumerations cannot be instantiated; however they can be
+    subclassed.
+
+    """
+
+    def __init__(self, name, bases, dict):
+	"""Constructor -- create an enumeration.
+
+	Called at the end of the class statement.  The arguments are
+	the name of the new class, a tuple containing the base
+	classes, and a dictionary containing everything that was
+	entered in the class' namespace during execution of the class
+	statement.  In the above example, it would be {'red': 1,
+	'green': 2, 'blue': 3}.
+
+	"""
+	for base in bases:
+	    if base.__class__ is not EnumMetaClass:
+		raise TypeError, "Enumeration base class must be enumeration"
+	bases = filter(lambda x: x is not Enum, bases)
+	self.__name__ = name
+	self.__bases__ = bases
+	self.__dict = {}
+	for key, value in dict.items():
+	    self.__dict[key] = EnumInstance(name, key, value)
+
+    def __getattr__(self, name):
+	"""Return an enumeration value.
+
+	For example, Color.red returns the value corresponding to red.
+
+	XXX Perhaps the values should be created in the constructor?
+
+	This looks in the class dictionary and if it is not found
+	there asks the base classes.
+
+	The special attribute __members__ returns the list of names
+	defined in this class (it does not merge in the names defined
+	in base classes).
+
+	"""
+	if name == '__members__':
+	    return self.__dict.keys()
+
+	try:
+	    return self.__dict[name]
+	except KeyError:
+	    for base in self.__bases__:
+		try:
+		    return getattr(base, name)
+		except AttributeError:
+		    continue
+
+	raise AttributeError, name
+
+    def __repr__(self):
+	s = self.__name__
+	if self.__bases__:
+	    s = s + '(' + string.join(map(lambda x: x.__name__,
+					  self.__bases__), ", ") + ')'
+	if self.__dict:
+	    list = []
+	    for key, value in self.__dict.items():
+		list.append("%s: %s" % (key, int(value)))
+	    s = "%s: {%s}" % (s, string.join(list, ", "))
+	return s
+
+
+class EnumInstance:
+    """Class to represent an enumeration value.
+
+    EnumInstance('Color', 'red', 12) prints as 'Color.red' and behaves
+    like the integer 12 when compared, but doesn't support arithmetic.
+
+    XXX Should it record the actual enumeration rather than just its
+    name?
+
+    """
+
+    def __init__(self, classname, enumname, value):
+	self.__classname = classname
+	self.__enumname = enumname
+	self.__value = value
+
+    def __int__(self):
+	return self.__value
+
+    def __repr__(self):
+	return "EnumInstance(%s, %s, %s)" % (`self.__classname`,
+					     `self.__enumname`,
+					     `self.__value`)
+
+    def __str__(self):
+	return "%s.%s" % (self.__classname, self.__enumname)
+
+    def __cmp__(self, other):
+	return cmp(self.__value, int(other))
+
+
+# Create the base class for enumerations.
+# It is an empty enumeration.
+Enum = EnumMetaClass("Enum", (), {})
+
+
+def _test():
+
+    class Color(Enum):
+	red = 1
+	green = 2
+	blue = 3
+
+    print Color.red
+    print dir(Color)
+
+    print Color.red == Color.red
+    print Color.red == Color.blue
+    print Color.red == 1
+    print Color.red == 2
+
+    class ExtendedColor(Color):
+	white = 0
+	orange = 4
+	yellow = 5
+	purple = 6
+	black = 7
+
+    print ExtendedColor.orange
+    print ExtendedColor.red
+
+    print Color.red == ExtendedColor.red
+
+    class OtherColor(Enum):
+	white = 4
+	blue = 5
+
+    class MergedColor(Color, OtherColor):
+	pass
+
+    print MergedColor.red
+    print MergedColor.white
+
+    print Color
+    print ExtendedColor
+    print OtherColor
+    print MergedColor
+
+if __name__ == '__main__':
+    _test()
diff --git a/Demo/metaclasses/Trace.py b/Demo/metaclasses/Trace.py
new file mode 100644
index 0000000..ed3944f
--- /dev/null
+++ b/Demo/metaclasses/Trace.py
@@ -0,0 +1,126 @@
+"""Tracing metaclass."""
+
+import types
+
+class TraceMetaClass:
+    """Metaclass for tracing.
+
+    Classes defined using this metaclass have an automatic tracing
+    feature -- by setting the __trace_output__ instance (or class)
+    variable to a file object, trace messages about all calls are
+    written to the file.  The trace formatting can be changed by
+    defining a suitable __trace_call__ method.
+
+    """
+
+    __inited = 0
+
+    def __init__(self, name, bases, dict):
+	self.__name__ = name
+	self.__bases__ = bases
+	self.__dict = dict
+	# XXX Can't define __dict__, alas
+	self.__inited = 1
+
+    def __getattr__(self, name):
+	try:
+	    return self.__dict[name]
+	except KeyError:
+	    for base in self.__bases__:
+		try:
+		    return getattr(base, name)
+		except AttributeError:
+		    pass
+	    raise AttributeError, name
+
+    def __setattr__(self, name, value):
+	if not self.__inited:
+	    self.__dict__[name] = value
+	else:
+	    self.__dict[name] = value
+
+    def __call__(self, *args, **kw):
+	inst = TracingInstance()
+	inst.__meta_init__(self)
+	try:
+	    init = inst.__getattr__('__init__')
+	except AttributeError:
+	    init = lambda: None
+	apply(init, args, kw)
+	return inst
+
+    __trace_output__ = None
+
+class TracingInstance:
+    """Helper class to represent an instance of a tracing class."""
+
+    def __trace_call__(self, fp, fmt, *args):
+	fp.write((fmt+'\n') % args)
+
+    def __meta_init__(self, klass):
+	self.__class = klass
+
+    def __getattr__(self, name):
+	# Invoked for any attr not in the instance's __dict__
+	try:
+	    raw = self.__class.__getattr__(name)
+	except AttributeError:
+	    raise AttributeError, name
+	if type(raw) != types.FunctionType:
+	    return raw
+	# It's a function
+	fullname = self.__class.__name__ + "." + name
+	if not self.__trace_output__ or name == '__trace_call__':
+	    return NotTracingWrapper(fullname, raw, self)
+	else:
+	    return TracingWrapper(fullname, raw, self)
+
+class NotTracingWrapper:
+    def __init__(self, name, func, inst):
+	self.__name__ = name
+	self.func = func
+	self.inst = inst
+    def __call__(self, *args, **kw):
+	return apply(self.func, (self.inst,) + args, kw)
+
+class TracingWrapper(NotTracingWrapper):
+    def __call__(self, *args, **kw):
+	self.inst.__trace_call__(self.inst.__trace_output__,
+				 "calling %s, inst=%s, args=%s, kw=%s",
+				 self.__name__, self.inst, args, kw)
+	try:
+	    rv = apply(self.func, (self.inst,) + args, kw)
+	except:
+	    t, v, tb = sys.exc_info()
+	    self.inst.__trace_call__(self.inst.__trace_output__,
+				     "returning from %s with exception %s: %s",
+				     self.__name__, t, v)
+	    raise t, v, tb
+	else:
+	    self.inst.__trace_call__(self.inst.__trace_output__,
+				     "returning from %s with value %s",
+				     self.__name__, rv)
+	    return rv
+
+Traced = TraceMetaClass('Traced', (), {'__trace_output__': None})
+
+
+def _test():
+    import sys
+    class C(Traced):
+	def __init__(self, x=0): self.x = x
+	def m1(self, x): self.x = x
+	def m2(self, y): return self.x + y
+    C.__trace_output__ = sys.stdout
+    x = C(4321)
+    print x
+    print x.x
+    print x.m1(100)
+    print x.m1(10)
+    print x.m2(33)
+    print x.m1(5)
+    print x.m2(4000)
+    print x.x
+
+if __name__ == '__main__':
+    _test()