[Zope-Checkins] CVS: Packages/ZConfig - __init__.py:1.3.10.6 datatypes.py:1.1.2.13 info.py:1.1.2.17 schema.py:1.1.2.29

Fred L. Drake, Jr. fred@zope.com
Thu, 19 Dec 2002 11:51:57 -0500


Update of /cvs-repository/Packages/ZConfig
In directory cvs.zope.org:/tmp/cvs-serv28967

Modified Files:
      Tag: zconfig-schema-devel-branch
	__init__.py datatypes.py info.py schema.py 
Log Message:
Straighten out exceptions so schema parsing gets a distinct exception type
that carries location information as usable attributes.


=== Packages/ZConfig/__init__.py 1.3.10.5 => 1.3.10.6 ===
--- Packages/ZConfig/__init__.py:1.3.10.5	Mon Dec 16 13:26:09 2002
+++ Packages/ZConfig/__init__.py	Thu Dec 19 11:51:27 2002
@@ -38,6 +38,37 @@
         return self.message
 
 
+class _ParseError(ConfigurationError):
+    def __init__(self, msg, url, lineno, colno=None):
+        self.url = url
+        self.lineno = lineno
+        self.colno = colno
+        ConfigurationError.__init__(self, msg)
+
+    def __str__(self):
+        s = self.message
+        if self.url:
+            s += "\n("
+        elif (self.lineno, self.colno) != (None, None):
+            s += " ("
+        if self.lineno:
+            s += "line %d" % self.lineno
+            if self.colno is not None:
+                s += ", column %d" % self.colno
+            if self.url:
+                s += " in %s)" % self.url
+        elif self.url:
+            s += self.url + ")"
+        return self.message + s
+
+
+class SchemaError(_ParseError):
+    """Raised when there's an error in the schema itself."""
+
+    def __init__(self, msg, url=None, lineno=None, colno=None):
+        _ParseError.__init__(self, msg, url, lineno, colno)
+
+
 class ConfigurationMissingSectionError(ConfigurationError):
     def __init__(self, type, name=None):
         self.type = type
@@ -58,14 +89,8 @@
         ConfigurationError.__init__(self, details + ')')
 
 
-class ConfigurationSyntaxError(ConfigurationError):
-    def __init__(self, msg, url, lineno):
-        self.url = url
-        self.lineno = lineno
-        ConfigurationError.__init__(self, msg)
-
-    def __str__(self):
-        return "%s\n(line %s in %s)" % (self.message, self.lineno, self.url)
+class ConfigurationSyntaxError(_ParseError):
+    """Raised when there's a syntax error in a configuration file."""
 
 
 class ConfigurationTypeError(ConfigurationError):


=== Packages/ZConfig/datatypes.py 1.1.2.12 => 1.1.2.13 ===
--- Packages/ZConfig/datatypes.py:1.1.2.12	Fri Dec 13 15:38:57 2002
+++ Packages/ZConfig/datatypes.py	Thu Dec 19 11:51:27 2002
@@ -168,8 +168,6 @@
         self._other = {}
 
     def get(self, name):
-        if name is None:
-            name = "str"
         t = self._stock.get(name)
         if t is None:
             t = self._other.get(name)


=== Packages/ZConfig/info.py 1.1.2.16 => 1.1.2.17 ===
--- Packages/ZConfig/info.py:1.1.2.16	Wed Dec 18 11:15:59 2002
+++ Packages/ZConfig/info.py	Thu Dec 19 11:51:27 2002
@@ -51,13 +51,19 @@
 class BaseInfo:
     """Information about a single configuration key."""
 
+    description = None
+    example = None
+    metadefault = None
+
     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")
+                raise ZConfig.SchemaError(
+                    "maxOccurs must be at least 1")
             if minOccurs is not None and minOccurs < maxOccurs:
-                raise ValueError("minOccurs must be at least maxOccurs")
+                raise ZConfig.SchemaError(
+                    "minOccurs must be at least maxOccurs")
         self.name = name
         self.datatype = datatype
         self.minOccurs = minOccurs
@@ -130,11 +136,11 @@
         # attribute   - name of the attribute on the SectionValue object
         if maxOccurs > 1:
             if name not in ('*', '+'):
