[Python-3000] PEP 3115 chaining rules (was Re: pep 3124 plans)

Phillip J. Eby pje at telecommunity.com
Tue Jul 31 18:26:35 CEST 2007


At 07:40 PM 7/31/2007 +1000, Nick Coghlan wrote:
>Phillip J. Eby wrote:
>>In other words, a class' metaclass has to be a derivative of all 
>>its bases' metaclasses; ISTM that a __prepare__ namespace needs to 
>>be a derivative in some sense of all its bases' __prepare__ 
>>results.  This probably isn't enforceable, but the pattern should 
>>be documented such that e.g. the overloading metaclass' __prepare__ 
>>would return a mapping that delegates operations to the mapping 
>>returned by its super()'s __prepare__, and the actual class 
>>creation would be similarly chained.  PEP 3115 probably needs a 
>>section to explain these issues and recommend best practices for 
>>implementing __prepare__ and class creation on that basis.  I'll 
>>write something up after I've thought this through some more.
>
>A variant of the metaclass rule specific to __prepare__ might look 
>something like:
>   A class's metaclass providing the __prepare__ method must be a 
> subclass of all of the class's base classes providing __prepare__ methods.

That doesn't really work; among other things, it would require 
everything to be a dict subclass, since type.__prepare__() will 
presumably return a dict.  Therefore, it really does need to be 
delegation instead of inheritance, or it becomes very difficult to 
provide any "interesting" properties.

So let's say that your super().__prepare__() is your "delegate".  And 
we recommend that any write operations you receive, you should also 
invoke on your delegate, and that you delegate any read operations 
you can't handle (i.e., key not found) to your delegate as well.

And of course, this requirement is recursive -- i.e., all metaclasses 
that define a __prepare__() should follow it, in order to be fully 
co-operative.

Actually, speaking of co-operative metaclasses, I wonder if it's time 
to finally implement automatic metaclass mixing in 3.x?  Python 
currently requires you to mix base classes' metaclasses, but doesn't 
provide any assistance in doing so.

For 2.x, I wrote a function that can be called to automatically 
generate a mixed metaclass for a type; perhaps we should include 
something like it in the stdlib, so if you get a mixed metaclasses 
error, the error message itself can suggest using 'metaclass=mixed' 
or whatever we call it.



More information about the Python-3000 mailing list