API Reference

This is pyproject_metadata, a library for working with PEP 621 metadata.

Example usage:

from pyproject_metadata import StandardMetadata

metadata = StandardMetadata.from_pyproject(
    parsed_pyproject, allow_extra_keys=False, all_errors=True, metadata_version="2.3"
)

pkg_info = metadata.as_rfc822()
with open("METADATA", "wb") as f:
    f.write(pkg_info.as_bytes())

ep = self.metadata.entrypoints.copy()
ep["console_scripts"] = self.metadata.scripts
ep["gui_scripts"] = self.metadata.gui_scripts
for group, entries in ep.items():
    if entries:
        with open("entry_points.txt", "w", encoding="utf-8") as f:
            print(f"[{group}]", file=f)
            for name, target in entries.items():
                print(f"{name} = {target}", file=f)
            print(file=f)
class pyproject_metadata.License(text, file)[source]

Bases: object

This represents a classic license, which contains text, and optionally a file path. Modern licenses are just SPDX identifiers, which are strings.

text: str
file: Path | None
class pyproject_metadata.RFC822Message[source]

Bases: EmailMessage

This is email.message.EmailMessage with two small changes: it defaults to our RFC822Policy, and it correctly writes unicode when being called with bytes().

as_bytes(unixfrom=False, policy=None)[source]

This handles unicode encoding.

Return type:

bytes

class pyproject_metadata.RFC822Policy(**kw)[source]

Bases: EmailPolicy

This is email.policy.EmailPolicy, but with a simple header_store_parse implementation that handles multiline values, and some nice defaults.

Create new Policy, possibly overriding some defaults.

See class docstring for a list of overridable attributes.

utf8 = True
mangle_from_ = False
max_line_length = 0
header_store_parse(name, value)[source]

Given the header name and the value provided by the application program, return the (name, value) that should be stored in the model. The name is returned unchanged. If the input value has a ‘name’ attribute and it matches the name ignoring case, the value is returned unchanged. Otherwise the name and value are passed to header_factory method, and the resulting custom header object is returned as the value. In this case a ValueError is raised if the input value contains CR or LF characters.

Return type:

tuple[str, str]

class pyproject_metadata.Readme(text, file, content_type)[source]

Bases: object

This represents a readme, which contains text and a content type, and optionally a file path.

text: str
file: Path | None
content_type: str
class pyproject_metadata.StandardMetadata(name, version=None, description=None, license=None, license_files=None, readme=None, requires_python=None, dependencies=<factory>, optional_dependencies=<factory>, entrypoints=<factory>, authors=<factory>, maintainers=<factory>, urls=<factory>, classifiers=<factory>, keywords=<factory>, scripts=<factory>, gui_scripts=<factory>, dynamic=<factory>, dynamic_metadata=<factory>, metadata_version=None, all_errors=False)[source]

Bases: object

This class represents the standard metadata fields for a project. It can be used to read metadata from a pyproject.toml table, validate it, and write it to an RFC822 message or JSON.

name: str
version: Version | None = None
description: str | None = None
license: License | str | None = None
license_files: list[Path] | None = None
readme: Readme | None = None
requires_python: SpecifierSet | None = None
dependencies: list[Requirement]
optional_dependencies: dict[str, list[Requirement]]
entrypoints: dict[str, dict[str, str]]
authors: list[tuple[str, str | None]]
maintainers: list[tuple[str, str | None]]
urls: dict[str, str]
classifiers: list[str]
keywords: list[str]
scripts: dict[str, str]
gui_scripts: dict[str, str]
dynamic: list[Literal['authors', 'classifiers', 'dependencies', 'description', 'dynamic', 'entry-points', 'gui-scripts', 'keywords', 'license', 'maintainers', 'optional-dependencies', 'readme', 'requires-python', 'scripts', 'urls', 'version']]

This field is used to track dynamic fields. You can’t set a field not in this list.

dynamic_metadata: list[str]

This is a list of METADATA fields that can change in between SDist and wheel. Requires metadata_version 2.2+.

metadata_version: str | None = None

This is the target metadata version. If None, it will be computed as a minimum based on the fields set.

all_errors: bool = False

If True, all errors will be collected and raised in an ExceptionGroup.

property auto_metadata_version: str

This computes the metadata version based on the fields set in the object if metadata_version is None.

Return type:

str

property canonical_name: str

