By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,201 Members | 937 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,201 IT Pros & Developers. It's quick & easy.

Trouble with metaclass

P: n/a
Hi,

I'm having trouble with a metaclass suposed to check the method signature of
its classes.

Here's the metaclass:

class MetaChecker(type):
def __new__(cls, name, bases, attribs):
for name, value in attribs.iteritems():
if inspect.ismethod(value):
if not isSingleArg(value):
raise "%s is not a thunk method!"%name
return type.__new__(cls, name, bases, attribs)
def isSingleArg(fn):

args = inspect.getargspec(fn)[0]
if len(args) == 1:
return 1
else:
return None
And here's a class with this metaclass:

class Preconditions (object):

__metaclass__ = MetaChecker

If I define a descendant of Preprocesor with a method with 2 arguments, I
don't get any error:
class P (Preprocessor):
def f(self, x):
return x
What am I doing wrong? O:-)

Jul 18 '05 #1
Share this Question
Share on Google+
3 Replies


P: n/a
Fernando Rodriguez wrote:
Hi,

I'm having trouble with a metaclass suposed to check the method signature of
its classes.

Here's the metaclass:

class MetaChecker(type):
def __new__(cls, name, bases, attribs):
for name, value in attribs.iteritems():
if inspect.ismethod(value):
if not isSingleArg(value):
raise "%s is not a thunk method!"%name
return type.__new__(cls, name, bases, attribs)
def isSingleArg(fn):

args = inspect.getargspec(fn)[0]
if len(args) == 1:
return 1
else:
return None
And here's a class with this metaclass:

class Preconditions (object):

__metaclass__ = MetaChecker

If I define a descendant of Preprocesor with a method with 2 arguments, I
don't get any error:
class P (Preprocessor):
def f(self, x):
return x
What am I doing wrong? O:-)


The problem seems to be with ismethod function. Cf.:

import inspect

class MetaFoo(type):
def __new__(cls, name, bases, attribs):
for name, value in attribs.iteritems():
if inspect.isfunction(value):
print '%s(%s)' % (name, ',
'.join(inspect.getargspec(value)[0])) // Sorry, it's wrapped :(

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

class Base(object):
__metaclass__ = MetaFoo

class Foo(Base):
def method0(self): pass
def method1(self, x): pass
def method2(self, x, y): pass

And compare:

class Foo(object):
def method(self): pass
print 'inside', inspect.ismethod(method)
print 'inside', type(method)

print 'outside', inspect.ismethod(Foo.method)
print 'outside', type(Foo.method)

Python2.3 prints:
inside False
inside <type 'function'>
outside True
outside <type 'instancemethod'>
regards,
anton.

Jul 18 '05 #2

P: n/a
anton muhin wrote:
Fernando Rodriguez wrote: ...
class MetaChecker(type):
def __new__(cls, name, bases, attribs):
for name, value in attribs.iteritems():
if inspect.ismethod(value):

... The problem seems to be with ismethod function. Cf.:


Right, or, more precisely, there is no problem with ismethod -- it
correctly reports that the values in the attribs dictionary are not
method objects (they're function objects).

Summarizing and simplifying only a little bit...:

1. The def statement always and exclusively creates a function object.

2. A function object is also a descriptor: when you call f.__get__(x),
you get back a method object with im_func == f and im_self == x.

3. The attribute lookup process calls x.__get__(self) on any attribute
it may find in the class's dictionary.

But at this point in the execution of the metaclass's __new__, there
is no "class dictionary" yet -- there isn't even a _class_ -- just a
plain dictionary of attributes which will BECOME the class dictionary
once you call type.__new-_ with that dict as the 4th argument.
Alex

Jul 18 '05 #3

P: n/a
Fernando Rodriguez <fr*@easyjob.net> wrote in message news:<jb********************************@4ax.com>. ..
Hi,

I'm having trouble with a metaclass suposed to check the method signature of
its classes.

Here's the metaclass:

class MetaChecker(type):
def __new__(cls, name, bases, attribs):
for name, value in attribs.iteritems():
if inspect.ismethod(value):
if not isSingleArg(value):
raise "%s is not a thunk method!"%name
return type.__new__(cls, name, bases, attribs)
def isSingleArg(fn):

args = inspect.getargspec(fn)[0]
if len(args) == 1:
return 1
else:
return None
And here's a class with this metaclass:

class Preconditions (object):

__metaclass__ = MetaChecker

If I define a descendant of Preprocesor with a method with 2 arguments, I
don't get any error:
class P (Preprocessor):
def f(self, x):
return x
What am I doing wrong? O:-)


The metaclass is right and actually the names you are using (Preconditions/
Preprocessors) suggest to me that you are using the right tool for the job;
the only problem is that you must use 'inspect.isfunction' and not
'inspect.ismethod', because of the methods <=> functions mismatch I am
sure you know everything about ;) If not, please feel free to ask.

Also, I would use

return super(mcl,MetaChecker).__new__(mcl,name,bases,attr ibs)

instead of type.__new__, anticipating the need for multiple inheritance
of metaclasses.
Michele
Jul 18 '05 #4

This discussion thread is closed

Replies have been disabled for this discussion.