Skip to content

Commit 09ae63c

Browse files
committed
wip
1 parent 9619624 commit 09ae63c

File tree

2 files changed

+267
-0
lines changed

2 files changed

+267
-0
lines changed

:w

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
# Copyright 2022 The Bazel Authors. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
""
16+
17+
load("@rules_testing//lib:analysis_test.bzl", "analysis_test")
18+
load("@rules_testing//lib:test_suite.bzl", "test_suite")
19+
load("@pythons_hub//:versions.bzl", "DEFAULT_PYTHON_VERSION", "MINOR_MAPPING")
20+
load("//python:versions.bzl", "PLATFORMS", "TOOL_VERSIONS")
21+
load("//python/private:bzlmod_enabled.bzl", "BZLMOD_ENABLED") # buildifier: disable=bzl-visibility
22+
load("//python/private:full_version.bzl", "full_version") # buildifier: disable=bzl-visibility
23+
load("//tests/support:support.bzl", "PYTHON_VERSION")
24+
load("//python/private:toolchain_types.bzl", "EXEC_TOOLS_TOOLCHAIN_TYPE") # buildifier: disable=bzl-visibility
25+
load("//tests/support:sh_py_run_test.bzl", "py_reconfig_test")
26+
load("//python:py_runtime_info", "PyRuntimeInfo")
27+
#
28+
# # This includes a simple transition implementation
29+
# def _transition_impl(input_settings, attr):
30+
# settings = {
31+
# PYTHON_VERSION: input_settings[PYTHON_VERSION],
32+
# }
33+
# if attr.python_version:
34+
# settings[PYTHON_VERSION] = attr.python_version
35+
# return settings
36+
#
37+
# _python_version_transition = transition(
38+
# implementation = _transition_impl,
39+
# inputs = [PYTHON_VERSION],
40+
# outputs = [PYTHON_VERSION],
41+
# )
42+
43+
_analysis_tests = []
44+
45+
def _test_toolchain_precedence(name):
46+
analysis_test(
47+
name = name,
48+
impl = _test_toolchain_precedence_impl,
49+
target = "//python:current_py_toolchain",
50+
config_settings = {
51+
PYTHON_VERSION: "3.12",
52+
},
53+
)
54+
55+
def _test_toolchain_precedence_impl(env, target):
56+
# Check that the forwarded UvToolchainInfo looks vaguely correct.
57+
py_runtime = env.expect.that_target(target).provider(
58+
PyRuntimeInfo,
59+
factory = lambda v, meta: v,
60+
)
61+
fail(py_runtime)
62+
env.expect.that_str(str(py_runtime.label)).contains("//tests/uv/uv:fake_foof")
63+
64+
_analysis_tests.append(_test_toolchain_precedence)
65+
66+
def define_toolchain_tests(name):
67+
"""Define the toolchain tests.
68+
69+
Args:
70+
name: Only present to satisfy tooling.
71+
"""
72+
test_suite(
73+
name = name,
74+
tests = _analysis_tests,
75+
)
76+
77+
for platform_key, platform_info in PLATFORMS.items():
78+
native.config_setting(
79+
name = "_is_{}".format(platform_key),
80+
flag_values = platform_info.flag_values,
81+
constraint_values = platform_info.compatible_with,
82+
)
83+
84+
# First we expect the transitions with a specific version to always
85+
# give us that specific version
86+
exact_version_tests = {
87+
(v, v): "python_{}_test".format(v)
88+
for v in TOOL_VERSIONS
89+
}
90+
native.test_suite(
91+
name = "exact_version_tests",
92+
tests = exact_version_tests.values(),
93+
)
94+
95+
if BZLMOD_ENABLED:
96+
# Then we expect to get the version in the MINOR_MAPPING if we provide
97+
# the version from the MINOR_MAPPING
98+
minor_mapping_tests = {
99+
(minor, full): "python_{}_test".format(minor)
100+
for minor, full in MINOR_MAPPING.items()
101+
}
102+
native.test_suite(
103+
name = "minor_mapping_tests",
104+
tests = minor_mapping_tests.values(),
105+
)
106+
107+
# Lastly, if we don't provide any version to the transition, we should
108+
# get the default version
109+
default_version = full_version(
110+
version = DEFAULT_PYTHON_VERSION,
111+
minor_mapping = MINOR_MAPPING,
112+
)
113+
default_version_tests = {
114+
(None, default_version): "default_version_test",
115+
}
116+
tests = exact_version_tests | minor_mapping_tests | default_version_tests
117+
else:
118+
# Outside bzlmod the default version and the minor mapping tests do not
119+
# make sense because the user loading things in the WORKSPACE ultimately defines
120+
# the matching order.
121+
tests = exact_version_tests
122+
123+
for (input_python_version, expect_python_version), test_name in tests.items():
124+
meta = TOOL_VERSIONS[expect_python_version]
125+
target_compatible_with = {
126+
"//conditions:default": ["@platforms//:incompatible"],
127+
}
128+
for platform_key in meta["sha256"].keys():
129+
is_platform = "_is_{}".format(platform_key)
130+
target_compatible_with[is_platform] = []
131+
132+
py_reconfig_test(
133+
name = test_name,
134+
srcs = ["python_toolchain_test.py"],
135+
main = "python_toolchain_test.py",
136+
python_version = input_python_version,
137+
env = {
138+
"EXPECT_PYTHON_VERSION": expect_python_version,
139+
},
140+
deps = ["//python/runfiles"],
141+
data = ["//tests/support:current_build_settings"],
142+
target_compatible_with = select(target_compatible_with),
143+
)

