Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Trouble with metaclass

0 views
Skip to first unread message

Fernando Rodriguez

unread,
Nov 13, 2003, 6:27:03 AM11/13/03
to
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:-)

anton muhin

unread,
Nov 13, 2003, 7:42:19 AM11/13/03
to

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.

Alex Martelli

unread,
Nov 13, 2003, 8:38:56 AM11/13/03
to
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

Michele Simionato

unread,
Nov 13, 2003, 8:51:25 AM11/13/03
to
Fernando Rodriguez <f...@easyjob.net> wrote in message news:<jbq6rvob5qjddbtt6...@4ax.com>...

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,attribs)

instead of type.__new__, anticipating the need for multiple inheritance
of metaclasses.


Michele

0 new messages