Hatch plugin that adds a packaging extra to the wheel metadata with pinned dependencies from uv.lock.
# pyproject.toml
[build-system]
requires = [
"hatchling",
"hatch-pinned-extra>=0.0.1,<0.1.0",
]
build-backend = "hatchling.build"
[tool.hatch.metadata.hooks.pinned_extra]
name = "pinned"If your package doesn't have any optional dependencies already, you will need to mark them as dynamic:
# pyproject.toml
[project]
dynamic = [
"optional-dependencies",
]To use a pylock.toml file instead of uv.lock, set lockfile to the file path:
[tool.hatch.metadata.hooks.pinned_extra]
lockfile = "pylock.prod.toml"Note
The pinned will contain ALL the dependencies in pylock.toml, so you'll want to make sure it includes only runtime or relevant dependencies, e.g. by generating it with the --no-dev flag.
Note
pylock.toml files may produce less precise environment markers than uv.lock because the
pylock format does not carry the resolver's internal per-Python-version splits. For example,
a uv.lock-derived pinned requirement might read
anyio==4.13.0; python_full_version >= "3.13" or (python_full_version >= "3.10" and python_full_version < "3.13")
while the equivalent from a pylock.toml would be anyio==4.13.0; python_full_version >= "3.10".
The plugin requires the HATCH_PINNED_EXTRA_ENABLE environment variable to be set to a truthy value to activate (e.g. 1, true, yes, on). This design allows you to control when pinned dependencies are included:
# Build with pinned dependencies
HATCH_PINNED_EXTRA_ENABLE=1 uv build
# Update lockfile without constraints from pinned dependencies
uv lock --upgradeThis approach solves the circular dependency issue where pinned dependencies become constraints during uv lock --upgrade, preventing actual upgrades.