[Zconfig] SVN: ZConfig/trunk/ fix up the ZConfig tree to separate distribution stuff from code

Fred L. Drake, Jr. fdrake at gmail.com
Mon Sep 19 16:22:49 EDT 2005


Log message for revision 38533:
  fix up the ZConfig tree to separate distribution stuff from code

Changed:
  A   ZConfig/trunk/DEPENDENCIES.cfg
  U   ZConfig/trunk/PACKAGE.cfg
  U   ZConfig/trunk/SETUP.cfg
  A   ZConfig/trunk/ZConfig/
  A   ZConfig/trunk/ZConfig/__init__.py
  A   ZConfig/trunk/ZConfig/cfgparser.py
  A   ZConfig/trunk/ZConfig/cmdline.py
  A   ZConfig/trunk/ZConfig/components/
  A   ZConfig/trunk/ZConfig/datatypes.py
  A   ZConfig/trunk/ZConfig/info.py
  A   ZConfig/trunk/ZConfig/loader.py
  A   ZConfig/trunk/ZConfig/matcher.py
  A   ZConfig/trunk/ZConfig/schema.py
  A   ZConfig/trunk/ZConfig/substitution.py
  A   ZConfig/trunk/ZConfig/tests/
  A   ZConfig/trunk/ZConfig/url.py
  D   ZConfig/trunk/__init__.py
  D   ZConfig/trunk/cfgparser.py
  D   ZConfig/trunk/cmdline.py
  D   ZConfig/trunk/components/
  D   ZConfig/trunk/datatypes.py
  D   ZConfig/trunk/info.py
  D   ZConfig/trunk/loader.py
  D   ZConfig/trunk/matcher.py
  D   ZConfig/trunk/schema.py
  D   ZConfig/trunk/substitution.py
  D   ZConfig/trunk/tests/
  D   ZConfig/trunk/url.py
  A   ZConfig/trunk/zpkg.conf

-=-
Added: ZConfig/trunk/DEPENDENCIES.cfg
===================================================================
--- ZConfig/trunk/DEPENDENCIES.cfg	2005-09-19 19:53:54 UTC (rev 38532)
+++ ZConfig/trunk/DEPENDENCIES.cfg	2005-09-19 20:22:48 UTC (rev 38533)
@@ -0,0 +1,6 @@
+# We need this since we're playing games with zpkg.  As far as zpkg is
+# concerned, we're building a small collection distribution that
+# contains a single Python package.  That package is what we're naming
+# here.
+
+ZConfig


Property changes on: ZConfig/trunk/DEPENDENCIES.cfg
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:eol-style
   + native

Modified: ZConfig/trunk/PACKAGE.cfg
===================================================================
--- ZConfig/trunk/PACKAGE.cfg	2005-09-19 19:53:54 UTC (rev 38532)
+++ ZConfig/trunk/PACKAGE.cfg	2005-09-19 20:22:48 UTC (rev 38533)
@@ -2,21 +2,16 @@
 
 # Add a few things to the distribution root.
 <distribution>
-  doc
   LICENSE.txt
   NEWS.txt
   README.txt
+  doc/zconfig.pdf
+  doc/schema.dtd
 </distribution>
 
 # Specify what is included in the component.
 <collection>
-  # Python modules from the package:
-  *.py
-
-  # Child packages:
-  components
-  tests
-
-  # Other files and directories needed when distutils runs:
+  doc/zconfig.pdf
+  doc/schema.dtd
   scripts
 </collection>

Modified: ZConfig/trunk/SETUP.cfg
===================================================================
--- ZConfig/trunk/SETUP.cfg	2005-09-19 19:53:54 UTC (rev 38532)
+++ ZConfig/trunk/SETUP.cfg	2005-09-19 20:22:48 UTC (rev 38533)
@@ -1,6 +1,6 @@
 # Metadata used by zpkg.
 
-#documentation  doc/zconfig.pdf
-#documentation  doc/schema.dtd
+documentation  doc/zconfig.pdf
+documentation  doc/schema.dtd
 
 script scripts/zconfig*

Copied: ZConfig/trunk/ZConfig/__init__.py (from rev 38532, ZConfig/trunk/__init__.py)

Copied: ZConfig/trunk/ZConfig/cfgparser.py (from rev 38532, ZConfig/trunk/cfgparser.py)

Copied: ZConfig/trunk/ZConfig/cmdline.py (from rev 38532, ZConfig/trunk/cmdline.py)

Copied: ZConfig/trunk/ZConfig/components (from rev 38532, ZConfig/trunk/components)

Copied: ZConfig/trunk/ZConfig/datatypes.py (from rev 38532, ZConfig/trunk/datatypes.py)

Copied: ZConfig/trunk/ZConfig/info.py (from rev 38532, ZConfig/trunk/info.py)

Copied: ZConfig/trunk/ZConfig/loader.py (from rev 38532, ZConfig/trunk/loader.py)

Copied: ZConfig/trunk/ZConfig/matcher.py (from rev 38532, ZConfig/trunk/matcher.py)

Copied: ZConfig/trunk/ZConfig/schema.py (from rev 38532, ZConfig/trunk/schema.py)

Copied: ZConfig/trunk/ZConfig/substitution.py (from rev 38532, ZConfig/trunk/substitution.py)

Copied: ZConfig/trunk/ZConfig/tests (from rev 38532, ZConfig/trunk/tests)

Copied: ZConfig/trunk/ZConfig/url.py (from rev 38532, ZConfig/trunk/url.py)

Deleted: ZConfig/trunk/__init__.py
===================================================================
--- ZConfig/trunk/__init__.py	2005-09-19 19:53:54 UTC (rev 38532)
+++ ZConfig/trunk/__init__.py	2005-09-19 20:22:48 UTC (rev 38533)
@@ -1,128 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2002, 2003 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-"""Configuration data structures and loader for the ZRS.
-
-$Id: __init__.py,v 1.18 2004/04/15 20:33:32 fdrake Exp $
-"""
-version_info = (2, 3)
-__version__ = ".".join([str(n) for n in version_info])
-
-from ZConfig.loader import loadConfig, loadConfigFile
-from ZConfig.loader import loadSchema, loadSchemaFile
-
-
-class ConfigurationError(Exception):
-    """Base class for ZConfig exceptions."""
-
-    def __init__(self, msg, url=None):
-        self.message = msg
-        self.url = url
-        Exception.__init__(self, msg)
-
-    def __str__(self):
-        return self.message
-
-
-class _ParseError(ConfigurationError):
-    def __init__(self, msg, url, lineno, colno=None):
-        self.lineno = lineno
-        self.colno = colno
-        ConfigurationError.__init__(self, msg, url)
-
-    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
-            else:
-                s += ")"
-        elif self.url:
-            s += self.url + ")"
-        return 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 SchemaResourceError(SchemaError):
-    """Raised when there's an error locating a resource required by the schema.
-    """
-
-    def __init__(self, msg, url=None, lineno=None, colno=None,
-                 path=None, package=None, filename=None):
-        self.filename = filename
-        self.package = package
-        if path is not None:
-            path = path[:]
-        self.path = path
-        SchemaError.__init__(self, msg, url, lineno, colno)
-
-    def __str__(self):
-        s = SchemaError.__str__(self)
-        if self.package is not None:
-            s += "\n  Package name: " + repr(self.package)
-        if self.filename is not None:
-            s += "\n  File name: " + repr(self.filename)
-        if self.package is not None:
-            s += "\n  Package path: " + repr(self.path)
-        return s
-
-
-class ConfigurationSyntaxError(_ParseError):
-    """Raised when there's a syntax error in a configuration file."""
-
-
-class DataConversionError(ConfigurationError, ValueError):
-    """Raised when a data type conversion function raises ValueError."""
-
-    def __init__(self, exception, value, position):
-        ConfigurationError.__init__(self, str(exception))
-        self.exception = exception
-        self.value = value
-        self.lineno, self.colno, self.url = position
-
-    def __str__(self):
-        s = "%s (line %s" % (self.message, self.lineno)
-        if self.colno is not None:
-            s += ", %s" % self.colno
-        if self.url:
-            s += ", in %s)" % self.url
-        else:
-            s += ")"
-        return s
-
-
-class SubstitutionSyntaxError(ConfigurationError):
-    """Raised when interpolation source text contains syntactical errors."""
-
-
-class SubstitutionReplacementError(ConfigurationSyntaxError, LookupError):
-    """Raised when no replacement is available for a reference."""
-
-    def __init__(self, source, name, url=None, lineno=None):
-        self.source = source
-        self.name = name
-        ConfigurationSyntaxError.__init__(
-            self, "no replacement for " + `name`, url, lineno)

