[Checkins]
SVN: five.localsitemanager/trunk/src/five/localsitemanager/
Basic nested site functionality in place. Needs more tests.
Rocky Burt
rocky at serverzen.com
Thu Feb 22 13:35:54 EST 2007
Log message for revision 72766:
Basic nested site functionality in place. Needs more tests.
Changed:
U five.localsitemanager/trunk/src/five/localsitemanager/__init__.py
A five.localsitemanager/trunk/src/five/localsitemanager/configure.zcml
U five.localsitemanager/trunk/src/five/localsitemanager/localsitemanager.txt
-=-
Modified: five.localsitemanager/trunk/src/five/localsitemanager/__init__.py
===================================================================
--- five.localsitemanager/trunk/src/five/localsitemanager/__init__.py 2007-02-22 18:35:11 UTC (rev 72765)
+++ five.localsitemanager/trunk/src/five/localsitemanager/__init__.py 2007-02-22 18:35:54 UTC (rev 72766)
@@ -1,4 +1,6 @@
+from Acquisition import aq_parent, aq_base
from zope.component.globalregistry import base
+from zope.traversing.interfaces import IContainmentRoot
from zope.app.component.interfaces import ISite
from zope.component.persistentregistry import PersistentComponents
from Products.Five.component.interfaces import IObjectManagerSite
@@ -19,4 +21,70 @@
obj.setSiteManager(components)
def make_objectmanager_site(obj):
+ """Just a bit of sugar coating to make an unnofficial objectmanager
+ based site.
+ """
+
make_site(obj, IObjectManagerSite)
+
+def get_parent(obj):
+ """Returns the container the object was traversed via. This
+ is a version of zope.traversing.api.getParent that is designed to
+ handle acquisition as well.
+
+ Returns None if the object is a containment root.
+ Raises TypeError if the object doesn't have enough context to get the
+ parent.
+ """
+
+ if IContainmentRoot.providedBy(obj):
+ return None
+
+ parent = getattr(obj, '__parent__', None)
+ if parent is not None:
+ return parent
+
+ parent = aq_parent(obj)
+ if parent is not None:
+ return parent
+
+ raise TypeError("Not enough context information to get parent", obj)
+
+
+def find_next_sitemanager(site):
+ """Find the closest sitemanager that is not the specified site's
+ sitemanager.
+ """
+
+ container = site
+ sm = None
+ while sm is None:
+ if IContainmentRoot.providedBy(container):
+ # we're the root site, return None
+ return None
+
+ try:
+ container = get_parent(container)
+ except TypeError:
+ # there was not enough context; probably run from a test
+ return None
+
+ if ISite.providedBy(container):
+ sm = container.getSiteManager()
+ return sm
+
+def update_sitemanager_bases(site):
+ """Formulate the most appropriate __bases__ value for a site's site manager
+ by asking find_next_sitemanager what the next appropriate site manager
+ is. After this call, the __bases__ is guaranteed to have one and only
+ one value in the __bases__ list/tuple.
+ """
+
+ next = find_next_sitemanager(site)
+ if next is None:
+ next = base
+ sm = site.getSiteManager()
+ sm.__bases__ = (next, )
+
+def update_sitemanager_bases_handler(site, event):
+ update_sitemanager_bases(site)
Added: five.localsitemanager/trunk/src/five/localsitemanager/configure.zcml
===================================================================
--- five.localsitemanager/trunk/src/five/localsitemanager/configure.zcml 2007-02-22 18:35:11 UTC (rev 72765)
+++ five.localsitemanager/trunk/src/five/localsitemanager/configure.zcml 2007-02-22 18:35:54 UTC (rev 72766)
@@ -0,0 +1,11 @@
+<configure
+ xmlns="http://namespaces.zope.org/zope"
+ xmlns:browser="http://namespaces.zope.org/browser">
+
+ <subscriber
+ for="zope.app.component.interfaces.ISite
+ zope.app.container.interfaces.IObjectMovedEvent"
+ handler=".update_sitemanager_bases_handler"
+ />
+
+</configure>
Modified: five.localsitemanager/trunk/src/five/localsitemanager/localsitemanager.txt
===================================================================
--- five.localsitemanager/trunk/src/five/localsitemanager/localsitemanager.txt 2007-02-22 18:35:11 UTC (rev 72765)
+++ five.localsitemanager/trunk/src/five/localsitemanager/localsitemanager.txt 2007-02-22 18:35:54 UTC (rev 72766)
@@ -99,3 +99,61 @@
<Adapter TestAdapter adapting "foo">
>>> ITestAdapter(Foo('foo'))
<Adapter TestAdapter adapting "foo">
+
+Nested Sites
+------------
+
+Whenever a component is queried using the component registry, the active
+component registry (ie site manager) needs to be smart enough to check
+all *parent* component registries as well.
+
+Implementation-wise this means that each component registry needs to have
+an appropriate ``__bases__`` attribute configured that is aware of
+containment and (in the case of Zope 2) acquisition to some respect.
+
+Start by creating some nested sites.
+
+ >>> from five.localsitemanager import update_sitemanager_bases
+
+ >>> folder1 = Folder('folder1')
+ >>> make_objectmanager_site(folder1)
+ >>> update_sitemanager_bases(folder1)
+
+ >>> folder1_1 = Folder('folder1_1')
+ >>> make_objectmanager_site(folder1_1)
+ >>> ignored = folder1._setObject('folder1_1', folder1_1)
+ >>> folder1_1 = folder1['folder1_1']
+ >>> update_sitemanager_bases(folder1_1)
+
+Now we check the actual next-site-lookup logic to make sure it's working.
+
+ >>> from five.localsitemanager import find_next_sitemanager, get_parent
+
+Needed to implement our own get_parent (zope3 has one) that is acquisition
+aware.
+
+ >>> get_parent(folder1)
+ Traceback (most recent call last):
+ ...
+ TypeError: ('Not enough context...
+
+ >>> get_parent(folder1_1)
+ <Folder at folder1>
+
+Any logic that sets up a site manager's ``__bases__`` will use the
+``find_next_sitemanager`` function to figure out the next closest place
+to look.
+
+ >>> find_next_sitemanager(folder1) is None
+ True
+
+ >>> find_next_sitemanager(folder1_1)
+ <PersistentComponents ...>
+
+Now we make sure that that the ``__bases__`` have been setup appropriately.
+
+ >>> folder1.getSiteManager().__bases__
+ (<BaseGlobalComponents base>,)
+
+ >>> folder1_1.getSiteManager().__bases__
+ (<PersistentComponents ...>,)
More information about the Checkins
mailing list