uv (Python dependency manager)
The repo manages its top-level Python dependencies with uv. The
nested buildscripts/bazel_rules_mongo/ package still uses Poetry — see its own
pyproject.toml/poetry.lock for that lifecycle.
What lives where
| File | Purpose |
|---|---|
pyproject.toml |
Source of truth. Declares deps under [project.dependencies] and PEP 735 [dependency-groups], plus uv-specific config under [tool.uv.*]. |
uv.lock |
Pinned resolution of pyproject.toml. Generated by uv lock --static-urls (rules_pycross requires per-wheel URLs). Cross-platform via PEP 508 markers. |
bazel/uv/defs.bzl |
Compatibility shim exposing dependency(name, group=None) → @pypi//<name>, matching the prior rules_poetry call sites verbatim. |
buildscripts/uv_sync.sh |
Workstation/CI bootstrap. Installs the pinned uv into the active venv and runs uv sync --all-groups --no-install-project. |
buildscripts/uv_version.txt |
Pinned uv version (kept in sync with [tool.uv] in pyproject.toml). |
buildscripts/uv_lock_check.py |
Pre-submit check: fails if uv.lock is stale relative to pyproject.toml. |
Workflows
Edit a dependency
- Modify
pyproject.tomlunder[project.dependencies]or one of the[dependency-groups]tables. buildscripts/uv_sync.sh -f— refreshesuv.lock(uses--static-urls).- Commit
pyproject.tomlanduv.locktogether.
Populate the workstation venv
source python3-venv/bin/activate
buildscripts/uv_sync.sh
Reference a dependency from BUILD.bazel
load("//bazel/uv:defs.bzl", "dependency")
py_library(
name = "...",
deps = [
dependency("pyyaml"),
dependency("boto3", group = "aws"), # group arg is accepted but ignored at build time
],
)
The group kwarg is preserved from the prior rules_poetry API for source compatibility. All
groups are merged into the single @pypi hub; the package label is the same regardless of group.
Add/skip groups at install time
# `--active` targets the activated venv; without it (or
# UV_PROJECT_ENVIRONMENT) uv installs into `<repo>/.venv`.
# `--locked` refuses to run if uv.lock is stale instead of rewriting it.
uv sync --active --locked --all-groups # everything (default for dev)
uv sync --active --locked --only-group lint # just the lint group
uv sync --active --locked --all-groups --no-group powercycle-incompatible # powercycle remote setup
Bazel integration
MODULE.bazel uses rules_pycross's
lock_import.import_uv extension to consume uv.lock directly:
pyproject.toml + uv.lock
│
│ lock_import.import_uv(lock_file = "//:uv.lock", repo = "pypi") (MODULE.bazel)
▼
@pypi//<package> (http_file for wheels, pycross_wheel_build for sdists)
▲
│ //bazel/uv:defs.bzl::dependency()
│
BUILD.bazel: deps = [ dependency("pyyaml") ]
Wheels resolve to http_file targets (remote-cacheable). Sdists become pycross_wheel_build
actions (real Bazel actions — remote-executable). Both consume the URLs and hashes baked into
uv.lock; no per-build simple-index fetch.
Why uv
- Speed:
uv syncanduv lockare an order of magnitude faster than Poetry. - Single Rust binary — no pip/python startup tax.
- PEP 735 native — dependency groups are a standardized concept.
- Preserves cross-platform resolution via PEP 508 markers (Linux x86_64 / aarch64 / ppc64le / s390x, macOS x86_64 / arm64, Windows x86_64).