Skip to content

Commit e97cb9e

Browse files
committed
fix
1 parent a014b8a commit e97cb9e

3 files changed

Lines changed: 63 additions & 75 deletions

File tree

python/private/pypi/hub_builder.bzl

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,16 @@ def _create_whl_repos(
578578
interpreter = _detect_interpreter(self, pip_attr, python_version)
579579

580580
for whl in requirements_by_platform:
581+
# Check if all sources for this wheel have the same requirement line.
582+
# If they do, we can reuse the same whl_library repository across platforms.
583+
same_requirements = True
584+
if whl.srcs:
585+
first_req = whl.srcs[0].requirement_line
586+
for src in whl.srcs[1:]:
587+
if src.requirement_line != first_req:
588+
same_requirements = False
589+
break
590+
581591
whl_library_args = common_args | _whl_library_args(
582592
self,
583593
whl = whl,
@@ -594,6 +604,7 @@ def _create_whl_repos(
594604
auth_patterns = self._config.auth_patterns or pip_attr.auth_patterns,
595605
python_version = _major_minor_version(python_version),
596606
is_multiple_versions = whl.is_multiple_versions,
607+
same_requirements = same_requirements,
597608
interpreter = interpreter,
598609
enable_pipstar_extract = enable_pipstar_extract,
599610
)
@@ -664,6 +675,7 @@ def _whl_repo(
664675
whl_library_args,
665676
index_url,
666677
is_multiple_versions,
678+
same_requirements,
667679
download_only,
668680
netrc,
669681
auth_patterns,
@@ -695,7 +707,7 @@ def _whl_repo(
695707
return None
696708
else:
697709
# Fallback to a pip-installed wheel
698-
target_platforms = src.target_platforms if is_multiple_versions else []
710+
target_platforms = src.target_platforms if (is_multiple_versions or not same_requirements) else []
699711
return struct(
700712
repo_name = pypi_repo_name(
701713
normalize_name(src.distribution),
@@ -725,11 +737,11 @@ def _whl_repo(
725737
# TODO @aignas 2025-11-02: once we have pipstar enabled we can add extra
726738
# targets to each hub for each extra combination and solve this more cleanly as opposed to
727739
# duplicating whl_library repositories.
728-
target_platforms = src.target_platforms if is_multiple_versions else []
740+
target_platforms = src.target_platforms if (is_multiple_versions or not same_requirements) else []
729741

730742
return struct(
731743
repo_name = whl_repo_name(src.filename, src.sha256, *target_platforms),
732-
whl_repo_name = whl_repo_name(src.filename, src.sha256),
744+
whl_repo_name = whl_repo_name(src.filename, src.sha256, *target_platforms),
733745
args = args,
734746
config_setting = whl_config_setting(
735747
version = python_version,

tests/pypi/hub_builder/hub_builder_tests.bzl

Lines changed: 30 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -310,20 +310,16 @@ def _test_simple_extras_vs_no_extras_simpleapi(env):
310310
},
311311
})
312312
pypi.whl_libraries().contains_exactly({
313-
"pypi_315_simple_py3_none_any_deadbeef_osx_aarch64": {
314-
"config_load": "@pypi//:config.bzl",
315-
"dep_template": "@pypi//{name}:{target}",
313+
"simple_py3_none_any_deadbeef_osx_aarch64": {
316314
"filename": "simple-0.0.1-py3-none-any.whl",
317-
"index_url": "https://example.com/simple/",
315+
"index_url": "https://example.com/simple",
318316
"requirement": "simple[foo]==0.0.1",
319317
"sha256": "deadbeef",
320318
"urls": ["/simple-0.0.1-py3-none-any.whl"],
321319
},
322-
"pypi_315_simple_py3_none_any_deadbeef_windows_aarch64": {
323-
"config_load": "@pypi//:config.bzl",
324-
"dep_template": "@pypi//{name}:{target}",
320+
"simple_py3_none_any_deadbeef_windows_aarch64": {
325321
"filename": "simple-0.0.1-py3-none-any.whl",
326-
"index_url": "https://example.com/simple/",
322+
"index_url": "https://example.com/simple",
327323
"requirement": "simple==0.0.1",
328324
"sha256": "deadbeef",
329325
"urls": ["/simple-0.0.1-py3-none-any.whl"],
@@ -642,38 +638,30 @@ torch==2.4.1+cpu ; platform_machine == 'x86_64' \
642638
},
643639
})
644640
pypi.whl_libraries().contains_exactly({
645-
"pypi_312_torch_cp312_cp312_linux_x86_64_8800deef_linux_x86_64": {
646-
"config_load": "@pypi//:config.bzl",
647-
"dep_template": "@pypi//{name}:{target}",
641+
"torch_cp312_cp312_linux_x86_64_8800deef_linux_x86_64": {
648642
"filename": "torch-2.4.1+cpu-cp312-cp312-linux_x86_64.whl",
649-
"index_url": "https://torch.index/torch/",
643+
"index_url": "https://torch.index/torch",
650644
"requirement": "torch==2.4.1+cpu",
651645
"sha256": "8800deef0026011d502c0c256cc4b67d002347f63c3a38cd8e45f1f445c61364",
652646
"urls": ["/whl/cpu/torch-2.4.1%2Bcpu-cp312-cp312-linux_x86_64.whl"],
653647
},
654-
"pypi_312_torch_cp312_cp312_manylinux_2_17_aarch64_36109432_linux_aarch64": {
655-
"config_load": "@pypi//:config.bzl",
656-
"dep_template": "@pypi//{name}:{target}",
648+
"torch_cp312_cp312_manylinux_2_17_aarch64_36109432_linux_aarch64": {
657649
"filename": "torch-2.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",
658-
"index_url": "https://torch.index/torch/",
650+
"index_url": "https://torch.index/torch",
659651
"requirement": "torch==2.4.1",
660652
"sha256": "36109432b10bd7163c9b30ce896f3c2cca1b86b9765f956a1594f0ff43091e2a",
661653
"urls": ["/whl/cpu/torch-2.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl"],
662654
},
663-
"pypi_312_torch_cp312_cp312_win_amd64_3a570e5c_windows_x86_64": {
664-
"config_load": "@pypi//:config.bzl",
665-
"dep_template": "@pypi//{name}:{target}",
655+
"torch_cp312_cp312_win_amd64_3a570e5c_windows_x86_64": {
666656
"filename": "torch-2.4.1+cpu-cp312-cp312-win_amd64.whl",
667-
"index_url": "https://torch.index/torch/",
657+
"index_url": "https://torch.index/torch",
668658
"requirement": "torch==2.4.1+cpu",
669659
"sha256": "3a570e5c553415cdbddfe679207327b3a3806b21c6adea14fba77684d1619e97",
670660
"urls": ["/whl/cpu/torch-2.4.1%2Bcpu-cp312-cp312-win_amd64.whl"],
671661
},
672-
"pypi_312_torch_cp312_none_macosx_11_0_arm64_72b484d5_osx_aarch64": {
673-
"config_load": "@pypi//:config.bzl",
674-
"dep_template": "@pypi//{name}:{target}",
662+
"torch_cp312_none_macosx_11_0_arm64_72b484d5_osx_aarch64": {
675663
"filename": "torch-2.4.1-cp312-none-macosx_11_0_arm64.whl",
676-
"index_url": "https://torch.index/torch/",
664+
"index_url": "https://torch.index/torch",
677665
"requirement": "torch==2.4.1",
678666
"sha256": "72b484d5b6cec1a735bf3fa5a1c4883d01748698c5e9cfdbeb4ffab7c7987e0d",
679667
"urls": ["/whl/cpu/torch-2.4.1-cp312-none-macosx_11_0_arm64.whl"],
@@ -813,8 +801,6 @@ simple==0.0.1 --hash=sha256:deadb00f
813801
},
814802
})
815803
want_whl_library = {
816-
"config_load": "@pypi//:config.bzl",
817-
"dep_template": "@pypi//{name}:{target}",
818804
"filename": "simple-0.0.1-py3-none-any.whl",
819805
"index_url": test.expect_index_url,
820806
"requirement": "simple==0.0.1",
@@ -824,7 +810,7 @@ simple==0.0.1 --hash=sha256:deadb00f
824810
if getattr(test, "envsubst", []):
825811
want_whl_library["envsubst"] = test.envsubst
826812
pypi.whl_libraries().contains_exactly({
827-
"pypi_315_simple_py3_none_any_deadb00f": want_whl_library,
813+
"simple_py3_none_any_deadb00f": want_whl_library,
828814
})
829815
pypi.extra_aliases().contains_exactly({})
830816

@@ -1156,6 +1142,20 @@ git_dep @ git+https://git.server/repo/project@deadbeefdeadbeef
11561142
},
11571143
})
11581144
pypi.whl_libraries().contains_exactly({
1145+
"direct_without_sha_0_0_1_py3_none_any": {
1146+
"filename": "direct_without_sha-0.0.1-py3-none-any.whl",
1147+
"requirement": "direct_without_sha==0.0.1",
1148+
"sha256": "",
1149+
"urls": ["example-direct.org/direct_without_sha-0.0.1-py3-none-any.whl"],
1150+
"whl_patches": {"my_patch": "1"},
1151+
},
1152+
"plat_py3_none_linux_x86_64_deadb44f": {
1153+
"filename": "plat-pkg-0.0.4-py3-none-linux_x86_64.whl",
1154+
"index_url": "https://pypi.org/simple",
1155+
"requirement": "plat_pkg==0.0.4",
1156+
"sha256": "deadb44f",
1157+
"urls": ["example2.org/index/plat_pkg/"],
1158+
},
11591159
"pypi_315_any_name": {
11601160
"config_load": "@pypi//:config.bzl",
11611161
"dep_template": "@pypi//{name}:{target}",
@@ -1166,15 +1166,6 @@ git_dep @ git+https://git.server/repo/project@deadbeefdeadbeef
11661166
"sha256": "",
11671167
"urls": ["some-archive/any-name.tar.gz"],
11681168
},
1169-
"pypi_315_direct_without_sha_0_0_1_py3_none_any": {
1170-
"config_load": "@pypi//:config.bzl",
1171-
"dep_template": "@pypi//{name}:{target}",
1172-
"filename": "direct_without_sha-0.0.1-py3-none-any.whl",
1173-
"requirement": "direct_without_sha==0.0.1",
1174-
"sha256": "",
1175-
"urls": ["example-direct.org/direct_without_sha-0.0.1-py3-none-any.whl"],
1176-
"whl_patches": {"my_patch": "1"},
1177-
},
11781169
"pypi_315_git_dep": {
11791170
"config_load": "@pypi//:config.bzl",
11801171
"dep_template": "@pypi//{name}:{target}",
@@ -1189,35 +1180,20 @@ git_dep @ git+https://git.server/repo/project@deadbeefdeadbeef
11891180
"python_interpreter_target": "unit_test_interpreter_target",
11901181
"requirement": "pip_fallback==0.0.1",
11911182
},
1192-
"pypi_315_plat_py3_none_linux_x86_64_deadb44f": {
1193-
"config_load": "@pypi//:config.bzl",
1194-
"dep_template": "@pypi//{name}:{target}",
1195-
"filename": "plat-pkg-0.0.4-py3-none-linux_x86_64.whl",
1196-
"index_url": "https://pypi.org/simple",
1197-
"requirement": "plat_pkg==0.0.4",
1198-
"sha256": "deadb44f",
1199-
"urls": ["example2.org/index/plat_pkg/"],
1200-
},
1201-
"pypi_315_simple_py3_none_any_deadb00f": {
1202-
"config_load": "@pypi//:config.bzl",
1203-
"dep_template": "@pypi//{name}:{target}",
1183+
"simple_py3_none_any_deadb00f": {
12041184
"filename": "simple-0.0.1-py3-none-any.whl",
12051185
"index_url": "https://pypi.org/simple",
12061186
"requirement": "simple==0.0.1",
12071187
"sha256": "deadb00f",
12081188
"urls": ["example2.org"],
12091189
},
1210-
"pypi_315_some_pkg_py3_none_any_deadbaaf": {
1211-
"config_load": "@pypi//:config.bzl",
1212-
"dep_template": "@pypi//{name}:{target}",
1190+
"some_pkg_py3_none_any_deadbaaf": {
12131191
"filename": "some_pkg-0.0.1-py3-none-any.whl",
12141192
"requirement": "some_pkg==0.0.1",
12151193
"sha256": "deadbaaf",
12161194
"urls": ["example-direct.org/some_pkg-0.0.1-py3-none-any.whl"],
12171195
},
1218-
"pypi_315_some_py3_none_any_deadb33f": {
1219-
"config_load": "@pypi//:config.bzl",
1220-
"dep_template": "@pypi//{name}:{target}",
1196+
"some_py3_none_any_deadb33f": {
12211197
"filename": "some-other-pkg-0.0.1-py3-none-any.whl",
12221198
"index_url": "https://with_index_url",
12231199
"requirement": "some_other_pkg==0.0.1",

tests/pypi/parse_requirements/parse_requirements_tests.bzl

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1052,7 +1052,7 @@ def _test_uv_lock_consistent(env):
10521052
env.expect.that_collection(got).contains_exactly([
10531053
struct(
10541054
name = "foo",
1055-
index_url = "",
1055+
index_url = "https://pypi.org/simple/foo",
10561056
is_exposed = True,
10571057
is_multiple_versions = False,
10581058
srcs = [
@@ -1080,7 +1080,7 @@ def _test_uv_lock_primary_source(env):
10801080
env.expect.that_collection(got).contains_exactly([
10811081
struct(
10821082
name = "foo",
1083-
index_url = "",
1083+
index_url = "https://pypi.org/simple/foo",
10841084
is_exposed = True,
10851085
is_multiple_versions = False,
10861086
srcs = [
@@ -1108,7 +1108,7 @@ def _test_uv_lock_primary_source_multiple_versions(env):
11081108
env.expect.that_collection(got).contains_exactly([
11091109
struct(
11101110
name = "foo",
1111-
index_url = "",
1111+
index_url = "https://pypi.org/simple/foo",
11121112
is_exposed = True,
11131113
is_multiple_versions = True,
11141114
srcs = [
@@ -1146,7 +1146,7 @@ def _test_uv_lock_primary_source_with_extras(env):
11461146
env.expect.that_collection(got).contains_exactly([
11471147
struct(
11481148
name = "foo",
1149-
index_url = "",
1149+
index_url = "https://pypi.org/simple/foo",
11501150
is_exposed = True,
11511151
is_multiple_versions = False,
11521152
srcs = [
@@ -1174,7 +1174,7 @@ def _test_uv_lock_primary_source_includes_virtual(env):
11741174
env.expect.that_collection(got).contains_exactly([
11751175
struct(
11761176
name = "foo",
1177-
index_url = "",
1177+
index_url = "https://pypi.org/simple/foo",
11781178
is_exposed = True,
11791179
is_multiple_versions = False,
11801180
srcs = [
@@ -1212,7 +1212,7 @@ def _test_uv_lock_cross_consistent(env):
12121212
env.expect.that_collection(got).contains_exactly([
12131213
struct(
12141214
name = "foo",
1215-
index_url = "",
1215+
index_url = "https://pypi.org/simple/foo",
12161216
is_exposed = True,
12171217
is_multiple_versions = False,
12181218
srcs = [
@@ -1268,7 +1268,7 @@ def _test_uv_lock_rules_python_pkg_not_skipped(env):
12681268
env.expect.that_collection(got).contains_exactly([
12691269
struct(
12701270
name = "rules_python",
1271-
index_url = "",
1271+
index_url = "https://pypi.org/simple/rules-python",
12721272
is_exposed = True,
12731273
is_multiple_versions = False,
12741274
srcs = [
@@ -1301,7 +1301,7 @@ def _test_uv_lock_no_consistency_check(env):
13011301
env.expect.that_collection(got).contains_exactly([
13021302
struct(
13031303
name = "foo",
1304-
index_url = "",
1304+
index_url = "https://pypi.org/simple/foo",
13051305
is_exposed = True,
13061306
is_multiple_versions = False,
13071307
srcs = [
@@ -1329,7 +1329,7 @@ def _test_uv_lock_multiple_packages(env):
13291329
env.expect.that_collection(got).contains_exactly([
13301330
struct(
13311331
name = "bar",
1332-
index_url = "",
1332+
index_url = "https://pypi.org/simple/bar",
13331333
is_exposed = True,
13341334
is_multiple_versions = False,
13351335
srcs = [
@@ -1347,7 +1347,7 @@ def _test_uv_lock_multiple_packages(env):
13471347
),
13481348
struct(
13491349
name = "foo",
1350-
index_url = "",
1350+
index_url = "https://pypi.org/simple/foo",
13511351
is_exposed = True,
13521352
is_multiple_versions = False,
13531353
srcs = [
@@ -1376,7 +1376,7 @@ def _test_uv_lock_with_extra_pip_args(env):
13761376
env.expect.that_collection(got).contains_exactly([
13771377
struct(
13781378
name = "foo",
1379-
index_url = "",
1379+
index_url = "https://pypi.org/simple/foo",
13801380
is_exposed = True,
13811381
is_multiple_versions = False,
13821382
srcs = [
@@ -1408,7 +1408,7 @@ def _test_uv_lock_multi_os_with_requirements(env):
14081408
env.expect.that_collection(got).contains_exactly([
14091409
struct(
14101410
name = "foo",
1411-
index_url = "",
1411+
index_url = "https://pypi.org/simple/foo",
14121412
is_exposed = True,
14131413
is_multiple_versions = False,
14141414
srcs = [
@@ -1436,7 +1436,7 @@ def _test_uv_lock_extras_optional_deps(env):
14361436
env.expect.that_collection(got).contains_exactly([
14371437
struct(
14381438
name = "foo",
1439-
index_url = "",
1439+
index_url = "https://pypi.org/simple/foo",
14401440
is_exposed = True,
14411441
is_multiple_versions = False,
14421442
srcs = [
@@ -1464,7 +1464,7 @@ def _test_uv_lock_extras_dep_edge(env):
14641464
env.expect.that_collection(got).contains_exactly([
14651465
struct(
14661466
name = "bar",
1467-
index_url = "",
1467+
index_url = "https://pypi.org/simple/bar",
14681468
is_exposed = True,
14691469
is_multiple_versions = False,
14701470
srcs = [
@@ -1482,7 +1482,7 @@ def _test_uv_lock_extras_dep_edge(env):
14821482
),
14831483
struct(
14841484
name = "foo",
1485-
index_url = "",
1485+
index_url = "https://pypi.org/simple/foo",
14861486
is_exposed = True,
14871487
is_multiple_versions = False,
14881488
srcs = [
@@ -1517,7 +1517,7 @@ def _test_uv_lock_wheel_dedup_single_version(env):
15171517
env.expect.that_collection(got).contains_exactly([
15181518
struct(
15191519
name = "foo",
1520-
index_url = "",
1520+
index_url = "https://pypi.org/simple/foo",
15211521
is_exposed = True,
15221522
is_multiple_versions = False,
15231523
srcs = [
@@ -1563,7 +1563,7 @@ def _test_uv_lock_wheel_dedup_resolution_markers(env):
15631563
env.expect.that_collection(got).contains_exactly([
15641564
struct(
15651565
name = "foo",
1566-
index_url = "",
1566+
index_url = "https://pypi.org/simple/foo",
15671567
is_exposed = True,
15681568
is_multiple_versions = True,
15691569
srcs = [
@@ -1601,7 +1601,7 @@ def _test_uv_lock_requires_dist_extras(env):
16011601
env.expect.that_collection(got).contains_exactly([
16021602
struct(
16031603
name = "foo",
1604-
index_url = "",
1604+
index_url = "https://pypi.org/simple/foo",
16051605
is_exposed = True,
16061606
is_multiple_versions = False,
16071607
srcs = [

0 commit comments

Comments
 (0)