From 7216867782139d46df501c2e46cdd8b59169718f Mon Sep 17 00:00:00 2001 From: nichmor Date: Mon, 22 Apr 2024 10:30:28 +0300 Subject: [PATCH 1/4] feat: add linting support for recipe.yaml --- pixi.lock | 536 ++++++++++++++--------- pixi.toml | 2 + src/rattler_build_conda_compat/lint.py | 406 +++++++++++++++++ src/rattler_build_conda_compat/loader.py | 24 + tests/data/recipe_requirements.yaml | 8 + tests/test_rattler_loader.py | 10 +- 6 files changed, 769 insertions(+), 217 deletions(-) create mode 100644 src/rattler_build_conda_compat/lint.py create mode 100644 tests/data/recipe_requirements.yaml diff --git a/pixi.lock b/pixi.lock index 55ba806..e0d5181 100644 --- a/pixi.lock +++ b/pixi.lock @@ -32,7 +32,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.13.4-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/fmt-10.2.1-h00ab1b0_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-73.2-h59595ed_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.6-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.7-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-7.1.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib_resources-6.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.3-pyhd8ed1ab_0.conda @@ -58,12 +58,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.58.0-h47da74e_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hd590300_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libsolv-0.7.28-hfc55251_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.45.2-h2797004_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.45.3-h2797004_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libssh2-1.11.0-h0841786_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-13.2.0-h7e041cc_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.38.1-h0b41bf4_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.12.6-h232c23b_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.12.6-h232c23b_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.2.13-hd590300_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/lz4-c-1.9.4-hcb278e6_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/lzo-2.10-h516909a_1000.tar.bz2 @@ -86,12 +86,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/pycosat-0.6.6-py312h98912ed_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha2e5f31_6.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.2-hab00c5b_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.3-hab00c5b_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/python-libarchive-c-5.1-py312h7900ff3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/python_abi-3.12-4_cp312.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytz-2024.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.1-py312h98912ed_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/rattler-build-0.14.2-h614bb76_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/rattler-build-0.15.0-h614bb76_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8228510_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.34.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/reproc-14.2.4.post0-hd590300_1.conda @@ -101,7 +101,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/rpds-py-0.18.0-py312h4b3b743_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ruamel.yaml-0.18.6-py312h98912ed_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ruamel.yaml.clib-0.2.8-py312h98912ed_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.5.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.5-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h4845f30_101.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 @@ -144,7 +144,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.13.4-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/fmt-10.2.1-h7728843_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/icu-73.2-hf5e326d_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.6-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.7-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-7.1.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib_resources-6.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.3-pyhd8ed1ab_0.conda @@ -169,9 +169,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/libmambapy-1.5.8-py312h67f5953_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libnghttp2-1.58.0-h64cf6d3_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libsolv-0.7.28-h2d185b6_2.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.45.2-h92b6c6a_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.45.3-h92b6c6a_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libssh2-1.11.0-hd019ec5_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/libxml2-2.12.6-hc0ae0f7_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libxml2-2.12.6-hc0ae0f7_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.2.13-h8a1eda9_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/lz4-c-1.9.4-hf0c8a7f_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/lzo-2.10-haf1e3a3_1000.tar.bz2 @@ -193,12 +193,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/pycosat-0.6.6-py312h104f124_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha2e5f31_6.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.12.2-h9f0c242_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.12.3-h1411813_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/python-libarchive-c-5.1-py312hb401068_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/python_abi-3.12-4_cp312.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytz-2024.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/pyyaml-6.0.1-py312h104f124_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/rattler-build-0.14.2-hd81679c_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/rattler-build-0.15.0-hd81679c_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/readline-8.2-h9e318b2_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.34.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/reproc-14.2.4.post0-h10d778d_1.conda @@ -208,7 +208,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/rpds-py-0.18.0-py312h1b0e595_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/ruamel.yaml-0.18.6-py312h41838bb_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/ruamel.yaml.clib-0.2.8-py312h41838bb_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.5.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/sigtool-0.1.3-h88f4db0_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.5-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/tapi-1100.0.11-h9ce4665_0.tar.bz2 @@ -253,7 +253,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.13.4-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/fmt-10.2.1-h2ffa867_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-73.2-hc8870d7_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.6-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.7-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-7.1.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib_resources-6.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.3-pyhd8ed1ab_0.conda @@ -278,9 +278,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmambapy-1.5.8-py312h344e357_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libnghttp2-1.58.0-ha4dd798_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsolv-0.7.28-h1059232_2.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.45.2-h091b4b1_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.45.3-h091b4b1_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libssh2-1.11.0-h7a5bd25_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-2.12.6-h0d0cfa8_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-2.12.6-h0d0cfa8_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.2.13-h53f4e23_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/lz4-c-1.9.4-hb7217d7_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/lzo-2.10-h642e427_1000.tar.bz2 @@ -302,12 +302,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pycosat-0.6.6-py312h02f2b3b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha2e5f31_6.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.12.2-hdf0ec26_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.12.3-h4a7b5fc_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-libarchive-c-5.1-py312h81bd7bf_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python_abi-3.12-4_cp312.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytz-2024.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyyaml-6.0.1-py312h02f2b3b_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rattler-build-0.14.2-h2b8f702_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rattler-build-0.15.0-h2b8f702_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.2-h92ec313_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.34.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/reproc-14.2.4.post0-h93a5062_1.conda @@ -317,7 +317,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rpds-py-0.18.0-py312h77200ec_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ruamel.yaml-0.18.6-py312he37b823_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ruamel.yaml.clib-0.2.8-py312he37b823_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.5.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/sigtool-0.1.3-h44b9a77_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.5-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tapi-1100.0.11-he4954df_0.tar.bz2 @@ -358,7 +358,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/distro-1.9.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.13.4-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/fmt-10.2.1-h181d51b_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.6-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.7-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-7.1.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib_resources-6.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.3-pyhd8ed1ab_0.conda @@ -376,9 +376,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/libmamba-1.5.8-h3f09ed1_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libmambapy-1.5.8-py312h66cf91f_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libsolv-0.7.28-h12be248_2.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.45.2-hcfcfb64_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.45.3-hcfcfb64_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libssh2-1.11.0-h7dfc565_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-2.12.6-hc3477c8_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-2.12.6-hc3477c8_2.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.2.13-hcfcfb64_5.conda - conda: https://conda.anaconda.org/conda-forge/win-64/lz4-c-1.9.4-hcfcfb64_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/lzo-2.10-he774522_1000.tar.bz2 @@ -400,12 +400,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/pycosat-0.6.6-py312he70551f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyh0701188_6.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.12.2-h2628c8c_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.12.3-h2628c8c_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/win-64/python-libarchive-c-5.1-py312h2e8e312_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/python_abi-3.12-4_cp312.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytz-2024.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/pyyaml-6.0.1-py312he70551f_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/rattler-build-0.14.2-h7ea99a0_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/rattler-build-0.15.0-h7ea99a0_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.34.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/reproc-14.2.4.post0-hcfcfb64_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/reproc-cpp-14.2.4.post0-h63175ca_1.conda @@ -414,7 +414,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/rpds-py-0.18.0-py312hfccd98a_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/ruamel.yaml-0.18.6-py312he70551f_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/ruamel.yaml.clib-0.2.8-py312he70551f_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.5.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.5-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h5226925_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 @@ -467,7 +467,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.13.4-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/fmt-10.2.1-h00ab1b0_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-73.2-h59595ed_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.6-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.7-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-7.1.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib_resources-6.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda @@ -494,12 +494,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.58.0-h47da74e_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hd590300_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libsolv-0.7.28-hfc55251_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.45.2-h2797004_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.45.3-h2797004_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libssh2-1.11.0-h0841786_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-13.2.0-h7e041cc_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.38.1-h0b41bf4_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.12.6-h232c23b_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.12.6-h232c23b_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.2.13-hd590300_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/lz4-c-1.9.4-hcb278e6_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/lzo-2.10-h516909a_1000.tar.bz2 @@ -523,12 +523,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha2e5f31_6.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.1.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.2-hab00c5b_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.3-hab00c5b_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/python-libarchive-c-5.1-py312h7900ff3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/python_abi-3.12-4_cp312.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytz-2024.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.1-py312h98912ed_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/rattler-build-0.14.2-h614bb76_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/rattler-build-0.15.0-h614bb76_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8228510_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.34.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/reproc-14.2.4.post0-hd590300_1.conda @@ -538,8 +538,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/rpds-py-0.18.0-py312h4b3b743_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ruamel.yaml-0.18.6-py312h98912ed_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ruamel.yaml.clib-0.2.8-py312h98912ed_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/ruff-0.3.5-py312h9118e91_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ruff-0.3.7-py312h9118e91_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.5.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.5-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/syrupy-4.6.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h4845f30_101.conda @@ -584,7 +584,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.13.4-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/fmt-10.2.1-h7728843_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/icu-73.2-hf5e326d_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.6-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.7-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-7.1.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib_resources-6.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda @@ -610,9 +610,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/libmambapy-1.5.8-py312h67f5953_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libnghttp2-1.58.0-h64cf6d3_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libsolv-0.7.28-h2d185b6_2.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.45.2-h92b6c6a_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.45.3-h92b6c6a_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libssh2-1.11.0-hd019ec5_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/libxml2-2.12.6-hc0ae0f7_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libxml2-2.12.6-hc0ae0f7_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.2.13-h8a1eda9_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/lz4-c-1.9.4-hf0c8a7f_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/lzo-2.10-haf1e3a3_1000.tar.bz2 @@ -635,12 +635,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha2e5f31_6.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.1.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.12.2-h9f0c242_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.12.3-h1411813_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/python-libarchive-c-5.1-py312hb401068_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/python_abi-3.12-4_cp312.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytz-2024.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/pyyaml-6.0.1-py312h104f124_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/rattler-build-0.14.2-hd81679c_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/rattler-build-0.15.0-hd81679c_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/readline-8.2-h9e318b2_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.34.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/reproc-14.2.4.post0-h10d778d_1.conda @@ -650,8 +650,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/rpds-py-0.18.0-py312h1b0e595_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/ruamel.yaml-0.18.6-py312h41838bb_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/ruamel.yaml.clib-0.2.8-py312h41838bb_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/ruff-0.3.5-py312h1bc86af_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ruff-0.3.7-py312h1bc86af_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.5.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/sigtool-0.1.3-h88f4db0_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.5-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/syrupy-4.6.1-pyhd8ed1ab_0.conda @@ -698,7 +698,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.13.4-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/fmt-10.2.1-h2ffa867_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-73.2-hc8870d7_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.6-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.7-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-7.1.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib_resources-6.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda @@ -724,9 +724,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmambapy-1.5.8-py312h344e357_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libnghttp2-1.58.0-ha4dd798_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsolv-0.7.28-h1059232_2.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.45.2-h091b4b1_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.45.3-h091b4b1_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libssh2-1.11.0-h7a5bd25_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-2.12.6-h0d0cfa8_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-2.12.6-h0d0cfa8_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.2.13-h53f4e23_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/lz4-c-1.9.4-hb7217d7_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/lzo-2.10-h642e427_1000.tar.bz2 @@ -749,12 +749,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha2e5f31_6.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.1.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.12.2-hdf0ec26_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.12.3-h4a7b5fc_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-libarchive-c-5.1-py312h81bd7bf_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python_abi-3.12-4_cp312.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytz-2024.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyyaml-6.0.1-py312h02f2b3b_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rattler-build-0.14.2-h2b8f702_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rattler-build-0.15.0-h2b8f702_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.2-h92ec313_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.34.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/reproc-14.2.4.post0-h93a5062_1.conda @@ -764,8 +764,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rpds-py-0.18.0-py312h77200ec_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ruamel.yaml-0.18.6-py312he37b823_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ruamel.yaml.clib-0.2.8-py312he37b823_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ruff-0.3.5-py312h1ae9fbf_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ruff-0.3.7-py312h1ae9fbf_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.5.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/sigtool-0.1.3-h44b9a77_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.5-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/syrupy-4.6.1-pyhd8ed1ab_0.conda @@ -808,7 +808,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.13.4-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/fmt-10.2.1-h181d51b_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.6-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.7-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-7.1.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib_resources-6.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda @@ -827,9 +827,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/libmamba-1.5.8-h3f09ed1_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libmambapy-1.5.8-py312h66cf91f_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libsolv-0.7.28-h12be248_2.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.45.2-hcfcfb64_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.45.3-hcfcfb64_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libssh2-1.11.0-h7dfc565_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-2.12.6-hc3477c8_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-2.12.6-hc3477c8_2.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.2.13-hcfcfb64_5.conda - conda: https://conda.anaconda.org/conda-forge/win-64/lz4-c-1.9.4-hcfcfb64_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/lzo-2.10-he774522_1000.tar.bz2 @@ -852,12 +852,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyh0701188_6.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.1.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.12.2-h2628c8c_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.12.3-h2628c8c_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/win-64/python-libarchive-c-5.1-py312h2e8e312_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/python_abi-3.12-4_cp312.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytz-2024.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/pyyaml-6.0.1-py312he70551f_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/rattler-build-0.14.2-h7ea99a0_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/rattler-build-0.15.0-h7ea99a0_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/referencing-0.34.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/reproc-14.2.4.post0-hcfcfb64_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/reproc-cpp-14.2.4.post0-h63175ca_1.conda @@ -866,8 +866,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/rpds-py-0.18.0-py312hfccd98a_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/ruamel.yaml-0.18.6-py312he70551f_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/ruamel.yaml.clib-0.2.8-py312he70551f_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/ruff-0.3.5-py312h60fbdae_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ruff-0.3.7-py312h60fbdae_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.5.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.5-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/syrupy-4.6.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h5226925_1.conda @@ -965,6 +965,8 @@ packages: - soupsieve >=1.2 license: MIT license_family: MIT + purls: + - pkg:pypi/beautifulsoup4 size: 118200 timestamp: 1705564819537 - kind: conda @@ -980,6 +982,8 @@ packages: - python ==2.7.*|>=3.7 license: BSD-3-Clause license_family: BSD + purls: + - pkg:pypi/boltons size: 297896 timestamp: 1711936529147 - kind: conda @@ -1000,6 +1004,8 @@ packages: - libbrotlicommon 1.1.0 hd590300_1 license: MIT license_family: MIT + purls: + - pkg:pypi/brotli size: 350604 timestamp: 1695990206327 - kind: conda @@ -1021,6 +1027,8 @@ packages: - libbrotlicommon 1.1.0 hcfcfb64_1 license: MIT license_family: MIT + purls: + - pkg:pypi/brotli size: 322514 timestamp: 1695991054894 - kind: conda @@ -1041,6 +1049,8 @@ packages: - libbrotlicommon 1.1.0 hb547adb_1 license: MIT license_family: MIT + purls: + - pkg:pypi/brotli size: 343435 timestamp: 1695990731924 - kind: conda @@ -1060,6 +1070,8 @@ packages: - libbrotlicommon 1.1.0 h0dc2134_1 license: MIT license_family: MIT + purls: + - pkg:pypi/brotli size: 366883 timestamp: 1695990710194 - kind: conda @@ -1079,6 +1091,8 @@ packages: - tomli license: MIT license_family: MIT + purls: + - pkg:pypi/build size: 17759 timestamp: 1631843776429 - kind: conda @@ -1309,6 +1323,8 @@ packages: depends: - python >=3.7 license: ISC + purls: + - pkg:pypi/certifi size: 160559 timestamp: 1707022289175 - kind: conda @@ -1326,6 +1342,8 @@ packages: - python_abi 3.12.* *_cp312 license: MIT license_family: MIT + purls: + - pkg:pypi/cffi size: 282370 timestamp: 1696002004433 - kind: conda @@ -1344,6 +1362,8 @@ packages: - python_abi 3.12.* *_cp312 license: MIT license_family: MIT + purls: + - pkg:pypi/cffi size: 284245 timestamp: 1696002181644 - kind: conda @@ -1363,6 +1383,8 @@ packages: - vc14_runtime >=14.29.30139 license: MIT license_family: MIT + purls: + - pkg:pypi/cffi size: 287805 timestamp: 1696002408940 - kind: conda @@ -1381,6 +1403,8 @@ packages: - python_abi 3.12.* *_cp312 license: MIT license_family: MIT + purls: + - pkg:pypi/cffi size: 294523 timestamp: 1696001868949 - kind: conda @@ -1562,6 +1586,8 @@ packages: - conda-env >=2.6 license: BSD-3-Clause license_family: BSD + purls: + - pkg:pypi/conda size: 1198612 timestamp: 1711446530411 - kind: conda @@ -1599,6 +1625,8 @@ packages: - conda-content-trust >=0.1.1 license: BSD-3-Clause license_family: BSD + purls: + - pkg:pypi/conda size: 1195527 timestamp: 1711445992988 - kind: conda @@ -1637,6 +1665,8 @@ packages: - conda-env >=2.6 license: BSD-3-Clause license_family: BSD + purls: + - pkg:pypi/conda size: 1197572 timestamp: 1711446174975 - kind: conda @@ -1674,6 +1704,8 @@ packages: - conda-build >=24.3 license: BSD-3-Clause license_family: BSD + purls: + - pkg:pypi/conda size: 1196619 timestamp: 1711446125221 - kind: conda @@ -1712,6 +1744,8 @@ packages: - conda-verify >=3.1.0 license: BSD-3-Clause license_family: BSD + purls: + - pkg:pypi/conda-build size: 752036 timestamp: 1711609193364 - kind: conda @@ -1751,6 +1785,8 @@ packages: - conda-verify >=3.1.0 license: BSD-3-Clause license_family: BSD + purls: + - pkg:pypi/conda-build size: 752571 timestamp: 1711608769290 - kind: conda @@ -1791,6 +1827,8 @@ packages: - conda-verify >=3.1.0 license: BSD-3-Clause license_family: BSD + purls: + - pkg:pypi/conda-build size: 751442 timestamp: 1711608951046 - kind: conda @@ -1830,6 +1868,8 @@ packages: - conda-verify >=3.1.0 license: BSD-3-Clause license_family: BSD + purls: + - pkg:pypi/conda-build size: 753262 timestamp: 1711608860452 - kind: conda @@ -1852,6 +1892,8 @@ packages: - pyyaml >=6 license: BSD-3-Clause license_family: BSD + purls: + - pkg:pypi/conda-index size: 176354 timestamp: 1708062210737 - kind: conda @@ -1870,6 +1912,8 @@ packages: - python >=3.8 license: BSD-3-Clause license_family: BSD + purls: + - pkg:pypi/conda-libmamba-solver size: 41157 timestamp: 1706566194042 - kind: conda @@ -1887,6 +1931,8 @@ packages: - zstandard >=0.15 license: BSD-3-Clause license_family: BSD + purls: + - pkg:pypi/conda-package-handling size: 255143 timestamp: 1691048232276 - kind: conda @@ -1903,6 +1949,8 @@ packages: - zstandard >=0.15 license: BSD-3-Clause license_family: BSD + purls: + - pkg:pypi/conda-package-streaming size: 19183 timestamp: 1691009348105 - kind: conda @@ -2055,21 +2103,21 @@ packages: timestamp: 1692901622519 - kind: conda name: idna - version: '3.6' + version: '3.7' build: pyhd8ed1ab_0 subdir: noarch noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/idna-3.6-pyhd8ed1ab_0.conda - sha256: 6ee4c986d69ce61e60a20b2459b6f2027baeba153f0a64995fd3cb47c2cc7e07 - md5: 1a76f09108576397c41c0b0c5bd84134 + url: https://conda.anaconda.org/conda-forge/noarch/idna-3.7-pyhd8ed1ab_0.conda + sha256: 9687ee909ed46169395d4f99a0ee94b80a52f87bed69cd454bb6d37ffeb0ec7b + md5: c0cc1420498b17414d8617d0b9f506ca depends: - python >=3.6 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/idna - size: 50124 - timestamp: 1701027126206 + size: 52718 + timestamp: 1713279497047 - kind: conda name: importlib-metadata version: 7.1.0 @@ -2084,6 +2132,8 @@ packages: - zipp >=0.5 license: Apache-2.0 license_family: APACHE + purls: + - pkg:pypi/importlib-metadata size: 27043 timestamp: 1710971498183 - kind: conda @@ -2251,6 +2301,8 @@ packages: - rpds-py >=0.7.1 license: MIT license_family: MIT + purls: + - pkg:pypi/jsonschema size: 72817 timestamp: 1705707712082 - kind: conda @@ -3149,6 +3201,8 @@ packages: - yaml-cpp >=0.8.0,<0.9.0a0 license: BSD-3-Clause license_family: BSD + purls: + - pkg:pypi/libmambapy size: 255134 timestamp: 1711395612039 - kind: conda @@ -3172,6 +3226,8 @@ packages: - yaml-cpp >=0.8.0,<0.9.0a0 license: BSD-3-Clause license_family: BSD + purls: + - pkg:pypi/libmambapy size: 634593 timestamp: 1711396223183 - kind: conda @@ -3193,6 +3249,8 @@ packages: - yaml-cpp >=0.8.0,<0.9.0a0 license: BSD-3-Clause license_family: BSD + purls: + - pkg:pypi/libmambapy size: 272088 timestamp: 1711395982732 - kind: conda @@ -3215,6 +3273,8 @@ packages: - yaml-cpp >=0.8.0,<0.9.0a0 license: BSD-3-Clause license_family: BSD + purls: + - pkg:pypi/libmambapy size: 306497 timestamp: 1711395345839 - kind: conda @@ -3363,59 +3423,59 @@ packages: timestamp: 1711553127824 - kind: conda name: libsqlite - version: 3.45.2 + version: 3.45.3 build: h091b4b1_0 subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.45.2-h091b4b1_0.conda - sha256: 7c234320a1a2132b9cc972aaa06bb215bb220a5b1addb0bed7a5a321c805920e - md5: 9d07427ee5bd9afd1e11ce14368a48d6 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.45.3-h091b4b1_0.conda + sha256: 4337f466eb55bbdc74e168b52ec8c38f598e3664244ec7a2536009036e2066cc + md5: c8c1186c7f3351f6ffddb97b1f54fc58 depends: - libzlib >=1.2.13,<1.3.0a0 license: Unlicense - size: 825300 - timestamp: 1710255078823 + size: 824794 + timestamp: 1713367748819 - kind: conda name: libsqlite - version: 3.45.2 + version: 3.45.3 build: h2797004_0 subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.45.2-h2797004_0.conda - sha256: 8cdbeb7902729e319510a82d7c642402981818702b58812af265ef55d1315473 - md5: 866983a220e27a80cb75e85cb30466a1 + url: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.45.3-h2797004_0.conda + sha256: e2273d6860eadcf714a759ffb6dc24a69cfd01f2a0ea9d6c20f86049b9334e0c + md5: b3316cbe90249da4f8e84cd66e1cc55b depends: - libgcc-ng >=12 - libzlib >=1.2.13,<1.3.0a0 license: Unlicense - size: 857489 - timestamp: 1710254744982 + size: 859858 + timestamp: 1713367435849 - kind: conda name: libsqlite - version: 3.45.2 + version: 3.45.3 build: h92b6c6a_0 subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.45.2-h92b6c6a_0.conda - sha256: 320ec73a4e3dd377757a2595770b8137ec4583df4d7782472d76377cdbdc4543 - md5: 086f56e13a96a6cfb1bf640505ae6b70 + url: https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.45.3-h92b6c6a_0.conda + sha256: 4d44b68fb29dcbc2216a8cae0b274b02ef9b4ae05d1d0f785362ed30b91c9b52 + md5: 68e462226209f35182ef66eda0f794ff depends: - libzlib >=1.2.13,<1.3.0a0 license: Unlicense - size: 902355 - timestamp: 1710254991672 + size: 902546 + timestamp: 1713367776445 - kind: conda name: libsqlite - version: 3.45.2 + version: 3.45.3 build: hcfcfb64_0 subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.45.2-hcfcfb64_0.conda - sha256: 4bb24b986550275a6d02835150d943c4c675808d05c0efc5c2a22154d007a69f - md5: f95359f8dc5abf7da7776ece9ef10bc5 + url: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.45.3-hcfcfb64_0.conda + sha256: 06ec75faa51d7ec6d5db98889e869b579a9df19d7d3d9baff8359627da4a3b7e + md5: 73f5dc8e2d55d9a1e14b11f49c3b4a28 depends: - ucrt >=10.0.20348.0 - vc >=14.2,<15 - vc14_runtime >=14.29.30139 license: Unlicense - size: 869606 - timestamp: 1710255095740 + size: 870518 + timestamp: 1713367888406 - kind: conda name: libssh2 version: 1.11.0 @@ -3524,12 +3584,12 @@ packages: - kind: conda name: libxml2 version: 2.12.6 - build: h0d0cfa8_1 - build_number: 1 + build: h0d0cfa8_2 + build_number: 2 subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-2.12.6-h0d0cfa8_1.conda - sha256: f18775ca8494ead5451d4acfc53fa7ebf7a8b5ed04c43bcc50fab847c9780cb3 - md5: c08526c957192192e1e7b4f622761144 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-2.12.6-h0d0cfa8_2.conda + sha256: a5c10af641d6accf3effb3c3a3c594d931bb374f9e3e796719f3ecf769cfb0fc + md5: 27577d561de7659487b062c363d8a527 depends: - icu >=73.2,<74.0a0 - libiconv >=1.17,<2.0a0 @@ -3537,17 +3597,17 @@ packages: - xz >=5.2.6,<6.0a0 license: MIT license_family: MIT - size: 588539 - timestamp: 1711318256840 + size: 588638 + timestamp: 1713314780561 - kind: conda name: libxml2 version: 2.12.6 - build: h232c23b_1 - build_number: 1 + build: h232c23b_2 + build_number: 2 subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.12.6-h232c23b_1.conda - sha256: c0bd693bb1a7e5aba388a0c79be16ff92e2411e03aaa920f94b4b33bf099e254 - md5: 6853448e9ca1cfd5f15382afd2a6d123 + url: https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.12.6-h232c23b_2.conda + sha256: 0fd41df7211aae04f492c8550ce10238e8cfa8b1abebc2215a983c5e66d284ea + md5: 9a3a42df8a95f65334dfc7b80da1195d depends: - icu >=73.2,<74.0a0 - libgcc-ng >=12 @@ -3556,17 +3616,17 @@ packages: - xz >=5.2.6,<6.0a0 license: MIT license_family: MIT - size: 705994 - timestamp: 1711318087106 + size: 704938 + timestamp: 1713314718258 - kind: conda name: libxml2 version: 2.12.6 - build: hc0ae0f7_1 - build_number: 1 + build: hc0ae0f7_2 + build_number: 2 subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/libxml2-2.12.6-hc0ae0f7_1.conda - sha256: 07a5dc7316d4c1ff3d924df6a76e6a13380d702fa5b3b1889e56d0672e5b8201 - md5: bd85e0ca9e1ffaadc3b56079fd956035 + url: https://conda.anaconda.org/conda-forge/osx-64/libxml2-2.12.6-hc0ae0f7_2.conda + sha256: 2598a525b1769338f96c3d4badad7d8b95c9ddcea86db3f9479a274803190e5c + md5: 50b997370584f2c83ca0c38e9028eab9 depends: - icu >=73.2,<74.0a0 - libiconv >=1.17,<2.0a0 @@ -3574,17 +3634,17 @@ packages: - xz >=5.2.6,<6.0a0 license: MIT license_family: MIT - size: 620164 - timestamp: 1711318305209 + size: 619622 + timestamp: 1713314870641 - kind: conda name: libxml2 version: 2.12.6 - build: hc3477c8_1 - build_number: 1 + build: hc3477c8_2 + build_number: 2 subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/libxml2-2.12.6-hc3477c8_1.conda - sha256: 1846c1318a5987e7315ca3648b55b38e5cfd9853370803a0f5159bc0071609c1 - md5: eb9f59dd51f50f5aa369813fa63ba569 + url: https://conda.anaconda.org/conda-forge/win-64/libxml2-2.12.6-hc3477c8_2.conda + sha256: 9a717cad6da52c84cfc490f7d52203c4cbc9e0e0389941fc6523273be5ccd17a + md5: ac7af7a949db01dae61ddc48f4a93d79 depends: - libiconv >=1.17,<2.0a0 - libzlib >=1.2.13,<1.3.0a0 @@ -3593,8 +3653,8 @@ packages: - vc14_runtime >=14.29.30139 license: MIT license_family: MIT - size: 1640801 - timestamp: 1711318467301 + size: 1589904 + timestamp: 1713315104803 - kind: conda name: libzlib version: 1.2.13 @@ -3902,6 +3962,8 @@ packages: - vc >=14.2,<15 - vc14_runtime >=14.29.30139 license: BSD-3-Clause AND MIT + purls: + - pkg:pypi/menuinst size: 125911 timestamp: 1705068951324 - kind: conda @@ -3916,6 +3978,8 @@ packages: - python >=3.12,<3.13.0a0 - python_abi 3.12.* *_cp312 license: BSD-3-Clause AND MIT + purls: + - pkg:pypi/menuinst size: 158511 timestamp: 1705068403609 - kind: conda @@ -3931,6 +3995,8 @@ packages: - python >=3.12,<3.13.0a0 *_cpython - python_abi 3.12.* *_cp312 license: BSD-3-Clause AND MIT + purls: + - pkg:pypi/menuinst size: 159866 timestamp: 1705068748439 - kind: conda @@ -3945,6 +4011,8 @@ packages: - python >=3.12,<3.13.0a0 - python_abi 3.12.* *_cp312 license: BSD-3-Clause AND MIT + purls: + - pkg:pypi/menuinst size: 159905 timestamp: 1705068695868 - kind: conda @@ -4158,6 +4226,8 @@ packages: - tomli license: MIT license_family: MIT + purls: + - pkg:pypi/pep517 size: 19044 timestamp: 1667916747996 - kind: conda @@ -4318,6 +4388,8 @@ packages: - python_abi 3.12.* *_cp312 license: Apache-2.0 license_family: Apache + purls: + - pkg:pypi/lief size: 537434 timestamp: 1711566440502 - kind: conda @@ -4337,6 +4409,8 @@ packages: - python_abi 3.12.* *_cp312 license: Apache-2.0 license_family: Apache + purls: + - pkg:pypi/lief size: 539467 timestamp: 1711566025401 - kind: conda @@ -4359,6 +4433,8 @@ packages: - vc14_runtime >=14.38.33130 license: Apache-2.0 license_family: Apache + purls: + - pkg:pypi/lief size: 561588 timestamp: 1711565313159 - kind: conda @@ -4378,6 +4454,8 @@ packages: - python_abi 3.12.* *_cp312 license: Apache-2.0 license_family: Apache + purls: + - pkg:pypi/lief size: 758297 timestamp: 1711563364357 - kind: conda @@ -4408,6 +4486,8 @@ packages: - python_abi 3.12.* *_cp312 license: MIT license_family: MIT + purls: + - pkg:pypi/pycosat size: 86424 timestamp: 1696356256622 - kind: conda @@ -4423,6 +4503,8 @@ packages: - python_abi 3.12.* *_cp312 license: MIT license_family: MIT + purls: + - pkg:pypi/pycosat size: 89221 timestamp: 1696356180943 - kind: conda @@ -4439,6 +4521,8 @@ packages: - python_abi 3.12.* *_cp312 license: MIT license_family: MIT + purls: + - pkg:pypi/pycosat size: 88549 timestamp: 1696355931150 - kind: conda @@ -4457,6 +4541,8 @@ packages: - vc14_runtime >=14.29.30139 license: MIT license_family: MIT + purls: + - pkg:pypi/pycosat size: 77670 timestamp: 1696356641443 - kind: conda @@ -4542,75 +4628,72 @@ packages: timestamp: 1709992719691 - kind: conda name: python - version: 3.12.2 - build: h2628c8c_0_cpython - subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/python-3.12.2-h2628c8c_0_cpython.conda - sha256: b8eda863b48ae4531635e23fd15e759d93212b6204c6847d591e25fa5fd67477 - md5: be8803e9f75a477df61d4aabea3c1246 + version: 3.12.3 + build: h1411813_0_cpython + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/python-3.12.3-h1411813_0_cpython.conda + sha256: 3b327ffc152a245011011d1d730781577a8274fde1cf6243f073749ead8f1c2a + md5: df1448ec6cbf8eceb03d29003cf72ae6 depends: + - __osx >=10.9 - bzip2 >=1.0.8,<2.0a0 - - libexpat >=2.5.0,<3.0a0 + - libexpat >=2.6.2,<3.0a0 - libffi >=3.4,<4.0a0 - - libsqlite >=3.45.1,<4.0a0 + - libsqlite >=3.45.2,<4.0a0 - libzlib >=1.2.13,<1.3.0a0 + - ncurses >=6.4.20240210,<7.0a0 - openssl >=3.2.1,<4.0a0 + - readline >=8.2,<9.0a0 - tk >=8.6.13,<8.7.0a0 - tzdata - - ucrt >=10.0.20348.0 - - vc >=14.2,<15 - - vc14_runtime >=14.29.30139 - xz >=5.2.6,<6.0a0 constrains: - python_abi 3.12.* *_cp312 license: Python-2.0 - size: 16083296 - timestamp: 1708116662336 + size: 14557341 + timestamp: 1713208068012 - kind: conda name: python - version: 3.12.2 - build: h9f0c242_0_cpython - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/python-3.12.2-h9f0c242_0_cpython.conda - sha256: 7647ac06c3798a182a4bcb1ff58864f1ef81eb3acea6971295304c23e43252fb - md5: 0179b8007ba008cf5bec11f3b3853902 + version: 3.12.3 + build: h2628c8c_0_cpython + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/python-3.12.3-h2628c8c_0_cpython.conda + sha256: 1a95494abe572a8819c933f978df89f00bde72ea9432d46a70632599e8029ea4 + md5: f07c8c5dd98767f9a652de5d039b284e depends: - bzip2 >=1.0.8,<2.0a0 - - libexpat >=2.5.0,<3.0a0 + - libexpat >=2.6.2,<3.0a0 - libffi >=3.4,<4.0a0 - - libsqlite >=3.45.1,<4.0a0 + - libsqlite >=3.45.2,<4.0a0 - libzlib >=1.2.13,<1.3.0a0 - - ncurses >=6.4,<7.0a0 - openssl >=3.2.1,<4.0a0 - - readline >=8.2,<9.0a0 - tk >=8.6.13,<8.7.0a0 - tzdata + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 - xz >=5.2.6,<6.0a0 constrains: - python_abi 3.12.* *_cp312 license: Python-2.0 - size: 14596811 - timestamp: 1708118065292 + size: 16179248 + timestamp: 1713205644673 - kind: conda name: python - version: 3.12.2 - build: hab00c5b_0_cpython - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.2-hab00c5b_0_cpython.conda - sha256: ddb7a2d8d78046bda5d7631e6814f9468d2eb054e10f86f4648c9d1fdaa30c0f - md5: ad7b68400f3a6ebe72b00be093c7f301 + version: 3.12.3 + build: h4a7b5fc_0_cpython + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.12.3-h4a7b5fc_0_cpython.conda + sha256: c761fb3713ea66bce3889b33b6f400afb2dd192d1fc2686446e9d8166cfcec6b + md5: 8643ab37bece6ae8f112464068d9df9c depends: + - __osx >=11.0 - bzip2 >=1.0.8,<2.0a0 - - ld_impl_linux-64 >=2.36.1 - - libexpat >=2.5.0,<3.0a0 + - libexpat >=2.6.2,<3.0a0 - libffi >=3.4,<4.0a0 - - libgcc-ng >=12 - - libnsl >=2.0.1,<2.1.0a0 - - libsqlite >=3.45.1,<4.0a0 - - libuuid >=2.38.1,<3.0a0 - - libxcrypt >=4.4.36 + - libsqlite >=3.45.2,<4.0a0 - libzlib >=1.2.13,<1.3.0a0 - - ncurses >=6.4,<7.0a0 + - ncurses >=6.4.20240210,<7.0a0 - openssl >=3.2.1,<4.0a0 - readline >=8.2,<9.0a0 - tk >=8.6.13,<8.7.0a0 @@ -4619,23 +4702,28 @@ packages: constrains: - python_abi 3.12.* *_cp312 license: Python-2.0 - size: 32312631 - timestamp: 1708118077305 + size: 13207557 + timestamp: 1713206576646 - kind: conda name: python - version: 3.12.2 - build: hdf0ec26_0_cpython - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.12.2-hdf0ec26_0_cpython.conda - sha256: ccd6c55a286d51d907c878ed2bfa7d1becce0fee71374a9386c5eb90d803ac72 - md5: 85e91138ae921a2771f57a50120272bd + version: 3.12.3 + build: hab00c5b_0_cpython + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.3-hab00c5b_0_cpython.conda + sha256: f9865bcbff69f15fd89a33a2da12ad616e98d65ce7c83c644b92e66e5016b227 + md5: 2540b74d304f71d3e89c81209db4db84 depends: - bzip2 >=1.0.8,<2.0a0 - - libexpat >=2.5.0,<3.0a0 + - ld_impl_linux-64 >=2.36.1 + - libexpat >=2.6.2,<3.0a0 - libffi >=3.4,<4.0a0 - - libsqlite >=3.45.1,<4.0a0 + - libgcc-ng >=12 + - libnsl >=2.0.1,<2.1.0a0 + - libsqlite >=3.45.2,<4.0a0 + - libuuid >=2.38.1,<3.0a0 + - libxcrypt >=4.4.36 - libzlib >=1.2.13,<1.3.0a0 - - ncurses >=6.4,<7.0a0 + - ncurses >=6.4.20240210,<7.0a0 - openssl >=3.2.1,<4.0a0 - readline >=8.2,<9.0a0 - tk >=8.6.13,<8.7.0a0 @@ -4644,8 +4732,8 @@ packages: constrains: - python_abi 3.12.* *_cp312 license: Python-2.0 - size: 13085901 - timestamp: 1708117361381 + size: 31991381 + timestamp: 1713208036041 - kind: conda name: python-libarchive-c version: '5.1' @@ -4812,6 +4900,8 @@ packages: - yaml >=0.2.5,<0.3.0a0 license: MIT license_family: MIT + purls: + - pkg:pypi/pyyaml size: 182705 timestamp: 1695373895409 - kind: conda @@ -4829,6 +4919,8 @@ packages: - yaml >=0.2.5,<0.3.0a0 license: MIT license_family: MIT + purls: + - pkg:pypi/pyyaml size: 185636 timestamp: 1695373742454 - kind: conda @@ -4847,6 +4939,8 @@ packages: - yaml >=0.2.5,<0.3.0a0 license: MIT license_family: MIT + purls: + - pkg:pypi/pyyaml size: 196583 timestamp: 1695373632212 - kind: conda @@ -4867,72 +4961,74 @@ packages: - yaml >=0.2.5,<0.3.0a0 license: MIT license_family: MIT + purls: + - pkg:pypi/pyyaml size: 167932 timestamp: 1695374097139 - kind: conda name: rattler-build - version: 0.14.2 + version: 0.15.0 build: h2b8f702_0 subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/rattler-build-0.14.2-h2b8f702_0.conda - sha256: 4b2389bf30a87e5a6986aa0a67855a3f3c1c64dd8e7dbf2e384628e7e840f179 - md5: 8b5e3ba56307739cd8cd9c227e3f24ea + url: https://conda.anaconda.org/conda-forge/osx-arm64/rattler-build-0.15.0-h2b8f702_0.conda + sha256: 4fd077a49b920ba15fc9446471fb1edddcf9c638eb77f2a504fe25f2424aa7a2 + md5: 5f1437b3e04e7b9b140d87364d3f892d depends: - libcxx >=16 constrains: - __osx >=11.0 license: BSD-3-Clause license_family: BSD - size: 7534946 - timestamp: 1712347699584 + size: 7583997 + timestamp: 1713391566597 - kind: conda name: rattler-build - version: 0.14.2 + version: 0.15.0 build: h614bb76_0 subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/rattler-build-0.14.2-h614bb76_0.conda - sha256: 618cbd47da85a1f0718a7d206cfacf9f5989d64adc2b5cd5b7b52a963a0c7ca4 - md5: 9b9414e7a6c5f14a42f94aa8363135eb + url: https://conda.anaconda.org/conda-forge/linux-64/rattler-build-0.15.0-h614bb76_0.conda + sha256: 6f0fdf6e4cbb8416df982e4814e112c0e26a8eb9e6184a640e5ff155a9063796 + md5: 7e5875d2427c0c38a399648036583647 depends: - libgcc-ng >=12 - libstdcxx-ng >=12 - openssl >=3.2.1,<4.0a0 license: BSD-3-Clause license_family: BSD - size: 9898931 - timestamp: 1712346494684 + size: 9921940 + timestamp: 1713390727210 - kind: conda name: rattler-build - version: 0.14.2 + version: 0.15.0 build: h7ea99a0_0 subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/rattler-build-0.14.2-h7ea99a0_0.conda - sha256: 474e024329cb2447f98322679209d129468d4d8616f013646138907fbe9bfe91 - md5: e52038e4956f89ae01f24ffefa8829e9 + url: https://conda.anaconda.org/conda-forge/win-64/rattler-build-0.15.0-h7ea99a0_0.conda + sha256: a477de68c9774db427b85acf9cc0de6154ae79f17c26ef219b3e9bbc62170cc4 + md5: ca24907908a0382010234c1a117ec67a depends: - ucrt >=10.0.20348.0 - vc >=14.2,<15 - vc14_runtime >=14.29.30139 license: BSD-3-Clause license_family: BSD - size: 7169856 - timestamp: 1712347847918 + size: 7194383 + timestamp: 1713392068197 - kind: conda name: rattler-build - version: 0.14.2 + version: 0.15.0 build: hd81679c_0 subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/rattler-build-0.14.2-hd81679c_0.conda - sha256: 7b30babcacebae4272ac198dd286a5713a1c4ec2145398bad4415b36bcffee47 - md5: cae0218fe92d15a1afbf8f0e2225e443 + url: https://conda.anaconda.org/conda-forge/osx-64/rattler-build-0.15.0-hd81679c_0.conda + sha256: 0b0160466b300d35bfdb653c7ce1afafcf2a985d5ffac606148da7fd1084f44f + md5: d05f80bd69affc1da6a60f415ac51342 depends: - libcxx >=16 constrains: - __osx >=10.12 license: BSD-3-Clause license_family: BSD - size: 7860086 - timestamp: 1712347574442 + size: 7882297 + timestamp: 1713391855237 - kind: pypi name: rattler-build-conda-compat version: 0.0.2 @@ -5377,6 +5473,8 @@ packages: - python_abi 3.12.* *_cp312 license: MIT license_family: MIT + purls: + - pkg:pypi/ruamel-yaml-clib size: 118650 timestamp: 1707314908121 - kind: conda @@ -5393,6 +5491,8 @@ packages: - python_abi 3.12.* *_cp312 license: MIT license_family: MIT + purls: + - pkg:pypi/ruamel-yaml-clib size: 135640 timestamp: 1707314642857 - kind: conda @@ -5409,6 +5509,8 @@ packages: - python_abi 3.12.* *_cp312 license: MIT license_family: MIT + purls: + - pkg:pypi/ruamel-yaml-clib size: 111221 timestamp: 1707315016121 - kind: conda @@ -5427,16 +5529,18 @@ packages: - vc14_runtime >=14.29.30139 license: MIT license_family: MIT + purls: + - pkg:pypi/ruamel-yaml-clib size: 96333 timestamp: 1707315306489 - kind: conda name: ruff - version: 0.3.5 + version: 0.3.7 build: py312h1ae9fbf_0 subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/ruff-0.3.5-py312h1ae9fbf_0.conda - sha256: 5296fa79876620d8265163b57a718ed17c271c05e95281fdae722591349e146b - md5: 0f3eea1aaceaeefe6007431c3ed547c5 + url: https://conda.anaconda.org/conda-forge/osx-arm64/ruff-0.3.7-py312h1ae9fbf_0.conda + sha256: d410024c1f5007dded6cde0336ef66eb1f20c6012541cdfab8098bf92f88f76f + md5: 19a5d0d42b93d6705a430836e27a72e8 depends: - libcxx >=16 - python >=3.12,<3.13.0a0 @@ -5448,16 +5552,16 @@ packages: license_family: MIT purls: - pkg:pypi/ruff - size: 5771748 - timestamp: 1712000754650 + size: 5873488 + timestamp: 1712963468673 - kind: conda name: ruff - version: 0.3.5 + version: 0.3.7 build: py312h1bc86af_0 subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/ruff-0.3.5-py312h1bc86af_0.conda - sha256: 1b4f63c99f7cee254f4643b44ff799c202c6df2884d00e8f9e4c365c9306c1a2 - md5: e786229e16a01b80085ea1dd850546f5 + url: https://conda.anaconda.org/conda-forge/osx-64/ruff-0.3.7-py312h1bc86af_0.conda + sha256: 34453d115397fb697c5786f25382f3419e418dcbb5a185d0e6217388b1edfd9b + md5: 43f114392c6f66ef9238edbd9c229815 depends: - libcxx >=16 - python >=3.12,<3.13.0a0 @@ -5468,16 +5572,16 @@ packages: license_family: MIT purls: - pkg:pypi/ruff - size: 6082763 - timestamp: 1712000953476 + size: 6190521 + timestamp: 1712963528403 - kind: conda name: ruff - version: 0.3.5 + version: 0.3.7 build: py312h60fbdae_0 subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/ruff-0.3.5-py312h60fbdae_0.conda - sha256: e8deef5c04d74900702a959ce9260ab69e48e6c5a59326ae947b679990524c7d - md5: 2351d21767e094ae4ed4cd69c63fca48 + url: https://conda.anaconda.org/conda-forge/win-64/ruff-0.3.7-py312h60fbdae_0.conda + sha256: e1f2debb0daa31da527aa45281c8f5097c9bda74589ad7c8c6056011528a86e0 + md5: fbed1c59af89011cd6f286e5c12771a2 depends: - python >=3.12,<3.13.0a0 - python_abi 3.12.* *_cp312 @@ -5488,16 +5592,16 @@ packages: license_family: MIT purls: - pkg:pypi/ruff - size: 6251931 - timestamp: 1712001041025 + size: 6336660 + timestamp: 1712963199532 - kind: conda name: ruff - version: 0.3.5 + version: 0.3.7 build: py312h9118e91_0 subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/ruff-0.3.5-py312h9118e91_0.conda - sha256: fe8320ae9f369adb60990ab5e2d55246be58b1bb569f6753f8e566e958fc5475 - md5: a02f3dd98086ac515702e68e7fb88f62 + url: https://conda.anaconda.org/conda-forge/linux-64/ruff-0.3.7-py312h9118e91_0.conda + sha256: 457e71eb4a877715353510ec1fc28742bb21f874551a1ca1ef9f91456e18c202 + md5: 76dc72c065cc15f69b96656b3431a5a4 depends: - libgcc-ng >=12 - libstdcxx-ng >=12 @@ -5507,25 +5611,25 @@ packages: license_family: MIT purls: - pkg:pypi/ruff - size: 6285718 - timestamp: 1711999610306 + size: 6410120 + timestamp: 1712962253616 - kind: conda name: setuptools - version: 69.2.0 + version: 69.5.1 build: pyhd8ed1ab_0 subdir: noarch noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.2.0-pyhd8ed1ab_0.conda - sha256: 78a75c75a5dacda6de5f4056c9c990141bdaf4f64245673a590594d00bc63713 - md5: da214ecd521a720a9d521c68047682dc + url: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.5.1-pyhd8ed1ab_0.conda + sha256: 72d143408507043628b32bed089730b6d5f5445eccc44b59911ec9f262e365e7 + md5: 7462280d81f639363e6e63c81276bd9e depends: - python >=3.8 license: MIT license_family: MIT purls: - pkg:pypi/setuptools - size: 471183 - timestamp: 1710344615844 + size: 501790 + timestamp: 1713094963112 - kind: conda name: sigtool version: 0.1.3 diff --git a/pixi.toml b/pixi.toml index fd14eeb..d6d662c 100644 --- a/pixi.toml +++ b/pixi.toml @@ -15,6 +15,8 @@ python = ">=3.8" build = "*" rattler-build = "*" conda-build = "*" +"ruamel.yaml" = "*" +conda = ">=4.2" [pypi-dependencies] rattler-build-conda-compat = { path = ".", editable = true} diff --git a/src/rattler_build_conda_compat/lint.py b/src/rattler_build_conda_compat/lint.py new file mode 100644 index 0000000..3e2cd5e --- /dev/null +++ b/src/rattler_build_conda_compat/lint.py @@ -0,0 +1,406 @@ +import re + +from inspect import cleandoc +import os.path +import string +import textwrap +import ruamel.yaml +from typing import Any, Sequence +import requests +from conda.models.version import VersionOrder +from functools import cache +from jsonschema import Draft202012Validator +from jsonschema import ValidationError +from textwrap import indent + +SCHEMA_URL = "https://raw.githubusercontent.com/prefix-dev/recipe-format/main/schema.json" + +REQUIREMENTS_ORDER = ["build", "host", "run"] + +ALLOWED_LICENSE_FAMILIES = """ +AGPL +LGPL +GPL3 +GPL2 +GPL +BSD +MIT +APACHE +PSF +CC +MOZILLA +PUBLIC-DOMAIN +PROPRIETARY +OTHER +NONE +""".split() + +# regular expressions +GPL2_REGEX = re.compile("GPL[^3]*2") # match GPL2 +GPL3_REGEX = re.compile("GPL[^2]*3") # match GPL3 +GPL23_REGEX = re.compile("GPL[^2]*>= *2") # match GPL >= 2 +CC_REGEX = re.compile(r"CC\w+") # match CC +PUNK_REGEX = re.compile("[%s]" % re.escape(string.punctuation)) # removes punks + +JINJA_VAR_PAT = re.compile(r"${{(.*?)}}") + +def _format_validation_msg(error: ValidationError): + return cleandoc( + f""" + In recipe.yaml: `{error.instance}`. +{indent(error.message, " " * 12 + "> ")} + """ + ) + + + +@cache +def get_recipe_schema() -> dict[Any, Any]: + return requests.get(SCHEMA_URL).json() + + +def yaml_reader(): + # define global yaml API + # roundrip-loader and allowing duplicate keys + # for handling # [filter] / # [not filter] + # Don't use a global variable for this as a global + # variable will make conda-smithy thread unsafe. + yaml = ruamel.yaml.YAML(typ="rt") + yaml.allow_duplicate_keys = True + return yaml + + + + +def lint_recipe_yaml_by_schema(recipe_file): + schema = get_recipe_schema() + yaml = yaml_reader() + + with open(recipe_file) as fh: + meta = yaml.load(fh) + + validator = Draft202012Validator(schema) + + lints = [] + + for error in validator.iter_errors(meta): + lints.append(_format_validation_msg(error)) + return lints + + + +def lint_about_contents(about_section, lints): + for about_item in ["homepage", "license", "summary"]: + # if the section doesn't exist, or is just empty, lint it. + if not about_section.get(about_item, ""): + lints.append( + "The {} item is expected in the about section." + "".format(about_item) + ) + + + +def lint_recipe_maintainers(maintainers_section, lints): + if not maintainers_section: + lints.append( + "The recipe could do with some maintainers listed in " + "the `extra/recipe-maintainers` section." + ) + + if not ( + isinstance(maintainers_section, Sequence) + and not isinstance(maintainers_section, str) + ): + lints.append("Recipe maintainers should be a json list.") + +def lint_recipe_tests(test_section=dict(), outputs_section=list(), lints=list()) -> list[str]: + TEST_KEYS = {"script", "python"} + hints = [] + + if not any(key in TEST_KEYS for key in test_section): + if not outputs_section: + lints.append("The recipe must have some tests.") + else: + has_outputs_test = False + no_test_hints = [] + for section in outputs_section: + test_section = section.get("test", {}) + if any(key in TEST_KEYS for key in test_section): + has_outputs_test = True + else: + no_test_hints.append( + "It looks like the '{}' output doesn't " + "have any tests.".format(section.get("name", "???")) + ) + if has_outputs_test: + hints.extend(no_test_hints) + else: + lints.append("The recipe must have some tests.") + + return hints + +def lint_license_not_unknown(license: str, lints: list): + license = license.lower() + if "unknown" == license.strip(): + lints.append("The recipe license cannot be unknown.") + + +def lint_build_number(build_section: dict, lints: list): + build_number = build_section.get("number", None) + if build_number is None: + lints.append("The recipe must have a `build/number` section.") + +def lint_requirements_order(requirements_section: dict, lints: list): + seen_requirements = [ + k for k in requirements_section if k in REQUIREMENTS_ORDER + ] + requirements_order_sorted = sorted( + seen_requirements, key=REQUIREMENTS_ORDER.index + ) + if seen_requirements != requirements_order_sorted: + lints.append( + "The `requirements/` sections should be defined " + "in the following order: " + + ", ".join(REQUIREMENTS_ORDER) + + "; instead saw: " + + ", ".join(seen_requirements) + + "." + ) + +def lint_package_version(package_section: dict, context_section: dict): + package_ver = str(package_section.get("version")) + context_ver = str(context_section.get("version")) + ver = package_ver if package_ver is not None and not package_ver.startswith("$") else context_ver + + try: + VersionOrder(ver) + except: + return "Package version {} doesn't match conda spec".format(ver) + +def lint_files_have_hash(sources_section: list, lints: list): + for source_section in sources_section: + if "url" in source_section and not ( + {"sha1", "sha256", "md5"} & set(source_section.keys()) + ): + lints.append( + "When defining a source/url please add a sha256, sha1 " + "or md5 checksum (sha256 preferably)." + ) + +def lint_legacy_compilers(build_reqs): + if build_reqs and ("toolchain" in build_reqs): + return """Using toolchain directly in this manner is deprecated. Consider + using the compilers outlined + [here](https://conda-forge.org/docs/maintainer/knowledge_base.html#compilers).""" + + +def lint_has_recipe_file(about_section, lints): + license_file = about_section.get("license_file", None) + if not license_file: + lints.append("license_file entry is missing, but is required.") + +def lint_package_name(package_section: dict, context_section: dict): + package_name = str(package_section.get("name")) + context_name = str(context_section.get("name")) + ver = package_name if package_name is not None and not package_name.startswith("$") else context_name + + recipe_name = package_section.get("name", "").strip() + if re.match(r"^[a-z0-9_\-.]+$", recipe_name) is None: + return """ + Recipe name has invalid characters. only lowercase alpha, numeric, + underscores, hyphens and dots allowed """ + + + +def lint_legacy_patterns(requirements_section): + lints = [] + build_reqs = requirements_section.get("build", None) + if build_reqs and ("numpy x.x" in build_reqs): + lints.append( + "Using pinned numpy packages is a deprecated pattern. Consider " + "using the method outlined " + "[here](https://conda-forge.org/docs/maintainer/knowledge_base.html#linking-numpy)." + ) + return lints + + +def lint_usage_of_selectors_for_noarch(noarch_value, build_section, requirements_section): + lints = [] + + for section in requirements_section: + section_requirements = requirements_section[section] + + if any(isinstance(req, dict) for req in section_requirements): + lints.append( + "`noarch` packages can't have skips with selectors. If " + "the selectors are necessary, please remove " + "`noarch: {}`.".format(noarch_value) + ) + break + + if "skip" in build_section: + lints.append( + "`noarch` packages can't have skips with selectors. If " + "the selectors are necessary, please remove " + "`noarch: {}`.".format(noarch_value) + ) + + return lints + +def lint_usage_of_single_space_in_pinned_requirements(requirements_section: dict): + def verify_requirement(requirement): + import re + pattern = r'\b\w+\b(\s*(>=|>|<=|<|==)\s*\d+\.\d+)?' + if re.match(pattern, requirement): + return True + return False + + lints = [] + for section, requirements in requirements_section.items(): + for req in requirements: + is_valid = verify_requirement(req) + if not is_valid: + lints.append(f"``requirements: {section}: {req}`` should not " + "contain a space between relational operator and the version, i.e. " + "``{name} {pin}`` and must contain a space between the name and the pin") + return lints + +def lint_non_noarch_dont_constrain_python_and_rbase(requirements_section): + check_languages = ["python", "r-base"] + host_reqs = requirements_section.get("host") or [] + run_reqs = requirements_section.get("run") or [] + + lints = [] + + for language in check_languages: + filtered_host_reqs = [req for req in host_reqs if req.startswith(f"{language} ")] + filtered_run_reqs = [req for req in run_reqs if req.startswith(f"{language} ")] + + if filtered_host_reqs and not filtered_run_reqs: + lints.append(f"If {language} is a host requirement, it should be a run requirement.") + + for reqs in [filtered_host_reqs, filtered_run_reqs]: + if language not in reqs: + for req in reqs: + constraint = req.split(" ", 1)[1] + if constraint.startswith(">") or constraint.startswith("<") or constraint.startswith("="): + lints.append(f"Non noarch packages should have {language} requirement without any version constraints.") + + return lints + +def lint_variable_reference_should_have_space(recipe_dir, recipe_file): + hints = [] + if recipe_dir is not None and os.path.exists(recipe_file): + bad_vars = [] + bad_lines = [] + with open(recipe_file, "r") as fh: + for i, line in enumerate(fh.readlines()): + for m in JINJA_VAR_PAT.finditer(line): + if m.group(1) is not None: + var = m.group(1) + if var != " %s " % var.strip(): + bad_vars.append(m.group(1).strip()) + bad_lines.append(i + 1) + if bad_vars: + hints.append( + "Jinja2 variable references are suggested to " + "take a ``{{}}``" + " form. See lines %s." % (bad_lines,) + ) + + return hints + +def lint_lower_bound_on_python(run_requirements, outputs_section): + lints = [] + # if noarch_value == "python" and not outputs_section: + for req in run_requirements: + if (req.strip().split()[0] == "python") and (req != "python"): + break + else: + lints.append( + "noarch: python recipes are required to have a lower bound " + "on the python version. Typically this means putting " + "`python >=3.6` in **both** `host` and `run` but you should check " + "upstream for the package's Python compatibility." + ) + +def hint_pip_usage(build_section): + hints = [] + + if "script" in build_section: + scripts = build_section["script"] + if isinstance(scripts, str): + scripts = [scripts] + for script in scripts: + if "python setup.py install" in script: + hints.append( + "Whenever possible python packages should use pip. " + "See https://conda-forge.org/docs/maintainer/adding_pkgs.html#use-pip" + ) + return hints + + +def hint_noarch_usage(build_section, requirement_section: dict): + build_reqs = requirement_section.get("build_reqs", None) + hints = [] + if ( + # move outside the call + # noarch_value is None + build_reqs + and not any(["_compiler_stub" in b for b in build_reqs]) + and ("pip" in build_reqs) + # move outside the call + # and (is_staged_recipes or not conda_forge) + ): + no_arch_possible = True + if "skip" in build_section: + no_arch_possible = False + + for _, section_requirements in requirement_section.items(): + if any(isinstance(requirement, dict) for requirement in section_requirements): + no_arch_possible = False + break + + if no_arch_possible: + hints.append( + "Whenever possible python packages should use noarch. " + "See https://conda-forge.org/docs/maintainer/knowledge_base.html#noarch-builds" + ) + + return hints + + + + +def normalize_license(s): + """Set to ALL CAPS, replace common GPL patterns, and strip""" + s = s.upper() + s = re.sub("GENERAL PUBLIC LICENSE", "GPL", s) + s = re.sub("LESSER *", "L", s) + s = re.sub("AFFERO *", "A", s) + return s.strip() + +def remove_special_characters(s): + """Remove punctuation, spaces, tabs, and line feeds""" + s = PUNK_REGEX.sub(" ", s) + s = re.sub(r"\s+", "", s) + return s + +def indent(message): + textwrap.fill(textwrap.dedent(message)) + +def ensure_valid_license_family(about_section): + try: + license_family = about_section["license_family"] + except KeyError: + return + allowed_families = [ + remove_special_characters(normalize_license(fam)) for fam in ALLOWED_LICENSE_FAMILIES + ] + if remove_special_characters(normalize_license(license_family)) not in allowed_families: + raise RuntimeError( + indent( + f"about/license_family '{license_family}' not allowed. " + f"Allowed families are {", ".join(sorted(ALLOWED_LICENSE_FAMILIES))}." + ) + ) \ No newline at end of file diff --git a/src/rattler_build_conda_compat/loader.py b/src/rattler_build_conda_compat/loader.py index c2986e1..39fae76 100644 --- a/src/rattler_build_conda_compat/loader.py +++ b/src/rattler_build_conda_compat/loader.py @@ -81,3 +81,27 @@ def parse_recipe_config_file(path, namespace): with RecipeLoader.with_namespace(namespace): content = yaml.load(f, Loader=RecipeLoader) return remove_empty_keys(content) + + +def load_all_requirements(path) -> dict: + with open(path) as f: + content = yaml.load(f, Loader=yaml.BaseLoader) + + requirements_section = content.get("requirements", None) + if not requirements_section: + return content + + for section in requirements_section: + section_reqs = requirements_section[section] + expanded_reqs = [] + for req in section_reqs: + if isinstance(req, dict): + then_reqs = req.get("then", []) + else_reqs = req.get("else", []) + expanded_reqs.extend(then_reqs) + expanded_reqs.extend(else_reqs) + else: + expanded_reqs.append(req) + requirements_section[section] = expanded_reqs + + return content diff --git a/tests/data/recipe_requirements.yaml b/tests/data/recipe_requirements.yaml new file mode 100644 index 0000000..8c2ab1f --- /dev/null +++ b/tests/data/recipe_requirements.yaml @@ -0,0 +1,8 @@ +requirements: + build: + - ${{ compiler('c') }} + - if: linux + then: + - ${{ cdt('xorg-x11-proto-devel') }} + host: + - python \ No newline at end of file diff --git a/tests/test_rattler_loader.py b/tests/test_rattler_loader.py index ac94bda..12b3e55 100644 --- a/tests/test_rattler_loader.py +++ b/tests/test_rattler_loader.py @@ -1,4 +1,5 @@ -from rattler_build_conda_compat.loader import parse_recipe_config_file +import yaml +from rattler_build_conda_compat.loader import parse_recipe_config_file, load_all_requirements from pathlib import Path @@ -8,3 +9,10 @@ def test_load_variants(snapshot, unix_namespace): loaded_variants = parse_recipe_config_file(str(variants_path), unix_namespace) assert loaded_variants == snapshot + + +def test_load_all_requirements(): + recipe_path = Path("tests/data/recipe_requirements.yaml") + + content = load_all_requirements(recipe_path) + print(content) From f80f959a93b4087367745aab2279863f47306f50 Mon Sep 17 00:00:00 2001 From: nichmor Date: Thu, 25 Apr 2024 16:53:46 +0300 Subject: [PATCH 2/4] feat: add linting support --- pixi.lock | 501 +++++++++++++++++++++++ pixi.toml | 5 +- pyproject.toml | 2 +- src/rattler_build_conda_compat/lint.py | 430 +++++++++++++------ src/rattler_build_conda_compat/loader.py | 22 +- 5 files changed, 832 insertions(+), 128 deletions(-) diff --git a/pixi.lock b/pixi.lock index e0d5181..31a4e76 100644 --- a/pixi.lock +++ b/pixi.lock @@ -28,6 +28,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/conda-libmamba-solver-24.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-handling-2.2.0-pyh38be061_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-streaming-0.9.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cryptography-42.0.5-py312h241aef2_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/deprecated-1.2.14-pyh1a96a4e_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/distro-1.9.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.13.4-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/fmt-10.2.1-h00ab1b0_0.conda @@ -57,6 +59,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libmambapy-1.5.8-py312hd9e9ff6_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.58.0-h47da74e_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hd590300_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsodium-1.0.18-h36c2ea0_1.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/libsolv-0.7.28-hfc55251_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.45.3-h2797004_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libssh2-1.11.0-h0841786_0.conda @@ -85,8 +88,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/pybind11-abi-4-hd8ed1ab_3.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/pycosat-0.6.6-py312h98912ed_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pygithub-2.3.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pyjwt-2.8.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pynacl-1.5.0-py312h98912ed_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha2e5f31_6.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.3-hab00c5b_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/python-libarchive-c-5.1-py312h7900ff3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/python_abi-3.12-4_cp312.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytz-2024.1-pyhd8ed1ab_0.conda @@ -102,13 +109,17 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/ruamel.yaml-0.18.6-py312h98912ed_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ruamel.yaml.clib-0.2.8-py312h98912ed_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.5.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.16.0-pyh6c4a22f_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.5-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h4845f30_101.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.66.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/truststore-0.8.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.11.0-hd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.11.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/wrapt-1.16.0-py312h98912ed_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/xz-5.2.6-h166bdaf_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h7f98852_2.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-cpp-0.8.0-h59595ed_0.conda @@ -140,6 +151,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/conda-libmamba-solver-24.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-handling-2.2.0-pyh38be061_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-streaming-0.9.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cryptography-42.0.5-py312h3d16f4b_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/deprecated-1.2.14-pyh1a96a4e_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/distro-1.9.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.13.4-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/fmt-10.2.1-h7728843_0.conda @@ -168,6 +181,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/libmamba-1.5.8-ha449628_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libmambapy-1.5.8-py312h67f5953_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libnghttp2-1.58.0-h64cf6d3_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libsodium-1.0.18-hbcb3906_1.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/libsolv-0.7.28-h2d185b6_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.45.3-h92b6c6a_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libssh2-1.11.0-hd019ec5_0.conda @@ -192,8 +206,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/pybind11-abi-4-hd8ed1ab_3.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/pycosat-0.6.6-py312h104f124_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pygithub-2.3.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pyjwt-2.8.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/pynacl-1.5.0-py312h104f124_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha2e5f31_6.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.12.3-h1411813_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/python-libarchive-c-5.1-py312hb401068_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/python_abi-3.12-4_cp312.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytz-2024.1-pyhd8ed1ab_0.conda @@ -210,14 +228,18 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/ruamel.yaml.clib-0.2.8-py312h41838bb_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.5.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/sigtool-0.1.3-h88f4db0_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.16.0-pyh6c4a22f_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.5-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/tapi-1100.0.11-h9ce4665_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-h1abcd95_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.66.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/truststore-0.8.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.11.0-hd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.11.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/wrapt-1.16.0-py312h41838bb_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/xz-5.2.6-h775f41a_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/yaml-0.2.5-h0d85af4_2.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/yaml-cpp-0.8.0-he965462_0.conda @@ -249,6 +271,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/conda-libmamba-solver-24.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-handling-2.2.0-pyh38be061_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-streaming-0.9.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cryptography-42.0.5-py312h99f8e83_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/deprecated-1.2.14-pyh1a96a4e_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/distro-1.9.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.13.4-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/fmt-10.2.1-h2ffa867_0.conda @@ -277,6 +301,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmamba-1.5.8-h90c426b_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmambapy-1.5.8-py312h344e357_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libnghttp2-1.58.0-ha4dd798_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsodium-1.0.18-h27ca646_1.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsolv-0.7.28-h1059232_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.45.3-h091b4b1_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libssh2-1.11.0-h7a5bd25_0.conda @@ -301,8 +326,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/pybind11-abi-4-hd8ed1ab_3.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pycosat-0.6.6-py312h02f2b3b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pygithub-2.3.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pyjwt-2.8.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pynacl-1.5.0-py312h02f2b3b_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha2e5f31_6.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.12.3-h4a7b5fc_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-libarchive-c-5.1-py312h81bd7bf_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python_abi-3.12-4_cp312.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytz-2024.1-pyhd8ed1ab_0.conda @@ -319,14 +348,18 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ruamel.yaml.clib-0.2.8-py312he37b823_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.5.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/sigtool-0.1.3-h44b9a77_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.16.0-pyh6c4a22f_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.5-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tapi-1100.0.11-he4954df_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h5083fa2_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.66.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/truststore-0.8.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.11.0-hd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.11.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/wrapt-1.16.0-py312he37b823_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/xz-5.2.6-h57fd34a_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/yaml-0.2.5-h3422bc3_2.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/yaml-cpp-0.8.0-h13dd4ca_0.conda @@ -355,6 +388,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/conda-libmamba-solver-24.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-handling-2.2.0-pyh38be061_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-streaming-0.9.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cryptography-42.0.5-py312h1f4a190_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/deprecated-1.2.14-pyh1a96a4e_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/distro-1.9.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.13.4-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/fmt-10.2.1-h181d51b_0.conda @@ -399,8 +434,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/pybind11-abi-4-hd8ed1ab_3.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/pycosat-0.6.6-py312he70551f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pygithub-2.3.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pyjwt-2.8.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pynacl-1.5.0-py312hc560f31_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyh0701188_6.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.12.3-h2628c8c_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/python-libarchive-c-5.1-py312h2e8e312_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/python_abi-3.12-4_cp312.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytz-2024.1-pyhd8ed1ab_0.conda @@ -415,11 +454,14 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/ruamel.yaml-0.18.6-py312he70551f_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/ruamel.yaml.clib-0.2.8-py312he70551f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.5.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.16.0-pyh6c4a22f_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.5-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h5226925_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.66.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/truststore-0.8.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.11.0-hd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.11.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.22621.0-h57928b3_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.2.1-pyhd8ed1ab_0.conda @@ -427,6 +469,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.38.33130-h82b7239_18.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vs2015_runtime-14.38.33130-hcb4865c_18.conda - conda: https://conda.anaconda.org/conda-forge/noarch/win_inet_pton-1.1.0-pyhd8ed1ab_6.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/wrapt-1.16.0-py312he70551f_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/xz-5.2.6-h8d14728_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/yaml-0.2.5-h8ffe710_2.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/yaml-cpp-0.8.0-h63175ca_0.conda @@ -462,6 +505,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/conda-libmamba-solver-24.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-handling-2.2.0-pyh38be061_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-streaming-0.9.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cryptography-42.0.5-py312h241aef2_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/deprecated-1.2.14-pyh1a96a4e_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/distro-1.9.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.13.4-pyhd8ed1ab_0.conda @@ -493,6 +538,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libmambapy-1.5.8-py312hd9e9ff6_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.58.0-h47da74e_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hd590300_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsodium-1.0.18-h36c2ea0_1.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/libsolv-0.7.28-hfc55251_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.45.3-h2797004_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libssh2-1.11.0-h0841786_0.conda @@ -521,9 +567,13 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/pybind11-abi-4-hd8ed1ab_3.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/pycosat-0.6.6-py312h98912ed_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pygithub-2.3.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pyjwt-2.8.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pynacl-1.5.0-py312h98912ed_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha2e5f31_6.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.1.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.3-hab00c5b_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/python-libarchive-c-5.1-py312h7900ff3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/python_abi-3.12-4_cp312.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytz-2024.1-pyhd8ed1ab_0.conda @@ -540,14 +590,18 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/ruamel.yaml.clib-0.2.8-py312h98912ed_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ruff-0.3.7-py312h9118e91_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.5.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.16.0-pyh6c4a22f_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.5-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/syrupy-4.6.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h4845f30_101.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.66.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/truststore-0.8.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.11.0-hd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.11.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/wrapt-1.16.0-py312h98912ed_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/xz-5.2.6-h166bdaf_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h7f98852_2.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-cpp-0.8.0-h59595ed_0.conda @@ -579,6 +633,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/conda-libmamba-solver-24.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-handling-2.2.0-pyh38be061_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-streaming-0.9.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cryptography-42.0.5-py312h3d16f4b_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/deprecated-1.2.14-pyh1a96a4e_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/distro-1.9.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.13.4-pyhd8ed1ab_0.conda @@ -609,6 +665,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/libmamba-1.5.8-ha449628_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libmambapy-1.5.8-py312h67f5953_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libnghttp2-1.58.0-h64cf6d3_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libsodium-1.0.18-hbcb3906_1.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/libsolv-0.7.28-h2d185b6_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.45.3-h92b6c6a_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libssh2-1.11.0-hd019ec5_0.conda @@ -633,9 +690,13 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/pybind11-abi-4-hd8ed1ab_3.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/pycosat-0.6.6-py312h104f124_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pygithub-2.3.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pyjwt-2.8.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/pynacl-1.5.0-py312h104f124_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha2e5f31_6.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.1.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.12.3-h1411813_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/python-libarchive-c-5.1-py312hb401068_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/python_abi-3.12-4_cp312.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytz-2024.1-pyhd8ed1ab_0.conda @@ -653,6 +714,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/ruff-0.3.7-py312h1bc86af_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.5.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/sigtool-0.1.3-h88f4db0_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.16.0-pyh6c4a22f_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.5-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/syrupy-4.6.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/tapi-1100.0.11-h9ce4665_0.tar.bz2 @@ -660,8 +722,11 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.66.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/truststore-0.8.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.11.0-hd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.11.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/wrapt-1.16.0-py312h41838bb_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/xz-5.2.6-h775f41a_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/yaml-0.2.5-h0d85af4_2.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/yaml-cpp-0.8.0-he965462_0.conda @@ -693,6 +758,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/conda-libmamba-solver-24.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-handling-2.2.0-pyh38be061_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-streaming-0.9.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cryptography-42.0.5-py312h99f8e83_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/deprecated-1.2.14-pyh1a96a4e_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/distro-1.9.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.13.4-pyhd8ed1ab_0.conda @@ -723,6 +790,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmamba-1.5.8-h90c426b_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libmambapy-1.5.8-py312h344e357_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libnghttp2-1.58.0-ha4dd798_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsodium-1.0.18-h27ca646_1.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsolv-0.7.28-h1059232_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.45.3-h091b4b1_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libssh2-1.11.0-h7a5bd25_0.conda @@ -747,9 +815,13 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/pybind11-abi-4-hd8ed1ab_3.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pycosat-0.6.6-py312h02f2b3b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pygithub-2.3.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pyjwt-2.8.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pynacl-1.5.0-py312h02f2b3b_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha2e5f31_6.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.1.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.12.3-h4a7b5fc_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-libarchive-c-5.1-py312h81bd7bf_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python_abi-3.12-4_cp312.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytz-2024.1-pyhd8ed1ab_0.conda @@ -767,6 +839,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ruff-0.3.7-py312h1ae9fbf_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.5.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/sigtool-0.1.3-h44b9a77_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.16.0-pyh6c4a22f_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.5-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/syrupy-4.6.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tapi-1100.0.11-he4954df_0.tar.bz2 @@ -774,8 +847,11 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.66.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/truststore-0.8.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.11.0-hd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.11.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/wrapt-1.16.0-py312he37b823_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/xz-5.2.6-h57fd34a_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/yaml-0.2.5-h3422bc3_2.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/yaml-cpp-0.8.0-h13dd4ca_0.conda @@ -804,6 +880,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/conda-libmamba-solver-24.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-handling-2.2.0-pyh38be061_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/conda-package-streaming-0.9.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cryptography-42.0.5-py312h1f4a190_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/deprecated-1.2.14-pyh1a96a4e_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/distro-1.9.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.13.4-pyhd8ed1ab_0.conda @@ -850,9 +928,13 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/pybind11-abi-4-hd8ed1ab_3.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/pycosat-0.6.6-py312he70551f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pygithub-2.3.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pyjwt-2.8.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pynacl-1.5.0-py312hc560f31_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyh0701188_6.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.1.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.12.3-h2628c8c_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/python-libarchive-c-5.1-py312h2e8e312_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/python_abi-3.12-4_cp312.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytz-2024.1-pyhd8ed1ab_0.conda @@ -868,12 +950,15 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/ruamel.yaml.clib-0.2.8-py312he70551f_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/ruff-0.3.7-py312h60fbdae_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.5.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.16.0-pyh6c4a22f_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.5-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/syrupy-4.6.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h5226925_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.66.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/truststore-0.8.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.11.0-hd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.11.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.22621.0-h57928b3_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.2.1-pyhd8ed1ab_0.conda @@ -881,6 +966,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.38.33130-h82b7239_18.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vs2015_runtime-14.38.33130-hcb4865c_18.conda - conda: https://conda.anaconda.org/conda-forge/noarch/win_inet_pton-1.1.0-pyhd8ed1ab_6.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/wrapt-1.16.0-py312he70551f_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/xz-5.2.6-h8d14728_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/yaml-0.2.5-h8ffe710_2.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/yaml-cpp-0.8.0-h63175ca_0.conda @@ -1953,6 +2039,110 @@ packages: - pkg:pypi/conda-package-streaming size: 19183 timestamp: 1691009348105 +- kind: conda + name: cryptography + version: 42.0.5 + build: py312h1f4a190_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/cryptography-42.0.5-py312h1f4a190_0.conda + sha256: 6475b53ddb2b623a34d515977704488b19bf1ef8c5a1a9004c22a739351f8588 + md5: 14256d16d22cfbba12f0bb9e485e9077 + depends: + - cffi >=1.12 + - openssl >=3.2.1,<4.0a0 + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: Apache-2.0 AND BSD-3-Clause AND PSF-2.0 AND MIT + license_family: BSD + purls: + - pkg:pypi/cryptography + size: 1143364 + timestamp: 1708781427908 +- kind: conda + name: cryptography + version: 42.0.5 + build: py312h241aef2_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/cryptography-42.0.5-py312h241aef2_0.conda + sha256: 5dc135fc6ea57bf94cf32313f91c93f8a4af15133879dd86e6c8c16e4e07c55e + md5: 0d8c0e4e8c1b2796eaf6770a76a9d1e4 + depends: + - cffi >=1.12 + - libgcc-ng >=12 + - openssl >=3.2.1,<4.0a0 + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + license: Apache-2.0 AND BSD-3-Clause AND PSF-2.0 AND MIT + license_family: BSD + purls: + - pkg:pypi/cryptography + size: 1976047 + timestamp: 1708780611460 +- kind: conda + name: cryptography + version: 42.0.5 + build: py312h3d16f4b_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/cryptography-42.0.5-py312h3d16f4b_0.conda + sha256: dcf489514a1b93981da61de21c94a35a8f6f969759cdb5a9c222bfb10bc5063e + md5: 6132f6e13868c12209c823c8d193e16e + depends: + - __osx >=10.12 + - cffi >=1.12 + - openssl >=3.2.1,<4.0a0 + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + constrains: + - __osx >=10.12 + license: Apache-2.0 AND BSD-3-Clause AND PSF-2.0 AND MIT + license_family: BSD + purls: + - pkg:pypi/cryptography + size: 1281399 + timestamp: 1708853006483 +- kind: conda + name: cryptography + version: 42.0.5 + build: py312h99f8e83_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/cryptography-42.0.5-py312h99f8e83_0.conda + sha256: 6e37a83b60a85cb58224213c710b476a2a06fe48f45c1fa76b1d7a2c3ddaff0a + md5: 32f29561e515d2aae57275d8b7af528d + depends: + - cffi >=1.12 + - openssl >=3.2.1,<4.0a0 + - python >=3.12,<3.13.0a0 + - python >=3.12,<3.13.0a0 *_cpython + - python_abi 3.12.* *_cp312 + constrains: + - __osx >=11.0 + license: Apache-2.0 AND BSD-3-Clause AND PSF-2.0 AND MIT + license_family: BSD + purls: + - pkg:pypi/cryptography + size: 1274922 + timestamp: 1708780961058 +- kind: conda + name: deprecated + version: 1.2.14 + build: pyh1a96a4e_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/deprecated-1.2.14-pyh1a96a4e_0.conda + sha256: 8f61539b00ea315c99f8b6f9e2408caa6894593617676741214cc0280e875ca0 + md5: 4e4c4236e1ca9bcd8816b921a4805882 + depends: + - python >=2.7 + - wrapt <2,>=1.10 + license: MIT + license_family: MIT + purls: + - pkg:pypi/deprecated + size: 14033 + timestamp: 1685233463632 - kind: conda name: distro version: 1.9.0 @@ -3354,6 +3544,44 @@ packages: license_family: GPL size: 33408 timestamp: 1697359010159 +- kind: conda + name: libsodium + version: 1.0.18 + build: h27ca646_1 + build_number: 1 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libsodium-1.0.18-h27ca646_1.tar.bz2 + sha256: 1d95fe5e5e6a0700669aab454b2a32f97289c9ed8d1f7667c2ba98327a6f05bc + md5: 90859688dbca4735b74c02af14c4c793 + license: ISC + size: 324912 + timestamp: 1605135878892 +- kind: conda + name: libsodium + version: 1.0.18 + build: h36c2ea0_1 + build_number: 1 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libsodium-1.0.18-h36c2ea0_1.tar.bz2 + sha256: 53da0c8b79659df7b53eebdb80783503ce72fb4b10ed6e9e05cc0e9e4207a130 + md5: c3788462a6fbddafdb413a9f9053e58d + depends: + - libgcc-ng >=7.5.0 + license: ISC + size: 374999 + timestamp: 1605135674116 +- kind: conda + name: libsodium + version: 1.0.18 + build: hbcb3906_1 + build_number: 1 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libsodium-1.0.18-hbcb3906_1.tar.bz2 + sha256: 2da45f14e3d383b4b9e3a8bacc95cd2832aac2dbf9fbc70d255d384a310c5660 + md5: 24632c09ed931af617fe6d5292919cab + license: ISC + size: 528765 + timestamp: 1605135849110 - kind: conda name: libsolv version: 0.7.28 @@ -4562,6 +4790,139 @@ packages: - pkg:pypi/pycparser size: 105098 timestamp: 1711811634025 +- kind: conda + name: pygithub + version: 2.3.0 + build: pyhd8ed1ab_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/pygithub-2.3.0-pyhd8ed1ab_0.conda + sha256: 6f03bffc523305f60b2c9a60d085cdefcfb98329251dd109e995dde878b14d23 + md5: b07dc79f5617b22abbaba663d84d1400 + depends: + - cryptography >=3.4.0 + - deprecated + - pyjwt >=2.4.0 + - pynacl >=1.4.0 + - python >=3.7 + - python-dateutil + - requests >=2.14.0 + - typing-extensions >=4.0.0 + - urllib3 >=1.26.0 + license: LGPL-3.0-only + license_family: LGPL + purls: + - pkg:pypi/pygithub + size: 145581 + timestamp: 1711296584144 +- kind: conda + name: pyjwt + version: 2.8.0 + build: pyhd8ed1ab_1 + build_number: 1 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/pyjwt-2.8.0-pyhd8ed1ab_1.conda + sha256: d7cb7fbafd767e938db10820c76a9c16d91faf5a081842159cc185787879eb07 + md5: 74f76d4868dbba5870f2cf1d9b12d8f3 + depends: + - python >=3.7 + constrains: + - cryptography >=3.3.1 + license: MIT + license_family: MIT + purls: + - pkg:pypi/pyjwt + size: 24906 + timestamp: 1706895211122 +- kind: conda + name: pynacl + version: 1.5.0 + build: py312h02f2b3b_3 + build_number: 3 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/pynacl-1.5.0-py312h02f2b3b_3.conda + sha256: 733bba1d4b25f17a5e30f99dc4355b6cd9345cf0c9a1241c205323d8e0ec42af + md5: 5648ef2d224601e852af9b4e8eb30d3a + depends: + - cffi >=1.4.1 + - libsodium >=1.0.18,<1.0.19.0a0 + - python >=3.12.0rc3,<3.13.0a0 + - python >=3.12.0rc3,<3.13.0a0 *_cpython + - python_abi 3.12.* *_cp312 + - six + license: Apache-2.0 + license_family: Apache + purls: + - pkg:pypi/pynacl + size: 1148303 + timestamp: 1695545270114 +- kind: conda + name: pynacl + version: 1.5.0 + build: py312h104f124_3 + build_number: 3 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/pynacl-1.5.0-py312h104f124_3.conda + sha256: 9e7f8189c8cb3e0e4318b59ca42ff97f7803a732c69b1fb192e7c2af3f4234c3 + md5: eee6d82c708669043c7d581afd45a6db + depends: + - cffi >=1.4.1 + - libsodium >=1.0.18,<1.0.19.0a0 + - python >=3.12.0rc3,<3.13.0a0 + - python_abi 3.12.* *_cp312 + - six + license: Apache-2.0 + license_family: Apache + purls: + - pkg:pypi/pynacl + size: 1165861 + timestamp: 1695545180164 +- kind: conda + name: pynacl + version: 1.5.0 + build: py312h98912ed_3 + build_number: 3 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/pynacl-1.5.0-py312h98912ed_3.conda + sha256: f9077093cbd75165abd2f538ad2924ec4cf3a5928604e9ff6ffcf2b224de2163 + md5: 66244781991f08a163ff80a91359dbf5 + depends: + - cffi >=1.4.1 + - libgcc-ng >=12 + - libsodium >=1.0.18,<1.0.19.0a0 + - python >=3.12.0rc3,<3.13.0a0 + - python_abi 3.12.* *_cp312 + - six + license: Apache-2.0 + license_family: Apache + purls: + - pkg:pypi/pynacl + size: 1147941 + timestamp: 1695545046950 +- kind: conda + name: pynacl + version: 1.5.0 + build: py312hc560f31_3 + build_number: 3 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/pynacl-1.5.0-py312hc560f31_3.conda + sha256: 7b525604cbf5af4858b970e92aa37fbe9bbc83739c099dc734210f48ceb24fe2 + md5: c0c5ade781f5914663ba090a86088af0 + depends: + - cffi >=1.4.1 + - python >=3.12.0rc3,<3.13.0a0 + - python_abi 3.12.* *_cp312 + - six + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: Apache-2.0 + license_family: Apache + purls: + - pkg:pypi/pynacl + size: 1247874 + timestamp: 1695545310942 - kind: conda name: pysocks version: 1.7.1 @@ -4734,6 +5095,24 @@ packages: license: Python-2.0 size: 31991381 timestamp: 1713208036041 +- kind: conda + name: python-dateutil + version: 2.9.0 + build: pyhd8ed1ab_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0-pyhd8ed1ab_0.conda + sha256: f3ceef02ac164a8d3a080d0d32f8e2ebe10dd29e3a685d240e38b3599e146320 + md5: 2cf4264fffb9e6eff6031c5b6884d61c + depends: + - python >=3.7 + - six >=1.5 + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/python-dateutil + size: 222742 + timestamp: 1709299922152 - kind: conda name: python-libarchive-c version: '5.1' @@ -5658,6 +6037,23 @@ packages: license_family: MIT size: 213817 timestamp: 1643442169866 +- kind: conda + name: six + version: 1.16.0 + build: pyh6c4a22f_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/six-1.16.0-pyh6c4a22f_0.tar.bz2 + sha256: a85c38227b446f42c5b90d9b642f2c0567880c15d72492d8da074a59c8f91dd6 + md5: e5f25f8dbc060e9a8d912e432202afc2 + depends: + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/six + size: 14259 + timestamp: 1620240338595 - kind: conda name: soupsieve version: '2.5' @@ -5836,6 +6232,38 @@ packages: - pkg:pypi/truststore size: 20667 timestamp: 1694154740564 +- kind: conda + name: typing-extensions + version: 4.11.0 + build: hd8ed1ab_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.11.0-hd8ed1ab_0.conda + sha256: aecbd9c601ba5a6c128da8975276fd817b968a9edc969b7ae97aee76e80a14a6 + md5: 471e3988f8ca5e9eb3ce6be7eac3bcee + depends: + - typing_extensions 4.11.0 pyha770c72_0 + license: PSF-2.0 + license_family: PSF + size: 10093 + timestamp: 1712330094282 +- kind: conda + name: typing_extensions + version: 4.11.0 + build: pyha770c72_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.11.0-pyha770c72_0.conda + sha256: a7e8714d14f854058e971a6ed44f18cc37cc685f98ddefb2e6b7899a0cc4d1a2 + md5: 6ef2fc37559256cf682d8b3375e89b80 + depends: + - python >=3.8 + license: PSF-2.0 + license_family: PSF + purls: + - pkg:pypi/typing-extensions + size: 37583 + timestamp: 1712330089194 - kind: conda name: tzdata version: 2024a @@ -5948,6 +6376,79 @@ packages: - pkg:pypi/win-inet-pton size: 8191 timestamp: 1667051294134 +- kind: conda + name: wrapt + version: 1.16.0 + build: py312h41838bb_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/wrapt-1.16.0-py312h41838bb_0.conda + sha256: 9ed208c4c844c50f161764df7ed7a226c42822917c892ab7c8f67eec6ca96dff + md5: d87798aa7210da2c5eaf96c0346dca00 + depends: + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + license: BSD-2-Clause + license_family: BSD + purls: + - pkg:pypi/wrapt + size: 59057 + timestamp: 1699533259706 +- kind: conda + name: wrapt + version: 1.16.0 + build: py312h98912ed_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/wrapt-1.16.0-py312h98912ed_0.conda + sha256: dc8431b343961347ad93b33d2d8270e8c15d8825382f4f2540835c94aba2de05 + md5: fa957a1c7bee7e47ad44633caf7be8bc + depends: + - libgcc-ng >=12 + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + license: BSD-2-Clause + license_family: BSD + purls: + - pkg:pypi/wrapt + size: 62482 + timestamp: 1699532968076 +- kind: conda + name: wrapt + version: 1.16.0 + build: py312he37b823_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/wrapt-1.16.0-py312he37b823_0.conda + sha256: 25824dd9a22f2c1e8f205eb55c906b28b2f4748a68cb8e3d95ffdf73f08cbac9 + md5: 86726ebb1f6da39c68f306ae624ee4ed + depends: + - python >=3.12,<3.13.0a0 + - python >=3.12,<3.13.0a0 *_cpython + - python_abi 3.12.* *_cp312 + license: BSD-2-Clause + license_family: BSD + purls: + - pkg:pypi/wrapt + size: 59676 + timestamp: 1699533197501 +- kind: conda + name: wrapt + version: 1.16.0 + build: py312he70551f_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/wrapt-1.16.0-py312he70551f_0.conda + sha256: e4b5ac6c897e68a798dfe13a1499dc9b555c48b468aa477d456807f2a7366c30 + md5: cea7b1aa961de6a8ac90584b5968a01d + depends: + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: BSD-2-Clause + license_family: BSD + purls: + - pkg:pypi/wrapt + size: 61358 + timestamp: 1699533495284 - kind: conda name: xz version: 5.2.6 diff --git a/pixi.toml b/pixi.toml index d6d662c..9df6806 100644 --- a/pixi.toml +++ b/pixi.toml @@ -1,7 +1,7 @@ [project] name = "rattler-build-conda-compat" -version = "0.1.0" -description = "Add a short description here" +version = "0.0.3" +description = "A package for exposing rattler-build API for conda-smithy" authors = ["nichmor "] channels = ["conda-forge"] platforms = ["win-64", "linux-64", "osx-64", "osx-arm64"] @@ -17,6 +17,7 @@ rattler-build = "*" conda-build = "*" "ruamel.yaml" = "*" conda = ">=4.2" +pygithub = ">=2,<3" [pypi-dependencies] rattler-build-conda-compat = { path = ".", editable = true} diff --git a/pyproject.toml b/pyproject.toml index 774ee5f..b64c0a0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,6 +10,6 @@ description="A package for exposing rattler-build API for conda-smithy" readme = "README.md" authors = [{name = "Nichita Morcotilo", email = "nichita@prefix.dev"}] license = {file = "LICENSE.txt"} -version = "0.0.2" +version = "0.0.3" requires-python = ">=3.8" diff --git a/src/rattler_build_conda_compat/lint.py b/src/rattler_build_conda_compat/lint.py index 3e2cd5e..5e9c8ac 100644 --- a/src/rattler_build_conda_compat/lint.py +++ b/src/rattler_build_conda_compat/lint.py @@ -2,10 +2,10 @@ from inspect import cleandoc import os.path -import string -import textwrap +import tomllib +import github import ruamel.yaml -from typing import Any, Sequence +from typing import Any, Mapping, Sequence import requests from conda.models.version import VersionOrder from functools import cache @@ -13,36 +13,17 @@ from jsonschema import ValidationError from textwrap import indent -SCHEMA_URL = "https://raw.githubusercontent.com/prefix-dev/recipe-format/main/schema.json" +from rattler_build_conda_compat.loader import load_yaml + +SCHEMA_URL = ( + "https://raw.githubusercontent.com/prefix-dev/recipe-format/main/schema.json" +) REQUIREMENTS_ORDER = ["build", "host", "run"] -ALLOWED_LICENSE_FAMILIES = """ -AGPL -LGPL -GPL3 -GPL2 -GPL -BSD -MIT -APACHE -PSF -CC -MOZILLA -PUBLIC-DOMAIN -PROPRIETARY -OTHER -NONE -""".split() - -# regular expressions -GPL2_REGEX = re.compile("GPL[^3]*2") # match GPL2 -GPL3_REGEX = re.compile("GPL[^2]*3") # match GPL3 -GPL23_REGEX = re.compile("GPL[^2]*>= *2") # match GPL >= 2 -CC_REGEX = re.compile(r"CC\w+") # match CC -PUNK_REGEX = re.compile("[%s]" % re.escape(string.punctuation)) # removes punks - -JINJA_VAR_PAT = re.compile(r"${{(.*?)}}") + +JINJA_VAR_PAT = re.compile(r"\${{(.*?)}}") + def _format_validation_msg(error: ValidationError): return cleandoc( @@ -53,7 +34,6 @@ def _format_validation_msg(error: ValidationError): ) - @cache def get_recipe_schema() -> dict[Any, Any]: return requests.get(SCHEMA_URL).json() @@ -70,8 +50,6 @@ def yaml_reader(): return yaml - - def lint_recipe_yaml_by_schema(recipe_file): schema = get_recipe_schema() yaml = yaml_reader() @@ -88,16 +66,13 @@ def lint_recipe_yaml_by_schema(recipe_file): return lints - def lint_about_contents(about_section, lints): for about_item in ["homepage", "license", "summary"]: # if the section doesn't exist, or is just empty, lint it. if not about_section.get(about_item, ""): lints.append( - "The {} item is expected in the about section." - "".format(about_item) - ) - + "The {} item is expected in the about section." "".format(about_item) + ) def lint_recipe_maintainers(maintainers_section, lints): @@ -109,12 +84,16 @@ def lint_recipe_maintainers(maintainers_section, lints): if not ( isinstance(maintainers_section, Sequence) - and not isinstance(maintainers_section, str) + and not isinstance(maintainers_section, str) ): lints.append("Recipe maintainers should be a json list.") -def lint_recipe_tests(test_section=dict(), outputs_section=list(), lints=list()) -> list[str]: + +def lint_recipe_tests( + test_section=dict(), outputs_section=list() +) -> (list[str], list[str]): TEST_KEYS = {"script", "python"} + lints = [] hints = [] if not any(key in TEST_KEYS for key in test_section): @@ -124,20 +103,21 @@ def lint_recipe_tests(test_section=dict(), outputs_section=list(), lints=list()) has_outputs_test = False no_test_hints = [] for section in outputs_section: - test_section = section.get("test", {}) + test_section = section.get("tests", {}) if any(key in TEST_KEYS for key in test_section): has_outputs_test = True else: no_test_hints.append( "It looks like the '{}' output doesn't " "have any tests.".format(section.get("name", "???")) - ) + ) if has_outputs_test: hints.extend(no_test_hints) else: lints.append("The recipe must have some tests.") - return hints + return lints, hints + def lint_license_not_unknown(license: str, lints: list): license = license.lower() @@ -150,13 +130,10 @@ def lint_build_number(build_section: dict, lints: list): if build_number is None: lints.append("The recipe must have a `build/number` section.") + def lint_requirements_order(requirements_section: dict, lints: list): - seen_requirements = [ - k for k in requirements_section if k in REQUIREMENTS_ORDER - ] - requirements_order_sorted = sorted( - seen_requirements, key=REQUIREMENTS_ORDER.index - ) + seen_requirements = [k for k in requirements_section if k in REQUIREMENTS_ORDER] + requirements_order_sorted = sorted(seen_requirements, key=REQUIREMENTS_ORDER.index) if seen_requirements != requirements_order_sorted: lints.append( "The `requirements/` sections should be defined " @@ -167,16 +144,23 @@ def lint_requirements_order(requirements_section: dict, lints: list): + "." ) + def lint_package_version(package_section: dict, context_section: dict): package_ver = str(package_section.get("version")) context_ver = str(context_section.get("version")) - ver = package_ver if package_ver is not None and not package_ver.startswith("$") else context_ver + ver = ( + package_ver + if package_ver is not None and not package_ver.startswith("$") + else context_ver + ) try: VersionOrder(ver) - except: + + except Exception: return "Package version {} doesn't match conda spec".format(ver) + def lint_files_have_hash(sources_section: list, lints: list): for source_section in sources_section: if "url" in source_section and not ( @@ -187,6 +171,7 @@ def lint_files_have_hash(sources_section: list, lints: list): "or md5 checksum (sha256 preferably)." ) + def lint_legacy_compilers(build_reqs): if build_reqs and ("toolchain" in build_reqs): return """Using toolchain directly in this manner is deprecated. Consider @@ -199,17 +184,19 @@ def lint_has_recipe_file(about_section, lints): if not license_file: lints.append("license_file entry is missing, but is required.") + def lint_package_name(package_section: dict, context_section: dict): package_name = str(package_section.get("name")) context_name = str(context_section.get("name")) - ver = package_name if package_name is not None and not package_name.startswith("$") else context_name + actual_name = ( + package_name + if package_name is not None and not package_name.startswith("$") + else context_name + ) - recipe_name = package_section.get("name", "").strip() - if re.match(r"^[a-z0-9_\-.]+$", recipe_name) is None: - return """ - Recipe name has invalid characters. only lowercase alpha, numeric, - underscores, hyphens and dots allowed """ - + actual_name = actual_name.strip() + if re.match(r"^[a-z0-9_\-.]+$", actual_name) is None: + return """Recipe name has invalid characters. only lowercase alpha, numeric, underscores, hyphens and dots allowed""" def lint_legacy_patterns(requirements_section): @@ -224,12 +211,16 @@ def lint_legacy_patterns(requirements_section): return lints -def lint_usage_of_selectors_for_noarch(noarch_value, build_section, requirements_section): +def lint_usage_of_selectors_for_noarch( + noarch_value, build_section, requirements_section +): lints = [] - for section in requirements_section: section_requirements = requirements_section[section] + if not section_requirements: + continue + if any(isinstance(req, dict) for req in section_requirements): lints.append( "`noarch` packages can't have skips with selectors. If " @@ -237,7 +228,7 @@ def lint_usage_of_selectors_for_noarch(noarch_value, build_section, requirements "`noarch: {}`.".format(noarch_value) ) break - + if "skip" in build_section: lints.append( "`noarch` packages can't have skips with selectors. If " @@ -247,47 +238,96 @@ def lint_usage_of_selectors_for_noarch(noarch_value, build_section, requirements return lints + def lint_usage_of_single_space_in_pinned_requirements(requirements_section: dict): - def verify_requirement(requirement): - import re - pattern = r'\b\w+\b(\s*(>=|>|<=|<|==)\s*\d+\.\d+)?' - if re.match(pattern, requirement): - return True - return False + def verify_requirement(requirement, section): + lints = [] + if "${{" in requirement: + return lints + parts = requirement.split() + if len(parts) > 2 and parts[1] in [ + "!=", + "=", + "==", + ">", + "<", + "<=", + ">=", + ]: + # check for too many spaces + lints.append( + ( + "``requirements: {section}: {requirement}`` should not " + "contain a space between relational operator and the version, i.e. " + "``{name} {pin}``" + ).format( + section=section, + requirement=requirement, + name=parts[0], + pin="".join(parts[1:]), + ) + ) + return lints + # check that there is a space if there is a pin + bad_char_idx = [(parts[0].find(c), c) for c in "><="] + bad_char_idx = [bci for bci in bad_char_idx if bci[0] >= 0] + if bad_char_idx: + bad_char_idx.sort() + i = bad_char_idx[0][0] + lints.append( + ( + "``requirements: {section}: {requirement}`` must " + "contain a space between the name and the pin, i.e. " + "``{name} {pin}``" + ).format( + section=section, + requirement=requirement, + name=parts[0][:i], + pin=parts[0][i:] + "".join(parts[1:]), + ) + ) + + return lints lints = [] for section, requirements in requirements_section.items(): + if not requirements: + continue for req in requirements: - is_valid = verify_requirement(req) - if not is_valid: - lints.append(f"``requirements: {section}: {req}`` should not " - "contain a space between relational operator and the version, i.e. " - "``{name} {pin}`` and must contain a space between the name and the pin") + lints.extend(verify_requirement(req, section)) return lints + def lint_non_noarch_dont_constrain_python_and_rbase(requirements_section): check_languages = ["python", "r-base"] host_reqs = requirements_section.get("host") or [] run_reqs = requirements_section.get("run") or [] - + lints = [] - + for language in check_languages: - filtered_host_reqs = [req for req in host_reqs if req.startswith(f"{language} ")] - filtered_run_reqs = [req for req in run_reqs if req.startswith(f"{language} ")] - + filtered_host_reqs = [req for req in host_reqs if req.startswith(f"{language}")] + filtered_run_reqs = [req for req in run_reqs if req.startswith(f"{language}")] + if filtered_host_reqs and not filtered_run_reqs: - lints.append(f"If {language} is a host requirement, it should be a run requirement.") - + lints.append( + f"If {language} is a host requirement, it should be a run requirement." + ) + for reqs in [filtered_host_reqs, filtered_run_reqs]: if language not in reqs: for req in reqs: - constraint = req.split(" ", 1)[1] - if constraint.startswith(">") or constraint.startswith("<") or constraint.startswith("="): - lints.append(f"Non noarch packages should have {language} requirement without any version constraints.") - + splitted = req.split(" ", 1) + if len(splitted) > 1: + constraint = req.split(" ", 1)[1] + if constraint.startswith(">") or constraint.startswith("<"): + lints.append( + f"Non noarch packages should have {language} requirement without any version constraints." + ) + return lints + def lint_variable_reference_should_have_space(recipe_dir, recipe_file): hints = [] if recipe_dir is not None and os.path.exists(recipe_file): @@ -304,12 +344,13 @@ def lint_variable_reference_should_have_space(recipe_dir, recipe_file): if bad_vars: hints.append( "Jinja2 variable references are suggested to " - "take a ``{{}}``" + "take a ``${{}}``" " form. See lines %s." % (bad_lines,) ) return hints + def lint_lower_bound_on_python(run_requirements, outputs_section): lints = [] # if noarch_value == "python" and not outputs_section: @@ -324,6 +365,7 @@ def lint_lower_bound_on_python(run_requirements, outputs_section): "upstream for the package's Python compatibility." ) + def hint_pip_usage(build_section): hints = [] @@ -341,13 +383,18 @@ def hint_pip_usage(build_section): def hint_noarch_usage(build_section, requirement_section: dict): - build_reqs = requirement_section.get("build_reqs", None) + build_reqs = requirement_section.get("build", None) hints = [] if ( # move outside the call # noarch_value is None build_reqs - and not any(["_compiler_stub" in b for b in build_reqs]) + and not any( + [ + b.startswith("${{") and ("compiler('c')" in b or 'compiler("c")' in b) + for b in build_reqs + ] + ) and ("pip" in build_reqs) # move outside the call # and (is_staged_recipes or not conda_forge) @@ -355,52 +402,201 @@ def hint_noarch_usage(build_section, requirement_section: dict): no_arch_possible = True if "skip" in build_section: no_arch_possible = False - + for _, section_requirements in requirement_section.items(): - if any(isinstance(requirement, dict) for requirement in section_requirements): + if any( + isinstance(requirement, dict) for requirement in section_requirements + ): no_arch_possible = False break - + if no_arch_possible: hints.append( "Whenever possible python packages should use noarch. " "See https://conda-forge.org/docs/maintainer/knowledge_base.html#noarch-builds" ) - return hints + return hints +def run_conda_forge_specific( + recipe_dir, + package_section, + extra_section, + sources_section, + requirements_section, + outputs_section, +): + lints = [] + hints = [] + gh = github.Github(os.environ["GH_TOKEN"]) -def normalize_license(s): - """Set to ALL CAPS, replace common GPL patterns, and strip""" - s = s.upper() - s = re.sub("GENERAL PUBLIC LICENSE", "GPL", s) - s = re.sub("LESSER *", "L", s) - s = re.sub("AFFERO *", "A", s) - return s.strip() + # Fetch list of recipe maintainers + maintainers = extra_section.get("recipe-maintainers", []) -def remove_special_characters(s): - """Remove punctuation, spaces, tabs, and line feeds""" - s = PUNK_REGEX.sub(" ", s) - s = re.sub(r"\s+", "", s) - return s + recipe_dirname = os.path.basename(recipe_dir) if recipe_dir else "recipe" + recipe_name = package_section.get("name", "").strip() + is_staged_recipes = recipe_dirname != "recipe" + + # 1: Check that the recipe does not exist in conda-forge or bioconda + if is_staged_recipes and recipe_name: + cf = gh.get_user(os.getenv("GH_ORG", "conda-forge")) + + for name in set( + [ + recipe_name, + recipe_name.replace("-", "_"), + recipe_name.replace("_", "-"), + ] + ): + try: + if cf.get_repo("{}-feedstock".format(name)): + existing_recipe_name = name + feedstock_exists = True + break + else: + feedstock_exists = False + except github.UnknownObjectException: + feedstock_exists = False -def indent(message): - textwrap.fill(textwrap.dedent(message)) + if feedstock_exists and existing_recipe_name == recipe_name: + lints.append("Feedstock with the same name exists in conda-forge.") + elif feedstock_exists: + hints.append( + "Feedstock with the name {} exists in conda-forge. Is it the same as this package ({})?".format( + existing_recipe_name, + recipe_name, + ) + ) -def ensure_valid_license_family(about_section): - try: - license_family = about_section["license_family"] - except KeyError: + bio = gh.get_user("bioconda").get_repo("bioconda-recipes") + try: + bio.get_dir_contents("recipes/{}".format(recipe_name)) + except github.UnknownObjectException: + pass + else: + hints.append( + "Recipe with the same name exists in bioconda: " + "please discuss with @conda-forge/bioconda-recipes." + ) + + url = None + if isinstance(sources_section, dict): + if str(sources_section.get("url")).startswith( + "https://pypi.io/packages/source/" + ): + url = sources_section["url"] + else: + for source_section in sources_section: + if str(source_section.get("url")).startswith( + "https://pypi.io/packages/source/" + ): + url = source_section["url"] + + if url: + # get pypi name from urls like "https://pypi.io/packages/source/b/build/build-0.4.0.tar.gz" + pypi_name = url.split("/")[6] + mapping_request = requests.get( + "https://raw.githubusercontent.com/regro/cf-graph-countyfair/master/mappings/pypi/name_mapping.yaml" + ) + if mapping_request.status_code == 200: + mapping_raw_yaml = mapping_request.content + mapping = load_yaml(mapping_raw_yaml) + for pkg in mapping: + if pkg.get("pypi_name", "") == pypi_name: + conda_name = pkg["conda_name"] + hints.append( + f"A conda package with same name ({conda_name}) already exists." + ) + + # 2: Check that the recipe maintainers exists: + for maintainer in maintainers: + if "/" in maintainer: + # It's a team. Checking for existence is expensive. Skip for now + continue + try: + gh.get_user(maintainer) + except github.UnknownObjectException: + lints.append('Recipe maintainer "{}" does not exist'.format(maintainer)) + + # 3: if the recipe dir is inside the example dir + if recipe_dir is not None and "recipes/example/" in recipe_dir: + lints.append( + "Please move the recipe out of the example dir and " "into its own dir." + ) + + # 4: Do not delete example recipe + if is_staged_recipes and recipe_dir is not None: + example_meta_fname = os.path.abspath( + os.path.join(recipe_dir, "..", "example", "meta.yaml") + ) + + if not os.path.exists(example_meta_fname): + msg = ( + "Please do not delete the example recipe found in " + "`recipes/example/meta.yaml`." + ) + + if msg not in lints: + lints.append(msg) + + # 5: Package-specific hints + # (e.g. do not depend on matplotlib, only matplotlib-base) + # TODO: do the same for if selectors + build_reqs = requirements_section.get("build") or [] + host_reqs = requirements_section.get("host") or [] + run_reqs = requirements_section.get("run") or [] + for out in outputs_section: + _req = out.get("requirements") or {} + if isinstance(_req, Mapping): + build_reqs += _req.get("build") or [] + host_reqs += _req.get("host") or [] + run_reqs += _req.get("run") or [] + else: + run_reqs += _req + + hints_toml_url = "https://raw.githubusercontent.com/conda-forge/conda-forge-pinning-feedstock/main/recipe/linter_hints/hints.toml" + hints_toml_req = requests.get(hints_toml_url) + if hints_toml_req.status_code != 200: + # too bad, but not important enough to throw an error; + # linter will rerun on the next commit anyway return - allowed_families = [ - remove_special_characters(normalize_license(fam)) for fam in ALLOWED_LICENSE_FAMILIES - ] - if remove_special_characters(normalize_license(license_family)) not in allowed_families: - raise RuntimeError( - indent( - f"about/license_family '{license_family}' not allowed. " - f"Allowed families are {", ".join(sorted(ALLOWED_LICENSE_FAMILIES))}." + hints_toml_str = hints_toml_req.content.decode("utf-8") + specific_hints = tomllib.loads(hints_toml_str)["hints"] + + for rq in build_reqs + host_reqs + run_reqs: + dep = rq.split(" ")[0].strip() + if dep in specific_hints and specific_hints[dep] not in hints: + hints.append(specific_hints[dep]) + + # 6: Check if all listed maintainers have commented: + pr_number = os.environ.get("STAGED_RECIPES_PR_NUMBER") + + if is_staged_recipes and maintainers and pr_number: + # Get PR details using GitHub API + current_pr = gh.get_repo("conda-forge/staged-recipes").get_pull(int(pr_number)) + + # Get PR author, issue comments, and review comments + pr_author = current_pr.user.login + issue_comments = current_pr.get_issue_comments() + review_comments = current_pr.get_reviews() + + # Combine commenters from both issue comments and review comments + commenters = {comment.user.login for comment in issue_comments} + commenters.update({review.user.login for review in review_comments}) + + # Check if all maintainers have either commented or are the PR author + non_participating_maintainers = set() + for maintainer in maintainers: + if maintainer not in commenters and maintainer != pr_author: + non_participating_maintainers.add(maintainer) + + # Add a lint message if there are any non-participating maintainers + if non_participating_maintainers: + lints.append( + f"The following maintainers have not yet confirmed that they are willing to be listed here: " + f"{', '.join(non_participating_maintainers)}. Please ask them to comment on this PR if they are." ) - ) \ No newline at end of file + + return lints, hints diff --git a/src/rattler_build_conda_compat/loader.py b/src/rattler_build_conda_compat/loader.py index 39fae76..56d4472 100644 --- a/src/rattler_build_conda_compat/loader.py +++ b/src/rattler_build_conda_compat/loader.py @@ -1,6 +1,6 @@ from contextlib import contextmanager import yaml -from typing import Any +from typing import Any, Union class RecipeLoader(yaml.BaseLoader): @@ -66,6 +66,10 @@ def construct_sequence(self, node: Any, deep: bool = False) -> Any: return [self.construct_object(child, deep=deep) for child in node.value] +def load_yaml(content: Union[str, bytes]): + return yaml.load(content, Loader=RecipeLoader) + + def remove_empty_keys(variant_dict): filtered_dict = {} for key, value in variant_dict.items(): @@ -83,16 +87,18 @@ def parse_recipe_config_file(path, namespace): return remove_empty_keys(content) -def load_all_requirements(path) -> dict: - with open(path) as f: - content = yaml.load(f, Loader=yaml.BaseLoader) +def load_all_requirements(content) -> dict: + # with open(path) as f: + # content = yaml.load(f, Loader=yaml.BaseLoader) - requirements_section = content.get("requirements", None) + requirements_section = dict(content.get("requirements", {})) if not requirements_section: - return content - + return {} + for section in requirements_section: section_reqs = requirements_section[section] + if not section_reqs: + continue expanded_reqs = [] for req in section_reqs: if isinstance(req, dict): @@ -104,4 +110,4 @@ def load_all_requirements(path) -> dict: expanded_reqs.append(req) requirements_section[section] = expanded_reqs - return content + return requirements_section From d10ac125b87e6d7c7d14116a71ef5d5c28126439 Mon Sep 17 00:00:00 2001 From: nichmor Date: Thu, 25 Apr 2024 16:54:43 +0300 Subject: [PATCH 3/4] misc: update lockfile --- pixi.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pixi.lock b/pixi.lock index 31a4e76..392a272 100644 --- a/pixi.lock +++ b/pixi.lock @@ -5410,9 +5410,9 @@ packages: timestamp: 1713391855237 - kind: pypi name: rattler-build-conda-compat - version: 0.0.2 + version: 0.0.3 path: . - sha256: 30e8c7c6d01ffb58a7a8663ea0db34015821e1cfb2761836ba6e643a8048a59f + sha256: 86573463a4d85e97bb765a5eca0423c016664e1588519468255fc6dc72530a8d requires_python: '>=3.8' editable: true - kind: conda From 06d5a07a3efd599f2c82bc2adedf645191db4de1 Mon Sep 17 00:00:00 2001 From: nichmor Date: Thu, 25 Apr 2024 17:00:51 +0300 Subject: [PATCH 4/4] fix: API usage of loader --- pixi.toml | 3 +++ src/rattler_build_conda_compat/loader.py | 4 +++- tests/test_rattler_loader.py | 8 +++++--- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/pixi.toml b/pixi.toml index 9df6806..356666a 100644 --- a/pixi.toml +++ b/pixi.toml @@ -28,6 +28,9 @@ pytest = "*" syrupy = "*" ruff = "*" +[feature.test.tasks] +test = "pytest" + [environments] test = ["test"] \ No newline at end of file diff --git a/src/rattler_build_conda_compat/loader.py b/src/rattler_build_conda_compat/loader.py index 56d4472..28b5c12 100644 --- a/src/rattler_build_conda_compat/loader.py +++ b/src/rattler_build_conda_compat/loader.py @@ -1,4 +1,6 @@ from contextlib import contextmanager +from os import PathLike +from pathlib import Path import yaml from typing import Any, Union @@ -67,7 +69,7 @@ def construct_sequence(self, node: Any, deep: bool = False) -> Any: def load_yaml(content: Union[str, bytes]): - return yaml.load(content, Loader=RecipeLoader) + return yaml.load(content, Loader=yaml.BaseLoader) def remove_empty_keys(variant_dict): diff --git a/tests/test_rattler_loader.py b/tests/test_rattler_loader.py index 12b3e55..ee4d5ae 100644 --- a/tests/test_rattler_loader.py +++ b/tests/test_rattler_loader.py @@ -1,5 +1,5 @@ import yaml -from rattler_build_conda_compat.loader import parse_recipe_config_file, load_all_requirements +from rattler_build_conda_compat.loader import load_yaml, parse_recipe_config_file, load_all_requirements from pathlib import Path @@ -12,7 +12,9 @@ def test_load_variants(snapshot, unix_namespace): def test_load_all_requirements(): - recipe_path = Path("tests/data/recipe_requirements.yaml") + recipe_content = Path("tests/data/recipe_requirements.yaml").read_text() - content = load_all_requirements(recipe_path) + recipe_content = load_yaml(recipe_content) + + content = load_all_requirements(recipe_content) print(content)