[Zope-Checkins] CVS: Zope/lib/python/ZConfig/tests - __init__.py:1.1.40.1 runtests.py:1.1.40.2 test_config.py:1.1.2.3 test_datatypes.py:1.1.2.10 test_loader.py:1.1.2.7 test_schema.py:1.1.2.39 test_subst.py:1.1.2.4 test_zopeschema.py:1.1.2.8

Fred L. Drake, Jr. fred@zope.com
Thu, 9 Jan 2003 14:28:23 -0500


Update of /cvs-repository/Zope/lib/python/ZConfig/tests
In directory cvs.zope.org:/tmp/cvs-serv3113/tests

Modified Files:
      Tag: zconfig-schema-devel-branch
	__init__.py runtests.py test_config.py test_datatypes.py 
	test_loader.py test_schema.py test_subst.py test_zopeschema.py 
Log Message:
Merge from the ZConfig HEAD.

=== Zope/lib/python/ZConfig/tests/__init__.py 1.1 => 1.1.40.1 ===
--- Zope/lib/python/ZConfig/tests/__init__.py:1.1	Tue Oct  8 17:42:17 2002
+++ Zope/lib/python/ZConfig/tests/__init__.py	Thu Jan  9 14:27:49 2003
@@ -1,6 +1,6 @@
 ##############################################################################
 #
-# Copyright (c) 2002 Zope Corporation and Contributors.
+# Copyright (c) 2002, 2003 Zope Corporation and Contributors.
 # All Rights Reserved.
 #
 # This software is subject to the provisions of the Zope Public License,


=== Zope/lib/python/ZConfig/tests/runtests.py 1.1.40.1 => 1.1.40.2 ===
--- Zope/lib/python/ZConfig/tests/runtests.py:1.1.40.1	Wed Dec 11 15:20:37 2002
+++ Zope/lib/python/ZConfig/tests/runtests.py	Thu Jan  9 14:27:49 2003
@@ -1,7 +1,7 @@
 #! /usr/bin/env python
 ##############################################################################
 #
-# Copyright (c) 2002 Zope Corporation and Contributors.
+# Copyright (c) 2002, 2003 Zope Corporation and Contributors.
 # All Rights Reserved.
 #
 # This software is subject to the provisions of the Zope Public License,


=== Zope/lib/python/ZConfig/tests/test_config.py 1.1.2.2 => 1.1.2.3 ===
--- Zope/lib/python/ZConfig/tests/test_config.py:1.1.2.2	Thu Jan  2 12:26:30 2003
+++ Zope/lib/python/ZConfig/tests/test_config.py	Thu Jan  9 14:27:49 2003
@@ -1,6 +1,6 @@
 ##############################################################################
 #
-# Copyright (c) 2002 Zope Corporation and Contributors.
+# Copyright (c) 2002, 2003 Zope Corporation and Contributors.
 # All Rights Reserved.
 #
 # This software is subject to the provisions of the Zope Public License,
@@ -204,6 +204,12 @@
         self.assertEqual(conf.get("VAR2"), "value2")
         self.assertEqual(conf.get("var3"), "value3")
         self.assertEqual(conf.get("VAR3"), "value3")
+        self.assertEqual(conf.get("var4"), "value")
+
+    def test_includes_with_defines(self):
+        conf = self.load("outer.conf")
+        self.assertEqual(conf.get("refinner"), "inner")
+        self.assertEqual(conf.get("refouter"), "outer")
 
     def test_define(self):
         conf = self.load("simple.conf")


=== Zope/lib/python/ZConfig/tests/test_datatypes.py 1.1.2.9 => 1.1.2.10 ===
--- Zope/lib/python/ZConfig/tests/test_datatypes.py:1.1.2.9	Fri Jan  3 14:01:28 2003
+++ Zope/lib/python/ZConfig/tests/test_datatypes.py	Thu Jan  9 14:27:49 2003
@@ -26,6 +26,8 @@
 except NameError:
     here = sys.argv[0]
 
+here = os.path.abspath(here)
+
 class DatatypeTestCase(unittest.TestCase):
     types = ZConfig.datatypes.Registry()
 
