[Zope-CVS] CVS: Products/Ape/lib/apelib/zope2 - apeconf.xml:1.1.2.1 baseconf.xml:1.1.2.3 classifier.py:1.2.2.1 fsmapper.py:1.2.2.2 ofsserial.py:1.2.2.2

Shane Hathaway shane@zope.com
Mon, 7 Jul 2003 18:59:39 -0400


Update of /cvs-repository/Products/Ape/lib/apelib/zope2
In directory cvs.zope.org:/tmp/cvs-serv2793/zope2

Modified Files:
      Tag: ape-newconf-branch
	baseconf.xml classifier.py fsmapper.py ofsserial.py 
Added Files:
      Tag: ape-newconf-branch
	apeconf.xml 
Log Message:
Implemented XML-based configuration.  The filesystem tests pass.

Used an experimental approach for mixing configuration from multiple sources.
Take a look at zope2/apeconf.xml.


=== Added File Products/Ape/lib/apelib/zope2/apeconf.xml ===
<?xml version="1.0"?>

<configuration>

<!-- Root mapper -->

<mapper name="zope2" class="Persistence.PersistentMapping">
 <serializer name="root_items"
   factory="apelib.zodb3.serializers.BasicPersistentMapping" />
 <serializer name="roll_call" factory="apelib.zodb3.serializers.RollCall" />
 <variant name="filesystem">
  <classifier factory="apelib.zope2.classifier.MetaTypeClassifier">
   <gateway factory="apelib.fs.classification.FSClassificationSection" />
  </classifier>
  <keygen factory="apelib.core.keygen.PathKeychainGenerator" />
  <gateway name="root_items" factory="apelib.zope2.ofsserial.ReadOnlyRoot"
    param="/" />
 </variant>
</mapper>

<!-- Abstract mappers -->

<mapper name="base" class="none">
 <serializer name="id" order="a"
   factory="apelib.zope2.ofsserial.IdAttribute" />
 <serializer name="modtime"
   factory="apelib.zodb3.serializers.ModTimeAttribute" />
 <serializer name="security"
   factory="apelib.zope2.security.SecurityAttributes" />
 <serializer name="remainder" order="z"
   factory="apelib.zodb3.serializers.RemainingState" />
 <variant name="filesystem">
  <gateway name="id" factory="apelib.fs.structure.FSAutoId" />
  <gateway name="modtime" factory="apelib.fs.structure.FSModTime" />
  <gateway name="remainder" factory="apelib.fs.properties.FSSectionData"
    param="remainder" />
  <gateway name="security" factory="apelib.fs.security.FSSecurityAttributes" />
 </variant>
</mapper>

<mapper name="base_p" class="none" extends="base">
 <serializer name="properties"
   factory="apelib.zope2.ofsserial.OFSProperties" />
 <variant name="filesystem">
  <gateway name="properties" factory="apelib.fs.properties.FSProperties" />
 </variant>
</mapper>

<!-- Reusable serializers and gateways -->

<serializer name="folder_items" factory="apelib.zope2.ofsserial.FolderItems" />

<serializer name="optional_properties"
  factory="apelib.zope2.ofsserial.OptionalOFSProperties" />

<variant name="filesystem">
 <gateway name="fs_binary_data" factory="apelib.fs.structure.FSFileData"
   param="binary" />
 <gateway name="fs_text_data" factory="apelib.fs.structure.FSFileData"
   param="text" />
 <gateway name="fs_dir_items" factory="apelib.fs.structure.FSDirectoryItems" />
</variant>

<!-- Mappers for particular content types -->

<mapper name="OFS.Folder.Folder" extends="base_p" parent="zope2">
 <serializer name="items" use="folder_items" />
 <use-for fallback="directory" />
 <variant name="filesystem">
  <gateway name="items" use="fs_dir_items" />
 </variant>
</mapper>

<mapper name="OFS.Image.File" extends="base_p" parent="zope2">
 <serializer name="data" factory="apelib.zope2.ofsserial.FilePData" />
 <use-for fallback="file" />
 <option name="content_type_attr" value="content_type" />
 <variant name="filesystem">
  <gateway name="data" use="fs_binary_data" />
 </variant>
</mapper>

<mapper name="OFS.Image.Image" extends="OFS.Image.File" parent="zope2">
 <use-for extensions=".gif .jpg .jpeg .png" />
 <option name="content_type_attr" value="content_type" />
</mapper>

<mapper name="Products.PageTemplates.ZopePageTemplate.ZopePageTemplate"
  extends="base_p" parent="zope2">
 <serializer name="text" factory="apelib.core.serializers.StringDataAttribute"
  param="_text" />
 <use-for extensions=".html .htm .zpt .pt" />
 <variant name="filesystem">
  <gateway name="text" use="fs_text_data" />
 </variant>
</mapper>

