Skip to content

Commit 1de8269

Browse files
committed
wip
1 parent 7f99cb7 commit 1de8269

File tree

6 files changed

+87
-26
lines changed

6 files changed

+87
-26
lines changed

python/private/pypi/extension.bzl

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@
1616

1717
load("@bazel_features//:features.bzl", "bazel_features")
1818
load("@pythons_hub//:interpreters.bzl", "INTERPRETER_LABELS")
19+
load("@pythons_hub//:versions.bzl", "MINOR_MAPPING")
1920
load("//python/private:auth.bzl", "AUTH_ATTRS")
21+
load("//python/private:full_version.bzl", "full_version")
2022
load("//python/private:normalize_name.bzl", "normalize_name")
2123
load("//python/private:repo_utils.bzl", "repo_utils")
2224
load("//python/private:semver.bzl", "semver")
@@ -173,6 +175,7 @@ def _create_whl_repos(
173175
logger = logger,
174176
)
175177

178+
platforms = {}
176179
for whl_name, requirements in requirements_by_platform.items():
177180
group_name = whl_group_mapping.get(whl_name)
178181
group_deps = requirement_cycles.get(group_name, [])
@@ -233,6 +236,10 @@ def _create_whl_repos(
233236
))
234237

235238
whl_libraries[repo_name] = args
239+
240+
# TODO @aignas 2025-03-23: make this more efficient
241+
for p in args.pop("experimental_target_platforms", []):
242+
platforms[p] = None
236243
whl_map.setdefault(whl_name, {})[config_setting] = repo_name
237244

238245
return struct(
@@ -244,6 +251,7 @@ def _create_whl_repos(
244251
},
245252
extra_aliases = extra_aliases,
246253
whl_libraries = whl_libraries,
254+
platforms = platforms,
247255
)
248256

249257
def _whl_repos(*, requirement, whl_library_args, download_only, netrc, auth_patterns, multiple_requirements_for_whl = False, python_version):
@@ -408,6 +416,7 @@ You cannot use both the additive_build_content and additive_build_content_file a
408416
exposed_packages = {}
409417
extra_aliases = {}
410418
whl_libraries = {}
419+
platforms = {}
411420

412421
is_reproducible = True
413422

@@ -485,6 +494,7 @@ You cannot use both the additive_build_content and additive_build_content_file a
485494
extra_aliases[hub_name].setdefault(whl_name, {}).update(aliases)
486495
exposed_packages.setdefault(hub_name, {}).update(out.exposed_packages)
487496
whl_libraries.update(out.whl_libraries)
497+
platforms.setdefault(hub_name, {}).update(out.platforms)
488498

489499
# TODO @aignas 2024-04-05: how do we support different requirement
490500
# cycles for different abis/oses? For now we will need the users to
@@ -521,6 +531,17 @@ You cannot use both the additive_build_content and additive_build_content_file a
521531
}
522532
for hub_name, extra_whl_aliases in extra_aliases.items()
523533
},
534+
platforms = {
535+
hub_name: sorted(p)
536+
for hub_name, p in platforms.items()
537+
},
538+
python_versions = {
539+
hub_name: sorted({
540+
full_version(version = v, minor_mapping = MINOR_MAPPING): None
541+
for v in m.python_versions
542+
})
543+
for hub_name, m in pip_hub_map.items()
544+
},
524545
whl_libraries = {
525546
k: dict(sorted(args.items()))
526547
for k, args in sorted(whl_libraries.items())
@@ -612,6 +633,8 @@ def _pip_impl(module_ctx):
612633
for key, values in whl_map.items()
613634
},
614635
packages = mods.exposed_packages.get(hub_name, []),
636+
python_versions = mods.python_versions[hub_name],
637+
platforms = mods.platforms.get(hub_name, ["host"]),
615638
groups = mods.hub_group_map.get(hub_name),
616639
)
617640

python/private/pypi/generate_whl_library_build_bazel.bzl

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
"""Generate the BUILD.bazel contents for a repo defined by a whl_library."""
1616

17+
load("//python/private:bzlmod_enabled.bzl", "BZLMOD_ENABLED")
1718
load("//python/private:text_util.bzl", "render")
1819

