Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: default py_runtime version info to --python_version #2198

Merged
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: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ A brief description of the categories of changes:
* (gazelle): Update error messages when unable to resolve a dependency to be more human-friendly.
* (flags) The {obj}`--python_version` flag now also returns
{obj}`config_common.FeatureFlagInfo`.
* (toolchains) When {obj}`py_runtime.interpreter_version_info` isn't specified,
the {obj}`--python_version` flag will determine the value. This allows
specifying the build-time Python version for the
{obj}`runtime_env_toolchains`.
* (toolchains) {obj}`py_cc_toolchain.libs` and {obj}`PyCcToolchainInfo.libs` is
optional. This is to support situations where only the Python headers are
available.
Expand Down
47 changes: 36 additions & 11 deletions python/private/common/py_runtime_rule.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

load("@bazel_skylib//lib:dicts.bzl", "dicts")
load("@bazel_skylib//lib:paths.bzl", "paths")
load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo")
load("//python/private:reexports.bzl", "BuiltinPyRuntimeInfo")
load("//python/private:util.bzl", "IS_BAZEL_7_OR_HIGHER")
load(":attributes.bzl", "NATIVE_RULES_ALLOWLIST_ATTRS")
Expand Down Expand Up @@ -80,6 +81,10 @@ def _py_runtime_impl(ctx):
python_version = ctx.attr.python_version

interpreter_version_info = ctx.attr.interpreter_version_info
if not interpreter_version_info:
python_version_flag = ctx.attr._python_version_flag[BuildSettingInfo].value
if python_version_flag:
interpreter_version_info = _interpreter_version_info_from_version_str(python_version_flag)

# TODO: Uncomment this after --incompatible_python_disable_py2 defaults to true
# if ctx.fragments.py.disable_py2 and python_version == "PY2":
Expand Down Expand Up @@ -133,13 +138,6 @@ def _py_runtime_impl(ctx):
),
]

def _is_singleton_depset(files):
# Bazel 6 doesn't have this helper to optimize detecting singleton depsets.
if _py_builtins:
return _py_builtins.is_singleton_depset(files)
else:
return len(files.to_list()) == 1

# Bind to the name "py_runtime" to preserve the kind/rule_class it shows up
# as elsewhere.
py_runtime = rule(
Expand Down Expand Up @@ -260,15 +258,22 @@ the target platform. For an in-build runtime this attribute must not be set.
"""),
"interpreter_version_info": attr.string_dict(
doc = """
Version information about the interpreter this runtime provides. The
supported keys match the names for `sys.version_info`. While the input
Version information about the interpreter this runtime provides.
If not specified, uses {obj}`--python_version`
The supported keys match the names for `sys.version_info`. While the input
values are strings, most are converted to ints. The supported keys are:
* major: int, the major version number
* minor: int, the minor version number
* micro: optional int, the micro version number
* releaselevel: optional str, the release level
* serial: optional int, the serial number of the release"
""",
* serial: optional int, the serial number of the release
:::{versionchanged} 0.36.0
{obj}`--python_version` determines the default value.
:::
""",
mandatory = False,
),
"pyc_tag": attr.string(
Expand Down Expand Up @@ -327,5 +332,25 @@ The {obj}`PyRuntimeInfo.zip_main_template` field.
:::
""",
),
"_python_version_flag": attr.label(
default = "//python/config_settings:python_version",
),
}),
)

def _is_singleton_depset(files):
# Bazel 6 doesn't have this helper to optimize detecting singleton depsets.
if _py_builtins:
return _py_builtins.is_singleton_depset(files)
else:
return len(files.to_list()) == 1

def _interpreter_version_info_from_version_str(version_str):
parts = version_str.split(".")
version_info = {}
for key in ("major", "minor", "micro"):
if not parts:
break
version_info[key] = parts.pop(0)

return version_info
29 changes: 29 additions & 0 deletions tests/py_runtime/py_runtime_tests.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ load("//python:py_runtime.bzl", "py_runtime")
load("//python:py_runtime_info.bzl", "PyRuntimeInfo")
load("//tests/base_rules:util.bzl", br_util = "util")
load("//tests/support:py_runtime_info_subject.bzl", "py_runtime_info_subject")
load("//tests/support:support.bzl", "PYTHON_VERSION")

_tests = []

Expand Down Expand Up @@ -528,6 +529,34 @@ def _test_interpreter_version_info_parses_values_to_struct_impl(env, target):

_tests.append(_test_interpreter_version_info_parses_values_to_struct)

def _test_version_info_from_flag(name):
if not config.enable_pystar:
rt_util.skip_test(name)
return
py_runtime(
name = name + "_subject",
interpreter_version_info = None,
interpreter_path = "/bogus",
)
analysis_test(
name = name,
target = name + "_subject",
impl = _test_version_info_from_flag_impl,
config_settings = {
PYTHON_VERSION: "3.12",
},
)

def _test_version_info_from_flag_impl(env, target):
version_info = env.expect.that_target(target).provider(PyRuntimeInfo, factory = py_runtime_info_subject).interpreter_version_info()
version_info.major().equals(3)
version_info.minor().equals(12)
version_info.micro().equals(None)
version_info.releaselevel().equals(None)
version_info.serial().equals(None)

_tests.append(_test_version_info_from_flag)

def py_runtime_test_suite(name):
test_suite(
name = name,
Expand Down