Skip to content

Commit 8d40b19

Browse files
authored
fix(bzlmod): only expose common packages via the requirements constants (#1955)
With this change the default `gazelle` instructions still work and users do not need to worry about which package is present on which platform. Work towards #260
1 parent 4e70959 commit 8d40b19

File tree

5 files changed

+57
-3
lines changed

5 files changed

+57
-3
lines changed

CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,20 @@ A brief description of the categories of changes:
3636
removed in a future release.
3737

3838
### Fixed
39+
* (bzlmod): When using `experimental_index_url` the `all_requirements`,
40+
`all_whl_requirements` and `all_data_requirements` will now only include
41+
common packages that are available on all target platforms. This is to ensure
42+
that packages that are only present for some platforms are pulled only via
43+
the `deps` of the materialized `py_library`. If you would like to include
44+
platform specific packages, using a `select` statement with references to the
45+
specific package will still work (e.g.
46+
```
47+
my_attr = all_requirements + select(
48+
{
49+
"@platforms//os:linux": ["@pypi//foo_available_only_on_linux"],
50+
"//conditions:default": [],
51+
}
52+
)`.
3953
* (bzlmod): Targets in `all_requirements` now use the same form as targets returned by the `requirement` macro.
4054
* (rules) Auto exec groups are enabled. This allows actions run by the rules,
4155
such as precompiling, to pick an execution platform separately from what

python/private/pypi/bzlmod.bzl

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ You cannot use both the additive_build_content and additive_build_content_file a
9797
whl_mods = whl_mods,
9898
)
9999

100-
def _create_whl_repos(module_ctx, pip_attr, whl_map, whl_overrides, group_map, simpleapi_cache):
100+
def _create_whl_repos(module_ctx, pip_attr, whl_map, whl_overrides, group_map, simpleapi_cache, exposed_packages):
101101
logger = repo_utils.logger(module_ctx)
102102
python_interpreter_target = pip_attr.python_interpreter_target
103103
is_hub_reproducible = True
@@ -245,7 +245,9 @@ def _create_whl_repos(module_ctx, pip_attr, whl_map, whl_overrides, group_map, s
245245
if get_index_urls:
246246
# TODO @aignas 2024-05-26: move to a separate function
247247
found_something = False
248+
is_exposed = False
248249
for requirement in requirements:
250+
is_exposed = is_exposed or requirement.is_exposed
249251
for distribution in requirement.whls + [requirement.sdist]:
250252
if not distribution:
251253
# sdist may be None
@@ -290,6 +292,8 @@ def _create_whl_repos(module_ctx, pip_attr, whl_map, whl_overrides, group_map, s
290292
)
291293

292294
if found_something:
295+
if is_exposed:
296+
exposed_packages.setdefault(hub_name, {})[whl_name] = None
293297
continue
294298

295299
requirement = select_requirement(
@@ -431,6 +435,7 @@ def _pip_impl(module_ctx):
431435
# Where hub, whl, and pip are the repo names
432436
hub_whl_map = {}
433437
hub_group_map = {}
438+
exposed_packages = {}
434439

435440
simpleapi_cache = {}
436441
is_extension_reproducible = True
@@ -470,7 +475,7 @@ def _pip_impl(module_ctx):
470475
else:
471476
pip_hub_map[pip_attr.hub_name].python_versions.append(pip_attr.python_version)
472477

473-
is_hub_reproducible = _create_whl_repos(module_ctx, pip_attr, hub_whl_map, whl_overrides, hub_group_map, simpleapi_cache)
478+
is_hub_reproducible = _create_whl_repos(module_ctx, pip_attr, hub_whl_map, whl_overrides, hub_group_map, simpleapi_cache, exposed_packages)
474479
is_extension_reproducible = is_extension_reproducible and is_hub_reproducible
475480

476481
for hub_name, whl_map in hub_whl_map.items():
@@ -482,6 +487,7 @@ def _pip_impl(module_ctx):
482487
for key, value in whl_map.items()
483488
},
484489
default_version = _major_minor_version(DEFAULT_PYTHON_VERSION),
490+
packages = sorted(exposed_packages.get(hub_name, {})),
485491
groups = hub_group_map.get(hub_name),
486492
)
487493

python/private/pypi/hub_repository.bzl

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ exports_files(["requirements.bzl"])
2929
"""
3030

3131
def _impl(rctx):
32-
bzl_packages = rctx.attr.whl_map.keys()
32+
bzl_packages = rctx.attr.packages or rctx.attr.whl_map.keys()
3333
aliases = render_multiplatform_pkg_aliases(
3434
aliases = {
3535
key: [whl_alias(**v) for v in json.decode(values)]
@@ -77,6 +77,12 @@ setting.""",
7777
"groups": attr.string_list_dict(
7878
mandatory = False,
7979
),
80+
"packages": attr.string_list(
81+
mandatory = False,
82+
doc = """\
83+
The list of packages that will be exposed via all_*requirements macros. Defaults to whl_map keys.
84+
""",
85+
),
8086
"repo_name": attr.string(
8187
mandatory = True,
8288
doc = "The apparent name of the repo. This is needed because in bzlmod, the name attribute becomes the canonical name.",

python/private/pypi/parse_requirements.bzl

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,8 @@ def parse_requirements(
181181
* srcs: The Simple API downloadable source list.
182182
* requirement_line: The original requirement line.
183183
* target_platforms: The list of target platforms that this package is for.
184+
* is_exposed: A boolean if the package should be exposed via the hub
185+
repository.
184186
185187
The second element is extra_pip_args should be passed to `whl_library`.
186188
"""
@@ -266,6 +268,8 @@ def parse_requirements(
266268
for p in DEFAULT_PLATFORMS
267269
if p not in configured_platforms
268270
]
271+
for p in plats:
272+
configured_platforms[p] = file
269273

270274
contents = ctx.read(file)
271275

@@ -344,6 +348,19 @@ def parse_requirements(
344348

345349
ret = {}
346350
for whl_name, reqs in requirements_by_platform.items():
351+
requirement_target_platforms = {}
352+
for r in reqs.values():
353+
for p in r.target_platforms:
354+
requirement_target_platforms[p] = None
355+
356+
is_exposed = len(requirement_target_platforms) == len(configured_platforms)
357+
if not is_exposed and logger:
358+
logger.debug(lambda: "Package {} will not be exposed because it is only present on a subset of platforms: {} out of {}".format(
359+
whl_name,
360+
sorted(requirement_target_platforms),
361+
sorted(configured_platforms),
362+
))
363+
347364
for r in sorted(reqs.values(), key = lambda r: r.requirement_line):
348365
whls, sdist = _add_dists(
349366
r,
@@ -362,6 +379,7 @@ def parse_requirements(
362379
download = r.download,
363380
whls = whls,
364381
sdist = sdist,
382+
is_exposed = is_exposed,
365383
),
366384
)
367385

tests/pypi/parse_requirements/parse_requirements_tests.bzl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ def _test_simple(env):
9898
],
9999
whls = [],
100100
sdist = None,
101+
is_exposed = True,
101102
),
102103
],
103104
})
@@ -145,6 +146,7 @@ def _test_platform_markers_with_python_version(env):
145146
],
146147
whls = [],
147148
sdist = None,
149+
is_exposed = True,
148150
),
149151
],
150152
})
@@ -181,6 +183,7 @@ def _test_dupe_requirements(env):
181183
],
182184
whls = [],
183185
sdist = None,
186+
is_exposed = True,
184187
),
185188
],
186189
})
@@ -220,6 +223,7 @@ def _test_multi_os(env):
220223
target_platforms = ["windows_x86_64"],
221224
whls = [],
222225
sdist = None,
226+
is_exposed = False,
223227
),
224228
],
225229
"foo": [
@@ -244,6 +248,7 @@ def _test_multi_os(env):
244248
],
245249
whls = [],
246250
sdist = None,
251+
is_exposed = True,
247252
),
248253
struct(
249254
distribution = "foo",
@@ -258,6 +263,7 @@ def _test_multi_os(env):
258263
target_platforms = ["windows_x86_64"],
259264
whls = [],
260265
sdist = None,
266+
is_exposed = True,
261267
),
262268
],
263269
})
@@ -317,6 +323,7 @@ def _test_multi_os_download_only_platform(env):
317323
target_platforms = ["linux_x86_64"],
318324
whls = [],
319325
sdist = None,
326+
is_exposed = True,
320327
),
321328
],
322329
})
@@ -371,6 +378,7 @@ def _test_os_arch_requirements_with_default(env):
371378
target_platforms = ["linux_aarch64", "linux_x86_64"],
372379
whls = [],
373380
sdist = None,
381+
is_exposed = True,
374382
),
375383
struct(
376384
distribution = "foo",
@@ -385,6 +393,7 @@ def _test_os_arch_requirements_with_default(env):
385393
target_platforms = ["linux_super_exotic"],
386394
whls = [],
387395
sdist = None,
396+
is_exposed = True,
388397
),
389398
struct(
390399
distribution = "foo",
@@ -406,6 +415,7 @@ def _test_os_arch_requirements_with_default(env):
406415
],
407416
whls = [],
408417
sdist = None,
418+
is_exposed = True,
409419
),
410420
],
411421
})

0 commit comments

Comments
 (0)