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