-                raise ZConfig.ConfigurationError(
+                raise ZConfig.SchemaError(
                     "sections which can occur more than once must"
                     " use a name of '*' or '+'")
             if not attribute:
-                raise ZConfig.ConfigurationError(
+                raise ZConfig.SchemaError(
                     "sections which can occur more than once must"
                     " specify a target attribute name")
         if sectiontype.istypegroup():
@@ -174,7 +180,7 @@
     def addtype(self, typeinfo):
         n = typeinfo.name.lower()
         if self._types.has_key(n):
-            raise ZConfig.ConfigurationError("type name cannot be redefined: "
+            raise ZConfig.SchemaError("type name cannot be redefined: "
                                              + `typeinfo.name`)
         self._types[n] = typeinfo
 
@@ -183,14 +189,14 @@
         try:
             return self._types[n]
         except KeyError:
-            raise ZConfig.ConfigurationError("unknown type name: " + `name`)
+            raise ZConfig.SchemaError("unknown type name: " + `name`)
 
     def gettypenames(self):
         return self._types.keys()
 
     def finish(self):
         if not self._types:
-            raise ZConfig.ConfigurationError(
+            raise ZConfig.SchemaError(
                 "sectiongroup must contain at least on sectiontype")
 
 
@@ -227,10 +233,11 @@
         # check naming constraints
         assert key or info.attribute
         if key and self._keymap.has_key(key):
-            raise ValueError("child name %s already used" % key)
+            raise ZConfig.SchemaError(
+                "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)
+            raise ZConfig.SchemaError(
+                "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)


=== Packages/ZConfig/schema.py 1.1.2.28 => 1.1.2.29 ===
--- Packages/ZConfig/schema.py:1.1.2.28	Thu Dec 19 10:18:29 2002
+++ Packages/ZConfig/schema.py	Thu Dec 19 11:51:27 2002
@@ -111,7 +111,7 @@
         if v is None:
             return v
         else:
-            return self._basic_key(v)
+            return self.basic_key(v)
 
     def push_prefix(self, attrs):
         name = attrs.get("prefix")
@@ -137,9 +137,13 @@
     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 self._registry.get(default)
+            dtname = default
+
+        try:
+            return self._registry.get(dtname)
+        except ValueError, e:
+            self.error(e[0])
 
     def get_sect_typeinfo(self, attrs):
         keytype = self.get_datatype(attrs, "keytype", "basic-key")
@@ -164,7 +168,7 @@
         if not name:
             self.error(
                 "sectiontype name must not be omitted or empty")
-        name = self._identifier(name)
+        name = self.identifier(name)
         self.push_prefix(attrs)
         keytype, valuetype, datatype = self.get_sect_typeinfo(attrs)
         sectinfo = info.SectionType(name, keytype, valuetype, datatype)
@@ -290,7 +294,7 @@
             self.error(element + " name must be specified and non-empty")
         aname = attrs.get("attribute")
         if aname:
-            aname = self._identifier(aname)
+            aname = self.identifier(aname)
         if name in ("*", "+"):
             if not aname:
                 self.error(
@@ -301,13 +305,38 @@
             # run the keytype converter to make sure this is a valid key
             name = self._stack[-1].keytype(name)
             if not aname:
-                aname = self._basic_key(name)
-                aname = self._identifier(aname.replace('-', '_'))
-            return None, self._basic_key(name), aname
+                aname = self.basic_key(name)
+                aname = self.identifier(aname.replace('-', '_'))
+            return None, self.basic_key(name), aname
+
+    # datatype conversion wrappers
+
+    def basic_key(self, s):
+        try:
+            return self._basic_key(s)
+        except ValueError, e:
+            self.error(e[0])
+        except ZConfig.SchemaError, e:
+            self.initerror(e)
+            raise
+
+    def identifier(self, s):
+        try:
+            return self._identifier(s)
+        except ValueError, e:
+            self.error(e[0])
+        except ZConfig.SchemaError, e:
+            self.initerror(e)
+            raise
 
-    def error(self, message):
+    # exception setup helpers
+
+    def initerror(self, e):
         if self._locator is not None:
-            colno = self._locator.getColumnNumber()
-            lineno = self._locator.getLineNumber()
-            message = message + ' (at line %s, column %s)' % (lineno, colno)
-        raise ZConfig.ConfigurationError(message)
+            e.colno = self._locator.getColumnNumber()
+            e.lineno = self._locator.getLineNumber()
+            e.url = self._locator.getSystemId()
+        return e
+
+    def error(self, message):
+        raise self.initerror(ZConfig.SchemaError(message))