Python
packaging
Published

November 4, 2023

pyproject.toml metadata and dependencies

Python allows to specify metadata and dependencies in a pyproject.toml.

I have started using the metadata declaration recently and tried the dependency specification this week.

I added an example to the folder of the post. It contains project metadata and examples for project and development dependencies.

Code
def print_file(file_name):
  with open(file_name, "r") as file:
      print(file.read())

print_file("pyproject.toml")
[project]
name = "hd-example"
version = "0.1"
description = "An example for pyproject"
maintainers = [{ name = "Holger Döring" }]
license = { text = "MIT License" }
requires-python = ">=3.11"
dependencies = [
  "requests",
]

[project.optional-dependencies]
dev = [
  "pip-tools",
  "ruff",
]

[project.urls]
 homepage = ""
repository = "https://github.com/hdigital/starter-python.git"


# specify build system to run pip-tools
# (application is not a package and no build is needed)
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

There is a toml parser in the standard library since Python 3.11, released in October last year. It can be used to read the pyproject.toml.

import tomli as tomllib  # Python <= 3.10

with open("pyproject.toml", "rb") as toml_file:
    toml_data = tomllib.load(toml_file)

toml_data
{'project': {'name': 'hd-example',
  'version': '0.1',
  'description': 'An example for pyproject',
  'maintainers': [{'name': 'Holger Döring'}],
  'license': {'text': 'MIT License'},
  'requires-python': '>=3.11',
  'dependencies': ['requests'],
  'optional-dependencies': {'dev': ['pip-tools', 'ruff']},
  'urls': {'homepage': '',
   'repository': 'https://github.com/hdigital/starter-python.git'}},
 'build-system': {'requires': ['hatchling'],
  'build-backend': 'hatchling.build'}}

I like to pin dependencies in one requirements.txt. Such a file can be created with pip-tools.

python -m piptools compile --upgrade --extra dev pyproject.toml

Usually, I include the --generate-hashes option but leave it out here to shorten the output by not including hash keys.

Code
print_file("requirements.txt")
#
# This file is autogenerated by pip-compile with Python 3.11
# by the following command:
#
#    pip-compile --extra=dev pyproject.toml
#
build==1.0.3
    # via pip-tools
certifi==2023.7.22
    # via requests
charset-normalizer==3.3.2
    # via requests
click==8.1.7
    # via pip-tools
idna==3.4
    # via requests
packaging==23.2
    # via build
pip-tools==7.3.0
    # via hd-example (pyproject.toml)
pyproject-hooks==1.0.0
    # via build
requests==2.31.0
    # via hd-example (pyproject.toml)
ruff==0.1.4
    # via hd-example (pyproject.toml)
urllib3==2.0.7
    # via requests
wheel==0.41.3
    # via pip-tools

# The following packages are considered to be unsafe in a requirements file:
# pip
# setuptools