GitHub - pypa/pyproject-metadata: PEP 621 metadata parsing (original) (raw)
pyproject-metadata
Dataclass for PEP 621 metadata with support for core metadata generation
This project does not implement the parsing of pyproject.toml
containing PEP 621 metadata.
Instead, given a Python data structure representing PEP 621 metadata (already parsed), it will validate this input and generate a PEP 643-compliant metadata file (e.g. PKG-INFO
).
Usage
Afterinstalling 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)
print(metadata.entrypoints) # same fields as defined in PEP 621
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 normalizemetadata.license
with an SPDX validation tool, such as the one being added topackaging
. 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.licence_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), usepyproject_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 aPrivate ::
prefix; these are only restricted for upload to PyPI (such asPrivate :: 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.