[zpkg] SVN: zpkgtools/trunk/ Merge philikon-toplevel-modules branch.

Philipp von Weitershausen philikon at philikon.de
Tue Nov 29 11:12:14 EST 2005


Log message for revision 40410:
  Merge philikon-toplevel-modules branch.
  

Changed:
  U   zpkgtools/trunk/test.py
  U   zpkgtools/trunk/zpkgsetup/loggingapi.py
  A   zpkgtools/trunk/zpkgsetup/module.xml
  U   zpkgtools/trunk/zpkgsetup/package.py
  U   zpkgtools/trunk/zpkgsetup/setup.py
  A   zpkgtools/trunk/zpkgsetup/tests/input2/
  U   zpkgtools/trunk/zpkgsetup/tests/test_publication.py
  U   zpkgtools/trunk/zpkgsetup/tests/test_setup.py
  U   zpkgtools/trunk/zpkgtools/app.py
  U   zpkgtools/trunk/zpkgtools/tests/input/README.txt
  U   zpkgtools/trunk/zpkgtools/tests/input/collection-1/DEPENDENCIES.cfg
  A   zpkgtools/trunk/zpkgtools/tests/input/module.conf
  A   zpkgtools/trunk/zpkgtools/tests/input/module.py
  U   zpkgtools/trunk/zpkgtools/tests/input/packages.map
  U   zpkgtools/trunk/zpkgtools/tests/test_app.py

-=-
Modified: zpkgtools/trunk/test.py
===================================================================
--- zpkgtools/trunk/test.py	2005-11-29 15:43:35 UTC (rev 40409)
+++ zpkgtools/trunk/test.py	2005-11-29 16:12:14 UTC (rev 40410)
@@ -14,18 +14,18 @@
 ##############################################################################
 """Convenience test script for Jim.
 
-$Id: test.py,v 1.1 2004/06/11 02:15:49 fdrake Exp $
+$Id$
 """
 import os.path
 import sys
 
 try:
-    from zope.app.testing.test import process_args
+    from zope.testing import testrunner
 except ImportError:
     if sys.argv[1:]:
         # We got args, but we're not about to support them here.
         print >>sys.stderr, \
-              "arguments only supported when zope.app.tests is available"
+              "arguments only supported when zope.testing is available"
         sys.exit(2)
 
     def test_suite():
@@ -41,5 +41,5 @@
     # 1. search for tests in starting in this directory
     # 2. there are only unit tests, not functional tests
     here = os.path.dirname(os.path.realpath(__file__))
-    sys.argv[1:1] = ["-l", here, "-u"]
-    process_args()
+    defaults = ['--tests-pattern', '^tests$', "--test-path", here, '-v']
+    result = testrunner.run(defaults)

Modified: zpkgtools/trunk/zpkgsetup/loggingapi.py
===================================================================
--- zpkgtools/trunk/zpkgsetup/loggingapi.py	2005-11-29 15:43:35 UTC (rev 40409)
+++ zpkgtools/trunk/zpkgsetup/loggingapi.py	2005-11-29 16:12:14 UTC (rev 40410)
@@ -19,7 +19,7 @@
 
 This isn't sufficient to support building packages with Python 2.2.
 
-$Id: loggingapi.py,v 1.1 2004/06/11 19:24:35 fdrake Exp $
+$Id$
 """
 
 try:

Copied: zpkgtools/trunk/zpkgsetup/module.xml (from rev 40409, zpkgtools/branches/philikon-toplevel-modules/zpkgsetup/module.xml)

Modified: zpkgtools/trunk/zpkgsetup/package.py
===================================================================
--- zpkgtools/trunk/zpkgsetup/package.py	2005-11-29 15:43:35 UTC (rev 40409)
+++ zpkgtools/trunk/zpkgsetup/package.py	2005-11-29 16:12:14 UTC (rev 40410)
@@ -67,6 +67,7 @@
 
 
 PACKAGE_CONF = "SETUP.cfg"
+MODULE_CONF = "MODULE.cfg"
 
 get_schema = cfgparser.cachedSchemaLoader("package.xml")
 
@@ -124,6 +125,14 @@
                                for path in pkginfo.header]
     return pkginfo
 
+def read_module_info(directory):
+    module_schema = cfgparser.cachedSchemaLoader("module.xml")
+    module_cfg = os.path.join(directory, MODULE_CONF)
+    f = file(module_cfg)
+    url = urlutils.file_url(urllib.pathname2url(module_cfg))
+    pkginfo, _ = cfgparser.loadConfigFile(module_schema(), f, url)
+    f.close()
+    return pkginfo
 
 def read_package_info(directory, reldir=None):
     """Read the package information file from a specified directory.

