diff --git a/examples/bzlmod/MODULE.bazel.lock b/examples/bzlmod/MODULE.bazel.lock index 9cad5952d7..4e33d687aa 100644 --- a/examples/bzlmod/MODULE.bazel.lock +++ b/examples/bzlmod/MODULE.bazel.lock @@ -1562,7 +1562,7 @@ }, "@@rules_python~//python/extensions:pip.bzl%pip": { "general": { - "bzlTransitiveDigest": "i5dWUNj1rZ4NKXmzLiGceV+1gAsDWtpJED1w1tdB7WY=", + "bzlTransitiveDigest": "5z/5q3EBJB0+9vXWaXw/dEVXUjcekSAzue8KfeZAILQ=", "usagesDigest": "VmrNvB/4EhzsYieLDka9584M+pYKPpjNLl3Wcb5rx/c=", "recordedFileInputs": { "@@//requirements_lock_3_10.txt": "5e7083982a7e60f34998579a0ae83b520d46ab8f2552cc51337217f024e6def5", @@ -6732,7 +6732,7 @@ "repo_name": "other_module_pip", "extra_hub_aliases": {}, "whl_map": { - "absl_py": "[{\"repo\":\"other_module_pip_311_absl_py\",\"version\":\"3.11\"}]" + "absl_py": "{\"other_module_pip_311_absl_py\":[{\"version\":\"3.11\"}]}" }, "packages": [ "absl_py" @@ -6751,53 +6751,53 @@ ] }, "whl_map": { - "alabaster": "[{\"repo\":\"pip_310_alabaster\",\"version\":\"3.10\"},{\"filename\":\"alabaster-0.7.13-py3-none-any.whl\",\"repo\":\"pip_39_alabaster_py3_none_any_1ee19aca\",\"version\":\"3.9\"},{\"filename\":\"alabaster-0.7.13.tar.gz\",\"repo\":\"pip_39_alabaster_sdist_a27a4a08\",\"version\":\"3.9\"}]", - "astroid": "[{\"repo\":\"pip_310_astroid\",\"version\":\"3.10\"},{\"filename\":\"astroid-2.12.13-py3-none-any.whl\",\"repo\":\"pip_39_astroid_py3_none_any_10e0ad5f\",\"version\":\"3.9\"},{\"filename\":\"astroid-2.12.13.tar.gz\",\"repo\":\"pip_39_astroid_sdist_1493fe8b\",\"version\":\"3.9\"}]", - "babel": "[{\"repo\":\"pip_310_babel\",\"version\":\"3.10\"},{\"filename\":\"Babel-2.13.1-py3-none-any.whl\",\"repo\":\"pip_39_babel_py3_none_any_7077a498\",\"version\":\"3.9\"},{\"filename\":\"Babel-2.13.1.tar.gz\",\"repo\":\"pip_39_babel_sdist_33e0952d\",\"version\":\"3.9\"}]", - "certifi": "[{\"repo\":\"pip_310_certifi\",\"version\":\"3.10\"},{\"filename\":\"certifi-2023.7.22-py3-none-any.whl\",\"repo\":\"pip_39_certifi_py3_none_any_92d60375\",\"version\":\"3.9\"},{\"filename\":\"certifi-2023.7.22.tar.gz\",\"repo\":\"pip_39_certifi_sdist_539cc1d1\",\"version\":\"3.9\"}]", - "chardet": "[{\"repo\":\"pip_310_chardet\",\"version\":\"3.10\"},{\"filename\":\"chardet-4.0.0-py2.py3-none-any.whl\",\"repo\":\"pip_39_chardet_py2_none_any_f864054d\",\"version\":\"3.9\"},{\"filename\":\"chardet-4.0.0.tar.gz\",\"repo\":\"pip_39_chardet_sdist_0d6f53a1\",\"version\":\"3.9\"}]", - "colorama": "[{\"repo\":\"pip_310_colorama\",\"version\":\"3.10\"},{\"filename\":\"colorama-0.4.6-py2.py3-none-any.whl\",\"repo\":\"pip_39_colorama_py2_none_any_4f1d9991\",\"version\":\"3.9\"},{\"filename\":\"colorama-0.4.6.tar.gz\",\"repo\":\"pip_39_colorama_sdist_08695f5c\",\"version\":\"3.9\"}]", - "dill": "[{\"repo\":\"pip_310_dill\",\"version\":\"3.10\"},{\"filename\":\"dill-0.3.6-py3-none-any.whl\",\"repo\":\"pip_39_dill_py3_none_any_a07ffd23\",\"version\":\"3.9\"},{\"filename\":\"dill-0.3.6.tar.gz\",\"repo\":\"pip_39_dill_sdist_e5db55f3\",\"version\":\"3.9\"}]", - "docutils": "[{\"repo\":\"pip_310_docutils\",\"version\":\"3.10\"},{\"filename\":\"docutils-0.20.1-py3-none-any.whl\",\"repo\":\"pip_39_docutils_py3_none_any_96f387a2\",\"version\":\"3.9\"},{\"filename\":\"docutils-0.20.1.tar.gz\",\"repo\":\"pip_39_docutils_sdist_f08a4e27\",\"version\":\"3.9\"}]", - "idna": "[{\"repo\":\"pip_310_idna\",\"version\":\"3.10\"},{\"filename\":\"idna-2.10-py2.py3-none-any.whl\",\"repo\":\"pip_39_idna_py2_none_any_b97d804b\",\"version\":\"3.9\"},{\"filename\":\"idna-2.10.tar.gz\",\"repo\":\"pip_39_idna_sdist_b307872f\",\"version\":\"3.9\"}]", - "imagesize": "[{\"repo\":\"pip_310_imagesize\",\"version\":\"3.10\"},{\"filename\":\"imagesize-1.4.1-py2.py3-none-any.whl\",\"repo\":\"pip_39_imagesize_py2_none_any_0d8d18d0\",\"version\":\"3.9\"},{\"filename\":\"imagesize-1.4.1.tar.gz\",\"repo\":\"pip_39_imagesize_sdist_69150444\",\"version\":\"3.9\"}]", - "importlib_metadata": "[{\"filename\":\"importlib_metadata-8.4.0-py3-none-any.whl\",\"repo\":\"pip_39_importlib_metadata_py3_none_any_66f342cc\",\"version\":\"3.9\"},{\"filename\":\"importlib_metadata-8.4.0.tar.gz\",\"repo\":\"pip_39_importlib_metadata_sdist_9a547d3b\",\"version\":\"3.9\"}]", - "isort": "[{\"repo\":\"pip_310_isort\",\"version\":\"3.10\"},{\"filename\":\"isort-5.11.4-py3-none-any.whl\",\"repo\":\"pip_39_isort_py3_none_any_c033fd0e\",\"version\":\"3.9\"},{\"filename\":\"isort-5.11.4.tar.gz\",\"repo\":\"pip_39_isort_sdist_6db30c5d\",\"version\":\"3.9\"}]", - "jinja2": "[{\"repo\":\"pip_310_jinja2\",\"version\":\"3.10\"},{\"filename\":\"jinja2-3.1.4-py3-none-any.whl\",\"repo\":\"pip_39_jinja2_py3_none_any_bc5dd2ab\",\"version\":\"3.9\"},{\"filename\":\"jinja2-3.1.4.tar.gz\",\"repo\":\"pip_39_jinja2_sdist_4a3aee7a\",\"version\":\"3.9\"}]", - "lazy_object_proxy": "[{\"repo\":\"pip_310_lazy_object_proxy\",\"version\":\"3.10\"},{\"filename\":\"lazy-object-proxy-1.10.0.tar.gz\",\"repo\":\"pip_39_lazy_object_proxy_sdist_78247b6d\",\"version\":\"3.9\"},{\"filename\":\"lazy_object_proxy-1.10.0-cp39-cp39-macosx_10_9_x86_64.whl\",\"repo\":\"pip_39_lazy_object_proxy_cp39_cp39_macosx_10_9_x86_64_366c32fe\",\"version\":\"3.9\"},{\"filename\":\"lazy_object_proxy-1.10.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl\",\"repo\":\"pip_39_lazy_object_proxy_cp39_cp39_manylinux_2_17_aarch64_2297f08f\",\"version\":\"3.9\"},{\"filename\":\"lazy_object_proxy-1.10.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl\",\"repo\":\"pip_39_lazy_object_proxy_cp39_cp39_manylinux_2_5_x86_64_18dd842b\",\"version\":\"3.9\"},{\"filename\":\"lazy_object_proxy-1.10.0-cp39-cp39-musllinux_1_1_aarch64.whl\",\"repo\":\"pip_39_lazy_object_proxy_cp39_cp39_musllinux_1_1_aarch64_21713819\",\"version\":\"3.9\"},{\"filename\":\"lazy_object_proxy-1.10.0-cp39-cp39-musllinux_1_1_x86_64.whl\",\"repo\":\"pip_39_lazy_object_proxy_cp39_cp39_musllinux_1_1_x86_64_9a3a87cf\",\"version\":\"3.9\"},{\"filename\":\"lazy_object_proxy-1.10.0-cp39-cp39-win_amd64.whl\",\"repo\":\"pip_39_lazy_object_proxy_cp39_cp39_win_amd64_a899b10e\",\"version\":\"3.9\"}]", - "markupsafe": "[{\"repo\":\"pip_310_markupsafe\",\"version\":\"3.10\"},{\"filename\":\"MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_universal2.whl\",\"repo\":\"pip_39_markupsafe_cp39_cp39_macosx_10_9_universal2_8023faf4\",\"version\":\"3.9\"},{\"filename\":\"MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_x86_64.whl\",\"repo\":\"pip_39_markupsafe_cp39_cp39_macosx_10_9_x86_64_6b2b5695\",\"version\":\"3.9\"},{\"filename\":\"MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl\",\"repo\":\"pip_39_markupsafe_cp39_cp39_manylinux_2_17_aarch64_9dcdfd0e\",\"version\":\"3.9\"},{\"filename\":\"MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl\",\"repo\":\"pip_39_markupsafe_cp39_cp39_manylinux_2_17_x86_64_05fb2117\",\"version\":\"3.9\"},{\"filename\":\"MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_aarch64.whl\",\"repo\":\"pip_39_markupsafe_cp39_cp39_musllinux_1_1_aarch64_ab4a0df4\",\"version\":\"3.9\"},{\"filename\":\"MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_x86_64.whl\",\"repo\":\"pip_39_markupsafe_cp39_cp39_musllinux_1_1_x86_64_0a4e4a1a\",\"version\":\"3.9\"},{\"filename\":\"MarkupSafe-2.1.3-cp39-cp39-win_amd64.whl\",\"repo\":\"pip_39_markupsafe_cp39_cp39_win_amd64_3fd4abcb\",\"version\":\"3.9\"},{\"filename\":\"MarkupSafe-2.1.3.tar.gz\",\"repo\":\"pip_39_markupsafe_sdist_af598ed3\",\"version\":\"3.9\"}]", - "mccabe": "[{\"repo\":\"pip_310_mccabe\",\"version\":\"3.10\"},{\"filename\":\"mccabe-0.7.0-py2.py3-none-any.whl\",\"repo\":\"pip_39_mccabe_py2_none_any_6c2d30ab\",\"version\":\"3.9\"},{\"filename\":\"mccabe-0.7.0.tar.gz\",\"repo\":\"pip_39_mccabe_sdist_348e0240\",\"version\":\"3.9\"}]", - "packaging": "[{\"repo\":\"pip_310_packaging\",\"version\":\"3.10\"},{\"filename\":\"packaging-23.2-py3-none-any.whl\",\"repo\":\"pip_39_packaging_py3_none_any_8c491190\",\"version\":\"3.9\"},{\"filename\":\"packaging-23.2.tar.gz\",\"repo\":\"pip_39_packaging_sdist_048fb0e9\",\"version\":\"3.9\"}]", - "pathspec": "[{\"repo\":\"pip_310_pathspec\",\"version\":\"3.10\"},{\"filename\":\"pathspec-0.10.3-py3-none-any.whl\",\"repo\":\"pip_39_pathspec_py3_none_any_3c95343a\",\"version\":\"3.9\"},{\"filename\":\"pathspec-0.10.3.tar.gz\",\"repo\":\"pip_39_pathspec_sdist_56200de4\",\"version\":\"3.9\"}]", - "platformdirs": "[{\"repo\":\"pip_310_platformdirs\",\"version\":\"3.10\"},{\"filename\":\"platformdirs-2.6.0-py3-none-any.whl\",\"repo\":\"pip_39_platformdirs_py3_none_any_1a89a123\",\"version\":\"3.9\"},{\"filename\":\"platformdirs-2.6.0.tar.gz\",\"repo\":\"pip_39_platformdirs_sdist_b46ffafa\",\"version\":\"3.9\"}]", - "pygments": "[{\"repo\":\"pip_310_pygments\",\"version\":\"3.10\"},{\"filename\":\"Pygments-2.16.1-py3-none-any.whl\",\"repo\":\"pip_39_pygments_py3_none_any_13fc09fa\",\"version\":\"3.9\"},{\"filename\":\"Pygments-2.16.1.tar.gz\",\"repo\":\"pip_39_pygments_sdist_1daff049\",\"version\":\"3.9\"}]", - "pylint": "[{\"repo\":\"pip_310_pylint\",\"version\":\"3.10\"},{\"filename\":\"pylint-2.15.9-py3-none-any.whl\",\"repo\":\"pip_39_pylint_py3_none_any_349c8cd3\",\"version\":\"3.9\"},{\"filename\":\"pylint-2.15.9.tar.gz\",\"repo\":\"pip_39_pylint_sdist_18783cca\",\"version\":\"3.9\"}]", - "pylint_print": "[{\"repo\":\"pip_310_pylint_print\",\"version\":\"3.10\"},{\"filename\":\"pylint-print-1.0.1.tar.gz\",\"repo\":\"pip_39_pylint_print_sdist_30aa207e\",\"version\":\"3.9\"},{\"filename\":\"pylint_print-1.0.1-py3-none-any.whl\",\"repo\":\"pip_39_pylint_print_py3_none_any_a2b2599e\",\"version\":\"3.9\"}]", - "python_dateutil": "[{\"repo\":\"pip_310_python_dateutil\",\"version\":\"3.10\"},{\"filename\":\"python-dateutil-2.8.2.tar.gz\",\"repo\":\"pip_39_python_dateutil_sdist_0123cacc\",\"version\":\"3.9\"},{\"filename\":\"python_dateutil-2.8.2-py2.py3-none-any.whl\",\"repo\":\"pip_39_python_dateutil_py2_none_any_961d03dc\",\"version\":\"3.9\"}]", - "python_magic": "[{\"repo\":\"pip_310_python_magic\",\"version\":\"3.10\"},{\"filename\":\"python-magic-0.4.27.tar.gz\",\"repo\":\"pip_39_python_magic_sdist_c1ba14b0\",\"version\":\"3.9\"},{\"filename\":\"python_magic-0.4.27-py2.py3-none-any.whl\",\"repo\":\"pip_39_python_magic_py2_none_any_c212960a\",\"version\":\"3.9\"}]", - "pyyaml": "[{\"repo\":\"pip_310_pyyaml\",\"version\":\"3.10\"},{\"filename\":\"PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl\",\"repo\":\"pip_39_pyyaml_cp39_cp39_macosx_10_9_x86_64_9eb6caa9\",\"version\":\"3.9\"},{\"filename\":\"PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl\",\"repo\":\"pip_39_pyyaml_cp39_cp39_macosx_11_0_arm64_c8098ddc\",\"version\":\"3.9\"},{\"filename\":\"PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl\",\"repo\":\"pip_39_pyyaml_cp39_cp39_manylinux_2_17_aarch64_5773183b\",\"version\":\"3.9\"},{\"filename\":\"PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl\",\"repo\":\"pip_39_pyyaml_cp39_cp39_manylinux_2_17_s390x_b786eecb\",\"version\":\"3.9\"},{\"filename\":\"PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl\",\"repo\":\"pip_39_pyyaml_cp39_cp39_manylinux_2_17_x86_64_bc1bf292\",\"version\":\"3.9\"},{\"filename\":\"PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl\",\"repo\":\"pip_39_pyyaml_cp39_cp39_musllinux_1_1_x86_64_04ac92ad\",\"version\":\"3.9\"},{\"filename\":\"PyYAML-6.0.1-cp39-cp39-win_amd64.whl\",\"repo\":\"pip_39_pyyaml_cp39_cp39_win_amd64_510c9dee\",\"version\":\"3.9\"},{\"filename\":\"PyYAML-6.0.1.tar.gz\",\"repo\":\"pip_39_pyyaml_sdist_bfdf460b\",\"version\":\"3.9\"}]", - "requests": "[{\"repo\":\"pip_310_requests\",\"version\":\"3.10\"},{\"filename\":\"requests-2.25.1-py2.py3-none-any.whl\",\"repo\":\"pip_39_requests_py2_none_any_c210084e\",\"version\":\"3.9\"},{\"filename\":\"requests-2.25.1.tar.gz\",\"repo\":\"pip_39_requests_sdist_27973dd4\",\"version\":\"3.9\"}]", - "s3cmd": "[{\"repo\":\"pip_310_s3cmd\",\"version\":\"3.10\"},{\"filename\":\"s3cmd-2.1.0-py2.py3-none-any.whl\",\"repo\":\"pip_39_s3cmd_py2_none_any_49cd23d5\",\"version\":\"3.9\"},{\"filename\":\"s3cmd-2.1.0.tar.gz\",\"repo\":\"pip_39_s3cmd_sdist_966b0a49\",\"version\":\"3.9\"}]", - "setuptools": "[{\"filename\":\"setuptools-65.6.3-py3-none-any.whl\",\"repo\":\"pip_39_setuptools_py3_none_any_57f6f22b\",\"version\":\"3.9\"},{\"filename\":\"setuptools-65.6.3.tar.gz\",\"repo\":\"pip_39_setuptools_sdist_a7620757\",\"version\":\"3.9\"}]", - "six": "[{\"repo\":\"pip_310_six\",\"version\":\"3.10\"},{\"filename\":\"six-1.16.0-py2.py3-none-any.whl\",\"repo\":\"pip_39_six_py2_none_any_8abb2f1d\",\"version\":\"3.9\"},{\"filename\":\"six-1.16.0.tar.gz\",\"repo\":\"pip_39_six_sdist_1e61c374\",\"version\":\"3.9\"}]", - "snowballstemmer": "[{\"repo\":\"pip_310_snowballstemmer\",\"version\":\"3.10\"},{\"filename\":\"snowballstemmer-2.2.0-py2.py3-none-any.whl\",\"repo\":\"pip_39_snowballstemmer_py2_none_any_c8e1716e\",\"version\":\"3.9\"},{\"filename\":\"snowballstemmer-2.2.0.tar.gz\",\"repo\":\"pip_39_snowballstemmer_sdist_09b16deb\",\"version\":\"3.9\"}]", - "sphinx": "[{\"repo\":\"pip_310_sphinx\",\"version\":\"3.10\"},{\"filename\":\"sphinx-7.2.6-py3-none-any.whl\",\"repo\":\"pip_39_sphinx_py3_none_any_1e09160a\",\"version\":\"3.9\"},{\"filename\":\"sphinx-7.2.6.tar.gz\",\"repo\":\"pip_39_sphinx_sdist_9a5160e1\",\"version\":\"3.9\"}]", - "sphinxcontrib_applehelp": "[{\"repo\":\"pip_310_sphinxcontrib_applehelp\",\"version\":\"3.10\"},{\"filename\":\"sphinxcontrib_applehelp-1.0.7-py3-none-any.whl\",\"repo\":\"pip_39_sphinxcontrib_applehelp_py3_none_any_094c4d56\",\"version\":\"3.9\"},{\"filename\":\"sphinxcontrib_applehelp-1.0.7.tar.gz\",\"repo\":\"pip_39_sphinxcontrib_applehelp_sdist_39fdc8d7\",\"version\":\"3.9\"}]", - "sphinxcontrib_devhelp": "[{\"repo\":\"pip_310_sphinxcontrib_devhelp\",\"version\":\"3.10\"},{\"filename\":\"sphinxcontrib_devhelp-1.0.5-py3-none-any.whl\",\"repo\":\"pip_39_sphinxcontrib_devhelp_py3_none_any_fe8009ae\",\"version\":\"3.9\"},{\"filename\":\"sphinxcontrib_devhelp-1.0.5.tar.gz\",\"repo\":\"pip_39_sphinxcontrib_devhelp_sdist_63b41e0d\",\"version\":\"3.9\"}]", - "sphinxcontrib_htmlhelp": "[{\"repo\":\"pip_310_sphinxcontrib_htmlhelp\",\"version\":\"3.10\"},{\"filename\":\"sphinxcontrib_htmlhelp-2.0.4-py3-none-any.whl\",\"repo\":\"pip_39_sphinxcontrib_htmlhelp_py3_none_any_8001661c\",\"version\":\"3.9\"},{\"filename\":\"sphinxcontrib_htmlhelp-2.0.4.tar.gz\",\"repo\":\"pip_39_sphinxcontrib_htmlhelp_sdist_6c26a118\",\"version\":\"3.9\"}]", - "sphinxcontrib_jsmath": "[{\"repo\":\"pip_310_sphinxcontrib_jsmath\",\"version\":\"3.10\"},{\"filename\":\"sphinxcontrib-jsmath-1.0.1.tar.gz\",\"repo\":\"pip_39_sphinxcontrib_jsmath_sdist_a9925e4a\",\"version\":\"3.9\"},{\"filename\":\"sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl\",\"repo\":\"pip_39_sphinxcontrib_jsmath_py2_none_any_2ec2eaeb\",\"version\":\"3.9\"}]", - "sphinxcontrib_qthelp": "[{\"repo\":\"pip_310_sphinxcontrib_qthelp\",\"version\":\"3.10\"},{\"filename\":\"sphinxcontrib_qthelp-1.0.6-py3-none-any.whl\",\"repo\":\"pip_39_sphinxcontrib_qthelp_py3_none_any_bf76886e\",\"version\":\"3.9\"},{\"filename\":\"sphinxcontrib_qthelp-1.0.6.tar.gz\",\"repo\":\"pip_39_sphinxcontrib_qthelp_sdist_62b9d1a1\",\"version\":\"3.9\"}]", - "sphinxcontrib_serializinghtml": "[{\"repo\":\"pip_310_sphinxcontrib_serializinghtml\",\"version\":\"3.10\"},{\"filename\":\"sphinxcontrib_serializinghtml-1.1.9-py3-none-any.whl\",\"repo\":\"pip_39_sphinxcontrib_serializinghtml_py3_none_any_9b36e503\",\"version\":\"3.9\"},{\"filename\":\"sphinxcontrib_serializinghtml-1.1.9.tar.gz\",\"repo\":\"pip_39_sphinxcontrib_serializinghtml_sdist_0c64ff89\",\"version\":\"3.9\"}]", - "tabulate": "[{\"repo\":\"pip_310_tabulate\",\"version\":\"3.10\"},{\"filename\":\"tabulate-0.9.0-py3-none-any.whl\",\"repo\":\"pip_39_tabulate_py3_none_any_024ca478\",\"version\":\"3.9\"},{\"filename\":\"tabulate-0.9.0.tar.gz\",\"repo\":\"pip_39_tabulate_sdist_0095b12b\",\"version\":\"3.9\"}]", - "tomli": "[{\"repo\":\"pip_310_tomli\",\"version\":\"3.10\"},{\"filename\":\"tomli-2.0.1-py3-none-any.whl\",\"repo\":\"pip_39_tomli_py3_none_any_939de3e7\",\"version\":\"3.9\"},{\"filename\":\"tomli-2.0.1.tar.gz\",\"repo\":\"pip_39_tomli_sdist_de526c12\",\"version\":\"3.9\"}]", - "tomlkit": "[{\"repo\":\"pip_310_tomlkit\",\"version\":\"3.10\"},{\"filename\":\"tomlkit-0.11.6-py3-none-any.whl\",\"repo\":\"pip_39_tomlkit_py3_none_any_07de26b0\",\"version\":\"3.9\"},{\"filename\":\"tomlkit-0.11.6.tar.gz\",\"repo\":\"pip_39_tomlkit_sdist_71b952e5\",\"version\":\"3.9\"}]", - "typing_extensions": "[{\"repo\":\"pip_310_typing_extensions\",\"version\":\"3.10\"},{\"filename\":\"typing_extensions-4.12.2-py3-none-any.whl\",\"repo\":\"pip_39_typing_extensions_py3_none_any_04e5ca03\",\"version\":\"3.9\"},{\"filename\":\"typing_extensions-4.12.2.tar.gz\",\"repo\":\"pip_39_typing_extensions_sdist_1a7ead55\",\"version\":\"3.9\"}]", - "urllib3": "[{\"repo\":\"pip_310_urllib3\",\"version\":\"3.10\"},{\"filename\":\"urllib3-1.26.18-py2.py3-none-any.whl\",\"repo\":\"pip_39_urllib3_py2_none_any_34b97092\",\"version\":\"3.9\"},{\"filename\":\"urllib3-1.26.18.tar.gz\",\"repo\":\"pip_39_urllib3_sdist_f8ecc1bb\",\"version\":\"3.9\"}]", - "websockets": "[{\"repo\":\"pip_310_websockets\",\"version\":\"3.10\"},{\"filename\":\"websockets-11.0.3-cp39-cp39-macosx_10_9_universal2.whl\",\"repo\":\"pip_39_websockets_cp39_cp39_macosx_10_9_universal2_777354ee\",\"version\":\"3.9\"},{\"filename\":\"websockets-11.0.3-cp39-cp39-macosx_10_9_x86_64.whl\",\"repo\":\"pip_39_websockets_cp39_cp39_macosx_10_9_x86_64_8c82f119\",\"version\":\"3.9\"},{\"filename\":\"websockets-11.0.3-cp39-cp39-macosx_11_0_arm64.whl\",\"repo\":\"pip_39_websockets_cp39_cp39_macosx_11_0_arm64_3580dd9c\",\"version\":\"3.9\"},{\"filename\":\"websockets-11.0.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl\",\"repo\":\"pip_39_websockets_cp39_cp39_manylinux_2_17_aarch64_6f1a3f10\",\"version\":\"3.9\"},{\"filename\":\"websockets-11.0.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl\",\"repo\":\"pip_39_websockets_cp39_cp39_manylinux_2_5_x86_64_279e5de4\",\"version\":\"3.9\"},{\"filename\":\"websockets-11.0.3-cp39-cp39-musllinux_1_1_aarch64.whl\",\"repo\":\"pip_39_websockets_cp39_cp39_musllinux_1_1_aarch64_1fdf26fa\",\"version\":\"3.9\"},{\"filename\":\"websockets-11.0.3-cp39-cp39-musllinux_1_1_x86_64.whl\",\"repo\":\"pip_39_websockets_cp39_cp39_musllinux_1_1_x86_64_97b52894\",\"version\":\"3.9\"},{\"filename\":\"websockets-11.0.3-cp39-cp39-win_amd64.whl\",\"repo\":\"pip_39_websockets_cp39_cp39_win_amd64_c792ea4e\",\"version\":\"3.9\"},{\"filename\":\"websockets-11.0.3-py3-none-any.whl\",\"repo\":\"pip_39_websockets_py3_none_any_6681ba9e\",\"version\":\"3.9\"},{\"filename\":\"websockets-11.0.3.tar.gz\",\"repo\":\"pip_39_websockets_sdist_88fc51d9\",\"version\":\"3.9\"}]", - "wheel": "[{\"repo\":\"pip_310_wheel\",\"version\":\"3.10\"},{\"filename\":\"wheel-0.40.0-py3-none-any.whl\",\"repo\":\"pip_39_wheel_py3_none_any_d236b20e\",\"version\":\"3.9\"},{\"filename\":\"wheel-0.40.0.tar.gz\",\"repo\":\"pip_39_wheel_sdist_cd1196f3\",\"version\":\"3.9\"}]", - "wrapt": "[{\"repo\":\"pip_310_wrapt\",\"version\":\"3.10\"},{\"filename\":\"wrapt-1.14.1-cp39-cp39-macosx_10_9_x86_64.whl\",\"repo\":\"pip_39_wrapt_cp39_cp39_macosx_10_9_x86_64_3232822c\",\"version\":\"3.9\"},{\"filename\":\"wrapt-1.14.1-cp39-cp39-macosx_11_0_arm64.whl\",\"repo\":\"pip_39_wrapt_cp39_cp39_macosx_11_0_arm64_988635d1\",\"version\":\"3.9\"},{\"filename\":\"wrapt-1.14.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl\",\"repo\":\"pip_39_wrapt_cp39_cp39_manylinux_2_17_aarch64_9cca3c2c\",\"version\":\"3.9\"},{\"filename\":\"wrapt-1.14.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl\",\"repo\":\"pip_39_wrapt_cp39_cp39_manylinux_2_5_x86_64_40e7bc81\",\"version\":\"3.9\"},{\"filename\":\"wrapt-1.14.1-cp39-cp39-musllinux_1_1_aarch64.whl\",\"repo\":\"pip_39_wrapt_cp39_cp39_musllinux_1_1_aarch64_b9b7a708\",\"version\":\"3.9\"},{\"filename\":\"wrapt-1.14.1-cp39-cp39-musllinux_1_1_x86_64.whl\",\"repo\":\"pip_39_wrapt_cp39_cp39_musllinux_1_1_x86_64_34aa51c4\",\"version\":\"3.9\"},{\"filename\":\"wrapt-1.14.1-cp39-cp39-win_amd64.whl\",\"repo\":\"pip_39_wrapt_cp39_cp39_win_amd64_dee60e1d\",\"version\":\"3.9\"},{\"filename\":\"wrapt-1.14.1.tar.gz\",\"repo\":\"pip_39_wrapt_sdist_380a85cf\",\"version\":\"3.9\"}]", - "yamllint": "[{\"repo\":\"pip_310_yamllint\",\"version\":\"3.10\"},{\"filename\":\"yamllint-1.28.0-py2.py3-none-any.whl\",\"repo\":\"pip_39_yamllint_py2_none_any_89bb5b5a\",\"version\":\"3.9\"},{\"filename\":\"yamllint-1.28.0.tar.gz\",\"repo\":\"pip_39_yamllint_sdist_9e3d8ddd\",\"version\":\"3.9\"}]", - "zipp": "[{\"filename\":\"zipp-3.20.0-py3-none-any.whl\",\"repo\":\"pip_39_zipp_py3_none_any_58da6168\",\"version\":\"3.9\"},{\"filename\":\"zipp-3.20.0.tar.gz\",\"repo\":\"pip_39_zipp_sdist_0145e43d\",\"version\":\"3.9\"}]" + "alabaster": "{\"pip_310_alabaster\":[{\"version\":\"3.10\"}],\"pip_39_alabaster_py3_none_any_1ee19aca\":[{\"filename\":\"alabaster-0.7.13-py3-none-any.whl\",\"version\":\"3.9\"}],\"pip_39_alabaster_sdist_a27a4a08\":[{\"filename\":\"alabaster-0.7.13.tar.gz\",\"version\":\"3.9\"}]}", + "astroid": "{\"pip_310_astroid\":[{\"version\":\"3.10\"}],\"pip_39_astroid_py3_none_any_10e0ad5f\":[{\"filename\":\"astroid-2.12.13-py3-none-any.whl\",\"version\":\"3.9\"}],\"pip_39_astroid_sdist_1493fe8b\":[{\"filename\":\"astroid-2.12.13.tar.gz\",\"version\":\"3.9\"}]}", + "babel": "{\"pip_310_babel\":[{\"version\":\"3.10\"}],\"pip_39_babel_py3_none_any_7077a498\":[{\"filename\":\"Babel-2.13.1-py3-none-any.whl\",\"version\":\"3.9\"}],\"pip_39_babel_sdist_33e0952d\":[{\"filename\":\"Babel-2.13.1.tar.gz\",\"version\":\"3.9\"}]}", + "certifi": "{\"pip_310_certifi\":[{\"version\":\"3.10\"}],\"pip_39_certifi_py3_none_any_92d60375\":[{\"filename\":\"certifi-2023.7.22-py3-none-any.whl\",\"version\":\"3.9\"}],\"pip_39_certifi_sdist_539cc1d1\":[{\"filename\":\"certifi-2023.7.22.tar.gz\",\"version\":\"3.9\"}]}", + "chardet": "{\"pip_310_chardet\":[{\"version\":\"3.10\"}],\"pip_39_chardet_py2_none_any_f864054d\":[{\"filename\":\"chardet-4.0.0-py2.py3-none-any.whl\",\"version\":\"3.9\"}],\"pip_39_chardet_sdist_0d6f53a1\":[{\"filename\":\"chardet-4.0.0.tar.gz\",\"version\":\"3.9\"}]}", + "colorama": "{\"pip_310_colorama\":[{\"version\":\"3.10\"}],\"pip_39_colorama_py2_none_any_4f1d9991\":[{\"filename\":\"colorama-0.4.6-py2.py3-none-any.whl\",\"version\":\"3.9\"}],\"pip_39_colorama_sdist_08695f5c\":[{\"filename\":\"colorama-0.4.6.tar.gz\",\"version\":\"3.9\"}]}", + "dill": "{\"pip_310_dill\":[{\"version\":\"3.10\"}],\"pip_39_dill_py3_none_any_a07ffd23\":[{\"filename\":\"dill-0.3.6-py3-none-any.whl\",\"version\":\"3.9\"}],\"pip_39_dill_sdist_e5db55f3\":[{\"filename\":\"dill-0.3.6.tar.gz\",\"version\":\"3.9\"}]}", + "docutils": "{\"pip_310_docutils\":[{\"version\":\"3.10\"}],\"pip_39_docutils_py3_none_any_96f387a2\":[{\"filename\":\"docutils-0.20.1-py3-none-any.whl\",\"version\":\"3.9\"}],\"pip_39_docutils_sdist_f08a4e27\":[{\"filename\":\"docutils-0.20.1.tar.gz\",\"version\":\"3.9\"}]}", + "idna": "{\"pip_310_idna\":[{\"version\":\"3.10\"}],\"pip_39_idna_py2_none_any_b97d804b\":[{\"filename\":\"idna-2.10-py2.py3-none-any.whl\",\"version\":\"3.9\"}],\"pip_39_idna_sdist_b307872f\":[{\"filename\":\"idna-2.10.tar.gz\",\"version\":\"3.9\"}]}", + "imagesize": "{\"pip_310_imagesize\":[{\"version\":\"3.10\"}],\"pip_39_imagesize_py2_none_any_0d8d18d0\":[{\"filename\":\"imagesize-1.4.1-py2.py3-none-any.whl\",\"version\":\"3.9\"}],\"pip_39_imagesize_sdist_69150444\":[{\"filename\":\"imagesize-1.4.1.tar.gz\",\"version\":\"3.9\"}]}", + "importlib_metadata": "{\"pip_39_importlib_metadata_py3_none_any_66f342cc\":[{\"filename\":\"importlib_metadata-8.4.0-py3-none-any.whl\",\"version\":\"3.9\"}],\"pip_39_importlib_metadata_sdist_9a547d3b\":[{\"filename\":\"importlib_metadata-8.4.0.tar.gz\",\"version\":\"3.9\"}]}", + "isort": "{\"pip_310_isort\":[{\"version\":\"3.10\"}],\"pip_39_isort_py3_none_any_c033fd0e\":[{\"filename\":\"isort-5.11.4-py3-none-any.whl\",\"version\":\"3.9\"}],\"pip_39_isort_sdist_6db30c5d\":[{\"filename\":\"isort-5.11.4.tar.gz\",\"version\":\"3.9\"}]}", + "jinja2": "{\"pip_310_jinja2\":[{\"version\":\"3.10\"}],\"pip_39_jinja2_py3_none_any_bc5dd2ab\":[{\"filename\":\"jinja2-3.1.4-py3-none-any.whl\",\"version\":\"3.9\"}],\"pip_39_jinja2_sdist_4a3aee7a\":[{\"filename\":\"jinja2-3.1.4.tar.gz\",\"version\":\"3.9\"}]}", + "lazy_object_proxy": "{\"pip_310_lazy_object_proxy\":[{\"version\":\"3.10\"}],\"pip_39_lazy_object_proxy_cp39_cp39_macosx_10_9_x86_64_366c32fe\":[{\"filename\":\"lazy_object_proxy-1.10.0-cp39-cp39-macosx_10_9_x86_64.whl\",\"version\":\"3.9\"}],\"pip_39_lazy_object_proxy_cp39_cp39_manylinux_2_17_aarch64_2297f08f\":[{\"filename\":\"lazy_object_proxy-1.10.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl\",\"version\":\"3.9\"}],\"pip_39_lazy_object_proxy_cp39_cp39_manylinux_2_5_x86_64_18dd842b\":[{\"filename\":\"lazy_object_proxy-1.10.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl\",\"version\":\"3.9\"}],\"pip_39_lazy_object_proxy_cp39_cp39_musllinux_1_1_aarch64_21713819\":[{\"filename\":\"lazy_object_proxy-1.10.0-cp39-cp39-musllinux_1_1_aarch64.whl\",\"version\":\"3.9\"}],\"pip_39_lazy_object_proxy_cp39_cp39_musllinux_1_1_x86_64_9a3a87cf\":[{\"filename\":\"lazy_object_proxy-1.10.0-cp39-cp39-musllinux_1_1_x86_64.whl\",\"version\":\"3.9\"}],\"pip_39_lazy_object_proxy_cp39_cp39_win_amd64_a899b10e\":[{\"filename\":\"lazy_object_proxy-1.10.0-cp39-cp39-win_amd64.whl\",\"version\":\"3.9\"}],\"pip_39_lazy_object_proxy_sdist_78247b6d\":[{\"filename\":\"lazy-object-proxy-1.10.0.tar.gz\",\"version\":\"3.9\"}]}", + "markupsafe": "{\"pip_310_markupsafe\":[{\"version\":\"3.10\"}],\"pip_39_markupsafe_cp39_cp39_macosx_10_9_universal2_8023faf4\":[{\"filename\":\"MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_universal2.whl\",\"version\":\"3.9\"}],\"pip_39_markupsafe_cp39_cp39_macosx_10_9_x86_64_6b2b5695\":[{\"filename\":\"MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_x86_64.whl\",\"version\":\"3.9\"}],\"pip_39_markupsafe_cp39_cp39_manylinux_2_17_aarch64_9dcdfd0e\":[{\"filename\":\"MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl\",\"version\":\"3.9\"}],\"pip_39_markupsafe_cp39_cp39_manylinux_2_17_x86_64_05fb2117\":[{\"filename\":\"MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl\",\"version\":\"3.9\"}],\"pip_39_markupsafe_cp39_cp39_musllinux_1_1_aarch64_ab4a0df4\":[{\"filename\":\"MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_aarch64.whl\",\"version\":\"3.9\"}],\"pip_39_markupsafe_cp39_cp39_musllinux_1_1_x86_64_0a4e4a1a\":[{\"filename\":\"MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_x86_64.whl\",\"version\":\"3.9\"}],\"pip_39_markupsafe_cp39_cp39_win_amd64_3fd4abcb\":[{\"filename\":\"MarkupSafe-2.1.3-cp39-cp39-win_amd64.whl\",\"version\":\"3.9\"}],\"pip_39_markupsafe_sdist_af598ed3\":[{\"filename\":\"MarkupSafe-2.1.3.tar.gz\",\"version\":\"3.9\"}]}", + "mccabe": "{\"pip_310_mccabe\":[{\"version\":\"3.10\"}],\"pip_39_mccabe_py2_none_any_6c2d30ab\":[{\"filename\":\"mccabe-0.7.0-py2.py3-none-any.whl\",\"version\":\"3.9\"}],\"pip_39_mccabe_sdist_348e0240\":[{\"filename\":\"mccabe-0.7.0.tar.gz\",\"version\":\"3.9\"}]}", + "packaging": "{\"pip_310_packaging\":[{\"version\":\"3.10\"}],\"pip_39_packaging_py3_none_any_8c491190\":[{\"filename\":\"packaging-23.2-py3-none-any.whl\",\"version\":\"3.9\"}],\"pip_39_packaging_sdist_048fb0e9\":[{\"filename\":\"packaging-23.2.tar.gz\",\"version\":\"3.9\"}]}", + "pathspec": "{\"pip_310_pathspec\":[{\"version\":\"3.10\"}],\"pip_39_pathspec_py3_none_any_3c95343a\":[{\"filename\":\"pathspec-0.10.3-py3-none-any.whl\",\"version\":\"3.9\"}],\"pip_39_pathspec_sdist_56200de4\":[{\"filename\":\"pathspec-0.10.3.tar.gz\",\"version\":\"3.9\"}]}", + "platformdirs": "{\"pip_310_platformdirs\":[{\"version\":\"3.10\"}],\"pip_39_platformdirs_py3_none_any_1a89a123\":[{\"filename\":\"platformdirs-2.6.0-py3-none-any.whl\",\"version\":\"3.9\"}],\"pip_39_platformdirs_sdist_b46ffafa\":[{\"filename\":\"platformdirs-2.6.0.tar.gz\",\"version\":\"3.9\"}]}", + "pygments": "{\"pip_310_pygments\":[{\"version\":\"3.10\"}],\"pip_39_pygments_py3_none_any_13fc09fa\":[{\"filename\":\"Pygments-2.16.1-py3-none-any.whl\",\"version\":\"3.9\"}],\"pip_39_pygments_sdist_1daff049\":[{\"filename\":\"Pygments-2.16.1.tar.gz\",\"version\":\"3.9\"}]}", + "pylint": "{\"pip_310_pylint\":[{\"version\":\"3.10\"}],\"pip_39_pylint_py3_none_any_349c8cd3\":[{\"filename\":\"pylint-2.15.9-py3-none-any.whl\",\"version\":\"3.9\"}],\"pip_39_pylint_sdist_18783cca\":[{\"filename\":\"pylint-2.15.9.tar.gz\",\"version\":\"3.9\"}]}", + "pylint_print": "{\"pip_310_pylint_print\":[{\"version\":\"3.10\"}],\"pip_39_pylint_print_py3_none_any_a2b2599e\":[{\"filename\":\"pylint_print-1.0.1-py3-none-any.whl\",\"version\":\"3.9\"}],\"pip_39_pylint_print_sdist_30aa207e\":[{\"filename\":\"pylint-print-1.0.1.tar.gz\",\"version\":\"3.9\"}]}", + "python_dateutil": "{\"pip_310_python_dateutil\":[{\"version\":\"3.10\"}],\"pip_39_python_dateutil_py2_none_any_961d03dc\":[{\"filename\":\"python_dateutil-2.8.2-py2.py3-none-any.whl\",\"version\":\"3.9\"}],\"pip_39_python_dateutil_sdist_0123cacc\":[{\"filename\":\"python-dateutil-2.8.2.tar.gz\",\"version\":\"3.9\"}]}", + "python_magic": "{\"pip_310_python_magic\":[{\"version\":\"3.10\"}],\"pip_39_python_magic_py2_none_any_c212960a\":[{\"filename\":\"python_magic-0.4.27-py2.py3-none-any.whl\",\"version\":\"3.9\"}],\"pip_39_python_magic_sdist_c1ba14b0\":[{\"filename\":\"python-magic-0.4.27.tar.gz\",\"version\":\"3.9\"}]}", + "pyyaml": "{\"pip_310_pyyaml\":[{\"version\":\"3.10\"}],\"pip_39_pyyaml_cp39_cp39_macosx_10_9_x86_64_9eb6caa9\":[{\"filename\":\"PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl\",\"version\":\"3.9\"}],\"pip_39_pyyaml_cp39_cp39_macosx_11_0_arm64_c8098ddc\":[{\"filename\":\"PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl\",\"version\":\"3.9\"}],\"pip_39_pyyaml_cp39_cp39_manylinux_2_17_aarch64_5773183b\":[{\"filename\":\"PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl\",\"version\":\"3.9\"}],\"pip_39_pyyaml_cp39_cp39_manylinux_2_17_s390x_b786eecb\":[{\"filename\":\"PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl\",\"version\":\"3.9\"}],\"pip_39_pyyaml_cp39_cp39_manylinux_2_17_x86_64_bc1bf292\":[{\"filename\":\"PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl\",\"version\":\"3.9\"}],\"pip_39_pyyaml_cp39_cp39_musllinux_1_1_x86_64_04ac92ad\":[{\"filename\":\"PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl\",\"version\":\"3.9\"}],\"pip_39_pyyaml_cp39_cp39_win_amd64_510c9dee\":[{\"filename\":\"PyYAML-6.0.1-cp39-cp39-win_amd64.whl\",\"version\":\"3.9\"}],\"pip_39_pyyaml_sdist_bfdf460b\":[{\"filename\":\"PyYAML-6.0.1.tar.gz\",\"version\":\"3.9\"}]}", + "requests": "{\"pip_310_requests\":[{\"version\":\"3.10\"}],\"pip_39_requests_py2_none_any_c210084e\":[{\"filename\":\"requests-2.25.1-py2.py3-none-any.whl\",\"version\":\"3.9\"}],\"pip_39_requests_sdist_27973dd4\":[{\"filename\":\"requests-2.25.1.tar.gz\",\"version\":\"3.9\"}]}", + "s3cmd": "{\"pip_310_s3cmd\":[{\"version\":\"3.10\"}],\"pip_39_s3cmd_py2_none_any_49cd23d5\":[{\"filename\":\"s3cmd-2.1.0-py2.py3-none-any.whl\",\"version\":\"3.9\"}],\"pip_39_s3cmd_sdist_966b0a49\":[{\"filename\":\"s3cmd-2.1.0.tar.gz\",\"version\":\"3.9\"}]}", + "setuptools": "{\"pip_39_setuptools_py3_none_any_57f6f22b\":[{\"filename\":\"setuptools-65.6.3-py3-none-any.whl\",\"version\":\"3.9\"}],\"pip_39_setuptools_sdist_a7620757\":[{\"filename\":\"setuptools-65.6.3.tar.gz\",\"version\":\"3.9\"}]}", + "six": "{\"pip_310_six\":[{\"version\":\"3.10\"}],\"pip_39_six_py2_none_any_8abb2f1d\":[{\"filename\":\"six-1.16.0-py2.py3-none-any.whl\",\"version\":\"3.9\"}],\"pip_39_six_sdist_1e61c374\":[{\"filename\":\"six-1.16.0.tar.gz\",\"version\":\"3.9\"}]}", + "snowballstemmer": "{\"pip_310_snowballstemmer\":[{\"version\":\"3.10\"}],\"pip_39_snowballstemmer_py2_none_any_c8e1716e\":[{\"filename\":\"snowballstemmer-2.2.0-py2.py3-none-any.whl\",\"version\":\"3.9\"}],\"pip_39_snowballstemmer_sdist_09b16deb\":[{\"filename\":\"snowballstemmer-2.2.0.tar.gz\",\"version\":\"3.9\"}]}", + "sphinx": "{\"pip_310_sphinx\":[{\"version\":\"3.10\"}],\"pip_39_sphinx_py3_none_any_1e09160a\":[{\"filename\":\"sphinx-7.2.6-py3-none-any.whl\",\"version\":\"3.9\"}],\"pip_39_sphinx_sdist_9a5160e1\":[{\"filename\":\"sphinx-7.2.6.tar.gz\",\"version\":\"3.9\"}]}", + "sphinxcontrib_applehelp": "{\"pip_310_sphinxcontrib_applehelp\":[{\"version\":\"3.10\"}],\"pip_39_sphinxcontrib_applehelp_py3_none_any_094c4d56\":[{\"filename\":\"sphinxcontrib_applehelp-1.0.7-py3-none-any.whl\",\"version\":\"3.9\"}],\"pip_39_sphinxcontrib_applehelp_sdist_39fdc8d7\":[{\"filename\":\"sphinxcontrib_applehelp-1.0.7.tar.gz\",\"version\":\"3.9\"}]}", + "sphinxcontrib_devhelp": "{\"pip_310_sphinxcontrib_devhelp\":[{\"version\":\"3.10\"}],\"pip_39_sphinxcontrib_devhelp_py3_none_any_fe8009ae\":[{\"filename\":\"sphinxcontrib_devhelp-1.0.5-py3-none-any.whl\",\"version\":\"3.9\"}],\"pip_39_sphinxcontrib_devhelp_sdist_63b41e0d\":[{\"filename\":\"sphinxcontrib_devhelp-1.0.5.tar.gz\",\"version\":\"3.9\"}]}", + "sphinxcontrib_htmlhelp": "{\"pip_310_sphinxcontrib_htmlhelp\":[{\"version\":\"3.10\"}],\"pip_39_sphinxcontrib_htmlhelp_py3_none_any_8001661c\":[{\"filename\":\"sphinxcontrib_htmlhelp-2.0.4-py3-none-any.whl\",\"version\":\"3.9\"}],\"pip_39_sphinxcontrib_htmlhelp_sdist_6c26a118\":[{\"filename\":\"sphinxcontrib_htmlhelp-2.0.4.tar.gz\",\"version\":\"3.9\"}]}", + "sphinxcontrib_jsmath": "{\"pip_310_sphinxcontrib_jsmath\":[{\"version\":\"3.10\"}],\"pip_39_sphinxcontrib_jsmath_py2_none_any_2ec2eaeb\":[{\"filename\":\"sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl\",\"version\":\"3.9\"}],\"pip_39_sphinxcontrib_jsmath_sdist_a9925e4a\":[{\"filename\":\"sphinxcontrib-jsmath-1.0.1.tar.gz\",\"version\":\"3.9\"}]}", + "sphinxcontrib_qthelp": "{\"pip_310_sphinxcontrib_qthelp\":[{\"version\":\"3.10\"}],\"pip_39_sphinxcontrib_qthelp_py3_none_any_bf76886e\":[{\"filename\":\"sphinxcontrib_qthelp-1.0.6-py3-none-any.whl\",\"version\":\"3.9\"}],\"pip_39_sphinxcontrib_qthelp_sdist_62b9d1a1\":[{\"filename\":\"sphinxcontrib_qthelp-1.0.6.tar.gz\",\"version\":\"3.9\"}]}", + "sphinxcontrib_serializinghtml": "{\"pip_310_sphinxcontrib_serializinghtml\":[{\"version\":\"3.10\"}],\"pip_39_sphinxcontrib_serializinghtml_py3_none_any_9b36e503\":[{\"filename\":\"sphinxcontrib_serializinghtml-1.1.9-py3-none-any.whl\",\"version\":\"3.9\"}],\"pip_39_sphinxcontrib_serializinghtml_sdist_0c64ff89\":[{\"filename\":\"sphinxcontrib_serializinghtml-1.1.9.tar.gz\",\"version\":\"3.9\"}]}", + "tabulate": "{\"pip_310_tabulate\":[{\"version\":\"3.10\"}],\"pip_39_tabulate_py3_none_any_024ca478\":[{\"filename\":\"tabulate-0.9.0-py3-none-any.whl\",\"version\":\"3.9\"}],\"pip_39_tabulate_sdist_0095b12b\":[{\"filename\":\"tabulate-0.9.0.tar.gz\",\"version\":\"3.9\"}]}", + "tomli": "{\"pip_310_tomli\":[{\"version\":\"3.10\"}],\"pip_39_tomli_py3_none_any_939de3e7\":[{\"filename\":\"tomli-2.0.1-py3-none-any.whl\",\"version\":\"3.9\"}],\"pip_39_tomli_sdist_de526c12\":[{\"filename\":\"tomli-2.0.1.tar.gz\",\"version\":\"3.9\"}]}", + "tomlkit": "{\"pip_310_tomlkit\":[{\"version\":\"3.10\"}],\"pip_39_tomlkit_py3_none_any_07de26b0\":[{\"filename\":\"tomlkit-0.11.6-py3-none-any.whl\",\"version\":\"3.9\"}],\"pip_39_tomlkit_sdist_71b952e5\":[{\"filename\":\"tomlkit-0.11.6.tar.gz\",\"version\":\"3.9\"}]}", + "typing_extensions": "{\"pip_310_typing_extensions\":[{\"version\":\"3.10\"}],\"pip_39_typing_extensions_py3_none_any_04e5ca03\":[{\"filename\":\"typing_extensions-4.12.2-py3-none-any.whl\",\"version\":\"3.9\"}],\"pip_39_typing_extensions_sdist_1a7ead55\":[{\"filename\":\"typing_extensions-4.12.2.tar.gz\",\"version\":\"3.9\"}]}", + "urllib3": "{\"pip_310_urllib3\":[{\"version\":\"3.10\"}],\"pip_39_urllib3_py2_none_any_34b97092\":[{\"filename\":\"urllib3-1.26.18-py2.py3-none-any.whl\",\"version\":\"3.9\"}],\"pip_39_urllib3_sdist_f8ecc1bb\":[{\"filename\":\"urllib3-1.26.18.tar.gz\",\"version\":\"3.9\"}]}", + "websockets": "{\"pip_310_websockets\":[{\"version\":\"3.10\"}],\"pip_39_websockets_cp39_cp39_macosx_10_9_universal2_777354ee\":[{\"filename\":\"websockets-11.0.3-cp39-cp39-macosx_10_9_universal2.whl\",\"version\":\"3.9\"}],\"pip_39_websockets_cp39_cp39_macosx_10_9_x86_64_8c82f119\":[{\"filename\":\"websockets-11.0.3-cp39-cp39-macosx_10_9_x86_64.whl\",\"version\":\"3.9\"}],\"pip_39_websockets_cp39_cp39_macosx_11_0_arm64_3580dd9c\":[{\"filename\":\"websockets-11.0.3-cp39-cp39-macosx_11_0_arm64.whl\",\"version\":\"3.9\"}],\"pip_39_websockets_cp39_cp39_manylinux_2_17_aarch64_6f1a3f10\":[{\"filename\":\"websockets-11.0.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl\",\"version\":\"3.9\"}],\"pip_39_websockets_cp39_cp39_manylinux_2_5_x86_64_279e5de4\":[{\"filename\":\"websockets-11.0.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl\",\"version\":\"3.9\"}],\"pip_39_websockets_cp39_cp39_musllinux_1_1_aarch64_1fdf26fa\":[{\"filename\":\"websockets-11.0.3-cp39-cp39-musllinux_1_1_aarch64.whl\",\"version\":\"3.9\"}],\"pip_39_websockets_cp39_cp39_musllinux_1_1_x86_64_97b52894\":[{\"filename\":\"websockets-11.0.3-cp39-cp39-musllinux_1_1_x86_64.whl\",\"version\":\"3.9\"}],\"pip_39_websockets_cp39_cp39_win_amd64_c792ea4e\":[{\"filename\":\"websockets-11.0.3-cp39-cp39-win_amd64.whl\",\"version\":\"3.9\"}],\"pip_39_websockets_py3_none_any_6681ba9e\":[{\"filename\":\"websockets-11.0.3-py3-none-any.whl\",\"version\":\"3.9\"}],\"pip_39_websockets_sdist_88fc51d9\":[{\"filename\":\"websockets-11.0.3.tar.gz\",\"version\":\"3.9\"}]}", + "wheel": "{\"pip_310_wheel\":[{\"version\":\"3.10\"}],\"pip_39_wheel_py3_none_any_d236b20e\":[{\"filename\":\"wheel-0.40.0-py3-none-any.whl\",\"version\":\"3.9\"}],\"pip_39_wheel_sdist_cd1196f3\":[{\"filename\":\"wheel-0.40.0.tar.gz\",\"version\":\"3.9\"}]}", + "wrapt": "{\"pip_310_wrapt\":[{\"version\":\"3.10\"}],\"pip_39_wrapt_cp39_cp39_macosx_10_9_x86_64_3232822c\":[{\"filename\":\"wrapt-1.14.1-cp39-cp39-macosx_10_9_x86_64.whl\",\"version\":\"3.9\"}],\"pip_39_wrapt_cp39_cp39_macosx_11_0_arm64_988635d1\":[{\"filename\":\"wrapt-1.14.1-cp39-cp39-macosx_11_0_arm64.whl\",\"version\":\"3.9\"}],\"pip_39_wrapt_cp39_cp39_manylinux_2_17_aarch64_9cca3c2c\":[{\"filename\":\"wrapt-1.14.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl\",\"version\":\"3.9\"}],\"pip_39_wrapt_cp39_cp39_manylinux_2_5_x86_64_40e7bc81\":[{\"filename\":\"wrapt-1.14.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl\",\"version\":\"3.9\"}],\"pip_39_wrapt_cp39_cp39_musllinux_1_1_aarch64_b9b7a708\":[{\"filename\":\"wrapt-1.14.1-cp39-cp39-musllinux_1_1_aarch64.whl\",\"version\":\"3.9\"}],\"pip_39_wrapt_cp39_cp39_musllinux_1_1_x86_64_34aa51c4\":[{\"filename\":\"wrapt-1.14.1-cp39-cp39-musllinux_1_1_x86_64.whl\",\"version\":\"3.9\"}],\"pip_39_wrapt_cp39_cp39_win_amd64_dee60e1d\":[{\"filename\":\"wrapt-1.14.1-cp39-cp39-win_amd64.whl\",\"version\":\"3.9\"}],\"pip_39_wrapt_sdist_380a85cf\":[{\"filename\":\"wrapt-1.14.1.tar.gz\",\"version\":\"3.9\"}]}", + "yamllint": "{\"pip_310_yamllint\":[{\"version\":\"3.10\"}],\"pip_39_yamllint_py2_none_any_89bb5b5a\":[{\"filename\":\"yamllint-1.28.0-py2.py3-none-any.whl\",\"version\":\"3.9\"}],\"pip_39_yamllint_sdist_9e3d8ddd\":[{\"filename\":\"yamllint-1.28.0.tar.gz\",\"version\":\"3.9\"}]}", + "zipp": "{\"pip_39_zipp_py3_none_any_58da6168\":[{\"filename\":\"zipp-3.20.0-py3-none-any.whl\",\"version\":\"3.9\"}],\"pip_39_zipp_sdist_0145e43d\":[{\"filename\":\"zipp-3.20.0.tar.gz\",\"version\":\"3.9\"}]}" }, "packages": [ "alabaster", @@ -6867,8 +6867,8 @@ "repo_name": "pip_deps", "extra_hub_aliases": {}, "whl_map": { - "numpy": "[{\"repo\":\"pip_deps_310_numpy\",\"version\":\"3.10\"},{\"repo\":\"pip_deps_311_numpy\",\"version\":\"3.11\"},{\"repo\":\"pip_deps_312_numpy\",\"version\":\"3.12\"},{\"repo\":\"pip_deps_38_numpy\",\"version\":\"3.8\"},{\"repo\":\"pip_deps_39_numpy\",\"version\":\"3.9\"}]", - "setuptools": "[{\"repo\":\"pip_deps_310_setuptools\",\"version\":\"3.10\"},{\"repo\":\"pip_deps_311_setuptools\",\"version\":\"3.11\"},{\"repo\":\"pip_deps_312_setuptools\",\"version\":\"3.12\"},{\"repo\":\"pip_deps_38_setuptools\",\"version\":\"3.8\"},{\"repo\":\"pip_deps_39_setuptools\",\"version\":\"3.9\"}]" + "numpy": "{\"pip_deps_310_numpy\":[{\"version\":\"3.10\"}],\"pip_deps_311_numpy\":[{\"version\":\"3.11\"}],\"pip_deps_312_numpy\":[{\"version\":\"3.12\"}],\"pip_deps_38_numpy\":[{\"version\":\"3.8\"}],\"pip_deps_39_numpy\":[{\"version\":\"3.9\"}]}", + "setuptools": "{\"pip_deps_310_setuptools\":[{\"version\":\"3.10\"}],\"pip_deps_311_setuptools\":[{\"version\":\"3.11\"}],\"pip_deps_312_setuptools\":[{\"version\":\"3.12\"}],\"pip_deps_38_setuptools\":[{\"version\":\"3.8\"}],\"pip_deps_39_setuptools\":[{\"version\":\"3.9\"}]}" }, "packages": [ "numpy", @@ -6884,8 +6884,8 @@ "repo_name": "rules_fuzzing_py_deps", "extra_hub_aliases": {}, "whl_map": { - "absl_py": "[{\"repo\":\"rules_fuzzing_py_deps_310_absl_py\",\"version\":\"3.10\"},{\"repo\":\"rules_fuzzing_py_deps_311_absl_py\",\"version\":\"3.11\"},{\"repo\":\"rules_fuzzing_py_deps_312_absl_py\",\"version\":\"3.12\"},{\"repo\":\"rules_fuzzing_py_deps_38_absl_py\",\"version\":\"3.8\"},{\"repo\":\"rules_fuzzing_py_deps_39_absl_py\",\"version\":\"3.9\"}]", - "six": "[{\"repo\":\"rules_fuzzing_py_deps_310_six\",\"version\":\"3.10\"},{\"repo\":\"rules_fuzzing_py_deps_311_six\",\"version\":\"3.11\"},{\"repo\":\"rules_fuzzing_py_deps_312_six\",\"version\":\"3.12\"},{\"repo\":\"rules_fuzzing_py_deps_38_six\",\"version\":\"3.8\"},{\"repo\":\"rules_fuzzing_py_deps_39_six\",\"version\":\"3.9\"}]" + "absl_py": "{\"rules_fuzzing_py_deps_310_absl_py\":[{\"version\":\"3.10\"}],\"rules_fuzzing_py_deps_311_absl_py\":[{\"version\":\"3.11\"}],\"rules_fuzzing_py_deps_312_absl_py\":[{\"version\":\"3.12\"}],\"rules_fuzzing_py_deps_38_absl_py\":[{\"version\":\"3.8\"}],\"rules_fuzzing_py_deps_39_absl_py\":[{\"version\":\"3.9\"}]}", + "six": "{\"rules_fuzzing_py_deps_310_six\":[{\"version\":\"3.10\"}],\"rules_fuzzing_py_deps_311_six\":[{\"version\":\"3.11\"}],\"rules_fuzzing_py_deps_312_six\":[{\"version\":\"3.12\"}],\"rules_fuzzing_py_deps_38_six\":[{\"version\":\"3.8\"}],\"rules_fuzzing_py_deps_39_six\":[{\"version\":\"3.9\"}]}" }, "packages": [ "absl_py", @@ -7035,7 +7035,7 @@ }, "@@rules_python~//python/private/pypi:pip.bzl%pip_internal": { "general": { - "bzlTransitiveDigest": "ltVKFX5LXgwSpZtjuyF02xZspYIWHEFmpxmzvnyMbQ8=", + "bzlTransitiveDigest": "B67ozliTSCjdGS4zjmFP7NmOPBeoLELYslQaEaQLr78=", "usagesDigest": "/lZXl/ZgP+u5PE8WkeWTyYBsvX9XQWFn1antj5qrBzQ=", "recordedFileInputs": { "@@rules_python~//tools/publish/requirements_linux.txt": "8175b4c8df50ae2f22d1706961884beeb54e7da27bd2447018314a175981997d", @@ -9426,36 +9426,36 @@ "repo_name": "rules_python_publish_deps", "extra_hub_aliases": {}, "whl_map": { - "backports_tarfile": "[{\"filename\":\"backports.tarfile-1.2.0-py3-none-any.whl\",\"repo\":\"rules_python_publish_deps_311_backports_tarfile_py3_none_any_77e284d7\",\"version\":\"3.11\"},{\"filename\":\"backports_tarfile-1.2.0.tar.gz\",\"repo\":\"rules_python_publish_deps_311_backports_tarfile_sdist_d75e02c2\",\"version\":\"3.11\"}]", - "certifi": "[{\"filename\":\"certifi-2024.8.30-py3-none-any.whl\",\"repo\":\"rules_python_publish_deps_311_certifi_py3_none_any_922820b5\",\"version\":\"3.11\"},{\"filename\":\"certifi-2024.8.30.tar.gz\",\"repo\":\"rules_python_publish_deps_311_certifi_sdist_bec941d2\",\"version\":\"3.11\"}]", - "cffi": "[{\"filename\":\"cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl\",\"repo\":\"rules_python_publish_deps_311_cffi_cp311_cp311_manylinux_2_17_aarch64_a1ed2dd2\",\"version\":\"3.11\"},{\"filename\":\"cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl\",\"repo\":\"rules_python_publish_deps_311_cffi_cp311_cp311_manylinux_2_17_ppc64le_46bf4316\",\"version\":\"3.11\"},{\"filename\":\"cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl\",\"repo\":\"rules_python_publish_deps_311_cffi_cp311_cp311_manylinux_2_17_s390x_a24ed04c\",\"version\":\"3.11\"},{\"filename\":\"cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl\",\"repo\":\"rules_python_publish_deps_311_cffi_cp311_cp311_manylinux_2_17_x86_64_610faea7\",\"version\":\"3.11\"},{\"filename\":\"cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl\",\"repo\":\"rules_python_publish_deps_311_cffi_cp311_cp311_musllinux_1_1_aarch64_a9b15d49\",\"version\":\"3.11\"},{\"filename\":\"cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl\",\"repo\":\"rules_python_publish_deps_311_cffi_cp311_cp311_musllinux_1_1_x86_64_fc48c783\",\"version\":\"3.11\"},{\"filename\":\"cffi-1.17.1.tar.gz\",\"repo\":\"rules_python_publish_deps_311_cffi_sdist_1c39c601\",\"version\":\"3.11\"}]", - "charset_normalizer": "[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_universal2.whl\",\"repo\":\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_macosx_10_9_universal2_0d99dd8f\",\"version\":\"3.11\"},{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_x86_64.whl\",\"repo\":\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_macosx_10_9_x86_64_c57516e5\",\"version\":\"3.11\"},{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-macosx_11_0_arm64.whl\",\"repo\":\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_macosx_11_0_arm64_6dba5d19\",\"version\":\"3.11\"},{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl\",\"repo\":\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_manylinux_2_17_aarch64_bf4475b8\",\"version\":\"3.11\"},{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl\",\"repo\":\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_manylinux_2_17_ppc64le_ce031db0\",\"version\":\"3.11\"},{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl\",\"repo\":\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_manylinux_2_17_s390x_8ff4e7cd\",\"version\":\"3.11\"},{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl\",\"repo\":\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_manylinux_2_17_x86_64_3710a975\",\"version\":\"3.11\"},{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_aarch64.whl\",\"repo\":\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_musllinux_1_2_aarch64_47334db7\",\"version\":\"3.11\"},{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_ppc64le.whl\",\"repo\":\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_musllinux_1_2_ppc64le_f1a2f519\",\"version\":\"3.11\"},{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_s390x.whl\",\"repo\":\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_musllinux_1_2_s390x_63bc5c4a\",\"version\":\"3.11\"},{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_x86_64.whl\",\"repo\":\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_musllinux_1_2_x86_64_bcb4f8ea\",\"version\":\"3.11\"},{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-win_amd64.whl\",\"repo\":\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_win_amd64_cee4373f\",\"version\":\"3.11\"},{\"filename\":\"charset_normalizer-3.4.0-py3-none-any.whl\",\"repo\":\"rules_python_publish_deps_311_charset_normalizer_py3_none_any_fe9f97fe\",\"version\":\"3.11\"},{\"filename\":\"charset_normalizer-3.4.0.tar.gz\",\"repo\":\"rules_python_publish_deps_311_charset_normalizer_sdist_223217c3\",\"version\":\"3.11\"}]", - "cryptography": "[{\"filename\":\"cryptography-43.0.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl\",\"repo\":\"rules_python_publish_deps_311_cryptography_cp39_abi3_manylinux_2_17_aarch64_846da004\",\"version\":\"3.11\"},{\"filename\":\"cryptography-43.0.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl\",\"repo\":\"rules_python_publish_deps_311_cryptography_cp39_abi3_manylinux_2_17_x86_64_0f996e72\",\"version\":\"3.11\"},{\"filename\":\"cryptography-43.0.3-cp39-abi3-manylinux_2_28_aarch64.whl\",\"repo\":\"rules_python_publish_deps_311_cryptography_cp39_abi3_manylinux_2_28_aarch64_f7b178f1\",\"version\":\"3.11\"},{\"filename\":\"cryptography-43.0.3-cp39-abi3-manylinux_2_28_x86_64.whl\",\"repo\":\"rules_python_publish_deps_311_cryptography_cp39_abi3_manylinux_2_28_x86_64_c2e6fc39\",\"version\":\"3.11\"},{\"filename\":\"cryptography-43.0.3-cp39-abi3-musllinux_1_2_aarch64.whl\",\"repo\":\"rules_python_publish_deps_311_cryptography_cp39_abi3_musllinux_1_2_aarch64_e1be4655\",\"version\":\"3.11\"},{\"filename\":\"cryptography-43.0.3-cp39-abi3-musllinux_1_2_x86_64.whl\",\"repo\":\"rules_python_publish_deps_311_cryptography_cp39_abi3_musllinux_1_2_x86_64_df6b6c6d\",\"version\":\"3.11\"},{\"filename\":\"cryptography-43.0.3.tar.gz\",\"repo\":\"rules_python_publish_deps_311_cryptography_sdist_315b9001\",\"version\":\"3.11\"}]", - "docutils": "[{\"filename\":\"docutils-0.21.2-py3-none-any.whl\",\"repo\":\"rules_python_publish_deps_311_docutils_py3_none_any_dafca5b9\",\"version\":\"3.11\"},{\"filename\":\"docutils-0.21.2.tar.gz\",\"repo\":\"rules_python_publish_deps_311_docutils_sdist_3a6b1873\",\"version\":\"3.11\"}]", - "idna": "[{\"filename\":\"idna-3.10-py3-none-any.whl\",\"repo\":\"rules_python_publish_deps_311_idna_py3_none_any_946d195a\",\"version\":\"3.11\"},{\"filename\":\"idna-3.10.tar.gz\",\"repo\":\"rules_python_publish_deps_311_idna_sdist_12f65c9b\",\"version\":\"3.11\"}]", - "importlib_metadata": "[{\"filename\":\"importlib_metadata-8.5.0-py3-none-any.whl\",\"repo\":\"rules_python_publish_deps_311_importlib_metadata_py3_none_any_45e54197\",\"version\":\"3.11\"},{\"filename\":\"importlib_metadata-8.5.0.tar.gz\",\"repo\":\"rules_python_publish_deps_311_importlib_metadata_sdist_71522656\",\"version\":\"3.11\"}]", - "jaraco_classes": "[{\"filename\":\"jaraco.classes-3.4.0-py3-none-any.whl\",\"repo\":\"rules_python_publish_deps_311_jaraco_classes_py3_none_any_f662826b\",\"version\":\"3.11\"},{\"filename\":\"jaraco.classes-3.4.0.tar.gz\",\"repo\":\"rules_python_publish_deps_311_jaraco_classes_sdist_47a024b5\",\"version\":\"3.11\"}]", - "jaraco_context": "[{\"filename\":\"jaraco.context-6.0.1-py3-none-any.whl\",\"repo\":\"rules_python_publish_deps_311_jaraco_context_py3_none_any_f797fc48\",\"version\":\"3.11\"},{\"filename\":\"jaraco_context-6.0.1.tar.gz\",\"repo\":\"rules_python_publish_deps_311_jaraco_context_sdist_9bae4ea5\",\"version\":\"3.11\"}]", - "jaraco_functools": "[{\"filename\":\"jaraco.functools-4.1.0-py3-none-any.whl\",\"repo\":\"rules_python_publish_deps_311_jaraco_functools_py3_none_any_ad159f13\",\"version\":\"3.11\"},{\"filename\":\"jaraco_functools-4.1.0.tar.gz\",\"repo\":\"rules_python_publish_deps_311_jaraco_functools_sdist_70f7e0e2\",\"version\":\"3.11\"}]", - "jeepney": "[{\"filename\":\"jeepney-0.8.0-py3-none-any.whl\",\"repo\":\"rules_python_publish_deps_311_jeepney_py3_none_any_c0a454ad\",\"version\":\"3.11\"},{\"filename\":\"jeepney-0.8.0.tar.gz\",\"repo\":\"rules_python_publish_deps_311_jeepney_sdist_5efe48d2\",\"version\":\"3.11\"}]", - "keyring": "[{\"filename\":\"keyring-25.4.1-py3-none-any.whl\",\"repo\":\"rules_python_publish_deps_311_keyring_py3_none_any_5426f817\",\"version\":\"3.11\"},{\"filename\":\"keyring-25.4.1.tar.gz\",\"repo\":\"rules_python_publish_deps_311_keyring_sdist_b07ebc55\",\"version\":\"3.11\"}]", - "markdown_it_py": "[{\"filename\":\"markdown-it-py-3.0.0.tar.gz\",\"repo\":\"rules_python_publish_deps_311_markdown_it_py_sdist_e3f60a94\",\"version\":\"3.11\"},{\"filename\":\"markdown_it_py-3.0.0-py3-none-any.whl\",\"repo\":\"rules_python_publish_deps_311_markdown_it_py_py3_none_any_35521684\",\"version\":\"3.11\"}]", - "mdurl": "[{\"filename\":\"mdurl-0.1.2-py3-none-any.whl\",\"repo\":\"rules_python_publish_deps_311_mdurl_py3_none_any_84008a41\",\"version\":\"3.11\"},{\"filename\":\"mdurl-0.1.2.tar.gz\",\"repo\":\"rules_python_publish_deps_311_mdurl_sdist_bb413d29\",\"version\":\"3.11\"}]", - "more_itertools": "[{\"filename\":\"more-itertools-10.5.0.tar.gz\",\"repo\":\"rules_python_publish_deps_311_more_itertools_sdist_5482bfef\",\"version\":\"3.11\"},{\"filename\":\"more_itertools-10.5.0-py3-none-any.whl\",\"repo\":\"rules_python_publish_deps_311_more_itertools_py3_none_any_037b0d32\",\"version\":\"3.11\"}]", - "nh3": "[{\"filename\":\"nh3-0.2.18-cp37-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl\",\"repo\":\"rules_python_publish_deps_311_nh3_cp37_abi3_macosx_10_12_x86_64_14c5a72e\",\"version\":\"3.11\"},{\"filename\":\"nh3-0.2.18-cp37-abi3-macosx_10_12_x86_64.whl\",\"repo\":\"rules_python_publish_deps_311_nh3_cp37_abi3_macosx_10_12_x86_64_7b7c2a3c\",\"version\":\"3.11\"},{\"filename\":\"nh3-0.2.18-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl\",\"repo\":\"rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_aarch64_42c64511\",\"version\":\"3.11\"},{\"filename\":\"nh3-0.2.18-cp37-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl\",\"repo\":\"rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_armv7l_0411beb0\",\"version\":\"3.11\"},{\"filename\":\"nh3-0.2.18-cp37-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl\",\"repo\":\"rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_ppc64_5f36b271\",\"version\":\"3.11\"},{\"filename\":\"nh3-0.2.18-cp37-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl\",\"repo\":\"rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_ppc64le_34c03fa7\",\"version\":\"3.11\"},{\"filename\":\"nh3-0.2.18-cp37-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl\",\"repo\":\"rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_s390x_19aaba96\",\"version\":\"3.11\"},{\"filename\":\"nh3-0.2.18-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl\",\"repo\":\"rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_x86_64_de3ceed6\",\"version\":\"3.11\"},{\"filename\":\"nh3-0.2.18-cp37-abi3-musllinux_1_2_aarch64.whl\",\"repo\":\"rules_python_publish_deps_311_nh3_cp37_abi3_musllinux_1_2_aarch64_f0eca9ca\",\"version\":\"3.11\"},{\"filename\":\"nh3-0.2.18-cp37-abi3-musllinux_1_2_armv7l.whl\",\"repo\":\"rules_python_publish_deps_311_nh3_cp37_abi3_musllinux_1_2_armv7l_3a157ab1\",\"version\":\"3.11\"},{\"filename\":\"nh3-0.2.18-cp37-abi3-musllinux_1_2_x86_64.whl\",\"repo\":\"rules_python_publish_deps_311_nh3_cp37_abi3_musllinux_1_2_x86_64_36c95d4b\",\"version\":\"3.11\"},{\"filename\":\"nh3-0.2.18-cp37-abi3-win_amd64.whl\",\"repo\":\"rules_python_publish_deps_311_nh3_cp37_abi3_win_amd64_8ce0f819\",\"version\":\"3.11\"},{\"filename\":\"nh3-0.2.18.tar.gz\",\"repo\":\"rules_python_publish_deps_311_nh3_sdist_94a16692\",\"version\":\"3.11\"}]", - "pkginfo": "[{\"filename\":\"pkginfo-1.10.0-py3-none-any.whl\",\"repo\":\"rules_python_publish_deps_311_pkginfo_py3_none_any_889a6da2\",\"version\":\"3.11\"},{\"filename\":\"pkginfo-1.10.0.tar.gz\",\"repo\":\"rules_python_publish_deps_311_pkginfo_sdist_5df73835\",\"version\":\"3.11\"}]", - "pycparser": "[{\"filename\":\"pycparser-2.22-py3-none-any.whl\",\"repo\":\"rules_python_publish_deps_311_pycparser_py3_none_any_c3702b6d\",\"version\":\"3.11\"},{\"filename\":\"pycparser-2.22.tar.gz\",\"repo\":\"rules_python_publish_deps_311_pycparser_sdist_491c8be9\",\"version\":\"3.11\"}]", - "pygments": "[{\"filename\":\"pygments-2.18.0-py3-none-any.whl\",\"repo\":\"rules_python_publish_deps_311_pygments_py3_none_any_b8e6aca0\",\"version\":\"3.11\"},{\"filename\":\"pygments-2.18.0.tar.gz\",\"repo\":\"rules_python_publish_deps_311_pygments_sdist_786ff802\",\"version\":\"3.11\"}]", - "pywin32_ctypes": "[{\"filename\":\"pywin32-ctypes-0.2.3.tar.gz\",\"repo\":\"rules_python_publish_deps_311_pywin32_ctypes_sdist_d162dc04\",\"version\":\"3.11\"},{\"filename\":\"pywin32_ctypes-0.2.3-py3-none-any.whl\",\"repo\":\"rules_python_publish_deps_311_pywin32_ctypes_py3_none_any_8a151337\",\"version\":\"3.11\"}]", - "readme_renderer": "[{\"filename\":\"readme_renderer-44.0-py3-none-any.whl\",\"repo\":\"rules_python_publish_deps_311_readme_renderer_py3_none_any_2fbca89b\",\"version\":\"3.11\"},{\"filename\":\"readme_renderer-44.0.tar.gz\",\"repo\":\"rules_python_publish_deps_311_readme_renderer_sdist_8712034e\",\"version\":\"3.11\"}]", - "requests": "[{\"filename\":\"requests-2.32.3-py3-none-any.whl\",\"repo\":\"rules_python_publish_deps_311_requests_py3_none_any_70761cfe\",\"version\":\"3.11\"},{\"filename\":\"requests-2.32.3.tar.gz\",\"repo\":\"rules_python_publish_deps_311_requests_sdist_55365417\",\"version\":\"3.11\"}]", - "requests_toolbelt": "[{\"filename\":\"requests-toolbelt-1.0.0.tar.gz\",\"repo\":\"rules_python_publish_deps_311_requests_toolbelt_sdist_7681a0a3\",\"version\":\"3.11\"},{\"filename\":\"requests_toolbelt-1.0.0-py2.py3-none-any.whl\",\"repo\":\"rules_python_publish_deps_311_requests_toolbelt_py2_none_any_cccfdd66\",\"version\":\"3.11\"}]", - "rfc3986": "[{\"filename\":\"rfc3986-2.0.0-py2.py3-none-any.whl\",\"repo\":\"rules_python_publish_deps_311_rfc3986_py2_none_any_50b1502b\",\"version\":\"3.11\"},{\"filename\":\"rfc3986-2.0.0.tar.gz\",\"repo\":\"rules_python_publish_deps_311_rfc3986_sdist_97aacf9d\",\"version\":\"3.11\"}]", - "rich": "[{\"filename\":\"rich-13.9.3-py3-none-any.whl\",\"repo\":\"rules_python_publish_deps_311_rich_py3_none_any_9836f509\",\"version\":\"3.11\"},{\"filename\":\"rich-13.9.3.tar.gz\",\"repo\":\"rules_python_publish_deps_311_rich_sdist_bc1e01b8\",\"version\":\"3.11\"}]", - "secretstorage": "[{\"filename\":\"SecretStorage-3.3.3-py3-none-any.whl\",\"repo\":\"rules_python_publish_deps_311_secretstorage_py3_none_any_f356e662\",\"version\":\"3.11\"},{\"filename\":\"SecretStorage-3.3.3.tar.gz\",\"repo\":\"rules_python_publish_deps_311_secretstorage_sdist_2403533e\",\"version\":\"3.11\"}]", - "twine": "[{\"filename\":\"twine-5.1.1-py3-none-any.whl\",\"repo\":\"rules_python_publish_deps_311_twine_py3_none_any_215dbe7b\",\"version\":\"3.11\"},{\"filename\":\"twine-5.1.1.tar.gz\",\"repo\":\"rules_python_publish_deps_311_twine_sdist_9aa08251\",\"version\":\"3.11\"}]", - "urllib3": "[{\"filename\":\"urllib3-2.2.3-py3-none-any.whl\",\"repo\":\"rules_python_publish_deps_311_urllib3_py3_none_any_ca899ca0\",\"version\":\"3.11\"},{\"filename\":\"urllib3-2.2.3.tar.gz\",\"repo\":\"rules_python_publish_deps_311_urllib3_sdist_e7d814a8\",\"version\":\"3.11\"}]", - "zipp": "[{\"filename\":\"zipp-3.20.2-py3-none-any.whl\",\"repo\":\"rules_python_publish_deps_311_zipp_py3_none_any_a817ac80\",\"version\":\"3.11\"},{\"filename\":\"zipp-3.20.2.tar.gz\",\"repo\":\"rules_python_publish_deps_311_zipp_sdist_bc9eb26f\",\"version\":\"3.11\"}]" + "backports_tarfile": "{\"rules_python_publish_deps_311_backports_tarfile_py3_none_any_77e284d7\":[{\"filename\":\"backports.tarfile-1.2.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_backports_tarfile_sdist_d75e02c2\":[{\"filename\":\"backports_tarfile-1.2.0.tar.gz\",\"version\":\"3.11\"}]}", + "certifi": "{\"rules_python_publish_deps_311_certifi_py3_none_any_922820b5\":[{\"filename\":\"certifi-2024.8.30-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_certifi_sdist_bec941d2\":[{\"filename\":\"certifi-2024.8.30.tar.gz\",\"version\":\"3.11\"}]}", + "cffi": "{\"rules_python_publish_deps_311_cffi_cp311_cp311_manylinux_2_17_aarch64_a1ed2dd2\":[{\"filename\":\"cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cffi_cp311_cp311_manylinux_2_17_ppc64le_46bf4316\":[{\"filename\":\"cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cffi_cp311_cp311_manylinux_2_17_s390x_a24ed04c\":[{\"filename\":\"cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cffi_cp311_cp311_manylinux_2_17_x86_64_610faea7\":[{\"filename\":\"cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cffi_cp311_cp311_musllinux_1_1_aarch64_a9b15d49\":[{\"filename\":\"cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cffi_cp311_cp311_musllinux_1_1_x86_64_fc48c783\":[{\"filename\":\"cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cffi_sdist_1c39c601\":[{\"filename\":\"cffi-1.17.1.tar.gz\",\"version\":\"3.11\"}]}", + "charset_normalizer": "{\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_macosx_10_9_universal2_0d99dd8f\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_universal2.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_macosx_10_9_x86_64_c57516e5\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_macosx_11_0_arm64_6dba5d19\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-macosx_11_0_arm64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_manylinux_2_17_aarch64_bf4475b8\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_manylinux_2_17_ppc64le_ce031db0\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_manylinux_2_17_s390x_8ff4e7cd\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_manylinux_2_17_x86_64_3710a975\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_musllinux_1_2_aarch64_47334db7\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_aarch64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_musllinux_1_2_ppc64le_f1a2f519\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_ppc64le.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_musllinux_1_2_s390x_63bc5c4a\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_s390x.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_musllinux_1_2_x86_64_bcb4f8ea\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_win_amd64_cee4373f\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-win_amd64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_py3_none_any_fe9f97fe\":[{\"filename\":\"charset_normalizer-3.4.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_sdist_223217c3\":[{\"filename\":\"charset_normalizer-3.4.0.tar.gz\",\"version\":\"3.11\"}]}", + "cryptography": "{\"rules_python_publish_deps_311_cryptography_cp39_abi3_manylinux_2_17_aarch64_846da004\":[{\"filename\":\"cryptography-43.0.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cryptography_cp39_abi3_manylinux_2_17_x86_64_0f996e72\":[{\"filename\":\"cryptography-43.0.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cryptography_cp39_abi3_manylinux_2_28_aarch64_f7b178f1\":[{\"filename\":\"cryptography-43.0.3-cp39-abi3-manylinux_2_28_aarch64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cryptography_cp39_abi3_manylinux_2_28_x86_64_c2e6fc39\":[{\"filename\":\"cryptography-43.0.3-cp39-abi3-manylinux_2_28_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cryptography_cp39_abi3_musllinux_1_2_aarch64_e1be4655\":[{\"filename\":\"cryptography-43.0.3-cp39-abi3-musllinux_1_2_aarch64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cryptography_cp39_abi3_musllinux_1_2_x86_64_df6b6c6d\":[{\"filename\":\"cryptography-43.0.3-cp39-abi3-musllinux_1_2_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cryptography_sdist_315b9001\":[{\"filename\":\"cryptography-43.0.3.tar.gz\",\"version\":\"3.11\"}]}", + "docutils": "{\"rules_python_publish_deps_311_docutils_py3_none_any_dafca5b9\":[{\"filename\":\"docutils-0.21.2-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_docutils_sdist_3a6b1873\":[{\"filename\":\"docutils-0.21.2.tar.gz\",\"version\":\"3.11\"}]}", + "idna": "{\"rules_python_publish_deps_311_idna_py3_none_any_946d195a\":[{\"filename\":\"idna-3.10-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_idna_sdist_12f65c9b\":[{\"filename\":\"idna-3.10.tar.gz\",\"version\":\"3.11\"}]}", + "importlib_metadata": "{\"rules_python_publish_deps_311_importlib_metadata_py3_none_any_45e54197\":[{\"filename\":\"importlib_metadata-8.5.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_importlib_metadata_sdist_71522656\":[{\"filename\":\"importlib_metadata-8.5.0.tar.gz\",\"version\":\"3.11\"}]}", + "jaraco_classes": "{\"rules_python_publish_deps_311_jaraco_classes_py3_none_any_f662826b\":[{\"filename\":\"jaraco.classes-3.4.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_jaraco_classes_sdist_47a024b5\":[{\"filename\":\"jaraco.classes-3.4.0.tar.gz\",\"version\":\"3.11\"}]}", + "jaraco_context": "{\"rules_python_publish_deps_311_jaraco_context_py3_none_any_f797fc48\":[{\"filename\":\"jaraco.context-6.0.1-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_jaraco_context_sdist_9bae4ea5\":[{\"filename\":\"jaraco_context-6.0.1.tar.gz\",\"version\":\"3.11\"}]}", + "jaraco_functools": "{\"rules_python_publish_deps_311_jaraco_functools_py3_none_any_ad159f13\":[{\"filename\":\"jaraco.functools-4.1.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_jaraco_functools_sdist_70f7e0e2\":[{\"filename\":\"jaraco_functools-4.1.0.tar.gz\",\"version\":\"3.11\"}]}", + "jeepney": "{\"rules_python_publish_deps_311_jeepney_py3_none_any_c0a454ad\":[{\"filename\":\"jeepney-0.8.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_jeepney_sdist_5efe48d2\":[{\"filename\":\"jeepney-0.8.0.tar.gz\",\"version\":\"3.11\"}]}", + "keyring": "{\"rules_python_publish_deps_311_keyring_py3_none_any_5426f817\":[{\"filename\":\"keyring-25.4.1-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_keyring_sdist_b07ebc55\":[{\"filename\":\"keyring-25.4.1.tar.gz\",\"version\":\"3.11\"}]}", + "markdown_it_py": "{\"rules_python_publish_deps_311_markdown_it_py_py3_none_any_35521684\":[{\"filename\":\"markdown_it_py-3.0.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_markdown_it_py_sdist_e3f60a94\":[{\"filename\":\"markdown-it-py-3.0.0.tar.gz\",\"version\":\"3.11\"}]}", + "mdurl": "{\"rules_python_publish_deps_311_mdurl_py3_none_any_84008a41\":[{\"filename\":\"mdurl-0.1.2-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_mdurl_sdist_bb413d29\":[{\"filename\":\"mdurl-0.1.2.tar.gz\",\"version\":\"3.11\"}]}", + "more_itertools": "{\"rules_python_publish_deps_311_more_itertools_py3_none_any_037b0d32\":[{\"filename\":\"more_itertools-10.5.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_more_itertools_sdist_5482bfef\":[{\"filename\":\"more-itertools-10.5.0.tar.gz\",\"version\":\"3.11\"}]}", + "nh3": "{\"rules_python_publish_deps_311_nh3_cp37_abi3_macosx_10_12_x86_64_14c5a72e\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_macosx_10_12_x86_64_7b7c2a3c\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-macosx_10_12_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_aarch64_42c64511\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_armv7l_0411beb0\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_ppc64_5f36b271\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_ppc64le_34c03fa7\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_s390x_19aaba96\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_x86_64_de3ceed6\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_musllinux_1_2_aarch64_f0eca9ca\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-musllinux_1_2_aarch64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_musllinux_1_2_armv7l_3a157ab1\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-musllinux_1_2_armv7l.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_musllinux_1_2_x86_64_36c95d4b\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-musllinux_1_2_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_win_amd64_8ce0f819\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-win_amd64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_sdist_94a16692\":[{\"filename\":\"nh3-0.2.18.tar.gz\",\"version\":\"3.11\"}]}", + "pkginfo": "{\"rules_python_publish_deps_311_pkginfo_py3_none_any_889a6da2\":[{\"filename\":\"pkginfo-1.10.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_pkginfo_sdist_5df73835\":[{\"filename\":\"pkginfo-1.10.0.tar.gz\",\"version\":\"3.11\"}]}", + "pycparser": "{\"rules_python_publish_deps_311_pycparser_py3_none_any_c3702b6d\":[{\"filename\":\"pycparser-2.22-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_pycparser_sdist_491c8be9\":[{\"filename\":\"pycparser-2.22.tar.gz\",\"version\":\"3.11\"}]}", + "pygments": "{\"rules_python_publish_deps_311_pygments_py3_none_any_b8e6aca0\":[{\"filename\":\"pygments-2.18.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_pygments_sdist_786ff802\":[{\"filename\":\"pygments-2.18.0.tar.gz\",\"version\":\"3.11\"}]}", + "pywin32_ctypes": "{\"rules_python_publish_deps_311_pywin32_ctypes_py3_none_any_8a151337\":[{\"filename\":\"pywin32_ctypes-0.2.3-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_pywin32_ctypes_sdist_d162dc04\":[{\"filename\":\"pywin32-ctypes-0.2.3.tar.gz\",\"version\":\"3.11\"}]}", + "readme_renderer": "{\"rules_python_publish_deps_311_readme_renderer_py3_none_any_2fbca89b\":[{\"filename\":\"readme_renderer-44.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_readme_renderer_sdist_8712034e\":[{\"filename\":\"readme_renderer-44.0.tar.gz\",\"version\":\"3.11\"}]}", + "requests": "{\"rules_python_publish_deps_311_requests_py3_none_any_70761cfe\":[{\"filename\":\"requests-2.32.3-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_requests_sdist_55365417\":[{\"filename\":\"requests-2.32.3.tar.gz\",\"version\":\"3.11\"}]}", + "requests_toolbelt": "{\"rules_python_publish_deps_311_requests_toolbelt_py2_none_any_cccfdd66\":[{\"filename\":\"requests_toolbelt-1.0.0-py2.py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_requests_toolbelt_sdist_7681a0a3\":[{\"filename\":\"requests-toolbelt-1.0.0.tar.gz\",\"version\":\"3.11\"}]}", + "rfc3986": "{\"rules_python_publish_deps_311_rfc3986_py2_none_any_50b1502b\":[{\"filename\":\"rfc3986-2.0.0-py2.py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_rfc3986_sdist_97aacf9d\":[{\"filename\":\"rfc3986-2.0.0.tar.gz\",\"version\":\"3.11\"}]}", + "rich": "{\"rules_python_publish_deps_311_rich_py3_none_any_9836f509\":[{\"filename\":\"rich-13.9.3-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_rich_sdist_bc1e01b8\":[{\"filename\":\"rich-13.9.3.tar.gz\",\"version\":\"3.11\"}]}", + "secretstorage": "{\"rules_python_publish_deps_311_secretstorage_py3_none_any_f356e662\":[{\"filename\":\"SecretStorage-3.3.3-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_secretstorage_sdist_2403533e\":[{\"filename\":\"SecretStorage-3.3.3.tar.gz\",\"version\":\"3.11\"}]}", + "twine": "{\"rules_python_publish_deps_311_twine_py3_none_any_215dbe7b\":[{\"filename\":\"twine-5.1.1-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_twine_sdist_9aa08251\":[{\"filename\":\"twine-5.1.1.tar.gz\",\"version\":\"3.11\"}]}", + "urllib3": "{\"rules_python_publish_deps_311_urllib3_py3_none_any_ca899ca0\":[{\"filename\":\"urllib3-2.2.3-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_urllib3_sdist_e7d814a8\":[{\"filename\":\"urllib3-2.2.3.tar.gz\",\"version\":\"3.11\"}]}", + "zipp": "{\"rules_python_publish_deps_311_zipp_py3_none_any_a817ac80\":[{\"filename\":\"zipp-3.20.2-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_zipp_sdist_bc9eb26f\":[{\"filename\":\"zipp-3.20.2.tar.gz\",\"version\":\"3.11\"}]}" }, "packages": [ "backports_tarfile", diff --git a/python/private/pypi/BUILD.bazel b/python/private/pypi/BUILD.bazel index dafbcfb757..fef0859932 100644 --- a/python/private/pypi/BUILD.bazel +++ b/python/private/pypi/BUILD.bazel @@ -64,6 +64,7 @@ bzl_library( ":parse_whl_name_bzl", ":pip_repository_attrs_bzl", ":simpleapi_download_bzl", + ":whl_alias_bzl", ":whl_library_bzl", ":whl_repo_name_bzl", "//python/private:full_version_bzl", @@ -156,7 +157,7 @@ bzl_library( name = "multi_pip_parse_bzl", srcs = ["multi_pip_parse.bzl"], deps = [ - "pip_repository_bzl", + ":pip_repository_bzl", "//python/private:text_util_bzl", ], ) @@ -230,6 +231,7 @@ bzl_library( ":parse_requirements_bzl", ":pip_repository_attrs_bzl", ":render_pkg_aliases_bzl", + ":whl_alias_bzl", "//python/private:normalize_name_bzl", "//python/private:repo_utils_bzl", "//python/private:text_util_bzl", @@ -257,6 +259,7 @@ bzl_library( deps = [ ":generate_group_library_build_bazel_bzl", ":parse_whl_name_bzl", + ":whl_alias_bzl", ":whl_target_platforms_bzl", "//python/private:normalize_name_bzl", "//python/private:text_util_bzl", @@ -283,6 +286,11 @@ bzl_library( ], ) +bzl_library( + name = "whl_alias_bzl", + srcs = ["whl_config_setting.bzl"], +) + bzl_library( name = "whl_library_alias_bzl", srcs = ["whl_library_alias.bzl"], diff --git a/python/private/pypi/extension.bzl b/python/private/pypi/extension.bzl index ea2bafdb77..5ad589528d 100644 --- a/python/private/pypi/extension.bzl +++ b/python/private/pypi/extension.bzl @@ -23,13 +23,13 @@ load("//python/private:semver.bzl", "semver") load("//python/private:version_label.bzl", "version_label") load(":attrs.bzl", "use_isolated") load(":evaluate_markers.bzl", "evaluate_markers", EVALUATE_MARKERS_SRCS = "SRCS") -load(":hub_repository.bzl", "hub_repository") +load(":hub_repository.bzl", "hub_repository", "whl_aliases") load(":parse_requirements.bzl", "host_platform", "parse_requirements", "select_requirement") load(":parse_whl_name.bzl", "parse_whl_name") load(":pip_repository_attrs.bzl", "ATTRS") -load(":render_pkg_aliases.bzl", "whl_alias") load(":requirements_files_by_platform.bzl", "requirements_files_by_platform") load(":simpleapi_download.bzl", "simpleapi_download") +load(":whl_config_setting.bzl", "whl_config_setting") load(":whl_library.bzl", "whl_library") load(":whl_repo_name.bzl", "pypi_repo_name", "whl_repo_name") @@ -87,7 +87,7 @@ def _create_whl_repos( Returns a {type}`struct` with the following attributes: whl_map: {type}`dict[str, list[struct]]` the output is keyed by the normalized package name and the values are the instances of the - {bzl:obj}`whl_alias` return values. + {bzl:obj}`whl_config_setting` return values. exposed_packages: {type}`dict[str, Any]` this is just a way to represent a set of string values. whl_libraries: {type}`dict[str, dict[str, Any]]` the keys are the @@ -305,14 +305,11 @@ def _create_whl_repos( whl_libraries[repo_name] = args - whl_map.setdefault(whl_name, []).append( - whl_alias( - repo = repo_name, - version = major_minor, - filename = distribution.filename, - target_platforms = target_platforms, - ), - ) + whl_map.setdefault(whl_name, {})[whl_config_setting( + version = major_minor, + filename = distribution.filename, + target_platforms = target_platforms, + )] = repo_name if found_something: if is_exposed: @@ -343,12 +340,7 @@ def _create_whl_repos( # args are manipulated in the code going before. repo_name = "{}_{}".format(pip_name, whl_name) whl_libraries[repo_name] = dict(whl_library_args.items()) - whl_map.setdefault(whl_name, []).append( - whl_alias( - repo = repo_name, - version = major_minor, - ), - ) + whl_map.setdefault(whl_name, {})[whl_config_setting(version = major_minor)] = repo_name continue is_exposed = False @@ -372,13 +364,10 @@ def _create_whl_repos( *target_platforms ) whl_libraries[repo_name] = args - whl_map.setdefault(whl_name, []).append( - whl_alias( - repo = repo_name, - version = major_minor, - target_platforms = target_platforms or None, - ), - ) + whl_map.setdefault(whl_name, {})[whl_config_setting( + version = major_minor, + target_platforms = target_platforms or None, + )] = repo_name if is_exposed: exposed_packages[whl_name] = None @@ -521,7 +510,8 @@ You cannot use both the additive_build_content and additive_build_content_file a ) hub_whl_map.setdefault(hub_name, {}) for key, settings in out.whl_map.items(): - hub_whl_map[hub_name].setdefault(key, []).extend(settings) + for setting, repo in settings.items(): + hub_whl_map[hub_name].setdefault(key, {}).setdefault(repo, []).append(setting) extra_aliases.setdefault(hub_name, {}) for whl_name, aliases in out.extra_aliases.items(): extra_aliases[hub_name].setdefault(whl_name, {}).update(aliases) @@ -541,7 +531,7 @@ You cannot use both the additive_build_content and additive_build_content_file a whl_mods = dict(sorted(whl_mods.items())), hub_whl_map = { hub_name: { - whl_name: sorted(settings, key = lambda x: (x.version, x.filename)) + whl_name: dict(settings) for whl_name, settings in sorted(whl_map.items()) } for hub_name, whl_map in sorted(hub_whl_map.items()) @@ -571,20 +561,6 @@ You cannot use both the additive_build_content and additive_build_content_file a is_reproducible = is_reproducible, ) -def _alias_dict(a): - ret = { - "repo": a.repo, - } - if a.config_setting: - ret["config_setting"] = a.config_setting - if a.filename: - ret["filename"] = a.filename - if a.target_platforms: - ret["target_platforms"] = a.target_platforms - if a.version: - ret["version"] = a.version - return ret - def _pip_impl(module_ctx): """Implementation of a class tag that creates the pip hub and corresponding pip spoke whl repositories. @@ -665,7 +641,7 @@ def _pip_impl(module_ctx): repo_name = hub_name, extra_hub_aliases = mods.extra_aliases.get(hub_name, {}), whl_map = { - key: json.encode([_alias_dict(a) for a in aliases]) + key: whl_aliases(aliases) for key, aliases in whl_map.items() }, packages = mods.exposed_packages.get(hub_name, []), diff --git a/python/private/pypi/hub_repository.bzl b/python/private/pypi/hub_repository.bzl index 69d937142a..7692f80b79 100644 --- a/python/private/pypi/hub_repository.bzl +++ b/python/private/pypi/hub_repository.bzl @@ -15,11 +15,8 @@ "" load("//python/private:text_util.bzl", "render") -load( - ":render_pkg_aliases.bzl", - "render_multiplatform_pkg_aliases", - "whl_alias", -) +load(":render_pkg_aliases.bzl", "render_multiplatform_pkg_aliases") +load(":whl_config_setting.bzl", "whl_config_setting") _BUILD_FILE_CONTENTS = """\ package(default_visibility = ["//visibility:public"]) @@ -32,7 +29,7 @@ def _impl(rctx): bzl_packages = rctx.attr.packages or rctx.attr.whl_map.keys() aliases = render_multiplatform_pkg_aliases( aliases = { - key: [whl_alias(**v) for v in json.decode(values)] + key: _whl_aliases(values) for key, values in rctx.attr.whl_map.items() }, extra_hub_aliases = rctx.attr.extra_hub_aliases, @@ -97,3 +94,45 @@ in the pip.parse tag class. doc = """A rule for bzlmod mulitple pip repository creation. PRIVATE USE ONLY.""", implementation = _impl, ) + +def _whl_aliases(repo_mapping_json): + """Inverse of whl_aliases + + Args: + repo_mapping_json: {type}`str` + + Returns: + What `whl_aliases` accepts. + """ + return { + whl_config_setting(**v): repo + for repo, values in json.decode(repo_mapping_json).items() + for v in values + } + +def whl_aliases(repo_mapping): + """A function to serialize the aliases so that `hub_repository` can accept them. + + Args: + repo_mapping: {type}`dict[str, list[struct]]` repo to + {obj}`whl_config_setting` mapping. + + Returns: + A deserializable JSON string + """ + return json.encode({ + repo: [_whl_config_setting_dict(s) for s in settings] + for repo, settings in repo_mapping.items() + }) + +def _whl_config_setting_dict(a): + ret = {} + if a.config_setting: + ret["config_setting"] = a.config_setting + if a.filename: + ret["filename"] = a.filename + if a.target_platforms: + ret["target_platforms"] = a.target_platforms + if a.version: + ret["version"] = a.version + return ret diff --git a/python/private/pypi/pip_repository.bzl b/python/private/pypi/pip_repository.bzl index 90cda77465..6071573d09 100644 --- a/python/private/pypi/pip_repository.bzl +++ b/python/private/pypi/pip_repository.bzl @@ -21,7 +21,7 @@ load("//python/private:text_util.bzl", "render") load(":evaluate_markers.bzl", "evaluate_markers", EVALUATE_MARKERS_SRCS = "SRCS") load(":parse_requirements.bzl", "host_platform", "parse_requirements", "select_requirement") load(":pip_repository_attrs.bzl", "ATTRS") -load(":render_pkg_aliases.bzl", "render_pkg_aliases", "whl_alias") +load(":render_pkg_aliases.bzl", "render_pkg_aliases") load(":requirements_files_by_platform.bzl", "requirements_files_by_platform") def _get_python_interpreter_attr(rctx): @@ -174,7 +174,7 @@ def _pip_repository_impl(rctx): aliases = render_pkg_aliases( aliases = { - pkg: [whl_alias(repo = rctx.attr.name + "_" + pkg)] + pkg: rctx.attr.name + "_" + pkg for pkg in bzl_packages or [] }, ) diff --git a/python/private/pypi/pkg_aliases.bzl b/python/private/pypi/pkg_aliases.bzl index de9545e986..a83555dc78 100644 --- a/python/private/pypi/pkg_aliases.bzl +++ b/python/private/pypi/pkg_aliases.bzl @@ -16,6 +16,7 @@ This is used in bzlmod and non-bzlmod setups.""" +load("@bazel_skylib//lib:selects.bzl", "selects") load("//python/private:text_util.bzl", "render") load( ":labels.bzl", @@ -26,6 +27,8 @@ load( "WHEEL_FILE_IMPL_LABEL", "WHEEL_FILE_PUBLIC_LABEL", ) +load(":parse_whl_name.bzl", "parse_whl_name") +load(":whl_target_platforms.bzl", "whl_target_platforms") _NO_MATCH_ERROR_TEMPLATE = """\ No matching wheel for current configuration's Python version. @@ -53,7 +56,11 @@ def _no_match_error(actual): return _NO_MATCH_ERROR_TEMPLATE.format( config_settings = render.indent( - "\n".join(sorted(actual.keys())), + "\n".join(sorted([ + value + for key in actual + for value in (key if type(key) == "tuple" else [key]) + ])), ).lstrip(), rules_python = "rules_python", ) @@ -65,17 +72,21 @@ def pkg_aliases( group_name = None, extra_aliases = None, native = native, - select = select): + select = selects.with_or, + **kwargs): """Create aliases for an actual package. Args: name: {type}`str` The name of the package. - actual: {type}`dict[Label, str] | str` The name of the repo the aliases point to, or a dict of select conditions to repo names for the aliases to point to - mapping to repositories. + actual: {type}`dict[Label | tuple, str] | str` The name of the repo the + aliases point to, or a dict of select conditions to repo names for + the aliases to point to mapping to repositories. The keys are passed + to bazel skylib's `selects.with_or`, so they can be tuples as well. group_name: {type}`str` The group name that the pkg belongs to. extra_aliases: {type}`list[str]` The extra aliases to be created. native: {type}`struct` used in unit tests. select: {type}`select` used in unit tests. + **kwargs: extra kwargs to pass to {bzl:obj}`get_filename_config_settings`. """ native.alias( name = name, @@ -91,6 +102,8 @@ def pkg_aliases( x: x for x in extra_aliases or [] } + + actual = multiplatform_whl_aliases(aliases = actual, **kwargs) no_match_error = _no_match_error(actual) for name, target_name in target_names.items(): @@ -102,11 +115,11 @@ def pkg_aliases( elif type(actual) == type({}): _actual = select( { - config_setting: "@{repo}//:{target_name}".format( + v: "@{repo}//:{target_name}".format( repo = repo, target_name = name, ) - for config_setting, repo in actual.items() + for v, repo in actual.items() }, no_match_error = no_match_error, ) @@ -132,3 +145,253 @@ def pkg_aliases( name = WHEEL_FILE_PUBLIC_LABEL, actual = "//_groups:{}_whl".format(group_name), ) + +def _normalize_versions(name, versions): + if not versions: + return versions + + if (0, 0) in versions: + fail("Invalid version in '{}': cannot specify (0, 0) as a value".format(name)) + + return sorted(versions) + +def multiplatform_whl_aliases( + *, + aliases = [], + glibc_versions = None, + muslc_versions = None, + osx_versions = None): + """convert a list of aliases from filename to config_setting ones. + + Args: + aliases: {type}`str | dict[whl_config_setting | str, str]`: The aliases + to process. Any aliases that have the filename set will be + converted to a dict of config settings to repo names. + glibc_versions: {type}`list[tuple[int, int]]` list of versions that can be + used in this hub repo. + muslc_versions: {type}`list[tuple[int, int]]` list of versions that can be + used in this hub repo. + osx_versions: {type}`list[tuple[int, int]]` list of versions that can be + used in this hub repo. + + Returns: + A dict with of config setting labels to repo names or the repo name itself. + """ + + if type(aliases) == type(""): + # We don't have any aliases, this is a repo name + return aliases + + # TODO @aignas 2024-11-17: we might be able to use FeatureFlagInfo and some + # code gen to create a version_lt_x target, which would allow us to check + # if the libc version is in a particular range. + glibc_versions = _normalize_versions("glibc_versions", glibc_versions) + muslc_versions = _normalize_versions("muslc_versions", muslc_versions) + osx_versions = _normalize_versions("osx_versions", osx_versions) + + ret = {} + versioned_additions = {} + for alias, repo in aliases.items(): + if type(alias) != "struct": + ret[alias] = repo + continue + elif not (alias.filename or alias.target_platforms): + # This is an internal consistency check + fail("Expected to have either 'filename' or 'target_platforms' set, got: {}".format(alias)) + + config_settings, all_versioned_settings = get_filename_config_settings( + filename = alias.filename or "", + target_platforms = alias.target_platforms, + python_version = alias.version, + # If we have multiple platforms but no wheel filename, lets use different + # config settings. + non_whl_prefix = "sdist" if alias.filename else "", + glibc_versions = glibc_versions, + muslc_versions = muslc_versions, + osx_versions = osx_versions, + ) + + for setting in config_settings: + ret["//_config" + setting] = repo + + # Now for the versioned platform config settings, we need to select one + # that best fits the bill and if there are multiple wheels, e.g. + # manylinux_2_17_x86_64 and manylinux_2_28_x86_64, then we need to select + # the former when the glibc is in the range of [2.17, 2.28) and then chose + # the later if it is [2.28, ...). If the 2.28 wheel was not present in + # the hub, then we would need to use 2.17 for all the glibc version + # configurations. + # + # Here we add the version settings to a dict where we key the range of + # versions that the whl spans. If the wheel supports musl and glibc at + # the same time, we do this for each supported platform, hence the + # double dict. + for default_setting, versioned in all_versioned_settings.items(): + versions = sorted(versioned) + min_version = versions[0] + max_version = versions[-1] + + versioned_additions.setdefault(default_setting, {})[(min_version, max_version)] = struct( + repo = repo, + settings = versioned, + ) + + versioned = {} + for default_setting, candidates in versioned_additions.items(): + # Sort the candidates by the range of versions the span, so that we + # start with the lowest version. + for _, candidate in sorted(candidates.items()): + # Set the default with the first candidate, which gives us the highest + # compatibility. If the users want to use a higher-version than the default + # they can configure the glibc_version flag. + versioned.setdefault("//_config" + default_setting, candidate.repo) + + # We will be overwriting previously added entries, but that is intended. + for _, setting in candidate.settings.items(): + versioned["//_config" + setting] = candidate.repo + + ret.update(versioned) + return ret + +def get_filename_config_settings( + *, + filename, + target_platforms, + python_version, + glibc_versions = None, + muslc_versions = None, + osx_versions = None, + non_whl_prefix = "sdist"): + """Get the filename config settings. + + Args: + filename: the distribution filename (can be a whl or an sdist). + target_platforms: list[str], target platforms in "{abi}_{os}_{cpu}" format. + glibc_versions: list[tuple[int, int]], list of versions. + muslc_versions: list[tuple[int, int]], list of versions. + osx_versions: list[tuple[int, int]], list of versions. + python_version: the python version to generate the config_settings for. + non_whl_prefix: the prefix of the config setting when the whl we don't have + a filename ending with ".whl". + + Returns: + A tuple: + * A list of config settings that are generated by ./pip_config_settings.bzl + * The list of default version settings. + """ + prefixes = [] + suffixes = [] + setting_supported_versions = {} + + if filename.endswith(".whl"): + if (0, 0) in glibc_versions: + fail("Invalid version in 'glibc_versions': cannot specify (0, 0) as a value") + if (0, 0) in muslc_versions: + fail("Invalid version in 'muslc_versions': cannot specify (0, 0) as a value") + if (0, 0) in osx_versions: + fail("Invalid version in 'osx_versions': cannot specify (0, 0) as a value") + + glibc_versions = sorted(glibc_versions) + muslc_versions = sorted(muslc_versions) + osx_versions = sorted(osx_versions) + + parsed = parse_whl_name(filename) + if parsed.python_tag == "py2.py3": + py = "py" + elif parsed.python_tag.startswith("cp"): + py = "cp3x" + else: + py = "py3" + + if parsed.abi_tag.startswith("cp"): + abi = "cp" + else: + abi = parsed.abi_tag + + if parsed.platform_tag == "any": + prefixes = ["_{}_{}_any".format(py, abi)] + else: + prefixes = ["_{}_{}".format(py, abi)] + suffixes = _whl_config_setting_suffixes( + platform_tag = parsed.platform_tag, + glibc_versions = glibc_versions, + muslc_versions = muslc_versions, + osx_versions = osx_versions, + setting_supported_versions = setting_supported_versions, + ) + else: + prefixes = [""] if not non_whl_prefix else ["_" + non_whl_prefix] + + versioned = { + ":is_cp{}{}_{}".format(python_version, p, suffix): { + version: ":is_cp{}{}_{}".format(python_version, p, setting) + for version, setting in versions.items() + } + for p in prefixes + for suffix, versions in setting_supported_versions.items() + } + + if suffixes or target_platforms or versioned: + return [ + ":is_cp{}{}_{}".format(python_version, p, s) + for p in prefixes + for s in suffixes or [_non_versioned_platform(p) for p in target_platforms or []] + ], versioned + else: + return [":is_cp{}{}".format(python_version, p) for p in prefixes], setting_supported_versions + +def _whl_config_setting_suffixes( + platform_tag, + glibc_versions, + muslc_versions, + osx_versions, + setting_supported_versions): + suffixes = [] + for platform_tag in platform_tag.split("."): + for p in whl_target_platforms(platform_tag): + prefix = p.os + suffix = p.cpu + if "manylinux" in platform_tag: + prefix = "manylinux" + versions = glibc_versions + elif "musllinux" in platform_tag: + prefix = "musllinux" + versions = muslc_versions + elif p.os in ["linux", "windows"]: + versions = [(0, 0)] + elif p.os == "osx": + versions = osx_versions + if "universal2" in platform_tag: + suffix += "_universal2" + else: + fail("Unsupported whl os: {}".format(p.os)) + + default_version_setting = "{}_{}".format(prefix, suffix) + supported_versions = {} + for v in versions: + if v == (0, 0): + suffixes.append(default_version_setting) + elif v >= p.version: + supported_versions[v] = "{}_{}_{}_{}".format( + prefix, + v[0], + v[1], + suffix, + ) + if supported_versions: + setting_supported_versions[default_version_setting] = supported_versions + + return suffixes + +def _non_versioned_platform(p, *, strict = False): + """A small utility function that converts 'cp311_linux_x86_64' to 'linux_x86_64'. + + This is so that we can tighten the code structure later by using strict = True. + """ + has_abi = p.startswith("cp") + if has_abi: + return p.partition("_")[-1] + elif not strict: + return p + else: + fail("Expected to always have a platform in the form '{{abi}}_{{os}}_{{arch}}', got: {}".format(p)) diff --git a/python/private/pypi/render_pkg_aliases.bzl b/python/private/pypi/render_pkg_aliases.bzl index 98c9d0906f..205236c8fb 100644 --- a/python/private/pypi/render_pkg_aliases.bzl +++ b/python/private/pypi/render_pkg_aliases.bzl @@ -62,18 +62,41 @@ which has a "null" version value and will not match version constraints. """ def _repr_actual(aliases): - if len(aliases) == 1 and not aliases[0].version and not aliases[0].config_setting: - return repr(aliases[0].repo) + if type(aliases) == type(""): + return repr(aliases) actual = {} - for alias in aliases: - actual[alias.config_setting or ("//_config:is_python_" + alias.version)] = alias.repo - return render.indent(render.dict(actual)).lstrip() + for alias, repo in aliases.items(): + if alias.filename: + config_setting = """whl_config_setting(\n{}\n)""".format( + render.indent("\n".join([ + "{} = {},".format(k, repr(v)) + for k, v in { + "filename": alias.filename, + "target_platforms": alias.target_platforms, + "version": alias.version, + }.items() + if v + ])), + ) + else: + config_setting = repr( + alias.config_setting or ("//_config:is_python_" + alias.version), + ) + actual[config_setting] = repo + + return render.indent(render.dict(actual, key_repr = lambda x: x)).lstrip() + +def _render_common_aliases(*, name, aliases, extra_aliases = [], group_name = None, **kwargs): + actual_repr = _repr_actual(aliases) + extra_loads = "" + if "whl_config_setting" in actual_repr: + extra_loads = """load("@rules_python//python/private/pypi:whl_config_setting.bzl", "whl_config_setting")""" + extra_loads += "\n" -def _render_common_aliases(*, name, aliases, extra_aliases = [], group_name = None): return """\ load("@rules_python//python/private/pypi:pkg_aliases.bzl", "pkg_aliases") - +{extra_loads} package(default_visibility = ["//visibility:public"]) pkg_aliases( @@ -81,14 +104,23 @@ pkg_aliases( actual = {actual}, group_name = {group_name}, extra_aliases = {extra_aliases}, -)""".format( +{kwargs})""".format( + extra_loads = extra_loads, name = name, - actual = _repr_actual(aliases), + actual = actual_repr, group_name = repr(group_name), extra_aliases = repr(extra_aliases), + kwargs = "" if not kwargs else ( + render.indent( + "\n".join([ + "{} = {},".format(k, repr(v)) + for k, v in kwargs.items() + ]), + ) + "\n" + ), ) -def render_pkg_aliases(*, aliases, requirement_cycles = None, extra_hub_aliases = {}): +def render_pkg_aliases(*, aliases, requirement_cycles = None, extra_hub_aliases = {}, **kwargs): """Create alias declarations for each PyPI package. The aliases should be appended to the pip_repository BUILD.bazel file. These aliases @@ -97,10 +129,11 @@ def render_pkg_aliases(*, aliases, requirement_cycles = None, extra_hub_aliases Args: aliases: dict, the keys are normalized distribution names and values are the - whl_alias instances. + whl_config_setting instances. requirement_cycles: any package groups to also add. extra_hub_aliases: The list of extra aliases for each whl to be added in addition to the default ones. + **kwargs: Extra kwargs to pass to the rules. Returns: A dict of file paths and their contents. @@ -130,6 +163,7 @@ def render_pkg_aliases(*, aliases, requirement_cycles = None, extra_hub_aliases aliases = pkg_aliases, extra_aliases = extra_hub_aliases.get(normalize_name(name), []), group_name = whl_group_mapping.get(normalize_name(name)), + **kwargs ).strip() for name, pkg_aliases in aliases.items() } @@ -138,48 +172,11 @@ def render_pkg_aliases(*, aliases, requirement_cycles = None, extra_hub_aliases files["_groups/BUILD.bazel"] = generate_group_library_build_bazel("", requirement_cycles) return files -def whl_alias(*, repo, version = None, config_setting = None, filename = None, target_platforms = None): - """The bzl_packages value used by by the render_pkg_aliases function. - - This contains the minimum amount of information required to generate correct - aliases in a hub repository. - - Args: - repo: str, the repo of where to find the things to be aliased. - version: optional(str), the version of the python toolchain that this - whl alias is for. If not set, then non-version aware aliases will be - constructed. This is mainly used for better error messages when there - is no match found during a select. - config_setting: optional(Label or str), the config setting that we should use. Defaults - to "//_config:is_python_{version}". - filename: optional(str), the distribution filename to derive the config_setting. - target_platforms: optional(list[str]), the list of target_platforms for this - distribution. - - Returns: - a struct with the validated and parsed values. - """ - if not repo: - fail("'repo' must be specified") - - if target_platforms: - for p in target_platforms: - if not p.startswith("cp"): - fail("target_platform should start with 'cp' denoting the python version, got: " + p) - - return struct( - config_setting = config_setting, - filename = filename, - repo = repo, - target_platforms = target_platforms, - version = version, - ) - def render_multiplatform_pkg_aliases(*, aliases, **kwargs): """Render the multi-platform pkg aliases. Args: - aliases: dict[str, list(whl_alias)] A list of aliases that will be + aliases: dict[str, list(whl_config_setting)] A list of aliases that will be transformed from ones having `filename` to ones having `config_setting`. **kwargs: extra arguments passed to render_pkg_aliases. @@ -188,117 +185,23 @@ def render_multiplatform_pkg_aliases(*, aliases, **kwargs): """ flag_versions = get_whl_flag_versions( - aliases = [ + settings = [ a for bunch in aliases.values() for a in bunch ], ) - config_setting_aliases = { - pkg: multiplatform_whl_aliases( - aliases = pkg_aliases, - glibc_versions = flag_versions.get("glibc_versions", []), - muslc_versions = flag_versions.get("muslc_versions", []), - osx_versions = flag_versions.get("osx_versions", []), - ) - for pkg, pkg_aliases in aliases.items() - } - contents = render_pkg_aliases( - aliases = config_setting_aliases, + aliases = aliases, + glibc_versions = flag_versions.get("glibc_versions", []), + muslc_versions = flag_versions.get("muslc_versions", []), + osx_versions = flag_versions.get("osx_versions", []), **kwargs ) contents["_config/BUILD.bazel"] = _render_config_settings(**flag_versions) return contents -def multiplatform_whl_aliases(*, aliases, **kwargs): - """convert a list of aliases from filename to config_setting ones. - - Args: - aliases: list(whl_alias): The aliases to process. Any aliases that have - the filename set will be converted to a list of aliases, each with - an appropriate config_setting value. - **kwargs: Extra parameters passed to get_filename_config_settings. - - Returns: - A dict with aliases to be used in the hub repo. - """ - - ret = [] - versioned_additions = {} - for alias in aliases: - if not alias.filename and not alias.target_platforms: - ret.append(alias) - continue - - config_settings, all_versioned_settings = get_filename_config_settings( - # TODO @aignas 2024-05-27: pass the parsed whl to reduce the - # number of duplicate operations. - filename = alias.filename or "", - target_platforms = alias.target_platforms, - python_version = alias.version, - # If we have multiple platforms but no wheel filename, lets use different - # config settings. - non_whl_prefix = "sdist" if alias.filename else "", - **kwargs - ) - - for setting in config_settings: - ret.append(whl_alias( - repo = alias.repo, - version = alias.version, - config_setting = "//_config" + setting, - )) - - # Now for the versioned platform config settings, we need to select one - # that best fits the bill and if there are multiple wheels, e.g. - # manylinux_2_17_x86_64 and manylinux_2_28_x86_64, then we need to select - # the former when the glibc is in the range of [2.17, 2.28) and then chose - # the later if it is [2.28, ...). If the 2.28 wheel was not present in - # the hub, then we would need to use 2.17 for all the glibc version - # configurations. - # - # Here we add the version settings to a dict where we key the range of - # versions that the whl spans. If the wheel supports musl and glibc at - # the same time, we do this for each supported platform, hence the - # double dict. - for default_setting, versioned in all_versioned_settings.items(): - versions = sorted(versioned) - min_version = versions[0] - max_version = versions[-1] - - versioned_additions.setdefault(default_setting, {})[(min_version, max_version)] = struct( - repo = alias.repo, - python_version = alias.version, - settings = versioned, - ) - - versioned = {} - for default_setting, candidates in versioned_additions.items(): - # Sort the candidates by the range of versions the span, so that we - # start with the lowest version. - for _, candidate in sorted(candidates.items()): - # Set the default with the first candidate, which gives us the highest - # compatibility. If the users want to use a higher-version than the default - # they can configure the glibc_version flag. - versioned.setdefault(default_setting, whl_alias( - version = candidate.python_version, - config_setting = "//_config" + default_setting, - repo = candidate.repo, - )) - - # We will be overwriting previously added entries, but that is intended. - for _, setting in sorted(candidate.settings.items()): - versioned[setting] = whl_alias( - version = candidate.python_version, - config_setting = "//_config" + setting, - repo = candidate.repo, - ) - - ret.extend(versioned.values()) - return ret - def _render_config_settings(python_versions = [], target_platforms = [], osx_versions = [], glibc_versions = [], muslc_versions = []): return """\ load("@rules_python//python/private/pypi:config_settings.bzl", "config_settings") @@ -319,11 +222,11 @@ config_settings( target_platforms = render.indent(render.list(target_platforms)).lstrip(), ) -def get_whl_flag_versions(aliases): - """Return all of the flag versions that is used by the aliases +def get_whl_flag_versions(settings): + """Return all of the flag versions that is used by the settings Args: - aliases: list[whl_alias] + settings: list[whl_config_setting] Returns: dict, which may have keys: @@ -335,17 +238,17 @@ def get_whl_flag_versions(aliases): muslc_versions = {} osx_versions = {} - for a in aliases: - if not a.version and not a.filename: + for setting in settings: + if not setting.version and not setting.filename: continue - if a.version: - python_versions[a.version] = None + if setting.version: + python_versions[setting.version] = None - if a.filename and a.filename.endswith(".whl") and not a.filename.endswith("-any.whl"): - parsed = parse_whl_name(a.filename) + if setting.filename and setting.filename.endswith(".whl") and not setting.filename.endswith("-any.whl"): + parsed = parse_whl_name(setting.filename) else: - for plat in a.target_platforms or []: + for plat in setting.target_platforms or []: target_platforms[_non_versioned_platform(plat)] = None continue @@ -396,131 +299,3 @@ def _non_versioned_platform(p, *, strict = False): return p else: fail("Expected to always have a platform in the form '{{abi}}_{{os}}_{{arch}}', got: {}".format(p)) - -def get_filename_config_settings( - *, - filename, - target_platforms, - python_version, - glibc_versions = None, - muslc_versions = None, - osx_versions = None, - non_whl_prefix = "sdist"): - """Get the filename config settings. - - Args: - filename: the distribution filename (can be a whl or an sdist). - target_platforms: list[str], target platforms in "{abi}_{os}_{cpu}" format. - glibc_versions: list[tuple[int, int]], list of versions. - muslc_versions: list[tuple[int, int]], list of versions. - osx_versions: list[tuple[int, int]], list of versions. - python_version: the python version to generate the config_settings for. - non_whl_prefix: the prefix of the config setting when the whl we don't have - a filename ending with ".whl". - - Returns: - A tuple: - * A list of config settings that are generated by ./pip_config_settings.bzl - * The list of default version settings. - """ - prefixes = [] - suffixes = [] - setting_supported_versions = {} - - if filename.endswith(".whl"): - if (0, 0) in glibc_versions: - fail("Invalid version in 'glibc_versions': cannot specify (0, 0) as a value") - if (0, 0) in muslc_versions: - fail("Invalid version in 'muslc_versions': cannot specify (0, 0) as a value") - if (0, 0) in osx_versions: - fail("Invalid version in 'osx_versions': cannot specify (0, 0) as a value") - - glibc_versions = sorted(glibc_versions) - muslc_versions = sorted(muslc_versions) - osx_versions = sorted(osx_versions) - - parsed = parse_whl_name(filename) - if parsed.python_tag == "py2.py3": - py = "py" - elif parsed.python_tag.startswith("cp"): - py = "cp3x" - else: - py = "py3" - - if parsed.abi_tag.startswith("cp"): - abi = "cp" - else: - abi = parsed.abi_tag - - if parsed.platform_tag == "any": - prefixes = ["_{}_{}_any".format(py, abi)] - suffixes = [_non_versioned_platform(p) for p in target_platforms or []] - else: - prefixes = ["_{}_{}".format(py, abi)] - suffixes = _whl_config_setting_suffixes( - platform_tag = parsed.platform_tag, - glibc_versions = glibc_versions, - muslc_versions = muslc_versions, - osx_versions = osx_versions, - setting_supported_versions = setting_supported_versions, - ) - else: - prefixes = [""] if not non_whl_prefix else ["_" + non_whl_prefix] - suffixes = [_non_versioned_platform(p) for p in target_platforms or []] - - versioned = { - ":is_cp{}{}_{}".format(python_version, p, suffix): { - version: ":is_cp{}{}_{}".format(python_version, p, setting) - for version, setting in versions.items() - } - for p in prefixes - for suffix, versions in setting_supported_versions.items() - } - - if suffixes or versioned: - return [":is_cp{}{}_{}".format(python_version, p, s) for p in prefixes for s in suffixes], versioned - else: - return [":is_cp{}{}".format(python_version, p) for p in prefixes], setting_supported_versions - -def _whl_config_setting_suffixes( - platform_tag, - glibc_versions, - muslc_versions, - osx_versions, - setting_supported_versions): - suffixes = [] - for platform_tag in platform_tag.split("."): - for p in whl_target_platforms(platform_tag): - prefix = p.os - suffix = p.cpu - if "manylinux" in platform_tag: - prefix = "manylinux" - versions = glibc_versions - elif "musllinux" in platform_tag: - prefix = "musllinux" - versions = muslc_versions - elif p.os in ["linux", "windows"]: - versions = [(0, 0)] - elif p.os == "osx": - versions = osx_versions - if "universal2" in platform_tag: - suffix += "_universal2" - else: - fail("Unsupported whl os: {}".format(p.os)) - - default_version_setting = "{}_{}".format(prefix, suffix) - supported_versions = {} - for v in versions: - if v == (0, 0): - suffixes.append(default_version_setting) - elif v >= p.version: - supported_versions[v] = "{}_{}_{}_{}".format( - prefix, - v[0], - v[1], - suffix, - ) - if supported_versions: - setting_supported_versions[default_version_setting] = supported_versions - - return suffixes diff --git a/python/private/pypi/whl_config_setting.bzl b/python/private/pypi/whl_config_setting.bzl new file mode 100644 index 0000000000..e46c7d37d7 --- /dev/null +++ b/python/private/pypi/whl_config_setting.bzl @@ -0,0 +1,50 @@ +# 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 small function to create an alias for a whl distribution" + +def whl_config_setting(*, repo = None, version = None, config_setting = None, filename = None, target_platforms = None): + """The bzl_packages value used by by the render_pkg_aliases function. + + This contains the minimum amount of information required to generate correct + aliases in a hub repository. + + Args: + repo: str, the repo of where to find the things to be aliased. + version: optional(str), the version of the python toolchain that this + whl alias is for. If not set, then non-version aware aliases will be + constructed. This is mainly used for better error messages when there + is no match found during a select. + config_setting: optional(Label or str), the config setting that we should use. Defaults + to "//_config:is_python_{version}". + filename: optional(str), the distribution filename to derive the config_setting. + target_platforms: optional(list[str]), the list of target_platforms for this + distribution. + + Returns: + a struct with the validated and parsed values. + """ + if target_platforms: + for p in target_platforms: + if not p.startswith("cp"): + fail("target_platform should start with 'cp' denoting the python version, got: " + p) + + return struct( + config_setting = config_setting, + filename = filename, + repo = repo, + # Make the struct hashable + target_platforms = tuple(target_platforms) if target_platforms else None, + version = version, + ) diff --git a/tests/pypi/extension/extension_tests.bzl b/tests/pypi/extension/extension_tests.bzl index 39670cd71f..7dfd8762a7 100644 --- a/tests/pypi/extension/extension_tests.bzl +++ b/tests/pypi/extension/extension_tests.bzl @@ -17,7 +17,7 @@ load("@rules_testing//lib:test_suite.bzl", "test_suite") load("@rules_testing//lib:truth.bzl", "subjects") load("//python/private/pypi:extension.bzl", "parse_modules") # buildifier: disable=bzl-visibility -load("//python/private/pypi:render_pkg_aliases.bzl", "whl_alias") # buildifier: disable=bzl-visibility +load("//python/private/pypi:whl_config_setting.bzl", "whl_config_setting") # buildifier: disable=bzl-visibility _tests = [] @@ -158,12 +158,13 @@ def _test_simple(env): pypi.exposed_packages().contains_exactly({"pypi": ["simple"]}) pypi.hub_group_map().contains_exactly({"pypi": {}}) pypi.hub_whl_map().contains_exactly({"pypi": { - "simple": [ - whl_alias( - repo = "pypi_315_simple", - version = "3.15", - ), - ], + "simple": { + "pypi_315_simple": [ + whl_config_setting( + version = "3.15", + ), + ], + }, }}) pypi.whl_libraries().contains_exactly({ "pypi_315_simple": { @@ -206,23 +207,25 @@ def _test_simple_multiple_requirements(env): pypi.exposed_packages().contains_exactly({"pypi": ["simple"]}) pypi.hub_group_map().contains_exactly({"pypi": {}}) pypi.hub_whl_map().contains_exactly({"pypi": { - "simple": [ - whl_alias( - repo = "pypi_315_simple_windows_x86_64", - target_platforms = [ - "cp315_windows_x86_64", - ], - version = "3.15", - ), - whl_alias( - repo = "pypi_315_simple_osx_aarch64_osx_x86_64", - target_platforms = [ - "cp315_osx_aarch64", - "cp315_osx_x86_64", - ], - version = "3.15", - ), - ], + "simple": { + "pypi_315_simple_osx_aarch64_osx_x86_64": [ + whl_config_setting( + target_platforms = [ + "cp315_osx_aarch64", + "cp315_osx_x86_64", + ], + version = "3.15", + ), + ], + "pypi_315_simple_windows_x86_64": [ + whl_config_setting( + target_platforms = [ + "cp315_windows_x86_64", + ], + version = "3.15", + ), + ], + }, }}) pypi.whl_libraries().contains_exactly({ "pypi_315_simple_osx_aarch64_osx_x86_64": { @@ -289,24 +292,25 @@ simple==0.0.3 --hash=sha256:deadbaaf pypi.exposed_packages().contains_exactly({"pypi": ["simple"]}) pypi.hub_group_map().contains_exactly({"pypi": {}}) pypi.hub_whl_map().contains_exactly({"pypi": { - "extra": [ - whl_alias( - repo = "pypi_315_extra", - version = "3.15", - ), - ], - "simple": [ - whl_alias( - repo = "pypi_315_simple_linux_x86_64", - target_platforms = ["cp315_linux_x86_64"], - version = "3.15", - ), - whl_alias( - repo = "pypi_315_simple_osx_aarch64", - target_platforms = ["cp315_osx_aarch64"], - version = "3.15", - ), - ], + "extra": { + "pypi_315_extra": [ + whl_config_setting(version = "3.15"), + ], + }, + "simple": { + "pypi_315_simple_linux_x86_64": [ + whl_config_setting( + target_platforms = ["cp315_linux_x86_64"], + version = "3.15", + ), + ], + "pypi_315_simple_osx_aarch64": [ + whl_config_setting( + target_platforms = ["cp315_osx_aarch64"], + version = "3.15", + ), + ], + }, }}) pypi.whl_libraries().contains_exactly({ "pypi_315_extra": { @@ -404,24 +408,23 @@ some_pkg==0.0.1 pypi.hub_group_map().contains_exactly({"pypi": {}}) pypi.hub_whl_map().contains_exactly({ "pypi": { - "simple": [ - whl_alias( - filename = "simple-0.0.1-py3-none-any.whl", - repo = "pypi_315_simple_py3_none_any_deadb00f", - version = "3.15", - ), - whl_alias( - filename = "simple-0.0.1.tar.gz", - repo = "pypi_315_simple_sdist_deadbeef", - version = "3.15", - ), - ], - "some_pkg": [ - whl_alias( - repo = "pypi_315_some_pkg", - version = "3.15", - ), - ], + "simple": { + "pypi_315_simple_py3_none_any_deadb00f": [ + whl_config_setting( + filename = "simple-0.0.1-py3-none-any.whl", + version = "3.15", + ), + ], + "pypi_315_simple_sdist_deadbeef": [ + whl_config_setting( + filename = "simple-0.0.1.tar.gz", + version = "3.15", + ), + ], + }, + "some_pkg": { + "pypi_315_some_pkg": [whl_config_setting(version = "3.15")], + }, }, }) pypi.whl_libraries().contains_exactly({ diff --git a/tests/pypi/pkg_aliases/pkg_aliases_test.bzl b/tests/pypi/pkg_aliases/pkg_aliases_test.bzl index cf801ae643..0fa66d05eb 100644 --- a/tests/pypi/pkg_aliases/pkg_aliases_test.bzl +++ b/tests/pypi/pkg_aliases/pkg_aliases_test.bzl @@ -15,80 +15,54 @@ """pkg_aliases tests""" load("@rules_testing//lib:test_suite.bzl", "test_suite") +load("//python/private/pypi:config_settings.bzl", "config_settings") # buildifier: disable=bzl-visibility load( "//python/private/pypi:pkg_aliases.bzl", + "multiplatform_whl_aliases", "pkg_aliases", ) # buildifier: disable=bzl-visibility +load("//python/private/pypi:whl_config_setting.bzl", "whl_config_setting") # buildifier: disable=bzl-visibility _tests = [] def _test_legacy_aliases(env): - actual = [] + got = {} pkg_aliases( name = "foo", actual = "repo", native = struct( - alias = lambda **kwargs: actual.append(kwargs), + alias = lambda name, actual: got.update({name: actual}), ), extra_aliases = ["my_special"], ) # buildifier: disable=unsorted-dict-items - want = [ - { - "name": "foo", - "actual": ":pkg", - }, - { - "name": "pkg", - "actual": "@repo//:pkg", - }, - { - "name": "whl", - "actual": "@repo//:whl", - }, - { - "name": "data", - "actual": "@repo//:data", - }, - { - "name": "dist_info", - "actual": "@repo//:dist_info", - }, - { - "name": "my_special", - "actual": "@repo//:my_special", - }, - ] + want = { + "foo": ":pkg", + "pkg": "@repo//:pkg", + "whl": "@repo//:whl", + "data": "@repo//:data", + "dist_info": "@repo//:dist_info", + "my_special": "@repo//:my_special", + } - env.expect.that_collection(actual).contains_exactly(want) + env.expect.that_dict(got).contains_exactly(want) _tests.append(_test_legacy_aliases) def _test_config_setting_aliases(env): # Use this function as it is used in pip_repository - actual = [] + got = {} actual_no_match_error = [] def mock_select(value, no_match_error = None): actual_no_match_error.append(no_match_error) - env.expect.that_str(no_match_error).equals("""\ -No matching wheel for current configuration's Python version. - -The current build configuration's Python version doesn't match any of the Python -wheels available for this wheel. This wheel supports the following Python + env.expect.that_str(no_match_error).contains("""\ configuration settings: //:my_config_setting -To determine the current configuration's Python version, run: - `bazel config ` (shown further below) -and look for - rules_python//python/config_settings:python_version - -If the value is missing, then the "default" Python version is being used, -which has a "null" version value and will not match version constraints. """) - return struct(value = value, no_match_error = no_match_error != None) + return value pkg_aliases( name = "bar_baz", @@ -97,66 +71,123 @@ which has a "null" version value and will not match version constraints. }, extra_aliases = ["my_special"], native = struct( - alias = lambda **kwargs: actual.append(kwargs), + alias = lambda name, actual: got.update({name: actual}), ), select = mock_select, ) # buildifier: disable=unsorted-dict-items - want = [ - { - "name": "bar_baz", - "actual": ":pkg", - }, - { - "name": "pkg", - "actual": struct( - value = { - "//:my_config_setting": "@bar_baz_repo//:pkg", - }, - no_match_error = True, - ), + want = { + "pkg": { + "//:my_config_setting": "@bar_baz_repo//:pkg", }, - { - "name": "whl", - "actual": struct( - value = { - "//:my_config_setting": "@bar_baz_repo//:whl", - }, - no_match_error = True, - ), + } + env.expect.that_dict(got).contains_at_least(want) + +_tests.append(_test_config_setting_aliases) + +def _test_config_setting_aliases_many(env): + # Use this function as it is used in pip_repository + got = {} + actual_no_match_error = [] + + def mock_select(value, no_match_error = None): + actual_no_match_error.append(no_match_error) + env.expect.that_str(no_match_error).contains("""\ +configuration settings: + //:another_config_setting + //:my_config_setting + //:third_config_setting +""") + return value + + pkg_aliases( + name = "bar_baz", + actual = { + ( + "//:my_config_setting", + "//:another_config_setting", + ): "bar_baz_repo", + "//:third_config_setting": "foo_repo", }, - { - "name": "data", - "actual": struct( - value = { - "//:my_config_setting": "@bar_baz_repo//:data", - }, - no_match_error = True, - ), + extra_aliases = ["my_special"], + native = struct( + alias = lambda name, actual: got.update({name: actual}), + ), + select = mock_select, + ) + + # buildifier: disable=unsorted-dict-items + want = { + "my_special": { + ( + "//:my_config_setting", + "//:another_config_setting", + ): "@bar_baz_repo//:my_special", + "//:third_config_setting": "@foo_repo//:my_special", }, - { - "name": "dist_info", - "actual": struct( - value = { - "//:my_config_setting": "@bar_baz_repo//:dist_info", - }, - no_match_error = True, - ), + } + env.expect.that_dict(got).contains_at_least(want) + +_tests.append(_test_config_setting_aliases_many) + +def _test_multiplatform_whl_aliases(env): + # Use this function as it is used in pip_repository + got = {} + actual_no_match_error = [] + + def mock_select(value, no_match_error = None): + actual_no_match_error.append(no_match_error) + env.expect.that_str(no_match_error).contains("""\ +configuration settings: + //:my_config_setting + //_config:is_cp3.9_linux_x86_64 + //_config:is_cp3.9_py3_none_any + //_config:is_cp3.9_py3_none_any_linux_x86_64 + +""") + return value + + pkg_aliases( + name = "bar_baz", + actual = { + whl_config_setting( + filename = "foo-0.0.0-py3-none-any.whl", + version = "3.9", + ): "filename_repo", + whl_config_setting( + filename = "foo-0.0.0-py3-none-any.whl", + version = "3.9", + target_platforms = ["cp39_linux_x86_64"], + ): "filename_repo_for_platform", + whl_config_setting( + version = "3.9", + target_platforms = ["cp39_linux_x86_64"], + ): "bzlmod_repo_for_a_particular_platform", + "//:my_config_setting": "bzlmod_repo", }, - { - "name": "my_special", - "actual": struct( - value = { - "//:my_config_setting": "@bar_baz_repo//:my_special", - }, - no_match_error = True, - ), + extra_aliases = [], + native = struct( + alias = lambda name, actual: got.update({name: actual}), + ), + select = mock_select, + glibc_versions = [], + muslc_versions = [], + osx_versions = [], + ) + + # buildifier: disable=unsorted-dict-items + want = { + "pkg": { + "//:my_config_setting": "@bzlmod_repo//:pkg", + "//_config:is_cp3.9_linux_x86_64": "@bzlmod_repo_for_a_particular_platform//:pkg", + "//_config:is_cp3.9_py3_none_any": "@filename_repo//:pkg", + "//_config:is_cp3.9_py3_none_any_linux_x86_64": "@filename_repo_for_platform//:pkg", }, - ] - env.expect.that_collection(actual).contains_exactly(want) + } + env.expect.that_dict(got).contains_at_least(want) -_tests.append(_test_config_setting_aliases) +_tests.append(_test_multiplatform_whl_aliases) def _test_group_aliases(env): # Use this function as it is used in pip_repository @@ -208,6 +239,232 @@ def _test_group_aliases(env): _tests.append(_test_group_aliases) +def _test_multiplatform_whl_aliases_empty(env): + # Check that we still work with an empty requirements.txt + got = multiplatform_whl_aliases(aliases = {}) + env.expect.that_dict(got).contains_exactly({}) + +_tests.append(_test_multiplatform_whl_aliases_empty) + +def _test_multiplatform_whl_aliases_nofilename(env): + aliases = { + "//:label": "foo", + } + got = multiplatform_whl_aliases(aliases = aliases) + env.expect.that_dict(got).contains_exactly(aliases) + +_tests.append(_test_multiplatform_whl_aliases_nofilename) + +def _test_multiplatform_whl_aliases_nofilename_target_platforms(env): + aliases = { + whl_config_setting( + config_setting = "//:ignored", + version = "3.1", + target_platforms = [ + "cp31_linux_x86_64", + "cp31_linux_aarch64", + ], + ): "foo", + } + + got = multiplatform_whl_aliases(aliases = aliases) + + want = { + "//_config:is_cp3.1_linux_aarch64": "foo", + "//_config:is_cp3.1_linux_x86_64": "foo", + } + env.expect.that_dict(got).contains_exactly(want) + +_tests.append(_test_multiplatform_whl_aliases_nofilename_target_platforms) + +def _test_multiplatform_whl_aliases_filename(env): + aliases = { + whl_config_setting( + filename = "foo-0.0.3-py3-none-any.whl", + version = "3.2", + ): "foo-py3-0.0.3", + whl_config_setting( + filename = "foo-0.0.1-py3-none-any.whl", + version = "3.1", + ): "foo-py3-0.0.1", + whl_config_setting( + filename = "foo-0.0.2-py3-none-any.whl", + version = "3.1", + target_platforms = [ + "cp31_linux_x86_64", + "cp31_linux_aarch64", + ], + ): "foo-0.0.2", + } + got = multiplatform_whl_aliases( + aliases = aliases, + glibc_versions = [], + muslc_versions = [], + osx_versions = [], + ) + want = { + "//_config:is_cp3.1_py3_none_any": "foo-py3-0.0.1", + "//_config:is_cp3.1_py3_none_any_linux_aarch64": "foo-0.0.2", + "//_config:is_cp3.1_py3_none_any_linux_x86_64": "foo-0.0.2", + "//_config:is_cp3.2_py3_none_any": "foo-py3-0.0.3", + } + env.expect.that_dict(got).contains_exactly(want) + +_tests.append(_test_multiplatform_whl_aliases_filename) + +def _test_multiplatform_whl_aliases_filename_versioned(env): + aliases = { + whl_config_setting( + filename = "foo-0.0.1-py3-none-manylinux_2_17_x86_64.whl", + version = "3.1", + ): "glibc-2.17", + whl_config_setting( + filename = "foo-0.0.1-py3-none-manylinux_2_18_x86_64.whl", + version = "3.1", + ): "glibc-2.18", + whl_config_setting( + filename = "foo-0.0.1-py3-none-musllinux_1_1_x86_64.whl", + version = "3.1", + ): "musl-1.1", + } + got = multiplatform_whl_aliases( + aliases = aliases, + glibc_versions = [(2, 17), (2, 18)], + muslc_versions = [(1, 1), (1, 2)], + osx_versions = [], + ) + want = { + # This could just work with: + # select({ + # "//_config:is_gt_eq_2.18": "//_config:is_cp3.1_py3_none_manylinux_x86_64", + # "//conditions:default": "//_config:is_gt_eq_2.18", + # }): "glibc-2.18", + # select({ + # "//_config:is_range_2.17_2.18": "//_config:is_cp3.1_py3_none_manylinux_x86_64", + # "//_config:is_glibc_default": "//_config:is_cp3.1_py3_none_manylinux_x86_64", + # "//conditions:default": "//_config:is_glibc_default", + # }): "glibc-2.17", + # ( + # "//_config:is_gt_musl_1.1": "musl-1.1", + # "//_config:is_musl_default": "musl-1.1", + # ): "musl-1.1", + # + # For this to fully work we need to have the pypi:config_settings.bzl to generate the + # extra targets that use the FeatureFlagInfo and this to generate extra aliases for the + # config settings. + "//_config:is_cp3.1_py3_none_manylinux_2_17_x86_64": "glibc-2.17", + "//_config:is_cp3.1_py3_none_manylinux_2_18_x86_64": "glibc-2.18", + "//_config:is_cp3.1_py3_none_manylinux_x86_64": "glibc-2.17", + "//_config:is_cp3.1_py3_none_musllinux_1_1_x86_64": "musl-1.1", + "//_config:is_cp3.1_py3_none_musllinux_1_2_x86_64": "musl-1.1", + "//_config:is_cp3.1_py3_none_musllinux_x86_64": "musl-1.1", + } + env.expect.that_dict(got).contains_exactly(want) + +_tests.append(_test_multiplatform_whl_aliases_filename_versioned) + +def _mock_alias(container): + return lambda name, **kwargs: container.append(name) + +def _mock_config_setting(container): + def _inner(name, flag_values = None, constraint_values = None, **_): + if flag_values or constraint_values: + container.append(name) + return + + fail("At least one of 'flag_values' or 'constraint_values' needs to be set") + + return _inner + +def _test_config_settings_exist_legacy(env): + aliases = { + whl_config_setting( + version = "3.11", + target_platforms = [ + "cp311_linux_aarch64", + "cp311_linux_x86_64", + ], + ): "repo", + } + available_config_settings = [] + config_settings( + python_versions = ["3.11"], + native = struct( + alias = _mock_alias(available_config_settings), + config_setting = _mock_config_setting(available_config_settings), + ), + target_platforms = [ + "linux_aarch64", + "linux_x86_64", + ], + ) + + got_aliases = multiplatform_whl_aliases( + aliases = aliases, + ) + got = [a.partition(":")[-1] for a in got_aliases] + + env.expect.that_collection(available_config_settings).contains_at_least(got) + +_tests.append(_test_config_settings_exist_legacy) + +def _test_config_settings_exist(env): + for py_tag in ["py2.py3", "py3", "py311", "cp311"]: + if py_tag == "py2.py3": + abis = ["none"] + elif py_tag.startswith("py"): + abis = ["none", "abi3"] + else: + abis = ["none", "abi3", "cp311"] + + for abi_tag in abis: + for platform_tag, kwargs in { + "any": {}, + "macosx_11_0_arm64": { + "osx_versions": [(11, 0)], + "target_platforms": ["osx_aarch64"], + }, + "manylinux_2_17_x86_64": { + "glibc_versions": [(2, 17), (2, 18)], + "target_platforms": ["linux_x86_64"], + }, + "manylinux_2_18_x86_64": { + "glibc_versions": [(2, 17), (2, 18)], + "target_platforms": ["linux_x86_64"], + }, + "musllinux_1_1_aarch64": { + "muslc_versions": [(1, 2), (1, 1), (1, 0)], + "target_platforms": ["linux_aarch64"], + }, + }.items(): + aliases = { + whl_config_setting( + filename = "foo-0.0.1-{}-{}-{}.whl".format(py_tag, abi_tag, platform_tag), + version = "3.11", + ): "repo", + } + available_config_settings = [] + config_settings( + python_versions = ["3.11"], + native = struct( + alias = _mock_alias(available_config_settings), + config_setting = _mock_config_setting(available_config_settings), + ), + **kwargs + ) + + got_aliases = multiplatform_whl_aliases( + aliases = aliases, + glibc_versions = kwargs.get("glibc_versions", []), + muslc_versions = kwargs.get("muslc_versions", []), + osx_versions = kwargs.get("osx_versions", []), + ) + got = [a.partition(":")[-1] for a in got_aliases] + + env.expect.that_collection(available_config_settings).contains_at_least(got) + +_tests.append(_test_config_settings_exist) + def pkg_aliases_test_suite(name): """Create the test suite. diff --git a/tests/pypi/render_pkg_aliases/render_pkg_aliases_test.bzl b/tests/pypi/render_pkg_aliases/render_pkg_aliases_test.bzl index 4741df04b4..a7f7c36b52 100644 --- a/tests/pypi/render_pkg_aliases/render_pkg_aliases_test.bzl +++ b/tests/pypi/render_pkg_aliases/render_pkg_aliases_test.bzl @@ -15,16 +15,17 @@ """render_pkg_aliases tests""" load("@rules_testing//lib:test_suite.bzl", "test_suite") -load("//python/private/pypi:config_settings.bzl", "config_settings") # buildifier: disable=bzl-visibility load( - "//python/private/pypi:render_pkg_aliases.bzl", + "//python/private/pypi:pkg_aliases.bzl", "get_filename_config_settings", +) # buildifier: disable=bzl-visibility +load( + "//python/private/pypi:render_pkg_aliases.bzl", "get_whl_flag_versions", - "multiplatform_whl_aliases", "render_multiplatform_pkg_aliases", "render_pkg_aliases", - "whl_alias", ) # buildifier: disable=bzl-visibility +load("//python/private/pypi:whl_config_setting.bzl", "whl_config_setting") # buildifier: disable=bzl-visibility _tests = [] @@ -42,9 +43,7 @@ _tests.append(_test_empty) def _test_legacy_aliases(env): actual = render_pkg_aliases( aliases = { - "foo": [ - whl_alias(repo = "pypi_foo"), - ], + "foo": "pypi_foo", }, ) @@ -69,15 +68,23 @@ def _test_bzlmod_aliases(env): # Use this function as it is used in pip_repository actual = render_multiplatform_pkg_aliases( aliases = { - "bar-baz": [ - whl_alias(version = "3.2", repo = "pypi_32_bar_baz", config_setting = "//:my_config_setting"), - ], + "bar-baz": { + whl_config_setting( + version = "3.2", + config_setting = "//:my_config_setting", + ): "pypi_32_bar_baz", + whl_config_setting( + version = "3.2", + filename = "foo-0.0.0-py3-none-any.whl", + ): "filename_repo", + }, }, ) want_key = "bar_baz/BUILD.bazel" want_content = """\ load("@rules_python//python/private/pypi:pkg_aliases.bzl", "pkg_aliases") +load("@rules_python//python/private/pypi:whl_config_setting.bzl", "whl_config_setting") package(default_visibility = ["//visibility:public"]) @@ -85,9 +92,16 @@ pkg_aliases( name = "bar_baz", actual = { "//:my_config_setting": "pypi_32_bar_baz", + whl_config_setting( + filename = "foo-0.0.0-py3-none-any.whl", + version = "3.2", + ): "filename_repo", }, group_name = None, extra_aliases = [], + glibc_versions = [], + muslc_versions = [], + osx_versions = [], )""" env.expect.that_str(actual.pop("_config/BUILD.bazel")).equals( @@ -112,14 +126,14 @@ _tests.append(_test_bzlmod_aliases) def _test_aliases_are_created_for_all_wheels(env): actual = render_pkg_aliases( aliases = { - "bar": [ - whl_alias(version = "3.1", repo = "pypi_31_bar"), - whl_alias(version = "3.2", repo = "pypi_32_bar"), - ], - "foo": [ - whl_alias(version = "3.1", repo = "pypi_32_foo"), - whl_alias(version = "3.2", repo = "pypi_31_foo"), - ], + "bar": { + whl_config_setting(version = "3.1"): "pypi_31_bar", + whl_config_setting(version = "3.2"): "pypi_32_bar", + }, + "foo": { + whl_config_setting(version = "3.1"): "pypi_32_foo", + whl_config_setting(version = "3.2"): "pypi_31_foo", + }, }, ) @@ -135,18 +149,18 @@ _tests.append(_test_aliases_are_created_for_all_wheels) def _test_aliases_with_groups(env): actual = render_pkg_aliases( aliases = { - "bar": [ - whl_alias(version = "3.1", repo = "pypi_31_bar"), - whl_alias(version = "3.2", repo = "pypi_32_bar"), - ], - "baz": [ - whl_alias(version = "3.1", repo = "pypi_31_baz"), - whl_alias(version = "3.2", repo = "pypi_32_baz"), - ], - "foo": [ - whl_alias(version = "3.1", repo = "pypi_32_foo"), - whl_alias(version = "3.2", repo = "pypi_31_foo"), - ], + "bar": { + whl_config_setting(version = "3.1"): "pypi_31_bar", + whl_config_setting(version = "3.2"): "pypi_32_bar", + }, + "baz": { + whl_config_setting(version = "3.1"): "pypi_31_baz", + whl_config_setting(version = "3.2"): "pypi_32_baz", + }, + "foo": { + whl_config_setting(version = "3.1"): "pypi_32_foo", + whl_config_setting(version = "3.2"): "pypi_31_foo", + }, }, requirement_cycles = { "group": ["bar", "baz"], @@ -175,7 +189,7 @@ _tests.append(_test_aliases_with_groups) def _test_empty_flag_versions(env): got = get_whl_flag_versions( - aliases = [], + settings = [], ) want = {} env.expect.that_dict(got).contains_exactly(want) @@ -184,10 +198,10 @@ _tests.append(_test_empty_flag_versions) def _test_get_python_versions(env): got = get_whl_flag_versions( - aliases = [ - whl_alias(repo = "foo", version = "3.3"), - whl_alias(repo = "foo", version = "3.2"), - ], + settings = { + whl_config_setting(version = "3.3"): "foo", + whl_config_setting(version = "3.2"): "foo", + }, ) want = { "python_versions": ["3.2", "3.3"], @@ -198,9 +212,9 @@ _tests.append(_test_get_python_versions) def _test_get_python_versions_with_target_platforms(env): got = get_whl_flag_versions( - aliases = [ - whl_alias(repo = "foo", version = "3.3", target_platforms = ["cp33_linux_x86_64"]), - whl_alias(repo = "foo", version = "3.2", target_platforms = ["cp32_linux_x86_64", "cp32_osx_aarch64"]), + settings = [ + whl_config_setting(repo = "foo", version = "3.3", target_platforms = ["cp33_linux_x86_64"]), + whl_config_setting(repo = "foo", version = "3.2", target_platforms = ["cp32_linux_x86_64", "cp32_osx_aarch64"]), ], ) want = { @@ -216,8 +230,8 @@ _tests.append(_test_get_python_versions_with_target_platforms) def _test_get_python_versions_from_filenames(env): got = get_whl_flag_versions( - aliases = [ - whl_alias( + settings = [ + whl_config_setting( repo = "foo", version = "3.3", filename = "foo-0.0.0-py3-none-" + plat + ".whl", @@ -254,8 +268,8 @@ _tests.append(_test_get_python_versions_from_filenames) def _test_get_flag_versions_from_alias_target_platforms(env): got = get_whl_flag_versions( - aliases = [ - whl_alias( + settings = [ + whl_config_setting( repo = "foo", version = "3.3", filename = "foo-0.0.0-py3-none-" + plat + ".whl", @@ -264,7 +278,7 @@ def _test_get_flag_versions_from_alias_target_platforms(env): "windows_x86_64", ] ] + [ - whl_alias( + whl_config_setting( repo = "foo", version = "3.3", filename = "foo-0.0.0-py3-none-any.whl", @@ -467,227 +481,6 @@ def _test_cp37_abi3_manylinux_2_17_musllinux_1_1_aarch64(env): _tests.append(_test_cp37_abi3_manylinux_2_17_musllinux_1_1_aarch64) -def _test_multiplatform_whl_aliases_empty(env): - # Check that we still work with an empty requirements.txt - got = multiplatform_whl_aliases(aliases = []) - env.expect.that_collection(got).contains_exactly([]) - -_tests.append(_test_multiplatform_whl_aliases_empty) - -def _test_multiplatform_whl_aliases_nofilename(env): - aliases = [ - whl_alias( - repo = "foo", - config_setting = "//:label", - version = "3.1", - ), - ] - got = multiplatform_whl_aliases(aliases = aliases) - env.expect.that_collection(got).contains_exactly(aliases) - -_tests.append(_test_multiplatform_whl_aliases_nofilename) - -def _test_multiplatform_whl_aliases_nofilename_target_platforms(env): - aliases = [ - whl_alias( - repo = "foo", - config_setting = "//:ignored", - version = "3.1", - target_platforms = [ - "cp31_linux_x86_64", - "cp31_linux_aarch64", - ], - ), - ] - - got = multiplatform_whl_aliases(aliases = aliases) - - want = [ - whl_alias(config_setting = "//_config:is_cp3.1_linux_x86_64", repo = "foo", version = "3.1"), - whl_alias(config_setting = "//_config:is_cp3.1_linux_aarch64", repo = "foo", version = "3.1"), - ] - env.expect.that_collection(got).contains_exactly(want) - -_tests.append(_test_multiplatform_whl_aliases_nofilename_target_platforms) - -def _test_multiplatform_whl_aliases_filename(env): - aliases = [ - whl_alias( - repo = "foo-py3-0.0.3", - filename = "foo-0.0.3-py3-none-any.whl", - version = "3.2", - ), - whl_alias( - repo = "foo-py3-0.0.1", - filename = "foo-0.0.1-py3-none-any.whl", - version = "3.1", - ), - whl_alias( - repo = "foo-0.0.2", - filename = "foo-0.0.2-py3-none-any.whl", - version = "3.1", - target_platforms = [ - "cp31_linux_x86_64", - "cp31_linux_aarch64", - ], - ), - ] - got = multiplatform_whl_aliases( - aliases = aliases, - glibc_versions = [], - muslc_versions = [], - osx_versions = [], - ) - want = [ - whl_alias(config_setting = "//_config:is_cp3.1_py3_none_any", repo = "foo-py3-0.0.1", version = "3.1"), - whl_alias(config_setting = "//_config:is_cp3.1_py3_none_any_linux_aarch64", repo = "foo-0.0.2", version = "3.1"), - whl_alias(config_setting = "//_config:is_cp3.1_py3_none_any_linux_x86_64", repo = "foo-0.0.2", version = "3.1"), - whl_alias(config_setting = "//_config:is_cp3.2_py3_none_any", repo = "foo-py3-0.0.3", version = "3.2"), - ] - env.expect.that_collection(got).contains_exactly(want) - -_tests.append(_test_multiplatform_whl_aliases_filename) - -def _test_multiplatform_whl_aliases_filename_versioned(env): - aliases = [ - whl_alias( - repo = "glibc-2.17", - filename = "foo-0.0.1-py3-none-manylinux_2_17_x86_64.whl", - version = "3.1", - ), - whl_alias( - repo = "glibc-2.18", - filename = "foo-0.0.1-py3-none-manylinux_2_18_x86_64.whl", - version = "3.1", - ), - whl_alias( - repo = "musl", - filename = "foo-0.0.1-py3-none-musllinux_1_1_x86_64.whl", - version = "3.1", - ), - ] - got = multiplatform_whl_aliases( - aliases = aliases, - glibc_versions = [(2, 17), (2, 18)], - muslc_versions = [(1, 1), (1, 2)], - osx_versions = [], - ) - want = [ - whl_alias(config_setting = "//_config:is_cp3.1_py3_none_manylinux_2_17_x86_64", repo = "glibc-2.17", version = "3.1"), - whl_alias(config_setting = "//_config:is_cp3.1_py3_none_manylinux_2_18_x86_64", repo = "glibc-2.18", version = "3.1"), - whl_alias(config_setting = "//_config:is_cp3.1_py3_none_manylinux_x86_64", repo = "glibc-2.17", version = "3.1"), - whl_alias(config_setting = "//_config:is_cp3.1_py3_none_musllinux_1_1_x86_64", repo = "musl", version = "3.1"), - whl_alias(config_setting = "//_config:is_cp3.1_py3_none_musllinux_1_2_x86_64", repo = "musl", version = "3.1"), - whl_alias(config_setting = "//_config:is_cp3.1_py3_none_musllinux_x86_64", repo = "musl", version = "3.1"), - ] - env.expect.that_collection(got).contains_exactly(want) - -_tests.append(_test_multiplatform_whl_aliases_filename_versioned) - -def _mock_alias(container): - return lambda name, **kwargs: container.append(name) - -def _mock_config_setting(container): - def _inner(name, flag_values = None, constraint_values = None, **_): - if flag_values or constraint_values: - container.append(name) - return - - fail("At least one of 'flag_values' or 'constraint_values' needs to be set") - - return _inner - -def _test_config_settings_exist_legacy(env): - aliases = [ - whl_alias( - repo = "repo", - version = "3.11", - target_platforms = [ - "cp311_linux_aarch64", - "cp311_linux_x86_64", - ], - ), - ] - available_config_settings = [] - config_settings( - python_versions = ["3.11"], - native = struct( - alias = _mock_alias(available_config_settings), - config_setting = _mock_config_setting(available_config_settings), - ), - target_platforms = [ - "linux_aarch64", - "linux_x86_64", - ], - ) - - got_aliases = multiplatform_whl_aliases( - aliases = aliases, - ) - got = [a.config_setting.partition(":")[-1] for a in got_aliases] - - env.expect.that_collection(available_config_settings).contains_at_least(got) - -_tests.append(_test_config_settings_exist_legacy) - -def _test_config_settings_exist(env): - for py_tag in ["py2.py3", "py3", "py311", "cp311"]: - if py_tag == "py2.py3": - abis = ["none"] - elif py_tag.startswith("py"): - abis = ["none", "abi3"] - else: - abis = ["none", "abi3", "cp311"] - - for abi_tag in abis: - for platform_tag, kwargs in { - "any": {}, - "macosx_11_0_arm64": { - "osx_versions": [(11, 0)], - "target_platforms": ["osx_aarch64"], - }, - "manylinux_2_17_x86_64": { - "glibc_versions": [(2, 17), (2, 18)], - "target_platforms": ["linux_x86_64"], - }, - "manylinux_2_18_x86_64": { - "glibc_versions": [(2, 17), (2, 18)], - "target_platforms": ["linux_x86_64"], - }, - "musllinux_1_1_aarch64": { - "muslc_versions": [(1, 2), (1, 1), (1, 0)], - "target_platforms": ["linux_aarch64"], - }, - }.items(): - aliases = [ - whl_alias( - repo = "repo", - filename = "foo-0.0.1-{}-{}-{}.whl".format(py_tag, abi_tag, platform_tag), - version = "3.11", - ), - ] - available_config_settings = [] - config_settings( - python_versions = ["3.11"], - native = struct( - alias = _mock_alias(available_config_settings), - config_setting = _mock_config_setting(available_config_settings), - ), - **kwargs - ) - - got_aliases = multiplatform_whl_aliases( - aliases = aliases, - glibc_versions = kwargs.get("glibc_versions", []), - muslc_versions = kwargs.get("muslc_versions", []), - osx_versions = kwargs.get("osx_versions", []), - ) - got = [a.config_setting.partition(":")[-1] for a in got_aliases] - - env.expect.that_collection(available_config_settings).contains_at_least(got) - -_tests.append(_test_config_settings_exist) - def render_pkg_aliases_test_suite(name): """Create the test suite.