Skip to content

Commit f693239

Browse files
committed
fix #3374
1 parent aa5d088 commit f693239

File tree

3 files changed

+159
-14
lines changed

3 files changed

+159
-14
lines changed

python/private/pypi/hub_builder.bzl

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -566,8 +566,13 @@ def _whl_repo(
566566
for p in src.target_platforms
567567
]
568568

569+
# TODO @aignas 2025-11-02: once we have pipstar enabled we can add extra
570+
# targets to each hub for each extra combination and solve this more cleanly as opposed to
571+
# duplicating whl_library repositories.
572+
target_platforms = src.target_platforms if is_multiple_versions else []
573+
569574
return struct(
570-
repo_name = whl_repo_name(src.filename, src.sha256),
575+
repo_name = whl_repo_name(src.filename, src.sha256, *target_platforms),
571576
args = args,
572577
config_setting = whl_config_setting(
573578
version = python_version,

python/private/pypi/whl_repo_name.bzl

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,14 @@
1818
load("//python/private:normalize_name.bzl", "normalize_name")
1919
load(":parse_whl_name.bzl", "parse_whl_name")
2020

21-
def whl_repo_name(filename, sha256):
21+
def whl_repo_name(filename, sha256, *target_platforms):
2222
"""Return a valid whl_library repo name given a distribution filename.
2323
2424
Args:
2525
filename: {type}`str` the filename of the distribution.
2626
sha256: {type}`str` the sha256 of the distribution.
27+
*target_platforms: {type}`list[str]` the extra suffixes to append.
28+
Only used when we need to support different extras per version.
2729
2830
Returns:
2931
a string that can be used in {obj}`whl_library`.
@@ -59,6 +61,8 @@ def whl_repo_name(filename, sha256):
5961
elif version:
6062
parts.insert(1, version)
6163

64+
parts.extend([p.partition("_")[-1] for p in target_platforms])
65+
6266
return "_".join(parts)
6367

6468
def pypi_repo_name(whl_name, *target_platforms):

tests/pypi/hub_builder/hub_builder_tests.bzl

Lines changed: 148 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,142 @@ def _test_simple_multiple_requirements(env):
203203

204204
_tests.append(_test_simple_multiple_requirements)
205205

206+
def _test_simple_extras_vs_no_extras(env):
207+
builder = hub_builder(env)
208+
builder.pip_parse(
209+
_mock_mctx(
210+
read = lambda x: {
211+
"darwin.txt": "simple[foo]==0.0.1 --hash=sha256:deadbeef",
212+
"win.txt": "simple==0.0.1 --hash=sha256:deadbeef",
213+
}[x],
214+
),
215+
_parse(
216+
hub_name = "pypi",
217+
python_version = "3.15",
218+
requirements_darwin = "darwin.txt",
219+
requirements_windows = "win.txt",
220+
),
221+
)
222+
pypi = builder.build()
223+
224+
pypi.exposed_packages().contains_exactly(["simple"])
225+
pypi.group_map().contains_exactly({})
226+
pypi.whl_map().contains_exactly({
227+
"simple": {
228+
"pypi_315_simple_osx_aarch64": [
229+
whl_config_setting(
230+
target_platforms = [
231+
"cp315_osx_aarch64",
232+
],
233+
version = "3.15",
234+
),
235+
],
236+
"pypi_315_simple_windows_aarch64": [
237+
whl_config_setting(
238+
target_platforms = [
239+
"cp315_windows_aarch64",
240+
],
241+
version = "3.15",
242+
),
243+
],
244+
},
245+
})
246+
pypi.whl_libraries().contains_exactly({
247+
"pypi_315_simple_osx_aarch64": {
248+
"config_load": "@pypi//:config.bzl",
249+
"dep_template": "@pypi//{name}:{target}",
250+
"python_interpreter_target": "unit_test_interpreter_target",
251+
"requirement": "simple[foo]==0.0.1 --hash=sha256:deadbeef",
252+
},
253+
"pypi_315_simple_windows_aarch64": {
254+
"config_load": "@pypi//:config.bzl",
255+
"dep_template": "@pypi//{name}:{target}",
256+
"python_interpreter_target": "unit_test_interpreter_target",
257+
"requirement": "simple==0.0.1 --hash=sha256:deadbeef",
258+
},
259+
})
260+
pypi.extra_aliases().contains_exactly({})
261+
262+
_tests.append(_test_simple_extras_vs_no_extras)
263+
264+
def _test_simple_extras_vs_no_extras_simpleapi(env):
265+
def mocksimpleapi_download(*_, **__):
266+
return {
267+
"simple": parse_simpleapi_html(
268+
url = "https://example.com",
269+
content = """\
270+
<a href="/simple-0.0.1-py3-none-any.whl#sha256=deadbeef">simple-0.0.1-py3-none-any.whl</a><br/>
271+
""",
272+
),
273+
}
274+
275+
builder = hub_builder(
276+
env,
277+
simpleapi_download_fn = mocksimpleapi_download,
278+
)
279+
builder.pip_parse(
280+
_mock_mctx(
281+
read = lambda x: {
282+
"darwin.txt": "simple[foo]==0.0.1 --hash=sha256:deadbeef",
283+
"win.txt": "simple==0.0.1 --hash=sha256:deadbeef",
284+
}[x],
285+
),
286+
_parse(
287+
hub_name = "pypi",
288+
python_version = "3.15",
289+
requirements_darwin = "darwin.txt",
290+
requirements_windows = "win.txt",
291+
experimental_index_url = "example.com",
292+
),
293+
)
294+
pypi = builder.build()
295+
296+
pypi.exposed_packages().contains_exactly(["simple"])
297+
pypi.group_map().contains_exactly({})
298+
pypi.whl_map().contains_exactly({
299+
"simple": {
300+
"pypi_315_simple_py3_none_any_deadbeef_osx_aarch64": [
301+
whl_config_setting(
302+
target_platforms = [
303+
"cp315_osx_aarch64",
304+
],
305+
version = "3.15",
306+
),
307+
],
308+
"pypi_315_simple_py3_none_any_deadbeef_windows_aarch64": [
309+
whl_config_setting(
310+
target_platforms = [
311+
"cp315_windows_aarch64",
312+
],
313+
version = "3.15",
314+
),
315+
],
316+
},
317+
})
318+
pypi.whl_libraries().contains_exactly({
319+
"pypi_315_simple_py3_none_any_deadbeef_osx_aarch64": {
320+
"config_load": "@pypi//:config.bzl",
321+
"dep_template": "@pypi//{name}:{target}",
322+
"filename": "simple-0.0.1-py3-none-any.whl",
323+
"python_interpreter_target": "unit_test_interpreter_target",
324+
"requirement": "simple[foo]==0.0.1",
325+
"sha256": "deadbeef",
326+
"urls": ["https://example.com/simple-0.0.1-py3-none-any.whl"],
327+
},
328+
"pypi_315_simple_py3_none_any_deadbeef_windows_aarch64": {
329+
"config_load": "@pypi//:config.bzl",
330+
"dep_template": "@pypi//{name}:{target}",
331+
"filename": "simple-0.0.1-py3-none-any.whl",
332+
"python_interpreter_target": "unit_test_interpreter_target",
333+
"requirement": "simple==0.0.1",
334+
"sha256": "deadbeef",
335+
"urls": ["https://example.com/simple-0.0.1-py3-none-any.whl"],
336+
},
337+
})
338+
pypi.extra_aliases().contains_exactly({})
339+
340+
_tests.append(_test_simple_extras_vs_no_extras_simpleapi)
341+
206342
def _test_simple_multiple_python_versions(env):
207343
builder = hub_builder(
208344
env,
@@ -496,34 +632,34 @@ torch==2.4.1+cpu ; platform_machine == 'x86_64' \
496632
pypi.group_map().contains_exactly({})
497633
pypi.whl_map().contains_exactly({
498634
"torch": {
499-
"pypi_312_torch_cp312_cp312_linux_x86_64_8800deef": [
635+
"pypi_312_torch_cp312_cp312_linux_x86_64_8800deef_linux_x86_64": [
500636
whl_config_setting(
501-
target_platforms = ("cp312_linux_x86_64",),
637+
target_platforms = ["cp312_linux_x86_64"],
502638
version = "3.12",
503639
),
504640
],
505-
"pypi_312_torch_cp312_cp312_manylinux_2_17_aarch64_36109432": [
641+
"pypi_312_torch_cp312_cp312_manylinux_2_17_aarch64_36109432_linux_aarch64": [
506642
whl_config_setting(
507-
target_platforms = ("cp312_linux_aarch64",),
643+
target_platforms = ["cp312_linux_aarch64"],
508644
version = "3.12",
509645
),
510646
],
511-
"pypi_312_torch_cp312_cp312_win_amd64_3a570e5c": [
647+
"pypi_312_torch_cp312_cp312_win_amd64_3a570e5c_windows_x86_64": [
512648
whl_config_setting(
513-
target_platforms = ("cp312_windows_x86_64",),
649+
target_platforms = ["cp312_windows_x86_64"],
514650
version = "3.12",
515651
),
516652
],
517-
"pypi_312_torch_cp312_none_macosx_11_0_arm64_72b484d5": [
653+
"pypi_312_torch_cp312_none_macosx_11_0_arm64_72b484d5_osx_aarch64": [
518654
whl_config_setting(
519-
target_platforms = ("cp312_osx_aarch64",),
655+
target_platforms = ["cp312_osx_aarch64"],
520656
version = "3.12",
521657
),
522658
],
523659
},
524660
})
525661
pypi.whl_libraries().contains_exactly({
526-
"pypi_312_torch_cp312_cp312_linux_x86_64_8800deef": {
662+
"pypi_312_torch_cp312_cp312_linux_x86_64_8800deef_linux_x86_64": {
527663
"config_load": "@pypi//:config.bzl",
528664
"dep_template": "@pypi//{name}:{target}",
529665
"filename": "torch-2.4.1+cpu-cp312-cp312-linux_x86_64.whl",
@@ -532,7 +668,7 @@ torch==2.4.1+cpu ; platform_machine == 'x86_64' \
532668
"sha256": "8800deef0026011d502c0c256cc4b67d002347f63c3a38cd8e45f1f445c61364",
533669
"urls": ["https://torch.index/whl/cpu/torch-2.4.1%2Bcpu-cp312-cp312-linux_x86_64.whl"],
534670
},
535-
"pypi_312_torch_cp312_cp312_manylinux_2_17_aarch64_36109432": {
671+
"pypi_312_torch_cp312_cp312_manylinux_2_17_aarch64_36109432_linux_aarch64": {
536672
"config_load": "@pypi//:config.bzl",
537673
"dep_template": "@pypi//{name}:{target}",
538674
"filename": "torch-2.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",
@@ -541,7 +677,7 @@ torch==2.4.1+cpu ; platform_machine == 'x86_64' \
541677
"sha256": "36109432b10bd7163c9b30ce896f3c2cca1b86b9765f956a1594f0ff43091e2a",
542678
"urls": ["https://torch.index/whl/cpu/torch-2.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl"],
543679
},
544-
"pypi_312_torch_cp312_cp312_win_amd64_3a570e5c": {
680+
"pypi_312_torch_cp312_cp312_win_amd64_3a570e5c_windows_x86_64": {
545681
"config_load": "@pypi//:config.bzl",
546682
"dep_template": "@pypi//{name}:{target}",
547683
"filename": "torch-2.4.1+cpu-cp312-cp312-win_amd64.whl",
@@ -550,7 +686,7 @@ torch==2.4.1+cpu ; platform_machine == 'x86_64' \
550686
"sha256": "3a570e5c553415cdbddfe679207327b3a3806b21c6adea14fba77684d1619e97",
551687
"urls": ["https://torch.index/whl/cpu/torch-2.4.1%2Bcpu-cp312-cp312-win_amd64.whl"],
552688
},
553-
"pypi_312_torch_cp312_none_macosx_11_0_arm64_72b484d5": {
689+
"pypi_312_torch_cp312_none_macosx_11_0_arm64_72b484d5_osx_aarch64": {
554690
"config_load": "@pypi//:config.bzl",
555691
"dep_template": "@pypi//{name}:{target}",
556692
"filename": "torch-2.4.1-cp312-none-macosx_11_0_arm64.whl",

0 commit comments

Comments
 (0)