@@ -69,19 +69,31 @@ def _flag_values(python_versions):
69
69
70
70
VERSION_FLAG_VALUES = _flag_values (TOOL_VERSIONS .keys ())
71
71
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 ):
73
73
"""Create a config setting for matching 'python_version' configuration flag.
74
74
75
75
This function is mainly intended for internal use within the `whl_library` and `pip_parse`
76
76
machinery.
77
77
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
+
78
88
Args:
79
89
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.
85
97
**kwargs: extra kwargs passed to the `config_setting`.
86
98
"""
87
99
if python_version not in name :
@@ -90,34 +102,38 @@ def is_python_config_setting(name, *, python_version, match_any = None, **kwargs
90
102
if python_version not in VERSION_FLAG_VALUES :
91
103
fail ("The 'python_version' must be known to 'rules_python', choose from the values: {}" .format (VERSION_FLAG_VALUES .keys ()))
92
104
93
- flag_values = {
94
- _PYTHON_VERSION_FLAG : python_version ,
95
- }
96
-
97
105
python_versions = VERSION_FLAG_VALUES [python_version ]
98
- if len (python_versions ) == 1 and not match_any :
106
+ if len (python_versions ) == 1 :
99
107
native .config_setting (
100
108
name = name ,
101
- flag_values = flag_values ,
109
+ flag_values = {
110
+ _PYTHON_VERSION_FLAG : python_version ,
111
+ },
102
112
** kwargs
103
113
)
104
114
return
105
115
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 )
121
137
122
138
for name_ , flag_values_ in create_config_settings .items ():
123
139
native .config_setting (
@@ -162,25 +178,13 @@ def construct_config_settings(name = None): # buildifier: disable=function-docs
162
178
)
163
179
164
180
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
-
175
181
is_python_config_setting (
176
182
name = "is_python_{}" .format (version ),
177
183
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
+ },
185
189
visibility = ["//visibility:public" ],
186
190
)
0 commit comments