Deleted: ZConfig/trunk/cfgparser.py
===================================================================
--- ZConfig/trunk/cfgparser.py	2005-09-19 19:53:54 UTC (rev 38532)
+++ ZConfig/trunk/cfgparser.py	2005-09-19 20:22:48 UTC (rev 38533)
@@ -1,193 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2002, 2003 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-"""Configuration parser."""
-
-import ZConfig
-import ZConfig.url
-
-from ZConfig.substitution import isname, substitute
-
-
-class ZConfigParser:
-    __metaclass__ = type
-    __slots__ = ('resource', 'context', 'lineno',
-                 'stack', 'defines', 'file', 'url')
-
-    def __init__(self, resource, context, defines=None):
-        self.resource = resource
-        self.context = context
-        self.file = resource.file
-        self.url = resource.url
-        self.lineno = 0
-        self.stack = []   # [(type, name, prevmatcher), ...]
-        if defines is None:
-            defines = {}
-        self.defines = defines
-
-    def nextline(self):
-        line = self.file.readline()
-        if line:
-            self.lineno += 1
-            return False, line.strip()
-        else:
-            return True, None
-
-    def parse(self, section):
-        done, line = self.nextline()
-        while not done:
-            if line[:1] in ("", "#"):
-                # blank line or comment
-                pass
-
-            elif line[:2] == "</":
-                # section end
-                if line[-1] != ">":
-                    self.error("malformed section end")
-                section = self.end_section(section, line[2:-1])
-
-            elif line[0] == "<":
-                # section start
-                if line[-1] != ">":
-                    self.error("malformed section start")
-                section = self.start_section(section, line[1:-1])
-
-            elif line[0] == "%":
-                self.handle_directive(section, line[1:])
-
-            else:
-                self.handle_key_value(section, line)
-
-            done, line = self.nextline()
-
-        if self.stack:
-            self.error("unclosed sections not allowed")
-
-    def start_section(self, section, rest):
-        isempty = rest[-1:] == "/"
-        if isempty:
-            rest = rest[:-1]
-        text = rest.rstrip()
-        # parse section start stuff here
-        m = _section_start_rx.match(text)
-        if not m:
-            self.error("malformed section header")
-        type, name = m.group('type', 'name')
-        type = self._normalize_case(type)
-        if name:
-            name = self._normalize_case(name)
-        try:
-            newsect = self.context.startSection(section, type, name)
-        except ZConfig.ConfigurationError, e:
-            self.error(e[0])
-
-        if isempty:
-            self.context.endSection(section, type, name, newsect)
-            return section
-        else:
-            self.stack.append((type, name, section))
-            return newsect
-
-    def end_section(self, section, rest):
-        if not self.stack:
-            self.error("unexpected section end")
-        type = self._normalize_case(rest.rstrip())
-        opentype, name, prevsection = self.stack.pop()
-        if type != opentype:
-            self.error("unbalanced section end")
-        try:
-            self.context.endSection(
-                prevsection, type, name, section)
-        except ZConfig.ConfigurationError, e:
-            self.error(e[0])
-        return prevsection
-
-    def handle_key_value(self, section, rest):
-        m = _keyvalue_rx.match(rest)
-        if not m:
-            self.error("malformed configuration data")
-        key, value = m.group('key', 'value')
-        if not value:
-            value = ''
-        else:
-            value = self.replace(value)
-        try:
-            section.addValue(key, value, (self.lineno, None, self.url))
-        except ZConfig.ConfigurationError, e:
-            self.error(e[0])
-
-    def handle_directive(self, section, rest):
-        m = _keyvalue_rx.match(rest)
-        if not m:
-            self.error("missing or unrecognized directive")
-        name, arg = m.group('key', 'value')
-        if name not in ("define", "import", "include"):
-            self.error("unknown directive: " + `name`)
-        if not arg:
-            self.error("missing argument to %%%s directive" % name)
-        if name == "include":
-            self.handle_include(section, arg)
-        elif name == "define":
-            self.handle_define(section, arg)
-        elif name == "import":
-            self.handle_import(section, arg)
-        else:
-            assert 0, "unexpected directive for " + `"%" + rest`
-
-    def handle_import(self, section, rest):
-        pkgname = self.replace(rest.strip())
-        self.context.importSchemaComponent(pkgname)
-
-    def handle_include(self, section, rest):
-        rest = self.replace(rest.strip())
-        newurl = ZConfig.url.urljoin(self.url, rest)
-        self.context.includeConfiguration(section, newurl, self.defines)
-
-    def handle_define(self, section, rest):
-        parts = rest.split(None, 1)
-        defname = self._normalize_case(parts[0])
-        defvalue = ''
-        if len(parts) == 2:
-            defvalue = parts[1]
-        if self.defines.has_key(defname):
-            self.error("cannot redefine " + `defname`)
-        if not isname(defname):
-            self.error("not a substitution legal name: " + `defname`)
-        self.defines[defname] = self.replace(defvalue)
-
-    def replace(self, text):
-        try:
-            return substitute(text, self.defines)
-        except ZConfig.SubstitutionReplacementError, e:
-            e.lineno = self.lineno
-            e.url = self.url
-            raise
-
-    def error(self, message):
-        raise ZConfig.ConfigurationSyntaxError(message, self.url, self.lineno)
-
-    def _normalize_case(self, string):
-        return string.lower()
-
-
-import re
-# _name_re does not allow "(" or ")" for historical reasons.  Though
-# the restriction could be lifted, there seems no need to do so.
-_name_re = r"[^\s()]+"
-_keyvalue_rx = re.compile(r"(?P<key>%s)\s*(?P<value>[^\s].*)?$"
-                          % _name_re)
-_section_start_rx = re.compile(r"(?P<type>%s)"
-                               r"(?:\s+(?P<name>%s))?"
-                               r"$"
-                               % (_name_re, _name_re))
-del re

Deleted: ZConfig/trunk/cmdline.py
===================================================================
--- ZConfig/trunk/cmdline.py	2005-09-19 19:53:54 UTC (rev 38532)
+++ ZConfig/trunk/cmdline.py	2005-09-19 20:22:48 UTC (rev 38533)
@@ -1,182 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2003 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-
-"""Support for command-line provision of settings.
-
-This module provides an extension of the ConfigLoader class which adds
-a way to add configuration settings from an alternate source.  Each
-setting is described by a string of the form::
-
-    some/path/to/key=value
-"""
-
-import ZConfig
-import ZConfig.loader
-import ZConfig.matcher
-
-
-class ExtendedConfigLoader(ZConfig.loader.ConfigLoader):
-    def __init__(self, schema):
-        ZConfig.loader.ConfigLoader.__init__(self, schema)
-        self.clopts = []   # [(optpath, value, source-position), ...]
-
-    def addOption(self, spec, pos=None):
-        if pos is None:
-            pos = "<command-line option>", -1, -1
-        if "=" not in spec:
-            e = ZConfig.ConfigurationSyntaxError(
-                "invalid configuration specifier", *pos)
-            e.specifier = spec
-            raise e
-        # For now, just add it to the list; not clear that checking
-        # against the schema at this point buys anything.
-        opt, val = spec.split("=", 1)
-        optpath = opt.split("/")
-        if "" in optpath:
-            # // is not allowed in option path
-            e = ZConfig.ConfigurationSyntaxError(
-                "'//' is not allowed in an option path", *pos)
-            e.specifier = spec
-            raise e
-        self.clopts.append((optpath, val, pos))
-
-    def createSchemaMatcher(self):
-        if self.clopts:
-            sm = ExtendedSchemaMatcher(self.schema)
-            sm.set_optionbag(self.cook())
-        else:
-            sm = ZConfig.loader.ConfigLoader.createSchemaMatcher(self)
-        return sm
-
-    def cook(self):
-        if self.clopts:
-            return OptionBag(self.schema, self.schema, self.clopts)
-        else:
-            return None
-
-
-class OptionBag:
-    def __init__(self, schema, sectiontype, options):
-        self.sectiontype = sectiontype
-        self.schema = schema
-        self.keypairs = {}
-        self.sectitems = []
-        self._basic_key = schema.registry.get("basic-key")
-        for item in options:
-            optpath, val, pos = item
-            name = sectiontype.keytype(optpath[0])
-            if len(optpath) == 1:
-                self.add_value(name, val, pos)
-            else:
-                self.sectitems.append(item)
-
-    def basic_key(self, s, pos):
-        try:
-            return self._basic_key(s)
-        except ValueError:
-            raise ZConfig.ConfigurationSyntaxError(
-                "could not convert basic-key value", *pos)
-
-    def add_value(self, name, val, pos):
-        if self.keypairs.has_key(name):
-            L = self.keypairs[name]
-        else:
-            L = []
-            self.keypairs[name] = L
-        L.append((val, pos))
-
-    def has_key(self, name):
-        return self.keypairs.has_key(name)
-
-    def get_key(self, name):
-        """Return a list of (value, pos) items for the key 'name'.
-
-        The returned list may be empty.
-        """
-        L = self.keypairs.get(name)
-        if L:
-            del self.keypairs[name]
-            return L
-        else:
-            return []
-
-    def keys(self):
-        return self.keypairs.keys()
-
-    def get_section_info(self, type, name):
-        L = []  # what pertains to the child section
-        R = []  # what we keep
-        for item in self.sectitems:
-            optpath, val, pos = item
-            s = optpath[0]
-            bk = self.basic_key(s, pos)
-            if name and self._normalize_case(s) == name:
-                L.append((optpath[1:], val, pos))
-            elif bk == type:
-                L.append((optpath[1:], val, pos))
-            else:
-                R.append(item)
-        if L:
-            self.sectitems[:] = R
-            return OptionBag(self.schema, self.schema.gettype(type), L)
-        else:
-            return None
-
-    def finish(self):
-        if self.sectitems or self.keypairs:
-            raise ZConfig.ConfigurationError(
-                "not all command line options were consumed")
-
-    def _normalize_case(self, string):
-        return string.lower()
-
-
-class MatcherMixin:
-    def set_optionbag(self, bag):
-        self.optionbag = bag
-
-    def addValue(self, key, value, position):
-        try:
-            realkey = self.type.keytype(key)
-        except ValueError, e:
-            raise ZConfig.DataConversionError(e, key, position)
-        if self.optionbag.has_key(realkey):
-            return
-        ZConfig.matcher.BaseMatcher.addValue(self, key, value, position)
-
-    def createChildMatcher(self, type, name):
-        sm = ZConfig.matcher.BaseMatcher.createChildMatcher(self, type, name)
-        bag = self.optionbag.get_section_info(type.name, name)
-        if bag is not None:
-            sm = ExtendedSectionMatcher(
-                sm.info, sm.type, sm.name, sm.handlers)
-            sm.set_optionbag(bag)
-        return sm
-
-    def finish_optionbag(self):
-        for key in self.optionbag.keys():
-            for val, pos in self.optionbag.get_key(key):
-                ZConfig.matcher.BaseMatcher.addValue(self, key, val, pos)
-        self.optionbag.finish()
-
-
-class ExtendedSectionMatcher(MatcherMixin, ZConfig.matcher.SectionMatcher):
-    def finish(self):
-        self.finish_optionbag()
-        return ZConfig.matcher.SectionMatcher.finish(self)
-
-class ExtendedSchemaMatcher(MatcherMixin, ZConfig.matcher.SchemaMatcher):
-    def finish(self):
-        self.finish_optionbag()
-        return ZConfig.matcher.SchemaMatcher.finish(self)