tests/toolchains/defs.bzl

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,141 @@
1515
""
1616

1717
load("@pythons_hub//:versions.bzl", "DEFAULT_PYTHON_VERSION", "MINOR_MAPPING")
18+
load("@rules_testing//lib:analysis_test.bzl", "analysis_test")
19+
load("@rules_testing//lib:test_suite.bzl", "test_suite")
20+
load("@rules_testing//lib:util.bzl", rt_util = "util")
1821
load("//python:versions.bzl", "PLATFORMS", "TOOL_VERSIONS")
1922
load("//python/private:bzlmod_enabled.bzl", "BZLMOD_ENABLED") # buildifier: disable=bzl-visibility
2023
load("//python/private:full_version.bzl", "full_version") # buildifier: disable=bzl-visibility
24+
load("//python/private:toolchain_types.bzl", "EXEC_TOOLS_TOOLCHAIN_TYPE") # buildifier: disable=bzl-visibility
2125
load("//tests/support:sh_py_run_test.bzl", "py_reconfig_test")
26+
load("//tests/support:support.bzl", "PYTHON_VERSION")
27+
28+
_analysis_tests = []
29+
30+
def _transition_impl(input_settings, attr):
31+
settings = {
32+
PYTHON_VERSION: input_settings[PYTHON_VERSION],
33+
}
34+
if attr.python_version:
35+
settings[PYTHON_VERSION] = attr.python_version
36+
return settings
37+
38+
_python_version_transition = transition(
39+
implementation = _transition_impl,
40+
inputs = [PYTHON_VERSION],
41+
outputs = [PYTHON_VERSION],
42+
)
43+
44+
TestInfo = provider(
45+
doc = "",
46+
fields = {
47+
"got": "",
48+
"want": "",
49+
},
50+
)
51+
52+
def _lock_impl(ctx):
53+
exec_tools = ctx.toolchains[EXEC_TOOLS_TOOLCHAIN_TYPE].exec_tools
54+
got_version = exec_tools.exec_interpreter[platform_common.ToolchainInfo].py3_runtime.interpreter_version_info
55+
return [
56+
TestInfo(
57+
got = "{}.{}.{}".format(
58+
got_version.major,
59+
got_version.minor,
60+
got_version.micro,
61+
),
62+
want = ctx.attr.want_version,
63+
),
64+
]
65+
66+
_simple_transition = rule(
67+
implementation = _lock_impl,
68+
attrs = {
69+
"python_version": attr.string(
70+
doc = "Public, see the docs in the macro.",
71+
),
72+
"want_version": attr.string(
73+
doc = "Public, see the docs in the macro.",
74+
),
75+
"_allowlist_function_transition": attr.label(
76+
default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
77+
),
78+
},
79+
toolchains = [
80+
EXEC_TOOLS_TOOLCHAIN_TYPE,
81+
],
82+
cfg = _python_version_transition,
83+
)
84+
85+
def _test_toolchain_precedence(name):
86+
# First we expect the transitions with a specific version to always
87+
# give us that specific version
88+
exact_version_tests = {
89+
(v, v): v.replace(".", "_")
90+
for v in TOOL_VERSIONS
91+
}
92+
93+
if BZLMOD_ENABLED:
94+
# Then we expect to get the version in the MINOR_MAPPING if we provide
95+
# the version from the MINOR_MAPPING
96+
minor_mapping_tests = {
97+
(minor, full): minor.replace(".", "_")
98+
for minor, full in MINOR_MAPPING.items()
99+
}
100+
101+
# Lastly, if we don't provide any version to the transition, we should
102+
# get the default version
103+
default_version = full_version(
104+
version = DEFAULT_PYTHON_VERSION,
105+
minor_mapping = MINOR_MAPPING,
106+
)
107+
default_version_tests = {
108+
(None, default_version): "default",
109+
}
110+
tests = exact_version_tests | minor_mapping_tests | default_version_tests
111+
else:
112+
# Outside bzlmod the default version and the minor mapping tests do not
113+
# make sense because the user loading things in the WORKSPACE ultimately defines
114+
# the matching order.
115+
tests = exact_version_tests
116+
117+
analysis_test(
118+
name = name,
119+
impl = _test_toolchain_precedence_impl,
120+
targets = {
121+
"{}_{}".format(name, test_name): rt_util.helper_target(
122+
_simple_transition,
123+
name = "{}_{}".format(name, test_name),
124+
python_version = input_version,
125+
want_version = want_version,
126+
)
127+
for (input_version, want_version), test_name in tests.items()
128+
},
129+
)
130+
131+
def _test_toolchain_precedence_impl(env, targets):
132+
# Check that the forwarded PyRuntimeInfo looks vaguely correct.
133+
for target in dir(targets):
134+
test_info = env.expect.that_target(target).provider(
135+
TestInfo,
136+
factory = lambda v, meta: v,
137+
)
138+
env.expect.that_str(test_info.got).equals(test_info.want)
139+
140+
_analysis_tests.append(_test_toolchain_precedence)
22141

23142
def define_toolchain_tests(name):
24143
"""Define the toolchain tests.
25144
26145
Args:
27146
name: Only present to satisfy tooling.
28147
"""
148+
test_suite(
149+
name = name,
150+
tests = _analysis_tests,
151+
)
152+
29153
for platform_key, platform_info in PLATFORMS.items():
30154
native.config_setting(
31155
name = "_is_{}".format(platform_key),

0 commit comments

Comments
 (0)