@@ -159,20 +161,27 @@
     def test_datatype_socket_address(self):
         convert = self.types.get("socket-address")
         eq = self.assertEqual
-        raises = self.assertRaises
         AF_INET = socket.AF_INET
-        eq(convert("Host.Example.Com:80"),(AF_INET, ("host.example.com", 80)))
-        eq(convert(":80"),                (AF_INET, ("", 80)))
-        eq(convert("80"),                 (AF_INET, ("", 80)))
-        eq(convert("host.EXAMPLE.com"),   (AF_INET, ("host.example.com",None)))
+
+        def check(value, family, address, self=self, convert=convert):
+            a = convert(value)
+            self.assertEqual(a.family, family)
+            self.assertEqual(a.address, address)
+
+        check("Host.Example.Com:80", AF_INET, ("host.example.com", 80))
+        check(":80",                 AF_INET, ("", 80))
+        check("80",                  AF_INET, ("", 80))
+        check("host.EXAMPLE.com",    AF_INET, ("host.example.com",None))
+        a1 = convert("/tmp/var/@345.4")
+        a2 = convert("/tmp/var/@345.4:80")
+        self.assertEqual(a1.address, "/tmp/var/@345.4")
+        self.assertEqual(a2.address, "/tmp/var/@345.4:80")
         if hasattr(socket, "AF_UNIX"):
-            eq(convert("/tmp/var/@345.4"),
-               (socket.AF_UNIX, "/tmp/var/@345.4"))
-            eq(convert("/tmp/var/@345.4:80"),
-               (socket.AF_UNIX, "/tmp/var/@345.4:80"))
+            self.assertEqual(a1.family, socket.AF_UNIX)
+            self.assertEqual(a2.family, socket.AF_UNIX)
         else:
-            raises(ValueError, convert, "/tmp/var/@345.4")
-            raises(ValueError, convert, "/tmp/var/@345.4:80")
+            self.assert_(a1.family is None)
+            self.assert_(a2.family is None)
 
     def test_constructor(self):
         convert = self.types.get('constructor')


=== Zope/lib/python/ZConfig/tests/test_loader.py 1.1.2.6 => 1.1.2.7 ===
--- Zope/lib/python/ZConfig/tests/test_loader.py:1.1.2.6	Fri Jan  3 13:07:10 2003
+++ Zope/lib/python/ZConfig/tests/test_loader.py	Thu Jan  9 14:27:49 2003
@@ -1,6 +1,6 @@
 ##############################################################################
 #
-# Copyright (c) 2002 Zope Corporation and Contributors.
+# Copyright (c) 2002, 2003 Zope Corporation and Contributors.
 # All Rights Reserved.
 #
 # This software is subject to the provisions of the Zope Public License,
@@ -13,31 +13,40 @@
 ##############################################################################
 """Tests of ZConfig.loader classes and helper functions."""
 
+import os.path
+import sys
 import unittest
-import urlparse
 
 from StringIO import StringIO
 
 import ZConfig
 import ZConfig.loader
-
-from ZConfig import url
+import ZConfig.url
 
 from ZConfig.tests.test_config import CONFIG_BASE
 
 
+try:
+    myfile = __file__
+except NameError:
+    myfile = sys.argv[0]
+
+myfile = os.path.abspath(myfile)
+LIBRARY_DIR = os.path.join(os.path.dirname(myfile), "library")
+
+
 class LoaderTestCase(unittest.TestCase):
 
     def test_schema_caching(self):
         loader = ZConfig.loader.SchemaLoader()
-        url = urlparse.urljoin(CONFIG_BASE, "simple.xml")
+        url = ZConfig.url.urljoin(CONFIG_BASE, "simple.xml")
         schema1 = loader.loadURL(url)
         schema2 = loader.loadURL(url)
         self.assert_(schema1 is schema2)
 
     def test_schema_components(self):
         loader = ZConfig.loader.SchemaLoader()
-        url = urlparse.urljoin(CONFIG_BASE, "library.xml")
+        url = ZConfig.url.urljoin(CONFIG_BASE, "library.xml")
         schema = loader.loadURL(url)
         type_a = loader.loadURL(url + "#type-a")
         type_b = loader.loadURL(url + "#type-b")
