From ee53da780787658626a038104e89ed4182c4c9e3 Mon Sep 17 00:00:00 2001 From: Richard Levasseur Date: Thu, 3 Nov 2022 15:26:03 -0700 Subject: [PATCH] Implement PyRuntimeInfo in Starlark This is a basic transcription of the PyRuntimeInfo class; it isn't enabled, used, or tested yet. Subsequent changes will address test failures. Work towards #15897 PiperOrigin-RevId: 485988691 Change-Id: Ic42b03bc6b82d04742273b6a7f331665dd91aee5 --- .../builtins_bzl/common/python/providers.bzl | 88 ++++++++++++++++++- .../common/python/py_runtime_rule.bzl | 5 +- 2 files changed, 89 insertions(+), 4 deletions(-) diff --git a/src/main/starlark/builtins_bzl/common/python/providers.bzl b/src/main/starlark/builtins_bzl/common/python/providers.bzl index c916b11a2592b3..1c365a96f4e4b7 100644 --- a/src/main/starlark/builtins_bzl/common/python/providers.bzl +++ b/src/main/starlark/builtins_bzl/common/python/providers.bzl @@ -12,5 +12,91 @@ # See the License for the specific language governing permissions and # limitations under the License. """Providers for Python rules.""" -PyRuntimeInfo = _builtins.toplevel.PyRuntimeInfo + +DEFAULT_STUB_SHEBANG = "#!/usr/bin/env python3" +_PYTHON_VERSION_VALUES = ["PY2", "PY3"] + +def _PyRuntimeInfo_init( + *, + interpreter_path = None, + interpreter = None, + files = None, + coverage_tool = None, + coverage_files = None, + python_version, + stub_shebang = None): + if (interpreter_path == None) == (interpreter == None): + fail("exactly one of interpreter_path or interpreter must be set") + if (interpreter == None) != (files == None): + fail("interpreter and files must both be set or neither must be set") + if (coverage_tool == None) == (coverage_files == None): + fail("coverage_tool and coverage_files must both be set or neither must be set") + if python_version not in _PYTHON_VERSION_VALUES: + fail("invalid python_version: '{}'; must be one of {}".format( + python_version, + _PYTHON_VERSION_VALUES, + )) + if not stub_shebang: + stub_shebang = DEFAULT_STUB_SHEBANG + return { + "interpreter_path": interpreter_path, + "interpreter": interpreter, + "files": files, + "coverage_tool": coverage_tool, + "coverage_files": coverage_files, + "python_version": python_version, + "stub_shebang": stub_shebang, + } + +PyRuntimeInfo, _unused_raw_py_runtime_info_ctor = provider( + doc = """Contains information about a Python runtime, as returned by the `py_runtime` +rule. + +A Python runtime describes either a *platform runtime* or an *in-build runtime*. +A platform runtime accesses a system-installed interpreter at a known path, +whereas an in-build runtime points to a `File` that acts as the interpreter. In +both cases, an "interpreter" is really any executable binary or wrapper script +that is capable of running a Python script passed on the command line, following +the same conventions as the standard CPython interpreter. +""", + init = _PyRuntimeInfo_init, + fields = { + "interpreter_path": ( + "If this is a platform runtime, this field is the absolute " + + "filesystem path to the interpreter on the target platform. " + + "Otherwise, this is `None`." + ), + "interpreter": ( + "If this is an in-build runtime, this field is a `File` representing " + + "the interpreter. Otherwise, this is `None`. Note that an in-build " + + "runtime can use either a prebuilt, checked-in interpreter or an " + + "interpreter built from source." + ), + "files": ( + "If this is an in-build runtime, this field is a `depset` of `File`s" + + "that need to be added to the runfiles of an executable target that " + + "uses this runtime (in particular, files needed by `interpreter`). " + + "The value of `interpreter` need not be included in this field. If " + + "this is a platform runtime then this field is `None`." + ), + "coverage_tool": ( + "If set, this field is a `File` representing tool used for collecting code coverage information from python tests. Otherwise, this is `None`." + ), + "coverage_files": ( + "The files required at runtime for using `coverage_tool`. " + + "Will be `None` if no `coverage_tool` was provided." + ), + "python_version": ( + "Indicates whether this runtime uses Python major version 2 or 3. " + + "Valid values are (only) `\"PY2\"` and " + + "`\"PY3\"`." + ), + "stub_shebang": ( + "\"Shebang\" expression prepended to the bootstrapping Python stub " + + "script used when executing `py_binary` targets. Does not " + + "apply to Windows." + ), + }, +) + PyInfo = _builtins.toplevel.PyInfo 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 b59aaeec7f8104..3c645a7ae124d6 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 @@ -14,6 +14,7 @@ """Implementation of py_runtime rule.""" load(":common/paths.bzl", "paths") +load(":common/python/providers.bzl", "DEFAULT_STUB_SHEBANG") _PyRuntimeInfo = _builtins.toplevel.PyRuntimeInfo @@ -169,9 +170,7 @@ value. """, ), "stub_shebang": attr.string( - # TODO(b/254866025): Have PyRuntimeInfo and this use a shared - # constant - default = "#!/usr/bin/env python3", + default = DEFAULT_STUB_SHEBANG, doc = """ "Shebang" expression prepended to the bootstrapping Python stub script used when executing `py_binary` targets.