<mapper name="OFS.DTMLMethod.DTMLMethod" extends="base" parent="zope2">
 <serializer name="text" factory="apelib.core.serializers.StringDataAttribute"
  param="raw" />
 <use-for extensions=".dtml" />
 <variant name="filesystem">
  <gateway name="text" use="fs_text_data" />
 </variant>
</mapper>

<mapper name="OFS.DTMLMethod.DTMLDocument"
  extends="OFS.DTMLMethod.DTMLMethod" parent="zope2">
 <serializer name="properties" enabled="false" />
</mapper>

<mapper name="Products.ZSQLMethods.SQL.SQL" extends="base" parent="zope2">
 <serializer name="properties"
   factory="apelib.zope2.scripts.ZSQLMethodPropertiesSerializer" />
 <serializer name="text"
   factory="apelib.zope2.scripts.ZSQLMethodSerializer" />
 <use-for extensions=".sql" />
 <variant name="filesystem">
  <gateway name="properties" factory="apelib.fs.properties.FSProperties"
    param="ZSQL Properties" />
  <gateway name="text" use="fs_text_data" />
 </variant>
</mapper>

<mapper name="Products.PythonScripts.PythonScript.PythonScript"
  extends="base" parent="zope2">
 <serializer name="body"
   factory="apelib.zope2.scripts.PythonScriptSerializer" />
 <use-for extensions=".py" />
 <variant name="filesystem">
  <gateway name="body" use="fs_text_data" />
 </variant>
</mapper>

<mapper name="AccessControl.User.UserFolder" extends="base" parent="zope2">
 <serializer name="data"
   factory="apelib.zope2.security.UserFolderSerializer" />
 <variant name="filesystem">
  <gateway name="data" factory="apelib.fs.security.FSUserList" />
 </variant>
</mapper>

<mapper name="anyfolder" class="any" extends="base_p" parent="zope2">
 <serializer name="properties" use="optional_properties" />
 <serializer name="items" use="folder_items" />
 <use-for fallback="folderish_object" />
 <variant name="filesystem">
  <gateway name="items" use="fs_dir_items" />
 </variant>
</mapper>

<mapper name="anyfile" class="any" extends="base_p" parent="zope2">
 <serializer name="properties" use="optional_properties" />
 <use-for fallback="fileish_object" />
 <variant name="filesystem">
  <gateway name="remainder" use="fs_binary_data" />
 </variant>
</mapper>

<mapper name="OFS.Application.Application" extends="base_p" parent="zope2">
 <serializer name="items" use="folder_items" />
 <serializer name="id" enabled="false" />
 <gateway name="id" enabled="false" />
 <variant name="filesystem">
  <gateway name="items" use="fs_dir_items" />
  <use-for key="/" />
 </variant>
</mapper>

<mapper name="anyfile">
 <use-for class="Products.CMFCore.SkinsTool.SkinsTool" />
 <use-for class="App.ApplicationManager.ApplicationManager" />
</mapper>

</configuration>



=== Products/Ape/lib/apelib/zope2/baseconf.xml 1.1.2.2 => 1.1.2.3 ===
--- Products/Ape/lib/apelib/zope2/baseconf.xml:1.1.2.2	Thu Jun 26 00:35:08 2003
+++ Products/Ape/lib/apelib/zope2/baseconf.xml	Mon Jul  7 18:59:32 2003
@@ -15,11 +15,11 @@
    factory="apelib.zodb3.serializers.ModTimeAttribute" />
  <serializer name="security"
    factory="apelib.zope2.security.SecurityAttributes" />
- <serializer name="remainder" final="true"
+ <serializer name="remainder" order="final"
    factory="apelib.zodb3.serializers.RemainingState" />
 </mapper>
 
-<mapper name="base_p" class="none" extends="base" parent="zope2">
+<mapper name="base_p" class="none" extends="base">
  <serializer name="properties"
    factory="apelib.zope2.ofsserial.OFSProperties" />
 </mapper>


