API reference

Loader

The driver consumed by build backends.

class dynamic_metadata.loader.Resolved(project, dynamic_fields=frozenset({}))

The result of resolve().

Parameters:
dynamic_fields: frozenset[str] = frozenset({})

For an SDist build, the fields whose value may differ in a wheel built from it (METADATA 2.2 Dynamic); empty for every other build state.

property dynamic_headers: tuple[str, ...]

dynamic_fields as sorted core-metadata header names (Dynamic: values).

project: dict[str, Any]

The new [project] table. Fields a provider produced are removed from dynamic, as are the SDist-dynamic fields below.

dynamic_metadata.loader.dynamic_wheel_fields(entries)

Collect the fields to mark Dynamic in SDist metadata (METADATA 2.2).

Asks each provider’s optional dynamic_wheel hook which fields may legitimately differ between the SDist and a wheel built from it. A field is dynamic if any provider reports it True: contributions to a field merge, so one dynamic part makes the merged value dynamic (PEP 643 permits marking a field Dynamic even when its value is also given). A field no provider mentions is not dynamic, and version may never be.

Providers are loaded fresh here, so dynamic_wheel cannot rely on state from a dynamic_metadata call.

Parameters:

entries (Sequence[Mapping[str, Any]])

Return type:

set[str]

dynamic_metadata.loader.entries_from_pyproject(pyproject)

Return the validated [[tool.dynamic-metadata]] entries of a parsed pyproject.toml.

Returns [] if the table is absent. Raises ConfigError if it is not an array of tables or an entry lacks provider.

Parameters:

pyproject (Mapping[str, Any])

Return type:

list[dict[str, Any]]

dynamic_metadata.loader.get_requires_for_dynamic_metadata(entries)

Collect every provider’s extra build requirements, in entry order.

Call this from each PEP 517 get_requires_for_build_* hook. A provider without the optional get_requires_for_dynamic_metadata hook contributes nothing.

A provider that is found but fails to import — typically because it imports at module level a package it would have declared as its own requirement — is skipped, since its hook cannot be asked; the import error surfaces later, when the metadata is resolved. An unknown provider name or a missing local module still raises.

Parameters:

entries (Sequence[Mapping[str, Any]])

Return type:

list[str]

dynamic_metadata.loader.load_dynamic_metadata(entries)

Load each entry’s provider, yielding it with its plugin settings.

Entries are processed in order; provider is consumed here and the remaining keys are returned as plugin settings.

Parameters:

entries (Sequence[Mapping[str, Any]])

Return type:

Generator[tuple[DynamicMetadataProtocol, dict[str, Any]], None, None]

dynamic_metadata.loader.load_provider(provider)

Load a provider from its config value, returning the object whose hooks are called.

provider is the value of the provider key in a [[tool.dynamic-metadata]] entry, in one of two forms:

  • a string — a name registered in the PROVIDER_GROUP entry-point group. Installed plugins are only reachable this way; a raw import path is not accepted.

  • an inline table {path, module} — a local plugin imported from the path directory as a module path ("pkg.mod" or "pkg.mod:Class"), for a plugin living inside the project being built. Entry points are not consulted.

A bare module is returned as-is (hooks are module-level functions); a class is instantiated with no arguments so its hooks are bound methods sharing state through self; an already-instantiated object is used directly.

Parameters:

provider (object)

Return type:

DynamicMetadataProtocol

dynamic_metadata.loader.process_dynamic_metadata(project, entries, build_state)

Process dynamic metadata.

Takes the original [project] table and an ordered list of [[tool.dynamic-metadata]] entries, and returns a new project table. Entries run in list order: each provider is called with a read-only snapshot of the project as resolved so far, so a later entry can read a field an earlier one produced via project[...]. A provider returns a dict fragment of the project table ({field: value, ...}) which is merged in.

build_state is the backend’s description of the current build. It must be one of these build states (BUILD_STATES): "sdist", "wheel", "editable", "metadata_wheel", or "metadata_editable". A provider that cares about it implements an optional build_state hook, called with this value before dynamic_metadata; providers that ignore it simply omit the hook.

Parameters:
Return type:

dict[str, Any]

dynamic_metadata.loader.resolve(pyproject, build_state, *, backend_fields=(), strict=True)

Resolve a whole parsed pyproject.toml, handling the dynamic bookkeeping.

This is entries_from_pyproject(), process_dynamic_metadata(), and (for "sdist") dynamic_wheel_fields() in one call. If there are no entries the [project] table is returned unchanged ({} if absent); if there are entries but no [project] table, ConfigError is raised.

For an SDist build, the fields the providers report as wheel-dynamic are removed from dynamic (so the PKG-INFO is valid) and returned as dynamic_fields for the backend to write as Dynamic: headers.

With strict (the default), a field still listed in dynamic after that — declared dynamic but produced by no provider — raises ConfigError, unless it is in backend_fields, the fields the backend fills in itself (for example version read from a build file).

Parameters:
Return type:

Resolved

Errors

Exceptions raised by dynamic_metadata.loader.

Every error the loader raises itself derives from DynamicMetadataError, so a backend can translate them all with one except clause. The subclasses also keep a standard base (ValueError, ImportError, …) so existing handlers keep working. An exception raised inside a provider’s hook is not wrapped and propagates unchanged.

exception dynamic_metadata.errors.ConfigError

Bases: DynamicMetadataError, ValueError

The [[tool.dynamic-metadata]] configuration (or a loader argument) is invalid.

exception dynamic_metadata.errors.DynamicMetadataError

Bases: Exception

Base class for every error the loader raises.

exception dynamic_metadata.errors.InvalidFieldError

Bases: DynamicMetadataError, ValueError

A provider returned a field that cannot be set, or set it in an invalid way.

exception dynamic_metadata.errors.ProviderLoadError

Bases: DynamicMetadataError, ImportError

The provider was found but importing it failed (for example a missing dependency).

exception dynamic_metadata.errors.ProviderNotFoundError

Bases: DynamicMetadataError, ModuleNotFoundError

No provider is registered under the given name, or the local module is missing.

Plugin protocols

The protocols a provider may implement. Every provider satisfies DynamicMetadataProtocol; the others add optional hooks.

class dynamic_metadata.protocols.DynamicMetadataProtocol(*args, **kwargs)
class dynamic_metadata.protocols.DynamicMetadataBuildStateProtocol(*args, **kwargs)
class dynamic_metadata.protocols.DynamicMetadataRequirementsProtocol(*args, **kwargs)
class dynamic_metadata.protocols.DynamicMetadataWheelProtocol(*args, **kwargs)

Field taxonomy

The single source of truth for which [project] fields can be dynamic and what shape their value has.

Plugin helpers

Shared helpers that bundled and third-party plugins can reuse.

Schema

dynamic_metadata.schema.get_schema()
Return type:

dict[str, Any]