diff --git a/.github/actions/features_parse/action.yml b/.github/actions/features_parse/action.yml deleted file mode 100644 index 99c79a2f..00000000 --- a/.github/actions/features_parse/action.yml +++ /dev/null @@ -1,18 +0,0 @@ -name: features_parse -description: Parses the given GardenLinux features parameters -inputs: - flags: - description: "Flags passed to `gl-features-parse`" - required: true -outputs: - result: - description: "features result" - value: ${{ steps.result.outputs.result }} -runs: - using: composite - steps: - - uses: gardenlinux/python-gardenlinux-lib/.github/actions/setup@0.10.11 - - id: result - shell: bash - run: | - echo "result=$(gl-features-parse ${{ inputs.flags }})" | tee -a $GITHUB_OUTPUT diff --git a/.github/actions/flavors_parse/action.yml b/.github/actions/flavors_parse/action.yml deleted file mode 100644 index b31b58a2..00000000 --- a/.github/actions/flavors_parse/action.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: flavors_parse -description: Parses the given GardenLinux flavors parameters -inputs: - flags: - description: "Flags passed to `gl-flavors-parse`" - required: true - flavors_matrix: - description: "Generated GitHub workflow flavors matrix" -outputs: - matrix: - description: "Flavors matrix" - value: ${{ steps.matrix.outputs.matrix }} -runs: - using: composite - steps: - - uses: gardenlinux/python-gardenlinux-lib/.github/actions/setup@0.10.11 - - id: matrix - shell: bash - run: | - MATRIX='${{ inputs.flavors_matrix }}' - - if [[ $(echo "${MATRIX}" | jq -r 'type') != 'object' ]]; then - FLAVORS=$(gl-flavors-parse ${{ inputs.flags }}) - MATRIX=$(jq -nc \ - --argjson flavors "$(echo $FLAVORS)" \ - '{ - include: ( - $flavors | reduce (to_entries[]) as $item ([]; . + ($item.value | map({"arch": $item.key, "flavor": .}))) - ) - }' - ) - fi - - echo "matrix=$MATRIX" | tee -a $GITHUB_OUTPUT diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ea1dcf0b..834f774f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -2,7 +2,10 @@ name: pre-release on: push: - tags: [ "[0-9]+.[0-9]+.[0-9]+*" ] + branches: + - main + tags: + - "[0-9]+.[0-9]+.[0-9]+*" env: GIT_CLIFF_VERSION: 2.13.1 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index cb783c5c..984bb12e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -22,6 +22,5 @@ repos: - id: mypy args: [--strict, --ignore-missing-imports, --check-untyped-defs, --allow-untyped-decorators] additional_dependencies: - - types-click - types-PyYAML - types-requests diff --git a/cliff.toml b/cliff.toml index 4199d166..b6aff8c1 100644 --- a/cliff.toml +++ b/cliff.toml @@ -42,11 +42,10 @@ footer = """ {% for release in releases -%} {% if release.version -%} {% if release.previous.version -%} - [{{ release.previous.version | trim_start_matches(pat="v") }}]: \ - {{ self::remote_url() }}/compare/{{ release.previous.version }}...{{ release.version }} + - [v{{ release.previous.version | trim_start_matches(pat="v") }}]({{ self::remote_url() }}/compare/{{ release.previous.version }}...{{ release.version }}) {% endif -%} {% else -%} - [unreleased]: {{ self::remote_url() }}/compare/{{ release.previous.version }}...HEAD + - [unreleased]({{ self::remote_url() }}/compare/{{ release.previous.version }}...HEAD) {% endif -%} {% endfor %} diff --git a/docs/cli.rst b/docs/cli.rst index f975b2aa..caee3ff5 100644 --- a/docs/cli.rst +++ b/docs/cli.rst @@ -6,20 +6,20 @@ Available command-line tools provided by the Garden Linux Python Library Features Commands ----------------- -gl-cname -~~~~~~~~ - -Generate a canonical name (cname) from feature sets. - -.. autoprogram:: gardenlinux.features.cname_main:get_parser() - gl-features-parse ~~~~~~~~~~~~~~~~~ -Parse and extract information from GardenLinux features. +Parse and extract information from Garden Linux features. .. autoprogram:: gardenlinux.features.__main__:get_parser() +gl-features-metadata +~~~~~~~~~~~~~~~~~~~~ + +Provides Garden Linux release metadata file handling. + +.. autoprogram:: gardenlinux.features.metadata_main:get_parser() + Flavors Commands ---------------- @@ -38,9 +38,7 @@ gl-oci Push OCI artifacts to a registry and manage manifests. -.. click:: gardenlinux.oci.__main__:cli - :prog: gl-oci - :show-nested: +.. autoprogram:: gardenlinux.oci.__main__:get_parser() S3 Commands ----------- diff --git a/docs/conf.py b/docs/conf.py index a24c6f5f..45b219c5 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -20,7 +20,6 @@ "sphinx.ext.coverage", "sphinx_rtd_theme", "sphinx.ext.napoleon", - "sphinx_click", "sphinxcontrib.autoprogram", "sphinx_markdown_builder", ] diff --git a/poetry.lock b/poetry.lock index d29211c2..5f36c432 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 2.4.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.2.0 and should not be changed by hand. [[package]] name = "alabaster" @@ -25,45 +25,69 @@ files = [ [[package]] name = "ast-serialize" -version = "0.5.0" +version = "0.12.1" description = "Python bindings for mypy AST serialization" optional = false python-versions = ">=3.7" groups = ["dev"] files = [ - {file = "ast_serialize-0.5.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:8f5c14f169eb0972c0c21bada5358b23d6047c76583b005234f865b11f1fa00a"}, - {file = "ast_serialize-0.5.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7d1a2de9de5be04652f0ed60738356ef94f66db37924a9499fffe98dc491aa0b"}, - {file = "ast_serialize-0.5.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:be5173fb66f9b49026d9d5a2ff0fc7c7009077107c0eb285b2d60fdf1fe10bd1"}, - {file = "ast_serialize-0.5.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f8015cd071ac1339924ee2b8098c93e00e155f30a16f40ec9816fcf84f4753f6"}, - {file = "ast_serialize-0.5.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5499e8797edff2a9186aa313ed382c6b422e798e9332d9953badcee6e69a88f2"}, - {file = "ast_serialize-0.5.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6848f2a093fb5548751a9a09bff8fcd229e2bbeb0e3331f391b6ae6d26cd9903"}, - {file = "ast_serialize-0.5.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:832d4c998e0b091fd60a6d6bceee535483c4d490de9ba85003af835225719261"}, - {file = "ast_serialize-0.5.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:16db7c62ec0b8efe1d7afd283a388d8f74f2605d56032e5a37747d2de8dba027"}, - {file = "ast_serialize-0.5.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:baf5eb061eb5bccade4128ad42da33787d72f6013809cd1b590376ece8b3c937"}, - {file = "ast_serialize-0.5.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:104e4a35bd7c124173c41760ef9aaea17ddb3f86c65cb643671d59afbe3ee94c"}, - {file = "ast_serialize-0.5.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:36be371028fc1675acb38a331bde160dbab7ff907fdf00b67eb6911aa106951b"}, - {file = "ast_serialize-0.5.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:061ee58bdb52341c8201a6df41182a977736bae3b7ded87ca7176ca25a8a47ab"}, - {file = "ast_serialize-0.5.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:b15219e9cdc9f53f6f4cb51c009203507228226148c05c5e8fe451c28b435eb3"}, - {file = "ast_serialize-0.5.0-cp314-cp314t-win32.whl", hash = "sha256:842d1c004bb466c7df036f95fabef789570541922b10976b12f5592a69cf0b38"}, - {file = "ast_serialize-0.5.0-cp314-cp314t-win_amd64.whl", hash = "sha256:b0c06d760909b095cc466356dfccd05a1c7233a6ca191c020dca2c6a6f16c24c"}, - {file = "ast_serialize-0.5.0-cp314-cp314t-win_arm64.whl", hash = "sha256:787baedb0262cc49e8ce37cc15c00ae818e46a165a3b36f5e21ed174998104cb"}, - {file = "ast_serialize-0.5.0-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:0668aa9459cfa8c9c49ddd2163ebcf43088ba045ef7492af6fe22e0098303101"}, - {file = "ast_serialize-0.5.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:bf683d6363edf2b39eed6b6d4fe22d34b6203867a67e27134d9e2a2680c4bc4a"}, - {file = "ast_serialize-0.5.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cc22cf0c9be65e71cf88fda130af60d61eb4a79370ad4cfe7900d48a4aa2211"}, - {file = "ast_serialize-0.5.0-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f66173891548c9f2726bf27957b41cabce12fa679dc6da505ddbde4d4b3b31cf"}, - {file = "ast_serialize-0.5.0-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e42d729ef2be96a14efbad355093284739e3670ece3e534f82cc8832790911d9"}, - {file = "ast_serialize-0.5.0-cp39-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b725026bafa801dbd7310eb13a75f0a2e370e7e51b2cb225f9d21fcfadf919ee"}, - {file = "ast_serialize-0.5.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b54f60c1d78767a53b67eaa663f0dfac3afe606aa07f1301572f588b73d64809"}, - {file = "ast_serialize-0.5.0-cp39-abi3-manylinux_2_31_riscv64.whl", hash = "sha256:27d51654fc240a1e87e742d353d98eb45b75f62f129086b3596ab53df2ac2a43"}, - {file = "ast_serialize-0.5.0-cp39-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2782c36237c46dd1674542f2109740ea5ea485a169bf1431939ada0434e17934"}, - {file = "ast_serialize-0.5.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:1943db345233cc7194a470f13afa9c59772c0b123dea0c9414c4d4ca54369759"}, - {file = "ast_serialize-0.5.0-cp39-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:df1c00022cbbcb064bfaa505aa9c9295362443ce5dacb459d1331d3da353f887"}, - {file = "ast_serialize-0.5.0-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:cae65289fc456fde04af979a2be09302ef5d8ab92ef23e596d6746dc267ada27"}, - {file = "ast_serialize-0.5.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:239a4c354e8d676e9d94631d1d4a64edc6b266f86ff3a5a80aedd344f342c01d"}, - {file = "ast_serialize-0.5.0-cp39-abi3-win32.whl", hash = "sha256:143a4ef63285a075871908fda3672dc21864b83a8ec3ee12304aa3e4c5387b9a"}, - {file = "ast_serialize-0.5.0-cp39-abi3-win_amd64.whl", hash = "sha256:cf25572c526add400f26a4750dc6ce0c3bb93fc1f75e7ae0cad4ce4f2cd5c590"}, - {file = "ast_serialize-0.5.0-cp39-abi3-win_arm64.whl", hash = "sha256:92a31c9c20d25a076edaeec76b128a3535d74a24f340b9a8a7e96c9b86dc9642"}, - {file = "ast_serialize-0.5.0.tar.gz", hash = "sha256:5880091bfe6f4f986f22866375c2e884843e7a0b6343ae41aeea659613d879b6"}, + {file = "ast_serialize-0.12.1-cp314-cp314-pyemscripten_2026_0_wasm32.whl", hash = "sha256:e73255c9227fd74eac8a9b55c4049e8ad7b66d1f690bf827c98a86b2e594def7"}, + {file = "ast_serialize-0.12.1-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:4655ef993e69e01bb47d2d99647de9bbb74af03938438656832cd010d95de348"}, + {file = "ast_serialize-0.12.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:bac5a99a2c91dd823be9b8c44645694fccbb0750773cc5b27889a9f6f22fce89"}, + {file = "ast_serialize-0.12.1-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6485e681625ed7a094221f16a7ff2ef154946112266a05cf83bde50c959ef345"}, + {file = "ast_serialize-0.12.1-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a513bc6f60980d01767f7cbe39b17ce0373e722824a74ce28d6cea49ee3c8460"}, + {file = "ast_serialize-0.12.1-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:82866f3523d53ffca8d2a69a750bec52908b69f728012e40959bebce2620453c"}, + {file = "ast_serialize-0.12.1-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:243054a05a5190f5d087b5c8b16423e7f1cefa4991bac26e9c8ace18074b75b6"}, + {file = "ast_serialize-0.12.1-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7d9fbe5a3e8acddfc2fddff3dbbc7ea0e9798b3df3428f851b8abc52a3806f31"}, + {file = "ast_serialize-0.12.1-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:d3d516da3463071d27e64caf54d88cba25cf4ad4afcc807e0bcf67743719f03e"}, + {file = "ast_serialize-0.12.1-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8d6711adf11136c77e3a35517de9488a5081d1012874fae99c2876b64f4daace"}, + {file = "ast_serialize-0.12.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:cbe239bee4bd609186daf60b95b7b0f47146c7f7f55f6da83807d747d6fe753f"}, + {file = "ast_serialize-0.12.1-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:5bbf582286c9dc6b4c544ef645dc99e4b3aa09db28892bc60344141f6926641f"}, + {file = "ast_serialize-0.12.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:99e33c93efb5254a70c525b46038212371dfe5693d48eb2d0d5f17d936a263d7"}, + {file = "ast_serialize-0.12.1-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:aa6c17a2b7f07e81fa8cfcc4aa7c832b3e57733853aebea113ab502f9b0963db"}, + {file = "ast_serialize-0.12.1-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:f896fa38e0af38821e1ab1425c5dee89e359623e165765bdeae7d0eb6909e76d"}, + {file = "ast_serialize-0.12.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:af699e81fd7ce80b8b03945826d8ea23dd36d072f10d4613402da597ba4ee9c6"}, + {file = "ast_serialize-0.12.1-cp314-cp314t-win32.whl", hash = "sha256:10b59afc108eb285146acb23d1b5ec0fc58bb3c09cb2ab8876402df06c373c3b"}, + {file = "ast_serialize-0.12.1-cp314-cp314t-win_amd64.whl", hash = "sha256:72e871f6995a066c1b19104f8a6b5832b1163adb9a8267c2aa4711fbb0f4d1f3"}, + {file = "ast_serialize-0.12.1-cp314-cp314t-win_arm64.whl", hash = "sha256:3398e458047d21c9bc1b323fe5aab77c608dc9ddb65b2d44deebaff503a1f1eb"}, + {file = "ast_serialize-0.12.1-cp315-abi3.abi3t-macosx_10_12_x86_64.whl", hash = "sha256:410233de149ab8414cb27c6fc73e9d2baa35d6f971672d540d752060d980ffb4"}, + {file = "ast_serialize-0.12.1-cp315-abi3.abi3t-macosx_11_0_arm64.whl", hash = "sha256:b9a2310845302f1a6bd45ae8a67d5760211103a8d66410b854bfa440d107e093"}, + {file = "ast_serialize-0.12.1-cp315-abi3.abi3t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ff65f40f49d5e1a1a043ba366081d59a4e26a9f5c1b07eb1170e172115da7ca"}, + {file = "ast_serialize-0.12.1-cp315-abi3.abi3t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:536d783c4d91331f094e0a892221e619be5ffbe6fb6640885f14d7f226ec90ca"}, + {file = "ast_serialize-0.12.1-cp315-abi3.abi3t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c42d2d65f388d1960c5796231eb9bf5a988c46228633eb489605c4549ad16c52"}, + {file = "ast_serialize-0.12.1-cp315-abi3.abi3t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a5628a12acc875fe7a167910f18d101dd101c2a7b1e6c2b6f7289ffaff25805c"}, + {file = "ast_serialize-0.12.1-cp315-abi3.abi3t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e855adfa5bb982b2e6fe09056b2d584f6dd4fce085d91a07d1155683751b6b5"}, + {file = "ast_serialize-0.12.1-cp315-abi3.abi3t-manylinux_2_31_riscv64.whl", hash = "sha256:fafe1471e8aca6c87b4913b7b54ff97197adf702fbe28692284b929dfa62ff96"}, + {file = "ast_serialize-0.12.1-cp315-abi3.abi3t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a5cac246474d2a703147d1605a6ac5ba0fa9e0a443cf1cf42513adf4df02686f"}, + {file = "ast_serialize-0.12.1-cp315-abi3.abi3t-musllinux_1_2_aarch64.whl", hash = "sha256:6e25cd319fb0d7b39fcac666784ec86708ccbc78d07a698b1400cf5ed40c045b"}, + {file = "ast_serialize-0.12.1-cp315-abi3.abi3t-musllinux_1_2_armv7l.whl", hash = "sha256:657a7354ea16ed4d29f8127ed477c6fee3915c111d135f020ca835a991438e90"}, + {file = "ast_serialize-0.12.1-cp315-abi3.abi3t-musllinux_1_2_i686.whl", hash = "sha256:9eb9de7e59621acdb3e66984f374272b33d56d15a04763e2fd0604211e1c8303"}, + {file = "ast_serialize-0.12.1-cp315-abi3.abi3t-musllinux_1_2_ppc64le.whl", hash = "sha256:09cc4d3103c1fc97f6845ba307af1db9cde5226bef47f8843220dde83f2276ba"}, + {file = "ast_serialize-0.12.1-cp315-abi3.abi3t-musllinux_1_2_riscv64.whl", hash = "sha256:c9e2a592706fd791c2271ce9c8f4e38c98d3ea0b4a86b511e09a4fe3ac44ab37"}, + {file = "ast_serialize-0.12.1-cp315-abi3.abi3t-musllinux_1_2_x86_64.whl", hash = "sha256:f4ac042e95a575432c1730ca4cb9183066a2074886a599f46c1f1b0955fb8198"}, + {file = "ast_serialize-0.12.1-cp315-abi3.abi3t-win32.whl", hash = "sha256:b3cd105995942cc6163a229674a86161ba1305f646493efd59bd6723a357ee14"}, + {file = "ast_serialize-0.12.1-cp315-abi3.abi3t-win_amd64.whl", hash = "sha256:a9cd24a26126088693ca054547ea0a391398a29cf1a3a2bec1009b4b6acc8b82"}, + {file = "ast_serialize-0.12.1-cp315-abi3.abi3t-win_arm64.whl", hash = "sha256:9649cd903db0dc047906c6dd740784a2ba665d54f7e43ba31457edbce76c9493"}, + {file = "ast_serialize-0.12.1-cp315-cp315-pyemscripten_2026_5_wasm32.whl", hash = "sha256:5ef62601db3ce5c23445132262a193075e211fb2fc87b46b7550dd351fac0976"}, + {file = "ast_serialize-0.12.1-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:98d91cd3a6cb76a39512ee090a539d1e3206b732ad8150eb38918cffa1ddf515"}, + {file = "ast_serialize-0.12.1-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:8a32f184ce3e4b1d0b06d642a1243281cf55b99e0323680b1b8f904029fd7700"}, + {file = "ast_serialize-0.12.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e62126ac2be2d9340ac1b3ee7a0466a883ecbed634cff0929c88ca0b671483b7"}, + {file = "ast_serialize-0.12.1-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0f93a70fa9826c04ea9f2c3a880f87f4cca09a828144ed5084682abd28110980"}, + {file = "ast_serialize-0.12.1-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1858887be56a64a2aea899423dfe43787c34c75c18b0d7497de8e618d54b2790"}, + {file = "ast_serialize-0.12.1-cp39-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:89a2bc39a820bc7785b60c53a5742b4e8dd4c1a599294e2dd68fae545883d44a"}, + {file = "ast_serialize-0.12.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50a9eaedf1db4857dad7cc47dd757ed70bfcc40b89d44d516c4a2f0d5033bd76"}, + {file = "ast_serialize-0.12.1-cp39-abi3-manylinux_2_31_riscv64.whl", hash = "sha256:c30b609e8fea426b310543126de876592236a25aa8ebd59f1e2b323dd52a4085"}, + {file = "ast_serialize-0.12.1-cp39-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7b1ad06513022cfa1337744959255af0ef16119d2beb1e547b67f37ad9433d4a"}, + {file = "ast_serialize-0.12.1-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:6add54b495e37ae3cf3a1f0d5eaba364814eb72e93026adc41b7791e4b0d45d3"}, + {file = "ast_serialize-0.12.1-cp39-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:5fc136cd08001b817ad0b3e7426f50a7d2b8982dc7c6491f0af78af4c3dd8672"}, + {file = "ast_serialize-0.12.1-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:45a9e6b700bbd973d49942668a5cdbeffa693f2e250b8a5409abd1fa9d351854"}, + {file = "ast_serialize-0.12.1-cp39-abi3-musllinux_1_2_ppc64le.whl", hash = "sha256:a1d8267f83c613ea0a31f2518df074bd62e98a4b3a4892f6a529d74e08e02dba"}, + {file = "ast_serialize-0.12.1-cp39-abi3-musllinux_1_2_riscv64.whl", hash = "sha256:9a0cbab9796e6ce841197feeba4008faa96b4cc7741129542fd81c882d7a4f01"}, + {file = "ast_serialize-0.12.1-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:b4282695f1d51a3c6ef76560351bad5af880eff7d755aefea325bffb9bf68c25"}, + {file = "ast_serialize-0.12.1-cp39-abi3-win32.whl", hash = "sha256:119d1b0cadaba4a6e475f9bbe79eecc79351e373142eabe7c353f0250d70aebb"}, + {file = "ast_serialize-0.12.1-cp39-abi3-win_amd64.whl", hash = "sha256:3d6ed63d4fc1ec867b8cb522d58c36df0e8f05e487bea0ffd102043a37636d72"}, + {file = "ast_serialize-0.12.1-cp39-abi3-win_arm64.whl", hash = "sha256:610a41351de68199de9a1434499083b4256c0df7658ec1cfc0a0a7b20b08d317"}, + {file = "ast_serialize-0.12.1.tar.gz", hash = "sha256:5285a390caf1c44368ae270f037f797b91427d138b7d43cad0f1fda4c83518d9"}, ] [[package]] @@ -120,18 +144,18 @@ yaml = ["PyYAML"] [[package]] name = "boto3" -version = "1.43.36" -description = "The AWS SDK for Python" +version = "1.43.108" +description = "The AWS SDK for Python (Boto3)" optional = false python-versions = ">=3.10" groups = ["main", "dev"] files = [ - {file = "boto3-1.43.36-py3-none-any.whl", hash = "sha256:42942dde254673abcbc9e6e60017c88341a4f49d99d24e1f2e290fb38138c26f"}, - {file = "boto3-1.43.36.tar.gz", hash = "sha256:587d7ee92a12e440ad12b0e7f11f3358f0c4d65b19f64726efc94aaf194aff28"}, + {file = "boto3-1.43.108-py3-none-any.whl", hash = "sha256:19e9da95ef0c494e27052049a42137550e66730509bb613e76eaa30ddf9a7170"}, + {file = "boto3-1.43.108.tar.gz", hash = "sha256:03341f089158368acf83e921aca98b706095322ca52bc4c039a616940aa5ad41"}, ] [package.dependencies] -botocore = ">=1.43.36,<1.44.0" +botocore = ">=1.43.108,<1.44.0" jmespath = ">=0.7.1,<2.0.0" s3transfer = ">=0.19.0,<0.20.0" @@ -140,14 +164,14 @@ crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] [[package]] name = "boto3-stubs" -version = "1.43.34" -description = "Type annotations for boto3 1.43.34 generated with mypy-boto3-builder 8.12.0" +version = "1.43.108" +description = "Type annotations for boto3 1.43.108 generated with mypy-boto3-builder 8.12.0" optional = false python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "boto3_stubs-1.43.34-py3-none-any.whl", hash = "sha256:66794a638cf96307622124eaa786f32e3eff7f87b683f1d0d60cf4bc40ce69ae"}, - {file = "boto3_stubs-1.43.34.tar.gz", hash = "sha256:2b6580065e1e145687fd576f15bcf5a399619c8d5121769c8a59c784c2dd22ac"}, + {file = "boto3_stubs-1.43.108-py3-none-any.whl", hash = "sha256:40f02e30f6e455ccb658dcdeb5756ce23bde767f425ab6d7f57a9ffad75a848c"}, + {file = "boto3_stubs-1.43.108.tar.gz", hash = "sha256:a1ed29b4c7957568e6261fc36d4c59025c004997a229e8f01940c205f2128e4a"}, ] [package.dependencies] @@ -158,10 +182,13 @@ types-s3transfer = "*" [package.extras] accessanalyzer = ["mypy-boto3-accessanalyzer (>=1.43.0,<1.44.0)"] account = ["mypy-boto3-account (>=1.43.0,<1.44.0)"] +account-access = ["mypy-boto3-account-access (>=1.43.0,<1.44.0)"] acm = ["mypy-boto3-acm (>=1.43.0,<1.44.0)"] acm-pca = ["mypy-boto3-acm-pca (>=1.43.0,<1.44.0)"] +agent-registry = ["mypy-boto3-agent-registry (>=1.43.0,<1.44.0)"] +agent-registry-control = ["mypy-boto3-agent-registry-control (>=1.43.0,<1.44.0)"] aiops = ["mypy-boto3-aiops (>=1.43.0,<1.44.0)"] -all = ["mypy-boto3-accessanalyzer (>=1.43.0,<1.44.0)", "mypy-boto3-account (>=1.43.0,<1.44.0)", "mypy-boto3-acm (>=1.43.0,<1.44.0)", "mypy-boto3-acm-pca (>=1.43.0,<1.44.0)", "mypy-boto3-aiops (>=1.43.0,<1.44.0)", "mypy-boto3-amp (>=1.43.0,<1.44.0)", "mypy-boto3-amplify (>=1.43.0,<1.44.0)", "mypy-boto3-amplifybackend (>=1.43.0,<1.44.0)", "mypy-boto3-amplifyuibuilder (>=1.43.0,<1.44.0)", "mypy-boto3-apigateway (>=1.43.0,<1.44.0)", "mypy-boto3-apigatewaymanagementapi (>=1.43.0,<1.44.0)", "mypy-boto3-apigatewayv2 (>=1.43.0,<1.44.0)", "mypy-boto3-appconfig (>=1.43.0,<1.44.0)", "mypy-boto3-appconfigdata (>=1.43.0,<1.44.0)", "mypy-boto3-appfabric (>=1.43.0,<1.44.0)", "mypy-boto3-appflow (>=1.43.0,<1.44.0)", "mypy-boto3-appintegrations (>=1.43.0,<1.44.0)", "mypy-boto3-application-autoscaling (>=1.43.0,<1.44.0)", "mypy-boto3-application-insights (>=1.43.0,<1.44.0)", "mypy-boto3-application-signals (>=1.43.0,<1.44.0)", "mypy-boto3-applicationcostprofiler (>=1.43.0,<1.44.0)", "mypy-boto3-appmesh (>=1.43.0,<1.44.0)", "mypy-boto3-apprunner (>=1.43.0,<1.44.0)", "mypy-boto3-appstream (>=1.43.0,<1.44.0)", "mypy-boto3-appsync (>=1.43.0,<1.44.0)", "mypy-boto3-arc-region-switch (>=1.43.0,<1.44.0)", "mypy-boto3-arc-zonal-shift (>=1.43.0,<1.44.0)", "mypy-boto3-artifact (>=1.43.0,<1.44.0)", "mypy-boto3-athena (>=1.43.0,<1.44.0)", "mypy-boto3-auditmanager (>=1.43.0,<1.44.0)", "mypy-boto3-autoscaling (>=1.43.0,<1.44.0)", "mypy-boto3-autoscaling-plans (>=1.43.0,<1.44.0)", "mypy-boto3-b2bi (>=1.43.0,<1.44.0)", "mypy-boto3-backup (>=1.43.0,<1.44.0)", "mypy-boto3-backup-gateway (>=1.43.0,<1.44.0)", "mypy-boto3-backupsearch (>=1.43.0,<1.44.0)", "mypy-boto3-batch (>=1.43.0,<1.44.0)", "mypy-boto3-bcm-dashboards (>=1.43.0,<1.44.0)", "mypy-boto3-bcm-data-exports (>=1.43.0,<1.44.0)", "mypy-boto3-bcm-pricing-calculator (>=1.43.0,<1.44.0)", "mypy-boto3-bcm-recommended-actions (>=1.43.0,<1.44.0)", "mypy-boto3-bedrock (>=1.43.0,<1.44.0)", "mypy-boto3-bedrock-agent (>=1.43.0,<1.44.0)", "mypy-boto3-bedrock-agent-runtime (>=1.43.0,<1.44.0)", "mypy-boto3-bedrock-agentcore (>=1.43.0,<1.44.0)", "mypy-boto3-bedrock-agentcore-control (>=1.43.0,<1.44.0)", "mypy-boto3-bedrock-data-automation (>=1.43.0,<1.44.0)", "mypy-boto3-bedrock-data-automation-runtime (>=1.43.0,<1.44.0)", "mypy-boto3-bedrock-runtime (>=1.43.0,<1.44.0)", "mypy-boto3-billing (>=1.43.0,<1.44.0)", "mypy-boto3-billingconductor (>=1.43.0,<1.44.0)", "mypy-boto3-braket (>=1.43.0,<1.44.0)", "mypy-boto3-budgets (>=1.43.0,<1.44.0)", "mypy-boto3-ce (>=1.43.0,<1.44.0)", "mypy-boto3-chatbot (>=1.43.0,<1.44.0)", "mypy-boto3-chime (>=1.43.0,<1.44.0)", "mypy-boto3-chime-sdk-identity (>=1.43.0,<1.44.0)", "mypy-boto3-chime-sdk-media-pipelines (>=1.43.0,<1.44.0)", "mypy-boto3-chime-sdk-meetings (>=1.43.0,<1.44.0)", "mypy-boto3-chime-sdk-messaging (>=1.43.0,<1.44.0)", "mypy-boto3-chime-sdk-voice (>=1.43.0,<1.44.0)", "mypy-boto3-cleanrooms (>=1.43.0,<1.44.0)", "mypy-boto3-cleanroomsml (>=1.43.0,<1.44.0)", "mypy-boto3-cloud9 (>=1.43.0,<1.44.0)", "mypy-boto3-cloudcontrol (>=1.43.0,<1.44.0)", "mypy-boto3-clouddirectory (>=1.43.0,<1.44.0)", "mypy-boto3-cloudformation (>=1.43.0,<1.44.0)", "mypy-boto3-cloudfront (>=1.43.0,<1.44.0)", "mypy-boto3-cloudfront-keyvaluestore (>=1.43.0,<1.44.0)", "mypy-boto3-cloudhsm (>=1.43.0,<1.44.0)", "mypy-boto3-cloudhsmv2 (>=1.43.0,<1.44.0)", "mypy-boto3-cloudsearch (>=1.43.0,<1.44.0)", "mypy-boto3-cloudsearchdomain (>=1.43.0,<1.44.0)", "mypy-boto3-cloudtrail (>=1.43.0,<1.44.0)", "mypy-boto3-cloudtrail-data (>=1.43.0,<1.44.0)", "mypy-boto3-cloudwatch (>=1.43.0,<1.44.0)", "mypy-boto3-codeartifact (>=1.43.0,<1.44.0)", "mypy-boto3-codebuild (>=1.43.0,<1.44.0)", "mypy-boto3-codecatalyst (>=1.43.0,<1.44.0)", "mypy-boto3-codecommit (>=1.43.0,<1.44.0)", "mypy-boto3-codeconnections (>=1.43.0,<1.44.0)", "mypy-boto3-codedeploy (>=1.43.0,<1.44.0)", "mypy-boto3-codeguru-reviewer (>=1.43.0,<1.44.0)", "mypy-boto3-codeguru-security (>=1.43.0,<1.44.0)", "mypy-boto3-codeguruprofiler (>=1.43.0,<1.44.0)", "mypy-boto3-codepipeline (>=1.43.0,<1.44.0)", "mypy-boto3-codestar-connections (>=1.43.0,<1.44.0)", "mypy-boto3-codestar-notifications (>=1.43.0,<1.44.0)", "mypy-boto3-cognito-identity (>=1.43.0,<1.44.0)", "mypy-boto3-cognito-idp (>=1.43.0,<1.44.0)", "mypy-boto3-cognito-sync (>=1.43.0,<1.44.0)", "mypy-boto3-comprehend (>=1.43.0,<1.44.0)", "mypy-boto3-comprehendmedical (>=1.43.0,<1.44.0)", "mypy-boto3-compute-optimizer (>=1.43.0,<1.44.0)", "mypy-boto3-compute-optimizer-automation (>=1.43.0,<1.44.0)", "mypy-boto3-config (>=1.43.0,<1.44.0)", "mypy-boto3-connect (>=1.43.0,<1.44.0)", "mypy-boto3-connect-contact-lens (>=1.43.0,<1.44.0)", "mypy-boto3-connectcampaigns (>=1.43.0,<1.44.0)", "mypy-boto3-connectcampaignsv2 (>=1.43.0,<1.44.0)", "mypy-boto3-connectcases (>=1.43.0,<1.44.0)", "mypy-boto3-connecthealth (>=1.43.0,<1.44.0)", "mypy-boto3-connectparticipant (>=1.43.0,<1.44.0)", "mypy-boto3-controlcatalog (>=1.43.0,<1.44.0)", "mypy-boto3-controltower (>=1.43.0,<1.44.0)", "mypy-boto3-cost-optimization-hub (>=1.43.0,<1.44.0)", "mypy-boto3-cur (>=1.43.0,<1.44.0)", "mypy-boto3-customer-profiles (>=1.43.0,<1.44.0)", "mypy-boto3-databrew (>=1.43.0,<1.44.0)", "mypy-boto3-dataexchange (>=1.43.0,<1.44.0)", "mypy-boto3-datapipeline (>=1.43.0,<1.44.0)", "mypy-boto3-datasync (>=1.43.0,<1.44.0)", "mypy-boto3-datazone (>=1.43.0,<1.44.0)", "mypy-boto3-dax (>=1.43.0,<1.44.0)", "mypy-boto3-deadline (>=1.43.0,<1.44.0)", "mypy-boto3-detective (>=1.43.0,<1.44.0)", "mypy-boto3-devicefarm (>=1.43.0,<1.44.0)", "mypy-boto3-devops-agent (>=1.43.0,<1.44.0)", "mypy-boto3-devops-guru (>=1.43.0,<1.44.0)", "mypy-boto3-directconnect (>=1.43.0,<1.44.0)", "mypy-boto3-discovery (>=1.43.0,<1.44.0)", "mypy-boto3-dlm (>=1.43.0,<1.44.0)", "mypy-boto3-dms (>=1.43.0,<1.44.0)", "mypy-boto3-docdb (>=1.43.0,<1.44.0)", "mypy-boto3-docdb-elastic (>=1.43.0,<1.44.0)", "mypy-boto3-drs (>=1.43.0,<1.44.0)", "mypy-boto3-ds (>=1.43.0,<1.44.0)", "mypy-boto3-ds-data (>=1.43.0,<1.44.0)", "mypy-boto3-dsql (>=1.43.0,<1.44.0)", "mypy-boto3-dynamodb (>=1.43.0,<1.44.0)", "mypy-boto3-dynamodbstreams (>=1.43.0,<1.44.0)", "mypy-boto3-ebs (>=1.43.0,<1.44.0)", "mypy-boto3-ec2 (>=1.43.0,<1.44.0)", "mypy-boto3-ec2-instance-connect (>=1.43.0,<1.44.0)", "mypy-boto3-ecr (>=1.43.0,<1.44.0)", "mypy-boto3-ecr-public (>=1.43.0,<1.44.0)", "mypy-boto3-ecs (>=1.43.0,<1.44.0)", "mypy-boto3-efs (>=1.43.0,<1.44.0)", "mypy-boto3-eks (>=1.43.0,<1.44.0)", "mypy-boto3-eks-auth (>=1.43.0,<1.44.0)", "mypy-boto3-elasticache (>=1.43.0,<1.44.0)", "mypy-boto3-elasticbeanstalk (>=1.43.0,<1.44.0)", "mypy-boto3-elb (>=1.43.0,<1.44.0)", "mypy-boto3-elbv2 (>=1.43.0,<1.44.0)", "mypy-boto3-elementalinference (>=1.43.0,<1.44.0)", "mypy-boto3-emr (>=1.43.0,<1.44.0)", "mypy-boto3-emr-containers (>=1.43.0,<1.44.0)", "mypy-boto3-emr-serverless (>=1.43.0,<1.44.0)", "mypy-boto3-entityresolution (>=1.43.0,<1.44.0)", "mypy-boto3-es (>=1.43.0,<1.44.0)", "mypy-boto3-events (>=1.43.0,<1.44.0)", "mypy-boto3-evs (>=1.43.0,<1.44.0)", "mypy-boto3-finspace (>=1.43.0,<1.44.0)", "mypy-boto3-finspace-data (>=1.43.0,<1.44.0)", "mypy-boto3-firehose (>=1.43.0,<1.44.0)", "mypy-boto3-fis (>=1.43.0,<1.44.0)", "mypy-boto3-fms (>=1.43.0,<1.44.0)", "mypy-boto3-forecast (>=1.43.0,<1.44.0)", "mypy-boto3-forecastquery (>=1.43.0,<1.44.0)", "mypy-boto3-frauddetector (>=1.43.0,<1.44.0)", "mypy-boto3-freetier (>=1.43.0,<1.44.0)", "mypy-boto3-fsx (>=1.43.0,<1.44.0)", "mypy-boto3-gamelift (>=1.43.0,<1.44.0)", "mypy-boto3-gameliftstreams (>=1.43.0,<1.44.0)", "mypy-boto3-geo-maps (>=1.43.0,<1.44.0)", "mypy-boto3-geo-places (>=1.43.0,<1.44.0)", "mypy-boto3-geo-routes (>=1.43.0,<1.44.0)", "mypy-boto3-glacier (>=1.43.0,<1.44.0)", "mypy-boto3-globalaccelerator (>=1.43.0,<1.44.0)", "mypy-boto3-glue (>=1.43.0,<1.44.0)", "mypy-boto3-grafana (>=1.43.0,<1.44.0)", "mypy-boto3-greengrass (>=1.43.0,<1.44.0)", "mypy-boto3-greengrassv2 (>=1.43.0,<1.44.0)", "mypy-boto3-groundstation (>=1.43.0,<1.44.0)", "mypy-boto3-guardduty (>=1.43.0,<1.44.0)", "mypy-boto3-health (>=1.43.0,<1.44.0)", "mypy-boto3-healthlake (>=1.43.0,<1.44.0)", "mypy-boto3-iam (>=1.43.0,<1.44.0)", "mypy-boto3-identitystore (>=1.43.0,<1.44.0)", "mypy-boto3-imagebuilder (>=1.43.0,<1.44.0)", "mypy-boto3-importexport (>=1.43.0,<1.44.0)", "mypy-boto3-inspector (>=1.43.0,<1.44.0)", "mypy-boto3-inspector-scan (>=1.43.0,<1.44.0)", "mypy-boto3-inspector2 (>=1.43.0,<1.44.0)", "mypy-boto3-interconnect (>=1.43.0,<1.44.0)", "mypy-boto3-internetmonitor (>=1.43.0,<1.44.0)", "mypy-boto3-invoicing (>=1.43.0,<1.44.0)", "mypy-boto3-iot (>=1.43.0,<1.44.0)", "mypy-boto3-iot-data (>=1.43.0,<1.44.0)", "mypy-boto3-iot-jobs-data (>=1.43.0,<1.44.0)", "mypy-boto3-iot-managed-integrations (>=1.43.0,<1.44.0)", "mypy-boto3-iotdeviceadvisor (>=1.43.0,<1.44.0)", "mypy-boto3-iotevents (>=1.43.0,<1.44.0)", "mypy-boto3-iotevents-data (>=1.43.0,<1.44.0)", "mypy-boto3-iotfleetwise (>=1.43.0,<1.44.0)", "mypy-boto3-iotsecuretunneling (>=1.43.0,<1.44.0)", "mypy-boto3-iotsitewise (>=1.43.0,<1.44.0)", "mypy-boto3-iotthingsgraph (>=1.43.0,<1.44.0)", "mypy-boto3-iottwinmaker (>=1.43.0,<1.44.0)", "mypy-boto3-iotwireless (>=1.43.0,<1.44.0)", "mypy-boto3-ivs (>=1.43.0,<1.44.0)", "mypy-boto3-ivs-realtime (>=1.43.0,<1.44.0)", "mypy-boto3-ivschat (>=1.43.0,<1.44.0)", "mypy-boto3-kafka (>=1.43.0,<1.44.0)", "mypy-boto3-kafkaconnect (>=1.43.0,<1.44.0)", "mypy-boto3-kendra (>=1.43.0,<1.44.0)", "mypy-boto3-kendra-ranking (>=1.43.0,<1.44.0)", "mypy-boto3-keyspaces (>=1.43.0,<1.44.0)", "mypy-boto3-keyspacesstreams (>=1.43.0,<1.44.0)", "mypy-boto3-kinesis (>=1.43.0,<1.44.0)", "mypy-boto3-kinesis-video-archived-media (>=1.43.0,<1.44.0)", "mypy-boto3-kinesis-video-media (>=1.43.0,<1.44.0)", "mypy-boto3-kinesis-video-signaling (>=1.43.0,<1.44.0)", "mypy-boto3-kinesis-video-webrtc-storage (>=1.43.0,<1.44.0)", "mypy-boto3-kinesisanalytics (>=1.43.0,<1.44.0)", "mypy-boto3-kinesisanalyticsv2 (>=1.43.0,<1.44.0)", "mypy-boto3-kinesisvideo (>=1.43.0,<1.44.0)", "mypy-boto3-kms (>=1.43.0,<1.44.0)", "mypy-boto3-lakeformation (>=1.43.0,<1.44.0)", "mypy-boto3-lambda (>=1.43.0,<1.44.0)", "mypy-boto3-launch-wizard (>=1.43.0,<1.44.0)", "mypy-boto3-lex-models (>=1.43.0,<1.44.0)", "mypy-boto3-lex-runtime (>=1.43.0,<1.44.0)", "mypy-boto3-lexv2-models (>=1.43.0,<1.44.0)", "mypy-boto3-lexv2-runtime (>=1.43.0,<1.44.0)", "mypy-boto3-license-manager (>=1.43.0,<1.44.0)", "mypy-boto3-license-manager-linux-subscriptions (>=1.43.0,<1.44.0)", "mypy-boto3-license-manager-user-subscriptions (>=1.43.0,<1.44.0)", "mypy-boto3-lightsail (>=1.43.0,<1.44.0)", "mypy-boto3-location (>=1.43.0,<1.44.0)", "mypy-boto3-logs (>=1.43.0,<1.44.0)", "mypy-boto3-lookoutequipment (>=1.43.0,<1.44.0)", "mypy-boto3-m2 (>=1.43.0,<1.44.0)", "mypy-boto3-machinelearning (>=1.43.0,<1.44.0)", "mypy-boto3-macie2 (>=1.43.0,<1.44.0)", "mypy-boto3-mailmanager (>=1.43.0,<1.44.0)", "mypy-boto3-managedblockchain (>=1.43.0,<1.44.0)", "mypy-boto3-managedblockchain-query (>=1.43.0,<1.44.0)", "mypy-boto3-marketplace-agreement (>=1.43.0,<1.44.0)", "mypy-boto3-marketplace-catalog (>=1.43.0,<1.44.0)", "mypy-boto3-marketplace-deployment (>=1.43.0,<1.44.0)", "mypy-boto3-marketplace-discovery (>=1.43.0,<1.44.0)", "mypy-boto3-marketplace-entitlement (>=1.43.0,<1.44.0)", "mypy-boto3-marketplace-reporting (>=1.43.0,<1.44.0)", "mypy-boto3-marketplacecommerceanalytics (>=1.43.0,<1.44.0)", "mypy-boto3-mediaconnect (>=1.43.0,<1.44.0)", "mypy-boto3-mediaconvert (>=1.43.0,<1.44.0)", "mypy-boto3-medialive (>=1.43.0,<1.44.0)", "mypy-boto3-mediapackage (>=1.43.0,<1.44.0)", "mypy-boto3-mediapackage-vod (>=1.43.0,<1.44.0)", "mypy-boto3-mediapackagev2 (>=1.43.0,<1.44.0)", "mypy-boto3-mediastore (>=1.43.0,<1.44.0)", "mypy-boto3-mediastore-data (>=1.43.0,<1.44.0)", "mypy-boto3-mediatailor (>=1.43.0,<1.44.0)", "mypy-boto3-medical-imaging (>=1.43.0,<1.44.0)", "mypy-boto3-memorydb (>=1.43.0,<1.44.0)", "mypy-boto3-meteringmarketplace (>=1.43.0,<1.44.0)", "mypy-boto3-mgh (>=1.43.0,<1.44.0)", "mypy-boto3-mgn (>=1.43.0,<1.44.0)", "mypy-boto3-migration-hub-refactor-spaces (>=1.43.0,<1.44.0)", "mypy-boto3-migrationhub-config (>=1.43.0,<1.44.0)", "mypy-boto3-migrationhuborchestrator (>=1.43.0,<1.44.0)", "mypy-boto3-migrationhubstrategy (>=1.43.0,<1.44.0)", "mypy-boto3-mpa (>=1.43.0,<1.44.0)", "mypy-boto3-mq (>=1.43.0,<1.44.0)", "mypy-boto3-mturk (>=1.43.0,<1.44.0)", "mypy-boto3-mwaa (>=1.43.0,<1.44.0)", "mypy-boto3-mwaa-serverless (>=1.43.0,<1.44.0)", "mypy-boto3-neptune (>=1.43.0,<1.44.0)", "mypy-boto3-neptune-graph (>=1.43.0,<1.44.0)", "mypy-boto3-neptunedata (>=1.43.0,<1.44.0)", "mypy-boto3-network-firewall (>=1.43.0,<1.44.0)", "mypy-boto3-networkflowmonitor (>=1.43.0,<1.44.0)", "mypy-boto3-networkmanager (>=1.43.0,<1.44.0)", "mypy-boto3-networkmonitor (>=1.43.0,<1.44.0)", "mypy-boto3-notifications (>=1.43.0,<1.44.0)", "mypy-boto3-notificationscontacts (>=1.43.0,<1.44.0)", "mypy-boto3-nova-act (>=1.43.0,<1.44.0)", "mypy-boto3-oam (>=1.43.0,<1.44.0)", "mypy-boto3-observabilityadmin (>=1.43.0,<1.44.0)", "mypy-boto3-odb (>=1.43.0,<1.44.0)", "mypy-boto3-omics (>=1.43.0,<1.44.0)", "mypy-boto3-opensearch (>=1.43.0,<1.44.0)", "mypy-boto3-opensearchserverless (>=1.43.0,<1.44.0)", "mypy-boto3-organizations (>=1.43.0,<1.44.0)", "mypy-boto3-osis (>=1.43.0,<1.44.0)", "mypy-boto3-outposts (>=1.43.0,<1.44.0)", "mypy-boto3-panorama (>=1.43.0,<1.44.0)", "mypy-boto3-partnercentral-account (>=1.43.0,<1.44.0)", "mypy-boto3-partnercentral-benefits (>=1.43.0,<1.44.0)", "mypy-boto3-partnercentral-channel (>=1.43.0,<1.44.0)", "mypy-boto3-partnercentral-selling (>=1.43.0,<1.44.0)", "mypy-boto3-payment-cryptography (>=1.43.0,<1.44.0)", "mypy-boto3-payment-cryptography-data (>=1.43.0,<1.44.0)", "mypy-boto3-pca-connector-ad (>=1.43.0,<1.44.0)", "mypy-boto3-pca-connector-scep (>=1.43.0,<1.44.0)", "mypy-boto3-pcs (>=1.43.0,<1.44.0)", "mypy-boto3-personalize (>=1.43.0,<1.44.0)", "mypy-boto3-personalize-events (>=1.43.0,<1.44.0)", "mypy-boto3-personalize-runtime (>=1.43.0,<1.44.0)", "mypy-boto3-pi (>=1.43.0,<1.44.0)", "mypy-boto3-pinpoint (>=1.43.0,<1.44.0)", "mypy-boto3-pinpoint-email (>=1.43.0,<1.44.0)", "mypy-boto3-pinpoint-sms-voice (>=1.43.0,<1.44.0)", "mypy-boto3-pinpoint-sms-voice-v2 (>=1.43.0,<1.44.0)", "mypy-boto3-pipes (>=1.43.0,<1.44.0)", "mypy-boto3-polly (>=1.43.0,<1.44.0)", "mypy-boto3-pricing (>=1.43.0,<1.44.0)", "mypy-boto3-proton (>=1.43.0,<1.44.0)", "mypy-boto3-qapps (>=1.43.0,<1.44.0)", "mypy-boto3-qbusiness (>=1.43.0,<1.44.0)", "mypy-boto3-qconnect (>=1.43.0,<1.44.0)", "mypy-boto3-quicksight (>=1.43.0,<1.44.0)", "mypy-boto3-ram (>=1.43.0,<1.44.0)", "mypy-boto3-rbin (>=1.43.0,<1.44.0)", "mypy-boto3-rds (>=1.43.0,<1.44.0)", "mypy-boto3-rds-data (>=1.43.0,<1.44.0)", "mypy-boto3-redshift (>=1.43.0,<1.44.0)", "mypy-boto3-redshift-data (>=1.43.0,<1.44.0)", "mypy-boto3-redshift-serverless (>=1.43.0,<1.44.0)", "mypy-boto3-rekognition (>=1.43.0,<1.44.0)", "mypy-boto3-repostspace (>=1.43.0,<1.44.0)", "mypy-boto3-resiliencehub (>=1.43.0,<1.44.0)", "mypy-boto3-resiliencehubv2 (>=1.43.0,<1.44.0)", "mypy-boto3-resource-explorer-2 (>=1.43.0,<1.44.0)", "mypy-boto3-resource-groups (>=1.43.0,<1.44.0)", "mypy-boto3-resourcegroupstaggingapi (>=1.43.0,<1.44.0)", "mypy-boto3-rolesanywhere (>=1.43.0,<1.44.0)", "mypy-boto3-route53 (>=1.43.0,<1.44.0)", "mypy-boto3-route53-recovery-cluster (>=1.43.0,<1.44.0)", "mypy-boto3-route53-recovery-control-config (>=1.43.0,<1.44.0)", "mypy-boto3-route53-recovery-readiness (>=1.43.0,<1.44.0)", "mypy-boto3-route53domains (>=1.43.0,<1.44.0)", "mypy-boto3-route53globalresolver (>=1.43.0,<1.44.0)", "mypy-boto3-route53profiles (>=1.43.0,<1.44.0)", "mypy-boto3-route53resolver (>=1.43.0,<1.44.0)", "mypy-boto3-rtbfabric (>=1.43.0,<1.44.0)", "mypy-boto3-rum (>=1.43.0,<1.44.0)", "mypy-boto3-s3 (>=1.43.0,<1.44.0)", "mypy-boto3-s3control (>=1.43.0,<1.44.0)", "mypy-boto3-s3files (>=1.43.0,<1.44.0)", "mypy-boto3-s3outposts (>=1.43.0,<1.44.0)", "mypy-boto3-s3tables (>=1.43.0,<1.44.0)", "mypy-boto3-s3vectors (>=1.43.0,<1.44.0)", "mypy-boto3-sagemaker (>=1.43.0,<1.44.0)", "mypy-boto3-sagemaker-a2i-runtime (>=1.43.0,<1.44.0)", "mypy-boto3-sagemaker-edge (>=1.43.0,<1.44.0)", "mypy-boto3-sagemaker-featurestore-runtime (>=1.43.0,<1.44.0)", "mypy-boto3-sagemaker-geospatial (>=1.43.0,<1.44.0)", "mypy-boto3-sagemaker-metrics (>=1.43.0,<1.44.0)", "mypy-boto3-sagemaker-runtime (>=1.43.0,<1.44.0)", "mypy-boto3-sagemakerjobruntime (>=1.43.0,<1.44.0)", "mypy-boto3-savingsplans (>=1.43.0,<1.44.0)", "mypy-boto3-scheduler (>=1.43.0,<1.44.0)", "mypy-boto3-schemas (>=1.43.0,<1.44.0)", "mypy-boto3-sdb (>=1.43.0,<1.44.0)", "mypy-boto3-secretsmanager (>=1.43.0,<1.44.0)", "mypy-boto3-security-ir (>=1.43.0,<1.44.0)", "mypy-boto3-securityagent (>=1.43.0,<1.44.0)", "mypy-boto3-securityhub (>=1.43.0,<1.44.0)", "mypy-boto3-securitylake (>=1.43.0,<1.44.0)", "mypy-boto3-serverlessrepo (>=1.43.0,<1.44.0)", "mypy-boto3-service-quotas (>=1.43.0,<1.44.0)", "mypy-boto3-servicecatalog (>=1.43.0,<1.44.0)", "mypy-boto3-servicecatalog-appregistry (>=1.43.0,<1.44.0)", "mypy-boto3-servicediscovery (>=1.43.0,<1.44.0)", "mypy-boto3-ses (>=1.43.0,<1.44.0)", "mypy-boto3-sesv2 (>=1.43.0,<1.44.0)", "mypy-boto3-shield (>=1.43.0,<1.44.0)", "mypy-boto3-signer (>=1.43.0,<1.44.0)", "mypy-boto3-signer-data (>=1.43.0,<1.44.0)", "mypy-boto3-signin (>=1.43.0,<1.44.0)", "mypy-boto3-simpledbv2 (>=1.43.0,<1.44.0)", "mypy-boto3-simspaceweaver (>=1.43.0,<1.44.0)", "mypy-boto3-snow-device-management (>=1.43.0,<1.44.0)", "mypy-boto3-snowball (>=1.43.0,<1.44.0)", "mypy-boto3-sns (>=1.43.0,<1.44.0)", "mypy-boto3-socialmessaging (>=1.43.0,<1.44.0)", "mypy-boto3-sqs (>=1.43.0,<1.44.0)", "mypy-boto3-ssm (>=1.43.0,<1.44.0)", "mypy-boto3-ssm-contacts (>=1.43.0,<1.44.0)", "mypy-boto3-ssm-guiconnect (>=1.43.0,<1.44.0)", "mypy-boto3-ssm-incidents (>=1.43.0,<1.44.0)", "mypy-boto3-ssm-quicksetup (>=1.43.0,<1.44.0)", "mypy-boto3-ssm-sap (>=1.43.0,<1.44.0)", "mypy-boto3-sso (>=1.43.0,<1.44.0)", "mypy-boto3-sso-admin (>=1.43.0,<1.44.0)", "mypy-boto3-sso-oidc (>=1.43.0,<1.44.0)", "mypy-boto3-stepfunctions (>=1.43.0,<1.44.0)", "mypy-boto3-storagegateway (>=1.43.0,<1.44.0)", "mypy-boto3-sts (>=1.43.0,<1.44.0)", "mypy-boto3-supplychain (>=1.43.0,<1.44.0)", "mypy-boto3-support (>=1.43.0,<1.44.0)", "mypy-boto3-support-app (>=1.43.0,<1.44.0)", "mypy-boto3-sustainability (>=1.43.0,<1.44.0)", "mypy-boto3-swf (>=1.43.0,<1.44.0)", "mypy-boto3-synthetics (>=1.43.0,<1.44.0)", "mypy-boto3-taxsettings (>=1.43.0,<1.44.0)", "mypy-boto3-textract (>=1.43.0,<1.44.0)", "mypy-boto3-timestream-influxdb (>=1.43.0,<1.44.0)", "mypy-boto3-timestream-query (>=1.43.0,<1.44.0)", "mypy-boto3-timestream-write (>=1.43.0,<1.44.0)", "mypy-boto3-tnb (>=1.43.0,<1.44.0)", "mypy-boto3-transcribe (>=1.43.0,<1.44.0)", "mypy-boto3-transfer (>=1.43.0,<1.44.0)", "mypy-boto3-translate (>=1.43.0,<1.44.0)", "mypy-boto3-trustedadvisor (>=1.43.0,<1.44.0)", "mypy-boto3-uxc (>=1.43.0,<1.44.0)", "mypy-boto3-verifiedpermissions (>=1.43.0,<1.44.0)", "mypy-boto3-voice-id (>=1.43.0,<1.44.0)", "mypy-boto3-vpc-lattice (>=1.43.0,<1.44.0)", "mypy-boto3-waf (>=1.43.0,<1.44.0)", "mypy-boto3-waf-regional (>=1.43.0,<1.44.0)", "mypy-boto3-wafv2 (>=1.43.0,<1.44.0)", "mypy-boto3-wellarchitected (>=1.43.0,<1.44.0)", "mypy-boto3-wickr (>=1.43.0,<1.44.0)", "mypy-boto3-wisdom (>=1.43.0,<1.44.0)", "mypy-boto3-workdocs (>=1.43.0,<1.44.0)", "mypy-boto3-workmail (>=1.43.0,<1.44.0)", "mypy-boto3-workmailmessageflow (>=1.43.0,<1.44.0)", "mypy-boto3-workspaces (>=1.43.0,<1.44.0)", "mypy-boto3-workspaces-instances (>=1.43.0,<1.44.0)", "mypy-boto3-workspaces-thin-client (>=1.43.0,<1.44.0)", "mypy-boto3-workspaces-web (>=1.43.0,<1.44.0)", "mypy-boto3-xray (>=1.43.0,<1.44.0)"] +all = ["mypy-boto3-accessanalyzer (>=1.43.0,<1.44.0)", "mypy-boto3-account (>=1.43.0,<1.44.0)", "mypy-boto3-account-access (>=1.43.0,<1.44.0)", "mypy-boto3-acm (>=1.43.0,<1.44.0)", "mypy-boto3-acm-pca (>=1.43.0,<1.44.0)", "mypy-boto3-agent-registry (>=1.43.0,<1.44.0)", "mypy-boto3-agent-registry-control (>=1.43.0,<1.44.0)", "mypy-boto3-aiops (>=1.43.0,<1.44.0)", "mypy-boto3-amp (>=1.43.0,<1.44.0)", "mypy-boto3-amplify (>=1.43.0,<1.44.0)", "mypy-boto3-amplifybackend (>=1.43.0,<1.44.0)", "mypy-boto3-amplifyuibuilder (>=1.43.0,<1.44.0)", "mypy-boto3-apigateway (>=1.43.0,<1.44.0)", "mypy-boto3-apigatewaymanagementapi (>=1.43.0,<1.44.0)", "mypy-boto3-apigatewayv2 (>=1.43.0,<1.44.0)", "mypy-boto3-appconfig (>=1.43.0,<1.44.0)", "mypy-boto3-appconfigdata (>=1.43.0,<1.44.0)", "mypy-boto3-appfabric (>=1.43.0,<1.44.0)", "mypy-boto3-appflow (>=1.43.0,<1.44.0)", "mypy-boto3-appintegrations (>=1.43.0,<1.44.0)", "mypy-boto3-application-autoscaling (>=1.43.0,<1.44.0)", "mypy-boto3-application-insights (>=1.43.0,<1.44.0)", "mypy-boto3-application-signals (>=1.43.0,<1.44.0)", "mypy-boto3-applicationcostprofiler (>=1.43.0,<1.44.0)", "mypy-boto3-appmesh (>=1.43.0,<1.44.0)", "mypy-boto3-apprunner (>=1.43.0,<1.44.0)", "mypy-boto3-appstream (>=1.43.0,<1.44.0)", "mypy-boto3-appsync (>=1.43.0,<1.44.0)", "mypy-boto3-arc-region-switch (>=1.43.0,<1.44.0)", "mypy-boto3-arc-zonal-shift (>=1.43.0,<1.44.0)", "mypy-boto3-artifact (>=1.43.0,<1.44.0)", "mypy-boto3-athena (>=1.43.0,<1.44.0)", "mypy-boto3-auditmanager (>=1.43.0,<1.44.0)", "mypy-boto3-autoscaling (>=1.43.0,<1.44.0)", "mypy-boto3-autoscaling-plans (>=1.43.0,<1.44.0)", "mypy-boto3-b2bi (>=1.43.0,<1.44.0)", "mypy-boto3-backup (>=1.43.0,<1.44.0)", "mypy-boto3-backup-gateway (>=1.43.0,<1.44.0)", "mypy-boto3-backupsearch (>=1.43.0,<1.44.0)", "mypy-boto3-batch (>=1.43.0,<1.44.0)", "mypy-boto3-bcm-dashboards (>=1.43.0,<1.44.0)", "mypy-boto3-bcm-data-exports (>=1.43.0,<1.44.0)", "mypy-boto3-bcm-pricing-calculator (>=1.43.0,<1.44.0)", "mypy-boto3-bcm-recommended-actions (>=1.43.0,<1.44.0)", "mypy-boto3-bedrock (>=1.43.0,<1.44.0)", "mypy-boto3-bedrock-agent (>=1.43.0,<1.44.0)", "mypy-boto3-bedrock-agent-runtime (>=1.43.0,<1.44.0)", "mypy-boto3-bedrock-agentcore (>=1.43.0,<1.44.0)", "mypy-boto3-bedrock-agentcore-control (>=1.43.0,<1.44.0)", "mypy-boto3-bedrock-data-automation (>=1.43.0,<1.44.0)", "mypy-boto3-bedrock-data-automation-runtime (>=1.43.0,<1.44.0)", "mypy-boto3-bedrock-runtime (>=1.43.0,<1.44.0)", "mypy-boto3-billing (>=1.43.0,<1.44.0)", "mypy-boto3-billingconductor (>=1.43.0,<1.44.0)", "mypy-boto3-braket (>=1.43.0,<1.44.0)", "mypy-boto3-budgets (>=1.43.0,<1.44.0)", "mypy-boto3-ce (>=1.43.0,<1.44.0)", "mypy-boto3-chatbot (>=1.43.0,<1.44.0)", "mypy-boto3-chime (>=1.43.0,<1.44.0)", "mypy-boto3-chime-sdk-identity (>=1.43.0,<1.44.0)", "mypy-boto3-chime-sdk-media-pipelines (>=1.43.0,<1.44.0)", "mypy-boto3-chime-sdk-meetings (>=1.43.0,<1.44.0)", "mypy-boto3-chime-sdk-messaging (>=1.43.0,<1.44.0)", "mypy-boto3-chime-sdk-voice (>=1.43.0,<1.44.0)", "mypy-boto3-cleanrooms (>=1.43.0,<1.44.0)", "mypy-boto3-cleanroomsml (>=1.43.0,<1.44.0)", "mypy-boto3-cloud9 (>=1.43.0,<1.44.0)", "mypy-boto3-cloudcontrol (>=1.43.0,<1.44.0)", "mypy-boto3-clouddirectory (>=1.43.0,<1.44.0)", "mypy-boto3-cloudformation (>=1.43.0,<1.44.0)", "mypy-boto3-cloudfront (>=1.43.0,<1.44.0)", "mypy-boto3-cloudfront-keyvaluestore (>=1.43.0,<1.44.0)", "mypy-boto3-cloudhsm (>=1.43.0,<1.44.0)", "mypy-boto3-cloudhsmv2 (>=1.43.0,<1.44.0)", "mypy-boto3-cloudsearch (>=1.43.0,<1.44.0)", "mypy-boto3-cloudsearchdomain (>=1.43.0,<1.44.0)", "mypy-boto3-cloudtrail (>=1.43.0,<1.44.0)", "mypy-boto3-cloudtrail-data (>=1.43.0,<1.44.0)", "mypy-boto3-cloudwatch (>=1.43.0,<1.44.0)", "mypy-boto3-cloudwatchomni (>=1.43.0,<1.44.0)", "mypy-boto3-codeartifact (>=1.43.0,<1.44.0)", "mypy-boto3-codebuild (>=1.43.0,<1.44.0)", "mypy-boto3-codecatalyst (>=1.43.0,<1.44.0)", "mypy-boto3-codecommit (>=1.43.0,<1.44.0)", "mypy-boto3-codeconnections (>=1.43.0,<1.44.0)", "mypy-boto3-codedeploy (>=1.43.0,<1.44.0)", "mypy-boto3-codeguru-reviewer (>=1.43.0,<1.44.0)", "mypy-boto3-codeguru-security (>=1.43.0,<1.44.0)", "mypy-boto3-codeguruprofiler (>=1.43.0,<1.44.0)", "mypy-boto3-codepipeline (>=1.43.0,<1.44.0)", "mypy-boto3-codestar-connections (>=1.43.0,<1.44.0)", "mypy-boto3-codestar-notifications (>=1.43.0,<1.44.0)", "mypy-boto3-cognito-identity (>=1.43.0,<1.44.0)", "mypy-boto3-cognito-idp (>=1.43.0,<1.44.0)", "mypy-boto3-cognito-sync (>=1.43.0,<1.44.0)", "mypy-boto3-comprehend (>=1.43.0,<1.44.0)", "mypy-boto3-comprehendmedical (>=1.43.0,<1.44.0)", "mypy-boto3-compute-optimizer (>=1.43.0,<1.44.0)", "mypy-boto3-compute-optimizer-automation (>=1.43.0,<1.44.0)", "mypy-boto3-config (>=1.43.0,<1.44.0)", "mypy-boto3-connect (>=1.43.0,<1.44.0)", "mypy-boto3-connect-contact-lens (>=1.43.0,<1.44.0)", "mypy-boto3-connectcampaigns (>=1.43.0,<1.44.0)", "mypy-boto3-connectcampaignsv2 (>=1.43.0,<1.44.0)", "mypy-boto3-connectcases (>=1.43.0,<1.44.0)", "mypy-boto3-connecthealth (>=1.43.0,<1.44.0)", "mypy-boto3-connectparticipant (>=1.43.0,<1.44.0)", "mypy-boto3-controlcatalog (>=1.43.0,<1.44.0)", "mypy-boto3-controltower (>=1.43.0,<1.44.0)", "mypy-boto3-cost-optimization-hub (>=1.43.0,<1.44.0)", "mypy-boto3-cur (>=1.43.0,<1.44.0)", "mypy-boto3-customer-profiles (>=1.43.0,<1.44.0)", "mypy-boto3-databrew (>=1.43.0,<1.44.0)", "mypy-boto3-dataexchange (>=1.43.0,<1.44.0)", "mypy-boto3-datapipeline (>=1.43.0,<1.44.0)", "mypy-boto3-datasync (>=1.43.0,<1.44.0)", "mypy-boto3-datazone (>=1.43.0,<1.44.0)", "mypy-boto3-dax (>=1.43.0,<1.44.0)", "mypy-boto3-deadline (>=1.43.0,<1.44.0)", "mypy-boto3-detective (>=1.43.0,<1.44.0)", "mypy-boto3-devicefarm (>=1.43.0,<1.44.0)", "mypy-boto3-devops-agent (>=1.43.0,<1.44.0)", "mypy-boto3-devops-guru (>=1.43.0,<1.44.0)", "mypy-boto3-directconnect (>=1.43.0,<1.44.0)", "mypy-boto3-discovery (>=1.43.0,<1.44.0)", "mypy-boto3-dlm (>=1.43.0,<1.44.0)", "mypy-boto3-dms (>=1.43.0,<1.44.0)", "mypy-boto3-docdb (>=1.43.0,<1.44.0)", "mypy-boto3-docdb-elastic (>=1.43.0,<1.44.0)", "mypy-boto3-drs (>=1.43.0,<1.44.0)", "mypy-boto3-ds (>=1.43.0,<1.44.0)", "mypy-boto3-ds-data (>=1.43.0,<1.44.0)", "mypy-boto3-dsql (>=1.43.0,<1.44.0)", "mypy-boto3-dynamodb (>=1.43.0,<1.44.0)", "mypy-boto3-dynamodbstreams (>=1.43.0,<1.44.0)", "mypy-boto3-ebs (>=1.43.0,<1.44.0)", "mypy-boto3-ec2 (>=1.43.0,<1.44.0)", "mypy-boto3-ec2-instance-connect (>=1.43.0,<1.44.0)", "mypy-boto3-ecr (>=1.43.0,<1.44.0)", "mypy-boto3-ecr-public (>=1.43.0,<1.44.0)", "mypy-boto3-ecs (>=1.43.0,<1.44.0)", "mypy-boto3-efs (>=1.43.0,<1.44.0)", "mypy-boto3-eks (>=1.43.0,<1.44.0)", "mypy-boto3-eks-auth (>=1.43.0,<1.44.0)", "mypy-boto3-elasticache (>=1.43.0,<1.44.0)", "mypy-boto3-elasticbeanstalk (>=1.43.0,<1.44.0)", "mypy-boto3-elb (>=1.43.0,<1.44.0)", "mypy-boto3-elbv2 (>=1.43.0,<1.44.0)", "mypy-boto3-elementalinference (>=1.43.0,<1.44.0)", "mypy-boto3-emr (>=1.43.0,<1.44.0)", "mypy-boto3-emr-containers (>=1.43.0,<1.44.0)", "mypy-boto3-emr-serverless (>=1.43.0,<1.44.0)", "mypy-boto3-endusermessaging (>=1.43.0,<1.44.0)", "mypy-boto3-entityresolution (>=1.43.0,<1.44.0)", "mypy-boto3-es (>=1.43.0,<1.44.0)", "mypy-boto3-eventbridgev2 (>=1.43.0,<1.44.0)", "mypy-boto3-events (>=1.43.0,<1.44.0)", "mypy-boto3-evs (>=1.43.0,<1.44.0)", "mypy-boto3-finspace (>=1.43.0,<1.44.0)", "mypy-boto3-finspace-data (>=1.43.0,<1.44.0)", "mypy-boto3-firehose (>=1.43.0,<1.44.0)", "mypy-boto3-fis (>=1.43.0,<1.44.0)", "mypy-boto3-fms (>=1.43.0,<1.44.0)", "mypy-boto3-forecast (>=1.43.0,<1.44.0)", "mypy-boto3-forecastquery (>=1.43.0,<1.44.0)", "mypy-boto3-frauddetector (>=1.43.0,<1.44.0)", "mypy-boto3-freetier (>=1.43.0,<1.44.0)", "mypy-boto3-fsx (>=1.43.0,<1.44.0)", "mypy-boto3-gamelift (>=1.43.0,<1.44.0)", "mypy-boto3-gameliftstreams (>=1.43.0,<1.44.0)", "mypy-boto3-geo-maps (>=1.43.0,<1.44.0)", "mypy-boto3-geo-places (>=1.43.0,<1.44.0)", "mypy-boto3-geo-routes (>=1.43.0,<1.44.0)", "mypy-boto3-glacier (>=1.43.0,<1.44.0)", "mypy-boto3-globalaccelerator (>=1.43.0,<1.44.0)", "mypy-boto3-glue (>=1.43.0,<1.44.0)", "mypy-boto3-grafana (>=1.43.0,<1.44.0)", "mypy-boto3-greengrass (>=1.43.0,<1.44.0)", "mypy-boto3-greengrassv2 (>=1.43.0,<1.44.0)", "mypy-boto3-groundstation (>=1.43.0,<1.44.0)", "mypy-boto3-guardduty (>=1.43.0,<1.44.0)", "mypy-boto3-health (>=1.43.0,<1.44.0)", "mypy-boto3-healthlake (>=1.43.0,<1.44.0)", "mypy-boto3-iam (>=1.43.0,<1.44.0)", "mypy-boto3-iam-toolbox (>=1.43.0,<1.44.0)", "mypy-boto3-identitystore (>=1.43.0,<1.44.0)", "mypy-boto3-imagebuilder (>=1.43.0,<1.44.0)", "mypy-boto3-importexport (>=1.43.0,<1.44.0)", "mypy-boto3-inspector (>=1.43.0,<1.44.0)", "mypy-boto3-inspector-scan (>=1.43.0,<1.44.0)", "mypy-boto3-inspector2 (>=1.43.0,<1.44.0)", "mypy-boto3-interconnect (>=1.43.0,<1.44.0)", "mypy-boto3-internetmonitor (>=1.43.0,<1.44.0)", "mypy-boto3-invoicing (>=1.43.0,<1.44.0)", "mypy-boto3-iot (>=1.43.0,<1.44.0)", "mypy-boto3-iot-data (>=1.43.0,<1.44.0)", "mypy-boto3-iot-jobs-data (>=1.43.0,<1.44.0)", "mypy-boto3-iot-managed-integrations (>=1.43.0,<1.44.0)", "mypy-boto3-iotdeviceadvisor (>=1.43.0,<1.44.0)", "mypy-boto3-iotfleetwise (>=1.43.0,<1.44.0)", "mypy-boto3-iotsecuretunneling (>=1.43.0,<1.44.0)", "mypy-boto3-iotsitewise (>=1.43.0,<1.44.0)", "mypy-boto3-iotthingsgraph (>=1.43.0,<1.44.0)", "mypy-boto3-iottwinmaker (>=1.43.0,<1.44.0)", "mypy-boto3-iotwireless (>=1.43.0,<1.44.0)", "mypy-boto3-ivs (>=1.43.0,<1.44.0)", "mypy-boto3-ivs-realtime (>=1.43.0,<1.44.0)", "mypy-boto3-ivschat (>=1.43.0,<1.44.0)", "mypy-boto3-kafka (>=1.43.0,<1.44.0)", "mypy-boto3-kafkaconnect (>=1.43.0,<1.44.0)", "mypy-boto3-kendra (>=1.43.0,<1.44.0)", "mypy-boto3-kendra-ranking (>=1.43.0,<1.44.0)", "mypy-boto3-keyspaces (>=1.43.0,<1.44.0)", "mypy-boto3-keyspacesstreams (>=1.43.0,<1.44.0)", "mypy-boto3-kinesis (>=1.43.0,<1.44.0)", "mypy-boto3-kinesis-video-archived-media (>=1.43.0,<1.44.0)", "mypy-boto3-kinesis-video-media (>=1.43.0,<1.44.0)", "mypy-boto3-kinesis-video-signaling (>=1.43.0,<1.44.0)", "mypy-boto3-kinesis-video-webrtc-storage (>=1.43.0,<1.44.0)", "mypy-boto3-kinesisanalytics (>=1.43.0,<1.44.0)", "mypy-boto3-kinesisanalyticsv2 (>=1.43.0,<1.44.0)", "mypy-boto3-kinesisvideo (>=1.43.0,<1.44.0)", "mypy-boto3-kms (>=1.43.0,<1.44.0)", "mypy-boto3-lakeformation (>=1.43.0,<1.44.0)", "mypy-boto3-lambda (>=1.43.0,<1.44.0)", "mypy-boto3-lambda-core (>=1.43.0,<1.44.0)", "mypy-boto3-lambda-microvms (>=1.43.0,<1.44.0)", "mypy-boto3-lambda-web (>=1.43.0,<1.44.0)", "mypy-boto3-launch-wizard (>=1.43.0,<1.44.0)", "mypy-boto3-lex-models (>=1.43.0,<1.44.0)", "mypy-boto3-lex-runtime (>=1.43.0,<1.44.0)", "mypy-boto3-lexv2-models (>=1.43.0,<1.44.0)", "mypy-boto3-lexv2-runtime (>=1.43.0,<1.44.0)", "mypy-boto3-license-manager (>=1.43.0,<1.44.0)", "mypy-boto3-license-manager-linux-subscriptions (>=1.43.0,<1.44.0)", "mypy-boto3-license-manager-user-subscriptions (>=1.43.0,<1.44.0)", "mypy-boto3-lightsail (>=1.43.0,<1.44.0)", "mypy-boto3-location (>=1.43.0,<1.44.0)", "mypy-boto3-logs (>=1.43.0,<1.44.0)", "mypy-boto3-lookoutequipment (>=1.43.0,<1.44.0)", "mypy-boto3-m2 (>=1.43.0,<1.44.0)", "mypy-boto3-machinelearning (>=1.43.0,<1.44.0)", "mypy-boto3-macie2 (>=1.43.0,<1.44.0)", "mypy-boto3-mailmanager (>=1.43.0,<1.44.0)", "mypy-boto3-managedblockchain (>=1.43.0,<1.44.0)", "mypy-boto3-managedblockchain-query (>=1.43.0,<1.44.0)", "mypy-boto3-marketplace-agreement (>=1.43.0,<1.44.0)", "mypy-boto3-marketplace-catalog (>=1.43.0,<1.44.0)", "mypy-boto3-marketplace-deployment (>=1.43.0,<1.44.0)", "mypy-boto3-marketplace-discovery (>=1.43.0,<1.44.0)", "mypy-boto3-marketplace-entitlement (>=1.43.0,<1.44.0)", "mypy-boto3-marketplace-reporting (>=1.43.0,<1.44.0)", "mypy-boto3-marketplacecommerceanalytics (>=1.43.0,<1.44.0)", "mypy-boto3-mediaconnect (>=1.43.0,<1.44.0)", "mypy-boto3-mediaconvert (>=1.43.0,<1.44.0)", "mypy-boto3-medialive (>=1.43.0,<1.44.0)", "mypy-boto3-mediapackage (>=1.43.0,<1.44.0)", "mypy-boto3-mediapackage-vod (>=1.43.0,<1.44.0)", "mypy-boto3-mediapackagev2 (>=1.43.0,<1.44.0)", "mypy-boto3-mediastore (>=1.43.0,<1.44.0)", "mypy-boto3-mediastore-data (>=1.43.0,<1.44.0)", "mypy-boto3-mediatailor (>=1.43.0,<1.44.0)", "mypy-boto3-medical-imaging (>=1.43.0,<1.44.0)", "mypy-boto3-memorydb (>=1.43.0,<1.44.0)", "mypy-boto3-meteringmarketplace (>=1.43.0,<1.44.0)", "mypy-boto3-mgh (>=1.43.0,<1.44.0)", "mypy-boto3-mgn (>=1.43.0,<1.44.0)", "mypy-boto3-migration-hub-refactor-spaces (>=1.43.0,<1.44.0)", "mypy-boto3-migrationhub-config (>=1.43.0,<1.44.0)", "mypy-boto3-migrationhuborchestrator (>=1.43.0,<1.44.0)", "mypy-boto3-migrationhubstrategy (>=1.43.0,<1.44.0)", "mypy-boto3-mpa (>=1.43.0,<1.44.0)", "mypy-boto3-mq (>=1.43.0,<1.44.0)", "mypy-boto3-mturk (>=1.43.0,<1.44.0)", "mypy-boto3-mwaa (>=1.43.0,<1.44.0)", "mypy-boto3-mwaa-serverless (>=1.43.0,<1.44.0)", "mypy-boto3-neptune (>=1.43.0,<1.44.0)", "mypy-boto3-neptune-graph (>=1.43.0,<1.44.0)", "mypy-boto3-neptunedata (>=1.43.0,<1.44.0)", "mypy-boto3-network-firewall (>=1.43.0,<1.44.0)", "mypy-boto3-network-security-manager (>=1.43.0,<1.44.0)", "mypy-boto3-networkflowmonitor (>=1.43.0,<1.44.0)", "mypy-boto3-networkmanager (>=1.43.0,<1.44.0)", "mypy-boto3-networkmonitor (>=1.43.0,<1.44.0)", "mypy-boto3-notifications (>=1.43.0,<1.44.0)", "mypy-boto3-notificationscontacts (>=1.43.0,<1.44.0)", "mypy-boto3-nova-act (>=1.43.0,<1.44.0)", "mypy-boto3-oam (>=1.43.0,<1.44.0)", "mypy-boto3-observabilityadmin (>=1.43.0,<1.44.0)", "mypy-boto3-odb (>=1.43.0,<1.44.0)", "mypy-boto3-omics (>=1.43.0,<1.44.0)", "mypy-boto3-opensearch (>=1.43.0,<1.44.0)", "mypy-boto3-opensearchserverless (>=1.43.0,<1.44.0)", "mypy-boto3-organizations (>=1.43.0,<1.44.0)", "mypy-boto3-osis (>=1.43.0,<1.44.0)", "mypy-boto3-outposts (>=1.43.0,<1.44.0)", "mypy-boto3-partnercentral-account (>=1.43.0,<1.44.0)", "mypy-boto3-partnercentral-benefits (>=1.43.0,<1.44.0)", "mypy-boto3-partnercentral-channel (>=1.43.0,<1.44.0)", "mypy-boto3-partnercentral-revenue-measurement (>=1.43.0,<1.44.0)", "mypy-boto3-partnercentral-selling (>=1.43.0,<1.44.0)", "mypy-boto3-payment-cryptography (>=1.43.0,<1.44.0)", "mypy-boto3-payment-cryptography-data (>=1.43.0,<1.44.0)", "mypy-boto3-pca-connector-ad (>=1.43.0,<1.44.0)", "mypy-boto3-pca-connector-scep (>=1.43.0,<1.44.0)", "mypy-boto3-pcs (>=1.43.0,<1.44.0)", "mypy-boto3-personalize (>=1.43.0,<1.44.0)", "mypy-boto3-personalize-events (>=1.43.0,<1.44.0)", "mypy-boto3-personalize-runtime (>=1.43.0,<1.44.0)", "mypy-boto3-pi (>=1.43.0,<1.44.0)", "mypy-boto3-pinpoint (>=1.43.0,<1.44.0)", "mypy-boto3-pinpoint-email (>=1.43.0,<1.44.0)", "mypy-boto3-pinpoint-sms-voice (>=1.43.0,<1.44.0)", "mypy-boto3-pinpoint-sms-voice-v2 (>=1.43.0,<1.44.0)", "mypy-boto3-pipes (>=1.43.0,<1.44.0)", "mypy-boto3-polly (>=1.43.0,<1.44.0)", "mypy-boto3-pricing (>=1.43.0,<1.44.0)", "mypy-boto3-pricing-plan-manager (>=1.43.0,<1.44.0)", "mypy-boto3-proton (>=1.43.0,<1.44.0)", "mypy-boto3-qapps (>=1.43.0,<1.44.0)", "mypy-boto3-qbusiness (>=1.43.0,<1.44.0)", "mypy-boto3-qconnect (>=1.43.0,<1.44.0)", "mypy-boto3-quicksight (>=1.43.0,<1.44.0)", "mypy-boto3-ram (>=1.43.0,<1.44.0)", "mypy-boto3-rbin (>=1.43.0,<1.44.0)", "mypy-boto3-rds (>=1.43.0,<1.44.0)", "mypy-boto3-rds-data (>=1.43.0,<1.44.0)", "mypy-boto3-redshift (>=1.43.0,<1.44.0)", "mypy-boto3-redshift-data (>=1.43.0,<1.44.0)", "mypy-boto3-redshift-serverless (>=1.43.0,<1.44.0)", "mypy-boto3-rekognition (>=1.43.0,<1.44.0)", "mypy-boto3-repostspace (>=1.43.0,<1.44.0)", "mypy-boto3-resiliencehub (>=1.43.0,<1.44.0)", "mypy-boto3-resiliencehubv2 (>=1.43.0,<1.44.0)", "mypy-boto3-resource-explorer-2 (>=1.43.0,<1.44.0)", "mypy-boto3-resource-groups (>=1.43.0,<1.44.0)", "mypy-boto3-resourcegroupstaggingapi (>=1.43.0,<1.44.0)", "mypy-boto3-rolesanywhere (>=1.43.0,<1.44.0)", "mypy-boto3-route53 (>=1.43.0,<1.44.0)", "mypy-boto3-route53-recovery-cluster (>=1.43.0,<1.44.0)", "mypy-boto3-route53-recovery-control-config (>=1.43.0,<1.44.0)", "mypy-boto3-route53-recovery-readiness (>=1.43.0,<1.44.0)", "mypy-boto3-route53domains (>=1.43.0,<1.44.0)", "mypy-boto3-route53globalresolver (>=1.43.0,<1.44.0)", "mypy-boto3-route53profiles (>=1.43.0,<1.44.0)", "mypy-boto3-route53resolver (>=1.43.0,<1.44.0)", "mypy-boto3-rtbfabric (>=1.43.0,<1.44.0)", "mypy-boto3-rum (>=1.43.0,<1.44.0)", "mypy-boto3-s3 (>=1.43.0,<1.44.0)", "mypy-boto3-s3control (>=1.43.0,<1.44.0)", "mypy-boto3-s3files (>=1.43.0,<1.44.0)", "mypy-boto3-s3outposts (>=1.43.0,<1.44.0)", "mypy-boto3-s3tables (>=1.43.0,<1.44.0)", "mypy-boto3-s3vectors (>=1.43.0,<1.44.0)", "mypy-boto3-sagemaker (>=1.43.0,<1.44.0)", "mypy-boto3-sagemaker-a2i-runtime (>=1.43.0,<1.44.0)", "mypy-boto3-sagemaker-edge (>=1.43.0,<1.44.0)", "mypy-boto3-sagemaker-featurestore-runtime (>=1.43.0,<1.44.0)", "mypy-boto3-sagemaker-geospatial (>=1.43.0,<1.44.0)", "mypy-boto3-sagemaker-metrics (>=1.43.0,<1.44.0)", "mypy-boto3-sagemaker-runtime (>=1.43.0,<1.44.0)", "mypy-boto3-sagemakerjobruntime (>=1.43.0,<1.44.0)", "mypy-boto3-savingsplans (>=1.43.0,<1.44.0)", "mypy-boto3-scheduler (>=1.43.0,<1.44.0)", "mypy-boto3-schemas (>=1.43.0,<1.44.0)", "mypy-boto3-sdb (>=1.43.0,<1.44.0)", "mypy-boto3-secretsmanager (>=1.43.0,<1.44.0)", "mypy-boto3-security-ir (>=1.43.0,<1.44.0)", "mypy-boto3-securityagent (>=1.43.0,<1.44.0)", "mypy-boto3-securityhub (>=1.43.0,<1.44.0)", "mypy-boto3-securitylake (>=1.43.0,<1.44.0)", "mypy-boto3-serverlessrepo (>=1.43.0,<1.44.0)", "mypy-boto3-service-quotas (>=1.43.0,<1.44.0)", "mypy-boto3-servicecatalog (>=1.43.0,<1.44.0)", "mypy-boto3-servicecatalog-appregistry (>=1.43.0,<1.44.0)", "mypy-boto3-servicediscovery (>=1.43.0,<1.44.0)", "mypy-boto3-ses (>=1.43.0,<1.44.0)", "mypy-boto3-sesv2 (>=1.43.0,<1.44.0)", "mypy-boto3-shield (>=1.43.0,<1.44.0)", "mypy-boto3-signer (>=1.43.0,<1.44.0)", "mypy-boto3-signer-data (>=1.43.0,<1.44.0)", "mypy-boto3-signin (>=1.43.0,<1.44.0)", "mypy-boto3-simpledbv2 (>=1.43.0,<1.44.0)", "mypy-boto3-snow-device-management (>=1.43.0,<1.44.0)", "mypy-boto3-snowball (>=1.43.0,<1.44.0)", "mypy-boto3-sns (>=1.43.0,<1.44.0)", "mypy-boto3-socialmessaging (>=1.43.0,<1.44.0)", "mypy-boto3-sqs (>=1.43.0,<1.44.0)", "mypy-boto3-ssm (>=1.43.0,<1.44.0)", "mypy-boto3-ssm-contacts (>=1.43.0,<1.44.0)", "mypy-boto3-ssm-guiconnect (>=1.43.0,<1.44.0)", "mypy-boto3-ssm-incidents (>=1.43.0,<1.44.0)", "mypy-boto3-ssm-quicksetup (>=1.43.0,<1.44.0)", "mypy-boto3-ssm-sap (>=1.43.0,<1.44.0)", "mypy-boto3-sso (>=1.43.0,<1.44.0)", "mypy-boto3-sso-admin (>=1.43.0,<1.44.0)", "mypy-boto3-sso-oidc (>=1.43.0,<1.44.0)", "mypy-boto3-stepfunctions (>=1.43.0,<1.44.0)", "mypy-boto3-storagegateway (>=1.43.0,<1.44.0)", "mypy-boto3-sts (>=1.43.0,<1.44.0)", "mypy-boto3-supplychain (>=1.43.0,<1.44.0)", "mypy-boto3-support (>=1.43.0,<1.44.0)", "mypy-boto3-support-app (>=1.43.0,<1.44.0)", "mypy-boto3-supportauthz (>=1.43.0,<1.44.0)", "mypy-boto3-sustainability (>=1.43.0,<1.44.0)", "mypy-boto3-swf (>=1.43.0,<1.44.0)", "mypy-boto3-synthetics (>=1.43.0,<1.44.0)", "mypy-boto3-taxsettings (>=1.43.0,<1.44.0)", "mypy-boto3-textract (>=1.43.0,<1.44.0)", "mypy-boto3-timestream-influxdb (>=1.43.0,<1.44.0)", "mypy-boto3-timestream-query (>=1.43.0,<1.44.0)", "mypy-boto3-timestream-write (>=1.43.0,<1.44.0)", "mypy-boto3-tnb (>=1.43.0,<1.44.0)", "mypy-boto3-transcribe (>=1.43.0,<1.44.0)", "mypy-boto3-transfer (>=1.43.0,<1.44.0)", "mypy-boto3-translate (>=1.43.0,<1.44.0)", "mypy-boto3-trustedadvisor (>=1.43.0,<1.44.0)", "mypy-boto3-uxc (>=1.43.0,<1.44.0)", "mypy-boto3-verifiedpermissions (>=1.43.0,<1.44.0)", "mypy-boto3-voice-id (>=1.43.0,<1.44.0)", "mypy-boto3-vpc-lattice (>=1.43.0,<1.44.0)", "mypy-boto3-waf (>=1.43.0,<1.44.0)", "mypy-boto3-waf-regional (>=1.43.0,<1.44.0)", "mypy-boto3-wafv2 (>=1.43.0,<1.44.0)", "mypy-boto3-wellarchitected (>=1.43.0,<1.44.0)", "mypy-boto3-wickr (>=1.43.0,<1.44.0)", "mypy-boto3-wisdom (>=1.43.0,<1.44.0)", "mypy-boto3-workdocs (>=1.43.0,<1.44.0)", "mypy-boto3-workmail (>=1.43.0,<1.44.0)", "mypy-boto3-workmailmessageflow (>=1.43.0,<1.44.0)", "mypy-boto3-workspaces (>=1.43.0,<1.44.0)", "mypy-boto3-workspaces-instances (>=1.43.0,<1.44.0)", "mypy-boto3-workspaces-thin-client (>=1.43.0,<1.44.0)", "mypy-boto3-workspaces-web (>=1.43.0,<1.44.0)", "mypy-boto3-xray (>=1.43.0,<1.44.0)"] amp = ["mypy-boto3-amp (>=1.43.0,<1.44.0)"] amplify = ["mypy-boto3-amplify (>=1.43.0,<1.44.0)"] amplifybackend = ["mypy-boto3-amplifybackend (>=1.43.0,<1.44.0)"] @@ -208,7 +235,7 @@ bedrock-data-automation-runtime = ["mypy-boto3-bedrock-data-automation-runtime ( bedrock-runtime = ["mypy-boto3-bedrock-runtime (>=1.43.0,<1.44.0)"] billing = ["mypy-boto3-billing (>=1.43.0,<1.44.0)"] billingconductor = ["mypy-boto3-billingconductor (>=1.43.0,<1.44.0)"] -boto3 = ["boto3 (==1.43.34)"] +boto3 = ["boto3 (==1.43.108)"] braket = ["mypy-boto3-braket (>=1.43.0,<1.44.0)"] budgets = ["mypy-boto3-budgets (>=1.43.0,<1.44.0)"] ce = ["mypy-boto3-ce (>=1.43.0,<1.44.0)"] @@ -234,6 +261,7 @@ cloudsearchdomain = ["mypy-boto3-cloudsearchdomain (>=1.43.0,<1.44.0)"] cloudtrail = ["mypy-boto3-cloudtrail (>=1.43.0,<1.44.0)"] cloudtrail-data = ["mypy-boto3-cloudtrail-data (>=1.43.0,<1.44.0)"] cloudwatch = ["mypy-boto3-cloudwatch (>=1.43.0,<1.44.0)"] +cloudwatchomni = ["mypy-boto3-cloudwatchomni (>=1.43.0,<1.44.0)"] codeartifact = ["mypy-boto3-codeartifact (>=1.43.0,<1.44.0)"] codebuild = ["mypy-boto3-codebuild (>=1.43.0,<1.44.0)"] codecatalyst = ["mypy-boto3-codecatalyst (>=1.43.0,<1.44.0)"] @@ -306,9 +334,11 @@ elementalinference = ["mypy-boto3-elementalinference (>=1.43.0,<1.44.0)"] emr = ["mypy-boto3-emr (>=1.43.0,<1.44.0)"] emr-containers = ["mypy-boto3-emr-containers (>=1.43.0,<1.44.0)"] emr-serverless = ["mypy-boto3-emr-serverless (>=1.43.0,<1.44.0)"] +endusermessaging = ["mypy-boto3-endusermessaging (>=1.43.0,<1.44.0)"] entityresolution = ["mypy-boto3-entityresolution (>=1.43.0,<1.44.0)"] es = ["mypy-boto3-es (>=1.43.0,<1.44.0)"] essential = ["mypy-boto3-cloudformation (>=1.43.0,<1.44.0)", "mypy-boto3-dynamodb (>=1.43.0,<1.44.0)", "mypy-boto3-ec2 (>=1.43.0,<1.44.0)", "mypy-boto3-lambda (>=1.43.0,<1.44.0)", "mypy-boto3-rds (>=1.43.0,<1.44.0)", "mypy-boto3-s3 (>=1.43.0,<1.44.0)", "mypy-boto3-sqs (>=1.43.0,<1.44.0)"] +eventbridgev2 = ["mypy-boto3-eventbridgev2 (>=1.43.0,<1.44.0)"] events = ["mypy-boto3-events (>=1.43.0,<1.44.0)"] evs = ["mypy-boto3-evs (>=1.43.0,<1.44.0)"] finspace = ["mypy-boto3-finspace (>=1.43.0,<1.44.0)"] @@ -338,6 +368,7 @@ guardduty = ["mypy-boto3-guardduty (>=1.43.0,<1.44.0)"] health = ["mypy-boto3-health (>=1.43.0,<1.44.0)"] healthlake = ["mypy-boto3-healthlake (>=1.43.0,<1.44.0)"] iam = ["mypy-boto3-iam (>=1.43.0,<1.44.0)"] +iam-toolbox = ["mypy-boto3-iam-toolbox (>=1.43.0,<1.44.0)"] identitystore = ["mypy-boto3-identitystore (>=1.43.0,<1.44.0)"] imagebuilder = ["mypy-boto3-imagebuilder (>=1.43.0,<1.44.0)"] importexport = ["mypy-boto3-importexport (>=1.43.0,<1.44.0)"] @@ -352,8 +383,6 @@ iot-data = ["mypy-boto3-iot-data (>=1.43.0,<1.44.0)"] iot-jobs-data = ["mypy-boto3-iot-jobs-data (>=1.43.0,<1.44.0)"] iot-managed-integrations = ["mypy-boto3-iot-managed-integrations (>=1.43.0,<1.44.0)"] iotdeviceadvisor = ["mypy-boto3-iotdeviceadvisor (>=1.43.0,<1.44.0)"] -iotevents = ["mypy-boto3-iotevents (>=1.43.0,<1.44.0)"] -iotevents-data = ["mypy-boto3-iotevents-data (>=1.43.0,<1.44.0)"] iotfleetwise = ["mypy-boto3-iotfleetwise (>=1.43.0,<1.44.0)"] iotsecuretunneling = ["mypy-boto3-iotsecuretunneling (>=1.43.0,<1.44.0)"] iotsitewise = ["mypy-boto3-iotsitewise (>=1.43.0,<1.44.0)"] @@ -380,6 +409,9 @@ kinesisvideo = ["mypy-boto3-kinesisvideo (>=1.43.0,<1.44.0)"] kms = ["mypy-boto3-kms (>=1.43.0,<1.44.0)"] lakeformation = ["mypy-boto3-lakeformation (>=1.43.0,<1.44.0)"] lambda = ["mypy-boto3-lambda (>=1.43.0,<1.44.0)"] +lambda-core = ["mypy-boto3-lambda-core (>=1.43.0,<1.44.0)"] +lambda-microvms = ["mypy-boto3-lambda-microvms (>=1.43.0,<1.44.0)"] +lambda-web = ["mypy-boto3-lambda-web (>=1.43.0,<1.44.0)"] launch-wizard = ["mypy-boto3-launch-wizard (>=1.43.0,<1.44.0)"] lex-models = ["mypy-boto3-lex-models (>=1.43.0,<1.44.0)"] lex-runtime = ["mypy-boto3-lex-runtime (>=1.43.0,<1.44.0)"] @@ -432,6 +464,7 @@ neptune = ["mypy-boto3-neptune (>=1.43.0,<1.44.0)"] neptune-graph = ["mypy-boto3-neptune-graph (>=1.43.0,<1.44.0)"] neptunedata = ["mypy-boto3-neptunedata (>=1.43.0,<1.44.0)"] network-firewall = ["mypy-boto3-network-firewall (>=1.43.0,<1.44.0)"] +network-security-manager = ["mypy-boto3-network-security-manager (>=1.43.0,<1.44.0)"] networkflowmonitor = ["mypy-boto3-networkflowmonitor (>=1.43.0,<1.44.0)"] networkmanager = ["mypy-boto3-networkmanager (>=1.43.0,<1.44.0)"] networkmonitor = ["mypy-boto3-networkmonitor (>=1.43.0,<1.44.0)"] @@ -447,10 +480,10 @@ opensearchserverless = ["mypy-boto3-opensearchserverless (>=1.43.0,<1.44.0)"] organizations = ["mypy-boto3-organizations (>=1.43.0,<1.44.0)"] osis = ["mypy-boto3-osis (>=1.43.0,<1.44.0)"] outposts = ["mypy-boto3-outposts (>=1.43.0,<1.44.0)"] -panorama = ["mypy-boto3-panorama (>=1.43.0,<1.44.0)"] partnercentral-account = ["mypy-boto3-partnercentral-account (>=1.43.0,<1.44.0)"] partnercentral-benefits = ["mypy-boto3-partnercentral-benefits (>=1.43.0,<1.44.0)"] partnercentral-channel = ["mypy-boto3-partnercentral-channel (>=1.43.0,<1.44.0)"] +partnercentral-revenue-measurement = ["mypy-boto3-partnercentral-revenue-measurement (>=1.43.0,<1.44.0)"] partnercentral-selling = ["mypy-boto3-partnercentral-selling (>=1.43.0,<1.44.0)"] payment-cryptography = ["mypy-boto3-payment-cryptography (>=1.43.0,<1.44.0)"] payment-cryptography-data = ["mypy-boto3-payment-cryptography-data (>=1.43.0,<1.44.0)"] @@ -468,6 +501,7 @@ pinpoint-sms-voice-v2 = ["mypy-boto3-pinpoint-sms-voice-v2 (>=1.43.0,<1.44.0)"] pipes = ["mypy-boto3-pipes (>=1.43.0,<1.44.0)"] polly = ["mypy-boto3-polly (>=1.43.0,<1.44.0)"] pricing = ["mypy-boto3-pricing (>=1.43.0,<1.44.0)"] +pricing-plan-manager = ["mypy-boto3-pricing-plan-manager (>=1.43.0,<1.44.0)"] proton = ["mypy-boto3-proton (>=1.43.0,<1.44.0)"] qapps = ["mypy-boto3-qapps (>=1.43.0,<1.44.0)"] qbusiness = ["mypy-boto3-qbusiness (>=1.43.0,<1.44.0)"] @@ -533,7 +567,6 @@ signer = ["mypy-boto3-signer (>=1.43.0,<1.44.0)"] signer-data = ["mypy-boto3-signer-data (>=1.43.0,<1.44.0)"] signin = ["mypy-boto3-signin (>=1.43.0,<1.44.0)"] simpledbv2 = ["mypy-boto3-simpledbv2 (>=1.43.0,<1.44.0)"] -simspaceweaver = ["mypy-boto3-simspaceweaver (>=1.43.0,<1.44.0)"] snow-device-management = ["mypy-boto3-snow-device-management (>=1.43.0,<1.44.0)"] snowball = ["mypy-boto3-snowball (>=1.43.0,<1.44.0)"] sns = ["mypy-boto3-sns (>=1.43.0,<1.44.0)"] @@ -554,6 +587,7 @@ sts = ["mypy-boto3-sts (>=1.43.0,<1.44.0)"] supplychain = ["mypy-boto3-supplychain (>=1.43.0,<1.44.0)"] support = ["mypy-boto3-support (>=1.43.0,<1.44.0)"] support-app = ["mypy-boto3-support-app (>=1.43.0,<1.44.0)"] +supportauthz = ["mypy-boto3-supportauthz (>=1.43.0,<1.44.0)"] sustainability = ["mypy-boto3-sustainability (>=1.43.0,<1.44.0)"] swf = ["mypy-boto3-swf (>=1.43.0,<1.44.0)"] synthetics = ["mypy-boto3-synthetics (>=1.43.0,<1.44.0)"] @@ -588,14 +622,14 @@ xray = ["mypy-boto3-xray (>=1.43.0,<1.44.0)"] [[package]] name = "botocore" -version = "1.43.36" +version = "1.43.108" description = "Low-level, data-driven core of boto 3." optional = false python-versions = ">=3.10" groups = ["main", "dev"] files = [ - {file = "botocore-1.43.36-py3-none-any.whl", hash = "sha256:3c65fdc39ed01d8dfde1e961b34038aed03c459f8ddf80717a12ac006475e49d"}, - {file = "botocore-1.43.36.tar.gz", hash = "sha256:4cae47d1b2d426316b85a0087d9e69e048f13bc003b5177d74639fe9dfd28205"}, + {file = "botocore-1.43.108-py3-none-any.whl", hash = "sha256:ab9d16c6b4350aaa54ed28202dfa2998b2d735fdbf3247eb60af469d8d48a5b8"}, + {file = "botocore-1.43.108.tar.gz", hash = "sha256:ee4f75cf3bdbb0da7912e089950e8112f692016539d939312c771499958e6cfd"}, ] [package.dependencies] @@ -604,130 +638,143 @@ python-dateutil = ">=2.1,<3.0.0" urllib3 = ">=1.25.4,<2.2.0 || >2.2.0,<3" [package.extras] -crt = ["awscrt (==0.32.2)"] +crt = ["awscrt (==0.36.0)"] [[package]] name = "botocore-stubs" -version = "1.42.41" +version = "1.43.67" description = "Type annotations and code completion for botocore" optional = false -python-versions = ">=3.9" +python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "botocore_stubs-1.42.41-py3-none-any.whl", hash = "sha256:9423110fb0e391834bd2ed44ae5f879d8cb370a444703d966d30842ce2bcb5f0"}, - {file = "botocore_stubs-1.42.41.tar.gz", hash = "sha256:dbeac2f744df6b814ce83ec3f3777b299a015cbea57a2efc41c33b8c38265825"}, + {file = "botocore_stubs-1.43.67-py3-none-any.whl", hash = "sha256:c51262bac3341c1cda71f05fa01141fffd3990d7a92c7960e3b755c1bc830373"}, + {file = "botocore_stubs-1.43.67.tar.gz", hash = "sha256:853e74014a1f557055c4ffae5fb38d7c65c7c0520e1aab366cac41d5428f419d"}, ] -[package.dependencies] -types-awscrt = "*" - [package.extras] botocore = ["botocore"] [[package]] name = "certifi" -version = "2026.4.22" +version = "2026.7.22" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.7" groups = ["main", "dev", "docs"] files = [ - {file = "certifi-2026.4.22-py3-none-any.whl", hash = "sha256:3cb2210c8f88ba2318d29b0388d1023c8492ff72ecdde4ebdaddbb13a31b1c4a"}, - {file = "certifi-2026.4.22.tar.gz", hash = "sha256:8d455352a37b71bf76a79caa83a3d6c25afee4a385d632127b6afb3963f1c580"}, + {file = "certifi-2026.7.22-py3-none-any.whl", hash = "sha256:62f22742b58a1a33014a2b6b706588a8d7e2a88ae7bd1a6ebe8c992928483775"}, + {file = "certifi-2026.7.22.tar.gz", hash = "sha256:741e2c3b351ddf169a738da9f2c048608ff7f2c5cc02f1ebc6b118bb090d5d55"}, ] [[package]] name = "cffi" -version = "2.0.0" +version = "2.1.1" description = "Foreign Function Interface for Python calling C code." optional = false -python-versions = ">=3.9" +python-versions = ">=3.10" groups = ["main", "dev"] files = [ - {file = "cffi-2.0.0-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:0cf2d91ecc3fcc0625c2c530fe004f82c110405f101548512cce44322fa8ac44"}, - {file = "cffi-2.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f73b96c41e3b2adedc34a7356e64c8eb96e03a3782b535e043a986276ce12a49"}, - {file = "cffi-2.0.0-cp310-cp310-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:53f77cbe57044e88bbd5ed26ac1d0514d2acf0591dd6bb02a3ae37f76811b80c"}, - {file = "cffi-2.0.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3e837e369566884707ddaf85fc1744b47575005c0a229de3327f8f9a20f4efeb"}, - {file = "cffi-2.0.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:5eda85d6d1879e692d546a078b44251cdd08dd1cfb98dfb77b670c97cee49ea0"}, - {file = "cffi-2.0.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:9332088d75dc3241c702d852d4671613136d90fa6881da7d770a483fd05248b4"}, - {file = "cffi-2.0.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fc7de24befaeae77ba923797c7c87834c73648a05a4bde34b3b7e5588973a453"}, - {file = "cffi-2.0.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:cf364028c016c03078a23b503f02058f1814320a56ad535686f90565636a9495"}, - {file = "cffi-2.0.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e11e82b744887154b182fd3e7e8512418446501191994dbf9c9fc1f32cc8efd5"}, - {file = "cffi-2.0.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8ea985900c5c95ce9db1745f7933eeef5d314f0565b27625d9a10ec9881e1bfb"}, - {file = "cffi-2.0.0-cp310-cp310-win32.whl", hash = "sha256:1f72fb8906754ac8a2cc3f9f5aaa298070652a0ffae577e0ea9bd480dc3c931a"}, - {file = "cffi-2.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:b18a3ed7d5b3bd8d9ef7a8cb226502c6bf8308df1525e1cc676c3680e7176739"}, - {file = "cffi-2.0.0-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:b4c854ef3adc177950a8dfc81a86f5115d2abd545751a304c5bcf2c2c7283cfe"}, - {file = "cffi-2.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2de9a304e27f7596cd03d16f1b7c72219bd944e99cc52b84d0145aefb07cbd3c"}, - {file = "cffi-2.0.0-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:baf5215e0ab74c16e2dd324e8ec067ef59e41125d3eade2b863d294fd5035c92"}, - {file = "cffi-2.0.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:730cacb21e1bdff3ce90babf007d0a0917cc3e6492f336c2f0134101e0944f93"}, - {file = "cffi-2.0.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:6824f87845e3396029f3820c206e459ccc91760e8fa24422f8b0c3d1731cbec5"}, - {file = "cffi-2.0.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:9de40a7b0323d889cf8d23d1ef214f565ab154443c42737dfe52ff82cf857664"}, - {file = "cffi-2.0.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8941aaadaf67246224cee8c3803777eed332a19d909b47e29c9842ef1e79ac26"}, - {file = "cffi-2.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a05d0c237b3349096d3981b727493e22147f934b20f6f125a3eba8f994bec4a9"}, - {file = "cffi-2.0.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:94698a9c5f91f9d138526b48fe26a199609544591f859c870d477351dc7b2414"}, - {file = "cffi-2.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:5fed36fccc0612a53f1d4d9a816b50a36702c28a2aa880cb8a122b3466638743"}, - {file = "cffi-2.0.0-cp311-cp311-win32.whl", hash = "sha256:c649e3a33450ec82378822b3dad03cc228b8f5963c0c12fc3b1e0ab940f768a5"}, - {file = "cffi-2.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:66f011380d0e49ed280c789fbd08ff0d40968ee7b665575489afa95c98196ab5"}, - {file = "cffi-2.0.0-cp311-cp311-win_arm64.whl", hash = "sha256:c6638687455baf640e37344fe26d37c404db8b80d037c3d29f58fe8d1c3b194d"}, - {file = "cffi-2.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6d02d6655b0e54f54c4ef0b94eb6be0607b70853c45ce98bd278dc7de718be5d"}, - {file = "cffi-2.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8eca2a813c1cb7ad4fb74d368c2ffbbb4789d377ee5bb8df98373c2cc0dee76c"}, - {file = "cffi-2.0.0-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:21d1152871b019407d8ac3985f6775c079416c282e431a4da6afe7aefd2bccbe"}, - {file = "cffi-2.0.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b21e08af67b8a103c71a250401c78d5e0893beff75e28c53c98f4de42f774062"}, - {file = "cffi-2.0.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:1e3a615586f05fc4065a8b22b8152f0c1b00cdbc60596d187c2a74f9e3036e4e"}, - {file = "cffi-2.0.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:81afed14892743bbe14dacb9e36d9e0e504cd204e0b165062c488942b9718037"}, - {file = "cffi-2.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3e17ed538242334bf70832644a32a7aae3d83b57567f9fd60a26257e992b79ba"}, - {file = "cffi-2.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3925dd22fa2b7699ed2617149842d2e6adde22b262fcbfada50e3d195e4b3a94"}, - {file = "cffi-2.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2c8f814d84194c9ea681642fd164267891702542f028a15fc97d4674b6206187"}, - {file = "cffi-2.0.0-cp312-cp312-win32.whl", hash = "sha256:da902562c3e9c550df360bfa53c035b2f241fed6d9aef119048073680ace4a18"}, - {file = "cffi-2.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:da68248800ad6320861f129cd9c1bf96ca849a2771a59e0344e88681905916f5"}, - {file = "cffi-2.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:4671d9dd5ec934cb9a73e7ee9676f9362aba54f7f34910956b84d727b0d73fb6"}, - {file = "cffi-2.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:00bdf7acc5f795150faa6957054fbbca2439db2f775ce831222b66f192f03beb"}, - {file = "cffi-2.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:45d5e886156860dc35862657e1494b9bae8dfa63bf56796f2fb56e1679fc0bca"}, - {file = "cffi-2.0.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:07b271772c100085dd28b74fa0cd81c8fb1a3ba18b21e03d7c27f3436a10606b"}, - {file = "cffi-2.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d48a880098c96020b02d5a1f7d9251308510ce8858940e6fa99ece33f610838b"}, - {file = "cffi-2.0.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:f93fd8e5c8c0a4aa1f424d6173f14a892044054871c771f8566e4008eaa359d2"}, - {file = "cffi-2.0.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:dd4f05f54a52fb558f1ba9f528228066954fee3ebe629fc1660d874d040ae5a3"}, - {file = "cffi-2.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c8d3b5532fc71b7a77c09192b4a5a200ea992702734a2e9279a37f2478236f26"}, - {file = "cffi-2.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d9b29c1f0ae438d5ee9acb31cadee00a58c46cc9c0b2f9038c6b0b3470877a8c"}, - {file = "cffi-2.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6d50360be4546678fc1b79ffe7a66265e28667840010348dd69a314145807a1b"}, - {file = "cffi-2.0.0-cp313-cp313-win32.whl", hash = "sha256:74a03b9698e198d47562765773b4a8309919089150a0bb17d829ad7b44b60d27"}, - {file = "cffi-2.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:19f705ada2530c1167abacb171925dd886168931e0a7b78f5bffcae5c6b5be75"}, - {file = "cffi-2.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:256f80b80ca3853f90c21b23ee78cd008713787b1b1e93eae9f3d6a7134abd91"}, - {file = "cffi-2.0.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:fc33c5141b55ed366cfaad382df24fe7dcbc686de5be719b207bb248e3053dc5"}, - {file = "cffi-2.0.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c654de545946e0db659b3400168c9ad31b5d29593291482c43e3564effbcee13"}, - {file = "cffi-2.0.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:24b6f81f1983e6df8db3adc38562c83f7d4a0c36162885ec7f7b77c7dcbec97b"}, - {file = "cffi-2.0.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:12873ca6cb9b0f0d3a0da705d6086fe911591737a59f28b7936bdfed27c0d47c"}, - {file = "cffi-2.0.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:d9b97165e8aed9272a6bb17c01e3cc5871a594a446ebedc996e2397a1c1ea8ef"}, - {file = "cffi-2.0.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:afb8db5439b81cf9c9d0c80404b60c3cc9c3add93e114dcae767f1477cb53775"}, - {file = "cffi-2.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:737fe7d37e1a1bffe70bd5754ea763a62a066dc5913ca57e957824b72a85e205"}, - {file = "cffi-2.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:38100abb9d1b1435bc4cc340bb4489635dc2f0da7456590877030c9b3d40b0c1"}, - {file = "cffi-2.0.0-cp314-cp314-win32.whl", hash = "sha256:087067fa8953339c723661eda6b54bc98c5625757ea62e95eb4898ad5e776e9f"}, - {file = "cffi-2.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:203a48d1fb583fc7d78a4c6655692963b860a417c0528492a6bc21f1aaefab25"}, - {file = "cffi-2.0.0-cp314-cp314-win_arm64.whl", hash = "sha256:dbd5c7a25a7cb98f5ca55d258b103a2054f859a46ae11aaf23134f9cc0d356ad"}, - {file = "cffi-2.0.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:9a67fc9e8eb39039280526379fb3a70023d77caec1852002b4da7e8b270c4dd9"}, - {file = "cffi-2.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7a66c7204d8869299919db4d5069a82f1561581af12b11b3c9f48c584eb8743d"}, - {file = "cffi-2.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7cc09976e8b56f8cebd752f7113ad07752461f48a58cbba644139015ac24954c"}, - {file = "cffi-2.0.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:92b68146a71df78564e4ef48af17551a5ddd142e5190cdf2c5624d0c3ff5b2e8"}, - {file = "cffi-2.0.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:b1e74d11748e7e98e2f426ab176d4ed720a64412b6a15054378afdb71e0f37dc"}, - {file = "cffi-2.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:28a3a209b96630bca57cce802da70c266eb08c6e97e5afd61a75611ee6c64592"}, - {file = "cffi-2.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:7553fb2090d71822f02c629afe6042c299edf91ba1bf94951165613553984512"}, - {file = "cffi-2.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6c6c373cfc5c83a975506110d17457138c8c63016b563cc9ed6e056a82f13ce4"}, - {file = "cffi-2.0.0-cp314-cp314t-win32.whl", hash = "sha256:1fc9ea04857caf665289b7a75923f2c6ed559b8298a1b8c49e59f7dd95c8481e"}, - {file = "cffi-2.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:d68b6cef7827e8641e8ef16f4494edda8b36104d79773a334beaa1e3521430f6"}, - {file = "cffi-2.0.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0a1527a803f0a659de1af2e1fd700213caba79377e27e4693648c2923da066f9"}, - {file = "cffi-2.0.0-cp39-cp39-macosx_10_13_x86_64.whl", hash = "sha256:fe562eb1a64e67dd297ccc4f5addea2501664954f2692b69a76449ec7913ecbf"}, - {file = "cffi-2.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:de8dad4425a6ca6e4e5e297b27b5c824ecc7581910bf9aee86cb6835e6812aa7"}, - {file = "cffi-2.0.0-cp39-cp39-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:4647afc2f90d1ddd33441e5b0e85b16b12ddec4fca55f0d9671fef036ecca27c"}, - {file = "cffi-2.0.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3f4d46d8b35698056ec29bca21546e1551a205058ae1a181d871e278b0b28165"}, - {file = "cffi-2.0.0-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:e6e73b9e02893c764e7e8d5bb5ce277f1a009cd5243f8228f75f842bf937c534"}, - {file = "cffi-2.0.0-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:cb527a79772e5ef98fb1d700678fe031e353e765d1ca2d409c92263c6d43e09f"}, - {file = "cffi-2.0.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:61d028e90346df14fedc3d1e5441df818d095f3b87d286825dfcbd6459b7ef63"}, - {file = "cffi-2.0.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:0f6084a0ea23d05d20c3edcda20c3d006f9b6f3fefeac38f59262e10cef47ee2"}, - {file = "cffi-2.0.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:1cd13c99ce269b3ed80b417dcd591415d3372bcac067009b6e0f59c7d4015e65"}, - {file = "cffi-2.0.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:89472c9762729b5ae1ad974b777416bfda4ac5642423fa93bd57a09204712322"}, - {file = "cffi-2.0.0-cp39-cp39-win32.whl", hash = "sha256:2081580ebb843f759b9f617314a24ed5738c51d2aee65d31e02f6f7a2b97707a"}, - {file = "cffi-2.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:b882b3df248017dba09d6b16defe9b5c407fe32fc7c65a9c69798e6175601be9"}, - {file = "cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529"}, + {file = "cffi-2.1.1-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:baed1e86cc735622097354b9d1281406caf42ff42a886d29faa8e8d1630333be"}, + {file = "cffi-2.1.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ca82be1a1d406ecfe1d25dc16cb33488e5a16bf4438c9fb590484ea29d92478b"}, + {file = "cffi-2.1.1-cp310-cp310-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:42e2f76b9455f5a9a844f770bf3e200ed3da0e15f5df3db9c31fe80b04b3d004"}, + {file = "cffi-2.1.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5a59cc1c4442bc3d5c703bf720b51138d0bfc173618807c9ee2490a7541dd3d9"}, + {file = "cffi-2.1.1-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:9f8d177621de5cb38ee3e731eda45d421db093ec0739f46a5594babda7987a98"}, + {file = "cffi-2.1.1-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:75f80557d1389eddbd0de2681f6a390a0c5338c31ddaa821381c203fc3fd50d9"}, + {file = "cffi-2.1.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:194cffa889098ced9976c3fc6340305e43f6303657d298da55366907c05c22d6"}, + {file = "cffi-2.1.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:5bb4e7ea95dcd6a014a6fef62e62467d67d8e582326443f3d68e71d6320a9fcf"}, + {file = "cffi-2.1.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3d22a20b1fb1632cc72c22f95f7b0d2961c3e1c235f245ba4c606c4771035659"}, + {file = "cffi-2.1.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:1dea0e4d7d4f11f619fe8c1d76caf49e24405b4b5743c0e3be16a500ecd930c9"}, + {file = "cffi-2.1.1-cp310-cp310-win32.whl", hash = "sha256:7ce713ace7c0e4520535b42b77eaa742c16dab813978064913e5a3cf82973b41"}, + {file = "cffi-2.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:a48d62ab9d6f4f98c983223a547af44be6ca3691074c31cecced6facd3ba2dc1"}, + {file = "cffi-2.1.1-cp311-cp311-macosx_10_15_x86_64.whl", hash = "sha256:c8d2c9fd1f2d16f780d15127abb050d13d1a76c03a4bd87d7e4980e45e511e12"}, + {file = "cffi-2.1.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:398aff33cee2767e3e781d2554c54bd0dff386bb437581e0d8011fde1a942ec1"}, + {file = "cffi-2.1.1-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:154852545011f779917b11c78db2358d095da62a9a172b78ad0a583ee5adc0d0"}, + {file = "cffi-2.1.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3311ed60d36f83378794e1009ac6258bafbf81f7888b4caa7b35a521e3f95813"}, + {file = "cffi-2.1.1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:6e192623c49c94421616a5778fba35cf0d5a8d000650c1967ef4448ee5cdd990"}, + {file = "cffi-2.1.1-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:a6e721d4b0e45d5b65e87534470e67b18dcd092c83f68fba09f152b9cbc061af"}, + {file = "cffi-2.1.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:34e261f78cb6ceaaa36f42f2613f4380d94d9c759a9c73c769ee6e0247364632"}, + {file = "cffi-2.1.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7225e4514edb64eb6740324353e0da0711954fd8d7da4576755b1c6e09b697cd"}, + {file = "cffi-2.1.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:df913725b79db7bcf03448f36b7bf8815363417d5b58deecf9305e3e30f0f21a"}, + {file = "cffi-2.1.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f5cfbc5fe74540d335175b656c725d74d90e3730c626d92575eea35029d9afaa"}, + {file = "cffi-2.1.1-cp311-cp311-win32.whl", hash = "sha256:f8ec5e643a9a937f64e1999eb9f75d072263751912dc5cd06d3c85f8f44be7c3"}, + {file = "cffi-2.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:42f6930c31dc7f50732c9ae793c2786c7b6b044195967bbdde40bb9be81c4cc0"}, + {file = "cffi-2.1.1-cp311-cp311-win_arm64.whl", hash = "sha256:c7659f22557c5a0bc4855cd635f55edec690cc008a40768527762cb9fb263455"}, + {file = "cffi-2.1.1-cp312-cp312-macosx_10_15_x86_64.whl", hash = "sha256:c8c69575568085ba0b1b10c0249d779a214aea6f6522e949a0fc9fb0fcb449d0"}, + {file = "cffi-2.1.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f81b3b8f3d4e343550fa4baa0e479bba9f2d29ce9c2e9b51d1ce1718d7442fcf"}, + {file = "cffi-2.1.1-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:811bd1e21d32de12efca32393a0ab3f5133b54fce9bd44b8bd77ab07da14bf6a"}, + {file = "cffi-2.1.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:68e62fe11f30d5ca8289242866f0a5291402d8529ca2178ab8afc5c9694ae890"}, + {file = "cffi-2.1.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:4a7c934f7360e8cd64fe9efadcbd10c7c6364f531e432b9a4bf5ccbc9e0e8b50"}, + {file = "cffi-2.1.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:3143d81e29e1e20a9ce10901ec369012947876596f75a222235965f2b7ae832e"}, + {file = "cffi-2.1.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c1453022f490d2459a11819d83ad1d586e9ff65a12ac3e705ffebd46d3685dcf"}, + {file = "cffi-2.1.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:208f941bb9d18e768138677f0a6d2ce01f590df56043dda1df1535ac57c88517"}, + {file = "cffi-2.1.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:210019b6c7cf07f081b4c54635c8cf744377001350e29cc0f81c4377b4797735"}, + {file = "cffi-2.1.1-cp312-cp312-win32.whl", hash = "sha256:046bfc24911b37851ee1b51aab8bffe713d89c68c6a057b09484ce9fd5f69b4e"}, + {file = "cffi-2.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:f53e442b08449d42821fa4a4fba000095af9f62742a500f978a9f557ec44339a"}, + {file = "cffi-2.1.1-cp312-cp312-win_arm64.whl", hash = "sha256:7bde5e4cc5c10140859842b9d383af292b22639a4dffb725314baf45968cef80"}, + {file = "cffi-2.1.1-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:b5bdfd1c873d4e093aabc0ca84c4ca6dbc4f752afb5c86f146d9742580c9da2e"}, + {file = "cffi-2.1.1-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:31348097ff5bbe827ccc41795d4dd099d9f0625e7def00ee653c137a490c2a6c"}, + {file = "cffi-2.1.1-cp313-cp313-macosx_10_15_x86_64.whl", hash = "sha256:9d2055050ea716bd38b7f7f1579c275386646b4894c155a3e2f3cd62ed41b7c6"}, + {file = "cffi-2.1.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:19ee6127ee34de7d83ce3d371ebc5ed91addbdcc39f9ab15ce4eb35a4e534971"}, + {file = "cffi-2.1.1-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:6a8dddef476fab96d066d578fc88526767b836ab5ab21754e1d5bf3879c31c7c"}, + {file = "cffi-2.1.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f16c709686a78c727bbbf059f92b0bf41c6fc60deec706d2dc19f529175a6125"}, + {file = "cffi-2.1.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:fcd22650c908d7b7da162bbfaab594a1227a15d1643a98c68b122ac642fa2264"}, + {file = "cffi-2.1.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:aa9511c62d14da7aacc9b4bf51f3f697a621e83b2d6919008243c3aad168eea3"}, + {file = "cffi-2.1.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a931079504ecc49efed7744c476a5c343a92fabf66dec2db95edb1b2fdc770e2"}, + {file = "cffi-2.1.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a2d7755bef5a12ed488f4ef1f1b69ee9191d7396083b755a5d2295f6edb4768b"}, + {file = "cffi-2.1.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e0bcb7e0f677f543555d2adff3bf19c05f66cdb4796e5ff602442ab2fe3c4ef7"}, + {file = "cffi-2.1.1-cp313-cp313-win32.whl", hash = "sha256:334644fbac4eff73d985a17a91226df55d0f394160c4cfb880e084c8f7161cac"}, + {file = "cffi-2.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:1aa5645c30469b09530c4ebca77ebf8f17618293c58f8549cb1a543a50236e7d"}, + {file = "cffi-2.1.1-cp313-cp313-win_arm64.whl", hash = "sha256:63bbfd5ded17c4840ac07cd8f1c21ba9d9708141f840b324f422f41b207e3973"}, + {file = "cffi-2.1.1-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:7dbb61fe3a7699468030f71bbe5f8a0e326a151daa91beb11a6fc1f980c55e1c"}, + {file = "cffi-2.1.1-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:f24fb43132a4c6b4cb4eb029492919b2db645be6808d738f244fd146c03c32cb"}, + {file = "cffi-2.1.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:d28630f5854ab07ab1fd4aba756de52326c82e6be15d414b12793f1975048b54"}, + {file = "cffi-2.1.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:661c298b4821edebead0c91edd2b00374d67ad7c5a1f7a91d4442633b79d6a72"}, + {file = "cffi-2.1.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:58acb8ab8e295e6c5ea12f888cbb13cf21511ef2a3303a23f4325c29d17fe5c1"}, + {file = "cffi-2.1.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:456a61fa52d579ebf9df2e9552ead5129855dbaff6c1e5a9b1bc408809bdc062"}, + {file = "cffi-2.1.1-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:a4f00aa42f75d6e4595e8866e748cc1705adc0cddfeb2ca86d0d03993d63ba03"}, + {file = "cffi-2.1.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b0431303acaea1089ad4b3e9ce4e6518193def1118d4073ca848635ee4ea2e96"}, + {file = "cffi-2.1.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:64faea20f4e2613363a1a9b9c7dd73058f3ecd00133a511e72ad7c511658f527"}, + {file = "cffi-2.1.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5c58fe613dc5e5336357eff555824a314d8e43282600435c8d1cb6a7a2fedd13"}, + {file = "cffi-2.1.1-cp314-cp314-win32.whl", hash = "sha256:1a18a57b58cfb21fc28d72e876acf10eaed67a1ed96226f92af4df681d571c4c"}, + {file = "cffi-2.1.1-cp314-cp314-win_amd64.whl", hash = "sha256:3222ba5d678f80a030e6afbcc33dc1ae5cb45facabb61cee2c7016b8432fde48"}, + {file = "cffi-2.1.1-cp314-cp314-win_arm64.whl", hash = "sha256:ab36d55f9ed2d067327667c2fea18dda018eb628dd6347aa01dda6cf1f5d3836"}, + {file = "cffi-2.1.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:7750c6449dff7864bb9bb27ddfb0267756189201a3afc911d82b3caacd70dfc3"}, + {file = "cffi-2.1.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:0beceaabe56af686895136a2de78db54ecd8e4046b236b8fd6d6cb61389e9bf2"}, + {file = "cffi-2.1.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:49cbc70e6542d4ccccb936558d1064a8012541e78f821f955cff24e357776c94"}, + {file = "cffi-2.1.1-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:e2d65b31f36619cda3999b78b2aa9632e76b78448e7a56fc4240824200e7c4fc"}, + {file = "cffi-2.1.1-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:28907ab9bfb6aa13184cfc17c6b8e1023c5ab6fd7076d8c20a35e59fe04f8f29"}, + {file = "cffi-2.1.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:51b31d1c98274844cfd7838ce00bfc27c7423a4dc00fc0772fc3331c2cc90676"}, + {file = "cffi-2.1.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5e7cecbaadb83884793e05828cee59b210b24583b9c7425d0ba6a754fe22eb4e"}, + {file = "cffi-2.1.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:25792eac27877609e7bb06d42ff88278a6624fff2ba9bbb523c09616b117e80f"}, + {file = "cffi-2.1.1-cp314-cp314t-win32.whl", hash = "sha256:8ef53b2de9bcb9197d31854256575d59dbac0cba72ac627bb291ef5eceb74be4"}, + {file = "cffi-2.1.1-cp314-cp314t-win_amd64.whl", hash = "sha256:616f097f2fe415bc92a247f02e11f634e1f9e9a83d327e3c915c15089c87869e"}, + {file = "cffi-2.1.1-cp314-cp314t-win_arm64.whl", hash = "sha256:ad2c86c495b899d862ea0f4b42891b8713a3bd45dd4105c7fd51c2a72f39f3a5"}, + {file = "cffi-2.1.1-cp315-cp315-ios_13_0_arm64_iphoneos.whl", hash = "sha256:dddad92b554513a31f272570678ba307fb9f618f05e3d4a5eacafff9eae03e1d"}, + {file = "cffi-2.1.1-cp315-cp315-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:da0e573f9f97159390c89d9f1a9e41908b66d408cc5b58d08cf3847d844c531b"}, + {file = "cffi-2.1.1-cp315-cp315-macosx_10_15_x86_64.whl", hash = "sha256:fb92203a88b3d3053034db775110081c49d28be6551923805e039924093761e4"}, + {file = "cffi-2.1.1-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:2ae64be792b8966f2c69538199728b290e34726562896df1e5dc8ffd8d8188e8"}, + {file = "cffi-2.1.1-cp315-cp315-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:507a24c282e0f42f8ed737cf048572cbf580468da5555764a8331735e9c736b6"}, + {file = "cffi-2.1.1-cp315-cp315-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:246fa40ce8645a614ff682e0b70f37134e460eaf93a775e0cbe3cca585a67a80"}, + {file = "cffi-2.1.1-cp315-cp315-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:471cee653ae88de62096552e6d24ccb4a5adb8c8c9f10b5054d0122c15bf2779"}, + {file = "cffi-2.1.1-cp315-cp315-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:aeae0e330c9f6acd681f647d46cefd30c29f93e3392882e792e82080c9691399"}, + {file = "cffi-2.1.1-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:42a494cee34437f05546455144f2b5d9ac09b1face62bcfce597d2e521066688"}, + {file = "cffi-2.1.1-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:cc572dace3f60ef98d7b12ff411d20f5362feb31a0439eab0085bbfd349982d7"}, + {file = "cffi-2.1.1-cp315-cp315-win32.whl", hash = "sha256:4f42141fc14250de6dde5ee7ea4432be017252d91f19c5ad043c084cea629cac"}, + {file = "cffi-2.1.1-cp315-cp315-win_amd64.whl", hash = "sha256:e6e8cff14d6fb0be70a09c0bdc58096f501952d04624ebf867e0e56da2df8960"}, + {file = "cffi-2.1.1-cp315-cp315-win_arm64.whl", hash = "sha256:27350daa11d4f10c540e6e89dada4c54feb7256ad03e9a4dc075ebad7ba360d1"}, + {file = "cffi-2.1.1-cp315-cp315t-macosx_10_15_x86_64.whl", hash = "sha256:c26608d2222fb1e94487e4a387d85f13eb55d5ed725cb25a0c589ac4ee60e7bc"}, + {file = "cffi-2.1.1-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:4be96343e422f2dfcd12ab5c9f5aebe03f82f737c6bffeca6830b3875cb44aab"}, + {file = "cffi-2.1.1-cp315-cp315t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:937c0052c05a31ca1daf18de3158eed4dbfcb9cc107adbea227728d647be701e"}, + {file = "cffi-2.1.1-cp315-cp315t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:df423d40ee8654634421812bc3b196da3f9bd7d32929da813f8394c4348a5358"}, + {file = "cffi-2.1.1-cp315-cp315t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:a730a083190634c65cca36ba5f489531576ebd79bcd5c8e172130f6453127231"}, + {file = "cffi-2.1.1-cp315-cp315t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:363e05fa78e15116c3c32c210ee36884fd6b9afa6d440e47112c3bd511d64cb6"}, + {file = "cffi-2.1.1-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:770de9db11e84213beec501cfcaa013b019820ca881e03344dea5844f7876d94"}, + {file = "cffi-2.1.1-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:7da0c5eff80f0197f3b3d1232ec5a682a9325f4ae9016a78f5f5ca35f9ced1f5"}, + {file = "cffi-2.1.1-cp315-cp315t-win32.whl", hash = "sha256:06c72bb76605a4b0cd0aad6930b69d4baf7dd5d806cfc409b824191099700e66"}, + {file = "cffi-2.1.1-cp315-cp315t-win_amd64.whl", hash = "sha256:d9c275eaacd24aa73f94ffd6de08fc3f932424d8b6c376f4bed7cde376fe7bc3"}, + {file = "cffi-2.1.1-cp315-cp315t-win_arm64.whl", hash = "sha256:d18e5ac0f2f03f4f518d3e23db0f0cad7faa1da8620e9c09461d443bbf6e6692"}, + {file = "cffi-2.1.1.tar.gz", hash = "sha256:dd31f52ea1086513bb9df30f8fcee9b8918323ae067a3d5b78bc826a000712be"}, ] markers = {dev = "platform_python_implementation != \"PyPy\""} @@ -748,285 +795,328 @@ files = [ [[package]] name = "charset-normalizer" -version = "3.4.7" +version = "3.5.2" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." optional = false python-versions = ">=3.7" groups = ["main", "dev", "docs"] files = [ - {file = "charset_normalizer-3.4.7-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cdd68a1fb318e290a2077696b7eb7a21a49163c455979c639bf5a5dcdc46617d"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e17b8d5d6a8c47c85e68ca8379def1303fd360c3e22093a807cd34a71cd082b8"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:511ef87c8aec0783e08ac18565a16d435372bc1ac25a91e6ac7f5ef2b0bff790"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:007d05ec7321d12a40227aae9e2bc6dca73f3cb21058999a1df9e193555a9dcc"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cf29836da5119f3c8a8a70667b0ef5fdca3bb12f80fd06487cfa575b3909b393"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-manylinux_2_31_armv7l.whl", hash = "sha256:12d8baf840cc7889b37c7c770f478adea7adce3dcb3944d02ec87508e2dcf153"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d560742f3c0d62afaccf9f41fe485ed69bd7661a241f86a3ef0f0fb8b1a397af"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:b14b2d9dac08e28bb8046a1a0434b1750eb221c8f5b87a68f4fa11a6f97b5e34"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:bc17a677b21b3502a21f66a8cc64f5bfad4df8a0b8434d661666f8ce90ac3af1"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:750e02e074872a3fad7f233b47734166440af3cdea0add3e95163110816d6752"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:4e5163c14bffd570ef2affbfdd77bba66383890797df43dc8b4cc7d6f500bf53"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:6ed74185b2db44f41ef35fd1617c5888e59792da9bbc9190d6c7300617182616"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:94e1885b270625a9a828c9793b4d52a64445299baa1fea5a173bf1d3dd9a1a5a"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-win32.whl", hash = "sha256:6785f414ae0f3c733c437e0f3929197934f526d19dfaa75e18fdb4f94c6fb374"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-win_amd64.whl", hash = "sha256:6696b7688f54f5af4462118f0bfa7c1621eeb87154f77fa04b9295ce7a8f2943"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-win_arm64.whl", hash = "sha256:66671f93accb62ed07da56613636f3641f1a12c13046ce91ffc923721f23c008"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7641bb8895e77f921102f72833904dcd9901df5d6d72a2ab8f31d04b7e51e4e7"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:202389074300232baeb53ae2569a60901f7efadd4245cf3a3bf0617d60b439d7"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:30b8d1d8c52a48c2c5690e152c169b673487a2a58de1ec7393196753063fcd5e"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:532bc9bf33a68613fd7d65e4b1c71a6a38d7d42604ecf239c77392e9b4e8998c"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2fe249cb4651fd12605b7288b24751d8bfd46d35f12a20b1ba33dea122e690df"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-manylinux_2_31_armv7l.whl", hash = "sha256:65bcd23054beab4d166035cabbc868a09c1a49d1efe458fe8e4361215df40265"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:08e721811161356f97b4059a9ba7bafb23ea5ee2255402c42881c214e173c6b4"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e060d01aec0a910bdccb8be71faf34e7799ce36950f8294c8bf612cba65a2c9e"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:38c0109396c4cfc574d502df99742a45c72c08eff0a36158b6f04000043dbf38"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:1c2a768fdd44ee4a9339a9b0b130049139b8ce3c01d2ce09f67f5a68048d477c"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:1a87ca9d5df6fe460483d9a5bbf2b18f620cbed41b432e2bddb686228282d10b"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:d635aab80466bc95771bb78d5370e74d36d1fe31467b6b29b8b57b2a3cd7d22c"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ae196f021b5e7c78e918242d217db021ed2a6ace2bc6ae94c0fc596221c7f58d"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-win32.whl", hash = "sha256:adb2597b428735679446b46c8badf467b4ca5f5056aae4d51a19f9570301b1ad"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-win_amd64.whl", hash = "sha256:8e385e4267ab76874ae30db04c627faaaf0b509e1ccc11a95b3fc3e83f855c00"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-win_arm64.whl", hash = "sha256:d4a48e5b3c2a489fae013b7589308a40146ee081f6f509e047e0e096084ceca1"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:eca9705049ad3c7345d574e3510665cb2cf844c2f2dcfe675332677f081cbd46"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6178f72c5508bfc5fd446a5905e698c6212932f25bcdd4b47a757a50605a90e2"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e1421b502d83040e6d7fb2fb18dff63957f720da3d77b2fbd3187ceb63755d7b"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:edac0f1ab77644605be2cbba52e6b7f630731fc42b34cb0f634be1a6eface56a"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5649fd1c7bade02f320a462fdefd0b4bd3ce036065836d4f42e0de958038e116"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-manylinux_2_31_armv7l.whl", hash = "sha256:203104ed3e428044fd943bc4bf45fa73c0730391f9621e37fe39ecf477b128cb"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:298930cec56029e05497a76988377cbd7457ba864beeea92ad7e844fe74cd1f1"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:708838739abf24b2ceb208d0e22403dd018faeef86ddac04319a62ae884c4f15"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:0f7eb884681e3938906ed0434f20c63046eacd0111c4ba96f27b76084cd679f5"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:4dc1e73c36828f982bfe79fadf5919923f8a6f4df2860804db9a98c48824ce8d"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:aed52fea0513bac0ccde438c188c8a471c4e0f457c2dd20cdbf6ea7a450046c7"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:fea24543955a6a729c45a73fe90e08c743f0b3334bbf3201e6c4bc1b0c7fa464"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:bb6d88045545b26da47aa879dd4a89a71d1dce0f0e549b1abcb31dfe4a8eac49"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-win32.whl", hash = "sha256:2257141f39fe65a3fdf38aeccae4b953e5f3b3324f4ff0daf9f15b8518666a2c"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-win_amd64.whl", hash = "sha256:5ed6ab538499c8644b8a3e18debabcd7ce684f3fa91cf867521a7a0279cab2d6"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-win_arm64.whl", hash = "sha256:56be790f86bfb2c98fb742ce566dfb4816e5a83384616ab59c49e0604d49c51d"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:f496c9c3cc02230093d8330875c4c3cdfc3b73612a5fd921c65d39cbcef08063"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0ea948db76d31190bf08bd371623927ee1339d5f2a0b4b1b4a4439a65298703c"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a277ab8928b9f299723bc1a2dabb1265911b1a76341f90a510368ca44ad9ab66"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3bec022aec2c514d9cf199522a802bd007cd588ab17ab2525f20f9c34d067c18"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e044c39e41b92c845bc815e5ae4230804e8e7bc29e399b0437d64222d92809dd"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-manylinux_2_31_armv7l.whl", hash = "sha256:f495a1652cf3fbab2eb0639776dad966c2fb874d79d87ca07f9d5f059b8bd215"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e712b419df8ba5e42b226c510472b37bd57b38e897d3eca5e8cfd410a29fa859"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7804338df6fcc08105c7745f1502ba68d900f45fd770d5bdd5288ddccb8a42d8"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:481551899c856c704d58119b5025793fa6730adda3571971af568f66d2424bb5"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:f59099f9b66f0d7145115e6f80dd8b1d847176df89b234a5a6b3f00437aa0832"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:f59ad4c0e8f6bba240a9bb85504faa1ab438237199d4cce5f622761507b8f6a6"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:3dedcc22d73ec993f42055eff4fcfed9318d1eeb9a6606c55892a26964964e48"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:64f02c6841d7d83f832cd97ccf8eb8a906d06eb95d5276069175c696b024b60a"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-win32.whl", hash = "sha256:4042d5c8f957e15221d423ba781e85d553722fc4113f523f2feb7b188cc34c5e"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-win_amd64.whl", hash = "sha256:3946fa46a0cf3e4c8cb1cc52f56bb536310d34f25f01ca9b6c16afa767dab110"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-win_arm64.whl", hash = "sha256:80d04837f55fc81da168b98de4f4b797ef007fc8a79ab71c6ec9bc4dd662b15b"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:c36c333c39be2dbca264d7803333c896ab8fa7d4d6f0ab7edb7dfd7aea6e98c0"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1c2aed2e5e41f24ea8ef1590b8e848a79b56f3a5564a65ceec43c9d692dc7d8a"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:54523e136b8948060c0fa0bc7b1b50c32c186f2fceee897a495406bb6e311d2b"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:715479b9a2802ecac752a3b0efa2b0b60285cf962ee38414211abdfccc233b41"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bd6c2a1c7573c64738d716488d2cdd3c00e340e4835707d8fdb8dc1a66ef164e"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-manylinux_2_31_armv7l.whl", hash = "sha256:c45e9440fb78f8ddabcf714b68f936737a121355bf59f3907f4e17721b9d1aae"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3534e7dcbdcf757da6b85a0bbf5b6868786d5982dd959b065e65481644817a18"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:e8ac484bf18ce6975760921bb6148041faa8fef0547200386ea0b52b5d27bf7b"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:a5fe03b42827c13cdccd08e6c0247b6a6d4b5e3cdc53fd1749f5896adcdc2356"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:2d6eb928e13016cea4f1f21d1e10c1cebd5a421bc57ddf5b1142ae3f86824fab"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:e74327fb75de8986940def6e8dee4f127cc9752bee7355bb323cc5b2659b6d46"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:d6038d37043bced98a66e68d3aa2b6a35505dc01328cd65217cefe82f25def44"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:7579e913a5339fb8fa133f6bbcfd8e6749696206cf05acdbdca71a1b436d8e72"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-win32.whl", hash = "sha256:5b77459df20e08151cd6f8b9ef8ef1f961ef73d85c21a555c7eed5b79410ec10"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-win_amd64.whl", hash = "sha256:92a0a01ead5e668468e952e4238cccd7c537364eb7d851ab144ab6627dbbe12f"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-win_arm64.whl", hash = "sha256:67f6279d125ca0046a7fd386d01b311c6363844deac3e5b069b514ba3e63c246"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:effc3f449787117233702311a1b7d8f59cba9ced946ba727bdc329ec69028e24"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fbccdc05410c9ee21bbf16a35f4c1d16123dcdeb8a1d38f33654fa21d0234f79"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:733784b6d6def852c814bce5f318d25da2ee65dd4839a0718641c696e09a2960"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a89c23ef8d2c6b27fd200a42aa4ac72786e7c60d40efdc76e6011260b6e949c4"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6c114670c45346afedc0d947faf3c7f701051d2518b943679c8ff88befe14f8e"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:a180c5e59792af262bf263b21a3c49353f25945d8d9f70628e73de370d55e1e1"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3c9a494bc5ec77d43cea229c4f6db1e4d8fe7e1bbffa8b6f0f0032430ff8ab44"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8d828b6667a32a728a1ad1d93957cdf37489c57b97ae6c4de2860fa749b8fc1e"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:cf1493cd8607bec4d8a7b9b004e699fcf8f9103a9284cc94962cb73d20f9d4a3"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:0c96c3b819b5c3e9e165495db84d41914d6894d55181d2d108cc1a69bfc9cce0"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:752a45dc4a6934060b3b0dab47e04edc3326575f82be64bc4fc293914566503e"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:8778f0c7a52e56f75d12dae53ae320fae900a8b9b4164b981b9c5ce059cd1fcb"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ce3412fbe1e31eb81ea42f4169ed94861c56e643189e1e75f0041f3fe7020abe"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-win32.whl", hash = "sha256:c03a41a8784091e67a39648f70c5f97b5b6a37f216896d44d2cdcb82615339a0"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-win_amd64.whl", hash = "sha256:03853ed82eeebbce3c2abfdbc98c96dc205f32a79627688ac9a27370ea61a49c"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-win_arm64.whl", hash = "sha256:c35abb8bfff0185efac5878da64c45dafd2b37fb0383add1be155a763c1f083d"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e5f4d355f0a2b1a31bc3edec6795b46324349c9cb25eed068049e4f472fb4259"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:16d971e29578a5e97d7117866d15889a4a07befe0e87e703ed63cd90cb348c01"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:dca4bbc466a95ba9c0234ef56d7dd9509f63da22274589ebd4ed7f1f4d4c54e3"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e80c8378d8f3d83cd3164da1ad2df9e37a666cdde7b1cb2298ed0b558064be30"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:36836d6ff945a00b88ba1e4572d721e60b5b8c98c155d465f56ad19d68f23734"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-manylinux_2_31_armv7l.whl", hash = "sha256:bd9b23791fe793e4968dba0c447e12f78e425c59fc0e3b97f6450f4781f3ee60"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:aef65cd602a6d0e0ff6f9930fcb1c8fec60dd2cfcb6facaf4bdb0e5873042db0"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:82b271f5137d07749f7bf32f70b17ab6eaabedd297e75dce75081a24f76eb545"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-musllinux_1_2_armv7l.whl", hash = "sha256:1efde3cae86c8c273f1eb3b287be7d8499420cf2fe7585c41d370d3e790054a5"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:c593052c465475e64bbfe5dbd81680f64a67fdc752c56d7a0ae205dc8aeefe0f"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-musllinux_1_2_riscv64.whl", hash = "sha256:af21eb4409a119e365397b2adbaca4c9ccab56543a65d5dbd9f920d6ac29f686"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:84c018e49c3bf790f9c2771c45e9313a08c2c2a6342b162cd650258b57817706"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:dd915403e231e6b1809fe9b6d9fc55cf8fb5e02765ac625d9cd623342a7905d7"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-win32.whl", hash = "sha256:320ade88cfb846b8cd6b4ddf5ee9e80ee0c1f52401f2456b84ae1ae6a1a5f207"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-win_amd64.whl", hash = "sha256:1dc8b0ea451d6e69735094606991f32867807881400f808a106ee1d963c46a83"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:177a0ba5f0211d488e295aaf82707237e331c24788d8d76c96c5a41594723217"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6e0d51f618228538a3e8f46bd246f87a6cd030565e015803691603f55e12afb5"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:14265bfe1f09498b9d8ec91e9ec9fa52775edf90fcbde092b25f4a33d444fea9"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:87fad7d9ba98c86bcb41b2dc8dbb326619be2562af1f8ff50776a39e55721c5a"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f22dec1690b584cea26fade98b2435c132c1b5f68e39f5a0b7627cd7ae31f1dc"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-manylinux_2_31_armv7l.whl", hash = "sha256:d61f00a0869d77422d9b2aba989e2d24afa6ffd552af442e0e58de4f35ea6d00"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:6370e8686f662e6a3941ee48ed4742317cafbe5707e36406e9df792cdb535776"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:a6c5863edfbe888d9eff9c8b8087354e27618d9da76425c119293f11712a6319"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:ed065083d0898c9d5b4bbec7b026fd755ff7454e6e8b73a67f8c744b13986e24"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:2cd4a60d0e2fb04537162c62bbbb4182f53541fe0ede35cdf270a1c1e723cc42"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:813c0e0132266c08eb87469a642cb30aaff57c5f426255419572aaeceeaa7bf4"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:07d9e39b01743c3717745f4c530a6349eadbfa043c7577eef86c502c15df2c67"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c0f081d69a6e58272819b70288d3221a6ee64b98df852631c80f293514d3b274"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-win32.whl", hash = "sha256:8751d2787c9131302398b11e6c8068053dcb55d5a8964e114b6e196cf16cb366"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-win_amd64.whl", hash = "sha256:12a6fff75f6bc66711b73a2f0addfc4c8c15a20e805146a02d147a318962c444"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-win_arm64.whl", hash = "sha256:bb8cc7534f51d9a017b93e3e85b260924f909601c3df002bcdb58ddb4dc41a5c"}, - {file = "charset_normalizer-3.4.7-py3-none-any.whl", hash = "sha256:3dce51d0f5e7951f8bb4900c257dad282f49190fdbebecd4ba99bcc41fef404d"}, - {file = "charset_normalizer-3.4.7.tar.gz", hash = "sha256:ae89db9e5f98a11a4bf50407d4363e7b09b31e55bc117b4f7d80aab97ba009e5"}, -] - -[[package]] -name = "click" -version = "8.4.1" -description = "Composable command line interface toolkit" -optional = false -python-versions = ">=3.10" -groups = ["main", "docs"] -files = [ - {file = "click-8.4.1-py3-none-any.whl", hash = "sha256:482be17c6991b8c19c5429a1e995d9b0efdbb63172824c41f99965dc0ade8ec2"}, - {file = "click-8.4.1.tar.gz", hash = "sha256:918b5633eddf6b41c32d4f454bf0de810065c74e3f7dbf8ee5452f8be88d3e96"}, + {file = "charset_normalizer-3.5.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:195c26fb65950f8fce54e26349852b7bdd7c5f120aeefbcc440b8a20faaed4a3"}, + {file = "charset_normalizer-3.5.2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9373ad13ef0d2c0fb761e04e55bfdee5a08b52cef2c882c8fbe9935b1517152e"}, + {file = "charset_normalizer-3.5.2-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:ddf19c062bea7a0cc80f519243d2c01dd091be0cf952a0750d4ad576709559f5"}, + {file = "charset_normalizer-3.5.2-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:3d14b50de6bf4d0edf857a9386836846f982b8f524e188e2e68b96d702bcf4aa"}, + {file = "charset_normalizer-3.5.2-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:28a15fdad492a99b6eccfaaed66ef3f74050680545ea61ec8b2f4c538f1f1320"}, + {file = "charset_normalizer-3.5.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8a893cc101149f80a653f82062ebc95b34525a2614382e1da5458fe7c6997249"}, + {file = "charset_normalizer-3.5.2-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:619799369eeef6366ed3e8755a5670f4f2f0fb6b30a0fd7264dc0fdc2357058e"}, + {file = "charset_normalizer-3.5.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:447441e76ec720b15e64418d32e092297340387053047c7c694f579efb0ee1d9"}, + {file = "charset_normalizer-3.5.2-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:62588a277bfb59def052abd940703fa35107152bf479781a878617d60faf8fb5"}, + {file = "charset_normalizer-3.5.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:44bd4fbb29dfbeba60e7d2bd000c59e4b21ddb3cc53912b14048d37092706d7c"}, + {file = "charset_normalizer-3.5.2-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:30fcd120b732aa79317f08dee04d7de0847822e4cf7ee0e9f445bb958832252c"}, + {file = "charset_normalizer-3.5.2-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:50e3adfb96fc189eb27b1cf62d3b598b89b4bb0420d93a3d3e42e137409011be"}, + {file = "charset_normalizer-3.5.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b736353c0a625bbd5fcec108576e2385db3496f4f771f785ff32e108d3c3bc45"}, + {file = "charset_normalizer-3.5.2-cp310-cp310-win32.whl", hash = "sha256:f5833ad231be5eb6553de524a70f48d71b2c8563101750531e0b80184e175cd4"}, + {file = "charset_normalizer-3.5.2-cp310-cp310-win_amd64.whl", hash = "sha256:1461ac396c4fdb983a675f20aa555624f0ee18ac83d832b9244ffff3d8055275"}, + {file = "charset_normalizer-3.5.2-cp310-cp310-win_arm64.whl", hash = "sha256:c6708715abcf3c73b99508253e961a9967f02fe536532834149574eda6de0d1c"}, + {file = "charset_normalizer-3.5.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:3d21b8b13c7592db2ac5e544a6d83187b995257472b0c9e8351b6d507ae37ed6"}, + {file = "charset_normalizer-3.5.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d760fe2a4d7c3b226cb9026d6a842868d52a7901bd98420e1baf14e80da85cf5"}, + {file = "charset_normalizer-3.5.2-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c9790464842f85f437dbbb54417eda1e0e6bfc52dd8d22d6fd1c994b73b2dc74"}, + {file = "charset_normalizer-3.5.2-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4685902cf26edf013ed7a3da0f426ebba7a00ebb9541386d835afbf002c11cab"}, + {file = "charset_normalizer-3.5.2-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4495c5002a7b28557e7e222e77e0b661183e432b7d6d2e788101e3f240e05b8c"}, + {file = "charset_normalizer-3.5.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:211d5a3eb6af8f513b8d4ca19a8c1b7accab1b5f0d3175f9826b03c1a920dc1f"}, + {file = "charset_normalizer-3.5.2-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ef4fcbf3327382cd4c9f540babd61248208af7b93eec4de397b4d5f58a09e288"}, + {file = "charset_normalizer-3.5.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:bd16aabe4a02a297c23417aa17ac6299dbd8c49f673bcd645b4929b11f5a4400"}, + {file = "charset_normalizer-3.5.2-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:fb9e68df06293761f9fe66ade60a9bc6d0f5e42b8acf2939a9158af86ab0e5bd"}, + {file = "charset_normalizer-3.5.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:59f63901b0031c3136cf64704dcb21de0bbae62ce2c9529bc39d27665463de37"}, + {file = "charset_normalizer-3.5.2-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:304d5463e65a35d7bb0850550e0780395395f6fcf452f04db7d5ca7cecc425ac"}, + {file = "charset_normalizer-3.5.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:9cf9b1a857e25c4baceeb3624e92a56df3668f398c4acba74e174d81fb4d1d3a"}, + {file = "charset_normalizer-3.5.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:114e4d0c92d618409ed82a99e22b5c5e768fe995f2973f78265f4524f49d4640"}, + {file = "charset_normalizer-3.5.2-cp311-cp311-win32.whl", hash = "sha256:2625388c6c754520c37abaf3b41eb34d1cc4a373f457898f08606c8e362b891d"}, + {file = "charset_normalizer-3.5.2-cp311-cp311-win_amd64.whl", hash = "sha256:87e50a3e7cb90af586b6c5faf23e302a970415ac73bd7bd90a515a04b427ef96"}, + {file = "charset_normalizer-3.5.2-cp311-cp311-win_arm64.whl", hash = "sha256:254eb48b9fa5ee9898a3c445825a1f340fe53712a098904b39b0bddba8ea3cb1"}, + {file = "charset_normalizer-3.5.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:ed2a239c0ea213acc1908150a3037257083c7c083128f1a4cec2ec4b97dca491"}, + {file = "charset_normalizer-3.5.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b91363207bd9dc966a691e959bb47f64b30f7ac4b072be9968b366982f7db77c"}, + {file = "charset_normalizer-3.5.2-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:38a873987f3be698494da8b2e3085e29da02da7b633dce73e79c699a113d7bf0"}, + {file = "charset_normalizer-3.5.2-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:355ad8011081dec5412240c087a9a0c9d4d5039f3ed11a3f13e18c2b29b56c51"}, + {file = "charset_normalizer-3.5.2-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ee21e28f0430bd6dc9086c6e525d5e818a44a5ad19720c8a0ef766792f3eb5e5"}, + {file = "charset_normalizer-3.5.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3d31298449090ab8d47b7b1b2a555ff73cac7ed438a08b7ac160980c7ebed649"}, + {file = "charset_normalizer-3.5.2-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:5cde776b7cc66e4f6c99612cea4aa7269aa65863f7a15841b2c264f103822f4e"}, + {file = "charset_normalizer-3.5.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ae4f5fea5b8b8ccff88238cc8569303e5ee95efae67fa62922a311397a71f346"}, + {file = "charset_normalizer-3.5.2-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:f7d486c83842422badd511868fd8a9a20e9407ace71564b6af47ce7e60a336c1"}, + {file = "charset_normalizer-3.5.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:11a4d68a6ecda3292cb1e50239e111543ba5d709bb62a6b4ea1afcfa729d8875"}, + {file = "charset_normalizer-3.5.2-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:d6734d2ef8a50fbf8445c139477da401f50d62a0606bf00e20ec6d87773fefb1"}, + {file = "charset_normalizer-3.5.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:a815775b6c38d4e0ff7bcffbeba67feded90202bb6a226b8dd35f1c855217413"}, + {file = "charset_normalizer-3.5.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:23851fb4e1b85ed3f6c2a27b777cdfe2e19fb5b38429a8faf38c7542b7665869"}, + {file = "charset_normalizer-3.5.2-cp312-cp312-win32.whl", hash = "sha256:db19d07e2e0129e974a0e65d0064fc222a446cd5122c2fd4184d2af9fc734a9e"}, + {file = "charset_normalizer-3.5.2-cp312-cp312-win_amd64.whl", hash = "sha256:780fbe7cab297b81dad9fb8dc5eb003c0468ffb0d9e5f65068c53a34661a96bc"}, + {file = "charset_normalizer-3.5.2-cp312-cp312-win_arm64.whl", hash = "sha256:e2af3aad578aa6bd1384bcf4750fc285e5a9de53f40b7d41e5a0bf748edeb2b3"}, + {file = "charset_normalizer-3.5.2-cp313-cp313-android_24_arm64_v8a.whl", hash = "sha256:ed905975ab14056a2e5eb1c376cb2e1ebc5396baf84163939c518556fccde9f5"}, + {file = "charset_normalizer-3.5.2-cp313-cp313-android_24_x86_64.whl", hash = "sha256:a66c3bc5ab1f0ff2164fc9965ddd611ff0802173f4b9d24554c563f6ab7e1d6e"}, + {file = "charset_normalizer-3.5.2-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:d2374b62878abb00cd8309b32af6c0b715cd02dec0ca74ef12e5069bdc64144a"}, + {file = "charset_normalizer-3.5.2-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:d376bbd28b3a8999db1a103b3b388aee6f1ddeb3e51bc2172993efdcd86e064d"}, + {file = "charset_normalizer-3.5.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:6045373d5a89a5ec71afde535db987ca28e76dfa276c2d4c818265b375d4b055"}, + {file = "charset_normalizer-3.5.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:849df64e889b2e17230d58410a03dba311a65b163508fd33679b2b737d4b7858"}, + {file = "charset_normalizer-3.5.2-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:15c44f7edfd477b06f517a5cc317fc1707edb9de2c865f43d4b6513907473234"}, + {file = "charset_normalizer-3.5.2-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a89012d6d5476ee112d20d998570ed58df2260a852afb1758809cd6900411d21"}, + {file = "charset_normalizer-3.5.2-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0c951d5e6dd9c2ff60609476752bee49da4206adde960ebc247766937f72e718"}, + {file = "charset_normalizer-3.5.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7218e8f32b0956cfcd048fd42d9d5779809745ca1d86113ca56f66e7ae1549c4"}, + {file = "charset_normalizer-3.5.2-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a19a731138fc27d5682277d3b9df22855cea1239bce7fcec5f78f42ef2d1f3c3"}, + {file = "charset_normalizer-3.5.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:62603db9a7caa0802eaa28c1c46fecd7b3a263a774069c24c3c28c302448721c"}, + {file = "charset_normalizer-3.5.2-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:b6856554c4f44d79fc2307d5768854310a8f0096e501c75637542c82292b0429"}, + {file = "charset_normalizer-3.5.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:1bc0baf5ef96b6ede57d47f4b8fe4d9d84019c3bfcbeb20a41edc6a6ee341f1f"}, + {file = "charset_normalizer-3.5.2-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:56bc200a365efb37383b7852e4cc5898d3b2da5987289b543956cf8cad71018a"}, + {file = "charset_normalizer-3.5.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:2c9ad19a6cfcd5ea5c0d41161d22f9df1dcc277e9bef2751391334546a314c00"}, + {file = "charset_normalizer-3.5.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e243bd13217235fc7290c621941c3f5cc8b66e4872495be821d7436ba2fb838d"}, + {file = "charset_normalizer-3.5.2-cp313-cp313-pyemscripten_2025_0_wasm32.whl", hash = "sha256:a090bb2c68df85450502e3e20d665e3a5af9c65a84d6508ed477badd49166fd3"}, + {file = "charset_normalizer-3.5.2-cp313-cp313-win32.whl", hash = "sha256:2b7b3bbfb4fe8ef40600792d762fbaa9057559f9d3fad209525b7a22b99e91fd"}, + {file = "charset_normalizer-3.5.2-cp313-cp313-win_amd64.whl", hash = "sha256:78456a747de8dc58360ffa581f30a002baf5aa28cb262536545e91f113ed7639"}, + {file = "charset_normalizer-3.5.2-cp313-cp313-win_arm64.whl", hash = "sha256:11912e4bb14baae7c5d8791aa55ba0a3a03ec6729073307b0f57270abaa713d3"}, + {file = "charset_normalizer-3.5.2-cp314-cp314-android_24_arm64_v8a.whl", hash = "sha256:1afb975bd5d68d5ce9f6b6d44fdf2f7e34b895a35e95708a7a91b20a3b51d187"}, + {file = "charset_normalizer-3.5.2-cp314-cp314-android_24_x86_64.whl", hash = "sha256:bbbfc8e28816f19d7c0f1816664980c0a9875d01b27cdf8eedddb639d9e108ad"}, + {file = "charset_normalizer-3.5.2-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:7967d08cf06dee78443b874f98c98036f624f3a4e73e11f9f64f5be4d25393cf"}, + {file = "charset_normalizer-3.5.2-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:4c2b5031f63e331e3839b40aed2dd6f191e9c07edbde303e7876846ea1946995"}, + {file = "charset_normalizer-3.5.2-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:fcff63213e8e6e47770541a4607175404f47cbb3ebea7b6058cc82d524a0e424"}, + {file = "charset_normalizer-3.5.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8d86d6fc60743dc916eb79e2eb1ec4818e21e427731543af40a3021851174a13"}, + {file = "charset_normalizer-3.5.2-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:7a881931aa470808df94a8c380eed2bbbc76cd9dc622310f99665658c821eb6d"}, + {file = "charset_normalizer-3.5.2-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8024d00c3faf3fc0c16e07a69f4405e8eac7cc0ab15f65fe6cf43827c4cf72b4"}, + {file = "charset_normalizer-3.5.2-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4d48f2d08b9de5864e2c8744d4461b862fb149a18274abc8b698c45975573438"}, + {file = "charset_normalizer-3.5.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:34276fd796040bf0993ab33a369aa572e6979c7aab225a88893667ad8eac8f7a"}, + {file = "charset_normalizer-3.5.2-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0521c5665880b33d603717defa76c094048900010897909952397feb3039da56"}, + {file = "charset_normalizer-3.5.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:eff0ac9dbe711a4aee69bf04a83896aa9b85f19641264053a9f6d48573abb7dd"}, + {file = "charset_normalizer-3.5.2-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:1503bccbeb36d5527790c3930327704c39af22de3112f1b1666a9f3ce15ee204"}, + {file = "charset_normalizer-3.5.2-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:52aa6992700996af31f375de0c6bacd402b0097fe40b53c426b9f51a90ebabc7"}, + {file = "charset_normalizer-3.5.2-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:e09a3942ecbdee5cce73ea9d42da82b81b72ac1bf031ce069b93b5adf4eac8cd"}, + {file = "charset_normalizer-3.5.2-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:c7c9ab723cde841fefb34efbad91e87f00a674b1fe1cd0784fde742bf2c154dc"}, + {file = "charset_normalizer-3.5.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ddc7dacc8ece3a182e7f15cb862d1fd616b46d076cb1ae9dd232b2c38b655874"}, + {file = "charset_normalizer-3.5.2-cp314-cp314-pyemscripten_2026_0_wasm32.whl", hash = "sha256:ee43c17b173d46a3212baa6ead3ae258eeabdae48c263a01ccf0218c366dd655"}, + {file = "charset_normalizer-3.5.2-cp314-cp314-win32.whl", hash = "sha256:4f87960d57feabfb618e4e0af6e7371645fa26a277860739d6e5d6e0012c92f0"}, + {file = "charset_normalizer-3.5.2-cp314-cp314-win_amd64.whl", hash = "sha256:e4e81e09c1578b8df602e3db08b0b3ea0a6947ad612f52bf8dc5ea8d47691f0c"}, + {file = "charset_normalizer-3.5.2-cp314-cp314-win_arm64.whl", hash = "sha256:80d02b6f04e92601a081dd97b23d3128033098bff5d35d392ddcc0476ea11253"}, + {file = "charset_normalizer-3.5.2-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:dca9ab98072a5a54ebacebdc45f53e645336b320c667410b061be1ca588ae709"}, + {file = "charset_normalizer-3.5.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f0aa869112ef88429ae17820d99c3dd9504c9e9c671d3c246f3d7442cb051084"}, + {file = "charset_normalizer-3.5.2-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c0afc6800ba57ccc350374c5bd6150419915d95ce93cdbab2d783d75eaf30ecb"}, + {file = "charset_normalizer-3.5.2-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7dcd882da75ef9adf94903b1e3b9419e8aa8fb4c7396822b834b9ef7fb96954f"}, + {file = "charset_normalizer-3.5.2-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2e06a3a98f916dd41d27f3105e02e7a40181c98c94b9158733d03a6f80506c09"}, + {file = "charset_normalizer-3.5.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6bd128f206a7752ae1f2ab6c61bf8a24ba28913a10df8b14c2637b973ff97a80"}, + {file = "charset_normalizer-3.5.2-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c8f3d67aeaf55f017982b73683f0e7342ba2f6635a78f69ce89ebb26aa411e5c"}, + {file = "charset_normalizer-3.5.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:fe9753dfee015c570d73df76f899f18444d41388bffcde097deba51c4fadbb9f"}, + {file = "charset_normalizer-3.5.2-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:92888bb3187c5ba50500b00b3b310c9f2c651709d28036077680cb5255450a03"}, + {file = "charset_normalizer-3.5.2-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:d008d90a7f2471519aef0c90dfbe73b3e6e4d5e66ac48e19154c17e89e98b604"}, + {file = "charset_normalizer-3.5.2-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:31f3930700408d211f13378ccbe1c40845d8da54bd0681fac3a9b5aae81c7aa8"}, + {file = "charset_normalizer-3.5.2-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:2a925889534b3748302dae5dead07cc13480de1dac3aea80a941b729b471ef93"}, + {file = "charset_normalizer-3.5.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:f5ec61164adcec446f8969a3358ec3f9b26bbda3b9213e5586d219afa8df2915"}, + {file = "charset_normalizer-3.5.2-cp314-cp314t-win32.whl", hash = "sha256:598a11a2c7ebaa5334bf698bf29568c9c390abac6a154d8170fedecd1cea38c5"}, + {file = "charset_normalizer-3.5.2-cp314-cp314t-win_amd64.whl", hash = "sha256:7fdde2c9fd9e3eca40631e024664cf2584272cc8f96308cbe5fdfc930f51d8bc"}, + {file = "charset_normalizer-3.5.2-cp314-cp314t-win_arm64.whl", hash = "sha256:d1befeed746d247c81127bb14de9dc3d30edb6e5976d34f83f86ed262b1d9105"}, + {file = "charset_normalizer-3.5.2-cp315-cp315-macosx_10_15_universal2.whl", hash = "sha256:87475fabc8d9996fd9c27debb395e642e8c838d78a00b6e932227a0e06b81e26"}, + {file = "charset_normalizer-3.5.2-cp315-cp315-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9409a8bf35cf78353942504b24a57de3d75b708997a1e4bd8db71ac8633ce364"}, + {file = "charset_normalizer-3.5.2-cp315-cp315-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:498dc3188ca05a68231ac3fdbfc7f57eb67e1343c30e0fea17f8218c1599b253"}, + {file = "charset_normalizer-3.5.2-cp315-cp315-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e242bb1c5e76e97dfa9e7f209a71e93a01d7f19ffdd5cfbb2e2d55b4f08f8ab0"}, + {file = "charset_normalizer-3.5.2-cp315-cp315-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:def79fa35ef0cef8d2accec024f4fdc7ead3012ff02f5215c783f39f03ef8cfc"}, + {file = "charset_normalizer-3.5.2-cp315-cp315-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3df041de8887954562c9b261cba85ca0e9ded74048daf125f45edcfaa4832229"}, + {file = "charset_normalizer-3.5.2-cp315-cp315-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:04851f73ae72b8413dddadb16a49dfee95263553741fd42d546f7d66907e6be5"}, + {file = "charset_normalizer-3.5.2-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:183b88127acdb4fabe59d951ab424faf1af7b63cdbb5f776186c1ea2ffcaed98"}, + {file = "charset_normalizer-3.5.2-cp315-cp315-musllinux_1_2_armv7l.whl", hash = "sha256:16fa0eccf81304b79c5cd87f9271c3b85dd9dd99245e4422ae9c0dd45e0f99d3"}, + {file = "charset_normalizer-3.5.2-cp315-cp315-musllinux_1_2_ppc64le.whl", hash = "sha256:7441d755b7ab94f8d4eb3e43ec05482d760842fd263d003a99102d742cd835e2"}, + {file = "charset_normalizer-3.5.2-cp315-cp315-musllinux_1_2_riscv64.whl", hash = "sha256:ca403d7e4798f525fdfc78e258820419cbbd0f0ecbab9de7840e3c017cf6b8cf"}, + {file = "charset_normalizer-3.5.2-cp315-cp315-musllinux_1_2_s390x.whl", hash = "sha256:df29a0a7107f7011e77f4eebdddec4c7331e24d787a0b21a46d63bdf7445da95"}, + {file = "charset_normalizer-3.5.2-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:f3c96f633825733f735c5a9cf21d21a257d8e1edf0b1cee0a064b9c424ca0f7d"}, + {file = "charset_normalizer-3.5.2-cp315-cp315-win32.whl", hash = "sha256:281cb91036248400f4cc957495cccd44c275c2e0c5854f7e45ac5cf7dc193847"}, + {file = "charset_normalizer-3.5.2-cp315-cp315-win_amd64.whl", hash = "sha256:89b53f3cda69831909888e0494f4fa0bcd3537e3e138dabeb620bd6ad946bae8"}, + {file = "charset_normalizer-3.5.2-cp315-cp315-win_arm64.whl", hash = "sha256:6be488a102b8cf28d0391d8c4ba7748938ae28b78ad901f8585520fca33ead1a"}, + {file = "charset_normalizer-3.5.2-cp315-cp315t-macosx_10_15_universal2.whl", hash = "sha256:915563965d418f986e7e145accc592eae9e1a1be3566ff98a05d7a9ec42a76e1"}, + {file = "charset_normalizer-3.5.2-cp315-cp315t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:65cd72beeeca9d3aaea1201e5923859f308f952f9c71de93f06063c79f0f7a3b"}, + {file = "charset_normalizer-3.5.2-cp315-cp315t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:b7fd005a73d9e657273b7a10dc71a9e03c8fb9ee6999798d6918ce095b81ac7f"}, + {file = "charset_normalizer-3.5.2-cp315-cp315t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e54da4baf05720032d527874d40b65fa4d7e5c6c6a43d0c3adbeffcaf275a2b3"}, + {file = "charset_normalizer-3.5.2-cp315-cp315t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:124fbf1a8ff966d87ae05bb8bd45a71f966055ed8bba320d0c7cf450bc5f4d0e"}, + {file = "charset_normalizer-3.5.2-cp315-cp315t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:28b4f0d66fb834ff90f28209ac7bce77868c45d8c93e26f906709d9b7c2e1af9"}, + {file = "charset_normalizer-3.5.2-cp315-cp315t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:58ca3755ee7ff7f59b57789ec9833c9de9ea275405cdd240eda1f193112e398a"}, + {file = "charset_normalizer-3.5.2-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:443eae2bf318abeaf6f15d785138f71fd6de770e99a92158b8b814265e079115"}, + {file = "charset_normalizer-3.5.2-cp315-cp315t-musllinux_1_2_armv7l.whl", hash = "sha256:58f361dcbab699cf8f42db3f47c8e7fd1036f138c23a5d08de9fde5f425a730c"}, + {file = "charset_normalizer-3.5.2-cp315-cp315t-musllinux_1_2_ppc64le.whl", hash = "sha256:1b4cbc7c3491ccb4aa17fcd8165649d01cf39f76de1696da8631b5f71b85401d"}, + {file = "charset_normalizer-3.5.2-cp315-cp315t-musllinux_1_2_riscv64.whl", hash = "sha256:ba0b1d2620edf869789c3879223f52bf2afc5d31b3cb47cc57b3a12c05e2aa9d"}, + {file = "charset_normalizer-3.5.2-cp315-cp315t-musllinux_1_2_s390x.whl", hash = "sha256:5e2b6b57e9733d39f0c9fd3185efa6b8e29652c4cd8fe94180272cf6ed9a78c4"}, + {file = "charset_normalizer-3.5.2-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:51cf45226a9b588d0d2b4880c62d686934b63ab0bd79ca23ab0e9762eb27441b"}, + {file = "charset_normalizer-3.5.2-cp315-cp315t-win32.whl", hash = "sha256:5fb29fb8cd1a46c27a1bf9613ad5ec2599310d46b4025d9556404a6b6a292800"}, + {file = "charset_normalizer-3.5.2-cp315-cp315t-win_amd64.whl", hash = "sha256:a192e2c40070d92c3ccf777e3a5c4ff515573cd2bb7ed0c537fdadbbec5bbf21"}, + {file = "charset_normalizer-3.5.2-cp315-cp315t-win_arm64.whl", hash = "sha256:749e97e1b32313717a565abbe321bc2190bc8b35f1a67e4cdbc7c56c8d8ffe58"}, + {file = "charset_normalizer-3.5.2-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:4275811936e2f06feff5e598fb42a1b7ae852da8e39605211892b56b81a34efd"}, + {file = "charset_normalizer-3.5.2-cp37-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:1c50fe28bbc2ced33386f298650d91218076c05420e6cbd790b913adc41659e7"}, + {file = "charset_normalizer-3.5.2-cp37-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d19fbd981a488e22cd04883659ca6b08f50b5974f9fd7c95655ef6a043e5893f"}, + {file = "charset_normalizer-3.5.2-cp37-abi3-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:0fed1d06615f022ee3b13caf5e8b180cfea32bb2c5aded8a9d44277afc040f93"}, + {file = "charset_normalizer-3.5.2-cp37-abi3-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:838dcc90063569a0448120554591a1d6c4a4ffe11babf048908793154ab86ade"}, + {file = "charset_normalizer-3.5.2-cp37-abi3-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2ce45c6627b22c47e390bc91a41c3d13032192e699fa0bea96e9671b373d69b0"}, + {file = "charset_normalizer-3.5.2-cp37-abi3-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0774bf9bf620249fee3e0b8b9fd3065de213be30f3aa94ce2494b3b638949e26"}, + {file = "charset_normalizer-3.5.2-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:1db38f4c5496827c1a501846d64d14c3b80c7e6714e406cd7dc36a9899fa1011"}, + {file = "charset_normalizer-3.5.2-cp37-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:304d8e4d493af723536393eee0c689eb7813f4a474c8b479dee63f1fdd98f621"}, + {file = "charset_normalizer-3.5.2-cp37-abi3-musllinux_1_2_ppc64le.whl", hash = "sha256:9b7f416ff0978e2f2249330527f0ad6fa02f4932e6199692d3b52da2048c19e4"}, + {file = "charset_normalizer-3.5.2-cp37-abi3-musllinux_1_2_riscv64.whl", hash = "sha256:01077390b03f7988f11d700a2194e69b119741a86b1a638b1db88891e3eced8e"}, + {file = "charset_normalizer-3.5.2-cp37-abi3-musllinux_1_2_s390x.whl", hash = "sha256:7e841fb9010836c992c9f12fcbd43a831de93a5f726fc1ccd8ca1d0268c5014c"}, + {file = "charset_normalizer-3.5.2-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:9cae88599c7219005d879f98e5ed53341e9a122af585e1091200358a3003d2a0"}, + {file = "charset_normalizer-3.5.2-cp37-abi3-win32.whl", hash = "sha256:01b0c0d2262a9e28e8484a278c7e1b5d650e3ac8cf2683d2967e25899f208bdf"}, + {file = "charset_normalizer-3.5.2-cp37-abi3-win_amd64.whl", hash = "sha256:9f56f72050826f63dcee7a7f55b0a77168cb3bfc553fd405e7f8f9ece75a4036"}, + {file = "charset_normalizer-3.5.2-cp37-abi3-win_arm64.whl", hash = "sha256:40ab6bffa02ae10a0581e6c198be7d2d8ca5c2a0c64e4ed3465d766df457573e"}, + {file = "charset_normalizer-3.5.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:75a3ceed0724d625d64b86ca20aba182e4df462e04c2414fc941c0f523f06aac"}, + {file = "charset_normalizer-3.5.2-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0891b9d3903c5571c03771ca669a4b0ec5618ca722a5c957d3d29cd4e5062848"}, + {file = "charset_normalizer-3.5.2-cp39-cp39-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:fc14a032f813bf5fe624d991960ea83e9715adc27e4c1830a2361eb1d02ac341"}, + {file = "charset_normalizer-3.5.2-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8b2bfab86aa71ae13aa41a6a26aab338e0db2b8bc75434b05aea89e011ff35a4"}, + {file = "charset_normalizer-3.5.2-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:9bde855991b7e362c146535e3136a50bfaffc0487d38b33ca7e5edefc6e23849"}, + {file = "charset_normalizer-3.5.2-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:55ea99acb17b9325618de155a0cd6a2e8f5d10be008113e1d433bbb58db543b2"}, + {file = "charset_normalizer-3.5.2-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:68eb192d85ab8e5f6ec69c2bc6ac0179fbf04a5ac1569d12fbef74883fe102d0"}, + {file = "charset_normalizer-3.5.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:d913de495d90407cd859d263bee2e5d1a4ed3eb6573c04e70d9ec619a7cbed7f"}, + {file = "charset_normalizer-3.5.2-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:3ddacd27458c45bdacd6bd6db644bfb730efbf9e830310186e3045c9c5be8fb2"}, + {file = "charset_normalizer-3.5.2-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:588461c2e8384d309bd63e5826019b6977bc66d629b99ac8737bb795d7b2cb5a"}, + {file = "charset_normalizer-3.5.2-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:e80e6c2f55656b4824d72065abb4ddd6a525c74bd78a0aab5d9fc2cf4fb5af50"}, + {file = "charset_normalizer-3.5.2-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:d4a7319f304a774bed22115bc891618e45f85065ab44ea6acd07d274e750519a"}, + {file = "charset_normalizer-3.5.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:fd1fbe0f116b6e55da77aca2c6ddcddcfac2186cbf78bdebf40fc156efca389d"}, + {file = "charset_normalizer-3.5.2-cp39-cp39-win32.whl", hash = "sha256:93223adc95033dd47133a46ccfc316a0139176fd79085762e27202ec56018f03"}, + {file = "charset_normalizer-3.5.2-cp39-cp39-win_amd64.whl", hash = "sha256:15bb4005af6320d259dc7593ca84a38d7fe06a421dbcf7b910ae23979101e787"}, + {file = "charset_normalizer-3.5.2-cp39-cp39-win_arm64.whl", hash = "sha256:2cc961b171b3f3440f410489ab3573e86aea8736134ebbb40ea1338b7f0831bc"}, + {file = "charset_normalizer-3.5.2-py3-none-any.whl", hash = "sha256:b6b751274acb69d77b3323d6b7dbaa3c7fdfc1eb829b7eb61d262f32e1af9685"}, + {file = "charset_normalizer-3.5.2.tar.gz", hash = "sha256:39de2a259fc954455c57274dc94c79d5842774e1247a016aff30bc0efed0f4ef"}, ] -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} - [[package]] name = "colorama" version = "0.4.6" description = "Cross-platform colored terminal text." optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" -groups = ["main", "dev", "docs"] +groups = ["dev", "docs"] files = [ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] -markers = {main = "platform_system == \"Windows\"", dev = "platform_system == \"Windows\" or sys_platform == \"win32\"", docs = "platform_system == \"Windows\" or sys_platform == \"win32\""} +markers = {dev = "platform_system == \"Windows\" or sys_platform == \"win32\"", docs = "sys_platform == \"win32\""} [[package]] name = "coverage" -version = "7.14.0" +version = "7.16.2" description = "Code coverage measurement for Python" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "coverage-7.14.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:84c32d90bf4537f0e7b4dec9aaa9a938fb8205136b9d2ecf4d7629d5262dc075"}, - {file = "coverage-7.14.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:7c843572c605ab51cfdb5c6b5f2586e2a8467c0d28eca4bdef4ec70c5fecbd82"}, - {file = "coverage-7.14.0-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:0c451757d3fa2603354fdc789b5e58a0e327a117c370a40e3476ba4eabab228c"}, - {file = "coverage-7.14.0-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:3fd43f0616e765ab78d069cf8358def7363957a45cee446d65c502dcfeea7893"}, - {file = "coverage-7.14.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:731e535b1498b27d13594a0527a79b0510867b0ad891532be41cb883f2128e20"}, - {file = "coverage-7.14.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c7492f2d493b976941c7ca050f273cbda2f43c381124f7586a3e3c16d1804fec"}, - {file = "coverage-7.14.0-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:dc38367eaa2abb1b766ac333142bce7655335a73537f5c8b75aaa89c2b987757"}, - {file = "coverage-7.14.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:0a951308cde22cf77f953955a754d04dccb57fe3bb8e345d685778ed9fc1632a"}, - {file = "coverage-7.14.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:fab3877e4ebb06bd9d4d4d00ee53309ee5478e66873c66a382272e3ee33eb7ea"}, - {file = "coverage-7.14.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:b812eb847b19876ebf33fb6c4f11819af05ab6050b0bfa1bc53412ae81779adb"}, - {file = "coverage-7.14.0-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:d9c8ef6ed820c433de075657d72dda1f89a2984955e58b8a75feb3f184250218"}, - {file = "coverage-7.14.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:d128b1bba9361fbaaf6a19e179e6cfd6a9103ce0c0555876f72780acc93efd85"}, - {file = "coverage-7.14.0-cp310-cp310-win32.whl", hash = "sha256:65f267ca1370726ec2c1aa38bbe4df9a71a740f22878d2d4bf59d71a4cd8d323"}, - {file = "coverage-7.14.0-cp310-cp310-win_amd64.whl", hash = "sha256:b34ece8065914f938ed7f2c5872bb865336977a52919149846eac3744327267a"}, - {file = "coverage-7.14.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6a78e2a9d9c5e3b8d4ab9b9d28c985ea66fced0a7d7c2aec1f216e03a2011480"}, - {file = "coverage-7.14.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a1816c505187592dcd1c5a5f226601a549f70365fbd00930ac88b0c225b76bb4"}, - {file = "coverage-7.14.0-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:d8e1762f0e9cbc26ec315471e7b47855218e833cd5a032d706fbf43845d878c7"}, - {file = "coverage-7.14.0-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:9336e23e8bb3a3925398261385e2a1533957d3e760e91070dcb0e98bfa514eed"}, - {file = "coverage-7.14.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9cd1169b2230f9cbe9c638ba38022ed7a2b1e641cc07f7cea0365e4be2a74980"}, - {file = "coverage-7.14.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d1bb3543b58fea74d2cd1abc4054cc927e4724687cb4560cd2ed88d2c7d820c0"}, - {file = "coverage-7.14.0-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a93bac2cb577ef60074999ed56d8a1535894398e2ed920d4185c3ec0c8864742"}, - {file = "coverage-7.14.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:5904abf7e18cddc463219b17552229650c6b79e061d31a1059283051169cf7d5"}, - {file = "coverage-7.14.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:741f57cddc9004a8c81b084660215f33a6b597dbe62c31386b983ee26310e327"}, - {file = "coverage-7.14.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:664123feb0929d7affc135717dbd70d61d98688a08ab1e5ba464739620c6252d"}, - {file = "coverage-7.14.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:c83d2399a51bbec8429266905d33616f04bc5726b1138c35844d5fcd896b2e20"}, - {file = "coverage-7.14.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bcb2e855b87321259a037429288ae85216d191c74de3e79bf57cd2bc0761992c"}, - {file = "coverage-7.14.0-cp311-cp311-win32.whl", hash = "sha256:731dc15b385ac52289743d476245b61e1a2927e803bef655b52bc3b2a75a21f3"}, - {file = "coverage-7.14.0-cp311-cp311-win_amd64.whl", hash = "sha256:bfb0ed8ec5d25e93face268115d7964db9df8b9aae8edcde9ec6b16c726a7cc1"}, - {file = "coverage-7.14.0-cp311-cp311-win_arm64.whl", hash = "sha256:7ebb1c6df9f78046a1b1e0a89674cd4bf73b7c648914eebcf976a57fd99a5627"}, - {file = "coverage-7.14.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7ffd19fc8aed057fd686a17a4935eef5f9859d69208f96310e893e64b9b6ccf5"}, - {file = "coverage-7.14.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:829994cfe1aeb773ca27bf246d4badc1e764893e3bfb98fff820fcecd1ca4662"}, - {file = "coverage-7.14.0-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:b4f07cf7edcb7ec39431a5074d7ea83b29a9f71fcfc494f0f40af4e65180420f"}, - {file = "coverage-7.14.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:ca3d9cf2c32b521bd9518385608787fa86f38daf993695307531822c3430ed67"}, - {file = "coverage-7.14.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:92af52828e7f29d827346b0294e5a0853fa206db77db0395b282918d41e28db9"}, - {file = "coverage-7.14.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7b2bb6c9d7e769360d0f20a0f219603fd64f0c8f97de17ab25853261602be0fb"}, - {file = "coverage-7.14.0-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:1c9ed6ef99f88fb8c14aa8e2bf8eb0fe55fa2edfea68f8675d78741df1a5ac0e"}, - {file = "coverage-7.14.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8231ade007f37959fbf58acc677f26b922c02eda6f0428ea307da0fd39681bf3"}, - {file = "coverage-7.14.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:d8b013632cc1ce1d09dbe4f32667b4d320ec2f54fc326ebeffcd0b0bcc2bb6c4"}, - {file = "coverage-7.14.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:1733198802d71ec4c524f322e2867ee05c62e9e75df86bdca545407a221827d1"}, - {file = "coverage-7.14.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:72a305291fa8ee01332f1aaf38b348ca34097f6aa0b0ef627eef2837e57bbba5"}, - {file = "coverage-7.14.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fcaba850dd317c65423a9d63d88f9573c53b00354d6dd95724576cc98a131595"}, - {file = "coverage-7.14.0-cp312-cp312-win32.whl", hash = "sha256:5ac83957a80d0701310e96d8bec68cdcf4f90a7674b7d13f15a344315b41ab27"}, - {file = "coverage-7.14.0-cp312-cp312-win_amd64.whl", hash = "sha256:70390b0da32cb90b501953716302906e8bcce087cb283e70d8c97729f22e92b2"}, - {file = "coverage-7.14.0-cp312-cp312-win_arm64.whl", hash = "sha256:91b993743d959b8be85b4abf9d5478216a69329c321efe5be0433c1a841d691d"}, - {file = "coverage-7.14.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f2bbb8254370eb4c628ff3d6fa8a7f74ddc40565394d4f7ab791d1fe568e37ef"}, - {file = "coverage-7.14.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:23b81107f46d3f21d0cbce30664fcec0f5d9f585638a67081750f99738f6bf66"}, - {file = "coverage-7.14.0-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:22a7e06a5f11a757cdfe79018e9095f9f69ae283c5cd8123774c788deec8717b"}, - {file = "coverage-7.14.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:9d1aa57a1dc8e05bdc42e81c5d671d849577aeedf279f4c449d6d286f9ed88ca"}, - {file = "coverage-7.14.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:90c1a51bcfddf645b3bb7ec333d9e94393a8e94f55642380fa8a9a5a9e636cb7"}, - {file = "coverage-7.14.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a841fae2fadcae4f438d43b6ccc4aac2ad609f47cdb6cfdce60cbb3fe5ca7bc2"}, - {file = "coverage-7.14.0-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c79d2319cabef1fe8e86df73371126931550804738f78ad7d31e3aad85a67367"}, - {file = "coverage-7.14.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:1b23b0c6f0b1db6ad769b7050c8b641c0bf215ded26c1816955b17b7f26edfa9"}, - {file = "coverage-7.14.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:55d3089079ce181a4566b1065ab28d2575eb76d8ac8f81f4fcda2bf037fee087"}, - {file = "coverage-7.14.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:49c005cba1e2f9677fb2845dcdf9a2e72a52a17d63e8231aaaae35d9f50215ef"}, - {file = "coverage-7.14.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:9117377b823daa28aa8635fbb08cda1cd6be3d7143257345459559aeef852d52"}, - {file = "coverage-7.14.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7b79d646cf46d5cf9a9f40281d4441df5849e445726e369006d2b117710b33fe"}, - {file = "coverage-7.14.0-cp313-cp313-win32.whl", hash = "sha256:fb609b3658479e33f9516d46f1a89dbb9b6c261366e3a11844a96ec487533dae"}, - {file = "coverage-7.14.0-cp313-cp313-win_amd64.whl", hash = "sha256:0773d8329cf32b6fd222e4b52622c61fe8d503eb966cfc8d3c3c10c96266d50e"}, - {file = "coverage-7.14.0-cp313-cp313-win_arm64.whl", hash = "sha256:b4e26a0f1b696faf283bffe5b8569e44e336c582439df5d53281ab89ee0cba96"}, - {file = "coverage-7.14.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:953f521ca9445300397e65fda3dca58b2dbd68fee983777420b57ac3c77e9f90"}, - {file = "coverage-7.14.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:98af83fd65ae24b1fdd03aaead967a9f523bcd2f1aab2d4f3ffda65bb568a6f1"}, - {file = "coverage-7.14.0-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:668b92e6958c4db7cf92e81caac328dfbbdbb215db2850ad28f0cbe1eea0bfbd"}, - {file = "coverage-7.14.0-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:9fbd898551762dea00d3fef2b1c4f99afd2c6a3ff952ea07d60a9bd5ed4f34bc"}, - {file = "coverage-7.14.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:68af363c07ecd8d4b7d4043d85cb376d7d227eceb54e5323ee45da73dbd3e426"}, - {file = "coverage-7.14.0-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6e57054a583da8ac55edf24117ea4c9133032cfc4cf72aa2d48c1e5d4b52f899"}, - {file = "coverage-7.14.0-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cc3499459bbcdd51a65b64c35ab7ed2764eaf3cba826e0df3f1d7fe2e102b70b"}, - {file = "coverage-7.14.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:45899ec2138a4346ed34d601dedf5076fb74edf2d1dd9dc76a78e82397edee90"}, - {file = "coverage-7.14.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:8767486808c436f05b23ab98eb963fb29185e32a9357a166971685cb3459900f"}, - {file = "coverage-7.14.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:a3b5ddfd6aa7ddad53ee3edb231e88a2151507a43229b7d71b953916deca127d"}, - {file = "coverage-7.14.0-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:63df0fe568e698e1045792399f8ab6da3a6c2dce3182813fb92afa2641087b47"}, - {file = "coverage-7.14.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:827d6397dbd95144939b18f89edf31f63e1f99633e8d5f32f22ba8bdda567477"}, - {file = "coverage-7.14.0-cp313-cp313t-win32.whl", hash = "sha256:7bf43e000d24012599b879791cff41589af90674722421ef11b11a5431920bab"}, - {file = "coverage-7.14.0-cp313-cp313t-win_amd64.whl", hash = "sha256:3f5549365af25d770e06b1f8f5682d9a5637d06eb494db91c6fa75d3950cc917"}, - {file = "coverage-7.14.0-cp313-cp313t-win_arm64.whl", hash = "sha256:6d160217ec6fe890f16ad3a9531761589443749e448f91986c972714fad361c8"}, - {file = "coverage-7.14.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:9aed9fa983514ca032790f3fe0d1c0e42ca7e16b42432af1706b50a9a46bef5d"}, - {file = "coverage-7.14.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ba3b8390db29296dbbf49e91b6fe08f990743a90c8f447ba4c2ffc29670dfa63"}, - {file = "coverage-7.14.0-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3a5d8e876dfa2f102e970b183863d6dedd023d3c0eeca1fe7a9787bc5f28b212"}, - {file = "coverage-7.14.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:5ebb8f4614a3787d567e610bbfdf96a4798dd69a1afb1bd8ad228d4111fe6ff3"}, - {file = "coverage-7.14.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b9bf47223dd8db3d4c4b2e443b02bace480d428f0822c3f991600448a176c97"}, - {file = "coverage-7.14.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:3485a836550b303d006d57cc06e3d5afaabc642c77050b7c985a97b13e3776b8"}, - {file = "coverage-7.14.0-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3e7e88110bae996d199d1693ca8ec3fd52441d426401ae963437598667b4c5eb"}, - {file = "coverage-7.14.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:15228a6800ce7bdf1b74800595e56db7138cecb338fdbf044806e10dcf182dfe"}, - {file = "coverage-7.14.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:9d26ac7f5398bafc5b57421ad994e8a4749e8a7a0e62d05ec7d53014d5963bfa"}, - {file = "coverage-7.14.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:2fb73254ff43c911c967a899e1359bc5049b4b115d6e8fbdde4937d0a2246cd5"}, - {file = "coverage-7.14.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:454a380af72c6adada298ed270d38c7a391288198dbfb8467f786f588751a90c"}, - {file = "coverage-7.14.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:65c86fb646d2bd2972e96bd1a8b45817ed907cee68655d6295fe7ec031d04cca"}, - {file = "coverage-7.14.0-cp314-cp314-win32.whl", hash = "sha256:6a6516b02a6101398e19a3f44820f69bab2590697f7def4331f668b14adaf828"}, - {file = "coverage-7.14.0-cp314-cp314-win_amd64.whl", hash = "sha256:45e0f79d8351fa76e256716df91eab12890d32678b9590df7ae1042e4bd4cf5d"}, - {file = "coverage-7.14.0-cp314-cp314-win_arm64.whl", hash = "sha256:4b899594a8b2d81e5cc064a0d7f9cac2081fed91049456cae7676787e41549c9"}, - {file = "coverage-7.14.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:f580f8c80acd94ac72e863efe2cab791d8c38d153e0b463b92dfa000d5c84cd1"}, - {file = "coverage-7.14.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a2bd259c442cd43c49b30fbafc51776eb19ea396faf159d26a83e6a0a5f13b0c"}, - {file = "coverage-7.14.0-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:a706b908dfa85538863504c624b237a3cc34232bf403c057414ebfdb3b4d9f84"}, - {file = "coverage-7.14.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:7333cd944ee4393b9b3d3c1b598c936d4fc8d70573a4c7dacfec5590dd50e436"}, - {file = "coverage-7.14.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0f162bc9a15b82d947b02651b0c7e1609d6f7a8735ca330cfadec8481dd97d5a"}, - {file = "coverage-7.14.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:362cb78e01a5dc82009d88004cf60f2e6b6d6fcbfdec05b05af73b0abf40118f"}, - {file = "coverage-7.14.0-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:acebd068fca5512c3a6fde9c045f901613478781a73f0e82b307b214daef23fb"}, - {file = "coverage-7.14.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:29fe3da551dface75deb2ccbf87b6b66e2e7ef38f6d89050b428be94afff3490"}, - {file = "coverage-7.14.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:b4cc4fce8672fffcb09b0eafc167b396b3ba53c4a7230f54b7aaffbf6c835fa9"}, - {file = "coverage-7.14.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:5d4a51aad8ba8bdcd2b8bd8f03d4aca19693fa2327a3470e4718a25b03481020"}, - {file = "coverage-7.14.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:9f323af3e1e4f68b60b7b247e37b8515563a61375518fa59de1af48ba28a3db6"}, - {file = "coverage-7.14.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:1a0abc7342ea9711c469dd8b821c6c311e6bc6aac1442e5fbd6b27fae0a8f3db"}, - {file = "coverage-7.14.0-cp314-cp314t-win32.whl", hash = "sha256:a9f864ef57b7172e2db87a096642dd51e179e085ab6b2c371c29e885f65c8fb2"}, - {file = "coverage-7.14.0-cp314-cp314t-win_amd64.whl", hash = "sha256:29943e552fdc08e082eb51400fb2f58e118a83b5542bd06531214e084399b644"}, - {file = "coverage-7.14.0-cp314-cp314t-win_arm64.whl", hash = "sha256:742a73ea621953b012f2c4c2219b512180dd84489acf5b1596b0aafc55b9100b"}, - {file = "coverage-7.14.0-py3-none-any.whl", hash = "sha256:8de5b61163aee3d05c8a2beab6f47913df7981dad1baf82c414d99158c286ab1"}, - {file = "coverage-7.14.0.tar.gz", hash = "sha256:057a6af2f160a85384cde4ab36f0d2777bae1057bae255f95413cdd382aa5c74"}, + {file = "coverage-7.16.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:23219888477edd736b6fcaec1272d47d93b926e999641ffea7e53a1738e70b2b"}, + {file = "coverage-7.16.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:40c0f00899fe6181ae7f434ceb200e51f5ee4b8ed10e3b5f0b605f0cae15da87"}, + {file = "coverage-7.16.2-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:a4624f80732f6b427ac58f1f59c577a0994a12e8174b5af6a027b4b58795d4c3"}, + {file = "coverage-7.16.2-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:191803c4996b499fcd78c2ad5e5f767dcc53cb4dc6de6d6a741b443a1821ef02"}, + {file = "coverage-7.16.2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9fd670ac43b709c575aefc25bf52d8a598a3bc5017bddfd0a179152ab06a2deb"}, + {file = "coverage-7.16.2-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:705e5af11d34647efdc170c7840b6857c81cf74be96419a553f237e68e62cb72"}, + {file = "coverage-7.16.2-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:8afd9bf35cc6a1f22eb3634808fa8e0b91902459c5721ef2e4461dfe771d7f08"}, + {file = "coverage-7.16.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3f43bac1856ba269b905302778d4df433d6006489a192174ad77ac528e395032"}, + {file = "coverage-7.16.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:f8475460aa33ee28ac896ab1156d0bb3b6c639f7f8383c2677d3359eb35f8205"}, + {file = "coverage-7.16.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:d6276d78f6fca7d0ac066d5da4165c5acd07829e8305c2cb900b738fb3a75a72"}, + {file = "coverage-7.16.2-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:736fde09ea39646d11f8e3b76bd3425c075aa4dd45f24891970bb77c14ff20f5"}, + {file = "coverage-7.16.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c85d54e7e8a2ca932fe8399301af9b8d5907ea2a455ffaff6e7d1208db83b943"}, + {file = "coverage-7.16.2-cp310-cp310-win32.whl", hash = "sha256:5139009b5efd2194fc168ee9362f0e191ba612ef5d29242f9269c22f9b8f80c7"}, + {file = "coverage-7.16.2-cp310-cp310-win_amd64.whl", hash = "sha256:c3305c38a2fa21a4254f2ace7dd9ef5fc569c9a558b66e7017650b3d637fb95e"}, + {file = "coverage-7.16.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:732d950e51f3ba4fb6209c73250f3e8924fefca42953ee04a9e65d8c02414d7d"}, + {file = "coverage-7.16.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5dca0bb66b4c3d624ba047887bf70270030c150692d543cb501293dc38a9f4b5"}, + {file = "coverage-7.16.2-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:af2a2a8c7c74de0559e0c368d94c8def9e16c58faaee33a0bf081057c4227e3b"}, + {file = "coverage-7.16.2-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:db5f8394e17f877a625b257f2ba0ce8e728a499c2c1579ad66220272cd3df510"}, + {file = "coverage-7.16.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5b3146d2317c75f70df2509066d979dadd941f7021cdf9b5db4bcd8568258e25"}, + {file = "coverage-7.16.2-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9e1d0ced76318bab499693ff25f64faa343415187cb2e4d7befdfdd391a1cf6a"}, + {file = "coverage-7.16.2-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:af98ad5ed9d6daaca956201e00bb429a7eb2b080426686f70a20353e0f9839f5"}, + {file = "coverage-7.16.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1d56e4d21c56d2046447733f8b118409597db48c01efe898ee9ac24e858ec2d6"}, + {file = "coverage-7.16.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1d5d0e3b660506fb84f995814e3118a21efdc0c8eb80127da1be627d90093c17"}, + {file = "coverage-7.16.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:17228fbca0f22976f797be94e975dcd237799c657d49551c7de1e0654d1202e9"}, + {file = "coverage-7.16.2-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:bc0b0ac781d489304b741269857f1f8338b7a26b1b89c06c0344658001ec0035"}, + {file = "coverage-7.16.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bf1bd822ec4e387ed245bed0d71151582cf7be9e5309bc4145eefe36083d5878"}, + {file = "coverage-7.16.2-cp311-cp311-win32.whl", hash = "sha256:7ed238d227e23cc300c3d464babdaf9f6ddc740aa1b15a77ae96136e6a7c4516"}, + {file = "coverage-7.16.2-cp311-cp311-win_amd64.whl", hash = "sha256:a90700f743e29aa3d75a6ff5f01953176a889c00e526194bc4d281731b88d99d"}, + {file = "coverage-7.16.2-cp311-cp311-win_arm64.whl", hash = "sha256:a336eec40e3520d369b8a6cdabb4f596e69a8b42927ca074aa1452fed943238a"}, + {file = "coverage-7.16.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:218d742afca2b5ad5ca759e93eddedfbcc6eadf8322f080dcefc40b7bd4e2d48"}, + {file = "coverage-7.16.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a9a638be322a8d76a41cdb17781c7f82aaee6a66493d8ffb7e2c09ee22423d99"}, + {file = "coverage-7.16.2-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:724bd0f1e81856b35e59fc98cf7b4e544a3cb662e4e0864dca73d4326ee9d808"}, + {file = "coverage-7.16.2-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:5375ebd99038021b35e99dc88255022912c06565d316212f4a576e4b08d30f5d"}, + {file = "coverage-7.16.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7a076277ca9f5750cc230f0f578ebd2620cec60255b25707361699fef6fb465c"}, + {file = "coverage-7.16.2-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:58d4a54c6ea672afef66d49be922a2c69826c5ae1a42a9cd94f0c9c2bacdf800"}, + {file = "coverage-7.16.2-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0dcbcfcc059117284c603ff8cb61a65872512882f84a8cf0339241f7f7c2f148"}, + {file = "coverage-7.16.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:afdf43b72ef3876c1fe66423b91466e37877c9e81e8cec70542b7e8525b9d1b7"}, + {file = "coverage-7.16.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:9acc7f7ec4a1b5f89bd929fde5b8a714f6fafdc6cc18725413d510aa082b47ad"}, + {file = "coverage-7.16.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:80d3f7b48d43ee8fc5e8707a8adb43d743a5a1a85256c25a24f9d6d0e2238fa6"}, + {file = "coverage-7.16.2-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:126d1af8804d7224421fe991ff65d3ce649081560df7a98b1a5ffff07f9923bd"}, + {file = "coverage-7.16.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c19cd6d025c1673f22afcd22c7df8a662d779e05d8e3fa6820c22afb895b0206"}, + {file = "coverage-7.16.2-cp312-cp312-win32.whl", hash = "sha256:152877cdc8a07264882cfcd503ba56a3ef6cba56a70e8c70f6eb8ffd7384789a"}, + {file = "coverage-7.16.2-cp312-cp312-win_amd64.whl", hash = "sha256:e6c52d3307824ff93b39efd99e4185d557db40bd841452abfb32e5d9151ca162"}, + {file = "coverage-7.16.2-cp312-cp312-win_arm64.whl", hash = "sha256:a678c0b6b22086ec2427359d22e37445d4a792f5fdbbc744112c7dade65cad02"}, + {file = "coverage-7.16.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1a37c6e478cf687e1aa30a593d19c92c02fad9d122b51ab73f51b8dc7a0c0fc9"}, + {file = "coverage-7.16.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0993d0e90858c03943d3cb152e068a20dd4707924deec84dd2230261baae3b1b"}, + {file = "coverage-7.16.2-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:bb2fc905bbf4e6b7f40806ea79e31515abf6349594cdf0adf27c4215f0463204"}, + {file = "coverage-7.16.2-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:4358b9c8c0125b460407f3017c6cce8156e904b32772c5630d27112f52bdbfe5"}, + {file = "coverage-7.16.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1f15254427c9b33eedac4f198eaf9e356eb4f6214551afb43da6194a2c088ad7"}, + {file = "coverage-7.16.2-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9a75a4704ff640e46170042eec1f984385a121227c505d5a16ad8e495f452541"}, + {file = "coverage-7.16.2-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:14253fc7bb15749b849795a06f5d3b6d8bc3fb8a4b5ddc341faf7a89dce205fc"}, + {file = "coverage-7.16.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:921415102a90637fcc2e3f169f61dad7699ecf690e8639fc21b813acbedc0967"}, + {file = "coverage-7.16.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cce2bc991293f15cc4084ca116827b5900c5f34e1a54dfe83f10ab5c43162eb7"}, + {file = "coverage-7.16.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:e1fa594c887365b69745f25a416806e61085dd07b94c9eae68a6e20730629b23"}, + {file = "coverage-7.16.2-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:11e597173af1dc33d5f8a7332ada544199269a223af1ee1770ddd5e245ad0fe8"}, + {file = "coverage-7.16.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:3e7f99698ba3a7d13988bdd984b7ebf13af4dbe2166dc8502eef90d77603b0a4"}, + {file = "coverage-7.16.2-cp313-cp313-win32.whl", hash = "sha256:f80bd9f9633eafc73d0a913ba2645c96ba58bba1befc30590f7c0fbfde59d865"}, + {file = "coverage-7.16.2-cp313-cp313-win_amd64.whl", hash = "sha256:8be099e979fc42559328a21828281b4578304191ae46ed4e80a407048a82eee6"}, + {file = "coverage-7.16.2-cp313-cp313-win_arm64.whl", hash = "sha256:28ff850182a67d117990fa2ce5ea1032836d8c9630dae867e8bdd3bff4533b79"}, + {file = "coverage-7.16.2-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:4ee546b9e4872ffa194bf07ac87bfa1202ebb824d0795dc1ef22f175545ca90a"}, + {file = "coverage-7.16.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:a2fac6895eb299a2e52d7bbb8fb3903502b9da8d3f5309ceb16ec40c646b58ee"}, + {file = "coverage-7.16.2-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:57ff3783f99d75a1e81dd56a9737eb5665e6736a5d93258ba596b6dcad8fd05b"}, + {file = "coverage-7.16.2-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:35f37886699cb9abd29958247d718628d5bc6f39e623dff66a09e546c42a7e03"}, + {file = "coverage-7.16.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0fd7a86fdda7cb6d616d178654bd0ad6bc0f3f33c2e478aa598500a1a9e34eda"}, + {file = "coverage-7.16.2-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ac0f3b379c94acc2f7dce5f5f0b24d44fa1cc6a509717ef83dfee07450c2117c"}, + {file = "coverage-7.16.2-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:7d0732c83746bc24123c581a85d9dd96b70ddb538c9076020aa1a041790361e9"}, + {file = "coverage-7.16.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7b451c68218c150f616bc9649783ec8de76a59792c759b43aa0c9c0466a465e4"}, + {file = "coverage-7.16.2-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:a56ac4fa5a75c7e182e8f62600cfb4aff43c5ed7356a034f3557659c3bec1d90"}, + {file = "coverage-7.16.2-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:4cc4f73aa3fabc36e32046d6cd2971405948d8a903636508a3d3b2f9128b3a95"}, + {file = "coverage-7.16.2-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:723dcdab91357159b722935b500ee8abc0a66c8c432e1e9fabf4cc7598952de8"}, + {file = "coverage-7.16.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5397e21a90dde0e9c6896b77ded8f0be26b66f8b22b33aed41f6043ed95d55e6"}, + {file = "coverage-7.16.2-cp314-cp314-win32.whl", hash = "sha256:848893e1d361448c113dc2f0913503522a6f7be231d0e38333d2a22d9698a011"}, + {file = "coverage-7.16.2-cp314-cp314-win_amd64.whl", hash = "sha256:5a27b731c171e43dc8b5f32b76a5051dde2ec9b9366c87028f08a7088ebc2c7b"}, + {file = "coverage-7.16.2-cp314-cp314-win_arm64.whl", hash = "sha256:1c569a9fd25505f1cd6bea90588818f90373ce90e2632e2cacf19ddbd6e14fdb"}, + {file = "coverage-7.16.2-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:d93db87adb6b1c1b408dce4763314b55d76a9f589e96783a84ac9e7689e48bdf"}, + {file = "coverage-7.16.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:aa62c85046473959c13ba9edca9dc90a77d5c1095b1ba313556314d77fe5b036"}, + {file = "coverage-7.16.2-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:db76506aa5416081f3e8974ae0f7965c58ada0bb0ef7339ac86099588dbb20d3"}, + {file = "coverage-7.16.2-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:a0f2285329dac10ab08f79cb11f5692c497018e6c7c511f95e6fd63a70b8f831"}, + {file = "coverage-7.16.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:382d3346d56b0eec1b793d53a4c88799c8053f516aa3a8d7c44315696954bacf"}, + {file = "coverage-7.16.2-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:648352b94507179d82637292e7ae8802508d95f78e2f00a705a50b6c48011681"}, + {file = "coverage-7.16.2-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fb2bde05838fffae1a1bf75e5d411a6cac3e4e9bb97e6640fed8cd47888b33f0"}, + {file = "coverage-7.16.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:6a75180829efb8ae62b4aded25be6ddca1c888d138d2d82e21d93bfbd88f41cb"}, + {file = "coverage-7.16.2-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:99704f73721e23859112072d522076e11c31744fc96b5652e5dd2018aa4359f7"}, + {file = "coverage-7.16.2-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:29309ccc86b7f33df7db12813c299f215bbbc470ed6292d0bedd63ffae1ebf64"}, + {file = "coverage-7.16.2-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:30c1b65d529e46569899fadca59e4a87c1faf2886923f1307ba61e654d4f3c20"}, + {file = "coverage-7.16.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:dcf4bc2aab4e16b1c4c0c2005918f23a7dd5d7821ddae82caed9e3342dc2fcce"}, + {file = "coverage-7.16.2-cp314-cp314t-win32.whl", hash = "sha256:a9cd3de0a5bfe7b0e21ee10e1a14e3d61bf52efc88217ab1d95d6ace6970bd46"}, + {file = "coverage-7.16.2-cp314-cp314t-win_amd64.whl", hash = "sha256:611a44e5229a59d7483ce830160e1a0e85f700562c7a5651c7c63fb8f4eb528c"}, + {file = "coverage-7.16.2-cp314-cp314t-win_arm64.whl", hash = "sha256:22957cef43ce038641de78ba995de7568d2d6a37c6ddbf7fa0fd7d1ae2344d91"}, + {file = "coverage-7.16.2-cp315-cp315-macosx_10_15_x86_64.whl", hash = "sha256:414c26dfdb96aac2d570a54e03008f001e32eb2d413705365503648c6bd361d8"}, + {file = "coverage-7.16.2-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:00d3eb96e9988c45f50cccd1f1496571ac5c1f91386ac02c4d55516eeda19a24"}, + {file = "coverage-7.16.2-cp315-cp315-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:4dbbd1155ca46e6e0b6b89d204428c56ef6a459af21333f365d135a2820e5a09"}, + {file = "coverage-7.16.2-cp315-cp315-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:8fc15cc8d0d06e873c00ef18e1372d605f9aaf3de27d8c24e50782e75bc8b843"}, + {file = "coverage-7.16.2-cp315-cp315-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9c6afdd69218202bc1758c9a14b86b8cf1084f37ed2ca143e567a103772b16d1"}, + {file = "coverage-7.16.2-cp315-cp315-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:aba5c63b7afdc749cc9eae943d5b868cba2b261a176378fa1c5a30bc8bc89982"}, + {file = "coverage-7.16.2-cp315-cp315-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:9174f0af24e5eff248b9dbfe76ec5275a3d19d37edbc2810543f12cf97347a34"}, + {file = "coverage-7.16.2-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:80e9fdb4c3d926b6ba721d4bf7435bdb869c3527ae7803290361d0ab73db13b6"}, + {file = "coverage-7.16.2-cp315-cp315-musllinux_1_2_i686.whl", hash = "sha256:7b3bce4a0d05401d70b7d0d5ca783e686bc9d30e81dbd7d980d532609bf809e4"}, + {file = "coverage-7.16.2-cp315-cp315-musllinux_1_2_ppc64le.whl", hash = "sha256:44f21e407b278efdfc1ee5e481e00518bd1d500310a30a5fbf2bcbedfef4aaf0"}, + {file = "coverage-7.16.2-cp315-cp315-musllinux_1_2_riscv64.whl", hash = "sha256:59c3926585e1cd1f2190f4b2ac9014de1bbeaf0d5d0587b0dc6b0aa90d17896a"}, + {file = "coverage-7.16.2-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:066429634299e14dd2d511e1e85f8f9cecc500781f6b41907c0dd6f1baea7e63"}, + {file = "coverage-7.16.2-cp315-cp315-win32.whl", hash = "sha256:893ea9cf86cb8d2546812ac93d973aaf2ee1fb45110a873b014214fd23e3725e"}, + {file = "coverage-7.16.2-cp315-cp315-win_amd64.whl", hash = "sha256:01c6908bc613b420c26c818fe948e1b97dfd041a53c98b01c63bd8321f5c9aae"}, + {file = "coverage-7.16.2-cp315-cp315-win_arm64.whl", hash = "sha256:967d72c835d7a8cf0af99ec813a2d06e3db6df706402f1fe85b31b437645f495"}, + {file = "coverage-7.16.2-cp315-cp315t-macosx_10_15_x86_64.whl", hash = "sha256:98d9c97f51b334b0adce7b964442a9af33c1a00c6ac856984cc5dc8d18f81c75"}, + {file = "coverage-7.16.2-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:3e861f1071dcc2fec1e88bef0920f6b1eaa66a143555b4f8ab79ba2b0f30ef55"}, + {file = "coverage-7.16.2-cp315-cp315t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:fb9d92ecfe2d5b494367c67f7446f8b75b68d8d0c8cf3bc3e6997478be25d9e2"}, + {file = "coverage-7.16.2-cp315-cp315t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:eb57acff4a74246ae513c142d4b36e18c389c3aed8661914a53f7cd0071031b2"}, + {file = "coverage-7.16.2-cp315-cp315t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:444889f7f66b74e4455c0a97e0e166dd41177f1dca8c0239a47cff25e05ba7e1"}, + {file = "coverage-7.16.2-cp315-cp315t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a740ea6f083c6db7b926534d159508f80ba275ab35e722522de0d18d0f56e55f"}, + {file = "coverage-7.16.2-cp315-cp315t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:8e209591f7c41ae4a9171335cf6156afda0b21de73b02f73f5aa95b2d5fbb08d"}, + {file = "coverage-7.16.2-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:396bb16e04ce04efbb3df91456ae4e3da918e69ecdf67fb711b0a0fdf35ccce0"}, + {file = "coverage-7.16.2-cp315-cp315t-musllinux_1_2_i686.whl", hash = "sha256:9cdf19874e0d247f32f03609200370343c3c7aa260b191d8c2bb251d36198283"}, + {file = "coverage-7.16.2-cp315-cp315t-musllinux_1_2_ppc64le.whl", hash = "sha256:fd3d72233eb8b48acc94fa57d44e2d32ce8e7abed02882ccb6d855ccc4ed33ec"}, + {file = "coverage-7.16.2-cp315-cp315t-musllinux_1_2_riscv64.whl", hash = "sha256:bb4ffe96aa663cee727659db5a2afeb38c95f8677b747d447b90d6d4874ea2c5"}, + {file = "coverage-7.16.2-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:dba2edfb054f6d4a08df9d1637c39a5aa3865bca6617c13c86be21e45658a59c"}, + {file = "coverage-7.16.2-cp315-cp315t-win32.whl", hash = "sha256:251aed777c47c77aba047096d4542889db089227655711dfc2b9c54ef0e15e35"}, + {file = "coverage-7.16.2-cp315-cp315t-win_amd64.whl", hash = "sha256:2aca0bdfa9e91621d5b09d815357bf63def4fc0e9cb66da67bf2cf93f3b1a6f5"}, + {file = "coverage-7.16.2-cp315-cp315t-win_arm64.whl", hash = "sha256:b88841e654f09732804809e435b3e005a929ffd9998b872b7b213957b8759cb8"}, + {file = "coverage-7.16.2-py3-none-any.whl", hash = "sha256:11d28e9123a9156cb405d8d27b44256c9a58fb5decc2073a8f17862057e3aa0f"}, + {file = "coverage-7.16.2.tar.gz", hash = "sha256:ca64d9f1f384f151b9511bec01126072acd2f313439f8ed015a22d8790aab6fa"}, ] [package.extras] @@ -1096,14 +1186,14 @@ ssh = ["bcrypt (>=3.1.5)"] [[package]] name = "distlib" -version = "0.4.0" +version = "0.4.3" description = "Distribution utilities" optional = false python-versions = "*" groups = ["dev"] files = [ - {file = "distlib-0.4.0-py2.py3-none-any.whl", hash = "sha256:9659f7d87e46584a30b5780e43ac7a2143098441670ff0a49d5f9034c54a6c16"}, - {file = "distlib-0.4.0.tar.gz", hash = "sha256:feec40075be03a04501a973d81f633735b4b69f98b05450592310c0f401a4e0d"}, + {file = "distlib-0.4.3-py2.py3-none-any.whl", hash = "sha256:4b0ce306c966eb73bc3a7b6abad017c556dadd92c44701562cd528ac7fde4d5b"}, + {file = "distlib-0.4.3.tar.gz", hash = "sha256:f152097224a0ae24be5a0f6bae1b9359af82133bce63f98a95f86cae1aede9ed"}, ] [[package]] @@ -1120,26 +1210,26 @@ files = [ [[package]] name = "filelock" -version = "3.29.0" +version = "4.0.11" description = "A platform independent file lock." optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "filelock-3.29.0-py3-none-any.whl", hash = "sha256:96f5f6344709aa1572bbf631c640e4ebeeb519e08da902c39a001882f30ac258"}, - {file = "filelock-3.29.0.tar.gz", hash = "sha256:69974355e960702e789734cb4871f884ea6fe50bd8404051a3530bc07809cf90"}, + {file = "filelock-4.0.11-py3-none-any.whl", hash = "sha256:1cbdc4ace7fb11d2f6d073f5c3d91537a23b3d58d2bf2fdffc12c6d717a589c6"}, + {file = "filelock-4.0.11.tar.gz", hash = "sha256:9dc453a1edd25626a6fc97c2cb1bd9f7e46345843d40b3181c071761fb9a5f7a"}, ] [[package]] name = "identify" -version = "2.6.19" +version = "2.6.20" description = "File identification library for Python" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "identify-2.6.19-py2.py3-none-any.whl", hash = "sha256:20e6a87f786f768c092a721ad107fc9df0eb89347be9396cadf3f4abbd1fb78a"}, - {file = "identify-2.6.19.tar.gz", hash = "sha256:6be5020c38fcb07da56c53733538a3081ea5aa70d36a156f83044bfbf9173842"}, + {file = "identify-2.6.20-py2.py3-none-any.whl", hash = "sha256:6a16b69b93187244e0548cbfd25b3e4a6f9a7a2ad784625c3bec2b8d27b81aaa"}, + {file = "identify-2.6.20.tar.gz", hash = "sha256:ad729860a923858d26917c2f4fb0a1d83d27a75b1e090c06440c573f048f3285"}, ] [package.extras] @@ -1147,29 +1237,29 @@ license = ["ukkonen"] [[package]] name = "idna" -version = "3.15" +version = "3.20" description = "Internationalized Domain Names in Applications (IDNA)" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" groups = ["main", "dev", "docs"] files = [ - {file = "idna-3.15-py3-none-any.whl", hash = "sha256:048adeaf8c2d788c40fee287673ccaa74c24ffd8dcf09ffa555a2fbb59f10ac8"}, - {file = "idna-3.15.tar.gz", hash = "sha256:ca962446ea538f7092a95e057da437618e886f4d349216d2b1e294abfdb65fdc"}, + {file = "idna-3.20-py3-none-any.whl", hash = "sha256:ab7ae7122974553370f0bdb919e1a960b2cd1bc1ef0276416d896db81c14582c"}, + {file = "idna-3.20.tar.gz", hash = "sha256:a7db850025b95ded1eae8a46181a1a6c56c92c96f0e2b005d9ff8dc0210cab44"}, ] [package.extras] -all = ["mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] +all = ["coverage (>=7.10.0)", "hypothesis (>=6.141.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.16.0)", "ty (>=0.0.37)"] [[package]] name = "imagesize" -version = "1.5.0" -description = "Getting image size from png/jpeg/jpeg2000/gif file" +version = "2.0.1" +description = "Get image size from headers (BMP/PNG/JPEG/JPEG2000/GIF/TIFF/SVG/Netpbm/WebP/AVIF/HEIC/HEIF)" optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" +python-versions = ">=3.10" groups = ["docs"] files = [ - {file = "imagesize-1.5.0-py2.py3-none-any.whl", hash = "sha256:32677681b3f434c2cb496f00e89c5a291247b35b1f527589909e008057da5899"}, - {file = "imagesize-1.5.0.tar.gz", hash = "sha256:8bfc5363a7f2133a89f0098451e0bcb1cd71aba4dc02bbcecb39d99d40e1b94f"}, + {file = "imagesize-2.0.1-py3-none-any.whl", hash = "sha256:ea0c9a0384df69ed86a943a15cde37d0360b82491b3910dc2215e202e62b5b02"}, + {file = "imagesize-2.0.1.tar.gz", hash = "sha256:b2ba6a4dea487a7ebcd53248d3476aca449d30db12a2dde5e0c5ca9624fd77e5"}, ] [[package]] @@ -1243,7 +1333,7 @@ files = [ [package.dependencies] attrs = ">=22.2.0" -jsonschema-specifications = ">=2023.3.6" +jsonschema-specifications = ">=2023.03.6" referencing = ">=0.28.4" rpds-py = ">=0.25.0" @@ -1268,103 +1358,150 @@ referencing = ">=0.31.0" [[package]] name = "librt" -version = "0.11.0" +version = "0.16.0" description = "Mypyc runtime library" optional = false python-versions = ">=3.9" groups = ["dev"] markers = "platform_python_implementation != \"PyPy\"" files = [ - {file = "librt-0.11.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6e94ebfcfa2d5e9926d6c3b9aa4617ffc42a845b4321fb84021b872358c82a0f"}, - {file = "librt-0.11.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ae627397a2f351560440d872d6f7c8dbb4072e57868e7b2fc5b8b430fe489d45"}, - {file = "librt-0.11.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dc329359321b67d24efdf4bc69012b0597001649544db662c001db5a0184794c"}, - {file = "librt-0.11.0-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:7e82e642ab0f7608ce2fe53d76ca2280a9ee33a1b06556142c7c6fe80a86fc33"}, - {file = "librt-0.11.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:88145c15c67731d54283d135b03244028c750cc9edc334a96a4f5950ebdb2884"}, - {file = "librt-0.11.0-cp310-cp310-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:9d36a51b3d93320b686588e27123f4995804dbf1bce81df78c02fc3c6eea9280"}, - {file = "librt-0.11.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d00f3ac06a2a8b246327f11e186a53a100a4d5c7ed52346367e5ec751d51586c"}, - {file = "librt-0.11.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:461bbceede621f1ffb8839755f8663e886087ee7af16294cab7fb4d782c62eeb"}, - {file = "librt-0.11.0-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:0cad8a4d6a8ff03c9b76f9414caccd78e7cfbc8a2e12fa334d8e1d9932753783"}, - {file = "librt-0.11.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f37aa505b3cf60701562eddb32df74b12a9e380c207fd8b06dd157a943ac7ea0"}, - {file = "librt-0.11.0-cp310-cp310-win32.whl", hash = "sha256:94663a21534637f0e787ec2a2a756022df6e5b7b2335a5cdd7d8e33d68a2af89"}, - {file = "librt-0.11.0-cp310-cp310-win_amd64.whl", hash = "sha256:dec7db73758c2b54953fd8b7fe348c45188fe26b39ee18446196edd08453a5d4"}, - {file = "librt-0.11.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:93d95bd45b7d58343d8b90d904450a545144eec19a002511163426f8ab1fae29"}, - {file = "librt-0.11.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4ee278c769a713638cdacd4c0436d72156e75df3ebc0166ab2b9dc43acc386c9"}, - {file = "librt-0.11.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f230cb1cbc9faaa616f9a678f530ebcf186e414b6bcbd88b960e4ba1b92428d5"}, - {file = "librt-0.11.0-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:5d63c855d86938d9de93e265c9bd8c705b51ec494de5738340ee93767a686e4b"}, - {file = "librt-0.11.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:993f028be9e96a08d31df3479ac80d99be374d17f3b78e4796b3fd3c913d4e89"}, - {file = "librt-0.11.0-cp311-cp311-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:258d73a0aa66a055e65b2e4d1b8cdb23b9d132c5bb915d9547d804fcaed116cc"}, - {file = "librt-0.11.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0827efe7854718f04aaddf6496e96960a956e676fe1d0f04eb41511fd8ad06d5"}, - {file = "librt-0.11.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:7753e57d6e12d019c0d8786f1c09c709f4c3fcc57c3887b24e36e6c06ec938b7"}, - {file = "librt-0.11.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:11bd19822431cc21af9f27374e7ae2e58103c7d98bda823536a6c47f6bb2bb3d"}, - {file = "librt-0.11.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:22bdf239b219d3993761a148ffa134b19e52e9989c84f845d5d7b71d70a17412"}, - {file = "librt-0.11.0-cp311-cp311-win32.whl", hash = "sha256:46c60b61e308eb535fbd6fa622b1ee1bb2815691c1ad9c98bf7b84952ec3bc8d"}, - {file = "librt-0.11.0-cp311-cp311-win_amd64.whl", hash = "sha256:902e546ff044f579ff1c953ff5fce97b636fe9e3943996b2177710c6ef076f73"}, - {file = "librt-0.11.0-cp311-cp311-win_arm64.whl", hash = "sha256:65ac3bc20f78aa0ee5ae84baa68917f89fef4af63e941084dd019a0d0e749f0c"}, - {file = "librt-0.11.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b87504f1690a23b9a2cca841191a04f83895d4fc2dd04df91d82b1a04ca2ad46"}, - {file = "librt-0.11.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40071fc5fe0ce8daa6de616702314a01e1250711682b0523d6ab8d4525910cb3"}, - {file = "librt-0.11.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:137e79445c896a0ea7b265f52d23954e05b64222ee1af69e2cb34219067cbb67"}, - {file = "librt-0.11.0-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:cca6644054e78746d8d4ef238681f9c34ff8b584fe6b988ecebb8db3b15e622a"}, - {file = "librt-0.11.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d5b0eea49f5562861ee8d757a32ef7d559c1d35be2aaaa1ec28941d74c9ffc8a"}, - {file = "librt-0.11.0-cp312-cp312-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0d1029d7e1ae1a7e647ed6fb5df8c4ce2dffefb7a9f5fd1376a4554d96dac09f"}, - {file = "librt-0.11.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:bc3ce6b33c5828d9e80592011a5c584cb2ce86edbc4088405f70da47dc1d1b3b"}, - {file = "librt-0.11.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:936c5995f3514a42111f20099397d8177c79b4d7e70961e396c6f5a0a3566766"}, - {file = "librt-0.11.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:9bc0ca6ad9381cbe8e4aa6e5726e4c80c78115a6e9723c599ed1d73e092bc49d"}, - {file = "librt-0.11.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:070aa8c26c0a74774317a72df8851facc7f0f012a5b406557ac56992d92e1ec8"}, - {file = "librt-0.11.0-cp312-cp312-win32.whl", hash = "sha256:6bf14feb84b05ae945277395451998c89c54d0def4070eb5c08de544930b245a"}, - {file = "librt-0.11.0-cp312-cp312-win_amd64.whl", hash = "sha256:75672f0bc524ede266287d532d7923dbce94c7514ad07627bac3d0c6d92cc4d9"}, - {file = "librt-0.11.0-cp312-cp312-win_arm64.whl", hash = "sha256:2f10cf143e4a9bb0f4f5af568a00df94a2d69ef41c2579584454bb0fe5cc642c"}, - {file = "librt-0.11.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:78dc31f7fdfe9c9d0eb0e8f42d139db230e826415bbcabd9f0e9faaaee909894"}, - {file = "librt-0.11.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:fa475675db22290c3158e1d42326d0f5a65f04f44a0e68c3630a25b53560fb9c"}, - {file = "librt-0.11.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:621db29691044bdeda22e789e482e1b0f3a985d90e3426c9c6d17606416205ea"}, - {file = "librt-0.11.0-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:a9010e2ed5b3a9e158c5fd966b3ab7e834bb3d3aacc8f66c91dd4b57a3799230"}, - {file = "librt-0.11.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7c39513d8b7477a2e1ed8c43fc21c524e8d5a0f8d4e8b7b074dbdbe7820a08e2"}, - {file = "librt-0.11.0-cp313-cp313-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:7aef3cf1d5af86e770ab04bfd993dfc4ae8b8c17f66fb77dd4a7d50de7bbb1a3"}, - {file = "librt-0.11.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:557183ddc36babe46b27dd60facbd5adb4492181a5be887587d57cda6e092f21"}, - {file = "librt-0.11.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:83d3e1f72bd42f6c5c0b7daec530c3f829bd02db42c70b8ddf0c2d90a2459930"}, - {file = "librt-0.11.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:4ce1f21fbe589bc1afd7872dece84fb0e1144f794a288e58a10d2c54a55c43be"}, - {file = "librt-0.11.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:970b09f7044ea2b64c9da42fd3d335666518cfd1c6e8a182c95da73d0214b41e"}, - {file = "librt-0.11.0-cp313-cp313-win32.whl", hash = "sha256:78fddc31cd4d3caa897ad5d31f856b1faadc9474021ad6cb182b9018793e254e"}, - {file = "librt-0.11.0-cp313-cp313-win_amd64.whl", hash = "sha256:8ca8aa88751a775870b764e93bad5135385f563cb8dcee399abf034ea4d3cb47"}, - {file = "librt-0.11.0-cp313-cp313-win_arm64.whl", hash = "sha256:96f044bb325fd9cf1a723015638c219e9143f0dfbc0ca54c565df2b7fc748b44"}, - {file = "librt-0.11.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:4a017a95e5837dc15a8c5661d60e05daa96b90908b1aa6b7acdf443cd25c8ebd"}, - {file = "librt-0.11.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:b1ecbd9819deccc39b7542bf4d2a740d8a620694d39989e58661d3763458f8d4"}, - {file = "librt-0.11.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7da327dacd7be8f8ec36547373550744a3cc0e536d54665cd83f8bcd961200e8"}, - {file = "librt-0.11.0-cp314-cp314-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:0dc56b1f8d06e60db362cc3fdae206681817f86ce4725d34511473487f12a34b"}, - {file = "librt-0.11.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:05fb8fb2ab90e21c8d12ea240d744ad514da9baf381ebfa70d91d20d21713175"}, - {file = "librt-0.11.0-cp314-cp314-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cae74872be221df4374d10fec61f93ed1513b9546ea84f2c0bf73ab3e9bd0b03"}, - {file = "librt-0.11.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:32bcc918c0148eb7e3d57385125bac7e5f9e4359d05f07448b09f6f778c2f31c"}, - {file = "librt-0.11.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:f9743fc99135d5f78d2454435615f6dec0473ca507c26ce9d92b10b562a280d3"}, - {file = "librt-0.11.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:5ba067f4aadae8fda802d91d2124c90c42195ff32d9161d3549e6d05cfe26f96"}, - {file = "librt-0.11.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:de3bf945454d032f9e390b85c4072e0a0570bf825421c8be0e71209fa65e1abe"}, - {file = "librt-0.11.0-cp314-cp314-win32.whl", hash = "sha256:d2277a05f6dcb9fd13db9566aac4fabd68c3ea1ea46ee5567d4eef8efa495a2f"}, - {file = "librt-0.11.0-cp314-cp314-win_amd64.whl", hash = "sha256:ab73e8db5e3f564d812c1f5c3a175930a5f9bc96ccb5e3b22a34d7858b401cf7"}, - {file = "librt-0.11.0-cp314-cp314-win_arm64.whl", hash = "sha256:aea3caa317752e3a466fa8af45d91ee0ea8c7fdd96e42b0a8dd9b76a7931eba1"}, - {file = "librt-0.11.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:d1b36540d7aaf9b9101b3a6f376c8d8e9f7a9aec93ed05918f2c69d493ffef72"}, - {file = "librt-0.11.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:efbb343ab2ce3540f4ecbe6315d677ed70f37cd9a72b1e58066c918ca83acbaa"}, - {file = "librt-0.11.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:aa0dd688aab3f7914d3e6e5e3554978e0383312fb8e771d84be008a35b9ee548"}, - {file = "librt-0.11.0-cp314-cp314t-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:f5fb36b8c6c63fdcbb1d526d94c0d1331610d43f4118cc1beb4efef4f3faacb2"}, - {file = "librt-0.11.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4a9a237d13addb93715b6fee74023d5ee3469b53fce527626c0e088aa585805f"}, - {file = "librt-0.11.0-cp314-cp314t-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:5ddd17bd87b2c56ddd60e546a7984a2e64c4e8eab92fb4cf3830a48ad5469d51"}, - {file = "librt-0.11.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:bd43992b4473d42f12ff9e68326079f0696d9d4e6000e8f39a0238d482ba6ee2"}, - {file = "librt-0.11.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:f8e3e8056dd674e279741485e2e512d6e9a751c7455809d0114e6ebf8d781085"}, - {file = "librt-0.11.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:c1f708d8ae9c56cf38a903c44297243d2ec83fd82b396b977e0144a3e76217e3"}, - {file = "librt-0.11.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:0add982e0e7b9fc14cf4b33789d5f13f66581889b88c2f58099f6ce8f92617bd"}, - {file = "librt-0.11.0-cp314-cp314t-win32.whl", hash = "sha256:2b481d846ac894c4e8403c5fd0e87c5d11d6499e404b474602508a224ff531c8"}, - {file = "librt-0.11.0-cp314-cp314t-win_amd64.whl", hash = "sha256:28edb433edde181112a908c78907af28f964eabc15f4dd16c9d66c834302677c"}, - {file = "librt-0.11.0-cp314-cp314t-win_arm64.whl", hash = "sha256:dee008f20b542e3cd162ba338a7f9ec0f6d23d395f66fe8aeeec3c9d067ea253"}, - {file = "librt-0.11.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6bd72d903911d995ab666dbd1871f8b1e80925a699af8063fbf50053329fb05f"}, - {file = "librt-0.11.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0ef69ac715f3cd8e5cd252cb2aebfa72c015492aacc339d5d7bf8fef3c62c677"}, - {file = "librt-0.11.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:624a40c4a4ad7773315c287276cd024509b2c66ff5904f504bfc08d2c70293ab"}, - {file = "librt-0.11.0-cp39-cp39-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:41dc19fe150b69716c8ece4f76773a9e8813fe3e35e032a58b4d46423fb8d7c0"}, - {file = "librt-0.11.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4e8bd98ea9c47ae90b319a087ab28dac493f1ffbc1ecd1f28fcdbf3b7e1108d1"}, - {file = "librt-0.11.0-cp39-cp39-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:84308fc49423ce6475d1c5d1985cd69a8ca9f0325fc7d5f81bb690a3f3625d4e"}, - {file = "librt-0.11.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:ff0fbaf5f44a21beeb0110f2ab64f45135a9536a834b79c0d1ef018f2786bbfa"}, - {file = "librt-0.11.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:9c028a9442a18e266955d364ce42259136e79a7ba14d773e0d778d5f70cd56f1"}, - {file = "librt-0.11.0-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:9f1692105a02bcf853f355032a5fdc5494358ef83d8fd22d16de375c85cec3f5"}, - {file = "librt-0.11.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7a80a71e1fda83cc752a9141e87aae7fef279538597564d670e9ce513f286192"}, - {file = "librt-0.11.0-cp39-cp39-win32.whl", hash = "sha256:140695816ddf3c86eb972981a26f35efd871c44b0c3aed44c8cd01749386617f"}, - {file = "librt-0.11.0-cp39-cp39-win_amd64.whl", hash = "sha256:92f7ff819c197fc30473190a12c2856f325ac90aabfccbeb2072d28cc2e234e3"}, - {file = "librt-0.11.0.tar.gz", hash = "sha256:075dc3ef4458a278e0195cbf6ac9d38808d9b906c5a6c7f7f79c3888276a3fb1"}, + {file = "librt-0.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:96f576f2711f8519152ec76d0e599243555c1f07679fa73606ca8c8c868c0be6"}, + {file = "librt-0.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2bec3818c7da7c96ceae0ef5915a3d16c52dd08f3ea913bf1fe8568c447c7978"}, + {file = "librt-0.16.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:64c79520414a3fdfc6aabd7593e6169afa14d5f8d9908d4b498db068868b08dd"}, + {file = "librt-0.16.0-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:f81b5b19ce748ef68d4746656b7929762eb2fe99269b266e4be07e2ee4de7144"}, + {file = "librt-0.16.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c71d1b76210a36729fedfc5115069b50a3d8619054745f8758fe5d6f19e86671"}, + {file = "librt-0.16.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:473eebc7866bb0a0c8849a292b5e7157c1aba5d14d0f0f610c52158d6d964262"}, + {file = "librt-0.16.0-cp310-cp310-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:4eb1313a19847089ee81e88742abedf285c60538816640b99742d8534b81d26a"}, + {file = "librt-0.16.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:ebefd60b42e2a82b32d136bb5f7c94eadfcd29f772b547df6f3291d1ed855a1c"}, + {file = "librt-0.16.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:6c5da27e8056439f927ea896735da60e616c477a8293feaa3233d4e7781a6726"}, + {file = "librt-0.16.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:67e718c7a43f8db325abbbf1404e2d535f12f8f7a1a82259568385cc5274b82a"}, + {file = "librt-0.16.0-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:314e703f0c19320dc8094e7a784b9cf29e1b67402515abf580069a6363c0b4f1"}, + {file = "librt-0.16.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:943c6bbecbdf7fa575a4f2952fcfd848c88ef95507c3fca411e89d4ac3ff8143"}, + {file = "librt-0.16.0-cp310-cp310-win32.whl", hash = "sha256:7cc365f006891afb006b52d5ee5ee74c09306ffa20e2f8705a32a4450af2f3ba"}, + {file = "librt-0.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:0314058469f4d2fd279ce7c62ac274ac82c3918ef7db62ef0697c4c359370155"}, + {file = "librt-0.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:fe4372c52d4849096c6cc1cda2817d293ec51440c890474ed59ef38d46556f18"}, + {file = "librt-0.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c72c5295a84bd249526da9bdca38f2e176d15c31c13bb0063c5053f4ca023421"}, + {file = "librt-0.16.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:be56ba9c884143495b517f23fe794ae367d58cd89ea0fdd6d437e3c024a87f9f"}, + {file = "librt-0.16.0-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:ef46c1a29ffb8c72e882e22618ec618778eacd0578fb22c6e7cf9c11d15f357b"}, + {file = "librt-0.16.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d3c94211ee0c4f8d649ec06b7c115c0ec4eadb873a0e3154ca15cef3f814b071"}, + {file = "librt-0.16.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:94aed6a8308818b91677957d1bd03188869cd7aeb23c5dba7912a6c0402f7602"}, + {file = "librt-0.16.0-cp311-cp311-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:349c0bcb87ebd07481b6ff781e25cdc699723dbe2212e57dabb27f7a13b7b87d"}, + {file = "librt-0.16.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:001bfd59a7d45b17e3e75f2a8c6405280b35e7b84471792778e718c4f368950e"}, + {file = "librt-0.16.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:28e038895b998d7a0c7798922ce8a1dc157675df5cf1c9ef0aca809ed804b7a1"}, + {file = "librt-0.16.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:0dbe4096a7ecc00fa835d24510ad8545a4efef738dac96e0e63516783ccde905"}, + {file = "librt-0.16.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:5cd5b092441053364af968ea12084692cb9d4a22f3ce9524e377880bf028761e"}, + {file = "librt-0.16.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3ddeb3c9dedb461bb457c6c7d9aa7fbf35329da313d1a7543d00c8d0f3473c96"}, + {file = "librt-0.16.0-cp311-cp311-win32.whl", hash = "sha256:e05108e0849966f53a8d2d3112a7af881d0efaa479bc735bba91108f9f2350a7"}, + {file = "librt-0.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:5f49cff01bd608ef7d97104cb035c75455e79c2d70bf4a506cf773338ac1860d"}, + {file = "librt-0.16.0-cp311-cp311-win_arm64.whl", hash = "sha256:1d28ae980ae2218f9c5b95d191e947296f918c9bf0b400d467a9430275bbe678"}, + {file = "librt-0.16.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:fe52bf4641069e7978a14253b036cb9002def1926317e710f2e249f8a8c47742"}, + {file = "librt-0.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5bcc2c4726ced915b00de0c9856a4eeabfb3fddb93e10e0b8f735b7709358b6d"}, + {file = "librt-0.16.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ff7baa55f8e7c69851419e50a666015d02a74198716fd45c0125a2112e0a389f"}, + {file = "librt-0.16.0-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:b95d5d92ab83d39e760a52091bb1baba664f3a2351e39b1e16801e5747c2f0e9"}, + {file = "librt-0.16.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b6d085d70bce51d43c5c7c36d63490770180d8779e71c49305c87b4213918de7"}, + {file = "librt-0.16.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:36e53948e99bbe3ffea257124cfcae1cfb01831555c9a9c903c9f9a72db7fd07"}, + {file = "librt-0.16.0-cp312-cp312-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:54d11f726aae9df5a6ffbbf0a03a52449bbac84a53ef03669cb41cdfd4ae41bf"}, + {file = "librt-0.16.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4323193ac0cd025f85af531df8ba91bf24d1973b401697347a6282e8fd3fcf5e"}, + {file = "librt-0.16.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e42f8e098b9c5396fefa05fb1cc7e33b0e08fc51da106b5de4a45fd22aac6743"}, + {file = "librt-0.16.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:39ec1d5a14e37baf1450a6cabf03fe552340808bf1ad9d71824ab90117716459"}, + {file = "librt-0.16.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:d1aabe3925cbb4a08d15b7b20ba4011b53019da0c4173a25155139b7b1baed65"}, + {file = "librt-0.16.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:300c3ffdc459f4a779a8411ecb188e3ac0b1ff3a3a7b099642555dedae06c69b"}, + {file = "librt-0.16.0-cp312-cp312-win32.whl", hash = "sha256:c17194318e4c0c0348b36f36c2ec7534436fe0a4c15582403162a4f08c80797a"}, + {file = "librt-0.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:25a58a19ea8d83b68209f04912df765e9260635ef77646542ed4b4abe6bc7940"}, + {file = "librt-0.16.0-cp312-cp312-win_arm64.whl", hash = "sha256:f7be7cf555bc30ec12622e9447299cc4a9b8ff307548b634794353db0c2065dc"}, + {file = "librt-0.16.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c5e6144e68b577f157519f2ba88ca20e3ed61c29b00e5cdfa76cd2d45acf059a"}, + {file = "librt-0.16.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:33f41443a1f4e1f099331b3d8120e409fbff84b9760bc1cc9ea496f37ddaa5cc"}, + {file = "librt-0.16.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7e510b7770bee609617a3374a96548eb114cae048023e3f049ee449e7ff2db32"}, + {file = "librt-0.16.0-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:efc49c462d4516b8a58b00b490078fa64689fd1fe66970cc190131d7afb8027e"}, + {file = "librt-0.16.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:92caf82ebef5e12d21c72242b70d1e92536f1711cf2a727a4c276de4b4469087"}, + {file = "librt-0.16.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:17bac7f7a16b328fff77e440287693eb017abde913595b5827ebccbc21ecd8a6"}, + {file = "librt-0.16.0-cp313-cp313-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:5b976054553670829985ed767feb78fb6bcede0175327c4844dd5c281c1be659"}, + {file = "librt-0.16.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0058f9d68721094105917254c72ac0569117bb7b13b9769cf45d26d89f9d21cd"}, + {file = "librt-0.16.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:30b7beaf3f4487b7d8adef1f158b49067cb4d5a19fa7a3bf31a4e7a820e435c5"}, + {file = "librt-0.16.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:468df902df016a06eb0e40b0747dc8d14e47d7a38b18b63b1fb167d85cb94d63"}, + {file = "librt-0.16.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:aea7b1f2b125dad5de85f049136651bff256c883c65e6b9209b2da0a1ac3cdef"}, + {file = "librt-0.16.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a8afb6557920860b7a3a596eb804cf37e09e7cf8a803db2478c202acc72d8c2e"}, + {file = "librt-0.16.0-cp313-cp313-pyemscripten_2025_0_wasm32.whl", hash = "sha256:77c7a2b4fe2c1369e0d5aa1cade26740a7b14be32fbc9a5535d617d20065c39d"}, + {file = "librt-0.16.0-cp313-cp313-win32.whl", hash = "sha256:02d89c813d5ff74b17df72d3a34819d132cd168e56b81bf755b809bd9e46b8c4"}, + {file = "librt-0.16.0-cp313-cp313-win_amd64.whl", hash = "sha256:14ed6ebe3e4f85f326d7920011ad30ff49ed9334e62cf88caef9ba973d9e3a92"}, + {file = "librt-0.16.0-cp313-cp313-win_arm64.whl", hash = "sha256:83d4041a3d9b2fd053a8a4e1f22878b3e5833e2712956382d5c048d791454e91"}, + {file = "librt-0.16.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:931a0bb0fcac88f263e269e46eb30ba8e21402cd3c62ca40cb97034c0693fab1"}, + {file = "librt-0.16.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1bc17e54e5305f8d40b7ca203671ff5a9e59c1d0f8ea0f625dcca53a3984de11"}, + {file = "librt-0.16.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:877698bf6bca5721d8be345f2fe09778e40ecadea8b58c73075f2b1a53666bf2"}, + {file = "librt-0.16.0-cp314-cp314-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:5981c011b306781ce561e18e14230a14524a3d8109b97553666c942c18f31a96"}, + {file = "librt-0.16.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:afced3dfc17cd805ecf7a3d77996a71cf5f2c75aa66eb0c21a9930f4fc992f86"}, + {file = "librt-0.16.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ca8052401c55d7511dda6760719fda7618067e83535d7d0010096d216c34b667"}, + {file = "librt-0.16.0-cp314-cp314-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:1e511762a074005bb0aa569166779834e75e438370226930d0ce1866d4b6a33b"}, + {file = "librt-0.16.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:f1e8591bd8a5a628cd7f07954c6a1592359a878bf032957a8e9057a41d644311"}, + {file = "librt-0.16.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:a4aaefb4ba6c07e1aeebb2795c8958148f1d6f9af3b555b53d23d766edb6d67a"}, + {file = "librt-0.16.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:d92db7a0f6aee44f1baee94750457e8d2d1c6ccea41842de6268d34e8dc7eddd"}, + {file = "librt-0.16.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:378dfaffb38e59c24a87cde5713cd865d51ff7383fa12947f3907f306ea1ca55"}, + {file = "librt-0.16.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:3e0c39bdc85370422e8b637be76eb1fd07d30967551b03e62267dd156f553152"}, + {file = "librt-0.16.0-cp314-cp314-pyemscripten_2026_0_wasm32.whl", hash = "sha256:1b384b90ab79a7bc30b566895809a636e0666f21f3cf12b54823d025b7e83839"}, + {file = "librt-0.16.0-cp314-cp314-win32.whl", hash = "sha256:52327da75a94012e7f932f913d20d3876bed3c102be00e6c3e8600ff7bdd58a7"}, + {file = "librt-0.16.0-cp314-cp314-win_amd64.whl", hash = "sha256:3f0b8114c44b2ac06ff5dacd08e07e8e807ff4f46083f2a1602685122559be41"}, + {file = "librt-0.16.0-cp314-cp314-win_arm64.whl", hash = "sha256:8caf96a4ef8fb27d0ac0d1ad8337d26a240acd4a02fe4345d0a8f264753e8f99"}, + {file = "librt-0.16.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:953107e2f68d0f3512c48f898b0dbf0ce5cc52bba0f318d847c985dc555ee4cc"}, + {file = "librt-0.16.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ad37d5b9abd49c9a655dcda7ea52a8a752884062ef1ee71ae17c2f2a0f81fe6a"}, + {file = "librt-0.16.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2c4aa329c17bd1aaea4f6e89335d8ccd494b3a5830b6654462273e50e11023f0"}, + {file = "librt-0.16.0-cp314-cp314t-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:0ead24d2562a49473dddd9efef8581f020007eb0054389c3ee3ffad38b1ca4c9"}, + {file = "librt-0.16.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:02118f56a9c36ddd07dfd9b919d9ecc117ba20a90987d56aa4c429fa34509188"}, + {file = "librt-0.16.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4e29522c62e28595ff7e324c6834ade51127707f0e255b18d1c1cf03d39c1048"}, + {file = "librt-0.16.0-cp314-cp314t-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3ff4b2367926b69c6215635902cccb04048e73094e9862900d27cb2c6bbff143"}, + {file = "librt-0.16.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c6f1b27bf1632a7e016af9f145f82be95e1edd7721a646505c21059257cb5a04"}, + {file = "librt-0.16.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:5696d7f52e7b37217cb3a8f92c744fe835942602fdd4c1a8bc4741d3bfdce15e"}, + {file = "librt-0.16.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:6072e92dd876ff6ceeb6cf371e35e51f479349837391341f479b08df4564242b"}, + {file = "librt-0.16.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:39ca4f2f2fe05de8e63493da592d84311adabe5bef52b193851981da9816b302"}, + {file = "librt-0.16.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:f9807485a908f00355820f18e91e045ffdcdc5adb68aaec40a1e2b88c5f7bba1"}, + {file = "librt-0.16.0-cp314-cp314t-win32.whl", hash = "sha256:94be5cb7bca4df6201f4183e9e4fa2086c655283d20b38cd84500a69057575a7"}, + {file = "librt-0.16.0-cp314-cp314t-win_amd64.whl", hash = "sha256:d46ca272b251d033dd4527b0dec5f261a28a52bd5fa0f99c117b0a1f8588cc2d"}, + {file = "librt-0.16.0-cp314-cp314t-win_arm64.whl", hash = "sha256:b9d6d4b14e92d876f8026b54c20c445f36425214c1081dc76f74e40db386b82b"}, + {file = "librt-0.16.0-cp315-cp315-macosx_10_15_x86_64.whl", hash = "sha256:6fe436af2eaf630474f491af5d032cbe45f93fcff5c3b9fe4ab194a7255b20ff"}, + {file = "librt-0.16.0-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:8ff5d26c529336be9bd7ae04483235d77778ee7d6444a95353102b542601ce81"}, + {file = "librt-0.16.0-cp315-cp315-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:909d8e3c1faee44cb762b1c519ff8613dcc5ceae5c99987a00917b5a31fd1d6a"}, + {file = "librt-0.16.0-cp315-cp315-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:6d4a64283ee61824b5790de882bc68e2d9d7a5143537cb7a966f7354f71646d4"}, + {file = "librt-0.16.0-cp315-cp315-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5810ba811297fdf37a1531a57667cb8ace0842013ca8606bf9eb7c24cf4be154"}, + {file = "librt-0.16.0-cp315-cp315-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e56aaf8c167548dc8e5d6f3bd0f48dcdd299a23c73be3f744aab79d99e9c7f5d"}, + {file = "librt-0.16.0-cp315-cp315-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:8f36c58e33b304b525c6c9c5076399c6ebf1109e17b9051a05a407b091b9215b"}, + {file = "librt-0.16.0-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:242e00b3d4fa37c3d3c1ca5f5c9adb7d909ddb1eac9c41f2787320d00caa0af2"}, + {file = "librt-0.16.0-cp315-cp315-musllinux_1_2_i686.whl", hash = "sha256:0253721561787b8df8443eb347b7a6461015354e5bdd37ee38a41fef220d2bb0"}, + {file = "librt-0.16.0-cp315-cp315-musllinux_1_2_ppc64le.whl", hash = "sha256:3e483a8d69ede8067db70c0e83007423b6925de6fd53afed01d66160f2e9398c"}, + {file = "librt-0.16.0-cp315-cp315-musllinux_1_2_riscv64.whl", hash = "sha256:69ba927445cfaaffb4081003ef5224c55a5c2ab67ef956f416ef744916e44121"}, + {file = "librt-0.16.0-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:d6a365f2ab45a984d0e00eee0dd17f599ceab8cadab6ea07b6111c8132fc0e42"}, + {file = "librt-0.16.0-cp315-cp315-pyemscripten_2026_5_wasm32.whl", hash = "sha256:f01f3805f2dae4781c0c34b440e31740d082950bdaf89a6f601ad589a28af57a"}, + {file = "librt-0.16.0-cp315-cp315-win32.whl", hash = "sha256:b0e3e721c75d2e79a76d4422c79d7ba705fe1bbafec907037fe7a657a480a0e3"}, + {file = "librt-0.16.0-cp315-cp315-win_amd64.whl", hash = "sha256:bc02954b1295de798bbdb0b4e2d8a28c2117de8b5c73dcbeb27dc32572dfb971"}, + {file = "librt-0.16.0-cp315-cp315-win_arm64.whl", hash = "sha256:c5db585d43449a5f54303d4b2774e45e1babd975cfe1630a3d708c0b80c3e560"}, + {file = "librt-0.16.0-cp315-cp315t-macosx_10_15_x86_64.whl", hash = "sha256:f06c689cb14afd9b612727553a5ec5a40febf113ca41c4413a2b0b334285884b"}, + {file = "librt-0.16.0-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:13b4e8aba90b0b1c82474e9844aa9ffe7ad3faa484350e1da64cb8188d903134"}, + {file = "librt-0.16.0-cp315-cp315t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5a269c46ae327d8e6f8c1f85f7516cb52c0fa48127565a1105a4f4a05ff2a0b4"}, + {file = "librt-0.16.0-cp315-cp315t-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:a33e0dae1f8592146a4764d54ce842b278732d21a84e17c3bbe6b1bc158a2248"}, + {file = "librt-0.16.0-cp315-cp315t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:47ada6ea32636492c61aa8ad27ae3b9404bfe7a97e3ba946d1984236cc741da0"}, + {file = "librt-0.16.0-cp315-cp315t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c43bd6e642d8a248c114327f98dd25ac5a7cb5aa168ef02f0559b91874df16b8"}, + {file = "librt-0.16.0-cp315-cp315t-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c3d1bb7841a816ace6449bb26d3f9560dbfa20e71c568d23f0f62bf1e68f50b1"}, + {file = "librt-0.16.0-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:3931f7a3db322e7f44e02a280e3949326ce9579ad388ee8d691dc7c76da9fb70"}, + {file = "librt-0.16.0-cp315-cp315t-musllinux_1_2_i686.whl", hash = "sha256:f4462528b6000afe8f16907b5c7c2553abf1df005ba5140e6eb394541c3624c3"}, + {file = "librt-0.16.0-cp315-cp315t-musllinux_1_2_ppc64le.whl", hash = "sha256:80039ba9b6a7d5f1a0175a4cca6bbefead87bd854c80abad1cb30afe47a830db"}, + {file = "librt-0.16.0-cp315-cp315t-musllinux_1_2_riscv64.whl", hash = "sha256:7a1d272724b581bb6bc769dfdafed6da2ecc9886ba2450311de55a4ac2e1e9cd"}, + {file = "librt-0.16.0-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:fbe4fb8c5445f7496d7f7f6bb0807875d09d47e6771ffa175fb2df2895fb86ba"}, + {file = "librt-0.16.0-cp315-cp315t-win32.whl", hash = "sha256:375bfe6b572a8f6cfc398709356046173bf27e64c4c5edaf5f7062f051fb4bf9"}, + {file = "librt-0.16.0-cp315-cp315t-win_amd64.whl", hash = "sha256:bd3150023d3dc2bc70f3784e59ffa1140d56ddba3d8125b3d6f9f85221279bfc"}, + {file = "librt-0.16.0-cp315-cp315t-win_arm64.whl", hash = "sha256:8ceafb70f2a4f0826f11031942e59c0728fd98da112dc346d4352bde1e486866"}, + {file = "librt-0.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e1967e36ac4cae0c7e9615ad32e1a513cdacff79f9e8afb28bedc91caf48b4f3"}, + {file = "librt-0.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:20fe0bf9053885e21c62b3e091fb5e73e1c54d1daf2e70eb388d70763bcd4220"}, + {file = "librt-0.16.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6a63610fa76524edfa605b5b259a603915c7a6e10e54f003e5503030506e81de"}, + {file = "librt-0.16.0-cp39-cp39-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:845a511b60ca43b9880dcc84a9784c891d6a2098c829130b320846c69c9c0c68"}, + {file = "librt-0.16.0-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d608f0bf3b8cbddd0067fe02cb8cab7d13e8eb9386b23a1843d4363044fd9e22"}, + {file = "librt-0.16.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:df183721229ae51eef90108c115b43e98cb169b6155d34480338e5fc6616df00"}, + {file = "librt-0.16.0-cp39-cp39-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:4b6183e2e2e0ee00aac2ec07c7f7d151c97e85666b304f574b71cff0f9fccc4e"}, + {file = "librt-0.16.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:273d00be33792a15189331df10f1f1331621b043881e66c6c4377f7f776e1291"}, + {file = "librt-0.16.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:aa9357a1b4d4fc787bb718a59cb1112c28c8a976d6bfa268b71cc0a4ab8f3a94"}, + {file = "librt-0.16.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:e9ce0bc440e7fd09b5f51f372f0f6640658f854b8fb05260f819cc669c93c42d"}, + {file = "librt-0.16.0-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:6c8893eae2fd13c5488d94056f3e6e5cf3142bfb1c4acaf136cb33d760c5964b"}, + {file = "librt-0.16.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7393c9a48dcce4817dbd4b0d8ff6237efe9b0a0609f5b0adaef315f8541726b5"}, + {file = "librt-0.16.0-cp39-cp39-win32.whl", hash = "sha256:71b93b42784e25b975079573c642a8fedb049a7bb31d70a51721b1666b3b2ced"}, + {file = "librt-0.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:5750a105b42a416f930edc59054927a406effb2550cd5bab92ad7a5842ed5d05"}, + {file = "librt-0.16.0.tar.gz", hash = "sha256:ac38d6d8d66bf3d744148dbbc0b8e193e195a51e364ed55e224631f5721891fc"}, ] [[package]] @@ -1393,101 +1530,163 @@ testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions", "pytest-tim [[package]] name = "markupsafe" -version = "3.0.3" +version = "3.0.4" description = "Safely add untrusted strings to HTML/XML markup." optional = false python-versions = ">=3.9" groups = ["dev", "docs"] files = [ - {file = "markupsafe-3.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2f981d352f04553a7171b8e44369f2af4055f888dfb147d55e42d29e29e74559"}, - {file = "markupsafe-3.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e1c1493fb6e50ab01d20a22826e57520f1284df32f2d8601fdd90b6304601419"}, - {file = "markupsafe-3.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1ba88449deb3de88bd40044603fafffb7bc2b055d626a330323a9ed736661695"}, - {file = "markupsafe-3.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f42d0984e947b8adf7dd6dde396e720934d12c506ce84eea8476409563607591"}, - {file = "markupsafe-3.0.3-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c0c0b3ade1c0b13b936d7970b1d37a57acde9199dc2aecc4c336773e1d86049c"}, - {file = "markupsafe-3.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:0303439a41979d9e74d18ff5e2dd8c43ed6c6001fd40e5bf2e43f7bd9bbc523f"}, - {file = "markupsafe-3.0.3-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:d2ee202e79d8ed691ceebae8e0486bd9a2cd4794cec4824e1c99b6f5009502f6"}, - {file = "markupsafe-3.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:177b5253b2834fe3678cb4a5f0059808258584c559193998be2601324fdeafb1"}, - {file = "markupsafe-3.0.3-cp310-cp310-win32.whl", hash = "sha256:2a15a08b17dd94c53a1da0438822d70ebcd13f8c3a95abe3a9ef9f11a94830aa"}, - {file = "markupsafe-3.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:c4ffb7ebf07cfe8931028e3e4c85f0357459a3f9f9490886198848f4fa002ec8"}, - {file = "markupsafe-3.0.3-cp310-cp310-win_arm64.whl", hash = "sha256:e2103a929dfa2fcaf9bb4e7c091983a49c9ac3b19c9061b6d5427dd7d14d81a1"}, - {file = "markupsafe-3.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1cc7ea17a6824959616c525620e387f6dd30fec8cb44f649e31712db02123dad"}, - {file = "markupsafe-3.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4bd4cd07944443f5a265608cc6aab442e4f74dff8088b0dfc8238647b8f6ae9a"}, - {file = "markupsafe-3.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b5420a1d9450023228968e7e6a9ce57f65d148ab56d2313fcd589eee96a7a50"}, - {file = "markupsafe-3.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0bf2a864d67e76e5c9a34dc26ec616a66b9888e25e7b9460e1c76d3293bd9dbf"}, - {file = "markupsafe-3.0.3-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc51efed119bc9cfdf792cdeaa4d67e8f6fcccab66ed4bfdd6bde3e59bfcbb2f"}, - {file = "markupsafe-3.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:068f375c472b3e7acbe2d5318dea141359e6900156b5b2ba06a30b169086b91a"}, - {file = "markupsafe-3.0.3-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:7be7b61bb172e1ed687f1754f8e7484f1c8019780f6f6b0786e76bb01c2ae115"}, - {file = "markupsafe-3.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a"}, - {file = "markupsafe-3.0.3-cp311-cp311-win32.whl", hash = "sha256:0db14f5dafddbb6d9208827849fad01f1a2609380add406671a26386cdf15a19"}, - {file = "markupsafe-3.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:de8a88e63464af587c950061a5e6a67d3632e36df62b986892331d4620a35c01"}, - {file = "markupsafe-3.0.3-cp311-cp311-win_arm64.whl", hash = "sha256:3b562dd9e9ea93f13d53989d23a7e775fdfd1066c33494ff43f5418bc8c58a5c"}, - {file = "markupsafe-3.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d53197da72cc091b024dd97249dfc7794d6a56530370992a5e1a08983ad9230e"}, - {file = "markupsafe-3.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1872df69a4de6aead3491198eaf13810b565bdbeec3ae2dc8780f14458ec73ce"}, - {file = "markupsafe-3.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3a7e8ae81ae39e62a41ec302f972ba6ae23a5c5396c8e60113e9066ef893da0d"}, - {file = "markupsafe-3.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d6dd0be5b5b189d31db7cda48b91d7e0a9795f31430b7f271219ab30f1d3ac9d"}, - {file = "markupsafe-3.0.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:94c6f0bb423f739146aec64595853541634bde58b2135f27f61c1ffd1cd4d16a"}, - {file = "markupsafe-3.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:be8813b57049a7dc738189df53d69395eba14fb99345e0a5994914a3864c8a4b"}, - {file = "markupsafe-3.0.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:83891d0e9fb81a825d9a6d61e3f07550ca70a076484292a70fde82c4b807286f"}, - {file = "markupsafe-3.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:77f0643abe7495da77fb436f50f8dab76dbc6e5fd25d39589a0f1fe6548bfa2b"}, - {file = "markupsafe-3.0.3-cp312-cp312-win32.whl", hash = "sha256:d88b440e37a16e651bda4c7c2b930eb586fd15ca7406cb39e211fcff3bf3017d"}, - {file = "markupsafe-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:26a5784ded40c9e318cfc2bdb30fe164bdb8665ded9cd64d500a34fb42067b1c"}, - {file = "markupsafe-3.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:35add3b638a5d900e807944a078b51922212fb3dedb01633a8defc4b01a3c85f"}, - {file = "markupsafe-3.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e1cf1972137e83c5d4c136c43ced9ac51d0e124706ee1c8aa8532c1287fa8795"}, - {file = "markupsafe-3.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219"}, - {file = "markupsafe-3.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6"}, - {file = "markupsafe-3.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676"}, - {file = "markupsafe-3.0.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:509fa21c6deb7a7a273d629cf5ec029bc209d1a51178615ddf718f5918992ab9"}, - {file = "markupsafe-3.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4afe79fb3de0b7097d81da19090f4df4f8d3a2b3adaa8764138aac2e44f3af1"}, - {file = "markupsafe-3.0.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:795e7751525cae078558e679d646ae45574b47ed6e7771863fcc079a6171a0fc"}, - {file = "markupsafe-3.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8485f406a96febb5140bfeca44a73e3ce5116b2501ac54fe953e488fb1d03b12"}, - {file = "markupsafe-3.0.3-cp313-cp313-win32.whl", hash = "sha256:bdd37121970bfd8be76c5fb069c7751683bdf373db1ed6c010162b2a130248ed"}, - {file = "markupsafe-3.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5"}, - {file = "markupsafe-3.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:7e68f88e5b8799aa49c85cd116c932a1ac15caaa3f5db09087854d218359e485"}, - {file = "markupsafe-3.0.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:218551f6df4868a8d527e3062d0fb968682fe92054e89978594c28e642c43a73"}, - {file = "markupsafe-3.0.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3524b778fe5cfb3452a09d31e7b5adefeea8c5be1d43c4f810ba09f2ceb29d37"}, - {file = "markupsafe-3.0.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4e885a3d1efa2eadc93c894a21770e4bc67899e3543680313b09f139e149ab19"}, - {file = "markupsafe-3.0.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8709b08f4a89aa7586de0aadc8da56180242ee0ada3999749b183aa23df95025"}, - {file = "markupsafe-3.0.3-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b8512a91625c9b3da6f127803b166b629725e68af71f8184ae7e7d54686a56d6"}, - {file = "markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9b79b7a16f7fedff2495d684f2b59b0457c3b493778c9eed31111be64d58279f"}, - {file = "markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:12c63dfb4a98206f045aa9563db46507995f7ef6d83b2f68eda65c307c6829eb"}, - {file = "markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8f71bc33915be5186016f675cd83a1e08523649b0e33efdb898db577ef5bb009"}, - {file = "markupsafe-3.0.3-cp313-cp313t-win32.whl", hash = "sha256:69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354"}, - {file = "markupsafe-3.0.3-cp313-cp313t-win_amd64.whl", hash = "sha256:1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218"}, - {file = "markupsafe-3.0.3-cp313-cp313t-win_arm64.whl", hash = "sha256:ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287"}, - {file = "markupsafe-3.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:eaa9599de571d72e2daf60164784109f19978b327a3910d3e9de8c97b5b70cfe"}, - {file = "markupsafe-3.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026"}, - {file = "markupsafe-3.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f34c41761022dd093b4b6896d4810782ffbabe30f2d443ff5f083e0cbbb8c737"}, - {file = "markupsafe-3.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:457a69a9577064c05a97c41f4e65148652db078a3a509039e64d3467b9e7ef97"}, - {file = "markupsafe-3.0.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e8afc3f2ccfa24215f8cb28dcf43f0113ac3c37c2f0f0806d8c70e4228c5cf4d"}, - {file = "markupsafe-3.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ec15a59cf5af7be74194f7ab02d0f59a62bdcf1a537677ce67a2537c9b87fcda"}, - {file = "markupsafe-3.0.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:0eb9ff8191e8498cca014656ae6b8d61f39da5f95b488805da4bb029cccbfbaf"}, - {file = "markupsafe-3.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2713baf880df847f2bece4230d4d094280f4e67b1e813eec43b4c0e144a34ffe"}, - {file = "markupsafe-3.0.3-cp314-cp314-win32.whl", hash = "sha256:729586769a26dbceff69f7a7dbbf59ab6572b99d94576a5592625d5b411576b9"}, - {file = "markupsafe-3.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:bdc919ead48f234740ad807933cdf545180bfbe9342c2bb451556db2ed958581"}, - {file = "markupsafe-3.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:5a7d5dc5140555cf21a6fefbdbf8723f06fcd2f63ef108f2854de715e4422cb4"}, - {file = "markupsafe-3.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:1353ef0c1b138e1907ae78e2f6c63ff67501122006b0f9abad68fda5f4ffc6ab"}, - {file = "markupsafe-3.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1085e7fbddd3be5f89cc898938f42c0b3c711fdcb37d75221de2666af647c175"}, - {file = "markupsafe-3.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1b52b4fb9df4eb9ae465f8d0c228a00624de2334f216f178a995ccdcf82c4634"}, - {file = "markupsafe-3.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50"}, - {file = "markupsafe-3.0.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f190daf01f13c72eac4efd5c430a8de82489d9cff23c364c3ea822545032993e"}, - {file = "markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e56b7d45a839a697b5eb268c82a71bd8c7f6c94d6fd50c3d577fa39a9f1409f5"}, - {file = "markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:f3e98bb3798ead92273dc0e5fd0f31ade220f59a266ffd8a4f6065e0a3ce0523"}, - {file = "markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5678211cb9333a6468fb8d8be0305520aa073f50d17f089b5b4b477ea6e67fdc"}, - {file = "markupsafe-3.0.3-cp314-cp314t-win32.whl", hash = "sha256:915c04ba3851909ce68ccc2b8e2cd691618c4dc4c4232fb7982bca3f41fd8c3d"}, - {file = "markupsafe-3.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4faffd047e07c38848ce017e8725090413cd80cbc23d86e55c587bf979e579c9"}, - {file = "markupsafe-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa"}, - {file = "markupsafe-3.0.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:15d939a21d546304880945ca1ecb8a039db6b4dc49b2c5a400387cdae6a62e26"}, - {file = "markupsafe-3.0.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f71a396b3bf33ecaa1626c255855702aca4d3d9fea5e051b41ac59a9c1c41edc"}, - {file = "markupsafe-3.0.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0f4b68347f8c5eab4a13419215bdfd7f8c9b19f2b25520968adfad23eb0ce60c"}, - {file = "markupsafe-3.0.3-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e8fc20152abba6b83724d7ff268c249fa196d8259ff481f3b1476383f8f24e42"}, - {file = "markupsafe-3.0.3-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:949b8d66bc381ee8b007cd945914c721d9aba8e27f71959d750a46f7c282b20b"}, - {file = "markupsafe-3.0.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:3537e01efc9d4dccdf77221fb1cb3b8e1a38d5428920e0657ce299b20324d758"}, - {file = "markupsafe-3.0.3-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:591ae9f2a647529ca990bc681daebdd52c8791ff06c2bfa05b65163e28102ef2"}, - {file = "markupsafe-3.0.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a320721ab5a1aba0a233739394eb907f8c8da5c98c9181d1161e77a0c8e36f2d"}, - {file = "markupsafe-3.0.3-cp39-cp39-win32.whl", hash = "sha256:df2449253ef108a379b8b5d6b43f4b1a8e81a061d6537becd5582fba5f9196d7"}, - {file = "markupsafe-3.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:7c3fb7d25180895632e5d3148dbdc29ea38ccb7fd210aa27acbd1201a1902c6e"}, - {file = "markupsafe-3.0.3-cp39-cp39-win_arm64.whl", hash = "sha256:38664109c14ffc9e7437e86b4dceb442b0096dfe3541d7864d9cbe1da4cf36c8"}, - {file = "markupsafe-3.0.3.tar.gz", hash = "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698"}, + {file = "markupsafe-3.0.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:dd8ea6ebee7aedbf7c749fa80521d9ccf1ba473e0d1e14805caafbaad281c889"}, + {file = "markupsafe-3.0.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:dff05cb7016dff1e9fd68f4122c127b65dfc59de5306cfb7ad92f956f230bee2"}, + {file = "markupsafe-3.0.4-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cf63c214fe879a65e69a386f915e36104fc84254ab141240f8854602d8e0be2a"}, + {file = "markupsafe-3.0.4-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:2a6ef68ae94aed8721934072b27a3b654ea2100b97e4ab864cf1489c90926fbc"}, + {file = "markupsafe-3.0.4-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:fd9f8797427910198f95bced71ddfed61130d7e349213bfb8466c9c99e2c46a8"}, + {file = "markupsafe-3.0.4-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d1aca03ede943eb80ab3d63bb082c84b7aab85ea83bd0fd0c200260945fb49d9"}, + {file = "markupsafe-3.0.4-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0764a13d34cae40db7bbf3a09b7e9b491bf4603e20b263a7a9d6b8e324975d0a"}, + {file = "markupsafe-3.0.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:9388003072b95f2f1e3fd908604194d653ba21330d811961a78b7da1a77e9e36"}, + {file = "markupsafe-3.0.4-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:8698d70a8081ee8c090dbb394768b5789a1da8b131b5499f89d071dd3cfaf6be"}, + {file = "markupsafe-3.0.4-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:bf053da3c97a4bc5ecfbb218cdd2983febd91c617be8367d139882aa11e490aa"}, + {file = "markupsafe-3.0.4-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:9438a2648b2195980cb2dd8e53ed7b8df91319e2d0b70ae61a9e1d1bc8d3bec9"}, + {file = "markupsafe-3.0.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:88d59b473bfb03259722600839af9bbd7fa13a2eb514beefeedb95997882f69a"}, + {file = "markupsafe-3.0.4-cp310-cp310-win32.whl", hash = "sha256:4a540e2d3192792fc84eced57bef37851ccb2b41f73291bb17408eea77bcd278"}, + {file = "markupsafe-3.0.4-cp310-cp310-win_amd64.whl", hash = "sha256:5c22873ad1f0532ba40fa1727f3c0fc1bbbaab6d373d4cbe3f0dc74b2e2521c7"}, + {file = "markupsafe-3.0.4-cp310-cp310-win_arm64.whl", hash = "sha256:3d23795802fc8bd72534836d64489bbf0f67c088959091bdb22e10735a5107bf"}, + {file = "markupsafe-3.0.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9e25feb9e330b63edb0278a0acdf85e50d0cb0fbf49c3084abbe4e24ae195346"}, + {file = "markupsafe-3.0.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7d3391b2188d18737cb2fa147028b1096236eaa7e156446c650a489fa2cadc91"}, + {file = "markupsafe-3.0.4-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:849dd2bb0e5e4ab2b71c7191726a4a8d5aa8a610daa584728cbee0b710ddc4ef"}, + {file = "markupsafe-3.0.4-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:befb4158af32106b9a93db8d6d1d1cbbd418c0d5aca0cabb7b1780abf0c89169"}, + {file = "markupsafe-3.0.4-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:71f88e749ea29f67f21f3b36433c1dc54c7729ed2a6d9e2da2e0d9e0d7b224eb"}, + {file = "markupsafe-3.0.4-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6da83a088f8ef93b2d483a8232a4dbf4d69d3d8496b568a03c56becac43e1808"}, + {file = "markupsafe-3.0.4-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:8f0fac8b13d14bb06c68195f849371924ae53dd7b1c00fed24650f704383b692"}, + {file = "markupsafe-3.0.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:4a7cdc2a420ca01058182da4253329764d4bfa055564d1eced90e6ba1e8b1d3d"}, + {file = "markupsafe-3.0.4-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:83b3944fea42a8400edf92fd1770fb8d0d4f7de651353bd2d8525a92dba69a21"}, + {file = "markupsafe-3.0.4-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:8138eb83940ec7299024d92d4dee45f601b9e6c5ffde9d25f4e35e326203c707"}, + {file = "markupsafe-3.0.4-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:811d02d5122171c1941357efd8f9bf4ffe907b7f0a1a4e729a880e4be3f46e3e"}, + {file = "markupsafe-3.0.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:50b5bedc9ed8a94fc8857a42ef4f84a81ea88f8d4f05dc8705fb23ee6d8dcca7"}, + {file = "markupsafe-3.0.4-cp311-cp311-win32.whl", hash = "sha256:2e5a7cd7fdd14fcb1ae5d7d8bf23d24fbd1daefd1fbca2580132e1ea75f098b5"}, + {file = "markupsafe-3.0.4-cp311-cp311-win_amd64.whl", hash = "sha256:fdb4ca07ab75ffadab4a8b135ad59cdbb3156b99310f3d565370da74a15d6bd3"}, + {file = "markupsafe-3.0.4-cp311-cp311-win_arm64.whl", hash = "sha256:569d65055d367e3dcdf30c3f41119467b73d9ee9faf332bdf40402644f5ac08e"}, + {file = "markupsafe-3.0.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:61631e08084be9e21a8967ec3139c7616ed7c5e9368e05c86d1b39562c8a57b6"}, + {file = "markupsafe-3.0.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0930db9bdc62d22944e10b066448bb65dc9abe9112880c7cab8da54db4284d5f"}, + {file = "markupsafe-3.0.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6a45c3d514f2436064db00d7fc8778d888f0236ebfed649b53d13a59e69ad51b"}, + {file = "markupsafe-3.0.4-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:1e1451fab512d1bcc3dc26988ec1edb0b82c2db909132872cd9356070a6b63df"}, + {file = "markupsafe-3.0.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:bd3ce56ae2cbae3ba82b683bc425cd7e48d2ed8b10f3e818186b6f5646d9271c"}, + {file = "markupsafe-3.0.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8e124f974786f831d6043728e38296969d3579db8896fe004682f5758e613581"}, + {file = "markupsafe-3.0.4-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c02e8f18bdedba082cef725942ac823b9b60656db07f7e265cb31618dfd00d77"}, + {file = "markupsafe-3.0.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9f098115c247e11d138ab83a28fa0323c77015007ea2df73ba5fd714dfefd67c"}, + {file = "markupsafe-3.0.4-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:d5f93ebbeb8032d47e349328ec8662d973d9b05a70b3c35df1f91fe419b84749"}, + {file = "markupsafe-3.0.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:64511c54db4e4987aef4c41923235927428729e8174c5dba488429be70a998ed"}, + {file = "markupsafe-3.0.4-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:e1a622f13970d81f95d0c72f9dc090dce9085fccfa4c9f2174377ee32bd15786"}, + {file = "markupsafe-3.0.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c9a7f43c0b202b334cc9184af09bb8f21d3a209e038efaf106936fb69e6b026e"}, + {file = "markupsafe-3.0.4-cp312-cp312-win32.whl", hash = "sha256:f0ec3b750b59375eab5b0fb2b9254810c00a3375be6d789899f1055a1d556237"}, + {file = "markupsafe-3.0.4-cp312-cp312-win_amd64.whl", hash = "sha256:11935df9bf455ed0c04eb87bcd720f02b1fe5e02128a9430f23aed6f93336fc7"}, + {file = "markupsafe-3.0.4-cp312-cp312-win_arm64.whl", hash = "sha256:a4bbd2d87dd233b9fc5812160c3d0ffbe42edc22a26ce0469f58479ede633fe9"}, + {file = "markupsafe-3.0.4-cp313-cp313-android_24_arm64_v8a.whl", hash = "sha256:de8b364c423ef0a4bad9069657d617f9a5d2b2062457a89b1fa16ee199c399c1"}, + {file = "markupsafe-3.0.4-cp313-cp313-android_24_x86_64.whl", hash = "sha256:34bdde374c5932765d7dc685c4a1d191a3207852d67e8e0a9eb6ea85156181f1"}, + {file = "markupsafe-3.0.4-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:6bd9e1788e15bfcf6a9082de42e30387e7b85d211ab21e57a939bb8cfaaf8d96"}, + {file = "markupsafe-3.0.4-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:5066b244f576f91afc8ee3ba029a89f99d39c79b1853fe9d39bea9f0afbec148"}, + {file = "markupsafe-3.0.4-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:7a83aa6e4805df46fed18e989d3d16f86ef60cb50bbc8d9ce3a6be89165fbf6e"}, + {file = "markupsafe-3.0.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:2d1b7d9308288661f56672b1b157d75fc536714d3638487bbea17b6318a78248"}, + {file = "markupsafe-3.0.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:73e77980c7207854f00fc4e71fb1626868d5740ab4012623d55c7a99ad122a72"}, + {file = "markupsafe-3.0.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7018d4af1cd272e847aa5917983ab5e83e4f6579f9dbfecd4a79c0ca80b144c2"}, + {file = "markupsafe-3.0.4-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c90d5b3d4e944e065a301d741b3c1d784f6bd1f503aa68b4967e32b2ba313d85"}, + {file = "markupsafe-3.0.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:18a801868a884f216e784d7d14db2a4077143ce7610440aee2ce8f734e7cfcde"}, + {file = "markupsafe-3.0.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:434139499bb20b502ed3baa1f169e618f924a97e7a777fea1a49446d80106cf6"}, + {file = "markupsafe-3.0.4-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:9e227f3dbe6bde7491cf0a9965d00b88c6b1a4a95d11480ddf88bb96d397c19f"}, + {file = "markupsafe-3.0.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b8cd1f918b26fd7b1832ece557cc18f2d8747309ff8b3f0ef9d4250c5ad67a39"}, + {file = "markupsafe-3.0.4-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:a5fcffb37e602b0b3c1638a97746b9b96125caa9bcf6fa41d337a9261de231ee"}, + {file = "markupsafe-3.0.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:5989cb26b2e1efc6a42216a9f6b5ee495ce5ace2e5b352a9af489976b32d1ee2"}, + {file = "markupsafe-3.0.4-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:add96447a86d205ab616665d53b2950ee81083757f56e6ea833c8b2917646b46"}, + {file = "markupsafe-3.0.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:2628d3a8cb648ecebb3c5d6b0a1052d400e4d8b7ac0fb786be8d285b50040d17"}, + {file = "markupsafe-3.0.4-cp313-cp313-win32.whl", hash = "sha256:672d207103e6b16ca098611b0f9efad6bc00afd47c03d6ef62186495ca677dc0"}, + {file = "markupsafe-3.0.4-cp313-cp313-win_amd64.whl", hash = "sha256:1f1f9477e174582b0a1b583d60b66e1f2cf5d3fe12cee985e4aedf44766600e5"}, + {file = "markupsafe-3.0.4-cp313-cp313-win_arm64.whl", hash = "sha256:06de8ef6331f6e822c28d577dc8bf43fe398800477c49498f38fc38b67ff33fc"}, + {file = "markupsafe-3.0.4-cp314-cp314-android_24_arm64_v8a.whl", hash = "sha256:4ed644d75aa94a2baf7ec3a96eaa160ea58c742eb9d27c6506053c5c40fc84ed"}, + {file = "markupsafe-3.0.4-cp314-cp314-android_24_x86_64.whl", hash = "sha256:6d2a9efe686f9de00d0d1ea32a4a5a86d558a2277501bd78d964214eab625e59"}, + {file = "markupsafe-3.0.4-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:8781a792a070cf2bd1b86d3aa943894115faaba6e88122a7bf32d62072742453"}, + {file = "markupsafe-3.0.4-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:971a3bbb75d97ae4e2e8f7d4834236f86f85f0c85e04ab2e191db1123b04f80b"}, + {file = "markupsafe-3.0.4-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:8909c2f1c6dd65e054ac4b573a91c8384d1492281e55d82d159d653f7a13adf6"}, + {file = "markupsafe-3.0.4-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:4cf3468d5ec187ffffcaca8e61929a37448f215dafc1386a12c750a72fe53634"}, + {file = "markupsafe-3.0.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:52704c5d36eb6dda8866493decd61111fff86244c9b1ad225ca01b9e91e5970f"}, + {file = "markupsafe-3.0.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1caa2fa5a6184fb233153b35f654e6687bd555476f6170f29d8ee9be1a8b0af9"}, + {file = "markupsafe-3.0.4-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:387d8cd30e69b3f0a72877b9ae717033396404e19095b17fe89753a981fda44f"}, + {file = "markupsafe-3.0.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:051417f74bcaaefa316276e0ff723f541616ca51043d070da00249d9bddd3e3c"}, + {file = "markupsafe-3.0.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a8e9f292fcda89b324f2f5c91d13f1424a153e40fc2756f38ee23b15835ff300"}, + {file = "markupsafe-3.0.4-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:df1ae86ff54725a01fa1a0510b914ca53a161b7050be74f6204e24aded5971d0"}, + {file = "markupsafe-3.0.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:8965520ac587c94a4ac48b729be3d8b8de00af39699b17585dfb599babe77977"}, + {file = "markupsafe-3.0.4-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:340cbb1957ba99929cbf19a75626d36ba1ae21d1730b287d1cf7f824a20c4fc7"}, + {file = "markupsafe-3.0.4-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:3a93d9616ddecfb393727a0041a562cf0b15a244e20f2bd25efc7949be4c4f17"}, + {file = "markupsafe-3.0.4-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:d2e56fd3b00222722abfb3f5f0759ddbae4b90811b5ad4343c64030ad1bde70c"}, + {file = "markupsafe-3.0.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:0d9c47709875fdb321452056622e930c52afbc07a7d780762fbb8b4d91ce6fa4"}, + {file = "markupsafe-3.0.4-cp314-cp314-win32.whl", hash = "sha256:38fc55594dab834470b6733dead2ee9e3f657fb0608c769dcafa0ba5ab52f45c"}, + {file = "markupsafe-3.0.4-cp314-cp314-win_amd64.whl", hash = "sha256:c1bc67752d5f21013cfe430df4062441714eab79f65a6a05e01505957e9c35fe"}, + {file = "markupsafe-3.0.4-cp314-cp314-win_arm64.whl", hash = "sha256:7e1636da3d8dfc220b6dd10264db5f2b165e4888c4518594898fbe381049af8a"}, + {file = "markupsafe-3.0.4-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:805c8b84534fa10891890f0e4be39f3a99e94615d93e8836bf9fa1fdca2feeb2"}, + {file = "markupsafe-3.0.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:fa95848c929b6a75f6848d3c9793e59db365ee436776e57db835cdbfa79ba977"}, + {file = "markupsafe-3.0.4-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e916035e3e9930cbdfdd10abf48861340221857f45509565898e012263f7b289"}, + {file = "markupsafe-3.0.4-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:b4d12837e0203bbace818ff4a7461afdcd78bcd782351cea148139180d7bcffe"}, + {file = "markupsafe-3.0.4-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5086f9975abb1ab531ee6afca1761e4b59a19b446f3f6522ed776963228cfe5a"}, + {file = "markupsafe-3.0.4-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b4a635a0487774f841cb1fb62e907e7195cc95bc761e053184b8acc3ceb20733"}, + {file = "markupsafe-3.0.4-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cb96e6e088d6cf71c1ea977510948320234824cf226e32f6f6e044f7a9c82b34"}, + {file = "markupsafe-3.0.4-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8b5d563170ff8ba3181caa967c99a3c804d1dedb702c7cb93a6a7c32247da978"}, + {file = "markupsafe-3.0.4-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:396ec4e65cc889f69786b3b89478b471cee5a3bcf468b9d9bb03e1a30fb291fc"}, + {file = "markupsafe-3.0.4-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:15ba9e28640feef770374b116a6f019c21f52404aeabe516aa7f800587b98cfc"}, + {file = "markupsafe-3.0.4-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:d920abdfa61279ba1a2ef9484aab07bf03331f8c08a10120fa332353d06e6932"}, + {file = "markupsafe-3.0.4-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:a9f54054101545a9a9cccefddf54316aa6e4491611fcbef9e91b3b6bebec04f6"}, + {file = "markupsafe-3.0.4-cp314-cp314t-win32.whl", hash = "sha256:12a606a492de952afcb43b59a14aaaaad120e708d3663dd0fdf2d738d427a691"}, + {file = "markupsafe-3.0.4-cp314-cp314t-win_amd64.whl", hash = "sha256:a18f38cafc329bac5e3c2b96c765b4c96d3d103421ed22ab7988c1e3fce27464"}, + {file = "markupsafe-3.0.4-cp314-cp314t-win_arm64.whl", hash = "sha256:eba154571c16e032112afac0dc2dfe9e63c2ceb7aedd07bb7eecf2ce26d4dd4c"}, + {file = "markupsafe-3.0.4-cp315-cp315-android_24_arm64_v8a.whl", hash = "sha256:737c9c3981998eba27f11786f84fddcbabc74068b72a4a1f454ea02094b57b65"}, + {file = "markupsafe-3.0.4-cp315-cp315-android_24_x86_64.whl", hash = "sha256:489505b03f692c3f376394e49194fa7a7f9e8558d6e293a7056a0032b0c38163"}, + {file = "markupsafe-3.0.4-cp315-cp315-ios_13_0_arm64_iphoneos.whl", hash = "sha256:077293e425f28ec737dbcad442a71752e28f8ae27cde3d68acd1fb212091cd92"}, + {file = "markupsafe-3.0.4-cp315-cp315-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:9348cbb300d224fe3b89793262cb093504d4ae927004468463f745188a193e4a"}, + {file = "markupsafe-3.0.4-cp315-cp315-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:b807e598953730f82e4eae3bd30f6a122cf6b31c398c6b504c0e04c13c170429"}, + {file = "markupsafe-3.0.4-cp315-cp315-macosx_10_15_x86_64.whl", hash = "sha256:799c39bdf5e2f1292fedd3009f7b3c9e760f10b2420cb9638d56920840ff6db8"}, + {file = "markupsafe-3.0.4-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:ae9dcb8fbe244cb82f8a6458b455b927a03685e383d9bacf1ea5ce180b96dc97"}, + {file = "markupsafe-3.0.4-cp315-cp315-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4bced6e2a6dba6a28f7dd3c6ce14df1b2dd495923f16ea484cad03decd463b2b"}, + {file = "markupsafe-3.0.4-cp315-cp315-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3882fb412298575bae3b9c46868251f15cc69307359f87bb1b382e53d6e5a2c9"}, + {file = "markupsafe-3.0.4-cp315-cp315-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:04e7902ba80ee4bac1d50a549606527a1dcf0476cd81403db41099d3b60ec653"}, + {file = "markupsafe-3.0.4-cp315-cp315-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:925f929d6b59a8b3f8b8c6ac363cd0af7eecc81efb3071770b3c6717c450a369"}, + {file = "markupsafe-3.0.4-cp315-cp315-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f68edfc67aabac33708941f26f22a7b8e9f81429bc0cf249fcf7d66b23af8d19"}, + {file = "markupsafe-3.0.4-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:e5c802729725bd07e2bc3ab7b76dc7e0bbfc53129d8f1eb1c002c24cf774717e"}, + {file = "markupsafe-3.0.4-cp315-cp315-musllinux_1_2_armv7l.whl", hash = "sha256:55ffd6ce583d97dc71dc92e930324c8c0d25aea7e3ade6ae54ef77cedb096811"}, + {file = "markupsafe-3.0.4-cp315-cp315-musllinux_1_2_ppc64le.whl", hash = "sha256:2cb3dd71fc6be918ad4264346a8ed69485f9b7ed7bf35495d8e22807cd6b8bea"}, + {file = "markupsafe-3.0.4-cp315-cp315-musllinux_1_2_riscv64.whl", hash = "sha256:94f5407f7bc64fa6463906b896f9904beeeb7dd8dc116ee8e9056c8714ff9916"}, + {file = "markupsafe-3.0.4-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:2dad610540cb2e6272855c178f08ae9a1c7ac258a7fb71660553a5f104b42741"}, + {file = "markupsafe-3.0.4-cp315-cp315-win32.whl", hash = "sha256:03470d1a8268e692ecf79ecd565593e59d44219377a7ead61f1f1b94c1f7ff6b"}, + {file = "markupsafe-3.0.4-cp315-cp315-win_amd64.whl", hash = "sha256:d882a373d8093c2941e01291b7ced96e9cbe4781da9a7751ca7e6c70385e5214"}, + {file = "markupsafe-3.0.4-cp315-cp315-win_arm64.whl", hash = "sha256:353bd63081912ab8cfa6a0c7d185934cdf8426f04c618bba6bc4b394f2069b67"}, + {file = "markupsafe-3.0.4-cp315-cp315t-macosx_10_15_x86_64.whl", hash = "sha256:c61750fadcd119d0825bcb7d7d675dd264dcc89cc05292aab5be68ebdbb374ad"}, + {file = "markupsafe-3.0.4-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:1c0df495a977d10460a94941799c72d5b5ab03d3858d949b55b5a66c8f371c99"}, + {file = "markupsafe-3.0.4-cp315-cp315t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:02fa4acbc6a3fc5c693c34d4dd8c1130b7fe99cc915181b0ddd6f72aeb296002"}, + {file = "markupsafe-3.0.4-cp315-cp315t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:05295589e619b9bed252a86b532b8e27350abc372d18ba89b59375325e91ec1e"}, + {file = "markupsafe-3.0.4-cp315-cp315t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:be6cb0c799abb0e2ba3e618e6d28ddddf7e485f6c2ce938dfa237daf3905072c"}, + {file = "markupsafe-3.0.4-cp315-cp315t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:26e9867520db70d37f7fb421a7f0d8adb40171011fb84ce869afa1a83370dfa8"}, + {file = "markupsafe-3.0.4-cp315-cp315t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f03460ff076f70ab595bb45a0205ccea1971443575b6920c52e755dec2b3fbfe"}, + {file = "markupsafe-3.0.4-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:436e3ffc6310d3c41878c601db29098102fe5d8a467c49da4a4125254e0980f2"}, + {file = "markupsafe-3.0.4-cp315-cp315t-musllinux_1_2_armv7l.whl", hash = "sha256:4e2c4809c14559aa7ef426f27fb35afbb38104c349a903bf8f3600456764bb38"}, + {file = "markupsafe-3.0.4-cp315-cp315t-musllinux_1_2_ppc64le.whl", hash = "sha256:da2af0d7aebfc2074080d72efa6ab8317c62481ef1f896f65d9999c1c01f4494"}, + {file = "markupsafe-3.0.4-cp315-cp315t-musllinux_1_2_riscv64.whl", hash = "sha256:aa2c838cc024642cc04c6854232f32b43e5e22833dd11119c1766c7873b8370d"}, + {file = "markupsafe-3.0.4-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:b91cc9d336957239ff200f30097e6fea2dc6d6fb3c81e853eaa09eac904fd894"}, + {file = "markupsafe-3.0.4-cp315-cp315t-win32.whl", hash = "sha256:e49fb0d1ce92cfa0cb198cc5b1b11cdf9d0638658e2a2db2687e39db7c87fc78"}, + {file = "markupsafe-3.0.4-cp315-cp315t-win_amd64.whl", hash = "sha256:4f6e0852a0283b1b1fd776eeb7b766a5f440b3e2bd31ab51af3b400585f3965c"}, + {file = "markupsafe-3.0.4-cp315-cp315t-win_arm64.whl", hash = "sha256:39dbacefc411633db5b4378b066a9aca70a3d7e2922c9e578d825f844026eeba"}, + {file = "markupsafe-3.0.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f291bcf42ae98eb5107edb162c3c998b4a89648fd8e99ed4cbd12705292788cd"}, + {file = "markupsafe-3.0.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ac0c7c9f1609b0c4c114feb1d7a3409564c7fb77e360bed9e97e5d25dfeaf868"}, + {file = "markupsafe-3.0.4-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6768d67d1bce64270e0fdc2e69309d68b9b18ae56ddf6c711d168e9d051c2cac"}, + {file = "markupsafe-3.0.4-cp39-cp39-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:14bd2d845d62ab678eaf81da89d7b621b51756c72346745c1a594c09d49207a2"}, + {file = "markupsafe-3.0.4-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:007e1ffd9bf65bb6ee96df7b258fc632a4868dd5566037986c64781f35a36e98"}, + {file = "markupsafe-3.0.4-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5e8b3d0b18fd623afa12ecb2ce8d8becef69f9b5440c6330c7972200e0bb84b0"}, + {file = "markupsafe-3.0.4-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:57f9947a7e57a081c1e3e0a2dd0d2dcf290a4531450e6f611e30084c222a7295"}, + {file = "markupsafe-3.0.4-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:b61687d0828e72bf5cda24a2690188f37170bd31c9359ac97e4e66569f120a16"}, + {file = "markupsafe-3.0.4-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:0cee7cb0f9a1b6892ea482237d9403b3d1b4603aee057d0ff01f0fac2d019a97"}, + {file = "markupsafe-3.0.4-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:94e4c421742086aeee4c32a506eec8859d7634aad943f7e6aacf70f813478768"}, + {file = "markupsafe-3.0.4-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:9240187afb63d2f9ddc3e032c670356fe941f6e20662ea168a5dc3f1f317e1b3"}, + {file = "markupsafe-3.0.4-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:e841068dc0be4cb6dfb5c890eb88cbdcff2f4a332393c7ec94e8e618bd32c1a8"}, + {file = "markupsafe-3.0.4-cp39-cp39-win32.whl", hash = "sha256:f61efe1d2fe0de16158a5fe1d1cf3c14bdb6aecd54d8938fd26512c525c1f624"}, + {file = "markupsafe-3.0.4-cp39-cp39-win_amd64.whl", hash = "sha256:2b2b1e18af909b448bb3cf9e3433366f7a8726271fc214e8b10e0f62a78c724b"}, + {file = "markupsafe-3.0.4-cp39-cp39-win_arm64.whl", hash = "sha256:6669c1bf34080161ce49c589cc512ef24d4c704ac9d2b2d3667f519c60418378"}, + {file = "markupsafe-3.0.4.tar.gz", hash = "sha256:2e9ad7dd851bf45fab9f75cbff4cb493fee9979e8d8c7c9c3ee119022518edd6"}, ] [[package]] @@ -1504,14 +1703,14 @@ files = [ [[package]] name = "moto" -version = "5.2.2" +version = "5.2.3" description = "A library that allows you to easily mock out tests based on AWS infrastructure" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "moto-5.2.2-py3-none-any.whl", hash = "sha256:3817f1e39721ca833579b921e53e3b68547ace6a34d848c9486fbb5905808de9"}, - {file = "moto-5.2.2.tar.gz", hash = "sha256:aac8023a429e125e91c91f8f4730a67b54f518cda587352f7e67252fe3168f75"}, + {file = "moto-5.2.3-py3-none-any.whl", hash = "sha256:5ec31b3cdbb383a19d46030157bd82aaaa7a9cc5f564200f995663d347bd4728"}, + {file = "moto-5.2.3.tar.gz", hash = "sha256:a9e95c3218b6eda18e74571f1ced11cb1bc3151467d562c1da6037b9d19832cb"}, ] [package.dependencies] @@ -1619,14 +1818,14 @@ reports = ["lxml"] [[package]] name = "mypy-boto3-s3" -version = "1.43.5" -description = "Type annotations for boto3 S3 1.43.5 service generated with mypy-boto3-builder 8.12.0" +version = "1.43.106" +description = "Type annotations for boto3 S3 1.43.106 service generated with mypy-boto3-builder 8.12.0" optional = false python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "mypy_boto3_s3-1.43.5-py3-none-any.whl", hash = "sha256:7cd836cf3ec384b6a05b108047034ece03bb7dd0bd0890c527673eafc44907bb"}, - {file = "mypy_boto3_s3-1.43.5.tar.gz", hash = "sha256:ba67dbc3da825b6818839db3823722f3b12304dd116e94ed398eb7ade86b0f62"}, + {file = "mypy_boto3_s3-1.43.106-py3-none-any.whl", hash = "sha256:e233d04dbcf3925522dff4346e75c37344ec3d1cbb82337e5eed2af263847668"}, + {file = "mypy_boto3_s3-1.43.106.tar.gz", hash = "sha256:731195f15830699a36e29d3c8abb2918bccd3587eb2edcb233f8046967893279"}, ] [[package]] @@ -1643,49 +1842,52 @@ files = [ [[package]] name = "networkx" -version = "3.6.1" +version = "3.7" description = "Python package for creating and manipulating graphs and networks" optional = false -python-versions = "!=3.14.1,>=3.11" +python-versions = "!=3.14.1,>=3.12" groups = ["main"] files = [ - {file = "networkx-3.6.1-py3-none-any.whl", hash = "sha256:d47fbf302e7d9cbbb9e2555a0d267983d2aa476bac30e90dfbe5669bd57f3762"}, - {file = "networkx-3.6.1.tar.gz", hash = "sha256:26b7c357accc0c8cde558ad486283728b65b6a95d85ee1cd66bafab4c8168509"}, + {file = "networkx-3.7-py3-none-any.whl", hash = "sha256:e3fd2c13a7814cee3746340d8d7f8598a67f16a58bf47fb7f8793fab6efca1b0"}, + {file = "networkx-3.7.tar.gz", hash = "sha256:fd77a511bd90f39f3d016351345b52cf5319b813bdca01de3f755d3cca62e96a"}, ] [package.extras] -benchmarking = ["asv", "virtualenv"] -default = ["matplotlib (>=3.8)", "numpy (>=1.25)", "pandas (>=2.0)", "scipy (>=1.11.2)"] +benchmarking = ["asv (>=0.6.5)", "py-rattler (>=0.21,<0.22)", "virtualenv"] +default = ["matplotlib (>=3.10)", "numpy (>=2.2)", "pandas (>=2.3)", "scipy (>=1.15)"] developer = ["mypy (>=1.15)", "pre-commit (>=4.1)"] doc = ["intersphinx-registry", "myst-nb (>=1.1)", "numpydoc (>=1.8.0)", "pillow (>=10)", "pydata-sphinx-theme (>=0.16)", "sphinx (>=8.0)", "sphinx-gallery (>=0.18)", "texext (>=0.6.7)"] -example = ["cairocffi (>=1.7)", "contextily (>=1.6)", "igraph (>=0.11)", "iplotx (>=0.9.0)", "momepy (>=0.7.2)", "osmnx (>=2.0.0)", "scikit-learn (>=1.5)", "seaborn (>=0.13)"] -extra = ["lxml (>=4.6)", "pydot (>=3.0.1)", "pygraphviz (>=1.14)", "sympy (>=1.10)"] +example = ["cairocffi (>=1.7)", "contextily (>=1.6)", "hiveplotlib (>=0.28)", "igraph (>=0.11)", "iplotx (>=0.9.0)", "momepy (>=0.7.2)", "osmnx (>=2.0.0)", "scikit-learn (>=1.6)", "seaborn (>=0.13)"] +extra = ["lxml (>=4.6)", "pydot (>=3.0.1)", "pygraphviz (>=2.0)", "sympy (>=1.10)"] release = ["build (>=0.10)", "changelist (==0.5)", "twine (>=4.0)", "wheel (>=0.40)"] test = ["pytest (>=7.2)", "pytest-cov (>=4.0)", "pytest-xdist (>=3.0)"] test-extras = ["pytest-mpl", "pytest-randomly"] [[package]] name = "nodeenv" -version = "1.10.0" +version = "1.11.0" description = "Node.js virtual environment builder" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" groups = ["dev"] files = [ - {file = "nodeenv-1.10.0-py2.py3-none-any.whl", hash = "sha256:5bb13e3eed2923615535339b3c620e76779af4cb4c6a90deccc9e36b274d3827"}, - {file = "nodeenv-1.10.0.tar.gz", hash = "sha256:996c191ad80897d076bdfba80a41994c2b47c68e224c542b48feba42ba00f8bb"}, + {file = "nodeenv-1.11.0-py2.py3-none-any.whl", hash = "sha256:edaa16e6c14d7cf395d75d4bbd5a26390f4dc06501a33b4e76282b02cc688a25"}, + {file = "nodeenv-1.11.0.tar.gz", hash = "sha256:3ce8fe5b71d16e8af7039ca65257354100bc772965d6bc549070649e53b1b146"}, ] +[package.extras] +certifi = ["certifi"] + [[package]] name = "oras" -version = "0.2.42" +version = "0.2.43" description = "OCI Registry as Storage Python SDK" optional = false python-versions = "*" groups = ["main"] files = [ - {file = "oras-0.2.42-py3-none-any.whl", hash = "sha256:d1e2184d42ce99258bd0ad56d932b0f4fce289bccf1b5094436a29579f385728"}, - {file = "oras-0.2.42.tar.gz", hash = "sha256:51d17088e5dffdeb585dd930bdccb4329762bef4af3f18600392ebae525a9231"}, + {file = "oras-0.2.43-py3-none-any.whl", hash = "sha256:bf295b1cfb5017f579c35c3394c7a71707f6aff463cb6699d5d191a6d8b56ea6"}, + {file = "oras-0.2.43.tar.gz", hash = "sha256:761f2b518fce50e5e9482975363ff0230f63fc65f84c09510fbcc301782a047c"}, ] [package.dependencies] @@ -1700,14 +1902,14 @@ tests = ["pytest (>=4.6.2)"] [[package]] name = "packaging" -version = "26.2" +version = "26.3" description = "Core utilities for Python packages" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" groups = ["dev", "docs"] files = [ - {file = "packaging-26.2-py3-none-any.whl", hash = "sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e"}, - {file = "packaging-26.2.tar.gz", hash = "sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661"}, + {file = "packaging-26.3-py3-none-any.whl", hash = "sha256:d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c"}, + {file = "packaging-26.3.tar.gz", hash = "sha256:94edc256424af38762eb31306eed28beb9f0efc50a8837492c9d6fd6004aed79"}, ] [[package]] @@ -1729,14 +1931,14 @@ re2 = ["google-re2 (>=1.1)"] [[package]] name = "platformdirs" -version = "4.9.6" +version = "4.12.3" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "platformdirs-4.9.6-py3-none-any.whl", hash = "sha256:e61adb1d5e5cb3441b4b7710bea7e4c12250ca49439228cc1021c00dcfac0917"}, - {file = "platformdirs-4.9.6.tar.gz", hash = "sha256:3bfa75b0ad0db84096ae777218481852c0ebc6c727b3168c1b9e0118e458cf0a"}, + {file = "platformdirs-4.12.3-py3-none-any.whl", hash = "sha256:080f3b39423b5abfca9a23d84c4e9795f54d395cd8459867a8ded44084fcd5f8"}, + {file = "platformdirs-4.12.3.tar.gz", hash = "sha256:427fc0bb321ae0c5b037fa03238ca74820437be162e78b4848c4d4055b9b766c"}, ] [[package]] @@ -1778,14 +1980,14 @@ test = ["coverage", "fixtures", "pytest", "requests-mock", "tox"] [[package]] name = "pre-commit" -version = "4.6.0" +version = "4.6.2" description = "A framework for managing and maintaining multi-language pre-commit hooks." optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "pre_commit-4.6.0-py2.py3-none-any.whl", hash = "sha256:e2cf246f7299edcabcf15f9b0571fdce06058527f0a06535068a86d38089f29b"}, - {file = "pre_commit-4.6.0.tar.gz", hash = "sha256:718d2208cef53fdc38206e40524a6d4d9576d103eb16f0fec11c875e7716e9d9"}, + {file = "pre_commit-4.6.2-py2.py3-none-any.whl", hash = "sha256:e2dde9a75d3bce11bd3831c26d134df00a2803c1d818be6a0383c3dcda25dc4e"}, + {file = "pre_commit-4.6.2.tar.gz", hash = "sha256:8f5d7bfb021ecdbcd9d49d89847082dd24172ccde534390081a679ad046e2441"}, ] [package.dependencies] @@ -1810,68 +2012,78 @@ markers = {main = "implementation_name != \"PyPy\"", dev = "platform_python_impl [[package]] name = "pygit2" -version = "1.19.3" +version = "1.20.1" description = "Python bindings for libgit2." optional = false python-versions = ">=3.11" groups = ["main"] files = [ - {file = "pygit2-1.19.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:59bca67a3f2af724659494bec9fed288b99242be13d76349d0170177512712fa"}, - {file = "pygit2-1.19.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bb2e65666356f072d774f935aa0858f68ea34644d7a1467ea4918470748a2722"}, - {file = "pygit2-1.19.3-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0424822de48cb466f54c45c4d73924be201fd8ad347ccf0545fe7e601f056ebb"}, - {file = "pygit2-1.19.3-cp311-cp311-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e6aeb43e12fde33ec981209da90f66076e956538e457e4a50ba1665f97e3b2ea"}, - {file = "pygit2-1.19.3-cp311-cp311-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:eaf59b7f6435c276850d34392503b55e703392094ff4c87c3c0a4161b3d90133"}, - {file = "pygit2-1.19.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e536656457dd306d0ebae2ac442c2c8f8798ea2333095b85391bc3423f4ac1b3"}, - {file = "pygit2-1.19.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:38d52f8d30bf969e3bfcab22cf5cdc4dc69590e06e8e948b1bb25cccb3bbbe3d"}, - {file = "pygit2-1.19.3-cp311-cp311-win32.whl", hash = "sha256:8b7a0a16372b245d065efb10a4ef5d61dc08794a69fa8ed6dd1ff918409b7d84"}, - {file = "pygit2-1.19.3-cp311-cp311-win_amd64.whl", hash = "sha256:2b8f748836ac00fd785373ef8f5c9be1ed509e357cb270cc3f5674c0ad44d44d"}, - {file = "pygit2-1.19.3-cp311-cp311-win_arm64.whl", hash = "sha256:98f2241ef66ec97ab21a2a1a6851c1305929c7a9e9e3e94db5faeb5d2ed06aa2"}, - {file = "pygit2-1.19.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d696ee240cc8b84e747b04443d85768c859ef0b88abe4a3505dc0b8e2a953ca0"}, - {file = "pygit2-1.19.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:86318a704bef836067fa9ac06c56591738d548dcdf2ea24ec227257e3f8115f8"}, - {file = "pygit2-1.19.3-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dc3ddb3e5d16cf662d2d0faeb53259e31ae584cc990cd76df909beeb4a36736a"}, - {file = "pygit2-1.19.3-cp312-cp312-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:73820fb34339fe3c52731d1c46c298a3239ee75b61bc3a2d9b45f8b8873acc47"}, - {file = "pygit2-1.19.3-cp312-cp312-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:20f6ad50608f51b053bf6c321ae2c31cc57f15e4131a4609261c44e29bdae7cb"}, - {file = "pygit2-1.19.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b2c63c7a371dbd5825e5fb7069b759c79aa5dec97806d49cb2c9f9a8a373209d"}, - {file = "pygit2-1.19.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:977eb52cd4134ff60d3faa168327a03f8724278c38bfcd347d8e3a11041ee9cd"}, - {file = "pygit2-1.19.3-cp312-cp312-win32.whl", hash = "sha256:14a2734d793d2d937d3bfc9d35b280ec83fc97a91b1934b1013554d41e6d3d70"}, - {file = "pygit2-1.19.3-cp312-cp312-win_amd64.whl", hash = "sha256:a7caeaf46aaa8e51c512af9ac1377f388e4836c9d042e134bbc5e22519fbd1bf"}, - {file = "pygit2-1.19.3-cp312-cp312-win_arm64.whl", hash = "sha256:2aafa010e3ac227913f398c8a680bce419e396dfe651685fffb779ed1c109a00"}, - {file = "pygit2-1.19.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:9238bf7a8a953f4faedcbe90eb097b760a2709c7e7ab38edcf18dc2d0ce9dcff"}, - {file = "pygit2-1.19.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7f999a4995504a6c14443de9481b7c6c54802663fe80c7504e1b946348f43786"}, - {file = "pygit2-1.19.3-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0918bc9b7597f243aa4b9c785912ae853e9aee4f572bcd5c9c591fcb703542f7"}, - {file = "pygit2-1.19.3-cp313-cp313-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:18403fee0171867be5fc1c1415bcd5d5a7fab51299bdd44bcf467c22a868fd22"}, - {file = "pygit2-1.19.3-cp313-cp313-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cacece712337029092a98cf1af8d244e92fa8b36e5a64d7e14212ff73ea821e8"}, - {file = "pygit2-1.19.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:49d7c494bdaa5a8da366e4c4b7c822e52bd33bb6f22c67f8585b5396e91f8ac7"}, - {file = "pygit2-1.19.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:2bbe74fbe553c6f991512391822c27c9321e3a0b45cab872f45c8d458393eee3"}, - {file = "pygit2-1.19.3-cp313-cp313-win32.whl", hash = "sha256:3ab184751ca7a92007dbd8ae4ae4ac3b7228ef60ae2d2e18129b44bbe5c0aa4c"}, - {file = "pygit2-1.19.3-cp313-cp313-win_amd64.whl", hash = "sha256:522d9c6ab9206880dceaae5516720c0f0df706859d2ba97f49adcaeea2d661bd"}, - {file = "pygit2-1.19.3-cp313-cp313-win_arm64.whl", hash = "sha256:c77d5a1334ca3f1432c83457e03be8759d8e9040e0d25c59c738f2318545654a"}, - {file = "pygit2-1.19.3-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:214140f2201474e9d8e3889e5635e323aa90a58e6ae224a9de56be83d3e9b747"}, - {file = "pygit2-1.19.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:46fc9fd234b2a38176625af6bfd2dbad99ab937379a980761c59a343bdff4910"}, - {file = "pygit2-1.19.3-cp314-cp314-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:eb9f46b561ee53f22cb479e7fdefd7b8ae478d12656436a48166c2ad81a3c021"}, - {file = "pygit2-1.19.3-cp314-cp314-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9f393932fadd8e74f26d7ebb58da649e7a188d9156b732dd6c9f0dfc273d4430"}, - {file = "pygit2-1.19.3-cp314-cp314-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c9521a9b45de3affd82618e94f7e5116685e695e65fcbf67b2f1e44a086c0f4a"}, - {file = "pygit2-1.19.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:241f0fcd2aaf025e9fb5e1887eac5f244cb6b0a6e83dc27d673fa634ab0e0ee3"}, - {file = "pygit2-1.19.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:c1729caee68cdf35c0cdb913de3850724438e4bdf480742da4f21a3e86d83662"}, - {file = "pygit2-1.19.3-cp314-cp314-win32.whl", hash = "sha256:2c300d234ef15e4c557a7e9ac880163606b364d0d4e20ddbf1204b4ee9f9b61c"}, - {file = "pygit2-1.19.3-cp314-cp314-win_amd64.whl", hash = "sha256:0ff9f187b01d6629c14ad069b100e147093b70279496984faa012783c5832b66"}, - {file = "pygit2-1.19.3-cp314-cp314-win_arm64.whl", hash = "sha256:cdfbf879ee0d468d7929eb26e35db7442b56a411af1d5b7d28e858cccf71598a"}, - {file = "pygit2-1.19.3-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:79a3b565e20bbbbf21d29de1675a18e0e556545a2c738f38c0ac0435269f56bd"}, - {file = "pygit2-1.19.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:828856512070cda223c19046b02af50135a5b0efa274a80fbf7c82d773f8e89f"}, - {file = "pygit2-1.19.3-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:eec2b1d50bf52d2139d3d478d6d5f5ee56103da4a6dbd786344e8a85254dd07b"}, - {file = "pygit2-1.19.3-cp314-cp314t-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:dbfa10f22670e7fef13bf249c32aebcafe23115790155d6b71efafb9aa7d4cba"}, - {file = "pygit2-1.19.3-cp314-cp314t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d22c2940bde27f9ffe095aac87e7c8b8a9c787f91782c7463387d39a2592d04c"}, - {file = "pygit2-1.19.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:0ed9f15b4b0b80191669fdf5b702b697ffbc245d24995befa80e46bef3aea25e"}, - {file = "pygit2-1.19.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:40f1253e042d0a5dfed16eec92b5b28a529c2873f4ee77ca60d1ea7b79a14600"}, - {file = "pygit2-1.19.3-cp314-cp314t-win32.whl", hash = "sha256:245d627a8ae3f35dafd9ce5b35538ddb5ba0c3fe6be8d2f9aa410f93a9184b83"}, - {file = "pygit2-1.19.3-cp314-cp314t-win_amd64.whl", hash = "sha256:8d2e3044ac1b09ef9120deb1896a56423c6dd17eb5ac4012c3c49dd590ee4910"}, - {file = "pygit2-1.19.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ef2790c9ff7e7673d7262e9e059c5af86c09197037073fd004d22a63e4151291"}, - {file = "pygit2-1.19.3-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7a1fe33a036aa2172934cafbdd17e2a0f3a73477727fc147e94f881bfe3961c2"}, - {file = "pygit2-1.19.3-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:09db53b92c546e621218fb82a97149dc7a155a8323a3dbce6b5048da70b0c00c"}, - {file = "pygit2-1.19.3-pp311-pypy311_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c14d61de0c803188a0481d394a8ba61c7e1c38210a1e525097f18a0ad563009e"}, - {file = "pygit2-1.19.3-pp311-pypy311_pp73-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:806d1e22d3828ea6767fb025f355374d6dd562161a0312f995723ab15e1de42d"}, - {file = "pygit2-1.19.3-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:5af3422728f61958b6a0faaf7de754ecae5bed689adc31d1b727da3c697a752b"}, - {file = "pygit2-1.19.3.tar.gz", hash = "sha256:a543e6d4ebb43825564935758dc234e770016fed673b84370d46ae9580558831"}, + {file = "pygit2-1.20.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:46664438cc9aadb342df445be15d96c4bea77544ac641ab79d2977dccd0f0948"}, + {file = "pygit2-1.20.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bd18be3dcb5d0d1723f9294748f681d7206ad5e54202e862239f07f10e006803"}, + {file = "pygit2-1.20.1-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:daa99ea66858b50ad1f6eab699d9cfe3b8c2c43e17296a5c9af6c71fa8d96576"}, + {file = "pygit2-1.20.1-cp311-cp311-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9eef7be5132651da77b6278330cde2b776f8503e1a7a9058c790b0cb62dfbb5e"}, + {file = "pygit2-1.20.1-cp311-cp311-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6f6f393dd052e1f635ea9f6b7d825cd9c8cd1c9462f68a197eab086657c7cf65"}, + {file = "pygit2-1.20.1-cp311-cp311-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ee44842ec283a6d0d382a9df17ae757c1c2f975fa2e39b37bceaa5e3528dca29"}, + {file = "pygit2-1.20.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:af88e5e152c35919fc18de2c588434919e491a387316e9232faa9c615aa88904"}, + {file = "pygit2-1.20.1-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:da44497239265ff0bf6b706ca71578399254a954aa4d8eb780cfab075893419e"}, + {file = "pygit2-1.20.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e387b02ab5ef01f03ba84ac0a300c3b13cf427d9063dba0fb4a66a6cf23783e0"}, + {file = "pygit2-1.20.1-cp311-cp311-win32.whl", hash = "sha256:2b321fd4e29c4ce8b46108730ef3e145cd3b7de5fd118cac8cabcc5d9ae989f5"}, + {file = "pygit2-1.20.1-cp311-cp311-win_amd64.whl", hash = "sha256:4c5d154468206cf617340e7c9e96b53fcfee0c180cd38834c1dcdc5b0d0be8af"}, + {file = "pygit2-1.20.1-cp311-cp311-win_arm64.whl", hash = "sha256:72a4b9efdb1bbeb97ba466ac1c02f2bf7ed1edffd96d02a146017228eac68191"}, + {file = "pygit2-1.20.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a0a1353e1e0074bc79f506c60b63dd6b59ff60a1f21570cb9721ce73ac3b8262"}, + {file = "pygit2-1.20.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8537a48ab25338f38d5707e8d34d8817eb7cc492fe551ef0219980fe6f77cd8d"}, + {file = "pygit2-1.20.1-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f09a132454dbc97f80fb8155fe5d2cc40b1924827c42e8c741b9950af6a509ef"}, + {file = "pygit2-1.20.1-cp312-cp312-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1d60a644d1280210f88e00ebe9929212eb74b0e32260c61c22c0d148fe8d0afd"}, + {file = "pygit2-1.20.1-cp312-cp312-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:39724d0d4f922058e1105c6a084f5c801eef6b7991033e6cb8d3efd174ef5338"}, + {file = "pygit2-1.20.1-cp312-cp312-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:befdb91f1d5f09981289d9785948a4f902cc3a961904bf9ae40010ef71fd51b4"}, + {file = "pygit2-1.20.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f25df036a3ea4fcaa5051a1cc3adc1ed62e328a3a68b139ceb41b344882c6ea8"}, + {file = "pygit2-1.20.1-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:009b2b5d2eb01f5da2d6dcdd51acf67478dcf953799c0d1f425b04e60f4fd3d8"}, + {file = "pygit2-1.20.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:579ab2893420983662bdd1a6870f889e03674fb9c9dc314075083b7f741d3bf5"}, + {file = "pygit2-1.20.1-cp312-cp312-win32.whl", hash = "sha256:532a63e6a6f2457465d1c1497a3dabc2676daf17d7c8d919246cfc99137e3e57"}, + {file = "pygit2-1.20.1-cp312-cp312-win_amd64.whl", hash = "sha256:0bab03e4879ea55fd9c7b16c2d28d8023484c82e1d145fad67b1ac0efca596f2"}, + {file = "pygit2-1.20.1-cp312-cp312-win_arm64.whl", hash = "sha256:38e663e69224d02611c7293d9bd633a2237560d730db7c3d9fd3662a468105ef"}, + {file = "pygit2-1.20.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:21adc71ee1ac877b00118c21d5f20150c90443e04b60e4da7e9db8504aaf048b"}, + {file = "pygit2-1.20.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e60f5d8a01593d8d51c97325a7b6b5b1f644fccef1f54c1b0a6d47f11ab359c1"}, + {file = "pygit2-1.20.1-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e958111749908c4f1989e33f3a98754eda56b3279e56bfab6d6fb513a7ea688c"}, + {file = "pygit2-1.20.1-cp313-cp313-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:96f45b908d3daaea084f2ed659b1227a1727691a5a980a9bec3e37541afc1f22"}, + {file = "pygit2-1.20.1-cp313-cp313-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0f65c55b5217dd2cea0fefe287624bb9522266d984a06d1e87c1879cf6bd7585"}, + {file = "pygit2-1.20.1-cp313-cp313-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:7a1201c416db8e9ad572a389299c2db9df36d613676599f0984b78446db55437"}, + {file = "pygit2-1.20.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:083df8b7b113afe3ceabdf17be8e7e4156f2938e22d2b3d17c96965568eea1b7"}, + {file = "pygit2-1.20.1-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:2e8a64a50f8ad839acbf069f2552046bcafb01ccbe632dcb64cb29417f870ed1"}, + {file = "pygit2-1.20.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:cb369a00ebb1eb513c5219d9975bbd7d6a0e9b551c5440299142a21354b7d121"}, + {file = "pygit2-1.20.1-cp313-cp313-win32.whl", hash = "sha256:2eef49c2d0f1aa089c60b92f2b20604e3f27991bd1ceb8a8a51fb13075ce8427"}, + {file = "pygit2-1.20.1-cp313-cp313-win_amd64.whl", hash = "sha256:5e4d6e37db59712e3f2148c33464536faf32bc863d283d97ebd280632ed5f138"}, + {file = "pygit2-1.20.1-cp313-cp313-win_arm64.whl", hash = "sha256:fe108609d988fee5bab198f2ad2cbbe9b5eb08c64919c0f68fcdb7adf6d5f3f0"}, + {file = "pygit2-1.20.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:ceaa949c826975addc1cfb7d9b487714e9fded04cca9dcf9b7a844ae2da8657b"}, + {file = "pygit2-1.20.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:6c69da2cd18366c2b9827d9a9c7ebb9dc593fea5defbbc9b7704c8a6222a7d56"}, + {file = "pygit2-1.20.1-cp314-cp314-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3d507bf62f5d447e382667411972921e0afe923e9567f3476a1f7b73db8bf49b"}, + {file = "pygit2-1.20.1-cp314-cp314-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:edc36d68a9fc632ba8cf54dc2823aa03bee966d2e787aaed35fff606996519c0"}, + {file = "pygit2-1.20.1-cp314-cp314-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:860c971fd53a9f14713a51b6343827b82d2b7dc7955e8c28c81ca3c90033b6a2"}, + {file = "pygit2-1.20.1-cp314-cp314-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:523a1571a55e4dbb33bd052ed72132ffe02e204fab5229b840ffadb9ec62e671"}, + {file = "pygit2-1.20.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:e40c7221c781a5421405155f1664f216ee2611ee5bf377aa4d4df446f50950fb"}, + {file = "pygit2-1.20.1-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:2759b548ee9c5812cc34660c02076aa4a92d9a0c75678fcbf7ca9def9120bd7a"}, + {file = "pygit2-1.20.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:4455105391f0ca6e35f5d340348ad98811de5a09f50fe832b6f44f8d97286f08"}, + {file = "pygit2-1.20.1-cp314-cp314-win32.whl", hash = "sha256:bec861767a185d281cbf71620ecfe92cb529cd8a9acf3fa18d0820accae9debc"}, + {file = "pygit2-1.20.1-cp314-cp314-win_amd64.whl", hash = "sha256:b6630a7a61dbd831b2731ac715257851325daa839a3d1251d27f968e33866a19"}, + {file = "pygit2-1.20.1-cp314-cp314-win_arm64.whl", hash = "sha256:e7b6704ba134bf6d91d161844771f8501b909adf8feb8a479d8f95477ea253ea"}, + {file = "pygit2-1.20.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:befbfc4841e8018de7ffb364675449dbea847b95ddf4d5116da07ed9566551ba"}, + {file = "pygit2-1.20.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1ecb9382e94a7cc55339c7dd0024c011746a400543f61e518736012effad4fb4"}, + {file = "pygit2-1.20.1-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:10f872e4b57f7172ae07fb7f0080f4681ccecf9e779a816a0c6e55a0f96921f9"}, + {file = "pygit2-1.20.1-cp314-cp314t-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e8c8ba963914a9797548a44baa798614a93f222f8cd41ea2ca3cc1e91a911f88"}, + {file = "pygit2-1.20.1-cp314-cp314t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9ebf99b3eae022e8d67141cd89f73ab408f93870a0a3a38f4372c5c7b107346e"}, + {file = "pygit2-1.20.1-cp314-cp314t-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b7261f02e88b1dde453f340534eca6d70116a952e2ee6949b0f061fbe75c01dc"}, + {file = "pygit2-1.20.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:ea9e46030542223016880664a12b6387be6da6f8177f90b4f96b6f26e2e59b23"}, + {file = "pygit2-1.20.1-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:b0daf388b21f71c3e5e52a1168911feef36e6a5eff32a0c1bf78e23ace1e2d1d"}, + {file = "pygit2-1.20.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6cb313dd02e71d2b79b512040ebc5ff15189043d00c550594e2df920ab51bea1"}, + {file = "pygit2-1.20.1-cp314-cp314t-win32.whl", hash = "sha256:0217a3432b7af85c2946126b9369a16d5b4b4e7a61207b825a3d680d757c8561"}, + {file = "pygit2-1.20.1-cp314-cp314t-win_amd64.whl", hash = "sha256:030b2d60b82ff29ab66b73ec76a6e15298019d0ea963f8882ea6b7cc1c48fe0e"}, + {file = "pygit2-1.20.1-cp314-cp314t-win_arm64.whl", hash = "sha256:57473456976183d2b74e4ad4804e515ed648ed5fafe2c901ef166bcbd386668f"}, + {file = "pygit2-1.20.1-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:bb1ec65b486c1f06bb51945d73cb785f91ee34cdcee85217ed277aa68c429fe5"}, + {file = "pygit2-1.20.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:b15a1c21f39a8e1fc3d09179d9ad435f8db9ad1a39ed54afe8c00f8b9b6fab2f"}, + {file = "pygit2-1.20.1-pp311-pypy311_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0faa5da9a2ca5bd54b02157497588c46f1d2ca463868718922923f79b05191fa"}, + {file = "pygit2-1.20.1-pp311-pypy311_pp73-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d4a1af34170d1f8a1d788c8611a7465a4a834baa7daa3d380b1ef4391726e23a"}, + {file = "pygit2-1.20.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:6477884c76a5197138bc2abd1a5e36b6d45a8cf836290fa06289adb48a641437"}, + {file = "pygit2-1.20.1.tar.gz", hash = "sha256:36dff84d237f2b8f18b0b146d6e7c3f99a7bce2da98cc4103a14387f53319f95"}, ] [package.dependencies] @@ -1879,14 +2091,14 @@ cffi = ">=2.0" [[package]] name = "pygithub" -version = "2.9.1" +version = "2.10.0" description = "Use the full Github API v3" optional = false -python-versions = ">=3.9" +python-versions = ">=3.10" groups = ["main"] files = [ - {file = "pygithub-2.9.1-py3-none-any.whl", hash = "sha256:2ec78fca30092d51a42d76f4ddb02131b6f0c666a35dfdf364cf302cdda115b9"}, - {file = "pygithub-2.9.1.tar.gz", hash = "sha256:59771d7ff63d54d427be2e7d0dad2208dfffc2b0a045fec959263787739b611c"}, + {file = "pygithub-2.10.0-py3-none-any.whl", hash = "sha256:192ada2a76e4afc7d6b37e500c9bfeba1731e6506697445a5ba1c4af8bf0b924"}, + {file = "pygithub-2.10.0.tar.gz", hash = "sha256:90ff24ef1cd1bd57124c2a3869cafee9d7b066909129ecdaba2c2d1903bc118d"}, ] [package.dependencies] @@ -1898,14 +2110,14 @@ urllib3 = ">=1.26.0" [[package]] name = "pygments" -version = "2.20.0" +version = "2.21.0" description = "Pygments is a syntax highlighting package written in Python." optional = false python-versions = ">=3.9" groups = ["main", "dev", "docs"] files = [ - {file = "pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176"}, - {file = "pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f"}, + {file = "pygments-2.21.0-py3-none-any.whl", hash = "sha256:2363c69b61c4a97c838da3b130dcd6468f4848992b21a82f2a63ec34377137d9"}, + {file = "pygments-2.21.0.tar.gz", hash = "sha256:610ca751c9bc2492b38eb9a38a7fbc93edbbb2d7182edaf34e66ae493dee5c8c"}, ] [package.extras] @@ -1913,14 +2125,14 @@ windows-terminal = ["colorama (>=0.4.6)"] [[package]] name = "pyjwt" -version = "2.12.1" +version = "2.15.1" description = "JSON Web Token implementation in Python" optional = false python-versions = ">=3.9" groups = ["main"] files = [ - {file = "pyjwt-2.12.1-py3-none-any.whl", hash = "sha256:28ca37c070cad8ba8cd9790cd940535d40274d22f80ab87f3ac6a713e6e8454c"}, - {file = "pyjwt-2.12.1.tar.gz", hash = "sha256:c74a7a2adf861c04d002db713dd85f84beb242228e671280bf709d765b03672b"}, + {file = "pyjwt-2.15.1-py3-none-any.whl", hash = "sha256:42d59d631f7768a1028a64c7ff581a9bf7519804daf91fc5b6c56e30eec5e193"}, + {file = "pyjwt-2.15.1.tar.gz", hash = "sha256:4f259e80cdfb6b3fc18a7de51fd1ef9ec79652f25019bae68975ca2468a34df8"}, ] [package.dependencies] @@ -1928,9 +2140,6 @@ cryptography = {version = ">=3.4.0", optional = true, markers = "extra == \"cryp [package.extras] crypto = ["cryptography (>=3.4.0)"] -dev = ["coverage[toml] (==7.10.7)", "cryptography (>=3.4.0)", "pre-commit", "pytest (>=8.4.2,<9.0.0)", "sphinx", "sphinx-rtd-theme", "zope.interface"] -docs = ["sphinx", "sphinx-rtd-theme", "zope.interface"] -tests = ["coverage[toml] (==7.10.7)", "pytest (>=8.4.2,<9.0.0)"] [[package]] name = "pynacl" @@ -2033,34 +2242,29 @@ six = ">=1.5" [[package]] name = "python-discovery" -version = "1.3.1" +version = "1.6.1" description = "Python interpreter discovery" optional = false python-versions = ">=3.8" groups = ["dev"] files = [ - {file = "python_discovery-1.3.1-py3-none-any.whl", hash = "sha256:ed188687ebb3b82c01a17cd5ac62fc94d9f6487a7f1a0f9dfe89753fec91039c"}, - {file = "python_discovery-1.3.1.tar.gz", hash = "sha256:62f6db28064c9613e7ca76cb3f00c38c839a07c31c00dfe7ed0986493d2150a6"}, + {file = "python_discovery-1.6.1-py3-none-any.whl", hash = "sha256:d43fcdef879fe795352bd13ccf8d185ba5a9f86f36cfcd00529f596e737442b3"}, + {file = "python_discovery-1.6.1.tar.gz", hash = "sha256:cf87d3627dfb4412437fdd5b13eae402607722998d21567993aedbc59b23c15e"}, ] [package.dependencies] filelock = ">=3.15.4" -platformdirs = ">=4.3.6,<5" - -[package.extras] -docs = ["furo (>=2025.12.19)", "sphinx (>=9.1)", "sphinx-autodoc-typehints (>=3.6.3)", "sphinxcontrib-mermaid (>=2)", "sphinxcontrib-towncrier (>=0.4)", "towncrier (>=25.8)"] -testing = ["covdefaults (>=2.3)", "coverage (>=7.5.4)", "pytest (>=8.3.5)", "pytest-mock (>=3.14)", "setuptools (>=75.1)"] [[package]] name = "python-dotenv" -version = "1.2.2" +version = "1.2.4" description = "Read key-value pairs from a .env file and set them as environment variables" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "python_dotenv-1.2.2-py3-none-any.whl", hash = "sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a"}, - {file = "python_dotenv-1.2.2.tar.gz", hash = "sha256:2c371a91fbd7ba082c2c1dc1f8bf89ca22564a087c2c287cd9b662adde799cf3"}, + {file = "python_dotenv-1.2.4-py3-none-any.whl", hash = "sha256:42269a8a5b3fd54ffa6f3d84b18abed50064717576b4ecf03dc4a55d8aa04fdc"}, + {file = "python_dotenv-1.2.4.tar.gz", hash = "sha256:f0d53e69935a851c0dcc78f3ab7aaccd8cabef0b92382b576b824212902873c0"}, ] [package.extras] @@ -2207,14 +2411,14 @@ fixture = ["fixtures"] [[package]] name = "responses" -version = "0.26.0" +version = "0.26.3" description = "A utility library for mocking out the `requests` Python library." optional = false python-versions = ">=3.8" groups = ["dev"] files = [ - {file = "responses-0.26.0-py3-none-any.whl", hash = "sha256:03ec4409088cd5c66b71ecbbbd27fe2c58ddfad801c66203457b3e6a04868c37"}, - {file = "responses-0.26.0.tar.gz", hash = "sha256:c7f6923e6343ef3682816ba421c006626777893cb0d5e1434f674b649bac9eb4"}, + {file = "responses-0.26.3-py3-none-any.whl", hash = "sha256:74474f799334ac4f37d93b6437ecc3bb1bb5c77a8d31780a338643be2dce0af8"}, + {file = "responses-0.26.3.tar.gz", hash = "sha256:b0c11ca8131b8b227b8d5108e6ed39772222bd5aab030ed430e8f99057c4c409"}, ] [package.dependencies] @@ -2258,159 +2462,175 @@ files = [ [[package]] name = "rpds-py" -version = "0.30.0" +version = "2026.9.1" description = "Python bindings to Rust's persistent data structures (rpds)" optional = false -python-versions = ">=3.10" +python-versions = ">=3.11" groups = ["main"] files = [ - {file = "rpds_py-0.30.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:679ae98e00c0e8d68a7fda324e16b90fd5260945b45d3b824c892cec9eea3288"}, - {file = "rpds_py-0.30.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4cc2206b76b4f576934f0ed374b10d7ca5f457858b157ca52064bdfc26b9fc00"}, - {file = "rpds_py-0.30.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:389a2d49eded1896c3d48b0136ead37c48e221b391c052fba3f4055c367f60a6"}, - {file = "rpds_py-0.30.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:32c8528634e1bf7121f3de08fa85b138f4e0dc47657866630611b03967f041d7"}, - {file = "rpds_py-0.30.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f207f69853edd6f6700b86efb84999651baf3789e78a466431df1331608e5324"}, - {file = "rpds_py-0.30.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:67b02ec25ba7a9e8fa74c63b6ca44cf5707f2fbfadae3ee8e7494297d56aa9df"}, - {file = "rpds_py-0.30.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c0e95f6819a19965ff420f65578bacb0b00f251fefe2c8b23347c37174271f3"}, - {file = "rpds_py-0.30.0-cp310-cp310-manylinux_2_31_riscv64.whl", hash = "sha256:a452763cc5198f2f98898eb98f7569649fe5da666c2dc6b5ddb10fde5a574221"}, - {file = "rpds_py-0.30.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e0b65193a413ccc930671c55153a03ee57cecb49e6227204b04fae512eb657a7"}, - {file = "rpds_py-0.30.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:858738e9c32147f78b3ac24dc0edb6610000e56dc0f700fd5f651d0a0f0eb9ff"}, - {file = "rpds_py-0.30.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:da279aa314f00acbb803da1e76fa18666778e8a8f83484fba94526da5de2cba7"}, - {file = "rpds_py-0.30.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7c64d38fb49b6cdeda16ab49e35fe0da2e1e9b34bc38bd78386530f218b37139"}, - {file = "rpds_py-0.30.0-cp310-cp310-win32.whl", hash = "sha256:6de2a32a1665b93233cde140ff8b3467bdb9e2af2b91079f0333a0974d12d464"}, - {file = "rpds_py-0.30.0-cp310-cp310-win_amd64.whl", hash = "sha256:1726859cd0de969f88dc8673bdd954185b9104e05806be64bcd87badbe313169"}, - {file = "rpds_py-0.30.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:a2bffea6a4ca9f01b3f8e548302470306689684e61602aa3d141e34da06cf425"}, - {file = "rpds_py-0.30.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dc4f992dfe1e2bc3ebc7444f6c7051b4bc13cd8e33e43511e8ffd13bf407010d"}, - {file = "rpds_py-0.30.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:422c3cb9856d80b09d30d2eb255d0754b23e090034e1deb4083f8004bd0761e4"}, - {file = "rpds_py-0.30.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:07ae8a593e1c3c6b82ca3292efbe73c30b61332fd612e05abee07c79359f292f"}, - {file = "rpds_py-0.30.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:12f90dd7557b6bd57f40abe7747e81e0c0b119bef015ea7726e69fe550e394a4"}, - {file = "rpds_py-0.30.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:99b47d6ad9a6da00bec6aabe5a6279ecd3c06a329d4aa4771034a21e335c3a97"}, - {file = "rpds_py-0.30.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:33f559f3104504506a44bb666b93a33f5d33133765b0c216a5bf2f1e1503af89"}, - {file = "rpds_py-0.30.0-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:946fe926af6e44f3697abbc305ea168c2c31d3e3ef1058cf68f379bf0335a78d"}, - {file = "rpds_py-0.30.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:495aeca4b93d465efde585977365187149e75383ad2684f81519f504f5c13038"}, - {file = "rpds_py-0.30.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d9a0ca5da0386dee0655b4ccdf46119df60e0f10da268d04fe7cc87886872ba7"}, - {file = "rpds_py-0.30.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8d6d1cc13664ec13c1b84241204ff3b12f9bb82464b8ad6e7a5d3486975c2eed"}, - {file = "rpds_py-0.30.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3896fa1be39912cf0757753826bc8bdc8ca331a28a7c4ae46b7a21280b06bb85"}, - {file = "rpds_py-0.30.0-cp311-cp311-win32.whl", hash = "sha256:55f66022632205940f1827effeff17c4fa7ae1953d2b74a8581baaefb7d16f8c"}, - {file = "rpds_py-0.30.0-cp311-cp311-win_amd64.whl", hash = "sha256:a51033ff701fca756439d641c0ad09a41d9242fa69121c7d8769604a0a629825"}, - {file = "rpds_py-0.30.0-cp311-cp311-win_arm64.whl", hash = "sha256:47b0ef6231c58f506ef0b74d44e330405caa8428e770fec25329ed2cb971a229"}, - {file = "rpds_py-0.30.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a161f20d9a43006833cd7068375a94d035714d73a172b681d8881820600abfad"}, - {file = "rpds_py-0.30.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6abc8880d9d036ecaafe709079969f56e876fcf107f7a8e9920ba6d5a3878d05"}, - {file = "rpds_py-0.30.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca28829ae5f5d569bb62a79512c842a03a12576375d5ece7d2cadf8abe96ec28"}, - {file = "rpds_py-0.30.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a1010ed9524c73b94d15919ca4d41d8780980e1765babf85f9a2f90d247153dd"}, - {file = "rpds_py-0.30.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f8d1736cfb49381ba528cd5baa46f82fdc65c06e843dab24dd70b63d09121b3f"}, - {file = "rpds_py-0.30.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d948b135c4693daff7bc2dcfc4ec57237a29bd37e60c2fabf5aff2bbacf3e2f1"}, - {file = "rpds_py-0.30.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47f236970bccb2233267d89173d3ad2703cd36a0e2a6e92d0560d333871a3d23"}, - {file = "rpds_py-0.30.0-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:2e6ecb5a5bcacf59c3f912155044479af1d0b6681280048b338b28e364aca1f6"}, - {file = "rpds_py-0.30.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a8fa71a2e078c527c3e9dc9fc5a98c9db40bcc8a92b4e8858e36d329f8684b51"}, - {file = "rpds_py-0.30.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:73c67f2db7bc334e518d097c6d1e6fed021bbc9b7d678d6cc433478365d1d5f5"}, - {file = "rpds_py-0.30.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:5ba103fb455be00f3b1c2076c9d4264bfcb037c976167a6047ed82f23153f02e"}, - {file = "rpds_py-0.30.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7cee9c752c0364588353e627da8a7e808a66873672bcb5f52890c33fd965b394"}, - {file = "rpds_py-0.30.0-cp312-cp312-win32.whl", hash = "sha256:1ab5b83dbcf55acc8b08fc62b796ef672c457b17dbd7820a11d6c52c06839bdf"}, - {file = "rpds_py-0.30.0-cp312-cp312-win_amd64.whl", hash = "sha256:a090322ca841abd453d43456ac34db46e8b05fd9b3b4ac0c78bcde8b089f959b"}, - {file = "rpds_py-0.30.0-cp312-cp312-win_arm64.whl", hash = "sha256:669b1805bd639dd2989b281be2cfd951c6121b65e729d9b843e9639ef1fd555e"}, - {file = "rpds_py-0.30.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:f83424d738204d9770830d35290ff3273fbb02b41f919870479fab14b9d303b2"}, - {file = "rpds_py-0.30.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e7536cd91353c5273434b4e003cbda89034d67e7710eab8761fd918ec6c69cf8"}, - {file = "rpds_py-0.30.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2771c6c15973347f50fece41fc447c054b7ac2ae0502388ce3b6738cd366e3d4"}, - {file = "rpds_py-0.30.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0a59119fc6e3f460315fe9d08149f8102aa322299deaa5cab5b40092345c2136"}, - {file = "rpds_py-0.30.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:76fec018282b4ead0364022e3c54b60bf368b9d926877957a8624b58419169b7"}, - {file = "rpds_py-0.30.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:692bef75a5525db97318e8cd061542b5a79812d711ea03dbc1f6f8dbb0c5f0d2"}, - {file = "rpds_py-0.30.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9027da1ce107104c50c81383cae773ef5c24d296dd11c99e2629dbd7967a20c6"}, - {file = "rpds_py-0.30.0-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:9cf69cdda1f5968a30a359aba2f7f9aa648a9ce4b580d6826437f2b291cfc86e"}, - {file = "rpds_py-0.30.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a4796a717bf12b9da9d3ad002519a86063dcac8988b030e405704ef7d74d2d9d"}, - {file = "rpds_py-0.30.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5d4c2aa7c50ad4728a094ebd5eb46c452e9cb7edbfdb18f9e1221f597a73e1e7"}, - {file = "rpds_py-0.30.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ba81a9203d07805435eb06f536d95a266c21e5b2dfbf6517748ca40c98d19e31"}, - {file = "rpds_py-0.30.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:945dccface01af02675628334f7cf49c2af4c1c904748efc5cf7bbdf0b579f95"}, - {file = "rpds_py-0.30.0-cp313-cp313-win32.whl", hash = "sha256:b40fb160a2db369a194cb27943582b38f79fc4887291417685f3ad693c5a1d5d"}, - {file = "rpds_py-0.30.0-cp313-cp313-win_amd64.whl", hash = "sha256:806f36b1b605e2d6a72716f321f20036b9489d29c51c91f4dd29a3e3afb73b15"}, - {file = "rpds_py-0.30.0-cp313-cp313-win_arm64.whl", hash = "sha256:d96c2086587c7c30d44f31f42eae4eac89b60dabbac18c7669be3700f13c3ce1"}, - {file = "rpds_py-0.30.0-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:eb0b93f2e5c2189ee831ee43f156ed34e2a89a78a66b98cadad955972548be5a"}, - {file = "rpds_py-0.30.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:922e10f31f303c7c920da8981051ff6d8c1a56207dbdf330d9047f6d30b70e5e"}, - {file = "rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cdc62c8286ba9bf7f47befdcea13ea0e26bf294bda99758fd90535cbaf408000"}, - {file = "rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:47f9a91efc418b54fb8190a6b4aa7813a23fb79c51f4bb84e418f5476c38b8db"}, - {file = "rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1f3587eb9b17f3789ad50824084fa6f81921bbf9a795826570bda82cb3ed91f2"}, - {file = "rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:39c02563fc592411c2c61d26b6c5fe1e51eaa44a75aa2c8735ca88b0d9599daa"}, - {file = "rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51a1234d8febafdfd33a42d97da7a43f5dcb120c1060e352a3fbc0c6d36e2083"}, - {file = "rpds_py-0.30.0-cp313-cp313t-manylinux_2_31_riscv64.whl", hash = "sha256:eb2c4071ab598733724c08221091e8d80e89064cd472819285a9ab0f24bcedb9"}, - {file = "rpds_py-0.30.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6bdfdb946967d816e6adf9a3d8201bfad269c67efe6cefd7093ef959683c8de0"}, - {file = "rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:c77afbd5f5250bf27bf516c7c4a016813eb2d3e116139aed0096940c5982da94"}, - {file = "rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:61046904275472a76c8c90c9ccee9013d70a6d0f73eecefd38c1ae7c39045a08"}, - {file = "rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4c5f36a861bc4b7da6516dbdf302c55313afa09b81931e8280361a4f6c9a2d27"}, - {file = "rpds_py-0.30.0-cp313-cp313t-win32.whl", hash = "sha256:3d4a69de7a3e50ffc214ae16d79d8fbb0922972da0356dcf4d0fdca2878559c6"}, - {file = "rpds_py-0.30.0-cp313-cp313t-win_amd64.whl", hash = "sha256:f14fc5df50a716f7ece6a80b6c78bb35ea2ca47c499e422aa4463455dd96d56d"}, - {file = "rpds_py-0.30.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:68f19c879420aa08f61203801423f6cd5ac5f0ac4ac82a2368a9fcd6a9a075e0"}, - {file = "rpds_py-0.30.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ec7c4490c672c1a0389d319b3a9cfcd098dcdc4783991553c332a15acf7249be"}, - {file = "rpds_py-0.30.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f251c812357a3fed308d684a5079ddfb9d933860fc6de89f2b7ab00da481e65f"}, - {file = "rpds_py-0.30.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac98b175585ecf4c0348fd7b29c3864bda53b805c773cbf7bfdaffc8070c976f"}, - {file = "rpds_py-0.30.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3e62880792319dbeb7eb866547f2e35973289e7d5696c6e295476448f5b63c87"}, - {file = "rpds_py-0.30.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4e7fc54e0900ab35d041b0601431b0a0eb495f0851a0639b6ef90f7741b39a18"}, - {file = "rpds_py-0.30.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47e77dc9822d3ad616c3d5759ea5631a75e5809d5a28707744ef79d7a1bcfcad"}, - {file = "rpds_py-0.30.0-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:b4dc1a6ff022ff85ecafef7979a2c6eb423430e05f1165d6688234e62ba99a07"}, - {file = "rpds_py-0.30.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4559c972db3a360808309e06a74628b95eaccbf961c335c8fe0d590cf587456f"}, - {file = "rpds_py-0.30.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:0ed177ed9bded28f8deb6ab40c183cd1192aa0de40c12f38be4d59cd33cb5c65"}, - {file = "rpds_py-0.30.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:ad1fa8db769b76ea911cb4e10f049d80bf518c104f15b3edb2371cc65375c46f"}, - {file = "rpds_py-0.30.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:46e83c697b1f1c72b50e5ee5adb4353eef7406fb3f2043d64c33f20ad1c2fc53"}, - {file = "rpds_py-0.30.0-cp314-cp314-win32.whl", hash = "sha256:ee454b2a007d57363c2dfd5b6ca4a5d7e2c518938f8ed3b706e37e5d470801ed"}, - {file = "rpds_py-0.30.0-cp314-cp314-win_amd64.whl", hash = "sha256:95f0802447ac2d10bcc69f6dc28fe95fdf17940367b21d34e34c737870758950"}, - {file = "rpds_py-0.30.0-cp314-cp314-win_arm64.whl", hash = "sha256:613aa4771c99f03346e54c3f038e4cc574ac09a3ddfb0e8878487335e96dead6"}, - {file = "rpds_py-0.30.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:7e6ecfcb62edfd632e56983964e6884851786443739dbfe3582947e87274f7cb"}, - {file = "rpds_py-0.30.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a1d0bc22a7cdc173fedebb73ef81e07faef93692b8c1ad3733b67e31e1b6e1b8"}, - {file = "rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d08f00679177226c4cb8c5265012eea897c8ca3b93f429e546600c971bcbae7"}, - {file = "rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5965af57d5848192c13534f90f9dd16464f3c37aaf166cc1da1cae1fd5a34898"}, - {file = "rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9a4e86e34e9ab6b667c27f3211ca48f73dba7cd3d90f8d5b11be56e5dbc3fb4e"}, - {file = "rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e5d3e6b26f2c785d65cc25ef1e5267ccbe1b069c5c21b8cc724efee290554419"}, - {file = "rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:626a7433c34566535b6e56a1b39a7b17ba961e97ce3b80ec62e6f1312c025551"}, - {file = "rpds_py-0.30.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:acd7eb3f4471577b9b5a41baf02a978e8bdeb08b4b355273994f8b87032000a8"}, - {file = "rpds_py-0.30.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fe5fa731a1fa8a0a56b0977413f8cacac1768dad38d16b3a296712709476fbd5"}, - {file = "rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:74a3243a411126362712ee1524dfc90c650a503502f135d54d1b352bd01f2404"}, - {file = "rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:3e8eeb0544f2eb0d2581774be4c3410356eba189529a6b3e36bbbf9696175856"}, - {file = "rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:dbd936cde57abfee19ab3213cf9c26be06d60750e60a8e4dd85d1ab12c8b1f40"}, - {file = "rpds_py-0.30.0-cp314-cp314t-win32.whl", hash = "sha256:dc824125c72246d924f7f796b4f63c1e9dc810c7d9e2355864b3c3a73d59ade0"}, - {file = "rpds_py-0.30.0-cp314-cp314t-win_amd64.whl", hash = "sha256:27f4b0e92de5bfbc6f86e43959e6edd1425c33b5e69aab0984a72047f2bcf1e3"}, - {file = "rpds_py-0.30.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:c2262bdba0ad4fc6fb5545660673925c2d2a5d9e2e0fb603aad545427be0fc58"}, - {file = "rpds_py-0.30.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:ee6af14263f25eedc3bb918a3c04245106a42dfd4f5c2285ea6f997b1fc3f89a"}, - {file = "rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3adbb8179ce342d235c31ab8ec511e66c73faa27a47e076ccc92421add53e2bb"}, - {file = "rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:250fa00e9543ac9b97ac258bd37367ff5256666122c2d0f2bc97577c60a1818c"}, - {file = "rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9854cf4f488b3d57b9aaeb105f06d78e5529d3145b1e4a41750167e8c213c6d3"}, - {file = "rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:993914b8e560023bc0a8bf742c5f303551992dcb85e247b1e5c7f4a7d145bda5"}, - {file = "rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58edca431fb9b29950807e301826586e5bbf24163677732429770a697ffe6738"}, - {file = "rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_31_riscv64.whl", hash = "sha256:dea5b552272a944763b34394d04577cf0f9bd013207bc32323b5a89a53cf9c2f"}, - {file = "rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ba3af48635eb83d03f6c9735dfb21785303e73d22ad03d489e88adae6eab8877"}, - {file = "rpds_py-0.30.0-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:dff13836529b921e22f15cb099751209a60009731a68519630a24d61f0b1b30a"}, - {file = "rpds_py-0.30.0-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:1b151685b23929ab7beec71080a8889d4d6d9fa9a983d213f07121205d48e2c4"}, - {file = "rpds_py-0.30.0-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:ac37f9f516c51e5753f27dfdef11a88330f04de2d564be3991384b2f3535d02e"}, - {file = "rpds_py-0.30.0.tar.gz", hash = "sha256:dd8ff7cf90014af0c0f787eea34794ebf6415242ee1d6fa91eaba725cc441e84"}, + {file = "rpds_py-2026.9.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:2711d29b653b3bce48a63d18b9c6b53274669e6d6c4094dddeb4d9a0e45128b2"}, + {file = "rpds_py-2026.9.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3231c4c0e521dafa5be0c9f114ee2c2ad46650836f2d72caa86801950c3e7044"}, + {file = "rpds_py-2026.9.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e01b3c878c8641913e688edd1b3f08658c6783d29cf6b826bd3c0d1ae7a1ffaa"}, + {file = "rpds_py-2026.9.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3e524c7874ac72884d28e16dd5b8d839fd09e0fe76b020d3fbca23212a7b8c52"}, + {file = "rpds_py-2026.9.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:761fdae6728ceb99ab182fad2f0cc1e262f610834dc891aea1d1a2a2e634776f"}, + {file = "rpds_py-2026.9.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6b723eb406dec5bc9ec516c73ab9c3239a3284e017f7eb89ee2b3258bd504fb7"}, + {file = "rpds_py-2026.9.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:136a1c3fe4402b7008bc81cb62ee538481795b61a7e83df88dff3b3f02b726ff"}, + {file = "rpds_py-2026.9.1-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:839dde845559254f34885267c6878f60d61d5205180226d976fe488d45fa128e"}, + {file = "rpds_py-2026.9.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:56cd8b3f77d7b6812f533b662186a1f28316931166ddc00fb893b1b0db7e9888"}, + {file = "rpds_py-2026.9.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:074a4d198bc34d9a8ea425114fc3ded6d11ec01f6a314a8db67454a5152d8834"}, + {file = "rpds_py-2026.9.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:6beb738155fe8ab8091afdfa5a3226b21c2b1593f1e50ebb90eb25b44dbc0391"}, + {file = "rpds_py-2026.9.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:57492a550a1d88d29d003247e5f78dd8cf04a701fac0e4c8db8745a6d2504e0a"}, + {file = "rpds_py-2026.9.1-cp311-cp311-win32.whl", hash = "sha256:d95a354e02393eada6d7351184671aced9d4cce109dabf927cb7aa99624352a1"}, + {file = "rpds_py-2026.9.1-cp311-cp311-win_amd64.whl", hash = "sha256:ce4d4f52e2a4324396caddbd45a97d8d7be5f42edd25d2355282a9c34f9b2f7f"}, + {file = "rpds_py-2026.9.1-cp311-cp311-win_arm64.whl", hash = "sha256:fdcd198979b4ecffcc1beba366a7fbcf4eb41243691a82fe52ceb0b902f09c12"}, + {file = "rpds_py-2026.9.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:50906f5aea24b5a865cbd0a589698288631d9f3a54c3a937c83aefa95a0d14af"}, + {file = "rpds_py-2026.9.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:e21c1429e205828ea886a2293a4a2c8e01f4c25d9893ca330e97a6cf73f52e7b"}, + {file = "rpds_py-2026.9.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2693b2728bbcc48d09a981a356954b0c47c53ff25b545856f28a889ea619f69a"}, + {file = "rpds_py-2026.9.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8601470267d938bcb7f3ab1a336100af51a4fd5b6ed030ef52461bb3ef5e7e07"}, + {file = "rpds_py-2026.9.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3890a6aa36e6baa53d5258a2a25d3ef8b37ad165a6ab27a892d7c3e3a432cd69"}, + {file = "rpds_py-2026.9.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6b5b393eda5ea42cca1c1a6665f2a4882b4fd5d1777e41ce0545a107fb008c9d"}, + {file = "rpds_py-2026.9.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:addeda51556dac7c1a2f14cda62db8b621cd12afba3091d03a96c72932387eab"}, + {file = "rpds_py-2026.9.1-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:d9edf30457d74eebfd76b045535e36f1cd89062566a128a0db2145ca042d787e"}, + {file = "rpds_py-2026.9.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:815d26356930846a40c7bc1366e7b1b0320ab8a063e66c11298a208bed0fd237"}, + {file = "rpds_py-2026.9.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3b5a6f40f0a1486b4b36c888123afc67acdbd9f33235927acf5ff295429a0ba3"}, + {file = "rpds_py-2026.9.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b5b8b0753718d258fd454283fbd57e14545d3b40583fa672e27cb4f987626bcc"}, + {file = "rpds_py-2026.9.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:46d80bc76b51a6c24f9944368c28d38b8bcbcea1da4f2f8d3ebc31a67e8c6ec6"}, + {file = "rpds_py-2026.9.1-cp312-cp312-win32.whl", hash = "sha256:befc2d6a953e563f8a7bfd87a42c22ebf8a3e980dcb7b6a4d17b70b0e914e8a3"}, + {file = "rpds_py-2026.9.1-cp312-cp312-win_amd64.whl", hash = "sha256:5ce8943f79c2210f7abcc28e86367b03b28d95027fd01c46d2472373ae70c86f"}, + {file = "rpds_py-2026.9.1-cp312-cp312-win_arm64.whl", hash = "sha256:501909f2e4a1e2dee528ef766fe3c469060ebc17e54a8383d404ba07a81a6f02"}, + {file = "rpds_py-2026.9.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:a36b70596407634ca82d4b989a3729074a008537a0522e4c8046a67c729103e9"}, + {file = "rpds_py-2026.9.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:eba5d173f7d5708b22a93815017a4611873ed54db9f268077c0dd1ed99cfc858"}, + {file = "rpds_py-2026.9.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:457866b85daf5034296666168b84a69e0b2e89dc4f1af102b46f6448a60b9063"}, + {file = "rpds_py-2026.9.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a3a52a3ba86436ab3aef510fbe21512abc2ddd1993005dfe50514bd2284ef025"}, + {file = "rpds_py-2026.9.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d7841166b7fa64c9c56404617ae4341448847482d45933b13135d26c130519e5"}, + {file = "rpds_py-2026.9.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:926bdd3e3b5998ddf70cc64bc8cf57209571f9044542913afb673799fec77dd0"}, + {file = "rpds_py-2026.9.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7868b85224291c6cb6759f9b5adb9745f486d226f62b16a614dd5a2a5ab2b35b"}, + {file = "rpds_py-2026.9.1-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:3cd182d7291d29b92c521a0069d9c01ba6193628a9a105531d11b40a6d731a33"}, + {file = "rpds_py-2026.9.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e6ea1cda8d8c688278430e4268a42f5e5da3bdd74578dfadc0820c3f1766ce83"}, + {file = "rpds_py-2026.9.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5943980471829f6de242a20b109de3111ba6b77e3af0ffc587028ac854b05e6c"}, + {file = "rpds_py-2026.9.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:76d3af9732d2dab69f28179b40ba2d87e2f1d5824b4a694780aa787d685e8f36"}, + {file = "rpds_py-2026.9.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:78326f4cb4427a56ba4996c0762b63be45f06b85f086526420d2b3a66e40f84d"}, + {file = "rpds_py-2026.9.1-cp313-cp313-win32.whl", hash = "sha256:172e47169583f46ce118cbec68e6795d0da0f4606b488b6434f8276bca0a058c"}, + {file = "rpds_py-2026.9.1-cp313-cp313-win_amd64.whl", hash = "sha256:3e93b2cd69a9830be33e03945cd7cda940a0a8bfcfbff41d6144f0cb0d3d8bd9"}, + {file = "rpds_py-2026.9.1-cp313-cp313-win_arm64.whl", hash = "sha256:d151e148117294133bf8af7eeace085e7e87432db15ab6adf640330298a47f6f"}, + {file = "rpds_py-2026.9.1-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:c9d1aca01f49170fdcf5c92761b1fafe97f554b721ca4570c5949fff778f0d4b"}, + {file = "rpds_py-2026.9.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:3f0e9ac28fc067d4d34b88ae43c48e9489455c97fee9633d851f7eeed5a05d35"}, + {file = "rpds_py-2026.9.1-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:07deecbfce94c78473018bc7d10b337cc651d12df87a1eb2cb3e4024bc9c33d0"}, + {file = "rpds_py-2026.9.1-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:821b2755db9194409254012f429c56643416fb96ef9be090be82ec8826b7f477"}, + {file = "rpds_py-2026.9.1-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3c91c210ae7645626c608400e3519b4a642f837cce09ca830db3beb2e9f274d4"}, + {file = "rpds_py-2026.9.1-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:54ac2158a6f96cfbabff0b2eedaf94b90c5ec7ca8317fcadc61e1c2b2e0ff6ef"}, + {file = "rpds_py-2026.9.1-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eac2f5dbafd585dfe31f86a23ebf0d3ba480a9d49ebc87947267b5608d4ea0cd"}, + {file = "rpds_py-2026.9.1-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:8aa5dda18d39b6143eb24809d158f9252c88f402749b6f1b62a506cc7d96cc35"}, + {file = "rpds_py-2026.9.1-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5c90e7fa02e8f5de0d10c17595c568ada48c5302e749462c0ea1a4c362111a86"}, + {file = "rpds_py-2026.9.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:e6d198bad4e49dd6732fbd636e2fc5c082f45c8cad0b4acb756b00c82c76072e"}, + {file = "rpds_py-2026.9.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:96beca19ec79de272e8668585380ff9092c47077c1d7a1e098e00bbd921f4785"}, + {file = "rpds_py-2026.9.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:a5cf77eb04f20b720be95265a3e00eb2a14814074255cc27069c551b2db53118"}, + {file = "rpds_py-2026.9.1-cp314-cp314-win32.whl", hash = "sha256:a03d57b86d2a51d0a66c92177e2be154ad015f357791d306e714569999cdb4cc"}, + {file = "rpds_py-2026.9.1-cp314-cp314-win_amd64.whl", hash = "sha256:837c6b305e26fe0f75b15c92cf3b2ba29e0ae19dc40b1c557b026cb426347d0c"}, + {file = "rpds_py-2026.9.1-cp314-cp314-win_arm64.whl", hash = "sha256:fce4b85234a0cbad67bf8e6e1201ee815d172c9aebad75f25645bc4d834f8e31"}, + {file = "rpds_py-2026.9.1-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:3a72c11530d71abfb66c8d7696a2f86c43e63fca8b948f1a784ac490f4ec688e"}, + {file = "rpds_py-2026.9.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:068c37bba854ec2fe42f7365c640af11dd9895890ccbf2df5070d0c059bd7f96"}, + {file = "rpds_py-2026.9.1-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7fca4eb6df565e2a928f1c7dad92d27db8f9df0f449e76423ed5d7e713ed445"}, + {file = "rpds_py-2026.9.1-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c933c6678c6f116ff8af47a4c6db0868b8ace74af0343016c0ef00f00272ea69"}, + {file = "rpds_py-2026.9.1-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:028ad274ea951dac64491b5d1e65712a4aeabfdbdb9fccf797b57bd899b0c495"}, + {file = "rpds_py-2026.9.1-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:740d0a99cf9de0b17a3943388e9294a59becf75e7c43421f387bd3c7a9901f7c"}, + {file = "rpds_py-2026.9.1-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0da298fb372dc192610a4b9ecbc68a0cd8b675bbbd1fc519d01b41cfd658333e"}, + {file = "rpds_py-2026.9.1-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:eb61be926bb81567c1f48bdc8aa22b9855048dc2efd53871f9f7e6e9a5632346"}, + {file = "rpds_py-2026.9.1-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:42e75466f83cd43f6026c81eab74246efb2bdadafb307b85700632d06c68f299"}, + {file = "rpds_py-2026.9.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:617f59cde379b4f648a09797b7f683d04b90a46344cddab85639da5aff0f5531"}, + {file = "rpds_py-2026.9.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:3edae8c5ddfdb6985d49ae9d150516e5076888879022f91a26c2de9276ce0bdb"}, + {file = "rpds_py-2026.9.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:0f045bb053c9057720d72c56dffe30dffdc05997b2897a827b9325f0ab6623fa"}, + {file = "rpds_py-2026.9.1-cp314-cp314t-win32.whl", hash = "sha256:bf35d0568abda97233239ce32896d3ad53fccc537832c104e30c94aa5fb93569"}, + {file = "rpds_py-2026.9.1-cp314-cp314t-win_amd64.whl", hash = "sha256:1e8d4d79d828299bf44a55db22a9388ab967b49d17132c88eab0f4360b48da8e"}, + {file = "rpds_py-2026.9.1-cp315-cp315-macosx_10_12_x86_64.whl", hash = "sha256:1d77b649e6f7cdf12ca5c2a98dad0ad37f9ea9b6f960408a92f0cb12bb3d04d9"}, + {file = "rpds_py-2026.9.1-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:00ba2d8c7dd4ee537978ddf4b3fbd712bef2d8751603f7f3146b3f4287768e25"}, + {file = "rpds_py-2026.9.1-cp315-cp315-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec450527cbf485e13c8d3602a54f428ab0432fdade0ede75efd74b735421c871"}, + {file = "rpds_py-2026.9.1-cp315-cp315-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:306ee1850d8105b5baf977e78d45fcadd12c1a54678d614c9baf217708446e91"}, + {file = "rpds_py-2026.9.1-cp315-cp315-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ef6b65b03247c54692ad4fd9ee97cb772781927db72e3cb05e70b3db6d1ff14f"}, + {file = "rpds_py-2026.9.1-cp315-cp315-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a575404ebc9cf2e91edd32eaf570ec1430eb900d4f56724ba7dd4bc1fc9c176d"}, + {file = "rpds_py-2026.9.1-cp315-cp315-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c16ab111bc27c646ba8aa005d0527754edc538ebb636f0b1bf8e244b48d1945"}, + {file = "rpds_py-2026.9.1-cp315-cp315-manylinux_2_31_riscv64.whl", hash = "sha256:7664419f27db41d4f1c43a78dccda7dd6e8ef2428df3ee01d0c2a07a6b071297"}, + {file = "rpds_py-2026.9.1-cp315-cp315-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4b26b03d9d2658ee2fa234f8f4f19f38a09773fe5261028025032e26d4d35af0"}, + {file = "rpds_py-2026.9.1-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:be3e47e2d91aa3942ff9bf4077a505226005abfc39b6f7554a91c1b9393986b9"}, + {file = "rpds_py-2026.9.1-cp315-cp315-musllinux_1_2_i686.whl", hash = "sha256:6307a0da524939decb8ca4a3933b8ab62525794411d6984fca6726e732804af6"}, + {file = "rpds_py-2026.9.1-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:159a7aab5c5e8b112c8830f54717ce56da1252ebdbb526f5be2df2309280b9e7"}, + {file = "rpds_py-2026.9.1-cp315-cp315-win32.whl", hash = "sha256:dbc2673f9223d420c91145599b3ba45a8a50c207d1976908e5fb5ddb0c9b9429"}, + {file = "rpds_py-2026.9.1-cp315-cp315-win_amd64.whl", hash = "sha256:75c38c50ab9aca840225d9a9a3810bf11d04bd5c1f186cabbb8aee56db3e9b15"}, + {file = "rpds_py-2026.9.1-cp315-cp315-win_arm64.whl", hash = "sha256:a431156bb41865fc14cd5d79bb9d7bbed83110b0159e34e62ae30951f96c0009"}, + {file = "rpds_py-2026.9.1-cp315-cp315t-macosx_10_12_x86_64.whl", hash = "sha256:ef0d8c843e2827d6c120ab4687e9423fb1d893db1df27b7c1506615bcb9734a0"}, + {file = "rpds_py-2026.9.1-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:45bc6bccf78b20fd834237d18db64965d7ee68ba7f60440a26c7ab71e7b8d51a"}, + {file = "rpds_py-2026.9.1-cp315-cp315t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d55198263bb51f557550c6ed2e6d1cb6a6fed6eb5c9120b741c5926bef8a45d"}, + {file = "rpds_py-2026.9.1-cp315-cp315t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a8763f20692da7df39b0afdd1ba3042b004c50a45994f76c2d9a25641f7673db"}, + {file = "rpds_py-2026.9.1-cp315-cp315t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e43d4a1f673e8a1cbd8533e809e02b4bf9d4f2280269bb640436556312121250"}, + {file = "rpds_py-2026.9.1-cp315-cp315t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea394a937f17a54c51239348bdbe2e3518124c8d4a8951ba04a311d3095bd18f"}, + {file = "rpds_py-2026.9.1-cp315-cp315t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cdeaa99ce822dca76cfb1b993e9120c5ea212f2eb66d48950ad63c349668a018"}, + {file = "rpds_py-2026.9.1-cp315-cp315t-manylinux_2_31_riscv64.whl", hash = "sha256:b4f062343e7ad3fa94f2c66e5ae667dee47ee74dd41a9057c4fbe163236a123d"}, + {file = "rpds_py-2026.9.1-cp315-cp315t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:22ffd29a63d71fb1b81552c21f2c2b734949b7ac751a9be70675a939a900839b"}, + {file = "rpds_py-2026.9.1-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:08dae4a4095150a7c4545a1fb40b98e1ab1744fbc2770d92c977b9dadaa49ab6"}, + {file = "rpds_py-2026.9.1-cp315-cp315t-musllinux_1_2_i686.whl", hash = "sha256:9a0460d43603d1fd9ef59c30278531e15d78581721ddb538fa560aa7817ea4ad"}, + {file = "rpds_py-2026.9.1-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:1c2d1f6da5128eabf34e963d7163a818846075a52568250d006c4c953b40f903"}, + {file = "rpds_py-2026.9.1-cp315-cp315t-win32.whl", hash = "sha256:5c6ee90dee3e85e055ddfd502d611643d9b0fd94c818220bda84ec3dacd9b27b"}, + {file = "rpds_py-2026.9.1-cp315-cp315t-win_amd64.whl", hash = "sha256:fe5ad0664ec772b02c45859041aa17655709cced7a31005817fbbbd988c25567"}, + {file = "rpds_py-2026.9.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4c0d2cb595a420b34d5086db0add011e26e2c09d6a024afbac4228bf8f863a30"}, + {file = "rpds_py-2026.9.1-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f3d6ed6a98cfd19155996605474982cc470d7601746a6439078f1a5a3fa8b050"}, + {file = "rpds_py-2026.9.1-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8171b44a054e5c67fd748ada04187f1250bf35b95f85e52ab64bcf3331a923bb"}, + {file = "rpds_py-2026.9.1-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fda1d96e542c37b6c804547dbf489c129fe7c97183a76a5ec275909ba1a063df"}, + {file = "rpds_py-2026.9.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:270bdcdaac5d5b6f73c5e22e7e135c7f2a50e789f71d9e241d5be8d90026e19a"}, + {file = "rpds_py-2026.9.1-pp311-pypy311_pp73-manylinux_2_31_riscv64.whl", hash = "sha256:84a6ecc0c940169190d2c23bd969debd48c94dbc855acd60188a68d71d421608"}, + {file = "rpds_py-2026.9.1-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ab4b2fda7c2b542f7f9d886cc6a838c5079d2b76f72e6081411faba11adde2c9"}, + {file = "rpds_py-2026.9.1-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:44b32a7c4f0da3d28af31c259e38ddcff096f855e205ed0671d02fcf44f1ea1c"}, + {file = "rpds_py-2026.9.1-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:a3dbc5ed9514908d5046107d7b1346bde71eea61de6e0e4919c19354f97e769f"}, + {file = "rpds_py-2026.9.1-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:6eae33003518fd4cb4f83a218d5371469dd3001aa3b87128c005b07762f7fe5e"}, + {file = "rpds_py-2026.9.1-pp311-pypy311_pp80-macosx_10_12_x86_64.whl", hash = "sha256:0483515261947e4e8b8e1375bf7463e7eb6ccfb3d86e7b554d90cd5285f20f32"}, + {file = "rpds_py-2026.9.1-pp311-pypy311_pp80-macosx_11_0_arm64.whl", hash = "sha256:4cfaf02209061880210819934de2f4f6aa83dc04dafe6770276acc240a56da31"}, + {file = "rpds_py-2026.9.1-pp312-pypy312_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6cdc537c8633d7fd92a82e2e0d2ab74320a3f63d5e59fb9cf08711e08fe151c4"}, + {file = "rpds_py-2026.9.1-pp312-pypy312_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:10e208f2425d973938afcd56e28a7c4be32e27b6a60b5d381f49fb9d8acf9759"}, + {file = "rpds_py-2026.9.1-pp312-pypy312_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6c0dbbcc19735fe5f8b0a54c07659d154a9e69f47e15d0a6ab7299215daf62cb"}, + {file = "rpds_py-2026.9.1-pp312-pypy312_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:684fd492fff4fead00587544e059be2bbcb6f93454f21fa2a91b66fc7508be82"}, + {file = "rpds_py-2026.9.1-pp312-pypy312_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d1028417bb44037eb3069c1009bd7b7277212876cda22fbe565b0bca9fab6d2c"}, + {file = "rpds_py-2026.9.1-pp312-pypy312_pp73-manylinux_2_31_riscv64.whl", hash = "sha256:492e5e428cbe126221611f47e068f01660352feec4ad18bc0f5ea9b2ae88fb14"}, + {file = "rpds_py-2026.9.1-pp312-pypy312_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:88b5268892fde430d5531f95bc560b6efbbd67c929662c586afd729a96e7461c"}, + {file = "rpds_py-2026.9.1-pp312-pypy312_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:01445c8d194aa032a08e944f16567672da1c62dbdbefd8b6d0693032e290cf68"}, + {file = "rpds_py-2026.9.1-pp312-pypy312_pp73-musllinux_1_2_i686.whl", hash = "sha256:eef6a03b0b6d08d0835ccfa8ec8d1bc70525e3801387567137b50c557695e6da"}, + {file = "rpds_py-2026.9.1-pp312-pypy312_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:6b9bf3135b4ad5981df9a73d71a35272d650a2985ae9c2746357b24d59de2448"}, + {file = "rpds_py-2026.9.1-pp312-pypy312_pp80-macosx_10_12_x86_64.whl", hash = "sha256:56c6952a9b15047466d0c2347c446a761d4527f89976156341e68f0ce5cc08b0"}, + {file = "rpds_py-2026.9.1-pp312-pypy312_pp80-macosx_11_0_arm64.whl", hash = "sha256:b242c27c8f836305a4a72df9cdd564386ac57b807bd252a063223331c9316b37"}, + {file = "rpds_py-2026.9.1.tar.gz", hash = "sha256:4793ef7f78268b124b73fa933440f01d258bbae01de9fa53e9080c9ab0425a12"}, ] [[package]] name = "s3transfer" -version = "0.19.0" +version = "0.19.2" description = "An Amazon S3 Transfer Manager" optional = false python-versions = ">=3.10" groups = ["main", "dev"] files = [ - {file = "s3transfer-0.19.0-py3-none-any.whl", hash = "sha256:777cc2415536f1debadb5c2ef7779275d0fc0fe0e042411cdd6caebeb2685262"}, - {file = "s3transfer-0.19.0.tar.gz", hash = "sha256:ce436931687addc4c1712d52d40b32f53e88315723f107ffa20ba82b05a0f685"}, + {file = "s3transfer-0.19.2-py3-none-any.whl", hash = "sha256:d8168eccca828cbb2cd573675333f3bddd254313a9c42494b84c76b539e8ba25"}, + {file = "s3transfer-0.19.2.tar.gz", hash = "sha256:ba0309fd86be3c27dbf78cdd813c13c5e1df16e5874b99d2535ebbdfb9892993"}, ] [package.dependencies] -botocore = ">=1.37.4,<2.0a0" +botocore = ">=1.37.4,<2.0a.0" [package.extras] -crt = ["botocore[crt] (>=1.37.4,<2.0a0)"] +crt = ["botocore[crt] (>=1.37.4,<2.0a.0)"] [[package]] name = "semver" -version = "3.0.4" +version = "3.1.0" description = "Python helper for Semantic Versioning (https://semver.org)" optional = false -python-versions = ">=3.7" +python-versions = ">=3.10" groups = ["main"] files = [ - {file = "semver-3.0.4-py3-none-any.whl", hash = "sha256:9c824d87ba7f7ab4a1890799cec8596f15c1241cb473404ea1cb0c55e4b04746"}, - {file = "semver-3.0.4.tar.gz", hash = "sha256:afc7d8c584a5ed0a11033af086e8af226a9c0b206f313e0301f8dd7b6b589602"}, + {file = "semver-3.1.0-py3-none-any.whl", hash = "sha256:6e4998f8b4762acdfea85f9bfd5b4032e0bb50038dc04bf82011b42d5d1145c5"}, + {file = "semver-3.1.0.tar.gz", hash = "sha256:14bc073439513d7773662a338f4db9829cf16c12b74b9568e2d2689975fbd7fc"}, ] +[package.extras] +native = ["fast-semver-rs-backend (>=0.1.1) ; platform_python_implementation == \"CPython\""] + [[package]] name = "six" version = "1.17.0" @@ -2425,14 +2645,14 @@ files = [ [[package]] name = "snowballstemmer" -version = "3.0.1" -description = "This package provides 32 stemmers for 30 languages generated from Snowball algorithms." +version = "3.1.1" +description = "This package provides 36 stemmers for 34 languages generated from Snowball algorithms." optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*" +python-versions = ">=3.3" groups = ["docs"] files = [ - {file = "snowballstemmer-3.0.1-py3-none-any.whl", hash = "sha256:6cd7b3897da8d6c9ffb968a6781fa6532dce9c3618a4b127d920dab764a19064"}, - {file = "snowballstemmer-3.0.1.tar.gz", hash = "sha256:6d5eeeec8e9f84d4d56b847692bacf79bc2c8e90c7f80ca4444ff8b6f2e52895"}, + {file = "snowballstemmer-3.1.1-py3-none-any.whl", hash = "sha256:7e207fa178741da09cdee59d3ecec3827ad5f92b1fc5c9ff3755b639f71f5752"}, + {file = "snowballstemmer-3.1.1.tar.gz", hash = "sha256:e07bbc54a0d798fe6010a12398422e62a8bfbba95c394fd0956ef58cb4d3e260"}, ] [[package]] @@ -2466,37 +2686,16 @@ sphinxcontrib-jsmath = ">=1.0.1" sphinxcontrib-qthelp = ">=1.0.6" sphinxcontrib-serializinghtml = ">=1.1.9" -[[package]] -name = "sphinx-click" -version = "6.2.0" -description = "Sphinx extension that automatically documents click applications" -optional = false -python-versions = ">=3.10" -groups = ["docs"] -files = [ - {file = "sphinx_click-6.2.0-py3-none-any.whl", hash = "sha256:1fb1851cb4f2c286d43cbcd57f55db6ef5a8d208bfc3370f19adde232e5803d7"}, - {file = "sphinx_click-6.2.0.tar.gz", hash = "sha256:fc78b4154a4e5159462e36de55b8643747da6cda86b3b52a8bb62289e603776c"}, -] - -[package.dependencies] -click = ">=8.0" -docutils = "*" -sphinx = ">=4.0" - -[package.extras] -docs = ["reno"] -test = ["pytest", "pytest-cov"] - [[package]] name = "sphinx-markdown-builder" -version = "0.6.10" +version = "0.6.11" description = "A Sphinx extension to add markdown generation support." optional = false python-versions = ">=3.7" groups = ["docs"] files = [ - {file = "sphinx_markdown_builder-0.6.10-py3-none-any.whl", hash = "sha256:16d86738b9ac69fcbc86e373c31c6402c30af1fa8d98d0f62cc5f38bfe5fc26e"}, - {file = "sphinx_markdown_builder-0.6.10.tar.gz", hash = "sha256:cd5acf88d52ea0146a712fd557404f10326dff3428a78ba928e59b1727fd4a86"}, + {file = "sphinx_markdown_builder-0.6.11-py3-none-any.whl", hash = "sha256:acfb94d6ee66c7a47da0ca0420578fa16f115812af25b8fd21755d5909aacf51"}, + {file = "sphinx_markdown_builder-0.6.11.tar.gz", hash = "sha256:ba3bf33e0e42ff30ae686ac73957a95e6d045790dcfbaca012dd8ae01794e577"}, ] [package.dependencies] @@ -2659,14 +2858,14 @@ test = ["pytest"] [[package]] name = "stevedore" -version = "5.8.0" +version = "5.9.1" description = "Manage dynamic plugins for Python applications" optional = false -python-versions = ">=3.10" +python-versions = ">=3.11" groups = ["dev"] files = [ - {file = "stevedore-5.8.0-py3-none-any.whl", hash = "sha256:88eede9e66ca80e34085b9174e2327da2c61ac91f24f70e41c3ad76e4bb4872b"}, - {file = "stevedore-5.8.0.tar.gz", hash = "sha256:b49867b32ca3016e94100e68dbf26e72aa7b8708d0a3f73c08aeb220370ac715"}, + {file = "stevedore-5.9.1-py3-none-any.whl", hash = "sha256:5c8ff3a9f336cc1a06ac0f597bc79d11a2f950bfd32e290ca56b5a301fafafbf"}, + {file = "stevedore-5.9.1.tar.gz", hash = "sha256:e97a2667923efda926e8713fde6a73616df68210a3cbc6f02b48967b676fd8bf"}, ] [[package]] @@ -2684,52 +2883,28 @@ files = [ [package.extras] widechars = ["wcwidth"] -[[package]] -name = "types-awscrt" -version = "0.31.3" -description = "Type annotations and code completion for awscrt" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "types_awscrt-0.31.3-py3-none-any.whl", hash = "sha256:e5ce65a00a2ab4f35eacc1e3d700d792338d56e4823ee7b4dbe017f94cfc4458"}, - {file = "types_awscrt-0.31.3.tar.gz", hash = "sha256:09d3eaf00231e0f47e101bd9867e430873bc57040050e2a3bd8305cb4fc30865"}, -] - -[[package]] -name = "types-click" -version = "7.1.8" -description = "Typing stubs for click" -optional = false -python-versions = "*" -groups = ["dev"] -files = [ - {file = "types-click-7.1.8.tar.gz", hash = "sha256:b6604968be6401dc516311ca50708a0a28baa7a0cb840efd7412f0dbbff4e092"}, - {file = "types_click-7.1.8-py3-none-any.whl", hash = "sha256:8cb030a669e2e927461be9827375f83c16b8178c365852c060a34e24871e7e81"}, -] - [[package]] name = "types-pyyaml" -version = "6.0.12.20260518" +version = "6.0.12.20260906" description = "Typing stubs for PyYAML" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "types_pyyaml-6.0.12.20260518-py3-none-any.whl", hash = "sha256:d2150f75a231c9fe9c7463bd29487d93e60bac90400287351384bc2284eba7cd"}, - {file = "types_pyyaml-6.0.12.20260518.tar.gz", hash = "sha256:d917f83fb38462550338c1297faedd860b3ec83912b96b1e3d73255f7473e466"}, + {file = "types_pyyaml-6.0.12.20260906-py3-none-any.whl", hash = "sha256:bca893ff0d51df5c9053137d5d0e6ccd36e939a196356f1d5c16372422f5137b"}, + {file = "types_pyyaml-6.0.12.20260906.tar.gz", hash = "sha256:f59c1cc05010b833d2d72287bbaa72610106b28d42d89a907313117faba85212"}, ] [[package]] name = "types-requests" -version = "2.33.0.20260518" +version = "2.33.0.20260906" description = "Typing stubs for requests" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "types_requests-2.33.0.20260518-py3-none-any.whl", hash = "sha256:626d697d1adaaff76e2044dc8c5c051d8f21abc157bdfe204a75558076fe0bf0"}, - {file = "types_requests-2.33.0.20260518.tar.gz", hash = "sha256:df7bd3bfe0ca8402dfb841e7d9be714bb5578203283d66d7dc4ef69343449a5e"}, + {file = "types_requests-2.33.0.20260906-py3-none-any.whl", hash = "sha256:9f53622652bd921ead7a54d665be1b8d518165c8b51cc9d68d944cd6b6bfa8fb"}, + {file = "types_requests-2.33.0.20260906.tar.gz", hash = "sha256:76ab8a0fb736744a0c3deee7aa57b2927e301f078d9e61f5391b3e92002416b9"}, ] [package.dependencies] @@ -2749,26 +2924,26 @@ files = [ [[package]] name = "typing-extensions" -version = "4.15.0" +version = "4.16.0" description = "Backported and Experimental Type Hints for Python 3.9+" optional = false python-versions = ">=3.9" groups = ["main", "dev"] files = [ - {file = "typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548"}, - {file = "typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466"}, + {file = "typing_extensions-4.16.0-py3-none-any.whl", hash = "sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8"}, + {file = "typing_extensions-4.16.0.tar.gz", hash = "sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5"}, ] [[package]] name = "urllib3" -version = "2.7.0" +version = "2.8.0" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = ">=3.10" groups = ["main", "dev", "docs"] files = [ - {file = "urllib3-2.7.0-py3-none-any.whl", hash = "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897"}, - {file = "urllib3-2.7.0.tar.gz", hash = "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c"}, + {file = "urllib3-2.8.0-py3-none-any.whl", hash = "sha256:0cf3cae568d36aa9576b28dfb35f11328f1cb974ca7647d9475ebb86c75ac6e3"}, + {file = "urllib3-2.8.0.tar.gz", hash = "sha256:63bf2ead4c879426ebf22ef2a781eeb4aa3b4ae798a0435506f8687fd5bb9b63"}, ] [package.extras] @@ -2779,32 +2954,33 @@ zstd = ["backports-zstd (>=1.0.0) ; python_version < \"3.14\""] [[package]] name = "virtualenv" -version = "21.3.3" +version = "21.14.5" description = "Virtual Python Environment builder" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "virtualenv-21.3.3-py3-none-any.whl", hash = "sha256:7d5987d8369e098e41406efb780a3d4ca79280097293899e351a6407ee153ab3"}, - {file = "virtualenv-21.3.3.tar.gz", hash = "sha256:f5bda277e553b1c2b3c1a8debfc30496e1288cc93ce6b7b71b3280047e317328"}, + {file = "virtualenv-21.14.5-py3-none-any.whl", hash = "sha256:b0651e0174982bba17cc6f0aaa2ef496730cb85a3f35eb5d1119d1c904f7d1da"}, + {file = "virtualenv-21.14.5.tar.gz", hash = "sha256:c4cb6c13e46b57225a999c7e22a09b163393878facc7ac4c059a57f46faa1647"}, ] [package.dependencies] distlib = ">=0.3.7,<1" -filelock = {version = ">=3.24.2,<4", markers = "python_version >= \"3.10\""} +filelock = {version = ">=3.24.2,<5", markers = "python_version >= \"3.10\""} +packaging = ">=23.1" platformdirs = ">=3.9.1,<5" -python-discovery = ">=1.3.1" +python-discovery = ">=1.6" [[package]] name = "werkzeug" -version = "3.1.8" +version = "3.1.9" description = "The comprehensive WSGI web application library." optional = false python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "werkzeug-3.1.8-py3-none-any.whl", hash = "sha256:63a77fb8892bf28ebc3178683445222aa500e48ebad5ec77b0ad80f8726b1f50"}, - {file = "werkzeug-3.1.8.tar.gz", hash = "sha256:9bad61a4268dac112f1c5cd4630a56ede601b6ed420300677a869083d70a4c44"}, + {file = "werkzeug-3.1.9-py3-none-any.whl", hash = "sha256:6392e50c78460ba618e5b21f08a71f59c99ce99cdc6cf6e3dd7e6ccca8754fab"}, + {file = "werkzeug-3.1.9.tar.gz", hash = "sha256:55ca7c70a75689be937aa27f8ff4b018f06ff4838fc73045560bf0f5a1291060"}, ] [package.dependencies] @@ -2831,4 +3007,4 @@ test = ["pytest", "pytest-cov"] [metadata] lock-version = "2.1" python-versions = ">=3.13,!=3.14.1" -content-hash = "b89a42dd269e68aaf5515aaa786491a9ed3b3ff2e6742b6c3bb29ec68047412d" +content-hash = "4bf10225df8f9ad839ed957b95fd30f9c17b439bc078ef7fa402287870f8bbae" diff --git a/pyproject.toml b/pyproject.toml index 6db81aed..8758feb7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "gardenlinux" -version = "0.10.19" +version = "1.0.0" description = "Contains tools to work with the features directory of gardenlinux, for example deducting dependencies from feature sets or validating cnames" authors = ["Garden Linux Maintainers "] license = "Apache-2.0" @@ -10,47 +10,44 @@ packages = [{ include = "gardenlinux", from = "src" }] [tool.poetry.dependencies] python = ">=3.13,!=3.14.1" apt-repo = "^0.5" -boto3 = "^1.43.10" -click = "^8.4.0" +boto3 = "^1.43.108" cryptography = "^49.0.0" jsonschema = "^4.26.0" -networkx = "^3.6" -oras = "^0.2.38" -podman = "^5.6.0" -pygit2 = "^1.19.1" -pygments = "^2.19.2" -PyGithub = "^2.8.1" -PyYAML = "^6.0.2" -semver = "^3.0.4" +networkx = "^3.7" +oras = "^0.2.43" +podman = "^5.8.0" +pygit2 = "^1.20.1" +pygments = "^2.21.0" +PyGithub = "^2.10.0" +PyYAML = "^6.0.3" +semver = "^3.1.0" [tool.poetry.group.dev.dependencies] bandit = "^1.9.4" isort = "^8.0.1" moto = "^5.2.1" -pre-commit = "^4.6.0" +pre-commit = "^4.6.2" python-dotenv = "^1.2.2" -pytest = "^9.0.3" +pytest = "^9.1.1" pytest-cov = "^7.1.0" requests-mock = "^1.12.1" mypy = "2.1.0" -types-click = "^7.1.8" types-pyyaml = "^6.0.12.20260518" types-requests = "^2.33.0.20260518" boto3-stubs = { extras = ["s3"], version = "^1.42.41" } [tool.poetry.group.docs.dependencies] -sphinx-rtd-theme = "^3.0.2" -sphinx-click = "^6.2.0" +sphinx-rtd-theme = "^3.1.0" sphinxcontrib-autoprogram = "^0.1.8" -sphinx-markdown-builder = "^0.6.10" +sphinx-markdown-builder = "^0.6.11" [tool.poetry.scripts] -gl-cname = "gardenlinux.features.cname_main:main" gl-feature-fs-diff = "gardenlinux.features.reproducibility.__main__:main" gl-features-parse = "gardenlinux.features.__main__:main" gl-flavors-parse = "gardenlinux.flavors.__main__:main" gl-gh-release = "gardenlinux.github.release.__main__:main" gl-oci = "gardenlinux.oci.__main__:main" +gl-metadata = "gardenlinux.features.metadata_main:main" gl-s3 = "gardenlinux.s3.__main__:main" [tool.pytest.ini_options] diff --git a/src/gardenlinux/constants.py b/src/gardenlinux/constants.py index 5c2fe8ed..d61101e6 100644 --- a/src/gardenlinux/constants.py +++ b/src/gardenlinux/constants.py @@ -4,9 +4,9 @@ ARCHS = ["amd64", "arm64"] # GardenLinux "bare" feature -BARE_FLAVOR_FEATURE_CONTENT = {"description": "Bare flavor", "type": "platform"} +BARE_CNAME_FEATURE_CONTENT = {"description": "Bare flavor", "type": "platform"} -BARE_FLAVOR_LIBC_FEATURE_CONTENT = { +BARE_CNAME_LIBC_FEATURE_CONTENT = { "description": "Bare libc feature", "type": "element", } @@ -147,6 +147,7 @@ GL_BUG_REPORT_URL = "https://github.com/gardenlinux/gardenlinux/issues" GL_COMMIT_SPECIAL_VALUES = ("local",) +GL_VERSION_SPECIAL_VALUES = ("today",) GL_CONTAINER_REGISTRY_BASE_URL = "ghcr.io/gardenlinux/gardenlinux" GL_DEB_REPO_BASE_URL = "https://packages.gardenlinux.io/gardenlinux" GL_DISTRIBUTION_NAME = "Garden Linux" diff --git a/src/gardenlinux/features/__init__.py b/src/gardenlinux/features/__init__.py index a6e7692e..ed61af2f 100644 --- a/src/gardenlinux/features/__init__.py +++ b/src/gardenlinux/features/__init__.py @@ -4,7 +4,10 @@ Features module """ -from .cname import CName +from .artifact_base_name import ArtifactBaseName +from .c_name import CName +from .flavor import Flavor from .parser import Parser +from .versioned_flavor import VersionedFlavor -__all__ = ["CName", "Parser"] +__all__ = ["ArtifactBaseName", "CName", "Flavor", "Parser", "VersionedFlavor"] diff --git a/src/gardenlinux/features/__main__.py b/src/gardenlinux/features/__main__.py index d0b7f8ad..7cd2501e 100644 --- a/src/gardenlinux/features/__main__.py +++ b/src/gardenlinux/features/__main__.py @@ -6,31 +6,32 @@ """ import argparse -import logging import os import re from os import path from typing import Any, Set -from .cname import CName +from .artifact_base_name import ArtifactBaseName from .parser import Parser _ARGS_TYPE_ALLOWED = [ + "arch", + "artifact-base-name", "cname", - "cname_base", - "container_name", - "container_tag", - "commit_id", + "commit-id", + "container-name", + "container-tag", + "elements", "features", - "platform", - "platforms", "flags", "flavor", - "elements", - "arch", - "version", - "version_and_commit_id", "graph", + "platform", + "platform-variant", + "platforms", + "version", + "version_and_commit-id", + "versioned-flavor", ] RE_CAMEL_CASE_SPLITTER = re.compile("([A-Z]+|[a-z0-9])([A-Z])(?!$)") @@ -50,20 +51,25 @@ def get_parser() -> argparse.ArgumentParser: parser = argparse.ArgumentParser( prog="gl-features-parse", - description="Parse and extract information from GardenLinux features.", + description="Parse and extract information from Garden Linux features.", ) parser.add_argument( "--arch", dest="arch", - help="Target architecture (e.g., amd64, arm64). Overrides architecture from cname.", + help="Target architecture (e.g., amd64, arm64). Overrides architecture from CName.", + ) + + parser.add_argument( + "--artifact-base-name", + dest="artifact_base_name", + help="Artifact base name to parse. Must be a valid Garden Linux Artifact Base Name.", ) parser.add_argument( "--cname", dest="cname", - required=True, - help="Canonical name (cname) to parse. Must be a valid GardenLinux canonical name.", + help="Canonical Name (CName) to parse.", ) parser.add_argument( @@ -79,21 +85,23 @@ def get_parser() -> argparse.ArgumentParser: ) parser.add_argument( - "--release-file", - dest="release_file", - help="Path to a release file containing cname metadata. Either --feature-dir or --release-file must be provided.", + "--flavor", + dest="flavor", + help="Garden Linux flavor name.", ) parser.add_argument( - "--default-arch", - dest="default_arch", - help="Default architecture to use if architecture cannot be determined from cname or other sources.", + "--ignore", + dest="ignore", + type=lambda arg: set([f for f in arg.split(",") if f]), + default=set(), + help="Comma-separated list of features to ignore when processing (e.g., 'feature1,feature2').", ) parser.add_argument( - "--default-version", - dest="default_version", - help="Default version to use if version cannot be determined from files or other sources.", + "--release-file", + dest="release_file", + help="Path to a release file containing features metadata. Either --feature-dir or --release-file must be provided.", ) parser.add_argument( @@ -103,11 +111,9 @@ def get_parser() -> argparse.ArgumentParser: ) parser.add_argument( - "--ignore", - dest="ignore", - type=lambda arg: set([f for f in arg.split(",") if f]), - default=set(), - help="Comma-separated list of features to ignore when processing (e.g., 'feature1,feature2').", + "--versioned-flavor", + dest="versioned_flavor", + help="Garden Linux versioned flavor name.", ) parser.add_argument( @@ -133,143 +139,78 @@ def main() -> None: parser = get_parser() args = parser.parse_args() - assert bool(args.feature_dir) or bool(args.release_file), ( - "Please provide either `--feature_dir` or `--release_file` argument" + assert args.feature_dir or args.release_file or os.environ.get("GL_ROOT_DIR"), ( + "Please provide either `--feature-dir` or `--release-file` argument" ) arch = args.arch commit_id_or_hash = args.commit - gardenlinux_root = path.dirname(args.feature_dir) + gardenlinux_root = os.environ.get("GL_ROOT_DIR", path.dirname(args.feature_dir)) version = args.version - if arch is None or arch == "": - arch = args.default_arch - - if gardenlinux_root == "": + if not gardenlinux_root: gardenlinux_root = "." - if version is None or version == "": - try: - version, commit_id_or_hash = get_version_and_commit_id_from_files( - gardenlinux_root - ) - except RuntimeError as exc: - logging.debug( - "Failed to parse version information for GL root '{0}': {1}".format( - gardenlinux_root, exc - ) - ) - - version = args.default_version + if not version or not commit_id_or_hash: + version, commit_id_or_hash = ( + ArtifactBaseName.get_version_and_commit_id_from_files(gardenlinux_root) + ) - cname = CName(args.cname, arch=arch, commit_hash=commit_id_or_hash, version=version) + abn_object = ArtifactBaseName.new_instance( + args.artifact_base_name, + cname=args.cname, + flavor=args.flavor, + versioned_flavor=args.versioned_flavor, + arch=arch, + version=version, + commit_id_or_hash=commit_id_or_hash, + ) if args.release_file is not None: - cname.load_from_release_file(args.release_file) - - arch = cname.arch - flavor = cname.flavor - commit_id_or_hash = cname.commit_id - version = cname.version - - if (arch is None or arch == "") and ( - args.type in ("cname", "container_name", "arch") - ): - raise RuntimeError( - "Architecture could not be determined and no default architecture set" - ) + abn_object.load_from_release_file(args.release_file) - if (commit_id_or_hash is None or commit_id_or_hash == "") and ( - args.type in ("container_tag", "commit_id", "version_and_commit_id") - ): - raise RuntimeError("Commit ID not specified") - - if (version is None or version == "") and ( - args.type - in ( - "container_tag", - "commit_id", - "version", - "version_and_commit_id", - ) - ): - raise RuntimeError("Version not specified and no default version set") + arch = abn_object.arch + cname = abn_object.cname + commit_id_or_hash = abn_object.commit_id + version = abn_object.version feature_dir_name = path.basename(args.feature_dir) if args.type == "arch": print(arch) elif args.type in ( - "cname_base", + "artifact-base-name", "cname", - "container_name", + "container-name", "elements", "features", "flags", "flavor", "graph", "platform", + "platform-variant", "platforms", + "versioned-flavor", ): if args.type == "graph" or len(args.ignore) > 0: features_parser = Parser(gardenlinux_root, feature_dir_name) print_output_from_features_parser( - args.type, cname, features_parser, flavor, args.ignore + args.type, abn_object, features_parser, cname, args.ignore ) else: - print_output_from_cname(args.type, cname) - elif args.type == "commit_id": - print(commit_id_or_hash[:8]) # type: ignore[index] - elif args.type == "container_tag": - print(re.sub("\\W+", "-", f"{version}-{commit_id_or_hash[:8]}")) # type: ignore[index] + print_output_from_abn_object(args.type, abn_object) + elif args.type == "commit-id": + print(commit_id_or_hash[:8]) + elif args.type == "container-tag": + print(re.sub("\\W+", "-", f"{version}-{commit_id_or_hash[:8]}")) elif args.type == "version": print(version) - elif args.type == "version_and_commit_id": - print(f"{version}-{commit_id_or_hash[:8]}") # type: ignore[index] - - -def get_version_and_commit_id_from_files(gardenlinux_root: str) -> tuple[str, str]: - """ - Returns the version and commit ID based on files in the GardenLinux root directory. - - :param gardenlinux_root: GardenLinux root directory - - :return: (tuple) Version and commit ID if readable - :since: 0.7.0 - """ - - commit_hash = None - version = None - - if os.access(path.join(gardenlinux_root, "COMMIT"), os.R_OK): - with open(path.join(gardenlinux_root, "COMMIT"), "r") as fp: - commit_hash = fp.read().strip()[:8] - - if os.access(path.join(gardenlinux_root, "VERSION"), os.R_OK): - with open(path.join(gardenlinux_root, "VERSION"), "r") as fp: - version = fp.read().strip() - - if commit_hash is None or version is None: - raise RuntimeError("Failed to read version or commit ID from files") - - return (version, commit_hash) + elif args.type == "version_and_commit-id": + print(f"{version}-{commit_id_or_hash[:8]}") -def get_minimal_feature_set(graph: Any) -> Set[str]: - """ - Returns the minimal set of features described by the given graph. - - :param graph: networkx.Digraph - - :return: (set) Minimal set of features - :since: 0.7.0 - """ - - return set([node for (node, degree) in graph.in_degree() if degree == 0]) - - -def graph_as_mermaid_markup(flavor: str | None, graph: Any) -> str: +def graph_as_mermaid_markup(cname: str | None, graph: Any) -> str: """ Generates a mermaid.js representation of the graph. This is helpful to identify dependencies between features. @@ -277,17 +218,17 @@ def graph_as_mermaid_markup(flavor: str | None, graph: Any) -> str: Syntax docs: https://mermaid.js.org/syntax/flowchart.html?id=flowcharts-basic-syntax - :param flavor: Flavor name - :param graph: networkx.Digraph + :param cname: Garden Linux canonical name + :param graph: networkx.Digraph :return: (str) mermaid.js representation :since: 0.7.0 """ - if flavor is None: - raise RuntimeError("Error while generating graph: Flavor is None!") + if cname is None: + raise RuntimeError("Error while generating graph: CName is None!") - markup = f"---\ntitle: Dependency Graph for Feature {flavor}\n---\ngraph TD;\n" + markup = f"---\ntitle: Dependency Graph for Feature {cname}\n---\ngraph TD;\n" for u, v in graph.edges: markup += f" {u}-->{v};\n" @@ -297,9 +238,9 @@ def graph_as_mermaid_markup(flavor: str | None, graph: Any) -> str: def print_output_from_features_parser( output_type: str, - cname_instance: CName, + abn_object: ArtifactBaseName, parser: Parser, - flavor: str, + cname: str, ignores_list: Set[str], ) -> None: """ @@ -307,7 +248,7 @@ def print_output_from_features_parser( :param output_type: Output type :param parser: Features parser - :param flavor: Flavor + :param cname: Garden Linux canonical name :param ignores_list: Features to ignore :since: 1.0.0 @@ -316,54 +257,61 @@ def print_output_from_features_parser( def additional_filter_func(node: str) -> bool: return node not in ignores_list - if output_type == "features": - print( - parser.filter_as_string( - flavor, additional_filter_func=additional_filter_func + match output_type: + case "features": + print( + parser.filter_as_string( + cname, additional_filter_func=additional_filter_func + ) + ) + case "platform" | "platforms" | "elements" | "flags": + features_by_type = parser.filter_as_dict( + cname, additional_filter_func=additional_filter_func ) - ) - elif output_type in ("platform", "platforms", "elements", "flags"): - features_by_type = parser.filter_as_dict( - flavor, additional_filter_func=additional_filter_func - ) - - if output_type == "platform": - print(features_by_type["platform"][0]) - if output_type == "platforms": - print(",".join(features_by_type["platform"])) - elif output_type == "elements": - print(",".join(features_by_type["element"])) - elif output_type == "flags": - print(",".join(features_by_type["flag"])) - else: - graph = parser.filter(flavor, additional_filter_func=additional_filter_func) - - sorted_features = Parser.sort_graph_nodes(graph) - minimal_feature_set = get_minimal_feature_set(graph) - - sorted_minimal_features = Parser.subset(minimal_feature_set, sorted_features) - - cname_base = Parser.get_flavor_from_feature_set(sorted_minimal_features) - - if output_type == "cname_base": - print(cname_base) - elif output_type == "cname": - cname = flavor - - if cname_instance.arch is not None: - cname += f"-{cname_instance.arch}" - - if cname_instance.version_and_commit_id is not None: - cname += f"-{cname_instance.version_and_commit_id}" - - print(cname) - elif output_type == "container_name": - print(RE_CAMEL_CASE_SPLITTER.sub("\\1_\\2", cname_base).lower()) - elif output_type == "graph": - print(graph_as_mermaid_markup(flavor, graph)) + match output_type: + case "elements": + print(",".join(features_by_type["element"])) + case "flags": + print(",".join(features_by_type["flag"])) + case "platform": + print(features_by_type["platform"][0]) + case "platforms": + print(",".join(features_by_type["platform"])) + case "platform-variant": + print(abn_object.platform_variant) + case _: + graph = parser.filter(cname, additional_filter_func=additional_filter_func) + + sorted_features = Parser.sort_graph_nodes(graph) + minimal_feature_set = Parser.get_minimal_feature_set(graph) + + sorted_minimal_features = Parser.subset( + minimal_feature_set, sorted_features + ) -def print_output_from_cname(output_type: str, cname_instance: CName) -> None: + cname = Parser.get_cname_from_feature_set(sorted_minimal_features) + + match output_type: + case "artifact-base-name": + print( + f"{cname}-{abn_object.arch}-{abn_object.version_and_commit_id}" + ) + case "cname": + print(cname) + case "container-name": + print(RE_CAMEL_CASE_SPLITTER.sub("\\1_\\2", cname).lower()) + case "flavor": + print(f"{cname}-{abn_object.arch}") + case "graph": + print(graph_as_mermaid_markup(cname, graph)) + case "versioned-flavor": + print(f"{cname}-{abn_object.arch}-{abn_object.version}") + + +def print_output_from_abn_object( + output_type: str, abn_object: ArtifactBaseName +) -> None: """ Prints output to stdout based on the given CName instance. @@ -373,33 +321,35 @@ def print_output_from_cname(output_type: str, cname_instance: CName) -> None: :since: 1.0.0 """ - if output_type in ("cname_base", "cname", "flavor"): - sorted_features = Parser.get_flavor_as_feature_set(cname_instance.flavor) - flavor = Parser.get_flavor_from_feature_set(sorted_features) - - if output_type in ("cname_base", "flavor"): - print(flavor) - else: - if cname_instance.version_and_commit_id is None: - raise RuntimeError( - "Version and commit ID can't be provided without appropriate input." - ) - - print( - f"{flavor}-{cname_instance.arch}-{cname_instance.version_and_commit_id}" - ) - elif output_type == "container_name": - print(RE_CAMEL_CASE_SPLITTER.sub("\\1-\\2", cname_instance.flavor).lower()) - elif output_type == "platform": - print(cname_instance.platform) - elif output_type == "platforms": - print(cname_instance.feature_set_platform) - elif output_type == "elements": - print(cname_instance.feature_set_element) - elif output_type == "features": - print(cname_instance.feature_set) - elif output_type == "flags": - print(cname_instance.feature_set_flag) + match output_type: + case "artifact-base-name" | "cname" | "flavor" | "versioned-flavor": + cname = abn_object.cname + + match output_type: + case "artifact-base-name": + print( + f"{cname}-{abn_object.arch}-{abn_object.version_and_commit_id}" + ) + case "cname": + print(cname) + case "flavor": + print(f"{cname}-{abn_object.arch}") + case "versioned-flavor": + print(f"{cname}-{abn_object.arch}-{abn_object.version}") + case "container-name": + print(RE_CAMEL_CASE_SPLITTER.sub("\\1-\\2", abn_object.cname).lower()) + case "elements": + print(abn_object.feature_set_element) + case "features": + print(abn_object.feature_set) + case "flags": + print(abn_object.feature_set_flag) + case "platform": + print(abn_object.platform) + case "platform-variant": + print(abn_object.platform_variant) + case "platforms": + print(abn_object.feature_set_platform) if __name__ == "__main__": diff --git a/src/gardenlinux/features/artifact_base_name.py b/src/gardenlinux/features/artifact_base_name.py new file mode 100644 index 00000000..e4112471 --- /dev/null +++ b/src/gardenlinux/features/artifact_base_name.py @@ -0,0 +1,442 @@ +# -*- coding: utf-8 -*- + +""" +Artifact base name (ABN) +""" + +import os +import re +from configparser import UNNAMED_SECTION, ConfigParser +from os import PathLike +from pathlib import Path +from typing import Optional, Self + +from ..constants import ( + GL_BUG_REPORT_URL, + GL_COMMIT_SPECIAL_VALUES, + GL_DISTRIBUTION_NAME, + GL_HOME_URL, + GL_RELEASE_ID, + GL_SUPPORT_URL, + GL_VERSION_SPECIAL_VALUES, +) +from .versioned_flavor import VersionedFlavor + + +class ArtifactBaseName(VersionedFlavor): + """ + Class to represent an artifact base name (ABN). It can be parsed from any + file type. + + :author: Garden Linux Maintainers + :copyright: Copyright 2026 SAP SE + :package: gardenlinux + :subpackage: features + :since: 1.0.0 + :license: https://www.apache.org/licenses/LICENSE-2.0 + Apache License, Version 2.0 + """ + + def __init__( + self, + artifact: str, + ): + """ + Constructor __init__(ArtifactBaseName) + + :param artifact: Artifact name + + :since: 1.0.0 + """ + + re_object = re.compile( + "([a-zA-Z0-9]+([\\_\\-][a-zA-Z0-9]+)*?)-([a-z0-9]+)-([a-z0-9.]+)-([a-z0-9]+)(\\.|$)" + ) + + re_match = re_object.match(artifact) + + if not re_match: + raise ValueError(f"Not a valid Garden Linux artifact: {artifact}") + + commit_id_or_hash = re_match[5] + + self._commit_id = commit_id_or_hash[:8] + self._commit_hash = None + + if ( + len(commit_id_or_hash) == 40 + or commit_id_or_hash in GL_COMMIT_SPECIAL_VALUES + ): # sha1 hex + self._commit_hash = commit_id_or_hash + + VersionedFlavor.__init__(self, re_match[1], re_match[3], re_match[4]) + + @property + def commit_hash(self) -> Optional[str]: + """ + Returns the commit hash if part of the ABN parsed. + + :return: (str) Commit hash + :since: 1.0.0 + """ + + return self._commit_hash + + @commit_hash.setter + def commit_hash(self, commit_hash: str) -> None: + """ + Sets the commit hash + + :param commit_hash: Commit hash + + :since: 1.0.0 + """ + + if self._commit_id is not None and not commit_hash.startswith(self._commit_id): + raise RuntimeError("Commit hash given differs from commit ID already set") + + self._commit_id = commit_hash[:8] + self._commit_hash = commit_hash + + @property + def commit_id(self) -> str: + """ + Returns the commit ID if part of the ABN parsed. + + :return: (str) Commit ID + :since: 1.0.0 + """ + + return self._commit_id + + @property + def release_metadata_string(self) -> str: + """ + Returns the release metadata describing the given ABN instance. + + :return: (str) Release metadata + :since: 1.0.0 + """ + + commit_hash = self.commit_hash + commit_id = self.commit_id + platform_variant = self.platform_variant + version = self.version + + if commit_hash is None: + commit_hash = commit_id + + if platform_variant is None: + platform_variant = "" + + if version is None: + pretty_name = f"{GL_DISTRIBUTION_NAME} unsupported version" + version = "" + else: + pretty_name = f"{GL_DISTRIBUTION_NAME} {version}" + + metadata = f""" +ID={GL_RELEASE_ID} +ID_LIKE=debian +NAME="{GL_DISTRIBUTION_NAME}" +PRETTY_NAME="{pretty_name}" +IMAGE_VERSION={version} +VARIANT_ID="{self.flavor}" +HOME_URL="{GL_HOME_URL}" +SUPPORT_URL="{GL_SUPPORT_URL}" +BUG_REPORT_URL="{GL_BUG_REPORT_URL}" +GARDENLINUX_CNAME="{self.cname}" +GARDENLINUX_FEATURES="{self.feature_set}" +GARDENLINUX_FEATURES_PLATFORMS="{self.feature_set_platform}" +GARDENLINUX_FEATURES_ELEMENTS="{self.feature_set_element}" +GARDENLINUX_FEATURES_FLAGS="{self.feature_set_flag}" +GARDENLINUX_PLATFORM="{self.platform}" +GARDENLINUX_PLATFORM_VARIANT="{platform_variant}" +GARDENLINUX_VERSION="{version}" +GARDENLINUX_COMMIT_ID="{commit_id}" +GARDENLINUX_COMMIT_ID_LONG="{commit_hash}" + """.strip() + + return metadata + + @property + def version_and_commit_id(self) -> str: + """ + Returns the version and commit ID of the ABN parsed. + + :return: (str) Version and commit ID + :since: 1.0.0 + """ + + return f"{self.version}-{self.commit_id}" + + def __str__(self) -> str: + """ + Returns the Garden Linux artifact base name. + + :return: (str) Returns the ABN + :since: 1.0.0 + """ + + versioned_flavor = VersionedFlavor.__str__(self) + versioned_flavor += f"-{self.commit_id}" + + return versioned_flavor + + def _copy_from_instance(self, artifact_base_name: Self) -> None: + """ + Copies values from a given ABN instance. + + :param artifact_base_name: ABN instance + + :since: 1.0.0 + """ + + VersionedFlavor._copy_from_instance(self, artifact_base_name) + + self._commit_hash = artifact_base_name.commit_hash + self._commit_id = artifact_base_name.commit_id + + def load_from_release_file(self, release_file: PathLike[str] | str) -> None: + """ + Loads and parses a release metadata file. + + :param release_file: Release metadata file + + :since: 1.0.0 + """ + + artifact_base_name = self.__class__.new_from_release_file(release_file) + + if ( + artifact_base_name.flavor != self.flavor + or ( + self._commit_id is not None + and self._commit_id != artifact_base_name.commit_id + ) + or ( + self._version is not None + and self._version != artifact_base_name.version + ) + or ( + not self._flag_frankenstein + and artifact_base_name.platform + not in artifact_base_name.feature_set_platform + ) + ): + raise RuntimeError( + f"Release metadata file given is invalid: {release_file} failed consistency check - {self} != {artifact_base_name}" + ) + + self._copy_from_instance(artifact_base_name) + + def save_to_release_file( + self, release_file: PathLike[str] | str, overwrite: Optional[bool] = False + ) -> None: + """ + Saves the release metadata file. + + :param release_file: Release metadata file + + :since: 1.0.0 + """ + + if not isinstance(release_file, PathLike): + release_file = Path(release_file) + + if not overwrite and release_file.exists(): # type: ignore[attr-defined] + raise RuntimeError( + f"Refused to overwrite existing release metadata file: {release_file}" + ) + + with release_file.open("w") as fp: # type: ignore[attr-defined] + fp.write(self.release_metadata_string) + + @staticmethod + def new_from_release_file(release_file: PathLike[str] | str) -> "ArtifactBaseName": + """ + Loads and parses a release metadata file to return a new ABN instance. + + :param release_file: Release metadata file + + :return: (object) ABN instance + :since: 1.0.0 + """ + + if not isinstance(release_file, PathLike): + release_file = Path(release_file) + + if not release_file.exists(): # type: ignore[attr-defined] + raise RuntimeError( + f"Release metadata file given is invalid: {release_file}" + ) + + release_config = ConfigParser(allow_unnamed_section=True) + release_config.read(release_file) + + for release_field in ( + "VARIANT_ID", + "GARDENLINUX_COMMIT_ID_LONG", + "GARDENLINUX_FEATURES", + "GARDENLINUX_PLATFORM", + "GARDENLINUX_VERSION", + ): + if not release_config.has_option(UNNAMED_SECTION, release_field): + raise RuntimeError( + f"Release metadata file given is invalid: {release_file} misses {release_field}" + ) + + artifact_base_name = release_config.get(UNNAMED_SECTION, "VARIANT_ID").strip( + "\"'" + ) + + artifact_base_name += "-" + release_config.get( + UNNAMED_SECTION, "GARDENLINUX_VERSION" + ).strip("\"'") + + artifact_base_name += "-" + release_config.get( + UNNAMED_SECTION, "GARDENLINUX_COMMIT_ID_LONG" + ).strip("\"'") + + abn_object = ArtifactBaseName(artifact_base_name) + + abn_object._feature_set_cached = release_config.get( + UNNAMED_SECTION, "GARDENLINUX_FEATURES" + ).strip("\"'") + + if release_config.has_option(UNNAMED_SECTION, "GARDENLINUX_FEATURES_ELEMENTS"): + abn_object._feature_elements_cached = ( + release_config.get(UNNAMED_SECTION, "GARDENLINUX_FEATURES_ELEMENTS") + .strip("\"'") + .split(",") + ) + + if release_config.has_option(UNNAMED_SECTION, "GARDENLINUX_FEATURES_FLAGS"): + abn_object._feature_flags_cached = ( + release_config.get(UNNAMED_SECTION, "GARDENLINUX_FEATURES_FLAGS") + .strip("\"'") + .split(",") + ) + + if release_config.has_option(UNNAMED_SECTION, "GARDENLINUX_FEATURES_PLATFORMS"): + abn_object._feature_platforms_cached = ( + release_config.get(UNNAMED_SECTION, "GARDENLINUX_FEATURES_PLATFORMS") + .strip("\"'") + .split(",") + ) + + abn_object._platform_cached = release_config.get( + UNNAMED_SECTION, "GARDENLINUX_PLATFORM" + ).strip("\"'") + + if release_config.has_option(UNNAMED_SECTION, "GARDENLINUX_PLATFORM_VARIANT"): + abn_object._platform_variant_cached = release_config.get( + UNNAMED_SECTION, "GARDENLINUX_PLATFORM_VARIANT" + ).strip("\"'") + + return abn_object + + @staticmethod + def get_version_and_commit_id_from_files( + gardenlinux_root: Path | str, + ) -> tuple[Optional[str], Optional[str]]: + """ + Returns the version and commit ID based on files in the GardenLinux root directory. + + :param gardenlinux_root: GardenLinux root directory + + :return: (tuple) Version and commit ID if readable; None for both values otherwise + :since: 1.0.0 + """ + + if not isinstance(gardenlinux_root, PathLike): + gardenlinux_root = Path(gardenlinux_root) + + commit_hash = None + version = None + + if os.access(gardenlinux_root.joinpath("COMMIT"), os.R_OK): + with gardenlinux_root.joinpath("COMMIT").open("r") as fp: + commit_hash = fp.read().strip()[:8] + + if os.access(gardenlinux_root.joinpath("VERSION"), os.R_OK): + with gardenlinux_root.joinpath("VERSION").open("r") as fp: + version = fp.read().strip() + + if commit_hash is None or version is None: + return (None, None) + + return (version, commit_hash) + + @staticmethod + def new_instance( + artifact_base_name: Optional[str] = None, + versioned_flavor: Optional[str] = None, + flavor: Optional[str] = None, + cname: Optional[str] = None, + arch: Optional[str] = None, + version: Optional[str] = None, + commit_id_or_hash: Optional[str] = None, + ) -> "ArtifactBaseName": + """ + Returns a new ABN instance based on various input data available. + + :param artifact_base_name: Artifact base name + :param versioned_flavor: Garden Linux versioned flavor + :param flavor: Garden Linux flavor + :param cname: Garden Linux Ccanonical Name + :param arch: Artifact architecture + :param version: Artifact version + :param commit_id_or_hash: Artifact commit ID or hash + + :return: (object) ABN instance + :since: 1.0.0 + """ + + if not artifact_base_name: + if versioned_flavor: + if not commit_id_or_hash: + raise ValueError("Argument missing: commit_id_or_hash") + + artifact_base_name = versioned_flavor + f"-{commit_id_or_hash}" + elif flavor: + if not version: + raise ValueError("Argument missing: version") + if not commit_id_or_hash: + raise ValueError("Argument missing: commit_id_or_hash") + + artifact_base_name = flavor + f"-{version}-{commit_id_or_hash}" + elif cname: + if not arch: + raise ValueError("Argument missing: arch") + if not version: + raise ValueError("Argument missing: version") + if not commit_id_or_hash: + raise ValueError("Argument missing: commit_id_or_hash") + + artifact_base_name = cname + f"-{arch}-{version}-{commit_id_or_hash}" + else: + raise ValueError( + "Argument missing: At least one of artifact_base_name, cname, flavor or versioned_flavor" + ) + + abn_object = ArtifactBaseName(artifact_base_name) + + if cname and abn_object.cname != cname: + raise RuntimeError("CName does not match the given argument") + if arch and abn_object.arch != arch: + raise RuntimeError("Architecture does not match the given argument") + if ( + version + and version not in GL_VERSION_SPECIAL_VALUES + and abn_object.version != version + ): + raise RuntimeError("Version does not match the given argument") + + if commit_id_or_hash: + if abn_object.commit_hash and abn_object.commit_hash != commit_id_or_hash: + raise RuntimeError("Commit hash does not match the given argument") + elif abn_object.commit_id != commit_id_or_hash: + raise RuntimeError("Commit ID does not match the given argument") + + return abn_object diff --git a/src/gardenlinux/features/c_name.py b/src/gardenlinux/features/c_name.py new file mode 100644 index 00000000..cdb6a2fa --- /dev/null +++ b/src/gardenlinux/features/c_name.py @@ -0,0 +1,235 @@ +# -*- coding: utf-8 -*- + +""" +Garden Linux Canonical Name (CName) +""" + +from os import environ +from typing import Any, Dict, List, Optional, Self + +from ..constants import GL_PLATFORM_FRANKENSTEIN +from .parser import Parser + + +class CName(object): + """ + Class to represent a Garden Linux Canonical Name (CName). + + :author: Garden Linux Maintainers + :copyright: Copyright 2024 SAP SE + :package: gardenlinux + :subpackage: features + :since: 1.0.0 + :license: https://www.apache.org/licenses/LICENSE-2.0 + Apache License, Version 2.0 + """ + + def __init__( + self, + cname: str, + ): + """ + Constructor __init__(CName) + + :param cname: CName to represent + + :since: 1.0.0 + """ + + self._cname = cname + self._feature_elements_cached: Optional[List[str]] = None + self._feature_flags_cached: Optional[List[str]] = None + self._feature_platforms_cached: Optional[List[str]] = None + self._feature_set_cached: Optional[str] = None + self._features_cached: Optional[Dict[str, Any]] = None + self._platform_cached: Optional[str] = None + self._platform_variant_cached: Optional[str] = None + + self._flag_frankenstein = bool(environ.get("GL_ALLOW_FRANKENSTEIN", False)) + + self._flag_multiple_platforms = bool( + environ.get("GL_ALLOW_MULTIPLE_PLATFORMS", False) + ) + + if self._flag_frankenstein: + self._flag_multiple_platforms = True + + @property + def cname(self) -> str: + """ + Returns the CName parsed. + + :return: (str) CName + :since: 0.7.0 + """ + + return self._cname + + @property + def features(self) -> Dict[str, Any]: + """ + Returns the features for the CName parsed. + + :return: (dict) Features of the CName + :since: 0.10.14 + """ + + if self._features_cached is None: + self._features_cached = Parser().filter_as_dict(self.cname) + + return self._features_cached + + @property + def feature_set(self) -> str: + """ + Returns the feature set for the CName parsed. + + :return: (str) Feature set of the CName + :since: 0.7.0 + """ + + if self._feature_set_cached is not None: + return self._feature_set_cached + + return Parser().filter_as_string(self.cname) + + @property + def feature_set_element(self) -> str: + """ + Returns the feature set of type "element" for the CName parsed. + + :return: (str) Feature set elements + :since: 1.0.0 + """ + + if self._feature_elements_cached is not None: + return ",".join(self._feature_elements_cached) + + return ",".join(self.features["element"]) + + @property + def feature_set_flag(self) -> str: + """ + Returns the feature set of type "flag" for the CName parsed. + + :return: (str) Feature set flags + :since: 1.0.0 + """ + + if self._feature_flags_cached is not None: + return ",".join(self._feature_flags_cached) + + return ",".join(self.features["flag"]) + + @property + def feature_set_platform(self) -> str: + """ + Returns the feature set of type "platform" for the CName parsed. + + :return: (str) Feature set platform + :since: 1.0.0 + """ + + if self._feature_platforms_cached is None: + platforms = self.features["platform"] + else: + platforms = self._feature_platforms_cached + + if self._flag_multiple_platforms: + return ",".join(platforms) + + assert len(platforms) < 2, "Only one platform is supported" + return platforms[0] # type: ignore[no-any-return] + + @property + def feature_set_list(self) -> List[str]: + """ + Returns the feature set for the CName parsed. + + :return: (list) Feature set list of the CName + :since: 0.10.12 + """ + + if self._feature_set_cached is not None: + return self._feature_set_cached.split(",") + + return Parser().filter_as_list(self.cname) + + @property + def platform(self) -> str: + """ + Returns the platform for the CName parsed. + + :return: (str) Platform + :since: 0.7.0 + """ + + if self._platform_cached is not None: + platforms = [self._platform_cached] + elif self._feature_platforms_cached is not None: + platforms = self._feature_platforms_cached + else: + platforms = self.features["platform"] + + if self._flag_frankenstein and len(platforms) > 1: + return GL_PLATFORM_FRANKENSTEIN + + if not self._flag_multiple_platforms: + assert len(platforms) < 2 + "Only one platform is supported" + + return platforms[0] + + @property + def platform_variant(self) -> Optional[str]: + """ + Returns the platform variant for the CName parsed. + + :return: (str) Platform variant + :since: 1.0.0 + """ + + if self._platform_variant_cached is not None: + return self._platform_variant_cached + + # @TODO: Platform variant is set by GardenLinux features to the release file. If not read or cached it is currently invisible for this library. + return None + + @platform_variant.setter + def platform_variant(self, variant: str) -> None: + """ + Sets the the platform variant + + :param variant: Platform variant + + :since: 1.0.0 + """ + + self._platform_variant_cached = variant + + def __str__(self) -> str: + """ + Returns the Garden Linux Canonical Name. + + :return: (str) Returns the Garden Linux Canonical Name + :since: 1.0.0 + """ + + return self.cname + + def _copy_from_instance(self, c_name: Self) -> None: + """ + Copies values from a given Garden Linux Canonical Name instance. + + :param cname_object: Garden Linux Canonical Name instance + + :since: 1.0.0 + """ + + self._cname = c_name.cname + self._feature_set_cached = c_name.feature_set + self._feature_elements_cached = c_name.feature_set_element.split(",") + self._feature_flags_cached = c_name.feature_set_flag.split(",") + self._feature_platforms_cached = c_name.feature_set_platform.split(",") + self._platform_cached = c_name.platform + self._platform_variant_cached = c_name.platform_variant diff --git a/src/gardenlinux/features/cname.py b/src/gardenlinux/features/cname.py deleted file mode 100644 index 98c9cc29..00000000 --- a/src/gardenlinux/features/cname.py +++ /dev/null @@ -1,613 +0,0 @@ -# -*- coding: utf-8 -*- - -""" -Canonical name (cname) -""" - -import re -from configparser import UNNAMED_SECTION, ConfigParser -from os import PathLike, environ -from pathlib import Path -from typing import Any, Dict, List, Optional, Self - -from ..constants import ( - ARCHS, - GL_BUG_REPORT_URL, - GL_DISTRIBUTION_NAME, - GL_HOME_URL, - GL_PLATFORM_FRANKENSTEIN, - GL_RELEASE_ID, - GL_SUPPORT_URL, -) -from .parser import Parser - - -class CName(object): - """ - Class to represent a canonical name (cname). - - :author: Garden Linux Maintainers - :copyright: Copyright 2024 SAP SE - :package: gardenlinux - :subpackage: features - :since: 0.7.0 - :license: https://www.apache.org/licenses/LICENSE-2.0 - Apache License, Version 2.0 - """ - - def __init__( - self, - cname: str, - arch: Optional[str] = None, - commit_hash: Optional[str] = None, - version: Optional[str] = None, - ): - """ - Constructor __init__(CName) - - :param cname: Canonical name to represent - :param arch: Architecture if not part of cname - :param commit_hash: Commit ID or hash if not part of cname - :param version: Version if not part of cname - - :since: 0.7.0 - """ - - self._arch = None - self._commit_hash = None - self._commit_id = None - self._feature_elements_cached: Optional[List[str]] = None - self._feature_flags_cached: Optional[List[str]] = None - self._feature_platforms_cached: Optional[List[str]] = None - self._feature_set_cached: Optional[str] = None - self._features_cached: Optional[Dict[str, Any]] = None - self._platform_cached: Optional[str] = None - self._platform_variant_cached: Optional[str] = None - self._flavor = "" - self._version = None - - self._flag_frankenstein = bool(environ.get("GL_ALLOW_FRANKENSTEIN", False)) - - self._flag_multiple_platforms = bool( - environ.get("GL_ALLOW_MULTIPLE_PLATFORMS", False) - ) - - if self._flag_frankenstein: - self._flag_multiple_platforms = True - - commit_id_or_hash = None - - if version is not None: - # Support version values formatted as - - if commit_hash is None: - re_match = re.match("([a-z0-9.]+)(-([a-z0-9]+))?$", version) - assert re_match, f"Not a valid version {version}" - - commit_id_or_hash = re_match[3] - version = re_match[1] - else: - commit_id_or_hash = commit_hash - - re_object = re.compile( - "([a-zA-Z0-9]+([\\_\\-][a-zA-Z0-9]+)*?)(-([a-z0-9]+)(-([a-z0-9.]+)-([a-z0-9]+))*)?$" - ) - - re_match = re_object.match(cname) - - # Workaround Garden Linux canonical names without mandatory final commit hash - if ( - not re_match - and commit_id_or_hash - and re.match( - "([a-zA-Z0-9]+([\\_\\-][a-zA-Z0-9]+)*?)(-([a-z0-9]+)(-([a-z0-9.]+))*)?$", - cname, - ) - ): - re_match = re_object.match(f"{cname}-{commit_id_or_hash}") - - assert re_match, f"Not a valid Garden Linux canonical name {cname}" - - if re_match.lastindex == 1: - self._flavor = re_match[1] - else: - if commit_id_or_hash is None: - commit_id_or_hash = re_match[7] - elif re_match.group(7) is not None: - assert commit_id_or_hash.startswith(re_match[7]), ( - f"Mismatch between Garden Linux canonical name '{cname}' and given commit ID '{commit_id_or_hash}' detected" - ) - - self._flavor = re_match[1] - self._version = re_match[6] - - if re_match[4] in ARCHS: - self._arch = re_match[4] - else: - self._flavor += re_match[3] - - if self._arch is None and arch is not None: - self._arch = arch - - if version is not None: - if self._version is None: - self._version = version - else: - assert version == self._version, ( - f"Mismatch between Garden Linux canonical name '{cname}' and given version '{version}' detected" - ) - - if commit_id_or_hash is not None: - self._commit_id = commit_id_or_hash[:8] - - if len(commit_id_or_hash) == 40 or commit_id_or_hash == "local": # sha1 hex - self._commit_hash = commit_id_or_hash - - @property - def arch(self) -> Optional[str]: - """ - Returns the architecture for the cname parsed. - - :return: (str) CName architecture - :since: 0.7.0 - """ - - return self._arch - - @property - def cname(self) -> str: - """ - Returns the cname parsed. - - :return: (str) CName - :since: 0.7.0 - """ - - cname = self._flavor - - if self._arch is not None: - cname += f"-{self._arch}" - - if self._commit_id is not None and self._version is not None: - cname += f"-{self.version_and_commit_id}" - - return cname - - @property - def commit_hash(self) -> Optional[str]: - """ - Returns the commit hash if part of the cname parsed. - - :return: (str) Commit hash - :since: 1.0.0 - """ - - return self._commit_hash - - @commit_hash.setter - def commit_hash(self, commit_hash: str) -> None: - """ - Sets the commit hash - - :param commit_hash: Commit hash - - :since: 1.0.0 - """ - - if self._commit_id is not None and not commit_hash.startswith(self._commit_id): - raise RuntimeError("Commit hash given differs from commit ID already set") - - self._commit_id = commit_hash[:8] - self._commit_hash = commit_hash - - @property - def commit_id(self) -> Optional[str]: - """ - Returns the commit ID if part of the cname parsed. - - :return: (str) Commit ID - :since: 0.7.0 - """ - - return self._commit_id - - @property - def flavor(self) -> str: - """ - Returns the flavor for the cname parsed. - - :return: (str) Flavor - :since: 0.7.0 - """ - - return self._flavor - - @property - def features(self) -> Dict[str, Any]: - """ - Returns the features for the cname parsed. - - :return: (dict) Features of the cname - :since: 0.10.14 - """ - - if self._features_cached is None: - self._features_cached = Parser().filter_as_dict(self.flavor) - - return self._features_cached - - @property - def feature_set(self) -> str: - """ - Returns the feature set for the cname parsed. - - :return: (str) Feature set of the cname - :since: 0.7.0 - """ - - if self._feature_set_cached is not None: - return self._feature_set_cached - - return Parser().filter_as_string(self.flavor) - - @property - def feature_set_element(self) -> str: - """ - Returns the feature set of type "element" for the cname parsed. - - :return: (str) Feature set elements - :since: 1.0.0 - """ - - if self._feature_elements_cached is not None: - return ",".join(self._feature_elements_cached) - - return ",".join(self.features["element"]) - - @property - def feature_set_flag(self) -> str: - """ - Returns the feature set of type "flag" for the cname parsed. - - :return: (str) Feature set flags - :since: 1.0.0 - """ - - if self._feature_flags_cached is not None: - return ",".join(self._feature_flags_cached) - - return ",".join(self.features["flag"]) - - @property - def feature_set_platform(self) -> str: - """ - Returns the feature set of type "platform" for the cname parsed. - - :return: (str) Feature set platform - :since: 1.0.0 - """ - - if self._feature_platforms_cached is None: - platforms = self.features["platform"] - else: - platforms = self._feature_platforms_cached - - if self._flag_multiple_platforms: - return ",".join(platforms) - - assert len(platforms) < 2 - "Only one platform is supported" - return platforms[0] # type: ignore[no-any-return] - - @property - def feature_set_list(self) -> List[str]: - """ - Returns the feature set for the cname parsed. - - :return: (list) Feature set list of the cname - :since: 0.10.12 - """ - - if self._feature_set_cached is not None: - return self._feature_set_cached.split(",") - - return Parser().filter_as_list(self.flavor) - - @property - def platform(self) -> str: - """ - Returns the platform for the cname parsed. - - :return: (str) Platform - :since: 0.7.0 - """ - - if self._platform_cached is not None: - platforms = [self._platform_cached] - elif self._feature_platforms_cached is not None: - platforms = self._feature_platforms_cached - else: - platforms = self.features["platform"] - - if self._flag_frankenstein and len(platforms) > 1: - return GL_PLATFORM_FRANKENSTEIN - - if not self._flag_multiple_platforms: - assert len(platforms) < 2 - "Only one platform is supported" - - return platforms[0] - - @property - def platform_variant(self) -> Optional[str]: - """ - Returns the platform variant for the cname parsed. - - :return: (str) Platform variant - :since: 1.0.0 - """ - - if self._platform_variant_cached is not None: - return self._platform_variant_cached - - # @TODO: Platform variant is set by GardenLinux features to the release file. If not read or cached it is currently invisible for this library. - return None - - @platform_variant.setter - def platform_variant(self, variant: str) -> None: - """ - Sets the the platform variant - - :param variant: Platform variant - - :since: 1.0.0 - """ - - self._platform_variant_cached = variant - - @property - def release_metadata_string(self) -> str: - """ - Returns the release metadata describing the given CName instance. - - :return: (str) Release metadata describing the given CName instance - :since: 1.0.0 - """ - - commit_hash = self.commit_hash - commit_id = self.commit_id - platform_variant = self.platform_variant - version = self.version - - if commit_id is None: - commit_id = "" - - if commit_hash is None: - commit_hash = commit_id - - if platform_variant is None: - platform_variant = "" - - if version is None: - pretty_name = f"{GL_DISTRIBUTION_NAME} unsupported version" - version = "" - else: - pretty_name = f"{GL_DISTRIBUTION_NAME} {version}" - - metadata = f""" -ID={GL_RELEASE_ID} -ID_LIKE=debian -NAME="{GL_DISTRIBUTION_NAME}" -PRETTY_NAME="{pretty_name}" -IMAGE_VERSION={version} -VARIANT_ID="{self.flavor}-{self.arch}" -HOME_URL="{GL_HOME_URL}" -SUPPORT_URL="{GL_SUPPORT_URL}" -BUG_REPORT_URL="{GL_BUG_REPORT_URL}" -GARDENLINUX_CNAME="{self.cname}" -GARDENLINUX_FEATURES="{self.feature_set}" -GARDENLINUX_FEATURES_PLATFORMS="{self.feature_set_platform}" -GARDENLINUX_FEATURES_ELEMENTS="{self.feature_set_element}" -GARDENLINUX_FEATURES_FLAGS="{self.feature_set_flag}" -GARDENLINUX_PLATFORM="{self.platform}" -GARDENLINUX_PLATFORM_VARIANT="{platform_variant}" -GARDENLINUX_VERSION="{version}" -GARDENLINUX_COMMIT_ID="{commit_id}" -GARDENLINUX_COMMIT_ID_LONG="{commit_hash}" - """.strip() - - return metadata - - @property - def version(self) -> Optional[str]: - """ - Returns the version if part of the cname parsed. - - :return: (str) Version - :since: 0.7.0 - """ - - return self._version - - @property - def version_and_commit_id(self) -> Optional[str]: - """ - Returns the version and commit ID if part of the cname parsed. - - :return: (str) Version and commit ID - :since: 0.7.0 - """ - - if self._version is None or self._commit_id is None: - return None - - return f"{self._version}-{self._commit_id}" - - @property - def version_epoch(self) -> Optional[int]: - """ - Returns the GardenLinux version epoch of the cname parsed. - - :return: (str) GardenLinux version epoch - :since: 1.0.0 - """ - - epoch = None - - if self._version is not None and "." in self._version: - epoch = int(self._version.split(".", 1)[0]) - - return epoch - - def _copy_from_cname_object(self, cname_object: Self) -> None: - """ - Copies values from a given Garden Linux canonical name instance. - - :param cname_object: Garden Linux canonical name instance - - :since: 1.0.0 - """ - - self._arch = cname_object.arch - self._commit_hash = cname_object.commit_hash - self._commit_id = cname_object.commit_id - self._feature_set_cached = cname_object.feature_set - self._feature_elements_cached = cname_object.feature_set_element.split(",") - self._feature_flags_cached = cname_object.feature_set_flag.split(",") - self._feature_platforms_cached = cname_object.feature_set_platform.split(",") - self._platform_cached = cname_object.platform - self._platform_variant_cached = cname_object.platform_variant - self._version = cname_object.version - - def load_from_release_file(self, release_file: PathLike[str] | str) -> None: - """ - Loads and parses a release metadata file. - - :param release_file: Release metadata file - - :since: 1.0.0 - """ - - cname_object = CName.new_from_release_file(release_file) - - if ( - cname_object.flavor != self.flavor - or ( - self._commit_id is not None - and self._commit_id != cname_object.commit_id - ) - or (self._version is not None and self._version != cname_object.version) - or ( - not self._flag_frankenstein - and cname_object.platform not in cname_object.feature_set_platform - ) - ): - raise RuntimeError( - f"Release metadata file given is invalid: {release_file} failed consistency check - {self.cname} != {cname_object.cname}" - ) - - self._copy_from_cname_object(cname_object) - - def save_to_release_file( - self, release_file: PathLike[str] | str, overwrite: Optional[bool] = False - ) -> None: - """ - Saves the release metadata file. - - :param release_file: Release metadata file - - :since: 1.0.0 - """ - - if not isinstance(release_file, PathLike): - release_file = Path(release_file) - - if not overwrite and release_file.exists(): # type: ignore[attr-defined] - raise RuntimeError( - f"Refused to overwrite existing release metadata file: {release_file}" - ) - - with release_file.open("w") as fp: # type: ignore[attr-defined] - fp.write(self.release_metadata_string) - - @staticmethod - def new_from_release_file(release_file: PathLike[str] | str) -> "CName": - """ - Loads and parses a release metadata file. - - :param release_file: Release metadata file - - :since: 0.10.10 - """ - - if not isinstance(release_file, PathLike): - release_file = Path(release_file) - - if not release_file.exists(): # type: ignore[attr-defined] - raise RuntimeError( - f"Release metadata file given is invalid: {release_file}" - ) - - release_config = ConfigParser(allow_unnamed_section=True) - release_config.read(release_file) - - for release_field in ( - "GARDENLINUX_CNAME", - "GARDENLINUX_COMMIT_ID_LONG", - "GARDENLINUX_FEATURES", - "GARDENLINUX_PLATFORM", - "GARDENLINUX_VERSION", - ): - if not release_config.has_option(UNNAMED_SECTION, release_field): - raise RuntimeError( - f"Release metadata file given is invalid: {release_file} misses {release_field}" - ) - - commit_hash = release_config.get( - UNNAMED_SECTION, "GARDENLINUX_COMMIT_ID_LONG" - ).strip("\"'") - - version = release_config.get(UNNAMED_SECTION, "GARDENLINUX_VERSION").strip( - "\"'" - ) - - cname_object = CName( - release_config.get(UNNAMED_SECTION, "GARDENLINUX_CNAME").strip("\"'"), - commit_hash=commit_hash, - version=version, - ) - - cname_object._feature_set_cached = release_config.get( - UNNAMED_SECTION, "GARDENLINUX_FEATURES" - ).strip("\"'") - - if release_config.has_option(UNNAMED_SECTION, "GARDENLINUX_FEATURES_ELEMENTS"): - cname_object._feature_elements_cached = ( - release_config.get(UNNAMED_SECTION, "GARDENLINUX_FEATURES_ELEMENTS") - .strip("\"'") - .split(",") - ) - - if release_config.has_option(UNNAMED_SECTION, "GARDENLINUX_FEATURES_FLAGS"): - cname_object._feature_flags_cached = ( - release_config.get(UNNAMED_SECTION, "GARDENLINUX_FEATURES_FLAGS") - .strip("\"'") - .split(",") - ) - - if release_config.has_option(UNNAMED_SECTION, "GARDENLINUX_FEATURES_PLATFORMS"): - cname_object._feature_platforms_cached = ( - release_config.get(UNNAMED_SECTION, "GARDENLINUX_FEATURES_PLATFORMS") - .strip("\"'") - .split(",") - ) - - cname_object._platform_cached = release_config.get( - UNNAMED_SECTION, "GARDENLINUX_PLATFORM" - ).strip("\"'") - - if release_config.has_option(UNNAMED_SECTION, "GARDENLINUX_PLATFORM_VARIANT"): - cname_object._platform_variant_cached = release_config.get( - UNNAMED_SECTION, "GARDENLINUX_PLATFORM_VARIANT" - ).strip("\"'") - - return cname_object diff --git a/src/gardenlinux/features/cname_main.py b/src/gardenlinux/features/cname_main.py deleted file mode 100644 index 5ce5998c..00000000 --- a/src/gardenlinux/features/cname_main.py +++ /dev/null @@ -1,131 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -""" -gl-cname main entrypoint -""" - -import argparse -import logging -import re -from os.path import basename, dirname - -from .__main__ import ( - get_minimal_feature_set, - get_version_and_commit_id_from_files, -) -from .cname import CName -from .parser import Parser - - -def get_parser() -> argparse.ArgumentParser: - """ - Get the argument parser for gl-cname. - Used for documentation generation. - - :return: ArgumentParser instance - :since: 1.0.0 - """ - - parser = argparse.ArgumentParser( - prog="gl-cname", - description="Generate a canonical name (cname) from feature sets.", - ) - - parser.add_argument( - "--arch", - dest="arch", - help="Target architecture (e.g., amd64, arm64). If not specified, will be determined from the cname or feature set.", - ) - - parser.add_argument( - "--commit", - dest="commit", - help="Git commit hash. If not specified, will be read from COMMIT file in the GardenLinux root directory.", - ) - - parser.add_argument( - "--feature-dir", - default="features", - help="Path to the features directory (default: 'features').", - ) - - parser.add_argument( - "--version", - dest="version", - help="Version string. If not specified, will be read from VERSION file in the GardenLinux root directory.", - ) - - parser.add_argument( - "cname", - help="Canonical name (cname) to process. Must be a valid GardenLinux canonical name format.", - ) - - return parser - - -def main() -> None: - """ - gl-cname main() - - :since: 0.7.0 - """ - - parser = get_parser() - args = parser.parse_args() - - re_match = re.match( - "([a-zA-Z0-9]+([\\_\\-][a-zA-Z0-9]+)*?)(-([a-z0-9]+)(-([a-z0-9.]+)-([a-z0-9]+))*)?$", - args.cname, - ) - - assert re_match, f"Not a valid Garden Linux canonical name {args.cname}" - - arch = args.arch - commit_id_or_hash = args.commit - gardenlinux_root = dirname(args.feature_dir) - version = args.version - - if gardenlinux_root == "": - gardenlinux_root = "." - - if not version: - try: - version, commit_id_or_hash = get_version_and_commit_id_from_files( - gardenlinux_root - ) - except RuntimeError as exc: - logging.warning( - "Failed to parse version information for GL root '{0}': {1}".format( - gardenlinux_root, exc - ) - ) - - cname = CName(args.cname, arch=arch, commit_hash=commit_id_or_hash, version=version) - - assert cname.arch, "Architecture could not be determined" - - feature_dir_name = basename(args.feature_dir) - - if gardenlinux_root == "": - gardenlinux_root = "." - - graph = Parser(gardenlinux_root, feature_dir_name).filter(cname.flavor) - - sorted_features = Parser.sort_graph_nodes(graph) - minimal_feature_set = get_minimal_feature_set(graph) - - sorted_minimal_features = Parser.subset(minimal_feature_set, sorted_features) - - generated_cname = Parser.get_flavor_from_feature_set(sorted_minimal_features) - - generated_cname += f"-{cname.arch}" - - if cname.version_and_commit_id is not None: - generated_cname += f"-{cname.version_and_commit_id}" - - print(generated_cname) - - -if __name__ == "__main__": - main() diff --git a/src/gardenlinux/features/flavor.py b/src/gardenlinux/features/flavor.py new file mode 100644 index 00000000..9c9f7ce7 --- /dev/null +++ b/src/gardenlinux/features/flavor.py @@ -0,0 +1,88 @@ +# -*- coding: utf-8 -*- + +""" +Garden Linux flavor +""" + +from typing import Self + +from .c_name import CName + + +class Flavor(CName): + """ + Class to represent a Garden Linux flavor. + + :author: Garden Linux Maintainers + :copyright: Copyright 2026 SAP SE + :package: gardenlinux + :subpackage: features + :since: 1.0.0 + :license: https://www.apache.org/licenses/LICENSE-2.0 + Apache License, Version 2.0 + """ + + def __init__( + self, + cname: str, + arch: str, + ): + """ + Constructor __init__(Flavor) + + :param cname: CName to represent + :param arch: Architecture if not part of cname + + :since: 1.0.0 + """ + + CName.__init__(self, cname) + self._arch = arch + + @property + def arch(self) -> str: + """ + Returns the architecture for the CName parsed. + + :return: (str) CName architecture + :since: 0.7.0 + """ + + return self._arch + + @property + def flavor(self) -> str: + """ + Returns the Garden Linux flavor parsed. + + :return: (str) Flavor + :since: 0.7.0 + """ + + flavor = CName.__str__(self) + flavor += f"-{self.arch}" + + return flavor + + def __str__(self) -> str: + """ + Returns the Garden Linux flavor. + + :return: (str) Flavor + :since: 1.0.0 + """ + + return self.flavor + + def _copy_from_instance(self, flavor: Self) -> None: + """ + Copies values from a given Garden Linux flavor instance. + + :param cname_object: Flavor instance + + :since: 1.0.0 + """ + + CName._copy_from_instance(self, flavor) + + self._arch = flavor.arch diff --git a/src/gardenlinux/features/metadata_main.py b/src/gardenlinux/features/metadata_main.py index 9bb2c1d7..99825b89 100644 --- a/src/gardenlinux/features/metadata_main.py +++ b/src/gardenlinux/features/metadata_main.py @@ -6,8 +6,9 @@ """ import argparse +from os import environ -from .cname import CName +from .artifact_base_name import ArtifactBaseName _ARGS_ACTION_ALLOWED = [ "output-release-metadata", @@ -15,21 +16,74 @@ ] -def main() -> None: +def get_parser() -> argparse.ArgumentParser: """ - gl-metadata main() + Get the argument parser for gl-metadata. + Used for documentation generation. - :since: 0.7.0 + :return: ArgumentParser instance + :since: 1.0.0 """ - parser = argparse.ArgumentParser() + parser = argparse.ArgumentParser( + prog="gl-metadata", + description="Handle GardenLinux metadata reading and writing.", + ) + + parser.add_argument( + "--arch", + dest="arch", + help="Target architecture (e.g., amd64, arm64). Overrides architecture from CName.", + ) + + parser.add_argument( + "--artifact-base-name", + dest="artifact_base_name", + help="Artifact base name to parse. Must be a valid Garden Linux Artifact Base Name.", + ) + + parser.add_argument( + "--cname", + dest="cname", + help="Canonical Name (CName) to parse.", + ) + + parser.add_argument( + "--commit", + dest="commit", + help="Git commit hash. If not specified, will be read from COMMIT file or release file.", + ) + + parser.add_argument( + "--flavor", + dest="flavor", + help="GardenLinux flavor name.", + ) + + parser.add_argument( + "--release-file", + dest="release_file", + help="Path to a release file containing features metadata.", + ) + + parser.add_argument( + "--overwrite-file", + type=bool, + dest="overwrite_file", + help="Accept overwriting existing files.", + ) - parser.add_argument("--arch", dest="arch") - parser.add_argument("--cname", required=True, dest="cname") - parser.add_argument("--commit-hash", dest="commit_hash") - parser.add_argument("--release-file", dest="release_file") - parser.add_argument("--overwrite-file", type=bool, dest="overwrite_file") - parser.add_argument("--version", dest="version") + parser.add_argument( + "--version", + dest="version", + help="Version string. If not specified, will be read from VERSION file or release file.", + ) + + parser.add_argument( + "--versioned-flavor", + dest="versioned_flavor", + help="GardenLinux versioned flavor name.", + ) parser.add_argument( "action", @@ -38,22 +92,48 @@ def main() -> None: default="output-release-metadata", ) + return parser + + +def main() -> None: + """ + gl-metadata main() + + :since: 0.7.0 + """ + + parser = get_parser() args = parser.parse_args() - cname = CName( - args.cname, arch=args.arch, commit_hash=args.commit_hash, version=args.version + commit_id_or_hash = args.commit + gardenlinux_root = environ.get("GL_ROOT_DIR") + version = args.version + + if not gardenlinux_root: + gardenlinux_root = "." + + if not version or not commit_id_or_hash: + version, commit_id_or_hash = ( + ArtifactBaseName.get_version_and_commit_id_from_files(gardenlinux_root) + ) + + abn_object = ArtifactBaseName.new_instance( + args.artifact_base_name, + cname=args.cname, + flavor=args.flavor, + versioned_flavor=args.versioned_flavor, + arch=args.arch, + version=args.version, + commit_id_or_hash=args.commit, ) - if args.commit_hash is not None: - cname.commit_hash = args.commit_hash - if args.action == "write": - cname.save_to_release_file(args.release_file, args.overwrite_file) + abn_object.save_to_release_file(args.release_file, args.overwrite_file) else: if args.release_file is not None: - cname.load_from_release_file(args.release_file) + abn_object.load_from_release_file(args.release_file) - print(cname.release_metadata_string) + print(abn_object.release_metadata_string) if __name__ == "__main__": diff --git a/src/gardenlinux/features/parser.py b/src/gardenlinux/features/parser.py index 497e66fb..8e239e1b 100644 --- a/src/gardenlinux/features/parser.py +++ b/src/gardenlinux/features/parser.py @@ -14,7 +14,7 @@ import networkx import yaml -from ..constants import BARE_FLAVOR_FEATURE_CONTENT, BARE_FLAVOR_LIBC_FEATURE_CONTENT +from ..constants import BARE_CNAME_FEATURE_CONTENT, BARE_CNAME_LIBC_FEATURE_CONTENT from ..logger import LoggerSetup @@ -132,7 +132,7 @@ def filter( :since: 0.7.0 """ - feature_set = Parser.get_flavor_as_feature_set(cname) + feature_set = Parser.get_cname_as_feature_set(cname) return self.filter_based_on_feature_set( feature_set, ignore_excludes, additional_filter_func @@ -278,9 +278,9 @@ def filter_based_on_feature_set( # @TODO: Remove "special" handling once "bare" is a first-class citizen of the feature graph if "bare" in feature_set: if not self.graph.has_node("bare"): - self.graph.add_node("bare", content=BARE_FLAVOR_FEATURE_CONTENT) + self.graph.add_node("bare", content=BARE_CNAME_FEATURE_CONTENT) if not self.graph.has_node("libc"): - self.graph.add_node("libc", content=BARE_FLAVOR_LIBC_FEATURE_CONTENT) + self.graph.add_node("libc", content=BARE_CNAME_LIBC_FEATURE_CONTENT) for feature in feature_set: for node in networkx.descendants( @@ -363,22 +363,36 @@ def _read_feature_yaml(self, feature_yaml_file: str) -> Dict[str, Any]: return {"name": name, "content": content} @staticmethod - def get_flavor_from_feature_set(sorted_features: List[str]) -> str: + def get_cname_from_feature_set(feature_set_list: List[str]) -> str: """ Get the base cname for the feature set given. - :param sorted_features: Sorted feature set + :param feature_set_list: Feature set list - :return: (str) Base cname - :since: 0.7.0 + :return: (str) Garden Linux canonical name + :since: 1.0.0 """ + if not feature_set_list: + raise ValueError("At least one platform must be given as a feature") + + platform = feature_set_list.pop(0) + features = [] + flags = [] + + for feature in feature_set_list: + if feature[:1] == "_": + flags.append(feature) + else: + features.append(feature) + return reduce( - lambda a, b: a + ("-" if not b.startswith("_") else "") + b, sorted_features + lambda a, b: a + ("-" if not b.startswith("_") else "") + b, + [platform] + sorted(features) + sorted(flags), ) @staticmethod - def get_flavor_as_feature_set(cname: str) -> List[str]: + def get_cname_as_feature_set(cname: str) -> List[str]: """ Returns the features of a given canonical name. @@ -478,6 +492,19 @@ def _get_graph_node_type(node: str) -> str: return node.get("content", {}).get("type") # type: ignore[attr-defined, no-any-return] + @staticmethod + def get_minimal_feature_set(graph: networkx.Graph) -> Set[str]: + """ + Returns the minimal set of features described by the given graph. + + :param graph: networkx.Graph + + :return: (set) Minimal set of features + :since: 1.0.0 + """ + + return set([node for (node, degree) in graph.in_degree() if degree == 0]) + @staticmethod def set_default_gardenlinux_root_dir(root_dir: str) -> None: """ diff --git a/src/gardenlinux/features/reproducibility/diff_parser.py b/src/gardenlinux/features/reproducibility/diff_parser.py index 319622d0..924fb3b1 100644 --- a/src/gardenlinux/features/reproducibility/diff_parser.py +++ b/src/gardenlinux/features/reproducibility/diff_parser.py @@ -59,9 +59,9 @@ def __init__( self.all_flavors: set[str] = set() self.reproducible_flavors: set[str] = set() self.passed_by_whitelist: set[str] = set() - self.expected_falvors: set[str] = set() + self.expected_flavors: set[str] = set() self.missing_flavors: set[str] = set() - self.unexpected_falvors: set[str] = set() + self.unexpected_flavors: set[str] = set() def sort_features(self, graph: nx.DiGraph) -> list[str]: """ @@ -97,17 +97,17 @@ def parse( diff_dir = Path(self._gardenlinux_root).joinpath(diff_dir) - self.expected_falvors = { - f"{variant['flavor']}-{variant['arch']}" + self.expected_flavors = { + f"{variant['cname']}-{variant['arch']}" for variant in (flavors_matrix["include"] + bare_flavors_matrix["include"]) } - for flavor in os.listdir(diff_dir): - if flavor.endswith(self._SUFFIX): - with open(diff_dir.joinpath(flavor), "r") as f: + for artifact in os.listdir(diff_dir): + if artifact.endswith(self._SUFFIX): + with open(diff_dir.joinpath(artifact), "r") as f: content = f.read() - flavor = flavor.rstrip(self._SUFFIX) + flavor = artifact.rstrip(self._SUFFIX) self.all_flavors.add(flavor) if content == "": self.reproducible_flavors.add(flavor) @@ -117,8 +117,8 @@ def parse( else: non_reproducible_flavors[flavor] = content.split("\n")[:-1] - self.missing_flavors = self.expected_falvors - self.all_flavors - self.unexpected_falvors = self.all_flavors - self.expected_falvors + self.missing_flavors = self.expected_flavors - self.all_flavors + self.unexpected_flavors = self.all_flavors - self.expected_flavors # Map files to flavors affected_flavors: Dict[str, set[str]] = {} # {file: {flavors...}} diff --git a/src/gardenlinux/features/reproducibility/markdown_formatter.py b/src/gardenlinux/features/reproducibility/markdown_formatter.py index 86e9f546..a0040288 100644 --- a/src/gardenlinux/features/reproducibility/markdown_formatter.py +++ b/src/gardenlinux/features/reproducibility/markdown_formatter.py @@ -190,19 +190,19 @@ def _header( 100 * ( len(self._diff_parser.reproducible_flavors) - / len(self._diff_parser.expected_falvors) + / len(self._diff_parser.expected_flavors) ), 1, ) emoji = ( "✅" - if len(self._diff_parser.expected_falvors) + if len(self._diff_parser.expected_flavors) == len(self._diff_parser.reproducible_flavors) else ("⚠️" if successrate >= SUCCESS_TRESHOLD else "❌") ) - total_count = len(self._diff_parser.expected_falvors) + total_count = len(self._diff_parser.expected_flavors) problem_count = ( "" @@ -226,18 +226,18 @@ def _header( + "" ) - if len(self._diff_parser.unexpected_falvors) > 0: + if len(self._diff_parser.unexpected_flavors) > 0: # This should never happen, but print a warning if it somehow does explanation += ( "\n\n
⁉️ These flavors were not expected to appear in the results, please check for errors in the workflow\
"
-                + "
".join(sorted(self._diff_parser.unexpected_falvors)) + + "
".join(sorted(self._diff_parser.unexpected_flavors)) + "
" ) explanation += ( "" - if len(self._diff_parser.expected_falvors) + if len(self._diff_parser.expected_flavors) <= len(self._diff_parser.reproducible_flavors) else "\n\n*The mentioned features are included in every affected flavor and not included in every unaffected flavor.*" ) @@ -270,7 +270,7 @@ def _table( if len(self._diff_parser.missing_flavors) > 0: row = "|❌ Workflow run did not produce any results|" - row += f"**{round(100 * (len(self._diff_parser.missing_flavors) / len(self._diff_parser.expected_falvors)), 1)}%** affected
" + row += f"**{round(100 * (len(self._diff_parser.missing_flavors) / len(self._diff_parser.expected_flavors)), 1)}%** affected
" row += self._dropdown(self._diff_parser.missing_flavors) row += "|No analysis available|\n" rows += row @@ -285,7 +285,7 @@ def sorting_function(files: frozenset[str]) -> tuple[int, str]: row = "|" row += self._dropdown(files) row += "|" - row += f"**{round(100 * (len(flavors) / len(self._diff_parser.expected_falvors)), 1)}%** affected
" + row += f"**{round(100 * (len(flavors) / len(self._diff_parser.expected_flavors)), 1)}%** affected
" row += self._dropdown(flavors) row += "|" if len(tree) == 0: @@ -300,7 +300,7 @@ def sorting_function(files: frozenset[str]) -> tuple[int, str]: row = "|" row += "✅ No problems found" row += "|" - row += f"**{round(100 * (len(self._diff_parser.reproducible_flavors) / len(self._diff_parser.expected_falvors)), 1)}%**
" + row += f"**{round(100 * (len(self._diff_parser.reproducible_flavors) / len(self._diff_parser.expected_flavors)), 1)}%**
" row += self._dropdown(self._diff_parser.reproducible_flavors) row += "|" row += "-" @@ -308,7 +308,7 @@ def sorting_function(files: frozenset[str]) -> tuple[int, str]: rows += row if len(self._diff_parser.reproducible_flavors) < len( - self._diff_parser.expected_falvors + self._diff_parser.expected_flavors ): rows += "\n*To add affected files to the whitelist, edit `src/gardenlinux/features/reproducibility/nightly_whitelist.json` in python-gardenlinux-lib*\n" diff --git a/src/gardenlinux/features/versioned_flavor.py b/src/gardenlinux/features/versioned_flavor.py new file mode 100644 index 00000000..e026a8ea --- /dev/null +++ b/src/gardenlinux/features/versioned_flavor.py @@ -0,0 +1,97 @@ +# -*- coding: utf-8 -*- + +""" +Garden Linux versioned flavor +""" + +from typing import Optional, Self + +from .flavor import Flavor + + +class VersionedFlavor(Flavor): + """ + Class to represent a Garden Linux versioned flavor. + + :author: Garden Linux Maintainers + :copyright: Copyright 2026 SAP SE + :package: gardenlinux + :subpackage: features + :since: 1.0.0 + :license: https://www.apache.org/licenses/LICENSE-2.0 + Apache License, Version 2.0 + """ + + def __init__( + self, + flavor: str, + arch: str, + version: str, + ): + """ + Constructor __init__(VersionedFlavor) + + :param cname: CName to represent + :param arch: Architecture + :param commit_hash: Commit ID or hash + :param version: Version + + :since: 1.0.0 + """ + + Flavor.__init__(self, flavor, arch) + + self._version = version + + @property + def version(self) -> str: + """ + Returns the version. + + :return: (str) Version + :since: 0.7.0 + """ + + return self._version + + @property + def version_epoch(self) -> Optional[int]: + """ + Returns the Garden Linux version epoch. + + :return: (str) Garden Linux version epoch + :since: 1.0.0 + """ + + epoch = None + + if self._version is not None and "." in self._version: + epoch = int(self._version.split(".", 1)[0]) + + return epoch + + def __str__(self) -> str: + """ + Returns the Garden Linux versioned flavor. + + :return: (str) Returns the Garden Linux versioned flavor + :since: 1.0.0 + """ + + flavor = Flavor.__str__(self) + flavor += f"-{self.version}" + + return flavor + + def _copy_from_instance(self, versioned_flavor: Self) -> None: + """ + Copies values from a given Garden Linux versioned flavor instance. + + :param cname_object: Garden Linux versioned flavor instance + + :since: 1.0.0 + """ + + Flavor._copy_from_instance(self, versioned_flavor) + + self._version = versioned_flavor.version diff --git a/src/gardenlinux/flavors/parser.py b/src/gardenlinux/flavors/parser.py index 08d6e3e6..48224b93 100644 --- a/src/gardenlinux/flavors/parser.py +++ b/src/gardenlinux/flavors/parser.py @@ -12,6 +12,7 @@ from jsonschema import validate as jsonschema_validate from ..constants import GL_FLAVORS_SCHEMA +from ..features import Parser as FeaturesParser from ..logger import LoggerSetup @@ -111,13 +112,10 @@ def filter( continue # Process features - formatted_features = f"-{'-'.join(features)}" if features else "" + cname = FeaturesParser.get_cname_from_feature_set([name] + features) # Construct the combination - combination = f"{name}-{formatted_features}-{arch}" - - # Format the combination to clean up "--" and "-_" - combination = combination.replace("--", "-").replace("-_", "_") + combination = f"{cname}-{arch}" # Exclude combinations explicitly if Parser.should_exclude(combination, [], wildcard_excludes): diff --git a/src/gardenlinux/github/release/__main__.py b/src/gardenlinux/github/release/__main__.py index b18c5440..a1b97dff 100644 --- a/src/gardenlinux/github/release/__main__.py +++ b/src/gardenlinux/github/release/__main__.py @@ -1,5 +1,6 @@ import argparse import logging +from pathlib import Path from gardenlinux.constants import GARDENLINUX_GITHUB_RELEASE_BUCKET_NAME from gardenlinux.logger import LoggerSetup @@ -127,20 +128,21 @@ def get_parser() -> argparse.ArgumentParser: ) upload_parser.add_argument( - "--release_id", + "--release-id", required=True, help="GitHub release ID to upload the file to (required).", ) upload_parser.add_argument( - "--file_path", + "--file", + type=Path, required=True, help="Path to the file to upload (required).", ) upload_parser.add_argument( "--dry-run", - action="store_true", + action=argparse.BooleanOptionalAction, default=False, help="Perform a dry run without actually uploading the file.", ) @@ -190,11 +192,9 @@ def main() -> None: if args.dry_run: print("Dry Run ...") - print( - f"The file {args.file_path} would be uploaded for release: {release.name}" - ) + print(f"The file {args.file} would be uploaded for release: {release.name}") else: - release.upload_asset(args.file_path, args.overwrite_same_name) + release.upload_asset(args.file, args.overwrite_same_name) else: parser.print_help() diff --git a/src/gardenlinux/github/release/release_images_metadata.py b/src/gardenlinux/github/release/release_images_metadata.py index e1446374..569a04dd 100644 --- a/src/gardenlinux/github/release/release_images_metadata.py +++ b/src/gardenlinux/github/release/release_images_metadata.py @@ -18,7 +18,7 @@ from ...apt import DebsrcFile from ...constants import GL_DEB_REPO_BASE_URL, GLVD_BASE_URL, REQUESTS_TIMEOUTS -from ...features import CName +from ...features import ArtifactBaseName from ...flavors import Parser from ...git import Repository from ...logger import LoggerSetup @@ -153,31 +153,28 @@ def grouped_flavors_metadata( f"{flavor=} version={self._version} commitish={self._commitish}" ) - cname = CName( - flavor[1], - arch=flavor[0], - commit_hash=self._commitish, - version=self._version, + abn_object = ArtifactBaseName( + f"{flavor[1]}-{self._version}-{self._commitish}" ) try: release_object = list( s3_artifacts.bucket.objects.filter( - Prefix=f"meta/singles/{cname.cname}" + Prefix=f"meta/singles/{abn_object}" ) )[0] s3_artifacts.bucket.download_file( release_object.key, - str(Path(tmpdir, f"{cname.cname}.s3_metadata.yaml")), + str(Path(tmpdir, f"{abn_object}.s3_metadata.yaml")), ) except IndexError: self._logger.warning( - f"No artifacts found for flavor {cname.cname}, skipping..." + f"No artifacts found for flavor {abn_object}, skipping..." ) continue - with Path(tmpdir, f"{cname.cname}.s3_metadata.yaml").open("r") as file: + with Path(tmpdir, f"{abn_object}.s3_metadata.yaml").open("r") as file: s3_data = ReleaseImagesMetadata.parse_s3_metadata( yaml.load(file, Loader=yaml.SafeLoader) ) diff --git a/src/gardenlinux/oci/__init__.py b/src/gardenlinux/oci/__init__.py index 35ab1a4e..99883854 100644 --- a/src/gardenlinux/oci/__init__.py +++ b/src/gardenlinux/oci/__init__.py @@ -4,7 +4,6 @@ OCI module """ -from .container import Container from .image import Image from .image_manifest import ImageManifest from .index import Index @@ -12,9 +11,9 @@ from .manifest import Manifest from .podman import Podman from .podman_context import PodmanContext +from .repository import Repository __all__ = [ - "Container", "ImageManifest", "Image", "Index", @@ -22,4 +21,5 @@ "Manifest", "Podman", "PodmanContext", + "Repository", ] diff --git a/src/gardenlinux/oci/__main__.py b/src/gardenlinux/oci/__main__.py index f0edf08d..72290fb0 100755 --- a/src/gardenlinux/oci/__main__.py +++ b/src/gardenlinux/oci/__main__.py @@ -4,636 +4,601 @@ gl-oci main entrypoint """ +import argparse import json -from typing import List +from pathlib import Path +from typing import Optional -import click - -from .container import Container from .image_manifest import ImageManifest from .podman import Podman from .podman_context import PodmanContext +from .repository import Repository -@click.group() -def cli() -> None: +def _add_additional_tag_list_to_parser(parser: argparse.ArgumentParser) -> None: """ - gl-oci provides functionality to handle OCI containers. It can pull and push - images from remote repositories as well as handle GardenLinux artifacts, OCI - image indices and manifests. + Add `--additional-tag` to the given argument parser. - :since: 0.7.0 + :param parser: ArgumentParser instance + + :since: 1.0.0 """ - pass - - -@cli.command() -@click.option( - "--index", - required=True, - help="OCI image index", -) -@click.option( - "--index-tag", - required=True, - help="OCI image index tag", -) -@click.option( - "--container", - required=True, - help="Container Name", -) -@click.option( - "--tag", - required=True, - help="OCI tag of image", -) -@click.option( - "--insecure", - type=bool, - default=False, - help="Use HTTP to communicate with the registry", -) -@click.option( - "--additional_tag", - required=False, - multiple=True, - help="Additional tag to push the index with", -) -def add_container_to_index( - index: str, - index_tag: str, - container: str, - tag: str, - insecure: bool, - additional_tag: List[str], -) -> None: + parser.add_argument( + "--additional-tag", + action="append", + default=[], + dest="additional_tag", + help="Additional tag to push the index with", + ) + + +def _add_arch_to_parser(parser: argparse.ArgumentParser) -> None: """ - Adds an image container to an OCI image index. + Add `--arch` to the given argument parser. + + :param parser: ArgumentParser instance :since: 1.0.0 """ - manifest_container = Container(f"{container}:{tag}", insecure=insecure) - - manifest = manifest_container.read_manifest() - - index_resource = Container(f"{index}:{index_tag}", insecure=insecure) - - image_index = index_resource.read_or_generate_index() - image_index.append_manifest(manifest) - - index_resource.push_index(image_index) - index_resource.push_index_for_tags(image_index, additional_tag) - - -@cli.command() -@click.option( - "--container", - required=True, - help="Container Name", -) -@click.option( - "--tag", - required=True, - help="OCI tag of image", -) -@click.option( - "--dir", - "directory", - required=True, - type=click.Path(), - help="Path to the build Containerfile", -) -@click.option( - "--platform", - required=False, - help="OCI platform as os/arch/variant", -) -@click.option( - "--additional_tag", - required=False, - multiple=True, - help="Additional tag to push the manifest with", -) -@click.option( - "--build_arg", - required=False, - default=[], - multiple=True, - help="Additional build args for Containerfile", -) -@click.option( - "--oci_archive", - required=False, - help="Write build result to the OCI archive path and file name", -) -def build_container( - container: str, - tag: str, - directory: str, - platform: str, - additional_tag: List[str], - build_arg: List[str], - oci_archive: str, -) -> None: + parser.add_argument( + "--arch", + required=False, + dest="arch", + help="Target Image CPU Architecture", + ) + + +def _add_build_arg_to_parser(parser: argparse.ArgumentParser) -> None: """ - Build an OCI container based on the defined `Containerfile`. + Add `--build-arg` to the given argument parser. + + :param parser: ArgumentParser instance :since: 1.0.0 """ - podman = Podman() + parser.add_argument( + "--build-arg", + action="append", + default=[], + dest="build_arg", + help="Additional build args for Containerfile", + ) - with PodmanContext() as podman_context: - if oci_archive is None: - image_id = podman.build( - directory, - podman=podman_context, - platform=platform, - oci_tag=f"{container}:{tag}", - build_args=Podman.parse_build_args_list(build_arg), - ) - else: - build_result_data = podman.build_and_save_oci_archive( - directory, - oci_archive, - podman=podman_context, - platform=platform, - oci_tag=f"{container}:{tag}", - build_args=Podman.parse_build_args_list(build_arg), - ) - _, image_id = build_result_data.popitem() +def _add_cname_to_parser(parser: argparse.ArgumentParser) -> None: + """ + Add `--cname` to the given argument parser. - if additional_tag is not None: - podman.tag_list( - image_id, Podman.get_container_tag_list(container, additional_tag) - ) + :param parser: ArgumentParser instance + + :since: 1.0.0 + """ - print(image_id) + parser.add_argument( + "--cname", + required=True, + dest="cname", + help="Canonical Name of Image", + ) -@cli.command() -@click.option( - "--oci_archive", - required=False, - help="Write build result to the OCI archive path and file name", -) -@click.option( - "--additional_tag", - required=False, - multiple=True, - help="Additional tag to push the manifest with", -) -def load_container(oci_archive: str, additional_tag: List[str]) -> None: +def _add_commit_to_parser(parser: argparse.ArgumentParser) -> None: """ - Load an OCI archive. + Add `--commit` to the given argument parser. + + :param parser: ArgumentParser instance :since: 1.0.0 """ - podman = Podman() + parser.add_argument( + "--commit", + required=False, + dest="commit", + help="Commit of image", + ) + + +def _add_cosign_file_to_parser(parser: argparse.ArgumentParser) -> None: + """ + Add `--cosign-file` to the given argument parser. + + :param parser: ArgumentParser instance + + :since: 1.0.0 + """ + + parser.add_argument( + "--cosign-file", + type=Path, + required=False, + dest="cosign_file", + help="A file where the pushed manifests digests is written to. The content can be used by an external tool (e.g. cosign) to sign the manifests contents", + ) + + +def _add_dir_to_parser( + parser: argparse.ArgumentParser, help_text: str, default_value: Optional[str] = None +) -> None: + """ + Add `--dir` to the given argument parser. - with PodmanContext() as podman_context: - image_id = podman.load_oci_archive(oci_archive, podman=podman_context) + :param parser: ArgumentParser instance - if additional_tag is not None: - podman.tag_list(image_id, additional_tag, podman=podman_context) + :since: 1.0.0 + """ - print(image_id) + parser.add_argument( + "--dir", + type=Path, + required=(default_value is None), + default=default_value, + dest="directory", + help=help_text, + ) -@cli.command() -@click.option( - "--dir", - "directory", - required=True, - type=click.Path(), - help="path to the build artifacts", -) -def load_containers_from_directory(directory: str) -> None: +def _add_manifest_file_to_parser(parser: argparse.ArgumentParser) -> None: """ - Load multiple OCI archives. + Add `--manifest-file` to the given argument parser. + + :param parser: ArgumentParser instance :since: 1.0.0 """ - result = Podman().load_oci_archives_from_directory(directory) - print(json.dumps(result)) - - -@cli.command() -@click.option( - "--index", - required=True, - help="OCI image index", -) -@click.option( - "--index-tag", - required=True, - help="OCI image index tag", -) -@click.option( - "--insecure", - type=bool, - default=False, - help="Use HTTP to communicate with the registry", -) -@click.option( - "--additional_tag", - required=False, - multiple=True, - help="Additional tag to push the index with", -) -def new_index( - index: str, index_tag: str, insecure: bool, additional_tag: List[str] + parser.add_argument( + "--manifest-file", + type=Path, + default="manifests/manifest.json", + dest="manifest_file", + help="A file where the index entry for the pushed manifest is written to.", + ) + + +def _add_oci_archive_to_parser( + parser: argparse.ArgumentParser, required: bool = True ) -> None: """ - Create a new OCI image index. + Add `--oci-archive` to the given argument parser. + + :param parser: ArgumentParser instance :since: 1.0.0 """ - index_resource = Container(f"{index}:{index_tag}", insecure=insecure) - - image_index = index_resource.generate_index() - index_resource.push_index(image_index) - index_resource.push_index_for_tags(image_index, additional_tag) - - -@cli.command() -@click.option( - "--container", - required=True, - help="Container Name", -) -@click.option( - "--tag", - required=False, - help="OCI tag of image", -) -@click.option( - "--platform", - required=False, - help="OCI platform as os/arch/variant", -) -@click.option( - "--insecure", - type=bool, - default=False, - help="Use HTTP to communicate with the registry", -) -def pull_container(container: str, tag: str, platform: str, insecure: bool) -> None: - """ - Pull an OCI image container from a remote OCI registry. + parser.add_argument( + "--oci-archive", + type=Path, + required=required, + dest="oci_archive", + help="Write build result to the OCI archive path and file name", + ) + + +def _add_oci_destination_to_parser(parser: argparse.ArgumentParser) -> None: + """ + Add `--destination` to the given argument parser. + + :param parser: ArgumentParser instance :since: 1.0.0 """ - image_id = Podman(insecure=insecure).pull(container, oci_tag=tag, platform=platform) - print(image_id) - - -@cli.command() -@click.option( - "--container", - required=True, - help="Container Name", -) -@click.option( - "--tag", - required=False, - help="OCI tag of image", -) -@click.option( - "--destination", - required=False, - help="OCI container destination", -) -@click.option( - "--insecure", - type=bool, - default=False, - help="Use HTTP to communicate with the registry", -) -def push_container(container: str, tag: str, destination: str, insecure: bool) -> None: - """ - Push an OCI image container to a remote OCI registry. + parser.add_argument( + "--destination", + required=False, + dest="destination", + help="OCI repository destination", + ) + + +def _add_oci_index_args_to_parser(parser: argparse.ArgumentParser) -> None: + """ + Add `--index and --index-tag` to the given argument parser. + + :param parser: ArgumentParser instance :since: 1.0.0 """ - Podman(insecure=insecure).push(container, oci_tag=tag, destination=destination) - - -@cli.command() -@click.option( - "--index", - required=True, - help="OCI image index", -) -@click.option( - "--index-tag", - required=True, - help="OCI image index tag", -) -@click.option( - "--manifest_folder", - default="manifests", - help="A folder where the index entries are read from.", -) -@click.option( - "--insecure", - default=False, - help="Use HTTP to communicate with the registry", -) -@click.option( - "--additional_tag", - required=False, - multiple=True, - help="Additional tag to push the index with", -) -def push_index_from_directory( - index: str, - index_tag: str, - manifest_folder: str, - insecure: bool, - additional_tag: List[str], -) -> None: + parser.add_argument( + "--index", + required=True, + dest="index", + help="OCI image index", + ) + + parser.add_argument( + "--index-tag", + required=True, + dest="index_tag", + help="OCI image index tag", + ) + + +def _add_oci_insecure_to_parser(parser: argparse.ArgumentParser) -> None: """ - Pushes manifests stored in a directory to a given OCI image index. - - :since: 0.10.9 - """ - - index_resource = Container(f"{index}:{index_tag}", insecure=insecure) - index_resource.push_index_from_directory(manifest_folder, additional_tag) - - -@cli.command() -@click.option( - "--index", - required=True, - help="OCI image index", -) -@click.option( - "--index-tag", - required=True, - help="OCI image index tag", -) -@click.option( - "--insecure", - default=False, - help="Use HTTP to communicate with the registry", -) -@click.option( - "--tag", - required=True, - multiple=True, - help="Tag to push the OCI image index with", -) -def push_index_tags(index: str, index_tag: str, insecure: bool, tag: List[str]) -> None: - """ - Push OCI image index tags to a registry. - - :since: 0.10.9 - """ - - index_resource = Container(f"{index}:{index_tag}", insecure=insecure) - - image_index = index_resource.read_or_generate_index() - index_resource.push_index_for_tags(image_index, tag) - - -@cli.command() -@click.option( - "--container", - required=True, - help="Container Name", -) -@click.option("--cname", required=True, help="Canonical Name of Image") -@click.option( - "--arch", - required=False, - default=None, - help="Target Image CPU Architecture", -) -@click.option( - "--version", - required=False, - default=None, - help="Version of image", -) -@click.option( - "--commit", - required=False, - default=None, - help="Commit of image", -) -@click.option( - "--dir", - "directory", - required=True, - type=click.Path(), - help="path to the build artifacts", -) -@click.option( - "--cosign_file", - required=False, - help="A file where the pushed manifests digests is written to. The content can be used by an external tool (e.g. cosign) to sign the manifests contents", -) -@click.option( - "--manifest_file", - type=click.Path(), - default="manifests/manifest.json", - help="A file where the index entry for the pushed manifest is written to.", -) -@click.option( - "--insecure", - type=bool, - default=False, - help="Use HTTP to communicate with the registry", -) -@click.option( - "--additional_tag", - required=False, - multiple=True, - help="Additional tag to push the manifest with", -) -def push_manifest( - container: str, - cname: str, - arch: str, - version: str, - commit: str, - directory: str, - cosign_file: str, - manifest_file: str, - insecure: bool, - additional_tag: List[str], + Add `--insecure` to the given argument parser. + + :param parser: ArgumentParser instance + + :since: 1.0.0 + """ + + parser.add_argument( + "--insecure", + action=argparse.BooleanOptionalAction, + dest="insecure", + default=False, + help="Use HTTP to communicate with the registry", + ) + + +def _add_oci_platform_to_parser( + parser: argparse.ArgumentParser, required: bool = True ) -> None: """ - Push to an OCI image container given GardenLinux canonical named artifacts - in a specified directory. + Add `--platform` to the given argument parser. - :since: 0.7.0 + :param parser: ArgumentParser instance + + :since: 1.0.0 """ - container = Container(f"{container}:{version}", insecure=insecure) + parser.add_argument( + "--platform", + required=required, + dest="platform", + help="OCI platform as os/arch/variant", + ) + + +def _add_oci_repository_to_parser(parser: argparse.ArgumentParser) -> None: + """ + Add `--repository` to the given argument parser. - manifest = container.read_or_generate_manifest(cname, arch, version, commit) + :param parser: ArgumentParser instance - if not isinstance(manifest, ImageManifest): - raise RuntimeError("Data given for OCI image manifest is incomplete") + :since: 1.0.0 + """ - container.push_manifest_and_artifacts_from_directory( - manifest, directory, manifest_file, additional_tag + parser.add_argument( + "--repository", + required=True, + dest="repository", + help="Repository Path", ) - if cosign_file: - print(manifest.digest, file=open(cosign_file, "w")) - - -@cli.command() -@click.option( - "--container", - required=True, - help="Container Name", -) -@click.option( - "--cname", - required=False, - default=None, - help="Canonical Name of Image", -) -@click.option( - "--arch", - required=False, - default=None, - help="Target Image CPU Architecture", -) -@click.option( - "--version", - required=False, - default=None, - help="Version of image", -) -@click.option( - "--commit", - required=False, - default=None, - help="Commit of image", -) -@click.option( - "--insecure", - type=bool, - default=False, - help="Use HTTP to communicate with the registry", -) -@click.option( - "--tag", - required=True, - multiple=True, - help="Tag to push the manifest with", -) -def push_manifest_tags( - container: str, - cname: str, - arch: str, - version: str, - commit: str, - insecure: bool, - tag: List[str], + +def _add_oci_tag_to_parser( + parser: argparse.ArgumentParser, + required: bool = True, + multiple: bool = False, ) -> None: """ - Push tags to an OCI image container for a given GardenLinux canonical named image. + Add `--tag` to the given argument parser. + + :param parser: ArgumentParser instance - :since: 0.10.0 + :since: 1.0.0 """ - container = Container(f"{container}:{version}", insecure=insecure) + kwargs = { + "required": required, + "dest": "tag", + "help": "OCI tag of image", + } - manifest = container.read_or_generate_manifest(cname, arch, version, commit) - container.push_manifest_for_tags(manifest, tag) + if multiple: + kwargs["action"] = "append" + kwargs["default"] = [] + parser.add_argument("--tag", **kwargs) # type: ignore[arg-type] -@cli.command() -@click.option( - "--container", - required=True, - help="Container Name", -) -@click.option( - "--tag", - required=False, - help="OCI tag of image", -) -@click.option( - "--oci_archive", - required=False, - help="Write build result to the OCI archive path and file name", -) -def save_container(container: str, tag: str, oci_archive: str) -> None: + +def _add_version_to_parser(parser: argparse.ArgumentParser) -> None: """ - Saves a given OCI image container as an OCI archive. + Add `--version` to the given argument parser. + + :param parser: ArgumentParser instance :since: 1.0.0 """ - podman = Podman() - - image_id = podman.get_image_id(container, oci_tag=tag) - podman.save_oci_archive(image_id, oci_archive, oci_tag=tag) + parser.add_argument( + "--version", + required=False, + dest="version", + help="Version of image", + ) -@cli.command() -@click.option( - "--container", - required=True, - help="Container Name", -) -@click.option( - "--tag", - required=False, - help="OCI tag of image", -) -@click.option( - "--additional_tag", - required=False, - multiple=True, - help="Additional tag to push the manifest with", -) -def tag_container(container: str, tag: str, additional_tag: List[str]) -> None: +def get_parser() -> argparse.ArgumentParser: """ - Adds additional tags to a given OCI image container. + Get the argument parser for gl-oci. + Used for documentation generation. + :return: ArgumentParser instance :since: 1.0.0 """ - podman = Podman() + parser = argparse.ArgumentParser( + prog="gl-oci", + description="gl-oci provides functionality to handle OCI images.", + ) - with PodmanContext() as podman_context: - image_id = podman.get_image_id(container, podman=podman_context, oci_tag=tag) + subparsers = parser.add_subparsers(dest="action", help="Action to perform.") - if additional_tag is not None: - podman.tag_list( - image_id, - Podman.get_container_tag_list(container, additional_tag), - podman=podman_context, - ) + add_image_to_index_parser = subparsers.add_parser("add-image-to-index") + + _add_oci_index_args_to_parser(add_image_to_index_parser) + _add_oci_repository_to_parser(add_image_to_index_parser) + _add_oci_tag_to_parser(add_image_to_index_parser) + _add_oci_insecure_to_parser(add_image_to_index_parser) + _add_additional_tag_list_to_parser(add_image_to_index_parser) + + build_image_parser = subparsers.add_parser("build-image") + + _add_oci_repository_to_parser(build_image_parser) + _add_oci_tag_to_parser(build_image_parser) + _add_dir_to_parser(build_image_parser, "Path to the build Containerfile") + _add_oci_platform_to_parser(build_image_parser, False) + _add_additional_tag_list_to_parser(build_image_parser) + _add_build_arg_to_parser(build_image_parser) + _add_oci_archive_to_parser(build_image_parser, False) + + load_image_parser = subparsers.add_parser("load-image") + + _add_oci_archive_to_parser(load_image_parser, False) + _add_additional_tag_list_to_parser(load_image_parser) + + load_images_from_directory_parser = subparsers.add_parser( + "load-images-from-directory" + ) + + _add_dir_to_parser( + load_images_from_directory_parser, "Directory of the build artifacts" + ) + + new_index_parser = subparsers.add_parser("new-index") + + _add_oci_index_args_to_parser(new_index_parser) + _add_oci_insecure_to_parser(new_index_parser) + _add_additional_tag_list_to_parser(new_index_parser) + + pull_image_parser = subparsers.add_parser("pull-image") + + _add_oci_repository_to_parser(pull_image_parser) + _add_oci_tag_to_parser(pull_image_parser, False) + _add_oci_platform_to_parser(pull_image_parser, False) + _add_oci_insecure_to_parser(pull_image_parser) + + push_image_parser = subparsers.add_parser("push-image") + + _add_oci_repository_to_parser(push_image_parser) + _add_oci_tag_to_parser(push_image_parser, False) + _add_oci_destination_to_parser(push_image_parser) + _add_oci_insecure_to_parser(push_image_parser) + + push_index_from_directory_parser = subparsers.add_parser( + "push-index-from-directory" + ) + + _add_oci_index_args_to_parser(push_index_from_directory_parser) + + _add_dir_to_parser( + push_index_from_directory_parser, + default_value="manifests", + help_text="Directory to read index entry files from.", + ) + + _add_oci_insecure_to_parser(push_index_from_directory_parser) + _add_additional_tag_list_to_parser(push_index_from_directory_parser) + + push_index_tags_parser = subparsers.add_parser("push-index-tags") + + _add_oci_index_args_to_parser(push_index_tags_parser) + _add_oci_insecure_to_parser(push_index_tags_parser) + _add_oci_tag_to_parser(push_index_tags_parser, multiple=True) + + push_manifest_parser = subparsers.add_parser("push-manifest") + + _add_oci_repository_to_parser(push_manifest_parser) + _add_cname_to_parser(push_manifest_parser) + _add_arch_to_parser(push_manifest_parser) + _add_version_to_parser(push_manifest_parser) + _add_commit_to_parser(push_manifest_parser) + _add_dir_to_parser(push_manifest_parser, "Directory of the build artifacts") + _add_manifest_file_to_parser(push_manifest_parser) + _add_cosign_file_to_parser(push_manifest_parser) + _add_oci_insecure_to_parser(push_manifest_parser) + _add_additional_tag_list_to_parser(push_manifest_parser) + + push_manifest_tags_parser = subparsers.add_parser("push-manifest-tags") + + _add_oci_repository_to_parser(push_manifest_tags_parser) + _add_cname_to_parser(push_manifest_tags_parser) + _add_arch_to_parser(push_manifest_tags_parser) + _add_version_to_parser(push_manifest_tags_parser) + _add_commit_to_parser(push_manifest_tags_parser) + _add_oci_insecure_to_parser(push_manifest_tags_parser) + _add_oci_tag_to_parser(push_manifest_tags_parser, multiple=True) + + save_image_parser = subparsers.add_parser("save-image") + + _add_oci_repository_to_parser(save_image_parser) + _add_oci_tag_to_parser(save_image_parser, False) + _add_oci_archive_to_parser(save_image_parser, False) + + tag_image_parser = subparsers.add_parser("tag-image") + + _add_oci_repository_to_parser(tag_image_parser) + _add_oci_tag_to_parser(tag_image_parser, False) + _add_additional_tag_list_to_parser(tag_image_parser) + + return parser def main() -> None: """ - gl-oci main() + gl-oci provides functionality to handle OCI images. It can pull and push + images from remote repositories as well as handle GardenLinux artifacts, OCI + image indices and manifests. :since: 0.7.0 """ - cli() + parser = get_parser() + args = parser.parse_args() + + match args.action: + case "add-image-to-index": + manifest_repository = Repository( + f"{args.repository}:{args.tag}", insecure=args.insecure + ) + + manifest = manifest_repository.read_manifest() + + index_resource = Repository( + f"{args.index}:{args.index_tag}", insecure=args.insecure + ) + + image_index = index_resource.read_or_generate_index() + image_index.append_manifest(manifest) + + index_resource.push_index(image_index) + index_resource.push_index_for_tags(image_index, args.additional_tag) + case "build-image": + podman = Podman() + + with PodmanContext() as podman_context: + if args.oci_archive is None: + image_id = podman.build( + args.directory, + podman=podman_context, + platform=args.platform, + oci_tag=f"{args.repository}:{args.tag}", + build_args=Podman.parse_build_args_list(args.build_arg), + ) + else: + build_result_data = podman.build_and_save_oci_archive( + args.directory, + args.oci_archive, + podman=podman_context, + platform=args.platform, + oci_tag=f"{args.repository}:{args.tag}", + build_args=Podman.parse_build_args_list(args.build_arg), + ) + + _, image_id = build_result_data.popitem() + + if args.additional_tag is not None: + podman.tag_list( + image_id, + Podman.get_image_tag_list(args.repository, args.additional_tag), + ) + + print(image_id) + case "load-image": + podman = Podman() + + with PodmanContext() as podman_context: + image_id = podman.load_oci_archive( + args.oci_archive, podman=podman_context + ) + + if args.additional_tag is not None: + podman.tag_list( + image_id, args.additional_tag, podman=podman_context + ) + + print(image_id) + case "load-images-from-directory": + result = Podman().load_oci_archives_from_directory(args.directory) + print(json.dumps(result)) + case "new-index": + index_resource = Repository( + f"{args.index}:{args.index_tag}", insecure=args.insecure + ) + + image_index = index_resource.generate_index() + index_resource.push_index(image_index) + index_resource.push_index_for_tags(image_index, args.additional_tag) + case "pull-image": + image_id = Podman(insecure=args.insecure).pull( + args.repository, oci_tag=args.tag, platform=args.platform + ) + print(image_id) + case "push-image": + Podman(insecure=args.insecure).push( + args.repository, oci_tag=args.tag, destination=args.destination + ) + case "push-index-from-directory": + index_resource = Repository( + f"{args.index}:{args.index_tag}", insecure=args.insecure + ) + index_resource.push_index_from_directory( + args.directory, args.additional_tag + ) + case "push-index-tags": + index_resource = Repository( + f"{args.index}:{args.index_tag}", insecure=args.insecure + ) + + image_index = index_resource.read_or_generate_index() + index_resource.push_index_for_tags(image_index, args.tag) + case "push-manifest": + repository = Repository( + f"{args.repository}:{args.version}", insecure=args.insecure + ) + + manifest = repository.read_or_generate_manifest( + args.cname, args.arch, args.version, args.commit + ) + + if not isinstance(manifest, ImageManifest): + raise RuntimeError("Data given for OCI image manifest is incomplete") + + repository.push_manifest_and_artifacts_from_directory( + manifest, args.directory, args.manifest_file, args.additional_tag + ) + + if args.cosign_file: + print(manifest.digest, file=open(args.cosign_file, "w")) + case "push-manifest-tags": + repository = Repository( + f"{args.repository}:{args.version}", insecure=args.insecure + ) + + manifest = repository.read_or_generate_manifest( + args.cname, args.arch, args.version, args.commit + ) + + repository.push_manifest_for_tags(manifest, args.tag) + case "save-image": + podman = Podman() + + image_id = podman.get_image_id(args.repository, oci_tag=args.tag) + podman.save_oci_archive(image_id, args.oci_archive, oci_tag=args.tag) + case "tag-image": + podman = Podman() + + with PodmanContext() as podman_context: + image_id = podman.get_image_id( + args.repository, podman=podman_context, oci_tag=args.tag + ) + + if args.additional_tag is not None: + podman.tag_list( + image_id, + Podman.get_image_tag_list(args.repository, args.additional_tag), + podman=podman_context, + ) if __name__ == "__main__": - cli() + main() diff --git a/src/gardenlinux/oci/image_manifest.py b/src/gardenlinux/oci/image_manifest.py index 324c16c8..ded6608a 100644 --- a/src/gardenlinux/oci/image_manifest.py +++ b/src/gardenlinux/oci/image_manifest.py @@ -13,7 +13,7 @@ from oras.defaults import annotation_title as ANNOTATION_TITLE from ..constants import GL_DISTRIBUTION_NAME, GL_REPOSITORY_URL -from ..features import CName +from ..features import Flavor from .layer import Layer from .manifest import Manifest from .platform import new_platform @@ -154,7 +154,26 @@ def flavor(self) -> str: :since: 0.7.0 """ - return CName(self.cname).flavor + return Flavor(self.cname, self.arch).flavor + + @flavor.setter + def flavor(self, value: str) -> None: + """ + Sets the GardenLinux flavor of the OCI image manifest. + + :param value: OCI image GardenLinux flavor + + :since: 1.0.0 + """ + + self._ensure_annotations_dict() + + if "-" not in value: + raise RuntimeError(f"GardenLinux flavor is invalid: {value}") + + cname, arch = value.rsplit("-", 1) + self["annotations"][ImageManifest.ANNOTATION_ARCH_KEY] = arch + self["annotations"][ImageManifest.ANNOTATION_CNAME_KEY] = cname @property def extended_dict(self) -> Dict[str, Any]: diff --git a/src/gardenlinux/oci/podman.py b/src/gardenlinux/oci/podman.py index 28c585d2..246e4f81 100644 --- a/src/gardenlinux/oci/podman.py +++ b/src/gardenlinux/oci/podman.py @@ -56,7 +56,7 @@ def build( **kwargs: Any, ) -> str: """ - Build a container. + Build a image. :since: 1.0.0 """ @@ -96,7 +96,7 @@ def build_and_save_oci_archive( **kwargs: Any, ) -> Dict[str, str]: """ - Build a container and save the result as an OCI archive with the given path and file name. + Build a image and save the result as an OCI archive with the given path and file name. :since: 1.0.0 """ @@ -119,41 +119,39 @@ def build_and_save_oci_archive( @PodmanContext.wrap def get_image( self, - container: str, + image: str, podman: PodmanContext, oci_tag: Optional[str] = None, ) -> Image: """ - Returns the Podman image ID for a given OCI container tag. + Returns the Podman image ID for a given OCI image tag. :since: 1.0.0 """ - container_tag = container - if oci_tag is not None: if ":" in oci_tag: - container_tag = oci_tag + image = oci_tag else: - container_tag += f":{oci_tag}" + image += f":{oci_tag}" - return Image(podman.images.get(container_tag)) + return Image(podman.images.get(image)) @PodmanContext.wrap def get_image_id( self, - container: str, + image: str, podman: PodmanContext, oci_tag: Optional[str] = None, ) -> str: """ - Returns the Podman image ID for a given OCI container tag. + Returns the Podman image ID for a given OCI image tag. :since: 1.0.0 """ - image = self.get_image(container, oci_tag=oci_tag, podman=podman) - return image.id # type: ignore[no-any-return] + image_object = self.get_image(image, oci_tag=oci_tag, podman=podman) + return image_object.id # type: ignore[no-any-return] @PodmanContext.wrap def load_oci_archive( @@ -195,13 +193,13 @@ def load_oci_archives_from_directory( @PodmanContext.wrap def pull( self, - container: str, + image: str, podman: PodmanContext, platform: Optional[str] = None, oci_tag: Optional[str] = None, ) -> str: """ - Pulls a given OCI container. + Pulls a given OCI image. :since: 1.0.0 """ @@ -217,19 +215,19 @@ def pull( if oci_tag is not None: kwargs["tag"] = oci_tag - image = podman.images.pull(container, **kwargs) - return image.id # type: ignore[no-any-return] + image_object = podman.images.pull(image, **kwargs) + return image_object.id # type: ignore[no-any-return] @PodmanContext.wrap def push( self, - container: str, + image: str, podman: PodmanContext, destination: Optional[str] = None, oci_tag: Optional[str] = None, ) -> None: """ - Pushs a given OCI container. + Pushs a given OCI image. :since: 1.0.0 """ @@ -245,7 +243,7 @@ def push( if oci_tag is not None: kwargs["tag"] = oci_tag - podman.images.push(container, **kwargs) + podman.images.push(image, **kwargs) @PodmanContext.wrap def save_oci_archive( @@ -285,22 +283,22 @@ def save_oci_archive( def tag( self, image_id: str, - oci_container_tag: str, + oci_tag: str, podman: PodmanContext, ) -> None: """ - Tags a given Podman image ID with the container tag given. + Tags a given Podman image ID with the image tag given. :since: 1.0.0 """ - if ":" in oci_container_tag: - oci_data = oci_container_tag.rsplit(":", 1) + if ":" in oci_tag: + oci_data = oci_tag.rsplit(":", 1) if len(oci_data) < 2: raise RuntimeError("No tag given") else: - oci_data = ["", oci_container_tag] + oci_data = ["", oci_tag] image = podman.images.get(image_id) image.tag(oci_data[0], oci_data[1]) @@ -309,36 +307,36 @@ def tag( def tag_list( self, image_id: str, - oci_container_tags_list: List[str], + oci_tags_list: List[str], podman: PodmanContext, ) -> None: """ - Tags a given Podman image ID with the list of container tags given. + Tags a given Podman image ID with the list of image tags given. :since: 1.0.0 """ - for container_tag in oci_container_tags_list: - self.tag(image_id, container_tag, podman=podman) + for oci_tag in oci_tags_list: + self.tag(image_id, oci_tag, podman=podman) @staticmethod - def get_container_tag_list(container: str, tag_list: Sequence[str]) -> List[str]: + def get_image_tag_list(image: str, tag_list: Sequence[str]) -> List[str]: """ - Returns a list of "container:tag" values. + Returns a list of "image:tag" values. :since: 1.0.0 """ - container_tag_list = [] + image_tag_list = [] if isinstance(tag_list, Sequence): for tag in tag_list: if ":" in tag: - container_tag_list.append(tag) + image_tag_list.append(tag) else: - container_tag_list.append(f"{container}:{tag}") + image_tag_list.append(f"{image}:{tag}") - return container_tag_list + return image_tag_list @staticmethod def parse_build_args_list(args_list: List[str]) -> Dict[str, str]: diff --git a/src/gardenlinux/oci/container.py b/src/gardenlinux/oci/repository.py similarity index 81% rename from src/gardenlinux/oci/container.py rename to src/gardenlinux/oci/repository.py index f01195d7..de55dc38 100644 --- a/src/gardenlinux/oci/container.py +++ b/src/gardenlinux/oci/repository.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- """ -OCI container +OCI repository """ import json @@ -22,7 +22,7 @@ from requests import HTTPError, Response from ..constants import OCI_IMAGE_INDEX_MEDIA_TYPE -from ..features.cname import CName +from ..features import ArtifactBaseName from ..logger import LoggerSetup from .image_manifest import ImageManifest from .index import Index @@ -31,55 +31,55 @@ from .schemas import index as IndexSchema -class Container(Registry): # type: ignore[misc] +class Repository(Registry): # type: ignore[misc] """ - OCI container instance to provide methods for interaction. + OCI repository instance to provide methods for interaction. :author: Garden Linux Maintainers :copyright: Copyright 2024 SAP SE :package: gardenlinux :subpackage: oci - :since: 0.7.0 + :since: 1.0.0 :license: https://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 """ def __init__( self, - container_url: str, + repository_url: str, insecure: bool = False, token: Optional[str] = None, logger: Optional[logging.Logger] = None, ): """ - Constructor __init__(Container) + Constructor __init__(Repository) - :param container_url: OCI container URL + :param repository_url: OCI repository URL :param insecure: True if access is provided via HTTP without encryption :param token: OCI access token :param logger: Logger instance - :since: 0.7.0 + :since: 1.0.0 """ - container_data = container_url.rsplit(":", 1) + repository_data = repository_url.rsplit(":", 1) - if len(container_data) < 2: - raise RuntimeError("Container name given is invalid") + if len(repository_data) < 2: + raise RuntimeError("Repository name given is invalid") - self._container_version = container_data[1] + self._repository_version = repository_data[1] - if "://" in container_data[0]: - scheme = container_data[0].split(":", 1)[0].lower() + if "://" in repository_data[0]: + scheme = repository_data[0].split(":", 1)[0].lower() insecure = scheme != "https" - self._container_url = container_data[0] + self._repository_url = repository_data[0] else: scheme = "http" if insecure else "https" - self._container_url = f"{scheme}://{container_data[0]}" + self._repository_url = f"{scheme}://{repository_data[0]}" - container_url_data = urlsplit(self._container_url) + repository_url_data = urlsplit(self._repository_url) self._token = None if token is None: @@ -93,7 +93,7 @@ def __init__( Registry.__init__( self, - hostname=container_url_data.netloc, + hostname=repository_url_data.netloc, auth_backend=auth_backend, insecure=insecure, ) @@ -101,7 +101,7 @@ def __init__( if logger is None or not logger.hasHandlers(): logger = LoggerSetup.get_logger("gardenlinux.oci") - self._container_name = container_url_data.path[1:] + self._repository_name = repository_url_data.path[1:] self._logger = logger if self._token is not None: @@ -123,9 +123,9 @@ def __init__( def generate_image_manifest( self, cname: str, - architecture: Optional[str] = None, - version: Optional[str] = None, - commit: Optional[str] = None, + architecture: Optional[str], + version: Optional[str], + commit: Optional[str], feature_set: Optional[str] = None, ) -> ImageManifest: """ @@ -141,31 +141,21 @@ def generate_image_manifest( :since: 0.10.0 """ - cname_object = CName(cname, architecture, version) - - if architecture is None: - architecture = cname_object.arch - if version is None: - version = cname_object.version - if commit is None: - commit = cname_object.commit_id - if feature_set is None: - feature_set = cname_object.feature_set - - if commit is None: - commit = "" + if not architecture or not version or not commit: + raise ValueError( + "Failed to validate input for generating an OCI image manifest" + ) + abn_object = ArtifactBaseName(f"{cname}-{architecture}-{version}-{commit}") manifest = ImageManifest() - manifest.version = version # type: ignore[assignment] - manifest.cname = cname - manifest.arch = architecture # type: ignore[assignment] - manifest.feature_set = feature_set + manifest.flavor = abn_object.flavor + manifest.version = version manifest.commit = commit description = ( - f"Image: {cname} " - f"Flavor: {cname_object.flavor} " + f"Image: {cname}-{architecture}-{version}-{commit}" + f"Flavor: {cname}-{architecture} " f"Architecture: {architecture} " f"Features: {feature_set} " f"Commit: {commit} " @@ -198,11 +188,8 @@ def generate_manifest( """ Generates an OCI manifest - :param cname: Canonical name of the manifest - :param architecture: Target architecture of the manifest :param version: Artifacts version of the manifest :param commit: The commit hash of the manifest - :param feature_set: The expanded list of the included features of this manifest :return: (object) OCI manifest :since: 0.9.2 @@ -226,7 +213,7 @@ def _get_index_without_response_parsing(self) -> Response: """ manifest_url = self.get_container( - f"{self._container_name}:{self._container_version}" + f"{self._repository_name}:{self._repository_version}" ).manifest_url() return self.do_request( # type: ignore[no-any-return] @@ -243,7 +230,7 @@ def _get_manifest_without_response_parsing(self, reference: str) -> Response: """ return self.do_request( # type: ignore[no-any-return] - f"{self.prefix}://{self.hostname}/v2/{self._container_name}/manifests/{reference}", + f"{self.prefix}://{self.hostname}/v2/{self._repository_name}/manifests/{reference}", headers={"Accept": "application/vnd.oci.image.manifest.v1+json"}, ) @@ -359,7 +346,7 @@ def push_manifest( if not isinstance(manifest, Manifest): raise RuntimeError("Artifacts image manifest given is invalid") - container_name = f"{self._container_name}:{self._container_version}" + repository_name = f"{self._repository_name}:{self._repository_version}" fd, config_file = mkstemp() @@ -368,24 +355,26 @@ def push_manifest( fp.write(manifest.config_json) self._check_200_response( - self.upload_blob(config_file, container_name, manifest["config"]) + self.upload_blob(config_file, repository_name, manifest["config"]) ) - self._logger.debug(f"Successfully pushed config for {container_name}") + self._logger.debug(f"Successfully pushed config for {repository_name}") finally: Path(config_file).unlink() - manifest_url = f"{self._container_url}:{self._container_version}" + manifest_url = f"{self._repository_url}:{self._repository_version}" if isinstance(manifest, ImageManifest): - manifest_url += f"-{manifest.cname}-{manifest.arch}" + manifest_url += f"-{manifest.flavor}-{manifest.version}-{manifest.commit}-{manifest.arch}" + elif not self._repository_version: + raise RuntimeError("Failed to push OCI manifest with invalid tag") - manifest_container = OrasContainer(manifest_url) + manifest_repository = OrasContainer(manifest_url) - self._check_200_response(self.upload_manifest(manifest, manifest_container)) + self._check_200_response(self.upload_manifest(manifest, manifest_repository)) self._logger.info( - f"Successfully pushed {manifest_container} ({manifest.digest})" + f"Successfully pushed {manifest_repository} ({manifest.digest})" ) if isinstance(additional_tags, Sequence) and len(additional_tags) > 0: @@ -429,7 +418,7 @@ def push_manifest_and_artifacts( if not isinstance(artifacts_dir, PathLike): artifacts_dir = Path(artifacts_dir) - container_name = f"{self._container_name}:{self._container_version}" + repository_name = f"{self._repository_name}:{self._repository_version}" # For each file, create sign, attach and push a layer for artifact in artifacts_with_metadata: @@ -456,7 +445,7 @@ def push_manifest_and_artifacts( self._logger.debug(f"Layer: {layer_dict}") self._check_200_response( - self.upload_blob(file_path_name, container_name, layer_dict) + self.upload_blob(file_path_name, repository_name, layer_dict) ) self._logger.info( @@ -506,7 +495,7 @@ def push_manifest_and_artifacts_from_directory( if file_name.is_file() ] - artifacts_with_metadata = Container.get_artifacts_metadata_from_files( + artifacts_with_metadata = Repository.get_artifacts_metadata_from_files( files, manifest.arch ) @@ -547,9 +536,11 @@ def push_manifest_for_tags(self, manifest: Manifest, tags: List[str]) -> None: # For each additional tag, push the manifest using Registry.upload_manifest for tag in tags: - manifest_container = OrasContainer(f"{self._container_url}:{tag}") + manifest_repository = OrasContainer(f"{self._repository_url}:{tag}") - self._check_200_response(self.upload_manifest(manifest, manifest_container)) + self._check_200_response( + self.upload_manifest(manifest, manifest_repository) + ) def read_index(self) -> Index: """ @@ -573,6 +564,7 @@ def read_manifest( cname: Optional[str] = None, architecture: Optional[str] = None, version: Optional[str] = None, + commit: Optional[str] = None, ) -> Manifest: """ Reads the OCI manifest from registry. @@ -580,6 +572,7 @@ def read_manifest( :param cname: Canonical name of the manifest :param architecture: Target architecture of the manifest :param version: Artifacts version of the manifest + :param commit: The Git commit ID of the manifest :return: OCI image manifest :since: 1.0.0 @@ -589,16 +582,14 @@ def read_manifest( manifest_type = Manifest response = self._get_manifest_without_response_parsing( - self._container_version + self._repository_version ) else: + abn_object = ArtifactBaseName(f"{cname}-{architecture}-{version}-{commit}") manifest_type = ImageManifest - if architecture is None: - architecture = CName(cname, architecture, version).arch - response = self._get_manifest_without_response_parsing( - f"{self._container_version}-{cname}-{architecture}" + f"{self._repository_version}-{abn_object}-{architecture}" ) if response.ok: @@ -619,7 +610,11 @@ def read_or_generate_index(self) -> Index: try: index = self.read_index() except HTTPError as exc: - if exc.response.status_code != 404: + if exc.response.status_code == 404: + self._logger.debug( + f"gardenlinux.oci.Repository.read_index() failed: {exc}" + ) + else: raise index = self.generate_index() @@ -647,18 +642,24 @@ def read_or_generate_manifest( :since: 0.7.0 """ - try: - manifest = self.read_manifest(cname, architecture, version) - except HTTPError as exc: - if exc.response.status_code != 404: - raise + manifest = None - if cname is None: - manifest = self.generate_manifest(version, commit) - else: - manifest = self.generate_image_manifest( - cname, architecture, version, commit, feature_set - ) + if cname: + try: + manifest = self.read_manifest(cname, architecture, version, commit) + except HTTPError as exc: + if exc.response.status_code == 404: + self._logger.debug( + f"gardenlinux.oci.Repository.read_manifest() failed: {exc}" + ) + else: + raise + + manifest = self.generate_image_manifest( + cname, architecture, version, commit, feature_set + ) + else: + manifest = self.generate_manifest(version, commit) return manifest @@ -667,7 +668,7 @@ def _upload_index(self, index: Index, reference: Optional[str] = None) -> Respon Uploads the given OCI image index and returns the response. :param index: OCI image index - :param reference: OCI container reference (tag) to push to + :param reference: OCI repository reference (tag) to push to :return: (object) OCI image index put response :since: 0.7.0 @@ -676,27 +677,29 @@ def _upload_index(self, index: Index, reference: Optional[str] = None) -> Respon jsonschema.validate(index, schema=IndexSchema) if reference is None: - reference = self._container_version + reference = self._repository_version return self.do_request( # type: ignore[no-any-return] - f"{self.prefix}://{self.hostname}/v2/{self._container_name}/manifests/{reference}", + f"{self.prefix}://{self.hostname}/v2/{self._repository_name}/manifests/{reference}", "PUT", headers={"Content-Type": OCI_IMAGE_INDEX_MEDIA_TYPE}, json=index.extended_dict, ) - def upload_manifest(self, manifest: Manifest, container: OrasContainer) -> Response: + def upload_manifest( + self, manifest: Manifest, repository: OrasContainer + ) -> Response: """ oras-project.github.io: Read a manifest file and upload it. - :param manifest: manifest to upload - :param container: parsed container URI + :param manifest: Manifest to upload + :param repository: Repository URI :return: (object) OCI manifest put response :since: 1.0.0 """ - return Registry.upload_manifest(self, manifest.extended_dict, container) # type: ignore[no-any-return] + return Registry.upload_manifest(self, manifest.extended_dict, repository) # type: ignore[no-any-return] @staticmethod def get_artifacts_metadata_from_files( diff --git a/src/gardenlinux/s3/__main__.py b/src/gardenlinux/s3/__main__.py index f794631c..a49fdf3d 100644 --- a/src/gardenlinux/s3/__main__.py +++ b/src/gardenlinux/s3/__main__.py @@ -43,16 +43,16 @@ def get_parser() -> argparse.ArgumentParser: download_parser = subparsers.add_parser("download-artifacts-from-bucket") download_parser.add_argument( - "--cname", + "--artifact-base-name", required=False, - dest="cname", - help="Canonical name (cname) used as the S3 key prefix for artifacts.", + dest="artifact_base_name", + help="Artifact base name used as the S3 key prefix for artifacts.", ) upload_parser = subparsers.add_parser("upload-artifacts-to-bucket") upload_parser.add_argument( - "--artifact-name", dest="artifact_name", help="S3 artifact base name." + "--artifact-base-name", dest="artifact_base_name", help="S3 artifact base name." ) return parser @@ -69,8 +69,10 @@ def main() -> None: args = parser.parse_args() if args.action == "download-artifacts-from-bucket": - S3Artifacts(args.bucket).download_to_directory(args.cname, args.path) + S3Artifacts(args.bucket).download_to_directory( + args.artifact_base_name, args.path + ) elif args.action == "upload-artifacts-to-bucket": S3Artifacts(args.bucket).upload_from_directory( - args.artifact_name, args.path, dry_run=args.dry_run + args.artifact_base_name, args.path, dry_run=args.dry_run ) diff --git a/src/gardenlinux/s3/s3_artifacts.py b/src/gardenlinux/s3/s3_artifacts.py index 09fd6a37..064513b6 100644 --- a/src/gardenlinux/s3/s3_artifacts.py +++ b/src/gardenlinux/s3/s3_artifacts.py @@ -18,7 +18,7 @@ import yaml -from ..features import CName +from ..features import ArtifactBaseName from .bucket import Bucket @@ -67,13 +67,13 @@ def bucket(self) -> Bucket: return self._bucket def download_to_directory( - self, cname: str, artifacts_dir: PathLike[str] | str + self, artifact_base_name: str, artifacts_dir: PathLike[str] | str ) -> None: """ Download S3 artifacts to a given directory. - :param cname: Canonical name of the GardenLinux S3 artifacts - :param artifacts_dir: Path for the image artifacts + :param artifact_base_name: Artifact base name of the Garden Linux S3 artifacts + :param artifacts_dir: Path for the image artifacts :since: 0.8.0 """ @@ -84,14 +84,17 @@ def download_to_directory( raise RuntimeError(f"Artifacts directory given is invalid: {artifacts_dir}") release_object = list( - self._bucket.objects.filter(Prefix=f"meta/singles/{cname}") + self._bucket.objects.filter(Prefix=f"meta/singles/{artifact_base_name}") )[0] self._bucket.download_file( - release_object.key, str(artifacts_dir.joinpath(f"{cname}.s3_metadata.yaml")) + release_object.key, + str(artifacts_dir.joinpath(f"{artifact_base_name}.s3_metadata.yaml")), ) - for s3_object in self._bucket.objects.filter(Prefix=f"objects/{cname}").all(): + for s3_object in self._bucket.objects.filter( + Prefix=f"objects/{artifact_base_name}" + ).all(): self._bucket.download_file( s3_object.key, str(artifacts_dir.joinpath(basename(s3_object.key))) ) @@ -121,35 +124,44 @@ def upload_from_directory( release_file = artifacts_dir.joinpath(f"{base_name}.release") try: - cname_object = CName.new_from_release_file(release_file) + abn_object = ArtifactBaseName.new_from_release_file(release_file) except RuntimeError: if not release_file.exists(): raise RuntimeError( f"Release metadata file given is invalid: {release_file}" ) + base_abn_object = ArtifactBaseName(base_name) + release_config = ConfigParser(allow_unnamed_section=True) release_config.read(release_file) - cname_object = CName( - release_config.get(UNNAMED_SECTION, "GARDENLINUX_CNAME").strip("\"'"), - commit_hash=release_config.get( - UNNAMED_SECTION, "GARDENLINUX_COMMIT_ID_LONG" - ).strip("\"'"), - version=release_config.get( - UNNAMED_SECTION, "GARDENLINUX_VERSION" - ).strip("\"'"), - ) + artifact_base_name = release_config.get( + UNNAMED_SECTION, "GARDENLINUX_CNAME" + ).strip("\"'") + + artifact_base_name += "-" + base_abn_object.arch + + artifact_base_name += "-" + release_config.get( + UNNAMED_SECTION, "GARDENLINUX_VERSION" + ).strip("\"'") - if cname_object.version_and_commit_id is None: + artifact_base_name += "-" + release_config.get( + UNNAMED_SECTION, "GARDENLINUX_COMMIT_ID_LONG" + ).strip("\"'") + + abn_object = ArtifactBaseName(artifact_base_name) + + if abn_object.version_and_commit_id is None: raise RuntimeError( "Version information could not be determined from release file" ) - arch = cname_object.arch - feature_set_list = cname_object.feature_set_list + arch = abn_object.arch + feature_set_list = abn_object.feature_set_list release_timestamp = stat(release_file).st_ctime requirements_file = artifacts_dir.joinpath(f"{base_name}.requirements") + publishing_group = "" require_uefi = None secureboot = None @@ -196,13 +208,13 @@ def upload_from_directory( re_object = re.compile("[^a-zA-Z0-9\\s+\\-=.\\_:/@]") arch = re_object.sub("+", arch) - commit_id_or_hash = cname_object.commit_hash + commit_id_or_hash = abn_object.commit_hash if commit_id_or_hash is None: - commit_id_or_hash = cname_object.commit_id + commit_id_or_hash = abn_object.commit_id metadata = { - "platform": cname_object.platform, + "platform": abn_object.platform, "architecture": arch, "build_committish": commit_id_or_hash, "build_timestamp": datetime.fromtimestamp(release_timestamp), @@ -214,14 +226,14 @@ def upload_from_directory( "s3_bucket": self._bucket.name, "s3_key": f"meta/singles/{base_name}", "test_result": None, - "version": cname_object.version, + "version": abn_object.version, "paths": [], } - if cname_object.version_epoch is not None: - metadata["gardenlinux_epoch"] = cname_object.version_epoch + if abn_object.version_epoch is not None: + metadata["gardenlinux_epoch"] = abn_object.version_epoch - platform_variant = cname_object.platform_variant + platform_variant = abn_object.platform_variant if platform_variant is not None: metadata["platform_variant"] = platform_variant @@ -253,8 +265,8 @@ def upload_from_directory( s3_tags = { "architecture": arch, - "platform": re_object.sub("+", cname_object.platform), - "version": re_object.sub("+", cname_object.version), # type: ignore[arg-type] + "platform": re_object.sub("+", abn_object.platform), + "version": re_object.sub("+", abn_object.version), "committish": commit_id_or_hash, "md5sum": md5sum, "sha256sum": sha256sum, diff --git a/test-data/gardenlinux b/test-data/gardenlinux index 8c14e750..c15e9789 160000 --- a/test-data/gardenlinux +++ b/test-data/gardenlinux @@ -1 +1 @@ -Subproject commit 8c14e75011397cd6d16c1182f3377678c885b87a +Subproject commit c15e9789b16b0e64019b52b45fb6fa3b3c0f608c diff --git a/test-data/reproducibility/diff_files/compare_nightly.md b/test-data/reproducibility/diff_files/compare_nightly.md index 1f41fd03..a5843bda 100644 --- a/test-data/reproducibility/diff_files/compare_nightly.md +++ b/test-data/reproducibility/diff_files/compare_nightly.md @@ -13,7 +13,7 @@ Comparison of nightly **[#2405](https://github.com/gardenlinux/gardenlinux/actio | Affected Files | Flavors | Features Causing the Problem | |----------------|---------|------------------------------| -|`/etc/hostname`|**4.9%** affected
`container-amd64`
`container-arm64`
`container-pythonDev-amd64`
`container-pythonDev-arm64`|
container
| +|`/etc/hostname`|**4.9%** affected
`container-amd64`
`container-arm64`
`container-pythonDev-amd64`
`container-pythonDev-arm64`|
container:
_archgrouped
| |✅ No problems found|**95.1%**
ali-gardener_prod-amd64...`ali-gardener_prod-amd64`
`aws-gardener_fips_prod-amd64`
`aws-gardener_fips_prod-arm64`
`aws-gardener_prod-amd64`
`aws-gardener_prod-arm64`
`aws-gardener_prod_tpm2_trustedboot-amd64`
`aws-gardener_prod_tpm2_trustedboot-arm64`
`aws-gardener_prod_trustedboot-amd64`
`aws-gardener_prod_trustedboot-arm64`
`aws-gardener_prod_usi-amd64`
`aws-gardener_prod_usi-arm64`
`azure-gardener_prod-amd64`
`azure-gardener_prod-arm64`
`azure-gardener_prod_tpm2_trustedboot-amd64`
`azure-gardener_prod_tpm2_trustedboot-arm64`
`azure-gardener_prod_trustedboot-amd64`
`azure-gardener_prod_trustedboot-arm64`
`azure-gardener_prod_usi-amd64`
`azure-gardener_prod_usi-arm64`
`bare-libc-amd64`
`bare-libc-arm64`
`bare-nodejs-amd64`
`bare-nodejs-arm64`
`bare-python-amd64`
`bare-python-arm64`
`bare-sapmachine-amd64`
`bare-sapmachine-arm64`
`baremetal-capi-amd64`
`baremetal-capi-arm64`
`baremetal-gardener_prod-amd64`
`baremetal-gardener_prod-arm64`
`baremetal-gardener_prod_tpm2_trustedboot-amd64`
`baremetal-gardener_prod_tpm2_trustedboot-arm64`
`baremetal-gardener_prod_trustedboot-amd64`
`baremetal-gardener_prod_trustedboot-arm64`
`baremetal-gardener_prod_usi-amd64`
`baremetal-gardener_prod_usi-arm64`
`baremetal-gardener_pxe-amd64`
`baremetal-gardener_pxe-arm64`
`baremetal-vhost-amd64`
`baremetal-vhost-arm64`
`baremetal_pxe-amd64`
`baremetal_pxe-arm64`
`gcp-gardener_prod-amd64`
`gcp-gardener_prod-arm64`
`gcp-gardener_prod_tpm2_trustedboot-amd64`
`gcp-gardener_prod_tpm2_trustedboot-arm64`
`gcp-gardener_prod_trustedboot-amd64`
`gcp-gardener_prod_trustedboot-arm64`
`gcp-gardener_prod_usi-amd64`
`gcp-gardener_prod_usi-arm64`
`gdch-gardener_prod-amd64`
`gdch-gardener_prod-arm64`
`kvm-gardener_prod-amd64`
`kvm-gardener_prod-arm64`
`kvm-gardener_prod_tpm2_trustedboot-amd64`
`kvm-gardener_prod_tpm2_trustedboot-arm64`
`kvm-gardener_prod_trustedboot-amd64`
`kvm-gardener_prod_trustedboot-arm64`
`kvm-gardener_prod_usi-amd64`
`kvm-gardener_prod_usi-arm64`
`lima-amd64`
`lima-arm64`
`openstack-gardener_prod-amd64`
`openstack-gardener_prod-arm64`
`openstack-gardener_prod_tpm2_trustedboot-amd64`
`openstack-gardener_prod_tpm2_trustedboot-arm64`
`openstack-gardener_prod_trustedboot-amd64`
`openstack-gardener_prod_trustedboot-arm64`
`openstack-gardener_prod_usi-amd64`
`openstack-gardener_prod_usi-arm64`
`openstack-metal-gardener_prod-amd64`
`openstack-metal-gardener_prod-arm64`
`openstack-metal-gardener_prod_usi-amd64`
`openstack-metal-gardener_prod_usi-arm64`
`vmware-gardener_prod-amd64`
`vmware-gardener_prod-arm64`
|-| *To add affected files to the whitelist, edit `src/gardenlinux/features/reproducibility/nightly_whitelist.json` in python-gardenlinux-lib* diff --git a/test-data/reproducibility/diff_files/compare_nightly_different_commit.md b/test-data/reproducibility/diff_files/compare_nightly_different_commit.md index e6d3a430..16b2a7ba 100644 --- a/test-data/reproducibility/diff_files/compare_nightly_different_commit.md +++ b/test-data/reproducibility/diff_files/compare_nightly_different_commit.md @@ -15,7 +15,7 @@ Comparison of nightly **[#2405](https://github.com/gardenlinux/gardenlinux/actio | Affected Files | Flavors | Features Causing the Problem | |----------------|---------|------------------------------| -|`/etc/hostname`|**4.9%** affected
`container-amd64`
`container-arm64`
`container-pythonDev-amd64`
`container-pythonDev-arm64`|
container
| +|`/etc/hostname`|**4.9%** affected
`container-amd64`
`container-arm64`
`container-pythonDev-amd64`
`container-pythonDev-arm64`|
container:
_archgrouped
| |✅ No problems found|**95.1%**
ali-gardener_prod-amd64...`ali-gardener_prod-amd64`
`aws-gardener_fips_prod-amd64`
`aws-gardener_fips_prod-arm64`
`aws-gardener_prod-amd64`
`aws-gardener_prod-arm64`
`aws-gardener_prod_tpm2_trustedboot-amd64`
`aws-gardener_prod_tpm2_trustedboot-arm64`
`aws-gardener_prod_trustedboot-amd64`
`aws-gardener_prod_trustedboot-arm64`
`aws-gardener_prod_usi-amd64`
`aws-gardener_prod_usi-arm64`
`azure-gardener_prod-amd64`
`azure-gardener_prod-arm64`
`azure-gardener_prod_tpm2_trustedboot-amd64`
`azure-gardener_prod_tpm2_trustedboot-arm64`
`azure-gardener_prod_trustedboot-amd64`
`azure-gardener_prod_trustedboot-arm64`
`azure-gardener_prod_usi-amd64`
`azure-gardener_prod_usi-arm64`
`bare-libc-amd64`
`bare-libc-arm64`
`bare-nodejs-amd64`
`bare-nodejs-arm64`
`bare-python-amd64`
`bare-python-arm64`
`bare-sapmachine-amd64`
`bare-sapmachine-arm64`
`baremetal-capi-amd64`
`baremetal-capi-arm64`
`baremetal-gardener_prod-amd64`
`baremetal-gardener_prod-arm64`
`baremetal-gardener_prod_tpm2_trustedboot-amd64`
`baremetal-gardener_prod_tpm2_trustedboot-arm64`
`baremetal-gardener_prod_trustedboot-amd64`
`baremetal-gardener_prod_trustedboot-arm64`
`baremetal-gardener_prod_usi-amd64`
`baremetal-gardener_prod_usi-arm64`
`baremetal-gardener_pxe-amd64`
`baremetal-gardener_pxe-arm64`
`baremetal-vhost-amd64`
`baremetal-vhost-arm64`
`baremetal_pxe-amd64`
`baremetal_pxe-arm64`
`gcp-gardener_prod-amd64`
`gcp-gardener_prod-arm64`
`gcp-gardener_prod_tpm2_trustedboot-amd64`
`gcp-gardener_prod_tpm2_trustedboot-arm64`
`gcp-gardener_prod_trustedboot-amd64`
`gcp-gardener_prod_trustedboot-arm64`
`gcp-gardener_prod_usi-amd64`
`gcp-gardener_prod_usi-arm64`
`gdch-gardener_prod-amd64`
`gdch-gardener_prod-arm64`
`kvm-gardener_prod-amd64`
`kvm-gardener_prod-arm64`
`kvm-gardener_prod_tpm2_trustedboot-amd64`
`kvm-gardener_prod_tpm2_trustedboot-arm64`
`kvm-gardener_prod_trustedboot-amd64`
`kvm-gardener_prod_trustedboot-arm64`
`kvm-gardener_prod_usi-amd64`
`kvm-gardener_prod_usi-arm64`
`lima-amd64`
`lima-arm64`
`openstack-gardener_prod-amd64`
`openstack-gardener_prod-arm64`
`openstack-gardener_prod_tpm2_trustedboot-amd64`
`openstack-gardener_prod_tpm2_trustedboot-arm64`
`openstack-gardener_prod_trustedboot-amd64`
`openstack-gardener_prod_trustedboot-arm64`
`openstack-gardener_prod_usi-amd64`
`openstack-gardener_prod_usi-arm64`
`openstack-metal-gardener_prod-amd64`
`openstack-metal-gardener_prod-arm64`
`openstack-metal-gardener_prod_usi-amd64`
`openstack-metal-gardener_prod_usi-arm64`
`vmware-gardener_prod-amd64`
`vmware-gardener_prod-arm64`
|-| *To add affected files to the whitelist, edit `src/gardenlinux/features/reproducibility/nightly_whitelist.json` in python-gardenlinux-lib* diff --git a/test-data/reproducibility/diff_files/different_commit.md b/test-data/reproducibility/diff_files/different_commit.md index c23088c5..49a532ae 100644 --- a/test-data/reproducibility/diff_files/different_commit.md +++ b/test-data/reproducibility/diff_files/different_commit.md @@ -13,7 +13,7 @@ Comparison of the latest nightly **[#2365](https://github.com/gardenlinux/garden | Affected Files | Flavors | Features Causing the Problem | |----------------|---------|------------------------------| -|`/etc/hostname`|**4.9%** affected
`container-amd64`
`container-arm64`
`container-pythonDev-amd64`
`container-pythonDev-arm64`|
container
| +|`/etc/hostname`|**4.9%** affected
`container-amd64`
`container-arm64`
`container-pythonDev-amd64`
`container-pythonDev-arm64`|
container:
_archgrouped
| |✅ No problems found|**95.1%**
ali-gardener_prod-amd64...`ali-gardener_prod-amd64`
`aws-gardener_fips_prod-amd64`
`aws-gardener_fips_prod-arm64`
`aws-gardener_prod-amd64`
`aws-gardener_prod-arm64`
`aws-gardener_prod_tpm2_trustedboot-amd64`
`aws-gardener_prod_tpm2_trustedboot-arm64`
`aws-gardener_prod_trustedboot-amd64`
`aws-gardener_prod_trustedboot-arm64`
`aws-gardener_prod_usi-amd64`
`aws-gardener_prod_usi-arm64`
`azure-gardener_prod-amd64`
`azure-gardener_prod-arm64`
`azure-gardener_prod_tpm2_trustedboot-amd64`
`azure-gardener_prod_tpm2_trustedboot-arm64`
`azure-gardener_prod_trustedboot-amd64`
`azure-gardener_prod_trustedboot-arm64`
`azure-gardener_prod_usi-amd64`
`azure-gardener_prod_usi-arm64`
`bare-libc-amd64`
`bare-libc-arm64`
`bare-nodejs-amd64`
`bare-nodejs-arm64`
`bare-python-amd64`
`bare-python-arm64`
`bare-sapmachine-amd64`
`bare-sapmachine-arm64`
`baremetal-capi-amd64`
`baremetal-capi-arm64`
`baremetal-gardener_prod-amd64`
`baremetal-gardener_prod-arm64`
`baremetal-gardener_prod_tpm2_trustedboot-amd64`
`baremetal-gardener_prod_tpm2_trustedboot-arm64`
`baremetal-gardener_prod_trustedboot-amd64`
`baremetal-gardener_prod_trustedboot-arm64`
`baremetal-gardener_prod_usi-amd64`
`baremetal-gardener_prod_usi-arm64`
`baremetal-gardener_pxe-amd64`
`baremetal-gardener_pxe-arm64`
`baremetal-vhost-amd64`
`baremetal-vhost-arm64`
`baremetal_pxe-amd64`
`baremetal_pxe-arm64`
`gcp-gardener_prod-amd64`
`gcp-gardener_prod-arm64`
`gcp-gardener_prod_tpm2_trustedboot-amd64`
`gcp-gardener_prod_tpm2_trustedboot-arm64`
`gcp-gardener_prod_trustedboot-amd64`
`gcp-gardener_prod_trustedboot-arm64`
`gcp-gardener_prod_usi-amd64`
`gcp-gardener_prod_usi-arm64`
`gdch-gardener_prod-amd64`
`gdch-gardener_prod-arm64`
`kvm-gardener_prod-amd64`
`kvm-gardener_prod-arm64`
`kvm-gardener_prod_tpm2_trustedboot-amd64`
`kvm-gardener_prod_tpm2_trustedboot-arm64`
`kvm-gardener_prod_trustedboot-amd64`
`kvm-gardener_prod_trustedboot-arm64`
`kvm-gardener_prod_usi-amd64`
`kvm-gardener_prod_usi-arm64`
`lima-amd64`
`lima-arm64`
`openstack-gardener_prod-amd64`
`openstack-gardener_prod-arm64`
`openstack-gardener_prod_tpm2_trustedboot-amd64`
`openstack-gardener_prod_tpm2_trustedboot-arm64`
`openstack-gardener_prod_trustedboot-amd64`
`openstack-gardener_prod_trustedboot-arm64`
`openstack-gardener_prod_usi-amd64`
`openstack-gardener_prod_usi-arm64`
`openstack-metal-gardener_prod-amd64`
`openstack-metal-gardener_prod-arm64`
`openstack-metal-gardener_prod_usi-amd64`
`openstack-metal-gardener_prod_usi-arm64`
`vmware-gardener_prod-amd64`
`vmware-gardener_prod-arm64`
|-| *To add affected files to the whitelist, edit `src/gardenlinux/features/reproducibility/nightly_whitelist.json` in python-gardenlinux-lib* diff --git a/test-data/reproducibility/diff_files/one_issue.md b/test-data/reproducibility/diff_files/one_issue.md index 5c09d2ba..d5ae281d 100644 --- a/test-data/reproducibility/diff_files/one_issue.md +++ b/test-data/reproducibility/diff_files/one_issue.md @@ -9,7 +9,7 @@ | Affected Files | Flavors | Features Causing the Problem | |----------------|---------|------------------------------| -|`/etc/hostname`|**4.9%** affected
`container-amd64`
`container-arm64`
`container-pythonDev-amd64`
`container-pythonDev-arm64`|
container
| +|`/etc/hostname`|**4.9%** affected
`container-amd64`
`container-arm64`
`container-pythonDev-amd64`
`container-pythonDev-arm64`|
container:
_archgrouped
| |✅ No problems found|**95.1%**
ali-gardener_prod-amd64...`ali-gardener_prod-amd64`
`aws-gardener_fips_prod-amd64`
`aws-gardener_fips_prod-arm64`
`aws-gardener_prod-amd64`
`aws-gardener_prod-arm64`
`aws-gardener_prod_tpm2_trustedboot-amd64`
`aws-gardener_prod_tpm2_trustedboot-arm64`
`aws-gardener_prod_trustedboot-amd64`
`aws-gardener_prod_trustedboot-arm64`
`aws-gardener_prod_usi-amd64`
`aws-gardener_prod_usi-arm64`
`azure-gardener_prod-amd64`
`azure-gardener_prod-arm64`
`azure-gardener_prod_tpm2_trustedboot-amd64`
`azure-gardener_prod_tpm2_trustedboot-arm64`
`azure-gardener_prod_trustedboot-amd64`
`azure-gardener_prod_trustedboot-arm64`
`azure-gardener_prod_usi-amd64`
`azure-gardener_prod_usi-arm64`
`bare-libc-amd64`
`bare-libc-arm64`
`bare-nodejs-amd64`
`bare-nodejs-arm64`
`bare-python-amd64`
`bare-python-arm64`
`bare-sapmachine-amd64`
`bare-sapmachine-arm64`
`baremetal-capi-amd64`
`baremetal-capi-arm64`
`baremetal-gardener_prod-amd64`
`baremetal-gardener_prod-arm64`
`baremetal-gardener_prod_tpm2_trustedboot-amd64`
`baremetal-gardener_prod_tpm2_trustedboot-arm64`
`baremetal-gardener_prod_trustedboot-amd64`
`baremetal-gardener_prod_trustedboot-arm64`
`baremetal-gardener_prod_usi-amd64`
`baremetal-gardener_prod_usi-arm64`
`baremetal-gardener_pxe-amd64`
`baremetal-gardener_pxe-arm64`
`baremetal-vhost-amd64`
`baremetal-vhost-arm64`
`baremetal_pxe-amd64`
`baremetal_pxe-arm64`
`gcp-gardener_prod-amd64`
`gcp-gardener_prod-arm64`
`gcp-gardener_prod_tpm2_trustedboot-amd64`
`gcp-gardener_prod_tpm2_trustedboot-arm64`
`gcp-gardener_prod_trustedboot-amd64`
`gcp-gardener_prod_trustedboot-arm64`
`gcp-gardener_prod_usi-amd64`
`gcp-gardener_prod_usi-arm64`
`gdch-gardener_prod-amd64`
`gdch-gardener_prod-arm64`
`kvm-gardener_prod-amd64`
`kvm-gardener_prod-arm64`
`kvm-gardener_prod_tpm2_trustedboot-amd64`
`kvm-gardener_prod_tpm2_trustedboot-arm64`
`kvm-gardener_prod_trustedboot-amd64`
`kvm-gardener_prod_trustedboot-arm64`
`kvm-gardener_prod_usi-amd64`
`kvm-gardener_prod_usi-arm64`
`lima-amd64`
`lima-arm64`
`openstack-gardener_prod-amd64`
`openstack-gardener_prod-arm64`
`openstack-gardener_prod_tpm2_trustedboot-amd64`
`openstack-gardener_prod_tpm2_trustedboot-arm64`
`openstack-gardener_prod_trustedboot-amd64`
`openstack-gardener_prod_trustedboot-arm64`
`openstack-gardener_prod_usi-amd64`
`openstack-gardener_prod_usi-arm64`
`openstack-metal-gardener_prod-amd64`
`openstack-metal-gardener_prod-arm64`
`openstack-metal-gardener_prod_usi-amd64`
`openstack-metal-gardener_prod_usi-arm64`
`vmware-gardener_prod-amd64`
`vmware-gardener_prod-arm64`
|-| *To add affected files to the whitelist, edit `src/gardenlinux/features/reproducibility/nightly_whitelist.json` in python-gardenlinux-lib* diff --git a/tests/conftest.py b/tests/conftest.py index 093ad3dc..fcb3e4be 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -138,11 +138,16 @@ def zot_session() -> Generator[subprocess.Popen[Any]]: os.close(fd) zot_config = { - "distSpecVersion": "1.1.0", - "storage": {"rootDirectory": "output/registry/zot"}, + "distSpecVersion": "1.1.1", + "storage": { + "rootDirectory": "output/registry/zot", + "commit": True, + "gc": False, + }, "http": { "address": "127.0.0.1", "port": "18081", + "externalURL": "http://127.0.0.1:18081", "auth": {"htpasswd": {"path": f"{htpasswd_file}"}}, "accessControl": { "repositories": { diff --git a/tests/constants.py b/tests/constants.py index 6a2bd967..28a260b2 100644 --- a/tests/constants.py +++ b/tests/constants.py @@ -11,7 +11,7 @@ REGISTRY = "127.0.0.1:18081" REGISTRY_URL = f"http://{REGISTRY}" REPO_NAME = "gardenlinux-example" -CONTAINER_NAME_ZOT_EXAMPLE = f"{REGISTRY}/{REPO_NAME}" +REPOSITORY_NAME_ZOT_EXAMPLE = f"{REGISTRY}/{REPO_NAME}" GARDENLINUX_ROOT_DIR_EXAMPLE = f"{TEST_DATA_DIR}/gardenlinux/.build" TEST_PLATFORMS = ["aws", "azure", "baremetal", "gcp", "openstack"] diff --git a/tests/features/constants.py b/tests/features/constants.py index e99ac286..d92df8e9 100644 --- a/tests/features/constants.py +++ b/tests/features/constants.py @@ -7,25 +7,29 @@ ) -def generate_container_amd64_release_metadata(version: str, commit_hash: str) -> str: - return f""" +def generate_container_release_metadata( + version: str, commit_hash: str, arch: str = "amd64", variant: str = "" +) -> str: + metadata = f""" ID={GL_RELEASE_ID} ID_LIKE=debian NAME="{GL_DISTRIBUTION_NAME}" PRETTY_NAME="{GL_DISTRIBUTION_NAME} {version}" IMAGE_VERSION={version} -VARIANT_ID="container-amd64" +VARIANT_ID="container-{arch}" HOME_URL="{GL_HOME_URL}" SUPPORT_URL="{GL_SUPPORT_URL}" BUG_REPORT_URL="{GL_BUG_REPORT_URL}" -GARDENLINUX_CNAME="container-amd64-{version}-{commit_hash}" -GARDENLINUX_FEATURES="_slim,base,container" +GARDENLINUX_CNAME="container" +GARDENLINUX_FEATURES="_archgrouped,_slim,base,container" GARDENLINUX_FEATURES_PLATFORMS="container" GARDENLINUX_FEATURES_ELEMENTS="base" -GARDENLINUX_FEATURES_FLAGS="_slim" +GARDENLINUX_FEATURES_FLAGS="_archgrouped,_slim" GARDENLINUX_PLATFORM="container" -GARDENLINUX_PLATFORM_VARIANT="" +GARDENLINUX_PLATFORM_VARIANT="{variant}" GARDENLINUX_VERSION="{version}" GARDENLINUX_COMMIT_ID="{commit_hash}" GARDENLINUX_COMMIT_ID_LONG="{commit_hash}" -""".strip() +""" + + return metadata.strip() diff --git a/tests/features/test_cname.py b/tests/features/test_cname.py index 3d173844..13b13b95 100644 --- a/tests/features/test_cname.py +++ b/tests/features/test_cname.py @@ -19,12 +19,12 @@ "metal_pxe", ), ( - "container-amd64", + "container", "container", ), ], ) -def test_cname_flavor(input_cname: str, expected_output: str) -> None: +def test_cname(input_cname: str, expected_output: str) -> None: """ Tests if cname returns the dict with expected features. @@ -32,19 +32,6 @@ def test_cname_flavor(input_cname: str, expected_output: str) -> None: features have changed since writing this test. In this case, update the expected output accordingly. You can print the output of cname so you have the dict in the expected format. """ - cname = CName(input_cname) - assert cname.flavor == expected_output - - -def test_cname_commit_id_setter() -> None: - """ - Tests cname setter for `commit_id` to verify a given ID before overwriting. - """ - cname = CName("container", arch="amd64", version="today", commit_hash="local") - - # Act / Assert - with pytest.raises( - RuntimeError, match="Commit hash given differs from commit ID already set" - ): - cname.commit_hash = "broken" + cname = CName(input_cname) + assert str(cname) == expected_output diff --git a/tests/features/test_cname_main.py b/tests/features/test_cname_main.py deleted file mode 100644 index 5a40c5fb..00000000 --- a/tests/features/test_cname_main.py +++ /dev/null @@ -1,159 +0,0 @@ -import logging -import sys -import types -from typing import Any, List, Tuple - -import networkx -import pytest - -import gardenlinux.features.cname_main as cname_main -from gardenlinux.features import Parser - - -def test_main_happy( - monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str] -) -> None: - """ - Test the "Happy Path" of the main() function. - """ - # Arrange - argv = ["prog", "--arch", "amd64", "--version", "1.0-abc123", "flav-amd64"] - monkeypatch.setattr(sys, "argv", argv) - - class FakeGraph: - def in_degree(self) -> List[Tuple[str, int]]: - return [("f1", 0)] - - edges = [("f1", "f2")] - - class FakeParser(Parser): - def __init__(self, *a: Any, **k: Any): - pass - - def filter(self, *a: Any, **k: Any) -> networkx.Graph: - return FakeGraph() - - @staticmethod - def sort_graph_nodes(graph: networkx.Graph) -> List[str]: - return ["f1", "f2"] - - monkeypatch.setattr(cname_main, "Parser", FakeParser) - - # Act - cname_main.main() - - # Assert - out = capsys.readouterr().out - assert "f1" in out - assert "amd64" in out - - -def test_main_version_from_file( - monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str] -) -> None: - """ - "Happy Path" test for grabbing the version and commit id from file in main(). - """ - # Arrange - argv = ["prog", "--arch", "amd64", "flav-amd64"] - monkeypatch.setattr(sys, "argv", argv) - - monkeypatch.setattr( - cname_main, - "get_version_and_commit_id_from_files", - lambda root: ("2.0", "abcdef12"), - ) - - class FakeParser(Parser): - def __init__(self, *a: Any, **k: Any): - pass - - def filter(self, *a: Any, **k: Any) -> networkx.Graph: - return types.SimpleNamespace(in_degree=lambda: [("f1", 0)], edges=[]) - - @staticmethod - def sort_graph_nodes(graph: networkx.Graph) -> List[str]: - return ["f1"] - - monkeypatch.setattr(cname_main, "Parser", FakeParser) - - # Act - cname_main.main() - - # Assert - assert "2.0-abcdef12" in capsys.readouterr().out - - -def test_cname_main_version_file_missing_warns( - monkeypatch: pytest.MonkeyPatch, caplog: pytest.LogCaptureFixture -) -> None: - """ - Check if a warning is logged when it fails to read version and commit id files. - - Specifically, this test simulates a scenario where the helper function - `get_version_and_commit_id_from_files` raises a RuntimeError, which would occur - if the expected version or commit files are missing or unreadable. - """ - # Arrange - argv = ["prog", "--arch", "amd64", "flav-amd64"] - monkeypatch.setattr(sys, "argv", argv) - - # Patch version fatch function to raise RuntimeError (Simulates missing files) - def raise_runtime(*args: Any, **kwargs: Any) -> None: - raise RuntimeError("missing") - - monkeypatch.setattr( - cname_main, "get_version_and_commit_id_from_files", raise_runtime - ) - - # Patch Parser for minimal valid graph - class FakeParser(Parser): - def __init__(self, *a: Any, **k: Any): - pass - - # Return object with in_degree method returning a node with zero dependencies - def filter(self, *a: Any, **k: Any) -> networkx.Graph: - return types.SimpleNamespace(in_degree=lambda: [("f1", 0)], edges=[]) - - @staticmethod - def sort_graph_nodes(graph: networkx.Graph) -> List[str]: - return ["f1"] - - monkeypatch.setattr(cname_main, "Parser", FakeParser) - - # Capture any logs with WARNING level - caplog.set_level(logging.WARNING) - - # Act - cname_main.main() - - # Assert - assert "Failed to parse version information" in caplog.text - - -def test_cname_main_invalid_cname_raises(monkeypatch: pytest.MonkeyPatch) -> None: - """ - Test if AssertionError is raised with an invalid or malformed cname. - """ - # Arrange - argv = ["prog", "--arch", "amd64", "--version", "1.0", "INVALID@NAME"] - monkeypatch.setattr(sys, "argv", argv) - - # Act / Assert - with pytest.raises(AssertionError): - cname_main.main() - - -def test_cname_main_missing_arch_in_cname_raises( - monkeypatch: pytest.MonkeyPatch, -) -> None: - """ - Test if an assertion error is raised when the arch argument is missing. - """ - # Arrange - argv = ["prog", "--version", "1.0", "flav"] - monkeypatch.setattr(sys, "argv", argv) - - # Act / Assert - with pytest.raises(AssertionError): - cname_main.main() diff --git a/tests/features/test_main.py b/tests/features/test_main.py index a0df4326..cdac5e58 100644 --- a/tests/features/test_main.py +++ b/tests/features/test_main.py @@ -1,16 +1,14 @@ import sys -import types from pathlib import Path -from tempfile import TemporaryDirectory -from typing import Any, List, Tuple +from typing import List, Optional import pytest import gardenlinux.features.__main__ as fema -from gardenlinux.features import CName +from gardenlinux.features import ArtifactBaseName from ..constants import GL_ROOT_DIR -from .constants import generate_container_amd64_release_metadata +from .constants import generate_container_release_metadata # ------------------------------- # Helper function tests @@ -40,26 +38,11 @@ class MockGraph: # Act / Assert with pytest.raises( - RuntimeError, match="Error while generating graph: Flavor is None!" + RuntimeError, match="Error while generating graph: CName is None!" ): fema.graph_as_mermaid_markup(None, MockGraph()) -def test_get_minimal_feature_set_filters() -> None: - # Arrange - class FakeGraph: - def in_degree(self) -> List[Tuple[str, int]]: - return [("a", 0), ("b", 1), ("c", 0)] - - graph = FakeGraph() - - # Act - result = fema.get_minimal_feature_set(graph) - - # Assert - assert result == {"a", "c"} - - def test_get_version_and_commit_from_file(tmp_path: Path) -> None: # Arrange commit_file = tmp_path / "COMMIT" @@ -68,191 +51,463 @@ def test_get_version_and_commit_from_file(tmp_path: Path) -> None: version_file.write_text("1.2.3\n") # Act - version, commit = fema.get_version_and_commit_id_from_files(str(tmp_path)) + version, commit = ArtifactBaseName.get_version_and_commit_id_from_files( + str(tmp_path) + ) # Arrange assert version == "1.2.3" assert commit == "abcdef12" -def test_get_version_missing_file_raises(tmp_path: Path) -> None: - # Arrange (one file only) - (tmp_path / "COMMIT").write_text("abcdef1234\n") - - # Act / Assert - with pytest.raises(RuntimeError): - fema.get_version_and_commit_id_from_files(str(tmp_path)) - - # ------------------------------- # Tests for main() # ------------------------------- -def test_main_prints_arch( - monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str] -) -> None: - # Arrange - argv = ["prog", "--arch", "amd64", "--cname", "flav", "--version", "1.0", "arch"] - monkeypatch.setattr(sys, "argv", argv) - monkeypatch.setattr(fema, "Parser", lambda *a, **kw: None) - # Act - fema.main() - # Assert - out = capsys.readouterr().out - assert "amd64" in out - - -def test_main_prints_container_name( - monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str] +@pytest.mark.parametrize( + "input_argv, monkeypatch_version, release_metadata, ignored_features, expected_output", + [ + ( + [ + "--arch", + "amd64", + "--cname", + "flav", + "--version", + "1.0", + "--commit", + "local", + "arch", + ], + False, + None, + "", + "amd64", + ), + ( + [ + "--arch", + "arm64", + "--cname", + "container", + "--version", + "today", + "--commit", + "local", + "arch", + ], + False, + generate_container_release_metadata("today", "local", "arm64"), + "", + "arm64", + ), + ( + [ + "--arch", + "amd64", + "--cname", + "container-pythonDev", + "artifact-base-name", + ], + True, + None, + "", + "container-pythonDev-amd64-1.2.3-abcdef12", + ), + ( + [ + "--arch", + "amd64", + "--cname", + "container", + "--version", + "today", + "--commit", + "local", + "artifact-base-name", + ], + False, + generate_container_release_metadata("today", "local"), + "", + "container-amd64-today-local", + ), + ( + [ + "--arch", + "amd64", + "--cname", + "container-pythonDev", + "artifact-base-name", + ], + True, + None, + "_archgrouped", + "container-pythonDev-amd64-1.2.3-abcdef12", + ), + ( + ["--arch", "amd64", "--cname", "flav", "cname"], + True, + None, + "", + "flav", + ), + ( + [ + "--arch", + "amd64", + "--cname", + "container", + "--version", + "today", + "--commit", + "local", + "cname", + ], + False, + generate_container_release_metadata("today", "local"), + "", + "container", + ), + ( + ["--arch", "amd64", "--cname", "flav", "commit-id"], + True, + None, + "", + "abcdef12", + ), + ( + [ + "--arch", + "amd64", + "--cname", + "container", + "--version", + "today", + "--commit", + "local", + "commit-id", + ], + False, + generate_container_release_metadata("today", "local"), + "", + "local", + ), + ( + [ + "--arch", + "amd64", + "--cname", + "container-pythonDev", + "--version", + "1.0", + "--commit", + "local", + "container-name", + ], + True, + None, + "", + "container-python-dev", + ), + ( + [ + "--arch", + "amd64", + "--cname", + "flav", + "--version", + "1.0", + "--commit", + "post1", + "container-tag", + ], + False, + None, + "", + "1-0-post1", + ), + ( + ["--arch", "amd64", "--cname", "container-pythonDev", "elements"], + True, + None, + "", + "python,pythonDev,base", + ), + ( + [ + "--arch", + "amd64", + "--cname", + "container", + "--version", + "today", + "--commit", + "local", + "elements", + ], + False, + generate_container_release_metadata("today", "local"), + "", + "base", + ), + ( + ["--arch", "amd64", "--cname", "container-pythonDev", "features"], + True, + None, + "", + "python,pythonDev,_archgrouped,_slim,base,container", + ), + ( + ["--arch", "amd64", "--cname", "container-pythonDev", "features"], + True, + None, + "_archgrouped", + "python,pythonDev,_slim,base,container", + ), + ( + [ + "--arch", + "amd64", + "--cname", + "container", + "--version", + "today", + "--commit", + "local", + "features", + ], + False, + generate_container_release_metadata("today", "local"), + "", + "_archgrouped,_slim,base,container", + ), + ( + [ + "--arch", + "amd64", + "--cname", + "container", + "--version", + "today", + "--commit", + "local", + "features", + ], + False, + generate_container_release_metadata("today", "local"), + "_archgrouped", + "_slim,base,container", + ), + ( + ["--arch", "amd64", "--cname", "container-pythonDev", "flags"], + True, + None, + "", + "_archgrouped,_slim", + ), + ( + ["--arch", "amd64", "--cname", "container-pythonDev", "flags"], + True, + None, + "_archgrouped", + "_slim", + ), + ( + [ + "--arch", + "amd64", + "--cname", + "container", + "--version", + "today", + "--commit", + "local", + "flags", + ], + False, + generate_container_release_metadata("today", "local"), + "", + "_archgrouped,_slim", + ), + ( + ["--arch", "amd64", "--cname", "container-pythonDev", "flavor"], + True, + None, + "", + "container-pythonDev-amd64", + ), + ( + ["--arch", "amd64", "--cname", "container-pythonDev", "platform"], + True, + None, + "", + "container", + ), + ( + [ + "--arch", + "amd64", + "--cname", + "container", + "--version", + "today", + "--commit", + "local", + "platform", + ], + False, + generate_container_release_metadata( + "today", "local", variant="magicMachine" + ), + "", + "container", + ), + ( + ["--arch", "amd64", "--cname", "container-pythonDev", "platforms"], + True, + None, + "", + "container", + ), + ( + [ + "--arch", + "amd64", + "--cname", + "container", + "--version", + "today", + "--commit", + "local", + "platform-variant", + ], + False, + generate_container_release_metadata( + "today", "local", variant="magicMachine" + ), + "", + "magicMachine", + ), + ( + ["--arch", "amd64", "--cname", "container-pythonDev", "version"], + True, + None, + "", + "1.2.3", + ), + ( + [ + "--arch", + "amd64", + "--cname", + "container-pythonDev", + "version_and_commit-id", + ], + True, + None, + "", + "1.2.3-abcdef12", + ), + ( + [ + "--arch", + "amd64", + "--cname", + "container", + "version_and_commit-id", + ], + True, + generate_container_release_metadata("1.2.3", "abcdef12"), + "", + "1.2.3-abcdef12", + ), + ( + ["--arch", "amd64", "--cname", "container-pythonDev", "versioned-flavor"], + True, + None, + "", + "container-pythonDev-amd64-1.2.3", + ), + ], +) +def test_main_prints_result( + input_argv: List[str], + monkeypatch_version: bool, + release_metadata: Optional[str], + ignored_features: Optional[str], + expected_output: str, + monkeypatch: pytest.MonkeyPatch, + capsys: pytest.CaptureFixture[str], + tmp_path: Path, ) -> None: # Arrange argv = [ - "prog", - "--arch", - "amd64", - "--cname", - "container-pythonDev", - "--version", - "1.0", - "container_name", - ] - monkeypatch.setattr(sys, "argv", argv) - monkeypatch.setattr(fema, "Parser", lambda *a, **kw: None) - - # Act - fema.main() - - # Assert - out = capsys.readouterr().out - assert "container-python-dev" in out + "gl-feature-parse", + "--feature-dir", + f"{GL_ROOT_DIR}/features", + ] + input_argv + if release_metadata: + os_release_file = Path(tmp_path, "os_release") -def test_main_prints_container_tag( - monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str] -) -> None: - # Arrange - argv = [ - "prog", - "--arch", - "amd64", - "--cname", - "flav", - "--version", - "1.0", - "--commit", - "~post1", - "container_tag", - ] - monkeypatch.setattr(sys, "argv", argv) - monkeypatch.setattr(fema, "Parser", lambda *a, **kw: None) - - # Act - fema.main() + with os_release_file.open("w") as fp: + fp.write(release_metadata) - # Assert - out = capsys.readouterr().out.strip() - assert "1-0-post1" == out + argv += [ + "--release-file", + str(os_release_file), + ] + if ignored_features: + argv += [ + "--ignore", + str(ignored_features), + ] -def test_main_prints_commit_id( - monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str] -) -> None: - # Arrange - argv = ["prog", "--arch", "amd64", "--cname", "flav", "commit_id"] monkeypatch.setattr(sys, "argv", argv) - monkeypatch.setattr( - fema, - "Parser", - lambda *a, **kw: types.SimpleNamespace(filter=lambda *a, **k: None), - ) - # Patch get_version_and_commit_id_from_files - monkeypatch.setattr( - fema, "get_version_and_commit_id_from_files", lambda root: ("1.2.3", "abcdef12") - ) + # monkeypatch.setattr(fema, "Parser", lambda *a, **kw: None) + + if monkeypatch_version: + monkeypatch.setattr( + "gardenlinux.features.artifact_base_name.ArtifactBaseName.get_version_and_commit_id_from_files", + lambda root: ("1.2.3", "abcdef12"), + ) # Act fema.main() + # Assert captured = capsys.readouterr() - assert "abcdef12" == captured.out.strip() + assert captured.out.strip() == expected_output -def test_main_prints_flags_elements_platforms( - monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str] +def test_get_version_missing_file_raises( + monkeypatch: pytest.MonkeyPatch, tmp_path: Path ) -> None: - # Arrange + # Arrange (one file only) + (tmp_path / "COMMIT").write_text("abcdef1234\n") + argv = [ "prog", "--arch", "amd64", "--cname", "flav", - "--version", - "1.0", - "flags", + "version", ] - monkeypatch.setattr(sys, "argv", argv) - - class FakeCName(CName): - def __init__(self, *a: Any, **k: Any): - CName.__init__(self, *a, **k) - self._feature_flags_cached = ["flag1"] - monkeypatch.setattr(fema, "CName", FakeCName) - - # Act - fema.main() - - # Assert - out = capsys.readouterr().out - assert "flag1" in out - - -def test_main_prints_version( - monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str] -) -> None: - # Arrange - argv = ["prog", "--arch", "amd64", "--cname", "flav", "version"] monkeypatch.setattr(sys, "argv", argv) - monkeypatch.setattr( - fema, - "Parser", - lambda *a, **kw: types.SimpleNamespace(filter=lambda *a, **k: None), - ) - # Patch get_version_and_commit_id_from_files - monkeypatch.setattr( - fema, "get_version_and_commit_id_from_files", lambda root: ("1.2.3", "abcdef12") - ) - - # Act - fema.main() - - captured = capsys.readouterr() - assert "1.2.3" == captured.out.strip() - + monkeypatch.setattr(fema, "Parser", lambda *a, **kw: None) -def test_main_prints_version_and_commit_id( - monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str] -) -> None: - # Arrange - argv = ["prog", "--arch", "amd64", "--cname", "flav", "version_and_commit_id"] - monkeypatch.setattr(sys, "argv", argv) - monkeypatch.setattr( - fema, - "Parser", - lambda *a, **kw: types.SimpleNamespace(filter=lambda *a, **k: None), - ) - # Patch get_version_and_commit_id_from_files - monkeypatch.setattr( - fema, "get_version_and_commit_id_from_files", lambda root: ("1.2.3", "abcdef12") + # Act / Assert + assert ArtifactBaseName.get_version_and_commit_id_from_files(str(tmp_path)) == ( + None, + None, ) - # Act - fema.main() - - captured = capsys.readouterr() - assert "1.2.3-abcdef12" == captured.out.strip() + with pytest.raises(ValueError, match="Argument missing: version"): + fema.main() def test_main_requires_cname(monkeypatch: pytest.MonkeyPatch) -> None: @@ -261,7 +516,10 @@ def test_main_requires_cname(monkeypatch: pytest.MonkeyPatch) -> None: monkeypatch.setattr(fema, "Parser", lambda *a, **kw: None) # Act / Assert - with pytest.raises(SystemExit): + with pytest.raises( + ValueError, + match="Argument missing: At least one of artifact_base_name, cname, flavor or versioned_flavor", + ): fema.main() @@ -272,7 +530,7 @@ def test_main_cname_raises_missing_commit_id(monkeypatch: pytest.MonkeyPatch) -> "prog", "--cname", "flav", - "--default-arch", + "--arch", "amd64", "--version", "1.0", @@ -281,7 +539,7 @@ def test_main_cname_raises_missing_commit_id(monkeypatch: pytest.MonkeyPatch) -> monkeypatch.setattr(sys, "argv", argv) # Act / Assert - with pytest.raises(RuntimeError, match="Version and commit ID"): + with pytest.raises(ValueError, match="Argument missing: version"): fema.main() @@ -292,7 +550,7 @@ def test_main_raises_no_arch_no_default(monkeypatch: pytest.MonkeyPatch) -> None monkeypatch.setattr(sys, "argv", argv) # Act / Assert - with pytest.raises(RuntimeError, match="Architecture could not be determined"): + with pytest.raises(ValueError, match="Argument missing: arch"): fema.main() @@ -308,13 +566,13 @@ def test_main_raises_missing_commit_id( "flav", "--version", "1.0", - "version_and_commit_id", + "version_and_commit-id", ] monkeypatch.setattr(sys, "argv", argv) monkeypatch.setattr(fema, "Parser", lambda *a, **kw: None) # Act / Assert - with pytest.raises(RuntimeError, match="Commit ID not specified"): + with pytest.raises(ValueError, match="Argument missing: version"): fema.main() @@ -387,34 +645,3 @@ def test_main_with_exclude_cname_print_features( "sap,ssh,_fwcfg,_ignite,_legacy,_nopkg,_prod,_slim,base,server,cloud,kvm,multipath,iscsi,nvme,gardener" == captured ) - - -def test_cname_release_file( - monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str] -) -> None: - """ - Test validation between release metadata and arguments given - """ - # Arrange - with TemporaryDirectory() as tmpdir: - os_release_file = Path(tmpdir, "os_release") - - with os_release_file.open("w") as fp: - fp.write(generate_container_amd64_release_metadata("today", "local")) - - argv = [ - "prog", - "--cname", - "container-amd64-today-local", - "--release-file", - str(os_release_file), - "cname", - ] - monkeypatch.setattr(sys, "argv", argv) - - # Act / Assert - fema.main() - - # Assert - out = capsys.readouterr().out - assert "container-amd64-today-local" in out diff --git a/tests/features/test_metadata_main.py b/tests/features/test_metadata_main.py index b8f0fc69..9487c269 100644 --- a/tests/features/test_metadata_main.py +++ b/tests/features/test_metadata_main.py @@ -6,7 +6,7 @@ import gardenlinux.features.metadata_main as metadata_main -from .constants import generate_container_amd64_release_metadata +from .constants import generate_container_release_metadata def test_main_output( @@ -18,7 +18,7 @@ def test_main_output( # Arrange argv = [ "prog", - "--cname", + "--flavor", "container-amd64", "--version", "today", @@ -32,8 +32,8 @@ def test_main_output( metadata_main.main() # Assert - expected = generate_container_amd64_release_metadata("today", "local") - assert expected == capsys.readouterr().out.strip() + expected = generate_container_release_metadata("today", "local") + assert capsys.readouterr().out.strip() == expected def test_main_write( @@ -47,7 +47,7 @@ def test_main_write( os_release_file = Path(tmpdir, "os_release") argv = [ "prog", - "--cname", + "--flavor", "container-amd64", "--version", "today", @@ -63,35 +63,60 @@ def test_main_write( metadata_main.main() # Assert - expected = generate_container_amd64_release_metadata("today", "local") + expected = generate_container_release_metadata("today", "local") assert expected == os_release_file.open("r").read() -def test_main_validation(monkeypatch: pytest.MonkeyPatch) -> None: +def test_main_validation(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> None: """ Test validation between release metadata and arguments given """ # Arrange - with TemporaryDirectory() as tmpdir: - os_release_file = Path(tmpdir, "os_release") + os_release_file = Path(tmp_path, "os_release") - with os_release_file.open("w") as fp: - fp.write(generate_container_amd64_release_metadata("today", "local")) + with os_release_file.open("w") as fp: + fp.write(generate_container_release_metadata("today", "local")) - argv = [ - "prog", - "--cname", - "base-python-amd64", - "--version", - "today", - "--commit", - "local", - "--release-file", - str(os_release_file), - "output-release-metadata", - ] - monkeypatch.setattr(sys, "argv", argv) + argv = [ + "prog", + "--flavor", + "base-python-amd64", + "--version", + "today", + "--commit", + "local", + "--release-file", + str(os_release_file), + "output-release-metadata", + ] + monkeypatch.setattr(sys, "argv", argv) + + # Act / Assert + with pytest.raises(RuntimeError): + metadata_main.main() + + +def test_main_version_missing_file_raises( + monkeypatch: pytest.MonkeyPatch, tmp_path: Path +) -> None: + # Arrange + (tmp_path / "COMMIT").write_text("abcdef1234\n") - # Act / Assert - with pytest.raises(RuntimeError): - metadata_main.main() + os_release_file = Path(tmp_path, "os_release") + + with os_release_file.open("w") as fp: + fp.write(generate_container_release_metadata("today", "local")) + + argv = [ + "prog", + "--flavor", + "base-python-amd64", + "--release-file", + str(os_release_file), + "output-release-metadata", + ] + monkeypatch.setattr(sys, "argv", argv) + + # Act / Assert + with pytest.raises(ValueError, match="Argument missing: version"): + metadata_main.main() diff --git a/tests/features/test_parser.py b/tests/features/test_parser.py index 7bb49fe3..adb9ffa0 100644 --- a/tests/features/test_parser.py +++ b/tests/features/test_parser.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, List +from typing import Any, Dict, List, Tuple import pytest @@ -132,21 +132,36 @@ def test_parser_return_intersection_subset() -> None: assert result == ["a", "c"] -def test_get_flavor_from_feature_set() -> None: +def test_get_cname_from_feature_set() -> None: # Arrange sorted_features = ["base", "_hidden", "extra"] # Act - result = Parser.get_flavor_from_feature_set(sorted_features) + result = Parser.get_cname_from_feature_set(sorted_features) # Assert - assert result == "base_hidden-extra" + assert result == "base-extra_hidden" -def test_gget_flavor_from_feature_set_empty_raises() -> None: +def test_get_cname_from_feature_set_empty_raises() -> None: # get_flavor with empty iterable raises TypeError - with pytest.raises(TypeError): - Parser.get_flavor_from_feature_set([]) + with pytest.raises(ValueError): + Parser.get_cname_from_feature_set([]) + + +def test_get_minimal_feature_set_filters() -> None: + # Arrange + class FakeGraph: + def in_degree(self) -> List[Tuple[str, int]]: + return [("a", 0), ("b", 1), ("c", 0)] + + graph = FakeGraph() + + # Act + result = Parser.get_minimal_feature_set(graph) + + # Assert + assert result == {"a", "c"} def test_parser_subset_nomatch() -> None: diff --git a/tests/features/test_reproducibility.py b/tests/features/test_reproducibility.py index 7cc5cdd2..0a99d466 100644 --- a/tests/features/test_reproducibility.py +++ b/tests/features/test_reproducibility.py @@ -8,94 +8,94 @@ from gardenlinux.features.reproducibility.comparator import Comparator from gardenlinux.features.reproducibility.markdown_formatter import MarkdownFormatter -FLAVORS_MATRIX = { +CNAMES_MATRIX = { "include": [ - {"arch": "amd64", "flavor": "ali-gardener_prod"}, - {"arch": "amd64", "flavor": "aws-gardener_fips_prod"}, - {"arch": "amd64", "flavor": "aws-gardener_prod"}, - {"arch": "amd64", "flavor": "aws-gardener_prod_tpm2_trustedboot"}, - {"arch": "amd64", "flavor": "aws-gardener_prod_trustedboot"}, - {"arch": "amd64", "flavor": "aws-gardener_prod_usi"}, - {"arch": "amd64", "flavor": "azure-gardener_prod"}, - {"arch": "amd64", "flavor": "azure-gardener_prod_tpm2_trustedboot"}, - {"arch": "amd64", "flavor": "azure-gardener_prod_trustedboot"}, - {"arch": "amd64", "flavor": "azure-gardener_prod_usi"}, - {"arch": "amd64", "flavor": "baremetal-capi"}, - {"arch": "amd64", "flavor": "baremetal-gardener_prod"}, - {"arch": "amd64", "flavor": "baremetal-gardener_prod_tpm2_trustedboot"}, - {"arch": "amd64", "flavor": "baremetal-gardener_prod_trustedboot"}, - {"arch": "amd64", "flavor": "baremetal-gardener_prod_usi"}, - {"arch": "amd64", "flavor": "baremetal-gardener_pxe"}, - {"arch": "amd64", "flavor": "baremetal-vhost"}, - {"arch": "amd64", "flavor": "baremetal_pxe"}, - {"arch": "amd64", "flavor": "container"}, - {"arch": "amd64", "flavor": "container-pythonDev"}, - {"arch": "amd64", "flavor": "gcp-gardener_prod"}, - {"arch": "amd64", "flavor": "gcp-gardener_prod_tpm2_trustedboot"}, - {"arch": "amd64", "flavor": "gcp-gardener_prod_trustedboot"}, - {"arch": "amd64", "flavor": "gcp-gardener_prod_usi"}, - {"arch": "amd64", "flavor": "gdch-gardener_prod"}, - {"arch": "amd64", "flavor": "kvm-gardener_prod"}, - {"arch": "amd64", "flavor": "kvm-gardener_prod_tpm2_trustedboot"}, - {"arch": "amd64", "flavor": "kvm-gardener_prod_trustedboot"}, - {"arch": "amd64", "flavor": "kvm-gardener_prod_usi"}, - {"arch": "amd64", "flavor": "lima"}, - {"arch": "amd64", "flavor": "openstack-gardener_prod"}, - {"arch": "amd64", "flavor": "openstack-gardener_prod_tpm2_trustedboot"}, - {"arch": "amd64", "flavor": "openstack-gardener_prod_trustedboot"}, - {"arch": "amd64", "flavor": "openstack-gardener_prod_usi"}, - {"arch": "amd64", "flavor": "openstack-metal-gardener_prod"}, - {"arch": "amd64", "flavor": "openstack-metal-gardener_prod_usi"}, - {"arch": "amd64", "flavor": "vmware-gardener_prod"}, - {"arch": "arm64", "flavor": "aws-gardener_fips_prod"}, - {"arch": "arm64", "flavor": "aws-gardener_prod"}, - {"arch": "arm64", "flavor": "aws-gardener_prod_tpm2_trustedboot"}, - {"arch": "arm64", "flavor": "aws-gardener_prod_trustedboot"}, - {"arch": "arm64", "flavor": "aws-gardener_prod_usi"}, - {"arch": "arm64", "flavor": "azure-gardener_prod"}, - {"arch": "arm64", "flavor": "azure-gardener_prod_tpm2_trustedboot"}, - {"arch": "arm64", "flavor": "azure-gardener_prod_trustedboot"}, - {"arch": "arm64", "flavor": "azure-gardener_prod_usi"}, - {"arch": "arm64", "flavor": "baremetal-capi"}, - {"arch": "arm64", "flavor": "baremetal-gardener_prod"}, - {"arch": "arm64", "flavor": "baremetal-gardener_prod_tpm2_trustedboot"}, - {"arch": "arm64", "flavor": "baremetal-gardener_prod_trustedboot"}, - {"arch": "arm64", "flavor": "baremetal-gardener_prod_usi"}, - {"arch": "arm64", "flavor": "baremetal-gardener_pxe"}, - {"arch": "arm64", "flavor": "baremetal-vhost"}, - {"arch": "arm64", "flavor": "baremetal_pxe"}, - {"arch": "arm64", "flavor": "container"}, - {"arch": "arm64", "flavor": "container-pythonDev"}, - {"arch": "arm64", "flavor": "gcp-gardener_prod"}, - {"arch": "arm64", "flavor": "gcp-gardener_prod_tpm2_trustedboot"}, - {"arch": "arm64", "flavor": "gcp-gardener_prod_trustedboot"}, - {"arch": "arm64", "flavor": "gcp-gardener_prod_usi"}, - {"arch": "arm64", "flavor": "gdch-gardener_prod"}, - {"arch": "arm64", "flavor": "kvm-gardener_prod"}, - {"arch": "arm64", "flavor": "kvm-gardener_prod_tpm2_trustedboot"}, - {"arch": "arm64", "flavor": "kvm-gardener_prod_trustedboot"}, - {"arch": "arm64", "flavor": "kvm-gardener_prod_usi"}, - {"arch": "arm64", "flavor": "lima"}, - {"arch": "arm64", "flavor": "openstack-gardener_prod"}, - {"arch": "arm64", "flavor": "openstack-gardener_prod_tpm2_trustedboot"}, - {"arch": "arm64", "flavor": "openstack-gardener_prod_trustedboot"}, - {"arch": "arm64", "flavor": "openstack-gardener_prod_usi"}, - {"arch": "arm64", "flavor": "openstack-metal-gardener_prod"}, - {"arch": "arm64", "flavor": "openstack-metal-gardener_prod_usi"}, - {"arch": "arm64", "flavor": "vmware-gardener_prod"}, + {"arch": "amd64", "cname": "ali-gardener_prod"}, + {"arch": "amd64", "cname": "aws-gardener_fips_prod"}, + {"arch": "amd64", "cname": "aws-gardener_prod"}, + {"arch": "amd64", "cname": "aws-gardener_prod_tpm2_trustedboot"}, + {"arch": "amd64", "cname": "aws-gardener_prod_trustedboot"}, + {"arch": "amd64", "cname": "aws-gardener_prod_usi"}, + {"arch": "amd64", "cname": "azure-gardener_prod"}, + {"arch": "amd64", "cname": "azure-gardener_prod_tpm2_trustedboot"}, + {"arch": "amd64", "cname": "azure-gardener_prod_trustedboot"}, + {"arch": "amd64", "cname": "azure-gardener_prod_usi"}, + {"arch": "amd64", "cname": "baremetal-capi"}, + {"arch": "amd64", "cname": "baremetal-gardener_prod"}, + {"arch": "amd64", "cname": "baremetal-gardener_prod_tpm2_trustedboot"}, + {"arch": "amd64", "cname": "baremetal-gardener_prod_trustedboot"}, + {"arch": "amd64", "cname": "baremetal-gardener_prod_usi"}, + {"arch": "amd64", "cname": "baremetal-gardener_pxe"}, + {"arch": "amd64", "cname": "baremetal-vhost"}, + {"arch": "amd64", "cname": "baremetal_pxe"}, + {"arch": "amd64", "cname": "container"}, + {"arch": "amd64", "cname": "container-pythonDev"}, + {"arch": "amd64", "cname": "gcp-gardener_prod"}, + {"arch": "amd64", "cname": "gcp-gardener_prod_tpm2_trustedboot"}, + {"arch": "amd64", "cname": "gcp-gardener_prod_trustedboot"}, + {"arch": "amd64", "cname": "gcp-gardener_prod_usi"}, + {"arch": "amd64", "cname": "gdch-gardener_prod"}, + {"arch": "amd64", "cname": "kvm-gardener_prod"}, + {"arch": "amd64", "cname": "kvm-gardener_prod_tpm2_trustedboot"}, + {"arch": "amd64", "cname": "kvm-gardener_prod_trustedboot"}, + {"arch": "amd64", "cname": "kvm-gardener_prod_usi"}, + {"arch": "amd64", "cname": "lima"}, + {"arch": "amd64", "cname": "openstack-gardener_prod"}, + {"arch": "amd64", "cname": "openstack-gardener_prod_tpm2_trustedboot"}, + {"arch": "amd64", "cname": "openstack-gardener_prod_trustedboot"}, + {"arch": "amd64", "cname": "openstack-gardener_prod_usi"}, + {"arch": "amd64", "cname": "openstack-metal-gardener_prod"}, + {"arch": "amd64", "cname": "openstack-metal-gardener_prod_usi"}, + {"arch": "amd64", "cname": "vmware-gardener_prod"}, + {"arch": "arm64", "cname": "aws-gardener_fips_prod"}, + {"arch": "arm64", "cname": "aws-gardener_prod"}, + {"arch": "arm64", "cname": "aws-gardener_prod_tpm2_trustedboot"}, + {"arch": "arm64", "cname": "aws-gardener_prod_trustedboot"}, + {"arch": "arm64", "cname": "aws-gardener_prod_usi"}, + {"arch": "arm64", "cname": "azure-gardener_prod"}, + {"arch": "arm64", "cname": "azure-gardener_prod_tpm2_trustedboot"}, + {"arch": "arm64", "cname": "azure-gardener_prod_trustedboot"}, + {"arch": "arm64", "cname": "azure-gardener_prod_usi"}, + {"arch": "arm64", "cname": "baremetal-capi"}, + {"arch": "arm64", "cname": "baremetal-gardener_prod"}, + {"arch": "arm64", "cname": "baremetal-gardener_prod_tpm2_trustedboot"}, + {"arch": "arm64", "cname": "baremetal-gardener_prod_trustedboot"}, + {"arch": "arm64", "cname": "baremetal-gardener_prod_usi"}, + {"arch": "arm64", "cname": "baremetal-gardener_pxe"}, + {"arch": "arm64", "cname": "baremetal-vhost"}, + {"arch": "arm64", "cname": "baremetal_pxe"}, + {"arch": "arm64", "cname": "container"}, + {"arch": "arm64", "cname": "container-pythonDev"}, + {"arch": "arm64", "cname": "gcp-gardener_prod"}, + {"arch": "arm64", "cname": "gcp-gardener_prod_tpm2_trustedboot"}, + {"arch": "arm64", "cname": "gcp-gardener_prod_trustedboot"}, + {"arch": "arm64", "cname": "gcp-gardener_prod_usi"}, + {"arch": "arm64", "cname": "gdch-gardener_prod"}, + {"arch": "arm64", "cname": "kvm-gardener_prod"}, + {"arch": "arm64", "cname": "kvm-gardener_prod_tpm2_trustedboot"}, + {"arch": "arm64", "cname": "kvm-gardener_prod_trustedboot"}, + {"arch": "arm64", "cname": "kvm-gardener_prod_usi"}, + {"arch": "arm64", "cname": "lima"}, + {"arch": "arm64", "cname": "openstack-gardener_prod"}, + {"arch": "arm64", "cname": "openstack-gardener_prod_tpm2_trustedboot"}, + {"arch": "arm64", "cname": "openstack-gardener_prod_trustedboot"}, + {"arch": "arm64", "cname": "openstack-gardener_prod_usi"}, + {"arch": "arm64", "cname": "openstack-metal-gardener_prod"}, + {"arch": "arm64", "cname": "openstack-metal-gardener_prod_usi"}, + {"arch": "arm64", "cname": "vmware-gardener_prod"}, ] } -BARE_FLAVORS_MATRIX = { +BARE_CNAMES_MATRIX = { "include": [ - {"arch": "amd64", "flavor": "bare-libc"}, - {"arch": "amd64", "flavor": "bare-nodejs"}, - {"arch": "amd64", "flavor": "bare-python"}, - {"arch": "amd64", "flavor": "bare-sapmachine"}, - {"arch": "arm64", "flavor": "bare-libc"}, - {"arch": "arm64", "flavor": "bare-nodejs"}, - {"arch": "arm64", "flavor": "bare-python"}, - {"arch": "arm64", "flavor": "bare-sapmachine"}, + {"arch": "amd64", "cname": "bare-libc"}, + {"arch": "amd64", "cname": "bare-nodejs"}, + {"arch": "amd64", "cname": "bare-python"}, + {"arch": "amd64", "cname": "bare-sapmachine"}, + {"arch": "arm64", "cname": "bare-libc"}, + {"arch": "arm64", "cname": "bare-nodejs"}, + {"arch": "arm64", "cname": "bare-python"}, + {"arch": "arm64", "cname": "bare-sapmachine"}, ] } @@ -110,16 +110,16 @@ def test_formatter(i: str) -> None: if nightly_stats.is_file(): formatter = MarkdownFormatter( - FLAVORS_MATRIX, - BARE_FLAVORS_MATRIX, + CNAMES_MATRIX, + BARE_CNAMES_MATRIX, diff_files.joinpath(i), gardenlinux_root=str(gardenlinux_root), nightly_stats=nightly_stats, ) else: formatter = MarkdownFormatter( - FLAVORS_MATRIX, - BARE_FLAVORS_MATRIX, + CNAMES_MATRIX, + BARE_CNAMES_MATRIX, diff_files.joinpath(i), gardenlinux_root=str(gardenlinux_root), ) @@ -143,8 +143,8 @@ def test_formatter_main( str(gardenlinux_root.joinpath("features")), "--diff-dir", str(diff_files.joinpath(i)), - json.dumps(FLAVORS_MATRIX), - json.dumps(BARE_FLAVORS_MATRIX), + json.dumps(CNAMES_MATRIX), + json.dumps(BARE_CNAMES_MATRIX), ] if nightly_stats.is_file(): diff --git a/tests/github/test_main.py b/tests/github/test_main.py index 981e4499..5f9e9480 100644 --- a/tests/github/test_main.py +++ b/tests/github/test_main.py @@ -147,9 +147,9 @@ def test_script_upload_needs_github_token( "gardenlinux", "--repo", "gardenlinux", - "--release_id", + "--release-id", TEST_GARDENLINUX_RELEASE_MINOR, - "--file_path", + "--file", str(artifact_for_upload), "--dry-run", ], @@ -174,8 +174,7 @@ def test_script_parse_args_upload_command_required_args( captured = capfd.readouterr() assert ( - "the following arguments are required: --release_id, --file_path" - in captured.err + "the following arguments are required: --release-id, --file" in captured.err ), "Expected help message on missing arguments for 'upload' command" @@ -208,9 +207,9 @@ def test_script_upload_dry_run( "gardenlinux", "--repo", "gardenlinux", - "--release_id", + "--release-id", TEST_GARDENLINUX_RELEASE_MINOR, - "--file_path", + "--file", str(artifact_for_upload), "--dry-run", ], @@ -267,9 +266,9 @@ def test_script_upload_inaccessible_file( "gardenlinux", "--repo", "gardenlinux", - "--release_id", + "--release-id", TEST_GARDENLINUX_RELEASE_MINOR, - "--file_path", + "--file", str(artifact_for_upload), ], ) @@ -319,9 +318,9 @@ def test_script_upload( "gardenlinux", "--repo", "gardenlinux", - "--release_id", + "--release-id", TEST_GARDENLINUX_RELEASE_MINOR, - "--file_path", + "--file", str(artifact_for_upload), ], ) diff --git a/tests/oci/test_image_manifest.py b/tests/oci/test_image_manifest.py index 4ac89691..3d744c52 100644 --- a/tests/oci/test_image_manifest.py +++ b/tests/oci/test_image_manifest.py @@ -22,10 +22,16 @@ def test_ImageManifest_arch() -> None: def test_ImageManifest_cname() -> None: # Arrange - cname = "container-amd64-today-local" + arch = "amd64" + cname = "container" empty_manifest = ImageManifest() - manifest = ImageManifest(annotations={ImageManifest.ANNOTATION_CNAME_KEY: cname}) + manifest = ImageManifest( + annotations={ + ImageManifest.ANNOTATION_CNAME_KEY: cname, + ImageManifest.ANNOTATION_ARCH_KEY: arch, + } + ) # Assert with pytest.raises(RuntimeError): @@ -58,18 +64,25 @@ def test_ImageManifest_feature_set() -> None: def test_ImageManifest_flavor() -> None: # Arrange - flavor = "container" - cname = f"{flavor}-amd64-today-local" + arch = "amd64" + cname = "container" + flavor = f"{cname}-{arch}" empty_manifest = ImageManifest() - manifest = ImageManifest(annotations={ImageManifest.ANNOTATION_CNAME_KEY: cname}) + manifest = ImageManifest( + annotations={ + ImageManifest.ANNOTATION_CNAME_KEY: cname, + ImageManifest.ANNOTATION_ARCH_KEY: arch, + } + ) # Assert with pytest.raises(RuntimeError): - assert empty_manifest.flavor == flavor + assert empty_manifest.cname == cname - empty_manifest.cname = cname - assert empty_manifest.flavor == flavor + empty_manifest.flavor = flavor + assert empty_manifest.cname == cname + assert empty_manifest.arch == arch assert manifest.flavor == flavor diff --git a/tests/oci/test_main.py b/tests/oci/test_main.py index 27727684..234b1dbd 100644 --- a/tests/oci/test_main.py +++ b/tests/oci/test_main.py @@ -6,13 +6,13 @@ import pytest import gardenlinux.oci.__main__ as oci_main -from gardenlinux.oci import Container, Podman +from gardenlinux.oci import Podman, Repository from gardenlinux.oci.podman_context import PodmanContext from ..constants import REGISTRY, REPO_NAME, TEST_DATA_DIR -def test_main_build_container( +def test_main_build_image( monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture ) -> None: monkeypatch.setattr( @@ -20,18 +20,17 @@ def test_main_build_container( "argv", [ "__main__.py", - "build-container", + "build-image", "--dir", f"{TEST_DATA_DIR}/oci/build", - "--container", + "--repository", "container-test", "--tag", "latest", ], ) - with pytest.raises(SystemExit, match="0"): - oci_main.main() + oci_main.main() captured = capsys.readouterr() image_id = captured.out.strip() @@ -46,7 +45,7 @@ def test_main_build_container( podman.images.remove(image) -def test_main_build_container_and_save_as_oci_archive( +def test_main_build_image_and_save_as_oci_archive( monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture ) -> None: with TemporaryDirectory() as tmpdir: @@ -55,14 +54,14 @@ def test_main_build_container_and_save_as_oci_archive( "argv", [ "__main__.py", - "build-container", + "build-image", "--dir", f"{TEST_DATA_DIR}/oci/build", - "--container", + "--repository", "container-test", "--tag", "latest", - "--oci_archive", + "--oci-archive", f"{tmpdir}/archive.oci", ], ) @@ -70,8 +69,7 @@ def test_main_build_container_and_save_as_oci_archive( image_id = None try: - with pytest.raises(SystemExit, match="0"): - oci_main.main() + oci_main.main() captured = capsys.readouterr() image_id = captured.out.strip() @@ -84,7 +82,7 @@ def test_main_build_container_and_save_as_oci_archive( podman.images.remove(image) -def test_main_load_container( +def test_main_load_image( monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture ) -> None: with PodmanContext() as podman_context, TemporaryDirectory() as tmpdir: @@ -102,14 +100,13 @@ def test_main_load_container( "argv", [ "__main__.py", - "load-container", - "--oci_archive", + "load-image", + "--oci-archive", f"{tmpdir}/archive.oci", ], ) - with pytest.raises(SystemExit, match="0"): - oci_main.main() + oci_main.main() captured = capsys.readouterr() image_id_exported = captured.out.strip() @@ -121,7 +118,7 @@ def test_main_load_container( podman_context.images.remove(image) -def test_main_load_containers_from_directory( +def test_main_load_images_from_directory( monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture ) -> None: with PodmanContext() as podman_context, TemporaryDirectory() as tmpdir: @@ -139,14 +136,13 @@ def test_main_load_containers_from_directory( "argv", [ "__main__.py", - "load-containers-from-directory", + "load-images-from-directory", "--dir", f"{tmpdir}", ], ) - with pytest.raises(SystemExit, match="0"): - oci_main.main() + oci_main.main() captured = capsys.readouterr() result = json.loads(captured.out) @@ -161,7 +157,7 @@ def test_main_load_containers_from_directory( @pytest.mark.usefixtures("zot_session") -def test_main_push_container( +def test_main_push_image( monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture ) -> None: with PodmanContext() as podman_context, TemporaryDirectory(): @@ -178,30 +174,28 @@ def test_main_push_container( "argv", [ "__main__.py", - "push-container", - "--container", + "push-image", + "--repository", image_id, "--destination", f"docker://{REGISTRY}/{REPO_NAME}/kidden:latest", "--insecure", - "true", ], ) - with pytest.raises(SystemExit, match="0"): - oci_main.main() + oci_main.main() - container = Container( + repository = Repository( f"http://{REGISTRY}/{REPO_NAME}/kidden:latest", insecure=True ) # Assert - the following read would fail if push has not been successful - _ = container.read_manifest() + _ = repository.read_manifest() finally: if image_built is not None: podman_context.images.remove(image_built) -def test_main_tag_container( +def test_main_tag_image( monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture ) -> None: with PodmanContext() as podman_context, TemporaryDirectory(): @@ -218,20 +212,19 @@ def test_main_tag_container( "argv", [ "__main__.py", - "tag-container", - "--container", + "tag-image", + "--repository", image_id, - "--additional_tag", + "--additional-tag", "latest", - "--additional_tag", + "--additional-tag", "test:latest", - "--additional_tag", + "--additional-tag", "localhost/kidden:latest", ], ) - with pytest.raises(SystemExit, match="0"): - oci_main.main() + oci_main.main() image = podman_context.images.get(image_id) @@ -244,7 +237,7 @@ def test_main_tag_container( podman_context.images.remove(image, force=True) -def test_main_save_container(monkeypatch: pytest.MonkeyPatch) -> None: +def test_main_save_image(monkeypatch: pytest.MonkeyPatch) -> None: with PodmanContext() as podman, TemporaryDirectory() as tmpdir: image_id = Podman().build( f"{TEST_DATA_DIR}/oci/build", oci_tag="container-test:latest", podman=podman @@ -255,19 +248,18 @@ def test_main_save_container(monkeypatch: pytest.MonkeyPatch) -> None: "argv", [ "__main__.py", - "save-container", - "--container", + "save-image", + "--repository", "container-test:latest", "--tag", "localhost/container-test:latest", - "--oci_archive", + "--oci-archive", f"{tmpdir}/archive.oci", ], ) try: - with pytest.raises(SystemExit, match="0"): - oci_main.main() + oci_main.main() assert Path(tmpdir, "archive.oci").exists() finally: diff --git a/tests/oci/test_oci.py b/tests/oci/test_oci.py index 50c50af2..9aeb9ccb 100644 --- a/tests/oci/test_oci.py +++ b/tests/oci/test_oci.py @@ -3,19 +3,18 @@ from typing import Any, List, Optional, Tuple import pytest -from click.testing import CliRunner from oras.client import OrasClient from oras.provider import Registry sys.path.append("src") -from gardenlinux.oci.__main__ import cli as gl_oci +from gardenlinux.oci.__main__ import main as gl_oci from ..constants import ( - CONTAINER_NAME_ZOT_EXAMPLE, GARDENLINUX_ROOT_DIR_EXAMPLE, REGISTRY, REGISTRY_URL, + REPOSITORY_NAME_ZOT_EXAMPLE, TEST_ARCHITECTURES, TEST_COMMIT, TEST_FEATURE_SET, @@ -27,124 +26,118 @@ def push_manifest( - runner: CliRunner, + monkeypatch: pytest.MonkeyPatch, version: str, arch: str, cname: str, additional_tags: Optional[List[str]] = None, -) -> bool: +) -> None: """Push manifest to registry and return success status""" print(f"Pushing manifest for {cname} {arch}") - cmd = [ + args = [ + "gl-oci", "push-manifest", - "--container", - CONTAINER_NAME_ZOT_EXAMPLE, - "--version", - version, - "--arch", - arch, + "--repository", + REPOSITORY_NAME_ZOT_EXAMPLE, "--cname", cname, + "--arch", + arch, + "--version", + version, + "--commit", + TEST_COMMIT, "--dir", GARDENLINUX_ROOT_DIR_EXAMPLE, - "--insecure", - "True", - "--cosign_file", + "--cosign-file", "digest", - "--manifest_file", + "--manifest-file", "manifests/manifest.json", + "--insecure", ] if additional_tags: for tag in additional_tags: - cmd.extend(["--additional_tag", tag]) + args.extend(["--additional-tag", tag]) - try: - result = runner.invoke( - gl_oci, - cmd, - catch_exceptions=False, - ) - print(f"Push manifest output: {result.output}") - return result.exit_code == 0 - except Exception as e: - print(f"Error during push manifest: {str(e)}") - return False + monkeypatch.setattr( + sys, + "argv", + args, + ) + + gl_oci() def push_manifest_tags( - runner: CliRunner, + monkeypatch: pytest.MonkeyPatch, version: str, arch: str, cname: str, tags: Optional[List[str]] = None, -) -> bool: +) -> None: """Push manifest to registry and return success status""" print(f"Pushing manifest for {cname} {arch}") - cmd = [ + args = [ + "gl-oci", "push-manifest-tags", - "--container", - CONTAINER_NAME_ZOT_EXAMPLE, - "--version", - version, - "--arch", - arch, + "--repository", + REPOSITORY_NAME_ZOT_EXAMPLE, "--cname", cname, + "--arch", + arch, + "--version", + version, + "--commit", + TEST_COMMIT, "--insecure", - "True", ] if tags: for tag in tags: - cmd.extend(["--tag", tag]) + args.extend(["--tag", tag]) - try: - result = runner.invoke( - gl_oci, - cmd, - catch_exceptions=False, - ) - print(f"Push manifest tags output: {result.output}") - return result.exit_code == 0 - except Exception as e: - print(f"Error during push manifest tags: {str(e)}") - return False + monkeypatch.setattr( + sys, + "argv", + args, + ) + + gl_oci() def update_index( - runner: CliRunner, version: str, additional_tags: Optional[List[str]] = None -) -> bool: + monkeypatch: pytest.MonkeyPatch, + version: str, + additional_tags: Optional[List[str]] = None, +) -> None: """Update index in registry and return success status""" print("Updating index") - cmd = [ + args = [ + "gl-oci", "push-index-from-directory", "--index", - CONTAINER_NAME_ZOT_EXAMPLE, + REPOSITORY_NAME_ZOT_EXAMPLE, "--index-tag", version, "--insecure", - "True", ] if additional_tags: for tag in additional_tags: - cmd.extend(["--additional_tag", tag]) + args.extend(["--additional-tag", tag]) - try: - result = runner.invoke( - gl_oci, - cmd, - catch_exceptions=False, - ) - print(f"Update index output: {result.output}") - return result.exit_code == 0 - except Exception as e: - print(f"Error during update index: {str(e)}") - return False + monkeypatch.setattr( + sys, + "argv", + args, + ) + + gl_oci() def get_catalog(client: OrasClient) -> List[Any]: @@ -223,19 +216,22 @@ def verify_combined_tag_manifest( assert "annotations" in manifest, "Manifest should contain annotations" annotations = manifest.get("annotations", {}) + + assert annotations.get("cname") == cname, f"Manifest should have cname {cname}" + assert annotations.get("architecture") == arch, ( f"Manifest should have architecture {arch}" ) - assert annotations.get("cname") == cname, f"Manifest should have cname {cname}" - assert annotations.get("version") == version, ( - f"Manifest should have version {version}" - ) if feature_set: assert annotations.get("feature_set") == feature_set, ( f"Manifest should have feature_set {feature_set}" ) + assert annotations.get("version") == version, ( + f"Manifest should have version {version}" + ) + if commit: assert annotations.get("commit") == commit, ( f"Manifest should have commit {commit}" @@ -339,11 +335,11 @@ def test_push_manifest_and_index( cname: str, additional_tags_index: List[str], additional_tags_manifest: List[str], + monkeypatch: pytest.MonkeyPatch, ) -> None: print(f"\n\n=== Starting test for {cname} {arch} {version} ===") - runner = CliRunner() repo_name = "gardenlinux-example" - combined_tag = f"{version}-{cname}-{arch}" + combined_tag = f"{version}-{cname}-{arch}-{version}-{TEST_COMMIT}-{arch}" post_push_manifest_tags = [] @@ -352,20 +348,12 @@ def test_push_manifest_and_index( post_push_manifest_tags = additional_tags_manifest additional_tags_manifest = [] - push_successful = push_manifest( - runner, version, arch, cname, additional_tags_manifest - ) - assert push_successful, "Manifest push should succeed" + push_manifest(monkeypatch, version, arch, cname, additional_tags_manifest) if len(post_push_manifest_tags) > 0: - push_successful = push_manifest_tags( - runner, version, arch, cname, post_push_manifest_tags - ) - assert push_successful, "Manifest tags push should succeed" + push_manifest_tags(monkeypatch, version, arch, cname, post_push_manifest_tags) - if push_successful: - update_index_successful = update_index(runner, version, additional_tags_index) - assert update_index_successful, "Index update should succeed" + update_index(monkeypatch, version, additional_tags_index) # Verify registry contents print(f"\n=== Verifying registry for {cname} {arch} {version} ===") diff --git a/tests/oci/test_podman.py b/tests/oci/test_podman.py index c0688adc..71e0ffc1 100644 --- a/tests/oci/test_podman.py +++ b/tests/oci/test_podman.py @@ -21,7 +21,7 @@ def test_podman_tag_list( try: podman.tag_list( image_id, - Podman.get_container_tag_list("container-test", ["a", "b", "c"]), + Podman.get_image_tag_list("container-test", ["a", "b", "c"]), ) image = podman_context.images.get(image_id) diff --git a/tests/oci/test_container.py b/tests/oci/test_repository.py similarity index 56% rename from tests/oci/test_container.py rename to tests/oci/test_repository.py index deecdc61..d03865f4 100644 --- a/tests/oci/test_container.py +++ b/tests/oci/test_repository.py @@ -5,13 +5,13 @@ from requests import Response from requests.exceptions import HTTPError -from gardenlinux.oci import Container +from gardenlinux.oci import Repository -from ..constants import CONTAINER_NAME_ZOT_EXAMPLE, REGISTRY, TEST_COMMIT, TEST_VERSION +from ..constants import REGISTRY, REPOSITORY_NAME_ZOT_EXAMPLE, TEST_COMMIT, TEST_VERSION -@pytest.fixture(name="Container_login_403") -def patch__Container_login_403(monkeypatch: pytest.MonkeyPatch) -> None: +@pytest.fixture(name="Repository_login_403") +def patch_Repository_login_403(monkeypatch: pytest.MonkeyPatch) -> None: """Patch `login()` to return HTTP 403. `docker.errors.APIError` extends from `requests.exceptions.HTTPError` as well.""" def login_403(*args: Any, **kwargs: Any) -> None: @@ -19,11 +19,11 @@ def login_403(*args: Any, **kwargs: Any) -> None: response.status_code = 403 raise HTTPError("403 Forbidden", response=response) - monkeypatch.setattr(Container, "login", login_403) + monkeypatch.setattr(Repository, "login", login_403) -@pytest.fixture(name="Container_read_or_generate_403") -def patch__Container_read_or_generate_403(monkeypatch: pytest.MonkeyPatch) -> None: +@pytest.fixture(name="Repository_read_or_generate_403") +def patch_Repository_read_or_generate_403(monkeypatch: pytest.MonkeyPatch) -> None: """Patch `read_or_generate_manifest()` to return HTTP 403.""" def read_or_generate_403(*args: Any, **kwargs: Any) -> None: @@ -31,16 +31,18 @@ def read_or_generate_403(*args: Any, **kwargs: Any) -> None: response.status_code = 403 raise HTTPError("403 Forbidden", response=response) - monkeypatch.setattr(Container, "read_or_generate_manifest", read_or_generate_403) + monkeypatch.setattr(Repository, "read_or_generate_manifest", read_or_generate_403) @pytest.mark.usefixtures("zot_session") def test_manifest() -> None: """Verify a newly created manifest returns correct commit value.""" # Arrange - container = Container(f"{CONTAINER_NAME_ZOT_EXAMPLE}:{TEST_VERSION}", insecure=True) + repository = Repository( + f"{REPOSITORY_NAME_ZOT_EXAMPLE}:{TEST_VERSION}", insecure=True + ) - manifest = container.read_or_generate_manifest( + manifest = repository.read_or_generate_manifest( version=TEST_VERSION, commit=TEST_COMMIT ) @@ -49,46 +51,48 @@ def test_manifest() -> None: @pytest.mark.usefixtures("zot_session") -@pytest.mark.usefixtures("Container_read_or_generate_403") +@pytest.mark.usefixtures("Repository_read_or_generate_403") def test_manifest_403() -> None: - """Verify container calls raises exceptions for certain errors.""" + """Verify repository calls raises exceptions for certain errors.""" # Arrange - container = Container(f"{CONTAINER_NAME_ZOT_EXAMPLE}:{TEST_VERSION}", insecure=True) + repository = Repository( + f"{REPOSITORY_NAME_ZOT_EXAMPLE}:{TEST_VERSION}", insecure=True + ) with pytest.raises(HTTPError): - container.read_or_generate_manifest(version=TEST_VERSION, commit=TEST_COMMIT) + repository.read_or_generate_manifest(version=TEST_VERSION, commit=TEST_COMMIT) @pytest.mark.usefixtures("zot_session") def test_manifest_auth_token( monkeypatch: pytest.MonkeyPatch, caplog: pytest.LogCaptureFixture ) -> None: - """Verify container calls use login environment variables if defined.""" + """Verify repository calls use login environment variables if defined.""" with monkeypatch.context(): token = "test" monkeypatch.setenv("GL_CLI_REGISTRY_TOKEN", token) # Arrange - container = Container( - f"{CONTAINER_NAME_ZOT_EXAMPLE}:{TEST_VERSION}", insecure=True + repository = Repository( + f"{REPOSITORY_NAME_ZOT_EXAMPLE}:{TEST_VERSION}", insecure=True ) # Assert - assert container.auth.token == b64encode(bytes(token, "utf-8")).decode("utf-8") + assert repository.auth.token == b64encode(bytes(token, "utf-8")).decode("utf-8") @pytest.mark.usefixtures("zot_session") -@pytest.mark.usefixtures("Container_login_403") +@pytest.mark.usefixtures("Repository_login_403") def test_manifest_login_username_password( monkeypatch: pytest.MonkeyPatch, caplog: pytest.LogCaptureFixture ) -> None: - """Verify container calls use login environment variables if defined.""" + """Verify repository calls use login environment variables if defined.""" with monkeypatch.context(): monkeypatch.setenv("GL_CLI_REGISTRY_USERNAME", "test") monkeypatch.setenv("GL_CLI_REGISTRY_PASSWORD", "test") # Arrange - Container(f"{REGISTRY}/protected/test:{TEST_VERSION}", insecure=True) + Repository(f"{REGISTRY}/protected/test:{TEST_VERSION}", insecure=True) # Assert assert "Login error: 403 Forbidden" in caplog.text diff --git a/tests/s3/conftest.py b/tests/s3/conftest.py index 8ba1fa09..9219fd06 100644 --- a/tests/s3/conftest.py +++ b/tests/s3/conftest.py @@ -20,10 +20,10 @@ class S3Env: s3: S3ServiceResource bucket_name: str tmp_path: Path - cname: str + artifact_base_name: str -def make_cname( +def make_artifact_base_name( flavor: str = "container_trustedboot_usi", arch: str = "amd64", version: str = "1234.1", @@ -64,5 +64,5 @@ def s3_setup( monkeypatch.setattr("gardenlinux.s3.s3_artifacts.file_digest", dummy_digest) - cname = make_cname() - yield S3Env(s3, BUCKET_NAME, tmp_path, cname) + artifact_base_name = make_artifact_base_name() + yield S3Env(s3, BUCKET_NAME, tmp_path, artifact_base_name) diff --git a/tests/s3/constants.py b/tests/s3/constants.py index b8a06bf9..d63680fe 100644 --- a/tests/s3/constants.py +++ b/tests/s3/constants.py @@ -1,7 +1,8 @@ # -*- coding: utf-8 -*- RELEASE_DATA = """ -GARDENLINUX_CNAME="container_trustedboot_usi-amd64-1234.1" +VARIANT_ID="container_trustedboot_usi-amd64" +GARDENLINUX_CNAME="container_trustedboot_usi" GARDENLINUX_VERSION=1234.1 GARDENLINUX_COMMIT_ID="abc123lo" GARDENLINUX_COMMIT_ID_LONG="abc123long" diff --git a/tests/s3/test_main.py b/tests/s3/test_main.py index 7fa100ff..9051e084 100644 --- a/tests/s3/test_main.py +++ b/tests/s3/test_main.py @@ -22,7 +22,7 @@ "--path", "some/path", "download-artifacts-from-bucket", - "--cname", + "--artifact-base-name", "test-cname", ], "download_to_directory", @@ -37,7 +37,7 @@ "--path", "some/path", "upload-artifacts-to-bucket", - "--artifact-name", + "--artifact-base-name", "test-cname", ], "upload_from_directory", @@ -84,11 +84,11 @@ def test_main_with_expected_result( "--path", str(env.tmp_path), "upload-artifacts-to-bucket", - "--artifact-name", - env.cname, + "--artifact-base-name", + env.artifact_base_name, ], ): - release_path = env.tmp_path / f"{env.cname}.release" + release_path = env.tmp_path / f"{env.artifact_base_name}.release" release_path.write_text(RELEASE_DATA) s3m.main() diff --git a/tests/s3/test_s3_artifacts.py b/tests/s3/test_s3_artifacts.py index 9983c46f..b6e6e08e 100644 --- a/tests/s3/test_s3_artifacts.py +++ b/tests/s3/test_s3_artifacts.py @@ -37,19 +37,21 @@ def test_download_to_directory_success(s3_setup: S3Env) -> None: env = s3_setup bucket = env.s3.Bucket(env.bucket_name) - bucket.put_object(Key=f"meta/singles/{env.cname}", Body=b"metadata") - bucket.put_object(Key=f"objects/{env.cname}/file1", Body=b"data1") - bucket.put_object(Key=f"objects/{env.cname}/file2", Body=b"data2") + bucket.put_object(Key=f"meta/singles/{env.artifact_base_name}", Body=b"metadata") + bucket.put_object(Key=f"objects/{env.artifact_base_name}/file1", Body=b"data1") + bucket.put_object(Key=f"objects/{env.artifact_base_name}/file2", Body=b"data2") with TemporaryDirectory() as tmpdir: outdir = Path(tmpdir) # Act artifacts = S3Artifacts(env.bucket_name) - artifacts.download_to_directory(env.cname, outdir) + artifacts.download_to_directory(env.artifact_base_name, outdir) # Assert - assert (outdir / f"{env.cname}.s3_metadata.yaml").read_bytes() == b"metadata" + assert ( + outdir / f"{env.artifact_base_name}.s3_metadata.yaml" + ).read_bytes() == b"metadata" assert (outdir / "file1").read_bytes() == b"data1" assert (outdir / "file2").read_bytes() == b"data2" @@ -64,7 +66,9 @@ def test_download_to_directory_invalid_path(s3_setup: S3Env) -> None: # Act / Assert with pytest.raises(RuntimeError): - artifacts.download_to_directory(env.cname, "/invalid/path/does/not/exist") + artifacts.download_to_directory( + env.artifact_base_name, "/invalid/path/does/not/exist" + ) def test_download_to_directory_non_pathlike_raises(s3_setup: S3Env) -> None: @@ -72,7 +76,7 @@ def test_download_to_directory_non_pathlike_raises(s3_setup: S3Env) -> None: env = s3_setup artifacts = S3Artifacts(env.bucket_name) with pytest.raises(RuntimeError): - artifacts.download_to_directory(env.cname, "nopath") + artifacts.download_to_directory(env.artifact_base_name, "nopath") def test_download_to_directory_no_metadata_raises(s3_setup: S3Env) -> None: @@ -84,7 +88,7 @@ def test_download_to_directory_no_metadata_raises(s3_setup: S3Env) -> None: # Act / Assert with TemporaryDirectory() as tmpdir: with pytest.raises(IndexError): - artifacts.download_to_directory(env.cname, tmpdir) + artifacts.download_to_directory(env.artifact_base_name, tmpdir) def test_upload_from_directory_success(s3_setup: S3Env) -> None: @@ -94,30 +98,37 @@ def test_upload_from_directory_success(s3_setup: S3Env) -> None: # Arrange env = s3_setup - release_path = env.tmp_path / f"{env.cname}.release" + release_path = env.tmp_path / f"{env.artifact_base_name}.release" release_path.write_text(RELEASE_DATA) - for filename in [f"{env.cname}-file1", f"{env.cname}-file2", "container"]: + for filename in [ + f"{env.artifact_base_name}-file1", + f"{env.artifact_base_name}-file2", + "container", + ]: (env.tmp_path / filename).write_bytes(b"dummy content") # Act artifacts = S3Artifacts(env.bucket_name) - artifacts.upload_from_directory(env.cname, env.tmp_path) + artifacts.upload_from_directory(env.artifact_base_name, env.tmp_path) # Assert bucket = env.s3.Bucket(env.bucket_name) keys = [obj.key for obj in bucket.objects.all()] - assert f"objects/{env.cname}/{env.cname}-file1" in keys - assert f"objects/{env.cname}/{env.cname}-file2" in keys - assert f"meta/singles/{env.cname}" in keys + assert f"objects/{env.artifact_base_name}/{env.artifact_base_name}-file1" in keys + assert f"objects/{env.artifact_base_name}/{env.artifact_base_name}-file2" in keys + assert f"meta/singles/{env.artifact_base_name}" in keys - meta_obj = list(bucket.objects.filter(Prefix=f"meta/singles/{env.cname}"))[0] + meta_obj = list( + bucket.objects.filter(Prefix=f"meta/singles/{env.artifact_base_name}") + )[0] metadata = yaml.safe_load(meta_obj.get()["Body"].read()) assert metadata["require_uefi"] is True assert metadata["secureboot"] is True raw_tags_response = env.s3.meta.client.get_object_tagging( - Bucket=env.bucket_name, Key=f"objects/{env.cname}/{env.cname}-file1" + Bucket=env.bucket_name, + Key=f"objects/{env.artifact_base_name}/{env.artifact_base_name}-file1", ) tags = {tag["Key"]: tag["Value"] for tag in raw_tags_response["TagSet"]} assert tags["platform"] == "container" @@ -132,28 +143,34 @@ def test_upload_from_directory_with_delete(s3_setup: S3Env) -> None: bucket = env.s3.Bucket(env.bucket_name) # Arrange: create release and artifact files locally - release = env.tmp_path / f"{env.cname}.release" + release = env.tmp_path / f"{env.artifact_base_name}.release" release.write_text(RELEASE_DATA) - artifact = env.tmp_path / f"{env.cname}.kernel" + artifact = env.tmp_path / f"{env.artifact_base_name}.kernel" artifact.write_bytes(b"fake") # Arrange: put dummy existing objects to be deleted - bucket.put_object(Key=f"objects/{env.cname}/{artifact.name}", Body=b"old data") - bucket.put_object(Key=f"meta/singles/{env.cname}", Body=b"old metadata") + bucket.put_object( + Key=f"objects/{env.artifact_base_name}/{artifact.name}", Body=b"old data" + ) + bucket.put_object( + Key=f"meta/singles/{env.artifact_base_name}", Body=b"old metadata" + ) artifacts = S3Artifacts(env.bucket_name) # Act - artifacts.upload_from_directory(env.cname, env.tmp_path, delete_before_push=True) + artifacts.upload_from_directory( + env.artifact_base_name, env.tmp_path, delete_before_push=True + ) # Assert keys = [obj.key for obj in bucket.objects.all()] # The old key should no longer be present as old data (no duplicates) # but the new upload file key should exist (artifact uploaded) - assert f"objects/{env.cname}/{artifact.name}" in keys - assert f"meta/singles/{env.cname}" in keys + assert f"objects/{env.artifact_base_name}/{artifact.name}" in keys + assert f"meta/singles/{env.artifact_base_name}" in keys def test_upload_from_directory_invalid_dir_raises(s3_setup: S3Env) -> None: @@ -161,7 +178,7 @@ def test_upload_from_directory_invalid_dir_raises(s3_setup: S3Env) -> None: env = s3_setup artifacts = S3Artifacts(env.bucket_name) with pytest.raises(RuntimeError, match="invalid"): - artifacts.upload_from_directory(env.cname, "/invalid/path") + artifacts.upload_from_directory(env.artifact_base_name, "/invalid/path") def test_upload_from_directory_version_mismatch(s3_setup: S3Env) -> None: @@ -170,13 +187,13 @@ def test_upload_from_directory_version_mismatch(s3_setup: S3Env) -> None: """ # Arrange env = s3_setup - release_path = env.tmp_path / f"{env.cname}.release" + release_path = env.tmp_path / f"{env.artifact_base_name}.release" bad_data = RELEASE_DATA.replace("1234.1", "9999.9") release_path.write_text(bad_data) artifacts = S3Artifacts(env.bucket_name) # Act / Assert - artifacts.upload_from_directory(env.cname, env.tmp_path) + artifacts.upload_from_directory(env.artifact_base_name, env.tmp_path) def test_upload_from_directory_succeeds_because_of_release_file( @@ -199,7 +216,7 @@ def test_upload_from_directory_invalid_artifact_name(s3_setup: S3Env) -> None: """ # Arrange env = s3_setup - (env.tmp_path / f"{env.cname}.release").write_text(RELEASE_DATA) + (env.tmp_path / f"{env.artifact_base_name}.release").write_text(RELEASE_DATA) # Create "bad" artifact that does not start with cname bad_file = env.tmp_path / "no_match" @@ -208,14 +225,19 @@ def test_upload_from_directory_invalid_artifact_name(s3_setup: S3Env) -> None: artifacts = S3Artifacts(env.bucket_name) # Act - artifacts.upload_from_directory(env.cname, env.tmp_path) + artifacts.upload_from_directory(env.artifact_base_name, env.tmp_path) # Assert bucket = env.s3.Bucket(env.bucket_name) - assert len(list(bucket.objects.filter(Prefix=f"meta/singles/{env.cname}"))) == 1 + assert ( + len( + list(bucket.objects.filter(Prefix=f"meta/singles/{env.artifact_base_name}")) + ) + == 1 + ) -def test_upload_from_directory_invalid_release_file_with_valid_cname( +def test_upload_from_directory_beside_of_incomplete_release_file( s3_setup: S3Env, ) -> None: """ @@ -223,20 +245,25 @@ def test_upload_from_directory_invalid_release_file_with_valid_cname( """ # Arrange env = s3_setup - release_path = env.tmp_path / f"{env.cname}.release" + release_path = env.tmp_path / f"{env.artifact_base_name}.release" bad_data = RELEASE_DATA.replace( - "GARDENLINUX_FEATURES_PLATFORMS=", "GARDENLINUX_FEATURES_PLATFORMS_UNDEFINED=" + "GARDENLINUX_PLATFORM=", "GARDENLINUX_PLATFORM_UNDEFINED=" ) release_path.write_text(bad_data) artifacts = S3Artifacts(env.bucket_name) # Act - artifacts.upload_from_directory(env.cname, env.tmp_path) + artifacts.upload_from_directory(env.artifact_base_name, env.tmp_path) # Assert bucket = env.s3.Bucket(env.bucket_name) - assert len(list(bucket.objects.filter(Prefix=f"meta/singles/{env.cname}"))) == 1 + assert ( + len( + list(bucket.objects.filter(Prefix=f"meta/singles/{env.artifact_base_name}")) + ) + == 1 + ) def test_upload_from_directory_commit_mismatch(s3_setup: S3Env) -> None: @@ -245,13 +272,13 @@ def test_upload_from_directory_commit_mismatch(s3_setup: S3Env) -> None: """ # Arrange env = s3_setup - release_path = env.tmp_path / f"{env.cname}.release" + release_path = env.tmp_path / f"{env.artifact_base_name}.release" bad_data = RELEASE_DATA.replace("abc123", "wrong") release_path.write_text(bad_data) artifacts = S3Artifacts(env.bucket_name) # Act / Assert - artifacts.upload_from_directory(env.cname, env.tmp_path) + artifacts.upload_from_directory(env.artifact_base_name, env.tmp_path) def test_upload_from_directory_with_platform_variant(s3_setup: S3Env) -> None: @@ -260,20 +287,23 @@ def test_upload_from_directory_with_platform_variant(s3_setup: S3Env) -> None: """ # Arrange env = s3_setup - release_path = env.tmp_path / f"{env.cname}.release" + release_path = env.tmp_path / f"{env.artifact_base_name}.release" release_path.write_text( RELEASE_DATA.strip() + "\nGARDENLINUX_PLATFORM_VARIANT=test" ) + print(release_path.read_text()) # Act artifacts = S3Artifacts(env.bucket_name) - artifacts.upload_from_directory(env.cname, env.tmp_path) + artifacts.upload_from_directory(env.artifact_base_name, env.tmp_path) # Assert bucket = env.s3.Bucket(env.bucket_name) meta_obj = next( - o for o in bucket.objects.all() if o.key == f"meta/singles/{env.cname}" + o + for o in bucket.objects.all() + if o.key == f"meta/singles/{env.artifact_base_name}" ) metadata = yaml.safe_load(meta_obj.get()["Body"].read()) assert metadata["platform_variant"] == "test" @@ -283,21 +313,23 @@ def test_upload_directory_with_requirements_override(s3_setup: S3Env) -> None: """Ensure .requirements file values overide feature flag defaults.""" # Arrange env = s3_setup - (env.tmp_path / f"{env.cname}.release").write_text(RELEASE_DATA) - (env.tmp_path / f"{env.cname}.requirements").write_text( + (env.tmp_path / f"{env.artifact_base_name}.release").write_text(RELEASE_DATA) + (env.tmp_path / f"{env.artifact_base_name}.requirements").write_text( "uefi = false\nsecureboot = true\n" ) - artifact_file = env.tmp_path / f"{env.cname}-artifact" + artifact_file = env.tmp_path / f"{env.artifact_base_name}-artifact" artifact_file.write_bytes(b"abc") # Act artifacts = S3Artifacts(env.bucket_name) - artifacts.upload_from_directory(env.cname, env.tmp_path) + artifacts.upload_from_directory(env.artifact_base_name, env.tmp_path) # Assert bucket = env.s3.Bucket(env.bucket_name) meta_obj = next( - o for o in bucket.objects.all() if o.key == f"meta/singles/{env.cname}" + o + for o in bucket.objects.all() + if o.key == f"meta/singles/{env.artifact_base_name}" ) metadata = yaml.safe_load(meta_obj.get()["Body"].read()) assert metadata["require_uefi"] is False @@ -308,20 +340,22 @@ def test_upload_directory_with_publishing_group(s3_setup: S3Env) -> None: """A publishing_group value in the .requirements file is copied into the metadata.""" # Arrange env = s3_setup - (env.tmp_path / f"{env.cname}.release").write_text(RELEASE_DATA) - (env.tmp_path / f"{env.cname}.requirements").write_text( + (env.tmp_path / f"{env.artifact_base_name}.release").write_text(RELEASE_DATA) + (env.tmp_path / f"{env.artifact_base_name}.requirements").write_text( "arch = amd64\npublishing_group = container\n" ) - (env.tmp_path / f"{env.cname}-artifact").write_bytes(b"abc") + (env.tmp_path / f"{env.artifact_base_name}-artifact").write_bytes(b"abc") # Act artifacts = S3Artifacts(env.bucket_name) - artifacts.upload_from_directory(env.cname, env.tmp_path) + artifacts.upload_from_directory(env.artifact_base_name, env.tmp_path) # Assert bucket = env.s3.Bucket(env.bucket_name) meta_obj = next( - o for o in bucket.objects.all() if o.key == f"meta/singles/{env.cname}" + o + for o in bucket.objects.all() + if o.key == f"meta/singles/{env.artifact_base_name}" ) metadata = yaml.safe_load(meta_obj.get()["Body"].read()) assert metadata["publishing_group"] == "container" @@ -331,20 +365,22 @@ def test_upload_directory_without_publishing_group(s3_setup: S3Env) -> None: """An empty or absent publishing_group is not emitted, marking a standalone build.""" # Arrange env = s3_setup - (env.tmp_path / f"{env.cname}.release").write_text(RELEASE_DATA) - (env.tmp_path / f"{env.cname}.requirements").write_text( + (env.tmp_path / f"{env.artifact_base_name}.release").write_text(RELEASE_DATA) + (env.tmp_path / f"{env.artifact_base_name}.requirements").write_text( "arch = amd64\npublishing_group = \n" ) - (env.tmp_path / f"{env.cname}-artifact").write_bytes(b"abc") + (env.tmp_path / f"{env.artifact_base_name}-artifact").write_bytes(b"abc") # Act artifacts = S3Artifacts(env.bucket_name) - artifacts.upload_from_directory(env.cname, env.tmp_path) + artifacts.upload_from_directory(env.artifact_base_name, env.tmp_path) # Assert bucket = env.s3.Bucket(env.bucket_name) meta_obj = next( - o for o in bucket.objects.all() if o.key == f"meta/singles/{env.cname}" + o + for o in bucket.objects.all() + if o.key == f"meta/singles/{env.artifact_base_name}" ) metadata = yaml.safe_load(meta_obj.get()["Body"].read()) assert "publishing_group" not in metadata