1920
_RENDER = {
@@ -26,7 +27,8 @@ _RENDER = {
2627
"entry_points": render.dict,
2728
"extras": render.list,
2829
"group_deps": render.list,
29-
"platforms": render.list,
30+
"host_python_version": str,
31+
"platforms": str,
3032
"requires_dist": render.list,
3133
"srcs_exclude": render.list,
3234
"tags": render.list,
@@ -36,7 +38,7 @@ _RENDER = {
3638
# this repository can be publicly visible without the need for
3739
# export_files
3840
_TEMPLATE = """\
39-
load("@rules_python//python/private/pypi:whl_library_targets.bzl", "whl_library_targets")
41+
{loads}
4042
4143
package(default_visibility = ["//visibility:public"])
4244
@@ -61,6 +63,17 @@ def generate_whl_library_build_bazel(
6163
"""
6264

6365
additional_content = []
66+
loads = {
67+
"@rules_python//python/private/pypi:whl_library_targets.bzl": ('"whl_library_targets"',),
68+
}
69+
if BZLMOD_ENABLED:
70+
dep_template = kwargs["dep_template"]
71+
loads[dep_template.format(
72+
name = "",
73+
target = "requirements.bzl",
74+
)] = ("hub_settings = \"private\"",)
75+
kwargs["platforms"] = "hub_settings.platforms"
76+
kwargs["host_python_version"] = "hub_settings.python_versions[0]"
6477
if annotation:
6578
kwargs["data"] = annotation.data
6679
kwargs["copy_files"] = annotation.copy_files
@@ -73,6 +86,13 @@ def generate_whl_library_build_bazel(
7386
contents = "\n".join(
7487
[
7588
_TEMPLATE.format(
89+
loads = "\n".join([
90+
"load({}, {})".format(
91+
repr(path),
92+
", ".join([s for s in symbols]),
93+
)
94+
for path, symbols in loads.items()
95+
]),
7696
kwargs = render.indent("\n".join([
7797
"{} = {},".format(k, _RENDER.get(k, repr)(v))
7898
for k, v in sorted(kwargs.items())

python/private/pypi/hub_repository.bzl

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
""
1616

1717
load("//python/private:text_util.bzl", "render")
18+
load(":parse_requirements.bzl", "host_platform")
1819
load(":render_pkg_aliases.bzl", "render_multiplatform_pkg_aliases")
1920
load(":whl_config_setting.bzl", "whl_config_setting")
2021

@@ -44,6 +45,11 @@ def _impl(rctx):
4445
# `requirement`, et al. macros.
4546
macro_tmpl = "@@{name}//{{}}:{{}}".format(name = rctx.attr.name)
4647

48+
platforms = [
49+
host_platform(rctx) if p == "host" else p
50+
for p in rctx.attr.platforms
51+
]
52+
4753
rctx.file("BUILD.bazel", _BUILD_FILE_CONTENTS)
4854
rctx.template("requirements.bzl", rctx.attr._template, substitutions = {
4955
"%%ALL_DATA_REQUIREMENTS%%": render.list([
@@ -59,6 +65,8 @@ def _impl(rctx):
5965
for p in bzl_packages
6066
}),
6167
"%%MACRO_TMPL%%": macro_tmpl,
68+
"%%PLATFORMS%%": render.indent(render.list(sorted(platforms))).lstrip(),
69+
"%%PYTHON_VERSIONS%%": render.indent(render.list(sorted(rctx.attr.python_versions))).lstrip(),
6270
})
6371

6472
hub_repository = repository_rule(
@@ -74,6 +82,24 @@ hub_repository = repository_rule(
7482
mandatory = False,
7583
doc = """\
7684
The list of packages that will be exposed via all_*requirements macros. Defaults to whl_map keys.
85+
""",
86+
),
87+
# TODO @aignas 2025-03-23: get the `platforms` and `python_versions`
88+
# from the aliases? This requires us to only create aliases for the
89+
# target platforms and python_versions we care about. Python versions
90+
# probably still need to be passed in.
91+
"platforms": attr.string_list(
92+
mandatory = True,
93+
doc = """\
94+
The list of target platforms that are supported in this hub repository. This
95+
can contain 'abi_os_arch' tuples or 'host' to keep the lock files os/arch
96+
agnostic.
97+
""",
98+
),
99+
"python_versions": attr.string_list(
100+
mandatory = True,
101+
doc = """\
102+
The list of python versions that are supported in this hub repository.
77103
""",
78104
),
79105
"repo_name": attr.string(

python/private/pypi/requirements.bzl.tmpl.bzlmod

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,15 @@ all_whl_requirements = all_whl_requirements_by_package.values()
1313

1414
all_data_requirements = %%ALL_DATA_REQUIREMENTS%%
1515

16+
# Internal constants used for passing information to `whl_library`
17+
# repositories without causing re-fetching. This is not intended to be
18+
# a stable API and may break. If you would like to depend on it, please raise
19+
# a ticket describing your use-case.
20+
private = struct(
21+
python_versions = %%PYTHON_VERSIONS%%,
22+
platforms = %%PLATFORMS%%,
23+
)
24+
1625
def requirement(name):
1726
return "%%MACRO_TMPL%%".format(pip_utils.normalize_name(name), "pkg")
1827

python/private/pypi/whl_library.bzl

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ load("//python/private:repo_utils.bzl", "REPO_DEBUG_ENV_VAR", "repo_utils")
2121
load(":attrs.bzl", "ATTRS", "use_isolated")
2222
load(":deps.bzl", "all_repo_names", "record_files")
2323
load(":generate_whl_library_build_bazel.bzl", "generate_whl_library_build_bazel")
24-
load(":parse_requirements.bzl", "host_platform")
2524
load(":parse_whl_name.bzl", "parse_whl_name")
2625
load(":patch_whl.bzl", "patch_whl")
2726
load(":pypi_repo_utils.bzl", "pypi_repo_utils")
@@ -354,6 +353,7 @@ def _whl_library_impl(rctx):
354353
entry_points[entry_point_without_py] = entry_point_script_name
355354

356355
build_file_contents = generate_whl_library_build_bazel(
356+
name = metadata["name"],
357357
whl_name = whl_path.basename,
358358
# TODO @aignas 2025-03-23: load the dep_template from the hub repository
359359
dep_template = rctx.attr.dep_template or "@{}{{name}}//:{{target}}".format(rctx.attr.repo_prefix),
@@ -369,25 +369,12 @@ def _whl_library_impl(rctx):
369369
entry_points = entry_points,
370370
# TODO @aignas 2025-03-23: store the annotation in the hub repo.
371371
annotation = None if not rctx.attr.annotation else struct(**json.decode(rctx.read(rctx.attr.annotation))),
372-
name = metadata["name"],
373372
requires_dist = metadata["requires_dist"],
374-
# target the host platform if the target platform is not specified in the rule.
375-
# TODO @aignas 2025-03-23: we should materialize this inside the
376-
# hub_repository `requirements.bzl` file as `TARGET_PLATFORMS` with a
377-
# note, that this is internal and will be only for usage of the
378-
# `whl_library`
379-
platforms = target_platforms or [
380-
"{}_{}".format(metadata["abi"], host_platform(rctx)),
381-
],
382-
# TODO @aignas 2025-03-23: we should expose the requested extras via a
383-
# dict in `requirements.bzl` `EXTRAS` where the key is the package name
384-
# and the value is the list of requested extras. like the above, for
385-
# internal usage only.
373+
# TODO @aignas 2025-03-23: we should just generate targets for all of the
374+
# exposed extras and ask users to depend on this by `@pypi//foo:foo__extra`.
375+
# Since all of the dependencies go through the `hub` repository, the extras
376+
# that include packages that we don't
386377
extras = metadata["extras"],
387-
# TODO @aignas 2025-03-23: we should expose full python version via the
388-
# TARGET_PYTHON_VERSIONS list so that we can correctly calculate the
389-
# deps. This would be again, internal only stuff.
390-
host_python_version = metadata["python_version"],
391378
)
392379
rctx.file("BUILD.bazel", build_file_contents)
393380

python/private/pypi/whl_library_targets.bzl

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ def whl_library_targets(
5858
copy_file = copy_file,
5959
py_binary = py_binary,
6060
py_library = py_library,
61+
deps = deps,
6162
)):
6263
"""Create all of the whl_library targets.
6364
@@ -101,7 +102,7 @@ def whl_library_targets(
101102
# the analysis phase. This means that we need to get the target platform abi
102103
# from the python version/versions we are setting the package up for. We can
103104
# potentially get this from the python toolchain interpreter.
104-
package_deps = deps(
105+
package_deps = rules.deps(
105106
name = name,
106107
requires_dist = requires_dist,
107108
platforms = platforms,
@@ -112,11 +113,6 @@ def whl_library_targets(
112113
dependencies = package_deps.deps
113114
dependencies_by_platform = package_deps.deps_select
114115

115-
dependencies = sorted([normalize_name(d) for d in dependencies])
116-
dependencies_by_platform = {
117-
platform: sorted([normalize_name(d) for d in deps])
118-
for platform, deps in dependencies_by_platform.items()
119-
}
120116
tags = sorted(tags)
121117
data = [] + data
122118

0 commit comments

Comments
 (0)