Commit 4cd66c41 authored by PJ Eby's avatar PJ Eby

Added the ``include_package_data`` keyword to ``setup()``, allowing you to

automatically include any package data listed in revision control or
``MANIFEST.in``.  Now projects can manage their data files and source
manifests without having to maintain two ways to express the same file
list.  Yay!

--HG--
branch : setuptools
extra : convert_revision : svn%3A6015fed2-1504-0410-9fe1-9d1591cc4771/sandbox/trunk/setuptools%4041473
parent f3694a03
...@@ -36,7 +36,7 @@ setup( ...@@ -36,7 +36,7 @@ setup(
url = "http://peak.telecommunity.com/DevCenter/setuptools", url = "http://peak.telecommunity.com/DevCenter/setuptools",
test_suite = 'setuptools.tests.test_suite', test_suite = 'setuptools.tests.test_suite',
packages = find_packages(), packages = find_packages(),
package_data = {'setuptools': ['*.exe']}, include_package_data = True,
py_modules = ['pkg_resources', 'easy_install', 'site'], py_modules = ['pkg_resources', 'easy_install', 'site'],
zip_safe = False, # We want 'python -m easy_install' to work, for now :( zip_safe = False, # We want 'python -m easy_install' to work, for now :(
...@@ -53,6 +53,7 @@ setup( ...@@ -53,6 +53,7 @@ setup(
"entry_points = setuptools.dist:check_entry_points", "entry_points = setuptools.dist:check_entry_points",
"test_suite = setuptools.dist:check_test_suite", "test_suite = setuptools.dist:check_test_suite",
"zip_safe = setuptools.dist:assert_bool", "zip_safe = setuptools.dist:assert_bool",
"include_package_data = setuptools.dist:assert_bool",
], ],
"egg_info.writers": [ "egg_info.writers": [
"PKG-INFO = setuptools.command.egg_info:write_pkg_info", "PKG-INFO = setuptools.command.egg_info:write_pkg_info",
...@@ -66,7 +67,6 @@ setup( ...@@ -66,7 +67,6 @@ setup(
"console_scripts": "console_scripts":
["easy_install = setuptools.command.easy_install:main"], ["easy_install = setuptools.command.easy_install:main"],
}, },
classifiers = [f.strip() for f in """ classifiers = [f.strip() for f in """
Development Status :: 3 - Alpha Development Status :: 3 - Alpha
Intended Audience :: Developers Intended Audience :: Developers
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
entry_points = setuptools.dist:check_entry_points entry_points = setuptools.dist:check_entry_points
extras_require = setuptools.dist:check_extras extras_require = setuptools.dist:check_extras
install_requires = setuptools.dist:check_install_requires install_requires = setuptools.dist:check_install_requires
include_package_data = setuptools.dist:assert_bool
namespace_packages = setuptools.dist:check_nsp namespace_packages = setuptools.dist:check_nsp
test_suite = setuptools.dist:check_test_suite test_suite = setuptools.dist:check_test_suite
eager_resources = setuptools.dist:assert_string_list eager_resources = setuptools.dist:assert_string_list
......
...@@ -189,6 +189,13 @@ The following keyword arguments to ``setup()`` are added or changed by ...@@ -189,6 +189,13 @@ The following keyword arguments to ``setup()`` are added or changed by
``setuptools``. All of them are optional; you do not have to supply them ``setuptools``. All of them are optional; you do not have to supply them
unless you need the associated ``setuptools`` feature. unless you need the associated ``setuptools`` feature.
``include_package_data``
If set to ``True``, this tells ``setuptools`` to automatically include any
data files it finds inside your package directories, that are either under
CVS or Subversion control, or which are specified by your ``MANIFEST.in``
file. For more information, see the section below on `Including Data
Files`_.
``package_data`` ``package_data``
A dictionary mapping package names to lists of glob patterns. For a A dictionary mapping package names to lists of glob patterns. For a
complete description and examples, see the section below on `Including complete description and examples, see the section below on `Including
...@@ -514,8 +521,26 @@ Including Data Files ...@@ -514,8 +521,26 @@ Including Data Files
The distutils have traditionally allowed installation of "data files", which The distutils have traditionally allowed installation of "data files", which
are placed in a platform-specific location. However, the most common use case are placed in a platform-specific location. However, the most common use case
for data files distributed with a package is for use *by* the package, usually for data files distributed with a package is for use *by* the package, usually
by including the data files in the package directory. Setuptools supports this by including the data files in the package directory.
by allowing a ``package_data`` argument to ``setup()``, e.g.::
Setuptools offers two ways to specify data files to be included in your
packages. First, you can simply use the ``include_package_data`` keyword,
e.g.::
from setuptools import setup, find_packages
setup(
...
include_package_data = True
)
This tells setuptools to install any data files it finds in your packages. The
data files must be under CVS or Subversion control, or else they must be
specified via the distutils' ``MANIFEST.in`` file.
If you want finer-grained control over what files are included (for example, if
you have documentation files in your package directories and want to exclude
them from installation), then you can use the ``package_data`` keyword instead,
e.g.::
from setuptools import setup, find_packages from setuptools import setup, find_packages
setup( setup(
...@@ -576,7 +601,6 @@ python.org website.) ...@@ -576,7 +601,6 @@ python.org website.)
__ http://docs.python.org/dist/node11.html __ http://docs.python.org/dist/node11.html
Accessing Data Files at Runtime Accessing Data Files at Runtime
------------------------------- -------------------------------
...@@ -1982,6 +2006,10 @@ Release Notes/Change History ...@@ -1982,6 +2006,10 @@ Release Notes/Change History
the project's ``.egg-info`` directory as ``SOURCES.txt``, and it is rebuilt the project's ``.egg-info`` directory as ``SOURCES.txt``, and it is rebuilt
every time the ``egg_info`` command is run. every time the ``egg_info`` command is run.
* Added the ``include_package_data`` keyword to ``setup()``, allowing you to
automatically include any package data listed in revision control or
``MANIFEST.in``.
0.6a8 0.6a8
* Fixed some problems building extensions when Pyrex was installed, especially * Fixed some problems building extensions when Pyrex was installed, especially
with Python 2.4 and/or packages using SWIG. with Python 2.4 and/or packages using SWIG.
......
...@@ -3,7 +3,6 @@ from distutils.command.build_py import build_py as _build_py ...@@ -3,7 +3,6 @@ from distutils.command.build_py import build_py as _build_py
from distutils.util import convert_path from distutils.util import convert_path
from glob import glob from glob import glob
class build_py(_build_py): class build_py(_build_py):
"""Enhanced 'build_py' command that includes data files with packages """Enhanced 'build_py' command that includes data files with packages
...@@ -17,7 +16,7 @@ class build_py(_build_py): ...@@ -17,7 +16,7 @@ class build_py(_build_py):
def finalize_options(self): def finalize_options(self):
_build_py.finalize_options(self) _build_py.finalize_options(self)
self.package_data = self.distribution.package_data self.package_data = self.distribution.package_data
self.data_files = self.get_data_files() if 'data_files' in self.__dict__: del self.__dict__['data_files']
def run(self): def run(self):
"""Build modules, packages, and copy data files to build directory""" """Build modules, packages, and copy data files to build directory"""
...@@ -35,12 +34,14 @@ class build_py(_build_py): ...@@ -35,12 +34,14 @@ class build_py(_build_py):
# output files are. # output files are.
self.byte_compile(_build_py.get_outputs(self, include_bytecode=0)) self.byte_compile(_build_py.get_outputs(self, include_bytecode=0))
def __getattr__(self,attr):
if attr=='data_files': # lazily compute data files
self.data_files = files = self._get_data_files(); return files
return _build_py.__getattr__(self,attr)
def _get_data_files(self):
def get_data_files(self):
"""Generate list of '(package,src_dir,build_dir,filenames)' tuples""" """Generate list of '(package,src_dir,build_dir,filenames)' tuples"""
self.analyze_manifest()
data = [] data = []
for package in self.packages or (): for package in self.packages or ():
# Locate package source directory # Locate package source directory
...@@ -63,7 +64,7 @@ class build_py(_build_py): ...@@ -63,7 +64,7 @@ class build_py(_build_py):
"""Return filenames for package's data files in 'src_dir'""" """Return filenames for package's data files in 'src_dir'"""
globs = (self.package_data.get('', []) globs = (self.package_data.get('', [])
+ self.package_data.get(package, [])) + self.package_data.get(package, []))
files = [] files = self.manifest_files.get(package, [])[:]
for pattern in globs: for pattern in globs:
# Each pattern has to be converted to a platform-specific path # Each pattern has to be converted to a platform-specific path
files.extend(glob(os.path.join(src_dir, convert_path(pattern)))) files.extend(glob(os.path.join(src_dir, convert_path(pattern))))
...@@ -79,45 +80,44 @@ class build_py(_build_py): ...@@ -79,45 +80,44 @@ class build_py(_build_py):
self.copy_file(os.path.join(src_dir, filename), target) self.copy_file(os.path.join(src_dir, filename), target)
def analyze_manifest(self):
self.manifest_files = mf = {}
if not self.distribution.include_package_data:
return
def get_outputs(self, include_bytecode=1): src_dirs = {}
"""Return complete list of files copied to the build directory for package in self.packages or ():
# Locate package source directory
This includes both '.py' files and data files, as well as '.pyc' and src_dirs[self.get_package_dir(package)] = package
'.pyo' files if 'include_bytecode' is true. (This method is needed for
the 'install_lib' command to do its job properly, and to generate a self.run_command('egg_info')
correct installation manifest.) ei_cmd = self.get_finalized_command('egg_info')
""" for path in ei_cmd.filelist.files:
return _build_py.get_outputs(self, include_bytecode) + [ if path.endswith('.py'): continue
os.path.join(build_dir, filename) d,f = os.path.split(path)
for package, src_dir, build_dir,filenames in self.data_files while d and d not in src_dirs:
for filename in filenames d, df = os.path.split(d)
] f = os.path.join(df, f)
if d in src_dirs:
mf.setdefault(src_dirs[d],[]).append(path)
if sys.version>="2.4":
# Python 2.4 already has the above code
build_py = _build_py def get_data_files(self): pass # kludge 2.4 for lazy computation
if sys.version<"2.4": # Python 2.4 already has this code
def get_outputs(self, include_bytecode=1):
"""Return complete list of files copied to the build directory
This includes both '.py' files and data files, as well as '.pyc'
and '.pyo' files if 'include_bytecode' is true. (This method is
needed for the 'install_lib' command to do its job properly, and to
generate a correct installation manifest.)
"""
return _build_py.get_outputs(self, include_bytecode) + [
os.path.join(build_dir, filename)
for package, src_dir, build_dir,filenames in self.data_files
for filename in filenames
]
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment