Kapil Thangavelu wrote:
A few of us (Alec Mitchell, Godefroid Chapelle, Balazs Ree, Rocky Burt,
Daniel Nouri, Rob Miller, Vincenzo Di Somma, and myself) have been
discussing this in depth at the Sorrento Sprint. We've reached consensus
on how we hope to resolve the issues arising from the recent introduction
of five.localsitemanager and the deprecation of getToolByName.
We believe that these recent changes have introduced implicit magic into a
standard Zope3 api to fit Zope2 acquisition. There should be an explicit
separate api if we want acquisition wrapped context-aware utilities. As an
example of a symptom caused by the implicit implementation, KSS (which was
developed as a pure zope 3 component) breaks when used with Plone, even
though it is a perfectly valid z3 component. Once we return to using
getToolByName for tool lookup, the KSS/Plone3 issue disappears, because
the magic wrapping of things stops. This KSS/Plone3 issue arises because
the five.lsm acquisition breaks down when you add in non five.lsm
component registries. If you need Zope2 acquisition, you should use an
accessor api to get things wrapped.
In addition, getToolByName is the most fundamental and widely used api in
all of CMF, and we're going to be issuing hundreds of deprecating warnings
for every single cmf application extant.
As a solution, we propose
* The five.localsitemanager code should *NOT* be dealing with acquisition,
it should be restricted to setting up a bases chain for persistent
components that does parent lookup.
* getToolByName deprecation should be reverted. Its internal mechanisms
should be kept the same as in the current CMF 2.1 release, using
getUtility, *AND* it should be the one doing acquisition wrapping.
So instead of doing implicit magic in the getUtility call stack, let's be
explicit, while still allowing the flexibility that registered components
provide. Which in turn results in an untouched zope3 getUtility execution
path for looking up utilities.
getToolByName should return acquisition wrapped utilities via name
mapping, and become un-deprecated. Context for wrapping would be the
context passed as an argument to getToolByName, as it always has been. It
would issue deprecation warnings when it has to lookup a tool via aq_get
instead of getUtility. The mechanism for registering tool names would
raise an error when anyone tries to register a component which does not
The getToolByInterfaceName method would no longer be necessary as
getToolByName can be called from restricted code. However if needed it
could remain and use the result of getSite() as the context for wrapping
the tool resulting from the utility lookup.
These are good arguments, I think. I'm not sure anyone quite could've
predicted the trouble we had with five.lsm (is it even needed anymore if
all of this is acted upon?), so it's good to get some fresh thinking on
The one thing I don't see here explicitly is the forward migration path.
I think it would be worthwhile to work towards a future where we have no
tools or other programmer-support-mechanisms in content space. I suspect
that all context-less tools today could be rewritten to be regular
global utilities, and all persitence-needing tools could be changed to
be standard local utilities that if needed did getUtility(ISiteRoot) to
get hold of the site root and acquire things from there (except, how
does the site root then get an acquisition context? Maybe it doesn't
However, if we still promote and use getToolByName() then people will
not start using getUtility() and importing interfaces and we will find
it more difficult to deprecate (eventually) and then move to a world
where we can have real utilities (where possible/sensible).
Going back to square one, the reason why we (and I'm very guilty in
this) pushed for something at the framework level (spawning five.lsm)
was that originally we ended up with calling code needing to do:
>>> from Products.CMFCore.interfaces import IWorkflowTool
>>> from zope.component import getUtility
>>> wftool = getUtility(IWorkflowTool).__of__(context)
Such explicit wrapping is black magic voodoo to most people and would
probably lead to lots of hard-to-debug errors. Requiring people to know
*when* to wrap and when it's not necessary is tantamount to requiring
them to know the implementation details of each tool.
I would agree, though, that it's not worth "breaking" the way local
component registries work in Zope 3 by imposing arbitrary acquisition on
them if that is indeed what we're doing. I don't think it was anyone's
intention to do so, and the five.lsm implementation was never 100%
finished was it?
One thing I'd like to ask, is that someone asks Philipp (I've CC'd him,
since I know he's not reading lists in detail right now) for comment,
since he as usual had various useful insights into the original
discussion on this.
We don't mean to belittle the hard work that anyone has put into this so
far, and we hope this is received in the spirit that it is intended. We
are willing to implement this if we can reach some consensus that this is
the right thing to do.
This is the part of the email I like the most :)
It's a bit scary to have to revert the hundreds of changes that have
been made to the Plone 3.0 codebase and probably hundreds more to the
CMF codebase to move to getUtility, though.
Zope-CMF maillist - Zope-CMF@lists.zope.org
See http://collector.zope.org/CMF for bug reports and feature requests