Modified: zpkgtools/trunk/zpkgsetup/setup.py
===================================================================
--- zpkgtools/trunk/zpkgsetup/setup.py	2005-11-29 15:43:35 UTC (rev 40409)
+++ zpkgtools/trunk/zpkgsetup/setup.py	2005-11-29 16:12:14 UTC (rev 40410)
@@ -67,6 +67,7 @@
         self.package_data = {}
         self.package_dir = {}
         self.package_headers = []
+        self.py_modules = []
         self.ext_modules = []
         self.scripts = []
         self.platforms = None
@@ -82,6 +83,10 @@
         pkgdir = os.path.join(self._working_dir, self._pkgname)
         self.scan(self._pkgname, pkgdir, self._pkgname)
         depsdir = os.path.join(self._working_dir, "Dependencies")
+        modsdir = os.path.join(self._working_dir, "Modules")
+        if os.path.isdir(modsdir):
+            # we do the following so that top-level modules can be installed
+            self.package_dir[""] = 'Modules'
         if os.path.isdir(depsdir):
             depnames = os.listdir(depsdir)
             suffix = "-%s-%s" % (self._pkgname, self.version)
@@ -97,9 +102,22 @@
                     print >>sys.stderr, \
                           "unexpected file in Dependencies/: %r" % name
                     continue
+
                 depname = name[:-len(suffix)]
+                reldir = posixpath.join("Dependencies", name, depname)
                 pkgdir = os.path.join(depdir, depname)
-                reldir = posixpath.join("Dependencies", name, depname)
+
+                # quick hack to see if we're dealing with a top-level
+                # module or not. If we are, slightly adjust the
+                # dependency name etc. according to the value supplied
+                # in SETUP.cfg.
+                if os.path.exists(os.path.join(depdir, package.MODULE_CONF)):
+                    pkginfo = package.read_module_info(depdir)
+                    if pkginfo.module:
+                        depname = pkginfo.module[:-3]
+                        reldir = "Modules"
+                        pkgdir = os.path.join(modsdir, depname)
+
                 self.scan(depname, pkgdir, reldir)
 
     def setup(self):
@@ -163,7 +181,6 @@
         #
         parts = root.split("/")
         local_root = os.path.join(*parts)