@@ -49,13 +58,13 @@
 
     def test_simple_import_with_cache(self):
         loader = ZConfig.loader.SchemaLoader()
-        url1 = urlparse.urljoin(CONFIG_BASE, "library.xml")
+        url1 = ZConfig.url.urljoin(CONFIG_BASE, "library.xml")
         schema1 = loader.loadURL(url1)
         sio = StringIO("<schema>"
                        "  <import src='library.xml'/>"
                        "  <section type='type-a' name='section'/>"
                        "</schema>")
-        url2 = urlparse.urljoin(CONFIG_BASE, "stringio")
+        url2 = ZConfig.url.urljoin(CONFIG_BASE, "stringio")
         schema2 = loader.loadFile(sio, url2)
         self.assert_(schema1.gettype("type-a") is schema2.gettype("type-a"))
 
@@ -69,59 +78,68 @@
                                    "          package='ZConfig'/>"
                                    "</schema>"))
 
-    def test_zconfig_resource(self):
-        loader = ZConfig.loader.SchemaLoader()
-        r = loader.openResource("zconfig:schema.dtd")
-        self.assert_(r.fragment is None)
-        self.assertEqual(r.url, "zconfig:schema.dtd")
-        # just make sure we can read it; we don't care about the content:
-        self.assert_(r.readline())
-        self.assert_(not r.closed)
-        r.close()
-        self.assert_(r.closed)
-
-    def test_urldefrag(self):
-        eq = self.assertEqual
-        eq(url.urldefrag("zconfig:abc/def.ghi#frag"),
-           ("zconfig:abc/def.ghi", "frag"))
-        eq(url.urldefrag("zconfig:abc/def.ghi"),
-           ("zconfig:abc/def.ghi", ''))
-
-    def test_urlsplit_absolute(self):
-        parts = url.urlsplit("zconfig:path/to/resource/file.txt#fragment")
-        self.assertEqual(parts, ("zconfig", '', "path/to/resource/file.txt",
-                                 '', "fragment"))
-        self.assertRaises(ValueError, url.urlsplit, "zconfig://host")
-        self.assertRaises(ValueError, url.urlsplit, "zconfig:host?query")
-
-    def test_urlsplit_relative(self):
-        eq = self.assertEqual
-        raises = self.assertRaises
-
-        def urlsplit(s):
-            return url.urlsplit(s, scheme="zconfig")
-
-        eq(urlsplit("#frag"),
-           ('zconfig', '', '', '', "frag"))
-        eq(urlsplit("path/to/resource#frag"),
-           ('zconfig', '', "path/to/resource", '', "frag"))
-        eq(url.urlsplit("path/to/resource/file.txt#fragment", "zconfig"),
-           ('zconfig', '', "path/to/resource/file.txt", '', "fragment"))
-
-        raises(ValueError, urlsplit, "/path/to/resource")
-        raises(ValueError, urlsplit, "/path/to/resource?query")
-        raises(ValueError, urlsplit, "path/to/resource?query")
-
-    def test_urljoin(self):
-        eq = self.assertEqual
-        eq(url.urljoin("zconfig:path/file.txt#oldfrag", "../newpath/foo.xml"),
-           "zconfig:newpath/foo.xml")
-        eq(url.urljoin("zconfig:abc.xml", "def.xml"),
-           "zconfig:def.xml")
-        eq(url.urljoin("zconfig:abc.xml", "#frag"),
-           "zconfig:abc.xml#frag")
-        self.assertRaises(ValueError, url.urljoin,
-                          "zconfig:abc.xml", "../def.xml")
+    def test_import_from_package(self):
+        loader = ZConfig.loader.SchemaLoader(library=LIBRARY_DIR)
+        sio = StringIO("<schema>"
+                       "  <import package='widget'/>"
+                       "</schema>")
+        schema = loader.loadFile(sio)
+        self.assert_(schema.gettype("widget-a") is not None)
+
+    def test_import_from_package_extended(self):
+        loader = ZConfig.loader.SchemaLoader(library=LIBRARY_DIR)
+        sio = StringIO("<schema>"
+                       "  <import package='thing'/>"
+                       "  <section name='*' type='thing' attribute='thing'/>"
+                       "</schema>")
+        schema = loader.loadFile(sio)
+        schema.gettype("thing")
+        schema.gettype("thing-a")
+        schema.gettype("thing-b")
+        schema.gettype("thing-ext")
+
+        # Make sure the extension is wired in properly:
+        sio = StringIO("<thing-ext thing/>")
+        conf, handlers = ZConfig.loadConfigFile(schema, sio)
+        self.assertEqual(conf.thing.thing_ext_key, "thing-ext-default")
+
+    def test_urlsplit_urlunsplit(self):
+        # Extracted from Python's test.test_urlparse module:
+        for url, parsed, split in [
+            ('http://www.python.org',
+             ('http', 'www.python.org', '', '', '', ''),
+             ('http', 'www.python.org', '', '', '')),
+            ('http://www.python.org#abc',
+             ('http', 'www.python.org', '', '', '', 'abc'),
+             ('http', 'www.python.org', '', '', 'abc')),
+            ('http://www.python.org/#abc',
+             ('http', 'www.python.org', '/', '', '', 'abc'),
+             ('http', 'www.python.org', '/', '', 'abc')),
+            ("http://a/b/c/d;p?q#f",
+             ('http', 'a', '/b/c/d', 'p', 'q', 'f'),
+             ('http', 'a', '/b/c/d;p', 'q', 'f')),
+            ('file:///tmp/junk.txt',
+             ('file', '', '/tmp/junk.txt', '', '', ''),
+             ('file', '', '/tmp/junk.txt', '', '')),
+            ]:
+            result = ZConfig.url.urlsplit(url)
+            self.assertEqual(result, split)
+            result2 = ZConfig.url.urlunsplit(result)
+            self.assertEqual(result2, url)
+
+    def test_file_url_normalization(self):
+        self.assertEqual(
+            ZConfig.url.urlnormalize("file:/abc/def"),
+            "file:///abc/def")
+        self.assertEqual(
+            ZConfig.url.urlunsplit(("file", "", "/abc/def", "", "")),
+            "file:///abc/def")
+        self.assertEqual(
+            ZConfig.url.urljoin("file:/abc/", "def"),
+            "file:///abc/def")
+        self.assertEqual(
+            ZConfig.url.urldefrag("file:/abc/def#frag"),
+            ("file:///abc/def", "frag"))
 
 
 def test_suite():


