[Twisted-Python] Interface.adaptWith and Interface.__adapt__
Phillip J. Eby
pje at telecommunity.com
Wed Jun 4 16:10:27 MDT 2003
Hi. I'm working on a new interface adaptation package for Python, called
PyProtocols. It's an extension of PEP 246 to include a standardized API
for declaring support for particular interfaces, and how to adapt
instances, types, and other interfaces to an interface. It includes its
own interface library, but also has adapters and monkeypatching for Zope
interfaces to make them usable with the API. That is, since the API is
itself defined with interfaces, it uses itself to adapt Zope interfaces to
the interface for interfaces it uses. :)
Anyway, I'd like to add support for Twisted interfaces as well. I started
today on trying to write adapters to map Twisted's interface/adapter API
onto the PyProtocols API, and I ran into a bit of a snag.
I was about to write the code to add an __adapt__ method to Twisted
interfaces, when I noticed there is already some code related to
__adapt__. But that code isn't at all compatible with the PEP 246 spec for
__adapt__, as I understand it. PEP 246 wants to be able to call an
object's __adapt__ method with a single argument, while MetaInterface
expects to yank out 'im_func' and pass two arguments into it.
The only way I can see to get this to work with PEP 246, is to monkeypatch
MetaInterface.__call__ to find '__adapt__' by checking the interface's
dictionary, rather than using __getattr__. In this way, I can give
MetaInterface an __adapt__ method that will be found whenever you refer to
ISomething.__adapt__, but MetaInterface.__call__ will still find any
__adapt__ that was put in by a 'def' in the interface body.
Essentially, I would be monkeypatching to change these two lines:
if hasattr(self, '__adapt__'):
adapter = self.__adapt__.im_func(adaptable, default)
To:
if '__adapt__' in self.__dict__:
adapter = self.__dict__['__adapt__'](adaptable, default)
Because self.__adapt__ would no longer be the same value as
self.__dict__['__adapt__'], due to my adding a MetaInterface.__adapt__
method. I assume that no inheritance lookup would be required, because
interface inheritance for adaptation purposes is reversed. That is, a
subclass of an interface would not want to inherit its base interface's
__adapt__, because a subclass interface has more stringent requirements for
its implementors. Therefore, a superclass __adapt__ isn't guaranteed to
work for a subclass.
Anyway... I noticed that the only code in Twisted currently (that I could
find) that actually uses the current __adapt__ setup is the test suite. Is
there any way this might be changeable to something more compatible with
PEP 246? I mean, if I jump through enough hoops building adapters and
monkeypatching, I can probably make it so that this will work
transparently, and anybody who uses PyProtocols will then be able to mix
Twisted, Zope, and PyProtocols interfaces in their applications. But it's
pretty messy, and I'm wondering about the copyright status if I have to
copy a lot of code from MetaInterface.__call__ in order to monkeypatch a
replacement. (I'd like to release PyProtocols under the PSF license.)
Anyway, if you'd like some background on PyProtocols, the reference manual
is at:
http://peak.telecommunity.com/protocol_ref/
I don't know if you guys have previously looked at PEP 246 or thought about
any of the adapter precedence/implication/declaration issues that
PyProtocols tries to address. It may be that some of what I've done may be
useful to you. OTOH, you may have already looked at this sort of thing and
have different requirements for your component architecture. My goal is
merely compatibility among Python frameworks, so that people who use more
than one framework's "Interface" types (e.g. Zope, Twisted, PEAK, etc.) can
have some common ground rules, similar to the DBAPI or the way most Python
numeric types can be used in an expression together.
More information about the Twisted-Python
mailing list