Skip to content

Commit 8645443

Browse files
committed
refactor: move interpreter detection to a simple function
1 parent a2bc653 commit 8645443

File tree

2 files changed

+59
-40
lines changed

2 files changed

+59
-40
lines changed

python/private/pypi/extension.bzl

Lines changed: 14 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -120,22 +120,17 @@ def _create_whl_repos(
120120
pip_attr,
121121
whl_overrides,
122122
config,
123-
available_interpreters = INTERPRETER_LABELS,
123+
hub,
124124
minor_mapping = MINOR_MAPPING,
125-
evaluate_markers = None,
126-
get_index_urls = None):
125+
evaluate_markers = None):
127126
"""create all of the whl repositories
128127
129128
Args:
130129
module_ctx: {type}`module_ctx`.
131130
pip_attr: {type}`struct` - the struct that comes from the tag class iteration.
132131
whl_overrides: {type}`dict[str, struct]` - per-wheel overrides.
132+
hub: TODO.
133133
config: The platform configuration.
134-
get_index_urls: A function used to get the index URLs
135-
available_interpreters: {type}`dict[str, Label]` The dictionary of available
136-
interpreters that have been registered using the `python` bzlmod extension.
137-
The keys are in the form `python_{snake_case_version}_host`. This is to be
138-
used during the `repository_rule` and must be always compatible with the host.
139134
minor_mapping: {type}`dict[str, str]` The dictionary needed to resolve the full
140135
python version used to parse package METADATA files.
141136
evaluate_markers: the function used to evaluate the markers.
@@ -152,7 +147,8 @@ def _create_whl_repos(
152147
rule.
153148
"""
154149
logger = repo_utils.logger(module_ctx, "pypi:create_whl_repos")
155-
python_interpreter_target = pip_attr.python_interpreter_target
150+
get_index_urls = hub.get_index_urls(pip_attr)
151+
interpreter = hub.detect_interpreter(pip_attr)
156152

157153
# containers to aggregate outputs from this function
158154
whl_map = {}
@@ -162,31 +158,10 @@ def _create_whl_repos(
162158
}
163159
whl_libraries = {}
164160

