Trouble with metaclass

Discussion in 'Python' started by Fernando Rodriguez, Nov 13, 2003.

  1. 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:)
     
    Fernando Rodriguez, Nov 13, 2003
    #1
    1. Advertising

  2. Fernando Rodriguez

    anton muhin Guest

    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.
     
    anton muhin, Nov 13, 2003
    #2
    1. Advertising

  3. 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
     
    Alex Martelli, Nov 13, 2003
    #3
  4. Fernando Rodriguez <> wrote in message news:<>...
    > 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,attribs)

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


    Michele
     
    Michele Simionato, Nov 13, 2003
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Gustavo Niemeyer

    Metaclass discussons

    Gustavo Niemeyer, Aug 22, 2003, in forum: Python
    Replies:
    5
    Views:
    381
    Gustavo Niemeyer
    Aug 25, 2003
  2. Replies:
    9
    Views:
    384
    David Mertz
    Sep 10, 2003
  3. Metaclass and __slots__

    , Nov 6, 2003, in forum: Python
    Replies:
    1
    Views:
    325
    Peter Otten
    Nov 6, 2003
  4. ironfroggy
    Replies:
    16
    Views:
    448
    Michele Simionato
    Jun 3, 2005
  5. Steven D'Aprano

    Metaclass of a metaclass

    Steven D'Aprano, Jun 5, 2012, in forum: Python
    Replies:
    1
    Views:
    322
Loading...

Share This Page