Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions .bazelrc.deleted_packages
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,6 @@ common --deleted_packages=examples/bzlmod/libs/my_lib
common --deleted_packages=examples/bzlmod/other_module
common --deleted_packages=examples/bzlmod/other_module/other_module/pkg
common --deleted_packages=examples/bzlmod/patches
common --deleted_packages=examples/bzlmod/py_proto_library
common --deleted_packages=examples/bzlmod/py_proto_library/example.com/another_proto
common --deleted_packages=examples/bzlmod/py_proto_library/example.com/proto
common --deleted_packages=examples/bzlmod/py_proto_library/foo_external
common --deleted_packages=examples/bzlmod/runfiles
common --deleted_packages=examples/bzlmod/tests
common --deleted_packages=examples/bzlmod/tests/other_module
Expand Down
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ END_UNRELEASED_TEMPLATE
`true`, a `py_*` target's `pyi_srcs` attribute will be set if any `.pyi` files
that are associated with the target's `srcs` are present.
([#3354](https://github.com/bazel-contrib/rules_python/issues/3354)).
* (zipapp) {obj}`py_zipapp_binary` and {obj}`py_zipapp_test` rules added. These
will replace `--build_python_zip` and the zip output group of
`py_binary/py_test`. The zipapp rules support more functionality, correctness,
and have better build performance.

{#v1-8-2}
## [1.8.2] - 2026-01-24
Expand All @@ -98,6 +102,7 @@ END_UNRELEASED_TEMPLATE
### Fixed
* (pipstar) Extra resolution that refers back to the package being resolved works again.
Fixes [#3524](https://github.com/bazel-contrib/rules_python/issues/3524).
>>>>>>> b4ec825850fb27e5568165d0a388f5cc4b2b84a2

{#v1-8-0}
## [1.8.0] - 2025-12-19
Expand Down
3 changes: 3 additions & 0 deletions docs/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -125,10 +125,13 @@ sphinx_stardocs(
"//python/private/pypi:pkg_aliases_bzl",
"//python/private/pypi:whl_config_setting_bzl",
"//python/private/pypi:whl_library_bzl",
"//python/private/zipapp:py_zipapp_rule_bzl",
"//python/uv:lock_bzl",
"//python/uv:uv_bzl",
"//python/uv:uv_toolchain_bzl",
"//python/uv:uv_toolchain_info_bzl",
"//python/zipapp:py_zipapp_binary_bzl",
"//python/zipapp:py_zipapp_test_bzl",
] + ([
# This depends on @pythons_hub, which is only created under bzlmod,
"//python/extensions:pip_bzl",
Expand Down
1 change: 1 addition & 0 deletions python/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ filegroup(
"//python/runfiles:distribution",
"//python/runtime_env_toolchains:distribution",
"//python/uv:distribution",
"//python/zipapp:distribution",
],
visibility = ["//:__pkg__"],
)
Expand Down
22 changes: 10 additions & 12 deletions python/private/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ filegroup(
"//python/private/cc:distribution",
"//python/private/pypi:distribution",
"//python/private/whl_filegroup:distribution",
"//python/private/zipapp:distribution",
"//tools/build_defs/python/private:distribution",
],
visibility = ["//python:__pkg__"],
Expand Down Expand Up @@ -77,7 +78,9 @@ bzl_library(
":py_info_bzl",
":py_internal_bzl",
":reexports_bzl",
":rule_builders_bzl",
":rules_cc_srcs_bzl",
"@bazel_skylib//lib:dicts",
"@bazel_skylib//rules:common_settings",
],
)
Expand Down Expand Up @@ -366,7 +369,7 @@ bzl_library(
name = "py_cc_toolchain_rule_bzl",
srcs = ["py_cc_toolchain_rule.bzl"],
deps = [
":common_labels.bzl",
":common_labels_bzl",
":py_cc_toolchain_info_bzl",
":rules_cc_srcs_bzl",
":sentinel_bzl",
Expand Down Expand Up @@ -460,7 +463,10 @@ bzl_library(
bzl_library(
name = "py_interpreter_program_bzl",
srcs = ["py_interpreter_program.bzl"],
deps = ["@bazel_skylib//rules:common_settings"],
deps = [
":sentinel_bzl",
"@bazel_skylib//rules:common_settings",
],
)

bzl_library(
Expand Down Expand Up @@ -740,8 +746,8 @@ bzl_library(
srcs = ["venv_runfiles.bzl"],
deps = [
":common_bzl",
":py_info.bzl",
":py_internal.bzl",
":py_info_bzl",
":py_internal_bzl",
"@bazel_skylib//lib:paths",
],
)
Expand Down Expand Up @@ -786,14 +792,6 @@ filegroup(
visibility = ["//visibility:public"],
)

filegroup(
name = "zip_main_template",
srcs = ["zip_main_template.py"],
# Not actually public. Only public because it's an implicit dependency of
# py_runtime.
visibility = ["//visibility:public"],
)

filegroup(
name = "site_init_template",
srcs = ["site_init_template.py"],
Expand Down
119 changes: 119 additions & 0 deletions python/private/common.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
load("@bazel_skylib//lib:paths.bzl", "paths")
load("@rules_cc//cc/common:cc_common.bzl", "cc_common")
load("@rules_cc//cc/common:cc_info.bzl", "CcInfo")
load("//python/private:py_interpreter_program.bzl", "PyInterpreterProgramInfo")
load("//python/private:toolchain_types.bzl", "EXEC_TOOLS_TOOLCHAIN_TYPE")
load(":cc_helper.bzl", "cc_helper")
load(":py_cc_link_params_info.bzl", "PyCcLinkParamsInfo")
load(":py_info.bzl", "PyInfo", "PyInfoBuilder")
Expand Down Expand Up @@ -463,3 +465,120 @@ def collect_deps(ctx, extra_deps = []):
deps = list(deps)
deps.extend(extra_deps)
return deps

def maybe_create_repo_mapping(ctx, *, runfiles):
"""Creates a repo mapping manifest if bzlmod is enabled.

There isn't a way to reference the repo mapping Bazel implicitly
creates, so we have to manually create it ourselves.

Args:
ctx: rule ctx.
runfiles: runfiles object to generate mapping for.

Returns:
File object if the repo mapping manifest was created, None otherwise.
"""
if not py_internal.is_bzlmod_enabled(ctx):
return None

# We have to add `.custom` because `{name}.repo_mapping` is used by Bazel
# internally.
repo_mapping_manifest = ctx.actions.declare_file(ctx.label.name + ".custom.repo_mapping")
py_internal.create_repo_mapping_manifest(
ctx = ctx,
runfiles = runfiles,
output = repo_mapping_manifest,
)
return repo_mapping_manifest

def actions_run(
ctx,
*,
executable,
toolchain = None,
**kwargs):
"""Runs a tool as an action, supporting py_interpreter_program targets.

This is wrapper around `ctx.actions.run()` that sets some useful defaults,
supports handling `py_interpreter_program` targets, and some other features
to let the target being run influence the action invocation.

Args:
ctx: The rule context. The rule must have the
`//python:exec_tools_toolchain_type` toolchain available.
executable: The executable to run. This can be a target that provides
`PyInterpreterProgramInfo` or a regular executable target. If it
provides `testing.ExecutionInfo`, the requirements will be added to
the execution requirements.
toolchain: The toolchain type to use. Must be None or
`//python:exec_tools_toolchain_type`.
**kwargs: Additional arguments to pass to `ctx.actions.run()`.
`mnemonic` and `progress_message` are required.
"""
mnemonic = kwargs.pop("mnemonic", None)
if not mnemonic:
fail("actions_run: missing required argument 'mnemonic'")

progress_message = kwargs.pop("progress_message", None)
if not progress_message:
fail("actions_run: missing required argument 'progress_message'")

tools = kwargs.pop("tools", None)
tools = list(tools) if tools else []
arguments = kwargs.pop("arguments", [])

action_arguments = []
action_env = {
"PYTHONHASHSEED": "0", # Helps avoid non-deterministic behavior
"PYTHONNOUSERSITE": "1", # Helps avoid non-deterministic behavior
"PYTHONSAFEPATH": "1", # Helps avoid incorrect import issues
}
default_info = executable[DefaultInfo]
if PyInterpreterProgramInfo in executable:
if toolchain and toolchain != EXEC_TOOLS_TOOLCHAIN_TYPE:
fail(("Action {}: tool {} provides PyInterpreterProgramInfo, which " +
"requires the `toolchain` arg be " +
"None or {}, got: {}").format(
mnemonic,
executable,
EXEC_TOOLS_TOOLCHAIN_TYPE,
toolchain,
))
exec_tools = ctx.toolchains[EXEC_TOOLS_TOOLCHAIN_TYPE].exec_tools
action_exe = exec_tools.exec_interpreter[DefaultInfo].files_to_run

program_info = executable[PyInterpreterProgramInfo]

interpreter_args = ctx.actions.args()
interpreter_args.add_all(program_info.interpreter_args)
interpreter_args.add(default_info.files_to_run.executable)
action_arguments.append(interpreter_args)

action_env.update(program_info.env)
tools.append(default_info.files_to_run)
toolchain = EXEC_TOOLS_TOOLCHAIN_TYPE
else:
action_exe = executable[DefaultInfo].files_to_run

execution_requirements = {}
if testing.ExecutionInfo in executable:
execution_requirements.update(executable[testing.ExecutionInfo].requirements)

# Give precedence to caller's execution requirements.
execution_requirements.update(kwargs.pop("execution_requirements", None) or {})

# Give precedence to caller's env.
action_env.update(kwargs.pop("env", None) or {})
action_arguments.extend(arguments)
ctx.actions.run(
executable = action_exe,
arguments = action_arguments,
tools = tools,
env = action_env,
execution_requirements = execution_requirements,
toolchain = toolchain,
mnemonic = mnemonic,
progress_message = progress_message,
**kwargs
)
Loading