473,378 Members | 1,470 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,378 software developers and data experts.

Wrapping method calls with metaclasses

I've never used metaclasses in real life before and while searching through
the online Cookbook I found this gorgeous example:

"Wrapping method calls (meta-class example)"
http://aspn.activestate.com/ASPN/Coo.../Recipe/198078

What I want to do in my app is to log all method calls and seems that the
metaclass example above do this fine but it fails when it's needed to
instantiate the class I'm in in a method. So if I do:

class Test(object):
__metaclass__ = LogTheMethods
def foo(self):
return Test()

this generate a Runtime Error cause recursion never stops :(
Any hint to enhance the example?
--
Lawrence - http://www.oluyede.org/blog
"Anyone can freely use whatever he wants but the light at the end
of the tunnel for most of his problems is Python"
Dec 6 '05 #1
4 1789
Lawrence Oluyede <ra***@dot.com> wrote:
I've never used metaclasses in real life before and while searching through
the online Cookbook I found this gorgeous example:

"Wrapping method calls (meta-class example)"
http://aspn.activestate.com/ASPN/Coo.../Recipe/198078

What I want to do in my app is to log all method calls and seems that the
metaclass example above do this fine but it fails when it's needed to
instantiate the class I'm in in a method. So if I do:

class Test(object):
__metaclass__ = LogTheMethods
def foo(self):
return Test()

this generate a Runtime Error cause recursion never stops :(
Any hint to enhance the example?


I can't reproduce the infinite recursion you observe, by merging said
recipe and your definition of class Test, w/Python 2.4.2 on Mac OS 10.4.

Can you please supply a minimal complete example, e.g. simplifying
function logthemethod to just emit s/thing to stdout etc, that does
exhibit the runaway recursion problem you observe?
Alex
Dec 7 '05 #2
Il 2005-12-07, Alex Martelli <al***@mail.comcast.net> ha scritto:
I can't reproduce the infinite recursion you observe, by merging said
recipe and your definition of class Test, w/Python 2.4.2 on Mac OS 10.4.


It seemed that the problem arose because I was not using super() in a new
style class based hierarchy.

class Test(object):
__metaclass__ = LogTheMethods
logMatch = '.*'

def __init__(self, foo):
self.foo = foo

def test(self):
return "test"

class TestChild(Test):
def __init__(self):
# with super this works
Test.__init__(self, "foo")

def test(self):
return "child"

d = {'test': Test,
'child': TestChild}

class MainTest(object):
__metaclass__ = LogTheMethods
logMatch = '.*'

def create_test(self, key):
return d[key]()

if __name__ == '__main__':
l = MainTest()
print l.create_test("child").test()
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)
"""

In my project I'm doing deeply nested recursion things and it exceeds the
maximum recursion limit for this problem this way.

I don't get to fully work the metaclass anyway for other weird reasons
(using super() I lose an attribute around?!) I'm gonna fix this.
--
Lawrence - http://www.oluyede.org/blog
"Anyone can freely use whatever he wants but the light at the end
of the tunnel for most of his problems is Python"
Dec 7 '05 #3
Il 2005-12-07, Lawrence Oluyede <ra***@dot.com> ha scritto:
I don't get to fully work the metaclass anyway for other weird reasons
(using super() I lose an attribute around?!) I'm gonna fix this.


It was a bug of one of the super() in the chain.
Still suffer from deep recursion limit error with that metaclass.
Keep trying.
--
Lawrence - http://www.oluyede.org/blog
"Anyone can freely use whatever he wants but the light at the end
of the tunnel for most of his problems is Python"
Dec 7 '05 #4
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)(*ar gl,**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

Dec 7 '05 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

13
by: Jeremy Sanders | last post by:
Is it possible to implement some sort of "lazy" creation of objects only when the object is used, but behaving in the same way as the object? For instance: class Foo: def __init__(self, val):...
2
by: Andrzej Kaczmarczyk | last post by:
Hi I am experiencing something weird. maybe you could help me. I have two ineditable classes from outsource libraries: DataColumn and GridColumn I have built a wrapper class around...
2
by: =?Utf-8?B?S2lrZQ==?= | last post by:
Hello, I need to be able to somehow wrap calls made through a standard Interface used to access a WCF service. The reason for this is to have a higher degree of control, mainly to catch all...
6
by: mh | last post by:
I am instantiating a class A (which I am importing from somebody else, so I can't modify it) into my class X. Is there a way I can intercept or wrape calls to methods in A? I.e., in the code...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.