Skip to content

Commit

Permalink
Added the include_package_data keyword to setup(), allowing y…
Browse files Browse the repository at this point in the history
…ou 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
  • Loading branch information
PJ Eby committed Nov 18, 2005
1 parent f3694a0 commit 4cd66c4
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 50 deletions.
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def get_description():
url = "http://peak.telecommunity.com/DevCenter/setuptools",
test_suite = 'setuptools.tests.test_suite',
packages = find_packages(),
package_data = {'setuptools': ['*.exe']},
include_package_data = True,
py_modules = ['pkg_resources', 'easy_install', 'site'],

zip_safe = False, # We want 'python -m easy_install' to work, for now :(
Expand All @@ -53,6 +53,7 @@ def get_description():
"entry_points = setuptools.dist:check_entry_points",
"test_suite = setuptools.dist:check_test_suite",
"zip_safe = setuptools.dist:assert_bool",
"include_package_data = setuptools.dist:assert_bool",
],
"egg_info.writers": [
"PKG-INFO = setuptools.command.egg_info:write_pkg_info",
Expand All @@ -66,7 +67,6 @@ def get_description():
"console_scripts":
["easy_install = setuptools.command.easy_install:main"],
},

classifiers = [f.strip() for f in """
Development Status :: 3 - Alpha
Intended Audience :: Developers
Expand Down
1 change: 1 addition & 0 deletions setuptools.egg-info/entry_points.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
entry_points = setuptools.dist:check_entry_points
extras_require = setuptools.dist:check_extras
install_requires = setuptools.dist:check_install_requires
include_package_data = setuptools.dist:assert_bool
namespace_packages = setuptools.dist:check_nsp
test_suite = setuptools.dist:check_test_suite
eager_resources = setuptools.dist:assert_string_list
Expand Down
34 changes: 31 additions & 3 deletions setuptools.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
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``
A dictionary mapping package names to lists of glob patterns. For a
complete description and examples, see the section below on `Including
Expand Down Expand Up @@ -514,8 +521,26 @@ Including Data Files
The distutils have traditionally allowed installation of "data files", which
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
by including the data files in the package directory. Setuptools supports this
by allowing a ``package_data`` argument to ``setup()``, e.g.::
by including the data files in the package directory.

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
setup(
Expand Down Expand Up @@ -576,7 +601,6 @@ python.org website.)
__ http://docs.python.org/dist/node11.html



Accessing Data Files at Runtime
-------------------------------

Expand Down Expand Up @@ -1982,6 +2006,10 @@ Release Notes/Change History
the project's ``.egg-info`` directory as ``SOURCES.txt``, and it is rebuilt
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
* Fixed some problems building extensions when Pyrex was installed, especially
with Python 2.4 and/or packages using SWIG.
Expand Down
90 changes: 45 additions & 45 deletions setuptools/command/build_py.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
from distutils.util import convert_path
from glob import glob


class build_py(_build_py):
"""Enhanced 'build_py' command that includes data files with packages
Expand All @@ -17,7 +16,7 @@ class build_py(_build_py):
def finalize_options(self):
_build_py.finalize_options(self)
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):
"""Build modules, packages, and copy data files to build directory"""
Expand All @@ -35,12 +34,14 @@ def run(self):
# output files are.
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"""
self.analyze_manifest()
data = []
for package in self.packages or ():
# Locate package source directory
Expand All @@ -63,7 +64,7 @@ def find_data_files(self, package, src_dir):
"""Return filenames for package's data files in 'src_dir'"""
globs = (self.package_data.get('', [])
+ self.package_data.get(package, []))
files = []
files = self.manifest_files.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))))
Expand All @@ -79,45 +80,44 @@ def build_package_data(self):
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):
"""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
]


if sys.version>="2.4":
# Python 2.4 already has the above code
build_py = _build_py




















src_dirs = {}
for package in self.packages or ():
# Locate package source directory
src_dirs[self.get_package_dir(package)] = package

self.run_command('egg_info')
ei_cmd = self.get_finalized_command('egg_info')
for path in ei_cmd.filelist.files:
if path.endswith('.py'): continue
d,f = os.path.split(path)
while d and d not in src_dirs:
d, df = os.path.split(d)
f = os.path.join(df, f)
if d in src_dirs:
mf.setdefault(src_dirs[d],[]).append(path)


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
]



0 comments on commit 4cd66c4

Please sign in to comment.