Minimal Python setup.py with prerequisites

Related: Upload user Python module to PyPi


The optional setup.py for setuptools-based Python packages can be reduced to a one-line file for simple Python packages, by putting the project metadata in setup.cfg. The example setup.cfg file below is associated with a setup.py file containing merely:

from setuptools import setup; setup()

This is installed as usual by:

python -m pip install -e .

or similar.

It can be most effective to put all project configuration, including Python package prerequisites in setup.cfg instead of setup.py. setup.cfg is human-readable and machine-parseable without first installing the package. Putting as many parameters as possible into setup.cfg instead of setup.py is important and beneficial for reasons including:

  • reproducible results
  • security risk mitigation
  • getting package prerequisite tree list

Example

This is an example of best practices (since 2016) of minimal setup.py using setup.cfg. It does not use requirements.txt.

setup.cfg holds the machine-readable configuration, easy for humans too:

[metadata]
name = mycoolpkg
author = Joe Smith
author_email = me@gmail.com
description = My awesome program prints cool messages
version = file: __init__.py
url = https://github.com/joe/mycoolpkg
keywords =
  cool printing
  networking
classifiers =
  Development Status :: 4 - Beta
  Intended Audience :: Science/Research
  Programming Language :: Python :: 3.6
  Programming Language :: Python :: 3.7
  Programming Language :: Python :: 3.8
  Topic :: Scientific/Engineering
long_description = file: README.md
long_description_content_type = text/markdown
license_files =
  LICENSE.txt

[options]
python_requires = >= 2.7
packages = find:
zip_safe: False
scripts =
#  joesprint.py
install_requires =
#  colorama

[options.extras_require]
tests =
  pytest
  pytest-cov
  coveralls
  flake8
  mypy

[options.entry_points]
console_scripts =
#  joesprint = joesprint:main

The companion to setup.cfg is pyproject.toml. pyproject.toml is used in general for Python project settings, including ones not using setuptools. The standard way to communicate that setuptools is used for a Python project is with pyproject.toml containing:

[build-system]
requires = ["setuptools", "wheel"]

Coverage

Test coverage is configured in .coveragerc, like:

[run]
cover_pylib = false
omit =
    /home/travis/virtualenv/*
    */site-packages/*

[report]
exclude_lines =
    pragma: no cover
    def __repr__
    RuntimeError
    NotImplementedError
    FileNotFoundError
    ImportError

PEP8 / Type hinting checks

PEP8 checking via flake8 is configured in .flake8:

[flake8]
max-line-length = 132
exclude = .git,__pycache__,doc/,docs/,build/,dist/,archive/

MyPy type hint checking is configured via mypy.ini.

pytest.ini

If one wishes to configure Pytest itself, that can be done in pytest.ini. It is recommended to configure Pytest in pytest.ini instead of setup.cfg for best stability. For example, require Pytest ≥ 3.9 with pytest.ini containing:

[pytest]

minversion = 3.9

MANIFEST.in

MANIFEST.in is usually not necessary. It’s better in general to specify scripts and data files in setup.cfg.

Notes

  • install_requires cannot read requirements.txt as file: is not in the setup.cfg install_requires input types
  • console_scripts expects a file joesprint.py with the function main designed to accept command line input, perhaps using argparse.ArgumentParser
  • python_requires parameter avoids user confusion if they have an old Python version. Instead of them opening a GitHub issue or just not using your program at all, they’ll get a useful error message.

Classifiers

Classifiers are optional, but help your project be indexed better in PyPi (and hence search engines). Classifiers must be from this official classifiers list or they will fail when uploading your package to PyPi.

setup.py Fortran f2py

Python can easily import Fortran code using f2py. See this f2py example setup.py.

Notes

setuptools 38.6 and wheel 0.31 support Markdown README. Pip 10 brought pyproject.toml support, necessary for clean handling of Python Extension Modules via Numpy as well as setup.cfg support.