[Zope3-dev] Re: IMPORTANT: How to look up adapters

Tres Seaver tseaver at zope.com
Fri Jul 2 12:27:59 EDT 2004


Jim Fulton wrote:
> 
> For simple adaptation, where you adapt a single object to a single
> interface without a name providing qualification, you should call the
> interface:
> 
>   adapter = iface(ob)
> 
> If you want to provide a default to be used if the adapter
> can't be found, just pass it as an additional argument:
> 
>   adapter = iface(ob, default)
> 
> Note that if the object already provides the interface, then
> the object is returned.  Otherwise, if the object conforms
> to the interface (has a __conform__ that returns a non-None
> value for the interface), then the __conform__ method will
> be used to create the adapter.
> 
> This syntax has only been around for a couple of months.
> It appears that a number of people haven't heard about it,
> as I've recently noticed new code using the old syntax:
> 
>   adapter = getAdapter(ob, iface)
> 
> We have a problem with the old syntax.
> 
> We used to have four functions, getAdapter, queryAdapter,
> getNamedAdapter, queryNamedAdapter. The "Named" methods had
> different sematics than the non-"Named" methods.  The non-
> "Named" methods would return the object if the object already
> provided the interface. They would also return the result of
> calling the __conform__ method on the object, if present and if
> it's result was not None. The "Named" methods didn't consider
> whether the object aleady provided or conformed to the interface.
> The rational for this was that the name in a named-adapter
> lookup is an interface qualifier.  An object cannot provide
> or conform to a qualified interface.  A qualifid interface
> can only be provided through adapter lookup.
> 
> Now it happens that the un-"Named" methods allowed a name argument
> to be provided. This was for backward compatability and lasted
> much longer than it should have. They generated deprecation warnings
> if non-empty names were provided.
> 
> In an attempt to simplify the API just before the beta, the "Named"
> and un-"Named" methods were incorrectly merged.  This was based on the
> observation that they both seemed to take the same arguments.  I
> wasn't paying close enough attention and OKed this. :(  This led
> to the following problem.  With the current remaining
> queryAdapter and getAdapter functions, the name argument is ignored if
> the object provides or conforms to the interface.  This is a latent
> bug that hasn't bitten us yet, AFAIK, because we aren't making very heavy
> use of named adapters yet.  This will be more of a problem in the future.
> 
> There are two ways I can fix this:
> 
> 1. I can add back the "Named" methods and remove the name argument
>    from the un-"Named" methods.
> 
> 2. I can give the current un-"Named" methods the semantics of the
>    old "Named" methods.  This means that queryAdapter and getAdapter
>    will no longer consider whether an object provides or conforms to an
>    interface.
> 
>    We don't really need to call getAdapter or queryAdapter to
>    get the old behavior, because we can just call the interfaces.
>    Being able to get a simple adapter either by calling get/queryAdapter
>    or by calling the interface violates Python's "one way to do it"
>    philosophy.
> 
> There is one case where calling an interface isn't equivalent to 
> get/queryAdapter. If you want to supply a context argument to specify
>  a different place to look up adapters, you can't pass it to the 
> interface. This is an extreme edge case. I know of no place in the
> Zope 3 tree where this is needed, but it is something we want to
> allow. I propose to provide new functions: getSpecialAdapter and
> querySpecialAdapter. These functions will require a context to be
> specified and will return the object if it provides the requested
> interface and will use __conform__ if it conforms to the interface.

How about 'getAdapterInContext' and 'queryAdapterInContext', instead?

> Both of these options are backward inconpatible.  While I'm not happy about
> doing this after the beta, it's better than doing it after the final 
> release.
> 
> I prefer option 2 because:
> 
> - It provides a single way to do simple adaptation
> 
> - It provides simpler names for named-adapter lookup, which
>   are more consistent with multi-adapter (also named) lookup.
> 
> - It requires the least code change.
> 
> It's unclear which option is the least impact on add-on
> software.  I don't know how many people are still doing
> simple-adapter lookup with getAdapter and queryAdapter.
> With the change, these calls will break, because the name
> argument will be required.  On the one hand, breakage is bad,
> but, the breakage should be obvious.
> 
> I'm going to go ahead and do this (ootion 2).  Perhaps I'll
> change my mind if there are loud objections, but I hope there
> won't be. :)

+1 on the general plan.

Tres.
-- 
===============================================================
Tres Seaver                                tseaver at zope.com
Zope Corporation      "Zope Dealers"       http://www.zope.com



More information about the Zope3-dev mailing list