=== Products/Ape/lib/apelib/zope2/classifier.py 1.2 => 1.2.2.1 ===
--- Products/Ape/lib/apelib/zope2/classifier.py:1.2	Wed Jun  4 11:59:14 2003
+++ Products/Ape/lib/apelib/zope2/classifier.py	Mon Jul  7 18:59:32 2003
@@ -44,105 +44,66 @@
     """
     __implements__ = IClassifier
 
-    # flag values (constant)
-    CONTENT_TYPE_ATTR = 1
-
 
     def __init__(self, gw=None):
         self.gw = gw
-        self.key_to_res = {}
-        self.ext_to_mt = {}
-        self.mt_to_ext = {}
-        self.fmt_to_mt = {}
-        self.mt_to_mapper = {}
-        self.flags = {}
-
-
-    def setGateway(self, gw):
-        self.gw = gw
-
-
-    def register(self, meta_type, mapper_name, extensions=()):
-        """Registers a mapper to handle a Zope meta_type."""
-        for ext in extensions:
-            if not ext.startswith('.'):
-                ext = '.' + ext
-            ext = ext.lower()
-            self.ext_to_mt[ext] = meta_type
-        if extensions:
-            self.mt_to_ext[meta_type] = extensions[0]
-        self.mt_to_mapper[meta_type] = mapper_name
-
-
-    def registerKey(self, meta_type, mapper_name, key):
-        """Registers a mapper to handle a specific path.
-
-        For example, the application object mapper usually handles
-        the path '/'.
-        """
-        self.key_to_res[key] = ({'meta_type': meta_type}, mapper_name)
-
-
-    def registerDefaultLoader(self, meta_type, mapper_name, isdir):
-        """Registers a mapper to load unknown files or directories."""
-        if isdir:
-            ext = '<directory>'
+        self.key_to_mapper = {}
+        self.class_to_mapper = {}
+        self.ext_to_mapper = {}
+        self.fallback_to_mapper = {}
+        self.options = {}  # { (mapper_name, option) -> value }
+
+
+    def register(self, attr, value, mapper_name):
+        if attr == 'key':
+            self.key_to_mapper[value] = mapper_name
+        elif attr == 'extension':
+            self.ext_to_mapper[value] = mapper_name
+        elif attr == 'class':
+            self.class_to_mapper[value] = mapper_name
+        elif attr == 'fallback':
+            assert value in ('directory', 'file',
+                             'folderish_object', 'fileish_object'), value
+            self.fallback_to_mapper[value] = mapper_name
         else:
-            ext = '<file>'
-        self.ext_to_mt[ext] = meta_type
-        self.mt_to_mapper[meta_type] = mapper_name
-
-
-    def registerDefaultStorage(self, meta_type, mapper_name, folderish):
-        """Registers a mapper to store unknown objects."""
-        if folderish:
-            fmt = 'folder'
-        else:
-            fmt = 'file'
-        self.fmt_to_mt[fmt] = meta_type
-        self.mt_to_mapper[meta_type] = mapper_name
-
+            raise ValueError('Unknown attr: %s' % attr)
 
-    def setFlags(self, mapper_name, flags):
-        """Sets flags associated with a certain mapper."""
-        self.flags[mapper_name] = flags
 
+    def setOption(self, mapper_name, option, value):
+        assert option in ('default_extension', 'content_type_attr'), option
+        self.options[(mapper_name, option)] = value
+            
 
     def classifyObject(self, value, keychain):
         """Chooses a mapper and classification for storing an object."""
-        res = self.key_to_res.get(keychain[-1])
-        if res is not None:
-            return res
-        mt = value.meta_type
-        mapper_name = self.mt_to_mapper.get(mt)
+        klass = value.__class__
+        class_name = '%s.%s' % (klass.__module__, klass.__name__)
+        classification = {'class_name': class_name}
+        mapper_name = self.key_to_mapper.get(keychain[-1])
+        if mapper_name is None:
+            mapper_name = self.class_to_mapper.get(class_name)
         if mapper_name is None:
             folderish = isinstance(value, ObjectManager)
-            # Store in a default format
+            # Store in a fallback format
             if folderish:
-                fmt = 'folder'
+                fallback = 'folderish_object'
             else:
-                fmt = 'file'
-            mt = self.fmt_to_mt.get(fmt)
-            if mt is None:
-                raise SerializationError(
-                    'No classification known for %s' % repr(keychain))
-            mapper_name = self.mt_to_mapper.get(mt)
-            if mapper_name is None:
-                raise SerializationError(
-                    'No mapper known for meta_type %s' % repr(mt))
-        klass = value.__class__
-        ci = '%s:%s' % (klass.__module__, klass.__name__)
-        classification = {'meta_type': mt, 'class_name': ci}
-
-        flags = self.flags.get(mapper_name, 0)
-        if flags and (flags & MetaTypeClassifier.CONTENT_TYPE_ATTR):
-            ct = str(getattr(aq_base(value), 'content_type', None))
-            if ct:
-                ext = fixed_extensions.get(ct)
-                if ext is None:
-                    ext = guess_extension(ct)
+                fallback = 'fileish_object'
+            mapper_name = self.fallback_to_mapper.get(fallback)
+            if mapper_name is not None:
+                # Force a particular mapper
+                classification['mapper_name'] = mapper_name
+        if mapper_name is None:
+            raise SerializationError(
+                'No mapper known for class %s' % repr(class_name))
+        cta = self.options.get((mapper_name, 'content_type_attr'))
+        if cta is not None:
+            ct = str(getattr(aq_base(value), cta, None))
+            ext = fixed_extensions.get(ct)
+            if ext is None:
+                ext = guess_extension(ct)
         else:
-            ext = self.mt_to_ext.get(mt)
+            ext = self.options.get((mapper_name, 'default_extension'))
         if ext:
             classification['extension'] = ext
 
@@ -151,35 +112,37 @@
 
     def classifyState(self, event):
         """Chooses a mapper and classification for loading an object."""
-        keychain = event.getKeychain()
-        res = self.key_to_res.get(keychain[-1])
-        if res is not None:
-            return res
         classification, serial = self.gw.load(event)
-        mt = classification.get('meta_type')
-        if mt is None:
+        class_name = classification.get('class_name')
+        mapper_name = classification.get('mapper_name')
+        if mapper_name is None:
+            mapper_name = self.key_to_mapper.get(event.getKey())
+        if mapper_name is None:
+            # bw compat: look for certain meta_types.
+            mt = classification.get('meta_type')
+            if mt == '(folderish object)':
+                mapper_name = self.fallback_to_mapper.get('folderish_object')
+            elif mt == '(fileish object)':
+                mapper_name = self.fallback_to_mapper.get('fileish_object')
+        if mapper_name is None and class_name is not None:
+            mapper_name = self.class_to_mapper.get(class_name)
+        if mapper_name is None:
             t = classification.get('node_type')
             if t == 'd':
                 # Directory
-                mt = self.ext_to_mt.get('<directory>', 'Folder')
+                mapper_name = self.fallback_to_mapper.get('directory')
             elif t == 'f':
                 # File
                 ext = classification.get('extension')
                 if ext:
                     if not ext.startswith('.'):
                         ext = '.' + ext
-                    mt = self.ext_to_mt.get(ext.lower())
-                if not mt:
-                    mt = self.ext_to_mt.get('<file>', 'File')
-            else:
-                raise DeserializationError(
-                    'No classification known for %s' % repr(keychain))
-            assert mt is not None
-            classification['meta_type'] = mt
-        mapper_name = self.mt_to_mapper.get(mt)
+                    mapper_name = self.ext_to_mapper.get(ext.lower())
+                if not mapper_name:
+                    mapper_name = self.fallback_to_mapper.get('file')
         if mapper_name is None:
             raise DeserializationError(
-                'No mapper known for meta_type %s' % repr(mt))
+                'No mapper known for class %s' % repr(class_name))
         return classification, mapper_name
 
 


=== Products/Ape/lib/apelib/zope2/fsmapper.py 1.2.2.1 => 1.2.2.2 ===
--- Products/Ape/lib/apelib/zope2/fsmapper.py:1.2.2.1	Tue Jun 24 17:38:44 2003
+++ Products/Ape/lib/apelib/zope2/fsmapper.py	Mon Jul  7 18:59:32 2003
@@ -23,7 +23,7 @@
 from apelib.zodb3.gateways import ReadOnlyItems
 
 
-def createAbstractMapper():
+def XXXcreateAbstractMapper():
     """Object mapper factory.
 
     Usage in database configuration file:
