Python packages

After some hesitation, I now use pyproject.toml describe, build, and publish my Python packages. In this document I document the setup. Let’s assume a python package called package_name. Then, the git repo should look like this:

Repository layout

package-name
├── .gitignore
├── LICENSE
├── README.md
├── package_name
│   ├── __init__.py
│   └── main.py
└── pyproject.toml

The package is described by the pyproject.toml file. It looks like this:

[project]
name = "project-name"
authors = [
    { name = "Jochen Klar", email = "mail@jochenklar.de" },
]
maintainers = [
    { name = "Jochen Klar", email = "mail@jochenklar.de" },
]
description = """
Lorem ipsum dolor sit amet, consetetur sadipscing elitr,
sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat"""
readme = "README.md"
requires-python = ">=3.8"
license = { file = "LICENSE" }
classifiers = [
    'Operating System :: OS Independent',
    'License :: OSI Approved :: MIT License',
    'Programming Language :: Python :: 3.8',
    'Programming Language :: Python :: 3.9',
    'Programming Language :: Python :: 3.10',
    'Programming Language :: Python :: 3.11',
]
dependencies = [
    "Django>=4.2",
    ...
]
dynamic = ["version"]

[project.urls]
Repository = "https://github.com/jochenklar/project-name"

# if the package provides command line scripts
[project.scripts]
main-script = "project_name.main:main"

[tool.setuptools]
packages = ["project_name"]

[tool.setuptools.dynamic]
version = { attr = "project_name.__version__" }

The package_name/__init__.py contains the version in the following form:

VERSION = __version__ = '1.0.0'

Publication process

In order to publish the package on PyPI, you need an account there. The credentials can be put in a ~/.pypirc file:

[pypi]
username: ...
password: ...

[testpypi]
repository: https://test.pypi.org/legacy/
username: ...
password: ...

The build and twine packages need to be installed (in the current virtual environment):

pip install build twine

Then the package can be build:

python -m build

and checked:

twine check dist/*

The actual publication is then done using:

twine upload -r testpypi dist/*  # on the test server
twine upload dist/*              # on the live system

Afterwards, a release on GitHub can be done, but don’t forget to push the commit with the updated version**.

1