[Zconfig] SVN: ZConfig/trunk/ZConfig/ add support for importing schema components from ZIP archives (including eggs)

Fred L. Drake, Jr. fdrake at gmail.com
Tue Nov 8 11:33:54 EST 2005


Log message for revision 39982:
  add support for importing schema components from ZIP archives (including eggs)

Changed:
  U   ZConfig/trunk/ZConfig/loader.py
  A   ZConfig/trunk/ZConfig/tests/foosample.zip
  U   ZConfig/trunk/ZConfig/tests/test_loader.py
  A   ZConfig/trunk/ZConfig/tests/zipsource/
  A   ZConfig/trunk/ZConfig/tests/zipsource/README.txt
  A   ZConfig/trunk/ZConfig/tests/zipsource/foo/
  A   ZConfig/trunk/ZConfig/tests/zipsource/foo/__init__.py
  A   ZConfig/trunk/ZConfig/tests/zipsource/foo/sample/
  A   ZConfig/trunk/ZConfig/tests/zipsource/foo/sample/__init__.py
  A   ZConfig/trunk/ZConfig/tests/zipsource/foo/sample/component.xml
  A   ZConfig/trunk/ZConfig/tests/zipsource/foo/sample/datatypes.py

-=-
Modified: ZConfig/trunk/ZConfig/loader.py
===================================================================
--- ZConfig/trunk/ZConfig/loader.py	2005-11-08 16:31:24 UTC (rev 39981)
+++ ZConfig/trunk/ZConfig/loader.py	2005-11-08 16:33:53 UTC (rev 39982)
@@ -13,6 +13,7 @@
 ##############################################################################
 """Schema loader utility."""
 
+import cStringIO
 import os.path
 import sys
 import urllib
@@ -90,16 +91,20 @@
         # 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))
+        if url.startswith("package:"):
+            _, package, filename = url.split(":", 2)
+            file = openPackageResource(package, filename)
+        else:
+            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):
@@ -135,7 +140,30 @@
             return True
 
 
+def openPackageResource(package, path):
+    __import__(package)
+    pkg = sys.modules[package]
+    try:
+        loader = pkg.__loader__
+    except AttributeError:
+        relpath = os.path.join(*path.split("/"))
+        for dir in pkg.__path__:
+            filename = os.path.join(dir, relpath)
+            if os.path.exists(filename):
+                break
+        else:
+            raise ZConfig.SchemaResourceError("schema component not found",
+                                              filename=path,
+                                              package=package,
+                                              path=pkg.__path__)
+        url = "file:" + urllib.pathname2url(filename)
+        url = ZConfig.url.urlnormalize(url)
+        return urllib2.urlopen(url)
+    else:
+        loadpath = os.path.join(os.path.dirname(pkg.__file__), path)
+        return cStringIO.StringIO(loader.get_data(loadpath))
 
+
 def _url_from_file(file):
     name = getattr(file, "name", None)
     if name and name[0] != "<" and name[-1] != ">":
@@ -184,16 +212,7 @@
             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__)
+        return "package:%s:%s" % (package, file)
 
 
 class ConfigLoader(BaseLoader):

Added: ZConfig/trunk/ZConfig/tests/foosample.zip
===================================================================
(Binary files differ)


Property changes on: ZConfig/trunk/ZConfig/tests/foosample.zip
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Modified: ZConfig/trunk/ZConfig/tests/test_loader.py
===================================================================
--- ZConfig/trunk/ZConfig/tests/test_loader.py	2005-11-08 16:31:24 UTC (rev 39981)
+++ ZConfig/trunk/ZConfig/tests/test_loader.py	2005-11-08 16:33:53 UTC (rev 39982)
@@ -284,9 +284,57 @@
                           "http://www.zope.org/no-such-document/")
 
 
