[Zope-CVS] CVS: Products/Ape/lib/apelib/config - apeconf.py:1.5 common.py:1.3 minitables.py:NONE

Shane Hathaway shane at zope.com
Mon Feb 2 10:07:48 EST 2004


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

Modified Files:
	apeconf.py common.py 
Removed Files:
	minitables.py 
Log Message:
Moved ape-0_8-branch to the HEAD.

>From CHANGES.txt:

- Major restructuring to reduce the number of concepts in
  Ape. Keychains and keys have been replaced with simple string OIDs.
  There is now a flat namespace of mappers instead of a tree.  Only
  one classifier and one OID generator are used in any object
  database.

- The ZODB root object is now stored on the filesystem.


=== Products/Ape/lib/apelib/config/apeconf.py 1.4 => 1.5 ===
--- Products/Ape/lib/apelib/config/apeconf.py:1.4	Thu Aug 14 16:17:00 2003
+++ Products/Ape/lib/apelib/config/apeconf.py	Mon Feb  2 10:07:17 2004
@@ -17,17 +17,14 @@
 """
 from __future__ import nested_scopes
 
-from apelib.core.mapper import Mapper
+from apelib.core.mapper import Mapper, MapperConfiguration
 from apelib.core.serializers import CompositeSerializer, AnyObjectSerializer
 from apelib.core.gateways import CompositeGateway
-from apelib.core.interfaces import IDatabaseInitializer
+from apelib.core.interfaces import IDatabaseInitializer, ConfigurationError
 
-from minitables import Table, TableSchema
+from apelib.zodb3.zodbtables import Table, TableSchema
 from common import Directive, DirectiveReader, ComponentSystem
 
-class AssemblyError(Exception):
-    """Error while assembling components"""
-
 
 class MapperDeclaration(Directive):
     schema = TableSchema()
@@ -37,14 +34,14 @@
 class MapperAttribute(Directive):
     schema = TableSchema()
     schema.addColumn('mapper_name', primary=1)
-    # Attribute names: 'class', 'parent', 'extends'
+    # Attribute names: 'class', 'extends', 'register-class'
     schema.addColumn('name', primary=1, indexed=1)
     schema.addColumn('value')
 
 
 class ComponentDefinition(Directive):
     schema = TableSchema()
-    # comptypes: 'serializer', 'gateway', 'classifier', 'keygen'
+    # comptypes: 'serializer', 'gateway', 'classifier', 'oid_generator'
     schema.addColumn('comptype', primary=1)
     schema.addColumn('name', primary=1)
     schema.addColumn('producer')
@@ -54,20 +51,12 @@
     schema = TableSchema()
     schema.addColumn('mapper_name', primary=1)
     schema.addColumn('comptype', primary=1)
-    schema.addColumn('producer')
-
-
-class MapperCompositeComponent(Directive):
-    schema = TableSchema()
-    schema.addColumn('mapper_name', primary=1)
-    schema.addColumn('comptype', primary=1)
     schema.addColumn('name', primary=1)
     schema.addColumn('producer')
     schema.addColumn('order')
 
 
-class MapperRegistration(Directive):
-    # Contains a use-for directive
+class MapperUseFor(Directive):
     schema = TableSchema()
     schema.addColumn('mapper_name', primary=1)
     schema.addColumn('attr', primary=1)
@@ -164,33 +153,38 @@
         mapper_name = str(attrs['name'])
         vars['mapper_name'] = mapper_name
         d.append(MapperDeclaration(source, mapper_name))
-        for key in ('class', 'parent', 'extends'):
+        for key in ('class', 'extends', 'register-class'):
             if attrs.has_key(key):
-                d.append(MapperAttribute(source, mapper_name, key, attrs[key]))
+                value = attrs[key]
+                if (key == 'register-class'):
+                    if value.lower() == 'true':
+                        value = True
+                    elif value.lower() == 'false':
+                        value = False
+                    else:
+                        raise ValueError("Value must be true or false")
+                d.append(MapperAttribute(source, mapper_name, key, value))
 
-    def handle_component(source, vars, attrs, comptype, multiple):
+    def handle_mapper_component(source, vars, attrs, comptype):
         d = vars['directives']
         producer = makeProducer(source, comptype, attrs)
         mapper_name = vars.get('mapper_name')
         if mapper_name is None:
             # Reusable component
             name = attrs['name']
-            directive = ComponentDefinition(source, comptype, name, producer)
-        elif multiple:
+            directive = ComponentDefinition(
+                source, comptype, name, producer)
+        else:
             # Composite component of a mapper
             name = attrs['name']
-            directive = MapperCompositeComponent(
+            directive = MapperComponent(
                 source, mapper_name, comptype,
                 name, producer, attrs.get('order', 'middle'))
-        else:
-            # Singular component of a mapper
-            directive = MapperComponent(
-                source, mapper_name, comptype, producer)
         d.append(directive)
         return producer
 
     def handle_serializer(source, vars, attrs):
-        handle_component(source, vars, attrs, 'serializer', multiple=1)
+        handle_mapper_component(source, vars, attrs, 'serializer')
 
     def handle_gateway(source, vars, attrs):
         p = vars.get('classifier_producer')
@@ -206,19 +200,25 @@
                     source)
             p.sub_producer = makeProducer(source, 'gateway', attrs)
         else:
-            handle_component(source, vars, attrs, 'gateway', multiple=1)
+            handle_mapper_component(source, vars, attrs, 'gateway')
 
     def handle_classifier(source, vars, attrs):
-        p = handle_component(source, vars, attrs, 'classifier', multiple=0)
-        vars['classifier_producer'] = p
+        d = vars['directives']
+        producer = makeProducer(source, 'classifier', attrs)
+        directive = ComponentDefinition(source, 'classifier', '', producer)
+        d.append(directive)
+        vars['classifier_producer'] = producer
 
-    def handle_keygen(source, vars, attrs):
-        handle_component(source, vars, attrs, 'keygen', multiple=0)
+    def handle_oid_generator(source, vars, attrs):
+        d = vars['directives']
+        producer = makeProducer(source, 'oid_generator', attrs)
+        directive = ComponentDefinition(source, 'oid_generator', '', producer)
+        d.append(directive)
 
     def handle_use_for(source, vars, attrs):
         d = vars['directives']
         mapper_name = vars['mapper_name']
-        for attr in ('class', 'extensions', 'fallback', 'key'):
+        for attr in ('class', 'extensions', 'generic', 'oid'):
             if attrs.has_key(attr):
                 v = attrs[attr]
                 if attr == 'extensions':
@@ -227,7 +227,7 @@
                         if not ext.startswith('.'):
                             ext = '.' + ext
                         ext = ext.lower()
-                        d.append(MapperRegistration(
+                        d.append(MapperUseFor(
                             source, mapper_name, 'extension', ext))
                         if first:
                             # Use a classifier option to set the default
@@ -235,15 +235,8 @@
                             first = 0
                             d.append(ClassifierOption(
                                 source, mapper_name, 'default_extension', ext))
-                elif attr == 'key':
-                    try:
-                        v = int(v)
-                    except ValueError:
-                        v = str(v)
-                    d.append(MapperRegistration(
-                        source, mapper_name, attr, v))
                 else:
-                    d.append(MapperRegistration(
+                    d.append(MapperUseFor(
                         source, mapper_name, attr, v))
 
     def handle_option(source, vars, attrs):
@@ -260,7 +253,7 @@
         'serializer':    handle_serializer,
         'gateway':       handle_gateway,
         'classifier':    handle_classifier,
-        'keygen':        handle_keygen,
+        'oid-generator': handle_oid_generator,
         'use-for':       handle_use_for,
         'option':        handle_option,
         }
@@ -270,7 +263,7 @@
 
 
 class BasicComponentAssembler:
-    """Assembler for simple components.
+    """Assembler for producer-based components.
 
     Configures at the time of creation.
     """
@@ -280,8 +273,8 @@
         records = compsys.dtables.query(
             ComponentDefinition, comptype=comptype, name=name)
         if not records:
-            raise AssemblyError("No %s component named %s exists"
-                                % (comptype, repr(name)))
+            raise ConfigurationError("No %s component named %s exists"
+                                     % (comptype, repr(name)))
         assert len(records) == 1
         producer = records[0]['producer']
         self.producer = producer
@@ -294,67 +287,46 @@
 
 
 class MapperAssembler:
-    """Assembler for mapper components.
+    """Assembler for one mapper component.
     """
-
     def __init__(self, compsys, comptype, name):
         self.compsys = compsys
-        self.dtables = dtables = compsys.dtables
+        dtables = compsys.dtables
         self.mapper_name = name
         if not dtables.query(MapperDeclaration, mapper_name=name):
-            raise AssemblyError("No mapper named %s exists" % repr(name))
+            raise ConfigurationError("No mapper named %s exists" % repr(name))
         self.subobjs = []  # all subobjects
         self.attrs = {}
         for record in dtables.query(MapperAttribute, mapper_name=name):
-            self.attrs[record['name']] = record['value']
+            self.attrs[record.name] = record.value
         self.prepareSubComponents()
 
     def prepareSubComponents(self):
-        self.single_comps = {} # comptype -> record
         self.multi_comps = {}  # comptype -> name -> record
+        dtables = self.compsys.dtables
         name = self.mapper_name
         all_names = []  # mapper_name and all of its base mapper_names
         while name:
             all_names.append(name)
-            records = self.dtables.query(MapperComponent, mapper_name=name)
-            for r in records:
-                self.single_comps.setdefault(r['comptype'], r)
-            records = self.dtables.query(
-                MapperCompositeComponent, mapper_name=name)
+            records = dtables.query(
+                MapperComponent, mapper_name=name)
             for r in records:
-                d = self.multi_comps.setdefault(r['comptype'], {})
-                d.setdefault(r['name'], r)
-            name = self.dtables.queryField(
+                d = self.multi_comps.setdefault(r.comptype, {})
+                d.setdefault(r.name, r)
+            name = dtables.queryField(
                 MapperAttribute, 'value', mapper_name=name, name='extends')
             if name and name in all_names:
-                raise AssemblyError(
+                raise ConfigurationError(
                     "Circular extension in mappers %s" % repr(all_names))
-        self.sub_mapper_names = []
-        records = self.dtables.query(
-            MapperAttribute, name='parent', value=self.mapper_name)
-        for r in records:
-            self.sub_mapper_names.append(r['mapper_name'])
 
     def create(self):
         self.obj = Mapper()
         return self.obj
 
     def configure(self):
-        self.setParent()
         self.addSerializers()
         self.addGateways()
-        self.setClassifier()
-        self.setKeygen()
         self.addInitializers()
-        self.addSubMappers()
-        self.registerClassifications()
-
-    def setParent(self):
-        if self.attrs.get('parent'):
-            p = self.compsys.get('mapper', self.attrs['parent'])
-            self.obj.setParent(p)
-        else:
-            self.obj.setParent(None)
 
     def addSerializers(self):
         cname = self.attrs.get('class')
@@ -370,115 +342,107 @@
                 cname = self.mapper_name
             pos = cname.rfind('.')
             if pos < 0:
-                raise AssemblyError("Class name must include a module name")
+                raise ConfigurationError("Class name must include a module name")
             s = CompositeSerializer(cname[:pos], cname[pos + 1:])
-        
+
         d = self.multi_comps.get('serializer')
         if d:
-            ordered = [(r.get('order', '').lower(), name, r)
+            ordered = [((r.order or '').lower(), name, r)
                        for name, r in d.items()]
             ordered.sort()
             for order, name, r in ordered:
-                o = r['producer'](self.compsys)
+                o = r.producer(self.compsys)
                 if o is not None:
-                    s.addSerializer(str(name), o)
+                    s.add(str(name), o)
                     self.subobjs.append(o)
-        self.obj.setSerializer(s)
+        self.obj.serializer = s
 
     def addGateways(self):
         g = CompositeGateway()
         d = self.multi_comps.get('gateway')
         if d:
             for name, r in d.items():
-                o = r['producer'](self.compsys)
+                o = r.producer(self.compsys)
                 if o is not None:
-                    g.addGateway(str(name), o)
+                    g.add(str(name), o)
                     self.subobjs.append(o)
-        self.obj.setGateway(g)
-
-    def setClassifier(self):
-        r = self.single_comps.get('classifier')
-        if r:
-            o = r['producer'](self.compsys)
-            self.classifier = o
-            if o is not None:
-                self.obj.setClassifier(o)
-                self.subobjs.append(o)
-                gw = o.getGateway()
-                if gw is not None:
-                    self.subobjs.append(gw)
-
-    def setKeygen(self):
-        r = self.single_comps.get('keygen')
-        if r:
-            o = r['producer'](self.compsys)
-            if o is not None:
-                self.obj.setKeychainGenerator(o)
-                self.subobjs.append(o)
+        self.obj.gateway = g
 
     def addInitializers(self):
         for o in self.subobjs:
             if IDatabaseInitializer.isImplementedBy(o):
-                self.obj.addInitializer(o)
+                self.obj.initializers.append(o)
+
+
+class ClassifierAssembler (BasicComponentAssembler):
+    """Assembler for one classifier.
+    """
+    def __init__(self, compsys, comptype, name):
+        assert comptype == "classifier", comptype
+        assert name == '', name
+        BasicComponentAssembler.__init__(self, compsys, comptype, name)
 
-    def addSubMappers(self):
-        for name in self.sub_mapper_names:
-            o = self.compsys.get('mapper', name)
-            self.obj.addSubMapper(name, o)
+    def create(self):
+        self.obj = BasicComponentAssembler.create(self)
+        return self.obj
 
-    def registerClassifications(self):
-        """Registers classifications on behalf of sub-mappers."""
+    def configure(self):
+        dtables = self.compsys.dtables
         all_regs = {}     # { (attr, value) -> mapper_name }
         all_options = {}  # { (mapper_name, option) -> value }
-        for name in self.sub_mapper_names:
+        mapper_names = [r.mapper_name for r in
+                        dtables.query(MapperDeclaration)]
+        # Gather classification options from each mapper configuration.
+        for name in mapper_names:
             # use-for directives
-            records = self.dtables.query(
-                MapperRegistration, mapper_name=name)
+            records = dtables.query(
+                MapperUseFor, mapper_name=name)
             for r in records:
-                key = ((r['attr'], r['value']))
+                key = ((r.attr, r.value))
                 if all_regs.has_key(key) and all_regs[key] != name:
-                    raise AssemblyError(
+                    raise ConfigurationError(
                         "Mappers %s and %s are contending over %s == %s" % (
                         name, all_regs[key],
-                        r['attr'], repr(r['value'])))
+                        repr(r.attr), repr(r.value)))
                 all_regs[key] = name
 
-            # class="" attributes
-            class_name = self.dtables.queryField(
-                MapperAttribute, 'value', mapper_name=name, name='class')
-            if class_name is None:
-                class_name = name
-            elif class_name in ('none', 'any'):
-                class_name = None
-            if class_name is not None:
-                # Add an implicit use-for directive
-                key = ('class', class_name)
-                if all_regs.has_key(key) and all_regs[key] != name:
-                    raise AssemblyError(
-                        "Mappers %s and %s are contending over %s == %s" % (
-                        name, all_regs[key],
-                        'class', repr(class_name)))
-                all_regs[key] = name
+            register_class = dtables.queryField(
+                MapperAttribute, 'value', mapper_name=name,
+                name='register-class')
+            if register_class or register_class is None:
+                # Create an implicit 'use-for class' directive
+                class_name = dtables.queryField(
+                    MapperAttribute, 'value', mapper_name=name, name='class')
+                if class_name is None:
+                    class_name = name
+                elif class_name in ('none', 'any'):
+                    class_name = None
+                if class_name is not None:
+                    key = ('class', class_name)
+                    if all_regs.has_key(key) and all_regs[key] != name:
+                        raise ConfigurationError(
+                            "Mappers %s and %s are contending over %s == %s" % (
+                            name, all_regs[key],
+                            "'class'", repr(class_name)))
+                    all_regs[key] = name
 
             # options
-            records = self.dtables.query(
+            records = dtables.query(
                 ClassifierOption, mapper_name=name)
             for r in records:
-                all_options[(name, r['option'])] = r['value']
+                all_options[(name, r.option)] = r.value
 
+        # Perform the registrations.
         if all_regs or all_options:
-            if self.classifier is None:
-                raise AssemblyError(
-                    "Mapper %s needs a classifier because it has "
-                    "sub-mappers with registrations" % self.mapper_name)
             for (attr, value), name in all_regs.items():
-                self.classifier.register(attr, value, name)
+                self.obj.register(attr, value, name)
             for (name, option), value in all_options.items():
-                self.classifier.setOption(name, option, value)
-
+                self.obj.setOption(name, option, value)
+            
+        
 
-def wireMapper(filenames, vname='', mapper_name='root'):
-    """Returns an Ape mapper built according to the configuration files.
+def configure(filenames, vname=''):
+    """Returns a MapperConfiguration built from configuration files.
     """
     handlers = getElementHandlers()
     reader = DirectiveReader(handlers)
@@ -487,9 +451,19 @@
     directives = reader.getDirectives(vname)
     cs = ComponentSystem(directives)
     cs.addComponentType('mapper', MapperAssembler)
-    for comptype in ('serializer', 'gateway', 'classifier', 'keygen'):
+    cs.addComponentType('classifier', ClassifierAssembler)
+    for comptype in ('serializer', 'gateway', 'oid_generator'):
         cs.addComponentType(comptype, BasicComponentAssembler)
-    mapper = cs.get('mapper', mapper_name)
-    mapper.checkConfiguration(path=mapper_name)
-    return mapper
+    mappers = {}
+    for record in cs.dtables.query(MapperDeclaration):
+        name = record.mapper_name
+        mappers[name] = cs.get('mapper', name)
+    classifier = cs.get('classifier', '')
+    oid_gen = cs.get('oid_generator', '')
+    conf = MapperConfiguration(mappers, classifier, oid_gen)
+    for obj in (classifier.gateway, oid_gen):
+        if IDatabaseInitializer.isImplementedBy(obj):
+            conf.initializers.append(obj)
+    conf.check()
+    return conf
 


=== Products/Ape/lib/apelib/config/common.py 1.2 => 1.3 ===
--- Products/Ape/lib/apelib/config/common.py:1.2	Wed Jul  9 11:39:55 2003
+++ Products/Ape/lib/apelib/config/common.py	Mon Feb  2 10:07:17 2004
@@ -19,7 +19,7 @@
 import xml.sax.handler
 from xml.sax import parse
 
-import minitables
+from apelib.zodb3 import zodbtables
 
 
 class Directive:
@@ -41,8 +41,9 @@
                 kw[key] = args[n]
         self.data = kw
         unique_key = [self.__class__]
-        for name in self.schema.getPrimaryNames():
-            unique_key.append(kw[name])
+        for column in self.schema.columns:
+            if column.primary:
+                unique_key.append(kw[column.name])
         self.unique_key = tuple(unique_key)
 
     def getUniqueKey(self):
@@ -51,7 +52,7 @@
     def index(self, tables):
         t = tables.get(self.__class__)
         if t is None:
-            t = minitables.Table(self.schema)
+            t = zodbtables.Table(self.schema)
             tables[self.__class__] = t
         t.insert(self.data)
 

=== Removed File Products/Ape/lib/apelib/config/minitables.py ===




More information about the Zope-CVS mailing list