Deleted: ZConfig/trunk/datatypes.py
===================================================================
--- ZConfig/trunk/datatypes.py	2005-09-19 19:53:54 UTC (rev 38532)
+++ ZConfig/trunk/datatypes.py	2005-09-19 20:22:48 UTC (rev 38533)
@@ -1,425 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2002, 2003 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-"""Selection of standard datatypes for ZConfig."""
-
-import os
-import re
-import sys
-import datetime
-
-try:
-    unicode
-except NameError:
-    have_unicode = False
-else:
-    have_unicode = True
-
-
-class MemoizedConversion:
-    """Conversion helper that caches the results of expensive conversions."""
-
-    def __init__(self, conversion):
-        self._memo = {}
-        self._conversion = conversion
-
-    def __call__(self, value):
-        try:
-            return self._memo[value]
-        except KeyError:
-            v = self._conversion(value)
-            self._memo[value] = v
-            return v
-
-
-class RangeCheckedConversion:
-    """Conversion helper that range checks another conversion."""
-
-    def __init__(self, conversion, min=None, max=None):
-        self._min = min
-        self._max = max
-        self._conversion = conversion
-
-    def __call__(self, value):
-        v = self._conversion(value)
-        if self._min is not None and v < self._min:
-            raise ValueError("%s is below lower bound (%s)"
-                             % (`v`, `self._min`))
-        if self._max is not None and v > self._max:
-            raise ValueError("%s is above upper bound (%s)"
-                             % (`v`, `self._max`))
-        return v
-
-
-class RegularExpressionConversion:
-    reason = "value did not match regular expression"
-
-    def __init__(self, regex):
-        self._rx = re.compile(regex)
-
-    def __call__(self, value):
-        m = self._rx.match(value)
-        if m and m.group() == value:
-            return value
-        else:
-            raise ValueError("%s: %s" % (self.reason, repr(value)))
-
-
-def check_locale(value):
-    import locale
-    prev = locale.setlocale(locale.LC_ALL)
-    try:
-        try:
-            locale.setlocale(locale.LC_ALL, value)
-        finally:
-            locale.setlocale(locale.LC_ALL, prev)
-    except locale.Error:
-        raise ValueError(
-            'The specified locale "%s" is not supported by your system.\n'
-            'See your operating system documentation for more\n'
-            'information on locale support.' % value)
-    else:
-        return value
-
-
-class BasicKeyConversion(RegularExpressionConversion):
-    def __init__(self):
-        RegularExpressionConversion.__init__(self, "[a-zA-Z][-._a-zA-Z0-9]*")
-
-    def __call__(self, value):
-        value = str(value)
-        return RegularExpressionConversion.__call__(self, value).lower()
-
-
-class ASCIIConversion(RegularExpressionConversion):
-    def __call__(self, value):
-        value = RegularExpressionConversion.__call__(self, value)
-        if have_unicode and isinstance(value, unicode):
-            value = value.encode("ascii")
-        return value
-
-
-_ident_re = "[_a-zA-Z][_a-zA-Z0-9]*"
-
-class IdentifierConversion(ASCIIConversion):
-    reason = "not a valid Python identifier"
-
-    def __init__(self):
-        ASCIIConversion.__init__(self, _ident_re)
-
-
-class DottedNameConversion(ASCIIConversion):
-    reason = "not a valid dotted name"
-
-    def __init__(self):
-        ASCIIConversion.__init__(self,
-                                 r"%s(?:\.%s)*" % (_ident_re, _ident_re))
-
-
-class DottedNameSuffixConversion(ASCIIConversion):
-    reason = "not a valid dotted name or suffix"
-
-    def __init__(self):
-        ASCIIConversion.__init__(self,
-                                 r"(?:%s)(?:\.%s)*|(?:\.%s)+"
-                                 % (_ident_re, _ident_re, _ident_re))
-
-
-def integer(value):
-    try:
-        return int(value)
-    except ValueError:
-        return long(value)
-    except OverflowError:
-        return long(value)
-
-
-def null_conversion(value):
-    return value
-
-
-def asBoolean(s):
-    """Convert a string value to a boolean value."""
-    ss = str(s).lower()
-    if ss in ('yes', 'true', 'on'):
-        return True
-    elif ss in ('no', 'false', 'off'):
-        return False
-    else:
-        raise ValueError("not a valid boolean value: " + repr(s))
-
-
-def string_list(s):
-    """Convert a string to a list of strings using .split()."""
-    return s.split()
-
-
-port_number = RangeCheckedConversion(integer, min=1, max=0xffff).__call__
-
-
-class InetAddress:
-
-    def __init__(self, default_host):
-        self.DEFAULT_HOST = default_host
-
-    def __call__(self, s):
-        # returns (host, port) tuple
-        host = ''
-        port = None
-        if ":" in s:
-            host, s = s.split(":", 1)
-            if s:
-                port = port_number(s)
-            host = host.lower()
-        else:
-            try:
-                port = port_number(s)
-            except ValueError:
-                if len(s.split()) != 1:
-                    raise ValueError("not a valid host name: " + repr(s))
-                host = s.lower()
-        if not host:
-            host = self.DEFAULT_HOST
-        return host, port
-
-
-if sys.platform[:3] == "win":
-    DEFAULT_HOST = "localhost"
-else:
-    DEFAULT_HOST = ""
-
-inet_address = InetAddress(DEFAULT_HOST)
-inet_connection_address = InetAddress("127.0.0.1")
-inet_binding_address = InetAddress("")
-
-class SocketAddress:
-    def __init__(self, s):
-        import socket
-        if "/" in s or s.find(os.sep) >= 0:
-            self.family = getattr(socket, "AF_UNIX", None)
-            self.address = s
-        else:
-            self.family = socket.AF_INET
-            self.address = self._parse_address(s)
-
-    def _parse_address(self, s):
-        return inet_address(s)
-
-class SocketBindingAddress(SocketAddress):
-
-    def _parse_address(self, s):
-        return inet_binding_address(s)
-
-class SocketConnectionAddress(SocketAddress):
-
-    def _parse_address(self, s):
-        return inet_connection_address(s)
-
-
-def float_conversion(v):
-    if isinstance(v, basestring):
-        if v.lower() in ["inf", "-inf", "nan"]:
-            raise ValueError(`v` + " is not a portable float representation")
-    return float(v)
-
-class IpaddrOrHostname(RegularExpressionConversion):
-    def __init__(self):
-        # IP address regex from the Perl Cookbook, Recipe 6.23 (revised ed.)
-        # We allow underscores in hostnames although this is considered
-        # illegal according to RFC1034.
-        expr = (r"(^(\d|[01]?\d\d|2[0-4]\d|25[0-5])\." #ipaddr
-                r"(\d|[01]?\d\d|2[0-4]\d|25[0-5])\." #ipaddr cont'd
-                r"(\d|[01]?\d\d|2[0-4]\d|25[0-5])\." #ipaddr cont'd
-                r"(\d|[01]?\d\d|2[0-4]\d|25[0-5])$)" #ipaddr cont'd
-                r"|([A-Za-z_][-A-Za-z0-9_.]*[-A-Za-z0-9_])") # or hostname
-        RegularExpressionConversion.__init__(self, expr)
-
-    def __call__(self, value):
-        return RegularExpressionConversion.__call__(self, value).lower()
-
-def existing_directory(v):
-    nv = os.path.expanduser(v)
-    if os.path.isdir(nv):
-        return nv
-    raise ValueError('%s is not an existing directory' % v)
-
-def existing_path(v):
-    nv = os.path.expanduser(v)
-    if os.path.exists(nv):
-        return nv
-    raise ValueError('%s is not an existing path' % v)
-
-def existing_file(v):
-    nv = os.path.expanduser(v)
-    if os.path.exists(nv):
-        return nv
-    raise ValueError('%s is not an existing file' % v)
-
-def existing_dirpath(v):
-    nv = os.path.expanduser(v)
-    dir = os.path.dirname(nv)
-    if not dir:
-        # relative pathname with no directory component
-        return nv
-    if os.path.isdir(dir):
-        return nv
-    raise ValueError('The directory named as part of the path %s '
-                     'does not exist.' % v)
-
-
-class SuffixMultiplier:
-    # d is a dictionary of suffixes to integer multipliers.  If no suffixes
-    # match, default is the multiplier.  Matches are case insensitive.  Return
-    # values are in the fundamental unit.
-    def __init__(self, d, default=1):
-        self._d = d
-        self._default = default
-        # all keys must be the same size
-        self._keysz = None
-        for k in d.keys():
-            if self._keysz is None:
-                self._keysz = len(k)
-            else:
-                assert self._keysz == len(k)
-
-    def __call__(self, v):
-        v = v.lower()
-        for s, m in self._d.items():
-            if v[-self._keysz:] == s:
-                return int(v[:-self._keysz]) * m
-        return int(v) * self._default
-
-
-def timedelta(s):
-    # Unlike the standard time-interval data type, which returns a float
-    # number of seconds, this datatype takes a wider range of syntax and
-    # returns a datetime.timedelta
-    #
-    # Accepts suffixes:
-    #    w - weeks
-    #    d - days
-    #    h - hours
-    #    m - minutes
-    #    s - seconds
-    #
-    # and all arguments may be integers or floats, positive or negative.
-    # More than one time interval suffix value may appear on the line, but
-    # they should all be separated by spaces, e.g.:
-    #
-    # sleep_time 4w 2d 7h 12m 0.00001s
-    weeks = days = hours = minutes = seconds = 0
-    for part in s.split():
-        val = float(part[:-1])
-        suffix = part[-1]
-        if suffix == 'w':
-            weeks = val
-        elif suffix == 'd':
-            days = val
-        elif suffix == 'h':
-            hours = val
-        elif suffix == 'm':
-            minutes = val
-        elif suffix == 's':
-            seconds = val
-        else:
-            raise TypeError('bad part %s in %s' % (part, s))
-    return datetime.timedelta(weeks=weeks, days=days, hours=hours,
-                              minutes=minutes, seconds=seconds)
-
-
-stock_datatypes = {
-    "boolean":           asBoolean,
-    "dotted-name":       DottedNameConversion(),
-    "dotted-suffix":     DottedNameSuffixConversion(),
-    "identifier":        IdentifierConversion(),
-    "integer":           integer,
-    "float":             float_conversion,
-    "string":            str,
-    "string-list":       string_list,
-    "null":              null_conversion,
-    "locale":            MemoizedConversion(check_locale),
-    "port-number":       port_number,
-    "basic-key":         BasicKeyConversion(),
-    "inet-address":      inet_address,
-    "inet-binding-address":    inet_binding_address,
-    "inet-connection-address": inet_connection_address,
-    "socket-address":    SocketAddress,
-    "socket-binding-address":    SocketBindingAddress,
-    "socket-connection-address": SocketConnectionAddress,
-    "ipaddr-or-hostname":IpaddrOrHostname(),
-    "existing-directory":existing_directory,
-    "existing-path":     existing_path,
-    "existing-file":     existing_file,
-    "existing-dirpath":  existing_dirpath,
-    "byte-size":         SuffixMultiplier({'kb': 1024,
-                                           'mb': 1024*1024,
-                                           'gb': 1024*1024*1024L,
-                                           }),
-    "time-interval":     SuffixMultiplier({'s': 1,
-                                           'm': 60,
-                                           'h': 60*60,
-                                           'd': 60*60*24,
-                                           }),
-    "timedelta":         timedelta,
-    }
-
-
-class Registry:
-    def __init__(self, stock=None):
-        if stock is None:
-            stock = stock_datatypes.copy()
-        self._stock = stock
-        self._other = {}
-        self._basic_key = None
-
-    def get(self, name):
-        if '.' not in name:
-            if self._basic_key is None:
-                self._basic_key = self._other.get("basic-key")
-                if self._basic_key is None:
-                    self._basic_key = self._stock.get("basic-key")
-                if self._basic_key is None:
-                    self._basic_key = stock_datatypes["basic-key"]
-            name = self._basic_key(name)
-        t = self._stock.get(name)
-        if t is None:
-            t = self._other.get(name)
-            if t is None:
-                t = self.search(name)
-        return t
-
-    def register(self, name, conversion):
-        if self._stock.has_key(name):
-            raise ValueError("datatype name conflicts with built-in type: "
-                             + `name`)
-        if self._other.has_key(name):
-            raise ValueError("datatype name already registered: " + `name`)
-        self._other[name] = conversion
-
-    def search(self, name):
-        if not "." in name:
-            raise ValueError("unloadable datatype name: " + `name`)
-        components = name.split('.')
-        start = components[0]
-        g = {}
-        package = __import__(start, g, g)
-        modulenames = [start]
-        for component in components[1:]:
-            modulenames.append(component)
-            try:
-                package = getattr(package, component)
-            except AttributeError:
-                n = '.'.join(modulenames)
-                package = __import__(n, g, g, component)
-        self._other[name] = package
-        return package

