Hatchling Auto Extras Hook (Custom Metadata Hook Pattern)

0.1.3 · active · verified Tue Apr 14

This entry describes a common pattern for creating a custom metadata hook within Hatchling (version 1.x), enabling automatic generation or modification of project extras. While 'hatchling-autoextras-hook' exists as a PyPI package, its low version and lack of dedicated documentation suggest it's more of an illustrative or niche implementation rather than a widely used standalone plugin. The typical approach involves implementing a custom metadata hook using `hatchling` itself, which allows dynamic modification of project metadata during the build process, including `optional-dependencies` (extras). Hatchling is a modern, extensible build backend for Python projects, with a rapid release cadence.

Warnings

Install

Imports

Quickstart

This example demonstrates how to set up a custom metadata hook (`hatch_build.py`) to dynamically add or modify extras (optional-dependencies) in your `pyproject.toml`. The `dynamic = ["optional-dependencies"]` declaration is crucial. The hook's `update` method receives the project's metadata and can modify it in-place. Configuration can be passed to the hook via `pyproject.toml`.

# pyproject.toml
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "my-project"
version = "0.1.0"
dynamic = ["optional-dependencies"]

[tool.hatch.metadata.hooks.custom]
path = "hatch_build.py"

# hatch_build.py
from hatchling.metadata.plugin.interface import MetadataHookInterface

class CustomMetadataHook(MetadataHookInterface):
    PLUGIN_NAME = 'custom' # This name is fixed for custom hooks defined via `path`

    def update(self, metadata: dict) -> None:
        # Example: dynamically generate 'docs' extra
        if 'docs' not in metadata.get('optional-dependencies', {}):
            metadata.setdefault('optional-dependencies', {})
            metadata['optional-dependencies']['docs'] = [
                "sphinx>=5.0",
                "myst-parser",
            ]
        
        # Example: dynamically generate 'testing' extra based on some logic
        if 'TEST_ENV' in self.config: # Access hook configuration
            metadata.setdefault('optional-dependencies', {})
            metadata['optional-dependencies']['testing'] = [
                "pytest>=7.0",
                "pytest-cov",
            ]

# To see effect, you would typically run:
# hatch build

view raw JSON →