=== Zope/lib/python/ZConfig/tests/test_schema.py 1.1.2.38 => 1.1.2.39 ===
--- Zope/lib/python/ZConfig/tests/test_schema.py:1.1.2.38	Fri Jan  3 12:05:22 2003
+++ Zope/lib/python/ZConfig/tests/test_schema.py	Thu Jan  9 14:27:49 2003
@@ -1,6 +1,6 @@
 ##############################################################################
 #
-# Copyright (c) 2002 Zope Corporation and Contributors.
+# Copyright (c) 2002, 2003 Zope Corporation and Contributors.
 # All Rights Reserved.
 #
 # This software is subject to the provisions of the Zope Public License,
@@ -49,9 +49,9 @@
         self.assert_(self.schema.issection())
         return self.schema
 
-    def load_schema_text(self, text):
+    def load_schema_text(self, text, url=None):
         sio = StringIO.StringIO(text)
-        self.schema = ZConfig.loadSchemaFile(sio)
+        self.schema = ZConfig.loadSchemaFile(sio, url)
         return self.schema
 
     def load_config(self, schema, conf_url, num_handlers=0):
@@ -60,9 +60,9 @@
         self.assertEqual(len(self.handlers), num_handlers)
         return self.conf
 
-    def load_config_text(self, schema, text, num_handlers=0):
+    def load_config_text(self, schema, text, num_handlers=0, url=None):
         sio = StringIO.StringIO(text)
