[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