A method to handle project.dynamic fields generically.
The specification is generic, but currently, it is a feature used only in scikit-build-core.
I.e. for now you must use
[build-system]
requires = ["scikit-build-core"]
build-backend = "scikit_build_core.build"Example¶
[project]
name = "mypackage"
dynamic = ["version"]
[tool.scikit-build]
sdist.include = ["src/package/_version.py"]
[[tool.dynamic-metadata]]
provider = "scikit_build_core.metadata.setuptools_scm"
[tool.setuptools_scm] # Section required
version_file = "src/package/_version.py"[project]
name = "mypackage"
dynamic = ["version"]
[tool.scikit-build]
sdist.include = ["src/package/_version.py"]
metadata.version.provider = "scikit_build_core.metadata.setuptools_scm"
[tool.setuptools_scm] # Section required
version_file = "src/package/_version.py"From the user side¶
Add a field that you want to be resolved dynamically in
project.dynamic[1]Add a
[[tool.dynamic-metadata]]section with aproviderthat can provide that fieldConfigure all other (arbitrary) keys that the provider consumes in
tool.dynamic-metadataor othertool.*Profit?
Pre-defined plugins¶
There are some pre-defined plugins to get you started both in scikit-build-core or dynamic-metadata.
To use the latter, make sure dynamic-metadata is in the build-system.requires.
For an updated documentation check the relevant documentation section in scikit-build-core and dynamic-metadata.
Get version from git metadata
[project]
name = "mypackage"
dynamic = ["version"]
[[tool.dynamic-metadata]]
provider = "scikit_build_core.metadata.setuptools_scm"
[tool.setuptools_scm]dynamic field:
versioninputs:
tool.setuptools_scm
See setuptools-scm
Format a field from a regex search of a file
[project]
name = "mypackage"
dynamic = ["version"]
[[tool.dynamic-metadata]]
provider = "scikit_build_core.metadata.regex"
field = "version"
input = "src/package/_version.py"dynamic field: any, specify in
fieldinputs:
field: The metadata field to setinput: The file to readregex: The pattern to search for (default: match for__version__,VERSION)result:str.formattemplate to generate with the named regex groups (default:{value})remove: A regex to be stripped afterresultis rendered
Format a field from other values in project table
[project]
name = "mypackage"
dynamic = ["version"]
[[tool.dynamic-metadata]]
provider = "scikit_build_core.metadata.template"
field = "dependencies"
result = ["mypackage-core == {project[version]}"]dynamic field: any, specify in
fieldinputs:
field: The metadata field to setresult:str.formattemplate to generate with theprojecttable
Generate a comprehensive readme from snippets or with substitution
[project]
name = "mypackage"
dynamic = ["readme"]
[[tool.dynamic-metadata]]
provider = "scikit_build_core.metadata.fancy_pypi_readme"
[tool.hatch.metadata.hooks.fancy-pypi-readme]dynamic field:
readmeinputs:
[tool.hatch.metadata.hooks.fancy-pypi-readme]
Parse a Python file and use a variable
[project]
name = "mypackage"
dynamic = ["version"]
[[tool.dynamic-metadata]]
provider = "dynamic_metadata.ast"
field = "version"
input = "src/my_package/__init__.py"
name = "__version__"dynamic field: any, specify in
fieldinputs:
field: The metadata field to setinput: The python file to parsename: The global variable to read
Read a file and pass it to the field
[project]
name = "mypackage"
dynamic = ["dependencies"]
[[tool.dynamic-metadata]]
provider = "dynamic_metadata.from_file"
field = "dependencies"
path = "requirements.txt"dynamic field: any, specify in
fieldinputs:
field: The metadata field to setpath: The file to read
Set the field statically
[project]
name = "mypackage"
dynamic = ["version"]
[[tool.dynamic-metadata]]
provider = "dynamic_metadata.static"
version = "1.2.3"dynamic field: any
inputs: any
projectfields
Build a readme from multiple fragments
[project]
name = "mypackage"
dynamic = ["readme"]
[[tool.dynamic-metadata]]
provider = "dynamic_metadata.readme_fragment"
path = "README.md"dynamic field:
readmeinputs:
text: A literal textpath: A file to readcontent-type: The readme content type (default:text/markdown)start-after,end-before: Markers indicating the content (exclusive)start-at,end-at: Markers indicating the content (inclusive)pattern: A regex pattern to capture the fragment
Pin the runtime dependencies to the versions in build-system.requires
[project]
name = "mypackage"
dynamic = ["dependencies"]
[[tool.dynamic-metadata]]
provider = "dynamic_metadata.pin_installed"
packages = ["torch==x.x.*"]dynamic field:
dependenciesinputs:
packages: A list of requirement templates
Apply a regex substitution on the field previously generated
[[tool.dynamic-metadata]]
provider = "dynamic_metadata.substitute"
field = "readme"
pattern = "#(\\d+)"
replacement = "[#\\1](https://github.com/org/repo/issues/\\1)"dynamic field: any, specify in
fieldinputs:
field: The metadata field to transformpattern: The regex pattern to searchreplacement: The regex replacementignore-case: Whether to match case-insensitivelyformat: Whether to resolveproject
Order matters¶
The tool.dynamic-metadata are processed in the order they appear in pyproject.toml.
If a provider expects a dynamic field to have been resolved, make sure you order them appropriately.
1 2 3 4 5 6 7 8 9 10 11 12 13[project] name = "mypackage" dynamic = ["version", "dependencies"] [[tool.dynamic-metadata]] provider = "scikit_build_core.metadata.setuptools_scm" [[tool.dynamic-metadata]] provider = "scikit_build_core.metadata.template" field = "dependencies" result = ["mypackage-core == {project[version]}"] [tool.setuptools_scm]
Want more? Custom plugins¶
You can write your own plugin and use it locally or distribute it via dynamic_metadata.provider entry-point.
[[tool.dynamic-metadata]]
provider = {path = "helpers/plugins", module = "my_plugin"}The referenced module/class must have at least the function
def dynamic_metadata(
settings: Mapping[str, Any],
project: Mapping[str, Any],
) -> dict[str, Any]:
"""
:param settings: all the additional fields defined in the ``[[tool.dynamic-metadata]]``
:param project: current view of the ``[project]``
:return: a ``[project]`` snippet to be merged
"""With PEP 808 you can have mixed static and dynamic fields for table and array fields like
dependencies,scripts