-        self.conf, self.handlers = ZConfig.loadConfigFile(schema, sio)
+        self.conf, self.handlers = ZConfig.loadConfigFile(schema, sio, url)
         self.assertEqual(len(self.handlers), num_handlers)
         return self.conf
 
@@ -126,7 +126,7 @@
     def test_app_sectiontype(self):
         schema = self.load_schema_text(
             "<schema datatype='.appsection' prefix='%s'>"
-            "  <sectiontype type='foo' datatype='.MySection'>"
+            "  <sectiontype name='foo' datatype='.MySection'>"
             "    <key name='sample' datatype='integer' default='345'/>"
             "    </sectiontype>"
             "  <section name='sect' type='foo' />"
@@ -148,7 +148,7 @@
     def test_empty_sections(self):
         schema = self.load_schema_text(
             "<schema>"
-            "  <sectiontype type='section'/>"
+            "  <sectiontype name='section'/>"
             "  <section type='section' name='s1'/>"
             "  <section type='section' name='s2'/>"
             "</schema>")
@@ -162,17 +162,17 @@
     def test_deeply_nested_sections(self):
         schema = self.load_schema_text(
             "<schema>"
-            "  <sectiontype type='type1'>"
+            "  <sectiontype name='type1'>"
             "    <key name='key' default='type1-value'/>"
-            "    </sectiontype>"
-            "  <sectiontype type='type2'>"
+            "  </sectiontype>"
+            "  <sectiontype name='type2'>"
             "    <key name='key' default='type2-value'/>"
             "    <section name='sect' type='type1'/>"
-            "    </sectiontype>"
-            "  <sectiontype type='type3'>"
+            "  </sectiontype>"
+            "  <sectiontype name='type3'>"
             "    <key name='key' default='type3-value'/>"
             "    <section name='sect' type='type2'/>"
-            "    </sectiontype>"
+            "  </sectiontype>"
             "  <section name='sect' type='type3'/>"
             "</schema>")
         conf = self.load_config_text(schema,
@@ -250,9 +250,9 @@
     def test_handler_ordering(self):
         schema = self.load_schema_text(
             "<schema handler='c'>"
-            "  <sectiontype type='inner'>"
+            "  <sectiontype name='inner'>"
             "  </sectiontype>"
-            "  <sectiontype type='outer'>"
+            "  <sectiontype name='outer'>"
             "    <section type='inner' name='sect-inner' handler='a'/>"
             "  </sectiontype>"
             "  <section type='outer' name='sect-outer' handler='b'/>"
@@ -273,10 +273,10 @@
     def test_duplicate_section_names(self):
         schema = self.load_schema_text(
             "<schema>"
-            "  <sectiontype type='sect'/>"
-            "  <sectiontype type='nesting'>"
+            "  <sectiontype name='sect'/>"
+            "  <sectiontype name='nesting'>"
             "    <section name='a' type='sect'/>"
-            "    </sectiontype>"
+            "  </sectiontype>"
             "  <section name='a' type='nesting'/>"
             "</schema>")
         self.assertRaises(ZConfig.ConfigurationError,
@@ -299,29 +299,28 @@
         self.assertRaises(ZConfig.SchemaError,
                           self.load_schema_text, "<schema datatype='foobar'/>")
 
-    def test_load_sectiongroup(self):
+    def test_load_abstracttype(self):
         schema = self.load_schema_text(
             "<schema>"
-            "  <sectiongroup type='group'>"
-            "    <sectiontype type='t1'>"
-            "      <key name='k1' default='default1'/>"
-            "      </sectiontype>"
-            "    <sectiontype type='t2'>"
-            "      <key name='k2' default='default2'/>"
-            "      </sectiontype>"
-            "    </sectiongroup>"
+            "  <abstracttype name='group'/>"
+            "  <sectiontype name='t1' implements='group'>"
+            "    <key name='k1' default='default1'/>"
+            "  </sectiontype>"
+            "  <sectiontype name='t2' implements='group'>"
+            "    <key name='k2' default='default2'/>"
+            "  </sectiontype>"
             "  <multisection name='*' type='group' attribute='g'/>"
             "</schema>")
         # check the types that get defined
         t = schema.gettype("group")
-        self.assert_(t.istypegroup())
+        self.assert_(t.isabstract())
         t1 = schema.gettype("t1")
-        self.assert_(not t1.istypegroup())
-        self.assert_(t.gettype("t1") is t1)
+        self.assert_(not t1.isabstract())
+        self.assert_(t.getsubtype("t1") is t1)
         t2 = schema.gettype("t2")
-        self.assert_(not t2.istypegroup())
-        self.assert_(t.gettype("t2") is t2)
-        self.assertRaises(ZConfig.ConfigurationError, t.gettype, "group")
+        self.assert_(not t2.isabstract())
+        self.assert_(t.getsubtype("t2") is t2)
+        self.assertRaises(ZConfig.ConfigurationError, t.getsubtype, "group")
         self.assert_(t1 is not t2)
         # try loading a config that relies on this schema
         conf = self.load_config_text(schema,
@@ -342,38 +341,31 @@
         self.assert_(conf.g[2]._type is t2)
         self.assert_(conf.g[3]._type is t2)
 
-    def test_sectiongroup_extension(self):
+    def test_abstracttype_extension(self):
         schema = self.load_schema_text(
             "<schema>"
-            "  <sectiongroup type='group'/>"
-            "  <sectiontype type='extra' group='group'/>"
+            "  <abstracttype name='group'/>"
+            "  <sectiontype name='extra' implements='group'/>"
             "  <section name='thing' type='group'/>"
             "</schema>")
-        group = schema.gettype("group")
-        self.assert_(schema.gettype("extra") is group.gettype("extra"))
+        abstype = schema.gettype("group")
+        self.assert_(schema.gettype("extra") is abstype.getsubtype("extra"))
 
         # make sure we can use the extension in a config:
         conf = self.load_config_text(schema, "<extra thing/>")
         self.assertEqual(conf.thing.getSectionType(), "extra")
 
-    def test_sectiongroup_extension_errors(self):
-        # specifying a non-existant group
+    def test_abstracttype_extension_errors(self):
+        # specifying a non-existant abstracttype
         self.assertRaises(ZConfig.SchemaError, self.load_schema_text,
                           "<schema>"
-                          "  <sectiontype type='s' group='group'/>"
+                          "  <sectiontype name='s' implements='group'/>"
                           "</schema>")
-        # specifying something that isn't a group
+        # specifying something that isn't an abstracttype
         self.assertRaises(ZConfig.SchemaError, self.load_schema_text,
                           "<schema>"
-                          "  <sectiontype type='t1'/>"
-                          "  <sectiontype type='t2' group='t1'/>"
-                          "</schema>")
-        # specifying a group from w/in a group
-        self.assertRaises(ZConfig.SchemaError, self.load_schema_text,
-                          "<schema>"
-                          "  <sectiongroup type='group'>"
-                          "    <sectiontype type='t' group='group'/>"
-                          "  </sectiongroup>"
+                          "  <sectiontype name='t1'/>"
+                          "  <sectiontype name='t2' implements='t1'/>"
                           "</schema>")
 
     def test_arbitrary_key(self):
@@ -429,8 +421,8 @@
 
         schema = self.load_schema_text(
             "<schema type='top'>"
-            "  <sectiontype type='used'/>"
-            "  <sectiontype type='unused'/>"
+            "  <sectiontype name='used'/>"
+            "  <sectiontype name='unused'/>"
             "  <section type='used' name='a'/>"
             "</schema>")
         L = schema.getrequiredtypes()
@@ -445,8 +437,8 @@
 
         schema = self.load_schema_text(
             "<schema type='top'>"
-            "  <sectiontype type='used'/>"
-            "  <sectiontype type='unused'/>"
+            "  <sectiontype name='used'/>"
+            "  <sectiontype name='unused'/>"
             "  <section type='used' name='a'/>"
             "</schema>")
         self.assertEqual(schema.getunusedtypes(), ["unused"])
@@ -461,7 +453,7 @@
     def test_simple_anonymous_section(self):
         schema = self.load_schema_text(
             "<schema>"
-            "  <sectiontype type='sect'>"
+            "  <sectiontype name='sect'>"
             "    <key name='key' default='value'/>"
             "  </sectiontype>"
             "  <section name='*' type='sect' attribute='attr'/>"
@@ -472,7 +464,7 @@
     def test_simple_anynamed_section(self):
         schema = self.load_schema_text(
             "<schema>"
-            "  <sectiontype type='sect'>"
+            "  <sectiontype name='sect'>"
             "    <key name='key' default='value'/>"
             "  </sectiontype>"
             "  <section name='+' type='sect' attribute='attr'/>"
@@ -488,19 +480,18 @@
     def test_nested_abstract_sectiontype(self):
         schema = self.load_schema_text(
             "<schema>"
-            "  <sectiongroup type='abstract'>"
-            "    <sectiontype type='t1'/>"
-            "    <sectiontype type='t2'>"
-            "      <section type='abstract' name='s1'/>"
-            "    </sectiontype>"
-            "  </sectiongroup>"
+            "  <abstracttype name='abstract'/>"
+            "  <sectiontype name='t1' implements='abstract'/>"
+            "  <sectiontype name='t2' implements='abstract'>"
+            "    <section type='abstract' name='s1'/>"
+            "  </sectiontype>"
             "  <section type='abstract' name='*' attribute='s2'/>"
             "</schema>")
         conf = self.load_config_text(schema, "<t2>\n <t1 s1/>\n</t2>")
 
     def test_reserved_attribute_prefix(self):
         template = ("<schema>\n"
-                    "  <sectiontype type='s'/>\n"
+                    "  <sectiontype name='s'/>\n"
                     "  %s\n"
                     "</schema>")
         def check(thing, self=self, template=template):
@@ -516,6 +507,105 @@
         check("<section type='s' name='*' attribute='getSectionThing'/>")
         check("<multisection type='s' name='*' attribute='getSection'/>")
         check("<multisection type='s' name='*' attribute='getSectionThing'/>")
+
+    def test_sectiontype_as_schema(self):
+        schema = self.load_schema_text(
+            "<schema>"
+            "  <sectiontype name='s'>"
+            "    <key name='skey' default='skey-default'/>"
+            "  </sectiontype>"
+            "  <sectiontype name='t'>"
+            "    <key name='tkey' default='tkey-default'/>"
+            "    <section name='*' type='s' attribute='section'/>"
+            "  </sectiontype>"
+            "</schema>")
+        t = schema.gettype("t")
+        conf = self.load_config_text(t, "<s/>")
+        self.assertEqual(conf.tkey, "tkey-default")
+        self.assertEqual(conf.section.skey, "skey-default")
+
+    def test_datatype_conversion_error(self):
+        schema_url = "file:///tmp/fake-url-1.xml"
+        config_url = "file:///tmp/fake-url-2.xml"
+        schema = self.load_schema_text("<schema>\n"
+                                       "  <key name='key' default='bogus'"
+                                       "       datatype='integer'/>"
+                                       "</schema>", url=schema_url)
+        e = self.get_data_conversion_error(
+            schema, "", config_url)
+        self.assertEqual(e.url, schema_url)
+        self.assertEqual(e.lineno, 2)
+
+        e = self.get_data_conversion_error(
+            schema, "# comment\n\n key splat\n", config_url)
+        self.assertEqual(e.url, config_url)
+        self.assertEqual(e.lineno, 3)
+
+    def get_data_conversion_error(self, schema, src, url):
+        try:
+            self.load_config_text(schema, src, url=url)
+        except ZConfig.DataConversionError, e:
+            return e
+        else:
+            self.fail("expected ZConfig.DataConversionError")
+
+    def test_numeric_section_name(self):
+        schema = self.load_schema_text("<schema>"
+                                       "  <sectiontype name='sect'/>"
+                                       "  <multisection name='*' type='sect'"
+                                       "                attribute='things'/>"
+                                       "</schema>")
+        conf = self.load_config_text(schema,
+                                     "<sect 1 />")
+        self.assertEqual(len(conf.things), 1)
+
+    def test_sectiontype_extension(self):
+        schema = self.load_schema_text("<schema>"
+                                       "  <sectiontype name='t1'>"
+                                       "    <key name='k1'/>"
+                                       "  </sectiontype>"
+                                       "  <sectiontype name='t2' extends='t1'>"
+                                       "    <key name='k2'/>"
+                                       "  </sectiontype>"
+                                       "  <section name='s' type='t2'/>"
+                                       "</schema>")
+        conf = self.load_config_text(schema,
+                                     "<t2 s>\n"
+                                     "  k1 k1-value\n"
+                                     "  k2 k2-value\n"
+                                     "</t2>")
+        self.assertEqual(conf.s.k1, "k1-value")
+        self.assertEqual(conf.s.k2, "k2-value")
+
+    def test_sectiontype_extension_errors(self):
+        # cannot override key from base
+        self.assertRaises(ZConfig.SchemaError, self.load_schema_text,
+                          "<schema>"
+                          "  <sectiontype name='t1'>"
+                          "    <key name='k1'/>"
+                          "  </sectiontype>"
+                          "  <sectiontype name='t2' extends='t1'>"
+                          "    <key name='k1'/>"
+                          "  </sectiontype>"
+                          "</schema>")
+        # cannot extend non-existing section
+        self.assertRaises(ZConfig.SchemaError, self.load_schema_text,
+                          "<schema>"
+                          "  <sectiontype name='t2' extends='t1'/>"
+                          "</schema>")
+        # cannot extend abstract type
+        self.assertRaises(ZConfig.SchemaError, self.load_schema_text,
+                          "<schema>"
+                          "  <abstracttype name='t1'/>"
+                          "  <sectiontype name='t2' extends='t1'/>"
+                          "</schema>")
+        # cannot specify keytype
+        self.assertRaises(ZConfig.SchemaError, self.load_schema_text,
+                          "<schema>"
+                          "  <sectiontype name='t1' keytype='string'/>"
+                          "  <sectiontype name='t2' extends='t1'"
+                          "               keytype='integer'/>"
+                          "</schema>")
 
 
 def test_suite():


=== Zope/lib/python/ZConfig/tests/test_subst.py 1.1.2.3 => 1.1.2.4 ===
--- Zope/lib/python/ZConfig/tests/test_subst.py:1.1.2.3	Fri Dec 20 12:49:02 2002
+++ Zope/lib/python/ZConfig/tests/test_subst.py	Thu Jan  9 14:27:49 2003
@@ -1,6 +1,6 @@
 ##############################################################################
 #
-# Copyright (c) 2002 Zope Corporation and Contributors.
+# Copyright (c) 2002, 2003 Zope Corporation and Contributors.
 # All Rights Reserved.
 #
 # This software is subject to the provisions of the Zope Public License,


=== Zope/lib/python/ZConfig/tests/test_zopeschema.py 1.1.2.7 => 1.1.2.8 ===
--- Zope/lib/python/ZConfig/tests/test_zopeschema.py:1.1.2.7	Tue Dec 24 15:49:51 2002
+++ Zope/lib/python/ZConfig/tests/test_zopeschema.py	Thu Jan  9 14:27:49 2003
@@ -1,6 +1,6 @@
 ##############################################################################
 #
-# Copyright (c) 2002 Zope Corporation and Contributors.
+# Copyright (c) 2002, 2003 Zope Corporation and Contributors.
 # All Rights Reserved.
 #
 # This software is subject to the provisions of the Zope Public License,
@@ -119,12 +119,10 @@
     # tests
 
     def test_defaultbug(self):
-        schema = self.load_schema('zconfig:zope.xml')
-        conf = self.load_config(schema, 'empty.conf')
+        schema, conf = self.load_both('zope.xml', 'empty.conf')
 
     def test_load_populated(self):
-        schema = self.load_schema('zconfig:zope.xml')
-        conf = self.load_config(schema, 'zope-allpopulated.conf')
+        schema, conf = self.load_both('zope.xml', 'zope-allpopulated.conf')
         self.assertEqual(conf.zope_home, '.')
         self.assertEqual(conf.instance_home, '.')
         self.assertEqual(conf.software_home, '.')