[Python-Dev] PEP 246, redux

James Y Knight foom at fuhm.net
Wed Jan 12 19:47:30 CET 2005


I'd just like to share a use case for transitive adaption that I've 
just run into (I'm using Zope.Interface which does not support it). 
Make of this what you will, I just thought an actual example where 
transitive adaption is actually necessary might be useful to the 
discussion.

I have a framework with an interface 'IResource'. A number of classes 
implement this interface. I introduce a new version of the API, with an 
'INewResource', so I register a wrapping adapter from 
IResource->INewResource in the global adapter registry.

This all works fine as long as all the old code returns objects that 
directly provide IResource. However, the issue is that code working 
with the old API *doesn't* just do that, it may also have returned 
something that is adaptable to IResource. Therefore, calling 
INewResource(obj) will fail, because there is no direct adapter from 
obj to INewResource, only obj->IResource and IResource->INewResource.

Now, I can't just add the extra adapters from obj->INewResource myself, 
because the adapter from obj->IResource is in client code, 
compatibility with which is needed. So, as far as I can tell, I have 
two options:
1) everywhere I want to adapt to INewResource, do a dance:

resource = INewResource(result, None)
if resource is not None:
   return resource

resource = IResource(result, None)
if resource is not None:
   return INewResource(resource)
else:
   raise TypeError("blah")

2) Make a custom __adapt__ on INewResource to do similar thing. This 
seems somewhat difficult with zope.interface (need two classes) but 
does work.

class INewResource(zope.interface.Interface):
     pass

class SpecialAdaptInterfaceClass(zope.interface.InterfaceClass):
     def __adapt__(self, result):
         resource = zope.interface.InterfaceClass.__adapt__(self, other)
         if resource is not None:
             return resource

         resource = IResource(result, None)
         if resource is not None:
             return INewResource(result)

INewResource.__class__ = SpecialAdaptInterfaceClass



I chose #2. In any case, it certainly looks doable, even with a 
non-transitive adaptation system, but it's somewhat irritating. 
Especially if you end up needing to do that kind of thing often.

James



More information about the Python-Dev mailing list