@@ -120,6 +120,18 @@
     root_mapper.checkConfiguration()
 
     return root_mapper
+
+
+def createAbstractMapper():
+    import os
+    from apelib.config.apeconf import makeComponentSystem
+    here = os.path.dirname(__file__)
+    filenames = (os.path.join(here, 'apeconf.xml'),)
+    vnames = ('filesystem', '')
+    cs = makeComponentSystem(filenames, vnames)
+    m = cs.get('mapper', 'zope2')
+    m.checkConfiguration(path='zope2')
+    return m
 
 
 def createMapper(basepath, **kw):


=== Products/Ape/lib/apelib/zope2/ofsserial.py 1.2.2.1 => 1.2.2.2 ===
--- Products/Ape/lib/apelib/zope2/ofsserial.py:1.2.2.1	Tue Jun 24 17:38:44 2003
+++ Products/Ape/lib/apelib/zope2/ofsserial.py	Mon Jul  7 18:59:32 2003
@@ -28,6 +28,9 @@
 from apelib.core.interfaces import ISerializer
 from apelib.core.schemas import FieldSchema, RowSequenceSchema
 from apelib.core.exceptions import SerializationError
+from apelib.core.serializers import OptionalSerializer
+from apelib.zodb3.gateways import ReadOnlyItems
+
 
 string_repr_types = {
     # Properties that are safe to render as strings for storage.
@@ -262,4 +265,17 @@
                 # Fall back to a default.
                 data = ''
             object._updateProperty(id, data)
+
+
+class ReadOnlyRoot(ReadOnlyItems):
+    """Zope 2 application root."""
+
+    def __init__(self, root_key):
+        ReadOnlyItems.__init__(self, {'Application': (str(root_key),)})
+
+
+class OptionalOFSProperties(OptionalSerializer):
+
+    def __init__(self):
+        OptionalSerializer.__init__(self, OFSProperties(), [])