Python minimal package with pyproject.toml

Python packaging can be described in pyproject.toml alone per PEP 621. These packages are installable in live developer mode:

python -m pip install -e .

Or via PyPI like any other Python package. It can be most effective to put all project configuration, including Python package prerequisites in pyproject.toml alone as a single source of truth. pyproject.toml is human-readable and machine-parseable without first installing the package. Putting all package metadata into pyproject.toml instead of setup.py gives benefits including:

  • reproducible results
  • security risk mitigation
  • dynamic prerequisite tree based on Python version etc.
  • static or dynamic package version

This is an example of a minimal pyproject.toml that works all alone, no other metadata files required, except perhaps MANIFEST.in for advanced cases. The __version__ is contained in file mypkg/__init__.py as Python code:

__version__ = "1.2.3"

pyproject.toml:

[build-system]
requires = ["setuptools>=61.0.0", "wheel"]
build-backend = "setuptools.build_meta"

[project]
name = "mypkg"
description = "My really awesome package."
keywords = ["random", "cool"]
classifiers = ["Development Status :: 5 - Production/Stable",
 "Environment :: Console",
 "Intended Audience :: Science/Research",
 "Operating System :: OS Independent",
 "Programming Language :: Python :: 3",
]
requires-python = ">=3.7"
dynamic = ["version", "readme"]

[tool.setuptools.dynamic]
readme = {file = ["README.md"], content-type = "text/markdown"}
version = {attr = "mypkg.__version__"}

PEP8 checking via flake8 is configured in .flake8:

[flake8]
max-line-length = 100
exclude = .git,__pycache__,doc/,docs/,build/,dist/,archive/
per-file-ignores =
  __init__.py:F401

MANIFEST.in is used to specify external files installed.

Classifiers are optional and help projects indexing in PyPI and search engines. Classifiers must be from the official classifier trove or they will fail when uploading a package to PyPI.

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