[Zope3-checkins] CVS: Packages/ZConfig - SectionMatcher.py:1.1.2.1 SchemaInfo.py:1.1.2.3 SchemaParser.py:1.1.4.2
Fred L. Drake, Jr.
fred@zope.com
Mon, 9 Dec 2002 12:02:26 -0500
Update of /cvs-repository/Packages/ZConfig
In directory cvs.zope.org:/tmp/cvs-serv8712
Modified Files:
Tag: zconfig-schema-devel-branch
SchemaInfo.py SchemaParser.py
Added Files:
Tag: zconfig-schema-devel-branch
SectionMatcher.py
Log Message:
Checkpoint: more progress.
=== Added File Packages/ZConfig/SectionMatcher.py ===
"""Utility that manages the binding of configuration data to a section."""
import ZConfig
class SectionMatcher:
def __init__(self, info, name=None):
if name is not None:
self.name = info.nametype.convert(name)
if not info.isAllowedName(self.name):
raise ZConfig.ConfigurationError(
"%s is not an allowed name for %s sections"
% (`name`, `info.name`))
elif info.allowUnnamed():
self.name = None
else:
raise ZConfig.ConfigurationError(
`info.name` + " sections may not be unnamed")
self.info = info
self._values = {}
def addKeyValue(self, key, value):
keyinfo = self.info.getinfo(key)
if keyinfo.issection():
if keyinfo.name:
extra = " in %s sections" % `keyinfo.name`
else:
extra = ""
raise ZConfig.ConfigurationError(
"%s is not a valid key name%s" % (`key`, extra))
L = self._values.get(key)
if L is None:
L = []
if keyinfo.maxOccurs is None:
L.append(value)
elif len(L) = keyinfo.maxOccurs:
raise ZConfig.ConfigurationError(
"too many values for " + `name`)
else:
L.append(value)
self._values[key] = L
def finish(self):
"""Check the constraints of the section and convert to an application
object."""
values = {}
for key in self.info.getchildnames():
ci = self.info.getinfo(key)
if self._values.has_key(key):
L = self._values[key]
if len(L) < ci.minOccurs:
raise ZConfig.ConfigurationError(
"not enough values for %s; %d found, %d required"
% (`key`, len(L), ci.minOccurs))
else:
L = ci.getdefault()
def constuct(self):
keys = self.info.getchildnames()
values = [None] * len(keys)
for i in range(len(keys)):
name = keys[i]
ci = self.info.getinfo(name)
if self._values.has_key(name):
L = self._values[key]
elif ci.ismulti():
L = ci.getdefault()
else:
L = [ci.getdefault()]
if ci.ismulti():
values[i] = [ci.datatype.convert(s) for s in L]
else:
assert len(L) == 1
values[i] = ci.datatype.convert(L[0])
v = SectionValue(keys, values)
# XXX Really should delay this until after all the
# XXX sibling SectionValue instances have been created and
# XXX we're ready to construct the parent.
if self.info.handler:
v = self.info.handler(v)
return v
class SectionValue:
def __init__(self, keys, values):
self._keys = keys
self._values = values
def __len__(self):
return len(self._keys)
def __getitem__(self, index):
if isinstance(index, slice):
raise TypeError("SectionValue does not support slicing")
return self._values[index]
def __getattr__(self, name):
try:
i = self._keys.index(name)
except ValueError:
raise AttributeError, name
return self._values[i]
=== Packages/ZConfig/SchemaInfo.py 1.1.2.2 => 1.1.2.3 ===
--- Packages/ZConfig/SchemaInfo.py:1.1.2.2 Fri Dec 6 21:37:46 2002
+++ Packages/ZConfig/SchemaInfo.py Mon Dec 9 12:02:25 2002
@@ -5,10 +5,11 @@
"""Information about a single configuration key."""
def __init__(self, name, datatype, minOccurs, maxOccurs, handler):
- if maxOccurs < 1:
- raise ValueError("maxOccurs must be at least 1")
- if minOccurs < maxOccurs:
- raise ValueError("minOccurs must be at least maxOccurs")
+ if maxOccurs is not None and maxOccurs < 1:
+ if maxOccurs < 1:
+ raise ValueError("maxOccurs must be at least 1")
+ if minOccurs is not None and minOccurs < maxOccurs:
+ raise ValueError("minOccurs must be at least maxOccurs")
self.name = name
self.datatype = datatype
self.minOccurs = minOccurs
@@ -20,6 +21,11 @@
def finish(self):
if self._finished:
raise ValueError("cannot finish KeyInfo more than once")
+ if self.minOccurs is None:
+ if self._default is not None:
+ self.minOccurs = 1
+ else:
+ self.minOccurs = 0
self._finished = True
def adddefault(self, value):
@@ -41,8 +47,12 @@
raise ValueError("cannot get default value of key before KeyInfo"
" has been completely initialized")
if self._default is None and self.maxOccurs > 1:
- self._default = []
- return self._default
+ return []
+ else:
+ return self._default
+
+ def hasdefault(self):
+ return self._default is not None
def ismulti(self):
return self.maxOccurs > 1
@@ -68,12 +78,12 @@
def _add_child(self, thing):
for c in self._children:
- if name == c.name:
- raise ValueError("child name %s already used" % name)
+ if thing.name == c.name:
+ raise ValueError("child name %s already used" % thing.name)
self._children.append(thing)
def addkey(self, keyinfo):
- self._add_child(keyinfo.name, keyinfo)
+ self._add_child(keyinfo)
def getinfo(self, name):
for c in self._children:
=== Packages/ZConfig/SchemaParser.py 1.1.4.1 => 1.1.4.2 ===
--- Packages/ZConfig/SchemaParser.py:1.1.4.1 Fri Dec 6 18:54:03 2002
+++ Packages/ZConfig/SchemaParser.py Mon Dec 9 12:02:25 2002
@@ -23,6 +23,22 @@
self._cdata = None
self._locator = None
self._prefixes = []
+ self._schema = None
+ self._stack = []
+ self._sections = []
+
+ def parseFile(self, file):
+ if isinstance(file, str) or isinstance(file, unicode):
+ file = open(file, 'rU')
+ return self.parseStream(file)
+
+ def parseString(self, s):
+ xml.sax.parseString(s, self)
+ return self._schema
+
+ def parseStream(self, stream):
+ xml.sax.parse(stream, self)
+ return self._schema
# SAX 2 ContentHandler methods
@@ -70,8 +86,6 @@
def endDocument(self):
if not self._schema:
self.doSchemaError("no schema found")
- self.checkClasses()
- self.context.setSchema(self._schema)
# schema loading logic
@@ -83,7 +97,7 @@
def push_prefix(self, attrs):
name = attrs.get("prefix")
- self._prefixes.append(self.get_classname(name) or "")
+ self._prefixes.append(self.get_classname(name or ""))
def start_schema(self, attrs):
self.start_section(attrs)
@@ -119,18 +133,21 @@
else:
names = None
maxOccurs, minOccurs, handler = self.get_common_info(attrs)
-
+ section = SectionInfo(None, None, minOccurs, maxOccurs, handler,
+ keytype, names)
+ self._stack.append(section)
+ self._sections.append(section)
def end_section(self):
del self._prefixes[-1]
- self._stack[-1].finish()
+ del self._sections[-1]
+ self._stack.pop().finish()
def start_sectiongroup(self, attrs):
self.push_prefix(attrs)
def end_sectiongroup(self):
del self._prefixes[-1]
- self._stack.pop().finish()
def start_key(self, attrs):
name = attrs.get("name")
@@ -149,12 +166,22 @@
def get_common_info(self, attrs):
maxOccurs = attrs.get("maxOccurs")
- if maxOccurs:
- maxOccurs = int(maxOccurs)
+ if maxOccurs is not None:
+ if maxOccurs == "unbounded":
+ maxOccurs = None
+ else:
+ maxOccurs = int(maxOccurs)
+ else:
+ maxOccurs = 1
minOccurs = attrs.get("minOccurs")
if minOccurs:
minOccurs = int(minOccurs)
+ else:
+ minOccurs = None
handler = attrs.get("handler")
if handler:
handler = self.get_classname(handler)
return maxOccurs, minOccurs, handler
+
+ def doSchemaError(self, message):
+ raise ZConfig.ConfigurationError(message)