Global Venv
Bazel rules for generating usable virtualenv from Bazel targets.
Usage
A venv can be created by invoking the following command
bazel run @rules_venv//python/global_venv
From here a venv will likely be available at .venv within your workspace that
can be activated for improved IDE support.
Pyright / Pylance
By default, a bazel-pyrightconfig.json is generated with extraPaths pointing to
each Bazel output directory that contains generated Python sources. To use it, add
an extends field to your pyrightconfig.json:
{
"extends": "bazel-pyrightconfig.json"
}
Important: Do not define extraPaths in your own pyrightconfig.json. Pyright's
extends replaces array fields rather than merging them, so any extraPaths in the
child config will override the generated values.
Ruff / isort
Ruff classifies imports as first-party by checking whether the imported module can be
resolved under its src directories. Generated sources (.pyi stubs, .so extensions)
only exist under bazel-out, so ruff needs those directories in src:
# .ruff.toml
src = [".", "bazel-out/k8-*/bin"]
For standalone isort:
# .isort.cfg
[isort]
src_paths = .,bazel-out/k8-*/bin
The glob k8-* covers all Bazel configurations (k8-fastbuild, k8-opt, k8-dbg).
Entrypoints
By default, py_global_venv auto-discovers console_scripts entrypoints from pip
packages (via importlib.metadata) and generates executable scripts in the venv's
bin/ directory. Pre-built binaries shipped via wheel data scripts (e.g. ruff) are
also symlinked into the venv. This allows IDEs to find tools like black, ruff, or
mypy inside the venv.
Additional entrypoints can be specified manually:
py_global_venv(
name = "global_venv",
entrypoints = {
"my_tool": "my.module:cli",
},
)
Auto-discovery can be disabled with gen_entrypoints = False.
Functions
Aspects
py_global_venv
load("@rules_venv//python/global_venv:defs.bzl", "py_global_venv")
py_global_venv(*, name, gen_pyrightconfig, gen_entrypoints, entrypoints, build_srcs, **kwargs)
Define a "global venv" executable.
When gen_pyrightconfig is enabled (the default), running this target
writes a bazel-pyrightconfig.json at the workspace root containing
extraPaths that point into bazel-bin. This lets Pyright/Pylance
resolve generated Python sources that live outside the source tree.
To use it, add an extends field to your pyrightconfig.json::
{
"extends": "bazel-pyrightconfig.json",
...
}
Important: Do not define extraPaths in your own pyrightconfig.json
when using extends. Pyright's extends replaces array fields rather
than merging them, so any extraPaths in the child config will override
the generated values from bazel-pyrightconfig.json.
When targets use configuration transitions (e.g. py_cc_extension building
with compilation_mode = "opt"), generated files may live in directories
like bazel-out/k8-opt/bin instead of bazel-out/k8-fastbuild/bin. The
generated bazel-pyrightconfig.json includes all observed output directories
automatically.
For ruff or isort to correctly classify first-party imports that
include generated sources, add the Bazel output directories to the src
setting::
# .ruff.toml
src = [".", "bazel-out/k8-*/bin"]
For standalone isort::
# .isort.cfg
[isort]
src_paths = .,bazel-out/k8-*/bin
This allows ruff/isort to find generated .pyi stubs and .so extensions
when determining whether an import is first-party or third-party.
When gen_entrypoints is enabled (the default), running this target will
auto-discover console_scripts entrypoints from pip packages via
importlib.metadata and generate executable scripts in the venv's bin/
directory. Pre-built binaries shipped via wheel data scripts (e.g. ruff)
are also symlinked into the venv. This allows IDEs to find tools like
black, ruff, or mypy inside the venv. Additional entrypoints can
be specified manually via entrypoints.
PARAMETERS
py_global_venv_aspect
load("@rules_venv//python/global_venv:defs.bzl", "py_global_venv_aspect")
py_global_venv_aspect()
An aspect for generating metadata required to include Python targets in a global venv.
ASPECT ATTRIBUTES
ATTRIBUTES