How do you add additional files to a wheel?
Question: How do control what files are included in a wheel? It appears `MANIFEST.in`
isn't used by `python setup.py bdist_wheel`.

**UPDATE** :

I was wrong about the difference between installing from a source tarball vs a
wheel. The source distribution includes files specified in `MANIFEST.in`, but
the installed package only has python files. Steps are needed to identify
additional files that should be installed, whether the install is via source
distribution, egg, or wheel. Namely,
[package_data](https://docs.python.org/2/distutils/setupscript.html#installing-
package-data) is needed for additional package files, and
[data_files](https://docs.python.org/2/distutils/setupscript.html#installing-
additional-files) for files outside your package like command line scripts or
system config files.

## Original Question

I have [a project](https://github.com/tulsawebdevs/django-multi-gtfs) where
I've been using `python setup.py sdist` to build my package, `MANIFEST.in` to
control the files included and excluded, and
[pyroma](https://pypi.python.org/pypi/pyroma) and [check-
manifest](https://pypi.python.org/pypi/check-manifest) to confirm my settings.

I recently converted it to dual Python 2 / 3 code, and added a setup.cfg with

    
    
    [bdist_wheel]
    universal = 1
    

I can build a wheel with `python setup.py bdist_wheel`, and it appears to be a
universal wheel as desired. However, it doesn't include all of the files
specified in `MANIFEST.in`.

## What gets installed?

I dug deeper, and now know more about packaging and wheel. Here's what I
learned:

I upload two package files to the [multigtfs project on
PyPi](https://pypi.python.org/pypi/multigtfs/0.4.2):

  * `multigtfs-0.4.2.tar.gz` \- the source tar ball, which includes all the files in `MANIFEST.in`.
  * `multigtfs-0.4.2-py2.py3-none-any.whl` \- The binary distribution in question.

I created two new virtual environments, both with Python 2.7.5, and installed
each package (`pip install multigtfs-0.4.2.tar.gz`). The two environments are
almost identical. They have different `.pyc` files, which are the "compiled"
Python files. There are log files which record the different paths on disk.
The install from the source tar ball includes a folder
`multigtfs-0.4.2-py27.egg-info`, detailing the installation, and the wheel
install has a `multigtfs-0.4.2.dist-info` folder, with the details of that
process. However, from the point of view of code using the multigtfs project,
there is no difference between the two installation methods.

Explicitly, neither has the .zip files used by my test, so the test suite will
fail:

    
    
    $ django-admin startproject demo
    $ cd demo
    $ pip install psycopg2  # DB driver for PostGIS project
    $ createdb demo         # Create PostgreSQL database
    $ psql -d demo -c "CREATE EXTENSION postgis" # Make it a PostGIS database 
    $ vi demo/settings.py   # Add multigtfs to INSTALLED_APPS,
                            # Update DATABASE to set ENGINE to django.contrib.gis.db.backends.postgis
                            # Update DATABASE to set NAME to test
    $ ./manage.py test multigtfs.tests  # Run the tests
    ...
    IOError: [Errno 2] No such file or directory: u'/Users/john/.virtualenvs/test/lib/python2.7/site-packages/multigtfs/tests/fixtures/test3.zip'
    

## Specifying additional files

Using the suggestions from the answers, I added some additional directives to
`setup.py`:

    
    
    from __future__ import unicode_literals
    # setup.py now requires some funky binary strings
    ...
    setup(
        name='multigtfs',
        packages=find_packages(),
        package_data={b'multigtfs': ['test/fixtures/*.zip']},
        include_package_data=True,
        ...
    )
    

This installs the zip files (as well as the README) to the folder, and tests
now run correctly. Thanks for the suggestions!


Answer: Have you tried using `package_data` in your `setup.py`? `MANIFEST.in` seems
targetted for python versions <= 2.6, I'm not sure if higher versions even
look at it.

After exploring <https://github.com/pypa/sampleproject>, their `MANIFEST.in`
says:

    
    
    # If using Python 2.6 or less, then have to include package data, even though
    # it's already declared in setup.py
    include sample/*.dat
    

which seems to imply this method is outdated. Meanwhile, in `setup.py` they
declare:

    
    
    setup(
        name='sample',
        ...
        # If there are data files included in your packages that need to be
        # installed, specify them here.  If using Python 2.6 or less, then these
        # have to be included in MANIFEST.in as well.
        package_data={
            'sample': ['package_data.dat'],
        },
        ...
    )
    

(I'm not sure why they chose a wildcard in `MANIFEST.in` and a filename in
`setup.py`. They refer to the same file)

Which, along with being simpler, again seems to imply that the `package_data`
route is superior to the `MANIFEST.in` method. Well, unless you have to
support 2.6 that is, in which case my prayers go out to you.

