Philip, I've now modified the latest setuptools (0.6c5) so that the egg_info
command respects package_data and exclude_package_data when creating its
sources manifest (and thus influencing sdist's choice of files). Does this
sound like the right approach to you (I figured sdist should base its choice
of files on egg_info)?

I've encountered one problem so far, which is that if data files are both
listed in *.egg-info/SOURCES.txt and exclude_package_data they are not
excluded. This may happen if files are added to the exclude list after a
.egg-info is already generated. I'm not familiar enough with setuptools'
design to know how to best solve this.

Please let me know what you think.

Best,
Arve

On 2/3/07, Arve Knudsen <[EMAIL PROTECTED]> wrote:

On Sat, 03 Feb 2007 17:03:27 +0100, Phillip J. Eby <[EMAIL PROTECTED]>
wrote:

> At 12:48 PM 2/3/2007 +0100, Arve Knudsen wrote:
>> Funny, I seem to recall having raised the same issue, but not receiving
>> much in way of an answer. Glad to see it's being taken care of at
least.
>
> Um, it's not being "taken care of".  As I said, "a patch would go a long
> way towards getting it in."  That means it's probably *not* being taken
> care of any time soon, unless somebody submits one.

I interpreted you as having recognized the problem, but that it would not
make it into 0.6.  As long as it can be scheduled for a future version I
can try my hand at contributing a patch (unless someone else wants to).

Arve
_______________________________________________
Distutils-SIG maillist  -  Distutils-SIG@python.org
http://mail.python.org/mailman/listinfo/distutils-sig

diff -ru setuptools-0.6c5/setuptools/command/egg_info.py setuptools-0.6c5_mod/setuptools/command/egg_info.py
--- setuptools-0.6c5/setuptools/command/egg_info.py	2006-10-31 18:20:42.000000000 +0100
+++ setuptools-0.6c5_mod/setuptools/command/egg_info.py	2007-02-10 19:23:52.000000000 +0100
@@ -3,7 +3,8 @@
 Create a distribution's .egg-info directory and contents"""
 
 # This module should be kept compatible with Python 2.3
-import os, re
+import os, re, fnmatch
+from glob import glob
 from setuptools import Command
 from distutils.errors import *
 from distutils import log
@@ -299,6 +300,10 @@
         pass
 
     def run(self):
+        self.packages = self.distribution.packages
+        self.package_data = self.distribution.package_data
+        self.exclude_package_data = self.distribution.exclude_package_data or {}
+
         self.filelist = FileList()
         if not os.path.exists(self.manifest):
             self.write_manifest()   # it must exist so it'll get in the list
@@ -306,11 +311,75 @@
         self.add_defaults()
         if os.path.exists(self.template):
             self.read_template()
+        self._add_data_files()
+
         self.prune_file_list()
         self.filelist.sort()
         self.filelist.remove_duplicates()
         self.write_manifest()
 
+    def _add_data_files(self):
+        buildPy = self.get_finalized_command("build_py")
+        for package in buildPy.packages or ():
+            # Locate package source directory
+            src_dir = buildPy.get_package_dir(package)
+
+            # Length of path to strip from found files
+            plen = len(src_dir)+1
+
+            # Strip directory from globbed filenames
+            for f in self._find_data_files(package, src_dir, buildPy):
+                if not f in self.filelist.files:
+                    self.filelist.append(f)
+
+    def _find_data_files(self, package, src_dir, buildPy):
+        """Return filenames for package's data files in 'src_dir'"""
+        mf = {}
+        if self.distribution.include_package_data:
+            src_dirs = {}
+            for package in buildPy.packages or ():
+                # Locate package source directory
+                src_dirs[assert_relative(buildPy.get_package_dir(package))] = package
+
+            for path in self.filelist.files:
+                d,f = os.path.split(assert_relative(path))
+                prev = None
+                oldf = f
+                while d and d!=prev and d not in src_dirs:
+                    prev = d
+                    d, df = os.path.split(d)
+                    f = os.path.join(df, f)
+                if d in src_dirs:
+                    if path.endswith('.py') and f==oldf:
+                        continue    # it's a module, not data
+                    mf.setdefault(src_dirs[d],[]).append(path)
+
+        globs = (self.package_data.get('', [])
+                 + self.package_data.get(package, []))
+        files = mf.get(package, [])[:]
+        for pattern in globs:
+            # Each pattern has to be converted to a platform-specific path
+            files.extend(glob(os.path.join(src_dir, convert_path(pattern))))
+        return self._exclude_data_files(package, src_dir, files)
+
+    def _exclude_data_files(self, package, src_dir, files):
+        """Filter filenames for package's data files in 'src_dir'"""
+        globs = (self.exclude_package_data.get('', [])
+                 + self.exclude_package_data.get(package, []))
+        bad = []
+        for pattern in globs:
+            bad.extend(
+                fnmatch.filter(
+                    files, os.path.join(src_dir, convert_path(pattern))
+                )
+            )
+        bad = dict.fromkeys(bad)
+        seen = {}
+        return [
+            f for f in files if f not in bad
+                and f not in seen and seen.setdefault(f,1)  # ditch dupes
+        ]
+
     def write_manifest (self):
         """Write the file list in 'self.filelist' (presumably as filled in
         by 'add_defaults()' and 'read_template()') to the manifest file
_______________________________________________
Distutils-SIG maillist  -  Distutils-SIG@python.org
http://mail.python.org/mailman/listinfo/distutils-sig

Reply via email to