Deleted: ZConfig/trunk/info.py
===================================================================
--- ZConfig/trunk/info.py	2005-09-19 19:53:54 UTC (rev 38532)
+++ ZConfig/trunk/info.py	2005-09-19 20:22:48 UTC (rev 38533)
@@ -1,514 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2002, 2003 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-"""Objects that can describe a ZConfig schema."""
-
-import copy
-
-import ZConfig
-
-
-class UnboundedThing:
-    __metaclass__ = type
-    __slots__ = ()
-
-    def __lt__(self, other):
-        return False
-
-    def __le__(self, other):
-        return isinstance(other, self.__class__)
-
-    def __gt__(self, other):
-        return True
-
-    def __ge__(self, other):
-        return True
-
-    def __eq__(self, other):
-        return isinstance(other, self.__class__)
-
-    def __ne__(self, other):
-        return not isinstance(other, self.__class__)
-
-    def __repr__(self):
-        return "<Unbounded>"
-
-Unbounded = UnboundedThing()
-
-
-class ValueInfo:
-    __metaclass__ = type
-    __slots__ = 'value', 'position'
-
-    def __init__(self, value, position):
-        self.value = value
-        # position is (lineno, colno, url)
-        self.position = position
-
-    def convert(self, datatype):
-        try:
-            return datatype(self.value)
-        except ValueError, e:
-            raise ZConfig.DataConversionError(e, self.value, self.position)
-
-
-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 ZConfig.SchemaError(
-                    "maxOccurs must be at least 1")
-            if minOccurs is not None and minOccurs < maxOccurs:
-                raise ZConfig.SchemaError(
-                    "minOccurs must be at least maxOccurs")
-        self.name = name
-        self.datatype = datatype
-        self.minOccurs = minOccurs
-        self.maxOccurs = maxOccurs
-        self.handler = handler
-        self.attribute = attribute
-
-    def __repr__(self):
-        clsname = self.__class__.__name__
-        return "<%s for %s>" % (clsname, `self.name`)
-
-    def isabstract(self):
-        return False
-
-    def ismulti(self):
-        return self.maxOccurs > 1
-
-    def issection(self):
-        return False
-
-
-class BaseKeyInfo(BaseInfo):
-
-    _rawdefaults = None
-
-    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
-
-    def finish(self):
-        if self._finished:
-            raise ZConfig.SchemaError(
-                "cannot finish KeyInfo more than once")
-        self._finished = True
-
-    def adddefault(self, value, position, key=None):
-        if self._finished:
-            raise ZConfig.SchemaError(
-                "cannot add default values to finished KeyInfo")
-        # Check that the name/keyed relationship is right:
-        if self.name == "+" and key is None:
-            raise ZConfig.SchemaError(
-                "default values must be keyed for name='+'")
-        elif self.name != "+" and key is not None:
-            raise ZConfig.SchemaError(
-                "unexpected key for default value")
-        self.add_valueinfo(ValueInfo(value, position), key)
-
-    def add_valueinfo(self, vi, key):
-        """Actually add a ValueInfo to this key-info object.
-
-        The appropriate value of None-ness of key has already been
-        checked with regard to the name of the key, and has been found
-        permissible to add.
-
-        This method is a requirement for subclasses, and should not be
-        called by client code.
-        """
-        raise NotImplementedError(
-            "add_valueinfo() must be implemented by subclasses of BaseKeyInfo")
-
-    def prepare_raw_defaults(self):
-        assert self.name == "+"
-        if self._rawdefaults is None:
-            self._rawdefaults = self._default
-        self._default = {}
-
-
-class KeyInfo(BaseKeyInfo):
-
-    _default = None
-
-    def __init__(self, name, datatype, minOccurs, handler, attribute):
-        BaseKeyInfo.__init__(self, name, datatype, minOccurs, 1,
-                             handler, attribute)
-        if self.name == "+":
-            self._default = {}
-
-    def add_valueinfo(self, vi, key):
-        if self.name == "+":
-            if self._default.has_key(key):
-                # not ideal: we're presenting the unconverted
-                # version of the key
-                raise ZConfig.SchemaError(
-                    "duplicate default value for key %s" % `key`)
-            self._default[key] = vi
-        elif self._default is not None:
-            raise ZConfig.SchemaError(
-                "cannot set more than one default to key with maxOccurs == 1")
-        else:
-            self._default = vi
-
-    def computedefault(self, keytype):
-        self.prepare_raw_defaults()
-        for k, vi in self._rawdefaults.iteritems():
-            key = ValueInfo(k, vi.position).convert(keytype)
-            self.add_valueinfo(vi, key)
-
-    def getdefault(self):
-        # Use copy.copy() to make sure we don't allow polution of
-        # our internal data without having to worry about both the
-        # list and dictionary cases:
-        return copy.copy(self._default)
-
-
-class MultiKeyInfo(BaseKeyInfo):
-
-    def __init__(self, name, datatype, minOccurs, maxOccurs, handler,
-                 attribute):
-        BaseKeyInfo.__init__(self, name, datatype, minOccurs, maxOccurs,
-                             handler, attribute)
-        if self.name == "+":
-            self._default = {}
-        else:
-            self._default = []
-
-    def add_valueinfo(self, vi, key):
-        if self.name == "+":
-            # This is a keyed value, not a simple value:
-            if key in self._default:
-                self._default[key].append(vi)
-            else:
-                self._default[key] = [vi]
-        else:
-            self._default.append(vi)
-
-    def computedefault(self, keytype):
-        self.prepare_raw_defaults()
-        for k, vlist in self._rawdefaults.iteritems():
-            key = ValueInfo(k, vlist[0].position).convert(keytype)
-            for vi in vlist:
-                self.add_valueinfo(vi, key)
-
-    def getdefault(self):
-        return copy.copy(self._default)
-
-
-class SectionInfo(BaseInfo):
-    def __init__(self, name, sectiontype, minOccurs, maxOccurs, handler,
-                 attribute):
-        # name        - name of the section; one of '*', '+', or name1
-        # sectiontype - SectionType instance
-        # minOccurs   - minimum number of occurances of the section
-        # maxOccurs   - maximum number of occurances; if > 1, name
-        #               must be '*' or '+'
-        # handler     - handler name called when value(s) must take effect,
-        #               or None
-        # attribute   - name of the attribute on the SectionValue object
-        if maxOccurs > 1:
-            if name not in ('*', '+'):
-                raise ZConfig.SchemaError(
-                    "sections which can occur more than once must"
-                    " use a name of '*' or '+'")
-            if not attribute:
-                raise ZConfig.SchemaError(
-                    "sections which can occur more than once must"
-                    " specify a target attribute name")
-        if sectiontype.isabstract():
-            datatype = None
-        else:
-            datatype = sectiontype.datatype
-        BaseInfo.__init__(self, name, datatype,
-                          minOccurs, maxOccurs, handler, attribute)
-        self.sectiontype = sectiontype
-
-    def __repr__(self):
-        clsname = self.__class__.__name__
-        return "<%s for %s (%s)>" % (
-            clsname, self.sectiontype.name, `self.name`)
-
-    def issection(self):
-        return True
-
-    def allowUnnamed(self):
-        return self.name == "*"
-
-    def isAllowedName(self, name):
-        if name == "*" or name == "+":
-            return False
-        elif self.name == "+":
-            return name and True or False
-        elif self.name == "*":
-            return True
-        else:
-            return name == self.name
-
-    def getdefault(self):
-        # sections cannot have defaults
-        if self.maxOccurs > 1:
-            return []
-        else:
-            return None
-
-
-class AbstractType:
-    __metaclass__ = type
-    __slots__ = '_subtypes', 'name', 'description'
-
-    def __init__(self, name):
-        self._subtypes = {}
-        self.name = name
-        self.description = None
-
-    def addsubtype(self, type):
-        self._subtypes[type.name] = type
-
-    def getsubtype(self, name):
-        try:
-            return self._subtypes[name]
-        except KeyError:
-            raise ZConfig.SchemaError("no sectiontype %s in abstracttype %s"
-                                      % (`name`, `self.name`))
-
-    def hassubtype(self, name):
-        """Return true iff this type has 'name' as a concrete manifestation."""
-        return name in self._subtypes.keys()
-
-    def getsubtypenames(self):
-        """Return the names of all concrete types as a sorted list."""
-        L = self._subtypes.keys()
-        L.sort()
-        return L
-
-    def isabstract(self):
-        return True
-
-
-class SectionType:
-    def __init__(self, name, keytype, valuetype, datatype, registry, types):
-        # name      - name of the section, or '*' or '+'
-        # datatype  - type for the section itself
-        # keytype   - type for the keys themselves
-        # valuetype - default type for key values
-        self.name = name
-        self.datatype = datatype
-        self.keytype = keytype
-        self.valuetype = valuetype
-        self.handler = None
-        self.description = None
-        self.registry = registry
-        self._children = []    # [(key, info), ...]
-        self._attrmap = {}     # {attribute: info, ...}
-        self._keymap = {}      # {key: info, ...}
-        self._types = types
-
-    def gettype(self, name):
-        n = name.lower()
-        try:
-            return self._types[n]
-        except KeyError:
-            raise ZConfig.SchemaError("unknown type name: " + `name`)
-
-    def gettypenames(self):
-        return self._types.keys()
-
-    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 ZConfig.SchemaError(
-                "child name %s already used" % key)
-        if info.attribute and self._attrmap.has_key(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] = info
-        if key:
-            self._keymap[key] = info
-        self._children.append((key, info))
-
-    def addkey(self, keyinfo):
-        self._add_child(keyinfo.name, keyinfo)
-
-    def addsection(self, name, sectinfo):
-        assert name not in ("*", "+")
-        self._add_child(name, sectinfo)
-
-    def getinfo(self, key):
-        if not key:
-            raise ZConfig.ConfigurationError(
-                "cannot match a key without a name")
-        try:
-            return self._keymap[key]
-        except KeyError:
-            raise ZConfig.ConfigurationError("no key matching " + `key`)
-
-    def getrequiredtypes(self):
-        d = {}
-        if self.name:
-            d[self.name] = 1
-        stack = [self]
-        while stack:
-            info = stack.pop()
-            for key, ci in info._children:
-                if ci.issection():
-                    t = ci.sectiontype
-                    if not d.has_key(t.name):
-                        d[t.name] = 1
-                        stack.append(t)
-        return d.keys()
-
-    def getsectioninfo(self, type, name):
-        for key, info in self._children:
-            if key:
-                if key == name:
-                    if not info.issection():
-                        raise ZConfig.ConfigurationError(
-                            "section name %s already in use for key" % key)
-                    st = info.sectiontype
-                    if st.isabstract():
-                        try:
-                            st = st.getsubtype(type)
-                        except ZConfig.ConfigurationError:
-                            raise ZConfig.ConfigurationError(
-                                "section type %s not allowed for name %s"
-                                % (`type`, `key`))
-                    if not st.name == type:
-                        raise ZConfig.ConfigurationError(
-                            "name %s must be used for a %s section"
-                            % (`name`, `st.name`))
-                    return info
-            # else must be a sectiontype or an abstracttype:
-            elif info.sectiontype.name == type:
-                if not (name or info.allowUnnamed()):
-                    raise ZConfig.ConfigurationError(
-                        `type` + " sections must be named")
-                return info
-            elif info.sectiontype.isabstract():
-                st = info.sectiontype
-                if st.name == type:
-                    raise ZConfig.ConfigurationError(
-                        "cannot define section with an abstract type")
-                try:
-                    st = st.getsubtype(type)
-                except ZConfig.ConfigurationError:
-                    # not this one; maybe a different one
-                    pass
-                else:
-                    return info
-        raise ZConfig.ConfigurationError(
-            "no matching section defined for type='%s', name='%s'" % (
-            type, name))
-
-    def isabstract(self):
-        return False
-
-
-class SchemaType(SectionType):
-    def __init__(self, keytype, valuetype, datatype, handler, url,
-                 registry):
-        SectionType.__init__(self, None, keytype, valuetype, datatype,
-                             registry, {})
-        self._components = {}
-        self.handler = handler
-        self.url = url
-
-    def addtype(self, typeinfo):
-        n = typeinfo.name
-        if self._types.has_key(n):
-            raise ZConfig.SchemaError("type name cannot be redefined: "
-                                      + `typeinfo.name`)
-        self._types[n] = typeinfo
-
-    def allowUnnamed(self):
-        return True
-
-    def isAllowedName(self, name):
-        return False
-
-    def issection(self):
-        return True
-
-    def getunusedtypes(self):
-        alltypes = self.gettypenames()
-        reqtypes = self.getrequiredtypes()
-        for n in reqtypes:
-            alltypes.remove(n)
-        if self.name and self.name in alltypes:
-            alltypes.remove(self.name)
-        return alltypes
-
-    def createSectionType(self, name, keytype, valuetype, datatype):
-        t = SectionType(name, keytype, valuetype, datatype,
-                        self.registry, self._types)
-        self.addtype(t)
-        return t
-
-    def deriveSectionType(self, base, name, keytype, valuetype, datatype):
-        if isinstance(base, SchemaType):
-            raise ZConfig.SchemaError(
-                "cannot derive sectiontype from top-level schema")
-        t = self.createSectionType(name, keytype, valuetype, datatype)
-        t._attrmap.update(base._attrmap)
-        t._keymap.update(base._keymap)
-        t._children.extend(base._children)
-        for i in range(len(t._children)):
-            key, info = t._children[i]
-            if isinstance(info, BaseKeyInfo) and info.name == "+":
-                # need to create a new info object and recompute the
-                # default mapping based on the new keytype
-                info = copy.copy(info)
-                info.computedefault(t.keytype)
-                t._children[i] = (key, info)
-        return t
-
-    def addComponent(self, name):
-        if self._components.has_key(name):
-            raise ZConfig.SchemaError("already have component %s" % name)
-        self._components[name] = name
-
-    def hasComponent(self, name):
-        return self._components.has_key(name)
-
-
-def createDerivedSchema(base):
-    new = SchemaType(base.keytype, base.valuetype, base.datatype,
-                     base.handler, base.url, base.registry)
-    new._components.update(base._components)
-    new.description = base.description
-    new._children[:] = base._children
-    new._attrmap.update(base._attrmap)
-    new._keymap.update(base._keymap)
-    new._types.update(base._types)
-    return new

