[Zope3-checkins] CVS: Packages/ZConfig - info.py:1.1.2.4 matcher.py:1.1.2.5 schema.py:1.1.2.3
Fred L. Drake, Jr.
fred@zope.com
Wed, 11 Dec 2002 01:10:37 -0500
Update of /cvs-repository/Packages/ZConfig
In directory cvs.zope.org:/tmp/cvs-serv2496
Modified Files:
Tag: zconfig-schema-devel-branch
info.py matcher.py schema.py
Log Message:
Basic nested sections work! Not very clean, but working.
Needs refactoring/cleanup, lots of unit tests.
=== Packages/ZConfig/info.py 1.1.2.3 => 1.1.2.4 ===
--- Packages/ZConfig/info.py:1.1.2.3 Tue Dec 10 18:25:01 2002
+++ Packages/ZConfig/info.py Wed Dec 11 01:10:36 2002
@@ -106,51 +106,75 @@
assert keytype is not None
self.typename = typename
self.keytype = keytype
- self.names = names # '*', '+', or [name1, ...]
+ self.names = names # '*', '+', or [name1, ...]
self.nametype = nametype
- self._children = [] # [(name, info), ...]
- self._attrmap = {} # {attribute: index, ...}
+ self._children = [] # [info, ...]
+ self._attrmap = {} # {attribute: index, ...}
+ self._keymap = {} # {key: index, ...}
+ self._secttypemap = {} # {section type: info, ...}
+ if datatype is None:
+ datatype = _null_conversion
KeyInfo.__init__(self, None, datatype, minOccurs, maxOccurs,
handler, attribute)
- def _add_child(self, name, 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 __len__(self):
+ return len(self._children)
+
+ def __getitem__(self, index):
+ return self._children[index]
+
+ def _add_child(self, key, info):
+ # check naming constraints
+ assert key or info.attribute
+ if key and self._keymap.has_key(key):
+ raise ValueError("child name %s already used" % key)
+ if info.attribute and self._attrmap.has_key(info.attribute):
+ raise ValueError("child attribute name %s already used"
+ % info.attribute)
+ # a-ok, add the item to the appropriate maps
+ if info.attribute:
+ self._attrmap[info.attribute] = len(self._children)
+ if key:
+ self._keymap[key] = len(self._children)
+ self._children.append((key, info))
def addkey(self, keyinfo):
self._add_child(keyinfo.name, keyinfo)
def addsection(self, name, sectinfo):
assert name not in ("*", "+")
+ # Check that this isn't a different definition of the section type,
+ # since once _add_child() returns we must succeed, or undo a whole
+ # bunch of stuff. This is the easier alternative. ;-)
+ oldinfo = self._secttypemap.get(sectinfo.typename)
+ if oldinfo not in (None, sectinfo):
+ raise ZConfig.ConfigurationError(
+ "duplicate definition of section type " + `name`)
self._add_child(name, sectinfo)
+ self._secttypemap[sectinfo.typename] = sectinfo
- def getinfo(self, name):
- if not name:
+ def getinfo(self, key):
+ if not key:
raise ZConfig.ConfigurationError(
"cannot match a key without a name")
- for n, info in self._children:
- if n == name:
- return info
- raise ZConfig.ConfigurationError("no key matching " + `name`)
+ index = self._keymap.get(key)
+ if index is None:
+ raise ZConfig.ConfigurationError("no key matching " + `key`)
+ else:
+ return self._children[index][1]
def getchildnames(self):
- return [n for (n,info) in self._children]
+ return [key for (key, info) in self._children]
def getsectionindex(self, type, name):
index = -1
- for n, info in self._children:
+ for key, info in self._children:
index += 1
- if n:
- if n == name:
+ if key:
+ if key == name:
if not info.issection():
raise ZConfig.ConfigurationError(
- "section name %s already in use for key"
- % str(n))
+ "section name %s already in use for key" % key)
if not info.typename == type:
raise ZConfig.ConfigurationError(
"name %s must be used for a %s section"
@@ -194,3 +218,10 @@
def isAllowedName(self, name):
return False
+
+
+class NullConversion:
+ def convert(self, value):
+ return value
+
+_null_conversion = NullConversion()
=== Packages/ZConfig/matcher.py 1.1.2.4 => 1.1.2.5 ===
--- Packages/ZConfig/matcher.py:1.1.2.4 Tue Dec 10 18:25:01 2002
+++ Packages/ZConfig/matcher.py Wed Dec 11 01:10:36 2002
@@ -19,68 +19,85 @@
raise ZConfig.ConfigurationError(
`info.name` + " sections may not be unnamed")
self.info = info
- self._values = {}
+ self._values = [None] * len(info)
def addSection(self, type, name, sectvalue):
i = self.info.getsectionindex(type, name)
- raise NotImpementedError("still working on this...")
+ ci = self.info.getsectioninfo(type, name)
+ v = self._values[i]
+ if v is None and ci.ismulti():
+ v = [sectvalue]
+ self._values[i] = v
+ elif ci.ismulti():
+ v.append(sectvalue)
+ else:
+ self._values[i] = sectvalue
def addValue(self, key, value):
- keyinfo = self.info.getinfo(key)
- if keyinfo.issection():
- if keyinfo.name:
+ length = len(self.info)
+ for i in range(length):
+ k, ci = self.info[i]
+ if k == key:
+ break
+ else:
+ raise ZConfig.ConfigurationError(
+ `key` + " is not a known key name")
+ if ci.issection():
+ if ci.name:
extra = " in %s sections" % `self.info.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`)
+
+ v = self._values[i]
+ if v is None:
+ if ci.ismulti():
+ v = []
+ self._values[i] = v
+ elif not ci.ismulti():
+ raise ZConfig.ConfigurationError(
+ `key` + " does not support multiple values")
+ elif len(v) == ci.maxOccurs:
+ raise ZConfig.ConfigurationError(
+ "too many values for " + `name`)
+
+ if ci.ismulti():
+ v.append(value)
else:
- L.append(value)
- self._values[key] = L
+ self._values[i] = value
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()
- return self.constuct()
-
- 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)
+ length = len(self.info)
+ values = [None] * length
+ keys = [None] * length
+ for i in range(length):
+ key, ci = self.info[i]
keys[i] = ci.attribute
- if self._values.has_key(name):
- L = self._values[name]
- elif ci.ismulti():
- L = ci.getdefault()
- else:
- L = [ci.getdefault()]
+ if ci.ismulti() and len(self._values[i]) < ci.minOccurs:
+ raise ZConfig.ConfigurationError(
+ "not enough values for %s; %d found, %d required"
+ % (`key`, len(L), ci.minOccurs))
+ v = self._values[i]
+ if v is None:
+ if ci.ismulti():
+ v = ci.getdefault()[:]
+ else:
+ v = ci.getdefault()
+ self._values[i] = v
+ return self.constuct(keys, values)
+
+ def constuct(self, keys, values):
+ length = len(self.info)
+ for i in range(length):
+ name, ci = self.info[i]
+ dt = ci.datatype
if ci.ismulti():
- values[i] = [ci.datatype.convert(s) for s in L]
- elif ci.issection() and ci.datatype is None:
- values[i] = L[0]
+ values[i] = [dt.convert(s) for s in self._values[i]]
else:
- assert len(L) == 1
- values[i] = ci.datatype.convert(L[0])
+ values[i] = dt.convert(self._values[i])
v = SectionValue(keys, values)
# XXX Really should delay this until after all the
# XXX sibling SectionValue instances have been created and
=== Packages/ZConfig/schema.py 1.1.2.2 => 1.1.2.3 ===
--- Packages/ZConfig/schema.py:1.1.2.2 Tue Dec 10 18:25:01 2002
+++ Packages/ZConfig/schema.py Wed Dec 11 01:10:36 2002
@@ -40,15 +40,15 @@
def startElement(self, name, attrs):
attrs = dict(attrs)
if name == "schema":
- if self._schema:
+ if self._schema is not None:
self.doSchemaError("schema element improperly nested")
self.start_schema(attrs)
elif name in self._handled_tags:
- if not self._schema:
+ if self._schema is None:
self.doSchemaError(name + " element outside of schema")
getattr(self, "start_" + name)(attrs)
elif name in self._cdata_tags:
- if not self._schema:
+ if self._schema is None:
self.doSchemaError(name + " element outside of schema")
if self._cdata is not None:
self.doSchemaError(name + " element improperly nested")