[Zope3-checkins] CVS: Zope3/src/zope/app/services - factories.py:1.1 configuration.py:1.33 configure.zcml:1.35

Guido van Rossum guido@python.org
Wed, 11 Jun 2003 13:25:03 -0400


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

Modified Files:
	configuration.py configure.zcml 
Added Files:
	factories.py 
Log Message:
Use custom fssync adapters for various configuration objects (Service,
Connection, Cache and Utility configurations to be precise).  This
goes part of the way to using relative paths to enable checkin a site
management folder in under a different name, which is needed for
bundles.

Also did a little bit of cleanup.


=== Added File Zope3/src/zope/app/services/factories.py ===
##############################################################################
#
# Copyright (c) 2003 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""A collection of factory functions for various configuration classes.

See method factory() in class ComponentConfigurationAdapter in file
configuration.py.

The functions here may create invalid objects; a subsequent setBody()
call to the adapter's setBody() method will make the object valid.

$Id: factories.py,v 1.1 2003/06/11 17:25:02 gvanrossum Exp $
"""

def CacheConfiguration():
    from zope.app.service.cache import CacheConfiguration
    return CacheConfiguration("", "") # name, componentPath

def ConnectionConfiguration():
    from zope.app.service.connection import ConnectionConfiguration
    return ConnectionConfiguration("", "") # name, componentPath

def ServiceConfiguration():
    from zope.app.services.service import ServiceConfiguration
    return ServiceConfiguration("", "") # name, componentPath

def UtilityConfiguration():
    from zope.app.services.utility import UtilityConfiguration
    return UtilityConfiguration("", None, "") # name, interface, componentPath


=== Zope3/src/zope/app/services/configuration.py 1.32 => 1.33 ===
--- Zope3/src/zope/app/services/configuration.py:1.32	Sat Jun  7 02:37:28 2003
+++ Zope3/src/zope/app/services/configuration.py	Wed Jun 11 13:25:02 2003
@@ -17,6 +17,12 @@
 """
 __metaclass__ = type
 
+
+# XXX Backward Compatibility for pickles
+import sys
+sys.modules['zope.app.services.configurationmanager'
+            ] = sys.modules['zope.app.services.configuration']
+
 from persistence import Persistent
 from zope.interface import implements
 from zope.app.interfaces.annotation import IAnnotations
@@ -526,40 +532,54 @@
         return v
 
     def get(self, key, default=None):
-        "See Interface.Common.Mapping.IReadMapping"
+        "See IReadMapping"
         for k, v in self._data:
             if k == key:
                 return v
         return default
 
     def __contains__(self, key):
-        "See Interface.Common.Mapping.IReadMapping"
+        "See IReadMapping"
         return self.get(key) is not None
 
 
     def keys(self):
-        "See Interface.Common.Mapping.IEnumerableMapping"
+        "See IEnumerableMapping"
         return [k for k, v in self._data]
 
     def __iter__(self):
         return iter(self.keys())
 
     def values(self):
-        "See Interface.Common.Mapping.IEnumerableMapping"
+        "See IEnumerableMapping"
         return [v for k, v in self._data]
 
     def items(self):
-        "See Interface.Common.Mapping.IEnumerableMapping"
+        "See IEnumerableMapping"
         return self._data
 
     def __len__(self):
-        "See Interface.Common.Mapping.IEnumerableMapping"
+        "See IEnumerableMapping"
         return len(self._data)
 
     def setObject(self, key, object):
         "See IWriteContainer"
         self._next += 1
-        key = str(self._next)
+        if key:
+            if key in self:
+                raise DuplicationError("key is already registered", key)
+            try:
+                n = int(key)
+            except ValueError:
+                pass
+            else:
+                if n > self._next:
+                    self._next = n
+        else:
+            key = str(self._next)
+            while key in self:
+                self._next += 1
+                key = str(self._next)
         self._data += ((key, object), )
         return key
 
@@ -666,7 +686,89 @@
     getConfigurationManager = ContextMethod(getConfigurationManager)
 
 
-# XXX Backward Compatibility for pickles
-import sys
-sys.modules['zope.app.services.configurationmanager'
-            ] = sys.modules['zope.app.services.configuration']
+from zope.xmlpickle import dumps, loads
+from zope.app.interfaces.fssync import IObjectFile
+from zope.app.fssync.classes import ObjectEntryAdapter
+
+class ComponentConfigurationAdapter(ObjectEntryAdapter):
+
+    """Fssync adapter for ComponentConfiguration objects and subclasses.
+
+    This is fairly generic -- it should apply to most subclasses of
+    ComponentConfiguration.  But in order for it to work for a
+    specific subclass (say, UtilityConfiguration), you have to (a) add
+    an entry to configure.zcml, like this:
+
+        <fssync:adapter
+            class=".utility.UtilityConfiguration"
+            factory=".configuration.ComponentConfigurationAdapter"
+            />
+
+    and (b) add a function to factories.py, like this:
+
+        def UtilityConfiguration():
+            from zope.app.services.utility import UtilityConfiguration
+            return UtilityConfiguration("", None, "")
+
+    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>).
+    """
+
+    implements(IObjectFile)
+
+    def factory(self):
+        """See IObjectEntry."""
+        name = self.context.__class__.__name__
+        return "zope.app.services.factories." + name
+
+    def getBody(self):
+        """See IObjectEntry."""
+        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]
+        return dumps(ivars)
+
+    def setBody(self, body):
+        """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]) + "/"


=== Zope3/src/zope/app/services/configure.zcml 1.34 => 1.35 ===
--- Zope3/src/zope/app/services/configure.zcml:1.34	Thu Jun  5 08:03:17 2003
+++ Zope3/src/zope/app/services/configure.zcml	Wed Jun 11 13:25:02 2003
@@ -516,6 +516,26 @@
     factory=".module.ModuleAdapter"
     />
 
+<fssync:adapter
+    class=".cache.CacheConfiguration"
+    factory=".configuration.ComponentConfigurationAdapter"
+    />
+
+<fssync:adapter
+    class=".connection.ConnectionConfiguration"
+    factory=".configuration.ComponentConfigurationAdapter"
+    />
+
+<fssync:adapter
+    class=".service.ServiceConfiguration"
+    factory=".configuration.ComponentConfigurationAdapter"
+    />
+
+<fssync:adapter
+    class=".utility.UtilityConfiguration"
+    factory=".configuration.ComponentConfigurationAdapter"
+    />
+
 <adapter 
   for="zope.app.interfaces.services.service.IServiceManager"
   provides="zope.app.interfaces.file.IDirectoryFactory"