Skip to content

Commit 67a3e8a

Browse files
committed
clarify code and use different concepts for label reusing
1 parent 85bbb84 commit 67a3e8a

File tree

1 file changed

+48
-44
lines changed

1 file changed

+48
-44
lines changed

python/private/config_settings.bzl

+48-44
Original file line numberDiff line numberDiff line change
@@ -69,19 +69,31 @@ def _flag_values(python_versions):
6969

7070
VERSION_FLAG_VALUES = _flag_values(TOOL_VERSIONS.keys())
7171

72-
def is_python_config_setting(name, *, python_version, match_any = None, **kwargs):
72+
def is_python_config_setting(name, *, python_version, reuse_conditions = None, **kwargs):
7373
"""Create a config setting for matching 'python_version' configuration flag.
7474
7575
This function is mainly intended for internal use within the `whl_library` and `pip_parse`
7676
machinery.
7777
78+
The matching of the 'python_version' flag depends on the value passed in
79+
`python_version` and here is the example for `3.8` (but the same applies
80+
to other python versions present in @//python:versions.bzl#TOOL_VERSIONS):
81+
* "3.8" -> ["3.8", "3.8.1", "3.8.2", ..., "3.8.19"] # All 3.8 versions
82+
* "3.8.2" -> ["3.8.2"] # Only 3.8.2
83+
* "3.8.19" -> ["3.8.19", "3.8"] # The latest version should also match 3.8 so
84+
as when the `3.8` toolchain is used we just use the latest `3.8` toolchain.
85+
this makes the `select("is_python_3.8.19")` work no matter how the user
86+
specifies the latest python version to use.
87+
7888
Args:
7989
name: name for the target that will be created to be used in select statements.
80-
python_version: The python_version to be passed in the `flag_values` in the `config_setting`.
81-
match_any: The labels that should be used for matching the extra
82-
versions, which get passed to `config_setting_group.match_any`. If
83-
empty or None, this macro will create config settings necessary to
84-
match the `python_version` value.
90+
python_version: The python_version to be passed in the `flag_values` in the
91+
`config_setting`. Depending on the version, the matching python version list
92+
can be as described above.
93+
reuse_conditions: A dict of version to version label for which we should
94+
reuse config_setting targets instead of creating them from scratch. This
95+
is useful when using is_python_config_setting multiple times in the
96+
same package with the same `major.minor` python versions.
8597
**kwargs: extra kwargs passed to the `config_setting`.
8698
"""
8799
if python_version not in name:
@@ -90,34 +102,38 @@ def is_python_config_setting(name, *, python_version, match_any = None, **kwargs
90102
if python_version not in VERSION_FLAG_VALUES:
91103
fail("The 'python_version' must be known to 'rules_python', choose from the values: {}".format(VERSION_FLAG_VALUES.keys()))
92104

93-
flag_values = {
94-
_PYTHON_VERSION_FLAG: python_version,
95-
}
96-
97105
python_versions = VERSION_FLAG_VALUES[python_version]
98-
if len(python_versions) == 1 and not match_any:
106+
if len(python_versions) == 1:
99107
native.config_setting(
100108
name = name,
101-
flag_values = flag_values,
109+
flag_values = {
110+
_PYTHON_VERSION_FLAG: python_version,
111+
},
102112
**kwargs
103113
)
104114
return
105115

106-
if not match_any:
107-
create_config_settings = {
108-
"_{}".format(name).replace(python_version, version): {_PYTHON_VERSION_FLAG: version}
109-
for version in python_versions
110-
}
111-
match_any = list(create_config_settings.keys())
112-
else:
113-
setting_name = "_" + name if len(python_versions) > 1 else name
114-
create_config_settings = {setting_name: flag_values}
115-
if setting_name not in match_any:
116-
# Here we expect the user to supply us with a name of the label that
117-
# would be created by this function. This needs to be the case because
118-
# the VERSION_FLAG_VALUES values contain the all of the versions that
119-
# have to be matched.
120-
fail("'{}' must be present in 'match_any'".format(setting_name))
116+
reuse_conditions = reuse_conditions or {}
117+
create_config_settings = {
118+
"_{}".format(name).replace(python_version, version): {_PYTHON_VERSION_FLAG: version}
119+
for version in python_versions
120+
if not reuse_conditions or version not in reuse_conditions
121+
}
122+
match_any = list(create_config_settings.keys())
123+
for version, condition in reuse_conditions.items():
124+
if len(VERSION_FLAG_VALUES[version]) == 1:
125+
match_any.append(condition)
126+
continue
127+
128+
# Convert the name to an internal label that this function would create,
129+
# so that we are hitting the config_setting and not the config_setting_group.
130+
condition = Label(condition)
131+
if hasattr(condition, "same_package_label"):
132+
condition = condition.same_package_label("_" + condition.name)
133+
else:
134+
condition = condition.relative("_" + condition.name)
135+
136+
match_any.append(condition)
121137

122138
for name_, flag_values_ in create_config_settings.items():
123139
native.config_setting(
@@ -162,25 +178,13 @@ def construct_config_settings(name = None): # buildifier: disable=function-docs
162178
)
163179

164180
for version, matching_versions in VERSION_FLAG_VALUES.items():
165-
match_any = None
166-
if len(matching_versions) > 1:
167-
match_any = [
168-
# Use the internal labels created by this macro in order to handle matching
169-
# 3.8 config value if using the 3.8 version from MINOR_MAPPING with generating
170-
# fewer targets overall.
171-
("_is_python_{}" if len(VERSION_FLAG_VALUES[v]) > 1 else "is_python_{}").format(v)
172-
for v in matching_versions
173-
]
174-
175181
is_python_config_setting(
176182
name = "is_python_{}".format(version),
177183
python_version = version,
178-
# NOTE @aignas 2024-03-16: if we don't have this, then we may create duplicate
179-
# targets. I think this should be improved, but I haven't figured out how yet
180-
# and I ran out of time.
181-
#
182-
# The fact that this parameter is needed here, suggests that we may need to
183-
# think of a better abstraction here.
184-
match_any = match_any,
184+
reuse_conditions = {
185+
v: native.package_relative_label("is_python_{}".format(v))
186+
for v in matching_versions
187+
if v != version
188+
},
185189
visibility = ["//visibility:public"],
186190
)

0 commit comments

Comments
 (0)