diff --git a/news/unified-platform-packages.fixed.md b/news/unified-platform-packages.fixed.md new file mode 100644 index 0000000000..bfcbdd9df1 --- /dev/null +++ b/news/unified-platform-packages.fixed.md @@ -0,0 +1,3 @@ +(pypi) Include platform-specific packages in the unified +`@pypi` hub so that their aliases resolve on supported target +platforms. ([#4171](https://github.com/bazel-contrib/rules_python/issues/4171)) diff --git a/python/private/pypi/extension.bzl b/python/private/pypi/extension.bzl index cafe245eb2..952c65755f 100644 --- a/python/private/pypi/extension.bzl +++ b/python/private/pypi/extension.bzl @@ -505,7 +505,7 @@ def _create_unified_hub_repo(mods): extra_aliases = {} for hub_name in hubs: - for pkg_name in mods.exposed_packages.get(hub_name, []): + for pkg_name in mods.hub_whl_map[hub_name]: norm_pkg = normalize_name(pkg_name) if norm_pkg not in packages: packages[norm_pkg] = [] diff --git a/tests/integration/unified_pypi/BUILD.bazel b/tests/integration/unified_pypi/BUILD.bazel index c0b9905fa6..19a8a1925c 100644 --- a/tests/integration/unified_pypi/BUILD.bazel +++ b/tests/integration/unified_pypi/BUILD.bazel @@ -59,3 +59,19 @@ py_binary( main = "bin_declared_only.py", deps = ["@pypi//declared_only_pkg:declared-only-alias"], ) + +platform( + name = "linux_x86_64", + constraint_values = [ + "@platforms//cpu:x86_64", + "@platforms//os:linux", + ], +) + +platform( + name = "windows_x86_64", + constraint_values = [ + "@platforms//cpu:x86_64", + "@platforms//os:windows", + ], +) diff --git a/tests/integration/unified_pypi/MODULE.bazel b/tests/integration/unified_pypi/MODULE.bazel index 6a4b87e015..f8e1589d69 100644 --- a/tests/integration/unified_pypi/MODULE.bazel +++ b/tests/integration/unified_pypi/MODULE.bazel @@ -1,5 +1,6 @@ module(name = "unified_pypi") +bazel_dep(name = "platforms", version = "0.0.11") bazel_dep(name = "rules_python", version = "0.0.0") local_path_override( module_name = "rules_python", @@ -36,11 +37,19 @@ pip.parse( ) use_repo(pip, "pypi_a") -# pypi_b has colorama and six, and acts as designated fallback +# `pypi_b` supplies `six` only on Linux and is the fallback hub. pip.parse( hub_name = "pypi_b", python_version = "3.11", - requirements_lock = "//:requirements_b.txt", + requirements_by_platform = { + "//:requirements_b.txt": "linux_*", + "//:requirements_b_without_six.txt": "osx_*,windows_*", + }, + target_platforms = [ + "{os}_{arch}", + "linux_x86_64", + "windows_x86_64", + ], ) use_repo(pip, "pypi_b") diff --git a/tests/integration/unified_pypi/requirements_b_without_six.txt b/tests/integration/unified_pypi/requirements_b_without_six.txt new file mode 100644 index 0000000000..ab5f031951 --- /dev/null +++ b/tests/integration/unified_pypi/requirements_b_without_six.txt @@ -0,0 +1,3 @@ +colorama==0.4.5 \ + --hash=sha256:854bf444933e37f5824ae7bfc1e98d5bce2ebe4160d46b5edf346a89358e99da \ + --hash=sha256:e6c6b4334fc50988a639d9b98ae42f5c90ec94cb1495b4fe76c5f72cf7f79435 diff --git a/tests/integration/unified_pypi_test.py b/tests/integration/unified_pypi_test.py index a19a9fcfbe..38e198f131 100644 --- a/tests/integration/unified_pypi_test.py +++ b/tests/integration/unified_pypi_test.py @@ -20,6 +20,27 @@ def test_cli_override(self): "//:test_cli", ) + def test_platform_specific_package(self): + for hub in ("auto", "pypi_b"): + with self.subTest(hub=hub): + self.run_bazel( + "build", + "--platforms=//:linux_x86_64", + f"--@rules_python//python/config_settings:venv={hub}", + "@pypi//six", + "@pypi//six:whl", + ) + + def test_platform_specific_package_rejects_unsupported_platform(self): + result = self.run_bazel( + "cquery", + "--platforms=//:windows_x86_64", + "@pypi//six", + check=False, + ) + self.assertNotEqual(result.exit_code, 0) + self.assert_result_matches(result, "No matching wheel") + def test_disjoint_package_cquery_succeeds_but_build_fails(self): self.run_bazel("cquery", "//:bin_six_a") result = self.run_bazel("build", "//:bin_six_a", check=False)