SVN: zpkgtools/trunk/zpkg - remove the Dependencies/Includes/ directory from distributions

"Fred L. Drake, Jr." <[email protected]>
Newsgroups gmane.comp.web.zope.public-cvs
Message-ID <[email protected]>
Log message for revision 37846:
  - remove the Dependencies/Includes/ directory from distributions
  
  - remember what Python package provided a header, so we can build it
    out / install it in the right location
  
  - add a "build_headers" command that runs before "build_ext"; this
    makes the headers available in something more like the recommended
    structure, and runs as part of distutils.code.setup(), avoiding
    dependency on distribution construction artifacts
  
  - extend the "build" and "build_ext" commands so "build_headers" is
    run as needed
  
  - fix base directory computation for configuration loading in the case
    when no directory component is passed in
  

Changed:
  A   zpkgtools/trunk/zpkgsetup/build.py
  A   zpkgtools/trunk/zpkgsetup/build_ext.py
  A   zpkgtools/trunk/zpkgsetup/build_headers.py
  U   zpkgtools/trunk/zpkgsetup/dist.py
  U   zpkgtools/trunk/zpkgsetup/package.py
  U   zpkgtools/trunk/zpkgsetup/setup.py
  U   zpkgtools/trunk/zpkgtools/app.py
  U   zpkgtools/trunk/zpkgtools/config.py

-=-
Added: zpkgtools/trunk/zpkgsetup/build.py
===================================================================
--- zpkgtools/trunk/zpkgsetup/build.py	2005-08-10 18:20:20 UTC (rev 37845)
+++ zpkgtools/trunk/zpkgsetup/build.py	2005-08-10 18:30:46 UTC (rev 37846)
@@ -0,0 +1,35 @@
+"""Extended 'build' command that adds support for build_headers.
+
+"""
+__docformat__ = "reStructuredText"
+
+import distutils.command.build
+import os.path
+import sys
+
+
+class build(distutils.command.build.build):
+
+    user_options = distutils.command.build.build.user_options + [
+        ('build-headers=', None,
+         "build directory for headers"),
+        ]
+
+    def has_headers(self):
+        return self.distribution.has_headers()
+
+    # add build_headers before build_ext:
+    sub_commands = list(distutils.command.build.build.sub_commands)
+    for i in range(len(sub_commands)):
+        if sub_commands[i][0] == "build_ext":
+            sub_commands.insert(i, ("build_headers", has_headers))
+
+    def initialize_options(self):
+        distutils.command.build.build.initialize_options(self)
+        self.build_headers = None
+
+    def finalize_options(self):
+        distutils.command.build.build.finalize_options(self)
+        if self.build_headers is None:
+            self.build_headers = os.path.join(self.build_base,
+                                              "include-" + sys.version[0:3])


Property changes on: zpkgtools/trunk/zpkgsetup/build.py
___________________________________________________________________
Name: svn:mime-type
   + text/x-python
Name: svn:eol-style
   + native

Added: zpkgtools/trunk/zpkgsetup/build_ext.py
===================================================================
--- zpkgtools/trunk/zpkgsetup/build_ext.py	2005-08-10 18:20:20 UTC (rev 37845)
+++ zpkgtools/trunk/zpkgsetup/build_ext.py	2005-08-10 18:30:46 UTC (rev 37846)
@@ -0,0 +1,29 @@
+"""Extended build_ext command that adds support for 'built' headers.
+
+If there are any public headers for any of the packages included in
+this distribution, the build/include-X.Y/ directory is added to the
+include path of the extensions being built.  This also ensures that
+the build_headers command runs before the build_ext command.
+
+"""
+__docformat__ = "reStructuredText"
+
+import distutils.command.build_ext
+import os.path
+
+
+class build_ext(distutils.command.build_ext.build_ext):
+
+    def run(self):
+        cmd = self.get_finalized_command("build_headers")
+        if cmd.package_headers:
+            self.run_command("build_headers")
+            self._extra_includes = cmd.build_dir
+        else:
+            self._extra_includes = None
+        distutils.command.build_ext.build_ext.run(self)
+
+    def build_extension(self, ext):
+        if self._extra_includes:
+            ext.include_dirs.append(self._extra_includes)
+        distutils.command.build_ext.build_ext.build_extension(self, ext)


Property changes on: zpkgtools/trunk/zpkgsetup/build_ext.py
___________________________________________________________________
Name: svn:mime-type
   + text/x-python
Name: svn:eol-style
   + native