Deleted: ZConfig/trunk/loader.py
===================================================================
--- ZConfig/trunk/loader.py	2005-09-19 19:53:54 UTC (rev 38532)
+++ ZConfig/trunk/loader.py	2005-09-19 20:22:48 UTC (rev 38533)
@@ -1,307 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2002, 2003 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-"""Schema loader utility."""
-
-import os.path
-import sys
-import urllib
-import urllib2
-
-import ZConfig
-import ZConfig.cfgparser
-import ZConfig.datatypes
-import ZConfig.info
-import ZConfig.matcher
-import ZConfig.schema
-import ZConfig.url
-
-
-def loadSchema(url):
-    return SchemaLoader().loadURL(url)
-
-def loadSchemaFile(file, url=None):
-    return SchemaLoader().loadFile(file, url)
-
-def loadConfig(schema, url, overrides=()):
-    return _get_config_loader(schema, overrides).loadURL(url)
-
-def loadConfigFile(schema, file, url=None, overrides=()):
-    return _get_config_loader(schema, overrides).loadFile(file, url)
-
-
-def _get_config_loader(schema, overrides):
-    if overrides:
-        from ZConfig import cmdline
-        loader = cmdline.ExtendedConfigLoader(schema)
-        for opt in overrides:
-            loader.addOption(opt)
-    else:
-        loader = ConfigLoader(schema)
-    return loader
-
-
-class BaseLoader:
-    def __init__(self):
-        pass
-
-    def createResource(self, file, url):
-        return Resource(file, url)
-
-    def loadURL(self, url):
-        url = self.normalizeURL(url)
-        r = self.openResource(url)
-        try:
-            return self.loadResource(r)
-        finally:
-            r.close()
-
-    def loadFile(self, file, url=None):
-        if not url:
-            url = _url_from_file(file)
-        r = self.createResource(file, url)
-        try:
-            return self.loadResource(r)
-        finally:
-            r.close()
-
-    # utilities
-
-    def loadResource(self, resource):
-        raise NotImplementedError(
-            "BaseLoader.loadResource() must be overridden by a subclass")
-
-    def openResource(self, url):
-        # ConfigurationError exceptions raised here should be
-        # str()able to generate a message for an end user.
-        #
-        # XXX This should be replaced to use a local cache for remote
-        # resources.  The policy needs to support both re-retrieve on
-        # change and provide the cached resource when the remote
-        # resource is not accessible.
-        url = str(url)
-        try:
-            file = urllib2.urlopen(url)
-        except urllib2.URLError, e:
-            # urllib2.URLError has a particularly hostile str(), so we
-            # generally don't want to pass it along to the user.
-            self._raise_open_error(url, e.reason)
-        except (IOError, OSError), e:
-            # Python 2.1 raises a different error from Python 2.2+,
-            # so we catch both to make sure we detect the situation.
-            self._raise_open_error(url, str(e))
-        return self.createResource(file, url)
-
-    def _raise_open_error(self, url, message):
-        if url[:7].lower() == "file://":
-            what = "file"
-            ident = urllib.url2pathname(url[7:])
-        else:
-            what = "URL"
-            ident = url
-        raise ZConfig.ConfigurationError(
-            "error opening %s %s: %s" % (what, ident, message),
-            url)
-
-    def normalizeURL(self, url):
-        if self.isPath(url):
-            url = "file://" + urllib.pathname2url(os.path.abspath(url))
-        newurl, fragment = ZConfig.url.urldefrag(url)
-        if fragment:
-            raise ZConfig.ConfigurationError(
-                "fragment identifiers are not supported",
-                url)
-        return newurl
-
-    def isPath(self, s):
-        """Return True iff 's' should be handled as a filesystem path."""
-        if ":" in s:
-            # XXX This assumes that one-character scheme identifiers
-            # are always Windows drive letters; I don't know of any
-            # one-character scheme identifiers.
-            scheme, rest = urllib.splittype(s)
-            return len(scheme) == 1
-        else:
-            return True
-
-
-
-def _url_from_file(file):
-    name = getattr(file, "name", None)
-    if name and name[0] != "<" and name[-1] != ">":
-        return "file://" + urllib.pathname2url(os.path.abspath(name))
-    else:
-        return None
-
-
-class SchemaLoader(BaseLoader):
-    def __init__(self, registry=None):
-        if registry is None:
-            registry = ZConfig.datatypes.Registry()
-        BaseLoader.__init__(self)
-        self.registry = registry
-        self._cache = {}
-
-    def loadResource(self, resource):
-        if resource.url and self._cache.has_key(resource.url):
-            schema = self._cache[resource.url]
-        else:
-            schema = ZConfig.schema.parseResource(resource, self)
-            self._cache[resource.url] = schema
-        return schema
-
-    # schema parser support API
-
-    def schemaComponentSource(self, package, file):
-        parts = package.split(".")
-        if not parts:
-            raise ZConfig.SchemaError(
-                "illegal schema component name: " + `package`)
-        if "" in parts:
-            # '' somewhere in the package spec; still illegal
-            raise ZConfig.SchemaError(
-                "illegal schema component name: " + `package`)
-        file = file or "component.xml"
-        try:
-            __import__(package)
-        except ImportError, e:
-            raise ZConfig.SchemaResourceError(
-                "could not load package %s: %s" % (package, str(e)),
-                filename=file,
-                package=package)
-        pkg = sys.modules[package]
-        if not hasattr(pkg, "__path__"):
-            raise ZConfig.SchemaResourceError(
-                "import name does not refer to a package",
-                filename=file, package=package)
-        for dir in pkg.__path__:
-            dirname = os.path.abspath(dir)
-            fn = os.path.join(dirname, file)
-            if os.path.exists(fn):
-                return "file://" + urllib.pathname2url(fn)
-        else:
-            raise ZConfig.SchemaResourceError("schema component not found",
-                                              filename=file,
-                                              package=package,
-                                              path=pkg.__path__)
-
-
-class ConfigLoader(BaseLoader):
-    def __init__(self, schema):
-        if schema.isabstract():
-            raise ZConfig.SchemaError(
-                "cannot check a configuration an abstract type")
-        BaseLoader.__init__(self)
-        self.schema = schema
-        self._private_schema = False
-
-    def loadResource(self, resource):
-        sm = self.createSchemaMatcher()
-        self._parse_resource(sm, resource)
-        result = sm.finish(), CompositeHandler(sm.handlers, self.schema)
-        return result
-
-    def createSchemaMatcher(self):
-        return ZConfig.matcher.SchemaMatcher(self.schema)
-
-    # config parser support API
-
-    def startSection(self, parent, type, name):
-        t = self.schema.gettype(type)
-        if t.isabstract():
-            raise ZConfig.ConfigurationError(
-                "concrete sections cannot match abstract section types;"
-                " found abstract type " + `type`)
-        return parent.createChildMatcher(t, name)
-
-    def endSection(self, parent, type, name, matcher):
-        sectvalue = matcher.finish()
-        parent.addSection(type, name, sectvalue)
-
-    def importSchemaComponent(self, pkgname):
-        schema = self.schema
-        if not self._private_schema:
-            # replace the schema with an extended schema on the first %import
-            self._loader = SchemaLoader(self.schema.registry)
-            schema = ZConfig.info.createDerivedSchema(self.schema)
-            self._private_schema = True
-            self.schema = schema
-        url = self._loader.schemaComponentSource(pkgname, '')
-        if schema.hasComponent(url):
-            return
-        resource = self.openResource(url)
-        schema.addComponent(url)
-        try:
-            ZConfig.schema.parseComponent(resource, self._loader, schema)
-        finally:
-            resource.close()
-
-    def includeConfiguration(self, section, url, defines):
-        url = self.normalizeURL(url)
-        r = self.openResource(url)
-        try:
-            self._parse_resource(section, r, defines)
-        finally:
-            r.close()
-
-    # internal helper
-
-    def _parse_resource(self, matcher, resource, defines=None):
-        parser = ZConfig.cfgparser.ZConfigParser(resource, self, defines)
-        parser.parse(matcher)
-
-
-class CompositeHandler:
-
-    def __init__(self, handlers, schema):
-        self._handlers = handlers
-        self._convert = schema.registry.get("basic-key")
-
-    def __call__(self, handlermap):
-        d = {}
-        for name, callback in handlermap.items():
-            n = self._convert(name)
-            if d.has_key(n):
-                raise ZConfig.ConfigurationError(
-                    "handler name not unique when converted to a basic-key: "
-                    + `name`)
-            d[n] = callback
-        L = []
-        for handler, value in self._handlers:
-            if not d.has_key(handler):
-                L.append(handler)
-        if L:
-            raise ZConfig.ConfigurationError(
-                "undefined handlers: " + ", ".join(L))
-        for handler, value in self._handlers:
-            f = d[handler]
-            if f is not None:
-                f(value)
-
-    def __len__(self):
-        return len(self._handlers)
-
-
-class Resource:
-    def __init__(self, file, url):
-        self.file = file
-        self.url = url
-
-    def close(self):
-        if self.file is not None:
-            self.file.close()
-            self.file = None
-            self.closed = True
-
-    def __getattr__(self, name):
-        return getattr(self.file, name)

