Skip to content

What is PEP 621?

PEP 621 defines the [project] table in pyproject.toml for declaring project name, version, description, dependencies, license, and other core metadata. Any compliant build tool can read this table without executing Python code or recognizing tool-specific configuration.

How tools stored metadata before PEP 621

Before PEP 621, every build tool stored project metadata in its own format. Setuptools used setup.py (executable Python) or setup.cfg (an INI format with a setuptools-specific schema). Flit used [tool.flit.metadata]. Poetry stored everything under [tool.poetry].

Reading a project’s name or dependencies required knowing which tool built it, or running its build system. Metadata inside setup.py could not be read statically at all.

What the [project] table defines

PEP 621 reserves the [project] key in pyproject.toml for standard metadata. A minimal project configuration:

[project]
name = "my-package"
version = "1.0.0"
description = "A short description."
requires-python = ">=3.11"
dependencies = [
    "requests>=2.28",
]

[project.scripts]
my-tool = "my_package.cli:main"

name is always required. version is required unless listed in dynamic (see below). Optional fields include:

  • description, readme, requires-python, license
  • authors, maintainers, keywords, classifiers
  • urls, scripts, gui-scripts, entry-points
  • dependencies, optional-dependencies

These fields map directly to core metadata, the wire format inside wheels and sdists. PEP 621 defines how the source-tree declaration translates into the same fields that installers read after a package is built.

Computed fields: the dynamic key

Some projects derive their version from a git tag, a file, or a commit hash rather than hardcoding it in pyproject.toml. The dynamic key lists which fields the backend computes rather than reads from [project]:

[project]
name = "my-package"
dynamic = ["version"]

A plugin like hatch-vcs or setuptools-scm then supplies the version during the build. All other metadata still belongs in [project].

Which backends support PEP 621

Backend PEP 621 support
uv_build Native
Hatchling Native
flit_core Native (replaced [tool.flit.metadata])
setuptools From v61.0.0
pdm-backend Native
poetry-core From Poetry 2.0; [tool.poetry] still works

PEP 621 standardizes where metadata lives, not how packages get built. The [build-system] table from PEP 517/518 still determines which backend runs. Switching from Hatchling to uv_build means changing [build-system]; the [project] table stays the same.

Related

Learn More

Last updated on