fix(py_runtime): make py_runtime_pair return builtin PyRuntimeInfo under Bazel 6; make python_bootstrap_template public (#1611)
This fixes two bugs from
https://github.com/bazelbuild/rules_python/pull/1574:
* Bazel 6's py_binary rejects the rules_python Starlark implemented
PyRuntimeInfo.
* python_bootstrap_template.txt isn't public; this prevents py_runtime
from being
used outside rules_python itself (e.g. in the python toolchain repos)
With Bazel 6, the `py_binary` rule performs a type check of the
PyRuntimeInfo value it gets from the toolchain to verify it is an
instance of the Java-implemented PyRuntimeInfo class. This type check
fails when the provider is implemented in rules_python in Starlark.
To fix, make the `py_runtime_info` prefer the builtin PyRuntimeInfo
provider when running under Bazel 6. The two providers are (currently)
the same, so are mostly interchangable. This satisfies the type check
that `py_binary` performs.
`py_runtime` as an implicit dependency on
`//python/private:python_bootstrap_template.txt`,
but that target is only visible to rules python itself. This means the
py_runtime targets
created in the toolchain repos fail. To fix, make the file public.
Fixes https://github.com/bazelbuild/rules_python/issues/1610
diff --git a/python/private/BUILD.bazel b/python/private/BUILD.bazel
index 4f47206..1793382 100644
--- a/python/private/BUILD.bazel
+++ b/python/private/BUILD.bazel
@@ -266,6 +266,13 @@
visibility = ["//:__subpackages__"],
)
+exports_files(
+ ["python_bootstrap_template.txt"],
+ # Not actually public. Only public because it's an implicit dependency of
+ # py_runtime.
+ visibility = ["//visibility:public"],
+)
+
# Used to determine the use of `--stamp` in Starlark rules
stamp_build_setting(name = "stamp")
diff --git a/python/private/py_runtime_pair_rule.bzl b/python/private/py_runtime_pair_rule.bzl
index 574e1fe..e7b7867 100644
--- a/python/private/py_runtime_pair_rule.bzl
+++ b/python/private/py_runtime_pair_rule.bzl
@@ -16,6 +16,7 @@
load("//python:py_runtime_info.bzl", "PyRuntimeInfo")
load("//python/private:reexports.bzl", "BuiltinPyRuntimeInfo")
+load("//python/private:util.bzl", "IS_BAZEL_7_OR_HIGHER")
def _py_runtime_pair_impl(ctx):
if ctx.attr.py2_runtime != None:
@@ -45,7 +46,11 @@
)]
def _get_py_runtime_info(target):
- if PyRuntimeInfo in target:
+ # Prior to Bazel 7, the builtin PyRuntimeInfo object must be used because
+ # py_binary (implemented in Java) performs a type check on the provider
+ # value to verify it is an instance of the Java-implemented PyRuntimeInfo
+ # class.
+ if IS_BAZEL_7_OR_HIGHER and PyRuntimeInfo in target:
return target[PyRuntimeInfo]
else:
return target[BuiltinPyRuntimeInfo]
diff --git a/tests/py_runtime_pair/py_runtime_pair_tests.bzl b/tests/py_runtime_pair/py_runtime_pair_tests.bzl
index 74da181..236f1ba 100644
--- a/tests/py_runtime_pair/py_runtime_pair_tests.bzl
+++ b/tests/py_runtime_pair/py_runtime_pair_tests.bzl
@@ -17,6 +17,7 @@
load("@rules_testing//lib:test_suite.bzl", "test_suite")
load("@rules_testing//lib:truth.bzl", "matching", "subjects")
load("@rules_testing//lib:util.bzl", rt_util = "util")
+load("//python:py_binary.bzl", "py_binary")
load("//python:py_runtime.bzl", "py_runtime")
load("//python:py_runtime_pair.bzl", "py_runtime_pair")
load("//python/private:reexports.bzl", "BuiltinPyRuntimeInfo") # buildifier: disable=bzl-visibility
@@ -99,6 +100,46 @@
_tests.append(_test_builtin_py_info_accepted)
+def _test_py_runtime_pair_and_binary(name):
+ rt_util.helper_target(
+ py_runtime,
+ name = name + "_runtime",
+ interpreter_path = "/fake_interpreter",
+ python_version = "PY3",
+ )
+ rt_util.helper_target(
+ py_runtime_pair,
+ name = name + "_pair",
+ py3_runtime = name + "_runtime",
+ )
+ native.toolchain(
+ name = name + "_toolchain",
+ toolchain = name + "_pair",
+ toolchain_type = "//python:toolchain_type",
+ )
+ rt_util.helper_target(
+ py_binary,
+ name = name + "_subject",
+ srcs = [name + "_subject.py"],
+ )
+ analysis_test(
+ name = name,
+ target = name + "_subject",
+ impl = _test_py_runtime_pair_and_binary_impl,
+ config_settings = {
+ "//command_line_option:extra_toolchains": [
+ "//tests/py_runtime_pair:{}_toolchain".format(name),
+ "//tests/cc:all",
+ ],
+ },
+ )
+
+def _test_py_runtime_pair_and_binary_impl(env, target):
+ # Building indicates success, so nothing to assert
+ _ = env, target # @unused
+
+_tests.append(_test_py_runtime_pair_and_binary)
+
def py_runtime_pair_test_suite(name):
test_suite(
name = name,