165-
# if we do not have the python_interpreter set in the attributes
166-
# we programmatically find it.
167-
hub_name = pip_attr.hub_name
168-
if python_interpreter_target == None and not pip_attr.python_interpreter:
169-
python_name = "python_{}_host".format(
170-
pip_attr.python_version.replace(".", "_"),
171-
)
172-
if python_name not in available_interpreters:
173-
fail((
174-
"Unable to find interpreter for pip hub '{hub_name}' for " +
175-
"python_version={version}: Make sure a corresponding " +
176-
'`python.toolchain(python_version="{version}")` call exists.' +
177-
"Expected to find {python_name} among registered versions:\n {labels}"
178-
).format(
179-
hub_name = hub_name,
180-
version = pip_attr.python_version,
181-
python_name = python_name,
182-
labels = " \n".join(available_interpreters),
183-
))
184-
python_interpreter_target = available_interpreters[python_name]
185-
186161
# TODO @aignas 2025-06-29: we should not need the version in the pip_name if
187162
# we are using pipstar and we are downloading the wheel using the downloader
188163
pip_name = "{}_{}".format(
189-
hub_name,
164+
hub.name,
190165
version_label(pip_attr.python_version),
191166
)
192167
major_minor = _major_minor_version(pip_attr.python_version)
@@ -249,8 +224,8 @@ def _create_whl_repos(
249224
}
250225
for k, plats in requirements.items()
251226
},
252-
python_interpreter = pip_attr.python_interpreter,
253-
python_interpreter_target = python_interpreter_target,
227+
python_interpreter = interpreter.path,
228+
python_interpreter_target = interpreter.target,
254229
srcs = pip_attr._evaluate_markers_srcs,
255230
logger = logger,
256231
)
@@ -293,7 +268,7 @@ def _create_whl_repos(
293268
# Construct args separately so that the lock file can be smaller and does not include unused
294269
# attrs.
295270
whl_library_args = dict(
296-
dep_template = "@{}//{{name}}:{{target}}".format(hub_name),
271+
dep_template = "@{}//{{name}}:{{target}}".format(hub.name),
297272
)
298273
maybe_args = dict(
299274
# The following values are safe to omit if they have false like values
@@ -306,8 +281,8 @@ def _create_whl_repos(
306281
group_deps = group_deps,
307282
group_name = group_name,
308283
pip_data_exclude = pip_attr.pip_data_exclude,
309-
python_interpreter = pip_attr.python_interpreter,
310-
python_interpreter_target = python_interpreter_target,
284+
python_interpreter = interpreter.path,
285+
python_interpreter_target = interpreter.target,
311286
whl_patches = {
312287
p: json.encode(args)
313288
for p, args in whl_overrides.get(whl.name, {}).items()
@@ -664,6 +639,8 @@ You cannot use both the additive_build_content and additive_build_content_file a
664639
module_name = mod.name,
665640
simpleapi_download_fn = simpleapi_download,
666641
simpleapi_cache = simpleapi_cache,
642+
minor_mapping = kwargs.get("minor_mapping", MINOR_MAPPING),
643+
available_interpreters = kwargs.pop("available_interpreters", INTERPRETER_LABELS),
667644
)
668645
pip_hub_map[pip_attr.hub_name] = builder
669646
elif pip_hub_map[hub_name].module_name != mod.name:
@@ -690,8 +667,8 @@ You cannot use both the additive_build_content and additive_build_content_file a
690667
# TODO @aignas 2025-05-19: express pip.parse as a series of configure calls
691668
out = _create_whl_repos(
692669
module_ctx,
670+
hub = builder,
693671
pip_attr = pip_attr,
694-
get_index_urls = builder.get_index_urls(pip_attr),
695672
whl_overrides = whl_overrides,
696673
config = config,
697674
**kwargs

python/private/pypi/hub_builder.bzl

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,37 @@ def hub_builder(
66
*,
77
name,
88
module_name,
9+
minor_mapping,
10+
available_interpreters,
911
simpleapi_download_fn,
1012
simpleapi_cache = {}):
11-
"""Return a hub builder instance"""
13+
"""Return a hub builder instance
14+
15+
Args:
16+
name: TODO
17+
module_name: TODO
18+
minor_mapping: TODO
19+
available_interpreters: {type}`dict[str, Label]` The dictionary of available
20+
interpreters that have been registered using the `python` bzlmod extension.
21+
The keys are in the form `python_{snake_case_version}_host`. This is to be
22+
used during the `repository_rule` and must be always compatible with the host.
23+
simpleapi_download_fn: TODO
24+
simpleapi_cache: TODO
25+
"""
1226

1327
# buildifier: disable=uninitialized
1428
self = struct(
1529
name = name,
1630
module_name = module_name,
1731
python_versions = [],
32+
_minor_mapping = minor_mapping,
33+
_available_interpreters = available_interpreters,
1834
_simpleapi_download_fn = simpleapi_download_fn,
1935
_simpleapi_cache = simpleapi_cache,
2036
# keep sorted
21-
add = lambda *args, **kwargs: _add(self, *args, **kwargs),
22-
get_index_urls = lambda *args, **kwargs: _get_index_urls(self, *args, **kwargs),
37+
add = lambda *a, **k: _add(self, *a, **k),
38+
get_index_urls = lambda *a, **k: _get_index_urls(self, *a, **k),
39+
detect_interpreter = lambda *a, **k: _detect_interpreter(self, *a, **k),
2340
)
2441

2542
# buildifier: enable=uninitialized
@@ -71,3 +88,28 @@ def _get_index_urls(self, pip_attr):
7188
fail("'experimental_index_url_overrides' is a no-op unless 'experimental_index_url' is set")
7289

7390
return get_index_urls
91+
92+
def _detect_interpreter(self, pip_attr):
93+
python_interpreter_target = pip_attr.python_interpreter_target
94+
if python_interpreter_target == None and not pip_attr.python_interpreter:
95+
python_name = "python_{}_host".format(
96+
pip_attr.python_version.replace(".", "_"),
97+
)
98+
if python_name not in self._available_interpreters:
99+
fail((
100+
"Unable to find interpreter for pip hub '{hub_name}' for " +
101+
"python_version={version}: Make sure a corresponding " +
102+
'`python.toolchain(python_version="{version}")` call exists.' +
103+
"Expected to find {python_name} among registered versions:\n {labels}"
104+
).format(
105+
hub_name = self.name,
106+
version = pip_attr.python_version,
107+
python_name = python_name,
108+
labels = " \n".join(self._available_interpreters),
109+
))
110+
python_interpreter_target = self._available_interpreters[python_name]
111+
112+
return struct(
113+
target = python_interpreter_target,
114+
path = pip_attr.python_interpreter,
115+
)

0 commit comments

Comments
 (0)