solving the metaclass conflict

Michele Simionato mis6 at pitt.edu
Sun Jun 8 07:34:12 EDT 2003


pje at telecommunity.com (Phillip J. Eby) wrote in message news:<25b5433d.0306071443.63b27df6 at posting.google.com>...
> mis6 at pitt.edu (Michele Simionato) wrote in message news:<2259b0e2.0306070629.7f5fcad7 at posting.google.com> <http://groups.google.com/groups?selm=2259b0e2.0306070629.7f5fcad7%40posting.google.com>...
> > I have just posted a recipe on the online Cookbook that could be of interest
> > for metaclasses users.
> > 
> > ----------------------------------------------------------------------------
> > 
> > Description:
> > 
> > Any serious user of metaclasses has been bitten at least once by the 
> > infamous metaclass/metatype conflict. Here I give a general recipe
                                                        ^^^^^^
Here I have exaggerated a bit. I am aware my recipe has limitations:
that's why I call it a recipe! Notice that it fits in something like
25 lines,
skipping comments. It is general enough for that size.

>FYI, note that your implementation doesn't:

>* Handle classic classes in the base class list ('trivial()' should
>check for 'is ClassType' as well as 'is type')

This is on design: 

1) I don't want people to use classic classes;
2) They will go away at some point;
3) They can be trivially converted to new-style classes with 
    a __metaclass__=type line at the beginning of the module.

Moreover, as you say, if one really wants it, it is trivial to fix it.

> * Handle non-type metatype roots (e.g. ExtensionClass and MESS)

I don't use this kind of stuff and they are not standard,  so it was
not in the design to support them.

> * Handle multi-level metaclasses (e.g. metametaclasses)

True: look at the source code line

  # create new metaclass,shift possible conflict to meta-metaclasses 
  return type(metaname,metabases,{}) 

The comments explicitly says that I don't want to fiddle with the
meta-metaclass
conflict. This could be done with a recursive version (something like
substituting 'type' here with 'clsfactory()(metaname,metabases,{})')
but I wanted to keep the recipe SIMPLE, I am not designing an
implementation for usage in core Python (even if I think somebody
should do that).

>* Remove unneeded metaclasses that are a subclass of another listed
>metaclass

Probably, as David says, you mean the reverse: one should remove
unneeded
metaclasses that are a superclass of another listed metaclass. Does
not seem
so dangerous, but I will fix it.

>* Reuse all generated metaclasses (You're memoizing on a set of base
>classes, rather than on the set of unique metaclasses.)

I am also memoizing the passed metaclasses (i.e. the 'metas' tuple)
and
from the tuple of bases classes I get the corresponding metaclasses,
so
it is not obvious when _generatemetaclass will fail. Can you give a
counterexample ? If yes, I will fix it.

> PEAK's 'peak.util.Meta' module contains a more-complete implementation
> of this technique.  (See <http://peak.telecommunity.com/> for info on
> PEAK.)

I will look at it.

>It's bloody difficult to write a correct, complete, and efficient
>metaclass generator, so it's no wonder Guido chose to punt on this in
>2.2 (and 2.3 for that matter).

I would say it is difficult, indeed. Maybe not bloody difficult,
though.
I think may recipe is good enough for most users, especially since
they
can understand how it works and its limitations (which were indicated
in the commented lines BTW; I don't think meta-metaclasses are so
largely used to deserve explicit mention). Anyway, I will fix the
issue
with meta-metaclasses if it can be done with few lines of code, and
the issue with unneeded metaclasses, too. Not sure if I want to fix
the
issue with classic classes, tough.

Thanks for the feedback, it is what I asked for.

                                   Michele




More information about the Python-list mailing list