From c57c14e24be83de56f424c2225d028e457699e0d Mon Sep 17 00:00:00 2001 From: rhysrevans3 Date: Thu, 14 May 2026 10:29:49 +0100 Subject: [PATCH 01/35] Update poetry. --- poetry.lock | 101 +++++++++++++++++++++++++------------------------ pyproject.toml | 1 + 2 files changed, 53 insertions(+), 49 deletions(-) diff --git a/poetry.lock b/poetry.lock index 08791af..b498cb5 100644 --- a/poetry.lock +++ b/poetry.lock @@ -445,60 +445,63 @@ files = [ [[package]] name = "confluent-kafka" -version = "2.6.0" +version = "2.14.0" description = "Confluent's Python client for Apache Kafka" optional = false -python-versions = "*" +python-versions = ">=3.8" groups = ["main"] files = [ - {file = "confluent-kafka-2.6.0.tar.gz", hash = "sha256:f7afe69639bd2ab15404dd46a76e06213342a23cb5642d873342847cb2198c87"}, - {file = "confluent_kafka-2.6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:123d8cff9e1f45be333b266a49beb649bc1f8f9a67a37a8b35cf7f441cb03452"}, - {file = "confluent_kafka-2.6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ac6e397ee25019aeab320e5d4d3650078eb644908dc23eb2353726fe0c980dc8"}, - {file = "confluent_kafka-2.6.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:fd70c7ac03606c6bccbc92d1876586c5c81b80416d11e24af1e6d965edf43b92"}, - {file = "confluent_kafka-2.6.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:b9c8ea8e8817512a0431f2d95060cf1f88c20262a4f395816ee2c96fba1576bf"}, - {file = "confluent_kafka-2.6.0-cp310-cp310-win_amd64.whl", hash = "sha256:ce5d55a3ed1ec8ff449592b1295208d5b3846f1962d1c3a8cfd0022ea3e01cf5"}, - {file = "confluent_kafka-2.6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b6343f83052c6a6234a9c12cfa764a8b7440dbe0d293027606e314827fa7ad6a"}, - {file = "confluent_kafka-2.6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1a26e91200bbd0f09effe4d2f3b524c959c4a8925b62cb022676aeb223195f96"}, - {file = "confluent_kafka-2.6.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:6830b17a7c2253b95b873b3cf0fe877ce882e348cfcf9d4d939ade5626f87b1d"}, - {file = "confluent_kafka-2.6.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:7a9a58472e23112043e9a36e048241bccc3fd211f066fba778c070f0eafa35c8"}, - {file = "confluent_kafka-2.6.0-cp311-cp311-win_amd64.whl", hash = "sha256:c134c1afdc6c83c82228a3bec9550a62748ec4cd9b6913efed4f4e903db321cc"}, - {file = "confluent_kafka-2.6.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:7d14f70ca8c8435116119cf343028aa98987badb7ef06f1a37b480074b15ba64"}, - {file = "confluent_kafka-2.6.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6c7d7161d6e68ffc7497e4768c30654151319edb6637739ac64e857a404fe531"}, - {file = "confluent_kafka-2.6.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:7189a64a0a829f391e65167de39234904ab374a6d453f6017f9287adb45cd469"}, - {file = "confluent_kafka-2.6.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:2a685e1c14b5cb20a8567cb42b762021488fce95c770cf6b1d3a4f175d9aaaac"}, - {file = "confluent_kafka-2.6.0-cp312-cp312-win_amd64.whl", hash = "sha256:e9e4b279852b1c3f6457ee00245327cfe6023b3271b01e5ae73d3995cb7dfee4"}, - {file = "confluent_kafka-2.6.0-cp313-cp313-macosx_13_0_arm64.whl", hash = "sha256:d17a8014a153c719d1b8a742c285a98aa96f482a78f09ebc0aedc593ae8bea29"}, - {file = "confluent_kafka-2.6.0-cp313-cp313-macosx_13_0_x86_64.whl", hash = "sha256:ab6607603806dc05f3671a249c7bed3821321b58af151f9bc1b3cfd73bb526d8"}, - {file = "confluent_kafka-2.6.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:e46fbc61d36752b4a6d6c48e042dd2e10c7c2c4f00e51033fd8e3d435a2ee44c"}, - {file = "confluent_kafka-2.6.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:e36d8b924ed884e0eabbdb22519c059b528953358c739e0f6c0510e447260402"}, - {file = "confluent_kafka-2.6.0-cp313-cp313-win_amd64.whl", hash = "sha256:47b9f8497938c75036f3dd124da50cb56599ae7c238803bfe2a52ed5b6cda197"}, - {file = "confluent_kafka-2.6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b6a67672eb7fb7669539e3c57ce3d51beefaf74f21498be92b8624ee86ab9d64"}, - {file = "confluent_kafka-2.6.0-cp36-cp36m-manylinux_2_28_aarch64.whl", hash = "sha256:adbc37516440246edd3ff99069c49338cd27d6957d596075a19d6ff0bcb2fd40"}, - {file = "confluent_kafka-2.6.0-cp36-cp36m-manylinux_2_28_x86_64.whl", hash = "sha256:4ee544a258891dddc709ae8f97242861f3eedd9e945688b5bfe99238004f68ee"}, - {file = "confluent_kafka-2.6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:e8c1fec7f05f52f2cd57969bacba7afc81c71cd4b2a6629ebba0df08d5c4068f"}, - {file = "confluent_kafka-2.6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:4a7f244d0476e8c54bb1fe008195e2b9c491317976008945b0e4d3deef369310"}, - {file = "confluent_kafka-2.6.0-cp37-cp37m-manylinux_2_28_aarch64.whl", hash = "sha256:86f7ef75cc977a0750db46b397a75db88a70879c2e8f4c1e0ed2b47e485a8110"}, - {file = "confluent_kafka-2.6.0-cp37-cp37m-manylinux_2_28_x86_64.whl", hash = "sha256:045f67a6718e2e7312c6407f4510cd6c8293533936b9e6c4ebc78e46c4b4c5dd"}, - {file = "confluent_kafka-2.6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:4397365bf0d988a0bc21b82d717eba4fb879682d3d1737b88717c9cd6248a9c1"}, - {file = "confluent_kafka-2.6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c486a4ebb998545a32e8abb70995db519c46913b3fbcaf022ca49a53ba807907"}, - {file = "confluent_kafka-2.6.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:1cdb0e2c755bfe8e85d7e1dbd949557646279a97c2a1925fdeff4054a509e07b"}, - {file = "confluent_kafka-2.6.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:c0dbbbefa0f2d0390bf86567d7d3711c4bf186def8f61b6ed9cff493af10e056"}, - {file = "confluent_kafka-2.6.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:bf44a28a1e5e53da1acb0d356ef6c96a23062c20ab6d0c4e470f50b29004e26b"}, - {file = "confluent_kafka-2.6.0-cp38-cp38-win_amd64.whl", hash = "sha256:5ac22691e84eac632011d138d33c2d3446a6cb3db893bf42143737e461603554"}, - {file = "confluent_kafka-2.6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:87f022be528cb601d5a6b828328e7df795999fac3975ead82e8a3d2210d8b0f7"}, - {file = "confluent_kafka-2.6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e3b6756436a1302d19a1cb75623e23182fa197c853c87d43f15c99b43f8fbb17"}, - {file = "confluent_kafka-2.6.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:e05514ab6b50ed209d091029af868950ae5a2e46f9b27231d6d352352b7f3323"}, - {file = "confluent_kafka-2.6.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:bf59fb1054544de9ebcdf564c2acfad7d05cd758b91d82d6057a87529be898c8"}, - {file = "confluent_kafka-2.6.0-cp39-cp39-win_amd64.whl", hash = "sha256:99a39a6a697ed1ab1d738835dfd18fb2f1ffd76fc2d00e037d4fa26a07cf798e"}, + {file = "confluent_kafka-2.14.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a9a5205a90f60895737a671ee1a027813d539aaaa82984b793e7807ca35b24bf"}, + {file = "confluent_kafka-2.14.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f6405feef51d2881aeb6d360176bc1d20ffb1793f10684149bd89bf95483b535"}, + {file = "confluent_kafka-2.14.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:259709101786221211fbe3e5654fef04b0c321066339a4c9e3cdb7dd27a0ad9d"}, + {file = "confluent_kafka-2.14.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:f1fa8ed04e1e590c1d5f265aba0f0c03b82b5ee39c44d469f8a45b4f84aadbb9"}, + {file = "confluent_kafka-2.14.0-cp310-cp310-win_amd64.whl", hash = "sha256:5bf19b0ed1ed7af037b406163264220d560336e62a42adaaaa36a9ca9fc7cec8"}, + {file = "confluent_kafka-2.14.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:21c5ce6f388a5bd5d8f102026250faa528694cf7cf71fb6a1b321dad27874c1c"}, + {file = "confluent_kafka-2.14.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2eaeabe10c44f8b4c0b879602e804548f2c49eae9e5d40a6d88e372c4c876810"}, + {file = "confluent_kafka-2.14.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:163f30cfe49f56d85d208ddf6db50a64cb4156d85ff0d5925cbf53c9c1ff5229"}, + {file = "confluent_kafka-2.14.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:c86583d81b71c097e7fb9b2b7e45aa7e3f43cf23308319e0d6bd6eede3027732"}, + {file = "confluent_kafka-2.14.0-cp311-cp311-win_amd64.whl", hash = "sha256:74a9af680de1aab2a701c3a4645275374f556cabbf559fa569450fe4f8c61e25"}, + {file = "confluent_kafka-2.14.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:737b63f2389c9d63f3da0923681aa95abad1cb2f96b10f38192ef19ab727c883"}, + {file = "confluent_kafka-2.14.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1610aa31880c874bfa3351d898d6e6cdbfab2a0f9443598fd64425bbc815cb06"}, + {file = "confluent_kafka-2.14.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:9cca8929bbc3d68a3299b21239c48def860f04e4661c7a59efe3104ecaea0e08"}, + {file = "confluent_kafka-2.14.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:4d2e4718371c06579f649835239d1acf6ab5386a88f70e9cb9b839855c83c4a9"}, + {file = "confluent_kafka-2.14.0-cp312-cp312-win_amd64.whl", hash = "sha256:c37aff51512e817316edd6eafa8a2e59745052a7d1e61e09931b1caa11803266"}, + {file = "confluent_kafka-2.14.0-cp313-cp313-macosx_13_0_arm64.whl", hash = "sha256:a6dc0e49e8ac99854bd89ec7ac16c54af4488c7617baa633e615320dfbe44b25"}, + {file = "confluent_kafka-2.14.0-cp313-cp313-macosx_13_0_x86_64.whl", hash = "sha256:308c972b23f44e4d0eb3e76b987872c9a7d04148a5a4f29313bbbec3841d75b4"}, + {file = "confluent_kafka-2.14.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:9b0acf2fffa19a6ffc2d6f0b82f3b7f1771f5d3943312438f3532ae69b6f2e83"}, + {file = "confluent_kafka-2.14.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:0023a941dbd8a2325e9e0d13ed1b2236c7d4ff3279b3d99cf06cf1409ab26d22"}, + {file = "confluent_kafka-2.14.0-cp313-cp313-win_amd64.whl", hash = "sha256:3da898df3ebb866f61312365e9108cbadcfe74fb73af8d03add856542e715cfe"}, + {file = "confluent_kafka-2.14.0-cp314-cp314-macosx_13_0_arm64.whl", hash = "sha256:05bbf9745cadb1a6fd3b03508572d2cd5455d8d9960a437537ddac9d3f89ee49"}, + {file = "confluent_kafka-2.14.0-cp314-cp314-macosx_13_0_x86_64.whl", hash = "sha256:32a72ff85d7b4428532aa477b8dfa4223a5c69f4e90fecaa64e1924cc99a06b6"}, + {file = "confluent_kafka-2.14.0-cp314-cp314-manylinux_2_28_aarch64.whl", hash = "sha256:4fd75d53e0e36f7ff9c5454f7a3cf4a54790db3bfda169c3b582ddc97111f6f6"}, + {file = "confluent_kafka-2.14.0-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:eb17528ec7b177ec5e38214852f3dadb5d77172e0fb25c7c992c0cbc3dcfbaa2"}, + {file = "confluent_kafka-2.14.0-cp314-cp314-win_amd64.whl", hash = "sha256:578afb532ded604cb98174a14a88847367191bcbe4f52a1661f5238dc5cf75dd"}, + {file = "confluent_kafka-2.14.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e5d19d48f34aa95fc3b9230481c0271cbc5dec1ed4ca02e94789bdd254517854"}, + {file = "confluent_kafka-2.14.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:073c89cb29c81c6d2b96c1503f88d96af8af44dc9cfaf51bb21447830c6a511b"}, + {file = "confluent_kafka-2.14.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:bda97981149fbfafe066e5a46cb988785dc9c4d6ac52ff981c044364921dc243"}, + {file = "confluent_kafka-2.14.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:f31ddd2a25728e6388e0ead3c231c4cf460577edfb3cc3de6693a11ed1014d42"}, + {file = "confluent_kafka-2.14.0-cp38-cp38-win_amd64.whl", hash = "sha256:8b291848a3398f91a4336cfe2a8a61b3583390fe10f6af8f5b110df4eea99940"}, + {file = "confluent_kafka-2.14.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:cefd69330800d7d60d790879176b33d19f9c6bfc3ca77a6be94045fc79102390"}, + {file = "confluent_kafka-2.14.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:33d7984ad73de6d6671f859d598e91551595d0a681ade4f78461152bf11e7a7a"}, + {file = "confluent_kafka-2.14.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:376abebb8ddc7bee54ab529d28cc6fbe55dac8dc07cc7cf5d49814245032f021"}, + {file = "confluent_kafka-2.14.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:01bbbdccccb3406ab724e02c4f6ce5aea1671f9a85d009e3a0b6e524d464a4c2"}, + {file = "confluent_kafka-2.14.0-cp39-cp39-win_amd64.whl", hash = "sha256:63e636813d4350b9c26f94af09c48225245ed508fd6f53c755f4b0cb76ff5fdb"}, + {file = "confluent_kafka-2.14.0.tar.gz", hash = "sha256:34efddfd06766d1153d10a70c23a98f6035e253a906db8ed04cb0249fc3b0fd2"}, ] [package.extras] -avro = ["avro (>=1.11.1,<2)", "fastavro (>=0.23.0,<1.0) ; python_version < \"3.0\"", "fastavro (>=1.0) ; python_version > \"3.0\"", "requests"] -dev = ["avro (>=1.11.1,<2)", "fastavro (>=0.23.0,<1.0) ; python_version < \"3.0\"", "fastavro (>=1.0) ; python_version > \"3.0\"", "flake8", "pytest (==4.6.4) ; python_version < \"3.0\"", "pytest ; python_version >= \"3.0\"", "pytest-timeout", "requests"] -doc = ["avro (>=1.11.1,<2)", "fastavro (>=0.23.0,<1.0) ; python_version < \"3.0\"", "fastavro (>=1.0) ; python_version > \"3.0\"", "requests", "sphinx", "sphinx-rtd-theme"] -json = ["jsonschema", "pyrsistent (==0.16.1) ; python_version < \"3.0\"", "pyrsistent ; python_version > \"3.0\"", "requests"] -protobuf = ["protobuf", "requests"] -schema-registry = ["requests"] +all = ["async-timeout", "attrs", "attrs", "attrs (>=21.2.0)", "authlib (>=1.0.0)", "authlib (>=1.0.0)", "avro (>=1.11.1,<2)", "avro (>=1.11.1,<2)", "azure-identity", "azure-identity", "azure-keyvault-keys", "azure-keyvault-keys", "black (>=24.0.0)", "boto3", "boto3 (>=1.35)", "cachetools", "cachetools (>=5.5.0)", "cel-python (>=0.4.0)", "cel-python (>=0.4.0)", "certifi", "confluent-kafka", "fastapi", "fastavro (>=1.5.4,<1.8.0) ; python_version == \"3.7\"", "fastavro (>=1.5.4,<1.8.0) ; python_version == \"3.7\"", "fastavro (>=1.5.4,<2) ; python_version > \"3.7\"", "fastavro (>=1.5.4,<2) ; python_version > \"3.7\"", "flake8", "google-api-core", "google-api-core", "google-auth", "google-auth", "google-cloud-kms", "google-cloud-kms", "google-re2 (<1.1.20251105)", "googleapis-common-protos", "googleapis-common-protos", "hkdf (==0.0.3)", "hkdf (==0.0.3)", "httpx (>=0.26)", "httpx (>=0.26)", "hvac", "hvac", "isort (>=5.13.0)", "jsonata-python", "jsonata-python", "jsonschema (>=4.18.0)", "jsonschema (>=4.18.0)", "mypy", "opentelemetry-distro", "opentelemetry-exporter-otlp", "orjson", "orjson (>=3.10)", "orjson (>=3.10)", "pandoc", "pluggy (<1.6.0)", "protobuf", "protobuf", "psutil", "pydantic", "pyrsistent", "pyrsistent", "pytest", "pytest-asyncio", "pytest-timeout", "pytest_cov", "pyyaml (>=6.0.0)", "pyyaml (>=6.0.0)", "requests", "requests", "requests-mock", "respx", "six", "sphinx", "sphinx-rtd-theme", "tink", "tink", "tomli ; python_version < \"3.11\"", "types-cachetools", "types-requests", "urllib3 (<3)", "uvicorn"] +avro = ["attrs (>=21.2.0)", "authlib (>=1.0.0)", "avro (>=1.11.1,<2)", "cachetools (>=5.5.0)", "certifi", "fastavro (>=1.5.4,<1.8.0) ; python_version == \"3.7\"", "fastavro (>=1.5.4,<2) ; python_version > \"3.7\"", "httpx (>=0.26)", "requests"] +dev = ["async-timeout", "attrs", "attrs", "attrs (>=21.2.0)", "authlib (>=1.0.0)", "authlib (>=1.0.0)", "avro (>=1.11.1,<2)", "avro (>=1.11.1,<2)", "azure-identity", "azure-identity", "azure-keyvault-keys", "azure-keyvault-keys", "black (>=24.0.0)", "boto3", "boto3 (>=1.35)", "cachetools", "cachetools (>=5.5.0)", "cel-python (>=0.4.0)", "cel-python (>=0.4.0)", "certifi", "confluent-kafka", "fastapi", "fastavro (>=1.5.4,<1.8.0) ; python_version == \"3.7\"", "fastavro (>=1.5.4,<1.8.0) ; python_version == \"3.7\"", "fastavro (>=1.5.4,<2) ; python_version > \"3.7\"", "fastavro (>=1.5.4,<2) ; python_version > \"3.7\"", "flake8", "google-api-core", "google-api-core", "google-auth", "google-auth", "google-cloud-kms", "google-cloud-kms", "google-re2 (<1.1.20251105)", "googleapis-common-protos", "googleapis-common-protos", "hkdf (==0.0.3)", "hkdf (==0.0.3)", "httpx (>=0.26)", "httpx (>=0.26)", "hvac", "hvac", "isort (>=5.13.0)", "jsonata-python", "jsonata-python", "jsonschema (>=4.18.0)", "jsonschema (>=4.18.0)", "mypy", "orjson", "orjson (>=3.10)", "orjson (>=3.10)", "pandoc", "pluggy (<1.6.0)", "protobuf", "protobuf", "pydantic", "pyrsistent", "pyrsistent", "pytest", "pytest-asyncio", "pytest-timeout", "pytest_cov", "pyyaml (>=6.0.0)", "pyyaml (>=6.0.0)", "requests", "requests", "requests-mock", "respx", "six", "sphinx", "sphinx-rtd-theme", "tink", "tink", "tomli ; python_version < \"3.11\"", "types-cachetools", "types-requests", "urllib3 (<3)", "uvicorn"] +docs = ["attrs (>=21.2.0)", "authlib (>=1.0.0)", "avro (>=1.11.1,<2)", "azure-identity", "azure-keyvault-keys", "boto3 (>=1.35)", "cachetools (>=5.5.0)", "cel-python (>=0.4.0)", "certifi", "fastavro (>=1.5.4,<1.8.0) ; python_version == \"3.7\"", "fastavro (>=1.5.4,<2) ; python_version > \"3.7\"", "google-api-core", "google-auth", "google-cloud-kms", "google-re2 (<1.1.20251105)", "googleapis-common-protos", "hkdf (==0.0.3)", "httpx (>=0.26)", "hvac", "jsonata-python", "jsonschema (>=4.18.0)", "orjson (>=3.10)", "pandoc", "protobuf", "pyrsistent", "pyyaml (>=6.0.0)", "requests", "sphinx", "sphinx-rtd-theme", "tink", "tomli ; python_version < \"3.11\""] +examples = ["attrs", "authlib (>=1.0.0)", "avro (>=1.11.1,<2)", "azure-identity", "azure-keyvault-keys", "boto3", "cachetools", "cel-python (>=0.4.0)", "confluent-kafka", "fastapi", "fastavro (>=1.5.4,<1.8.0) ; python_version == \"3.7\"", "fastavro (>=1.5.4,<2) ; python_version > \"3.7\"", "google-api-core", "google-auth", "google-cloud-kms", "googleapis-common-protos", "hkdf (==0.0.3)", "httpx (>=0.26)", "hvac", "jsonata-python", "jsonschema (>=4.18.0)", "orjson (>=3.10)", "protobuf", "pydantic", "pyrsistent", "pyyaml (>=6.0.0)", "requests", "six", "tink", "uvicorn"] +json = ["attrs (>=21.2.0)", "authlib (>=1.0.0)", "cachetools (>=5.5.0)", "certifi", "httpx (>=0.26)", "jsonschema (>=4.18.0)", "orjson (>=3.10)", "pyrsistent"] +protobuf = ["attrs (>=21.2.0)", "authlib (>=1.0.0)", "cachetools (>=5.5.0)", "certifi", "googleapis-common-protos", "httpx (>=0.26)", "protobuf"] +rules = ["attrs (>=21.2.0)", "authlib (>=1.0.0)", "azure-identity", "azure-keyvault-keys", "boto3 (>=1.35)", "cachetools (>=5.5.0)", "cel-python (>=0.4.0)", "certifi", "google-api-core", "google-auth", "google-cloud-kms", "google-re2 (<1.1.20251105)", "hkdf (==0.0.3)", "httpx (>=0.26)", "hvac", "jsonata-python", "pyyaml (>=6.0.0)", "tink"] +schema-registry = ["attrs (>=21.2.0)", "authlib (>=1.0.0)", "cachetools (>=5.5.0)", "certifi", "httpx (>=0.26)"] +schemaregistry = ["attrs (>=21.2.0)", "authlib (>=1.0.0)", "cachetools (>=5.5.0)", "certifi", "httpx (>=0.26)"] +soaktest = ["opentelemetry-distro", "opentelemetry-exporter-otlp", "psutil"] +tests = ["async-timeout", "attrs", "attrs (>=21.2.0)", "authlib (>=1.0.0)", "avro (>=1.11.1,<2)", "azure-identity", "azure-keyvault-keys", "black (>=24.0.0)", "boto3 (>=1.35)", "cachetools (>=5.5.0)", "cel-python (>=0.4.0)", "certifi", "fastavro (>=1.5.4,<1.8.0) ; python_version == \"3.7\"", "fastavro (>=1.5.4,<2) ; python_version > \"3.7\"", "flake8", "google-api-core", "google-auth", "google-cloud-kms", "google-re2 (<1.1.20251105)", "googleapis-common-protos", "hkdf (==0.0.3)", "httpx (>=0.26)", "hvac", "isort (>=5.13.0)", "jsonata-python", "jsonschema (>=4.18.0)", "mypy", "orjson", "orjson (>=3.10)", "pluggy (<1.6.0)", "protobuf", "pyrsistent", "pytest", "pytest-asyncio", "pytest-timeout", "pytest_cov", "pyyaml (>=6.0.0)", "requests", "requests-mock", "respx", "tink", "types-cachetools", "types-requests", "urllib3 (<3)"] [[package]] name = "coverage" @@ -2324,11 +2327,11 @@ h11 = ">=0.8" standard = ["colorama (>=0.4) ; sys_platform == \"win32\"", "httptools (>=0.6.3)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1) ; sys_platform != \"win32\" and sys_platform != \"cygwin\" and platform_python_implementation != \"PyPy\"", "watchfiles (>=0.13)", "websockets (>=10.4)"] [extras] -ceda = ["httpx", "httpx-auth"] +ceda = ["confluent-kafka", "httpx", "httpx-auth"] globus = ["boto3", "certifi", "cffi", "charset-normalizer", "cryptography", "esgvoc", "globus-sdk", "idna", "pyjwt"] test = ["httpx", "pytest", "pytest-cov", "pytest-mock"] [metadata] lock-version = "2.1" python-versions = ">=3.12,<4.0" -content-hash = "5a057f8a9beeed61f4d099e3c770146dd7d433b105c0878de29081f12c8189da" +content-hash = "80c751ab30adb72c33612cce0c1a5f0da20c8baf2de121f55e44895445a6437b" diff --git a/pyproject.toml b/pyproject.toml index 98b50f4..a28a5e6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,6 +21,7 @@ dependencies = [ ceda = [ "httpx>=0.28.1", "httpx-auth>=0.23.1", + "confluent-kafka>=2.12.1", ] globus = [ "boto3==1.35.60", From a738f2d32347aa214f1b9d6e49b67450cbf38f88 Mon Sep 17 00:00:00 2001 From: rhysrevans3 Date: Thu, 14 May 2026 10:37:51 +0100 Subject: [PATCH 02/35] Bump pydantic version for python 3.14. --- poetry.lock | 249 +++++++++++++++++++++++++++---------------------- pyproject.toml | 1 + 2 files changed, 136 insertions(+), 114 deletions(-) diff --git a/poetry.lock b/poetry.lock index b498cb5..e088f8d 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1454,21 +1454,21 @@ files = [ [[package]] name = "pydantic" -version = "2.11.10" +version = "2.13.4" description = "Data validation using Python type hints" optional = false python-versions = ">=3.9" groups = ["main"] files = [ - {file = "pydantic-2.11.10-py3-none-any.whl", hash = "sha256:802a655709d49bd004c31e865ef37da30b540786a46bfce02333e0e24b5fe29a"}, - {file = "pydantic-2.11.10.tar.gz", hash = "sha256:dc280f0982fbda6c38fada4e476dc0a4f3aeaf9c6ad4c28df68a666ec3c61423"}, + {file = "pydantic-2.13.4-py3-none-any.whl", hash = "sha256:45a282cde31d808236fd7ea9d919b128653c8b38b393d1c4ab335c62924d9aba"}, + {file = "pydantic-2.13.4.tar.gz", hash = "sha256:c40756b57adaa8b1efeeced5c196f3f3b7c435f90e84ea7f443901bec8099ef6"}, ] [package.dependencies] annotated-types = ">=0.6.0" -pydantic-core = "2.33.2" -typing-extensions = ">=4.12.2" -typing-inspection = ">=0.4.0" +pydantic-core = "2.46.4" +typing-extensions = ">=4.14.1" +typing-inspection = ">=0.4.2" [package.extras] email = ["email-validator (>=2.0.0)"] @@ -1476,115 +1476,136 @@ timezone = ["tzdata ; python_version >= \"3.9\" and platform_system == \"Windows [[package]] name = "pydantic-core" -version = "2.33.2" +version = "2.46.4" description = "Core functionality for Pydantic validation and serialization" optional = false python-versions = ">=3.9" groups = ["main"] files = [ - {file = "pydantic_core-2.33.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2b3d326aaef0c0399d9afffeb6367d5e26ddc24d351dbc9c636840ac355dc5d8"}, - {file = "pydantic_core-2.33.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e5b2671f05ba48b94cb90ce55d8bdcaaedb8ba00cc5359f6810fc918713983d"}, - {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0069c9acc3f3981b9ff4cdfaf088e98d83440a4c7ea1bc07460af3d4dc22e72d"}, - {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d53b22f2032c42eaaf025f7c40c2e3b94568ae077a606f006d206a463bc69572"}, - {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0405262705a123b7ce9f0b92f123334d67b70fd1f20a9372b907ce1080c7ba02"}, - {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4b25d91e288e2c4e0662b8038a28c6a07eaac3e196cfc4ff69de4ea3db992a1b"}, - {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6bdfe4b3789761f3bcb4b1ddf33355a71079858958e3a552f16d5af19768fef2"}, - {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:efec8db3266b76ef9607c2c4c419bdb06bf335ae433b80816089ea7585816f6a"}, - {file = "pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:031c57d67ca86902726e0fae2214ce6770bbe2f710dc33063187a68744a5ecac"}, - {file = "pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:f8de619080e944347f5f20de29a975c2d815d9ddd8be9b9b7268e2e3ef68605a"}, - {file = "pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:73662edf539e72a9440129f231ed3757faab89630d291b784ca99237fb94db2b"}, - {file = "pydantic_core-2.33.2-cp310-cp310-win32.whl", hash = "sha256:0a39979dcbb70998b0e505fb1556a1d550a0781463ce84ebf915ba293ccb7e22"}, - {file = "pydantic_core-2.33.2-cp310-cp310-win_amd64.whl", hash = "sha256:b0379a2b24882fef529ec3b4987cb5d003b9cda32256024e6fe1586ac45fc640"}, - {file = "pydantic_core-2.33.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:4c5b0a576fb381edd6d27f0a85915c6daf2f8138dc5c267a57c08a62900758c7"}, - {file = "pydantic_core-2.33.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e799c050df38a639db758c617ec771fd8fb7a5f8eaaa4b27b101f266b216a246"}, - {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dc46a01bf8d62f227d5ecee74178ffc448ff4e5197c756331f71efcc66dc980f"}, - {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a144d4f717285c6d9234a66778059f33a89096dfb9b39117663fd8413d582dcc"}, - {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:73cf6373c21bc80b2e0dc88444f41ae60b2f070ed02095754eb5a01df12256de"}, - {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3dc625f4aa79713512d1976fe9f0bc99f706a9dee21dfd1810b4bbbf228d0e8a"}, - {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:881b21b5549499972441da4758d662aeea93f1923f953e9cbaff14b8b9565aef"}, - {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bdc25f3681f7b78572699569514036afe3c243bc3059d3942624e936ec93450e"}, - {file = "pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:fe5b32187cbc0c862ee201ad66c30cf218e5ed468ec8dc1cf49dec66e160cc4d"}, - {file = "pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:bc7aee6f634a6f4a95676fcb5d6559a2c2a390330098dba5e5a5f28a2e4ada30"}, - {file = "pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:235f45e5dbcccf6bd99f9f472858849f73d11120d76ea8707115415f8e5ebebf"}, - {file = "pydantic_core-2.33.2-cp311-cp311-win32.whl", hash = "sha256:6368900c2d3ef09b69cb0b913f9f8263b03786e5b2a387706c5afb66800efd51"}, - {file = "pydantic_core-2.33.2-cp311-cp311-win_amd64.whl", hash = "sha256:1e063337ef9e9820c77acc768546325ebe04ee38b08703244c1309cccc4f1bab"}, - {file = "pydantic_core-2.33.2-cp311-cp311-win_arm64.whl", hash = "sha256:6b99022f1d19bc32a4c2a0d544fc9a76e3be90f0b3f4af413f87d38749300e65"}, - {file = "pydantic_core-2.33.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a7ec89dc587667f22b6a0b6579c249fca9026ce7c333fc142ba42411fa243cdc"}, - {file = "pydantic_core-2.33.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3c6db6e52c6d70aa0d00d45cdb9b40f0433b96380071ea80b09277dba021ddf7"}, - {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e61206137cbc65e6d5256e1166f88331d3b6238e082d9f74613b9b765fb9025"}, - {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eb8c529b2819c37140eb51b914153063d27ed88e3bdc31b71198a198e921e011"}, - {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c52b02ad8b4e2cf14ca7b3d918f3eb0ee91e63b3167c32591e57c4317e134f8f"}, - {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:96081f1605125ba0855dfda83f6f3df5ec90c61195421ba72223de35ccfb2f88"}, - {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f57a69461af2a5fa6e6bbd7a5f60d3b7e6cebb687f55106933188e79ad155c1"}, - {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:572c7e6c8bb4774d2ac88929e3d1f12bc45714ae5ee6d9a788a9fb35e60bb04b"}, - {file = "pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:db4b41f9bd95fbe5acd76d89920336ba96f03e149097365afe1cb092fceb89a1"}, - {file = "pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:fa854f5cf7e33842a892e5c73f45327760bc7bc516339fda888c75ae60edaeb6"}, - {file = "pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5f483cfb75ff703095c59e365360cb73e00185e01aaea067cd19acffd2ab20ea"}, - {file = "pydantic_core-2.33.2-cp312-cp312-win32.whl", hash = "sha256:9cb1da0f5a471435a7bc7e439b8a728e8b61e59784b2af70d7c169f8dd8ae290"}, - {file = "pydantic_core-2.33.2-cp312-cp312-win_amd64.whl", hash = "sha256:f941635f2a3d96b2973e867144fde513665c87f13fe0e193c158ac51bfaaa7b2"}, - {file = "pydantic_core-2.33.2-cp312-cp312-win_arm64.whl", hash = "sha256:cca3868ddfaccfbc4bfb1d608e2ccaaebe0ae628e1416aeb9c4d88c001bb45ab"}, - {file = "pydantic_core-2.33.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:1082dd3e2d7109ad8b7da48e1d4710c8d06c253cbc4a27c1cff4fbcaa97a9e3f"}, - {file = "pydantic_core-2.33.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f517ca031dfc037a9c07e748cefd8d96235088b83b4f4ba8939105d20fa1dcd6"}, - {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a9f2c9dd19656823cb8250b0724ee9c60a82f3cdf68a080979d13092a3b0fef"}, - {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2b0a451c263b01acebe51895bfb0e1cc842a5c666efe06cdf13846c7418caa9a"}, - {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ea40a64d23faa25e62a70ad163571c0b342b8bf66d5fa612ac0dec4f069d916"}, - {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fb2d542b4d66f9470e8065c5469ec676978d625a8b7a363f07d9a501a9cb36a"}, - {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdac5d6ffa1b5a83bca06ffe7583f5576555e6c8b3a91fbd25ea7780f825f7d"}, - {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:04a1a413977ab517154eebb2d326da71638271477d6ad87a769102f7c2488c56"}, - {file = "pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:c8e7af2f4e0194c22b5b37205bfb293d166a7344a5b0d0eaccebc376546d77d5"}, - {file = "pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:5c92edd15cd58b3c2d34873597a1e20f13094f59cf88068adb18947df5455b4e"}, - {file = "pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:65132b7b4a1c0beded5e057324b7e16e10910c106d43675d9bd87d4f38dde162"}, - {file = "pydantic_core-2.33.2-cp313-cp313-win32.whl", hash = "sha256:52fb90784e0a242bb96ec53f42196a17278855b0f31ac7c3cc6f5c1ec4811849"}, - {file = "pydantic_core-2.33.2-cp313-cp313-win_amd64.whl", hash = "sha256:c083a3bdd5a93dfe480f1125926afcdbf2917ae714bdb80b36d34318b2bec5d9"}, - {file = "pydantic_core-2.33.2-cp313-cp313-win_arm64.whl", hash = "sha256:e80b087132752f6b3d714f041ccf74403799d3b23a72722ea2e6ba2e892555b9"}, - {file = "pydantic_core-2.33.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:61c18fba8e5e9db3ab908620af374db0ac1baa69f0f32df4f61ae23f15e586ac"}, - {file = "pydantic_core-2.33.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95237e53bb015f67b63c91af7518a62a8660376a6a0db19b89acc77a4d6199f5"}, - {file = "pydantic_core-2.33.2-cp313-cp313t-win_amd64.whl", hash = "sha256:c2fc0a768ef76c15ab9238afa6da7f69895bb5d1ee83aeea2e3509af4472d0b9"}, - {file = "pydantic_core-2.33.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:a2b911a5b90e0374d03813674bf0a5fbbb7741570dcd4b4e85a2e48d17def29d"}, - {file = "pydantic_core-2.33.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6fa6dfc3e4d1f734a34710f391ae822e0a8eb8559a85c6979e14e65ee6ba2954"}, - {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c54c939ee22dc8e2d545da79fc5381f1c020d6d3141d3bd747eab59164dc89fb"}, - {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:53a57d2ed685940a504248187d5685e49eb5eef0f696853647bf37c418c538f7"}, - {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:09fb9dd6571aacd023fe6aaca316bd01cf60ab27240d7eb39ebd66a3a15293b4"}, - {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0e6116757f7959a712db11f3e9c0a99ade00a5bbedae83cb801985aa154f071b"}, - {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d55ab81c57b8ff8548c3e4947f119551253f4e3787a7bbc0b6b3ca47498a9d3"}, - {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c20c462aa4434b33a2661701b861604913f912254e441ab8d78d30485736115a"}, - {file = "pydantic_core-2.33.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:44857c3227d3fb5e753d5fe4a3420d6376fa594b07b621e220cd93703fe21782"}, - {file = "pydantic_core-2.33.2-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:eb9b459ca4df0e5c87deb59d37377461a538852765293f9e6ee834f0435a93b9"}, - {file = "pydantic_core-2.33.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9fcd347d2cc5c23b06de6d3b7b8275be558a0c90549495c699e379a80bf8379e"}, - {file = "pydantic_core-2.33.2-cp39-cp39-win32.whl", hash = "sha256:83aa99b1285bc8f038941ddf598501a86f1536789740991d7d8756e34f1e74d9"}, - {file = "pydantic_core-2.33.2-cp39-cp39-win_amd64.whl", hash = "sha256:f481959862f57f29601ccced557cc2e817bce7533ab8e01a797a48b49c9692b3"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5c4aa4e82353f65e548c476b37e64189783aa5384903bfea4f41580f255fddfa"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:d946c8bf0d5c24bf4fe333af284c59a19358aa3ec18cb3dc4370080da1e8ad29"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:87b31b6846e361ef83fedb187bb5b4372d0da3f7e28d85415efa92d6125d6e6d"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa9d91b338f2df0508606f7009fde642391425189bba6d8c653afd80fd6bb64e"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2058a32994f1fde4ca0480ab9d1e75a0e8c87c22b53a3ae66554f9af78f2fe8c"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:0e03262ab796d986f978f79c943fc5f620381be7287148b8010b4097f79a39ec"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:1a8695a8d00c73e50bff9dfda4d540b7dee29ff9b8053e38380426a85ef10052"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:fa754d1850735a0b0e03bcffd9d4b4343eb417e47196e4485d9cca326073a42c"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a11c8d26a50bfab49002947d3d237abe4d9e4b5bdc8846a63537b6488e197808"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:dd14041875d09cc0f9308e37a6f8b65f5585cf2598a53aa0123df8b129d481f8"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:d87c561733f66531dced0da6e864f44ebf89a8fba55f31407b00c2f7f9449593"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f82865531efd18d6e07a04a17331af02cb7a651583c418df8266f17a63c6612"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bfb5112df54209d820d7bf9317c7a6c9025ea52e49f46b6a2060104bba37de7"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:64632ff9d614e5eecfb495796ad51b0ed98c453e447a76bcbeeb69615079fc7e"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:f889f7a40498cc077332c7ab6b4608d296d852182211787d4f3ee377aaae66e8"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:de4b83bb311557e439b9e186f733f6c645b9417c84e2eb8203f3f820a4b988bf"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:82f68293f055f51b51ea42fafc74b6aad03e70e191799430b90c13d643059ebb"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:329467cecfb529c925cf2bbd4d60d2c509bc2fb52a20c1045bf09bb70971a9c1"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:87acbfcf8e90ca885206e98359d7dca4bcbb35abdc0ff66672a293e1d7a19101"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:7f92c15cd1e97d4b12acd1cc9004fa092578acfa57b67ad5e43a197175d01a64"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d3f26877a748dc4251cfcfda9dfb5f13fcb034f5308388066bcfe9031b63ae7d"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dac89aea9af8cd672fa7b510e7b8c33b0bba9a43186680550ccf23020f32d535"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:970919794d126ba8645f3837ab6046fb4e72bbc057b3709144066204c19a455d"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:3eb3fe62804e8f859c49ed20a8451342de53ed764150cb14ca71357c765dc2a6"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:3abcd9392a36025e3bd55f9bd38d908bd17962cc49bc6da8e7e96285336e2bca"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:3a1c81334778f9e3af2f8aeb7a960736e5cab1dfebfb26aabca09afd2906c039"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2807668ba86cb38c6817ad9bc66215ab8584d1d304030ce4f0887336f28a5e27"}, - {file = "pydantic_core-2.33.2.tar.gz", hash = "sha256:7cb8bc3605c29176e1b105350d2e6474142d7c1bd1d9327c4a9bdb46bf827acc"}, + {file = "pydantic_core-2.46.4-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:a396dcc17e5a0b164dbe026896245a4fa9ff402edca1dff0be3d53a517f74de4"}, + {file = "pydantic_core-2.46.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:da4b951fe36dc7c3a1ccb4e3cd1747c3542b8c9ceede8fc86cae054e764485f5"}, + {file = "pydantic_core-2.46.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb63e0198ca18aad131c089b9204c23079c3afa95487e561f4c522d519e55aba"}, + {file = "pydantic_core-2.46.4-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f47286a97f0bc9b8859519809077b91b2cefe4ae47fcbf5e466a009c1c5d742b"}, + {file = "pydantic_core-2.46.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:905a0ed8ea6f2d61c1738835f99b699348d7857379083e5fc497fa0c967a407c"}, + {file = "pydantic_core-2.46.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea793e075b70290d89d8142074262885d3f7da19634845135751bd6344f73b50"}, + {file = "pydantic_core-2.46.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:395aebd9183f9d112f569aeb5b2214d1a10a33bec8456447f7fbdfa51d38d4cd"}, + {file = "pydantic_core-2.46.4-cp310-cp310-manylinux_2_31_riscv64.whl", hash = "sha256:b078afbc25f3a1436c7a1d2cd3e322497ee99615ba97c563566fdf46aff1ee01"}, + {file = "pydantic_core-2.46.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f747929cf940cddb5b3668a390056ddd5ba2e5010615ea2dcf4f9c4f3ab8791d"}, + {file = "pydantic_core-2.46.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:daa27d92c36f24388fe3ad306b174781c747627f134452e4f128ea00ce1fe8c4"}, + {file = "pydantic_core-2.46.4-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:19e51f073cd3df251856a8a4189fbdf1de4012c3ebacfb1884f94f1eb406079f"}, + {file = "pydantic_core-2.46.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c1747f85cee84c26985853c6f3d9bd3e75da5212912443fa111c113b9c246f39"}, + {file = "pydantic_core-2.46.4-cp310-cp310-win32.whl", hash = "sha256:2f84c03c8607173d16b5a854ec68a2f9079ae03237a54fb506d13af47e1d018d"}, + {file = "pydantic_core-2.46.4-cp310-cp310-win_amd64.whl", hash = "sha256:8358a950c8909158e3df31538a7e4edc2d7265a7c54b47f0864d9e5bae9dcebf"}, + {file = "pydantic_core-2.46.4-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:0e96592440881c74a213e5ad528e2b24d3d4f940de2766bed9010ab1d9e51594"}, + {file = "pydantic_core-2.46.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e0d65b8c354be7fb5f720c3caa8bc940bc2d20ce749c8e06135f07f8ed95dd7c"}, + {file = "pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bfb192b3f4b9e8a89b6277b6ce787564f62cfd272055f6e685726b111dc7826"}, + {file = "pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9037063db01f09b09e237c282b6792bd4da634b5402c4e7f0c61effed7701a04"}, + {file = "pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fc010ab034c8c7452522748bf937df58020d256ccae0874463d1f4d01758af8e"}, + {file = "pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c5dac79fa1614d1e06ca695109c6105923bd9c7d1d6c918d4e637b7e6b32fd3"}, + {file = "pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f9fa868638bf362d3d138ea55829cefb3d5f4b0d7f142234382a15e2485dbec4"}, + {file = "pydantic_core-2.46.4-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:17299feefe090f2caa5b8e37222bb5f663e4935a8bfa6931d4102e5df1a9f398"}, + {file = "pydantic_core-2.46.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4c63ebc82684aa89d9a3bcbd13d515b3be44250dc68dd3bd81526c1cb31286c3"}, + {file = "pydantic_core-2.46.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:aaa2a54443eff1950ba5ddc6b6ccda0d9c84a364276a62f969bdf2a390650848"}, + {file = "pydantic_core-2.46.4-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:18e5ceec2ab67e6d5f1a9085e5a24c9c4e2ac4545730bfe668680bca05e555f3"}, + {file = "pydantic_core-2.46.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a0f62d0a58f4e7da165457e995725421e0064f2255d8eccebc49f41bbc23b109"}, + {file = "pydantic_core-2.46.4-cp311-cp311-win32.whl", hash = "sha256:041bde0a48fd37cf71cab1c9d56d3e8625a3793fef1f7dd232b3ff37e978ecda"}, + {file = "pydantic_core-2.46.4-cp311-cp311-win_amd64.whl", hash = "sha256:6f2eeda33a839975441c86a4119e1383c50b47faf0cbb5176985565c6bb02c33"}, + {file = "pydantic_core-2.46.4-cp311-cp311-win_arm64.whl", hash = "sha256:14f4c5d6db102bd796a627bbb3a17b4cf4574b9ae861d8b7c9a9661c6dd3362d"}, + {file = "pydantic_core-2.46.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:3245406455a5d98187ec35530fd772b1d799b26667980872c8d4614991e2c4a2"}, + {file = "pydantic_core-2.46.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:962ccbab7b642487b1d8b7df90ef677e03134cf1fd8880bf698649b22a69371f"}, + {file = "pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8233f2947cf85404441fd7e0085f53b10c93e0ee78611099b5c7237e36aacbf7"}, + {file = "pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3a233125ac121aa3ffba9a2b59edfc4a985a76092dc8279586ab4b71390875e7"}, + {file = "pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b712b53160b79a5850310b912a5ef8e57e56947c8ad690c227f5c9d7e561712"}, + {file = "pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9401557acd873c3a7f3eb9383edef8ac4968f9510e340f4808d427e75667e7b4"}, + {file = "pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:926c9541b14b12b1681dca8a0b75feb510b06c6341b70a8e500c2fdcff837cce"}, + {file = "pydantic_core-2.46.4-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:56cb4851bcaf3d117eddcef4fe66afd750a50274b0da8e22be256d10e5611987"}, + {file = "pydantic_core-2.46.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c68fcd102d71ea85c5b2dfac3f4f8476eff42a9e078fd5faefff6d145063536b"}, + {file = "pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b2f69dec1725e79a012d920df1707de5caf7ed5e08f3be4435e25803efc47458"}, + {file = "pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:8d0820e8192167f80d88d64038e609c31452eeca865b4e1d9950a27a4609b00b"}, + {file = "pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fbdb89b3e1c94a30cc5edfce477c6e6a5dc4d8f84665b455c27582f211a1c72c"}, + {file = "pydantic_core-2.46.4-cp312-cp312-win32.whl", hash = "sha256:9aa768456404a8bf48a4406685ac2bec8e72b62c69313734fa3b73cf33b3a894"}, + {file = "pydantic_core-2.46.4-cp312-cp312-win_amd64.whl", hash = "sha256:e9c26f834c65f5752f3f06cb08cb86a913ceb7274d0db6e267808a708b46bc89"}, + {file = "pydantic_core-2.46.4-cp312-cp312-win_arm64.whl", hash = "sha256:4fc73cb559bdb54b1134a706a2802a4cddd27a0633f5abb7e53056268751ac6a"}, + {file = "pydantic_core-2.46.4-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:5d5902252db0d3cedf8d4a1bc68f70eeb430f7e4c7104c8c476753519b423008"}, + {file = "pydantic_core-2.46.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:c94f0688e7b8d0a67abf40e57a7eaaecd17cc9586706a31b76c031f63df052b4"}, + {file = "pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f027324c56cd5406ca49c124b0db10e56c69064fec039acc571c29020cc87c76"}, + {file = "pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e739fee756ba1010f8bcccb534252e85a35fe45ae92c295a06059ce58b74ccd3"}, + {file = "pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9d56801be94b86a9da183e5f3766e6310752b99ff647e38b09a9500d88e46e76"}, + {file = "pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2412e734dcb48da14d4e4006b82b46b74f2518b8a26ee7e58c6844a6cd6d03c4"}, + {file = "pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9551187363ffc0de2a00b2e47c25aeaeb1020b69b668762966df15fc5659dd5a"}, + {file = "pydantic_core-2.46.4-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:0186750b482eefa11d7f435892b09c5c606193ef3375bcf94aa00ae6bfb66262"}, + {file = "pydantic_core-2.46.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5855698a4856556d86e8e6cd8434bc3ac0314ee8e12089ae0e143f64c6256e4e"}, + {file = "pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:cbaf13819775b7f769bf4a1f066cb6df7a28d4480081a589828ef190226881cd"}, + {file = "pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:633147d34cf4550417f12e2b1a0383973bdf5cdfde212cb09e9a581cf10820be"}, + {file = "pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:82cf5301172168103724d49a1444d3378cb20cdee30b116a1bd6031236298a5d"}, + {file = "pydantic_core-2.46.4-cp313-cp313-win32.whl", hash = "sha256:9fa8ae11da9e2b3126c6426f147e0fba88d96d65921799bb30c6abd1cb2c97fb"}, + {file = "pydantic_core-2.46.4-cp313-cp313-win_amd64.whl", hash = "sha256:6b3ace8194b0e5204818c92802dcdca7fc6d88aabbb799d7c795540d9cd6d292"}, + {file = "pydantic_core-2.46.4-cp313-cp313-win_arm64.whl", hash = "sha256:184c081504d17f1c1066e430e117142b2c77d9448a97f7b65c6ac9fd9aee238d"}, + {file = "pydantic_core-2.46.4-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:428e04521a40150c85216fc8b85e8d39fece235a9cf5e383761238c7fa9b96fb"}, + {file = "pydantic_core-2.46.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:23ace664830ee0bfe014a0c7bc248b1f7f25ed7ad103852c317624a1083af462"}, + {file = "pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce5c1d2a8b27468f433ca974829c44060b8097eedc39933e3c206a90ee49c4a9"}, + {file = "pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7283d57845ecf5a163403eb0702dfc220cc4fbdd18919cb5ccea4f95ee1cdab4"}, + {file = "pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8daafc69c93ee8a0204506a3b6b30f586ef54028f52aeeeb5c4cfc5184fd5914"}, + {file = "pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd2213145bcc2ba85884d0ac63d222fece9209678f77b9b4d76f054c561adb28"}, + {file = "pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a5f930472650a82629163023e630d160863fce524c616f4e5186e5de9d9a49b"}, + {file = "pydantic_core-2.46.4-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:c1b3f518abeca3aa13c712fd202306e145abf59a18b094a6bafb2d2bbf59192c"}, + {file = "pydantic_core-2.46.4-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1a7dd0b3ee80d90150e3495a3a13ac34dbcbfd4f012996a6a1d8900e91b5c0fb"}, + {file = "pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:3fb702cd90b0446a3a1c5e470bfa0dd23c0233b676a9099ddcc964fa6ca13898"}, + {file = "pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:b8458003118a712e66286df6a707db01c52c0f52f7db8e4a38f0da1d3b94fc4e"}, + {file = "pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:372429a130e469c9cd698925ce5fc50940b7a1336b0d82038e63d5bbc4edc519"}, + {file = "pydantic_core-2.46.4-cp314-cp314-win32.whl", hash = "sha256:85bb3611ff1802f3ee7fdd7dbff26b56f343fb432d57a4728fdd49b6ef35e2f4"}, + {file = "pydantic_core-2.46.4-cp314-cp314-win_amd64.whl", hash = "sha256:811ff8e9c313ab425368bcbb36e5c4ebd7108c2bbf4e4089cfbb0b01eff63fac"}, + {file = "pydantic_core-2.46.4-cp314-cp314-win_arm64.whl", hash = "sha256:bfec22eab3c8cc2ceec0248aec886624116dc079afa027ecc8ad4a7e62010f8a"}, + {file = "pydantic_core-2.46.4-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:af8244b2bef6aaad6d92cda81372de7f8c8d36c9f0c3ea36e827c60e7d9467a0"}, + {file = "pydantic_core-2.46.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5a4330cdbc57162e4b3aa303f588ba752257694c9c9be3e7ebb11b4aca659b5d"}, + {file = "pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:29c61fc04a3d840155ff08e475a04809278972fe6aef51e2720554e96367e34b"}, + {file = "pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c50f2528cf200c5eed56faf3f4e22fcd5f38c157a8b78576e6ba3168ec35f000"}, + {file = "pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0cbe8b01f948de4286c74cdd6c667aceb38f5c1e26f0693b3983d9d74887c65e"}, + {file = "pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:617d7e2ca7dcb8c5cf6bcb8c59b8832c94b36196bbf1cbd1bfb56ed341905edd"}, + {file = "pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7027560ee92211647d0d34e3f7cd6f50da56399d26a9c8ad0da286d3869a53f3"}, + {file = "pydantic_core-2.46.4-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:f99626688942fb746e545232e7726926f3be91b5975f8b55327665fafda991c7"}, + {file = "pydantic_core-2.46.4-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fc3e9034a63de20e15e8ade85358bc6efc614008cab72898b4b4952bea0509ff"}, + {file = "pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:97e7cf2be5c77b7d1a9713a05605d49460d02c6078d38d8bef3cbe323c548424"}, + {file = "pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:3bf92c5d0e00fefaab325a4d27828fe6b6e2a21848686b5b60d2d9eeb09d76c6"}, + {file = "pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:3ecbc122d18468d06ca279dc26a8c2e2d5acb10943bb35e36ae92096dc3b5565"}, + {file = "pydantic_core-2.46.4-cp314-cp314t-win32.whl", hash = "sha256:e846ae7835bf0703ae43f534ab79a867146dadd59dc9ca5c8b53d5c8f7c9ef02"}, + {file = "pydantic_core-2.46.4-cp314-cp314t-win_amd64.whl", hash = "sha256:2108ba5c1c1eca18030634489dc544844144ee36357f2f9f780b93e7ddbb44b5"}, + {file = "pydantic_core-2.46.4-cp314-cp314t-win_arm64.whl", hash = "sha256:4fcbe087dbc2068af7eda3aa87634eba216dbda64d1ae73c8684b621d33f6596"}, + {file = "pydantic_core-2.46.4-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:fd8b3d9fd264be37976686c7f65cd52a83f5e84f4bfd2adf9c1d469676bbb6ae"}, + {file = "pydantic_core-2.46.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9f444c499b3eefd3a92e348059471ea0c3a6e303d9c1cec09fa748fd9f895201"}, + {file = "pydantic_core-2.46.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3447661d99f75a3683a4cf5c87da72f2161964611864dbbeac7fbb118bb4bfc0"}, + {file = "pydantic_core-2.46.4-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8b9bab013d1c7a79d3501ff86d0bc9c31bf587db4551677b96bec07df78c6b15"}, + {file = "pydantic_core-2.46.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d995260fdf4e1db774581b4900e0f832abe3c7c84996726bbc161b19c8f29e76"}, + {file = "pydantic_core-2.46.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f13a646d65d09fbf1bc6b3a9635d30095c8e7e5cc419ff35ecc563c5fd04cd49"}, + {file = "pydantic_core-2.46.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:432c179df7874eeb73307aad2df0755e1ae0efa61ff0ea89b93e194411ae3928"}, + {file = "pydantic_core-2.46.4-cp39-cp39-manylinux_2_31_riscv64.whl", hash = "sha256:e68b7a074f65a2fd746c52a7ce6142ab7006074ac269ace0c25cd8ba171f8066"}, + {file = "pydantic_core-2.46.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4a05d69cba51d852c5c3e92758653245a50c0b646ced0cf05bd793ed592839d6"}, + {file = "pydantic_core-2.46.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:228ee9bae8bef5b1e97ec58302f80357c37199e0d0a99174e138d28e6957b9d9"}, + {file = "pydantic_core-2.46.4-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:10e17cbb10a330363733efc4d7c4d0dd827ac0909b8f6a6542298fed1ea62f29"}, + {file = "pydantic_core-2.46.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:91a06d2e259ecfbd8c901d70c3c507900458498142b3026a296b7de4d1322cc9"}, + {file = "pydantic_core-2.46.4-cp39-cp39-win32.whl", hash = "sha256:d80ee3d731373b24cebbc10d689ca4ee1875caf0d5703a245db18efd4dd37fc1"}, + {file = "pydantic_core-2.46.4-cp39-cp39-win_amd64.whl", hash = "sha256:3be77f45df024d789a672ae34f8b06fb346c4f9f46ea714956660ea4862e89ac"}, + {file = "pydantic_core-2.46.4-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:14d4edf427bdcf950a8a02d7cb44a08614388dd6e1bdcbf4f67504fa7887da9c"}, + {file = "pydantic_core-2.46.4-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:0ce40cd7b21210e99342afafbd4d0f76d784eb5b1d60f3bdc566be4983c6c73b"}, + {file = "pydantic_core-2.46.4-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:90884113d8b48f760e9587002789ddd741e76ab9f89518cd1e43b1f1a52ec44b"}, + {file = "pydantic_core-2.46.4-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:66ce7632c22d837c95301830e111ad0128a32b8207533b60896a96c4915192ea"}, + {file = "pydantic_core-2.46.4-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:1d8ba486450b14f3b1d63bc521d410ec7565e52f887b9fb671791886436a42f7"}, + {file = "pydantic_core-2.46.4-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:3009f12e4e90b7f88b4f9adb1b0c4a3d58fe7820f3238c190047209d148026df"}, + {file = "pydantic_core-2.46.4-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad785e92e6dc634c21555edc8bd6b64957ab844541bcb96a1366c202951ae526"}, + {file = "pydantic_core-2.46.4-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00c603d540afdd6b80eb39f078f33ebd46211f02f33e34a32d9f053bba711de0"}, + {file = "pydantic_core-2.46.4-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:0c563b08bca408dc7f65f700633d8442fffb2421fc47b8101377e9fd65051ff0"}, + {file = "pydantic_core-2.46.4-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:db06ffe51636ffe9ca531fe9023dd64bdd794be8754cb5df57c5498ae5b518a7"}, + {file = "pydantic_core-2.46.4-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:133878133d271ade3d41d1bfb2a45ec38dbdbda40bc065921c6b04e4630127e2"}, + {file = "pydantic_core-2.46.4-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9bc519fbf2b7578398853d815009ae5e4d4603d12f4e3f91da8c06852d3da3e9"}, + {file = "pydantic_core-2.46.4-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:c7a7bd4e39e8e4c12c39cd480356842b6a8a06e41b23a55a5e3e191718838ddf"}, + {file = "pydantic_core-2.46.4-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:d396ec2b979760aaf3218e76c24e65bd0aca24983298653b3a9d7a45f9e47b30"}, + {file = "pydantic_core-2.46.4-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:86e1a4418c6cd97d60c95c71164158eaf7324fae7b0923264016baa993eba6fc"}, + {file = "pydantic_core-2.46.4-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:d51026d73fcfd93610abc7b27789c26b313920fcfb20e27462d74a7f8b06e983"}, + {file = "pydantic_core-2.46.4.tar.gz", hash = "sha256:62f875393d7f270851f20523dd2e29f082bcc82292d66db2b64ea71f64b6e1c1"}, ] [package.dependencies] -typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" +typing-extensions = ">=4.14.1" [[package]] name = "pydantic-settings" @@ -2263,14 +2284,14 @@ shellingham = ">=1.3.0" [[package]] name = "typing-extensions" -version = "4.12.2" -description = "Backported and Experimental Type Hints for Python 3.8+" +version = "4.15.0" +description = "Backported and Experimental Type Hints for Python 3.9+" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" groups = ["main"] files = [ - {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, - {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, + {file = "typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548"}, + {file = "typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466"}, ] [[package]] @@ -2327,11 +2348,11 @@ h11 = ">=0.8" standard = ["colorama (>=0.4) ; sys_platform == \"win32\"", "httptools (>=0.6.3)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1) ; sys_platform != \"win32\" and sys_platform != \"cygwin\" and platform_python_implementation != \"PyPy\"", "watchfiles (>=0.13)", "websockets (>=10.4)"] [extras] -ceda = ["confluent-kafka", "httpx", "httpx-auth"] +ceda = ["confluent-kafka", "httpx", "httpx-auth", "pydantic"] globus = ["boto3", "certifi", "cffi", "charset-normalizer", "cryptography", "esgvoc", "globus-sdk", "idna", "pyjwt"] test = ["httpx", "pytest", "pytest-cov", "pytest-mock"] [metadata] lock-version = "2.1" python-versions = ">=3.12,<4.0" -content-hash = "80c751ab30adb72c33612cce0c1a5f0da20c8baf2de121f55e44895445a6437b" +content-hash = "1f7a09b7b5d8457373e33a8594bd3ac85c8b9ce1310660858bb0f875e7394c86" diff --git a/pyproject.toml b/pyproject.toml index a28a5e6..7c631dd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,6 +22,7 @@ ceda = [ "httpx>=0.28.1", "httpx-auth>=0.23.1", "confluent-kafka>=2.12.1", + "pydantic>=2.12" ] globus = [ "boto3==1.35.60", From aa79dd1b67bab90fdf5543f6403b214428f26af0 Mon Sep 17 00:00:00 2001 From: rhysrevans3 Date: Tue, 19 May 2026 14:41:31 +0100 Subject: [PATCH 03/35] Updating default extensions. --- src/settings/__init__.py | 106 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 103 insertions(+), 3 deletions(-) diff --git a/src/settings/__init__.py b/src/settings/__init__.py index 4ae46ac..d2c4641 100644 --- a/src/settings/__init__.py +++ b/src/settings/__init__.py @@ -12,9 +12,29 @@ "CMIP6": { "CMIP6": { "regex": [ - r"https:\/\/stac-extensions\.github\.io\/cmip6\/v[0-9]\.[0-9]\.[0-9]/schema\.json" + r"https:\/\/esgf\.github\.io\/stac-transaction-api\/cmip6\/v[0-9]\.[0-9]\.[0-9]/schema\.json" ], - "default": "https://stac-extensions.github.io/cmip6/v1.0.0/schema.json", + "default": "https://esgf.github.io/stac-transaction-api/cmip6/v3.0.4/schema.json", + }, + "alternate_assets": { + "regex": [ + r"https:\/\/stac-extensions\.github\.io\/alternate-assets\/v[0-9]\.[0-9]\.[0-9]\/schema\.json" + ], + "default": "https://stac-extensions.github.io/alternate-assets/v1.2.0/schema.json", + }, + "file": { + "regex": [ + r"https:\/\/stac-extensions\.github\.io\/file\/v[0-9]\.[0-9]\.[0-9]/schema\.json" + ], + "default": "https://stac-extensions.github.io/file/v2.1.0/schema.json", + }, + }, + "CMIP6PLUS": { + "CMIP6PLUS": { + "regex": [ + r"https:\/\/esgf\.github\.io\/stac-transaction-api\/cmip6plus\/v[0-9]\.[0-9]\.[0-9]/schema\.json" + ], + "default": "https://esgf.github.io/stac-transaction-api/cmip6plus/v1.0.1/schema.json", }, "alternate_assets": { "regex": [ @@ -34,7 +54,87 @@ "regex": [ r"https:\/\/stac-extensions\.github\.io\/cmip7\/v[0-9]\.[0-9]\.[0-9]\/schema\.json" ], - "default": "https://stac-extensions.github.io/cmip7/v1.0.0/schema.json", + "default": "https://stac-extensions.github.io/cmip7/v3.0.6/schema.json", + }, + "alternate_assets": { + "regex": [ + r"https:\/\/stac-extensions\.github\.io\/alternate-assets\/v[0-9]\.[0-9]\.[0-9]\/schema\.json" + ], + "default": "https://stac-extensions.github.io/alternate-assets/v1.2.0/schema.json", + }, + "file": { + "regex": [ + r"https:\/\/stac-extensions\.github\.io\/file\/v[0-9]\.[0-9]\.[0-9]/schema\.json" + ], + "default": "https://stac-extensions.github.io/file/v2.1.0/schema.json", + }, + }, + "CORDEX-CMIP6": { + "CORDEX-CMIP6": { + "regex": [ + r"https:\/\/esgf\.github\.io\/stac-transaction-api\/cordex-cmip6\/v[0-9]\.[0-9]\.[0-9]/schema\.json" + ], + "default": "https://esgf.github.io/stac-transaction-api/cordex-cmip6/v3.1.2/schema.json", + }, + "alternate_assets": { + "regex": [ + r"https:\/\/stac-extensions\.github\.io\/alternate-assets\/v[0-9]\.[0-9]\.[0-9]\/schema\.json" + ], + "default": "https://stac-extensions.github.io/alternate-assets/v1.2.0/schema.json", + }, + "file": { + "regex": [ + r"https:\/\/stac-extensions\.github\.io\/file\/v[0-9]\.[0-9]\.[0-9]/schema\.json" + ], + "default": "https://stac-extensions.github.io/file/v2.1.0/schema.json", + }, + }, + "INPUT4MIPS": { + "INPUT4MIPS": { + "regex": [ + r"https:\/\/stac-extensions\.github\.io\/input4mips\/v[0-9]\.[0-9]\.[0-9]\/schema\.json" + ], + "default": "https://stac-extensions.github.io/input4mips/v3.0.0/schema.json", + }, + "alternate_assets": { + "regex": [ + r"https:\/\/stac-extensions\.github\.io\/alternate-assets\/v[0-9]\.[0-9]\.[0-9]\/schema\.json" + ], + "default": "https://stac-extensions.github.io/alternate-assets/v1.2.0/schema.json", + }, + "file": { + "regex": [ + r"https:\/\/stac-extensions\.github\.io\/file\/v[0-9]\.[0-9]\.[0-9]/schema\.json" + ], + "default": "https://stac-extensions.github.io/file/v2.1.0/schema.json", + }, + }, + "OBS4MIPS": { + "OBS4MIPS": { + "regex": [ + r"https:\/\/stac-extensions\.github\.io\/obs4mips\/v[0-9]\.[0-9]\.[0-9]\/schema\.json" + ], + "default": "https://stac-extensions.github.io/obs4mips/v1.0.0/schema.json", + }, + "alternate_assets": { + "regex": [ + r"https:\/\/stac-extensions\.github\.io\/alternate-assets\/v[0-9]\.[0-9]\.[0-9]\/schema\.json" + ], + "default": "https://stac-extensions.github.io/alternate-assets/v1.2.0/schema.json", + }, + "file": { + "regex": [ + r"https:\/\/stac-extensions\.github\.io\/file\/v[0-9]\.[0-9]\.[0-9]/schema\.json" + ], + "default": "https://stac-extensions.github.io/file/v2.1.0/schema.json", + }, + }, + "OBS4REF": { + "OBS4REF": { + "regex": [ + r"https:\/\/stac-extensions\.github\.io\/obs4ref\/v[0-9]\.[0-9]\.[0-9]\/schema\.json" + ], + "default": "https://stac-extensions.github.io/obs4ref/v1.0.1/schema.json", }, "alternate_assets": { "regex": [ From df14767a0b8e32060d1c40c8175e653293a0e505 Mon Sep 17 00:00:00 2001 From: rhysrevans3 Date: Wed, 3 Jun 2026 15:54:30 +0100 Subject: [PATCH 04/35] Add geometry validation. --- src/utils.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/utils.py b/src/utils.py index ece1fae..24b67d7 100644 --- a/src/utils.py +++ b/src/utils.py @@ -11,6 +11,7 @@ UnexpectedExtensionException, ) from jsonschema.protocols import Validator +from shapely.geometry import shape from stac_fastapi.extensions.core.transaction.request import ( PartialItem, PatchAddReplaceTest, @@ -180,6 +181,20 @@ def get_extension_validator(extension: str) -> Validator: return cls(schema) +def validate_geometry(geometry: dict) -> None: + """Validate GeoJSON geometry + + Args: + geometry (dict): geometry to be validation. + + Raises: + STACValidationException: Validation error + """ + geometry_shape = shape(geometry) + if not geometry_shape.is_valid: + raise STACValidationException() + + def validate_patch( item_id: str, item: PartialItem, @@ -196,6 +211,9 @@ def validate_patch( STACValidationException: Validation error UnexpectedExtensionException: Unexpect exception with validation """ + if item.geometry: + validate_geometry(item.geometry) + item, null_keys = get_null_keys(item) for extension in extensions: @@ -246,6 +264,8 @@ def validate_post( Raises: STACValidationException: Validation error """ + validate_geometry(item.geometry) + for extension in extensions: extension_validator = get_extension_validator(str(extension)) From fd5959ac610c08b7a07c0767d4979608c47618de Mon Sep 17 00:00:00 2001 From: rhysrevans3 Date: Thu, 4 Jun 2026 08:38:00 +0100 Subject: [PATCH 05/35] Add shapely dependency. --- poetry.lock | 158 ++++++++++++++++++++++++++++++++++++++++++++++++- pyproject.toml | 1 + 2 files changed, 158 insertions(+), 1 deletion(-) diff --git a/poetry.lock b/poetry.lock index 367f7cd..0dd7766 100644 --- a/poetry.lock +++ b/poetry.lock @@ -510,6 +510,88 @@ files = [ {file = "markupsafe-3.0.3.tar.gz", hash = "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698"}, ] +[[package]] +name = "numpy" +version = "2.4.6" +description = "Fundamental package for array computing in Python" +optional = false +python-versions = ">=3.11" +groups = ["main"] +files = [ + {file = "numpy-2.4.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0280e0356c0829a18d9de1cb7eee50ec22ca639878d7240307ca0943d73cd2c4"}, + {file = "numpy-2.4.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:110f8b71aacb688ec69062bb7f6938a0f8acb01b7c1c4beb453c65b6d234584d"}, + {file = "numpy-2.4.6-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:4cfe66903cc32a9921a6733d96b19bb6abf310397581bbad89c228f5abaf0ee8"}, + {file = "numpy-2.4.6-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:8155154c7c691289fe18f510b5d4657c68c67989f293f0535a91360392ff6538"}, + {file = "numpy-2.4.6-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0ab0a9c4ffb1a6d95ef519fe4247dba8eb6b18ad93999f76b7f657039acabd47"}, + {file = "numpy-2.4.6-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:89cd468399cfd2504718f0ba50e410dca55a170b61a02ad92bb18c8a65186e93"}, + {file = "numpy-2.4.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c2d37ab77531417474168eb79d6d80b14f821a966818505d03013d0833edb7a8"}, + {file = "numpy-2.4.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f407cb6b8e9d6d8c626bc73c945db1706035af8fd632295547bf1c9e46d092d6"}, + {file = "numpy-2.4.6-cp311-cp311-win32.whl", hash = "sha256:ddea102b48f9e339f3948bf22040944184627a30fdf7f858667673b9c5f033c8"}, + {file = "numpy-2.4.6-cp311-cp311-win_amd64.whl", hash = "sha256:1e254a00cdf42b1e4d5b3d68d33af63268d41340d8885df2ab6470f2e1500147"}, + {file = "numpy-2.4.6-cp311-cp311-win_arm64.whl", hash = "sha256:ed9749eef4cbd126da3dc1d6bcb3a57f5eb7ac6a6484146bdbf743f552dfc577"}, + {file = "numpy-2.4.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:001fbb8e08d942dd57599e781f2472269ee7f2755fae407b4f67b2f0b17da3f1"}, + {file = "numpy-2.4.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ebfb099f8dcf083deef3ac1ca4c1503f387cf76296fcb3816b66f5ecb5f54fdb"}, + {file = "numpy-2.4.6-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:3213d622a0283a39a93d188f3cf72b26862df52fbb4ca3697f51705016523d41"}, + {file = "numpy-2.4.6-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:357cc07a6d7b0b182ff02249616a03742827ebb1277546b5c7cd7f7620a45698"}, + {file = "numpy-2.4.6-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5f9fb9157b4ce2971008323afe46053787b526ef624fea915b261468a8421a0f"}, + {file = "numpy-2.4.6-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:90f9849678c75fe7afa2d348ac842c168b0a4d3d61919687216dfc547976d853"}, + {file = "numpy-2.4.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c1a2af6c6ef86344a6b0db6b97834208bf598db514f2b155042439b62605601a"}, + {file = "numpy-2.4.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e5805d5a22fd19c8ccff10a9561f9df94436b0545619ea579db2d3c35294bce2"}, + {file = "numpy-2.4.6-cp312-cp312-win32.whl", hash = "sha256:e3eeb0aabd6bd5ce64faae67e9935203a6991b4bc2a485a767fbafb2c5125f45"}, + {file = "numpy-2.4.6-cp312-cp312-win_amd64.whl", hash = "sha256:d8e8286dd7cea7895157318d1b91cdacac64c479f3cbc8dce548331728484751"}, + {file = "numpy-2.4.6-cp312-cp312-win_arm64.whl", hash = "sha256:4081eb135ac24158bd51cdfbef16f1c64df7063b1143f24731387137c092bec8"}, + {file = "numpy-2.4.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:511dbaf848decaaaf4b4ca48032619fb3138710c4bf7da7617765edad1ef96b0"}, + {file = "numpy-2.4.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bf162abab1c1a736333192707cef898e735a5ca00f38f27eeedf44b39d9e85eb"}, + {file = "numpy-2.4.6-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:043191bfa8eab18c776647b62723ac9dddece59743b13f49b2016094129c2b3f"}, + {file = "numpy-2.4.6-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:6180d8b35af935aed8ece3a85e0a43f87393ae0ac87c8d2c8bd2c993f7270ef3"}, + {file = "numpy-2.4.6-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:72fbe16c6fac95aedf5937fa873445cec2110be35d8a4e9433d7501fd98dae6b"}, + {file = "numpy-2.4.6-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a7830bab239b79cda9c08c2da014761cafb48da6150e1da17ac06283f43b6089"}, + {file = "numpy-2.4.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ef4aea96ce4d3b074422cb4f2f64e216bf9e213004bb58ecfdf50ea02ea8eb9a"}, + {file = "numpy-2.4.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:dfa20cc6ca228e6b155b11da03825975ce66aea520985dbbddf0f2a5a495c605"}, + {file = "numpy-2.4.6-cp313-cp313-win32.whl", hash = "sha256:56b39e5e0622a09a25bf5baf62f4bcf0cb8a41ae6e2819cf49bbc5a74c083f91"}, + {file = "numpy-2.4.6-cp313-cp313-win_amd64.whl", hash = "sha256:c4fc99836233ea196540b17ab0983aff60ed07941751930f5f4d05bc3b3b7359"}, + {file = "numpy-2.4.6-cp313-cp313-win_arm64.whl", hash = "sha256:a7c711e21628b52034bb5ab8d1bce291f752fcc5e92accc615778acee1ff4778"}, + {file = "numpy-2.4.6-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:112b06a867b235ef466ed3508ddf0238050df9c727cafb5301ac385b899189a1"}, + {file = "numpy-2.4.6-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:eaf7fa2de5c0be8ae6ff8e9bea2ccd725e980541244521d8d4b5f3354a27babe"}, + {file = "numpy-2.4.6-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:7265a2f3d436e54ef9f2b52b5c937e6be778781bd97a590319d7348f1c1ca997"}, + {file = "numpy-2.4.6-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f74a575920ab21fe304421a3fc28793d82e299cae9eccb37084e9fc7f3617c20"}, + {file = "numpy-2.4.6-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ede83e07a75dd06bc501566c1eca2afc0d61677c1472ac9ad93fdee6e638a48d"}, + {file = "numpy-2.4.6-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:68bb27509ac1b9a3443094260f6326150663b06abe40b73a2f81160623da5b67"}, + {file = "numpy-2.4.6-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:a0df0043bdb289bde1f62da130d20df23d58b45429f752bc7a8fc5325a225ecd"}, + {file = "numpy-2.4.6-cp313-cp313t-win32.whl", hash = "sha256:29a287e0cf63ff528da061de6b9f64a4618da591ca1046aafc54062e40ca7eab"}, + {file = "numpy-2.4.6-cp313-cp313t-win_amd64.whl", hash = "sha256:25c692919ac5a01f170a3bfcd62d745b24fd095c353d50812637d6fcab442e75"}, + {file = "numpy-2.4.6-cp313-cp313t-win_arm64.whl", hash = "sha256:1e978ec1e8bd0e0e4de6bb75de9d30cbb74db6b6a2bb727618613703ca0167dd"}, + {file = "numpy-2.4.6-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:06ca2f61ec4385a07a6977c55ba998a4466c123642b4a32694d3128fce18c079"}, + {file = "numpy-2.4.6-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:38efbc8de75c7a0fc1ac190162d892787f3f47b57cc291231aafee36b80982b7"}, + {file = "numpy-2.4.6-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:d581b735e177fdcdce6fed8e7e8880a3fb6ee4e3653a3ac6af01c6f4c03effc5"}, + {file = "numpy-2.4.6-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:0a041d3d761dc3c35cc56ce0351506a02bcbc25f7b169f652435141a17db9096"}, + {file = "numpy-2.4.6-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:40fdc1ae7125e518ea98e53e69a4ebc27e1fd50510c47b7ea130cf21e5e1d42b"}, + {file = "numpy-2.4.6-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a2c306dea656c12c68f51f4cea133cbe78ca7435eb28c735eac1d3ebe73be6e8"}, + {file = "numpy-2.4.6-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:33111801a01c12a8a1e3721f0a9232f8cfc8ae2c6b7098167e6f623c6073f402"}, + {file = "numpy-2.4.6-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ae506e6902902557576a26ff33eda8695e7ecb3cb36c3b573a0765dee114ebdb"}, + {file = "numpy-2.4.6-cp314-cp314-win32.whl", hash = "sha256:aaf159caa35993cb1f56fb9b8e4610d35758e7ca005412eb1daa856a78c9c4b1"}, + {file = "numpy-2.4.6-cp314-cp314-win_amd64.whl", hash = "sha256:b507f5c4c1d508876d1819b6bf9a49d365b96320b5d4993426b33a23ca4b8261"}, + {file = "numpy-2.4.6-cp314-cp314-win_arm64.whl", hash = "sha256:6f41ae150c4e32db4f3310cdaf64b1593a03dbabe29eec77fc9b50fe64061df6"}, + {file = "numpy-2.4.6-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ece3d2cfe132e7d51f44a832b303895e6f2d499c5e74dfbdb06ee246147a304a"}, + {file = "numpy-2.4.6-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:e3e5193ef5a3dc73bceee50f7fdc2c90dbb76c42df8d8fae3d1067a583df579e"}, + {file = "numpy-2.4.6-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:17f9ade344e7d9b464a084d69bcf18fc691cb1db67c62ed80820bf4926d78f0e"}, + {file = "numpy-2.4.6-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9cd5ffd25db4e7ba6a375693b3fc0fc1791ec636c17db3720da19bde7180ec43"}, + {file = "numpy-2.4.6-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7d92c3819208a60205a12a245c91ad70cb0a85336659b19b834205573ac8456e"}, + {file = "numpy-2.4.6-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e85b752a1e912b70eaad4fafbd4d1238007ab221de2009b9a2f5ae7461239895"}, + {file = "numpy-2.4.6-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:29cb7f67d10b479ff07c17d33e39f78c07f71c40ef30d63c153d340e96cd3fb4"}, + {file = "numpy-2.4.6-cp314-cp314t-win32.whl", hash = "sha256:260a5d70215b61ab4fadf5c7baacd64821842975eea312125ed3c39a6391b063"}, + {file = "numpy-2.4.6-cp314-cp314t-win_amd64.whl", hash = "sha256:81a1cca95ed5bb92aa8b10dd2cdc9a0d3853a50fad926c28b5d7e8ea54389627"}, + {file = "numpy-2.4.6-cp314-cp314t-win_arm64.whl", hash = "sha256:0c9136e14ed34a9e343a31c533d78a9813a69a3148332bce5e9821cb2f996e66"}, + {file = "numpy-2.4.6-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:55cced7c52e981362f708ad635198e97a752dfba412cc03c23bbf3bd8d5cd662"}, + {file = "numpy-2.4.6-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:d6da64deb6b8ed903e7560180a92f2d804ee1ba5eeb849ac2748b8c1aba1f6d7"}, + {file = "numpy-2.4.6-pp311-pypy311_pp73-macosx_14_0_arm64.whl", hash = "sha256:68a5124b13fa6cc2086764a20005d30bc0548146f7f5322f02fce212ca14317f"}, + {file = "numpy-2.4.6-pp311-pypy311_pp73-macosx_14_0_x86_64.whl", hash = "sha256:948424b06129ce883307e8cff868c31396d8dc7630a59c61d70d98dbe70f222c"}, + {file = "numpy-2.4.6-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5dbbdb29840ca3d91ee0fece42fc29278886d908280bfec0a5846c6f901a3eb0"}, + {file = "numpy-2.4.6-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8ad03c0965fb3c692200e74d458ca28c1dbb4ce96f9a479a8aa041ad5fabca02"}, + {file = "numpy-2.4.6-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:2803abfebfc990042cd494d8ce2d5f82e9d847af6d35ec486923aa19dbad5e73"}, + {file = "numpy-2.4.6.tar.gz", hash = "sha256:f3a3570c4a2a16746ac2c31a7c7c7b0c186b95ce902e33db6f28094ed7387dda"}, +] + [[package]] name = "pydantic" version = "2.13.4" @@ -845,6 +927,80 @@ files = [ {file = "rpds_py-0.25.1.tar.gz", hash = "sha256:8960b6dac09b62dac26e75d7e2c4a22efb835d827a7278c34f72b2b84fa160e3"}, ] +[[package]] +name = "shapely" +version = "2.1.2" +description = "Manipulation and analysis of geometric objects" +optional = false +python-versions = ">=3.10" +groups = ["main"] +files = [ + {file = "shapely-2.1.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7ae48c236c0324b4e139bea88a306a04ca630f49be66741b340729d380d8f52f"}, + {file = "shapely-2.1.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:eba6710407f1daa8e7602c347dfc94adc02205ec27ed956346190d66579eb9ea"}, + {file = "shapely-2.1.2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ef4a456cc8b7b3d50ccec29642aa4aeda959e9da2fe9540a92754770d5f0cf1f"}, + {file = "shapely-2.1.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:e38a190442aacc67ff9f75ce60aec04893041f16f97d242209106d502486a142"}, + {file = "shapely-2.1.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:40d784101f5d06a1fd30b55fc11ea58a61be23f930d934d86f19a180909908a4"}, + {file = "shapely-2.1.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f6f6cd5819c50d9bcf921882784586aab34a4bd53e7553e175dece6db513a6f0"}, + {file = "shapely-2.1.2-cp310-cp310-win32.whl", hash = "sha256:fe9627c39c59e553c90f5bc3128252cb85dc3b3be8189710666d2f8bc3a5503e"}, + {file = "shapely-2.1.2-cp310-cp310-win_amd64.whl", hash = "sha256:1d0bfb4b8f661b3b4ec3565fa36c340bfb1cda82087199711f86a88647d26b2f"}, + {file = "shapely-2.1.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:91121757b0a36c9aac3427a651a7e6567110a4a67c97edf04f8d55d4765f6618"}, + {file = "shapely-2.1.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:16a9c722ba774cf50b5d4541242b4cce05aafd44a015290c82ba8a16931ff63d"}, + {file = "shapely-2.1.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:cc4f7397459b12c0b196c9efe1f9d7e92463cbba142632b4cc6d8bbbbd3e2b09"}, + {file = "shapely-2.1.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:136ab87b17e733e22f0961504d05e77e7be8c9b5a8184f685b4a91a84efe3c26"}, + {file = "shapely-2.1.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:16c5d0fc45d3aa0a69074979f4f1928ca2734fb2e0dde8af9611e134e46774e7"}, + {file = "shapely-2.1.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6ddc759f72b5b2b0f54a7e7cde44acef680a55019eb52ac63a7af2cf17cb9cd2"}, + {file = "shapely-2.1.2-cp311-cp311-win32.whl", hash = "sha256:2fa78b49485391224755a856ed3b3bd91c8455f6121fee0db0e71cefb07d0ef6"}, + {file = "shapely-2.1.2-cp311-cp311-win_amd64.whl", hash = "sha256:c64d5c97b2f47e3cd9b712eaced3b061f2b71234b3fc263e0fcf7d889c6559dc"}, + {file = "shapely-2.1.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:fe2533caae6a91a543dec62e8360fe86ffcdc42a7c55f9dfd0128a977a896b94"}, + {file = "shapely-2.1.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ba4d1333cc0bc94381d6d4308d2e4e008e0bd128bdcff5573199742ee3634359"}, + {file = "shapely-2.1.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0bd308103340030feef6c111d3eb98d50dc13feea33affc8a6f9fa549e9458a3"}, + {file = "shapely-2.1.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1e7d4d7ad262a48bb44277ca12c7c78cb1b0f56b32c10734ec9a1d30c0b0c54b"}, + {file = "shapely-2.1.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e9eddfe513096a71896441a7c37db72da0687b34752c4e193577a145c71736fc"}, + {file = "shapely-2.1.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:980c777c612514c0cf99bc8a9de6d286f5e186dcaf9091252fcd444e5638193d"}, + {file = "shapely-2.1.2-cp312-cp312-win32.whl", hash = "sha256:9111274b88e4d7b54a95218e243282709b330ef52b7b86bc6aaf4f805306f454"}, + {file = "shapely-2.1.2-cp312-cp312-win_amd64.whl", hash = "sha256:743044b4cfb34f9a67205cee9279feaf60ba7d02e69febc2afc609047cb49179"}, + {file = "shapely-2.1.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b510dda1a3672d6879beb319bc7c5fd302c6c354584690973c838f46ec3e0fa8"}, + {file = "shapely-2.1.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8cff473e81017594d20ec55d86b54bc635544897e13a7cfc12e36909c5309a2a"}, + {file = "shapely-2.1.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:fe7b77dc63d707c09726b7908f575fc04ff1d1ad0f3fb92aec212396bc6cfe5e"}, + {file = "shapely-2.1.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7ed1a5bbfb386ee8332713bf7508bc24e32d24b74fc9a7b9f8529a55db9f4ee6"}, + {file = "shapely-2.1.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a84e0582858d841d54355246ddfcbd1fce3179f185da7470f41ce39d001ee1af"}, + {file = "shapely-2.1.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:dc3487447a43d42adcdf52d7ac73804f2312cbfa5d433a7d2c506dcab0033dfd"}, + {file = "shapely-2.1.2-cp313-cp313-win32.whl", hash = "sha256:9c3a3c648aedc9f99c09263b39f2d8252f199cb3ac154fadc173283d7d111350"}, + {file = "shapely-2.1.2-cp313-cp313-win_amd64.whl", hash = "sha256:ca2591bff6645c216695bdf1614fca9c82ea1144d4a7591a466fef64f28f0715"}, + {file = "shapely-2.1.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:2d93d23bdd2ed9dc157b46bc2f19b7da143ca8714464249bef6771c679d5ff40"}, + {file = "shapely-2.1.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:01d0d304b25634d60bd7cf291828119ab55a3bab87dc4af1e44b07fb225f188b"}, + {file = "shapely-2.1.2-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8d8382dd120d64b03698b7298b89611a6ea6f55ada9d39942838b79c9bc89801"}, + {file = "shapely-2.1.2-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:19efa3611eef966e776183e338b2d7ea43569ae99ab34f8d17c2c054d3205cc0"}, + {file = "shapely-2.1.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:346ec0c1a0fcd32f57f00e4134d1200e14bf3f5ae12af87ba83ca275c502498c"}, + {file = "shapely-2.1.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6305993a35989391bd3476ee538a5c9a845861462327efe00dd11a5c8c709a99"}, + {file = "shapely-2.1.2-cp313-cp313t-win32.whl", hash = "sha256:c8876673449f3401f278c86eb33224c5764582f72b653a415d0e6672fde887bf"}, + {file = "shapely-2.1.2-cp313-cp313t-win_amd64.whl", hash = "sha256:4a44bc62a10d84c11a7a3d7c1c4fe857f7477c3506e24c9062da0db0ae0c449c"}, + {file = "shapely-2.1.2-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:9a522f460d28e2bf4e12396240a5fc1518788b2fcd73535166d748399ef0c223"}, + {file = "shapely-2.1.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1ff629e00818033b8d71139565527ced7d776c269a49bd78c9df84e8f852190c"}, + {file = "shapely-2.1.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f67b34271dedc3c653eba4e3d7111aa421d5be9b4c4c7d38d30907f796cb30df"}, + {file = "shapely-2.1.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:21952dc00df38a2c28375659b07a3979d22641aeb104751e769c3ee825aadecf"}, + {file = "shapely-2.1.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:1f2f33f486777456586948e333a56ae21f35ae273be99255a191f5c1fa302eb4"}, + {file = "shapely-2.1.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:cf831a13e0d5a7eb519e96f58ec26e049b1fad411fc6fc23b162a7ce04d9cffc"}, + {file = "shapely-2.1.2-cp314-cp314-win32.whl", hash = "sha256:61edcd8d0d17dd99075d320a1dd39c0cb9616f7572f10ef91b4b5b00c4aeb566"}, + {file = "shapely-2.1.2-cp314-cp314-win_amd64.whl", hash = "sha256:a444e7afccdb0999e203b976adb37ea633725333e5b119ad40b1ca291ecf311c"}, + {file = "shapely-2.1.2-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:5ebe3f84c6112ad3d4632b1fd2290665aa75d4cef5f6c5d77c4c95b324527c6a"}, + {file = "shapely-2.1.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5860eb9f00a1d49ebb14e881f5caf6c2cf472c7fd38bd7f253bbd34f934eb076"}, + {file = "shapely-2.1.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b705c99c76695702656327b819c9660768ec33f5ce01fa32b2af62b56ba400a1"}, + {file = "shapely-2.1.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a1fd0ea855b2cf7c9cddaf25543e914dd75af9de08785f20ca3085f2c9ca60b0"}, + {file = "shapely-2.1.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:df90e2db118c3671a0754f38e36802db75fe0920d211a27481daf50a711fdf26"}, + {file = "shapely-2.1.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:361b6d45030b4ac64ddd0a26046906c8202eb60d0f9f53085f5179f1d23021a0"}, + {file = "shapely-2.1.2-cp314-cp314t-win32.whl", hash = "sha256:b54df60f1fbdecc8ebc2c5b11870461a6417b3d617f555e5033f1505d36e5735"}, + {file = "shapely-2.1.2-cp314-cp314t-win_amd64.whl", hash = "sha256:0036ac886e0923417932c2e6369b6c52e38e0ff5d9120b90eef5cd9a5fc5cae9"}, + {file = "shapely-2.1.2.tar.gz", hash = "sha256:2ed4ecb28320a433db18a5bf029986aa8afcfd740745e78847e330d5d94922a9"}, +] + +[package.dependencies] +numpy = ">=1.21" + +[package.extras] +docs = ["matplotlib", "numpydoc (==1.1.*)", "sphinx", "sphinx-book-theme", "sphinx-remove-toctrees"] +test = ["pytest", "pytest-cov", "scipy-doctest"] + [[package]] name = "sniffio" version = "1.3.1" @@ -1010,4 +1166,4 @@ standard = ["colorama (>=0.4) ; sys_platform == \"win32\"", "httptools (>=0.6.3) [metadata] lock-version = "2.1" python-versions = ">=3.12,<4.0" -content-hash = "98a9ea5ead134e1d07e3bc3e007e063d768e25ee6ef3994ff446384ecec233b1" +content-hash = "3a65ae94dafe7e743fd7567717c30cc64904a84ea816da42493ffcbe293d5e73" diff --git a/pyproject.toml b/pyproject.toml index 207f3e1..e40ae1f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,6 +15,7 @@ dependencies = [ "stac-fastapi.types>=6.0.0", "stac-fastapi.extensions>=6.0.0", "uvicorn>=0.46.0", + "shapely>=2.1.2", ] [dependency-groups] From 74e6b8e0d9367bec6ea68e00025f20ec2a8dc4ea Mon Sep 17 00:00:00 2001 From: rhysrevans3 Date: Thu, 4 Jun 2026 08:47:45 +0100 Subject: [PATCH 06/35] Update extensions. --- src/settings/__init__.py | 84 +++++++++++----------------------------- 1 file changed, 22 insertions(+), 62 deletions(-) diff --git a/src/settings/__init__.py b/src/settings/__init__.py index ed0a2cf..62f1231 100644 --- a/src/settings/__init__.py +++ b/src/settings/__init__.py @@ -11,19 +11,19 @@ "CMIP6": { "CMIP6": { "regex": [ - r"https:\/\/esgf\.github\.io\/stac-transaction-api\/cmip6\/v[0-9]\.[0-9]\.[0-9]/schema\.json" + "https:\\/\\/esgf\\.github\\.io\\/stac-transaction-api\\/cmip6\\/v[0-9]\\.[0-9]\\.[0-9]/schema\\.json" ], "default": "https://esgf.github.io/stac-transaction-api/cmip6/v3.0.4/schema.json", }, "alternate_assets": { "regex": [ - r"https:\/\/stac-extensions\.github\.io\/alternate-assets\/v[0-9]\.[0-9]\.[0-9]\/schema\.json" + "https:\\/\\/stac-extensions\\.github\\.io\\/alternate-assets\\/v[0-9]\\.[0-9]\\.[0-9]\\/schema\\.json" ], "default": "https://stac-extensions.github.io/alternate-assets/v1.2.0/schema.json", }, "file": { "regex": [ - r"https:\/\/stac-extensions\.github\.io\/file\/v[0-9]\.[0-9]\.[0-9]/schema\.json" + "https:\\/\\/stac-extensions\\.github\\.io\\/file\\/v[0-9]\\.[0-9]\\.[0-9]/schema\\.json" ], "default": "https://stac-extensions.github.io/file/v2.1.0/schema.json", }, @@ -31,39 +31,19 @@ "CMIP6Plus": { "CMIP6Plus": { "regex": [ - r"https:\/\/esgf\.github\.io\/stac-transaction-api\/cmip6plus\/v[0-9]\.[0-9]\.[0-9]/schema\.json" + "https:\\/\\/esgf\\.github\\.io\\/stac-transaction-api\\/cmip6plus\\/v[0-9]\\.[0-9]\\.[0-9]/schema\\.json" ], "default": "https://esgf.github.io/stac-transaction-api/cmip6plus/v1.0.4/schema.json", }, "alternate_assets": { "regex": [ - r"https:\/\/stac-extensions\.github\.io\/alternate-assets\/v[0-9]\.[0-9]\.[0-9]\/schema\.json" + "https:\\/\\/stac-extensions\\.github\\.io\\/alternate-assets\\/v[0-9]\\.[0-9]\\.[0-9]\\/schema\\.json" ], "default": "https://stac-extensions.github.io/alternate-assets/v1.2.0/schema.json", }, "file": { "regex": [ - r"https:\/\/stac-extensions\.github\.io\/file\/v[0-9]\.[0-9]\.[0-9]/schema\.json" - ], - "default": "https://stac-extensions.github.io/file/v2.1.0/schema.json", - }, - }, - "CORDEX-CMIP6": { - "CORDEX-CMIP6": { - "regex": [ - r"https:\/\/esgf\.github\.io\/stac-transaction-api\/cordex-cmip6\/v[0-9]\.[0-9]\.[0-9]/schema\.json" - ], - "default": "https://esgf.github.io/stac-transaction-api/cordex-cmip6/v3.1.2/schema.json", - }, - "alternate_assets": { - "regex": [ - r"https:\/\/stac-extensions\.github\.io\/alternate-assets\/v[0-9]\.[0-9]\.[0-9]\/schema\.json" - ], - "default": "https://stac-extensions.github.io/alternate-assets/v1.2.0/schema.json", - }, - "file": { - "regex": [ - r"https:\/\/stac-extensions\.github\.io\/file\/v[0-9]\.[0-9]\.[0-9]/schema\.json" + "https:\\/\\/stac-extensions\\.github\\.io\\/file\\/v[0-9]\\.[0-9]\\.[0-9]/schema\\.json" ], "default": "https://stac-extensions.github.io/file/v2.1.0/schema.json", }, @@ -71,79 +51,59 @@ "CMIP7": { "CMIP7": { "regex": [ - r"https:\/\/stac-extensions\.github\.io\/cmip7\/v[0-9]\.[0-9]\.[0-9]\/schema\.json" + "https:\\/\\/esgf\\.github\\.io\\/stac-transaction-api\\/cmip7\\/v[0-9]\\.[0-9]\\.[0-9]\\/schema\\.json" ], - "default": "https://stac-extensions.github.io/cmip7/v3.0.6/schema.json", + "default": "https://esgf.github.io/stac-transaction-api/cmip7/v1.0.0/schema.json", }, "alternate_assets": { "regex": [ - r"https:\/\/stac-extensions\.github\.io\/alternate-assets\/v[0-9]\.[0-9]\.[0-9]\/schema\.json" + "https:\\/\\/stac-extensions\\.github\\.io\\/alternate-assets\\/v[0-9]\\.[0-9]\\.[0-9]\\/schema\\.json" ], "default": "https://stac-extensions.github.io/alternate-assets/v1.2.0/schema.json", }, "file": { "regex": [ - r"https:\/\/stac-extensions\.github\.io\/file\/v[0-9]\.[0-9]\.[0-9]/schema\.json" + "https:\\/\\/stac-extensions\\.github\\.io\\/file\\/v[0-9]\\.[0-9]\\.[0-9]/schema\\.json" ], "default": "https://stac-extensions.github.io/file/v2.1.0/schema.json", }, }, - "INPUT4MIPS": { - "INPUT4MIPS": { - "regex": [ - r"https:\/\/stac-extensions\.github\.io\/input4mips\/v[0-9]\.[0-9]\.[0-9]\/schema\.json" - ], - "default": "https://stac-extensions.github.io/input4mips/v3.0.0/schema.json", - }, - "alternate_assets": { - "regex": [ - r"https:\/\/stac-extensions\.github\.io\/alternate-assets\/v[0-9]\.[0-9]\.[0-9]\/schema\.json" - ], - "default": "https://stac-extensions.github.io/alternate-assets/v1.2.0/schema.json", - }, - "file": { - "regex": [ - r"https:\/\/stac-extensions\.github\.io\/file\/v[0-9]\.[0-9]\.[0-9]/schema\.json" - ], - "default": "https://stac-extensions.github.io/file/v2.1.0/schema.json", - }, - }, - "OBS4MIPS": { - "OBS4MIPS": { + "CORDEX-CMIP6": { + "CORDEX-CMIP6": { "regex": [ - r"https:\/\/stac-extensions\.github\.io\/obs4mips\/v[0-9]\.[0-9]\.[0-9]\/schema\.json" + "https:\\/\\/esgf\\.github\\.io\\/stac-transaction-api\\/cordex-cmip6\\/v[0-9]\\.[0-9]\\.[0-9]/schema\\.json" ], - "default": "https://stac-extensions.github.io/obs4mips/v1.0.0/schema.json", + "default": "https://esgf.github.io/stac-transaction-api/cordex-cmip6/v3.1.2/schema.json", }, "alternate_assets": { "regex": [ - r"https:\/\/stac-extensions\.github\.io\/alternate-assets\/v[0-9]\.[0-9]\.[0-9]\/schema\.json" + "https:\\/\\/stac-extensions\\.github\\.io\\/alternate-assets\\/v[0-9]\\.[0-9]\\.[0-9]\\/schema\\.json" ], "default": "https://stac-extensions.github.io/alternate-assets/v1.2.0/schema.json", }, "file": { "regex": [ - r"https:\/\/stac-extensions\.github\.io\/file\/v[0-9]\.[0-9]\.[0-9]/schema\.json" + "https:\\/\\/stac-extensions\\.github\\.io\\/file\\/v[0-9]\\.[0-9]\\.[0-9]/schema\\.json" ], "default": "https://stac-extensions.github.io/file/v2.1.0/schema.json", }, }, - "OBS4REF": { - "OBS4REF": { + "obs4MIPs": { + "obs4MIPs": { "regex": [ - r"https:\/\/stac-extensions\.github\.io\/obs4ref\/v[0-9]\.[0-9]\.[0-9]\/schema\.json" + "https:\\/\\/esgf\\.github\\.io\\/stac-transaction-api\\/obs4mips\\/v[0-9]\\.[0-9]\\.[0-9]/schema\\.json" ], - "default": "https://stac-extensions.github.io/obs4ref/v1.0.1/schema.json", + "default": "https://esgf.github.io/stac-transaction-api/obs4mips/v1.0.0/schema.json", }, "alternate_assets": { "regex": [ - r"https:\/\/stac-extensions\.github\.io\/alternate-assets\/v[0-9]\.[0-9]\.[0-9]\/schema\.json" + "https:\\/\\/stac-extensions\\.github\\.io\\/alternate-assets\\/v[0-9]\\.[0-9]\\.[0-9]\\/schema\\.json" ], "default": "https://stac-extensions.github.io/alternate-assets/v1.2.0/schema.json", }, "file": { "regex": [ - r"https:\/\/stac-extensions\.github\.io\/file\/v[0-9]\.[0-9]\.[0-9]/schema\.json" + "https:\\/\\/stac-extensions\\.github\\.io\\/file\\/v[0-9]\\.[0-9]\\.[0-9]/schema\\.json" ], "default": "https://stac-extensions.github.io/file/v2.1.0/schema.json", }, From e12e4155953ede346ed280ab069171b84c904113 Mon Sep 17 00:00:00 2001 From: rhysrevans3 Date: Thu, 4 Jun 2026 14:28:54 +0100 Subject: [PATCH 07/35] pre-commit. --- src/settings/__init__.py | 60 ++++++++++------------------------------ 1 file changed, 15 insertions(+), 45 deletions(-) diff --git a/src/settings/__init__.py b/src/settings/__init__.py index 62f1231..b9a8786 100644 --- a/src/settings/__init__.py +++ b/src/settings/__init__.py @@ -10,101 +10,71 @@ DEFAULT_EXTENSIONS = { "CMIP6": { "CMIP6": { - "regex": [ - "https:\\/\\/esgf\\.github\\.io\\/stac-transaction-api\\/cmip6\\/v[0-9]\\.[0-9]\\.[0-9]/schema\\.json" - ], + "regex": ["https:\\/\\/esgf\\.github\\.io\\/stac-transaction-api\\/cmip6\\/v[0-9]\\.[0-9]\\.[0-9]/schema\\.json"], "default": "https://esgf.github.io/stac-transaction-api/cmip6/v3.0.4/schema.json", }, "alternate_assets": { - "regex": [ - "https:\\/\\/stac-extensions\\.github\\.io\\/alternate-assets\\/v[0-9]\\.[0-9]\\.[0-9]\\/schema\\.json" - ], + "regex": ["https:\\/\\/stac-extensions\\.github\\.io\\/alternate-assets\\/v[0-9]\\.[0-9]\\.[0-9]\\/schema\\.json"], "default": "https://stac-extensions.github.io/alternate-assets/v1.2.0/schema.json", }, "file": { - "regex": [ - "https:\\/\\/stac-extensions\\.github\\.io\\/file\\/v[0-9]\\.[0-9]\\.[0-9]/schema\\.json" - ], + "regex": ["https:\\/\\/stac-extensions\\.github\\.io\\/file\\/v[0-9]\\.[0-9]\\.[0-9]/schema\\.json"], "default": "https://stac-extensions.github.io/file/v2.1.0/schema.json", }, }, "CMIP6Plus": { "CMIP6Plus": { - "regex": [ - "https:\\/\\/esgf\\.github\\.io\\/stac-transaction-api\\/cmip6plus\\/v[0-9]\\.[0-9]\\.[0-9]/schema\\.json" - ], + "regex": ["https:\\/\\/esgf\\.github\\.io\\/stac-transaction-api\\/cmip6plus\\/v[0-9]\\.[0-9]\\.[0-9]/schema\\.json"], "default": "https://esgf.github.io/stac-transaction-api/cmip6plus/v1.0.4/schema.json", }, "alternate_assets": { - "regex": [ - "https:\\/\\/stac-extensions\\.github\\.io\\/alternate-assets\\/v[0-9]\\.[0-9]\\.[0-9]\\/schema\\.json" - ], + "regex": ["https:\\/\\/stac-extensions\\.github\\.io\\/alternate-assets\\/v[0-9]\\.[0-9]\\.[0-9]\\/schema\\.json"], "default": "https://stac-extensions.github.io/alternate-assets/v1.2.0/schema.json", }, "file": { - "regex": [ - "https:\\/\\/stac-extensions\\.github\\.io\\/file\\/v[0-9]\\.[0-9]\\.[0-9]/schema\\.json" - ], + "regex": ["https:\\/\\/stac-extensions\\.github\\.io\\/file\\/v[0-9]\\.[0-9]\\.[0-9]/schema\\.json"], "default": "https://stac-extensions.github.io/file/v2.1.0/schema.json", }, }, "CMIP7": { "CMIP7": { - "regex": [ - "https:\\/\\/esgf\\.github\\.io\\/stac-transaction-api\\/cmip7\\/v[0-9]\\.[0-9]\\.[0-9]\\/schema\\.json" - ], + "regex": ["https:\\/\\/esgf\\.github\\.io\\/stac-transaction-api\\/cmip7\\/v[0-9]\\.[0-9]\\.[0-9]\\/schema\\.json"], "default": "https://esgf.github.io/stac-transaction-api/cmip7/v1.0.0/schema.json", }, "alternate_assets": { - "regex": [ - "https:\\/\\/stac-extensions\\.github\\.io\\/alternate-assets\\/v[0-9]\\.[0-9]\\.[0-9]\\/schema\\.json" - ], + "regex": ["https:\\/\\/stac-extensions\\.github\\.io\\/alternate-assets\\/v[0-9]\\.[0-9]\\.[0-9]\\/schema\\.json"], "default": "https://stac-extensions.github.io/alternate-assets/v1.2.0/schema.json", }, "file": { - "regex": [ - "https:\\/\\/stac-extensions\\.github\\.io\\/file\\/v[0-9]\\.[0-9]\\.[0-9]/schema\\.json" - ], + "regex": ["https:\\/\\/stac-extensions\\.github\\.io\\/file\\/v[0-9]\\.[0-9]\\.[0-9]/schema\\.json"], "default": "https://stac-extensions.github.io/file/v2.1.0/schema.json", }, }, "CORDEX-CMIP6": { "CORDEX-CMIP6": { - "regex": [ - "https:\\/\\/esgf\\.github\\.io\\/stac-transaction-api\\/cordex-cmip6\\/v[0-9]\\.[0-9]\\.[0-9]/schema\\.json" - ], + "regex": ["https:\\/\\/esgf\\.github\\.io\\/stac-transaction-api\\/cordex-cmip6\\/v[0-9]\\.[0-9]\\.[0-9]/schema\\.json"], "default": "https://esgf.github.io/stac-transaction-api/cordex-cmip6/v3.1.2/schema.json", }, "alternate_assets": { - "regex": [ - "https:\\/\\/stac-extensions\\.github\\.io\\/alternate-assets\\/v[0-9]\\.[0-9]\\.[0-9]\\/schema\\.json" - ], + "regex": ["https:\\/\\/stac-extensions\\.github\\.io\\/alternate-assets\\/v[0-9]\\.[0-9]\\.[0-9]\\/schema\\.json"], "default": "https://stac-extensions.github.io/alternate-assets/v1.2.0/schema.json", }, "file": { - "regex": [ - "https:\\/\\/stac-extensions\\.github\\.io\\/file\\/v[0-9]\\.[0-9]\\.[0-9]/schema\\.json" - ], + "regex": ["https:\\/\\/stac-extensions\\.github\\.io\\/file\\/v[0-9]\\.[0-9]\\.[0-9]/schema\\.json"], "default": "https://stac-extensions.github.io/file/v2.1.0/schema.json", }, }, "obs4MIPs": { "obs4MIPs": { - "regex": [ - "https:\\/\\/esgf\\.github\\.io\\/stac-transaction-api\\/obs4mips\\/v[0-9]\\.[0-9]\\.[0-9]/schema\\.json" - ], + "regex": ["https:\\/\\/esgf\\.github\\.io\\/stac-transaction-api\\/obs4mips\\/v[0-9]\\.[0-9]\\.[0-9]/schema\\.json"], "default": "https://esgf.github.io/stac-transaction-api/obs4mips/v1.0.0/schema.json", }, "alternate_assets": { - "regex": [ - "https:\\/\\/stac-extensions\\.github\\.io\\/alternate-assets\\/v[0-9]\\.[0-9]\\.[0-9]\\/schema\\.json" - ], + "regex": ["https:\\/\\/stac-extensions\\.github\\.io\\/alternate-assets\\/v[0-9]\\.[0-9]\\.[0-9]\\/schema\\.json"], "default": "https://stac-extensions.github.io/alternate-assets/v1.2.0/schema.json", }, "file": { - "regex": [ - "https:\\/\\/stac-extensions\\.github\\.io\\/file\\/v[0-9]\\.[0-9]\\.[0-9]/schema\\.json" - ], + "regex": ["https:\\/\\/stac-extensions\\.github\\.io\\/file\\/v[0-9]\\.[0-9]\\.[0-9]/schema\\.json"], "default": "https://stac-extensions.github.io/file/v2.1.0/schema.json", }, }, From b79d66b0bf4547c921043f474221ec9912fee1b3 Mon Sep 17 00:00:00 2001 From: rhysrevans3 Date: Thu, 4 Jun 2026 14:31:21 +0100 Subject: [PATCH 08/35] Fix regex. --- src/settings/__init__.py | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/settings/__init__.py b/src/settings/__init__.py index b9a8786..e86f030 100644 --- a/src/settings/__init__.py +++ b/src/settings/__init__.py @@ -10,71 +10,71 @@ DEFAULT_EXTENSIONS = { "CMIP6": { "CMIP6": { - "regex": ["https:\\/\\/esgf\\.github\\.io\\/stac-transaction-api\\/cmip6\\/v[0-9]\\.[0-9]\\.[0-9]/schema\\.json"], + "regex": [r"https:\/\/esgf\.github\.io\/stac-transaction-api\/cmip6\/v[0-9]\.[0-9]\.[0-9]/schema\.json"], "default": "https://esgf.github.io/stac-transaction-api/cmip6/v3.0.4/schema.json", }, "alternate_assets": { - "regex": ["https:\\/\\/stac-extensions\\.github\\.io\\/alternate-assets\\/v[0-9]\\.[0-9]\\.[0-9]\\/schema\\.json"], + "regex": [r"https:\/\/stac-extensions\.github\.io\/alternate-assets\/v[0-9]\.[0-9]\.[0-9]\/schema\.json"], "default": "https://stac-extensions.github.io/alternate-assets/v1.2.0/schema.json", }, "file": { - "regex": ["https:\\/\\/stac-extensions\\.github\\.io\\/file\\/v[0-9]\\.[0-9]\\.[0-9]/schema\\.json"], + "regex": [r"https:\/\/stac-extensions\.github\.io\/file\/v[0-9]\.[0-9]\.[0-9]/schema\.json"], "default": "https://stac-extensions.github.io/file/v2.1.0/schema.json", }, }, "CMIP6Plus": { "CMIP6Plus": { - "regex": ["https:\\/\\/esgf\\.github\\.io\\/stac-transaction-api\\/cmip6plus\\/v[0-9]\\.[0-9]\\.[0-9]/schema\\.json"], + "regex": [r"https:\/\/esgf\.github\.io\/stac-transaction-api\/cmip6plus\/v[0-9]\.[0-9]\.[0-9]/schema\.json"], "default": "https://esgf.github.io/stac-transaction-api/cmip6plus/v1.0.4/schema.json", }, "alternate_assets": { - "regex": ["https:\\/\\/stac-extensions\\.github\\.io\\/alternate-assets\\/v[0-9]\\.[0-9]\\.[0-9]\\/schema\\.json"], + "regex": [r"https:\/\/stac-extensions\.github\.io\/alternate-assets\/v[0-9]\.[0-9]\.[0-9]\/schema\.json"], "default": "https://stac-extensions.github.io/alternate-assets/v1.2.0/schema.json", }, "file": { - "regex": ["https:\\/\\/stac-extensions\\.github\\.io\\/file\\/v[0-9]\\.[0-9]\\.[0-9]/schema\\.json"], + "regex": [r"https:\/\/stac-extensions\.github\.io\/file\/v[0-9]\.[0-9]\.[0-9]/schema\.json"], "default": "https://stac-extensions.github.io/file/v2.1.0/schema.json", }, }, "CMIP7": { "CMIP7": { - "regex": ["https:\\/\\/esgf\\.github\\.io\\/stac-transaction-api\\/cmip7\\/v[0-9]\\.[0-9]\\.[0-9]\\/schema\\.json"], + "regex": [r"https:\/\/esgf\.github\.io\/stac-transaction-api\/cmip7\/v[0-9]\.[0-9]\.[0-9]\/schema\.json"], "default": "https://esgf.github.io/stac-transaction-api/cmip7/v1.0.0/schema.json", }, "alternate_assets": { - "regex": ["https:\\/\\/stac-extensions\\.github\\.io\\/alternate-assets\\/v[0-9]\\.[0-9]\\.[0-9]\\/schema\\.json"], + "regex": [r"https:\/\/stac-extensions\.github\.io\/alternate-assets\/v[0-9]\.[0-9]\.[0-9]\/schema\.json"], "default": "https://stac-extensions.github.io/alternate-assets/v1.2.0/schema.json", }, "file": { - "regex": ["https:\\/\\/stac-extensions\\.github\\.io\\/file\\/v[0-9]\\.[0-9]\\.[0-9]/schema\\.json"], + "regex": [r"https:\/\/stac-extensions\.github\.io\/file\/v[0-9]\.[0-9]\.[0-9]/schema\.json"], "default": "https://stac-extensions.github.io/file/v2.1.0/schema.json", }, }, "CORDEX-CMIP6": { "CORDEX-CMIP6": { - "regex": ["https:\\/\\/esgf\\.github\\.io\\/stac-transaction-api\\/cordex-cmip6\\/v[0-9]\\.[0-9]\\.[0-9]/schema\\.json"], + "regex": [r"https:\/\/esgf\.github\.io\/stac-transaction-api\/cordex-cmip6\/v[0-9]\.[0-9]\.[0-9]/schema\.json"], "default": "https://esgf.github.io/stac-transaction-api/cordex-cmip6/v3.1.2/schema.json", }, "alternate_assets": { - "regex": ["https:\\/\\/stac-extensions\\.github\\.io\\/alternate-assets\\/v[0-9]\\.[0-9]\\.[0-9]\\/schema\\.json"], + "regex": [r"https:\/\/stac-extensions\.github\.io\/alternate-assets\/v[0-9]\.[0-9]\.[0-9]\/schema\.json"], "default": "https://stac-extensions.github.io/alternate-assets/v1.2.0/schema.json", }, "file": { - "regex": ["https:\\/\\/stac-extensions\\.github\\.io\\/file\\/v[0-9]\\.[0-9]\\.[0-9]/schema\\.json"], + "regex": [r"https:\/\/stac-extensions\.github\.io\/file\/v[0-9]\.[0-9]\.[0-9]/schema\.json"], "default": "https://stac-extensions.github.io/file/v2.1.0/schema.json", }, }, "obs4MIPs": { "obs4MIPs": { - "regex": ["https:\\/\\/esgf\\.github\\.io\\/stac-transaction-api\\/obs4mips\\/v[0-9]\\.[0-9]\\.[0-9]/schema\\.json"], + "regex": [r"https:\/\/esgf\.github\.io\/stac-transaction-api\/obs4mips\/v[0-9]\.[0-9]\.[0-9]/schema\.json"], "default": "https://esgf.github.io/stac-transaction-api/obs4mips/v1.0.0/schema.json", }, "alternate_assets": { - "regex": ["https:\\/\\/stac-extensions\\.github\\.io\\/alternate-assets\\/v[0-9]\\.[0-9]\\.[0-9]\\/schema\\.json"], + "regex": [r"https:\/\/stac-extensions\.github\.io\/alternate-assets\/v[0-9]\.[0-9]\.[0-9]\/schema\.json"], "default": "https://stac-extensions.github.io/alternate-assets/v1.2.0/schema.json", }, "file": { - "regex": ["https:\\/\\/stac-extensions\\.github\\.io\\/file\\/v[0-9]\\.[0-9]\\.[0-9]/schema\\.json"], + "regex": [r"https:\/\/stac-extensions\.github\.io\/file\/v[0-9]\.[0-9]\.[0-9]/schema\.json"], "default": "https://stac-extensions.github.io/file/v2.1.0/schema.json", }, }, From bd35864c69039400870fa7c7e871e1363e31d088 Mon Sep 17 00:00:00 2001 From: rhysrevans3 Date: Wed, 10 Jun 2026 08:20:47 +0100 Subject: [PATCH 09/35] Add WGS84 bound box validation. --- src/utils.py | 53 +++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 46 insertions(+), 7 deletions(-) diff --git a/src/utils.py b/src/utils.py index ef065aa..e53d211 100644 --- a/src/utils.py +++ b/src/utils.py @@ -25,7 +25,9 @@ logger = logging.getLogger("uvicorn.error") -def operation_to_partial_item(collection_id: str, operations: list[PatchOperation]) -> PartialItem: +def operation_to_partial_item( + collection_id: str, operations: list[PatchOperation] +) -> PartialItem: """Convert operations to partial item Args: @@ -82,7 +84,9 @@ def operation_to_partial_item(collection_id: str, operations: list[PatchOperatio return PartialItem.model_validate(item) -def validate_extensions(collection_id: str, item_extensions: list[str], strict: bool = False) -> list[str]: +def validate_extensions( + collection_id: str, item_extensions: list[str], strict: bool = False +) -> list[str]: """Validate expected default extensions are present. Args: @@ -106,14 +110,20 @@ def validate_extensions(collection_id: str, item_extensions: list[str], strict: expected_extension_key, expected_extension, ) in expected_extensions.copy().items(): - if any(re.compile(regex).match(str(item_extension)) for regex in expected_extension["regex"]): + if any( + re.compile(regex).match(str(item_extension)) + for regex in expected_extension["regex"] + ): expected_extensions.pop(expected_extension_key) expected = True if not expected: raise UnexpectedExtensionException(extension=item_extension) - missing_extensions = [expected_extension["default"] for expected_extension in expected_extensions.values()] + missing_extensions = [ + expected_extension["default"] + for expected_extension in expected_extensions.values() + ] if strict & len(missing_extensions) > 0: raise ExpectedExtensionsMissingException(extensions=missing_extensions) @@ -171,6 +181,22 @@ def get_extension_validator(extension: str) -> Validator: return cls(schema) +def validate_bbox(bbox: list[int | float]) -> None: + """Validate bounding box is WGS84 + + Args: + bbox (int | float): bounding box to be validated + + Raises: + STACValidationException: _description_ + """ + minx, miny, maxx, maxy = bbox[:4] + if not (-180.0 <= minx <= 180.0 and -180.0 <= maxx <= 180.0) or not ( + -90.0 <= miny <= 90.0 and -90.0 <= maxy <= 90.0 + ): + raise STACValidationException() + + def validate_geometry(geometry: dict) -> None: """Validate GeoJSON geometry @@ -184,6 +210,9 @@ def validate_geometry(geometry: dict) -> None: if not geometry_shape.is_valid: raise STACValidationException() + # Check geometry is WGS84 + validate_bbox(geometry_shape.bounds) + def validate_patch( item_id: str, @@ -204,6 +233,9 @@ def validate_patch( if item.geometry: validate_geometry(item.geometry) + if item.bbox: + validate_bbox(item.bbox) + item, null_keys = get_null_keys(item) for extension in extensions: @@ -211,7 +243,9 @@ def validate_patch( required_keys = set() raise_errors = [] - for error in extension_validator.iter_errors(json.loads(item.model_dump_json())): + for error in extension_validator.iter_errors( + json.loads(item.model_dump_json()) + ): if error.validator in ["oneOf"]: continue @@ -223,7 +257,9 @@ def validate_patch( raise_errors.append(error) for null_key_error in required_keys & null_keys: - raise_errors.append(f"Variable {null_key_error} is required and cannot be removed") + raise_errors.append( + f"Variable {null_key_error} is required and cannot be removed" + ) if raise_errors: logger.error(f"STAC validation error: {item_id}") @@ -251,12 +287,15 @@ def validate_post( STACValidationException: Validation error """ validate_geometry(item.geometry) + validate_bbox(item.bbox) for extension in extensions: extension_validator = get_extension_validator(str(extension)) raise_errors = [] - for error in extension_validator.iter_errors(json.loads(item.model_dump_json())): + for error in extension_validator.iter_errors( + json.loads(item.model_dump_json()) + ): raise_errors.append(error) if raise_errors: From c66864ea409e9591dee064ddeeda24937be51182 Mon Sep 17 00:00:00 2001 From: rhysrevans3 Date: Wed, 10 Jun 2026 08:21:51 +0100 Subject: [PATCH 10/35] pre-commit. --- src/utils.py | 34 ++++++++-------------------------- 1 file changed, 8 insertions(+), 26 deletions(-) diff --git a/src/utils.py b/src/utils.py index e53d211..cd113dc 100644 --- a/src/utils.py +++ b/src/utils.py @@ -25,9 +25,7 @@ logger = logging.getLogger("uvicorn.error") -def operation_to_partial_item( - collection_id: str, operations: list[PatchOperation] -) -> PartialItem: +def operation_to_partial_item(collection_id: str, operations: list[PatchOperation]) -> PartialItem: """Convert operations to partial item Args: @@ -84,9 +82,7 @@ def operation_to_partial_item( return PartialItem.model_validate(item) -def validate_extensions( - collection_id: str, item_extensions: list[str], strict: bool = False -) -> list[str]: +def validate_extensions(collection_id: str, item_extensions: list[str], strict: bool = False) -> list[str]: """Validate expected default extensions are present. Args: @@ -110,20 +106,14 @@ def validate_extensions( expected_extension_key, expected_extension, ) in expected_extensions.copy().items(): - if any( - re.compile(regex).match(str(item_extension)) - for regex in expected_extension["regex"] - ): + if any(re.compile(regex).match(str(item_extension)) for regex in expected_extension["regex"]): expected_extensions.pop(expected_extension_key) expected = True if not expected: raise UnexpectedExtensionException(extension=item_extension) - missing_extensions = [ - expected_extension["default"] - for expected_extension in expected_extensions.values() - ] + missing_extensions = [expected_extension["default"] for expected_extension in expected_extensions.values()] if strict & len(missing_extensions) > 0: raise ExpectedExtensionsMissingException(extensions=missing_extensions) @@ -191,9 +181,7 @@ def validate_bbox(bbox: list[int | float]) -> None: STACValidationException: _description_ """ minx, miny, maxx, maxy = bbox[:4] - if not (-180.0 <= minx <= 180.0 and -180.0 <= maxx <= 180.0) or not ( - -90.0 <= miny <= 90.0 and -90.0 <= maxy <= 90.0 - ): + if not (-180.0 <= minx <= 180.0 and -180.0 <= maxx <= 180.0) or not (-90.0 <= miny <= 90.0 and -90.0 <= maxy <= 90.0): raise STACValidationException() @@ -243,9 +231,7 @@ def validate_patch( required_keys = set() raise_errors = [] - for error in extension_validator.iter_errors( - json.loads(item.model_dump_json()) - ): + for error in extension_validator.iter_errors(json.loads(item.model_dump_json())): if error.validator in ["oneOf"]: continue @@ -257,9 +243,7 @@ def validate_patch( raise_errors.append(error) for null_key_error in required_keys & null_keys: - raise_errors.append( - f"Variable {null_key_error} is required and cannot be removed" - ) + raise_errors.append(f"Variable {null_key_error} is required and cannot be removed") if raise_errors: logger.error(f"STAC validation error: {item_id}") @@ -293,9 +277,7 @@ def validate_post( extension_validator = get_extension_validator(str(extension)) raise_errors = [] - for error in extension_validator.iter_errors( - json.loads(item.model_dump_json()) - ): + for error in extension_validator.iter_errors(json.loads(item.model_dump_json())): raise_errors.append(error) if raise_errors: From 2da624426a4bdf7d5f292f6a56b0256f91f72960 Mon Sep 17 00:00:00 2001 From: rhysrevans3 Date: Wed, 10 Jun 2026 08:39:06 +0100 Subject: [PATCH 11/35] Simplify bbox if. --- src/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils.py b/src/utils.py index cd113dc..7e77f7b 100644 --- a/src/utils.py +++ b/src/utils.py @@ -181,7 +181,7 @@ def validate_bbox(bbox: list[int | float]) -> None: STACValidationException: _description_ """ minx, miny, maxx, maxy = bbox[:4] - if not (-180.0 <= minx <= 180.0 and -180.0 <= maxx <= 180.0) or not (-90.0 <= miny <= 90.0 and -90.0 <= maxy <= 90.0): + if not (-180.0 <= minx <= 180.0 and -180.0 <= maxx <= 180.0 and -90.0 <= miny <= 90.0 and -90.0 <= maxy <= 90.0): raise STACValidationException() From 2ee127ff7d6b856a89ff30769119242942969ff7 Mon Sep 17 00:00:00 2001 From: rhysrevans3 Date: Thu, 18 Jun 2026 15:47:06 +0100 Subject: [PATCH 12/35] Add minimum version check for STAC extensions. --- poetry.lock | 871 ++++++++++++++++++++++++++++++++++++++++++++++++- pyproject.toml | 3 +- src/utils.py | 32 +- 3 files changed, 889 insertions(+), 17 deletions(-) diff --git a/poetry.lock b/poetry.lock index 0dd7766..53c8260 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 2.1.0 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.4.1 and should not be changed by hand. [[package]] name = "annotated-types" @@ -6,7 +6,7 @@ version = "0.7.0" description = "Reusable constraint types to use with typing.Annotated" optional = false python-versions = ">=3.8" -groups = ["main"] +groups = ["main", "ceda"] files = [ {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, @@ -18,7 +18,7 @@ version = "4.8.0" description = "High level compatibility layer for multiple asynchronous event loop implementations" optional = false python-versions = ">=3.9" -groups = ["main"] +groups = ["main", "ceda", "test"] files = [ {file = "anyio-4.8.0-py3-none-any.whl", hash = "sha256:b5011f270ab5eb0abf13385f851315585cc37ef330dd88e27ec3d34d651fd47a"}, {file = "anyio-4.8.0.tar.gz", hash = "sha256:1d9fe889df5212298c0c0723fa20479d1b94883a2df44bd3897aa91083316f7a"}, @@ -54,6 +54,46 @@ docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphi tests = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] tests-mypy = ["mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\""] +[[package]] +name = "boto3" +version = "1.43.6" +description = "The AWS SDK for Python" +optional = false +python-versions = ">=3.10" +groups = ["globus"] +files = [ + {file = "boto3-1.43.6-py3-none-any.whl", hash = "sha256:179601ec2992726a718053bf41e43c223ceba397d31ceab11f64d9c910d9fc3a"}, + {file = "boto3-1.43.6.tar.gz", hash = "sha256:e6315effaf12b890b99956e6f8e2c3000a3f64e4ee91943cec3895ce9a836afb"}, +] + +[package.dependencies] +botocore = ">=1.43.6,<1.44.0" +jmespath = ">=0.7.1,<2.0.0" +s3transfer = ">=0.17.0,<0.18.0" + +[package.extras] +crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] + +[[package]] +name = "botocore" +version = "1.43.32" +description = "Low-level, data-driven core of boto 3." +optional = false +python-versions = ">=3.10" +groups = ["globus"] +files = [ + {file = "botocore-1.43.32-py3-none-any.whl", hash = "sha256:429796537fde1301df90d394808985d88cd51b36a6e769e5c12f6a6877605428"}, + {file = "botocore-1.43.32.tar.gz", hash = "sha256:88ed52268b8f7e8ff8f9df5adbbf61e5bbb5dc618ee50de4346cabe93a482792"}, +] + +[package.dependencies] +jmespath = ">=0.7.1,<2.0.0" +python-dateutil = ">=2.1,<3.0.0" +urllib3 = ">=1.25.4,<2.2.0 || >2.2.0,<3" + +[package.extras] +crt = ["awscrt (==0.32.2)"] + [[package]] name = "brotli" version = "1.1.0" @@ -72,6 +112,10 @@ files = [ {file = "Brotli-1.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a37b8f0391212d29b3a91a799c8e4a2855e0576911cdfb2515487e30e322253d"}, {file = "Brotli-1.1.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:e84799f09591700a4154154cab9787452925578841a94321d5ee8fb9a9a328f0"}, {file = "Brotli-1.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f66b5337fa213f1da0d9000bc8dc0cb5b896b726eefd9c6046f699b169c41b9e"}, + {file = "Brotli-1.1.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:5dab0844f2cf82be357a0eb11a9087f70c5430b2c241493fc122bb6f2bb0917c"}, + {file = "Brotli-1.1.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e4fe605b917c70283db7dfe5ada75e04561479075761a0b3866c081d035b01c1"}, + {file = "Brotli-1.1.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:1e9a65b5736232e7a7f91ff3d02277f11d339bf34099a56cdab6a8b3410a02b2"}, + {file = "Brotli-1.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:58d4b711689366d4a03ac7957ab8c28890415e267f9b6589969e74b6e42225ec"}, {file = "Brotli-1.1.0-cp310-cp310-win32.whl", hash = "sha256:be36e3d172dc816333f33520154d708a2657ea63762ec16b62ece02ab5e4daf2"}, {file = "Brotli-1.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:0c6244521dda65ea562d5a69b9a26120769b7a9fb3db2fe9545935ed6735b128"}, {file = "Brotli-1.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a3daabb76a78f829cafc365531c972016e4aa8d5b4bf60660ad8ecee19df7ccc"}, @@ -84,8 +128,14 @@ files = [ {file = "Brotli-1.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:19c116e796420b0cee3da1ccec3b764ed2952ccfcc298b55a10e5610ad7885f9"}, {file = "Brotli-1.1.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:510b5b1bfbe20e1a7b3baf5fed9e9451873559a976c1a78eebaa3b86c57b4265"}, {file = "Brotli-1.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a1fd8a29719ccce974d523580987b7f8229aeace506952fa9ce1d53a033873c8"}, + {file = "Brotli-1.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c247dd99d39e0338a604f8c2b3bc7061d5c2e9e2ac7ba9cc1be5a69cb6cd832f"}, + {file = "Brotli-1.1.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1b2c248cd517c222d89e74669a4adfa5577e06ab68771a529060cf5a156e9757"}, + {file = "Brotli-1.1.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:2a24c50840d89ded6c9a8fdc7b6ed3692ed4e86f1c4a4a938e1e92def92933e0"}, + {file = "Brotli-1.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f31859074d57b4639318523d6ffdca586ace54271a73ad23ad021acd807eb14b"}, {file = "Brotli-1.1.0-cp311-cp311-win32.whl", hash = "sha256:39da8adedf6942d76dc3e46653e52df937a3c4d6d18fdc94a7c29d263b1f5b50"}, {file = "Brotli-1.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:aac0411d20e345dc0920bdec5548e438e999ff68d77564d5e9463a7ca9d3e7b1"}, + {file = "Brotli-1.1.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:32d95b80260d79926f5fab3c41701dbb818fde1c9da590e77e571eefd14abe28"}, + {file = "Brotli-1.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b760c65308ff1e462f65d69c12e4ae085cff3b332d894637f6273a12a482d09f"}, {file = "Brotli-1.1.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:316cc9b17edf613ac76b1f1f305d2a748f1b976b033b049a6ecdfd5612c70409"}, {file = "Brotli-1.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:caf9ee9a5775f3111642d33b86237b05808dafcd6268faa492250e9b78046eb2"}, {file = "Brotli-1.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:70051525001750221daa10907c77830bc889cb6d865cc0b813d9db7fefc21451"}, @@ -96,8 +146,24 @@ files = [ {file = "Brotli-1.1.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:4093c631e96fdd49e0377a9c167bfd75b6d0bad2ace734c6eb20b348bc3ea180"}, {file = "Brotli-1.1.0-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:7e4c4629ddad63006efa0ef968c8e4751c5868ff0b1c5c40f76524e894c50248"}, {file = "Brotli-1.1.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:861bf317735688269936f755fa136a99d1ed526883859f86e41a5d43c61d8966"}, + {file = "Brotli-1.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:87a3044c3a35055527ac75e419dfa9f4f3667a1e887ee80360589eb8c90aabb9"}, + {file = "Brotli-1.1.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:c5529b34c1c9d937168297f2c1fde7ebe9ebdd5e121297ff9c043bdb2ae3d6fb"}, + {file = "Brotli-1.1.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:ca63e1890ede90b2e4454f9a65135a4d387a4585ff8282bb72964fab893f2111"}, + {file = "Brotli-1.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e79e6520141d792237c70bcd7a3b122d00f2613769ae0cb61c52e89fd3443839"}, {file = "Brotli-1.1.0-cp312-cp312-win32.whl", hash = "sha256:5f4d5ea15c9382135076d2fb28dde923352fe02951e66935a9efaac8f10e81b0"}, {file = "Brotli-1.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:906bc3a79de8c4ae5b86d3d75a8b77e44404b0f4261714306e3ad248d8ab0951"}, + {file = "Brotli-1.1.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8bf32b98b75c13ec7cf774164172683d6e7891088f6316e54425fde1efc276d5"}, + {file = "Brotli-1.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7bc37c4d6b87fb1017ea28c9508b36bbcb0c3d18b4260fcdf08b200c74a6aee8"}, + {file = "Brotli-1.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c0ef38c7a7014ffac184db9e04debe495d317cc9c6fb10071f7fefd93100a4f"}, + {file = "Brotli-1.1.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:91d7cc2a76b5567591d12c01f019dd7afce6ba8cba6571187e21e2fc418ae648"}, + {file = "Brotli-1.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a93dde851926f4f2678e704fadeb39e16c35d8baebd5252c9fd94ce8ce68c4a0"}, + {file = "Brotli-1.1.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f0db75f47be8b8abc8d9e31bc7aad0547ca26f24a54e6fd10231d623f183d089"}, + {file = "Brotli-1.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6967ced6730aed543b8673008b5a391c3b1076d834ca438bbd70635c73775368"}, + {file = "Brotli-1.1.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:7eedaa5d036d9336c95915035fb57422054014ebdeb6f3b42eac809928e40d0c"}, + {file = "Brotli-1.1.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:d487f5432bf35b60ed625d7e1b448e2dc855422e87469e3f450aa5552b0eb284"}, + {file = "Brotli-1.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:832436e59afb93e1836081a20f324cb185836c617659b07b129141a8426973c7"}, + {file = "Brotli-1.1.0-cp313-cp313-win32.whl", hash = "sha256:43395e90523f9c23a3d5bdf004733246fba087f2948f87ab28015f12359ca6a0"}, + {file = "Brotli-1.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:9011560a466d2eb3f5a6e4929cf4a09be405c64154e12df0dd72713f6500e32b"}, {file = "Brotli-1.1.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:a090ca607cbb6a34b0391776f0cb48062081f5f60ddcce5d11838e67a01928d1"}, {file = "Brotli-1.1.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2de9d02f5bda03d27ede52e8cfe7b865b066fa49258cbab568720aa5be80a47d"}, {file = "Brotli-1.1.0-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2333e30a5e00fe0fe55903c8832e08ee9c3b1382aacf4db26664a16528d51b4b"}, @@ -107,6 +173,10 @@ files = [ {file = "Brotli-1.1.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:fd5f17ff8f14003595ab414e45fce13d073e0762394f957182e69035c9f3d7c2"}, {file = "Brotli-1.1.0-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:069a121ac97412d1fe506da790b3e69f52254b9df4eb665cd42460c837193354"}, {file = "Brotli-1.1.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:e93dfc1a1165e385cc8239fab7c036fb2cd8093728cbd85097b284d7b99249a2"}, + {file = "Brotli-1.1.0-cp36-cp36m-musllinux_1_2_aarch64.whl", hash = "sha256:aea440a510e14e818e67bfc4027880e2fb500c2ccb20ab21c7a7c8b5b4703d75"}, + {file = "Brotli-1.1.0-cp36-cp36m-musllinux_1_2_i686.whl", hash = "sha256:6974f52a02321b36847cd19d1b8e381bf39939c21efd6ee2fc13a28b0d99348c"}, + {file = "Brotli-1.1.0-cp36-cp36m-musllinux_1_2_ppc64le.whl", hash = "sha256:a7e53012d2853a07a4a79c00643832161a910674a893d296c9f1259859a289d2"}, + {file = "Brotli-1.1.0-cp36-cp36m-musllinux_1_2_x86_64.whl", hash = "sha256:d7702622a8b40c49bffb46e1e3ba2e81268d5c04a34f460978c6b5517a34dd52"}, {file = "Brotli-1.1.0-cp36-cp36m-win32.whl", hash = "sha256:a599669fd7c47233438a56936988a2478685e74854088ef5293802123b5b2460"}, {file = "Brotli-1.1.0-cp36-cp36m-win_amd64.whl", hash = "sha256:d143fd47fad1db3d7c27a1b1d66162e855b5d50a89666af46e1679c496e8e579"}, {file = "Brotli-1.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:11d00ed0a83fa22d29bc6b64ef636c4552ebafcef57154b4ddd132f5638fbd1c"}, @@ -118,6 +188,10 @@ files = [ {file = "Brotli-1.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:919e32f147ae93a09fe064d77d5ebf4e35502a8df75c29fb05788528e330fe74"}, {file = "Brotli-1.1.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:23032ae55523cc7bccb4f6a0bf368cd25ad9bcdcc1990b64a647e7bbcce9cb5b"}, {file = "Brotli-1.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:224e57f6eac61cc449f498cc5f0e1725ba2071a3d4f48d5d9dffba42db196438"}, + {file = "Brotli-1.1.0-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:cb1dac1770878ade83f2ccdf7d25e494f05c9165f5246b46a621cc849341dc01"}, + {file = "Brotli-1.1.0-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:3ee8a80d67a4334482d9712b8e83ca6b1d9bc7e351931252ebef5d8f7335a547"}, + {file = "Brotli-1.1.0-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:5e55da2c8724191e5b557f8e18943b1b4839b8efc3ef60d65985bcf6f587dd38"}, + {file = "Brotli-1.1.0-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:d342778ef319e1026af243ed0a07c97acf3bad33b9f29e7ae6a1f68fd083e90c"}, {file = "Brotli-1.1.0-cp37-cp37m-win32.whl", hash = "sha256:587ca6d3cef6e4e868102672d3bd9dc9698c309ba56d41c2b9c85bbb903cdb95"}, {file = "Brotli-1.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:2954c1c23f81c2eaf0b0717d9380bd348578a94161a65b3a2afc62c86467dd68"}, {file = "Brotli-1.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:efa8b278894b14d6da122a72fefcebc28445f2d3f880ac59d46c90f4c13be9a3"}, @@ -130,6 +204,10 @@ files = [ {file = "Brotli-1.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1ab4fbee0b2d9098c74f3057b2bc055a8bd92ccf02f65944a241b4349229185a"}, {file = "Brotli-1.1.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:141bd4d93984070e097521ed07e2575b46f817d08f9fa42b16b9b5f27b5ac088"}, {file = "Brotli-1.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:fce1473f3ccc4187f75b4690cfc922628aed4d3dd013d047f95a9b3919a86596"}, + {file = "Brotli-1.1.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:d2b35ca2c7f81d173d2fadc2f4f31e88cc5f7a39ae5b6db5513cf3383b0e0ec7"}, + {file = "Brotli-1.1.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:af6fa6817889314555aede9a919612b23739395ce767fe7fcbea9a80bf140fe5"}, + {file = "Brotli-1.1.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:2feb1d960f760a575dbc5ab3b1c00504b24caaf6986e2dc2b01c09c87866a943"}, + {file = "Brotli-1.1.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:4410f84b33374409552ac9b6903507cdb31cd30d2501fc5ca13d18f73548444a"}, {file = "Brotli-1.1.0-cp38-cp38-win32.whl", hash = "sha256:db85ecf4e609a48f4b29055f1e144231b90edc90af7481aa731ba2d059226b1b"}, {file = "Brotli-1.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:3d7954194c36e304e1523f55d7042c59dc53ec20dd4e9ea9d151f1b62b4415c0"}, {file = "Brotli-1.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5fb2ce4b8045c78ebbc7b8f3c15062e435d47e7393cc57c25115cfd49883747a"}, @@ -142,6 +220,10 @@ files = [ {file = "Brotli-1.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:949f3b7c29912693cee0afcf09acd6ebc04c57af949d9bf77d6101ebb61e388c"}, {file = "Brotli-1.1.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:89f4988c7203739d48c6f806f1e87a1d96e0806d44f0fba61dba81392c9e474d"}, {file = "Brotli-1.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:de6551e370ef19f8de1807d0a9aa2cdfdce2e85ce88b122fe9f6b2b076837e59"}, + {file = "Brotli-1.1.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:0737ddb3068957cf1b054899b0883830bb1fec522ec76b1098f9b6e0f02d9419"}, + {file = "Brotli-1.1.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:4f3607b129417e111e30637af1b56f24f7a49e64763253bbc275c75fa887d4b2"}, + {file = "Brotli-1.1.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:6c6e0c425f22c1c719c42670d561ad682f7bfeeef918edea971a79ac5252437f"}, + {file = "Brotli-1.1.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:494994f807ba0b92092a163a0a283961369a65f6cbe01e8891132b7a320e61eb"}, {file = "Brotli-1.1.0-cp39-cp39-win32.whl", hash = "sha256:f0d8a7a6b5983c2496e364b969f0e526647a06b075d034f3297dc66f3b360c64"}, {file = "Brotli-1.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:cdad5b9014d83ca68c25d2e9444e28e967ef16e80f6b436918c700c117a85467"}, {file = "Brotli-1.1.0.tar.gz", hash = "sha256:81de08ac11bcb85841e440c13611c00b67d3bf82698314928d0b676362546724"}, @@ -167,6 +249,255 @@ starlette = ">=0.25.0" test-brotli = ["mypy (>=0.770)", "requests (>=2.23.0)"] test-brotlipy = ["brotlipy (>=0.7.0)", "mypy (>=0.770)", "requests (>=2.23.0)"] +[[package]] +name = "certifi" +version = "2026.6.17" +description = "Python package for providing Mozilla's CA Bundle." +optional = false +python-versions = ">=3.7" +groups = ["ceda", "globus", "test"] +files = [ + {file = "certifi-2026.6.17-py3-none-any.whl", hash = "sha256:2227dcbaafe0d2f59279d1762ddddc37783ed4354594f194ffc31d20f41fc3db"}, + {file = "certifi-2026.6.17.tar.gz", hash = "sha256:024c88eeec92ca068db80f02b8b07c9cef7b9fe261d1d535abfd5abd6f6af432"}, +] + +[[package]] +name = "cffi" +version = "2.0.0" +description = "Foreign Function Interface for Python calling C code." +optional = false +python-versions = ">=3.9" +groups = ["globus"] +markers = "platform_python_implementation != \"PyPy\"" +files = [ + {file = "cffi-2.0.0-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:0cf2d91ecc3fcc0625c2c530fe004f82c110405f101548512cce44322fa8ac44"}, + {file = "cffi-2.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f73b96c41e3b2adedc34a7356e64c8eb96e03a3782b535e043a986276ce12a49"}, + {file = "cffi-2.0.0-cp310-cp310-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:53f77cbe57044e88bbd5ed26ac1d0514d2acf0591dd6bb02a3ae37f76811b80c"}, + {file = "cffi-2.0.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3e837e369566884707ddaf85fc1744b47575005c0a229de3327f8f9a20f4efeb"}, + {file = "cffi-2.0.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:5eda85d6d1879e692d546a078b44251cdd08dd1cfb98dfb77b670c97cee49ea0"}, + {file = "cffi-2.0.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:9332088d75dc3241c702d852d4671613136d90fa6881da7d770a483fd05248b4"}, + {file = "cffi-2.0.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fc7de24befaeae77ba923797c7c87834c73648a05a4bde34b3b7e5588973a453"}, + {file = "cffi-2.0.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:cf364028c016c03078a23b503f02058f1814320a56ad535686f90565636a9495"}, + {file = "cffi-2.0.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e11e82b744887154b182fd3e7e8512418446501191994dbf9c9fc1f32cc8efd5"}, + {file = "cffi-2.0.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8ea985900c5c95ce9db1745f7933eeef5d314f0565b27625d9a10ec9881e1bfb"}, + {file = "cffi-2.0.0-cp310-cp310-win32.whl", hash = "sha256:1f72fb8906754ac8a2cc3f9f5aaa298070652a0ffae577e0ea9bd480dc3c931a"}, + {file = "cffi-2.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:b18a3ed7d5b3bd8d9ef7a8cb226502c6bf8308df1525e1cc676c3680e7176739"}, + {file = "cffi-2.0.0-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:b4c854ef3adc177950a8dfc81a86f5115d2abd545751a304c5bcf2c2c7283cfe"}, + {file = "cffi-2.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2de9a304e27f7596cd03d16f1b7c72219bd944e99cc52b84d0145aefb07cbd3c"}, + {file = "cffi-2.0.0-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:baf5215e0ab74c16e2dd324e8ec067ef59e41125d3eade2b863d294fd5035c92"}, + {file = "cffi-2.0.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:730cacb21e1bdff3ce90babf007d0a0917cc3e6492f336c2f0134101e0944f93"}, + {file = "cffi-2.0.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:6824f87845e3396029f3820c206e459ccc91760e8fa24422f8b0c3d1731cbec5"}, + {file = "cffi-2.0.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:9de40a7b0323d889cf8d23d1ef214f565ab154443c42737dfe52ff82cf857664"}, + {file = "cffi-2.0.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8941aaadaf67246224cee8c3803777eed332a19d909b47e29c9842ef1e79ac26"}, + {file = "cffi-2.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a05d0c237b3349096d3981b727493e22147f934b20f6f125a3eba8f994bec4a9"}, + {file = "cffi-2.0.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:94698a9c5f91f9d138526b48fe26a199609544591f859c870d477351dc7b2414"}, + {file = "cffi-2.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:5fed36fccc0612a53f1d4d9a816b50a36702c28a2aa880cb8a122b3466638743"}, + {file = "cffi-2.0.0-cp311-cp311-win32.whl", hash = "sha256:c649e3a33450ec82378822b3dad03cc228b8f5963c0c12fc3b1e0ab940f768a5"}, + {file = "cffi-2.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:66f011380d0e49ed280c789fbd08ff0d40968ee7b665575489afa95c98196ab5"}, + {file = "cffi-2.0.0-cp311-cp311-win_arm64.whl", hash = "sha256:c6638687455baf640e37344fe26d37c404db8b80d037c3d29f58fe8d1c3b194d"}, + {file = "cffi-2.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6d02d6655b0e54f54c4ef0b94eb6be0607b70853c45ce98bd278dc7de718be5d"}, + {file = "cffi-2.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8eca2a813c1cb7ad4fb74d368c2ffbbb4789d377ee5bb8df98373c2cc0dee76c"}, + {file = "cffi-2.0.0-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:21d1152871b019407d8ac3985f6775c079416c282e431a4da6afe7aefd2bccbe"}, + {file = "cffi-2.0.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b21e08af67b8a103c71a250401c78d5e0893beff75e28c53c98f4de42f774062"}, + {file = "cffi-2.0.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:1e3a615586f05fc4065a8b22b8152f0c1b00cdbc60596d187c2a74f9e3036e4e"}, + {file = "cffi-2.0.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:81afed14892743bbe14dacb9e36d9e0e504cd204e0b165062c488942b9718037"}, + {file = "cffi-2.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3e17ed538242334bf70832644a32a7aae3d83b57567f9fd60a26257e992b79ba"}, + {file = "cffi-2.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3925dd22fa2b7699ed2617149842d2e6adde22b262fcbfada50e3d195e4b3a94"}, + {file = "cffi-2.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2c8f814d84194c9ea681642fd164267891702542f028a15fc97d4674b6206187"}, + {file = "cffi-2.0.0-cp312-cp312-win32.whl", hash = "sha256:da902562c3e9c550df360bfa53c035b2f241fed6d9aef119048073680ace4a18"}, + {file = "cffi-2.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:da68248800ad6320861f129cd9c1bf96ca849a2771a59e0344e88681905916f5"}, + {file = "cffi-2.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:4671d9dd5ec934cb9a73e7ee9676f9362aba54f7f34910956b84d727b0d73fb6"}, + {file = "cffi-2.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:00bdf7acc5f795150faa6957054fbbca2439db2f775ce831222b66f192f03beb"}, + {file = "cffi-2.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:45d5e886156860dc35862657e1494b9bae8dfa63bf56796f2fb56e1679fc0bca"}, + {file = "cffi-2.0.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:07b271772c100085dd28b74fa0cd81c8fb1a3ba18b21e03d7c27f3436a10606b"}, + {file = "cffi-2.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d48a880098c96020b02d5a1f7d9251308510ce8858940e6fa99ece33f610838b"}, + {file = "cffi-2.0.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:f93fd8e5c8c0a4aa1f424d6173f14a892044054871c771f8566e4008eaa359d2"}, + {file = "cffi-2.0.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:dd4f05f54a52fb558f1ba9f528228066954fee3ebe629fc1660d874d040ae5a3"}, + {file = "cffi-2.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c8d3b5532fc71b7a77c09192b4a5a200ea992702734a2e9279a37f2478236f26"}, + {file = "cffi-2.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d9b29c1f0ae438d5ee9acb31cadee00a58c46cc9c0b2f9038c6b0b3470877a8c"}, + {file = "cffi-2.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6d50360be4546678fc1b79ffe7a66265e28667840010348dd69a314145807a1b"}, + {file = "cffi-2.0.0-cp313-cp313-win32.whl", hash = "sha256:74a03b9698e198d47562765773b4a8309919089150a0bb17d829ad7b44b60d27"}, + {file = "cffi-2.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:19f705ada2530c1167abacb171925dd886168931e0a7b78f5bffcae5c6b5be75"}, + {file = "cffi-2.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:256f80b80ca3853f90c21b23ee78cd008713787b1b1e93eae9f3d6a7134abd91"}, + {file = "cffi-2.0.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:fc33c5141b55ed366cfaad382df24fe7dcbc686de5be719b207bb248e3053dc5"}, + {file = "cffi-2.0.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c654de545946e0db659b3400168c9ad31b5d29593291482c43e3564effbcee13"}, + {file = "cffi-2.0.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:24b6f81f1983e6df8db3adc38562c83f7d4a0c36162885ec7f7b77c7dcbec97b"}, + {file = "cffi-2.0.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:12873ca6cb9b0f0d3a0da705d6086fe911591737a59f28b7936bdfed27c0d47c"}, + {file = "cffi-2.0.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:d9b97165e8aed9272a6bb17c01e3cc5871a594a446ebedc996e2397a1c1ea8ef"}, + {file = "cffi-2.0.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:afb8db5439b81cf9c9d0c80404b60c3cc9c3add93e114dcae767f1477cb53775"}, + {file = "cffi-2.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:737fe7d37e1a1bffe70bd5754ea763a62a066dc5913ca57e957824b72a85e205"}, + {file = "cffi-2.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:38100abb9d1b1435bc4cc340bb4489635dc2f0da7456590877030c9b3d40b0c1"}, + {file = "cffi-2.0.0-cp314-cp314-win32.whl", hash = "sha256:087067fa8953339c723661eda6b54bc98c5625757ea62e95eb4898ad5e776e9f"}, + {file = "cffi-2.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:203a48d1fb583fc7d78a4c6655692963b860a417c0528492a6bc21f1aaefab25"}, + {file = "cffi-2.0.0-cp314-cp314-win_arm64.whl", hash = "sha256:dbd5c7a25a7cb98f5ca55d258b103a2054f859a46ae11aaf23134f9cc0d356ad"}, + {file = "cffi-2.0.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:9a67fc9e8eb39039280526379fb3a70023d77caec1852002b4da7e8b270c4dd9"}, + {file = "cffi-2.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7a66c7204d8869299919db4d5069a82f1561581af12b11b3c9f48c584eb8743d"}, + {file = "cffi-2.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7cc09976e8b56f8cebd752f7113ad07752461f48a58cbba644139015ac24954c"}, + {file = "cffi-2.0.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:92b68146a71df78564e4ef48af17551a5ddd142e5190cdf2c5624d0c3ff5b2e8"}, + {file = "cffi-2.0.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:b1e74d11748e7e98e2f426ab176d4ed720a64412b6a15054378afdb71e0f37dc"}, + {file = "cffi-2.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:28a3a209b96630bca57cce802da70c266eb08c6e97e5afd61a75611ee6c64592"}, + {file = "cffi-2.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:7553fb2090d71822f02c629afe6042c299edf91ba1bf94951165613553984512"}, + {file = "cffi-2.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6c6c373cfc5c83a975506110d17457138c8c63016b563cc9ed6e056a82f13ce4"}, + {file = "cffi-2.0.0-cp314-cp314t-win32.whl", hash = "sha256:1fc9ea04857caf665289b7a75923f2c6ed559b8298a1b8c49e59f7dd95c8481e"}, + {file = "cffi-2.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:d68b6cef7827e8641e8ef16f4494edda8b36104d79773a334beaa1e3521430f6"}, + {file = "cffi-2.0.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0a1527a803f0a659de1af2e1fd700213caba79377e27e4693648c2923da066f9"}, + {file = "cffi-2.0.0-cp39-cp39-macosx_10_13_x86_64.whl", hash = "sha256:fe562eb1a64e67dd297ccc4f5addea2501664954f2692b69a76449ec7913ecbf"}, + {file = "cffi-2.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:de8dad4425a6ca6e4e5e297b27b5c824ecc7581910bf9aee86cb6835e6812aa7"}, + {file = "cffi-2.0.0-cp39-cp39-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:4647afc2f90d1ddd33441e5b0e85b16b12ddec4fca55f0d9671fef036ecca27c"}, + {file = "cffi-2.0.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3f4d46d8b35698056ec29bca21546e1551a205058ae1a181d871e278b0b28165"}, + {file = "cffi-2.0.0-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:e6e73b9e02893c764e7e8d5bb5ce277f1a009cd5243f8228f75f842bf937c534"}, + {file = "cffi-2.0.0-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:cb527a79772e5ef98fb1d700678fe031e353e765d1ca2d409c92263c6d43e09f"}, + {file = "cffi-2.0.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:61d028e90346df14fedc3d1e5441df818d095f3b87d286825dfcbd6459b7ef63"}, + {file = "cffi-2.0.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:0f6084a0ea23d05d20c3edcda20c3d006f9b6f3fefeac38f59262e10cef47ee2"}, + {file = "cffi-2.0.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:1cd13c99ce269b3ed80b417dcd591415d3372bcac067009b6e0f59c7d4015e65"}, + {file = "cffi-2.0.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:89472c9762729b5ae1ad974b777416bfda4ac5642423fa93bd57a09204712322"}, + {file = "cffi-2.0.0-cp39-cp39-win32.whl", hash = "sha256:2081580ebb843f759b9f617314a24ed5738c51d2aee65d31e02f6f7a2b97707a"}, + {file = "cffi-2.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:b882b3df248017dba09d6b16defe9b5c407fe32fc7c65a9c69798e6175601be9"}, + {file = "cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529"}, +] + +[package.dependencies] +pycparser = {version = "*", markers = "implementation_name != \"PyPy\""} + +[[package]] +name = "charset-normalizer" +version = "3.4.7" +description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +optional = false +python-versions = ">=3.7" +groups = ["globus"] +files = [ + {file = "charset_normalizer-3.4.7-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cdd68a1fb318e290a2077696b7eb7a21a49163c455979c639bf5a5dcdc46617d"}, + {file = "charset_normalizer-3.4.7-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e17b8d5d6a8c47c85e68ca8379def1303fd360c3e22093a807cd34a71cd082b8"}, + {file = "charset_normalizer-3.4.7-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:511ef87c8aec0783e08ac18565a16d435372bc1ac25a91e6ac7f5ef2b0bff790"}, + {file = "charset_normalizer-3.4.7-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:007d05ec7321d12a40227aae9e2bc6dca73f3cb21058999a1df9e193555a9dcc"}, + {file = "charset_normalizer-3.4.7-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cf29836da5119f3c8a8a70667b0ef5fdca3bb12f80fd06487cfa575b3909b393"}, + {file = "charset_normalizer-3.4.7-cp310-cp310-manylinux_2_31_armv7l.whl", hash = "sha256:12d8baf840cc7889b37c7c770f478adea7adce3dcb3944d02ec87508e2dcf153"}, + {file = "charset_normalizer-3.4.7-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d560742f3c0d62afaccf9f41fe485ed69bd7661a241f86a3ef0f0fb8b1a397af"}, + {file = "charset_normalizer-3.4.7-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:b14b2d9dac08e28bb8046a1a0434b1750eb221c8f5b87a68f4fa11a6f97b5e34"}, + {file = "charset_normalizer-3.4.7-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:bc17a677b21b3502a21f66a8cc64f5bfad4df8a0b8434d661666f8ce90ac3af1"}, + {file = "charset_normalizer-3.4.7-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:750e02e074872a3fad7f233b47734166440af3cdea0add3e95163110816d6752"}, + {file = "charset_normalizer-3.4.7-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:4e5163c14bffd570ef2affbfdd77bba66383890797df43dc8b4cc7d6f500bf53"}, + {file = "charset_normalizer-3.4.7-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:6ed74185b2db44f41ef35fd1617c5888e59792da9bbc9190d6c7300617182616"}, + {file = "charset_normalizer-3.4.7-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:94e1885b270625a9a828c9793b4d52a64445299baa1fea5a173bf1d3dd9a1a5a"}, + {file = "charset_normalizer-3.4.7-cp310-cp310-win32.whl", hash = "sha256:6785f414ae0f3c733c437e0f3929197934f526d19dfaa75e18fdb4f94c6fb374"}, + {file = "charset_normalizer-3.4.7-cp310-cp310-win_amd64.whl", hash = "sha256:6696b7688f54f5af4462118f0bfa7c1621eeb87154f77fa04b9295ce7a8f2943"}, + {file = "charset_normalizer-3.4.7-cp310-cp310-win_arm64.whl", hash = "sha256:66671f93accb62ed07da56613636f3641f1a12c13046ce91ffc923721f23c008"}, + {file = "charset_normalizer-3.4.7-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7641bb8895e77f921102f72833904dcd9901df5d6d72a2ab8f31d04b7e51e4e7"}, + {file = "charset_normalizer-3.4.7-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:202389074300232baeb53ae2569a60901f7efadd4245cf3a3bf0617d60b439d7"}, + {file = "charset_normalizer-3.4.7-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:30b8d1d8c52a48c2c5690e152c169b673487a2a58de1ec7393196753063fcd5e"}, + {file = "charset_normalizer-3.4.7-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:532bc9bf33a68613fd7d65e4b1c71a6a38d7d42604ecf239c77392e9b4e8998c"}, + {file = "charset_normalizer-3.4.7-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2fe249cb4651fd12605b7288b24751d8bfd46d35f12a20b1ba33dea122e690df"}, + {file = "charset_normalizer-3.4.7-cp311-cp311-manylinux_2_31_armv7l.whl", hash = "sha256:65bcd23054beab4d166035cabbc868a09c1a49d1efe458fe8e4361215df40265"}, + {file = "charset_normalizer-3.4.7-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:08e721811161356f97b4059a9ba7bafb23ea5ee2255402c42881c214e173c6b4"}, + {file = "charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e060d01aec0a910bdccb8be71faf34e7799ce36950f8294c8bf612cba65a2c9e"}, + {file = "charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:38c0109396c4cfc574d502df99742a45c72c08eff0a36158b6f04000043dbf38"}, + {file = "charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:1c2a768fdd44ee4a9339a9b0b130049139b8ce3c01d2ce09f67f5a68048d477c"}, + {file = "charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:1a87ca9d5df6fe460483d9a5bbf2b18f620cbed41b432e2bddb686228282d10b"}, + {file = "charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:d635aab80466bc95771bb78d5370e74d36d1fe31467b6b29b8b57b2a3cd7d22c"}, + {file = "charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ae196f021b5e7c78e918242d217db021ed2a6ace2bc6ae94c0fc596221c7f58d"}, + {file = "charset_normalizer-3.4.7-cp311-cp311-win32.whl", hash = "sha256:adb2597b428735679446b46c8badf467b4ca5f5056aae4d51a19f9570301b1ad"}, + {file = "charset_normalizer-3.4.7-cp311-cp311-win_amd64.whl", hash = "sha256:8e385e4267ab76874ae30db04c627faaaf0b509e1ccc11a95b3fc3e83f855c00"}, + {file = "charset_normalizer-3.4.7-cp311-cp311-win_arm64.whl", hash = "sha256:d4a48e5b3c2a489fae013b7589308a40146ee081f6f509e047e0e096084ceca1"}, + {file = "charset_normalizer-3.4.7-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:eca9705049ad3c7345d574e3510665cb2cf844c2f2dcfe675332677f081cbd46"}, + {file = "charset_normalizer-3.4.7-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6178f72c5508bfc5fd446a5905e698c6212932f25bcdd4b47a757a50605a90e2"}, + {file = "charset_normalizer-3.4.7-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e1421b502d83040e6d7fb2fb18dff63957f720da3d77b2fbd3187ceb63755d7b"}, + {file = "charset_normalizer-3.4.7-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:edac0f1ab77644605be2cbba52e6b7f630731fc42b34cb0f634be1a6eface56a"}, + {file = "charset_normalizer-3.4.7-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5649fd1c7bade02f320a462fdefd0b4bd3ce036065836d4f42e0de958038e116"}, + {file = "charset_normalizer-3.4.7-cp312-cp312-manylinux_2_31_armv7l.whl", hash = "sha256:203104ed3e428044fd943bc4bf45fa73c0730391f9621e37fe39ecf477b128cb"}, + {file = "charset_normalizer-3.4.7-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:298930cec56029e05497a76988377cbd7457ba864beeea92ad7e844fe74cd1f1"}, + {file = "charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:708838739abf24b2ceb208d0e22403dd018faeef86ddac04319a62ae884c4f15"}, + {file = "charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:0f7eb884681e3938906ed0434f20c63046eacd0111c4ba96f27b76084cd679f5"}, + {file = "charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:4dc1e73c36828f982bfe79fadf5919923f8a6f4df2860804db9a98c48824ce8d"}, + {file = "charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:aed52fea0513bac0ccde438c188c8a471c4e0f457c2dd20cdbf6ea7a450046c7"}, + {file = "charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:fea24543955a6a729c45a73fe90e08c743f0b3334bbf3201e6c4bc1b0c7fa464"}, + {file = "charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:bb6d88045545b26da47aa879dd4a89a71d1dce0f0e549b1abcb31dfe4a8eac49"}, + {file = "charset_normalizer-3.4.7-cp312-cp312-win32.whl", hash = "sha256:2257141f39fe65a3fdf38aeccae4b953e5f3b3324f4ff0daf9f15b8518666a2c"}, + {file = "charset_normalizer-3.4.7-cp312-cp312-win_amd64.whl", hash = "sha256:5ed6ab538499c8644b8a3e18debabcd7ce684f3fa91cf867521a7a0279cab2d6"}, + {file = "charset_normalizer-3.4.7-cp312-cp312-win_arm64.whl", hash = "sha256:56be790f86bfb2c98fb742ce566dfb4816e5a83384616ab59c49e0604d49c51d"}, + {file = "charset_normalizer-3.4.7-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:f496c9c3cc02230093d8330875c4c3cdfc3b73612a5fd921c65d39cbcef08063"}, + {file = "charset_normalizer-3.4.7-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0ea948db76d31190bf08bd371623927ee1339d5f2a0b4b1b4a4439a65298703c"}, + {file = "charset_normalizer-3.4.7-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a277ab8928b9f299723bc1a2dabb1265911b1a76341f90a510368ca44ad9ab66"}, + {file = "charset_normalizer-3.4.7-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3bec022aec2c514d9cf199522a802bd007cd588ab17ab2525f20f9c34d067c18"}, + {file = "charset_normalizer-3.4.7-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e044c39e41b92c845bc815e5ae4230804e8e7bc29e399b0437d64222d92809dd"}, + {file = "charset_normalizer-3.4.7-cp313-cp313-manylinux_2_31_armv7l.whl", hash = "sha256:f495a1652cf3fbab2eb0639776dad966c2fb874d79d87ca07f9d5f059b8bd215"}, + {file = "charset_normalizer-3.4.7-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e712b419df8ba5e42b226c510472b37bd57b38e897d3eca5e8cfd410a29fa859"}, + {file = "charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7804338df6fcc08105c7745f1502ba68d900f45fd770d5bdd5288ddccb8a42d8"}, + {file = "charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:481551899c856c704d58119b5025793fa6730adda3571971af568f66d2424bb5"}, + {file = "charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:f59099f9b66f0d7145115e6f80dd8b1d847176df89b234a5a6b3f00437aa0832"}, + {file = "charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:f59ad4c0e8f6bba240a9bb85504faa1ab438237199d4cce5f622761507b8f6a6"}, + {file = "charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:3dedcc22d73ec993f42055eff4fcfed9318d1eeb9a6606c55892a26964964e48"}, + {file = "charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:64f02c6841d7d83f832cd97ccf8eb8a906d06eb95d5276069175c696b024b60a"}, + {file = "charset_normalizer-3.4.7-cp313-cp313-win32.whl", hash = "sha256:4042d5c8f957e15221d423ba781e85d553722fc4113f523f2feb7b188cc34c5e"}, + {file = "charset_normalizer-3.4.7-cp313-cp313-win_amd64.whl", hash = "sha256:3946fa46a0cf3e4c8cb1cc52f56bb536310d34f25f01ca9b6c16afa767dab110"}, + {file = "charset_normalizer-3.4.7-cp313-cp313-win_arm64.whl", hash = "sha256:80d04837f55fc81da168b98de4f4b797ef007fc8a79ab71c6ec9bc4dd662b15b"}, + {file = "charset_normalizer-3.4.7-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:c36c333c39be2dbca264d7803333c896ab8fa7d4d6f0ab7edb7dfd7aea6e98c0"}, + {file = "charset_normalizer-3.4.7-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1c2aed2e5e41f24ea8ef1590b8e848a79b56f3a5564a65ceec43c9d692dc7d8a"}, + {file = "charset_normalizer-3.4.7-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:54523e136b8948060c0fa0bc7b1b50c32c186f2fceee897a495406bb6e311d2b"}, + {file = "charset_normalizer-3.4.7-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:715479b9a2802ecac752a3b0efa2b0b60285cf962ee38414211abdfccc233b41"}, + {file = "charset_normalizer-3.4.7-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bd6c2a1c7573c64738d716488d2cdd3c00e340e4835707d8fdb8dc1a66ef164e"}, + {file = "charset_normalizer-3.4.7-cp314-cp314-manylinux_2_31_armv7l.whl", hash = "sha256:c45e9440fb78f8ddabcf714b68f936737a121355bf59f3907f4e17721b9d1aae"}, + {file = "charset_normalizer-3.4.7-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3534e7dcbdcf757da6b85a0bbf5b6868786d5982dd959b065e65481644817a18"}, + {file = "charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:e8ac484bf18ce6975760921bb6148041faa8fef0547200386ea0b52b5d27bf7b"}, + {file = "charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:a5fe03b42827c13cdccd08e6c0247b6a6d4b5e3cdc53fd1749f5896adcdc2356"}, + {file = "charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:2d6eb928e13016cea4f1f21d1e10c1cebd5a421bc57ddf5b1142ae3f86824fab"}, + {file = "charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:e74327fb75de8986940def6e8dee4f127cc9752bee7355bb323cc5b2659b6d46"}, + {file = "charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:d6038d37043bced98a66e68d3aa2b6a35505dc01328cd65217cefe82f25def44"}, + {file = "charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:7579e913a5339fb8fa133f6bbcfd8e6749696206cf05acdbdca71a1b436d8e72"}, + {file = "charset_normalizer-3.4.7-cp314-cp314-win32.whl", hash = "sha256:5b77459df20e08151cd6f8b9ef8ef1f961ef73d85c21a555c7eed5b79410ec10"}, + {file = "charset_normalizer-3.4.7-cp314-cp314-win_amd64.whl", hash = "sha256:92a0a01ead5e668468e952e4238cccd7c537364eb7d851ab144ab6627dbbe12f"}, + {file = "charset_normalizer-3.4.7-cp314-cp314-win_arm64.whl", hash = "sha256:67f6279d125ca0046a7fd386d01b311c6363844deac3e5b069b514ba3e63c246"}, + {file = "charset_normalizer-3.4.7-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:effc3f449787117233702311a1b7d8f59cba9ced946ba727bdc329ec69028e24"}, + {file = "charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fbccdc05410c9ee21bbf16a35f4c1d16123dcdeb8a1d38f33654fa21d0234f79"}, + {file = "charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:733784b6d6def852c814bce5f318d25da2ee65dd4839a0718641c696e09a2960"}, + {file = "charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a89c23ef8d2c6b27fd200a42aa4ac72786e7c60d40efdc76e6011260b6e949c4"}, + {file = "charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6c114670c45346afedc0d947faf3c7f701051d2518b943679c8ff88befe14f8e"}, + {file = "charset_normalizer-3.4.7-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:a180c5e59792af262bf263b21a3c49353f25945d8d9f70628e73de370d55e1e1"}, + {file = "charset_normalizer-3.4.7-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3c9a494bc5ec77d43cea229c4f6db1e4d8fe7e1bbffa8b6f0f0032430ff8ab44"}, + {file = "charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8d828b6667a32a728a1ad1d93957cdf37489c57b97ae6c4de2860fa749b8fc1e"}, + {file = "charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:cf1493cd8607bec4d8a7b9b004e699fcf8f9103a9284cc94962cb73d20f9d4a3"}, + {file = "charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:0c96c3b819b5c3e9e165495db84d41914d6894d55181d2d108cc1a69bfc9cce0"}, + {file = "charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:752a45dc4a6934060b3b0dab47e04edc3326575f82be64bc4fc293914566503e"}, + {file = "charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:8778f0c7a52e56f75d12dae53ae320fae900a8b9b4164b981b9c5ce059cd1fcb"}, + {file = "charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ce3412fbe1e31eb81ea42f4169ed94861c56e643189e1e75f0041f3fe7020abe"}, + {file = "charset_normalizer-3.4.7-cp314-cp314t-win32.whl", hash = "sha256:c03a41a8784091e67a39648f70c5f97b5b6a37f216896d44d2cdcb82615339a0"}, + {file = "charset_normalizer-3.4.7-cp314-cp314t-win_amd64.whl", hash = "sha256:03853ed82eeebbce3c2abfdbc98c96dc205f32a79627688ac9a27370ea61a49c"}, + {file = "charset_normalizer-3.4.7-cp314-cp314t-win_arm64.whl", hash = "sha256:c35abb8bfff0185efac5878da64c45dafd2b37fb0383add1be155a763c1f083d"}, + {file = "charset_normalizer-3.4.7-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e5f4d355f0a2b1a31bc3edec6795b46324349c9cb25eed068049e4f472fb4259"}, + {file = "charset_normalizer-3.4.7-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:16d971e29578a5e97d7117866d15889a4a07befe0e87e703ed63cd90cb348c01"}, + {file = "charset_normalizer-3.4.7-cp38-cp38-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:dca4bbc466a95ba9c0234ef56d7dd9509f63da22274589ebd4ed7f1f4d4c54e3"}, + {file = "charset_normalizer-3.4.7-cp38-cp38-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e80c8378d8f3d83cd3164da1ad2df9e37a666cdde7b1cb2298ed0b558064be30"}, + {file = "charset_normalizer-3.4.7-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:36836d6ff945a00b88ba1e4572d721e60b5b8c98c155d465f56ad19d68f23734"}, + {file = "charset_normalizer-3.4.7-cp38-cp38-manylinux_2_31_armv7l.whl", hash = "sha256:bd9b23791fe793e4968dba0c447e12f78e425c59fc0e3b97f6450f4781f3ee60"}, + {file = "charset_normalizer-3.4.7-cp38-cp38-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:aef65cd602a6d0e0ff6f9930fcb1c8fec60dd2cfcb6facaf4bdb0e5873042db0"}, + {file = "charset_normalizer-3.4.7-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:82b271f5137d07749f7bf32f70b17ab6eaabedd297e75dce75081a24f76eb545"}, + {file = "charset_normalizer-3.4.7-cp38-cp38-musllinux_1_2_armv7l.whl", hash = "sha256:1efde3cae86c8c273f1eb3b287be7d8499420cf2fe7585c41d370d3e790054a5"}, + {file = "charset_normalizer-3.4.7-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:c593052c465475e64bbfe5dbd81680f64a67fdc752c56d7a0ae205dc8aeefe0f"}, + {file = "charset_normalizer-3.4.7-cp38-cp38-musllinux_1_2_riscv64.whl", hash = "sha256:af21eb4409a119e365397b2adbaca4c9ccab56543a65d5dbd9f920d6ac29f686"}, + {file = "charset_normalizer-3.4.7-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:84c018e49c3bf790f9c2771c45e9313a08c2c2a6342b162cd650258b57817706"}, + {file = "charset_normalizer-3.4.7-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:dd915403e231e6b1809fe9b6d9fc55cf8fb5e02765ac625d9cd623342a7905d7"}, + {file = "charset_normalizer-3.4.7-cp38-cp38-win32.whl", hash = "sha256:320ade88cfb846b8cd6b4ddf5ee9e80ee0c1f52401f2456b84ae1ae6a1a5f207"}, + {file = "charset_normalizer-3.4.7-cp38-cp38-win_amd64.whl", hash = "sha256:1dc8b0ea451d6e69735094606991f32867807881400f808a106ee1d963c46a83"}, + {file = "charset_normalizer-3.4.7-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:177a0ba5f0211d488e295aaf82707237e331c24788d8d76c96c5a41594723217"}, + {file = "charset_normalizer-3.4.7-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6e0d51f618228538a3e8f46bd246f87a6cd030565e015803691603f55e12afb5"}, + {file = "charset_normalizer-3.4.7-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:14265bfe1f09498b9d8ec91e9ec9fa52775edf90fcbde092b25f4a33d444fea9"}, + {file = "charset_normalizer-3.4.7-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:87fad7d9ba98c86bcb41b2dc8dbb326619be2562af1f8ff50776a39e55721c5a"}, + {file = "charset_normalizer-3.4.7-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f22dec1690b584cea26fade98b2435c132c1b5f68e39f5a0b7627cd7ae31f1dc"}, + {file = "charset_normalizer-3.4.7-cp39-cp39-manylinux_2_31_armv7l.whl", hash = "sha256:d61f00a0869d77422d9b2aba989e2d24afa6ffd552af442e0e58de4f35ea6d00"}, + {file = "charset_normalizer-3.4.7-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:6370e8686f662e6a3941ee48ed4742317cafbe5707e36406e9df792cdb535776"}, + {file = "charset_normalizer-3.4.7-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:a6c5863edfbe888d9eff9c8b8087354e27618d9da76425c119293f11712a6319"}, + {file = "charset_normalizer-3.4.7-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:ed065083d0898c9d5b4bbec7b026fd755ff7454e6e8b73a67f8c744b13986e24"}, + {file = "charset_normalizer-3.4.7-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:2cd4a60d0e2fb04537162c62bbbb4182f53541fe0ede35cdf270a1c1e723cc42"}, + {file = "charset_normalizer-3.4.7-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:813c0e0132266c08eb87469a642cb30aaff57c5f426255419572aaeceeaa7bf4"}, + {file = "charset_normalizer-3.4.7-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:07d9e39b01743c3717745f4c530a6349eadbfa043c7577eef86c502c15df2c67"}, + {file = "charset_normalizer-3.4.7-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c0f081d69a6e58272819b70288d3221a6ee64b98df852631c80f293514d3b274"}, + {file = "charset_normalizer-3.4.7-cp39-cp39-win32.whl", hash = "sha256:8751d2787c9131302398b11e6c8068053dcb55d5a8964e114b6e196cf16cb366"}, + {file = "charset_normalizer-3.4.7-cp39-cp39-win_amd64.whl", hash = "sha256:12a6fff75f6bc66711b73a2f0addfc4c8c15a20e805146a02d147a318962c444"}, + {file = "charset_normalizer-3.4.7-cp39-cp39-win_arm64.whl", hash = "sha256:bb8cc7534f51d9a017b93e3e85b260924f909601c3df002bcdb58ddb4dc41a5c"}, + {file = "charset_normalizer-3.4.7-py3-none-any.whl", hash = "sha256:3dce51d0f5e7951f8bb4900c257dad282f49190fdbebecd4ba99bcc41fef404d"}, + {file = "charset_normalizer-3.4.7.tar.gz", hash = "sha256:ae89db9e5f98a11a4bf50407d4363e7b09b31e55bc117b4f7d80aab97ba009e5"}, +] + [[package]] name = "click" version = "8.1.8" @@ -188,12 +519,12 @@ version = "0.4.6" description = "Cross-platform colored terminal text." optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" -groups = ["main"] -markers = "platform_system == \"Windows\"" +groups = ["main", "test"] files = [ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] +markers = {main = "platform_system == \"Windows\"", test = "sys_platform == \"win32\""} [[package]] name = "confluent-kafka" @@ -201,7 +532,7 @@ version = "2.14.0" description = "Confluent's Python client for Apache Kafka" optional = false python-versions = ">=3.8" -groups = ["main"] +groups = ["main", "ceda"] files = [ {file = "confluent_kafka-2.14.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a9a5205a90f60895737a671ee1a027813d539aaaa82984b793e7807ca35b24bf"}, {file = "confluent_kafka-2.14.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f6405feef51d2881aeb6d360176bc1d20ffb1793f10684149bd89bf95483b535"}, @@ -255,6 +586,187 @@ schemaregistry = ["attrs (>=21.2.0)", "authlib (>=1.0.0)", "cachetools (>=5.5.0) soaktest = ["opentelemetry-distro", "opentelemetry-exporter-otlp", "psutil"] tests = ["async-timeout", "attrs", "attrs (>=21.2.0)", "authlib (>=1.0.0)", "avro (>=1.11.1,<2)", "azure-identity", "azure-keyvault-keys", "black (>=24.0.0)", "boto3 (>=1.35)", "cachetools (>=5.5.0)", "cel-python (>=0.4.0)", "certifi", "fastavro (>=1.5.4,<1.8.0) ; python_version == \"3.7\"", "fastavro (>=1.5.4,<2) ; python_version > \"3.7\"", "flake8", "google-api-core", "google-auth", "google-cloud-kms", "google-re2 (<1.1.20251105)", "googleapis-common-protos", "hkdf (==0.0.3)", "httpx (>=0.26)", "hvac", "isort (>=5.13.0)", "jsonata-python", "jsonschema (>=4.18.0)", "mypy", "orjson", "orjson (>=3.10)", "pluggy (<1.6.0)", "protobuf", "pyrsistent", "pytest", "pytest-asyncio", "pytest-timeout", "pytest_cov", "pyyaml (>=6.0.0)", "requests", "requests-mock", "respx", "tink", "types-cachetools", "types-requests", "urllib3 (<3)"] +[[package]] +name = "coverage" +version = "7.14.1" +description = "Code coverage measurement for Python" +optional = false +python-versions = ">=3.10" +groups = ["test"] +files = [ + {file = "coverage-7.14.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3e3680291c4a1d0dadfa84a2c459576a4af5133abb617905714339a0c73138cf"}, + {file = "coverage-7.14.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a5274669f37f2343635a347b91a60777621341ab3378e9c6ac9335eee704bddf"}, + {file = "coverage-7.14.1-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:cfe5a5fec635799ef33428f1e5e61bafa45a92a96190ba731561ba558ccc214d"}, + {file = "coverage-7.14.1-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:62a9f70b52e0b5a95cfef4a5c5641b06983cadc5e538a3feeb5c00211f523ac2"}, + {file = "coverage-7.14.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3c18ebc343e15be53049b3a2dce38fe82d58f37e20ab9094b3a39c0aa4f6bb47"}, + {file = "coverage-7.14.1-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b84ffdf877644e7096aa936991efeed873f7f3df57b9cd001312b7668ab08550"}, + {file = "coverage-7.14.1-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e854312c4103f2ad4c0dc023b69b77ebfd2c89db5f86c4c94dc2353f9a92167e"}, + {file = "coverage-7.14.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c643734307300234fafa36bf2a040a7235f8f177ea1fd6ec1423aea6fb7b929f"}, + {file = "coverage-7.14.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:84ac9499e48700399a5dd0ea7085b5091961fec52c68d66b4ec0d3cf7f4441b1"}, + {file = "coverage-7.14.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:7f02d09f70776579b926d889a4c9c235070a1f47c40458aeaca563fae5acfdb5"}, + {file = "coverage-7.14.1-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:ce66d8e46da2bb5ee313a745cbd2e391d319176c1f7a9451bfcd3a2fb920859b"}, + {file = "coverage-7.14.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c912c259304cfb5ee584481cfb7ce1ff932b4d61e6c9140b8f19cb7b5ed82332"}, + {file = "coverage-7.14.1-cp310-cp310-win32.whl", hash = "sha256:1238cb94638e610e972c60dac68e813f868dc7d6e982535270558443058d9d59"}, + {file = "coverage-7.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:fc459e5d73be2d6332fcfe8dbf3d8994671fe33c700f4565988ecfa511547253"}, + {file = "coverage-7.14.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:478b5bcd63c2e1357c5c7e16c070690df7b07f676b1c114d7b93e533c664309f"}, + {file = "coverage-7.14.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a24a81f9715ee42ef59a316cc11611c98fe23920f7c81861315c9f3ff4a230f4"}, + {file = "coverage-7.14.1-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:196a13319ad88d6d8ef5ab489ec4f44ddde2143c0c7d5b27786f6c3ffd56a7e1"}, + {file = "coverage-7.14.1-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:3d452fd08b5c72c5167c93e6867b5c08500bd40f2a21e1e854a500550b6cc36f"}, + {file = "coverage-7.14.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:23bf7fa51ac02e07fc7c96849b82946da47ae862dc8f86d183b2a4864fc38129"}, + {file = "coverage-7.14.1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:bcaa50684dcaadfa599ac48f81103c756d791cfd85c97203d2217c593d48b860"}, + {file = "coverage-7.14.1-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:4ea1c034f95c9b056e856b794630b17f9fa3d57e4800ff1e503d3be0f9c9078c"}, + {file = "coverage-7.14.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c7e057326434e441306226fbeb5d1aaf14a2637efe97ba668306635835f32ad7"}, + {file = "coverage-7.14.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:59baf88468dbc8d63b1887afd92bda52e40bb1561696e5819670601403810cec"}, + {file = "coverage-7.14.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:d34d75f892b3ab73ba11cab5442cce7b3e168fd64162b16f0e1e0d09c508edef"}, + {file = "coverage-7.14.1-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:3a56abc20a472baf0304c455721bc601477440d28ecfde8a03dde79ede07e0df"}, + {file = "coverage-7.14.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6a3cb83d1552c0cd1b4906655b6a33fd4a8473229633a901c6b73bf86914dee9"}, + {file = "coverage-7.14.1-cp311-cp311-win32.whl", hash = "sha256:10274a1fbeb8ec5d72966e17bb198a3104257aca4ac09d98667c5f8aca8c8548"}, + {file = "coverage-7.14.1-cp311-cp311-win_amd64.whl", hash = "sha256:87ebdf787d4888e3f3f2d523eadc6e18c6d18c6d0eb173801a189641627fb37e"}, + {file = "coverage-7.14.1-cp311-cp311-win_arm64.whl", hash = "sha256:dd34767fa19848d35659ffc0a75314f58c7af3f1cd87ec521e8292a1238398a3"}, + {file = "coverage-7.14.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a06c76364a9360e33d6d23769aefdf7f66f38e2ffb60ceb1baaa4989d83b695c"}, + {file = "coverage-7.14.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fad54e871165f6ec2f536063ac74c3104508a12963e64072ba44bd822de52b0c"}, + {file = "coverage-7.14.1-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:84b535f00655ecafe1d929d1fb00ed5d6fa3051ea643ab2c161a3887b86f294b"}, + {file = "coverage-7.14.1-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:6b6b0853b895fe0e98cbfc580d1ec3393d9302b4b1e96a77b3f5c91fdab899e6"}, + {file = "coverage-7.14.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:442cc9c952b2df400cda54bb04ab87330cf2cd08a8692cbbea36773531eb6f37"}, + {file = "coverage-7.14.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8270544c361ed405a27a060dbc9ed2c124b084d96dfdc2d9a2510482aef981ad"}, + {file = "coverage-7.14.1-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:48b283b1dd6372e8de2a7a9a4c4d5dc06f4d4fd209b876f3c88a7a205a0c8f84"}, + {file = "coverage-7.14.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5b0c99ba93a07d56f6df340bb79be53202a082b2fdb81bfe6190b741a3470d54"}, + {file = "coverage-7.14.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e471bc5769ff073b058cfadb0d736b56ce067c8560eabeb0da88462df98c23e7"}, + {file = "coverage-7.14.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f497a1ea81d4cd7c10ddcaa685135b9aabd291af3d55775a9ddf3cb7a364cdd9"}, + {file = "coverage-7.14.1-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:2222be86d0b54f5dd5a38f45f17f315f737245e857bf0bdedc70734f84a13c02"}, + {file = "coverage-7.14.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:85e85586565842f6932abebd4c18bcb1074223dc0b3576e7d173ca710622813a"}, + {file = "coverage-7.14.1-cp312-cp312-win32.whl", hash = "sha256:4a28fd227808366b196a75476dced2eb35b351d6766ba9c858dc93319e87f4f1"}, + {file = "coverage-7.14.1-cp312-cp312-win_amd64.whl", hash = "sha256:54acdb6674a4661768d7bf7db32dfb9f46ab1d764f8aba6df75ce1a6a088724e"}, + {file = "coverage-7.14.1-cp312-cp312-win_arm64.whl", hash = "sha256:99cd41ff91afd94896fea3bc002706b6ae4ce95727d06e4a0f39c0a8d8bd8b1a"}, + {file = "coverage-7.14.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:be9f2c802dcfce3f71298303aa5dad0dce440a76c52f2f60dacd8656dab78793"}, + {file = "coverage-7.14.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6223a72fd0e4c7156353ec0f08a5f93623e1d3034d0e2683b9bb8ea674131b1d"}, + {file = "coverage-7.14.1-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:7279d2110a28cebc738b6459ecda2771735a4c18465fbbd36b3288fe5ed92247"}, + {file = "coverage-7.14.1-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:9eeb3fcbc13ba40dfbdb22d01d196a28e9cef9ed4c29b60061a1e0e823a9929d"}, + {file = "coverage-7.14.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5f0cfc27c539f07cf5c0a4cfe211d0b6cae039f8f40526dbaa71944e64b50a7b"}, + {file = "coverage-7.14.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:221c70f316241a78e77e607c227cefc8808d4e08f28d99c04f35694690e940be"}, + {file = "coverage-7.14.1-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:da028256b04ec30e5e0114b6f76172938c313991f0a2d3d894271315cf5d5e43"}, + {file = "coverage-7.14.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:76a085d7005236a767e3426148b2c407e53ad61695c562f8a81da2d373324901"}, + {file = "coverage-7.14.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b553d04b5e778a8e56d57eb134aff42a92718ecba45e79c4764ecfa40efd92ff"}, + {file = "coverage-7.14.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:46f714d2fb8ae2f4f29f23ada7f1e79b759fff5a70f94a1dac23af204c3ec9e4"}, + {file = "coverage-7.14.1-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:1896f5e19ff3f0431c7ce2172adc54890fd97f86b59ced8ca1649145d9ffe35d"}, + {file = "coverage-7.14.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:62fd185ef9df3c33d1c8178c5af105f762afbad96038de9a4ae100aa6297ca33"}, + {file = "coverage-7.14.1-cp313-cp313-win32.whl", hash = "sha256:ab4af6352741a604c431c6072fce5bee33bf0f20dc7a56618d6bf6bb89e9810c"}, + {file = "coverage-7.14.1-cp313-cp313-win_amd64.whl", hash = "sha256:7af486dabe8954d03b087f0021540897afe084f04e16ff5579e08cc46f871416"}, + {file = "coverage-7.14.1-cp313-cp313-win_arm64.whl", hash = "sha256:2224f89ffd0c5605ccce1ed7a584da162bc7c55f601ab1c946bc9de31a486b42"}, + {file = "coverage-7.14.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:de286598cc65d2b489411174b1faec2f5a7775fb3201fd925db2a76b4030f37d"}, + {file = "coverage-7.14.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:042c46ded7c288aeb07cf14a28b6c1e10b78fcba40171c3fa1e939377eeef0b5"}, + {file = "coverage-7.14.1-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:f4ddbe407477f04c45115d1a4e5bc480f753553b534d338d4c3358b1cdd0ea52"}, + {file = "coverage-7.14.1-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:d13e6725992e2d2fd7d81d4f5241952d13740121dfd501da09201be39b2c003a"}, + {file = "coverage-7.14.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f747dc8edcfe740130f28f32f3995e955494285717e86ee25af51db2219df08a"}, + {file = "coverage-7.14.1-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ced2f09ef276fd58611a1ef502164ad266d2b75174e5a40cabbdb4033f9f6cf2"}, + {file = "coverage-7.14.1-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b84800013769a78ccb9ef4659402e26d06867e337b61ec365f77ad008adea80e"}, + {file = "coverage-7.14.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:ea8cd6ca0ee9f616aaef3afc6882e32c2cbf18b00d96313ffd76af650574034d"}, + {file = "coverage-7.14.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:aa5e304a873fabddc11e484e9b6b738bd38bd7bed17b09aa84eecf5332e8b8bb"}, + {file = "coverage-7.14.1-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:5a1c5215be81035e629d5bc756650634d0bf31991038db7a0eccb90f025ce16d"}, + {file = "coverage-7.14.1-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:79058c47dae6788504b5effb319961bcd72d7240551464b91d474bc0ed186d69"}, + {file = "coverage-7.14.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:370c5afae3fa0658e11694a32b24c2778f6bc2d17718121f94ee185e69f26b54"}, + {file = "coverage-7.14.1-cp313-cp313t-win32.whl", hash = "sha256:3758dd0a7f1fa57365ef2e781df0f0731d38b6e3772259d13dae4bd8a958d4b1"}, + {file = "coverage-7.14.1-cp313-cp313t-win_amd64.whl", hash = "sha256:6ff665fb023a77386fe11685190cee1f60a7d635994a30d9b0a061533d470fce"}, + {file = "coverage-7.14.1-cp313-cp313t-win_arm64.whl", hash = "sha256:17a5a241e5997621a956a7f402a7433ef4221e5152809b785bec79e2323799f1"}, + {file = "coverage-7.14.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:d5ed429d0b8edaac649e889b4ffcedb6c80b06629a3f93050e3dddfb99235bee"}, + {file = "coverage-7.14.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:8011224a62280e50dab346960c03cf47aca1a1e09e608c0fb33fd6e0cc8e9500"}, + {file = "coverage-7.14.1-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:12c42ec1e14f553c4f817e989365982e646e27211f10a0f717855b94a79c8906"}, + {file = "coverage-7.14.1-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:06144cd511cf2624873a035c5069cf297144f6e77a73ee3d7a55b605ec5efb42"}, + {file = "coverage-7.14.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a311d8e1da24be5c1ccf85cbfb06315dbaa1703d5a1eab3f6432c72b837917c8"}, + {file = "coverage-7.14.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c79cead5b5bc584d9c71451cb984d0e3a84e0c0937379c8efcbf27c8d661b851"}, + {file = "coverage-7.14.1-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:dcbf65f1f66a26cdd88c35cf68fb4729c5d1cd2e88added72420541dfb212034"}, + {file = "coverage-7.14.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:fd86572566fb40189a8260446158235159bc7a82dfbc87a3b39cf4fb57fcec1c"}, + {file = "coverage-7.14.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:7771b601718fdde84832c3a434ca9bbf4ae9adbc49d84198b4110700c3c77c36"}, + {file = "coverage-7.14.1-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:39b21e212c55af06fa375e3dbf90a8a8e38792f3a910c580066d23563830ddd5"}, + {file = "coverage-7.14.1-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:f2302660e32562a532b442480121aef8aa61a5bdb20b30bf0adab29f10a5a4b4"}, + {file = "coverage-7.14.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:03a6f93c1ec3b7f2e77b5dbcc5573a2c21f12529a5c6bbe0f16f72303cc2fa4d"}, + {file = "coverage-7.14.1-cp314-cp314-win32.whl", hash = "sha256:8a3ce026d73290f42f08dafecbd82c193a74df280461fbf97300fec51fd133ee"}, + {file = "coverage-7.14.1-cp314-cp314-win_amd64.whl", hash = "sha256:114c95ef29302423b87d159075805f4ab973254a2638a5d7d046c94887cc87d7"}, + {file = "coverage-7.14.1-cp314-cp314-win_arm64.whl", hash = "sha256:a07891c3f4805442b31b71e84ba3cf29ed1aa9a428284e06deeb4b23e5b46343"}, + {file = "coverage-7.14.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:1101a5ebb083aecb625ebb6209d4105b58f647b093cb2dc8122d7b33f743cfe1"}, + {file = "coverage-7.14.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:851b9e1e4e8a4608e77c79714b2e77c0970d2ed7202a05e92ae407817481887b"}, + {file = "coverage-7.14.1-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:d5b89cdfb2ee051b71e8c3c70bd81a9eff81100f736a269136fe1a68efe00474"}, + {file = "coverage-7.14.1-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:0177614a0370f227888b4e436a7c55686d6a9f90eb1ade2b624ba685a1686e86"}, + {file = "coverage-7.14.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2d69af5dea2de76fc485a83032a630523f985198b7e25be901ec60181587b01e"}, + {file = "coverage-7.14.1-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:35ab22d91de736e8966b980dc355cbcdd2c6dbbcfe275f9a2991bc8a91b3df65"}, + {file = "coverage-7.14.1-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:357d4e32935c36588aaba057d734fa32428c360c9fc2e4442afbf1b646beee6e"}, + {file = "coverage-7.14.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:51bd64741cc6fa065abd300ede1afe5a5291ece9c31da8b24884deda48bcc3f8"}, + {file = "coverage-7.14.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:9132cd363a68a4c3daa7c8704a654b1e39d3360f6f5b8ddd470608a945236c07"}, + {file = "coverage-7.14.1-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:07c6290b1697b862c0478eab545eec949a0d0e4d6d03497f446d706da3b4f2de"}, + {file = "coverage-7.14.1-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:5ea0c297e27133853b4d8a3eb799bff5a2dbd9f2f41537a240d337ac9b4df890"}, + {file = "coverage-7.14.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:01b7733daad0237daa01ef80fe2dfceffc911e6a17fa7b55d14aa8214eaaaecd"}, + {file = "coverage-7.14.1-cp314-cp314t-win32.whl", hash = "sha256:6adc5a36984624a70bf11d7184e20fa0a49aa7c47ffab43804106a1a695ea22e"}, + {file = "coverage-7.14.1-cp314-cp314t-win_amd64.whl", hash = "sha256:ddf799247318f34dbcd2efa8c95a8d0642674e926bb1774cf9b63dfd2a389d1c"}, + {file = "coverage-7.14.1-cp314-cp314t-win_arm64.whl", hash = "sha256:145986fe66647eb489f18d9a997567a3fd358584c4b5a808769113abc07466af"}, + {file = "coverage-7.14.1-py3-none-any.whl", hash = "sha256:a252f21c27e38347e60111a3266b03827422a7d5525951aceee313aa68bab1d2"}, + {file = "coverage-7.14.1.tar.gz", hash = "sha256:30c08f7d90415aa98b3c990385dea2939b0da55f38515e5b369b83655f8523be"}, +] + +[package.extras] +toml = ["tomli ; python_full_version <= \"3.11.0a6\""] + +[[package]] +name = "cryptography" +version = "49.0.0" +description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." +optional = false +python-versions = "!=3.9.0,!=3.9.1,>=3.9" +groups = ["globus"] +files = [ + {file = "cryptography-49.0.0-cp311-abi3-macosx_11_0_arm64.whl", hash = "sha256:966fe0e9c67490071f14c0d2b1cb2dfb3023c5ce39457343931415f08382f2db"}, + {file = "cryptography-49.0.0-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:36d1709f992593689b45bda411498d62c6e365f2ca00b84657d4dadd24de16db"}, + {file = "cryptography-49.0.0-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0e959b578856a3924bc0cbb710fc12c387b9412a951389f3ca61704a9e25f325"}, + {file = "cryptography-49.0.0-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:53ecee2e23f7169b6117e99fc8a944e5e50f79e69758a83b52a00cb98ab2b2d2"}, + {file = "cryptography-49.0.0-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:2eda353d8a27bcbcaa4cbed18994a74ab4d19a2ca897db188ea269ab9b71419b"}, + {file = "cryptography-49.0.0-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:2afe9051da7ae7bd5905da5a949280c7d2bb75682e188f650a9d0f2756b834c6"}, + {file = "cryptography-49.0.0-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:0b82e28ee398a386f0807bba7884d30f25218855690f45115831bcce5d90822c"}, + {file = "cryptography-49.0.0-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:ccac2bfebc306b862133e3bb71f3f6ee8bb525240089b2d952e4144b3a6d5da7"}, + {file = "cryptography-49.0.0-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:d0527ce944105f257f605a827d6ebead966c752038b6e8656abb9c5edee6fc68"}, + {file = "cryptography-49.0.0-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:cbc77da8c523d5abd028635ba850a6966fcee2c82e2bf65a41d1d8afe0f98be9"}, + {file = "cryptography-49.0.0-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:b87e65d263b3e5d3bb92a57e2a6638e2f31110fa7aa890c7b2dbba42248d0a3f"}, + {file = "cryptography-49.0.0-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:66ec79c3904820572d7e987abdf304281f141d37ad9a489b8e97066e7b9b6459"}, + {file = "cryptography-49.0.0-cp311-abi3-win_amd64.whl", hash = "sha256:e5dfc1e64de5677cec922ffa8da89c546d0415bf6efdf081842e5d44c84e1f0e"}, + {file = "cryptography-49.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:73a205dce83953d131a4aa1e0fd917a2fd1c5b1eef251e9d7152efefcbf5caf7"}, + {file = "cryptography-49.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:196ecd6a36e4e9aa10270393bb98d8df88fccee0bf1e5128b91ae4eb4375896d"}, + {file = "cryptography-49.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7abcee80084cda3f7691f3eb1ce480d8df49cec637b429aa35986c1de71738aa"}, + {file = "cryptography-49.0.0-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:4ae387c9cb68ea569ca17e490d66d8142b81c3cc814bf179974b7d146e490bbb"}, + {file = "cryptography-49.0.0-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:f37d847238971164fdbc68ade6f6574aecc9c0af714190e2083429ff68f4ce9d"}, + {file = "cryptography-49.0.0-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:c2bc30226390d60ea19d9f82b19db005fe0452154a23c1c410c12ea801e43561"}, + {file = "cryptography-49.0.0-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:07cab27cc7b7e0fd28e5e26bb9eeedde5c135c868b46de4a27845abe94af6122"}, + {file = "cryptography-49.0.0-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:b20133d204d2bb56ba047642199603876c872026ca53e79c35b83772ab2cc505"}, + {file = "cryptography-49.0.0-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:b970c6da94d5bb18629db453d14f2a1300f6bf59b61e9b82377931ef95504866"}, + {file = "cryptography-49.0.0-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:d8ecde755e2e91bf773fc94e8c9d730cd7f2007004cb492263a794ec3899a1c8"}, + {file = "cryptography-49.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e3fb64c420688e5319ae25113a354015abbd8dffbfbc41781a1ea66fc7622ac3"}, + {file = "cryptography-49.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:32703d93296f5c1f4b53349ad3a250c2cae0fdecd3a3dd5d47e616d8d616af27"}, + {file = "cryptography-49.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:33cd0565932807baddb67b96dbee92f2c374b5c89dee09fd74079aeb8c8dba61"}, + {file = "cryptography-49.0.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:ec5e529fb80935c94fe7b729f9972b50e351a0e6b50aa294fd5cabb109fcc29a"}, + {file = "cryptography-49.0.0-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f78ff2c9ed8dc2d036b0f4d640e22522213d047c1b14e61205a7e55c80a494d4"}, + {file = "cryptography-49.0.0-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:35b151772baff2c74cba7fa290ceaff4c3b11c0c881eb93eb5dbc05a7cfbba18"}, + {file = "cryptography-49.0.0-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:0f21641cf4b30fca7aee061ced0ec7ad7b073518088b7c9969a297c0ae796c69"}, + {file = "cryptography-49.0.0-cp39-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:9e82dcc8e56052715fb18b2429e3bca4823b1629136a2084fc45a9a5cecb9b64"}, + {file = "cryptography-49.0.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:6f2debedf9ca60cf1d5bd466475638af5130f89965605cd818484d19987d3a21"}, + {file = "cryptography-49.0.0-cp39-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:8c25ceb16df5b9435f3f6a9829204985b0e0cbee3b48aacd432c7d2c850b44d9"}, + {file = "cryptography-49.0.0-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:28d8b15e6275f12c8a207dc309dfa957903c927d08d0cc937ee3f63f200693cc"}, + {file = "cryptography-49.0.0-cp39-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:6fc361c34fb6aac015ce19435876635e5c6d21db31998b0920f675f131e043b8"}, + {file = "cryptography-49.0.0-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:2400ef9c9e2299a25614eb1dea3db54a69b1349efd043bfac9c67630d136df36"}, + {file = "cryptography-49.0.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:67e1d20ad9ef3a563c59ef22e7a8a0b8210bd26604369ea4a30a7c66aefe504e"}, + {file = "cryptography-49.0.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:42b0684e0e40cf26122427802486f6d93aea593612603a94fbf260c7eb1e9c1b"}, + {file = "cryptography-49.0.0-cp39-abi3-win_amd64.whl", hash = "sha256:026ac7423e6fa66872d3bf889be5974507da3944f866f704fa200eadacd00001"}, + {file = "cryptography-49.0.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:fc1e275c2f1d97b1a6450b8b0ea3ebfa6e087a611c2b26cb2404d48588abab7b"}, + {file = "cryptography-49.0.0-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:c83782480a4a9da4d0feb51950131ba32e12e70813848b3343f6e18c28a66838"}, + {file = "cryptography-49.0.0-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:b39efa323140595abd3ecca8529d321ae50f55f3aa3ba9cc81ea56a6011953d5"}, + {file = "cryptography-49.0.0-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:b47db11c2c3525083296069b98ac5221907455e989ae0c2e3008bde851921615"}, + {file = "cryptography-49.0.0-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:084ef1af862eb07ec46d25f68689f2102a9fc0e05ce7b80f14f5fe51e4eef0f6"}, + {file = "cryptography-49.0.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:be9fcb48a55f023493482827d4f459bd263cc20efde64f204b97c123201850c6"}, + {file = "cryptography-49.0.0.tar.gz", hash = "sha256:f89660a348f4f78a92366240a61404e337586ef7f5909a2fef59ca88ef505493"}, +] + +[package.dependencies] +cffi = {version = ">=2.0.0", markers = "platform_python_implementation != \"PyPy\""} + +[package.extras] +ssh = ["bcrypt (>=3.1.5)"] + [[package]] name = "esgf-core-utils" version = "1.0.7" @@ -317,25 +829,107 @@ dev = ["bump-my-version", "pre-commit"] docs = ["mkdocs", "mkdocs-material", "pygments"] test = ["pytest", "pytest-cov", "shapely"] +[[package]] +name = "globus-sdk" +version = "3.62.0" +description = "Globus SDK for Python" +optional = false +python-versions = ">=3.8" +groups = ["globus"] +files = [ + {file = "globus_sdk-3.62.0-py3-none-any.whl", hash = "sha256:76e1d1699aefd556339f5caff780bb59ea966455b97eb6153769387aef842459"}, + {file = "globus_sdk-3.62.0.tar.gz", hash = "sha256:5eabe95ee8c8f891b6b3367924037627bcd388b3433f2994062c5efc67915890"}, +] + +[package.dependencies] +cryptography = ">=3.3.1,<3.4.0 || >3.4.0" +pyjwt = {version = ">=2.0.0,<3.0.0", extras = ["crypto"]} +requests = ">=2.19.1,<3.0.0" + [[package]] name = "h11" version = "0.14.0" description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" optional = false python-versions = ">=3.7" -groups = ["main"] +groups = ["main", "ceda", "test"] files = [ {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, ] +[[package]] +name = "httpcore" +version = "1.0.8" +description = "A minimal low-level HTTP client." +optional = false +python-versions = ">=3.8" +groups = ["ceda", "test"] +files = [ + {file = "httpcore-1.0.8-py3-none-any.whl", hash = "sha256:5254cf149bcb5f75e9d1b2b9f729ea4a4b883d1ad7379fc632b727cec23674be"}, + {file = "httpcore-1.0.8.tar.gz", hash = "sha256:86e94505ed24ea06514883fd44d2bc02d90e77e7979c8eb71b90f41d364a1bad"}, +] + +[package.dependencies] +certifi = "*" +h11 = ">=0.13,<0.15" + +[package.extras] +asyncio = ["anyio (>=4.0,<5.0)"] +http2 = ["h2 (>=3,<5)"] +socks = ["socksio (==1.*)"] +trio = ["trio (>=0.22.0,<1.0)"] + +[[package]] +name = "httpx" +version = "0.28.1" +description = "The next generation HTTP client." +optional = false +python-versions = ">=3.8" +groups = ["ceda", "test"] +files = [ + {file = "httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad"}, + {file = "httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc"}, +] + +[package.dependencies] +anyio = "*" +certifi = "*" +httpcore = "==1.*" +idna = "*" + +[package.extras] +brotli = ["brotli ; platform_python_implementation == \"CPython\"", "brotlicffi ; platform_python_implementation != \"CPython\""] +cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"] +http2 = ["h2 (>=3,<5)"] +socks = ["socksio (==1.*)"] +zstd = ["zstandard (>=0.18.0)"] + +[[package]] +name = "httpx-auth" +version = "0.23.1" +description = "Authentication for HTTPX" +optional = false +python-versions = ">=3.9" +groups = ["ceda"] +files = [ + {file = "httpx_auth-0.23.1-py3-none-any.whl", hash = "sha256:04f8bd0824efe3d9fb79690cc670b0da98ea809babb7aea04a72f334d4fd5ec5"}, + {file = "httpx_auth-0.23.1.tar.gz", hash = "sha256:27b5a6022ad1b41a303b8737fa2e3e4bce6bbbe7ab67fed0b261359be62e0434"}, +] + +[package.dependencies] +httpx = "==0.28.*" + +[package.extras] +testing = ["pyjwt (==2.*)", "pytest-asyncio (==0.25.*)", "pytest-cov (==6.*)", "pytest_httpx (==0.35.*)", "time-machine (==2.*)"] + [[package]] name = "idna" version = "3.10" description = "Internationalized Domain Names in Applications (IDNA)" optional = false python-versions = ">=3.6" -groups = ["main"] +groups = ["main", "ceda", "globus", "test"] files = [ {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, @@ -344,6 +938,18 @@ files = [ [package.extras] all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] +[[package]] +name = "iniconfig" +version = "2.3.0" +description = "brain-dead simple config-ini parsing" +optional = false +python-versions = ">=3.10" +groups = ["test"] +files = [ + {file = "iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12"}, + {file = "iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730"}, +] + [[package]] name = "iso8601" version = "2.1.0" @@ -374,6 +980,18 @@ MarkupSafe = ">=2.0" [package.extras] i18n = ["Babel (>=2.7)"] +[[package]] +name = "jmespath" +version = "1.1.0" +description = "JSON Matching Expressions" +optional = false +python-versions = ">=3.9" +groups = ["globus"] +files = [ + {file = "jmespath-1.1.0-py3-none-any.whl", hash = "sha256:a5663118de4908c91729bea0acadca56526eb2698e83de10cd116ae0f4e97c64"}, + {file = "jmespath-1.1.0.tar.gz", hash = "sha256:472c87d80f36026ae83c6ddd0f1d05d4e510134ed462851fd5f754c8c3cbb88d"}, +] + [[package]] name = "jsonschema" version = "4.24.0" @@ -388,7 +1006,7 @@ files = [ [package.dependencies] attrs = ">=22.2.0" -jsonschema-specifications = ">=2023.03.6" +jsonschema-specifications = ">=2023.3.6" referencing = ">=0.28.4" rpds-py = ">=0.7.1" @@ -592,13 +1210,54 @@ files = [ {file = "numpy-2.4.6.tar.gz", hash = "sha256:f3a3570c4a2a16746ac2c31a7c7c7b0c186b95ce902e33db6f28094ed7387dda"}, ] +[[package]] +name = "packaging" +version = "26.2" +description = "Core utilities for Python packages" +optional = false +python-versions = ">=3.8" +groups = ["main", "test"] +files = [ + {file = "packaging-26.2-py3-none-any.whl", hash = "sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e"}, + {file = "packaging-26.2.tar.gz", hash = "sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661"}, +] + +[[package]] +name = "pluggy" +version = "1.6.0" +description = "plugin and hook calling mechanisms for python" +optional = false +python-versions = ">=3.9" +groups = ["test"] +files = [ + {file = "pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746"}, + {file = "pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3"}, +] + +[package.extras] +dev = ["pre-commit", "tox"] +testing = ["coverage", "pytest", "pytest-benchmark"] + +[[package]] +name = "pycparser" +version = "3.0" +description = "C parser in Python" +optional = false +python-versions = ">=3.10" +groups = ["globus"] +markers = "platform_python_implementation != \"PyPy\" and implementation_name != \"PyPy\"" +files = [ + {file = "pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992"}, + {file = "pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29"}, +] + [[package]] name = "pydantic" version = "2.13.4" description = "Data validation using Python type hints" optional = false python-versions = ">=3.9" -groups = ["main"] +groups = ["main", "ceda"] files = [ {file = "pydantic-2.13.4-py3-none-any.whl", hash = "sha256:45a282cde31d808236fd7ea9d919b128653c8b38b393d1c4ab335c62924d9aba"}, {file = "pydantic-2.13.4.tar.gz", hash = "sha256:c40756b57adaa8b1efeeced5c196f3f3b7c435f90e84ea7f443901bec8099ef6"}, @@ -620,7 +1279,7 @@ version = "2.46.4" description = "Core functionality for Pydantic validation and serialization" optional = false python-versions = ">=3.9" -groups = ["main"] +groups = ["main", "ceda"] files = [ {file = "pydantic_core-2.46.4-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:a396dcc17e5a0b164dbe026896245a4fa9ff402edca1dff0be3d53a517f74de4"}, {file = "pydantic_core-2.46.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:da4b951fe36dc7c3a1ccb4e3cd1747c3542b8c9ceede8fc86cae054e764485f5"}, @@ -768,6 +1427,117 @@ azure-key-vault = ["azure-identity (>=1.16.0)", "azure-keyvault-secrets (>=4.8.0 toml = ["tomli (>=2.0.1)"] yaml = ["pyyaml (>=6.0.1)"] +[[package]] +name = "pygments" +version = "2.20.0" +description = "Pygments is a syntax highlighting package written in Python." +optional = false +python-versions = ">=3.9" +groups = ["test"] +files = [ + {file = "pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176"}, + {file = "pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f"}, +] + +[package.extras] +windows-terminal = ["colorama (>=0.4.6)"] + +[[package]] +name = "pyjwt" +version = "2.12.1" +description = "JSON Web Token implementation in Python" +optional = false +python-versions = ">=3.9" +groups = ["globus"] +files = [ + {file = "pyjwt-2.12.1-py3-none-any.whl", hash = "sha256:28ca37c070cad8ba8cd9790cd940535d40274d22f80ab87f3ac6a713e6e8454c"}, + {file = "pyjwt-2.12.1.tar.gz", hash = "sha256:c74a7a2adf861c04d002db713dd85f84beb242228e671280bf709d765b03672b"}, +] + +[package.dependencies] +cryptography = {version = ">=3.4.0", optional = true, markers = "extra == \"crypto\""} + +[package.extras] +crypto = ["cryptography (>=3.4.0)"] +dev = ["coverage[toml] (==7.10.7)", "cryptography (>=3.4.0)", "pre-commit", "pytest (>=8.4.2,<9.0.0)", "sphinx", "sphinx-rtd-theme", "zope.interface"] +docs = ["sphinx", "sphinx-rtd-theme", "zope.interface"] +tests = ["coverage[toml] (==7.10.7)", "pytest (>=8.4.2,<9.0.0)"] + +[[package]] +name = "pytest" +version = "9.1.0" +description = "pytest: simple powerful testing with Python" +optional = false +python-versions = ">=3.10" +groups = ["test"] +files = [ + {file = "pytest-9.1.0-py3-none-any.whl", hash = "sha256:8ebb0e7888bdf2bdfc602ec51f8f62d50200af37356c74e503c79a94f5c81f32"}, + {file = "pytest-9.1.0.tar.gz", hash = "sha256:41dd9148c08072446394cefd3d79701701335a9f4cae69ba92e39f6c7f5c061c"}, +] + +[package.dependencies] +colorama = {version = ">=0.4", markers = "sys_platform == \"win32\""} +iniconfig = ">=1.0.1" +packaging = ">=22" +pluggy = ">=1.5,<2" +pygments = ">=2.7.2" + +[package.extras] +dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "requests", "setuptools", "xmlschema"] + +[[package]] +name = "pytest-cov" +version = "7.1.0" +description = "Pytest plugin for measuring coverage." +optional = false +python-versions = ">=3.9" +groups = ["test"] +files = [ + {file = "pytest_cov-7.1.0-py3-none-any.whl", hash = "sha256:a0461110b7865f9a271aa1b51e516c9a95de9d696734a2f71e3e78f46e1d4678"}, + {file = "pytest_cov-7.1.0.tar.gz", hash = "sha256:30674f2b5f6351aa09702a9c8c364f6a01c27aae0c1366ae8016160d1efc56b2"}, +] + +[package.dependencies] +coverage = {version = ">=7.10.6", extras = ["toml"]} +pluggy = ">=1.2" +pytest = ">=7" + +[package.extras] +testing = ["process-tests", "pytest-xdist", "virtualenv"] + +[[package]] +name = "pytest-mock" +version = "3.15.1" +description = "Thin-wrapper around the mock package for easier use with pytest" +optional = false +python-versions = ">=3.9" +groups = ["test"] +files = [ + {file = "pytest_mock-3.15.1-py3-none-any.whl", hash = "sha256:0a25e2eb88fe5168d535041d09a4529a188176ae608a6d249ee65abc0949630d"}, + {file = "pytest_mock-3.15.1.tar.gz", hash = "sha256:1849a238f6f396da19762269de72cb1814ab44416fa73a8686deac10b0d87a0f"}, +] + +[package.dependencies] +pytest = ">=6.2.5" + +[package.extras] +dev = ["pre-commit", "pytest-asyncio", "tox"] + +[[package]] +name = "python-dateutil" +version = "2.9.0.post0" +description = "Extensions to the standard Python datetime module" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +groups = ["globus"] +files = [ + {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, + {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, +] + +[package.dependencies] +six = ">=1.5" + [[package]] name = "python-dotenv" version = "1.0.1" @@ -800,6 +1570,28 @@ attrs = ">=22.2.0" rpds-py = ">=0.7.0" typing-extensions = {version = ">=4.4.0", markers = "python_version < \"3.13\""} +[[package]] +name = "requests" +version = "2.34.2" +description = "Python HTTP for Humans." +optional = false +python-versions = ">=3.10" +groups = ["globus"] +files = [ + {file = "requests-2.34.2-py3-none-any.whl", hash = "sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0"}, + {file = "requests-2.34.2.tar.gz", hash = "sha256:f288924cae4e29463698d6d60bc6a4da69c89185ad1e0bcc4104f584e960b9ed"}, +] + +[package.dependencies] +certifi = ">=2023.5.7" +charset_normalizer = ">=2,<4" +idna = ">=2.5,<4" +urllib3 = ">=1.26,<3" + +[package.extras] +socks = ["PySocks (>=1.5.6,!=1.5.7)"] +use-chardet-on-py3 = ["chardet (>=3.0.2,<8)"] + [[package]] name = "rpds-py" version = "0.25.1" @@ -927,6 +1719,24 @@ files = [ {file = "rpds_py-0.25.1.tar.gz", hash = "sha256:8960b6dac09b62dac26e75d7e2c4a22efb835d827a7278c34f72b2b84fa160e3"}, ] +[[package]] +name = "s3transfer" +version = "0.17.1" +description = "An Amazon S3 Transfer Manager" +optional = false +python-versions = ">=3.10" +groups = ["globus"] +files = [ + {file = "s3transfer-0.17.1-py3-none-any.whl", hash = "sha256:5b9827d1044159bbb01b86ef8902760ea39281927f5de31de75e1d657177bf4c"}, + {file = "s3transfer-0.17.1.tar.gz", hash = "sha256:042dd5e3b1b512355e35a23f0223e426b7042e80b97830ea2680ddce327fc45e"}, +] + +[package.dependencies] +botocore = ">=1.37.4,<2.0a0" + +[package.extras] +crt = ["botocore[crt] (>=1.37.4,<2.0a0)"] + [[package]] name = "shapely" version = "2.1.2" @@ -1001,13 +1811,25 @@ numpy = ">=1.21" docs = ["matplotlib", "numpydoc (==1.1.*)", "sphinx", "sphinx-book-theme", "sphinx-remove-toctrees"] test = ["pytest", "pytest-cov", "scipy-doctest"] +[[package]] +name = "six" +version = "1.17.0" +description = "Python 2 and 3 compatibility utilities" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +groups = ["globus"] +files = [ + {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"}, + {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, +] + [[package]] name = "sniffio" version = "1.3.1" description = "Sniff out which async library your code is running under" optional = false python-versions = ">=3.7" -groups = ["main"] +groups = ["main", "ceda", "test"] files = [ {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, @@ -1123,11 +1945,12 @@ version = "4.15.0" description = "Backported and Experimental Type Hints for Python 3.9+" optional = false python-versions = ">=3.9" -groups = ["main"] +groups = ["main", "ceda", "test"] files = [ {file = "typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548"}, {file = "typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466"}, ] +markers = {test = "python_version == \"3.12\""} [[package]] name = "typing-inspection" @@ -1135,7 +1958,7 @@ version = "0.4.2" description = "Runtime typing introspection tools" optional = false python-versions = ">=3.9" -groups = ["main"] +groups = ["main", "ceda"] files = [ {file = "typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7"}, {file = "typing_inspection-0.4.2.tar.gz", hash = "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464"}, @@ -1144,6 +1967,24 @@ files = [ [package.dependencies] typing-extensions = ">=4.12.0" +[[package]] +name = "urllib3" +version = "2.7.0" +description = "HTTP library with thread-safe connection pooling, file post, and more." +optional = false +python-versions = ">=3.10" +groups = ["globus"] +files = [ + {file = "urllib3-2.7.0-py3-none-any.whl", hash = "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897"}, + {file = "urllib3-2.7.0.tar.gz", hash = "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c"}, +] + +[package.extras] +brotli = ["brotli (>=1.2.0) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=1.2.0.0) ; platform_python_implementation != \"CPython\""] +h2 = ["h2 (>=4,<5)"] +socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] +zstd = ["backports-zstd (>=1.0.0) ; python_version < \"3.14\""] + [[package]] name = "uvicorn" version = "0.46.0" @@ -1166,4 +2007,4 @@ standard = ["colorama (>=0.4) ; sys_platform == \"win32\"", "httptools (>=0.6.3) [metadata] lock-version = "2.1" python-versions = ">=3.12,<4.0" -content-hash = "3a65ae94dafe7e743fd7567717c30cc64904a84ea816da42493ffcbe293d5e73" +content-hash = "8493615b34d707f5955454b9188bd21294fe41cd77b08883b1266e48414dcb51" diff --git a/pyproject.toml b/pyproject.toml index e40ae1f..8155e6d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,10 +12,11 @@ dependencies = [ "esgf-core-utils>=1.0.7", "fastapi>=0.114.0", "jsonschema>=4.24.0", + "packaging>=26.2", + "shapely>=2.1.2", "stac-fastapi.types>=6.0.0", "stac-fastapi.extensions>=6.0.0", "uvicorn>=0.46.0", - "shapely>=2.1.2", ] [dependency-groups] diff --git a/src/utils.py b/src/utils.py index 7e77f7b..9c08912 100644 --- a/src/utils.py +++ b/src/utils.py @@ -9,6 +9,7 @@ OperationNotPermittedException, STACValidationException, UnexpectedExtensionException, + ExtensionBelowMinimumException, ) from jsonschema.protocols import Validator from shapely.geometry import shape @@ -18,12 +19,22 @@ PatchOperation, ) from stac_pydantic.item import Item - +from packaging.version import Version from settings import DEFAULT_EXTENSIONS # Setup logger logger = logging.getLogger("uvicorn.error") +VERSION_REGEX = re.compile( + r'/v(' + r'(?P0|[1-9]\d*)\.' + r'(?P0|[1-9]\d*)\.' + r'(?P0|[1-9]\d*)' + r'(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?' + r'(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?' + r')/' + ) + def operation_to_partial_item(collection_id: str, operations: list[PatchOperation]) -> PartialItem: """Convert operations to partial item @@ -81,6 +92,23 @@ def operation_to_partial_item(collection_id: str, operations: list[PatchOperatio return PartialItem.model_validate(item) +def validate_extension_version(minimum: str, extension: str) -> None: + """Validate an extenions version is above the minimum. + + Args: + default (str): default extension with minimum version. + extension (str): extension to be validated. + + Raises: + ExtensionBelowMinimumException: extension below minimum + """ + + minimum_version = VERSION_REGEX.search(extension).group(1) + extension_version = VERSION_REGEX.search(minimum).group(1) + + if Version(extension_version) < Version(minimum_version): + raise ExtensionBelowMinimumException(extension=extension, minimum_version=f"v{minimum_version}") + def validate_extensions(collection_id: str, item_extensions: list[str], strict: bool = False) -> list[str]: """Validate expected default extensions are present. @@ -110,6 +138,8 @@ def validate_extensions(collection_id: str, item_extensions: list[str], strict: expected_extensions.pop(expected_extension_key) expected = True + validate_extension_version(minimum=expected_extension["default"], extension=str(item_extension)) + if not expected: raise UnexpectedExtensionException(extension=item_extension) From 7b9a612d4ed4c22609cd10998ca5f017499f50e8 Mon Sep 17 00:00:00 2001 From: rhysrevans3 Date: Thu, 18 Jun 2026 16:02:37 +0100 Subject: [PATCH 13/35] pre-commit. --- src/utils.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/utils.py b/src/utils.py index 9c08912..06d1ed8 100644 --- a/src/utils.py +++ b/src/utils.py @@ -26,14 +26,14 @@ logger = logging.getLogger("uvicorn.error") VERSION_REGEX = re.compile( - r'/v(' - r'(?P0|[1-9]\d*)\.' - r'(?P0|[1-9]\d*)\.' - r'(?P0|[1-9]\d*)' - r'(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?' - r'(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?' - r')/' - ) + r"/v(" + r"(?P0|[1-9]\d*)\." + r"(?P0|[1-9]\d*)\." + r"(?P0|[1-9]\d*)" + r"(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?" + r"(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?" + r")/" +) def operation_to_partial_item(collection_id: str, operations: list[PatchOperation]) -> PartialItem: @@ -92,6 +92,7 @@ def operation_to_partial_item(collection_id: str, operations: list[PatchOperatio return PartialItem.model_validate(item) + def validate_extension_version(minimum: str, extension: str) -> None: """Validate an extenions version is above the minimum. From 71537c80311fac8b665ada822609e72f6cf0eadf Mon Sep 17 00:00:00 2001 From: rhysrevans3 Date: Fri, 19 Jun 2026 09:32:44 +0100 Subject: [PATCH 14/35] Move version regex to settings. --- src/settings/__init__.py | 13 ++++++++++++- src/utils.py | 12 +----------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/settings/__init__.py b/src/settings/__init__.py index e86f030..ac551ef 100644 --- a/src/settings/__init__.py +++ b/src/settings/__init__.py @@ -1,12 +1,13 @@ import os from typing import Literal - +import re from pydantic_settings import BaseSettings, SettingsConfigDict if os.environ.get("TRANSACTION_AUTHORIZER") == "egi": from settings.ceda import CEDAClientSettings as ClientSettings else: from settings.globus import GlobusClientSettings as ClientSettings + DEFAULT_EXTENSIONS = { "CMIP6": { "CMIP6": { @@ -80,6 +81,16 @@ }, } +VERSION_REGEX = re.compile( + r"/v(" + r"(?P0|[1-9]\d*)\." + r"(?P0|[1-9]\d*)\." + r"(?P0|[1-9]\d*)" + r"(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?" + r"(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?" + r")/" +) + class Settings(BaseSettings): """ diff --git a/src/utils.py b/src/utils.py index 06d1ed8..253e552 100644 --- a/src/utils.py +++ b/src/utils.py @@ -20,21 +20,11 @@ ) from stac_pydantic.item import Item from packaging.version import Version -from settings import DEFAULT_EXTENSIONS +from settings import DEFAULT_EXTENSIONS, VERSION_REGEX # Setup logger logger = logging.getLogger("uvicorn.error") -VERSION_REGEX = re.compile( - r"/v(" - r"(?P0|[1-9]\d*)\." - r"(?P0|[1-9]\d*)\." - r"(?P0|[1-9]\d*)" - r"(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?" - r"(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?" - r")/" -) - def operation_to_partial_item(collection_id: str, operations: list[PatchOperation]) -> PartialItem: """Convert operations to partial item From 58a59ee68d6e28dc8183b9ae371f903c69c4c2fc Mon Sep 17 00:00:00 2001 From: rhysrevans3 Date: Mon, 22 Jun 2026 12:29:38 +0100 Subject: [PATCH 15/35] Add scope skip to EGI authorizer. --- src/authorizer/egi_authorizer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/authorizer/egi_authorizer.py b/src/authorizer/egi_authorizer.py index 44817bf..f61c075 100644 --- a/src/authorizer/egi_authorizer.py +++ b/src/authorizer/egi_authorizer.py @@ -28,7 +28,7 @@ class EGIAuthorizer(BaseHTTPMiddleware): async def dispatch(self, request: Request, call_next): # Need to bypass authorization for this endpoint - if request.url.path == "/healthcheck": + if request.url.path in ["/healthcheck", "/scope"]: return await call_next(request) logger.info("Request Headers %s", request.headers) From a7996f3c9af1c60a72a575f5f3acd41a57053dc4 Mon Sep 17 00:00:00 2001 From: rhysrevans3 Date: Mon, 22 Jun 2026 12:50:49 +0100 Subject: [PATCH 16/35] Add scope url for EGI auth. --- src/api.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/api.py b/src/api.py index 8f876bb..d6cfa8e 100644 --- a/src/api.py +++ b/src/api.py @@ -21,6 +21,17 @@ async def healthcheck(): ) +if settings.authorizer == "egi": + + @app.get("/scope") + async def scope(): + return JSONResponse( + content={"scope": "offline_access entitlements"}, + media_type="application/json", + status_code=200, + ) + + @app.exception_handler(RFC9457Exception) async def rfc9457_handler(request: Request, exc: RFC9457Exception): return JSONResponse( From 608af98a27b36e4afce20d2bc1e9f2eed259fa85 Mon Sep 17 00:00:00 2001 From: rhysrevans3 Date: Tue, 23 Jun 2026 08:29:35 +0100 Subject: [PATCH 17/35] Make scope a setting. --- src/api.py | 2 +- src/settings/ceda.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/api.py b/src/api.py index d6cfa8e..b571a1f 100644 --- a/src/api.py +++ b/src/api.py @@ -26,7 +26,7 @@ async def healthcheck(): @app.get("/scope") async def scope(): return JSONResponse( - content={"scope": "offline_access entitlements"}, + content={"scope": settings.client.scope}, media_type="application/json", status_code=200, ) diff --git a/src/settings/ceda.py b/src/settings/ceda.py index 13b3afd..fe55661 100644 --- a/src/settings/ceda.py +++ b/src/settings/ceda.py @@ -14,3 +14,4 @@ class CEDAClientSettings(BaseModel): r"urn\:mace\:egi\.eu\:group\:esgf.vo.egi.eu\:(?P[^:]*)\:(?P[^:]*)" r"(\:institution\:(?P[^:]*))?\:role=(?P[^:]*)#aai\.egi\.eu" ) + scope: str = "offline_access entitlements" From c79b824cbdf612bf8dfbba0433fe6f16f11d9223 Mon Sep 17 00:00:00 2001 From: rhysrevans3 Date: Tue, 23 Jun 2026 11:38:24 +0100 Subject: [PATCH 18/35] Update imports and stac-fastapi version. --- poetry.lock | 53 +++++++++++++++++++------------------------------- pyproject.toml | 4 ++-- src/client.py | 4 ++-- src/utils.py | 2 +- 4 files changed, 25 insertions(+), 38 deletions(-) diff --git a/poetry.lock b/poetry.lock index 53c8260..2c90772 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1837,55 +1837,46 @@ files = [ [[package]] name = "stac-fastapi-api" -version = "6.0.0" +version = "6.3.0" description = "An implementation of STAC API based on the FastAPI framework." optional = false -python-versions = ">=3.9" +python-versions = ">=3.11" groups = ["main"] files = [ - {file = "stac_fastapi_api-6.0.0-py3-none-any.whl", hash = "sha256:8cb99869d886d806a098d0d0caf46a75bd39ff64a8dfdf491bded065ed4d53b6"}, - {file = "stac_fastapi_api-6.0.0.tar.gz", hash = "sha256:ab6241df62847c3b012f5bb6dfca5c7cd6a3c097afd8e5881b0e213a3d6dcdb2"}, + {file = "stac_fastapi_api-6.3.0-py3-none-any.whl", hash = "sha256:767b281f606f13d242b3834e6a0ed50cc2c7d0022184613ab7613750dd2a4d3a"}, + {file = "stac_fastapi_api-6.3.0.tar.gz", hash = "sha256:d4d093dae4b13da8228eadae11ab2d9f438a22078b0559c5c39533ce1195926a"}, ] [package.dependencies] -brotli_asgi = "*" -"stac-fastapi.types" = ">=6.0,<7.0" - -[package.extras] -benchmark = ["pytest-benchmark"] -dev = ["httpx", "pre-commit", "pytest", "pytest-asyncio", "pytest-cov", "requests"] -docs = ["black (>=23.10.1)", "griffe-inherited-docstrings (>=1.0.0)", "mkdocs (>=1.4.3)", "mkdocs-jupyter (>=0.24.5)", "mkdocs-material[imaging] (>=9.5)", "mkdocstrings[python] (>=0.25.1)"] +brotli-asgi = "*" +stac-fastapi-types = ">=6.2,<7.0" [[package]] name = "stac-fastapi-extensions" -version = "6.0.0" -description = "An implementation of STAC API based on the FastAPI framework." +version = "6.3.0" +description = "Extensions for stac-fastapi apis." optional = false -python-versions = ">=3.9" +python-versions = ">=3.11" groups = ["main"] files = [ - {file = "stac_fastapi_extensions-6.0.0-py3-none-any.whl", hash = "sha256:c158a63c5ca7e83d95817956385c58606ab92b0c733ab3a62a42e3d65b108274"}, - {file = "stac_fastapi_extensions-6.0.0.tar.gz", hash = "sha256:3829982d07299bb82605774d311675795fbc6972c920b6aa48ef6853cc187f7b"}, + {file = "stac_fastapi_extensions-6.3.0-py3-none-any.whl", hash = "sha256:d4c541dff1e2a2b7997c01b676fce0c4cd1c82faa88630efe3da3f976a738b24"}, + {file = "stac_fastapi_extensions-6.3.0.tar.gz", hash = "sha256:79f941bb7aa7f6a4e3c19da8deacda1dee42f19c596360f5ce9a9f9ecde214d8"}, ] [package.dependencies] -"stac-fastapi.api" = ">=6.0,<7.0" -"stac-fastapi.types" = ">=6.0,<7.0" - -[package.extras] -dev = ["pre-commit", "pytest", "pytest-asyncio", "pytest-cov", "requests"] -docs = ["black (>=23.10.1)", "griffe-inherited-docstrings (>=1.0.0)", "mkdocs (>=1.4.3)", "mkdocs-jupyter (>=0.24.5)", "mkdocs-material[imaging] (>=9.5)", "mkdocstrings[python] (>=0.25.1)"] +stac-fastapi-api = ">=6.2,<7.0" +stac-fastapi-types = ">=6.2,<7.0" [[package]] name = "stac-fastapi-types" -version = "6.0.0" -description = "An implementation of STAC API based on the FastAPI framework." +version = "6.3.0" +description = "Core API for stac-fastapi modules." optional = false -python-versions = ">=3.9" +python-versions = ">=3.11" groups = ["main"] files = [ - {file = "stac_fastapi_types-6.0.0-py3-none-any.whl", hash = "sha256:127db34c036223359c6a4a4a7d0a16d5f41d9b841a5dd109978b9dc1c0cfbf61"}, - {file = "stac_fastapi_types-6.0.0.tar.gz", hash = "sha256:ce058af7813e009b4ec1f7ccd1187c5d661b9505099b7b208c814c278ecd68a7"}, + {file = "stac_fastapi_types-6.3.0-py3-none-any.whl", hash = "sha256:fcbaa7b3128917bd4f761296d93c13d54696c08f0e7d561c91b12244d2a1047a"}, + {file = "stac_fastapi_types-6.3.0.tar.gz", hash = "sha256:7a084f9660f1e61f160f4a4f21a52f8355be4af983c48ed5a77d7f5e024b3509"}, ] [package.dependencies] @@ -1893,11 +1884,7 @@ attrs = ">=23.2.0" fastapi = ">=0.109.0" iso8601 = ">=1.0.2,<2.2.0" pydantic-settings = ">=2" -stac_pydantic = ">=3.3.0,<4.0" - -[package.extras] -dev = ["pre-commit", "pytest", "pytest-asyncio", "pytest-cov", "requests"] -docs = ["black (>=23.10.1)", "griffe-inherited-docstrings (>=1.0.0)", "mkdocs (>=1.4.3)", "mkdocs-jupyter (>=0.24.5)", "mkdocs-material[imaging] (>=9.5)", "mkdocstrings[python] (>=0.25.1)"] +stac-pydantic = ">=3.3.0,<4.0" [[package]] name = "stac-pydantic" @@ -2007,4 +1994,4 @@ standard = ["colorama (>=0.4) ; sys_platform == \"win32\"", "httptools (>=0.6.3) [metadata] lock-version = "2.1" python-versions = ">=3.12,<4.0" -content-hash = "8493615b34d707f5955454b9188bd21294fe41cd77b08883b1266e48414dcb51" +content-hash = "912d4156e14111ffaef1793ddc85859099bab225ab2356b768115e9e8d8fae78" diff --git a/pyproject.toml b/pyproject.toml index 8155e6d..cb2cc28 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,8 +14,8 @@ dependencies = [ "jsonschema>=4.24.0", "packaging>=26.2", "shapely>=2.1.2", - "stac-fastapi.types>=6.0.0", - "stac-fastapi.extensions>=6.0.0", + "stac-fastapi.types>=6.3.0", + "stac-fastapi.extensions>=6.3.0", "uvicorn>=0.46.0", ] diff --git a/src/client.py b/src/client.py index 4ef26d1..874d79c 100644 --- a/src/client.py +++ b/src/client.py @@ -27,8 +27,8 @@ ) from esgf_core_utils.models.kafka.producer import KafkaProducer from fastapi import Request, Response, status -from stac_fastapi.extensions.core.transaction import BaseTransactionsClient -from stac_fastapi.extensions.core.transaction.request import PartialItem, PatchOperation +from stac_fastapi.extensions.transaction import BaseTransactionsClient +from stac_fastapi.extensions.transaction.request import PartialItem, PatchOperation from stac_fastapi.types.stac import Collection from stac_pydantic.item import Item diff --git a/src/utils.py b/src/utils.py index 253e552..fd4eb66 100644 --- a/src/utils.py +++ b/src/utils.py @@ -13,7 +13,7 @@ ) from jsonschema.protocols import Validator from shapely.geometry import shape -from stac_fastapi.extensions.core.transaction.request import ( +from stac_fastapi.extensions.transaction.request import ( PartialItem, PatchAddReplaceTest, PatchOperation, From ab6f67984586e0011caa35240eb921943506be54 Mon Sep 17 00:00:00 2001 From: rhysrevans3 Date: Tue, 23 Jun 2026 11:42:58 +0100 Subject: [PATCH 19/35] Update import. --- src/api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api.py b/src/api.py index b571a1f..dc7bc66 100644 --- a/src/api.py +++ b/src/api.py @@ -1,7 +1,7 @@ from esgf_core_utils.models.exceptions import RFC9457Exception from fastapi import FastAPI, Request from fastapi.responses import JSONResponse -from stac_fastapi.extensions.core.transaction import TransactionExtension +from stac_fastapi.extensions import TransactionExtension from stac_fastapi.types.config import ApiSettings from authorizer import Authorizer From c7f7831597b8dd0896f6469470314480b4c87c0f Mon Sep 17 00:00:00 2001 From: rhysrevans3 Date: Tue, 23 Jun 2026 12:41:20 +0100 Subject: [PATCH 20/35] Update logging for egi authorizer. --- src/authorizer/egi_authorizer.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/authorizer/egi_authorizer.py b/src/authorizer/egi_authorizer.py index f61c075..7bc9417 100644 --- a/src/authorizer/egi_authorizer.py +++ b/src/authorizer/egi_authorizer.py @@ -31,7 +31,7 @@ async def dispatch(self, request: Request, call_next): if request.url.path in ["/healthcheck", "/scope"]: return await call_next(request) - logger.info("Request Headers %s", request.headers) + logger.debug("Request Headers %s", request.headers) auth = httpx.BasicAuth( username=settings.client.client_id, @@ -39,7 +39,7 @@ async def dispatch(self, request: Request, call_next): ) async with httpx.AsyncClient(timeout=5.0, verify=False) as client: - logger.info( + logger.debug( "Post request to %s", settings.client.introspection_endpoint, ) @@ -54,6 +54,8 @@ async def dispatch(self, request: Request, call_next): token_info = response.json() + logger.debug("Token info: %s", token_info) + authorizer = EGIAuth( regex=settings.client.regex, requester_data=RequesterData( From 93097d66816111207cdd0c92ff2d571ce96a9811 Mon Sep 17 00:00:00 2001 From: rhysrevans3 Date: Tue, 23 Jun 2026 13:02:52 +0100 Subject: [PATCH 21/35] Set logging level in api. --- src/api.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/api.py b/src/api.py index dc7bc66..154e1bf 100644 --- a/src/api.py +++ b/src/api.py @@ -1,3 +1,5 @@ +import logging + from esgf_core_utils.models.exceptions import RFC9457Exception from fastapi import FastAPI, Request from fastapi.responses import JSONResponse @@ -8,6 +10,9 @@ from client import TransactionClient from settings import settings +logger = logging.getLogger("uvicorn.error") +logger.setLevel(logging.DEBUG if settings.debug else logging.INFO) + app = FastAPI(debug=settings.debug) From 119da8777e9ebd9a644897e81995adc1493d1de1 Mon Sep 17 00:00:00 2001 From: rhysrevans3 Date: Tue, 23 Jun 2026 13:34:30 +0100 Subject: [PATCH 22/35] Add EGI audience check. --- src/authorizer/egi_authorizer.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/authorizer/egi_authorizer.py b/src/authorizer/egi_authorizer.py index 7bc9417..7d93c0d 100644 --- a/src/authorizer/egi_authorizer.py +++ b/src/authorizer/egi_authorizer.py @@ -2,6 +2,7 @@ import httpx from esgf_core_utils.models.auth.egi import EGIAuth +from esgf_core_utils.models.exceptions import InvalidTokenAudienceException from esgf_core_utils.models.kafka.events import RequesterData from fastapi import Request from starlette.middleware.base import BaseHTTPMiddleware @@ -54,6 +55,12 @@ async def dispatch(self, request: Request, call_next): token_info = response.json() + if request.headers["host"] not in token_info["aud"]: + raise InvalidTokenAudienceException( + token_audience=request.headers["host"], + expected_audience=", ".join(token_info["aud"]), + ) + logger.debug("Token info: %s", token_info) authorizer = EGIAuth( From 6858116d014e7187733aac054dc85bb4dd5ee24e Mon Sep 17 00:00:00 2001 From: rhysrevans3 Date: Tue, 23 Jun 2026 13:55:58 +0100 Subject: [PATCH 23/35] Add healthcheck log filtering. --- src/api.py | 8 ++++++++ src/client.py | 51 +++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 47 insertions(+), 12 deletions(-) diff --git a/src/api.py b/src/api.py index 154e1bf..cafe2c2 100644 --- a/src/api.py +++ b/src/api.py @@ -13,6 +13,14 @@ logger = logging.getLogger("uvicorn.error") logger.setLevel(logging.DEBUG if settings.debug else logging.INFO) + +class HealthCheckFilter(logging.Filter): + def filter(self, record): + return "/healthcheck" not in record.getMessage() + + +logging.getLogger("uvicorn.access").addFilter(HealthCheckFilter()) + app = FastAPI(debug=settings.debug) diff --git a/src/client.py b/src/client.py index 874d79c..7ac087c 100644 --- a/src/client.py +++ b/src/client.py @@ -43,6 +43,7 @@ # Setup logger # logger = logging.getLogger(__name__) logger = logging.getLogger("uvicorn.error") +logger.setLevel(logging.DEBUG) class TransactionClient(BaseTransactionsClient): @@ -65,7 +66,9 @@ def allowed_groups(self, properties, acp) -> list: return groups return [] - def globus_authorize(self, item: Item, request: Request, collection_id: str) -> dict: + def globus_authorize( + self, item: Item, request: Request, collection_id: str + ) -> dict: properties = item.properties if item.collection != collection_id: @@ -73,7 +76,9 @@ def globus_authorize(self, item: Item, request: Request, collection_id: str) -> if getattr(properties, "project", None) != collection_id: raise ValueError("Item project must match path collection_id") - allowed_groups = self.allowed_groups(properties, settings.client.access_control_policy) + allowed_groups = self.allowed_groups( + properties, settings.client.access_control_policy + ) allowed_groups_uuid = [g.get("uuid") for g in allowed_groups] authorizer = request.state.authorizer @@ -90,7 +95,9 @@ def globus_authorize(self, item: Item, request: Request, collection_id: str) -> } ) if not authorized_identities: - raise MissingPermissionException(permission_type="globus", target=collection_id) + raise MissingPermissionException( + permission_type="globus", target=collection_id + ) requester_data = RequesterData( client_id=token_info.get("client_id"), @@ -151,7 +158,9 @@ def authorize( ) -> Auth: if settings.authorizer == "globus": - return self.globus_authorize(collection_id=collection_id, item=item, request=request) + return self.globus_authorize( + collection_id=collection_id, item=item, request=request + ) else: return self.egi_authorize( collection_id=collection_id, @@ -189,7 +198,9 @@ async def create_item( item_extensions = item.stac_extensions if item.stac_extensions else [] try: - item_extensions = validate_extensions(collection_id=collection_id, item_extensions=item_extensions) + item_extensions = validate_extensions( + collection_id=collection_id, item_extensions=item_extensions + ) validate_post( event_id=event_id, request_id=request_id, @@ -221,7 +232,9 @@ async def create_item( data = Data(type="STAC", payload=payload) - publisher = Publisher(package=user_agent[0], version=user_agent[1] if len(user_agent) > 1 else "") + publisher = Publisher( + package=user_agent[0], version=user_agent[1] if len(user_agent) > 1 else "" + ) metadata = Metadata( auth=auth, @@ -272,7 +285,9 @@ async def update_item( item_extensions = item.stac_extensions if item.stac_extensions else [] - item_extensions = validate_extensions(collection_id=collection_id, item_extensions=item_extensions) + item_extensions = validate_extensions( + collection_id=collection_id, item_extensions=item_extensions + ) validate_post( event_id=event_id, @@ -293,7 +308,9 @@ async def update_item( data = Data(type="STAC", payload=payload) - publisher = Publisher(package=user_agent[0], version=user_agent[1] if len(user_agent) > 1 else "") + publisher = Publisher( + package=user_agent[0], version=user_agent[1] if len(user_agent) > 1 else "" + ) metadata = Metadata( auth=auth, event_id=event_id, @@ -328,7 +345,11 @@ async def patch_item( ) -> Optional[Union[Item, Response]]: logger.info("PATCH REQUEST: %s", patch) - item = operation_to_partial_item(collection_id=collection_id, operations=patch) if isinstance(patch, list) else patch + item = ( + operation_to_partial_item(collection_id=collection_id, operations=patch) + if isinstance(patch, list) + else patch + ) headers = request.headers.get("headers", {}) @@ -346,7 +367,9 @@ async def patch_item( item_extensions = item.stac_extensions if item.stac_extensions else [] - item_extensions = validate_extensions(collection_id=collection_id, item_extensions=item_extensions) + item_extensions = validate_extensions( + collection_id=collection_id, item_extensions=item_extensions + ) validate_patch( event_id=event_id, @@ -367,7 +390,9 @@ async def patch_item( data = Data(type="STAC", payload=payload) - publisher = Publisher(package=user_agent[0], version=user_agent[1] if len(user_agent) > 1 else "") + publisher = Publisher( + package=user_agent[0], version=user_agent[1] if len(user_agent) > 1 else "" + ) metadata = Metadata( auth=auth, event_id=event_id, @@ -426,7 +451,9 @@ async def delete_item( data = Data(type="STAC", payload=payload) - publisher = Publisher(package=user_agent[0], version=user_agent[1] if len(user_agent) > 1 else "") + publisher = Publisher( + package=user_agent[0], version=user_agent[1] if len(user_agent) > 1 else "" + ) metadata = Metadata( auth=auth, From 168c9787dbff5b06c516ccf80cb8eabee739198d Mon Sep 17 00:00:00 2001 From: rhysrevans3 Date: Wed, 24 Jun 2026 12:41:09 +0100 Subject: [PATCH 24/35] Update to use common Authorizer for EGIAuthorizer. --- src/authorizer/egi_authorizer.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/authorizer/egi_authorizer.py b/src/authorizer/egi_authorizer.py index 7d93c0d..d911724 100644 --- a/src/authorizer/egi_authorizer.py +++ b/src/authorizer/egi_authorizer.py @@ -1,7 +1,7 @@ import logging import httpx -from esgf_core_utils.models.auth.egi import EGIAuth +from esgf_core_utils.models.auth import Authorizer from esgf_core_utils.models.exceptions import InvalidTokenAudienceException from esgf_core_utils.models.kafka.events import RequesterData from fastapi import Request @@ -63,7 +63,7 @@ async def dispatch(self, request: Request, call_next): logger.debug("Token info: %s", token_info) - authorizer = EGIAuth( + authorizer = Authorizer( regex=settings.client.regex, requester_data=RequesterData( client_id=token_info["client_id"], From a98a3a85a6d6501dd24c5026a04b52e0fc3ab743 Mon Sep 17 00:00:00 2001 From: rhysrevans3 Date: Wed, 24 Jun 2026 13:13:44 +0100 Subject: [PATCH 25/35] Remove unneeded event and request id from validation. --- src/client.py | 6 ------ src/utils.py | 58 +++++++++++++++++++++++++++++++++++---------------- 2 files changed, 40 insertions(+), 24 deletions(-) diff --git a/src/client.py b/src/client.py index 7ac087c..39a3f87 100644 --- a/src/client.py +++ b/src/client.py @@ -202,8 +202,6 @@ async def create_item( collection_id=collection_id, item_extensions=item_extensions ) validate_post( - event_id=event_id, - request_id=request_id, item_id=item.id, item=item, extensions=item_extensions, @@ -290,8 +288,6 @@ async def update_item( ) validate_post( - event_id=event_id, - request_id=request_id, item_id=item.id, item=item, extensions=item_extensions, @@ -372,8 +368,6 @@ async def patch_item( ) validate_patch( - event_id=event_id, - request_id=request_id, item_id=item_id, item=item, extensions=item_extensions, diff --git a/src/utils.py b/src/utils.py index fd4eb66..91dedaf 100644 --- a/src/utils.py +++ b/src/utils.py @@ -6,12 +6,13 @@ import jsonschema from esgf_core_utils.models.exceptions import ( ExpectedExtensionsMissingException, + ExtensionBelowMinimumException, OperationNotPermittedException, STACValidationException, UnexpectedExtensionException, - ExtensionBelowMinimumException, ) from jsonschema.protocols import Validator +from packaging.version import Version from shapely.geometry import shape from stac_fastapi.extensions.transaction.request import ( PartialItem, @@ -19,14 +20,16 @@ PatchOperation, ) from stac_pydantic.item import Item -from packaging.version import Version + from settings import DEFAULT_EXTENSIONS, VERSION_REGEX # Setup logger logger = logging.getLogger("uvicorn.error") -def operation_to_partial_item(collection_id: str, operations: list[PatchOperation]) -> PartialItem: +def operation_to_partial_item( + collection_id: str, operations: list[PatchOperation] +) -> PartialItem: """Convert operations to partial item Args: @@ -98,10 +101,14 @@ def validate_extension_version(minimum: str, extension: str) -> None: extension_version = VERSION_REGEX.search(minimum).group(1) if Version(extension_version) < Version(minimum_version): - raise ExtensionBelowMinimumException(extension=extension, minimum_version=f"v{minimum_version}") + raise ExtensionBelowMinimumException( + extension=extension, minimum_version=f"v{minimum_version}" + ) -def validate_extensions(collection_id: str, item_extensions: list[str], strict: bool = False) -> list[str]: +def validate_extensions( + collection_id: str, item_extensions: list[str], strict: bool = False +) -> list[str]: """Validate expected default extensions are present. Args: @@ -125,16 +132,24 @@ def validate_extensions(collection_id: str, item_extensions: list[str], strict: expected_extension_key, expected_extension, ) in expected_extensions.copy().items(): - if any(re.compile(regex).match(str(item_extension)) for regex in expected_extension["regex"]): + if any( + re.compile(regex).match(str(item_extension)) + for regex in expected_extension["regex"] + ): expected_extensions.pop(expected_extension_key) expected = True - validate_extension_version(minimum=expected_extension["default"], extension=str(item_extension)) + validate_extension_version( + minimum=expected_extension["default"], extension=str(item_extension) + ) if not expected: raise UnexpectedExtensionException(extension=item_extension) - missing_extensions = [expected_extension["default"] for expected_extension in expected_extensions.values()] + missing_extensions = [ + expected_extension["default"] + for expected_extension in expected_extensions.values() + ] if strict & len(missing_extensions) > 0: raise ExpectedExtensionsMissingException(extensions=missing_extensions) @@ -202,7 +217,12 @@ def validate_bbox(bbox: list[int | float]) -> None: STACValidationException: _description_ """ minx, miny, maxx, maxy = bbox[:4] - if not (-180.0 <= minx <= 180.0 and -180.0 <= maxx <= 180.0 and -90.0 <= miny <= 90.0 and -90.0 <= maxy <= 90.0): + if not ( + -180.0 <= minx <= 180.0 + and -180.0 <= maxx <= 180.0 + and -90.0 <= miny <= 90.0 + and -90.0 <= maxy <= 90.0 + ): raise STACValidationException() @@ -252,7 +272,9 @@ def validate_patch( required_keys = set() raise_errors = [] - for error in extension_validator.iter_errors(json.loads(item.model_dump_json())): + for error in extension_validator.iter_errors( + json.loads(item.model_dump_json()) + ): if error.validator in ["oneOf"]: continue @@ -264,17 +286,17 @@ def validate_patch( raise_errors.append(error) for null_key_error in required_keys & null_keys: - raise_errors.append(f"Variable {null_key_error} is required and cannot be removed") + raise_errors.append( + f"Variable {null_key_error} is required and cannot be removed" + ) if raise_errors: - logger.error(f"STAC validation error: {item_id}") + logger.error("STAC validation error: %s", item_id) raise STACValidationException() def validate_post( - event_id: str, - request_id: str, item_id: str, item: Item, extensions: list[str], @@ -282,8 +304,6 @@ def validate_post( """Validate a Item post request Args: - event_id (str): ID of the Kafka event - request_id (str): ID of the request item_id (str): ID of the item to validate item (Item): Partial Item to be validated to validate extensions (list[str]): List of STAC extensions to be validated against @@ -298,10 +318,12 @@ def validate_post( extension_validator = get_extension_validator(str(extension)) raise_errors = [] - for error in extension_validator.iter_errors(json.loads(item.model_dump_json())): + for error in extension_validator.iter_errors( + json.loads(item.model_dump_json()) + ): raise_errors.append(error) if raise_errors: - logger.error(f"STAC validation error: {item_id}") + logger.error("STAC validation error: %s", item_id) raise STACValidationException() From 81e8d2df2ebdd42b9140925bc119aac321716f42 Mon Sep 17 00:00:00 2001 From: rhysrevans3 Date: Wed, 24 Jun 2026 13:15:47 +0100 Subject: [PATCH 26/35] EGIAuth to Authorizer. --- src/client.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/client.py b/src/client.py index 39a3f87..68a03ce 100644 --- a/src/client.py +++ b/src/client.py @@ -3,7 +3,7 @@ from datetime import datetime from typing import Optional, Union -from esgf_core_utils.models.auth.egi import EGIAuth +from esgf_core_utils.models.auth import Authorizer from esgf_core_utils.models.exceptions import ( AuthorizationException, ExpectedExtensionsMissingException, @@ -132,7 +132,7 @@ def egi_authorize( Returns: Auth: Auth object if successful """ - authorizer: EGIAuth = request.state.authorizer + authorizer: Authorizer = request.state.authorizer authorizer.authorize( collection_id=collection_id, item=item, From ae08ad42496880b44f1307d78a1ff42da5148dc8 Mon Sep 17 00:00:00 2001 From: rhysrevans3 Date: Wed, 24 Jun 2026 13:54:52 +0100 Subject: [PATCH 27/35] pre-commit. --- src/client.py | 50 ++++++++++++-------------------------------------- src/utils.py | 45 ++++++++++----------------------------------- 2 files changed, 22 insertions(+), 73 deletions(-) diff --git a/src/client.py b/src/client.py index 68a03ce..c126899 100644 --- a/src/client.py +++ b/src/client.py @@ -66,9 +66,7 @@ def allowed_groups(self, properties, acp) -> list: return groups return [] - def globus_authorize( - self, item: Item, request: Request, collection_id: str - ) -> dict: + def globus_authorize(self, item: Item, request: Request, collection_id: str) -> dict: properties = item.properties if item.collection != collection_id: @@ -76,9 +74,7 @@ def globus_authorize( if getattr(properties, "project", None) != collection_id: raise ValueError("Item project must match path collection_id") - allowed_groups = self.allowed_groups( - properties, settings.client.access_control_policy - ) + allowed_groups = self.allowed_groups(properties, settings.client.access_control_policy) allowed_groups_uuid = [g.get("uuid") for g in allowed_groups] authorizer = request.state.authorizer @@ -95,9 +91,7 @@ def globus_authorize( } ) if not authorized_identities: - raise MissingPermissionException( - permission_type="globus", target=collection_id - ) + raise MissingPermissionException(permission_type="globus", target=collection_id) requester_data = RequesterData( client_id=token_info.get("client_id"), @@ -158,9 +152,7 @@ def authorize( ) -> Auth: if settings.authorizer == "globus": - return self.globus_authorize( - collection_id=collection_id, item=item, request=request - ) + return self.globus_authorize(collection_id=collection_id, item=item, request=request) else: return self.egi_authorize( collection_id=collection_id, @@ -198,9 +190,7 @@ async def create_item( item_extensions = item.stac_extensions if item.stac_extensions else [] try: - item_extensions = validate_extensions( - collection_id=collection_id, item_extensions=item_extensions - ) + item_extensions = validate_extensions(collection_id=collection_id, item_extensions=item_extensions) validate_post( item_id=item.id, item=item, @@ -230,9 +220,7 @@ async def create_item( data = Data(type="STAC", payload=payload) - publisher = Publisher( - package=user_agent[0], version=user_agent[1] if len(user_agent) > 1 else "" - ) + publisher = Publisher(package=user_agent[0], version=user_agent[1] if len(user_agent) > 1 else "") metadata = Metadata( auth=auth, @@ -283,9 +271,7 @@ async def update_item( item_extensions = item.stac_extensions if item.stac_extensions else [] - item_extensions = validate_extensions( - collection_id=collection_id, item_extensions=item_extensions - ) + item_extensions = validate_extensions(collection_id=collection_id, item_extensions=item_extensions) validate_post( item_id=item.id, @@ -304,9 +290,7 @@ async def update_item( data = Data(type="STAC", payload=payload) - publisher = Publisher( - package=user_agent[0], version=user_agent[1] if len(user_agent) > 1 else "" - ) + publisher = Publisher(package=user_agent[0], version=user_agent[1] if len(user_agent) > 1 else "") metadata = Metadata( auth=auth, event_id=event_id, @@ -341,11 +325,7 @@ async def patch_item( ) -> Optional[Union[Item, Response]]: logger.info("PATCH REQUEST: %s", patch) - item = ( - operation_to_partial_item(collection_id=collection_id, operations=patch) - if isinstance(patch, list) - else patch - ) + item = operation_to_partial_item(collection_id=collection_id, operations=patch) if isinstance(patch, list) else patch headers = request.headers.get("headers", {}) @@ -363,9 +343,7 @@ async def patch_item( item_extensions = item.stac_extensions if item.stac_extensions else [] - item_extensions = validate_extensions( - collection_id=collection_id, item_extensions=item_extensions - ) + item_extensions = validate_extensions(collection_id=collection_id, item_extensions=item_extensions) validate_patch( item_id=item_id, @@ -384,9 +362,7 @@ async def patch_item( data = Data(type="STAC", payload=payload) - publisher = Publisher( - package=user_agent[0], version=user_agent[1] if len(user_agent) > 1 else "" - ) + publisher = Publisher(package=user_agent[0], version=user_agent[1] if len(user_agent) > 1 else "") metadata = Metadata( auth=auth, event_id=event_id, @@ -445,9 +421,7 @@ async def delete_item( data = Data(type="STAC", payload=payload) - publisher = Publisher( - package=user_agent[0], version=user_agent[1] if len(user_agent) > 1 else "" - ) + publisher = Publisher(package=user_agent[0], version=user_agent[1] if len(user_agent) > 1 else "") metadata = Metadata( auth=auth, diff --git a/src/utils.py b/src/utils.py index 91dedaf..95d6d52 100644 --- a/src/utils.py +++ b/src/utils.py @@ -27,9 +27,7 @@ logger = logging.getLogger("uvicorn.error") -def operation_to_partial_item( - collection_id: str, operations: list[PatchOperation] -) -> PartialItem: +def operation_to_partial_item(collection_id: str, operations: list[PatchOperation]) -> PartialItem: """Convert operations to partial item Args: @@ -101,14 +99,10 @@ def validate_extension_version(minimum: str, extension: str) -> None: extension_version = VERSION_REGEX.search(minimum).group(1) if Version(extension_version) < Version(minimum_version): - raise ExtensionBelowMinimumException( - extension=extension, minimum_version=f"v{minimum_version}" - ) + raise ExtensionBelowMinimumException(extension=extension, minimum_version=f"v{minimum_version}") -def validate_extensions( - collection_id: str, item_extensions: list[str], strict: bool = False -) -> list[str]: +def validate_extensions(collection_id: str, item_extensions: list[str], strict: bool = False) -> list[str]: """Validate expected default extensions are present. Args: @@ -132,24 +126,16 @@ def validate_extensions( expected_extension_key, expected_extension, ) in expected_extensions.copy().items(): - if any( - re.compile(regex).match(str(item_extension)) - for regex in expected_extension["regex"] - ): + if any(re.compile(regex).match(str(item_extension)) for regex in expected_extension["regex"]): expected_extensions.pop(expected_extension_key) expected = True - validate_extension_version( - minimum=expected_extension["default"], extension=str(item_extension) - ) + validate_extension_version(minimum=expected_extension["default"], extension=str(item_extension)) if not expected: raise UnexpectedExtensionException(extension=item_extension) - missing_extensions = [ - expected_extension["default"] - for expected_extension in expected_extensions.values() - ] + missing_extensions = [expected_extension["default"] for expected_extension in expected_extensions.values()] if strict & len(missing_extensions) > 0: raise ExpectedExtensionsMissingException(extensions=missing_extensions) @@ -217,12 +203,7 @@ def validate_bbox(bbox: list[int | float]) -> None: STACValidationException: _description_ """ minx, miny, maxx, maxy = bbox[:4] - if not ( - -180.0 <= minx <= 180.0 - and -180.0 <= maxx <= 180.0 - and -90.0 <= miny <= 90.0 - and -90.0 <= maxy <= 90.0 - ): + if not (-180.0 <= minx <= 180.0 and -180.0 <= maxx <= 180.0 and -90.0 <= miny <= 90.0 and -90.0 <= maxy <= 90.0): raise STACValidationException() @@ -272,9 +253,7 @@ def validate_patch( required_keys = set() raise_errors = [] - for error in extension_validator.iter_errors( - json.loads(item.model_dump_json()) - ): + for error in extension_validator.iter_errors(json.loads(item.model_dump_json())): if error.validator in ["oneOf"]: continue @@ -286,9 +265,7 @@ def validate_patch( raise_errors.append(error) for null_key_error in required_keys & null_keys: - raise_errors.append( - f"Variable {null_key_error} is required and cannot be removed" - ) + raise_errors.append(f"Variable {null_key_error} is required and cannot be removed") if raise_errors: logger.error("STAC validation error: %s", item_id) @@ -318,9 +295,7 @@ def validate_post( extension_validator = get_extension_validator(str(extension)) raise_errors = [] - for error in extension_validator.iter_errors( - json.loads(item.model_dump_json()) - ): + for error in extension_validator.iter_errors(json.loads(item.model_dump_json())): raise_errors.append(error) if raise_errors: From 024e460cbba58c6971c1a0fe0356f60adcba025f Mon Sep 17 00:00:00 2001 From: rhysrevans3 Date: Wed, 24 Jun 2026 14:38:59 +0100 Subject: [PATCH 28/35] Bump version. --- pyproject.toml | 4 +-- src/api.py | 2 +- test/stac_client.py | 62 ++++++++++++++++++++++++++++++++++----------- 3 files changed, 50 insertions(+), 18 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index cb2cc28..a9d0a4a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,8 +1,8 @@ [project] name = "stac-transaction-api" requires-python = ">=3.12,<4.0" -description = "West ESGF STAC Transaction API" -version = "0.1.0" +description = "ESGF STAC Transaction API" +version = "0.2.0" authors = [ {"name" = "Lukasz Lacinski", "email" = "lukasz@uchicago.edu"}, {"name" = "Steve Turoscy", "email" = "sturoscy@uchicago.edu"}, diff --git a/src/api.py b/src/api.py index cafe2c2..96732a3 100644 --- a/src/api.py +++ b/src/api.py @@ -63,7 +63,7 @@ async def rfc9457_handler(request: Request, exc: RFC9457Exception): api_settings = ApiSettings( api_title="STAC Transaction API", - api_version="0.1.0", + api_version="0.2.0", openapi_url="/openapi.json", ) diff --git a/test/stac_client.py b/test/stac_client.py index f732cee..3ece333 100644 --- a/test/stac_client.py +++ b/test/stac_client.py @@ -1,11 +1,17 @@ import os -from globus_sdk import NativeAppAuthClient, RefreshTokenAuthorizer, BaseClient, GroupsClient + +from globus_sdk import ( + BaseClient, + GroupsClient, + NativeAppAuthClient, + RefreshTokenAuthorizer, +) from globus_sdk.scopes import GroupsScopes from globus_sdk.tokenstorage import SimpleJSONFileAdapter -from settings import STAC_CLIENT, TOKEN_STORAGE_FILE, STAC_TRANSACTION_API +from settings import STAC_CLIENT, STAC_TRANSACTION_API, TOKEN_STORAGE_FILE -__version__ = "0.1.0" +__version__ = "0.2.0" class TransactionClient: @@ -14,12 +20,20 @@ def __init__(self, stac_api=None, verbose=False, silent=False): self.stac_api = stac_api else: self.stac_api = STAC_TRANSACTION_API.get("base_url") - self.scopes = [GroupsScopes.view_my_groups_and_memberships, STAC_TRANSACTION_API.get("scope_string")] - self.auth_client = NativeAppAuthClient(client_id=STAC_CLIENT.get("client_id"), app_name="ESGF2 STAC Transaction API") + self.scopes = [ + GroupsScopes.view_my_groups_and_memberships, + STAC_TRANSACTION_API.get("scope_string"), + ] + self.auth_client = NativeAppAuthClient( + client_id=STAC_CLIENT.get("client_id"), + app_name="ESGF2 STAC Transaction API", + ) self._create_clients() def _do_login_flow(self): - self.auth_client.oauth2_start_flow(requested_scopes=self.scopes, refresh_tokens=True) + self.auth_client.oauth2_start_flow( + requested_scopes=self.scopes, refresh_tokens=True + ) authorize_url = self.auth_client.oauth2_get_authorize_url() print("Please go to this URL and login: {0}".format(authorize_url)) auth_code = input("Please enter the code here: ").strip() @@ -31,11 +45,19 @@ def _create_clients(self): if not token_storage.file_exists(): response = self._do_login_flow() token_storage.store(response) - self.groups_tokens = response.by_resource_server[GroupsClient.resource_server] - self.transaction_tokens = response.by_resource_server[STAC_TRANSACTION_API.get("client_id")] + self.groups_tokens = response.by_resource_server[ + GroupsClient.resource_server + ] + self.transaction_tokens = response.by_resource_server[ + STAC_TRANSACTION_API.get("client_id") + ] else: - self.groups_tokens = token_storage.get_token_data(GroupsClient.resource_server) - self.transaction_tokens = token_storage.get_token_data(STAC_TRANSACTION_API.get("client_id")) + self.groups_tokens = token_storage.get_token_data( + GroupsClient.resource_server + ) + self.transaction_tokens = token_storage.get_token_data( + STAC_TRANSACTION_API.get("client_id") + ) groups_authorizer = RefreshTokenAuthorizer( self.groups_tokens["refresh_token"], @@ -53,7 +75,9 @@ def _create_clients(self): expires_at=self.transaction_tokens["expires_at_seconds"], on_refresh=token_storage.on_refresh, ) - self.transaction_client = BaseClient(base_url=self.stac_api, authorizer=transaction_authorizer) + self.transaction_client = BaseClient( + base_url=self.stac_api, authorizer=transaction_authorizer + ) def get_my_groups(self): groups = self.groups_client.get_my_groups() @@ -64,7 +88,9 @@ def post(self, entry): headers = { "User-Agent": f"test_client/{__version__}", } - resp = self.transaction_client.post(f"/collections/{collection}/items", headers=headers, data=entry) + resp = self.transaction_client.post( + f"/collections/{collection}/items", headers=headers, data=entry + ) if resp.http_status == 201: print(resp.http_status) print("Published (POST)") @@ -83,7 +109,9 @@ def put(self, entry): headers = { "User-Agent": f"test_client/{__version__}", } - resp = self.transaction_client.put(f"/collections/{collection}/items/{item_id}", headers=headers, data=entry) + resp = self.transaction_client.put( + f"/collections/{collection}/items/{item_id}", headers=headers, data=entry + ) if resp.http_status == 201: print(resp.http_status) print("Updated (PUT)") @@ -107,7 +135,9 @@ def json_patch(self, collection, item_id, entry): "Content-Type": "application/json-patch+json", "User-Agent": f"test_client/{__version__}", } - resp = self.transaction_client.patch(f"/collections/{collection}/items/{item_id}", headers=headers, data=entry) + resp = self.transaction_client.patch( + f"/collections/{collection}/items/{item_id}", headers=headers, data=entry + ) if resp.http_status == 201: print(resp.http_status) print("Updated (JSON PATCH)") @@ -130,7 +160,9 @@ def merge_patch(self, collection, item_id, entry): "Content-Type": "application/merge-patch+json", "User-Agent": f"test_client/{__version__}", } - resp = self.transaction_client.patch(f"/collections/{collection}/items/{item_id}", headers=headers, data=entry) + resp = self.transaction_client.patch( + f"/collections/{collection}/items/{item_id}", headers=headers, data=entry + ) if resp.http_status == 201: print(resp.http_status) print("Updated (MERGE PATCH)") From 5e6a37fb216c1c7cbe5a57b4a94edaf75e2f657a Mon Sep 17 00:00:00 2001 From: rhysrevans3 Date: Wed, 24 Jun 2026 14:39:51 +0100 Subject: [PATCH 29/35] pre-commit. --- test/stac_client.py | 40 ++++++++++------------------------------ 1 file changed, 10 insertions(+), 30 deletions(-) diff --git a/test/stac_client.py b/test/stac_client.py index 3ece333..ee9b4a1 100644 --- a/test/stac_client.py +++ b/test/stac_client.py @@ -31,9 +31,7 @@ def __init__(self, stac_api=None, verbose=False, silent=False): self._create_clients() def _do_login_flow(self): - self.auth_client.oauth2_start_flow( - requested_scopes=self.scopes, refresh_tokens=True - ) + self.auth_client.oauth2_start_flow(requested_scopes=self.scopes, refresh_tokens=True) authorize_url = self.auth_client.oauth2_get_authorize_url() print("Please go to this URL and login: {0}".format(authorize_url)) auth_code = input("Please enter the code here: ").strip() @@ -45,19 +43,11 @@ def _create_clients(self): if not token_storage.file_exists(): response = self._do_login_flow() token_storage.store(response) - self.groups_tokens = response.by_resource_server[ - GroupsClient.resource_server - ] - self.transaction_tokens = response.by_resource_server[ - STAC_TRANSACTION_API.get("client_id") - ] + self.groups_tokens = response.by_resource_server[GroupsClient.resource_server] + self.transaction_tokens = response.by_resource_server[STAC_TRANSACTION_API.get("client_id")] else: - self.groups_tokens = token_storage.get_token_data( - GroupsClient.resource_server - ) - self.transaction_tokens = token_storage.get_token_data( - STAC_TRANSACTION_API.get("client_id") - ) + self.groups_tokens = token_storage.get_token_data(GroupsClient.resource_server) + self.transaction_tokens = token_storage.get_token_data(STAC_TRANSACTION_API.get("client_id")) groups_authorizer = RefreshTokenAuthorizer( self.groups_tokens["refresh_token"], @@ -75,9 +65,7 @@ def _create_clients(self): expires_at=self.transaction_tokens["expires_at_seconds"], on_refresh=token_storage.on_refresh, ) - self.transaction_client = BaseClient( - base_url=self.stac_api, authorizer=transaction_authorizer - ) + self.transaction_client = BaseClient(base_url=self.stac_api, authorizer=transaction_authorizer) def get_my_groups(self): groups = self.groups_client.get_my_groups() @@ -88,9 +76,7 @@ def post(self, entry): headers = { "User-Agent": f"test_client/{__version__}", } - resp = self.transaction_client.post( - f"/collections/{collection}/items", headers=headers, data=entry - ) + resp = self.transaction_client.post(f"/collections/{collection}/items", headers=headers, data=entry) if resp.http_status == 201: print(resp.http_status) print("Published (POST)") @@ -109,9 +95,7 @@ def put(self, entry): headers = { "User-Agent": f"test_client/{__version__}", } - resp = self.transaction_client.put( - f"/collections/{collection}/items/{item_id}", headers=headers, data=entry - ) + resp = self.transaction_client.put(f"/collections/{collection}/items/{item_id}", headers=headers, data=entry) if resp.http_status == 201: print(resp.http_status) print("Updated (PUT)") @@ -135,9 +119,7 @@ def json_patch(self, collection, item_id, entry): "Content-Type": "application/json-patch+json", "User-Agent": f"test_client/{__version__}", } - resp = self.transaction_client.patch( - f"/collections/{collection}/items/{item_id}", headers=headers, data=entry - ) + resp = self.transaction_client.patch(f"/collections/{collection}/items/{item_id}", headers=headers, data=entry) if resp.http_status == 201: print(resp.http_status) print("Updated (JSON PATCH)") @@ -160,9 +142,7 @@ def merge_patch(self, collection, item_id, entry): "Content-Type": "application/merge-patch+json", "User-Agent": f"test_client/{__version__}", } - resp = self.transaction_client.patch( - f"/collections/{collection}/items/{item_id}", headers=headers, data=entry - ) + resp = self.transaction_client.patch(f"/collections/{collection}/items/{item_id}", headers=headers, data=entry) if resp.http_status == 201: print(resp.http_status) print("Updated (MERGE PATCH)") From 2c1fda2b2c0673afbc1322c744b345da4fc28c7d Mon Sep 17 00:00:00 2001 From: rhysrevans3 Date: Wed, 24 Jun 2026 14:47:18 +0100 Subject: [PATCH 30/35] Bump core utils version. --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index a9d0a4a..6d5da65 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,7 +9,7 @@ authors = [ ] readme = "README.md" dependencies = [ - "esgf-core-utils>=1.0.7", + "esgf-core-utils>=1.1.0", "fastapi>=0.114.0", "jsonschema>=4.24.0", "packaging>=26.2", From 678d3ac433244291c626375e3818c999c7660a58 Mon Sep 17 00:00:00 2001 From: rhysrevans3 Date: Wed, 24 Jun 2026 14:58:14 +0100 Subject: [PATCH 31/35] Move token info log. --- src/authorizer/egi_authorizer.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/authorizer/egi_authorizer.py b/src/authorizer/egi_authorizer.py index d911724..3f6581b 100644 --- a/src/authorizer/egi_authorizer.py +++ b/src/authorizer/egi_authorizer.py @@ -55,14 +55,14 @@ async def dispatch(self, request: Request, call_next): token_info = response.json() + logger.debug("Token info: %s", token_info) + if request.headers["host"] not in token_info["aud"]: raise InvalidTokenAudienceException( token_audience=request.headers["host"], expected_audience=", ".join(token_info["aud"]), ) - logger.debug("Token info: %s", token_info) - authorizer = Authorizer( regex=settings.client.regex, requester_data=RequesterData( From 8e7c1d9f7cd7807fa5ed6e5570067064f2805347 Mon Sep 17 00:00:00 2001 From: rhysrevans3 Date: Wed, 24 Jun 2026 15:09:04 +0100 Subject: [PATCH 32/35] Compare host to audience hostnames. --- src/authorizer/egi_authorizer.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/authorizer/egi_authorizer.py b/src/authorizer/egi_authorizer.py index 3f6581b..0f6d905 100644 --- a/src/authorizer/egi_authorizer.py +++ b/src/authorizer/egi_authorizer.py @@ -1,4 +1,5 @@ import logging +from urllib.parse import urlparse import httpx from esgf_core_utils.models.auth import Authorizer @@ -57,7 +58,9 @@ async def dispatch(self, request: Request, call_next): logger.debug("Token info: %s", token_info) - if request.headers["host"] not in token_info["aud"]: + if request.headers["host"] not in [ + urlparse(aud).hostname for aud in token_info["aud"] + ]: raise InvalidTokenAudienceException( token_audience=request.headers["host"], expected_audience=", ".join(token_info["aud"]), From 5ef1cc871dbd1787fa6425876e620f92a6d99171 Mon Sep 17 00:00:00 2001 From: rhysrevans3 Date: Wed, 24 Jun 2026 15:32:12 +0100 Subject: [PATCH 33/35] Add InvalidTokenAudienceException handler. --- src/api.py | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/api.py b/src/api.py index 96732a3..08478cd 100644 --- a/src/api.py +++ b/src/api.py @@ -1,6 +1,10 @@ import logging +import uuid -from esgf_core_utils.models.exceptions import RFC9457Exception +from esgf_core_utils.models.exceptions import ( + InvalidTokenAudienceException, + RFC9457Exception, +) from fastapi import FastAPI, Request from fastapi.responses import JSONResponse from stac_fastapi.extensions import TransactionExtension @@ -59,6 +63,24 @@ async def rfc9457_handler(request: Request, exc: RFC9457Exception): ) +@app.exception_handler(InvalidTokenAudienceException) +async def invalid_token_audience_handler( + request: Request, exc: InvalidTokenAudienceException +): + event_id = uuid.uuid4().hex + request_id = request.headers.get("x-request-id", uuid.uuid4().hex) + return JSONResponse( + status_code=exc.status_code, + content={ + "status_code": exc.status_code, + "type": exc.type, + "title": exc.title, + "detail": exc.detail, + "instance": f"{request_id}:{event_id}", + }, + ) + + core_client = TransactionClient() api_settings = ApiSettings( From 76d97e355d6d5ea215b3d347fe00ab189f7f61c3 Mon Sep 17 00:00:00 2001 From: rhysrevans3 Date: Wed, 24 Jun 2026 15:52:54 +0100 Subject: [PATCH 34/35] Correct version order. --- src/utils.py | 49 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 37 insertions(+), 12 deletions(-) diff --git a/src/utils.py b/src/utils.py index 95d6d52..be15731 100644 --- a/src/utils.py +++ b/src/utils.py @@ -27,7 +27,9 @@ logger = logging.getLogger("uvicorn.error") -def operation_to_partial_item(collection_id: str, operations: list[PatchOperation]) -> PartialItem: +def operation_to_partial_item( + collection_id: str, operations: list[PatchOperation] +) -> PartialItem: """Convert operations to partial item Args: @@ -95,14 +97,18 @@ def validate_extension_version(minimum: str, extension: str) -> None: ExtensionBelowMinimumException: extension below minimum """ - minimum_version = VERSION_REGEX.search(extension).group(1) - extension_version = VERSION_REGEX.search(minimum).group(1) + minimum_version = VERSION_REGEX.search(minimum).group(1) + extension_version = VERSION_REGEX.search(extension).group(1) if Version(extension_version) < Version(minimum_version): - raise ExtensionBelowMinimumException(extension=extension, minimum_version=f"v{minimum_version}") + raise ExtensionBelowMinimumException( + extension=extension, minimum_version=f"v{minimum_version}" + ) -def validate_extensions(collection_id: str, item_extensions: list[str], strict: bool = False) -> list[str]: +def validate_extensions( + collection_id: str, item_extensions: list[str], strict: bool = False +) -> list[str]: """Validate expected default extensions are present. Args: @@ -126,16 +132,24 @@ def validate_extensions(collection_id: str, item_extensions: list[str], strict: expected_extension_key, expected_extension, ) in expected_extensions.copy().items(): - if any(re.compile(regex).match(str(item_extension)) for regex in expected_extension["regex"]): + if any( + re.compile(regex).match(str(item_extension)) + for regex in expected_extension["regex"] + ): expected_extensions.pop(expected_extension_key) expected = True - validate_extension_version(minimum=expected_extension["default"], extension=str(item_extension)) + validate_extension_version( + minimum=expected_extension["default"], extension=str(item_extension) + ) if not expected: raise UnexpectedExtensionException(extension=item_extension) - missing_extensions = [expected_extension["default"] for expected_extension in expected_extensions.values()] + missing_extensions = [ + expected_extension["default"] + for expected_extension in expected_extensions.values() + ] if strict & len(missing_extensions) > 0: raise ExpectedExtensionsMissingException(extensions=missing_extensions) @@ -203,7 +217,12 @@ def validate_bbox(bbox: list[int | float]) -> None: STACValidationException: _description_ """ minx, miny, maxx, maxy = bbox[:4] - if not (-180.0 <= minx <= 180.0 and -180.0 <= maxx <= 180.0 and -90.0 <= miny <= 90.0 and -90.0 <= maxy <= 90.0): + if not ( + -180.0 <= minx <= 180.0 + and -180.0 <= maxx <= 180.0 + and -90.0 <= miny <= 90.0 + and -90.0 <= maxy <= 90.0 + ): raise STACValidationException() @@ -253,7 +272,9 @@ def validate_patch( required_keys = set() raise_errors = [] - for error in extension_validator.iter_errors(json.loads(item.model_dump_json())): + for error in extension_validator.iter_errors( + json.loads(item.model_dump_json()) + ): if error.validator in ["oneOf"]: continue @@ -265,7 +286,9 @@ def validate_patch( raise_errors.append(error) for null_key_error in required_keys & null_keys: - raise_errors.append(f"Variable {null_key_error} is required and cannot be removed") + raise_errors.append( + f"Variable {null_key_error} is required and cannot be removed" + ) if raise_errors: logger.error("STAC validation error: %s", item_id) @@ -295,7 +318,9 @@ def validate_post( extension_validator = get_extension_validator(str(extension)) raise_errors = [] - for error in extension_validator.iter_errors(json.loads(item.model_dump_json())): + for error in extension_validator.iter_errors( + json.loads(item.model_dump_json()) + ): raise_errors.append(error) if raise_errors: From 10caf7cd95a0075809ccdb7c1c60a407bf74a0e5 Mon Sep 17 00:00:00 2001 From: rhysrevans3 Date: Wed, 24 Jun 2026 16:03:05 +0100 Subject: [PATCH 35/35] Add ExtensionBelowMinimumException to RFC9457Exception exceptions. --- src/api.py | 4 +-- src/authorizer/egi_authorizer.py | 4 +-- src/client.py | 30 ++++++++++++++++----- src/utils.py | 45 +++++++------------------------- 4 files changed, 36 insertions(+), 47 deletions(-) diff --git a/src/api.py b/src/api.py index 08478cd..2277d71 100644 --- a/src/api.py +++ b/src/api.py @@ -64,9 +64,7 @@ async def rfc9457_handler(request: Request, exc: RFC9457Exception): @app.exception_handler(InvalidTokenAudienceException) -async def invalid_token_audience_handler( - request: Request, exc: InvalidTokenAudienceException -): +async def invalid_token_audience_handler(request: Request, exc: InvalidTokenAudienceException): event_id = uuid.uuid4().hex request_id = request.headers.get("x-request-id", uuid.uuid4().hex) return JSONResponse( diff --git a/src/authorizer/egi_authorizer.py b/src/authorizer/egi_authorizer.py index 0f6d905..b58b100 100644 --- a/src/authorizer/egi_authorizer.py +++ b/src/authorizer/egi_authorizer.py @@ -58,9 +58,7 @@ async def dispatch(self, request: Request, call_next): logger.debug("Token info: %s", token_info) - if request.headers["host"] not in [ - urlparse(aud).hostname for aud in token_info["aud"] - ]: + if request.headers["host"] not in [urlparse(aud).hostname for aud in token_info["aud"]]: raise InvalidTokenAudienceException( token_audience=request.headers["host"], expected_audience=", ".join(token_info["aud"]), diff --git a/src/client.py b/src/client.py index c126899..5fe48a6 100644 --- a/src/client.py +++ b/src/client.py @@ -7,6 +7,7 @@ from esgf_core_utils.models.exceptions import ( AuthorizationException, ExpectedExtensionsMissingException, + ExtensionBelowMinimumException, MissingPermissionException, OperationNotPermittedException, RFC9457Exception, @@ -202,6 +203,7 @@ async def create_item( OperationNotPermittedException, STACValidationException, UnexpectedExtensionException, + ExtensionBelowMinimumException, ) as exc: rfc_exc = RFC9457Exception() rfc_exc.status_code = 400 @@ -210,6 +212,7 @@ async def create_item( rfc_exc.detail = exc.detail rfc_exc.instance = f"{request_id}:{event_id}" raise rfc_exc from exc + user_agent = headers.get("user-agent", "/").split("/") payload = CreatePayload( @@ -342,14 +345,29 @@ async def patch_item( ) item_extensions = item.stac_extensions if item.stac_extensions else [] + try: - item_extensions = validate_extensions(collection_id=collection_id, item_extensions=item_extensions) + item_extensions = validate_extensions(collection_id=collection_id, item_extensions=item_extensions) - validate_patch( - item_id=item_id, - item=item, - extensions=item_extensions, - ) + validate_patch( + item_id=item_id, + item=item, + extensions=item_extensions, + ) + except ( + ExpectedExtensionsMissingException, + OperationNotPermittedException, + STACValidationException, + UnexpectedExtensionException, + ExtensionBelowMinimumException, + ) as exc: + rfc_exc = RFC9457Exception() + rfc_exc.status_code = 400 + rfc_exc.type = exc.type + rfc_exc.title = exc.title + rfc_exc.detail = exc.detail + rfc_exc.instance = f"{request_id}:{event_id}" + raise rfc_exc from exc user_agent = headers.get("user-agent", "/").split("/") diff --git a/src/utils.py b/src/utils.py index be15731..624b3c9 100644 --- a/src/utils.py +++ b/src/utils.py @@ -27,9 +27,7 @@ logger = logging.getLogger("uvicorn.error") -def operation_to_partial_item( - collection_id: str, operations: list[PatchOperation] -) -> PartialItem: +def operation_to_partial_item(collection_id: str, operations: list[PatchOperation]) -> PartialItem: """Convert operations to partial item Args: @@ -101,14 +99,10 @@ def validate_extension_version(minimum: str, extension: str) -> None: extension_version = VERSION_REGEX.search(extension).group(1) if Version(extension_version) < Version(minimum_version): - raise ExtensionBelowMinimumException( - extension=extension, minimum_version=f"v{minimum_version}" - ) + raise ExtensionBelowMinimumException(extension=extension, minimum_version=f"v{minimum_version}") -def validate_extensions( - collection_id: str, item_extensions: list[str], strict: bool = False -) -> list[str]: +def validate_extensions(collection_id: str, item_extensions: list[str], strict: bool = False) -> list[str]: """Validate expected default extensions are present. Args: @@ -132,24 +126,16 @@ def validate_extensions( expected_extension_key, expected_extension, ) in expected_extensions.copy().items(): - if any( - re.compile(regex).match(str(item_extension)) - for regex in expected_extension["regex"] - ): + if any(re.compile(regex).match(str(item_extension)) for regex in expected_extension["regex"]): expected_extensions.pop(expected_extension_key) expected = True - validate_extension_version( - minimum=expected_extension["default"], extension=str(item_extension) - ) + validate_extension_version(minimum=expected_extension["default"], extension=str(item_extension)) if not expected: raise UnexpectedExtensionException(extension=item_extension) - missing_extensions = [ - expected_extension["default"] - for expected_extension in expected_extensions.values() - ] + missing_extensions = [expected_extension["default"] for expected_extension in expected_extensions.values()] if strict & len(missing_extensions) > 0: raise ExpectedExtensionsMissingException(extensions=missing_extensions) @@ -217,12 +203,7 @@ def validate_bbox(bbox: list[int | float]) -> None: STACValidationException: _description_ """ minx, miny, maxx, maxy = bbox[:4] - if not ( - -180.0 <= minx <= 180.0 - and -180.0 <= maxx <= 180.0 - and -90.0 <= miny <= 90.0 - and -90.0 <= maxy <= 90.0 - ): + if not (-180.0 <= minx <= 180.0 and -180.0 <= maxx <= 180.0 and -90.0 <= miny <= 90.0 and -90.0 <= maxy <= 90.0): raise STACValidationException() @@ -272,9 +253,7 @@ def validate_patch( required_keys = set() raise_errors = [] - for error in extension_validator.iter_errors( - json.loads(item.model_dump_json()) - ): + for error in extension_validator.iter_errors(json.loads(item.model_dump_json())): if error.validator in ["oneOf"]: continue @@ -286,9 +265,7 @@ def validate_patch( raise_errors.append(error) for null_key_error in required_keys & null_keys: - raise_errors.append( - f"Variable {null_key_error} is required and cannot be removed" - ) + raise_errors.append(f"Variable {null_key_error} is required and cannot be removed") if raise_errors: logger.error("STAC validation error: %s", item_id) @@ -318,9 +295,7 @@ def validate_post( extension_validator = get_extension_validator(str(extension)) raise_errors = [] - for error in extension_validator.iter_errors( - json.loads(item.model_dump_json()) - ): + for error in extension_validator.iter_errors(json.loads(item.model_dump_json())): raise_errors.append(error) if raise_errors: