[Zope3-checkins] CVS: Packages/ZConfig - datatypes.py:1.1.2.12 loader.py:1.1.2.13 matcher.py:1.1.2.21 schema.py:1.1.2.16
Fred L. Drake, Jr.
fred@zope.com
Fri, 13 Dec 2002 15:38:59 -0500
Update of /cvs-repository/Packages/ZConfig
In directory cvs.zope.org:/tmp/cvs-serv32011
Modified Files:
Tag: zconfig-schema-devel-branch
datatypes.py loader.py matcher.py schema.py
Log Message:
Several changes:
- ZConfig.loader.SchemaLoader takes an optional datatype registry,
allowing it to be given a pre-loaded or app-specific package of
types.
- ZConfig.datatypes acts as a standard type registry, though it
provides the default implementation.
- Don't call handler functions as the configuration object is built
up; save them up and allow the application decide when to call
them. *** This changes the return values from the .loadURL() and
.loadFile() methods of SchemaLoader. ***
- ZConfig.schema.SchemaParser only uses types looked up from the
provided type registry; it provides no default implementations.
=== Packages/ZConfig/datatypes.py 1.1.2.11 => 1.1.2.12 ===
--- Packages/ZConfig/datatypes.py:1.1.2.11 Fri Dec 13 15:15:02 2002
+++ Packages/ZConfig/datatypes.py Fri Dec 13 15:38:57 2002
@@ -202,8 +202,3 @@
package = __import__(n, g, g, component)
self._other[name] = package
return package
-
-
-_r = Registry()
-get = _r.get
-register = _r.register
=== Packages/ZConfig/loader.py 1.1.2.12 => 1.1.2.13 ===
--- Packages/ZConfig/loader.py:1.1.2.12 Fri Dec 13 10:16:57 2002
+++ Packages/ZConfig/loader.py Fri Dec 13 15:38:57 2002
@@ -20,6 +20,7 @@
import ZConfig
+from ZConfig import datatypes
from ZConfig import matcher
try:
@@ -79,6 +80,12 @@
class SchemaLoader(BaseLoader):
_fragment = None
+ def __init__(self, registry=None):
+ if registry is None:
+ registry = datatypes.Registry()
+ self.registry = registry
+ BaseLoader.__init__(self)
+
def normalizeURL(self, url):
if url:
url, self._fragment = urlparse.urldefrag(url)
@@ -86,7 +93,7 @@
def loadResource(self, resource):
from ZConfig.schema import SchemaParser
- parser = SchemaParser()
+ parser = SchemaParser(self.registry)
schema = parser.parseStream(resource.file)
if self._fragment:
schema = schema.gettype(self._fragment)
@@ -99,9 +106,10 @@
self.schema = schema
def loadResource(self, resource):
- sm = matcher.SchemaMatcher(self.schema)
+ self.handlers = []
+ sm = matcher.SchemaMatcher(self.schema, self.handlers)
self._parse_resource(sm, resource)
- return sm.finish()
+ return sm.finish(), CompositeHandler(self.handlers)
# parser support API
@@ -116,7 +124,8 @@
raise ZConfig.ConfigurationError(
"%s is not an allowed name for %s sections"
% (`name`, `ci.sectiontype.name`))
- return matcher.SectionMatcher(ci, self.schema.gettype(type), name)
+ return matcher.SectionMatcher(ci, self.schema.gettype(type), name,
+ self.handlers)
def endSection(self, parent, type, name, delegatename, matcher):
assert not delegatename
@@ -133,6 +142,18 @@
from ZConfig.cfgparser import ZConfigParser
parser = ZConfigParser(resource, self)
parser.parse(matcher)
+
+
+class CompositeHandler:
+ def __init__(self, handlers):
+ self._handlers = handlers
+
+ def __call__(self):
+ for handler, value in self._handlers:
+ handler(value)
+
+ def __len__(self):
+ return len(self._handlers)
class Resource:
=== Packages/ZConfig/matcher.py 1.1.2.20 => 1.1.2.21 ===
--- Packages/ZConfig/matcher.py:1.1.2.20 Fri Dec 13 13:50:34 2002
+++ Packages/ZConfig/matcher.py Fri Dec 13 15:38:57 2002
@@ -19,11 +19,14 @@
class BaseMatcher:
- def __init__(self, info, type):
+ def __init__(self, info, type, handlers):
self.info = info
self.type = type
self._values = [None] * len(type)
self._sectionnames = {}
+ if handlers is None:
+ handlers = []
+ self._handlers = handlers
def __repr__(self):
clsname = self.__class__.__name__
@@ -139,7 +142,7 @@
# XXX sibling SectionValue instances have been created and
# XXX we're ready to construct the parent.
if self.info.handler is not None:
- self.info.handler(v)
+ self._handlers.append((self.info.handler, v))
return v
def createValue(self, attrnames):
@@ -147,21 +150,21 @@
class SectionMatcher(BaseMatcher):
- def __init__(self, info, type, name):
+ def __init__(self, info, type, name, handlers):
if name or info.allowUnnamed():
self.name = name
else:
raise ZConfig.ConfigurationError(
`type.name` + " sections may not be unnamed")
- BaseMatcher.__init__(self, info, type)
+ BaseMatcher.__init__(self, info, type, handlers)
def createValue(self, attrnames):
return SectionValue(attrnames, self._values, self.name, self.type)
class SchemaMatcher(BaseMatcher):
- def __init__(self, info):
- BaseMatcher.__init__(self, info, info)
+ def __init__(self, info, handlers=None):
+ BaseMatcher.__init__(self, info, info, handlers)
def finish(self):
# Since there's no outer container to call datatype()
=== Packages/ZConfig/schema.py 1.1.2.15 => 1.1.2.16 ===
--- Packages/ZConfig/schema.py:1.1.2.15 Fri Dec 13 12:28:11 2002
+++ Packages/ZConfig/schema.py Fri Dec 13 15:38:57 2002
@@ -17,7 +17,6 @@
import ZConfig
-from ZConfig import datatypes
from ZConfig import info
@@ -31,22 +30,14 @@
return d
-default_value_type = datatypes.get("str")
-default_key_type = datatypes.get("basic-key")
-default_name_type = default_key_type
-
-def default_section_type(value):
- return value
-
-_identifier = datatypes.get("identifier")
-
-
class SchemaParser(xml.sax.ContentHandler):
_cdata_tags = "description", "metadefault", "example", "default"
_handled_tags = "schema", "key", "section", "sectiongroup", "sectiontype"
- def __init__(self):
+ def __init__(self, registry):
+ self._registry = registry
+ self._identifier = registry.get("identifier")
self._cdata = None
self._locator = None
self._prefixes = []
@@ -120,17 +111,17 @@
self.doSchemaError("prefix may not begin with '.'")
self._prefixes.append(prefix)
- def get_datatype(self, attrs, key, default):
- if attrs.has_key(key):
- dtname = self.get_classname(attrs[key])
- return datatypes.get(dtname)
+ def get_datatype(self, attrs, attrkey, default):
+ if attrs.has_key(attrkey):
+ dtname = self.get_classname(attrs[attrkey])
+ return self._registry.get(dtname)
else:
- return default
+ return self._registry.get(default)
def get_sect_typeinfo(self, attrs):
- keytype = self.get_datatype(attrs, "keytype", default_key_type)
- valuetype = self.get_datatype(attrs, "valuetype", default_value_type)
- datatype = self.get_datatype(attrs, "datatype", default_section_type)
+ keytype = self.get_datatype(attrs, "keytype", "basic-key")
+ valuetype = self.get_datatype(attrs, "valuetype", "str")
+ datatype = self.get_datatype(attrs, "datatype", "null")
return keytype, valuetype, datatype
def start_schema(self, attrs):
@@ -149,7 +140,7 @@
if not name:
self.doSchemaError(
"sectiontype name must not be omitted or empty")
- name = _identifier(name)
+ name = self._identifier(name)
keytype, valuetype, datatype = self.get_sect_typeinfo(attrs)
sectinfo = info.SectionType(name, keytype, valuetype, datatype)
self._schema.addtype(sectinfo)
@@ -197,13 +188,13 @@
self.doSchemaError("key name may not be omitted or empty")
# run the keytype converter to make sure this is a valid key
name = self._stack[-1].keytype(name)
- datatype = datatypes.get(attrs.get("datatype"))
+ datatype = self._registry.get(attrs.get("datatype"))
maxOccurs, minOccurs, handler = self.get_common_info(attrs)
attribute = attrs.get("attribute")
if attribute:
- attribute = _identifier(attribute)
+ attribute = self._identifier(attribute)
else:
- attribute = _identifier(name.replace("-", "_"))
+ attribute = self._identifier(name.replace("-", "_"))
key = info.KeyInfo(name, datatype, minOccurs, maxOccurs, handler,
attribute)
self._stack[-1].addkey(key)
@@ -239,7 +230,7 @@
self.doSchemaError("section name must be specified and non-empty")
aname = attrs.get("attribute")
if aname:
- aname = _identifier(aname)
+ aname = self._identifier(aname)
if name in ("*", "+"):
if not aname:
self.doSchemaError(
@@ -247,7 +238,7 @@
" when using '*' or '+' for a section name")
return name, None, aname
else:
- return None, _identifier(name), aname
+ return None, self._identifier(name), aname
def doSchemaError(self, message):
raise ZConfig.ConfigurationError(message)