-        self.package_dir[""] = root
         if os.path.isfile(os.path.join(local_root, package.PACKAGE_CONF)):
             # There's a SETUP.cfg at the top level; load it:
             pkginfo = package.loadCollectionInfo(
@@ -186,12 +203,18 @@
                 self.scan_package(pkgname, local_full_path, relative_path)
 
     def scan(self, name, directory, reldir):
+        module_py = directory + '.py'
         init_py = os.path.join(directory, "__init__.py")
-        if os.path.isfile(init_py):
+        if os.path.isfile(module_py):
+            self.scan_module(name, module_py, reldir)
+        elif os.path.isfile(init_py):
             self.scan_package(name, directory, reldir)
         else:
             self.scan_collection(name, directory, reldir)
 
+    def scan_module(self, name, filename, reldir):
+        self.py_modules.append(name)
+
     def scan_collection(self, name, directory, reldir):
         # load the collection metadata
         pkginfo = package.loadCollectionInfo(directory, reldir)

Copied: zpkgtools/trunk/zpkgsetup/tests/input2 (from rev 40409, zpkgtools/branches/philikon-toplevel-modules/zpkgsetup/tests/input2)

Modified: zpkgtools/trunk/zpkgsetup/tests/test_publication.py
===================================================================
--- zpkgtools/trunk/zpkgsetup/tests/test_publication.py	2005-11-29 15:43:35 UTC (rev 40409)
+++ zpkgtools/trunk/zpkgsetup/tests/test_publication.py	2005-11-29 16:12:14 UTC (rev 40410)
@@ -13,7 +13,7 @@
 ##############################################################################
 """Tests for zpkgtools.publication
 
-$Id: test_publication.py,v 1.1 2004/06/14 20:46:41 fdrake Exp $
+$Id$
 """
 import unittest
 

Modified: zpkgtools/trunk/zpkgsetup/tests/test_setup.py
===================================================================
--- zpkgtools/trunk/zpkgsetup/tests/test_setup.py	2005-11-29 15:43:35 UTC (rev 40409)
+++ zpkgtools/trunk/zpkgsetup/tests/test_setup.py	2005-11-29 16:12:14 UTC (rev 40410)
@@ -69,8 +69,17 @@
         #
         #context.packages.sort()
         #self.assertEqual(context.packages, ["package", "package2"])
-        
 
+    def test_modules(self):
+        input2 = os.path.join(os.path.dirname(__file__), "input2")
+        context = setup.SetupContext("collection", "0.0.0",
+                                     os.path.join(input2, "setup.py"))
+        context.initialize()
+        self.assertEqual(context.py_modules, ['module'])
+        self.assertEqual(context.package_dir[''], 'Modules')
 
 def test_suite():
     return unittest.makeSuite(SetupContextTestCase)
+
+if __name__ == '__main__':
+    unittest.main(defaultTest='test_suite')

Modified: zpkgtools/trunk/zpkgtools/app.py
===================================================================
--- zpkgtools/trunk/zpkgtools/app.py	2005-11-29 15:43:35 UTC (rev 40409)
+++ zpkgtools/trunk/zpkgtools/app.py	2005-11-29 16:12:14 UTC (rev 40410)
@@ -211,7 +211,11 @@
 
     def get_component(self, resource, location):
         try:
-            return Component(resource, location, self.ip)
+            source = self.ip.loader.load(location)
+            if os.path.isfile(source):
+                return ModuleComponent(resource, location, source, self.ip)
+            else:
+                return PackageComponent(resource, location, source, self.ip)
         except zpkgtools.Error, e:
             self.error(str(e), rc=1)
 
@@ -384,8 +388,11 @@
             raise
 
 
-class Component:
-    def __init__(self, name, url, ip):
+class PackageComponent:
+    """Regular Python package or non-code component.
+    """
+
+    def __init__(self, name, url, source, ip):
         self.name = name
         self.url = url
         self.ip = ip
@@ -393,7 +400,7 @@
         self.destination = None
         self.pkginfo = None
         self.pubinfo = None
-        self.source = self.ip.loader.load(self.url)
+        self.source = source
         specs = include.load(self.source)
         if specs.loads:
             source = self.ip.loader.load_mutable_copy(self.url)
@@ -465,7 +472,7 @@
         return self.pubinfo
 
     def is_python_package(self):
-        """Return True iff this component represents a Python package."""
+        """Return True if this component represents a Python package."""
         if self.destination:
             dir = os.path.join(self.destination, self.name)
         else:
@@ -473,7 +480,7 @@
         return os.path.isfile(os.path.join(dir, "__init__.py"))
 
     def has_packaging_data(self):
-        """Return True iff this component contains packaging metadata."""
+        """Return True if this component contains packaging metadata."""
         # Should PUBLICATION.cfg count toword this?
         dir = self.source
         for fn in (package.PACKAGE_CONF,
@@ -544,6 +551,93 @@
         f.close()
 
 
+class ModuleComponent:
+    """Component representing a top-level module
+    """
+
+    def __init__(self, name, url, source, ip):
+        self.name = name
+        self.url = url
+        self.ip = ip
+        self.dependencies = None
+        self.destination = None
+        self.pkginfo = None
+        self.pubinfo = None
+        self.source = source
+        self.filename = os.path.basename(source)
+        specs = include.load(self.source)
+        specs.collection.cook()
+        specs.distribution.cook()
+        self.collection = specs.collection
+        self.distribution = specs.distribution
+        #
+        # Check that this package is valid:
+        #
+        if not self.is_python_package():
+            raise zpkgtools.Error(
+                "%r is an invalid distribution component: all components must"
+                " either be a Python package or provide a %s file"
+                % (name, package.PACKAGE_CONF))
+
+    def get_dependencies(self):
+        """Get the direct dependencies of this component.
+
+        :return: A set of the dependencies.
+        :rtype: `sets.Set`
+
+        We simply rule that top-level modules have no dependencies.
+        At least we have no way of knowing.
+        """
+        self.dependencies = sets.Set()
+        return self.dependencies
+
+    def get_package_info(self):
+        return self.pkginfo
+
+    def get_publication_info(self):
+        return self.pubinfo
+
+    def is_python_package(self):
+        """Return True if this component represents a Python package."""
+        if self.destination:
+            filename = os.path.join(self.destination, self.filename)
+        else:
+            filename = self.source
+        return os.path.isfile(filename)
+
+    def has_packaging_data(self):
+        """Return True if this component contains packaging metadata.
+
+        For top-level modules, we simply rule that the have no
+        packaging metadata. They just want to be installed, basta."""
+        return False
+
+    def write_package(self, destination):
+        self.destination = destination
+        if not os.path.exists(destination):
+            os.mkdir(destination)
+        self.ip.addIncludes(destination, self.distribution)
+        self.write_module_cfg()
+        module_dest = os.path.join(destination, '..', '..', 'Modules')
+        if not os.path.exists(module_dest):
+            os.mkdir(module_dest)
+        self.ip.copy_file(self.source, module_dest)
+
+    def write_module_cfg(self):
+        module_cfg = os.path.join(self.destination, 'MODULE.cfg')
+        self.ip.add_output(module_cfg)
+        f = file(module_cfg, 'w')
+        print >>f, "module %s" % self.filename
+        f.close()
+
+    def write_setup_cfg(self):
+        pass
+
+    def write_setup_py(self, filename="setup.py", version=None, pathparts=[],
+                       distclass=None):
+        pass
+
+
 SETUP_HEADER = """\
 #! /usr/bin/env python
 #

Modified: zpkgtools/trunk/zpkgtools/tests/input/README.txt
===================================================================
--- zpkgtools/trunk/zpkgtools/tests/input/README.txt	2005-11-29 15:43:35 UTC (rev 40409)
+++ zpkgtools/trunk/zpkgtools/tests/input/README.txt	2005-11-29 16:12:14 UTC (rev 40410)
@@ -4,8 +4,9 @@
 
 This directory contains a bunch of sample input trees to use with zpkg
 and the tests.  This is not a package itself, though it contains
-(top-level) packages (as well as non-package directories).  The sample
-resources are quite minimal; they don't represent *useful* resources.
+(top-level) packages and modules (as well as non-package directories).
+The sample resources are quite minimal; they don't represent *useful*
+resources.
 
 Making this directory not be a package itself allows zpkg to actually
 be able to package itself without losing test data.

Modified: zpkgtools/trunk/zpkgtools/tests/input/collection-1/DEPENDENCIES.cfg
===================================================================
--- zpkgtools/trunk/zpkgtools/tests/input/collection-1/DEPENDENCIES.cfg	2005-11-29 15:43:35 UTC (rev 40409)
+++ zpkgtools/trunk/zpkgtools/tests/input/collection-1/DEPENDENCIES.cfg	2005-11-29 16:12:14 UTC (rev 40410)
@@ -1,2 +1,3 @@
 package
+module
 collection:collection-2

Copied: zpkgtools/trunk/zpkgtools/tests/input/module.conf (from rev 40409, zpkgtools/branches/philikon-toplevel-modules/zpkgtools/tests/input/module.conf)

Copied: zpkgtools/trunk/zpkgtools/tests/input/module.py (from rev 40409, zpkgtools/branches/philikon-toplevel-modules/zpkgtools/tests/input/module.py)

Modified: zpkgtools/trunk/zpkgtools/tests/input/packages.map
===================================================================
--- zpkgtools/trunk/zpkgtools/tests/input/packages.map	2005-11-29 15:43:35 UTC (rev 40409)
+++ zpkgtools/trunk/zpkgtools/tests/input/packages.map	2005-11-29 16:12:14 UTC (rev 40410)
@@ -4,3 +4,4 @@
 collection-2  collection-2/
 
 package       package/
+module        module.py
\ No newline at end of file

Modified: zpkgtools/trunk/zpkgtools/tests/test_app.py
===================================================================
--- zpkgtools/trunk/zpkgtools/tests/test_app.py	2005-11-29 15:43:35 UTC (rev 40409)
+++ zpkgtools/trunk/zpkgtools/tests/test_app.py	2005-11-29 16:12:14 UTC (rev 40410)
@@ -18,6 +18,7 @@
 import sys
 import unittest
 import urllib
+import re
 
 from StringIO import StringIO
 
@@ -291,7 +292,7 @@
             sys.stderr = old_stderr
 
 
-class ComponentTestCase(unittest.TestCase):
+class PackageComponentTestCase(unittest.TestCase):
 
     def setUp(self):
         self.tmpdir = tempfile.mkdtemp(prefix="test-app-")
@@ -309,25 +310,30 @@
     def test_validation_of_package_without_setup_cfg(self):
         self.write_app_file("__init__.py", "# make this a package\n")
         #
-        c = app.Component("mypkg", self.mypkg_url, self.ip)
+        source = self.ip.loader.load(self.mypkg_url)
+        c = app.PackageComponent("mypkg", self.mypkg_url, source, self.ip)
         self.assert_(c.is_python_package())
 
     def test_validation_of_package_with_setup_cfg(self):
         self.write_app_file("SETUP.cfg", "# this is a simple package\n")
         self.write_app_file("__init__.py", "# make this a package\n")
         #
-        c = app.Component("mypkg", self.mypkg_url, self.ip)
+        source = self.ip.loader.load(self.mypkg_url)
+        c = app.PackageComponent("mypkg", self.mypkg_url, source, self.ip)
         self.assert_(c.is_python_package())
 
     def test_validation_of_nonpackage_with_setup_cfg(self):
         self.write_app_file("SETUP.cfg", "# this is a simple package\n")
         #
-        c = app.Component("mypkg", self.mypkg_url, self.ip)
+        source = self.ip.loader.load(self.mypkg_url)
+        c = app.PackageComponent("mypkg", self.mypkg_url, source, self.ip)
         self.assert_(not c.is_python_package())
 
     def test_non_validation_of_nonpackage_without_setup_cfg(self):
+        source = self.ip.loader.load(self.mypkg_url)
         self.assertRaises(zpkgtools.Error,
-                          app.Component, "mypkg", self.mypkg_url, self.ip)
+                          app.PackageComponent,
+                          "mypkg", self.mypkg_url, source, self.ip)
 
     def test_component_metadata_is_copied_by_default(self):
         self.write_app_file(publication.PUBLICATION_CONF,
@@ -338,7 +344,8 @@
         self.write_app_file(package.PACKAGE_CONF,
                             "# nothing to specify\n")
         #
-        c = app.Component("mypkg", self.mypkg_url, self.ip)
+        source = self.ip.loader.load(self.mypkg_url)
+        c = app.PackageComponent("mypkg", self.mypkg_url, source, self.ip)
         dest = tempfile.mkdtemp(prefix="test-app-dest-")
         try:
             c.write_package(dest)
@@ -367,7 +374,8 @@
         self.write_app_file("README",
                             "some text\n")
         #
-        c = app.Component("mypkg", self.mypkg_url, self.ip)
+        source = self.ip.loader.load(self.mypkg_url)
+        c = app.PackageComponent("mypkg", self.mypkg_url, source, self.ip)
         dest = tempfile.mkdtemp(prefix="test-app-dest-")
         try:
             c.write_package(dest)
@@ -644,7 +652,35 @@
         finally:
             os.chdir(orig_pwd)
 
+    def test_toplevel_module_as_a_dependency(self):
+        # Test that a top-level module which is loaded as a dependency
+        # (we don't really support top-level modules as the primary
+        # collection) is properly set up.
+        config = os.path.join(os.path.dirname(os.path.abspath(__file__)),
+                              "input", "module.conf")
+        package_map = self.createPackageMap()
+        app = self.createApplication(
+            ["-C", config, "-t", "-m", package_map])
+        app.run()
 
+        # test that the module file is copied to the right location
+        modules_dir = os.path.join(app.destination, "Modules")
+        self.assert_(os.path.exists(modules_dir))
+        module_py = os.path.join(app.destination, "Modules", 'module.py')
+        self.assert_(os.path.exists(module_py))
+        orig_module_py = os.path.join(os.path.dirname(__file__), "input",
+                                      "module.py")
+        self.assertEqual(file(module_py).read(), file(orig_module_py).read())
+
+        # test that MODULE.cfg exists and points to the module file
+        depdir = os.path.join(app.destination, "Dependencies",
+                              "module-collection-1-0.0.0")
+        self.assert_(os.path.exists(depdir))
+        module_cfg = os.path.join(depdir, "MODULE.cfg")
+        self.assert_(os.path.exists(module_cfg))
+        self.assert_(re.match(r"module(\s+)module.py", file(module_cfg).read()))
+        shutil.rmtree(app.destination)
+
 class DelayedCleanupBuilderApplication(app.BuilderApplication):
 
     def cleanup(self):
@@ -669,7 +705,7 @@
 
 def test_suite():
     suite = unittest.makeSuite(CommandLineTestCase)
-    suite.addTest(unittest.makeSuite(ComponentTestCase))
+    suite.addTest(unittest.makeSuite(PackageComponentTestCase))
     suite.addTest(unittest.makeSuite(BuilderApplicationTestCase))
     return suite
 



More information about the zpkg mailing list