Skip to content

Commit aa60229

Browse files
dotoleeoakaignas
andauthored
fix(pypi): expose pypi packages only common to all python versions (bazel-contrib#3107)
Closes bazel-contrib#2921 For a single pypi repo with multiple python versions, `all_requirements` fail when a pypi package supports Python version A but not version B. In this case, the pypi package would be included only in requirements lock file for version A, not in one for version B. However, the failure occurs since the package is included in `all_requirements` even for Python version B. (Minimal reproduction: https://github.com/dotoleeoak/rules-python-2921-repro) This happens since `packages` parameter for `hub_repository` targets are including all packages across all requirement lock files. Instead of union of packages, intersection of packages for requirement files should be passed to `packages` and exposed to `all_requirements` macro, so that those packages are compatible with all Python versions. --------- Co-authored-by: Ignas Anikevicius <[email protected]>
1 parent 004be45 commit aa60229

File tree

3 files changed

+109
-1
lines changed

3 files changed

+109
-1
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@ END_UNRELEASED_TEMPLATE
9191
* Multi-line python imports (e.g. with escaped newlines) are now correctly processed by Gazelle.
9292
* (toolchains) `local_runtime_repo` works with multiarch Debian with Python 3.8
9393
([#3099](https://github.com/bazel-contrib/rules_python/issues/3099)).
94+
* (pypi) Expose pypi packages only common to all Python versions in `all_requirements`
95+
([#2921](https://github.com/bazel-contrib/rules_python/issues/2921)).
9496

9597
{#v0-0-0-added}
9698
### Added

python/private/pypi/extension.bzl

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -601,7 +601,15 @@ You cannot use both the additive_build_content and additive_build_content_file a
601601
extra_aliases.setdefault(hub_name, {})
602602
for whl_name, aliases in out.extra_aliases.items():
603603
extra_aliases[hub_name].setdefault(whl_name, {}).update(aliases)
604-
exposed_packages.setdefault(hub_name, {}).update(out.exposed_packages)
604+
if hub_name not in exposed_packages:
605+
exposed_packages[hub_name] = out.exposed_packages
606+
else:
607+
intersection = {}
608+
for pkg in out.exposed_packages:
609+
if pkg not in exposed_packages[hub_name]:
610+
continue
611+
intersection[pkg] = None
612+
exposed_packages[hub_name] = intersection
605613
whl_libraries.update(out.whl_libraries)
606614

607615
# TODO @aignas 2024-04-05: how do we support different requirement

tests/pypi/extension/extension_tests.bzl

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,104 @@ def _test_simple_multiple_requirements(env):
285285

286286
_tests.append(_test_simple_multiple_requirements)
287287

288+
def _test_simple_multiple_python_versions(env):
289+
pypi = _parse_modules(
290+
env,
291+
module_ctx = _mock_mctx(
292+
_mod(
293+
name = "rules_python",
294+
parse = [
295+
_parse(
296+
hub_name = "pypi",
297+
python_version = "3.15",
298+
requirements_lock = "requirements_3_15.txt",
299+
),
300+
_parse(
301+
hub_name = "pypi",
302+
python_version = "3.16",
303+
requirements_lock = "requirements_3_16.txt",
304+
),
305+
],
306+
),
307+
read = lambda x: {
308+
"requirements_3_15.txt": """
309+
simple==0.0.1 --hash=sha256:deadbeef
310+
old-package==0.0.1 --hash=sha256:deadbaaf
311+
""",
312+
"requirements_3_16.txt": """
313+
simple==0.0.2 --hash=sha256:deadb00f
314+
new-package==0.0.1 --hash=sha256:deadb00f2
315+
""",
316+
}[x],
317+
),
318+
available_interpreters = {
319+
"python_3_15_host": "unit_test_interpreter_target",
320+
"python_3_16_host": "unit_test_interpreter_target",
321+
},
322+
minor_mapping = {
323+
"3.15": "3.15.19",
324+
"3.16": "3.16.9",
325+
},
326+
)
327+
328+
pypi.exposed_packages().contains_exactly({"pypi": ["simple"]})
329+
pypi.hub_group_map().contains_exactly({"pypi": {}})
330+
pypi.hub_whl_map().contains_exactly({
331+
"pypi": {
332+
"new_package": {
333+
"pypi_316_new_package": [
334+
whl_config_setting(
335+
version = "3.16",
336+
),
337+
],
338+
},
339+
"old_package": {
340+
"pypi_315_old_package": [
341+
whl_config_setting(
342+
version = "3.15",
343+
),
344+
],
345+
},
346+
"simple": {
347+
"pypi_315_simple": [
348+
whl_config_setting(
349+
version = "3.15",
350+
),
351+
],
352+
"pypi_316_simple": [
353+
whl_config_setting(
354+
version = "3.16",
355+
),
356+
],
357+
},
358+
},
359+
})
360+
pypi.whl_libraries().contains_exactly({
361+
"pypi_315_old_package": {
362+
"dep_template": "@pypi//{name}:{target}",
363+
"python_interpreter_target": "unit_test_interpreter_target",
364+
"requirement": "old-package==0.0.1 --hash=sha256:deadbaaf",
365+
},
366+
"pypi_315_simple": {
367+
"dep_template": "@pypi//{name}:{target}",
368+
"python_interpreter_target": "unit_test_interpreter_target",
369+
"requirement": "simple==0.0.1 --hash=sha256:deadbeef",
370+
},
371+
"pypi_316_new_package": {
372+
"dep_template": "@pypi//{name}:{target}",
373+
"python_interpreter_target": "unit_test_interpreter_target",
374+
"requirement": "new-package==0.0.1 --hash=sha256:deadb00f2",
375+
},
376+
"pypi_316_simple": {
377+
"dep_template": "@pypi//{name}:{target}",
378+
"python_interpreter_target": "unit_test_interpreter_target",
379+
"requirement": "simple==0.0.2 --hash=sha256:deadb00f",
380+
},
381+
})
382+
pypi.whl_mods().contains_exactly({})
383+
384+
_tests.append(_test_simple_multiple_python_versions)
385+
288386
def _test_simple_with_markers(env):
289387
pypi = _parse_modules(
290388
env,

0 commit comments

Comments
 (0)