Conditional adapters
There are use cases when you just want to adapt an object if some condition is true. For instance I wanted to adapt xml-rpc requests only if they were meant for my application, so I wouldn’t interfere with other packages that may use xml-rpc. I found it was rather easy (after figuring out how :) to make a conditional adapter. Here’s a simple example that can be run in a zope prompt (zopectl debug).
First we have some imports, basic interfaces and classes.
from zope.interface import Interface, implements, implementer
from zope.component import adapts, adapter, provideAdapter
class IA(Interface):
pass
class A(object):
implements(IA)x=7
class IB(Interface):
pass
An adapter class for adapting objects providing IA to IB would typically look like this:
class AdapterAtoB(object):
implements(IB)adapts(IA)def __init__(self, context):
....self.context = context
After registering this adapter one would be able to adapt objects providing IA to IB:
provideAdapter(AdapterAtoB)
>>> a = A()
>>> b = IB(a)
But let’s say you want the adapter lookup to succeed only when A.x = 7, then you would need to do something like this:
class AdapterAtoB(object):
implements(IB)#we don't need adapts anymoredef __init__(self, context):
....self.context = context
@adapter(IA)
@implementer(IB)
def a_to_b(obj):
if obj.x == 7:
....return AdapterAtoB(obj)
else:
....return None
>>> provideAdapter(a_to_b)
>>> a = A()
>>> b = IB(a)
>>> a.x = 2
b = IB(a)
TypeError: ('Could not adapt', <A object at ...>, <InterfaceClass IB>)
Mission accomplished.
(had problems with indenting, that’s why the dots are there)
Can’t we just conditionally raise TypeError in __init__ instead of rewriting as function?