3.5 KiB
How to configure custom dynamic metadata
If you have project metadata that is not appropriate for static entry into pyproject.toml
you will need to provide a custom metadata hook to apply such data during builds.
!!! abstract "Alternatives" Dynamic metadata is a way to have a single source of truth that will be available at build time and at run time. Another way to achieve that is to enter the build data statically and then look up the same information dynamically in the program or package, using importlib.metadata.
If the [version field](../../config/metadata.md#version) is the only metadata of concern, Hatchling provides a few built-in ways such as the [`regex` version source](../../plugins/version-source/regex.md) and also [third-party plugins](../../plugins/version-source/reference.md). The approach here will also work, but is more complex.
Update project metadata
Change the [project]
section of pyproject.toml
:
- Define the dynamic field as an array of all the fields you will set dynamically e.g.
dynamic = ["version", "license", "authors", "maintainers"]
- If any of those fields have static definitions in
pyproject.toml
, delete those definitions. It is verboten to define a field statically and dynamically.
Add a section to trigger loading of dynamic metadata plugins: [tool.hatch.metadata.hooks.custom]
. Use exactly that name, regardless of the name of the class you will use or its PLUGIN_NAME
. There doesn't need to be anything in the section.
If your plugin requires additional third-party packages to do its work, add them to the requires
array in the [build-system]
section of pyproject.toml
.
Implement hook
The dynamic lookup must happen in a custom plugin that you write. The default expectation is that it is in a hatch_build.py
file at the root of the project. Subclass MetadataHookInterface
and implement update()
; for example, here's plugin that reads metadata from a JSON file:
import json
import os
from hatchling.metadata.plugin.interface import MetadataHookInterface
class JSONMetaDataHook(MetadataHookInterface):
def update(self, metadata):
src_file = os.path.join(self.root, "gnumeric", ".constants.json")
with open(src_file) as src:
constants = json.load(src)
metadata["version"] = constants["__version__"]
metadata["license"] = constants["__license__"]
metadata["authors"] = [
{"name": constants["__author__"], "email": constants["__author_email__"]},
]
- You must import the MetadataHookInterface to subclass it.
- Do your operations inside the
update
method. metadata
refers to project metadata.- When writing to metadata, use
list
for TOML arrays. Note that if a list is expected, it is required even if there is a single element. - Use
dict
for TOML tables e.g.authors
.
If you want to store the hook in a different location, set the path
option:
[tool.hatch.metadata.hooks.custom]
path = "some/where.py"