[Zope3-checkins] CVS: Zope3/src/zope/app/services - configuration.py:1.34

Guido van Rossum guido@python.org
Thu, 12 Jun 2003 13:04:15 -0400


Update of /cvs-repository/Zope3/src/zope/app/services
In directory cvs.zope.org:/tmp/cvs-serv25618/services

Modified Files:
	configuration.py 
Log Message:
Use/allow relative paths in ComponentConfiguration subclasses.
Existing absolute paths will continue to work, but all newly created
ComponentConfiguration subclass instances will use a path relative to
the site management folder containing the configured object -- i.e.,
this is just the object's name.  Fixed all places where I've seen
absolute paths used.  (Still to do: use relative paths for references
*to* the configuration object as well; these occur in registries, and
are also used by the IUseConfigurable machinery and by dependencies.)


=== Zope3/src/zope/app/services/configuration.py 1.33 => 1.34 ===
--- Zope3/src/zope/app/services/configuration.py:1.33	Wed Jun 11 13:25:02 2003
+++ Zope3/src/zope/app/services/configuration.py	Thu Jun 12 13:03:44 2003
@@ -50,14 +50,14 @@
 from zope.app.interfaces.services.configuration import Unregistered
 from zope.app.interfaces.services.configuration import Registered, Active
 from zope.app.traversing import getRoot, getPath, traverse
-from zope.app.traversing import canonicalPath
 from zope.component import getAdapter, queryAdapter
 from zope.component import getServiceManager
 from zope.app.context import ContextWrapper
-from zope.context import ContextMethod, ContextDescriptor
+from zope.context import ContextMethod, ContextDescriptor, getWrapperContainer
 from zope.proxy import removeAllProxies
 from zope.security.checker import InterfaceChecker
 from zope.security.proxy import Proxy, trustedRemoveSecurityProxy
+from zope.proxy import getProxiedObject
 
 class ConfigurationStatusProperty(ContextDescriptor):
 
@@ -355,11 +355,17 @@
         self.permission = permission
 
     def implementationSummary(self):
-        return canonicalPath(self.componentPath)
+        return self.componentPath
 
     def getComponent(wrapped_self):
         service_manager = getServiceManager(wrapped_self)
 
+        # The user of the configuration object may not have permission
+        # to traverse to the component.  Yet they should be able to
+        # get it by calling getComponent() on a configuration object
+        # for which they do have permission.  What they get will be
+        # wrapped in a security proxy of course.  Hence:
+
         # We have to be clever here. We need to do an honest to
         # god unrestricted traveral, which means we have to
         # traverse from an unproxied object. But, it's not enough
@@ -369,9 +375,20 @@
         # traverses from there, so we need to make sure the
         # physical root isn't proxied.
 
-        # get the root and unproxy it.
+        path = wrapped_self.componentPath
+        # Get the root and unproxy it
         root = removeAllProxies(getRoot(service_manager))
-        component = traverse(root, wrapped_self.componentPath)
+        if path.startswith("/"):
+            # Absolute path
+            component = traverse(root, path)
+        else:
+            # Relative path.
+            # XXX We do a strange little dance because we want the
+            #     context to inherit the unproxied root, and this is
+            #     the only way to keep it.
+            ancestor = getWrapperContainer(getWrapperContainer(wrapped_self))
+            ancestor = traverse(root, getPath(ancestor))
+            component = traverse(ancestor, path)
 
         if wrapped_self.permission:
             if type(component) is Proxy:
@@ -712,11 +729,9 @@
 
     The file representation of a configuration object is an XML pickle
     for a modified version of the instance dict.  In this version of
-    the instance dict, the componentPath attribute is converted to a
-    path relative to the highest level site management folder
-    containing the configuration object, and the __annotations__
-    attribute is omitted, because annotations are already stored on
-    the filesystem in a different way (in @@Zope/Annotations/<file>).
+    the instance dict, the __annotations__ attribute is omitted,
+    because annotations are already stored on the filesystem in a
+    different way (in @@Zope/Annotations/<file>).
     """
 
     implements(IObjectFile)
@@ -731,9 +746,6 @@
         obj = removeAllProxies(self.context)
         ivars = {}
         ivars.update(obj.__getstate__())
-        cpname = "componentPath"
-        if cpname in ivars:
-            ivars[cpname] = self._make_relative_path(ivars[cpname])
         aname = "__annotations__"
         if aname in ivars:
             del ivars[aname]
@@ -743,32 +755,4 @@
         """See IObjectEntry."""
         obj = removeAllProxies(self.context)
         ivars = loads(body)
-        cpname = "componentPath"
-        if cpname in ivars:
-            ivars[cpname] = self._make_absolute_path(ivars[cpname])
         obj.__setstate__(ivars)
-
-    def _make_relative_path(self, apath):
-        if apath.startswith("/"):
-            prefix = self._get_prefix()
-            if prefix and apath.startswith(prefix):
-                apath = apath[len(prefix):]
-                while apath.startswith("/"):
-                    apath = apath[1:]
-        return apath
-
-    def _make_absolute_path(self, rpath):
-        if not rpath.startswith("/"):
-            prefix = self._get_prefix()
-            if prefix:
-                rpath = prefix + rpath
-        return rpath
-
-    def _get_prefix(self):
-        parts = getPath(self.context).split("/")
-        try:
-            i = parts.index("++etc++site")
-        except ValueError:
-            return None
-        else:
-            return "/".join(parts[:i+2]) + "/"