Deleted: ZConfig/trunk/matcher.py
===================================================================
--- ZConfig/trunk/matcher.py	2005-09-19 19:53:54 UTC (rev 38532)
+++ ZConfig/trunk/matcher.py	2005-09-19 20:22:48 UTC (rev 38533)
@@ -1,302 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2002, 2003 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-"""Utility that manages the binding of configuration data to a section."""
-
-import ZConfig
-
-from ZConfig.info import ValueInfo
-
-
-class BaseMatcher:
-    def __init__(self, info, type, handlers):
-        self.info = info
-        self.type = type
-        self._values = {}
-        for key, info in type:
-            if info.name == "+" and not info.issection():
-                v = {}
-            elif info.ismulti():
-                v = []
-            else:
-                v = None
-            assert info.attribute is not None
-            self._values[info.attribute] = v
-        self._sectionnames = {}
-        if handlers is None:
-            handlers = []
-        self.handlers = handlers
-
-    def __repr__(self):
-        clsname = self.__class__.__name__
-        extra = "type " + `self.type.name`
-        return "<%s for %s>" % (clsname, extra)
-
-    def addSection(self, type, name, sectvalue):
-        if name:
-            if self._sectionnames.has_key(name):
-                raise ZConfig.ConfigurationError(
-                    "section names must not be re-used within the"
-                    " same container:" + `name`)
-            self._sectionnames[name] = name
-        ci = self.type.getsectioninfo(type, name)
-        attr = ci.attribute
-        v = self._values[attr]
-        if ci.ismulti():
-            v.append(sectvalue)
-        elif v is None:
-            self._values[attr] = sectvalue
-        else:
-            raise ZConfig.ConfigurationError(
-                "too many instances of %s section" % `ci.sectiontype.name`)
-
-    def addValue(self, key, value, position):
-        try:
-            realkey = self.type.keytype(key)
-        except ValueError, e:
-            raise ZConfig.DataConversionError(e, key, position)
-        arbkey_info = None
-        for i in range(len(self.type)):
-            k, ci = self.type[i]
-            if k == realkey:
-                break
-            if ci.name == "+" and not ci.issection():
-                arbkey_info = k, ci
-        else:
-            if arbkey_info is None:
-                raise ZConfig.ConfigurationError(
-                    `key` + " is not a known key name")
-            k, ci = arbkey_info
-        if ci.issection():
-            if ci.name:
-                extra = " in %s sections" % `self.type.name`
-            else:
-                extra = ""
-            raise ZConfig.ConfigurationError(
-                "%s is not a valid key name%s" % (`key`, extra))
-
-        ismulti = ci.ismulti()
-        attr = ci.attribute
-        assert attr is not None
-        v = self._values[attr]
-        if v is None:
-            if k == '+':
-                v = {}
-            elif ismulti:
-                v = []
-            self._values[attr] = v
-        elif not ismulti:
-            if k != '+':
-                raise ZConfig.ConfigurationError(
-                    `key` + " does not support multiple values")
-        elif len(v) == ci.maxOccurs:
-            raise ZConfig.ConfigurationError(
-                "too many values for " + `name`)
-
-        value = ValueInfo(value, position)
-        if k == '+':
-            if ismulti:
-                if v.has_key(realkey):
-                    v[realkey].append(value)
-                else:
-                    v[realkey] = [value]
-            else:
-                if v.has_key(realkey):
-                    raise ZConfig.ConfigurationError(
-                        "too many values for " + `key`)
-                v[realkey] = value
-        elif ismulti:
-            v.append(value)
-        else:
-            self._values[attr] = value
-
-    def createChildMatcher(self, type, name):
-        ci = self.type.getsectioninfo(type.name, name)
-        assert not ci.isabstract()
-        if not ci.isAllowedName(name):
-            raise ZConfig.ConfigurationError(
-                "%s is not an allowed name for %s sections"
-                % (`name`, `ci.sectiontype.name`))
-        return SectionMatcher(ci, type, name, self.handlers)
-
-    def finish(self):
-        """Check the constraints of the section and convert to an application
-        object."""
-        values = self._values
-        for key, ci in self.type:
-            if key:
-                key = repr(key)
-            else:
-                key = "section type " + `ci.sectiontype.name`
-            assert ci.attribute is not None
-            attr = ci.attribute
-            v = values[attr]
-            if ci.name == '+' and not ci.issection():
-                # v is a dict
-                if ci.minOccurs > len(v):
-                    raise ZConfig.ConfigurationError(
-                        "no keys defined for the %s key/value map; at least %d"
-                        " must be specified" % (attr, ci.minOccurs))
-            if v is None and ci.minOccurs:
-                default = ci.getdefault()
-                if default is None:
-                    raise ZConfig.ConfigurationError(
-                        "no values for %s; %s required" % (key, ci.minOccurs))
-                else:
-                    v = values[attr] = default[:]
-            if ci.ismulti():
-                if not v:
-                    default = ci.getdefault()
-                    if isinstance(default, dict):
-                        v.update(default)
-                    else:
-                        v[:] = default
-                if len(v) < ci.minOccurs:
-                    raise ZConfig.ConfigurationError(
-                        "not enough values for %s; %d found, %d required"
-                        % (key, len(v), ci.minOccurs))
-            if v is None and not ci.issection():
-                if ci.ismulti():
-                    v = ci.getdefault()[:]
-                else:
-                    v = ci.getdefault()
-                values[attr] = v
-        return self.constuct()
-
-    def constuct(self):
-        values = self._values
-        for name, ci in self.type:
-            assert ci.attribute is not None
-            attr = ci.attribute
-            if ci.ismulti():
-                if ci.issection():
-                    v = []
-                    for s in values[attr]:
-                        if s is not None:
-                            st = s.getSectionDefinition()
-                            try:
-                                s = st.datatype(s)
-                            except ValueError, e:
-                                raise ZConfig.DataConversionError(
-                                    e, s, (-1, -1, None))
-                        v.append(s)
-                elif ci.name == '+':
-                    v = values[attr]
-                    for key, val in v.items():
-                        v[key] = [vi.convert(ci.datatype) for vi in val]
-                else:
-                    v = [vi.convert(ci.datatype) for vi in values[attr]]
-            elif ci.issection():
-                if values[attr] is not None:
-                    st = values[attr].getSectionDefinition()
-                    try:
-                        v = st.datatype(values[attr])
-                    except ValueError, e:
-                        raise ZConfig.DataConversionError(
-                            e, values[attr], (-1, -1, None))
-                else:
-                    v = None
-            elif name == '+':
-                v = values[attr]
-                if not v:
-                    for key, val in ci.getdefault().items():
-                        v[key] = val.convert(ci.datatype)
-                else:
-                    for key, val in v.items():
-                        v[key] = val.convert(ci.datatype)
-            else:
-                v = values[attr]
-                if v is not None:
-                    v = v.convert(ci.datatype)
-            values[attr] = v
-            if ci.handler is not None:
-                self.handlers.append((ci.handler, v))
-        return self.createValue()
-
-    def createValue(self):
-        return SectionValue(self._values, None, self)
-
-
-class SectionMatcher(BaseMatcher):
-    def __init__(self, info, type, name, handlers):
-        if name or info.allowUnnamed():
-            self.name = name
-        else:
-            raise ZConfig.ConfigurationError(
-                `type.name` + " sections may not be unnamed")
-        BaseMatcher.__init__(self, info, type, handlers)
-
-    def createValue(self):
-        return SectionValue(self._values, self.name, self)
-
-
-class SchemaMatcher(BaseMatcher):
-    def __init__(self, schema):
-        BaseMatcher.__init__(self, schema, schema, [])
-
-    def finish(self):
-        # Since there's no outer container to call datatype()
-        # for the schema, we convert on the way out.
-        v = BaseMatcher.finish(self)
-        v = self.type.datatype(v)
-        if self.type.handler is not None:
-            self.handlers.append((self.type.handler, v))
-        return v
-
-
-class SectionValue:
-    """Generic 'bag-of-values' object for a section.
-
-    Derived classes should always call the SectionValue constructor
-    before attempting to modify self.
-    """
-
-    def __init__(self, values, name, matcher):
-        self.__dict__.update(values)
-        self._name = name
-        self._matcher = matcher
-        self._attributes = tuple(values.keys())
-
-    def __repr__(self):
-        if self._name:
-            # probably unique for a given config file; more readable than id()
-            name = `self._name`
-        else:
-            # identify uniquely
-            name = "at %#x" % id(self)
-        clsname = self.__class__.__name__
-        return "<%s for %s %s>" % (clsname, self._matcher.type.name, name)
-
-    def __str__(self):
-        l = []
-        attrnames = [s for s in self.__dict__.keys() if s[0] != "_"]
-        attrnames.sort()
-        for k in attrnames:
-            v = getattr(self, k)
-            l.append('%-40s: %s' % (k, v))
-        return '\n'.join(l)
-
-    def getSectionName(self):
-        return self._name
-
-    def getSectionType(self):
-        return self._matcher.type.name
-
-    def getSectionDefinition(self):
-        return self._matcher.type
-
-    def getSectionMatcher(self):
-        return self._matcher
-
-    def getSectionAttributes(self):
-        return self._attributes

