Decorator metaclass

thomas.karolski at googlemail.com thomas.karolski at googlemail.com
Thu May 22 22:28:22 EDT 2008


Hi,
I would like to create a Decorator metaclass, which automatically
turns a class which inherits from the "Decorator" type into a
decorator.
A decorator in this case, is simply a class which has all of its
decorator implementation inside a decorator() method. Every other
attribute access is being proxied to decorator().getParent().

Here's my attempt:
-------------------------------------------------------
from new import classobj

class DecoratorType(type):
	def __new__(cls, name, bases, dct):
		dct2 = {}
		for key, val in dct.iteritems():
			dct2[key] = val

		# create a new class which will store all of the implementation
		impl = classobj('%sImpl'%name,(),dct2)

		# update the old class to implement this implementation
		def __init__(self, *args, **dargs):
			object.__setattr__(self, '__impl', impl(*args, **dargs))
		def decorator(self):
			return object.__getattribute__(self,'__impl')
		def __getattribute__(self, attr):
			if attr=="decorator":
				return object.__getattribute__(self,'decorator')
			return getattr(object.__getattribute__(self, 'decorator')
().getParent(), attr)
		dct = {}
		dct['__init__'] = __init__
		dct['decorator'] = decorator
		dct['__getattribute__'] = __getattribute__

		return type.__new__(cls, name, bases, dct)

class Decorator(object):
	__metaclass__ = DecoratorType

class HBar(Decorator):
	def __init__(self, number):
		Decorator.__init__(self)
		self._number = number
	def inc(self):
		self._number += 1
	def p(self):
		print self._number

hbar = HBar(10)
for each in dir(hbar.decorator()):
	print each

hbar.decorator().p()
hbar.decorator().inc()
hbar.decorator().p()
-------------------------------------------------------
Unfortunately this does not work. The newly defined __init__ method
inside __new__, does a call to impl(*args, **dargs). However, since
the HBar.__init__ calls the Decorator.__init__ method, but the
HBar.__init__ method no longer resides inside HBar, but rather inside
HBarImpl (which is no longer a subtype of Decorator), the compiler
complains that Decorator.__init__ is not being called with a Decorator
instance as its first argument (which is true).
I tried changing the definition of impl inside __new__ to have
Decorator as one of its bases, but then for some reason impl(*args,
**dargs) asks for 4 arguments (just like __new__) and I have no clue
as to why that happens.

Any help on this?

Regards,
Thomas K.



More information about the Python-list mailing list