[Zope3-checkins] CVS: Packages/ZConfig - url.py:1.1.2.1 cfgparser.py:1.1.2.7 loader.py:1.1.2.24

Fred L. Drake, Jr. fred@zope.com
Tue, 24 Dec 2002 15:48:18 -0500


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

Modified Files:
      Tag: zconfig-schema-devel-branch
	cfgparser.py loader.py 
Added Files:
      Tag: zconfig-schema-devel-branch
	url.py 
Log Message:
Use a new URI scheme to identify local ZConfig resources, and use the URL
helpers from ZConfig.url instead of using the urlparse module directly.


=== Added File Packages/ZConfig/url.py ===
"""urlparse-like helpers that support the zconfig scheme."""

import posixpath as _posixpath
import urlparse as _urlparse

from urllib import splittype as _splittype
from urlparse import urlunsplit


def urldefrag(url):
    parts = urlsplit(url)
    if parts[0] == "zconfig" and '#' in url:
        path, fragment = parts[2].split('#', 1)
        parts = "zconfig", '', path, '', ''
        return parts, fragment
    else:
        return _urlparse.urldefrag(url)


def urljoin(base, relurl):
    if _splittype(base)[0] != "zconfig":
        return _urlparse.urljoin(base, relurl)
    relscheme = _splittype(relurl)[0]
    if relscheme and relscheme != "zconfig":
        return _urlparse.urljoin(base, relurl)
    baseparts = urlsplit(base)
    relparts = urlsplit(relurl, "zconfig")
    if relparts[2]:
        d = _posixpath.dirname(baseparts[2]) + '/'
        path = _posixpath.normpath(_posixpath.join(d, relparts[2]))
    else:
        path = baseparts[2]
    parts = path.split('/')
    if '..' in parts:
        raise ValueError("zconfig URIs cannot include '..' references: "
                         + `path`)
    s = "zconfig:" + path
    if relparts[4]:
        s += "#" + relparts[4]
    return s


def urlsplit(url, scheme=''):
    parts = _urlparse.urlsplit(url)
    scheme = parts[0] or scheme
    if scheme == "zconfig":
        path = parts[2]
        if not path:
            raise ValueError("zconfig URIs require a non-empty path component")
        if parts[0] and '..' in path.split('/'):
            raise ValueError("zconfig URIs cannot include '..' references: "
                             + `url`)
        # Split the fragment ourselves since the urlparse module
        # doesn't know about the zconfig: scheme.
        if '#' in path:
            path, fragment = path.split('#', 1)
            parts = "zconfig", '', path, '', fragment
        if path[0] == '/':
            raise ValueError(
                "path component of zconfig: URIs may not start with '/'")
        if '?' in path:
            raise ValueError("zconfig: URIs may not contain queries: "
                             + `url`)
    return parts


=== Packages/ZConfig/cfgparser.py 1.1.2.6 => 1.1.2.7 ===
--- Packages/ZConfig/cfgparser.py:1.1.2.6	Fri Dec 20 12:49:00 2002
+++ Packages/ZConfig/cfgparser.py	Tue Dec 24 15:48:18 2002
@@ -15,6 +15,7 @@
 
 from ZConfig import ConfigurationError, ConfigurationSyntaxError
 from ZConfig.substitution import isname, substitute
+from ZConfig.url import urljoin
 
 try:
     True
@@ -143,8 +144,7 @@
             assert 0, "unexpected directive for " + `"%" + rest`
 
     def handle_include(self, section, rest):
-        import urlparse
-        newurl = urlparse.urljoin(self.url, rest)
+        newurl = urljoin(self.url, rest)
         self.context.includeConfiguration(section, newurl)
 
     def handle_define(self, section, rest):


=== Packages/ZConfig/loader.py 1.1.2.23 => 1.1.2.24 ===
--- Packages/ZConfig/loader.py:1.1.2.23	Mon Dec 23 11:21:57 2002
+++ Packages/ZConfig/loader.py	Tue Dec 24 15:48:18 2002
@@ -16,12 +16,12 @@
 import os.path
 import urllib
 import urllib2
-import urlparse
 
 import ZConfig
 
 from ZConfig import datatypes
 from ZConfig import matcher
+from ZConfig.url import urldefrag, urljoin, urlsplit, urlunsplit
 
 try:
     True
@@ -29,6 +29,11 @@
     True = 1
     False = 0
 
+
+RESOURCE_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)),
+                            "resources")
+
+
 def loadSchema(url):
     return SchemaLoader().loadURL(url)
 
@@ -59,7 +64,7 @@
 
     def loadFile(self, file, url=None):
         if not url:
-            url = self._url_from_file(file)
+            url = _url_from_file(file)
         r = self.createResource(file, url)
         return self.loadResource(r)
 
@@ -74,20 +79,27 @@
         # resources.  The policy needs to support both re-retrieve on
         # change and provide the cached resource when the remote
         # resource is not accessible.
-        url, fragment = urlparse.urldefrag(url)
-        file = urllib2.urlopen(url)
+        parts = list(urlsplit(url))
+        fragment = parts[-1]
+        if fragment:
+            parts[-1] = ''
+            url = urlunsplit(tuple(parts))
+        if parts[0] == 'zconfig':
+            file = _open_resource_file(url)
+        else:
+            file = urllib2.urlopen(url)
         return self.createResource(file, url, fragment or None)
 
     def normalizeURL(self, url):
         if os.path.exists(url):
             url = "file://" + urllib.pathname2url(os.path.abspath(url))
         else:
-            parts = urlparse.urlparse(url)
+            parts = urlsplit(url)
             if not parts[0]:
                 raise ValueError("invalid URL, or file does not exist:\n"
                                  + repr(url))
         if url and not self.allowFragments():
-            url, fragment = urlparse.urldefrag(url)
+            url, fragment = urldefrag(url)
             if fragment:
                 raise ZConfig.ConfigurationError(
                     "fragment identifiers are not currently supported")
@@ -96,12 +108,22 @@
     def allowFragments(self):
         return False
 
-    def _url_from_file(self, 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
+
+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
+
+
+def _open_resource_file(url):
+    parts = urlsplit(url)
+    assert parts[0] == 'zconfig'
+    fn = os.path.join(RESOURCE_DIR, parts[2])
+    if not os.path.isfile(fn):
+        raise ValueError("no such resource: " + `parts[2]`)
+    return open(fn)
 
 
 class SchemaLoader(BaseLoader):