Deleted: ZConfig/trunk/schema.py
===================================================================
--- ZConfig/trunk/schema.py	2005-09-19 19:53:54 UTC (rev 38532)
+++ ZConfig/trunk/schema.py	2005-09-19 20:22:48 UTC (rev 38533)
@@ -1,582 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2002, 2003 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-"""Parser for ZConfig schemas."""
-
-import os
-import xml.sax
-
-import ZConfig
-
-from ZConfig import info
-from ZConfig import url
-
-
-def parseResource(resource, loader):
-    parser = SchemaParser(loader, resource.url)
-    xml.sax.parse(resource.file, parser)
-    return parser._schema
-
-
-def parseComponent(resource, loader, schema):
-    parser = ComponentParser(loader, resource.url, schema)
-    xml.sax.parse(resource.file, parser)
-
-
-def _srepr(ob):
-    if isinstance(ob, type(u'')):
-        # drop the leading "u" from a unicode repr
-        return `ob`[1:]
-    else:
-        return `ob`
-
-
-class BaseParser(xml.sax.ContentHandler):
-
-    _cdata_tags = "description", "metadefault", "example", "default"
-    _handled_tags = ("import", "abstracttype", "sectiontype",
-                     "key", "multikey", "section", "multisection")
-
-    _allowed_parents = {
-        "description": ["key", "section", "multikey", "multisection",
-                        "sectiontype", "abstracttype",
-                        "schema", "component"],
-        "example": ["key", "section", "multikey", "multisection"],
-        "metadefault": ["key", "section", "multikey", "multisection"],
-        "default": ["key", "multikey"],
-        "import": ["schema", "component"],
-        "abstracttype": ["schema", "component"],
-        "sectiontype": ["schema", "component"],
-        "key": ["schema", "sectiontype"],
-        "multikey": ["schema", "sectiontype"],
-        "section": ["schema", "sectiontype"],
-        "multisection": ["schema", "sectiontype"],
-        }
-
-    def __init__(self, loader, url):
-        self._registry = loader.registry
-        self._loader = loader
-        self._basic_key = self._registry.get("basic-key")
-        self._identifier = self._registry.get("identifier")
-        self._cdata = None
-        self._locator = None
-        self._prefixes = []
-        self._schema = None
-        self._stack = []
-        self._url = url
-        self._elem_stack = []
-
-    # SAX 2 ContentHandler methods
-
-    def setDocumentLocator(self, locator):
-        self._locator = locator
-
-    def startElement(self, name, attrs):
-        attrs = dict(attrs)
-        if self._elem_stack:
-            parent = self._elem_stack[-1]
-            if not self._allowed_parents.has_key(name):
-                self.error("Unknown tag " + name)
-            if parent not in self._allowed_parents[name]:
-                self.error("%s elements may not be nested in %s elements"
-                           % (_srepr(name), _srepr(parent)))
-        elif name != self._top_level:
-            self.error("Unknown document type " + name)
-        self._elem_stack.append(name)
-        if name == self._top_level:
-            if self._schema is not None:
-                self.error("schema element improperly nested")
-            getattr(self, "start_" + name)(attrs)
-        elif name in self._handled_tags:
-            if self._schema is None:
-                self.error(name + " element outside of schema")
-            getattr(self, "start_" + name)(attrs)
-        elif name in self._cdata_tags:
-            if self._schema is None:
-                self.error(name + " element outside of schema")
-            if self._cdata is not None:
-                self.error(name + " element improperly nested")
-            self._cdata = []
-            self._position = None
-            self._attrs = attrs
-
-    def characters(self, data):
-        if self._cdata is not None:
-            if self._position is None:
-                self._position = self.get_position()
-            self._cdata.append(data)
-        elif data.strip():
-            self.error("unexpected non-blank character data: "
-                       + `data.strip()`)
-
-    def endElement(self, name):
-        del self._elem_stack[-1]
-        if name in self._handled_tags:
-            getattr(self, "end_" + name)()
-        else:
-            data = ''.join(self._cdata).strip()
-            self._cdata = None
-            getattr(self, "characters_" + name)(data)
-
-    def endDocument(self):
-        if self._schema is None:
-            self.error("no %s found" % self._top_level)
-
-    # helper methods
-
-    def get_position(self):
-        if self._locator:
-            return (self._locator.getLineNumber(),
-                    self._locator.getColumnNumber(),
-                    (self._locator.getSystemId() or self._url))
-        else:
-            return None, None, self._url
-
-    def get_handler(self, attrs):
-        v = attrs.get("handler")
-        if v is None:
-            return v
-        else:
-            return self.basic_key(v)
-
-    def push_prefix(self, attrs):
-        name = attrs.get("prefix")
-        if name:
-            if self._prefixes:
-                convert = self._registry.get("dotted-suffix")
-            else:
-                convert = self._registry.get("dotted-name")
-            try:
-                name = convert(name)
-            except ValueError, err:
-                self.error("not a valid prefix: %s (%s)"
-                           % (_srepr(name), str(err)))
-            if name[0] == ".":
-                prefix = self._prefixes[-1] + name
-            else:
-                prefix = name
-        elif self._prefixes:
-            prefix = self._prefixes[-1]
-        else:
-            prefix = ''
-        self._prefixes.append(prefix)
-
-    def pop_prefix(self):
-        del self._prefixes[-1]
-
-    def get_classname(self, name):
-        name = str(name)
-        if name.startswith("."):
-            return self._prefixes[-1] + name
-        else:
-            return name
-
-    def get_datatype(self, attrs, attrkey, default, base=None):
-        if attrs.has_key(attrkey):
-            dtname = self.get_classname(attrs[attrkey])
-        else:
-            convert = getattr(base, attrkey, None)
-            if convert is not None:
-                return convert
-            dtname = default
-
-        try:
-            return self._registry.get(dtname)
-        except ValueError, e:
-            self.error(e[0])
-
-    def get_sect_typeinfo(self, attrs, base=None):
-        keytype = self.get_datatype(attrs, "keytype", "basic-key", base)
-        valuetype = self.get_datatype(attrs, "valuetype", "string")
-        datatype = self.get_datatype(attrs, "datatype", "null", base)
-        return keytype, valuetype, datatype
-
-    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):
-        # used by start_multi*()
-        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")
-        return self._schema.gettype(type)
-
-    def get_key_info(self, attrs, element):
-        any, name, attribute = self.get_name_info(attrs, element)
-        if any == '*':
-            self.error(element + " may not specify '*' for name")
-        if not name and any != '+':
-            self.error(element + " name may not be omitted or empty")
-        datatype = self.get_datatype(attrs, "datatype", "string")
-        handler = self.get_handler(attrs)
-        return name or any, datatype, handler, attribute
-
-    def get_name_info(self, attrs, element, default=None):
-        name = attrs.get("name", default)
-        if not name:
-            self.error(element + " name must be specified and non-empty")
-        aname = attrs.get("attribute")
-        if aname:
-            aname = self.identifier(aname)
-            if aname.startswith("getSection"):
-                # reserved; used for SectionValue methods to get meta-info
-                self.error("attribute names may not start with 'getSection'")
-        if name in ("*", "+"):
-            if not aname:
-                self.error(
-                    "container attribute must be specified and non-empty"
-                    " when using '*' or '+' for a section name")
-            return name, None, aname
-        else:
-            # run the keytype converter to make sure this is a valid key
-            try:
-                name = self._stack[-1].keytype(name)
-            except ValueError, e:
-                self.error("could not convert key name to keytype: " + str(e))
-            if not aname:
-                aname = self.basic_key(name)
-                aname = self.identifier(aname.replace('-', '_'))
-            return None, name, aname
-
-    # schema loading logic
-
-    def characters_default(self, data):
-        key = self._attrs.get("key")
-        self._stack[-1].adddefault(data, self._position, key)
-
-    def characters_description(self, data):
-        if self._stack[-1].description is not None:
-            self.error(
-                "at most one <description> may be used for each element")
-        self._stack[-1].description = data
-
-    def characters_example(self, data):
-        self._stack[-1].example = data
-
-    def characters_metadefault(self, data):
-        self._stack[-1].metadefault = data
-
-    def start_import(self, attrs):
-        src = attrs.get("src", "").strip()
-        pkg = attrs.get("package", "").strip()
-        file = attrs.get("file", "").strip()
-        if not (src or pkg):
-            self.error("import must specify either src or package")
-        if src and pkg:
-            self.error("import may only specify one of src or package")
-        if src:
-            if file:
-                self.error("import may not specify file and src")
-            src = url.urljoin(self._url, src)
-            src, fragment = url.urldefrag(src)
-            if fragment:
-                self.error("import src many not include"
-                           " a fragment identifier")
-            schema = self._loader.loadURL(src)
-            for n in schema.gettypenames():
-                self._schema.addtype(schema.gettype(n))
-        else:
-            if os.path.dirname(file):
-                self.error("file may not include a directory part")
-            pkg = self.get_classname(pkg)
-            src = self._loader.schemaComponentSource(pkg, file)
-            if not self._schema.hasComponent(src):
-                self._schema.addComponent(src)
-                self.loadComponent(src)
-
-    def loadComponent(self, src):
-        r = self._loader.openResource(src)
-        parser = ComponentParser(self._loader, src, self._schema)
-        try:
-            xml.sax.parse(r.file, parser)
-        finally:
-            r.close()
-
-    def end_import(self):
-        pass
-
-    def start_sectiontype(self, attrs):
-        name = attrs.get("name")
-        if not name:
-            self.error("sectiontype name must not be omitted or empty")
-        name = self.basic_key(name)
-        self.push_prefix(attrs)
-        if attrs.has_key("extends"):
-            basename = self.basic_key(attrs["extends"])
-            base = self._schema.gettype(basename)
-            if base.isabstract():
-                self.error("sectiontype cannot extend an abstract type")
-            keytype, valuetype, datatype = self.get_sect_typeinfo(attrs, base)
-            sectinfo = self._schema.deriveSectionType(
-                base, name, keytype, valuetype, datatype)
-        else:
-            keytype, valuetype, datatype = self.get_sect_typeinfo(attrs)
-            sectinfo = self._schema.createSectionType(
-                name, keytype, valuetype, datatype)
-        if attrs.has_key("implements"):
-            ifname = self.basic_key(attrs["implements"])
-            interface = self._schema.gettype(ifname)
-            if not interface.isabstract():
-                self.error(
-                    "type specified by implements is not an abstracttype")
-            interface.addsubtype(sectinfo)
-        self._stack.append(sectinfo)
-
-    def end_sectiontype(self):
-        self.pop_prefix()
-        self._stack.pop()
-
-    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", "*")
-        if any and not attribute:
-            self.error(
-                "attribute must be specified if section name is '*' or '+'")
-        section = info.SectionInfo(any or 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, "multisection", "*")
-        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_abstracttype(self, attrs):
-        name = attrs.get("name")
-        if not name:
-            self.error("abstracttype name must not be omitted or empty")
-        name = self.basic_key(name)
-        abstype = info.AbstractType(name)
-        self._schema.addtype(abstype)
-        self._stack.append(abstype)
-
-    def end_abstracttype(self):
-        self._stack.pop()
-
-    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, 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.get_position())
-        if name != "+":
-            key.finish()
-        self._stack[-1].addkey(key)
-        self._stack.append(key)
-
-    def end_key(self):
-        key = self._stack.pop()
-        if key.name == "+":
-            key.computedefault(self._stack[-1].keytype)
-            key.finish()
-
-    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.MultiKeyInfo(name, datatype, min, max, handler, attribute)
-        self._stack[-1].addkey(key)
-        self._stack.append(key)
-
-    def end_multikey(self):
-        multikey = self._stack.pop()
-        if multikey.name == "+":
-            multikey.computedefault(self._stack[-1].keytype)
-        multikey.finish()
-
-    # datatype conversion wrappers
-
-    def basic_key(self, s):
-        try:
-            return self._basic_key(s)
-        except ValueError, e:
-            self.error(e[0])
-
-    def identifier(self, s):
-        try:
-            return self._identifier(s)
-        except ValueError, e:
-            self.error(e[0])
-
-    # exception setup helpers
-
-    def initerror(self, e):
-        if self._locator is not None:
-            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))
-
-
-class SchemaParser(BaseParser):
-
-    # needed by startElement() and endElement()
-    _handled_tags = BaseParser._handled_tags + ("schema",)
-    _top_level = "schema"
-
-    def __init__(self, loader, url, extending_parser=None):
-        BaseParser.__init__(self, loader, url)
-        self._extending_parser = extending_parser
-        self._base_keytypes = []
-        self._base_datatypes = []
-
-    def start_schema(self, attrs):
-        self.push_prefix(attrs)
-        handler = self.get_handler(attrs)
-        keytype, valuetype, datatype = self.get_sect_typeinfo(attrs)
-
-        if self._extending_parser is None:
-            # We're not being inherited, so we need to create the schema
-            self._schema = info.SchemaType(keytype, valuetype, datatype,
-                                           handler, self._url, self._registry)
-        else:
-            # Parse into the extending ("subclass") parser's schema
-            self._schema = self._extending_parser._schema
-
-        self._stack = [self._schema]
-
-        if attrs.has_key("extends"):
-            sources = attrs["extends"].split()
-            sources.reverse()
-
-            for src in sources:
-                src = url.urljoin(self._url, src)
-                src, fragment = url.urldefrag(src)
-                if fragment:
-                    self.error("schema extends many not include"
-                               " a fragment identifier")
-                self.extendSchema(src)
-
-            # Inherit keytype from bases, if unspecified and not conflicting
-            if self._base_keytypes and not attrs.has_key("keytype"):
-                keytype = self._base_keytypes[0]
-                for kt in self._base_keytypes[1:]:
-                    if kt is not keytype:
-                        self.error("base schemas have conflicting keytypes,"
-                                   " but no keytype was specified in the"
-                                   " extending schema")
-
-            # Inherit datatype from bases, if unspecified and not conflicting
-            if self._base_datatypes and not attrs.has_key("datatype"):
-                datatype = self._base_datatypes[0]
-                for dt in self._base_datatypes[1:]:
-                    if dt is not datatype:
-                        self.error("base schemas have conflicting datatypes,"
-                                   " but no datatype was specified in the"
-                                   " extending schema")
-
-        # Reset the schema types to our own, while we parse the schema body
-        self._schema.keytype = keytype
-        self._schema.valuetype = valuetype
-        self._schema.datatype = datatype
-
-        # Update base key/datatypes for the "extending" parser
-        if self._extending_parser is not None:
-            self._extending_parser._base_keytypes.append(keytype)
-            self._extending_parser._base_datatypes.append(datatype)
-
-
-    def extendSchema(self,src):
-        parser = SchemaParser(self._loader, src, self)
-        r = self._loader.openResource(src)
-        try:
-            xml.sax.parse(r.file, parser)
-        finally:
-            r.close()
-
-    def end_schema(self):
-        del self._stack[-1]
-        assert not self._stack
-        self.pop_prefix()
-        assert not self._prefixes
-
-
-class ComponentParser(BaseParser):
-
-    _handled_tags = BaseParser._handled_tags + ("component",)
-    _top_level = "component"
-
-    def __init__(self, loader, url, schema):
-        BaseParser.__init__(self, loader, url)
-        self._parent = schema
-
-    def characters_description(self, data):
-        if self._stack:
-            self._stack[-1].description = data
-
-    def start_key(self, attrs):
-        self._check_not_toplevel("key")
-        BaseParser.start_key(self, attrs)
-
-    def start_multikey(self, attrs):
-        self._check_not_toplevel("multikey")
-        BaseParser.start_multikey(self, attrs)
-
-    def start_section(self, attrs):
-        self._check_not_toplevel("section")
-        BaseParser.start_section(self, attrs)
-
-    def start_multisection(self, attrs):
-        self._check_not_toplevel("multisection")
-        BaseParser.start_multisection(self, attrs)
-
-    def start_component(self, attrs):
-        self._schema = self._parent
-        self.push_prefix(attrs)
-
-    def end_component(self):
-        self.pop_prefix()
-
-    def _check_not_toplevel(self, what):
-        if not self._stack:
-            self.error("cannot define top-level %s in a schema %s"
-                       % (what, self._top_level))

