[Interface-dev] Doing multi-adaptation through interface call
(again)
Jim Fulton
jim at zope.com
Sat Aug 14 08:16:42 EDT 2004
I really like being able to do adaptation by calling
interfaces. Zope uses multi-adapters a fair bit. These are
adapters that adapt multiple objects. They have a number of
differences from single adapters:
- The adapt multiple objects. The factories have multiple arguments.
- __conform__ isn't used
- There's no question of whether an object already implements an
interface.
As mentioned here before, I'd like to be able to use tuples to
indicate multi-adaptation in Zope:
adapter = IFoo((a, b))
This is potentially a problem, because someone might have registered
an adapter for tuple.
I'd like to suggest the following compromise:
Zope's component facility will register an adapter hook after
the normal adapter hooks. This hook will, if a tuple if given,
try to get a multi-adapter. If someone has registered a normal
adapter from tuple, then that would be found first by the normal
adapter hooks and take precedence over any multi-adapters.
With this mechanism, multi-adapters can be supported without affecting
regular tuple adapters. In the unlikely event that there are both
tuple adapters and multi-adapters providing the same interface, the
multi adapters will lose.
Some alternatives (think of the above as alternative A):
B. Allow multiple arguments to __call__, as in:
adapter = IFoo(a, b)
This introduces 2 ambiguities:
1. In a two argument case, we can't distinguish multi-adaptation
from single adaptation with a default. We could fix this by
always requiring that the default be given as a keyword argument,
but that introduces a backward incompatability.
2. In a single-argument case, we can't distinguish the normal-adapter
case from the multi-adapter (with one input) case. One could argue that
this is a yagni, but I'm a bit uncomfortable saying that multiple
adaptation is for 0, 2, or more than 2 objects.
C. Add additional methods to interfaces. I wanted to avoid cluttering
the interface API with to much component support, however:
- Adaptation is a pretty important feature of interfaces, and
- Zope's component architecture is coalescing to the point where it consists
solely of adapters and utilities, where, clearly, adapters are the most important.
- The adapter registry is provided by the interface package, so, perhaps
it makes sense to surface access to registries in the interface API.
If we did this, I'd probably add the following interface methods:
def multi_adapt(*objects, **options):
"""Adapt multiple objects
Options:
- default: The value to return if no adapter can be found. This
defaults to None
- name: Look up a named adapter with the given name.
"""
def subscribers(*objects):
"""Return the subscribers for the given objects
An iterable object is returned. Adapters are not computed until
they are returned by the iterator. So, for example, if you had a for loop
like:
for subscriber in IFoo.subscribers(a, b):
if some condition:
break
Then subscribers not yet retrieved when we break out of the loop are
not computed.
"""
This is slippery slope. I can also think of a number of other methods to handle
more obscure cases that are needed in Zope, but not often.
Thoughts?
Jim
--
Jim Fulton mailto:jim at zope.com Python Powered!
CTO (540) 361-1714 http://www.python.org
Zope Corporation http://www.zope.com http://www.zope.org
More information about the Interface-dev
mailing list