[Zope-CMF] Re: getToolByName depreciation, getUtility, and five.lsm

Philipp von Weitershausen philipp at weitershausen.de
Thu Mar 29 00:53:44 EDT 2007

Martin Aspeli wrote:
>> 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  support Acquisition.
>> 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.


> The one thing I don't see here explicitly is the forward migration path. 

Make tools not depend on acquisition and you get can start looking them 
up using getUtility. This will take time, so I'd be ok if for now we 
can't use getUtility right away (unless you're willing to do manual 

> I think it would be worthwhile to work towards a future where we have no 
> tools or other programmer-support-mechanisms in content space.

At least new stuff can be Zope 3-style already.

> 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 
> need to?).

Well, ideally we'll be able to model containment relationships using 
__parent__ in Zope 2 as well...

> 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).

I can say from personal experience that deprecating less in more time is 
easier on the people and on yourself :).

> 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.

(Welcome to Acquisition!)

> 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.

getToolByName sounds like a sensible abstraction, don't you think?

>> 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.

Why, you guys have tests, dontcha? :)

http://worldcookery.com -- Professional Zope documentation and training

More information about the Zope-CMF mailing list