[Zope3-dev] Context and Component Lookup II
Jim Fulton
jim at zope.com
Thu Aug 7 12:34:59 EDT 2003
This is an update to the earlier proposal, "Context and Component
Lookup" in response to Phillip Eby's remarks. Thanks Phillip.
Summary:
I propose the component architecture API be modified so that all
component-lookup calls have an optional "context" keyword argument.
When a context is provided, it will control how components are
looked up. When we get a context, we will adapt it to
IServiceService, and use the resulting object to get the needed
service.
If no context is passed to a component-lookup function, then an
application-defined strategy will be used. The default strategy is
to use the global service manager. In Zope, the site containing the
published object will be used.
Whether or not a context is passed to a component-lookup routine
will depend on whether the calling code is particular about where
components come from. In many cases, we don't care where a component
comes from as long as it satisfies a specified interface. If
calling code *does* care, then it must explcitly provide an
appropriate context.
Zope will provide an adapter from IContained to IServiceService to
support explicit location-based component lookup. IContained is an
interface implemented by components that track location in a
containment hierarchy.
Updated proposal
This is, essentially a proposal. It is here, rather than the Wiki due
to the birthing pains of new zope.org. :)
As things stand now, component lookup is based on location. For
example, suppose we have two sites, S1 and S11. S11 is a subsite of
S1, which is a subsite of the root folder, which is also typically a
site. Now, suppose we have object O in site S11. If we look up an
adapter for O:
a = getAdapter(O, IFoo)
we'll look for an adapter factory in S11, then in S1, then in the root
site, and finally in the global adapter service. This is all well and
good, I think. Note that to do this, we use contextual information for
O. For example, now, we use the context wrapper around O to figure out
where it is. In the future we might use a __container__ attribute of
O.
Now, supposer we access a subobject of O, O.x. Further, suppose
we don't have context information for O.x:
x = O.x
a = getAdapter(x, IBar)
Now, because x doesn't have any context information, we'll only look
in the global adapter service. This is likely to lead to unpleasant
surprises if S1 or the root site defined an applicable adapter.
Now consider a slightly different case. Suppose we access a view of O
in S11 via a URL:
http://eek.com/S1/x/y/S11/z//O/someview.html
So we have a request in S11. Now suppose that in that view, we access
object P from S1. We use a view, V, of P in generating the output
(for the view of O in S11). There are different definitions of this
view in S1 and S11. Which one should we use? I'm inclined to think
that we should use the one from S11.
Now, suppose, from someview.html, we call a method on P. Let's
supposer that P needs to look up a utility to provide IFoo. Now,
imagine that S1 and S11 each provide a (separate) utility for IFoo.
Which one should we use. I suggest that that depends on how flexible
P is. P might be happy to use *any* utility as long as it implements
IFoo. It might even prefer to use the utility available in the place
where it's used, if possible. On the other hand, P may have some
dependency on a particular utility or utility source. If, for some
reason, it's important for P to be able to get a utility from a
particular place, there should be a way for it to do so.
In discussing the previous version of this proposal with Phillip Eby,
Phillip argued that code calling the component-lookup API should
control how components are looked up. I'd prefer to say that code
calling component-lookup routines should be able to control
how components are looked up.
In summary, I'd like to address 2 issues:
- Code that has no context information cannot get at locally-defined
components.
- Components that are designed to fit into whatever context they're
used in have no convenient way to cause components they need to be
lookup up in that context.
Proposed solution
We will update the component-lookup APIs to always accept an
optional "context" keyword argument.
If no context is provided, then an application-defined lookup policy
will be used. The default policy will be to use the global service
manager. The default Zope policy will be to use the (most specific)
site containing the published object for a request. This policy
will, of course, be pluggable.
If a context is provided (and is not None), it will be adapted to
IServiceService, and the resulting service service will be used to
look up the service to handler the lookup. Zope will provide a
default adapter from IContained that provides location-based
lookup::
class IContained(Interface):
"""Objects contained in containers
"""
__container__ = Attribute("The container")
__name__ = schema.TextLine(
__doc__=
"""The name within the container
The container can be traversed with this name to get the object.
""")
Some examples:
1. getAdapter(X, I)
Adapt X to I using an application-defined lookup strategy.
Note that, by default, and in (future) Zope, X's location does not
affect component lookup.
2. getAdapter(X, I, context=C)
Adapt X to I using a lookup strategy determined by C.
3. getAdapter(X, I, context=self)
Adapt X to I using a lookup strategy determined by self.
This is essentially the same as 2. If self is some content object
that implements IContained, then, in Zope, we'll look up the
component in self's site.
4. getAdapter(X, I, context=globalServiceManager)
Adapt X to I using an adapter found in the global service manager,
bypassing any local customizations.
5. getUtility(I)
Get a utility that provides I using an application-defined lookup
strategy. Note that we have changed the signature of getUtility so
that it no longer accepts a positional context argument. The
context is now optiona..
6. getUtility(I, context=C)
Get a utility that provides I using a lookup strategy determined by C.
Thoughts?
Jim
--
Jim Fulton mailto:jim at zope.com Python Powered!
CTO (703) 361-1714 http://www.python.org
Zope Corporation http://www.zope.com http://www.zope.org
More information about the Zope3-dev
mailing list