WIP (feat): Introduce an experimental `uv` toolchain
Context
This PR introduces a toolchain for uv and a module extension that can install it. It will be followed by some rules that make use of the toolchain for things like dependency locking.
Relates to https://github.com/bazelbuild/rules_python/issues/1975
Still outstanding:
- Address final comments from reviewers
- Remove placeholder
uv_pip_compilerule (and usages) before merging
Notes
Try it out:
cd examples/bzlmod
bazel run --sandbox_debug //:spike_uv_pip_compile
I ran that on my osx_x86_64 and it is locking for Windows:
Click me
# This file was autogenerated by uv via the following command:
# uv pip compile --python external/rules_python~~python~python_3_9_x86_64-apple-darwin/bin/python3 --python-platform windows --python-version 3.9 --no-strip-extras --generate-hashes --output-file bazel-out/darwin_x86_64-fastbuild/bin/spike_uv_pip_compile.requirements.out requirements.in
alabaster==0.7.16 \
--hash=sha256:75a8b99c28a5dad50dd7f8ccdd447a121ddb3892da9e53d1ca5cca3106d58d65 \
--hash=sha256:b46733c07dce03ae4e150330b975c75737fa60f0a7c591b6c8bf4928a28e2c92
# via sphinx
astroid==2.13.5 \
--hash=sha256:6891f444625b6edb2ac798829b689e95297e100ddf89dbed5a8c610e34901501 \
--hash=sha256:df164d5ac811b9f44105a72b8f9d5edfb7b5b2d7e979b04ea377a77b3229114a
# via pylint
babel==2.15.0 \
--hash=sha256:08706bdad8d0a3413266ab61bd6c34d0c28d6e1e7badf40a2cebe67644e2e1fb \
--hash=sha256:8daf0e265d05768bc6c7a314cf1321e9a123afc328cc635c18622a2f30a04413
# via sphinx
certifi==2024.6.2 \
--hash=sha256:3cd43f1c6fa7dedc5899d69d3ad0398fd018ad1a17fba83ddaf78aa46c747516 \
--hash=sha256:ddc6c8ce995e6987e7faf5e3f1b02b302836a0e5d98ece18392cb1a36c72ad56
# via requests
chardet==4.0.0 \
--hash=sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa \
--hash=sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5
# via requests
colorama==0.4.6 \
--hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \
--hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6
# via
# -r requirements.in
# pylint
# sphinx
dill==0.3.8 \
--hash=sha256:3ebe3c479ad625c4553aca177444d89b486b1d84982eeacded644afc0cf797ca \
--hash=sha256:c36ca9ffb54365bdd2f8eb3eff7d2a21237f8452b57ace88b1ac615b7e815bd7
# via pylint
docutils==0.21.2 \
--hash=sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f \
--hash=sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2
# via sphinx
idna==2.10 \
--hash=sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6 \
--hash=sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0
# via requests
imagesize==1.4.1 \
--hash=sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b \
--hash=sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a
# via sphinx
importlib-metadata==7.2.1 \
--hash=sha256:509ecb2ab77071db5137c655e24ceb3eee66e7bbc6574165d0d114d9fc4bbe68 \
--hash=sha256:ffef94b0b66046dd8ea2d619b701fe978d9264d38f3998bc4c27ec3b146a87c8
# via sphinx
isort==5.13.2 \
--hash=sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109 \
--hash=sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6
# via pylint
jinja2==3.1.4 \
--hash=sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369 \
--hash=sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d
# via sphinx
lazy-object-proxy==1.10.0 \
--hash=sha256:009e6bb1f1935a62889ddc8541514b6a9e1fcf302667dcb049a0be5c8f613e56 \
--hash=sha256:02c83f957782cbbe8136bee26416686a6ae998c7b6191711a04da776dc9e47d4 \
--hash=sha256:0aefc7591920bbd360d57ea03c995cebc204b424524a5bd78406f6e1b8b2a5d8 \
--hash=sha256:127a789c75151db6af398b8972178afe6bda7d6f68730c057fbbc2e96b08d282 \
--hash=sha256:18dd842b49456aaa9a7cf535b04ca4571a302ff72ed8740d06b5adcd41fe0757 \
--hash=sha256:217138197c170a2a74ca0e05bddcd5f1796c735c37d0eee33e43259b192aa424 \
--hash=sha256:2297f08f08a2bb0d32a4265e98a006643cd7233fb7983032bd61ac7a02956b3b \
--hash=sha256:2fc0a92c02fa1ca1e84fc60fa258458e5bf89d90a1ddaeb8ed9cc3147f417255 \
--hash=sha256:30b339b2a743c5288405aa79a69e706a06e02958eab31859f7f3c04980853b70 \
--hash=sha256:366c32fe5355ef5fc8a232c5436f4cc66e9d3e8967c01fb2e6302fd6627e3d94 \
--hash=sha256:3ad54b9ddbe20ae9f7c1b29e52f123120772b06dbb18ec6be9101369d63a4074 \
--hash=sha256:5ad9e6ed739285919aa9661a5bbed0aaf410aa60231373c5579c6b4801bd883c \
--hash=sha256:5faf03a7d8942bb4476e3b62fd0f4cf94eaf4618e304a19865abf89a35c0bbee \
--hash=sha256:75fc59fc450050b1b3c203c35020bc41bd2695ed692a392924c6ce180c6f1dc9 \
--hash=sha256:76a095cfe6045c7d0ca77db9934e8f7b71b14645f0094ffcd842349ada5c5fb9 \
--hash=sha256:78247b6d45f43a52ef35c25b5581459e85117225408a4128a3daf8bf9648ac69 \
--hash=sha256:782e2c9b2aab1708ffb07d4bf377d12901d7a1d99e5e410d648d892f8967ab1f \
--hash=sha256:7ab7004cf2e59f7c2e4345604a3e6ea0d92ac44e1c2375527d56492014e690c3 \
--hash=sha256:80b39d3a151309efc8cc48675918891b865bdf742a8616a337cb0090791a0de9 \
--hash=sha256:80fa48bd89c8f2f456fc0765c11c23bf5af827febacd2f523ca5bc1893fcc09d \
--hash=sha256:855e068b0358ab916454464a884779c7ffa312b8925c6f7401e952dcf3b89977 \
--hash=sha256:92f09ff65ecff3108e56526f9e2481b8116c0b9e1425325e13245abfd79bdb1b \
--hash=sha256:952c81d415b9b80ea261d2372d2a4a2332a3890c2b83e0535f263ddfe43f0d43 \
--hash=sha256:9a3a87cf1e133e5b1994144c12ca4aa3d9698517fe1e2ca82977781b16955658 \
--hash=sha256:9e4ed0518a14dd26092614412936920ad081a424bdcb54cc13349a8e2c6d106a \
--hash=sha256:a899b10e17743683b293a729d3a11f2f399e8a90c73b089e29f5d0fe3509f0dd \
--hash=sha256:b1f711e2c6dcd4edd372cf5dec5c5a30d23bba06ee012093267b3376c079ec83 \
--hash=sha256:b4f87d4ed9064b2628da63830986c3d2dca7501e6018347798313fcf028e2fd4 \
--hash=sha256:cb73507defd385b7705c599a94474b1d5222a508e502553ef94114a143ec6696 \
--hash=sha256:dc0d2fc424e54c70c4bc06787e4072c4f3b1aa2f897dfdc34ce1013cf3ceef05 \
--hash=sha256:e221060b701e2aa2ea991542900dd13907a5c90fa80e199dbf5a03359019e7a3 \
--hash=sha256:e271058822765ad5e3bca7f05f2ace0de58a3f4e62045a8c90a0dfd2f8ad8cc6 \
--hash=sha256:e2adb09778797da09d2b5ebdbceebf7dd32e2c96f79da9052b2e87b6ea495895 \
--hash=sha256:e333e2324307a7b5d86adfa835bb500ee70bfcd1447384a822e96495796b0ca4 \
--hash=sha256:e98c8af98d5707dcdecc9ab0863c0ea6e88545d42ca7c3feffb6b4d1e370c7ba \
--hash=sha256:edb45bb8278574710e68a6b021599a10ce730d156e5b254941754a9cc0b17d03 \
--hash=sha256:fec03caabbc6b59ea4a638bee5fce7117be8e99a4103d9d5ad77f15d6f81020c
# via astroid
markupsafe==2.1.5 \
--hash=sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf \
--hash=sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff \
--hash=sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f \
--hash=sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3 \
--hash=sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532 \
--hash=sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f \
--hash=sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617 \
--hash=sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df \
--hash=sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4 \
--hash=sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906 \
--hash=sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f \
--hash=sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4 \
--hash=sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8 \
--hash=sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371 \
--hash=sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2 \
--hash=sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465 \
--hash=sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52 \
--hash=sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6 \
--hash=sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169 \
--hash=sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad \
--hash=sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2 \
--hash=sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0 \
--hash=sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029 \
--hash=sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f \
--hash=sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a \
--hash=sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced \
--hash=sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5 \
--hash=sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c \
--hash=sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf \
--hash=sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9 \
--hash=sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb \
--hash=sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad \
--hash=sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3 \
--hash=sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1 \
--hash=sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46 \
--hash=sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc \
--hash=sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a \
--hash=sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee \
--hash=sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900 \
--hash=sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5 \
--hash=sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea \
--hash=sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f \
--hash=sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5 \
--hash=sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e \
--hash=sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a \
--hash=sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f \
--hash=sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50 \
--hash=sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a \
--hash=sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b \
--hash=sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4 \
--hash=sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff \
--hash=sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2 \
--hash=sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46 \
--hash=sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b \
--hash=sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf \
--hash=sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5 \
--hash=sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5 \
--hash=sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab \
--hash=sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd \
--hash=sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68
# via jinja2
mccabe==0.7.0 \
--hash=sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325 \
--hash=sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e
# via pylint
packaging==24.1 \
--hash=sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002 \
--hash=sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124
# via sphinx
pathspec==0.12.1 \
--hash=sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08 \
--hash=sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712
# via yamllint
platformdirs==4.2.2 \
--hash=sha256:2d7a1657e36a80ea911db832a8a6ece5ee53d8de21edd5cc5879af6530b1bfee \
--hash=sha256:38b7b51f512eed9e84a22788b4bce1de17c0adb134d6becb09836e37d8654cd3
# via pylint
pygments==2.18.0 \
--hash=sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199 \
--hash=sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a
# via sphinx
pylint==2.15.10 \
--hash=sha256:9df0d07e8948a1c3ffa3b6e2d7e6e63d9fb457c5da5b961ed63106594780cc7e \
--hash=sha256:b3dc5ef7d33858f297ac0d06cc73862f01e4f2e74025ec3eff347ce0bc60baf5
# via
# -r requirements.in
# pylint-print
pylint-print==1.0.1 \
--hash=sha256:30aa207e9718ebf4ceb47fb87012092e6d8743aab932aa07aa14a73e750ad3d0 \
--hash=sha256:a2b2599e7887b93e551db2624c523c1e6e9e58c3be8416cd98d41e4427e2669b
# via -r requirements.in
python-dateutil==2.9.0.post0 \
--hash=sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3 \
--hash=sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427
# via
# -r requirements.in
# s3cmd
python-magic==0.4.27 \
--hash=sha256:c1ba14b08e4a5f5c31a302b7721239695b2f0f058d125bd5ce1ee36b9d9d3c3b \
--hash=sha256:c212960ad306f700aa0d01e5d7a325d20548ff97eb9920dcd29513174f0294d3
# via s3cmd
pyyaml==6.0.1 \
--hash=sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5 \
--hash=sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc \
--hash=sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df \
--hash=sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741 \
--hash=sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206 \
--hash=sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27 \
--hash=sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595 \
--hash=sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62 \
--hash=sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98 \
--hash=sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696 \
--hash=sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290 \
--hash=sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9 \
--hash=sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d \
--hash=sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6 \
--hash=sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867 \
--hash=sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47 \
--hash=sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486 \
--hash=sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6 \
--hash=sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3 \
--hash=sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007 \
--hash=sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938 \
--hash=sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0 \
--hash=sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c \
--hash=sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735 \
--hash=sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d \
--hash=sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28 \
--hash=sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4 \
--hash=sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba \
--hash=sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8 \
--hash=sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef \
--hash=sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5 \
--hash=sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd \
--hash=sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3 \
--hash=sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0 \
--hash=sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515 \
--hash=sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c \
--hash=sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c \
--hash=sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924 \
--hash=sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34 \
--hash=sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43 \
--hash=sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859 \
--hash=sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673 \
--hash=sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54 \
--hash=sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a \
--hash=sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b \
--hash=sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab \
--hash=sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa \
--hash=sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c \
--hash=sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585 \
--hash=sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d \
--hash=sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f
# via yamllint
requests==2.25.1 \
--hash=sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804 \
--hash=sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e
# via
# -r requirements.in
# sphinx
s3cmd==2.1.0 \
--hash=sha256:49cd23d516b17974b22b611a95ce4d93fe326feaa07320bd1d234fed68cbccfa \
--hash=sha256:966b0a494a916fc3b4324de38f089c86c70ee90e8e1cae6d59102103a4c0cc03
# via -r requirements.in
six==1.16.0 \
--hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \
--hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254
# via python-dateutil
snowballstemmer==2.2.0 \
--hash=sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1 \
--hash=sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a
# via sphinx
sphinx==7.3.7 \
--hash=sha256:413f75440be4cacf328f580b4274ada4565fb2187d696a84970c23f77b64d8c3 \
--hash=sha256:a4a7db75ed37531c05002d56ed6948d4c42f473a36f46e1382b0bd76ca9627bc
# via -r requirements.in
sphinxcontrib-applehelp==1.0.8 \
--hash=sha256:c40a4f96f3776c4393d933412053962fac2b84f4c99a7982ba42e09576a70619 \
--hash=sha256:cb61eb0ec1b61f349e5cc36b2028e9e7ca765be05e49641c97241274753067b4
# via sphinx
sphinxcontrib-devhelp==1.0.6 \
--hash=sha256:6485d09629944511c893fa11355bda18b742b83a2b181f9a009f7e500595c90f \
--hash=sha256:9893fd3f90506bc4b97bdb977ceb8fbd823989f4316b28c3841ec128544372d3
# via sphinx
sphinxcontrib-htmlhelp==2.0.5 \
--hash=sha256:0dc87637d5de53dd5eec3a6a01753b1ccf99494bd756aafecd74b4fa9e729015 \
--hash=sha256:393f04f112b4d2f53d93448d4bce35842f62b307ccdc549ec1585e950bc35e04
# via sphinx
sphinxcontrib-jsmath==1.0.1 \
--hash=sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178 \
--hash=sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8
# via sphinx
sphinxcontrib-qthelp==1.0.7 \
--hash=sha256:053dedc38823a80a7209a80860b16b722e9e0209e32fea98c90e4e6624588ed6 \
--hash=sha256:e2ae3b5c492d58fcbd73281fbd27e34b8393ec34a073c792642cd8e529288182
# via sphinx
sphinxcontrib-serializinghtml==1.1.10 \
--hash=sha256:326369b8df80a7d2d8d7f99aa5ac577f51ea51556ed974e7716cfd4fca3f6cb7 \
--hash=sha256:93f3f5dc458b91b192fe10c397e324f262cf163d79f3282c158e8436a2c4511f
# via
# -r requirements.in
# sphinx
tabulate==0.9.0 \
--hash=sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c \
--hash=sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f
# via -r requirements.in
tomli==2.0.1 \
--hash=sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc \
--hash=sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f
# via
# pylint
# sphinx
tomlkit==0.12.5 \
--hash=sha256:af914f5a9c59ed9d0762c7b64d3b5d5df007448eb9cd2edc8a46b1eafead172f \
--hash=sha256:eef34fba39834d4d6b73c9ba7f3e4d1c417a4e56f89a7e96e090dd0d24b8fb3c
# via pylint
typing-extensions==4.12.2 \
--hash=sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d \
--hash=sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8
# via
# astroid
# pylint
urllib3==1.26.19 \
--hash=sha256:37a0344459b199fce0e80b0d3569837ec6b6937435c5244e7fd73fa6006830f3 \
--hash=sha256:3e3d753a8618b86d7de333b4223005f68720bcd6a7d2bcb9fbd2229ec7c1e429
# via requests
websockets==12.0 \
--hash=sha256:00700340c6c7ab788f176d118775202aadea7602c5cc6be6ae127761c16d6b0b \
--hash=sha256:0bee75f400895aef54157b36ed6d3b308fcab62e5260703add87f44cee9c82a6 \
--hash=sha256:0e6e2711d5a8e6e482cacb927a49a3d432345dfe7dea8ace7b5790df5932e4df \
--hash=sha256:12743ab88ab2af1d17dd4acb4645677cb7063ef4db93abffbf164218a5d54c6b \
--hash=sha256:1a9d160fd080c6285e202327aba140fc9a0d910b09e423afff4ae5cbbf1c7205 \
--hash=sha256:1bf386089178ea69d720f8db6199a0504a406209a0fc23e603b27b300fdd6892 \
--hash=sha256:1df2fbd2c8a98d38a66f5238484405b8d1d16f929bb7a33ed73e4801222a6f53 \
--hash=sha256:1e4b3f8ea6a9cfa8be8484c9221ec0257508e3a1ec43c36acdefb2a9c3b00aa2 \
--hash=sha256:1f38a7b376117ef7aff996e737583172bdf535932c9ca021746573bce40165ed \
--hash=sha256:23509452b3bc38e3a057382c2e941d5ac2e01e251acce7adc74011d7d8de434c \
--hash=sha256:248d8e2446e13c1d4326e0a6a4e9629cb13a11195051a73acf414812700badbd \
--hash=sha256:25eb766c8ad27da0f79420b2af4b85d29914ba0edf69f547cc4f06ca6f1d403b \
--hash=sha256:27a5e9964ef509016759f2ef3f2c1e13f403725a5e6a1775555994966a66e931 \
--hash=sha256:2c71bd45a777433dd9113847af751aae36e448bc6b8c361a566cb043eda6ec30 \
--hash=sha256:2cb388a5bfb56df4d9a406783b7f9dbefb888c09b71629351cc6b036e9259370 \
--hash=sha256:2d225bb6886591b1746b17c0573e29804619c8f755b5598d875bb4235ea639be \
--hash=sha256:2e5fc14ec6ea568200ea4ef46545073da81900a2b67b3e666f04adf53ad452ec \
--hash=sha256:363f57ca8bc8576195d0540c648aa58ac18cf85b76ad5202b9f976918f4219cf \
--hash=sha256:3c6cc1360c10c17463aadd29dd3af332d4a1adaa8796f6b0e9f9df1fdb0bad62 \
--hash=sha256:3d829f975fc2e527a3ef2f9c8f25e553eb7bc779c6665e8e1d52aa22800bb38b \
--hash=sha256:3e3aa8c468af01d70332a382350ee95f6986db479ce7af14d5e81ec52aa2b402 \
--hash=sha256:3f61726cae9f65b872502ff3c1496abc93ffbe31b278455c418492016e2afc8f \
--hash=sha256:423fc1ed29f7512fceb727e2d2aecb952c46aa34895e9ed96071821309951123 \
--hash=sha256:46e71dbbd12850224243f5d2aeec90f0aaa0f2dde5aeeb8fc8df21e04d99eff9 \
--hash=sha256:4d87be612cbef86f994178d5186add3d94e9f31cc3cb499a0482b866ec477603 \
--hash=sha256:5693ef74233122f8ebab026817b1b37fe25c411ecfca084b29bc7d6efc548f45 \
--hash=sha256:5aa9348186d79a5f232115ed3fa9020eab66d6c3437d72f9d2c8ac0c6858c558 \
--hash=sha256:5d873c7de42dea355d73f170be0f23788cf3fa9f7bed718fd2830eefedce01b4 \
--hash=sha256:5f6ffe2c6598f7f7207eef9a1228b6f5c818f9f4d53ee920aacd35cec8110438 \
--hash=sha256:604428d1b87edbf02b233e2c207d7d528460fa978f9e391bd8aaf9c8311de137 \
--hash=sha256:6350b14a40c95ddd53e775dbdbbbc59b124a5c8ecd6fbb09c2e52029f7a9f480 \
--hash=sha256:6e2df67b8014767d0f785baa98393725739287684b9f8d8a1001eb2839031447 \
--hash=sha256:6e96f5ed1b83a8ddb07909b45bd94833b0710f738115751cdaa9da1fb0cb66e8 \
--hash=sha256:6e9e7db18b4539a29cc5ad8c8b252738a30e2b13f033c2d6e9d0549b45841c04 \
--hash=sha256:70ec754cc2a769bcd218ed8d7209055667b30860ffecb8633a834dde27d6307c \
--hash=sha256:7b645f491f3c48d3f8a00d1fce07445fab7347fec54a3e65f0725d730d5b99cb \
--hash=sha256:7fa3d25e81bfe6a89718e9791128398a50dec6d57faf23770787ff441d851967 \
--hash=sha256:81df9cbcbb6c260de1e007e58c011bfebe2dafc8435107b0537f393dd38c8b1b \
--hash=sha256:8572132c7be52632201a35f5e08348137f658e5ffd21f51f94572ca6c05ea81d \
--hash=sha256:87b4aafed34653e465eb77b7c93ef058516cb5acf3eb21e42f33928616172def \
--hash=sha256:8e332c210b14b57904869ca9f9bf4ca32f5427a03eeb625da9b616c85a3a506c \
--hash=sha256:9893d1aa45a7f8b3bc4510f6ccf8db8c3b62120917af15e3de247f0780294b92 \
--hash=sha256:9edf3fc590cc2ec20dc9d7a45108b5bbaf21c0d89f9fd3fd1685e223771dc0b2 \
--hash=sha256:9fdf06fd06c32205a07e47328ab49c40fc1407cdec801d698a7c41167ea45113 \
--hash=sha256:a02413bc474feda2849c59ed2dfb2cddb4cd3d2f03a2fedec51d6e959d9b608b \
--hash=sha256:a1d9697f3337a89691e3bd8dc56dea45a6f6d975f92e7d5f773bc715c15dde28 \
--hash=sha256:a571f035a47212288e3b3519944f6bf4ac7bc7553243e41eac50dd48552b6df7 \
--hash=sha256:ab3d732ad50a4fbd04a4490ef08acd0517b6ae6b77eb967251f4c263011a990d \
--hash=sha256:ae0a5da8f35a5be197f328d4727dbcfafa53d1824fac3d96cdd3a642fe09394f \
--hash=sha256:b067cb952ce8bf40115f6c19f478dc71c5e719b7fbaa511359795dfd9d1a6468 \
--hash=sha256:b2ee7288b85959797970114deae81ab41b731f19ebcd3bd499ae9ca0e3f1d2c8 \
--hash=sha256:b81f90dcc6c85a9b7f29873beb56c94c85d6f0dac2ea8b60d995bd18bf3e2aae \
--hash=sha256:ba0cab91b3956dfa9f512147860783a1829a8d905ee218a9837c18f683239611 \
--hash=sha256:baa386875b70cbd81798fa9f71be689c1bf484f65fd6fb08d051a0ee4e79924d \
--hash=sha256:bbe6013f9f791944ed31ca08b077e26249309639313fff132bfbf3ba105673b9 \
--hash=sha256:bea88d71630c5900690fcb03161ab18f8f244805c59e2e0dc4ffadae0a7ee0ca \
--hash=sha256:befe90632d66caaf72e8b2ed4d7f02b348913813c8b0a32fae1cc5fe3730902f \
--hash=sha256:c3181df4583c4d3994d31fb235dc681d2aaad744fbdbf94c4802485ececdecf2 \
--hash=sha256:c4e37d36f0d19f0a4413d3e18c0d03d0c268ada2061868c1e6f5ab1a6d575077 \
--hash=sha256:c588f6abc13f78a67044c6b1273a99e1cf31038ad51815b3b016ce699f0d75c2 \
--hash=sha256:cbe83a6bbdf207ff0541de01e11904827540aa069293696dd528a6640bd6a5f6 \
--hash=sha256:d554236b2a2006e0ce16315c16eaa0d628dab009c33b63ea03f41c6107958374 \
--hash=sha256:dbcf72a37f0b3316e993e13ecf32f10c0e1259c28ffd0a85cee26e8549595fbc \
--hash=sha256:dc284bbc8d7c78a6c69e0c7325ab46ee5e40bb4d50e494d8131a07ef47500e9e \
--hash=sha256:dff6cdf35e31d1315790149fee351f9e52978130cef6c87c4b6c9b3baf78bc53 \
--hash=sha256:e469d01137942849cff40517c97a30a93ae79917752b34029f0ec72df6b46399 \
--hash=sha256:eb809e816916a3b210bed3c82fb88eaf16e8afcf9c115ebb2bacede1797d2547 \
--hash=sha256:ed2fcf7a07334c77fc8a230755c2209223a7cc44fc27597729b8ef5425aa61a3 \
--hash=sha256:f44069528d45a933997a6fef143030d8ca8042f0dfaad753e2906398290e2870 \
--hash=sha256:f764ba54e33daf20e167915edc443b6f88956f37fb606449b4a5b10ba42235a5 \
--hash=sha256:fc4e7fa5414512b481a2483775a8e8be7803a35b30ca805afa4998a84f9fd9e8 \
--hash=sha256:ffefa1374cd508d633646d51a8e9277763a9b78ae71324183693959cf94635a7
# via -r requirements.in
wheel==0.43.0 \
--hash=sha256:465ef92c69fa5c5da2d1cf8ac40559a8c940886afcef87dcf14b9470862f1d85 \
--hash=sha256:55c570405f142630c6b9f72fe09d9b67cf1477fcf543ae5b8dcb1f5b7377da81
# via -r requirements.in
wrapt==1.16.0 \
--hash=sha256:0d2691979e93d06a95a26257adb7bfd0c93818e89b1406f5a28f36e0d8c1e1fc \
--hash=sha256:14d7dc606219cdd7405133c713f2c218d4252f2a469003f8c46bb92d5d095d81 \
--hash=sha256:1a5db485fe2de4403f13fafdc231b0dbae5eca4359232d2efc79025527375b09 \
--hash=sha256:1acd723ee2a8826f3d53910255643e33673e1d11db84ce5880675954183ec47e \
--hash=sha256:1ca9b6085e4f866bd584fb135a041bfc32cab916e69f714a7d1d397f8c4891ca \
--hash=sha256:1dd50a2696ff89f57bd8847647a1c363b687d3d796dc30d4dd4a9d1689a706f0 \
--hash=sha256:2076fad65c6736184e77d7d4729b63a6d1ae0b70da4868adeec40989858eb3fb \
--hash=sha256:2a88e6010048489cda82b1326889ec075a8c856c2e6a256072b28eaee3ccf487 \
--hash=sha256:3ebf019be5c09d400cf7b024aa52b1f3aeebeff51550d007e92c3c1c4afc2a40 \
--hash=sha256:418abb18146475c310d7a6dc71143d6f7adec5b004ac9ce08dc7a34e2babdc5c \
--hash=sha256:43aa59eadec7890d9958748db829df269f0368521ba6dc68cc172d5d03ed8060 \
--hash=sha256:44a2754372e32ab315734c6c73b24351d06e77ffff6ae27d2ecf14cf3d229202 \
--hash=sha256:490b0ee15c1a55be9c1bd8609b8cecd60e325f0575fc98f50058eae366e01f41 \
--hash=sha256:49aac49dc4782cb04f58986e81ea0b4768e4ff197b57324dcbd7699c5dfb40b9 \
--hash=sha256:5eb404d89131ec9b4f748fa5cfb5346802e5ee8836f57d516576e61f304f3b7b \
--hash=sha256:5f15814a33e42b04e3de432e573aa557f9f0f56458745c2074952f564c50e664 \
--hash=sha256:5f370f952971e7d17c7d1ead40e49f32345a7f7a5373571ef44d800d06b1899d \
--hash=sha256:66027d667efe95cc4fa945af59f92c5a02c6f5bb6012bff9e60542c74c75c362 \
--hash=sha256:66dfbaa7cfa3eb707bbfcd46dab2bc6207b005cbc9caa2199bcbc81d95071a00 \
--hash=sha256:685f568fa5e627e93f3b52fda002c7ed2fa1800b50ce51f6ed1d572d8ab3e7fc \
--hash=sha256:6906c4100a8fcbf2fa735f6059214bb13b97f75b1a61777fcf6432121ef12ef1 \
--hash=sha256:6a42cd0cfa8ffc1915aef79cb4284f6383d8a3e9dcca70c445dcfdd639d51267 \
--hash=sha256:6dcfcffe73710be01d90cae08c3e548d90932d37b39ef83969ae135d36ef3956 \
--hash=sha256:6f6eac2360f2d543cc875a0e5efd413b6cbd483cb3ad7ebf888884a6e0d2e966 \
--hash=sha256:72554a23c78a8e7aa02abbd699d129eead8b147a23c56e08d08dfc29cfdddca1 \
--hash=sha256:73870c364c11f03ed072dda68ff7aea6d2a3a5c3fe250d917a429c7432e15228 \
--hash=sha256:73aa7d98215d39b8455f103de64391cb79dfcad601701a3aa0dddacf74911d72 \
--hash=sha256:75ea7d0ee2a15733684badb16de6794894ed9c55aa5e9903260922f0482e687d \
--hash=sha256:7bd2d7ff69a2cac767fbf7a2b206add2e9a210e57947dd7ce03e25d03d2de292 \
--hash=sha256:807cc8543a477ab7422f1120a217054f958a66ef7314f76dd9e77d3f02cdccd0 \
--hash=sha256:8e9723528b9f787dc59168369e42ae1c3b0d3fadb2f1a71de14531d321ee05b0 \
--hash=sha256:9090c9e676d5236a6948330e83cb89969f433b1943a558968f659ead07cb3b36 \
--hash=sha256:9153ed35fc5e4fa3b2fe97bddaa7cbec0ed22412b85bcdaf54aeba92ea37428c \
--hash=sha256:9159485323798c8dc530a224bd3ffcf76659319ccc7bbd52e01e73bd0241a0c5 \
--hash=sha256:941988b89b4fd6b41c3f0bfb20e92bd23746579736b7343283297c4c8cbae68f \
--hash=sha256:94265b00870aa407bd0cbcfd536f17ecde43b94fb8d228560a1e9d3041462d73 \
--hash=sha256:98b5e1f498a8ca1858a1cdbffb023bfd954da4e3fa2c0cb5853d40014557248b \
--hash=sha256:9b201ae332c3637a42f02d1045e1d0cccfdc41f1f2f801dafbaa7e9b4797bfc2 \
--hash=sha256:a0ea261ce52b5952bf669684a251a66df239ec6d441ccb59ec7afa882265d593 \
--hash=sha256:a33a747400b94b6d6b8a165e4480264a64a78c8a4c734b62136062e9a248dd39 \
--hash=sha256:a452f9ca3e3267cd4d0fcf2edd0d035b1934ac2bd7e0e57ac91ad6b95c0c6389 \
--hash=sha256:a86373cf37cd7764f2201b76496aba58a52e76dedfaa698ef9e9688bfd9e41cf \
--hash=sha256:ac83a914ebaf589b69f7d0a1277602ff494e21f4c2f743313414378f8f50a4cf \
--hash=sha256:aefbc4cb0a54f91af643660a0a150ce2c090d3652cf4052a5397fb2de549cd89 \
--hash=sha256:b3646eefa23daeba62643a58aac816945cadc0afaf21800a1421eeba5f6cfb9c \
--hash=sha256:b47cfad9e9bbbed2339081f4e346c93ecd7ab504299403320bf85f7f85c7d46c \
--hash=sha256:b935ae30c6e7400022b50f8d359c03ed233d45b725cfdd299462f41ee5ffba6f \
--hash=sha256:bb2dee3874a500de01c93d5c71415fcaef1d858370d405824783e7a8ef5db440 \
--hash=sha256:bc57efac2da352a51cc4658878a68d2b1b67dbe9d33c36cb826ca449d80a8465 \
--hash=sha256:bf5703fdeb350e36885f2875d853ce13172ae281c56e509f4e6eca049bdfb136 \
--hash=sha256:c31f72b1b6624c9d863fc095da460802f43a7c6868c5dda140f51da24fd47d7b \
--hash=sha256:c5cd603b575ebceca7da5a3a251e69561bec509e0b46e4993e1cac402b7247b8 \
--hash=sha256:d2efee35b4b0a347e0d99d28e884dfd82797852d62fcd7ebdeee26f3ceb72cf3 \
--hash=sha256:d462f28826f4657968ae51d2181a074dfe03c200d6131690b7d65d55b0f360f8 \
--hash=sha256:d5e49454f19ef621089e204f862388d29e6e8d8b162efce05208913dde5b9ad6 \
--hash=sha256:da4813f751142436b075ed7aa012a8778aa43a99f7b36afe9b742d3ed8bdc95e \
--hash=sha256:db2e408d983b0e61e238cf579c09ef7020560441906ca990fe8412153e3b291f \
--hash=sha256:db98ad84a55eb09b3c32a96c576476777e87c520a34e2519d3e59c44710c002c \
--hash=sha256:dbed418ba5c3dce92619656802cc5355cb679e58d0d89b50f116e4a9d5a9603e \
--hash=sha256:dcdba5c86e368442528f7060039eda390cc4091bfd1dca41e8046af7c910dda8 \
--hash=sha256:decbfa2f618fa8ed81c95ee18a387ff973143c656ef800c9f24fb7e9c16054e2 \
--hash=sha256:e4fdb9275308292e880dcbeb12546df7f3e0f96c6b41197e0cf37d2826359020 \
--hash=sha256:eb1b046be06b0fce7249f1d025cd359b4b80fc1c3e24ad9eca33e0dcdb2e4a35 \
--hash=sha256:eb6e651000a19c96f452c85132811d25e9264d836951022d6e81df2fff38337d \
--hash=sha256:ed867c42c268f876097248e05b6117a65bcd1e63b779e916fe2e33cd6fd0d3c3 \
--hash=sha256:edfad1d29c73f9b863ebe7082ae9321374ccb10879eeabc84ba3b69f2579d537 \
--hash=sha256:f2058f813d4f2b5e3a9eb2eb3faf8f1d99b81c3e51aeda4b168406443e8ba809 \
--hash=sha256:f6b2d0c6703c988d334f297aa5df18c45e97b0af3679bb75059e0e0bd8b1069d \
--hash=sha256:f8212564d49c50eb4565e502814f694e240c55551a5f1bc841d4fcaabb0a9b8a \
--hash=sha256:ffa565331890b90056c01db69c0fe634a776f8019c143a5ae265f9c6bc4bd6d4
# via astroid
yamllint==1.35.1 \
--hash=sha256:2e16e504bb129ff515b37823b472750b36b6de07963bd74b307341ef5ad8bdc3 \
--hash=sha256:7a003809f88324fd2c877734f2d575ee7881dd9043360657cc8049c809eba6cd
# via -r requirements.in
zipp==3.19.2 \
--hash=sha256:bf1dcf6450f873a13e952a29504887c89e6de7506209e5b1bcc3460135d4de19 \
--hash=sha256:f091755f667055f2d02b32c53771a7a6c8b47e1fdbc4b72a8b9072b3eef8015c
# via importlib-metadata
Try it out:
cd examples/bzlmod
bazel run --sandbox_debug //:spike_uv_show_template_variables
UV_BIN: external/rules_python~~uv~uv_x86_64-apple-darwin/uv
Thanks for the initial review @aignas
Having an interface like:
Yes. I like the look of it. We will keep iterating on it. The interface you have there is almost an exact match of what I have in mind.
Should we accept requirements.in or pyproject.toml as input to the pip.parse so that the user does not need to specify it using in the pin target? I would probably say yes to this.
Yes. That's aligned with my thinking and helps with the migration path and onboarding. In addition, we should also support a simple bazel list of requirements specifiers `requirement_specifiers = ["requests > 2.0.0", "click > 7.0.0", ]
Should we automatically generate targets for pinning for all of the platform targets that the user wants to support? I would also probably say yes to that.
Yes. That's aligned with my thinking too.
Users needing to create a requirements_lock.txt file to store the output of the pinning. The error is unintuitive and I think we could do some stuff there - aspects write_source_file does not fail if the destination file is not present.
Yes. I'd like to fix it too. I think in your interface sketch, as long as we use a directory with deterministic named files, then it should be reasonable to do. I think that would let the target run on initial bootstrap without failing 🤞
- A rule (not a macro) that does
uv pip compileand uses auvtoolchain and thepythontoolchain to get the tools. This allows us to pass the right interpreter touvall the time. We should haveexecconfiguration on the rule for the toolchains.
Yes, agreed. I think a toolchain makes sense. I avoided in this quick hack because every time I get involved with toolchains, I confuse myself 😂 I think cfg = exec here makes sense and uv works well because it can "cross-pin" for the target platform, but please double check it all during reviews.
re: toolchains: Yeah, toolchains are exactly for this sort of thing. uv is basically a "compiler" for the requirements.in "source code".
Here's the basic for a toolchain-based implementation. T
# BUILD
toolchain_type(name = "uv_toolchain_type")
toolchain(
name = "uv_toolchain",
toolchain_type = ":uv_toolchain_type",
toolchain = ":uv_toolchain_impl"
)
uv_toolchain(
name = "uv_toolchain_impl",
uv = "@uv//:bin",
)
# uv_toolchain.bzl
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")
}
)
# compile_requirements.bzl
def _compile_requirements_impl(ctx):
requirements_out = ctx.actions.declare_file(ctx.label.name + ".requirements.out")
uv = ctx.toolchains[":uv_toolchain_type"].uv
pv = ctx.toolchains["//python:toolchain_type"].interpreter_version_info
python = ctx.toolchains["//python:exec_tools_toolchain_type"].interpreter
args = ctx.actions.args()
# IDK the args, but you get the gist. Additional args like platform, cpu, etc
# can be added by depending on the flags and passing them along.
args.add("--python", python)
args.add("--python-version", "{}.{}".format(pv.major, pv.minor))
args.add("--requirements-in", ctx.file.requirements_in)
args.add("--requirements-out", requirements_out)
ctx.actions.run(
executable = uv,
args = args,
inputs = depset([requirements_in]),
outputs = [requirements_out],
tools = [python]
)
return [DefaultInfo(
files = [requirements_out],
)]
compile_requirements = rule(
implementation = _compile_requirements_impl,
attrs = {
"requirements_in": attr.label(allow_single_file = True)
},
toolchains = [
"//python:toolchain_type",
"//python:exec_tools_toolchain_type",
":uv_toolchain_type",
]
)
That should be the gist of it. The above allows bazel build //:compile_with_uv, where the output would be the resolved requirements file.
An alternative might be to add it to the exec_tools toolchain type, too, directly or indirectly.
In order to have something like bazel run //:compile_using_uv, where uv is directly run, then the above has to change a bit (the uv binary has to be in the target config for that, so requires some slightly different wiring).
- Is
pinthe best name? Should we instead uselock?
You're probably right. I use them interchangeably a lot of the time, but it's probably better to be precise here. I'm not sure if there is a good write-up anywhere on the topic that clearly describes the difference between pinning vs locking?
To me, here's the difference:
- Pinning - Updating requirement specifiers to pin them to some range of versions. Possibly SemVer style or
~=is a good example of pinning within a range. Renovate and / or dependabot would bump pins in { requirements.in | pyproject.toml } and then lock outputs to concrete requirements.txt. See locking definition. - Locking - Recording the precise version of dependency in a file.
I think if we align on those, then I think :lock is probably the more precise term to be using here?
I had some code laying around with using the uv binaries directly, so I took the liberty to push that here.
Thanks both! I'll hopefully have some time today and I think my goal will be to add a simple toolchain. It's likely that it could be merged independently even if unused while we work on the rest of the interface and functionality.
Some additional thoughts I've had:
- Should the toolchain be optional or mandatory (I mean in end-state. Not while we introduce the functionality. While we introduce it, it could be optional, but I'm tempted to say end-state its not-optional if you use the pypi_install / pap.parse) functionality? Also fine to late-bind on this and we can figure it out while the ideas develop.
- Maybe controversial, but Im going to try frame this not as "uv" specifically, but more as a "locking toolchain"? Of course, we can share that it has some "uv" functionality, and we can probably expose a raw "uv" mode behind something like "unsafe_uv_args" or let people execute the toolchain directly, but I would really rather support the standards (in this case PEP 621 for pyproject.toml and PEP 508 dependency specifiers) than specific tools for now. We can discuss face to face, but PEP 621 is supported by pip, uv, PDM and Poetry will support it in v2. The 508 specifiers are supported by everything of course. That would mean that the fact that we produce / vendor a "requirements.txt" as a lockfile is actually our implementation choice and we can change it later if necessary. Either to a "uv lockfile", or our own format, or some future Python lockfile standard if one emerges. The 621 files are supported by tools like dependabot and renovate, and it's easy to document how to trigger a bazel build after a dependabot PR that bumps the pyproject.toml
- On IDE support, I think in addition to the
:locktarget, I would also like to add a:ide-venvtarget that spits out a.venvfor the IDEs
First of all, thank you for looking into that! I've been personally struggling with maintaining pip-compile'd lock files across multiple platforms a lot. I wish I knew uv existed 🥲, however, I eventually migrated to rules_pycross for better QoL and happy with the choice.
One thought for consideration: how does it align with #1360 ? If rules_pycross is pulled, pip-compile will be replaced with PDM/Poetry altogether, both of which produce platform-independent lock files. In my opinion, having platform-agnostic lock files should be the ultimate goal as it is easier to maintain, and it seems uv authors are of the same opinion (see uv#Limitations). That said, perhaps expediting rules_pycross integration should be prioritized? At the same time, I can see that using uv to bring great value at less effort.
They're unrelated for the most part. This PR is to assist with a better implementation of compile_pip_requirements. That issue was more how we could align to bring some code across for another initiative that we likely won't pursue at the moment. We did vendor some of the code at the time https://github.com/bazelbuild/rules_python/tree/main/third_party/rules_pycross We can probably close that issue #1360 tbh.
If pycross is working for you, that's great! There's no real reason to favor rules_python. Use what works best for you.
We keep close eyes on the standards, and I'm sure one day a lockfile standard will emerge. However, I must say that it's not that important that a lockfile is standardized as long as the input dependency specifiers are standardized. Which fortunately they are and have been for a long time. So largely anyone using a PEP621 pyproject.toml can relock dependencies and I would largely expect the lockfiles to be similar. The important thing is whether a resolver can find a valid solution, not that all resolvers produce identical solutions.
We keep close eyes on the standards, and I'm sure one day a lockfile standard will emerge. However, I must say that it's not that important that a lockfile is standardized as long as the input dependency specifiers are standardized. Which fortunately they are. So largely anyone using a PEP621 pyproject.toml can relock dependencies and I would largely expect to the lockfiles to be similar. The important thing is whether a resolver can find a valid solution, not that all resolvers produce identical solutions.
I am fully on the same page. I might have been unclear in that bit as I was primarily looking at this PR as a way to make multi-platform like easier, but I wasn't concerned with that. I am not even convinced a lockfile standard is needed at all. My sentiment was about using something like pmd or poetry that generates platform-agnostic lockfiles given that there was an intention to integrate rules_pycross that already uses just that (or at least that was my understanding of what was supposed to happen), rather than (what feels like but technically is not) a wrapper tool around pip-compile to fix its incompetence in multi-platform lock files :)
Either way, if uv is integrated into compile_pip_requirements and can generate all the lock files for specified platforms on any host in one go, it will be a win. No more bringing Docker --platform linux/amd64 to create a lock file for linux on a Mac laptop :)
Creating cross-platform uv.lock file is in the works, is that going to be considered as well
Creating https://github.com/astral-sh/uv/issues/3347 file is in the works, is that going to be considered as well
We are aware of that. The PR is still in development and discussions with the maintainers, so it's too early to commit to anything. The lockfile format itself is really an implementation detail in this design though.
I'm curious though: what difference does it make to the functionality what the lockfile format is? As I mentioned in other comments, the lockfile format itself is not the most important thing.
So largely anyone using a PEP621 pyproject.toml can relock dependencies and I would largely expect the lockfiles to be similar. The important thing is whether a resolver can find a valid solution, not that all resolvers produce identical solutions.
I'm curious though: what difference does it make to the functionality what the lockfile format is? As I mentioned in other comments, the lockfile format itself is not the most important thing.
I will say that a lock file that includes the URLs of the wheels/sdist, has the advantage of utilizing the bazel downloader directly without an extra step of fetching the metadata. Also having a single lock file for all platforms is a plus.
FYI, @groodt, I have created #2006 to move the remaining of the PyPI related
code to python/pypi where we are re-exporting the publicly consumable
symbols. I think we should clean them up before releasing 1.0.0, but for now
all the changes where backwards compatible. I think this spike could structure
the files like:
python/private/pypi/uv_toolchain.bzl- Auvtoolchain definition.python/private/pypi/uv_pip_compile.bzl- Auv pip compileimplementation that is imported from thepip.parsehub repo.
The gist is that we can keep implementation specific names in private/pypi
whilst the public API can be whatever we choose. I see we have
compile_pip_requirements right now in //python:pip.bzl, but since there
will be two implementation of that in rules_python (one legacy and one with
uv), I thought having a name pip_compile and uv_pip_compile for the
internal bazel functions might make more sense for us to quickly see what is
going on when browsing the code.
@ewianda
I will say that a lock file that includes the URLs of the wheels/sdist, has the advantage of utilizing the bazel downloader directly without an extra step of fetching the metadata. Also having a single lock file for all platforms is a plus.
There are many projects that have very different requirements, so its hard to
have a one-thing-fits-all solution. And no-one is arguing with you that having
a single lock file is nice and having URLs in the lock file is also good - this
is where the Python community as a whole is moving. On the other hand, some
rules_python users mentioned that they have different requirements.txt files
for different python versions, OS, arch combinations and supporting these use
cases is where we meet our users today.
As for needing to call PyPI before fetching - it is done only needed when
rules_python or the lock file is updated. However, the packages won't be
re-fetched if they do not change, because of how the repository cache and
bzlmod works. Maybe in the future we can optimize that even more. If there
are bugs where refetching is done more eagerly, please raise issues. In the
case of bazel mod vendor, that feature is going to land only in 7.3.0 and I
am sure there will be more things ironed before it is fully usable - bazel
team is using rules_python so we are likely to collaborate with them on that
at some point.
If you would like to consider rules_python to support uv, pdm or poetry
or another universal lock file format, please create a GitHub issue so that we
have a paper trail to clearly see who are interested in these features and who
could help test them once (if) somebody starts implementing it. Let's continue
discussions about alternative lock formats in such issues and keep this PR
focused on this spike of having uv pip compile integrated.
The gist is that we can keep implementation specific names in
private/pypiwhilst the public API can be whatever we choose. I see we havecompile_pip_requirementsright now in//python:pip.bzl, but since there will be two implementation of that inrules_python(one legacy and one withuv), I thought having a namepip_compileanduv_pip_compilefor the internal bazel functions might make more sense for us to quickly see what is going on when browsing the code.
Sounds good. Yes, I've been very much looking forward to moving towards a more conventional structure. I long for the simplicity of a clean set of rules, but things are improving all the time 😂
This PR is now ready for another pass @aignas @rickeylev Please read updated description at top of PR.
It's got the "bones" of a functioning toolchain. Before I spend more time polishing it and fixing CI, first want you to highlight any showstoppers. A possible approach for this PR could be to fix CI and get the toolchain into a mergeable state, while leaving it experimental and not integrated with the rest of the rules. Let me know your preference. Im equally happy to sit on this branch to spar on the rest of the functionality.
should it be optional or mandatory in the end state
I would say mandatory. We eventually want to stop using the pip backend entirely, right? Is there any reason for it stick around?
frame it as a locking toolchain
I like this idea. This might complicate the implementation a bit, though :). Basically, the higher level pip_compile() rule has to know how to call the different implementations of the tools. This translates to either
pip_compile()rule passes a fixed set of args; the tool has to translate these args.- or
pip_compile()gets a function from the toolchain, which builds the args (provider can return functions :D)
I didn't look at pep 621, but, regardless, there are certain inputs we have to pass in somehow.
But otherwise, this is easy for toolchains to support. It just needs a value in target_settings (just like the uv_version thing I mention in the comments). To control the backend on a per-uv_pip_compile basis, an attribute with transition.
have ide-venv target produce .venv target
.venv is a directory, with everything installed right? But this rule (uv_pip_compile) is just doing requirements compiling. My point being, it can't produce a venv, since creating that requires going through the pip.parse-type of logic to create the repos, download things, etc.
To be clear, I'm not against a venv-creating thing, its just outside the purview and ability of the compile rule.
show stoppers, experimental mergable vs sitting in a branch
I'm +1 on submitting it in an non-final state and calling it experimental in the interim. IMHO it makes it easier to develop and iterate. Ignas has been doing this, so he can confirm/deny :). Given the massive improvement uv gives, I wouldn't be surprised if you get some good feedback from early adopters (and to be clear, we won't apply the backwards compatibility policy to such early adopters).
FYI i pushed a few changes to address some of my more nit/style type of comments. I avoided changing stuff that seemed likely to cause larger merge conflict annoyances
@aignas @rickeylev
Thanks for the reviews. Here's what Im thinking now in terms of next steps.
- Focus on merging a complete toolchain only. We can spar on the interface for
uv_pip_compile(or whatever we end up calling it). My original desire for an improved dependency locking capability is beyond a simple replication of the existingcompile_pip_requirementsand more along the lines of adding something to thepiphub. But I'd be happy to provide some bridge / support for the legacy macro. I would just prefer to deprecate that entire approach eventually because I believe its flawed. Lets chat about the plans for anything beyond a toolchain at next maintainers meeting. - Firm up all the docstrings to a point we are happy. Or hide all of this functionality from docs until we are ready? I don't mind either way. It might be a good idea to not commit to anything with this yet?
- Update all the file download urls and hashes and uncomment the code that skips hash verification
- Address outstanding review comments
Once we have that and a green CI, then we can either merge this PR or create a clean PR with just the toolchain.
Agree?
My vote would be to keep everything in this PR under python/private, so that we have time (a few more PRs) to iron out the interfaces and docs.
I would love to dog food the interfaces before we expose them and I am happy with the plan on adding something to the pip hub repo, but would love if we can make the maintenance of all of the requirements files in the rules_python repo easier to maintai (i.e. relock from a single OS for all of the platforms). This could be done whilst the code is still in private, I think we could enforce this with the visibility statements in our codebase.
If I understood correctly, what you proposed was bigger scope of the initial PR. My thinking was that as long as we can replace the sphinxdocs locking of the requirements, this code is working enough to be merged at least in its initial form.
What do you think?
My vote would be to keep everything in this PR under python/private, so that we have time (a few more PRs) to iron out the interfaces and docs.
I would love to dog food the interfaces before we expose them and I am happy with the plan on adding something to the pip hub repo, but would love if we can make the maintenance of all of the requirements files in the rules_python repo easier
What do you think?
SGTM. I think in that instance, then I would probably still do it across a few PRs.
- This PR (or a clean one if we prefer) with just the basic toolchain
- A PR to add some basic
uv_pip_compile(or any other name) to replace our internal usage - N x PRs of inevitable fixes / improvements
- Decide if we want to expand the functionality to
pip hub repostyle or to open up what we have so far - Whatever we open up via visibility rules, we announce as experimental for some period
Your plans sounds good. :) thanks for working on this!
On 28 June 2024 21:35:37 GMT+09:00, Greg Roodt @.***> wrote:
My vote would be to keep everything in this PR under python/private, so that we have time (a few more PRs) to iron out the interfaces and docs.
I would love to dog food the interfaces before we expose them and I am happy with the plan on adding something to the pip hub repo, but would love if we can make the maintenance of all of the requirements files in the rules_python repo easier
What do you think?
SGTM. I think in that instance, then I would probably still do it across a few PRs.
- This PR (or a clean one if we prefer) with just the basic toolchain
- A PR to add some basic
uv_pip_compile(or any other name) to replace our internal usage- N x PRs of Inevitable polish / fixes / improvements
- Decide if we want to expand to the functionality to
pip hub repostyle or to open up what we have so far- Whatever we open up via visibility rules, we announce as experimental for some period
-- Reply to this email directly or view it on GitHub: https://github.com/bazelbuild/rules_python/pull/1989#issuecomment-2196810726 You are receiving this because you were mentioned.
Message ID: @.***>
@aignas @rickeylev This is ready for another pass. I've also updated the title and description.
If it got lost in the noise, my current plan is as follows:
- This PR (or a clean one if we prefer) with just the basic toolchain 👈 This PR
- A follow-up PR to add some basic uv_pip_compile (or any other name) to replace our internal usage
- N x PRs of inevitable fixes / improvements
- Decide if we want to expand the functionality to pip hub repo style or to open up what we have so far
- Whatever we open up via visibility rules, we announce as experimental for some period
re: how toolchain registration is working
Ok. You've convinced me. Also some issues I encountered with rules_jsonnet and some passing conversations with people at work also led me to discover this: https://github.com/bazelbuild/bazel/discussions/22024#discussioncomment-9160537
I tend to agree with you. The naming doesn't matter and it's cleaner to use :all. I don't like the idea of having other extensions transitively clobber toolchain registration, so I've required it to be registered in the root module. If / when the uv toolchain is registered as part of rules_python, we can implement the recommendation described in the discussion linked above. This would mean the root module has full control, but for convenience or engineer laziness, rules_python can provide sane defaults that would work in most cases, but do have a risk of transitive clobbering.
I know I implemented the numeric prefixes in earlier iterations, but I've removed it for now. I found it to be a bit too arcane and unnecessary right now. It can be added back later once we're further along.
Ok @aignas @rickeylev This is probably ready for another pass. I think I've incorporated the majority of the requested changes.
I've also updated the original PR description with some items to follow-up with https://github.com/bazelbuild/rules_python/pull/1989#issue-2359800132 so please have a read of that as well and let me know if there is more to add.