Return the canonical name of the project.

Return type:

str

classmethod from_pyproject(data, project_dir='.', metadata_version=None, dynamic_metadata=None, *, allow_extra_keys=None, all_errors=False)[source]

Read metadata from a pyproject.toml table. This is the main method for creating an instance of this class. It also supports two additional fields: allow_extra_keys to control what happens when extra keys are present in the pyproject table, and all_errors, to raise all errors in an ExceptionGroup instead of raising the first one.

Return type:

Self

as_rfc822()[source]

Return an RFC822 message with the metadata.

Return type:

RFC822Message

as_json()[source]

Return a JSON message with the metadata.

Return type:

dict[str, str | list[str]]

validate(*, warn=True)[source]

Validate metadata for consistency and correctness. Will also produce warnings if warn is given. Respects all_errors. This is called when loading a pyproject.toml, and when making metadata. Checks:

  • metadata_version is a known version or None

  • name is a valid project name

  • license_files can’t be used with classic license

  • License classifiers can’t be used with SPDX license

  • description is a single line (warning)

  • license is not an SPDX license expression if metadata_version >= 2.4 (warning)

  • License classifiers deprecated for metadata_version >= 2.4 (warning)

  • license is an SPDX license expression if metadata_version >= 2.4

  • license_files is supported only for metadata_version >= 2.4

  • project_url can’t contain keys over 32 characters

Return type:

None

pyproject_metadata.field_to_metadata(field)[source]

Return the METADATA fields that correspond to a project field.

Return type:

frozenset[str]

pyproject_metadata.extras_build_system(pyproject_table)[source]

Return any extra keys in the build-system table.

Return type:

set[str]

pyproject_metadata.extras_project(pyproject_table)[source]

Return any extra keys in the project table.

Return type:

set[str]

pyproject_metadata.extras_top_level(pyproject_table)[source]

Return any extra keys in the top-level of the pyproject table.

Return type:

set[str]

Submodules

pyproject_metadata.constants module

Constants for the pyproject_metadata package, collected here to make them easy to update. These should be considered mostly private.

pyproject_metadata.errors module

This module defines exceptions and error handling utilities. It is the recommend path to access ConfiguratonError, ConfigurationWarning, and ExceptionGroup. For backward compatibility, ConfigurationError is re-exported in the top-level package.

exception pyproject_metadata.errors.ConfigurationError(msg, *, key=None)[source]

Bases: Exception

Error in the backend metadata. Has an optional key attribute, which will be non-None if the error is related to a single key in the pyproject.toml file.

property key: str | None
Return type:

Optional[str]

exception pyproject_metadata.errors.ConfigurationWarning[source]

Bases: UserWarning

Warnings about backend metadata.

exception pyproject_metadata.errors.ExceptionGroup

Bases: BaseExceptionGroup, Exception

pyproject_metadata.project_table module

This module contains type definitions for the tables used in the pyproject.toml. You should either import this at type-check time only, or make sure typing_extensions is available for Python 3.10 and below.

Documentation notice: the fields with hyphens are not shown due to a sphinx-autodoc bug.

class pyproject_metadata.project_table.BuildSystemTable

Bases: TypedDict

requires: List[str]
class pyproject_metadata.project_table.ContactTable[source]

Bases: TypedDict

name: str
email: str
class pyproject_metadata.project_table.IncludeGroupTable

Bases: TypedDict

class pyproject_metadata.project_table.LicenseTable[source]

Bases: TypedDict

text: str
file: str
class pyproject_metadata.project_table.ProjectTable

Bases: TypedDict

name: Required[str]
version: str
description: str
license: LicenseTable | str
readme: str | ReadmeTable
dependencies: List[str]
authors: List[ContactTable]
maintainers: List[ContactTable]
urls: Dict[str, str]
classifiers: List[str]
keywords: List[str]
scripts: Dict[str, str]
dynamic: List[Literal['authors', 'classifiers', 'dependencies', 'description', 'dynamic', 'entry-points', 'gui-scripts', 'keywords', 'license', 'maintainers', 'optional-dependencies', 'readme', 'requires-python', 'scripts', 'urls', 'version']]
class pyproject_metadata.project_table.PyProjectTable

Bases: TypedDict

project: ProjectTable
tool: Dict[str, Any]
class pyproject_metadata.project_table.ReadmeTable

Bases: TypedDict

file: str
text: str