[PEAK] Contextual / DecoratorTools.classy oddity

Phillip J. Eby pje at telecommunity.com
Thu Jul 24 21:08:32 EDT 2008


At 02:42 AM 7/25/2008 +0300, Sergey Schetinin wrote:
>Sorry to bother you but it's me again. Here's an odd error (also attached):
>
> >>> from peak.context import Service
> >>> from peak.util.decorators import classy
> >>>
> >>> class A(Service, classy): pass
>...
> >>> class B(A): pass
>...
> >>> class C(A): pass
>...
> >>> class D(B,C): pass
>...
>Traceback (most recent call last):
>   File "<stdin>", line 1, in <module>
>   File 
> "c:\python25\lib\site-packages\DecoratorTools-1.7-py2.5.egg\peak\util\decorators.py",
>line 625, in __new__
>     cls = super(classy_class, meta).__new__(meta, name, bases, cdict)
>TypeError: Error when calling the metaclass bases
>     metaclass conflict: the metaclass of a derived class must be a
>(non-strict) subclass of the metaclasses of all its bases
>
>
>
>This seems to be exactly the thing classy is supposed to help avoid
>and it's very strange to me that error happens when declaring D cause
>there shouldn't be any MRO changes -- the subclasses are empty. The
>actual case when I got this was trying to subclass both Service and
>Component.

The issue here is that B and C have their own unique metaclasses, 
which are not derived from one another.  Specifically, Service 
creates a unique metaclass for each derived class, and these 
independent metaclasses can't be mixed.  You need to do something 
like this if you want to inherit from more than one Service subclass:

     class D(B, C):
         class __metaclass__(type(B), type(C)):
             pass

I've personally never needed to multiple-inherit Services, so didn't 
notice.  It's a bit of a wart, I suppose, but I'm not sure whether I 
care, or if it's a good idea to do in the first place.  (That is, 
there might be other negative consequences of doing it.)

Anyway, the limitation here is of peak.context, which as I've 
mentioned previously, isn't really ready for prime time.  "classy" on 
its own doesn't do this, it's the metaclass-per-Service-subclass 
that's the cause here.




More information about the PEAK mailing list