So we've decided to let interfaces grow `adapt` and `utility` methods. I've
written a simple and straight-forward implementation of them (see the
tlotze-component-API branches of zope.interface and zope.component) that is
closely modelled on the exisiting `__call__`. In particular, the new methods
use component hooks which are like adapter hooks but with a richer set of call
parameters. There are a few tests for the new methods as well, so everything
should be fine.
Except that I don't like the implications now that I have actually written
down the code. I'll describe the problem I see and then suggest an idea that I
don't think we've been considering in the discussion two weeks ago:
We're intentionally leaking the concept of utilities to zope.interface.
Assuming we're entirely fine with this, we still need to decide how much of
the particulars of the ZCA we want to bring along: named components, lookup
contexts, the ComponentLookupError. My current implementation tries to
introduce enough generic behaviour into the `adapt` and `utility` methods so
that they don't cause too obvious (conceptual) dependencies of zope.interface
* `adapt` and `utility` don't define particular optional arguments but pass
all keyword parameters except for `default` to the component hook which,
being implemented by zope.component, keeps the knowledge about named
adapters and lookup contexts within the latter package.
* The hook invokes the `query*` functions to play nice with any other
component hooks and the interface methods raise a TypeError if all of them
fail to find a component.
However, the generic behaviour gets in our way: the method signatures become
useless and hooks lose the possibility of raising useful exceptions.
I've tried some variations but as long as the `adapt` and `utility` methods
are actually implemented by zope.interface, it will always come down to a
compromise that either renders the new methods unusable with anything that's
not very much like zope.component, or makes for a half-hearted copy of the
functionality we currently have in the zope.component API.
I discussed this a bit with Wolfgang as we both don't like this kind of
compromise in such core functionality. We came up with the idea that a clean
solution would be to keep any implementation of the two methods out of
zope.interface and rather inject them into the interface API by code kept
entirely within zope.component. We do realise how close to the concept of
monkey-patching this comes, but maybe it wouldn't be so bad if we could do it
in a more structured way (being intentionally vague here yet).
In particular, keeping the concrete `adapt` and `utility` methods out of the
core implementation of interfaces would address the concern raised by somebody
on this list that we were going to tailor zope.interface too much to the needs
of the Zope ecosystem. Uses of interfaces other than adaptation and component
lookup could get convenience methods registered by the same mechanism
zope.component would end up employing, which is a big conceptual advantage
from my point of view.
What do people think of this?
Zope-Dev maillist - Zope-Dev@zope.org
** No cross posts or HTML encoding! **
(Related lists -