Python setuptools: files

From wikinotes

Documentation

setuptools: packaging datafiles https://setuptools.readthedocs.io/en/latest/setuptools.html#including-data-files
python: packaging datafiles https://packaging.python.org/distributing/#data-files

src Files

packages

Packages determines what top-level python-packages are to be copied/included in your distribution.
You can define these by hand, or use setuptools to determine them automatically.

setuptools.setup(
    packages = setuptools.find_packages(exclude=['tests*'])
)

General Files

package_data (project-install)

C libraries, icons, etc. get installed inside your project.
Non-python files installed to your project are defined in package_data.

include/exclude_package_data (allow/denylist)


For most cases, this is the easier way of including files into the installed source directory.

  • include_package_data includes every non-python file in your source tree
  • exclude_package_data has the same format (and restrictions) as the raw package_data dict, and it lets you target specific you do not want to package.
setuptools.setup( 
    include_package_data = True,
    exclude_package_data = {
        'relpath/from/setup.py_dir/srctree' : ['README.rst', 'dir/*.txt', '*.rst' ],
    },
)

package_data dict

In contrast to the above approach, package_data gives you the power to set exactly what you want to copy, and nothing else. Personally, I find this to be more labour intensive that it needs to be.

The format of package_data is:

setuptools.setup(
    package_data = {
        'relpath/from/setup.py_dir/srctree' : [ '*.rst', 'dir/*.txt', 'README.rst' ],
    }
)

There are however some gotchas:

  • package_data is not recursive. Also, It matches files only.
  • every directory used as a key in package_data's dict MUST BE A PYTHON PACKAGE
  • subdirectories of packages can be used on the file-match side (if those subdirectories are not packages). That means every dir on the key side must contain __init__.py

data_files (os)

WARNING:

deprecated, does not work with wheels

NOTE:

There is no current way of distributing files outside of your package using setuptools.
They recommend providing them to users and allowing them to install them.
See https://setuptools.readthedocs.io/en/latest/setuptools.html#non-package-data-files

manpages, autocompletionscripts, configfiles etc. are installed outside of your project hierarchy.
These files are managed using data_files.

data_files


data_files recursively copies directories/files and allows you to install files from outside of your package to outside of your package.

setuptools.setup(
    data_files   = [
        ('tests',              ['*']) ,                 ## ??
        ('/etc/some_file.txt', ['data/some_file.txt']), ## dir-with-setup.py/data/some_file.txt is copied to /etc/some_file.txt
        ('man/man1', ['myprogram.1.gz']),               ## dir-with-setup.py/myprogram.1.gz     is copied to /man/man1/myprogram.1.gz
    ],
)

Manifest.in

Manifest.in works like setup.py's package_data except that MANIFEST.in :

  • finds files relative to the directory containing setup.py instead of the source-dir under it
  • writes files to the package-format you are using (.zip, .tar.gz, wheel,...). Files are not copied into the installed source tree unless they are already there.

Think of it as feeding setup.py files and informing the user rather than ensuring files are available in your source-tree.

MANIFEST.in commands:

include              README.rst            # <filepath_from_seutup.py_dir>
recursive-include    images   *.png *.jpg  # <dirpath_from_setup.py_dir>   <file_match> <file_match> <file_match> ...