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 anymore
def __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)

One Response to “Conditional adapters”

  1. Alek says on May 8th, 2007 at 7:28 pm

    Can’t we just conditionally raise TypeError in __init__ instead of rewriting as function?

Leave a Reply