From 4a816ca23e0fe4990316b04b2a9b12edfac5690f Mon Sep 17 00:00:00 2001 From: Greg Date: Tue, 18 Jun 2024 22:54:45 +1000 Subject: [PATCH 01/67] Spike uv --- examples/bzlmod/requirements_windows_3_9.txt | 54 ++++++++++---------- python/private/bzlmod/pin.sh | 9 ++++ python/private/bzlmod/pip.bzl | 53 +++++++++++++++++++ python/private/bzlmod/pip_repository.bzl | 21 +++++++- 4 files changed, 110 insertions(+), 27 deletions(-) create mode 100644 python/private/bzlmod/pin.sh diff --git a/examples/bzlmod/requirements_windows_3_9.txt b/examples/bzlmod/requirements_windows_3_9.txt index 636b4dfc3e..0821958301 100644 --- a/examples/bzlmod/requirements_windows_3_9.txt +++ b/examples/bzlmod/requirements_windows_3_9.txt @@ -1,11 +1,5 @@ -# -# This file is autogenerated by pip-compile with Python 3.9 -# by the following command: -# -# bazel run //:requirements_3_9.update -# ---extra-index-url https://pypi.org/simple/ - +# This file was autogenerated by uv via the following command: +# uv pip compile /Users/groodt/work/rules_python/examples/bzlmod/requirements.in --python-platform windows --python-version 3.9 --output-file /Users/groodt/work/rules_python/examples/bzlmod/requirements_windows_3_9.txt --generate-hashes --no-strip-extras alabaster==0.7.13 \ --hash=sha256:1ee19aca801bbabb5ba3f5f258e4422dfa86f82f3e9cefb0859b283cdd7f62a3 \ --hash=sha256:a27a4a084d5e690e16e01e03ad2b2e552c61a65469419b907243193de1a84ae2 @@ -30,7 +24,7 @@ colorama==0.4.6 \ --hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \ --hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 # via - # -r requirements.in + # -r /Users/groodt/work/rules_python/examples/bzlmod/requirements.in # pylint # sphinx dill==0.3.6 \ @@ -186,17 +180,17 @@ pylint==2.15.9 \ --hash=sha256:18783cca3cfee5b83c6c5d10b3cdb66c6594520ffae61890858fe8d932e1c6b4 \ --hash=sha256:349c8cd36aede4d50a0754a8c0218b43323d13d5d88f4b2952ddfe3e169681eb # via - # -r requirements.in + # -r /Users/groodt/work/rules_python/examples/bzlmod/requirements.in # pylint-print pylint-print==1.0.1 \ --hash=sha256:30aa207e9718ebf4ceb47fb87012092e6d8743aab932aa07aa14a73e750ad3d0 \ --hash=sha256:a2b2599e7887b93e551db2624c523c1e6e9e58c3be8416cd98d41e4427e2669b - # via -r requirements.in + # via -r /Users/groodt/work/rules_python/examples/bzlmod/requirements.in python-dateutil==2.8.2 \ --hash=sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86 \ --hash=sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9 # via - # -r requirements.in + # -r /Users/groodt/work/rules_python/examples/bzlmod/requirements.in # s3cmd python-magic==0.4.27 \ --hash=sha256:c1ba14b08e4a5f5c31a302b7721239695b2f0f058d125bd5ce1ee36b9d9d3c3b \ @@ -259,12 +253,16 @@ requests==2.25.1 \ --hash=sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804 \ --hash=sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e # via - # -r requirements.in + # -r /Users/groodt/work/rules_python/examples/bzlmod/requirements.in # sphinx s3cmd==2.1.0 \ --hash=sha256:49cd23d516b17974b22b611a95ce4d93fe326feaa07320bd1d234fed68cbccfa \ --hash=sha256:966b0a494a916fc3b4324de38f089c86c70ee90e8e1cae6d59102103a4c0cc03 - # via -r requirements.in + # via -r /Users/groodt/work/rules_python/examples/bzlmod/requirements.in +setuptools==65.6.3 \ + --hash=sha256:57f6f22bde4e042978bcd50176fdb381d7c21a9efa4041202288d3737a0c6a54 \ + --hash=sha256:a7620757bf984b58deaf32fc8a4577a9bbc0850cf92c20e1ce41c38c19e5fb75 + # via yamllint six==1.16.0 \ --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \ --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254 @@ -277,7 +275,7 @@ sphinx==7.2.6 \ --hash=sha256:1e09160a40b956dc623c910118fa636da93bd3ca0b9876a7b3df90f07d691560 \ --hash=sha256:9a5160e1ea90688d5963ba09a2dcd8bdd526620edbb65c328728f1b2228d5ab5 # via - # -r requirements.in + # -r /Users/groodt/work/rules_python/examples/bzlmod/requirements.in # sphinxcontrib-applehelp # sphinxcontrib-devhelp # sphinxcontrib-htmlhelp @@ -307,12 +305,12 @@ sphinxcontrib-serializinghtml==1.1.9 \ --hash=sha256:0c64ff898339e1fac29abd2bf5f11078f3ec413cfe9c046d3120d7ca65530b54 \ --hash=sha256:9b36e503703ff04f20e9675771df105e58aa029cfcbc23b8ed716019b7416ae1 # via - # -r requirements.in + # -r /Users/groodt/work/rules_python/examples/bzlmod/requirements.in # sphinx tabulate==0.9.0 \ --hash=sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c \ --hash=sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f - # via -r requirements.in + # via -r /Users/groodt/work/rules_python/examples/bzlmod/requirements.in tomli==2.0.1 \ --hash=sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc \ --hash=sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f @@ -402,11 +400,11 @@ websockets==11.0.3 \ --hash=sha256:f61bdb1df43dc9c131791fbc2355535f9024b9a04398d3bd0684fc16ab07df74 \ --hash=sha256:fb06eea71a00a7af0ae6aefbb932fb8a7df3cb390cc217d51a9ad7343de1b8d0 \ --hash=sha256:ffd7dcaf744f25f82190856bc26ed81721508fc5cbf2a330751e135ff1283564 - # via -r requirements.in + # via -r /Users/groodt/work/rules_python/examples/bzlmod/requirements.in wheel==0.40.0 \ --hash=sha256:cd1196f3faee2b31968d626e1731c94f99cbdb67cf5a46e4f5656cbee7738873 \ --hash=sha256:d236b20e7cb522daf2390fa84c55eea81c5c30190f90f29ae2ca1ad8355bf247 - # via -r requirements.in + # via -r /Users/groodt/work/rules_python/examples/bzlmod/requirements.in wrapt==1.14.1 \ --hash=sha256:00b6d4ea20a906c0ca56d84f93065b398ab74b927a7a3dbd470f6fc503f95dc3 \ --hash=sha256:01c205616a89d09827986bc4e859bcabd64f5a0662a7fe95e0d359424e0e071b \ @@ -414,23 +412,30 @@ wrapt==1.14.1 \ --hash=sha256:07f7a7d0f388028b2df1d916e94bbb40624c59b48ecc6cbc232546706fac74c2 \ --hash=sha256:11871514607b15cfeb87c547a49bca19fde402f32e2b1c24a632506c0a756656 \ --hash=sha256:1b376b3f4896e7930f1f772ac4b064ac12598d1c38d04907e696cc4d794b43d3 \ + --hash=sha256:2020f391008ef874c6d9e208b24f28e31bcb85ccff4f335f15a3251d222b92d9 \ --hash=sha256:21ac0156c4b089b330b7666db40feee30a5d52634cc4560e1905d6529a3897ff \ + --hash=sha256:240b1686f38ae665d1b15475966fe0472f78e71b1b4903c143a842659c8e4cb9 \ --hash=sha256:257fd78c513e0fb5cdbe058c27a0624c9884e735bbd131935fd49e9fe719d310 \ + --hash=sha256:26046cd03936ae745a502abf44dac702a5e6880b2b01c29aea8ddf3353b68224 \ --hash=sha256:2b39d38039a1fdad98c87279b48bc5dce2c0ca0d73483b12cb72aa9609278e8a \ --hash=sha256:2cf71233a0ed05ccdabe209c606fe0bac7379fdcf687f39b944420d2a09fdb57 \ --hash=sha256:2fe803deacd09a233e4762a1adcea5db5d31e6be577a43352936179d14d90069 \ + --hash=sha256:2feecf86e1f7a86517cab34ae6c2f081fd2d0dac860cb0c0ded96d799d20b335 \ --hash=sha256:3232822c7d98d23895ccc443bbdf57c7412c5a65996c30442ebe6ed3df335383 \ --hash=sha256:34aa51c45f28ba7f12accd624225e2b1e5a3a45206aa191f6f9aac931d9d56fe \ + --hash=sha256:358fe87cc899c6bb0ddc185bf3dbfa4ba646f05b1b0b9b5a27c2cb92c2cea204 \ --hash=sha256:36f582d0c6bc99d5f39cd3ac2a9062e57f3cf606ade29a0a0d6b323462f4dd87 \ --hash=sha256:380a85cf89e0e69b7cfbe2ea9f765f004ff419f34194018a6827ac0e3edfed4d \ --hash=sha256:40e7bc81c9e2b2734ea4bc1aceb8a8f0ceaac7c5299bc5d69e37c44d9081d43b \ --hash=sha256:43ca3bbbe97af00f49efb06e352eae40434ca9d915906f77def219b88e85d907 \ + --hash=sha256:49ef582b7a1152ae2766557f0550a9fcbf7bbd76f43fbdc94dd3bf07cc7168be \ --hash=sha256:4fcc4649dc762cddacd193e6b55bc02edca674067f5f98166d7713b193932b7f \ --hash=sha256:5a0f54ce2c092aaf439813735584b9537cad479575a09892b8352fea5e988dc0 \ --hash=sha256:5a9a0d155deafd9448baff28c08e150d9b24ff010e899311ddd63c45c2445e28 \ --hash=sha256:5b02d65b9ccf0ef6c34cba6cf5bf2aab1bb2f49c6090bafeecc9cd81ad4ea1c1 \ --hash=sha256:60db23fa423575eeb65ea430cee741acb7c26a1365d103f7b0f6ec412b893853 \ --hash=sha256:642c2e7a804fcf18c222e1060df25fc210b9c58db7c91416fb055897fc27e8cc \ + --hash=sha256:6447e9f3ba72f8e2b985a1da758767698efa72723d5b59accefd716e9e8272bf \ --hash=sha256:6a9a25751acb379b466ff6be78a315e2b439d4c94c1e99cb7266d40a537995d3 \ --hash=sha256:6b1a564e6cb69922c7fe3a678b9f9a3c54e72b469875aa8018f18b4d1dd1adf3 \ --hash=sha256:6d323e1554b3d22cfc03cd3243b5bb815a51f5249fdcbb86fda4bf62bab9e164 \ @@ -453,8 +458,10 @@ wrapt==1.14.1 \ --hash=sha256:9e0fd32e0148dd5dea6af5fee42beb949098564cc23211a88d799e434255a1f4 \ --hash=sha256:9f3e6f9e05148ff90002b884fbc2a86bd303ae847e472f44ecc06c2cd2fcdb2d \ --hash=sha256:a85d2b46be66a71bedde836d9e41859879cc54a2a04fad1191eb50c2066f6e9d \ + --hash=sha256:a9008dad07d71f68487c91e96579c8567c98ca4c3881b9b113bc7b33e9fd78b8 \ --hash=sha256:a9a52172be0b5aae932bef82a79ec0a0ce87288c7d132946d645eba03f0ad8a8 \ --hash=sha256:aa31fdcc33fef9eb2552cbcbfee7773d5a6792c137b359e82879c101e98584c5 \ + --hash=sha256:acae32e13a4153809db37405f5eba5bac5fbe2e2ba61ab227926a22901051c0a \ --hash=sha256:b014c23646a467558be7da3d6b9fa409b2c567d2110599b7cf9a0c5992b3b471 \ --hash=sha256:b21bb4c09ffabfa0e85e3a6b623e19b80e7acd709b9f91452b8297ace2a8ab00 \ --hash=sha256:b5901a312f4d14c59918c221323068fad0540e34324925c8475263841dbdfe68 \ @@ -469,6 +476,7 @@ wrapt==1.14.1 \ --hash=sha256:dee60e1de1898bde3b238f18340eec6148986da0455d8ba7848d50470a7a32fb \ --hash=sha256:e2f83e18fe2f4c9e7db597e988f72712c0c3676d337d8b101f6758107c42425b \ --hash=sha256:e3fb1677c720409d5f671e39bac6c9e0e422584e5f518bfd50aa4cbbea02433f \ + --hash=sha256:ecee4132c6cd2ce5308e21672015ddfed1ff975ad0ac8d27168ea82e71413f55 \ --hash=sha256:ee2b1b1769f6707a8a445162ea16dddf74285c3964f605877a20e38545c3c462 \ --hash=sha256:ee6acae74a2b91865910eef5e7de37dc6895ad96fa23603d1d27ea69df545015 \ --hash=sha256:ef3f72c9666bba2bab70d2a8b79f2c6d2c1a42a7f7e2b0ec83bb2f9e383950af @@ -476,14 +484,8 @@ wrapt==1.14.1 \ yamllint==1.28.0 \ --hash=sha256:89bb5b5ac33b1ade059743cf227de73daa34d5e5a474b06a5e17fc16583b0cf2 \ --hash=sha256:9e3d8ddd16d0583214c5fdffe806c9344086721f107435f68bad990e5a88826b - # via -r requirements.in + # via -r /Users/groodt/work/rules_python/examples/bzlmod/requirements.in zipp==3.17.0 \ --hash=sha256:0e923e726174922dce09c53c59ad483ff7bbb8e572e00c7f7c46b88556409f31 \ --hash=sha256:84e64a1c28cf7e91ed2078bb8cc8c259cb19b76942096c8d7b84947690cabaf0 # via importlib-metadata - -# The following packages are considered to be unsafe in a requirements file: -setuptools==65.6.3 \ - --hash=sha256:57f6f22bde4e042978bcd50176fdb381d7c21a9efa4041202288d3737a0c6a54 \ - --hash=sha256:a7620757bf984b58deaf32fc8a4577a9bbc0850cf92c20e1ce41c38c19e5fb75 - # via yamllint diff --git a/python/private/bzlmod/pin.sh b/python/private/bzlmod/pin.sh new file mode 100644 index 0000000000..6744a3de78 --- /dev/null +++ b/python/private/bzlmod/pin.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +set -euo pipefail + +uv_path=$1 +shift + +$uv_path pip compile \ + "$@" diff --git a/python/private/bzlmod/pip.bzl b/python/private/bzlmod/pip.bzl index 122debd2a2..072ff3b8ae 100644 --- a/python/private/bzlmod/pip.bzl +++ b/python/private/bzlmod/pip.bzl @@ -14,6 +14,8 @@ "pip module extension for use with bzlmod" +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") +load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe") load("@bazel_features//:features.bzl", "bazel_features") load("@pythons_hub//:interpreters.bzl", "DEFAULT_PYTHON_VERSION", "INTERPRETER_LABELS") load( @@ -323,6 +325,52 @@ def _create_whl_repos(module_ctx, pip_attr, whl_map, whl_overrides, group_map, s return is_hub_reproducible +# TODO(groodt): Add more platforms +_UV_DEPS = { + "linux_aarch64": ( + "https://files.pythonhosted.org/packages/00/82/3d0acad7ebd4098aaa23f163b492b47fd9321b2681c55918fe5f18856513/uv-0.2.12-py3-none-manylinux_2_28_aarch64.whl", + "05d809516b651997a151585c9bbd150d888e71976a734781a3dde95430c1cab2" + ), + "linux_x86_64": ( + "https://files.pythonhosted.org/packages/d9/85/e608bfe78772afa3f9807a074203982131ff9c12e279bb3bc502e14d51ab/uv-0.2.12-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", + "78d5329094de1f6b503bffe00abcdf1aaa7b3e4aa2aa373e128d7faf39b98de9", + ), + "osx_x86_64": ( + "https://files.pythonhosted.org/packages/ff/f5/df24800e195f10e41aeb4a89f38488aca76c22d0f87c3eb8bf309f940aa3/uv-0.2.12-py3-none-macosx_10_12_x86_64.whl", + "85d2b9649c14014d6c54ecfb5d36f57e5c0e890957078ed4937e03569141d99b", + ), +} + +# Repository to retrieve tools for pinning dependencies. +# We currently use uv as a dependency for the pinning tool. +def _fetch_pin_dependencies(python_version, platform): + url, sha256 = _UV_DEPS.get(platform) + py_version_label = "cp" + version_label(python_version) + + name = "{py_version_label}_{platform}_uv".format( + py_version_label = py_version_label, + platform = platform, + ) + maybe( + http_archive, + name = name, + build_file_content = """ +filegroup( + name = "uv", + srcs = glob(["*/scripts/uv"]), + visibility = ["//visibility:public"], +) +""", + sha256 = sha256, + type = "zip", + urls = [url], + ) + + return "@{py_version_label}_{platform}_uv//:uv".format( + py_version_label = py_version_label, + platform = platform, + ) + def _pip_impl(module_ctx): """Implementation of a class tag that creates the pip hub and corresponding pip spoke whl repositories. @@ -472,6 +520,10 @@ def _pip_impl(module_ctx): is_hub_reproducible = _create_whl_repos(module_ctx, pip_attr, hub_whl_map, whl_overrides, hub_group_map, simpleapi_cache) is_extension_reproducible = is_extension_reproducible and is_hub_reproducible + # Register repository for pin tooling + repository_platform = host_platform(module_ctx.os) + pin_tool_label = _fetch_pin_dependencies(_major_minor_version(DEFAULT_PYTHON_VERSION), repository_platform) + for hub_name, whl_map in hub_whl_map.items(): pip_repository( name = hub_name, @@ -482,6 +534,7 @@ def _pip_impl(module_ctx): }, default_version = _major_minor_version(DEFAULT_PYTHON_VERSION), groups = hub_group_map.get(hub_name), + pin_tool_label = pin_tool_label, ) if bazel_features.external_deps.extension_metadata_has_reproducible: diff --git a/python/private/bzlmod/pip_repository.bzl b/python/private/bzlmod/pip_repository.bzl index d42eb8b056..3df9829294 100644 --- a/python/private/bzlmod/pip_repository.bzl +++ b/python/private/bzlmod/pip_repository.bzl @@ -26,6 +26,18 @@ package(default_visibility = ["//visibility:public"]) # Ensure the `requirements.bzl` source can be accessed by stardoc, since users load() from it exports_files(["requirements.bzl"]) + +sh_binary( + name = "pin", + srcs = ["pin.sh"], + data = [ + "{pin_tool_label}", + ], + args = [ + "$(location {pin_tool_label})", + ], + visibility = ["//visibility:public"], +) """ def _pip_repository_impl(rctx): @@ -48,7 +60,10 @@ def _pip_repository_impl(rctx): # `requirement`, et al. macros. macro_tmpl = "@@{name}//{{}}:{{}}".format(name = rctx.attr.name) - rctx.file("BUILD.bazel", _BUILD_FILE_CONTENTS) + rctx.template("pin.sh", rctx.attr._pin) + rctx.file("BUILD.bazel", _BUILD_FILE_CONTENTS.format( + pin_tool_label = rctx.attr.pin_tool_label, + )) rctx.template("requirements.bzl", rctx.attr._template, substitutions = { "%%ALL_DATA_REQUIREMENTS%%": render.list([ macro_tmpl.format(p, "data") @@ -91,6 +106,10 @@ in the pip.parse tag class. "_template": attr.label( default = ":requirements.bzl.tmpl", ), + "_pin": attr.label(default = ":pin.sh"), + "pin_tool_label": attr.string( + mandatory = True, + ), } pip_repository = repository_rule( From 6d0bdeb2dca9c9459f9bd7807fb8c927f7270c75 Mon Sep 17 00:00:00 2001 From: Greg Date: Tue, 18 Jun 2024 23:15:19 +1000 Subject: [PATCH 02/67] Spike uv --- examples/bzlmod/requirements_windows_3_9.txt | 54 ++++++++++---------- 1 file changed, 26 insertions(+), 28 deletions(-) diff --git a/examples/bzlmod/requirements_windows_3_9.txt b/examples/bzlmod/requirements_windows_3_9.txt index 0821958301..636b4dfc3e 100644 --- a/examples/bzlmod/requirements_windows_3_9.txt +++ b/examples/bzlmod/requirements_windows_3_9.txt @@ -1,5 +1,11 @@ -# This file was autogenerated by uv via the following command: -# uv pip compile /Users/groodt/work/rules_python/examples/bzlmod/requirements.in --python-platform windows --python-version 3.9 --output-file /Users/groodt/work/rules_python/examples/bzlmod/requirements_windows_3_9.txt --generate-hashes --no-strip-extras +# +# This file is autogenerated by pip-compile with Python 3.9 +# by the following command: +# +# bazel run //:requirements_3_9.update +# +--extra-index-url https://pypi.org/simple/ + alabaster==0.7.13 \ --hash=sha256:1ee19aca801bbabb5ba3f5f258e4422dfa86f82f3e9cefb0859b283cdd7f62a3 \ --hash=sha256:a27a4a084d5e690e16e01e03ad2b2e552c61a65469419b907243193de1a84ae2 @@ -24,7 +30,7 @@ colorama==0.4.6 \ --hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \ --hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 # via - # -r /Users/groodt/work/rules_python/examples/bzlmod/requirements.in + # -r requirements.in # pylint # sphinx dill==0.3.6 \ @@ -180,17 +186,17 @@ pylint==2.15.9 \ --hash=sha256:18783cca3cfee5b83c6c5d10b3cdb66c6594520ffae61890858fe8d932e1c6b4 \ --hash=sha256:349c8cd36aede4d50a0754a8c0218b43323d13d5d88f4b2952ddfe3e169681eb # via - # -r /Users/groodt/work/rules_python/examples/bzlmod/requirements.in + # -r requirements.in # pylint-print pylint-print==1.0.1 \ --hash=sha256:30aa207e9718ebf4ceb47fb87012092e6d8743aab932aa07aa14a73e750ad3d0 \ --hash=sha256:a2b2599e7887b93e551db2624c523c1e6e9e58c3be8416cd98d41e4427e2669b - # via -r /Users/groodt/work/rules_python/examples/bzlmod/requirements.in + # via -r requirements.in python-dateutil==2.8.2 \ --hash=sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86 \ --hash=sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9 # via - # -r /Users/groodt/work/rules_python/examples/bzlmod/requirements.in + # -r requirements.in # s3cmd python-magic==0.4.27 \ --hash=sha256:c1ba14b08e4a5f5c31a302b7721239695b2f0f058d125bd5ce1ee36b9d9d3c3b \ @@ -253,16 +259,12 @@ requests==2.25.1 \ --hash=sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804 \ --hash=sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e # via - # -r /Users/groodt/work/rules_python/examples/bzlmod/requirements.in + # -r requirements.in # sphinx s3cmd==2.1.0 \ --hash=sha256:49cd23d516b17974b22b611a95ce4d93fe326feaa07320bd1d234fed68cbccfa \ --hash=sha256:966b0a494a916fc3b4324de38f089c86c70ee90e8e1cae6d59102103a4c0cc03 - # via -r /Users/groodt/work/rules_python/examples/bzlmod/requirements.in -setuptools==65.6.3 \ - --hash=sha256:57f6f22bde4e042978bcd50176fdb381d7c21a9efa4041202288d3737a0c6a54 \ - --hash=sha256:a7620757bf984b58deaf32fc8a4577a9bbc0850cf92c20e1ce41c38c19e5fb75 - # via yamllint + # via -r requirements.in six==1.16.0 \ --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \ --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254 @@ -275,7 +277,7 @@ sphinx==7.2.6 \ --hash=sha256:1e09160a40b956dc623c910118fa636da93bd3ca0b9876a7b3df90f07d691560 \ --hash=sha256:9a5160e1ea90688d5963ba09a2dcd8bdd526620edbb65c328728f1b2228d5ab5 # via - # -r /Users/groodt/work/rules_python/examples/bzlmod/requirements.in + # -r requirements.in # sphinxcontrib-applehelp # sphinxcontrib-devhelp # sphinxcontrib-htmlhelp @@ -305,12 +307,12 @@ sphinxcontrib-serializinghtml==1.1.9 \ --hash=sha256:0c64ff898339e1fac29abd2bf5f11078f3ec413cfe9c046d3120d7ca65530b54 \ --hash=sha256:9b36e503703ff04f20e9675771df105e58aa029cfcbc23b8ed716019b7416ae1 # via - # -r /Users/groodt/work/rules_python/examples/bzlmod/requirements.in + # -r requirements.in # sphinx tabulate==0.9.0 \ --hash=sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c \ --hash=sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f - # via -r /Users/groodt/work/rules_python/examples/bzlmod/requirements.in + # via -r requirements.in tomli==2.0.1 \ --hash=sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc \ --hash=sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f @@ -400,11 +402,11 @@ websockets==11.0.3 \ --hash=sha256:f61bdb1df43dc9c131791fbc2355535f9024b9a04398d3bd0684fc16ab07df74 \ --hash=sha256:fb06eea71a00a7af0ae6aefbb932fb8a7df3cb390cc217d51a9ad7343de1b8d0 \ --hash=sha256:ffd7dcaf744f25f82190856bc26ed81721508fc5cbf2a330751e135ff1283564 - # via -r /Users/groodt/work/rules_python/examples/bzlmod/requirements.in + # via -r requirements.in wheel==0.40.0 \ --hash=sha256:cd1196f3faee2b31968d626e1731c94f99cbdb67cf5a46e4f5656cbee7738873 \ --hash=sha256:d236b20e7cb522daf2390fa84c55eea81c5c30190f90f29ae2ca1ad8355bf247 - # via -r /Users/groodt/work/rules_python/examples/bzlmod/requirements.in + # via -r requirements.in wrapt==1.14.1 \ --hash=sha256:00b6d4ea20a906c0ca56d84f93065b398ab74b927a7a3dbd470f6fc503f95dc3 \ --hash=sha256:01c205616a89d09827986bc4e859bcabd64f5a0662a7fe95e0d359424e0e071b \ @@ -412,30 +414,23 @@ wrapt==1.14.1 \ --hash=sha256:07f7a7d0f388028b2df1d916e94bbb40624c59b48ecc6cbc232546706fac74c2 \ --hash=sha256:11871514607b15cfeb87c547a49bca19fde402f32e2b1c24a632506c0a756656 \ --hash=sha256:1b376b3f4896e7930f1f772ac4b064ac12598d1c38d04907e696cc4d794b43d3 \ - --hash=sha256:2020f391008ef874c6d9e208b24f28e31bcb85ccff4f335f15a3251d222b92d9 \ --hash=sha256:21ac0156c4b089b330b7666db40feee30a5d52634cc4560e1905d6529a3897ff \ - --hash=sha256:240b1686f38ae665d1b15475966fe0472f78e71b1b4903c143a842659c8e4cb9 \ --hash=sha256:257fd78c513e0fb5cdbe058c27a0624c9884e735bbd131935fd49e9fe719d310 \ - --hash=sha256:26046cd03936ae745a502abf44dac702a5e6880b2b01c29aea8ddf3353b68224 \ --hash=sha256:2b39d38039a1fdad98c87279b48bc5dce2c0ca0d73483b12cb72aa9609278e8a \ --hash=sha256:2cf71233a0ed05ccdabe209c606fe0bac7379fdcf687f39b944420d2a09fdb57 \ --hash=sha256:2fe803deacd09a233e4762a1adcea5db5d31e6be577a43352936179d14d90069 \ - --hash=sha256:2feecf86e1f7a86517cab34ae6c2f081fd2d0dac860cb0c0ded96d799d20b335 \ --hash=sha256:3232822c7d98d23895ccc443bbdf57c7412c5a65996c30442ebe6ed3df335383 \ --hash=sha256:34aa51c45f28ba7f12accd624225e2b1e5a3a45206aa191f6f9aac931d9d56fe \ - --hash=sha256:358fe87cc899c6bb0ddc185bf3dbfa4ba646f05b1b0b9b5a27c2cb92c2cea204 \ --hash=sha256:36f582d0c6bc99d5f39cd3ac2a9062e57f3cf606ade29a0a0d6b323462f4dd87 \ --hash=sha256:380a85cf89e0e69b7cfbe2ea9f765f004ff419f34194018a6827ac0e3edfed4d \ --hash=sha256:40e7bc81c9e2b2734ea4bc1aceb8a8f0ceaac7c5299bc5d69e37c44d9081d43b \ --hash=sha256:43ca3bbbe97af00f49efb06e352eae40434ca9d915906f77def219b88e85d907 \ - --hash=sha256:49ef582b7a1152ae2766557f0550a9fcbf7bbd76f43fbdc94dd3bf07cc7168be \ --hash=sha256:4fcc4649dc762cddacd193e6b55bc02edca674067f5f98166d7713b193932b7f \ --hash=sha256:5a0f54ce2c092aaf439813735584b9537cad479575a09892b8352fea5e988dc0 \ --hash=sha256:5a9a0d155deafd9448baff28c08e150d9b24ff010e899311ddd63c45c2445e28 \ --hash=sha256:5b02d65b9ccf0ef6c34cba6cf5bf2aab1bb2f49c6090bafeecc9cd81ad4ea1c1 \ --hash=sha256:60db23fa423575eeb65ea430cee741acb7c26a1365d103f7b0f6ec412b893853 \ --hash=sha256:642c2e7a804fcf18c222e1060df25fc210b9c58db7c91416fb055897fc27e8cc \ - --hash=sha256:6447e9f3ba72f8e2b985a1da758767698efa72723d5b59accefd716e9e8272bf \ --hash=sha256:6a9a25751acb379b466ff6be78a315e2b439d4c94c1e99cb7266d40a537995d3 \ --hash=sha256:6b1a564e6cb69922c7fe3a678b9f9a3c54e72b469875aa8018f18b4d1dd1adf3 \ --hash=sha256:6d323e1554b3d22cfc03cd3243b5bb815a51f5249fdcbb86fda4bf62bab9e164 \ @@ -458,10 +453,8 @@ wrapt==1.14.1 \ --hash=sha256:9e0fd32e0148dd5dea6af5fee42beb949098564cc23211a88d799e434255a1f4 \ --hash=sha256:9f3e6f9e05148ff90002b884fbc2a86bd303ae847e472f44ecc06c2cd2fcdb2d \ --hash=sha256:a85d2b46be66a71bedde836d9e41859879cc54a2a04fad1191eb50c2066f6e9d \ - --hash=sha256:a9008dad07d71f68487c91e96579c8567c98ca4c3881b9b113bc7b33e9fd78b8 \ --hash=sha256:a9a52172be0b5aae932bef82a79ec0a0ce87288c7d132946d645eba03f0ad8a8 \ --hash=sha256:aa31fdcc33fef9eb2552cbcbfee7773d5a6792c137b359e82879c101e98584c5 \ - --hash=sha256:acae32e13a4153809db37405f5eba5bac5fbe2e2ba61ab227926a22901051c0a \ --hash=sha256:b014c23646a467558be7da3d6b9fa409b2c567d2110599b7cf9a0c5992b3b471 \ --hash=sha256:b21bb4c09ffabfa0e85e3a6b623e19b80e7acd709b9f91452b8297ace2a8ab00 \ --hash=sha256:b5901a312f4d14c59918c221323068fad0540e34324925c8475263841dbdfe68 \ @@ -476,7 +469,6 @@ wrapt==1.14.1 \ --hash=sha256:dee60e1de1898bde3b238f18340eec6148986da0455d8ba7848d50470a7a32fb \ --hash=sha256:e2f83e18fe2f4c9e7db597e988f72712c0c3676d337d8b101f6758107c42425b \ --hash=sha256:e3fb1677c720409d5f671e39bac6c9e0e422584e5f518bfd50aa4cbbea02433f \ - --hash=sha256:ecee4132c6cd2ce5308e21672015ddfed1ff975ad0ac8d27168ea82e71413f55 \ --hash=sha256:ee2b1b1769f6707a8a445162ea16dddf74285c3964f605877a20e38545c3c462 \ --hash=sha256:ee6acae74a2b91865910eef5e7de37dc6895ad96fa23603d1d27ea69df545015 \ --hash=sha256:ef3f72c9666bba2bab70d2a8b79f2c6d2c1a42a7f7e2b0ec83bb2f9e383950af @@ -484,8 +476,14 @@ wrapt==1.14.1 \ yamllint==1.28.0 \ --hash=sha256:89bb5b5ac33b1ade059743cf227de73daa34d5e5a474b06a5e17fc16583b0cf2 \ --hash=sha256:9e3d8ddd16d0583214c5fdffe806c9344086721f107435f68bad990e5a88826b - # via -r /Users/groodt/work/rules_python/examples/bzlmod/requirements.in + # via -r requirements.in zipp==3.17.0 \ --hash=sha256:0e923e726174922dce09c53c59ad483ff7bbb8e572e00c7f7c46b88556409f31 \ --hash=sha256:84e64a1c28cf7e91ed2078bb8cc8c259cb19b76942096c8d7b84947690cabaf0 # via importlib-metadata + +# The following packages are considered to be unsafe in a requirements file: +setuptools==65.6.3 \ + --hash=sha256:57f6f22bde4e042978bcd50176fdb381d7c21a9efa4041202288d3737a0c6a54 \ + --hash=sha256:a7620757bf984b58deaf32fc8a4577a9bbc0850cf92c20e1ce41c38c19e5fb75 + # via yamllint From c5c3f881bd47355e6e14500242f9890aa52140d0 Mon Sep 17 00:00:00 2001 From: Greg Date: Wed, 19 Jun 2024 00:04:07 +1000 Subject: [PATCH 03/67] Adds Windows --- python/private/bzlmod/pip.bzl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/python/private/bzlmod/pip.bzl b/python/private/bzlmod/pip.bzl index 072ff3b8ae..363eb01941 100644 --- a/python/private/bzlmod/pip.bzl +++ b/python/private/bzlmod/pip.bzl @@ -339,6 +339,10 @@ _UV_DEPS = { "https://files.pythonhosted.org/packages/ff/f5/df24800e195f10e41aeb4a89f38488aca76c22d0f87c3eb8bf309f940aa3/uv-0.2.12-py3-none-macosx_10_12_x86_64.whl", "85d2b9649c14014d6c54ecfb5d36f57e5c0e890957078ed4937e03569141d99b", ), + "windows_x86_64": ( + "https://files.pythonhosted.org/packages/c8/bc/a905f3d4b961781ead58243bd4f3c6cd2fcb2deaa55c565a64ba7d06cd20/uv-0.2.12-py3-none-win_amd64.whl", + "ca95af397769422e11e87dc147be1262a54d3a13d8837b69c80fad20f1ff9af4", + ), } # Repository to retrieve tools for pinning dependencies. From f038ce8f9fc7b380aca39c51efb1cae2ed4993da Mon Sep 17 00:00:00 2001 From: Greg Date: Wed, 19 Jun 2024 00:06:37 +1000 Subject: [PATCH 04/67] buildifier --- python/private/bzlmod/pip.bzl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/private/bzlmod/pip.bzl b/python/private/bzlmod/pip.bzl index 363eb01941..339852102c 100644 --- a/python/private/bzlmod/pip.bzl +++ b/python/private/bzlmod/pip.bzl @@ -14,9 +14,9 @@ "pip module extension for use with bzlmod" +load("@bazel_features//:features.bzl", "bazel_features") load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe") -load("@bazel_features//:features.bzl", "bazel_features") load("@pythons_hub//:interpreters.bzl", "DEFAULT_PYTHON_VERSION", "INTERPRETER_LABELS") load( "//python/pip_install:pip_repository.bzl", @@ -329,7 +329,7 @@ def _create_whl_repos(module_ctx, pip_attr, whl_map, whl_overrides, group_map, s _UV_DEPS = { "linux_aarch64": ( "https://files.pythonhosted.org/packages/00/82/3d0acad7ebd4098aaa23f163b492b47fd9321b2681c55918fe5f18856513/uv-0.2.12-py3-none-manylinux_2_28_aarch64.whl", - "05d809516b651997a151585c9bbd150d888e71976a734781a3dde95430c1cab2" + "05d809516b651997a151585c9bbd150d888e71976a734781a3dde95430c1cab2", ), "linux_x86_64": ( "https://files.pythonhosted.org/packages/d9/85/e608bfe78772afa3f9807a074203982131ff9c12e279bb3bc502e14d51ab/uv-0.2.12-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", From 80863335395c0b2e5a5f16728281038c523652bc Mon Sep 17 00:00:00 2001 From: Greg Date: Wed, 19 Jun 2024 00:09:56 +1000 Subject: [PATCH 05/67] buildifier --- python/private/bzlmod/pip_repository.bzl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/python/private/bzlmod/pip_repository.bzl b/python/private/bzlmod/pip_repository.bzl index 3df9829294..c22977032f 100644 --- a/python/private/bzlmod/pip_repository.bzl +++ b/python/private/bzlmod/pip_repository.bzl @@ -92,6 +92,9 @@ setting.""", "groups": attr.string_list_dict( mandatory = False, ), + "pin_tool_label": attr.string( + mandatory = True, + ), "repo_name": attr.string( mandatory = True, doc = "The apparent name of the repo. This is needed because in bzlmod, the name attribute becomes the canonical name.", @@ -103,13 +106,10 @@ The wheel map where values are json.encoded strings of the whl_map constructed in the pip.parse tag class. """, ), + "_pin": attr.label(default = ":pin.sh"), "_template": attr.label( default = ":requirements.bzl.tmpl", ), - "_pin": attr.label(default = ":pin.sh"), - "pin_tool_label": attr.string( - mandatory = True, - ), } pip_repository = repository_rule( From 25913637a19f390c1042b45937e20e4bd8cd6cc6 Mon Sep 17 00:00:00 2001 From: Ignas Anikevicius <240938+aignas@users.noreply.github.com> Date: Mon, 6 May 2024 16:03:28 +0900 Subject: [PATCH 06/67] chore: add uv to rules_python bzlmod CHANGELOG: - (bzlmod) Added `uv` to handle requirements files internally within rules_python. --- MODULE.bazel | 27 ++++ python/private/bzlmod/uv.bzl | 88 +++++++++++++ python/private/text_util.bzl | 9 ++ python/private/uv_hub.bzl | 198 ++++++++++++++++++++++++++++++ python/private/uv_pip_compile.bzl | 21 ++++ 5 files changed, 343 insertions(+) create mode 100644 python/private/bzlmod/uv.bzl create mode 100644 python/private/uv_hub.bzl create mode 100644 python/private/uv_pip_compile.bzl diff --git a/MODULE.bazel b/MODULE.bazel index 3cdc47fb7b..09724bd10d 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -107,6 +107,33 @@ dev_pip.parse( ) use_repo(dev_pip, "dev_pip", "pypiserver") +# uv setup - because we support WORKSPACE and bzlmod, we cannot use rules_uv, +# loading rules_uv from any of the `bzlmod` files may break the users who don't +# have uv registered in their repos and I could not figure out how to load it +# in a way where bzlmod and non-bzlmod pathways would have different files but +# we could share the same `pip_compile` rule. We still have tests using +# WORKSPACE, so they would break if that was the case. +uv = use_extension( + "//python/private/bzlmod:uv.bzl", + "uv", + dev_dependency = True, +) +uv.install( + # When updating, clear the sha values and observe the terminal output warnings when running + # bazel run @uv + files = { + "uv-aarch64-apple-darwin.tar.gz": "35e320cfa41c8902d66e2c491b5b2d2414e1c6443177c660736de657c66fb2c2", + "uv-aarch64-unknown-linux-gnu.tar.gz": "62b24363f21c07e02f62cf8e298ee6ec30e844006f3a52ac55c02903c755586d", + "uv-powerpc64le-unknown-linux-gnu.tar.gz": "07b1856e71c35f93ef5359c54f63d819841762316bf4d7c2774e178412d9090c", + "uv-s390x-unknown-linux-gnu.tar.gz": "773725ad1e02d6f4c90494fad5309a7cb4ce03b2e377fad336fecd895bc42dd2", + "uv-x86_64-apple-darwin.tar.gz": "cf5393f17de6961c7140d68f80e09c1f43ef47f8fac923ccd41896cce698f296", + "uv-x86_64-pc-windows-msvc.zip": "a44eb417b0c1e1c7cffd7349b8019d684f6200d0b5cfaef7dc322e8312bb254c", + "uv-x86_64-unknown-linux-gnu.tar.gz": "e748caea4ddafd3aebba771f4e8f51fe5aa517b71151a648269b3be982a349a1", + }, + version = "0.1.39", +) +use_repo(uv, "uv") + # Bazel integration test setup below bazel_binaries = use_extension( diff --git a/python/private/bzlmod/uv.bzl b/python/private/bzlmod/uv.bzl new file mode 100644 index 0000000000..18116fc40a --- /dev/null +++ b/python/private/bzlmod/uv.bzl @@ -0,0 +1,88 @@ +# Copyright 2024 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""A simple extension to install `uv` to be used within the `pip` bzlmod extension.""" + +load("//python/private:text_util.bzl", "render") +load("//python/private:uv_hub.bzl", "uv_hub") + +def _impl(module_ctx): + repos = [] + dev_repos = [] + for mod in module_ctx.modules: + for tag in mod.tags.install: + print_warning = False + want_files = {} + urls = {} + for file, want_sha256 in tag.files.items(): + url = tag.url_template.format( + version = tag.version, + file = file, + ) + if not want_sha256: + print_warning = True + sha256_file = module_ctx.path(file + ".sha256") + module_ctx.download( + url = url + ".sha256", + output = sha256_file, + ) + want_sha256 = module_ctx.read(sha256_file).split(" ")[0] + + want_files[file] = want_sha256 + urls[file] = url + + if print_warning: + # buildifier: disable=print + print("\n".join( + [ + "WARNING: Update the uv.install 'files' attribute to be:", + render.indent("files = {},".format(render.dict(want_files))), + ], + )) + + uv_repos = uv_hub( + name = tag.hub_name, + filenames = want_files, + urls = urls, + ) + if module_ctx.is_dev_dependency(tag): + dev_repos.extend(uv_repos) + else: + repos.extend(uv_repos) + + return module_ctx.extension_metadata( + root_module_direct_deps = repos, + root_module_direct_dev_deps = dev_repos, + ) + +uv = module_extension( + implementation = _impl, + tag_classes = { + "install": tag_class( + attrs = { + "files": attr.string_dict( + mandatory = True, + ), + "hub_name": attr.string( + default = "uv", + ), + "url_template": attr.string( + default = "https://github.com/astral-sh/uv/releases/download/{version}/{file}", + ), + "version": attr.string(mandatory = True), + }, + ), + }, + doc = """A module extension for installing uv.""", +) diff --git a/python/private/text_util.bzl b/python/private/text_util.bzl index dade9cba9b..71708bfd96 100644 --- a/python/private/text_util.bzl +++ b/python/private/text_util.bzl @@ -96,6 +96,14 @@ def _render_tuple(items, *, value_repr = repr): ")", ]) +def _render_call(rule, **kwargs): + return "\n".join( + ["{}(".format(rule)] + [ + _indent("{} = {},".format(k, v)) + for k, v in kwargs.items() + ] + [")"], + ) + render = struct( alias = _render_alias, dict = _render_dict, @@ -103,4 +111,5 @@ render = struct( list = _render_list, select = _render_select, tuple = _render_tuple, + call = _render_call, ) diff --git a/python/private/uv_hub.bzl b/python/private/uv_hub.bzl new file mode 100644 index 0000000000..b0175ddfb3 --- /dev/null +++ b/python/private/uv_hub.bzl @@ -0,0 +1,198 @@ +# Copyright 2024 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""A simple extension to install `uv` to be used within the `pip` bzlmod extension.""" + +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") +load(":text_util.bzl", "render") + +def _get_cpu(f): + f = f.lower() + if "x86_64" in f or "amd64" in f: + return "x86_64" + + if "aarch64" in f: + return "aarch64" + + if "powerpc" in f: + return "ppc" + + if "s390x" in f: + return "s390x" + + fail("Could not determine cpu for '{}'".format(f)) + +def _get_os(f): + f = f.lower() + if "windows" in f: + return "windows" + + if "linux" in f: + return "linux" + + if "darwin" in f: + return "osx" + + fail("Could not determine os for '{}'".format(f)) + +def _impl(rctx): + constraints = { + "{}_{}".format(_get_os(f), _get_cpu(f)): [ + "@platforms//cpu:" + _get_cpu(f), + "@platforms//os:" + _get_os(f), + ] + for f in rctx.attr.filenames + } + + rctx.file( + "BUILD.bazel", + "\n\n".join( + [ + """load("@bazel_skylib//rules:native_binary.bzl", "native_binary")""", + render.call( + rule = "native_binary", + name = repr("uv"), + src = render.select( + { + ":is_" + os_arch: "@{}_{}//:{}".format( + rctx.attr.hub_name, + os_arch, + "uv" if "windows" not in os_arch else "uv.exe", + ) + for os_arch in constraints.keys() + }, + no_match_error = repr("'uv' is not available for your host platform"), + ), + out = render.select({ + "@platforms//os:windows": "uv.exe", + "//conditions:default": "uv", + }), + visibility = render.list(["@rules_python//:__subpackages__"]), + ), + ] + [ + render.call( + rule = "config_setting", + name = repr("is_{}".format(os_arch)), + constraint_values = render.list(constraint_values), + visibility = render.list(["//visibility:private"]), + ) + for os_arch, constraint_values in constraints.items() + ], + ), + ) + +_uv_hub = repository_rule( + implementation = _impl, + attrs = { + "filenames": attr.string_list(mandatory = True), + "hub_name": attr.string(mandatory = True), + }, + doc = "A hub repository for exposing the tool internally", +) + +def _impl_host(rctx): + arch = _get_cpu(rctx.os.arch) + os = _get_os(rctx.os.name) + os_arch = "{}_{}".format(os, arch) + + target = Label("@@{}_{}//:{}".format( + rctx.name[:-len("_host")], + os_arch, + "uv" if "windows" not in os_arch else "uv.exe", + )) + rctx.symlink(target, "uv") + rctx.file( + "BUILD.bazel", + render.call( + rule = "exports_files", + srcs = render.list(["uv"]), + visibility = render.list([ + "@{}//:__subpackages__".format(rctx.attr.hub_name), + ]), + ), + ) + +_uv_host = repository_rule( + implementation = _impl_host, + attrs = { + "filenames": attr.string_list(mandatory = True), + "hub_name": attr.string(mandatory = True), + }, + doc = "A hub repository for exposing the tool internally", +) + +def _uv_archive(hub_name, file, url, sha256): + """uv_archive creates a spoke repo for the uv hub repo.""" + if url.endswith(".tar.gz"): + strip_prefix = file[:-len(".tar.gz")] + else: + strip_prefix = None + + cpu = _get_cpu(file) + os = _get_os(file) + name = "{}_{}_{}".format(hub_name, os, cpu) + + http_archive( + name = name, + url = url, + sha256 = sha256, + strip_prefix = strip_prefix, + build_file_content = render.call( + rule = "exports_files", + srcs = """glob(["*"])""", + visibility = render.list([ + "@{}//:__subpackages__".format(hub_name), + ]), + ), + ) + +def uv_hub(name, filenames, urls, add_host_hub = False): + """Create a uv hub repository for using the tool in rules. + + Args: + name: str, the name of the hub repo. + filenames: dict[str, str], the map from filename to sha256 of the filename. + urls: dict[str, str], the map from filename to its url. + add_host_hub: bool, a boolean controlling if a repo name "{name}_host" + is created. This could be useful in using the uv binary in repository + rules in the `pip.parse` extension. + + Returns: + The list of repos that should be publicly used + """ + for file, want_sha256 in filenames.items(): + _uv_archive( + hub_name = name, + file = file, + url = urls[file], + sha256 = want_sha256, + ) + + _uv_hub( + name = name, + hub_name = name, + filenames = filenames.keys(), + ) + repos = [name] + + if add_host_hub: + # This could allow uv to be used in the `pip.parse` extension + _uv_host( + name = name + "_host", + hub_name = name, + filenames = filenames.keys(), + ) + repos.append(name + "_host") + + return repos diff --git a/python/private/uv_pip_compile.bzl b/python/private/uv_pip_compile.bzl new file mode 100644 index 0000000000..8fe7c11d66 --- /dev/null +++ b/python/private/uv_pip_compile.bzl @@ -0,0 +1,21 @@ +# Copyright 2024 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""A simple extension to install `uv` to be used within the `pip` bzlmod extension.""" + +uv_pip_compile = rule( + attrs = { + "_tool": "@uv", + }, +) From 2797a460227826cf97771b558926a0162963eae5 Mon Sep 17 00:00:00 2001 From: Ignas Anikevicius <240938+aignas@users.noreply.github.com> Date: Wed, 19 Jun 2024 23:17:52 +0900 Subject: [PATCH 07/67] adapt the uv directly from http_archive --- MODULE.bazel | 10 ++--- python/private/bzlmod/pip.bzl | 57 ------------------------ python/private/bzlmod/pip_repository.bzl | 6 +-- python/private/bzlmod/uv.bzl | 2 +- python/private/uv_hub.bzl | 2 +- python/private/uv_pip_compile.bzl | 21 --------- 6 files changed, 7 insertions(+), 91 deletions(-) delete mode 100644 python/private/uv_pip_compile.bzl diff --git a/MODULE.bazel b/MODULE.bazel index 09724bd10d..124815045c 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -113,14 +113,10 @@ use_repo(dev_pip, "dev_pip", "pypiserver") # in a way where bzlmod and non-bzlmod pathways would have different files but # we could share the same `pip_compile` rule. We still have tests using # WORKSPACE, so they would break if that was the case. -uv = use_extension( - "//python/private/bzlmod:uv.bzl", - "uv", - dev_dependency = True, -) +uv = use_extension("//python/private/bzlmod:uv.bzl", "uv") uv.install( # When updating, clear the sha values and observe the terminal output warnings when running - # bazel run @uv + # bazel run @rules_python_uv//:uv files = { "uv-aarch64-apple-darwin.tar.gz": "35e320cfa41c8902d66e2c491b5b2d2414e1c6443177c660736de657c66fb2c2", "uv-aarch64-unknown-linux-gnu.tar.gz": "62b24363f21c07e02f62cf8e298ee6ec30e844006f3a52ac55c02903c755586d", @@ -132,7 +128,7 @@ uv.install( }, version = "0.1.39", ) -use_repo(uv, "uv") +use_repo(uv, "rules_python_uv") # Bazel integration test setup below diff --git a/python/private/bzlmod/pip.bzl b/python/private/bzlmod/pip.bzl index 339852102c..122debd2a2 100644 --- a/python/private/bzlmod/pip.bzl +++ b/python/private/bzlmod/pip.bzl @@ -15,8 +15,6 @@ "pip module extension for use with bzlmod" load("@bazel_features//:features.bzl", "bazel_features") -load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") -load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe") load("@pythons_hub//:interpreters.bzl", "DEFAULT_PYTHON_VERSION", "INTERPRETER_LABELS") load( "//python/pip_install:pip_repository.bzl", @@ -325,56 +323,6 @@ def _create_whl_repos(module_ctx, pip_attr, whl_map, whl_overrides, group_map, s return is_hub_reproducible -# TODO(groodt): Add more platforms -_UV_DEPS = { - "linux_aarch64": ( - "https://files.pythonhosted.org/packages/00/82/3d0acad7ebd4098aaa23f163b492b47fd9321b2681c55918fe5f18856513/uv-0.2.12-py3-none-manylinux_2_28_aarch64.whl", - "05d809516b651997a151585c9bbd150d888e71976a734781a3dde95430c1cab2", - ), - "linux_x86_64": ( - "https://files.pythonhosted.org/packages/d9/85/e608bfe78772afa3f9807a074203982131ff9c12e279bb3bc502e14d51ab/uv-0.2.12-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", - "78d5329094de1f6b503bffe00abcdf1aaa7b3e4aa2aa373e128d7faf39b98de9", - ), - "osx_x86_64": ( - "https://files.pythonhosted.org/packages/ff/f5/df24800e195f10e41aeb4a89f38488aca76c22d0f87c3eb8bf309f940aa3/uv-0.2.12-py3-none-macosx_10_12_x86_64.whl", - "85d2b9649c14014d6c54ecfb5d36f57e5c0e890957078ed4937e03569141d99b", - ), - "windows_x86_64": ( - "https://files.pythonhosted.org/packages/c8/bc/a905f3d4b961781ead58243bd4f3c6cd2fcb2deaa55c565a64ba7d06cd20/uv-0.2.12-py3-none-win_amd64.whl", - "ca95af397769422e11e87dc147be1262a54d3a13d8837b69c80fad20f1ff9af4", - ), -} - -# Repository to retrieve tools for pinning dependencies. -# We currently use uv as a dependency for the pinning tool. -def _fetch_pin_dependencies(python_version, platform): - url, sha256 = _UV_DEPS.get(platform) - py_version_label = "cp" + version_label(python_version) - - name = "{py_version_label}_{platform}_uv".format( - py_version_label = py_version_label, - platform = platform, - ) - maybe( - http_archive, - name = name, - build_file_content = """ -filegroup( - name = "uv", - srcs = glob(["*/scripts/uv"]), - visibility = ["//visibility:public"], -) -""", - sha256 = sha256, - type = "zip", - urls = [url], - ) - - return "@{py_version_label}_{platform}_uv//:uv".format( - py_version_label = py_version_label, - platform = platform, - ) - def _pip_impl(module_ctx): """Implementation of a class tag that creates the pip hub and corresponding pip spoke whl repositories. @@ -524,10 +472,6 @@ def _pip_impl(module_ctx): is_hub_reproducible = _create_whl_repos(module_ctx, pip_attr, hub_whl_map, whl_overrides, hub_group_map, simpleapi_cache) is_extension_reproducible = is_extension_reproducible and is_hub_reproducible - # Register repository for pin tooling - repository_platform = host_platform(module_ctx.os) - pin_tool_label = _fetch_pin_dependencies(_major_minor_version(DEFAULT_PYTHON_VERSION), repository_platform) - for hub_name, whl_map in hub_whl_map.items(): pip_repository( name = hub_name, @@ -538,7 +482,6 @@ def _pip_impl(module_ctx): }, default_version = _major_minor_version(DEFAULT_PYTHON_VERSION), groups = hub_group_map.get(hub_name), - pin_tool_label = pin_tool_label, ) if bazel_features.external_deps.extension_metadata_has_reproducible: diff --git a/python/private/bzlmod/pip_repository.bzl b/python/private/bzlmod/pip_repository.bzl index c22977032f..31eb5c1094 100644 --- a/python/private/bzlmod/pip_repository.bzl +++ b/python/private/bzlmod/pip_repository.bzl @@ -62,7 +62,7 @@ def _pip_repository_impl(rctx): rctx.template("pin.sh", rctx.attr._pin) rctx.file("BUILD.bazel", _BUILD_FILE_CONTENTS.format( - pin_tool_label = rctx.attr.pin_tool_label, + pin_tool_label = str(rctx.attr._pin_tool), )) rctx.template("requirements.bzl", rctx.attr._template, substitutions = { "%%ALL_DATA_REQUIREMENTS%%": render.list([ @@ -92,9 +92,6 @@ setting.""", "groups": attr.string_list_dict( mandatory = False, ), - "pin_tool_label": attr.string( - mandatory = True, - ), "repo_name": attr.string( mandatory = True, doc = "The apparent name of the repo. This is needed because in bzlmod, the name attribute becomes the canonical name.", @@ -107,6 +104,7 @@ in the pip.parse tag class. """, ), "_pin": attr.label(default = ":pin.sh"), + "_pin_tool": attr.label(default = "@rules_python_uv//:uv"), "_template": attr.label( default = ":requirements.bzl.tmpl", ), diff --git a/python/private/bzlmod/uv.bzl b/python/private/bzlmod/uv.bzl index 18116fc40a..78214696a4 100644 --- a/python/private/bzlmod/uv.bzl +++ b/python/private/bzlmod/uv.bzl @@ -75,7 +75,7 @@ uv = module_extension( mandatory = True, ), "hub_name": attr.string( - default = "uv", + default = "rules_python_uv", ), "url_template": attr.string( default = "https://github.com/astral-sh/uv/releases/download/{version}/{file}", diff --git a/python/private/uv_hub.bzl b/python/private/uv_hub.bzl index b0175ddfb3..0cf254341b 100644 --- a/python/private/uv_hub.bzl +++ b/python/private/uv_hub.bzl @@ -78,7 +78,7 @@ def _impl(rctx): "@platforms//os:windows": "uv.exe", "//conditions:default": "uv", }), - visibility = render.list(["@rules_python//:__subpackages__"]), + visibility = render.list(["//visibility:public"]), ), ] + [ render.call( diff --git a/python/private/uv_pip_compile.bzl b/python/private/uv_pip_compile.bzl deleted file mode 100644 index 8fe7c11d66..0000000000 --- a/python/private/uv_pip_compile.bzl +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright 2024 The Bazel Authors. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""A simple extension to install `uv` to be used within the `pip` bzlmod extension.""" - -uv_pip_compile = rule( - attrs = { - "_tool": "@uv", - }, -) From 308fe3286920934decda1080bfa9de1e0a3d47a4 Mon Sep 17 00:00:00 2001 From: Ignas Anikevicius <240938+aignas@users.noreply.github.com> Date: Wed, 19 Jun 2024 23:48:33 +0900 Subject: [PATCH 08/67] bump uv version --- MODULE.bazel | 18 ++++++++---------- python/private/bzlmod/uv.bzl | 11 +++++++++-- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/MODULE.bazel b/MODULE.bazel index 124815045c..d8010054ca 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -115,18 +115,16 @@ use_repo(dev_pip, "dev_pip", "pypiserver") # WORKSPACE, so they would break if that was the case. uv = use_extension("//python/private/bzlmod:uv.bzl", "uv") uv.install( - # When updating, clear the sha values and observe the terminal output warnings when running - # bazel run @rules_python_uv//:uv files = { - "uv-aarch64-apple-darwin.tar.gz": "35e320cfa41c8902d66e2c491b5b2d2414e1c6443177c660736de657c66fb2c2", - "uv-aarch64-unknown-linux-gnu.tar.gz": "62b24363f21c07e02f62cf8e298ee6ec30e844006f3a52ac55c02903c755586d", - "uv-powerpc64le-unknown-linux-gnu.tar.gz": "07b1856e71c35f93ef5359c54f63d819841762316bf4d7c2774e178412d9090c", - "uv-s390x-unknown-linux-gnu.tar.gz": "773725ad1e02d6f4c90494fad5309a7cb4ce03b2e377fad336fecd895bc42dd2", - "uv-x86_64-apple-darwin.tar.gz": "cf5393f17de6961c7140d68f80e09c1f43ef47f8fac923ccd41896cce698f296", - "uv-x86_64-pc-windows-msvc.zip": "a44eb417b0c1e1c7cffd7349b8019d684f6200d0b5cfaef7dc322e8312bb254c", - "uv-x86_64-unknown-linux-gnu.tar.gz": "e748caea4ddafd3aebba771f4e8f51fe5aa517b71151a648269b3be982a349a1", + "uv-aarch64-apple-darwin.tar.gz": "f588388d2b13f77e4526e619f618a306b6b026a96975fbfb2c6dd1ded134cb72", + "uv-aarch64-unknown-linux-gnu.tar.gz": "f342442088a56a8a5e4af6781501870bed1b388b37ac2e9deb250cd1d0dc1845", + "uv-powerpc64le-unknown-linux-gnu.tar.gz": "0f38a41264be0ef325f8d438f34ea95c002736b3c092e3276518a2253c4ff923", + "uv-s390x-unknown-linux-gnu.tar.gz": "dc843c32e51ee3fb46381699bffbc4b6040c51083a1dc7d6c597582b84956aa7", + "uv-x86_64-apple-darwin.tar.gz": "6262eba42ebb9035a574b74c5ea253a41353fb4b6b264600e3b05b1a7f4cabc0", + "uv-x86_64-pc-windows-msvc.zip": "898ce45b3767ea97429426a7bd0ec54d070eb9e29ff2b072bdcf288bf6ddc9a1", + "uv-x86_64-unknown-linux-gnu.tar.gz": "3f96048fa1b82eca14d45bbcc86714cd0dee19a73ef9311da6707faa308ec25f", }, - version = "0.1.39", + version = "0.2.13", ) use_repo(uv, "rules_python_uv") diff --git a/python/private/bzlmod/uv.bzl b/python/private/bzlmod/uv.bzl index 78214696a4..57cb7f0934 100644 --- a/python/private/bzlmod/uv.bzl +++ b/python/private/bzlmod/uv.bzl @@ -14,7 +14,6 @@ """A simple extension to install `uv` to be used within the `pip` bzlmod extension.""" -load("//python/private:text_util.bzl", "render") load("//python/private:uv_hub.bzl", "uv_hub") def _impl(module_ctx): @@ -47,7 +46,15 @@ def _impl(module_ctx): print("\n".join( [ "WARNING: Update the uv.install 'files' attribute to be:", - render.indent("files = {},".format(render.dict(want_files))), + " ".join([ + "buildozer", + "'remove files'", + ] + [ + "'dict_set files {}:{}'".format(k, v) + for k, v in want_files.items() + ] + [ + "MODULE.bazel:", + ]), ], )) From 04e5e6c944e6f9832b0f0f58408dfd0b2ae9d44e Mon Sep 17 00:00:00 2001 From: Ignas Anikevicius <240938+aignas@users.noreply.github.com> Date: Wed, 19 Jun 2024 23:51:43 +0900 Subject: [PATCH 09/67] move the usage of the uv extension around --- MODULE.bazel | 6 ------ 1 file changed, 6 deletions(-) diff --git a/MODULE.bazel b/MODULE.bazel index d8010054ca..8d4fb570a0 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -107,12 +107,6 @@ dev_pip.parse( ) use_repo(dev_pip, "dev_pip", "pypiserver") -# uv setup - because we support WORKSPACE and bzlmod, we cannot use rules_uv, -# loading rules_uv from any of the `bzlmod` files may break the users who don't -# have uv registered in their repos and I could not figure out how to load it -# in a way where bzlmod and non-bzlmod pathways would have different files but -# we could share the same `pip_compile` rule. We still have tests using -# WORKSPACE, so they would break if that was the case. uv = use_extension("//python/private/bzlmod:uv.bzl", "uv") uv.install( files = { From 0fcdf656c4669626ec53edacb4441ce57e77df93 Mon Sep 17 00:00:00 2001 From: Ignas Anikevicius <240938+aignas@users.noreply.github.com> Date: Wed, 19 Jun 2024 23:55:33 +0900 Subject: [PATCH 10/67] fixup the buildozer fixup command --- MODULE.bazel | 30 +++++++++++++++--------------- python/private/bzlmod/uv.bzl | 2 +- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/MODULE.bazel b/MODULE.bazel index 8d4fb570a0..deaa841c1a 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -68,6 +68,21 @@ pip.parse( ) use_repo(pip, "rules_python_publish_deps") +uv = use_extension("//python/private/bzlmod:uv.bzl", "uv") +uv.install( + files = { + "uv-aarch64-apple-darwin.tar.gz": "f588388d2b13f77e4526e619f618a306b6b026a96975fbfb2c6dd1ded134cb72", + "uv-aarch64-unknown-linux-gnu.tar.gz": "f342442088a56a8a5e4af6781501870bed1b388b37ac2e9deb250cd1d0dc1845", + "uv-powerpc64le-unknown-linux-gnu.tar.gz": "0f38a41264be0ef325f8d438f34ea95c002736b3c092e3276518a2253c4ff923", + "uv-s390x-unknown-linux-gnu.tar.gz": "dc843c32e51ee3fb46381699bffbc4b6040c51083a1dc7d6c597582b84956aa7", + "uv-x86_64-apple-darwin.tar.gz": "6262eba42ebb9035a574b74c5ea253a41353fb4b6b264600e3b05b1a7f4cabc0", + "uv-x86_64-pc-windows-msvc.zip": "898ce45b3767ea97429426a7bd0ec54d070eb9e29ff2b072bdcf288bf6ddc9a1", + "uv-x86_64-unknown-linux-gnu.tar.gz": "3f96048fa1b82eca14d45bbcc86714cd0dee19a73ef9311da6707faa308ec25f", + }, + version = "0.2.13", +) +use_repo(uv, "rules_python_uv") + # ===== DEV ONLY DEPS AND SETUP BELOW HERE ===== bazel_dep(name = "stardoc", version = "0.6.2", dev_dependency = True, repo_name = "io_bazel_stardoc") bazel_dep(name = "rules_bazel_integration_test", version = "0.20.0", dev_dependency = True) @@ -107,21 +122,6 @@ dev_pip.parse( ) use_repo(dev_pip, "dev_pip", "pypiserver") -uv = use_extension("//python/private/bzlmod:uv.bzl", "uv") -uv.install( - files = { - "uv-aarch64-apple-darwin.tar.gz": "f588388d2b13f77e4526e619f618a306b6b026a96975fbfb2c6dd1ded134cb72", - "uv-aarch64-unknown-linux-gnu.tar.gz": "f342442088a56a8a5e4af6781501870bed1b388b37ac2e9deb250cd1d0dc1845", - "uv-powerpc64le-unknown-linux-gnu.tar.gz": "0f38a41264be0ef325f8d438f34ea95c002736b3c092e3276518a2253c4ff923", - "uv-s390x-unknown-linux-gnu.tar.gz": "dc843c32e51ee3fb46381699bffbc4b6040c51083a1dc7d6c597582b84956aa7", - "uv-x86_64-apple-darwin.tar.gz": "6262eba42ebb9035a574b74c5ea253a41353fb4b6b264600e3b05b1a7f4cabc0", - "uv-x86_64-pc-windows-msvc.zip": "898ce45b3767ea97429426a7bd0ec54d070eb9e29ff2b072bdcf288bf6ddc9a1", - "uv-x86_64-unknown-linux-gnu.tar.gz": "3f96048fa1b82eca14d45bbcc86714cd0dee19a73ef9311da6707faa308ec25f", - }, - version = "0.2.13", -) -use_repo(uv, "rules_python_uv") - # Bazel integration test setup below bazel_binaries = use_extension( diff --git a/python/private/bzlmod/uv.bzl b/python/private/bzlmod/uv.bzl index 57cb7f0934..1c709f26b6 100644 --- a/python/private/bzlmod/uv.bzl +++ b/python/private/bzlmod/uv.bzl @@ -53,7 +53,7 @@ def _impl(module_ctx): "'dict_set files {}:{}'".format(k, v) for k, v in want_files.items() ] + [ - "MODULE.bazel:", + "MODULE.bazel:%uv.install", ]), ], )) From 9b1f5fdaf2d5223ca767aef9cd8fabb381868f88 Mon Sep 17 00:00:00 2001 From: Greg Date: Sun, 23 Jun 2024 01:33:57 +1000 Subject: [PATCH 11/67] Hacky toolchain. Needs py interpreter. --- MODULE.bazel | 4 +- examples/bzlmod/BUILD.bazel | 4 ++ examples/bzlmod/MODULE.bazel | 12 +++-- examples/bzlmod/other_module/BUILD.bazel | 4 ++ examples/bzlmod/other_module/MODULE.bazel | 1 + python/private/bzlmod/pin.sh | 9 ---- python/private/bzlmod/pip.bzl | 5 ++ python/private/bzlmod/pip_repository.bzl | 28 +++++----- python/private/py_lock_dependencies.bzl | 51 ++++++++++++++++++ python/private/uv/BUILD.bazel | 63 +++++++++++++++++++++++ python/private/{bzlmod => uv}/uv.bzl | 14 ++--- python/private/{ => uv}/uv_hub.bzl | 8 +-- python/private/uv/uv_toolchain.bzl | 27 ++++++++++ 13 files changed, 190 insertions(+), 40 deletions(-) delete mode 100644 python/private/bzlmod/pin.sh create mode 100644 python/private/py_lock_dependencies.bzl create mode 100644 python/private/uv/BUILD.bazel rename python/private/{bzlmod => uv}/uv.bzl (88%) rename python/private/{ => uv}/uv_hub.bzl (96%) create mode 100644 python/private/uv/uv_toolchain.bzl diff --git a/MODULE.bazel b/MODULE.bazel index deaa841c1a..24206e7787 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -68,8 +68,8 @@ pip.parse( ) use_repo(pip, "rules_python_publish_deps") -uv = use_extension("//python/private/bzlmod:uv.bzl", "uv") -uv.install( +uv = use_extension("//python/private/uv:uv.bzl", "uv") +uv.download( files = { "uv-aarch64-apple-darwin.tar.gz": "f588388d2b13f77e4526e619f618a306b6b026a96975fbfb2c6dd1ded134cb72", "uv-aarch64-unknown-linux-gnu.tar.gz": "f342442088a56a8a5e4af6781501870bed1b388b37ac2e9deb250cd1d0dc1845", diff --git a/examples/bzlmod/BUILD.bazel b/examples/bzlmod/BUILD.bazel index bb16f98a6f..966ce61dcb 100644 --- a/examples/bzlmod/BUILD.bazel +++ b/examples/bzlmod/BUILD.bazel @@ -12,6 +12,10 @@ load("@python_versions//3.10:defs.bzl", compile_pip_requirements_3_10 = "compile load("@python_versions//3.9:defs.bzl", compile_pip_requirements_3_9 = "compile_pip_requirements") load("@rules_python//python:defs.bzl", "py_binary", "py_library", "py_test") +exports_files([ + "requirements.in", +]) + # This stanza calls a rule that generates targets for managing pip dependencies # with pip-compile. compile_pip_requirements_3_9( diff --git a/examples/bzlmod/MODULE.bazel b/examples/bzlmod/MODULE.bazel index e46989e9fd..ed8464ba6f 100644 --- a/examples/bzlmod/MODULE.bazel +++ b/examples/bzlmod/MODULE.bazel @@ -94,6 +94,7 @@ use_repo(pip, "whl_mods_hub") # Alternatively, `python_interpreter_target` can be used to directly specify # the Python interpreter to run to resolve dependencies. pip.parse( + dependencies_file = ":requirements.in", # We can use `envsubst in the above envsubst = ["PIP_INDEX_URL"], # Use the bazel downloader to query the simple API for downloading the sources @@ -148,6 +149,7 @@ pip.parse( }, ) pip.parse( + dependencies_file = ":requirements.in", experimental_requirement_cycles = { "sphinx": [ "sphinx", @@ -197,8 +199,8 @@ pip.override( ) use_repo(pip, "pip") -bazel_dep(name = "other_module", version = "", repo_name = "our_other_module") -local_path_override( - module_name = "other_module", - path = "other_module", -) +# bazel_dep(name = "other_module", version = "", repo_name = "our_other_module") +# local_path_override( +# module_name = "other_module", +# path = "other_module", +# ) diff --git a/examples/bzlmod/other_module/BUILD.bazel b/examples/bzlmod/other_module/BUILD.bazel index a93b92aaed..ca8f624a48 100644 --- a/examples/bzlmod/other_module/BUILD.bazel +++ b/examples/bzlmod/other_module/BUILD.bazel @@ -1,5 +1,9 @@ load("@python_versions//3.11:defs.bzl", compile_pip_requirements_311 = "compile_pip_requirements") +exports_files([ + "requirements.in", +]) + # NOTE: To update the requirements, you need to uncomment the rules_python # override in the MODULE.bazel. compile_pip_requirements_311( diff --git a/examples/bzlmod/other_module/MODULE.bazel b/examples/bzlmod/other_module/MODULE.bazel index 959501abc2..0492e8cf8f 100644 --- a/examples/bzlmod/other_module/MODULE.bazel +++ b/examples/bzlmod/other_module/MODULE.bazel @@ -46,6 +46,7 @@ use_repo( pip = use_extension("@rules_python//python/extensions:pip.bzl", "pip") pip.parse( + dependencies_file = ":requirements.in", hub_name = "other_module_pip", # NOTE: This version must be different than the root module's # default python version. diff --git a/python/private/bzlmod/pin.sh b/python/private/bzlmod/pin.sh deleted file mode 100644 index 6744a3de78..0000000000 --- a/python/private/bzlmod/pin.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -uv_path=$1 -shift - -$uv_path pip compile \ - "$@" diff --git a/python/private/bzlmod/pip.bzl b/python/private/bzlmod/pip.bzl index 122debd2a2..71b5008083 100644 --- a/python/private/bzlmod/pip.bzl +++ b/python/private/bzlmod/pip.bzl @@ -482,6 +482,7 @@ def _pip_impl(module_ctx): }, default_version = _major_minor_version(DEFAULT_PYTHON_VERSION), groups = hub_group_map.get(hub_name), + dependencies_file = pip_attr.dependencies_file, # buildifier: disable=uninitialized ) if bazel_features.external_deps.extension_metadata_has_reproducible: @@ -513,6 +514,10 @@ def _pip_parse_ext_attrs(**kwargs): A dict of attributes. """ attrs = dict({ + "dependencies_file": attr.label( + mandatory = True, + allow_single_file = [".in", ".toml"], + ), "experimental_extra_index_urls": attr.string_list( doc = """\ The extra index URLs to use for downloading wheels using bazel downloader. diff --git a/python/private/bzlmod/pip_repository.bzl b/python/private/bzlmod/pip_repository.bzl index 31eb5c1094..7c68eb1df5 100644 --- a/python/private/bzlmod/pip_repository.bzl +++ b/python/private/bzlmod/pip_repository.bzl @@ -23,19 +23,14 @@ load("//python/private:text_util.bzl", "render") _BUILD_FILE_CONTENTS = """\ package(default_visibility = ["//visibility:public"]) +load("@rules_python//python/private:py_lock_dependencies.bzl", "py_lock_dependencies") # Ensure the `requirements.bzl` source can be accessed by stardoc, since users load() from it exports_files(["requirements.bzl"]) -sh_binary( - name = "pin", - srcs = ["pin.sh"], - data = [ - "{pin_tool_label}", - ], - args = [ - "$(location {pin_tool_label})", - ], +py_lock_dependencies( + name = "lock", + dependencies_file = "{dependencies_file}", visibility = ["//visibility:public"], ) """ @@ -60,9 +55,8 @@ def _pip_repository_impl(rctx): # `requirement`, et al. macros. macro_tmpl = "@@{name}//{{}}:{{}}".format(name = rctx.attr.name) - rctx.template("pin.sh", rctx.attr._pin) rctx.file("BUILD.bazel", _BUILD_FILE_CONTENTS.format( - pin_tool_label = str(rctx.attr._pin_tool), + dependencies_file = str(rctx.attr.dependencies_file), )) rctx.template("requirements.bzl", rctx.attr._template, substitutions = { "%%ALL_DATA_REQUIREMENTS%%": render.list([ @@ -82,6 +76,9 @@ def _pip_repository_impl(rctx): }) pip_repository_attrs = { + "constraints_file": attr.label( + allow_single_file = [".txt"], + ), "default_version": attr.string( mandatory = True, doc = """\ @@ -89,9 +86,16 @@ This is the default python version in the format of X.Y. This should match what is setup by the 'python' extension using the 'is_default = True' setting.""", ), + "dependencies_file": attr.label( + mandatory = True, + allow_single_file = [".in", ".toml"], + ), "groups": attr.string_list_dict( mandatory = False, ), + "overrides_file": attr.label( + allow_single_file = [".txt"], + ), "repo_name": attr.string( mandatory = True, doc = "The apparent name of the repo. This is needed because in bzlmod, the name attribute becomes the canonical name.", @@ -103,8 +107,6 @@ The wheel map where values are json.encoded strings of the whl_map constructed in the pip.parse tag class. """, ), - "_pin": attr.label(default = ":pin.sh"), - "_pin_tool": attr.label(default = "@rules_python_uv//:uv"), "_template": attr.label( default = ":requirements.bzl.tmpl", ), diff --git a/python/private/py_lock_dependencies.bzl b/python/private/py_lock_dependencies.bzl new file mode 100644 index 0000000000..da87db8b43 --- /dev/null +++ b/python/private/py_lock_dependencies.bzl @@ -0,0 +1,51 @@ +# Copyright 2024 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"Rule for locking third-party dependencies." + +def _py_lock_dependencies(ctx): + uv = ctx.toolchains["//python/private/uv:toolchain_type"].uv + args = ctx.actions.args() + args.add("pip") + args.add("compile") + args.add("--python-platform", "windows") + args.add("--python-version", "3.9") + args.add("--no-strip-extras") + args.add("--generate-hashes") + requirements_out = ctx.actions.declare_file(ctx.label.name + ".requirements.out") + args.add("--output-file", requirements_out) + args.add(ctx.file.dependencies_file) + + ctx.actions.run( + executable = uv.files_to_run, + arguments = [args], + inputs = [ctx.file.dependencies_file], + outputs = [requirements_out], + ) + + return [DefaultInfo( + files = depset([requirements_out]), + )] + +py_lock_dependencies = rule( + implementation = _py_lock_dependencies, + attrs = { + "constraints_file": attr.label(allow_single_file = True), + "dependencies_file": attr.label(allow_single_file = True), + "overrides_file": attr.label(allow_single_file = True), + }, + toolchains = [ + "//python/private/uv:toolchain_type", + ], +) diff --git a/python/private/uv/BUILD.bazel b/python/private/uv/BUILD.bazel new file mode 100644 index 0000000000..46170a66fa --- /dev/null +++ b/python/private/uv/BUILD.bazel @@ -0,0 +1,63 @@ +# Copyright 2024 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +load(":uv_toolchain.bzl", "uv_toolchain") + +toolchain_type(name = "toolchain_type") + +uv_toolchain( + name = "uv_toolchain_impl", + uv = "@rules_python_uv//:bin", +) + +toolchain( + name = "uv_toolchain_linux", + exec_compatible_with = [ + "@platforms//os:linux", + "@platforms//cpu:x86_64", + ], + target_compatible_with = [ + "@platforms//os:linux", + "@platforms//cpu:x86_64", + ], + toolchain = ":uv_toolchain_impl", + toolchain_type = ":toolchain_type", +) + +toolchain( + name = "uv_toolchain_osx", + exec_compatible_with = [ + "@platforms//os:osx", + "@platforms//cpu:x86_64", + ], + target_compatible_with = [ + "@platforms//os:osx", + "@platforms//cpu:x86_64", + ], + toolchain = ":uv_toolchain_impl", + toolchain_type = ":toolchain_type", +) + +toolchain( + name = "uv_toolchain_windows", + exec_compatible_with = [ + "@platforms//os:windows", + "@platforms//cpu:x86_64", + ], + target_compatible_with = [ + "@platforms//os:windows", + "@platforms//cpu:x86_64", + ], + toolchain = ":uv_toolchain_impl", + toolchain_type = ":toolchain_type", +) diff --git a/python/private/bzlmod/uv.bzl b/python/private/uv/uv.bzl similarity index 88% rename from python/private/bzlmod/uv.bzl rename to python/private/uv/uv.bzl index 1c709f26b6..391c87b8cd 100644 --- a/python/private/bzlmod/uv.bzl +++ b/python/private/uv/uv.bzl @@ -12,15 +12,15 @@ # See the License for the specific language governing permissions and # limitations under the License. -"""A simple extension to install `uv` to be used within the `pip` bzlmod extension.""" +"""A module extension for downloading uv.""" -load("//python/private:uv_hub.bzl", "uv_hub") +load("//python/private/uv:uv_hub.bzl", "uv_hub") def _impl(module_ctx): repos = [] dev_repos = [] for mod in module_ctx.modules: - for tag in mod.tags.install: + for tag in mod.tags.download: print_warning = False want_files = {} urls = {} @@ -45,7 +45,7 @@ def _impl(module_ctx): # buildifier: disable=print print("\n".join( [ - "WARNING: Update the uv.install 'files' attribute to be:", + "WARNING: Update the uv.download 'files' attribute to be:", " ".join([ "buildozer", "'remove files'", @@ -53,7 +53,7 @@ def _impl(module_ctx): "'dict_set files {}:{}'".format(k, v) for k, v in want_files.items() ] + [ - "MODULE.bazel:%uv.install", + "MODULE.bazel:%uv.download", ]), ], )) @@ -76,7 +76,7 @@ def _impl(module_ctx): uv = module_extension( implementation = _impl, tag_classes = { - "install": tag_class( + "download": tag_class( attrs = { "files": attr.string_dict( mandatory = True, @@ -91,5 +91,5 @@ uv = module_extension( }, ), }, - doc = """A module extension for installing uv.""", + doc = """A module extension for downloading uv.""", ) diff --git a/python/private/uv_hub.bzl b/python/private/uv/uv_hub.bzl similarity index 96% rename from python/private/uv_hub.bzl rename to python/private/uv/uv_hub.bzl index 0cf254341b..1ceeed7321 100644 --- a/python/private/uv_hub.bzl +++ b/python/private/uv/uv_hub.bzl @@ -12,10 +12,10 @@ # See the License for the specific language governing permissions and # limitations under the License. -"""A simple extension to install `uv` to be used within the `pip` bzlmod extension.""" +"Repository rules to create a hub repository for uv" load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") -load(":text_util.bzl", "render") +load("//python/private:text_util.bzl", "render") def _get_cpu(f): f = f.lower() @@ -62,7 +62,7 @@ def _impl(rctx): """load("@bazel_skylib//rules:native_binary.bzl", "native_binary")""", render.call( rule = "native_binary", - name = repr("uv"), + name = repr("bin"), src = render.select( { ":is_" + os_arch: "@{}_{}//:{}".format( @@ -157,7 +157,7 @@ def _uv_archive(hub_name, file, url, sha256): ), ) -def uv_hub(name, filenames, urls, add_host_hub = False): +def uv_hub(name, filenames, urls, add_host_hub = True): """Create a uv hub repository for using the tool in rules. Args: diff --git a/python/private/uv/uv_toolchain.bzl b/python/private/uv/uv_toolchain.bzl new file mode 100644 index 0000000000..2da98b2bd8 --- /dev/null +++ b/python/private/uv/uv_toolchain.bzl @@ -0,0 +1,27 @@ +# Copyright 2024 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"uv toolchain module extension" + +def _uv_toolchain_impl(ctx): + return [platform_common.ToolchainInfo( + uv = ctx.attr.uv, + )] + +uv_toolchain = rule( + implementation = _uv_toolchain_impl, + attrs = { + "uv": attr.label(executable = True, cfg = "exec"), + }, +) From abbcc9793e599795ced4e9b9eef089fdb9dd564a Mon Sep 17 00:00:00 2001 From: Greg Date: Sun, 23 Jun 2024 01:35:42 +1000 Subject: [PATCH 12/67] Hacky toolchain. Needs py interpreter. --- examples/bzlmod/MODULE.bazel | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/bzlmod/MODULE.bazel b/examples/bzlmod/MODULE.bazel index ed8464ba6f..02bd35e51c 100644 --- a/examples/bzlmod/MODULE.bazel +++ b/examples/bzlmod/MODULE.bazel @@ -199,8 +199,8 @@ pip.override( ) use_repo(pip, "pip") -# bazel_dep(name = "other_module", version = "", repo_name = "our_other_module") -# local_path_override( -# module_name = "other_module", -# path = "other_module", -# ) +bazel_dep(name = "other_module", version = "", repo_name = "our_other_module") +local_path_override( + module_name = "other_module", + path = "other_module", +) From 4a01495f1156b2dfd60e8cb3f4a753aecb137eac Mon Sep 17 00:00:00 2001 From: Greg Date: Sun, 23 Jun 2024 02:34:00 +1000 Subject: [PATCH 13/67] Kinda works --- python/private/py_lock_dependencies.bzl | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/python/private/py_lock_dependencies.bzl b/python/private/py_lock_dependencies.bzl index da87db8b43..7b57c82fb0 100644 --- a/python/private/py_lock_dependencies.bzl +++ b/python/private/py_lock_dependencies.bzl @@ -16,22 +16,29 @@ def _py_lock_dependencies(ctx): uv = ctx.toolchains["//python/private/uv:toolchain_type"].uv + python = ctx.toolchains["@bazel_tools//tools/python:toolchain_type"].py3_runtime.interpreter + dependencies_file = ctx.file.dependencies_file + args = ctx.actions.args() args.add("pip") args.add("compile") + + # uv will use this python for operations where it needs to execute python code. See: UV_PYTHON and https://github.com/astral-sh/uv?tab=readme-ov-file#installing-into-arbitrary-python-environments + args.add("--python", python) args.add("--python-platform", "windows") args.add("--python-version", "3.9") args.add("--no-strip-extras") args.add("--generate-hashes") requirements_out = ctx.actions.declare_file(ctx.label.name + ".requirements.out") args.add("--output-file", requirements_out) - args.add(ctx.file.dependencies_file) + args.add(dependencies_file) ctx.actions.run( executable = uv.files_to_run, arguments = [args], - inputs = [ctx.file.dependencies_file], + inputs = [dependencies_file], outputs = [requirements_out], + tools = [python], ) return [DefaultInfo( @@ -46,6 +53,7 @@ py_lock_dependencies = rule( "overrides_file": attr.label(allow_single_file = True), }, toolchains = [ + "@bazel_tools//tools/python:toolchain_type", "//python/private/uv:toolchain_type", ], ) From c6bddea63ac28197045d0c51347d32546c505ef6 Mon Sep 17 00:00:00 2001 From: Greg Date: Sun, 23 Jun 2024 20:44:43 +1000 Subject: [PATCH 14/67] . --- python/private/pypi/bzlmod.bzl | 5 +++++ python/private/pypi/hub_repository.bzl | 21 ++++++++++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/python/private/pypi/bzlmod.bzl b/python/private/pypi/bzlmod.bzl index e98208a2a6..e6e7c08b7d 100644 --- a/python/private/pypi/bzlmod.bzl +++ b/python/private/pypi/bzlmod.bzl @@ -483,6 +483,7 @@ def _pip_impl(module_ctx): }, default_version = _major_minor_version(DEFAULT_PYTHON_VERSION), groups = hub_group_map.get(hub_name), + dependencies_file = pip_attr.dependencies_file, # buildifier: disable=uninitialized ) if bazel_features.external_deps.extension_metadata_has_reproducible: @@ -514,6 +515,10 @@ def _pip_parse_ext_attrs(**kwargs): A dict of attributes. """ attrs = dict({ + "dependencies_file": attr.label( + mandatory = True, + allow_single_file = [".in", ".toml"], + ), "experimental_extra_index_urls": attr.string_list( doc = """\ The extra index URLs to use for downloading wheels using bazel downloader. diff --git a/python/private/pypi/hub_repository.bzl b/python/private/pypi/hub_repository.bzl index 40a3ab13e5..099d02d542 100644 --- a/python/private/pypi/hub_repository.bzl +++ b/python/private/pypi/hub_repository.bzl @@ -23,9 +23,16 @@ load( _BUILD_FILE_CONTENTS = """\ package(default_visibility = ["//visibility:public"]) +load("@rules_python//python/private:py_lock_dependencies.bzl", "py_lock_dependencies") # Ensure the `requirements.bzl` source can be accessed by stardoc, since users load() from it exports_files(["requirements.bzl"]) + +py_lock_dependencies( + name = "lock", + dependencies_file = "{dependencies_file}", + visibility = ["//visibility:public"], +) """ def _impl(rctx): @@ -48,7 +55,9 @@ def _impl(rctx): # `requirement`, et al. macros. macro_tmpl = "@@{name}//{{}}:{{}}".format(name = rctx.attr.name) - rctx.file("BUILD.bazel", _BUILD_FILE_CONTENTS) + rctx.file("BUILD.bazel", _BUILD_FILE_CONTENTS.format( + dependencies_file = str(rctx.attr.dependencies_file), + )) rctx.template("requirements.bzl", rctx.attr._template, substitutions = { "%%ALL_DATA_REQUIREMENTS%%": render.list([ macro_tmpl.format(p, "data") @@ -67,6 +76,9 @@ def _impl(rctx): hub_repository = repository_rule( attrs = { + "constraints_file": attr.label( + allow_single_file = [".txt"], + ), "default_version": attr.string( mandatory = True, doc = """\ @@ -74,9 +86,16 @@ This is the default python version in the format of X.Y. This should match what is setup by the 'python' extension using the 'is_default = True' setting.""", ), + "dependencies_file": attr.label( + mandatory = True, + allow_single_file = [".in", ".toml"], + ), "groups": attr.string_list_dict( mandatory = False, ), + "overrides_file": attr.label( + allow_single_file = [".txt"], + ), "repo_name": attr.string( mandatory = True, doc = "The apparent name of the repo. This is needed because in bzlmod, the name attribute becomes the canonical name.", From 750d8da7fca5e276af141858ce23c12b7e339282 Mon Sep 17 00:00:00 2001 From: Greg Date: Mon, 24 Jun 2024 01:48:59 +1000 Subject: [PATCH 15/67] Init toolchain --- MODULE.bazel | 19 +- python/BUILD.bazel | 19 ++ python/extensions.bzl | 46 ++++ python/private/pypi/BUILD.bazel | 18 ++ python/private/pypi/resolved_toolchain.bzl | 41 ++++ python/private/pypi/toolchains_repo.bzl | 78 +++++++ python/private/pypi/uv_toolchain.bzl | 88 ++++++++ python/private/pypi/versions.bzl | 14 ++ python/private/uv/BUILD.bazel | 63 ------ python/private/uv/uv.bzl | 95 --------- python/private/uv/uv_hub.bzl | 198 ------------------ python/repositories.bzl | 63 ++++++ .../uv/uv_toolchain.bzl => toolchain.bzl} | 16 +- 13 files changed, 377 insertions(+), 381 deletions(-) create mode 100644 python/extensions.bzl create mode 100644 python/private/pypi/resolved_toolchain.bzl create mode 100644 python/private/pypi/toolchains_repo.bzl create mode 100644 python/private/pypi/uv_toolchain.bzl create mode 100644 python/private/pypi/versions.bzl delete mode 100644 python/private/uv/BUILD.bazel delete mode 100644 python/private/uv/uv.bzl delete mode 100644 python/private/uv/uv_hub.bzl rename python/{private/uv/uv_toolchain.bzl => toolchain.bzl} (68%) diff --git a/MODULE.bazel b/MODULE.bazel index 24206e7787..cff08754ee 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -68,20 +68,11 @@ pip.parse( ) use_repo(pip, "rules_python_publish_deps") -uv = use_extension("//python/private/uv:uv.bzl", "uv") -uv.download( - files = { - "uv-aarch64-apple-darwin.tar.gz": "f588388d2b13f77e4526e619f618a306b6b026a96975fbfb2c6dd1ded134cb72", - "uv-aarch64-unknown-linux-gnu.tar.gz": "f342442088a56a8a5e4af6781501870bed1b388b37ac2e9deb250cd1d0dc1845", - "uv-powerpc64le-unknown-linux-gnu.tar.gz": "0f38a41264be0ef325f8d438f34ea95c002736b3c092e3276518a2253c4ff923", - "uv-s390x-unknown-linux-gnu.tar.gz": "dc843c32e51ee3fb46381699bffbc4b6040c51083a1dc7d6c597582b84956aa7", - "uv-x86_64-apple-darwin.tar.gz": "6262eba42ebb9035a574b74c5ea253a41353fb4b6b264600e3b05b1a7f4cabc0", - "uv-x86_64-pc-windows-msvc.zip": "898ce45b3767ea97429426a7bd0ec54d070eb9e29ff2b072bdcf288bf6ddc9a1", - "uv-x86_64-unknown-linux-gnu.tar.gz": "3f96048fa1b82eca14d45bbcc86714cd0dee19a73ef9311da6707faa308ec25f", - }, - version = "0.2.13", -) -use_repo(uv, "rules_python_uv") +uv = use_extension("//python:extensions.bzl", "uv") +uv.toolchain(uv_version = "0.2.13") +use_repo(uv, "uv_toolchains") + +register_toolchains("@uv_toolchains//:all") # ===== DEV ONLY DEPS AND SETUP BELOW HERE ===== bazel_dep(name = "stardoc", version = "0.6.2", dev_dependency = True, repo_name = "io_bazel_stardoc") diff --git a/python/BUILD.bazel b/python/BUILD.bazel index 29b495bf90..248816836c 100644 --- a/python/BUILD.bazel +++ b/python/BUILD.bazel @@ -222,6 +222,12 @@ bzl_library( ], ) +bzl_library( + name = "toolchain", + srcs = [":toolchain.bzl"], + visibility = ["//visibility:public"], +) + bzl_library( name = "versions_bzl", srcs = ["versions.bzl"], @@ -336,3 +342,16 @@ exports_files([ current_py_toolchain( name = "current_py_toolchain", ) + +toolchain_type( + name = "uv_toolchain_type", + visibility = ["//visibility:public"], +) + +resolved_toolchain( + name = "uv_resolved_toolchain", + # Marked manual so that `bazel test //...` passes + # even if no toolchain is registered. + tags = ["manual"], + visibility = ["//visibility:public"], +) diff --git a/python/extensions.bzl b/python/extensions.bzl new file mode 100644 index 0000000000..53ee13a92e --- /dev/null +++ b/python/extensions.bzl @@ -0,0 +1,46 @@ +"""Extensions for bzlmod.""" + +load(":repositories.bzl", "uv_register_toolchains") + +_DEFAULT_NAME = "uv" + +uv_toolchain = tag_class(attrs = { + "name": attr.string(doc = """\ +Base name for generated repositories, allowing more than one uv toolchain to be registered. +Overriding the default is only permitted in the root module. +""", default = "uv"), + "uv_version": attr.string(doc = "Explicit version of uv.", mandatory = True), +}) + +def _uv_toolchain_extension(module_ctx): + registrations = {} + for mod in module_ctx.modules: + for toolchain in mod.tags.uv_toolchain: + if toolchain.name != _DEFAULT_NAME and not mod.is_root: + fail("""\ + Only the root module may override the default name for the uv toolchain. + This prevents conflicting registrations in the global namespace of external repos. + """) + if toolchain.name not in registrations.keys(): + registrations[toolchain.name] = [] + registrations[toolchain.name].append(toolchain.uv_version) + for name, versions in registrations.items(): + if len(versions) > 1: + # TODO: should be semver-aware, using MVS + selected = sorted(versions, reverse = True)[0] + + # buildifier: disable=print + print("NOTE: uv toolchain {} has multiple versions {}, selected {}".format(name, versions, selected)) + else: + selected = versions[0] + + uv_register_toolchains( + name = name, + uv_version = selected, + register = False, + ) + +uv = module_extension( + implementation = _uv_toolchain_extension, + tag_classes = {"toolchain": uv_toolchain}, +) diff --git a/python/private/pypi/BUILD.bazel b/python/private/pypi/BUILD.bazel index 1530837f7d..af9d65ee7f 100644 --- a/python/private/pypi/BUILD.bazel +++ b/python/private/pypi/BUILD.bazel @@ -236,3 +236,21 @@ bzl_library( srcs = ["whl_target_platforms.bzl"], deps = [":parse_whl_name_bzl"], ) + +bzl_library( + name = "toolchains_repo", + srcs = ["toolchains_repo.bzl"], + visibility = ["//python:__subpackages__"], +) + +bzl_library( + name = "versions", + srcs = ["versions.bzl"], + visibility = ["//python:__subpackages__"], +) + +bzl_library( + name = "resolved_toolchain", + srcs = ["resolved_toolchain.bzl"], + visibility = ["//python:__subpackages__"], +) diff --git a/python/private/pypi/resolved_toolchain.bzl b/python/private/pypi/resolved_toolchain.bzl new file mode 100644 index 0000000000..52ed60ca1c --- /dev/null +++ b/python/private/pypi/resolved_toolchain.bzl @@ -0,0 +1,41 @@ +# Copyright 2024 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""This module implements an alias rule to the resolved toolchain. +""" + +DOC = """\ +Exposes a concrete toolchain which is the result of Bazel resolving the +toolchain for the execution or target platform. +Workaround for https://github.com/bazelbuild/bazel/issues/14009 +""" + +# Forward all the providers +def _uv_resolved_toolchain_impl(ctx): + toolchain_info = ctx.toolchains["//python:uv_toolchain_type"] + return [ + toolchain_info, + toolchain_info.defaultinfo, + toolchain_info.templatevariableinfo, + toolchain_info.uvtoolchaininfo, + ] + +# Copied from java_toolchain_alias +# https://cs.opensource.google/bazel/bazel/+/master:tools/jdk/java_toolchain_alias.bzl +uv_resolved_toolchain = rule( + implementation = _uv_resolved_toolchain_impl, + toolchains = ["//python:uv_toolchain_type"], + incompatible_use_toolchain_transition = True, + doc = DOC, +) diff --git a/python/private/pypi/toolchains_repo.bzl b/python/private/pypi/toolchains_repo.bzl new file mode 100644 index 0000000000..a0e8d37d57 --- /dev/null +++ b/python/private/pypi/toolchains_repo.bzl @@ -0,0 +1,78 @@ +# Copyright 2024 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"Creates a repository to hold toolchains" + +UV_PLATFORMS = { + "aarch64-apple-darwin": struct( + compatible_with = [ + "@platforms//os:macos", + "@platforms//cpu:aarch64", + ], + ), + "x86_64-apple-darwin": struct( + compatible_with = [ + "@platforms//os:macos", + "@platforms//cpu:x86_64", + ], + ), + "x86_64-pc-windows-msvc": struct( + compatible_with = [ + "@platforms//os:windows", + "@platforms//cpu:x86_64", + ], + ), + "x86_64-unknown-linux-gnu": struct( + compatible_with = [ + "@platforms//os:linux", + "@platforms//cpu:x86_64", + ], + ), +} + +def _toolchains_repo_impl(repository_ctx): + build_content = """# Generated by toolchains_repo.bzl +# +# These can be registered in the workspace file or passed to --extra_toolchains flag. +# By default all these toolchains are registered by the uv_register_toolchains macro +# so you don't normally need to interact with these targets. + +""" + + for [platform, meta] in UV_PLATFORMS.items(): + build_content += """ +# Declare a toolchain Bazel will select for running the tool in an action +# on the execution platform. +toolchain( + name = "{platform}_uv_toolchain", + exec_compatible_with = {compatible_with}, + toolchain = "@{user_repository_name}_{platform}//:uv_toolchain", + toolchain_type = "@rules_python//python:uv_toolchain_type", +) +""".format( + platform = platform, + user_repository_name = repository_ctx.attr.user_repository_name, + compatible_with = meta.compatible_with, + ) + + repository_ctx.file("BUILD.bazel", build_content) + +uv_toolchains_repo = repository_rule( + _toolchains_repo_impl, + doc = """Creates a repository with toolchain definitions for all known platforms + which can be registered or selected.""", + attrs = { + "user_repository_name": attr.string(doc = "what the user chose for the base name"), + }, +) diff --git a/python/private/pypi/uv_toolchain.bzl b/python/private/pypi/uv_toolchain.bzl new file mode 100644 index 0000000000..3ead3e631b --- /dev/null +++ b/python/private/pypi/uv_toolchain.bzl @@ -0,0 +1,88 @@ +# Copyright 2024 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""This module implements the uv toolchain rule""" + +UvToolchainInfo = provider( + doc = "Information about how to invoke the uv executable.", + fields = { + "uv_files": """Files required in runfiles to make the uv executable available. + +May be empty if the uv_path points to a locally installed uv binary.""", + "uv_path": "Path to the uv executable.", + }, +) + +# Avoid using non-normalized paths (workspace/../other_workspace/path) +def _to_manifest_path(ctx, file): + if file.short_path.startswith("../"): + return "external/" + file.short_path[3:] + else: + return ctx.workspace_name + "/" + file.short_path + +def _uv_toolchain_impl(ctx): + if ctx.attr.uv_tool and ctx.attr.uv_path: + fail("Can only set one of uv_tool or uv_path but both were set.") + if not ctx.attr.uv_tool and not ctx.attr.uv_path: + fail("Must set one of uv_tool or uv_path.") + + uv_files = [] + uv_path = ctx.attr.uv_path + + if ctx.attr.uv_tool: + uv_files = ctx.attr.uv_tool.files.to_list() + uv_path = _to_manifest_path(ctx, tool_files[0]) + + # Make the $(UV_BIN) variable available in places like genrules. + # See https://docs.bazel.build/versions/main/be/make-variables.html#custom_variables + templatevariableinfo = platform_common.TemplateVariableInfo({ + "UV_BIN": uv_path, + }) + defaultinfo = DefaultInfo( + files = depset(uv_files), + runfiles = ctx.runfiles(files = uv_files), + ) + uvtoolchaininfo = UvToolchainInfo( + uv_path = uv_path, + uv_files = uv_files, + ) + + # Export all the providers inside our ToolchainInfo + # so the resolved_toolchain rule can grab and re-export them. + toolchaininfo = platform_common.ToolchainInfo( + uvtoolchaininfo = uvtoolchaininfo, + templatevariableinfo = templatevariableinfo, + defaultinfo = defaultinfo, + ) + return [ + defaultinfo, + toolchaininfo, + templatevariableinfo, + ] + +uv_toolchain = rule( + implementation = _uv_toolchain_impl, + attrs = { + "uv_path": attr.string( + doc = "Path to an existing uv executable", + mandatory = False, + ), + "uv_tool": attr.label( + doc = "A hermetically downloaded executable target for the target platform.", + mandatory = False, + allow_single_file = True, + ), + }, + doc = "Defines a uv toolchain.", +) diff --git a/python/private/pypi/versions.bzl b/python/private/pypi/versions.bzl new file mode 100644 index 0000000000..77ed5941a9 --- /dev/null +++ b/python/private/pypi/versions.bzl @@ -0,0 +1,14 @@ +"""Version and integrity information for downloaded artifacts""" + +# From: https://github.com/astral-sh/uv/releases +UV_TOOL_VERSIONS = { + "0.2.13": { + "aarch64-apple-darwin": "f588388d2b13f77e4526e619f618a306b6b026a96975fbfb2c6dd1ded134cb72", + "aarch64-unknown-linux-gnu": "f342442088a56a8a5e4af6781501870bed1b388b37ac2e9deb250cd1d0dc1845", + "powerpc64le-unknown-linux-gnu": "0f38a41264be0ef325f8d438f34ea95c002736b3c092e3276518a2253c4ff923", + "s390x-unknown-linux-gnu": "dc843c32e51ee3fb46381699bffbc4b6040c51083a1dc7d6c597582b84956aa7", + "x86_64-apple-darwin": "6262eba42ebb9035a574b74c5ea253a41353fb4b6b264600e3b05b1a7f4cabc0", + "x86_64-pc-windows-msvc": "898ce45b3767ea97429426a7bd0ec54d070eb9e29ff2b072bdcf288bf6ddc9a1", + "x86_64-unknown-linux-gnu": "3f96048fa1b82eca14d45bbcc86714cd0dee19a73ef9311da6707faa308ec25f", + }, +} diff --git a/python/private/uv/BUILD.bazel b/python/private/uv/BUILD.bazel deleted file mode 100644 index 46170a66fa..0000000000 --- a/python/private/uv/BUILD.bazel +++ /dev/null @@ -1,63 +0,0 @@ -# Copyright 2024 The Bazel Authors. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -load(":uv_toolchain.bzl", "uv_toolchain") - -toolchain_type(name = "toolchain_type") - -uv_toolchain( - name = "uv_toolchain_impl", - uv = "@rules_python_uv//:bin", -) - -toolchain( - name = "uv_toolchain_linux", - exec_compatible_with = [ - "@platforms//os:linux", - "@platforms//cpu:x86_64", - ], - target_compatible_with = [ - "@platforms//os:linux", - "@platforms//cpu:x86_64", - ], - toolchain = ":uv_toolchain_impl", - toolchain_type = ":toolchain_type", -) - -toolchain( - name = "uv_toolchain_osx", - exec_compatible_with = [ - "@platforms//os:osx", - "@platforms//cpu:x86_64", - ], - target_compatible_with = [ - "@platforms//os:osx", - "@platforms//cpu:x86_64", - ], - toolchain = ":uv_toolchain_impl", - toolchain_type = ":toolchain_type", -) - -toolchain( - name = "uv_toolchain_windows", - exec_compatible_with = [ - "@platforms//os:windows", - "@platforms//cpu:x86_64", - ], - target_compatible_with = [ - "@platforms//os:windows", - "@platforms//cpu:x86_64", - ], - toolchain = ":uv_toolchain_impl", - toolchain_type = ":toolchain_type", -) diff --git a/python/private/uv/uv.bzl b/python/private/uv/uv.bzl deleted file mode 100644 index 391c87b8cd..0000000000 --- a/python/private/uv/uv.bzl +++ /dev/null @@ -1,95 +0,0 @@ -# Copyright 2024 The Bazel Authors. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""A module extension for downloading uv.""" - -load("//python/private/uv:uv_hub.bzl", "uv_hub") - -def _impl(module_ctx): - repos = [] - dev_repos = [] - for mod in module_ctx.modules: - for tag in mod.tags.download: - print_warning = False - want_files = {} - urls = {} - for file, want_sha256 in tag.files.items(): - url = tag.url_template.format( - version = tag.version, - file = file, - ) - if not want_sha256: - print_warning = True - sha256_file = module_ctx.path(file + ".sha256") - module_ctx.download( - url = url + ".sha256", - output = sha256_file, - ) - want_sha256 = module_ctx.read(sha256_file).split(" ")[0] - - want_files[file] = want_sha256 - urls[file] = url - - if print_warning: - # buildifier: disable=print - print("\n".join( - [ - "WARNING: Update the uv.download 'files' attribute to be:", - " ".join([ - "buildozer", - "'remove files'", - ] + [ - "'dict_set files {}:{}'".format(k, v) - for k, v in want_files.items() - ] + [ - "MODULE.bazel:%uv.download", - ]), - ], - )) - - uv_repos = uv_hub( - name = tag.hub_name, - filenames = want_files, - urls = urls, - ) - if module_ctx.is_dev_dependency(tag): - dev_repos.extend(uv_repos) - else: - repos.extend(uv_repos) - - return module_ctx.extension_metadata( - root_module_direct_deps = repos, - root_module_direct_dev_deps = dev_repos, - ) - -uv = module_extension( - implementation = _impl, - tag_classes = { - "download": tag_class( - attrs = { - "files": attr.string_dict( - mandatory = True, - ), - "hub_name": attr.string( - default = "rules_python_uv", - ), - "url_template": attr.string( - default = "https://github.com/astral-sh/uv/releases/download/{version}/{file}", - ), - "version": attr.string(mandatory = True), - }, - ), - }, - doc = """A module extension for downloading uv.""", -) diff --git a/python/private/uv/uv_hub.bzl b/python/private/uv/uv_hub.bzl deleted file mode 100644 index 1ceeed7321..0000000000 --- a/python/private/uv/uv_hub.bzl +++ /dev/null @@ -1,198 +0,0 @@ -# Copyright 2024 The Bazel Authors. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"Repository rules to create a hub repository for uv" - -load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") -load("//python/private:text_util.bzl", "render") - -def _get_cpu(f): - f = f.lower() - if "x86_64" in f or "amd64" in f: - return "x86_64" - - if "aarch64" in f: - return "aarch64" - - if "powerpc" in f: - return "ppc" - - if "s390x" in f: - return "s390x" - - fail("Could not determine cpu for '{}'".format(f)) - -def _get_os(f): - f = f.lower() - if "windows" in f: - return "windows" - - if "linux" in f: - return "linux" - - if "darwin" in f: - return "osx" - - fail("Could not determine os for '{}'".format(f)) - -def _impl(rctx): - constraints = { - "{}_{}".format(_get_os(f), _get_cpu(f)): [ - "@platforms//cpu:" + _get_cpu(f), - "@platforms//os:" + _get_os(f), - ] - for f in rctx.attr.filenames - } - - rctx.file( - "BUILD.bazel", - "\n\n".join( - [ - """load("@bazel_skylib//rules:native_binary.bzl", "native_binary")""", - render.call( - rule = "native_binary", - name = repr("bin"), - src = render.select( - { - ":is_" + os_arch: "@{}_{}//:{}".format( - rctx.attr.hub_name, - os_arch, - "uv" if "windows" not in os_arch else "uv.exe", - ) - for os_arch in constraints.keys() - }, - no_match_error = repr("'uv' is not available for your host platform"), - ), - out = render.select({ - "@platforms//os:windows": "uv.exe", - "//conditions:default": "uv", - }), - visibility = render.list(["//visibility:public"]), - ), - ] + [ - render.call( - rule = "config_setting", - name = repr("is_{}".format(os_arch)), - constraint_values = render.list(constraint_values), - visibility = render.list(["//visibility:private"]), - ) - for os_arch, constraint_values in constraints.items() - ], - ), - ) - -_uv_hub = repository_rule( - implementation = _impl, - attrs = { - "filenames": attr.string_list(mandatory = True), - "hub_name": attr.string(mandatory = True), - }, - doc = "A hub repository for exposing the tool internally", -) - -def _impl_host(rctx): - arch = _get_cpu(rctx.os.arch) - os = _get_os(rctx.os.name) - os_arch = "{}_{}".format(os, arch) - - target = Label("@@{}_{}//:{}".format( - rctx.name[:-len("_host")], - os_arch, - "uv" if "windows" not in os_arch else "uv.exe", - )) - rctx.symlink(target, "uv") - rctx.file( - "BUILD.bazel", - render.call( - rule = "exports_files", - srcs = render.list(["uv"]), - visibility = render.list([ - "@{}//:__subpackages__".format(rctx.attr.hub_name), - ]), - ), - ) - -_uv_host = repository_rule( - implementation = _impl_host, - attrs = { - "filenames": attr.string_list(mandatory = True), - "hub_name": attr.string(mandatory = True), - }, - doc = "A hub repository for exposing the tool internally", -) - -def _uv_archive(hub_name, file, url, sha256): - """uv_archive creates a spoke repo for the uv hub repo.""" - if url.endswith(".tar.gz"): - strip_prefix = file[:-len(".tar.gz")] - else: - strip_prefix = None - - cpu = _get_cpu(file) - os = _get_os(file) - name = "{}_{}_{}".format(hub_name, os, cpu) - - http_archive( - name = name, - url = url, - sha256 = sha256, - strip_prefix = strip_prefix, - build_file_content = render.call( - rule = "exports_files", - srcs = """glob(["*"])""", - visibility = render.list([ - "@{}//:__subpackages__".format(hub_name), - ]), - ), - ) - -def uv_hub(name, filenames, urls, add_host_hub = True): - """Create a uv hub repository for using the tool in rules. - - Args: - name: str, the name of the hub repo. - filenames: dict[str, str], the map from filename to sha256 of the filename. - urls: dict[str, str], the map from filename to its url. - add_host_hub: bool, a boolean controlling if a repo name "{name}_host" - is created. This could be useful in using the uv binary in repository - rules in the `pip.parse` extension. - - Returns: - The list of repos that should be publicly used - """ - for file, want_sha256 in filenames.items(): - _uv_archive( - hub_name = name, - file = file, - url = urls[file], - sha256 = want_sha256, - ) - - _uv_hub( - name = name, - hub_name = name, - filenames = filenames.keys(), - ) - repos = [name] - - if add_host_hub: - # This could allow uv to be used in the `pip.parse` extension - _uv_host( - name = name + "_host", - hub_name = name, - filenames = filenames.keys(), - ) - repos.append(name + "_host") - - return repos diff --git a/python/repositories.bzl b/python/repositories.bzl index 245aae2546..1769a3d402 100644 --- a/python/repositories.bzl +++ b/python/repositories.bzl @@ -33,6 +33,8 @@ load( "toolchain_aliases", "toolchains_repo", ) +load("//python/private/pypi:toolchains_repo.bzl", "UV_PLATFORMS", "uv_toolchains_repo") +load("//python/private/pypi:versions.bzl", "UV_TOOL_VERSIONS") load( ":versions.bzl", "DEFAULT_RELEASE_BASE_URL", @@ -721,3 +723,64 @@ def python_register_multi_toolchains( for python_version in (python_versions + [default_version]) }, ) + +def _uv_repo_impl(repository_ctx): + suffix = ".zip" if repository_ctx.attr.platform == "windows" else ".tar.gz" + url = "https://github.com/astral-sh/uv/releases/download/{version}/uv-{platform}{suffix}".format( + repository_ctx.attr.uv_version, + repository_ctx.attr.platform, + suffix, + ) + + repository_ctx.download_and_extract( + url = url, + integrity = UV_TOOL_VERSIONS[repository_ctx.attr.uv_version][repository_ctx.attr.platform], + ) + build_content = """# Generated by repositories.bzl +load("@rules_python//python:toolchain.bzl", "uv_toolchain") + +uv_toolchain( + name = "uv_toolchain", + uv_tool = select({ + "@bazel_tools//src/conditions:host_windows": "uv.exe", + "//conditions:default": "uv", + }), +) +""" + + # Base BUILD file for this repository + repository_ctx.file("BUILD.bazel", build_content) + +uv_repositories = repository_rule( + _uv_repo_impl, + doc = "Fetch external tools needed for uv toolchain", + attrs = { + "platform": attr.string(mandatory = True, values = UV_PLATFORMS.keys()), + "uv_version": attr.string(mandatory = True, values = UV_TOOL_VERSIONS.keys()), + }, +) + +# Wrapper macro around everything above, this is the primary API +def uv_register_toolchains(name, register = True, **kwargs): + """Convenience macro for users which does typical setup. + + Users can avoid this macro and do these steps themselves, if they want more control. + Args: + name: base name for all created repos, like "uv0_2_13" + register: whether to call through to native.register_toolchains. + Should be True for WORKSPACE users, but false when used under bzlmod extension + **kwargs: passed to each node_repositories call + """ + for platform in UV_PLATFORMS.keys(): + uv_repositories( + name = name + "_" + platform, + platform = platform, + **kwargs + ) + if register: + native.register_toolchains("@%s_toolchains//:%s_toolchain" % (name, platform)) + + uv_toolchains_repo( + name = name + "_toolchains", + user_repository_name = name, + ) diff --git a/python/private/uv/uv_toolchain.bzl b/python/toolchain.bzl similarity index 68% rename from python/private/uv/uv_toolchain.bzl rename to python/toolchain.bzl index 2da98b2bd8..2c953d8bdf 100644 --- a/python/private/uv/uv_toolchain.bzl +++ b/python/toolchain.bzl @@ -12,16 +12,10 @@ # See the License for the specific language governing permissions and # limitations under the License. -"uv toolchain module extension" +"""All toolchains re-exported here""" -def _uv_toolchain_impl(ctx): - return [platform_common.ToolchainInfo( - uv = ctx.attr.uv, - )] +load("//python/private/pypi:uv_toolchain.bzl", _UvToolchainInfo = "UvToolchainInfo", _uv_toolchain = "uv_toolchain") -uv_toolchain = rule( - implementation = _uv_toolchain_impl, - attrs = { - "uv": attr.label(executable = True, cfg = "exec"), - }, -) +UvToolchainInfo = _UvToolchainInfo + +uv_toolchain = _uv_toolchain From 3a1f889d844c71ed09e7d9ffe644a1f5a1b25fb2 Mon Sep 17 00:00:00 2001 From: Greg Date: Mon, 24 Jun 2024 02:10:21 +1000 Subject: [PATCH 16/67] Init toolchain --- examples/bzlmod/BUILD.bazel | 4 ---- examples/bzlmod/MODULE.bazel | 2 -- examples/bzlmod/other_module/BUILD.bazel | 4 ---- python/BUILD.bazel | 3 ++- python/extensions.bzl | 2 +- python/private/pypi/bzlmod.bzl | 5 ----- python/private/pypi/hub_repository.bzl | 20 +------------------ .../{ => pypi}/py_lock_dependencies.bzl | 4 +++- 8 files changed, 7 insertions(+), 37 deletions(-) rename python/private/{ => pypi}/py_lock_dependencies.bzl (95%) diff --git a/examples/bzlmod/BUILD.bazel b/examples/bzlmod/BUILD.bazel index 966ce61dcb..bb16f98a6f 100644 --- a/examples/bzlmod/BUILD.bazel +++ b/examples/bzlmod/BUILD.bazel @@ -12,10 +12,6 @@ load("@python_versions//3.10:defs.bzl", compile_pip_requirements_3_10 = "compile load("@python_versions//3.9:defs.bzl", compile_pip_requirements_3_9 = "compile_pip_requirements") load("@rules_python//python:defs.bzl", "py_binary", "py_library", "py_test") -exports_files([ - "requirements.in", -]) - # This stanza calls a rule that generates targets for managing pip dependencies # with pip-compile. compile_pip_requirements_3_9( diff --git a/examples/bzlmod/MODULE.bazel b/examples/bzlmod/MODULE.bazel index 02bd35e51c..e46989e9fd 100644 --- a/examples/bzlmod/MODULE.bazel +++ b/examples/bzlmod/MODULE.bazel @@ -94,7 +94,6 @@ use_repo(pip, "whl_mods_hub") # Alternatively, `python_interpreter_target` can be used to directly specify # the Python interpreter to run to resolve dependencies. pip.parse( - dependencies_file = ":requirements.in", # We can use `envsubst in the above envsubst = ["PIP_INDEX_URL"], # Use the bazel downloader to query the simple API for downloading the sources @@ -149,7 +148,6 @@ pip.parse( }, ) pip.parse( - dependencies_file = ":requirements.in", experimental_requirement_cycles = { "sphinx": [ "sphinx", diff --git a/examples/bzlmod/other_module/BUILD.bazel b/examples/bzlmod/other_module/BUILD.bazel index ca8f624a48..a93b92aaed 100644 --- a/examples/bzlmod/other_module/BUILD.bazel +++ b/examples/bzlmod/other_module/BUILD.bazel @@ -1,9 +1,5 @@ load("@python_versions//3.11:defs.bzl", compile_pip_requirements_311 = "compile_pip_requirements") -exports_files([ - "requirements.in", -]) - # NOTE: To update the requirements, you need to uncomment the rules_python # override in the MODULE.bazel. compile_pip_requirements_311( diff --git a/python/BUILD.bazel b/python/BUILD.bazel index 248816836c..a876bc8006 100644 --- a/python/BUILD.bazel +++ b/python/BUILD.bazel @@ -25,6 +25,7 @@ that @rules_python//python is only concerned with the core rules. load("@bazel_skylib//:bzl_library.bzl", "bzl_library") load("//python/private:autodetecting_toolchain.bzl", "define_autodetecting_toolchain") +load("//python/private/pypi:resolved_toolchain.bzl", "uv_resolved_toolchain") load(":current_py_toolchain.bzl", "current_py_toolchain") package(default_visibility = ["//visibility:public"]) @@ -348,7 +349,7 @@ toolchain_type( visibility = ["//visibility:public"], ) -resolved_toolchain( +uv_resolved_toolchain( name = "uv_resolved_toolchain", # Marked manual so that `bazel test //...` passes # even if no toolchain is registered. diff --git a/python/extensions.bzl b/python/extensions.bzl index 53ee13a92e..aceb974c52 100644 --- a/python/extensions.bzl +++ b/python/extensions.bzl @@ -15,7 +15,7 @@ Overriding the default is only permitted in the root module. def _uv_toolchain_extension(module_ctx): registrations = {} for mod in module_ctx.modules: - for toolchain in mod.tags.uv_toolchain: + for toolchain in mod.tags.toolchain: if toolchain.name != _DEFAULT_NAME and not mod.is_root: fail("""\ Only the root module may override the default name for the uv toolchain. diff --git a/python/private/pypi/bzlmod.bzl b/python/private/pypi/bzlmod.bzl index e6e7c08b7d..e98208a2a6 100644 --- a/python/private/pypi/bzlmod.bzl +++ b/python/private/pypi/bzlmod.bzl @@ -483,7 +483,6 @@ def _pip_impl(module_ctx): }, default_version = _major_minor_version(DEFAULT_PYTHON_VERSION), groups = hub_group_map.get(hub_name), - dependencies_file = pip_attr.dependencies_file, # buildifier: disable=uninitialized ) if bazel_features.external_deps.extension_metadata_has_reproducible: @@ -515,10 +514,6 @@ def _pip_parse_ext_attrs(**kwargs): A dict of attributes. """ attrs = dict({ - "dependencies_file": attr.label( - mandatory = True, - allow_single_file = [".in", ".toml"], - ), "experimental_extra_index_urls": attr.string_list( doc = """\ The extra index URLs to use for downloading wheels using bazel downloader. diff --git a/python/private/pypi/hub_repository.bzl b/python/private/pypi/hub_repository.bzl index 099d02d542..a6506308a6 100644 --- a/python/private/pypi/hub_repository.bzl +++ b/python/private/pypi/hub_repository.bzl @@ -27,12 +27,6 @@ load("@rules_python//python/private:py_lock_dependencies.bzl", "py_lock_dependen # Ensure the `requirements.bzl` source can be accessed by stardoc, since users load() from it exports_files(["requirements.bzl"]) - -py_lock_dependencies( - name = "lock", - dependencies_file = "{dependencies_file}", - visibility = ["//visibility:public"], -) """ def _impl(rctx): @@ -55,9 +49,7 @@ def _impl(rctx): # `requirement`, et al. macros. macro_tmpl = "@@{name}//{{}}:{{}}".format(name = rctx.attr.name) - rctx.file("BUILD.bazel", _BUILD_FILE_CONTENTS.format( - dependencies_file = str(rctx.attr.dependencies_file), - )) + rctx.file("BUILD.bazel", _BUILD_FILE_CONTENTS) rctx.template("requirements.bzl", rctx.attr._template, substitutions = { "%%ALL_DATA_REQUIREMENTS%%": render.list([ macro_tmpl.format(p, "data") @@ -76,9 +68,6 @@ def _impl(rctx): hub_repository = repository_rule( attrs = { - "constraints_file": attr.label( - allow_single_file = [".txt"], - ), "default_version": attr.string( mandatory = True, doc = """\ @@ -86,16 +75,9 @@ This is the default python version in the format of X.Y. This should match what is setup by the 'python' extension using the 'is_default = True' setting.""", ), - "dependencies_file": attr.label( - mandatory = True, - allow_single_file = [".in", ".toml"], - ), "groups": attr.string_list_dict( mandatory = False, ), - "overrides_file": attr.label( - allow_single_file = [".txt"], - ), "repo_name": attr.string( mandatory = True, doc = "The apparent name of the repo. This is needed because in bzlmod, the name attribute becomes the canonical name.", diff --git a/python/private/py_lock_dependencies.bzl b/python/private/pypi/py_lock_dependencies.bzl similarity index 95% rename from python/private/py_lock_dependencies.bzl rename to python/private/pypi/py_lock_dependencies.bzl index 7b57c82fb0..ec2d255de1 100644 --- a/python/private/py_lock_dependencies.bzl +++ b/python/private/pypi/py_lock_dependencies.bzl @@ -15,7 +15,9 @@ "Rule for locking third-party dependencies." def _py_lock_dependencies(ctx): - uv = ctx.toolchains["//python/private/uv:toolchain_type"].uv + info = ctx.toolchains["//python/:uv_toolchain_type"].uvtoolchaininfo + uv = info.uv_path + python = ctx.toolchains["@bazel_tools//tools/python:toolchain_type"].py3_runtime.interpreter dependencies_file = ctx.file.dependencies_file From 37859b80f5b1f72e5c16ba207ce26719c2928606 Mon Sep 17 00:00:00 2001 From: Greg Date: Mon, 24 Jun 2024 02:12:41 +1000 Subject: [PATCH 17/67] Init toolchain --- examples/bzlmod/other_module/MODULE.bazel | 1 - python/private/text_util.bzl | 9 --------- 2 files changed, 10 deletions(-) diff --git a/examples/bzlmod/other_module/MODULE.bazel b/examples/bzlmod/other_module/MODULE.bazel index 0492e8cf8f..959501abc2 100644 --- a/examples/bzlmod/other_module/MODULE.bazel +++ b/examples/bzlmod/other_module/MODULE.bazel @@ -46,7 +46,6 @@ use_repo( pip = use_extension("@rules_python//python/extensions:pip.bzl", "pip") pip.parse( - dependencies_file = ":requirements.in", hub_name = "other_module_pip", # NOTE: This version must be different than the root module's # default python version. diff --git a/python/private/text_util.bzl b/python/private/text_util.bzl index d02b31dcad..702a08e281 100644 --- a/python/private/text_util.bzl +++ b/python/private/text_util.bzl @@ -99,14 +99,6 @@ def _render_tuple(items, *, value_repr = repr): ")", ]) -def _render_call(rule, **kwargs): - return "\n".join( - ["{}(".format(rule)] + [ - _indent("{} = {},".format(k, v)) - for k, v in kwargs.items() - ] + [")"], - ) - render = struct( alias = _render_alias, dict = _render_dict, @@ -114,5 +106,4 @@ render = struct( list = _render_list, select = _render_select, tuple = _render_tuple, - call = _render_call, ) From 0ff0003101d6d10046a2aa882398afa60109a7c6 Mon Sep 17 00:00:00 2001 From: Greg Date: Mon, 24 Jun 2024 02:14:18 +1000 Subject: [PATCH 18/67] Init toolchain --- python/private/pypi/hub_repository.bzl | 1 - 1 file changed, 1 deletion(-) diff --git a/python/private/pypi/hub_repository.bzl b/python/private/pypi/hub_repository.bzl index a6506308a6..40a3ab13e5 100644 --- a/python/private/pypi/hub_repository.bzl +++ b/python/private/pypi/hub_repository.bzl @@ -23,7 +23,6 @@ load( _BUILD_FILE_CONTENTS = """\ package(default_visibility = ["//visibility:public"]) -load("@rules_python//python/private:py_lock_dependencies.bzl", "py_lock_dependencies") # Ensure the `requirements.bzl` source can be accessed by stardoc, since users load() from it exports_files(["requirements.bzl"]) From aefd672cf6a3b3f1c1edef1bb4a722ea2e23f95f Mon Sep 17 00:00:00 2001 From: Greg Date: Mon, 24 Jun 2024 03:05:07 +1000 Subject: [PATCH 19/67] Init toolchain --- examples/bzlmod/BUILD.bazel | 6 ++++++ python/private/pypi/BUILD.bazel | 6 ++++++ ...lock_dependencies.bzl => uv_pip_compile.bzl} | 15 ++++++++------- python/private/pypi/uv_toolchain.bzl | 2 +- python/repositories.bzl | 17 +++++++++++++---- 5 files changed, 34 insertions(+), 12 deletions(-) rename python/private/pypi/{py_lock_dependencies.bzl => uv_pip_compile.bzl} (86%) diff --git a/examples/bzlmod/BUILD.bazel b/examples/bzlmod/BUILD.bazel index bb16f98a6f..3dd01dc5f4 100644 --- a/examples/bzlmod/BUILD.bazel +++ b/examples/bzlmod/BUILD.bazel @@ -11,6 +11,7 @@ load("@python_3_9//:defs.bzl", py_test_with_transition = "py_test") load("@python_versions//3.10:defs.bzl", compile_pip_requirements_3_10 = "compile_pip_requirements") load("@python_versions//3.9:defs.bzl", compile_pip_requirements_3_9 = "compile_pip_requirements") load("@rules_python//python:defs.bzl", "py_binary", "py_library", "py_test") +load("@rules_python//python/private/pypi:uv_pip_compile.bzl", "uv_pip_compile") # This stanza calls a rule that generates targets for managing pip dependencies # with pip-compile. @@ -21,6 +22,11 @@ compile_pip_requirements_3_9( requirements_windows = "requirements_windows_3_9.txt", ) +uv_pip_compile( + name = "spike_uv_pip_compile", + dependencies_file = "requirements.in", +) + # This stanza calls a rule that generates targets for managing pip dependencies # with pip-compile. compile_pip_requirements_3_10( diff --git a/python/private/pypi/BUILD.bazel b/python/private/pypi/BUILD.bazel index 65d96b93dd..a1dd1393f3 100644 --- a/python/private/pypi/BUILD.bazel +++ b/python/private/pypi/BUILD.bazel @@ -301,3 +301,9 @@ bzl_library( srcs = ["resolved_toolchain.bzl"], visibility = ["//python:__subpackages__"], ) + +bzl_library( + name = "uv_pip_compile", + srcs = ["uv_pip_compile.bzl"], + visibility = ["//visibility:public"], +) diff --git a/python/private/pypi/py_lock_dependencies.bzl b/python/private/pypi/uv_pip_compile.bzl similarity index 86% rename from python/private/pypi/py_lock_dependencies.bzl rename to python/private/pypi/uv_pip_compile.bzl index ec2d255de1..04ad0149c3 100644 --- a/python/private/pypi/py_lock_dependencies.bzl +++ b/python/private/pypi/uv_pip_compile.bzl @@ -12,10 +12,10 @@ # See the License for the specific language governing permissions and # limitations under the License. -"Rule for locking third-party dependencies." +"Rule for locking third-party dependencies with uv." -def _py_lock_dependencies(ctx): - info = ctx.toolchains["//python/:uv_toolchain_type"].uvtoolchaininfo +def _uv_pip_compile(ctx): + info = ctx.toolchains["//python:uv_toolchain_type"].uvtoolchaininfo uv = info.uv_path python = ctx.toolchains["@bazel_tools//tools/python:toolchain_type"].py3_runtime.interpreter @@ -35,8 +35,9 @@ def _py_lock_dependencies(ctx): args.add("--output-file", requirements_out) args.add(dependencies_file) + print(uv) ctx.actions.run( - executable = uv.files_to_run, + executable = uv, arguments = [args], inputs = [dependencies_file], outputs = [requirements_out], @@ -47,8 +48,8 @@ def _py_lock_dependencies(ctx): files = depset([requirements_out]), )] -py_lock_dependencies = rule( - implementation = _py_lock_dependencies, +uv_pip_compile = rule( + implementation = _uv_pip_compile, attrs = { "constraints_file": attr.label(allow_single_file = True), "dependencies_file": attr.label(allow_single_file = True), @@ -56,6 +57,6 @@ py_lock_dependencies = rule( }, toolchains = [ "@bazel_tools//tools/python:toolchain_type", - "//python/private/uv:toolchain_type", + "//python:uv_toolchain_type", ], ) diff --git a/python/private/pypi/uv_toolchain.bzl b/python/private/pypi/uv_toolchain.bzl index 3ead3e631b..059ff5db0d 100644 --- a/python/private/pypi/uv_toolchain.bzl +++ b/python/private/pypi/uv_toolchain.bzl @@ -42,7 +42,7 @@ def _uv_toolchain_impl(ctx): if ctx.attr.uv_tool: uv_files = ctx.attr.uv_tool.files.to_list() - uv_path = _to_manifest_path(ctx, tool_files[0]) + uv_path = _to_manifest_path(ctx, uv_files[0]) # Make the $(UV_BIN) variable available in places like genrules. # See https://docs.bazel.build/versions/main/be/make-variables.html#custom_variables diff --git a/python/repositories.bzl b/python/repositories.bzl index 1a79cc1bc4..459c7d2f8c 100644 --- a/python/repositories.bzl +++ b/python/repositories.bzl @@ -726,15 +726,24 @@ def python_register_multi_toolchains( def _uv_repo_impl(repository_ctx): suffix = ".zip" if repository_ctx.attr.platform == "windows" else ".tar.gz" + filename = "uv-{platform}{suffix}".format( + platform = repository_ctx.attr.platform, + suffix = suffix, + ) url = "https://github.com/astral-sh/uv/releases/download/{version}/uv-{platform}{suffix}".format( - repository_ctx.attr.uv_version, - repository_ctx.attr.platform, - suffix, + version = repository_ctx.attr.uv_version, + platform = repository_ctx.attr.platform, + suffix = suffix, ) + if filename.endswith(".tar.gz"): + strip_prefix = filename[:-len(".tar.gz")] + else: + strip_prefix = None repository_ctx.download_and_extract( url = url, - integrity = UV_TOOL_VERSIONS[repository_ctx.attr.uv_version][repository_ctx.attr.platform], + #integrity = UV_TOOL_VERSIONS[repository_ctx.attr.uv_version][repository_ctx.attr.platform], + stripPrefix = strip_prefix, ) build_content = """# Generated by repositories.bzl load("@rules_python//python:toolchain.bzl", "uv_toolchain") From 8002c0e9e22b5c28fa0f285148c614887f6d64b7 Mon Sep 17 00:00:00 2001 From: Greg Date: Mon, 24 Jun 2024 22:28:41 +1000 Subject: [PATCH 20/67] Working toolchain --- python/private/pypi/toolchains_repo.bzl | 6 ++++ python/private/pypi/uv_pip_compile.bzl | 3 +- python/private/pypi/uv_toolchain.bzl | 48 +++++++------------------ python/repositories.bzl | 43 +++++++++++++--------- 4 files changed, 46 insertions(+), 54 deletions(-) diff --git a/python/private/pypi/toolchains_repo.bzl b/python/private/pypi/toolchains_repo.bzl index a0e8d37d57..d3932ddd82 100644 --- a/python/private/pypi/toolchains_repo.bzl +++ b/python/private/pypi/toolchains_repo.bzl @@ -21,6 +21,12 @@ UV_PLATFORMS = { "@platforms//cpu:aarch64", ], ), + "aarch64-unknown-linux-gnu": struct( + compatible_with = [ + "@platforms//os:linux", + "@platforms//cpu:aarch64", + ], + ), "x86_64-apple-darwin": struct( compatible_with = [ "@platforms//os:macos", diff --git a/python/private/pypi/uv_pip_compile.bzl b/python/private/pypi/uv_pip_compile.bzl index 04ad0149c3..1a84eb2cfa 100644 --- a/python/private/pypi/uv_pip_compile.bzl +++ b/python/private/pypi/uv_pip_compile.bzl @@ -16,7 +16,7 @@ def _uv_pip_compile(ctx): info = ctx.toolchains["//python:uv_toolchain_type"].uvtoolchaininfo - uv = info.uv_path + uv = info.binary python = ctx.toolchains["@bazel_tools//tools/python:toolchain_type"].py3_runtime.interpreter dependencies_file = ctx.file.dependencies_file @@ -35,7 +35,6 @@ def _uv_pip_compile(ctx): args.add("--output-file", requirements_out) args.add(dependencies_file) - print(uv) ctx.actions.run( executable = uv, arguments = [args], diff --git a/python/private/pypi/uv_toolchain.bzl b/python/private/pypi/uv_toolchain.bzl index 059ff5db0d..37cbb7dfd7 100644 --- a/python/private/pypi/uv_toolchain.bzl +++ b/python/private/pypi/uv_toolchain.bzl @@ -17,45 +17,24 @@ UvToolchainInfo = provider( doc = "Information about how to invoke the uv executable.", fields = { - "uv_files": """Files required in runfiles to make the uv executable available. - -May be empty if the uv_path points to a locally installed uv binary.""", - "uv_path": "Path to the uv executable.", + "binary": "Executable uv binary", + "version": "Uv version", }, ) -# Avoid using non-normalized paths (workspace/../other_workspace/path) -def _to_manifest_path(ctx, file): - if file.short_path.startswith("../"): - return "external/" + file.short_path[3:] - else: - return ctx.workspace_name + "/" + file.short_path - def _uv_toolchain_impl(ctx): - if ctx.attr.uv_tool and ctx.attr.uv_path: - fail("Can only set one of uv_tool or uv_path but both were set.") - if not ctx.attr.uv_tool and not ctx.attr.uv_path: - fail("Must set one of uv_tool or uv_path.") - - uv_files = [] - uv_path = ctx.attr.uv_path + binary = ctx.executable.uv - if ctx.attr.uv_tool: - uv_files = ctx.attr.uv_tool.files.to_list() - uv_path = _to_manifest_path(ctx, uv_files[0]) - - # Make the $(UV_BIN) variable available in places like genrules. - # See https://docs.bazel.build/versions/main/be/make-variables.html#custom_variables templatevariableinfo = platform_common.TemplateVariableInfo({ - "UV_BIN": uv_path, + "UV_BIN": binary.path, }) defaultinfo = DefaultInfo( - files = depset(uv_files), - runfiles = ctx.runfiles(files = uv_files), + files = depset([binary]), + runfiles = ctx.runfiles(files = [binary]), ) uvtoolchaininfo = UvToolchainInfo( - uv_path = uv_path, - uv_files = uv_files, + binary = binary, + version = ctx.attr.version.removeprefix("v"), ) # Export all the providers inside our ToolchainInfo @@ -74,15 +53,14 @@ def _uv_toolchain_impl(ctx): uv_toolchain = rule( implementation = _uv_toolchain_impl, attrs = { - "uv_path": attr.string( - doc = "Path to an existing uv executable", - mandatory = False, - ), - "uv_tool": attr.label( - doc = "A hermetically downloaded executable target for the target platform.", + "uv": attr.label( + doc = "A static uv binary.", mandatory = False, allow_single_file = True, + executable = True, + cfg = "exec", ), + "version": attr.string(mandatory = True, doc = "Version of the uv binary."), }, doc = "Defines a uv toolchain.", ) diff --git a/python/repositories.bzl b/python/repositories.bzl index 459c7d2f8c..88b4e3e4d4 100644 --- a/python/repositories.bzl +++ b/python/repositories.bzl @@ -724,15 +724,29 @@ def python_register_multi_toolchains( }, ) +UV_BUILD_TMPL = """\ +# Generated by repositories.bzl +load("@rules_python//python:toolchain.bzl", "uv_toolchain") + +uv_toolchain( + name = "uv_toolchain", + uv = "{binary}", + version = "{version}", +) +""" + def _uv_repo_impl(repository_ctx): - suffix = ".zip" if repository_ctx.attr.platform == "windows" else ".tar.gz" + platform = repository_ctx.attr.platform + uv_version = repository_ctx.attr.uv_version + + suffix = ".zip" if platform == "windows" else ".tar.gz" filename = "uv-{platform}{suffix}".format( - platform = repository_ctx.attr.platform, + platform = platform, suffix = suffix, ) url = "https://github.com/astral-sh/uv/releases/download/{version}/uv-{platform}{suffix}".format( - version = repository_ctx.attr.uv_version, - platform = repository_ctx.attr.platform, + version = uv_version, + platform = platform, suffix = suffix, ) if filename.endswith(".tar.gz"): @@ -745,20 +759,15 @@ def _uv_repo_impl(repository_ctx): #integrity = UV_TOOL_VERSIONS[repository_ctx.attr.uv_version][repository_ctx.attr.platform], stripPrefix = strip_prefix, ) - build_content = """# Generated by repositories.bzl -load("@rules_python//python:toolchain.bzl", "uv_toolchain") - -uv_toolchain( - name = "uv_toolchain", - uv_tool = select({ - "@bazel_tools//src/conditions:host_windows": "uv.exe", - "//conditions:default": "uv", - }), -) -""" - # Base BUILD file for this repository - repository_ctx.file("BUILD.bazel", build_content) + binary = "uv.exe" if platform.startswith("windows_") else "uv" + repository_ctx.file( + "BUILD.bazel", + UV_BUILD_TMPL.format( + binary = binary, + version = uv_version, + ), + ) uv_repositories = repository_rule( _uv_repo_impl, From 1c8bf779394e9143dc39d4b267ac0f47f7d47197 Mon Sep 17 00:00:00 2001 From: Greg Date: Mon, 24 Jun 2024 22:31:02 +1000 Subject: [PATCH 21/67] Working toolchain --- python/private/pypi/toolchains_repo.bzl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/python/private/pypi/toolchains_repo.bzl b/python/private/pypi/toolchains_repo.bzl index d3932ddd82..e136f9c046 100644 --- a/python/private/pypi/toolchains_repo.bzl +++ b/python/private/pypi/toolchains_repo.bzl @@ -48,7 +48,8 @@ UV_PLATFORMS = { } def _toolchains_repo_impl(repository_ctx): - build_content = """# Generated by toolchains_repo.bzl + build_content = """\ +# Generated by toolchains_repo.bzl # # These can be registered in the workspace file or passed to --extra_toolchains flag. # By default all these toolchains are registered by the uv_register_toolchains macro From 435606686d8918fec8aa728159221ed4aa196de0 Mon Sep 17 00:00:00 2001 From: Greg Date: Wed, 26 Jun 2024 22:59:44 +1000 Subject: [PATCH 22/67] Working executable rule --- MODULE.bazel | 2 +- examples/bzlmod/BUILD.bazel | 3 +- python/defs.bzl | 3 + python/extensions/BUILD.bazel | 9 +++ python/extensions/uv.bzl | 19 +++++ python/private/bzlmod/BUILD.bazel | 8 ++ python/private/bzlmod/uv.bzl | 19 +++++ python/private/pypi/BUILD.bazel | 6 ++ .../pypi/uv_extension.bzl} | 18 ++++- python/private/pypi/uv_pip_compile.bzl | 78 ++++++++++++++----- python/private/pypi/uv_toolchain.bzl | 4 +- python/repositories.bzl | 7 +- 12 files changed, 146 insertions(+), 30 deletions(-) create mode 100644 python/extensions/uv.bzl create mode 100644 python/private/bzlmod/uv.bzl rename python/{extensions.bzl => private/pypi/uv_extension.bzl} (70%) diff --git a/MODULE.bazel b/MODULE.bazel index 33955e4fc0..d5fd56f3bb 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -66,7 +66,7 @@ pip.parse( ) use_repo(pip, "rules_python_publish_deps") -uv = use_extension("//python:extensions.bzl", "uv") +uv = use_extension("//python/extensions:uv.bzl", "uv") uv.toolchain(uv_version = "0.2.13") use_repo(uv, "uv_toolchains") diff --git a/examples/bzlmod/BUILD.bazel b/examples/bzlmod/BUILD.bazel index 3dd01dc5f4..d33b7a58b1 100644 --- a/examples/bzlmod/BUILD.bazel +++ b/examples/bzlmod/BUILD.bazel @@ -10,8 +10,7 @@ load("@pip//:requirements.bzl", "all_data_requirements", "all_requirements", "al load("@python_3_9//:defs.bzl", py_test_with_transition = "py_test") load("@python_versions//3.10:defs.bzl", compile_pip_requirements_3_10 = "compile_pip_requirements") load("@python_versions//3.9:defs.bzl", compile_pip_requirements_3_9 = "compile_pip_requirements") -load("@rules_python//python:defs.bzl", "py_binary", "py_library", "py_test") -load("@rules_python//python/private/pypi:uv_pip_compile.bzl", "uv_pip_compile") +load("@rules_python//python:defs.bzl", "py_binary", "py_library", "py_test", "uv_pip_compile") # This stanza calls a rule that generates targets for managing pip dependencies # with pip-compile. diff --git a/python/defs.bzl b/python/defs.bzl index bd89f5b1f2..e26a150e62 100644 --- a/python/defs.bzl +++ b/python/defs.bzl @@ -21,6 +21,7 @@ load("//python:py_runtime.bzl", _py_runtime = "py_runtime") load("//python:py_runtime_info.bzl", internal_PyRuntimeInfo = "PyRuntimeInfo") load("//python:py_runtime_pair.bzl", _py_runtime_pair = "py_runtime_pair") load("//python:py_test.bzl", _py_test = "py_test") +load("//python/private/pypi:uv_pip_compile.bzl", _uv_pip_compile = "uv_pip_compile") load(":current_py_toolchain.bzl", _current_py_toolchain = "current_py_toolchain") load(":py_import.bzl", _py_import = "py_import") @@ -47,3 +48,5 @@ py_binary = _py_binary py_test = _py_test py_runtime = _py_runtime + +uv_pip_compile = _uv_pip_compile diff --git a/python/extensions/BUILD.bazel b/python/extensions/BUILD.bazel index 1bc2a71192..c8b6dbe0f5 100644 --- a/python/extensions/BUILD.bazel +++ b/python/extensions/BUILD.bazel @@ -39,3 +39,12 @@ bzl_library( "//python/private/bzlmod:python_bzl", ], ) + +bzl_library( + name = "uv_bzl", + srcs = ["uv.bzl"], + visibility = ["//:__subpackages__"], + deps = [ + "//python/private/bzlmod:python_bzl", + ], +) diff --git a/python/extensions/uv.bzl b/python/extensions/uv.bzl new file mode 100644 index 0000000000..26f51ea1ac --- /dev/null +++ b/python/extensions/uv.bzl @@ -0,0 +1,19 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"uv module extension" + +load("//python/private/bzlmod:uv.bzl", _uv = "uv") + +uv = _uv diff --git a/python/private/bzlmod/BUILD.bazel b/python/private/bzlmod/BUILD.bazel index 2cb35fc03e..4ab92d33d4 100644 --- a/python/private/bzlmod/BUILD.bazel +++ b/python/private/bzlmod/BUILD.bazel @@ -53,3 +53,11 @@ bzl_library( "//python/private:py_toolchain_suite_bzl", ], ) + +bzl_library( + name = "uv_bzl", + srcs = ["uv.bzl"], + deps = [ + "//python/private/pypi:uv_extension.bzl", + ], +) diff --git a/python/private/bzlmod/uv.bzl b/python/private/bzlmod/uv.bzl new file mode 100644 index 0000000000..0818520d3b --- /dev/null +++ b/python/private/bzlmod/uv.bzl @@ -0,0 +1,19 @@ +# Copyright 2024 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"uv module extension" + +load("//python/private/pypi:uv_extension.bzl", _uv = "uv") + +uv = _uv diff --git a/python/private/pypi/BUILD.bazel b/python/private/pypi/BUILD.bazel index a1dd1393f3..419c4413b9 100644 --- a/python/private/pypi/BUILD.bazel +++ b/python/private/pypi/BUILD.bazel @@ -290,6 +290,12 @@ bzl_library( visibility = ["//python:__subpackages__"], ) +bzl_library( + name = "uv_extension", + srcs = ["uv_extension.bzl"], + visibility = ["//python:__subpackages__"], +) + bzl_library( name = "versions", srcs = ["versions.bzl"], diff --git a/python/extensions.bzl b/python/private/pypi/uv_extension.bzl similarity index 70% rename from python/extensions.bzl rename to python/private/pypi/uv_extension.bzl index aceb974c52..54faacd78b 100644 --- a/python/extensions.bzl +++ b/python/private/pypi/uv_extension.bzl @@ -1,6 +1,20 @@ -"""Extensions for bzlmod.""" +# Copyright 2024 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. -load(":repositories.bzl", "uv_register_toolchains") +"uv module extension" + +load("//python:repositories.bzl", "uv_register_toolchains") _DEFAULT_NAME = "uv" diff --git a/python/private/pypi/uv_pip_compile.bzl b/python/private/pypi/uv_pip_compile.bzl index 1a84eb2cfa..e2ff28301c 100644 --- a/python/private/pypi/uv_pip_compile.bzl +++ b/python/private/pypi/uv_pip_compile.bzl @@ -14,6 +14,17 @@ "Rule for locking third-party dependencies with uv." +script_template = """\ +{uv} pip compile \ +--python {python} \ +--python-platform windows \ +--python-version 3.9 \ +--no-strip-extras \ +--generate-hashes \ +--output-file - \ +{dependencies_file} +""" + def _uv_pip_compile(ctx): info = ctx.toolchains["//python:uv_toolchain_type"].uvtoolchaininfo uv = info.binary @@ -21,30 +32,58 @@ def _uv_pip_compile(ctx): python = ctx.toolchains["@bazel_tools//tools/python:toolchain_type"].py3_runtime.interpreter dependencies_file = ctx.file.dependencies_file - args = ctx.actions.args() - args.add("pip") - args.add("compile") + # Option 1: Build action option. + # Not really appropriate, but it executes. + + # args = ctx.actions.args() + # args.add("pip") + # args.add("compile") # uv will use this python for operations where it needs to execute python code. See: UV_PYTHON and https://github.com/astral-sh/uv?tab=readme-ov-file#installing-into-arbitrary-python-environments - args.add("--python", python) - args.add("--python-platform", "windows") - args.add("--python-version", "3.9") - args.add("--no-strip-extras") - args.add("--generate-hashes") - requirements_out = ctx.actions.declare_file(ctx.label.name + ".requirements.out") - args.add("--output-file", requirements_out) - args.add(dependencies_file) - - ctx.actions.run( - executable = uv, - arguments = [args], - inputs = [dependencies_file], - outputs = [requirements_out], - tools = [python], + # args.add("--python", python) + # args.add("--python-platform", "windows") + # args.add("--python-version", "3.9") + # args.add("--no-strip-extras") + # args.add("--generate-hashes") + #requirements_out = ctx.actions.declare_file(ctx.label.name + ".requirements.out") + # args.add("--output-file", requirements_out) + # args.add(dependencies_file) + + # ctx.actions.run( + # executable = uv, + # arguments = [args], + # inputs = [dependencies_file], + # outputs = [requirements_out], + # tools = [python], + # ) + + # Option 2: Run action option. + # Works to exec uv --version, but will need rest of arguments plumbed through. + + # executable = ctx.actions.declare_file("%s-uv" % ctx.label.name) + # ctx.actions.symlink( + # is_executable = True, + # output = executable, + # target_file = uv, + # ) + + # Option 3: Run action option. + # Works to exec uv with some (but not all) arguments plumbed through. Output to a directory of the resolved output needs to be done. + executable = ctx.actions.declare_file("{name}-{uv_name}".format( + name = ctx.label.name, + uv_name = uv.basename, + )) + script_content = script_template.format( + uv = uv.path, + python = python.path, + dependencies_file = dependencies_file.path, ) + ctx.actions.write(executable, script_content, is_executable = True) return [DefaultInfo( - files = depset([requirements_out]), + files = depset([executable]), + executable = executable, + runfiles = ctx.runfiles([uv, dependencies_file, python]), )] uv_pip_compile = rule( @@ -58,4 +97,5 @@ uv_pip_compile = rule( "@bazel_tools//tools/python:toolchain_type", "//python:uv_toolchain_type", ], + executable = True, ) diff --git a/python/private/pypi/uv_toolchain.bzl b/python/private/pypi/uv_toolchain.bzl index 37cbb7dfd7..c930660903 100644 --- a/python/private/pypi/uv_toolchain.bzl +++ b/python/private/pypi/uv_toolchain.bzl @@ -17,8 +17,8 @@ UvToolchainInfo = provider( doc = "Information about how to invoke the uv executable.", fields = { - "binary": "Executable uv binary", - "version": "Uv version", + "binary": "uv binary", + "version": "uv version", }, ) diff --git a/python/repositories.bzl b/python/repositories.bzl index 88b4e3e4d4..90441fc811 100644 --- a/python/repositories.bzl +++ b/python/repositories.bzl @@ -739,15 +739,14 @@ def _uv_repo_impl(repository_ctx): platform = repository_ctx.attr.platform uv_version = repository_ctx.attr.uv_version - suffix = ".zip" if platform == "windows" else ".tar.gz" + suffix = ".zip" if "windows" in platform else ".tar.gz" filename = "uv-{platform}{suffix}".format( platform = platform, suffix = suffix, ) - url = "https://github.com/astral-sh/uv/releases/download/{version}/uv-{platform}{suffix}".format( + url = "https://github.com/astral-sh/uv/releases/download/{version}/{filename}".format( version = uv_version, - platform = platform, - suffix = suffix, + filename = filename, ) if filename.endswith(".tar.gz"): strip_prefix = filename[:-len(".tar.gz")] From 26a87f2165145fee86883ebd225eb9e87b05ef29 Mon Sep 17 00:00:00 2001 From: Greg Date: Wed, 26 Jun 2024 23:11:55 +1000 Subject: [PATCH 23/67] Working executable rule --- python/private/pypi/uv_toolchain.bzl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/private/pypi/uv_toolchain.bzl b/python/private/pypi/uv_toolchain.bzl index c930660903..c4fbc9ef55 100644 --- a/python/private/pypi/uv_toolchain.bzl +++ b/python/private/pypi/uv_toolchain.bzl @@ -58,7 +58,7 @@ uv_toolchain = rule( mandatory = False, allow_single_file = True, executable = True, - cfg = "exec", + cfg = "target", ), "version": attr.string(mandatory = True, doc = "Version of the uv binary."), }, From eea3f3443e46caf6f00a09e3566c4c987a59518c Mon Sep 17 00:00:00 2001 From: Greg Date: Wed, 26 Jun 2024 23:15:04 +1000 Subject: [PATCH 24/67] Working executable rule --- python/repositories.bzl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/repositories.bzl b/python/repositories.bzl index 90441fc811..0f6cf9114f 100644 --- a/python/repositories.bzl +++ b/python/repositories.bzl @@ -751,7 +751,7 @@ def _uv_repo_impl(repository_ctx): if filename.endswith(".tar.gz"): strip_prefix = filename[:-len(".tar.gz")] else: - strip_prefix = None + strip_prefix = "" repository_ctx.download_and_extract( url = url, From 2cede410a3e09f9ee5377dbca638aef87d01be87 Mon Sep 17 00:00:00 2001 From: Richard Levasseur Date: Thu, 27 Jun 2024 19:02:31 -0700 Subject: [PATCH 25/67] Fix copyright date --- python/extensions/uv.bzl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/extensions/uv.bzl b/python/extensions/uv.bzl index 26f51ea1ac..375816e966 100644 --- a/python/extensions/uv.bzl +++ b/python/extensions/uv.bzl @@ -1,4 +1,4 @@ -# Copyright 2023 The Bazel Authors. All rights reserved. +# Copyright 2024 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. From 76b381a23be3ae566255d6fe3cdfbe2167479915 Mon Sep 17 00:00:00 2001 From: Richard Levasseur Date: Thu, 27 Jun 2024 19:12:46 -0700 Subject: [PATCH 26/67] address some nit/style type of comments --- python/private/pypi/BUILD.bazel | 2 ++ python/private/pypi/resolved_toolchain.bzl | 9 +++++---- python/private/pypi/toolchains_repo.bzl | 6 +++++- python/private/pypi/uv_pip_compile.bzl | 6 ++++-- python/private/pypi/versions.bzl | 13 +++++++++++++ python/private/toolchain_types.bzl | 1 + python/repositories.bzl | 3 ++- 7 files changed, 32 insertions(+), 8 deletions(-) diff --git a/python/private/pypi/BUILD.bazel b/python/private/pypi/BUILD.bazel index 419c4413b9..bf00b1a494 100644 --- a/python/private/pypi/BUILD.bazel +++ b/python/private/pypi/BUILD.bazel @@ -306,10 +306,12 @@ bzl_library( name = "resolved_toolchain", srcs = ["resolved_toolchain.bzl"], visibility = ["//python:__subpackages__"], + deps = ["//python/private:toolchain_types_bzl"], ) bzl_library( name = "uv_pip_compile", srcs = ["uv_pip_compile.bzl"], visibility = ["//visibility:public"], + deps = ["//python/private:toolchain_types_bzl"], ) diff --git a/python/private/pypi/resolved_toolchain.bzl b/python/private/pypi/resolved_toolchain.bzl index 52ed60ca1c..33055a5453 100644 --- a/python/private/pypi/resolved_toolchain.bzl +++ b/python/private/pypi/resolved_toolchain.bzl @@ -15,7 +15,9 @@ """This module implements an alias rule to the resolved toolchain. """ -DOC = """\ +load("//python/private:toolchain_types", "UV_TOOLCHAIN_TYPE") + +_DOC = """\ Exposes a concrete toolchain which is the result of Bazel resolving the toolchain for the execution or target platform. Workaround for https://github.com/bazelbuild/bazel/issues/14009 @@ -35,7 +37,6 @@ def _uv_resolved_toolchain_impl(ctx): # https://cs.opensource.google/bazel/bazel/+/master:tools/jdk/java_toolchain_alias.bzl uv_resolved_toolchain = rule( implementation = _uv_resolved_toolchain_impl, - toolchains = ["//python:uv_toolchain_type"], - incompatible_use_toolchain_transition = True, - doc = DOC, + toolchains = [UV_TOOLCHAIN_TYPE], + doc = _DOC, ) diff --git a/python/private/pypi/toolchains_repo.bzl b/python/private/pypi/toolchains_repo.bzl index e136f9c046..ab2fc47349 100644 --- a/python/private/pypi/toolchains_repo.bzl +++ b/python/private/pypi/toolchains_repo.bzl @@ -57,15 +57,18 @@ def _toolchains_repo_impl(repository_ctx): """ + # todo: sort this for more stable/predictable/friendly output for [platform, meta] in UV_PLATFORMS.items(): build_content += """ +load("@rules_python//python/private:toolchain_types.bzl", "UV_TOOLCHAIN_TYPE") + # Declare a toolchain Bazel will select for running the tool in an action # on the execution platform. toolchain( name = "{platform}_uv_toolchain", exec_compatible_with = {compatible_with}, toolchain = "@{user_repository_name}_{platform}//:uv_toolchain", - toolchain_type = "@rules_python//python:uv_toolchain_type", + toolchain_type = UV_TOOLCHAIN_TYPE, ) """.format( platform = platform, @@ -73,6 +76,7 @@ toolchain( compatible_with = meta.compatible_with, ) + repository_ctx.file("REPO.bazel", "") repository_ctx.file("BUILD.bazel", build_content) uv_toolchains_repo = repository_rule( diff --git a/python/private/pypi/uv_pip_compile.bzl b/python/private/pypi/uv_pip_compile.bzl index e2ff28301c..a9cc1dae87 100644 --- a/python/private/pypi/uv_pip_compile.bzl +++ b/python/private/pypi/uv_pip_compile.bzl @@ -14,6 +14,8 @@ "Rule for locking third-party dependencies with uv." +load("//python/private:toolchain_types.bzl", "TARGET_TOOLCHAIN_TYPE") + script_template = """\ {uv} pip compile \ --python {python} \ @@ -29,7 +31,7 @@ def _uv_pip_compile(ctx): info = ctx.toolchains["//python:uv_toolchain_type"].uvtoolchaininfo uv = info.binary - python = ctx.toolchains["@bazel_tools//tools/python:toolchain_type"].py3_runtime.interpreter + python = ctx.toolchains[TARGET_TOOLCHAIN_TYPE].py3_runtime.interpreter dependencies_file = ctx.file.dependencies_file # Option 1: Build action option. @@ -94,7 +96,7 @@ uv_pip_compile = rule( "overrides_file": attr.label(allow_single_file = True), }, toolchains = [ - "@bazel_tools//tools/python:toolchain_type", + TARGET_TOOLCHAIN_TYPE, "//python:uv_toolchain_type", ], executable = True, diff --git a/python/private/pypi/versions.bzl b/python/private/pypi/versions.bzl index 77ed5941a9..9c5a4b7d33 100644 --- a/python/private/pypi/versions.bzl +++ b/python/private/pypi/versions.bzl @@ -1,3 +1,16 @@ +# Copyright 2024 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. """Version and integrity information for downloaded artifacts""" # From: https://github.com/astral-sh/uv/releases diff --git a/python/private/toolchain_types.bzl b/python/private/toolchain_types.bzl index ef81bf3bd4..4e3a4a09a1 100644 --- a/python/private/toolchain_types.bzl +++ b/python/private/toolchain_types.bzl @@ -21,3 +21,4 @@ implementation of the toolchain. TARGET_TOOLCHAIN_TYPE = Label("//python:toolchain_type") EXEC_TOOLS_TOOLCHAIN_TYPE = Label("//python:exec_tools_toolchain_type") PY_CC_TOOLCHAIN_TYPE = Label("//python/cc:toolchain_type") +UV_TOOLCHAIN_TYPE = Label("//python:uv_toolchain_type") diff --git a/python/repositories.bzl b/python/repositories.bzl index 0f6cf9114f..d2b0cbfeca 100644 --- a/python/repositories.bzl +++ b/python/repositories.bzl @@ -767,6 +767,7 @@ def _uv_repo_impl(repository_ctx): version = uv_version, ), ) + repository_ctx.file("REPO.bazel", "") uv_repositories = repository_rule( _uv_repo_impl, @@ -786,7 +787,7 @@ def uv_register_toolchains(name, register = True, **kwargs): name: base name for all created repos, like "uv0_2_13" register: whether to call through to native.register_toolchains. Should be True for WORKSPACE users, but false when used under bzlmod extension - **kwargs: passed to each node_repositories call + **kwargs: passed to each uv_repositories call """ for platform in UV_PLATFORMS.keys(): uv_repositories( From 60414146b5e58706252611dbd99ed894fc0b8197 Mon Sep 17 00:00:00 2001 From: Greg Date: Fri, 28 Jun 2024 20:09:07 +1000 Subject: [PATCH 27/67] . --- python/private/pypi/BUILD.bazel | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/python/private/pypi/BUILD.bazel b/python/private/pypi/BUILD.bazel index 0a6a8232b6..fbc34731cd 100644 --- a/python/private/pypi/BUILD.bazel +++ b/python/private/pypi/BUILD.bazel @@ -257,6 +257,19 @@ bzl_library( visibility = ["//python:__subpackages__"], ) +bzl_library( + name = "uv_extension", + srcs = ["uv_extension.bzl"], + visibility = ["//python:__subpackages__"], +) + +bzl_library( + name = "uv_pip_compile", + srcs = ["uv_pip_compile.bzl"], + visibility = ["//visibility:public"], + deps = ["//python/private:toolchain_types_bzl"], +) + bzl_library( name = "whl_library_alias_bzl", srcs = ["whl_library_alias.bzl"], @@ -300,19 +313,6 @@ bzl_library( deps = [":parse_whl_name_bzl"], ) -bzl_library( - name = "uv_extension", - srcs = ["uv_extension.bzl"], - visibility = ["//python:__subpackages__"], -) - -bzl_library( - name = "uv_pip_compile", - srcs = ["uv_pip_compile.bzl"], - visibility = ["//visibility:public"], - deps = ["//python/private:toolchain_types_bzl"], -) - bzl_library( name = "versions", srcs = ["versions.bzl"], From ba09edcc618128182018ff616470c76b075e7e25 Mon Sep 17 00:00:00 2001 From: Greg Date: Sat, 29 Jun 2024 19:52:57 +1000 Subject: [PATCH 28/67] Address review comments --- python/private/bzlmod/python.bzl | 17 ++--------------- python/private/pypi/BUILD.bazel | 3 +++ python/private/pypi/resolved_toolchain.bzl | 2 +- python/private/pypi/toolchains_repo.bzl | 15 +++++++++++---- python/private/pypi/uv_pip_compile.bzl | 4 ++-- .../pypi/{versions.bzl => uv_versions.bzl} | 0 python/private/text_util.bzl | 16 ++++++++++++++++ python/repositories.bzl | 7 +++---- 8 files changed, 38 insertions(+), 26 deletions(-) rename python/private/pypi/{versions.bzl => uv_versions.bzl} (100%) diff --git a/python/private/bzlmod/python.bzl b/python/private/bzlmod/python.bzl index f8be271fd6..835e4d279b 100644 --- a/python/private/bzlmod/python.bzl +++ b/python/private/bzlmod/python.bzl @@ -16,6 +16,7 @@ load("@bazel_features//:features.bzl", "bazel_features") load("//python:repositories.bzl", "python_register_toolchains") +load("//python/private:text_util.bzl", "render") load("//python/private:toolchains_repo.bzl", "multi_toolchain_aliases") load("//python/private:util.bzl", "IS_BAZEL_6_4_OR_HIGHER") load(":pythons_hub.bzl", "hub_repo") @@ -25,20 +26,6 @@ load(":pythons_hub.bzl", "hub_repo") _MAX_NUM_TOOLCHAINS = 9999 _TOOLCHAIN_INDEX_PAD_LENGTH = len(str(_MAX_NUM_TOOLCHAINS)) -def _toolchain_prefix(index, name): - """Prefixes the given name with the index, padded with zeros to ensure lexicographic sorting. - - Examples: - _toolchain_prefix( 2, "foo") == "_0002_foo_" - _toolchain_prefix(2000, "foo") == "_2000_foo_" - """ - return "_{}_{}_".format(_left_pad_zero(index, _TOOLCHAIN_INDEX_PAD_LENGTH), name) - -def _left_pad_zero(index, length): - if index < 0: - fail("index must be non-negative") - return ("0" * length + str(index))[-length:] - # Printing a warning msg not debugging, so we have to disable # the buildifier check. # buildifier: disable=print @@ -202,7 +189,7 @@ def _python_impl(module_ctx): name = "pythons_hub", default_python_version = default_toolchain.python_version, toolchain_prefixes = [ - _toolchain_prefix(index, toolchain.name) + render.toolchain_prefix(index, toolchain.name, _TOOLCHAIN_INDEX_PAD_LENGTH) for index, toolchain in enumerate(toolchains) ], toolchain_python_versions = [t.python_version for t in toolchains], diff --git a/python/private/pypi/BUILD.bazel b/python/private/pypi/BUILD.bazel index fbc34731cd..90ccadf448 100644 --- a/python/private/pypi/BUILD.bazel +++ b/python/private/pypi/BUILD.bazel @@ -255,6 +255,9 @@ bzl_library( name = "toolchains_repo", srcs = ["toolchains_repo.bzl"], visibility = ["//python:__subpackages__"], + deps = [ + "//python/private:text_util_bzl", + ], ) bzl_library( diff --git a/python/private/pypi/resolved_toolchain.bzl b/python/private/pypi/resolved_toolchain.bzl index 33055a5453..dc52081d05 100644 --- a/python/private/pypi/resolved_toolchain.bzl +++ b/python/private/pypi/resolved_toolchain.bzl @@ -15,7 +15,7 @@ """This module implements an alias rule to the resolved toolchain. """ -load("//python/private:toolchain_types", "UV_TOOLCHAIN_TYPE") +load("//python/private:toolchain_types.bzl", "UV_TOOLCHAIN_TYPE") _DOC = """\ Exposes a concrete toolchain which is the result of Bazel resolving the diff --git a/python/private/pypi/toolchains_repo.bzl b/python/private/pypi/toolchains_repo.bzl index ab2fc47349..3b28a9f58d 100644 --- a/python/private/pypi/toolchains_repo.bzl +++ b/python/private/pypi/toolchains_repo.bzl @@ -14,6 +14,13 @@ "Creates a repository to hold toolchains" +load("//python/private:text_util.bzl", "render") + +# This limit can be increased essentially arbitrarily, but doing so will cause a rebuild of all +# targets using any of these toolchains due to the changed repository name. +_MAX_NUM_TOOLCHAINS = 9999 +_TOOLCHAIN_INDEX_PAD_LENGTH = len(str(_MAX_NUM_TOOLCHAINS)) + UV_PLATFORMS = { "aarch64-apple-darwin": struct( compatible_with = [ @@ -57,26 +64,26 @@ def _toolchains_repo_impl(repository_ctx): """ - # todo: sort this for more stable/predictable/friendly output - for [platform, meta] in UV_PLATFORMS.items(): + for index, [platform, meta] in enumerate(UV_PLATFORMS.items()): + prefix = render.toolchain_prefix(index, "uv_toolchain", _TOOLCHAIN_INDEX_PAD_LENGTH) build_content += """ load("@rules_python//python/private:toolchain_types.bzl", "UV_TOOLCHAIN_TYPE") # Declare a toolchain Bazel will select for running the tool in an action # on the execution platform. toolchain( - name = "{platform}_uv_toolchain", + name = "{prefix}{platform}", exec_compatible_with = {compatible_with}, toolchain = "@{user_repository_name}_{platform}//:uv_toolchain", toolchain_type = UV_TOOLCHAIN_TYPE, ) """.format( platform = platform, + prefix = prefix, user_repository_name = repository_ctx.attr.user_repository_name, compatible_with = meta.compatible_with, ) - repository_ctx.file("REPO.bazel", "") repository_ctx.file("BUILD.bazel", build_content) uv_toolchains_repo = repository_rule( diff --git a/python/private/pypi/uv_pip_compile.bzl b/python/private/pypi/uv_pip_compile.bzl index a9cc1dae87..1e3a3dd893 100644 --- a/python/private/pypi/uv_pip_compile.bzl +++ b/python/private/pypi/uv_pip_compile.bzl @@ -14,7 +14,7 @@ "Rule for locking third-party dependencies with uv." -load("//python/private:toolchain_types.bzl", "TARGET_TOOLCHAIN_TYPE") +load("//python/private:toolchain_types.bzl", "TARGET_TOOLCHAIN_TYPE", "UV_TOOLCHAIN_TYPE") script_template = """\ {uv} pip compile \ @@ -97,7 +97,7 @@ uv_pip_compile = rule( }, toolchains = [ TARGET_TOOLCHAIN_TYPE, - "//python:uv_toolchain_type", + UV_TOOLCHAIN_TYPE, ], executable = True, ) diff --git a/python/private/pypi/versions.bzl b/python/private/pypi/uv_versions.bzl similarity index 100% rename from python/private/pypi/versions.bzl rename to python/private/pypi/uv_versions.bzl diff --git a/python/private/text_util.bzl b/python/private/text_util.bzl index 702a08e281..8a018e7969 100644 --- a/python/private/text_util.bzl +++ b/python/private/text_util.bzl @@ -99,11 +99,27 @@ def _render_tuple(items, *, value_repr = repr): ")", ]) +def _toolchain_prefix(index, name, pad_length): + """Prefixes the given name with the index, padded with zeros to ensure lexicographic sorting. + + Examples: + toolchain_prefix( 2, "foo", 4) == "_0002_foo_" + toolchain_prefix(2000, "foo", 4) == "_2000_foo_" + """ + return "_{}_{}_".format(_left_pad_zero(index, pad_length), name) + +def _left_pad_zero(index, length): + if index < 0: + fail("index must be non-negative") + return ("0" * length + str(index))[-length:] + render = struct( alias = _render_alias, dict = _render_dict, indent = _indent, + left_pad_zero = _left_pad_zero, list = _render_list, select = _render_select, tuple = _render_tuple, + toolchain_prefix = _toolchain_prefix, ) diff --git a/python/repositories.bzl b/python/repositories.bzl index d2b0cbfeca..ba71b79e47 100644 --- a/python/repositories.bzl +++ b/python/repositories.bzl @@ -34,7 +34,7 @@ load( ) load("//python/private/pypi:deps.bzl", "pypi_deps") load("//python/private/pypi:toolchains_repo.bzl", "UV_PLATFORMS", "uv_toolchains_repo") -load("//python/private/pypi:versions.bzl", "UV_TOOL_VERSIONS") +load("//python/private/pypi:uv_versions.bzl", "UV_TOOL_VERSIONS") load( ":versions.bzl", "DEFAULT_RELEASE_BASE_URL", @@ -767,9 +767,8 @@ def _uv_repo_impl(repository_ctx): version = uv_version, ), ) - repository_ctx.file("REPO.bazel", "") -uv_repositories = repository_rule( +uv_repository = repository_rule( _uv_repo_impl, doc = "Fetch external tools needed for uv toolchain", attrs = { @@ -790,7 +789,7 @@ def uv_register_toolchains(name, register = True, **kwargs): **kwargs: passed to each uv_repositories call """ for platform in UV_PLATFORMS.keys(): - uv_repositories( + uv_repository( name = name + "_" + platform, platform = platform, **kwargs From ec0f6fa92b21955f07d9aa2619b32f39a8679fde Mon Sep 17 00:00:00 2001 From: Greg Date: Sat, 29 Jun 2024 19:58:44 +1000 Subject: [PATCH 29/67] Address review comments --- python/private/pypi/BUILD.bazel | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/python/private/pypi/BUILD.bazel b/python/private/pypi/BUILD.bazel index 90ccadf448..44450b65ec 100644 --- a/python/private/pypi/BUILD.bazel +++ b/python/private/pypi/BUILD.bazel @@ -273,6 +273,12 @@ bzl_library( deps = ["//python/private:toolchain_types_bzl"], ) +bzl_library( + name = "uv_versions_bzl", + srcs = ["uv_versions.bzl"], + visibility = ["//python:__subpackages__"], +) + bzl_library( name = "whl_library_alias_bzl", srcs = ["whl_library_alias.bzl"], @@ -315,9 +321,3 @@ bzl_library( srcs = ["whl_target_platforms.bzl"], deps = [":parse_whl_name_bzl"], ) - -bzl_library( - name = "versions", - srcs = ["versions.bzl"], - visibility = ["//python:__subpackages__"], -) From 4cb451ae8006eb88e2fc975d98ee8a60124a9fb6 Mon Sep 17 00:00:00 2001 From: Greg Date: Sat, 29 Jun 2024 21:21:35 +1000 Subject: [PATCH 30/67] Address review comments --- python/extensions/BUILD.bazel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/extensions/BUILD.bazel b/python/extensions/BUILD.bazel index c8b6dbe0f5..541c90e579 100644 --- a/python/extensions/BUILD.bazel +++ b/python/extensions/BUILD.bazel @@ -45,6 +45,6 @@ bzl_library( srcs = ["uv.bzl"], visibility = ["//:__subpackages__"], deps = [ - "//python/private/bzlmod:python_bzl", + "//python/private/bzlmod:uv_bzl", ], ) From 07c1ff65779e103ba1b5afa674c0eae3e8b65baf Mon Sep 17 00:00:00 2001 From: Greg Date: Sat, 29 Jun 2024 21:24:11 +1000 Subject: [PATCH 31/67] Address review comments --- python/extensions/uv.bzl | 2 +- python/private/bzlmod/uv.bzl | 19 ------------------- 2 files changed, 1 insertion(+), 20 deletions(-) delete mode 100644 python/private/bzlmod/uv.bzl diff --git a/python/extensions/uv.bzl b/python/extensions/uv.bzl index 375816e966..7fbc64d8ad 100644 --- a/python/extensions/uv.bzl +++ b/python/extensions/uv.bzl @@ -14,6 +14,6 @@ "uv module extension" -load("//python/private/bzlmod:uv.bzl", _uv = "uv") +load("//python/private/pypi:uv_extension.bzl", _uv = "uv") uv = _uv diff --git a/python/private/bzlmod/uv.bzl b/python/private/bzlmod/uv.bzl deleted file mode 100644 index 0818520d3b..0000000000 --- a/python/private/bzlmod/uv.bzl +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright 2024 The Bazel Authors. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"uv module extension" - -load("//python/private/pypi:uv_extension.bzl", _uv = "uv") - -uv = _uv From a60a308ffc8f8632786aee1b36583ba4c567ac24 Mon Sep 17 00:00:00 2001 From: Greg Date: Sat, 29 Jun 2024 21:30:51 +1000 Subject: [PATCH 32/67] Address review comments --- python/uv/BUILD.bazel | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 python/uv/BUILD.bazel diff --git a/python/uv/BUILD.bazel b/python/uv/BUILD.bazel new file mode 100644 index 0000000000..11aeffb9c7 --- /dev/null +++ b/python/uv/BUILD.bazel @@ -0,0 +1,28 @@ +# Copyright 2024 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +package(default_visibility = ["//visibility:public"]) + +toolchain_type( + name = "uv_toolchain_type", + visibility = ["//visibility:public"], +) + +uv_resolved_toolchain( + name = "uv_resolved_toolchain", + # Marked manual so that `bazel test //...` passes + # even if no toolchain is registered. + tags = ["manual"], + visibility = ["//visibility:public"], +) From ec0f9f409b299e6a51695b19ddf76b4a9ab07280 Mon Sep 17 00:00:00 2001 From: Greg Date: Sat, 29 Jun 2024 21:38:53 +1000 Subject: [PATCH 33/67] Address review comments --- examples/bzlmod/BUILD.bazel | 3 ++- python/uv/defs.bzl | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 python/uv/defs.bzl diff --git a/examples/bzlmod/BUILD.bazel b/examples/bzlmod/BUILD.bazel index d33b7a58b1..4b1d3c7673 100644 --- a/examples/bzlmod/BUILD.bazel +++ b/examples/bzlmod/BUILD.bazel @@ -10,7 +10,8 @@ load("@pip//:requirements.bzl", "all_data_requirements", "all_requirements", "al load("@python_3_9//:defs.bzl", py_test_with_transition = "py_test") load("@python_versions//3.10:defs.bzl", compile_pip_requirements_3_10 = "compile_pip_requirements") load("@python_versions//3.9:defs.bzl", compile_pip_requirements_3_9 = "compile_pip_requirements") -load("@rules_python//python:defs.bzl", "py_binary", "py_library", "py_test", "uv_pip_compile") +load("@rules_python//python:defs.bzl", "py_binary", "py_library", "py_test") +load("@rules_python//python/uv:defs.bzl", "uv_pip_compile") # This stanza calls a rule that generates targets for managing pip dependencies # with pip-compile. diff --git a/python/uv/defs.bzl b/python/uv/defs.bzl new file mode 100644 index 0000000000..afaab7ce46 --- /dev/null +++ b/python/uv/defs.bzl @@ -0,0 +1,19 @@ +# Copyright 2024 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Experimental toolchain for uv""" + +load("//python/private/pypi:uv_pip_compile.bzl", _uv_pip_compile = "uv_pip_compile") + +uv_pip_compile = _uv_pip_compile From 014afbb680a746ce3018e14adf9d4b3f90a9f6c9 Mon Sep 17 00:00:00 2001 From: Greg Date: Sat, 29 Jun 2024 21:40:29 +1000 Subject: [PATCH 34/67] Address review comments --- python/defs.bzl | 3 --- 1 file changed, 3 deletions(-) diff --git a/python/defs.bzl b/python/defs.bzl index e26a150e62..bd89f5b1f2 100644 --- a/python/defs.bzl +++ b/python/defs.bzl @@ -21,7 +21,6 @@ load("//python:py_runtime.bzl", _py_runtime = "py_runtime") load("//python:py_runtime_info.bzl", internal_PyRuntimeInfo = "PyRuntimeInfo") load("//python:py_runtime_pair.bzl", _py_runtime_pair = "py_runtime_pair") load("//python:py_test.bzl", _py_test = "py_test") -load("//python/private/pypi:uv_pip_compile.bzl", _uv_pip_compile = "uv_pip_compile") load(":current_py_toolchain.bzl", _current_py_toolchain = "current_py_toolchain") load(":py_import.bzl", _py_import = "py_import") @@ -48,5 +47,3 @@ py_binary = _py_binary py_test = _py_test py_runtime = _py_runtime - -uv_pip_compile = _uv_pip_compile From e8fbfa1265aefbf18714489ab8b1e634e2e9e43d Mon Sep 17 00:00:00 2001 From: Greg Date: Sat, 29 Jun 2024 21:43:07 +1000 Subject: [PATCH 35/67] Address review comments --- python/private/bzlmod/BUILD.bazel | 8 -------- 1 file changed, 8 deletions(-) diff --git a/python/private/bzlmod/BUILD.bazel b/python/private/bzlmod/BUILD.bazel index 4ab92d33d4..2cb35fc03e 100644 --- a/python/private/bzlmod/BUILD.bazel +++ b/python/private/bzlmod/BUILD.bazel @@ -53,11 +53,3 @@ bzl_library( "//python/private:py_toolchain_suite_bzl", ], ) - -bzl_library( - name = "uv_bzl", - srcs = ["uv.bzl"], - deps = [ - "//python/private/pypi:uv_extension.bzl", - ], -) From 23628ea177cc6ad63348ad68bd7fd31f2882c70c Mon Sep 17 00:00:00 2001 From: Greg Date: Sat, 29 Jun 2024 21:44:29 +1000 Subject: [PATCH 36/67] Address review comments --- python/BUILD.bazel | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/python/BUILD.bazel b/python/BUILD.bazel index 2ca28aa920..0e424abac0 100644 --- a/python/BUILD.bazel +++ b/python/BUILD.bazel @@ -24,7 +24,6 @@ that @rules_python//python is only concerned with the core rules. """ load("@bazel_skylib//:bzl_library.bzl", "bzl_library") -load("//python/private/pypi:resolved_toolchain.bzl", "uv_resolved_toolchain") load(":current_py_toolchain.bzl", "current_py_toolchain") package(default_visibility = ["//visibility:public"]) @@ -348,16 +347,3 @@ exports_files([ current_py_toolchain( name = "current_py_toolchain", ) - -toolchain_type( - name = "uv_toolchain_type", - visibility = ["//visibility:public"], -) - -uv_resolved_toolchain( - name = "uv_resolved_toolchain", - # Marked manual so that `bazel test //...` passes - # even if no toolchain is registered. - tags = ["manual"], - visibility = ["//visibility:public"], -) From c2d76945e34727c6fa3758a45d7341a7b844e2c6 Mon Sep 17 00:00:00 2001 From: Greg Date: Sat, 29 Jun 2024 22:02:16 +1000 Subject: [PATCH 37/67] Address review comments --- python/private/pypi/uv_pip_compile.bzl | 2 +- python/private/toolchain_types.bzl | 2 +- python/repositories.bzl | 2 +- python/uv/BUILD.bazel | 18 +++++++++++++++++- python/{ => uv}/toolchain.bzl | 0 5 files changed, 20 insertions(+), 4 deletions(-) rename python/{ => uv}/toolchain.bzl (100%) diff --git a/python/private/pypi/uv_pip_compile.bzl b/python/private/pypi/uv_pip_compile.bzl index 1e3a3dd893..dcf56d7aad 100644 --- a/python/private/pypi/uv_pip_compile.bzl +++ b/python/private/pypi/uv_pip_compile.bzl @@ -28,7 +28,7 @@ script_template = """\ """ def _uv_pip_compile(ctx): - info = ctx.toolchains["//python:uv_toolchain_type"].uvtoolchaininfo + info = ctx.toolchains["//python/uv:uv_toolchain_type"].uvtoolchaininfo uv = info.binary python = ctx.toolchains[TARGET_TOOLCHAIN_TYPE].py3_runtime.interpreter diff --git a/python/private/toolchain_types.bzl b/python/private/toolchain_types.bzl index 4e3a4a09a1..e908708ad4 100644 --- a/python/private/toolchain_types.bzl +++ b/python/private/toolchain_types.bzl @@ -21,4 +21,4 @@ implementation of the toolchain. TARGET_TOOLCHAIN_TYPE = Label("//python:toolchain_type") EXEC_TOOLS_TOOLCHAIN_TYPE = Label("//python:exec_tools_toolchain_type") PY_CC_TOOLCHAIN_TYPE = Label("//python/cc:toolchain_type") -UV_TOOLCHAIN_TYPE = Label("//python:uv_toolchain_type") +UV_TOOLCHAIN_TYPE = Label("//python/uv:uv_toolchain_type") diff --git a/python/repositories.bzl b/python/repositories.bzl index ba71b79e47..5b3f48f3e8 100644 --- a/python/repositories.bzl +++ b/python/repositories.bzl @@ -726,7 +726,7 @@ def python_register_multi_toolchains( UV_BUILD_TMPL = """\ # Generated by repositories.bzl -load("@rules_python//python:toolchain.bzl", "uv_toolchain") +load("@rules_python//python/uv:toolchain.bzl", "uv_toolchain") uv_toolchain( name = "uv_toolchain", diff --git a/python/uv/BUILD.bazel b/python/uv/BUILD.bazel index 11aeffb9c7..98ad052682 100644 --- a/python/uv/BUILD.bazel +++ b/python/uv/BUILD.bazel @@ -12,7 +12,11 @@ # See the License for the specific language governing permissions and # limitations under the License. -package(default_visibility = ["//visibility:public"]) +load("@bazel_skylib//:bzl_library.bzl", "bzl_library") +load("//python/private/pypi:resolved_toolchain.bzl", "uv_resolved_toolchain") + +# For stardoc to reference the files +exports_files(["defs.bzl"]) toolchain_type( name = "uv_toolchain_type", @@ -26,3 +30,15 @@ uv_resolved_toolchain( tags = ["manual"], visibility = ["//visibility:public"], ) + +bzl_library( + name = "defs", + srcs = ["defs.bzl"], + visibility = ["//visibility:public"], +) + +bzl_library( + name = "toolchain", + srcs = ["toolchain.bzl"], + visibility = ["//visibility:public"], +) diff --git a/python/toolchain.bzl b/python/uv/toolchain.bzl similarity index 100% rename from python/toolchain.bzl rename to python/uv/toolchain.bzl From fd9eebfe1f3a1256e224974e4ee3509bdda42cd3 Mon Sep 17 00:00:00 2001 From: Greg Date: Sat, 29 Jun 2024 22:03:39 +1000 Subject: [PATCH 38/67] Address review comments --- python/BUILD.bazel | 6 ------ 1 file changed, 6 deletions(-) diff --git a/python/BUILD.bazel b/python/BUILD.bazel index 0e424abac0..7a69ac8051 100644 --- a/python/BUILD.bazel +++ b/python/BUILD.bazel @@ -222,12 +222,6 @@ bzl_library( ], ) -bzl_library( - name = "toolchain", - srcs = [":toolchain.bzl"], - visibility = ["//visibility:public"], -) - bzl_library( name = "versions_bzl", srcs = ["versions.bzl"], From a59ab240ef6707451e878e421e4fe6de6134a4b2 Mon Sep 17 00:00:00 2001 From: Greg Date: Sat, 29 Jun 2024 22:54:13 +1000 Subject: [PATCH 39/67] Address review comments --- MODULE.bazel | 2 +- python/private/pypi/BUILD.bazel | 19 ---- python/private/toolchain_types.bzl | 1 - python/repositories.bzl | 80 ---------------- python/uv/BUILD.bazel | 9 +- python/uv/defs.bzl | 2 +- .../uv_extension.bzl => uv/extensions.bzl} | 2 +- python/uv/private/BUILD.bazel | 33 +++++++ .../private}/resolved_toolchain.bzl | 4 +- .../uv.bzl => uv/private/toolchain_types.bzl} | 9 +- .../pypi => uv/private}/toolchains_repo.bzl | 2 +- .../pypi => uv/private}/uv_pip_compile.bzl | 3 +- .../pypi => uv/private}/uv_toolchain.bzl | 0 .../private/versions.bzl} | 0 python/uv/repositories.bzl | 96 +++++++++++++++++++ python/uv/toolchain.bzl | 2 +- 16 files changed, 152 insertions(+), 112 deletions(-) rename python/{private/pypi/uv_extension.bzl => uv/extensions.bzl} (97%) create mode 100644 python/uv/private/BUILD.bazel rename python/{private/pypi => uv/private}/resolved_toolchain.bzl (90%) rename python/{extensions/uv.bzl => uv/private/toolchain_types.bzl} (68%) rename python/{private/pypi => uv/private}/toolchains_repo.bzl (97%) rename python/{private/pypi => uv/private}/uv_pip_compile.bzl (97%) rename python/{private/pypi => uv/private}/uv_toolchain.bzl (100%) rename python/{private/pypi/uv_versions.bzl => uv/private/versions.bzl} (100%) create mode 100644 python/uv/repositories.bzl diff --git a/MODULE.bazel b/MODULE.bazel index d5fd56f3bb..a4b8830b29 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -66,7 +66,7 @@ pip.parse( ) use_repo(pip, "rules_python_publish_deps") -uv = use_extension("//python/extensions:uv.bzl", "uv") +uv = use_extension("//python/uv:extensions.bzl", "uv") uv.toolchain(uv_version = "0.2.13") use_repo(uv, "uv_toolchains") diff --git a/python/private/pypi/BUILD.bazel b/python/private/pypi/BUILD.bazel index 44450b65ec..81d1c6afc8 100644 --- a/python/private/pypi/BUILD.bazel +++ b/python/private/pypi/BUILD.bazel @@ -260,25 +260,6 @@ bzl_library( ], ) -bzl_library( - name = "uv_extension", - srcs = ["uv_extension.bzl"], - visibility = ["//python:__subpackages__"], -) - -bzl_library( - name = "uv_pip_compile", - srcs = ["uv_pip_compile.bzl"], - visibility = ["//visibility:public"], - deps = ["//python/private:toolchain_types_bzl"], -) - -bzl_library( - name = "uv_versions_bzl", - srcs = ["uv_versions.bzl"], - visibility = ["//python:__subpackages__"], -) - bzl_library( name = "whl_library_alias_bzl", srcs = ["whl_library_alias.bzl"], diff --git a/python/private/toolchain_types.bzl b/python/private/toolchain_types.bzl index e908708ad4..ef81bf3bd4 100644 --- a/python/private/toolchain_types.bzl +++ b/python/private/toolchain_types.bzl @@ -21,4 +21,3 @@ implementation of the toolchain. TARGET_TOOLCHAIN_TYPE = Label("//python:toolchain_type") EXEC_TOOLS_TOOLCHAIN_TYPE = Label("//python:exec_tools_toolchain_type") PY_CC_TOOLCHAIN_TYPE = Label("//python/cc:toolchain_type") -UV_TOOLCHAIN_TYPE = Label("//python/uv:uv_toolchain_type") diff --git a/python/repositories.bzl b/python/repositories.bzl index 5b3f48f3e8..d58feefd31 100644 --- a/python/repositories.bzl +++ b/python/repositories.bzl @@ -33,8 +33,6 @@ load( "toolchains_repo", ) load("//python/private/pypi:deps.bzl", "pypi_deps") -load("//python/private/pypi:toolchains_repo.bzl", "UV_PLATFORMS", "uv_toolchains_repo") -load("//python/private/pypi:uv_versions.bzl", "UV_TOOL_VERSIONS") load( ":versions.bzl", "DEFAULT_RELEASE_BASE_URL", @@ -723,81 +721,3 @@ def python_register_multi_toolchains( for python_version in (python_versions + [default_version]) }, ) - -UV_BUILD_TMPL = """\ -# Generated by repositories.bzl -load("@rules_python//python/uv:toolchain.bzl", "uv_toolchain") - -uv_toolchain( - name = "uv_toolchain", - uv = "{binary}", - version = "{version}", -) -""" - -def _uv_repo_impl(repository_ctx): - platform = repository_ctx.attr.platform - uv_version = repository_ctx.attr.uv_version - - suffix = ".zip" if "windows" in platform else ".tar.gz" - filename = "uv-{platform}{suffix}".format( - platform = platform, - suffix = suffix, - ) - url = "https://github.com/astral-sh/uv/releases/download/{version}/{filename}".format( - version = uv_version, - filename = filename, - ) - if filename.endswith(".tar.gz"): - strip_prefix = filename[:-len(".tar.gz")] - else: - strip_prefix = "" - - repository_ctx.download_and_extract( - url = url, - #integrity = UV_TOOL_VERSIONS[repository_ctx.attr.uv_version][repository_ctx.attr.platform], - stripPrefix = strip_prefix, - ) - - binary = "uv.exe" if platform.startswith("windows_") else "uv" - repository_ctx.file( - "BUILD.bazel", - UV_BUILD_TMPL.format( - binary = binary, - version = uv_version, - ), - ) - -uv_repository = repository_rule( - _uv_repo_impl, - doc = "Fetch external tools needed for uv toolchain", - attrs = { - "platform": attr.string(mandatory = True, values = UV_PLATFORMS.keys()), - "uv_version": attr.string(mandatory = True, values = UV_TOOL_VERSIONS.keys()), - }, -) - -# Wrapper macro around everything above, this is the primary API -def uv_register_toolchains(name, register = True, **kwargs): - """Convenience macro for users which does typical setup. - - Users can avoid this macro and do these steps themselves, if they want more control. - Args: - name: base name for all created repos, like "uv0_2_13" - register: whether to call through to native.register_toolchains. - Should be True for WORKSPACE users, but false when used under bzlmod extension - **kwargs: passed to each uv_repositories call - """ - for platform in UV_PLATFORMS.keys(): - uv_repository( - name = name + "_" + platform, - platform = platform, - **kwargs - ) - if register: - native.register_toolchains("@%s_toolchains//:%s_toolchain" % (name, platform)) - - uv_toolchains_repo( - name = name + "_toolchains", - user_repository_name = name, - ) diff --git a/python/uv/BUILD.bazel b/python/uv/BUILD.bazel index 98ad052682..4f9b2cc5ea 100644 --- a/python/uv/BUILD.bazel +++ b/python/uv/BUILD.bazel @@ -13,7 +13,7 @@ # limitations under the License. load("@bazel_skylib//:bzl_library.bzl", "bzl_library") -load("//python/private/pypi:resolved_toolchain.bzl", "uv_resolved_toolchain") +load("//python/uv/private:resolved_toolchain.bzl", "uv_resolved_toolchain") # For stardoc to reference the files exports_files(["defs.bzl"]) @@ -37,6 +37,13 @@ bzl_library( visibility = ["//visibility:public"], ) +bzl_library( + name = "extensions", + srcs = ["extensions.bzl"], + visibility = ["//visibility:public"], + deps = [":repositories"], +) + bzl_library( name = "toolchain", srcs = ["toolchain.bzl"], diff --git a/python/uv/defs.bzl b/python/uv/defs.bzl index afaab7ce46..2e4fd7729f 100644 --- a/python/uv/defs.bzl +++ b/python/uv/defs.bzl @@ -14,6 +14,6 @@ """Experimental toolchain for uv""" -load("//python/private/pypi:uv_pip_compile.bzl", _uv_pip_compile = "uv_pip_compile") +load("//python/uv/private:uv_pip_compile.bzl", _uv_pip_compile = "uv_pip_compile") uv_pip_compile = _uv_pip_compile diff --git a/python/private/pypi/uv_extension.bzl b/python/uv/extensions.bzl similarity index 97% rename from python/private/pypi/uv_extension.bzl rename to python/uv/extensions.bzl index 54faacd78b..22280e3711 100644 --- a/python/private/pypi/uv_extension.bzl +++ b/python/uv/extensions.bzl @@ -14,7 +14,7 @@ "uv module extension" -load("//python:repositories.bzl", "uv_register_toolchains") +load("//python/uv:repositories.bzl", "uv_register_toolchains") _DEFAULT_NAME = "uv" diff --git a/python/uv/private/BUILD.bazel b/python/uv/private/BUILD.bazel new file mode 100644 index 0000000000..d772f35b44 --- /dev/null +++ b/python/uv/private/BUILD.bazel @@ -0,0 +1,33 @@ +# Copyright 2024 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +load("@bazel_skylib//:bzl_library.bzl", "bzl_library") + +bzl_library( + name = "toolchains_repo", + srcs = ["toolchains_repo.bzl"], + visibility = ["//python/uv:__subpackages__"], +) + +bzl_library( + name = "versions", + srcs = ["versions.bzl"], + visibility = ["//python/uv:__subpackages__"], +) + +bzl_library( + name = "resolved_toolchain", + srcs = ["resolved_toolchain.bzl"], + visibility = ["//python/uv:__subpackages__"], +) diff --git a/python/private/pypi/resolved_toolchain.bzl b/python/uv/private/resolved_toolchain.bzl similarity index 90% rename from python/private/pypi/resolved_toolchain.bzl rename to python/uv/private/resolved_toolchain.bzl index dc52081d05..ee5b2a8128 100644 --- a/python/private/pypi/resolved_toolchain.bzl +++ b/python/uv/private/resolved_toolchain.bzl @@ -15,7 +15,7 @@ """This module implements an alias rule to the resolved toolchain. """ -load("//python/private:toolchain_types.bzl", "UV_TOOLCHAIN_TYPE") +load("//python/uv/private:toolchain_types.bzl", "UV_TOOLCHAIN_TYPE") _DOC = """\ Exposes a concrete toolchain which is the result of Bazel resolving the @@ -25,7 +25,7 @@ Workaround for https://github.com/bazelbuild/bazel/issues/14009 # Forward all the providers def _uv_resolved_toolchain_impl(ctx): - toolchain_info = ctx.toolchains["//python:uv_toolchain_type"] + toolchain_info = ctx.toolchains["//python/uv:uv_toolchain_type"] return [ toolchain_info, toolchain_info.defaultinfo, diff --git a/python/extensions/uv.bzl b/python/uv/private/toolchain_types.bzl similarity index 68% rename from python/extensions/uv.bzl rename to python/uv/private/toolchain_types.bzl index 7fbc64d8ad..031e1ab0e0 100644 --- a/python/extensions/uv.bzl +++ b/python/uv/private/toolchain_types.bzl @@ -12,8 +12,11 @@ # See the License for the specific language governing permissions and # limitations under the License. -"uv module extension" +"""Labels to identify toolchain types. -load("//python/private/pypi:uv_extension.bzl", _uv = "uv") +This is a separate file because things needing the toolchain types (in +particular, toolchain() registrations) shouldn't need to load the entire +implementation of the toolchain. +""" -uv = _uv +UV_TOOLCHAIN_TYPE = Label("//python/uv:uv_toolchain_type") diff --git a/python/private/pypi/toolchains_repo.bzl b/python/uv/private/toolchains_repo.bzl similarity index 97% rename from python/private/pypi/toolchains_repo.bzl rename to python/uv/private/toolchains_repo.bzl index 3b28a9f58d..8fc36f2de5 100644 --- a/python/private/pypi/toolchains_repo.bzl +++ b/python/uv/private/toolchains_repo.bzl @@ -67,7 +67,7 @@ def _toolchains_repo_impl(repository_ctx): for index, [platform, meta] in enumerate(UV_PLATFORMS.items()): prefix = render.toolchain_prefix(index, "uv_toolchain", _TOOLCHAIN_INDEX_PAD_LENGTH) build_content += """ -load("@rules_python//python/private:toolchain_types.bzl", "UV_TOOLCHAIN_TYPE") +load("@rules_python//python/uv/private:toolchain_types.bzl", "UV_TOOLCHAIN_TYPE") # Declare a toolchain Bazel will select for running the tool in an action # on the execution platform. diff --git a/python/private/pypi/uv_pip_compile.bzl b/python/uv/private/uv_pip_compile.bzl similarity index 97% rename from python/private/pypi/uv_pip_compile.bzl rename to python/uv/private/uv_pip_compile.bzl index dcf56d7aad..8e43e2815c 100644 --- a/python/private/pypi/uv_pip_compile.bzl +++ b/python/uv/private/uv_pip_compile.bzl @@ -14,7 +14,8 @@ "Rule for locking third-party dependencies with uv." -load("//python/private:toolchain_types.bzl", "TARGET_TOOLCHAIN_TYPE", "UV_TOOLCHAIN_TYPE") +load("//python/private:toolchain_types.bzl", "TARGET_TOOLCHAIN_TYPE") +load("//python/uv/private:toolchain_types.bzl", "UV_TOOLCHAIN_TYPE") script_template = """\ {uv} pip compile \ diff --git a/python/private/pypi/uv_toolchain.bzl b/python/uv/private/uv_toolchain.bzl similarity index 100% rename from python/private/pypi/uv_toolchain.bzl rename to python/uv/private/uv_toolchain.bzl diff --git a/python/private/pypi/uv_versions.bzl b/python/uv/private/versions.bzl similarity index 100% rename from python/private/pypi/uv_versions.bzl rename to python/uv/private/versions.bzl diff --git a/python/uv/repositories.bzl b/python/uv/repositories.bzl new file mode 100644 index 0000000000..9c833cb785 --- /dev/null +++ b/python/uv/repositories.bzl @@ -0,0 +1,96 @@ +# Copyright 2024 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""todo""" + +load("//python/uv/private:toolchains_repo.bzl", "UV_PLATFORMS", "uv_toolchains_repo") +load("//python/uv/private:versions.bzl", "UV_TOOL_VERSIONS") + +UV_BUILD_TMPL = """\ +# Generated by repositories.bzl +load("@rules_python//python/uv:toolchain.bzl", "uv_toolchain") + +uv_toolchain( + name = "uv_toolchain", + uv = "{binary}", + version = "{version}", +) +""" + +def _uv_repo_impl(repository_ctx): + platform = repository_ctx.attr.platform + uv_version = repository_ctx.attr.uv_version + + suffix = ".zip" if "windows" in platform else ".tar.gz" + filename = "uv-{platform}{suffix}".format( + platform = platform, + suffix = suffix, + ) + url = "https://github.com/astral-sh/uv/releases/download/{version}/{filename}".format( + version = uv_version, + filename = filename, + ) + if filename.endswith(".tar.gz"): + strip_prefix = filename[:-len(".tar.gz")] + else: + strip_prefix = "" + + repository_ctx.download_and_extract( + url = url, + #integrity = UV_TOOL_VERSIONS[repository_ctx.attr.uv_version][repository_ctx.attr.platform], + stripPrefix = strip_prefix, + ) + + binary = "uv.exe" if platform.startswith("windows_") else "uv" + repository_ctx.file( + "BUILD.bazel", + UV_BUILD_TMPL.format( + binary = binary, + version = uv_version, + ), + ) + +uv_repository = repository_rule( + _uv_repo_impl, + doc = "Fetch external tools needed for uv toolchain", + attrs = { + "platform": attr.string(mandatory = True, values = UV_PLATFORMS.keys()), + "uv_version": attr.string(mandatory = True, values = UV_TOOL_VERSIONS.keys()), + }, +) + +# Wrapper macro around everything above, this is the primary API +def uv_register_toolchains(name, register = True, **kwargs): + """Convenience macro for users which does typical setup. + + Users can avoid this macro and do these steps themselves, if they want more control. + Args: + name: base name for all created repos, like "uv0_2_13" + register: whether to call through to native.register_toolchains. + Should be True for WORKSPACE users, but false when used under bzlmod extension + **kwargs: passed to each uv_repositories call + """ + for platform in UV_PLATFORMS.keys(): + uv_repository( + name = name + "_" + platform, + platform = platform, + **kwargs + ) + if register: + native.register_toolchains("@%s_toolchains//:%s_toolchain" % (name, platform)) + + uv_toolchains_repo( + name = name + "_toolchains", + user_repository_name = name, + ) diff --git a/python/uv/toolchain.bzl b/python/uv/toolchain.bzl index 2c953d8bdf..2be68d739e 100644 --- a/python/uv/toolchain.bzl +++ b/python/uv/toolchain.bzl @@ -14,7 +14,7 @@ """All toolchains re-exported here""" -load("//python/private/pypi:uv_toolchain.bzl", _UvToolchainInfo = "UvToolchainInfo", _uv_toolchain = "uv_toolchain") +load("//python/uv/private:uv_toolchain.bzl", _UvToolchainInfo = "UvToolchainInfo", _uv_toolchain = "uv_toolchain") UvToolchainInfo = _UvToolchainInfo From 431c79f9978a4f31a88f7c599db7fc391075c74c Mon Sep 17 00:00:00 2001 From: Greg Date: Sat, 29 Jun 2024 22:58:20 +1000 Subject: [PATCH 40/67] Address review comments --- python/uv/BUILD.bazel | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/python/uv/BUILD.bazel b/python/uv/BUILD.bazel index 4f9b2cc5ea..0ef78dccec 100644 --- a/python/uv/BUILD.bazel +++ b/python/uv/BUILD.bazel @@ -44,6 +44,16 @@ bzl_library( deps = [":repositories"], ) +bzl_library( + name = "repositories", + srcs = ["repositories.bzl"], + visibility = ["//visibility:public"], + deps = [ + "//python/uv/private:toolchains_repo", + "//python/uv/private:versions", + ], +) + bzl_library( name = "toolchain", srcs = ["toolchain.bzl"], From e67fdc802874645c1a0b663b4a6d049419c78d32 Mon Sep 17 00:00:00 2001 From: Greg Date: Sat, 29 Jun 2024 23:02:25 +1000 Subject: [PATCH 41/67] Address review comments --- python/private/pypi/BUILD.bazel | 16 ---------------- python/uv/BUILD.bazel | 6 +++--- python/uv/private/resolved_toolchain.bzl | 6 +++--- 3 files changed, 6 insertions(+), 22 deletions(-) diff --git a/python/private/pypi/BUILD.bazel b/python/private/pypi/BUILD.bazel index 81d1c6afc8..0960b6a21d 100644 --- a/python/private/pypi/BUILD.bazel +++ b/python/private/pypi/BUILD.bazel @@ -219,13 +219,6 @@ bzl_library( srcs = ["pip_repository_attrs.bzl"], ) -bzl_library( - name = "resolved_toolchain", - srcs = ["resolved_toolchain.bzl"], - visibility = ["//python:__subpackages__"], - deps = ["//python/private:toolchain_types_bzl"], -) - bzl_library( name = "render_pkg_aliases_bzl", srcs = ["render_pkg_aliases.bzl"], @@ -251,15 +244,6 @@ bzl_library( ], ) -bzl_library( - name = "toolchains_repo", - srcs = ["toolchains_repo.bzl"], - visibility = ["//python:__subpackages__"], - deps = [ - "//python/private:text_util_bzl", - ], -) - bzl_library( name = "whl_library_alias_bzl", srcs = ["whl_library_alias.bzl"], diff --git a/python/uv/BUILD.bazel b/python/uv/BUILD.bazel index 0ef78dccec..d2d8b2c07e 100644 --- a/python/uv/BUILD.bazel +++ b/python/uv/BUILD.bazel @@ -13,7 +13,7 @@ # limitations under the License. load("@bazel_skylib//:bzl_library.bzl", "bzl_library") -load("//python/uv/private:resolved_toolchain.bzl", "uv_resolved_toolchain") +load("//python/uv/private:resolved_toolchain.bzl", "resolved_toolchain") # For stardoc to reference the files exports_files(["defs.bzl"]) @@ -23,8 +23,8 @@ toolchain_type( visibility = ["//visibility:public"], ) -uv_resolved_toolchain( - name = "uv_resolved_toolchain", +resolved_toolchain( + name = "resolved_toolchain", # Marked manual so that `bazel test //...` passes # even if no toolchain is registered. tags = ["manual"], diff --git a/python/uv/private/resolved_toolchain.bzl b/python/uv/private/resolved_toolchain.bzl index ee5b2a8128..00274da3e0 100644 --- a/python/uv/private/resolved_toolchain.bzl +++ b/python/uv/private/resolved_toolchain.bzl @@ -24,7 +24,7 @@ Workaround for https://github.com/bazelbuild/bazel/issues/14009 """ # Forward all the providers -def _uv_resolved_toolchain_impl(ctx): +def _resolved_toolchain_impl(ctx): toolchain_info = ctx.toolchains["//python/uv:uv_toolchain_type"] return [ toolchain_info, @@ -35,8 +35,8 @@ def _uv_resolved_toolchain_impl(ctx): # Copied from java_toolchain_alias # https://cs.opensource.google/bazel/bazel/+/master:tools/jdk/java_toolchain_alias.bzl -uv_resolved_toolchain = rule( - implementation = _uv_resolved_toolchain_impl, +resolved_toolchain = rule( + implementation = _resolved_toolchain_impl, toolchains = [UV_TOOLCHAIN_TYPE], doc = _DOC, ) From d1411959f5c8326e23a4c1587d9d194f434d0606 Mon Sep 17 00:00:00 2001 From: Greg Date: Sat, 29 Jun 2024 23:03:57 +1000 Subject: [PATCH 42/67] Address review comments --- python/extensions/BUILD.bazel | 9 --------- 1 file changed, 9 deletions(-) diff --git a/python/extensions/BUILD.bazel b/python/extensions/BUILD.bazel index 541c90e579..1bc2a71192 100644 --- a/python/extensions/BUILD.bazel +++ b/python/extensions/BUILD.bazel @@ -39,12 +39,3 @@ bzl_library( "//python/private/bzlmod:python_bzl", ], ) - -bzl_library( - name = "uv_bzl", - srcs = ["uv.bzl"], - visibility = ["//:__subpackages__"], - deps = [ - "//python/private/bzlmod:uv_bzl", - ], -) From 3a0441b620a11753d7fa253c1c6dc11cd3bda516 Mon Sep 17 00:00:00 2001 From: Greg Date: Sat, 29 Jun 2024 23:11:17 +1000 Subject: [PATCH 43/67] Address review comments --- python/uv/private/BUILD.bazel | 20 +++++++-- python/uv/private/uv_toolchain.bzl | 66 ------------------------------ python/uv/toolchain.bzl | 53 ++++++++++++++++++++++-- 3 files changed, 65 insertions(+), 74 deletions(-) delete mode 100644 python/uv/private/uv_toolchain.bzl diff --git a/python/uv/private/BUILD.bazel b/python/uv/private/BUILD.bazel index d772f35b44..c759120092 100644 --- a/python/uv/private/BUILD.bazel +++ b/python/uv/private/BUILD.bazel @@ -14,6 +14,18 @@ load("@bazel_skylib//:bzl_library.bzl", "bzl_library") +bzl_library( + name = "resolved_toolchain", + srcs = ["resolved_toolchain.bzl"], + visibility = ["//python/uv:__subpackages__"], +) + +bzl_library( + name = "toolchain_types", + srcs = ["toolchain_types.bzl"], + visibility = ["//python/uv:__subpackages__"], +) + bzl_library( name = "toolchains_repo", srcs = ["toolchains_repo.bzl"], @@ -21,13 +33,13 @@ bzl_library( ) bzl_library( - name = "versions", - srcs = ["versions.bzl"], + name = "uv_pip_compile", + srcs = ["uv_pip_compile.bzl"], visibility = ["//python/uv:__subpackages__"], ) bzl_library( - name = "resolved_toolchain", - srcs = ["resolved_toolchain.bzl"], + name = "versions", + srcs = ["versions.bzl"], visibility = ["//python/uv:__subpackages__"], ) diff --git a/python/uv/private/uv_toolchain.bzl b/python/uv/private/uv_toolchain.bzl deleted file mode 100644 index c4fbc9ef55..0000000000 --- a/python/uv/private/uv_toolchain.bzl +++ /dev/null @@ -1,66 +0,0 @@ -# Copyright 2024 The Bazel Authors. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""This module implements the uv toolchain rule""" - -UvToolchainInfo = provider( - doc = "Information about how to invoke the uv executable.", - fields = { - "binary": "uv binary", - "version": "uv version", - }, -) - -def _uv_toolchain_impl(ctx): - binary = ctx.executable.uv - - templatevariableinfo = platform_common.TemplateVariableInfo({ - "UV_BIN": binary.path, - }) - defaultinfo = DefaultInfo( - files = depset([binary]), - runfiles = ctx.runfiles(files = [binary]), - ) - uvtoolchaininfo = UvToolchainInfo( - binary = binary, - version = ctx.attr.version.removeprefix("v"), - ) - - # Export all the providers inside our ToolchainInfo - # so the resolved_toolchain rule can grab and re-export them. - toolchaininfo = platform_common.ToolchainInfo( - uvtoolchaininfo = uvtoolchaininfo, - templatevariableinfo = templatevariableinfo, - defaultinfo = defaultinfo, - ) - return [ - defaultinfo, - toolchaininfo, - templatevariableinfo, - ] - -uv_toolchain = rule( - implementation = _uv_toolchain_impl, - attrs = { - "uv": attr.label( - doc = "A static uv binary.", - mandatory = False, - allow_single_file = True, - executable = True, - cfg = "target", - ), - "version": attr.string(mandatory = True, doc = "Version of the uv binary."), - }, - doc = "Defines a uv toolchain.", -) diff --git a/python/uv/toolchain.bzl b/python/uv/toolchain.bzl index 2be68d739e..c4fbc9ef55 100644 --- a/python/uv/toolchain.bzl +++ b/python/uv/toolchain.bzl @@ -12,10 +12,55 @@ # See the License for the specific language governing permissions and # limitations under the License. -"""All toolchains re-exported here""" +"""This module implements the uv toolchain rule""" -load("//python/uv/private:uv_toolchain.bzl", _UvToolchainInfo = "UvToolchainInfo", _uv_toolchain = "uv_toolchain") +UvToolchainInfo = provider( + doc = "Information about how to invoke the uv executable.", + fields = { + "binary": "uv binary", + "version": "uv version", + }, +) -UvToolchainInfo = _UvToolchainInfo +def _uv_toolchain_impl(ctx): + binary = ctx.executable.uv -uv_toolchain = _uv_toolchain + templatevariableinfo = platform_common.TemplateVariableInfo({ + "UV_BIN": binary.path, + }) + defaultinfo = DefaultInfo( + files = depset([binary]), + runfiles = ctx.runfiles(files = [binary]), + ) + uvtoolchaininfo = UvToolchainInfo( + binary = binary, + version = ctx.attr.version.removeprefix("v"), + ) + + # Export all the providers inside our ToolchainInfo + # so the resolved_toolchain rule can grab and re-export them. + toolchaininfo = platform_common.ToolchainInfo( + uvtoolchaininfo = uvtoolchaininfo, + templatevariableinfo = templatevariableinfo, + defaultinfo = defaultinfo, + ) + return [ + defaultinfo, + toolchaininfo, + templatevariableinfo, + ] + +uv_toolchain = rule( + implementation = _uv_toolchain_impl, + attrs = { + "uv": attr.label( + doc = "A static uv binary.", + mandatory = False, + allow_single_file = True, + executable = True, + cfg = "target", + ), + "version": attr.string(mandatory = True, doc = "Version of the uv binary."), + }, + doc = "Defines a uv toolchain.", +) From 40ccfb07d287a5fbe43922ecc529eb342d72cf73 Mon Sep 17 00:00:00 2001 From: Greg Date: Sat, 29 Jun 2024 23:23:46 +1000 Subject: [PATCH 44/67] Address review comments --- python/uv/private/uv_pip_compile.bzl | 2 +- python/uv/toolchain.bzl | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/python/uv/private/uv_pip_compile.bzl b/python/uv/private/uv_pip_compile.bzl index 8e43e2815c..1ad9b35334 100644 --- a/python/uv/private/uv_pip_compile.bzl +++ b/python/uv/private/uv_pip_compile.bzl @@ -29,7 +29,7 @@ script_template = """\ """ def _uv_pip_compile(ctx): - info = ctx.toolchains["//python/uv:uv_toolchain_type"].uvtoolchaininfo + info = ctx.toolchains["//python/uv:uv_toolchain_type"].uv_toolchain_info uv = info.binary python = ctx.toolchains[TARGET_TOOLCHAIN_TYPE].py3_runtime.interpreter diff --git a/python/uv/toolchain.bzl b/python/uv/toolchain.bzl index c4fbc9ef55..7d5f4aa2ca 100644 --- a/python/uv/toolchain.bzl +++ b/python/uv/toolchain.bzl @@ -25,29 +25,29 @@ UvToolchainInfo = provider( def _uv_toolchain_impl(ctx): binary = ctx.executable.uv - templatevariableinfo = platform_common.TemplateVariableInfo({ + template_variable_info = platform_common.TemplateVariableInfo({ "UV_BIN": binary.path, }) - defaultinfo = DefaultInfo( + default_info = DefaultInfo( files = depset([binary]), runfiles = ctx.runfiles(files = [binary]), ) - uvtoolchaininfo = UvToolchainInfo( + uv_toolchain_info = UvToolchainInfo( binary = binary, version = ctx.attr.version.removeprefix("v"), ) # Export all the providers inside our ToolchainInfo # so the resolved_toolchain rule can grab and re-export them. - toolchaininfo = platform_common.ToolchainInfo( - uvtoolchaininfo = uvtoolchaininfo, - templatevariableinfo = templatevariableinfo, - defaultinfo = defaultinfo, + toolchain_info = platform_common.ToolchainInfo( + uv_toolchain_info = uv_toolchain_info, + template_variable_info = template_variable_info, + default_info = default_info, ) return [ - defaultinfo, - toolchaininfo, - templatevariableinfo, + default_info, + toolchain_info, + template_variable_info, ] uv_toolchain = rule( From 77501956c232f8d0da8f16815cfa1f26f5198842 Mon Sep 17 00:00:00 2001 From: Greg Date: Sun, 30 Jun 2024 00:30:20 +1000 Subject: [PATCH 45/67] Address review comments --- python/BUILD.bazel | 2 ++ python/uv/BUILD.bazel | 10 ++++++++++ python/uv/private/BUILD.bazel | 6 ++++++ 3 files changed, 18 insertions(+) diff --git a/python/BUILD.bazel b/python/BUILD.bazel index 7a69ac8051..e83b79c914 100644 --- a/python/BUILD.bazel +++ b/python/BUILD.bazel @@ -11,6 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. + """This package contains two sets of rules: 1) the "core" Python rules, which were historically bundled with Bazel and @@ -41,6 +42,7 @@ filegroup( "//python/pip_install:distribution", "//python/private:distribution", "//python/runfiles:distribution", + "//python/uv:distribution", ], visibility = ["//:__pkg__"], ) diff --git a/python/uv/BUILD.bazel b/python/uv/BUILD.bazel index d2d8b2c07e..dc910a7e4e 100644 --- a/python/uv/BUILD.bazel +++ b/python/uv/BUILD.bazel @@ -15,6 +15,16 @@ load("@bazel_skylib//:bzl_library.bzl", "bzl_library") load("//python/uv/private:resolved_toolchain.bzl", "resolved_toolchain") +package(default_visibility = ["//:__subpackages__"]) + +filegroup( + name = "distribution", + srcs = glob(["**"]) + [ + "//python/uv/private:distribution", + ], + visibility = ["//python:__pkg__"], +) + # For stardoc to reference the files exports_files(["defs.bzl"]) diff --git a/python/uv/private/BUILD.bazel b/python/uv/private/BUILD.bazel index c759120092..a2bd1cc23a 100644 --- a/python/uv/private/BUILD.bazel +++ b/python/uv/private/BUILD.bazel @@ -14,6 +14,12 @@ load("@bazel_skylib//:bzl_library.bzl", "bzl_library") +filegroup( + name = "distribution", + srcs = glob(["**"]), + visibility = ["//python/uv:__pkg__"], +) + bzl_library( name = "resolved_toolchain", srcs = ["resolved_toolchain.bzl"], From 834293193a9bcd313c5911e8f470a381e7ef4fd9 Mon Sep 17 00:00:00 2001 From: Greg Date: Sun, 30 Jun 2024 13:27:09 +1000 Subject: [PATCH 46/67] Address review comments --- python/uv/repositories.bzl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/uv/repositories.bzl b/python/uv/repositories.bzl index 9c833cb785..c013212e0e 100644 --- a/python/uv/repositories.bzl +++ b/python/uv/repositories.bzl @@ -48,7 +48,7 @@ def _uv_repo_impl(repository_ctx): repository_ctx.download_and_extract( url = url, - #integrity = UV_TOOL_VERSIONS[repository_ctx.attr.uv_version][repository_ctx.attr.platform], + sha256 = UV_TOOL_VERSIONS[repository_ctx.attr.uv_version][repository_ctx.attr.platform], stripPrefix = strip_prefix, ) From d98ba6579ef3135e836286dcc29736e6bdc7e69b Mon Sep 17 00:00:00 2001 From: Greg Date: Sun, 30 Jun 2024 14:04:36 +1000 Subject: [PATCH 47/67] Address review comments --- python/uv/defs.bzl | 3 +++ python/uv/private/providers.bzl | 23 +++++++++++++++++++++++ python/uv/private/resolved_toolchain.bzl | 8 ++++---- python/uv/private/uv_pip_compile.bzl | 2 +- python/uv/toolchain.bzl | 8 +------- 5 files changed, 32 insertions(+), 12 deletions(-) create mode 100644 python/uv/private/providers.bzl diff --git a/python/uv/defs.bzl b/python/uv/defs.bzl index 2e4fd7729f..79876be059 100644 --- a/python/uv/defs.bzl +++ b/python/uv/defs.bzl @@ -14,6 +14,9 @@ """Experimental toolchain for uv""" +load("//python/uv/private:providers.bzl", _UvToolchainInfo = "UvToolchainInfo") load("//python/uv/private:uv_pip_compile.bzl", _uv_pip_compile = "uv_pip_compile") uv_pip_compile = _uv_pip_compile + +UvToolchainInfo = _UvToolchainInfo diff --git a/python/uv/private/providers.bzl b/python/uv/private/providers.bzl new file mode 100644 index 0000000000..1eadab9ef2 --- /dev/null +++ b/python/uv/private/providers.bzl @@ -0,0 +1,23 @@ +# Copyright 2024 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""This module contains the definitions of all providers.""" + +UvToolchainInfo = provider( + doc = "Information about how to invoke the uv executable.", + fields = { + "binary": "uv binary", + "version": "uv version", + }, +) diff --git a/python/uv/private/resolved_toolchain.bzl b/python/uv/private/resolved_toolchain.bzl index 00274da3e0..6642d5a696 100644 --- a/python/uv/private/resolved_toolchain.bzl +++ b/python/uv/private/resolved_toolchain.bzl @@ -25,12 +25,12 @@ Workaround for https://github.com/bazelbuild/bazel/issues/14009 # Forward all the providers def _resolved_toolchain_impl(ctx): - toolchain_info = ctx.toolchains["//python/uv:uv_toolchain_type"] + toolchain_info = ctx.toolchains[str(UV_TOOLCHAIN_TYPE)] return [ toolchain_info, - toolchain_info.defaultinfo, - toolchain_info.templatevariableinfo, - toolchain_info.uvtoolchaininfo, + toolchain_info.default_info, + toolchain_info.template_variable_info, + toolchain_info.uv_toolchain_info, ] # Copied from java_toolchain_alias diff --git a/python/uv/private/uv_pip_compile.bzl b/python/uv/private/uv_pip_compile.bzl index 1ad9b35334..776fedd50f 100644 --- a/python/uv/private/uv_pip_compile.bzl +++ b/python/uv/private/uv_pip_compile.bzl @@ -29,7 +29,7 @@ script_template = """\ """ def _uv_pip_compile(ctx): - info = ctx.toolchains["//python/uv:uv_toolchain_type"].uv_toolchain_info + info = ctx.toolchains[UV_TOOLCHAIN_TYPE].uv_toolchain_info uv = info.binary python = ctx.toolchains[TARGET_TOOLCHAIN_TYPE].py3_runtime.interpreter diff --git a/python/uv/toolchain.bzl b/python/uv/toolchain.bzl index 7d5f4aa2ca..051ed199d7 100644 --- a/python/uv/toolchain.bzl +++ b/python/uv/toolchain.bzl @@ -14,13 +14,7 @@ """This module implements the uv toolchain rule""" -UvToolchainInfo = provider( - doc = "Information about how to invoke the uv executable.", - fields = { - "binary": "uv binary", - "version": "uv version", - }, -) +load("//python/uv/private:providers.bzl", "UvToolchainInfo") def _uv_toolchain_impl(ctx): binary = ctx.executable.uv From dc0df0ba3dd61a24fa795b59eab22c4abc521aae Mon Sep 17 00:00:00 2001 From: Greg Date: Sun, 30 Jun 2024 14:23:30 +1000 Subject: [PATCH 48/67] Address review comments --- python/uv/extensions.bzl | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/python/uv/extensions.bzl b/python/uv/extensions.bzl index 22280e3711..c94a5bffac 100644 --- a/python/uv/extensions.bzl +++ b/python/uv/extensions.bzl @@ -16,13 +16,17 @@ load("//python/uv:repositories.bzl", "uv_register_toolchains") +_DOC = """\ +A module extension for working with uv. +""" + _DEFAULT_NAME = "uv" uv_toolchain = tag_class(attrs = { "name": attr.string(doc = """\ Base name for generated repositories, allowing more than one uv toolchain to be registered. Overriding the default is only permitted in the root module. -""", default = "uv"), +""", default = _DEFAULT_NAME), "uv_version": attr.string(doc = "Explicit version of uv.", mandatory = True), }) @@ -55,6 +59,7 @@ def _uv_toolchain_extension(module_ctx): ) uv = module_extension( + doc = _DOC, implementation = _uv_toolchain_extension, tag_classes = {"toolchain": uv_toolchain}, ) From 4c8c49033daca9bedd81ee4a83065edf40aef3b0 Mon Sep 17 00:00:00 2001 From: Greg Date: Sun, 30 Jun 2024 20:17:15 +1000 Subject: [PATCH 49/67] Address review comments --- python/uv/private/providers.bzl | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/python/uv/private/providers.bzl b/python/uv/private/providers.bzl index 1eadab9ef2..612260240e 100644 --- a/python/uv/private/providers.bzl +++ b/python/uv/private/providers.bzl @@ -17,7 +17,15 @@ UvToolchainInfo = provider( doc = "Information about how to invoke the uv executable.", fields = { - "binary": "uv binary", - "version": "uv version", + "binary": """ +:type: File + +The uv binary +""", + "version": """ +:type: str + +The uv version +""", }, ) From ae450486e523994c9a998089a06d878230cef872 Mon Sep 17 00:00:00 2001 From: Greg Date: Sun, 30 Jun 2024 20:25:51 +1000 Subject: [PATCH 50/67] Address review comments --- python/uv/toolchain.bzl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/uv/toolchain.bzl b/python/uv/toolchain.bzl index 051ed199d7..35810359dd 100644 --- a/python/uv/toolchain.bzl +++ b/python/uv/toolchain.bzl @@ -28,7 +28,7 @@ def _uv_toolchain_impl(ctx): ) uv_toolchain_info = UvToolchainInfo( binary = binary, - version = ctx.attr.version.removeprefix("v"), + version = ctx.attr.version, ) # Export all the providers inside our ToolchainInfo From 0b0d49ce21a7a08cf4a19252e02203ae88adb2cd Mon Sep 17 00:00:00 2001 From: Greg Date: Sun, 30 Jun 2024 21:57:20 +1000 Subject: [PATCH 51/67] Address review comments --- examples/bzlmod/BUILD.bazel | 11 +++++++++++ python/uv/private/providers.bzl | 6 +++--- python/uv/private/uv_pip_compile.bzl | 2 +- python/uv/toolchain.bzl | 22 +++++++++++----------- 4 files changed, 26 insertions(+), 15 deletions(-) diff --git a/examples/bzlmod/BUILD.bazel b/examples/bzlmod/BUILD.bazel index 4b1d3c7673..caf2fbcfaa 100644 --- a/examples/bzlmod/BUILD.bazel +++ b/examples/bzlmod/BUILD.bazel @@ -27,6 +27,17 @@ uv_pip_compile( dependencies_file = "requirements.in", ) +genrule( + name = "spike_uv_show_template_variables", + srcs = [], + outs = ["spike_uv_show_template_variables.out"], + cmd = """cat < $@ +echo UV_BIN: $(UV_BIN) +EOF""", + executable = True, + toolchains = ["@rules_python//python/uv:resolved_toolchain"], +) + # This stanza calls a rule that generates targets for managing pip dependencies # with pip-compile. compile_pip_requirements_3_10( diff --git a/python/uv/private/providers.bzl b/python/uv/private/providers.bzl index 612260240e..c0b63a56af 100644 --- a/python/uv/private/providers.bzl +++ b/python/uv/private/providers.bzl @@ -17,10 +17,10 @@ UvToolchainInfo = provider( doc = "Information about how to invoke the uv executable.", fields = { - "binary": """ -:type: File + "uv_target": """ +:type: Target -The uv binary +The uv binary `Target` """, "version": """ :type: str diff --git a/python/uv/private/uv_pip_compile.bzl b/python/uv/private/uv_pip_compile.bzl index 776fedd50f..48bfd56159 100644 --- a/python/uv/private/uv_pip_compile.bzl +++ b/python/uv/private/uv_pip_compile.bzl @@ -30,7 +30,7 @@ script_template = """\ def _uv_pip_compile(ctx): info = ctx.toolchains[UV_TOOLCHAIN_TYPE].uv_toolchain_info - uv = info.binary + uv = info.uv_target.files.to_list()[0] python = ctx.toolchains[TARGET_TOOLCHAIN_TYPE].py3_runtime.interpreter dependencies_file = ctx.file.dependencies_file diff --git a/python/uv/toolchain.bzl b/python/uv/toolchain.bzl index 35810359dd..2099b22c4c 100644 --- a/python/uv/toolchain.bzl +++ b/python/uv/toolchain.bzl @@ -17,26 +17,27 @@ load("//python/uv/private:providers.bzl", "UvToolchainInfo") def _uv_toolchain_impl(ctx): - binary = ctx.executable.uv + uv_target = ctx.attr.uv + uv_path = uv_target.files.to_list()[0].path - template_variable_info = platform_common.TemplateVariableInfo({ - "UV_BIN": binary.path, - }) default_info = DefaultInfo( - files = depset([binary]), - runfiles = ctx.runfiles(files = [binary]), + files = uv_target.files, + runfiles = ctx.runfiles(files = uv_target.files.to_list()), ) uv_toolchain_info = UvToolchainInfo( - binary = binary, + uv_target = uv_target, version = ctx.attr.version, ) + template_variable_info = platform_common.TemplateVariableInfo({ + "UV_BIN": uv_path, + }) # Export all the providers inside our ToolchainInfo # so the resolved_toolchain rule can grab and re-export them. toolchain_info = platform_common.ToolchainInfo( - uv_toolchain_info = uv_toolchain_info, - template_variable_info = template_variable_info, default_info = default_info, + template_variable_info = template_variable_info, + uv_toolchain_info = uv_toolchain_info, ) return [ default_info, @@ -49,9 +50,8 @@ uv_toolchain = rule( attrs = { "uv": attr.label( doc = "A static uv binary.", - mandatory = False, + mandatory = True, allow_single_file = True, - executable = True, cfg = "target", ), "version": attr.string(mandatory = True, doc = "Version of the uv binary."), From 93e81c63d8e6e55c08351ca177b9e5b99134ca7f Mon Sep 17 00:00:00 2001 From: Greg Date: Sun, 30 Jun 2024 22:27:40 +1000 Subject: [PATCH 52/67] Address review comments --- python/uv/private/toolchains_repo.bzl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/uv/private/toolchains_repo.bzl b/python/uv/private/toolchains_repo.bzl index 8fc36f2de5..5cccce0e15 100644 --- a/python/uv/private/toolchains_repo.bzl +++ b/python/uv/private/toolchains_repo.bzl @@ -73,7 +73,7 @@ load("@rules_python//python/uv/private:toolchain_types.bzl", "UV_TOOLCHAIN_TYPE" # on the execution platform. toolchain( name = "{prefix}{platform}", - exec_compatible_with = {compatible_with}, + target_compatible_with = {compatible_with}, toolchain = "@{user_repository_name}_{platform}//:uv_toolchain", toolchain_type = UV_TOOLCHAIN_TYPE, ) From 5ecc34521e3bebfd06a2901b9bd038ac4f60bc24 Mon Sep 17 00:00:00 2001 From: Greg Date: Sun, 30 Jun 2024 22:47:37 +1000 Subject: [PATCH 53/67] Address review comments --- python/uv/repositories.bzl | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/python/uv/repositories.bzl b/python/uv/repositories.bzl index c013212e0e..e8f9510267 100644 --- a/python/uv/repositories.bzl +++ b/python/uv/repositories.bzl @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -"""todo""" +"""Create repositories for uv toolchain dependencies""" load("//python/uv/private:toolchains_repo.bzl", "UV_PLATFORMS", "uv_toolchains_repo") load("//python/uv/private:versions.bzl", "UV_TOOL_VERSIONS") @@ -32,7 +32,9 @@ def _uv_repo_impl(repository_ctx): platform = repository_ctx.attr.platform uv_version = repository_ctx.attr.uv_version - suffix = ".zip" if "windows" in platform else ".tar.gz" + is_windows = "windows" in platform + + suffix = ".zip" if is_windows else ".tar.gz" filename = "uv-{platform}{suffix}".format( platform = platform, suffix = suffix, @@ -52,7 +54,7 @@ def _uv_repo_impl(repository_ctx): stripPrefix = strip_prefix, ) - binary = "uv.exe" if platform.startswith("windows_") else "uv" + binary = "uv.exe" if is_windows else "uv" repository_ctx.file( "BUILD.bazel", UV_BUILD_TMPL.format( From 57331183e70f27b90c32e3c675e6b29ef989ede6 Mon Sep 17 00:00:00 2001 From: Greg Date: Sun, 30 Jun 2024 23:00:44 +1000 Subject: [PATCH 54/67] Address review comments --- MODULE.bazel | 6 ------ examples/bzlmod/MODULE.bazel | 7 +++++++ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/MODULE.bazel b/MODULE.bazel index a4b8830b29..735600b98d 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -66,12 +66,6 @@ pip.parse( ) use_repo(pip, "rules_python_publish_deps") -uv = use_extension("//python/uv:extensions.bzl", "uv") -uv.toolchain(uv_version = "0.2.13") -use_repo(uv, "uv_toolchains") - -register_toolchains("@uv_toolchains//:all") - # ===== DEV ONLY DEPS AND SETUP BELOW HERE ===== bazel_dep(name = "stardoc", version = "0.6.2", dev_dependency = True, repo_name = "io_bazel_stardoc") bazel_dep(name = "rules_bazel_integration_test", version = "0.20.0", dev_dependency = True) diff --git a/examples/bzlmod/MODULE.bazel b/examples/bzlmod/MODULE.bazel index e46989e9fd..9457539aea 100644 --- a/examples/bzlmod/MODULE.bazel +++ b/examples/bzlmod/MODULE.bazel @@ -43,6 +43,13 @@ python.toolchain( # rules based on the `python_version` arg values. use_repo(python, "python_3_10", "python_3_9", "python_versions") +# Experimental: uv toolchain +uv = use_extension("@rules_python//python/uv:extensions.bzl", "uv") +uv.toolchain(uv_version = "0.2.13") +use_repo(uv, "uv_toolchains") + +register_toolchains("@uv_toolchains//:all") + # This extension allows a user to create modifications to how rules_python # creates different wheel repositories. Different attributes allow the user # to modify the BUILD file, and copy files. From 8e3cbe9a4a64929988f7bf845d3dbbed1b03fd47 Mon Sep 17 00:00:00 2001 From: Greg Date: Tue, 9 Jul 2024 20:00:11 +1000 Subject: [PATCH 55/67] Bump to uv 0.2.23 --- examples/bzlmod/MODULE.bazel | 2 +- python/uv/private/versions.bzl | 17 +++++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/examples/bzlmod/MODULE.bazel b/examples/bzlmod/MODULE.bazel index 9457539aea..4bca2446f6 100644 --- a/examples/bzlmod/MODULE.bazel +++ b/examples/bzlmod/MODULE.bazel @@ -45,7 +45,7 @@ use_repo(python, "python_3_10", "python_3_9", "python_versions") # Experimental: uv toolchain uv = use_extension("@rules_python//python/uv:extensions.bzl", "uv") -uv.toolchain(uv_version = "0.2.13") +uv.toolchain(uv_version = "0.2.23") use_repo(uv, "uv_toolchains") register_toolchains("@uv_toolchains//:all") diff --git a/python/uv/private/versions.bzl b/python/uv/private/versions.bzl index 9c5a4b7d33..b1787db87f 100644 --- a/python/uv/private/versions.bzl +++ b/python/uv/private/versions.bzl @@ -11,17 +11,18 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. + """Version and integrity information for downloaded artifacts""" # From: https://github.com/astral-sh/uv/releases UV_TOOL_VERSIONS = { - "0.2.13": { - "aarch64-apple-darwin": "f588388d2b13f77e4526e619f618a306b6b026a96975fbfb2c6dd1ded134cb72", - "aarch64-unknown-linux-gnu": "f342442088a56a8a5e4af6781501870bed1b388b37ac2e9deb250cd1d0dc1845", - "powerpc64le-unknown-linux-gnu": "0f38a41264be0ef325f8d438f34ea95c002736b3c092e3276518a2253c4ff923", - "s390x-unknown-linux-gnu": "dc843c32e51ee3fb46381699bffbc4b6040c51083a1dc7d6c597582b84956aa7", - "x86_64-apple-darwin": "6262eba42ebb9035a574b74c5ea253a41353fb4b6b264600e3b05b1a7f4cabc0", - "x86_64-pc-windows-msvc": "898ce45b3767ea97429426a7bd0ec54d070eb9e29ff2b072bdcf288bf6ddc9a1", - "x86_64-unknown-linux-gnu": "3f96048fa1b82eca14d45bbcc86714cd0dee19a73ef9311da6707faa308ec25f", + "0.2.23": { + "aarch64-apple-darwin": "1d41beb151ace9621a0e729d661cfb04d6375bffdaaf0e366d1653576ce3a687", + "aarch64-unknown-linux-gnu": "c35042255239b75d29b9fd4b0845894b91284ed3ff90c2595d0518b4c8902329", + "powerpc64le-unknown-linux-gnu": "ca16c9456d297e623164e3089d76259c6d70ac40c037dd2068accc3bb1b09d5e", + "s390x-unknown-linux-gnu": "55f8c2aa089f382645fce9eed3ee002f2cd48de4696568e7fd63105a02da568c", + "x86_64-apple-darwin": "960d2ae6ec31bcf5da3f66083dedc527712115b97ee43eae903d74a43874fa72", + "x86_64-pc-windows-msvc": "66f80537301c686a801b91468a43dbeb0881bd6d51857078c24f29e5dca8ecf1", + "x86_64-unknown-linux-gnu": "4384db514959beb4de1dcdf7f1f2d5faf664f7180820b0e7a521ef2147e33d1d", }, } From 7dd729ca0964b6c7330f6a9f5b7cedb51559e375 Mon Sep 17 00:00:00 2001 From: Greg Date: Tue, 9 Jul 2024 20:25:16 +1000 Subject: [PATCH 56/67] Address review comments --- python/uv/private/resolved_toolchain.bzl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/uv/private/resolved_toolchain.bzl b/python/uv/private/resolved_toolchain.bzl index 6642d5a696..19be7d1619 100644 --- a/python/uv/private/resolved_toolchain.bzl +++ b/python/uv/private/resolved_toolchain.bzl @@ -25,7 +25,7 @@ Workaround for https://github.com/bazelbuild/bazel/issues/14009 # Forward all the providers def _resolved_toolchain_impl(ctx): - toolchain_info = ctx.toolchains[str(UV_TOOLCHAIN_TYPE)] + toolchain_info = ctx.toolchains[UV_TOOLCHAIN_TYPE] return [ toolchain_info, toolchain_info.default_info, From bb2996cdfc38c2ff256dadcf97190c10a731adec Mon Sep 17 00:00:00 2001 From: Greg Date: Tue, 9 Jul 2024 20:29:27 +1000 Subject: [PATCH 57/67] Address review comments --- python/uv/BUILD.bazel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/uv/BUILD.bazel b/python/uv/BUILD.bazel index dc910a7e4e..dc6b92fdc0 100644 --- a/python/uv/BUILD.bazel +++ b/python/uv/BUILD.bazel @@ -22,7 +22,7 @@ filegroup( srcs = glob(["**"]) + [ "//python/uv/private:distribution", ], - visibility = ["//python:__pkg__"], + visibility = ["//:__subpackages__"], ) # For stardoc to reference the files From c31f6f975e62552cbd146fbec0f28b84e745f08e Mon Sep 17 00:00:00 2001 From: Greg Date: Tue, 9 Jul 2024 20:42:12 +1000 Subject: [PATCH 58/67] Address review comments --- python/uv/private/toolchains_repo.bzl | 37 ++++++++++++++++++--------- 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/python/uv/private/toolchains_repo.bzl b/python/uv/private/toolchains_repo.bzl index 5cccce0e15..995ff80af6 100644 --- a/python/uv/private/toolchains_repo.bzl +++ b/python/uv/private/toolchains_repo.bzl @@ -20,6 +20,18 @@ load("//python/private:text_util.bzl", "render") # targets using any of these toolchains due to the changed repository name. _MAX_NUM_TOOLCHAINS = 9999 _TOOLCHAIN_INDEX_PAD_LENGTH = len(str(_MAX_NUM_TOOLCHAINS)) +_TOOLCHAIN_TEMPLATE = """ +load("@rules_python//python/uv/private:toolchain_types.bzl", "UV_TOOLCHAIN_TYPE") + +# Declare a toolchain Bazel will select for running the tool in an action +# on the execution platform. +toolchain( + name = "{prefix}{platform}", + target_compatible_with = {compatible_with}, + toolchain = "@{user_repository_name}_{platform}//:uv_toolchain", + toolchain_type = UV_TOOLCHAIN_TYPE, +) +""" UV_PLATFORMS = { "aarch64-apple-darwin": struct( @@ -34,6 +46,18 @@ UV_PLATFORMS = { "@platforms//cpu:aarch64", ], ), + "powerpc64le-unknown-linux-gnu": struct( + compatible_with = [ + "@platforms//os:linux", + "@platforms//cpu:ppc", + ], + ), + "s390x-unknown-linux-gnu": struct( + compatible_with = [ + "@platforms//os:linux", + "@platforms//cpu:s390x", + ], + ), "x86_64-apple-darwin": struct( compatible_with = [ "@platforms//os:macos", @@ -66,18 +90,7 @@ def _toolchains_repo_impl(repository_ctx): for index, [platform, meta] in enumerate(UV_PLATFORMS.items()): prefix = render.toolchain_prefix(index, "uv_toolchain", _TOOLCHAIN_INDEX_PAD_LENGTH) - build_content += """ -load("@rules_python//python/uv/private:toolchain_types.bzl", "UV_TOOLCHAIN_TYPE") - -# Declare a toolchain Bazel will select for running the tool in an action -# on the execution platform. -toolchain( - name = "{prefix}{platform}", - target_compatible_with = {compatible_with}, - toolchain = "@{user_repository_name}_{platform}//:uv_toolchain", - toolchain_type = UV_TOOLCHAIN_TYPE, -) -""".format( + build_content += _TOOLCHAIN_TEMPLATE.format( platform = platform, prefix = prefix, user_repository_name = repository_ctx.attr.user_repository_name, From 6f2265554d0e8164a00bed4b983144511afa320b Mon Sep 17 00:00:00 2001 From: Greg Date: Tue, 9 Jul 2024 21:35:46 +1000 Subject: [PATCH 59/67] Add EXPERIMENTAL comments and visibility restrictions --- python/uv/BUILD.bazel | 17 ++++++++++++----- python/uv/defs.bzl | 6 +++++- python/uv/extensions.bzl | 6 +++++- python/uv/repositories.bzl | 6 +++++- python/uv/toolchain.bzl | 6 +++++- 5 files changed, 32 insertions(+), 9 deletions(-) diff --git a/python/uv/BUILD.bazel b/python/uv/BUILD.bazel index dc6b92fdc0..5890b6a15a 100644 --- a/python/uv/BUILD.bazel +++ b/python/uv/BUILD.bazel @@ -12,6 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. +# EXPERIMENTAL: This is experimental and subject may be removed without notice + load("@bazel_skylib//:bzl_library.bzl", "bzl_library") load("//python/uv/private:resolved_toolchain.bzl", "resolved_toolchain") @@ -38,26 +40,30 @@ resolved_toolchain( # Marked manual so that `bazel test //...` passes # even if no toolchain is registered. tags = ["manual"], - visibility = ["//visibility:public"], + # EXPERIMENTAL: Visibility is restricted to allow for changes. + visibility = ["//:__subpackages__"], ) bzl_library( name = "defs", srcs = ["defs.bzl"], - visibility = ["//visibility:public"], + # EXPERIMENTAL: Visibility is restricted to allow for changes. + visibility = ["//:__subpackages__"], ) bzl_library( name = "extensions", srcs = ["extensions.bzl"], - visibility = ["//visibility:public"], + # EXPERIMENTAL: Visibility is restricted to allow for changes. + visibility = ["//:__subpackages__"], deps = [":repositories"], ) bzl_library( name = "repositories", srcs = ["repositories.bzl"], - visibility = ["//visibility:public"], + # EXPERIMENTAL: Visibility is restricted to allow for changes. + visibility = ["//:__subpackages__"], deps = [ "//python/uv/private:toolchains_repo", "//python/uv/private:versions", @@ -67,5 +73,6 @@ bzl_library( bzl_library( name = "toolchain", srcs = ["toolchain.bzl"], - visibility = ["//visibility:public"], + # EXPERIMENTAL: Visibility is restricted to allow for changes. + visibility = ["//:__subpackages__"], ) diff --git a/python/uv/defs.bzl b/python/uv/defs.bzl index 79876be059..fe5d3a0717 100644 --- a/python/uv/defs.bzl +++ b/python/uv/defs.bzl @@ -12,7 +12,11 @@ # See the License for the specific language governing permissions and # limitations under the License. -"""Experimental toolchain for uv""" +""" +EXPERIMENTAL: This is experimental and subject may be removed without notice + +A toolchain for uv +""" load("//python/uv/private:providers.bzl", _UvToolchainInfo = "UvToolchainInfo") load("//python/uv/private:uv_pip_compile.bzl", _uv_pip_compile = "uv_pip_compile") diff --git a/python/uv/extensions.bzl b/python/uv/extensions.bzl index c94a5bffac..029c17cb1f 100644 --- a/python/uv/extensions.bzl +++ b/python/uv/extensions.bzl @@ -12,7 +12,11 @@ # See the License for the specific language governing permissions and # limitations under the License. -"uv module extension" +""" +EXPERIMENTAL: This is experimental and subject may be removed without notice + +A module extension for working with uv. +""" load("//python/uv:repositories.bzl", "uv_register_toolchains") diff --git a/python/uv/repositories.bzl b/python/uv/repositories.bzl index e8f9510267..3ef4c0cbc7 100644 --- a/python/uv/repositories.bzl +++ b/python/uv/repositories.bzl @@ -12,7 +12,11 @@ # See the License for the specific language governing permissions and # limitations under the License. -"""Create repositories for uv toolchain dependencies""" +""" +EXPERIMENTAL: This is experimental and subject may be removed without notice + +Create repositories for uv toolchain dependencies +""" load("//python/uv/private:toolchains_repo.bzl", "UV_PLATFORMS", "uv_toolchains_repo") load("//python/uv/private:versions.bzl", "UV_TOOL_VERSIONS") diff --git a/python/uv/toolchain.bzl b/python/uv/toolchain.bzl index 2099b22c4c..e83aeeb473 100644 --- a/python/uv/toolchain.bzl +++ b/python/uv/toolchain.bzl @@ -12,7 +12,11 @@ # See the License for the specific language governing permissions and # limitations under the License. -"""This module implements the uv toolchain rule""" +""" +EXPERIMENTAL: This is experimental and subject may be removed without notice + +This module implements the uv toolchain rule +""" load("//python/uv/private:providers.bzl", "UvToolchainInfo") From 22ad69fcedef84e83c8be50a50cb3e5ead6aeacf Mon Sep 17 00:00:00 2001 From: Greg Date: Tue, 9 Jul 2024 21:37:54 +1000 Subject: [PATCH 60/67] Add EXPERIMENTAL comments and visibility restrictions --- python/uv/BUILD.bazel | 2 +- python/uv/defs.bzl | 2 +- python/uv/extensions.bzl | 2 +- python/uv/repositories.bzl | 2 +- python/uv/toolchain.bzl | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/python/uv/BUILD.bazel b/python/uv/BUILD.bazel index 5890b6a15a..3dc76b2602 100644 --- a/python/uv/BUILD.bazel +++ b/python/uv/BUILD.bazel @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -# EXPERIMENTAL: This is experimental and subject may be removed without notice +# EXPERIMENTAL: This is experimental and may be removed without notice load("@bazel_skylib//:bzl_library.bzl", "bzl_library") load("//python/uv/private:resolved_toolchain.bzl", "resolved_toolchain") diff --git a/python/uv/defs.bzl b/python/uv/defs.bzl index fe5d3a0717..74a1a2b541 100644 --- a/python/uv/defs.bzl +++ b/python/uv/defs.bzl @@ -13,7 +13,7 @@ # limitations under the License. """ -EXPERIMENTAL: This is experimental and subject may be removed without notice +EXPERIMENTAL: This is experimental and may be removed without notice A toolchain for uv """ diff --git a/python/uv/extensions.bzl b/python/uv/extensions.bzl index 029c17cb1f..c16f25417c 100644 --- a/python/uv/extensions.bzl +++ b/python/uv/extensions.bzl @@ -13,7 +13,7 @@ # limitations under the License. """ -EXPERIMENTAL: This is experimental and subject may be removed without notice +EXPERIMENTAL: This is experimental and may be removed without notice A module extension for working with uv. """ diff --git a/python/uv/repositories.bzl b/python/uv/repositories.bzl index 3ef4c0cbc7..debb5e6453 100644 --- a/python/uv/repositories.bzl +++ b/python/uv/repositories.bzl @@ -13,7 +13,7 @@ # limitations under the License. """ -EXPERIMENTAL: This is experimental and subject may be removed without notice +EXPERIMENTAL: This is experimental and may be removed without notice Create repositories for uv toolchain dependencies """ diff --git a/python/uv/toolchain.bzl b/python/uv/toolchain.bzl index e83aeeb473..d5c76d8eb9 100644 --- a/python/uv/toolchain.bzl +++ b/python/uv/toolchain.bzl @@ -13,7 +13,7 @@ # limitations under the License. """ -EXPERIMENTAL: This is experimental and subject may be removed without notice +EXPERIMENTAL: This is experimental and may be removed without notice This module implements the uv toolchain rule """ From f4c8790c79cef58193811df48bfd63d872b1e8bc Mon Sep 17 00:00:00 2001 From: Greg Date: Tue, 9 Jul 2024 23:05:19 +1000 Subject: [PATCH 61/67] Address review comments --- python/uv/private/providers.bzl | 2 +- python/uv/private/uv_pip_compile.bzl | 2 +- python/uv/toolchain.bzl | 10 +++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/python/uv/private/providers.bzl b/python/uv/private/providers.bzl index c0b63a56af..ac1ef310ea 100644 --- a/python/uv/private/providers.bzl +++ b/python/uv/private/providers.bzl @@ -17,7 +17,7 @@ UvToolchainInfo = provider( doc = "Information about how to invoke the uv executable.", fields = { - "uv_target": """ + "uv": """ :type: Target The uv binary `Target` diff --git a/python/uv/private/uv_pip_compile.bzl b/python/uv/private/uv_pip_compile.bzl index 48bfd56159..f663e5f90e 100644 --- a/python/uv/private/uv_pip_compile.bzl +++ b/python/uv/private/uv_pip_compile.bzl @@ -30,7 +30,7 @@ script_template = """\ def _uv_pip_compile(ctx): info = ctx.toolchains[UV_TOOLCHAIN_TYPE].uv_toolchain_info - uv = info.uv_target.files.to_list()[0] + uv = info.uv.files.to_list()[0] python = ctx.toolchains[TARGET_TOOLCHAIN_TYPE].py3_runtime.interpreter dependencies_file = ctx.file.dependencies_file diff --git a/python/uv/toolchain.bzl b/python/uv/toolchain.bzl index d5c76d8eb9..d1ec3a9a63 100644 --- a/python/uv/toolchain.bzl +++ b/python/uv/toolchain.bzl @@ -21,15 +21,15 @@ This module implements the uv toolchain rule load("//python/uv/private:providers.bzl", "UvToolchainInfo") def _uv_toolchain_impl(ctx): - uv_target = ctx.attr.uv - uv_path = uv_target.files.to_list()[0].path + uv = ctx.attr.uv + uv_path = uv.files.to_list()[0].path default_info = DefaultInfo( - files = uv_target.files, - runfiles = ctx.runfiles(files = uv_target.files.to_list()), + files = uv.files, + runfiles = ctx.attr.uv[DefaultInfo].default_runfiles, ) uv_toolchain_info = UvToolchainInfo( - uv_target = uv_target, + uv = uv, version = ctx.attr.version, ) template_variable_info = platform_common.TemplateVariableInfo({ From 02c537db2a8f3c8bbd5c350bd14f17ccdecf6cd8 Mon Sep 17 00:00:00 2001 From: Greg Date: Tue, 9 Jul 2024 23:11:30 +1000 Subject: [PATCH 62/67] Address review comments --- python/uv/BUILD.bazel | 2 +- python/uv/toolchain.bzl | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/python/uv/BUILD.bazel b/python/uv/BUILD.bazel index 3dc76b2602..5890b6a15a 100644 --- a/python/uv/BUILD.bazel +++ b/python/uv/BUILD.bazel @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -# EXPERIMENTAL: This is experimental and may be removed without notice +# EXPERIMENTAL: This is experimental and subject may be removed without notice load("@bazel_skylib//:bzl_library.bzl", "bzl_library") load("//python/uv/private:resolved_toolchain.bzl", "resolved_toolchain") diff --git a/python/uv/toolchain.bzl b/python/uv/toolchain.bzl index d1ec3a9a63..82e7efd8c1 100644 --- a/python/uv/toolchain.bzl +++ b/python/uv/toolchain.bzl @@ -22,18 +22,17 @@ load("//python/uv/private:providers.bzl", "UvToolchainInfo") def _uv_toolchain_impl(ctx): uv = ctx.attr.uv - uv_path = uv.files.to_list()[0].path default_info = DefaultInfo( files = uv.files, - runfiles = ctx.attr.uv[DefaultInfo].default_runfiles, + runfiles = uv[DefaultInfo].default_runfiles, ) uv_toolchain_info = UvToolchainInfo( uv = uv, version = ctx.attr.version, ) template_variable_info = platform_common.TemplateVariableInfo({ - "UV_BIN": uv_path, + "UV_BIN": uv[DefaultInfo].files_to_run.executable.path, }) # Export all the providers inside our ToolchainInfo @@ -56,6 +55,7 @@ uv_toolchain = rule( doc = "A static uv binary.", mandatory = True, allow_single_file = True, + executable = True, cfg = "target", ), "version": attr.string(mandatory = True, doc = "Version of the uv binary."), From dfa24fe7f3bbf1725a99f19b56dd7918e73761c1 Mon Sep 17 00:00:00 2001 From: Greg Date: Wed, 10 Jul 2024 00:54:01 +1000 Subject: [PATCH 63/67] Address review comments --- examples/bzlmod/BUILD.bazel | 17 ---- examples/bzlmod/MODULE.bazel | 2 +- python/uv/BUILD.bazel | 2 +- python/uv/defs.bzl | 3 - python/uv/private/resolved_toolchain.bzl | 16 +++- python/uv/private/uv_pip_compile.bzl | 104 ----------------------- 6 files changed, 17 insertions(+), 127 deletions(-) delete mode 100644 python/uv/private/uv_pip_compile.bzl diff --git a/examples/bzlmod/BUILD.bazel b/examples/bzlmod/BUILD.bazel index caf2fbcfaa..bb16f98a6f 100644 --- a/examples/bzlmod/BUILD.bazel +++ b/examples/bzlmod/BUILD.bazel @@ -11,7 +11,6 @@ load("@python_3_9//:defs.bzl", py_test_with_transition = "py_test") load("@python_versions//3.10:defs.bzl", compile_pip_requirements_3_10 = "compile_pip_requirements") load("@python_versions//3.9:defs.bzl", compile_pip_requirements_3_9 = "compile_pip_requirements") load("@rules_python//python:defs.bzl", "py_binary", "py_library", "py_test") -load("@rules_python//python/uv:defs.bzl", "uv_pip_compile") # This stanza calls a rule that generates targets for managing pip dependencies # with pip-compile. @@ -22,22 +21,6 @@ compile_pip_requirements_3_9( requirements_windows = "requirements_windows_3_9.txt", ) -uv_pip_compile( - name = "spike_uv_pip_compile", - dependencies_file = "requirements.in", -) - -genrule( - name = "spike_uv_show_template_variables", - srcs = [], - outs = ["spike_uv_show_template_variables.out"], - cmd = """cat < $@ -echo UV_BIN: $(UV_BIN) -EOF""", - executable = True, - toolchains = ["@rules_python//python/uv:resolved_toolchain"], -) - # This stanza calls a rule that generates targets for managing pip dependencies # with pip-compile. compile_pip_requirements_3_10( diff --git a/examples/bzlmod/MODULE.bazel b/examples/bzlmod/MODULE.bazel index 4bca2446f6..3da17a6eb2 100644 --- a/examples/bzlmod/MODULE.bazel +++ b/examples/bzlmod/MODULE.bazel @@ -43,7 +43,7 @@ python.toolchain( # rules based on the `python_version` arg values. use_repo(python, "python_3_10", "python_3_9", "python_versions") -# Experimental: uv toolchain +# EXPERIMENTAL: This is experimental and may be removed without notice uv = use_extension("@rules_python//python/uv:extensions.bzl", "uv") uv.toolchain(uv_version = "0.2.23") use_repo(uv, "uv_toolchains") diff --git a/python/uv/BUILD.bazel b/python/uv/BUILD.bazel index 5890b6a15a..1910b826d5 100644 --- a/python/uv/BUILD.bazel +++ b/python/uv/BUILD.bazel @@ -41,7 +41,7 @@ resolved_toolchain( # even if no toolchain is registered. tags = ["manual"], # EXPERIMENTAL: Visibility is restricted to allow for changes. - visibility = ["//:__subpackages__"], + visibility = ["@rules_python//examples:__subpackages__"], ) bzl_library( diff --git a/python/uv/defs.bzl b/python/uv/defs.bzl index 74a1a2b541..20b426a355 100644 --- a/python/uv/defs.bzl +++ b/python/uv/defs.bzl @@ -19,8 +19,5 @@ A toolchain for uv """ load("//python/uv/private:providers.bzl", _UvToolchainInfo = "UvToolchainInfo") -load("//python/uv/private:uv_pip_compile.bzl", _uv_pip_compile = "uv_pip_compile") - -uv_pip_compile = _uv_pip_compile UvToolchainInfo = _UvToolchainInfo diff --git a/python/uv/private/resolved_toolchain.bzl b/python/uv/private/resolved_toolchain.bzl index 19be7d1619..d95cd42d35 100644 --- a/python/uv/private/resolved_toolchain.bzl +++ b/python/uv/private/resolved_toolchain.bzl @@ -26,9 +26,22 @@ Workaround for https://github.com/bazelbuild/bazel/issues/14009 # Forward all the providers def _resolved_toolchain_impl(ctx): toolchain_info = ctx.toolchains[UV_TOOLCHAIN_TYPE] + + # Bazel requires executable rules to create the executable themselves, + # so we create a symlink in this rule so that it appears this rule created its executable. + original_uv_executable = toolchain_info.uv_toolchain_info.uv[DefaultInfo].files_to_run.executable + symlink_uv_executable = ctx.actions.declare_file("uv_symlink_{}".format(original_uv_executable.basename)) + ctx.actions.symlink(output = symlink_uv_executable, target_file = original_uv_executable) + + new_default_info = DefaultInfo( + files = depset([symlink_uv_executable]), + runfiles = toolchain_info.default_info.default_runfiles, + executable = symlink_uv_executable, + ) + return [ toolchain_info, - toolchain_info.default_info, + new_default_info, toolchain_info.template_variable_info, toolchain_info.uv_toolchain_info, ] @@ -39,4 +52,5 @@ resolved_toolchain = rule( implementation = _resolved_toolchain_impl, toolchains = [UV_TOOLCHAIN_TYPE], doc = _DOC, + executable = True, ) diff --git a/python/uv/private/uv_pip_compile.bzl b/python/uv/private/uv_pip_compile.bzl deleted file mode 100644 index f663e5f90e..0000000000 --- a/python/uv/private/uv_pip_compile.bzl +++ /dev/null @@ -1,104 +0,0 @@ -# Copyright 2024 The Bazel Authors. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"Rule for locking third-party dependencies with uv." - -load("//python/private:toolchain_types.bzl", "TARGET_TOOLCHAIN_TYPE") -load("//python/uv/private:toolchain_types.bzl", "UV_TOOLCHAIN_TYPE") - -script_template = """\ -{uv} pip compile \ ---python {python} \ ---python-platform windows \ ---python-version 3.9 \ ---no-strip-extras \ ---generate-hashes \ ---output-file - \ -{dependencies_file} -""" - -def _uv_pip_compile(ctx): - info = ctx.toolchains[UV_TOOLCHAIN_TYPE].uv_toolchain_info - uv = info.uv.files.to_list()[0] - - python = ctx.toolchains[TARGET_TOOLCHAIN_TYPE].py3_runtime.interpreter - dependencies_file = ctx.file.dependencies_file - - # Option 1: Build action option. - # Not really appropriate, but it executes. - - # args = ctx.actions.args() - # args.add("pip") - # args.add("compile") - - # uv will use this python for operations where it needs to execute python code. See: UV_PYTHON and https://github.com/astral-sh/uv?tab=readme-ov-file#installing-into-arbitrary-python-environments - # args.add("--python", python) - # args.add("--python-platform", "windows") - # args.add("--python-version", "3.9") - # args.add("--no-strip-extras") - # args.add("--generate-hashes") - #requirements_out = ctx.actions.declare_file(ctx.label.name + ".requirements.out") - # args.add("--output-file", requirements_out) - # args.add(dependencies_file) - - # ctx.actions.run( - # executable = uv, - # arguments = [args], - # inputs = [dependencies_file], - # outputs = [requirements_out], - # tools = [python], - # ) - - # Option 2: Run action option. - # Works to exec uv --version, but will need rest of arguments plumbed through. - - # executable = ctx.actions.declare_file("%s-uv" % ctx.label.name) - # ctx.actions.symlink( - # is_executable = True, - # output = executable, - # target_file = uv, - # ) - - # Option 3: Run action option. - # Works to exec uv with some (but not all) arguments plumbed through. Output to a directory of the resolved output needs to be done. - executable = ctx.actions.declare_file("{name}-{uv_name}".format( - name = ctx.label.name, - uv_name = uv.basename, - )) - script_content = script_template.format( - uv = uv.path, - python = python.path, - dependencies_file = dependencies_file.path, - ) - ctx.actions.write(executable, script_content, is_executable = True) - - return [DefaultInfo( - files = depset([executable]), - executable = executable, - runfiles = ctx.runfiles([uv, dependencies_file, python]), - )] - -uv_pip_compile = rule( - implementation = _uv_pip_compile, - attrs = { - "constraints_file": attr.label(allow_single_file = True), - "dependencies_file": attr.label(allow_single_file = True), - "overrides_file": attr.label(allow_single_file = True), - }, - toolchains = [ - TARGET_TOOLCHAIN_TYPE, - UV_TOOLCHAIN_TYPE, - ], - executable = True, -) From 5c11f759a0b5e97c64256914c9d497c34359e684 Mon Sep 17 00:00:00 2001 From: Greg Date: Wed, 10 Jul 2024 01:00:55 +1000 Subject: [PATCH 64/67] Address review comments --- python/uv/BUILD.bazel | 2 +- python/uv/private/BUILD.bazel | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/python/uv/BUILD.bazel b/python/uv/BUILD.bazel index 1910b826d5..907bd29595 100644 --- a/python/uv/BUILD.bazel +++ b/python/uv/BUILD.bazel @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -# EXPERIMENTAL: This is experimental and subject may be removed without notice +# EXPERIMENTAL: This is experimental and may be removed without notice load("@bazel_skylib//:bzl_library.bzl", "bzl_library") load("//python/uv/private:resolved_toolchain.bzl", "resolved_toolchain") diff --git a/python/uv/private/BUILD.bazel b/python/uv/private/BUILD.bazel index a2bd1cc23a..081f95fade 100644 --- a/python/uv/private/BUILD.bazel +++ b/python/uv/private/BUILD.bazel @@ -38,12 +38,6 @@ bzl_library( visibility = ["//python/uv:__subpackages__"], ) -bzl_library( - name = "uv_pip_compile", - srcs = ["uv_pip_compile.bzl"], - visibility = ["//python/uv:__subpackages__"], -) - bzl_library( name = "versions", srcs = ["versions.bzl"], From 93829ca451ddc7b2b96e84e48a5d829732404ff8 Mon Sep 17 00:00:00 2001 From: Greg Date: Wed, 10 Jul 2024 13:23:40 +1000 Subject: [PATCH 65/67] Address review comments --- python/uv/BUILD.bazel | 6 +++--- python/uv/private/BUILD.bazel | 4 ++-- .../{resolved_toolchain.bzl => current_toolchain.bzl} | 6 +++--- python/uv/toolchain.bzl | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) rename python/uv/private/{resolved_toolchain.bzl => current_toolchain.bzl} (94%) diff --git a/python/uv/BUILD.bazel b/python/uv/BUILD.bazel index 907bd29595..3961c908ac 100644 --- a/python/uv/BUILD.bazel +++ b/python/uv/BUILD.bazel @@ -15,7 +15,7 @@ # EXPERIMENTAL: This is experimental and may be removed without notice load("@bazel_skylib//:bzl_library.bzl", "bzl_library") -load("//python/uv/private:resolved_toolchain.bzl", "resolved_toolchain") +load("//python/uv/private:current_toolchain.bzl", "current_toolchain") package(default_visibility = ["//:__subpackages__"]) @@ -35,8 +35,8 @@ toolchain_type( visibility = ["//visibility:public"], ) -resolved_toolchain( - name = "resolved_toolchain", +current_toolchain( + name = "current_toolchain", # Marked manual so that `bazel test //...` passes # even if no toolchain is registered. tags = ["manual"], diff --git a/python/uv/private/BUILD.bazel b/python/uv/private/BUILD.bazel index 081f95fade..56dab35757 100644 --- a/python/uv/private/BUILD.bazel +++ b/python/uv/private/BUILD.bazel @@ -21,8 +21,8 @@ filegroup( ) bzl_library( - name = "resolved_toolchain", - srcs = ["resolved_toolchain.bzl"], + name = "current_toolchain", + srcs = ["current_toolchain.bzl"], visibility = ["//python/uv:__subpackages__"], ) diff --git a/python/uv/private/resolved_toolchain.bzl b/python/uv/private/current_toolchain.bzl similarity index 94% rename from python/uv/private/resolved_toolchain.bzl rename to python/uv/private/current_toolchain.bzl index d95cd42d35..cd4a5926d2 100644 --- a/python/uv/private/resolved_toolchain.bzl +++ b/python/uv/private/current_toolchain.bzl @@ -24,7 +24,7 @@ Workaround for https://github.com/bazelbuild/bazel/issues/14009 """ # Forward all the providers -def _resolved_toolchain_impl(ctx): +def _current_toolchain_impl(ctx): toolchain_info = ctx.toolchains[UV_TOOLCHAIN_TYPE] # Bazel requires executable rules to create the executable themselves, @@ -48,8 +48,8 @@ def _resolved_toolchain_impl(ctx): # Copied from java_toolchain_alias # https://cs.opensource.google/bazel/bazel/+/master:tools/jdk/java_toolchain_alias.bzl -resolved_toolchain = rule( - implementation = _resolved_toolchain_impl, +current_toolchain = rule( + implementation = _current_toolchain_impl, toolchains = [UV_TOOLCHAIN_TYPE], doc = _DOC, executable = True, diff --git a/python/uv/toolchain.bzl b/python/uv/toolchain.bzl index 82e7efd8c1..dbfda0b70c 100644 --- a/python/uv/toolchain.bzl +++ b/python/uv/toolchain.bzl @@ -36,7 +36,7 @@ def _uv_toolchain_impl(ctx): }) # Export all the providers inside our ToolchainInfo - # so the resolved_toolchain rule can grab and re-export them. + # so the current_toolchain rule can grab and re-export them. toolchain_info = platform_common.ToolchainInfo( default_info = default_info, template_variable_info = template_variable_info, From a0f3d5c43e1c2d2d67bb2486ef1f13575e1f2ab4 Mon Sep 17 00:00:00 2001 From: Greg Date: Wed, 10 Jul 2024 23:19:23 +1000 Subject: [PATCH 66/67] Address review comments --- python/uv/extensions.bzl | 41 ++++-------- python/uv/private/toolchains_repo.bzl | 91 +++++---------------------- python/uv/private/versions.bzl | 73 ++++++++++++++++++--- python/uv/repositories.bzl | 55 ++++++++++------ 4 files changed, 130 insertions(+), 130 deletions(-) diff --git a/python/uv/extensions.bzl b/python/uv/extensions.bzl index c16f25417c..82560eb17c 100644 --- a/python/uv/extensions.bzl +++ b/python/uv/extensions.bzl @@ -24,43 +24,24 @@ _DOC = """\ A module extension for working with uv. """ -_DEFAULT_NAME = "uv" - uv_toolchain = tag_class(attrs = { - "name": attr.string(doc = """\ -Base name for generated repositories, allowing more than one uv toolchain to be registered. -Overriding the default is only permitted in the root module. -""", default = _DEFAULT_NAME), "uv_version": attr.string(doc = "Explicit version of uv.", mandatory = True), }) def _uv_toolchain_extension(module_ctx): - registrations = {} for mod in module_ctx.modules: for toolchain in mod.tags.toolchain: - if toolchain.name != _DEFAULT_NAME and not mod.is_root: - fail("""\ - Only the root module may override the default name for the uv toolchain. - This prevents conflicting registrations in the global namespace of external repos. - """) - if toolchain.name not in registrations.keys(): - registrations[toolchain.name] = [] - registrations[toolchain.name].append(toolchain.uv_version) - for name, versions in registrations.items(): - if len(versions) > 1: - # TODO: should be semver-aware, using MVS - selected = sorted(versions, reverse = True)[0] - - # buildifier: disable=print - print("NOTE: uv toolchain {} has multiple versions {}, selected {}".format(name, versions, selected)) - else: - selected = versions[0] - - uv_register_toolchains( - name = name, - uv_version = selected, - register = False, - ) + if not mod.is_root: + fail( + "Only the root module may configure the uv toolchain.", + "This prevents conflicting registrations with any other modules.", + "NOTE: We may wish to enforce a policy where toolchain configuration is only allowed in the root module, or in rules_python. See https://github.com/bazelbuild/bazel/discussions/22024", + ) + + uv_register_toolchains( + uv_version = toolchain.uv_version, + register_toolchains = False, + ) uv = module_extension( doc = _DOC, diff --git a/python/uv/private/toolchains_repo.bzl b/python/uv/private/toolchains_repo.bzl index 995ff80af6..12ae134c94 100644 --- a/python/uv/private/toolchains_repo.bzl +++ b/python/uv/private/toolchains_repo.bzl @@ -14,96 +14,37 @@ "Creates a repository to hold toolchains" -load("//python/private:text_util.bzl", "render") - -# This limit can be increased essentially arbitrarily, but doing so will cause a rebuild of all -# targets using any of these toolchains due to the changed repository name. -_MAX_NUM_TOOLCHAINS = 9999 -_TOOLCHAIN_INDEX_PAD_LENGTH = len(str(_MAX_NUM_TOOLCHAINS)) _TOOLCHAIN_TEMPLATE = """ -load("@rules_python//python/uv/private:toolchain_types.bzl", "UV_TOOLCHAIN_TYPE") - -# Declare a toolchain Bazel will select for running the tool in an action -# on the execution platform. toolchain( - name = "{prefix}{platform}", + name = "{name}", target_compatible_with = {compatible_with}, - toolchain = "@{user_repository_name}_{platform}//:uv_toolchain", - toolchain_type = UV_TOOLCHAIN_TYPE, + toolchain = "{toolchain_label}", + toolchain_type = "{toolchain_type}", ) """ -UV_PLATFORMS = { - "aarch64-apple-darwin": struct( - compatible_with = [ - "@platforms//os:macos", - "@platforms//cpu:aarch64", - ], - ), - "aarch64-unknown-linux-gnu": struct( - compatible_with = [ - "@platforms//os:linux", - "@platforms//cpu:aarch64", - ], - ), - "powerpc64le-unknown-linux-gnu": struct( - compatible_with = [ - "@platforms//os:linux", - "@platforms//cpu:ppc", - ], - ), - "s390x-unknown-linux-gnu": struct( - compatible_with = [ - "@platforms//os:linux", - "@platforms//cpu:s390x", - ], - ), - "x86_64-apple-darwin": struct( - compatible_with = [ - "@platforms//os:macos", - "@platforms//cpu:x86_64", - ], - ), - "x86_64-pc-windows-msvc": struct( - compatible_with = [ - "@platforms//os:windows", - "@platforms//cpu:x86_64", - ], - ), - "x86_64-unknown-linux-gnu": struct( - compatible_with = [ - "@platforms//os:linux", - "@platforms//cpu:x86_64", - ], - ), -} - def _toolchains_repo_impl(repository_ctx): - build_content = """\ -# Generated by toolchains_repo.bzl -# -# These can be registered in the workspace file or passed to --extra_toolchains flag. -# By default all these toolchains are registered by the uv_register_toolchains macro -# so you don't normally need to interact with these targets. - -""" + build_content = "" + for toolchain_name in repository_ctx.attr.toolchain_names: + toolchain_label = repository_ctx.attr.toolchain_labels[toolchain_name] + toolchain_compatible_with = repository_ctx.attr.toolchain_compatible_with[toolchain_name] - for index, [platform, meta] in enumerate(UV_PLATFORMS.items()): - prefix = render.toolchain_prefix(index, "uv_toolchain", _TOOLCHAIN_INDEX_PAD_LENGTH) build_content += _TOOLCHAIN_TEMPLATE.format( - platform = platform, - prefix = prefix, - user_repository_name = repository_ctx.attr.user_repository_name, - compatible_with = meta.compatible_with, + name = toolchain_name, + toolchain_type = repository_ctx.attr.toolchain_type, + toolchain_label = toolchain_label, + compatible_with = json.encode(toolchain_compatible_with), ) repository_ctx.file("BUILD.bazel", build_content) uv_toolchains_repo = repository_rule( _toolchains_repo_impl, - doc = """Creates a repository with toolchain definitions for all known platforms - which can be registered or selected.""", + doc = "Generates a toolchain hub repository", attrs = { - "user_repository_name": attr.string(doc = "what the user chose for the base name"), + "toolchain_compatible_with": attr.string_list_dict(doc = "A list of platform constraints for this toolchain, keyed by toolchain name.", mandatory = True), + "toolchain_labels": attr.string_dict(doc = "The name of the toolchain implementation target, keyed by toolchain name.", mandatory = True), + "toolchain_names": attr.string_list(doc = "List of toolchain names", mandatory = True), + "toolchain_type": attr.string(doc = "The toolchain type of the toolchains", mandatory = True), }, ) diff --git a/python/uv/private/versions.bzl b/python/uv/private/versions.bzl index b1787db87f..ab91a16e01 100644 --- a/python/uv/private/versions.bzl +++ b/python/uv/private/versions.bzl @@ -14,15 +14,74 @@ """Version and integrity information for downloaded artifacts""" +UV_PLATFORMS = { + "aarch64-apple-darwin": struct( + compatible_with = [ + "@platforms//os:macos", + "@platforms//cpu:aarch64", + ], + ), + "aarch64-unknown-linux-gnu": struct( + compatible_with = [ + "@platforms//os:linux", + "@platforms//cpu:aarch64", + ], + ), + "powerpc64le-unknown-linux-gnu": struct( + compatible_with = [ + "@platforms//os:linux", + "@platforms//cpu:ppc", + ], + ), + "s390x-unknown-linux-gnu": struct( + compatible_with = [ + "@platforms//os:linux", + "@platforms//cpu:s390x", + ], + ), + "x86_64-apple-darwin": struct( + compatible_with = [ + "@platforms//os:macos", + "@platforms//cpu:x86_64", + ], + ), + "x86_64-pc-windows-msvc": struct( + compatible_with = [ + "@platforms//os:windows", + "@platforms//cpu:x86_64", + ], + ), + "x86_64-unknown-linux-gnu": struct( + compatible_with = [ + "@platforms//os:linux", + "@platforms//cpu:x86_64", + ], + ), +} + # From: https://github.com/astral-sh/uv/releases UV_TOOL_VERSIONS = { "0.2.23": { - "aarch64-apple-darwin": "1d41beb151ace9621a0e729d661cfb04d6375bffdaaf0e366d1653576ce3a687", - "aarch64-unknown-linux-gnu": "c35042255239b75d29b9fd4b0845894b91284ed3ff90c2595d0518b4c8902329", - "powerpc64le-unknown-linux-gnu": "ca16c9456d297e623164e3089d76259c6d70ac40c037dd2068accc3bb1b09d5e", - "s390x-unknown-linux-gnu": "55f8c2aa089f382645fce9eed3ee002f2cd48de4696568e7fd63105a02da568c", - "x86_64-apple-darwin": "960d2ae6ec31bcf5da3f66083dedc527712115b97ee43eae903d74a43874fa72", - "x86_64-pc-windows-msvc": "66f80537301c686a801b91468a43dbeb0881bd6d51857078c24f29e5dca8ecf1", - "x86_64-unknown-linux-gnu": "4384db514959beb4de1dcdf7f1f2d5faf664f7180820b0e7a521ef2147e33d1d", + "aarch64-apple-darwin": struct( + sha256 = "1d41beb151ace9621a0e729d661cfb04d6375bffdaaf0e366d1653576ce3a687", + ), + "aarch64-unknown-linux-gnu": struct( + sha256 = "c35042255239b75d29b9fd4b0845894b91284ed3ff90c2595d0518b4c8902329", + ), + "powerpc64le-unknown-linux-gnu": struct( + sha256 = "ca16c9456d297e623164e3089d76259c6d70ac40c037dd2068accc3bb1b09d5e", + ), + "s390x-unknown-linux-gnu": struct( + sha256 = "55f8c2aa089f382645fce9eed3ee002f2cd48de4696568e7fd63105a02da568c", + ), + "x86_64-apple-darwin": struct( + sha256 = "960d2ae6ec31bcf5da3f66083dedc527712115b97ee43eae903d74a43874fa72", + ), + "x86_64-pc-windows-msvc": struct( + sha256 = "66f80537301c686a801b91468a43dbeb0881bd6d51857078c24f29e5dca8ecf1", + ), + "x86_64-unknown-linux-gnu": struct( + sha256 = "4384db514959beb4de1dcdf7f1f2d5faf664f7180820b0e7a521ef2147e33d1d", + ), }, } diff --git a/python/uv/repositories.bzl b/python/uv/repositories.bzl index debb5e6453..635746ce30 100644 --- a/python/uv/repositories.bzl +++ b/python/uv/repositories.bzl @@ -18,8 +18,10 @@ EXPERIMENTAL: This is experimental and may be removed without notice Create repositories for uv toolchain dependencies """ -load("//python/uv/private:toolchains_repo.bzl", "UV_PLATFORMS", "uv_toolchains_repo") -load("//python/uv/private:versions.bzl", "UV_TOOL_VERSIONS") +load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe") +load("//python/uv/private:toolchain_types.bzl", "UV_TOOLCHAIN_TYPE") +load("//python/uv/private:toolchains_repo.bzl", "uv_toolchains_repo") +load("//python/uv/private:versions.bzl", "UV_PLATFORMS", "UV_TOOL_VERSIONS") UV_BUILD_TMPL = """\ # Generated by repositories.bzl @@ -54,7 +56,7 @@ def _uv_repo_impl(repository_ctx): repository_ctx.download_and_extract( url = url, - sha256 = UV_TOOL_VERSIONS[repository_ctx.attr.uv_version][repository_ctx.attr.platform], + sha256 = UV_TOOL_VERSIONS[repository_ctx.attr.uv_version][repository_ctx.attr.platform].sha256, stripPrefix = strip_prefix, ) @@ -76,27 +78,44 @@ uv_repository = repository_rule( }, ) -# Wrapper macro around everything above, this is the primary API -def uv_register_toolchains(name, register = True, **kwargs): - """Convenience macro for users which does typical setup. +# buildifier: disable=unnamed-macro +def uv_register_toolchains(uv_version = None, register_toolchains = True): + """Convenience macro which does typical toolchain setup + + Skip this macro if you need more control over the toolchain setup. - Users can avoid this macro and do these steps themselves, if they want more control. Args: - name: base name for all created repos, like "uv0_2_13" - register: whether to call through to native.register_toolchains. - Should be True for WORKSPACE users, but false when used under bzlmod extension - **kwargs: passed to each uv_repositories call + uv_version: The uv toolchain version to download. + register_toolchains: If true, repositories will be generated to produce and register `uv_toolchain` targets. """ + if not uv_version: + fail("uv_version is required") + + toolchain_names = [] + toolchain_labels_by_toolchain = {} + toolchain_compatible_with_by_toolchain = {} + for platform in UV_PLATFORMS.keys(): - uv_repository( - name = name + "_" + platform, + uv_repository_name = platform + "_uv_toolchain" + + maybe( + uv_repository, + name = uv_repository_name, + uv_version = uv_version, platform = platform, - **kwargs ) - if register: - native.register_toolchains("@%s_toolchains//:%s_toolchain" % (name, platform)) + + toolchain_names.append(platform) + toolchain_labels_by_toolchain[platform] = "@{}//:uv_toolchain".format(uv_repository_name) + toolchain_compatible_with_by_toolchain[platform] = UV_PLATFORMS[platform].compatible_with uv_toolchains_repo( - name = name + "_toolchains", - user_repository_name = name, + name = "uv_toolchains", + toolchain_type = str(UV_TOOLCHAIN_TYPE), + toolchain_names = toolchain_names, + toolchain_labels = toolchain_labels_by_toolchain, + toolchain_compatible_with = toolchain_compatible_with_by_toolchain, ) + + if register_toolchains: + native.register_toolchains("@uv_toolchains//:all") From 7fb7af11583d515c64cbc408a1ce4c97dfeefa14 Mon Sep 17 00:00:00 2001 From: Greg Date: Wed, 10 Jul 2024 23:49:11 +1000 Subject: [PATCH 67/67] Address review comments --- python/uv/private/versions.bzl | 7 +++++++ python/uv/repositories.bzl | 9 +++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/python/uv/private/versions.bzl b/python/uv/private/versions.bzl index ab91a16e01..f7f0b9e0fe 100644 --- a/python/uv/private/versions.bzl +++ b/python/uv/private/versions.bzl @@ -16,42 +16,49 @@ UV_PLATFORMS = { "aarch64-apple-darwin": struct( + default_repo_name = "rules_python_uv_darwin_aarch64", compatible_with = [ "@platforms//os:macos", "@platforms//cpu:aarch64", ], ), "aarch64-unknown-linux-gnu": struct( + default_repo_name = "rules_python_uv_linux_aarch64", compatible_with = [ "@platforms//os:linux", "@platforms//cpu:aarch64", ], ), "powerpc64le-unknown-linux-gnu": struct( + default_repo_name = "rules_python_uv_linux_ppc", compatible_with = [ "@platforms//os:linux", "@platforms//cpu:ppc", ], ), "s390x-unknown-linux-gnu": struct( + default_repo_name = "rules_python_uv_linux_s390x", compatible_with = [ "@platforms//os:linux", "@platforms//cpu:s390x", ], ), "x86_64-apple-darwin": struct( + default_repo_name = "rules_python_uv_darwin_x86_64", compatible_with = [ "@platforms//os:macos", "@platforms//cpu:x86_64", ], ), "x86_64-pc-windows-msvc": struct( + default_repo_name = "rules_python_uv_windows_x86_64", compatible_with = [ "@platforms//os:windows", "@platforms//cpu:x86_64", ], ), "x86_64-unknown-linux-gnu": struct( + default_repo_name = "rules_python_uv_linux_x86_64", compatible_with = [ "@platforms//os:linux", "@platforms//cpu:x86_64", diff --git a/python/uv/repositories.bzl b/python/uv/repositories.bzl index 635746ce30..7f27e8bdc5 100644 --- a/python/uv/repositories.bzl +++ b/python/uv/repositories.bzl @@ -96,7 +96,7 @@ def uv_register_toolchains(uv_version = None, register_toolchains = True): toolchain_compatible_with_by_toolchain = {} for platform in UV_PLATFORMS.keys(): - uv_repository_name = platform + "_uv_toolchain" + uv_repository_name = UV_PLATFORMS[platform].default_repo_name maybe( uv_repository, @@ -105,9 +105,10 @@ def uv_register_toolchains(uv_version = None, register_toolchains = True): platform = platform, ) - toolchain_names.append(platform) - toolchain_labels_by_toolchain[platform] = "@{}//:uv_toolchain".format(uv_repository_name) - toolchain_compatible_with_by_toolchain[platform] = UV_PLATFORMS[platform].compatible_with + toolchain_name = uv_repository_name + "_toolchain" + toolchain_names.append(toolchain_name) + toolchain_labels_by_toolchain[toolchain_name] = "@{}//:uv_toolchain".format(uv_repository_name) + toolchain_compatible_with_by_toolchain[toolchain_name] = UV_PLATFORMS[platform].compatible_with uv_toolchains_repo( name = "uv_toolchains",