[Zope3-checkins] CVS: Packages/ZConfig - info.py:1.1.2.16 matcher.py:1.1.2.23 schema.py:1.1.2.22
Fred L. Drake, Jr.
fred@zope.com
Wed, 18 Dec 2002 11:16:31 -0500
Update of /cvs-repository/Packages/ZConfig
In directory cvs.zope.org:/tmp/cvs-serv21256
Modified Files:
Tag: zconfig-schema-devel-branch
info.py matcher.py schema.py
Log Message:
Changes to the schema language:
- The minOccurs and maxOccurs attributes are gone
- To specify minOccurs==1, use required="yes" in the schema
- To specify maxOccurs=="unbounded", use a <multikey> or <multisection>
instead of <key> or <section>
This needs some code review and refactoring, but works.
=== Packages/ZConfig/info.py 1.1.2.15 => 1.1.2.16 ===
--- Packages/ZConfig/info.py:1.1.2.15 Fri Dec 13 16:03:49 2002
+++ Packages/ZConfig/info.py Wed Dec 18 11:15:59 2002
@@ -82,6 +82,7 @@
class KeyInfo(BaseInfo):
def __init__(self, name, datatype, minOccurs, maxOccurs, handler,
attribute):
+ assert minOccurs is not None
BaseInfo.__init__(self, name, datatype, minOccurs, maxOccurs,
handler, attribute)
self._finished = False
@@ -90,11 +91,6 @@
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):
=== Packages/ZConfig/matcher.py 1.1.2.22 => 1.1.2.23 ===
--- Packages/ZConfig/matcher.py:1.1.2.22 Fri Dec 13 16:06:46 2002
+++ Packages/ZConfig/matcher.py Wed Dec 18 11:15:59 2002
@@ -110,7 +110,7 @@
v = values[i] = default[:]
if ci.ismulti():
if v is None:
- v = values[i] = []
+ v = values[i] = ci.getdefault()[:]
if len(v) < ci.minOccurs:
raise ZConfig.ConfigurationError(
"not enough values for %s; %d found, %d required"
@@ -129,16 +129,16 @@
name, ci = self.type[i]
if ci.ismulti():
if ci.issection():
- values[i] = [s.__type__.datatype(s)
- for s in values[i]]
+ v = [s.__type__.datatype(s) for s in values[i]]
else:
- values[i] = [ci.datatype(s) for s in values[i]]
+ v = [ci.datatype(s) for s in values[i]]
elif ci.issection():
- values[i] = values[i].__type__.datatype(values[i])
+ v = values[i].__type__.datatype(values[i])
else:
- values[i] = ci.datatype(values[i])
+ v = ci.datatype(values[i])
+ values[i] = v
if ci.handler is not None:
- self._handlers.append((ci.handler, values[i]))
+ self._handlers.append((ci.handler, v))
return self.createValue(attrnames)
def createValue(self, attrnames):
=== Packages/ZConfig/schema.py 1.1.2.21 => 1.1.2.22 ===
--- Packages/ZConfig/schema.py:1.1.2.21 Mon Dec 16 13:37:52 2002
+++ Packages/ZConfig/schema.py Wed Dec 18 11:15:59 2002
@@ -21,6 +21,12 @@
try:
+ True
+except NameError:
+ True = 1
+ False = 0
+
+try:
dict
except NameError:
def dict(mapping):
@@ -33,7 +39,8 @@
class SchemaParser(xml.sax.ContentHandler):
_cdata_tags = "description", "metadefault", "example", "default"
- _handled_tags = "schema", "key", "section", "sectiongroup", "sectiontype"
+ _handled_tags = ("schema", "sectiongroup", "sectiontype",
+ "key", "multikey", "section", "multisection")
def __init__(self, registry):
self._registry = registry
@@ -170,21 +177,59 @@
del self._prefixes[-1]
self._stack.pop()
- def start_section(self, attrs):
+ def get_required(self, attrs):
+ if attrs.has_key("required"):
+ v = attrs["required"]
+ if v == "yes":
+ return True
+ elif v == "no":
+ return False
+ self.error("value for 'required' must be 'yes' or 'no'")
+ else:
+ return False
+
+ def get_ordinality(self, attrs):
+ min, max = 0, info.Unbounded
+ if self.get_required(attrs):
+ min = 1
+ return min, max
+
+ def get_sectiontype(self, attrs):
type = attrs.get("type")
if not type:
self.error("section must specify type")
- sectiontype = self._schema.gettype(type)
- maxOccurs, minOccurs, handler = self.get_common_info(attrs)
+ return self._schema.gettype(type)
+
+ def start_section(self, attrs):
+ sectiontype = self.get_sectiontype(attrs)
+ handler = self.get_handler(attrs)
+ min = self.get_required(attrs) and 1 or 0
any, name, attribute = self.get_name_info(attrs)
- section = info.SectionInfo(any or name, sectiontype,
- minOccurs, maxOccurs, handler, attribute)
+ if any or not name:
+ self.error("section name may not be '*' or '+'")
+ section = info.SectionInfo(name, sectiontype,
+ min, 1, handler, attribute)
self._stack[-1].addsection(name, section)
self._stack.append(section)
def end_section(self):
self._stack.pop()
+ def start_multisection(self, attrs):
+ sectiontype = self.get_sectiontype(attrs)
+ min, max = self.get_ordinality(attrs)
+ any, name, attribute = self.get_name_info(attrs)
+ if any not in ("*", "+"):
+ self.error("multisection must specify '*' or '+' for the name")
+ handler = self.get_handler(attrs)
+ section = info.SectionInfo(any or name, sectiontype,
+ min, max, handler, attribute)
+ self._stack[-1].addsection(name, section)
+ self._stack.append(section)
+
+ def end_multisection(self):
+ self._stack.pop()
+
def start_sectiongroup(self, attrs):
if self._group is not None:
self.error("sectiongroup elements cannot be nested")
@@ -201,45 +246,48 @@
self._group = None
self._stack.pop().finish()
- def start_key(self, attrs):
+ def get_key_info(self, attrs, element):
name = attrs.get("name")
if not name:
- self.error("key name may not be omitted or empty")
+ self.error(element + " 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 = self._registry.get(attrs.get("datatype"))
- maxOccurs, minOccurs, handler = self.get_common_info(attrs)
+ datatype = self.get_datatype(attrs, "datatype", "str")
+ handler = self.get_handler(attrs)
attribute = attrs.get("attribute")
- if attribute:
+ if attribute is not None:
attribute = self._identifier(attribute)
else:
attribute = self._identifier(name.replace("-", "_"))
- key = info.KeyInfo(name, datatype, minOccurs, maxOccurs, handler,
- attribute)
+ return name, datatype, handler, attribute
+
+ def start_key(self, attrs):
+ name, datatype, handler, attribute = self.get_key_info(attrs, "key")
+ min = self.get_required(attrs) and 1 or 0
+ key = info.KeyInfo(name, datatype, min, 1, handler, attribute)
+ if attrs.has_key("default"):
+ if min:
+ self.error("required key cannot have a default value")
+ key.adddefault(str(attrs["default"]).strip())
self._stack[-1].addkey(key)
self._stack.append(key)
def end_key(self):
self._stack.pop().finish()
- def get_common_info(self, attrs):
- maxOccurs = attrs.get("maxOccurs")
- if maxOccurs is not None:
- if maxOccurs == "unbounded":
- maxOccurs = info.Unbounded
- else:
- maxOccurs = int(maxOccurs)
- else:
- maxOccurs = 1
- minOccurs = attrs.get("minOccurs")
- if minOccurs:
- minOccurs = int(minOccurs)
- if minOccurs > maxOccurs:
- self.error("minOccurs cannot be more than maxOccurs")
- else:
- minOccurs = None
- handler = self.get_handler(attrs)
- return maxOccurs, minOccurs, handler
+ def start_multikey(self, attrs):
+ if attrs.has_key("default"):
+ self.error("default values for multikey must be given using"
+ " 'default' elements")
+ name, datatype, handler, attribute = self.get_key_info(attrs,
+ "multikey")
+ min, max = self.get_ordinality(attrs)
+ key = info.KeyInfo(name, datatype, min, max, handler, attribute)
+ self._stack[-1].addkey(key)
+ self._stack.append(key)
+
+ def end_multikey(self):
+ self._stack.pop().finish()
def get_name_info(self, attrs):
name = attrs.get("name")