[Zope3-checkins] CVS: Packages/ZConfig - SchemaInfo.py:1.1.2.8 SchemaParser.py:1.1.4.5 SectionMatcher.py:1.1.2.3
Fred L. Drake, Jr.
fred@zope.com
Mon, 9 Dec 2002 17:51:21 -0500
Update of /cvs-repository/Packages/ZConfig
In directory cvs.zope.org:/tmp/cvs-serv5336
Modified Files:
Tag: zconfig-schema-devel-branch
SchemaInfo.py SchemaParser.py SectionMatcher.py
Log Message:
Allow data binding to names other than the key names.
=== Packages/ZConfig/SchemaInfo.py 1.1.2.7 => 1.1.2.8 ===
--- Packages/ZConfig/SchemaInfo.py:1.1.2.7 Mon Dec 9 14:12:55 2002
+++ Packages/ZConfig/SchemaInfo.py Mon Dec 9 17:51:20 2002
@@ -29,7 +29,8 @@
class KeyInfo:
"""Information about a single configuration key."""
- def __init__(self, name, datatype, minOccurs, maxOccurs, handler):
+ def __init__(self, name, datatype, minOccurs, maxOccurs, handler,
+ attribute):
if maxOccurs is not None and maxOccurs < 1:
if maxOccurs < 1:
raise ValueError("maxOccurs must be at least 1")
@@ -40,6 +41,7 @@
self.minOccurs = minOccurs
self.maxOccurs = maxOccurs
self.handler = handler
+ self.attribute = attribute
self._default = None
self._finished = False
@@ -91,57 +93,55 @@
class SectionInfo(KeyInfo):
def __init__(self, name, datatype, minOccurs, maxOccurs, handler,
- keytype, names, nametype):
+ attribute, keytype, names, nametype):
assert keytype is not None
self.keytype = keytype
- self.names = names
+ self.names = names # '*', '+', or [name1, ...]
self.nametype = nametype
- self._children = []
- self._keyindex = {}
+ self._children = [] # [(name, info), ...]
KeyInfo.__init__(self, name, datatype, minOccurs, maxOccurs,
- handler)
+ handler, attribute)
def _add_child(self, name, thing):
- if name in self._keyindex:
- raise ValueError("child name %s already used" % name)
- index = len(self._children)
- self._children.append(thing)
- self._keyindex[name] = index, thing
+ for n, info in self._children:
+ if name and n == name:
+ raise ValueError("child name %s already used" % name)
+ if info.attribute and info.attribute == thing.attribute:
+ raise ValueError("child attribute name %s already used"
+ % thing.attribute)
+ self._children.append((name, thing))
def addkey(self, keyinfo):
self._add_child(keyinfo.name, keyinfo)
def addsection(self, name, sectinfo):
- if name == "*" or name == "+":
- raise NotImplementedError("sections without a specific name"
- " are not yet supported")
+ assert name not in ("*", "+")
self._add_child(name, sectinfo)
def getinfo(self, name):
- try:
- index, thing = self._keyindex[name]
- except KeyError:
+ if not name:
return None
+ for n, info in self._children:
+ if n == name:
+ return info
else:
- return thing
+ return None
def getchildnames(self):
- L = [(i,n) for (n,(i,t)) in self._keyindex.iteritems()]
- L.sort()
- return [n for (i,n) in L]
+ return [n for (n,info) in self._children]
def issection(self):
return True
def allowUnnamed(self):
- return "*" in self.names
+ return self.names == "*"
def isAllowedName(self, name):
if name == "*" or name == "+":
return False
- elif "+" in self.names:
+ elif self.names == "+":
return bool(name)
elif not name:
- return "*" in self.names
+ return self.names == "*"
else:
return name in self.names
=== Packages/ZConfig/SchemaParser.py 1.1.4.4 => 1.1.4.5 ===
--- Packages/ZConfig/SchemaParser.py:1.1.4.4 Mon Dec 9 14:12:55 2002
+++ Packages/ZConfig/SchemaParser.py Mon Dec 9 17:51:20 2002
@@ -13,6 +13,8 @@
default_key_type = ZConfig.DataTypes.get("basic-key")
default_name_type = default_key_type
+_identifier = ZConfig.DataTypes.get("identifier").convert
+
class SchemaParser(xml.sax.ContentHandler):
@@ -108,7 +110,7 @@
keytype = ZConfig.DataTypes.get(attrs["keytype"])
else:
keytype = default_key_type
- self._schema = SectionInfo(None, None, 1, 1, handler,
+ self._schema = SectionInfo(None, None, 1, 1, handler, None,
keytype, (), None)
self._sections = [self._schema]
self._stack = [self._schema]
@@ -121,6 +123,9 @@
def start_section(self, attrs):
self.push_prefix(attrs)
+ type = attrs.get("type")
+ if not type:
+ self.doSchemaError("section does not specify type")
if attrs.has_key("keytype"):
keytype = ZConfig.DataTypes.get(attrs["keytype"])
else:
@@ -129,46 +134,19 @@
nametype = ZConfig.DataTypes.get(attrs["nametype"])
else:
nametype = default_name_type
- anyname = anyornoname = False
- names = []
- name = None
- if attrs.has_key("names"):
- for s in attrs["names"].split("|"):
- s = s.strip()
- if not s:
- self.doSchemaError("empty section name not allowed")
- if s == "*":
- if anyname:
- self.doSchemaError("cannot specify both '+' and '*'"
- " naming for a section")
- if anyornoname:
- self.doSchemaError("can specify '*' only once")
- anyornoname = True
- elif s == "+":
- if anyornoname:
- self.doSchemaError("cannot specify both '*' and '+'"
- " naming for a section")
- if anyname:
- self.doSchemaError("can specify '+' only once")
- anyname = True
- else:
- s = nametype.convert(s)
- if s == "*" or s == "+":
- self.doSchemaError("nametypes may not convert to"
- " '*' or '+'")
- name = name or s
- names.append(s)
- else:
- names = "*",
maxOccurs, minOccurs, handler = self.get_common_info(attrs)
+ any, names, attribute = self.get_names_info(attrs, nametype)
if self._stack:
parent = self._stack[-1]
else:
parent = self._schema
- section = SectionInfo(name, None, minOccurs, maxOccurs, handler,
- keytype, names, nametype)
- for n in names:
- parent.addsection(n, section)
+ section = SectionInfo(None, None, minOccurs, maxOccurs, handler,
+ attribute, keytype, names, nametype)
+ if any:
+ parent.addsection(None, section)
+ else:
+ for n in names:
+ parent.addsection(n, section)
self._stack.append(section)
self._sections.append(section)
@@ -179,6 +157,9 @@
def start_sectiongroup(self, attrs):
self.push_prefix(attrs)
+ name = attrs.get("name")
+ if not name:
+ self.doSchemaError("section group must be named")
def end_sectiongroup(self):
del self._prefixes[-1]
@@ -191,7 +172,13 @@
name = self._stack[-1].keytype.convert(name)
datatype = ZConfig.DataTypes.get(attrs.get("type"))
maxOccurs, minOccurs, handler = self.get_common_info(attrs)
- key = KeyInfo(name, datatype, minOccurs, maxOccurs, handler)
+ attribute = attrs.get("attribute")
+ if attribute:
+ attribute = _identifier(attribute)
+ else:
+ attribute = _identifier(name.replace("-", "_"))
+ key = KeyInfo(name, datatype, minOccurs, maxOccurs, handler,
+ attribute)
self._sections[-1].addkey(key)
self._stack.append(key)
@@ -218,6 +205,45 @@
if handler:
handler = self.get_classname(handler)
return maxOccurs, minOccurs, handler
+
+ def get_names_info(self, attrs, nametype):
+ if not attrs.get("names"):
+ self.doSchemaError("allowed section names must be specified")
+ anyname = None
+ names = []
+ s = attrs["names"]
+ if s in ("*", "+"):
+ aname = attrs.get("attribute")
+ if not aname:
+ self.doSchemaError(
+ "container attribute must be specified when using"
+ " '*' or '+' for section names")
+ return s, (), _identifier(aname)
+
+ for s in s.split("|"):
+ s = s.strip()
+ if not s:
+ self.doSchemaError("empty section name not allowed")
+ if s in ("*", "+"):
+ self.doSchemaError(
+ "'+' and '*' cannot be combined with other names")
+ else:
+ s = nametype.convert(s)
+ if s in ("*", "+"):
+ self.doSchemaError("nametypes may not convert to"
+ " '*' or '+'")
+ names.append(s)
+
+ if attrs.has_key("attribute"):
+ if len(names) > 1:
+ self.doSchemaError(
+ "cannot give target attribute name with"
+ " multiple named sections")
+ aname = _identifier(attrs["attribute"])
+ else:
+ aname = None
+
+ return None, tuple(names), aname
def doSchemaError(self, message):
raise ZConfig.ConfigurationError(message)
=== Packages/ZConfig/SectionMatcher.py 1.1.2.2 => 1.1.2.3 ===
--- Packages/ZConfig/SectionMatcher.py:1.1.2.2 Mon Dec 9 12:58:12 2002
+++ Packages/ZConfig/SectionMatcher.py Mon Dec 9 17:51:20 2002
@@ -60,6 +60,7 @@
for i in range(len(keys)):
name = keys[i]
ci = self.info.getinfo(name)
+ keys[i] = ci.attribute
if self._values.has_key(name):
L = self._values[key]
elif ci.ismulti():