+class TestResourcesInZip(unittest.TestCase):
+
+    def setUp(self):
+        self.old_path = sys.path[:]
+        # now add our sample EGG to sys.path:
+        zipfile = os.path.join(os.path.dirname(myfile), "foosample.zip")
+        sys.path.append(zipfile)
+
+    def tearDown(self):
+        sys.path[:] = self.old_path
+
+    def test_zip_import_component_from_schema(self):
+        sio = StringIO('''
+            <schema>
+              <abstracttype name="something"/>
+              <import package="foo.sample"/>
+              <section name="*"
+                       attribute="something"
+                       type="something"
+                       />
+            </schema>
+            ''')
+        schema = ZConfig.loadSchemaFile(sio)
+        t = schema.gettype("sample")
+        self.failIf(t.isabstract())
+
+    def test_zip_import_component_from_config(self):
+        sio = StringIO('''
+            <schema>
+              <abstracttype name="something"/>
+              <section name="*"
+                       attribute="something"
+                       type="something"
+                       />
+            </schema>
+            ''')
+        schema = ZConfig.loadSchemaFile(sio)
+        sio = StringIO('''
+            %import foo.sample
+            <sample>
+              data value
+            </sample>
+            ''')
+        config, _ = ZConfig.loadConfigFile(schema, sio)
+        self.assertEqual(config.something.data, "| value |")
+
+
 def test_suite():
     suite = unittest.makeSuite(LoaderTestCase)
     suite.addTest(unittest.makeSuite(TestNonExistentResources))
+    suite.addTest(unittest.makeSuite(TestResourcesInZip))
     return suite
 
 if __name__ == '__main__':

Added: ZConfig/trunk/ZConfig/tests/zipsource/README.txt
===================================================================
--- ZConfig/trunk/ZConfig/tests/zipsource/README.txt	2005-11-08 16:31:24 UTC (rev 39981)
+++ ZConfig/trunk/ZConfig/tests/zipsource/README.txt	2005-11-08 16:33:53 UTC (rev 39982)
@@ -0,0 +1,2 @@
+This directory contains a sample package that is used to create the
+'foosample.zip' file used in the tests.


Property changes on: ZConfig/trunk/ZConfig/tests/zipsource/README.txt
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:eol-style
   + native

Added: ZConfig/trunk/ZConfig/tests/zipsource/foo/__init__.py
===================================================================
--- ZConfig/trunk/ZConfig/tests/zipsource/foo/__init__.py	2005-11-08 16:31:24 UTC (rev 39981)
+++ ZConfig/trunk/ZConfig/tests/zipsource/foo/__init__.py	2005-11-08 16:33:53 UTC (rev 39982)
@@ -0,0 +1 @@
+# This directory is a Python package.


Property changes on: ZConfig/trunk/ZConfig/tests/zipsource/foo/__init__.py
___________________________________________________________________
Name: svn:mime-type
   + text/x-python
Name: svn:eol-style
   + native

Added: ZConfig/trunk/ZConfig/tests/zipsource/foo/sample/__init__.py
===================================================================
--- ZConfig/trunk/ZConfig/tests/zipsource/foo/sample/__init__.py	2005-11-08 16:31:24 UTC (rev 39981)
+++ ZConfig/trunk/ZConfig/tests/zipsource/foo/sample/__init__.py	2005-11-08 16:33:53 UTC (rev 39982)
@@ -0,0 +1 @@
+# This directory is a Python package.


Property changes on: ZConfig/trunk/ZConfig/tests/zipsource/foo/sample/__init__.py
___________________________________________________________________
Name: svn:mime-type
   + text/x-python
Name: svn:eol-style
   + native

Added: ZConfig/trunk/ZConfig/tests/zipsource/foo/sample/component.xml
===================================================================
--- ZConfig/trunk/ZConfig/tests/zipsource/foo/sample/component.xml	2005-11-08 16:31:24 UTC (rev 39981)
+++ ZConfig/trunk/ZConfig/tests/zipsource/foo/sample/component.xml	2005-11-08 16:33:53 UTC (rev 39982)
@@ -0,0 +1,9 @@
+<component prefix="foo.sample">
+
+  <!-- `something` is an abstract type that's already defined -->
+
+  <sectiontype name="sample" implements="something">
+    <key name="data" datatype=".datatypes.data"/>
+  </sectiontype>
+
+</component>

Added: ZConfig/trunk/ZConfig/tests/zipsource/foo/sample/datatypes.py
===================================================================
--- ZConfig/trunk/ZConfig/tests/zipsource/foo/sample/datatypes.py	2005-11-08 16:31:24 UTC (rev 39981)
+++ ZConfig/trunk/ZConfig/tests/zipsource/foo/sample/datatypes.py	2005-11-08 16:33:53 UTC (rev 39982)
@@ -0,0 +1,7 @@
+"""Sample datatypes used for testing.
+"""
+__docformat__ = "reStructuredText"
+
+
+def data(value):
+    return "| %s |" % value


Property changes on: ZConfig/trunk/ZConfig/tests/zipsource/foo/sample/datatypes.py
___________________________________________________________________
Name: svn:mime-type
   + text/x-python
Name: svn:eol-style
   + native



More information about the ZConfig mailing list