Python Packaging

The authoritative docs.

Example setup.py:

# Always prefer setuptools over distutils
from setuptools import setup, find_packages
# To use a consistent encoding
from codecs import open
from os import path

here = path.abspath(path.dirname(__file__))

setup(
    name='ursonos',
    version='0.0.1',
    packages=find_packages(),
    url='',
    license='',
    author='poirier',
    author_email='dan@poirier.us',
    description='Urwid application to control Sonos',
    install_requires=[
        'soco',
        'urwid'
    ]
)

To include non-Python files in the packaging, create a MANIFEST.in file. Example:

include path/to/*.conf

adds the files matching path/to/*.conf. Another:

recursive-include subdir/path *.txt *.rst

adds all files matching *.txt or *.rst that are anywhere under subdir/path. Finally:

prune examples/sample?/build

should be obvious.

Source package

To build a source package:

python setup.py sdist

Wheels

To build a Universal Wheel:

python setup.py bdist_wheel --universal

You can also permanently set the --universal flag in “setup.cfg” (e.g., see sampleproject/setup.cfg)

[bdist_wheel]
universal=1

Only use the --universal setting, if:

  1. Your project runs on Python 2 and 3 with no changes (i.e. it does not require 2to3).

  2. Your project does not have any C extensions.

Upload

The docs recommend twine

twine upload dist/*

Projects with code under a src directory

In this case, there’s a Django app pkgname under src, with a templates directory and a static directory that need to be included.

Setup.py:

from setuptools import setup, find_packages

setup(
    name="pkgname",
    version="1.9.13",
    packages=find_packages(where="src"),
    package_dir={"": "src", "pkgname": "src/pkgname"},
    url="",
    license="",
    author="poirier",
    author_email="",
    description="",
    python_requires=">=3.6",
    install_requires=["Django<=3.0", "dj-database-url", "gunicorn", "whitenoise"],
    entry_points={"console_scripts": ["manage=manage:main"]},

    package_data={
        "pkgname": ["templates/*.html", "templates/include/*.html", "static/*"],
    }
)

and MANIFEST.in:

graft pkgname/templates
graft pkgname/static