Deleted: ZConfig/trunk/substitution.py
===================================================================
--- ZConfig/trunk/substitution.py	2005-09-19 19:53:54 UTC (rev 38532)
+++ ZConfig/trunk/substitution.py	2005-09-19 20:22:48 UTC (rev 38533)
@@ -1,86 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2002, 2003 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-"""Substitution support for ZConfig values."""
-
-import ZConfig
-
-
-def substitute(s, mapping):
-    """Interpolate variables from `mapping` into `s`."""
-    if "$" in s:
-        result = ''
-        rest = s
-        while rest:
-            p, name, namecase, rest = _split(rest)
-            result += p
-            if name:
-                v = mapping.get(name)
-                if v is None:
-                    raise ZConfig.SubstitutionReplacementError(s, namecase)
-                result += v
-        return result
-    else:
-        return s
-
-
-def isname(s):
-    """Return True iff s is a valid substitution name."""
-    m = _name_match(s)
-    if m:
-        return m.group() == s
-    else:
-        return False
-
-
-def _split(s):
-    # Return a four tuple:  prefix, name, namecase, suffix
-    # - prefix is text that can be used literally in the result (may be '')
-    # - name is a referenced name, or None
-    # - namecase is the name with case preserved
-    # - suffix is trailling text that may contain additional references
-    #   (may be '' or None)
-    if "$" in s:
-        i = s.find("$")
-        c = s[i+1:i+2]
-        if c == "":
-            raise ZConfig.SubstitutionSyntaxError(
-                "illegal lone '$' at end of source")
-        if c == "$":
-            return s[:i+1], None, None, s[i+2:]
-        prefix = s[:i]
-        if c == "{":
-            m = _name_match(s, i + 2)
-            if not m:
-                raise ZConfig.SubstitutionSyntaxError(
-                    "'${' not followed by name")
-            name = m.group(0)
-            i = m.end() + 1
-            if not s.startswith("}", i - 1):
-                raise ZConfig.SubstitutionSyntaxError(
-                    "'${%s' not followed by '}'" % name)
-        else:
-            m = _name_match(s, i+1)
-            if not m:
-                raise ZConfig.SubstitutionSyntaxError(
-                    "'$' not followed by '$' or name")
-            name = m.group(0)
-            i = m.end()
-        return prefix, name.lower(), name, s[i:]
-    else:
-        return s, None, None, None
-
-
-import re
-_name_match = re.compile(r"[a-zA-Z_][a-zA-Z0-9_]*").match
-del re

Deleted: ZConfig/trunk/url.py
===================================================================
--- ZConfig/trunk/url.py	2005-09-19 19:53:54 UTC (rev 38532)
+++ ZConfig/trunk/url.py	2005-09-19 20:22:48 UTC (rev 38533)
@@ -1,67 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2002, 2003 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-"""urlparse-like helpers that normalize file: URLs.
-
-ZConfig and urllib2 expect file: URLs to consistently use the '//'
-hostpart seperator; the functions here enforce this constraint.
-"""
-
-import urlparse as _urlparse
-
-try:
-    from urlparse import urlsplit
-except ImportError:
-    def urlsplit(url):
-        # Check for the fragment here, since Python 2.1.3 didn't get
-        # it right for things like "http://www.python.org#frag".
-        if '#' in url:
-            url, fragment = url.split('#', 1)
-        else:
-            fragment = ''
-        parts = list(_urlparse.urlparse(url))
-        parts[-1] = fragment
-        param = parts.pop(3)
-        if param:
-            parts[2] += ";" + param
-        return tuple(parts)
-
-
-def urlnormalize(url):
-    lc = url.lower()
-    if lc.startswith("file:/") and not lc.startswith("file:///"):
-        url = "file://" + url[5:]
-    return url
-
-
-def urlunsplit(parts):
-    parts = list(parts)
-    parts.insert(3, '')
-    url = _urlparse.urlunparse(tuple(parts))
-    if (parts[0] == "file"
-        and url.startswith("file:/")
-        and not url.startswith("file:///")):
-        url = "file://" + url[5:]
-    return url
-
-
-def urldefrag(url):
-    url, fragment = _urlparse.urldefrag(url)
-    return urlnormalize(url), fragment
-
-
-def urljoin(base, relurl):
-    url = _urlparse.urljoin(base, relurl)
-    if url.startswith("file:/") and not url.startswith("file:///"):
-        url = "file://" + url[5:]
-    return url

Added: ZConfig/trunk/zpkg.conf
===================================================================
--- ZConfig/trunk/zpkg.conf	2005-09-19 19:53:54 UTC (rev 38532)
+++ ZConfig/trunk/zpkg.conf	2005-09-19 20:22:48 UTC (rev 38533)
@@ -0,0 +1,8 @@
+collect-dependencies true
+default-collection   ZConfig-dist
+release-name         ZConfig
+
+<resources>
+  ZConfig      ZConfig
+  ZConfig-dist .
+</resources>


Property changes on: ZConfig/trunk/zpkg.conf
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:eol-style
   + native



More information about the ZConfig mailing list