Adapter

In der Zope Component Architecture (ZCA) sind Adapter Komponenten, die aus anderen Komponenten erstellt werden um sie einem bestimmten Interface zur Verfügung zu stellen:

>>> class IPerson(interface.Interface):
...     name = interface.Attribute("Name")
>>> class PersonGreeter:
...
...     component.adapts(IPerson)
...     interface.implements(IGreeter)
...
...     def __init__(self, person):
...         self.person = person
...
...     def greet(self):
...         print "Hello", self.person.name

Die Klasse definiert einen Constructor, der ein Argument für jedes adaptierte Objekt nimmt.

component.adapts
deklariert, was angepasst werden soll.
adaptedBy

gibt eine Liste der Objekte aus, die adaptiert werden:

>>> list(component.adaptedBy(PersonGreeter)) == [IPerson]
True
provideAdapter

Sofern nur ein Interface angeboten wird, kann dieses einfach bereitgestellt werden mit:

>>> component.provideAdapter(PersonGreeter)

Ebenso können spezifische Argumente zum Registrieren eines Adapters angegeben werden:

>>> class VeitPersonGreeter(PersonGreeter):
...     name = 'Veit'
...     def greet(self):
...         print "Hello", self.person.name, "my name is", self.name
>>> component.provideAdapter(
...                        VeitPersonGreeter, [IPerson], IGreeter, 'veit')

oder als keyword arguments:

>>> class ChrisPersonGreeter(VeitPersonGreeter):
...     name = "Chris"
>>> component.provideAdapter(
...     factory=ChrisPersonGreeter, adapts=[IPerson],
...     provides=IGreeter, name='chris')
queryAdapter oder getAdapter

kann für For named adapters verwendet werden:

>>> component.queryAdapter(Person("Chris"), IGreeter, 'veit').greet()
Hello Chris my name is Veit
>>> component.getAdapter(Person("Chris"), IGreeter, 'veit').greet()
Hello Chris my name is Veit

Falls kein Adapter vorhanden ist, gibt queryAdapter einen Standardwert zurück wohingegen getAdapter eine Fehlermeldung ausgibt:

>>> component.queryAdapter(Person("Chris"), IGreeter, 'daniel')
>>> component.getAdapter(Person("Chris"), IGreeter, 'daniel')
... # doctest: +ELLIPSIS
Traceback (most recent call last):
...
ComponentLookupError: (...Person...>, <...IGreeter>, 'daniel')
queryMultiAdapter oder getMultiAdapter

gibt die Adapter mehrerer Objekte zurück.

Wenn wir z.B. einen Adapter mit mehreren Objekten erstellen:

>>> class TwoPersonGreeter:
...
...     component.adapts(IPerson, IPerson)
...     interface.implements(IGreeter)
...
...     def __init__(self, person, greeter):
...         self.person = person
...         self.greeter = greeter
...
...     def greet(self):
...         print "Hello", self.person.name
...         print "my name is", self.greeter.name

können wir diesen Multi-Adapter anfragen mit queryMultiAdapter oder getMultiAdapter:

>>> component.queryMultiAdapter((Person("Chris"), Person("Veit")),
...                                  IGreeter).greet()
Hello Chris
my name is Veit