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().

Create a new message with RFC822Policy.

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

Will always handle 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]

Require known headers, and replace newlines with spaces.

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>, import_names=None, import_namespaces=None, 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]
import_names: list[str] | None = None
import_namespaces: list[str] | None = None
dynamic: list[Literal['authors', 'classifiers', 'dependencies', 'description', 'dynamic', 'entry-points', 'gui-scripts', 'keywords', 'license', 'maintainers', 'optional-dependencies', 'readme', 'requires-python', 'scripts', 'urls', 'version', 'import-names', 'import-namespaces']]

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.

property canonical_name: str

Return the canonical name of the project.

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

  • import-name(paces)s is only supported on metadata_version >= 2.5

  • import-name(space)s must be valid names, optionally with ; private

  • import-names and import-namespaces cannot overlap.

Return type:

None

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]

pyproject_metadata.field_to_metadata(field)[source]

Return the METADATA fields that correspond to a project field.

Return type:

frozenset[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.

Create a new error with a key (can be None).

property key: str | None

Return the stored key.

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

Can have either name or email.

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

Bases: TypedDict

class pyproject_metadata.project_table.LicenseTable[source]

Bases: TypedDict

Can have either text or file. Legacy.

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', 'import-names', 'import-namespaces']]
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