From 8eb6bf3f27ec7b0a7e41484e29ce9537cc59fe41 Mon Sep 17 00:00:00 2001 From: Richard Levasseur Date: Tue, 25 Oct 2022 10:57:43 -0700 Subject: [PATCH] Implement most of py_runtime in Starlark Work towards #15897 PiperOrigin-RevId: 483722548 Change-Id: Ieee7859e516a946286eeb07f9a86d1ea2b159aa0 --- .../lib/rules/python/PythonConfiguration.java | 13 ++++ .../common/python/py_runtime_rule.bzl | 65 ++++++++++++++++++- 2 files changed, 76 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/google/devtools/build/lib/rules/python/PythonConfiguration.java b/src/main/java/com/google/devtools/build/lib/rules/python/PythonConfiguration.java index 8ca5334e769caa..596cf386f0991d 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/python/PythonConfiguration.java +++ b/src/main/java/com/google/devtools/build/lib/rules/python/PythonConfiguration.java @@ -25,6 +25,7 @@ import com.google.devtools.common.options.TriState; import javax.annotation.Nullable; import net.starlark.java.annot.StarlarkBuiltin; +import net.starlark.java.annot.StarlarkMethod; import net.starlark.java.eval.StarlarkValue; /** @@ -95,6 +96,14 @@ public PythonVersion getDefaultPythonVersion() { return defaultVersion; } + @StarlarkMethod( + name = "default_python_version", + structField = true, + doc = "The default python version from --incompatible_py3_is_default") + public String getDefaultPythonVersionForStarlark() { + return defaultVersion.name(); + } + @Override @Nullable public String getOutputDirectoryName() { @@ -140,6 +149,10 @@ public boolean buildTransitiveRunfilesTrees() { * Returns true if executable Python rules should obtain their runtime from the Python toolchain * rather than legacy flags. */ + @StarlarkMethod( + name = "use_toolchains", + structField = true, + doc = "The value from the --incompatible_use_python_toolchains flag") public boolean useToolchains() { return useToolchains; } diff --git a/src/main/starlark/builtins_bzl/common/python/py_runtime_rule.bzl b/src/main/starlark/builtins_bzl/common/python/py_runtime_rule.bzl index 3b15dedc3f5549..19aff9059d6f98 100644 --- a/src/main/starlark/builtins_bzl/common/python/py_runtime_rule.bzl +++ b/src/main/starlark/builtins_bzl/common/python/py_runtime_rule.bzl @@ -13,9 +13,70 @@ # limitations under the License. """Implementation of py_runtime rule.""" +load(":common/paths.bzl", "paths") + +_PyRuntimeInfo = _builtins.toplevel.PyRuntimeInfo + def _py_runtime_impl(ctx): - _ = ctx # @unused - fail("not implemented") + interpreter_path = ctx.attr.interpreter_path + interpreter = ctx.file.interpreter + if (interpreter_path and interpreter) or (not interpreter_path and not interpreter): + fail("exactly one of the 'interpreter' or 'interpreter_path' attributes must be specified") + + hermetic = bool(interpreter) + runtime_files = ctx.attr.files[DefaultInfo].files + if not hermetic: + if runtime_files: + fail("if 'interpreter_path' is given then 'files' must be empty") + if not paths.is_absolute(interpreter_path): + fail("interpreter_path must be an absolute path") + + if ctx.attr.coverage_tool: + coverage_di = ctx.attr.coverage_tool[DefaultInfo] + + # TODO(b/254866025): Use a Java helper to call NestedSet.isSingleton + # instead of always flattening to a list + coverage_di_files = coverage_di.files.to_list() + if len(coverage_di_files) == 1: + coverage_tool = coverage_di_files[0] + elif coverage_di.files_to_run and coverage_di.files_to_run.executable: + coverage_tool = coverage_di.files_to_run.executable + else: + fail("coverage_tool must be an executable target or must produce exactly one file.") + + coverage_files = depset(transitive = [ + coverage_di.files, + coverage_di.default_runfiles.files, + ]) + else: + coverage_tool = None + coverage_files = None + + python_version = ctx.attr.python_version + if python_version == "_INTERNAL_SENTINEL": + if ctx.fragments.py.use_toolchains: + fail( + "When using Python toolchains, this attribute must be set explicitly to either 'PY2' " + + "or 'PY3'. See https://github.com/bazelbuild/bazel/issues/7899 for more " + + "information. You can temporarily avoid this error by reverting to the legacy " + + "Python runtime mechanism (`--incompatible_use_python_toolchains=false`).", + ) + else: + python_version = ctx.fragments.default_python_version + + return [ + _PyRuntimeInfo( + files = runtime_files, + coverage_tool = coverage_tool, + coverage_files = coverage_files, + python_version = python_version, + stub_shebang = ctx.attr.stub_shebang, + ), + DefaultInfo( + files = runtime_files, + runfiles = ctx.runfiles(), + ), + ] # Bind to the name "py_runtime" to preserve the kind/rule_class it shows up # as elsewhere.