Lock
Note
Currently rules_python only supports requirements.txt format.
##2787 issue tracks pylock.toml support.
requirements.txt
pip compile
Generally, when working on a Python project, you’ll have some dependencies that themselves have other dependencies. You might also specify dependency bounds instead of specific versions. So you’ll need to generate a full list of all transitive dependencies and pinned versions for every dependency.
Typically, you’d have your project dependencies specified in pyproject.toml or requirements.in
and generate the full pinned list of dependencies in requirements_lock.txt, which you can
manage with compile_pip_requirements:
load("@rules_python//python:pip.bzl", "compile_pip_requirements")
compile_pip_requirements(
name = "requirements",
src = "requirements.in",
requirements_txt = "requirements_lock.txt",
)
This rule generates two targets:
bazel run [name].updatewill regenerate therequirements_txtfilebazel test [name]_testwill test that therequirements_txtfile is up to date
Once you generate this fully specified list of requirements, you can install the requirements (bzlmod/WORKSPACE).
Warning
If you’re specifying dependencies in pyproject.toml, make sure to include the
[build-system] configuration, with pinned dependencies.
compile_pip_requirements will use the build system specified to read your
project’s metadata, and you might see non-hermetic behavior if you don’t pin the
build system.
Not specifying [build-system] at all will result in using a default
[build-system] configuration, which uses unpinned versions
(ref).
pip compile Dependency groups
pip-compile doesn’t yet support pyproject.toml dependency groups. Follow pip-tools #2062 to see the status of their support.
In the meantime, support can be emulated by passing multiple files to srcs:
compile_pip_requirements(
srcs = ["pyproject.toml", "requirements-dev.in"]
...
)
uv pip compile (bzlmod only)
We also have an experimental setup for the uv pip compile way of generating lock files.
This is well tested with the public PyPI index, but you may hit some rough edges with private
mirrors.
Example usage
load("@rules_python//python/uv:lock.bzl", "lock")
lock(
name = "requirements",
srcs = ["pyproject.toml", "requirements.in"],
out = "requirements_lock.txt",
)
[tool.uv] settings from pyproject.toml
When a pyproject.toml file is among the lock.srcs, the
lock rule auto-detects the project directory and passes
--project <dir> to uv pip compile. This causes uv to read
[tool.uv] settings from that pyproject.toml, such as
no-build-isolation, exclude-dependencies, and workspace members.
If multiple pyproject.toml files are in lock.srcs, the one
with the shortest directory path is selected (this heuristic works for
typical uv workspace layouts where the root configuration is at the
shortest path).
If the auto-detection picks the wrong project directory, use the
project parameter to override:
lock(
name = "requirements",
srcs = ["pyproject.toml", "requirements.in"],
out = "requirements_lock.txt",
project = "subproject",
)
Warning
Known limitations of auto-detection
Workspace heuristic — the shortest-path selection may incorrectly assume the upper-most workspace
pyproject.tomlis the correct one. For monorepos with multiple independent sub-projects, you must setprojectexplicitly for eachlocktarget.No test target — unlike
compile_pip_requirements, no test target is auto-created; see thelockdocs for how to add one manually usingdiff_testfrombazel_skylib.
For more documentation see lock.