[Zope3-dev] Re: Interface support in Python? (was Re: [Zope3-dev] Proposal: Improving on __implements__)

Phillip J. Eby pje@telecommunity.com
Wed, 22 Jan 2003 19:24:52 -0500


At 06:29 PM 1/22/03 -0500, Jim Fulton wrote:
>Phillip J. Eby wrote:
>
>..
>
>>I think for me, another issue would most definitely be proper support for 
>>metaclasses, i.e. spelling the difference between what classes and 
>>instances implement.  While it may be true that "most people" will not 
>>implement metaclasses, it is still quite possible for them to be bitten 
>>by the difference when using metaclasses provided by someone else.
>>(Currently, __class_implements__ works reasonably well, but it can get 
>>really hairy when you have metametaclasses in play.)
>
>I agree. I'll note that you don't need meta classes to have classes
>that implement interesting interfaces. Classes do have some methods
>of their own, most notably __call__, and can habve more with class
>and static methods.

Right; It's just that the hairy part is that a metaclass can't use 
__implements__ to say what its instances implement!  IIRC, it has to define 
a __class_implements__ descriptor that returns different values for 
instances and classes.  Anyway, it's hairy because of the special casing 
for classes.


>>If we were writing the interface package today -- assuming Python 2.2 and 
>>up -- I'd suggest always asking an object's class for what it implements, 
>>passing in either the instance or the class.  That seems to be the only 
>>way to be completely unambiguous as to whose interfaces you're asking 
>>for, when the object in question might itself be a class or type.  An 
>>__implements__ descriptor can only be unambiguous if it's defined on the 
>>meta-most metaclass of the system.  So to do it cleanly it'd have to be 
>>part of type 'type', which implies a language change.
>
>I'm not sure what you just said. ;)

I would try to show you an example of the problem, but my brain is too 
fried right now.  The problem has to do with distinguishing between "class 
attributes" and "metaclass instance attributes" -- which are *not* the same 
thing.  Hopefully you are now confused about something more specifically 
confusing.  ;)


>I'll note that it is possible to design a descriptor for __implements__
>that will give different answers depending on whether you access it
>through a class or an instance.

I've done that; it didn't work nearly as well as fixing the Interface 
package to properly support __class_implements__ did.


>   You don't need __class_implements__.
>And you can get an object's implementation specification unambiguously.
>No meta-class is necessary.  To make this work, you don't want people
>setting __implements__ directly.

But if you *do* have a metaclass, the metaclass can't make assertions about 
its instances' interfaces, because the __implements__ slot on the metaclass 
instance will be occupied by a descriptor that's there to get the metaclass 
instance instance's interface assertions.

Maybe that one was more clear?  Anyway, this is all the same problem I'm 
describing throughout this message: class attribute descriptors take 
precedence over metaclass instance descriptors, unless the latter are 
"data" descriptors (i.e. that accept __set__ calls).  I'm not saying it's 
impossible to make it work, just that it's rather hairy, even with just one 
meta-level.  You can't use the class dictionary's '__implements__' entry to 
hold the value, because that entry needs to be saved for the descriptor to 
say what the class provides to *its* instances.  So you have to come up 
with another name for the entry to hold the value.  Only, you can't use the 
same name for both instances and classes, because there might be another 
meta-level that needs to store an assertion for *its* instances...