pyproject-metadata
Dataclass for pyproject.toml
[project]metadata with support for [core > metadata] generation
This project does not implement the parsing of pyproject.toml containing
pyproject.toml [project] metadata.
Instead, given a Python data structure representing pyproject.toml [project]
metadata (already parsed), it will validate this input and generate a PEP
643-compliant metadata file (e.g. PKG-INFO).
Usage
After
installing pyproject-metadata,
you can use it as a library in your scripts and programs:
from pyproject_metadata import StandardMetadata
parsed_pyproject = {...} # you can use parsers like `tomli` to obtain this dict
metadata = StandardMetadata.from_pyproject(parsed_pyproject, allow_extra_keys=False)
# Same fields as defined in pyproject.toml [project] metadata
print(metadata.entrypoints)
pkg_info = metadata.as_rfc822()
print(str(pkg_info)) # core metadata
SPDX licenses (METADATA 2.4+)
If project.license is a string or project.license-files is present, then
METADATA 2.4+ will be used. A user is expected to validate and normalize
metadata.license with an SPDX validation tool, such as the one being added to
packaging. Add something like this (requires packaging 24.2+):
if isinstance(metadata.license, str):
metadata.license = packaging.licenses.canonicalize_license_expression(
metadata.license
)
A backend is also expected to copy entries from project.license_files, which
are paths relative to the project directory, into the dist-info/licenses
folder, preserving the original source structure.
Dynamic Metadata (METADATA 2.2+)
Pyproject-metadata supports dynamic metadata. To use it, specify your METADATA
fields in dynamic_metadata. If you want to convert pyproject.toml field
names to METADATA field(s), use
pyproject_metadata.pyproject_to_metadata("field-name"), which will return a
frozenset of metadata names that are touched by that field.
Adding extra fields
You can add extra fields to the Message returned by to_rfc822(), as long as
they are valid metadata entries.
Collecting multiple errors
You can use the all_errors argument to from_pyproject to show all errors in
the metadata parse at once, instead of raising an exception on the first one.
The exception type will be pyproject_metadata.errors.ExceptionGroup (which is
just ExceptionGroup on Python 3.11+).
Validating extra fields
By default, a warning (pyproject_metadata.errors.ExtraKeyWarning) will be
issued for extra fields at the project table. You can pass allow_extra_keys=
to either avoid the check (True) or hard error (False). If you want to
detect extra keys, you can get them with pyproject_metadata.extra_top_level
and pyproject_metadata.extra_build_system. It is recommended that build
systems only warn on failures with these extra keys.
Validating classifiers
If you want to validate classifiers, then install the trove_classifiers
library (the canonical source for classifiers), and run:
import trove_classifiers
metadata_classifieres = {
c for c in metadata.classifiers if not c.startswith("Private ::")
}
invalid_classifiers = set(metadata.classifiers) - trove_classifiers.classifiers
# Also the deprecated dict if you want it
dep_names = set(metadata.classifiers) & set(trove_classifiers.deprecated_classifiers)
deprecated_classifiers = {
k: trove_classifiers.deprecated_classifiers[k] for k in dep_names
}
If you are writing a build backend, you should not validate classifiers with a
Private :: prefix; these are only restricted for upload to PyPI (such as
Private :: Do Not Upload).
Since classifiers are a moving target, it is probably best for build backends (which may be shipped by third party distributors like Debian or Fedora) to either ignore or have optional classifier validation.
Release files for pyproject-metadata 0.12.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pyproject_metadata-0.12.1.tar.gz | 48.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pyproject_metadata-0.12.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 71.9 kB
Release files / pyproject_metadata-0.12.1.tar.gz
| Download URL | pyproject_metadata-0.12.1.tar.gz |
|---|---|
| Size | 48.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8809a4df6fe08279b39a8890669506ed3158e0617855ac9aff098fcbe772ae4c
|
|
BLAKE2b-256 checksum How to use checksums |
4f761cae539918a7b1746d624c2f01560b793c22cd8c081157505bb9bbf0e34d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 4, 2026.
Transparency logRelease files / pyproject_metadata-0.12.1-py3-none-any.whl
| Download URL | pyproject_metadata-0.12.1-py3-none-any.whl |
|---|---|
| Size | 23.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
f7162d580a96386a8eb096da06215f981f547d1490f03055ef99e323bc2da427
|
|
BLAKE2b-256 checksum How to use checksums |
b98ed883718e872abc214ba053f60f7e6edc2abd5ffbd1544beb01a9c92ddd3c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 4, 2026.
Transparency log