diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 887668e2..e086d619 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,6 +30,8 @@ jobs: - name: Install supabase cli latest uses: supabase/setup-cli@v1 + with: + version: "latest" - name: Install uv uses: astral-sh/setup-uv@v6 diff --git a/.release-please-manifest.json b/.release-please-manifest.json index c1aa7c83..d4f4cd1a 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,5 +1,6 @@ { "src/supabase": "2.18.1", "src/realtime": "2.7.0", - "src/functions": "0.10.1" + "src/functions": "0.10.1", + "src/storage": "0.12.1" } diff --git a/Makefile b/Makefile index b5e8c2a2..7d5035f8 100644 --- a/Makefile +++ b/Makefile @@ -4,14 +4,16 @@ default: @echo "Available targets are: ci, pre-commit, publish" ci: pre-commit - make -C src/realtime tests make -C src/functions tests + make -C src/realtime tests + make -C src/storage tests make -C src/supabase tests publish: - uv build --project realtime - uv build --project supabase - uv build --project functions + uv build --package realtime + uv build --package storage3 + uv build --package supabase_functions + uv build --package supabase uv publish pre-commit: diff --git a/README.md b/README.md index 6e4a4b19..d93077be 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,8 @@ Python monorepo for all [Supabase](https://supabase.com) libraries. This is a wo - [supabase](src/supabase/README.md) - [realtime](src/realtime/README.md) +- [supabase_functions](src/functions/README.md) +- [storage3](src/storage/README.md) Relevant links: diff --git a/flake.lock b/flake.lock index 1d74bf2e..acbde409 100644 --- a/flake.lock +++ b/flake.lock @@ -2,11 +2,11 @@ "nodes": { "nixpkgs": { "locked": { - "lastModified": 1754214453, - "narHash": "sha256-Q/I2xJn/j1wpkGhWkQnm20nShYnG7TI99foDBpXm1SY=", + "lastModified": 1755615617, + "narHash": "sha256-HMwfAJBdrr8wXAkbGhtcby1zGFvs+StOp19xNsbqdOg=", "owner": "nixos", "repo": "nixpkgs", - "rev": "5b09dc45f24cf32316283e62aec81ffee3c3e376", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", "type": "github" }, "original": { diff --git a/pyproject.toml b/pyproject.toml index 766cbf1f..5a35fff9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,12 +2,14 @@ members = [ "src/realtime", "src/functions", - "src/supabase" + "src/supabase", + "src/storage" ] [tool.uv.sources] realtime = { workspace = true } supabase_functions = { workspace = true } +storage3 = { workspace = true } supabase = { workspace = true } [tool.pytest.ini_options] diff --git a/release-please-config.json b/release-please-config.json index 820447f3..29925656 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -8,10 +8,14 @@ "src/functions": { "changelog-path": "src/functions/CHANGELOG.md", "release-type": "python" - } + }, + "src/storage": { + "changelog-path": "src/storage/CHANGELOG.md", + "release-type": "python" + }, "src/supabase": { "changelog-path": "src/supabase/CHANGELOG.md", "release-type": "python" - }, + } } } diff --git a/src/functions/pyproject.toml b/src/functions/pyproject.toml index e2f399d5..f8fdb668 100644 --- a/src/functions/pyproject.toml +++ b/src/functions/pyproject.toml @@ -8,13 +8,15 @@ authors = [ ] license = "MIT" readme = "README.md" -repository = "https://github.com/supabase/supabase-py" requires-python = ">=3.9" dependencies = [ "httpx[http2] >=0.26,<0.29", "strenum >=0.4.15", ] +[project.urls] +repository = "https://github.com/supabase/supabase-py" + [dependency-groups] tests = [ "pyjwt >=2.8.0", diff --git a/src/storage/CHANGELOG.md b/src/storage/CHANGELOG.md new file mode 100644 index 00000000..3532979c --- /dev/null +++ b/src/storage/CHANGELOG.md @@ -0,0 +1,2047 @@ +# CHANGELOG + +## [0.12.2](https://github.com/supabase/storage-py/compare/v0.12.1...v0.12.2) (2025-08-15) + + +### Bug Fixes + +* remove extraneous char in test ([#389](https://github.com/supabase/storage-py/issues/389)) ([088cb7f](https://github.com/supabase/storage-py/commit/088cb7f74eb68deafa007b7b333ed9a9aac4b751)) +* use `BaseModel` instead of `dataclass` ([#386](https://github.com/supabase/storage-py/issues/386)) ([c4a81fb](https://github.com/supabase/storage-py/commit/c4a81fb9f7acacf8dccbf579daf4030200d8ab20)) + +## [0.12.1](https://github.com/supabase/storage-py/compare/v0.12.0...v0.12.1) (2025-08-05) + + +### Bug Fixes + +* add optional type field to bucket metadata ([#380](https://github.com/supabase/storage-py/issues/380)) ([ce48f6c](https://github.com/supabase/storage-py/commit/ce48f6c353453f9971e3c5614b56d02c9af40645)) + +## [0.12.0](https://github.com/supabase/storage-py/compare/v0.11.3...v0.12.0) (2025-06-19) + + +### Features + +* allow injection of httpx client ([#363](https://github.com/supabase/storage-py/issues/363)) ([b04be02](https://github.com/supabase/storage-py/commit/b04be02edaaa09801b1fd90e755c9ae0eedbb187)) + +## [0.11.3](https://github.com/supabase/storage-py/compare/v0.11.2...v0.11.3) (2025-01-29) + + +### Bug Fixes + +* older python versions are broken due to NotRequired ([#344](https://github.com/supabase/storage-py/issues/344)) ([ca567e9](https://github.com/supabase/storage-py/commit/ca567e9982a2f29cbc69c3e476ffcd8dad03abf5)) + +## [0.11.2](https://github.com/supabase/storage-py/compare/v0.11.1...v0.11.2) (2025-01-29) + + +### Bug Fixes + +* add correct naming for returned data keys ([#339](https://github.com/supabase/storage-py/issues/339)) ([4527da6](https://github.com/supabase/storage-py/commit/4527da69a87da08a13f6630bbdd919d721beef4a)) + +## [0.11.1](https://github.com/supabase/storage-py/compare/v0.11.0...v0.11.1) (2025-01-23) + + +### Bug Fixes + +* exists method raises error when no file found ([#335](https://github.com/supabase/storage-py/issues/335)) ([cc37894](https://github.com/supabase/storage-py/commit/cc378944d97e61718cfa31e5667e7ed52c07e428)) + +## [0.11.0](https://github.com/supabase/storage-py/compare/v0.10.0...v0.11.0) (2024-12-30) + + +### Features + +* add custom-metadata to upload ([#328](https://github.com/supabase/storage-py/issues/328)) ([d4f9794](https://github.com/supabase/storage-py/commit/d4f979492f94cab6402cf158a41172ef46d68559)) +* Implement info and exists file API methods ([#318](https://github.com/supabase/storage-py/issues/318)) ([0100ff1](https://github.com/supabase/storage-py/commit/0100ff10af7fc86cb6286269a7b91195e0393d3a)) + + +### Bug Fixes + +* file name in signed URLs is not URI-encoded ([#324](https://github.com/supabase/storage-py/issues/324)) ([c58fbb0](https://github.com/supabase/storage-py/commit/c58fbb0afcff087616d5913c3953e849bb2f6885)) +* incorrect upload return type ([#327](https://github.com/supabase/storage-py/issues/327)) ([eb8034f](https://github.com/supabase/storage-py/commit/eb8034f4f2ae4fdb2b12b3dc048d2cf4080fc193)) +* upload doesn't close file handle ([#323](https://github.com/supabase/storage-py/issues/323)) ([02ae7fc](https://github.com/supabase/storage-py/commit/02ae7fca681d3f73211c3a500145ed395a159ec3)) + +## [0.10.0](https://github.com/supabase/storage-py/compare/v0.9.0...v0.10.0) (2024-11-22) + + +### Features + +* add new storage error class ([#313](https://github.com/supabase/storage-py/issues/313)) ([f040f10](https://github.com/supabase/storage-py/commit/f040f10c3a17deec3aa96203c1629174c75b9b00)) + +## [0.9.0](https://github.com/supabase/storage-py/compare/v0.8.2...v0.9.0) (2024-10-28) + + +### Features + +* remove methods from the bucket object ([#305](https://github.com/supabase/storage-py/issues/305)) ([faa914d](https://github.com/supabase/storage-py/commit/faa914dfc460bdc6a63955e8affbb1275f1e984f)) + + +### Bug Fixes + +* add correct return data for upload to signed url ([#309](https://github.com/supabase/storage-py/issues/309)) ([748067f](https://github.com/supabase/storage-py/commit/748067f791a86a4298dd9075227a1be98c0ca4cc)) +* add search params to list buckets method ([#308](https://github.com/supabase/storage-py/issues/308)) ([fca2f00](https://github.com/supabase/storage-py/commit/fca2f005f3857e0f96b0505ab83474e3cf5e5e18)) +* upload and update method returns correct response body ([#307](https://github.com/supabase/storage-py/issues/307)) ([a9e874a](https://github.com/supabase/storage-py/commit/a9e874a12fd448d2eb3e48df2a80e187b9f41fbb)) + +## [0.8.2](https://github.com/supabase/storage-py/compare/v0.8.1...v0.8.2) (2024-10-18) + + +### Bug Fixes + +* bump minimal version of Python to 3.9 ([#302](https://github.com/supabase/storage-py/issues/302)) ([b0811b2](https://github.com/supabase/storage-py/commit/b0811b2b38d712d8cd136301663b0a5de20bf890)) + +## [0.8.1](https://github.com/supabase/storage-py/compare/v0.8.0...v0.8.1) (2024-10-02) + + +### Bug Fixes + +* httpx minimum version update ([#299](https://github.com/supabase/storage-py/issues/299)) ([90d2436](https://github.com/supabase/storage-py/commit/90d2436900558703129788679b356a21221f5c41)) + +## [0.8.0](https://github.com/supabase/storage-py/compare/v0.7.7...v0.8.0) (2024-09-28) + + +### Features + +* Proxy support ([#297](https://github.com/supabase/storage-py/issues/297)) ([59d733a](https://github.com/supabase/storage-py/commit/59d733a33145389b763c33985079257be0e3a8c3)) + +## v0.7.7 (2024-07-14) + +### Chore + +* chore(deps-dev): bump python-semantic-release from 9.8.3 to 9.8.5 (#276) + +Signed-off-by: dependabot[bot] <support@github.com> +Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> ([`0676ed6`](https://github.com/supabase-community/storage-py/commit/0676ed68d83f38649b869613b0e903e042248bec)) + +* chore: bump dependencies ([`89876df`](https://github.com/supabase-community/storage-py/commit/89876dfcf7721fb87d716a61deac596127107368)) + +* chore(deps-dev): bump sphinx-toolbox from 3.6.0 to 3.7.0 (#273) + +Signed-off-by: dependabot[bot] <support@github.com> +Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> ([`bdcb828`](https://github.com/supabase-community/storage-py/commit/bdcb828a6fe38c7454cab8e16b2d094f105e38c5)) + +* chore(deps): bump certifi from 2024.2.2 to 2024.7.4 in the pip group across 1 directory (#275) + +Signed-off-by: dependabot[bot] <support@github.com> +Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> ([`867759d`](https://github.com/supabase-community/storage-py/commit/867759dc83a1a1e3aa20c017886425212ba4b024)) + +* chore(deps): bump python-semantic-release/python-semantic-release from 9.8.3 to 9.8.5 (#277) + +Signed-off-by: dependabot[bot] <support@github.com> +Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> ([`fd7a2b0`](https://github.com/supabase-community/storage-py/commit/fd7a2b011c37c52a745a49bdc2d7c8f1a90d6284)) + +* chore(deps-dev): bump sphinx-toolbox from 3.5.0 to 3.6.0 (#270) ([`a965424`](https://github.com/supabase-community/storage-py/commit/a965424de5200782b021056ce2d8e08b2d0d718a)) + +* chore(deps): bump python-semantic-release/python-semantic-release from 9.8.1 to 9.8.3 ([`36f45f1`](https://github.com/supabase-community/storage-py/commit/36f45f1b94f275ebebddb7b0df6f40b1b0570796)) + +* chore(deps-dev): bump python-semantic-release from 9.8.1 to 9.8.3 ([`1fb3885`](https://github.com/supabase-community/storage-py/commit/1fb388562dbafa202f1a9e743e44bea9d68ed726)) + +* chore(deps-dev): bump urllib3 from 2.2.1 to 2.2.2 in the pip group across 1 directory (#264) ([`af591ee`](https://github.com/supabase-community/storage-py/commit/af591ee9511500a7e6f1a4cb54aec08ad5fa9b65)) + +* chore(deps): bump typing-extensions from 4.12.1 to 4.12.2 (#263) ([`b22f82b`](https://github.com/supabase-community/storage-py/commit/b22f82bc0b80db2585b009c2dd31f3d27b6989a2)) + +* chore(deps-dev): bump requests from 2.31.0 to 2.32.2 in the pip group across 1 directory (#262) ([`82e6aed`](https://github.com/supabase-community/storage-py/commit/82e6aed5547cc4d5ee1b369cfc76ad55ba14bf49)) + +* chore(deps): bump python-semantic-release/python-semantic-release from 9.7.3 to 9.8.1 (#261) ([`fc80cee`](https://github.com/supabase-community/storage-py/commit/fc80ceea43505d7cc3aa6b64eddf3c9eafe81254)) + +* chore(deps-dev): bump python-semantic-release from 9.7.3 to 9.8.1 (#259) ([`ddad5dd`](https://github.com/supabase-community/storage-py/commit/ddad5dd9089575fdfb0223fdb40c73594fde5f12)) + +* chore(deps): bump typing-extensions from 4.11.0 to 4.12.1 (#258) ([`a1ec9b1`](https://github.com/supabase-community/storage-py/commit/a1ec9b105c6ffc8989b3ea0fdf6fb4506e4aa842)) + +### Fix + +* fix: version bump (#278) ([`cd12e97`](https://github.com/supabase-community/storage-py/commit/cd12e97f1e61b1d52c10de6b6ccaa3f47c4310a0)) + +### Unknown + +* Enable HTTP2 (#271) ([`f98d565`](https://github.com/supabase-community/storage-py/commit/f98d565e65791103cb9f79da0bbcc4401f127ab2)) + +## v0.7.6 (2024-06-05) + +### Fix + +* fix: follow redirects (#257) ([`521fbd9`](https://github.com/supabase-community/storage-py/commit/521fbd924e0633b202fa792d5a52cf241e455060)) + +## v0.7.5 (2024-06-04) + +### Chore + +* chore(deps): bump python-semantic-release/python-semantic-release from 9.7.2 to 9.7.3 (#249) ([`ed5ed18`](https://github.com/supabase-community/storage-py/commit/ed5ed1826fdb1ec399e81e6d54b659125321f81e)) + +* chore(deps-dev): bump python-semantic-release from 9.7.2 to 9.7.3 (#248) ([`da71dd4`](https://github.com/supabase-community/storage-py/commit/da71dd4bf2be866a1642eab17bb78144f0597e85)) + +* chore(deps-dev): bump python-semantic-release from 9.4.1 to 9.7.2 (#246) ([`eef7b04`](https://github.com/supabase-community/storage-py/commit/eef7b0493e1ec43deb7e183eaadb87fc03ebff49)) + +* chore(deps): bump python-semantic-release/python-semantic-release from 9.4.1 to 9.7.2 (#247) ([`1527f18`](https://github.com/supabase-community/storage-py/commit/1527f184cd2530a5ec5c294c4eadb811056df0d6)) + +* chore: update .pre-commit-config.yaml (#240) ([`69ae839`](https://github.com/supabase-community/storage-py/commit/69ae8398328955c4b51a4b7ef4a5e1eb043dace1)) + +* chore(deps-dev): bump black from 24.3.0 to 24.4.2 (#236) ([`0449382`](https://github.com/supabase-community/storage-py/commit/04493823df2ee691a2cb3c7a4c04206474af4096)) + +* chore(tests): add supabase cli for tests (#245) ([`b148b09`](https://github.com/supabase-community/storage-py/commit/b148b090831210f06a30a9f08f0cc58728cbe810)) + +* chore(deps): bump idna from 3.6 to 3.7 (#228) ([`3ff6eed`](https://github.com/supabase-community/storage-py/commit/3ff6eed6e4410b52490cce7b2359dbfd59fb3cf6)) + +* chore(deps-dev): bump python-semantic-release from 9.3.0 to 9.4.1 (#225) ([`0b6dc6c`](https://github.com/supabase-community/storage-py/commit/0b6dc6cd6f7ef844c4edf485680b9bde57bc4acb)) + +* chore(deps): bump python-semantic-release/python-semantic-release from 9.4.0 to 9.4.1 (#227) ([`4ce32bc`](https://github.com/supabase-community/storage-py/commit/4ce32bc262c3b2a73df8cb2c08e28ffa2052176e)) + +* chore(deps): bump typing-extensions from 4.10.0 to 4.11.0 (#226) ([`2650cd8`](https://github.com/supabase-community/storage-py/commit/2650cd8195f17cf5ab11d5315a710bd8ac5ab629)) + +* chore(deps-dev): bump pytest-cov from 4.1.0 to 5.0.0 (#221) ([`2754a9e`](https://github.com/supabase-community/storage-py/commit/2754a9eaab978275bbfa316bbf3c70da3d61fb74)) + +* chore(deps): bump actions/cache from 3 to 4 (#219) ([`664519c`](https://github.com/supabase-community/storage-py/commit/664519c714e1a23e07047339d9a307aa630d9552)) + +* chore(deps): bump abatilo/actions-poetry from 2 to 3 (#218) ([`75e9dba`](https://github.com/supabase-community/storage-py/commit/75e9dba8bcb68010df2dfeb65d48ecb54dc32223)) + +* chore(deps): bump python-semantic-release/python-semantic-release from 9.3.0 to 9.4.0 (#224) ([`176d0da`](https://github.com/supabase-community/storage-py/commit/176d0da2934e7205982496cedf1c2c03874a0638)) + +### Fix + +* fix: add "verify" flag to the creation of client ([`9ad75b0`](https://github.com/supabase-community/storage-py/commit/9ad75b0a7259dcd21c2a854ca4a498b67afa1611)) + +### Unknown + +* Add stale bot (#237) ([`81935d3`](https://github.com/supabase-community/storage-py/commit/81935d38e1e2eefebe96dc91d8af012e015caf83)) + +## v0.7.4 (2024-03-23) + +### Chore + +* chore(deps-dev): bump python-semantic-release from 9.1.1 to 9.3.0 (#213) + +Signed-off-by: dependabot[bot] <support@github.com> +Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> ([`e2f594f`](https://github.com/supabase-community/storage-py/commit/e2f594f17b3f3596779b1aa83c60841868657503)) + +* chore(deps): bump python-dateutil from 2.8.2 to 2.9.0.post0 (#201) + +Signed-off-by: dependabot[bot] <support@github.com> +Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> ([`7471e7a`](https://github.com/supabase-community/storage-py/commit/7471e7a7c36750692b03501805e9059863787f99)) + +* chore: update ci pipeline to include python 3.12 in tests (#217) ([`dd264f1`](https://github.com/supabase-community/storage-py/commit/dd264f1793f3ca86ad544d5cdc0dcbb786c22904)) + +* chore(deps): bump httpx from 0.25.0 to 0.27.0 (#192) + +Signed-off-by: dependabot[bot] <support@github.com> +Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> ([`25b2d02`](https://github.com/supabase-community/storage-py/commit/25b2d02c7a7de2cd084a6644d40f7443acacc21c)) + +* chore(deps-dev): bump jinja2 from 3.1.2 to 3.1.3 (#182) + +Signed-off-by: dependabot[bot] <support@github.com> +Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> ([`3b419f5`](https://github.com/supabase-community/storage-py/commit/3b419f50adb893ce34bced49fc9ed4fe8bd27c6c)) + +* chore(deps): bump python-semantic-release/python-semantic-release from 9.2.2 to 9.3.0 (#215) + +Signed-off-by: dependabot[bot] <support@github.com> +Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> ([`290442a`](https://github.com/supabase-community/storage-py/commit/290442a13f5143af6db14a4a830ef319cab883e7)) + +* chore(deps-dev): bump pytest from 8.1.0 to 8.1.1 (#206) + +Signed-off-by: dependabot[bot] <support@github.com> +Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> ([`8bcb7a5`](https://github.com/supabase-community/storage-py/commit/8bcb7a5963d0d694ea20fe7f1da31e2474950809)) + +* chore(deps-dev): bump black from 24.2.0 to 24.3.0 (#208) + +Signed-off-by: dependabot[bot] <support@github.com> +Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> ([`e19d5c0`](https://github.com/supabase-community/storage-py/commit/e19d5c0311813cccf74a726fa7bbe9aee86a0765)) + +* chore(deps): bump python-semantic-release/python-semantic-release from 9.1.1 to 9.2.2 (#210) + +Signed-off-by: dependabot[bot] <support@github.com> +Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> ([`c22f449`](https://github.com/supabase-community/storage-py/commit/c22f44936e14aba015da29c2709c8943ed11cef8)) + +### Fix + +* fix: bump sphinx-press-theme from 0.8.0 to 0.9.1 (#216) + +Signed-off-by: dependabot[bot] <support@github.com> +Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> ([`4da4b73`](https://github.com/supabase-community/storage-py/commit/4da4b735e28400967f9303df14c7936a988dcf97)) + +## v0.7.3 (2024-03-11) + +### Chore + +* chore: update CODEOWNERS to use python-maintainers (#204) ([`4dc6a5a`](https://github.com/supabase-community/storage-py/commit/4dc6a5a0944f540a394c4bdda6250d33c40a4758)) + +### Fix + +* fix: add json decode error import (#205) ([`7327175`](https://github.com/supabase-community/storage-py/commit/732717510ed2aab7a2b131861b1a6b65fcb6a0dd)) + +## v0.7.2 (2024-03-10) + +### Chore + +* chore(deps-dev): bump black from 23.10.0 to 24.2.0 (#193) + +Signed-off-by: dependabot[bot] <support@github.com> +Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> ([`4613502`](https://github.com/supabase-community/storage-py/commit/46135021e8a0fcdc4d41c8465831092b13b9b326)) + +### Fix + +* fix: add upsert option to upload/update (#199) ([`db1b66a`](https://github.com/supabase-community/storage-py/commit/db1b66a0f12795e6ed4be1f3adb5776c296f3ede)) + +## v0.7.1 (2024-03-10) + +### Chore + +* chore(deps-dev): bump pytest from 7.4.4 to 8.1.0 (#200) + +Signed-off-by: dependabot[bot] <support@github.com> +Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> ([`bcb0af7`](https://github.com/supabase-community/storage-py/commit/bcb0af74468868eb5610d4b2e83f248b8baf6a7c)) + +* chore(deps): bump python-semantic-release/python-semantic-release from 8.0.0 to 9.1.1 (#188) + +Signed-off-by: dependabot[bot] <support@github.com> +Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> ([`dd56b26`](https://github.com/supabase-community/storage-py/commit/dd56b26012c6d71a93895ada757f3c1d04e19618)) + +* chore(deps): bump sphinx-notes/pages from 2 to 3 (#198) + +Signed-off-by: dependabot[bot] <support@github.com> +Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> ([`e592b7d`](https://github.com/supabase-community/storage-py/commit/e592b7dd80976cab138a9b27f45897e43cd07b06)) + +* chore(deps): bump codecov/codecov-action from 1 to 4 (#197) + +Signed-off-by: dependabot[bot] <support@github.com> +Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> ([`5928a4a`](https://github.com/supabase-community/storage-py/commit/5928a4a4aba43a892fb081c93f219fb5278b665b)) + +* chore(deps-dev): bump pre-commit from 3.4.0 to 3.5.0 (#156) + +Signed-off-by: dependabot[bot] <support@github.com> +Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> +Co-authored-by: Rodrigo Mansueli <rodrigo@mansueli.com> ([`331779f`](https://github.com/supabase-community/storage-py/commit/331779f2d3299d0561aba6db5421cfc233204899)) + +* chore(deps): bump github/codeql-action from 2 to 3 (#189) + +Signed-off-by: dependabot[bot] <support@github.com> +Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> ([`5db5fd2`](https://github.com/supabase-community/storage-py/commit/5db5fd29cf07fbc145a8e1a784959921a6eb1ba4)) + +* chore(deps): bump actions/setup-python from 2 to 5 (#190) + +Signed-off-by: dependabot[bot] <support@github.com> +Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> ([`6160615`](https://github.com/supabase-community/storage-py/commit/6160615201c9da59961e8d8016a4244dbe16f571)) + +* chore(deps): bump abatilo/actions-poetry from 2.2.0 to 3.0.0 (#186) + +Signed-off-by: dependabot[bot] <support@github.com> +Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> ([`1d02c5a`](https://github.com/supabase-community/storage-py/commit/1d02c5a66dde8cf91ef258e2a5db91c9af5eaca1)) + +* chore(deps): bump actions/checkout from 2 to 4 (#187) + +Signed-off-by: dependabot[bot] <support@github.com> +Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> ([`dd7e0a5`](https://github.com/supabase-community/storage-py/commit/dd7e0a5c7b4652efa85ab6ed76c24f266e4c0e06)) + +* chore(deps-dev): bump python-semantic-release from 8.1.1 to 9.1.1 (#191) + +Signed-off-by: dependabot[bot] <support@github.com> +Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> ([`504c8b2`](https://github.com/supabase-community/storage-py/commit/504c8b2201c7463126722ec9bb68413165908a92)) + +### Fix + +* fix: handle json decode error when there's no json response (e.g. on 403) (#203) + +Co-authored-by: joel <joel@joels-MacBook-Pro.local> ([`cce5ad4`](https://github.com/supabase-community/storage-py/commit/cce5ad420fa01bc032f55822572aa9e9c0061be0)) + +### Unknown + +* Update poetry.lock (#195) ([`641c24e`](https://github.com/supabase-community/storage-py/commit/641c24ee72865e27526a3e10891a437024b6e9ff)) + +* Merge branch 'main' of https://github.com/supabase-community/storage-py ([`84e26e2`](https://github.com/supabase-community/storage-py/commit/84e26e28179aca2eacc180932e1f49e71d04f713)) + +* Update dependabot.yml (#185) ([`1f2c2f8`](https://github.com/supabase-community/storage-py/commit/1f2c2f8fdf9e1e1501985f27cddaf61595c8ff5b)) + +* Update poetry.lock ([`1e81c90`](https://github.com/supabase-community/storage-py/commit/1e81c90be16bcbc6f245fa7a9dfc06ded0932206)) + +* Update MAINTAINERS.md ([`d3f7e8c`](https://github.com/supabase-community/storage-py/commit/d3f7e8c334815c63a77496d6f4ffef36b729f082)) + +* Update MAINTAINERS.md (#175) ([`6816f0c`](https://github.com/supabase-community/storage-py/commit/6816f0cf36c5995fb6cbf6e5bf9ad0b16e801bf3)) + +## v0.7.0 (2023-11-22) + +### Chore + +* chore: update GitHub workflow for releases ([`72ad275`](https://github.com/supabase-community/storage-py/commit/72ad2752849621446fd1df7ebc0b85dc4d9cf4cd)) + +* chore: add sync version of the update function ([`18c14a4`](https://github.com/supabase-community/storage-py/commit/18c14a4e7888cd14d09b7cbbd2e8b02f9cef02f0)) + +* chore(deps-dev): bump urllib3 from 2.0.5 to 2.0.7 + +Bumps [urllib3](https://github.com/urllib3/urllib3) from 2.0.5 to 2.0.7. +- [Release notes](https://github.com/urllib3/urllib3/releases) +- [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst) +- [Commits](https://github.com/urllib3/urllib3/compare/v2.0.5...2.0.7) + +--- +updated-dependencies: +- dependency-name: urllib3 + dependency-type: indirect +... + +Signed-off-by: dependabot[bot] <support@github.com> ([`79c9ca3`](https://github.com/supabase-community/storage-py/commit/79c9ca3b23e13e7f1d3788edc99d5939f59d0960)) + +* chore(deps-dev): bump pytest from 7.4.2 to 7.4.3 + +Bumps [pytest](https://github.com/pytest-dev/pytest) from 7.4.2 to 7.4.3. +- [Release notes](https://github.com/pytest-dev/pytest/releases) +- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst) +- [Commits](https://github.com/pytest-dev/pytest/compare/7.4.2...7.4.3) + +--- +updated-dependencies: +- dependency-name: pytest + dependency-type: direct:development + update-type: version-update:semver-patch +... + +Signed-off-by: dependabot[bot] <support@github.com> ([`87125bc`](https://github.com/supabase-community/storage-py/commit/87125bccaee9eeffd136af5ee8c442a4161b4761)) + +* chore(deps-dev): bump black from 23.9.1 to 23.10.0 + +Bumps [black](https://github.com/psf/black) from 23.9.1 to 23.10.0. +- [Release notes](https://github.com/psf/black/releases) +- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md) +- [Commits](https://github.com/psf/black/compare/23.9.1...23.10.0) + +--- +updated-dependencies: +- dependency-name: black + dependency-type: direct:development + update-type: version-update:semver-minor +... + +Signed-off-by: dependabot[bot] <support@github.com> ([`ac6f901`](https://github.com/supabase-community/storage-py/commit/ac6f9017d8cde34b930b0436af5f413fc589b12f)) + +### Feature + +* feat: add update existing file function ([`da4d785`](https://github.com/supabase-community/storage-py/commit/da4d785028e86899f1efc23394883836b94cd0d3)) + +### Unknown + +* Merge pull request #166 from supabase-community/chore/update-gh-workflow + +chore: update GitHub workflow for releases ([`f42d176`](https://github.com/supabase-community/storage-py/commit/f42d1766d4a8649a995ae474185eb50d0572bf2c)) + +* Merge pull request #165 from supabase-community/silentworks/file_update + +feat: add update existing file function ([`d8139e0`](https://github.com/supabase-community/storage-py/commit/d8139e0e36f5d083262e61809e74313969de7996)) + +* Merge pull request #158 from supabase-community/dependabot/pip/urllib3-2.0.7 + +chore(deps-dev): bump urllib3 from 2.0.5 to 2.0.7 ([`fc8cb5d`](https://github.com/supabase-community/storage-py/commit/fc8cb5d60511d3e795614ff17facebe22b6f93f2)) + +* Merge pull request #162 from supabase-community/dependabot/pip/main/pytest-7.4.3 + +chore(deps-dev): bump pytest from 7.4.2 to 7.4.3 ([`9b048cb`](https://github.com/supabase-community/storage-py/commit/9b048cbb913b725f326e1c3e8eaa4b9377b6f1d6)) + +* Merge pull request #159 from supabase-community/dependabot/pip/main/black-23.10.0 + +chore(deps-dev): bump black from 23.9.1 to 23.10.0 ([`0f332fa`](https://github.com/supabase-community/storage-py/commit/0f332fa714636f343deb390ec58a288563fc81d2)) + +## v0.6.1 (2023-10-02) + +### Documentation + +* docs: fix name of URLOptions type ([`5430e92`](https://github.com/supabase-community/storage-py/commit/5430e920492e6616ce833318daef44176b282401)) + +### Fix + +* fix: make precommit ignore markdown files ([`d2530fe`](https://github.com/supabase-community/storage-py/commit/d2530fe4b661e9b43dc6a0e124ac60ab3ffc64c9)) + +* fix: pass cache-control as formdata ([`9910fe0`](https://github.com/supabase-community/storage-py/commit/9910fe0d9e88c60798773d42a4449b1df62068ed)) + +* fix: use correct Any for typehint ([`5ad2ae8`](https://github.com/supabase-community/storage-py/commit/5ad2ae8ed67b6f8fe60ceff8ff6a85d92ac36725)) + +### Unknown + +* Merge pull request #154 from supabase-community/fix/cache-control + +fix: send cache-control as form data ([`bab90b6`](https://github.com/supabase-community/storage-py/commit/bab90b67f49631f7a8b2f77998a205b9d9029926)) + +## v0.6.0 (2023-09-28) + +### Chore + +* chore: run unasync ([`fc93662`](https://github.com/supabase-community/storage-py/commit/fc936629932271b12bb741b87140744c83d2369b)) + +* chore(deps-dev): bump pytest from 7.4.0 to 7.4.2 + +Bumps [pytest](https://github.com/pytest-dev/pytest) from 7.4.0 to 7.4.2. +- [Release notes](https://github.com/pytest-dev/pytest/releases) +- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst) +- [Commits](https://github.com/pytest-dev/pytest/compare/7.4.0...7.4.2) + +--- +updated-dependencies: +- dependency-name: pytest + dependency-type: direct:development + update-type: version-update:semver-patch +... + +Signed-off-by: dependabot[bot] <support@github.com> ([`08ea297`](https://github.com/supabase-community/storage-py/commit/08ea297ef0982c70444b0aab8da4072710e7458f)) + +### Feature + +* feat: bump version ([`10ba8be`](https://github.com/supabase-community/storage-py/commit/10ba8be2e1ef45cfc3a596a88e9a674fe5308b0b)) + +### Fix + +* fix: make download key optional ([`dbf8213`](https://github.com/supabase-community/storage-py/commit/dbf82137eb3c18b8892bf1853072f9e82dd0d57b)) + +### Unknown + +* Merge pull request #153 from supabase-community/fix/remove-required-key + +fix: make download key optional ([`d0c47c7`](https://github.com/supabase-community/storage-py/commit/d0c47c7dc72864c7e256f27d5d68ccebaff2c18a)) + +* Merge pull request #152 from supabase-community/j0/test_workflow + +feat: bump version ([`9b227ce`](https://github.com/supabase-community/storage-py/commit/9b227ce01b18093ee4967d4eaf249f43c7a22f60)) + +* Merge pull request #151 from supabase-community/fix/github-workflow-update + +Update python-semantic-release version and ci ([`bf49d51`](https://github.com/supabase-community/storage-py/commit/bf49d514390b86670b61ce2b5cd2b7fd8a92d6c3)) + +* Update python-semantic-release version and ci ([`ad7fc6d`](https://github.com/supabase-community/storage-py/commit/ad7fc6dab3a5be062598e64f4b287370eafcacd5)) + +* Merge pull request #150 from supabase-community/fix/github-workflow + +Fix semantic releaase workflow ([`e13cb9e`](https://github.com/supabase-community/storage-py/commit/e13cb9e5cbc735635d70a8d6f8c3df5b39eb739b)) + +* Fix semantic releaase workflow ([`3a00104`](https://github.com/supabase-community/storage-py/commit/3a00104fe5206bb48db9e440d8abfe503a6b505f)) + +* Merge pull request #149 from supabase-community/fix/correct-option-type-for-transforms + +Fix image transforms options ([`64a8ab2`](https://github.com/supabase-community/storage-py/commit/64a8ab21713d3b80c647ab54ef78f553744d5ad8)) + +* Ran pre-commit hooks ([`f8f7482`](https://github.com/supabase-community/storage-py/commit/f8f7482de2088a5539b3c68f53e4c76578c58a70)) + +* Rename options typehint +Add download option to get_public_url ([`4fc7d8d`](https://github.com/supabase-community/storage-py/commit/4fc7d8d9b6dfcfc8068834cfed1fdd5691ae38fc)) + +* Fix image transforms options ([`f007596`](https://github.com/supabase-community/storage-py/commit/f007596743ce18647cca782f7765716d4779f3a8)) + +* Merge pull request #136 from supabase-community/dependabot/pip/main/pytest-7.4.2 + +chore(deps-dev): bump pytest from 7.4.0 to 7.4.2 ([`7229864`](https://github.com/supabase-community/storage-py/commit/72298641ef1e15e54b897e9ff7ccdffffce511f5)) + +## v0.5.5 (2023-09-15) + +### Chore + +* chore: run black ([`14be266`](https://github.com/supabase-community/storage-py/commit/14be2669e381e3bd3fd3a2b73f8a76a3294f33b1)) + +* chore: create CODEOWNERS ([`8077001`](https://github.com/supabase-community/storage-py/commit/8077001711360c1d7ff2084089ee7eff1b1c99f4)) + +* chore(deps-dev): bump black from 23.7.0 to 23.9.1 + +Bumps [black](https://github.com/psf/black) from 23.7.0 to 23.9.1. +- [Release notes](https://github.com/psf/black/releases) +- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md) +- [Commits](https://github.com/psf/black/compare/23.7.0...23.9.1) + +--- +updated-dependencies: +- dependency-name: black + dependency-type: direct:development + update-type: version-update:semver-minor +... + +Signed-off-by: dependabot[bot] <support@github.com> ([`e789223`](https://github.com/supabase-community/storage-py/commit/e78922316e4189e19ff3a9d8c3ee38644014c42f)) + +* chore(deps-dev): bump gitpython from 3.1.32 to 3.1.35 + +Bumps [gitpython](https://github.com/gitpython-developers/GitPython) from 3.1.32 to 3.1.35. +- [Release notes](https://github.com/gitpython-developers/GitPython/releases) +- [Changelog](https://github.com/gitpython-developers/GitPython/blob/main/CHANGES) +- [Commits](https://github.com/gitpython-developers/GitPython/compare/3.1.32...3.1.35) + +--- +updated-dependencies: +- dependency-name: gitpython + dependency-type: indirect +... + +Signed-off-by: dependabot[bot] <support@github.com> ([`0497ef2`](https://github.com/supabase-community/storage-py/commit/0497ef221bb7382170e4f8267f5ea1f768c5619f)) + +* chore(deps-dev): bump pre-commit from 3.3.3 to 3.4.0 + +Bumps [pre-commit](https://github.com/pre-commit/pre-commit) from 3.3.3 to 3.4.0. +- [Release notes](https://github.com/pre-commit/pre-commit/releases) +- [Changelog](https://github.com/pre-commit/pre-commit/blob/main/CHANGELOG.md) +- [Commits](https://github.com/pre-commit/pre-commit/compare/v3.3.3...v3.4.0) + +--- +updated-dependencies: +- dependency-name: pre-commit + dependency-type: direct:development + update-type: version-update:semver-minor +... + +Signed-off-by: dependabot[bot] <support@github.com> ([`11b2d5a`](https://github.com/supabase-community/storage-py/commit/11b2d5a382d89b850cf6692fd11563422c307321)) + +* chore(deps-dev): bump python-semantic-release from 8.0.4 to 8.0.8 + +Bumps [python-semantic-release](https://github.com/python-semantic-release/python-semantic-release) from 8.0.4 to 8.0.8. +- [Release notes](https://github.com/python-semantic-release/python-semantic-release/releases) +- [Changelog](https://github.com/python-semantic-release/python-semantic-release/blob/master/CHANGELOG.md) +- [Commits](https://github.com/python-semantic-release/python-semantic-release/compare/v8.0.4...v8.0.8) + +--- +updated-dependencies: +- dependency-name: python-semantic-release + dependency-type: direct:development + update-type: version-update:semver-patch +... + +Signed-off-by: dependabot[bot] <support@github.com> ([`0de10b2`](https://github.com/supabase-community/storage-py/commit/0de10b2d39ed455114c8e049df973477f09d135c)) + +* chore(deps): bump httpx from 0.24.1 to 0.25.0 + +Bumps [httpx](https://github.com/encode/httpx) from 0.24.1 to 0.25.0. +- [Release notes](https://github.com/encode/httpx/releases) +- [Changelog](https://github.com/encode/httpx/blob/master/CHANGELOG.md) +- [Commits](https://github.com/encode/httpx/compare/0.24.1...0.25.0) + +--- +updated-dependencies: +- dependency-name: httpx + dependency-type: direct:production + update-type: version-update:semver-minor +... + +Signed-off-by: dependabot[bot] <support@github.com> ([`801681c`](https://github.com/supabase-community/storage-py/commit/801681c7c4458143e3e9ef23140456608fe09d5c)) + +### Fix + +* fix: run unasync and also patch type ([`98aae1c`](https://github.com/supabase-community/storage-py/commit/98aae1c7b8ebb383ab005fbaf4c70f8b388bca9e)) + +### Unknown + +* Merge pull request #143 from supabase-community/j0/patch_remove_type + +fix: patch type on remove ([`8dbd29a`](https://github.com/supabase-community/storage-py/commit/8dbd29aef0f9e5b74724f6405d325413c02247cb)) + +* Merge pull request #142 from supabase-community/j0/add_semver + +feat:add semver ([`eaf869a`](https://github.com/supabase-community/storage-py/commit/eaf869a1f03efb9b3f6d0feb1b07b35117581ede)) + +* Update pyproject.toml ([`b3abdb7`](https://github.com/supabase-community/storage-py/commit/b3abdb79ee28eaeeb9fbff9f5464940f80c3bcdc)) + +* Update ci.yml + +change ref to main ([`1ff3e20`](https://github.com/supabase-community/storage-py/commit/1ff3e20d7fb5c8fa21455e21fd388e66cb96b86c)) + +* feat:add semver ([`ff91715`](https://github.com/supabase-community/storage-py/commit/ff9171505b99573788879e86aeb897a8461c42ec)) + +* Merge pull request #141 from supabase-community/J0/add-codeowners + +chore: create CODEOWNERS ([`e25c803`](https://github.com/supabase-community/storage-py/commit/e25c8031363cee2c6a62c673ee613329c8fd401f)) + +* Merge pull request #139 from supabase-community/dependabot/pip/main/black-23.9.1 + +chore(deps-dev): bump black from 23.7.0 to 23.9.1 ([`d8f6584`](https://github.com/supabase-community/storage-py/commit/d8f6584bcd7ae67606b286bdfd9ed9fdf9a6a63a)) + +* Merge pull request #140 from supabase-community/dependabot/pip/gitpython-3.1.35 + +chore(deps-dev): bump gitpython from 3.1.32 to 3.1.35 ([`b39d082`](https://github.com/supabase-community/storage-py/commit/b39d0821c18896aa750f2ae9db0324e0500d5b05)) + +* Merge pull request #134 from supabase-community/dependabot/pip/main/pre-commit-3.4.0 + +chore(deps-dev): bump pre-commit from 3.3.3 to 3.4.0 ([`1ae2b4d`](https://github.com/supabase-community/storage-py/commit/1ae2b4de3f2e7ff96c2adb2ccc9687ff3743eea2)) + +* Merge pull request #132 from supabase-community/dependabot/pip/main/python-semantic-release-8.0.8 + +chore(deps-dev): bump python-semantic-release from 8.0.4 to 8.0.8 ([`bf90db3`](https://github.com/supabase-community/storage-py/commit/bf90db3fd0eacf0219480e0db3db2fa1501e2c9c)) + +* Merge pull request #138 from supabase-community/dependabot/pip/main/httpx-0.25.0 + +chore(deps): bump httpx from 0.24.1 to 0.25.0 ([`f09b35d`](https://github.com/supabase-community/storage-py/commit/f09b35dd46181ec99fdefee3755b4cb0adcfa232)) + +## v0.5.4 (2023-08-04) + +### Chore + +* chore(deps-dev): bump python-semantic-release from 7.34.3 to 8.0.4 + +Bumps [python-semantic-release](https://github.com/python-semantic-release/python-semantic-release) from 7.34.3 to 8.0.4. +- [Release notes](https://github.com/python-semantic-release/python-semantic-release/releases) +- [Changelog](https://github.com/python-semantic-release/python-semantic-release/blob/master/CHANGELOG.md) +- [Commits](https://github.com/python-semantic-release/python-semantic-release/compare/v7.34.3...v8.0.4) + +--- +updated-dependencies: +- dependency-name: python-semantic-release + dependency-type: direct:development + update-type: version-update:semver-major +... + +Signed-off-by: dependabot[bot] <support@github.com> ([`b99cd75`](https://github.com/supabase-community/storage-py/commit/b99cd754e1b7b30a1f1cc11e31b184cd0ad6401e)) + +* chore(deps-dev): bump sphinx from 7.1.1 to 7.1.2 + +Bumps [sphinx](https://github.com/sphinx-doc/sphinx) from 7.1.1 to 7.1.2. +- [Release notes](https://github.com/sphinx-doc/sphinx/releases) +- [Changelog](https://github.com/sphinx-doc/sphinx/blob/master/CHANGES) +- [Commits](https://github.com/sphinx-doc/sphinx/compare/v7.1.1...v7.1.2) + +--- +updated-dependencies: +- dependency-name: sphinx + dependency-type: direct:development + update-type: version-update:semver-patch +... + +Signed-off-by: dependabot[bot] <support@github.com> ([`ec41599`](https://github.com/supabase-community/storage-py/commit/ec415999b10217bda5c1a00f32cd68adcecc6999)) + +* chore(deps): bump typing-extensions from 4.7.0 to 4.7.1 + +Bumps [typing-extensions](https://github.com/python/typing_extensions) from 4.7.0 to 4.7.1. +- [Release notes](https://github.com/python/typing_extensions/releases) +- [Changelog](https://github.com/python/typing_extensions/blob/main/CHANGELOG.md) +- [Commits](https://github.com/python/typing_extensions/compare/4.7.0...4.7.1) + +--- +updated-dependencies: +- dependency-name: typing-extensions + dependency-type: direct:production + update-type: version-update:semver-patch +... + +Signed-off-by: dependabot[bot] <support@github.com> ([`5c4a0e4`](https://github.com/supabase-community/storage-py/commit/5c4a0e4ffaece42cea4ab174751581759343e04e)) + +* chore(deps-dev): bump cryptography from 41.0.2 to 41.0.3 + +Bumps [cryptography](https://github.com/pyca/cryptography) from 41.0.2 to 41.0.3. +- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst) +- [Commits](https://github.com/pyca/cryptography/compare/41.0.2...41.0.3) + +--- +updated-dependencies: +- dependency-name: cryptography + dependency-type: indirect +... + +Signed-off-by: dependabot[bot] <support@github.com> ([`778deec`](https://github.com/supabase-community/storage-py/commit/778deecfe9da3e2834d22cfabdcdf77f0d84df14)) + +* chore: bump httpx to ^0.24 ([`cad86d0`](https://github.com/supabase-community/storage-py/commit/cad86d07783794d635261184a1c6ddba95f3341c)) + +### Feature + +* feat: bump version ([`1496da0`](https://github.com/supabase-community/storage-py/commit/1496da08ab4f6ed83fd7b38646459f9d0c771508)) + +### Unknown + +* Merge pull request #124 from supabase-community/dependabot/pip/main/python-semantic-release-8.0.4 + +chore(deps-dev): bump python-semantic-release from 7.34.3 to 8.0.4 ([`f9f0645`](https://github.com/supabase-community/storage-py/commit/f9f064576832654d7d47551ce953ef3ba7152d0c)) + +* Merge pull request #128 from supabase-community/dependabot/pip/main/sphinx-7.1.2 + +chore(deps-dev): bump sphinx from 7.1.1 to 7.1.2 ([`4bb4aa1`](https://github.com/supabase-community/storage-py/commit/4bb4aa173fd8d3afbda5d85e3d26d4f1592b2dfb)) + +* Merge pull request #114 from supabase-community/dependabot/pip/main/typing-extensions-4.7.1 + +chore(deps): bump typing-extensions from 4.7.0 to 4.7.1 ([`cc99771`](https://github.com/supabase-community/storage-py/commit/cc9977103c423f3f8acc4184c8398ba18b12a04a)) + +* Merge pull request #127 from supabase-community/dependabot/pip/cryptography-41.0.3 + +chore(deps-dev): bump cryptography from 41.0.2 to 41.0.3 ([`950da37`](https://github.com/supabase-community/storage-py/commit/950da37a23f82c220ef28067d9b5640524146216)) + +* Merge pull request #125 from supabase-community/bump-httpx + +chore: bump httpx to ^0.24 ([`56a7594`](https://github.com/supabase-community/storage-py/commit/56a75941c7b1cc0427d67e9dc3c91b51937b4e40)) + +## v0.5.3 (2023-07-24) + +### Chore + +* chore: bump pyproject ([`2f2b3a6`](https://github.com/supabase-community/storage-py/commit/2f2b3a6f143826c8eb36c96ee679fa5c2adaec10)) + +* chore(deps-dev): bump pre-commit from 3.3.2 to 3.3.3 + +Bumps [pre-commit](https://github.com/pre-commit/pre-commit) from 3.3.2 to 3.3.3. +- [Release notes](https://github.com/pre-commit/pre-commit/releases) +- [Changelog](https://github.com/pre-commit/pre-commit/blob/main/CHANGELOG.md) +- [Commits](https://github.com/pre-commit/pre-commit/compare/v3.3.2...v3.3.3) + +--- +updated-dependencies: +- dependency-name: pre-commit + dependency-type: direct:development + update-type: version-update:semver-patch +... + +Signed-off-by: dependabot[bot] <support@github.com> ([`5729d3c`](https://github.com/supabase-community/storage-py/commit/5729d3c1877b26ed044cd7ed6a60a91399700a70)) + +* chore(deps): bump typing-extensions from 4.6.3 to 4.7.0 + +Bumps [typing-extensions](https://github.com/python/typing_extensions) from 4.6.3 to 4.7.0. +- [Release notes](https://github.com/python/typing_extensions/releases) +- [Changelog](https://github.com/python/typing_extensions/blob/main/CHANGELOG.md) +- [Commits](https://github.com/python/typing_extensions/compare/4.6.3...4.7.0) + +--- +updated-dependencies: +- dependency-name: typing-extensions + dependency-type: direct:production + update-type: version-update:semver-minor +... + +Signed-off-by: dependabot[bot] <support@github.com> ([`a550c7d`](https://github.com/supabase-community/storage-py/commit/a550c7df410be594a0dc0b05fa0f588b4ae67900)) + +* chore(deps-dev): bump pytest from 7.3.2 to 7.4.0 + +Bumps [pytest](https://github.com/pytest-dev/pytest) from 7.3.2 to 7.4.0. +- [Release notes](https://github.com/pytest-dev/pytest/releases) +- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst) +- [Commits](https://github.com/pytest-dev/pytest/compare/7.3.2...7.4.0) + +--- +updated-dependencies: +- dependency-name: pytest + dependency-type: direct:development + update-type: version-update:semver-minor +... + +Signed-off-by: dependabot[bot] <support@github.com> ([`c008911`](https://github.com/supabase-community/storage-py/commit/c0089114d945bd08c15d562aafb7b1dda56512b3)) + +* chore(deps-dev): bump pytest from 7.3.1 to 7.3.2 (#108) + +Bumps [pytest](https://github.com/pytest-dev/pytest) from 7.3.1 to 7.3.2. +- [Release notes](https://github.com/pytest-dev/pytest/releases) +- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst) +- [Commits](https://github.com/pytest-dev/pytest/compare/7.3.1...7.3.2) + +--- +updated-dependencies: +- dependency-name: pytest + dependency-type: direct:development + update-type: version-update:semver-patch +... + +Signed-off-by: dependabot[bot] <support@github.com> +Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> ([`e5df2ff`](https://github.com/supabase-community/storage-py/commit/e5df2ff8a269337d206b7396ebab04039eb1684e)) + +* chore: test upload_to_signed_url ([`82ccab4`](https://github.com/supabase-community/storage-py/commit/82ccab43c98ae55078ed5fab76d9c12320261235)) + +* chore: test create_signed_upload_url ([`c330397`](https://github.com/supabase-community/storage-py/commit/c330397e2657f5e9415c9c4959c07d769ff807a6)) + +* chore(deps-dev): bump pytest-asyncio from 0.20.3 to 0.21.0 + +Bumps [pytest-asyncio](https://github.com/pytest-dev/pytest-asyncio) from 0.20.3 to 0.21.0. +- [Release notes](https://github.com/pytest-dev/pytest-asyncio/releases) +- [Commits](https://github.com/pytest-dev/pytest-asyncio/compare/v0.20.3...v0.21.0) + +--- +updated-dependencies: +- dependency-name: pytest-asyncio + dependency-type: direct:development + update-type: version-update:semver-minor +... + +Signed-off-by: dependabot[bot] <support@github.com> ([`8b22943`](https://github.com/supabase-community/storage-py/commit/8b229435d96d9cc86df48a39746ff9e5286990fa)) + +* chore(deps): bump httpx from 0.23.3 to 0.24.1 + +Bumps [httpx](https://github.com/encode/httpx) from 0.23.3 to 0.24.1. +- [Release notes](https://github.com/encode/httpx/releases) +- [Changelog](https://github.com/encode/httpx/blob/master/CHANGELOG.md) +- [Commits](https://github.com/encode/httpx/compare/0.23.3...0.24.1) + +--- +updated-dependencies: +- dependency-name: httpx + dependency-type: direct:production + update-type: version-update:semver-minor +... + +Signed-off-by: dependabot[bot] <support@github.com> ([`1eef352`](https://github.com/supabase-community/storage-py/commit/1eef352118ae685ad0682559a9ee57cfe2cfe5e1)) + +* chore: update dependencies (#101) ([`03c5b03`](https://github.com/supabase-community/storage-py/commit/03c5b0378d989384e3f2f6a5a7c2b588929dd321)) + +* chore(deps): bump httpx from 0.23.3 to 0.24.0 + +Bumps [httpx](https://github.com/encode/httpx) from 0.23.3 to 0.24.0. +- [Release notes](https://github.com/encode/httpx/releases) +- [Changelog](https://github.com/encode/httpx/blob/master/CHANGELOG.md) +- [Commits](https://github.com/encode/httpx/compare/0.23.3...0.24.0) + +--- +updated-dependencies: +- dependency-name: httpx + dependency-type: direct:production + update-type: version-update:semver-minor +... + +Signed-off-by: dependabot[bot] <support@github.com> ([`84335cd`](https://github.com/supabase-community/storage-py/commit/84335cd6f363496898b6a81f405c30d6e64092bb)) + +* chore(deps-dev): bump pytest from 7.2.2 to 7.3.1 (#88) + +Bumps [pytest](https://github.com/pytest-dev/pytest) from 7.2.2 to 7.3.1. +- [Release notes](https://github.com/pytest-dev/pytest/releases) +- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst) +- [Commits](https://github.com/pytest-dev/pytest/compare/7.2.2...7.3.1) + +--- +updated-dependencies: +- dependency-name: pytest + dependency-type: direct:development + update-type: version-update:semver-minor +... + +Signed-off-by: dependabot[bot] <support@github.com> +Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> ([`a95a244`](https://github.com/supabase-community/storage-py/commit/a95a24410be08e9276f3e8214b621f6b82fd81ba)) + +* chore(deps-dev): bump pre-commit from 3.1.1 to 3.2.0 (#79) + +Bumps [pre-commit](https://github.com/pre-commit/pre-commit) from 3.1.1 to 3.2.0. +- [Release notes](https://github.com/pre-commit/pre-commit/releases) +- [Changelog](https://github.com/pre-commit/pre-commit/blob/main/CHANGELOG.md) +- [Commits](https://github.com/pre-commit/pre-commit/compare/v3.1.1...v3.2.0) + +--- +updated-dependencies: +- dependency-name: pre-commit + dependency-type: direct:development + update-type: version-update:semver-minor +... + +Signed-off-by: dependabot[bot] <support@github.com> +Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> ([`a603a2a`](https://github.com/supabase-community/storage-py/commit/a603a2a684cf6d47eb5b58866c8c8263cc909852)) + +* chore(deps-dev): bump pytest from 7.2.1 to 7.2.2 + +Bumps [pytest](https://github.com/pytest-dev/pytest) from 7.2.1 to 7.2.2. +- [Release notes](https://github.com/pytest-dev/pytest/releases) +- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst) +- [Commits](https://github.com/pytest-dev/pytest/compare/7.2.1...7.2.2) + +--- +updated-dependencies: +- dependency-name: pytest + dependency-type: direct:development + update-type: version-update:semver-patch +... + +Signed-off-by: dependabot[bot] <support@github.com> ([`e764f25`](https://github.com/supabase-community/storage-py/commit/e764f2503d3ec256c1e4a1917a1fd5a8d7d8c427)) + +### Documentation + +* docs: document all typed dicts ([`1489757`](https://github.com/supabase-community/storage-py/commit/1489757be0492daf9da680267b483cb175df6e68)) + +### Feature + +* feat: add upload_to_signed_url ([`f756460`](https://github.com/supabase-community/storage-py/commit/f75646050e5694930e927d4ffce4b53da9a5b80c)) + +* feat: make create_signed_upload_url method ([`8343bde`](https://github.com/supabase-community/storage-py/commit/8343bde8f61fab5ed8bf5caf2d2dd876fd61ffd1)) + +* feat: created functions to get multiple signed URLs. (#105) + +* feat: created functions to get multiple signed URLs. + +* feat: Fixed optional params. Handling auth token issue #73 in separate PR. + +* feat: remove sync code as it will be generated by unasync. + +* chore: generate sync client + +--------- + +Co-authored-by: Alexander Leonov <alleonov@icloud.com> +Co-authored-by: anand2312 <40204976+anand2312@users.noreply.github.com> ([`2c5e2fc`](https://github.com/supabase-community/storage-py/commit/2c5e2fc309ab0f862a21e52da9b0e7c2c9d24e19)) + +* feat: bucket level file controls and an update_bucket method (#103) + +* feat: bucket level file controls and an update_bucket method + +* fix: import __future__ annotations + +python 3.8 doesn't allow subscripting types like list ([`80454f9`](https://github.com/supabase-community/storage-py/commit/80454f9f6de5d6d5db9840b848b39937fabf5407)) + +### Unknown + +* Merge pull request #123 from supabase-community/j0/bump_storage_0_5_3 + +feat: bump version to 0.5.3 ([`f1df45f`](https://github.com/supabase-community/storage-py/commit/f1df45f4a9f0c72ab64e2f63a40a51bf56909b33)) + +* Merge pull request #109 from supabase-community/dependabot/pip/main/pre-commit-3.3.3 + +chore(deps-dev): bump pre-commit from 3.3.2 to 3.3.3 ([`2eb5ae8`](https://github.com/supabase-community/storage-py/commit/2eb5ae808409c43ea74e490bb682cb5e7e6e5f65)) + +* Merge pull request #113 from supabase-community/dependabot/pip/main/typing-extensions-4.7.0 + +chore(deps): bump typing-extensions from 4.6.3 to 4.7.0 ([`3a10bc6`](https://github.com/supabase-community/storage-py/commit/3a10bc618e19a7e710413779a2d0cc4dd1d98b79)) + +* Merge pull request #112 from supabase-community/dependabot/pip/main/pytest-7.4.0 + +chore(deps-dev): bump pytest from 7.3.2 to 7.4.0 ([`5cc339d`](https://github.com/supabase-community/storage-py/commit/5cc339d837ac9c0d69d66faab6db42f871b7881b)) + +* Merge pull request #107 from supabase-community/anand/sign-upload-urls + +feat: methods for signed url uploads ([`d4757d2`](https://github.com/supabase-community/storage-py/commit/d4757d20194da4b80d5aaec4ab03a6537b694c57)) + +* Merge branch 'main' into anand/sign-upload-urls ([`2b65b0e`](https://github.com/supabase-community/storage-py/commit/2b65b0ea2ef08bce48895a0263ac9c34551fbf01)) + +* Merge pull request #78 from supabase-community/dependabot/pip/main/pytest-asyncio-0.21.0 + +chore(deps-dev): bump pytest-asyncio from 0.20.3 to 0.21.0 ([`7e86450`](https://github.com/supabase-community/storage-py/commit/7e86450d61edf9cbfc849aedd4dbcb2c2229dfe7)) + +* Merge pull request #106 from supabase-community/J0/update-pre-commit-black + +Update .pre-commit-config.yaml ([`27b765c`](https://github.com/supabase-community/storage-py/commit/27b765c2913ca8f0e5d5a1759986f4d0d0566bf9)) + +* Update .pre-commit-config.yaml ([`a6dca37`](https://github.com/supabase-community/storage-py/commit/a6dca37629f2aef2527a9156fd579f337f45fa13)) + +* Merge pull request #102 from supabase-community/dependabot/pip/main/httpx-0.24.1 + +chore(deps): bump httpx from 0.23.3 to 0.24.1 ([`fc18260`](https://github.com/supabase-community/storage-py/commit/fc18260c959323b1a4721d3187febff42020321b)) + +* Make FileOptions type (#100) + +* Update lockfile + +* feat: add FileOptions type, make some bucket fields optional + +* feat: use FileOptions in upload and document it + +* docs: add upload example to README + +* fix: don't mark BaseBucket fields as default + +this breaks every other class that inherits from BaseBucket and tries to add +any non-default field. ([`1585e42`](https://github.com/supabase-community/storage-py/commit/1585e4279427934d5e027fc3ea2874085748caa6)) + +* Merge pull request #87 from supabase-community/dependabot/pip/main/httpx-0.24.0 + +chore(deps): bump httpx from 0.23.3 to 0.24.0 ([`b69a8ba`](https://github.com/supabase-community/storage-py/commit/b69a8bac00c4a4c05ab224b34fd99a21a712b256)) + +* Merge branch 'main' into dependabot/pip/main/httpx-0.24.0 ([`c1b64e1`](https://github.com/supabase-community/storage-py/commit/c1b64e105e06f146499ef7503a958e4f143cd4ed)) + +* Fix bad typing on upload functions (#89) + +* Fix bad typing on upload functions + +* Format using black ([`40fc84b`](https://github.com/supabase-community/storage-py/commit/40fc84b7784b37b9da24c09d2eba2d282603c4fb)) + +* Merge pull request #76 from supabase-community/dependabot/pip/main/pytest-7.2.2 + +chore(deps-dev): bump pytest from 7.2.1 to 7.2.2 ([`eef5524`](https://github.com/supabase-community/storage-py/commit/eef55243385d80905d0186b58bcede2092b6c7e4)) + +## v0.5.2 (2023-03-05) + +### Chore + +* chore: bump version ([`91c4456`](https://github.com/supabase-community/storage-py/commit/91c4456b55113347d4da2dc26ee3a08dd893ea0e)) + +* chore(deps): bump typing-extensions from 4.4.0 to 4.5.0 + +Bumps [typing-extensions](https://github.com/python/typing_extensions) from 4.4.0 to 4.5.0. +- [Release notes](https://github.com/python/typing_extensions/releases) +- [Changelog](https://github.com/python/typing_extensions/blob/main/CHANGELOG.md) +- [Commits](https://github.com/python/typing_extensions/compare/4.4.0...4.5.0) + +--- +updated-dependencies: +- dependency-name: typing-extensions + dependency-type: direct:production + update-type: version-update:semver-minor +... + +Signed-off-by: dependabot[bot] <support@github.com> ([`daaf68d`](https://github.com/supabase-community/storage-py/commit/daaf68d2eb4833bc2b8afb459688dcf4c7be5343)) + +* chore(deps-dev): bump python-semantic-release from 7.33.1 to 7.33.2 + +Bumps [python-semantic-release](https://github.com/relekang/python-semantic-release) from 7.33.1 to 7.33.2. +- [Release notes](https://github.com/relekang/python-semantic-release/releases) +- [Changelog](https://github.com/python-semantic-release/python-semantic-release/blob/master/CHANGELOG.md) +- [Commits](https://github.com/relekang/python-semantic-release/compare/v7.33.1...v7.33.2) + +--- +updated-dependencies: +- dependency-name: python-semantic-release + dependency-type: direct:development + update-type: version-update:semver-patch +... + +Signed-off-by: dependabot[bot] <support@github.com> ([`698672c`](https://github.com/supabase-community/storage-py/commit/698672c533cc595f1c1e54b1e230e85bed4fb274)) + +* chore(deps-dev): bump python-dotenv from 0.21.1 to 1.0.0 + +Bumps [python-dotenv](https://github.com/theskumar/python-dotenv) from 0.21.1 to 1.0.0. +- [Release notes](https://github.com/theskumar/python-dotenv/releases) +- [Changelog](https://github.com/theskumar/python-dotenv/blob/main/CHANGELOG.md) +- [Commits](https://github.com/theskumar/python-dotenv/compare/v0.21.1...v1.0.0) + +--- +updated-dependencies: +- dependency-name: python-dotenv + dependency-type: direct:development + update-type: version-update:semver-major +... + +Signed-off-by: dependabot[bot] <support@github.com> ([`192120c`](https://github.com/supabase-community/storage-py/commit/192120c6c332b06f426289dee4980cd1bed441cb)) + +* chore(deps-dev): bump black from 22.12.0 to 23.1.0 + +Bumps [black](https://github.com/psf/black) from 22.12.0 to 23.1.0. +- [Release notes](https://github.com/psf/black/releases) +- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md) +- [Commits](https://github.com/psf/black/compare/22.12.0...23.1.0) + +--- +updated-dependencies: +- dependency-name: black + dependency-type: direct:development + update-type: version-update:semver-major +... + +Signed-off-by: dependabot[bot] <support@github.com> ([`af38774`](https://github.com/supabase-community/storage-py/commit/af387746d0d18723afbe92595a0f47b285120d92)) + +* chore(deps-dev): bump pre-commit from 2.21.0 to 3.1.1 + +Bumps [pre-commit](https://github.com/pre-commit/pre-commit) from 2.21.0 to 3.1.1. +- [Release notes](https://github.com/pre-commit/pre-commit/releases) +- [Changelog](https://github.com/pre-commit/pre-commit/blob/main/CHANGELOG.md) +- [Commits](https://github.com/pre-commit/pre-commit/compare/v2.21.0...v3.1.1) + +--- +updated-dependencies: +- dependency-name: pre-commit + dependency-type: direct:development + update-type: version-update:semver-major +... + +Signed-off-by: dependabot[bot] <support@github.com> ([`ec3b46c`](https://github.com/supabase-community/storage-py/commit/ec3b46c43f88cd388ce22fc1dc62e6d75a39bb61)) + +* chore: bump version, bump CI ([`0679ae9`](https://github.com/supabase-community/storage-py/commit/0679ae9318a54b23e723fe0ccc989cf06020c5d9)) + +* chore: run black ([`2edbd6b`](https://github.com/supabase-community/storage-py/commit/2edbd6b74e1cd784b5ef4b39ffdce6e47e5e5e64)) + +* chore(deps-dev): bump sphinx from 5.3.0 to 6.1.3 + +Bumps [sphinx](https://github.com/sphinx-doc/sphinx) from 5.3.0 to 6.1.3. +- [Release notes](https://github.com/sphinx-doc/sphinx/releases) +- [Changelog](https://github.com/sphinx-doc/sphinx/blob/master/CHANGES) +- [Commits](https://github.com/sphinx-doc/sphinx/compare/v5.3.0...v6.1.3) + +--- +updated-dependencies: +- dependency-name: sphinx + dependency-type: direct:development + update-type: version-update:semver-major +... + +Signed-off-by: dependabot[bot] <support@github.com> ([`881fd9d`](https://github.com/supabase-community/storage-py/commit/881fd9d6dc4a576fea5a682e54804912d55781a4)) + +* chore(deps): bump cryptography from 39.0.0 to 39.0.1 + +Bumps [cryptography](https://github.com/pyca/cryptography) from 39.0.0 to 39.0.1. +- [Release notes](https://github.com/pyca/cryptography/releases) +- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst) +- [Commits](https://github.com/pyca/cryptography/compare/39.0.0...39.0.1) + +--- +updated-dependencies: +- dependency-name: cryptography + dependency-type: indirect +... + +Signed-off-by: dependabot[bot] <support@github.com> ([`1b3a638`](https://github.com/supabase-community/storage-py/commit/1b3a638857728a0e1c7854f615a3ab2c89b16c3d)) + +* chore(deps-dev): bump isort from 5.11.5 to 5.12.0 + +Bumps [isort](https://github.com/pycqa/isort) from 5.11.5 to 5.12.0. +- [Release notes](https://github.com/pycqa/isort/releases) +- [Changelog](https://github.com/PyCQA/isort/blob/main/CHANGELOG.md) +- [Commits](https://github.com/pycqa/isort/compare/5.11.5...5.12.0) + +--- +updated-dependencies: +- dependency-name: isort + dependency-type: direct:development + update-type: version-update:semver-minor +... + +Signed-off-by: dependabot[bot] <support@github.com> ([`96ad75f`](https://github.com/supabase-community/storage-py/commit/96ad75f0decbb48af846561b356a9fe4a634971e)) + +### Fix + +* fix: bump timeout ([`15f1547`](https://github.com/supabase-community/storage-py/commit/15f154789c329916b292d5504ad60b37f8b57ff2)) + +* fix: move timeout to constants file ([`873037a`](https://github.com/supabase-community/storage-py/commit/873037a51144685be76619eb151b917e8b0b8fdc)) + +* fix: add configurable timeout ([`281fbe7`](https://github.com/supabase-community/storage-py/commit/281fbe7e298aed67cd133c3a51265b356481b120)) + +### Unknown + +* Merge pull request #75 from supabase-community/0.5.6 + +chore: bump version to 0.5.2 ([`d584b04`](https://github.com/supabase-community/storage-py/commit/d584b044149be643a53b6d10c9347800bb8d8cf8)) + +* Merge pull request #64 from supabase-community/dependabot/pip/main/typing-extensions-4.5.0 + +chore(deps): bump typing-extensions from 4.4.0 to 4.5.0 ([`7cb23a2`](https://github.com/supabase-community/storage-py/commit/7cb23a25017ce8b2adbd775750f8a604437168c4)) + +* Merge pull request #65 from supabase-community/dependabot/pip/main/python-semantic-release-7.33.2 + +chore(deps-dev): bump python-semantic-release from 7.33.1 to 7.33.2 ([`547e23b`](https://github.com/supabase-community/storage-py/commit/547e23b590fcee173c5e2429a04cee3f5183f0a9)) + +* Merge pull request #69 from supabase-community/dependabot/pip/main/python-dotenv-1.0.0 + +chore(deps-dev): bump python-dotenv from 0.21.1 to 1.0.0 ([`49a7044`](https://github.com/supabase-community/storage-py/commit/49a7044764ce56502a0aaa5b3aaa2b6250a1fd84)) + +* Merge pull request #72 from ChartierLuc/bug-missing-types + +fix: added missing types ([`ed0dd37`](https://github.com/supabase-community/storage-py/commit/ed0dd37622ac3d516680d3a4b099c4e113da300b)) + +* Added missing types allowed_mime_types and file_size_limit ([`64e9e02`](https://github.com/supabase-community/storage-py/commit/64e9e02e8bea3e2b35ca37ed5d14c1197690accc)) + +* Merge pull request #56 from supabase-community/dependabot/pip/main/black-23.1.0 + +chore(deps-dev): bump black from 22.12.0 to 23.1.0 ([`7edeff7`](https://github.com/supabase-community/storage-py/commit/7edeff7135e9f3eb35d6016a3eb9ccbbf1351940)) + +* Merge pull request #74 from supabase-community/dependabot/pip/main/pre-commit-3.1.1 + +chore(deps-dev): bump pre-commit from 2.21.0 to 3.1.1 ([`0123f8f`](https://github.com/supabase-community/storage-py/commit/0123f8ff1708a8d13e9b436c1af376ab4c71be95)) + +* Merge pull request #68 from supabase-community/j0/bump_version_0_5_1 + +chore: bump version to 0_5_1 , bump CI ([`ae9fc30`](https://github.com/supabase-community/storage-py/commit/ae9fc30c4ed65ea27ad824560c3bd1e0cf20118a)) + +* Merge pull request #66 from supabase-community/j0/add_timeout + +fix: add configurable timeout ([`436121f`](https://github.com/supabase-community/storage-py/commit/436121ff23ff128a921f39739dae01b48b328b03)) + +* Merge pull request #61 from supabase-community/dependabot/pip/main/sphinx-6.1.3 + +chore(deps-dev): bump sphinx from 5.3.0 to 6.1.3 ([`afb57e7`](https://github.com/supabase-community/storage-py/commit/afb57e70b48fd3161e51ee1c903a4e416583cb60)) + +* Merge pull request #62 from supabase-community/dependabot/pip/cryptography-39.0.1 + +chore(deps): bump cryptography from 39.0.0 to 39.0.1 ([`728164b`](https://github.com/supabase-community/storage-py/commit/728164bfa24bef89341f57008f89995e063abea0)) + +* Merge pull request #60 from supabase-community/dependabot/pip/main/isort-5.12.0 + +chore(deps-dev): bump isort from 5.11.5 to 5.12.0 ([`eb5be13`](https://github.com/supabase-community/storage-py/commit/eb5be13152e2dcc5d402b2bff1ac5d2e0fb9cde5)) + +## v0.5.0 (2023-02-05) + +### Chore + +* chore: bump pre commit ([`25dd2cc`](https://github.com/supabase-community/storage-py/commit/25dd2cc99b5394fae189dd784fd3bc24223b01a0)) + +* chore: bump version and lockfile ([`f5a20db`](https://github.com/supabase-community/storage-py/commit/f5a20dbae42fb2e6d53816141fc77408d576990d)) + +* chore(deps-dev): bump python-semantic-release from 7.32.2 to 7.33.1 + +Bumps [python-semantic-release](https://github.com/relekang/python-semantic-release) from 7.32.2 to 7.33.1. +- [Release notes](https://github.com/relekang/python-semantic-release/releases) +- [Changelog](https://github.com/python-semantic-release/python-semantic-release/blob/master/CHANGELOG.md) +- [Commits](https://github.com/relekang/python-semantic-release/compare/v7.32.2...v7.33.1) + +--- +updated-dependencies: +- dependency-name: python-semantic-release + dependency-type: direct:development + update-type: version-update:semver-minor +... + +Signed-off-by: dependabot[bot] <support@github.com> ([`5bdb51d`](https://github.com/supabase-community/storage-py/commit/5bdb51dc86f8ec1529e3cb7bb8470e8a56f37e6c)) + +* chore(deps): bump wheel from 0.37.1 to 0.38.1 + +Bumps [wheel](https://github.com/pypa/wheel) from 0.37.1 to 0.38.1. +- [Release notes](https://github.com/pypa/wheel/releases) +- [Changelog](https://github.com/pypa/wheel/blob/main/docs/news.rst) +- [Commits](https://github.com/pypa/wheel/compare/0.37.1...0.38.1) + +--- +updated-dependencies: +- dependency-name: wheel + dependency-type: indirect +... + +Signed-off-by: dependabot[bot] <support@github.com> ([`ef2e864`](https://github.com/supabase-community/storage-py/commit/ef2e86407027ada25dc361aa7388366baebca38f)) + +### Fix + +* fix: bump python version ([`4d3a781`](https://github.com/supabase-community/storage-py/commit/4d3a7817ae3fb3ee4f93942406d8cfeb81103c88)) + +* fix: bump poetry version in ci ([`54110c4`](https://github.com/supabase-community/storage-py/commit/54110c4625c95e36461fb56e28287a97db7b02b7)) + +### Unknown + +* Merge pull request #58 from supabase-community/j0/bump_version + +chore: bump version and lockfile ([`3f44586`](https://github.com/supabase-community/storage-py/commit/3f4458680d8bac625edca18a249032b66533c06b)) + +* Merge pull request #57 from supabase-community/dependabot/pip/main/python-semantic-release-7.33.1 + +chore(deps-dev): bump python-semantic-release from 7.32.2 to 7.33.1 ([`06fb6f5`](https://github.com/supabase-community/storage-py/commit/06fb6f5686e90252828e28ea8d417f4c0c3e9599)) + +* Merge pull request #42 from supabase-community/dependabot/pip/wheel-0.38.1 + +chore(deps): bump wheel from 0.37.1 to 0.38.1 ([`f39c4fc`](https://github.com/supabase-community/storage-py/commit/f39c4fc66ab457ece68bc0a818d486e7ac775e10)) + +## v0.4.0 (2023-01-10) + +### Chore + +* chore: run black ([`3e985a9`](https://github.com/supabase-community/storage-py/commit/3e985a9e6b4305af0ec93c58c9af304c639b6df0)) + +* chore: set TransformOptions to None ([`ef32ae7`](https://github.com/supabase-community/storage-py/commit/ef32ae7e5137c54c8ea35ad3b8c2f2b965a8aecd)) + +* chore: port over infra from storage-js ([`88eb335`](https://github.com/supabase-community/storage-py/commit/88eb33532ff4ba04db740fc868d7ceed9bc0e18f)) + +* chore(deps-dev): bump pre-commit from 2.20.0 to 2.21.0 + +Bumps [pre-commit](https://github.com/pre-commit/pre-commit) from 2.20.0 to 2.21.0. +- [Release notes](https://github.com/pre-commit/pre-commit/releases) +- [Changelog](https://github.com/pre-commit/pre-commit/blob/main/CHANGELOG.md) +- [Commits](https://github.com/pre-commit/pre-commit/compare/v2.20.0...v2.21.0) + +--- +updated-dependencies: +- dependency-name: pre-commit + dependency-type: direct:development + update-type: version-update:semver-minor +... + +Signed-off-by: dependabot[bot] <support@github.com> ([`1708708`](https://github.com/supabase-community/storage-py/commit/1708708787c3344ed917ddd270ce7f105d9335f4)) + +* chore(deps): bump gitpython from 3.1.28 to 3.1.30 + +Bumps [gitpython](https://github.com/gitpython-developers/GitPython) from 3.1.28 to 3.1.30. +- [Release notes](https://github.com/gitpython-developers/GitPython/releases) +- [Changelog](https://github.com/gitpython-developers/GitPython/blob/main/CHANGES) +- [Commits](https://github.com/gitpython-developers/GitPython/compare/3.1.28...3.1.30) + +--- +updated-dependencies: +- dependency-name: gitpython + dependency-type: indirect +... + +Signed-off-by: dependabot[bot] <support@github.com> ([`84f48ed`](https://github.com/supabase-community/storage-py/commit/84f48ed47677868963be817c29753902975ef8fe)) + +### Feature + +* feat: add transform options to signed_url,download, and public_url ([`122b2a3`](https://github.com/supabase-community/storage-py/commit/122b2a3403dfa1fa33dd384b2a7c42e9f3094f9e)) + +* feat: add copy and transform option type ([`6be51ee`](https://github.com/supabase-community/storage-py/commit/6be51ee4a5bedabce6a25d05b9a38ae65f40efef)) + +### Fix + +* fix: add stray / ([`27b6bcd`](https://github.com/supabase-community/storage-py/commit/27b6bcd85866a152a1804679cb27f726a50d2bf3)) + +* fix: remove stray / ([`216cf36`](https://github.com/supabase-community/storage-py/commit/216cf3667479380fb893e16b4bd47d31f5a2b641)) + +* fix: update render_path for get_public_url ([`0272f1b`](https://github.com/supabase-community/storage-py/commit/0272f1b5dd787b8a51727c1c9de3116c15b124b6)) + +* fix: run black ([`42a9ed3`](https://github.com/supabase-community/storage-py/commit/42a9ed3f8f4e3d8e66f065f2ec64936a95b422b5)) + +* fix: handle stray / ([`dd72fd6`](https://github.com/supabase-community/storage-py/commit/dd72fd6758f975e8d1f1ba56765c21ac846cf62c)) + +* fix: handle stray / ([`604e804`](https://github.com/supabase-community/storage-py/commit/604e804e73583cd396829d41ecb8f3baf789f754)) + +* fix: remove query params ([`1feb825`](https://github.com/supabase-community/storage-py/commit/1feb82590a9f3ca025da41da82e8089f7835783f)) + +* fix: add query string param ([`72d299d`](https://github.com/supabase-community/storage-py/commit/72d299d4257265099e44c6b9e821fa3ca86d19ab)) + +* fix: strip out transformation changes ([`686b7fa`](https://github.com/supabase-community/storage-py/commit/686b7fa03007ee6dddc2bd96492a171bddf7de82)) + +* fix: remove stray $ ([`f0c8fdc`](https://github.com/supabase-community/storage-py/commit/f0c8fdcf69cd397e31c24091ae10550d65e0cb97)) + +* fix: switch from | to Union ([`f4005fd`](https://github.com/supabase-community/storage-py/commit/f4005fd672bc86bb694f2ddf50e202be7beb6370)) + +* fix: import Union, Optional from typing instead of typing-extensions ([`c5e5aba`](https://github.com/supabase-community/storage-py/commit/c5e5abaa8f7830cbfcd1caeafcd5d3c2140f2f0d)) + +* fix: omit infra changes ([`9b967ce`](https://github.com/supabase-community/storage-py/commit/9b967ce41d3598a68b08cbad45435a26fc0d5f0b)) + +* fix: add transform options on public url and download ([`7352f61`](https://github.com/supabase-community/storage-py/commit/7352f6128a1bd52e863dea0cf8db6f53519e6c78)) + +### Refactor + +* refactor: remove create_signed_urls ([`b43434f`](https://github.com/supabase-community/storage-py/commit/b43434f6e947ce8a5251c042c19a90f8b6d86a6b)) + +### Unknown + +* Merge pull request #49 from supabase-community/j0/add_transformation_bindings + +feat: add transformation bindings ([`a501d41`](https://github.com/supabase-community/storage-py/commit/a501d4109d570297d4f6c18cce8ef96df6228b1b)) + +* add 3.11 ([`51de064`](https://github.com/supabase-community/storage-py/commit/51de0644cf3f2b72d88deb04951db4a8e7d0b80d)) + +* Merge pull request #41 from supabase-community/dependabot/pip/main/pre-commit-2.21.0 + +chore(deps-dev): bump pre-commit from 2.20.0 to 2.21.0 ([`68bcc7d`](https://github.com/supabase-community/storage-py/commit/68bcc7d073d7a27f45719a6fc7eecccbcf833163)) + +* Merge pull request #47 from supabase-community/dependabot/pip/gitpython-3.1.30 + +chore(deps): bump gitpython from 3.1.28 to 3.1.30 ([`8e0452a`](https://github.com/supabase-community/storage-py/commit/8e0452a1b39269514cf5e58dff545a29c783e890)) + +## v0.3.6 (2023-01-05) + +### Chore + +* chore(deps): bump httpx from 0.23.0 to 0.23.3 + +Bumps [httpx](https://github.com/encode/httpx) from 0.23.0 to 0.23.3. +- [Release notes](https://github.com/encode/httpx/releases) +- [Changelog](https://github.com/encode/httpx/blob/master/CHANGELOG.md) +- [Commits](https://github.com/encode/httpx/compare/0.23.0...0.23.3) + +--- +updated-dependencies: +- dependency-name: httpx + dependency-type: direct:production + update-type: version-update:semver-patch +... + +Signed-off-by: dependabot[bot] <support@github.com> ([`211dd3c`](https://github.com/supabase-community/storage-py/commit/211dd3cd7f22ec8172b31eb8c2557aaed7054a00)) + +* chore(deps-dev): bump isort from 5.11.1 to 5.11.4 + +Bumps [isort](https://github.com/pycqa/isort) from 5.11.1 to 5.11.4. +- [Release notes](https://github.com/pycqa/isort/releases) +- [Changelog](https://github.com/PyCQA/isort/blob/main/CHANGELOG.md) +- [Commits](https://github.com/pycqa/isort/compare/5.11.1...5.11.4) + +--- +updated-dependencies: +- dependency-name: isort + dependency-type: direct:development + update-type: version-update:semver-patch +... + +Signed-off-by: dependabot[bot] <support@github.com> ([`996d377`](https://github.com/supabase-community/storage-py/commit/996d37752cfc33b2c9d93666a7f6cc3ebc721c04)) + +* chore(deps-dev): bump pytest-asyncio from 0.20.1 to 0.20.3 + +Bumps [pytest-asyncio](https://github.com/pytest-dev/pytest-asyncio) from 0.20.1 to 0.20.3. +- [Release notes](https://github.com/pytest-dev/pytest-asyncio/releases) +- [Changelog](https://github.com/pytest-dev/pytest-asyncio/blob/master/CHANGELOG.rst) +- [Commits](https://github.com/pytest-dev/pytest-asyncio/compare/v0.20.1...v0.20.3) + +--- +updated-dependencies: +- dependency-name: pytest-asyncio + dependency-type: direct:development + update-type: version-update:semver-patch +... + +Signed-off-by: dependabot[bot] <support@github.com> ([`3016a2b`](https://github.com/supabase-community/storage-py/commit/3016a2bd4d6a82c2af12a9a800acad0131ea21bf)) + +* chore(deps-dev): bump isort from 5.10.1 to 5.11.1 + +Bumps [isort](https://github.com/pycqa/isort) from 5.10.1 to 5.11.1. +- [Release notes](https://github.com/pycqa/isort/releases) +- [Changelog](https://github.com/PyCQA/isort/blob/main/CHANGELOG.md) +- [Commits](https://github.com/pycqa/isort/compare/5.10.1...5.11.1) + +--- +updated-dependencies: +- dependency-name: isort + dependency-type: direct:development + update-type: version-update:semver-minor +... + +Signed-off-by: dependabot[bot] <support@github.com> ([`87f87f5`](https://github.com/supabase-community/storage-py/commit/87f87f5b15228b8fdc3859ec6d5ef809d5512336)) + +* chore(deps): bump cryptography from 38.0.1 to 38.0.3 + +Bumps [cryptography](https://github.com/pyca/cryptography) from 38.0.1 to 38.0.3. +- [Release notes](https://github.com/pyca/cryptography/releases) +- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst) +- [Commits](https://github.com/pyca/cryptography/compare/38.0.1...38.0.3) + +--- +updated-dependencies: +- dependency-name: cryptography + dependency-type: indirect +... + +Signed-off-by: dependabot[bot] <support@github.com> ([`40ba3d6`](https://github.com/supabase-community/storage-py/commit/40ba3d6b622acb5ea8a593f7455acfbbd71efa69)) + +* chore(deps-dev): bump black from 22.10.0 to 22.12.0 + +Bumps [black](https://github.com/psf/black) from 22.10.0 to 22.12.0. +- [Release notes](https://github.com/psf/black/releases) +- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md) +- [Commits](https://github.com/psf/black/compare/22.10.0...22.12.0) + +--- +updated-dependencies: +- dependency-name: black + dependency-type: direct:development + update-type: version-update:semver-minor +... + +Signed-off-by: dependabot[bot] <support@github.com> ([`5c64886`](https://github.com/supabase-community/storage-py/commit/5c64886d092a83db2bf76ef7a4fb4b9b449622df)) + +* chore(deps): bump certifi from 2022.9.24 to 2022.12.7 + +Bumps [certifi](https://github.com/certifi/python-certifi) from 2022.9.24 to 2022.12.7. +- [Release notes](https://github.com/certifi/python-certifi/releases) +- [Commits](https://github.com/certifi/python-certifi/compare/2022.09.24...2022.12.07) + +--- +updated-dependencies: +- dependency-name: certifi + dependency-type: indirect +... + +Signed-off-by: dependabot[bot] <support@github.com> ([`822d714`](https://github.com/supabase-community/storage-py/commit/822d71431c46f2b36a9704d43d616921a070eb81)) + +* chore(release): bump version to v0.3.5 ([`323e65e`](https://github.com/supabase-community/storage-py/commit/323e65e98a6101685b689f9f21c87b29a29a1f6c)) + +* chore(deps-dev): bump python-semantic-release from 7.32.1 to 7.32.2 + +Bumps [python-semantic-release](https://github.com/relekang/python-semantic-release) from 7.32.1 to 7.32.2. +- [Release notes](https://github.com/relekang/python-semantic-release/releases) +- [Changelog](https://github.com/relekang/python-semantic-release/blob/master/CHANGELOG.md) +- [Commits](https://github.com/relekang/python-semantic-release/compare/v7.32.1...v7.32.2) + +--- +updated-dependencies: +- dependency-name: python-semantic-release + dependency-type: direct:development + update-type: version-update:semver-patch +... + +Signed-off-by: dependabot[bot] <support@github.com> ([`68df5c2`](https://github.com/supabase-community/storage-py/commit/68df5c2f32264a4dd9d71256b0f510a2defa1379)) + +* chore(deps-dev): bump pytest-asyncio from 0.19.0 to 0.20.1 (#26) + +Bumps [pytest-asyncio](https://github.com/pytest-dev/pytest-asyncio) from 0.19.0 to 0.20.1. +- [Release notes](https://github.com/pytest-dev/pytest-asyncio/releases) +- [Changelog](https://github.com/pytest-dev/pytest-asyncio/blob/master/CHANGELOG.rst) +- [Commits](https://github.com/pytest-dev/pytest-asyncio/compare/v0.19.0...v0.20.1) + +--- +updated-dependencies: +- dependency-name: pytest-asyncio + dependency-type: direct:development + update-type: version-update:semver-minor +... + +Signed-off-by: dependabot[bot] <support@github.com> + +Signed-off-by: dependabot[bot] <support@github.com> +Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> ([`999e8c9`](https://github.com/supabase-community/storage-py/commit/999e8c993822177d017ab3f7a69aea0209fefea2)) + +* chore(deps-dev): bump pytest from 6.2.5 to 7.2.0 (#28) + +Bumps [pytest](https://github.com/pytest-dev/pytest) from 6.2.5 to 7.2.0. +- [Release notes](https://github.com/pytest-dev/pytest/releases) +- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst) +- [Commits](https://github.com/pytest-dev/pytest/compare/6.2.5...7.2.0) + +--- +updated-dependencies: +- dependency-name: pytest + dependency-type: direct:development + update-type: version-update:semver-major +... + +Signed-off-by: dependabot[bot] <support@github.com> + +Signed-off-by: dependabot[bot] <support@github.com> +Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> ([`ed35024`](https://github.com/supabase-community/storage-py/commit/ed35024fea5f28fafd6e9b66e73b689e5a9f12f5)) + +* chore(deps-dev): bump pytest-cov from 3.0.0 to 4.0.0 + +Bumps [pytest-cov](https://github.com/pytest-dev/pytest-cov) from 3.0.0 to 4.0.0. +- [Release notes](https://github.com/pytest-dev/pytest-cov/releases) +- [Changelog](https://github.com/pytest-dev/pytest-cov/blob/master/CHANGELOG.rst) +- [Commits](https://github.com/pytest-dev/pytest-cov/compare/v3.0.0...v4.0.0) + +--- +updated-dependencies: +- dependency-name: pytest-cov + dependency-type: direct:development + update-type: version-update:semver-major +... + +Signed-off-by: dependabot[bot] <support@github.com> ([`d22118b`](https://github.com/supabase-community/storage-py/commit/d22118b7639d9bfef37a8de6bb6e80bcbcb33b85)) + +* chore(deps-dev): bump sphinx from 5.2.3 to 5.3.0 (#25) + +Bumps [sphinx](https://github.com/sphinx-doc/sphinx) from 5.2.3 to 5.3.0. +- [Release notes](https://github.com/sphinx-doc/sphinx/releases) +- [Changelog](https://github.com/sphinx-doc/sphinx/blob/master/CHANGES) +- [Commits](https://github.com/sphinx-doc/sphinx/compare/v5.2.3...v5.3.0) + +--- +updated-dependencies: +- dependency-name: sphinx + dependency-type: direct:development + update-type: version-update:semver-minor +... + +Signed-off-by: dependabot[bot] <support@github.com> + +Signed-off-by: dependabot[bot] <support@github.com> +Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> ([`9f7bc01`](https://github.com/supabase-community/storage-py/commit/9f7bc01b135fbdcb1f7767f426011c0630408712)) + +### Fix + +* fix: remove trailing "/" in `get_public_url` + +When using the `get_public_url` methods, you get the following +responses: + +``` +https://SUPABASE_ID.supabase.co/storage/v1//object/public/BUCKET/FILE +``` + +Notice the double slash between +the `v1` and the `object` substrings in the path. + +Even though the URL works---as +captured by the tests--it is a non +coherent way of rendering the +URLs. + +This commit sets it so that all the +sub-paths inside the public URL +have a single slash. + +Authored-By: Diego Rodriguez ([`8bf407c`](https://github.com/supabase-community/storage-py/commit/8bf407c5fc2bca401a673d42d0f9a82b7b9e80bb)) + +* fix: datetime and upload file type (#12) + +* [fix] datetime and upload file type + +fix datetime error and add more acceptable file type + +* [Fix] Add python-dateutil as dependency + +* Fix lock file + +* chore: reformat with black + +* chore: calm isort down + +Co-authored-by: Anand <40204976+anand2312@users.noreply.github.com> ([`a926a06`](https://github.com/supabase-community/storage-py/commit/a926a068234e68afbf8039fc7f71565397dfea86)) + +### Unknown + +* Merge pull request #46 from supabase-community/dependabot/pip/main/httpx-0.23.3 + +chore(deps): bump httpx from 0.23.0 to 0.23.3 ([`a9f2def`](https://github.com/supabase-community/storage-py/commit/a9f2def2c25daa6e8f17eaa76c3194943293682b)) + +* Merge pull request #40 from supabase-community/dependabot/pip/main/isort-5.11.4 + +chore(deps-dev): bump isort from 5.11.1 to 5.11.4 ([`fd3c480`](https://github.com/supabase-community/storage-py/commit/fd3c4805928f30591058c028bf67a095ea2bcced)) + +* Merge pull request #32 from supabase-community/dependabot/pip/main/pytest-asyncio-0.20.3 + +chore(deps-dev): bump pytest-asyncio from 0.20.1 to 0.20.3 ([`57205b1`](https://github.com/supabase-community/storage-py/commit/57205b106a2254cef73e95c04f1b7fd3bcbb4c00)) + +* Merge pull request #37 from supabase-community/dependabot/pip/main/isort-5.11.1 + +chore(deps-dev): bump isort from 5.10.1 to 5.11.1 ([`514b2b4`](https://github.com/supabase-community/storage-py/commit/514b2b46b79d0dd018d5ca92956010bb2a3344a1)) + +* Create codeql.yml ([`993d162`](https://github.com/supabase-community/storage-py/commit/993d162d6770d195dcece59db7cde4a8ae54b359)) + +* Merge pull request #34 from supabase-community/dependabot/pip/cryptography-38.0.3 + +chore(deps): bump cryptography from 38.0.1 to 38.0.3 ([`7e4060a`](https://github.com/supabase-community/storage-py/commit/7e4060acf2cf436d020af2e5c46da1e9c428b9e2)) + +* Merge pull request #35 from supabase-community/dependabot/pip/main/black-22.12.0 + +chore(deps-dev): bump black from 22.10.0 to 22.12.0 ([`0020dc4`](https://github.com/supabase-community/storage-py/commit/0020dc49c15b1658ef72ea207bcabddfe08214af)) + +* Merge pull request #33 from supabase-community/dependabot/pip/certifi-2022.12.7 + +chore(deps): bump certifi from 2022.9.24 to 2022.12.7 ([`4682db1`](https://github.com/supabase-community/storage-py/commit/4682db1f9aacd90c13c07bf3685f30f368522739)) + +* Merge pull request #13 from asciidiego/diegonyc/fix/public_url_parsing + +fix: remove leading "/" in `get_public_url` methods ([`ccd2316`](https://github.com/supabase-community/storage-py/commit/ccd2316f48a17d78d54577dd6add690137ec141a)) + +* Merge pull request #27 from supabase-community/dependabot/pip/main/python-semantic-release-7.32.2 + +chore(deps-dev): bump python-semantic-release from 7.32.1 to 7.32.2 ([`1f2a4b5`](https://github.com/supabase-community/storage-py/commit/1f2a4b589746130af1166de66d5281c3e3745a53)) + +* Merge pull request #23 from supabase-community/dependabot/pip/main/pytest-cov-4.0.0 + +chore(deps-dev): bump pytest-cov from 3.0.0 to 4.0.0 ([`67ad10c`](https://github.com/supabase-community/storage-py/commit/67ad10c92ef234db5551a2f3699e4be8f36fa15c)) + +## v0.3.5 (2022-10-11) + +### Chore + +* chore: bump version ([`15cbda8`](https://github.com/supabase-community/storage-py/commit/15cbda81b32d711b766cfc5e265c07dcb2835e9e)) + +* chore(deps-dev): bump sphinx from 4.5.0 to 5.2.3 + +Bumps [sphinx](https://github.com/sphinx-doc/sphinx) from 4.5.0 to 5.2.3. +- [Release notes](https://github.com/sphinx-doc/sphinx/releases) +- [Changelog](https://github.com/sphinx-doc/sphinx/blob/5.x/CHANGES) +- [Commits](https://github.com/sphinx-doc/sphinx/compare/v4.5.0...v5.2.3) + +--- +updated-dependencies: +- dependency-name: sphinx + dependency-type: direct:development + update-type: version-update:semver-major +... + +Signed-off-by: dependabot[bot] <support@github.com> ([`7fe29fe`](https://github.com/supabase-community/storage-py/commit/7fe29fec1ec9467139b247c3040c2c760955ecba)) + +* chore(deps-dev): bump python-dotenv from 0.20.0 to 0.21.0 + +Bumps [python-dotenv](https://github.com/theskumar/python-dotenv) from 0.20.0 to 0.21.0. +- [Release notes](https://github.com/theskumar/python-dotenv/releases) +- [Changelog](https://github.com/theskumar/python-dotenv/blob/main/CHANGELOG.md) +- [Commits](https://github.com/theskumar/python-dotenv/compare/v0.20.0...v0.21.0) + +--- +updated-dependencies: +- dependency-name: python-dotenv + dependency-type: direct:development + update-type: version-update:semver-minor +... + +Signed-off-by: dependabot[bot] <support@github.com> ([`6f72dc2`](https://github.com/supabase-community/storage-py/commit/6f72dc267e74c1724ec06014616884cd7745f87b)) + +* chore(deps): bump typing-extensions from 4.2.0 to 4.4.0 + +Bumps [typing-extensions](https://github.com/python/typing_extensions) from 4.2.0 to 4.4.0. +- [Release notes](https://github.com/python/typing_extensions/releases) +- [Changelog](https://github.com/python/typing_extensions/blob/main/CHANGELOG.md) +- [Commits](https://github.com/python/typing_extensions/compare/4.2.0...4.4.0) + +--- +updated-dependencies: +- dependency-name: typing-extensions + dependency-type: direct:production + update-type: version-update:semver-minor +... + +Signed-off-by: dependabot[bot] <support@github.com> ([`0b82bb5`](https://github.com/supabase-community/storage-py/commit/0b82bb534e4461e163e9f78b8390d51a889eedf1)) + +* chore: update lock ([`f34e23e`](https://github.com/supabase-community/storage-py/commit/f34e23e750dd37267541d782daae1483187930e9)) + +* chore(deps-dev): bump pytest-asyncio from 0.18.3 to 0.19.0 + +Bumps [pytest-asyncio](https://github.com/pytest-dev/pytest-asyncio) from 0.18.3 to 0.19.0. +- [Release notes](https://github.com/pytest-dev/pytest-asyncio/releases) +- [Changelog](https://github.com/pytest-dev/pytest-asyncio/blob/master/CHANGELOG.rst) +- [Commits](https://github.com/pytest-dev/pytest-asyncio/compare/v0.18.3...v0.19.0) + +--- +updated-dependencies: +- dependency-name: pytest-asyncio + dependency-type: direct:development + update-type: version-update:semver-minor +... + +Signed-off-by: dependabot[bot] <support@github.com> ([`8de4e10`](https://github.com/supabase-community/storage-py/commit/8de4e10f3438503c9a263122981ccffbf34b9e9a)) + +### Unknown + +* Merge pull request #22 from supabase-community/j0_bump_version + +chore: bump storage version ([`8156aae`](https://github.com/supabase-community/storage-py/commit/8156aaec8d75c305c519607bf8f88d65dad3a0af)) + +* Merge pull request #15 from supabase-community/dependabot/pip/main/sphinx-5.2.3 + +chore(deps-dev): bump sphinx from 4.5.0 to 5.2.3 ([`727c123`](https://github.com/supabase-community/storage-py/commit/727c12306a24c5410570e8b98b905fb75886e8ae)) + +* Merge pull request #17 from supabase-community/dependabot/pip/main/python-dotenv-0.21.0 + +chore(deps-dev): bump python-dotenv from 0.20.0 to 0.21.0 ([`1e2558a`](https://github.com/supabase-community/storage-py/commit/1e2558a85de0b7e307ace3690344833fb71dc399)) + +* Merge pull request #18 from supabase-community/dependabot/pip/main/typing-extensions-4.4.0 + +chore(deps): bump typing-extensions from 4.2.0 to 4.4.0 ([`41eb45d`](https://github.com/supabase-community/storage-py/commit/41eb45d44322bd7d079629de8d8d3a04c4f1b43e)) + +* Merge pull request #21 from supabase-community/J0-bump-httpx + +chore: bump httpx to 0.23 ([`517bd66`](https://github.com/supabase-community/storage-py/commit/517bd66cab5eb267e4140d77b36fecd89c4e106a)) + +* Update pyproject.toml ([`8bee432`](https://github.com/supabase-community/storage-py/commit/8bee43294530d2f5f54b1b9a32d112bc016cf478)) + +* Merge pull request #16 from supabase-community/dependabot/pip/main/pytest-asyncio-0.19.0 + +chore(deps-dev): bump pytest-asyncio from 0.18.3 to 0.19.0 ([`31d886c`](https://github.com/supabase-community/storage-py/commit/31d886cf50ba745deab7fc2352050bf6ab81d9e0)) + +* Update dependabot.yml ([`f6ef85e`](https://github.com/supabase-community/storage-py/commit/f6ef85e217d8f5d141a3fbc6879532e327e69a51)) + +* Justinbarak patch 1 (#14) + +* Removed double "/" in get_public_url + +* Removed double "/" in get_public_url ([`20de85e`](https://github.com/supabase-community/storage-py/commit/20de85e677e29cd17bb210a402be947f0ad98509)) + +## v0.3.4 (2022-06-07) + +### Fix + +* fix: signed_url + +fix: signed_url ([`c8cdf44`](https://github.com/supabase-community/storage-py/commit/c8cdf444090e7d9c6cd68ac4f31afb52921c3ea5)) + +* fix: try no timeout as fix instead of sleep ([`68026be`](https://github.com/supabase-community/storage-py/commit/68026be058a5e5a0684d7bc174da674dfc6a137c)) + +* fix: signed_url ([`bd2e09c`](https://github.com/supabase-community/storage-py/commit/bd2e09c28164b364ca919fd888019e837af3890f)) + +## v0.3.3 (2022-06-06) + +### Chore + +* chore: build sync ([`1217cba`](https://github.com/supabase-community/storage-py/commit/1217cbac50186fefde73eb83337af9dfbf202d26)) + +### Fix + +* fix: upload method + +fix: upload fixes ([`844561f`](https://github.com/supabase-community/storage-py/commit/844561f63d58ad869a4303941e7ef8194ae89154)) + +* fix: use ** to merge dicts ([`2965ae7`](https://github.com/supabase-community/storage-py/commit/2965ae79857fd3b264384b0fbe8c7172744a9f12)) + +* fix: poetry lock ([`4d2a73f`](https://github.com/supabase-community/storage-py/commit/4d2a73f7f8170ddeac5ef154fd3c14c7b7bfec71)) + +### Style + +* style: apply pre-commit ([`3b9a3b3`](https://github.com/supabase-community/storage-py/commit/3b9a3b38d553bd505bf077f07dcca18f5cfd72b4)) + +* style: use lowercase headers ([`66f088e`](https://github.com/supabase-community/storage-py/commit/66f088e8a28122b7085187c3e7c0c45e1ef68b30)) + +### Test + +* test: sleep before download ([`1d3959c`](https://github.com/supabase-community/storage-py/commit/1d3959c554f9547b941e1db4ec7373715f8ce38c)) + +* test: fix tests to check file content ([`7995837`](https://github.com/supabase-community/storage-py/commit/7995837647a3dded939698405aa79d2dc181b299)) + +## v0.3.2 (2022-05-16) + +### Ci + +* ci: add deploy docs action ([`a4cbacf`](https://github.com/supabase-community/storage-py/commit/a4cbacf17260bb434bc8d42cc7e142e9621e3cc7)) + +### Fix + +* fix: don't create virtualenv in CI (#7) ([`2a85860`](https://github.com/supabase-community/storage-py/commit/2a8586082ff667c7b525bccf01df2c0e890f2b66)) + +### Unknown + +* Docs (#6) + +* docs: setup + +* docs: write basic documentation + +* chore: fix lock file + +* chore: calm pre-commit down ([`0974414`](https://github.com/supabase-community/storage-py/commit/0974414707f3e97fc8e44197d1f59a5699a0b582)) + +## v0.3.1 (2022-05-01) + +### Fix + +* fix: parity with js ([`19f1816`](https://github.com/supabase-community/storage-py/commit/19f1816d23671d576ddf23feab401d51aaf7b3e4)) + +## v0.3.0 (2022-04-30) + +### Chore + +* chore: force release of 0.3.0 ([`5793136`](https://github.com/supabase-community/storage-py/commit/57931368c1800275b84326a7b0b3277c693c114d)) + +* chore(deps): add typing_extensions ([`f541599`](https://github.com/supabase-community/storage-py/commit/f5415994ca8076a70942a8ed13c600b002e175f7)) + +* chore: setup ci versioning and publishing ([`a4c1d0b`](https://github.com/supabase-community/storage-py/commit/a4c1d0bced258b3f65e4c9880b196e8d81e8d38d)) + +* chore: update README ([`8e1f2e3`](https://github.com/supabase-community/storage-py/commit/8e1f2e395b45121e544341e52dc0202c0e78aef4)) + +* chore: downgrade poetry back to 1.1.11 ([`1daf996`](https://github.com/supabase-community/storage-py/commit/1daf996dd01e39d473d6cc07bebe0d32607da8ac)) + +* chore(debug end): add tests_only to tests in makefile ([`b9a7dbd`](https://github.com/supabase-community/storage-py/commit/b9a7dbdbd73b51e11f33a3eb9aaae0f69a36420b)) + +* chore(debug): bump poetry version in ci ([`0d8cf48`](https://github.com/supabase-community/storage-py/commit/0d8cf4877f199bdbe9ef03b4d992659d664264b2)) + +* chore(debug): remove tests_only from tests ([`c8cbde7`](https://github.com/supabase-community/storage-py/commit/c8cbde711a490c266c91d482435a3e5a038e6f88)) + +* chore(debug): remove install from tests ([`320739d`](https://github.com/supabase-community/storage-py/commit/320739dbfb17411c90245dc1b37308b3c064b713)) + +* chore: build sync ([`ae05a5a`](https://github.com/supabase-community/storage-py/commit/ae05a5a8c4fedf63e7668ac3bd0b0cd40e1a185c)) + +* chore(deps): fix lock ([`2bb8ddc`](https://github.com/supabase-community/storage-py/commit/2bb8ddc96f3106c011958107b0e53f0af31ca67e)) + +* chore: rm type annotation ([`88457fa`](https://github.com/supabase-community/storage-py/commit/88457fa85246e37c7defe01b6397a14970fbf964)) + +* chore: add pytest-asyncio dependency ([`6a90169`](https://github.com/supabase-community/storage-py/commit/6a90169fe0f927d2c0b073809dbd6ad4b9b59b67)) + +### Ci + +* ci: add preview to poetry install in semantic-release ([`0fad863`](https://github.com/supabase-community/storage-py/commit/0fad863434e7b6e5a51bb3cd3836acad4504f727)) + +* ci: uncomment publish to pypi ([`aa6adaf`](https://github.com/supabase-community/storage-py/commit/aa6adaf4858087b041933619ccd93593c9251d28)) + +* ci(fix): bump poetry version again ([`1b9a455`](https://github.com/supabase-community/storage-py/commit/1b9a455ab6b69a910a74de04280e879afea9e177)) + +### Feature + +* feat: force version bump ([`62556c0`](https://github.com/supabase-community/storage-py/commit/62556c00a064c691df90be6f8c8a46cc1b772ba4)) + +* feat: ignore unused imports in certain files ([`efebefe`](https://github.com/supabase-community/storage-py/commit/efebefed65a3adfa23ef4142600215bd1e6cff01)) + +* feat: add context manager ([`ec61c29`](https://github.com/supabase-community/storage-py/commit/ec61c29f72a1dae1148dbd15ab5cdad61eac835c)) + +* feat: add build_sync to makefile ([`b0a8665`](https://github.com/supabase-community/storage-py/commit/b0a86658678ce98a977cf67c07f07847003dcccf)) + +* feat: add statusCode to exception ([`6923975`](https://github.com/supabase-community/storage-py/commit/692397503f4a475168b92a8d5d8cda7719d2bf65)) + +* feat: add key to clients ([`838af7c`](https://github.com/supabase-community/storage-py/commit/838af7c0aded3c2e20df2ddd8e665da33d65106d)) + +### Fix + +* fix(3.7 comp): import TypedDict from typing_extensions ([`dca5d6f`](https://github.com/supabase-community/storage-py/commit/dca5d6f716eb9624c4242a04e41e7b43f4e60ec6)) + +* fix: add AsyncClient ([`9522298`](https://github.com/supabase-community/storage-py/commit/9522298b9cb63531802984844287e7da3c996a93)) + +* fix: add storage to url ([`a33f9a3`](https://github.com/supabase-community/storage-py/commit/a33f9a398e43ef49d499b0685ff2557ca386c4fc)) + +* fix: async fixes ([`061cb15`](https://github.com/supabase-community/storage-py/commit/061cb15c4800117b71c4f3c50e3e1b9bd5989e7c)) + +* fix: typing.literal compatible w py3.7 ([`fcc21f1`](https://github.com/supabase-community/storage-py/commit/fcc21f16181a2127255edcf628e9f467a09874ca)) + +### Refactor + +* refactor: no need to remerge client headers ([`cef322e`](https://github.com/supabase-community/storage-py/commit/cef322e8fa3e17ec18399dbcae65daf2262acc02)) + +* refactor: use session to get url and headers ([`b3f049f`](https://github.com/supabase-community/storage-py/commit/b3f049f0332f678e4af4ae95e2e855cefe90c1e8)) + +### Style + +* style: add keyword arguments ([`8fa1279`](https://github.com/supabase-community/storage-py/commit/8fa12796929ee791a7978358ec2ff78dccb9b68d)) + +* style: sort imports ([`6d709b4`](https://github.com/supabase-community/storage-py/commit/6d709b4c8c8d3a920b60874288ed1b96f9610a2c)) + +* style: apply ([`688cfc7`](https://github.com/supabase-community/storage-py/commit/688cfc79b870df84ea2c85a1dae50f364799c258)) + +* style: fix ([`ab7275f`](https://github.com/supabase-community/storage-py/commit/ab7275ffd91564333fed58b5cc6ceb5b78da4d84)) + +### Test + +* test: adapt tests to context manager ([`fd9bc86`](https://github.com/supabase-community/storage-py/commit/fd9bc86fe9f04cbe3d4c76e5b27cd8cbd1b1b750)) + +* test: add tests ([`488e538`](https://github.com/supabase-community/storage-py/commit/488e538fc637a1f6c433f31b1cf076204540cd51)) + +### Unknown + +* Merge pull request #5 from supabase-community/fix-py3.7 + +Setup CD versioning and publishing with semantic release ([`9e840bc`](https://github.com/supabase-community/storage-py/commit/9e840bcdaabfc6161c9a15d5ac3bce3ba361012c)) + +* Merge pull request #4 from supabase-community/fix-py3.7 + +feat: python 3.7 compatibility and tests ([`5a8a1b4`](https://github.com/supabase-community/storage-py/commit/5a8a1b4be5e8dd6d49b6dc3ad642d8e7fe05fa3d)) + +* Update storage3/_async/file_api.py + +Co-authored-by: Anand <40204976+anand2312@users.noreply.github.com> ([`db49eb9`](https://github.com/supabase-community/storage-py/commit/db49eb9bfb5be369a88ab218583c4e5bb67a4130)) + +* Update storage3/_async/file_api.py + +Co-authored-by: Anand <40204976+anand2312@users.noreply.github.com> ([`3550527`](https://github.com/supabase-community/storage-py/commit/3550527710cd335c7eb392371eb9972dffcd0733)) + +* Update storage3/_async/file_api.py + +Co-authored-by: Anand <40204976+anand2312@users.noreply.github.com> ([`034a218`](https://github.com/supabase-community/storage-py/commit/034a218aac85a419d2c7849dc7e1a5d91fd5eb89)) + +* Update storage3/_async/file_api.py + +Co-authored-by: Anand <40204976+anand2312@users.noreply.github.com> ([`637182d`](https://github.com/supabase-community/storage-py/commit/637182d7bf92178777408af72269a82cd1d93983)) + +* Update storage3/_async/file_api.py + +Co-authored-by: Anand <40204976+anand2312@users.noreply.github.com> ([`2d34986`](https://github.com/supabase-community/storage-py/commit/2d34986b605a4907ff1c78ed24b4e76b8d95a991)) + +* Update storage3/_async/file_api.py + +Co-authored-by: Anand <40204976+anand2312@users.noreply.github.com> ([`07f67dd`](https://github.com/supabase-community/storage-py/commit/07f67ddbb90d9073aa9c6f6e7beff4d0fcf3b855)) + +* Update storage3/_async/file_api.py + +Co-authored-by: Anand <40204976+anand2312@users.noreply.github.com> ([`13445f7`](https://github.com/supabase-community/storage-py/commit/13445f78ae3edf317dd4f84e6937e4c332ec4391)) + +* Update storage3/_async/bucket.py + +Co-authored-by: Anand <40204976+anand2312@users.noreply.github.com> ([`d1cef58`](https://github.com/supabase-community/storage-py/commit/d1cef58304e6aa9981c2e36e54f85398450fc928)) + +* Update storage3/_async/bucket.py + +Co-authored-by: Anand <40204976+anand2312@users.noreply.github.com> ([`26fa8b2`](https://github.com/supabase-community/storage-py/commit/26fa8b2988e2a57ba3183b9772775b8e834d959a)) + +* Update storage3/_async/bucket.py + +Co-authored-by: Anand <40204976+anand2312@users.noreply.github.com> ([`20b47bb`](https://github.com/supabase-community/storage-py/commit/20b47bbce4068da381684654f8cecaef2ffe200b)) + +* Update storage3/_async/bucket.py + +Co-authored-by: Anand <40204976+anand2312@users.noreply.github.com> ([`91a8ff7`](https://github.com/supabase-community/storage-py/commit/91a8ff7f2882746e90d85c6d292f764ad5c60fcf)) + +* Update storage3/_async/bucket.py + +Co-authored-by: Anand <40204976+anand2312@users.noreply.github.com> ([`734e973`](https://github.com/supabase-community/storage-py/commit/734e9737e1337d5feecffb4789342fb44a0dcfce)) + +* refactor:export env variables to file ([`a9b8faf`](https://github.com/supabase-community/storage-py/commit/a9b8faf028aad56ea5caf598d983654cb8d713e0)) + +## v0.2.0 (2022-04-11) + +### Chore + +* chore: add usage instructions ([`1ab2974`](https://github.com/supabase-community/storage-py/commit/1ab29746e300e4977e50721168d33f3b42d4772a)) + +* chore: update versions and publish to PyPI ([`7c754cf`](https://github.com/supabase-community/storage-py/commit/7c754cfe4397ff75cd693ab38d4b37fb2e1dc3f5)) + +* chore: rename storage to storage3 ([`c62151c`](https://github.com/supabase-community/storage-py/commit/c62151c235e1856ea25faeb68515565b7034eb2c)) + +### Unknown + +* Sync support (#1) + +* deps: update black, add unasync + +* feat: make BaseBucket + +* feat: rework bucket, file APIs + +* fix: avoid circular import on StorageException + +* deps: add dotenv + +* feat: pass User-Agent header with requests + +* fix: correct type-hint + +* fix: formatting + +* chore: update example in README ([`75c9c43`](https://github.com/supabase-community/storage-py/commit/75c9c43ea373cb58970255b8e7438c2ec67e7f25)) + +* Merge branch 'main' of github.com:J0/storage-py into main ([`d41b573`](https://github.com/supabase-community/storage-py/commit/d41b57391f04453986f06d564c5c207e4c75b7cc)) + +## v0.1.0 (2021-12-24) + +### Chore + +* chore: update maintainers in license and pyproject ([`e77112c`](https://github.com/supabase-community/storage-py/commit/e77112c6ae43df258b85525e514903949a53f735)) + +* chore: update maintainers in license and pyproject ([`1e41913`](https://github.com/supabase-community/storage-py/commit/1e419130639cd2c03bcdf0af9ffd3aea34e81e85)) + +* chore: run pre-commit on all files ([`2654aa4`](https://github.com/supabase-community/storage-py/commit/2654aa4d898b724df11eba28350a6b1cdbb8c0da)) + +* chore: reinstate python version ([`8c9e022`](https://github.com/supabase-community/storage-py/commit/8c9e022780a75c120b7a512d086645b81ad867ad)) + +### Feature + +* feat: initial commit ([`6da4cd9`](https://github.com/supabase-community/storage-py/commit/6da4cd98de5a5344da6683d1082c3237f6870d8d)) + +### Refactor + +* refactor: update test client imports ([`ef1dff9`](https://github.com/supabase-community/storage-py/commit/ef1dff9052aa43165efc3b549026eefbfa75614b)) + +* refactor: change directory structure ([`57889bc`](https://github.com/supabase-community/storage-py/commit/57889bc13ff67ddcc4033ba2d587e7e9e87abb11)) + +### Unknown + +* bump: version 0.0.1 → 0.1.0 ([`a3f27bb`](https://github.com/supabase-community/storage-py/commit/a3f27bb9865c3f0ed76264fe8e014fd5323e7fa0)) diff --git a/src/storage/MAINTAINERS.md b/src/storage/MAINTAINERS.md new file mode 100644 index 00000000..a5fbfd46 --- /dev/null +++ b/src/storage/MAINTAINERS.md @@ -0,0 +1,16 @@ +This page lists all active maintainers of this repository. If you were a maintainer and would like to add your name to the Emeritus list, please send us a PR. + +See CONTRIBUTING.md for general contribution guidelines. + +# Maintainers (in alphabetical order) + +- [anand2312](https://github.com/anand2312) + + +# Emeritus Maintainers (in alphabetical order) +- [dreinon](https://github.com/dreinon) +- [fedden](https://github.com/fedden) +- [J0](https://github.com/J0) +- [leynier](https://github.com/leynier) + + diff --git a/src/storage/Makefile b/src/storage/Makefile new file mode 100644 index 00000000..a2b64561 --- /dev/null +++ b/src/storage/Makefile @@ -0,0 +1,17 @@ +run-infra: + supabase --workdir infra start -x studio,gotrue,postgrest,mailpit,realtime,edge-runtime,logflare,vector,supavisor + +stop-infra: + supabase --workdir infra stop + +tests: run-infra pytest + +pytest: + uv run --package storage3 pytest --cov=./ --cov-report=xml --cov-report=html -vv + +build-sync: + uv run --package storage3 run-unasync.py + sed -i '0,/SyncMock, /{s/SyncMock, //}' tests/_sync/test_bucket.py tests/_sync/test_client.py + sed -i 's/SyncMock/Mock/g' tests/_sync/test_bucket.py tests/_sync/test_client.py + sed -i 's/SyncClient/Client/g' storage3/_sync/client.py storage3/_sync/bucket.py storage3/_sync/file_api.py tests/_sync/test_bucket.py tests/_sync/test_client.py + sed -i 's/self\.session\.aclose/self\.session\.close/g' storage3/_sync/client.py diff --git a/src/storage/README.md b/src/storage/README.md new file mode 100644 index 00000000..a2c077c0 --- /dev/null +++ b/src/storage/README.md @@ -0,0 +1,31 @@ +# Storage-py + +Python Client library to interact with Supabase Storage. + + + +## How to use + +As it takes some effort to get the headers. We suggest that you use the storage functionality through the main [Supabase Python Client](https://github.com/supabase-community/supabase-py) + + +```python3 +from storage3 import AsyncStorageClient + +url = "https://.supabase.co/storage/v1" +key = "" +headers = {"apiKey": key, "Authorization": f"Bearer {key}"} + +storage_client = AsyncStorageClient(url, headers) + +async def get_buckets(): + await storage_client.list_buckets() +``` + +### Uploading files +When uploading files, make sure to set the correct mimetype by using the `file_options` argument: +```py +async def file_upload(): + await storage_client.from_("bucket").upload("/folder/file.png", file_object, {"content-type": "image/png"}) +``` +If no mime type is given, the default `text/plain` will be used. diff --git a/src/storage/infra/supabase/.gitignore b/src/storage/infra/supabase/.gitignore new file mode 100644 index 00000000..a3ad8805 --- /dev/null +++ b/src/storage/infra/supabase/.gitignore @@ -0,0 +1,4 @@ +# Supabase +.branches +.temp +.env diff --git a/src/storage/infra/supabase/config.toml b/src/storage/infra/supabase/config.toml new file mode 100644 index 00000000..c411da4a --- /dev/null +++ b/src/storage/infra/supabase/config.toml @@ -0,0 +1,171 @@ +# A string used to distinguish different Supabase projects on the same host. Defaults to the +# working directory name when running `supabase init`. +project_id = "storage-py" + +[api] +enabled = true +# Port to use for the API URL. +port = 55321 +# Schemas to expose in your API. Tables, views and stored procedures in this schema will get API +# endpoints. `public` is always included. +schemas = ["public", "graphql_public"] +# Extra schemas to add to the search_path of every request. `public` is always included. +extra_search_path = ["public", "extensions"] +# The maximum number of rows returns from a view, table, or stored procedure. Limits payload size +# for accidental or malicious requests. +max_rows = 1000 + +[db] +# Port to use for the local database URL. +port = 55322 +# Port used by db diff command to initialize the shadow database. +shadow_port = 55320 +# The database major version to use. This has to be the same as your remote database's. Run `SHOW +# server_version;` on the remote database to check. +major_version = 15 + +[db.pooler] +enabled = false +# Port to use for the local connection pooler. +port = 55329 +# Specifies when a server connection can be reused by other clients. +# Configure one of the supported pooler modes: `transaction`, `session`. +pool_mode = "transaction" +# How many server connections to allow per user/database pair. +default_pool_size = 20 +# Maximum number of client connections allowed. +max_client_conn = 100 + +[realtime] +enabled = false +# Bind realtime via either IPv4 or IPv6. (default: IPv4) +# ip_version = "IPv6" +# The maximum length in bytes of HTTP request headers. (default: 4096) +# max_header_length = 4096 + +[studio] +enabled = false +# Port to use for Supabase Studio. +port = 55323 +# External URL of the API server that frontend connects to. +api_url = "http://127.0.0.1" +# OpenAI API Key to use for Supabase AI in the Supabase Studio. +openai_api_key = "env(OPENAI_API_KEY)" + +# Email testing server. Emails sent with the local dev setup are not actually sent - rather, they +# are monitored, and you can view the emails that would have been sent from the web interface. +[inbucket] +enabled = false +# Port to use for the email testing server web interface. +port = 55324 +# Uncomment to expose additional ports for testing user applications that send emails. +# smtp_port = 55325 +# pop3_port = 55326 + +[storage] +enabled = true +# The maximum file size allowed (e.g. "5MB", "500KB"). +file_size_limit = "50MiB" + +[storage.image_transformation] +enabled = true + +[auth] +enabled = true +# The base URL of your website. Used as an allow-list for redirects and for constructing URLs used +# in emails. +site_url = "http://127.0.0.1:3000" +# A list of *exact* URLs that auth providers are permitted to redirect to post authentication. +additional_redirect_urls = ["https://127.0.0.1:3000"] +# How long tokens are valid for, in seconds. Defaults to 3600 (1 hour), maximum 604,800 (1 week). +jwt_expiry = 3600 +# If disabled, the refresh token will never expire. +enable_refresh_token_rotation = true +# Allows refresh tokens to be reused after expiry, up to the specified interval in seconds. +# Requires enable_refresh_token_rotation = true. +refresh_token_reuse_interval = 10 +# Allow/disallow new user signups to your project. +enable_signup = true +# Allow/disallow anonymous sign-ins to your project. +enable_anonymous_sign_ins = false +# Allow/disallow testing manual linking of accounts +enable_manual_linking = false + +[auth.email] +# Allow/disallow new user signups via email to your project. +enable_signup = false +# If enabled, a user will be required to confirm any email change on both the old, and new email +# addresses. If disabled, only the new email is required to confirm. +double_confirm_changes = false +# If enabled, users need to confirm their email address before signing in. +enable_confirmations = false +# Controls the minimum amount of time that must pass before sending another signup confirmation or password reset email. +max_frequency = "1s" + +# Uncomment to customize email template +# [auth.email.template.invite] +# subject = "You have been invited" +# content_path = "./supabase/templates/invite.html" + +[auth.sms] +# Allow/disallow new user signups via SMS to your project. +enable_signup = false +# If enabled, users need to confirm their phone number before signing in. +enable_confirmations = false +# Template for sending OTP to users +template = "Your code is {{ .Code }} ." +# Controls the minimum amount of time that must pass before sending another sms otp. +max_frequency = "5s" + +# Use pre-defined map of phone number to OTP for testing. +# [auth.sms.test_otp] +# 4152127777 = "123456" + +# This hook runs before a token is issued and allows you to add additional claims based on the authentication method used. +# [auth.hook.custom_access_token] +# enabled = true +# uri = "pg-functions:////" + +# Configure one of the supported SMS providers: `twilio`, `twilio_verify`, `messagebird`, `textlocal`, `vonage`. +[auth.sms.twilio] +enabled = false +account_sid = "" +message_service_sid = "" +# DO NOT commit your Twilio auth token to git. Use environment variable substitution instead: +auth_token = "env(SUPABASE_AUTH_SMS_TWILIO_AUTH_TOKEN)" + +# Use an external OAuth provider. The full list of providers are: `apple`, `azure`, `bitbucket`, +# `discord`, `facebook`, `github`, `gitlab`, `google`, `keycloak`, `linkedin_oidc`, `notion`, `twitch`, +# `twitter`, `slack`, `spotify`, `workos`, `zoom`. +[auth.external.apple] +enabled = false +client_id = "" +# DO NOT commit your OAuth provider secret to git. Use environment variable substitution instead: +secret = "env(SUPABASE_AUTH_EXTERNAL_APPLE_SECRET)" +# Overrides the default auth redirectUrl. +redirect_uri = "" +# Overrides the default auth provider URL. Used to support self-hosted gitlab, single-tenant Azure, +# or any other third-party OIDC providers. +url = "" +# If enabled, the nonce check will be skipped. Required for local sign in with Google auth. +skip_nonce_check = false + +[analytics] +enabled = false +port = 55327 +vector_port = 55328 +# Configure one of the supported backends: `postgres`, `bigquery`. +backend = "postgres" + +# Experimental features may be deprecated any time +[experimental] +# Configures Postgres storage engine to use OrioleDB (S3) +orioledb_version = "" +# Configures S3 bucket URL, eg. .s3-.amazonaws.com +s3_host = "env(S3_HOST)" +# Configures S3 bucket region, eg. us-east-1 +s3_region = "env(S3_REGION)" +# Configures AWS_ACCESS_KEY_ID for S3 bucket +s3_access_key = "env(S3_ACCESS_KEY)" +# Configures AWS_SECRET_ACCESS_KEY for S3 bucket +s3_secret_key = "env(S3_SECRET_KEY)" diff --git a/src/storage/infra/supabase/migrations/20240513232811_bucket_rls_policies.sql b/src/storage/infra/supabase/migrations/20240513232811_bucket_rls_policies.sql new file mode 100644 index 00000000..61efcc5f --- /dev/null +++ b/src/storage/infra/supabase/migrations/20240513232811_bucket_rls_policies.sql @@ -0,0 +1,41 @@ +CREATE POLICY "Enable read access for all users" ON "storage"."objects" +AS PERMISSIVE FOR SELECT +TO public +USING (true); + +CREATE POLICY "Enable insert for all users" ON "storage"."objects" +AS PERMISSIVE FOR INSERT +TO public +WITH CHECK (true); + +CREATE POLICY "Enable update for all users" ON "storage"."objects" +AS PERMISSIVE FOR UPDATE +TO public +USING (true) +WITH CHECK (true); + +CREATE POLICY "Enable delete for all users" ON "storage"."objects" +AS PERMISSIVE FOR DELETE +TO public +USING (true); + +CREATE POLICY "Enable read access for all users" ON "storage"."buckets" +AS PERMISSIVE FOR SELECT +TO public +USING (true); + +CREATE POLICY "Enable insert for all users " ON "storage"."buckets" +AS PERMISSIVE FOR INSERT +TO public +WITH CHECK (true); + +CREATE POLICY "Enable update for all users" ON "storage"."buckets" +AS PERMISSIVE FOR UPDATE +TO public +USING (true) +WITH CHECK (true); + +CREATE POLICY "Enable delete for all users" ON "storage"."buckets" +AS PERMISSIVE FOR DELETE +TO public +USING (true); diff --git a/src/storage/infra/supabase/seed.sql b/src/storage/infra/supabase/seed.sql new file mode 100644 index 00000000..e69de29b diff --git a/src/storage/pyproject.toml b/src/storage/pyproject.toml new file mode 100644 index 00000000..049b8ab2 --- /dev/null +++ b/src/storage/pyproject.toml @@ -0,0 +1,90 @@ +[project] +name = "storage3" +description = "Supabase Storage client for Python." +authors = [ + { name = "Joel Lee" , email="joel@joellee.org"}, + { name = "Leon Fedden" , email="leonfedden@gmail.com"}, + { name = "Daniel Reinón García" , email="danielreinon@outlook.com"}, + { name = "Leynier Gutiérrez González" , email="leynier41@gmail.com"}, + { name = "Anand Krishna" , email="anand2312@proton.me"}, +] +classifiers = [ + "Programming Language :: Python :: 3", + "License :: OSI Approved :: MIT License", + "Operating System :: OS Independent", +] +license = "MIT" +readme = "README.md" +version = "0.12.1" # {x-release-please-version} +requires-python = ">=3.9" + +dependencies = [ + "httpx[http2] >=0.26,<0.29", + "deprecation >=2.1.0", + "pydantic >=2.11.7", +] + +[project.urls] +documentation = "https://supabase.github.io/storage-py" +homepage = "https://supabase.github.io/storage-py" +repository = "https://github.com/supabase/supabase-py" + +[dependency-groups] +lints = [ + "pre-commit >=4.2.0", + "ruff >=0.12.1", + "unasync >= 0.6.0" +] +docs = [ + "Sphinx >=7.1.2", + "sphinx-press-theme >=0.9.1", + "sphinx-toolbox >=3.4.0", +] +tests = [ + "pytest >=8.3.5", + "pytest-asyncio >=0.21.0", + "pytest-cov >=6.1.0", + "python-dotenv >=1.1.0", +] +dev = [ + { include-group = "lints" }, + { include-group = "tests" }, + { include-group = "lints" }, + { include-group = "docs" }, +] + +[tool.ruff.lint] +select = [ + # pycodestyle + "E", + # Pyflakes + "F", + # pyupgrade + "UP", + # flake8-bugbear + # "B", + # flake8-simplify + # "SIM", + # isort + "I", +] +ignore = ["F401", "F403", "F841", "E712", "E501", "E402", "UP006", "UP035"] +# isort.required-imports = ["from __future__ import annotations"] + +[tool.ruff.lint.pyupgrade] +# Preserve types, even if a file imports `from __future__ import annotations`. +keep-runtime-typing = true + +[tool.pytest.ini_options] +asyncio_mode = "auto" +addopts = "tests" +filterwarnings = [ + "ignore::DeprecationWarning", # ignore deprecation warnings globally +] + +[tool.uv] +default-groups = [ "dev" ] + +[build-system] +requires = ["uv_build>=0.8.3,<0.9.0"] +build-backend = "uv_build" diff --git a/src/storage/run-unasync.py b/src/storage/run-unasync.py new file mode 100644 index 00000000..e4a94232 --- /dev/null +++ b/src/storage/run-unasync.py @@ -0,0 +1,13 @@ +from pathlib import Path + +import unasync + +paths = Path("src/functions").glob("**/*.py") +tests = Path("tests").glob("**/*.py") + +rules = (unasync._DEFAULT_RULE,) + +files = [str(p) for p in list(paths) + list(tests)] + +if __name__ == "__main__": + unasync.unasync_files(files, rules=rules) diff --git a/src/storage/src/storage3/__init__.py b/src/storage/src/storage3/__init__.py new file mode 100644 index 00000000..48b4cb74 --- /dev/null +++ b/src/storage/src/storage3/__init__.py @@ -0,0 +1,44 @@ +from __future__ import annotations + +from typing import Literal, Union, overload + +from storage3._async import AsyncStorageClient +from storage3._async.bucket import AsyncStorageBucketAPI +from storage3._async.file_api import AsyncBucket +from storage3._sync import SyncStorageClient +from storage3._sync.bucket import SyncStorageBucketAPI +from storage3._sync.file_api import SyncBucket +from storage3.constants import DEFAULT_TIMEOUT +from storage3.version import __version__ + +__all__ = [ + "create_client", + "__version__", + "AsyncStorageClient", + "AsyncBucket", + "AsyncStorageBucketAPI", + "SyncStorageClient", + "SyncBucket", + "SyncStorageBucketAPI", +] + + +@overload +def create_client( + url: str, headers: dict[str, str], *, is_async: Literal[True] +) -> AsyncStorageClient: ... + + +@overload +def create_client( + url: str, headers: dict[str, str], *, is_async: Literal[False] +) -> SyncStorageClient: ... + + +def create_client( + url: str, headers: dict[str, str], *, is_async: bool, timeout: int = DEFAULT_TIMEOUT +) -> Union[AsyncStorageClient, SyncStorageClient]: + if is_async: + return AsyncStorageClient(url, headers, timeout) + else: + return SyncStorageClient(url, headers, timeout) diff --git a/src/storage/src/storage3/_async/__init__.py b/src/storage/src/storage3/_async/__init__.py new file mode 100644 index 00000000..694f552f --- /dev/null +++ b/src/storage/src/storage3/_async/__init__.py @@ -0,0 +1 @@ +from .client import AsyncStorageClient as AsyncStorageClient diff --git a/src/storage/src/storage3/_async/bucket.py b/src/storage/src/storage3/_async/bucket.py new file mode 100644 index 00000000..b748b0e7 --- /dev/null +++ b/src/storage/src/storage3/_async/bucket.py @@ -0,0 +1,119 @@ +from __future__ import annotations + +from typing import Any, Optional + +from httpx import AsyncClient, HTTPStatusError, Response + +from ..exceptions import StorageApiError +from ..types import CreateOrUpdateBucketOptions, RequestMethod +from .file_api import AsyncBucket + +__all__ = ["AsyncStorageBucketAPI"] + + +class AsyncStorageBucketAPI: + """This class abstracts access to the endpoint to the Get, List, Empty, and Delete operations on a bucket""" + + def __init__(self, session: AsyncClient) -> None: + self._client = session + + async def _request( + self, + method: RequestMethod, + url: str, + json: Optional[dict[Any, Any]] = None, + ) -> Response: + try: + response = await self._client.request(method, url, json=json) + response.raise_for_status() + except HTTPStatusError as exc: + resp = exc.response.json() + raise StorageApiError(resp["message"], resp["error"], resp["statusCode"]) + + return response + + async def list_buckets(self) -> list[AsyncBucket]: + """Retrieves the details of all storage buckets within an existing product.""" + # if the request doesn't error, it is assured to return a list + res = await self._request("GET", "/bucket") + return [AsyncBucket(**bucket) for bucket in res.json()] + + async def get_bucket(self, id: str) -> AsyncBucket: + """Retrieves the details of an existing storage bucket. + + Parameters + ---------- + id + The unique identifier of the bucket you would like to retrieve. + """ + res = await self._request("GET", f"/bucket/{id}") + json = res.json() + return AsyncBucket(**json) + + async def create_bucket( + self, + id: str, + name: Optional[str] = None, + options: Optional[CreateOrUpdateBucketOptions] = None, + ) -> dict[str, str]: + """Creates a new storage bucket. + + Parameters + ---------- + id + A unique identifier for the bucket you are creating. + name + A name for the bucket you are creating. If not passed, the id is used as the name as well. + options + Extra options to send while creating the bucket. Valid options are `public`, `file_size_limit` and + `allowed_mime_types`. + """ + json: dict[str, Any] = {"id": id, "name": name or id} + if options: + json.update(**options) + res = await self._request( + "POST", + "/bucket", + json=json, + ) + return res.json() + + async def update_bucket( + self, id: str, options: CreateOrUpdateBucketOptions + ) -> dict[str, str]: + """Update a storage bucket. + + Parameters + ---------- + id + The unique identifier of the bucket you would like to update. + options + The properties you want to update. Valid options are `public`, `file_size_limit` and + `allowed_mime_types`. + """ + json = {"id": id, "name": id, **options} + res = await self._request("PUT", f"/bucket/{id}", json=json) + return res.json() + + async def empty_bucket(self, id: str) -> dict[str, str]: + """Removes all objects inside a single bucket. + + Parameters + ---------- + id + The unique identifier of the bucket you would like to empty. + """ + res = await self._request("POST", f"/bucket/{id}/empty", json={}) + return res.json() + + async def delete_bucket(self, id: str) -> dict[str, str]: + """Deletes an existing bucket. Note that you cannot delete buckets with existing objects inside. You must first + `empty()` the bucket. + + Parameters + ---------- + id + The unique identifier of the bucket you would like to delete. + """ + res = await self._request("DELETE", f"/bucket/{id}", json={}) + return res.json() diff --git a/src/storage/src/storage3/_async/client.py b/src/storage/src/storage3/_async/client.py new file mode 100644 index 00000000..b2c5b4e2 --- /dev/null +++ b/src/storage/src/storage3/_async/client.py @@ -0,0 +1,106 @@ +from __future__ import annotations + +from typing import Optional +from warnings import warn + +from httpx import AsyncClient + +from storage3.constants import DEFAULT_TIMEOUT + +from ..version import __version__ +from .bucket import AsyncStorageBucketAPI +from .file_api import AsyncBucketProxy + +__all__ = [ + "AsyncStorageClient", +] + + +class AsyncStorageClient(AsyncStorageBucketAPI): + """Manage storage buckets and files.""" + + def __init__( + self, + url: str, + headers: dict[str, str], + timeout: Optional[int] = None, + verify: Optional[bool] = None, + proxy: Optional[str] = None, + http_client: Optional[AsyncClient] = None, + ) -> None: + headers = { + "User-Agent": f"supabase-py/storage3 v{__version__}", + **headers, + } + + if timeout is not None: + warn( + "The 'timeout' parameter is deprecated. Please configure it in the http client instead.", + DeprecationWarning, + stacklevel=2, + ) + if verify is not None: + warn( + "The 'verify' parameter is deprecated. Please configure it in the http client instead.", + DeprecationWarning, + stacklevel=2, + ) + if proxy is not None: + warn( + "The 'proxy' parameter is deprecated. Please configure it in the http client instead.", + DeprecationWarning, + stacklevel=2, + ) + + self.verify = bool(verify) if verify is not None else True + self.timeout = int(abs(timeout)) if timeout is not None else DEFAULT_TIMEOUT + + self.session = self._create_session( + base_url=url, + headers=headers, + timeout=self.timeout, + verify=self.verify, + proxy=proxy, + http_client=http_client, + ) + super().__init__(self.session) + + def _create_session( + self, + base_url: str, + headers: dict[str, str], + timeout: int, + verify: bool = True, + proxy: Optional[str] = None, + http_client: Optional[AsyncClient] = None, + ) -> AsyncClient: + if http_client is not None: + http_client.base_url = base_url + http_client.headers.update({**headers}) + return http_client + + return AsyncClient( + base_url=base_url, + headers=headers, + timeout=timeout, + proxy=proxy, + verify=verify, + follow_redirects=True, + http2=True, + ) + + async def __aenter__(self) -> AsyncStorageClient: + return self + + async def __aexit__(self, exc_type, exc, tb) -> None: + await self.session.aclose() + + def from_(self, id: str) -> AsyncBucketProxy: + """Run a storage file operation. + + Parameters + ---------- + id + The unique identifier of the bucket + """ + return AsyncBucketProxy(id, self._client) diff --git a/src/storage/src/storage3/_async/file_api.py b/src/storage/src/storage3/_async/file_api.py new file mode 100644 index 00000000..80952466 --- /dev/null +++ b/src/storage/src/storage3/_async/file_api.py @@ -0,0 +1,557 @@ +from __future__ import annotations + +import base64 +import json +import urllib.parse +from dataclasses import dataclass, field +from io import BufferedReader, FileIO +from pathlib import Path +from typing import Any, Literal, Optional, Union, cast + +from httpx import AsyncClient, HTTPStatusError, Response + +from ..constants import DEFAULT_FILE_OPTIONS, DEFAULT_SEARCH_OPTIONS +from ..exceptions import StorageApiError +from ..types import ( + BaseBucket, + CreateSignedUrlResponse, + CreateSignedURLsOptions, + DownloadOptions, + FileOptions, + ListBucketFilesOptions, + RequestMethod, + SignedUploadURL, + SignedUrlResponse, + UploadData, + UploadResponse, + URLOptions, +) +from ..utils import StorageException + +__all__ = ["AsyncBucket"] + + +class AsyncBucketActionsMixin: + """Functions needed to access the file API.""" + + id: str + _client: AsyncClient + + async def _request( + self, + method: RequestMethod, + url: str, + headers: Optional[dict[str, Any]] = None, + json: Optional[dict[Any, Any]] = None, + files: Optional[Any] = None, + **kwargs: Any, + ) -> Response: + try: + response = await self._client.request( + method, url, headers=headers or {}, json=json, files=files, **kwargs + ) + response.raise_for_status() + except HTTPStatusError as exc: + resp = exc.response.json() + raise StorageApiError(resp["message"], resp["error"], resp["statusCode"]) + + # close the resource before returning the response + if files and "file" in files and isinstance(files["file"][1], BufferedReader): + files["file"][1].close() + + return response + + async def create_signed_upload_url(self, path: str) -> SignedUploadURL: + """ + Creates a signed upload URL. + + Parameters + ---------- + path + The file path, including the file name. For example `folder/image.png`. + """ + _path = self._get_final_path(path) + response = await self._request("POST", f"/object/upload/sign/{_path}") + data = response.json() + full_url: urllib.parse.ParseResult = urllib.parse.urlparse( + str(self._client.base_url) + cast(str, data["url"]).lstrip("/") + ) + query_params = urllib.parse.parse_qs(full_url.query) + if not query_params.get("token"): + raise StorageException("No token sent by the API") + return { + "signed_url": full_url.geturl(), + "signedUrl": full_url.geturl(), + "token": query_params["token"][0], + "path": path, + } + + async def upload_to_signed_url( + self, + path: str, + token: str, + file: Union[BufferedReader, bytes, FileIO, str, Path], + file_options: Optional[FileOptions] = None, + ) -> UploadResponse: + """ + Upload a file with a token generated from :meth:`.create_signed_url` + + Parameters + ---------- + path + The file path, including the file name + token + The token generated from :meth:`.create_signed_url` + file + The file contents or a file-like object to upload + file_options + Additional options for the uploaded file + """ + _path = self._get_final_path(path) + _url = urllib.parse.urlparse(f"/object/upload/sign/{_path}") + query_params = urllib.parse.urlencode({"token": token}) + final_url = f"{_url.geturl()}?{query_params}" + + if file_options is None: + file_options = {} + + cache_control = file_options.get("cache-control") + # cacheControl is also passed as form data + # https://github.com/supabase/storage-js/blob/fa44be8156295ba6320ffeff96bdf91016536a46/src/packages/StorageFileApi.ts#L89 + _data = {} + if cache_control: + file_options["cache-control"] = f"max-age={cache_control}" + _data = {"cacheControl": cache_control} + headers = { + **self._client.headers, + **DEFAULT_FILE_OPTIONS, + **file_options, + } + filename = path.rsplit("/", maxsplit=1)[-1] + + if ( + isinstance(file, BufferedReader) + or isinstance(file, bytes) + or isinstance(file, FileIO) + ): + # bytes or byte-stream-like object received + _file = {"file": (filename, file, headers.pop("content-type"))} + else: + # str or pathlib.path received + _file = { + "file": ( + filename, + open(file, "rb"), + headers.pop("content-type"), + ) + } + response = await self._request( + "PUT", final_url, files=_file, headers=headers, data=_data + ) + data: UploadData = response.json() + + return UploadResponse(path=path, Key=data.get("Key")) + + async def create_signed_url( + self, path: str, expires_in: int, options: URLOptions = {} + ) -> SignedUrlResponse: + """ + Parameters + ---------- + path + file path to be downloaded, including the current file name. + expires_in + number of seconds until the signed URL expires. + options + options to be passed for downloading or transforming the file. + """ + json = {"expiresIn": str(expires_in)} + download_query = "" + if options.get("download"): + json.update({"download": options["download"]}) + + download_query = ( + "&download=" + if options.get("download") is True + else f"&download={options.get('download')}" + ) + if options.get("transform"): + json.update({"transform": options["transform"]}) + + path = self._get_final_path(path) + response = await self._request( + "POST", + f"/object/sign/{path}", + json=json, + ) + data = response.json() + + # Prepare URL + url = urllib.parse.urlparse(data["signedURL"]) + url = urllib.parse.quote(url.path) + f"?{url.query}" + + signedURL = ( + f"{self._client.base_url}{cast(str, url).lstrip('/')}{download_query}" + ) + data: SignedUrlResponse = {"signedURL": signedURL, "signedUrl": signedURL} + return data + + async def create_signed_urls( + self, paths: list[str], expires_in: int, options: CreateSignedURLsOptions = {} + ) -> list[CreateSignedUrlResponse]: + """ + Parameters + ---------- + path + file path to be downloaded, including the current file name. + expires_in + number of seconds until the signed URL expires. + options + options to be passed for downloading the file. + """ + json = {"paths": paths, "expiresIn": str(expires_in)} + download_query = "" + if options.get("download"): + json.update({"download": options.get("download")}) + + download_query = ( + "&download=" + if options.get("download") is True + else f"&download={options.get('download')}" + ) + + response = await self._request( + "POST", + f"/object/sign/{self.id}", + json=json, + ) + data = response.json() + signed_urls = [] + for item in data: + # Prepare URL + url = urllib.parse.urlparse(item["signedURL"]) + url = urllib.parse.quote(url.path) + f"?{url.query}" + + signedURL = ( + f"{self._client.base_url}{cast(str, url).lstrip('/')}{download_query}" + ) + signed_item: CreateSignedUrlResponse = { + "error": item["error"], + "path": item["path"], + "signedURL": signedURL, + "signedUrl": signedURL, + } + signed_urls.append(signed_item) + return signed_urls + + async def get_public_url(self, path: str, options: URLOptions = {}) -> str: + """ + Parameters + ---------- + path + file path, including the path and file name. For example `folder/image.png`. + """ + _query_string = [] + download_query = "" + if options.get("download"): + download_query = ( + "&download=" + if options.get("download") is True + else f"&download={options.get('download')}" + ) + + if download_query: + _query_string.append(download_query) + + render_path = "render/image" if options.get("transform") else "object" + transformation_query = ( + urllib.parse.urlencode(options.get("transform")) + if options.get("transform") + else None + ) + + if transformation_query: + _query_string.append(transformation_query) + + query_string = "&".join(_query_string) + query_string = f"?{query_string}" + _path = self._get_final_path(path) + return f"{self._client.base_url}{render_path}/public/{_path}{query_string}" + + async def move(self, from_path: str, to_path: str) -> dict[str, str]: + """ + Moves an existing file, optionally renaming it at the same time. + + Parameters + ---------- + from_path + The original file path, including the current file name. For example `folder/image.png`. + to_path + The new file path, including the new file name. For example `folder/image-copy.png`. + """ + res = await self._request( + "POST", + "/object/move", + json={ + "bucketId": self.id, + "sourceKey": from_path, + "destinationKey": to_path, + }, + ) + return res.json() + + async def copy(self, from_path: str, to_path: str) -> dict[str, str]: + """ + Copies an existing file to a new path in the same bucket. + + Parameters + ---------- + from_path + The original file path, including the current file name. For example `folder/image.png`. + to_path + The new file path, including the new file name. For example `folder/image-copy.png`. + """ + res = await self._request( + "POST", + "/object/copy", + json={ + "bucketId": self.id, + "sourceKey": from_path, + "destinationKey": to_path, + }, + ) + return res.json() + + async def remove(self, paths: list) -> list[dict[str, Any]]: + """ + Deletes files within the same bucket + + Parameters + ---------- + paths + An array or list of files to be deletes, including the path and file name. For example [`folder/image.png`]. + """ + response = await self._request( + "DELETE", + f"/object/{self.id}", + json={"prefixes": paths}, + ) + return response.json() + + async def info( + self, + path: str, + ) -> list[dict[str, str]]: + """ + Lists info for a particular file. + + Parameters + ---------- + path + The path to the file. + """ + response = await self._request( + "GET", + f"/object/info/{self.id}/{path}", + ) + return response.json() + + async def exists( + self, + path: str, + ) -> bool: + """ + Returns True if the file exists, False otherwise. + + Parameters + ---------- + path + The path to the file. + """ + try: + response = await self._request( + "HEAD", + f"/object/{self.id}/{path}", + ) + return response.status_code == 200 + except json.JSONDecodeError: + return False + + async def list( + self, + path: Optional[str] = None, + options: Optional[ListBucketFilesOptions] = None, + ) -> list[dict[str, str]]: + """ + Lists all the files within a bucket. + + Parameters + ---------- + path + The folder path. + options + Search options, including `limit`, `offset`, `sortBy` and `search`. + """ + extra_options = options or {} + extra_headers = {"Content-Type": "application/json"} + body = { + **DEFAULT_SEARCH_OPTIONS, + **extra_options, + "prefix": path or "", + } + response = await self._request( + "POST", + f"/object/list/{self.id}", + json=body, + headers=extra_headers, + ) + return response.json() + + async def download(self, path: str, options: DownloadOptions = {}) -> bytes: + """ + Downloads a file. + + Parameters + ---------- + path + The file path to be downloaded, including the path and file name. For example `folder/image.png`. + """ + render_path = ( + "render/image/authenticated" if options.get("transform") else "object" + ) + transformation_query = urllib.parse.urlencode(options.get("transform") or {}) + query_string = f"?{transformation_query}" if transformation_query else "" + + _path = self._get_final_path(path) + response = await self._request( + "GET", + f"{render_path}/{_path}{query_string}", + ) + return response.content + + async def _upload_or_update( + self, + method: Literal["POST", "PUT"], + path: str, + file: Union[BufferedReader, bytes, FileIO, str, Path], + file_options: Optional[FileOptions] = None, + ) -> UploadResponse: + """ + Uploads a file to an existing bucket. + + Parameters + ---------- + path + The relative file path including the bucket ID. Should be of the format `bucket/folder/subfolder/filename.png`. + The bucket must already exist before attempting to upload. + file + The File object to be stored in the bucket. or a async generator of chunks + file_options + HTTP headers. + """ + if file_options is None: + file_options = {} + cache_control = file_options.pop("cache-control", None) + _data = {} + + upsert = file_options.pop("upsert", None) + if upsert: + file_options.update({"x-upsert": upsert}) + + metadata = file_options.pop("metadata", None) + file_opts_headers = file_options.pop("headers", None) + + headers = { + **self._client.headers, + **DEFAULT_FILE_OPTIONS, + **file_options, + } + + if metadata: + metadata_str = json.dumps(metadata) + headers["x-metadata"] = base64.b64encode(metadata_str.encode()) + _data.update({"metadata": metadata_str}) + + if file_opts_headers: + headers.update({**file_opts_headers}) + + # Only include x-upsert on a POST method + if method != "POST": + del headers["x-upsert"] + + filename = path.rsplit("/", maxsplit=1)[-1] + + if cache_control: + headers["cache-control"] = f"max-age={cache_control}" + _data.update({"cacheControl": cache_control}) + + if ( + isinstance(file, BufferedReader) + or isinstance(file, bytes) + or isinstance(file, FileIO) + ): + # bytes or byte-stream-like object received + files = {"file": (filename, file, headers.pop("content-type"))} + else: + # str or pathlib.path received + files = { + "file": ( + filename, + open(file, "rb"), + headers.pop("content-type"), + ) + } + + _path = self._get_final_path(path) + + response = await self._request( + method, f"/object/{_path}", files=files, headers=headers, data=_data + ) + + data: UploadData = response.json() + + return UploadResponse(path=path, Key=data.get("Key")) + + async def upload( + self, + path: str, + file: Union[BufferedReader, bytes, FileIO, str, Path], + file_options: Optional[FileOptions] = None, + ) -> UploadResponse: + """ + Uploads a file to an existing bucket. + + Parameters + ---------- + path + The relative file path including the bucket ID. Should be of the format `bucket/folder/subfolder/filename.png`. + The bucket must already exist before attempting to upload. + file + The File object to be stored in the bucket. or a async generator of chunks + file_options + HTTP headers. + """ + return await self._upload_or_update("POST", path, file, file_options) + + async def update( + self, + path: str, + file: Union[BufferedReader, bytes, FileIO, str, Path], + file_options: Optional[FileOptions] = None, + ) -> UploadResponse: + return await self._upload_or_update("PUT", path, file, file_options) + + def _get_final_path(self, path: str) -> str: + return f"{self.id}/{path}" + + +class AsyncBucket(BaseBucket): + """Represents a storage bucket.""" + + +@dataclass +class AsyncBucketProxy(AsyncBucketActionsMixin): + """A bucket proxy, this contains the minimum required fields to query the File API.""" + + id: str + _client: AsyncClient = field(repr=False) diff --git a/src/storage/src/storage3/_sync/__init__.py b/src/storage/src/storage3/_sync/__init__.py new file mode 100644 index 00000000..9eedb131 --- /dev/null +++ b/src/storage/src/storage3/_sync/__init__.py @@ -0,0 +1 @@ +from .client import SyncStorageClient as SyncStorageClient diff --git a/src/storage/src/storage3/_sync/bucket.py b/src/storage/src/storage3/_sync/bucket.py new file mode 100644 index 00000000..b81e90b8 --- /dev/null +++ b/src/storage/src/storage3/_sync/bucket.py @@ -0,0 +1,119 @@ +from __future__ import annotations + +from typing import Any, Optional + +from httpx import Client, HTTPStatusError, Response + +from ..exceptions import StorageApiError +from ..types import CreateOrUpdateBucketOptions, RequestMethod +from .file_api import SyncBucket + +__all__ = ["SyncStorageBucketAPI"] + + +class SyncStorageBucketAPI: + """This class abstracts access to the endpoint to the Get, List, Empty, and Delete operations on a bucket""" + + def __init__(self, session: Client) -> None: + self._client = session + + def _request( + self, + method: RequestMethod, + url: str, + json: Optional[dict[Any, Any]] = None, + ) -> Response: + try: + response = self._client.request(method, url, json=json) + response.raise_for_status() + except HTTPStatusError as exc: + resp = exc.response.json() + raise StorageApiError(resp["message"], resp["error"], resp["statusCode"]) + + return response + + def list_buckets(self) -> list[SyncBucket]: + """Retrieves the details of all storage buckets within an existing product.""" + # if the request doesn't error, it is assured to return a list + res = self._request("GET", "/bucket") + return [SyncBucket(**bucket) for bucket in res.json()] + + def get_bucket(self, id: str) -> SyncBucket: + """Retrieves the details of an existing storage bucket. + + Parameters + ---------- + id + The unique identifier of the bucket you would like to retrieve. + """ + res = self._request("GET", f"/bucket/{id}") + json = res.json() + return SyncBucket(**json) + + def create_bucket( + self, + id: str, + name: Optional[str] = None, + options: Optional[CreateOrUpdateBucketOptions] = None, + ) -> dict[str, str]: + """Creates a new storage bucket. + + Parameters + ---------- + id + A unique identifier for the bucket you are creating. + name + A name for the bucket you are creating. If not passed, the id is used as the name as well. + options + Extra options to send while creating the bucket. Valid options are `public`, `file_size_limit` and + `allowed_mime_types`. + """ + json: dict[str, Any] = {"id": id, "name": name or id} + if options: + json.update(**options) + res = self._request( + "POST", + "/bucket", + json=json, + ) + return res.json() + + def update_bucket( + self, id: str, options: CreateOrUpdateBucketOptions + ) -> dict[str, str]: + """Update a storage bucket. + + Parameters + ---------- + id + The unique identifier of the bucket you would like to update. + options + The properties you want to update. Valid options are `public`, `file_size_limit` and + `allowed_mime_types`. + """ + json = {"id": id, "name": id, **options} + res = self._request("PUT", f"/bucket/{id}", json=json) + return res.json() + + def empty_bucket(self, id: str) -> dict[str, str]: + """Removes all objects inside a single bucket. + + Parameters + ---------- + id + The unique identifier of the bucket you would like to empty. + """ + res = self._request("POST", f"/bucket/{id}/empty", json={}) + return res.json() + + def delete_bucket(self, id: str) -> dict[str, str]: + """Deletes an existing bucket. Note that you cannot delete buckets with existing objects inside. You must first + `empty()` the bucket. + + Parameters + ---------- + id + The unique identifier of the bucket you would like to delete. + """ + res = self._request("DELETE", f"/bucket/{id}", json={}) + return res.json() diff --git a/src/storage/src/storage3/_sync/client.py b/src/storage/src/storage3/_sync/client.py new file mode 100644 index 00000000..15876922 --- /dev/null +++ b/src/storage/src/storage3/_sync/client.py @@ -0,0 +1,106 @@ +from __future__ import annotations + +from typing import Optional +from warnings import warn + +from httpx import Client + +from storage3.constants import DEFAULT_TIMEOUT + +from ..version import __version__ +from .bucket import SyncStorageBucketAPI +from .file_api import SyncBucketProxy + +__all__ = [ + "SyncStorageClient", +] + + +class SyncStorageClient(SyncStorageBucketAPI): + """Manage storage buckets and files.""" + + def __init__( + self, + url: str, + headers: dict[str, str], + timeout: Optional[int] = None, + verify: Optional[bool] = None, + proxy: Optional[str] = None, + http_client: Optional[Client] = None, + ) -> None: + headers = { + "User-Agent": f"supabase-py/storage3 v{__version__}", + **headers, + } + + if timeout is not None: + warn( + "The 'timeout' parameter is deprecated. Please configure it in the http client instead.", + DeprecationWarning, + stacklevel=2, + ) + if verify is not None: + warn( + "The 'verify' parameter is deprecated. Please configure it in the http client instead.", + DeprecationWarning, + stacklevel=2, + ) + if proxy is not None: + warn( + "The 'proxy' parameter is deprecated. Please configure it in the http client instead.", + DeprecationWarning, + stacklevel=2, + ) + + self.verify = bool(verify) if verify is not None else True + self.timeout = int(abs(timeout)) if timeout is not None else DEFAULT_TIMEOUT + + self.session = self._create_session( + base_url=url, + headers=headers, + timeout=self.timeout, + verify=self.verify, + proxy=proxy, + http_client=http_client, + ) + super().__init__(self.session) + + def _create_session( + self, + base_url: str, + headers: dict[str, str], + timeout: int, + verify: bool = True, + proxy: Optional[str] = None, + http_client: Optional[Client] = None, + ) -> Client: + if http_client is not None: + http_client.base_url = base_url + http_client.headers.update({**headers}) + return http_client + + return Client( + base_url=base_url, + headers=headers, + timeout=timeout, + proxy=proxy, + verify=verify, + follow_redirects=True, + http2=True, + ) + + def __enter__(self) -> SyncStorageClient: + return self + + def __exit__(self, exc_type, exc, tb) -> None: + self.session.close() + + def from_(self, id: str) -> SyncBucketProxy: + """Run a storage file operation. + + Parameters + ---------- + id + The unique identifier of the bucket + """ + return SyncBucketProxy(id, self._client) diff --git a/src/storage/src/storage3/_sync/file_api.py b/src/storage/src/storage3/_sync/file_api.py new file mode 100644 index 00000000..a10a180f --- /dev/null +++ b/src/storage/src/storage3/_sync/file_api.py @@ -0,0 +1,557 @@ +from __future__ import annotations + +import base64 +import json +import urllib.parse +from dataclasses import dataclass, field +from io import BufferedReader, FileIO +from pathlib import Path +from typing import Any, Literal, Optional, Union, cast + +from httpx import Client, HTTPStatusError, Response + +from ..constants import DEFAULT_FILE_OPTIONS, DEFAULT_SEARCH_OPTIONS +from ..exceptions import StorageApiError +from ..types import ( + BaseBucket, + CreateSignedUrlResponse, + CreateSignedURLsOptions, + DownloadOptions, + FileOptions, + ListBucketFilesOptions, + RequestMethod, + SignedUploadURL, + SignedUrlResponse, + UploadData, + UploadResponse, + URLOptions, +) +from ..utils import StorageException + +__all__ = ["SyncBucket"] + + +class SyncBucketActionsMixin: + """Functions needed to access the file API.""" + + id: str + _client: Client + + def _request( + self, + method: RequestMethod, + url: str, + headers: Optional[dict[str, Any]] = None, + json: Optional[dict[Any, Any]] = None, + files: Optional[Any] = None, + **kwargs: Any, + ) -> Response: + try: + response = self._client.request( + method, url, headers=headers or {}, json=json, files=files, **kwargs + ) + response.raise_for_status() + except HTTPStatusError as exc: + resp = exc.response.json() + raise StorageApiError(resp["message"], resp["error"], resp["statusCode"]) + + # close the resource before returning the response + if files and "file" in files and isinstance(files["file"][1], BufferedReader): + files["file"][1].close() + + return response + + def create_signed_upload_url(self, path: str) -> SignedUploadURL: + """ + Creates a signed upload URL. + + Parameters + ---------- + path + The file path, including the file name. For example `folder/image.png`. + """ + _path = self._get_final_path(path) + response = self._request("POST", f"/object/upload/sign/{_path}") + data = response.json() + full_url: urllib.parse.ParseResult = urllib.parse.urlparse( + str(self._client.base_url) + cast(str, data["url"]).lstrip("/") + ) + query_params = urllib.parse.parse_qs(full_url.query) + if not query_params.get("token"): + raise StorageException("No token sent by the API") + return { + "signed_url": full_url.geturl(), + "signedUrl": full_url.geturl(), + "token": query_params["token"][0], + "path": path, + } + + def upload_to_signed_url( + self, + path: str, + token: str, + file: Union[BufferedReader, bytes, FileIO, str, Path], + file_options: Optional[FileOptions] = None, + ) -> UploadResponse: + """ + Upload a file with a token generated from :meth:`.create_signed_url` + + Parameters + ---------- + path + The file path, including the file name + token + The token generated from :meth:`.create_signed_url` + file + The file contents or a file-like object to upload + file_options + Additional options for the uploaded file + """ + _path = self._get_final_path(path) + _url = urllib.parse.urlparse(f"/object/upload/sign/{_path}") + query_params = urllib.parse.urlencode({"token": token}) + final_url = f"{_url.geturl()}?{query_params}" + + if file_options is None: + file_options = {} + + cache_control = file_options.get("cache-control") + # cacheControl is also passed as form data + # https://github.com/supabase/storage-js/blob/fa44be8156295ba6320ffeff96bdf91016536a46/src/packages/StorageFileApi.ts#L89 + _data = {} + if cache_control: + file_options["cache-control"] = f"max-age={cache_control}" + _data = {"cacheControl": cache_control} + headers = { + **self._client.headers, + **DEFAULT_FILE_OPTIONS, + **file_options, + } + filename = path.rsplit("/", maxsplit=1)[-1] + + if ( + isinstance(file, BufferedReader) + or isinstance(file, bytes) + or isinstance(file, FileIO) + ): + # bytes or byte-stream-like object received + _file = {"file": (filename, file, headers.pop("content-type"))} + else: + # str or pathlib.path received + _file = { + "file": ( + filename, + open(file, "rb"), + headers.pop("content-type"), + ) + } + response = self._request( + "PUT", final_url, files=_file, headers=headers, data=_data + ) + data: UploadData = response.json() + + return UploadResponse(path=path, Key=data.get("Key")) + + def create_signed_url( + self, path: str, expires_in: int, options: URLOptions = {} + ) -> SignedUrlResponse: + """ + Parameters + ---------- + path + file path to be downloaded, including the current file name. + expires_in + number of seconds until the signed URL expires. + options + options to be passed for downloading or transforming the file. + """ + json = {"expiresIn": str(expires_in)} + download_query = "" + if options.get("download"): + json.update({"download": options["download"]}) + + download_query = ( + "&download=" + if options.get("download") is True + else f"&download={options.get('download')}" + ) + if options.get("transform"): + json.update({"transform": options["transform"]}) + + path = self._get_final_path(path) + response = self._request( + "POST", + f"/object/sign/{path}", + json=json, + ) + data = response.json() + + # Prepare URL + url = urllib.parse.urlparse(data["signedURL"]) + url = urllib.parse.quote(url.path) + f"?{url.query}" + + signedURL = ( + f"{self._client.base_url}{cast(str, url).lstrip('/')}{download_query}" + ) + data: SignedUrlResponse = {"signedURL": signedURL, "signedUrl": signedURL} + return data + + def create_signed_urls( + self, paths: list[str], expires_in: int, options: CreateSignedURLsOptions = {} + ) -> list[CreateSignedUrlResponse]: + """ + Parameters + ---------- + path + file path to be downloaded, including the current file name. + expires_in + number of seconds until the signed URL expires. + options + options to be passed for downloading the file. + """ + json = {"paths": paths, "expiresIn": str(expires_in)} + download_query = "" + if options.get("download"): + json.update({"download": options.get("download")}) + + download_query = ( + "&download=" + if options.get("download") is True + else f"&download={options.get('download')}" + ) + + response = self._request( + "POST", + f"/object/sign/{self.id}", + json=json, + ) + data = response.json() + signed_urls = [] + for item in data: + # Prepare URL + url = urllib.parse.urlparse(item["signedURL"]) + url = urllib.parse.quote(url.path) + f"?{url.query}" + + signedURL = ( + f"{self._client.base_url}{cast(str, url).lstrip('/')}{download_query}" + ) + signed_item: CreateSignedUrlResponse = { + "error": item["error"], + "path": item["path"], + "signedURL": signedURL, + "signedUrl": signedURL, + } + signed_urls.append(signed_item) + return signed_urls + + def get_public_url(self, path: str, options: URLOptions = {}) -> str: + """ + Parameters + ---------- + path + file path, including the path and file name. For example `folder/image.png`. + """ + _query_string = [] + download_query = "" + if options.get("download"): + download_query = ( + "&download=" + if options.get("download") is True + else f"&download={options.get('download')}" + ) + + if download_query: + _query_string.append(download_query) + + render_path = "render/image" if options.get("transform") else "object" + transformation_query = ( + urllib.parse.urlencode(options.get("transform")) + if options.get("transform") + else None + ) + + if transformation_query: + _query_string.append(transformation_query) + + query_string = "&".join(_query_string) + query_string = f"?{query_string}" + _path = self._get_final_path(path) + return f"{self._client.base_url}{render_path}/public/{_path}{query_string}" + + def move(self, from_path: str, to_path: str) -> dict[str, str]: + """ + Moves an existing file, optionally renaming it at the same time. + + Parameters + ---------- + from_path + The original file path, including the current file name. For example `folder/image.png`. + to_path + The new file path, including the new file name. For example `folder/image-copy.png`. + """ + res = self._request( + "POST", + "/object/move", + json={ + "bucketId": self.id, + "sourceKey": from_path, + "destinationKey": to_path, + }, + ) + return res.json() + + def copy(self, from_path: str, to_path: str) -> dict[str, str]: + """ + Copies an existing file to a new path in the same bucket. + + Parameters + ---------- + from_path + The original file path, including the current file name. For example `folder/image.png`. + to_path + The new file path, including the new file name. For example `folder/image-copy.png`. + """ + res = self._request( + "POST", + "/object/copy", + json={ + "bucketId": self.id, + "sourceKey": from_path, + "destinationKey": to_path, + }, + ) + return res.json() + + def remove(self, paths: list) -> list[dict[str, Any]]: + """ + Deletes files within the same bucket + + Parameters + ---------- + paths + An array or list of files to be deletes, including the path and file name. For example [`folder/image.png`]. + """ + response = self._request( + "DELETE", + f"/object/{self.id}", + json={"prefixes": paths}, + ) + return response.json() + + def info( + self, + path: str, + ) -> list[dict[str, str]]: + """ + Lists info for a particular file. + + Parameters + ---------- + path + The path to the file. + """ + response = self._request( + "GET", + f"/object/info/{self.id}/{path}", + ) + return response.json() + + def exists( + self, + path: str, + ) -> bool: + """ + Returns True if the file exists, False otherwise. + + Parameters + ---------- + path + The path to the file. + """ + try: + response = self._request( + "HEAD", + f"/object/{self.id}/{path}", + ) + return response.status_code == 200 + except json.JSONDecodeError: + return False + + def list( + self, + path: Optional[str] = None, + options: Optional[ListBucketFilesOptions] = None, + ) -> list[dict[str, str]]: + """ + Lists all the files within a bucket. + + Parameters + ---------- + path + The folder path. + options + Search options, including `limit`, `offset`, `sortBy` and `search`. + """ + extra_options = options or {} + extra_headers = {"Content-Type": "application/json"} + body = { + **DEFAULT_SEARCH_OPTIONS, + **extra_options, + "prefix": path or "", + } + response = self._request( + "POST", + f"/object/list/{self.id}", + json=body, + headers=extra_headers, + ) + return response.json() + + def download(self, path: str, options: DownloadOptions = {}) -> bytes: + """ + Downloads a file. + + Parameters + ---------- + path + The file path to be downloaded, including the path and file name. For example `folder/image.png`. + """ + render_path = ( + "render/image/authenticated" if options.get("transform") else "object" + ) + transformation_query = urllib.parse.urlencode(options.get("transform") or {}) + query_string = f"?{transformation_query}" if transformation_query else "" + + _path = self._get_final_path(path) + response = self._request( + "GET", + f"{render_path}/{_path}{query_string}", + ) + return response.content + + def _upload_or_update( + self, + method: Literal["POST", "PUT"], + path: str, + file: Union[BufferedReader, bytes, FileIO, str, Path], + file_options: Optional[FileOptions] = None, + ) -> UploadResponse: + """ + Uploads a file to an existing bucket. + + Parameters + ---------- + path + The relative file path including the bucket ID. Should be of the format `bucket/folder/subfolder/filename.png`. + The bucket must already exist before attempting to upload. + file + The File object to be stored in the bucket. or a async generator of chunks + file_options + HTTP headers. + """ + if file_options is None: + file_options = {} + cache_control = file_options.pop("cache-control", None) + _data = {} + + upsert = file_options.pop("upsert", None) + if upsert: + file_options.update({"x-upsert": upsert}) + + metadata = file_options.pop("metadata", None) + file_opts_headers = file_options.pop("headers", None) + + headers = { + **self._client.headers, + **DEFAULT_FILE_OPTIONS, + **file_options, + } + + if metadata: + metadata_str = json.dumps(metadata) + headers["x-metadata"] = base64.b64encode(metadata_str.encode()) + _data.update({"metadata": metadata_str}) + + if file_opts_headers: + headers.update({**file_opts_headers}) + + # Only include x-upsert on a POST method + if method != "POST": + del headers["x-upsert"] + + filename = path.rsplit("/", maxsplit=1)[-1] + + if cache_control: + headers["cache-control"] = f"max-age={cache_control}" + _data.update({"cacheControl": cache_control}) + + if ( + isinstance(file, BufferedReader) + or isinstance(file, bytes) + or isinstance(file, FileIO) + ): + # bytes or byte-stream-like object received + files = {"file": (filename, file, headers.pop("content-type"))} + else: + # str or pathlib.path received + files = { + "file": ( + filename, + open(file, "rb"), + headers.pop("content-type"), + ) + } + + _path = self._get_final_path(path) + + response = self._request( + method, f"/object/{_path}", files=files, headers=headers, data=_data + ) + + data: UploadData = response.json() + + return UploadResponse(path=path, Key=data.get("Key")) + + def upload( + self, + path: str, + file: Union[BufferedReader, bytes, FileIO, str, Path], + file_options: Optional[FileOptions] = None, + ) -> UploadResponse: + """ + Uploads a file to an existing bucket. + + Parameters + ---------- + path + The relative file path including the bucket ID. Should be of the format `bucket/folder/subfolder/filename.png`. + The bucket must already exist before attempting to upload. + file + The File object to be stored in the bucket. or a async generator of chunks + file_options + HTTP headers. + """ + return self._upload_or_update("POST", path, file, file_options) + + def update( + self, + path: str, + file: Union[BufferedReader, bytes, FileIO, str, Path], + file_options: Optional[FileOptions] = None, + ) -> UploadResponse: + return self._upload_or_update("PUT", path, file, file_options) + + def _get_final_path(self, path: str) -> str: + return f"{self.id}/{path}" + + +class SyncBucket(BaseBucket): + """Represents a storage bucket.""" + + +@dataclass +class SyncBucketProxy(SyncBucketActionsMixin): + """A bucket proxy, this contains the minimum required fields to query the File API.""" + + id: str + _client: Client = field(repr=False) diff --git a/src/storage/src/storage3/constants.py b/src/storage/src/storage3/constants.py new file mode 100644 index 00000000..7bfc2f32 --- /dev/null +++ b/src/storage/src/storage3/constants.py @@ -0,0 +1,15 @@ +DEFAULT_SEARCH_OPTIONS = { + "limit": 100, + "offset": 0, + "sortBy": { + "column": "name", + "order": "asc", + }, +} +DEFAULT_FILE_OPTIONS = { + "cache-control": "3600", + "content-type": "text/plain;charset=UTF-8", + "x-upsert": "false", +} + +DEFAULT_TIMEOUT = 20 diff --git a/src/storage/src/storage3/exceptions.py b/src/storage/src/storage3/exceptions.py new file mode 100644 index 00000000..d589ca86 --- /dev/null +++ b/src/storage/src/storage3/exceptions.py @@ -0,0 +1,31 @@ +from typing import TypedDict + +from .utils import StorageException + + +class StorageApiErrorDict(TypedDict): + name: str + message: str + status: int + + +class StorageApiError(StorageException): + """Error raised when an operation on the storage API fails.""" + + def __init__(self, message: str, code: str, status: int) -> None: + error_message = ( + f"{{'statusCode': {status}, 'error': {code}, 'message': {message}}}" + ) + super().__init__(error_message) + self.name = "StorageApiError" + self.message = message + self.code = code + self.status = status + + def to_dict(self) -> StorageApiErrorDict: + return { + "name": self.name, + "code": self.code, + "message": self.message, + "status": self.status, + } diff --git a/src/storage/src/storage3/types.py b/src/storage/src/storage3/types.py new file mode 100644 index 00000000..d2c09039 --- /dev/null +++ b/src/storage/src/storage3/types.py @@ -0,0 +1,119 @@ +from __future__ import annotations + +from dataclasses import asdict, dataclass +from datetime import datetime +from typing import Any, Dict, Literal, Optional, TypedDict, Union + +from pydantic import BaseModel, ConfigDict + +RequestMethod = Literal["GET", "POST", "DELETE", "PUT", "HEAD"] + +config = ConfigDict(extra="ignore") + + +class BaseBucket(BaseModel): + """Represents a file storage bucket.""" + + model_config = config + + id: str + name: str + owner: str + public: bool + created_at: datetime + updated_at: datetime + file_size_limit: Optional[int] + allowed_mime_types: Optional[list[str]] + type: Optional[str] = None + + +# used in bucket.list method's option parameter +class _sortByType(TypedDict, total=False): + column: str + order: Literal["asc", "desc"] + + +class SignedUploadURL(TypedDict): + signed_url: str + signedUrl: str + token: str + path: str + + +class CreateOrUpdateBucketOptions(TypedDict, total=False): + public: bool + file_size_limit: int + allowed_mime_types: list[str] + + +class ListBucketFilesOptions(TypedDict, total=False): + limit: int + offset: int + sortBy: _sortByType + search: str + + +class TransformOptions(TypedDict, total=False): + height: int + width: int + resize: Literal["cover", "contain", "fill"] + format: Literal["origin", "avif"] + quality: int + + +class URLOptions(TypedDict, total=False): + download: Union[str, bool] + transform: TransformOptions + + +class CreateSignedURLsOptions(TypedDict, total=False): + download: Union[str, bool] + + +class DownloadOptions(TypedDict, total=False): + transform: TransformOptions + + +FileOptions = TypedDict( + "FileOptions", + { + "cache-control": str, + "content-type": str, + "x-upsert": str, + "upsert": str, + "metadata": Dict[str, Any], + "headers": Dict[str, str], + }, + total=False, +) + + +class UploadData(TypedDict, total=False): + Id: str + Key: str + + +@dataclass +class UploadResponse: + path: str + full_path: str + fullPath: str + + def __init__(self, path, Key): + self.path = path + self.full_path = Key + self.fullPath = Key + + dict = asdict + + +class SignedUrlResponse(TypedDict): + signedURL: str + signedUrl: str + + +class CreateSignedUrlResponse(TypedDict): + error: Optional[str] + path: str + signedURL: str + signedUrl: str diff --git a/src/storage/src/storage3/utils.py b/src/storage/src/storage3/utils.py new file mode 100644 index 00000000..93a1c3f1 --- /dev/null +++ b/src/storage/src/storage3/utils.py @@ -0,0 +1,26 @@ +from deprecation import deprecated +from httpx import AsyncClient as AsyncClient # noqa: F401 +from httpx import Client + +from .version import __version__ + + +class SyncClient(Client): + @deprecated( + "0.11.3", "1.0.0", __version__, "Use `Client` from the httpx package instead" + ) + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + @deprecated( + "0.11.3", + "1.0.0", + __version__, + "Use `close` method from `Client` in the httpx package instead", + ) + def aclose(self) -> None: + self.close() + + +class StorageException(Exception): + """Error raised when an operation on the storage API fails.""" diff --git a/src/storage/src/storage3/version.py b/src/storage/src/storage3/version.py new file mode 100644 index 00000000..89808b86 --- /dev/null +++ b/src/storage/src/storage3/version.py @@ -0,0 +1 @@ +__version__ = "0.12.2" # {x-release-please-version} diff --git a/src/storage/tests/__init__.py b/src/storage/tests/__init__.py new file mode 100644 index 00000000..bb6bf309 --- /dev/null +++ b/src/storage/tests/__init__.py @@ -0,0 +1,2 @@ +from storage3._async.file_api import AsyncBucketProxy as AsyncBucketProxy +from storage3._sync.file_api import SyncBucketProxy as SyncBucketProxy diff --git a/src/storage/tests/_async/__init__.py b/src/storage/tests/_async/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/storage/tests/_async/conftest.py b/src/storage/tests/_async/conftest.py new file mode 100644 index 00000000..34b4a356 --- /dev/null +++ b/src/storage/tests/_async/conftest.py @@ -0,0 +1,31 @@ +from __future__ import annotations + +import asyncio +import os +from collections.abc import AsyncGenerator, Generator + +import pytest +from dotenv import load_dotenv + +from storage3 import AsyncStorageClient + + +def pytest_configure(config) -> None: + load_dotenv(dotenv_path="tests/tests.env") + + +@pytest.fixture +async def storage() -> AsyncGenerator[AsyncStorageClient]: + url = os.environ.get("SUPABASE_TEST_URL") + assert url is not None, "Must provide SUPABASE_TEST_URL environment variable" + key = os.environ.get("SUPABASE_TEST_KEY") + assert key is not None, "Must provide SUPABASE_TEST_KEY environment variable" + async with AsyncStorageClient( + url, + { + "apiKey": key, + "Authorization": f"Bearer {key}", + }, + ) as client: + client.session.timeout = None + yield client diff --git a/src/storage/tests/_async/test_bucket.py b/src/storage/tests/_async/test_bucket.py new file mode 100644 index 00000000..fe8fa0b6 --- /dev/null +++ b/src/storage/tests/_async/test_bucket.py @@ -0,0 +1,209 @@ +from unittest.mock import AsyncMock, Mock + +import pytest +from httpx import HTTPStatusError, Response + +from storage3 import AsyncBucket, AsyncStorageBucketAPI +from storage3.exceptions import StorageApiError +from storage3.types import CreateOrUpdateBucketOptions + + +@pytest.fixture +def mock_client(): + return AsyncMock() + + +@pytest.fixture +def storage_api(mock_client): + return AsyncStorageBucketAPI(mock_client) + + +@pytest.fixture +def mock_response(): + response = Mock(spec=Response) + response.raise_for_status = Mock() + return response + + +async def test_list_buckets(storage_api, mock_client, mock_response): + # Mock response data + mock_response.json.return_value = [ + { + "id": "bucket1", + "name": "Bucket 1", + "public": True, + "owner": "test-owner", + "created_at": "2024-01-01", + "updated_at": "2024-01-01", + "file_size_limit": 1000000, + "allowed_mime_types": ["image/*"], + }, + { + "id": "bucket2", + "name": "Bucket 2", + "public": True, + "owner": "test-owner", + "created_at": "2024-01-01", + "updated_at": "2024-01-01", + "file_size_limit": 1000000, + "allowed_mime_types": ["image/*"], + }, + ] + mock_client.request.return_value = mock_response + + buckets = await storage_api.list_buckets() + + assert len(buckets) == 2 + assert all(isinstance(bucket, AsyncBucket) for bucket in buckets) + assert buckets[0].id == "bucket1" + assert buckets[1].id == "bucket2" + + mock_client.request.assert_called_once_with("GET", "/bucket", json=None) + + +async def test_get_bucket(storage_api, mock_client, mock_response): + bucket_id = "test-bucket" + mock_response.json.return_value = { + "id": bucket_id, + "name": "Test Bucket", + "public": True, + "owner": "test-owner", + "created_at": "2024-01-01", + "updated_at": "2024-01-01", + "file_size_limit": 1000000, + "allowed_mime_types": ["image/*"], + } + mock_client.request.return_value = mock_response + + bucket = await storage_api.get_bucket(bucket_id) + + assert isinstance(bucket, AsyncBucket) + assert bucket.id == bucket_id + assert bucket.name == "Test Bucket" + assert bucket.public is True + assert bucket.owner == "test-owner" + + mock_client.request.assert_called_once_with( + "GET", f"/bucket/{bucket_id}", json=None + ) + + +async def test_create_bucket(storage_api, mock_client, mock_response): + bucket_id = "new-bucket" + bucket_name = "New Bucket" + options = CreateOrUpdateBucketOptions( + public=True, file_size_limit=1000000, allowed_mime_types=["image/*"] + ) + + mock_response.json.return_value = {"message": "Bucket created successfully"} + mock_client.request.return_value = mock_response + + result = await storage_api.create_bucket(bucket_id, bucket_name, options) + + assert result == {"message": "Bucket created successfully"} + mock_client.request.assert_called_once_with( + "POST", + "/bucket", + json={ + "id": bucket_id, + "name": bucket_name, + "public": True, + "file_size_limit": 1000000, + "allowed_mime_types": ["image/*"], + }, + ) + + +async def test_create_bucket_minimal(storage_api, mock_client, mock_response): + bucket_id = "minimal-bucket" + mock_response.json.return_value = {"message": "Bucket created successfully"} + mock_client.request.return_value = mock_response + + result = await storage_api.create_bucket(bucket_id) + + assert result == {"message": "Bucket created successfully"} + mock_client.request.assert_called_once_with( + "POST", "/bucket", json={"id": bucket_id, "name": bucket_id} + ) + + +async def test_update_bucket(storage_api, mock_client, mock_response): + bucket_id = "update-bucket" + options = CreateOrUpdateBucketOptions(public=False, file_size_limit=2000000) + + mock_response.json.return_value = {"message": "Bucket updated successfully"} + mock_client.request.return_value = mock_response + + result = await storage_api.update_bucket(bucket_id, options) + + assert result == {"message": "Bucket updated successfully"} + mock_client.request.assert_called_once_with( + "PUT", + f"/bucket/{bucket_id}", + json={ + "id": bucket_id, + "name": bucket_id, + "public": False, + "file_size_limit": 2000000, + }, + ) + + +async def test_empty_bucket(storage_api, mock_client, mock_response): + bucket_id = "empty-bucket" + mock_response.json.return_value = {"message": "Bucket emptied successfully"} + mock_client.request.return_value = mock_response + + result = await storage_api.empty_bucket(bucket_id) + + assert result == {"message": "Bucket emptied successfully"} + mock_client.request.assert_called_once_with( + "POST", f"/bucket/{bucket_id}/empty", json={} + ) + + +async def test_delete_bucket(storage_api, mock_client, mock_response): + bucket_id = "delete-bucket" + mock_response.json.return_value = {"message": "Bucket deleted successfully"} + mock_client.request.return_value = mock_response + + result = await storage_api.delete_bucket(bucket_id) + + assert result == {"message": "Bucket deleted successfully"} + mock_client.request.assert_called_once_with( + "DELETE", f"/bucket/{bucket_id}", json={} + ) + + +async def test_request_error_handling(storage_api, mock_client): + error_response = Mock(spec=Response) + error_response.json.return_value = { + "message": "Test error message", + "error": "Test error", + "statusCode": 400, + } + + exc = HTTPStatusError("HTTP Error", request=Mock(), response=error_response) + mock_client.request.side_effect = exc + + with pytest.raises(StorageApiError) as exc_info: + await storage_api._request("GET", "/test") + + assert exc_info.value.message == "Test error message" + + +@pytest.mark.parametrize( + "method,url,json_data", + [ + ("GET", "/test", None), + ("POST", "/test", {"key": "value"}), + ("PUT", "/test", {"id": "123"}), + ("DELETE", "/test", {}), + ], +) +async def test_request_methods( + storage_api, mock_client, mock_response, method, url, json_data +): + mock_client.request.return_value = mock_response + await storage_api._request(method, url, json_data) + mock_client.request.assert_called_once_with(method, url, json=json_data) diff --git a/src/storage/tests/_async/test_client.py b/src/storage/tests/_async/test_client.py new file mode 100644 index 00000000..6b98d65e --- /dev/null +++ b/src/storage/tests/_async/test_client.py @@ -0,0 +1,696 @@ +from __future__ import annotations + +from dataclasses import dataclass +from typing import TYPE_CHECKING +from unittest.mock import AsyncMock, Mock, patch +from uuid import uuid4 + +import pytest +from httpx import AsyncClient as HttpxClient +from httpx import HTTPStatusError, Response + +from storage3 import AsyncStorageClient +from storage3.exceptions import StorageApiError +from storage3.utils import StorageException + +from .. import AsyncBucketProxy +from ..utils import AsyncFinalizerFactory + +if TYPE_CHECKING: + from pathlib import Path + from typing import Callable + + +# Global variable to track the ids from the buckets created in the tests run +temp_test_buckets_ids = [] + + +@pytest.fixture +def uuid_factory() -> Callable[[], str]: + def method() -> str: + """Generate a 8 digits long UUID""" + return uuid4().hex[:8] + + return method + + +@pytest.fixture +async def delete_left_buckets( + request: pytest.FixtureRequest, + storage: AsyncStorageClient, +): + """Ensures no test buckets are left when a test that created a bucket fails""" + + async def afinalizer(): + for bucket_id in temp_test_buckets_ids: + try: + await storage.empty_bucket(bucket_id) + await storage.delete_bucket(bucket_id) + except StorageException as e: + # Ignore 404 responses since they mean the bucket was already deleted + response = e.args[0] + if response["statusCode"] != 404: + raise e + continue + + request.addfinalizer(AsyncFinalizerFactory(afinalizer).finalizer) + + +async def bucket_factory( + storage: AsyncStorageClient, uuid_factory: Callable[[], str], public: bool +) -> str: + """Creates a test bucket which will be used in the whole storage tests run and deleted at the end""" + + +@pytest.fixture +async def bucket(storage: AsyncStorageClient, uuid_factory: Callable[[], str]) -> str: + """Creates a test bucket which will be used in the whole storage tests run and deleted at the end""" + bucket_id = uuid_factory() + + # Store bucket_id in global list + global temp_test_buckets_ids + temp_test_buckets_ids.append(bucket_id) + + await storage.create_bucket(id=bucket_id) + + yield bucket_id + + await storage.empty_bucket(bucket_id) + await storage.delete_bucket(bucket_id) + + temp_test_buckets_ids.remove(bucket_id) + + +@pytest.fixture +async def public_bucket( + storage: AsyncStorageClient, uuid_factory: Callable[[], str] +) -> str: + """Creates a test public bucket which will be used in the whole storage tests run and deleted at the end""" + bucket_id = uuid_factory() + + # Store bucket_id in global list + global temp_test_buckets_ids + temp_test_buckets_ids.append(bucket_id) + + await storage.create_bucket(id=bucket_id, options={"public": True}) + + yield bucket_id + + await storage.empty_bucket(bucket_id) + await storage.delete_bucket(bucket_id) + + temp_test_buckets_ids.remove(bucket_id) + + +@pytest.fixture +def storage_file_client(storage: AsyncStorageClient, bucket: str) -> AsyncBucketProxy: + """Creates the storage file client for the whole storage tests run""" + yield storage.from_(bucket) + + +@pytest.fixture +def storage_file_client_public( + storage: AsyncStorageClient, public_bucket: str +) -> AsyncBucketProxy: + """Creates the storage file client for the whole storage tests run""" + yield storage.from_(public_bucket) + + +@dataclass +class FileForTesting: + name: str + local_path: str + bucket_folder: str + bucket_path: str + mime_type: str + file_content: bytes + + +@pytest.fixture +def file(tmp_path: Path, uuid_factory: Callable[[], str]) -> FileForTesting: + """Creates a different test file (same content but different path) for each test""" + file_name = "test_image.svg" + file_content = ( + b' ' + b' ' + b' ' + b' ' + b' ' + ) + bucket_folder = uuid_factory() + bucket_path = f"{bucket_folder}/{file_name}" + file_path = tmp_path / file_name + with open(file_path, "wb") as f: + f.write(file_content) + + return FileForTesting( + name=file_name, + local_path=str(file_path), + bucket_folder=bucket_folder, + bucket_path=bucket_path, + mime_type="image/svg+xml", + file_content=file_content, + ) + + +@pytest.fixture +def two_files(tmp_path: Path, uuid_factory: Callable[[], str]) -> list[FileForTesting]: + """Creates multiple test files (different content, same bucket/folder path, different file names)""" + file_name_1 = "test_image_1.svg" + file_name_2 = "test_image_2.svg" + file_content = ( + b' ' + b' ' + b' ' + b' ' + b' ' + ) + file_content_2 = ( + b' ' + b' ' + b' ' + b' ' + b' ' + ) + bucket_folder = uuid_factory() + bucket_path_1 = f"{bucket_folder}/{file_name_1}" + bucket_path_2 = f"{bucket_folder}/{file_name_2}" + file_path_1 = tmp_path / file_name_1 + file_path_2 = tmp_path / file_name_2 + with open(file_path_1, "wb") as f: + f.write(file_content) + with open(file_path_2, "wb") as f: + f.write(file_content_2) + + return [ + FileForTesting( + name=file_name_1, + local_path=str(file_path_1), + bucket_folder=bucket_folder, + bucket_path=bucket_path_1, + mime_type="image/svg+xml", + file_content=file_content, + ), + FileForTesting( + name=file_name_2, + local_path=str(file_path_2), + bucket_folder=bucket_folder, + bucket_path=bucket_path_2, + mime_type="image/svg+xml", + file_content=file_content_2, + ), + ] + + +@pytest.fixture +def multi_file(tmp_path: Path, uuid_factory: Callable[[], str]) -> list[FileForTesting]: + """Creates multiple test files (same content, same bucket/folder path, different file names)""" + file_name_1 = "test_image_1.svg" + file_name_2 = "test_image_2.svg" + file_content = ( + b' ' + b' ' + b' ' + b' ' + b' ' + ) + bucket_folder = uuid_factory() + bucket_path_1 = f"{bucket_folder}/{file_name_1}" + bucket_path_2 = f"{bucket_folder}/{file_name_2}" + file_path_1 = tmp_path / file_name_1 + file_path_2 = tmp_path / file_name_2 + with open(file_path_1, "wb") as f: + f.write(file_content) + with open(file_path_2, "wb") as f: + f.write(file_content) + + return [ + FileForTesting( + name=file_name_1, + local_path=str(file_path_1), + bucket_folder=bucket_folder, + bucket_path=bucket_path_1, + mime_type="image/svg+xml", + file_content=file_content, + ), + FileForTesting( + name=file_name_2, + local_path=str(file_path_2), + bucket_folder=bucket_folder, + bucket_path=bucket_path_2, + mime_type="image/svg+xml", + file_content=file_content, + ), + ] + + +async def test_client_upload( + storage_file_client: AsyncBucketProxy, file: FileForTesting +) -> None: + """Ensure we can upload files to a bucket""" + await storage_file_client.upload( + file.bucket_path, file.local_path, {"content-type": file.mime_type} + ) + + image = await storage_file_client.download(file.bucket_path) + files = await storage_file_client.list(file.bucket_folder) + image_info = next((f for f in files if f.get("name") == file.name), None) + + assert image == file.file_content + assert image_info.get("metadata", {}).get("mimetype") == file.mime_type + + +async def test_client_update( + storage_file_client: AsyncBucketProxy, + two_files: list[FileForTesting], +) -> None: + """Ensure we can upload files to a bucket""" + await storage_file_client.upload( + two_files[0].bucket_path, + two_files[0].local_path, + {"content-type": two_files[0].mime_type}, + ) + + await storage_file_client.update( + two_files[0].bucket_path, + two_files[1].local_path, + {"content-type": two_files[1].mime_type}, + ) + + image = await storage_file_client.download(two_files[0].bucket_path) + file_list = await storage_file_client.list(two_files[0].bucket_folder) + image_info = next( + (f for f in file_list if f.get("name") == two_files[0].name), None + ) + + assert image == two_files[1].file_content + assert image_info.get("metadata", {}).get("mimetype") == two_files[1].mime_type + + +@pytest.mark.parametrize( + "path", ["foobar.txt", "example/nested.jpg", "/leading/slash.png"] +) +async def test_client_create_signed_upload_url( + storage_file_client: AsyncBucketProxy, path: str +) -> None: + """Ensure we can create signed URLs to upload files to a bucket""" + data = await storage_file_client.create_signed_upload_url(path) + assert data["path"] == path + assert data["token"] + expected_url = f"{storage_file_client._client.base_url}object/upload/sign/{storage_file_client.id}/{path.lstrip('/')}" + assert data["signed_url"].startswith(expected_url) + + +async def test_client_upload_to_signed_url( + storage_file_client: AsyncBucketProxy, file: FileForTesting +) -> None: + """Ensure we can upload to a signed URL with various options""" + # Test with content-type + data = await storage_file_client.create_signed_upload_url(file.bucket_path) + await storage_file_client.upload_to_signed_url( + data["path"], data["token"], file.file_content, {"content-type": file.mime_type} + ) + image = await storage_file_client.download(file.bucket_path) + files = await storage_file_client.list(file.bucket_folder) + image_info = next((f for f in files if f.get("name") == file.name), None) + + assert image == file.file_content + assert image_info.get("metadata", {}).get("mimetype") == file.mime_type + + # Test with file_options=None + data = await storage_file_client.create_signed_upload_url( + f"no_options_{file.bucket_path}" + ) + await storage_file_client.upload_to_signed_url( + data["path"], data["token"], file.file_content + ) + image = await storage_file_client.download(f"no_options_{file.bucket_path}") + assert image == file.file_content + + # Test with cache-control + data = await storage_file_client.create_signed_upload_url( + f"cached_{file.bucket_path}" + ) + await storage_file_client.upload_to_signed_url( + data["path"], data["token"], file.file_content, {"cache-control": "3600"} + ) + cached_info = await storage_file_client.info(f"cached_{file.bucket_path}") + assert cached_info.get("cache_control") == "max-age=3600" + + +async def test_client_create_signed_url( + storage_file_client: AsyncBucketProxy, file: FileForTesting +) -> None: + """Ensure we can create and use signed URLs with various options""" + await storage_file_client.upload( + file.bucket_path, file.local_path, {"content-type": file.mime_type} + ) + + # Test basic signed URL + signed_url = await storage_file_client.create_signed_url(file.bucket_path, 60) + async with HttpxClient(timeout=None) as client: + response = await client.get(signed_url["signedURL"]) + response.raise_for_status() + assert response.content == file.file_content + + # Test with download option + download_signed_url = await storage_file_client.create_signed_url( + file.bucket_path, 60, options={"download": "custom_download.svg"} + ) + async with HttpxClient(timeout=None) as client: + response = await client.get(download_signed_url["signedURL"]) + response.raise_for_status() + assert ( + response.headers["content-disposition"] + == "attachment; filename=custom_download.svg; filename*=UTF-8''custom_download.svg" + ) + assert response.content == file.file_content + + # Test with transform options + transform_signed_url = await storage_file_client.create_signed_url( + file.bucket_path, + 60, + options={"transform": {"width": 200, "height": 200, "resize": "cover"}}, + ) + # assert "width=200" in transform_signed_url["signedURL"] + # assert "height=200" in transform_signed_url["signedURL"] + # assert "resize=cover" in transform_signed_url["signedURL"] + # assert "format=png" in transform_signed_url["signedURL"] + async with HttpxClient(timeout=None) as client: + response = await client.get(transform_signed_url["signedURL"]) + response.raise_for_status() + + +async def test_client_create_signed_urls( + storage_file_client: AsyncBucketProxy, multi_file: list[FileForTesting] +) -> None: + """Ensure we can create signed urls for files in a bucket""" + paths = [] + for file in multi_file: + paths.append(file.bucket_path) + await storage_file_client.upload( + file.bucket_path, file.local_path, {"content-type": file.mime_type} + ) + + signed_urls = await storage_file_client.create_signed_urls(paths, 10) + + async with HttpxClient() as client: + for url in signed_urls: + response = await client.get(url["signedURL"]) + response.raise_for_status() + assert response.content == multi_file[0].file_content + + +async def test_client_get_public_url( + storage_file_client_public: AsyncBucketProxy, file: FileForTesting +) -> None: + """Ensure we can get the public url of a file in a bucket with various options""" + await storage_file_client_public.upload( + file.bucket_path, file.local_path, {"content-type": file.mime_type} + ) + + # Test basic public URL + public_url = await storage_file_client_public.get_public_url(file.bucket_path) + async with HttpxClient(timeout=None) as client: + response = await client.get(public_url) + response.raise_for_status() + assert response.content == file.file_content + + # Test with download option + download_url = await storage_file_client_public.get_public_url( + file.bucket_path, options={"download": "custom_name.svg"} + ) + async with HttpxClient(timeout=None) as client: + response = await client.get(download_url) + response.raise_for_status() + assert ( + response.headers["content-disposition"] + == "attachment; filename=custom_name.svg; filename*=UTF-8''custom_name.svg" + ) + assert response.content == file.file_content + + # Test with transform options + transform_url = await storage_file_client_public.get_public_url( + file.bucket_path, + options={"transform": {"width": 100, "height": 100, "resize": "contain"}}, + ) + assert "width=100" in transform_url + assert "height=100" in transform_url + assert "resize=contain" in transform_url + + +async def test_client_upload_with_custom_metadata( + storage_file_client_public: AsyncBucketProxy, file: FileForTesting +) -> None: + """Ensure we can get the public url of a file in a bucket""" + await storage_file_client_public.upload( + file.bucket_path, + file.local_path, + { + "content-type": file.mime_type, + "metadata": {"custom": "metadata", "second": "second", "third": "third"}, + }, + ) + + info = await storage_file_client_public.info(file.bucket_path) + assert "metadata" in info.keys() + assert info["name"] == file.bucket_path + assert info["metadata"] == { + "custom": "metadata", + "second": "second", + "third": "third", + } + + +async def test_client_info( + storage_file_client_public: AsyncBucketProxy, file: FileForTesting +) -> None: + """Ensure we can get the public url of a file in a bucket""" + await storage_file_client_public.upload( + file.bucket_path, file.local_path, {"content-type": file.mime_type} + ) + + info = await storage_file_client_public.info(file.bucket_path) + assert "metadata" in info.keys() + assert info["name"] == file.bucket_path + assert info["content_type"] == file.mime_type + + +async def test_client_info_with_error( + storage_file_client_public: AsyncBucketProxy, file: FileForTesting +) -> None: + """Ensure we can get the public url of a file in a bucket""" + await storage_file_client_public.upload( + file.bucket_path, file.local_path, {"content-type": file.mime_type} + ) + + """Ensure StorageException is raised when signed URL creation fails""" + mock_error_response = Mock(spec=Response) + mock_error_response.status_code = 404 + mock_error_response.json.return_value = { + "error": "Custom error message", + "statusCode": 404, + "message": "File not found", + } + + mock_response = Mock(spec=Response) + mock_response.json.return_value = {"error": "Custom error message"} + mock_response.raise_for_status.side_effect = HTTPStatusError( + "HTTP Error", request=Mock(), response=mock_error_response + ) + + with patch.object( + storage_file_client_public._client, "request", new_callable=AsyncMock + ) as mock_request: + mock_request.return_value = mock_response + + with pytest.raises( + StorageApiError, + match="{'statusCode': 404, 'error': Custom error message, 'message': File not found}", + ): + await storage_file_client_public.info(file.bucket_path) + + +async def test_client_exists( + storage_file_client_public: AsyncBucketProxy, file: FileForTesting +) -> None: + """Ensure we can get the public url of a file in a bucket""" + await storage_file_client_public.upload( + file.bucket_path, file.local_path, {"content-type": file.mime_type} + ) + + exists = await storage_file_client_public.exists(file.bucket_path) + + assert exists + + +async def test_client_exists_json_decode_error( + storage_file_client_public: AsyncBucketProxy, + monkeypatch: pytest.MonkeyPatch, +) -> None: + """Test exists method handling of json.JSONDecodeError""" + from json import JSONDecodeError + + async def mock_head(*args, **kwargs): + raise JSONDecodeError("Expecting value", "", 0) + + monkeypatch.setattr(storage_file_client_public._client, "head", mock_head) + exists = await storage_file_client_public.exists("some/path") + assert exists is False + + +async def test_client_copy( + storage_file_client: AsyncBucketProxy, file: FileForTesting +) -> None: + """Ensure we can copy files within a bucket""" + # Upload original file + await storage_file_client.upload( + file.bucket_path, file.local_path, {"content-type": file.mime_type} + ) + + # Copy to new path + new_path = f"{file.bucket_folder}/copied_{file.name}" + await storage_file_client.copy(file.bucket_path, new_path) + + # Verify both files exist and have same content + original = await storage_file_client.download(file.bucket_path) + copied = await storage_file_client.download(new_path) + assert original == copied == file.file_content + + # Verify metadata was copied + files = await storage_file_client.list(file.bucket_folder) + copied_info = next( + (f for f in files if f.get("name") == f"copied_{file.name}"), None + ) + assert copied_info.get("metadata", {}).get("mimetype") == file.mime_type + + +async def test_client_move( + storage_file_client: AsyncBucketProxy, file: FileForTesting +) -> None: + """Ensure we can move files within a bucket""" + # Upload original file + await storage_file_client.upload( + file.bucket_path, file.local_path, {"content-type": file.mime_type} + ) + + # Move to new path + new_path = f"{file.bucket_folder}/moved_{file.name}" + await storage_file_client.move(file.bucket_path, new_path) + + # Verify original doesn't exist + assert not await storage_file_client.exists(file.bucket_path) + + # Verify moved file exists with correct content + moved = await storage_file_client.download(new_path) + assert moved == file.file_content + + # Verify metadata was preserved + files = await storage_file_client.list(file.bucket_folder) + moved_info = next((f for f in files if f.get("name") == f"moved_{file.name}"), None) + assert moved_info.get("metadata", {}).get("mimetype") == file.mime_type + + +async def test_client_remove( + storage_file_client: AsyncBucketProxy, file: FileForTesting +) -> None: + """Ensure we can remove files from a bucket""" + # Upload file + await storage_file_client.upload( + file.bucket_path, file.local_path, {"content-type": file.mime_type} + ) + + # Verify file exists + assert await storage_file_client.exists(file.bucket_path) + + # Remove file + await storage_file_client.remove(file.bucket_path) + + # Verify file no longer exists + assert not await storage_file_client.exists(file.bucket_path) + + +async def test_client_remove_multiple( + storage_file_client: AsyncBucketProxy, multi_file: list[FileForTesting] +) -> None: + """Ensure we can remove multiple files from a bucket""" + # Upload files + paths = [] + for file in multi_file: + await storage_file_client.upload( + file.bucket_path, file.local_path, {"content-type": file.mime_type} + ) + paths.append(file.bucket_path) + + # Verify files exist + for path in paths: + assert await storage_file_client.exists(path) + + # Remove files + await storage_file_client.remove(paths) + + # Verify files no longer exist + for path in paths: + assert not await storage_file_client.exists(path) + + +async def test_client_create_signed_upload_url_error( + storage_file_client: AsyncBucketProxy, +) -> None: + """Ensure StorageException is raised when signed URL creation fails""" + mock_response = Mock(spec=Response) + mock_response.json.return_value = {"url": "https://example.com/test.txt"} + + with patch.object( + storage_file_client._client, "request", new_callable=AsyncMock + ) as mock_request: + mock_request.return_value = mock_response + + with pytest.raises(StorageException, match="No token sent by the API"): + await storage_file_client.create_signed_upload_url("test.txt") + + +async def test_client_create_signed_urls_with_download( + storage_file_client: AsyncBucketProxy, multi_file: list[FileForTesting] +) -> None: + """Ensure we can create signed urls with download options for files in a bucket""" + paths = [] + for file in multi_file: + paths.append(file.bucket_path) + await storage_file_client.upload( + file.bucket_path, file.local_path, {"content-type": file.mime_type} + ) + + signed_urls = await storage_file_client.create_signed_urls( + paths, 10, options={"download": True} + ) + + async with HttpxClient() as client: + for i, url in enumerate(signed_urls): + response = await client.get(url["signedURL"]) + response.raise_for_status() + assert response.content == multi_file[i].file_content diff --git a/src/storage/tests/_sync/__init__.py b/src/storage/tests/_sync/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/storage/tests/_sync/conftest.py b/src/storage/tests/_sync/conftest.py new file mode 100644 index 00000000..fe5064a7 --- /dev/null +++ b/src/storage/tests/_sync/conftest.py @@ -0,0 +1,42 @@ +from __future__ import annotations + +import asyncio +import os +from collections.abc import Generator + +import pytest +from dotenv import load_dotenv + +from storage3 import SyncStorageClient + + +def pytest_configure(config) -> None: + load_dotenv(dotenv_path="tests/tests.env") + + +@pytest.fixture(scope="package") +def event_loop() -> Generator[asyncio.AbstractEventLoop]: + """Returns an event loop for the current thread""" + try: + loop = asyncio.get_running_loop() + except RuntimeError: + loop = asyncio.new_event_loop() + yield loop + loop.close() + + +@pytest.fixture(scope="package") +def storage() -> Generator[SyncStorageClient]: + url = os.environ.get("SUPABASE_TEST_URL") + assert url is not None, "Must provide SUPABASE_TEST_URL environment variable" + key = os.environ.get("SUPABASE_TEST_KEY") + assert key is not None, "Must provide SUPABASE_TEST_KEY environment variable" + with SyncStorageClient( + url, + { + "apiKey": key, + "Authorization": f"Bearer {key}", + }, + ) as client: + client.session.timeout = None + yield client diff --git a/src/storage/tests/_sync/test_bucket.py b/src/storage/tests/_sync/test_bucket.py new file mode 100644 index 00000000..a732704d --- /dev/null +++ b/src/storage/tests/_sync/test_bucket.py @@ -0,0 +1,209 @@ +from unittest.mock import Mock + +import pytest +from httpx import HTTPStatusError, Response + +from storage3 import SyncBucket, SyncStorageBucketAPI +from storage3.exceptions import StorageApiError +from storage3.types import CreateOrUpdateBucketOptions + + +@pytest.fixture +def mock_client(): + return Mock() + + +@pytest.fixture +def storage_api(mock_client): + return SyncStorageBucketAPI(mock_client) + + +@pytest.fixture +def mock_response(): + response = Mock(spec=Response) + response.raise_for_status = Mock() + return response + + +def test_list_buckets(storage_api, mock_client, mock_response): + # Mock response data + mock_response.json.return_value = [ + { + "id": "bucket1", + "name": "Bucket 1", + "public": True, + "owner": "test-owner", + "created_at": "2024-01-01", + "updated_at": "2024-01-01", + "file_size_limit": 1000000, + "allowed_mime_types": ["image/*"], + }, + { + "id": "bucket2", + "name": "Bucket 2", + "public": True, + "owner": "test-owner", + "created_at": "2024-01-01", + "updated_at": "2024-01-01", + "file_size_limit": 1000000, + "allowed_mime_types": ["image/*"], + }, + ] + mock_client.request.return_value = mock_response + + buckets = storage_api.list_buckets() + + assert len(buckets) == 2 + assert all(isinstance(bucket, SyncBucket) for bucket in buckets) + assert buckets[0].id == "bucket1" + assert buckets[1].id == "bucket2" + + mock_client.request.assert_called_once_with("GET", "/bucket", json=None) + + +def test_get_bucket(storage_api, mock_client, mock_response): + bucket_id = "test-bucket" + mock_response.json.return_value = { + "id": bucket_id, + "name": "Test Bucket", + "public": True, + "owner": "test-owner", + "created_at": "2024-01-01", + "updated_at": "2024-01-01", + "file_size_limit": 1000000, + "allowed_mime_types": ["image/*"], + } + mock_client.request.return_value = mock_response + + bucket = storage_api.get_bucket(bucket_id) + + assert isinstance(bucket, SyncBucket) + assert bucket.id == bucket_id + assert bucket.name == "Test Bucket" + assert bucket.public is True + assert bucket.owner == "test-owner" + + mock_client.request.assert_called_once_with( + "GET", f"/bucket/{bucket_id}", json=None + ) + + +def test_create_bucket(storage_api, mock_client, mock_response): + bucket_id = "new-bucket" + bucket_name = "New Bucket" + options = CreateOrUpdateBucketOptions( + public=True, file_size_limit=1000000, allowed_mime_types=["image/*"] + ) + + mock_response.json.return_value = {"message": "Bucket created successfully"} + mock_client.request.return_value = mock_response + + result = storage_api.create_bucket(bucket_id, bucket_name, options) + + assert result == {"message": "Bucket created successfully"} + mock_client.request.assert_called_once_with( + "POST", + "/bucket", + json={ + "id": bucket_id, + "name": bucket_name, + "public": True, + "file_size_limit": 1000000, + "allowed_mime_types": ["image/*"], + }, + ) + + +def test_create_bucket_minimal(storage_api, mock_client, mock_response): + bucket_id = "minimal-bucket" + mock_response.json.return_value = {"message": "Bucket created successfully"} + mock_client.request.return_value = mock_response + + result = storage_api.create_bucket(bucket_id) + + assert result == {"message": "Bucket created successfully"} + mock_client.request.assert_called_once_with( + "POST", "/bucket", json={"id": bucket_id, "name": bucket_id} + ) + + +def test_update_bucket(storage_api, mock_client, mock_response): + bucket_id = "update-bucket" + options = CreateOrUpdateBucketOptions(public=False, file_size_limit=2000000) + + mock_response.json.return_value = {"message": "Bucket updated successfully"} + mock_client.request.return_value = mock_response + + result = storage_api.update_bucket(bucket_id, options) + + assert result == {"message": "Bucket updated successfully"} + mock_client.request.assert_called_once_with( + "PUT", + f"/bucket/{bucket_id}", + json={ + "id": bucket_id, + "name": bucket_id, + "public": False, + "file_size_limit": 2000000, + }, + ) + + +def test_empty_bucket(storage_api, mock_client, mock_response): + bucket_id = "empty-bucket" + mock_response.json.return_value = {"message": "Bucket emptied successfully"} + mock_client.request.return_value = mock_response + + result = storage_api.empty_bucket(bucket_id) + + assert result == {"message": "Bucket emptied successfully"} + mock_client.request.assert_called_once_with( + "POST", f"/bucket/{bucket_id}/empty", json={} + ) + + +def test_delete_bucket(storage_api, mock_client, mock_response): + bucket_id = "delete-bucket" + mock_response.json.return_value = {"message": "Bucket deleted successfully"} + mock_client.request.return_value = mock_response + + result = storage_api.delete_bucket(bucket_id) + + assert result == {"message": "Bucket deleted successfully"} + mock_client.request.assert_called_once_with( + "DELETE", f"/bucket/{bucket_id}", json={} + ) + + +def test_request_error_handling(storage_api, mock_client): + error_response = Mock(spec=Response) + error_response.json.return_value = { + "message": "Test error message", + "error": "Test error", + "statusCode": 400, + } + + exc = HTTPStatusError("HTTP Error", request=Mock(), response=error_response) + mock_client.request.side_effect = exc + + with pytest.raises(StorageApiError) as exc_info: + storage_api._request("GET", "/test") + + assert exc_info.value.message == "Test error message" + + +@pytest.mark.parametrize( + "method,url,json_data", + [ + ("GET", "/test", None), + ("POST", "/test", {"key": "value"}), + ("PUT", "/test", {"id": "123"}), + ("DELETE", "/test", {}), + ], +) +def test_request_methods( + storage_api, mock_client, mock_response, method, url, json_data +): + mock_client.request.return_value = mock_response + storage_api._request(method, url, json_data) + mock_client.request.assert_called_once_with(method, url, json=json_data) diff --git a/src/storage/tests/_sync/test_client.py b/src/storage/tests/_sync/test_client.py new file mode 100644 index 00000000..3d3b71e3 --- /dev/null +++ b/src/storage/tests/_sync/test_client.py @@ -0,0 +1,692 @@ +from __future__ import annotations + +from dataclasses import dataclass +from typing import TYPE_CHECKING +from unittest.mock import Mock, patch +from uuid import uuid4 + +import pytest +from httpx import Client as HttpxClient +from httpx import HTTPStatusError, Response + +from storage3 import SyncStorageClient +from storage3.exceptions import StorageApiError +from storage3.utils import StorageException + +from .. import SyncBucketProxy +from ..utils import SyncFinalizerFactory + +if TYPE_CHECKING: + from pathlib import Path + from typing import Callable + + +# Global variable to track the ids from the buckets created in the tests run +temp_test_buckets_ids = [] + + +@pytest.fixture(scope="module") +def uuid_factory() -> Callable[[], str]: + def method() -> str: + """Generate a 8 digits long UUID""" + return uuid4().hex[:8] + + return method + + +@pytest.fixture(scope="module", autouse=True) +def delete_left_buckets( + request: pytest.FixtureRequest, + storage: SyncStorageClient, +): + """Ensures no test buckets are left when a test that created a bucket fails""" + + def afinalizer(): + for bucket_id in temp_test_buckets_ids: + try: + storage.empty_bucket(bucket_id) + storage.delete_bucket(bucket_id) + except StorageException as e: + # Ignore 404 responses since they mean the bucket was already deleted + response = e.args[0] + if response["statusCode"] != 404: + raise e + continue + + request.addfinalizer(SyncFinalizerFactory(afinalizer).finalizer) + + +def bucket_factory( + storage: SyncStorageClient, uuid_factory: Callable[[], str], public: bool +) -> str: + """Creates a test bucket which will be used in the whole storage tests run and deleted at the end""" + + +@pytest.fixture(scope="module") +def bucket(storage: SyncStorageClient, uuid_factory: Callable[[], str]) -> str: + """Creates a test bucket which will be used in the whole storage tests run and deleted at the end""" + bucket_id = uuid_factory() + + # Store bucket_id in global list + global temp_test_buckets_ids + temp_test_buckets_ids.append(bucket_id) + + storage.create_bucket(id=bucket_id) + + yield bucket_id + + storage.empty_bucket(bucket_id) + storage.delete_bucket(bucket_id) + + temp_test_buckets_ids.remove(bucket_id) + + +@pytest.fixture(scope="module") +def public_bucket(storage: SyncStorageClient, uuid_factory: Callable[[], str]) -> str: + """Creates a test public bucket which will be used in the whole storage tests run and deleted at the end""" + bucket_id = uuid_factory() + + # Store bucket_id in global list + global temp_test_buckets_ids + temp_test_buckets_ids.append(bucket_id) + + storage.create_bucket(id=bucket_id, options={"public": True}) + + yield bucket_id + + storage.empty_bucket(bucket_id) + storage.delete_bucket(bucket_id) + + temp_test_buckets_ids.remove(bucket_id) + + +@pytest.fixture(scope="module") +def storage_file_client(storage: SyncStorageClient, bucket: str) -> SyncBucketProxy: + """Creates the storage file client for the whole storage tests run""" + yield storage.from_(bucket) + + +@pytest.fixture(scope="module") +def storage_file_client_public( + storage: SyncStorageClient, public_bucket: str +) -> SyncBucketProxy: + """Creates the storage file client for the whole storage tests run""" + yield storage.from_(public_bucket) + + +@dataclass +class FileForTesting: + name: str + local_path: str + bucket_folder: str + bucket_path: str + mime_type: str + file_content: bytes + + +@pytest.fixture +def file(tmp_path: Path, uuid_factory: Callable[[], str]) -> FileForTesting: + """Creates a different test file (same content but different path) for each test""" + file_name = "test_image.svg" + file_content = ( + b' ' + b' ' + b' ' + b' ' + b' ' + ) + bucket_folder = uuid_factory() + bucket_path = f"{bucket_folder}/{file_name}" + file_path = tmp_path / file_name + with open(file_path, "wb") as f: + f.write(file_content) + + return FileForTesting( + name=file_name, + local_path=str(file_path), + bucket_folder=bucket_folder, + bucket_path=bucket_path, + mime_type="image/svg+xml", + file_content=file_content, + ) + + +@pytest.fixture +def two_files(tmp_path: Path, uuid_factory: Callable[[], str]) -> list[FileForTesting]: + """Creates multiple test files (different content, same bucket/folder path, different file names)""" + file_name_1 = "test_image_1.svg" + file_name_2 = "test_image_2.svg" + file_content = ( + b' ' + b' ' + b' ' + b' ' + b' ' + ) + file_content_2 = ( + b' ' + b' ' + b' ' + b' ' + b' ' + ) + bucket_folder = uuid_factory() + bucket_path_1 = f"{bucket_folder}/{file_name_1}" + bucket_path_2 = f"{bucket_folder}/{file_name_2}" + file_path_1 = tmp_path / file_name_1 + file_path_2 = tmp_path / file_name_2 + with open(file_path_1, "wb") as f: + f.write(file_content) + with open(file_path_2, "wb") as f: + f.write(file_content_2) + + return [ + FileForTesting( + name=file_name_1, + local_path=str(file_path_1), + bucket_folder=bucket_folder, + bucket_path=bucket_path_1, + mime_type="image/svg+xml", + file_content=file_content, + ), + FileForTesting( + name=file_name_2, + local_path=str(file_path_2), + bucket_folder=bucket_folder, + bucket_path=bucket_path_2, + mime_type="image/svg+xml", + file_content=file_content_2, + ), + ] + + +@pytest.fixture +def multi_file(tmp_path: Path, uuid_factory: Callable[[], str]) -> list[FileForTesting]: + """Creates multiple test files (same content, same bucket/folder path, different file names)""" + file_name_1 = "test_image_1.svg" + file_name_2 = "test_image_2.svg" + file_content = ( + b' ' + b' ' + b' ' + b' ' + b' ' + ) + bucket_folder = uuid_factory() + bucket_path_1 = f"{bucket_folder}/{file_name_1}" + bucket_path_2 = f"{bucket_folder}/{file_name_2}" + file_path_1 = tmp_path / file_name_1 + file_path_2 = tmp_path / file_name_2 + with open(file_path_1, "wb") as f: + f.write(file_content) + with open(file_path_2, "wb") as f: + f.write(file_content) + + return [ + FileForTesting( + name=file_name_1, + local_path=str(file_path_1), + bucket_folder=bucket_folder, + bucket_path=bucket_path_1, + mime_type="image/svg+xml", + file_content=file_content, + ), + FileForTesting( + name=file_name_2, + local_path=str(file_path_2), + bucket_folder=bucket_folder, + bucket_path=bucket_path_2, + mime_type="image/svg+xml", + file_content=file_content, + ), + ] + + +def test_client_upload( + storage_file_client: SyncBucketProxy, file: FileForTesting +) -> None: + """Ensure we can upload files to a bucket""" + storage_file_client.upload( + file.bucket_path, file.local_path, {"content-type": file.mime_type} + ) + + image = storage_file_client.download(file.bucket_path) + files = storage_file_client.list(file.bucket_folder) + image_info = next((f for f in files if f.get("name") == file.name), None) + + assert image == file.file_content + assert image_info.get("metadata", {}).get("mimetype") == file.mime_type + + +def test_client_update( + storage_file_client: SyncBucketProxy, + two_files: list[FileForTesting], +) -> None: + """Ensure we can upload files to a bucket""" + storage_file_client.upload( + two_files[0].bucket_path, + two_files[0].local_path, + {"content-type": two_files[0].mime_type}, + ) + + storage_file_client.update( + two_files[0].bucket_path, + two_files[1].local_path, + {"content-type": two_files[1].mime_type}, + ) + + image = storage_file_client.download(two_files[0].bucket_path) + file_list = storage_file_client.list(two_files[0].bucket_folder) + image_info = next( + (f for f in file_list if f.get("name") == two_files[0].name), None + ) + + assert image == two_files[1].file_content + assert image_info.get("metadata", {}).get("mimetype") == two_files[1].mime_type + + +@pytest.mark.parametrize( + "path", ["foobar.txt", "example/nested.jpg", "/leading/slash.png"] +) +def test_client_create_signed_upload_url( + storage_file_client: SyncBucketProxy, path: str +) -> None: + """Ensure we can create signed URLs to upload files to a bucket""" + data = storage_file_client.create_signed_upload_url(path) + assert data["path"] == path + assert data["token"] + expected_url = f"{storage_file_client._client.base_url}object/upload/sign/{storage_file_client.id}/{path.lstrip('/')}" + assert data["signed_url"].startswith(expected_url) + + +def test_client_upload_to_signed_url( + storage_file_client: SyncBucketProxy, file: FileForTesting +) -> None: + """Ensure we can upload to a signed URL with various options""" + # Test with content-type + data = storage_file_client.create_signed_upload_url(file.bucket_path) + storage_file_client.upload_to_signed_url( + data["path"], data["token"], file.file_content, {"content-type": file.mime_type} + ) + image = storage_file_client.download(file.bucket_path) + files = storage_file_client.list(file.bucket_folder) + image_info = next((f for f in files if f.get("name") == file.name), None) + + assert image == file.file_content + assert image_info.get("metadata", {}).get("mimetype") == file.mime_type + + # Test with file_options=None + data = storage_file_client.create_signed_upload_url( + f"no_options_{file.bucket_path}" + ) + storage_file_client.upload_to_signed_url( + data["path"], data["token"], file.file_content + ) + image = storage_file_client.download(f"no_options_{file.bucket_path}") + assert image == file.file_content + + # Test with cache-control + data = storage_file_client.create_signed_upload_url(f"cached_{file.bucket_path}") + storage_file_client.upload_to_signed_url( + data["path"], data["token"], file.file_content, {"cache-control": "3600"} + ) + cached_info = storage_file_client.info(f"cached_{file.bucket_path}") + assert cached_info.get("cache_control") == "max-age=3600" + + +def test_client_create_signed_url( + storage_file_client: SyncBucketProxy, file: FileForTesting +) -> None: + """Ensure we can create and use signed URLs with various options""" + storage_file_client.upload( + file.bucket_path, file.local_path, {"content-type": file.mime_type} + ) + + # Test basic signed URL + signed_url = storage_file_client.create_signed_url(file.bucket_path, 60) + with HttpxClient(timeout=None) as client: + response = client.get(signed_url["signedURL"]) + response.raise_for_status() + assert response.content == file.file_content + + # Test with download option + download_signed_url = storage_file_client.create_signed_url( + file.bucket_path, 60, options={"download": "custom_download.svg"} + ) + with HttpxClient(timeout=None) as client: + response = client.get(download_signed_url["signedURL"]) + response.raise_for_status() + assert ( + response.headers["content-disposition"] + == "attachment; filename=custom_download.svg; filename*=UTF-8''custom_download.svg" + ) + assert response.content == file.file_content + + # Test with transform options + transform_signed_url = storage_file_client.create_signed_url( + file.bucket_path, + 60, + options={"transform": {"width": 200, "height": 200, "resize": "cover"}}, + ) + # assert "width=200" in transform_signed_url["signedURL"] + # assert "height=200" in transform_signed_url["signedURL"] + # assert "resize=cover" in transform_signed_url["signedURL"] + # assert "format=png" in transform_signed_url["signedURL"] + with HttpxClient(timeout=None) as client: + response = client.get(transform_signed_url["signedURL"]) + response.raise_for_status() + + +def test_client_create_signed_urls( + storage_file_client: SyncBucketProxy, multi_file: list[FileForTesting] +) -> None: + """Ensure we can create signed urls for files in a bucket""" + paths = [] + for file in multi_file: + paths.append(file.bucket_path) + storage_file_client.upload( + file.bucket_path, file.local_path, {"content-type": file.mime_type} + ) + + signed_urls = storage_file_client.create_signed_urls(paths, 10) + + with HttpxClient() as client: + for url in signed_urls: + response = client.get(url["signedURL"]) + response.raise_for_status() + assert response.content == multi_file[0].file_content + + +def test_client_get_public_url( + storage_file_client_public: SyncBucketProxy, file: FileForTesting +) -> None: + """Ensure we can get the public url of a file in a bucket with various options""" + storage_file_client_public.upload( + file.bucket_path, file.local_path, {"content-type": file.mime_type} + ) + + # Test basic public URL + public_url = storage_file_client_public.get_public_url(file.bucket_path) + with HttpxClient(timeout=None) as client: + response = client.get(public_url) + response.raise_for_status() + assert response.content == file.file_content + + # Test with download option + download_url = storage_file_client_public.get_public_url( + file.bucket_path, options={"download": "custom_name.svg"} + ) + with HttpxClient(timeout=None) as client: + response = client.get(download_url) + response.raise_for_status() + assert ( + response.headers["content-disposition"] + == "attachment; filename=custom_name.svg; filename*=UTF-8''custom_name.svg" + ) + assert response.content == file.file_content + + # Test with transform options + transform_url = storage_file_client_public.get_public_url( + file.bucket_path, + options={"transform": {"width": 100, "height": 100, "resize": "contain"}}, + ) + assert "width=100" in transform_url + assert "height=100" in transform_url + assert "resize=contain" in transform_url + + +def test_client_upload_with_custom_metadata( + storage_file_client_public: SyncBucketProxy, file: FileForTesting +) -> None: + """Ensure we can get the public url of a file in a bucket""" + storage_file_client_public.upload( + file.bucket_path, + file.local_path, + { + "content-type": file.mime_type, + "metadata": {"custom": "metadata", "second": "second", "third": "third"}, + }, + ) + + info = storage_file_client_public.info(file.bucket_path) + assert "metadata" in info.keys() + assert info["name"] == file.bucket_path + assert info["metadata"] == { + "custom": "metadata", + "second": "second", + "third": "third", + } + + +def test_client_info( + storage_file_client_public: SyncBucketProxy, file: FileForTesting +) -> None: + """Ensure we can get the public url of a file in a bucket""" + storage_file_client_public.upload( + file.bucket_path, file.local_path, {"content-type": file.mime_type} + ) + + info = storage_file_client_public.info(file.bucket_path) + assert "metadata" in info.keys() + assert info["name"] == file.bucket_path + assert info["content_type"] == file.mime_type + + +def test_client_info_with_error( + storage_file_client_public: SyncBucketProxy, file: FileForTesting +) -> None: + """Ensure we can get the public url of a file in a bucket""" + storage_file_client_public.upload( + file.bucket_path, file.local_path, {"content-type": file.mime_type} + ) + + """Ensure StorageException is raised when signed URL creation fails""" + mock_error_response = Mock(spec=Response) + mock_error_response.status_code = 404 + mock_error_response.json.return_value = { + "error": "Custom error message", + "statusCode": 404, + "message": "File not found", + } + + mock_response = Mock(spec=Response) + mock_response.json.return_value = {"error": "Custom error message"} + mock_response.raise_for_status.side_effect = HTTPStatusError( + "HTTP Error", request=Mock(), response=mock_error_response + ) + + with patch.object( + storage_file_client_public._client, "request", new_callable=Mock + ) as mock_request: + mock_request.return_value = mock_response + + with pytest.raises( + StorageApiError, + match="{'statusCode': 404, 'error': Custom error message, 'message': File not found}", + ): + storage_file_client_public.info(file.bucket_path) + + +def test_client_exists( + storage_file_client_public: SyncBucketProxy, file: FileForTesting +) -> None: + """Ensure we can get the public url of a file in a bucket""" + storage_file_client_public.upload( + file.bucket_path, file.local_path, {"content-type": file.mime_type} + ) + + exists = storage_file_client_public.exists(file.bucket_path) + + assert exists + + +def test_client_exists_json_decode_error( + storage_file_client_public: SyncBucketProxy, + monkeypatch: pytest.MonkeyPatch, +) -> None: + """Test exists method handling of json.JSONDecodeError""" + from json import JSONDecodeError + + def mock_head(*args, **kwargs): + raise JSONDecodeError("Expecting value", "", 0) + + monkeypatch.setattr(storage_file_client_public._client, "head", mock_head) + exists = storage_file_client_public.exists("some/path") + assert exists is False + + +def test_client_copy( + storage_file_client: SyncBucketProxy, file: FileForTesting +) -> None: + """Ensure we can copy files within a bucket""" + # Upload original file + storage_file_client.upload( + file.bucket_path, file.local_path, {"content-type": file.mime_type} + ) + + # Copy to new path + new_path = f"{file.bucket_folder}/copied_{file.name}" + storage_file_client.copy(file.bucket_path, new_path) + + # Verify both files exist and have same content + original = storage_file_client.download(file.bucket_path) + copied = storage_file_client.download(new_path) + assert original == copied == file.file_content + + # Verify metadata was copied + files = storage_file_client.list(file.bucket_folder) + copied_info = next( + (f for f in files if f.get("name") == f"copied_{file.name}"), None + ) + assert copied_info.get("metadata", {}).get("mimetype") == file.mime_type + + +def test_client_move( + storage_file_client: SyncBucketProxy, file: FileForTesting +) -> None: + """Ensure we can move files within a bucket""" + # Upload original file + storage_file_client.upload( + file.bucket_path, file.local_path, {"content-type": file.mime_type} + ) + + # Move to new path + new_path = f"{file.bucket_folder}/moved_{file.name}" + storage_file_client.move(file.bucket_path, new_path) + + # Verify original doesn't exist + assert not storage_file_client.exists(file.bucket_path) + + # Verify moved file exists with correct content + moved = storage_file_client.download(new_path) + assert moved == file.file_content + + # Verify metadata was preserved + files = storage_file_client.list(file.bucket_folder) + moved_info = next((f for f in files if f.get("name") == f"moved_{file.name}"), None) + assert moved_info.get("metadata", {}).get("mimetype") == file.mime_type + + +def test_client_remove( + storage_file_client: SyncBucketProxy, file: FileForTesting +) -> None: + """Ensure we can remove files from a bucket""" + # Upload file + storage_file_client.upload( + file.bucket_path, file.local_path, {"content-type": file.mime_type} + ) + + # Verify file exists + assert storage_file_client.exists(file.bucket_path) + + # Remove file + storage_file_client.remove(file.bucket_path) + + # Verify file no longer exists + assert not storage_file_client.exists(file.bucket_path) + + +def test_client_remove_multiple( + storage_file_client: SyncBucketProxy, multi_file: list[FileForTesting] +) -> None: + """Ensure we can remove multiple files from a bucket""" + # Upload files + paths = [] + for file in multi_file: + storage_file_client.upload( + file.bucket_path, file.local_path, {"content-type": file.mime_type} + ) + paths.append(file.bucket_path) + + # Verify files exist + for path in paths: + assert storage_file_client.exists(path) + + # Remove files + storage_file_client.remove(paths) + + # Verify files no longer exist + for path in paths: + assert not storage_file_client.exists(path) + + +def test_client_create_signed_upload_url_error( + storage_file_client: SyncBucketProxy, +) -> None: + """Ensure StorageException is raised when signed URL creation fails""" + mock_response = Mock(spec=Response) + mock_response.json.return_value = {"url": "https://example.com/test.txt"} + + with patch.object( + storage_file_client._client, "request", new_callable=Mock + ) as mock_request: + mock_request.return_value = mock_response + + with pytest.raises(StorageException, match="No token sent by the API"): + storage_file_client.create_signed_upload_url("test.txt") + + +def test_client_create_signed_urls_with_download( + storage_file_client: SyncBucketProxy, multi_file: list[FileForTesting] +) -> None: + """Ensure we can create signed urls with download options for files in a bucket""" + paths = [] + for file in multi_file: + paths.append(file.bucket_path) + storage_file_client.upload( + file.bucket_path, file.local_path, {"content-type": file.mime_type} + ) + + signed_urls = storage_file_client.create_signed_urls( + paths, 10, options={"download": True} + ) + + with HttpxClient() as client: + for i, url in enumerate(signed_urls): + response = client.get(url["signedURL"]) + response.raise_for_status() + assert response.content == multi_file[i].file_content diff --git a/src/storage/tests/test_client.py b/src/storage/tests/test_client.py new file mode 100644 index 00000000..d5434d46 --- /dev/null +++ b/src/storage/tests/test_client.py @@ -0,0 +1,101 @@ +from typing import Dict + +import pytest +from httpx import AsyncClient, Client, Timeout + +from storage3 import AsyncStorageClient, SyncStorageClient +from storage3.constants import DEFAULT_TIMEOUT + + +@pytest.fixture +def valid_url() -> str: + return "https://example.com/storage/v1" + + +@pytest.fixture +def valid_headers() -> Dict[str, str]: + return {"Authorization": "Bearer test_token", "apikey": "test_api_key"} + + +def test_create_async_client(valid_url, valid_headers): + client = AsyncStorageClient(url=valid_url, headers=valid_headers) + + assert isinstance(client, AsyncStorageClient) + assert all( + client._client.headers[key] == value for key, value in valid_headers.items() + ) + assert client._client.timeout == Timeout(DEFAULT_TIMEOUT) + + +def test_create_sync_client(valid_url, valid_headers): + client = SyncStorageClient(url=valid_url, headers=valid_headers) + + assert isinstance(client, SyncStorageClient) + assert all( + client._client.headers[key] == value for key, value in valid_headers.items() + ) + assert client._client.timeout == Timeout(DEFAULT_TIMEOUT) + + +def test_async_storage_client(valid_url, valid_headers): + headers = {"x-user-agent": "my-app/0.0.1"} + http_client = AsyncClient(headers=headers) + client = AsyncStorageClient( + url=valid_url, headers=valid_headers, http_client=http_client + ) + + assert isinstance(client, AsyncStorageClient) + assert all( + client._client.headers[key] == value for key, value in valid_headers.items() + ) + assert client._client.headers.get("x-user-agent") == "my-app/0.0.1" + assert client._client.timeout == Timeout(5.0) + + +def test_sync_storage_client(valid_url, valid_headers): + headers = {"x-user-agent": "my-app/0.0.1"} + http_client = Client(headers=headers) + client = SyncStorageClient( + url=valid_url, headers=valid_headers, http_client=http_client + ) + + assert isinstance(client, SyncStorageClient) + assert all( + client._client.headers[key] == value for key, value in valid_headers.items() + ) + assert client._client.headers.get("x-user-agent") == "my-app/0.0.1" + assert client._client.timeout == Timeout(5.0) + + +def test_async_storage_client_with_httpx(valid_url, valid_headers): + client = AsyncStorageClient(url=valid_url, headers=valid_headers) + + assert isinstance(client, AsyncStorageClient) + assert all( + client._client.headers[key] == value for key, value in valid_headers.items() + ) + assert client._client.timeout == Timeout(DEFAULT_TIMEOUT) + + +def test_sync_storage_client_with_httpx(valid_url, valid_headers): + client = SyncStorageClient(url=valid_url, headers=valid_headers) + + assert isinstance(client, SyncStorageClient) + assert all( + client._client.headers[key] == value for key, value in valid_headers.items() + ) + assert client._client.timeout == Timeout(DEFAULT_TIMEOUT) + + +def test_custom_timeout(valid_url, valid_headers): + custom_timeout = 30 + + async_client = AsyncStorageClient( + url=valid_url, headers=valid_headers, timeout=custom_timeout + ) + assert async_client._client.timeout == Timeout(custom_timeout) + + sync_client = SyncStorageClient( + url=valid_url, headers=valid_headers, timeout=custom_timeout + ) + assert sync_client._client.timeout == Timeout(custom_timeout) diff --git a/src/storage/tests/test_exceptions.py b/src/storage/tests/test_exceptions.py new file mode 100644 index 00000000..de9031d0 --- /dev/null +++ b/src/storage/tests/test_exceptions.py @@ -0,0 +1,47 @@ +from storage3.exceptions import StorageApiError + + +def test_storage_api_error_initialization(): + # Arrange + message = "Test error message" + code = "TEST_ERROR" + status = 400 + + # Act + error = StorageApiError(message, code, status) + + # Assert + assert error.message == message + assert error.code == code + assert error.status == status + assert error.name == "StorageApiError" + assert ( + str(error) + == "{'statusCode': 400, 'error': TEST_ERROR, 'message': Test error message}" + ) + + +def test_storage_api_error_to_dict(): + # Arrange + error = StorageApiError("Test message", "TEST_CODE", 404) + + # Act + error_dict = error.to_dict() + + # Assert + assert error_dict == { + "name": "StorageApiError", + "code": "TEST_CODE", + "message": "Test message", + "status": 404, + } + + +def test_storage_api_error_inheritance(): + # Arrange & Act + error = StorageApiError("Test message", "TEST_CODE", 500) + + # Assert + from storage3.utils import StorageException + + assert isinstance(error, StorageException) diff --git a/src/storage/tests/test_utils.py b/src/storage/tests/test_utils.py new file mode 100644 index 00000000..a6f308f5 --- /dev/null +++ b/src/storage/tests/test_utils.py @@ -0,0 +1,12 @@ +from deprecation import fail_if_not_removed + +from storage3.utils import SyncClient + + +@fail_if_not_removed +def test_sync_client(): + client = SyncClient() + # Verify that aclose method exists and calls close + assert hasattr(client, "aclose") + assert callable(client.aclose) + client.aclose() # Should not raise any exception diff --git a/src/storage/tests/tests.env b/src/storage/tests/tests.env new file mode 100644 index 00000000..b6b22300 --- /dev/null +++ b/src/storage/tests/tests.env @@ -0,0 +1,2 @@ +SUPABASE_TEST_KEY="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24iLCJleHAiOjE5ODM4MTI5OTZ9.CRXP1A7WOeoJeXxjNni43kdQwgnWNReilDMblYTn_I0" +SUPABASE_TEST_URL="http://localhost:55321/storage/v1" diff --git a/src/storage/tests/utils.py b/src/storage/tests/utils.py new file mode 100644 index 00000000..4705cf2f --- /dev/null +++ b/src/storage/tests/utils.py @@ -0,0 +1,16 @@ +import asyncio +from typing import Any, Callable, Coroutine + + +class AsyncFinalizerFactory: + def __init__(self, finalizer: Callable[[], Coroutine[Any, Any, None]]): + def func(): + event_loop = asyncio.get_event_loop_policy().get_event_loop() + return event_loop.run_until_complete(finalizer()) + + self.finalizer = func + + +class SyncFinalizerFactory: + def __init__(self, finalizer: Callable[[], None]): + self.finalizer = finalizer diff --git a/src/supabase/pyproject.toml b/src/supabase/pyproject.toml index 0de2b819..7c880ebb 100644 --- a/src/supabase/pyproject.toml +++ b/src/supabase/pyproject.toml @@ -21,9 +21,9 @@ requires-python = ">=3.9" dependencies = [ "realtime", "supabase_functions", + "storage3", "postgrest == 1.1.1", "supabase_auth == 2.12.3", - "storage3 == 0.12.0", "httpx >=0.26,<0.29", ] diff --git a/uv.lock b/uv.lock index fb0da69a..54dde19a 100644 --- a/uv.lock +++ b/uv.lock @@ -2,13 +2,16 @@ version = 1 revision = 2 requires-python = ">=3.9" resolution-markers = [ + "python_full_version >= '3.13'", + "python_full_version >= '3.11' and python_full_version < '3.13'", + "python_full_version == '3.10.*'", "python_full_version < '3.10'", - "python_full_version >= '3.10'", ] [manifest] members = [ "realtime", + "storage3", "supabase", "supabase-functions", ] @@ -138,6 +141,32 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl", hash = "sha256:053243f8b92b990551949e63930a839ff0cf0b0ebbe0597b0f3fb19e1a0fe82e", size = 7490, upload-time = "2025-07-03T22:54:42.156Z" }, ] +[[package]] +name = "alabaster" +version = "0.7.16" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.10'", +] +sdist = { url = "https://files.pythonhosted.org/packages/c9/3e/13dd8e5ed9094e734ac430b5d0eb4f2bb001708a8b7856cbf8e084e001ba/alabaster-0.7.16.tar.gz", hash = "sha256:75a8b99c28a5dad50dd7f8ccdd447a121ddb3892da9e53d1ca5cca3106d58d65", size = 23776, upload-time = "2024-01-10T00:56:10.189Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/32/34/d4e1c02d3bee589efb5dfa17f88ea08bdb3e3eac12bc475462aec52ed223/alabaster-0.7.16-py3-none-any.whl", hash = "sha256:b46733c07dce03ae4e150330b975c75737fa60f0a7c591b6c8bf4928a28e2c92", size = 13511, upload-time = "2024-01-10T00:56:08.388Z" }, +] + +[[package]] +name = "alabaster" +version = "1.0.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.13'", + "python_full_version >= '3.11' and python_full_version < '3.13'", + "python_full_version == '3.10.*'", +] +sdist = { url = "https://files.pythonhosted.org/packages/a6/f8/d9c74d0daf3f742840fd818d69cfae176fa332022fd44e3469487d5a9420/alabaster-1.0.0.tar.gz", hash = "sha256:c00dca57bca26fa62a6d7d0a9fcce65f3e026e9bfe33e9c538fd3fbb2144fd9e", size = 24210, upload-time = "2024-07-26T18:15:03.762Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/b3/6b4067be973ae96ba0d615946e314c5ae35f9f993eca561b356540bb0c2b/alabaster-1.0.0-py3-none-any.whl", hash = "sha256:fc6786402dc3fcb2de3cabd5fe455a2db534b371124f1f21de8731783dec828b", size = 13929, upload-time = "2024-07-26T18:15:02.05Z" }, +] + [[package]] name = "annotated-types" version = "0.7.0" @@ -162,6 +191,34 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/6f/12/e5e0282d673bb9746bacfb6e2dba8719989d3660cdb2ea79aee9a9651afb/anyio-4.10.0-py3-none-any.whl", hash = "sha256:60e474ac86736bbfd6f210f7a61218939c318f43f9972497381f1c5e930ed3d1", size = 107213, upload-time = "2025-08-04T08:54:24.882Z" }, ] +[[package]] +name = "apeye" +version = "1.4.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "apeye-core" }, + { name = "domdf-python-tools" }, + { name = "platformdirs" }, + { name = "requests" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/4f/6b/cc65e31843d7bfda8313a9dc0c77a21e8580b782adca53c7cb3e511fe023/apeye-1.4.1.tar.gz", hash = "sha256:14ea542fad689e3bfdbda2189a354a4908e90aee4bf84c15ab75d68453d76a36", size = 99219, upload-time = "2023-08-14T15:32:41.381Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/89/7b/2d63664777b3e831ac1b1d8df5bbf0b7c8bee48e57115896080890527b1b/apeye-1.4.1-py3-none-any.whl", hash = "sha256:44e58a9104ec189bf42e76b3a7fe91e2b2879d96d48e9a77e5e32ff699c9204e", size = 107989, upload-time = "2023-08-14T15:32:40.064Z" }, +] + +[[package]] +name = "apeye-core" +version = "1.1.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "domdf-python-tools" }, + { name = "idna" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e5/4c/4f108cfd06923bd897bf992a6ecb6fb122646ee7af94d7f9a64abd071d4c/apeye_core-1.1.5.tar.gz", hash = "sha256:5de72ed3d00cc9b20fea55e54b7ab8f5ef8500eb33a5368bc162a5585e238a55", size = 96511, upload-time = "2024-01-30T17:45:48.727Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/77/9f/fa9971d2a0c6fef64c87ba362a493a4f230eff4ea8dfb9f4c7cbdf71892e/apeye_core-1.1.5-py3-none-any.whl", hash = "sha256:dc27a93f8c9e246b3b238c5ea51edf6115ab2618ef029b9f2d9a190ec8228fbf", size = 99286, upload-time = "2024-01-30T17:45:46.764Z" }, +] + [[package]] name = "argcomplete" version = "3.6.2" @@ -189,12 +246,49 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/77/06/bb80f5f86020c4551da315d78b3ab75e8228f89f0162f2c3a819e407941a/attrs-25.3.0-py3-none-any.whl", hash = "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3", size = 63815, upload-time = "2025-03-13T11:10:21.14Z" }, ] +[[package]] +name = "autodocsumm" +version = "0.2.14" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "sphinx", version = "7.4.7", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, + { name = "sphinx", version = "8.2.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/03/96/92afe8a7912b327c01f0a8b6408c9556ee13b1aba5b98d587ac7327ff32d/autodocsumm-0.2.14.tar.gz", hash = "sha256:2839a9d4facc3c4eccd306c08695540911042b46eeafcdc3203e6d0bab40bc77", size = 46357, upload-time = "2024-10-23T18:51:47.369Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/87/bc/3f66af9beb683728e06ca08797e4e9d3e44f432f339718cae3ba856a9cad/autodocsumm-0.2.14-py3-none-any.whl", hash = "sha256:3bad8717fc5190802c60392a7ab04b9f3c97aa9efa8b3780b3d81d615bfe5dc0", size = 14640, upload-time = "2024-10-23T18:51:45.115Z" }, +] + +[[package]] +name = "babel" +version = "2.17.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7d/6b/d52e42361e1aa00709585ecc30b3f9684b3ab62530771402248b1b1d6240/babel-2.17.0.tar.gz", hash = "sha256:0c54cffb19f690cdcc52a3b50bcbf71e07a808d1c80d549f2459b9d2cf0afb9d", size = 9951852, upload-time = "2025-02-01T15:17:41.026Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/b8/3fe70c75fe32afc4bb507f75563d39bc5642255d1d94f1f23604725780bf/babel-2.17.0-py3-none-any.whl", hash = "sha256:4d0b53093fdfb4b21c92b5213dba5a1b23885afa8383709427046b21c366e5f2", size = 10182537, upload-time = "2025-02-01T15:17:37.39Z" }, +] + +[[package]] +name = "beautifulsoup4" +version = "4.13.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "soupsieve" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d8/e4/0c4c39e18fd76d6a628d4dd8da40543d136ce2d1752bd6eeeab0791f4d6b/beautifulsoup4-4.13.4.tar.gz", hash = "sha256:dbb3c4e1ceae6aefebdaf2423247260cd062430a410e38c66f2baa50a8437195", size = 621067, upload-time = "2025-04-15T17:05:13.836Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/50/cd/30110dc0ffcf3b131156077b90e9f60ed75711223f306da4db08eff8403b/beautifulsoup4-4.13.4-py3-none-any.whl", hash = "sha256:9bbbb14bfde9d79f38b8cd5f8c7c85f4b8f2523190ebed90e950a8dea4cb1c4b", size = 187285, upload-time = "2025-04-15T17:05:12.221Z" }, +] + [[package]] name = "black" version = "25.1.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "click" }, + { name = "click", version = "8.1.8", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "click", version = "8.2.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "mypy-extensions" }, { name = "packaging" }, { name = "pathspec" }, @@ -227,6 +321,24 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/09/71/54e999902aed72baf26bca0d50781b01838251a462612966e9fc4891eadd/black-25.1.0-py3-none-any.whl", hash = "sha256:95e8176dae143ba9097f351d174fdaf0ccd29efb414b362ae3fd72bf0f710717", size = 207646, upload-time = "2025-01-29T04:15:38.082Z" }, ] +[[package]] +name = "cachecontrol" +version = "0.14.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "msgpack" }, + { name = "requests" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/58/3a/0cbeb04ea57d2493f3ec5a069a117ab467f85e4a10017c6d854ddcbff104/cachecontrol-0.14.3.tar.gz", hash = "sha256:73e7efec4b06b20d9267b441c1f733664f989fb8688391b670ca812d70795d11", size = 28985, upload-time = "2025-04-30T16:45:06.135Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/81/4c/800b0607b00b3fd20f1087f80ab53d6b4d005515b0f773e4831e37cfa83f/cachecontrol-0.14.3-py3-none-any.whl", hash = "sha256:b35e44a3113f17d2a31c1e6b27b9de6d4405f84ae51baa8c1d3cc5b633010cae", size = 21802, upload-time = "2025-04-30T16:45:03.863Z" }, +] + +[package.optional-dependencies] +filecache = [ + { name = "filelock" }, +] + [[package]] name = "cattrs" version = "25.1.1" @@ -261,90 +373,111 @@ wheels = [ [[package]] name = "charset-normalizer" -version = "3.4.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e4/33/89c2ced2b67d1c2a61c19c6751aa8902d46ce3dacb23600a283619f5a12d/charset_normalizer-3.4.2.tar.gz", hash = "sha256:5baececa9ecba31eff645232d59845c07aa030f0c81ee70184a90d35099a0e63", size = 126367, upload-time = "2025-05-02T08:34:42.01Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/95/28/9901804da60055b406e1a1c5ba7aac1276fb77f1dde635aabfc7fd84b8ab/charset_normalizer-3.4.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7c48ed483eb946e6c04ccbe02c6b4d1d48e51944b6db70f697e089c193404941", size = 201818, upload-time = "2025-05-02T08:31:46.725Z" }, - { url = "https://files.pythonhosted.org/packages/d9/9b/892a8c8af9110935e5adcbb06d9c6fe741b6bb02608c6513983048ba1a18/charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b2d318c11350e10662026ad0eb71bb51c7812fc8590825304ae0bdd4ac283acd", size = 144649, upload-time = "2025-05-02T08:31:48.889Z" }, - { url = "https://files.pythonhosted.org/packages/7b/a5/4179abd063ff6414223575e008593861d62abfc22455b5d1a44995b7c101/charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9cbfacf36cb0ec2897ce0ebc5d08ca44213af24265bd56eca54bee7923c48fd6", size = 155045, upload-time = "2025-05-02T08:31:50.757Z" }, - { url = "https://files.pythonhosted.org/packages/3b/95/bc08c7dfeddd26b4be8c8287b9bb055716f31077c8b0ea1cd09553794665/charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18dd2e350387c87dabe711b86f83c9c78af772c748904d372ade190b5c7c9d4d", size = 147356, upload-time = "2025-05-02T08:31:52.634Z" }, - { url = "https://files.pythonhosted.org/packages/a8/2d/7a5b635aa65284bf3eab7653e8b4151ab420ecbae918d3e359d1947b4d61/charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8075c35cd58273fee266c58c0c9b670947c19df5fb98e7b66710e04ad4e9ff86", size = 149471, upload-time = "2025-05-02T08:31:56.207Z" }, - { url = "https://files.pythonhosted.org/packages/ae/38/51fc6ac74251fd331a8cfdb7ec57beba8c23fd5493f1050f71c87ef77ed0/charset_normalizer-3.4.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5bf4545e3b962767e5c06fe1738f951f77d27967cb2caa64c28be7c4563e162c", size = 151317, upload-time = "2025-05-02T08:31:57.613Z" }, - { url = "https://files.pythonhosted.org/packages/b7/17/edee1e32215ee6e9e46c3e482645b46575a44a2d72c7dfd49e49f60ce6bf/charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:7a6ab32f7210554a96cd9e33abe3ddd86732beeafc7a28e9955cdf22ffadbab0", size = 146368, upload-time = "2025-05-02T08:31:59.468Z" }, - { url = "https://files.pythonhosted.org/packages/26/2c/ea3e66f2b5f21fd00b2825c94cafb8c326ea6240cd80a91eb09e4a285830/charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:b33de11b92e9f75a2b545d6e9b6f37e398d86c3e9e9653c4864eb7e89c5773ef", size = 154491, upload-time = "2025-05-02T08:32:01.219Z" }, - { url = "https://files.pythonhosted.org/packages/52/47/7be7fa972422ad062e909fd62460d45c3ef4c141805b7078dbab15904ff7/charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:8755483f3c00d6c9a77f490c17e6ab0c8729e39e6390328e42521ef175380ae6", size = 157695, upload-time = "2025-05-02T08:32:03.045Z" }, - { url = "https://files.pythonhosted.org/packages/2f/42/9f02c194da282b2b340f28e5fb60762de1151387a36842a92b533685c61e/charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:68a328e5f55ec37c57f19ebb1fdc56a248db2e3e9ad769919a58672958e8f366", size = 154849, upload-time = "2025-05-02T08:32:04.651Z" }, - { url = "https://files.pythonhosted.org/packages/67/44/89cacd6628f31fb0b63201a618049be4be2a7435a31b55b5eb1c3674547a/charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:21b2899062867b0e1fde9b724f8aecb1af14f2778d69aacd1a5a1853a597a5db", size = 150091, upload-time = "2025-05-02T08:32:06.719Z" }, - { url = "https://files.pythonhosted.org/packages/1f/79/4b8da9f712bc079c0f16b6d67b099b0b8d808c2292c937f267d816ec5ecc/charset_normalizer-3.4.2-cp310-cp310-win32.whl", hash = "sha256:e8082b26888e2f8b36a042a58307d5b917ef2b1cacab921ad3323ef91901c71a", size = 98445, upload-time = "2025-05-02T08:32:08.66Z" }, - { url = "https://files.pythonhosted.org/packages/7d/d7/96970afb4fb66497a40761cdf7bd4f6fca0fc7bafde3a84f836c1f57a926/charset_normalizer-3.4.2-cp310-cp310-win_amd64.whl", hash = "sha256:f69a27e45c43520f5487f27627059b64aaf160415589230992cec34c5e18a509", size = 105782, upload-time = "2025-05-02T08:32:10.46Z" }, - { url = "https://files.pythonhosted.org/packages/05/85/4c40d00dcc6284a1c1ad5de5e0996b06f39d8232f1031cd23c2f5c07ee86/charset_normalizer-3.4.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:be1e352acbe3c78727a16a455126d9ff83ea2dfdcbc83148d2982305a04714c2", size = 198794, upload-time = "2025-05-02T08:32:11.945Z" }, - { url = "https://files.pythonhosted.org/packages/41/d9/7a6c0b9db952598e97e93cbdfcb91bacd89b9b88c7c983250a77c008703c/charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa88ca0b1932e93f2d961bf3addbb2db902198dca337d88c89e1559e066e7645", size = 142846, upload-time = "2025-05-02T08:32:13.946Z" }, - { url = "https://files.pythonhosted.org/packages/66/82/a37989cda2ace7e37f36c1a8ed16c58cf48965a79c2142713244bf945c89/charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d524ba3f1581b35c03cb42beebab4a13e6cdad7b36246bd22541fa585a56cccd", size = 153350, upload-time = "2025-05-02T08:32:15.873Z" }, - { url = "https://files.pythonhosted.org/packages/df/68/a576b31b694d07b53807269d05ec3f6f1093e9545e8607121995ba7a8313/charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28a1005facc94196e1fb3e82a3d442a9d9110b8434fc1ded7a24a2983c9888d8", size = 145657, upload-time = "2025-05-02T08:32:17.283Z" }, - { url = "https://files.pythonhosted.org/packages/92/9b/ad67f03d74554bed3aefd56fe836e1623a50780f7c998d00ca128924a499/charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fdb20a30fe1175ecabed17cbf7812f7b804b8a315a25f24678bcdf120a90077f", size = 147260, upload-time = "2025-05-02T08:32:18.807Z" }, - { url = "https://files.pythonhosted.org/packages/a6/e6/8aebae25e328160b20e31a7e9929b1578bbdc7f42e66f46595a432f8539e/charset_normalizer-3.4.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0f5d9ed7f254402c9e7d35d2f5972c9bbea9040e99cd2861bd77dc68263277c7", size = 149164, upload-time = "2025-05-02T08:32:20.333Z" }, - { url = "https://files.pythonhosted.org/packages/8b/f2/b3c2f07dbcc248805f10e67a0262c93308cfa149a4cd3d1fe01f593e5fd2/charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:efd387a49825780ff861998cd959767800d54f8308936b21025326de4b5a42b9", size = 144571, upload-time = "2025-05-02T08:32:21.86Z" }, - { url = "https://files.pythonhosted.org/packages/60/5b/c3f3a94bc345bc211622ea59b4bed9ae63c00920e2e8f11824aa5708e8b7/charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f0aa37f3c979cf2546b73e8222bbfa3dc07a641585340179d768068e3455e544", size = 151952, upload-time = "2025-05-02T08:32:23.434Z" }, - { url = "https://files.pythonhosted.org/packages/e2/4d/ff460c8b474122334c2fa394a3f99a04cf11c646da895f81402ae54f5c42/charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:e70e990b2137b29dc5564715de1e12701815dacc1d056308e2b17e9095372a82", size = 155959, upload-time = "2025-05-02T08:32:24.993Z" }, - { url = "https://files.pythonhosted.org/packages/a2/2b/b964c6a2fda88611a1fe3d4c400d39c66a42d6c169c924818c848f922415/charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:0c8c57f84ccfc871a48a47321cfa49ae1df56cd1d965a09abe84066f6853b9c0", size = 153030, upload-time = "2025-05-02T08:32:26.435Z" }, - { url = "https://files.pythonhosted.org/packages/59/2e/d3b9811db26a5ebf444bc0fa4f4be5aa6d76fc6e1c0fd537b16c14e849b6/charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6b66f92b17849b85cad91259efc341dce9c1af48e2173bf38a85c6329f1033e5", size = 148015, upload-time = "2025-05-02T08:32:28.376Z" }, - { url = "https://files.pythonhosted.org/packages/90/07/c5fd7c11eafd561bb51220d600a788f1c8d77c5eef37ee49454cc5c35575/charset_normalizer-3.4.2-cp311-cp311-win32.whl", hash = "sha256:daac4765328a919a805fa5e2720f3e94767abd632ae410a9062dff5412bae65a", size = 98106, upload-time = "2025-05-02T08:32:30.281Z" }, - { url = "https://files.pythonhosted.org/packages/a8/05/5e33dbef7e2f773d672b6d79f10ec633d4a71cd96db6673625838a4fd532/charset_normalizer-3.4.2-cp311-cp311-win_amd64.whl", hash = "sha256:e53efc7c7cee4c1e70661e2e112ca46a575f90ed9ae3fef200f2a25e954f4b28", size = 105402, upload-time = "2025-05-02T08:32:32.191Z" }, - { url = "https://files.pythonhosted.org/packages/d7/a4/37f4d6035c89cac7930395a35cc0f1b872e652eaafb76a6075943754f095/charset_normalizer-3.4.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0c29de6a1a95f24b9a1aa7aefd27d2487263f00dfd55a77719b530788f75cff7", size = 199936, upload-time = "2025-05-02T08:32:33.712Z" }, - { url = "https://files.pythonhosted.org/packages/ee/8a/1a5e33b73e0d9287274f899d967907cd0bf9c343e651755d9307e0dbf2b3/charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cddf7bd982eaa998934a91f69d182aec997c6c468898efe6679af88283b498d3", size = 143790, upload-time = "2025-05-02T08:32:35.768Z" }, - { url = "https://files.pythonhosted.org/packages/66/52/59521f1d8e6ab1482164fa21409c5ef44da3e9f653c13ba71becdd98dec3/charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fcbe676a55d7445b22c10967bceaaf0ee69407fbe0ece4d032b6eb8d4565982a", size = 153924, upload-time = "2025-05-02T08:32:37.284Z" }, - { url = "https://files.pythonhosted.org/packages/86/2d/fb55fdf41964ec782febbf33cb64be480a6b8f16ded2dbe8db27a405c09f/charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d41c4d287cfc69060fa91cae9683eacffad989f1a10811995fa309df656ec214", size = 146626, upload-time = "2025-05-02T08:32:38.803Z" }, - { url = "https://files.pythonhosted.org/packages/8c/73/6ede2ec59bce19b3edf4209d70004253ec5f4e319f9a2e3f2f15601ed5f7/charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e594135de17ab3866138f496755f302b72157d115086d100c3f19370839dd3a", size = 148567, upload-time = "2025-05-02T08:32:40.251Z" }, - { url = "https://files.pythonhosted.org/packages/09/14/957d03c6dc343c04904530b6bef4e5efae5ec7d7990a7cbb868e4595ee30/charset_normalizer-3.4.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cf713fe9a71ef6fd5adf7a79670135081cd4431c2943864757f0fa3a65b1fafd", size = 150957, upload-time = "2025-05-02T08:32:41.705Z" }, - { url = "https://files.pythonhosted.org/packages/0d/c8/8174d0e5c10ccebdcb1b53cc959591c4c722a3ad92461a273e86b9f5a302/charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a370b3e078e418187da8c3674eddb9d983ec09445c99a3a263c2011993522981", size = 145408, upload-time = "2025-05-02T08:32:43.709Z" }, - { url = "https://files.pythonhosted.org/packages/58/aa/8904b84bc8084ac19dc52feb4f5952c6df03ffb460a887b42615ee1382e8/charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a955b438e62efdf7e0b7b52a64dc5c3396e2634baa62471768a64bc2adb73d5c", size = 153399, upload-time = "2025-05-02T08:32:46.197Z" }, - { url = "https://files.pythonhosted.org/packages/c2/26/89ee1f0e264d201cb65cf054aca6038c03b1a0c6b4ae998070392a3ce605/charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:7222ffd5e4de8e57e03ce2cef95a4c43c98fcb72ad86909abdfc2c17d227fc1b", size = 156815, upload-time = "2025-05-02T08:32:48.105Z" }, - { url = "https://files.pythonhosted.org/packages/fd/07/68e95b4b345bad3dbbd3a8681737b4338ff2c9df29856a6d6d23ac4c73cb/charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:bee093bf902e1d8fc0ac143c88902c3dfc8941f7ea1d6a8dd2bcb786d33db03d", size = 154537, upload-time = "2025-05-02T08:32:49.719Z" }, - { url = "https://files.pythonhosted.org/packages/77/1a/5eefc0ce04affb98af07bc05f3bac9094513c0e23b0562d64af46a06aae4/charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:dedb8adb91d11846ee08bec4c8236c8549ac721c245678282dcb06b221aab59f", size = 149565, upload-time = "2025-05-02T08:32:51.404Z" }, - { url = "https://files.pythonhosted.org/packages/37/a0/2410e5e6032a174c95e0806b1a6585eb21e12f445ebe239fac441995226a/charset_normalizer-3.4.2-cp312-cp312-win32.whl", hash = "sha256:db4c7bf0e07fc3b7d89ac2a5880a6a8062056801b83ff56d8464b70f65482b6c", size = 98357, upload-time = "2025-05-02T08:32:53.079Z" }, - { url = "https://files.pythonhosted.org/packages/6c/4f/c02d5c493967af3eda9c771ad4d2bbc8df6f99ddbeb37ceea6e8716a32bc/charset_normalizer-3.4.2-cp312-cp312-win_amd64.whl", hash = "sha256:5a9979887252a82fefd3d3ed2a8e3b937a7a809f65dcb1e068b090e165bbe99e", size = 105776, upload-time = "2025-05-02T08:32:54.573Z" }, - { url = "https://files.pythonhosted.org/packages/ea/12/a93df3366ed32db1d907d7593a94f1fe6293903e3e92967bebd6950ed12c/charset_normalizer-3.4.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:926ca93accd5d36ccdabd803392ddc3e03e6d4cd1cf17deff3b989ab8e9dbcf0", size = 199622, upload-time = "2025-05-02T08:32:56.363Z" }, - { url = "https://files.pythonhosted.org/packages/04/93/bf204e6f344c39d9937d3c13c8cd5bbfc266472e51fc8c07cb7f64fcd2de/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eba9904b0f38a143592d9fc0e19e2df0fa2e41c3c3745554761c5f6447eedabf", size = 143435, upload-time = "2025-05-02T08:32:58.551Z" }, - { url = "https://files.pythonhosted.org/packages/22/2a/ea8a2095b0bafa6c5b5a55ffdc2f924455233ee7b91c69b7edfcc9e02284/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3fddb7e2c84ac87ac3a947cb4e66d143ca5863ef48e4a5ecb83bd48619e4634e", size = 153653, upload-time = "2025-05-02T08:33:00.342Z" }, - { url = "https://files.pythonhosted.org/packages/b6/57/1b090ff183d13cef485dfbe272e2fe57622a76694061353c59da52c9a659/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98f862da73774290f251b9df8d11161b6cf25b599a66baf087c1ffe340e9bfd1", size = 146231, upload-time = "2025-05-02T08:33:02.081Z" }, - { url = "https://files.pythonhosted.org/packages/e2/28/ffc026b26f441fc67bd21ab7f03b313ab3fe46714a14b516f931abe1a2d8/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c9379d65defcab82d07b2a9dfbfc2e95bc8fe0ebb1b176a3190230a3ef0e07c", size = 148243, upload-time = "2025-05-02T08:33:04.063Z" }, - { url = "https://files.pythonhosted.org/packages/c0/0f/9abe9bd191629c33e69e47c6ef45ef99773320e9ad8e9cb08b8ab4a8d4cb/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e635b87f01ebc977342e2697d05b56632f5f879a4f15955dfe8cef2448b51691", size = 150442, upload-time = "2025-05-02T08:33:06.418Z" }, - { url = "https://files.pythonhosted.org/packages/67/7c/a123bbcedca91d5916c056407f89a7f5e8fdfce12ba825d7d6b9954a1a3c/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:1c95a1e2902a8b722868587c0e1184ad5c55631de5afc0eb96bc4b0d738092c0", size = 145147, upload-time = "2025-05-02T08:33:08.183Z" }, - { url = "https://files.pythonhosted.org/packages/ec/fe/1ac556fa4899d967b83e9893788e86b6af4d83e4726511eaaad035e36595/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ef8de666d6179b009dce7bcb2ad4c4a779f113f12caf8dc77f0162c29d20490b", size = 153057, upload-time = "2025-05-02T08:33:09.986Z" }, - { url = "https://files.pythonhosted.org/packages/2b/ff/acfc0b0a70b19e3e54febdd5301a98b72fa07635e56f24f60502e954c461/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:32fc0341d72e0f73f80acb0a2c94216bd704f4f0bce10aedea38f30502b271ff", size = 156454, upload-time = "2025-05-02T08:33:11.814Z" }, - { url = "https://files.pythonhosted.org/packages/92/08/95b458ce9c740d0645feb0e96cea1f5ec946ea9c580a94adfe0b617f3573/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:289200a18fa698949d2b39c671c2cc7a24d44096784e76614899a7ccf2574b7b", size = 154174, upload-time = "2025-05-02T08:33:13.707Z" }, - { url = "https://files.pythonhosted.org/packages/78/be/8392efc43487ac051eee6c36d5fbd63032d78f7728cb37aebcc98191f1ff/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4a476b06fbcf359ad25d34a057b7219281286ae2477cc5ff5e3f70a246971148", size = 149166, upload-time = "2025-05-02T08:33:15.458Z" }, - { url = "https://files.pythonhosted.org/packages/44/96/392abd49b094d30b91d9fbda6a69519e95802250b777841cf3bda8fe136c/charset_normalizer-3.4.2-cp313-cp313-win32.whl", hash = "sha256:aaeeb6a479c7667fbe1099af9617c83aaca22182d6cf8c53966491a0f1b7ffb7", size = 98064, upload-time = "2025-05-02T08:33:17.06Z" }, - { url = "https://files.pythonhosted.org/packages/e9/b0/0200da600134e001d91851ddc797809e2fe0ea72de90e09bec5a2fbdaccb/charset_normalizer-3.4.2-cp313-cp313-win_amd64.whl", hash = "sha256:aa6af9e7d59f9c12b33ae4e9450619cf2488e2bbe9b44030905877f0b2324980", size = 105641, upload-time = "2025-05-02T08:33:18.753Z" }, - { url = "https://files.pythonhosted.org/packages/28/f8/dfb01ff6cc9af38552c69c9027501ff5a5117c4cc18dcd27cb5259fa1888/charset_normalizer-3.4.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:005fa3432484527f9732ebd315da8da8001593e2cf46a3d817669f062c3d9ed4", size = 201671, upload-time = "2025-05-02T08:34:12.696Z" }, - { url = "https://files.pythonhosted.org/packages/32/fb/74e26ee556a9dbfe3bd264289b67be1e6d616329403036f6507bb9f3f29c/charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e92fca20c46e9f5e1bb485887d074918b13543b1c2a1185e69bb8d17ab6236a7", size = 144744, upload-time = "2025-05-02T08:34:14.665Z" }, - { url = "https://files.pythonhosted.org/packages/ad/06/8499ee5aa7addc6f6d72e068691826ff093329fe59891e83b092ae4c851c/charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:50bf98d5e563b83cc29471fa114366e6806bc06bc7a25fd59641e41445327836", size = 154993, upload-time = "2025-05-02T08:34:17.134Z" }, - { url = "https://files.pythonhosted.org/packages/f1/a2/5e4c187680728219254ef107a6949c60ee0e9a916a5dadb148c7ae82459c/charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:721c76e84fe669be19c5791da68232ca2e05ba5185575086e384352e2c309597", size = 147382, upload-time = "2025-05-02T08:34:19.081Z" }, - { url = "https://files.pythonhosted.org/packages/4c/fe/56aca740dda674f0cc1ba1418c4d84534be51f639b5f98f538b332dc9a95/charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82d8fd25b7f4675d0c47cf95b594d4e7b158aca33b76aa63d07186e13c0e0ab7", size = 149536, upload-time = "2025-05-02T08:34:21.073Z" }, - { url = "https://files.pythonhosted.org/packages/53/13/db2e7779f892386b589173dd689c1b1e304621c5792046edd8a978cbf9e0/charset_normalizer-3.4.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b3daeac64d5b371dea99714f08ffc2c208522ec6b06fbc7866a450dd446f5c0f", size = 151349, upload-time = "2025-05-02T08:34:23.193Z" }, - { url = "https://files.pythonhosted.org/packages/69/35/e52ab9a276186f729bce7a0638585d2982f50402046e4b0faa5d2c3ef2da/charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:dccab8d5fa1ef9bfba0590ecf4d46df048d18ffe3eec01eeb73a42e0d9e7a8ba", size = 146365, upload-time = "2025-05-02T08:34:25.187Z" }, - { url = "https://files.pythonhosted.org/packages/a6/d8/af7333f732fc2e7635867d56cb7c349c28c7094910c72267586947561b4b/charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:aaf27faa992bfee0264dc1f03f4c75e9fcdda66a519db6b957a3f826e285cf12", size = 154499, upload-time = "2025-05-02T08:34:27.359Z" }, - { url = "https://files.pythonhosted.org/packages/7a/3d/a5b2e48acef264d71e036ff30bcc49e51bde80219bb628ba3e00cf59baac/charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:eb30abc20df9ab0814b5a2524f23d75dcf83cde762c161917a2b4b7b55b1e518", size = 157735, upload-time = "2025-05-02T08:34:29.798Z" }, - { url = "https://files.pythonhosted.org/packages/85/d8/23e2c112532a29f3eef374375a8684a4f3b8e784f62b01da931186f43494/charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:c72fbbe68c6f32f251bdc08b8611c7b3060612236e960ef848e0a517ddbe76c5", size = 154786, upload-time = "2025-05-02T08:34:31.858Z" }, - { url = "https://files.pythonhosted.org/packages/c7/57/93e0169f08ecc20fe82d12254a200dfaceddc1c12a4077bf454ecc597e33/charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:982bb1e8b4ffda883b3d0a521e23abcd6fd17418f6d2c4118d257a10199c0ce3", size = 150203, upload-time = "2025-05-02T08:34:33.88Z" }, - { url = "https://files.pythonhosted.org/packages/2c/9d/9bf2b005138e7e060d7ebdec7503d0ef3240141587651f4b445bdf7286c2/charset_normalizer-3.4.2-cp39-cp39-win32.whl", hash = "sha256:43e0933a0eff183ee85833f341ec567c0980dae57c464d8a508e1b2ceb336471", size = 98436, upload-time = "2025-05-02T08:34:35.907Z" }, - { url = "https://files.pythonhosted.org/packages/6d/24/5849d46cf4311bbf21b424c443b09b459f5b436b1558c04e45dbb7cc478b/charset_normalizer-3.4.2-cp39-cp39-win_amd64.whl", hash = "sha256:d11b54acf878eef558599658b0ffca78138c8c3655cf4f3a4a673c437e67732e", size = 105772, upload-time = "2025-05-02T08:34:37.935Z" }, - { url = "https://files.pythonhosted.org/packages/20/94/c5790835a017658cbfabd07f3bfb549140c3ac458cfc196323996b10095a/charset_normalizer-3.4.2-py3-none-any.whl", hash = "sha256:7f56930ab0abd1c45cd15be65cc741c28b1c9a34876ce8c17a2fa107810c0af0", size = 52626, upload-time = "2025-05-02T08:34:40.053Z" }, +version = "3.4.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/83/2d/5fd176ceb9b2fc619e63405525573493ca23441330fcdaee6bef9460e924/charset_normalizer-3.4.3.tar.gz", hash = "sha256:6fce4b8500244f6fcb71465d4a4930d132ba9ab8e71a7859e6a5d59851068d14", size = 122371, upload-time = "2025-08-09T07:57:28.46Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d6/98/f3b8013223728a99b908c9344da3aa04ee6e3fa235f19409033eda92fb78/charset_normalizer-3.4.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:fb7f67a1bfa6e40b438170ebdc8158b78dc465a5a67b6dde178a46987b244a72", size = 207695, upload-time = "2025-08-09T07:55:36.452Z" }, + { url = "https://files.pythonhosted.org/packages/21/40/5188be1e3118c82dcb7c2a5ba101b783822cfb413a0268ed3be0468532de/charset_normalizer-3.4.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cc9370a2da1ac13f0153780040f465839e6cccb4a1e44810124b4e22483c93fe", size = 147153, upload-time = "2025-08-09T07:55:38.467Z" }, + { url = "https://files.pythonhosted.org/packages/37/60/5d0d74bc1e1380f0b72c327948d9c2aca14b46a9efd87604e724260f384c/charset_normalizer-3.4.3-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:07a0eae9e2787b586e129fdcbe1af6997f8d0e5abaa0bc98c0e20e124d67e601", size = 160428, upload-time = "2025-08-09T07:55:40.072Z" }, + { url = "https://files.pythonhosted.org/packages/85/9a/d891f63722d9158688de58d050c59dc3da560ea7f04f4c53e769de5140f5/charset_normalizer-3.4.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:74d77e25adda8581ffc1c720f1c81ca082921329452eba58b16233ab1842141c", size = 157627, upload-time = "2025-08-09T07:55:41.706Z" }, + { url = "https://files.pythonhosted.org/packages/65/1a/7425c952944a6521a9cfa7e675343f83fd82085b8af2b1373a2409c683dc/charset_normalizer-3.4.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d0e909868420b7049dafd3a31d45125b31143eec59235311fc4c57ea26a4acd2", size = 152388, upload-time = "2025-08-09T07:55:43.262Z" }, + { url = "https://files.pythonhosted.org/packages/f0/c9/a2c9c2a355a8594ce2446085e2ec97fd44d323c684ff32042e2a6b718e1d/charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c6f162aabe9a91a309510d74eeb6507fab5fff92337a15acbe77753d88d9dcf0", size = 150077, upload-time = "2025-08-09T07:55:44.903Z" }, + { url = "https://files.pythonhosted.org/packages/3b/38/20a1f44e4851aa1c9105d6e7110c9d020e093dfa5836d712a5f074a12bf7/charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:4ca4c094de7771a98d7fbd67d9e5dbf1eb73efa4f744a730437d8a3a5cf994f0", size = 161631, upload-time = "2025-08-09T07:55:46.346Z" }, + { url = "https://files.pythonhosted.org/packages/a4/fa/384d2c0f57edad03d7bec3ebefb462090d8905b4ff5a2d2525f3bb711fac/charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:02425242e96bcf29a49711b0ca9f37e451da7c70562bc10e8ed992a5a7a25cc0", size = 159210, upload-time = "2025-08-09T07:55:47.539Z" }, + { url = "https://files.pythonhosted.org/packages/33/9e/eca49d35867ca2db336b6ca27617deed4653b97ebf45dfc21311ce473c37/charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:78deba4d8f9590fe4dae384aeff04082510a709957e968753ff3c48399f6f92a", size = 153739, upload-time = "2025-08-09T07:55:48.744Z" }, + { url = "https://files.pythonhosted.org/packages/2a/91/26c3036e62dfe8de8061182d33be5025e2424002125c9500faff74a6735e/charset_normalizer-3.4.3-cp310-cp310-win32.whl", hash = "sha256:d79c198e27580c8e958906f803e63cddb77653731be08851c7df0b1a14a8fc0f", size = 99825, upload-time = "2025-08-09T07:55:50.305Z" }, + { url = "https://files.pythonhosted.org/packages/e2/c6/f05db471f81af1fa01839d44ae2a8bfeec8d2a8b4590f16c4e7393afd323/charset_normalizer-3.4.3-cp310-cp310-win_amd64.whl", hash = "sha256:c6e490913a46fa054e03699c70019ab869e990270597018cef1d8562132c2669", size = 107452, upload-time = "2025-08-09T07:55:51.461Z" }, + { url = "https://files.pythonhosted.org/packages/7f/b5/991245018615474a60965a7c9cd2b4efbaabd16d582a5547c47ee1c7730b/charset_normalizer-3.4.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:b256ee2e749283ef3ddcff51a675ff43798d92d746d1a6e4631bf8c707d22d0b", size = 204483, upload-time = "2025-08-09T07:55:53.12Z" }, + { url = "https://files.pythonhosted.org/packages/c7/2a/ae245c41c06299ec18262825c1569c5d3298fc920e4ddf56ab011b417efd/charset_normalizer-3.4.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:13faeacfe61784e2559e690fc53fa4c5ae97c6fcedb8eb6fb8d0a15b475d2c64", size = 145520, upload-time = "2025-08-09T07:55:54.712Z" }, + { url = "https://files.pythonhosted.org/packages/3a/a4/b3b6c76e7a635748c4421d2b92c7b8f90a432f98bda5082049af37ffc8e3/charset_normalizer-3.4.3-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:00237675befef519d9af72169d8604a067d92755e84fe76492fef5441db05b91", size = 158876, upload-time = "2025-08-09T07:55:56.024Z" }, + { url = "https://files.pythonhosted.org/packages/e2/e6/63bb0e10f90a8243c5def74b5b105b3bbbfb3e7bb753915fe333fb0c11ea/charset_normalizer-3.4.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:585f3b2a80fbd26b048a0be90c5aae8f06605d3c92615911c3a2b03a8a3b796f", size = 156083, upload-time = "2025-08-09T07:55:57.582Z" }, + { url = "https://files.pythonhosted.org/packages/87/df/b7737ff046c974b183ea9aa111b74185ac8c3a326c6262d413bd5a1b8c69/charset_normalizer-3.4.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0e78314bdc32fa80696f72fa16dc61168fda4d6a0c014e0380f9d02f0e5d8a07", size = 150295, upload-time = "2025-08-09T07:55:59.147Z" }, + { url = "https://files.pythonhosted.org/packages/61/f1/190d9977e0084d3f1dc169acd060d479bbbc71b90bf3e7bf7b9927dec3eb/charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:96b2b3d1a83ad55310de8c7b4a2d04d9277d5591f40761274856635acc5fcb30", size = 148379, upload-time = "2025-08-09T07:56:00.364Z" }, + { url = "https://files.pythonhosted.org/packages/4c/92/27dbe365d34c68cfe0ca76f1edd70e8705d82b378cb54ebbaeabc2e3029d/charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:939578d9d8fd4299220161fdd76e86c6a251987476f5243e8864a7844476ba14", size = 160018, upload-time = "2025-08-09T07:56:01.678Z" }, + { url = "https://files.pythonhosted.org/packages/99/04/baae2a1ea1893a01635d475b9261c889a18fd48393634b6270827869fa34/charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:fd10de089bcdcd1be95a2f73dbe6254798ec1bda9f450d5828c96f93e2536b9c", size = 157430, upload-time = "2025-08-09T07:56:02.87Z" }, + { url = "https://files.pythonhosted.org/packages/2f/36/77da9c6a328c54d17b960c89eccacfab8271fdaaa228305330915b88afa9/charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1e8ac75d72fa3775e0b7cb7e4629cec13b7514d928d15ef8ea06bca03ef01cae", size = 151600, upload-time = "2025-08-09T07:56:04.089Z" }, + { url = "https://files.pythonhosted.org/packages/64/d4/9eb4ff2c167edbbf08cdd28e19078bf195762e9bd63371689cab5ecd3d0d/charset_normalizer-3.4.3-cp311-cp311-win32.whl", hash = "sha256:6cf8fd4c04756b6b60146d98cd8a77d0cdae0e1ca20329da2ac85eed779b6849", size = 99616, upload-time = "2025-08-09T07:56:05.658Z" }, + { url = "https://files.pythonhosted.org/packages/f4/9c/996a4a028222e7761a96634d1820de8a744ff4327a00ada9c8942033089b/charset_normalizer-3.4.3-cp311-cp311-win_amd64.whl", hash = "sha256:31a9a6f775f9bcd865d88ee350f0ffb0e25936a7f930ca98995c05abf1faf21c", size = 107108, upload-time = "2025-08-09T07:56:07.176Z" }, + { url = "https://files.pythonhosted.org/packages/e9/5e/14c94999e418d9b87682734589404a25854d5f5d0408df68bc15b6ff54bb/charset_normalizer-3.4.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e28e334d3ff134e88989d90ba04b47d84382a828c061d0d1027b1b12a62b39b1", size = 205655, upload-time = "2025-08-09T07:56:08.475Z" }, + { url = "https://files.pythonhosted.org/packages/7d/a8/c6ec5d389672521f644505a257f50544c074cf5fc292d5390331cd6fc9c3/charset_normalizer-3.4.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0cacf8f7297b0c4fcb74227692ca46b4a5852f8f4f24b3c766dd94a1075c4884", size = 146223, upload-time = "2025-08-09T07:56:09.708Z" }, + { url = "https://files.pythonhosted.org/packages/fc/eb/a2ffb08547f4e1e5415fb69eb7db25932c52a52bed371429648db4d84fb1/charset_normalizer-3.4.3-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c6fd51128a41297f5409deab284fecbe5305ebd7e5a1f959bee1c054622b7018", size = 159366, upload-time = "2025-08-09T07:56:11.326Z" }, + { url = "https://files.pythonhosted.org/packages/82/10/0fd19f20c624b278dddaf83b8464dcddc2456cb4b02bb902a6da126b87a1/charset_normalizer-3.4.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3cfb2aad70f2c6debfbcb717f23b7eb55febc0bb23dcffc0f076009da10c6392", size = 157104, upload-time = "2025-08-09T07:56:13.014Z" }, + { url = "https://files.pythonhosted.org/packages/16/ab/0233c3231af734f5dfcf0844aa9582d5a1466c985bbed6cedab85af9bfe3/charset_normalizer-3.4.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1606f4a55c0fd363d754049cdf400175ee96c992b1f8018b993941f221221c5f", size = 151830, upload-time = "2025-08-09T07:56:14.428Z" }, + { url = "https://files.pythonhosted.org/packages/ae/02/e29e22b4e02839a0e4a06557b1999d0a47db3567e82989b5bb21f3fbbd9f/charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:027b776c26d38b7f15b26a5da1044f376455fb3766df8fc38563b4efbc515154", size = 148854, upload-time = "2025-08-09T07:56:16.051Z" }, + { url = "https://files.pythonhosted.org/packages/05/6b/e2539a0a4be302b481e8cafb5af8792da8093b486885a1ae4d15d452bcec/charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:42e5088973e56e31e4fa58eb6bd709e42fc03799c11c42929592889a2e54c491", size = 160670, upload-time = "2025-08-09T07:56:17.314Z" }, + { url = "https://files.pythonhosted.org/packages/31/e7/883ee5676a2ef217a40ce0bffcc3d0dfbf9e64cbcfbdf822c52981c3304b/charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:cc34f233c9e71701040d772aa7490318673aa7164a0efe3172b2981218c26d93", size = 158501, upload-time = "2025-08-09T07:56:18.641Z" }, + { url = "https://files.pythonhosted.org/packages/c1/35/6525b21aa0db614cf8b5792d232021dca3df7f90a1944db934efa5d20bb1/charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:320e8e66157cc4e247d9ddca8e21f427efc7a04bbd0ac8a9faf56583fa543f9f", size = 153173, upload-time = "2025-08-09T07:56:20.289Z" }, + { url = "https://files.pythonhosted.org/packages/50/ee/f4704bad8201de513fdc8aac1cabc87e38c5818c93857140e06e772b5892/charset_normalizer-3.4.3-cp312-cp312-win32.whl", hash = "sha256:fb6fecfd65564f208cbf0fba07f107fb661bcd1a7c389edbced3f7a493f70e37", size = 99822, upload-time = "2025-08-09T07:56:21.551Z" }, + { url = "https://files.pythonhosted.org/packages/39/f5/3b3836ca6064d0992c58c7561c6b6eee1b3892e9665d650c803bd5614522/charset_normalizer-3.4.3-cp312-cp312-win_amd64.whl", hash = "sha256:86df271bf921c2ee3818f0522e9a5b8092ca2ad8b065ece5d7d9d0e9f4849bcc", size = 107543, upload-time = "2025-08-09T07:56:23.115Z" }, + { url = "https://files.pythonhosted.org/packages/65/ca/2135ac97709b400c7654b4b764daf5c5567c2da45a30cdd20f9eefe2d658/charset_normalizer-3.4.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:14c2a87c65b351109f6abfc424cab3927b3bdece6f706e4d12faaf3d52ee5efe", size = 205326, upload-time = "2025-08-09T07:56:24.721Z" }, + { url = "https://files.pythonhosted.org/packages/71/11/98a04c3c97dd34e49c7d247083af03645ca3730809a5509443f3c37f7c99/charset_normalizer-3.4.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:41d1fc408ff5fdfb910200ec0e74abc40387bccb3252f3f27c0676731df2b2c8", size = 146008, upload-time = "2025-08-09T07:56:26.004Z" }, + { url = "https://files.pythonhosted.org/packages/60/f5/4659a4cb3c4ec146bec80c32d8bb16033752574c20b1252ee842a95d1a1e/charset_normalizer-3.4.3-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1bb60174149316da1c35fa5233681f7c0f9f514509b8e399ab70fea5f17e45c9", size = 159196, upload-time = "2025-08-09T07:56:27.25Z" }, + { url = "https://files.pythonhosted.org/packages/86/9e/f552f7a00611f168b9a5865a1414179b2c6de8235a4fa40189f6f79a1753/charset_normalizer-3.4.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:30d006f98569de3459c2fc1f2acde170b7b2bd265dc1943e87e1a4efe1b67c31", size = 156819, upload-time = "2025-08-09T07:56:28.515Z" }, + { url = "https://files.pythonhosted.org/packages/7e/95/42aa2156235cbc8fa61208aded06ef46111c4d3f0de233107b3f38631803/charset_normalizer-3.4.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:416175faf02e4b0810f1f38bcb54682878a4af94059a1cd63b8747244420801f", size = 151350, upload-time = "2025-08-09T07:56:29.716Z" }, + { url = "https://files.pythonhosted.org/packages/c2/a9/3865b02c56f300a6f94fc631ef54f0a8a29da74fb45a773dfd3dcd380af7/charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6aab0f181c486f973bc7262a97f5aca3ee7e1437011ef0c2ec04b5a11d16c927", size = 148644, upload-time = "2025-08-09T07:56:30.984Z" }, + { url = "https://files.pythonhosted.org/packages/77/d9/cbcf1a2a5c7d7856f11e7ac2d782aec12bdfea60d104e60e0aa1c97849dc/charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:fdabf8315679312cfa71302f9bd509ded4f2f263fb5b765cf1433b39106c3cc9", size = 160468, upload-time = "2025-08-09T07:56:32.252Z" }, + { url = "https://files.pythonhosted.org/packages/f6/42/6f45efee8697b89fda4d50580f292b8f7f9306cb2971d4b53f8914e4d890/charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:bd28b817ea8c70215401f657edef3a8aa83c29d447fb0b622c35403780ba11d5", size = 158187, upload-time = "2025-08-09T07:56:33.481Z" }, + { url = "https://files.pythonhosted.org/packages/70/99/f1c3bdcfaa9c45b3ce96f70b14f070411366fa19549c1d4832c935d8e2c3/charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:18343b2d246dc6761a249ba1fb13f9ee9a2bcd95decc767319506056ea4ad4dc", size = 152699, upload-time = "2025-08-09T07:56:34.739Z" }, + { url = "https://files.pythonhosted.org/packages/a3/ad/b0081f2f99a4b194bcbb1934ef3b12aa4d9702ced80a37026b7607c72e58/charset_normalizer-3.4.3-cp313-cp313-win32.whl", hash = "sha256:6fb70de56f1859a3f71261cbe41005f56a7842cc348d3aeb26237560bfa5e0ce", size = 99580, upload-time = "2025-08-09T07:56:35.981Z" }, + { url = "https://files.pythonhosted.org/packages/9a/8f/ae790790c7b64f925e5c953b924aaa42a243fb778fed9e41f147b2a5715a/charset_normalizer-3.4.3-cp313-cp313-win_amd64.whl", hash = "sha256:cf1ebb7d78e1ad8ec2a8c4732c7be2e736f6e5123a4146c5b89c9d1f585f8cef", size = 107366, upload-time = "2025-08-09T07:56:37.339Z" }, + { url = "https://files.pythonhosted.org/packages/8e/91/b5a06ad970ddc7a0e513112d40113e834638f4ca1120eb727a249fb2715e/charset_normalizer-3.4.3-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:3cd35b7e8aedeb9e34c41385fda4f73ba609e561faedfae0a9e75e44ac558a15", size = 204342, upload-time = "2025-08-09T07:56:38.687Z" }, + { url = "https://files.pythonhosted.org/packages/ce/ec/1edc30a377f0a02689342f214455c3f6c2fbedd896a1d2f856c002fc3062/charset_normalizer-3.4.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b89bc04de1d83006373429975f8ef9e7932534b8cc9ca582e4db7d20d91816db", size = 145995, upload-time = "2025-08-09T07:56:40.048Z" }, + { url = "https://files.pythonhosted.org/packages/17/e5/5e67ab85e6d22b04641acb5399c8684f4d37caf7558a53859f0283a650e9/charset_normalizer-3.4.3-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2001a39612b241dae17b4687898843f254f8748b796a2e16f1051a17078d991d", size = 158640, upload-time = "2025-08-09T07:56:41.311Z" }, + { url = "https://files.pythonhosted.org/packages/f1/e5/38421987f6c697ee3722981289d554957c4be652f963d71c5e46a262e135/charset_normalizer-3.4.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8dcfc373f888e4fb39a7bc57e93e3b845e7f462dacc008d9749568b1c4ece096", size = 156636, upload-time = "2025-08-09T07:56:43.195Z" }, + { url = "https://files.pythonhosted.org/packages/a0/e4/5a075de8daa3ec0745a9a3b54467e0c2967daaaf2cec04c845f73493e9a1/charset_normalizer-3.4.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:18b97b8404387b96cdbd30ad660f6407799126d26a39ca65729162fd810a99aa", size = 150939, upload-time = "2025-08-09T07:56:44.819Z" }, + { url = "https://files.pythonhosted.org/packages/02/f7/3611b32318b30974131db62b4043f335861d4d9b49adc6d57c1149cc49d4/charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ccf600859c183d70eb47e05a44cd80a4ce77394d1ac0f79dbd2dd90a69a3a049", size = 148580, upload-time = "2025-08-09T07:56:46.684Z" }, + { url = "https://files.pythonhosted.org/packages/7e/61/19b36f4bd67f2793ab6a99b979b4e4f3d8fc754cbdffb805335df4337126/charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:53cd68b185d98dde4ad8990e56a58dea83a4162161b1ea9272e5c9182ce415e0", size = 159870, upload-time = "2025-08-09T07:56:47.941Z" }, + { url = "https://files.pythonhosted.org/packages/06/57/84722eefdd338c04cf3030ada66889298eaedf3e7a30a624201e0cbe424a/charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:30a96e1e1f865f78b030d65241c1ee850cdf422d869e9028e2fc1d5e4db73b92", size = 157797, upload-time = "2025-08-09T07:56:49.756Z" }, + { url = "https://files.pythonhosted.org/packages/72/2a/aff5dd112b2f14bcc3462c312dce5445806bfc8ab3a7328555da95330e4b/charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d716a916938e03231e86e43782ca7878fb602a125a91e7acb8b5112e2e96ac16", size = 152224, upload-time = "2025-08-09T07:56:51.369Z" }, + { url = "https://files.pythonhosted.org/packages/b7/8c/9839225320046ed279c6e839d51f028342eb77c91c89b8ef2549f951f3ec/charset_normalizer-3.4.3-cp314-cp314-win32.whl", hash = "sha256:c6dbd0ccdda3a2ba7c2ecd9d77b37f3b5831687d8dc1b6ca5f56a4880cc7b7ce", size = 100086, upload-time = "2025-08-09T07:56:52.722Z" }, + { url = "https://files.pythonhosted.org/packages/ee/7a/36fbcf646e41f710ce0a563c1c9a343c6edf9be80786edeb15b6f62e17db/charset_normalizer-3.4.3-cp314-cp314-win_amd64.whl", hash = "sha256:73dc19b562516fc9bcf6e5d6e596df0b4eb98d87e4f79f3ae71840e6ed21361c", size = 107400, upload-time = "2025-08-09T07:56:55.172Z" }, + { url = "https://files.pythonhosted.org/packages/c2/ca/9a0983dd5c8e9733565cf3db4df2b0a2e9a82659fd8aa2a868ac6e4a991f/charset_normalizer-3.4.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:70bfc5f2c318afece2f5838ea5e4c3febada0be750fcf4775641052bbba14d05", size = 207520, upload-time = "2025-08-09T07:57:11.026Z" }, + { url = "https://files.pythonhosted.org/packages/39/c6/99271dc37243a4f925b09090493fb96c9333d7992c6187f5cfe5312008d2/charset_normalizer-3.4.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:23b6b24d74478dc833444cbd927c338349d6ae852ba53a0d02a2de1fce45b96e", size = 147307, upload-time = "2025-08-09T07:57:12.4Z" }, + { url = "https://files.pythonhosted.org/packages/e4/69/132eab043356bba06eb333cc2cc60c6340857d0a2e4ca6dc2b51312886b3/charset_normalizer-3.4.3-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:34a7f768e3f985abdb42841e20e17b330ad3aaf4bb7e7aeeb73db2e70f077b99", size = 160448, upload-time = "2025-08-09T07:57:13.712Z" }, + { url = "https://files.pythonhosted.org/packages/04/9a/914d294daa4809c57667b77470533e65def9c0be1ef8b4c1183a99170e9d/charset_normalizer-3.4.3-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:fb731e5deb0c7ef82d698b0f4c5bb724633ee2a489401594c5c88b02e6cb15f7", size = 157758, upload-time = "2025-08-09T07:57:14.979Z" }, + { url = "https://files.pythonhosted.org/packages/b0/a8/6f5bcf1bcf63cb45625f7c5cadca026121ff8a6c8a3256d8d8cd59302663/charset_normalizer-3.4.3-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:257f26fed7d7ff59921b78244f3cd93ed2af1800ff048c33f624c87475819dd7", size = 152487, upload-time = "2025-08-09T07:57:16.332Z" }, + { url = "https://files.pythonhosted.org/packages/c4/72/d3d0e9592f4e504f9dea08b8db270821c909558c353dc3b457ed2509f2fb/charset_normalizer-3.4.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1ef99f0456d3d46a50945c98de1774da86f8e992ab5c77865ea8b8195341fc19", size = 150054, upload-time = "2025-08-09T07:57:17.576Z" }, + { url = "https://files.pythonhosted.org/packages/20/30/5f64fe3981677fe63fa987b80e6c01042eb5ff653ff7cec1b7bd9268e54e/charset_normalizer-3.4.3-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:2c322db9c8c89009a990ef07c3bcc9f011a3269bc06782f916cd3d9eed7c9312", size = 161703, upload-time = "2025-08-09T07:57:20.012Z" }, + { url = "https://files.pythonhosted.org/packages/e1/ef/dd08b2cac9284fd59e70f7d97382c33a3d0a926e45b15fc21b3308324ffd/charset_normalizer-3.4.3-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:511729f456829ef86ac41ca78c63a5cb55240ed23b4b737faca0eb1abb1c41bc", size = 159096, upload-time = "2025-08-09T07:57:21.329Z" }, + { url = "https://files.pythonhosted.org/packages/45/8c/dcef87cfc2b3f002a6478f38906f9040302c68aebe21468090e39cde1445/charset_normalizer-3.4.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:88ab34806dea0671532d3f82d82b85e8fc23d7b2dd12fa837978dad9bb392a34", size = 153852, upload-time = "2025-08-09T07:57:22.608Z" }, + { url = "https://files.pythonhosted.org/packages/63/86/9cbd533bd37883d467fcd1bd491b3547a3532d0fbb46de2b99feeebf185e/charset_normalizer-3.4.3-cp39-cp39-win32.whl", hash = "sha256:16a8770207946ac75703458e2c743631c79c59c5890c80011d536248f8eaa432", size = 99840, upload-time = "2025-08-09T07:57:23.883Z" }, + { url = "https://files.pythonhosted.org/packages/ce/d6/7e805c8e5c46ff9729c49950acc4ee0aeb55efb8b3a56687658ad10c3216/charset_normalizer-3.4.3-cp39-cp39-win_amd64.whl", hash = "sha256:d22dbedd33326a4a5190dd4fe9e9e693ef12160c77382d9e87919bce54f3d4ca", size = 107438, upload-time = "2025-08-09T07:57:25.287Z" }, + { url = "https://files.pythonhosted.org/packages/8a/1f/f041989e93b001bc4e44bb1669ccdcf54d3f00e628229a85b08d330615c5/charset_normalizer-3.4.3-py3-none-any.whl", hash = "sha256:ce571ab16d890d23b5c278547ba694193a45011ff86a9162a71307ed9f86759a", size = 53175, upload-time = "2025-08-09T07:57:26.864Z" }, ] [[package]] name = "click" version = "8.1.8" source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.10'", +] dependencies = [ - { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "colorama", marker = "python_full_version < '3.10' and sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/b9/2e/0090cbf739cee7d23781ad4b89a9894a41538e4fcf4c31dcdd705b78eb8b/click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a", size = 226593, upload-time = "2024-12-21T18:38:44.339Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/7e/d4/7ebdbd03970677812aac39c869717059dbb71a4cfc033ca6e5221787892c/click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2", size = 98188, upload-time = "2024-12-21T18:38:41.666Z" }, ] +[[package]] +name = "click" +version = "8.2.1" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.13'", + "python_full_version >= '3.11' and python_full_version < '3.13'", + "python_full_version == '3.10.*'", +] +dependencies = [ + { name = "colorama", marker = "python_full_version >= '3.10' and sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/60/6c/8ca2efa64cf75a977a0d7fac081354553ebe483345c734fb6b6515d96bbc/click-8.2.1.tar.gz", hash = "sha256:27c491cc05d968d271d5a1db13e3b5a184636d9d930f148c50b038f0d0646202", size = 286342, upload-time = "2025-05-20T23:19:49.832Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/85/32/10bb5764d90a8eee674e9dc6f4db6a0ab47c8c4d0d83c27f7c39ac415a4d/click-8.2.1-py3-none-any.whl", hash = "sha256:61a3265b914e850b85317d0b3109c7f8cd35a670f963866005d6ef1d5175a12b", size = 102215, upload-time = "2025-05-20T23:19:47.796Z" }, +] + [[package]] name = "colorama" version = "0.4.6" @@ -363,7 +496,8 @@ dependencies = [ { name = "charset-normalizer" }, { name = "colorama" }, { name = "decli" }, - { name = "importlib-metadata" }, + { name = "importlib-metadata", version = "8.6.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "importlib-metadata", version = "8.7.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "jinja2" }, { name = "packaging" }, { name = "pyyaml" }, @@ -379,97 +513,97 @@ wheels = [ [[package]] name = "coverage" -version = "7.10.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/87/0e/66dbd4c6a7f0758a8d18044c048779ba21fb94856e1edcf764bd5403e710/coverage-7.10.1.tar.gz", hash = "sha256:ae2b4856f29ddfe827106794f3589949a57da6f0d38ab01e24ec35107979ba57", size = 819938, upload-time = "2025-07-27T14:13:39.045Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ef/e7/0f4e35a15361337529df88151bddcac8e8f6d6fd01da94a4b7588901c2fe/coverage-7.10.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1c86eb388bbd609d15560e7cc0eb936c102b6f43f31cf3e58b4fd9afe28e1372", size = 214627, upload-time = "2025-07-27T14:11:01.211Z" }, - { url = "https://files.pythonhosted.org/packages/e0/fd/17872e762c408362072c936dbf3ca28c67c609a1f5af434b1355edcb7e12/coverage-7.10.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6b4ba0f488c1bdb6bd9ba81da50715a372119785458831c73428a8566253b86b", size = 215015, upload-time = "2025-07-27T14:11:03.988Z" }, - { url = "https://files.pythonhosted.org/packages/54/50/c9d445ba38ee5f685f03876c0f8223469e2e46c5d3599594dca972b470c8/coverage-7.10.1-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:083442ecf97d434f0cb3b3e3676584443182653da08b42e965326ba12d6b5f2a", size = 241995, upload-time = "2025-07-27T14:11:05.983Z" }, - { url = "https://files.pythonhosted.org/packages/cc/83/4ae6e0f60376af33de543368394d21b9ac370dc86434039062ef171eebf8/coverage-7.10.1-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:c1a40c486041006b135759f59189385da7c66d239bad897c994e18fd1d0c128f", size = 243253, upload-time = "2025-07-27T14:11:07.424Z" }, - { url = "https://files.pythonhosted.org/packages/49/90/17a4d9ac7171be364ce8c0bb2b6da05e618ebfe1f11238ad4f26c99f5467/coverage-7.10.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3beb76e20b28046989300c4ea81bf690df84ee98ade4dc0bbbf774a28eb98440", size = 245110, upload-time = "2025-07-27T14:11:09.152Z" }, - { url = "https://files.pythonhosted.org/packages/e1/f7/edc3f485d536ed417f3af2b4969582bcb5fab456241721825fa09354161e/coverage-7.10.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:bc265a7945e8d08da28999ad02b544963f813a00f3ed0a7a0ce4165fd77629f8", size = 243056, upload-time = "2025-07-27T14:11:10.586Z" }, - { url = "https://files.pythonhosted.org/packages/58/2c/c4c316a57718556b8d0cc8304437741c31b54a62934e7c8c551a7915c2f4/coverage-7.10.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:47c91f32ba4ac46f1e224a7ebf3f98b4b24335bad16137737fe71a5961a0665c", size = 241731, upload-time = "2025-07-27T14:11:12.145Z" }, - { url = "https://files.pythonhosted.org/packages/f7/93/c78e144c6f086043d0d7d9237c5b880e71ac672ed2712c6f8cca5544481f/coverage-7.10.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:1a108dd78ed185020f66f131c60078f3fae3f61646c28c8bb4edd3fa121fc7fc", size = 242023, upload-time = "2025-07-27T14:11:13.573Z" }, - { url = "https://files.pythonhosted.org/packages/8f/e1/34e8505ca81fc144a612e1cc79fadd4a78f42e96723875f4e9f1f470437e/coverage-7.10.1-cp310-cp310-win32.whl", hash = "sha256:7092cc82382e634075cc0255b0b69cb7cada7c1f249070ace6a95cb0f13548ef", size = 217130, upload-time = "2025-07-27T14:11:15.11Z" }, - { url = "https://files.pythonhosted.org/packages/75/2b/82adfce6edffc13d804aee414e64c0469044234af9296e75f6d13f92f6a2/coverage-7.10.1-cp310-cp310-win_amd64.whl", hash = "sha256:ac0c5bba938879c2fc0bc6c1b47311b5ad1212a9dcb8b40fe2c8110239b7faed", size = 218015, upload-time = "2025-07-27T14:11:16.836Z" }, - { url = "https://files.pythonhosted.org/packages/20/8e/ef088112bd1b26e2aa931ee186992b3e42c222c64f33e381432c8ee52aae/coverage-7.10.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b45e2f9d5b0b5c1977cb4feb5f594be60eb121106f8900348e29331f553a726f", size = 214747, upload-time = "2025-07-27T14:11:18.217Z" }, - { url = "https://files.pythonhosted.org/packages/2d/76/a1e46f3c6e0897758eb43af88bb3c763cb005f4950769f7b553e22aa5f89/coverage-7.10.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3a7a4d74cb0f5e3334f9aa26af7016ddb94fb4bfa11b4a573d8e98ecba8c34f1", size = 215128, upload-time = "2025-07-27T14:11:19.706Z" }, - { url = "https://files.pythonhosted.org/packages/78/4d/903bafb371a8c887826ecc30d3977b65dfad0e1e66aa61b7e173de0828b0/coverage-7.10.1-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:d4b0aab55ad60ead26159ff12b538c85fbab731a5e3411c642b46c3525863437", size = 245140, upload-time = "2025-07-27T14:11:21.261Z" }, - { url = "https://files.pythonhosted.org/packages/55/f1/1f8f09536f38394a8698dd08a0e9608a512eacee1d3b771e2d06397f77bf/coverage-7.10.1-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:dcc93488c9ebd229be6ee1f0d9aad90da97b33ad7e2912f5495804d78a3cd6b7", size = 246977, upload-time = "2025-07-27T14:11:23.15Z" }, - { url = "https://files.pythonhosted.org/packages/57/cc/ed6bbc5a3bdb36ae1bca900bbbfdcb23b260ef2767a7b2dab38b92f61adf/coverage-7.10.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:aa309df995d020f3438407081b51ff527171cca6772b33cf8f85344b8b4b8770", size = 249140, upload-time = "2025-07-27T14:11:24.743Z" }, - { url = "https://files.pythonhosted.org/packages/10/f5/e881ade2d8e291b60fa1d93d6d736107e940144d80d21a0d4999cff3642f/coverage-7.10.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:cfb8b9d8855c8608f9747602a48ab525b1d320ecf0113994f6df23160af68262", size = 246869, upload-time = "2025-07-27T14:11:26.156Z" }, - { url = "https://files.pythonhosted.org/packages/53/b9/6a5665cb8996e3cd341d184bb11e2a8edf01d8dadcf44eb1e742186cf243/coverage-7.10.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:320d86da829b012982b414c7cdda65f5d358d63f764e0e4e54b33097646f39a3", size = 244899, upload-time = "2025-07-27T14:11:27.622Z" }, - { url = "https://files.pythonhosted.org/packages/27/11/24156776709c4e25bf8a33d6bb2ece9a9067186ddac19990f6560a7f8130/coverage-7.10.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:dc60ddd483c556590da1d9482a4518292eec36dd0e1e8496966759a1f282bcd0", size = 245507, upload-time = "2025-07-27T14:11:29.544Z" }, - { url = "https://files.pythonhosted.org/packages/43/db/a6f0340b7d6802a79928659c9a32bc778ea420e87a61b568d68ac36d45a8/coverage-7.10.1-cp311-cp311-win32.whl", hash = "sha256:4fcfe294f95b44e4754da5b58be750396f2b1caca8f9a0e78588e3ef85f8b8be", size = 217167, upload-time = "2025-07-27T14:11:31.349Z" }, - { url = "https://files.pythonhosted.org/packages/f5/6f/1990eb4fd05cea4cfabdf1d587a997ac5f9a8bee883443a1d519a2a848c9/coverage-7.10.1-cp311-cp311-win_amd64.whl", hash = "sha256:efa23166da3fe2915f8ab452dde40319ac84dc357f635737174a08dbd912980c", size = 218054, upload-time = "2025-07-27T14:11:33.202Z" }, - { url = "https://files.pythonhosted.org/packages/b4/4d/5e061d6020251b20e9b4303bb0b7900083a1a384ec4e5db326336c1c4abd/coverage-7.10.1-cp311-cp311-win_arm64.whl", hash = "sha256:d12b15a8c3759e2bb580ffa423ae54be4f184cf23beffcbd641f4fe6e1584293", size = 216483, upload-time = "2025-07-27T14:11:34.663Z" }, - { url = "https://files.pythonhosted.org/packages/a5/3f/b051feeb292400bd22d071fdf933b3ad389a8cef5c80c7866ed0c7414b9e/coverage-7.10.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6b7dc7f0a75a7eaa4584e5843c873c561b12602439d2351ee28c7478186c4da4", size = 214934, upload-time = "2025-07-27T14:11:36.096Z" }, - { url = "https://files.pythonhosted.org/packages/f8/e4/a61b27d5c4c2d185bdfb0bfe9d15ab4ac4f0073032665544507429ae60eb/coverage-7.10.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:607f82389f0ecafc565813aa201a5cade04f897603750028dd660fb01797265e", size = 215173, upload-time = "2025-07-27T14:11:38.005Z" }, - { url = "https://files.pythonhosted.org/packages/8a/01/40a6ee05b60d02d0bc53742ad4966e39dccd450aafb48c535a64390a3552/coverage-7.10.1-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:f7da31a1ba31f1c1d4d5044b7c5813878adae1f3af8f4052d679cc493c7328f4", size = 246190, upload-time = "2025-07-27T14:11:39.887Z" }, - { url = "https://files.pythonhosted.org/packages/11/ef/a28d64d702eb583c377255047281305dc5a5cfbfb0ee36e721f78255adb6/coverage-7.10.1-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:51fe93f3fe4f5d8483d51072fddc65e717a175490804e1942c975a68e04bf97a", size = 248618, upload-time = "2025-07-27T14:11:41.841Z" }, - { url = "https://files.pythonhosted.org/packages/6a/ad/73d018bb0c8317725370c79d69b5c6e0257df84a3b9b781bda27a438a3be/coverage-7.10.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3e59d00830da411a1feef6ac828b90bbf74c9b6a8e87b8ca37964925bba76dbe", size = 250081, upload-time = "2025-07-27T14:11:43.705Z" }, - { url = "https://files.pythonhosted.org/packages/2d/dd/496adfbbb4503ebca5d5b2de8bed5ec00c0a76558ffc5b834fd404166bc9/coverage-7.10.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:924563481c27941229cb4e16eefacc35da28563e80791b3ddc5597b062a5c386", size = 247990, upload-time = "2025-07-27T14:11:45.244Z" }, - { url = "https://files.pythonhosted.org/packages/18/3c/a9331a7982facfac0d98a4a87b36ae666fe4257d0f00961a3a9ef73e015d/coverage-7.10.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:ca79146ee421b259f8131f153102220b84d1a5e6fb9c8aed13b3badfd1796de6", size = 246191, upload-time = "2025-07-27T14:11:47.093Z" }, - { url = "https://files.pythonhosted.org/packages/62/0c/75345895013b83f7afe92ec595e15a9a525ede17491677ceebb2ba5c3d85/coverage-7.10.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2b225a06d227f23f386fdc0eab471506d9e644be699424814acc7d114595495f", size = 247400, upload-time = "2025-07-27T14:11:48.643Z" }, - { url = "https://files.pythonhosted.org/packages/e2/a9/98b268cfc5619ef9df1d5d34fee408ecb1542d9fd43d467e5c2f28668cd4/coverage-7.10.1-cp312-cp312-win32.whl", hash = "sha256:5ba9a8770effec5baaaab1567be916c87d8eea0c9ad11253722d86874d885eca", size = 217338, upload-time = "2025-07-27T14:11:50.258Z" }, - { url = "https://files.pythonhosted.org/packages/fe/31/22a5440e4d1451f253c5cd69fdcead65e92ef08cd4ec237b8756dc0b20a7/coverage-7.10.1-cp312-cp312-win_amd64.whl", hash = "sha256:9eb245a8d8dd0ad73b4062135a251ec55086fbc2c42e0eb9725a9b553fba18a3", size = 218125, upload-time = "2025-07-27T14:11:52.034Z" }, - { url = "https://files.pythonhosted.org/packages/d6/2b/40d9f0ce7ee839f08a43c5bfc9d05cec28aaa7c9785837247f96cbe490b9/coverage-7.10.1-cp312-cp312-win_arm64.whl", hash = "sha256:7718060dd4434cc719803a5e526838a5d66e4efa5dc46d2b25c21965a9c6fcc4", size = 216523, upload-time = "2025-07-27T14:11:53.965Z" }, - { url = "https://files.pythonhosted.org/packages/ef/72/135ff5fef09b1ffe78dbe6fcf1e16b2e564cd35faeacf3d63d60d887f12d/coverage-7.10.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ebb08d0867c5a25dffa4823377292a0ffd7aaafb218b5d4e2e106378b1061e39", size = 214960, upload-time = "2025-07-27T14:11:55.959Z" }, - { url = "https://files.pythonhosted.org/packages/b1/aa/73a5d1a6fc08ca709a8177825616aa95ee6bf34d522517c2595484a3e6c9/coverage-7.10.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f32a95a83c2e17422f67af922a89422cd24c6fa94041f083dd0bb4f6057d0bc7", size = 215220, upload-time = "2025-07-27T14:11:57.899Z" }, - { url = "https://files.pythonhosted.org/packages/8d/40/3124fdd45ed3772a42fc73ca41c091699b38a2c3bd4f9cb564162378e8b6/coverage-7.10.1-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:c4c746d11c8aba4b9f58ca8bfc6fbfd0da4efe7960ae5540d1a1b13655ee8892", size = 245772, upload-time = "2025-07-27T14:12:00.422Z" }, - { url = "https://files.pythonhosted.org/packages/42/62/a77b254822efa8c12ad59e8039f2bc3df56dc162ebda55e1943e35ba31a5/coverage-7.10.1-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:7f39edd52c23e5c7ed94e0e4bf088928029edf86ef10b95413e5ea670c5e92d7", size = 248116, upload-time = "2025-07-27T14:12:03.099Z" }, - { url = "https://files.pythonhosted.org/packages/1d/01/8101f062f472a3a6205b458d18ef0444a63ae5d36a8a5ed5dd0f6167f4db/coverage-7.10.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ab6e19b684981d0cd968906e293d5628e89faacb27977c92f3600b201926b994", size = 249554, upload-time = "2025-07-27T14:12:04.668Z" }, - { url = "https://files.pythonhosted.org/packages/8f/7b/e51bc61573e71ff7275a4f167aecbd16cb010aefdf54bcd8b0a133391263/coverage-7.10.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5121d8cf0eacb16133501455d216bb5f99899ae2f52d394fe45d59229e6611d0", size = 247766, upload-time = "2025-07-27T14:12:06.234Z" }, - { url = "https://files.pythonhosted.org/packages/4b/71/1c96d66a51d4204a9d6d12df53c4071d87e110941a2a1fe94693192262f5/coverage-7.10.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:df1c742ca6f46a6f6cbcaef9ac694dc2cb1260d30a6a2f5c68c5f5bcfee1cfd7", size = 245735, upload-time = "2025-07-27T14:12:08.305Z" }, - { url = "https://files.pythonhosted.org/packages/13/d5/efbc2ac4d35ae2f22ef6df2ca084c60e13bd9378be68655e3268c80349ab/coverage-7.10.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:40f9a38676f9c073bf4b9194707aa1eb97dca0e22cc3766d83879d72500132c7", size = 247118, upload-time = "2025-07-27T14:12:09.903Z" }, - { url = "https://files.pythonhosted.org/packages/d1/22/073848352bec28ca65f2b6816b892fcf9a31abbef07b868487ad15dd55f1/coverage-7.10.1-cp313-cp313-win32.whl", hash = "sha256:2348631f049e884839553b9974f0821d39241c6ffb01a418efce434f7eba0fe7", size = 217381, upload-time = "2025-07-27T14:12:11.535Z" }, - { url = "https://files.pythonhosted.org/packages/b7/df/df6a0ff33b042f000089bd11b6bb034bab073e2ab64a56e78ed882cba55d/coverage-7.10.1-cp313-cp313-win_amd64.whl", hash = "sha256:4072b31361b0d6d23f750c524f694e1a417c1220a30d3ef02741eed28520c48e", size = 218152, upload-time = "2025-07-27T14:12:13.182Z" }, - { url = "https://files.pythonhosted.org/packages/30/e3/5085ca849a40ed6b47cdb8f65471c2f754e19390b5a12fa8abd25cbfaa8f/coverage-7.10.1-cp313-cp313-win_arm64.whl", hash = "sha256:3e31dfb8271937cab9425f19259b1b1d1f556790e98eb266009e7a61d337b6d4", size = 216559, upload-time = "2025-07-27T14:12:14.807Z" }, - { url = "https://files.pythonhosted.org/packages/cc/93/58714efbfdeb547909feaabe1d67b2bdd59f0597060271b9c548d5efb529/coverage-7.10.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:1c4f679c6b573a5257af6012f167a45be4c749c9925fd44d5178fd641ad8bf72", size = 215677, upload-time = "2025-07-27T14:12:16.68Z" }, - { url = "https://files.pythonhosted.org/packages/c0/0c/18eaa5897e7e8cb3f8c45e563e23e8a85686b4585e29d53cacb6bc9cb340/coverage-7.10.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:871ebe8143da284bd77b84a9136200bd638be253618765d21a1fce71006d94af", size = 215899, upload-time = "2025-07-27T14:12:18.758Z" }, - { url = "https://files.pythonhosted.org/packages/84/c1/9d1affacc3c75b5a184c140377701bbf14fc94619367f07a269cd9e4fed6/coverage-7.10.1-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:998c4751dabf7d29b30594af416e4bf5091f11f92a8d88eb1512c7ba136d1ed7", size = 257140, upload-time = "2025-07-27T14:12:20.357Z" }, - { url = "https://files.pythonhosted.org/packages/3d/0f/339bc6b8fa968c346df346068cca1f24bdea2ddfa93bb3dc2e7749730962/coverage-7.10.1-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:780f750a25e7749d0af6b3631759c2c14f45de209f3faaa2398312d1c7a22759", size = 259005, upload-time = "2025-07-27T14:12:22.007Z" }, - { url = "https://files.pythonhosted.org/packages/c8/22/89390864b92ea7c909079939b71baba7e5b42a76bf327c1d615bd829ba57/coverage-7.10.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:590bdba9445df4763bdbebc928d8182f094c1f3947a8dc0fc82ef014dbdd8324", size = 261143, upload-time = "2025-07-27T14:12:23.746Z" }, - { url = "https://files.pythonhosted.org/packages/2c/56/3d04d89017c0c41c7a71bd69b29699d919b6bbf2649b8b2091240b97dd6a/coverage-7.10.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9b2df80cb6a2af86d300e70acb82e9b79dab2c1e6971e44b78dbfc1a1e736b53", size = 258735, upload-time = "2025-07-27T14:12:25.73Z" }, - { url = "https://files.pythonhosted.org/packages/cb/40/312252c8afa5ca781063a09d931f4b9409dc91526cd0b5a2b84143ffafa2/coverage-7.10.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:d6a558c2725bfb6337bf57c1cd366c13798bfd3bfc9e3dd1f4a6f6fc95a4605f", size = 256871, upload-time = "2025-07-27T14:12:27.767Z" }, - { url = "https://files.pythonhosted.org/packages/1f/2b/564947d5dede068215aaddb9e05638aeac079685101462218229ddea9113/coverage-7.10.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:e6150d167f32f2a54690e572e0a4c90296fb000a18e9b26ab81a6489e24e78dd", size = 257692, upload-time = "2025-07-27T14:12:29.347Z" }, - { url = "https://files.pythonhosted.org/packages/93/1b/c8a867ade85cb26d802aea2209b9c2c80613b9c122baa8c8ecea6799648f/coverage-7.10.1-cp313-cp313t-win32.whl", hash = "sha256:d946a0c067aa88be4a593aad1236493313bafaa27e2a2080bfe88db827972f3c", size = 218059, upload-time = "2025-07-27T14:12:31.076Z" }, - { url = "https://files.pythonhosted.org/packages/a1/fe/cd4ab40570ae83a516bf5e754ea4388aeedd48e660e40c50b7713ed4f930/coverage-7.10.1-cp313-cp313t-win_amd64.whl", hash = "sha256:e37c72eaccdd5ed1130c67a92ad38f5b2af66eeff7b0abe29534225db2ef7b18", size = 219150, upload-time = "2025-07-27T14:12:32.746Z" }, - { url = "https://files.pythonhosted.org/packages/8d/16/6e5ed5854be6d70d0c39e9cb9dd2449f2c8c34455534c32c1a508c7dbdb5/coverage-7.10.1-cp313-cp313t-win_arm64.whl", hash = "sha256:89ec0ffc215c590c732918c95cd02b55c7d0f569d76b90bb1a5e78aa340618e4", size = 217014, upload-time = "2025-07-27T14:12:34.406Z" }, - { url = "https://files.pythonhosted.org/packages/54/8e/6d0bfe9c3d7121cf936c5f8b03e8c3da1484fb801703127dba20fb8bd3c7/coverage-7.10.1-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:166d89c57e877e93d8827dac32cedae6b0277ca684c6511497311249f35a280c", size = 214951, upload-time = "2025-07-27T14:12:36.069Z" }, - { url = "https://files.pythonhosted.org/packages/f2/29/e3e51a8c653cf2174c60532aafeb5065cea0911403fa144c9abe39790308/coverage-7.10.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:bed4a2341b33cd1a7d9ffc47df4a78ee61d3416d43b4adc9e18b7d266650b83e", size = 215229, upload-time = "2025-07-27T14:12:37.759Z" }, - { url = "https://files.pythonhosted.org/packages/e0/59/3c972080b2fa18b6c4510201f6d4dc87159d450627d062cd9ad051134062/coverage-7.10.1-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:ddca1e4f5f4c67980533df01430184c19b5359900e080248bbf4ed6789584d8b", size = 245738, upload-time = "2025-07-27T14:12:39.453Z" }, - { url = "https://files.pythonhosted.org/packages/2e/04/fc0d99d3f809452654e958e1788454f6e27b34e43f8f8598191c8ad13537/coverage-7.10.1-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:37b69226001d8b7de7126cad7366b0778d36777e4d788c66991455ba817c5b41", size = 248045, upload-time = "2025-07-27T14:12:41.387Z" }, - { url = "https://files.pythonhosted.org/packages/5e/2e/afcbf599e77e0dfbf4c97197747250d13d397d27e185b93987d9eaac053d/coverage-7.10.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b2f22102197bcb1722691296f9e589f02b616f874e54a209284dd7b9294b0b7f", size = 249666, upload-time = "2025-07-27T14:12:43.056Z" }, - { url = "https://files.pythonhosted.org/packages/6e/ae/bc47f7f8ecb7a06cbae2bf86a6fa20f479dd902bc80f57cff7730438059d/coverage-7.10.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:1e0c768b0f9ac5839dac5cf88992a4bb459e488ee8a1f8489af4cb33b1af00f1", size = 247692, upload-time = "2025-07-27T14:12:44.83Z" }, - { url = "https://files.pythonhosted.org/packages/b6/26/cbfa3092d31ccba8ba7647e4d25753263e818b4547eba446b113d7d1efdf/coverage-7.10.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:991196702d5e0b120a8fef2664e1b9c333a81d36d5f6bcf6b225c0cf8b0451a2", size = 245536, upload-time = "2025-07-27T14:12:46.527Z" }, - { url = "https://files.pythonhosted.org/packages/56/77/9c68e92500e6a1c83d024a70eadcc9a173f21aadd73c4675fe64c9c43fdf/coverage-7.10.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ae8e59e5f4fd85d6ad34c2bb9d74037b5b11be072b8b7e9986beb11f957573d4", size = 246954, upload-time = "2025-07-27T14:12:49.279Z" }, - { url = "https://files.pythonhosted.org/packages/7f/a5/ba96671c5a669672aacd9877a5987c8551501b602827b4e84256da2a30a7/coverage-7.10.1-cp314-cp314-win32.whl", hash = "sha256:042125c89cf74a074984002e165d61fe0e31c7bd40ebb4bbebf07939b5924613", size = 217616, upload-time = "2025-07-27T14:12:51.214Z" }, - { url = "https://files.pythonhosted.org/packages/e7/3c/e1e1eb95fc1585f15a410208c4795db24a948e04d9bde818fe4eb893bc85/coverage-7.10.1-cp314-cp314-win_amd64.whl", hash = "sha256:a22c3bfe09f7a530e2c94c87ff7af867259c91bef87ed2089cd69b783af7b84e", size = 218412, upload-time = "2025-07-27T14:12:53.429Z" }, - { url = "https://files.pythonhosted.org/packages/b0/85/7e1e5be2cb966cba95566ba702b13a572ca744fbb3779df9888213762d67/coverage-7.10.1-cp314-cp314-win_arm64.whl", hash = "sha256:ee6be07af68d9c4fca4027c70cea0c31a0f1bc9cb464ff3c84a1f916bf82e652", size = 216776, upload-time = "2025-07-27T14:12:55.482Z" }, - { url = "https://files.pythonhosted.org/packages/62/0f/5bb8f29923141cca8560fe2217679caf4e0db643872c1945ac7d8748c2a7/coverage-7.10.1-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:d24fb3c0c8ff0d517c5ca5de7cf3994a4cd559cde0315201511dbfa7ab528894", size = 215698, upload-time = "2025-07-27T14:12:57.225Z" }, - { url = "https://files.pythonhosted.org/packages/80/29/547038ffa4e8e4d9e82f7dfc6d152f75fcdc0af146913f0ba03875211f03/coverage-7.10.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1217a54cfd79be20512a67ca81c7da3f2163f51bbfd188aab91054df012154f5", size = 215902, upload-time = "2025-07-27T14:12:59.071Z" }, - { url = "https://files.pythonhosted.org/packages/e1/8a/7aaa8fbfaed900147987a424e112af2e7790e1ac9cd92601e5bd4e1ba60a/coverage-7.10.1-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:51f30da7a52c009667e02f125737229d7d8044ad84b79db454308033a7808ab2", size = 257230, upload-time = "2025-07-27T14:13:01.248Z" }, - { url = "https://files.pythonhosted.org/packages/e5/1d/c252b5ffac44294e23a0d79dd5acf51749b39795ccc898faeabf7bee903f/coverage-7.10.1-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:ed3718c757c82d920f1c94089066225ca2ad7f00bb904cb72b1c39ebdd906ccb", size = 259194, upload-time = "2025-07-27T14:13:03.247Z" }, - { url = "https://files.pythonhosted.org/packages/16/ad/6c8d9f83d08f3bac2e7507534d0c48d1a4f52c18e6f94919d364edbdfa8f/coverage-7.10.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cc452481e124a819ced0c25412ea2e144269ef2f2534b862d9f6a9dae4bda17b", size = 261316, upload-time = "2025-07-27T14:13:04.957Z" }, - { url = "https://files.pythonhosted.org/packages/d6/4e/f9bbf3a36c061e2e0e0f78369c006d66416561a33d2bee63345aee8ee65e/coverage-7.10.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:9d6f494c307e5cb9b1e052ec1a471060f1dea092c8116e642e7a23e79d9388ea", size = 258794, upload-time = "2025-07-27T14:13:06.715Z" }, - { url = "https://files.pythonhosted.org/packages/87/82/e600bbe78eb2cb0541751d03cef9314bcd0897e8eea156219c39b685f869/coverage-7.10.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:fc0e46d86905ddd16b85991f1f4919028092b4e511689bbdaff0876bd8aab3dd", size = 256869, upload-time = "2025-07-27T14:13:08.933Z" }, - { url = "https://files.pythonhosted.org/packages/ce/5d/2fc9a9236c5268f68ac011d97cd3a5ad16cc420535369bedbda659fdd9b7/coverage-7.10.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:80b9ccd82e30038b61fc9a692a8dc4801504689651b281ed9109f10cc9fe8b4d", size = 257765, upload-time = "2025-07-27T14:13:10.778Z" }, - { url = "https://files.pythonhosted.org/packages/8a/05/b4e00b2bd48a2dc8e1c7d2aea7455f40af2e36484ab2ef06deb85883e9fe/coverage-7.10.1-cp314-cp314t-win32.whl", hash = "sha256:e58991a2b213417285ec866d3cd32db17a6a88061a985dbb7e8e8f13af429c47", size = 218420, upload-time = "2025-07-27T14:13:12.882Z" }, - { url = "https://files.pythonhosted.org/packages/77/fb/d21d05f33ea27ece327422240e69654b5932b0b29e7fbc40fbab3cf199bf/coverage-7.10.1-cp314-cp314t-win_amd64.whl", hash = "sha256:e88dd71e4ecbc49d9d57d064117462c43f40a21a1383507811cf834a4a620651", size = 219536, upload-time = "2025-07-27T14:13:14.718Z" }, - { url = "https://files.pythonhosted.org/packages/a6/68/7fea94b141281ed8be3d1d5c4319a97f2befc3e487ce33657fc64db2c45e/coverage-7.10.1-cp314-cp314t-win_arm64.whl", hash = "sha256:1aadfb06a30c62c2eb82322171fe1f7c288c80ca4156d46af0ca039052814bab", size = 217190, upload-time = "2025-07-27T14:13:16.85Z" }, - { url = "https://files.pythonhosted.org/packages/c3/98/9b19d4aebfb31552596a7ac55cd678c3ebd74be6153888c56d39e23f376b/coverage-7.10.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:57b6e8789cbefdef0667e4a94f8ffa40f9402cee5fc3b8e4274c894737890145", size = 214625, upload-time = "2025-07-27T14:13:18.661Z" }, - { url = "https://files.pythonhosted.org/packages/ea/24/e2391365d0940fc757666ecd7572aced0963e859188e57169bd18fba5d29/coverage-7.10.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:85b22a9cce00cb03156334da67eb86e29f22b5e93876d0dd6a98646bb8a74e53", size = 215001, upload-time = "2025-07-27T14:13:20.478Z" }, - { url = "https://files.pythonhosted.org/packages/ce/0c/c1740d7fac57cb0c54cd04786f3dbfc4d0bfa0a6cc9f19f69c170ae67f6a/coverage-7.10.1-cp39-cp39-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:97b6983a2f9c76d345ca395e843a049390b39652984e4a3b45b2442fa733992d", size = 241082, upload-time = "2025-07-27T14:13:22.318Z" }, - { url = "https://files.pythonhosted.org/packages/45/b5/965b26315ecae6455bc40f1de8563a57e82cb31af8af2e2844655cf400f1/coverage-7.10.1-cp39-cp39-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:ddf2a63b91399a1c2f88f40bc1705d5a7777e31c7e9eb27c602280f477b582ba", size = 242979, upload-time = "2025-07-27T14:13:24.123Z" }, - { url = "https://files.pythonhosted.org/packages/0b/48/80c5c6a5a792348ba71b2315809c5a2daab2981564e31d1f3cd092c8cd97/coverage-7.10.1-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:47ab6dbbc31a14c5486420c2c1077fcae692097f673cf5be9ddbec8cdaa4cdbc", size = 244550, upload-time = "2025-07-27T14:13:25.9Z" }, - { url = "https://files.pythonhosted.org/packages/ab/73/332667b91cfa3c27130026af220fca478b07e913e96932d12c100e1a7314/coverage-7.10.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:21eb7d8b45d3700e7c2936a736f732794c47615a20f739f4133d5230a6512a88", size = 242482, upload-time = "2025-07-27T14:13:28.121Z" }, - { url = "https://files.pythonhosted.org/packages/ae/e6/24c9120ad91314be82f793a2a174fe738583a716264b1523fe95ad731cb3/coverage-7.10.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:283005bb4d98ae33e45f2861cd2cde6a21878661c9ad49697f6951b358a0379b", size = 240717, upload-time = "2025-07-27T14:13:29.93Z" }, - { url = "https://files.pythonhosted.org/packages/94/9a/21a4d5135eb4b8064fd9bf8a8eb8d4465982611d2d7fb569d6c2edf38f04/coverage-7.10.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:fefe31d61d02a8b2c419700b1fade9784a43d726de26495f243b663cd9fe1513", size = 241669, upload-time = "2025-07-27T14:13:31.726Z" }, - { url = "https://files.pythonhosted.org/packages/3f/1d/e4ce3b23f8b8b0fe196c436499414b1af06b9e1610cefedaaad37c9668d0/coverage-7.10.1-cp39-cp39-win32.whl", hash = "sha256:e8ab8e4c7ec7f8a55ac05b5b715a051d74eac62511c6d96d5bb79aaafa3b04cf", size = 217138, upload-time = "2025-07-27T14:13:33.481Z" }, - { url = "https://files.pythonhosted.org/packages/d3/c6/b7fcf41c341e686610fdf9ef1a4b29045015f36d3eecd17679874e4739ed/coverage-7.10.1-cp39-cp39-win_amd64.whl", hash = "sha256:c36baa0ecde742784aa76c2b816466d3ea888d5297fda0edbac1bf48fa94688a", size = 218035, upload-time = "2025-07-27T14:13:35.337Z" }, - { url = "https://files.pythonhosted.org/packages/0f/64/922899cff2c0fd3496be83fa8b81230f5a8d82a2ad30f98370b133c2c83b/coverage-7.10.1-py3-none-any.whl", hash = "sha256:fa2a258aa6bf188eb9a8948f7102a83da7c430a0dce918dbd8b60ef8fcb772d7", size = 206597, upload-time = "2025-07-27T14:13:37.221Z" }, +version = "7.10.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d6/4e/08b493f1f1d8a5182df0044acc970799b58a8d289608e0d891a03e9d269a/coverage-7.10.4.tar.gz", hash = "sha256:25f5130af6c8e7297fd14634955ba9e1697f47143f289e2a23284177c0061d27", size = 823798, upload-time = "2025-08-17T00:26:43.314Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9c/f4/350759710db50362685f922259c140592dba15eb4e2325656a98413864d9/coverage-7.10.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d92d6edb0ccafd20c6fbf9891ca720b39c2a6a4b4a6f9cf323ca2c986f33e475", size = 216403, upload-time = "2025-08-17T00:24:19.083Z" }, + { url = "https://files.pythonhosted.org/packages/29/7e/e467c2bb4d5ecfd166bfd22c405cce4c50de2763ba1d78e2729c59539a42/coverage-7.10.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:7202da14dc0236884fcc45665ffb2d79d4991a53fbdf152ab22f69f70923cc22", size = 216802, upload-time = "2025-08-17T00:24:21.824Z" }, + { url = "https://files.pythonhosted.org/packages/62/ab/2accdd1ccfe63b890e5eb39118f63c155202df287798364868a2884a50af/coverage-7.10.4-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:ada418633ae24ec8d0fcad5efe6fc7aa3c62497c6ed86589e57844ad04365674", size = 243558, upload-time = "2025-08-17T00:24:23.569Z" }, + { url = "https://files.pythonhosted.org/packages/43/04/c14c33d0cfc0f4db6b3504d01a47f4c798563d932a836fd5f2dbc0521d3d/coverage-7.10.4-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b828e33eca6c3322adda3b5884456f98c435182a44917ded05005adfa1415500", size = 245370, upload-time = "2025-08-17T00:24:24.858Z" }, + { url = "https://files.pythonhosted.org/packages/99/71/147053061f1f51c1d3b3d040c3cb26876964a3a0dca0765d2441411ca568/coverage-7.10.4-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:802793ba397afcfdbe9f91f89d65ae88b958d95edc8caf948e1f47d8b6b2b606", size = 247228, upload-time = "2025-08-17T00:24:26.167Z" }, + { url = "https://files.pythonhosted.org/packages/cc/92/7ef882205d4d4eb502e6154ee7122c1a1b1ce3f29d0166921e0fb550a5d3/coverage-7.10.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d0b23512338c54101d3bf7a1ab107d9d75abda1d5f69bc0887fd079253e4c27e", size = 245270, upload-time = "2025-08-17T00:24:27.424Z" }, + { url = "https://files.pythonhosted.org/packages/ab/3d/297a20603abcc6c7d89d801286eb477b0b861f3c5a4222730f1c9837be3e/coverage-7.10.4-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:f36b7dcf72d06a8c5e2dd3aca02be2b1b5db5f86404627dff834396efce958f2", size = 243287, upload-time = "2025-08-17T00:24:28.697Z" }, + { url = "https://files.pythonhosted.org/packages/65/f9/b04111438f41f1ddd5dc88706d5f8064ae5bb962203c49fe417fa23a362d/coverage-7.10.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:fce316c367a1dc2c411821365592eeb335ff1781956d87a0410eae248188ba51", size = 244164, upload-time = "2025-08-17T00:24:30.393Z" }, + { url = "https://files.pythonhosted.org/packages/1e/e5/c7d9eb7a9ea66cf92d069077719fb2b07782dcd7050b01a9b88766b52154/coverage-7.10.4-cp310-cp310-win32.whl", hash = "sha256:8c5dab29fc8070b3766b5fc85f8d89b19634584429a2da6d42da5edfadaf32ae", size = 218917, upload-time = "2025-08-17T00:24:31.67Z" }, + { url = "https://files.pythonhosted.org/packages/66/30/4d9d3b81f5a836b31a7428b8a25e6d490d4dca5ff2952492af130153c35c/coverage-7.10.4-cp310-cp310-win_amd64.whl", hash = "sha256:4b0d114616f0fccb529a1817457d5fb52a10e106f86c5fb3b0bd0d45d0d69b93", size = 219822, upload-time = "2025-08-17T00:24:32.89Z" }, + { url = "https://files.pythonhosted.org/packages/ec/ba/2c9817e62018e7d480d14f684c160b3038df9ff69c5af7d80e97d143e4d1/coverage-7.10.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:05d5f98ec893d4a2abc8bc5f046f2f4367404e7e5d5d18b83de8fde1093ebc4f", size = 216514, upload-time = "2025-08-17T00:24:34.188Z" }, + { url = "https://files.pythonhosted.org/packages/e3/5a/093412a959a6b6261446221ba9fb23bb63f661a5de70b5d130763c87f916/coverage-7.10.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9267efd28f8994b750d171e58e481e3bbd69e44baed540e4c789f8e368b24b88", size = 216914, upload-time = "2025-08-17T00:24:35.881Z" }, + { url = "https://files.pythonhosted.org/packages/2c/1f/2fdf4a71cfe93b07eae845ebf763267539a7d8b7e16b062f959d56d7e433/coverage-7.10.4-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:4456a039fdc1a89ea60823d0330f1ac6f97b0dbe9e2b6fb4873e889584b085fb", size = 247308, upload-time = "2025-08-17T00:24:37.61Z" }, + { url = "https://files.pythonhosted.org/packages/ba/16/33f6cded458e84f008b9f6bc379609a6a1eda7bffe349153b9960803fc11/coverage-7.10.4-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:c2bfbd2a9f7e68a21c5bd191be94bfdb2691ac40d325bac9ef3ae45ff5c753d9", size = 249241, upload-time = "2025-08-17T00:24:38.919Z" }, + { url = "https://files.pythonhosted.org/packages/84/98/9c18e47c889be58339ff2157c63b91a219272503ee32b49d926eea2337f2/coverage-7.10.4-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0ab7765f10ae1df7e7fe37de9e64b5a269b812ee22e2da3f84f97b1c7732a0d8", size = 251346, upload-time = "2025-08-17T00:24:40.507Z" }, + { url = "https://files.pythonhosted.org/packages/6d/07/00a6c0d53e9a22d36d8e95ddd049b860eef8f4b9fd299f7ce34d8e323356/coverage-7.10.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0a09b13695166236e171ec1627ff8434b9a9bae47528d0ba9d944c912d33b3d2", size = 249037, upload-time = "2025-08-17T00:24:41.904Z" }, + { url = "https://files.pythonhosted.org/packages/3e/0e/1e1b944d6a6483d07bab5ef6ce063fcf3d0cc555a16a8c05ebaab11f5607/coverage-7.10.4-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5c9e75dfdc0167d5675e9804f04a56b2cf47fb83a524654297000b578b8adcb7", size = 247090, upload-time = "2025-08-17T00:24:43.193Z" }, + { url = "https://files.pythonhosted.org/packages/62/43/2ce5ab8a728b8e25ced077111581290ffaef9efaf860a28e25435ab925cf/coverage-7.10.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c751261bfe6481caba15ec005a194cb60aad06f29235a74c24f18546d8377df0", size = 247732, upload-time = "2025-08-17T00:24:44.906Z" }, + { url = "https://files.pythonhosted.org/packages/a4/f3/706c4a24f42c1c5f3a2ca56637ab1270f84d9e75355160dc34d5e39bb5b7/coverage-7.10.4-cp311-cp311-win32.whl", hash = "sha256:051c7c9e765f003c2ff6e8c81ccea28a70fb5b0142671e4e3ede7cebd45c80af", size = 218961, upload-time = "2025-08-17T00:24:46.241Z" }, + { url = "https://files.pythonhosted.org/packages/e8/aa/6b9ea06e0290bf1cf2a2765bba89d561c5c563b4e9db8298bf83699c8b67/coverage-7.10.4-cp311-cp311-win_amd64.whl", hash = "sha256:1a647b152f10be08fb771ae4a1421dbff66141e3d8ab27d543b5eb9ea5af8e52", size = 219851, upload-time = "2025-08-17T00:24:48.795Z" }, + { url = "https://files.pythonhosted.org/packages/8b/be/f0dc9ad50ee183369e643cd7ed8f2ef5c491bc20b4c3387cbed97dd6e0d1/coverage-7.10.4-cp311-cp311-win_arm64.whl", hash = "sha256:b09b9e4e1de0d406ca9f19a371c2beefe3193b542f64a6dd40cfcf435b7d6aa0", size = 218530, upload-time = "2025-08-17T00:24:50.164Z" }, + { url = "https://files.pythonhosted.org/packages/9e/4a/781c9e4dd57cabda2a28e2ce5b00b6be416015265851060945a5ed4bd85e/coverage-7.10.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a1f0264abcabd4853d4cb9b3d164adbf1565da7dab1da1669e93f3ea60162d79", size = 216706, upload-time = "2025-08-17T00:24:51.528Z" }, + { url = "https://files.pythonhosted.org/packages/6a/8c/51255202ca03d2e7b664770289f80db6f47b05138e06cce112b3957d5dfd/coverage-7.10.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:536cbe6b118a4df231b11af3e0f974a72a095182ff8ec5f4868c931e8043ef3e", size = 216939, upload-time = "2025-08-17T00:24:53.171Z" }, + { url = "https://files.pythonhosted.org/packages/06/7f/df11131483698660f94d3c847dc76461369782d7a7644fcd72ac90da8fd0/coverage-7.10.4-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:9a4c0d84134797b7bf3f080599d0cd501471f6c98b715405166860d79cfaa97e", size = 248429, upload-time = "2025-08-17T00:24:54.934Z" }, + { url = "https://files.pythonhosted.org/packages/eb/fa/13ac5eda7300e160bf98f082e75f5c5b4189bf3a883dd1ee42dbedfdc617/coverage-7.10.4-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:7c155fc0f9cee8c9803ea0ad153ab6a3b956baa5d4cd993405dc0b45b2a0b9e0", size = 251178, upload-time = "2025-08-17T00:24:56.353Z" }, + { url = "https://files.pythonhosted.org/packages/9a/bc/f63b56a58ad0bec68a840e7be6b7ed9d6f6288d790760647bb88f5fea41e/coverage-7.10.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0a5f2ab6e451d4b07855d8bcf063adf11e199bff421a4ba57f5bb95b7444ca62", size = 252313, upload-time = "2025-08-17T00:24:57.692Z" }, + { url = "https://files.pythonhosted.org/packages/2b/b6/79338f1ea27b01266f845afb4485976211264ab92407d1c307babe3592a7/coverage-7.10.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:685b67d99b945b0c221be0780c336b303a7753b3e0ec0d618c795aada25d5e7a", size = 250230, upload-time = "2025-08-17T00:24:59.293Z" }, + { url = "https://files.pythonhosted.org/packages/bc/93/3b24f1da3e0286a4dc5832427e1d448d5296f8287464b1ff4a222abeeeb5/coverage-7.10.4-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0c079027e50c2ae44da51c2e294596cbc9dbb58f7ca45b30651c7e411060fc23", size = 248351, upload-time = "2025-08-17T00:25:00.676Z" }, + { url = "https://files.pythonhosted.org/packages/de/5f/d59412f869e49dcc5b89398ef3146c8bfaec870b179cc344d27932e0554b/coverage-7.10.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3749aa72b93ce516f77cf5034d8e3c0dfd45c6e8a163a602ede2dc5f9a0bb927", size = 249788, upload-time = "2025-08-17T00:25:02.354Z" }, + { url = "https://files.pythonhosted.org/packages/cc/52/04a3b733f40a0cc7c4a5b9b010844111dbf906df3e868b13e1ce7b39ac31/coverage-7.10.4-cp312-cp312-win32.whl", hash = "sha256:fecb97b3a52fa9bcd5a7375e72fae209088faf671d39fae67261f37772d5559a", size = 219131, upload-time = "2025-08-17T00:25:03.79Z" }, + { url = "https://files.pythonhosted.org/packages/83/dd/12909fc0b83888197b3ec43a4ac7753589591c08d00d9deda4158df2734e/coverage-7.10.4-cp312-cp312-win_amd64.whl", hash = "sha256:26de58f355626628a21fe6a70e1e1fad95702dafebfb0685280962ae1449f17b", size = 219939, upload-time = "2025-08-17T00:25:05.494Z" }, + { url = "https://files.pythonhosted.org/packages/83/c7/058bb3220fdd6821bada9685eadac2940429ab3c97025ce53549ff423cc1/coverage-7.10.4-cp312-cp312-win_arm64.whl", hash = "sha256:67e8885408f8325198862bc487038a4980c9277d753cb8812510927f2176437a", size = 218572, upload-time = "2025-08-17T00:25:06.897Z" }, + { url = "https://files.pythonhosted.org/packages/46/b0/4a3662de81f2ed792a4e425d59c4ae50d8dd1d844de252838c200beed65a/coverage-7.10.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:2b8e1d2015d5dfdbf964ecef12944c0c8c55b885bb5c0467ae8ef55e0e151233", size = 216735, upload-time = "2025-08-17T00:25:08.617Z" }, + { url = "https://files.pythonhosted.org/packages/c5/e8/e2dcffea01921bfffc6170fb4406cffb763a3b43a047bbd7923566708193/coverage-7.10.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:25735c299439018d66eb2dccf54f625aceb78645687a05f9f848f6e6c751e169", size = 216982, upload-time = "2025-08-17T00:25:10.384Z" }, + { url = "https://files.pythonhosted.org/packages/9d/59/cc89bb6ac869704d2781c2f5f7957d07097c77da0e8fdd4fd50dbf2ac9c0/coverage-7.10.4-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:715c06cb5eceac4d9b7cdf783ce04aa495f6aff657543fea75c30215b28ddb74", size = 247981, upload-time = "2025-08-17T00:25:11.854Z" }, + { url = "https://files.pythonhosted.org/packages/aa/23/3da089aa177ceaf0d3f96754ebc1318597822e6387560914cc480086e730/coverage-7.10.4-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:e017ac69fac9aacd7df6dc464c05833e834dc5b00c914d7af9a5249fcccf07ef", size = 250584, upload-time = "2025-08-17T00:25:13.483Z" }, + { url = "https://files.pythonhosted.org/packages/ad/82/e8693c368535b4e5fad05252a366a1794d481c79ae0333ed943472fd778d/coverage-7.10.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bad180cc40b3fccb0f0e8c702d781492654ac2580d468e3ffc8065e38c6c2408", size = 251856, upload-time = "2025-08-17T00:25:15.27Z" }, + { url = "https://files.pythonhosted.org/packages/56/19/8b9cb13292e602fa4135b10a26ac4ce169a7fc7c285ff08bedd42ff6acca/coverage-7.10.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:becbdcd14f685fada010a5f792bf0895675ecf7481304fe159f0cd3f289550bd", size = 250015, upload-time = "2025-08-17T00:25:16.759Z" }, + { url = "https://files.pythonhosted.org/packages/10/e7/e5903990ce089527cf1c4f88b702985bd65c61ac245923f1ff1257dbcc02/coverage-7.10.4-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:0b485ca21e16a76f68060911f97ebbe3e0d891da1dbbce6af7ca1ab3f98b9097", size = 247908, upload-time = "2025-08-17T00:25:18.232Z" }, + { url = "https://files.pythonhosted.org/packages/dd/c9/7d464f116df1df7fe340669af1ddbe1a371fc60f3082ff3dc837c4f1f2ab/coverage-7.10.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6c1d098ccfe8e1e0a1ed9a0249138899948afd2978cbf48eb1cc3fcd38469690", size = 249525, upload-time = "2025-08-17T00:25:20.141Z" }, + { url = "https://files.pythonhosted.org/packages/ce/42/722e0cdbf6c19e7235c2020837d4e00f3b07820fd012201a983238cc3a30/coverage-7.10.4-cp313-cp313-win32.whl", hash = "sha256:8630f8af2ca84b5c367c3df907b1706621abe06d6929f5045fd628968d421e6e", size = 219173, upload-time = "2025-08-17T00:25:21.56Z" }, + { url = "https://files.pythonhosted.org/packages/97/7e/aa70366f8275955cd51fa1ed52a521c7fcebcc0fc279f53c8c1ee6006dfe/coverage-7.10.4-cp313-cp313-win_amd64.whl", hash = "sha256:f68835d31c421736be367d32f179e14ca932978293fe1b4c7a6a49b555dff5b2", size = 219969, upload-time = "2025-08-17T00:25:23.501Z" }, + { url = "https://files.pythonhosted.org/packages/ac/96/c39d92d5aad8fec28d4606556bfc92b6fee0ab51e4a548d9b49fb15a777c/coverage-7.10.4-cp313-cp313-win_arm64.whl", hash = "sha256:6eaa61ff6724ca7ebc5326d1fae062d85e19b38dd922d50903702e6078370ae7", size = 218601, upload-time = "2025-08-17T00:25:25.295Z" }, + { url = "https://files.pythonhosted.org/packages/79/13/34d549a6177bd80fa5db758cb6fd3057b7ad9296d8707d4ab7f480b0135f/coverage-7.10.4-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:702978108876bfb3d997604930b05fe769462cc3000150b0e607b7b444f2fd84", size = 217445, upload-time = "2025-08-17T00:25:27.129Z" }, + { url = "https://files.pythonhosted.org/packages/6a/c0/433da866359bf39bf595f46d134ff2d6b4293aeea7f3328b6898733b0633/coverage-7.10.4-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e8f978e8c5521d9c8f2086ac60d931d583fab0a16f382f6eb89453fe998e2484", size = 217676, upload-time = "2025-08-17T00:25:28.641Z" }, + { url = "https://files.pythonhosted.org/packages/7e/d7/2b99aa8737f7801fd95222c79a4ebc8c5dd4460d4bed7ef26b17a60c8d74/coverage-7.10.4-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:df0ac2ccfd19351411c45e43ab60932b74472e4648b0a9edf6a3b58846e246a9", size = 259002, upload-time = "2025-08-17T00:25:30.065Z" }, + { url = "https://files.pythonhosted.org/packages/08/cf/86432b69d57debaef5abf19aae661ba8f4fcd2882fa762e14added4bd334/coverage-7.10.4-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:73a0d1aaaa3796179f336448e1576a3de6fc95ff4f07c2d7251d4caf5d18cf8d", size = 261178, upload-time = "2025-08-17T00:25:31.517Z" }, + { url = "https://files.pythonhosted.org/packages/23/78/85176593f4aa6e869cbed7a8098da3448a50e3fac5cb2ecba57729a5220d/coverage-7.10.4-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:873da6d0ed6b3ffc0bc01f2c7e3ad7e2023751c0d8d86c26fe7322c314b031dc", size = 263402, upload-time = "2025-08-17T00:25:33.339Z" }, + { url = "https://files.pythonhosted.org/packages/88/1d/57a27b6789b79abcac0cc5805b31320d7a97fa20f728a6a7c562db9a3733/coverage-7.10.4-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:c6446c75b0e7dda5daa876a1c87b480b2b52affb972fedd6c22edf1aaf2e00ec", size = 260957, upload-time = "2025-08-17T00:25:34.795Z" }, + { url = "https://files.pythonhosted.org/packages/fa/e5/3e5ddfd42835c6def6cd5b2bdb3348da2e34c08d9c1211e91a49e9fd709d/coverage-7.10.4-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:6e73933e296634e520390c44758d553d3b573b321608118363e52113790633b9", size = 258718, upload-time = "2025-08-17T00:25:36.259Z" }, + { url = "https://files.pythonhosted.org/packages/1a/0b/d364f0f7ef111615dc4e05a6ed02cac7b6f2ac169884aa57faeae9eb5fa0/coverage-7.10.4-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:52073d4b08d2cb571234c8a71eb32af3c6923149cf644a51d5957ac128cf6aa4", size = 259848, upload-time = "2025-08-17T00:25:37.754Z" }, + { url = "https://files.pythonhosted.org/packages/10/c6/bbea60a3b309621162e53faf7fac740daaf083048ea22077418e1ecaba3f/coverage-7.10.4-cp313-cp313t-win32.whl", hash = "sha256:e24afb178f21f9ceb1aefbc73eb524769aa9b504a42b26857243f881af56880c", size = 219833, upload-time = "2025-08-17T00:25:39.252Z" }, + { url = "https://files.pythonhosted.org/packages/44/a5/f9f080d49cfb117ddffe672f21eab41bd23a46179a907820743afac7c021/coverage-7.10.4-cp313-cp313t-win_amd64.whl", hash = "sha256:be04507ff1ad206f4be3d156a674e3fb84bbb751ea1b23b142979ac9eebaa15f", size = 220897, upload-time = "2025-08-17T00:25:40.772Z" }, + { url = "https://files.pythonhosted.org/packages/46/89/49a3fc784fa73d707f603e586d84a18c2e7796707044e9d73d13260930b7/coverage-7.10.4-cp313-cp313t-win_arm64.whl", hash = "sha256:f3e3ff3f69d02b5dad67a6eac68cc9c71ae343b6328aae96e914f9f2f23a22e2", size = 219160, upload-time = "2025-08-17T00:25:42.229Z" }, + { url = "https://files.pythonhosted.org/packages/b5/22/525f84b4cbcff66024d29f6909d7ecde97223f998116d3677cfba0d115b5/coverage-7.10.4-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:a59fe0af7dd7211ba595cf7e2867458381f7e5d7b4cffe46274e0b2f5b9f4eb4", size = 216717, upload-time = "2025-08-17T00:25:43.875Z" }, + { url = "https://files.pythonhosted.org/packages/a6/58/213577f77efe44333a416d4bcb251471e7f64b19b5886bb515561b5ce389/coverage-7.10.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:3a6c35c5b70f569ee38dc3350cd14fdd0347a8b389a18bb37538cc43e6f730e6", size = 216994, upload-time = "2025-08-17T00:25:45.405Z" }, + { url = "https://files.pythonhosted.org/packages/17/85/34ac02d0985a09472f41b609a1d7babc32df87c726c7612dc93d30679b5a/coverage-7.10.4-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:acb7baf49f513554c4af6ef8e2bd6e8ac74e6ea0c7386df8b3eb586d82ccccc4", size = 248038, upload-time = "2025-08-17T00:25:46.981Z" }, + { url = "https://files.pythonhosted.org/packages/47/4f/2140305ec93642fdaf988f139813629cbb6d8efa661b30a04b6f7c67c31e/coverage-7.10.4-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:a89afecec1ed12ac13ed203238b560cbfad3522bae37d91c102e690b8b1dc46c", size = 250575, upload-time = "2025-08-17T00:25:48.613Z" }, + { url = "https://files.pythonhosted.org/packages/f2/b5/41b5784180b82a083c76aeba8f2c72ea1cb789e5382157b7dc852832aea2/coverage-7.10.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:480442727f464407d8ade6e677b7f21f3b96a9838ab541b9a28ce9e44123c14e", size = 251927, upload-time = "2025-08-17T00:25:50.881Z" }, + { url = "https://files.pythonhosted.org/packages/78/ca/c1dd063e50b71f5aea2ebb27a1c404e7b5ecf5714c8b5301f20e4e8831ac/coverage-7.10.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:a89bf193707f4a17f1ed461504031074d87f035153239f16ce86dfb8f8c7ac76", size = 249930, upload-time = "2025-08-17T00:25:52.422Z" }, + { url = "https://files.pythonhosted.org/packages/8d/66/d8907408612ffee100d731798e6090aedb3ba766ecf929df296c1a7ee4fb/coverage-7.10.4-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:3ddd912c2fc440f0fb3229e764feec85669d5d80a988ff1b336a27d73f63c818", size = 247862, upload-time = "2025-08-17T00:25:54.316Z" }, + { url = "https://files.pythonhosted.org/packages/29/db/53cd8ec8b1c9c52d8e22a25434785bfc2d1e70c0cfb4d278a1326c87f741/coverage-7.10.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:8a538944ee3a42265e61c7298aeba9ea43f31c01271cf028f437a7b4075592cf", size = 249360, upload-time = "2025-08-17T00:25:55.833Z" }, + { url = "https://files.pythonhosted.org/packages/4f/75/5ec0a28ae4a0804124ea5a5becd2b0fa3adf30967ac656711fb5cdf67c60/coverage-7.10.4-cp314-cp314-win32.whl", hash = "sha256:fd2e6002be1c62476eb862b8514b1ba7e7684c50165f2a8d389e77da6c9a2ebd", size = 219449, upload-time = "2025-08-17T00:25:57.984Z" }, + { url = "https://files.pythonhosted.org/packages/9d/ab/66e2ee085ec60672bf5250f11101ad8143b81f24989e8c0e575d16bb1e53/coverage-7.10.4-cp314-cp314-win_amd64.whl", hash = "sha256:ec113277f2b5cf188d95fb66a65c7431f2b9192ee7e6ec9b72b30bbfb53c244a", size = 220246, upload-time = "2025-08-17T00:25:59.868Z" }, + { url = "https://files.pythonhosted.org/packages/37/3b/00b448d385f149143190846217797d730b973c3c0ec2045a7e0f5db3a7d0/coverage-7.10.4-cp314-cp314-win_arm64.whl", hash = "sha256:9744954bfd387796c6a091b50d55ca7cac3d08767795b5eec69ad0f7dbf12d38", size = 218825, upload-time = "2025-08-17T00:26:01.44Z" }, + { url = "https://files.pythonhosted.org/packages/ee/2e/55e20d3d1ce00b513efb6fd35f13899e1c6d4f76c6cbcc9851c7227cd469/coverage-7.10.4-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:5af4829904dda6aabb54a23879f0f4412094ba9ef153aaa464e3c1b1c9bc98e6", size = 217462, upload-time = "2025-08-17T00:26:03.014Z" }, + { url = "https://files.pythonhosted.org/packages/47/b3/aab1260df5876f5921e2c57519e73a6f6eeacc0ae451e109d44ee747563e/coverage-7.10.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7bba5ed85e034831fac761ae506c0644d24fd5594727e174b5a73aff343a7508", size = 217675, upload-time = "2025-08-17T00:26:04.606Z" }, + { url = "https://files.pythonhosted.org/packages/67/23/1cfe2aa50c7026180989f0bfc242168ac7c8399ccc66eb816b171e0ab05e/coverage-7.10.4-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:d57d555b0719834b55ad35045de6cc80fc2b28e05adb6b03c98479f9553b387f", size = 259176, upload-time = "2025-08-17T00:26:06.159Z" }, + { url = "https://files.pythonhosted.org/packages/9d/72/5882b6aeed3f9de7fc4049874fd7d24213bf1d06882f5c754c8a682606ec/coverage-7.10.4-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:ba62c51a72048bb1ea72db265e6bd8beaabf9809cd2125bbb5306c6ce105f214", size = 261341, upload-time = "2025-08-17T00:26:08.137Z" }, + { url = "https://files.pythonhosted.org/packages/1b/70/a0c76e3087596ae155f8e71a49c2c534c58b92aeacaf4d9d0cbbf2dde53b/coverage-7.10.4-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0acf0c62a6095f07e9db4ec365cc58c0ef5babb757e54745a1aa2ea2a2564af1", size = 263600, upload-time = "2025-08-17T00:26:11.045Z" }, + { url = "https://files.pythonhosted.org/packages/cb/5f/27e4cd4505b9a3c05257fb7fc509acbc778c830c450cb4ace00bf2b7bda7/coverage-7.10.4-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e1033bf0f763f5cf49ffe6594314b11027dcc1073ac590b415ea93463466deec", size = 261036, upload-time = "2025-08-17T00:26:12.693Z" }, + { url = "https://files.pythonhosted.org/packages/02/d6/cf2ae3a7f90ab226ea765a104c4e76c5126f73c93a92eaea41e1dc6a1892/coverage-7.10.4-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:92c29eff894832b6a40da1789b1f252305af921750b03ee4535919db9179453d", size = 258794, upload-time = "2025-08-17T00:26:14.261Z" }, + { url = "https://files.pythonhosted.org/packages/9e/b1/39f222eab0d78aa2001cdb7852aa1140bba632db23a5cfd832218b496d6c/coverage-7.10.4-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:822c4c830989c2093527e92acd97be4638a44eb042b1bdc0e7a278d84a070bd3", size = 259946, upload-time = "2025-08-17T00:26:15.899Z" }, + { url = "https://files.pythonhosted.org/packages/74/b2/49d82acefe2fe7c777436a3097f928c7242a842538b190f66aac01f29321/coverage-7.10.4-cp314-cp314t-win32.whl", hash = "sha256:e694d855dac2e7cf194ba33653e4ba7aad7267a802a7b3fc4347d0517d5d65cd", size = 220226, upload-time = "2025-08-17T00:26:17.566Z" }, + { url = "https://files.pythonhosted.org/packages/06/b0/afb942b6b2fc30bdbc7b05b087beae11c2b0daaa08e160586cf012b6ad70/coverage-7.10.4-cp314-cp314t-win_amd64.whl", hash = "sha256:efcc54b38ef7d5bfa98050f220b415bc5bb3d432bd6350a861cf6da0ede2cdcd", size = 221346, upload-time = "2025-08-17T00:26:19.311Z" }, + { url = "https://files.pythonhosted.org/packages/d8/66/e0531c9d1525cb6eac5b5733c76f27f3053ee92665f83f8899516fea6e76/coverage-7.10.4-cp314-cp314t-win_arm64.whl", hash = "sha256:6f3a3496c0fa26bfac4ebc458747b778cff201c8ae94fa05e1391bab0dbc473c", size = 219368, upload-time = "2025-08-17T00:26:21.011Z" }, + { url = "https://files.pythonhosted.org/packages/d1/61/4e38d86d31a268778d69bb3fd1fc88e0c7a78ffdee48f2b5d9e028a3dce5/coverage-7.10.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:48fd4d52600c2a9d5622e52dfae674a7845c5e1dceaf68b88c99feb511fbcfd6", size = 216393, upload-time = "2025-08-17T00:26:22.648Z" }, + { url = "https://files.pythonhosted.org/packages/17/16/5c2fdb1d213f57e0ff107738397aff68582fa90a6575ca165b49eae5a809/coverage-7.10.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:56217b470d09d69e6b7dcae38200f95e389a77db801cb129101697a4553b18b6", size = 216779, upload-time = "2025-08-17T00:26:24.422Z" }, + { url = "https://files.pythonhosted.org/packages/26/99/3aca6b4028e3667ccfbaef9cfd9dca8d85eb14deee7868373cc48cbee553/coverage-7.10.4-cp39-cp39-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:44ac3f21a6e28c5ff7f7a47bca5f87885f6a1e623e637899125ba47acd87334d", size = 243214, upload-time = "2025-08-17T00:26:26.468Z" }, + { url = "https://files.pythonhosted.org/packages/0d/33/27a7d2557f85001b2edb6a2f14037851f87ca7d69a4ca79460e1859f4c7f/coverage-7.10.4-cp39-cp39-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:3387739d72c84d17b4d2f7348749cac2e6700e7152026912b60998ee9a40066b", size = 245037, upload-time = "2025-08-17T00:26:28.071Z" }, + { url = "https://files.pythonhosted.org/packages/6d/68/92c0e18d36d34c774cb5053c9413188c27f8b3f9587e315193a30c1695ce/coverage-7.10.4-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3f111ff20d9a6348e0125be892608e33408dd268f73b020940dfa8511ad05503", size = 246809, upload-time = "2025-08-17T00:26:29.828Z" }, + { url = "https://files.pythonhosted.org/packages/03/22/f0618594010903401e782459c100755af3f275ea86d49b0d4f3afa3658d9/coverage-7.10.4-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:01a852f0a9859734b018a3f483cc962d0b381d48d350b1a0c47d618c73a0c398", size = 244695, upload-time = "2025-08-17T00:26:31.495Z" }, + { url = "https://files.pythonhosted.org/packages/e5/45/e704923a037a4a38a3c13ae6405c31236db2d274307ab28fd1a23b961cad/coverage-7.10.4-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:225111dd06759ba4e37cee4c0b4f3df2b15c879e9e3c37bf986389300b9917c3", size = 242766, upload-time = "2025-08-17T00:26:33.425Z" }, + { url = "https://files.pythonhosted.org/packages/e4/b7/4dc6f2b41aa907ae330ed841deb49c9487f6ec5072a577fc3a3b284fe855/coverage-7.10.4-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:2178d4183bd1ba608f0bb12e71e55838ba1b7dbb730264f8b08de9f8ef0c27d0", size = 243723, upload-time = "2025-08-17T00:26:35.688Z" }, + { url = "https://files.pythonhosted.org/packages/b7/62/0e58abc2ce2d9a5b906dd1c08802864f756365843c413aebf0184148ddfb/coverage-7.10.4-cp39-cp39-win32.whl", hash = "sha256:93d175fe81913aee7a6ea430abbdf2a79f1d9fd451610e12e334e4fe3264f563", size = 218927, upload-time = "2025-08-17T00:26:37.725Z" }, + { url = "https://files.pythonhosted.org/packages/a4/3e/4668a5b5601450d9c8aa71cc4f7e6c6c259350e577c758b894443598322a/coverage-7.10.4-cp39-cp39-win_amd64.whl", hash = "sha256:2221a823404bb941c7721cf0ef55ac6ee5c25d905beb60c0bba5e5e85415d353", size = 219838, upload-time = "2025-08-17T00:26:39.786Z" }, + { url = "https://files.pythonhosted.org/packages/bb/78/983efd23200921d9edb6bd40512e1aa04af553d7d5a171e50f9b2b45d109/coverage-7.10.4-py3-none-any.whl", hash = "sha256:065d75447228d05121e5c938ca8f0e91eed60a1eb2d1258d42d5084fecfc3302", size = 208365, upload-time = "2025-08-17T00:26:41.479Z" }, ] [package.optional-dependencies] @@ -477,6 +611,18 @@ toml = [ { name = "tomli", marker = "python_full_version <= '3.11'" }, ] +[[package]] +name = "cssutils" +version = "2.11.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "more-itertools" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/33/9f/329d26121fe165be44b1dfff21aa0dc348f04633931f1d20ed6cf448a236/cssutils-2.11.1.tar.gz", hash = "sha256:0563a76513b6af6eebbe788c3bf3d01c920e46b3f90c8416738c5cfc773ff8e2", size = 711657, upload-time = "2024-06-04T15:51:39.373Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a7/ec/bb273b7208c606890dc36540fe667d06ce840a6f62f9fae7e658fcdc90fb/cssutils-2.11.1-py3-none-any.whl", hash = "sha256:a67bfdfdff4f3867fab43698ec4897c1a828eca5973f4073321b3bccaf1199b1", size = 385747, upload-time = "2024-06-04T15:51:37.499Z" }, +] + [[package]] name = "decli" version = "0.6.3" @@ -498,6 +644,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/02/c3/253a89ee03fc9b9682f1541728eb66db7db22148cd94f89ab22528cd1e1b/deprecation-2.1.0-py2.py3-none-any.whl", hash = "sha256:a10811591210e1fb0e768a8c25517cabeabcba6f0bf96564f8ff45189f90b14a", size = 11178, upload-time = "2020-04-20T14:23:36.581Z" }, ] +[[package]] +name = "dict2css" +version = "0.3.0.post1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cssutils" }, + { name = "domdf-python-tools" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/24/eb/776eef1f1aa0188c0fc165c3a60b71027539f71f2eedc43ad21b060e9c39/dict2css-0.3.0.post1.tar.gz", hash = "sha256:89c544c21c4ca7472c3fffb9d37d3d926f606329afdb751dc1de67a411b70719", size = 7845, upload-time = "2023-11-22T11:09:20.958Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fe/47/290daabcf91628f4fc0e17c75a1690b354ba067066cd14407712600e609f/dict2css-0.3.0.post1-py3-none-any.whl", hash = "sha256:f006a6b774c3e31869015122ae82c491fd25e7de4a75607a62aa3e798f837e0d", size = 25647, upload-time = "2023-11-22T11:09:19.221Z" }, +] + [[package]] name = "distlib" version = "0.4.0" @@ -512,7 +671,8 @@ name = "docstring-to-markdown" version = "0.17" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "importlib-metadata" }, + { name = "importlib-metadata", version = "8.6.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "importlib-metadata", version = "8.7.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "typing-extensions" }, ] sdist = { url = "https://files.pythonhosted.org/packages/52/d8/8abe80d62c5dce1075578031bcfde07e735bcf0afe2886dd48b470162ab4/docstring_to_markdown-0.17.tar.gz", hash = "sha256:df72a112294c7492487c9da2451cae0faeee06e86008245c188c5761c9590ca3", size = 32260, upload-time = "2025-05-02T15:09:07.932Z" } @@ -520,12 +680,34 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/56/7b/af3d0da15bed3a8665419bb3a630585756920f4ad67abfdfef26240ebcc0/docstring_to_markdown-0.17-py3-none-any.whl", hash = "sha256:fd7d5094aa83943bf5f9e1a13701866b7c452eac19765380dead666e36d3711c", size = 23479, upload-time = "2025-05-02T15:09:06.676Z" }, ] +[[package]] +name = "docutils" +version = "0.21.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ae/ed/aefcc8cd0ba62a0560c3c18c33925362d46c6075480bfa4df87b28e169a9/docutils-0.21.2.tar.gz", hash = "sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f", size = 2204444, upload-time = "2024-04-23T18:57:18.24Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8f/d7/9322c609343d929e75e7e5e6255e614fcc67572cfd083959cdef3b7aad79/docutils-0.21.2-py3-none-any.whl", hash = "sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2", size = 587408, upload-time = "2024-04-23T18:57:14.835Z" }, +] + +[[package]] +name = "domdf-python-tools" +version = "3.10.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "natsort" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/36/8b/ab2d8a292bba8fe3135cacc8bfd3576710a14b8f2d0a8cde19130d5c9d21/domdf_python_tools-3.10.0.tar.gz", hash = "sha256:2ae308d2f4f1e9145f5f4ba57f840fbfd1c2983ee26e4824347789649d3ae298", size = 100458, upload-time = "2025-02-12T17:34:05.747Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5b/11/208f72084084d3f6a2ed5ebfdfc846692c3f7ad6dce65e400194924f7eed/domdf_python_tools-3.10.0-py3-none-any.whl", hash = "sha256:5e71c1be71bbcc1f881d690c8984b60e64298ec256903b3147f068bc33090c36", size = 126860, upload-time = "2025-02-12T17:34:04.093Z" }, +] + [[package]] name = "exceptiongroup" version = "1.3.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions", marker = "python_full_version < '3.13'" }, + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/0b/9f/a65090624ecf468cdca03533906e7c69ed7588582240cfe7cc9e770b50eb/exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88", size = 29749, upload-time = "2025-05-10T17:42:51.123Z" } wheels = [ @@ -534,11 +716,11 @@ wheels = [ [[package]] name = "filelock" -version = "3.18.0" +version = "3.19.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/0a/10/c23352565a6544bdc5353e0b15fc1c563352101f30e24bf500207a54df9a/filelock-3.18.0.tar.gz", hash = "sha256:adbc88eabb99d2fec8c9c1b229b171f18afa655400173ddc653d5d01501fb9f2", size = 18075, upload-time = "2025-03-14T07:11:40.47Z" } +sdist = { url = "https://files.pythonhosted.org/packages/40/bb/0ab3e58d22305b6f5440629d20683af28959bf793d98d11950e305c1c326/filelock-3.19.1.tar.gz", hash = "sha256:66eda1888b0171c998b35be2bcc0f6d75c388a7ce20c3f3f37aa8e96c2dddf58", size = 17687, upload-time = "2025-08-14T16:56:03.016Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/4d/36/2a115987e2d8c300a974597416d9de88f2444426de9571f4b59b2cca3acc/filelock-3.18.0-py3-none-any.whl", hash = "sha256:c401f4f8377c4464e6db25fff06205fd89bdd83b65eb0488ed1b160f780e21de", size = 16215, upload-time = "2025-03-14T07:11:39.145Z" }, + { url = "https://files.pythonhosted.org/packages/42/14/42b2651a2f46b022ccd948bca9f2d5af0fd8929c4eec235b8d6d844fbe67/filelock-3.19.1-py3-none-any.whl", hash = "sha256:d38e30481def20772f5baf097c122c3babc4fcdb7e14e57049eb9d88c6dc017d", size = 15988, upload-time = "2025-08-14T16:56:01.633Z" }, ] [[package]] @@ -683,6 +865,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/07/c6/80c95b1b2b94682a72cbdbfb85b81ae2daffa4291fbfa1b1464502ede10d/hpack-4.1.0-py3-none-any.whl", hash = "sha256:157ac792668d995c657d93111f46b4535ed114f0c9c8d672271bbec7eae1b496", size = 34357, upload-time = "2025-01-22T21:44:56.92Z" }, ] +[[package]] +name = "html5lib" +version = "1.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "six" }, + { name = "webencodings" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ac/b6/b55c3f49042f1df3dcd422b7f224f939892ee94f22abcf503a9b7339eaf2/html5lib-1.1.tar.gz", hash = "sha256:b2e5b40261e20f354d198eae92afc10d750afb487ed5e50f9c4eaf07c184146f", size = 272215, upload-time = "2020-06-22T23:32:38.834Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6c/dd/a834df6482147d48e225a49515aabc28974ad5a4ca3215c18a882565b028/html5lib-1.1-py2.py3-none-any.whl", hash = "sha256:0d78f8fde1c230e99fe37986a60526d7049ed4bf8a9fadbad5f00e22e58e041d", size = 112173, upload-time = "2020-06-22T23:32:36.781Z" }, +] + [[package]] name = "httpcore" version = "1.0.9" @@ -727,11 +922,11 @@ wheels = [ [[package]] name = "identify" -version = "2.6.12" +version = "2.6.13" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a2/88/d193a27416618628a5eea64e3223acd800b40749a96ffb322a9b55a49ed1/identify-2.6.12.tar.gz", hash = "sha256:d8de45749f1efb108badef65ee8386f0f7bb19a7f26185f74de6367bffbaf0e6", size = 99254, upload-time = "2025-05-23T20:37:53.3Z" } +sdist = { url = "https://files.pythonhosted.org/packages/82/ca/ffbabe3635bb839aa36b3a893c91a9b0d368cb4d8073e03a12896970af82/identify-2.6.13.tar.gz", hash = "sha256:da8d6c828e773620e13bfa86ea601c5a5310ba4bcd65edf378198b56a1f9fb32", size = 99243, upload-time = "2025-08-09T19:35:00.6Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/7a/cd/18f8da995b658420625f7ef13f037be53ae04ec5ad33f9b718240dcfd48c/identify-2.6.12-py2.py3-none-any.whl", hash = "sha256:ad9672d5a72e0d2ff7c5c8809b62dfa60458626352fb0eb7b55e69bdc45334a2", size = 99145, upload-time = "2025-05-23T20:37:51.495Z" }, + { url = "https://files.pythonhosted.org/packages/e7/ce/461b60a3ee109518c055953729bf9ed089a04db895d47e95444071dcdef2/identify-2.6.13-py2.py3-none-any.whl", hash = "sha256:60381139b3ae39447482ecc406944190f690d4a2997f2584062089848361b33b", size = 99153, upload-time = "2025-08-09T19:34:59.1Z" }, ] [[package]] @@ -743,18 +938,47 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442, upload-time = "2024-09-15T18:07:37.964Z" }, ] +[[package]] +name = "imagesize" +version = "1.4.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a7/84/62473fb57d61e31fef6e36d64a179c8781605429fd927b5dd608c997be31/imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a", size = 1280026, upload-time = "2022-07-01T12:21:05.687Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ff/62/85c4c919272577931d407be5ba5d71c20f0b616d31a0befe0ae45bb79abd/imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b", size = 8769, upload-time = "2022-07-01T12:21:02.467Z" }, +] + [[package]] name = "importlib-metadata" version = "8.6.1" source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.10'", +] dependencies = [ - { name = "zipp" }, + { name = "zipp", marker = "python_full_version < '3.10'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/33/08/c1395a292bb23fd03bdf572a1357c5a733d3eecbab877641ceacab23db6e/importlib_metadata-8.6.1.tar.gz", hash = "sha256:310b41d755445d74569f993ccfc22838295d9fe005425094fad953d7f15c8580", size = 55767, upload-time = "2025-01-20T22:21:30.429Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/79/9d/0fb148dc4d6fa4a7dd1d8378168d9b4cd8d4560a6fbf6f0121c5fc34eb68/importlib_metadata-8.6.1-py3-none-any.whl", hash = "sha256:02a89390c1e15fdfdc0d7c6b25cb3e62650d0494005c97d6f148bf5b9787525e", size = 26971, upload-time = "2025-01-20T22:21:29.177Z" }, ] +[[package]] +name = "importlib-metadata" +version = "8.7.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.13'", + "python_full_version >= '3.11' and python_full_version < '3.13'", + "python_full_version == '3.10.*'", +] +dependencies = [ + { name = "zipp", marker = "python_full_version >= '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/76/66/650a33bd90f786193e4de4b3ad86ea60b53c89b669a5c7be931fac31cdb0/importlib_metadata-8.7.0.tar.gz", hash = "sha256:d13b81ad223b890aa16c5471f2ac3056cf76c5f10f82d6f9292f0b415f389000", size = 56641, upload-time = "2025-04-27T15:29:01.736Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/20/b0/36bd937216ec521246249be3bf9855081de4c5e06a0c9b4219dbeda50373/importlib_metadata-8.7.0-py3-none-any.whl", hash = "sha256:e5dd1551894c77868a30651cef00984d50e1002d06942a7101d34870c5f02afd", size = 27656, upload-time = "2025-04-27T15:29:00.214Z" }, +] + [[package]] name = "iniconfig" version = "2.1.0" @@ -869,124 +1093,191 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b3/73/085399401383ce949f727afec55ec3abd76648d04b9f22e1c0e99cb4bec3/MarkupSafe-3.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:6e296a513ca3d94054c2c881cc913116e90fd030ad1c656b3869762b754f5f8a", size = 15506, upload-time = "2024-10-18T15:21:52.974Z" }, ] +[[package]] +name = "more-itertools" +version = "10.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ce/a0/834b0cebabbfc7e311f30b46c8188790a37f89fc8d756660346fe5abfd09/more_itertools-10.7.0.tar.gz", hash = "sha256:9fddd5403be01a94b204faadcff459ec3568cf110265d3c54323e1e866ad29d3", size = 127671, upload-time = "2025-04-22T14:17:41.838Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2b/9f/7ba6f94fc1e9ac3d2b853fdff3035fb2fa5afbed898c4a72b8a020610594/more_itertools-10.7.0-py3-none-any.whl", hash = "sha256:d43980384673cb07d2f7d2d918c616b30c659c089ee23953f601d6609c67510e", size = 65278, upload-time = "2025-04-22T14:17:40.49Z" }, +] + +[[package]] +name = "msgpack" +version = "1.1.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/45/b1/ea4f68038a18c77c9467400d166d74c4ffa536f34761f7983a104357e614/msgpack-1.1.1.tar.gz", hash = "sha256:77b79ce34a2bdab2594f490c8e80dd62a02d650b91a75159a63ec413b8d104cd", size = 173555, upload-time = "2025-06-13T06:52:51.324Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/33/52/f30da112c1dc92cf64f57d08a273ac771e7b29dea10b4b30369b2d7e8546/msgpack-1.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:353b6fc0c36fde68b661a12949d7d49f8f51ff5fa019c1e47c87c4ff34b080ed", size = 81799, upload-time = "2025-06-13T06:51:37.228Z" }, + { url = "https://files.pythonhosted.org/packages/e4/35/7bfc0def2f04ab4145f7f108e3563f9b4abae4ab0ed78a61f350518cc4d2/msgpack-1.1.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:79c408fcf76a958491b4e3b103d1c417044544b68e96d06432a189b43d1215c8", size = 78278, upload-time = "2025-06-13T06:51:38.534Z" }, + { url = "https://files.pythonhosted.org/packages/e8/c5/df5d6c1c39856bc55f800bf82778fd4c11370667f9b9e9d51b2f5da88f20/msgpack-1.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:78426096939c2c7482bf31ef15ca219a9e24460289c00dd0b94411040bb73ad2", size = 402805, upload-time = "2025-06-13T06:51:39.538Z" }, + { url = "https://files.pythonhosted.org/packages/20/8e/0bb8c977efecfe6ea7116e2ed73a78a8d32a947f94d272586cf02a9757db/msgpack-1.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8b17ba27727a36cb73aabacaa44b13090feb88a01d012c0f4be70c00f75048b4", size = 408642, upload-time = "2025-06-13T06:51:41.092Z" }, + { url = "https://files.pythonhosted.org/packages/59/a1/731d52c1aeec52006be6d1f8027c49fdc2cfc3ab7cbe7c28335b2910d7b6/msgpack-1.1.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7a17ac1ea6ec3c7687d70201cfda3b1e8061466f28f686c24f627cae4ea8efd0", size = 395143, upload-time = "2025-06-13T06:51:42.575Z" }, + { url = "https://files.pythonhosted.org/packages/2b/92/b42911c52cda2ba67a6418ffa7d08969edf2e760b09015593c8a8a27a97d/msgpack-1.1.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:88d1e966c9235c1d4e2afac21ca83933ba59537e2e2727a999bf3f515ca2af26", size = 395986, upload-time = "2025-06-13T06:51:43.807Z" }, + { url = "https://files.pythonhosted.org/packages/61/dc/8ae165337e70118d4dab651b8b562dd5066dd1e6dd57b038f32ebc3e2f07/msgpack-1.1.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:f6d58656842e1b2ddbe07f43f56b10a60f2ba5826164910968f5933e5178af75", size = 402682, upload-time = "2025-06-13T06:51:45.534Z" }, + { url = "https://files.pythonhosted.org/packages/58/27/555851cb98dcbd6ce041df1eacb25ac30646575e9cd125681aa2f4b1b6f1/msgpack-1.1.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:96decdfc4adcbc087f5ea7ebdcfd3dee9a13358cae6e81d54be962efc38f6338", size = 406368, upload-time = "2025-06-13T06:51:46.97Z" }, + { url = "https://files.pythonhosted.org/packages/d4/64/39a26add4ce16f24e99eabb9005e44c663db00e3fce17d4ae1ae9d61df99/msgpack-1.1.1-cp310-cp310-win32.whl", hash = "sha256:6640fd979ca9a212e4bcdf6eb74051ade2c690b862b679bfcb60ae46e6dc4bfd", size = 65004, upload-time = "2025-06-13T06:51:48.582Z" }, + { url = "https://files.pythonhosted.org/packages/7d/18/73dfa3e9d5d7450d39debde5b0d848139f7de23bd637a4506e36c9800fd6/msgpack-1.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:8b65b53204fe1bd037c40c4148d00ef918eb2108d24c9aaa20bc31f9810ce0a8", size = 71548, upload-time = "2025-06-13T06:51:49.558Z" }, + { url = "https://files.pythonhosted.org/packages/7f/83/97f24bf9848af23fe2ba04380388216defc49a8af6da0c28cc636d722502/msgpack-1.1.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:71ef05c1726884e44f8b1d1773604ab5d4d17729d8491403a705e649116c9558", size = 82728, upload-time = "2025-06-13T06:51:50.68Z" }, + { url = "https://files.pythonhosted.org/packages/aa/7f/2eaa388267a78401f6e182662b08a588ef4f3de6f0eab1ec09736a7aaa2b/msgpack-1.1.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:36043272c6aede309d29d56851f8841ba907a1a3d04435e43e8a19928e243c1d", size = 79279, upload-time = "2025-06-13T06:51:51.72Z" }, + { url = "https://files.pythonhosted.org/packages/f8/46/31eb60f4452c96161e4dfd26dbca562b4ec68c72e4ad07d9566d7ea35e8a/msgpack-1.1.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a32747b1b39c3ac27d0670122b57e6e57f28eefb725e0b625618d1b59bf9d1e0", size = 423859, upload-time = "2025-06-13T06:51:52.749Z" }, + { url = "https://files.pythonhosted.org/packages/45/16/a20fa8c32825cc7ae8457fab45670c7a8996d7746ce80ce41cc51e3b2bd7/msgpack-1.1.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8a8b10fdb84a43e50d38057b06901ec9da52baac6983d3f709d8507f3889d43f", size = 429975, upload-time = "2025-06-13T06:51:53.97Z" }, + { url = "https://files.pythonhosted.org/packages/86/ea/6c958e07692367feeb1a1594d35e22b62f7f476f3c568b002a5ea09d443d/msgpack-1.1.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ba0c325c3f485dc54ec298d8b024e134acf07c10d494ffa24373bea729acf704", size = 413528, upload-time = "2025-06-13T06:51:55.507Z" }, + { url = "https://files.pythonhosted.org/packages/75/05/ac84063c5dae79722bda9f68b878dc31fc3059adb8633c79f1e82c2cd946/msgpack-1.1.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:88daaf7d146e48ec71212ce21109b66e06a98e5e44dca47d853cbfe171d6c8d2", size = 413338, upload-time = "2025-06-13T06:51:57.023Z" }, + { url = "https://files.pythonhosted.org/packages/69/e8/fe86b082c781d3e1c09ca0f4dacd457ede60a13119b6ce939efe2ea77b76/msgpack-1.1.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:d8b55ea20dc59b181d3f47103f113e6f28a5e1c89fd5b67b9140edb442ab67f2", size = 422658, upload-time = "2025-06-13T06:51:58.419Z" }, + { url = "https://files.pythonhosted.org/packages/3b/2b/bafc9924df52d8f3bb7c00d24e57be477f4d0f967c0a31ef5e2225e035c7/msgpack-1.1.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4a28e8072ae9779f20427af07f53bbb8b4aa81151054e882aee333b158da8752", size = 427124, upload-time = "2025-06-13T06:51:59.969Z" }, + { url = "https://files.pythonhosted.org/packages/a2/3b/1f717e17e53e0ed0b68fa59e9188f3f610c79d7151f0e52ff3cd8eb6b2dc/msgpack-1.1.1-cp311-cp311-win32.whl", hash = "sha256:7da8831f9a0fdb526621ba09a281fadc58ea12701bc709e7b8cbc362feabc295", size = 65016, upload-time = "2025-06-13T06:52:01.294Z" }, + { url = "https://files.pythonhosted.org/packages/48/45/9d1780768d3b249accecc5a38c725eb1e203d44a191f7b7ff1941f7df60c/msgpack-1.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:5fd1b58e1431008a57247d6e7cc4faa41c3607e8e7d4aaf81f7c29ea013cb458", size = 72267, upload-time = "2025-06-13T06:52:02.568Z" }, + { url = "https://files.pythonhosted.org/packages/e3/26/389b9c593eda2b8551b2e7126ad3a06af6f9b44274eb3a4f054d48ff7e47/msgpack-1.1.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ae497b11f4c21558d95de9f64fff7053544f4d1a17731c866143ed6bb4591238", size = 82359, upload-time = "2025-06-13T06:52:03.909Z" }, + { url = "https://files.pythonhosted.org/packages/ab/65/7d1de38c8a22cf8b1551469159d4b6cf49be2126adc2482de50976084d78/msgpack-1.1.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:33be9ab121df9b6b461ff91baac6f2731f83d9b27ed948c5b9d1978ae28bf157", size = 79172, upload-time = "2025-06-13T06:52:05.246Z" }, + { url = "https://files.pythonhosted.org/packages/0f/bd/cacf208b64d9577a62c74b677e1ada005caa9b69a05a599889d6fc2ab20a/msgpack-1.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6f64ae8fe7ffba251fecb8408540c34ee9df1c26674c50c4544d72dbf792e5ce", size = 425013, upload-time = "2025-06-13T06:52:06.341Z" }, + { url = "https://files.pythonhosted.org/packages/4d/ec/fd869e2567cc9c01278a736cfd1697941ba0d4b81a43e0aa2e8d71dab208/msgpack-1.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a494554874691720ba5891c9b0b39474ba43ffb1aaf32a5dac874effb1619e1a", size = 426905, upload-time = "2025-06-13T06:52:07.501Z" }, + { url = "https://files.pythonhosted.org/packages/55/2a/35860f33229075bce803a5593d046d8b489d7ba2fc85701e714fc1aaf898/msgpack-1.1.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cb643284ab0ed26f6957d969fe0dd8bb17beb567beb8998140b5e38a90974f6c", size = 407336, upload-time = "2025-06-13T06:52:09.047Z" }, + { url = "https://files.pythonhosted.org/packages/8c/16/69ed8f3ada150bf92745fb4921bd621fd2cdf5a42e25eb50bcc57a5328f0/msgpack-1.1.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d275a9e3c81b1093c060c3837e580c37f47c51eca031f7b5fb76f7b8470f5f9b", size = 409485, upload-time = "2025-06-13T06:52:10.382Z" }, + { url = "https://files.pythonhosted.org/packages/c6/b6/0c398039e4c6d0b2e37c61d7e0e9d13439f91f780686deb8ee64ecf1ae71/msgpack-1.1.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:4fd6b577e4541676e0cc9ddc1709d25014d3ad9a66caa19962c4f5de30fc09ef", size = 412182, upload-time = "2025-06-13T06:52:11.644Z" }, + { url = "https://files.pythonhosted.org/packages/b8/d0/0cf4a6ecb9bc960d624c93effaeaae75cbf00b3bc4a54f35c8507273cda1/msgpack-1.1.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:bb29aaa613c0a1c40d1af111abf025f1732cab333f96f285d6a93b934738a68a", size = 419883, upload-time = "2025-06-13T06:52:12.806Z" }, + { url = "https://files.pythonhosted.org/packages/62/83/9697c211720fa71a2dfb632cad6196a8af3abea56eece220fde4674dc44b/msgpack-1.1.1-cp312-cp312-win32.whl", hash = "sha256:870b9a626280c86cff9c576ec0d9cbcc54a1e5ebda9cd26dab12baf41fee218c", size = 65406, upload-time = "2025-06-13T06:52:14.271Z" }, + { url = "https://files.pythonhosted.org/packages/c0/23/0abb886e80eab08f5e8c485d6f13924028602829f63b8f5fa25a06636628/msgpack-1.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:5692095123007180dca3e788bb4c399cc26626da51629a31d40207cb262e67f4", size = 72558, upload-time = "2025-06-13T06:52:15.252Z" }, + { url = "https://files.pythonhosted.org/packages/a1/38/561f01cf3577430b59b340b51329803d3a5bf6a45864a55f4ef308ac11e3/msgpack-1.1.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:3765afa6bd4832fc11c3749be4ba4b69a0e8d7b728f78e68120a157a4c5d41f0", size = 81677, upload-time = "2025-06-13T06:52:16.64Z" }, + { url = "https://files.pythonhosted.org/packages/09/48/54a89579ea36b6ae0ee001cba8c61f776451fad3c9306cd80f5b5c55be87/msgpack-1.1.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8ddb2bcfd1a8b9e431c8d6f4f7db0773084e107730ecf3472f1dfe9ad583f3d9", size = 78603, upload-time = "2025-06-13T06:52:17.843Z" }, + { url = "https://files.pythonhosted.org/packages/a0/60/daba2699b308e95ae792cdc2ef092a38eb5ee422f9d2fbd4101526d8a210/msgpack-1.1.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:196a736f0526a03653d829d7d4c5500a97eea3648aebfd4b6743875f28aa2af8", size = 420504, upload-time = "2025-06-13T06:52:18.982Z" }, + { url = "https://files.pythonhosted.org/packages/20/22/2ebae7ae43cd8f2debc35c631172ddf14e2a87ffcc04cf43ff9df9fff0d3/msgpack-1.1.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d592d06e3cc2f537ceeeb23d38799c6ad83255289bb84c2e5792e5a8dea268a", size = 423749, upload-time = "2025-06-13T06:52:20.211Z" }, + { url = "https://files.pythonhosted.org/packages/40/1b/54c08dd5452427e1179a40b4b607e37e2664bca1c790c60c442c8e972e47/msgpack-1.1.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4df2311b0ce24f06ba253fda361f938dfecd7b961576f9be3f3fbd60e87130ac", size = 404458, upload-time = "2025-06-13T06:52:21.429Z" }, + { url = "https://files.pythonhosted.org/packages/2e/60/6bb17e9ffb080616a51f09928fdd5cac1353c9becc6c4a8abd4e57269a16/msgpack-1.1.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e4141c5a32b5e37905b5940aacbc59739f036930367d7acce7a64e4dec1f5e0b", size = 405976, upload-time = "2025-06-13T06:52:22.995Z" }, + { url = "https://files.pythonhosted.org/packages/ee/97/88983e266572e8707c1f4b99c8fd04f9eb97b43f2db40e3172d87d8642db/msgpack-1.1.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b1ce7f41670c5a69e1389420436f41385b1aa2504c3b0c30620764b15dded2e7", size = 408607, upload-time = "2025-06-13T06:52:24.152Z" }, + { url = "https://files.pythonhosted.org/packages/bc/66/36c78af2efaffcc15a5a61ae0df53a1d025f2680122e2a9eb8442fed3ae4/msgpack-1.1.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4147151acabb9caed4e474c3344181e91ff7a388b888f1e19ea04f7e73dc7ad5", size = 424172, upload-time = "2025-06-13T06:52:25.704Z" }, + { url = "https://files.pythonhosted.org/packages/8c/87/a75eb622b555708fe0427fab96056d39d4c9892b0c784b3a721088c7ee37/msgpack-1.1.1-cp313-cp313-win32.whl", hash = "sha256:500e85823a27d6d9bba1d057c871b4210c1dd6fb01fbb764e37e4e8847376323", size = 65347, upload-time = "2025-06-13T06:52:26.846Z" }, + { url = "https://files.pythonhosted.org/packages/ca/91/7dc28d5e2a11a5ad804cf2b7f7a5fcb1eb5a4966d66a5d2b41aee6376543/msgpack-1.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:6d489fba546295983abd142812bda76b57e33d0b9f5d5b71c09a583285506f69", size = 72341, upload-time = "2025-06-13T06:52:27.835Z" }, + { url = "https://files.pythonhosted.org/packages/1f/bd/0792be119d7fe7dc2148689ef65c90507d82d20a204aab3b98c74a1f8684/msgpack-1.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f5be6b6bc52fad84d010cb45433720327ce886009d862f46b26d4d154001994b", size = 81882, upload-time = "2025-06-13T06:52:39.316Z" }, + { url = "https://files.pythonhosted.org/packages/75/77/ce06c8e26a816ae8730a8e030d263c5289adcaff9f0476f9b270bdd7c5c2/msgpack-1.1.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3a89cd8c087ea67e64844287ea52888239cbd2940884eafd2dcd25754fb72232", size = 78414, upload-time = "2025-06-13T06:52:40.341Z" }, + { url = "https://files.pythonhosted.org/packages/73/27/190576c497677fb4a0d05d896b24aea6cdccd910f206aaa7b511901befed/msgpack-1.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d75f3807a9900a7d575d8d6674a3a47e9f227e8716256f35bc6f03fc597ffbf", size = 400927, upload-time = "2025-06-13T06:52:41.399Z" }, + { url = "https://files.pythonhosted.org/packages/ed/af/6a0aa5a06762e70726ec3c10fb966600d84a7220b52635cb0ab2dc64d32f/msgpack-1.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d182dac0221eb8faef2e6f44701812b467c02674a322c739355c39e94730cdbf", size = 405903, upload-time = "2025-06-13T06:52:42.699Z" }, + { url = "https://files.pythonhosted.org/packages/1e/80/3f3da358cecbbe8eb12360814bd1277d59d2608485934742a074d99894a9/msgpack-1.1.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1b13fe0fb4aac1aa5320cd693b297fe6fdef0e7bea5518cbc2dd5299f873ae90", size = 393192, upload-time = "2025-06-13T06:52:43.986Z" }, + { url = "https://files.pythonhosted.org/packages/98/c6/3a0ec7fdebbb4f3f8f254696cd91d491c29c501dbebd86286c17e8f68cd7/msgpack-1.1.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:435807eeb1bc791ceb3247d13c79868deb22184e1fc4224808750f0d7d1affc1", size = 393851, upload-time = "2025-06-13T06:52:45.177Z" }, + { url = "https://files.pythonhosted.org/packages/39/37/df50d5f8e68514b60fbe70f6e8337ea2b32ae2be030871bcd9d1cf7d4b62/msgpack-1.1.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:4835d17af722609a45e16037bb1d4d78b7bdf19d6c0128116d178956618c4e88", size = 400292, upload-time = "2025-06-13T06:52:46.381Z" }, + { url = "https://files.pythonhosted.org/packages/fc/ec/1e067292e02d2ceb4c8cb5ba222c4f7bb28730eef5676740609dc2627e0f/msgpack-1.1.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a8ef6e342c137888ebbfb233e02b8fbd689bb5b5fcc59b34711ac47ebd504478", size = 401873, upload-time = "2025-06-13T06:52:47.957Z" }, + { url = "https://files.pythonhosted.org/packages/d3/31/e8c9c6b5b58d64c9efa99c8d181fcc25f38ead357b0360379fbc8a4234ad/msgpack-1.1.1-cp39-cp39-win32.whl", hash = "sha256:61abccf9de335d9efd149e2fff97ed5974f2481b3353772e8e2dd3402ba2bd57", size = 65028, upload-time = "2025-06-13T06:52:49.166Z" }, + { url = "https://files.pythonhosted.org/packages/20/d6/cd62cded572e5e25892747a5d27850170bcd03c855e9c69c538e024de6f9/msgpack-1.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:40eae974c873b2992fd36424a5d9407f93e97656d999f43fca9d29f820899084", size = 71700, upload-time = "2025-06-13T06:52:50.244Z" }, +] + [[package]] name = "multidict" -version = "6.6.3" +version = "6.6.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/3d/2c/5dad12e82fbdf7470f29bff2171484bf07cb3b16ada60a6589af8f376440/multidict-6.6.3.tar.gz", hash = "sha256:798a9eb12dab0a6c2e29c1de6f3468af5cb2da6053a20dfa3344907eed0937cc", size = 101006, upload-time = "2025-06-30T15:53:46.929Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/0b/67/414933982bce2efce7cbcb3169eaaf901e0f25baec69432b4874dfb1f297/multidict-6.6.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a2be5b7b35271f7fff1397204ba6708365e3d773579fe2a30625e16c4b4ce817", size = 77017, upload-time = "2025-06-30T15:50:58.931Z" }, - { url = "https://files.pythonhosted.org/packages/8a/fe/d8a3ee1fad37dc2ef4f75488b0d9d4f25bf204aad8306cbab63d97bff64a/multidict-6.6.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:12f4581d2930840295c461764b9a65732ec01250b46c6b2c510d7ee68872b140", size = 44897, upload-time = "2025-06-30T15:51:00.999Z" }, - { url = "https://files.pythonhosted.org/packages/1f/e0/265d89af8c98240265d82b8cbcf35897f83b76cd59ee3ab3879050fd8c45/multidict-6.6.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:dd7793bab517e706c9ed9d7310b06c8672fd0aeee5781bfad612f56b8e0f7d14", size = 44574, upload-time = "2025-06-30T15:51:02.449Z" }, - { url = "https://files.pythonhosted.org/packages/e6/05/6b759379f7e8e04ccc97cfb2a5dcc5cdbd44a97f072b2272dc51281e6a40/multidict-6.6.3-cp310-cp310-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:72d8815f2cd3cf3df0f83cac3f3ef801d908b2d90409ae28102e0553af85545a", size = 225729, upload-time = "2025-06-30T15:51:03.794Z" }, - { url = "https://files.pythonhosted.org/packages/4e/f5/8d5a15488edd9a91fa4aad97228d785df208ed6298580883aa3d9def1959/multidict-6.6.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:531e331a2ee53543ab32b16334e2deb26f4e6b9b28e41f8e0c87e99a6c8e2d69", size = 242515, upload-time = "2025-06-30T15:51:05.002Z" }, - { url = "https://files.pythonhosted.org/packages/6e/b5/a8f317d47d0ac5bb746d6d8325885c8967c2a8ce0bb57be5399e3642cccb/multidict-6.6.3-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:42ca5aa9329a63be8dc49040f63817d1ac980e02eeddba763a9ae5b4027b9c9c", size = 222224, upload-time = "2025-06-30T15:51:06.148Z" }, - { url = "https://files.pythonhosted.org/packages/76/88/18b2a0d5e80515fa22716556061189c2853ecf2aa2133081ebbe85ebea38/multidict-6.6.3-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:208b9b9757060b9faa6f11ab4bc52846e4f3c2fb8b14d5680c8aac80af3dc751", size = 253124, upload-time = "2025-06-30T15:51:07.375Z" }, - { url = "https://files.pythonhosted.org/packages/62/bf/ebfcfd6b55a1b05ef16d0775ae34c0fe15e8dab570d69ca9941073b969e7/multidict-6.6.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:acf6b97bd0884891af6a8b43d0f586ab2fcf8e717cbd47ab4bdddc09e20652d8", size = 251529, upload-time = "2025-06-30T15:51:08.691Z" }, - { url = "https://files.pythonhosted.org/packages/44/11/780615a98fd3775fc309d0234d563941af69ade2df0bb82c91dda6ddaea1/multidict-6.6.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:68e9e12ed00e2089725669bdc88602b0b6f8d23c0c95e52b95f0bc69f7fe9b55", size = 241627, upload-time = "2025-06-30T15:51:10.605Z" }, - { url = "https://files.pythonhosted.org/packages/28/3d/35f33045e21034b388686213752cabc3a1b9d03e20969e6fa8f1b1d82db1/multidict-6.6.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:05db2f66c9addb10cfa226e1acb363450fab2ff8a6df73c622fefe2f5af6d4e7", size = 239351, upload-time = "2025-06-30T15:51:12.18Z" }, - { url = "https://files.pythonhosted.org/packages/6e/cc/ff84c03b95b430015d2166d9aae775a3985d757b94f6635010d0038d9241/multidict-6.6.3-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:0db58da8eafb514db832a1b44f8fa7906fdd102f7d982025f816a93ba45e3dcb", size = 233429, upload-time = "2025-06-30T15:51:13.533Z" }, - { url = "https://files.pythonhosted.org/packages/2e/f0/8cd49a0b37bdea673a4b793c2093f2f4ba8e7c9d6d7c9bd672fd6d38cd11/multidict-6.6.3-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:14117a41c8fdb3ee19c743b1c027da0736fdb79584d61a766da53d399b71176c", size = 243094, upload-time = "2025-06-30T15:51:14.815Z" }, - { url = "https://files.pythonhosted.org/packages/96/19/5d9a0cfdafe65d82b616a45ae950975820289069f885328e8185e64283c2/multidict-6.6.3-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:877443eaaabcd0b74ff32ebeed6f6176c71850feb7d6a1d2db65945256ea535c", size = 248957, upload-time = "2025-06-30T15:51:16.076Z" }, - { url = "https://files.pythonhosted.org/packages/e6/dc/c90066151da87d1e489f147b9b4327927241e65f1876702fafec6729c014/multidict-6.6.3-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:70b72e749a4f6e7ed8fb334fa8d8496384840319512746a5f42fa0aec79f4d61", size = 243590, upload-time = "2025-06-30T15:51:17.413Z" }, - { url = "https://files.pythonhosted.org/packages/ec/39/458afb0cccbb0ee9164365273be3e039efddcfcb94ef35924b7dbdb05db0/multidict-6.6.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:43571f785b86afd02b3855c5ac8e86ec921b760298d6f82ff2a61daf5a35330b", size = 237487, upload-time = "2025-06-30T15:51:19.039Z" }, - { url = "https://files.pythonhosted.org/packages/35/38/0016adac3990426610a081787011177e661875546b434f50a26319dc8372/multidict-6.6.3-cp310-cp310-win32.whl", hash = "sha256:20c5a0c3c13a15fd5ea86c42311859f970070e4e24de5a550e99d7c271d76318", size = 41390, upload-time = "2025-06-30T15:51:20.362Z" }, - { url = "https://files.pythonhosted.org/packages/f3/d2/17897a8f3f2c5363d969b4c635aa40375fe1f09168dc09a7826780bfb2a4/multidict-6.6.3-cp310-cp310-win_amd64.whl", hash = "sha256:ab0a34a007704c625e25a9116c6770b4d3617a071c8a7c30cd338dfbadfe6485", size = 45954, upload-time = "2025-06-30T15:51:21.383Z" }, - { url = "https://files.pythonhosted.org/packages/2d/5f/d4a717c1e457fe44072e33fa400d2b93eb0f2819c4d669381f925b7cba1f/multidict-6.6.3-cp310-cp310-win_arm64.whl", hash = "sha256:769841d70ca8bdd140a715746199fc6473414bd02efd678d75681d2d6a8986c5", size = 42981, upload-time = "2025-06-30T15:51:22.809Z" }, - { url = "https://files.pythonhosted.org/packages/08/f0/1a39863ced51f639c81a5463fbfa9eb4df59c20d1a8769ab9ef4ca57ae04/multidict-6.6.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:18f4eba0cbac3546b8ae31e0bbc55b02c801ae3cbaf80c247fcdd89b456ff58c", size = 76445, upload-time = "2025-06-30T15:51:24.01Z" }, - { url = "https://files.pythonhosted.org/packages/c9/0e/a7cfa451c7b0365cd844e90b41e21fab32edaa1e42fc0c9f68461ce44ed7/multidict-6.6.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ef43b5dd842382329e4797c46f10748d8c2b6e0614f46b4afe4aee9ac33159df", size = 44610, upload-time = "2025-06-30T15:51:25.158Z" }, - { url = "https://files.pythonhosted.org/packages/c6/bb/a14a4efc5ee748cc1904b0748be278c31b9295ce5f4d2ef66526f410b94d/multidict-6.6.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bf9bd1fd5eec01494e0f2e8e446a74a85d5e49afb63d75a9934e4a5423dba21d", size = 44267, upload-time = "2025-06-30T15:51:26.326Z" }, - { url = "https://files.pythonhosted.org/packages/c2/f8/410677d563c2d55e063ef74fe578f9d53fe6b0a51649597a5861f83ffa15/multidict-6.6.3-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:5bd8d6f793a787153956cd35e24f60485bf0651c238e207b9a54f7458b16d539", size = 230004, upload-time = "2025-06-30T15:51:27.491Z" }, - { url = "https://files.pythonhosted.org/packages/fd/df/2b787f80059314a98e1ec6a4cc7576244986df3e56b3c755e6fc7c99e038/multidict-6.6.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1bf99b4daf908c73856bd87ee0a2499c3c9a3d19bb04b9c6025e66af3fd07462", size = 247196, upload-time = "2025-06-30T15:51:28.762Z" }, - { url = "https://files.pythonhosted.org/packages/05/f2/f9117089151b9a8ab39f9019620d10d9718eec2ac89e7ca9d30f3ec78e96/multidict-6.6.3-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:0b9e59946b49dafaf990fd9c17ceafa62976e8471a14952163d10a7a630413a9", size = 225337, upload-time = "2025-06-30T15:51:30.025Z" }, - { url = "https://files.pythonhosted.org/packages/93/2d/7115300ec5b699faa152c56799b089a53ed69e399c3c2d528251f0aeda1a/multidict-6.6.3-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e2db616467070d0533832d204c54eea6836a5e628f2cb1e6dfd8cd6ba7277cb7", size = 257079, upload-time = "2025-06-30T15:51:31.716Z" }, - { url = "https://files.pythonhosted.org/packages/15/ea/ff4bab367623e39c20d3b07637225c7688d79e4f3cc1f3b9f89867677f9a/multidict-6.6.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7394888236621f61dcdd25189b2768ae5cc280f041029a5bcf1122ac63df79f9", size = 255461, upload-time = "2025-06-30T15:51:33.029Z" }, - { url = "https://files.pythonhosted.org/packages/74/07/2c9246cda322dfe08be85f1b8739646f2c4c5113a1422d7a407763422ec4/multidict-6.6.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f114d8478733ca7388e7c7e0ab34b72547476b97009d643644ac33d4d3fe1821", size = 246611, upload-time = "2025-06-30T15:51:34.47Z" }, - { url = "https://files.pythonhosted.org/packages/a8/62/279c13d584207d5697a752a66ffc9bb19355a95f7659140cb1b3cf82180e/multidict-6.6.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:cdf22e4db76d323bcdc733514bf732e9fb349707c98d341d40ebcc6e9318ef3d", size = 243102, upload-time = "2025-06-30T15:51:36.525Z" }, - { url = "https://files.pythonhosted.org/packages/69/cc/e06636f48c6d51e724a8bc8d9e1db5f136fe1df066d7cafe37ef4000f86a/multidict-6.6.3-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:e995a34c3d44ab511bfc11aa26869b9d66c2d8c799fa0e74b28a473a692532d6", size = 238693, upload-time = "2025-06-30T15:51:38.278Z" }, - { url = "https://files.pythonhosted.org/packages/89/a4/66c9d8fb9acf3b226cdd468ed009537ac65b520aebdc1703dd6908b19d33/multidict-6.6.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:766a4a5996f54361d8d5a9050140aa5362fe48ce51c755a50c0bc3706460c430", size = 246582, upload-time = "2025-06-30T15:51:39.709Z" }, - { url = "https://files.pythonhosted.org/packages/cf/01/c69e0317be556e46257826d5449feb4e6aa0d18573e567a48a2c14156f1f/multidict-6.6.3-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:3893a0d7d28a7fe6ca7a1f760593bc13038d1d35daf52199d431b61d2660602b", size = 253355, upload-time = "2025-06-30T15:51:41.013Z" }, - { url = "https://files.pythonhosted.org/packages/c0/da/9cc1da0299762d20e626fe0042e71b5694f9f72d7d3f9678397cbaa71b2b/multidict-6.6.3-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:934796c81ea996e61914ba58064920d6cad5d99140ac3167901eb932150e2e56", size = 247774, upload-time = "2025-06-30T15:51:42.291Z" }, - { url = "https://files.pythonhosted.org/packages/e6/91/b22756afec99cc31105ddd4a52f95ab32b1a4a58f4d417979c570c4a922e/multidict-6.6.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9ed948328aec2072bc00f05d961ceadfd3e9bfc2966c1319aeaf7b7c21219183", size = 242275, upload-time = "2025-06-30T15:51:43.642Z" }, - { url = "https://files.pythonhosted.org/packages/be/f1/adcc185b878036a20399d5be5228f3cbe7f823d78985d101d425af35c800/multidict-6.6.3-cp311-cp311-win32.whl", hash = "sha256:9f5b28c074c76afc3e4c610c488e3493976fe0e596dd3db6c8ddfbb0134dcac5", size = 41290, upload-time = "2025-06-30T15:51:45.264Z" }, - { url = "https://files.pythonhosted.org/packages/e0/d4/27652c1c6526ea6b4f5ddd397e93f4232ff5de42bea71d339bc6a6cc497f/multidict-6.6.3-cp311-cp311-win_amd64.whl", hash = "sha256:bc7f6fbc61b1c16050a389c630da0b32fc6d4a3d191394ab78972bf5edc568c2", size = 45942, upload-time = "2025-06-30T15:51:46.377Z" }, - { url = "https://files.pythonhosted.org/packages/16/18/23f4932019804e56d3c2413e237f866444b774b0263bcb81df2fdecaf593/multidict-6.6.3-cp311-cp311-win_arm64.whl", hash = "sha256:d4e47d8faffaae822fb5cba20937c048d4f734f43572e7079298a6c39fb172cb", size = 42880, upload-time = "2025-06-30T15:51:47.561Z" }, - { url = "https://files.pythonhosted.org/packages/0e/a0/6b57988ea102da0623ea814160ed78d45a2645e4bbb499c2896d12833a70/multidict-6.6.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:056bebbeda16b2e38642d75e9e5310c484b7c24e3841dc0fb943206a72ec89d6", size = 76514, upload-time = "2025-06-30T15:51:48.728Z" }, - { url = "https://files.pythonhosted.org/packages/07/7a/d1e92665b0850c6c0508f101f9cf0410c1afa24973e1115fe9c6a185ebf7/multidict-6.6.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:e5f481cccb3c5c5e5de5d00b5141dc589c1047e60d07e85bbd7dea3d4580d63f", size = 45394, upload-time = "2025-06-30T15:51:49.986Z" }, - { url = "https://files.pythonhosted.org/packages/52/6f/dd104490e01be6ef8bf9573705d8572f8c2d2c561f06e3826b081d9e6591/multidict-6.6.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:10bea2ee839a759ee368b5a6e47787f399b41e70cf0c20d90dfaf4158dfb4e55", size = 43590, upload-time = "2025-06-30T15:51:51.331Z" }, - { url = "https://files.pythonhosted.org/packages/44/fe/06e0e01b1b0611e6581b7fd5a85b43dacc08b6cea3034f902f383b0873e5/multidict-6.6.3-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:2334cfb0fa9549d6ce2c21af2bfbcd3ac4ec3646b1b1581c88e3e2b1779ec92b", size = 237292, upload-time = "2025-06-30T15:51:52.584Z" }, - { url = "https://files.pythonhosted.org/packages/ce/71/4f0e558fb77696b89c233c1ee2d92f3e1d5459070a0e89153c9e9e804186/multidict-6.6.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b8fee016722550a2276ca2cb5bb624480e0ed2bd49125b2b73b7010b9090e888", size = 258385, upload-time = "2025-06-30T15:51:53.913Z" }, - { url = "https://files.pythonhosted.org/packages/e3/25/cca0e68228addad24903801ed1ab42e21307a1b4b6dd2cf63da5d3ae082a/multidict-6.6.3-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e5511cb35f5c50a2db21047c875eb42f308c5583edf96bd8ebf7d770a9d68f6d", size = 242328, upload-time = "2025-06-30T15:51:55.672Z" }, - { url = "https://files.pythonhosted.org/packages/6e/a3/46f2d420d86bbcb8fe660b26a10a219871a0fbf4d43cb846a4031533f3e0/multidict-6.6.3-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:712b348f7f449948e0a6c4564a21c7db965af900973a67db432d724619b3c680", size = 268057, upload-time = "2025-06-30T15:51:57.037Z" }, - { url = "https://files.pythonhosted.org/packages/9e/73/1c743542fe00794a2ec7466abd3f312ccb8fad8dff9f36d42e18fb1ec33e/multidict-6.6.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e4e15d2138ee2694e038e33b7c3da70e6b0ad8868b9f8094a72e1414aeda9c1a", size = 269341, upload-time = "2025-06-30T15:51:59.111Z" }, - { url = "https://files.pythonhosted.org/packages/a4/11/6ec9dcbe2264b92778eeb85407d1df18812248bf3506a5a1754bc035db0c/multidict-6.6.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8df25594989aebff8a130f7899fa03cbfcc5d2b5f4a461cf2518236fe6f15961", size = 256081, upload-time = "2025-06-30T15:52:00.533Z" }, - { url = "https://files.pythonhosted.org/packages/9b/2b/631b1e2afeb5f1696846d747d36cda075bfdc0bc7245d6ba5c319278d6c4/multidict-6.6.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:159ca68bfd284a8860f8d8112cf0521113bffd9c17568579e4d13d1f1dc76b65", size = 253581, upload-time = "2025-06-30T15:52:02.43Z" }, - { url = "https://files.pythonhosted.org/packages/bf/0e/7e3b93f79efeb6111d3bf9a1a69e555ba1d07ad1c11bceb56b7310d0d7ee/multidict-6.6.3-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:e098c17856a8c9ade81b4810888c5ad1914099657226283cab3062c0540b0643", size = 250750, upload-time = "2025-06-30T15:52:04.26Z" }, - { url = "https://files.pythonhosted.org/packages/ad/9e/086846c1d6601948e7de556ee464a2d4c85e33883e749f46b9547d7b0704/multidict-6.6.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:67c92ed673049dec52d7ed39f8cf9ebbadf5032c774058b4406d18c8f8fe7063", size = 251548, upload-time = "2025-06-30T15:52:06.002Z" }, - { url = "https://files.pythonhosted.org/packages/8c/7b/86ec260118e522f1a31550e87b23542294880c97cfbf6fb18cc67b044c66/multidict-6.6.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:bd0578596e3a835ef451784053cfd327d607fc39ea1a14812139339a18a0dbc3", size = 262718, upload-time = "2025-06-30T15:52:07.707Z" }, - { url = "https://files.pythonhosted.org/packages/8c/bd/22ce8f47abb0be04692c9fc4638508b8340987b18691aa7775d927b73f72/multidict-6.6.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:346055630a2df2115cd23ae271910b4cae40f4e336773550dca4889b12916e75", size = 259603, upload-time = "2025-06-30T15:52:09.58Z" }, - { url = "https://files.pythonhosted.org/packages/07/9c/91b7ac1691be95cd1f4a26e36a74b97cda6aa9820632d31aab4410f46ebd/multidict-6.6.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:555ff55a359302b79de97e0468e9ee80637b0de1fce77721639f7cd9440b3a10", size = 251351, upload-time = "2025-06-30T15:52:10.947Z" }, - { url = "https://files.pythonhosted.org/packages/6f/5c/4d7adc739884f7a9fbe00d1eac8c034023ef8bad71f2ebe12823ca2e3649/multidict-6.6.3-cp312-cp312-win32.whl", hash = "sha256:73ab034fb8d58ff85c2bcbadc470efc3fafeea8affcf8722855fb94557f14cc5", size = 41860, upload-time = "2025-06-30T15:52:12.334Z" }, - { url = "https://files.pythonhosted.org/packages/6a/a3/0fbc7afdf7cb1aa12a086b02959307848eb6bcc8f66fcb66c0cb57e2a2c1/multidict-6.6.3-cp312-cp312-win_amd64.whl", hash = "sha256:04cbcce84f63b9af41bad04a54d4cc4e60e90c35b9e6ccb130be2d75b71f8c17", size = 45982, upload-time = "2025-06-30T15:52:13.6Z" }, - { url = "https://files.pythonhosted.org/packages/b8/95/8c825bd70ff9b02462dc18d1295dd08d3e9e4eb66856d292ffa62cfe1920/multidict-6.6.3-cp312-cp312-win_arm64.whl", hash = "sha256:0f1130b896ecb52d2a1e615260f3ea2af55fa7dc3d7c3003ba0c3121a759b18b", size = 43210, upload-time = "2025-06-30T15:52:14.893Z" }, - { url = "https://files.pythonhosted.org/packages/52/1d/0bebcbbb4f000751fbd09957257903d6e002943fc668d841a4cf2fb7f872/multidict-6.6.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:540d3c06d48507357a7d57721e5094b4f7093399a0106c211f33540fdc374d55", size = 75843, upload-time = "2025-06-30T15:52:16.155Z" }, - { url = "https://files.pythonhosted.org/packages/07/8f/cbe241b0434cfe257f65c2b1bcf9e8d5fb52bc708c5061fb29b0fed22bdf/multidict-6.6.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:9c19cea2a690f04247d43f366d03e4eb110a0dc4cd1bbeee4d445435428ed35b", size = 45053, upload-time = "2025-06-30T15:52:17.429Z" }, - { url = "https://files.pythonhosted.org/packages/32/d2/0b3b23f9dbad5b270b22a3ac3ea73ed0a50ef2d9a390447061178ed6bdb8/multidict-6.6.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7af039820cfd00effec86bda5d8debef711a3e86a1d3772e85bea0f243a4bd65", size = 43273, upload-time = "2025-06-30T15:52:19.346Z" }, - { url = "https://files.pythonhosted.org/packages/fd/fe/6eb68927e823999e3683bc49678eb20374ba9615097d085298fd5b386564/multidict-6.6.3-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:500b84f51654fdc3944e936f2922114349bf8fdcac77c3092b03449f0e5bc2b3", size = 237124, upload-time = "2025-06-30T15:52:20.773Z" }, - { url = "https://files.pythonhosted.org/packages/e7/ab/320d8507e7726c460cb77117848b3834ea0d59e769f36fdae495f7669929/multidict-6.6.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f3fc723ab8a5c5ed6c50418e9bfcd8e6dceba6c271cee6728a10a4ed8561520c", size = 256892, upload-time = "2025-06-30T15:52:22.242Z" }, - { url = "https://files.pythonhosted.org/packages/76/60/38ee422db515ac69834e60142a1a69111ac96026e76e8e9aa347fd2e4591/multidict-6.6.3-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:94c47ea3ade005b5976789baaed66d4de4480d0a0bf31cef6edaa41c1e7b56a6", size = 240547, upload-time = "2025-06-30T15:52:23.736Z" }, - { url = "https://files.pythonhosted.org/packages/27/fb/905224fde2dff042b030c27ad95a7ae744325cf54b890b443d30a789b80e/multidict-6.6.3-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:dbc7cf464cc6d67e83e136c9f55726da3a30176f020a36ead246eceed87f1cd8", size = 266223, upload-time = "2025-06-30T15:52:25.185Z" }, - { url = "https://files.pythonhosted.org/packages/76/35/dc38ab361051beae08d1a53965e3e1a418752fc5be4d3fb983c5582d8784/multidict-6.6.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:900eb9f9da25ada070f8ee4a23f884e0ee66fe4e1a38c3af644256a508ad81ca", size = 267262, upload-time = "2025-06-30T15:52:26.969Z" }, - { url = "https://files.pythonhosted.org/packages/1f/a3/0a485b7f36e422421b17e2bbb5a81c1af10eac1d4476f2ff92927c730479/multidict-6.6.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7c6df517cf177da5d47ab15407143a89cd1a23f8b335f3a28d57e8b0a3dbb884", size = 254345, upload-time = "2025-06-30T15:52:28.467Z" }, - { url = "https://files.pythonhosted.org/packages/b4/59/bcdd52c1dab7c0e0d75ff19cac751fbd5f850d1fc39172ce809a74aa9ea4/multidict-6.6.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4ef421045f13879e21c994b36e728d8e7d126c91a64b9185810ab51d474f27e7", size = 252248, upload-time = "2025-06-30T15:52:29.938Z" }, - { url = "https://files.pythonhosted.org/packages/bb/a4/2d96aaa6eae8067ce108d4acee6f45ced5728beda55c0f02ae1072c730d1/multidict-6.6.3-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:6c1e61bb4f80895c081790b6b09fa49e13566df8fbff817da3f85b3a8192e36b", size = 250115, upload-time = "2025-06-30T15:52:31.416Z" }, - { url = "https://files.pythonhosted.org/packages/25/d2/ed9f847fa5c7d0677d4f02ea2c163d5e48573de3f57bacf5670e43a5ffaa/multidict-6.6.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:e5e8523bb12d7623cd8300dbd91b9e439a46a028cd078ca695eb66ba31adee3c", size = 249649, upload-time = "2025-06-30T15:52:32.996Z" }, - { url = "https://files.pythonhosted.org/packages/1f/af/9155850372563fc550803d3f25373308aa70f59b52cff25854086ecb4a79/multidict-6.6.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:ef58340cc896219e4e653dade08fea5c55c6df41bcc68122e3be3e9d873d9a7b", size = 261203, upload-time = "2025-06-30T15:52:34.521Z" }, - { url = "https://files.pythonhosted.org/packages/36/2f/c6a728f699896252cf309769089568a33c6439626648843f78743660709d/multidict-6.6.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:fc9dc435ec8699e7b602b94fe0cd4703e69273a01cbc34409af29e7820f777f1", size = 258051, upload-time = "2025-06-30T15:52:35.999Z" }, - { url = "https://files.pythonhosted.org/packages/d0/60/689880776d6b18fa2b70f6cc74ff87dd6c6b9b47bd9cf74c16fecfaa6ad9/multidict-6.6.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9e864486ef4ab07db5e9cb997bad2b681514158d6954dd1958dfb163b83d53e6", size = 249601, upload-time = "2025-06-30T15:52:37.473Z" }, - { url = "https://files.pythonhosted.org/packages/75/5e/325b11f2222a549019cf2ef879c1f81f94a0d40ace3ef55cf529915ba6cc/multidict-6.6.3-cp313-cp313-win32.whl", hash = "sha256:5633a82fba8e841bc5c5c06b16e21529573cd654f67fd833650a215520a6210e", size = 41683, upload-time = "2025-06-30T15:52:38.927Z" }, - { url = "https://files.pythonhosted.org/packages/b1/ad/cf46e73f5d6e3c775cabd2a05976547f3f18b39bee06260369a42501f053/multidict-6.6.3-cp313-cp313-win_amd64.whl", hash = "sha256:e93089c1570a4ad54c3714a12c2cef549dc9d58e97bcded193d928649cab78e9", size = 45811, upload-time = "2025-06-30T15:52:40.207Z" }, - { url = "https://files.pythonhosted.org/packages/c5/c9/2e3fe950db28fb7c62e1a5f46e1e38759b072e2089209bc033c2798bb5ec/multidict-6.6.3-cp313-cp313-win_arm64.whl", hash = "sha256:c60b401f192e79caec61f166da9c924e9f8bc65548d4246842df91651e83d600", size = 43056, upload-time = "2025-06-30T15:52:41.575Z" }, - { url = "https://files.pythonhosted.org/packages/3a/58/aaf8114cf34966e084a8cc9517771288adb53465188843d5a19862cb6dc3/multidict-6.6.3-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:02fd8f32d403a6ff13864b0851f1f523d4c988051eea0471d4f1fd8010f11134", size = 82811, upload-time = "2025-06-30T15:52:43.281Z" }, - { url = "https://files.pythonhosted.org/packages/71/af/5402e7b58a1f5b987a07ad98f2501fdba2a4f4b4c30cf114e3ce8db64c87/multidict-6.6.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:f3aa090106b1543f3f87b2041eef3c156c8da2aed90c63a2fbed62d875c49c37", size = 48304, upload-time = "2025-06-30T15:52:45.026Z" }, - { url = "https://files.pythonhosted.org/packages/39/65/ab3c8cafe21adb45b24a50266fd747147dec7847425bc2a0f6934b3ae9ce/multidict-6.6.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e924fb978615a5e33ff644cc42e6aa241effcf4f3322c09d4f8cebde95aff5f8", size = 46775, upload-time = "2025-06-30T15:52:46.459Z" }, - { url = "https://files.pythonhosted.org/packages/49/ba/9fcc1b332f67cc0c0c8079e263bfab6660f87fe4e28a35921771ff3eea0d/multidict-6.6.3-cp313-cp313t-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:b9fe5a0e57c6dbd0e2ce81ca66272282c32cd11d31658ee9553849d91289e1c1", size = 229773, upload-time = "2025-06-30T15:52:47.88Z" }, - { url = "https://files.pythonhosted.org/packages/a4/14/0145a251f555f7c754ce2dcbcd012939bbd1f34f066fa5d28a50e722a054/multidict-6.6.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b24576f208793ebae00280c59927c3b7c2a3b1655e443a25f753c4611bc1c373", size = 250083, upload-time = "2025-06-30T15:52:49.366Z" }, - { url = "https://files.pythonhosted.org/packages/9e/d4/d5c0bd2bbb173b586c249a151a26d2fb3ec7d53c96e42091c9fef4e1f10c/multidict-6.6.3-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:135631cb6c58eac37d7ac0df380294fecdc026b28837fa07c02e459c7fb9c54e", size = 228980, upload-time = "2025-06-30T15:52:50.903Z" }, - { url = "https://files.pythonhosted.org/packages/21/32/c9a2d8444a50ec48c4733ccc67254100c10e1c8ae8e40c7a2d2183b59b97/multidict-6.6.3-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:274d416b0df887aef98f19f21578653982cfb8a05b4e187d4a17103322eeaf8f", size = 257776, upload-time = "2025-06-30T15:52:52.764Z" }, - { url = "https://files.pythonhosted.org/packages/68/d0/14fa1699f4ef629eae08ad6201c6b476098f5efb051b296f4c26be7a9fdf/multidict-6.6.3-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e252017a817fad7ce05cafbe5711ed40faeb580e63b16755a3a24e66fa1d87c0", size = 256882, upload-time = "2025-06-30T15:52:54.596Z" }, - { url = "https://files.pythonhosted.org/packages/da/88/84a27570fbe303c65607d517a5f147cd2fc046c2d1da02b84b17b9bdc2aa/multidict-6.6.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2e4cc8d848cd4fe1cdee28c13ea79ab0ed37fc2e89dd77bac86a2e7959a8c3bc", size = 247816, upload-time = "2025-06-30T15:52:56.175Z" }, - { url = "https://files.pythonhosted.org/packages/1c/60/dca352a0c999ce96a5d8b8ee0b2b9f729dcad2e0b0c195f8286269a2074c/multidict-6.6.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9e236a7094b9c4c1b7585f6b9cca34b9d833cf079f7e4c49e6a4a6ec9bfdc68f", size = 245341, upload-time = "2025-06-30T15:52:57.752Z" }, - { url = "https://files.pythonhosted.org/packages/50/ef/433fa3ed06028f03946f3993223dada70fb700f763f70c00079533c34578/multidict-6.6.3-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:e0cb0ab69915c55627c933f0b555a943d98ba71b4d1c57bc0d0a66e2567c7471", size = 235854, upload-time = "2025-06-30T15:52:59.74Z" }, - { url = "https://files.pythonhosted.org/packages/1b/1f/487612ab56fbe35715320905215a57fede20de7db40a261759690dc80471/multidict-6.6.3-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:81ef2f64593aba09c5212a3d0f8c906a0d38d710a011f2f42759704d4557d3f2", size = 243432, upload-time = "2025-06-30T15:53:01.602Z" }, - { url = "https://files.pythonhosted.org/packages/da/6f/ce8b79de16cd885c6f9052c96a3671373d00c59b3ee635ea93e6e81b8ccf/multidict-6.6.3-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:b9cbc60010de3562545fa198bfc6d3825df430ea96d2cc509c39bd71e2e7d648", size = 252731, upload-time = "2025-06-30T15:53:03.517Z" }, - { url = "https://files.pythonhosted.org/packages/bb/fe/a2514a6aba78e5abefa1624ca85ae18f542d95ac5cde2e3815a9fbf369aa/multidict-6.6.3-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:70d974eaaa37211390cd02ef93b7e938de564bbffa866f0b08d07e5e65da783d", size = 247086, upload-time = "2025-06-30T15:53:05.48Z" }, - { url = "https://files.pythonhosted.org/packages/8c/22/b788718d63bb3cce752d107a57c85fcd1a212c6c778628567c9713f9345a/multidict-6.6.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:3713303e4a6663c6d01d648a68f2848701001f3390a030edaaf3fc949c90bf7c", size = 243338, upload-time = "2025-06-30T15:53:07.522Z" }, - { url = "https://files.pythonhosted.org/packages/22/d6/fdb3d0670819f2228f3f7d9af613d5e652c15d170c83e5f1c94fbc55a25b/multidict-6.6.3-cp313-cp313t-win32.whl", hash = "sha256:639ecc9fe7cd73f2495f62c213e964843826f44505a3e5d82805aa85cac6f89e", size = 47812, upload-time = "2025-06-30T15:53:09.263Z" }, - { url = "https://files.pythonhosted.org/packages/b6/d6/a9d2c808f2c489ad199723197419207ecbfbc1776f6e155e1ecea9c883aa/multidict-6.6.3-cp313-cp313t-win_amd64.whl", hash = "sha256:9f97e181f344a0ef3881b573d31de8542cc0dbc559ec68c8f8b5ce2c2e91646d", size = 53011, upload-time = "2025-06-30T15:53:11.038Z" }, - { url = "https://files.pythonhosted.org/packages/f2/40/b68001cba8188dd267590a111f9661b6256debc327137667e832bf5d66e8/multidict-6.6.3-cp313-cp313t-win_arm64.whl", hash = "sha256:ce8b7693da41a3c4fde5871c738a81490cea5496c671d74374c8ab889e1834fb", size = 45254, upload-time = "2025-06-30T15:53:12.421Z" }, - { url = "https://files.pythonhosted.org/packages/d2/64/ba29bd6dfc895e592b2f20f92378e692ac306cf25dd0be2f8e0a0f898edb/multidict-6.6.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c8161b5a7778d3137ea2ee7ae8a08cce0010de3b00ac671c5ebddeaa17cefd22", size = 76959, upload-time = "2025-06-30T15:53:13.827Z" }, - { url = "https://files.pythonhosted.org/packages/ca/cd/872ae4c134257dacebff59834983c1615d6ec863b6e3d360f3203aad8400/multidict-6.6.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1328201ee930f069961ae707d59c6627ac92e351ed5b92397cf534d1336ce557", size = 44864, upload-time = "2025-06-30T15:53:15.658Z" }, - { url = "https://files.pythonhosted.org/packages/15/35/d417d8f62f2886784b76df60522d608aba39dfc83dd53b230ca71f2d4c53/multidict-6.6.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b1db4d2093d6b235de76932febf9d50766cf49a5692277b2c28a501c9637f616", size = 44540, upload-time = "2025-06-30T15:53:17.208Z" }, - { url = "https://files.pythonhosted.org/packages/85/59/25cddf781f12cddb2386baa29744a3fdd160eb705539b48065f0cffd86d5/multidict-6.6.3-cp39-cp39-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:53becb01dd8ebd19d1724bebe369cfa87e4e7f29abbbe5c14c98ce4c383e16cd", size = 224075, upload-time = "2025-06-30T15:53:18.705Z" }, - { url = "https://files.pythonhosted.org/packages/c4/21/4055b6a527954c572498a8068c26bd3b75f2b959080e17e12104b592273c/multidict-6.6.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:41bb9d1d4c303886e2d85bade86e59885112a7f4277af5ad47ab919a2251f306", size = 240535, upload-time = "2025-06-30T15:53:20.359Z" }, - { url = "https://files.pythonhosted.org/packages/58/98/17f1f80bdba0b2fef49cf4ba59cebf8a81797f745f547abb5c9a4039df62/multidict-6.6.3-cp39-cp39-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:775b464d31dac90f23192af9c291dc9f423101857e33e9ebf0020a10bfcf4144", size = 219361, upload-time = "2025-06-30T15:53:22.371Z" }, - { url = "https://files.pythonhosted.org/packages/f8/0e/a5e595fdd0820069f0c29911d5dc9dc3a75ec755ae733ce59a4e6962ae42/multidict-6.6.3-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d04d01f0a913202205a598246cf77826fe3baa5a63e9f6ccf1ab0601cf56eca0", size = 251207, upload-time = "2025-06-30T15:53:24.307Z" }, - { url = "https://files.pythonhosted.org/packages/66/9e/0f51e4cffea2daf24c137feabc9ec848ce50f8379c9badcbac00b41ab55e/multidict-6.6.3-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d25594d3b38a2e6cabfdcafef339f754ca6e81fbbdb6650ad773ea9775af35ab", size = 249749, upload-time = "2025-06-30T15:53:26.056Z" }, - { url = "https://files.pythonhosted.org/packages/49/a0/a7cfc13c9a71ceb8c1c55457820733af9ce01e121139271f7b13e30c29d2/multidict-6.6.3-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:35712f1748d409e0707b165bf49f9f17f9e28ae85470c41615778f8d4f7d9609", size = 239202, upload-time = "2025-06-30T15:53:28.096Z" }, - { url = "https://files.pythonhosted.org/packages/c7/50/7ae0d1149ac71cab6e20bb7faf2a1868435974994595dadfdb7377f7140f/multidict-6.6.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1c8082e5814b662de8589d6a06c17e77940d5539080cbab9fe6794b5241b76d9", size = 237269, upload-time = "2025-06-30T15:53:30.124Z" }, - { url = "https://files.pythonhosted.org/packages/b4/ac/2d0bf836c9c63a57360d57b773359043b371115e1c78ff648993bf19abd0/multidict-6.6.3-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:61af8a4b771f1d4d000b3168c12c3120ccf7284502a94aa58c68a81f5afac090", size = 232961, upload-time = "2025-06-30T15:53:31.766Z" }, - { url = "https://files.pythonhosted.org/packages/85/e1/68a65f069df298615591e70e48bfd379c27d4ecb252117c18bf52eebc237/multidict-6.6.3-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:448e4a9afccbf297577f2eaa586f07067441e7b63c8362a3540ba5a38dc0f14a", size = 240863, upload-time = "2025-06-30T15:53:33.488Z" }, - { url = "https://files.pythonhosted.org/packages/ae/ab/702f1baca649f88ea1dc6259fc2aa4509f4ad160ba48c8e61fbdb4a5a365/multidict-6.6.3-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:233ad16999afc2bbd3e534ad8dbe685ef8ee49a37dbc2cdc9514e57b6d589ced", size = 246800, upload-time = "2025-06-30T15:53:35.21Z" }, - { url = "https://files.pythonhosted.org/packages/5e/0b/726e690bfbf887985a8710ef2f25f1d6dd184a35bd3b36429814f810a2fc/multidict-6.6.3-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:bb933c891cd4da6bdcc9733d048e994e22e1883287ff7540c2a0f3b117605092", size = 242034, upload-time = "2025-06-30T15:53:36.913Z" }, - { url = "https://files.pythonhosted.org/packages/73/bb/839486b27bcbcc2e0d875fb9d4012b4b6aa99639137343106aa7210e047a/multidict-6.6.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:37b09ca60998e87734699e88c2363abfd457ed18cfbf88e4009a4e83788e63ed", size = 235377, upload-time = "2025-06-30T15:53:38.618Z" }, - { url = "https://files.pythonhosted.org/packages/e3/46/574d75ab7b9ae8690fe27e89f5fcd0121633112b438edfb9ed2be8be096b/multidict-6.6.3-cp39-cp39-win32.whl", hash = "sha256:f54cb79d26d0cd420637d184af38f0668558f3c4bbe22ab7ad830e67249f2e0b", size = 41420, upload-time = "2025-06-30T15:53:40.309Z" }, - { url = "https://files.pythonhosted.org/packages/78/c3/8b3bc755508b777868349f4bfa844d3d31832f075ee800a3d6f1807338c5/multidict-6.6.3-cp39-cp39-win_amd64.whl", hash = "sha256:295adc9c0551e5d5214b45cf29ca23dbc28c2d197a9c30d51aed9e037cb7c578", size = 46124, upload-time = "2025-06-30T15:53:41.984Z" }, - { url = "https://files.pythonhosted.org/packages/b2/30/5a66e7e4550e80975faee5b5dd9e9bd09194d2fd8f62363119b9e46e204b/multidict-6.6.3-cp39-cp39-win_arm64.whl", hash = "sha256:15332783596f227db50fb261c2c251a58ac3873c457f3a550a95d5c0aa3c770d", size = 42973, upload-time = "2025-06-30T15:53:43.505Z" }, - { url = "https://files.pythonhosted.org/packages/d8/30/9aec301e9772b098c1f5c0ca0279237c9766d94b97802e9888010c64b0ed/multidict-6.6.3-py3-none-any.whl", hash = "sha256:8db10f29c7541fc5da4defd8cd697e1ca429db743fa716325f236079b96f775a", size = 12313, upload-time = "2025-06-30T15:53:45.437Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/69/7f/0652e6ed47ab288e3756ea9c0df8b14950781184d4bd7883f4d87dd41245/multidict-6.6.4.tar.gz", hash = "sha256:d2d4e4787672911b48350df02ed3fa3fffdc2f2e8ca06dd6afdf34189b76a9dd", size = 101843, upload-time = "2025-08-11T12:08:48.217Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/eb/6b/86f353088c1358e76fd30b0146947fddecee812703b604ee901e85cd2a80/multidict-6.6.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b8aa6f0bd8125ddd04a6593437bad6a7e70f300ff4180a531654aa2ab3f6d58f", size = 77054, upload-time = "2025-08-11T12:06:02.99Z" }, + { url = "https://files.pythonhosted.org/packages/19/5d/c01dc3d3788bb877bd7f5753ea6eb23c1beeca8044902a8f5bfb54430f63/multidict-6.6.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b9e5853bbd7264baca42ffc53391b490d65fe62849bf2c690fa3f6273dbcd0cb", size = 44914, upload-time = "2025-08-11T12:06:05.264Z" }, + { url = "https://files.pythonhosted.org/packages/46/44/964dae19ea42f7d3e166474d8205f14bb811020e28bc423d46123ddda763/multidict-6.6.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0af5f9dee472371e36d6ae38bde009bd8ce65ac7335f55dcc240379d7bed1495", size = 44601, upload-time = "2025-08-11T12:06:06.627Z" }, + { url = "https://files.pythonhosted.org/packages/31/20/0616348a1dfb36cb2ab33fc9521de1f27235a397bf3f59338e583afadd17/multidict-6.6.4-cp310-cp310-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:d24f351e4d759f5054b641c81e8291e5d122af0fca5c72454ff77f7cbe492de8", size = 224821, upload-time = "2025-08-11T12:06:08.06Z" }, + { url = "https://files.pythonhosted.org/packages/14/26/5d8923c69c110ff51861af05bd27ca6783011b96725d59ccae6d9daeb627/multidict-6.6.4-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:db6a3810eec08280a172a6cd541ff4a5f6a97b161d93ec94e6c4018917deb6b7", size = 242608, upload-time = "2025-08-11T12:06:09.697Z" }, + { url = "https://files.pythonhosted.org/packages/5c/cc/e2ad3ba9459aa34fa65cf1f82a5c4a820a2ce615aacfb5143b8817f76504/multidict-6.6.4-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:a1b20a9d56b2d81e2ff52ecc0670d583eaabaa55f402e8d16dd062373dbbe796", size = 222324, upload-time = "2025-08-11T12:06:10.905Z" }, + { url = "https://files.pythonhosted.org/packages/19/db/4ed0f65701afbc2cb0c140d2d02928bb0fe38dd044af76e58ad7c54fd21f/multidict-6.6.4-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8c9854df0eaa610a23494c32a6f44a3a550fb398b6b51a56e8c6b9b3689578db", size = 253234, upload-time = "2025-08-11T12:06:12.658Z" }, + { url = "https://files.pythonhosted.org/packages/94/c1/5160c9813269e39ae14b73debb907bfaaa1beee1762da8c4fb95df4764ed/multidict-6.6.4-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4bb7627fd7a968f41905a4d6343b0d63244a0623f006e9ed989fa2b78f4438a0", size = 251613, upload-time = "2025-08-11T12:06:13.97Z" }, + { url = "https://files.pythonhosted.org/packages/05/a9/48d1bd111fc2f8fb98b2ed7f9a115c55a9355358432a19f53c0b74d8425d/multidict-6.6.4-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:caebafea30ed049c57c673d0b36238b1748683be2593965614d7b0e99125c877", size = 241649, upload-time = "2025-08-11T12:06:15.204Z" }, + { url = "https://files.pythonhosted.org/packages/85/2a/f7d743df0019408768af8a70d2037546a2be7b81fbb65f040d76caafd4c5/multidict-6.6.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:ad887a8250eb47d3ab083d2f98db7f48098d13d42eb7a3b67d8a5c795f224ace", size = 239238, upload-time = "2025-08-11T12:06:16.467Z" }, + { url = "https://files.pythonhosted.org/packages/cb/b8/4f4bb13323c2d647323f7919201493cf48ebe7ded971717bfb0f1a79b6bf/multidict-6.6.4-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:ed8358ae7d94ffb7c397cecb62cbac9578a83ecefc1eba27b9090ee910e2efb6", size = 233517, upload-time = "2025-08-11T12:06:18.107Z" }, + { url = "https://files.pythonhosted.org/packages/33/29/4293c26029ebfbba4f574febd2ed01b6f619cfa0d2e344217d53eef34192/multidict-6.6.4-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:ecab51ad2462197a4c000b6d5701fc8585b80eecb90583635d7e327b7b6923eb", size = 243122, upload-time = "2025-08-11T12:06:19.361Z" }, + { url = "https://files.pythonhosted.org/packages/20/60/a1c53628168aa22447bfde3a8730096ac28086704a0d8c590f3b63388d0c/multidict-6.6.4-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:c5c97aa666cf70e667dfa5af945424ba1329af5dd988a437efeb3a09430389fb", size = 248992, upload-time = "2025-08-11T12:06:20.661Z" }, + { url = "https://files.pythonhosted.org/packages/a3/3b/55443a0c372f33cae5d9ec37a6a973802884fa0ab3586659b197cf8cc5e9/multidict-6.6.4-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:9a950b7cf54099c1209f455ac5970b1ea81410f2af60ed9eb3c3f14f0bfcf987", size = 243708, upload-time = "2025-08-11T12:06:21.891Z" }, + { url = "https://files.pythonhosted.org/packages/7c/60/a18c6900086769312560b2626b18e8cca22d9e85b1186ba77f4755b11266/multidict-6.6.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:163c7ea522ea9365a8a57832dea7618e6cbdc3cd75f8c627663587459a4e328f", size = 237498, upload-time = "2025-08-11T12:06:23.206Z" }, + { url = "https://files.pythonhosted.org/packages/11/3d/8bdd8bcaff2951ce2affccca107a404925a2beafedd5aef0b5e4a71120a6/multidict-6.6.4-cp310-cp310-win32.whl", hash = "sha256:17d2cbbfa6ff20821396b25890f155f40c986f9cfbce5667759696d83504954f", size = 41415, upload-time = "2025-08-11T12:06:24.77Z" }, + { url = "https://files.pythonhosted.org/packages/c0/53/cab1ad80356a4cd1b685a254b680167059b433b573e53872fab245e9fc95/multidict-6.6.4-cp310-cp310-win_amd64.whl", hash = "sha256:ce9a40fbe52e57e7edf20113a4eaddfacac0561a0879734e636aa6d4bb5e3fb0", size = 46046, upload-time = "2025-08-11T12:06:25.893Z" }, + { url = "https://files.pythonhosted.org/packages/cf/9a/874212b6f5c1c2d870d0a7adc5bb4cfe9b0624fa15cdf5cf757c0f5087ae/multidict-6.6.4-cp310-cp310-win_arm64.whl", hash = "sha256:01d0959807a451fe9fdd4da3e139cb5b77f7328baf2140feeaf233e1d777b729", size = 43147, upload-time = "2025-08-11T12:06:27.534Z" }, + { url = "https://files.pythonhosted.org/packages/6b/7f/90a7f01e2d005d6653c689039977f6856718c75c5579445effb7e60923d1/multidict-6.6.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:c7a0e9b561e6460484318a7612e725df1145d46b0ef57c6b9866441bf6e27e0c", size = 76472, upload-time = "2025-08-11T12:06:29.006Z" }, + { url = "https://files.pythonhosted.org/packages/54/a3/bed07bc9e2bb302ce752f1dabc69e884cd6a676da44fb0e501b246031fdd/multidict-6.6.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6bf2f10f70acc7a2446965ffbc726e5fc0b272c97a90b485857e5c70022213eb", size = 44634, upload-time = "2025-08-11T12:06:30.374Z" }, + { url = "https://files.pythonhosted.org/packages/a7/4b/ceeb4f8f33cf81277da464307afeaf164fb0297947642585884f5cad4f28/multidict-6.6.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:66247d72ed62d5dd29752ffc1d3b88f135c6a8de8b5f63b7c14e973ef5bda19e", size = 44282, upload-time = "2025-08-11T12:06:31.958Z" }, + { url = "https://files.pythonhosted.org/packages/03/35/436a5da8702b06866189b69f655ffdb8f70796252a8772a77815f1812679/multidict-6.6.4-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:105245cc6b76f51e408451a844a54e6823bbd5a490ebfe5bdfc79798511ceded", size = 229696, upload-time = "2025-08-11T12:06:33.087Z" }, + { url = "https://files.pythonhosted.org/packages/b6/0e/915160be8fecf1fca35f790c08fb74ca684d752fcba62c11daaf3d92c216/multidict-6.6.4-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cbbc54e58b34c3bae389ef00046be0961f30fef7cb0dd9c7756aee376a4f7683", size = 246665, upload-time = "2025-08-11T12:06:34.448Z" }, + { url = "https://files.pythonhosted.org/packages/08/ee/2f464330acd83f77dcc346f0b1a0eaae10230291450887f96b204b8ac4d3/multidict-6.6.4-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:56c6b3652f945c9bc3ac6c8178cd93132b8d82dd581fcbc3a00676c51302bc1a", size = 225485, upload-time = "2025-08-11T12:06:35.672Z" }, + { url = "https://files.pythonhosted.org/packages/71/cc/9a117f828b4d7fbaec6adeed2204f211e9caf0a012692a1ee32169f846ae/multidict-6.6.4-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b95494daf857602eccf4c18ca33337dd2be705bccdb6dddbfc9d513e6addb9d9", size = 257318, upload-time = "2025-08-11T12:06:36.98Z" }, + { url = "https://files.pythonhosted.org/packages/25/77/62752d3dbd70e27fdd68e86626c1ae6bccfebe2bb1f84ae226363e112f5a/multidict-6.6.4-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e5b1413361cef15340ab9dc61523e653d25723e82d488ef7d60a12878227ed50", size = 254689, upload-time = "2025-08-11T12:06:38.233Z" }, + { url = "https://files.pythonhosted.org/packages/00/6e/fac58b1072a6fc59af5e7acb245e8754d3e1f97f4f808a6559951f72a0d4/multidict-6.6.4-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e167bf899c3d724f9662ef00b4f7fef87a19c22b2fead198a6f68b263618df52", size = 246709, upload-time = "2025-08-11T12:06:39.517Z" }, + { url = "https://files.pythonhosted.org/packages/01/ef/4698d6842ef5e797c6db7744b0081e36fb5de3d00002cc4c58071097fac3/multidict-6.6.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:aaea28ba20a9026dfa77f4b80369e51cb767c61e33a2d4043399c67bd95fb7c6", size = 243185, upload-time = "2025-08-11T12:06:40.796Z" }, + { url = "https://files.pythonhosted.org/packages/aa/c9/d82e95ae1d6e4ef396934e9b0e942dfc428775f9554acf04393cce66b157/multidict-6.6.4-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:8c91cdb30809a96d9ecf442ec9bc45e8cfaa0f7f8bdf534e082c2443a196727e", size = 237838, upload-time = "2025-08-11T12:06:42.595Z" }, + { url = "https://files.pythonhosted.org/packages/57/cf/f94af5c36baaa75d44fab9f02e2a6bcfa0cd90acb44d4976a80960759dbc/multidict-6.6.4-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1a0ccbfe93ca114c5d65a2471d52d8829e56d467c97b0e341cf5ee45410033b3", size = 246368, upload-time = "2025-08-11T12:06:44.304Z" }, + { url = "https://files.pythonhosted.org/packages/4a/fe/29f23460c3d995f6a4b678cb2e9730e7277231b981f0b234702f0177818a/multidict-6.6.4-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:55624b3f321d84c403cb7d8e6e982f41ae233d85f85db54ba6286f7295dc8a9c", size = 253339, upload-time = "2025-08-11T12:06:45.597Z" }, + { url = "https://files.pythonhosted.org/packages/29/b6/fd59449204426187b82bf8a75f629310f68c6adc9559dc922d5abe34797b/multidict-6.6.4-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:4a1fb393a2c9d202cb766c76208bd7945bc194eba8ac920ce98c6e458f0b524b", size = 246933, upload-time = "2025-08-11T12:06:46.841Z" }, + { url = "https://files.pythonhosted.org/packages/19/52/d5d6b344f176a5ac3606f7a61fb44dc746e04550e1a13834dff722b8d7d6/multidict-6.6.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:43868297a5759a845fa3a483fb4392973a95fb1de891605a3728130c52b8f40f", size = 242225, upload-time = "2025-08-11T12:06:48.588Z" }, + { url = "https://files.pythonhosted.org/packages/ec/d3/5b2281ed89ff4d5318d82478a2a2450fcdfc3300da48ff15c1778280ad26/multidict-6.6.4-cp311-cp311-win32.whl", hash = "sha256:ed3b94c5e362a8a84d69642dbeac615452e8af9b8eb825b7bc9f31a53a1051e2", size = 41306, upload-time = "2025-08-11T12:06:49.95Z" }, + { url = "https://files.pythonhosted.org/packages/74/7d/36b045c23a1ab98507aefd44fd8b264ee1dd5e5010543c6fccf82141ccef/multidict-6.6.4-cp311-cp311-win_amd64.whl", hash = "sha256:d8c112f7a90d8ca5d20213aa41eac690bb50a76da153e3afb3886418e61cb22e", size = 46029, upload-time = "2025-08-11T12:06:51.082Z" }, + { url = "https://files.pythonhosted.org/packages/0f/5e/553d67d24432c5cd52b49047f2d248821843743ee6d29a704594f656d182/multidict-6.6.4-cp311-cp311-win_arm64.whl", hash = "sha256:3bb0eae408fa1996d87247ca0d6a57b7fc1dcf83e8a5c47ab82c558c250d4adf", size = 43017, upload-time = "2025-08-11T12:06:52.243Z" }, + { url = "https://files.pythonhosted.org/packages/05/f6/512ffd8fd8b37fb2680e5ac35d788f1d71bbaf37789d21a820bdc441e565/multidict-6.6.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0ffb87be160942d56d7b87b0fdf098e81ed565add09eaa1294268c7f3caac4c8", size = 76516, upload-time = "2025-08-11T12:06:53.393Z" }, + { url = "https://files.pythonhosted.org/packages/99/58/45c3e75deb8855c36bd66cc1658007589662ba584dbf423d01df478dd1c5/multidict-6.6.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d191de6cbab2aff5de6c5723101705fd044b3e4c7cfd587a1929b5028b9714b3", size = 45394, upload-time = "2025-08-11T12:06:54.555Z" }, + { url = "https://files.pythonhosted.org/packages/fd/ca/e8c4472a93a26e4507c0b8e1f0762c0d8a32de1328ef72fd704ef9cc5447/multidict-6.6.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:38a0956dd92d918ad5feff3db8fcb4a5eb7dba114da917e1a88475619781b57b", size = 43591, upload-time = "2025-08-11T12:06:55.672Z" }, + { url = "https://files.pythonhosted.org/packages/05/51/edf414f4df058574a7265034d04c935aa84a89e79ce90fcf4df211f47b16/multidict-6.6.4-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:6865f6d3b7900ae020b495d599fcf3765653bc927951c1abb959017f81ae8287", size = 237215, upload-time = "2025-08-11T12:06:57.213Z" }, + { url = "https://files.pythonhosted.org/packages/c8/45/8b3d6dbad8cf3252553cc41abea09ad527b33ce47a5e199072620b296902/multidict-6.6.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0a2088c126b6f72db6c9212ad827d0ba088c01d951cee25e758c450da732c138", size = 258299, upload-time = "2025-08-11T12:06:58.946Z" }, + { url = "https://files.pythonhosted.org/packages/3c/e8/8ca2e9a9f5a435fc6db40438a55730a4bf4956b554e487fa1b9ae920f825/multidict-6.6.4-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:0f37bed7319b848097085d7d48116f545985db988e2256b2e6f00563a3416ee6", size = 242357, upload-time = "2025-08-11T12:07:00.301Z" }, + { url = "https://files.pythonhosted.org/packages/0f/84/80c77c99df05a75c28490b2af8f7cba2a12621186e0a8b0865d8e745c104/multidict-6.6.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:01368e3c94032ba6ca0b78e7ccb099643466cf24f8dc8eefcfdc0571d56e58f9", size = 268369, upload-time = "2025-08-11T12:07:01.638Z" }, + { url = "https://files.pythonhosted.org/packages/0d/e9/920bfa46c27b05fb3e1ad85121fd49f441492dca2449c5bcfe42e4565d8a/multidict-6.6.4-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8fe323540c255db0bffee79ad7f048c909f2ab0edb87a597e1c17da6a54e493c", size = 269341, upload-time = "2025-08-11T12:07:02.943Z" }, + { url = "https://files.pythonhosted.org/packages/af/65/753a2d8b05daf496f4a9c367fe844e90a1b2cac78e2be2c844200d10cc4c/multidict-6.6.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b8eb3025f17b0a4c3cd08cda49acf312a19ad6e8a4edd9dbd591e6506d999402", size = 256100, upload-time = "2025-08-11T12:07:04.564Z" }, + { url = "https://files.pythonhosted.org/packages/09/54/655be13ae324212bf0bc15d665a4e34844f34c206f78801be42f7a0a8aaa/multidict-6.6.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:bbc14f0365534d35a06970d6a83478b249752e922d662dc24d489af1aa0d1be7", size = 253584, upload-time = "2025-08-11T12:07:05.914Z" }, + { url = "https://files.pythonhosted.org/packages/5c/74/ab2039ecc05264b5cec73eb018ce417af3ebb384ae9c0e9ed42cb33f8151/multidict-6.6.4-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:75aa52fba2d96bf972e85451b99d8e19cc37ce26fd016f6d4aa60da9ab2b005f", size = 251018, upload-time = "2025-08-11T12:07:08.301Z" }, + { url = "https://files.pythonhosted.org/packages/af/0a/ccbb244ac848e56c6427f2392741c06302bbfba49c0042f1eb3c5b606497/multidict-6.6.4-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:4fefd4a815e362d4f011919d97d7b4a1e566f1dde83dc4ad8cfb5b41de1df68d", size = 251477, upload-time = "2025-08-11T12:07:10.248Z" }, + { url = "https://files.pythonhosted.org/packages/0e/b0/0ed49bba775b135937f52fe13922bc64a7eaf0a3ead84a36e8e4e446e096/multidict-6.6.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:db9801fe021f59a5b375ab778973127ca0ac52429a26e2fd86aa9508f4d26eb7", size = 263575, upload-time = "2025-08-11T12:07:11.928Z" }, + { url = "https://files.pythonhosted.org/packages/3e/d9/7fb85a85e14de2e44dfb6a24f03c41e2af8697a6df83daddb0e9b7569f73/multidict-6.6.4-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:a650629970fa21ac1fb06ba25dabfc5b8a2054fcbf6ae97c758aa956b8dba802", size = 259649, upload-time = "2025-08-11T12:07:13.244Z" }, + { url = "https://files.pythonhosted.org/packages/03/9e/b3a459bcf9b6e74fa461a5222a10ff9b544cb1cd52fd482fb1b75ecda2a2/multidict-6.6.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:452ff5da78d4720d7516a3a2abd804957532dd69296cb77319c193e3ffb87e24", size = 251505, upload-time = "2025-08-11T12:07:14.57Z" }, + { url = "https://files.pythonhosted.org/packages/86/a2/8022f78f041dfe6d71e364001a5cf987c30edfc83c8a5fb7a3f0974cff39/multidict-6.6.4-cp312-cp312-win32.whl", hash = "sha256:8c2fcb12136530ed19572bbba61b407f655e3953ba669b96a35036a11a485793", size = 41888, upload-time = "2025-08-11T12:07:15.904Z" }, + { url = "https://files.pythonhosted.org/packages/c7/eb/d88b1780d43a56db2cba24289fa744a9d216c1a8546a0dc3956563fd53ea/multidict-6.6.4-cp312-cp312-win_amd64.whl", hash = "sha256:047d9425860a8c9544fed1b9584f0c8bcd31bcde9568b047c5e567a1025ecd6e", size = 46072, upload-time = "2025-08-11T12:07:17.045Z" }, + { url = "https://files.pythonhosted.org/packages/9f/16/b929320bf5750e2d9d4931835a4c638a19d2494a5b519caaaa7492ebe105/multidict-6.6.4-cp312-cp312-win_arm64.whl", hash = "sha256:14754eb72feaa1e8ae528468f24250dd997b8e2188c3d2f593f9eba259e4b364", size = 43222, upload-time = "2025-08-11T12:07:18.328Z" }, + { url = "https://files.pythonhosted.org/packages/3a/5d/e1db626f64f60008320aab00fbe4f23fc3300d75892a3381275b3d284580/multidict-6.6.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:f46a6e8597f9bd71b31cc708195d42b634c8527fecbcf93febf1052cacc1f16e", size = 75848, upload-time = "2025-08-11T12:07:19.912Z" }, + { url = "https://files.pythonhosted.org/packages/4c/aa/8b6f548d839b6c13887253af4e29c939af22a18591bfb5d0ee6f1931dae8/multidict-6.6.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:22e38b2bc176c5eb9c0a0e379f9d188ae4cd8b28c0f53b52bce7ab0a9e534657", size = 45060, upload-time = "2025-08-11T12:07:21.163Z" }, + { url = "https://files.pythonhosted.org/packages/eb/c6/f5e97e5d99a729bc2aa58eb3ebfa9f1e56a9b517cc38c60537c81834a73f/multidict-6.6.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5df8afd26f162da59e218ac0eefaa01b01b2e6cd606cffa46608f699539246da", size = 43269, upload-time = "2025-08-11T12:07:22.392Z" }, + { url = "https://files.pythonhosted.org/packages/dc/31/d54eb0c62516776f36fe67f84a732f97e0b0e12f98d5685bebcc6d396910/multidict-6.6.4-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:49517449b58d043023720aa58e62b2f74ce9b28f740a0b5d33971149553d72aa", size = 237158, upload-time = "2025-08-11T12:07:23.636Z" }, + { url = "https://files.pythonhosted.org/packages/c4/1c/8a10c1c25b23156e63b12165a929d8eb49a6ed769fdbefb06e6f07c1e50d/multidict-6.6.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ae9408439537c5afdca05edd128a63f56a62680f4b3c234301055d7a2000220f", size = 257076, upload-time = "2025-08-11T12:07:25.049Z" }, + { url = "https://files.pythonhosted.org/packages/ad/86/90e20b5771d6805a119e483fd3d1e8393e745a11511aebca41f0da38c3e2/multidict-6.6.4-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:87a32d20759dc52a9e850fe1061b6e41ab28e2998d44168a8a341b99ded1dba0", size = 240694, upload-time = "2025-08-11T12:07:26.458Z" }, + { url = "https://files.pythonhosted.org/packages/e7/49/484d3e6b535bc0555b52a0a26ba86e4d8d03fd5587d4936dc59ba7583221/multidict-6.6.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:52e3c8d43cdfff587ceedce9deb25e6ae77daba560b626e97a56ddcad3756879", size = 266350, upload-time = "2025-08-11T12:07:27.94Z" }, + { url = "https://files.pythonhosted.org/packages/bf/b4/aa4c5c379b11895083d50021e229e90c408d7d875471cb3abf721e4670d6/multidict-6.6.4-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ad8850921d3a8d8ff6fbef790e773cecfc260bbfa0566998980d3fa8f520bc4a", size = 267250, upload-time = "2025-08-11T12:07:29.303Z" }, + { url = "https://files.pythonhosted.org/packages/80/e5/5e22c5bf96a64bdd43518b1834c6d95a4922cc2066b7d8e467dae9b6cee6/multidict-6.6.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:497a2954adc25c08daff36f795077f63ad33e13f19bfff7736e72c785391534f", size = 254900, upload-time = "2025-08-11T12:07:30.764Z" }, + { url = "https://files.pythonhosted.org/packages/17/38/58b27fed927c07035abc02befacab42491e7388ca105e087e6e0215ead64/multidict-6.6.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:024ce601f92d780ca1617ad4be5ac15b501cc2414970ffa2bb2bbc2bd5a68fa5", size = 252355, upload-time = "2025-08-11T12:07:32.205Z" }, + { url = "https://files.pythonhosted.org/packages/d0/a1/dad75d23a90c29c02b5d6f3d7c10ab36c3197613be5d07ec49c7791e186c/multidict-6.6.4-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:a693fc5ed9bdd1c9e898013e0da4dcc640de7963a371c0bd458e50e046bf6438", size = 250061, upload-time = "2025-08-11T12:07:33.623Z" }, + { url = "https://files.pythonhosted.org/packages/b8/1a/ac2216b61c7f116edab6dc3378cca6c70dc019c9a457ff0d754067c58b20/multidict-6.6.4-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:190766dac95aab54cae5b152a56520fd99298f32a1266d66d27fdd1b5ac00f4e", size = 249675, upload-time = "2025-08-11T12:07:34.958Z" }, + { url = "https://files.pythonhosted.org/packages/d4/79/1916af833b800d13883e452e8e0977c065c4ee3ab7a26941fbfdebc11895/multidict-6.6.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:34d8f2a5ffdceab9dcd97c7a016deb2308531d5f0fced2bb0c9e1df45b3363d7", size = 261247, upload-time = "2025-08-11T12:07:36.588Z" }, + { url = "https://files.pythonhosted.org/packages/c5/65/d1f84fe08ac44a5fc7391cbc20a7cedc433ea616b266284413fd86062f8c/multidict-6.6.4-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:59e8d40ab1f5a8597abcef00d04845155a5693b5da00d2c93dbe88f2050f2812", size = 257960, upload-time = "2025-08-11T12:07:39.735Z" }, + { url = "https://files.pythonhosted.org/packages/13/b5/29ec78057d377b195ac2c5248c773703a6b602e132a763e20ec0457e7440/multidict-6.6.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:467fe64138cfac771f0e949b938c2e1ada2b5af22f39692aa9258715e9ea613a", size = 250078, upload-time = "2025-08-11T12:07:41.525Z" }, + { url = "https://files.pythonhosted.org/packages/c4/0e/7e79d38f70a872cae32e29b0d77024bef7834b0afb406ddae6558d9e2414/multidict-6.6.4-cp313-cp313-win32.whl", hash = "sha256:14616a30fe6d0a48d0a48d1a633ab3b8bec4cf293aac65f32ed116f620adfd69", size = 41708, upload-time = "2025-08-11T12:07:43.405Z" }, + { url = "https://files.pythonhosted.org/packages/9d/34/746696dffff742e97cd6a23da953e55d0ea51fa601fa2ff387b3edcfaa2c/multidict-6.6.4-cp313-cp313-win_amd64.whl", hash = "sha256:40cd05eaeb39e2bc8939451f033e57feaa2ac99e07dbca8afe2be450a4a3b6cf", size = 45912, upload-time = "2025-08-11T12:07:45.082Z" }, + { url = "https://files.pythonhosted.org/packages/c7/87/3bac136181e271e29170d8d71929cdeddeb77f3e8b6a0c08da3a8e9da114/multidict-6.6.4-cp313-cp313-win_arm64.whl", hash = "sha256:f6eb37d511bfae9e13e82cb4d1af36b91150466f24d9b2b8a9785816deb16605", size = 43076, upload-time = "2025-08-11T12:07:46.746Z" }, + { url = "https://files.pythonhosted.org/packages/64/94/0a8e63e36c049b571c9ae41ee301ada29c3fee9643d9c2548d7d558a1d99/multidict-6.6.4-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:6c84378acd4f37d1b507dfa0d459b449e2321b3ba5f2338f9b085cf7a7ba95eb", size = 82812, upload-time = "2025-08-11T12:07:48.402Z" }, + { url = "https://files.pythonhosted.org/packages/25/1a/be8e369dfcd260d2070a67e65dd3990dd635cbd735b98da31e00ea84cd4e/multidict-6.6.4-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0e0558693063c75f3d952abf645c78f3c5dfdd825a41d8c4d8156fc0b0da6e7e", size = 48313, upload-time = "2025-08-11T12:07:49.679Z" }, + { url = "https://files.pythonhosted.org/packages/26/5a/dd4ade298674b2f9a7b06a32c94ffbc0497354df8285f27317c66433ce3b/multidict-6.6.4-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3f8e2384cb83ebd23fd07e9eada8ba64afc4c759cd94817433ab8c81ee4b403f", size = 46777, upload-time = "2025-08-11T12:07:51.318Z" }, + { url = "https://files.pythonhosted.org/packages/89/db/98aa28bc7e071bfba611ac2ae803c24e96dd3a452b4118c587d3d872c64c/multidict-6.6.4-cp313-cp313t-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:f996b87b420995a9174b2a7c1a8daf7db4750be6848b03eb5e639674f7963773", size = 229321, upload-time = "2025-08-11T12:07:52.965Z" }, + { url = "https://files.pythonhosted.org/packages/c7/bc/01ddda2a73dd9d167bd85d0e8ef4293836a8f82b786c63fb1a429bc3e678/multidict-6.6.4-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cc356250cffd6e78416cf5b40dc6a74f1edf3be8e834cf8862d9ed5265cf9b0e", size = 249954, upload-time = "2025-08-11T12:07:54.423Z" }, + { url = "https://files.pythonhosted.org/packages/06/78/6b7c0f020f9aa0acf66d0ab4eb9f08375bac9a50ff5e3edb1c4ccd59eafc/multidict-6.6.4-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:dadf95aa862714ea468a49ad1e09fe00fcc9ec67d122f6596a8d40caf6cec7d0", size = 228612, upload-time = "2025-08-11T12:07:55.914Z" }, + { url = "https://files.pythonhosted.org/packages/00/44/3faa416f89b2d5d76e9d447296a81521e1c832ad6e40b92f990697b43192/multidict-6.6.4-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7dd57515bebffd8ebd714d101d4c434063322e4fe24042e90ced41f18b6d3395", size = 257528, upload-time = "2025-08-11T12:07:57.371Z" }, + { url = "https://files.pythonhosted.org/packages/05/5f/77c03b89af0fcb16f018f668207768191fb9dcfb5e3361a5e706a11db2c9/multidict-6.6.4-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:967af5f238ebc2eb1da4e77af5492219fbd9b4b812347da39a7b5f5c72c0fa45", size = 256329, upload-time = "2025-08-11T12:07:58.844Z" }, + { url = "https://files.pythonhosted.org/packages/cf/e9/ed750a2a9afb4f8dc6f13dc5b67b514832101b95714f1211cd42e0aafc26/multidict-6.6.4-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2a4c6875c37aae9794308ec43e3530e4aa0d36579ce38d89979bbf89582002bb", size = 247928, upload-time = "2025-08-11T12:08:01.037Z" }, + { url = "https://files.pythonhosted.org/packages/1f/b5/e0571bc13cda277db7e6e8a532791d4403dacc9850006cb66d2556e649c0/multidict-6.6.4-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:7f683a551e92bdb7fac545b9c6f9fa2aebdeefa61d607510b3533286fcab67f5", size = 245228, upload-time = "2025-08-11T12:08:02.96Z" }, + { url = "https://files.pythonhosted.org/packages/f3/a3/69a84b0eccb9824491f06368f5b86e72e4af54c3067c37c39099b6687109/multidict-6.6.4-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:3ba5aaf600edaf2a868a391779f7a85d93bed147854925f34edd24cc70a3e141", size = 235869, upload-time = "2025-08-11T12:08:04.746Z" }, + { url = "https://files.pythonhosted.org/packages/a9/9d/28802e8f9121a6a0804fa009debf4e753d0a59969ea9f70be5f5fdfcb18f/multidict-6.6.4-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:580b643b7fd2c295d83cad90d78419081f53fd532d1f1eb67ceb7060f61cff0d", size = 243446, upload-time = "2025-08-11T12:08:06.332Z" }, + { url = "https://files.pythonhosted.org/packages/38/ea/6c98add069b4878c1d66428a5f5149ddb6d32b1f9836a826ac764b9940be/multidict-6.6.4-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:37b7187197da6af3ee0b044dbc9625afd0c885f2800815b228a0e70f9a7f473d", size = 252299, upload-time = "2025-08-11T12:08:07.931Z" }, + { url = "https://files.pythonhosted.org/packages/3a/09/8fe02d204473e14c0af3affd50af9078839dfca1742f025cca765435d6b4/multidict-6.6.4-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:e1b93790ed0bc26feb72e2f08299691ceb6da5e9e14a0d13cc74f1869af327a0", size = 246926, upload-time = "2025-08-11T12:08:09.467Z" }, + { url = "https://files.pythonhosted.org/packages/37/3d/7b1e10d774a6df5175ecd3c92bff069e77bed9ec2a927fdd4ff5fe182f67/multidict-6.6.4-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:a506a77ddee1efcca81ecbeae27ade3e09cdf21a8ae854d766c2bb4f14053f92", size = 243383, upload-time = "2025-08-11T12:08:10.981Z" }, + { url = "https://files.pythonhosted.org/packages/50/b0/a6fae46071b645ae98786ab738447de1ef53742eaad949f27e960864bb49/multidict-6.6.4-cp313-cp313t-win32.whl", hash = "sha256:f93b2b2279883d1d0a9e1bd01f312d6fc315c5e4c1f09e112e4736e2f650bc4e", size = 47775, upload-time = "2025-08-11T12:08:12.439Z" }, + { url = "https://files.pythonhosted.org/packages/b2/0a/2436550b1520091af0600dff547913cb2d66fbac27a8c33bc1b1bccd8d98/multidict-6.6.4-cp313-cp313t-win_amd64.whl", hash = "sha256:6d46a180acdf6e87cc41dc15d8f5c2986e1e8739dc25dbb7dac826731ef381a4", size = 53100, upload-time = "2025-08-11T12:08:13.823Z" }, + { url = "https://files.pythonhosted.org/packages/97/ea/43ac51faff934086db9c072a94d327d71b7d8b40cd5dcb47311330929ef0/multidict-6.6.4-cp313-cp313t-win_arm64.whl", hash = "sha256:756989334015e3335d087a27331659820d53ba432befdef6a718398b0a8493ad", size = 45501, upload-time = "2025-08-11T12:08:15.173Z" }, + { url = "https://files.pythonhosted.org/packages/d4/d3/f04c5db316caee9b5b2cbba66270b358c922a959855995bedde87134287c/multidict-6.6.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:af7618b591bae552b40dbb6f93f5518328a949dac626ee75927bba1ecdeea9f4", size = 76977, upload-time = "2025-08-11T12:08:16.667Z" }, + { url = "https://files.pythonhosted.org/packages/70/39/a6200417d883e510728ab3caec02d3b66ff09e1c85e0aab2ba311abfdf06/multidict-6.6.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b6819f83aef06f560cb15482d619d0e623ce9bf155115150a85ab11b8342a665", size = 44878, upload-time = "2025-08-11T12:08:18.157Z" }, + { url = "https://files.pythonhosted.org/packages/6f/7e/815be31ed35571b137d65232816f61513fcd97b2717d6a9d7800b5a0c6e0/multidict-6.6.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4d09384e75788861e046330308e7af54dd306aaf20eb760eb1d0de26b2bea2cb", size = 44546, upload-time = "2025-08-11T12:08:19.694Z" }, + { url = "https://files.pythonhosted.org/packages/e2/f1/21b5bff6a8c3e2aff56956c241941ace6b8820e1abe6b12d3c52868a773d/multidict-6.6.4-cp39-cp39-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:a59c63061f1a07b861c004e53869eb1211ffd1a4acbca330e3322efa6dd02978", size = 223020, upload-time = "2025-08-11T12:08:21.554Z" }, + { url = "https://files.pythonhosted.org/packages/15/59/37083f1dd3439979a0ffeb1906818d978d88b4cc7f4600a9f89b1cb6713c/multidict-6.6.4-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:350f6b0fe1ced61e778037fdc7613f4051c8baf64b1ee19371b42a3acdb016a0", size = 240528, upload-time = "2025-08-11T12:08:23.45Z" }, + { url = "https://files.pythonhosted.org/packages/d1/f0/f054d123c87784307a27324c829eb55bcfd2e261eb785fcabbd832c8dc4a/multidict-6.6.4-cp39-cp39-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:0c5cbac6b55ad69cb6aa17ee9343dfbba903118fd530348c330211dc7aa756d1", size = 219540, upload-time = "2025-08-11T12:08:24.965Z" }, + { url = "https://files.pythonhosted.org/packages/e8/26/8f78ce17b7118149c17f238f28fba2a850b660b860f9b024a34d0191030f/multidict-6.6.4-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:630f70c32b8066ddfd920350bc236225814ad94dfa493fe1910ee17fe4365cbb", size = 251182, upload-time = "2025-08-11T12:08:26.511Z" }, + { url = "https://files.pythonhosted.org/packages/00/c3/a21466322d69f6594fe22d9379200f99194d21c12a5bbf8c2a39a46b83b6/multidict-6.6.4-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f8d4916a81697faec6cb724a273bd5457e4c6c43d82b29f9dc02c5542fd21fc9", size = 249371, upload-time = "2025-08-11T12:08:28.075Z" }, + { url = "https://files.pythonhosted.org/packages/c2/8e/2e673124eb05cf8dc82e9265eccde01a36bcbd3193e27799b8377123c976/multidict-6.6.4-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8e42332cf8276bb7645d310cdecca93a16920256a5b01bebf747365f86a1675b", size = 239235, upload-time = "2025-08-11T12:08:29.937Z" }, + { url = "https://files.pythonhosted.org/packages/2b/2d/bdd9f05e7c89e30a4b0e4faf0681a30748f8d1310f68cfdc0e3571e75bd5/multidict-6.6.4-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:f3be27440f7644ab9a13a6fc86f09cdd90b347c3c5e30c6d6d860de822d7cb53", size = 237410, upload-time = "2025-08-11T12:08:31.872Z" }, + { url = "https://files.pythonhosted.org/packages/46/4c/3237b83f8ca9a2673bb08fc340c15da005a80f5cc49748b587c8ae83823b/multidict-6.6.4-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:21f216669109e02ef3e2415ede07f4f8987f00de8cdfa0cc0b3440d42534f9f0", size = 232979, upload-time = "2025-08-11T12:08:33.399Z" }, + { url = "https://files.pythonhosted.org/packages/55/a6/a765decff625ae9bc581aed303cd1837955177dafc558859a69f56f56ba8/multidict-6.6.4-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:d9890d68c45d1aeac5178ded1d1cccf3bc8d7accf1f976f79bf63099fb16e4bd", size = 240979, upload-time = "2025-08-11T12:08:35.02Z" }, + { url = "https://files.pythonhosted.org/packages/6b/2d/9c75975cb0c66ea33cae1443bb265b2b3cd689bffcbc68872565f401da23/multidict-6.6.4-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:edfdcae97cdc5d1a89477c436b61f472c4d40971774ac4729c613b4b133163cb", size = 246849, upload-time = "2025-08-11T12:08:37.038Z" }, + { url = "https://files.pythonhosted.org/packages/3e/71/d21ac0843c1d8751fb5dcf8a1f436625d39d4577bc27829799d09b419af7/multidict-6.6.4-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:0b2e886624be5773e69cf32bcb8534aecdeb38943520b240fed3d5596a430f2f", size = 241798, upload-time = "2025-08-11T12:08:38.669Z" }, + { url = "https://files.pythonhosted.org/packages/94/3d/1d8911e53092837bd11b1c99d71de3e2a9a26f8911f864554677663242aa/multidict-6.6.4-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:be5bf4b3224948032a845d12ab0f69f208293742df96dc14c4ff9b09e508fc17", size = 235315, upload-time = "2025-08-11T12:08:40.266Z" }, + { url = "https://files.pythonhosted.org/packages/86/c5/4b758df96376f73e936b1942c6c2dfc17e37ed9d5ff3b01a811496966ca0/multidict-6.6.4-cp39-cp39-win32.whl", hash = "sha256:10a68a9191f284fe9d501fef4efe93226e74df92ce7a24e301371293bd4918ae", size = 41434, upload-time = "2025-08-11T12:08:41.965Z" }, + { url = "https://files.pythonhosted.org/packages/58/16/f1dfa2a0f25f2717a5e9e5fe8fd30613f7fe95e3530cec8d11f5de0b709c/multidict-6.6.4-cp39-cp39-win_amd64.whl", hash = "sha256:ee25f82f53262f9ac93bd7e58e47ea1bdcc3393cef815847e397cba17e284210", size = 46186, upload-time = "2025-08-11T12:08:43.367Z" }, + { url = "https://files.pythonhosted.org/packages/88/7d/a0568bac65438c494cb6950b29f394d875a796a237536ac724879cf710c9/multidict-6.6.4-cp39-cp39-win_arm64.whl", hash = "sha256:f9867e55590e0855bcec60d4f9a092b69476db64573c9fe17e92b0c50614c16a", size = 43115, upload-time = "2025-08-11T12:08:45.126Z" }, + { url = "https://files.pythonhosted.org/packages/fd/69/b547032297c7e63ba2af494edba695d781af8a0c6e89e4d06cf848b21d80/multidict-6.6.4-py3-none-any.whl", hash = "sha256:27d8f8e125c07cb954e54d75d04905a9bba8a439c1d84aca94949d4d03d8601c", size = 12313, upload-time = "2025-08-11T12:08:46.891Z" }, ] [[package]] @@ -1049,6 +1340,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", size = 4963, upload-time = "2025-04-22T14:54:22.983Z" }, ] +[[package]] +name = "natsort" +version = "8.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e2/a9/a0c57aee75f77794adaf35322f8b6404cbd0f89ad45c87197a937764b7d0/natsort-8.4.0.tar.gz", hash = "sha256:45312c4a0e5507593da193dedd04abb1469253b601ecaf63445ad80f0a1ea581", size = 76575, upload-time = "2023-06-20T04:17:19.925Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ef/82/7a9d0550484a62c6da82858ee9419f3dd1ccc9aa1c26a1e43da3ecd20b0d/natsort-8.4.0-py3-none-any.whl", hash = "sha256:4732914fb471f56b5cce04d7bae6f164a592c7712e1c85f9ef585e197299521c", size = 38268, upload-time = "2023-06-20T04:17:17.522Z" }, +] + [[package]] name = "nodeenv" version = "1.9.1" @@ -1120,7 +1420,7 @@ wheels = [ [[package]] name = "pre-commit" -version = "4.2.0" +version = "4.3.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cfgv" }, @@ -1129,9 +1429,9 @@ dependencies = [ { name = "pyyaml" }, { name = "virtualenv" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/08/39/679ca9b26c7bb2999ff122d50faa301e49af82ca9c066ec061cfbc0c6784/pre_commit-4.2.0.tar.gz", hash = "sha256:601283b9757afd87d40c4c4a9b2b5de9637a8ea02eaff7adc2d0fb4e04841146", size = 193424, upload-time = "2025-03-18T21:35:20.987Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ff/29/7cf5bbc236333876e4b41f56e06857a87937ce4bf91e117a6991a2dbb02a/pre_commit-4.3.0.tar.gz", hash = "sha256:499fe450cc9d42e9d58e606262795ecb64dd05438943c62b66f6a8673da30b16", size = 193792, upload-time = "2025-08-09T18:56:14.651Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/88/74/a88bf1b1efeae488a0c0b7bdf71429c313722d1fc0f377537fbe554e6180/pre_commit-4.2.0-py2.py3-none-any.whl", hash = "sha256:a009ca7205f1eb497d10b845e52c838a98b6cdd2102a6c8e4540e94ee75c58bd", size = 220707, upload-time = "2025-03-18T21:35:19.343Z" }, + { url = "https://files.pythonhosted.org/packages/5b/a5/987a405322d78a73b66e39e4a90e4ef156fd7141bf71df987e50717c321b/pre_commit-4.3.0-py2.py3-none-any.whl", hash = "sha256:2b0747ad7e6e967169136edffee14c16e148a778a54e4f967921aa1ebf2308d8", size = 220965, upload-time = "2025-08-09T18:56:13.192Z" }, ] [[package]] @@ -1452,18 +1752,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/bc/16/4ea354101abb1287856baa4af2732be351c7bee728065aed451b678153fd/pytest_cov-6.2.1-py3-none-any.whl", hash = "sha256:f5bc4c23f42f1cdd23c70b1dab1bbaef4fc505ba950d53e0081d0730dd7e86d5", size = 24644, upload-time = "2025-06-12T10:47:45.932Z" }, ] -[[package]] -name = "python-dateutil" -version = "2.9.0.post0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "six" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432, upload-time = "2024-03-01T18:36:20.211Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" }, -] - [[package]] name = "python-dotenv" version = "1.1.1" @@ -1508,7 +1796,7 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "black" }, { name = "docstring-to-markdown" }, - { name = "importlib-metadata", marker = "python_full_version < '3.10'" }, + { name = "importlib-metadata", version = "8.6.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "jedi" }, { name = "pluggy" }, { name = "python-lsp-jsonrpc" }, @@ -1657,29 +1945,119 @@ tests = [ { name = "python-dotenv", specifier = ">=1.1.1" }, ] +[[package]] +name = "requests" +version = "2.32.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "charset-normalizer" }, + { name = "idna" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c9/74/b3ff8e6c8446842c3f5c837e9c3dfcfe2018ea6ecef224c710c85ef728f4/requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf", size = 134517, upload-time = "2025-08-18T20:46:02.573Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6", size = 64738, upload-time = "2025-08-18T20:46:00.542Z" }, +] + +[[package]] +name = "roman-numerals-py" +version = "3.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/30/76/48fd56d17c5bdbdf65609abbc67288728a98ed4c02919428d4f52d23b24b/roman_numerals_py-3.1.0.tar.gz", hash = "sha256:be4bf804f083a4ce001b5eb7e3c0862479d10f94c936f6c4e5f250aa5ff5bd2d", size = 9017, upload-time = "2025-02-22T07:34:54.333Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/53/97/d2cbbaa10c9b826af0e10fdf836e1bf344d9f0abb873ebc34d1f49642d3f/roman_numerals_py-3.1.0-py3-none-any.whl", hash = "sha256:9da2ad2fb670bcf24e81070ceb3be72f6c11c440d73bd579fbeca1e9f330954c", size = 7742, upload-time = "2025-02-22T07:34:52.422Z" }, +] + +[[package]] +name = "ruamel-yaml" +version = "0.18.15" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "ruamel-yaml-clib", marker = "python_full_version < '3.14' and platform_python_implementation == 'CPython'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/3e/db/f3950f5e5031b618aae9f423a39bf81a55c148aecd15a34527898e752cf4/ruamel.yaml-0.18.15.tar.gz", hash = "sha256:dbfca74b018c4c3fba0b9cc9ee33e53c371194a9000e694995e620490fd40700", size = 146865, upload-time = "2025-08-19T11:15:10.694Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/e5/f2a0621f1781b76a38194acae72f01e37b1941470407345b6e8653ad7640/ruamel.yaml-0.18.15-py3-none-any.whl", hash = "sha256:148f6488d698b7a5eded5ea793a025308b25eca97208181b6a026037f391f701", size = 119702, upload-time = "2025-08-19T11:15:07.696Z" }, +] + +[[package]] +name = "ruamel-yaml-clib" +version = "0.2.12" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/20/84/80203abff8ea4993a87d823a5f632e4d92831ef75d404c9fc78d0176d2b5/ruamel.yaml.clib-0.2.12.tar.gz", hash = "sha256:6c8fbb13ec503f99a91901ab46e0b07ae7941cd527393187039aec586fdfd36f", size = 225315, upload-time = "2024-10-20T10:10:56.22Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/70/57/40a958e863e299f0c74ef32a3bde9f2d1ea8d69669368c0c502a0997f57f/ruamel.yaml.clib-0.2.12-cp310-cp310-macosx_13_0_arm64.whl", hash = "sha256:11f891336688faf5156a36293a9c362bdc7c88f03a8a027c2c1d8e0bcde998e5", size = 131301, upload-time = "2024-10-20T10:12:35.876Z" }, + { url = "https://files.pythonhosted.org/packages/98/a8/29a3eb437b12b95f50a6bcc3d7d7214301c6c529d8fdc227247fa84162b5/ruamel.yaml.clib-0.2.12-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:a606ef75a60ecf3d924613892cc603b154178ee25abb3055db5062da811fd969", size = 633728, upload-time = "2024-10-20T10:12:37.858Z" }, + { url = "https://files.pythonhosted.org/packages/35/6d/ae05a87a3ad540259c3ad88d71275cbd1c0f2d30ae04c65dcbfb6dcd4b9f/ruamel.yaml.clib-0.2.12-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd5415dded15c3822597455bc02bcd66e81ef8b7a48cb71a33628fc9fdde39df", size = 722230, upload-time = "2024-10-20T10:12:39.457Z" }, + { url = "https://files.pythonhosted.org/packages/7f/b7/20c6f3c0b656fe609675d69bc135c03aac9e3865912444be6339207b6648/ruamel.yaml.clib-0.2.12-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f66efbc1caa63c088dead1c4170d148eabc9b80d95fb75b6c92ac0aad2437d76", size = 686712, upload-time = "2024-10-20T10:12:41.119Z" }, + { url = "https://files.pythonhosted.org/packages/cd/11/d12dbf683471f888d354dac59593873c2b45feb193c5e3e0f2ebf85e68b9/ruamel.yaml.clib-0.2.12-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:22353049ba4181685023b25b5b51a574bce33e7f51c759371a7422dcae5402a6", size = 663936, upload-time = "2024-10-21T11:26:37.419Z" }, + { url = "https://files.pythonhosted.org/packages/72/14/4c268f5077db5c83f743ee1daeb236269fa8577133a5cfa49f8b382baf13/ruamel.yaml.clib-0.2.12-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:932205970b9f9991b34f55136be327501903f7c66830e9760a8ffb15b07f05cd", size = 696580, upload-time = "2024-10-21T11:26:39.503Z" }, + { url = "https://files.pythonhosted.org/packages/30/fc/8cd12f189c6405a4c1cf37bd633aa740a9538c8e40497c231072d0fef5cf/ruamel.yaml.clib-0.2.12-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a52d48f4e7bf9005e8f0a89209bf9a73f7190ddf0489eee5eb51377385f59f2a", size = 663393, upload-time = "2024-12-11T19:58:13.873Z" }, + { url = "https://files.pythonhosted.org/packages/80/29/c0a017b704aaf3cbf704989785cd9c5d5b8ccec2dae6ac0c53833c84e677/ruamel.yaml.clib-0.2.12-cp310-cp310-win32.whl", hash = "sha256:3eac5a91891ceb88138c113f9db04f3cebdae277f5d44eaa3651a4f573e6a5da", size = 100326, upload-time = "2024-10-20T10:12:42.967Z" }, + { url = "https://files.pythonhosted.org/packages/3a/65/fa39d74db4e2d0cd252355732d966a460a41cd01c6353b820a0952432839/ruamel.yaml.clib-0.2.12-cp310-cp310-win_amd64.whl", hash = "sha256:ab007f2f5a87bd08ab1499bdf96f3d5c6ad4dcfa364884cb4549aa0154b13a28", size = 118079, upload-time = "2024-10-20T10:12:44.117Z" }, + { url = "https://files.pythonhosted.org/packages/fb/8f/683c6ad562f558cbc4f7c029abcd9599148c51c54b5ef0f24f2638da9fbb/ruamel.yaml.clib-0.2.12-cp311-cp311-macosx_13_0_arm64.whl", hash = "sha256:4a6679521a58256a90b0d89e03992c15144c5f3858f40d7c18886023d7943db6", size = 132224, upload-time = "2024-10-20T10:12:45.162Z" }, + { url = "https://files.pythonhosted.org/packages/3c/d2/b79b7d695e2f21da020bd44c782490578f300dd44f0a4c57a92575758a76/ruamel.yaml.clib-0.2.12-cp311-cp311-manylinux2014_aarch64.whl", hash = "sha256:d84318609196d6bd6da0edfa25cedfbabd8dbde5140a0a23af29ad4b8f91fb1e", size = 641480, upload-time = "2024-10-20T10:12:46.758Z" }, + { url = "https://files.pythonhosted.org/packages/68/6e/264c50ce2a31473a9fdbf4fa66ca9b2b17c7455b31ef585462343818bd6c/ruamel.yaml.clib-0.2.12-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bb43a269eb827806502c7c8efb7ae7e9e9d0573257a46e8e952f4d4caba4f31e", size = 739068, upload-time = "2024-10-20T10:12:48.605Z" }, + { url = "https://files.pythonhosted.org/packages/86/29/88c2567bc893c84d88b4c48027367c3562ae69121d568e8a3f3a8d363f4d/ruamel.yaml.clib-0.2.12-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:811ea1594b8a0fb466172c384267a4e5e367298af6b228931f273b111f17ef52", size = 703012, upload-time = "2024-10-20T10:12:51.124Z" }, + { url = "https://files.pythonhosted.org/packages/11/46/879763c619b5470820f0cd6ca97d134771e502776bc2b844d2adb6e37753/ruamel.yaml.clib-0.2.12-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:cf12567a7b565cbf65d438dec6cfbe2917d3c1bdddfce84a9930b7d35ea59642", size = 704352, upload-time = "2024-10-21T11:26:41.438Z" }, + { url = "https://files.pythonhosted.org/packages/02/80/ece7e6034256a4186bbe50dee28cd032d816974941a6abf6a9d65e4228a7/ruamel.yaml.clib-0.2.12-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7dd5adc8b930b12c8fc5b99e2d535a09889941aa0d0bd06f4749e9a9397c71d2", size = 737344, upload-time = "2024-10-21T11:26:43.62Z" }, + { url = "https://files.pythonhosted.org/packages/f0/ca/e4106ac7e80efbabdf4bf91d3d32fc424e41418458251712f5672eada9ce/ruamel.yaml.clib-0.2.12-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1492a6051dab8d912fc2adeef0e8c72216b24d57bd896ea607cb90bb0c4981d3", size = 714498, upload-time = "2024-12-11T19:58:15.592Z" }, + { url = "https://files.pythonhosted.org/packages/67/58/b1f60a1d591b771298ffa0428237afb092c7f29ae23bad93420b1eb10703/ruamel.yaml.clib-0.2.12-cp311-cp311-win32.whl", hash = "sha256:bd0a08f0bab19093c54e18a14a10b4322e1eacc5217056f3c063bd2f59853ce4", size = 100205, upload-time = "2024-10-20T10:12:52.865Z" }, + { url = "https://files.pythonhosted.org/packages/b4/4f/b52f634c9548a9291a70dfce26ca7ebce388235c93588a1068028ea23fcc/ruamel.yaml.clib-0.2.12-cp311-cp311-win_amd64.whl", hash = "sha256:a274fb2cb086c7a3dea4322ec27f4cb5cc4b6298adb583ab0e211a4682f241eb", size = 118185, upload-time = "2024-10-20T10:12:54.652Z" }, + { url = "https://files.pythonhosted.org/packages/48/41/e7a405afbdc26af961678474a55373e1b323605a4f5e2ddd4a80ea80f628/ruamel.yaml.clib-0.2.12-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:20b0f8dc160ba83b6dcc0e256846e1a02d044e13f7ea74a3d1d56ede4e48c632", size = 133433, upload-time = "2024-10-20T10:12:55.657Z" }, + { url = "https://files.pythonhosted.org/packages/ec/b0/b850385604334c2ce90e3ee1013bd911aedf058a934905863a6ea95e9eb4/ruamel.yaml.clib-0.2.12-cp312-cp312-manylinux2014_aarch64.whl", hash = "sha256:943f32bc9dedb3abff9879edc134901df92cfce2c3d5c9348f172f62eb2d771d", size = 647362, upload-time = "2024-10-20T10:12:57.155Z" }, + { url = "https://files.pythonhosted.org/packages/44/d0/3f68a86e006448fb6c005aee66565b9eb89014a70c491d70c08de597f8e4/ruamel.yaml.clib-0.2.12-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95c3829bb364fdb8e0332c9931ecf57d9be3519241323c5274bd82f709cebc0c", size = 754118, upload-time = "2024-10-20T10:12:58.501Z" }, + { url = "https://files.pythonhosted.org/packages/52/a9/d39f3c5ada0a3bb2870d7db41901125dbe2434fa4f12ca8c5b83a42d7c53/ruamel.yaml.clib-0.2.12-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:749c16fcc4a2b09f28843cda5a193e0283e47454b63ec4b81eaa2242f50e4ccd", size = 706497, upload-time = "2024-10-20T10:13:00.211Z" }, + { url = "https://files.pythonhosted.org/packages/b0/fa/097e38135dadd9ac25aecf2a54be17ddf6e4c23e43d538492a90ab3d71c6/ruamel.yaml.clib-0.2.12-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bf165fef1f223beae7333275156ab2022cffe255dcc51c27f066b4370da81e31", size = 698042, upload-time = "2024-10-21T11:26:46.038Z" }, + { url = "https://files.pythonhosted.org/packages/ec/d5/a659ca6f503b9379b930f13bc6b130c9f176469b73b9834296822a83a132/ruamel.yaml.clib-0.2.12-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:32621c177bbf782ca5a18ba4d7af0f1082a3f6e517ac2a18b3974d4edf349680", size = 745831, upload-time = "2024-10-21T11:26:47.487Z" }, + { url = "https://files.pythonhosted.org/packages/db/5d/36619b61ffa2429eeaefaab4f3374666adf36ad8ac6330d855848d7d36fd/ruamel.yaml.clib-0.2.12-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b82a7c94a498853aa0b272fd5bc67f29008da798d4f93a2f9f289feb8426a58d", size = 715692, upload-time = "2024-12-11T19:58:17.252Z" }, + { url = "https://files.pythonhosted.org/packages/b1/82/85cb92f15a4231c89b95dfe08b09eb6adca929ef7df7e17ab59902b6f589/ruamel.yaml.clib-0.2.12-cp312-cp312-win32.whl", hash = "sha256:e8c4ebfcfd57177b572e2040777b8abc537cdef58a2120e830124946aa9b42c5", size = 98777, upload-time = "2024-10-20T10:13:01.395Z" }, + { url = "https://files.pythonhosted.org/packages/d7/8f/c3654f6f1ddb75daf3922c3d8fc6005b1ab56671ad56ffb874d908bfa668/ruamel.yaml.clib-0.2.12-cp312-cp312-win_amd64.whl", hash = "sha256:0467c5965282c62203273b838ae77c0d29d7638c8a4e3a1c8bdd3602c10904e4", size = 115523, upload-time = "2024-10-20T10:13:02.768Z" }, + { url = "https://files.pythonhosted.org/packages/29/00/4864119668d71a5fa45678f380b5923ff410701565821925c69780356ffa/ruamel.yaml.clib-0.2.12-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:4c8c5d82f50bb53986a5e02d1b3092b03622c02c2eb78e29bec33fd9593bae1a", size = 132011, upload-time = "2024-10-20T10:13:04.377Z" }, + { url = "https://files.pythonhosted.org/packages/7f/5e/212f473a93ae78c669ffa0cb051e3fee1139cb2d385d2ae1653d64281507/ruamel.yaml.clib-0.2.12-cp313-cp313-manylinux2014_aarch64.whl", hash = "sha256:e7e3736715fbf53e9be2a79eb4db68e4ed857017344d697e8b9749444ae57475", size = 642488, upload-time = "2024-10-20T10:13:05.906Z" }, + { url = "https://files.pythonhosted.org/packages/1f/8f/ecfbe2123ade605c49ef769788f79c38ddb1c8fa81e01f4dbf5cf1a44b16/ruamel.yaml.clib-0.2.12-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b7e75b4965e1d4690e93021adfcecccbca7d61c7bddd8e22406ef2ff20d74ef", size = 745066, upload-time = "2024-10-20T10:13:07.26Z" }, + { url = "https://files.pythonhosted.org/packages/e2/a9/28f60726d29dfc01b8decdb385de4ced2ced9faeb37a847bd5cf26836815/ruamel.yaml.clib-0.2.12-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:96777d473c05ee3e5e3c3e999f5d23c6f4ec5b0c38c098b3a5229085f74236c6", size = 701785, upload-time = "2024-10-20T10:13:08.504Z" }, + { url = "https://files.pythonhosted.org/packages/84/7e/8e7ec45920daa7f76046578e4f677a3215fe8f18ee30a9cb7627a19d9b4c/ruamel.yaml.clib-0.2.12-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:3bc2a80e6420ca8b7d3590791e2dfc709c88ab9152c00eeb511c9875ce5778bf", size = 693017, upload-time = "2024-10-21T11:26:48.866Z" }, + { url = "https://files.pythonhosted.org/packages/c5/b3/d650eaade4ca225f02a648321e1ab835b9d361c60d51150bac49063b83fa/ruamel.yaml.clib-0.2.12-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:e188d2699864c11c36cdfdada94d781fd5d6b0071cd9c427bceb08ad3d7c70e1", size = 741270, upload-time = "2024-10-21T11:26:50.213Z" }, + { url = "https://files.pythonhosted.org/packages/87/b8/01c29b924dcbbed75cc45b30c30d565d763b9c4d540545a0eeecffb8f09c/ruamel.yaml.clib-0.2.12-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4f6f3eac23941b32afccc23081e1f50612bdbe4e982012ef4f5797986828cd01", size = 709059, upload-time = "2024-12-11T19:58:18.846Z" }, + { url = "https://files.pythonhosted.org/packages/30/8c/ed73f047a73638257aa9377ad356bea4d96125b305c34a28766f4445cc0f/ruamel.yaml.clib-0.2.12-cp313-cp313-win32.whl", hash = "sha256:6442cb36270b3afb1b4951f060eccca1ce49f3d087ca1ca4563a6eb479cb3de6", size = 98583, upload-time = "2024-10-20T10:13:09.658Z" }, + { url = "https://files.pythonhosted.org/packages/b0/85/e8e751d8791564dd333d5d9a4eab0a7a115f7e349595417fd50ecae3395c/ruamel.yaml.clib-0.2.12-cp313-cp313-win_amd64.whl", hash = "sha256:e5b8daf27af0b90da7bb903a876477a9e6d7270be6146906b276605997c7e9a3", size = 115190, upload-time = "2024-10-20T10:13:10.66Z" }, + { url = "https://files.pythonhosted.org/packages/e5/46/ccdef7a84ad745c37cb3d9a81790f28fbc9adf9c237dba682017b123294e/ruamel.yaml.clib-0.2.12-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:fc4b630cd3fa2cf7fce38afa91d7cfe844a9f75d7f0f36393fa98815e911d987", size = 131834, upload-time = "2024-10-20T10:13:11.72Z" }, + { url = "https://files.pythonhosted.org/packages/29/09/932360f30ad1b7b79f08757e0a6fb8c5392a52cdcc182779158fe66d25ac/ruamel.yaml.clib-0.2.12-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:bc5f1e1c28e966d61d2519f2a3d451ba989f9ea0f2307de7bc45baa526de9e45", size = 636120, upload-time = "2024-10-20T10:13:12.84Z" }, + { url = "https://files.pythonhosted.org/packages/a2/2a/5b27602e7a4344c1334e26bf4739746206b7a60a8acdba33a61473468b73/ruamel.yaml.clib-0.2.12-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a0e060aace4c24dcaf71023bbd7d42674e3b230f7e7b97317baf1e953e5b519", size = 724914, upload-time = "2024-10-20T10:13:14.605Z" }, + { url = "https://files.pythonhosted.org/packages/da/1c/23497017c554fc06ff5701b29355522cff850f626337fff35d9ab352cb18/ruamel.yaml.clib-0.2.12-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e2f1c3765db32be59d18ab3953f43ab62a761327aafc1594a2a1fbe038b8b8a7", size = 689072, upload-time = "2024-10-20T10:13:15.939Z" }, + { url = "https://files.pythonhosted.org/packages/68/e6/f3d4ff3223f9ea49c3b7169ec0268e42bd49f87c70c0e3e853895e4a7ae2/ruamel.yaml.clib-0.2.12-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:d85252669dc32f98ebcd5d36768f5d4faeaeaa2d655ac0473be490ecdae3c285", size = 667091, upload-time = "2024-10-21T11:26:52.274Z" }, + { url = "https://files.pythonhosted.org/packages/84/62/ead07043527642491e5011b143f44b81ef80f1025a96069b7210e0f2f0f3/ruamel.yaml.clib-0.2.12-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e143ada795c341b56de9418c58d028989093ee611aa27ffb9b7f609c00d813ed", size = 699111, upload-time = "2024-10-21T11:26:54.294Z" }, + { url = "https://files.pythonhosted.org/packages/52/b3/fe4d84446f7e4887e3bea7ceff0a7df23790b5ed625f830e79ace88ebefb/ruamel.yaml.clib-0.2.12-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2c59aa6170b990d8d2719323e628aaf36f3bfbc1c26279c0eeeb24d05d2d11c7", size = 666365, upload-time = "2024-12-11T19:58:20.444Z" }, + { url = "https://files.pythonhosted.org/packages/6e/b3/7feb99a00bfaa5c6868617bb7651308afde85e5a0b23cd187fe5de65feeb/ruamel.yaml.clib-0.2.12-cp39-cp39-win32.whl", hash = "sha256:beffaed67936fbbeffd10966a4eb53c402fafd3d6833770516bf7314bc6ffa12", size = 100863, upload-time = "2024-10-20T10:13:17.244Z" }, + { url = "https://files.pythonhosted.org/packages/93/07/de635108684b7a5bb06e432b0930c5a04b6c59efe73bd966d8db3cc208f2/ruamel.yaml.clib-0.2.12-cp39-cp39-win_amd64.whl", hash = "sha256:040ae85536960525ea62868b642bdb0c2cc6021c9f9d507810c0c604e66f5a7b", size = 118653, upload-time = "2024-10-20T10:13:18.289Z" }, +] + [[package]] name = "ruff" -version = "0.12.7" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a1/81/0bd3594fa0f690466e41bd033bdcdf86cba8288345ac77ad4afbe5ec743a/ruff-0.12.7.tar.gz", hash = "sha256:1fc3193f238bc2d7968772c82831a4ff69252f673be371fb49663f0068b7ec71", size = 5197814, upload-time = "2025-07-29T22:32:35.877Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e1/d2/6cb35e9c85e7a91e8d22ab32ae07ac39cc34a71f1009a6f9e4a2a019e602/ruff-0.12.7-py3-none-linux_armv6l.whl", hash = "sha256:76e4f31529899b8c434c3c1dede98c4483b89590e15fb49f2d46183801565303", size = 11852189, upload-time = "2025-07-29T22:31:41.281Z" }, - { url = "https://files.pythonhosted.org/packages/63/5b/a4136b9921aa84638f1a6be7fb086f8cad0fde538ba76bda3682f2599a2f/ruff-0.12.7-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:789b7a03e72507c54fb3ba6209e4bb36517b90f1a3569ea17084e3fd295500fb", size = 12519389, upload-time = "2025-07-29T22:31:54.265Z" }, - { url = "https://files.pythonhosted.org/packages/a8/c9/3e24a8472484269b6b1821794141f879c54645a111ded4b6f58f9ab0705f/ruff-0.12.7-py3-none-macosx_11_0_arm64.whl", hash = "sha256:2e1c2a3b8626339bb6369116e7030a4cf194ea48f49b64bb505732a7fce4f4e3", size = 11743384, upload-time = "2025-07-29T22:31:59.575Z" }, - { url = "https://files.pythonhosted.org/packages/26/7c/458dd25deeb3452c43eaee853c0b17a1e84169f8021a26d500ead77964fd/ruff-0.12.7-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:32dec41817623d388e645612ec70d5757a6d9c035f3744a52c7b195a57e03860", size = 11943759, upload-time = "2025-07-29T22:32:01.95Z" }, - { url = "https://files.pythonhosted.org/packages/7f/8b/658798472ef260ca050e400ab96ef7e85c366c39cf3dfbef4d0a46a528b6/ruff-0.12.7-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:47ef751f722053a5df5fa48d412dbb54d41ab9b17875c6840a58ec63ff0c247c", size = 11654028, upload-time = "2025-07-29T22:32:04.367Z" }, - { url = "https://files.pythonhosted.org/packages/a8/86/9c2336f13b2a3326d06d39178fd3448dcc7025f82514d1b15816fe42bfe8/ruff-0.12.7-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a828a5fc25a3efd3e1ff7b241fd392686c9386f20e5ac90aa9234a5faa12c423", size = 13225209, upload-time = "2025-07-29T22:32:06.952Z" }, - { url = "https://files.pythonhosted.org/packages/76/69/df73f65f53d6c463b19b6b312fd2391dc36425d926ec237a7ed028a90fc1/ruff-0.12.7-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:5726f59b171111fa6a69d82aef48f00b56598b03a22f0f4170664ff4d8298efb", size = 14182353, upload-time = "2025-07-29T22:32:10.053Z" }, - { url = "https://files.pythonhosted.org/packages/58/1e/de6cda406d99fea84b66811c189b5ea139814b98125b052424b55d28a41c/ruff-0.12.7-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:74e6f5c04c4dd4aba223f4fe6e7104f79e0eebf7d307e4f9b18c18362124bccd", size = 13631555, upload-time = "2025-07-29T22:32:12.644Z" }, - { url = "https://files.pythonhosted.org/packages/6f/ae/625d46d5164a6cc9261945a5e89df24457dc8262539ace3ac36c40f0b51e/ruff-0.12.7-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5d0bfe4e77fba61bf2ccadf8cf005d6133e3ce08793bbe870dd1c734f2699a3e", size = 12667556, upload-time = "2025-07-29T22:32:15.312Z" }, - { url = "https://files.pythonhosted.org/packages/55/bf/9cb1ea5e3066779e42ade8d0cd3d3b0582a5720a814ae1586f85014656b6/ruff-0.12.7-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06bfb01e1623bf7f59ea749a841da56f8f653d641bfd046edee32ede7ff6c606", size = 12939784, upload-time = "2025-07-29T22:32:17.69Z" }, - { url = "https://files.pythonhosted.org/packages/55/7f/7ead2663be5627c04be83754c4f3096603bf5e99ed856c7cd29618c691bd/ruff-0.12.7-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:e41df94a957d50083fd09b916d6e89e497246698c3f3d5c681c8b3e7b9bb4ac8", size = 11771356, upload-time = "2025-07-29T22:32:20.134Z" }, - { url = "https://files.pythonhosted.org/packages/17/40/a95352ea16edf78cd3a938085dccc55df692a4d8ba1b3af7accbe2c806b0/ruff-0.12.7-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:4000623300563c709458d0ce170c3d0d788c23a058912f28bbadc6f905d67afa", size = 11612124, upload-time = "2025-07-29T22:32:22.645Z" }, - { url = "https://files.pythonhosted.org/packages/4d/74/633b04871c669e23b8917877e812376827c06df866e1677f15abfadc95cb/ruff-0.12.7-py3-none-musllinux_1_2_i686.whl", hash = "sha256:69ffe0e5f9b2cf2b8e289a3f8945b402a1b19eff24ec389f45f23c42a3dd6fb5", size = 12479945, upload-time = "2025-07-29T22:32:24.765Z" }, - { url = "https://files.pythonhosted.org/packages/be/34/c3ef2d7799c9778b835a76189c6f53c179d3bdebc8c65288c29032e03613/ruff-0.12.7-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:a07a5c8ffa2611a52732bdc67bf88e243abd84fe2d7f6daef3826b59abbfeda4", size = 12998677, upload-time = "2025-07-29T22:32:27.022Z" }, - { url = "https://files.pythonhosted.org/packages/77/ab/aca2e756ad7b09b3d662a41773f3edcbd262872a4fc81f920dc1ffa44541/ruff-0.12.7-py3-none-win32.whl", hash = "sha256:c928f1b2ec59fb77dfdf70e0419408898b63998789cc98197e15f560b9e77f77", size = 11756687, upload-time = "2025-07-29T22:32:29.381Z" }, - { url = "https://files.pythonhosted.org/packages/b4/71/26d45a5042bc71db22ddd8252ca9d01e9ca454f230e2996bb04f16d72799/ruff-0.12.7-py3-none-win_amd64.whl", hash = "sha256:9c18f3d707ee9edf89da76131956aba1270c6348bfee8f6c647de841eac7194f", size = 12912365, upload-time = "2025-07-29T22:32:31.517Z" }, - { url = "https://files.pythonhosted.org/packages/4c/9b/0b8aa09817b63e78d94b4977f18b1fcaead3165a5ee49251c5d5c245bb2d/ruff-0.12.7-py3-none-win_arm64.whl", hash = "sha256:dfce05101dbd11833a0776716d5d1578641b7fddb537fe7fa956ab85d1769b69", size = 11982083, upload-time = "2025-07-29T22:32:33.881Z" }, +version = "0.12.10" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/3b/eb/8c073deb376e46ae767f4961390d17545e8535921d2f65101720ed8bd434/ruff-0.12.10.tar.gz", hash = "sha256:189ab65149d11ea69a2d775343adf5f49bb2426fc4780f65ee33b423ad2e47f9", size = 5310076, upload-time = "2025-08-21T18:23:22.595Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/24/e7/560d049d15585d6c201f9eeacd2fd130def3741323e5ccf123786e0e3c95/ruff-0.12.10-py3-none-linux_armv6l.whl", hash = "sha256:8b593cb0fb55cc8692dac7b06deb29afda78c721c7ccfed22db941201b7b8f7b", size = 11935161, upload-time = "2025-08-21T18:22:26.965Z" }, + { url = "https://files.pythonhosted.org/packages/d1/b0/ad2464922a1113c365d12b8f80ed70fcfb39764288ac77c995156080488d/ruff-0.12.10-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:ebb7333a45d56efc7c110a46a69a1b32365d5c5161e7244aaf3aa20ce62399c1", size = 12660884, upload-time = "2025-08-21T18:22:30.925Z" }, + { url = "https://files.pythonhosted.org/packages/d7/f1/97f509b4108d7bae16c48389f54f005b62ce86712120fd8b2d8e88a7cb49/ruff-0.12.10-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d59e58586829f8e4a9920788f6efba97a13d1fa320b047814e8afede381c6839", size = 11872754, upload-time = "2025-08-21T18:22:34.035Z" }, + { url = "https://files.pythonhosted.org/packages/12/ad/44f606d243f744a75adc432275217296095101f83f966842063d78eee2d3/ruff-0.12.10-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:822d9677b560f1fdeab69b89d1f444bf5459da4aa04e06e766cf0121771ab844", size = 12092276, upload-time = "2025-08-21T18:22:36.764Z" }, + { url = "https://files.pythonhosted.org/packages/06/1f/ed6c265e199568010197909b25c896d66e4ef2c5e1c3808caf461f6f3579/ruff-0.12.10-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:37b4a64f4062a50c75019c61c7017ff598cb444984b638511f48539d3a1c98db", size = 11734700, upload-time = "2025-08-21T18:22:39.822Z" }, + { url = "https://files.pythonhosted.org/packages/63/c5/b21cde720f54a1d1db71538c0bc9b73dee4b563a7dd7d2e404914904d7f5/ruff-0.12.10-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2c6f4064c69d2542029b2a61d39920c85240c39837599d7f2e32e80d36401d6e", size = 13468783, upload-time = "2025-08-21T18:22:42.559Z" }, + { url = "https://files.pythonhosted.org/packages/02/9e/39369e6ac7f2a1848f22fb0b00b690492f20811a1ac5c1fd1d2798329263/ruff-0.12.10-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:059e863ea3a9ade41407ad71c1de2badfbe01539117f38f763ba42a1206f7559", size = 14436642, upload-time = "2025-08-21T18:22:45.612Z" }, + { url = "https://files.pythonhosted.org/packages/e3/03/5da8cad4b0d5242a936eb203b58318016db44f5c5d351b07e3f5e211bb89/ruff-0.12.10-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1bef6161e297c68908b7218fa6e0e93e99a286e5ed9653d4be71e687dff101cf", size = 13859107, upload-time = "2025-08-21T18:22:48.886Z" }, + { url = "https://files.pythonhosted.org/packages/19/19/dd7273b69bf7f93a070c9cec9494a94048325ad18fdcf50114f07e6bf417/ruff-0.12.10-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4f1345fbf8fb0531cd722285b5f15af49b2932742fc96b633e883da8d841896b", size = 12886521, upload-time = "2025-08-21T18:22:51.567Z" }, + { url = "https://files.pythonhosted.org/packages/c0/1d/b4207ec35e7babaee62c462769e77457e26eb853fbdc877af29417033333/ruff-0.12.10-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f68433c4fbc63efbfa3ba5db31727db229fa4e61000f452c540474b03de52a9", size = 13097528, upload-time = "2025-08-21T18:22:54.609Z" }, + { url = "https://files.pythonhosted.org/packages/ff/00/58f7b873b21114456e880b75176af3490d7a2836033779ca42f50de3b47a/ruff-0.12.10-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:141ce3d88803c625257b8a6debf4a0473eb6eed9643a6189b68838b43e78165a", size = 13080443, upload-time = "2025-08-21T18:22:57.413Z" }, + { url = "https://files.pythonhosted.org/packages/12/8c/9e6660007fb10189ccb78a02b41691288038e51e4788bf49b0a60f740604/ruff-0.12.10-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:f3fc21178cd44c98142ae7590f42ddcb587b8e09a3b849cbc84edb62ee95de60", size = 11896759, upload-time = "2025-08-21T18:23:00.473Z" }, + { url = "https://files.pythonhosted.org/packages/67/4c/6d092bb99ea9ea6ebda817a0e7ad886f42a58b4501a7e27cd97371d0ba54/ruff-0.12.10-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:7d1a4e0bdfafcd2e3e235ecf50bf0176f74dd37902f241588ae1f6c827a36c56", size = 11701463, upload-time = "2025-08-21T18:23:03.211Z" }, + { url = "https://files.pythonhosted.org/packages/59/80/d982c55e91df981f3ab62559371380616c57ffd0172d96850280c2b04fa8/ruff-0.12.10-py3-none-musllinux_1_2_i686.whl", hash = "sha256:e67d96827854f50b9e3e8327b031647e7bcc090dbe7bb11101a81a3a2cbf1cc9", size = 12691603, upload-time = "2025-08-21T18:23:06.935Z" }, + { url = "https://files.pythonhosted.org/packages/ad/37/63a9c788bbe0b0850611669ec6b8589838faf2f4f959647f2d3e320383ae/ruff-0.12.10-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:ae479e1a18b439c59138f066ae79cc0f3ee250712a873d00dbafadaad9481e5b", size = 13164356, upload-time = "2025-08-21T18:23:10.225Z" }, + { url = "https://files.pythonhosted.org/packages/47/d4/1aaa7fb201a74181989970ebccd12f88c0fc074777027e2a21de5a90657e/ruff-0.12.10-py3-none-win32.whl", hash = "sha256:9de785e95dc2f09846c5e6e1d3a3d32ecd0b283a979898ad427a9be7be22b266", size = 11896089, upload-time = "2025-08-21T18:23:14.232Z" }, + { url = "https://files.pythonhosted.org/packages/ad/14/2ad38fd4037daab9e023456a4a40ed0154e9971f8d6aed41bdea390aabd9/ruff-0.12.10-py3-none-win_amd64.whl", hash = "sha256:7837eca8787f076f67aba2ca559cefd9c5cbc3a9852fd66186f4201b87c1563e", size = 13004616, upload-time = "2025-08-21T18:23:17.422Z" }, + { url = "https://files.pythonhosted.org/packages/24/3c/21cf283d67af33a8e6ed242396863af195a8a6134ec581524fd22b9811b6/ruff-0.12.10-py3-none-win_arm64.whl", hash = "sha256:cc138cc06ed9d4bfa9d667a65af7172b47840e1a98b02ce7011c391e54635ffc", size = 12074225, upload-time = "2025-08-21T18:23:20.137Z" }, ] [[package]] @@ -1710,17 +2088,423 @@ wheels = [ ] [[package]] -name = "storage3" -version = "0.12.0" +name = "snowballstemmer" +version = "3.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/75/a7/9810d872919697c9d01295633f5d574fb416d47e535f258272ca1f01f447/snowballstemmer-3.0.1.tar.gz", hash = "sha256:6d5eeeec8e9f84d4d56b847692bacf79bc2c8e90c7f80ca4444ff8b6f2e52895", size = 105575, upload-time = "2025-05-09T16:34:51.843Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c8/78/3565d011c61f5a43488987ee32b6f3f656e7f107ac2782dd57bdd7d91d9a/snowballstemmer-3.0.1-py3-none-any.whl", hash = "sha256:6cd7b3897da8d6c9ffb968a6781fa6532dce9c3618a4b127d920dab764a19064", size = 103274, upload-time = "2025-05-09T16:34:50.371Z" }, +] + +[[package]] +name = "soupsieve" +version = "2.7" source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/3f/f4/4a80cd6ef364b2e8b65b15816a843c0980f7a5a2b4dc701fc574952aa19f/soupsieve-2.7.tar.gz", hash = "sha256:ad282f9b6926286d2ead4750552c8a6142bc4c783fd66b0293547c8fe6ae126a", size = 103418, upload-time = "2025-04-20T18:50:08.518Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e7/9c/0e6afc12c269578be5c0c1c9f4b49a8d32770a080260c333ac04cc1c832d/soupsieve-2.7-py3-none-any.whl", hash = "sha256:6e60cc5c1ffaf1cebcc12e8188320b72071e922c2e897f737cadce79ad5d30c4", size = 36677, upload-time = "2025-04-20T18:50:07.196Z" }, +] + +[[package]] +name = "sphinx" +version = "7.4.7" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.10'", +] +dependencies = [ + { name = "alabaster", version = "0.7.16", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "babel", marker = "python_full_version < '3.10'" }, + { name = "colorama", marker = "python_full_version < '3.10' and sys_platform == 'win32'" }, + { name = "docutils", marker = "python_full_version < '3.10'" }, + { name = "imagesize", marker = "python_full_version < '3.10'" }, + { name = "importlib-metadata", version = "8.6.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "jinja2", marker = "python_full_version < '3.10'" }, + { name = "packaging", marker = "python_full_version < '3.10'" }, + { name = "pygments", marker = "python_full_version < '3.10'" }, + { name = "requests", marker = "python_full_version < '3.10'" }, + { name = "snowballstemmer", marker = "python_full_version < '3.10'" }, + { name = "sphinxcontrib-applehelp", marker = "python_full_version < '3.10'" }, + { name = "sphinxcontrib-devhelp", marker = "python_full_version < '3.10'" }, + { name = "sphinxcontrib-htmlhelp", marker = "python_full_version < '3.10'" }, + { name = "sphinxcontrib-jsmath", marker = "python_full_version < '3.10'" }, + { name = "sphinxcontrib-qthelp", marker = "python_full_version < '3.10'" }, + { name = "sphinxcontrib-serializinghtml", marker = "python_full_version < '3.10'" }, + { name = "tomli", marker = "python_full_version < '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5b/be/50e50cb4f2eff47df05673d361095cafd95521d2a22521b920c67a372dcb/sphinx-7.4.7.tar.gz", hash = "sha256:242f92a7ea7e6c5b406fdc2615413890ba9f699114a9c09192d7dfead2ee9cfe", size = 8067911, upload-time = "2024-07-20T14:46:56.059Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0d/ef/153f6803c5d5f8917dbb7f7fcf6d34a871ede3296fa89c2c703f5f8a6c8e/sphinx-7.4.7-py3-none-any.whl", hash = "sha256:c2419e2135d11f1951cd994d6eb18a1835bd8fdd8429f9ca375dc1f3281bd239", size = 3401624, upload-time = "2024-07-20T14:46:52.142Z" }, +] + +[[package]] +name = "sphinx" +version = "8.1.3" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version == '3.10.*'", +] +dependencies = [ + { name = "alabaster", version = "1.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, + { name = "babel", marker = "python_full_version == '3.10.*'" }, + { name = "colorama", marker = "python_full_version == '3.10.*' and sys_platform == 'win32'" }, + { name = "docutils", marker = "python_full_version == '3.10.*'" }, + { name = "imagesize", marker = "python_full_version == '3.10.*'" }, + { name = "jinja2", marker = "python_full_version == '3.10.*'" }, + { name = "packaging", marker = "python_full_version == '3.10.*'" }, + { name = "pygments", marker = "python_full_version == '3.10.*'" }, + { name = "requests", marker = "python_full_version == '3.10.*'" }, + { name = "snowballstemmer", marker = "python_full_version == '3.10.*'" }, + { name = "sphinxcontrib-applehelp", marker = "python_full_version == '3.10.*'" }, + { name = "sphinxcontrib-devhelp", marker = "python_full_version == '3.10.*'" }, + { name = "sphinxcontrib-htmlhelp", marker = "python_full_version == '3.10.*'" }, + { name = "sphinxcontrib-jsmath", marker = "python_full_version == '3.10.*'" }, + { name = "sphinxcontrib-qthelp", marker = "python_full_version == '3.10.*'" }, + { name = "sphinxcontrib-serializinghtml", marker = "python_full_version == '3.10.*'" }, + { name = "tomli", marker = "python_full_version == '3.10.*'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/6f/6d/be0b61178fe2cdcb67e2a92fc9ebb488e3c51c4f74a36a7824c0adf23425/sphinx-8.1.3.tar.gz", hash = "sha256:43c1911eecb0d3e161ad78611bc905d1ad0e523e4ddc202a58a821773dc4c927", size = 8184611, upload-time = "2024-10-13T20:27:13.93Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/26/60/1ddff83a56d33aaf6f10ec8ce84b4c007d9368b21008876fceda7e7381ef/sphinx-8.1.3-py3-none-any.whl", hash = "sha256:09719015511837b76bf6e03e42eb7595ac8c2e41eeb9c29c5b755c6b677992a2", size = 3487125, upload-time = "2024-10-13T20:27:10.448Z" }, +] + +[[package]] +name = "sphinx" +version = "8.2.3" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.13'", + "python_full_version >= '3.11' and python_full_version < '3.13'", +] +dependencies = [ + { name = "alabaster", version = "1.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "babel", marker = "python_full_version >= '3.11'" }, + { name = "colorama", marker = "python_full_version >= '3.11' and sys_platform == 'win32'" }, + { name = "docutils", marker = "python_full_version >= '3.11'" }, + { name = "imagesize", marker = "python_full_version >= '3.11'" }, + { name = "jinja2", marker = "python_full_version >= '3.11'" }, + { name = "packaging", marker = "python_full_version >= '3.11'" }, + { name = "pygments", marker = "python_full_version >= '3.11'" }, + { name = "requests", marker = "python_full_version >= '3.11'" }, + { name = "roman-numerals-py", marker = "python_full_version >= '3.11'" }, + { name = "snowballstemmer", marker = "python_full_version >= '3.11'" }, + { name = "sphinxcontrib-applehelp", marker = "python_full_version >= '3.11'" }, + { name = "sphinxcontrib-devhelp", marker = "python_full_version >= '3.11'" }, + { name = "sphinxcontrib-htmlhelp", marker = "python_full_version >= '3.11'" }, + { name = "sphinxcontrib-jsmath", marker = "python_full_version >= '3.11'" }, + { name = "sphinxcontrib-qthelp", marker = "python_full_version >= '3.11'" }, + { name = "sphinxcontrib-serializinghtml", marker = "python_full_version >= '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/38/ad/4360e50ed56cb483667b8e6dadf2d3fda62359593faabbe749a27c4eaca6/sphinx-8.2.3.tar.gz", hash = "sha256:398ad29dee7f63a75888314e9424d40f52ce5a6a87ae88e7071e80af296ec348", size = 8321876, upload-time = "2025-03-02T22:31:59.658Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/31/53/136e9eca6e0b9dc0e1962e2c908fbea2e5ac000c2a2fbd9a35797958c48b/sphinx-8.2.3-py3-none-any.whl", hash = "sha256:4405915165f13521d875a8c29c8970800a0141c14cc5416a38feca4ea5d9b9c3", size = 3589741, upload-time = "2025-03-02T22:31:56.836Z" }, +] + +[[package]] +name = "sphinx-autodoc-typehints" +version = "2.3.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.10'", +] +dependencies = [ + { name = "sphinx", version = "7.4.7", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/74/cd/03e7b917230dc057922130a79ba0240df1693bfd76727ea33fae84b39138/sphinx_autodoc_typehints-2.3.0.tar.gz", hash = "sha256:535c78ed2d6a1bad393ba9f3dfa2602cf424e2631ee207263e07874c38fde084", size = 40709, upload-time = "2024-08-29T16:25:48.343Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a0/f3/e0a4ce49da4b6f4e4ce84b3c39a0677831884cb9d8a87ccbf1e9e56e53ac/sphinx_autodoc_typehints-2.3.0-py3-none-any.whl", hash = "sha256:3098e2c6d0ba99eacd013eb06861acc9b51c6e595be86ab05c08ee5506ac0c67", size = 19836, upload-time = "2024-08-29T16:25:46.707Z" }, +] + +[[package]] +name = "sphinx-autodoc-typehints" +version = "3.0.1" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version == '3.10.*'", +] +dependencies = [ + { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/26/f0/43c6a5ff3e7b08a8c3b32f81b859f1b518ccc31e45f22e2b41ced38be7b9/sphinx_autodoc_typehints-3.0.1.tar.gz", hash = "sha256:b9b40dd15dee54f6f810c924f863f9cf1c54f9f3265c495140ea01be7f44fa55", size = 36282, upload-time = "2025-01-16T18:25:30.958Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3c/dc/dc46c5c7c566b7ec5e8f860f9c89533bf03c0e6aadc96fb9b337867e4460/sphinx_autodoc_typehints-3.0.1-py3-none-any.whl", hash = "sha256:4b64b676a14b5b79cefb6628a6dc8070e320d4963e8ff640a2f3e9390ae9045a", size = 20245, upload-time = "2025-01-16T18:25:27.394Z" }, +] + +[[package]] +name = "sphinx-autodoc-typehints" +version = "3.2.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.13'", + "python_full_version >= '3.11' and python_full_version < '3.13'", +] +dependencies = [ + { name = "sphinx", version = "8.2.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/93/68/a388a9b8f066cd865d9daa65af589d097efbfab9a8c302d2cb2daa43b52e/sphinx_autodoc_typehints-3.2.0.tar.gz", hash = "sha256:107ac98bc8b4837202c88c0736d59d6da44076e65a0d7d7d543a78631f662a9b", size = 36724, upload-time = "2025-04-25T16:53:25.872Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f7/c7/8aab362e86cbf887e58be749a78d20ad743e1eb2c73c2b13d4761f39a104/sphinx_autodoc_typehints-3.2.0-py3-none-any.whl", hash = "sha256:884b39be23b1d884dcc825d4680c9c6357a476936e3b381a67ae80091984eb49", size = 20563, upload-time = "2025-04-25T16:53:24.492Z" }, +] + +[[package]] +name = "sphinx-jinja2-compat" +version = "0.4.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jinja2" }, + { name = "markupsafe" }, + { name = "standard-imghdr", marker = "python_full_version >= '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/43/98/43313781f29e8c6c46fec907430310172d6f207e95e4fbea9289990fbbfe/sphinx_jinja2_compat-0.4.1.tar.gz", hash = "sha256:0188f0802d42c3da72997533b55a00815659a78d3f81d4b4747b1fb15a5728e6", size = 5222, upload-time = "2025-08-06T20:06:25.824Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ce/c8/4fd58c1000d7f8f5572c507f4550d2e2d9741e500c68eb2e3da17cbe5a85/sphinx_jinja2_compat-0.4.1-py3-none-any.whl", hash = "sha256:64ca0d46f0d8029fbe69ea612793a55e6ef0113e1bba4a85d402158c09f17a14", size = 8123, upload-time = "2025-08-06T20:06:24.947Z" }, +] + +[[package]] +name = "sphinx-press-theme" +version = "0.9.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "sphinx", version = "7.4.7", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, + { name = "sphinx", version = "8.2.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e7/25/8769ef130d57ea449309a4ee2d76eed653063b5de27d34100822e34e7e93/sphinx_press_theme-0.9.1.tar.gz", hash = "sha256:1643dee7365f7831d1d3971b389b7c255641a7aced75f0681f71574e380046cf", size = 254696, upload-time = "2024-03-23T01:39:02.384Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cf/28/fbd928e5dcde4f8acdc7b2b730685dafb35d83437cc0b955332349e12b89/sphinx_press_theme-0.9.1-py3-none-any.whl", hash = "sha256:eed3fdd8df249b67136b507dfc6a84d1a2c5feca5376960c6d4d28ada4f6cdf7", size = 83558, upload-time = "2024-03-23T01:39:00.525Z" }, +] + +[[package]] +name = "sphinx-prompt" +version = "1.8.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.10'", +] +dependencies = [ + { name = "docutils", marker = "python_full_version < '3.10'" }, + { name = "pygments", marker = "python_full_version < '3.10'" }, + { name = "sphinx", version = "7.4.7", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e7/fb/7a07b8df1ca2418147a6b13e3f6b445071f2565198b45efa631d0d6ef0cd/sphinx_prompt-1.8.0.tar.gz", hash = "sha256:47482f86fcec29662fdfd23e7c04ef03582714195d01f5d565403320084372ed", size = 5121, upload-time = "2023-09-14T12:46:13.449Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/39/49/f890a2668b7cbf375f5528b549c8d36dd2e801b0fbb7b2b5ef65663ecb6c/sphinx_prompt-1.8.0-py3-none-any.whl", hash = "sha256:369ecc633f0711886f9b3a078c83264245be1adf46abeeb9b88b5519e4b51007", size = 7298, upload-time = "2023-09-14T12:46:12.373Z" }, +] + +[[package]] +name = "sphinx-prompt" +version = "1.9.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.13'", + "python_full_version >= '3.11' and python_full_version < '3.13'", + "python_full_version == '3.10.*'", +] +dependencies = [ + { name = "certifi", marker = "python_full_version >= '3.10'" }, + { name = "docutils", marker = "python_full_version >= '3.10'" }, + { name = "idna", marker = "python_full_version >= '3.10'" }, + { name = "pygments", marker = "python_full_version >= '3.10'" }, + { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, + { name = "sphinx", version = "8.2.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "urllib3", marker = "python_full_version >= '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/34/fe/ac4e24f35b5148b31ac717ae7dcc7a2f7ec56eb729e22c7252ed8ad2d9a5/sphinx_prompt-1.9.0.tar.gz", hash = "sha256:471b3c6d466dce780a9b167d9541865fd4e9a80ed46e31b06a52a0529ae995a1", size = 5340, upload-time = "2024-08-07T15:46:51.428Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/76/98/e90ca466e0ede452d3e5a8d92b8fb68db6de269856e019ed9cab69440522/sphinx_prompt-1.9.0-py3-none-any.whl", hash = "sha256:fd731446c03f043d1ff6df9f22414495b23067c67011cc21658ea8d36b3575fc", size = 7311, upload-time = "2024-08-07T15:46:50.329Z" }, +] + +[[package]] +name = "sphinx-tabs" +version = "3.4.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "docutils" }, + { name = "pygments" }, + { name = "sphinx", version = "7.4.7", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, + { name = "sphinx", version = "8.2.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/27/32/ab475e252dc2b704e82a91141fa404cdd8901a5cf34958fd22afacebfccd/sphinx-tabs-3.4.5.tar.gz", hash = "sha256:ba9d0c1e3e37aaadd4b5678449eb08176770e0fc227e769b6ce747df3ceea531", size = 16070, upload-time = "2024-01-21T12:13:39.392Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/20/9f/4ac7dbb9f23a2ff5a10903a4f9e9f43e0ff051f63a313e989c962526e305/sphinx_tabs-3.4.5-py3-none-any.whl", hash = "sha256:92cc9473e2ecf1828ca3f6617d0efc0aa8acb06b08c56ba29d1413f2f0f6cf09", size = 9904, upload-time = "2024-01-21T12:13:37.67Z" }, +] + +[[package]] +name = "sphinx-toolbox" +version = "4.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "apeye" }, + { name = "autodocsumm" }, + { name = "beautifulsoup4" }, + { name = "cachecontrol", extra = ["filecache"] }, + { name = "dict2css" }, + { name = "docutils" }, + { name = "domdf-python-tools" }, + { name = "filelock" }, + { name = "html5lib" }, + { name = "ruamel-yaml" }, + { name = "sphinx", version = "7.4.7", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, + { name = "sphinx", version = "8.2.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "sphinx-autodoc-typehints", version = "2.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "sphinx-autodoc-typehints", version = "3.0.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, + { name = "sphinx-autodoc-typehints", version = "3.2.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "sphinx-jinja2-compat" }, + { name = "sphinx-prompt", version = "1.8.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "sphinx-prompt", version = "1.9.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "sphinx-tabs" }, + { name = "tabulate" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/60/d2/fd68940102a02cbff392b91317618e0f87458e98a9684c0f74b1c58d4e49/sphinx_toolbox-4.0.0.tar.gz", hash = "sha256:48c31451db2e2d8c71c03939e72a19ef7bc92ca7850a62db63fc7bb8395b6785", size = 113819, upload-time = "2025-05-12T17:11:39.104Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/77/fd/5f03a1ad6623b3533a4b7ce8156f0b6a185f4a276d12567e434b855040d1/sphinx_toolbox-4.0.0-py3-none-any.whl", hash = "sha256:c700937baee505e440d44d46bc47ccd036ec282ae61b04e40342944128721117", size = 195781, upload-time = "2025-05-12T17:11:37.45Z" }, +] + +[[package]] +name = "sphinxcontrib-applehelp" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ba/6e/b837e84a1a704953c62ef8776d45c3e8d759876b4a84fe14eba2859106fe/sphinxcontrib_applehelp-2.0.0.tar.gz", hash = "sha256:2f29ef331735ce958efa4734873f084941970894c6090408b079c61b2e1c06d1", size = 20053, upload-time = "2024-07-29T01:09:00.465Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5d/85/9ebeae2f76e9e77b952f4b274c27238156eae7979c5421fba91a28f4970d/sphinxcontrib_applehelp-2.0.0-py3-none-any.whl", hash = "sha256:4cd3f0ec4ac5dd9c17ec65e9ab272c9b867ea77425228e68ecf08d6b28ddbdb5", size = 119300, upload-time = "2024-07-29T01:08:58.99Z" }, +] + +[[package]] +name = "sphinxcontrib-devhelp" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f6/d2/5beee64d3e4e747f316bae86b55943f51e82bb86ecd325883ef65741e7da/sphinxcontrib_devhelp-2.0.0.tar.gz", hash = "sha256:411f5d96d445d1d73bb5d52133377b4248ec79db5c793ce7dbe59e074b4dd1ad", size = 12967, upload-time = "2024-07-29T01:09:23.417Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/35/7a/987e583882f985fe4d7323774889ec58049171828b58c2217e7f79cdf44e/sphinxcontrib_devhelp-2.0.0-py3-none-any.whl", hash = "sha256:aefb8b83854e4b0998877524d1029fd3e6879210422ee3780459e28a1f03a8a2", size = 82530, upload-time = "2024-07-29T01:09:21.945Z" }, +] + +[[package]] +name = "sphinxcontrib-htmlhelp" +version = "2.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/43/93/983afd9aa001e5201eab16b5a444ed5b9b0a7a010541e0ddfbbfd0b2470c/sphinxcontrib_htmlhelp-2.1.0.tar.gz", hash = "sha256:c9e2916ace8aad64cc13a0d233ee22317f2b9025b9cf3295249fa985cc7082e9", size = 22617, upload-time = "2024-07-29T01:09:37.889Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0a/7b/18a8c0bcec9182c05a0b3ec2a776bba4ead82750a55ff798e8d406dae604/sphinxcontrib_htmlhelp-2.1.0-py3-none-any.whl", hash = "sha256:166759820b47002d22914d64a075ce08f4c46818e17cfc9470a9786b759b19f8", size = 98705, upload-time = "2024-07-29T01:09:36.407Z" }, +] + +[[package]] +name = "sphinxcontrib-jsmath" +version = "1.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b2/e8/9ed3830aeed71f17c026a07a5097edcf44b692850ef215b161b8ad875729/sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8", size = 5787, upload-time = "2019-01-21T16:10:16.347Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c2/42/4c8646762ee83602e3fb3fbe774c2fac12f317deb0b5dbeeedd2d3ba4b77/sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178", size = 5071, upload-time = "2019-01-21T16:10:14.333Z" }, +] + +[[package]] +name = "sphinxcontrib-qthelp" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/68/bc/9104308fc285eb3e0b31b67688235db556cd5b0ef31d96f30e45f2e51cae/sphinxcontrib_qthelp-2.0.0.tar.gz", hash = "sha256:4fe7d0ac8fc171045be623aba3e2a8f613f8682731f9153bb2e40ece16b9bbab", size = 17165, upload-time = "2024-07-29T01:09:56.435Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/27/83/859ecdd180cacc13b1f7e857abf8582a64552ea7a061057a6c716e790fce/sphinxcontrib_qthelp-2.0.0-py3-none-any.whl", hash = "sha256:b18a828cdba941ccd6ee8445dbe72ffa3ef8cbe7505d8cd1fa0d42d3f2d5f3eb", size = 88743, upload-time = "2024-07-29T01:09:54.885Z" }, +] + +[[package]] +name = "sphinxcontrib-serializinghtml" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/3b/44/6716b257b0aa6bfd51a1b31665d1c205fb12cb5ad56de752dfa15657de2f/sphinxcontrib_serializinghtml-2.0.0.tar.gz", hash = "sha256:e9d912827f872c029017a53f0ef2180b327c3f7fd23c87229f7a8e8b70031d4d", size = 16080, upload-time = "2024-07-29T01:10:09.332Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/52/a7/d2782e4e3f77c8450f727ba74a8f12756d5ba823d81b941f1b04da9d033a/sphinxcontrib_serializinghtml-2.0.0-py3-none-any.whl", hash = "sha256:6e2cb0eef194e10c27ec0023bfeb25badbbb5868244cf5bc5bdc04e4464bf331", size = 92072, upload-time = "2024-07-29T01:10:08.203Z" }, +] + +[[package]] +name = "standard-imghdr" +version = "3.10.14" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/09/d2/2eb5521072c9598886035c65c023f39f7384bcb73eed70794f469e34efac/standard_imghdr-3.10.14.tar.gz", hash = "sha256:2598fe2e7c540dbda34b233295e10957ab8dc8ac6f3bd9eaa8d38be167232e52", size = 5474, upload-time = "2024-04-21T18:55:10.859Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fb/d0/9852f70eb01f814843530c053542b72d30e9fbf74da7abb0107e71938389/standard_imghdr-3.10.14-py3-none-any.whl", hash = "sha256:cdf6883163349624dee9a81d2853a20260337c4cd41c04e99c082e01833a08e2", size = 5598, upload-time = "2024-04-21T18:54:48.587Z" }, +] + +[[package]] +name = "storage3" +version = "0.12.1" +source = { editable = "src/storage" } dependencies = [ { name = "deprecation" }, { name = "httpx", extra = ["http2"] }, - { name = "python-dateutil" }, + { name = "pydantic" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c5/86/9eae84e8ad4ba73f575f3eaf5536d949f2fd7d6adc85829f9af04bce97e2/storage3-0.12.0.tar.gz", hash = "sha256:94243f20922d57738bf42e96b9f5582b4d166e8bf209eccf20b146909f3f71b0", size = 10024, upload-time = "2025-06-19T17:50:51.763Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/b0/7e/693d6d603db142eb5e6f3cb76eb6e9c439582b7539e2695e175e2de3ac44/storage3-0.12.0-py3-none-any.whl", hash = "sha256:1c4585693ca42243ded1512b58e54c697111e91a20916cd14783eebc37e7c87d", size = 18422, upload-time = "2025-06-19T17:50:50.294Z" }, + +[package.dev-dependencies] +dev = [ + { name = "pre-commit" }, + { name = "pytest" }, + { name = "pytest-asyncio" }, + { name = "pytest-cov" }, + { name = "python-dotenv" }, + { name = "ruff" }, + { name = "sphinx", version = "7.4.7", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, + { name = "sphinx", version = "8.2.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "sphinx-press-theme" }, + { name = "sphinx-toolbox" }, + { name = "unasync" }, +] +docs = [ + { name = "sphinx", version = "7.4.7", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, + { name = "sphinx", version = "8.2.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "sphinx-press-theme" }, + { name = "sphinx-toolbox" }, +] +lints = [ + { name = "pre-commit" }, + { name = "ruff" }, + { name = "unasync" }, +] +tests = [ + { name = "pytest" }, + { name = "pytest-asyncio" }, + { name = "pytest-cov" }, + { name = "python-dotenv" }, +] + +[package.metadata] +requires-dist = [ + { name = "deprecation", specifier = ">=2.1.0" }, + { name = "httpx", extras = ["http2"], specifier = ">=0.26,<0.29" }, + { name = "pydantic", specifier = ">=2.11.7" }, +] + +[package.metadata.requires-dev] +dev = [ + { name = "pre-commit", specifier = ">=4.2.0" }, + { name = "pytest", specifier = ">=8.3.5" }, + { name = "pytest-asyncio", specifier = ">=0.21.0" }, + { name = "pytest-cov", specifier = ">=6.1.0" }, + { name = "python-dotenv", specifier = ">=1.1.0" }, + { name = "ruff", specifier = ">=0.12.1" }, + { name = "sphinx", specifier = ">=7.1.2" }, + { name = "sphinx-press-theme", specifier = ">=0.9.1" }, + { name = "sphinx-toolbox", specifier = ">=3.4.0" }, + { name = "unasync", specifier = ">=0.6.0" }, +] +docs = [ + { name = "sphinx", specifier = ">=7.1.2" }, + { name = "sphinx-press-theme", specifier = ">=0.9.1" }, + { name = "sphinx-toolbox", specifier = ">=3.4.0" }, +] +lints = [ + { name = "pre-commit", specifier = ">=4.2.0" }, + { name = "ruff", specifier = ">=0.12.1" }, + { name = "unasync", specifier = ">=0.6.0" }, +] +tests = [ + { name = "pytest", specifier = ">=8.3.5" }, + { name = "pytest-asyncio", specifier = ">=0.21.0" }, + { name = "pytest-cov", specifier = ">=6.1.0" }, + { name = "python-dotenv", specifier = ">=1.1.0" }, ] [[package]] @@ -1776,7 +2560,7 @@ requires-dist = [ { name = "httpx", specifier = ">=0.26,<0.29" }, { name = "postgrest", specifier = "==1.1.1" }, { name = "realtime", editable = "src/realtime" }, - { name = "storage3", specifier = "==0.12.0" }, + { name = "storage3", editable = "src/storage" }, { name = "supabase-auth", specifier = "==2.12.3" }, { name = "supabase-functions", editable = "src/functions" }, ] @@ -1878,6 +2662,15 @@ tests = [ { name = "pytest-cov", specifier = ">=4,<7" }, ] +[[package]] +name = "tabulate" +version = "0.9.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ec/fe/802052aecb21e3797b8f7902564ab6ea0d60ff8ca23952079064155d1ae1/tabulate-0.9.0.tar.gz", hash = "sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c", size = 81090, upload-time = "2022-10-06T17:21:48.54Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/40/44/4a5f08c96eb108af5cb50b41f76142f0afa346dfa99d5296fe7202a11854/tabulate-0.9.0-py3-none-any.whl", hash = "sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f", size = 35252, upload-time = "2022-10-06T17:21:44.262Z" }, +] + [[package]] name = "termcolor" version = "3.1.0" @@ -1967,72 +2760,93 @@ wheels = [ [[package]] name = "ujson" -version = "5.10.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f0/00/3110fd566786bfa542adb7932d62035e0c0ef662a8ff6544b6643b3d6fd7/ujson-5.10.0.tar.gz", hash = "sha256:b3cd8f3c5d8c7738257f1018880444f7b7d9b66232c64649f562d7ba86ad4bc1", size = 7154885, upload-time = "2024-05-14T02:02:34.233Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/7d/91/91678e49a9194f527e60115db84368c237ac7824992224fac47dcb23a5c6/ujson-5.10.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2601aa9ecdbee1118a1c2065323bda35e2c5a2cf0797ef4522d485f9d3ef65bd", size = 55354, upload-time = "2024-05-14T02:00:27.054Z" }, - { url = "https://files.pythonhosted.org/packages/de/2f/1ed8c9b782fa4f44c26c1c4ec686d728a4865479da5712955daeef0b2e7b/ujson-5.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:348898dd702fc1c4f1051bc3aacbf894caa0927fe2c53e68679c073375f732cf", size = 51808, upload-time = "2024-05-14T02:00:29.461Z" }, - { url = "https://files.pythonhosted.org/packages/51/bf/a3a38b2912288143e8e613c6c4c3f798b5e4e98c542deabf94c60237235f/ujson-5.10.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22cffecf73391e8abd65ef5f4e4dd523162a3399d5e84faa6aebbf9583df86d6", size = 51995, upload-time = "2024-05-14T02:00:30.93Z" }, - { url = "https://files.pythonhosted.org/packages/b4/6d/0df8f7a6f1944ba619d93025ce468c9252aa10799d7140e07014dfc1a16c/ujson-5.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26b0e2d2366543c1bb4fbd457446f00b0187a2bddf93148ac2da07a53fe51569", size = 53566, upload-time = "2024-05-14T02:00:33.091Z" }, - { url = "https://files.pythonhosted.org/packages/d5/ec/370741e5e30d5f7dc7f31a478d5bec7537ce6bfb7f85e72acefbe09aa2b2/ujson-5.10.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:caf270c6dba1be7a41125cd1e4fc7ba384bf564650beef0df2dd21a00b7f5770", size = 58499, upload-time = "2024-05-14T02:00:34.742Z" }, - { url = "https://files.pythonhosted.org/packages/fe/29/72b33a88f7fae3c398f9ba3e74dc2e5875989b25f1c1f75489c048a2cf4e/ujson-5.10.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a245d59f2ffe750446292b0094244df163c3dc96b3ce152a2c837a44e7cda9d1", size = 997881, upload-time = "2024-05-14T02:00:36.492Z" }, - { url = "https://files.pythonhosted.org/packages/70/5c/808fbf21470e7045d56a282cf5e85a0450eacdb347d871d4eb404270ee17/ujson-5.10.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:94a87f6e151c5f483d7d54ceef83b45d3a9cca7a9cb453dbdbb3f5a6f64033f5", size = 1140631, upload-time = "2024-05-14T02:00:38.995Z" }, - { url = "https://files.pythonhosted.org/packages/8f/6a/e1e8281408e6270d6ecf2375af14d9e2f41c402ab6b161ecfa87a9727777/ujson-5.10.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:29b443c4c0a113bcbb792c88bea67b675c7ca3ca80c3474784e08bba01c18d51", size = 1043511, upload-time = "2024-05-14T02:00:41.352Z" }, - { url = "https://files.pythonhosted.org/packages/cb/ca/e319acbe4863919ec62498bc1325309f5c14a3280318dca10fe1db3cb393/ujson-5.10.0-cp310-cp310-win32.whl", hash = "sha256:c18610b9ccd2874950faf474692deee4223a994251bc0a083c114671b64e6518", size = 38626, upload-time = "2024-05-14T02:00:43.483Z" }, - { url = "https://files.pythonhosted.org/packages/78/ec/dc96ca379de33f73b758d72e821ee4f129ccc32221f4eb3f089ff78d8370/ujson-5.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:924f7318c31874d6bb44d9ee1900167ca32aa9b69389b98ecbde34c1698a250f", size = 42076, upload-time = "2024-05-14T02:00:46.56Z" }, - { url = "https://files.pythonhosted.org/packages/23/ec/3c551ecfe048bcb3948725251fb0214b5844a12aa60bee08d78315bb1c39/ujson-5.10.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a5b366812c90e69d0f379a53648be10a5db38f9d4ad212b60af00bd4048d0f00", size = 55353, upload-time = "2024-05-14T02:00:48.04Z" }, - { url = "https://files.pythonhosted.org/packages/8d/9f/4731ef0671a0653e9f5ba18db7c4596d8ecbf80c7922dd5fe4150f1aea76/ujson-5.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:502bf475781e8167f0f9d0e41cd32879d120a524b22358e7f205294224c71126", size = 51813, upload-time = "2024-05-14T02:00:49.28Z" }, - { url = "https://files.pythonhosted.org/packages/1f/2b/44d6b9c1688330bf011f9abfdb08911a9dc74f76926dde74e718d87600da/ujson-5.10.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b91b5d0d9d283e085e821651184a647699430705b15bf274c7896f23fe9c9d8", size = 51988, upload-time = "2024-05-14T02:00:50.484Z" }, - { url = "https://files.pythonhosted.org/packages/29/45/f5f5667427c1ec3383478092a414063ddd0dfbebbcc533538fe37068a0a3/ujson-5.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:129e39af3a6d85b9c26d5577169c21d53821d8cf68e079060602e861c6e5da1b", size = 53561, upload-time = "2024-05-14T02:00:52.146Z" }, - { url = "https://files.pythonhosted.org/packages/26/21/a0c265cda4dd225ec1be595f844661732c13560ad06378760036fc622587/ujson-5.10.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f77b74475c462cb8b88680471193064d3e715c7c6074b1c8c412cb526466efe9", size = 58497, upload-time = "2024-05-14T02:00:53.366Z" }, - { url = "https://files.pythonhosted.org/packages/28/36/8fde862094fd2342ccc427a6a8584fed294055fdee341661c78660f7aef3/ujson-5.10.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7ec0ca8c415e81aa4123501fee7f761abf4b7f386aad348501a26940beb1860f", size = 997877, upload-time = "2024-05-14T02:00:55.095Z" }, - { url = "https://files.pythonhosted.org/packages/90/37/9208e40d53baa6da9b6a1c719e0670c3f474c8fc7cc2f1e939ec21c1bc93/ujson-5.10.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ab13a2a9e0b2865a6c6db9271f4b46af1c7476bfd51af1f64585e919b7c07fd4", size = 1140632, upload-time = "2024-05-14T02:00:57.099Z" }, - { url = "https://files.pythonhosted.org/packages/89/d5/2626c87c59802863d44d19e35ad16b7e658e4ac190b0dead17ff25460b4c/ujson-5.10.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:57aaf98b92d72fc70886b5a0e1a1ca52c2320377360341715dd3933a18e827b1", size = 1043513, upload-time = "2024-05-14T02:00:58.488Z" }, - { url = "https://files.pythonhosted.org/packages/2f/ee/03662ce9b3f16855770f0d70f10f0978ba6210805aa310c4eebe66d36476/ujson-5.10.0-cp311-cp311-win32.whl", hash = "sha256:2987713a490ceb27edff77fb184ed09acdc565db700ee852823c3dc3cffe455f", size = 38616, upload-time = "2024-05-14T02:01:00.463Z" }, - { url = "https://files.pythonhosted.org/packages/3e/20/952dbed5895835ea0b82e81a7be4ebb83f93b079d4d1ead93fcddb3075af/ujson-5.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:f00ea7e00447918ee0eff2422c4add4c5752b1b60e88fcb3c067d4a21049a720", size = 42071, upload-time = "2024-05-14T02:01:02.211Z" }, - { url = "https://files.pythonhosted.org/packages/e8/a6/fd3f8bbd80842267e2d06c3583279555e8354c5986c952385199d57a5b6c/ujson-5.10.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:98ba15d8cbc481ce55695beee9f063189dce91a4b08bc1d03e7f0152cd4bbdd5", size = 55642, upload-time = "2024-05-14T02:01:04.055Z" }, - { url = "https://files.pythonhosted.org/packages/a8/47/dd03fd2b5ae727e16d5d18919b383959c6d269c7b948a380fdd879518640/ujson-5.10.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a9d2edbf1556e4f56e50fab7d8ff993dbad7f54bac68eacdd27a8f55f433578e", size = 51807, upload-time = "2024-05-14T02:01:05.25Z" }, - { url = "https://files.pythonhosted.org/packages/25/23/079a4cc6fd7e2655a473ed9e776ddbb7144e27f04e8fc484a0fb45fe6f71/ujson-5.10.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6627029ae4f52d0e1a2451768c2c37c0c814ffc04f796eb36244cf16b8e57043", size = 51972, upload-time = "2024-05-14T02:01:06.458Z" }, - { url = "https://files.pythonhosted.org/packages/04/81/668707e5f2177791869b624be4c06fb2473bf97ee33296b18d1cf3092af7/ujson-5.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8ccb77b3e40b151e20519c6ae6d89bfe3f4c14e8e210d910287f778368bb3d1", size = 53686, upload-time = "2024-05-14T02:01:07.618Z" }, - { url = "https://files.pythonhosted.org/packages/bd/50/056d518a386d80aaf4505ccf3cee1c40d312a46901ed494d5711dd939bc3/ujson-5.10.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3caf9cd64abfeb11a3b661329085c5e167abbe15256b3b68cb5d914ba7396f3", size = 58591, upload-time = "2024-05-14T02:01:08.901Z" }, - { url = "https://files.pythonhosted.org/packages/fc/d6/aeaf3e2d6fb1f4cfb6bf25f454d60490ed8146ddc0600fae44bfe7eb5a72/ujson-5.10.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6e32abdce572e3a8c3d02c886c704a38a1b015a1fb858004e03d20ca7cecbb21", size = 997853, upload-time = "2024-05-14T02:01:10.772Z" }, - { url = "https://files.pythonhosted.org/packages/f8/d5/1f2a5d2699f447f7d990334ca96e90065ea7f99b142ce96e85f26d7e78e2/ujson-5.10.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a65b6af4d903103ee7b6f4f5b85f1bfd0c90ba4eeac6421aae436c9988aa64a2", size = 1140689, upload-time = "2024-05-14T02:01:12.214Z" }, - { url = "https://files.pythonhosted.org/packages/f2/2c/6990f4ccb41ed93744aaaa3786394bca0875503f97690622f3cafc0adfde/ujson-5.10.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:604a046d966457b6cdcacc5aa2ec5314f0e8c42bae52842c1e6fa02ea4bda42e", size = 1043576, upload-time = "2024-05-14T02:01:14.39Z" }, - { url = "https://files.pythonhosted.org/packages/14/f5/a2368463dbb09fbdbf6a696062d0c0f62e4ae6fa65f38f829611da2e8fdd/ujson-5.10.0-cp312-cp312-win32.whl", hash = "sha256:6dea1c8b4fc921bf78a8ff00bbd2bfe166345f5536c510671bccececb187c80e", size = 38764, upload-time = "2024-05-14T02:01:15.83Z" }, - { url = "https://files.pythonhosted.org/packages/59/2d/691f741ffd72b6c84438a93749ac57bf1a3f217ac4b0ea4fd0e96119e118/ujson-5.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:38665e7d8290188b1e0d57d584eb8110951a9591363316dd41cf8686ab1d0abc", size = 42211, upload-time = "2024-05-14T02:01:17.567Z" }, - { url = "https://files.pythonhosted.org/packages/0d/69/b3e3f924bb0e8820bb46671979770c5be6a7d51c77a66324cdb09f1acddb/ujson-5.10.0-cp313-cp313-macosx_10_9_x86_64.whl", hash = "sha256:618efd84dc1acbd6bff8eaa736bb6c074bfa8b8a98f55b61c38d4ca2c1f7f287", size = 55646, upload-time = "2024-05-14T02:01:19.26Z" }, - { url = "https://files.pythonhosted.org/packages/32/8a/9b748eb543c6cabc54ebeaa1f28035b1bd09c0800235b08e85990734c41e/ujson-5.10.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:38d5d36b4aedfe81dfe251f76c0467399d575d1395a1755de391e58985ab1c2e", size = 51806, upload-time = "2024-05-14T02:01:20.593Z" }, - { url = "https://files.pythonhosted.org/packages/39/50/4b53ea234413b710a18b305f465b328e306ba9592e13a791a6a6b378869b/ujson-5.10.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67079b1f9fb29ed9a2914acf4ef6c02844b3153913eb735d4bf287ee1db6e557", size = 51975, upload-time = "2024-05-14T02:01:21.904Z" }, - { url = "https://files.pythonhosted.org/packages/b4/9d/8061934f960cdb6dd55f0b3ceeff207fcc48c64f58b43403777ad5623d9e/ujson-5.10.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7d0e0ceeb8fe2468c70ec0c37b439dd554e2aa539a8a56365fd761edb418988", size = 53693, upload-time = "2024-05-14T02:01:23.742Z" }, - { url = "https://files.pythonhosted.org/packages/f5/be/7bfa84b28519ddbb67efc8410765ca7da55e6b93aba84d97764cd5794dbc/ujson-5.10.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:59e02cd37bc7c44d587a0ba45347cc815fb7a5fe48de16bf05caa5f7d0d2e816", size = 58594, upload-time = "2024-05-14T02:01:25.554Z" }, - { url = "https://files.pythonhosted.org/packages/48/eb/85d465abafb2c69d9699cfa5520e6e96561db787d36c677370e066c7e2e7/ujson-5.10.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2a890b706b64e0065f02577bf6d8ca3b66c11a5e81fb75d757233a38c07a1f20", size = 997853, upload-time = "2024-05-14T02:01:27.151Z" }, - { url = "https://files.pythonhosted.org/packages/9f/76/2a63409fc05d34dd7d929357b7a45e3a2c96f22b4225cd74becd2ba6c4cb/ujson-5.10.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:621e34b4632c740ecb491efc7f1fcb4f74b48ddb55e65221995e74e2d00bbff0", size = 1140694, upload-time = "2024-05-14T02:01:29.113Z" }, - { url = "https://files.pythonhosted.org/packages/45/ed/582c4daba0f3e1688d923b5cb914ada1f9defa702df38a1916c899f7c4d1/ujson-5.10.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b9500e61fce0cfc86168b248104e954fead61f9be213087153d272e817ec7b4f", size = 1043580, upload-time = "2024-05-14T02:01:31.447Z" }, - { url = "https://files.pythonhosted.org/packages/d7/0c/9837fece153051e19c7bade9f88f9b409e026b9525927824cdf16293b43b/ujson-5.10.0-cp313-cp313-win32.whl", hash = "sha256:4c4fc16f11ac1612f05b6f5781b384716719547e142cfd67b65d035bd85af165", size = 38766, upload-time = "2024-05-14T02:01:32.856Z" }, - { url = "https://files.pythonhosted.org/packages/d7/72/6cb6728e2738c05bbe9bd522d6fc79f86b9a28402f38663e85a28fddd4a0/ujson-5.10.0-cp313-cp313-win_amd64.whl", hash = "sha256:4573fd1695932d4f619928fd09d5d03d917274381649ade4328091ceca175539", size = 42212, upload-time = "2024-05-14T02:01:33.97Z" }, - { url = "https://files.pythonhosted.org/packages/97/94/50ff2f1b61d668907f20216873640ab19e0eaa77b51e64ee893f6adfb266/ujson-5.10.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:dfef2814c6b3291c3c5f10065f745a1307d86019dbd7ea50e83504950136ed5b", size = 55421, upload-time = "2024-05-14T02:01:49.765Z" }, - { url = "https://files.pythonhosted.org/packages/0c/b3/3d2ca621d8dbeaf6c5afd0725e1b4bbd465077acc69eff1e9302735d1432/ujson-5.10.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4734ee0745d5928d0ba3a213647f1c4a74a2a28edc6d27b2d6d5bd9fa4319e27", size = 51816, upload-time = "2024-05-14T02:01:51.047Z" }, - { url = "https://files.pythonhosted.org/packages/8d/af/5dc103cb4d08f051f82d162a738adb9da488d1e3fafb9fd9290ea3eabf8e/ujson-5.10.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d47ebb01bd865fdea43da56254a3930a413f0c5590372a1241514abae8aa7c76", size = 52023, upload-time = "2024-05-14T02:01:53.072Z" }, - { url = "https://files.pythonhosted.org/packages/5d/dd/b9a6027ba782b0072bf24a70929e15a58686668c32a37aebfcfaa9e00bdd/ujson-5.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dee5e97c2496874acbf1d3e37b521dd1f307349ed955e62d1d2f05382bc36dd5", size = 53622, upload-time = "2024-05-14T02:01:54.738Z" }, - { url = "https://files.pythonhosted.org/packages/1f/28/bcf6df25c1a9f1989dc2ddc4ac8a80e246857e089f91a9079fd8a0a01459/ujson-5.10.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7490655a2272a2d0b072ef16b0b58ee462f4973a8f6bbe64917ce5e0a256f9c0", size = 58563, upload-time = "2024-05-14T02:01:55.991Z" }, - { url = "https://files.pythonhosted.org/packages/9e/82/89404453a102d06d0937f6807c0a7ef2eec68b200b4ce4386127f3c28156/ujson-5.10.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:ba17799fcddaddf5c1f75a4ba3fd6441f6a4f1e9173f8a786b42450851bd74f1", size = 998050, upload-time = "2024-05-14T02:01:57.8Z" }, - { url = "https://files.pythonhosted.org/packages/63/eb/2a4ea07165cad217bc842bb684b053bafa8ffdb818c47911c621e97a33fc/ujson-5.10.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:2aff2985cef314f21d0fecc56027505804bc78802c0121343874741650a4d3d1", size = 1140672, upload-time = "2024-05-14T02:01:59.875Z" }, - { url = "https://files.pythonhosted.org/packages/72/53/d7bdf6afabeba3ed899f89d993c7f202481fa291d8c5be031c98a181eda4/ujson-5.10.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:ad88ac75c432674d05b61184178635d44901eb749786c8eb08c102330e6e8996", size = 1043577, upload-time = "2024-05-14T02:02:02.138Z" }, - { url = "https://files.pythonhosted.org/packages/19/b1/75f5f0d18501fd34487e46829de3070724c7b350f1983ba7f07e0986720b/ujson-5.10.0-cp39-cp39-win32.whl", hash = "sha256:2544912a71da4ff8c4f7ab5606f947d7299971bdd25a45e008e467ca638d13c9", size = 38654, upload-time = "2024-05-14T02:02:03.71Z" }, - { url = "https://files.pythonhosted.org/packages/77/0d/50d2f9238f6d6683ead5ecd32d83d53f093a3c0047ae4c720b6d586cb80d/ujson-5.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:3ff201d62b1b177a46f113bb43ad300b424b7847f9c5d38b1b4ad8f75d4a282a", size = 42134, upload-time = "2024-05-14T02:02:05.013Z" }, - { url = "https://files.pythonhosted.org/packages/95/53/e5f5e733fc3525e65f36f533b0dbece5e5e2730b760e9beacf7e3d9d8b26/ujson-5.10.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:5b6fee72fa77dc172a28f21693f64d93166534c263adb3f96c413ccc85ef6e64", size = 51846, upload-time = "2024-05-14T02:02:06.347Z" }, - { url = "https://files.pythonhosted.org/packages/59/1f/f7bc02a54ea7b47f3dc2d125a106408f18b0f47b14fc737f0913483ae82b/ujson-5.10.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:61d0af13a9af01d9f26d2331ce49bb5ac1fb9c814964018ac8df605b5422dcb3", size = 48103, upload-time = "2024-05-14T02:02:07.777Z" }, - { url = "https://files.pythonhosted.org/packages/1a/3a/d3921b6f29bc744d8d6c56db5f8bbcbe55115fd0f2b79c3c43ff292cc7c9/ujson-5.10.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ecb24f0bdd899d368b715c9e6664166cf694d1e57be73f17759573a6986dd95a", size = 47257, upload-time = "2024-05-14T02:02:09.46Z" }, - { url = "https://files.pythonhosted.org/packages/f1/04/f4e3883204b786717038064afd537389ba7d31a72b437c1372297cb651ea/ujson-5.10.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fbd8fd427f57a03cff3ad6574b5e299131585d9727c8c366da4624a9069ed746", size = 48468, upload-time = "2024-05-14T02:02:10.768Z" }, - { url = "https://files.pythonhosted.org/packages/17/cd/9c6547169eb01a22b04cbb638804ccaeb3c2ec2afc12303464e0f9b2ee5a/ujson-5.10.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:beeaf1c48e32f07d8820c705ff8e645f8afa690cca1544adba4ebfa067efdc88", size = 54266, upload-time = "2024-05-14T02:02:12.109Z" }, - { url = "https://files.pythonhosted.org/packages/70/bf/ecd14d3cf6127f8a990b01f0ad20e257f5619a555f47d707c57d39934894/ujson-5.10.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:baed37ea46d756aca2955e99525cc02d9181de67f25515c468856c38d52b5f3b", size = 42224, upload-time = "2024-05-14T02:02:13.843Z" }, - { url = "https://files.pythonhosted.org/packages/8d/96/a3a2356ca5a4b67fe32a0c31e49226114d5154ba2464bb1220a93eb383e8/ujson-5.10.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ba43cc34cce49cf2d4bc76401a754a81202d8aa926d0e2b79f0ee258cb15d3a4", size = 51855, upload-time = "2024-05-14T02:02:22.164Z" }, - { url = "https://files.pythonhosted.org/packages/73/3d/41e78e7500e75eb6b5a7ab06907a6df35603b92ac6f939b86f40e9fe2c06/ujson-5.10.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:ac56eb983edce27e7f51d05bc8dd820586c6e6be1c5216a6809b0c668bb312b8", size = 48059, upload-time = "2024-05-14T02:02:23.673Z" }, - { url = "https://files.pythonhosted.org/packages/be/14/e435cbe5b5189483adbba5fe328e88418ccd54b2b1f74baa4172384bb5cd/ujson-5.10.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f44bd4b23a0e723bf8b10628288c2c7c335161d6840013d4d5de20e48551773b", size = 47238, upload-time = "2024-05-14T02:02:24.873Z" }, - { url = "https://files.pythonhosted.org/packages/e8/d9/b6f4d1e6bec20a3b582b48f64eaa25209fd70dc2892b21656b273bc23434/ujson-5.10.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7c10f4654e5326ec14a46bcdeb2b685d4ada6911050aa8baaf3501e57024b804", size = 48457, upload-time = "2024-05-14T02:02:26.186Z" }, - { url = "https://files.pythonhosted.org/packages/23/1c/cfefabb5996e21a1a4348852df7eb7cfc69299143739e86e5b1071c78735/ujson-5.10.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0de4971a89a762398006e844ae394bd46991f7c385d7a6a3b93ba229e6dac17e", size = 54238, upload-time = "2024-05-14T02:02:28.468Z" }, - { url = "https://files.pythonhosted.org/packages/af/c4/fa70e77e1c27bbaf682d790bd09ef40e86807ada704c528ef3ea3418d439/ujson-5.10.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:e1402f0564a97d2a52310ae10a64d25bcef94f8dd643fcf5d310219d915484f7", size = 42230, upload-time = "2024-05-14T02:02:29.678Z" }, +version = "5.11.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/43/d9/3f17e3c5773fb4941c68d9a37a47b1a79c9649d6c56aefbed87cc409d18a/ujson-5.11.0.tar.gz", hash = "sha256:e204ae6f909f099ba6b6b942131cee359ddda2b6e4ea39c12eb8b991fe2010e0", size = 7156583, upload-time = "2025-08-20T11:57:02.452Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/86/0c/8bf7a4fabfd01c7eed92d9b290930ce6d14910dec708e73538baa38885d1/ujson-5.11.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:446e8c11c06048611c9d29ef1237065de0af07cabdd97e6b5b527b957692ec25", size = 55248, upload-time = "2025-08-20T11:55:02.368Z" }, + { url = "https://files.pythonhosted.org/packages/7b/2e/eeab0b8b641817031ede4f790db4c4942df44a12f44d72b3954f39c6a115/ujson-5.11.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:16ccb973b7ada0455201808ff11d48fe9c3f034a6ab5bd93b944443c88299f89", size = 53157, upload-time = "2025-08-20T11:55:04.012Z" }, + { url = "https://files.pythonhosted.org/packages/21/1b/a4e7a41870797633423ea79618526747353fd7be9191f3acfbdee0bf264b/ujson-5.11.0-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3134b783ab314d2298d58cda7e47e7a0f7f71fc6ade6ac86d5dbeaf4b9770fa6", size = 57657, upload-time = "2025-08-20T11:55:05.169Z" }, + { url = "https://files.pythonhosted.org/packages/94/ae/4e0d91b8f6db7c9b76423b3649612189506d5a06ddd3b6334b6d37f77a01/ujson-5.11.0-cp310-cp310-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:185f93ebccffebc8baf8302c869fac70dd5dd78694f3b875d03a31b03b062cdb", size = 59780, upload-time = "2025-08-20T11:55:06.325Z" }, + { url = "https://files.pythonhosted.org/packages/b3/cc/46b124c2697ca2da7c65c4931ed3cb670646978157aa57a7a60f741c530f/ujson-5.11.0-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d06e87eded62ff0e5f5178c916337d2262fdbc03b31688142a3433eabb6511db", size = 57307, upload-time = "2025-08-20T11:55:07.493Z" }, + { url = "https://files.pythonhosted.org/packages/39/eb/20dd1282bc85dede2f1c62c45b4040bc4c389c80a05983515ab99771bca7/ujson-5.11.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:181fb5b15703a8b9370b25345d2a1fd1359f0f18776b3643d24e13ed9c036d4c", size = 1036369, upload-time = "2025-08-20T11:55:09.192Z" }, + { url = "https://files.pythonhosted.org/packages/64/a2/80072439065d493e3a4b1fbeec991724419a1b4c232e2d1147d257cac193/ujson-5.11.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:a4df61a6df0a4a8eb5b9b1ffd673429811f50b235539dac586bb7e9e91994138", size = 1195738, upload-time = "2025-08-20T11:55:11.402Z" }, + { url = "https://files.pythonhosted.org/packages/5d/7e/d77f9e9c039d58299c350c978e086a804d1fceae4fd4a1cc6e8d0133f838/ujson-5.11.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:6eff24e1abd79e0ec6d7eae651dd675ddbc41f9e43e29ef81e16b421da896915", size = 1088718, upload-time = "2025-08-20T11:55:13.297Z" }, + { url = "https://files.pythonhosted.org/packages/ab/f1/697559d45acc849cada6b3571d53522951b1a64027400507aabc6a710178/ujson-5.11.0-cp310-cp310-win32.whl", hash = "sha256:30f607c70091483550fbd669a0b37471e5165b317d6c16e75dba2aa967608723", size = 39653, upload-time = "2025-08-20T11:55:14.869Z" }, + { url = "https://files.pythonhosted.org/packages/86/a2/70b73a0f55abe0e6b8046d365d74230c20c5691373e6902a599b2dc79ba1/ujson-5.11.0-cp310-cp310-win_amd64.whl", hash = "sha256:3d2720e9785f84312b8e2cb0c2b87f1a0b1c53aaab3b2af3ab817d54409012e0", size = 43720, upload-time = "2025-08-20T11:55:15.897Z" }, + { url = "https://files.pythonhosted.org/packages/1c/5f/b19104afa455630b43efcad3a24495b9c635d92aa8f2da4f30e375deb1a2/ujson-5.11.0-cp310-cp310-win_arm64.whl", hash = "sha256:85e6796631165f719084a9af00c79195d3ebf108151452fefdcb1c8bb50f0105", size = 38410, upload-time = "2025-08-20T11:55:17.556Z" }, + { url = "https://files.pythonhosted.org/packages/da/ea/80346b826349d60ca4d612a47cdf3533694e49b45e9d1c07071bb867a184/ujson-5.11.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d7c46cb0fe5e7056b9acb748a4c35aa1b428025853032540bb7e41f46767321f", size = 55248, upload-time = "2025-08-20T11:55:19.033Z" }, + { url = "https://files.pythonhosted.org/packages/57/df/b53e747562c89515e18156513cc7c8ced2e5e3fd6c654acaa8752ffd7cd9/ujson-5.11.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d8951bb7a505ab2a700e26f691bdfacf395bc7e3111e3416d325b513eea03a58", size = 53156, upload-time = "2025-08-20T11:55:20.174Z" }, + { url = "https://files.pythonhosted.org/packages/41/b8/ab67ec8c01b8a3721fd13e5cb9d85ab2a6066a3a5e9148d661a6870d6293/ujson-5.11.0-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:952c0be400229940248c0f5356514123d428cba1946af6fa2bbd7503395fef26", size = 57657, upload-time = "2025-08-20T11:55:21.296Z" }, + { url = "https://files.pythonhosted.org/packages/7b/c7/fb84f27cd80a2c7e2d3c6012367aecade0da936790429801803fa8d4bffc/ujson-5.11.0-cp311-cp311-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:94fcae844f1e302f6f8095c5d1c45a2f0bfb928cccf9f1b99e3ace634b980a2a", size = 59779, upload-time = "2025-08-20T11:55:22.772Z" }, + { url = "https://files.pythonhosted.org/packages/5d/7c/48706f7c1e917ecb97ddcfb7b1d756040b86ed38290e28579d63bd3fcc48/ujson-5.11.0-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7e0ec1646db172beb8d3df4c32a9d78015e671d2000af548252769e33079d9a6", size = 57284, upload-time = "2025-08-20T11:55:24.01Z" }, + { url = "https://files.pythonhosted.org/packages/ec/ce/48877c6eb4afddfd6bd1db6be34456538c07ca2d6ed233d3f6c6efc2efe8/ujson-5.11.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:da473b23e3a54448b008d33f742bcd6d5fb2a897e42d1fc6e7bf306ea5d18b1b", size = 1036395, upload-time = "2025-08-20T11:55:25.725Z" }, + { url = "https://files.pythonhosted.org/packages/8b/7a/2c20dc97ad70cd7c31ad0596ba8e2cf8794d77191ba4d1e0bded69865477/ujson-5.11.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:aa6b3d4f1c0d3f82930f4cbd7fe46d905a4a9205a7c13279789c1263faf06dba", size = 1195731, upload-time = "2025-08-20T11:55:27.915Z" }, + { url = "https://files.pythonhosted.org/packages/15/f5/ca454f2f6a2c840394b6f162fff2801450803f4ff56c7af8ce37640b8a2a/ujson-5.11.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4843f3ab4fe1cc596bb7e02228ef4c25d35b4bb0809d6a260852a4bfcab37ba3", size = 1088710, upload-time = "2025-08-20T11:55:29.426Z" }, + { url = "https://files.pythonhosted.org/packages/fe/d3/9ba310e07969bc9906eb7548731e33a0f448b122ad9705fed699c9b29345/ujson-5.11.0-cp311-cp311-win32.whl", hash = "sha256:e979fbc469a7f77f04ec2f4e853ba00c441bf2b06720aa259f0f720561335e34", size = 39648, upload-time = "2025-08-20T11:55:31.194Z" }, + { url = "https://files.pythonhosted.org/packages/57/f7/da05b4a8819f1360be9e71fb20182f0bb3ec611a36c3f213f4d20709e099/ujson-5.11.0-cp311-cp311-win_amd64.whl", hash = "sha256:683f57f0dd3acdd7d9aff1de0528d603aafcb0e6d126e3dc7ce8b020a28f5d01", size = 43717, upload-time = "2025-08-20T11:55:32.241Z" }, + { url = "https://files.pythonhosted.org/packages/9a/cc/f3f9ac0f24f00a623a48d97dc3814df5c2dc368cfb00031aa4141527a24b/ujson-5.11.0-cp311-cp311-win_arm64.whl", hash = "sha256:7855ccea3f8dad5e66d8445d754fc1cf80265a4272b5f8059ebc7ec29b8d0835", size = 38402, upload-time = "2025-08-20T11:55:33.641Z" }, + { url = "https://files.pythonhosted.org/packages/b9/ef/a9cb1fce38f699123ff012161599fb9f2ff3f8d482b4b18c43a2dc35073f/ujson-5.11.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7895f0d2d53bd6aea11743bd56e3cb82d729980636cd0ed9b89418bf66591702", size = 55434, upload-time = "2025-08-20T11:55:34.987Z" }, + { url = "https://files.pythonhosted.org/packages/b1/05/dba51a00eb30bd947791b173766cbed3492269c150a7771d2750000c965f/ujson-5.11.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:12b5e7e22a1fe01058000d1b317d3b65cc3daf61bd2ea7a2b76721fe160fa74d", size = 53190, upload-time = "2025-08-20T11:55:36.384Z" }, + { url = "https://files.pythonhosted.org/packages/03/3c/fd11a224f73fbffa299fb9644e425f38b38b30231f7923a088dd513aabb4/ujson-5.11.0-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0180a480a7d099082501cad1fe85252e4d4bf926b40960fb3d9e87a3a6fbbc80", size = 57600, upload-time = "2025-08-20T11:55:37.692Z" }, + { url = "https://files.pythonhosted.org/packages/55/b9/405103cae24899df688a3431c776e00528bd4799e7d68820e7ebcf824f92/ujson-5.11.0-cp312-cp312-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:fa79fdb47701942c2132a9dd2297a1a85941d966d8c87bfd9e29b0cf423f26cc", size = 59791, upload-time = "2025-08-20T11:55:38.877Z" }, + { url = "https://files.pythonhosted.org/packages/17/7b/2dcbc2bbfdbf68f2368fb21ab0f6735e872290bb604c75f6e06b81edcb3f/ujson-5.11.0-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8254e858437c00f17cb72e7a644fc42dad0ebb21ea981b71df6e84b1072aaa7c", size = 57356, upload-time = "2025-08-20T11:55:40.036Z" }, + { url = "https://files.pythonhosted.org/packages/d1/71/fea2ca18986a366c750767b694430d5ded6b20b6985fddca72f74af38a4c/ujson-5.11.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1aa8a2ab482f09f6c10fba37112af5f957689a79ea598399c85009f2f29898b5", size = 1036313, upload-time = "2025-08-20T11:55:41.408Z" }, + { url = "https://files.pythonhosted.org/packages/a3/bb/d4220bd7532eac6288d8115db51710fa2d7d271250797b0bfba9f1e755af/ujson-5.11.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a638425d3c6eed0318df663df44480f4a40dc87cc7c6da44d221418312f6413b", size = 1195782, upload-time = "2025-08-20T11:55:43.357Z" }, + { url = "https://files.pythonhosted.org/packages/80/47/226e540aa38878ce1194454385701d82df538ccb5ff8db2cf1641dde849a/ujson-5.11.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7e3cff632c1d78023b15f7e3a81c3745cd3f94c044d1e8fa8efbd6b161997bbc", size = 1088817, upload-time = "2025-08-20T11:55:45.262Z" }, + { url = "https://files.pythonhosted.org/packages/7e/81/546042f0b23c9040d61d46ea5ca76f0cc5e0d399180ddfb2ae976ebff5b5/ujson-5.11.0-cp312-cp312-win32.whl", hash = "sha256:be6b0eaf92cae8cdee4d4c9e074bde43ef1c590ed5ba037ea26c9632fb479c88", size = 39757, upload-time = "2025-08-20T11:55:46.522Z" }, + { url = "https://files.pythonhosted.org/packages/44/1b/27c05dc8c9728f44875d74b5bfa948ce91f6c33349232619279f35c6e817/ujson-5.11.0-cp312-cp312-win_amd64.whl", hash = "sha256:b7b136cc6abc7619124fd897ef75f8e63105298b5ca9bdf43ebd0e1fa0ee105f", size = 43859, upload-time = "2025-08-20T11:55:47.987Z" }, + { url = "https://files.pythonhosted.org/packages/22/2d/37b6557c97c3409c202c838aa9c960ca3896843b4295c4b7bb2bbd260664/ujson-5.11.0-cp312-cp312-win_arm64.whl", hash = "sha256:6cd2df62f24c506a0ba322d5e4fe4466d47a9467b57e881ee15a31f7ecf68ff6", size = 38361, upload-time = "2025-08-20T11:55:49.122Z" }, + { url = "https://files.pythonhosted.org/packages/1c/ec/2de9dd371d52c377abc05d2b725645326c4562fc87296a8907c7bcdf2db7/ujson-5.11.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:109f59885041b14ee9569bf0bb3f98579c3fa0652317b355669939e5fc5ede53", size = 55435, upload-time = "2025-08-20T11:55:50.243Z" }, + { url = "https://files.pythonhosted.org/packages/5b/a4/f611f816eac3a581d8a4372f6967c3ed41eddbae4008d1d77f223f1a4e0a/ujson-5.11.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a31c6b8004438e8c20fc55ac1c0e07dad42941db24176fe9acf2815971f8e752", size = 53193, upload-time = "2025-08-20T11:55:51.373Z" }, + { url = "https://files.pythonhosted.org/packages/e9/c5/c161940967184de96f5cbbbcce45b562a4bf851d60f4c677704b1770136d/ujson-5.11.0-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:78c684fb21255b9b90320ba7e199780f653e03f6c2528663768965f4126a5b50", size = 57603, upload-time = "2025-08-20T11:55:52.583Z" }, + { url = "https://files.pythonhosted.org/packages/2b/d6/c7b2444238f5b2e2d0e3dab300b9ddc3606e4b1f0e4bed5a48157cebc792/ujson-5.11.0-cp313-cp313-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:4c9f5d6a27d035dd90a146f7761c2272cf7103de5127c9ab9c4cd39ea61e878a", size = 59794, upload-time = "2025-08-20T11:55:53.69Z" }, + { url = "https://files.pythonhosted.org/packages/fe/a3/292551f936d3d02d9af148f53e1bc04306b00a7cf1fcbb86fa0d1c887242/ujson-5.11.0-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:837da4d27fed5fdc1b630bd18f519744b23a0b5ada1bbde1a36ba463f2900c03", size = 57363, upload-time = "2025-08-20T11:55:54.843Z" }, + { url = "https://files.pythonhosted.org/packages/90/a6/82cfa70448831b1a9e73f882225980b5c689bf539ec6400b31656a60ea46/ujson-5.11.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:787aff4a84da301b7f3bac09bc696e2e5670df829c6f8ecf39916b4e7e24e701", size = 1036311, upload-time = "2025-08-20T11:55:56.197Z" }, + { url = "https://files.pythonhosted.org/packages/84/5c/96e2266be50f21e9b27acaee8ca8f23ea0b85cb998c33d4f53147687839b/ujson-5.11.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:6dd703c3e86dc6f7044c5ac0b3ae079ed96bf297974598116aa5fb7f655c3a60", size = 1195783, upload-time = "2025-08-20T11:55:58.081Z" }, + { url = "https://files.pythonhosted.org/packages/8d/20/78abe3d808cf3bb3e76f71fca46cd208317bf461c905d79f0d26b9df20f1/ujson-5.11.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:3772e4fe6b0c1e025ba3c50841a0ca4786825a4894c8411bf8d3afe3a8061328", size = 1088822, upload-time = "2025-08-20T11:55:59.469Z" }, + { url = "https://files.pythonhosted.org/packages/d8/50/8856e24bec5e2fc7f775d867aeb7a3f137359356200ac44658f1f2c834b2/ujson-5.11.0-cp313-cp313-win32.whl", hash = "sha256:8fa2af7c1459204b7a42e98263b069bd535ea0cd978b4d6982f35af5a04a4241", size = 39753, upload-time = "2025-08-20T11:56:01.345Z" }, + { url = "https://files.pythonhosted.org/packages/5b/d8/1baee0f4179a4d0f5ce086832147b6cc9b7731c24ca08e14a3fdb8d39c32/ujson-5.11.0-cp313-cp313-win_amd64.whl", hash = "sha256:34032aeca4510a7c7102bd5933f59a37f63891f30a0706fb46487ab6f0edf8f0", size = 43866, upload-time = "2025-08-20T11:56:02.552Z" }, + { url = "https://files.pythonhosted.org/packages/a9/8c/6d85ef5be82c6d66adced3ec5ef23353ed710a11f70b0b6a836878396334/ujson-5.11.0-cp313-cp313-win_arm64.whl", hash = "sha256:ce076f2df2e1aa62b685086fbad67f2b1d3048369664b4cdccc50707325401f9", size = 38363, upload-time = "2025-08-20T11:56:03.688Z" }, + { url = "https://files.pythonhosted.org/packages/28/08/4518146f4984d112764b1dfa6fb7bad691c44a401adadaa5e23ccd930053/ujson-5.11.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:65724738c73645db88f70ba1f2e6fb678f913281804d5da2fd02c8c5839af302", size = 55462, upload-time = "2025-08-20T11:56:04.873Z" }, + { url = "https://files.pythonhosted.org/packages/29/37/2107b9a62168867a692654d8766b81bd2fd1e1ba13e2ec90555861e02b0c/ujson-5.11.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:29113c003ca33ab71b1b480bde952fbab2a0b6b03a4ee4c3d71687cdcbd1a29d", size = 53246, upload-time = "2025-08-20T11:56:06.054Z" }, + { url = "https://files.pythonhosted.org/packages/9b/f8/25583c70f83788edbe3ca62ce6c1b79eff465d78dec5eb2b2b56b3e98b33/ujson-5.11.0-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c44c703842024d796b4c78542a6fcd5c3cb948b9fc2a73ee65b9c86a22ee3638", size = 57631, upload-time = "2025-08-20T11:56:07.374Z" }, + { url = "https://files.pythonhosted.org/packages/ed/ca/19b3a632933a09d696f10dc1b0dfa1d692e65ad507d12340116ce4f67967/ujson-5.11.0-cp314-cp314-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:e750c436fb90edf85585f5c62a35b35082502383840962c6983403d1bd96a02c", size = 59877, upload-time = "2025-08-20T11:56:08.534Z" }, + { url = "https://files.pythonhosted.org/packages/55/7a/4572af5324ad4b2bfdd2321e898a527050290147b4ea337a79a0e4e87ec7/ujson-5.11.0-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f278b31a7c52eb0947b2db55a5133fbc46b6f0ef49972cd1a80843b72e135aba", size = 57363, upload-time = "2025-08-20T11:56:09.758Z" }, + { url = "https://files.pythonhosted.org/packages/7b/71/a2b8c19cf4e1efe53cf439cdf7198ac60ae15471d2f1040b490c1f0f831f/ujson-5.11.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ab2cb8351d976e788669c8281465d44d4e94413718af497b4e7342d7b2f78018", size = 1036394, upload-time = "2025-08-20T11:56:11.168Z" }, + { url = "https://files.pythonhosted.org/packages/7a/3e/7b98668cba3bb3735929c31b999b374ebc02c19dfa98dfebaeeb5c8597ca/ujson-5.11.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:090b4d11b380ae25453100b722d0609d5051ffe98f80ec52853ccf8249dfd840", size = 1195837, upload-time = "2025-08-20T11:56:12.6Z" }, + { url = "https://files.pythonhosted.org/packages/a1/ea/8870f208c20b43571a5c409ebb2fe9b9dba5f494e9e60f9314ac01ea8f78/ujson-5.11.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:80017e870d882d5517d28995b62e4e518a894f932f1e242cbc802a2fd64d365c", size = 1088837, upload-time = "2025-08-20T11:56:14.15Z" }, + { url = "https://files.pythonhosted.org/packages/63/b6/c0e6607e37fa47929920a685a968c6b990a802dec65e9c5181e97845985d/ujson-5.11.0-cp314-cp314-win32.whl", hash = "sha256:1d663b96eb34c93392e9caae19c099ec4133ba21654b081956613327f0e973ac", size = 41022, upload-time = "2025-08-20T11:56:15.509Z" }, + { url = "https://files.pythonhosted.org/packages/4e/56/f4fe86b4c9000affd63e9219e59b222dc48b01c534533093e798bf617a7e/ujson-5.11.0-cp314-cp314-win_amd64.whl", hash = "sha256:849e65b696f0d242833f1df4182096cedc50d414215d1371fca85c541fbff629", size = 45111, upload-time = "2025-08-20T11:56:16.597Z" }, + { url = "https://files.pythonhosted.org/packages/0a/f3/669437f0280308db4783b12a6d88c00730b394327d8334cc7a32ef218e64/ujson-5.11.0-cp314-cp314-win_arm64.whl", hash = "sha256:e73df8648c9470af2b6a6bf5250d4744ad2cf3d774dcf8c6e31f018bdd04d764", size = 39682, upload-time = "2025-08-20T11:56:17.763Z" }, + { url = "https://files.pythonhosted.org/packages/6e/cd/e9809b064a89fe5c4184649adeb13c1b98652db3f8518980b04227358574/ujson-5.11.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:de6e88f62796372fba1de973c11138f197d3e0e1d80bcb2b8aae1e826096d433", size = 55759, upload-time = "2025-08-20T11:56:18.882Z" }, + { url = "https://files.pythonhosted.org/packages/1b/be/ae26a6321179ebbb3a2e2685b9007c71bcda41ad7a77bbbe164005e956fc/ujson-5.11.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:49e56ef8066f11b80d620985ae36869a3ff7e4b74c3b6129182ec5d1df0255f3", size = 53634, upload-time = "2025-08-20T11:56:20.012Z" }, + { url = "https://files.pythonhosted.org/packages/ae/e9/fb4a220ee6939db099f4cfeeae796ecb91e7584ad4d445d4ca7f994a9135/ujson-5.11.0-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1a325fd2c3a056cf6c8e023f74a0c478dd282a93141356ae7f16d5309f5ff823", size = 58547, upload-time = "2025-08-20T11:56:21.175Z" }, + { url = "https://files.pythonhosted.org/packages/bd/f8/fc4b952b8f5fea09ea3397a0bd0ad019e474b204cabcb947cead5d4d1ffc/ujson-5.11.0-cp314-cp314t-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:a0af6574fc1d9d53f4ff371f58c96673e6d988ed2b5bf666a6143c782fa007e9", size = 60489, upload-time = "2025-08-20T11:56:22.342Z" }, + { url = "https://files.pythonhosted.org/packages/2e/e5/af5491dfda4f8b77e24cf3da68ee0d1552f99a13e5c622f4cef1380925c3/ujson-5.11.0-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:10f29e71ecf4ecd93a6610bd8efa8e7b6467454a363c3d6416db65de883eb076", size = 58035, upload-time = "2025-08-20T11:56:23.92Z" }, + { url = "https://files.pythonhosted.org/packages/c4/09/0945349dd41f25cc8c38d78ace49f14c5052c5bbb7257d2f466fa7bdb533/ujson-5.11.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:1a0a9b76a89827a592656fe12e000cf4f12da9692f51a841a4a07aa4c7ecc41c", size = 1037212, upload-time = "2025-08-20T11:56:25.274Z" }, + { url = "https://files.pythonhosted.org/packages/49/44/8e04496acb3d5a1cbee3a54828d9652f67a37523efa3d3b18a347339680a/ujson-5.11.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:b16930f6a0753cdc7d637b33b4e8f10d5e351e1fb83872ba6375f1e87be39746", size = 1196500, upload-time = "2025-08-20T11:56:27.517Z" }, + { url = "https://files.pythonhosted.org/packages/64/ae/4bc825860d679a0f208a19af2f39206dfd804ace2403330fdc3170334a2f/ujson-5.11.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:04c41afc195fd477a59db3a84d5b83a871bd648ef371cf8c6f43072d89144eef", size = 1089487, upload-time = "2025-08-20T11:56:29.07Z" }, + { url = "https://files.pythonhosted.org/packages/30/ed/5a057199fb0a5deabe0957073a1c1c1c02a3e99476cd03daee98ea21fa57/ujson-5.11.0-cp314-cp314t-win32.whl", hash = "sha256:aa6d7a5e09217ff93234e050e3e380da62b084e26b9f2e277d2606406a2fc2e5", size = 41859, upload-time = "2025-08-20T11:56:30.495Z" }, + { url = "https://files.pythonhosted.org/packages/aa/03/b19c6176bdf1dc13ed84b886e99677a52764861b6cc023d5e7b6ebda249d/ujson-5.11.0-cp314-cp314t-win_amd64.whl", hash = "sha256:48055e1061c1bb1f79e75b4ac39e821f3f35a9b82de17fce92c3140149009bec", size = 46183, upload-time = "2025-08-20T11:56:31.574Z" }, + { url = "https://files.pythonhosted.org/packages/5d/ca/a0413a3874b2dc1708b8796ca895bf363292f9c70b2e8ca482b7dbc0259d/ujson-5.11.0-cp314-cp314t-win_arm64.whl", hash = "sha256:1194b943e951092db611011cb8dbdb6cf94a3b816ed07906e14d3bc6ce0e90ab", size = 40264, upload-time = "2025-08-20T11:56:32.773Z" }, + { url = "https://files.pythonhosted.org/packages/39/bf/c6f59cdf74ce70bd937b97c31c42fd04a5ed1a9222d0197e77e4bd899841/ujson-5.11.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:65f3c279f4ed4bf9131b11972040200c66ae040368abdbb21596bf1564899694", size = 55283, upload-time = "2025-08-20T11:56:33.947Z" }, + { url = "https://files.pythonhosted.org/packages/8d/c1/a52d55638c0c644b8a63059f95ad5ffcb4ad8f60d8bc3e8680f78e77cc75/ujson-5.11.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:99c49400572cd77050894e16864a335225191fd72a818ea6423ae1a06467beac", size = 53168, upload-time = "2025-08-20T11:56:35.141Z" }, + { url = "https://files.pythonhosted.org/packages/75/6c/e64e19a01d59c8187d01ffc752ee3792a09f5edaaac2a0402de004459dd7/ujson-5.11.0-cp39-cp39-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0654a2691fc252c3c525e3d034bb27b8a7546c9d3eb33cd29ce6c9feda361a6a", size = 57809, upload-time = "2025-08-20T11:56:36.293Z" }, + { url = "https://files.pythonhosted.org/packages/9f/36/910117b7a8a1c188396f6194ca7bc8fd75e376d8f7e3cf5eb6219fc8b09d/ujson-5.11.0-cp39-cp39-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:6b6ec7e7321d7fc19abdda3ad809baef935f49673951a8bab486aea975007e02", size = 59797, upload-time = "2025-08-20T11:56:37.746Z" }, + { url = "https://files.pythonhosted.org/packages/c7/17/bcc85d282ee2f4cdef5f577e0a43533eedcae29cc6405edf8c62a7a50368/ujson-5.11.0-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f62b9976fabbcde3ab6e413f4ec2ff017749819a0786d84d7510171109f2d53c", size = 57378, upload-time = "2025-08-20T11:56:39.123Z" }, + { url = "https://files.pythonhosted.org/packages/ef/39/120bb76441bf835f3c3f42db9c206f31ba875711637a52a8209949ab04b0/ujson-5.11.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:7f1a27ab91083b4770e160d17f61b407f587548f2c2b5fbf19f94794c495594a", size = 1036515, upload-time = "2025-08-20T11:56:40.848Z" }, + { url = "https://files.pythonhosted.org/packages/b6/ae/fe1b4ff6388f681f6710e9494656957725b1e73ae50421ec04567df9fb75/ujson-5.11.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:ecd6ff8a3b5a90c292c2396c2d63c687fd0ecdf17de390d852524393cd9ed052", size = 1195753, upload-time = "2025-08-20T11:56:42.341Z" }, + { url = "https://files.pythonhosted.org/packages/92/20/005b93f2cf846ae50b46812fcf24bbdd127521197e5f1e1a82e3b3e730a1/ujson-5.11.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:9aacbeb23fdbc4b256a7d12e0beb9063a1ba5d9e0dbb2cfe16357c98b4334596", size = 1088844, upload-time = "2025-08-20T11:56:43.777Z" }, + { url = "https://files.pythonhosted.org/packages/41/9e/3142023c30008e2b24d7368a389b26d28d62fcd3f596d3d898a72dd09173/ujson-5.11.0-cp39-cp39-win32.whl", hash = "sha256:674f306e3e6089f92b126eb2fe41bcb65e42a15432c143365c729fdb50518547", size = 39652, upload-time = "2025-08-20T11:56:45.034Z" }, + { url = "https://files.pythonhosted.org/packages/ca/89/f4de0a3c485d0163f85f552886251876645fb62cbbe24fcdc0874b9fae03/ujson-5.11.0-cp39-cp39-win_amd64.whl", hash = "sha256:c6618f480f7c9ded05e78a1938873fde68baf96cdd74e6d23c7e0a8441175c4b", size = 43783, upload-time = "2025-08-20T11:56:46.156Z" }, + { url = "https://files.pythonhosted.org/packages/48/b1/2d50987a7b7cccb5c1fbe9ae7b184211106237b32c7039118c41d79632ea/ujson-5.11.0-cp39-cp39-win_arm64.whl", hash = "sha256:5600202a731af24a25e2d7b6eb3f648e4ecd4bb67c4d5cf12f8fab31677469c9", size = 38430, upload-time = "2025-08-20T11:56:47.653Z" }, + { url = "https://files.pythonhosted.org/packages/50/17/30275aa2933430d8c0c4ead951cc4fdb922f575a349aa0b48a6f35449e97/ujson-5.11.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:abae0fb58cc820092a0e9e8ba0051ac4583958495bfa5262a12f628249e3b362", size = 51206, upload-time = "2025-08-20T11:56:48.797Z" }, + { url = "https://files.pythonhosted.org/packages/c3/15/42b3924258eac2551f8f33fa4e35da20a06a53857ccf3d4deb5e5d7c0b6c/ujson-5.11.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:fac6c0649d6b7c3682a0a6e18d3de6857977378dce8d419f57a0b20e3d775b39", size = 48907, upload-time = "2025-08-20T11:56:50.136Z" }, + { url = "https://files.pythonhosted.org/packages/94/7e/0519ff7955aba581d1fe1fb1ca0e452471250455d182f686db5ac9e46119/ujson-5.11.0-pp311-pypy311_pp73-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4b42c115c7c6012506e8168315150d1e3f76e7ba0f4f95616f4ee599a1372bbc", size = 50319, upload-time = "2025-08-20T11:56:51.63Z" }, + { url = "https://files.pythonhosted.org/packages/74/cf/209d90506b7d6c5873f82c5a226d7aad1a1da153364e9ebf61eff0740c33/ujson-5.11.0-pp311-pypy311_pp73-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:86baf341d90b566d61a394869ce77188cc8668f76d7bb2c311d77a00f4bdf844", size = 56584, upload-time = "2025-08-20T11:56:52.89Z" }, + { url = "https://files.pythonhosted.org/packages/e9/97/bd939bb76943cb0e1d2b692d7e68629f51c711ef60425fa5bb6968037ecd/ujson-5.11.0-pp311-pypy311_pp73-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4598bf3965fc1a936bd84034312bcbe00ba87880ef1ee33e33c1e88f2c398b49", size = 51588, upload-time = "2025-08-20T11:56:54.054Z" }, + { url = "https://files.pythonhosted.org/packages/52/5b/8c5e33228f7f83f05719964db59f3f9f276d272dc43752fa3bbf0df53e7b/ujson-5.11.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:416389ec19ef5f2013592f791486bef712ebce0cd59299bf9df1ba40bb2f6e04", size = 43835, upload-time = "2025-08-20T11:56:55.237Z" }, ] [[package]] @@ -2048,18 +2862,28 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b8/b5/d2842541718ffa12060854735587543120a31ebc339435e0bd0faf368541/unasync-0.6.0-py3-none-any.whl", hash = "sha256:9cf7aaaea9737e417d8949bf9be55dc25fdb4ef1f4edc21b58f76ff0d2b9d73f", size = 9959, upload-time = "2024-05-03T11:14:56.17Z" }, ] +[[package]] +name = "urllib3" +version = "2.5.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/15/22/9ee70a2574a4f4599c47dd506532914ce044817c7752a79b6a51286319bc/urllib3-2.5.0.tar.gz", hash = "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760", size = 393185, upload-time = "2025-06-18T14:07:41.644Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a7/c2/fe1e52489ae3122415c51f387e221dd0773709bad6c6cdaa599e8a2c5185/urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc", size = 129795, upload-time = "2025-06-18T14:07:40.39Z" }, +] + [[package]] name = "virtualenv" -version = "20.32.0" +version = "20.34.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "distlib" }, { name = "filelock" }, { name = "platformdirs" }, + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/a9/96/0834f30fa08dca3738614e6a9d42752b6420ee94e58971d702118f7cfd30/virtualenv-20.32.0.tar.gz", hash = "sha256:886bf75cadfdc964674e6e33eb74d787dff31ca314ceace03ca5810620f4ecf0", size = 6076970, upload-time = "2025-07-21T04:09:50.985Z" } +sdist = { url = "https://files.pythonhosted.org/packages/1c/14/37fcdba2808a6c615681cd216fecae00413c9dab44fb2e57805ecf3eaee3/virtualenv-20.34.0.tar.gz", hash = "sha256:44815b2c9dee7ed86e387b842a84f20b93f7f417f95886ca1996a72a4138eb1a", size = 6003808, upload-time = "2025-08-13T14:24:07.464Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/5c/c6/f8f28009920a736d0df434b52e9feebfb4d702ba942f15338cb4a83eafc1/virtualenv-20.32.0-py3-none-any.whl", hash = "sha256:2c310aecb62e5aa1b06103ed7c2977b81e042695de2697d01017ff0f1034af56", size = 6057761, upload-time = "2025-07-21T04:09:48.059Z" }, + { url = "https://files.pythonhosted.org/packages/76/06/04c8e804f813cf972e3262f3f8584c232de64f0cde9f703b46cf53a45090/virtualenv-20.34.0-py3-none-any.whl", hash = "sha256:341f5afa7eee943e4984a9207c025feedd768baff6753cd660c857ceb3e36026", size = 5983279, upload-time = "2025-08-13T14:24:05.111Z" }, ] [[package]] @@ -2071,6 +2895,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/fd/84/fd2ba7aafacbad3c4201d395674fc6348826569da3c0937e75505ead3528/wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859", size = 34166, upload-time = "2024-01-06T02:10:55.763Z" }, ] +[[package]] +name = "webencodings" +version = "0.5.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0b/02/ae6ceac1baeda530866a85075641cec12989bd8d31af6d5ab4a3e8c92f47/webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923", size = 9721, upload-time = "2017-04-05T20:21:34.189Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/24/2a3e3df732393fed8b3ebf2ec078f05546de641fe1b667ee316ec1dcf3b7/webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78", size = 11774, upload-time = "2017-04-05T20:21:32.581Z" }, +] + [[package]] name = "websockets" version = "15.0.1"