Skip to content

Commit 87692a3

Browse files
committed
fix(whl_library): stop duplicating deps in whl_library
Before this PR we would incorrectly add deps to the platform-specific list if there were multiple entries in the `METADATA` file. It seems that some projects (e.g. [opencv-python]) have multiple entries in their METADATA file to help SAT solvers with selecting the right version when different interpreter versions are used. In our case, we will have only one version of a given package because we are operating with a locked dependency list, so we should ensure that we do not have duplicates across the lists. With this PR we are solving this during the construction of the dependency sets so that the internal model is always consistent. Fixes bazel-contrib#1873 [opencv-python]: https://pypi.org/project/opencv-python/
1 parent d3cec48 commit 87692a3

File tree

3 files changed

+63
-0
lines changed

3 files changed

+63
-0
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ A brief description of the categories of changes:
3434
* (whl_library): Fix the experimental_target_platforms overriding for platform
3535
specific wheels when the wheels are for any python interpreter version. Fixes
3636
[#1810](https://github.com/bazelbuild/rules_python/issues/1810).
37+
* (whl_library): Stop generating duplicate dependencies when encountering
38+
duplicates in the METADATA. Fixes
39+
[#1873](https://github.com/bazelbuild/rules_python/issues/1873).
3740
* (gazelle) In `project` or `package` generation modes, do not generate `py_test`
3841
rules when there are no test files and do not set `main = "__test__.py"` when
3942
that file doesn't exist.

python/pip_install/tools/wheel_installer/wheel.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,24 @@ def _add(self, dep: str, platform: Optional[Platform]):
370370

371371
if not platform:
372372
self._deps.add(dep)
373+
374+
# If the dep is in the platform-specific list, remove it from the select.
375+
pop_keys = []
376+
for p, deps in self._select.items():
377+
if dep not in deps:
378+
continue
379+
380+
deps.remove(dep)
381+
if not deps:
382+
pop_keys.append(p)
383+
384+
for p in pop_keys:
385+
self._select.pop(p)
386+
return
387+
388+
if dep in self._deps:
389+
# If the dep is already in the main dependency list, no need to add it in the
390+
# platform-specific dependency list.
373391
return
374392

375393
# Add the platform-specific dep

python/pip_install/tools/wheel_installer/wheel_test.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,48 @@ def test_deps_spanning_all_target_py_versions_are_added_to_common(self):
264264
self.assertEqual(["bar", "baz"], got.deps)
265265
self.assertEqual({}, got.deps_select)
266266

267+
def test_deps_are_not_duplicated(self):
268+
# See an example in
269+
# https://files.pythonhosted.org/packages/76/9e/db1c2d56c04b97981c06663384f45f28950a73d9acf840c4006d60d0a1ff/opencv_python-4.9.0.80-cp37-abi3-win32.whl.metadata
270+
requires_dist = [
271+
"bar >=0.1.0 ; python_version < '3.7'",
272+
"bar >=0.2.0 ; python_version >= '3.7'",
273+
"bar >=0.4.0 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64'",
274+
"bar >=0.4.0 ; python_version >= '3.9'",
275+
"bar >=0.5.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64'",
276+
"bar >=0.5.0 ; python_version >= '3.10' and platform_system == 'Darwin'",
277+
"bar >=0.5.0 ; python_version >= '3.10'",
278+
"bar >=0.6.0 ; python_version >= '3.11'",
279+
]
280+
281+
deps = wheel.Deps(
282+
"foo",
283+
requires_dist=requires_dist,
284+
platforms=wheel.Platform.from_string(["cp310_*"]),
285+
)
286+
got = deps.build()
287+
288+
self.assertEqual(["bar"], got.deps)
289+
self.assertEqual({}, got.deps_select)
290+
291+
def test_deps_are_not_duplicated_when_encountering_platform_dep_first(self):
292+
# Note, that we are sorting the incoming `requires_dist` and we need to ensure that we are not getting any
293+
# issues even if the platform-specific line comes first.
294+
requires_dist = [
295+
"bar >=0.4.0 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64'",
296+
"bar >=0.5.0 ; python_version >= '3.9'",
297+
]
298+
299+
deps = wheel.Deps(
300+
"foo",
301+
requires_dist=requires_dist,
302+
platforms=wheel.Platform.from_string(["cp310_*"]),
303+
)
304+
got = deps.build()
305+
306+
self.assertEqual(["bar"], got.deps)
307+
self.assertEqual({}, got.deps_select)
308+
267309

268310
class MinorVersionTest(unittest.TestCase):
269311
def test_host(self):

0 commit comments

Comments
 (0)