Added: zpkgtools/trunk/zpkgsetup/build_headers.py
===================================================================
--- zpkgtools/trunk/zpkgsetup/build_headers.py	2005-08-10 18:20:20 UTC (rev 37845)
+++ zpkgtools/trunk/zpkgsetup/build_headers.py	2005-08-10 18:30:46 UTC (rev 37846)
@@ -0,0 +1,53 @@
+"""
+"""
+__docformat__ = "reStructuredText"
+
+import distutils.core
+import distutils.util
+import os.path
+
+
+class build_headers(distutils.core.Command):
+    """Command that builds out the headers into build/headers-X.Y/.
+
+    The structure of the build/headers-X.Y/ directory is analogous to
+    that of the $exec_prefix/include/pythonX.Y/ directory: each
+    package gets a corresponding directory to which its public headers
+    are copied.  When the extension modules are built, this directory
+    will be added to the include search path before that containing
+    the Python headers.
+
+    """
+
+    description = "build out the public headers"
+
+    user_options = [
+        ('build-dir=', 'd', "directory to \"build\" (copy) to"),
+        ('force', 'f', "forcibly build everything (ignore file timestamps"),
+        ]
+
+    boolean_options = ['force']
+
+    def initialize_options (self):
+        self.build_dir = None
+        self.force = None
+        self.package_headers = None
+        self.outfiles = []
+
+    def finalize_options (self):
+        self.set_undefined_options('build',
+                                   ('build_headers', 'build_dir'),
+                                   ('force', 'force'))
+        self.package_headers = self.distribution.package_headers
+
+    def run(self):
+        if not self.package_headers:
+            return
+        for header in self.package_headers:
+            dir = os.path.join(self.build_dir, header.package)
+            self.mkpath(dir)
+            srcfile = distutils.util.convert_path(header.path)
+            outfile = os.path.join(
+                self.build_dir, header.package, os.path.basename(srcfile))
+            self.copy_file(srcfile, outfile)
+            self.outfiles.append(outfile)


Property changes on: zpkgtools/trunk/zpkgsetup/build_headers.py
___________________________________________________________________
Name: svn:mime-type
   + text/x-python
Name: svn:eol-style
   + native

Modified: zpkgtools/trunk/zpkgsetup/dist.py
===================================================================
--- zpkgtools/trunk/zpkgsetup/dist.py	2005-08-10 18:20:20 UTC (rev 37845)
+++ zpkgtools/trunk/zpkgsetup/dist.py	2005-08-10 18:30:46 UTC (rev 37846)
@@ -19,7 +19,11 @@
 import distutils.extension
 import sys
 
+import zpkgsetup.build
+import zpkgsetup.build_ext
+import zpkgsetup.build_headers
 
+
 class ZPkgExtension(distutils.extension.Extension):
     """Distutils representation of a compiled extension module."""
 
@@ -29,9 +33,16 @@
 
     def __init__ (self, attrs=None):
         self.package_data = None
+        self.package_headers = attrs.pop("package_headers", ())
         distutils.dist.Distribution.__init__(self, attrs)
         if self.package_data and sys.version_info < (2, 4):
             from zpkgsetup.build_py import build_py
             from zpkgsetup.install_lib import install_lib
             self.cmdclass.setdefault('build_py', build_py)
             self.cmdclass.setdefault('install_lib', install_lib)
+        self.cmdclass.setdefault('build',
+                                 zpkgsetup.build.build)
+        self.cmdclass.setdefault('build_ext',
+                                 zpkgsetup.build_ext.build_ext)
+        self.cmdclass.setdefault('build_headers',
+                                 zpkgsetup.build_headers.build_headers)

Modified: zpkgtools/trunk/zpkgsetup/package.py
===================================================================
--- zpkgtools/trunk/zpkgsetup/package.py	2005-08-10 18:20:20 UTC (rev 37845)
+++ zpkgtools/trunk/zpkgsetup/package.py	2005-08-10 18:30:46 UTC (rev 37846)
@@ -75,6 +75,17 @@
 PACKAGE_CONF = "SETUP.cfg"
 
 
