[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