[Zope3-dev] Interface.Implements module still broken for 2.2 metaclasses

Phillip J. Eby pje@telecommunity.com
Sun, 07 Jul 2002 16:54:42 -0400


At 09:20 PM 7/7/02 +0100, Steve Alexander wrote:
>Phillip J. Eby wrote:
>>The Interface.Implements module's getImplements() and 
>>getImplementsOfInstances() do not yield correct results for Python 2.2 
>>metaclass instances; that is, objects which inherit from 'type'.  The 
>>correction is straightforward, they need to use 'isinstance()'-based 
>>checks rather than 'type()' checks.  (And I have verified that they 
>>operate correctly with such a change.)  Unfortunately, I'm not sure that 
>>this can be properly backported to Python 2.1.
>
>I think that if they are changed to use isinstance(), they will no longer 
>work with context wrappers and security proxies.
>The solution is that isinstance in python 2.3 will take into account the 
>__class__ attribute of the object, so a semi-transparent proxy can publish 
>its inner object's __class__ attribute.

I'm not really sure what you're talking about, but I'm pretty sure it has 
nothing to do with what I'm talking about.  :)  I'm talking about these 
functions:

def getImplements(object):
     t = type(object)
     if t in ClassTypes:
         if hasattr(object, '__class_implements__'):
             return object.__class_implements__
     elif hasattr(object, '__implements__'):
         return object.__implements__

     return _typeImplements.get(t, None)


def getImplementsOfInstances(klass, tiget=_typeImplements.get):
     if type(klass) in ClassTypes:
         if hasattr(klass, '__implements__'):
             return klass.__implements__
         else:
             return None
     else:
         return tiget(klass, None)



I believe they should read as follows:

def getImplements(object):

     if isinstance(object,ClassTypes):
         if hasattr(object, '__class_implements__'):
             return object.__class_implements__
     elif hasattr(object, '__implements__'):
         return object.__implements__

     return _typeImplements.get(type(object), None)


def getImplementsOfInstances(klass, tiget=_typeImplements.get):
     if isinstance(klass,ClassTypes):
         if hasattr(klass, '__implements__'):
             return klass.__implements__
         else:
             return None
     else:
         return tiget(klass, None)


This change would only affect proxies which happened to be around classes 
-- and the change would simply make them *work* on such proxies once 
isinstance() uses __class__!  I can't see how making this change could 
possibly affect the current security proxies, since they don't subclass 'type'.

All of the Interface package unit tests run correctly with the change, and 
it also correctly handles the following situation:

from IFoo import IFoo

class myMeta(type):
     pass

class myClass(object):
     __metaclass__ = myMeta
     __implements__ = IFoo

# this line fails with unpatched code:
assert getImplementsOfInstances(myClass) is IFoo