Packaging
A main use of pyproject.toml
is for defining project metadata.
This includes:
- the name of your project, and your contact information,
- the versions of Python it is compatible with,
- the packages it depends on,
- the command-line tools it provides.
This information is used to build and install the project, as well as when publishing it on PyPI.
All this information is stored in the [project]
table of the
pyproject.toml
file.
Basic metadata
Add the following section to your file:
[project]
name = "my-package"
version = "0.1"
authors = [
{name = "Firstname Lastname", email = "me@me.org"}
]
description = "A really cool project"
license = "Apache-2.0"
license-files = ["LICENSE.md"]
keywords = ["science", "magic"]
You can change the authors or project name to values of your choice.
Note that:
- The project
name
is how other projects will refer to yours, e.g. when declaring their dependency on it. - The
name
cannot contain spaces. - The
keywords
make it easier to find your project on PyPI when searching for those terms.
Avoid hardcoding the version
You can set the version dynamically, based on some property in your code.
Change the version = "0.1"
line above to dynamic = ["version"]
.
Then add a new section:
[tool.setuptools.dynamic]
version = {attr = "my_package.__version__"}
This will read the version from the __version__
variable in
my_package/__init__.py
.
Dependencies
If your project uses other Python packages, you should generally make sure
they are installed alongside it.
You can declare declare what your package needs in order to run
in pyproject.toml
. This includes:
- what versions of Python it is compatible with,
- any other other packages it requires.
Add the following entries in the project
table, below the metadata:
[project]
...
requires-python = ">= 3.10"
dependencies = [
"pyyaml"
]
Install your package
Navigate to the project directory and run python -m pip install .
Among the output, you should see a message like
Collecting pyyaml (from my-package==1.0)
pip
is installing for your package's dependencies!
Also note the line
Successfully installed my-package-0.1
pyproject.toml
.
Entrypoints
When writing a package, you sometimes want to create a way of accessing
its functionality from the command line. For example, the pytest
package
creates an executable that can be called with pytest
on a terminal.
You can use pyproject.toml
to define any command-line entrypoints
that your package provides.
Add the following section in your file:
[project.scripts]
demo = "my_package.cli:run"
With this configuration, when your package is installed, pip
will create
a script that:
- can be executed with the command
demo
, and - when executed, it runs the function
run
fromcli.py
in your package.
Try out the entrypoint
Install your package again with python -m pip install .
to have
the new change take effect.
When the re-installation is complete, run demo
on the terminal.
You should see something like:
Trying out combine_arguments with x='A', y='B', z=4
Result is A4
Open the cli.py
file and verify that this is the output from
the run
function.
You have now made it possible for others to use your package both as a library and as a command-line tool!
Further resources
- The Python Packaging Authority (PyPA) provides a comprehensive guide to writing a pyproject.toml file.
- PyPA also maintains the latest version of the formal specification.
- The docs for
setuptools
(the default build backend) include a guide for how to configurepyproject.toml
for it. Other backends may have their own guidance. - PEP 621 proposed what project metadata should be stored.