fix(whl_library): correctly handle arch-specific deps in wheels (#2007)
It seems that there was a single-line bug that did not allow us to
handle arch-specific deps and since the percentage of such wheels is
extremely low, it went under the radar for quite some time.
I am going to not implement any explicit passing of the default python
version to `whl_library` as it is a much bigger change. Just doing this
could be sufficient for the time being.
Fixes #1996
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6ae6508..0cbf2f9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -41,6 +41,9 @@
`interpreter_version_info` arg.
* (bzlmod) Correctly pass `isolated`, `quiet` and `timeout` values to `whl_library`
and drop the defaults from the lock file.
+* (whl_library) Correctly handle arch-specific dependencies when we encounter a
+ platform specific wheel and use `experimental_target_platforms`.
+ Fixes [#1996](https://github.com/bazelbuild/rules_python/issues/1996).
* (rules) The first element of the default outputs is now the executable again.
### Removed
@@ -55,7 +58,7 @@
To enable it, set {obj}`--//python/config_settings:exec_tools_toolchain=enabled`.
This toolchain must be enabled for precompilation to work. This toolchain will
be enabled by default in a future release.
- Fixes [1967](https://github.com/bazelbuild/rules_python/issues/1967).
+ Fixes [#1967](https://github.com/bazelbuild/rules_python/issues/1967).
## [0.33.1] - 2024-06-13
diff --git a/python/private/pypi/whl_installer/wheel.py b/python/private/pypi/whl_installer/wheel.py
index 3d6780d..c167df9 100644
--- a/python/private/pypi/whl_installer/wheel.py
+++ b/python/private/pypi/whl_installer/wheel.py
@@ -342,7 +342,12 @@
self.name: str = Deps._normalize(name)
self._platforms: Set[Platform] = platforms or set()
self._target_versions = {p.minor_version for p in platforms or {}}
- self._add_version_select = platforms and len(self._target_versions) > 2
+ self._default_minor_version = None
+ if platforms and len(self._target_versions) > 2:
+ # TODO @aignas 2024-06-23: enable this to be set via a CLI arg
+ # for being more explicit.
+ self._default_minor_version = host_interpreter_minor_version()
+
if None in self._target_versions and len(self._target_versions) > 2:
raise ValueError(
f"all python versions need to be specified explicitly, got: {platforms}"
@@ -540,21 +545,21 @@
):
continue
- if match_arch and self._add_version_select:
+ if match_arch and self._default_minor_version:
self._add(req.name, plat)
- if plat.minor_version == host_interpreter_minor_version():
+ if plat.minor_version == self._default_minor_version:
self._add(req.name, Platform(plat.os, plat.arch))
elif match_arch:
- self._add(req.name, plat)
- elif match_os and self._add_version_select:
+ self._add(req.name, Platform(plat.os, plat.arch))
+ elif match_os and self._default_minor_version:
self._add(req.name, Platform(plat.os, minor_version=plat.minor_version))
- if plat.minor_version == host_interpreter_minor_version():
+ if plat.minor_version == self._default_minor_version:
self._add(req.name, Platform(plat.os))
elif match_os:
self._add(req.name, Platform(plat.os))
- elif match_version and self._add_version_select:
+ elif match_version and self._default_minor_version:
self._add(req.name, Platform(minor_version=plat.minor_version))
- if plat.minor_version == host_interpreter_minor_version():
+ if plat.minor_version == self._default_minor_version:
self._add(req.name, Platform())
elif match_version:
self._add(req.name, None)
diff --git a/tests/pypi/whl_installer/wheel_test.py b/tests/pypi/whl_installer/wheel_test.py
index 9b27205..76bfe72 100644
--- a/tests/pypi/whl_installer/wheel_test.py
+++ b/tests/pypi/whl_installer/wheel_test.py
@@ -220,6 +220,42 @@
@mock.patch(
"python.private.pypi.whl_installer.wheel.host_interpreter_minor_version"
)
+ def test_no_version_select_when_single_version(self, mock_host_interpreter_version):
+ requires_dist = [
+ "bar",
+ "baz; python_version >= '3.8'",
+ "posix_dep; os_name=='posix'",
+ "posix_dep_with_version; os_name=='posix' and python_version >= '3.8'",
+ "arch_dep; platform_machine=='x86_64' and python_version >= '3.8'",
+ ]
+ mock_host_interpreter_version.return_value = 7
+
+ self.maxDiff = None
+
+ deps = wheel.Deps(
+ "foo",
+ requires_dist=requires_dist,
+ platforms=[
+ wheel.Platform(os=os, arch=wheel.Arch.x86_64, minor_version=minor)
+ for minor in [8]
+ for os in [wheel.OS.linux, wheel.OS.windows]
+ ],
+ )
+ got = deps.build()
+
+ self.assertEqual(["bar", "baz"], got.deps)
+ self.assertEqual(
+ {
+ "@platforms//os:linux": ["posix_dep", "posix_dep_with_version"],
+ "linux_x86_64": ["arch_dep", "posix_dep", "posix_dep_with_version"],
+ "windows_x86_64": ["arch_dep"],
+ },
+ got.deps_select,
+ )
+
+ @mock.patch(
+ "python.private.pypi.whl_installer.wheel.host_interpreter_minor_version"
+ )
def test_can_get_version_select(self, mock_host_interpreter_version):
requires_dist = [
"bar",
@@ -227,6 +263,7 @@
"baz_new; python_version >= '3.8'",
"posix_dep; os_name=='posix'",
"posix_dep_with_version; os_name=='posix' and python_version >= '3.8'",
+ "arch_dep; platform_machine=='x86_64' and python_version < '3.8'",
]
mock_host_interpreter_version.return_value = 7
@@ -251,6 +288,8 @@
"@//python/config_settings:is_python_3.8": ["baz_new"],
"@//python/config_settings:is_python_3.9": ["baz_new"],
"@platforms//os:linux": ["baz", "posix_dep"],
+ "cp37_linux_x86_64": ["arch_dep", "baz", "posix_dep"],
+ "cp37_windows_x86_64": ["arch_dep", "baz"],
"cp37_linux_anyarch": ["baz", "posix_dep"],
"cp38_linux_anyarch": [
"baz_new",
@@ -262,6 +301,8 @@
"posix_dep",
"posix_dep_with_version",
],
+ "linux_x86_64": ["arch_dep", "baz", "posix_dep"],
+ "windows_x86_64": ["arch_dep", "baz"],
},
got.deps_select,
)