Wrapping method calls with metaclasses

Peter Otten __peter__ at web.de
Wed Dec 7 05:28:30 EST 2005


Lawrence Oluyede wrote:

> look in TestChild's __init__(). Not using super() fails with a
> 
> """
> File "/home/rhymes/downloads/simple_logger.py", line 55, in __init__
> Test.__init__(self, "foo")
> File "/home/rhymes/downloads/simple_logger.py", line 24, in _method
> returnval = getattr(self,'_H_%s' % methodname)(*argl,**argd)
> TypeError: __init__() takes exactly 1 argument (2 given)
> """

The problem with the recipe seems to be that the mangled _H_XXX() method is
always looked up in the child class. One fix may be to store the original
method in the wrapper instead of the class:

def logmethod(methodname, method):
    def _method(self,*argl,**argd):
        global indent

        #parse the arguments and create a string representation
        args = []
        for item in argl:
            args.append('%s' % str(item))
        for key,item in argd.items():
            args.append('%s=%s' % (key,str(item)))
        argstr = ','.join(args)
        print >> log,"%s%s.%s(%s) " %
(indStr*indent,str(self),methodname,argstr)
        indent += 1
        # do the actual method call
        returnval = method(self, *argl,**argd)
        indent -= 1
        print >> log,'%s:'% (indStr*indent), str(returnval)
        return returnval

    return _method


class LogTheMethods(type):
    def __new__(cls,classname,bases,classdict):
        logmatch = re.compile(classdict.get('logMatch','.*'))

        for attr,item in classdict.items():
            if callable(item) and logmatch.match(attr):
                classdict[attr] = logmethod(attr, item) # replace method by
wrapper

        return type.__new__(cls,classname,bases,classdict)
 
Be warned that I did not thoroughly test that.

Peter




More information about the Python-list mailing list