+class Header(object):
+    """Information about a header file and the package that provides it."""
+
+    def __init__(self, package, path):
+        self.package = package
+        self.path = path
+
+    def __repr__(self):
+        return "<Header(%r, %r)>" % (self.package, self.path)
+
+
 def loadPackageInfo(pkgname, directory, reldir):
     """Load package information for a Python package.
 
@@ -93,6 +104,8 @@
     pkginfo = read_package_info(directory, reldir)
     pkginfo.extensions = [create_extension(ext, pkgname, reldir)
                           for ext in pkginfo.extension]
+    pkginfo.package_headers = [Header(pkgname, path)
+                               for path in pkginfo.header]
     return pkginfo
 
 
@@ -112,6 +125,8 @@
     if pkginfo.extension:
         raise ValueError("extensions cannot be defined in collections")
     pkginfo.extensions = []
+    pkginfo.package_headers = [Header(pkgname, path)
+                               for path in pkginfo.header]
     return pkginfo
 
 

Modified: zpkgtools/trunk/zpkgsetup/setup.py
===================================================================
--- zpkgtools/trunk/zpkgsetup/setup.py	2005-08-10 18:20:20 UTC (rev 37845)
+++ zpkgtools/trunk/zpkgsetup/setup.py	2005-08-10 18:30:46 UTC (rev 37846)
@@ -66,6 +66,7 @@
         self.packages = []
         self.package_data = {}
         self.package_dir = {}
+        self.package_headers = []
         self.ext_modules = []
         self.scripts = []
         self.platforms = None
@@ -85,7 +86,7 @@
             depnames = os.listdir(depsdir)
             suffix = "-%s-%s" % (self._pkgname, self.version)
             for name in depnames:
-                if name != "Includes" and not name.endswith(suffix):
+                if not name.endswith(suffix):
                     # an unexpected name; we didn't put this here!
                     print >>sys.stderr, \
                           "unexpected name in Dependencies/: %r" % name
@@ -100,10 +101,6 @@
                 pkgdir = os.path.join(depdir, depname)
                 reldir = posixpath.join("Dependencies", name, depname)
                 self.scan(depname, pkgdir, reldir)
-            includes_dir = os.path.join(depsdir, "Includes")
-            if os.path.isdir(includes_dir):
-                for ext in self.ext_modules:
-                    ext.include_dirs.append(includes_dir)
 
     def setup(self):
         kwargs = self.__dict__.copy()
@@ -223,6 +220,7 @@
                 self.add_package_file(pkgname, posixpath.join(reldir, fn))
 
     def scan_basic(self, pkginfo):
+        self.package_headers.extend(pkginfo.package_headers)
         self.scripts.extend(pkginfo.script)
         if pkginfo.data_files:
             if self.data_files:

Modified: zpkgtools/trunk/zpkgtools/app.py
===================================================================
--- zpkgtools/trunk/zpkgtools/app.py	2005-08-10 18:20:20 UTC (rev 37845)
+++ zpkgtools/trunk/zpkgtools/app.py	2005-08-10 18:30:46 UTC (rev 37846)
@@ -173,7 +173,6 @@
                 component.write_setup_py(pathparts=["..", ".."],
                                          distclass=distclass)
                 component.write_setup_cfg()
-                self.add_headers(component)
         if self.options.application:
             top.write_setup_py(filename="install.py",
                                version=self.options.version,
@@ -190,22 +189,6 @@
         except zpkgtools.Error, e:
             self.error(str(e), rc=1)
 
-    def add_headers(self, component):
-        pkginfo = component.get_package_info()
-        if not pkginfo.header:
-            return
-        includes_dir = os.path.join(self.destination,
-                                    "Dependencies", "Includes")
-        if not os.path.isdir(includes_dir):
-            os.mkdir(includes_dir)
-        for src in pkginfo.header:
-            src = os.path.join(component.destination, *src.split("/"))
-            name = os.path.basename(src)
-            path = os.path.join(includes_dir, name)
-            if os.path.exists(path):
-                self.error("multiple headers with name %r" % name)
-            self.ip.copy_file(src, path)
-
     def add_manifest(self, destination):
         self.ip.add_manifest(destination)
         self.ip.add_output(os.path.join(destination, "MANIFEST"))

Modified: zpkgtools/trunk/zpkgtools/config.py
===================================================================
--- zpkgtools/trunk/zpkgtools/config.py	2005-08-10 18:20:20 UTC (rev 37845)
+++ zpkgtools/trunk/zpkgtools/config.py	2005-08-10 18:30:46 UTC (rev 37846)
@@ -140,9 +140,14 @@
             paths found in the configuration file.
 
         """
-        p = cfgparser.Parser(f, path, Schema(path, self.locations))
+        if basedir:
+            basedir = os.path.abspath(basedir)
+        else:
+            basedir = os.getcwd()
+        p = cfgparser.Parser(f, path, Schema(os.path.abspath(path),
+                                             self.locations))
         cf = p.load()
-        base = urlutils.file_url(os.path.abspath(basedir)) + "/"
+        base = urlutils.file_url(basedir) + "/"
         for value in cf.resource_map:
             value = urlparse.urljoin(base, value)
             self.location_maps.append(value)

_______________________________________________
Zope-CVS maillist  -  [email protected]
http://mail.zope.org/mailman/listinfo/zope-cvs

Zope CVS instructions: http://dev.zope.org/CVS
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.