[Zope-CMF] [CMF 2.1] PersistentComponents is not enough

Philipp von Weitershausen philipp at weitershausen.de
Mon Jan 8 09:40:09 EST 2007


Hi there,

others and I have been pushing the usage of local components in Five. As 
a result it looks like the CMF 2.1 will use the CA to look up its tools. 
Woohoo! (Kudos to Jens and all the others!)

There's one problem with all this which I admit I have failed to 
communicate better (certain key players know this for some time, but 
haven't spoken up either):

Using PersistentComponents() as the component registry (a.k.a. site 
manager) for local sites isn't enough. That's because it doesn't 
understand about containment hierarchies. Imagine this folder hierarchy:

/root_site/
+  cmf_site/
    +  somefolder/
    +  anotherfolder/
    +  sitefolder/
    +  +   stuff_in_here

"cmf_site" is obviously a site. Let's say "root_site" and "sitefolder" 
are also sites (yes, Zope3-style sites can be nested). That's not to say 
that sitefolder is another CMF Site, it's just a Zope3-style ISite 
(regular zope 2 folders can be sites in Zope 2.10).

You would expect component lookup at "stuff_in_here" to
* first lookup stuff in "sitefolder",
* then in "cmf_site",
* then in "root_site",
* and finally in the global registry

If you use PersistentComponents() this won't automatically happen!

Component registries have an __bases__ attribute which contains the next 
site manager in the in the lookup chain. Currently, we stub this out by 
simply putting the global registry in __bases__ and nothing else. The 
code that does this looks like that (this is from Jens's branch):

       components = PersistentComponents()
       components.__bases__ = (base,) # base is the global registry
       site.setSiteManager(components)

With such component registries in place at each "sitefolder", "cmf_site" 
and "root_site", component lookup will never cascade the way we 
intiutively would expect it from acquisition.


So, how do we fix this?

Obviously, the __bases__ attribute of site_folder's component registry 
must contain cmf_site's component registry and NOT the global one. 
cmf_site's registry in turn must refer to root_site's registry etc. 
Simple enough. It's really all about setting the right __bases__.

The tricky part is that this whole "linked list" of site managers needs 
to be updated when

* new sites are created somewhere in a hiearchy (e.g. root_folder used 
to be not a site, and now you turn it into one, then cmf_site's 
__bases__ should be updated to refer to the root_folder registry instead 
of the global one)

* sites get moved around, e.g. to places where you have a site higher in 
your parent hierarchy.

In Zope 3 already has code that deals with those things. It's a subclass 
of PersistentComponents called LocalSiteManager 
(zope.app.component.site). It figures __bases__ out itself based on the 
containment hierarchy (in Zope 3 that's __parent__).

LocalSiteManager is also a container (similar to a folder) so that local 
persistent components can be placed inside it instead of in the site 
object itself which normally contains only content objects. Usually the 
URL name of the site manager is ++etc++site, e.g. /cmf_site/++etc++site 
would be the site manager of cmf_site.

We need a LocalSiteManager implementation for Zope 2 (mostly because of 
the __bases__ thing, but perhaps also because we then have a designated 
place for local components instead of the portal root).

The Zope 2 version of LocalSiteManager should subclass 
PersistentComponents and then use Zope3's LocalSiteManager's approach to 
update __bases__ in the above mentioned cases. Zope 3's LocalSiteManager 
code contains some cruft that isn't needed in Zope 2. We really only 
need the __bases__ stuff (part of which is a subscriber for 
ObjectMovedEvent which needs to be adapted for Zope 2 as well). The most 
obvious difference is that the Zope 2 version of LocalSiteManager should 
use acquisition instead of __parent__ pointers to determine the 
containment hierarchy.

As a bonus, the Zope 2 LocalSiteManager could also mix in ObjectManager.


Since Five is feature-frozen and new stuff should be added in Python 
packages anyway, my suggestion is to put this thing into a 
five.localsitemanager package which would then be used by CMF 2.1, Plone 
3, etc.. It could possibly be included into the Zope 2.11 release.

I'd like to avoid making a Five 1.6.


Philipp


-- 
http://worldcookery.com -- Professional Zope documentation and training
2nd edition of Web Component Development with Zope 3 is now shipping!



More information about the Zope-CMF mailing list