From d834ed273287ef08b167d2b9192c93aa52e224f5 Mon Sep 17 00:00:00 2001 From: v-rocheleau Date: Fri, 11 Oct 2024 17:06:18 -0400 Subject: [PATCH 01/31] authz docs start --- README.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/README.md b/README.md index 3c54bb0..abb750d 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,26 @@ docker compose -f ./docker-compose.dev.yaml down You can then attach VS Code to the `tds` container, and use the preconfigured `Python Debugger (TDS)` for interactive debugging. +## Authorization plugin + +Although TDS is part of the Bento platform, it is meant to be reusable in other software stacks. +Since authorization requirements and technology vary wildy across different projects, +TDS allows adopters to write their own authorization logic in python. + +For Bento, we rely on API calls to a custom authorization service, +see [etc/bento.authz.module.py](./etc/bento.authz.module.py) for an example. + +For different authorization requirements, you could choose to write a custom module that performs authorization checks based on: +* An API key in the request header or in a cookie +* A JWT bearer token, for example you could: + * Allow/Deny simply based on the token's validity (decode + TTL) + * Allow/Deny based on the presence of a scope in the token + * Allow/Deny based on the presence of a group membership claim +* The results of API calls to an authorization service +* Policy engine evaluations, like OPA or Casbin + +TODO: add more details as this takes shape + ## Endpoints * /service-info From b388fe1c172bbba8bad55cf2c72250c4cc00a949 Mon Sep 17 00:00:00 2001 From: v-rocheleau Date: Tue, 15 Oct 2024 20:16:38 -0400 Subject: [PATCH 02/31] feat: injectable tds authz middleware plugin --- .vscode/launch.json | 1 + etc/bento.authz.module.py | 52 ++++++++++++++++--- .../authz/exceptions.py | 10 ++++ .../authz/middleware_mixin.py | 50 ++++++++++++++++++ transcriptomics_data_service/authz/plugin.py | 16 +++--- transcriptomics_data_service/main.py | 4 +- .../routers/ingest.py | 13 +++-- 7 files changed, 127 insertions(+), 19 deletions(-) create mode 100644 transcriptomics_data_service/authz/exceptions.py create mode 100644 transcriptomics_data_service/authz/middleware_mixin.py diff --git a/.vscode/launch.json b/.vscode/launch.json index 1caabd7..7c7005d 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -8,6 +8,7 @@ "name": "Python Debugger (TDS): Dev Container Attach", "type": "debugpy", "request": "attach", + "justMyCode": false, "connect": { "host": "0.0.0.0", "port": 9511 diff --git a/etc/bento.authz.module.py b/etc/bento.authz.module.py index 4c66a1d..a917792 100644 --- a/etc/bento.authz.module.py +++ b/etc/bento.authz.module.py @@ -1,15 +1,55 @@ -from fastapi import Request +from typing import Any, Awaitable, Callable, Coroutine +from fastapi import Depends, FastAPI, Request, Response from bento_lib.auth.middleware.fastapi import FastApiAuthMiddleware +from bento_lib.auth.permissions import P_INGEST_DATA +from bento_lib.auth.resources import RESOURCE_EVERYTHING, build_resource +from starlette.responses import Response from transcriptomics_data_service.config import get_config from transcriptomics_data_service.logger import get_logger +from transcriptomics_data_service.authz.middleware_mixin import BaseAuthzMiddleware config = get_config() logger = get_logger(config) -bento_authz = FastApiAuthMiddleware.build_from_pydantic_config(config, logger) -async def get_current_user_authorization(req: Request): - # TODO use as a propper middleware, or simply as an injectable with method calls? - print("************ This middleware performs authz checks for Bento") - return True +class CustomAuthzMiddleware(BaseAuthzMiddleware): + """ + Concrete implementation of BaseAuthzMiddleware to authorize with Bento's authorization service/model. + Essentialy a TDS wrapper for the bento_lib FastApiAuthMiddleware. + """ + + def __init__(self, config, logger, enabled: bool = True) -> None: + self.bento_authz = FastApiAuthMiddleware.build_from_pydantic_config(config, logger) + self.enabled = enabled + + def attach(self, app: FastAPI): + app.middleware("http")(self.bento_authz.dispatch) + + async def dispatch( + self, request: Request, call_next: Callable[[Request], Awaitable[Response]] + ) -> Coroutine[Any, Any, Response]: + # Use the bento_lib authz middleware's dispatch + return await self.bento_authz.dispatch(request, call_next) + + def dep_public_endpoint(self): + return self.bento_authz.dep_public_endpoint() + + # INGEST router authz dependency functions + + def dep_authorize_ingest(self): + # TODO authorize with propper permissions and resources + return self.bento_authz.dep_require_permissions_on_resource( + permissions=frozenset({P_INGEST_DATA}), resource=RESOURCE_EVERYTHING + ) + + def dep_authorize_normalize(self): + # TODO authorize with propper permissions and resources + return self.bento_authz.dep_require_permissions_on_resource( + permissions=frozenset({P_INGEST_DATA}), resource=RESOURCE_EVERYTHING + ) + + def mark_authz_done(self, request: Request): + self.bento_authz.mark_authz_done(request) + +authz_middleware = CustomAuthzMiddleware(config, logger) diff --git a/transcriptomics_data_service/authz/exceptions.py b/transcriptomics_data_service/authz/exceptions.py new file mode 100644 index 0000000..2bb6e53 --- /dev/null +++ b/transcriptomics_data_service/authz/exceptions.py @@ -0,0 +1,10 @@ +__all__ = [ + "AuthzException", +] + + +class AuthzException(Exception): + def __init__(self, message="Unauthorized", status_code=401) -> None: + super().__init__(message) + self.message = message + self.status_code = status_code diff --git a/transcriptomics_data_service/authz/middleware_mixin.py b/transcriptomics_data_service/authz/middleware_mixin.py new file mode 100644 index 0000000..4c64d45 --- /dev/null +++ b/transcriptomics_data_service/authz/middleware_mixin.py @@ -0,0 +1,50 @@ +from fastapi import Depends, FastAPI, Request, Response, status + +from typing import Awaitable, Callable +from abc import ABC, abstractmethod + + +class BaseAuthzMiddleware(ABC): + + @abstractmethod + def attach(self, app: FastAPI): + """ + Attaches itself to the TDS FastAPI app, all requests will go through the dispatch function. + """ + # app.middleware("http")(self.dispatch) + + @abstractmethod + async def dispatch(self, request: Request, call_next: Callable[[Request], Awaitable[Response]]) -> Response: + """ + Defines the way requests are handled by the authorization middleware, if it is attached to the FastAPI app. + This is to allow adopters to implement custom authorization logic. + When implementing this function, you can do the following on all incoming requests, before they get to their respective routers: + - Modify the request (e.g. add a header, modify the state before authz check) + - Pass the request to the rest of the application with call_next + - The request will first hit an endpoint dependency function (e.g. dep_authorize_ingest) + - The endpoint dep function evaluates if the request should be authorized and raises an exception if not + - If authorized, the request proceeds to the endpoint function + - If unauthorized, an exception should be caught and handled here, the request never reaches the endpoint function + - Modify the request before it is returned to the client + - Raise and catch exception based on authorization results + - Handle unauthorized responses + """ + pass + + @abstractmethod + def dep_authorize_ingest(self): + """ + Authorization function for the /ingest endpoint. + + Returns an inner function as a dependency, which is + """ + pass + + @abstractmethod + def dep_authorize_normalize(self): + """ + Endpoint: /normalize + + Authorizes the normalize endpoint + """ + pass diff --git a/transcriptomics_data_service/authz/plugin.py b/transcriptomics_data_service/authz/plugin.py index ded7ba5..18f4db0 100644 --- a/transcriptomics_data_service/authz/plugin.py +++ b/transcriptomics_data_service/authz/plugin.py @@ -1,9 +1,12 @@ import importlib.util -import sys -from fastapi import Depends, Request +from fastapi import Request -__all__ = ["get_request_authorization"] +from transcriptomics_data_service.authz.middleware_mixin import BaseAuthzMiddleware +from transcriptomics_data_service.config import get_config +from transcriptomics_data_service.logger import get_logger + +__all__ = ["authz_middleware"] def import_module_from_path(path): @@ -16,8 +19,7 @@ def import_module_from_path(path): # TODO find a way to allow plugin writers to specify additional dependencies to be installed AUTHZ_MODULE_PATH = "/tds/lib/authz.module.py" -authz_plugin = import_module_from_path(AUTHZ_MODULE_PATH) - +authz_plugin_module = import_module_from_path(AUTHZ_MODULE_PATH) -async def get_request_authorization(req: Request): - return await authz_plugin.get_current_user_authorization(req) +# Get the concrete authz middleware from the provided plugin module +authz_middleware: BaseAuthzMiddleware = authz_plugin_module.authz_middleware diff --git a/transcriptomics_data_service/main.py b/transcriptomics_data_service/main.py index 93d9d13..a1e649d 100644 --- a/transcriptomics_data_service/main.py +++ b/transcriptomics_data_service/main.py @@ -6,6 +6,8 @@ from transcriptomics_data_service.routers.experiment_results import experiment_router from transcriptomics_data_service.routers.expressions import expression_router from transcriptomics_data_service.routers.ingest import ingest_router +from transcriptomics_data_service.authz.plugin import authz_middleware + from . import __version__ from .config import get_config from .constants import BENTO_SERVICE_KIND, SERVICE_TYPE @@ -32,7 +34,7 @@ async def lifespan(_app: FastAPI): app = BentoFastAPI( - authz_middleware=None, + authz_middleware=authz_middleware, config=config_for_setup, logger=logger_for_setup, bento_extra_service_info=BENTO_SERVICE_INFO, diff --git a/transcriptomics_data_service/routers/ingest.py b/transcriptomics_data_service/routers/ingest.py index 2c246ab..aac871b 100644 --- a/transcriptomics_data_service/routers/ingest.py +++ b/transcriptomics_data_service/routers/ingest.py @@ -5,7 +5,7 @@ from transcriptomics_data_service.db import DatabaseDependency from transcriptomics_data_service.models import ExperimentResult, GeneExpression -from transcriptomics_data_service.authz.plugin import get_request_authorization +from transcriptomics_data_service.authz.plugin import authz_middleware __all__ = ["ingest_router"] @@ -17,6 +17,8 @@ @ingest_router.post( "/ingest/{experiment_result_id}/assembly-name/{assembly_name}/assembly-id/{assembly_id}", status_code=status.HTTP_200_OK, + # Injects the plugin authz middleware dep_authorize_ingest function + dependencies=[authz_middleware.dep_authorize_ingest()], ) async def ingest( request: Request, @@ -26,9 +28,6 @@ async def ingest( assembly_id: str, rcm_file: UploadFile = File(...), ): - # TODO make injectable - authorized = await get_request_authorization(request) - # Read and process rcm file file_bytes = rcm_file.file.read() buffer = StringIO(file_bytes.decode("utf-8")) @@ -55,7 +54,11 @@ async def ingest( return -@ingest_router.post("/normalize/{experiment_result_id}") +@ingest_router.post( + "/normalize/{experiment_result_id}", + status_code=status.HTTP_200_OK, + dependencies=[authz_middleware.dep_authorize_normalize()], +) async def normalize( db: DatabaseDependency, experiment_result_id: str, From 38b851f58e8a591738a25a9f40734b3a223bdf20 Mon Sep 17 00:00:00 2001 From: Victor Rocheleau Date: Wed, 16 Oct 2024 13:22:37 -0400 Subject: [PATCH 03/31] feat(authz): exempt docs and openapi from authz --- README.md | 25 +- docker-compose.dev.yaml | 1 + etc/bento.authz.module.py | 35 +- poetry.lock | 2735 +++++++++-------- pyproject.toml | 4 +- ...middleware_mixin.py => middleware_base.py} | 15 +- transcriptomics_data_service/authz/plugin.py | 2 +- transcriptomics_data_service/config.py | 7 +- 8 files changed, 1507 insertions(+), 1317 deletions(-) rename transcriptomics_data_service/authz/{middleware_mixin.py => middleware_base.py} (88%) diff --git a/README.md b/README.md index abb750d..a466d02 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,30 @@ For different authorization requirements, you could choose to write a custom mod * The results of API calls to an authorization service * Policy engine evaluations, like OPA or Casbin -TODO: add more details as this takes shape +### Using an authorization plugin + +When starting the TDS container, the FastAPI server will attempt to dynamicaly load the authorization plugin +middleware from `lib/authz.module.py`. + +If authorization is enabled and there is no file at `lib/authz.module.py`, an exception will be thrown and the server +will not start. + +Furthermore, the content of the file must follow some implementation guidelines: +from transcriptomics_data_service.authz.middleware_base import BaseAuthzMiddleware + +- You MUST declare a concrete class that extends [BaseAuthzMiddleware](./transcriptomics_data_service/authz/middleware_base.py) +- In that class, you MUST implement the functions from BaseAuthzMiddleware with the expected signatures: + - `attach`: used to attach the middleware to the FastAPI app + - `dipatch`: called for every request made to the API + - `dep_authorize_`: endpoint-specific, authz evaluation functions that should return an injectable function + +Looking at [bento.authz.module.py](./etc/bento.authz.module.py), we can see an implementation that is specific to +Bento's authorization service and libraries. + +Rather than directly implementing the `attach`, `dispatch` and other authorization logic, we rely on the `bento-lib` +`FastApiAuthMiddleware`, which already provides a reusable authorization middleware for FastAPI. + +The only thing left to do is to implement the endpoint-specific authorization functions. ## Endpoints diff --git a/docker-compose.dev.yaml b/docker-compose.dev.yaml index 8bb8186..fe3e103 100644 --- a/docker-compose.dev.yaml +++ b/docker-compose.dev.yaml @@ -9,6 +9,7 @@ services: depends_on: - tds-db environment: + - BENTO_UID=1001 - DATABASE_URI=postgres://tds_user:tds_password@tds-db:5432/tds_db - CORS_ORIGINS="*" - BENTO_AUTHZ_SERVICE_URL="" diff --git a/etc/bento.authz.module.py b/etc/bento.authz.module.py index a917792..19211d4 100644 --- a/etc/bento.authz.module.py +++ b/etc/bento.authz.module.py @@ -1,55 +1,36 @@ +from logging import Logger +from re import Pattern from typing import Any, Awaitable, Callable, Coroutine from fastapi import Depends, FastAPI, Request, Response from bento_lib.auth.middleware.fastapi import FastApiAuthMiddleware from bento_lib.auth.permissions import P_INGEST_DATA from bento_lib.auth.resources import RESOURCE_EVERYTHING, build_resource -from starlette.responses import Response +from starlette.middleware.base import BaseHTTPMiddleware from transcriptomics_data_service.config import get_config from transcriptomics_data_service.logger import get_logger -from transcriptomics_data_service.authz.middleware_mixin import BaseAuthzMiddleware +from transcriptomics_data_service.authz.middleware_base import BaseAuthzMiddleware config = get_config() logger = get_logger(config) -class CustomAuthzMiddleware(BaseAuthzMiddleware): +class CustomAuthzMiddleware(FastApiAuthMiddleware, BaseAuthzMiddleware): """ Concrete implementation of BaseAuthzMiddleware to authorize with Bento's authorization service/model. Essentialy a TDS wrapper for the bento_lib FastApiAuthMiddleware. """ - def __init__(self, config, logger, enabled: bool = True) -> None: - self.bento_authz = FastApiAuthMiddleware.build_from_pydantic_config(config, logger) - self.enabled = enabled - - def attach(self, app: FastAPI): - app.middleware("http")(self.bento_authz.dispatch) - - async def dispatch( - self, request: Request, call_next: Callable[[Request], Awaitable[Response]] - ) -> Coroutine[Any, Any, Response]: - # Use the bento_lib authz middleware's dispatch - return await self.bento_authz.dispatch(request, call_next) - - def dep_public_endpoint(self): - return self.bento_authz.dep_public_endpoint() - - # INGEST router authz dependency functions - def dep_authorize_ingest(self): # TODO authorize with propper permissions and resources - return self.bento_authz.dep_require_permissions_on_resource( + return self.dep_require_permissions_on_resource( permissions=frozenset({P_INGEST_DATA}), resource=RESOURCE_EVERYTHING ) def dep_authorize_normalize(self): # TODO authorize with propper permissions and resources - return self.bento_authz.dep_require_permissions_on_resource( + return self.dep_require_permissions_on_resource( permissions=frozenset({P_INGEST_DATA}), resource=RESOURCE_EVERYTHING ) - def mark_authz_done(self, request: Request): - self.bento_authz.mark_authz_done(request) - -authz_middleware = CustomAuthzMiddleware(config, logger) +authz_middleware = CustomAuthzMiddleware.build_from_fastapi_pydantic_config(config, logger) diff --git a/poetry.lock b/poetry.lock index 2ea6d4c..abb04f0 100644 --- a/poetry.lock +++ b/poetry.lock @@ -13,98 +13,113 @@ files = [ [[package]] name = "aiohappyeyeballs" -version = "2.3.4" +version = "2.4.3" description = "Happy Eyeballs for asyncio" optional = false -python-versions = "<4.0,>=3.8" +python-versions = ">=3.8" files = [ - {file = "aiohappyeyeballs-2.3.4-py3-none-any.whl", hash = "sha256:40a16ceffcf1fc9e142fd488123b2e218abc4188cf12ac20c67200e1579baa42"}, - {file = "aiohappyeyeballs-2.3.4.tar.gz", hash = "sha256:7e1ae8399c320a8adec76f6c919ed5ceae6edd4c3672f4d9eae2b27e37c80ff6"}, + {file = "aiohappyeyeballs-2.4.3-py3-none-any.whl", hash = "sha256:8a7a83727b2756f394ab2895ea0765a0a8c475e3c71e98d43d76f22b4b435572"}, + {file = "aiohappyeyeballs-2.4.3.tar.gz", hash = "sha256:75cf88a15106a5002a8eb1dab212525c00d1f4c0fa96e551c9fbe6f09a621586"}, ] [[package]] name = "aiohttp" -version = "3.10.0" +version = "3.10.10" description = "Async http client/server framework (asyncio)" optional = false python-versions = ">=3.8" files = [ - {file = "aiohttp-3.10.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:68ab608118e212f56feef44d4785aa90b713042da301f26338f36497b481cd79"}, - {file = "aiohttp-3.10.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:64a117c16273ca9f18670f33fc7fd9604b9f46ddb453ce948262889a6be72868"}, - {file = "aiohttp-3.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:54076a25f32305e585a3abae1f0ad10646bec539e0e5ebcc62b54ee4982ec29f"}, - {file = "aiohttp-3.10.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71c76685773444d90ae83874433505ed800e1706c391fdf9e57cc7857611e2f4"}, - {file = "aiohttp-3.10.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bdda86ab376f9b3095a1079a16fbe44acb9ddde349634f1c9909d13631ff3bcf"}, - {file = "aiohttp-3.10.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d6dcd1d21da5ae1416f69aa03e883a51e84b6c803b8618cbab341ac89a85b9e"}, - {file = "aiohttp-3.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06ef0135d7ab7fb0284342fbbf8e8ddf73b7fee8ecc55f5c3a3d0a6b765e6d8b"}, - {file = "aiohttp-3.10.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ccab9381f38c669bb9254d848f3b41a3284193b3e274a34687822f98412097e9"}, - {file = "aiohttp-3.10.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:947da3aee057010bc750b7b4bb65cbd01b0bdb7c4e1cf278489a1d4a1e9596b3"}, - {file = "aiohttp-3.10.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:5268b35fee7eb754fb5b3d0f16a84a2e9ed21306f5377f3818596214ad2d7714"}, - {file = "aiohttp-3.10.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:ff25d988fd6ce433b5c393094a5ca50df568bdccf90a8b340900e24e0d5fb45c"}, - {file = "aiohttp-3.10.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:594b4b4f1dfe8378b4a0342576dc87a930c960641159f5ae83843834016dbd59"}, - {file = "aiohttp-3.10.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c8820dad615cd2f296ed3fdea8402b12663ac9e5ea2aafc90ef5141eb10b50b8"}, - {file = "aiohttp-3.10.0-cp310-cp310-win32.whl", hash = "sha256:ab1d870403817c9a0486ca56ccbc0ebaf85d992277d48777faa5a95e40e5bcca"}, - {file = "aiohttp-3.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:563705a94ea3af43467167f3a21c665f3b847b2a0ae5544fa9e18df686a660da"}, - {file = "aiohttp-3.10.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:13679e11937d3f37600860de1f848e2e062e2b396d3aa79b38c89f9c8ab7e791"}, - {file = "aiohttp-3.10.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8c66a1aadafbc0bd7d648cb7fcb3860ec9beb1b436ce3357036a4d9284fcef9a"}, - {file = "aiohttp-3.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b7e3545b06aae925f90f06402e05cfb9c62c6409ce57041932163b09c48daad6"}, - {file = "aiohttp-3.10.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:effafe5144aa32f0388e8f99b1b2692cf094ea2f6b7ceca384b54338b77b1f50"}, - {file = "aiohttp-3.10.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a04f2c8d41821a2507b49b2694c40495a295b013afb0cc7355b337980b47c546"}, - {file = "aiohttp-3.10.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6dbfac556219d884d50edc6e1952a93545c2786193f00f5521ec0d9d464040ab"}, - {file = "aiohttp-3.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a65472256c5232681968deeea3cd5453aa091c44e8db09f22f1a1491d422c2d9"}, - {file = "aiohttp-3.10.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:941366a554e566efdd3f042e17a9e461a36202469e5fd2aee66fe3efe6412aef"}, - {file = "aiohttp-3.10.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:927b4aca6340301e7d8bb05278d0b6585b8633ea852b7022d604a5df920486bf"}, - {file = "aiohttp-3.10.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:34adb8412e736a5d0df6d1fccdf71599dfb07a63add241a94a189b6364e997f1"}, - {file = "aiohttp-3.10.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:43c60d9b332a01ee985f080f639f3e56abcfb95ec1320013c94083c3b6a2e143"}, - {file = "aiohttp-3.10.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:3f49edf7c5cd2987634116e1b6a0ee2438fca17f7c4ee480ff41decb76cf6158"}, - {file = "aiohttp-3.10.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9784246431eaf9d651b3cc06f9c64f9a9f57299f4971c5ea778fa0b81074ef13"}, - {file = "aiohttp-3.10.0-cp311-cp311-win32.whl", hash = "sha256:bec91402df78b897a47b66b9c071f48051cea68d853d8bc1d4404896c6de41ae"}, - {file = "aiohttp-3.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:25a9924343bf91b0c5082cae32cfc5a1f8787ac0433966319ec07b0ed4570722"}, - {file = "aiohttp-3.10.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:21dab4a704c68dc7bc2a1219a4027158e8968e2079f1444eda2ba88bc9f2895f"}, - {file = "aiohttp-3.10.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:872c0dcaccebd5733d535868fe2356aa6939f5827dcea7a8b9355bb2eff6f56e"}, - {file = "aiohttp-3.10.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f381424dbce313bb5a666a215e7a9dcebbc533e9a2c467a1f0c95279d24d1fa7"}, - {file = "aiohttp-3.10.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9ca48e9f092a417c6669ee8d3a19d40b3c66dde1a2ae0d57e66c34812819b671"}, - {file = "aiohttp-3.10.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bbe2f6d0466f5c59c7258e0745c20d74806a1385fbb7963e5bbe2309a11cc69b"}, - {file = "aiohttp-3.10.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:03799a95402a7ed62671c4465e1eae51d749d5439dbc49edb6eee52ea165c50b"}, - {file = "aiohttp-3.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5549c71c35b5f057a4eebcc538c41299826f7813f28880722b60e41c861a57ec"}, - {file = "aiohttp-3.10.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f6fa7a42b78d8698491dc4ad388169de54cca551aa9900f750547372de396277"}, - {file = "aiohttp-3.10.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:77bbf0a2f6fefac6c0db1792c234f577d80299a33ce7125467439097cf869198"}, - {file = "aiohttp-3.10.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:34eaf5cfcc979846d73571b1a4be22cad5e029d55cdbe77cdc7545caa4dcb925"}, - {file = "aiohttp-3.10.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:4f1de31a585344a106db43a9c3af2e15bb82e053618ff759f1fdd31d82da38eb"}, - {file = "aiohttp-3.10.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:f3a1ea61d96146e9b9e5597069466e2e4d9e01e09381c5dd51659f890d5e29e7"}, - {file = "aiohttp-3.10.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:73c01201219eb039a828bb58dcc13112eec2fed6eea718356316cd552df26e04"}, - {file = "aiohttp-3.10.0-cp312-cp312-win32.whl", hash = "sha256:33e915971eee6d2056d15470a1214e4e0f72b6aad10225548a7ab4c4f54e2db7"}, - {file = "aiohttp-3.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:2dc75da06c35a7b47a88ceadbf993a53d77d66423c2a78de8c6f9fb41ec35687"}, - {file = "aiohttp-3.10.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:f1bc4d68b83966012813598fe39b35b4e6019b69d29385cf7ec1cb08e1ff829b"}, - {file = "aiohttp-3.10.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d9b8b31c057a0b7bb822a159c490af05cb11b8069097f3236746a78315998afa"}, - {file = "aiohttp-3.10.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:10f0d7894ddc6ff8f369e3fdc082ef1f940dc1f5b9003cd40945d24845477220"}, - {file = "aiohttp-3.10.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:72de8ffba4a27e3c6e83e58a379fc4fe5548f69f9b541fde895afb9be8c31658"}, - {file = "aiohttp-3.10.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cd36d0f0afc2bd84f007cedd2d9a449c3cf04af471853a25eb71f28bc2e1a119"}, - {file = "aiohttp-3.10.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f64d503c661864866c09806ac360b95457f872d639ca61719115a9f389b2ec90"}, - {file = "aiohttp-3.10.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:31616121369bc823791056c632f544c6c8f8d1ceecffd8bf3f72ef621eaabf49"}, - {file = "aiohttp-3.10.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f76c12abb88b7ee64b3f9ae72f0644af49ff139067b5add142836dab405d60d4"}, - {file = "aiohttp-3.10.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:6c99eef30a7e98144bcf44d615bc0f445b3a3730495fcc16124cb61117e1f81e"}, - {file = "aiohttp-3.10.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:39e7ec718e7a1971a5d98357e3e8c0529477d45c711d32cd91999dc8d8404e1e"}, - {file = "aiohttp-3.10.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:f1cef548ee4e84264b78879de0c754bbe223193c6313beb242ce862f82eab184"}, - {file = "aiohttp-3.10.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:f98f036eab11d2f90cdd01b9d1410de9d7eb520d070debeb2edadf158b758431"}, - {file = "aiohttp-3.10.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:cc4376ff537f7d2c1e98f97f6d548e99e5d96078b0333c1d3177c11467b972de"}, - {file = "aiohttp-3.10.0-cp38-cp38-win32.whl", hash = "sha256:ebedc51ee6d39f9ea5e26e255fd56a7f4e79a56e77d960f9bae75ef4f95ed57f"}, - {file = "aiohttp-3.10.0-cp38-cp38-win_amd64.whl", hash = "sha256:aad87626f31a85fd4af02ba7fd6cc424b39d4bff5c8677e612882649da572e47"}, - {file = "aiohttp-3.10.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:1dc95c5e2a5e60095f1bb51822e3b504e6a7430c9b44bff2120c29bb876c5202"}, - {file = "aiohttp-3.10.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1c83977f7b6f4f4a96fab500f5a76d355f19f42675224a3002d375b3fb309174"}, - {file = "aiohttp-3.10.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8cedc48d36652dd3ac40e5c7c139d528202393e341a5e3475acedb5e8d5c4c75"}, - {file = "aiohttp-3.10.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4b099fbb823efed3c1d736f343ac60d66531b13680ee9b2669e368280f41c2b8"}, - {file = "aiohttp-3.10.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d583755ddb9c97a2da1322f17fc7d26792f4e035f472d675e2761c766f94c2ff"}, - {file = "aiohttp-3.10.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2a03a4407bdb9ae815f0d5a19df482b17df530cf7bf9c78771aa1c713c37ff1f"}, - {file = "aiohttp-3.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dcb6e65f6ea7caa0188e36bebe9e72b259d3d525634758c91209afb5a6cbcba7"}, - {file = "aiohttp-3.10.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b6612c6ed3147a4a2d6463454b94b877566b38215665be4c729cd8b7bdce15b4"}, - {file = "aiohttp-3.10.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:0b0c0148d2a69b82ffe650c2ce235b431d49a90bde7dd2629bcb40314957acf6"}, - {file = "aiohttp-3.10.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:0d85a173b4dbbaaad1900e197181ea0fafa617ca6656663f629a8a372fdc7d06"}, - {file = "aiohttp-3.10.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:12c43dace645023583f3dd2337dfc3aa92c99fb943b64dcf2bc15c7aa0fb4a95"}, - {file = "aiohttp-3.10.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:33acb0d9bf12cdc80ceec6f5fda83ea7990ce0321c54234d629529ca2c54e33d"}, - {file = "aiohttp-3.10.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:91e0b76502205484a4d1d6f25f461fa60fe81a7987b90e57f7b941b0753c3ec8"}, - {file = "aiohttp-3.10.0-cp39-cp39-win32.whl", hash = "sha256:1ebd8ed91428ffbe8b33a5bd6f50174e11882d5b8e2fe28670406ab5ee045ede"}, - {file = "aiohttp-3.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:0433795c4a8bafc03deb3e662192250ba5db347c41231b0273380d2f53c9ea0b"}, - {file = "aiohttp-3.10.0.tar.gz", hash = "sha256:e8dd7da2609303e3574c95b0ec9f1fd49647ef29b94701a2862cceae76382e1d"}, + {file = "aiohttp-3.10.10-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:be7443669ae9c016b71f402e43208e13ddf00912f47f623ee5994e12fc7d4b3f"}, + {file = "aiohttp-3.10.10-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7b06b7843929e41a94ea09eb1ce3927865387e3e23ebe108e0d0d09b08d25be9"}, + {file = "aiohttp-3.10.10-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:333cf6cf8e65f6a1e06e9eb3e643a0c515bb850d470902274239fea02033e9a8"}, + {file = "aiohttp-3.10.10-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:274cfa632350225ce3fdeb318c23b4a10ec25c0e2c880eff951a3842cf358ac1"}, + {file = "aiohttp-3.10.10-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d9e5e4a85bdb56d224f412d9c98ae4cbd032cc4f3161818f692cd81766eee65a"}, + {file = "aiohttp-3.10.10-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2b606353da03edcc71130b52388d25f9a30a126e04caef1fd637e31683033abd"}, + {file = "aiohttp-3.10.10-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ab5a5a0c7a7991d90446a198689c0535be89bbd6b410a1f9a66688f0880ec026"}, + {file = "aiohttp-3.10.10-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:578a4b875af3e0daaf1ac6fa983d93e0bbfec3ead753b6d6f33d467100cdc67b"}, + {file = "aiohttp-3.10.10-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:8105fd8a890df77b76dd3054cddf01a879fc13e8af576805d667e0fa0224c35d"}, + {file = "aiohttp-3.10.10-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3bcd391d083f636c06a68715e69467963d1f9600f85ef556ea82e9ef25f043f7"}, + {file = "aiohttp-3.10.10-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:fbc6264158392bad9df19537e872d476f7c57adf718944cc1e4495cbabf38e2a"}, + {file = "aiohttp-3.10.10-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:e48d5021a84d341bcaf95c8460b152cfbad770d28e5fe14a768988c461b821bc"}, + {file = "aiohttp-3.10.10-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:2609e9ab08474702cc67b7702dbb8a80e392c54613ebe80db7e8dbdb79837c68"}, + {file = "aiohttp-3.10.10-cp310-cp310-win32.whl", hash = "sha256:84afcdea18eda514c25bc68b9af2a2b1adea7c08899175a51fe7c4fb6d551257"}, + {file = "aiohttp-3.10.10-cp310-cp310-win_amd64.whl", hash = "sha256:9c72109213eb9d3874f7ac8c0c5fa90e072d678e117d9061c06e30c85b4cf0e6"}, + {file = "aiohttp-3.10.10-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:c30a0eafc89d28e7f959281b58198a9fa5e99405f716c0289b7892ca345fe45f"}, + {file = "aiohttp-3.10.10-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:258c5dd01afc10015866114e210fb7365f0d02d9d059c3c3415382ab633fcbcb"}, + {file = "aiohttp-3.10.10-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:15ecd889a709b0080f02721255b3f80bb261c2293d3c748151274dfea93ac871"}, + {file = "aiohttp-3.10.10-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3935f82f6f4a3820270842e90456ebad3af15810cf65932bd24da4463bc0a4c"}, + {file = "aiohttp-3.10.10-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:413251f6fcf552a33c981c4709a6bba37b12710982fec8e558ae944bfb2abd38"}, + {file = "aiohttp-3.10.10-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d1720b4f14c78a3089562b8875b53e36b51c97c51adc53325a69b79b4b48ebcb"}, + {file = "aiohttp-3.10.10-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:679abe5d3858b33c2cf74faec299fda60ea9de62916e8b67e625d65bf069a3b7"}, + {file = "aiohttp-3.10.10-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:79019094f87c9fb44f8d769e41dbb664d6e8fcfd62f665ccce36762deaa0e911"}, + {file = "aiohttp-3.10.10-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:fe2fb38c2ed905a2582948e2de560675e9dfbee94c6d5ccdb1301c6d0a5bf092"}, + {file = "aiohttp-3.10.10-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:a3f00003de6eba42d6e94fabb4125600d6e484846dbf90ea8e48a800430cc142"}, + {file = "aiohttp-3.10.10-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:1bbb122c557a16fafc10354b9d99ebf2f2808a660d78202f10ba9d50786384b9"}, + {file = "aiohttp-3.10.10-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:30ca7c3b94708a9d7ae76ff281b2f47d8eaf2579cd05971b5dc681db8caac6e1"}, + {file = "aiohttp-3.10.10-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:df9270660711670e68803107d55c2b5949c2e0f2e4896da176e1ecfc068b974a"}, + {file = "aiohttp-3.10.10-cp311-cp311-win32.whl", hash = "sha256:aafc8ee9b742ce75044ae9a4d3e60e3d918d15a4c2e08a6c3c3e38fa59b92d94"}, + {file = "aiohttp-3.10.10-cp311-cp311-win_amd64.whl", hash = "sha256:362f641f9071e5f3ee6f8e7d37d5ed0d95aae656adf4ef578313ee585b585959"}, + {file = "aiohttp-3.10.10-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:9294bbb581f92770e6ed5c19559e1e99255e4ca604a22c5c6397b2f9dd3ee42c"}, + {file = "aiohttp-3.10.10-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:a8fa23fe62c436ccf23ff930149c047f060c7126eae3ccea005f0483f27b2e28"}, + {file = "aiohttp-3.10.10-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5c6a5b8c7926ba5d8545c7dd22961a107526562da31a7a32fa2456baf040939f"}, + {file = "aiohttp-3.10.10-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:007ec22fbc573e5eb2fb7dec4198ef8f6bf2fe4ce20020798b2eb5d0abda6138"}, + {file = "aiohttp-3.10.10-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9627cc1a10c8c409b5822a92d57a77f383b554463d1884008e051c32ab1b3742"}, + {file = "aiohttp-3.10.10-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:50edbcad60d8f0e3eccc68da67f37268b5144ecc34d59f27a02f9611c1d4eec7"}, + {file = "aiohttp-3.10.10-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a45d85cf20b5e0d0aa5a8dca27cce8eddef3292bc29d72dcad1641f4ed50aa16"}, + {file = "aiohttp-3.10.10-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0b00807e2605f16e1e198f33a53ce3c4523114059b0c09c337209ae55e3823a8"}, + {file = "aiohttp-3.10.10-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f2d4324a98062be0525d16f768a03e0bbb3b9fe301ceee99611dc9a7953124e6"}, + {file = "aiohttp-3.10.10-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:438cd072f75bb6612f2aca29f8bd7cdf6e35e8f160bc312e49fbecab77c99e3a"}, + {file = "aiohttp-3.10.10-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:baa42524a82f75303f714108fea528ccacf0386af429b69fff141ffef1c534f9"}, + {file = "aiohttp-3.10.10-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:a7d8d14fe962153fc681f6366bdec33d4356f98a3e3567782aac1b6e0e40109a"}, + {file = "aiohttp-3.10.10-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c1277cd707c465cd09572a774559a3cc7c7a28802eb3a2a9472588f062097205"}, + {file = "aiohttp-3.10.10-cp312-cp312-win32.whl", hash = "sha256:59bb3c54aa420521dc4ce3cc2c3fe2ad82adf7b09403fa1f48ae45c0cbde6628"}, + {file = "aiohttp-3.10.10-cp312-cp312-win_amd64.whl", hash = "sha256:0e1b370d8007c4ae31ee6db7f9a2fe801a42b146cec80a86766e7ad5c4a259cf"}, + {file = "aiohttp-3.10.10-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ad7593bb24b2ab09e65e8a1d385606f0f47c65b5a2ae6c551db67d6653e78c28"}, + {file = "aiohttp-3.10.10-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1eb89d3d29adaf533588f209768a9c02e44e4baf832b08118749c5fad191781d"}, + {file = "aiohttp-3.10.10-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3fe407bf93533a6fa82dece0e74dbcaaf5d684e5a51862887f9eaebe6372cd79"}, + {file = "aiohttp-3.10.10-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50aed5155f819873d23520919e16703fc8925e509abbb1a1491b0087d1cd969e"}, + {file = "aiohttp-3.10.10-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4f05e9727ce409358baa615dbeb9b969db94324a79b5a5cea45d39bdb01d82e6"}, + {file = "aiohttp-3.10.10-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3dffb610a30d643983aeb185ce134f97f290f8935f0abccdd32c77bed9388b42"}, + {file = "aiohttp-3.10.10-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa6658732517ddabe22c9036479eabce6036655ba87a0224c612e1ae6af2087e"}, + {file = "aiohttp-3.10.10-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:741a46d58677d8c733175d7e5aa618d277cd9d880301a380fd296975a9cdd7bc"}, + {file = "aiohttp-3.10.10-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e00e3505cd80440f6c98c6d69269dcc2a119f86ad0a9fd70bccc59504bebd68a"}, + {file = "aiohttp-3.10.10-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ffe595f10566f8276b76dc3a11ae4bb7eba1aac8ddd75811736a15b0d5311414"}, + {file = "aiohttp-3.10.10-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:bdfcf6443637c148c4e1a20c48c566aa694fa5e288d34b20fcdc58507882fed3"}, + {file = "aiohttp-3.10.10-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:d183cf9c797a5291e8301790ed6d053480ed94070637bfaad914dd38b0981f67"}, + {file = "aiohttp-3.10.10-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:77abf6665ae54000b98b3c742bc6ea1d1fb31c394bcabf8b5d2c1ac3ebfe7f3b"}, + {file = "aiohttp-3.10.10-cp313-cp313-win32.whl", hash = "sha256:4470c73c12cd9109db8277287d11f9dd98f77fc54155fc71a7738a83ffcc8ea8"}, + {file = "aiohttp-3.10.10-cp313-cp313-win_amd64.whl", hash = "sha256:486f7aabfa292719a2753c016cc3a8f8172965cabb3ea2e7f7436c7f5a22a151"}, + {file = "aiohttp-3.10.10-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:1b66ccafef7336a1e1f0e389901f60c1d920102315a56df85e49552308fc0486"}, + {file = "aiohttp-3.10.10-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:acd48d5b80ee80f9432a165c0ac8cbf9253eaddb6113269a5e18699b33958dbb"}, + {file = "aiohttp-3.10.10-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3455522392fb15ff549d92fbf4b73b559d5e43dc522588f7eb3e54c3f38beee7"}, + {file = "aiohttp-3.10.10-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45c3b868724137f713a38376fef8120c166d1eadd50da1855c112fe97954aed8"}, + {file = "aiohttp-3.10.10-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:da1dee8948d2137bb51fbb8a53cce6b1bcc86003c6b42565f008438b806cccd8"}, + {file = "aiohttp-3.10.10-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c5ce2ce7c997e1971b7184ee37deb6ea9922ef5163c6ee5aa3c274b05f9e12fa"}, + {file = "aiohttp-3.10.10-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28529e08fde6f12eba8677f5a8608500ed33c086f974de68cc65ab218713a59d"}, + {file = "aiohttp-3.10.10-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f7db54c7914cc99d901d93a34704833568d86c20925b2762f9fa779f9cd2e70f"}, + {file = "aiohttp-3.10.10-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:03a42ac7895406220124c88911ebee31ba8b2d24c98507f4a8bf826b2937c7f2"}, + {file = "aiohttp-3.10.10-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:7e338c0523d024fad378b376a79faff37fafb3c001872a618cde1d322400a572"}, + {file = "aiohttp-3.10.10-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:038f514fe39e235e9fef6717fbf944057bfa24f9b3db9ee551a7ecf584b5b480"}, + {file = "aiohttp-3.10.10-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:64f6c17757251e2b8d885d728b6433d9d970573586a78b78ba8929b0f41d045a"}, + {file = "aiohttp-3.10.10-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:93429602396f3383a797a2a70e5f1de5df8e35535d7806c9f91df06f297e109b"}, + {file = "aiohttp-3.10.10-cp38-cp38-win32.whl", hash = "sha256:c823bc3971c44ab93e611ab1a46b1eafeae474c0c844aff4b7474287b75fe49c"}, + {file = "aiohttp-3.10.10-cp38-cp38-win_amd64.whl", hash = "sha256:54ca74df1be3c7ca1cf7f4c971c79c2daf48d9aa65dea1a662ae18926f5bc8ce"}, + {file = "aiohttp-3.10.10-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:01948b1d570f83ee7bbf5a60ea2375a89dfb09fd419170e7f5af029510033d24"}, + {file = "aiohttp-3.10.10-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9fc1500fd2a952c5c8e3b29aaf7e3cc6e27e9cfc0a8819b3bce48cc1b849e4cc"}, + {file = "aiohttp-3.10.10-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f614ab0c76397661b90b6851a030004dac502e48260ea10f2441abd2207fbcc7"}, + {file = "aiohttp-3.10.10-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:00819de9e45d42584bed046314c40ea7e9aea95411b38971082cad449392b08c"}, + {file = "aiohttp-3.10.10-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:05646ebe6b94cc93407b3bf34b9eb26c20722384d068eb7339de802154d61bc5"}, + {file = "aiohttp-3.10.10-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:998f3bd3cfc95e9424a6acd7840cbdd39e45bc09ef87533c006f94ac47296090"}, + {file = "aiohttp-3.10.10-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d9010c31cd6fa59438da4e58a7f19e4753f7f264300cd152e7f90d4602449762"}, + {file = "aiohttp-3.10.10-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7ea7ffc6d6d6f8a11e6f40091a1040995cdff02cfc9ba4c2f30a516cb2633554"}, + {file = "aiohttp-3.10.10-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:ef9c33cc5cbca35808f6c74be11eb7f5f6b14d2311be84a15b594bd3e58b5527"}, + {file = "aiohttp-3.10.10-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:ce0cdc074d540265bfeb31336e678b4e37316849d13b308607efa527e981f5c2"}, + {file = "aiohttp-3.10.10-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:597a079284b7ee65ee102bc3a6ea226a37d2b96d0418cc9047490f231dc09fe8"}, + {file = "aiohttp-3.10.10-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:7789050d9e5d0c309c706953e5e8876e38662d57d45f936902e176d19f1c58ab"}, + {file = "aiohttp-3.10.10-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:e7f8b04d83483577fd9200461b057c9f14ced334dcb053090cea1da9c8321a91"}, + {file = "aiohttp-3.10.10-cp39-cp39-win32.whl", hash = "sha256:c02a30b904282777d872266b87b20ed8cc0d1501855e27f831320f471d54d983"}, + {file = "aiohttp-3.10.10-cp39-cp39-win_amd64.whl", hash = "sha256:edfe3341033a6b53a5c522c802deb2079eee5cbfbb0af032a55064bd65c73a23"}, + {file = "aiohttp-3.10.10.tar.gz", hash = "sha256:0631dd7c9f0822cc61c88586ca76d5b5ada26538097d0f1df510b082bad3411a"}, ] [package.dependencies] @@ -114,7 +129,7 @@ async-timeout = {version = ">=4.0,<5.0", markers = "python_version < \"3.11\""} attrs = ">=17.3.0" frozenlist = ">=1.1.1" multidict = ">=4.5,<7.0" -yarl = ">=1.0,<2.0" +yarl = ">=1.12.0,<2.0" [package.extras] speedups = ["Brotli", "aiodns (>=3.2.0)", "brotlicffi"] @@ -160,13 +175,13 @@ files = [ [[package]] name = "anyio" -version = "4.4.0" +version = "4.6.2.post1" description = "High level compatibility layer for multiple asynchronous event loop implementations" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "anyio-4.4.0-py3-none-any.whl", hash = "sha256:c1b2d8f46a8a812513012e1107cb0e68c17159a7a594208005a57dc776e1bdc7"}, - {file = "anyio-4.4.0.tar.gz", hash = "sha256:5aadc6a1bbb7cdb0bede386cac5e2940f5e2ff3aa20277e991cf028e0585ce94"}, + {file = "anyio-4.6.2.post1-py3-none-any.whl", hash = "sha256:6d170c36fba3bdd840c73d3868c1e777e33676a69c3a72cf0a0d5d6d8009b61d"}, + {file = "anyio-4.6.2.post1.tar.gz", hash = "sha256:4c8bc31ccdb51c7f7bd251f51c609e038d63e34219b44aa86e47576389880b4c"}, ] [package.dependencies] @@ -176,9 +191,9 @@ sniffio = ">=1.1" typing-extensions = {version = ">=4.1", markers = "python_version < \"3.11\""} [package.extras] -doc = ["Sphinx (>=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"] -test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"] -trio = ["trio (>=0.23)"] +doc = ["Sphinx (>=7.4,<8.0)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"] +test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "truststore (>=0.9.1)", "uvloop (>=0.21.0b1)"] +trio = ["trio (>=0.26.1)"] [[package]] name = "async-timeout" @@ -250,81 +265,81 @@ test = ["flake8 (>=6.1,<7.0)", "uvloop (>=0.15.3)"] [[package]] name = "attrs" -version = "23.2.0" +version = "24.2.0" description = "Classes Without Boilerplate" optional = false python-versions = ">=3.7" files = [ - {file = "attrs-23.2.0-py3-none-any.whl", hash = "sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1"}, - {file = "attrs-23.2.0.tar.gz", hash = "sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30"}, + {file = "attrs-24.2.0-py3-none-any.whl", hash = "sha256:81921eb96de3191c8258c199618104dd27ac608d9366f5e35d011eae1867ede2"}, + {file = "attrs-24.2.0.tar.gz", hash = "sha256:5cfb1b9148b5b086569baec03f20d7b6bf3bcacc9a42bebf87ffaaca362f6346"}, ] [package.extras] -cov = ["attrs[tests]", "coverage[toml] (>=5.3)"] -dev = ["attrs[tests]", "pre-commit"] -docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"] -tests = ["attrs[tests-no-zope]", "zope-interface"] -tests-mypy = ["mypy (>=1.6)", "pytest-mypy-plugins"] -tests-no-zope = ["attrs[tests-mypy]", "cloudpickle", "hypothesis", "pympler", "pytest (>=4.3.0)", "pytest-xdist[psutil]"] +benchmark = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +cov = ["cloudpickle", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +dev = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier (<24.7)"] +tests = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +tests-mypy = ["mypy (>=1.11.1)", "pytest-mypy-plugins"] [[package]] name = "bento-lib" -version = "11.11.2" +version = "12.2.2" description = "A set of common utilities and helpers for Bento platform services." optional = false python-versions = "<4.0,>=3.10" files = [ - {file = "bento_lib-11.11.2-py3-none-any.whl", hash = "sha256:684edb7d084ca8b401d3beb9e6b50a108e00dc7bceca2829992908563ce45f62"}, - {file = "bento_lib-11.11.2.tar.gz", hash = "sha256:ec9056ce22a2be6fe5bd6075e6f69ea32f821c024710ed3daa5807905a6e4bc7"}, + {file = "bento_lib-12.2.2-py3-none-any.whl", hash = "sha256:c664325ff59914379e7f41f70f0a6fc78223060ad4daa1bda55a56a458c5e3d9"}, + {file = "bento_lib-12.2.2.tar.gz", hash = "sha256:1827569c3bf3eca8ac97a49c406a3267bc96ae46b20ededf4a5f39f5887bd3c7"}, ] [package.dependencies] -aiofiles = ">=23.2.1,<25" -aiohttp = ">=3.9.4,<4" -fastapi = {version = ">=0.104,<0.112", optional = true, markers = "extra == \"fastapi\""} -jsonschema = ">=4.20.0,<5" +aiofiles = ">=24.1.0,<25" +aiohttp = ">=3.10.5,<4" +fastapi = {version = ">=0.112.1,<0.116", optional = true, markers = "extra == \"fastapi\""} +jsonschema = ">=4.23.0,<5" psycopg2-binary = ">=2.9.9,<3.0" -pydantic = ">=2.5.2,<3" -pydantic-settings = ">=2.1.0,<3" -redis = ">=5.0.1,<6" -requests = ">=2.31.0,<3" +pydantic = ">=2.8.2,<3" +pydantic-settings = ">=2.4.0,<3" +redis = ">=5.0.8,<6" +requests = ">=2.32.3,<3" werkzeug = ">=2.2.3,<4" [package.extras] asyncpg = ["asyncpg (>=0.29.0,<0.30.0)"] -django = ["django (>=4.2.7,<5.1)", "djangorestframework (>=3.14.0,<3.16)"] -fastapi = ["fastapi (>=0.104,<0.112)"] +django = ["django (>=5.0.8,<5.2)", "djangorestframework (>=3.14.0,<3.16)"] +fastapi = ["fastapi (>=0.112.1,<0.116)"] flask = ["flask (>=2.2.5,<4)"] [[package]] name = "black" -version = "24.8.0" +version = "24.10.0" description = "The uncompromising code formatter." optional = false -python-versions = ">=3.8" -files = [ - {file = "black-24.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:09cdeb74d494ec023ded657f7092ba518e8cf78fa8386155e4a03fdcc44679e6"}, - {file = "black-24.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:81c6742da39f33b08e791da38410f32e27d632260e599df7245cccee2064afeb"}, - {file = "black-24.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:707a1ca89221bc8a1a64fb5e15ef39cd755633daa672a9db7498d1c19de66a42"}, - {file = "black-24.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:d6417535d99c37cee4091a2f24eb2b6d5ec42b144d50f1f2e436d9fe1916fe1a"}, - {file = "black-24.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:fb6e2c0b86bbd43dee042e48059c9ad7830abd5c94b0bc518c0eeec57c3eddc1"}, - {file = "black-24.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:837fd281f1908d0076844bc2b801ad2d369c78c45cf800cad7b61686051041af"}, - {file = "black-24.8.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:62e8730977f0b77998029da7971fa896ceefa2c4c4933fcd593fa599ecbf97a4"}, - {file = "black-24.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:72901b4913cbac8972ad911dc4098d5753704d1f3c56e44ae8dce99eecb0e3af"}, - {file = "black-24.8.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:7c046c1d1eeb7aea9335da62472481d3bbf3fd986e093cffd35f4385c94ae368"}, - {file = "black-24.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:649f6d84ccbae73ab767e206772cc2d7a393a001070a4c814a546afd0d423aed"}, - {file = "black-24.8.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2b59b250fdba5f9a9cd9d0ece6e6d993d91ce877d121d161e4698af3eb9c1018"}, - {file = "black-24.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:6e55d30d44bed36593c3163b9bc63bf58b3b30e4611e4d88a0c3c239930ed5b2"}, - {file = "black-24.8.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:505289f17ceda596658ae81b61ebbe2d9b25aa78067035184ed0a9d855d18afd"}, - {file = "black-24.8.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b19c9ad992c7883ad84c9b22aaa73562a16b819c1d8db7a1a1a49fb7ec13c7d2"}, - {file = "black-24.8.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1f13f7f386f86f8121d76599114bb8c17b69d962137fc70efe56137727c7047e"}, - {file = "black-24.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:f490dbd59680d809ca31efdae20e634f3fae27fba3ce0ba3208333b713bc3920"}, - {file = "black-24.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:eab4dd44ce80dea27dc69db40dab62d4ca96112f87996bca68cd75639aeb2e4c"}, - {file = "black-24.8.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3c4285573d4897a7610054af5a890bde7c65cb466040c5f0c8b732812d7f0e5e"}, - {file = "black-24.8.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9e84e33b37be070ba135176c123ae52a51f82306def9f7d063ee302ecab2cf47"}, - {file = "black-24.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:73bbf84ed136e45d451a260c6b73ed674652f90a2b3211d6a35e78054563a9bb"}, - {file = "black-24.8.0-py3-none-any.whl", hash = "sha256:972085c618ee94f402da1af548a4f218c754ea7e5dc70acb168bfaca4c2542ed"}, - {file = "black-24.8.0.tar.gz", hash = "sha256:2500945420b6784c38b9ee885af039f5e7471ef284ab03fa35ecdde4688cd83f"}, +python-versions = ">=3.9" +files = [ + {file = "black-24.10.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e6668650ea4b685440857138e5fe40cde4d652633b1bdffc62933d0db4ed9812"}, + {file = "black-24.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1c536fcf674217e87b8cc3657b81809d3c085d7bf3ef262ead700da345bfa6ea"}, + {file = "black-24.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:649fff99a20bd06c6f727d2a27f401331dc0cc861fb69cde910fe95b01b5928f"}, + {file = "black-24.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:fe4d6476887de70546212c99ac9bd803d90b42fc4767f058a0baa895013fbb3e"}, + {file = "black-24.10.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5a2221696a8224e335c28816a9d331a6c2ae15a2ee34ec857dcf3e45dbfa99ad"}, + {file = "black-24.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f9da3333530dbcecc1be13e69c250ed8dfa67f43c4005fb537bb426e19200d50"}, + {file = "black-24.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4007b1393d902b48b36958a216c20c4482f601569d19ed1df294a496eb366392"}, + {file = "black-24.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:394d4ddc64782e51153eadcaaca95144ac4c35e27ef9b0a42e121ae7e57a9175"}, + {file = "black-24.10.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b5e39e0fae001df40f95bd8cc36b9165c5e2ea88900167bddf258bacef9bbdc3"}, + {file = "black-24.10.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d37d422772111794b26757c5b55a3eade028aa3fde43121ab7b673d050949d65"}, + {file = "black-24.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:14b3502784f09ce2443830e3133dacf2c0110d45191ed470ecb04d0f5f6fcb0f"}, + {file = "black-24.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:30d2c30dc5139211dda799758559d1b049f7f14c580c409d6ad925b74a4208a8"}, + {file = "black-24.10.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1cbacacb19e922a1d75ef2b6ccaefcd6e93a2c05ede32f06a21386a04cedb981"}, + {file = "black-24.10.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1f93102e0c5bb3907451063e08b9876dbeac810e7da5a8bfb7aeb5a9ef89066b"}, + {file = "black-24.10.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ddacb691cdcdf77b96f549cf9591701d8db36b2f19519373d60d31746068dbf2"}, + {file = "black-24.10.0-cp313-cp313-win_amd64.whl", hash = "sha256:680359d932801c76d2e9c9068d05c6b107f2584b2a5b88831c83962eb9984c1b"}, + {file = "black-24.10.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:17374989640fbca88b6a448129cd1745c5eb8d9547b464f281b251dd00155ccd"}, + {file = "black-24.10.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:63f626344343083322233f175aaf372d326de8436f5928c042639a4afbbf1d3f"}, + {file = "black-24.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccfa1d0cb6200857f1923b602f978386a3a2758a65b52e0950299ea014be6800"}, + {file = "black-24.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:2cd9c95431d94adc56600710f8813ee27eea544dd118d45896bb734e9d7a0dc7"}, + {file = "black-24.10.0-py3-none-any.whl", hash = "sha256:3bb2b7a1f7b685f85b11fed1ef10f8a9148bceb49853e47a294a3dd963c1dd7d"}, + {file = "black-24.10.0.tar.gz", hash = "sha256:846ea64c97afe3bc677b761787993be4991810ecc7a4a937816dd6bddedc4875"}, ] [package.dependencies] @@ -338,30 +353,30 @@ typing-extensions = {version = ">=4.0.1", markers = "python_version < \"3.11\""} [package.extras] colorama = ["colorama (>=0.4.3)"] -d = ["aiohttp (>=3.7.4)", "aiohttp (>=3.7.4,!=3.9.0)"] +d = ["aiohttp (>=3.10)"] jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] uvloop = ["uvloop (>=0.15.2)"] [[package]] name = "cachetools" -version = "5.4.0" +version = "5.5.0" description = "Extensible memoizing collections and decorators" optional = false python-versions = ">=3.7" files = [ - {file = "cachetools-5.4.0-py3-none-any.whl", hash = "sha256:3ae3b49a3d5e28a77a0be2b37dbcb89005058959cb2323858c2657c4a8cab474"}, - {file = "cachetools-5.4.0.tar.gz", hash = "sha256:b8adc2e7c07f105ced7bc56dbb6dfbe7c4a00acce20e2227b3f355be89bc6827"}, + {file = "cachetools-5.5.0-py3-none-any.whl", hash = "sha256:02134e8439cdc2ffb62023ce1debca2944c3f289d66bb17ead3ab3dede74b292"}, + {file = "cachetools-5.5.0.tar.gz", hash = "sha256:2cc24fb4cbe39633fb7badd9db9ca6295d766d9c2995f245725a46715d050f2a"}, ] [[package]] name = "certifi" -version = "2024.7.4" +version = "2024.8.30" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" files = [ - {file = "certifi-2024.7.4-py3-none-any.whl", hash = "sha256:c198e21b1289c2ab85ee4e67bb4b4ef3ead0892059901a8d5b622f24a1101e90"}, - {file = "certifi-2024.7.4.tar.gz", hash = "sha256:5a1e7645bc0ec61a09e26c36f6106dd4cf40c6db3a1fb6352b0244e7fb057c7b"}, + {file = "certifi-2024.8.30-py3-none-any.whl", hash = "sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8"}, + {file = "certifi-2024.8.30.tar.gz", hash = "sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9"}, ] [[package]] @@ -377,101 +392,116 @@ files = [ [[package]] name = "charset-normalizer" -version = "3.3.2" +version = "3.4.0" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." optional = false python-versions = ">=3.7.0" files = [ - {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"}, - {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:4f9fc98dad6c2eaa32fc3af1417d95b5e3d08aff968df0cd320066def971f9a6"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0de7b687289d3c1b3e8660d0741874abe7888100efe14bd0f9fd7141bcbda92b"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5ed2e36c3e9b4f21dd9422f6893dec0abf2cca553af509b10cd630f878d3eb99"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40d3ff7fc90b98c637bda91c89d51264a3dcf210cade3a2c6f838c7268d7a4ca"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1110e22af8ca26b90bd6364fe4c763329b0ebf1ee213ba32b68c73de5752323d"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:86f4e8cca779080f66ff4f191a685ced73d2f72d50216f7112185dc02b90b9b7"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f683ddc7eedd742e2889d2bfb96d69573fde1d92fcb811979cdb7165bb9c7d3"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:27623ba66c183eca01bf9ff833875b459cad267aeeb044477fedac35e19ba907"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f606a1881d2663630ea5b8ce2efe2111740df4b687bd78b34a8131baa007f79b"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:0b309d1747110feb25d7ed6b01afdec269c647d382c857ef4663bbe6ad95a912"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:136815f06a3ae311fae551c3df1f998a1ebd01ddd424aa5603a4336997629e95"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:14215b71a762336254351b00ec720a8e85cada43b987da5a042e4ce3e82bd68e"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:79983512b108e4a164b9c8d34de3992f76d48cadc9554c9e60b43f308988aabe"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-win32.whl", hash = "sha256:c94057af19bc953643a33581844649a7fdab902624d2eb739738a30e2b3e60fc"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:55f56e2ebd4e3bc50442fbc0888c9d8c94e4e06a933804e2af3e89e2f9c1c749"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0d99dd8ff461990f12d6e42c7347fd9ab2532fb70e9621ba520f9e8637161d7c"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c57516e58fd17d03ebe67e181a4e4e2ccab1168f8c2976c6a334d4f819fe5944"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6dba5d19c4dfab08e58d5b36304b3f92f3bd5d42c1a3fa37b5ba5cdf6dfcbcee"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf4475b82be41b07cc5e5ff94810e6a01f276e37c2d55571e3fe175e467a1a1c"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce031db0408e487fd2775d745ce30a7cd2923667cf3b69d48d219f1d8f5ddeb6"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ff4e7cdfdb1ab5698e675ca622e72d58a6fa2a8aa58195de0c0061288e6e3ea"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3710a9751938947e6327ea9f3ea6332a09bf0ba0c09cae9cb1f250bd1f1549bc"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82357d85de703176b5587dbe6ade8ff67f9f69a41c0733cf2425378b49954de5"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:47334db71978b23ebcf3c0f9f5ee98b8d65992b65c9c4f2d34c2eaf5bcaf0594"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8ce7fd6767a1cc5a92a639b391891bf1c268b03ec7e021c7d6d902285259685c"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f1a2f519ae173b5b6a2c9d5fa3116ce16e48b3462c8b96dfdded11055e3d6365"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:63bc5c4ae26e4bc6be6469943b8253c0fd4e4186c43ad46e713ea61a0ba49129"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bcb4f8ea87d03bc51ad04add8ceaf9b0f085ac045ab4d74e73bbc2dc033f0236"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-win32.whl", hash = "sha256:9ae4ef0b3f6b41bad6366fb0ea4fc1d7ed051528e113a60fa2a65a9abb5b1d99"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:cee4373f4d3ad28f1ab6290684d8e2ebdb9e7a1b74fdc39e4c211995f77bec27"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0713f3adb9d03d49d365b70b84775d0a0d18e4ab08d12bc46baa6132ba78aaf6"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:de7376c29d95d6719048c194a9cf1a1b0393fbe8488a22008610b0361d834ecf"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4a51b48f42d9358460b78725283f04bddaf44a9358197b889657deba38f329db"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b295729485b06c1a0683af02a9e42d2caa9db04a373dc38a6a58cdd1e8abddf1"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ee803480535c44e7f5ad00788526da7d85525cfefaf8acf8ab9a310000be4b03"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d59d125ffbd6d552765510e3f31ed75ebac2c7470c7274195b9161a32350284"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8cda06946eac330cbe6598f77bb54e690b4ca93f593dee1568ad22b04f347c15"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07afec21bbbbf8a5cc3651aa96b980afe2526e7f048fdfb7f1014d84acc8b6d8"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6b40e8d38afe634559e398cc32b1472f376a4099c75fe6299ae607e404c033b2"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b8dcd239c743aa2f9c22ce674a145e0a25cb1566c495928440a181ca1ccf6719"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:84450ba661fb96e9fd67629b93d2941c871ca86fc38d835d19d4225ff946a631"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:44aeb140295a2f0659e113b31cfe92c9061622cadbc9e2a2f7b8ef6b1e29ef4b"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1db4e7fefefd0f548d73e2e2e041f9df5c59e178b4c72fbac4cc6f535cfb1565"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-win32.whl", hash = "sha256:5726cf76c982532c1863fb64d8c6dd0e4c90b6ece9feb06c9f202417a31f7dd7"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:b197e7094f232959f8f20541ead1d9862ac5ebea1d58e9849c1bf979255dfac9"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:dd4eda173a9fcccb5f2e2bd2a9f423d180194b1bf17cf59e3269899235b2a114"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e9e3c4c9e1ed40ea53acf11e2a386383c3304212c965773704e4603d589343ed"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:92a7e36b000bf022ef3dbb9c46bfe2d52c047d5e3f3343f43204263c5addc250"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54b6a92d009cbe2fb11054ba694bc9e284dad30a26757b1e372a1fdddaf21920"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ffd9493de4c922f2a38c2bf62b831dcec90ac673ed1ca182fe11b4d8e9f2a64"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:35c404d74c2926d0287fbd63ed5d27eb911eb9e4a3bb2c6d294f3cfd4a9e0c23"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4796efc4faf6b53a18e3d46343535caed491776a22af773f366534056c4e1fbc"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e7fdd52961feb4c96507aa649550ec2a0d527c086d284749b2f582f2d40a2e0d"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:92db3c28b5b2a273346bebb24857fda45601aef6ae1c011c0a997106581e8a88"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ab973df98fc99ab39080bfb0eb3a925181454d7c3ac8a1e695fddfae696d9e90"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4b67fdab07fdd3c10bb21edab3cbfe8cf5696f453afce75d815d9d7223fbe88b"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:aa41e526a5d4a9dfcfbab0716c7e8a1b215abd3f3df5a45cf18a12721d31cb5d"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ffc519621dce0c767e96b9c53f09c5d215578e10b02c285809f76509a3931482"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-win32.whl", hash = "sha256:f19c1585933c82098c2a520f8ec1227f20e339e33aca8fa6f956f6691b784e67"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:707b82d19e65c9bd28b81dde95249b07bf9f5b90ebe1ef17d9b57473f8a64b7b"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:dbe03226baf438ac4fda9e2d0715022fd579cb641c4cf639fa40d53b2fe6f3e2"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd9a8bd8900e65504a305bf8ae6fa9fbc66de94178c420791d0293702fce2df7"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8831399554b92b72af5932cdbbd4ddc55c55f631bb13ff8fe4e6536a06c5c51"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a14969b8691f7998e74663b77b4c36c0337cb1df552da83d5c9004a93afdb574"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dcaf7c1524c0542ee2fc82cc8ec337f7a9f7edee2532421ab200d2b920fc97cf"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:425c5f215d0eecee9a56cdb703203dda90423247421bf0d67125add85d0c4455"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:d5b054862739d276e09928de37c79ddeec42a6e1bfc55863be96a36ba22926f6"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:f3e73a4255342d4eb26ef6df01e3962e73aa29baa3124a8e824c5d3364a65748"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:2f6c34da58ea9c1a9515621f4d9ac379871a8f21168ba1b5e09d74250de5ad62"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:f09cb5a7bbe1ecae6e87901a2eb23e0256bb524a79ccc53eb0b7629fbe7677c4"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:0099d79bdfcf5c1f0c2c72f91516702ebf8b0b8ddd8905f97a8aecf49712c621"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-win32.whl", hash = "sha256:9c98230f5042f4945f957d006edccc2af1e03ed5e37ce7c373f00a5a4daa6149"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:62f60aebecfc7f4b82e3f639a7d1433a20ec32824db2199a11ad4f5e146ef5ee"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:af73657b7a68211996527dbfeffbb0864e043d270580c5aef06dc4b659a4b578"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cab5d0b79d987c67f3b9e9c53f54a61360422a5a0bc075f43cab5621d530c3b6"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9289fd5dddcf57bab41d044f1756550f9e7cf0c8e373b8cdf0ce8773dc4bd417"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b493a043635eb376e50eedf7818f2f322eabbaa974e948bd8bdd29eb7ef2a51"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fa2566ca27d67c86569e8c85297aaf413ffab85a8960500f12ea34ff98e4c41"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8e538f46104c815be19c975572d74afb53f29650ea2025bbfaef359d2de2f7f"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fd30dc99682dc2c603c2b315bded2799019cea829f8bf57dc6b61efde6611c8"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2006769bd1640bdf4d5641c69a3d63b71b81445473cac5ded39740a226fa88ab"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:dc15e99b2d8a656f8e666854404f1ba54765871104e50c8e9813af8a7db07f12"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:ab2e5bef076f5a235c3774b4f4028a680432cded7cad37bba0fd90d64b187d19"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:4ec9dd88a5b71abfc74e9df5ebe7921c35cbb3b641181a531ca65cdb5e8e4dea"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:43193c5cda5d612f247172016c4bb71251c784d7a4d9314677186a838ad34858"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:aa693779a8b50cd97570e5a0f343538a8dbd3e496fa5dcb87e29406ad0299654"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-win32.whl", hash = "sha256:7706f5850360ac01d80c89bcef1640683cc12ed87f42579dab6c5d3ed6888613"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:c3e446d253bd88f6377260d07c895816ebf33ffffd56c1c792b13bff9c3e1ade"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:980b4f289d1d90ca5efcf07958d3eb38ed9c0b7676bf2831a54d4f66f9c27dfa"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f28f891ccd15c514a0981f3b9db9aa23d62fe1a99997512b0491d2ed323d229a"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8aacce6e2e1edcb6ac625fb0f8c3a9570ccc7bfba1f63419b3769ccf6a00ed0"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd7af3717683bea4c87acd8c0d3d5b44d56120b26fd3f8a692bdd2d5260c620a"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5ff2ed8194587faf56555927b3aa10e6fb69d931e33953943bc4f837dfee2242"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e91f541a85298cf35433bf66f3fab2a4a2cff05c127eeca4af174f6d497f0d4b"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:309a7de0a0ff3040acaebb35ec45d18db4b28232f21998851cfa709eeff49d62"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:285e96d9d53422efc0d7a17c60e59f37fbf3dfa942073f666db4ac71e8d726d0"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:5d447056e2ca60382d460a604b6302d8db69476fd2015c81e7c35417cfabe4cd"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:20587d20f557fe189b7947d8e7ec5afa110ccf72a3128d61a2a387c3313f46be"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:130272c698667a982a5d0e626851ceff662565379baf0ff2cc58067b81d4f11d"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:ab22fbd9765e6954bc0bcff24c25ff71dcbfdb185fcdaca49e81bac68fe724d3"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7782afc9b6b42200f7362858f9e73b1f8316afb276d316336c0ec3bd73312742"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-win32.whl", hash = "sha256:2de62e8801ddfff069cd5c504ce3bc9672b23266597d4e4f50eda28846c322f2"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:95c3c157765b031331dd4db3c775e58deaee050a3042fcad72cbc4189d7c8dca"}, + {file = "charset_normalizer-3.4.0-py3-none-any.whl", hash = "sha256:fe9f97feb71aa9896b81973a7bbada8c49501dc73e58a10fcef6663af95e5079"}, + {file = "charset_normalizer-3.4.0.tar.gz", hash = "sha256:223217c3d4f82c3ac5e29032b3f1c2eb0fb591b72161f86d93f5719079dae93e"}, ] [[package]] @@ -501,63 +531,73 @@ files = [ [[package]] name = "coverage" -version = "7.6.0" +version = "7.6.3" description = "Code coverage measurement for Python" optional = false -python-versions = ">=3.8" -files = [ - {file = "coverage-7.6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:dff044f661f59dace805eedb4a7404c573b6ff0cdba4a524141bc63d7be5c7fd"}, - {file = "coverage-7.6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a8659fd33ee9e6ca03950cfdcdf271d645cf681609153f218826dd9805ab585c"}, - {file = "coverage-7.6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7792f0ab20df8071d669d929c75c97fecfa6bcab82c10ee4adb91c7a54055463"}, - {file = "coverage-7.6.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d4b3cd1ca7cd73d229487fa5caca9e4bc1f0bca96526b922d61053ea751fe791"}, - {file = "coverage-7.6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e7e128f85c0b419907d1f38e616c4f1e9f1d1b37a7949f44df9a73d5da5cd53c"}, - {file = "coverage-7.6.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a94925102c89247530ae1dab7dc02c690942566f22e189cbd53579b0693c0783"}, - {file = "coverage-7.6.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:dcd070b5b585b50e6617e8972f3fbbee786afca71b1936ac06257f7e178f00f6"}, - {file = "coverage-7.6.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:d50a252b23b9b4dfeefc1f663c568a221092cbaded20a05a11665d0dbec9b8fb"}, - {file = "coverage-7.6.0-cp310-cp310-win32.whl", hash = "sha256:0e7b27d04131c46e6894f23a4ae186a6a2207209a05df5b6ad4caee6d54a222c"}, - {file = "coverage-7.6.0-cp310-cp310-win_amd64.whl", hash = "sha256:54dece71673b3187c86226c3ca793c5f891f9fc3d8aa183f2e3653da18566169"}, - {file = "coverage-7.6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c7b525ab52ce18c57ae232ba6f7010297a87ced82a2383b1afd238849c1ff933"}, - {file = "coverage-7.6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4bea27c4269234e06f621f3fac3925f56ff34bc14521484b8f66a580aacc2e7d"}, - {file = "coverage-7.6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed8d1d1821ba5fc88d4a4f45387b65de52382fa3ef1f0115a4f7a20cdfab0e94"}, - {file = "coverage-7.6.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:01c322ef2bbe15057bc4bf132b525b7e3f7206f071799eb8aa6ad1940bcf5fb1"}, - {file = "coverage-7.6.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:03cafe82c1b32b770a29fd6de923625ccac3185a54a5e66606da26d105f37dac"}, - {file = "coverage-7.6.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0d1b923fc4a40c5832be4f35a5dab0e5ff89cddf83bb4174499e02ea089daf57"}, - {file = "coverage-7.6.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4b03741e70fb811d1a9a1d75355cf391f274ed85847f4b78e35459899f57af4d"}, - {file = "coverage-7.6.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a73d18625f6a8a1cbb11eadc1d03929f9510f4131879288e3f7922097a429f63"}, - {file = "coverage-7.6.0-cp311-cp311-win32.whl", hash = "sha256:65fa405b837060db569a61ec368b74688f429b32fa47a8929a7a2f9b47183713"}, - {file = "coverage-7.6.0-cp311-cp311-win_amd64.whl", hash = "sha256:6379688fb4cfa921ae349c76eb1a9ab26b65f32b03d46bb0eed841fd4cb6afb1"}, - {file = "coverage-7.6.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f7db0b6ae1f96ae41afe626095149ecd1b212b424626175a6633c2999eaad45b"}, - {file = "coverage-7.6.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:bbdf9a72403110a3bdae77948b8011f644571311c2fb35ee15f0f10a8fc082e8"}, - {file = "coverage-7.6.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cc44bf0315268e253bf563f3560e6c004efe38f76db03a1558274a6e04bf5d5"}, - {file = "coverage-7.6.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:da8549d17489cd52f85a9829d0e1d91059359b3c54a26f28bec2c5d369524807"}, - {file = "coverage-7.6.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0086cd4fc71b7d485ac93ca4239c8f75732c2ae3ba83f6be1c9be59d9e2c6382"}, - {file = "coverage-7.6.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1fad32ee9b27350687035cb5fdf9145bc9cf0a094a9577d43e909948ebcfa27b"}, - {file = "coverage-7.6.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:044a0985a4f25b335882b0966625270a8d9db3d3409ddc49a4eb00b0ef5e8cee"}, - {file = "coverage-7.6.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:76d5f82213aa78098b9b964ea89de4617e70e0d43e97900c2778a50856dac605"}, - {file = "coverage-7.6.0-cp312-cp312-win32.whl", hash = "sha256:3c59105f8d58ce500f348c5b56163a4113a440dad6daa2294b5052a10db866da"}, - {file = "coverage-7.6.0-cp312-cp312-win_amd64.whl", hash = "sha256:ca5d79cfdae420a1d52bf177de4bc2289c321d6c961ae321503b2ca59c17ae67"}, - {file = "coverage-7.6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d39bd10f0ae453554798b125d2f39884290c480f56e8a02ba7a6ed552005243b"}, - {file = "coverage-7.6.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:beb08e8508e53a568811016e59f3234d29c2583f6b6e28572f0954a6b4f7e03d"}, - {file = "coverage-7.6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b2e16f4cd2bc4d88ba30ca2d3bbf2f21f00f382cf4e1ce3b1ddc96c634bc48ca"}, - {file = "coverage-7.6.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6616d1c9bf1e3faea78711ee42a8b972367d82ceae233ec0ac61cc7fec09fa6b"}, - {file = "coverage-7.6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad4567d6c334c46046d1c4c20024de2a1c3abc626817ae21ae3da600f5779b44"}, - {file = "coverage-7.6.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:d17c6a415d68cfe1091d3296ba5749d3d8696e42c37fca5d4860c5bf7b729f03"}, - {file = "coverage-7.6.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:9146579352d7b5f6412735d0f203bbd8d00113a680b66565e205bc605ef81bc6"}, - {file = "coverage-7.6.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:cdab02a0a941af190df8782aafc591ef3ad08824f97850b015c8c6a8b3877b0b"}, - {file = "coverage-7.6.0-cp38-cp38-win32.whl", hash = "sha256:df423f351b162a702c053d5dddc0fc0ef9a9e27ea3f449781ace5f906b664428"}, - {file = "coverage-7.6.0-cp38-cp38-win_amd64.whl", hash = "sha256:f2501d60d7497fd55e391f423f965bbe9e650e9ffc3c627d5f0ac516026000b8"}, - {file = "coverage-7.6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7221f9ac9dad9492cecab6f676b3eaf9185141539d5c9689d13fd6b0d7de840c"}, - {file = "coverage-7.6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ddaaa91bfc4477d2871442bbf30a125e8fe6b05da8a0015507bfbf4718228ab2"}, - {file = "coverage-7.6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4cbe651f3904e28f3a55d6f371203049034b4ddbce65a54527a3f189ca3b390"}, - {file = "coverage-7.6.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:831b476d79408ab6ccfadaaf199906c833f02fdb32c9ab907b1d4aa0713cfa3b"}, - {file = "coverage-7.6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46c3d091059ad0b9c59d1034de74a7f36dcfa7f6d3bde782c49deb42438f2450"}, - {file = "coverage-7.6.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:4d5fae0a22dc86259dee66f2cc6c1d3e490c4a1214d7daa2a93d07491c5c04b6"}, - {file = "coverage-7.6.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:07ed352205574aad067482e53dd606926afebcb5590653121063fbf4e2175166"}, - {file = "coverage-7.6.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:49c76cdfa13015c4560702574bad67f0e15ca5a2872c6a125f6327ead2b731dd"}, - {file = "coverage-7.6.0-cp39-cp39-win32.whl", hash = "sha256:482855914928c8175735a2a59c8dc5806cf7d8f032e4820d52e845d1f731dca2"}, - {file = "coverage-7.6.0-cp39-cp39-win_amd64.whl", hash = "sha256:543ef9179bc55edfd895154a51792b01c017c87af0ebaae092720152e19e42ca"}, - {file = "coverage-7.6.0-pp38.pp39.pp310-none-any.whl", hash = "sha256:6fe885135c8a479d3e37a7aae61cbd3a0fb2deccb4dda3c25f92a49189f766d6"}, - {file = "coverage-7.6.0.tar.gz", hash = "sha256:289cc803fa1dc901f84701ac10c9ee873619320f2f9aff38794db4a4a0268d51"}, +python-versions = ">=3.9" +files = [ + {file = "coverage-7.6.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6da42bbcec130b188169107ecb6ee7bd7b4c849d24c9370a0c884cf728d8e976"}, + {file = "coverage-7.6.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c222958f59b0ae091f4535851cbb24eb57fc0baea07ba675af718fb5302dddb2"}, + {file = "coverage-7.6.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ab84a8b698ad5a6c365b08061920138e7a7dd9a04b6feb09ba1bfae68346ce6d"}, + {file = "coverage-7.6.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:70a6756ce66cd6fe8486c775b30889f0dc4cb20c157aa8c35b45fd7868255c5c"}, + {file = "coverage-7.6.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c2e6fa98032fec8282f6b27e3f3986c6e05702828380618776ad794e938f53a"}, + {file = "coverage-7.6.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:921fbe13492caf6a69528f09d5d7c7d518c8d0e7b9f6701b7719715f29a71e6e"}, + {file = "coverage-7.6.3-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:6d99198203f0b9cb0b5d1c0393859555bc26b548223a769baf7e321a627ed4fc"}, + {file = "coverage-7.6.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:87cd2e29067ea397a47e352efb13f976eb1b03e18c999270bb50589323294c6e"}, + {file = "coverage-7.6.3-cp310-cp310-win32.whl", hash = "sha256:a3328c3e64ea4ab12b85999eb0779e6139295bbf5485f69d42cf794309e3d007"}, + {file = "coverage-7.6.3-cp310-cp310-win_amd64.whl", hash = "sha256:bca4c8abc50d38f9773c1ec80d43f3768df2e8576807d1656016b9d3eeaa96fd"}, + {file = "coverage-7.6.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c51ef82302386d686feea1c44dbeef744585da16fcf97deea2a8d6c1556f519b"}, + {file = "coverage-7.6.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0ca37993206402c6c35dc717f90d4c8f53568a8b80f0bf1a1b2b334f4d488fba"}, + {file = "coverage-7.6.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c77326300b839c44c3e5a8fe26c15b7e87b2f32dfd2fc9fee1d13604347c9b38"}, + {file = "coverage-7.6.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e484e479860e00da1f005cd19d1c5d4a813324e5951319ac3f3eefb497cc549"}, + {file = "coverage-7.6.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c6c0f4d53ef603397fc894a895b960ecd7d44c727df42a8d500031716d4e8d2"}, + {file = "coverage-7.6.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:37be7b5ea3ff5b7c4a9db16074dc94523b5f10dd1f3b362a827af66a55198175"}, + {file = "coverage-7.6.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:43b32a06c47539fe275106b376658638b418c7cfdfff0e0259fbf877e845f14b"}, + {file = "coverage-7.6.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ee77c7bef0724165e795b6b7bf9c4c22a9b8468a6bdb9c6b4281293c6b22a90f"}, + {file = "coverage-7.6.3-cp311-cp311-win32.whl", hash = "sha256:43517e1f6b19f610a93d8227e47790722c8bf7422e46b365e0469fc3d3563d97"}, + {file = "coverage-7.6.3-cp311-cp311-win_amd64.whl", hash = "sha256:04f2189716e85ec9192df307f7c255f90e78b6e9863a03223c3b998d24a3c6c6"}, + {file = "coverage-7.6.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:27bd5f18d8f2879e45724b0ce74f61811639a846ff0e5c0395b7818fae87aec6"}, + {file = "coverage-7.6.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d546cfa78844b8b9c1c0533de1851569a13f87449897bbc95d698d1d3cb2a30f"}, + {file = "coverage-7.6.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9975442f2e7a5cfcf87299c26b5a45266ab0696348420049b9b94b2ad3d40234"}, + {file = "coverage-7.6.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:583049c63106c0555e3ae3931edab5669668bbef84c15861421b94e121878d3f"}, + {file = "coverage-7.6.3-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2341a78ae3a5ed454d524206a3fcb3cec408c2a0c7c2752cd78b606a2ff15af4"}, + {file = "coverage-7.6.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a4fb91d5f72b7e06a14ff4ae5be625a81cd7e5f869d7a54578fc271d08d58ae3"}, + {file = "coverage-7.6.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e279f3db904e3b55f520f11f983cc8dc8a4ce9b65f11692d4718ed021ec58b83"}, + {file = "coverage-7.6.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:aa23ce39661a3e90eea5f99ec59b763b7d655c2cada10729ed920a38bfc2b167"}, + {file = "coverage-7.6.3-cp312-cp312-win32.whl", hash = "sha256:52ac29cc72ee7e25ace7807249638f94c9b6a862c56b1df015d2b2e388e51dbd"}, + {file = "coverage-7.6.3-cp312-cp312-win_amd64.whl", hash = "sha256:40e8b1983080439d4802d80b951f4a93d991ef3261f69e81095a66f86cf3c3c6"}, + {file = "coverage-7.6.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:9134032f5aa445ae591c2ba6991d10136a1f533b1d2fa8f8c21126468c5025c6"}, + {file = "coverage-7.6.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:99670790f21a96665a35849990b1df447993880bb6463a0a1d757897f30da929"}, + {file = "coverage-7.6.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2dc7d6b380ca76f5e817ac9eef0c3686e7834c8346bef30b041a4ad286449990"}, + {file = "coverage-7.6.3-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f7b26757b22faf88fcf232f5f0e62f6e0fd9e22a8a5d0d5016888cdfe1f6c1c4"}, + {file = "coverage-7.6.3-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c59d6a4a4633fad297f943c03d0d2569867bd5372eb5684befdff8df8522e39"}, + {file = "coverage-7.6.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f263b18692f8ed52c8de7f40a0751e79015983dbd77b16906e5b310a39d3ca21"}, + {file = "coverage-7.6.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:79644f68a6ff23b251cae1c82b01a0b51bc40c8468ca9585c6c4b1aeee570e0b"}, + {file = "coverage-7.6.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:71967c35828c9ff94e8c7d405469a1fb68257f686bca7c1ed85ed34e7c2529c4"}, + {file = "coverage-7.6.3-cp313-cp313-win32.whl", hash = "sha256:e266af4da2c1a4cbc6135a570c64577fd3e6eb204607eaff99d8e9b710003c6f"}, + {file = "coverage-7.6.3-cp313-cp313-win_amd64.whl", hash = "sha256:ea52bd218d4ba260399a8ae4bb6b577d82adfc4518b93566ce1fddd4a49d1dce"}, + {file = "coverage-7.6.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:8d4c6ea0f498c7c79111033a290d060c517853a7bcb2f46516f591dab628ddd3"}, + {file = "coverage-7.6.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:331b200ad03dbaa44151d74daeb7da2cf382db424ab923574f6ecca7d3b30de3"}, + {file = "coverage-7.6.3-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54356a76b67cf8a3085818026bb556545ebb8353951923b88292556dfa9f812d"}, + {file = "coverage-7.6.3-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ebec65f5068e7df2d49466aab9128510c4867e532e07cb6960075b27658dca38"}, + {file = "coverage-7.6.3-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d33a785ea8354c480515e781554d3be582a86297e41ccbea627a5c632647f2cd"}, + {file = "coverage-7.6.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:f7ddb920106bbbbcaf2a274d56f46956bf56ecbde210d88061824a95bdd94e92"}, + {file = "coverage-7.6.3-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:70d24936ca6c15a3bbc91ee9c7fc661132c6f4c9d42a23b31b6686c05073bde5"}, + {file = "coverage-7.6.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:c30e42ea11badb147f0d2e387115b15e2bd8205a5ad70d6ad79cf37f6ac08c91"}, + {file = "coverage-7.6.3-cp313-cp313t-win32.whl", hash = "sha256:365defc257c687ce3e7d275f39738dcd230777424117a6c76043459db131dd43"}, + {file = "coverage-7.6.3-cp313-cp313t-win_amd64.whl", hash = "sha256:23bb63ae3f4c645d2d82fa22697364b0046fbafb6261b258a58587441c5f7bd0"}, + {file = "coverage-7.6.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:da29ceabe3025a1e5a5aeeb331c5b1af686daab4ff0fb4f83df18b1180ea83e2"}, + {file = "coverage-7.6.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:df8c05a0f574d480947cba11b947dc41b1265d721c3777881da2fb8d3a1ddfba"}, + {file = "coverage-7.6.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec1e3b40b82236d100d259854840555469fad4db64f669ab817279eb95cd535c"}, + {file = "coverage-7.6.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b4adeb878a374126f1e5cf03b87f66279f479e01af0e9a654cf6d1509af46c40"}, + {file = "coverage-7.6.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:43d6a66e33b1455b98fc7312b124296dad97a2e191c80320587234a77b1b736e"}, + {file = "coverage-7.6.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1990b1f4e2c402beb317840030bb9f1b6a363f86e14e21b4212e618acdfce7f6"}, + {file = "coverage-7.6.3-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:12f9515d875859faedb4144fd38694a761cd2a61ef9603bf887b13956d0bbfbb"}, + {file = "coverage-7.6.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:99ded130555c021d99729fabd4ddb91a6f4cc0707df4b1daf912c7850c373b13"}, + {file = "coverage-7.6.3-cp39-cp39-win32.whl", hash = "sha256:c3a79f56dee9136084cf84a6c7c4341427ef36e05ae6415bf7d787c96ff5eaa3"}, + {file = "coverage-7.6.3-cp39-cp39-win_amd64.whl", hash = "sha256:aac7501ae73d4a02f4b7ac8fcb9dc55342ca98ffb9ed9f2dfb8a25d53eda0e4d"}, + {file = "coverage-7.6.3-pp39.pp310-none-any.whl", hash = "sha256:b9853509b4bf57ba7b1f99b9d866c422c9c5248799ab20e652bbb8a184a38181"}, + {file = "coverage-7.6.3.tar.gz", hash = "sha256:bb7d5fe92bd0dc235f63ebe9f8c6e0884f7360f88f3411bfed1350c872ef2054"}, ] [package.dependencies] @@ -568,63 +608,67 @@ toml = ["tomli"] [[package]] name = "debugpy" -version = "1.8.2" +version = "1.8.7" description = "An implementation of the Debug Adapter Protocol for Python" optional = false python-versions = ">=3.8" files = [ - {file = "debugpy-1.8.2-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:7ee2e1afbf44b138c005e4380097d92532e1001580853a7cb40ed84e0ef1c3d2"}, - {file = "debugpy-1.8.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3f8c3f7c53130a070f0fc845a0f2cee8ed88d220d6b04595897b66605df1edd6"}, - {file = "debugpy-1.8.2-cp310-cp310-win32.whl", hash = "sha256:f179af1e1bd4c88b0b9f0fa153569b24f6b6f3de33f94703336363ae62f4bf47"}, - {file = "debugpy-1.8.2-cp310-cp310-win_amd64.whl", hash = "sha256:0600faef1d0b8d0e85c816b8bb0cb90ed94fc611f308d5fde28cb8b3d2ff0fe3"}, - {file = "debugpy-1.8.2-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:8a13417ccd5978a642e91fb79b871baded925d4fadd4dfafec1928196292aa0a"}, - {file = "debugpy-1.8.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:acdf39855f65c48ac9667b2801234fc64d46778021efac2de7e50907ab90c634"}, - {file = "debugpy-1.8.2-cp311-cp311-win32.whl", hash = "sha256:2cbd4d9a2fc5e7f583ff9bf11f3b7d78dfda8401e8bb6856ad1ed190be4281ad"}, - {file = "debugpy-1.8.2-cp311-cp311-win_amd64.whl", hash = "sha256:d3408fddd76414034c02880e891ea434e9a9cf3a69842098ef92f6e809d09afa"}, - {file = "debugpy-1.8.2-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:5d3ccd39e4021f2eb86b8d748a96c766058b39443c1f18b2dc52c10ac2757835"}, - {file = "debugpy-1.8.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:62658aefe289598680193ff655ff3940e2a601765259b123dc7f89c0239b8cd3"}, - {file = "debugpy-1.8.2-cp312-cp312-win32.whl", hash = "sha256:bd11fe35d6fd3431f1546d94121322c0ac572e1bfb1f6be0e9b8655fb4ea941e"}, - {file = "debugpy-1.8.2-cp312-cp312-win_amd64.whl", hash = "sha256:15bc2f4b0f5e99bf86c162c91a74c0631dbd9cef3c6a1d1329c946586255e859"}, - {file = "debugpy-1.8.2-cp38-cp38-macosx_11_0_x86_64.whl", hash = "sha256:5a019d4574afedc6ead1daa22736c530712465c0c4cd44f820d803d937531b2d"}, - {file = "debugpy-1.8.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40f062d6877d2e45b112c0bbade9a17aac507445fd638922b1a5434df34aed02"}, - {file = "debugpy-1.8.2-cp38-cp38-win32.whl", hash = "sha256:c78ba1680f1015c0ca7115671fe347b28b446081dada3fedf54138f44e4ba031"}, - {file = "debugpy-1.8.2-cp38-cp38-win_amd64.whl", hash = "sha256:cf327316ae0c0e7dd81eb92d24ba8b5e88bb4d1b585b5c0d32929274a66a5210"}, - {file = "debugpy-1.8.2-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:1523bc551e28e15147815d1397afc150ac99dbd3a8e64641d53425dba57b0ff9"}, - {file = "debugpy-1.8.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e24ccb0cd6f8bfaec68d577cb49e9c680621c336f347479b3fce060ba7c09ec1"}, - {file = "debugpy-1.8.2-cp39-cp39-win32.whl", hash = "sha256:7f8d57a98c5a486c5c7824bc0b9f2f11189d08d73635c326abef268f83950326"}, - {file = "debugpy-1.8.2-cp39-cp39-win_amd64.whl", hash = "sha256:16c8dcab02617b75697a0a925a62943e26a0330da076e2a10437edd9f0bf3755"}, - {file = "debugpy-1.8.2-py2.py3-none-any.whl", hash = "sha256:16e16df3a98a35c63c3ab1e4d19be4cbc7fdda92d9ddc059294f18910928e0ca"}, - {file = "debugpy-1.8.2.zip", hash = "sha256:95378ed08ed2089221896b9b3a8d021e642c24edc8fef20e5d4342ca8be65c00"}, + {file = "debugpy-1.8.7-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:95fe04a573b8b22896c404365e03f4eda0ce0ba135b7667a1e57bd079793b96b"}, + {file = "debugpy-1.8.7-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:628a11f4b295ffb4141d8242a9bb52b77ad4a63a2ad19217a93be0f77f2c28c9"}, + {file = "debugpy-1.8.7-cp310-cp310-win32.whl", hash = "sha256:85ce9c1d0eebf622f86cc68618ad64bf66c4fc3197d88f74bb695a416837dd55"}, + {file = "debugpy-1.8.7-cp310-cp310-win_amd64.whl", hash = "sha256:29e1571c276d643757ea126d014abda081eb5ea4c851628b33de0c2b6245b037"}, + {file = "debugpy-1.8.7-cp311-cp311-macosx_14_0_universal2.whl", hash = "sha256:caf528ff9e7308b74a1749c183d6808ffbedbb9fb6af78b033c28974d9b8831f"}, + {file = "debugpy-1.8.7-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cba1d078cf2e1e0b8402e6bda528bf8fda7ccd158c3dba6c012b7897747c41a0"}, + {file = "debugpy-1.8.7-cp311-cp311-win32.whl", hash = "sha256:171899588bcd412151e593bd40d9907133a7622cd6ecdbdb75f89d1551df13c2"}, + {file = "debugpy-1.8.7-cp311-cp311-win_amd64.whl", hash = "sha256:6e1c4ffb0c79f66e89dfd97944f335880f0d50ad29525dc792785384923e2211"}, + {file = "debugpy-1.8.7-cp312-cp312-macosx_14_0_universal2.whl", hash = "sha256:4d27d842311353ede0ad572600c62e4bcd74f458ee01ab0dd3a1a4457e7e3706"}, + {file = "debugpy-1.8.7-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:703c1fd62ae0356e194f3e7b7a92acd931f71fe81c4b3be2c17a7b8a4b546ec2"}, + {file = "debugpy-1.8.7-cp312-cp312-win32.whl", hash = "sha256:2f729228430ef191c1e4df72a75ac94e9bf77413ce5f3f900018712c9da0aaca"}, + {file = "debugpy-1.8.7-cp312-cp312-win_amd64.whl", hash = "sha256:45c30aaefb3e1975e8a0258f5bbd26cd40cde9bfe71e9e5a7ac82e79bad64e39"}, + {file = "debugpy-1.8.7-cp313-cp313-macosx_14_0_universal2.whl", hash = "sha256:d050a1ec7e925f514f0f6594a1e522580317da31fbda1af71d1530d6ea1f2b40"}, + {file = "debugpy-1.8.7-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2f4349a28e3228a42958f8ddaa6333d6f8282d5edaea456070e48609c5983b7"}, + {file = "debugpy-1.8.7-cp313-cp313-win32.whl", hash = "sha256:11ad72eb9ddb436afb8337891a986302e14944f0f755fd94e90d0d71e9100bba"}, + {file = "debugpy-1.8.7-cp313-cp313-win_amd64.whl", hash = "sha256:2efb84d6789352d7950b03d7f866e6d180284bc02c7e12cb37b489b7083d81aa"}, + {file = "debugpy-1.8.7-cp38-cp38-macosx_14_0_x86_64.whl", hash = "sha256:4b908291a1d051ef3331484de8e959ef3e66f12b5e610c203b5b75d2725613a7"}, + {file = "debugpy-1.8.7-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da8df5b89a41f1fd31503b179d0a84a5fdb752dddd5b5388dbd1ae23cda31ce9"}, + {file = "debugpy-1.8.7-cp38-cp38-win32.whl", hash = "sha256:b12515e04720e9e5c2216cc7086d0edadf25d7ab7e3564ec8b4521cf111b4f8c"}, + {file = "debugpy-1.8.7-cp38-cp38-win_amd64.whl", hash = "sha256:93176e7672551cb5281577cdb62c63aadc87ec036f0c6a486f0ded337c504596"}, + {file = "debugpy-1.8.7-cp39-cp39-macosx_14_0_x86_64.whl", hash = "sha256:90d93e4f2db442f8222dec5ec55ccfc8005821028982f1968ebf551d32b28907"}, + {file = "debugpy-1.8.7-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b6db2a370e2700557a976eaadb16243ec9c91bd46f1b3bb15376d7aaa7632c81"}, + {file = "debugpy-1.8.7-cp39-cp39-win32.whl", hash = "sha256:a6cf2510740e0c0b4a40330640e4b454f928c7b99b0c9dbf48b11efba08a8cda"}, + {file = "debugpy-1.8.7-cp39-cp39-win_amd64.whl", hash = "sha256:6a9d9d6d31846d8e34f52987ee0f1a904c7baa4912bf4843ab39dadf9b8f3e0d"}, + {file = "debugpy-1.8.7-py2.py3-none-any.whl", hash = "sha256:57b00de1c8d2c84a61b90880f7e5b6deaf4c312ecbde3a0e8912f2a56c4ac9ae"}, + {file = "debugpy-1.8.7.zip", hash = "sha256:18b8f731ed3e2e1df8e9cdaa23fb1fc9c24e570cd0081625308ec51c82efe42e"}, ] [[package]] name = "distlib" -version = "0.3.8" +version = "0.3.9" description = "Distribution utilities" optional = false python-versions = "*" files = [ - {file = "distlib-0.3.8-py2.py3-none-any.whl", hash = "sha256:034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784"}, - {file = "distlib-0.3.8.tar.gz", hash = "sha256:1530ea13e350031b6312d8580ddb6b27a104275a31106523b8f123787f494f64"}, + {file = "distlib-0.3.9-py2.py3-none-any.whl", hash = "sha256:47f8c22fd27c27e25a65601af709b38e4f0a45ea4fc2e710f65755fa8caaaf87"}, + {file = "distlib-0.3.9.tar.gz", hash = "sha256:a60f20dea646b8a33f3e7772f74dc0b2d0772d2837ee1342a00645c81edf9403"}, ] [[package]] name = "dnspython" -version = "2.6.1" +version = "2.7.0" description = "DNS toolkit" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "dnspython-2.6.1-py3-none-any.whl", hash = "sha256:5ef3b9680161f6fa89daf8ad451b5f1a33b18ae8a1c6778cdf4b43f08c0a6e50"}, - {file = "dnspython-2.6.1.tar.gz", hash = "sha256:e8f0f9c23a7b7cb99ded64e6c3a6f3e701d78f50c55e002b839dea7225cff7cc"}, + {file = "dnspython-2.7.0-py3-none-any.whl", hash = "sha256:b4c34b7d10b51bcc3a5071e7b8dee77939f1e878477eeecc965e9835f63c6c86"}, + {file = "dnspython-2.7.0.tar.gz", hash = "sha256:ce9c432eda0dc91cf618a5cedf1a4e142651196bbcd2c80e89ed5a907e5cfaf1"}, ] [package.extras] -dev = ["black (>=23.1.0)", "coverage (>=7.0)", "flake8 (>=7)", "mypy (>=1.8)", "pylint (>=3)", "pytest (>=7.4)", "pytest-cov (>=4.1.0)", "sphinx (>=7.2.0)", "twine (>=4.0.0)", "wheel (>=0.42.0)"] -dnssec = ["cryptography (>=41)"] +dev = ["black (>=23.1.0)", "coverage (>=7.0)", "flake8 (>=7)", "hypercorn (>=0.16.0)", "mypy (>=1.8)", "pylint (>=3)", "pytest (>=7.4)", "pytest-cov (>=4.1.0)", "quart-trio (>=0.11.0)", "sphinx (>=7.2.0)", "sphinx-rtd-theme (>=2.0.0)", "twine (>=4.0.0)", "wheel (>=0.42.0)"] +dnssec = ["cryptography (>=43)"] doh = ["h2 (>=4.1.0)", "httpcore (>=1.0.0)", "httpx (>=0.26.0)"] -doq = ["aioquic (>=0.9.25)"] -idna = ["idna (>=3.6)"] +doq = ["aioquic (>=1.0.0)"] +idna = ["idna (>=3.7)"] trio = ["trio (>=0.23)"] wmi = ["wmi (>=1.5.1)"] @@ -675,67 +719,69 @@ pysam = ">=0.22.0,<0.23.0" [[package]] name = "fastapi" -version = "0.111.1" +version = "0.115.2" description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" optional = false python-versions = ">=3.8" files = [ - {file = "fastapi-0.111.1-py3-none-any.whl", hash = "sha256:4f51cfa25d72f9fbc3280832e84b32494cf186f50158d364a8765aabf22587bf"}, - {file = "fastapi-0.111.1.tar.gz", hash = "sha256:ddd1ac34cb1f76c2e2d7f8545a4bcb5463bce4834e81abf0b189e0c359ab2413"}, + {file = "fastapi-0.115.2-py3-none-any.whl", hash = "sha256:61704c71286579cc5a598763905928f24ee98bfcc07aabe84cfefb98812bbc86"}, + {file = "fastapi-0.115.2.tar.gz", hash = "sha256:3995739e0b09fa12f984bce8fa9ae197b35d433750d3d312422d846e283697ee"}, ] [package.dependencies] -email_validator = ">=2.0.0" -fastapi-cli = ">=0.0.2" -httpx = ">=0.23.0" +email-validator = {version = ">=2.0.0", optional = true, markers = "extra == \"all\""} +fastapi-cli = {version = ">=0.0.5", extras = ["standard"], optional = true, markers = "extra == \"all\""} +httpx = {version = ">=0.23.0", optional = true, markers = "extra == \"all\""} itsdangerous = {version = ">=1.1.0", optional = true, markers = "extra == \"all\""} -jinja2 = ">=2.11.2" +jinja2 = {version = ">=2.11.2", optional = true, markers = "extra == \"all\""} orjson = {version = ">=3.2.1", optional = true, markers = "extra == \"all\""} pydantic = ">=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0 || >2.0.0,<2.0.1 || >2.0.1,<2.1.0 || >2.1.0,<3.0.0" pydantic-extra-types = {version = ">=2.0.0", optional = true, markers = "extra == \"all\""} pydantic-settings = {version = ">=2.0.0", optional = true, markers = "extra == \"all\""} -python-multipart = ">=0.0.7" +python-multipart = {version = ">=0.0.7", optional = true, markers = "extra == \"all\""} pyyaml = {version = ">=5.3.1", optional = true, markers = "extra == \"all\""} -starlette = ">=0.37.2,<0.38.0" +starlette = ">=0.37.2,<0.41.0" typing-extensions = ">=4.8.0" ujson = {version = ">=4.0.1,<4.0.2 || >4.0.2,<4.1.0 || >4.1.0,<4.2.0 || >4.2.0,<4.3.0 || >4.3.0,<5.0.0 || >5.0.0,<5.1.0 || >5.1.0", optional = true, markers = "extra == \"all\""} -uvicorn = {version = ">=0.12.0", extras = ["standard"]} +uvicorn = {version = ">=0.12.0", extras = ["standard"], optional = true, markers = "extra == \"all\""} [package.extras] -all = ["email_validator (>=2.0.0)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.7)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"] +all = ["email-validator (>=2.0.0)", "fastapi-cli[standard] (>=0.0.5)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.7)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"] +standard = ["email-validator (>=2.0.0)", "fastapi-cli[standard] (>=0.0.5)", "httpx (>=0.23.0)", "jinja2 (>=2.11.2)", "python-multipart (>=0.0.7)", "uvicorn[standard] (>=0.12.0)"] [[package]] name = "fastapi-cli" -version = "0.0.4" +version = "0.0.5" description = "Run and manage FastAPI apps from the command line with FastAPI CLI. 🚀" optional = false python-versions = ">=3.8" files = [ - {file = "fastapi_cli-0.0.4-py3-none-any.whl", hash = "sha256:a2552f3a7ae64058cdbb530be6fa6dbfc975dc165e4fa66d224c3d396e25e809"}, - {file = "fastapi_cli-0.0.4.tar.gz", hash = "sha256:e2e9ffaffc1f7767f488d6da34b6f5a377751c996f397902eb6abb99a67bde32"}, + {file = "fastapi_cli-0.0.5-py3-none-any.whl", hash = "sha256:e94d847524648c748a5350673546bbf9bcaeb086b33c24f2e82e021436866a46"}, + {file = "fastapi_cli-0.0.5.tar.gz", hash = "sha256:d30e1239c6f46fcb95e606f02cdda59a1e2fa778a54b64686b3ff27f6211ff9f"}, ] [package.dependencies] typer = ">=0.12.3" +uvicorn = {version = ">=0.15.0", extras = ["standard"]} [package.extras] -standard = ["fastapi", "uvicorn[standard] (>=0.15.0)"] +standard = ["uvicorn[standard] (>=0.15.0)"] [[package]] name = "filelock" -version = "3.15.4" +version = "3.16.1" description = "A platform independent file lock." optional = false python-versions = ">=3.8" files = [ - {file = "filelock-3.15.4-py3-none-any.whl", hash = "sha256:6ca1fffae96225dab4c6eaf1c4f4f28cd2568d3ec2a44e15a08520504de468e7"}, - {file = "filelock-3.15.4.tar.gz", hash = "sha256:2207938cbc1844345cb01a5a95524dae30f0ce089eba5b00378295a17e3e90cb"}, + {file = "filelock-3.16.1-py3-none-any.whl", hash = "sha256:2082e5703d51fbf98ea75855d9d5527e33d8ff23099bec374a134febee6946b0"}, + {file = "filelock-3.16.1.tar.gz", hash = "sha256:c249fbfcd5db47e5e2d6d62198e565475ee65e4831e2561c8e313fa7eb961435"}, ] [package.extras] -docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] -testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8.0.1)", "pytest (>=7.4.3)", "pytest-asyncio (>=0.21)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)", "virtualenv (>=20.26.2)"] -typing = ["typing-extensions (>=4.8)"] +docs = ["furo (>=2024.8.6)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4.1)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.6.1)", "diff-cover (>=9.2)", "pytest (>=8.3.3)", "pytest-asyncio (>=0.24)", "pytest-cov (>=5)", "pytest-mock (>=3.14)", "pytest-timeout (>=2.3.1)", "virtualenv (>=20.26.4)"] +typing = ["typing-extensions (>=4.12.2)"] [[package]] name = "frozenlist" @@ -836,13 +882,13 @@ files = [ [[package]] name = "httpcore" -version = "1.0.5" +version = "1.0.6" description = "A minimal low-level HTTP client." optional = false python-versions = ">=3.8" files = [ - {file = "httpcore-1.0.5-py3-none-any.whl", hash = "sha256:421f18bac248b25d310f3cacd198d55b8e6125c107797b609ff9b7a6ba7991b5"}, - {file = "httpcore-1.0.5.tar.gz", hash = "sha256:34a38e2f9291467ee3b44e89dd52615370e152954ba21721378a87b2960f7a61"}, + {file = "httpcore-1.0.6-py3-none-any.whl", hash = "sha256:27b59625743b85577a8c0e10e55b50b5368a4f2cfe8cc7bcfa9cf00829c2682f"}, + {file = "httpcore-1.0.6.tar.gz", hash = "sha256:73f6dbd6eb8c21bbf7ef8efad555481853f5f6acdeaff1edb0694289269ee17f"}, ] [package.dependencies] @@ -853,65 +899,72 @@ h11 = ">=0.13,<0.15" asyncio = ["anyio (>=4.0,<5.0)"] http2 = ["h2 (>=3,<5)"] socks = ["socksio (==1.*)"] -trio = ["trio (>=0.22.0,<0.26.0)"] +trio = ["trio (>=0.22.0,<1.0)"] [[package]] name = "httptools" -version = "0.6.1" +version = "0.6.2" description = "A collection of framework independent HTTP protocol utils." optional = false python-versions = ">=3.8.0" files = [ - {file = "httptools-0.6.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d2f6c3c4cb1948d912538217838f6e9960bc4a521d7f9b323b3da579cd14532f"}, - {file = "httptools-0.6.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:00d5d4b68a717765b1fabfd9ca755bd12bf44105eeb806c03d1962acd9b8e563"}, - {file = "httptools-0.6.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:639dc4f381a870c9ec860ce5c45921db50205a37cc3334e756269736ff0aac58"}, - {file = "httptools-0.6.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e57997ac7fb7ee43140cc03664de5f268813a481dff6245e0075925adc6aa185"}, - {file = "httptools-0.6.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0ac5a0ae3d9f4fe004318d64b8a854edd85ab76cffbf7ef5e32920faef62f142"}, - {file = "httptools-0.6.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:3f30d3ce413088a98b9db71c60a6ada2001a08945cb42dd65a9a9fe228627658"}, - {file = "httptools-0.6.1-cp310-cp310-win_amd64.whl", hash = "sha256:1ed99a373e327f0107cb513b61820102ee4f3675656a37a50083eda05dc9541b"}, - {file = "httptools-0.6.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7a7ea483c1a4485c71cb5f38be9db078f8b0e8b4c4dc0210f531cdd2ddac1ef1"}, - {file = "httptools-0.6.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:85ed077c995e942b6f1b07583e4eb0a8d324d418954fc6af913d36db7c05a5a0"}, - {file = "httptools-0.6.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b0bb634338334385351a1600a73e558ce619af390c2b38386206ac6a27fecfc"}, - {file = "httptools-0.6.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7d9ceb2c957320def533671fc9c715a80c47025139c8d1f3797477decbc6edd2"}, - {file = "httptools-0.6.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:4f0f8271c0a4db459f9dc807acd0eadd4839934a4b9b892f6f160e94da309837"}, - {file = "httptools-0.6.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6a4f5ccead6d18ec072ac0b84420e95d27c1cdf5c9f1bc8fbd8daf86bd94f43d"}, - {file = "httptools-0.6.1-cp311-cp311-win_amd64.whl", hash = "sha256:5cceac09f164bcba55c0500a18fe3c47df29b62353198e4f37bbcc5d591172c3"}, - {file = "httptools-0.6.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:75c8022dca7935cba14741a42744eee13ba05db00b27a4b940f0d646bd4d56d0"}, - {file = "httptools-0.6.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:48ed8129cd9a0d62cf4d1575fcf90fb37e3ff7d5654d3a5814eb3d55f36478c2"}, - {file = "httptools-0.6.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6f58e335a1402fb5a650e271e8c2d03cfa7cea46ae124649346d17bd30d59c90"}, - {file = "httptools-0.6.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:93ad80d7176aa5788902f207a4e79885f0576134695dfb0fefc15b7a4648d503"}, - {file = "httptools-0.6.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9bb68d3a085c2174c2477eb3ffe84ae9fb4fde8792edb7bcd09a1d8467e30a84"}, - {file = "httptools-0.6.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:b512aa728bc02354e5ac086ce76c3ce635b62f5fbc32ab7082b5e582d27867bb"}, - {file = "httptools-0.6.1-cp312-cp312-win_amd64.whl", hash = "sha256:97662ce7fb196c785344d00d638fc9ad69e18ee4bfb4000b35a52efe5adcc949"}, - {file = "httptools-0.6.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:8e216a038d2d52ea13fdd9b9c9c7459fb80d78302b257828285eca1c773b99b3"}, - {file = "httptools-0.6.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3e802e0b2378ade99cd666b5bffb8b2a7cc8f3d28988685dc300469ea8dd86cb"}, - {file = "httptools-0.6.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4bd3e488b447046e386a30f07af05f9b38d3d368d1f7b4d8f7e10af85393db97"}, - {file = "httptools-0.6.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe467eb086d80217b7584e61313ebadc8d187a4d95bb62031b7bab4b205c3ba3"}, - {file = "httptools-0.6.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:3c3b214ce057c54675b00108ac42bacf2ab8f85c58e3f324a4e963bbc46424f4"}, - {file = "httptools-0.6.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8ae5b97f690badd2ca27cbf668494ee1b6d34cf1c464271ef7bfa9ca6b83ffaf"}, - {file = "httptools-0.6.1-cp38-cp38-win_amd64.whl", hash = "sha256:405784577ba6540fa7d6ff49e37daf104e04f4b4ff2d1ac0469eaa6a20fde084"}, - {file = "httptools-0.6.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:95fb92dd3649f9cb139e9c56604cc2d7c7bf0fc2e7c8d7fbd58f96e35eddd2a3"}, - {file = "httptools-0.6.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:dcbab042cc3ef272adc11220517278519adf8f53fd3056d0e68f0a6f891ba94e"}, - {file = "httptools-0.6.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cf2372e98406efb42e93bfe10f2948e467edfd792b015f1b4ecd897903d3e8d"}, - {file = "httptools-0.6.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:678fcbae74477a17d103b7cae78b74800d795d702083867ce160fc202104d0da"}, - {file = "httptools-0.6.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:e0b281cf5a125c35f7f6722b65d8542d2e57331be573e9e88bc8b0115c4a7a81"}, - {file = "httptools-0.6.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:95658c342529bba4e1d3d2b1a874db16c7cca435e8827422154c9da76ac4e13a"}, - {file = "httptools-0.6.1-cp39-cp39-win_amd64.whl", hash = "sha256:7ebaec1bf683e4bf5e9fbb49b8cc36da482033596a415b3e4ebab5a4c0d7ec5e"}, - {file = "httptools-0.6.1.tar.gz", hash = "sha256:c6e26c30455600b95d94b1b836085138e82f177351454ee841c148f93a9bad5a"}, + {file = "httptools-0.6.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0238f07780782c018e9801d8f5f5aea3a4680a1af132034b444f677718c6fe88"}, + {file = "httptools-0.6.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:10d28e5597d4349390c640232c9366ddc15568114f56724fe30a53de9686b6ab"}, + {file = "httptools-0.6.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9ddaf99e362ae4169f6a8b3508f3487264e0a1b1e58c0b07b86407bc9ecee831"}, + {file = "httptools-0.6.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:efc9d039b6b8a36b182bc60774bb5d456b8ff9ec44cf97719f2f38bb1dcdd546"}, + {file = "httptools-0.6.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:b57cb8a4a8a8ffdaf0395326ef3b9c1aba36e58a421438fc04c002a1f511db63"}, + {file = "httptools-0.6.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b73cda1326738eab5d60640ca0b87ac4e4db09a099423c41b59a5681917e8d1d"}, + {file = "httptools-0.6.2-cp310-cp310-win_amd64.whl", hash = "sha256:352a496244360deb1c1d108391d76cd6f3dd9f53ccf975a082e74c6761af30c9"}, + {file = "httptools-0.6.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2e9d225b178a6cc700c23cf2f5daf85a10f93f1db7c34e9ee4ee0bbc29ad458a"}, + {file = "httptools-0.6.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d49b14fcc9b12a52da8667587efa124a18e1a3eb63bbbcabf9882f4008d171d6"}, + {file = "httptools-0.6.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d5c33d98b2311ddbe06e92b12b14de334dcfbe64ebcbb2c7a34b5c6036db512"}, + {file = "httptools-0.6.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:53cd2d776700bf0ed0e6fb203d716b041712ea4906479031cc5ac5421ecaa7d2"}, + {file = "httptools-0.6.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7da016a0dab1fcced89dfff8537033c5dc200015e14023368f3f4a69e39b8716"}, + {file = "httptools-0.6.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4d6e0ba155a1b3159551ac6b4551eb20028617e2e4bb71f2c61efed0756e6825"}, + {file = "httptools-0.6.2-cp311-cp311-win_amd64.whl", hash = "sha256:ad44569b0f508e046ffe85b4a547d5b68d1548fd90767df69449cc28021ee709"}, + {file = "httptools-0.6.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:c92d2b7c1a914ab2f66454961eeaf904f4fe7529b93ff537619d22c18b82d070"}, + {file = "httptools-0.6.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:78f920a75c1dbcb5a48a495f384d73ceb41e437a966c318eb7e56f1c1ad1df3e"}, + {file = "httptools-0.6.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:56bcd9ba0adf16edb4e3e45b8b9346f5b3b2372402e953d54c84b345d0f691e0"}, + {file = "httptools-0.6.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e350a887adb38ac65c93c2f395b60cf482baca61fd396ed8d6fd313dbcce6fac"}, + {file = "httptools-0.6.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ddc328c2a2daf2cf4bdc7bbc8a458dc4c840637223d4b8e01bce2168cc79fd23"}, + {file = "httptools-0.6.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ddaf38943dbb32333a182c894b6092a68b56c5e36d0c54ba3761d28119b15447"}, + {file = "httptools-0.6.2-cp312-cp312-win_amd64.whl", hash = "sha256:052f7f50e4a38f069478143878371ed17937f268349bcd68f6f7a9de9fcfce21"}, + {file = "httptools-0.6.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:406f7dc5d9db68cd9ac638d14c74d077085f76b45f704d3ec38d43b842b3cb44"}, + {file = "httptools-0.6.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:77e22c33123ce11231ff2773d8905e20b45d77a69459def7481283b72a583955"}, + {file = "httptools-0.6.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41965586b02715c3d83dd9153001f654e5b621de0c5255f5ef0635485212d0c0"}, + {file = "httptools-0.6.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:93b1839d54b80a06a51a31b90d024a1770e250d00de57e7ae069bafba932f398"}, + {file = "httptools-0.6.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:8fdb4634040d1dbde7e0b373e19668cdb61c0ee8690d3b4064ac748d85365bca"}, + {file = "httptools-0.6.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:c30902f9b9da0d74668b6f71d7b57081a4879d9a5ea93d5922dbe15b15b3b24a"}, + {file = "httptools-0.6.2-cp313-cp313-win_amd64.whl", hash = "sha256:cf61238811a75335751b4b17f8b221a35f93f2d57489296742adf98412d2a568"}, + {file = "httptools-0.6.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:8d80878cb40ebf88a48839ff7206ceb62e4b54327e0c2f9f15ee12edbd8b907e"}, + {file = "httptools-0.6.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5141ccc9dbd8cdc59d1e93e318d405477a940dc6ebadcb8d9f8da17d2812d353"}, + {file = "httptools-0.6.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1bb67d47f045f56e9a5da4deccf710bdde21212e4b1f4776b7a542449f6a7682"}, + {file = "httptools-0.6.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:76dcb8f5c866f1537ccbaad01ebb3611890d281ef8d25e050d1cc3d90fba6b3d"}, + {file = "httptools-0.6.2-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:1b7bc59362143dc2d02896dde94004ef54ff1989ceedf4b389ad3b530f312364"}, + {file = "httptools-0.6.2-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:c7a5715b1f46e9852442f496c0df2f8c393cc8f293f5396d2c8d95cac852fb51"}, + {file = "httptools-0.6.2-cp38-cp38-win_amd64.whl", hash = "sha256:3f0246ca7f78fa8e3902ddb985b9f55509d417a862f4634a8fa63a7a496266c8"}, + {file = "httptools-0.6.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:1099f73952e18c718ccaaf7a97ae58c94a91839c3d247c6184326f85a2eda7b4"}, + {file = "httptools-0.6.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c3e45d004531330030f7d07abe4865bc17963b9989bc1941cebbf7224010fb82"}, + {file = "httptools-0.6.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f4f2fea370361a90cb9330610a95303587eda9d1e69930dbbee9978eac1d5946"}, + {file = "httptools-0.6.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f0481154c91725f7e7b729a535190388be6c7cbae3bbf0e793343ca386282312"}, + {file = "httptools-0.6.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:d25f8fdbc6cc6561353c7a384d76295e6a85a4945115b8bc347855db150e8c77"}, + {file = "httptools-0.6.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:054bdee08e4f7c15c186f6e7dbc8f0cf974b8dd1832b5f17f988faf8b12815c9"}, + {file = "httptools-0.6.2-cp39-cp39-win_amd64.whl", hash = "sha256:4502620722b453c2c6306fad392c515dcb804dfa9c6d3b90d8926a07a7a01109"}, + {file = "httptools-0.6.2.tar.gz", hash = "sha256:ae694efefcb61317c79b2fa1caebc122060992408e389bb00889567e463a47f1"}, ] [package.extras] -test = ["Cython (>=0.29.24,<0.30.0)"] +test = ["Cython (>=0.29.24)"] [[package]] name = "httpx" -version = "0.27.0" +version = "0.27.2" description = "The next generation HTTP client." optional = false python-versions = ">=3.8" files = [ - {file = "httpx-0.27.0-py3-none-any.whl", hash = "sha256:71d5465162c13681bff01ad59b2cc68dd838ea1f10e51574bac27103f00c91a5"}, - {file = "httpx-0.27.0.tar.gz", hash = "sha256:a0cb88a46f32dc874e04ee956e4c2764aba2aa228f650b06788ba6bda2962ab5"}, + {file = "httpx-0.27.2-py3-none-any.whl", hash = "sha256:7bb2708e112d8fdd7829cd4243970f0c223274051cb35ee80c03301ee29a3df0"}, + {file = "httpx-0.27.2.tar.gz", hash = "sha256:f7c2be1d2f3c3c3160d441802406b206c2b76f5947b11115e6df10c6c65e66c2"}, ] [package.dependencies] @@ -926,18 +979,22 @@ brotli = ["brotli", "brotlicffi"] cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"] http2 = ["h2 (>=3,<5)"] socks = ["socksio (==1.*)"] +zstd = ["zstandard (>=0.18.0)"] [[package]] name = "idna" -version = "3.7" +version = "3.10" description = "Internationalized Domain Names in Applications (IDNA)" optional = false -python-versions = ">=3.5" +python-versions = ">=3.6" files = [ - {file = "idna-3.7-py3-none-any.whl", hash = "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"}, - {file = "idna-3.7.tar.gz", hash = "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc"}, + {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, + {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, ] +[package.extras] +all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] + [[package]] name = "iniconfig" version = "2.0.0" @@ -1000,13 +1057,13 @@ format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339- [[package]] name = "jsonschema-specifications" -version = "2023.12.1" +version = "2024.10.1" description = "The JSON Schema meta-schemas and vocabularies, exposed as a Registry" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "jsonschema_specifications-2023.12.1-py3-none-any.whl", hash = "sha256:87e4fdf3a94858b8a2ba2778d9ba57d8a9cafca7c7489c46ba0d30a8bc6a9c3c"}, - {file = "jsonschema_specifications-2023.12.1.tar.gz", hash = "sha256:48a76787b3e70f5ed53f1160d2b81f586e4ca6d1548c5de7085d1682674764cc"}, + {file = "jsonschema_specifications-2024.10.1-py3-none-any.whl", hash = "sha256:a09a0680616357d9a0ecf05c12ad234479f549239d0f5b55f3deea67475da9bf"}, + {file = "jsonschema_specifications-2024.10.1.tar.gz", hash = "sha256:0f38b83639958ce1152d02a7f062902c41c8fd20d558b0c34344292d417ae272"}, ] [package.dependencies] @@ -1038,71 +1095,72 @@ testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] [[package]] name = "markupsafe" -version = "2.1.5" +version = "3.0.1" description = "Safely add untrusted strings to HTML/XML markup." optional = false -python-versions = ">=3.7" -files = [ - {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-win32.whl", hash = "sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4"}, - {file = "MarkupSafe-2.1.5-cp310-cp310-win_amd64.whl", hash = "sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-win32.whl", hash = "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906"}, - {file = "MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl", hash = "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-win32.whl", hash = "sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad"}, - {file = "MarkupSafe-2.1.5-cp312-cp312-win_amd64.whl", hash = "sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-win32.whl", hash = "sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371"}, - {file = "MarkupSafe-2.1.5-cp37-cp37m-win_amd64.whl", hash = "sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-win32.whl", hash = "sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff"}, - {file = "MarkupSafe-2.1.5-cp38-cp38-win_amd64.whl", hash = "sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-win32.whl", hash = "sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf"}, - {file = "MarkupSafe-2.1.5-cp39-cp39-win_amd64.whl", hash = "sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5"}, - {file = "MarkupSafe-2.1.5.tar.gz", hash = "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b"}, +python-versions = ">=3.9" +files = [ + {file = "MarkupSafe-3.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:db842712984e91707437461930e6011e60b39136c7331e971952bb30465bc1a1"}, + {file = "MarkupSafe-3.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3ffb4a8e7d46ed96ae48805746755fadd0909fea2306f93d5d8233ba23dda12a"}, + {file = "MarkupSafe-3.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67c519635a4f64e495c50e3107d9b4075aec33634272b5db1cde839e07367589"}, + {file = "MarkupSafe-3.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:48488d999ed50ba8d38c581d67e496f955821dc183883550a6fbc7f1aefdc170"}, + {file = "MarkupSafe-3.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f31ae06f1328595d762c9a2bf29dafd8621c7d3adc130cbb46278079758779ca"}, + {file = "MarkupSafe-3.0.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:80fcbf3add8790caddfab6764bde258b5d09aefbe9169c183f88a7410f0f6dea"}, + {file = "MarkupSafe-3.0.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3341c043c37d78cc5ae6e3e305e988532b072329639007fd408a476642a89fd6"}, + {file = "MarkupSafe-3.0.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:cb53e2a99df28eee3b5f4fea166020d3ef9116fdc5764bc5117486e6d1211b25"}, + {file = "MarkupSafe-3.0.1-cp310-cp310-win32.whl", hash = "sha256:db15ce28e1e127a0013dfb8ac243a8e392db8c61eae113337536edb28bdc1f97"}, + {file = "MarkupSafe-3.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:4ffaaac913c3f7345579db4f33b0020db693f302ca5137f106060316761beea9"}, + {file = "MarkupSafe-3.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:26627785a54a947f6d7336ce5963569b5d75614619e75193bdb4e06e21d447ad"}, + {file = "MarkupSafe-3.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b954093679d5750495725ea6f88409946d69cfb25ea7b4c846eef5044194f583"}, + {file = "MarkupSafe-3.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:973a371a55ce9ed333a3a0f8e0bcfae9e0d637711534bcb11e130af2ab9334e7"}, + {file = "MarkupSafe-3.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:244dbe463d5fb6d7ce161301a03a6fe744dac9072328ba9fc82289238582697b"}, + {file = "MarkupSafe-3.0.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d98e66a24497637dd31ccab090b34392dddb1f2f811c4b4cd80c230205c074a3"}, + {file = "MarkupSafe-3.0.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ad91738f14eb8da0ff82f2acd0098b6257621410dcbd4df20aaa5b4233d75a50"}, + {file = "MarkupSafe-3.0.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:7044312a928a66a4c2a22644147bc61a199c1709712069a344a3fb5cfcf16915"}, + {file = "MarkupSafe-3.0.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a4792d3b3a6dfafefdf8e937f14906a51bd27025a36f4b188728a73382231d91"}, + {file = "MarkupSafe-3.0.1-cp311-cp311-win32.whl", hash = "sha256:fa7d686ed9883f3d664d39d5a8e74d3c5f63e603c2e3ff0abcba23eac6542635"}, + {file = "MarkupSafe-3.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:9ba25a71ebf05b9bb0e2ae99f8bc08a07ee8e98c612175087112656ca0f5c8bf"}, + {file = "MarkupSafe-3.0.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:8ae369e84466aa70f3154ee23c1451fda10a8ee1b63923ce76667e3077f2b0c4"}, + {file = "MarkupSafe-3.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40f1e10d51c92859765522cbd79c5c8989f40f0419614bcdc5015e7b6bf97fc5"}, + {file = "MarkupSafe-3.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5a4cb365cb49b750bdb60b846b0c0bc49ed62e59a76635095a179d440540c346"}, + {file = "MarkupSafe-3.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ee3941769bd2522fe39222206f6dd97ae83c442a94c90f2b7a25d847d40f4729"}, + {file = "MarkupSafe-3.0.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62fada2c942702ef8952754abfc1a9f7658a4d5460fabe95ac7ec2cbe0d02abc"}, + {file = "MarkupSafe-3.0.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4c2d64fdba74ad16138300815cfdc6ab2f4647e23ced81f59e940d7d4a1469d9"}, + {file = "MarkupSafe-3.0.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:fb532dd9900381d2e8f48172ddc5a59db4c445a11b9fab40b3b786da40d3b56b"}, + {file = "MarkupSafe-3.0.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0f84af7e813784feb4d5e4ff7db633aba6c8ca64a833f61d8e4eade234ef0c38"}, + {file = "MarkupSafe-3.0.1-cp312-cp312-win32.whl", hash = "sha256:cbf445eb5628981a80f54087f9acdbf84f9b7d862756110d172993b9a5ae81aa"}, + {file = "MarkupSafe-3.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:a10860e00ded1dd0a65b83e717af28845bb7bd16d8ace40fe5531491de76b79f"}, + {file = "MarkupSafe-3.0.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:e81c52638315ff4ac1b533d427f50bc0afc746deb949210bc85f05d4f15fd772"}, + {file = "MarkupSafe-3.0.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:312387403cd40699ab91d50735ea7a507b788091c416dd007eac54434aee51da"}, + {file = "MarkupSafe-3.0.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2ae99f31f47d849758a687102afdd05bd3d3ff7dbab0a8f1587981b58a76152a"}, + {file = "MarkupSafe-3.0.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c97ff7fedf56d86bae92fa0a646ce1a0ec7509a7578e1ed238731ba13aabcd1c"}, + {file = "MarkupSafe-3.0.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a7420ceda262dbb4b8d839a4ec63d61c261e4e77677ed7c66c99f4e7cb5030dd"}, + {file = "MarkupSafe-3.0.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:45d42d132cff577c92bfba536aefcfea7e26efb975bd455db4e6602f5c9f45e7"}, + {file = "MarkupSafe-3.0.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:4c8817557d0de9349109acb38b9dd570b03cc5014e8aabf1cbddc6e81005becd"}, + {file = "MarkupSafe-3.0.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6a54c43d3ec4cf2a39f4387ad044221c66a376e58c0d0e971d47c475ba79c6b5"}, + {file = "MarkupSafe-3.0.1-cp313-cp313-win32.whl", hash = "sha256:c91b394f7601438ff79a4b93d16be92f216adb57d813a78be4446fe0f6bc2d8c"}, + {file = "MarkupSafe-3.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:fe32482b37b4b00c7a52a07211b479653b7fe4f22b2e481b9a9b099d8a430f2f"}, + {file = "MarkupSafe-3.0.1-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:17b2aea42a7280db02ac644db1d634ad47dcc96faf38ab304fe26ba2680d359a"}, + {file = "MarkupSafe-3.0.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:852dc840f6d7c985603e60b5deaae1d89c56cb038b577f6b5b8c808c97580f1d"}, + {file = "MarkupSafe-3.0.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0778de17cff1acaeccc3ff30cd99a3fd5c50fc58ad3d6c0e0c4c58092b859396"}, + {file = "MarkupSafe-3.0.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:800100d45176652ded796134277ecb13640c1a537cad3b8b53da45aa96330453"}, + {file = "MarkupSafe-3.0.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d06b24c686a34c86c8c1fba923181eae6b10565e4d80bdd7bc1c8e2f11247aa4"}, + {file = "MarkupSafe-3.0.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:33d1c36b90e570ba7785dacd1faaf091203d9942bc036118fab8110a401eb1a8"}, + {file = "MarkupSafe-3.0.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:beeebf760a9c1f4c07ef6a53465e8cfa776ea6a2021eda0d0417ec41043fe984"}, + {file = "MarkupSafe-3.0.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:bbde71a705f8e9e4c3e9e33db69341d040c827c7afa6789b14c6e16776074f5a"}, + {file = "MarkupSafe-3.0.1-cp313-cp313t-win32.whl", hash = "sha256:82b5dba6eb1bcc29cc305a18a3c5365d2af06ee71b123216416f7e20d2a84e5b"}, + {file = "MarkupSafe-3.0.1-cp313-cp313t-win_amd64.whl", hash = "sha256:730d86af59e0e43ce277bb83970530dd223bf7f2a838e086b50affa6ec5f9295"}, + {file = "MarkupSafe-3.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:4935dd7883f1d50e2ffecca0aa33dc1946a94c8f3fdafb8df5c330e48f71b132"}, + {file = "MarkupSafe-3.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e9393357f19954248b00bed7c56f29a25c930593a77630c719653d51e7669c2a"}, + {file = "MarkupSafe-3.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40621d60d0e58aa573b68ac5e2d6b20d44392878e0bfc159012a5787c4e35bc8"}, + {file = "MarkupSafe-3.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f94190df587738280d544971500b9cafc9b950d32efcb1fba9ac10d84e6aa4e6"}, + {file = "MarkupSafe-3.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b6a387d61fe41cdf7ea95b38e9af11cfb1a63499af2759444b99185c4ab33f5b"}, + {file = "MarkupSafe-3.0.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:8ad4ad1429cd4f315f32ef263c1342166695fad76c100c5d979c45d5570ed58b"}, + {file = "MarkupSafe-3.0.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:e24bfe89c6ac4c31792793ad9f861b8f6dc4546ac6dc8f1c9083c7c4f2b335cd"}, + {file = "MarkupSafe-3.0.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:2a4b34a8d14649315c4bc26bbfa352663eb51d146e35eef231dd739d54a5430a"}, + {file = "MarkupSafe-3.0.1-cp39-cp39-win32.whl", hash = "sha256:242d6860f1fd9191aef5fae22b51c5c19767f93fb9ead4d21924e0bcb17619d8"}, + {file = "MarkupSafe-3.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:93e8248d650e7e9d49e8251f883eed60ecbc0e8ffd6349e18550925e31bd029b"}, + {file = "markupsafe-3.0.1.tar.gz", hash = "sha256:3e683ee4f5d0fa2dde4db77ed8dd8a876686e3fc417655c2ece9a90576905344"}, ] [[package]] @@ -1118,103 +1176,108 @@ files = [ [[package]] name = "multidict" -version = "6.0.5" +version = "6.1.0" description = "multidict implementation" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "multidict-6.0.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:228b644ae063c10e7f324ab1ab6b548bdf6f8b47f3ec234fef1093bc2735e5f9"}, - {file = "multidict-6.0.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:896ebdcf62683551312c30e20614305f53125750803b614e9e6ce74a96232604"}, - {file = "multidict-6.0.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:411bf8515f3be9813d06004cac41ccf7d1cd46dfe233705933dd163b60e37600"}, - {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d147090048129ce3c453f0292e7697d333db95e52616b3793922945804a433c"}, - {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:215ed703caf15f578dca76ee6f6b21b7603791ae090fbf1ef9d865571039ade5"}, - {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c6390cf87ff6234643428991b7359b5f59cc15155695deb4eda5c777d2b880f"}, - {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fd81c4ebdb4f214161be351eb5bcf385426bf023041da2fd9e60681f3cebae"}, - {file = "multidict-6.0.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3cc2ad10255f903656017363cd59436f2111443a76f996584d1077e43ee51182"}, - {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6939c95381e003f54cd4c5516740faba40cf5ad3eeff460c3ad1d3e0ea2549bf"}, - {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:220dd781e3f7af2c2c1053da9fa96d9cf3072ca58f057f4c5adaaa1cab8fc442"}, - {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:766c8f7511df26d9f11cd3a8be623e59cca73d44643abab3f8c8c07620524e4a"}, - {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:fe5d7785250541f7f5019ab9cba2c71169dc7d74d0f45253f8313f436458a4ef"}, - {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c1c1496e73051918fcd4f58ff2e0f2f3066d1c76a0c6aeffd9b45d53243702cc"}, - {file = "multidict-6.0.5-cp310-cp310-win32.whl", hash = "sha256:7afcdd1fc07befad18ec4523a782cde4e93e0a2bf71239894b8d61ee578c1319"}, - {file = "multidict-6.0.5-cp310-cp310-win_amd64.whl", hash = "sha256:99f60d34c048c5c2fabc766108c103612344c46e35d4ed9ae0673d33c8fb26e8"}, - {file = "multidict-6.0.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f285e862d2f153a70586579c15c44656f888806ed0e5b56b64489afe4a2dbfba"}, - {file = "multidict-6.0.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:53689bb4e102200a4fafa9de9c7c3c212ab40a7ab2c8e474491914d2305f187e"}, - {file = "multidict-6.0.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:612d1156111ae11d14afaf3a0669ebf6c170dbb735e510a7438ffe2369a847fd"}, - {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7be7047bd08accdb7487737631d25735c9a04327911de89ff1b26b81745bd4e3"}, - {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de170c7b4fe6859beb8926e84f7d7d6c693dfe8e27372ce3b76f01c46e489fcf"}, - {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:04bde7a7b3de05732a4eb39c94574db1ec99abb56162d6c520ad26f83267de29"}, - {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85f67aed7bb647f93e7520633d8f51d3cbc6ab96957c71272b286b2f30dc70ed"}, - {file = "multidict-6.0.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:425bf820055005bfc8aa9a0b99ccb52cc2f4070153e34b701acc98d201693733"}, - {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d3eb1ceec286eba8220c26f3b0096cf189aea7057b6e7b7a2e60ed36b373b77f"}, - {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7901c05ead4b3fb75113fb1dd33eb1253c6d3ee37ce93305acd9d38e0b5f21a4"}, - {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:e0e79d91e71b9867c73323a3444724d496c037e578a0e1755ae159ba14f4f3d1"}, - {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:29bfeb0dff5cb5fdab2023a7a9947b3b4af63e9c47cae2a10ad58394b517fddc"}, - {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e030047e85cbcedbfc073f71836d62dd5dadfbe7531cae27789ff66bc551bd5e"}, - {file = "multidict-6.0.5-cp311-cp311-win32.whl", hash = "sha256:2f4848aa3baa109e6ab81fe2006c77ed4d3cd1e0ac2c1fbddb7b1277c168788c"}, - {file = "multidict-6.0.5-cp311-cp311-win_amd64.whl", hash = "sha256:2faa5ae9376faba05f630d7e5e6be05be22913782b927b19d12b8145968a85ea"}, - {file = "multidict-6.0.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:51d035609b86722963404f711db441cf7134f1889107fb171a970c9701f92e1e"}, - {file = "multidict-6.0.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cbebcd5bcaf1eaf302617c114aa67569dd3f090dd0ce8ba9e35e9985b41ac35b"}, - {file = "multidict-6.0.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2ffc42c922dbfddb4a4c3b438eb056828719f07608af27d163191cb3e3aa6cc5"}, - {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ceb3b7e6a0135e092de86110c5a74e46bda4bd4fbfeeb3a3bcec79c0f861e450"}, - {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:79660376075cfd4b2c80f295528aa6beb2058fd289f4c9252f986751a4cd0496"}, - {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e4428b29611e989719874670fd152b6625500ad6c686d464e99f5aaeeaca175a"}, - {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d84a5c3a5f7ce6db1f999fb9438f686bc2e09d38143f2d93d8406ed2dd6b9226"}, - {file = "multidict-6.0.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:76c0de87358b192de7ea9649beb392f107dcad9ad27276324c24c91774ca5271"}, - {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:79a6d2ba910adb2cbafc95dad936f8b9386e77c84c35bc0add315b856d7c3abb"}, - {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:92d16a3e275e38293623ebf639c471d3e03bb20b8ebb845237e0d3664914caef"}, - {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:fb616be3538599e797a2017cccca78e354c767165e8858ab5116813146041a24"}, - {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:14c2976aa9038c2629efa2c148022ed5eb4cb939e15ec7aace7ca932f48f9ba6"}, - {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:435a0984199d81ca178b9ae2c26ec3d49692d20ee29bc4c11a2a8d4514c67eda"}, - {file = "multidict-6.0.5-cp312-cp312-win32.whl", hash = "sha256:9fe7b0653ba3d9d65cbe7698cca585bf0f8c83dbbcc710db9c90f478e175f2d5"}, - {file = "multidict-6.0.5-cp312-cp312-win_amd64.whl", hash = "sha256:01265f5e40f5a17f8241d52656ed27192be03bfa8764d88e8220141d1e4b3556"}, - {file = "multidict-6.0.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:19fe01cea168585ba0f678cad6f58133db2aa14eccaf22f88e4a6dccadfad8b3"}, - {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6bf7a982604375a8d49b6cc1b781c1747f243d91b81035a9b43a2126c04766f5"}, - {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:107c0cdefe028703fb5dafe640a409cb146d44a6ae201e55b35a4af8e95457dd"}, - {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:403c0911cd5d5791605808b942c88a8155c2592e05332d2bf78f18697a5fa15e"}, - {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aeaf541ddbad8311a87dd695ed9642401131ea39ad7bc8cf3ef3967fd093b626"}, - {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e4972624066095e52b569e02b5ca97dbd7a7ddd4294bf4e7247d52635630dd83"}, - {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d946b0a9eb8aaa590df1fe082cee553ceab173e6cb5b03239716338629c50c7a"}, - {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b55358304d7a73d7bdf5de62494aaf70bd33015831ffd98bc498b433dfe5b10c"}, - {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:a3145cb08d8625b2d3fee1b2d596a8766352979c9bffe5d7833e0503d0f0b5e5"}, - {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:d65f25da8e248202bd47445cec78e0025c0fe7582b23ec69c3b27a640dd7a8e3"}, - {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:c9bf56195c6bbd293340ea82eafd0071cb3d450c703d2c93afb89f93b8386ccc"}, - {file = "multidict-6.0.5-cp37-cp37m-win32.whl", hash = "sha256:69db76c09796b313331bb7048229e3bee7928eb62bab5e071e9f7fcc4879caee"}, - {file = "multidict-6.0.5-cp37-cp37m-win_amd64.whl", hash = "sha256:fce28b3c8a81b6b36dfac9feb1de115bab619b3c13905b419ec71d03a3fc1423"}, - {file = "multidict-6.0.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:76f067f5121dcecf0d63a67f29080b26c43c71a98b10c701b0677e4a065fbd54"}, - {file = "multidict-6.0.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b82cc8ace10ab5bd93235dfaab2021c70637005e1ac787031f4d1da63d493c1d"}, - {file = "multidict-6.0.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5cb241881eefd96b46f89b1a056187ea8e9ba14ab88ba632e68d7a2ecb7aadf7"}, - {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8e94e6912639a02ce173341ff62cc1201232ab86b8a8fcc05572741a5dc7d93"}, - {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:09a892e4a9fb47331da06948690ae38eaa2426de97b4ccbfafbdcbe5c8f37ff8"}, - {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55205d03e8a598cfc688c71ca8ea5f66447164efff8869517f175ea632c7cb7b"}, - {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37b15024f864916b4951adb95d3a80c9431299080341ab9544ed148091b53f50"}, - {file = "multidict-6.0.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2a1dee728b52b33eebff5072817176c172050d44d67befd681609b4746e1c2e"}, - {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:edd08e6f2f1a390bf137080507e44ccc086353c8e98c657e666c017718561b89"}, - {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:60d698e8179a42ec85172d12f50b1668254628425a6bd611aba022257cac1386"}, - {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:3d25f19500588cbc47dc19081d78131c32637c25804df8414463ec908631e453"}, - {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:4cc0ef8b962ac7a5e62b9e826bd0cd5040e7d401bc45a6835910ed699037a461"}, - {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:eca2e9d0cc5a889850e9bbd68e98314ada174ff6ccd1129500103df7a94a7a44"}, - {file = "multidict-6.0.5-cp38-cp38-win32.whl", hash = "sha256:4a6a4f196f08c58c59e0b8ef8ec441d12aee4125a7d4f4fef000ccb22f8d7241"}, - {file = "multidict-6.0.5-cp38-cp38-win_amd64.whl", hash = "sha256:0275e35209c27a3f7951e1ce7aaf93ce0d163b28948444bec61dd7badc6d3f8c"}, - {file = "multidict-6.0.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e7be68734bd8c9a513f2b0cfd508802d6609da068f40dc57d4e3494cefc92929"}, - {file = "multidict-6.0.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1d9ea7a7e779d7a3561aade7d596649fbecfa5c08a7674b11b423783217933f9"}, - {file = "multidict-6.0.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ea1456df2a27c73ce51120fa2f519f1bea2f4a03a917f4a43c8707cf4cbbae1a"}, - {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf590b134eb70629e350691ecca88eac3e3b8b3c86992042fb82e3cb1830d5e1"}, - {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5c0631926c4f58e9a5ccce555ad7747d9a9f8b10619621f22f9635f069f6233e"}, - {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dce1c6912ab9ff5f179eaf6efe7365c1f425ed690b03341911bf4939ef2f3046"}, - {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0868d64af83169e4d4152ec612637a543f7a336e4a307b119e98042e852ad9c"}, - {file = "multidict-6.0.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:141b43360bfd3bdd75f15ed811850763555a251e38b2405967f8e25fb43f7d40"}, - {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7df704ca8cf4a073334e0427ae2345323613e4df18cc224f647f251e5e75a527"}, - {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:6214c5a5571802c33f80e6c84713b2c79e024995b9c5897f794b43e714daeec9"}, - {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:cd6c8fca38178e12c00418de737aef1261576bd1b6e8c6134d3e729a4e858b38"}, - {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:e02021f87a5b6932fa6ce916ca004c4d441509d33bbdbeca70d05dff5e9d2479"}, - {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ebd8d160f91a764652d3e51ce0d2956b38efe37c9231cd82cfc0bed2e40b581c"}, - {file = "multidict-6.0.5-cp39-cp39-win32.whl", hash = "sha256:04da1bb8c8dbadf2a18a452639771951c662c5ad03aefe4884775454be322c9b"}, - {file = "multidict-6.0.5-cp39-cp39-win_amd64.whl", hash = "sha256:d6f6d4f185481c9669b9447bf9d9cf3b95a0e9df9d169bbc17e363b7d5487755"}, - {file = "multidict-6.0.5-py3-none-any.whl", hash = "sha256:0d63c74e3d7ab26de115c49bffc92cc77ed23395303d496eae515d4204a625e7"}, - {file = "multidict-6.0.5.tar.gz", hash = "sha256:f7e301075edaf50500f0b341543c41194d8df3ae5caf4702f2095f3ca73dd8da"}, + {file = "multidict-6.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3380252550e372e8511d49481bd836264c009adb826b23fefcc5dd3c69692f60"}, + {file = "multidict-6.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:99f826cbf970077383d7de805c0681799491cb939c25450b9b5b3ced03ca99f1"}, + {file = "multidict-6.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a114d03b938376557927ab23f1e950827c3b893ccb94b62fd95d430fd0e5cf53"}, + {file = "multidict-6.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b1c416351ee6271b2f49b56ad7f308072f6f44b37118d69c2cad94f3fa8a40d5"}, + {file = "multidict-6.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6b5d83030255983181005e6cfbac1617ce9746b219bc2aad52201ad121226581"}, + {file = "multidict-6.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3e97b5e938051226dc025ec80980c285b053ffb1e25a3db2a3aa3bc046bf7f56"}, + {file = "multidict-6.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d618649d4e70ac6efcbba75be98b26ef5078faad23592f9b51ca492953012429"}, + {file = "multidict-6.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:10524ebd769727ac77ef2278390fb0068d83f3acb7773792a5080f2b0abf7748"}, + {file = "multidict-6.1.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:ff3827aef427c89a25cc96ded1759271a93603aba9fb977a6d264648ebf989db"}, + {file = "multidict-6.1.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:06809f4f0f7ab7ea2cabf9caca7d79c22c0758b58a71f9d32943ae13c7ace056"}, + {file = "multidict-6.1.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:f179dee3b863ab1c59580ff60f9d99f632f34ccb38bf67a33ec6b3ecadd0fd76"}, + {file = "multidict-6.1.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:aaed8b0562be4a0876ee3b6946f6869b7bcdb571a5d1496683505944e268b160"}, + {file = "multidict-6.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3c8b88a2ccf5493b6c8da9076fb151ba106960a2df90c2633f342f120751a9e7"}, + {file = "multidict-6.1.0-cp310-cp310-win32.whl", hash = "sha256:4a9cb68166a34117d6646c0023c7b759bf197bee5ad4272f420a0141d7eb03a0"}, + {file = "multidict-6.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:20b9b5fbe0b88d0bdef2012ef7dee867f874b72528cf1d08f1d59b0e3850129d"}, + {file = "multidict-6.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:3efe2c2cb5763f2f1b275ad2bf7a287d3f7ebbef35648a9726e3b69284a4f3d6"}, + {file = "multidict-6.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c7053d3b0353a8b9de430a4f4b4268ac9a4fb3481af37dfe49825bf45ca24156"}, + {file = "multidict-6.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:27e5fc84ccef8dfaabb09d82b7d179c7cf1a3fbc8a966f8274fcb4ab2eb4cadb"}, + {file = "multidict-6.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0e2b90b43e696f25c62656389d32236e049568b39320e2735d51f08fd362761b"}, + {file = "multidict-6.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d83a047959d38a7ff552ff94be767b7fd79b831ad1cd9920662db05fec24fe72"}, + {file = "multidict-6.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d1a9dd711d0877a1ece3d2e4fea11a8e75741ca21954c919406b44e7cf971304"}, + {file = "multidict-6.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec2abea24d98246b94913b76a125e855eb5c434f7c46546046372fe60f666351"}, + {file = "multidict-6.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4867cafcbc6585e4b678876c489b9273b13e9fff9f6d6d66add5e15d11d926cb"}, + {file = "multidict-6.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:5b48204e8d955c47c55b72779802b219a39acc3ee3d0116d5080c388970b76e3"}, + {file = "multidict-6.1.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:d8fff389528cad1618fb4b26b95550327495462cd745d879a8c7c2115248e399"}, + {file = "multidict-6.1.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:a7a9541cd308eed5e30318430a9c74d2132e9a8cb46b901326272d780bf2d423"}, + {file = "multidict-6.1.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:da1758c76f50c39a2efd5e9859ce7d776317eb1dd34317c8152ac9251fc574a3"}, + {file = "multidict-6.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c943a53e9186688b45b323602298ab727d8865d8c9ee0b17f8d62d14b56f0753"}, + {file = "multidict-6.1.0-cp311-cp311-win32.whl", hash = "sha256:90f8717cb649eea3504091e640a1b8568faad18bd4b9fcd692853a04475a4b80"}, + {file = "multidict-6.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:82176036e65644a6cc5bd619f65f6f19781e8ec2e5330f51aa9ada7504cc1926"}, + {file = "multidict-6.1.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:b04772ed465fa3cc947db808fa306d79b43e896beb677a56fb2347ca1a49c1fa"}, + {file = "multidict-6.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:6180c0ae073bddeb5a97a38c03f30c233e0a4d39cd86166251617d1bbd0af436"}, + {file = "multidict-6.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:071120490b47aa997cca00666923a83f02c7fbb44f71cf7f136df753f7fa8761"}, + {file = "multidict-6.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50b3a2710631848991d0bf7de077502e8994c804bb805aeb2925a981de58ec2e"}, + {file = "multidict-6.1.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b58c621844d55e71c1b7f7c498ce5aa6985d743a1a59034c57a905b3f153c1ef"}, + {file = "multidict-6.1.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55b6d90641869892caa9ca42ff913f7ff1c5ece06474fbd32fb2cf6834726c95"}, + {file = "multidict-6.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b820514bfc0b98a30e3d85462084779900347e4d49267f747ff54060cc33925"}, + {file = "multidict-6.1.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:10a9b09aba0c5b48c53761b7c720aaaf7cf236d5fe394cd399c7ba662d5f9966"}, + {file = "multidict-6.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1e16bf3e5fc9f44632affb159d30a437bfe286ce9e02754759be5536b169b305"}, + {file = "multidict-6.1.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:76f364861c3bfc98cbbcbd402d83454ed9e01a5224bb3a28bf70002a230f73e2"}, + {file = "multidict-6.1.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:820c661588bd01a0aa62a1283f20d2be4281b086f80dad9e955e690c75fb54a2"}, + {file = "multidict-6.1.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:0e5f362e895bc5b9e67fe6e4ded2492d8124bdf817827f33c5b46c2fe3ffaca6"}, + {file = "multidict-6.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3ec660d19bbc671e3a6443325f07263be452c453ac9e512f5eb935e7d4ac28b3"}, + {file = "multidict-6.1.0-cp312-cp312-win32.whl", hash = "sha256:58130ecf8f7b8112cdb841486404f1282b9c86ccb30d3519faf301b2e5659133"}, + {file = "multidict-6.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:188215fc0aafb8e03341995e7c4797860181562380f81ed0a87ff455b70bf1f1"}, + {file = "multidict-6.1.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:d569388c381b24671589335a3be6e1d45546c2988c2ebe30fdcada8457a31008"}, + {file = "multidict-6.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:052e10d2d37810b99cc170b785945421141bf7bb7d2f8799d431e7db229c385f"}, + {file = "multidict-6.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f90c822a402cb865e396a504f9fc8173ef34212a342d92e362ca498cad308e28"}, + {file = "multidict-6.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b225d95519a5bf73860323e633a664b0d85ad3d5bede6d30d95b35d4dfe8805b"}, + {file = "multidict-6.1.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:23bfd518810af7de1116313ebd9092cb9aa629beb12f6ed631ad53356ed6b86c"}, + {file = "multidict-6.1.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c09fcfdccdd0b57867577b719c69e347a436b86cd83747f179dbf0cc0d4c1f3"}, + {file = "multidict-6.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf6bea52ec97e95560af5ae576bdac3aa3aae0b6758c6efa115236d9e07dae44"}, + {file = "multidict-6.1.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57feec87371dbb3520da6192213c7d6fc892d5589a93db548331954de8248fd2"}, + {file = "multidict-6.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0c3f390dc53279cbc8ba976e5f8035eab997829066756d811616b652b00a23a3"}, + {file = "multidict-6.1.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:59bfeae4b25ec05b34f1956eaa1cb38032282cd4dfabc5056d0a1ec4d696d3aa"}, + {file = "multidict-6.1.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:b2f59caeaf7632cc633b5cf6fc449372b83bbdf0da4ae04d5be36118e46cc0aa"}, + {file = "multidict-6.1.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:37bb93b2178e02b7b618893990941900fd25b6b9ac0fa49931a40aecdf083fe4"}, + {file = "multidict-6.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4e9f48f58c2c523d5a06faea47866cd35b32655c46b443f163d08c6d0ddb17d6"}, + {file = "multidict-6.1.0-cp313-cp313-win32.whl", hash = "sha256:3a37ffb35399029b45c6cc33640a92bef403c9fd388acce75cdc88f58bd19a81"}, + {file = "multidict-6.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:e9aa71e15d9d9beaad2c6b9319edcdc0a49a43ef5c0a4c8265ca9ee7d6c67774"}, + {file = "multidict-6.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:db7457bac39421addd0c8449933ac32d8042aae84a14911a757ae6ca3eef1392"}, + {file = "multidict-6.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d094ddec350a2fb899fec68d8353c78233debde9b7d8b4beeafa70825f1c281a"}, + {file = "multidict-6.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5845c1fd4866bb5dd3125d89b90e57ed3138241540897de748cdf19de8a2fca2"}, + {file = "multidict-6.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9079dfc6a70abe341f521f78405b8949f96db48da98aeb43f9907f342f627cdc"}, + {file = "multidict-6.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3914f5aaa0f36d5d60e8ece6a308ee1c9784cd75ec8151062614657a114c4478"}, + {file = "multidict-6.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c08be4f460903e5a9d0f76818db3250f12e9c344e79314d1d570fc69d7f4eae4"}, + {file = "multidict-6.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d093be959277cb7dee84b801eb1af388b6ad3ca6a6b6bf1ed7585895789d027d"}, + {file = "multidict-6.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3702ea6872c5a2a4eeefa6ffd36b042e9773f05b1f37ae3ef7264b1163c2dcf6"}, + {file = "multidict-6.1.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:2090f6a85cafc5b2db085124d752757c9d251548cedabe9bd31afe6363e0aff2"}, + {file = "multidict-6.1.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:f67f217af4b1ff66c68a87318012de788dd95fcfeb24cc889011f4e1c7454dfd"}, + {file = "multidict-6.1.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:189f652a87e876098bbc67b4da1049afb5f5dfbaa310dd67c594b01c10388db6"}, + {file = "multidict-6.1.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:6bb5992037f7a9eff7991ebe4273ea7f51f1c1c511e6a2ce511d0e7bdb754492"}, + {file = "multidict-6.1.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:ac10f4c2b9e770c4e393876e35a7046879d195cd123b4f116d299d442b335bcd"}, + {file = "multidict-6.1.0-cp38-cp38-win32.whl", hash = "sha256:e27bbb6d14416713a8bd7aaa1313c0fc8d44ee48d74497a0ff4c3a1b6ccb5167"}, + {file = "multidict-6.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:22f3105d4fb15c8f57ff3959a58fcab6ce36814486500cd7485651230ad4d4ef"}, + {file = "multidict-6.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:4e18b656c5e844539d506a0a06432274d7bd52a7487e6828c63a63d69185626c"}, + {file = "multidict-6.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a185f876e69897a6f3325c3f19f26a297fa058c5e456bfcff8015e9a27e83ae1"}, + {file = "multidict-6.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ab7c4ceb38d91570a650dba194e1ca87c2b543488fe9309b4212694174fd539c"}, + {file = "multidict-6.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e617fb6b0b6953fffd762669610c1c4ffd05632c138d61ac7e14ad187870669c"}, + {file = "multidict-6.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:16e5f4bf4e603eb1fdd5d8180f1a25f30056f22e55ce51fb3d6ad4ab29f7d96f"}, + {file = "multidict-6.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f4c035da3f544b1882bac24115f3e2e8760f10a0107614fc9839fd232200b875"}, + {file = "multidict-6.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:957cf8e4b6e123a9eea554fa7ebc85674674b713551de587eb318a2df3e00255"}, + {file = "multidict-6.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:483a6aea59cb89904e1ceabd2b47368b5600fb7de78a6e4a2c2987b2d256cf30"}, + {file = "multidict-6.1.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:87701f25a2352e5bf7454caa64757642734da9f6b11384c1f9d1a8e699758057"}, + {file = "multidict-6.1.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:682b987361e5fd7a139ed565e30d81fd81e9629acc7d925a205366877d8c8657"}, + {file = "multidict-6.1.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:ce2186a7df133a9c895dea3331ddc5ddad42cdd0d1ea2f0a51e5d161e4762f28"}, + {file = "multidict-6.1.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:9f636b730f7e8cb19feb87094949ba54ee5357440b9658b2a32a5ce4bce53972"}, + {file = "multidict-6.1.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:73eae06aa53af2ea5270cc066dcaf02cc60d2994bbb2c4ef5764949257d10f43"}, + {file = "multidict-6.1.0-cp39-cp39-win32.whl", hash = "sha256:1ca0083e80e791cffc6efce7660ad24af66c8d4079d2a750b29001b53ff59ada"}, + {file = "multidict-6.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:aa466da5b15ccea564bdab9c89175c762bc12825f4659c11227f515cee76fa4a"}, + {file = "multidict-6.1.0-py3-none-any.whl", hash = "sha256:48e171e52d1c4d33888e529b999e5900356b9ae588c2f09a52dcefb158b27506"}, + {file = "multidict-6.1.0.tar.gz", hash = "sha256:22ae2ebf9b0c69d206c003e2f6a914ea33f0a932d4aa16f236afc049d9958f4a"}, ] +[package.dependencies] +typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.11\""} + [[package]] name = "mypy-extensions" version = "1.0.0" @@ -1228,64 +1291,68 @@ files = [ [[package]] name = "orjson" -version = "3.10.6" +version = "3.10.7" description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy" optional = false python-versions = ">=3.8" files = [ - {file = "orjson-3.10.6-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:fb0ee33124db6eaa517d00890fc1a55c3bfe1cf78ba4a8899d71a06f2d6ff5c7"}, - {file = "orjson-3.10.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9c1c4b53b24a4c06547ce43e5fee6ec4e0d8fe2d597f4647fc033fd205707365"}, - {file = "orjson-3.10.6-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eadc8fd310edb4bdbd333374f2c8fec6794bbbae99b592f448d8214a5e4050c0"}, - {file = "orjson-3.10.6-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:61272a5aec2b2661f4fa2b37c907ce9701e821b2c1285d5c3ab0207ebd358d38"}, - {file = "orjson-3.10.6-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:57985ee7e91d6214c837936dc1608f40f330a6b88bb13f5a57ce5257807da143"}, - {file = "orjson-3.10.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:633a3b31d9d7c9f02d49c4ab4d0a86065c4a6f6adc297d63d272e043472acab5"}, - {file = "orjson-3.10.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:1c680b269d33ec444afe2bdc647c9eb73166fa47a16d9a75ee56a374f4a45f43"}, - {file = "orjson-3.10.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f759503a97a6ace19e55461395ab0d618b5a117e8d0fbb20e70cfd68a47327f2"}, - {file = "orjson-3.10.6-cp310-none-win32.whl", hash = "sha256:95a0cce17f969fb5391762e5719575217bd10ac5a189d1979442ee54456393f3"}, - {file = "orjson-3.10.6-cp310-none-win_amd64.whl", hash = "sha256:df25d9271270ba2133cc88ee83c318372bdc0f2cd6f32e7a450809a111efc45c"}, - {file = "orjson-3.10.6-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:b1ec490e10d2a77c345def52599311849fc063ae0e67cf4f84528073152bb2ba"}, - {file = "orjson-3.10.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:55d43d3feb8f19d07e9f01e5b9be4f28801cf7c60d0fa0d279951b18fae1932b"}, - {file = "orjson-3.10.6-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac3045267e98fe749408eee1593a142e02357c5c99be0802185ef2170086a863"}, - {file = "orjson-3.10.6-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c27bc6a28ae95923350ab382c57113abd38f3928af3c80be6f2ba7eb8d8db0b0"}, - {file = "orjson-3.10.6-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d27456491ca79532d11e507cadca37fb8c9324a3976294f68fb1eff2dc6ced5a"}, - {file = "orjson-3.10.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05ac3d3916023745aa3b3b388e91b9166be1ca02b7c7e41045da6d12985685f0"}, - {file = "orjson-3.10.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1335d4ef59ab85cab66fe73fd7a4e881c298ee7f63ede918b7faa1b27cbe5212"}, - {file = "orjson-3.10.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4bbc6d0af24c1575edc79994c20e1b29e6fb3c6a570371306db0993ecf144dc5"}, - {file = "orjson-3.10.6-cp311-none-win32.whl", hash = "sha256:450e39ab1f7694465060a0550b3f6d328d20297bf2e06aa947b97c21e5241fbd"}, - {file = "orjson-3.10.6-cp311-none-win_amd64.whl", hash = "sha256:227df19441372610b20e05bdb906e1742ec2ad7a66ac8350dcfd29a63014a83b"}, - {file = "orjson-3.10.6-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:ea2977b21f8d5d9b758bb3f344a75e55ca78e3ff85595d248eee813ae23ecdfb"}, - {file = "orjson-3.10.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b6f3d167d13a16ed263b52dbfedff52c962bfd3d270b46b7518365bcc2121eed"}, - {file = "orjson-3.10.6-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f710f346e4c44a4e8bdf23daa974faede58f83334289df80bc9cd12fe82573c7"}, - {file = "orjson-3.10.6-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7275664f84e027dcb1ad5200b8b18373e9c669b2a9ec33d410c40f5ccf4b257e"}, - {file = "orjson-3.10.6-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0943e4c701196b23c240b3d10ed8ecd674f03089198cf503105b474a4f77f21f"}, - {file = "orjson-3.10.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:446dee5a491b5bc7d8f825d80d9637e7af43f86a331207b9c9610e2f93fee22a"}, - {file = "orjson-3.10.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:64c81456d2a050d380786413786b057983892db105516639cb5d3ee3c7fd5148"}, - {file = "orjson-3.10.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:960db0e31c4e52fa0fc3ecbaea5b2d3b58f379e32a95ae6b0ebeaa25b93dfd34"}, - {file = "orjson-3.10.6-cp312-none-win32.whl", hash = "sha256:a6ea7afb5b30b2317e0bee03c8d34c8181bc5a36f2afd4d0952f378972c4efd5"}, - {file = "orjson-3.10.6-cp312-none-win_amd64.whl", hash = "sha256:874ce88264b7e655dde4aeaacdc8fd772a7962faadfb41abe63e2a4861abc3dc"}, - {file = "orjson-3.10.6-cp313-none-win32.whl", hash = "sha256:efdf2c5cde290ae6b83095f03119bdc00303d7a03b42b16c54517baa3c4ca3d0"}, - {file = "orjson-3.10.6-cp313-none-win_amd64.whl", hash = "sha256:8e190fe7888e2e4392f52cafb9626113ba135ef53aacc65cd13109eb9746c43e"}, - {file = "orjson-3.10.6-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:66680eae4c4e7fc193d91cfc1353ad6d01b4801ae9b5314f17e11ba55e934183"}, - {file = "orjson-3.10.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:caff75b425db5ef8e8f23af93c80f072f97b4fb3afd4af44482905c9f588da28"}, - {file = "orjson-3.10.6-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3722fddb821b6036fd2a3c814f6bd9b57a89dc6337b9924ecd614ebce3271394"}, - {file = "orjson-3.10.6-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c2c116072a8533f2fec435fde4d134610f806bdac20188c7bd2081f3e9e0133f"}, - {file = "orjson-3.10.6-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6eeb13218c8cf34c61912e9df2de2853f1d009de0e46ea09ccdf3d757896af0a"}, - {file = "orjson-3.10.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:965a916373382674e323c957d560b953d81d7a8603fbeee26f7b8248638bd48b"}, - {file = "orjson-3.10.6-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:03c95484d53ed8e479cade8628c9cea00fd9d67f5554764a1110e0d5aa2de96e"}, - {file = "orjson-3.10.6-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:e060748a04cccf1e0a6f2358dffea9c080b849a4a68c28b1b907f272b5127e9b"}, - {file = "orjson-3.10.6-cp38-none-win32.whl", hash = "sha256:738dbe3ef909c4b019d69afc19caf6b5ed0e2f1c786b5d6215fbb7539246e4c6"}, - {file = "orjson-3.10.6-cp38-none-win_amd64.whl", hash = "sha256:d40f839dddf6a7d77114fe6b8a70218556408c71d4d6e29413bb5f150a692ff7"}, - {file = "orjson-3.10.6-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:697a35a083c4f834807a6232b3e62c8b280f7a44ad0b759fd4dce748951e70db"}, - {file = "orjson-3.10.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fd502f96bf5ea9a61cbc0b2b5900d0dd68aa0da197179042bdd2be67e51a1e4b"}, - {file = "orjson-3.10.6-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f215789fb1667cdc874c1b8af6a84dc939fd802bf293a8334fce185c79cd359b"}, - {file = "orjson-3.10.6-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a2debd8ddce948a8c0938c8c93ade191d2f4ba4649a54302a7da905a81f00b56"}, - {file = "orjson-3.10.6-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5410111d7b6681d4b0d65e0f58a13be588d01b473822483f77f513c7f93bd3b2"}, - {file = "orjson-3.10.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bb1f28a137337fdc18384079fa5726810681055b32b92253fa15ae5656e1dddb"}, - {file = "orjson-3.10.6-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:bf2fbbce5fe7cd1aa177ea3eab2b8e6a6bc6e8592e4279ed3db2d62e57c0e1b2"}, - {file = "orjson-3.10.6-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:79b9b9e33bd4c517445a62b90ca0cc279b0f1f3970655c3df9e608bc3f91741a"}, - {file = "orjson-3.10.6-cp39-none-win32.whl", hash = "sha256:30b0a09a2014e621b1adf66a4f705f0809358350a757508ee80209b2d8dae219"}, - {file = "orjson-3.10.6-cp39-none-win_amd64.whl", hash = "sha256:49e3bc615652617d463069f91b867a4458114c5b104e13b7ae6872e5f79d0844"}, - {file = "orjson-3.10.6.tar.gz", hash = "sha256:e54b63d0a7c6c54a5f5f726bc93a2078111ef060fec4ecbf34c5db800ca3b3a7"}, + {file = "orjson-3.10.7-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:74f4544f5a6405b90da8ea724d15ac9c36da4d72a738c64685003337401f5c12"}, + {file = "orjson-3.10.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:34a566f22c28222b08875b18b0dfbf8a947e69df21a9ed5c51a6bf91cfb944ac"}, + {file = "orjson-3.10.7-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bf6ba8ebc8ef5792e2337fb0419f8009729335bb400ece005606336b7fd7bab7"}, + {file = "orjson-3.10.7-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac7cf6222b29fbda9e3a472b41e6a5538b48f2c8f99261eecd60aafbdb60690c"}, + {file = "orjson-3.10.7-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:de817e2f5fc75a9e7dd350c4b0f54617b280e26d1631811a43e7e968fa71e3e9"}, + {file = "orjson-3.10.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:348bdd16b32556cf8d7257b17cf2bdb7ab7976af4af41ebe79f9796c218f7e91"}, + {file = "orjson-3.10.7-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:479fd0844ddc3ca77e0fd99644c7fe2de8e8be1efcd57705b5c92e5186e8a250"}, + {file = "orjson-3.10.7-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:fdf5197a21dd660cf19dfd2a3ce79574588f8f5e2dbf21bda9ee2d2b46924d84"}, + {file = "orjson-3.10.7-cp310-none-win32.whl", hash = "sha256:d374d36726746c81a49f3ff8daa2898dccab6596864ebe43d50733275c629175"}, + {file = "orjson-3.10.7-cp310-none-win_amd64.whl", hash = "sha256:cb61938aec8b0ffb6eef484d480188a1777e67b05d58e41b435c74b9d84e0b9c"}, + {file = "orjson-3.10.7-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:7db8539039698ddfb9a524b4dd19508256107568cdad24f3682d5773e60504a2"}, + {file = "orjson-3.10.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:480f455222cb7a1dea35c57a67578848537d2602b46c464472c995297117fa09"}, + {file = "orjson-3.10.7-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8a9c9b168b3a19e37fe2778c0003359f07822c90fdff8f98d9d2a91b3144d8e0"}, + {file = "orjson-3.10.7-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8de062de550f63185e4c1c54151bdddfc5625e37daf0aa1e75d2a1293e3b7d9a"}, + {file = "orjson-3.10.7-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6b0dd04483499d1de9c8f6203f8975caf17a6000b9c0c54630cef02e44ee624e"}, + {file = "orjson-3.10.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b58d3795dafa334fc8fd46f7c5dc013e6ad06fd5b9a4cc98cb1456e7d3558bd6"}, + {file = "orjson-3.10.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:33cfb96c24034a878d83d1a9415799a73dc77480e6c40417e5dda0710d559ee6"}, + {file = "orjson-3.10.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e724cebe1fadc2b23c6f7415bad5ee6239e00a69f30ee423f319c6af70e2a5c0"}, + {file = "orjson-3.10.7-cp311-none-win32.whl", hash = "sha256:82763b46053727a7168d29c772ed5c870fdae2f61aa8a25994c7984a19b1021f"}, + {file = "orjson-3.10.7-cp311-none-win_amd64.whl", hash = "sha256:eb8d384a24778abf29afb8e41d68fdd9a156cf6e5390c04cc07bbc24b89e98b5"}, + {file = "orjson-3.10.7-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:44a96f2d4c3af51bfac6bc4ef7b182aa33f2f054fd7f34cc0ee9a320d051d41f"}, + {file = "orjson-3.10.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76ac14cd57df0572453543f8f2575e2d01ae9e790c21f57627803f5e79b0d3c3"}, + {file = "orjson-3.10.7-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bdbb61dcc365dd9be94e8f7df91975edc9364d6a78c8f7adb69c1cdff318ec93"}, + {file = "orjson-3.10.7-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b48b3db6bb6e0a08fa8c83b47bc169623f801e5cc4f24442ab2b6617da3b5313"}, + {file = "orjson-3.10.7-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:23820a1563a1d386414fef15c249040042b8e5d07b40ab3fe3efbfbbcbcb8864"}, + {file = "orjson-3.10.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0c6a008e91d10a2564edbb6ee5069a9e66df3fbe11c9a005cb411f441fd2c09"}, + {file = "orjson-3.10.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d352ee8ac1926d6193f602cbe36b1643bbd1bbcb25e3c1a657a4390f3000c9a5"}, + {file = "orjson-3.10.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:d2d9f990623f15c0ae7ac608103c33dfe1486d2ed974ac3f40b693bad1a22a7b"}, + {file = "orjson-3.10.7-cp312-none-win32.whl", hash = "sha256:7c4c17f8157bd520cdb7195f75ddbd31671997cbe10aee559c2d613592e7d7eb"}, + {file = "orjson-3.10.7-cp312-none-win_amd64.whl", hash = "sha256:1d9c0e733e02ada3ed6098a10a8ee0052dd55774de3d9110d29868d24b17faa1"}, + {file = "orjson-3.10.7-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:77d325ed866876c0fa6492598ec01fe30e803272a6e8b10e992288b009cbe149"}, + {file = "orjson-3.10.7-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9ea2c232deedcb605e853ae1db2cc94f7390ac776743b699b50b071b02bea6fe"}, + {file = "orjson-3.10.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:3dcfbede6737fdbef3ce9c37af3fb6142e8e1ebc10336daa05872bfb1d87839c"}, + {file = "orjson-3.10.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:11748c135f281203f4ee695b7f80bb1358a82a63905f9f0b794769483ea854ad"}, + {file = "orjson-3.10.7-cp313-none-win32.whl", hash = "sha256:a7e19150d215c7a13f39eb787d84db274298d3f83d85463e61d277bbd7f401d2"}, + {file = "orjson-3.10.7-cp313-none-win_amd64.whl", hash = "sha256:eef44224729e9525d5261cc8d28d6b11cafc90e6bd0be2157bde69a52ec83024"}, + {file = "orjson-3.10.7-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:6ea2b2258eff652c82652d5e0f02bd5e0463a6a52abb78e49ac288827aaa1469"}, + {file = "orjson-3.10.7-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:430ee4d85841e1483d487e7b81401785a5dfd69db5de01314538f31f8fbf7ee1"}, + {file = "orjson-3.10.7-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4b6146e439af4c2472c56f8540d799a67a81226e11992008cb47e1267a9b3225"}, + {file = "orjson-3.10.7-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:084e537806b458911137f76097e53ce7bf5806dda33ddf6aaa66a028f8d43a23"}, + {file = "orjson-3.10.7-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4829cf2195838e3f93b70fd3b4292156fc5e097aac3739859ac0dcc722b27ac0"}, + {file = "orjson-3.10.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1193b2416cbad1a769f868b1749535d5da47626ac29445803dae7cc64b3f5c98"}, + {file = "orjson-3.10.7-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:4e6c3da13e5a57e4b3dca2de059f243ebec705857522f188f0180ae88badd354"}, + {file = "orjson-3.10.7-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:c31008598424dfbe52ce8c5b47e0752dca918a4fdc4a2a32004efd9fab41d866"}, + {file = "orjson-3.10.7-cp38-none-win32.whl", hash = "sha256:7122a99831f9e7fe977dc45784d3b2edc821c172d545e6420c375e5a935f5a1c"}, + {file = "orjson-3.10.7-cp38-none-win_amd64.whl", hash = "sha256:a763bc0e58504cc803739e7df040685816145a6f3c8a589787084b54ebc9f16e"}, + {file = "orjson-3.10.7-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:e76be12658a6fa376fcd331b1ea4e58f5a06fd0220653450f0d415b8fd0fbe20"}, + {file = "orjson-3.10.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed350d6978d28b92939bfeb1a0570c523f6170efc3f0a0ef1f1df287cd4f4960"}, + {file = "orjson-3.10.7-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:144888c76f8520e39bfa121b31fd637e18d4cc2f115727865fdf9fa325b10412"}, + {file = "orjson-3.10.7-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:09b2d92fd95ad2402188cf51573acde57eb269eddabaa60f69ea0d733e789fe9"}, + {file = "orjson-3.10.7-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5b24a579123fa884f3a3caadaed7b75eb5715ee2b17ab5c66ac97d29b18fe57f"}, + {file = "orjson-3.10.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e72591bcfe7512353bd609875ab38050efe3d55e18934e2f18950c108334b4ff"}, + {file = "orjson-3.10.7-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:f4db56635b58cd1a200b0a23744ff44206ee6aa428185e2b6c4a65b3197abdcd"}, + {file = "orjson-3.10.7-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:0fa5886854673222618638c6df7718ea7fe2f3f2384c452c9ccedc70b4a510a5"}, + {file = "orjson-3.10.7-cp39-none-win32.whl", hash = "sha256:8272527d08450ab16eb405f47e0f4ef0e5ff5981c3d82afe0efd25dcbef2bcd2"}, + {file = "orjson-3.10.7-cp39-none-win_amd64.whl", hash = "sha256:974683d4618c0c7dbf4f69c95a979734bf183d0658611760017f6e70a145af58"}, + {file = "orjson-3.10.7.tar.gz", hash = "sha256:75ef0640403f945f3a1f9f6400686560dbfb0fb5b16589ad62cd477043c4eee3"}, ] [[package]] @@ -1312,19 +1379,19 @@ files = [ [[package]] name = "platformdirs" -version = "4.2.2" +version = "4.3.6" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." optional = false python-versions = ">=3.8" files = [ - {file = "platformdirs-4.2.2-py3-none-any.whl", hash = "sha256:2d7a1657e36a80ea911db832a8a6ece5ee53d8de21edd5cc5879af6530b1bfee"}, - {file = "platformdirs-4.2.2.tar.gz", hash = "sha256:38b7b51f512eed9e84a22788b4bce1de17c0adb134d6becb09836e37d8654cd3"}, + {file = "platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb"}, + {file = "platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907"}, ] [package.extras] -docs = ["furo (>=2023.9.10)", "proselint (>=0.13)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)"] -type = ["mypy (>=1.8)"] +docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.2)", "pytest-cov (>=5)", "pytest-mock (>=3.14)"] +type = ["mypy (>=1.11.2)"] [[package]] name = "pluggy" @@ -1341,98 +1408,203 @@ files = [ dev = ["pre-commit", "tox"] testing = ["pytest", "pytest-benchmark"] +[[package]] +name = "propcache" +version = "0.2.0" +description = "Accelerated property cache" +optional = false +python-versions = ">=3.8" +files = [ + {file = "propcache-0.2.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:c5869b8fd70b81835a6f187c5fdbe67917a04d7e52b6e7cc4e5fe39d55c39d58"}, + {file = "propcache-0.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:952e0d9d07609d9c5be361f33b0d6d650cd2bae393aabb11d9b719364521984b"}, + {file = "propcache-0.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:33ac8f098df0585c0b53009f039dfd913b38c1d2edafed0cedcc0c32a05aa110"}, + {file = "propcache-0.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:97e48e8875e6c13909c800fa344cd54cc4b2b0db1d5f911f840458a500fde2c2"}, + {file = "propcache-0.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:388f3217649d6d59292b722d940d4d2e1e6a7003259eb835724092a1cca0203a"}, + {file = "propcache-0.2.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f571aea50ba5623c308aa146eb650eebf7dbe0fd8c5d946e28343cb3b5aad577"}, + {file = "propcache-0.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3dfafb44f7bb35c0c06eda6b2ab4bfd58f02729e7c4045e179f9a861b07c9850"}, + {file = "propcache-0.2.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a3ebe9a75be7ab0b7da2464a77bb27febcb4fab46a34f9288f39d74833db7f61"}, + {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d2f0d0f976985f85dfb5f3d685697ef769faa6b71993b46b295cdbbd6be8cc37"}, + {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:a3dc1a4b165283bd865e8f8cb5f0c64c05001e0718ed06250d8cac9bec115b48"}, + {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:9e0f07b42d2a50c7dd2d8675d50f7343d998c64008f1da5fef888396b7f84630"}, + {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:e63e3e1e0271f374ed489ff5ee73d4b6e7c60710e1f76af5f0e1a6117cd26394"}, + {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:56bb5c98f058a41bb58eead194b4db8c05b088c93d94d5161728515bd52b052b"}, + {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7665f04d0c7f26ff8bb534e1c65068409bf4687aa2534faf7104d7182debb336"}, + {file = "propcache-0.2.0-cp310-cp310-win32.whl", hash = "sha256:7cf18abf9764746b9c8704774d8b06714bcb0a63641518a3a89c7f85cc02c2ad"}, + {file = "propcache-0.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:cfac69017ef97db2438efb854edf24f5a29fd09a536ff3a992b75990720cdc99"}, + {file = "propcache-0.2.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:63f13bf09cc3336eb04a837490b8f332e0db41da66995c9fd1ba04552e516354"}, + {file = "propcache-0.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:608cce1da6f2672a56b24a015b42db4ac612ee709f3d29f27a00c943d9e851de"}, + {file = "propcache-0.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:466c219deee4536fbc83c08d09115249db301550625c7fef1c5563a584c9bc87"}, + {file = "propcache-0.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc2db02409338bf36590aa985a461b2c96fce91f8e7e0f14c50c5fcc4f229016"}, + {file = "propcache-0.2.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a6ed8db0a556343d566a5c124ee483ae113acc9a557a807d439bcecc44e7dfbb"}, + {file = "propcache-0.2.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:91997d9cb4a325b60d4e3f20967f8eb08dfcb32b22554d5ef78e6fd1dda743a2"}, + {file = "propcache-0.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c7dde9e533c0a49d802b4f3f218fa9ad0a1ce21f2c2eb80d5216565202acab4"}, + {file = "propcache-0.2.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffcad6c564fe6b9b8916c1aefbb37a362deebf9394bd2974e9d84232e3e08504"}, + {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:97a58a28bcf63284e8b4d7b460cbee1edaab24634e82059c7b8c09e65284f178"}, + {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:945db8ee295d3af9dbdbb698cce9bbc5c59b5c3fe328bbc4387f59a8a35f998d"}, + {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:39e104da444a34830751715f45ef9fc537475ba21b7f1f5b0f4d71a3b60d7fe2"}, + {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:c5ecca8f9bab618340c8e848d340baf68bcd8ad90a8ecd7a4524a81c1764b3db"}, + {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:c436130cc779806bdf5d5fae0d848713105472b8566b75ff70048c47d3961c5b"}, + {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:191db28dc6dcd29d1a3e063c3be0b40688ed76434622c53a284e5427565bbd9b"}, + {file = "propcache-0.2.0-cp311-cp311-win32.whl", hash = "sha256:5f2564ec89058ee7c7989a7b719115bdfe2a2fb8e7a4543b8d1c0cc4cf6478c1"}, + {file = "propcache-0.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:6e2e54267980349b723cff366d1e29b138b9a60fa376664a157a342689553f71"}, + {file = "propcache-0.2.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:2ee7606193fb267be4b2e3b32714f2d58cad27217638db98a60f9efb5efeccc2"}, + {file = "propcache-0.2.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:91ee8fc02ca52e24bcb77b234f22afc03288e1dafbb1f88fe24db308910c4ac7"}, + {file = "propcache-0.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2e900bad2a8456d00a113cad8c13343f3b1f327534e3589acc2219729237a2e8"}, + {file = "propcache-0.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f52a68c21363c45297aca15561812d542f8fc683c85201df0bebe209e349f793"}, + {file = "propcache-0.2.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1e41d67757ff4fbc8ef2af99b338bfb955010444b92929e9e55a6d4dcc3c4f09"}, + {file = "propcache-0.2.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a64e32f8bd94c105cc27f42d3b658902b5bcc947ece3c8fe7bc1b05982f60e89"}, + {file = "propcache-0.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:55346705687dbd7ef0d77883ab4f6fabc48232f587925bdaf95219bae072491e"}, + {file = "propcache-0.2.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:00181262b17e517df2cd85656fcd6b4e70946fe62cd625b9d74ac9977b64d8d9"}, + {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6994984550eaf25dd7fc7bd1b700ff45c894149341725bb4edc67f0ffa94efa4"}, + {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:56295eb1e5f3aecd516d91b00cfd8bf3a13991de5a479df9e27dd569ea23959c"}, + {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:439e76255daa0f8151d3cb325f6dd4a3e93043e6403e6491813bcaaaa8733887"}, + {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f6475a1b2ecb310c98c28d271a30df74f9dd436ee46d09236a6b750a7599ce57"}, + {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:3444cdba6628accf384e349014084b1cacd866fbb88433cd9d279d90a54e0b23"}, + {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:4a9d9b4d0a9b38d1c391bb4ad24aa65f306c6f01b512e10a8a34a2dc5675d348"}, + {file = "propcache-0.2.0-cp312-cp312-win32.whl", hash = "sha256:69d3a98eebae99a420d4b28756c8ce6ea5a29291baf2dc9ff9414b42676f61d5"}, + {file = "propcache-0.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:ad9c9b99b05f163109466638bd30ada1722abb01bbb85c739c50b6dc11f92dc3"}, + {file = "propcache-0.2.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ecddc221a077a8132cf7c747d5352a15ed763b674c0448d811f408bf803d9ad7"}, + {file = "propcache-0.2.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0e53cb83fdd61cbd67202735e6a6687a7b491c8742dfc39c9e01e80354956763"}, + {file = "propcache-0.2.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:92fe151145a990c22cbccf9ae15cae8ae9eddabfc949a219c9f667877e40853d"}, + {file = "propcache-0.2.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d6a21ef516d36909931a2967621eecb256018aeb11fc48656e3257e73e2e247a"}, + {file = "propcache-0.2.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3f88a4095e913f98988f5b338c1d4d5d07dbb0b6bad19892fd447484e483ba6b"}, + {file = "propcache-0.2.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5a5b3bb545ead161be780ee85a2b54fdf7092815995661947812dde94a40f6fb"}, + {file = "propcache-0.2.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67aeb72e0f482709991aa91345a831d0b707d16b0257e8ef88a2ad246a7280bf"}, + {file = "propcache-0.2.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c997f8c44ec9b9b0bcbf2d422cc00a1d9b9c681f56efa6ca149a941e5560da2"}, + {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2a66df3d4992bc1d725b9aa803e8c5a66c010c65c741ad901e260ece77f58d2f"}, + {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:3ebbcf2a07621f29638799828b8d8668c421bfb94c6cb04269130d8de4fb7136"}, + {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:1235c01ddaa80da8235741e80815ce381c5267f96cc49b1477fdcf8c047ef325"}, + {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:3947483a381259c06921612550867b37d22e1df6d6d7e8361264b6d037595f44"}, + {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:d5bed7f9805cc29c780f3aee05de3262ee7ce1f47083cfe9f77471e9d6777e83"}, + {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e4a91d44379f45f5e540971d41e4626dacd7f01004826a18cb048e7da7e96544"}, + {file = "propcache-0.2.0-cp313-cp313-win32.whl", hash = "sha256:f902804113e032e2cdf8c71015651c97af6418363bea8d78dc0911d56c335032"}, + {file = "propcache-0.2.0-cp313-cp313-win_amd64.whl", hash = "sha256:8f188cfcc64fb1266f4684206c9de0e80f54622c3f22a910cbd200478aeae61e"}, + {file = "propcache-0.2.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:53d1bd3f979ed529f0805dd35ddaca330f80a9a6d90bc0121d2ff398f8ed8861"}, + {file = "propcache-0.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:83928404adf8fb3d26793665633ea79b7361efa0287dfbd372a7e74311d51ee6"}, + {file = "propcache-0.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:77a86c261679ea5f3896ec060be9dc8e365788248cc1e049632a1be682442063"}, + {file = "propcache-0.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:218db2a3c297a3768c11a34812e63b3ac1c3234c3a086def9c0fee50d35add1f"}, + {file = "propcache-0.2.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7735e82e3498c27bcb2d17cb65d62c14f1100b71723b68362872bca7d0913d90"}, + {file = "propcache-0.2.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:20a617c776f520c3875cf4511e0d1db847a076d720714ae35ffe0df3e440be68"}, + {file = "propcache-0.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67b69535c870670c9f9b14a75d28baa32221d06f6b6fa6f77a0a13c5a7b0a5b9"}, + {file = "propcache-0.2.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4569158070180c3855e9c0791c56be3ceeb192defa2cdf6a3f39e54319e56b89"}, + {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:db47514ffdbd91ccdc7e6f8407aac4ee94cc871b15b577c1c324236b013ddd04"}, + {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_armv7l.whl", hash = "sha256:2a60ad3e2553a74168d275a0ef35e8c0a965448ffbc3b300ab3a5bb9956c2162"}, + {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:662dd62358bdeaca0aee5761de8727cfd6861432e3bb828dc2a693aa0471a563"}, + {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:25a1f88b471b3bc911d18b935ecb7115dff3a192b6fef46f0bfaf71ff4f12418"}, + {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:f60f0ac7005b9f5a6091009b09a419ace1610e163fa5deaba5ce3484341840e7"}, + {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:74acd6e291f885678631b7ebc85d2d4aec458dd849b8c841b57ef04047833bed"}, + {file = "propcache-0.2.0-cp38-cp38-win32.whl", hash = "sha256:d9b6ddac6408194e934002a69bcaadbc88c10b5f38fb9307779d1c629181815d"}, + {file = "propcache-0.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:676135dcf3262c9c5081cc8f19ad55c8a64e3f7282a21266d05544450bffc3a5"}, + {file = "propcache-0.2.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:25c8d773a62ce0451b020c7b29a35cfbc05de8b291163a7a0f3b7904f27253e6"}, + {file = "propcache-0.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:375a12d7556d462dc64d70475a9ee5982465fbb3d2b364f16b86ba9135793638"}, + {file = "propcache-0.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1ec43d76b9677637a89d6ab86e1fef70d739217fefa208c65352ecf0282be957"}, + {file = "propcache-0.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f45eec587dafd4b2d41ac189c2156461ebd0c1082d2fe7013571598abb8505d1"}, + {file = "propcache-0.2.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bc092ba439d91df90aea38168e11f75c655880c12782facf5cf9c00f3d42b562"}, + {file = "propcache-0.2.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fa1076244f54bb76e65e22cb6910365779d5c3d71d1f18b275f1dfc7b0d71b4d"}, + {file = "propcache-0.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:682a7c79a2fbf40f5dbb1eb6bfe2cd865376deeac65acf9beb607505dced9e12"}, + {file = "propcache-0.2.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8e40876731f99b6f3c897b66b803c9e1c07a989b366c6b5b475fafd1f7ba3fb8"}, + {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:363ea8cd3c5cb6679f1c2f5f1f9669587361c062e4899fce56758efa928728f8"}, + {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:140fbf08ab3588b3468932974a9331aff43c0ab8a2ec2c608b6d7d1756dbb6cb"}, + {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:e70fac33e8b4ac63dfc4c956fd7d85a0b1139adcfc0d964ce288b7c527537fea"}, + {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:b33d7a286c0dc1a15f5fc864cc48ae92a846df287ceac2dd499926c3801054a6"}, + {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:f6d5749fdd33d90e34c2efb174c7e236829147a2713334d708746e94c4bde40d"}, + {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:22aa8f2272d81d9317ff5756bb108021a056805ce63dd3630e27d042c8092798"}, + {file = "propcache-0.2.0-cp39-cp39-win32.whl", hash = "sha256:73e4b40ea0eda421b115248d7e79b59214411109a5bc47d0d48e4c73e3b8fcf9"}, + {file = "propcache-0.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:9517d5e9e0731957468c29dbfd0f976736a0e55afaea843726e887f36fe017df"}, + {file = "propcache-0.2.0-py3-none-any.whl", hash = "sha256:2ccc28197af5313706511fab3a8b66dcd6da067a1331372c82ea1cb74285e036"}, + {file = "propcache-0.2.0.tar.gz", hash = "sha256:df81779732feb9d01e5d513fad0122efb3d53bbc75f61b2a4f29a020bc985e70"}, +] + [[package]] name = "psycopg2-binary" -version = "2.9.9" +version = "2.9.10" description = "psycopg2 - Python-PostgreSQL Database Adapter" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "psycopg2-binary-2.9.9.tar.gz", hash = "sha256:7f01846810177d829c7692f1f5ada8096762d9172af1b1a28d4ab5b77c923c1c"}, - {file = "psycopg2_binary-2.9.9-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c2470da5418b76232f02a2fcd2229537bb2d5a7096674ce61859c3229f2eb202"}, - {file = "psycopg2_binary-2.9.9-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c6af2a6d4b7ee9615cbb162b0738f6e1fd1f5c3eda7e5da17861eacf4c717ea7"}, - {file = "psycopg2_binary-2.9.9-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:75723c3c0fbbf34350b46a3199eb50638ab22a0228f93fb472ef4d9becc2382b"}, - {file = "psycopg2_binary-2.9.9-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:83791a65b51ad6ee6cf0845634859d69a038ea9b03d7b26e703f94c7e93dbcf9"}, - {file = "psycopg2_binary-2.9.9-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0ef4854e82c09e84cc63084a9e4ccd6d9b154f1dbdd283efb92ecd0b5e2b8c84"}, - {file = "psycopg2_binary-2.9.9-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ed1184ab8f113e8d660ce49a56390ca181f2981066acc27cf637d5c1e10ce46e"}, - {file = "psycopg2_binary-2.9.9-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d2997c458c690ec2bc6b0b7ecbafd02b029b7b4283078d3b32a852a7ce3ddd98"}, - {file = "psycopg2_binary-2.9.9-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:b58b4710c7f4161b5e9dcbe73bb7c62d65670a87df7bcce9e1faaad43e715245"}, - {file = "psycopg2_binary-2.9.9-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:0c009475ee389757e6e34611d75f6e4f05f0cf5ebb76c6037508318e1a1e0d7e"}, - {file = "psycopg2_binary-2.9.9-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8dbf6d1bc73f1d04ec1734bae3b4fb0ee3cb2a493d35ede9badbeb901fb40f6f"}, - {file = "psycopg2_binary-2.9.9-cp310-cp310-win32.whl", hash = "sha256:3f78fd71c4f43a13d342be74ebbc0666fe1f555b8837eb113cb7416856c79682"}, - {file = "psycopg2_binary-2.9.9-cp310-cp310-win_amd64.whl", hash = "sha256:876801744b0dee379e4e3c38b76fc89f88834bb15bf92ee07d94acd06ec890a0"}, - {file = "psycopg2_binary-2.9.9-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ee825e70b1a209475622f7f7b776785bd68f34af6e7a46e2e42f27b659b5bc26"}, - {file = "psycopg2_binary-2.9.9-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1ea665f8ce695bcc37a90ee52de7a7980be5161375d42a0b6c6abedbf0d81f0f"}, - {file = "psycopg2_binary-2.9.9-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:143072318f793f53819048fdfe30c321890af0c3ec7cb1dfc9cc87aa88241de2"}, - {file = "psycopg2_binary-2.9.9-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c332c8d69fb64979ebf76613c66b985414927a40f8defa16cf1bc028b7b0a7b0"}, - {file = "psycopg2_binary-2.9.9-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7fc5a5acafb7d6ccca13bfa8c90f8c51f13d8fb87d95656d3950f0158d3ce53"}, - {file = "psycopg2_binary-2.9.9-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:977646e05232579d2e7b9c59e21dbe5261f403a88417f6a6512e70d3f8a046be"}, - {file = "psycopg2_binary-2.9.9-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b6356793b84728d9d50ead16ab43c187673831e9d4019013f1402c41b1db9b27"}, - {file = "psycopg2_binary-2.9.9-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:bc7bb56d04601d443f24094e9e31ae6deec9ccb23581f75343feebaf30423359"}, - {file = "psycopg2_binary-2.9.9-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:77853062a2c45be16fd6b8d6de2a99278ee1d985a7bd8b103e97e41c034006d2"}, - {file = "psycopg2_binary-2.9.9-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:78151aa3ec21dccd5cdef6c74c3e73386dcdfaf19bced944169697d7ac7482fc"}, - {file = "psycopg2_binary-2.9.9-cp311-cp311-win32.whl", hash = "sha256:dc4926288b2a3e9fd7b50dc6a1909a13bbdadfc67d93f3374d984e56f885579d"}, - {file = "psycopg2_binary-2.9.9-cp311-cp311-win_amd64.whl", hash = "sha256:b76bedd166805480ab069612119ea636f5ab8f8771e640ae103e05a4aae3e417"}, - {file = "psycopg2_binary-2.9.9-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:8532fd6e6e2dc57bcb3bc90b079c60de896d2128c5d9d6f24a63875a95a088cf"}, - {file = "psycopg2_binary-2.9.9-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f8544b092a29a6ddd72f3556a9fcf249ec412e10ad28be6a0c0d948924f2212"}, - {file = "psycopg2_binary-2.9.9-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2d423c8d8a3c82d08fe8af900ad5b613ce3632a1249fd6a223941d0735fce493"}, - {file = "psycopg2_binary-2.9.9-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2e5afae772c00980525f6d6ecf7cbca55676296b580c0e6abb407f15f3706996"}, - {file = "psycopg2_binary-2.9.9-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e6f98446430fdf41bd36d4faa6cb409f5140c1c2cf58ce0bbdaf16af7d3f119"}, - {file = "psycopg2_binary-2.9.9-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c77e3d1862452565875eb31bdb45ac62502feabbd53429fdc39a1cc341d681ba"}, - {file = "psycopg2_binary-2.9.9-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:cb16c65dcb648d0a43a2521f2f0a2300f40639f6f8c1ecbc662141e4e3e1ee07"}, - {file = "psycopg2_binary-2.9.9-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:911dda9c487075abd54e644ccdf5e5c16773470a6a5d3826fda76699410066fb"}, - {file = "psycopg2_binary-2.9.9-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:57fede879f08d23c85140a360c6a77709113efd1c993923c59fde17aa27599fe"}, - {file = "psycopg2_binary-2.9.9-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:2293b001e319ab0d869d660a704942c9e2cce19745262a8aba2115ef41a0a42a"}, - {file = "psycopg2_binary-2.9.9-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:03ef7df18daf2c4c07e2695e8cfd5ee7f748a1d54d802330985a78d2a5a6dca9"}, - {file = "psycopg2_binary-2.9.9-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a602ea5aff39bb9fac6308e9c9d82b9a35c2bf288e184a816002c9fae930b77"}, - {file = "psycopg2_binary-2.9.9-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8359bf4791968c5a78c56103702000105501adb557f3cf772b2c207284273984"}, - {file = "psycopg2_binary-2.9.9-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:275ff571376626195ab95a746e6a04c7df8ea34638b99fc11160de91f2fef503"}, - {file = "psycopg2_binary-2.9.9-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:f9b5571d33660d5009a8b3c25dc1db560206e2d2f89d3df1cb32d72c0d117d52"}, - {file = "psycopg2_binary-2.9.9-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:420f9bbf47a02616e8554e825208cb947969451978dceb77f95ad09c37791dae"}, - {file = "psycopg2_binary-2.9.9-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:4154ad09dac630a0f13f37b583eae260c6aa885d67dfbccb5b02c33f31a6d420"}, - {file = "psycopg2_binary-2.9.9-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:a148c5d507bb9b4f2030a2025c545fccb0e1ef317393eaba42e7eabd28eb6041"}, - {file = "psycopg2_binary-2.9.9-cp37-cp37m-win32.whl", hash = "sha256:68fc1f1ba168724771e38bee37d940d2865cb0f562380a1fb1ffb428b75cb692"}, - {file = "psycopg2_binary-2.9.9-cp37-cp37m-win_amd64.whl", hash = "sha256:281309265596e388ef483250db3640e5f414168c5a67e9c665cafce9492eda2f"}, - {file = "psycopg2_binary-2.9.9-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:60989127da422b74a04345096c10d416c2b41bd7bf2a380eb541059e4e999980"}, - {file = "psycopg2_binary-2.9.9-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:246b123cc54bb5361588acc54218c8c9fb73068bf227a4a531d8ed56fa3ca7d6"}, - {file = "psycopg2_binary-2.9.9-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:34eccd14566f8fe14b2b95bb13b11572f7c7d5c36da61caf414d23b91fcc5d94"}, - {file = "psycopg2_binary-2.9.9-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:18d0ef97766055fec15b5de2c06dd8e7654705ce3e5e5eed3b6651a1d2a9a152"}, - {file = "psycopg2_binary-2.9.9-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d3f82c171b4ccd83bbaf35aa05e44e690113bd4f3b7b6cc54d2219b132f3ae55"}, - {file = "psycopg2_binary-2.9.9-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ead20f7913a9c1e894aebe47cccf9dc834e1618b7aa96155d2091a626e59c972"}, - {file = "psycopg2_binary-2.9.9-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:ca49a8119c6cbd77375ae303b0cfd8c11f011abbbd64601167ecca18a87e7cdd"}, - {file = "psycopg2_binary-2.9.9-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:323ba25b92454adb36fa425dc5cf6f8f19f78948cbad2e7bc6cdf7b0d7982e59"}, - {file = "psycopg2_binary-2.9.9-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:1236ed0952fbd919c100bc839eaa4a39ebc397ed1c08a97fc45fee2a595aa1b3"}, - {file = "psycopg2_binary-2.9.9-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:729177eaf0aefca0994ce4cffe96ad3c75e377c7b6f4efa59ebf003b6d398716"}, - {file = "psycopg2_binary-2.9.9-cp38-cp38-win32.whl", hash = "sha256:804d99b24ad523a1fe18cc707bf741670332f7c7412e9d49cb5eab67e886b9b5"}, - {file = "psycopg2_binary-2.9.9-cp38-cp38-win_amd64.whl", hash = "sha256:a6cdcc3ede532f4a4b96000b6362099591ab4a3e913d70bcbac2b56c872446f7"}, - {file = "psycopg2_binary-2.9.9-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:72dffbd8b4194858d0941062a9766f8297e8868e1dd07a7b36212aaa90f49472"}, - {file = "psycopg2_binary-2.9.9-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:30dcc86377618a4c8f3b72418df92e77be4254d8f89f14b8e8f57d6d43603c0f"}, - {file = "psycopg2_binary-2.9.9-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:31a34c508c003a4347d389a9e6fcc2307cc2150eb516462a7a17512130de109e"}, - {file = "psycopg2_binary-2.9.9-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:15208be1c50b99203fe88d15695f22a5bed95ab3f84354c494bcb1d08557df67"}, - {file = "psycopg2_binary-2.9.9-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1873aade94b74715be2246321c8650cabf5a0d098a95bab81145ffffa4c13876"}, - {file = "psycopg2_binary-2.9.9-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a58c98a7e9c021f357348867f537017057c2ed7f77337fd914d0bedb35dace7"}, - {file = "psycopg2_binary-2.9.9-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4686818798f9194d03c9129a4d9a702d9e113a89cb03bffe08c6cf799e053291"}, - {file = "psycopg2_binary-2.9.9-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:ebdc36bea43063116f0486869652cb2ed7032dbc59fbcb4445c4862b5c1ecf7f"}, - {file = "psycopg2_binary-2.9.9-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:ca08decd2697fdea0aea364b370b1249d47336aec935f87b8bbfd7da5b2ee9c1"}, - {file = "psycopg2_binary-2.9.9-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ac05fb791acf5e1a3e39402641827780fe44d27e72567a000412c648a85ba860"}, - {file = "psycopg2_binary-2.9.9-cp39-cp39-win32.whl", hash = "sha256:9dba73be7305b399924709b91682299794887cbbd88e38226ed9f6712eabee90"}, - {file = "psycopg2_binary-2.9.9-cp39-cp39-win_amd64.whl", hash = "sha256:f7ae5d65ccfbebdfa761585228eb4d0df3a8b15cfb53bd953e713e09fbb12957"}, + {file = "psycopg2-binary-2.9.10.tar.gz", hash = "sha256:4b3df0e6990aa98acda57d983942eff13d824135fe2250e6522edaa782a06de2"}, + {file = "psycopg2_binary-2.9.10-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:0ea8e3d0ae83564f2fc554955d327fa081d065c8ca5cc6d2abb643e2c9c1200f"}, + {file = "psycopg2_binary-2.9.10-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:3e9c76f0ac6f92ecfc79516a8034a544926430f7b080ec5a0537bca389ee0906"}, + {file = "psycopg2_binary-2.9.10-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2ad26b467a405c798aaa1458ba09d7e2b6e5f96b1ce0ac15d82fd9f95dc38a92"}, + {file = "psycopg2_binary-2.9.10-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:270934a475a0e4b6925b5f804e3809dd5f90f8613621d062848dd82f9cd62007"}, + {file = "psycopg2_binary-2.9.10-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:48b338f08d93e7be4ab2b5f1dbe69dc5e9ef07170fe1f86514422076d9c010d0"}, + {file = "psycopg2_binary-2.9.10-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f4152f8f76d2023aac16285576a9ecd2b11a9895373a1f10fd9db54b3ff06b4"}, + {file = "psycopg2_binary-2.9.10-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:32581b3020c72d7a421009ee1c6bf4a131ef5f0a968fab2e2de0c9d2bb4577f1"}, + {file = "psycopg2_binary-2.9.10-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:2ce3e21dc3437b1d960521eca599d57408a695a0d3c26797ea0f72e834c7ffe5"}, + {file = "psycopg2_binary-2.9.10-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:e984839e75e0b60cfe75e351db53d6db750b00de45644c5d1f7ee5d1f34a1ce5"}, + {file = "psycopg2_binary-2.9.10-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3c4745a90b78e51d9ba06e2088a2fe0c693ae19cc8cb051ccda44e8df8a6eb53"}, + {file = "psycopg2_binary-2.9.10-cp310-cp310-win32.whl", hash = "sha256:e5720a5d25e3b99cd0dc5c8a440570469ff82659bb09431c1439b92caf184d3b"}, + {file = "psycopg2_binary-2.9.10-cp310-cp310-win_amd64.whl", hash = "sha256:3c18f74eb4386bf35e92ab2354a12c17e5eb4d9798e4c0ad3a00783eae7cd9f1"}, + {file = "psycopg2_binary-2.9.10-cp311-cp311-macosx_12_0_x86_64.whl", hash = "sha256:04392983d0bb89a8717772a193cfaac58871321e3ec69514e1c4e0d4957b5aff"}, + {file = "psycopg2_binary-2.9.10-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:1a6784f0ce3fec4edc64e985865c17778514325074adf5ad8f80636cd029ef7c"}, + {file = "psycopg2_binary-2.9.10-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b5f86c56eeb91dc3135b3fd8a95dc7ae14c538a2f3ad77a19645cf55bab1799c"}, + {file = "psycopg2_binary-2.9.10-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2b3d2491d4d78b6b14f76881905c7a8a8abcf974aad4a8a0b065273a0ed7a2cb"}, + {file = "psycopg2_binary-2.9.10-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2286791ececda3a723d1910441c793be44625d86d1a4e79942751197f4d30341"}, + {file = "psycopg2_binary-2.9.10-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:512d29bb12608891e349af6a0cccedce51677725a921c07dba6342beaf576f9a"}, + {file = "psycopg2_binary-2.9.10-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:5a507320c58903967ef7384355a4da7ff3f28132d679aeb23572753cbf2ec10b"}, + {file = "psycopg2_binary-2.9.10-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:6d4fa1079cab9018f4d0bd2db307beaa612b0d13ba73b5c6304b9fe2fb441ff7"}, + {file = "psycopg2_binary-2.9.10-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:851485a42dbb0bdc1edcdabdb8557c09c9655dfa2ca0460ff210522e073e319e"}, + {file = "psycopg2_binary-2.9.10-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:35958ec9e46432d9076286dda67942ed6d968b9c3a6a2fd62b48939d1d78bf68"}, + {file = "psycopg2_binary-2.9.10-cp311-cp311-win32.whl", hash = "sha256:ecced182e935529727401b24d76634a357c71c9275b356efafd8a2a91ec07392"}, + {file = "psycopg2_binary-2.9.10-cp311-cp311-win_amd64.whl", hash = "sha256:ee0e8c683a7ff25d23b55b11161c2663d4b099770f6085ff0a20d4505778d6b4"}, + {file = "psycopg2_binary-2.9.10-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:880845dfe1f85d9d5f7c412efea7a08946a46894537e4e5d091732eb1d34d9a0"}, + {file = "psycopg2_binary-2.9.10-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:9440fa522a79356aaa482aa4ba500b65f28e5d0e63b801abf6aa152a29bd842a"}, + {file = "psycopg2_binary-2.9.10-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e3923c1d9870c49a2d44f795df0c889a22380d36ef92440ff618ec315757e539"}, + {file = "psycopg2_binary-2.9.10-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7b2c956c028ea5de47ff3a8d6b3cc3330ab45cf0b7c3da35a2d6ff8420896526"}, + {file = "psycopg2_binary-2.9.10-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f758ed67cab30b9a8d2833609513ce4d3bd027641673d4ebc9c067e4d208eec1"}, + {file = "psycopg2_binary-2.9.10-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8cd9b4f2cfab88ed4a9106192de509464b75a906462fb846b936eabe45c2063e"}, + {file = "psycopg2_binary-2.9.10-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6dc08420625b5a20b53551c50deae6e231e6371194fa0651dbe0fb206452ae1f"}, + {file = "psycopg2_binary-2.9.10-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:d7cd730dfa7c36dbe8724426bf5612798734bff2d3c3857f36f2733f5bfc7c00"}, + {file = "psycopg2_binary-2.9.10-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:155e69561d54d02b3c3209545fb08938e27889ff5a10c19de8d23eb5a41be8a5"}, + {file = "psycopg2_binary-2.9.10-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c3cc28a6fd5a4a26224007712e79b81dbaee2ffb90ff406256158ec4d7b52b47"}, + {file = "psycopg2_binary-2.9.10-cp312-cp312-win32.whl", hash = "sha256:ec8a77f521a17506a24a5f626cb2aee7850f9b69a0afe704586f63a464f3cd64"}, + {file = "psycopg2_binary-2.9.10-cp312-cp312-win_amd64.whl", hash = "sha256:18c5ee682b9c6dd3696dad6e54cc7ff3a1a9020df6a5c0f861ef8bfd338c3ca0"}, + {file = "psycopg2_binary-2.9.10-cp313-cp313-macosx_12_0_x86_64.whl", hash = "sha256:26540d4a9a4e2b096f1ff9cce51253d0504dca5a85872c7f7be23be5a53eb18d"}, + {file = "psycopg2_binary-2.9.10-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:e217ce4d37667df0bc1c397fdcd8de5e81018ef305aed9415c3b093faaeb10fb"}, + {file = "psycopg2_binary-2.9.10-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:245159e7ab20a71d989da00f280ca57da7641fa2cdcf71749c193cea540a74f7"}, + {file = "psycopg2_binary-2.9.10-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c4ded1a24b20021ebe677b7b08ad10bf09aac197d6943bfe6fec70ac4e4690d"}, + {file = "psycopg2_binary-2.9.10-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3abb691ff9e57d4a93355f60d4f4c1dd2d68326c968e7db17ea96df3c023ef73"}, + {file = "psycopg2_binary-2.9.10-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8608c078134f0b3cbd9f89b34bd60a943b23fd33cc5f065e8d5f840061bd0673"}, + {file = "psycopg2_binary-2.9.10-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:230eeae2d71594103cd5b93fd29d1ace6420d0b86f4778739cb1a5a32f607d1f"}, + {file = "psycopg2_binary-2.9.10-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:bb89f0a835bcfc1d42ccd5f41f04870c1b936d8507c6df12b7737febc40f0909"}, + {file = "psycopg2_binary-2.9.10-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:f0c2d907a1e102526dd2986df638343388b94c33860ff3bbe1384130828714b1"}, + {file = "psycopg2_binary-2.9.10-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f8157bed2f51db683f31306aa497311b560f2265998122abe1dce6428bd86567"}, + {file = "psycopg2_binary-2.9.10-cp38-cp38-macosx_12_0_x86_64.whl", hash = "sha256:eb09aa7f9cecb45027683bb55aebaaf45a0df8bf6de68801a6afdc7947bb09d4"}, + {file = "psycopg2_binary-2.9.10-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b73d6d7f0ccdad7bc43e6d34273f70d587ef62f824d7261c4ae9b8b1b6af90e8"}, + {file = "psycopg2_binary-2.9.10-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ce5ab4bf46a211a8e924d307c1b1fcda82368586a19d0a24f8ae166f5c784864"}, + {file = "psycopg2_binary-2.9.10-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:056470c3dc57904bbf63d6f534988bafc4e970ffd50f6271fc4ee7daad9498a5"}, + {file = "psycopg2_binary-2.9.10-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:73aa0e31fa4bb82578f3a6c74a73c273367727de397a7a0f07bd83cbea696baa"}, + {file = "psycopg2_binary-2.9.10-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:8de718c0e1c4b982a54b41779667242bc630b2197948405b7bd8ce16bcecac92"}, + {file = "psycopg2_binary-2.9.10-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:5c370b1e4975df846b0277b4deba86419ca77dbc25047f535b0bb03d1a544d44"}, + {file = "psycopg2_binary-2.9.10-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:ffe8ed017e4ed70f68b7b371d84b7d4a790368db9203dfc2d222febd3a9c8863"}, + {file = "psycopg2_binary-2.9.10-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:8aecc5e80c63f7459a1a2ab2c64df952051df196294d9f739933a9f6687e86b3"}, + {file = "psycopg2_binary-2.9.10-cp39-cp39-macosx_12_0_x86_64.whl", hash = "sha256:7a813c8bdbaaaab1f078014b9b0b13f5de757e2b5d9be6403639b298a04d218b"}, + {file = "psycopg2_binary-2.9.10-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d00924255d7fc916ef66e4bf22f354a940c67179ad3fd7067d7a0a9c84d2fbfc"}, + {file = "psycopg2_binary-2.9.10-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7559bce4b505762d737172556a4e6ea8a9998ecac1e39b5233465093e8cee697"}, + {file = "psycopg2_binary-2.9.10-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e8b58f0a96e7a1e341fc894f62c1177a7c83febebb5ff9123b579418fdc8a481"}, + {file = "psycopg2_binary-2.9.10-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b269105e59ac96aba877c1707c600ae55711d9dcd3fc4b5012e4af68e30c648"}, + {file = "psycopg2_binary-2.9.10-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:79625966e176dc97ddabc142351e0409e28acf4660b88d1cf6adb876d20c490d"}, + {file = "psycopg2_binary-2.9.10-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:8aabf1c1a04584c168984ac678a668094d831f152859d06e055288fa515e4d30"}, + {file = "psycopg2_binary-2.9.10-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:19721ac03892001ee8fdd11507e6a2e01f4e37014def96379411ca99d78aeb2c"}, + {file = "psycopg2_binary-2.9.10-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7f5d859928e635fa3ce3477704acee0f667b3a3d3e4bb109f2b18d4005f38287"}, + {file = "psycopg2_binary-2.9.10-cp39-cp39-win32.whl", hash = "sha256:3216ccf953b3f267691c90c6fe742e45d890d8272326b4a8b20850a03d05b7b8"}, + {file = "psycopg2_binary-2.9.10-cp39-cp39-win_amd64.whl", hash = "sha256:30e34c4e97964805f715206c7b789d54a78b70f3ff19fbe590104b71c45600e5"}, ] [[package]] name = "pydantic" -version = "2.8.2" +version = "2.9.2" description = "Data validation using Python type hints" optional = false python-versions = ">=3.8" files = [ - {file = "pydantic-2.8.2-py3-none-any.whl", hash = "sha256:73ee9fddd406dc318b885c7a2eab8a6472b68b8fb5ba8150949fc3db939f23c8"}, - {file = "pydantic-2.8.2.tar.gz", hash = "sha256:6f62c13d067b0755ad1c21a34bdd06c0c12625a22b0fc09c6b149816604f7c2a"}, + {file = "pydantic-2.9.2-py3-none-any.whl", hash = "sha256:f048cec7b26778210e28a0459867920654d48e5e62db0958433636cde4254f12"}, + {file = "pydantic-2.9.2.tar.gz", hash = "sha256:d155cef71265d1e9807ed1c32b4c8deec042a44a50a4188b25ac67ecd81a9c0f"}, ] [package.dependencies] -annotated-types = ">=0.4.0" -pydantic-core = "2.20.1" +annotated-types = ">=0.6.0" +pydantic-core = "2.23.4" typing-extensions = [ {version = ">=4.12.2", markers = "python_version >= \"3.13\""}, {version = ">=4.6.1", markers = "python_version < \"3.13\""}, @@ -1440,103 +1612,104 @@ typing-extensions = [ [package.extras] email = ["email-validator (>=2.0.0)"] +timezone = ["tzdata"] [[package]] name = "pydantic-core" -version = "2.20.1" +version = "2.23.4" description = "Core functionality for Pydantic validation and serialization" optional = false python-versions = ">=3.8" files = [ - {file = "pydantic_core-2.20.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:3acae97ffd19bf091c72df4d726d552c473f3576409b2a7ca36b2f535ffff4a3"}, - {file = "pydantic_core-2.20.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:41f4c96227a67a013e7de5ff8f20fb496ce573893b7f4f2707d065907bffdbd6"}, - {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f239eb799a2081495ea659d8d4a43a8f42cd1fe9ff2e7e436295c38a10c286a"}, - {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:53e431da3fc53360db73eedf6f7124d1076e1b4ee4276b36fb25514544ceb4a3"}, - {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f1f62b2413c3a0e846c3b838b2ecd6c7a19ec6793b2a522745b0869e37ab5bc1"}, - {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5d41e6daee2813ecceea8eda38062d69e280b39df793f5a942fa515b8ed67953"}, - {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d482efec8b7dc6bfaedc0f166b2ce349df0011f5d2f1f25537ced4cfc34fd98"}, - {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e93e1a4b4b33daed65d781a57a522ff153dcf748dee70b40c7258c5861e1768a"}, - {file = "pydantic_core-2.20.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e7c4ea22b6739b162c9ecaaa41d718dfad48a244909fe7ef4b54c0b530effc5a"}, - {file = "pydantic_core-2.20.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4f2790949cf385d985a31984907fecb3896999329103df4e4983a4a41e13e840"}, - {file = "pydantic_core-2.20.1-cp310-none-win32.whl", hash = "sha256:5e999ba8dd90e93d57410c5e67ebb67ffcaadcea0ad973240fdfd3a135506250"}, - {file = "pydantic_core-2.20.1-cp310-none-win_amd64.whl", hash = "sha256:512ecfbefef6dac7bc5eaaf46177b2de58cdf7acac8793fe033b24ece0b9566c"}, - {file = "pydantic_core-2.20.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:d2a8fa9d6d6f891f3deec72f5cc668e6f66b188ab14bb1ab52422fe8e644f312"}, - {file = "pydantic_core-2.20.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:175873691124f3d0da55aeea1d90660a6ea7a3cfea137c38afa0a5ffabe37b88"}, - {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:37eee5b638f0e0dcd18d21f59b679686bbd18917b87db0193ae36f9c23c355fc"}, - {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:25e9185e2d06c16ee438ed39bf62935ec436474a6ac4f9358524220f1b236e43"}, - {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:150906b40ff188a3260cbee25380e7494ee85048584998c1e66df0c7a11c17a6"}, - {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ad4aeb3e9a97286573c03df758fc7627aecdd02f1da04516a86dc159bf70121"}, - {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d3f3ed29cd9f978c604708511a1f9c2fdcb6c38b9aae36a51905b8811ee5cbf1"}, - {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b0dae11d8f5ded51699c74d9548dcc5938e0804cc8298ec0aa0da95c21fff57b"}, - {file = "pydantic_core-2.20.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:faa6b09ee09433b87992fb5a2859efd1c264ddc37280d2dd5db502126d0e7f27"}, - {file = "pydantic_core-2.20.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9dc1b507c12eb0481d071f3c1808f0529ad41dc415d0ca11f7ebfc666e66a18b"}, - {file = "pydantic_core-2.20.1-cp311-none-win32.whl", hash = "sha256:fa2fddcb7107e0d1808086ca306dcade7df60a13a6c347a7acf1ec139aa6789a"}, - {file = "pydantic_core-2.20.1-cp311-none-win_amd64.whl", hash = "sha256:40a783fb7ee353c50bd3853e626f15677ea527ae556429453685ae32280c19c2"}, - {file = "pydantic_core-2.20.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:595ba5be69b35777474fa07f80fc260ea71255656191adb22a8c53aba4479231"}, - {file = "pydantic_core-2.20.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a4f55095ad087474999ee28d3398bae183a66be4823f753cd7d67dd0153427c9"}, - {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f9aa05d09ecf4c75157197f27cdc9cfaeb7c5f15021c6373932bf3e124af029f"}, - {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e97fdf088d4b31ff4ba35db26d9cc472ac7ef4a2ff2badeabf8d727b3377fc52"}, - {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bc633a9fe1eb87e250b5c57d389cf28998e4292336926b0b6cdaee353f89a237"}, - {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d573faf8eb7e6b1cbbcb4f5b247c60ca8be39fe2c674495df0eb4318303137fe"}, - {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26dc97754b57d2fd00ac2b24dfa341abffc380b823211994c4efac7f13b9e90e"}, - {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:33499e85e739a4b60c9dac710c20a08dc73cb3240c9a0e22325e671b27b70d24"}, - {file = "pydantic_core-2.20.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:bebb4d6715c814597f85297c332297c6ce81e29436125ca59d1159b07f423eb1"}, - {file = "pydantic_core-2.20.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:516d9227919612425c8ef1c9b869bbbee249bc91912c8aaffb66116c0b447ebd"}, - {file = "pydantic_core-2.20.1-cp312-none-win32.whl", hash = "sha256:469f29f9093c9d834432034d33f5fe45699e664f12a13bf38c04967ce233d688"}, - {file = "pydantic_core-2.20.1-cp312-none-win_amd64.whl", hash = "sha256:035ede2e16da7281041f0e626459bcae33ed998cca6a0a007a5ebb73414ac72d"}, - {file = "pydantic_core-2.20.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:0827505a5c87e8aa285dc31e9ec7f4a17c81a813d45f70b1d9164e03a813a686"}, - {file = "pydantic_core-2.20.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:19c0fa39fa154e7e0b7f82f88ef85faa2a4c23cc65aae2f5aea625e3c13c735a"}, - {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa223cd1e36b642092c326d694d8bf59b71ddddc94cdb752bbbb1c5c91d833b"}, - {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c336a6d235522a62fef872c6295a42ecb0c4e1d0f1a3e500fe949415761b8a19"}, - {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7eb6a0587eded33aeefea9f916899d42b1799b7b14b8f8ff2753c0ac1741edac"}, - {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:70c8daf4faca8da5a6d655f9af86faf6ec2e1768f4b8b9d0226c02f3d6209703"}, - {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e9fa4c9bf273ca41f940bceb86922a7667cd5bf90e95dbb157cbb8441008482c"}, - {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:11b71d67b4725e7e2a9f6e9c0ac1239bbc0c48cce3dc59f98635efc57d6dac83"}, - {file = "pydantic_core-2.20.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:270755f15174fb983890c49881e93f8f1b80f0b5e3a3cc1394a255706cabd203"}, - {file = "pydantic_core-2.20.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:c81131869240e3e568916ef4c307f8b99583efaa60a8112ef27a366eefba8ef0"}, - {file = "pydantic_core-2.20.1-cp313-none-win32.whl", hash = "sha256:b91ced227c41aa29c672814f50dbb05ec93536abf8f43cd14ec9521ea09afe4e"}, - {file = "pydantic_core-2.20.1-cp313-none-win_amd64.whl", hash = "sha256:65db0f2eefcaad1a3950f498aabb4875c8890438bc80b19362cf633b87a8ab20"}, - {file = "pydantic_core-2.20.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:4745f4ac52cc6686390c40eaa01d48b18997cb130833154801a442323cc78f91"}, - {file = "pydantic_core-2.20.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a8ad4c766d3f33ba8fd692f9aa297c9058970530a32c728a2c4bfd2616d3358b"}, - {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41e81317dd6a0127cabce83c0c9c3fbecceae981c8391e6f1dec88a77c8a569a"}, - {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:04024d270cf63f586ad41fff13fde4311c4fc13ea74676962c876d9577bcc78f"}, - {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eaad4ff2de1c3823fddf82f41121bdf453d922e9a238642b1dedb33c4e4f98ad"}, - {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:26ab812fa0c845df815e506be30337e2df27e88399b985d0bb4e3ecfe72df31c"}, - {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c5ebac750d9d5f2706654c638c041635c385596caf68f81342011ddfa1e5598"}, - {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2aafc5a503855ea5885559eae883978c9b6d8c8993d67766ee73d82e841300dd"}, - {file = "pydantic_core-2.20.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:4868f6bd7c9d98904b748a2653031fc9c2f85b6237009d475b1008bfaeb0a5aa"}, - {file = "pydantic_core-2.20.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:aa2f457b4af386254372dfa78a2eda2563680d982422641a85f271c859df1987"}, - {file = "pydantic_core-2.20.1-cp38-none-win32.whl", hash = "sha256:225b67a1f6d602de0ce7f6c1c3ae89a4aa25d3de9be857999e9124f15dab486a"}, - {file = "pydantic_core-2.20.1-cp38-none-win_amd64.whl", hash = "sha256:6b507132dcfc0dea440cce23ee2182c0ce7aba7054576efc65634f080dbe9434"}, - {file = "pydantic_core-2.20.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:b03f7941783b4c4a26051846dea594628b38f6940a2fdc0df00b221aed39314c"}, - {file = "pydantic_core-2.20.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1eedfeb6089ed3fad42e81a67755846ad4dcc14d73698c120a82e4ccf0f1f9f6"}, - {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:635fee4e041ab9c479e31edda27fcf966ea9614fff1317e280d99eb3e5ab6fe2"}, - {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:77bf3ac639c1ff567ae3b47f8d4cc3dc20f9966a2a6dd2311dcc055d3d04fb8a"}, - {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ed1b0132f24beeec5a78b67d9388656d03e6a7c837394f99257e2d55b461611"}, - {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c6514f963b023aeee506678a1cf821fe31159b925c4b76fe2afa94cc70b3222b"}, - {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10d4204d8ca33146e761c79f83cc861df20e7ae9f6487ca290a97702daf56006"}, - {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2d036c7187b9422ae5b262badb87a20a49eb6c5238b2004e96d4da1231badef1"}, - {file = "pydantic_core-2.20.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9ebfef07dbe1d93efb94b4700f2d278494e9162565a54f124c404a5656d7ff09"}, - {file = "pydantic_core-2.20.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6b9d9bb600328a1ce523ab4f454859e9d439150abb0906c5a1983c146580ebab"}, - {file = "pydantic_core-2.20.1-cp39-none-win32.whl", hash = "sha256:784c1214cb6dd1e3b15dd8b91b9a53852aed16671cc3fbe4786f4f1db07089e2"}, - {file = "pydantic_core-2.20.1-cp39-none-win_amd64.whl", hash = "sha256:d2fe69c5434391727efa54b47a1e7986bb0186e72a41b203df8f5b0a19a4f669"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a45f84b09ac9c3d35dfcf6a27fd0634d30d183205230a0ebe8373a0e8cfa0906"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:d02a72df14dfdbaf228424573a07af10637bd490f0901cee872c4f434a735b94"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d2b27e6af28f07e2f195552b37d7d66b150adbaa39a6d327766ffd695799780f"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:084659fac3c83fd674596612aeff6041a18402f1e1bc19ca39e417d554468482"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:242b8feb3c493ab78be289c034a1f659e8826e2233786e36f2893a950a719bb6"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:38cf1c40a921d05c5edc61a785c0ddb4bed67827069f535d794ce6bcded919fc"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:e0bbdd76ce9aa5d4209d65f2b27fc6e5ef1312ae6c5333c26db3f5ade53a1e99"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:254ec27fdb5b1ee60684f91683be95e5133c994cc54e86a0b0963afa25c8f8a6"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:407653af5617f0757261ae249d3fba09504d7a71ab36ac057c938572d1bc9331"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:c693e916709c2465b02ca0ad7b387c4f8423d1db7b4649c551f27a529181c5ad"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b5ff4911aea936a47d9376fd3ab17e970cc543d1b68921886e7f64bd28308d1"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:177f55a886d74f1808763976ac4efd29b7ed15c69f4d838bbd74d9d09cf6fa86"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:964faa8a861d2664f0c7ab0c181af0bea66098b1919439815ca8803ef136fc4e"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:4dd484681c15e6b9a977c785a345d3e378d72678fd5f1f3c0509608da24f2ac0"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f6d6cff3538391e8486a431569b77921adfcdef14eb18fbf19b7c0a5294d4e6a"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:a6d511cc297ff0883bc3708b465ff82d7560193169a8b93260f74ecb0a5e08a7"}, - {file = "pydantic_core-2.20.1.tar.gz", hash = "sha256:26ca695eeee5f9f1aeeb211ffc12f10bcb6f71e2989988fda61dabd65db878d4"}, + {file = "pydantic_core-2.23.4-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:b10bd51f823d891193d4717448fab065733958bdb6a6b351967bd349d48d5c9b"}, + {file = "pydantic_core-2.23.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4fc714bdbfb534f94034efaa6eadd74e5b93c8fa6315565a222f7b6f42ca1166"}, + {file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63e46b3169866bd62849936de036f901a9356e36376079b05efa83caeaa02ceb"}, + {file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ed1a53de42fbe34853ba90513cea21673481cd81ed1be739f7f2efb931b24916"}, + {file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cfdd16ab5e59fc31b5e906d1a3f666571abc367598e3e02c83403acabc092e07"}, + {file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:255a8ef062cbf6674450e668482456abac99a5583bbafb73f9ad469540a3a232"}, + {file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a7cd62e831afe623fbb7aabbb4fe583212115b3ef38a9f6b71869ba644624a2"}, + {file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f09e2ff1f17c2b51f2bc76d1cc33da96298f0a036a137f5440ab3ec5360b624f"}, + {file = "pydantic_core-2.23.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e38e63e6f3d1cec5a27e0afe90a085af8b6806ee208b33030e65b6516353f1a3"}, + {file = "pydantic_core-2.23.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0dbd8dbed2085ed23b5c04afa29d8fd2771674223135dc9bc937f3c09284d071"}, + {file = "pydantic_core-2.23.4-cp310-none-win32.whl", hash = "sha256:6531b7ca5f951d663c339002e91aaebda765ec7d61b7d1e3991051906ddde119"}, + {file = "pydantic_core-2.23.4-cp310-none-win_amd64.whl", hash = "sha256:7c9129eb40958b3d4500fa2467e6a83356b3b61bfff1b414c7361d9220f9ae8f"}, + {file = "pydantic_core-2.23.4-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:77733e3892bb0a7fa797826361ce8a9184d25c8dffaec60b7ffe928153680ba8"}, + {file = "pydantic_core-2.23.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1b84d168f6c48fabd1f2027a3d1bdfe62f92cade1fb273a5d68e621da0e44e6d"}, + {file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df49e7a0861a8c36d089c1ed57d308623d60416dab2647a4a17fe050ba85de0e"}, + {file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ff02b6d461a6de369f07ec15e465a88895f3223eb75073ffea56b84d9331f607"}, + {file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:996a38a83508c54c78a5f41456b0103c30508fed9abcad0a59b876d7398f25fd"}, + {file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d97683ddee4723ae8c95d1eddac7c192e8c552da0c73a925a89fa8649bf13eea"}, + {file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:216f9b2d7713eb98cb83c80b9c794de1f6b7e3145eef40400c62e86cee5f4e1e"}, + {file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6f783e0ec4803c787bcea93e13e9932edab72068f68ecffdf86a99fd5918878b"}, + {file = "pydantic_core-2.23.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d0776dea117cf5272382634bd2a5c1b6eb16767c223c6a5317cd3e2a757c61a0"}, + {file = "pydantic_core-2.23.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d5f7a395a8cf1621939692dba2a6b6a830efa6b3cee787d82c7de1ad2930de64"}, + {file = "pydantic_core-2.23.4-cp311-none-win32.whl", hash = "sha256:74b9127ffea03643e998e0c5ad9bd3811d3dac8c676e47db17b0ee7c3c3bf35f"}, + {file = "pydantic_core-2.23.4-cp311-none-win_amd64.whl", hash = "sha256:98d134c954828488b153d88ba1f34e14259284f256180ce659e8d83e9c05eaa3"}, + {file = "pydantic_core-2.23.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:f3e0da4ebaef65158d4dfd7d3678aad692f7666877df0002b8a522cdf088f231"}, + {file = "pydantic_core-2.23.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f69a8e0b033b747bb3e36a44e7732f0c99f7edd5cea723d45bc0d6e95377ffee"}, + {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:723314c1d51722ab28bfcd5240d858512ffd3116449c557a1336cbe3919beb87"}, + {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bb2802e667b7051a1bebbfe93684841cc9351004e2badbd6411bf357ab8d5ac8"}, + {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d18ca8148bebe1b0a382a27a8ee60350091a6ddaf475fa05ef50dc35b5df6327"}, + {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33e3d65a85a2a4a0dc3b092b938a4062b1a05f3a9abde65ea93b233bca0e03f2"}, + {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:128585782e5bfa515c590ccee4b727fb76925dd04a98864182b22e89a4e6ed36"}, + {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:68665f4c17edcceecc112dfed5dbe6f92261fb9d6054b47d01bf6371a6196126"}, + {file = "pydantic_core-2.23.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:20152074317d9bed6b7a95ade3b7d6054845d70584216160860425f4fbd5ee9e"}, + {file = "pydantic_core-2.23.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:9261d3ce84fa1d38ed649c3638feefeae23d32ba9182963e465d58d62203bd24"}, + {file = "pydantic_core-2.23.4-cp312-none-win32.whl", hash = "sha256:4ba762ed58e8d68657fc1281e9bb72e1c3e79cc5d464be146e260c541ec12d84"}, + {file = "pydantic_core-2.23.4-cp312-none-win_amd64.whl", hash = "sha256:97df63000f4fea395b2824da80e169731088656d1818a11b95f3b173747b6cd9"}, + {file = "pydantic_core-2.23.4-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7530e201d10d7d14abce4fb54cfe5b94a0aefc87da539d0346a484ead376c3cc"}, + {file = "pydantic_core-2.23.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:df933278128ea1cd77772673c73954e53a1c95a4fdf41eef97c2b779271bd0bd"}, + {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cb3da3fd1b6a5d0279a01877713dbda118a2a4fc6f0d821a57da2e464793f05"}, + {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:42c6dcb030aefb668a2b7009c85b27f90e51e6a3b4d5c9bc4c57631292015b0d"}, + {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:696dd8d674d6ce621ab9d45b205df149399e4bb9aa34102c970b721554828510"}, + {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2971bb5ffe72cc0f555c13e19b23c85b654dd2a8f7ab493c262071377bfce9f6"}, + {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8394d940e5d400d04cad4f75c0598665cbb81aecefaca82ca85bd28264af7f9b"}, + {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0dff76e0602ca7d4cdaacc1ac4c005e0ce0dcfe095d5b5259163a80d3a10d327"}, + {file = "pydantic_core-2.23.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:7d32706badfe136888bdea71c0def994644e09fff0bfe47441deaed8e96fdbc6"}, + {file = "pydantic_core-2.23.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ed541d70698978a20eb63d8c5d72f2cc6d7079d9d90f6b50bad07826f1320f5f"}, + {file = "pydantic_core-2.23.4-cp313-none-win32.whl", hash = "sha256:3d5639516376dce1940ea36edf408c554475369f5da2abd45d44621cb616f769"}, + {file = "pydantic_core-2.23.4-cp313-none-win_amd64.whl", hash = "sha256:5a1504ad17ba4210df3a045132a7baeeba5a200e930f57512ee02909fc5c4cb5"}, + {file = "pydantic_core-2.23.4-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:d4488a93b071c04dc20f5cecc3631fc78b9789dd72483ba15d423b5b3689b555"}, + {file = "pydantic_core-2.23.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:81965a16b675b35e1d09dd14df53f190f9129c0202356ed44ab2728b1c905658"}, + {file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ffa2ebd4c8530079140dd2d7f794a9d9a73cbb8e9d59ffe24c63436efa8f271"}, + {file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:61817945f2fe7d166e75fbfb28004034b48e44878177fc54d81688e7b85a3665"}, + {file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:29d2c342c4bc01b88402d60189f3df065fb0dda3654744d5a165a5288a657368"}, + {file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5e11661ce0fd30a6790e8bcdf263b9ec5988e95e63cf901972107efc49218b13"}, + {file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d18368b137c6295db49ce7218b1a9ba15c5bc254c96d7c9f9e924a9bc7825ad"}, + {file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ec4e55f79b1c4ffb2eecd8a0cfba9955a2588497d96851f4c8f99aa4a1d39b12"}, + {file = "pydantic_core-2.23.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:374a5e5049eda9e0a44c696c7ade3ff355f06b1fe0bb945ea3cac2bc336478a2"}, + {file = "pydantic_core-2.23.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5c364564d17da23db1106787675fc7af45f2f7b58b4173bfdd105564e132e6fb"}, + {file = "pydantic_core-2.23.4-cp38-none-win32.whl", hash = "sha256:d7a80d21d613eec45e3d41eb22f8f94ddc758a6c4720842dc74c0581f54993d6"}, + {file = "pydantic_core-2.23.4-cp38-none-win_amd64.whl", hash = "sha256:5f5ff8d839f4566a474a969508fe1c5e59c31c80d9e140566f9a37bba7b8d556"}, + {file = "pydantic_core-2.23.4-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:a4fa4fc04dff799089689f4fd502ce7d59de529fc2f40a2c8836886c03e0175a"}, + {file = "pydantic_core-2.23.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0a7df63886be5e270da67e0966cf4afbae86069501d35c8c1b3b6c168f42cb36"}, + {file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dcedcd19a557e182628afa1d553c3895a9f825b936415d0dbd3cd0bbcfd29b4b"}, + {file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5f54b118ce5de9ac21c363d9b3caa6c800341e8c47a508787e5868c6b79c9323"}, + {file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:86d2f57d3e1379a9525c5ab067b27dbb8a0642fb5d454e17a9ac434f9ce523e3"}, + {file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:de6d1d1b9e5101508cb37ab0d972357cac5235f5c6533d1071964c47139257df"}, + {file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1278e0d324f6908e872730c9102b0112477a7f7cf88b308e4fc36ce1bdb6d58c"}, + {file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9a6b5099eeec78827553827f4c6b8615978bb4b6a88e5d9b93eddf8bb6790f55"}, + {file = "pydantic_core-2.23.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:e55541f756f9b3ee346b840103f32779c695a19826a4c442b7954550a0972040"}, + {file = "pydantic_core-2.23.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a5c7ba8ffb6d6f8f2ab08743be203654bb1aaa8c9dcb09f82ddd34eadb695605"}, + {file = "pydantic_core-2.23.4-cp39-none-win32.whl", hash = "sha256:37b0fe330e4a58d3c58b24d91d1eb102aeec675a3db4c292ec3928ecd892a9a6"}, + {file = "pydantic_core-2.23.4-cp39-none-win_amd64.whl", hash = "sha256:1498bec4c05c9c787bde9125cfdcc63a41004ff167f495063191b863399b1a29"}, + {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:f455ee30a9d61d3e1a15abd5068827773d6e4dc513e795f380cdd59932c782d5"}, + {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:1e90d2e3bd2c3863d48525d297cd143fe541be8bbf6f579504b9712cb6b643ec"}, + {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e203fdf807ac7e12ab59ca2bfcabb38c7cf0b33c41efeb00f8e5da1d86af480"}, + {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e08277a400de01bc72436a0ccd02bdf596631411f592ad985dcee21445bd0068"}, + {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f220b0eea5965dec25480b6333c788fb72ce5f9129e8759ef876a1d805d00801"}, + {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:d06b0c8da4f16d1d1e352134427cb194a0a6e19ad5db9161bf32b2113409e728"}, + {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:ba1a0996f6c2773bd83e63f18914c1de3c9dd26d55f4ac302a7efe93fb8e7433"}, + {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:9a5bce9d23aac8f0cf0836ecfc033896aa8443b501c58d0602dbfd5bd5b37753"}, + {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:78ddaaa81421a29574a682b3179d4cf9e6d405a09b99d93ddcf7e5239c742e21"}, + {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:883a91b5dd7d26492ff2f04f40fbb652de40fcc0afe07e8129e8ae779c2110eb"}, + {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88ad334a15b32a791ea935af224b9de1bf99bcd62fabf745d5f3442199d86d59"}, + {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:233710f069d251feb12a56da21e14cca67994eab08362207785cf8c598e74577"}, + {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:19442362866a753485ba5e4be408964644dd6a09123d9416c54cd49171f50744"}, + {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:624e278a7d29b6445e4e813af92af37820fafb6dcc55c012c834f9e26f9aaaef"}, + {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f5ef8f42bec47f21d07668a043f077d507e5bf4e668d5c6dfe6aaba89de1a5b8"}, + {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:aea443fffa9fbe3af1a9ba721a87f926fe548d32cab71d188a6ede77d0ff244e"}, + {file = "pydantic_core-2.23.4.tar.gz", hash = "sha256:2584f7cf844ac4d970fba483a717dbe10c1c1c96a969bf65d61ffe94df1b2863"}, ] [package.dependencies] @@ -1566,13 +1739,13 @@ semver = ["semver (>=3.0.2)"] [[package]] name = "pydantic-settings" -version = "2.4.0" +version = "2.5.2" description = "Settings management using Pydantic" optional = false python-versions = ">=3.8" files = [ - {file = "pydantic_settings-2.4.0-py3-none-any.whl", hash = "sha256:bb6849dc067f1687574c12a639e231f3a6feeed0a12d710c1382045c5db1c315"}, - {file = "pydantic_settings-2.4.0.tar.gz", hash = "sha256:ed81c3a0f46392b4d7c0a565c05884e6e54b3456e6f0fe4d8814981172dc9a88"}, + {file = "pydantic_settings-2.5.2-py3-none-any.whl", hash = "sha256:2c912e55fd5794a59bf8c832b9de832dcfdf4778d79ff79b708744eed499a907"}, + {file = "pydantic_settings-2.5.2.tar.gz", hash = "sha256:f90b139682bee4d2065273d5185d71d37ea46cfe57e1b5ae184fc6a0b2484ca0"}, ] [package.dependencies] @@ -1600,13 +1773,13 @@ windows-terminal = ["colorama (>=0.4.6)"] [[package]] name = "pyproject-api" -version = "1.7.1" +version = "1.8.0" description = "API to interact with the python pyproject.toml based projects" optional = false python-versions = ">=3.8" files = [ - {file = "pyproject_api-1.7.1-py3-none-any.whl", hash = "sha256:2dc1654062c2b27733d8fd4cdda672b22fe8741ef1dde8e3a998a9547b071eeb"}, - {file = "pyproject_api-1.7.1.tar.gz", hash = "sha256:7ebc6cd10710f89f4cf2a2731710a98abce37ebff19427116ff2174c9236a827"}, + {file = "pyproject_api-1.8.0-py3-none-any.whl", hash = "sha256:3d7d347a047afe796fd5d1885b1e391ba29be7169bd2f102fcd378f04273d228"}, + {file = "pyproject_api-1.8.0.tar.gz", hash = "sha256:77b8049f2feb5d33eefcc21b57f1e279636277a8ac8ad6b5871037b243778496"}, ] [package.dependencies] @@ -1614,8 +1787,8 @@ packaging = ">=24.1" tomli = {version = ">=2.0.1", markers = "python_version < \"3.11\""} [package.extras] -docs = ["furo (>=2024.5.6)", "sphinx-autodoc-typehints (>=2.2.1)"] -testing = ["covdefaults (>=2.3)", "pytest (>=8.2.2)", "pytest-cov (>=5)", "pytest-mock (>=3.14)", "setuptools (>=70.1)"] +docs = ["furo (>=2024.8.6)", "sphinx-autodoc-typehints (>=2.4.1)"] +testing = ["covdefaults (>=2.3)", "pytest (>=8.3.3)", "pytest-cov (>=5)", "pytest-mock (>=3.14)", "setuptools (>=75.1)"] [[package]] name = "pysam" @@ -1655,13 +1828,13 @@ files = [ [[package]] name = "pytest" -version = "8.3.2" +version = "8.3.3" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.8" files = [ - {file = "pytest-8.3.2-py3-none-any.whl", hash = "sha256:4ba08f9ae7dcf84ded419494d229b48d0903ea6407b030eaec46df5e6a73bba5"}, - {file = "pytest-8.3.2.tar.gz", hash = "sha256:c132345d12ce551242c87269de812483f5bcc87cdbb4722e48487ba194f9fdce"}, + {file = "pytest-8.3.3-py3-none-any.whl", hash = "sha256:a6853c7375b2663155079443d2e45de913a911a11d669df02a50814944db57b2"}, + {file = "pytest-8.3.3.tar.gz", hash = "sha256:70b98107bd648308a7952b06e6ca9a50bc660be218d53c257cc1fc94fda10181"}, ] [package.dependencies] @@ -1727,94 +1900,94 @@ cli = ["click (>=5.0)"] [[package]] name = "python-multipart" -version = "0.0.9" +version = "0.0.12" description = "A streaming multipart parser for Python" optional = false python-versions = ">=3.8" files = [ - {file = "python_multipart-0.0.9-py3-none-any.whl", hash = "sha256:97ca7b8ea7b05f977dc3849c3ba99d51689822fab725c3703af7c866a0c2b215"}, - {file = "python_multipart-0.0.9.tar.gz", hash = "sha256:03f54688c663f1b7977105f021043b0793151e4cb1c1a9d4a11fc13d622c4026"}, + {file = "python_multipart-0.0.12-py3-none-any.whl", hash = "sha256:43dcf96cf65888a9cd3423544dd0d75ac10f7aa0c3c28a175bbcd00c9ce1aebf"}, + {file = "python_multipart-0.0.12.tar.gz", hash = "sha256:045e1f98d719c1ce085ed7f7e1ef9d8ccc8c02ba02b5566d5f7521410ced58cb"}, ] -[package.extras] -dev = ["atomicwrites (==1.4.1)", "attrs (==23.2.0)", "coverage (==7.4.1)", "hatch", "invoke (==2.2.0)", "more-itertools (==10.2.0)", "pbr (==6.0.0)", "pluggy (==1.4.0)", "py (==1.11.0)", "pytest (==8.0.0)", "pytest-cov (==4.1.0)", "pytest-timeout (==2.2.0)", "pyyaml (==6.0.1)", "ruff (==0.2.1)"] - [[package]] name = "pyyaml" -version = "6.0.1" +version = "6.0.2" description = "YAML parser and emitter for Python" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"}, - {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"}, - {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, - {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, - {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, - {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, - {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, - {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, - {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, - {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"}, - {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, - {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, - {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, - {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, - {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, - {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, - {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, - {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, - {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, - {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, - {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, - {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, - {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, - {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, - {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"}, - {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"}, - {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"}, - {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"}, - {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"}, - {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"}, - {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"}, - {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"}, - {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"}, - {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"}, - {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, - {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, - {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, - {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, - {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, - {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, - {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, - {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"}, - {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, - {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, - {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, - {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, - {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, - {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, - {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, + {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, + {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, + {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237"}, + {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b"}, + {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed"}, + {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180"}, + {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68"}, + {file = "PyYAML-6.0.2-cp310-cp310-win32.whl", hash = "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99"}, + {file = "PyYAML-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e"}, + {file = "PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774"}, + {file = "PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee"}, + {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c"}, + {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317"}, + {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85"}, + {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4"}, + {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e"}, + {file = "PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5"}, + {file = "PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44"}, + {file = "PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab"}, + {file = "PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725"}, + {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5"}, + {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425"}, + {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476"}, + {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48"}, + {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b"}, + {file = "PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4"}, + {file = "PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8"}, + {file = "PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba"}, + {file = "PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1"}, + {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133"}, + {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484"}, + {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5"}, + {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc"}, + {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652"}, + {file = "PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183"}, + {file = "PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563"}, + {file = "PyYAML-6.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a"}, + {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5"}, + {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d"}, + {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083"}, + {file = "PyYAML-6.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706"}, + {file = "PyYAML-6.0.2-cp38-cp38-win32.whl", hash = "sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a"}, + {file = "PyYAML-6.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff"}, + {file = "PyYAML-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d"}, + {file = "PyYAML-6.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f"}, + {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290"}, + {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12"}, + {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19"}, + {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e"}, + {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725"}, + {file = "PyYAML-6.0.2-cp39-cp39-win32.whl", hash = "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631"}, + {file = "PyYAML-6.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8"}, + {file = "pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e"}, ] [[package]] name = "redis" -version = "5.0.8" +version = "5.1.1" description = "Python client for Redis database and key-value store" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "redis-5.0.8-py3-none-any.whl", hash = "sha256:56134ee08ea909106090934adc36f65c9bcbbaecea5b21ba704ba6fb561f8eb4"}, - {file = "redis-5.0.8.tar.gz", hash = "sha256:0c5b10d387568dfe0698c6fad6615750c24170e548ca2deac10c649d463e9870"}, + {file = "redis-5.1.1-py3-none-any.whl", hash = "sha256:f8ea06b7482a668c6475ae202ed8d9bcaa409f6e87fb77ed1043d912afd62e24"}, + {file = "redis-5.1.1.tar.gz", hash = "sha256:f6c997521fedbae53387307c5d0bf784d9acc28d9f1d058abeac566ec4dbed72"}, ] [package.dependencies] async-timeout = {version = ">=4.0.3", markers = "python_full_version < \"3.11.3\""} [package.extras] -hiredis = ["hiredis (>1.0.0)"] -ocsp = ["cryptography (>=36.0.1)", "pyopenssl (==20.0.1)", "requests (>=2.26.0)"] +hiredis = ["hiredis (>=3.0.0)"] +ocsp = ["cryptography (>=36.0.1)", "pyopenssl (==23.2.1)", "requests (>=2.31.0)"] [[package]] name = "referencing" @@ -1854,132 +2027,133 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "rich" -version = "13.7.1" +version = "13.9.2" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" optional = false -python-versions = ">=3.7.0" +python-versions = ">=3.8.0" files = [ - {file = "rich-13.7.1-py3-none-any.whl", hash = "sha256:4edbae314f59eb482f54e9e30bf00d33350aaa94f4bfcd4e9e3110e64d0d7222"}, - {file = "rich-13.7.1.tar.gz", hash = "sha256:9be308cb1fe2f1f57d67ce99e95af38a1e2bc71ad9813b0e247cf7ffbcc3a432"}, + {file = "rich-13.9.2-py3-none-any.whl", hash = "sha256:8c82a3d3f8dcfe9e734771313e606b39d8247bb6b826e196f4914b333b743cf1"}, + {file = "rich-13.9.2.tar.gz", hash = "sha256:51a2c62057461aaf7152b4d611168f93a9fc73068f8ded2790f29fe2b5366d0c"}, ] [package.dependencies] markdown-it-py = ">=2.2.0" pygments = ">=2.13.0,<3.0.0" +typing-extensions = {version = ">=4.0.0,<5.0", markers = "python_version < \"3.11\""} [package.extras] jupyter = ["ipywidgets (>=7.5.1,<9)"] [[package]] name = "rpds-py" -version = "0.19.1" +version = "0.20.0" description = "Python bindings to Rust's persistent data structures (rpds)" optional = false python-versions = ">=3.8" files = [ - {file = "rpds_py-0.19.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:aaf71f95b21f9dc708123335df22e5a2fef6307e3e6f9ed773b2e0938cc4d491"}, - {file = "rpds_py-0.19.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ca0dda0c5715efe2ab35bb83f813f681ebcd2840d8b1b92bfc6fe3ab382fae4a"}, - {file = "rpds_py-0.19.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:81db2e7282cc0487f500d4db203edc57da81acde9e35f061d69ed983228ffe3b"}, - {file = "rpds_py-0.19.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1a8dfa125b60ec00c7c9baef945bb04abf8ac772d8ebefd79dae2a5f316d7850"}, - {file = "rpds_py-0.19.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:271accf41b02687cef26367c775ab220372ee0f4925591c6796e7c148c50cab5"}, - {file = "rpds_py-0.19.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f9bc4161bd3b970cd6a6fcda70583ad4afd10f2750609fb1f3ca9505050d4ef3"}, - {file = "rpds_py-0.19.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f0cf2a0dbb5987da4bd92a7ca727eadb225581dd9681365beba9accbe5308f7d"}, - {file = "rpds_py-0.19.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b5e28e56143750808c1c79c70a16519e9bc0a68b623197b96292b21b62d6055c"}, - {file = "rpds_py-0.19.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c7af6f7b80f687b33a4cdb0a785a5d4de1fb027a44c9a049d8eb67d5bfe8a687"}, - {file = "rpds_py-0.19.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e429fc517a1c5e2a70d576077231538a98d59a45dfc552d1ac45a132844e6dfb"}, - {file = "rpds_py-0.19.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:d2dbd8f4990d4788cb122f63bf000357533f34860d269c1a8e90ae362090ff3a"}, - {file = "rpds_py-0.19.1-cp310-none-win32.whl", hash = "sha256:e0f9d268b19e8f61bf42a1da48276bcd05f7ab5560311f541d22557f8227b866"}, - {file = "rpds_py-0.19.1-cp310-none-win_amd64.whl", hash = "sha256:df7c841813f6265e636fe548a49664c77af31ddfa0085515326342a751a6ba51"}, - {file = "rpds_py-0.19.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:902cf4739458852fe917104365ec0efbea7d29a15e4276c96a8d33e6ed8ec137"}, - {file = "rpds_py-0.19.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f3d73022990ab0c8b172cce57c69fd9a89c24fd473a5e79cbce92df87e3d9c48"}, - {file = "rpds_py-0.19.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3837c63dd6918a24de6c526277910e3766d8c2b1627c500b155f3eecad8fad65"}, - {file = "rpds_py-0.19.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:cdb7eb3cf3deb3dd9e7b8749323b5d970052711f9e1e9f36364163627f96da58"}, - {file = "rpds_py-0.19.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:26ab43b6d65d25b1a333c8d1b1c2f8399385ff683a35ab5e274ba7b8bb7dc61c"}, - {file = "rpds_py-0.19.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:75130df05aae7a7ac171b3b5b24714cffeabd054ad2ebc18870b3aa4526eba23"}, - {file = "rpds_py-0.19.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c34f751bf67cab69638564eee34023909380ba3e0d8ee7f6fe473079bf93f09b"}, - {file = "rpds_py-0.19.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f2671cb47e50a97f419a02cd1e0c339b31de017b033186358db92f4d8e2e17d8"}, - {file = "rpds_py-0.19.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3c73254c256081704dba0a333457e2fb815364018788f9b501efe7c5e0ada401"}, - {file = "rpds_py-0.19.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4383beb4a29935b8fa28aca8fa84c956bf545cb0c46307b091b8d312a9150e6a"}, - {file = "rpds_py-0.19.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:dbceedcf4a9329cc665452db1aaf0845b85c666e4885b92ee0cddb1dbf7e052a"}, - {file = "rpds_py-0.19.1-cp311-none-win32.whl", hash = "sha256:f0a6d4a93d2a05daec7cb885157c97bbb0be4da739d6f9dfb02e101eb40921cd"}, - {file = "rpds_py-0.19.1-cp311-none-win_amd64.whl", hash = "sha256:c149a652aeac4902ecff2dd93c3b2681c608bd5208c793c4a99404b3e1afc87c"}, - {file = "rpds_py-0.19.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:56313be667a837ff1ea3508cebb1ef6681d418fa2913a0635386cf29cff35165"}, - {file = "rpds_py-0.19.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6d1d7539043b2b31307f2c6c72957a97c839a88b2629a348ebabe5aa8b626d6b"}, - {file = "rpds_py-0.19.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e1dc59a5e7bc7f44bd0c048681f5e05356e479c50be4f2c1a7089103f1621d5"}, - {file = "rpds_py-0.19.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b8f78398e67a7227aefa95f876481485403eb974b29e9dc38b307bb6eb2315ea"}, - {file = "rpds_py-0.19.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ef07a0a1d254eeb16455d839cef6e8c2ed127f47f014bbda64a58b5482b6c836"}, - {file = "rpds_py-0.19.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8124101e92c56827bebef084ff106e8ea11c743256149a95b9fd860d3a4f331f"}, - {file = "rpds_py-0.19.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:08ce9c95a0b093b7aec75676b356a27879901488abc27e9d029273d280438505"}, - {file = "rpds_py-0.19.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0b02dd77a2de6e49078c8937aadabe933ceac04b41c5dde5eca13a69f3cf144e"}, - {file = "rpds_py-0.19.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4dd02e29c8cbed21a1875330b07246b71121a1c08e29f0ee3db5b4cfe16980c4"}, - {file = "rpds_py-0.19.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:9c7042488165f7251dc7894cd533a875d2875af6d3b0e09eda9c4b334627ad1c"}, - {file = "rpds_py-0.19.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f809a17cc78bd331e137caa25262b507225854073fd319e987bd216bed911b7c"}, - {file = "rpds_py-0.19.1-cp312-none-win32.whl", hash = "sha256:3ddab996807c6b4227967fe1587febade4e48ac47bb0e2d3e7858bc621b1cace"}, - {file = "rpds_py-0.19.1-cp312-none-win_amd64.whl", hash = "sha256:32e0db3d6e4f45601b58e4ac75c6f24afbf99818c647cc2066f3e4b192dabb1f"}, - {file = "rpds_py-0.19.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:747251e428406b05fc86fee3904ee19550c4d2d19258cef274e2151f31ae9d38"}, - {file = "rpds_py-0.19.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:dc733d35f861f8d78abfaf54035461e10423422999b360966bf1c443cbc42705"}, - {file = "rpds_py-0.19.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bbda75f245caecff8faa7e32ee94dfaa8312a3367397975527f29654cd17a6ed"}, - {file = "rpds_py-0.19.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bd04d8cab16cab5b0a9ffc7d10f0779cf1120ab16c3925404428f74a0a43205a"}, - {file = "rpds_py-0.19.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e2d66eb41ffca6cc3c91d8387509d27ba73ad28371ef90255c50cb51f8953301"}, - {file = "rpds_py-0.19.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fdf4890cda3b59170009d012fca3294c00140e7f2abe1910e6a730809d0f3f9b"}, - {file = "rpds_py-0.19.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d1fa67ef839bad3815124f5f57e48cd50ff392f4911a9f3cf449d66fa3df62a5"}, - {file = "rpds_py-0.19.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b82c9514c6d74b89a370c4060bdb80d2299bc6857e462e4a215b4ef7aa7b090e"}, - {file = "rpds_py-0.19.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c7b07959866a6afb019abb9564d8a55046feb7a84506c74a6f197cbcdf8a208e"}, - {file = "rpds_py-0.19.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:4f580ae79d0b861dfd912494ab9d477bea535bfb4756a2269130b6607a21802e"}, - {file = "rpds_py-0.19.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:c6d20c8896c00775e6f62d8373aba32956aa0b850d02b5ec493f486c88e12859"}, - {file = "rpds_py-0.19.1-cp313-none-win32.whl", hash = "sha256:afedc35fe4b9e30ab240b208bb9dc8938cb4afe9187589e8d8d085e1aacb8309"}, - {file = "rpds_py-0.19.1-cp313-none-win_amd64.whl", hash = "sha256:1d4af2eb520d759f48f1073ad3caef997d1bfd910dc34e41261a595d3f038a94"}, - {file = "rpds_py-0.19.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:34bca66e2e3eabc8a19e9afe0d3e77789733c702c7c43cd008e953d5d1463fde"}, - {file = "rpds_py-0.19.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:24f8ae92c7fae7c28d0fae9b52829235df83f34847aa8160a47eb229d9666c7b"}, - {file = "rpds_py-0.19.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71157f9db7f6bc6599a852852f3389343bea34315b4e6f109e5cbc97c1fb2963"}, - {file = "rpds_py-0.19.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1d494887d40dc4dd0d5a71e9d07324e5c09c4383d93942d391727e7a40ff810b"}, - {file = "rpds_py-0.19.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7b3661e6d4ba63a094138032c1356d557de5b3ea6fd3cca62a195f623e381c76"}, - {file = "rpds_py-0.19.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:97fbb77eaeb97591efdc654b8b5f3ccc066406ccfb3175b41382f221ecc216e8"}, - {file = "rpds_py-0.19.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4cc4bc73e53af8e7a42c8fd7923bbe35babacfa7394ae9240b3430b5dcf16b2a"}, - {file = "rpds_py-0.19.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:35af5e4d5448fa179fd7fff0bba0fba51f876cd55212f96c8bbcecc5c684ae5c"}, - {file = "rpds_py-0.19.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:3511f6baf8438326e351097cecd137eb45c5f019944fe0fd0ae2fea2fd26be39"}, - {file = "rpds_py-0.19.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:57863d16187995c10fe9cf911b897ed443ac68189179541734502353af33e693"}, - {file = "rpds_py-0.19.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:9e318e6786b1e750a62f90c6f7fa8b542102bdcf97c7c4de2a48b50b61bd36ec"}, - {file = "rpds_py-0.19.1-cp38-none-win32.whl", hash = "sha256:53dbc35808c6faa2ce3e48571f8f74ef70802218554884787b86a30947842a14"}, - {file = "rpds_py-0.19.1-cp38-none-win_amd64.whl", hash = "sha256:8df1c283e57c9cb4d271fdc1875f4a58a143a2d1698eb0d6b7c0d7d5f49c53a1"}, - {file = "rpds_py-0.19.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:e76c902d229a3aa9d5ceb813e1cbcc69bf5bda44c80d574ff1ac1fa3136dea71"}, - {file = "rpds_py-0.19.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:de1f7cd5b6b351e1afd7568bdab94934d656abe273d66cda0ceea43bbc02a0c2"}, - {file = "rpds_py-0.19.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:24fc5a84777cb61692d17988989690d6f34f7f95968ac81398d67c0d0994a897"}, - {file = "rpds_py-0.19.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:74129d5ffc4cde992d89d345f7f7d6758320e5d44a369d74d83493429dad2de5"}, - {file = "rpds_py-0.19.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5e360188b72f8080fefa3adfdcf3618604cc8173651c9754f189fece068d2a45"}, - {file = "rpds_py-0.19.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:13e6d4840897d4e4e6b2aa1443e3a8eca92b0402182aafc5f4ca1f5e24f9270a"}, - {file = "rpds_py-0.19.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f09529d2332264a902688031a83c19de8fda5eb5881e44233286b9c9ec91856d"}, - {file = "rpds_py-0.19.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0d4b52811dcbc1aba08fd88d475f75b4f6db0984ba12275d9bed1a04b2cae9b5"}, - {file = "rpds_py-0.19.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:dd635c2c4043222d80d80ca1ac4530a633102a9f2ad12252183bcf338c1b9474"}, - {file = "rpds_py-0.19.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:f35b34a5184d5e0cc360b61664c1c06e866aab077b5a7c538a3e20c8fcdbf90b"}, - {file = "rpds_py-0.19.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:d4ec0046facab83012d821b33cead742a35b54575c4edfb7ed7445f63441835f"}, - {file = "rpds_py-0.19.1-cp39-none-win32.whl", hash = "sha256:f5b8353ea1a4d7dfb59a7f45c04df66ecfd363bb5b35f33b11ea579111d4655f"}, - {file = "rpds_py-0.19.1-cp39-none-win_amd64.whl", hash = "sha256:1fb93d3486f793d54a094e2bfd9cd97031f63fcb5bc18faeb3dd4b49a1c06523"}, - {file = "rpds_py-0.19.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:7d5c7e32f3ee42f77d8ff1a10384b5cdcc2d37035e2e3320ded909aa192d32c3"}, - {file = "rpds_py-0.19.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:89cc8921a4a5028d6dd388c399fcd2eef232e7040345af3d5b16c04b91cf3c7e"}, - {file = "rpds_py-0.19.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bca34e913d27401bda2a6f390d0614049f5a95b3b11cd8eff80fe4ec340a1208"}, - {file = "rpds_py-0.19.1-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5953391af1405f968eb5701ebbb577ebc5ced8d0041406f9052638bafe52209d"}, - {file = "rpds_py-0.19.1-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:840e18c38098221ea6201f091fc5d4de6128961d2930fbbc96806fb43f69aec1"}, - {file = "rpds_py-0.19.1-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6d8b735c4d162dc7d86a9cf3d717f14b6c73637a1f9cd57fe7e61002d9cb1972"}, - {file = "rpds_py-0.19.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce757c7c90d35719b38fa3d4ca55654a76a40716ee299b0865f2de21c146801c"}, - {file = "rpds_py-0.19.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a9421b23c85f361a133aa7c5e8ec757668f70343f4ed8fdb5a4a14abd5437244"}, - {file = "rpds_py-0.19.1-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:3b823be829407393d84ee56dc849dbe3b31b6a326f388e171555b262e8456cc1"}, - {file = "rpds_py-0.19.1-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:5e58b61dcbb483a442c6239c3836696b79f2cd8e7eec11e12155d3f6f2d886d1"}, - {file = "rpds_py-0.19.1-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:39d67896f7235b2c886fb1ee77b1491b77049dcef6fbf0f401e7b4cbed86bbd4"}, - {file = "rpds_py-0.19.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:8b32cd4ab6db50c875001ba4f5a6b30c0f42151aa1fbf9c2e7e3674893fb1dc4"}, - {file = "rpds_py-0.19.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:1c32e41de995f39b6b315d66c27dea3ef7f7c937c06caab4c6a79a5e09e2c415"}, - {file = "rpds_py-0.19.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:1a129c02b42d46758c87faeea21a9f574e1c858b9f358b6dd0bbd71d17713175"}, - {file = "rpds_py-0.19.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:346557f5b1d8fd9966059b7a748fd79ac59f5752cd0e9498d6a40e3ac1c1875f"}, - {file = "rpds_py-0.19.1-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:31e450840f2f27699d014cfc8865cc747184286b26d945bcea6042bb6aa4d26e"}, - {file = "rpds_py-0.19.1-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:01227f8b3e6c8961490d869aa65c99653df80d2f0a7fde8c64ebddab2b9b02fd"}, - {file = "rpds_py-0.19.1-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:69084fd29bfeff14816666c93a466e85414fe6b7d236cfc108a9c11afa6f7301"}, - {file = "rpds_py-0.19.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4d2b88efe65544a7d5121b0c3b003ebba92bfede2ea3577ce548b69c5235185"}, - {file = "rpds_py-0.19.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6ea961a674172ed2235d990d7edf85d15d8dfa23ab8575e48306371c070cda67"}, - {file = "rpds_py-0.19.1-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:5beffdbe766cfe4fb04f30644d822a1080b5359df7db3a63d30fa928375b2720"}, - {file = "rpds_py-0.19.1-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:720f3108fb1bfa32e51db58b832898372eb5891e8472a8093008010911e324c5"}, - {file = "rpds_py-0.19.1-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:c2087dbb76a87ec2c619253e021e4fb20d1a72580feeaa6892b0b3d955175a71"}, - {file = "rpds_py-0.19.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2ddd50f18ebc05ec29a0d9271e9dbe93997536da3546677f8ca00b76d477680c"}, - {file = "rpds_py-0.19.1.tar.gz", hash = "sha256:31dd5794837f00b46f4096aa8ccaa5972f73a938982e32ed817bb520c465e520"}, + {file = "rpds_py-0.20.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:3ad0fda1635f8439cde85c700f964b23ed5fc2d28016b32b9ee5fe30da5c84e2"}, + {file = "rpds_py-0.20.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9bb4a0d90fdb03437c109a17eade42dfbf6190408f29b2744114d11586611d6f"}, + {file = "rpds_py-0.20.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c6377e647bbfd0a0b159fe557f2c6c602c159fc752fa316572f012fc0bf67150"}, + {file = "rpds_py-0.20.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eb851b7df9dda52dc1415ebee12362047ce771fc36914586b2e9fcbd7d293b3e"}, + {file = "rpds_py-0.20.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1e0f80b739e5a8f54837be5d5c924483996b603d5502bfff79bf33da06164ee2"}, + {file = "rpds_py-0.20.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5a8c94dad2e45324fc74dce25e1645d4d14df9a4e54a30fa0ae8bad9a63928e3"}, + {file = "rpds_py-0.20.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8e604fe73ba048c06085beaf51147eaec7df856824bfe7b98657cf436623daf"}, + {file = "rpds_py-0.20.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:df3de6b7726b52966edf29663e57306b23ef775faf0ac01a3e9f4012a24a4140"}, + {file = "rpds_py-0.20.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:cf258ede5bc22a45c8e726b29835b9303c285ab46fc7c3a4cc770736b5304c9f"}, + {file = "rpds_py-0.20.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:55fea87029cded5df854ca7e192ec7bdb7ecd1d9a3f63d5c4eb09148acf4a7ce"}, + {file = "rpds_py-0.20.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ae94bd0b2f02c28e199e9bc51485d0c5601f58780636185660f86bf80c89af94"}, + {file = "rpds_py-0.20.0-cp310-none-win32.whl", hash = "sha256:28527c685f237c05445efec62426d285e47a58fb05ba0090a4340b73ecda6dee"}, + {file = "rpds_py-0.20.0-cp310-none-win_amd64.whl", hash = "sha256:238a2d5b1cad28cdc6ed15faf93a998336eb041c4e440dd7f902528b8891b399"}, + {file = "rpds_py-0.20.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:ac2f4f7a98934c2ed6505aead07b979e6f999389f16b714448fb39bbaa86a489"}, + {file = "rpds_py-0.20.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:220002c1b846db9afd83371d08d239fdc865e8f8c5795bbaec20916a76db3318"}, + {file = "rpds_py-0.20.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d7919548df3f25374a1f5d01fbcd38dacab338ef5f33e044744b5c36729c8db"}, + {file = "rpds_py-0.20.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:758406267907b3781beee0f0edfe4a179fbd97c0be2e9b1154d7f0a1279cf8e5"}, + {file = "rpds_py-0.20.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3d61339e9f84a3f0767b1995adfb171a0d00a1185192718a17af6e124728e0f5"}, + {file = "rpds_py-0.20.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1259c7b3705ac0a0bd38197565a5d603218591d3f6cee6e614e380b6ba61c6f6"}, + {file = "rpds_py-0.20.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5c1dc0f53856b9cc9a0ccca0a7cc61d3d20a7088201c0937f3f4048c1718a209"}, + {file = "rpds_py-0.20.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7e60cb630f674a31f0368ed32b2a6b4331b8350d67de53c0359992444b116dd3"}, + {file = "rpds_py-0.20.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:dbe982f38565bb50cb7fb061ebf762c2f254ca3d8c20d4006878766e84266272"}, + {file = "rpds_py-0.20.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:514b3293b64187172bc77c8fb0cdae26981618021053b30d8371c3a902d4d5ad"}, + {file = "rpds_py-0.20.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d0a26ffe9d4dd35e4dfdd1e71f46401cff0181c75ac174711ccff0459135fa58"}, + {file = "rpds_py-0.20.0-cp311-none-win32.whl", hash = "sha256:89c19a494bf3ad08c1da49445cc5d13d8fefc265f48ee7e7556839acdacf69d0"}, + {file = "rpds_py-0.20.0-cp311-none-win_amd64.whl", hash = "sha256:c638144ce971df84650d3ed0096e2ae7af8e62ecbbb7b201c8935c370df00a2c"}, + {file = "rpds_py-0.20.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a84ab91cbe7aab97f7446652d0ed37d35b68a465aeef8fc41932a9d7eee2c1a6"}, + {file = "rpds_py-0.20.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:56e27147a5a4c2c21633ff8475d185734c0e4befd1c989b5b95a5d0db699b21b"}, + {file = "rpds_py-0.20.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2580b0c34583b85efec8c5c5ec9edf2dfe817330cc882ee972ae650e7b5ef739"}, + {file = "rpds_py-0.20.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b80d4a7900cf6b66bb9cee5c352b2d708e29e5a37fe9bf784fa97fc11504bf6c"}, + {file = "rpds_py-0.20.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:50eccbf054e62a7b2209b28dc7a22d6254860209d6753e6b78cfaeb0075d7bee"}, + {file = "rpds_py-0.20.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:49a8063ea4296b3a7e81a5dfb8f7b2d73f0b1c20c2af401fb0cdf22e14711a96"}, + {file = "rpds_py-0.20.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ea438162a9fcbee3ecf36c23e6c68237479f89f962f82dae83dc15feeceb37e4"}, + {file = "rpds_py-0.20.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:18d7585c463087bddcfa74c2ba267339f14f2515158ac4db30b1f9cbdb62c8ef"}, + {file = "rpds_py-0.20.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d4c7d1a051eeb39f5c9547e82ea27cbcc28338482242e3e0b7768033cb083821"}, + {file = "rpds_py-0.20.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e4df1e3b3bec320790f699890d41c59d250f6beda159ea3c44c3f5bac1976940"}, + {file = "rpds_py-0.20.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2cf126d33a91ee6eedc7f3197b53e87a2acdac63602c0f03a02dd69e4b138174"}, + {file = "rpds_py-0.20.0-cp312-none-win32.whl", hash = "sha256:8bc7690f7caee50b04a79bf017a8d020c1f48c2a1077ffe172abec59870f1139"}, + {file = "rpds_py-0.20.0-cp312-none-win_amd64.whl", hash = "sha256:0e13e6952ef264c40587d510ad676a988df19adea20444c2b295e536457bc585"}, + {file = "rpds_py-0.20.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:aa9a0521aeca7d4941499a73ad7d4f8ffa3d1affc50b9ea11d992cd7eff18a29"}, + {file = "rpds_py-0.20.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:4a1f1d51eccb7e6c32ae89243cb352389228ea62f89cd80823ea7dd1b98e0b91"}, + {file = "rpds_py-0.20.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8a86a9b96070674fc88b6f9f71a97d2c1d3e5165574615d1f9168ecba4cecb24"}, + {file = "rpds_py-0.20.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6c8ef2ebf76df43f5750b46851ed1cdf8f109d7787ca40035fe19fbdc1acc5a7"}, + {file = "rpds_py-0.20.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b74b25f024b421d5859d156750ea9a65651793d51b76a2e9238c05c9d5f203a9"}, + {file = "rpds_py-0.20.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:57eb94a8c16ab08fef6404301c38318e2c5a32216bf5de453e2714c964c125c8"}, + {file = "rpds_py-0.20.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e1940dae14e715e2e02dfd5b0f64a52e8374a517a1e531ad9412319dc3ac7879"}, + {file = "rpds_py-0.20.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d20277fd62e1b992a50c43f13fbe13277a31f8c9f70d59759c88f644d66c619f"}, + {file = "rpds_py-0.20.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:06db23d43f26478303e954c34c75182356ca9aa7797d22c5345b16871ab9c45c"}, + {file = "rpds_py-0.20.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b2a5db5397d82fa847e4c624b0c98fe59d2d9b7cf0ce6de09e4d2e80f8f5b3f2"}, + {file = "rpds_py-0.20.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5a35df9f5548fd79cb2f52d27182108c3e6641a4feb0f39067911bf2adaa3e57"}, + {file = "rpds_py-0.20.0-cp313-none-win32.whl", hash = "sha256:fd2d84f40633bc475ef2d5490b9c19543fbf18596dcb1b291e3a12ea5d722f7a"}, + {file = "rpds_py-0.20.0-cp313-none-win_amd64.whl", hash = "sha256:9bc2d153989e3216b0559251b0c260cfd168ec78b1fac33dd485750a228db5a2"}, + {file = "rpds_py-0.20.0-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:f2fbf7db2012d4876fb0d66b5b9ba6591197b0f165db8d99371d976546472a24"}, + {file = "rpds_py-0.20.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:1e5f3cd7397c8f86c8cc72d5a791071431c108edd79872cdd96e00abd8497d29"}, + {file = "rpds_py-0.20.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce9845054c13696f7af7f2b353e6b4f676dab1b4b215d7fe5e05c6f8bb06f965"}, + {file = "rpds_py-0.20.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c3e130fd0ec56cb76eb49ef52faead8ff09d13f4527e9b0c400307ff72b408e1"}, + {file = "rpds_py-0.20.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4b16aa0107ecb512b568244ef461f27697164d9a68d8b35090e9b0c1c8b27752"}, + {file = "rpds_py-0.20.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aa7f429242aae2947246587d2964fad750b79e8c233a2367f71b554e9447949c"}, + {file = "rpds_py-0.20.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:af0fc424a5842a11e28956e69395fbbeab2c97c42253169d87e90aac2886d751"}, + {file = "rpds_py-0.20.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b8c00a3b1e70c1d3891f0db1b05292747f0dbcfb49c43f9244d04c70fbc40eb8"}, + {file = "rpds_py-0.20.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:40ce74fc86ee4645d0a225498d091d8bc61f39b709ebef8204cb8b5a464d3c0e"}, + {file = "rpds_py-0.20.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:4fe84294c7019456e56d93e8ababdad5a329cd25975be749c3f5f558abb48253"}, + {file = "rpds_py-0.20.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:338ca4539aad4ce70a656e5187a3a31c5204f261aef9f6ab50e50bcdffaf050a"}, + {file = "rpds_py-0.20.0-cp38-none-win32.whl", hash = "sha256:54b43a2b07db18314669092bb2de584524d1ef414588780261e31e85846c26a5"}, + {file = "rpds_py-0.20.0-cp38-none-win_amd64.whl", hash = "sha256:a1862d2d7ce1674cffa6d186d53ca95c6e17ed2b06b3f4c476173565c862d232"}, + {file = "rpds_py-0.20.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:3fde368e9140312b6e8b6c09fb9f8c8c2f00999d1823403ae90cc00480221b22"}, + {file = "rpds_py-0.20.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9824fb430c9cf9af743cf7aaf6707bf14323fb51ee74425c380f4c846ea70789"}, + {file = "rpds_py-0.20.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:11ef6ce74616342888b69878d45e9f779b95d4bd48b382a229fe624a409b72c5"}, + {file = "rpds_py-0.20.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c52d3f2f82b763a24ef52f5d24358553e8403ce05f893b5347098014f2d9eff2"}, + {file = "rpds_py-0.20.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9d35cef91e59ebbeaa45214861874bc6f19eb35de96db73e467a8358d701a96c"}, + {file = "rpds_py-0.20.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d72278a30111e5b5525c1dd96120d9e958464316f55adb030433ea905866f4de"}, + {file = "rpds_py-0.20.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b4c29cbbba378759ac5786730d1c3cb4ec6f8ababf5c42a9ce303dc4b3d08cda"}, + {file = "rpds_py-0.20.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6632f2d04f15d1bd6fe0eedd3b86d9061b836ddca4c03d5cf5c7e9e6b7c14580"}, + {file = "rpds_py-0.20.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:d0b67d87bb45ed1cd020e8fbf2307d449b68abc45402fe1a4ac9e46c3c8b192b"}, + {file = "rpds_py-0.20.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:ec31a99ca63bf3cd7f1a5ac9fe95c5e2d060d3c768a09bc1d16e235840861420"}, + {file = "rpds_py-0.20.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:22e6c9976e38f4d8c4a63bd8a8edac5307dffd3ee7e6026d97f3cc3a2dc02a0b"}, + {file = "rpds_py-0.20.0-cp39-none-win32.whl", hash = "sha256:569b3ea770c2717b730b61998b6c54996adee3cef69fc28d444f3e7920313cf7"}, + {file = "rpds_py-0.20.0-cp39-none-win_amd64.whl", hash = "sha256:e6900ecdd50ce0facf703f7a00df12374b74bbc8ad9fe0f6559947fb20f82364"}, + {file = "rpds_py-0.20.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:617c7357272c67696fd052811e352ac54ed1d9b49ab370261a80d3b6ce385045"}, + {file = "rpds_py-0.20.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:9426133526f69fcaba6e42146b4e12d6bc6c839b8b555097020e2b78ce908dcc"}, + {file = "rpds_py-0.20.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:deb62214c42a261cb3eb04d474f7155279c1a8a8c30ac89b7dcb1721d92c3c02"}, + {file = "rpds_py-0.20.0-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fcaeb7b57f1a1e071ebd748984359fef83ecb026325b9d4ca847c95bc7311c92"}, + {file = "rpds_py-0.20.0-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d454b8749b4bd70dd0a79f428731ee263fa6995f83ccb8bada706e8d1d3ff89d"}, + {file = "rpds_py-0.20.0-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d807dc2051abe041b6649681dce568f8e10668e3c1c6543ebae58f2d7e617855"}, + {file = "rpds_py-0.20.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c3c20f0ddeb6e29126d45f89206b8291352b8c5b44384e78a6499d68b52ae511"}, + {file = "rpds_py-0.20.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b7f19250ceef892adf27f0399b9e5afad019288e9be756d6919cb58892129f51"}, + {file = "rpds_py-0.20.0-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:4f1ed4749a08379555cebf4650453f14452eaa9c43d0a95c49db50c18b7da075"}, + {file = "rpds_py-0.20.0-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:dcedf0b42bcb4cfff4101d7771a10532415a6106062f005ab97d1d0ab5681c60"}, + {file = "rpds_py-0.20.0-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:39ed0d010457a78f54090fafb5d108501b5aa5604cc22408fc1c0c77eac14344"}, + {file = "rpds_py-0.20.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:bb273176be34a746bdac0b0d7e4e2c467323d13640b736c4c477881a3220a989"}, + {file = "rpds_py-0.20.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:f918a1a130a6dfe1d7fe0f105064141342e7dd1611f2e6a21cd2f5c8cb1cfb3e"}, + {file = "rpds_py-0.20.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:f60012a73aa396be721558caa3a6fd49b3dd0033d1675c6d59c4502e870fcf0c"}, + {file = "rpds_py-0.20.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3d2b1ad682a3dfda2a4e8ad8572f3100f95fad98cb99faf37ff0ddfe9cbf9d03"}, + {file = "rpds_py-0.20.0-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:614fdafe9f5f19c63ea02817fa4861c606a59a604a77c8cdef5aa01d28b97921"}, + {file = "rpds_py-0.20.0-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fa518bcd7600c584bf42e6617ee8132869e877db2f76bcdc281ec6a4113a53ab"}, + {file = "rpds_py-0.20.0-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f0475242f447cc6cb8a9dd486d68b2ef7fbee84427124c232bff5f63b1fe11e5"}, + {file = "rpds_py-0.20.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f90a4cd061914a60bd51c68bcb4357086991bd0bb93d8aa66a6da7701370708f"}, + {file = "rpds_py-0.20.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:def7400461c3a3f26e49078302e1c1b38f6752342c77e3cf72ce91ca69fb1bc1"}, + {file = "rpds_py-0.20.0-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:65794e4048ee837494aea3c21a28ad5fc080994dfba5b036cf84de37f7ad5074"}, + {file = "rpds_py-0.20.0-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:faefcc78f53a88f3076b7f8be0a8f8d35133a3ecf7f3770895c25f8813460f08"}, + {file = "rpds_py-0.20.0-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:5b4f105deeffa28bbcdff6c49b34e74903139afa690e35d2d9e3c2c2fba18cec"}, + {file = "rpds_py-0.20.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:fdfc3a892927458d98f3d55428ae46b921d1f7543b89382fdb483f5640daaec8"}, + {file = "rpds_py-0.20.0.tar.gz", hash = "sha256:d72a210824facfdaf8768cf2d7ca25a042c30320b3020de2fa04640920d4e121"}, ] [[package]] @@ -2006,13 +2180,13 @@ files = [ [[package]] name = "starlette" -version = "0.37.2" +version = "0.40.0" description = "The little ASGI library that shines." optional = false python-versions = ">=3.8" files = [ - {file = "starlette-0.37.2-py3-none-any.whl", hash = "sha256:6fe59f29268538e5d0d182f2791a479a0c64638e6935d1c6989e63fb2699c6ee"}, - {file = "starlette-0.37.2.tar.gz", hash = "sha256:9af890290133b79fc3db55474ade20f6220a364a0402e0b556e7cd5e1e093823"}, + {file = "starlette-0.40.0-py3-none-any.whl", hash = "sha256:c494a22fae73805376ea6bf88439783ecfba9aac88a43911b48c653437e784c4"}, + {file = "starlette-0.40.0.tar.gz", hash = "sha256:1a3139688fb298ce5e2d661d37046a66ad996ce94be4d4983be019a23a04ea35"}, ] [package.dependencies] @@ -2023,51 +2197,48 @@ full = ["httpx (>=0.22.0)", "itsdangerous", "jinja2", "python-multipart (>=0.0.7 [[package]] name = "tomli" -version = "2.0.1" +version = "2.0.2" description = "A lil' TOML parser" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, - {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, + {file = "tomli-2.0.2-py3-none-any.whl", hash = "sha256:2ebe24485c53d303f690b0ec092806a085f07af5a5aa1464f3931eec36caaa38"}, + {file = "tomli-2.0.2.tar.gz", hash = "sha256:d46d457a85337051c36524bc5349dd91b1877838e2979ac5ced3e710ed8a60ed"}, ] [[package]] name = "tox" -version = "4.16.0" +version = "4.22.0" description = "tox is a generic virtualenv management and test command line tool" optional = false python-versions = ">=3.8" files = [ - {file = "tox-4.16.0-py3-none-any.whl", hash = "sha256:61e101061b977b46cf00093d4319438055290ad0009f84497a07bf2d2d7a06d0"}, - {file = "tox-4.16.0.tar.gz", hash = "sha256:43499656f9949edb681c0f907f86fbfee98677af9919d8b11ae5ad77cb800748"}, + {file = "tox-4.22.0-py3-none-any.whl", hash = "sha256:03734d9a9ac138cd1a898a372fb1b8079e2728618ae06dc37cbf3686cfb56eea"}, + {file = "tox-4.22.0.tar.gz", hash = "sha256:acc6c627cb3316585238d55d2b633e132fea1bdb01b9d93b56bce7caea6ae73d"}, ] [package.dependencies] -cachetools = ">=5.3.3" +cachetools = ">=5.5" chardet = ">=5.2" colorama = ">=0.4.6" -filelock = ">=3.15.4" +filelock = ">=3.16.1" packaging = ">=24.1" -platformdirs = ">=4.2.2" +platformdirs = ">=4.3.6" pluggy = ">=1.5" -pyproject-api = ">=1.7.1" +pyproject-api = ">=1.8" tomli = {version = ">=2.0.1", markers = "python_version < \"3.11\""} -virtualenv = ">=20.26.3" - -[package.extras] -docs = ["furo (>=2024.5.6)", "sphinx (>=7.3.7)", "sphinx-argparse-cli (>=1.16)", "sphinx-autodoc-typehints (>=2.2.2)", "sphinx-copybutton (>=0.5.2)", "sphinx-inline-tabs (>=2023.4.21)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.11)"] -testing = ["build[virtualenv] (>=1.2.1)", "covdefaults (>=2.3)", "detect-test-pollution (>=1.2)", "devpi-process (>=1)", "diff-cover (>=9.1)", "distlib (>=0.3.8)", "flaky (>=3.8.1)", "hatch-vcs (>=0.4)", "hatchling (>=1.25)", "psutil (>=6)", "pytest (>=8.2.2)", "pytest-cov (>=5)", "pytest-mock (>=3.14)", "pytest-xdist (>=3.6.1)", "re-assert (>=1.1)", "setuptools (>=70.2)", "time-machine (>=2.14.2)", "wheel (>=0.43)"] +typing-extensions = {version = ">=4.12.2", markers = "python_version < \"3.11\""} +virtualenv = ">=20.26.6" [[package]] name = "typer" -version = "0.12.3" +version = "0.12.5" description = "Typer, build great CLIs. Easy to code. Based on Python type hints." optional = false python-versions = ">=3.7" files = [ - {file = "typer-0.12.3-py3-none-any.whl", hash = "sha256:070d7ca53f785acbccba8e7d28b08dcd88f79f1fbda035ade0aecec71ca5c914"}, - {file = "typer-0.12.3.tar.gz", hash = "sha256:49e73131481d804288ef62598d97a1ceef3058905aa536a1134f90891ba35482"}, + {file = "typer-0.12.5-py3-none-any.whl", hash = "sha256:62fe4e471711b147e3365034133904df3e235698399bc4de2b36c8579298d52b"}, + {file = "typer-0.12.5.tar.gz", hash = "sha256:f592f089bedcc8ec1b974125d64851029c3b1af145f04aca64d69410f0c9b722"}, ] [package.dependencies] @@ -2176,13 +2347,13 @@ files = [ [[package]] name = "urllib3" -version = "2.2.2" +version = "2.2.3" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = ">=3.8" files = [ - {file = "urllib3-2.2.2-py3-none-any.whl", hash = "sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472"}, - {file = "urllib3-2.2.2.tar.gz", hash = "sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168"}, + {file = "urllib3-2.2.3-py3-none-any.whl", hash = "sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac"}, + {file = "urllib3-2.2.3.tar.gz", hash = "sha256:e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9"}, ] [package.extras] @@ -2193,13 +2364,13 @@ zstd = ["zstandard (>=0.18.0)"] [[package]] name = "uvicorn" -version = "0.30.4" +version = "0.32.0" description = "The lightning-fast ASGI server." optional = false python-versions = ">=3.8" files = [ - {file = "uvicorn-0.30.4-py3-none-any.whl", hash = "sha256:06b00e3087e58c6865c284143c0c42f810b32ff4f265ab19d08c566f74a08728"}, - {file = "uvicorn-0.30.4.tar.gz", hash = "sha256:00db9a9e3711a5fa59866e2b02fac69d8dc70ce0814aaec9a66d1d9e5c832a30"}, + {file = "uvicorn-0.32.0-py3-none-any.whl", hash = "sha256:60b8f3a5ac027dcd31448f411ced12b5ef452c646f76f02f8cc3f25d8d26fd82"}, + {file = "uvicorn-0.32.0.tar.gz", hash = "sha256:f78b36b143c16f54ccdb8190d0a26b5f1901fe5a3c777e1ab29f26391af8551e"}, ] [package.dependencies] @@ -2219,57 +2390,64 @@ standard = ["colorama (>=0.4)", "httptools (>=0.5.0)", "python-dotenv (>=0.13)", [[package]] name = "uvloop" -version = "0.19.0" +version = "0.21.0" description = "Fast implementation of asyncio event loop on top of libuv" optional = false python-versions = ">=3.8.0" files = [ - {file = "uvloop-0.19.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:de4313d7f575474c8f5a12e163f6d89c0a878bc49219641d49e6f1444369a90e"}, - {file = "uvloop-0.19.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5588bd21cf1fcf06bded085f37e43ce0e00424197e7c10e77afd4bbefffef428"}, - {file = "uvloop-0.19.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b1fd71c3843327f3bbc3237bedcdb6504fd50368ab3e04d0410e52ec293f5b8"}, - {file = "uvloop-0.19.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a05128d315e2912791de6088c34136bfcdd0c7cbc1cf85fd6fd1bb321b7c849"}, - {file = "uvloop-0.19.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:cd81bdc2b8219cb4b2556eea39d2e36bfa375a2dd021404f90a62e44efaaf957"}, - {file = "uvloop-0.19.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5f17766fb6da94135526273080f3455a112f82570b2ee5daa64d682387fe0dcd"}, - {file = "uvloop-0.19.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4ce6b0af8f2729a02a5d1575feacb2a94fc7b2e983868b009d51c9a9d2149bef"}, - {file = "uvloop-0.19.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:31e672bb38b45abc4f26e273be83b72a0d28d074d5b370fc4dcf4c4eb15417d2"}, - {file = "uvloop-0.19.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:570fc0ed613883d8d30ee40397b79207eedd2624891692471808a95069a007c1"}, - {file = "uvloop-0.19.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5138821e40b0c3e6c9478643b4660bd44372ae1e16a322b8fc07478f92684e24"}, - {file = "uvloop-0.19.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:91ab01c6cd00e39cde50173ba4ec68a1e578fee9279ba64f5221810a9e786533"}, - {file = "uvloop-0.19.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:47bf3e9312f63684efe283f7342afb414eea4d3011542155c7e625cd799c3b12"}, - {file = "uvloop-0.19.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:da8435a3bd498419ee8c13c34b89b5005130a476bda1d6ca8cfdde3de35cd650"}, - {file = "uvloop-0.19.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:02506dc23a5d90e04d4f65c7791e65cf44bd91b37f24cfc3ef6cf2aff05dc7ec"}, - {file = "uvloop-0.19.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2693049be9d36fef81741fddb3f441673ba12a34a704e7b4361efb75cf30befc"}, - {file = "uvloop-0.19.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7010271303961c6f0fe37731004335401eb9075a12680738731e9c92ddd96ad6"}, - {file = "uvloop-0.19.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:5daa304d2161d2918fa9a17d5635099a2f78ae5b5960e742b2fcfbb7aefaa593"}, - {file = "uvloop-0.19.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:7207272c9520203fea9b93843bb775d03e1cf88a80a936ce760f60bb5add92f3"}, - {file = "uvloop-0.19.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:78ab247f0b5671cc887c31d33f9b3abfb88d2614b84e4303f1a63b46c046c8bd"}, - {file = "uvloop-0.19.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:472d61143059c84947aa8bb74eabbace30d577a03a1805b77933d6bd13ddebbd"}, - {file = "uvloop-0.19.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45bf4c24c19fb8a50902ae37c5de50da81de4922af65baf760f7c0c42e1088be"}, - {file = "uvloop-0.19.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:271718e26b3e17906b28b67314c45d19106112067205119dddbd834c2b7ce797"}, - {file = "uvloop-0.19.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:34175c9fd2a4bc3adc1380e1261f60306344e3407c20a4d684fd5f3be010fa3d"}, - {file = "uvloop-0.19.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e27f100e1ff17f6feeb1f33968bc185bf8ce41ca557deee9d9bbbffeb72030b7"}, - {file = "uvloop-0.19.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:13dfdf492af0aa0a0edf66807d2b465607d11c4fa48f4a1fd41cbea5b18e8e8b"}, - {file = "uvloop-0.19.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6e3d4e85ac060e2342ff85e90d0c04157acb210b9ce508e784a944f852a40e67"}, - {file = "uvloop-0.19.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8ca4956c9ab567d87d59d49fa3704cf29e37109ad348f2d5223c9bf761a332e7"}, - {file = "uvloop-0.19.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f467a5fd23b4fc43ed86342641f3936a68ded707f4627622fa3f82a120e18256"}, - {file = "uvloop-0.19.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:492e2c32c2af3f971473bc22f086513cedfc66a130756145a931a90c3958cb17"}, - {file = "uvloop-0.19.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2df95fca285a9f5bfe730e51945ffe2fa71ccbfdde3b0da5772b4ee4f2e770d5"}, - {file = "uvloop-0.19.0.tar.gz", hash = "sha256:0246f4fd1bf2bf702e06b0d45ee91677ee5c31242f39aab4ea6fe0c51aedd0fd"}, + {file = "uvloop-0.21.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ec7e6b09a6fdded42403182ab6b832b71f4edaf7f37a9a0e371a01db5f0cb45f"}, + {file = "uvloop-0.21.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:196274f2adb9689a289ad7d65700d37df0c0930fd8e4e743fa4834e850d7719d"}, + {file = "uvloop-0.21.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f38b2e090258d051d68a5b14d1da7203a3c3677321cf32a95a6f4db4dd8b6f26"}, + {file = "uvloop-0.21.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87c43e0f13022b998eb9b973b5e97200c8b90823454d4bc06ab33829e09fb9bb"}, + {file = "uvloop-0.21.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:10d66943def5fcb6e7b37310eb6b5639fd2ccbc38df1177262b0640c3ca68c1f"}, + {file = "uvloop-0.21.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:67dd654b8ca23aed0a8e99010b4c34aca62f4b7fce88f39d452ed7622c94845c"}, + {file = "uvloop-0.21.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:c0f3fa6200b3108919f8bdabb9a7f87f20e7097ea3c543754cabc7d717d95cf8"}, + {file = "uvloop-0.21.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0878c2640cf341b269b7e128b1a5fed890adc4455513ca710d77d5e93aa6d6a0"}, + {file = "uvloop-0.21.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9fb766bb57b7388745d8bcc53a359b116b8a04c83a2288069809d2b3466c37e"}, + {file = "uvloop-0.21.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8a375441696e2eda1c43c44ccb66e04d61ceeffcd76e4929e527b7fa401b90fb"}, + {file = "uvloop-0.21.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:baa0e6291d91649c6ba4ed4b2f982f9fa165b5bbd50a9e203c416a2797bab3c6"}, + {file = "uvloop-0.21.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4509360fcc4c3bd2c70d87573ad472de40c13387f5fda8cb58350a1d7475e58d"}, + {file = "uvloop-0.21.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:359ec2c888397b9e592a889c4d72ba3d6befba8b2bb01743f72fffbde663b59c"}, + {file = "uvloop-0.21.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f7089d2dc73179ce5ac255bdf37c236a9f914b264825fdaacaded6990a7fb4c2"}, + {file = "uvloop-0.21.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:baa4dcdbd9ae0a372f2167a207cd98c9f9a1ea1188a8a526431eef2f8116cc8d"}, + {file = "uvloop-0.21.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86975dca1c773a2c9864f4c52c5a55631038e387b47eaf56210f873887b6c8dc"}, + {file = "uvloop-0.21.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:461d9ae6660fbbafedd07559c6a2e57cd553b34b0065b6550685f6653a98c1cb"}, + {file = "uvloop-0.21.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:183aef7c8730e54c9a3ee3227464daed66e37ba13040bb3f350bc2ddc040f22f"}, + {file = "uvloop-0.21.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:bfd55dfcc2a512316e65f16e503e9e450cab148ef11df4e4e679b5e8253a5281"}, + {file = "uvloop-0.21.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:787ae31ad8a2856fc4e7c095341cccc7209bd657d0e71ad0dc2ea83c4a6fa8af"}, + {file = "uvloop-0.21.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ee4d4ef48036ff6e5cfffb09dd192c7a5027153948d85b8da7ff705065bacc6"}, + {file = "uvloop-0.21.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3df876acd7ec037a3d005b3ab85a7e4110422e4d9c1571d4fc89b0fc41b6816"}, + {file = "uvloop-0.21.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bd53ecc9a0f3d87ab847503c2e1552b690362e005ab54e8a48ba97da3924c0dc"}, + {file = "uvloop-0.21.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a5c39f217ab3c663dc699c04cbd50c13813e31d917642d459fdcec07555cc553"}, + {file = "uvloop-0.21.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:17df489689befc72c39a08359efac29bbee8eee5209650d4b9f34df73d22e414"}, + {file = "uvloop-0.21.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bc09f0ff191e61c2d592a752423c767b4ebb2986daa9ed62908e2b1b9a9ae206"}, + {file = "uvloop-0.21.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f0ce1b49560b1d2d8a2977e3ba4afb2414fb46b86a1b64056bc4ab929efdafbe"}, + {file = "uvloop-0.21.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e678ad6fe52af2c58d2ae3c73dc85524ba8abe637f134bf3564ed07f555c5e79"}, + {file = "uvloop-0.21.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:460def4412e473896ef179a1671b40c039c7012184b627898eea5072ef6f017a"}, + {file = "uvloop-0.21.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:10da8046cc4a8f12c91a1c39d1dd1585c41162a15caaef165c2174db9ef18bdc"}, + {file = "uvloop-0.21.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c097078b8031190c934ed0ebfee8cc5f9ba9642e6eb88322b9958b649750f72b"}, + {file = "uvloop-0.21.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:46923b0b5ee7fc0020bef24afe7836cb068f5050ca04caf6b487c513dc1a20b2"}, + {file = "uvloop-0.21.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:53e420a3afe22cdcf2a0f4846e377d16e718bc70103d7088a4f7623567ba5fb0"}, + {file = "uvloop-0.21.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88cb67cdbc0e483da00af0b2c3cdad4b7c61ceb1ee0f33fe00e09c81e3a6cb75"}, + {file = "uvloop-0.21.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:221f4f2a1f46032b403bf3be628011caf75428ee3cc204a22addf96f586b19fd"}, + {file = "uvloop-0.21.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:2d1f581393673ce119355d56da84fe1dd9d2bb8b3d13ce792524e1607139feff"}, + {file = "uvloop-0.21.0.tar.gz", hash = "sha256:3bf12b0fda68447806a7ad847bfa591613177275d35b6724b1ee573faa3704e3"}, ] [package.extras] +dev = ["Cython (>=3.0,<4.0)", "setuptools (>=60)"] docs = ["Sphinx (>=4.1.2,<4.2.0)", "sphinx-rtd-theme (>=0.5.2,<0.6.0)", "sphinxcontrib-asyncio (>=0.3.0,<0.4.0)"] -test = ["Cython (>=0.29.36,<0.30.0)", "aiohttp (==3.9.0b0)", "aiohttp (>=3.8.1)", "flake8 (>=5.0,<6.0)", "mypy (>=0.800)", "psutil", "pyOpenSSL (>=23.0.0,<23.1.0)", "pycodestyle (>=2.9.0,<2.10.0)"] +test = ["aiohttp (>=3.10.5)", "flake8 (>=5.0,<6.0)", "mypy (>=0.800)", "psutil", "pyOpenSSL (>=23.0.0,<23.1.0)", "pycodestyle (>=2.9.0,<2.10.0)"] [[package]] name = "virtualenv" -version = "20.26.3" +version = "20.26.6" description = "Virtual Python Environment builder" optional = false python-versions = ">=3.7" files = [ - {file = "virtualenv-20.26.3-py3-none-any.whl", hash = "sha256:8cc4a31139e796e9a7de2cd5cf2489de1217193116a8fd42328f1bd65f434589"}, - {file = "virtualenv-20.26.3.tar.gz", hash = "sha256:4c43a2a236279d9ea36a0d76f98d84bd6ca94ac4e0f4a3b9d46d05e10fea542a"}, + {file = "virtualenv-20.26.6-py3-none-any.whl", hash = "sha256:7345cc5b25405607a624d8418154577459c3e0277f5466dd79c49d5e492995f2"}, + {file = "virtualenv-20.26.6.tar.gz", hash = "sha256:280aede09a2a5c317e409a00102e7077c6432c5a38f0ef938e643805a7ad2c48"}, ] [package.dependencies] @@ -2283,86 +2461,94 @@ test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess [[package]] name = "watchfiles" -version = "0.22.0" +version = "0.24.0" description = "Simple, modern and high performance file watching and code reload in python." optional = false python-versions = ">=3.8" files = [ - {file = "watchfiles-0.22.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:da1e0a8caebf17976e2ffd00fa15f258e14749db5e014660f53114b676e68538"}, - {file = "watchfiles-0.22.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:61af9efa0733dc4ca462347becb82e8ef4945aba5135b1638bfc20fad64d4f0e"}, - {file = "watchfiles-0.22.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d9188979a58a096b6f8090e816ccc3f255f137a009dd4bbec628e27696d67c1"}, - {file = "watchfiles-0.22.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2bdadf6b90c099ca079d468f976fd50062905d61fae183f769637cb0f68ba59a"}, - {file = "watchfiles-0.22.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:067dea90c43bf837d41e72e546196e674f68c23702d3ef80e4e816937b0a3ffd"}, - {file = "watchfiles-0.22.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bbf8a20266136507abf88b0df2328e6a9a7c7309e8daff124dda3803306a9fdb"}, - {file = "watchfiles-0.22.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1235c11510ea557fe21be5d0e354bae2c655a8ee6519c94617fe63e05bca4171"}, - {file = "watchfiles-0.22.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c2444dc7cb9d8cc5ab88ebe792a8d75709d96eeef47f4c8fccb6df7c7bc5be71"}, - {file = "watchfiles-0.22.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:c5af2347d17ab0bd59366db8752d9e037982e259cacb2ba06f2c41c08af02c39"}, - {file = "watchfiles-0.22.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:9624a68b96c878c10437199d9a8b7d7e542feddda8d5ecff58fdc8e67b460848"}, - {file = "watchfiles-0.22.0-cp310-none-win32.whl", hash = "sha256:4b9f2a128a32a2c273d63eb1fdbf49ad64852fc38d15b34eaa3f7ca2f0d2b797"}, - {file = "watchfiles-0.22.0-cp310-none-win_amd64.whl", hash = "sha256:2627a91e8110b8de2406d8b2474427c86f5a62bf7d9ab3654f541f319ef22bcb"}, - {file = "watchfiles-0.22.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:8c39987a1397a877217be1ac0fb1d8b9f662c6077b90ff3de2c05f235e6a8f96"}, - {file = "watchfiles-0.22.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a927b3034d0672f62fb2ef7ea3c9fc76d063c4b15ea852d1db2dc75fe2c09696"}, - {file = "watchfiles-0.22.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:052d668a167e9fc345c24203b104c313c86654dd6c0feb4b8a6dfc2462239249"}, - {file = "watchfiles-0.22.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5e45fb0d70dda1623a7045bd00c9e036e6f1f6a85e4ef2c8ae602b1dfadf7550"}, - {file = "watchfiles-0.22.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c49b76a78c156979759d759339fb62eb0549515acfe4fd18bb151cc07366629c"}, - {file = "watchfiles-0.22.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c4a65474fd2b4c63e2c18ac67a0c6c66b82f4e73e2e4d940f837ed3d2fd9d4da"}, - {file = "watchfiles-0.22.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1cc0cba54f47c660d9fa3218158b8963c517ed23bd9f45fe463f08262a4adae1"}, - {file = "watchfiles-0.22.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94ebe84a035993bb7668f58a0ebf998174fb723a39e4ef9fce95baabb42b787f"}, - {file = "watchfiles-0.22.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e0f0a874231e2839abbf473256efffe577d6ee2e3bfa5b540479e892e47c172d"}, - {file = "watchfiles-0.22.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:213792c2cd3150b903e6e7884d40660e0bcec4465e00563a5fc03f30ea9c166c"}, - {file = "watchfiles-0.22.0-cp311-none-win32.whl", hash = "sha256:b44b70850f0073b5fcc0b31ede8b4e736860d70e2dbf55701e05d3227a154a67"}, - {file = "watchfiles-0.22.0-cp311-none-win_amd64.whl", hash = "sha256:00f39592cdd124b4ec5ed0b1edfae091567c72c7da1487ae645426d1b0ffcad1"}, - {file = "watchfiles-0.22.0-cp311-none-win_arm64.whl", hash = "sha256:3218a6f908f6a276941422b035b511b6d0d8328edd89a53ae8c65be139073f84"}, - {file = "watchfiles-0.22.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:c7b978c384e29d6c7372209cbf421d82286a807bbcdeb315427687f8371c340a"}, - {file = "watchfiles-0.22.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:bd4c06100bce70a20c4b81e599e5886cf504c9532951df65ad1133e508bf20be"}, - {file = "watchfiles-0.22.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:425440e55cd735386ec7925f64d5dde392e69979d4c8459f6bb4e920210407f2"}, - {file = "watchfiles-0.22.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:68fe0c4d22332d7ce53ad094622b27e67440dacefbaedd29e0794d26e247280c"}, - {file = "watchfiles-0.22.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a8a31bfd98f846c3c284ba694c6365620b637debdd36e46e1859c897123aa232"}, - {file = "watchfiles-0.22.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dc2e8fe41f3cac0660197d95216c42910c2b7e9c70d48e6d84e22f577d106fc1"}, - {file = "watchfiles-0.22.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55b7cc10261c2786c41d9207193a85c1db1b725cf87936df40972aab466179b6"}, - {file = "watchfiles-0.22.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28585744c931576e535860eaf3f2c0ec7deb68e3b9c5a85ca566d69d36d8dd27"}, - {file = "watchfiles-0.22.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:00095dd368f73f8f1c3a7982a9801190cc88a2f3582dd395b289294f8975172b"}, - {file = "watchfiles-0.22.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:52fc9b0dbf54d43301a19b236b4a4614e610605f95e8c3f0f65c3a456ffd7d35"}, - {file = "watchfiles-0.22.0-cp312-none-win32.whl", hash = "sha256:581f0a051ba7bafd03e17127735d92f4d286af941dacf94bcf823b101366249e"}, - {file = "watchfiles-0.22.0-cp312-none-win_amd64.whl", hash = "sha256:aec83c3ba24c723eac14225194b862af176d52292d271c98820199110e31141e"}, - {file = "watchfiles-0.22.0-cp312-none-win_arm64.whl", hash = "sha256:c668228833c5619f6618699a2c12be057711b0ea6396aeaece4ded94184304ea"}, - {file = "watchfiles-0.22.0-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:d47e9ef1a94cc7a536039e46738e17cce058ac1593b2eccdede8bf72e45f372a"}, - {file = "watchfiles-0.22.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:28f393c1194b6eaadcdd8f941307fc9bbd7eb567995232c830f6aef38e8a6e88"}, - {file = "watchfiles-0.22.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd64f3a4db121bc161644c9e10a9acdb836853155a108c2446db2f5ae1778c3d"}, - {file = "watchfiles-0.22.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2abeb79209630da981f8ebca30a2c84b4c3516a214451bfc5f106723c5f45843"}, - {file = "watchfiles-0.22.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4cc382083afba7918e32d5ef12321421ef43d685b9a67cc452a6e6e18920890e"}, - {file = "watchfiles-0.22.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d048ad5d25b363ba1d19f92dcf29023988524bee6f9d952130b316c5802069cb"}, - {file = "watchfiles-0.22.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:103622865599f8082f03af4214eaff90e2426edff5e8522c8f9e93dc17caee13"}, - {file = "watchfiles-0.22.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d3e1f3cf81f1f823e7874ae563457828e940d75573c8fbf0ee66818c8b6a9099"}, - {file = "watchfiles-0.22.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8597b6f9dc410bdafc8bb362dac1cbc9b4684a8310e16b1ff5eee8725d13dcd6"}, - {file = "watchfiles-0.22.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:0b04a2cbc30e110303baa6d3ddce8ca3664bc3403be0f0ad513d1843a41c97d1"}, - {file = "watchfiles-0.22.0-cp38-none-win32.whl", hash = "sha256:b610fb5e27825b570554d01cec427b6620ce9bd21ff8ab775fc3a32f28bba63e"}, - {file = "watchfiles-0.22.0-cp38-none-win_amd64.whl", hash = "sha256:fe82d13461418ca5e5a808a9e40f79c1879351fcaeddbede094028e74d836e86"}, - {file = "watchfiles-0.22.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:3973145235a38f73c61474d56ad6199124e7488822f3a4fc97c72009751ae3b0"}, - {file = "watchfiles-0.22.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:280a4afbc607cdfc9571b9904b03a478fc9f08bbeec382d648181c695648202f"}, - {file = "watchfiles-0.22.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3a0d883351a34c01bd53cfa75cd0292e3f7e268bacf2f9e33af4ecede7e21d1d"}, - {file = "watchfiles-0.22.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9165bcab15f2b6d90eedc5c20a7f8a03156b3773e5fb06a790b54ccecdb73385"}, - {file = "watchfiles-0.22.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dc1b9b56f051209be458b87edb6856a449ad3f803315d87b2da4c93b43a6fe72"}, - {file = "watchfiles-0.22.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8dc1fc25a1dedf2dd952909c8e5cb210791e5f2d9bc5e0e8ebc28dd42fed7562"}, - {file = "watchfiles-0.22.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dc92d2d2706d2b862ce0568b24987eba51e17e14b79a1abcd2edc39e48e743c8"}, - {file = "watchfiles-0.22.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:97b94e14b88409c58cdf4a8eaf0e67dfd3ece7e9ce7140ea6ff48b0407a593ec"}, - {file = "watchfiles-0.22.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:96eec15e5ea7c0b6eb5bfffe990fc7c6bd833acf7e26704eb18387fb2f5fd087"}, - {file = "watchfiles-0.22.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:28324d6b28bcb8d7c1041648d7b63be07a16db5510bea923fc80b91a2a6cbed6"}, - {file = "watchfiles-0.22.0-cp39-none-win32.whl", hash = "sha256:8c3e3675e6e39dc59b8fe5c914a19d30029e36e9f99468dddffd432d8a7b1c93"}, - {file = "watchfiles-0.22.0-cp39-none-win_amd64.whl", hash = "sha256:25c817ff2a86bc3de3ed2df1703e3d24ce03479b27bb4527c57e722f8554d971"}, - {file = "watchfiles-0.22.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b810a2c7878cbdecca12feae2c2ae8af59bea016a78bc353c184fa1e09f76b68"}, - {file = "watchfiles-0.22.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:f7e1f9c5d1160d03b93fc4b68a0aeb82fe25563e12fbcdc8507f8434ab6f823c"}, - {file = "watchfiles-0.22.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:030bc4e68d14bcad2294ff68c1ed87215fbd9a10d9dea74e7cfe8a17869785ab"}, - {file = "watchfiles-0.22.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ace7d060432acde5532e26863e897ee684780337afb775107c0a90ae8dbccfd2"}, - {file = "watchfiles-0.22.0-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5834e1f8b71476a26df97d121c0c0ed3549d869124ed2433e02491553cb468c2"}, - {file = "watchfiles-0.22.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:0bc3b2f93a140df6806c8467c7f51ed5e55a931b031b5c2d7ff6132292e803d6"}, - {file = "watchfiles-0.22.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8fdebb655bb1ba0122402352b0a4254812717a017d2dc49372a1d47e24073795"}, - {file = "watchfiles-0.22.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c8e0aa0e8cc2a43561e0184c0513e291ca891db13a269d8d47cb9841ced7c71"}, - {file = "watchfiles-0.22.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:2f350cbaa4bb812314af5dab0eb8d538481e2e2279472890864547f3fe2281ed"}, - {file = "watchfiles-0.22.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:7a74436c415843af2a769b36bf043b6ccbc0f8d784814ba3d42fc961cdb0a9dc"}, - {file = "watchfiles-0.22.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:00ad0bcd399503a84cc688590cdffbe7a991691314dde5b57b3ed50a41319a31"}, - {file = "watchfiles-0.22.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72a44e9481afc7a5ee3291b09c419abab93b7e9c306c9ef9108cb76728ca58d2"}, - {file = "watchfiles-0.22.0.tar.gz", hash = "sha256:988e981aaab4f3955209e7e28c7794acdb690be1efa7f16f8ea5aba7ffdadacb"}, + {file = "watchfiles-0.24.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:083dc77dbdeef09fa44bb0f4d1df571d2e12d8a8f985dccde71ac3ac9ac067a0"}, + {file = "watchfiles-0.24.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e94e98c7cb94cfa6e071d401ea3342767f28eb5a06a58fafdc0d2a4974f4f35c"}, + {file = "watchfiles-0.24.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82ae557a8c037c42a6ef26c494d0631cacca040934b101d001100ed93d43f361"}, + {file = "watchfiles-0.24.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:acbfa31e315a8f14fe33e3542cbcafc55703b8f5dcbb7c1eecd30f141df50db3"}, + {file = "watchfiles-0.24.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b74fdffce9dfcf2dc296dec8743e5b0332d15df19ae464f0e249aa871fc1c571"}, + {file = "watchfiles-0.24.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:449f43f49c8ddca87c6b3980c9284cab6bd1f5c9d9a2b00012adaaccd5e7decd"}, + {file = "watchfiles-0.24.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4abf4ad269856618f82dee296ac66b0cd1d71450fc3c98532d93798e73399b7a"}, + {file = "watchfiles-0.24.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f895d785eb6164678ff4bb5cc60c5996b3ee6df3edb28dcdeba86a13ea0465e"}, + {file = "watchfiles-0.24.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7ae3e208b31be8ce7f4c2c0034f33406dd24fbce3467f77223d10cd86778471c"}, + {file = "watchfiles-0.24.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:2efec17819b0046dde35d13fb8ac7a3ad877af41ae4640f4109d9154ed30a188"}, + {file = "watchfiles-0.24.0-cp310-none-win32.whl", hash = "sha256:6bdcfa3cd6fdbdd1a068a52820f46a815401cbc2cb187dd006cb076675e7b735"}, + {file = "watchfiles-0.24.0-cp310-none-win_amd64.whl", hash = "sha256:54ca90a9ae6597ae6dc00e7ed0a040ef723f84ec517d3e7ce13e63e4bc82fa04"}, + {file = "watchfiles-0.24.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:bdcd5538e27f188dd3c804b4a8d5f52a7fc7f87e7fd6b374b8e36a4ca03db428"}, + {file = "watchfiles-0.24.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2dadf8a8014fde6addfd3c379e6ed1a981c8f0a48292d662e27cabfe4239c83c"}, + {file = "watchfiles-0.24.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6509ed3f467b79d95fc62a98229f79b1a60d1b93f101e1c61d10c95a46a84f43"}, + {file = "watchfiles-0.24.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8360f7314a070c30e4c976b183d1d8d1585a4a50c5cb603f431cebcbb4f66327"}, + {file = "watchfiles-0.24.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:316449aefacf40147a9efaf3bd7c9bdd35aaba9ac5d708bd1eb5763c9a02bef5"}, + {file = "watchfiles-0.24.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:73bde715f940bea845a95247ea3e5eb17769ba1010efdc938ffcb967c634fa61"}, + {file = "watchfiles-0.24.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3770e260b18e7f4e576edca4c0a639f704088602e0bc921c5c2e721e3acb8d15"}, + {file = "watchfiles-0.24.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa0fd7248cf533c259e59dc593a60973a73e881162b1a2f73360547132742823"}, + {file = "watchfiles-0.24.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d7a2e3b7f5703ffbd500dabdefcbc9eafeff4b9444bbdd5d83d79eedf8428fab"}, + {file = "watchfiles-0.24.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d831ee0a50946d24a53821819b2327d5751b0c938b12c0653ea5be7dea9c82ec"}, + {file = "watchfiles-0.24.0-cp311-none-win32.whl", hash = "sha256:49d617df841a63b4445790a254013aea2120357ccacbed00253f9c2b5dc24e2d"}, + {file = "watchfiles-0.24.0-cp311-none-win_amd64.whl", hash = "sha256:d3dcb774e3568477275cc76554b5a565024b8ba3a0322f77c246bc7111c5bb9c"}, + {file = "watchfiles-0.24.0-cp311-none-win_arm64.whl", hash = "sha256:9301c689051a4857d5b10777da23fafb8e8e921bcf3abe6448a058d27fb67633"}, + {file = "watchfiles-0.24.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:7211b463695d1e995ca3feb38b69227e46dbd03947172585ecb0588f19b0d87a"}, + {file = "watchfiles-0.24.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4b8693502d1967b00f2fb82fc1e744df128ba22f530e15b763c8d82baee15370"}, + {file = "watchfiles-0.24.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cdab9555053399318b953a1fe1f586e945bc8d635ce9d05e617fd9fe3a4687d6"}, + {file = "watchfiles-0.24.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:34e19e56d68b0dad5cff62273107cf5d9fbaf9d75c46277aa5d803b3ef8a9e9b"}, + {file = "watchfiles-0.24.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:41face41f036fee09eba33a5b53a73e9a43d5cb2c53dad8e61fa6c9f91b5a51e"}, + {file = "watchfiles-0.24.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5148c2f1ea043db13ce9b0c28456e18ecc8f14f41325aa624314095b6aa2e9ea"}, + {file = "watchfiles-0.24.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7e4bd963a935aaf40b625c2499f3f4f6bbd0c3776f6d3bc7c853d04824ff1c9f"}, + {file = "watchfiles-0.24.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c79d7719d027b7a42817c5d96461a99b6a49979c143839fc37aa5748c322f234"}, + {file = "watchfiles-0.24.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:32aa53a9a63b7f01ed32e316e354e81e9da0e6267435c7243bf8ae0f10b428ef"}, + {file = "watchfiles-0.24.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ce72dba6a20e39a0c628258b5c308779b8697f7676c254a845715e2a1039b968"}, + {file = "watchfiles-0.24.0-cp312-none-win32.whl", hash = "sha256:d9018153cf57fc302a2a34cb7564870b859ed9a732d16b41a9b5cb2ebed2d444"}, + {file = "watchfiles-0.24.0-cp312-none-win_amd64.whl", hash = "sha256:551ec3ee2a3ac9cbcf48a4ec76e42c2ef938a7e905a35b42a1267fa4b1645896"}, + {file = "watchfiles-0.24.0-cp312-none-win_arm64.whl", hash = "sha256:b52a65e4ea43c6d149c5f8ddb0bef8d4a1e779b77591a458a893eb416624a418"}, + {file = "watchfiles-0.24.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:3d2e3ab79a1771c530233cadfd277fcc762656d50836c77abb2e5e72b88e3a48"}, + {file = "watchfiles-0.24.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:327763da824817b38ad125dcd97595f942d720d32d879f6c4ddf843e3da3fe90"}, + {file = "watchfiles-0.24.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd82010f8ab451dabe36054a1622870166a67cf3fce894f68895db6f74bbdc94"}, + {file = "watchfiles-0.24.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d64ba08db72e5dfd5c33be1e1e687d5e4fcce09219e8aee893a4862034081d4e"}, + {file = "watchfiles-0.24.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1cf1f6dd7825053f3d98f6d33f6464ebdd9ee95acd74ba2c34e183086900a827"}, + {file = "watchfiles-0.24.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:43e3e37c15a8b6fe00c1bce2473cfa8eb3484bbeecf3aefbf259227e487a03df"}, + {file = "watchfiles-0.24.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:88bcd4d0fe1d8ff43675360a72def210ebad3f3f72cabfeac08d825d2639b4ab"}, + {file = "watchfiles-0.24.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:999928c6434372fde16c8f27143d3e97201160b48a614071261701615a2a156f"}, + {file = "watchfiles-0.24.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:30bbd525c3262fd9f4b1865cb8d88e21161366561cd7c9e1194819e0a33ea86b"}, + {file = "watchfiles-0.24.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:edf71b01dec9f766fb285b73930f95f730bb0943500ba0566ae234b5c1618c18"}, + {file = "watchfiles-0.24.0-cp313-none-win32.whl", hash = "sha256:f4c96283fca3ee09fb044f02156d9570d156698bc3734252175a38f0e8975f07"}, + {file = "watchfiles-0.24.0-cp313-none-win_amd64.whl", hash = "sha256:a974231b4fdd1bb7f62064a0565a6b107d27d21d9acb50c484d2cdba515b9366"}, + {file = "watchfiles-0.24.0-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:ee82c98bed9d97cd2f53bdb035e619309a098ea53ce525833e26b93f673bc318"}, + {file = "watchfiles-0.24.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:fd92bbaa2ecdb7864b7600dcdb6f2f1db6e0346ed425fbd01085be04c63f0b05"}, + {file = "watchfiles-0.24.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f83df90191d67af5a831da3a33dd7628b02a95450e168785586ed51e6d28943c"}, + {file = "watchfiles-0.24.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fca9433a45f18b7c779d2bae7beeec4f740d28b788b117a48368d95a3233ed83"}, + {file = "watchfiles-0.24.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b995bfa6bf01a9e09b884077a6d37070464b529d8682d7691c2d3b540d357a0c"}, + {file = "watchfiles-0.24.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ed9aba6e01ff6f2e8285e5aa4154e2970068fe0fc0998c4380d0e6278222269b"}, + {file = "watchfiles-0.24.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e5171ef898299c657685306d8e1478a45e9303ddcd8ac5fed5bd52ad4ae0b69b"}, + {file = "watchfiles-0.24.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4933a508d2f78099162da473841c652ad0de892719043d3f07cc83b33dfd9d91"}, + {file = "watchfiles-0.24.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:95cf3b95ea665ab03f5a54765fa41abf0529dbaf372c3b83d91ad2cfa695779b"}, + {file = "watchfiles-0.24.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:01def80eb62bd5db99a798d5e1f5f940ca0a05986dcfae21d833af7a46f7ee22"}, + {file = "watchfiles-0.24.0-cp38-none-win32.whl", hash = "sha256:4d28cea3c976499475f5b7a2fec6b3a36208656963c1a856d328aeae056fc5c1"}, + {file = "watchfiles-0.24.0-cp38-none-win_amd64.whl", hash = "sha256:21ab23fdc1208086d99ad3f69c231ba265628014d4aed31d4e8746bd59e88cd1"}, + {file = "watchfiles-0.24.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:b665caeeda58625c3946ad7308fbd88a086ee51ccb706307e5b1fa91556ac886"}, + {file = "watchfiles-0.24.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5c51749f3e4e269231510da426ce4a44beb98db2dce9097225c338f815b05d4f"}, + {file = "watchfiles-0.24.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82b2509f08761f29a0fdad35f7e1638b8ab1adfa2666d41b794090361fb8b855"}, + {file = "watchfiles-0.24.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9a60e2bf9dc6afe7f743e7c9b149d1fdd6dbf35153c78fe3a14ae1a9aee3d98b"}, + {file = "watchfiles-0.24.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f7d9b87c4c55e3ea8881dfcbf6d61ea6775fffed1fedffaa60bd047d3c08c430"}, + {file = "watchfiles-0.24.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:78470906a6be5199524641f538bd2c56bb809cd4bf29a566a75051610bc982c3"}, + {file = "watchfiles-0.24.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:07cdef0c84c03375f4e24642ef8d8178e533596b229d32d2bbd69e5128ede02a"}, + {file = "watchfiles-0.24.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d337193bbf3e45171c8025e291530fb7548a93c45253897cd764a6a71c937ed9"}, + {file = "watchfiles-0.24.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ec39698c45b11d9694a1b635a70946a5bad066b593af863460a8e600f0dff1ca"}, + {file = "watchfiles-0.24.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2e28d91ef48eab0afb939fa446d8ebe77e2f7593f5f463fd2bb2b14132f95b6e"}, + {file = "watchfiles-0.24.0-cp39-none-win32.whl", hash = "sha256:7138eff8baa883aeaa074359daabb8b6c1e73ffe69d5accdc907d62e50b1c0da"}, + {file = "watchfiles-0.24.0-cp39-none-win_amd64.whl", hash = "sha256:b3ef2c69c655db63deb96b3c3e587084612f9b1fa983df5e0c3379d41307467f"}, + {file = "watchfiles-0.24.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:632676574429bee8c26be8af52af20e0c718cc7f5f67f3fb658c71928ccd4f7f"}, + {file = "watchfiles-0.24.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:a2a9891723a735d3e2540651184be6fd5b96880c08ffe1a98bae5017e65b544b"}, + {file = "watchfiles-0.24.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4a7fa2bc0efef3e209a8199fd111b8969fe9db9c711acc46636686331eda7dd4"}, + {file = "watchfiles-0.24.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:01550ccf1d0aed6ea375ef259706af76ad009ef5b0203a3a4cce0f6024f9b68a"}, + {file = "watchfiles-0.24.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:96619302d4374de5e2345b2b622dc481257a99431277662c30f606f3e22f42be"}, + {file = "watchfiles-0.24.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:85d5f0c7771dcc7a26c7a27145059b6bb0ce06e4e751ed76cdf123d7039b60b5"}, + {file = "watchfiles-0.24.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:951088d12d339690a92cef2ec5d3cfd957692834c72ffd570ea76a6790222777"}, + {file = "watchfiles-0.24.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49fb58bcaa343fedc6a9e91f90195b20ccb3135447dc9e4e2570c3a39565853e"}, + {file = "watchfiles-0.24.0.tar.gz", hash = "sha256:afb72325b74fa7a428c009c1b8be4b4d7c2afedafb2982827ef2156646df2fe1"}, ] [package.dependencies] @@ -2370,94 +2556,108 @@ anyio = ">=3.0.0" [[package]] name = "websockets" -version = "12.0" +version = "13.1" description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)" optional = false python-versions = ">=3.8" files = [ - {file = "websockets-12.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d554236b2a2006e0ce16315c16eaa0d628dab009c33b63ea03f41c6107958374"}, - {file = "websockets-12.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2d225bb6886591b1746b17c0573e29804619c8f755b5598d875bb4235ea639be"}, - {file = "websockets-12.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:eb809e816916a3b210bed3c82fb88eaf16e8afcf9c115ebb2bacede1797d2547"}, - {file = "websockets-12.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c588f6abc13f78a67044c6b1273a99e1cf31038ad51815b3b016ce699f0d75c2"}, - {file = "websockets-12.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5aa9348186d79a5f232115ed3fa9020eab66d6c3437d72f9d2c8ac0c6858c558"}, - {file = "websockets-12.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6350b14a40c95ddd53e775dbdbbbc59b124a5c8ecd6fbb09c2e52029f7a9f480"}, - {file = "websockets-12.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:70ec754cc2a769bcd218ed8d7209055667b30860ffecb8633a834dde27d6307c"}, - {file = "websockets-12.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6e96f5ed1b83a8ddb07909b45bd94833b0710f738115751cdaa9da1fb0cb66e8"}, - {file = "websockets-12.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4d87be612cbef86f994178d5186add3d94e9f31cc3cb499a0482b866ec477603"}, - {file = "websockets-12.0-cp310-cp310-win32.whl", hash = "sha256:befe90632d66caaf72e8b2ed4d7f02b348913813c8b0a32fae1cc5fe3730902f"}, - {file = "websockets-12.0-cp310-cp310-win_amd64.whl", hash = "sha256:363f57ca8bc8576195d0540c648aa58ac18cf85b76ad5202b9f976918f4219cf"}, - {file = "websockets-12.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:5d873c7de42dea355d73f170be0f23788cf3fa9f7bed718fd2830eefedce01b4"}, - {file = "websockets-12.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3f61726cae9f65b872502ff3c1496abc93ffbe31b278455c418492016e2afc8f"}, - {file = "websockets-12.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ed2fcf7a07334c77fc8a230755c2209223a7cc44fc27597729b8ef5425aa61a3"}, - {file = "websockets-12.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e332c210b14b57904869ca9f9bf4ca32f5427a03eeb625da9b616c85a3a506c"}, - {file = "websockets-12.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5693ef74233122f8ebab026817b1b37fe25c411ecfca084b29bc7d6efc548f45"}, - {file = "websockets-12.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e9e7db18b4539a29cc5ad8c8b252738a30e2b13f033c2d6e9d0549b45841c04"}, - {file = "websockets-12.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6e2df67b8014767d0f785baa98393725739287684b9f8d8a1001eb2839031447"}, - {file = "websockets-12.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:bea88d71630c5900690fcb03161ab18f8f244805c59e2e0dc4ffadae0a7ee0ca"}, - {file = "websockets-12.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:dff6cdf35e31d1315790149fee351f9e52978130cef6c87c4b6c9b3baf78bc53"}, - {file = "websockets-12.0-cp311-cp311-win32.whl", hash = "sha256:3e3aa8c468af01d70332a382350ee95f6986db479ce7af14d5e81ec52aa2b402"}, - {file = "websockets-12.0-cp311-cp311-win_amd64.whl", hash = "sha256:25eb766c8ad27da0f79420b2af4b85d29914ba0edf69f547cc4f06ca6f1d403b"}, - {file = "websockets-12.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0e6e2711d5a8e6e482cacb927a49a3d432345dfe7dea8ace7b5790df5932e4df"}, - {file = "websockets-12.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:dbcf72a37f0b3316e993e13ecf32f10c0e1259c28ffd0a85cee26e8549595fbc"}, - {file = "websockets-12.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:12743ab88ab2af1d17dd4acb4645677cb7063ef4db93abffbf164218a5d54c6b"}, - {file = "websockets-12.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b645f491f3c48d3f8a00d1fce07445fab7347fec54a3e65f0725d730d5b99cb"}, - {file = "websockets-12.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9893d1aa45a7f8b3bc4510f6ccf8db8c3b62120917af15e3de247f0780294b92"}, - {file = "websockets-12.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f38a7b376117ef7aff996e737583172bdf535932c9ca021746573bce40165ed"}, - {file = "websockets-12.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:f764ba54e33daf20e167915edc443b6f88956f37fb606449b4a5b10ba42235a5"}, - {file = "websockets-12.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:1e4b3f8ea6a9cfa8be8484c9221ec0257508e3a1ec43c36acdefb2a9c3b00aa2"}, - {file = "websockets-12.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:9fdf06fd06c32205a07e47328ab49c40fc1407cdec801d698a7c41167ea45113"}, - {file = "websockets-12.0-cp312-cp312-win32.whl", hash = "sha256:baa386875b70cbd81798fa9f71be689c1bf484f65fd6fb08d051a0ee4e79924d"}, - {file = "websockets-12.0-cp312-cp312-win_amd64.whl", hash = "sha256:ae0a5da8f35a5be197f328d4727dbcfafa53d1824fac3d96cdd3a642fe09394f"}, - {file = "websockets-12.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5f6ffe2c6598f7f7207eef9a1228b6f5c818f9f4d53ee920aacd35cec8110438"}, - {file = "websockets-12.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9edf3fc590cc2ec20dc9d7a45108b5bbaf21c0d89f9fd3fd1685e223771dc0b2"}, - {file = "websockets-12.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8572132c7be52632201a35f5e08348137f658e5ffd21f51f94572ca6c05ea81d"}, - {file = "websockets-12.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:604428d1b87edbf02b233e2c207d7d528460fa978f9e391bd8aaf9c8311de137"}, - {file = "websockets-12.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1a9d160fd080c6285e202327aba140fc9a0d910b09e423afff4ae5cbbf1c7205"}, - {file = "websockets-12.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87b4aafed34653e465eb77b7c93ef058516cb5acf3eb21e42f33928616172def"}, - {file = "websockets-12.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b2ee7288b85959797970114deae81ab41b731f19ebcd3bd499ae9ca0e3f1d2c8"}, - {file = "websockets-12.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:7fa3d25e81bfe6a89718e9791128398a50dec6d57faf23770787ff441d851967"}, - {file = "websockets-12.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:a571f035a47212288e3b3519944f6bf4ac7bc7553243e41eac50dd48552b6df7"}, - {file = "websockets-12.0-cp38-cp38-win32.whl", hash = "sha256:3c6cc1360c10c17463aadd29dd3af332d4a1adaa8796f6b0e9f9df1fdb0bad62"}, - {file = "websockets-12.0-cp38-cp38-win_amd64.whl", hash = "sha256:1bf386089178ea69d720f8db6199a0504a406209a0fc23e603b27b300fdd6892"}, - {file = "websockets-12.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:ab3d732ad50a4fbd04a4490ef08acd0517b6ae6b77eb967251f4c263011a990d"}, - {file = "websockets-12.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a1d9697f3337a89691e3bd8dc56dea45a6f6d975f92e7d5f773bc715c15dde28"}, - {file = "websockets-12.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1df2fbd2c8a98d38a66f5238484405b8d1d16f929bb7a33ed73e4801222a6f53"}, - {file = "websockets-12.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:23509452b3bc38e3a057382c2e941d5ac2e01e251acce7adc74011d7d8de434c"}, - {file = "websockets-12.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e5fc14ec6ea568200ea4ef46545073da81900a2b67b3e666f04adf53ad452ec"}, - {file = "websockets-12.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46e71dbbd12850224243f5d2aeec90f0aaa0f2dde5aeeb8fc8df21e04d99eff9"}, - {file = "websockets-12.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b81f90dcc6c85a9b7f29873beb56c94c85d6f0dac2ea8b60d995bd18bf3e2aae"}, - {file = "websockets-12.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:a02413bc474feda2849c59ed2dfb2cddb4cd3d2f03a2fedec51d6e959d9b608b"}, - {file = "websockets-12.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:bbe6013f9f791944ed31ca08b077e26249309639313fff132bfbf3ba105673b9"}, - {file = "websockets-12.0-cp39-cp39-win32.whl", hash = "sha256:cbe83a6bbdf207ff0541de01e11904827540aa069293696dd528a6640bd6a5f6"}, - {file = "websockets-12.0-cp39-cp39-win_amd64.whl", hash = "sha256:fc4e7fa5414512b481a2483775a8e8be7803a35b30ca805afa4998a84f9fd9e8"}, - {file = "websockets-12.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:248d8e2446e13c1d4326e0a6a4e9629cb13a11195051a73acf414812700badbd"}, - {file = "websockets-12.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f44069528d45a933997a6fef143030d8ca8042f0dfaad753e2906398290e2870"}, - {file = "websockets-12.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c4e37d36f0d19f0a4413d3e18c0d03d0c268ada2061868c1e6f5ab1a6d575077"}, - {file = "websockets-12.0-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d829f975fc2e527a3ef2f9c8f25e553eb7bc779c6665e8e1d52aa22800bb38b"}, - {file = "websockets-12.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:2c71bd45a777433dd9113847af751aae36e448bc6b8c361a566cb043eda6ec30"}, - {file = "websockets-12.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0bee75f400895aef54157b36ed6d3b308fcab62e5260703add87f44cee9c82a6"}, - {file = "websockets-12.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:423fc1ed29f7512fceb727e2d2aecb952c46aa34895e9ed96071821309951123"}, - {file = "websockets-12.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:27a5e9964ef509016759f2ef3f2c1e13f403725a5e6a1775555994966a66e931"}, - {file = "websockets-12.0-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c3181df4583c4d3994d31fb235dc681d2aaad744fbdbf94c4802485ececdecf2"}, - {file = "websockets-12.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:b067cb952ce8bf40115f6c19f478dc71c5e719b7fbaa511359795dfd9d1a6468"}, - {file = "websockets-12.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:00700340c6c7ab788f176d118775202aadea7602c5cc6be6ae127761c16d6b0b"}, - {file = "websockets-12.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e469d01137942849cff40517c97a30a93ae79917752b34029f0ec72df6b46399"}, - {file = "websockets-12.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffefa1374cd508d633646d51a8e9277763a9b78ae71324183693959cf94635a7"}, - {file = "websockets-12.0-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba0cab91b3956dfa9f512147860783a1829a8d905ee218a9837c18f683239611"}, - {file = "websockets-12.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2cb388a5bfb56df4d9a406783b7f9dbefb888c09b71629351cc6b036e9259370"}, - {file = "websockets-12.0-py3-none-any.whl", hash = "sha256:dc284bbc8d7c78a6c69e0c7325ab46ee5e40bb4d50e494d8131a07ef47500e9e"}, - {file = "websockets-12.0.tar.gz", hash = "sha256:81df9cbcbb6c260de1e007e58c011bfebe2dafc8435107b0537f393dd38c8b1b"}, + {file = "websockets-13.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f48c749857f8fb598fb890a75f540e3221d0976ed0bf879cf3c7eef34151acee"}, + {file = "websockets-13.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c7e72ce6bda6fb9409cc1e8164dd41d7c91466fb599eb047cfda72fe758a34a7"}, + {file = "websockets-13.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f779498eeec470295a2b1a5d97aa1bc9814ecd25e1eb637bd9d1c73a327387f6"}, + {file = "websockets-13.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4676df3fe46956fbb0437d8800cd5f2b6d41143b6e7e842e60554398432cf29b"}, + {file = "websockets-13.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a7affedeb43a70351bb811dadf49493c9cfd1ed94c9c70095fd177e9cc1541fa"}, + {file = "websockets-13.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1971e62d2caa443e57588e1d82d15f663b29ff9dfe7446d9964a4b6f12c1e700"}, + {file = "websockets-13.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:5f2e75431f8dc4a47f31565a6e1355fb4f2ecaa99d6b89737527ea917066e26c"}, + {file = "websockets-13.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:58cf7e75dbf7e566088b07e36ea2e3e2bd5676e22216e4cad108d4df4a7402a0"}, + {file = "websockets-13.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c90d6dec6be2c7d03378a574de87af9b1efea77d0c52a8301dd831ece938452f"}, + {file = "websockets-13.1-cp310-cp310-win32.whl", hash = "sha256:730f42125ccb14602f455155084f978bd9e8e57e89b569b4d7f0f0c17a448ffe"}, + {file = "websockets-13.1-cp310-cp310-win_amd64.whl", hash = "sha256:5993260f483d05a9737073be197371940c01b257cc45ae3f1d5d7adb371b266a"}, + {file = "websockets-13.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:61fc0dfcda609cda0fc9fe7977694c0c59cf9d749fbb17f4e9483929e3c48a19"}, + {file = "websockets-13.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ceec59f59d092c5007e815def4ebb80c2de330e9588e101cf8bd94c143ec78a5"}, + {file = "websockets-13.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c1dca61c6db1166c48b95198c0b7d9c990b30c756fc2923cc66f68d17dc558fd"}, + {file = "websockets-13.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:308e20f22c2c77f3f39caca508e765f8725020b84aa963474e18c59accbf4c02"}, + {file = "websockets-13.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62d516c325e6540e8a57b94abefc3459d7dab8ce52ac75c96cad5549e187e3a7"}, + {file = "websockets-13.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87c6e35319b46b99e168eb98472d6c7d8634ee37750d7693656dc766395df096"}, + {file = "websockets-13.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:5f9fee94ebafbc3117c30be1844ed01a3b177bb6e39088bc6b2fa1dc15572084"}, + {file = "websockets-13.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:7c1e90228c2f5cdde263253fa5db63e6653f1c00e7ec64108065a0b9713fa1b3"}, + {file = "websockets-13.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6548f29b0e401eea2b967b2fdc1c7c7b5ebb3eeb470ed23a54cd45ef078a0db9"}, + {file = "websockets-13.1-cp311-cp311-win32.whl", hash = "sha256:c11d4d16e133f6df8916cc5b7e3e96ee4c44c936717d684a94f48f82edb7c92f"}, + {file = "websockets-13.1-cp311-cp311-win_amd64.whl", hash = "sha256:d04f13a1d75cb2b8382bdc16ae6fa58c97337253826dfe136195b7f89f661557"}, + {file = "websockets-13.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:9d75baf00138f80b48f1eac72ad1535aac0b6461265a0bcad391fc5aba875cfc"}, + {file = "websockets-13.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:9b6f347deb3dcfbfde1c20baa21c2ac0751afaa73e64e5b693bb2b848efeaa49"}, + {file = "websockets-13.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:de58647e3f9c42f13f90ac7e5f58900c80a39019848c5547bc691693098ae1bd"}, + {file = "websockets-13.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1b54689e38d1279a51d11e3467dd2f3a50f5f2e879012ce8f2d6943f00e83f0"}, + {file = "websockets-13.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cf1781ef73c073e6b0f90af841aaf98501f975d306bbf6221683dd594ccc52b6"}, + {file = "websockets-13.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d23b88b9388ed85c6faf0e74d8dec4f4d3baf3ecf20a65a47b836d56260d4b9"}, + {file = "websockets-13.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3c78383585f47ccb0fcf186dcb8a43f5438bd7d8f47d69e0b56f71bf431a0a68"}, + {file = "websockets-13.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:d6d300f8ec35c24025ceb9b9019ae9040c1ab2f01cddc2bcc0b518af31c75c14"}, + {file = "websockets-13.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a9dcaf8b0cc72a392760bb8755922c03e17a5a54e08cca58e8b74f6902b433cf"}, + {file = "websockets-13.1-cp312-cp312-win32.whl", hash = "sha256:2f85cf4f2a1ba8f602298a853cec8526c2ca42a9a4b947ec236eaedb8f2dc80c"}, + {file = "websockets-13.1-cp312-cp312-win_amd64.whl", hash = "sha256:38377f8b0cdeee97c552d20cf1865695fcd56aba155ad1b4ca8779a5b6ef4ac3"}, + {file = "websockets-13.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a9ab1e71d3d2e54a0aa646ab6d4eebfaa5f416fe78dfe4da2839525dc5d765c6"}, + {file = "websockets-13.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b9d7439d7fab4dce00570bb906875734df13d9faa4b48e261c440a5fec6d9708"}, + {file = "websockets-13.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:327b74e915cf13c5931334c61e1a41040e365d380f812513a255aa804b183418"}, + {file = "websockets-13.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:325b1ccdbf5e5725fdcb1b0e9ad4d2545056479d0eee392c291c1bf76206435a"}, + {file = "websockets-13.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:346bee67a65f189e0e33f520f253d5147ab76ae42493804319b5716e46dddf0f"}, + {file = "websockets-13.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:91a0fa841646320ec0d3accdff5b757b06e2e5c86ba32af2e0815c96c7a603c5"}, + {file = "websockets-13.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:18503d2c5f3943e93819238bf20df71982d193f73dcecd26c94514f417f6b135"}, + {file = "websockets-13.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:a9cd1af7e18e5221d2878378fbc287a14cd527fdd5939ed56a18df8a31136bb2"}, + {file = "websockets-13.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:70c5be9f416aa72aab7a2a76c90ae0a4fe2755c1816c153c1a2bcc3333ce4ce6"}, + {file = "websockets-13.1-cp313-cp313-win32.whl", hash = "sha256:624459daabeb310d3815b276c1adef475b3e6804abaf2d9d2c061c319f7f187d"}, + {file = "websockets-13.1-cp313-cp313-win_amd64.whl", hash = "sha256:c518e84bb59c2baae725accd355c8dc517b4a3ed8db88b4bc93c78dae2974bf2"}, + {file = "websockets-13.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:c7934fd0e920e70468e676fe7f1b7261c1efa0d6c037c6722278ca0228ad9d0d"}, + {file = "websockets-13.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:149e622dc48c10ccc3d2760e5f36753db9cacf3ad7bc7bbbfd7d9c819e286f23"}, + {file = "websockets-13.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a569eb1b05d72f9bce2ebd28a1ce2054311b66677fcd46cf36204ad23acead8c"}, + {file = "websockets-13.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:95df24ca1e1bd93bbca51d94dd049a984609687cb2fb08a7f2c56ac84e9816ea"}, + {file = "websockets-13.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d8dbb1bf0c0a4ae8b40bdc9be7f644e2f3fb4e8a9aca7145bfa510d4a374eeb7"}, + {file = "websockets-13.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:035233b7531fb92a76beefcbf479504db8c72eb3bff41da55aecce3a0f729e54"}, + {file = "websockets-13.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:e4450fc83a3df53dec45922b576e91e94f5578d06436871dce3a6be38e40f5db"}, + {file = "websockets-13.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:463e1c6ec853202dd3657f156123d6b4dad0c546ea2e2e38be2b3f7c5b8e7295"}, + {file = "websockets-13.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:6d6855bbe70119872c05107e38fbc7f96b1d8cb047d95c2c50869a46c65a8e96"}, + {file = "websockets-13.1-cp38-cp38-win32.whl", hash = "sha256:204e5107f43095012b00f1451374693267adbb832d29966a01ecc4ce1db26faf"}, + {file = "websockets-13.1-cp38-cp38-win_amd64.whl", hash = "sha256:485307243237328c022bc908b90e4457d0daa8b5cf4b3723fd3c4a8012fce4c6"}, + {file = "websockets-13.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:9b37c184f8b976f0c0a231a5f3d6efe10807d41ccbe4488df8c74174805eea7d"}, + {file = "websockets-13.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:163e7277e1a0bd9fb3c8842a71661ad19c6aa7bb3d6678dc7f89b17fbcc4aeb7"}, + {file = "websockets-13.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4b889dbd1342820cc210ba44307cf75ae5f2f96226c0038094455a96e64fb07a"}, + {file = "websockets-13.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:586a356928692c1fed0eca68b4d1c2cbbd1ca2acf2ac7e7ebd3b9052582deefa"}, + {file = "websockets-13.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7bd6abf1e070a6b72bfeb71049d6ad286852e285f146682bf30d0296f5fbadfa"}, + {file = "websockets-13.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d2aad13a200e5934f5a6767492fb07151e1de1d6079c003ab31e1823733ae79"}, + {file = "websockets-13.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:df01aea34b6e9e33572c35cd16bae5a47785e7d5c8cb2b54b2acdb9678315a17"}, + {file = "websockets-13.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:e54affdeb21026329fb0744ad187cf812f7d3c2aa702a5edb562b325191fcab6"}, + {file = "websockets-13.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:9ef8aa8bdbac47f4968a5d66462a2a0935d044bf35c0e5a8af152d58516dbeb5"}, + {file = "websockets-13.1-cp39-cp39-win32.whl", hash = "sha256:deeb929efe52bed518f6eb2ddc00cc496366a14c726005726ad62c2dd9017a3c"}, + {file = "websockets-13.1-cp39-cp39-win_amd64.whl", hash = "sha256:7c65ffa900e7cc958cd088b9a9157a8141c991f8c53d11087e6fb7277a03f81d"}, + {file = "websockets-13.1-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:5dd6da9bec02735931fccec99d97c29f47cc61f644264eb995ad6c0c27667238"}, + {file = "websockets-13.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:2510c09d8e8df777177ee3d40cd35450dc169a81e747455cc4197e63f7e7bfe5"}, + {file = "websockets-13.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f1c3cf67185543730888b20682fb186fc8d0fa6f07ccc3ef4390831ab4b388d9"}, + {file = "websockets-13.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bcc03c8b72267e97b49149e4863d57c2d77f13fae12066622dc78fe322490fe6"}, + {file = "websockets-13.1-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:004280a140f220c812e65f36944a9ca92d766b6cc4560be652a0a3883a79ed8a"}, + {file = "websockets-13.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:e2620453c075abeb0daa949a292e19f56de518988e079c36478bacf9546ced23"}, + {file = "websockets-13.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:9156c45750b37337f7b0b00e6248991a047be4aa44554c9886fe6bdd605aab3b"}, + {file = "websockets-13.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:80c421e07973a89fbdd93e6f2003c17d20b69010458d3a8e37fb47874bd67d51"}, + {file = "websockets-13.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82d0ba76371769d6a4e56f7e83bb8e81846d17a6190971e38b5de108bde9b0d7"}, + {file = "websockets-13.1-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e9875a0143f07d74dc5e1ded1c4581f0d9f7ab86c78994e2ed9e95050073c94d"}, + {file = "websockets-13.1-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a11e38ad8922c7961447f35c7b17bffa15de4d17c70abd07bfbe12d6faa3e027"}, + {file = "websockets-13.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:4059f790b6ae8768471cddb65d3c4fe4792b0ab48e154c9f0a04cefaabcd5978"}, + {file = "websockets-13.1-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:25c35bf84bf7c7369d247f0b8cfa157f989862c49104c5cf85cb5436a641d93e"}, + {file = "websockets-13.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:83f91d8a9bb404b8c2c41a707ac7f7f75b9442a0a876df295de27251a856ad09"}, + {file = "websockets-13.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7a43cfdcddd07f4ca2b1afb459824dd3c6d53a51410636a2c7fc97b9a8cf4842"}, + {file = "websockets-13.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:48a2ef1381632a2f0cb4efeff34efa97901c9fbc118e01951ad7cfc10601a9bb"}, + {file = "websockets-13.1-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:459bf774c754c35dbb487360b12c5727adab887f1622b8aed5755880a21c4a20"}, + {file = "websockets-13.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:95858ca14a9f6fa8413d29e0a585b31b278388aa775b8a81fa24830123874678"}, + {file = "websockets-13.1-py3-none-any.whl", hash = "sha256:a9a396a6ad26130cdae92ae10c36af09d9bfe6cafe69670fd3b6da9b07b4044f"}, + {file = "websockets-13.1.tar.gz", hash = "sha256:a3b3366087c1bc0a2795111edcadddb8b3b59509d5db5d7ea3fdd69f954a8878"}, ] [[package]] name = "werkzeug" -version = "3.0.3" +version = "3.0.4" description = "The comprehensive WSGI web application library." optional = false python-versions = ">=3.8" files = [ - {file = "werkzeug-3.0.3-py3-none-any.whl", hash = "sha256:fc9645dc43e03e4d630d23143a04a7f947a9a3b5727cd535fdfe155a17cc48c8"}, - {file = "werkzeug-3.0.3.tar.gz", hash = "sha256:097e5bfda9f0aba8da6b8545146def481d06aa7d3266e7448e2cccf67dd8bd18"}, + {file = "werkzeug-3.0.4-py3-none-any.whl", hash = "sha256:02c9eb92b7d6c06f31a782811505d2157837cea66aaede3e217c7c27c039476c"}, + {file = "werkzeug-3.0.4.tar.gz", hash = "sha256:34f2371506b250df4d4f84bfe7b0921e4762525762bbd936614909fe25cd7306"}, ] [package.dependencies] @@ -2468,108 +2668,101 @@ watchdog = ["watchdog (>=2.3)"] [[package]] name = "yarl" -version = "1.9.4" +version = "1.15.3" description = "Yet another URL library" optional = false -python-versions = ">=3.7" -files = [ - {file = "yarl-1.9.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a8c1df72eb746f4136fe9a2e72b0c9dc1da1cbd23b5372f94b5820ff8ae30e0e"}, - {file = "yarl-1.9.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a3a6ed1d525bfb91b3fc9b690c5a21bb52de28c018530ad85093cc488bee2dd2"}, - {file = "yarl-1.9.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c38c9ddb6103ceae4e4498f9c08fac9b590c5c71b0370f98714768e22ac6fa66"}, - {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d9e09c9d74f4566e905a0b8fa668c58109f7624db96a2171f21747abc7524234"}, - {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8477c1ee4bd47c57d49621a062121c3023609f7a13b8a46953eb6c9716ca392"}, - {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d5ff2c858f5f6a42c2a8e751100f237c5e869cbde669a724f2062d4c4ef93551"}, - {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:357495293086c5b6d34ca9616a43d329317feab7917518bc97a08f9e55648455"}, - {file = "yarl-1.9.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54525ae423d7b7a8ee81ba189f131054defdb122cde31ff17477951464c1691c"}, - {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:801e9264d19643548651b9db361ce3287176671fb0117f96b5ac0ee1c3530d53"}, - {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e516dc8baf7b380e6c1c26792610230f37147bb754d6426462ab115a02944385"}, - {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:7d5aaac37d19b2904bb9dfe12cdb08c8443e7ba7d2852894ad448d4b8f442863"}, - {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:54beabb809ffcacbd9d28ac57b0db46e42a6e341a030293fb3185c409e626b8b"}, - {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bac8d525a8dbc2a1507ec731d2867025d11ceadcb4dd421423a5d42c56818541"}, - {file = "yarl-1.9.4-cp310-cp310-win32.whl", hash = "sha256:7855426dfbddac81896b6e533ebefc0af2f132d4a47340cee6d22cac7190022d"}, - {file = "yarl-1.9.4-cp310-cp310-win_amd64.whl", hash = "sha256:848cd2a1df56ddbffeb375535fb62c9d1645dde33ca4d51341378b3f5954429b"}, - {file = "yarl-1.9.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:35a2b9396879ce32754bd457d31a51ff0a9d426fd9e0e3c33394bf4b9036b099"}, - {file = "yarl-1.9.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4c7d56b293cc071e82532f70adcbd8b61909eec973ae9d2d1f9b233f3d943f2c"}, - {file = "yarl-1.9.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d8a1c6c0be645c745a081c192e747c5de06e944a0d21245f4cf7c05e457c36e0"}, - {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4b3c1ffe10069f655ea2d731808e76e0f452fc6c749bea04781daf18e6039525"}, - {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:549d19c84c55d11687ddbd47eeb348a89df9cb30e1993f1b128f4685cd0ebbf8"}, - {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7409f968456111140c1c95301cadf071bd30a81cbd7ab829169fb9e3d72eae9"}, - {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e23a6d84d9d1738dbc6e38167776107e63307dfc8ad108e580548d1f2c587f42"}, - {file = "yarl-1.9.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d8b889777de69897406c9fb0b76cdf2fd0f31267861ae7501d93003d55f54fbe"}, - {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:03caa9507d3d3c83bca08650678e25364e1843b484f19986a527630ca376ecce"}, - {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4e9035df8d0880b2f1c7f5031f33f69e071dfe72ee9310cfc76f7b605958ceb9"}, - {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:c0ec0ed476f77db9fb29bca17f0a8fcc7bc97ad4c6c1d8959c507decb22e8572"}, - {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:ee04010f26d5102399bd17f8df8bc38dc7ccd7701dc77f4a68c5b8d733406958"}, - {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:49a180c2e0743d5d6e0b4d1a9e5f633c62eca3f8a86ba5dd3c471060e352ca98"}, - {file = "yarl-1.9.4-cp311-cp311-win32.whl", hash = "sha256:81eb57278deb6098a5b62e88ad8281b2ba09f2f1147c4767522353eaa6260b31"}, - {file = "yarl-1.9.4-cp311-cp311-win_amd64.whl", hash = "sha256:d1d2532b340b692880261c15aee4dc94dd22ca5d61b9db9a8a361953d36410b1"}, - {file = "yarl-1.9.4-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0d2454f0aef65ea81037759be5ca9947539667eecebca092733b2eb43c965a81"}, - {file = "yarl-1.9.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:44d8ffbb9c06e5a7f529f38f53eda23e50d1ed33c6c869e01481d3fafa6b8142"}, - {file = "yarl-1.9.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:aaaea1e536f98754a6e5c56091baa1b6ce2f2700cc4a00b0d49eca8dea471074"}, - {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3777ce5536d17989c91696db1d459574e9a9bd37660ea7ee4d3344579bb6f129"}, - {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fc5fc1eeb029757349ad26bbc5880557389a03fa6ada41703db5e068881e5f2"}, - {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea65804b5dc88dacd4a40279af0cdadcfe74b3e5b4c897aa0d81cf86927fee78"}, - {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa102d6d280a5455ad6a0f9e6d769989638718e938a6a0a2ff3f4a7ff8c62cc4"}, - {file = "yarl-1.9.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09efe4615ada057ba2d30df871d2f668af661e971dfeedf0c159927d48bbeff0"}, - {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:008d3e808d03ef28542372d01057fd09168419cdc8f848efe2804f894ae03e51"}, - {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:6f5cb257bc2ec58f437da2b37a8cd48f666db96d47b8a3115c29f316313654ff"}, - {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:992f18e0ea248ee03b5a6e8b3b4738850ae7dbb172cc41c966462801cbf62cf7"}, - {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:0e9d124c191d5b881060a9e5060627694c3bdd1fe24c5eecc8d5d7d0eb6faabc"}, - {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3986b6f41ad22988e53d5778f91855dc0399b043fc8946d4f2e68af22ee9ff10"}, - {file = "yarl-1.9.4-cp312-cp312-win32.whl", hash = "sha256:4b21516d181cd77ebd06ce160ef8cc2a5e9ad35fb1c5930882baff5ac865eee7"}, - {file = "yarl-1.9.4-cp312-cp312-win_amd64.whl", hash = "sha256:a9bd00dc3bc395a662900f33f74feb3e757429e545d831eef5bb280252631984"}, - {file = "yarl-1.9.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:63b20738b5aac74e239622d2fe30df4fca4942a86e31bf47a81a0e94c14df94f"}, - {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7d7f7de27b8944f1fee2c26a88b4dabc2409d2fea7a9ed3df79b67277644e17"}, - {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c74018551e31269d56fab81a728f683667e7c28c04e807ba08f8c9e3bba32f14"}, - {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ca06675212f94e7a610e85ca36948bb8fc023e458dd6c63ef71abfd482481aa5"}, - {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5aef935237d60a51a62b86249839b51345f47564208c6ee615ed2a40878dccdd"}, - {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2b134fd795e2322b7684155b7855cc99409d10b2e408056db2b93b51a52accc7"}, - {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d25039a474c4c72a5ad4b52495056f843a7ff07b632c1b92ea9043a3d9950f6e"}, - {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f7d6b36dd2e029b6bcb8a13cf19664c7b8e19ab3a58e0fefbb5b8461447ed5ec"}, - {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:957b4774373cf6f709359e5c8c4a0af9f6d7875db657adb0feaf8d6cb3c3964c"}, - {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:d7eeb6d22331e2fd42fce928a81c697c9ee2d51400bd1a28803965883e13cead"}, - {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:6a962e04b8f91f8c4e5917e518d17958e3bdee71fd1d8b88cdce74dd0ebbf434"}, - {file = "yarl-1.9.4-cp37-cp37m-win32.whl", hash = "sha256:f3bc6af6e2b8f92eced34ef6a96ffb248e863af20ef4fde9448cc8c9b858b749"}, - {file = "yarl-1.9.4-cp37-cp37m-win_amd64.whl", hash = "sha256:ad4d7a90a92e528aadf4965d685c17dacff3df282db1121136c382dc0b6014d2"}, - {file = "yarl-1.9.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ec61d826d80fc293ed46c9dd26995921e3a82146feacd952ef0757236fc137be"}, - {file = "yarl-1.9.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8be9e837ea9113676e5754b43b940b50cce76d9ed7d2461df1af39a8ee674d9f"}, - {file = "yarl-1.9.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:bef596fdaa8f26e3d66af846bbe77057237cb6e8efff8cd7cc8dff9a62278bbf"}, - {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d47552b6e52c3319fede1b60b3de120fe83bde9b7bddad11a69fb0af7db32f1"}, - {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84fc30f71689d7fc9168b92788abc977dc8cefa806909565fc2951d02f6b7d57"}, - {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4aa9741085f635934f3a2583e16fcf62ba835719a8b2b28fb2917bb0537c1dfa"}, - {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:206a55215e6d05dbc6c98ce598a59e6fbd0c493e2de4ea6cc2f4934d5a18d130"}, - {file = "yarl-1.9.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07574b007ee20e5c375a8fe4a0789fad26db905f9813be0f9fef5a68080de559"}, - {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5a2e2433eb9344a163aced6a5f6c9222c0786e5a9e9cac2c89f0b28433f56e23"}, - {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:6ad6d10ed9b67a382b45f29ea028f92d25bc0bc1daf6c5b801b90b5aa70fb9ec"}, - {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:6fe79f998a4052d79e1c30eeb7d6c1c1056ad33300f682465e1b4e9b5a188b78"}, - {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a825ec844298c791fd28ed14ed1bffc56a98d15b8c58a20e0e08c1f5f2bea1be"}, - {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8619d6915b3b0b34420cf9b2bb6d81ef59d984cb0fde7544e9ece32b4b3043c3"}, - {file = "yarl-1.9.4-cp38-cp38-win32.whl", hash = "sha256:686a0c2f85f83463272ddffd4deb5e591c98aac1897d65e92319f729c320eece"}, - {file = "yarl-1.9.4-cp38-cp38-win_amd64.whl", hash = "sha256:a00862fb23195b6b8322f7d781b0dc1d82cb3bcac346d1e38689370cc1cc398b"}, - {file = "yarl-1.9.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:604f31d97fa493083ea21bd9b92c419012531c4e17ea6da0f65cacdcf5d0bd27"}, - {file = "yarl-1.9.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8a854227cf581330ffa2c4824d96e52ee621dd571078a252c25e3a3b3d94a1b1"}, - {file = "yarl-1.9.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ba6f52cbc7809cd8d74604cce9c14868306ae4aa0282016b641c661f981a6e91"}, - {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a6327976c7c2f4ee6816eff196e25385ccc02cb81427952414a64811037bbc8b"}, - {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8397a3817d7dcdd14bb266283cd1d6fc7264a48c186b986f32e86d86d35fbac5"}, - {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e0381b4ce23ff92f8170080c97678040fc5b08da85e9e292292aba67fdac6c34"}, - {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:23d32a2594cb5d565d358a92e151315d1b2268bc10f4610d098f96b147370136"}, - {file = "yarl-1.9.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ddb2a5c08a4eaaba605340fdee8fc08e406c56617566d9643ad8bf6852778fc7"}, - {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:26a1dc6285e03f3cc9e839a2da83bcbf31dcb0d004c72d0730e755b33466c30e"}, - {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:18580f672e44ce1238b82f7fb87d727c4a131f3a9d33a5e0e82b793362bf18b4"}, - {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:29e0f83f37610f173eb7e7b5562dd71467993495e568e708d99e9d1944f561ec"}, - {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:1f23e4fe1e8794f74b6027d7cf19dc25f8b63af1483d91d595d4a07eca1fb26c"}, - {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:db8e58b9d79200c76956cefd14d5c90af54416ff5353c5bfd7cbe58818e26ef0"}, - {file = "yarl-1.9.4-cp39-cp39-win32.whl", hash = "sha256:c7224cab95645c7ab53791022ae77a4509472613e839dab722a72abe5a684575"}, - {file = "yarl-1.9.4-cp39-cp39-win_amd64.whl", hash = "sha256:824d6c50492add5da9374875ce72db7a0733b29c2394890aef23d533106e2b15"}, - {file = "yarl-1.9.4-py3-none-any.whl", hash = "sha256:928cecb0ef9d5a7946eb6ff58417ad2fe9375762382f1bf5c55e61645f2c43ad"}, - {file = "yarl-1.9.4.tar.gz", hash = "sha256:566db86717cf8080b99b58b083b773a908ae40f06681e87e589a976faf8246bf"}, +python-versions = ">=3.9" +files = [ + {file = "yarl-1.15.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:14d6f07b7b4b3b8fba521904db58442281730b44318d6abb9908de79e2a4e4f4"}, + {file = "yarl-1.15.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:eacd9de9b5b8262818a2e1f88efbd8d523abc8453de238c5d2f6a91fa85032dd"}, + {file = "yarl-1.15.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5a63ed17af784da3de39b82adfd4f8404ad5ee2ec8f616b063f37da3e64e0521"}, + {file = "yarl-1.15.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b55cc82ba92c07af6ba619dcf70cc89f7b9626adefb87d251f80f2e77419f1da"}, + {file = "yarl-1.15.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:63ba82841ce315e4b5dc8b9345062638c74b1864d38172d0a0403e5a083b0950"}, + {file = "yarl-1.15.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:59dce412b2515de05ab2eb6aef19ad7f70857ad436cd65fc4276df007106fb42"}, + {file = "yarl-1.15.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e337737b8c9d837e5b4d9e906cc57ed7a639e16e515c8094509b17f556fdb642"}, + {file = "yarl-1.15.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2128315cdc517a45ceb72ec17b256a7940eeb4843c66834c203e7d6580c83405"}, + {file = "yarl-1.15.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:69c2d111e67a818e702ba957da8c8e62de916f5c1b3da043f744084c63f12d46"}, + {file = "yarl-1.15.3-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:d2a70e8bec768be7423d8d465858a3646b34257a20cc02fd92612f1b14931f50"}, + {file = "yarl-1.15.3-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:efe758958a7bffce68d91ade238df72667e1f18966ed7b1d3d390eead51a8903"}, + {file = "yarl-1.15.3-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:b765f19e23c29b68e4f8bbadd36f1da2333ba983d8da2d6518e5f0a7eb2579c2"}, + {file = "yarl-1.15.3-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:df494e5a79f2ef8f81f966f787e515760e639c6319a321c16198b379c256a157"}, + {file = "yarl-1.15.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:68b27a7d9fb0f145de608da2e45e37fd2397b00266f10487e557f769afa2842d"}, + {file = "yarl-1.15.3-cp310-cp310-win32.whl", hash = "sha256:6d1aba1f644d6e5e16edada31938c11b6c9c97e3bf065742a2c7740d38af0c19"}, + {file = "yarl-1.15.3-cp310-cp310-win_amd64.whl", hash = "sha256:925e72fc7a4222a5bf6d288876d5afacc8f833b49c4cca85f65089131ba25afa"}, + {file = "yarl-1.15.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:dbd4808a209b175b5ebbac24c4798dd7511c5ee522a16f2f0eac78c717dfcdfc"}, + {file = "yarl-1.15.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:20f8bdaf667386cea1a8f49cb69a85f90346656d750d3c1278be1dbc76601065"}, + {file = "yarl-1.15.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:adeac55335669a189189373c93d131ebfc2de3ec04f0d3aa7dff6661f83b89b6"}, + {file = "yarl-1.15.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:690d8f702945506b58c9c5834d586e8fd819b845fe6239ab16ebc64a92a6fd3d"}, + {file = "yarl-1.15.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:df7784a29b9689341c17d06d826e3b52ee59d6b6916177e4db0477be7aad5f72"}, + {file = "yarl-1.15.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:12c80ec2af97ff3e433699bcabc787ef34e7c08ec038a6e6a25fb81d7bb83607"}, + {file = "yarl-1.15.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:39533b927c665bcff7da80bf299218e4af12f3e2be27e9c456e29547bcefd631"}, + {file = "yarl-1.15.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:db32a5c2912db45e73f80107d178e30f5c48cf596762b3c60ddfebdd655385f0"}, + {file = "yarl-1.15.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:bde319602111e9acca3c4f87f4205b38ba6166004bf108de47553633f9a580fc"}, + {file = "yarl-1.15.3-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:493760c4ced954582db83c4760166992c016e1777ebc0f3ef1bb5eb60b2b5924"}, + {file = "yarl-1.15.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:d9cd73f7bff5079d87c2622aa418a75d5d3cdc944d3edb905c5dfc3235466eb0"}, + {file = "yarl-1.15.3-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:e924040582499f7514ec64691031504e6224b5ae7224216208fc2c94f8b13c89"}, + {file = "yarl-1.15.3-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:1c3e9ae98719fe180751b093d02dbcc33b78a37e861d0f2c9571720bd31555db"}, + {file = "yarl-1.15.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6f2911cae6dd012adaaf51494dad4cafb4284ad1f3b588df6ea3e3017e053750"}, + {file = "yarl-1.15.3-cp311-cp311-win32.whl", hash = "sha256:acdfe626607a245aedca35b211f9305a9e7a33349da525bf4ef3caaec8ef51cd"}, + {file = "yarl-1.15.3-cp311-cp311-win_amd64.whl", hash = "sha256:0ace3927502a9f90a868d62c66623703cf5096dcb586187266e9b964d8dd6c81"}, + {file = "yarl-1.15.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:decf9d76191bfe34835f1abd3fa8ebe8a9cd7e16300a5c7e82b18c0812bb22a2"}, + {file = "yarl-1.15.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ce65ed7ad7b6cbca06b0c011b170bd2b0bc56b0a740540e2713e5ac12d7b9b2e"}, + {file = "yarl-1.15.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3cf2b50352df8775591869aaa22c52b64d60376ba99c0802b42778fedc90b775"}, + {file = "yarl-1.15.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:32e8ebf0080ddd38ec05f8be940a3719e5fe1ab8bb6d2b3f6f8b89c9e34149aa"}, + {file = "yarl-1.15.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:05183fd49244517cb11c208d0ae128f2e8a85ddb7caf22ad8b0ffcdf5481fcb6"}, + {file = "yarl-1.15.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:46653b5fd29e63ffe63335da343829a2b00bb43b0bd9bb21240d3b42629629e2"}, + {file = "yarl-1.15.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b6316af233610b9868eda92cf68c016750cbf50085ac6c51faa17905ddd25605"}, + {file = "yarl-1.15.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5685ebc333c95b75be3a0a83a81b82b6411beee9585eaeb9e2e588ae8df23848"}, + {file = "yarl-1.15.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6da6f6c6ee5595658f21bb9d1ecd702f7a7f22f224ac063dfb595624aec4a2e0"}, + {file = "yarl-1.15.3-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:45c05b87a8494d9820ea1ac82118fd2f1d795d868e94766fe8ff670377bf6280"}, + {file = "yarl-1.15.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:04f930fcc940f96b8b29110c56882bcff8703f87a7b9354d3acf60ffded5a23d"}, + {file = "yarl-1.15.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:8df77742b403e71c5d62d22d150e6e35efd6096a15f2c7419815911c62225100"}, + {file = "yarl-1.15.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:f785d83ece0998e4ce4fadda22fa6c1ecc40e10f41617013a8726d2e9af0d98f"}, + {file = "yarl-1.15.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7794aade99be0d48b69bd5942acddfeff0de3d09c724d9abe4f19736708ef18f"}, + {file = "yarl-1.15.3-cp312-cp312-win32.whl", hash = "sha256:a3a98d70c667c957c7cd0b153d4cb5e45d43f5e2e23de73be6f7b5c883c01f72"}, + {file = "yarl-1.15.3-cp312-cp312-win_amd64.whl", hash = "sha256:90257bc627897a2c1d562efcd6a6b18887e9dacae795cad2367e8e16df47d966"}, + {file = "yarl-1.15.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:f94d8adfdec402ff97cecc243b310c01d571362ca87bcf8def8e15cb3aaac3ee"}, + {file = "yarl-1.15.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:d0328f798052a33803a77d0868c7f802e952127092c1738fc9e7bfcaac7207c5"}, + {file = "yarl-1.15.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f5f0a0691e39c2e7b5c0f23e6765fa6cb162dce99d9ab1897fdd0f7a4a38b6fb"}, + {file = "yarl-1.15.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:370f646d3654e196ddbf772a2d737fe4e1dd738267015b73ff6267ca592fd9d6"}, + {file = "yarl-1.15.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3487c57bc8f17f2586ae7fd0e77f65cd298d45b64d15f604bbb29f4cce0e7961"}, + {file = "yarl-1.15.3-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ef67989d480358482830dc3bc232709804f46a61e7e9841d3f0b1c13a4735b3b"}, + {file = "yarl-1.15.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b5ab6c64921802176f56c36aa67c5e6a8baf9557ec1662cb41ecdb5580b67eb9"}, + {file = "yarl-1.15.3-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cb474a06023d01ead9c072b2580c22b2691aa1cabdcc19c3171ab1fa6d8496e3"}, + {file = "yarl-1.15.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:92f9a45230d3aa8568c1d692ab27bf505a32dfe3b404721458fc374f411e8bd2"}, + {file = "yarl-1.15.3-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:24cad94cf2f46cc8e4b9cd44e4e8a84483536a6c54554960b02b10b5724ab122"}, + {file = "yarl-1.15.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:380f30073cbd9b740891bb56f44ee31f870e8721269b618ccc9913400936d9f6"}, + {file = "yarl-1.15.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:353306ba6f0218af1aefe4b9c8b3a0b81b209bc75d79357dac6aca70a7b09d6a"}, + {file = "yarl-1.15.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:fe03cea925d884b8f1157a7037df2f5b6a6478a64b78ee600832d8a9f044c83e"}, + {file = "yarl-1.15.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5c4cc1a438ac52562427330e33891f50a78ffd38d335abc64f93f201c83bdc82"}, + {file = "yarl-1.15.3-cp313-cp313-win32.whl", hash = "sha256:956975a3a1ce1f4537be22278d6a283b8bc74d77671f7f6469ab1e800f4e9b02"}, + {file = "yarl-1.15.3-cp313-cp313-win_amd64.whl", hash = "sha256:2e61b72cf15922a7a665299a6b6825bd9901d67ec3b9d3cf9b256dc1667c9bb1"}, + {file = "yarl-1.15.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:270fef2b335e60c91ee835c524445e2248af841c8b72f48769ed6c02fbff5873"}, + {file = "yarl-1.15.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:59b77f0682e1917be197fc8229530f0c6fb3ef8e242d8256ba091a3a1c0ef7e6"}, + {file = "yarl-1.15.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:cc4b999718287073dccd3acb0ef1593961bd7923af08991cb3c94080db503935"}, + {file = "yarl-1.15.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f9b251d3f90e125ff0d1f76257329a9190fa1bfd2157344c875580bff6dedc62"}, + {file = "yarl-1.15.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ccb4667e0c0a25815efbfe251d24b56624449a319d4bb497074dd49444fb306"}, + {file = "yarl-1.15.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ac26e43b56dbafb30256906bc763cc1f22e05825ae1ced4c6afbd0e6584f18de"}, + {file = "yarl-1.15.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2207491555af5dbbee4c3179a76766f7bc1ecff858f420ea96f2e105ca42c4dd"}, + {file = "yarl-1.15.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:14effa29db6113be065a594e13a0f45afb9c1e374fd22b4bc3a4eff0725184b2"}, + {file = "yarl-1.15.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:19077525cd36c797cae19262e15f2881da33c602fb35d075ff0e4263b51b8b88"}, + {file = "yarl-1.15.3-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:d80c019083506886df098b7bb0d844e19db7e226736829ef49f892ed0a070fa5"}, + {file = "yarl-1.15.3-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:c24debeec87908a864a2b4cb700f863db9441cabacdb22dc448c5d38b55c6f62"}, + {file = "yarl-1.15.3-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:1c49fe426c45520b4b8a48544d3a9a58194f39c1b57d92451883f847c299a137"}, + {file = "yarl-1.15.3-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:66ddcd7ee3264bc937860f4780290d60f6472ca0484c214fe805116a831121e8"}, + {file = "yarl-1.15.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:2a5cbbb06559757f091f9e71d3f76c27d4dfe0652cc3f17ccce398b8377bfda4"}, + {file = "yarl-1.15.3-cp39-cp39-win32.whl", hash = "sha256:d798de0b50efb66583fc096bcdaa852ed6ea3485a4eb610d6a634f8010d932f4"}, + {file = "yarl-1.15.3-cp39-cp39-win_amd64.whl", hash = "sha256:8f0b33fd088e93ba5f7f6dd55226630e7b78212752479c8fcc6abbd143b9c1ce"}, + {file = "yarl-1.15.3-py3-none-any.whl", hash = "sha256:a1d49ed6f4b812dde88e937d4c2bd3f13d72c23ef7de1e17a63b7cacef4b5691"}, + {file = "yarl-1.15.3.tar.gz", hash = "sha256:fbcff47f8ba82467f203037f7a30decf5c724211b224682f7236edb0dcbb5b95"}, ] [package.dependencies] idna = ">=2.0" multidict = ">=4.0" +propcache = ">=0.2.0" [metadata] lock-version = "2.0" python-versions = "^3.10.0" -content-hash = "a20f6ca06f9aca9773f27d9e2aeac44bccace9bdbd6e6ba889863927198579d6" +content-hash = "7a5c4f107fe125206eaca0e681af6b7673328f3f359f4bca6ee1e66a059bc250" diff --git a/pyproject.toml b/pyproject.toml index 5582d14..3bd696a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,9 +7,9 @@ readme = "README.md" [tool.poetry.dependencies] python = "^3.10.0" -fastapi = {extras = ["all"], version = "^0.111.1"} +fastapi = {extras = ["all"], version = "^0.115.0"} pydantic = "^2.6.1" -bento-lib = {extras = ["fastapi"], version = "^11.11.2"} +bento-lib = {extras = ["fastapi"], version = "^12.2.2"} jsonschema = "^4.21.1" pydantic-settings = "^2.1.0" asyncpg = "^0.29.0" diff --git a/transcriptomics_data_service/authz/middleware_mixin.py b/transcriptomics_data_service/authz/middleware_base.py similarity index 88% rename from transcriptomics_data_service/authz/middleware_mixin.py rename to transcriptomics_data_service/authz/middleware_base.py index 4c64d45..7140959 100644 --- a/transcriptomics_data_service/authz/middleware_mixin.py +++ b/transcriptomics_data_service/authz/middleware_base.py @@ -1,19 +1,16 @@ from fastapi import Depends, FastAPI, Request, Response, status from typing import Awaitable, Callable -from abc import ABC, abstractmethod -class BaseAuthzMiddleware(ABC): +class BaseAuthzMiddleware: - @abstractmethod def attach(self, app: FastAPI): """ Attaches itself to the TDS FastAPI app, all requests will go through the dispatch function. """ - # app.middleware("http")(self.dispatch) + raise NotImplemented() - @abstractmethod async def dispatch(self, request: Request, call_next: Callable[[Request], Awaitable[Response]]) -> Response: """ Defines the way requests are handled by the authorization middleware, if it is attached to the FastAPI app. @@ -29,22 +26,20 @@ async def dispatch(self, request: Request, call_next: Callable[[Request], Awaita - Raise and catch exception based on authorization results - Handle unauthorized responses """ - pass + raise NotImplemented() - @abstractmethod def dep_authorize_ingest(self): """ Authorization function for the /ingest endpoint. Returns an inner function as a dependency, which is """ - pass + raise NotImplemented() - @abstractmethod def dep_authorize_normalize(self): """ Endpoint: /normalize Authorizes the normalize endpoint """ - pass + raise NotImplemented() diff --git a/transcriptomics_data_service/authz/plugin.py b/transcriptomics_data_service/authz/plugin.py index 18f4db0..b004c25 100644 --- a/transcriptomics_data_service/authz/plugin.py +++ b/transcriptomics_data_service/authz/plugin.py @@ -2,7 +2,7 @@ from fastapi import Request -from transcriptomics_data_service.authz.middleware_mixin import BaseAuthzMiddleware +from transcriptomics_data_service.authz.middleware_base import BaseAuthzMiddleware from transcriptomics_data_service.config import get_config from transcriptomics_data_service.logger import get_logger diff --git a/transcriptomics_data_service/config.py b/transcriptomics_data_service/config.py index aac154a..d9aeb8e 100644 --- a/transcriptomics_data_service/config.py +++ b/transcriptomics_data_service/config.py @@ -1,4 +1,4 @@ -from bento_lib.config.pydantic import BentoBaseConfig +from bento_lib.config.pydantic import BentoFastAPIBaseConfig from fastapi import Depends from functools import lru_cache from typing import Annotated @@ -12,15 +12,12 @@ ] -class Config(BentoBaseConfig): +class Config(BentoFastAPIBaseConfig): service_id: str = f"{SERVICE_GROUP}:{SERVICE_ARTIFACT}" service_name: str = "Transcriptomics Data Service" service_description: str = "Transcriptomics data service for the Bento platform." service_url_base_path: str = "http://127.0.0.1:5000" # Base path to construct URIs from - service_docs_path: str = "/docs" - service_openapi_path: str = "/openapi.json" - database_uri: str = "postgres://localhost:5432" From 71e6d021cd54ff1a82d2df1356a53d1b52109380 Mon Sep 17 00:00:00 2001 From: Victor Rocheleau Date: Wed, 16 Oct 2024 13:25:30 -0400 Subject: [PATCH 04/31] rm readme line --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index a466d02..2ac1b70 100644 --- a/README.md +++ b/README.md @@ -63,8 +63,6 @@ If authorization is enabled and there is no file at `lib/authz.module.py`, an ex will not start. Furthermore, the content of the file must follow some implementation guidelines: -from transcriptomics_data_service.authz.middleware_base import BaseAuthzMiddleware - - You MUST declare a concrete class that extends [BaseAuthzMiddleware](./transcriptomics_data_service/authz/middleware_base.py) - In that class, you MUST implement the functions from BaseAuthzMiddleware with the expected signatures: - `attach`: used to attach the middleware to the FastAPI app From 3e82140655a1a27160f7ed3fddd28a91d5d25159 Mon Sep 17 00:00:00 2001 From: Victor Rocheleau Date: Wed, 16 Oct 2024 13:31:42 -0400 Subject: [PATCH 05/31] docs: authz plugin --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 2ac1b70..d8fb1b8 100644 --- a/README.md +++ b/README.md @@ -65,9 +65,10 @@ will not start. Furthermore, the content of the file must follow some implementation guidelines: - You MUST declare a concrete class that extends [BaseAuthzMiddleware](./transcriptomics_data_service/authz/middleware_base.py) - In that class, you MUST implement the functions from BaseAuthzMiddleware with the expected signatures: - - `attach`: used to attach the middleware to the FastAPI app - - `dipatch`: called for every request made to the API - - `dep_authorize_`: endpoint-specific, authz evaluation functions that should return an injectable function + - `attach`: used to attach the middleware to the FastAPI app. + - `dipatch`: called for every request made to the API. + - `dep_authorize_`: endpoint-specific, authz evaluation functions that should return an injectable function. +- Finally, the script should expose an instance of your concrete authz middleware, named `authz_middleware`. Looking at [bento.authz.module.py](./etc/bento.authz.module.py), we can see an implementation that is specific to Bento's authorization service and libraries. From 24d30aab00bb8481e4ef7a7406cab1590092148a Mon Sep 17 00:00:00 2001 From: Victor Rocheleau Date: Wed, 16 Oct 2024 13:34:55 -0400 Subject: [PATCH 06/31] rm unused imports --- etc/bento.authz.module.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/etc/bento.authz.module.py b/etc/bento.authz.module.py index 19211d4..7afb201 100644 --- a/etc/bento.authz.module.py +++ b/etc/bento.authz.module.py @@ -1,11 +1,6 @@ -from logging import Logger -from re import Pattern -from typing import Any, Awaitable, Callable, Coroutine -from fastapi import Depends, FastAPI, Request, Response from bento_lib.auth.middleware.fastapi import FastApiAuthMiddleware from bento_lib.auth.permissions import P_INGEST_DATA -from bento_lib.auth.resources import RESOURCE_EVERYTHING, build_resource -from starlette.middleware.base import BaseHTTPMiddleware +from bento_lib.auth.resources import RESOURCE_EVERYTHING from transcriptomics_data_service.config import get_config from transcriptomics_data_service.logger import get_logger @@ -33,4 +28,5 @@ def dep_authorize_normalize(self): permissions=frozenset({P_INGEST_DATA}), resource=RESOURCE_EVERYTHING ) + authz_middleware = CustomAuthzMiddleware.build_from_fastapi_pydantic_config(config, logger) From 6c71652c0dbffa0e635e49c4fcf59f02de81478a Mon Sep 17 00:00:00 2001 From: Victor Rocheleau Date: Wed, 16 Oct 2024 15:51:15 -0400 Subject: [PATCH 07/31] feat(authz): plugin dependencies for routers and fastapi app --- etc/bento.authz.module.py | 34 +++++++++--- etc/example.authz.module.py | 46 ++++++++++++++-- .../authz/middleware_base.py | 52 ++++++++++++++++--- transcriptomics_data_service/authz/plugin.py | 4 +- transcriptomics_data_service/main.py | 6 +-- .../routers/experiment_results.py | 7 +-- .../routers/expressions.py | 5 +- .../routers/ingest.py | 10 ++-- 8 files changed, 130 insertions(+), 34 deletions(-) diff --git a/etc/bento.authz.module.py b/etc/bento.authz.module.py index 7afb201..e7d1e27 100644 --- a/etc/bento.authz.module.py +++ b/etc/bento.authz.module.py @@ -1,5 +1,5 @@ from bento_lib.auth.middleware.fastapi import FastApiAuthMiddleware -from bento_lib.auth.permissions import P_INGEST_DATA +from bento_lib.auth.permissions import P_INGEST_DATA, P_DELETE_DATA, P_QUERY_DATA, Permission from bento_lib.auth.resources import RESOURCE_EVERYTHING from transcriptomics_data_service.config import get_config @@ -16,17 +16,35 @@ class CustomAuthzMiddleware(FastApiAuthMiddleware, BaseAuthzMiddleware): Essentialy a TDS wrapper for the bento_lib FastApiAuthMiddleware. """ - def dep_authorize_ingest(self): - # TODO authorize with propper permissions and resources + def _dep_perm_data_everything(self, permission: Permission): return self.dep_require_permissions_on_resource( - permissions=frozenset({P_INGEST_DATA}), resource=RESOURCE_EVERYTHING + permissions=frozenset({permission}), + resource=RESOURCE_EVERYTHING, + require_token=False, ) - def dep_authorize_normalize(self): + # INGESTION router paths + + def dep_authz_ingest(self): # TODO authorize with propper permissions and resources - return self.dep_require_permissions_on_resource( - permissions=frozenset({P_INGEST_DATA}), resource=RESOURCE_EVERYTHING - ) + return self._dep_perm_data_everything(P_INGEST_DATA) + + def dep_authz_normalize(self): + # TODO authorize with propper permissions and resources + return self._dep_perm_data_everything(P_INGEST_DATA) + + # EXPERIMENT RESULT router paths + + def dep_authz_get_experiment_result(self): + return self._dep_perm_data_everything(P_QUERY_DATA) + + def dep_authz_delete_experiment_result(self): + return self._dep_perm_data_everything(P_DELETE_DATA) + + # EXPRESSIONS router paths + + def dep_authz_expressions_list(self): + return self._dep_perm_data_everything(P_QUERY_DATA) authz_middleware = CustomAuthzMiddleware.build_from_fastapi_pydantic_config(config, logger) diff --git a/etc/example.authz.module.py b/etc/example.authz.module.py index 4fa0acd..103df80 100644 --- a/etc/example.authz.module.py +++ b/etc/example.authz.module.py @@ -1,5 +1,43 @@ -from fastapi import Depends, Request +from logging import Logger +from typing import Any, Awaitable, Callable, Coroutine +from fastapi import Depends, FastAPI, Request, Response +from starlette.responses import Response -async def get_current_user_authorization(request: Request): - print("****************** This is a dynamically imported module function") - return True +from transcriptomics_data_service.authz.middleware_base import BaseAuthzMiddleware +from transcriptomics_data_service.config import Config, get_config +from transcriptomics_data_service.logger import get_logger + +config = get_config() +logger = get_logger(config) + + +class ApiKeyAuthzMiddleware(BaseAuthzMiddleware): + """ + Concrete implementation of BaseAuthzMiddleware to authorize requests based on the provided API key. + """ + + def __init__(self, config: Config, logger: Logger) -> None: + super().__init__() + self.enabled = config.bento_authz_enabled + self.logger = logger + + def attach(self, app: FastAPI): + app.middleware("http")(self.dispatch) + + async def dispatch( + self, request: Request, call_next: Callable[[Request], Awaitable[Response]] + ) -> Coroutine[Any, Any, Response]: + if not self.enabled: + return await call_next(request) + + def dep_authz_ingest(self): + # TODO authorize with propper permissions and resources + pass + + def dep_authz_normalize(self): + # TODO authorize with propper permissions and resources + pass + + + +authz_middleware = ApiKeyAuthzMiddleware() diff --git a/transcriptomics_data_service/authz/middleware_base.py b/transcriptomics_data_service/authz/middleware_base.py index 7140959..2d54543 100644 --- a/transcriptomics_data_service/authz/middleware_base.py +++ b/transcriptomics_data_service/authz/middleware_base.py @@ -5,6 +5,8 @@ class BaseAuthzMiddleware: + # Middleware lifecycle functions + def attach(self, app: FastAPI): """ Attaches itself to the TDS FastAPI app, all requests will go through the dispatch function. @@ -28,18 +30,54 @@ async def dispatch(self, request: Request, call_next: Callable[[Request], Awaita """ raise NotImplemented() - def dep_authorize_ingest(self): + # Dependency injections + + def dep_app(self) -> None | list[Depends]: + """ + Specify a dependency to be added on ALL paths of the API. + Can be used to protect the application with an API key. """ - Authorization function for the /ingest endpoint. + return None - Returns an inner function as a dependency, which is + def dep_ingest_router(self) -> None | list[Depends]: """ - raise NotImplemented() + Specify a dependency to be added to the ingest router. + This dependency will apply on all the router's paths. + """ + return None - def dep_authorize_normalize(self): + def dep_expression_router(self) -> None | list[Depends]: """ - Endpoint: /normalize + Specify a dependency to be added to the expression_router. + This dependency will apply on all the router's paths. + """ + return None - Authorizes the normalize endpoint + def dep_experiment_result_router(self) -> None | list[Depends]: + """ + Specify a dependency to be added to the experiment_router. + This dependency will apply on all the router's paths. """ + return None + + # Endpoint specific dependency creators for authorization logic + + ###### INGEST router paths + + def dep_authz_ingest(self): + raise NotImplemented() + + def dep_authz_normalize(self): + raise NotImplemented() + + ###### EXPRESSIONS router paths + + def dep_authz_expressions_list(self): + raise NotImplemented() + + ###### EXPERIMENT RESULTS router paths + def dep_authz_delete_experiment_result(self): + raise NotImplemented() + + def dep_authz_get_experiment_result(self): raise NotImplemented() diff --git a/transcriptomics_data_service/authz/plugin.py b/transcriptomics_data_service/authz/plugin.py index b004c25..73a4508 100644 --- a/transcriptomics_data_service/authz/plugin.py +++ b/transcriptomics_data_service/authz/plugin.py @@ -6,7 +6,7 @@ from transcriptomics_data_service.config import get_config from transcriptomics_data_service.logger import get_logger -__all__ = ["authz_middleware"] +__all__ = ["authz_plugin"] def import_module_from_path(path): @@ -22,4 +22,4 @@ def import_module_from_path(path): authz_plugin_module = import_module_from_path(AUTHZ_MODULE_PATH) # Get the concrete authz middleware from the provided plugin module -authz_middleware: BaseAuthzMiddleware = authz_plugin_module.authz_middleware +authz_plugin: BaseAuthzMiddleware = authz_plugin_module.authz_middleware diff --git a/transcriptomics_data_service/main.py b/transcriptomics_data_service/main.py index a1e649d..6f6ce6b 100644 --- a/transcriptomics_data_service/main.py +++ b/transcriptomics_data_service/main.py @@ -6,7 +6,7 @@ from transcriptomics_data_service.routers.experiment_results import experiment_router from transcriptomics_data_service.routers.expressions import expression_router from transcriptomics_data_service.routers.ingest import ingest_router -from transcriptomics_data_service.authz.plugin import authz_middleware +from transcriptomics_data_service.authz.plugin import authz_plugin from . import __version__ from .config import get_config @@ -32,15 +32,15 @@ async def lifespan(_app: FastAPI): yield - app = BentoFastAPI( - authz_middleware=authz_middleware, + authz_middleware=authz_plugin, config=config_for_setup, logger=logger_for_setup, bento_extra_service_info=BENTO_SERVICE_INFO, service_type=SERVICE_TYPE, version=__version__, lifespan=lifespan, + dependencies=authz_plugin.dep_app() ) app.include_router(expression_router) diff --git a/transcriptomics_data_service/routers/experiment_results.py b/transcriptomics_data_service/routers/experiment_results.py index 094f7bd..d6a7f4e 100644 --- a/transcriptomics_data_service/routers/experiment_results.py +++ b/transcriptomics_data_service/routers/experiment_results.py @@ -1,17 +1,18 @@ from fastapi import APIRouter +from transcriptomics_data_service.authz.plugin import authz_plugin from transcriptomics_data_service.db import DatabaseDependency __all__ = ["experiment_router"] -experiment_router = APIRouter(prefix="/experiment") +experiment_router = APIRouter(prefix="/experiment", dependencies=authz_plugin.dep_experiment_result_router()) -@experiment_router.delete("/{experiment_result_id}") +@experiment_router.delete("/{experiment_result_id}", dependencies=[authz_plugin.dep_authz_delete_experiment_result()]) async def delete_experiment_result(db: DatabaseDependency, experiment_result_id: str): await db.delete_experiment_result(experiment_result_id) -@experiment_router.get("/{experiment_result_id}") +@experiment_router.get("/{experiment_result_id}", dependencies=[authz_plugin.dep_authz_get_experiment_result()]) async def get_experiment_result(db: DatabaseDependency, experiment_result_id: str): return await db.read_experiment_result(experiment_result_id) diff --git a/transcriptomics_data_service/routers/expressions.py b/transcriptomics_data_service/routers/expressions.py index b2d5feb..cc3a9c8 100644 --- a/transcriptomics_data_service/routers/expressions.py +++ b/transcriptomics_data_service/routers/expressions.py @@ -1,12 +1,13 @@ from fastapi import APIRouter, status +from transcriptomics_data_service.authz.plugin import authz_plugin from transcriptomics_data_service.db import DatabaseDependency __all__ = ["expression_router"] -expression_router = APIRouter(prefix="/expressions") +expression_router = APIRouter(prefix="/expressions", dependencies=authz_plugin.dep_expression_router()) -@expression_router.get("", status_code=status.HTTP_200_OK) +@expression_router.get("", status_code=status.HTTP_200_OK, dependencies=[authz_plugin.dep_authz_expressions_list()]) async def expressions_list(db: DatabaseDependency): return await db.fetch_expressions() diff --git a/transcriptomics_data_service/routers/ingest.py b/transcriptomics_data_service/routers/ingest.py index aac871b..1ebcacf 100644 --- a/transcriptomics_data_service/routers/ingest.py +++ b/transcriptomics_data_service/routers/ingest.py @@ -5,20 +5,20 @@ from transcriptomics_data_service.db import DatabaseDependency from transcriptomics_data_service.models import ExperimentResult, GeneExpression -from transcriptomics_data_service.authz.plugin import authz_middleware +from transcriptomics_data_service.authz.plugin import authz_plugin __all__ = ["ingest_router"] -ingest_router = APIRouter() +ingest_router = APIRouter(dependencies=authz_plugin.dep_ingest_router()) +# TODO make configurable? an argument? GENE_ID_KEY = "GeneID" - @ingest_router.post( "/ingest/{experiment_result_id}/assembly-name/{assembly_name}/assembly-id/{assembly_id}", status_code=status.HTTP_200_OK, # Injects the plugin authz middleware dep_authorize_ingest function - dependencies=[authz_middleware.dep_authorize_ingest()], + dependencies=[authz_plugin.dep_authz_ingest()], ) async def ingest( request: Request, @@ -57,7 +57,7 @@ async def ingest( @ingest_router.post( "/normalize/{experiment_result_id}", status_code=status.HTTP_200_OK, - dependencies=[authz_middleware.dep_authorize_normalize()], + dependencies=[authz_plugin.dep_authz_normalize()], ) async def normalize( db: DatabaseDependency, From c65d88a9d6cc3b5c9dd9fea28fba78fa763b2fd3 Mon Sep 17 00:00:00 2001 From: Victor Rocheleau Date: Wed, 16 Oct 2024 16:43:09 -0400 Subject: [PATCH 08/31] chore(authz): example api key authz plugin --- etc/example.authz.module.py | 63 ++++++++++++++++++++++++++++++++----- 1 file changed, 56 insertions(+), 7 deletions(-) diff --git a/etc/example.authz.module.py b/etc/example.authz.module.py index 103df80..b363396 100644 --- a/etc/example.authz.module.py +++ b/etc/example.authz.module.py @@ -1,6 +1,7 @@ from logging import Logger -from typing import Any, Awaitable, Callable, Coroutine -from fastapi import Depends, FastAPI, Request, Response +from typing import Annotated, Any, Awaitable, Callable, Coroutine +from fastapi import Depends, FastAPI, HTTPException, Header, Request, Response +from fastapi.responses import JSONResponse from starlette.responses import Response from transcriptomics_data_service.authz.middleware_base import BaseAuthzMiddleware @@ -10,6 +11,8 @@ config = get_config() logger = get_logger(config) +# The valid api key for authorization +API_KEY = "fake-super-secret-api-key" class ApiKeyAuthzMiddleware(BaseAuthzMiddleware): """ @@ -21,6 +24,8 @@ def __init__(self, config: Config, logger: Logger) -> None: self.enabled = config.bento_authz_enabled self.logger = logger + # Middleware lifecycle + def attach(self, app: FastAPI): app.middleware("http")(self.dispatch) @@ -29,15 +34,59 @@ async def dispatch( ) -> Coroutine[Any, Any, Response]: if not self.enabled: return await call_next(request) + + try: + res = await call_next(request) + except HTTPException as e: + # Catch exceptions raised by authz functions + self.logger.error(e) + return JSONResponse( + status_code=e.status_code, + content=e.detail + ) + + return res + + # API KEY authorization + def dep_app(self) -> None | list: + # Add an x_api_key Header + async def _inner(x_api_key: Annotated[str, Header()]): + return x_api_key + return [Depends(_inner)] + + def _dep_check_api_key(self): + # Checks if the API key header contains a valid API key + async def _inner(x_api_key: Annotated[str, Header()]): + if x_api_key != API_KEY: + raise HTTPException(status_code=403, detail="Unauthorized: invalid API key") + return Depends(_inner) + + # Authz logic: only check for valid API key def dep_authz_ingest(self): - # TODO authorize with propper permissions and resources - pass + return self._dep_check_api_key() def dep_authz_normalize(self): - # TODO authorize with propper permissions and resources - pass + return self._dep_check_api_key() + + def dep_authz_delete_experiment_result(self): + return self._dep_check_api_key() + + def dep_authz_expressions_list(self): + return self._dep_check_api_key() + + def dep_authz_get_experiment_result(self): + return self._dep_check_api_key() + # TODO figure these out with the way BentoFastAPI handles authz middleware + + def dep_public_endpoint(self): + # forces an API key authz on /service-info + return self._dep_check_api_key() + @staticmethod + def mark_authz_done(request: Request): + pass + -authz_middleware = ApiKeyAuthzMiddleware() +authz_middleware = ApiKeyAuthzMiddleware(config, logger) From a6c8377e3cef48c23ebe3140079afd12ab2ab95b Mon Sep 17 00:00:00 2001 From: Victor Rocheleau Date: Wed, 16 Oct 2024 17:50:15 -0400 Subject: [PATCH 09/31] typing and comments --- etc/bento.authz.module.py | 14 +++--- etc/example.authz.module.py | 46 +++++++++---------- .../authz/middleware_base.py | 32 ++++++++----- 3 files changed, 52 insertions(+), 40 deletions(-) diff --git a/etc/bento.authz.module.py b/etc/bento.authz.module.py index e7d1e27..8a9a0fe 100644 --- a/etc/bento.authz.module.py +++ b/etc/bento.authz.module.py @@ -9,28 +9,30 @@ config = get_config() logger = get_logger(config) +# TODO add Bento specific project/dataset ownership pattern to experiment_result_id -class CustomAuthzMiddleware(FastApiAuthMiddleware, BaseAuthzMiddleware): +class BentoAuthzMiddleware(FastApiAuthMiddleware, BaseAuthzMiddleware): """ Concrete implementation of BaseAuthzMiddleware to authorize with Bento's authorization service/model. - Essentialy a TDS wrapper for the bento_lib FastApiAuthMiddleware. + Extends the bento-lib FastApiAuthMiddleware, which includes all the middleware lifecycle and authorization logic. + + Notes: + - This middleware plugin will only work with a Bento authorization-service. + - TDS should be able to perform HTTP requests on the authz service url: `config.bento_authz_service_url` """ def _dep_perm_data_everything(self, permission: Permission): return self.dep_require_permissions_on_resource( permissions=frozenset({permission}), resource=RESOURCE_EVERYTHING, - require_token=False, ) # INGESTION router paths def dep_authz_ingest(self): - # TODO authorize with propper permissions and resources return self._dep_perm_data_everything(P_INGEST_DATA) def dep_authz_normalize(self): - # TODO authorize with propper permissions and resources return self._dep_perm_data_everything(P_INGEST_DATA) # EXPERIMENT RESULT router paths @@ -47,4 +49,4 @@ def dep_authz_expressions_list(self): return self._dep_perm_data_everything(P_QUERY_DATA) -authz_middleware = CustomAuthzMiddleware.build_from_fastapi_pydantic_config(config, logger) +authz_middleware = BentoAuthzMiddleware.build_from_fastapi_pydantic_config(config, logger) diff --git a/etc/example.authz.module.py b/etc/example.authz.module.py index b363396..1086b54 100644 --- a/etc/example.authz.module.py +++ b/etc/example.authz.module.py @@ -14,6 +14,7 @@ # The valid api key for authorization API_KEY = "fake-super-secret-api-key" + class ApiKeyAuthzMiddleware(BaseAuthzMiddleware): """ Concrete implementation of BaseAuthzMiddleware to authorize requests based on the provided API key. @@ -34,31 +35,40 @@ async def dispatch( ) -> Coroutine[Any, Any, Response]: if not self.enabled: return await call_next(request) - + try: res = await call_next(request) except HTTPException as e: # Catch exceptions raised by authz functions self.logger.error(e) - return JSONResponse( - status_code=e.status_code, - content=e.detail - ) - + return JSONResponse(status_code=e.status_code, content=e.detail) + return res # API KEY authorization - def dep_app(self) -> None | list: - # Add an x_api_key Header + def dep_app(self): + """ + API-level dependency injection + Injects a required header for the API key authz: x_api_key + OpenAPI automatically includes it on all paths. + """ + async def _inner(x_api_key: Annotated[str, Header()]): return x_api_key + return [Depends(_inner)] - + def _dep_check_api_key(self): - # Checks if the API key header contains a valid API key + """ + Dependency injection for the API key authorization. + The inner function checks the x_api_key header to validate the API key. + Raises an exception that should be caught and handled in the dispatch func. + """ + async def _inner(x_api_key: Annotated[str, Header()]): if x_api_key != API_KEY: raise HTTPException(status_code=403, detail="Unauthorized: invalid API key") + return Depends(_inner) # Authz logic: only check for valid API key @@ -68,25 +78,15 @@ def dep_authz_ingest(self): def dep_authz_normalize(self): return self._dep_check_api_key() - + def dep_authz_delete_experiment_result(self): return self._dep_check_api_key() - + def dep_authz_expressions_list(self): return self._dep_check_api_key() - - def dep_authz_get_experiment_result(self): - return self._dep_check_api_key() - - # TODO figure these out with the way BentoFastAPI handles authz middleware - def dep_public_endpoint(self): - # forces an API key authz on /service-info + def dep_authz_get_experiment_result(self): return self._dep_check_api_key() - - @staticmethod - def mark_authz_done(request: Request): - pass authz_middleware = ApiKeyAuthzMiddleware(config, logger) diff --git a/transcriptomics_data_service/authz/middleware_base.py b/transcriptomics_data_service/authz/middleware_base.py index 2d54543..421f5d2 100644 --- a/transcriptomics_data_service/authz/middleware_base.py +++ b/transcriptomics_data_service/authz/middleware_base.py @@ -1,6 +1,6 @@ from fastapi import Depends, FastAPI, Request, Response, status -from typing import Awaitable, Callable +from typing import Awaitable, Callable, Sequence class BaseAuthzMiddleware: @@ -32,52 +32,62 @@ async def dispatch(self, request: Request, call_next: Callable[[Request], Awaita # Dependency injections - def dep_app(self) -> None | list[Depends]: + def dep_public_endpoint(self) -> Depends: + """ + Dependency for public endpoints. + Used to set the /service-info dependencies. + Does nothing by default, override according to your needs. + """ + def _inner(): + pass + return Depends(_inner) + + def dep_app(self) -> None | Sequence[Depends]: """ Specify a dependency to be added on ALL paths of the API. Can be used to protect the application with an API key. """ return None - def dep_ingest_router(self) -> None | list[Depends]: + def dep_ingest_router(self) -> None | Sequence[Depends]: """ Specify a dependency to be added to the ingest router. This dependency will apply on all the router's paths. """ return None - def dep_expression_router(self) -> None | list[Depends]: + def dep_expression_router(self) -> None | Sequence[Depends]: """ Specify a dependency to be added to the expression_router. This dependency will apply on all the router's paths. """ return None - def dep_experiment_result_router(self) -> None | list[Depends]: + def dep_experiment_result_router(self) -> None | Sequence[Depends]: """ Specify a dependency to be added to the experiment_router. This dependency will apply on all the router's paths. """ return None - # Endpoint specific dependency creators for authorization logic + ###### Endpoint specific dependency creators for authorization logic ###### INGEST router paths - def dep_authz_ingest(self): + def dep_authz_ingest(self) -> Depends: raise NotImplemented() - def dep_authz_normalize(self): + def dep_authz_normalize(self) -> Depends: raise NotImplemented() ###### EXPRESSIONS router paths - def dep_authz_expressions_list(self): + def dep_authz_expressions_list(self) -> Depends: raise NotImplemented() ###### EXPERIMENT RESULTS router paths - def dep_authz_delete_experiment_result(self): + def dep_authz_delete_experiment_result(self) -> Depends: raise NotImplemented() - def dep_authz_get_experiment_result(self): + def dep_authz_get_experiment_result(self) -> Depends: raise NotImplemented() From a351ecc18de35bccaed3c1aeedd3f15cc7b6a02b Mon Sep 17 00:00:00 2001 From: Victor Rocheleau Date: Thu, 17 Oct 2024 17:03:19 -0400 Subject: [PATCH 10/31] chore: authz docs split --- README.md | 42 ++----------- docs/authz.md | 61 +++++++++++++++++++ .../authz/middleware_base.py | 2 +- 3 files changed, 66 insertions(+), 39 deletions(-) create mode 100644 docs/authz.md diff --git a/README.md b/README.md index d8fb1b8..05cfb65 100644 --- a/README.md +++ b/README.md @@ -38,45 +38,11 @@ You can then attach VS Code to the `tds` container, and use the preconfigured `P ## Authorization plugin -Although TDS is part of the Bento platform, it is meant to be reusable in other software stacks. -Since authorization requirements and technology vary wildy across different projects, -TDS allows adopters to write their own authorization logic in python. +The Transcriptomics-Data-Service is meant to be a reusable microservice that can be integrated in existing +stacks. Since authorization schemes vary across projects, TDS allows adopters to code their own authorization plugin, +enabling adopters to leverage their existing access control tools and policies. -For Bento, we rely on API calls to a custom authorization service, -see [etc/bento.authz.module.py](./etc/bento.authz.module.py) for an example. - -For different authorization requirements, you could choose to write a custom module that performs authorization checks based on: -* An API key in the request header or in a cookie -* A JWT bearer token, for example you could: - * Allow/Deny simply based on the token's validity (decode + TTL) - * Allow/Deny based on the presence of a scope in the token - * Allow/Deny based on the presence of a group membership claim -* The results of API calls to an authorization service -* Policy engine evaluations, like OPA or Casbin - -### Using an authorization plugin - -When starting the TDS container, the FastAPI server will attempt to dynamicaly load the authorization plugin -middleware from `lib/authz.module.py`. - -If authorization is enabled and there is no file at `lib/authz.module.py`, an exception will be thrown and the server -will not start. - -Furthermore, the content of the file must follow some implementation guidelines: -- You MUST declare a concrete class that extends [BaseAuthzMiddleware](./transcriptomics_data_service/authz/middleware_base.py) -- In that class, you MUST implement the functions from BaseAuthzMiddleware with the expected signatures: - - `attach`: used to attach the middleware to the FastAPI app. - - `dipatch`: called for every request made to the API. - - `dep_authorize_`: endpoint-specific, authz evaluation functions that should return an injectable function. -- Finally, the script should expose an instance of your concrete authz middleware, named `authz_middleware`. - -Looking at [bento.authz.module.py](./etc/bento.authz.module.py), we can see an implementation that is specific to -Bento's authorization service and libraries. - -Rather than directly implementing the `attach`, `dispatch` and other authorization logic, we rely on the `bento-lib` -`FastApiAuthMiddleware`, which already provides a reusable authorization middleware for FastAPI. - -The only thing left to do is to implement the endpoint-specific authorization functions. +See the [authorization docs](./docs/authz.md) for more information on how to create and use the authz plugin with TDS. ## Endpoints diff --git a/docs/authz.md b/docs/authz.md new file mode 100644 index 0000000..9f1ce1b --- /dev/null +++ b/docs/authz.md @@ -0,0 +1,61 @@ +# Authorization plugin + +Although TDS is part of the Bento platform, it is meant to be reusable in other software stacks. +Since authorization requirements and technology vary wildy across different projects, +TDS allows adopters to write their own authorization logic in python. + +For Bento, we rely on API calls to a custom authorization service, +see [etc/bento.authz.module.py](./etc/bento.authz.module.py) for an example. + +For different authorization requirements, you could choose to write a custom module that performs authorization checks based on: +* An API key in the request header or in a cookie +* A JWT bearer token, for example you could: + * Allow/Deny simply based on the token's validity (decode + TTL) + * Allow/Deny based on the presence of a scope in the token + * Allow/Deny based on the presence of a group membership claim +* The results of API calls to an authorization service +* Policy engine evaluations, like OPA or Casbin + +## Implementing an authorization plugin + +When starting the TDS container, the FastAPI server will attempt to dynamicaly load the authorization plugin +middleware from `lib/authz.module.py`. + +If authorization is enabled and there is no file at `lib/authz.module.py`, an exception will be thrown and the server +will not start. + +Furthermore, the content of the file must follow some implementation guidelines: +- You MUST declare a concrete class that extends [BaseAuthzMiddleware](./transcriptomics_data_service/authz/middleware_base.py) +- In that class, you MUST implement the functions from BaseAuthzMiddleware with the expected signatures: + - `attach`: used to attach the middleware to the FastAPI app. + - `dipatch`: called for every request made to the API. + - `dep_authorize_`: endpoint-specific, authz evaluation functions that should return an injectable function. +- Finally, the script should expose an instance of your concrete authz middleware, named `authz_middleware`. + +Looking at [bento.authz.module.py](./etc/bento.authz.module.py), we can see an implementation that is specific to +Bento's authorization service and libraries. + +Rather than directly implementing the `attach`, `dispatch` and other authorization logic, we rely on the `bento-lib` +`FastApiAuthMiddleware`, which already provides a reusable authorization middleware for FastAPI. + +The only thing left to do is to implement the endpoint-specific authorization functions. + +## Using an authorization plugin + +When using the production image, the authz plugin must be mounted correclty on the container. +Assuming you implemented an authz plugin at `~/custom_authz_lib/authz.module.py`, mount the host directory +to the container's `/tds/lib` directory. + +```yaml +services: + tds: + image: transcriptomics_data_service:latest + container_name: tds + # ... + volumes: + # Mount the directory containing authz.module.py, NOT the file itself + - ~/custom_authz_lib:/tds/lib + + tds-db: + # ... Omitted for simplicity +``` diff --git a/transcriptomics_data_service/authz/middleware_base.py b/transcriptomics_data_service/authz/middleware_base.py index 421f5d2..ce83a51 100644 --- a/transcriptomics_data_service/authz/middleware_base.py +++ b/transcriptomics_data_service/authz/middleware_base.py @@ -35,7 +35,7 @@ async def dispatch(self, request: Request, call_next: Callable[[Request], Awaita def dep_public_endpoint(self) -> Depends: """ Dependency for public endpoints. - Used to set the /service-info dependencies. + Used to set the /service-info endpoint's dependencies. Does nothing by default, override according to your needs. """ def _inner(): From 4fd27ee969bd395f99652430b33d099b8ed0be3c Mon Sep 17 00:00:00 2001 From: Victor Rocheleau Date: Mon, 21 Oct 2024 13:09:16 -0400 Subject: [PATCH 11/31] init resource scoping for bento authz --- etc/bento.authz.module.py | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/etc/bento.authz.module.py b/etc/bento.authz.module.py index 8a9a0fe..431181a 100644 --- a/etc/bento.authz.module.py +++ b/etc/bento.authz.module.py @@ -1,16 +1,21 @@ +from typing import Annotated from bento_lib.auth.middleware.fastapi import FastApiAuthMiddleware from bento_lib.auth.permissions import P_INGEST_DATA, P_DELETE_DATA, P_QUERY_DATA, Permission -from bento_lib.auth.resources import RESOURCE_EVERYTHING +from bento_lib.auth.resources import RESOURCE_EVERYTHING, build_resource +from fastapi import Depends, Request from transcriptomics_data_service.config import get_config from transcriptomics_data_service.logger import get_logger from transcriptomics_data_service.authz.middleware_base import BaseAuthzMiddleware +import re + config = get_config() logger = get_logger(config) # TODO add Bento specific project/dataset ownership pattern to experiment_result_id + class BentoAuthzMiddleware(FastApiAuthMiddleware, BaseAuthzMiddleware): """ Concrete implementation of BaseAuthzMiddleware to authorize with Bento's authorization service/model. @@ -21,6 +26,24 @@ class BentoAuthzMiddleware(FastApiAuthMiddleware, BaseAuthzMiddleware): - TDS should be able to perform HTTP requests on the authz service url: `config.bento_authz_service_url` """ + def _build_resource_from_id(self, experiment_result_id: str): + # Inject on an endpoint that uses the experiment_result_id param to create the authz Resource + # Ownsership of an experiment is baked-in the ExperimentResult's ID + # e.g. "----" + [project, dataset, experiment] = re.split("--", experiment_result_id) + print(project, dataset, experiment) + return build_resource(project, dataset) + + def _dep_require_permission(self, permission: Permission): + # Given a permission and the injected resource, will evaluate if allowed + async def inner(request: Request, resource: Annotated[dict, Depends(self._build_resource_from_id)]): + return self.dep_require_permissions_on_resource( + permissions=frozenset({permission}), + resource=resource, + ) + + return Depends(inner) + def _dep_perm_data_everything(self, permission: Permission): return self.dep_require_permissions_on_resource( permissions=frozenset({permission}), @@ -30,18 +53,19 @@ def _dep_perm_data_everything(self, permission: Permission): # INGESTION router paths def dep_authz_ingest(self): - return self._dep_perm_data_everything(P_INGEST_DATA) + # User needs P_INGEST_DATA permission on the target resource (injected) + return self._dep_require_permission(P_INGEST_DATA) def dep_authz_normalize(self): - return self._dep_perm_data_everything(P_INGEST_DATA) + return self._dep_require_permission(P_INGEST_DATA) # EXPERIMENT RESULT router paths def dep_authz_get_experiment_result(self): - return self._dep_perm_data_everything(P_QUERY_DATA) + return self._dep_require_permission(P_QUERY_DATA) def dep_authz_delete_experiment_result(self): - return self._dep_perm_data_everything(P_DELETE_DATA) + return self._dep_require_permission(P_DELETE_DATA) # EXPRESSIONS router paths From d73a1963333e037e57ec23f2c2d5b03e3cde8dc3 Mon Sep 17 00:00:00 2001 From: v-rocheleau Date: Mon, 21 Oct 2024 15:05:27 -0400 Subject: [PATCH 12/31] debug service info for bento integration --- transcriptomics_data_service/main.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/transcriptomics_data_service/main.py b/transcriptomics_data_service/main.py index 6f6ce6b..8f07cad 100644 --- a/transcriptomics_data_service/main.py +++ b/transcriptomics_data_service/main.py @@ -13,10 +13,12 @@ from .constants import BENTO_SERVICE_KIND, SERVICE_TYPE from .logger import get_logger +# TODO should probably be mounted as a JSON for usage outside Bento +# could also be used to indicate if deployment is Bento specific of not BENTO_SERVICE_INFO = { "serviceKind": BENTO_SERVICE_KIND, - "dataService": True, - "workflowProvider": True, + "dataService": False, # temp off to quiet bento-web errors + "workflowProvider": False, # temp off to quiet bento-web errors "gitRepository": "https://github.com/bento-platform/transcriptomics_data_service", } From 9ed9838d41a1be655303682ad61e500a083a4c69 Mon Sep 17 00:00:00 2001 From: v-rocheleau Date: Mon, 21 Oct 2024 15:11:10 -0400 Subject: [PATCH 13/31] lint --- transcriptomics_data_service/authz/middleware_base.py | 2 ++ transcriptomics_data_service/main.py | 5 +++-- transcriptomics_data_service/routers/ingest.py | 1 + 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/transcriptomics_data_service/authz/middleware_base.py b/transcriptomics_data_service/authz/middleware_base.py index ce83a51..4db50c3 100644 --- a/transcriptomics_data_service/authz/middleware_base.py +++ b/transcriptomics_data_service/authz/middleware_base.py @@ -38,8 +38,10 @@ def dep_public_endpoint(self) -> Depends: Used to set the /service-info endpoint's dependencies. Does nothing by default, override according to your needs. """ + def _inner(): pass + return Depends(_inner) def dep_app(self) -> None | Sequence[Depends]: diff --git a/transcriptomics_data_service/main.py b/transcriptomics_data_service/main.py index 8f07cad..a619fee 100644 --- a/transcriptomics_data_service/main.py +++ b/transcriptomics_data_service/main.py @@ -17,7 +17,7 @@ # could also be used to indicate if deployment is Bento specific of not BENTO_SERVICE_INFO = { "serviceKind": BENTO_SERVICE_KIND, - "dataService": False, # temp off to quiet bento-web errors + "dataService": False, # temp off to quiet bento-web errors "workflowProvider": False, # temp off to quiet bento-web errors "gitRepository": "https://github.com/bento-platform/transcriptomics_data_service", } @@ -34,6 +34,7 @@ async def lifespan(_app: FastAPI): yield + app = BentoFastAPI( authz_middleware=authz_plugin, config=config_for_setup, @@ -42,7 +43,7 @@ async def lifespan(_app: FastAPI): service_type=SERVICE_TYPE, version=__version__, lifespan=lifespan, - dependencies=authz_plugin.dep_app() + dependencies=authz_plugin.dep_app(), ) app.include_router(expression_router) diff --git a/transcriptomics_data_service/routers/ingest.py b/transcriptomics_data_service/routers/ingest.py index 1ebcacf..8ad9f6a 100644 --- a/transcriptomics_data_service/routers/ingest.py +++ b/transcriptomics_data_service/routers/ingest.py @@ -14,6 +14,7 @@ # TODO make configurable? an argument? GENE_ID_KEY = "GeneID" + @ingest_router.post( "/ingest/{experiment_result_id}/assembly-name/{assembly_name}/assembly-id/{assembly_id}", status_code=status.HTTP_200_OK, From f16362784be0d4665bc04d259946f22559d0b4df Mon Sep 17 00:00:00 2001 From: v-rocheleau Date: Mon, 21 Oct 2024 16:03:24 -0400 Subject: [PATCH 14/31] debug log and todo --- etc/bento.authz.module.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/etc/bento.authz.module.py b/etc/bento.authz.module.py index 431181a..bced955 100644 --- a/etc/bento.authz.module.py +++ b/etc/bento.authz.module.py @@ -13,9 +13,6 @@ config = get_config() logger = get_logger(config) -# TODO add Bento specific project/dataset ownership pattern to experiment_result_id - - class BentoAuthzMiddleware(FastApiAuthMiddleware, BaseAuthzMiddleware): """ Concrete implementation of BaseAuthzMiddleware to authorize with Bento's authorization service/model. @@ -30,8 +27,12 @@ def _build_resource_from_id(self, experiment_result_id: str): # Inject on an endpoint that uses the experiment_result_id param to create the authz Resource # Ownsership of an experiment is baked-in the ExperimentResult's ID # e.g. "----" + # TODO: come up with better delimiters [project, dataset, experiment] = re.split("--", experiment_result_id) print(project, dataset, experiment) + self._logger.debug( + f"Injecting resource: project={project} dataset={dataset} experiment_result_id={experiment_result_id}" + ) return build_resource(project, dataset) def _dep_require_permission(self, permission: Permission): From e18b8c99c72cb63b148d80e0dbc0c4498f0ef23e Mon Sep 17 00:00:00 2001 From: Victor Rocheleau Date: Mon, 21 Oct 2024 21:12:25 +0000 Subject: [PATCH 15/31] perf: authz dep chain with injectable resource --- etc/bento.authz.module.py | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/etc/bento.authz.module.py b/etc/bento.authz.module.py index bced955..3c512cb 100644 --- a/etc/bento.authz.module.py +++ b/etc/bento.authz.module.py @@ -13,6 +13,7 @@ config = get_config() logger = get_logger(config) + class BentoAuthzMiddleware(FastApiAuthMiddleware, BaseAuthzMiddleware): """ Concrete implementation of BaseAuthzMiddleware to authorize with Bento's authorization service/model. @@ -24,8 +25,8 @@ class BentoAuthzMiddleware(FastApiAuthMiddleware, BaseAuthzMiddleware): """ def _build_resource_from_id(self, experiment_result_id: str): - # Inject on an endpoint that uses the experiment_result_id param to create the authz Resource - # Ownsership of an experiment is baked-in the ExperimentResult's ID + # Injectable for endpoints that use the 'experiment_result_id' param to create the authz Resource + # Ownsership of an experiment is baked-in the ExperimentResult's ID in Bento # e.g. "----" # TODO: come up with better delimiters [project, dataset, experiment] = re.split("--", experiment_result_id) @@ -35,13 +36,16 @@ def _build_resource_from_id(self, experiment_result_id: str): ) return build_resource(project, dataset) - def _dep_require_permission(self, permission: Permission): - # Given a permission and the injected resource, will evaluate if allowed - async def inner(request: Request, resource: Annotated[dict, Depends(self._build_resource_from_id)]): - return self.dep_require_permissions_on_resource( - permissions=frozenset({permission}), - resource=resource, - ) + def _dep_require_permission_injected_resource( + self, + permission: Permission, + ): + # Given a permission and the injected resource, will evaluate if operation is allowed + async def inner( + request: Request, + resource: Annotated[dict, Depends(self._build_resource_from_id)], # Inject resource + ): + await self.async_check_authz_evaluate(request, frozenset({permission}), resource, set_authz_flag=True) return Depends(inner) @@ -55,18 +59,18 @@ def _dep_perm_data_everything(self, permission: Permission): def dep_authz_ingest(self): # User needs P_INGEST_DATA permission on the target resource (injected) - return self._dep_require_permission(P_INGEST_DATA) + return self._dep_require_permission_injected_resource(P_INGEST_DATA) def dep_authz_normalize(self): - return self._dep_require_permission(P_INGEST_DATA) + return self._dep_require_permission_injected_resource(P_INGEST_DATA) # EXPERIMENT RESULT router paths def dep_authz_get_experiment_result(self): - return self._dep_require_permission(P_QUERY_DATA) + return self._dep_require_permission_injected_resource(P_QUERY_DATA) def dep_authz_delete_experiment_result(self): - return self._dep_require_permission(P_DELETE_DATA) + return self._dep_require_permission_injected_resource(P_DELETE_DATA) # EXPRESSIONS router paths From f1db249c51b9239ad2225489c7b5971682f52e99 Mon Sep 17 00:00:00 2001 From: Victor Rocheleau Date: Wed, 23 Oct 2024 13:56:16 -0400 Subject: [PATCH 16/31] feat: authz plugin extra settings --- docs/authz.md | 24 +++++++++++++++++++ etc/example.authz.module.py | 18 ++++++++++++-- .../authz/middleware_base.py | 3 +++ transcriptomics_data_service/config.py | 5 ++++ 4 files changed, 48 insertions(+), 2 deletions(-) diff --git a/docs/authz.md b/docs/authz.md index 9f1ce1b..934fb4f 100644 --- a/docs/authz.md +++ b/docs/authz.md @@ -59,3 +59,27 @@ services: tds-db: # ... Omitted for simplicity ``` + +## Providing extra configurations for a custom authorization plugin + +You can add custom settings for your authorization plugin. +Following the API key authorization plugin [example](../etc/example.authz.module.py), +you will notice that the API key is not hard coded in a variable, but imported from the pydantic config. + +The TDS pydantic settings are configured to load a `.env` file from the authz plugin mount. +After the .env is loaded, you can access the extra settings with: `config.model_extra.get()`. + +In other scenarios, you could store any configuration values required for your authorization logic. + +## Defining additional python dependencies + +When implementing an authorization plugin, you may realize that the default python modules used in TDS are not enough +for your needs. + +Maybe you want to use OPA's Python client to evaluate policies, or an in-house Python library your team made for this +purpose. + +While the dependencies declared in [pyproject.toml](../pyproject.toml) are fixed for a given TDS release, +you can still speficy extra dependencies to be installed when the container starts! + +TODO: figure out how to do this diff --git a/etc/example.authz.module.py b/etc/example.authz.module.py index 1086b54..6e34cdd 100644 --- a/etc/example.authz.module.py +++ b/etc/example.authz.module.py @@ -11,8 +11,16 @@ config = get_config() logger = get_logger(config) -# The valid api key for authorization + +""" +CUSTOM PLUGIN CONFIGURATION +Extra configurations can be added to the config object by adding +a '.env' file in the plugin mount directory. +Variables placed there will be loaded as lowercase properties + +This variable's value can be accessed with: config.api_key API_KEY = "fake-super-secret-api-key" +""" class ApiKeyAuthzMiddleware(BaseAuthzMiddleware): @@ -25,6 +33,12 @@ def __init__(self, config: Config, logger: Logger) -> None: self.enabled = config.bento_authz_enabled self.logger = logger + # Load the api_key from the config's extras + self.api_key = config.model_extra.get("api_key") + if self.api_key is None: + # prevents the server from starting if misconfigured + raise ValueError("Expected variable 'API_KEY' is not set in the plugin's .env") + # Middleware lifecycle def attach(self, app: FastAPI): @@ -66,7 +80,7 @@ def _dep_check_api_key(self): """ async def _inner(x_api_key: Annotated[str, Header()]): - if x_api_key != API_KEY: + if x_api_key != self.api_key: raise HTTPException(status_code=403, detail="Unauthorized: invalid API key") return Depends(_inner) diff --git a/transcriptomics_data_service/authz/middleware_base.py b/transcriptomics_data_service/authz/middleware_base.py index 4db50c3..a9efdef 100644 --- a/transcriptomics_data_service/authz/middleware_base.py +++ b/transcriptomics_data_service/authz/middleware_base.py @@ -29,6 +29,9 @@ async def dispatch(self, request: Request, call_next: Callable[[Request], Awaita - Handle unauthorized responses """ raise NotImplemented() + + async def mark_authz_done(self, request: Request): + pass # Dependency injections diff --git a/transcriptomics_data_service/config.py b/transcriptomics_data_service/config.py index d9aeb8e..667b934 100644 --- a/transcriptomics_data_service/config.py +++ b/transcriptomics_data_service/config.py @@ -3,6 +3,8 @@ from functools import lru_cache from typing import Annotated +from pydantic_settings import BaseSettings, SettingsConfigDict + from .constants import SERVICE_GROUP, SERVICE_ARTIFACT __all__ = [ @@ -20,6 +22,9 @@ class Config(BentoFastAPIBaseConfig): database_uri: str = "postgres://localhost:5432" + # Allow extra configs from /tds/lib/.env for custom authz configuration + model_config = SettingsConfigDict(env_file="/tds/lib/.env", extra="allow") + @lru_cache() def get_config(): From 479a846271daf773650450168345bba6cec8d31a Mon Sep 17 00:00:00 2001 From: Victor Rocheleau Date: Wed, 23 Oct 2024 18:59:59 +0000 Subject: [PATCH 17/31] lint --- transcriptomics_data_service/authz/middleware_base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/transcriptomics_data_service/authz/middleware_base.py b/transcriptomics_data_service/authz/middleware_base.py index a9efdef..d42a5c6 100644 --- a/transcriptomics_data_service/authz/middleware_base.py +++ b/transcriptomics_data_service/authz/middleware_base.py @@ -29,7 +29,7 @@ async def dispatch(self, request: Request, call_next: Callable[[Request], Awaita - Handle unauthorized responses """ raise NotImplemented() - + async def mark_authz_done(self, request: Request): pass From 9e780ee3306194e4ae73ff75579cdacb2e61f980 Mon Sep 17 00:00:00 2001 From: Victor Rocheleau Date: Wed, 23 Oct 2024 20:02:14 +0000 Subject: [PATCH 18/31] authz plugin deps --- run.bash | 5 +++++ run.dev.bash | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/run.bash b/run.bash index 12e58b2..02ca96b 100644 --- a/run.bash +++ b/run.bash @@ -5,6 +5,11 @@ export ASGI_APP="transcriptomics_data_service.main:app" # Set default internal port to 5000 : "${INTERNAL_PORT:=5000}" +if ! [ -f /tds/lib/requirements.txt ]; then + echo "Installing authz plugin dependencies" + pip3 install -r /tds/lib/requirements.txt +fi + uvicorn \ --workers 1 \ --loop uvloop \ diff --git a/run.dev.bash b/run.dev.bash index e872cd8..65870af 100644 --- a/run.dev.bash +++ b/run.dev.bash @@ -3,6 +3,11 @@ # Update dependencies and install module locally /poetry_user_install_dev.bash +if ! [ -f /tds/lib/requirements.txt ]; then + echo "Installing authz plugin dependencies" + pip3 install -r /tds/lib/requirements.txt +fi + export ASGI_APP="transcriptomics_data_service.main:app" # Set default internal port to 5000 From cc8bbe27573f7188d638588d5944f1f1efa924fc Mon Sep 17 00:00:00 2001 From: Victor Rocheleau Date: Wed, 23 Oct 2024 17:05:33 -0400 Subject: [PATCH 19/31] feat: authz plugin extra dependencies --- docs/authz.md | 7 ++++++- run.bash | 4 ++-- run.dev.bash | 4 ++-- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/docs/authz.md b/docs/authz.md index 934fb4f..6b52160 100644 --- a/docs/authz.md +++ b/docs/authz.md @@ -82,4 +82,9 @@ purpose. While the dependencies declared in [pyproject.toml](../pyproject.toml) are fixed for a given TDS release, you can still speficy extra dependencies to be installed when the container starts! -TODO: figure out how to do this +To do so, add a `requirements.txt` file to the authz plugin mount. +During the initialization of the container, these additional dependencies will be installed, +allowing your plugin to use them. + +**Note: It is the plugin implementer's responsibility to ensure that these additional dependencies +don't conflict with those in [pyproject.toml](../pyproject.toml)** diff --git a/run.bash b/run.bash index 02ca96b..10b1be2 100644 --- a/run.bash +++ b/run.bash @@ -5,9 +5,9 @@ export ASGI_APP="transcriptomics_data_service.main:app" # Set default internal port to 5000 : "${INTERNAL_PORT:=5000}" +# Extra dependencies installation for authz plugin if ! [ -f /tds/lib/requirements.txt ]; then - echo "Installing authz plugin dependencies" - pip3 install -r /tds/lib/requirements.txt + pip install -r /tds/lib/requirements.txt fi uvicorn \ diff --git a/run.dev.bash b/run.dev.bash index 65870af..c1122f6 100644 --- a/run.dev.bash +++ b/run.dev.bash @@ -3,9 +3,9 @@ # Update dependencies and install module locally /poetry_user_install_dev.bash +# Extra dependencies installation for authz plugin if ! [ -f /tds/lib/requirements.txt ]; then - echo "Installing authz plugin dependencies" - pip3 install -r /tds/lib/requirements.txt + pip install -r /tds/lib/requirements.txt fi export ASGI_APP="transcriptomics_data_service.main:app" From 897158e45dd44d773163469613d1c1693f17da9c Mon Sep 17 00:00:00 2001 From: Victor Rocheleau Date: Mon, 28 Oct 2024 20:09:52 +0000 Subject: [PATCH 20/31] chore: add authz external dependency example --- etc/bento.authz.module.py | 10 +- etc/example-dep/extra-dep.authz.module.py | 93 +++++++++++++++++++ etc/example-dep/requirements.txt | 1 + etc/example.authz.module.py | 40 +++----- run.bash | 2 +- run.dev.bash | 2 +- .../authz/middleware_base.py | 22 ++--- transcriptomics_data_service/authz/plugin.py | 2 - .../routers/experiment_results.py | 4 +- .../routers/expressions.py | 2 +- .../routers/ingest.py | 4 +- 11 files changed, 130 insertions(+), 52 deletions(-) create mode 100644 etc/example-dep/extra-dep.authz.module.py create mode 100644 etc/example-dep/requirements.txt diff --git a/etc/bento.authz.module.py b/etc/bento.authz.module.py index 3c512cb..489da6b 100644 --- a/etc/bento.authz.module.py +++ b/etc/bento.authz.module.py @@ -59,23 +59,23 @@ def _dep_perm_data_everything(self, permission: Permission): def dep_authz_ingest(self): # User needs P_INGEST_DATA permission on the target resource (injected) - return self._dep_require_permission_injected_resource(P_INGEST_DATA) + return [self._dep_require_permission_injected_resource(P_INGEST_DATA)] def dep_authz_normalize(self): - return self._dep_require_permission_injected_resource(P_INGEST_DATA) + return [self._dep_require_permission_injected_resource(P_INGEST_DATA)] # EXPERIMENT RESULT router paths def dep_authz_get_experiment_result(self): - return self._dep_require_permission_injected_resource(P_QUERY_DATA) + return [self._dep_require_permission_injected_resource(P_QUERY_DATA)] def dep_authz_delete_experiment_result(self): - return self._dep_require_permission_injected_resource(P_DELETE_DATA) + return [self._dep_require_permission_injected_resource(P_DELETE_DATA)] # EXPRESSIONS router paths def dep_authz_expressions_list(self): - return self._dep_perm_data_everything(P_QUERY_DATA) + return [self._dep_perm_data_everything(P_QUERY_DATA)] authz_middleware = BentoAuthzMiddleware.build_from_fastapi_pydantic_config(config, logger) diff --git a/etc/example-dep/extra-dep.authz.module.py b/etc/example-dep/extra-dep.authz.module.py new file mode 100644 index 0000000..09d71d8 --- /dev/null +++ b/etc/example-dep/extra-dep.authz.module.py @@ -0,0 +1,93 @@ +from logging import Logger +from typing import Annotated, Any, Awaitable, Callable, Coroutine +from fastapi import Depends, FastAPI, HTTPException, Header, Request, Response +from fastapi.responses import JSONResponse + +from transcriptomics_data_service.authz.middleware_base import BaseAuthzMiddleware +from transcriptomics_data_service.config import Config, get_config +from transcriptomics_data_service.logger import get_logger + +config = get_config() +logger = get_logger(config) + + +""" +CUSTOM PLUGIN DEPENDENCY +Extra dependencies can be added if the authz plugin requires them. +In this example, the authz module imports the OPA agent. +Since OPA does not ship with TDS, a requirements.txt file must be placed under 'lib'. +""" + +from opa_client.opa import OpaClient + + +class ApiKeyAuthzMiddleware(BaseAuthzMiddleware): + """ + Concrete implementation of BaseAuthzMiddleware to authorize requests based on the provided API key. + """ + + def __init__(self, config: Config, logger: Logger) -> None: + super().__init__() + self.enabled = config.bento_authz_enabled + self.logger = logger + + # Init the OPA client with the server + self.opa_client = OpaClient(host="opa-container", port=8181) + try: + # Commented out as this is not pointing to a real OPA server + # self.logger.info(self.opa_client.check_connection()) + pass + except: + raise Exception("Could not establish connection to the OPA service.") + + # Middleware lifecycle + + def attach(self, app: FastAPI): + app.middleware("http")(self.dispatch) + + async def dispatch( + self, request: Request, call_next: Callable[[Request], Awaitable[Response]] + ) -> Coroutine[Any, Any, Response]: + if not self.enabled: + return await call_next(request) + + try: + res = await call_next(request) + except HTTPException as e: + # Catch exceptions raised by authz functions + self.logger.error(e) + return JSONResponse(status_code=e.status_code, content=e.detail) + + return res + + # OPA authorization + def _dep_check_opa(self): + async def inner(request: Request): + # Check the permission using the OPA client. + # We assume true for the sake of the demonstration + # authz_result = await self.opa_client.check_permission() + authz_result = True + if not authz_result: + raise HTTPException(status_code=403, detail="Unauthorized: policy evaluation failed") + + return Depends(inner) + + # Authz logic: only check for valid API key + + def dep_authz_ingest(self): + return [self._dep_check_opa()] + + def dep_authz_normalize(self): + return [self._dep_check_opa()] + + def dep_authz_delete_experiment_result(self): + return [self._dep_check_opa()] + + def dep_authz_expressions_list(self): + return [self._dep_check_opa()] + + def dep_authz_get_experiment_result(self): + return [self._dep_check_opa()] + + +authz_middleware = ApiKeyAuthzMiddleware(config, logger) diff --git a/etc/example-dep/requirements.txt b/etc/example-dep/requirements.txt new file mode 100644 index 0000000..4ef31a8 --- /dev/null +++ b/etc/example-dep/requirements.txt @@ -0,0 +1 @@ +opa-python-client==2.0.0 diff --git a/etc/example.authz.module.py b/etc/example.authz.module.py index 6e34cdd..13e7e19 100644 --- a/etc/example.authz.module.py +++ b/etc/example.authz.module.py @@ -1,8 +1,7 @@ from logging import Logger -from typing import Annotated, Any, Awaitable, Callable, Coroutine +from typing import Annotated, Any, Awaitable, Callable, Coroutine, Sequence from fastapi import Depends, FastAPI, HTTPException, Header, Request, Response from fastapi.responses import JSONResponse -from starlette.responses import Response from transcriptomics_data_service.authz.middleware_base import BaseAuthzMiddleware from transcriptomics_data_service.config import Config, get_config @@ -19,7 +18,7 @@ Variables placed there will be loaded as lowercase properties This variable's value can be accessed with: config.api_key -API_KEY = "fake-super-secret-api-key" +API_KEY="fake-super-secret-api-key" """ @@ -60,17 +59,6 @@ async def dispatch( return res # API KEY authorization - def dep_app(self): - """ - API-level dependency injection - Injects a required header for the API key authz: x_api_key - OpenAPI automatically includes it on all paths. - """ - - async def _inner(x_api_key: Annotated[str, Header()]): - return x_api_key - - return [Depends(_inner)] def _dep_check_api_key(self): """ @@ -85,22 +73,20 @@ async def _inner(x_api_key: Annotated[str, Header()]): return Depends(_inner) - # Authz logic: only check for valid API key - - def dep_authz_ingest(self): - return self._dep_check_api_key() - - def dep_authz_normalize(self): - return self._dep_check_api_key() + def dep_ingest_router(self) -> Sequence[Depends]: + # Require API key check on the ingest router + return [self._dep_check_api_key()] - def dep_authz_delete_experiment_result(self): - return self._dep_check_api_key() + def dep_expression_router(self) -> Sequence[Depends]: + # Require API key check on the expressions router + return [self._dep_check_api_key()] - def dep_authz_expressions_list(self): - return self._dep_check_api_key() + def dep_experiment_result_router(self) -> Sequence[Depends]: + # Require API key check on the experiment_result router + return [self._dep_check_api_key()] - def dep_authz_get_experiment_result(self): - return self._dep_check_api_key() + # NOTE: With an all-or-nothing authz mechanism like an API key, + # we can place the authz checks at the router level to have a more concise module. authz_middleware = ApiKeyAuthzMiddleware(config, logger) diff --git a/run.bash b/run.bash index 10b1be2..b88b452 100644 --- a/run.bash +++ b/run.bash @@ -6,7 +6,7 @@ export ASGI_APP="transcriptomics_data_service.main:app" : "${INTERNAL_PORT:=5000}" # Extra dependencies installation for authz plugin -if ! [ -f /tds/lib/requirements.txt ]; then +if [ -f /tds/lib/requirements.txt ]; then pip install -r /tds/lib/requirements.txt fi diff --git a/run.dev.bash b/run.dev.bash index c1122f6..98a4025 100644 --- a/run.dev.bash +++ b/run.dev.bash @@ -4,7 +4,7 @@ /poetry_user_install_dev.bash # Extra dependencies installation for authz plugin -if ! [ -f /tds/lib/requirements.txt ]; then +if [ -f /tds/lib/requirements.txt ]; then pip install -r /tds/lib/requirements.txt fi diff --git a/transcriptomics_data_service/authz/middleware_base.py b/transcriptomics_data_service/authz/middleware_base.py index d42a5c6..51f5120 100644 --- a/transcriptomics_data_service/authz/middleware_base.py +++ b/transcriptomics_data_service/authz/middleware_base.py @@ -30,7 +30,7 @@ async def dispatch(self, request: Request, call_next: Callable[[Request], Awaita """ raise NotImplemented() - async def mark_authz_done(self, request: Request): + def mark_authz_done(self, request: Request): pass # Dependency injections @@ -79,20 +79,20 @@ def dep_experiment_result_router(self) -> None | Sequence[Depends]: ###### INGEST router paths - def dep_authz_ingest(self) -> Depends: - raise NotImplemented() + def dep_authz_ingest(self) -> None | Sequence[Depends]: + return None - def dep_authz_normalize(self) -> Depends: - raise NotImplemented() + def dep_authz_normalize(self) -> None | Sequence[Depends]: + return None ###### EXPRESSIONS router paths - def dep_authz_expressions_list(self) -> Depends: - raise NotImplemented() + def dep_authz_expressions_list(self) -> None | Sequence[Depends]: + return None ###### EXPERIMENT RESULTS router paths - def dep_authz_delete_experiment_result(self) -> Depends: - raise NotImplemented() + def dep_authz_delete_experiment_result(self) -> None | Sequence[Depends]: + return None - def dep_authz_get_experiment_result(self) -> Depends: - raise NotImplemented() + def dep_authz_get_experiment_result(self) -> None | Sequence[Depends]: + return None diff --git a/transcriptomics_data_service/authz/plugin.py b/transcriptomics_data_service/authz/plugin.py index 73a4508..963480f 100644 --- a/transcriptomics_data_service/authz/plugin.py +++ b/transcriptomics_data_service/authz/plugin.py @@ -16,8 +16,6 @@ def import_module_from_path(path): return module -# TODO find a way to allow plugin writers to specify additional dependencies to be installed - AUTHZ_MODULE_PATH = "/tds/lib/authz.module.py" authz_plugin_module = import_module_from_path(AUTHZ_MODULE_PATH) diff --git a/transcriptomics_data_service/routers/experiment_results.py b/transcriptomics_data_service/routers/experiment_results.py index d6a7f4e..f4d825e 100644 --- a/transcriptomics_data_service/routers/experiment_results.py +++ b/transcriptomics_data_service/routers/experiment_results.py @@ -8,11 +8,11 @@ experiment_router = APIRouter(prefix="/experiment", dependencies=authz_plugin.dep_experiment_result_router()) -@experiment_router.delete("/{experiment_result_id}", dependencies=[authz_plugin.dep_authz_delete_experiment_result()]) +@experiment_router.delete("/{experiment_result_id}", dependencies=authz_plugin.dep_authz_delete_experiment_result()) async def delete_experiment_result(db: DatabaseDependency, experiment_result_id: str): await db.delete_experiment_result(experiment_result_id) -@experiment_router.get("/{experiment_result_id}", dependencies=[authz_plugin.dep_authz_get_experiment_result()]) +@experiment_router.get("/{experiment_result_id}", dependencies=authz_plugin.dep_authz_get_experiment_result()) async def get_experiment_result(db: DatabaseDependency, experiment_result_id: str): return await db.read_experiment_result(experiment_result_id) diff --git a/transcriptomics_data_service/routers/expressions.py b/transcriptomics_data_service/routers/expressions.py index cc3a9c8..5b181f6 100644 --- a/transcriptomics_data_service/routers/expressions.py +++ b/transcriptomics_data_service/routers/expressions.py @@ -8,6 +8,6 @@ expression_router = APIRouter(prefix="/expressions", dependencies=authz_plugin.dep_expression_router()) -@expression_router.get("", status_code=status.HTTP_200_OK, dependencies=[authz_plugin.dep_authz_expressions_list()]) +@expression_router.get("", status_code=status.HTTP_200_OK, dependencies=authz_plugin.dep_authz_expressions_list()) async def expressions_list(db: DatabaseDependency): return await db.fetch_expressions() diff --git a/transcriptomics_data_service/routers/ingest.py b/transcriptomics_data_service/routers/ingest.py index 8ad9f6a..312da67 100644 --- a/transcriptomics_data_service/routers/ingest.py +++ b/transcriptomics_data_service/routers/ingest.py @@ -19,7 +19,7 @@ "/ingest/{experiment_result_id}/assembly-name/{assembly_name}/assembly-id/{assembly_id}", status_code=status.HTTP_200_OK, # Injects the plugin authz middleware dep_authorize_ingest function - dependencies=[authz_plugin.dep_authz_ingest()], + dependencies=authz_plugin.dep_authz_ingest(), ) async def ingest( request: Request, @@ -58,7 +58,7 @@ async def ingest( @ingest_router.post( "/normalize/{experiment_result_id}", status_code=status.HTTP_200_OK, - dependencies=[authz_plugin.dep_authz_normalize()], + dependencies=authz_plugin.dep_authz_normalize(), ) async def normalize( db: DatabaseDependency, From 33d5fd7685b22dd840813001b24ede410f0b7ebf Mon Sep 17 00:00:00 2001 From: Victor Rocheleau Date: Thu, 31 Oct 2024 16:42:35 -0400 Subject: [PATCH 21/31] docs: authz implementation methods tables --- README.md | 2 +- docs/authz.md | 23 ++++++++++++++++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 05cfb65..1385a99 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ You can then attach VS Code to the `tds` container, and use the preconfigured `P The Transcriptomics-Data-Service is meant to be a reusable microservice that can be integrated in existing stacks. Since authorization schemes vary across projects, TDS allows adopters to code their own authorization plugin, -enabling adopters to leverage their existing access control tools and policies. +enabling adopters to leverage their existing access control code, tools and policies. See the [authorization docs](./docs/authz.md) for more information on how to create and use the authz plugin with TDS. diff --git a/docs/authz.md b/docs/authz.md index 6b52160..b1467fb 100644 --- a/docs/authz.md +++ b/docs/authz.md @@ -29,7 +29,6 @@ Furthermore, the content of the file must follow some implementation guidelines: - In that class, you MUST implement the functions from BaseAuthzMiddleware with the expected signatures: - `attach`: used to attach the middleware to the FastAPI app. - `dipatch`: called for every request made to the API. - - `dep_authorize_`: endpoint-specific, authz evaluation functions that should return an injectable function. - Finally, the script should expose an instance of your concrete authz middleware, named `authz_middleware`. Looking at [bento.authz.module.py](./etc/bento.authz.module.py), we can see an implementation that is specific to @@ -40,6 +39,28 @@ Rather than directly implementing the `attach`, `dispatch` and other authorizati The only thing left to do is to implement the endpoint-specific authorization functions. +Here is a full view of the methods you can implement and their purpose. +| Lifecycle methods | Mandatory | Description | +| ----------------- | --------- | ------------------------------------------------------------------------------------------- | +| `attach` | YES | Attaches the middleware to the FastAPI app | +| `dispatch` | YES | Middleware dispatch executed for all requests. Handle authorization errors/exceptions here | +| `mark_authz_done` | NO | Bento lib authz middleware specific, marks that the authz check on a request was performed | + +| App/router authorization methods | Description | +| -------------------------------- | -------------------------------------------------------------------- | +| `dep_app` | Returns a list of injectables that will be added as app dependencies | +| `dep_ingest_router` | Returns a list of injectables for the ingest router | +| `dep_expression_router` | Returns a list of injectables for the expression router | +| `dep_experiment_result_router` | Returns a list of injectables for the expression router | + +| Endpoint authorization methods | Description | +| ------------------------------------ | --------------------------------------------------------- | +| `dep_public_endpoint` | Returns an injectable authz function for public endpoints | +| `dep_authz_ingest` | TODO | +| `dep_authz_normalize` | TODO | +| `dep_authz_expressions_list` | TODO | +| `dep_authz_delete_experiment_result` | TODO | +| `dep_authz_get_experiment_result` | TODO | ## Using an authorization plugin When using the production image, the authz plugin must be mounted correclty on the container. From cbf98b33fe8206878c6c5e5c4364f466b5b7f42c Mon Sep 17 00:00:00 2001 From: v-rocheleau Date: Tue, 5 Nov 2024 11:58:22 -0500 Subject: [PATCH 22/31] chore: authz docs and examples --- docker-compose.dev.yaml | 2 +- docs/authz.md | 103 +++++++++++++----- .../authz.module.py} | 5 +- .../authz.module.py} | 6 +- .../requirements.txt | 0 .../authz/middleware_base.py | 16 ++- 6 files changed, 94 insertions(+), 38 deletions(-) rename etc/{example.authz.module.py => authz-api-key-extra-env/authz.module.py} (97%) rename etc/{example-dep/extra-dep.authz.module.py => authz-extra-dep/authz.module.py} (92%) rename etc/{example-dep => authz-extra-dep}/requirements.txt (100%) diff --git a/docker-compose.dev.yaml b/docker-compose.dev.yaml index fe3e103..f34ab7b 100644 --- a/docker-compose.dev.yaml +++ b/docker-compose.dev.yaml @@ -9,7 +9,7 @@ services: depends_on: - tds-db environment: - - BENTO_UID=1001 + - BENTO_UID=${UID} - DATABASE_URI=postgres://tds_user:tds_password@tds-db:5432/tds_db - CORS_ORIGINS="*" - BENTO_AUTHZ_SERVICE_URL="" diff --git a/docs/authz.md b/docs/authz.md index b1467fb..a539696 100644 --- a/docs/authz.md +++ b/docs/authz.md @@ -1,6 +1,7 @@ # Authorization plugin Although TDS is part of the Bento platform, it is meant to be reusable in other software stacks. + Since authorization requirements and technology vary wildy across different projects, TDS allows adopters to write their own authorization logic in python. @@ -16,6 +17,8 @@ For different authorization requirements, you could choose to write a custom mod * The results of API calls to an authorization service * Policy engine evaluations, like OPA or Casbin +TODO: add diagram showing how the plugin fits in with the app + ## Implementing an authorization plugin When starting the TDS container, the FastAPI server will attempt to dynamicaly load the authorization plugin @@ -26,9 +29,7 @@ will not start. Furthermore, the content of the file must follow some implementation guidelines: - You MUST declare a concrete class that extends [BaseAuthzMiddleware](./transcriptomics_data_service/authz/middleware_base.py) -- In that class, you MUST implement the functions from BaseAuthzMiddleware with the expected signatures: - - `attach`: used to attach the middleware to the FastAPI app. - - `dipatch`: called for every request made to the API. +- In that class, you MUST implement the required functions from `BaseAuthzMiddleware`: - Finally, the script should expose an instance of your concrete authz middleware, named `authz_middleware`. Looking at [bento.authz.module.py](./etc/bento.authz.module.py), we can see an implementation that is specific to @@ -37,30 +38,76 @@ Bento's authorization service and libraries. Rather than directly implementing the `attach`, `dispatch` and other authorization logic, we rely on the `bento-lib` `FastApiAuthMiddleware`, which already provides a reusable authorization middleware for FastAPI. -The only thing left to do is to implement the endpoint-specific authorization functions. - -Here is a full view of the methods you can implement and their purpose. -| Lifecycle methods | Mandatory | Description | -| ----------------- | --------- | ------------------------------------------------------------------------------------------- | -| `attach` | YES | Attaches the middleware to the FastAPI app | -| `dispatch` | YES | Middleware dispatch executed for all requests. Handle authorization errors/exceptions here | -| `mark_authz_done` | NO | Bento lib authz middleware specific, marks that the authz check on a request was performed | - -| App/router authorization methods | Description | -| -------------------------------- | -------------------------------------------------------------------- | -| `dep_app` | Returns a list of injectables that will be added as app dependencies | -| `dep_ingest_router` | Returns a list of injectables for the ingest router | -| `dep_expression_router` | Returns a list of injectables for the expression router | -| `dep_experiment_result_router` | Returns a list of injectables for the expression router | - -| Endpoint authorization methods | Description | -| ------------------------------------ | --------------------------------------------------------- | -| `dep_public_endpoint` | Returns an injectable authz function for public endpoints | -| `dep_authz_ingest` | TODO | -| `dep_authz_normalize` | TODO | -| `dep_authz_expressions_list` | TODO | -| `dep_authz_delete_experiment_result` | TODO | -| `dep_authz_get_experiment_result` | TODO | +The only thing left to do is to implement the authorization check functions. + +The next sections cover the specific methods that can be implemented to perform authorization. + +### Dependency injection + +The authorization middleware plugin leverages [FastAPI's dependency injection mechanisms](https://fastapi.tiangolo.com/tutorial/dependencies/). + +This simple yet powerful pattern allows us to integrate custom parametrized authorization checks at different levels of the application. + +In FastAPI, dependencies can be injected at different levels: +- App + - Affect ALL requests +- Routers + - Only affect the router's requests +- Endpoints + - Only affect the endpoint's requests + +The wiring of the dependency injection system is already in place, +adopters only need to implement the authorization checks as injectable dependencies in their implementation of `BaseAuthMiddleware`. + +### Lifecycle methods + +These methods determine the authz middleware's lifecycle behaviour. That is to say, how it attaches to the FastAPI app and how it handles +the incoming requests. + +| Lifecycle methods | Requires Implementation | Description | +| ----------------- | ----------------------- | ------------------------------------------------------------------------------------------- | +| `dispatch` | YES | Middleware dispatch executed for all requests. Handle authorization errors/exceptions here | +| `attach` | NO | Attaches the middleware to the FastAPI app | +| `mark_authz_done` | NO | Marks that the authz check on a request was performed for later handling in `dispatch`. | + +The `dispatch` function is the most important among them, since it is responsible for handling the authorization exceptions raised by the +authorization functions. A poor implementation could lead to broken access-control. + +While `attach` and `mark_authz_done` already have a default implementation, they can be overriden if needed. + +### App and router dependency methods + +These methods define dependencies that will be injected in the FastAPI app itself, or its routers, above the endpoints layer. +Authorization checks can be performed at this level rather than at the endpoints level. + +This is useful for all-or-nothing authorization logic, such as API key authorization, +where the API key should be present in all requests. + +If you are performing authz checks using these methods, make sure to raise an exception on unauthorized requests. + +| App/router dependency methods | Description | +| ------------------------------ | ------------------------------------------------------------------------------------------------ | +| `dep_app` | Returns a list of injectables that will be added as app dependencies, covering ALL paths | +| `dep_ingest_router` | Returns a list of injectables for the ingest router, covers `/ingest` and `/normalize` endpoints | +| `dep_expression_router` | Returns a list of injectables for the expression router, covers `/expressions` endpoints | +| `dep_experiment_result_router` | Returns a list of injectables for the expression router, covers `/experiment` endpoints | + +### Endpoints authorization methods + +These methods define dependencies that will be injected on specific endpoints. +If an endpoint must be protected by authz, implement the authz check for the appropriate endpoint. + +Again, make sure to raise exceptions on unauthorized requests and that the `dispatch` method handles said exceptions correctly. + +| Endpoint authorization methods | Description | +| ------------------------------------ | ------------------------------------------------------------------------------------ | +| `dep_public_endpoint` | Returns injectable authz functions for public endpoints (applied to `/service-info`) | +| `dep_authz_ingest` | Returns injectable authz functions for the `/ingest` endpoint | +| `dep_authz_normalize` | Returns injectable authz functions for the `/normalize` endpoint | +| `dep_authz_expressions_list` | Returns injectable authz functions for the `/expressions` endpoint | +| `dep_authz_delete_experiment_result` | Returns injectable authz functions for the `/experiment (DELETE)` endpoint | +| `dep_authz_get_experiment_result` | Returns injectable authz functions for the `/experiment (GET)` endpoint | + ## Using an authorization plugin When using the production image, the authz plugin must be mounted correclty on the container. @@ -88,7 +135,7 @@ Following the API key authorization plugin [example](../etc/example.authz.module you will notice that the API key is not hard coded in a variable, but imported from the pydantic config. The TDS pydantic settings are configured to load a `.env` file from the authz plugin mount. -After the .env is loaded, you can access the extra settings with: `config.model_extra.get()`. +After the `.env` is loaded, you can access the extra settings with: `config.model_extra.get()`. In other scenarios, you could store any configuration values required for your authorization logic. diff --git a/etc/example.authz.module.py b/etc/authz-api-key-extra-env/authz.module.py similarity index 97% rename from etc/example.authz.module.py rename to etc/authz-api-key-extra-env/authz.module.py index 13e7e19..8b9f2f9 100644 --- a/etc/example.authz.module.py +++ b/etc/authz-api-key-extra-env/authz.module.py @@ -1,6 +1,6 @@ from logging import Logger from typing import Annotated, Any, Awaitable, Callable, Coroutine, Sequence -from fastapi import Depends, FastAPI, HTTPException, Header, Request, Response +from fastapi import Depends, FastAPI, HTTPException, Header, Request, Response, status from fastapi.responses import JSONResponse from transcriptomics_data_service.authz.middleware_base import BaseAuthzMiddleware @@ -49,6 +49,7 @@ async def dispatch( if not self.enabled: return await call_next(request) + # Request was not checked for authz yet try: res = await call_next(request) except HTTPException as e: @@ -57,7 +58,7 @@ async def dispatch( return JSONResponse(status_code=e.status_code, content=e.detail) return res - + # API KEY authorization def _dep_check_api_key(self): diff --git a/etc/example-dep/extra-dep.authz.module.py b/etc/authz-extra-dep/authz.module.py similarity index 92% rename from etc/example-dep/extra-dep.authz.module.py rename to etc/authz-extra-dep/authz.module.py index 09d71d8..8fd5621 100644 --- a/etc/example-dep/extra-dep.authz.module.py +++ b/etc/authz-extra-dep/authz.module.py @@ -31,8 +31,12 @@ def __init__(self, config: Config, logger: Logger) -> None: self.enabled = config.bento_authz_enabled self.logger = logger + # Get custom OPA configs from lib/.env + opa_host = config.model_extra.get("opa_host") + opa_port = int(config.model_extra.get("opa_host_port")) + # Init the OPA client with the server - self.opa_client = OpaClient(host="opa-container", port=8181) + self.opa_client = OpaClient(host=opa_host, port=opa_port) try: # Commented out as this is not pointing to a real OPA server # self.logger.info(self.opa_client.check_connection()) diff --git a/etc/example-dep/requirements.txt b/etc/authz-extra-dep/requirements.txt similarity index 100% rename from etc/example-dep/requirements.txt rename to etc/authz-extra-dep/requirements.txt diff --git a/transcriptomics_data_service/authz/middleware_base.py b/transcriptomics_data_service/authz/middleware_base.py index 51f5120..0f2cfba 100644 --- a/transcriptomics_data_service/authz/middleware_base.py +++ b/transcriptomics_data_service/authz/middleware_base.py @@ -11,7 +11,7 @@ def attach(self, app: FastAPI): """ Attaches itself to the TDS FastAPI app, all requests will go through the dispatch function. """ - raise NotImplemented() + app.middleware("http")(self.dispatch) async def dispatch(self, request: Request, call_next: Callable[[Request], Awaitable[Response]]) -> Response: """ @@ -31,6 +31,11 @@ async def dispatch(self, request: Request, call_next: Callable[[Request], Awaita raise NotImplemented() def mark_authz_done(self, request: Request): + """ + Implement and use in authz check function to mark that the given request has been checked. + Used by the Bento specific authz middleware to return 403 by default. + Ignore if you plan on simply raising exceptions in the authz check methods (recommended). + """ pass # Dependency injections @@ -49,28 +54,27 @@ def _inner(): def dep_app(self) -> None | Sequence[Depends]: """ - Specify a dependency to be added on ALL paths of the API. - Can be used to protect the application with an API key. + Specify dependencies to be added on ALL paths of the API. """ return None def dep_ingest_router(self) -> None | Sequence[Depends]: """ - Specify a dependency to be added to the ingest router. + Specify dependencies to be added to the ingest router. This dependency will apply on all the router's paths. """ return None def dep_expression_router(self) -> None | Sequence[Depends]: """ - Specify a dependency to be added to the expression_router. + Specify dependencies to be added to the expression_router. This dependency will apply on all the router's paths. """ return None def dep_experiment_result_router(self) -> None | Sequence[Depends]: """ - Specify a dependency to be added to the experiment_router. + Specify dependencies to be added to the experiment_router. This dependency will apply on all the router's paths. """ return None From d87947c5675a6315d3b7427353a79251c88d11ea Mon Sep 17 00:00:00 2001 From: Victor Rocheleau Date: Wed, 6 Nov 2024 15:40:03 -0500 Subject: [PATCH 23/31] docs: authz plugin diagram --- docs/authz-plugin.png | Bin 0 -> 87062 bytes docs/authz.md | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 docs/authz-plugin.png diff --git a/docs/authz-plugin.png b/docs/authz-plugin.png new file mode 100644 index 0000000000000000000000000000000000000000..5be6b9448fc90ccb84a18220559df2e608d04c4e GIT binary patch literal 87062 zcmeFZXIRwB_9oh9Ot1}rf`Cec1OZWU78Gm{$vLS=7Ld^7U`8crOAwGGAW3M+IVcKB z2FV$bOp|k*RlWC~IrGf_!<~EQejCo?v->o3b^WSVc-On$s+Y>QF_?9D>){v%gTI8qOx(s`MBZUA zv=81Fs))fa_TN>IyN208|BER}d<*X!d~id@0fRXef&T5n;hzM-n+F_miq{W}9o~PE zg(A$Gasx)h;I3U&cj=ny_4a63+TNLSw;uJVO|Ed)yR&{SLYOa{-&plS>&HRty>r*& zo2hQmWJvp)->N361|3QpV>=x|Llb*!Ax^~fnn{wiZOTx|0;yzZqpH}b&(=NAI=3Wu z#iqT+WVCq2tISKxkhmf`Ra&*MR{Upi{8!>Wm=OGwGwWMA?fUyQhJ)%6)88)#u2R5? zkbkJ82M+xG%H^-!l7GJ{fAZJrKObUzT2A%%o3m&4dj0+C;em6rd;WeYM)7}#{C~cd z-@2!EV=z*r2Y+s)ce1o-)A(Lrn%sD2fb8<@OSI7MeR^%$HwF7O=MU5bheq2v3G?gT ztD?Y9c3pR_>^Wy-^MsO3J2=BtM6w*0z9)A<`izvWWZ?j6V@Uby9n z`^n@L|KY>=ECpou6MNBQl6JDYE}dRqF7hngoUdsqP>a8N_e0R7 zZHuMJUwSKjg4YD}Vmn!oO*00fZBXxcy>S3XSSEE7eHdN8Ciu?y`Wsm`xhpKXb|qSN zW;)@bLm&mFP-OM4rcRbK0rD8ozZ2@MWjXxyV$ql5M2r zMrgPJ%qXek<1NnVcST?OjjnuDQjwB+dznNFe@;O%ZSXWm>w2215%HjxrdJI{GC9)_ z`E*Xn3ci8=chiL&o2~s^8|Kfj2}>6p3zV>UU)0`f zx6Z<&gl6___8dz<>$&s#4ClY{yH8KjJ?MX;o9FeUGYO|OK>IfG{RB@ z)oCWd`umeSJthk7cS~%_;=Vf^85v;=#wy-Cbpc0rMc_*U^Mjr3Gvcd_#)SC%ZO`H1 zVHRAa@*mF4t>Dcs_I2)_kDN?NcXu6!X|-shfIIM^7T$F0Wk~FFFlsOL++d-m3XJ3x zSBWUQ(f(C%B*kFtDEG#-Y#z$r0@i)1zg@tT1#H*k2`%iI#xL7PYuzh`-BXvIW|S}w zI6QFNDp_k2C181YcyjJ{N)vi0tHfPq-ErRs4dZ0B|sWZgrD3y1%K4 z{?RDNSZ|*@=I@kj)!z-BB^fb!rv$Yo4~u*> zUeY&%)#}rG|7m0Y_hipi|Mj~=p_LE%5@vWDy6R2EqC)t7ktV*NiCR~kfz61KMqW~? z9i8&bww9kJpDk6xOuAIB$T2+z!7+QVbQ;{GNZu6e3}NZ;#8e^~&>Vc0X&6O4z@uzuGw z1zak`h2-Hh)0qk*!@fR2;fD~k`DOk%!=o9lTOrt^Om5yUhw{vi#q+c!T5fjmn)VyQ zcgB4E+v|m%Ps%qBF*6A~&eXFh#brPMuyFg(tm*v;437oJM7+tntf;tgv+U0>j^K39 zMineS2L|g9HC|kfAdVmM_V(P_I+y1#6Z|nL>Bdhp%_dKeKNT$XqR|G2d*Td-klqaN*bf{(o2R3wiavo>`cInUvSQTK~kMp(Tw}HHC|_Dm2larC%sEAS%x|HBm*RDd$~ZX(`s> zNj0gVaf9hpN)UpCmRO7vjL@SC6#hqwyl5O16%)j7G2B&k*COfG8wM6?V!He0XtYU= zE>A}S#GPyY>BXwMb}43Gu?h`f+9~*UNgteq-_kL`Zt5_D5{F?-g=>9jbMDbY_tR^5 z%JfCEoC?I9T(?j_?IZc# zsDxGI&OfyeaEMlNtw#y1WiQ#k;1%Zo2>ePZPcyI)DB6pLRzcw-=4q68VT6HnT059c zCkwnE6L217E0%1kGL>yFFVj#JtF?`_pY82;|A7Q#lQ{^$WUMvpR~>g;+wVSjvhtf~ zxbn2mPO-Z4)4TT_I1pwapEfu%n#glSLQT6!IZFZlN{YehC!kNI2m_cxQs<#VpSrSE z=&ieoHQIKkb`H0&(HQyKn4kDCKy&qJ984zZ82UEy57pP#$YkN?{}=e_5vPtO(MRk}}>(Gf`+I&KNtfw?0R?AjopAnTl`tJC+QEFx&`(i7$`I9I~Rd zbYj<-Ccq;`3lvenerI)%oc!q}RoJbX{YKA=%Km7-%Ui?;1IOsU-%;emDfAf(%*8VO zjhSkHo$&KM1tU@TpOU!N*LUOy{Gk*nC^9n60>@)j({>Z5>NX+IZ%udGNk@Y`mHf}$ zB+FmvaafD5SLW#WV#+#Mke$)i+2o~KsehWEU!d;fm9{MrZkQsZ97$b-XQC}ync`=x z>itzUWeNNJ_5_0>&{o<0)q~ybmbo8Wn>a_ z`7vdmas*BJ!Q9r04;Gi_RM0sEbrg&>3}gKWI7Wz{+7dPmRWtc_|CG&EbuXHRDi8nr z2Il`(7XN2_8kYTkXD$0oY2gFPCm4hYR!#?J|B{f9m|w~v7a2)16YKV zT>$n|$9;hDTYrNRFK=FIf3GvUkPvJ?Y_*T^4IcPU{NvrJ>x)eB!V4oOmSdZThexgE z2=}&1l-@f{)m|<-19me=9u~W`H7#UfHVR)g@$iCNpvKilty7m_gac%FjPHBHT;RAA z+x2I7baIO-Bm$K^v$x4Xs=k|CWhhr+PoU_@aSfq@iQ=QD>7nMp-!$|p1-I=qK?^~y zN-*yRR_CJ0^@t1G|BK4wMP4T=6j~e&4Gk?@#;WZ}#yPqsS=7~lBrnn^yll4?i1^fY zVmLkFy6@S2c@)jIWm_NL?>PWjV_8>S{ob4UtFNL}d9X_$LJ__+#HF+LRGUKs%1mbyrwUO-CgxCnM9^XRL)=Gbi_>w(Tup-T7@F z`S7SDMziNxQAD-RA1!-R63BVU!syN`B8GkxK}UOttgMtVn?h`)3^=q+U`KdLs^)zk?ln*~l= z9y`TmB?)vs+=EcRi)RVL+)JX^$kUnP_^u=PS5rw=!~*#XO52t#$eDY|8*o!oT|FM^QEB(AQUdm9 zf%of?l2R#x-@qi`Gx7D=OG9f8D?BsGZBDU*=Hu>%4WcIP%>1THQxh58=h>O}B16kg ze(P@|n=Irp1;29ZIUVQa={DK7@%&UbEFo|1(WBOrnf-ti+u)z(@0QSPc%p`m#< zuoFW3(bExrlTiy3lK!JBP#go0LU0tyMuWQ)SqlXWcOv4R&y-2VL$+}a+tb9Gcb8Z+ zlBN2aw)Mh@^^8>o{lj5|SP&jmu6a!Y_W^0#;&|=p_Ai0`?8oHMv z8`Y3^jzzZeb7(>dFcw-YhUy)eX(sjGXJFA)d|o{8KOHe(?}3|WPt3EkhI*5Jfw>RL zP4wzqAD3W%JUrc^f??Fx^CFY!r7Ij4KV%(GEXCsJBo?~BSXWCsEJ~9bD zQ@IsDL3Je;EpzIXLaw zC4*@nEOHizQK$@EYGhVARS^sy`5vg)2yft@m6bsNVYl0aB8AUp^IF2ETlk_?V4$S% zcTgsgI%>D-6OF}{deMZA!snh{chuaNrEdkIV=4cNESFxca!m-AU#t6DN$vE!ejSf5 z`$UV2i(!_Bam{nl-rROkn$}+pa`8tV;q%yVhK5md9d|Q+m^$>DLPcm$>MZfRh}5w3 zy^;t0QxLNSCx&^o!sj7`+n)~53-{bu4y718GZ;PObwd@3SVDZxcyv*%;@D?_EeB*E zy>YhAr`tGzPrB$_1ffp~PtILQ=WK+2@h@wPEFULA%$CKBX!i=97pr|2SI_JGzDRic zJt`FDR;4))i`u%6%?=(XiXJdW6-7aTT(BprM|YmBcfu!{Dea5#GS~8JHrUvyD%AJfZEX?=*|H%^#bDyp(hVB}EMXwQC#nEI1vVqK2YKV|@SCh6D0O6D}cg z@ig~_%II?qu_;(9IlTwp-1 zEEz5JqcDw4;;!dPX?*QU7Yv>ht^BYf!S|Um&&uRvbdyB9HqEw1B@_Mnx1)tzRgcp1 zy~gGow&uiHcJY-@sqVrgIYEtXY(5?+$-v%T`pc|V{pQUeFbij$!FGnxJH^1e)zedU z-4__L16Bu0)Ov>lQKH35cU@gwPv7Z>EXB>a%N<^GPHE=uPSqd;6_BhHBkRA?18R0U zKPwX~g0KGQJ=2}YZ!xZ0j4imivAVIwp6+dQ-RV9t*IN1ysjliIW}p))=kd4R)H~t@ zw*6k71+J;_zyEqrxyX)k2KeP?Rq33=b#b)rrq}y`2-8Qko8kFc2gZ55&iAz6U(gGE zV|jPKZ?o_+lNqp6#=(P`s}P6@@$cS|L4~qahCENow`4VeI!}^fZ^xkN(KBM7u659M zi+2rkW*R@8(*wpgeMLdL=i->0B?tiSza;z?JzU{XH0-8 zL>>&d<4}C4xoa`DEM&K`$h+*l^JJJ-Y{uQ!cgK)%>(7nQR{K4>!x3*$_b!TUGVE3! z#7P#MxVxisXIo8;0#%QovZ~z;*Vr{o%?IFrDvd{PU6bQdwG&!z{CvP~hFCI^BJZgL zRrPrsRN-ac4wVDY(Os?7=khR4-@Q9reZm#+KF5hPwIp??B7{)#~Cw^v#96?j4KH|hV9uXBmahYCuAZH`zaLSV&G`#8{sTPYD} zAQFL%s-a>Z((OXOi^5U5O%1!P4LZD#$b@OBh!(_a-cmqPum6bn^!@o}VMEOObjHBN zct{S%F)iH#NJIPO${Ow!U|}u;Y&B9+buqZB`Yy<1u#u>f@yId%cqQ{yVeo>#aPuvhb^8wdvK% z0FH&vJ?l%JEyE%86ZQ&bog}9^?*;3+FhL_&LN}K`Y}cLq8tI93ci-_~V%iE257O8S zQ86eyJiWb7dqCh5CkID!|4hIyW~!sVJfHkV-+pXXc&a6 z6e6uRFEF3M@i7SRRw-Sr%mSa@9Zv{pBYY9m)5M;(uH|3Xq8n!lLzCR0SC!l#cI z!lj1{2&EmceLi8ka8_2oD_>=+gopN1s=)Aw`i7X>xamqnfG>F25S6k0-rhF=E9QUO z>MI`RL?BF-7J6h-ijM!*^_FE*Q;5L45tllXAt#5p)!^f`ks>C)YIPj^?|k|4<*M68 zUHhL&E8dOFUFFRFu5OQ2+v3?RbU(O#3-O%J>Z-M?8y-H@=DNAskg#70qQ$+8{2kFr zkBx$%;o$`EZ@&eR$GNX46PM=aRe_d76lb+W*2K)S|72f&TIPgkFIHq2Sm1-58s5*m ztuu8vD2ZtH2fk;m`!aK`u}ydsOYW>GnT@cB6_pL;Qzy6HwP5r1_J(wzy1adcL2R|8 zdnNT^^d9GCHLXl-=!mc;9p33nP&`CyT~&V(y#1!ComM}vtQoYTQk!SH93nUTpgtY7(?pP>-5#GC9Me-9V^6+o zNYv(9{K9z76YnuE(qD1f&AEyg4-7`=+^ozq@#Q~i)in*FWzo?RYg+a>T=9dGR!#7% z@`T*`bu9qv>q@D~e~#hb@30yxeYvzFo=fiv3yxU--jHBndsWC))pUTFmWCHQw?C<&_-ipu59_(8M@;qKd=s*cww)gsGtRb8f&q5 zf>|+b_!;itt5@R*V8x`4FcaNXU~w>*s2|5hgdZ1INNy$}{JJ}}_0*C^=i?_&TFzhk z+?76;T1%>I$RB+h8a;Dd*O0B;k&=R8@HSZ5)-cb~!F?*jtB$cfA1~AeVG+B7xFkz1 z#fbfEKn{ZOThtc|F1AH1)Rv0FcbWViGM+Ar!<5Iyl&2IIdqAg)cXvtV^V_5Ll#>@r zX?h!3|4dn#edRvj`~B{EL(r%Lm_p6UC?$X2>x?FsDeg@NN(zO;2bjrhQxhG4>ZTQ1-ao%dLOcNwvB_y&QIPT(5QQ`sg~A8$owwvLrSlN%HNo9RWW zJLNr$5ailuFOd(x=b*}v@{Ex72)DRgUbw@HQHoh;|A@^uWIK$$lw8?h%;2pYI?bcV z%P9Kz>yYFQ#8hJuyZQLcOeY17)0@K6Wkph#;EAPWx+f-5!#UVK3oo?A=~HYfb5AyG z?vG>LV&)eTx&f>s7+!lW$tbmkE3%IJAV#@najL1Lt%37t*Kj~mcP;m>hdx<)?VsTsRivmR_X(7v4))%k2jg}+;hSFuK>6qmtUm`U|UH$4K4fkcQ zIOw~v=ctLpI->0MdQy+~Vs?l*K(jGQ$0PJki~*!GyG2G0Iu`H1I=^~ZV9*;E*OIG9 z;jpXiPVoZUmC=I=Tp{60dV8woM**j(19i*g>imfH!mTS_U-qfzRxvWfz6m@cSabxF zqYdAgs@84^Yu2;viHJtT7+hQRx9lrE{V32U$*5lr;{72?%FEK_z!On2NPObb%VS@A zGAxV9cfn=S@Zg|1L3c`SRZDKpCQjP2>+7ldUH7g&3KlR0(C{?paO(vo7J7yg5dyZs zIpvm4I!VJ|Jt_Fqkj>Bg20l!6ge5>XhO_DCD8xNzm{E6Th=-07rVTlVX%QH0%HTb>W$75=t4VBf&5>zexFuU_UVRg?DjItek3J}Ycg|E9Y zH}g1HG=9A`Ev&sVNnvYKmX-?6Udw%q|LH=R(MQF|PrdHTmWsNC@C2Iwpgdr}IKjGQ zC4~uty^I0nR3^af-z2OaMqCmmr6V9xhvj3~3ld}6u9amnC0-+QbQJhf;LL$JPH9r| zYk@Yj+d|rP$Q-;QoAi8_ZpB5P(ixJSjkQNYjU@4|XSu=H5q=b>A9CEy>*im{5#)aW zrM(#uZ49xjD+wI%+>}fK#F#j6$n`&Q_t5?|eanLNM(q<(C(|&4^C_4|Ok&cChRUcH zfT{j!lQ$VF7uAUDk=l7NAu+w>hurgD&z{K-z9X(e82n*HV7kj~+lfZ65cHo#^C z#8Unm9tBB;GIyjXK1f}xz)aC@BB;*Xy=*Ht-87V(KZbMN>U43c*ESw}WS7o)RY=k_ zu>Z+Ih;L|a4>O?TI0z4(0NudKq3}#X1MFC(ah0VE`dZ}(Z6$3MTv&JRFOz4M!P{&5 zBPBd_3F<%zIteFX_j<8~f&-uI7S|;p#ML<*^lp@#axLRn{pslg!xWCTeqS@Q#H~Z0 z^}Z7>2@7oP!!EPMx6HwiLOVN!yE3jQ+#yLTrap58MMN;L{8lSbCDnD}rcUgb6zzX{ z70;DE$mTCLXKe{NjMQm8+3#&KNU5F-4p`|Id3*Eb(FW-OAA74VKB!^SohQN3wAY%6z&b8l)*e4eL%T^MwC6m z^tGQ$is2GiHNth-@u4{o!}n7%eq3w`c2xVK4kZ-b+K&gQ!q|HS*1a8ki5j*Vlo@iD z{OyGykK!k{;IAY_;y;P@nW-!DVCGKltVigjyW z0kI_cy8?j)cOvTLD32&8TcG}y?GPLcbMg1MCv=BN*$1I4|8~=#;GTrVsrYMI3cIm5 zu#lynazEw6L(DxS0RA8_TDaC`j_TCV+5Hbp^SX14%|brjjEJQd?fJB7cd&Al1wt3V zT+6TdypH~Em$vzReJ|f#{mT>RraAhif1*B-;1DU=V+k0HHDez}KO2G|UEt94xUrKk z=H|fPZKU?{FBJ$&OgV{uk+k%K7&LK=J`Q#w8yL^Z7Wsg5NpDF>ME3m%Ahkl~iS8Bo z1V~5Ry{suQwJraq+WDWW?|T58czA|o#&ZuS?bbhOYinCF*L4vU99^J7Ld)AO>SS4; zy7Q@}|D=#6mHm++{E@ufn1Q?2orQ|3bGAim=ME+n{oAp+0cprIbZjDrX}cz_ocaUpr+9HQ-ZyW&X_| zDyTEEoj3FMDk_C1AEP?j8p-P%lxi&m03)ostPRY}Z*+5O6WZ|wn?pzkr13boK&2ZT zxriEpS_K6WHN%^iy|Nrh{9367 z=6a!9AT&{f<%k2ot^I+z6RaD`c_YWXvnb5EaKM^Dy81!%XxiLhuhv>uaFLyHZ1JM)!%A`XO2gB6>wG}iSxV@8wzBvVkV3($v z3`iBW_go*Kxg=eK?))i(hxH2|XisVfhlbkv6`~dbOJN-ZTK~_MbFTHr&YX#-dGv_z z=QyRj*&b;qB~;_Qryce>Q$jMH$m{nKEbT|tgnrc7hOnaaYAD9y$M@0tEB%%7Y~fob zBGepIEL7mKVAFsVBvHQf2wpcAwA}taa3;o zE?oY${<#a`VGJvrRIVRPART2Dv#Q?LgKuJRfZ7axQryC$7ye59X>tr!|DWIVPf&+>#AQq4s zgDwEHd(?>rp6Q_E2*g*&NroHjet6}5MJbBXkVAiTM|eBM&eyqEyn@Wf$2D$(isVO6 zeAvbD3E=`qFChWK?em)Buoy|#oQirWHdw_@5CPR+n34$wwB8Kl6aflZypbse&Lv z?grmJk5>7i{NjHo2b8N^+}#mliUl!b0J&Fs;uu+C%=kDs20FgqI7%3aG36W)b*4_I zr>(MdS#Unyt11w0!VLoS{!=Fl>lk)y)ipo)m+2|aeQoOhB;q>minM=XFj>X|8*Wnh zKLjO>gQJ5W(z$-cFdSqqHve!^P1j+q;Ya!9*#DNG+43x!C#(jbS$4F_Eb+m&KtW4WP^AmF*R)E<7t zEWqC0-f#5DL7MgBXYSw2NelMIWbMYpn2F`PRsDxwWr6AANL#e^zh&VGHGbz$pI?M zmLwIMyd3R|nYw9}E6lQf%J=Voa+>K&dwW5NgPk3xYWF(y&70VF?@sBYX);gw1_WqI zOFxE?dM`(pnwBvM+=9lE@ci-JSa7u21^>q<#I>>lMp-E(N6hvnfZ zH`7bkE%)u+d#anyx~qlaFfErZQ0u2Wms+(dmwStx1q-(?()jjyZCI1~O7yN?y=vK& zo!ps6*2EmG`oI7SkTp^lK_AHQ<#s5yf#0aCKV5=iguv;;&U^RnWn*QPh0n3Jy_oatFZF~f<8*+pubRDmCiXPLL-;@;DYyG1J-wc#;CZxx zLUHiHha4fVU&qYOK6vKiGr8PttK|iB(a(kkC4(X-{#<%t`*=gwVd_xfb=WCB?`@Bz ziB^RZtT!)hAWaOWWjE4%iM16Rw!iV6bI{b(G~6KkLtGrcY3->{*IlswEd>r{_~{-U zXx)Q+P0h`%uxTkYBt-Krgaw!aErf@1;{y8KR;~pYh>#Am%Ko2;u6%@ z*y!sf&dU1n=IGqqobXI8ty>8njqmpk;`xm|31RP6RSR-$9XvUgNWE%pCoU{izhAR4 zqOv)bMDwU_cu0+Svno4ED4Cj5E!%2E(6Zz6BkXvWRl2H+c2d{#?9wqS{fN@5MmAiA z&o(;Eq6m4RTFLnQqK^?GvZn%VOOxZeC++*3?Z5t_HMj!Hs&N(tgrq&q?IuC)(WNEs zDW5+#l1l3v)^slxdMkUwBz}?X?&nJTyKJ&E2)XPgkN3#G`#V?L7Acu9Lgcsx_TIs7uMZC+;3 zahrYgXu_+?nw!{~sx?zwg*dv%qGfXv`4q}CV)0>FM(ve6c@xpUqIsHhLJ8|($CgV3 zIB{A=t?D7qk3uupa_7;L@VRPz>;5+hjLuZbZq;%o)2AGBZMI}_s<#(RMIOw)HZ=O2 z)KWg)-0k=Qb~<1c|q4HG=1nuUO)RI62UzRF9Us?S}i zyLZbMkEH*qUt204scXq|Rw^mFoo*PR(W8^+DHrlQz(pDw&l!OwNjGLLZc7pP>^zEL z4+H{8LuyLaGP;wkr`7yP{YJ~gLk9i7|CkWsdE;cO+wV3(26J5On6vK>g>m^DXEAB( z?W#DCx9D1$fwM{}lEps{eVYa1bB?W}WoOCWAm#OI+|H3F&Q*JlUG&3ktk%$(d0?<4)cR75fvoGwsfCsx@POQmnhJyb4wq z6O1WIO8VN~GSy{;#esA~GcvDP9a-w2T(o&(qg);Lz9c;3PSusJVtj-`=oQSnX8=7Q z`>?0mwyM@>{TLf_aB=C_k~a#Cg|6rmrZdSK2bQ#o=)1cOt@Do zV{Xw={;r0{p*!Gm-LNyayUH889!gS0ZE221wcGD_i4Bh@A;eX6Is3qH14?Bp(vPk* z2Av`n>K)hBa?h2N-lNtWd_3$J{flHsr2b0aT$*2%Tp)wi+e&{db;Dah*fZ0zT&aDU zsiyT_y&c?Q7uB~m`ZNZaUI}^?XsFKJWe8ZnHCI$HDsQghObm-FI;TteEh{-4{Aap* z8!M;u^u{UH9;PhSIdAYychUkya&7fM`AIUSN^(3(pU=H+C)biz$ULD58+ilvz^a1Q zXrla!OjjwhLbvlh96?rc`}6wpG<$M>#dN6Ad=F#$+5yw5y9`uR?&T(;ayLe`iz|eW zI6A52b*K`*fcEhoLI0;Ou znHV=0_VE3_TJ3}Frkv{2O~&E;Gm6M#z`wNa*OKNz>|^BhQ>}lOjKY*8EXeeWLJd{B z3sJ`VdVAukvIRV4UOJ%3TeW!^j(nE_V`_!Xcl1mRnP^)Y@ny8XpS$M(mBkjVk)`#z zo3upvwSd`~s%U$DtGD9ykk-#rCEEe*&MAzn0) z?A~jwZ;cIUKwtRI*HPVk^OyUnre*|+H|z~wb>^kXZ#rVN#5ay`@J8QtZD}o&TV23t z)Cq4!z?ACVZx!y25PUm4Ujs*O&`GZ+7WE7hdtxkICaAKKME)rYfO*iq;B`)|vt3V1 z=J@2xx4LQQS)& z5FsGALUY37c1-#qiU%NZ=qrE4-KU~w(8?#p#BCS@0dK4~fyuI=&lZF|CVP*XsL<|g zCs}!K$J%TBY1oO%XezuSBA=$0(~@r%b!Fo?S#J4`^=wQA7V$)Y_r8OWF;I=xTX~P= z;~%ri37>FRiu^21#O+j(cY%|E24Z>wpE%c*Z)Vg8ffp^QZC&(mZcV+RdVDZ@G9lh3 zuTTG@!^e0pR$S%mK=bB$w=L}5(jl%smF~6G7PUkmIg*XtK^D?gU=>)pYVRwdn5-AA z6vJAunOSqPl|<8ftW^VM`Dy9beoRsU#pdmBS*<7rf&+Bx$j85qLv_gv9$dO*6D?s> zrc$Hzi7(2Vg}rI`fOge`UNE8YXS6%XK0duOnGc`CArshZzk*e_@3Nuen}0`Gw)B42 zyrQ&8E;O~n+k6s!nvzEL-4pMFyFak8+nyUGCjl(e7 zNSAGG7j+KrVjLuf8l_7>YMtZ~biMf_Pr&mDtCAu|yF^WBX#&ut7I%LuR7USm!XAC? z%4t<(U~XZJ4^Gejy7Ty4lySn!GvAPWF(wGi>piV95Zkq?`LE+AKR`xj`|Ntfz@5~Z z&^Bzd1F6K(Aj^t{TFGuu+wV}4&0eod-+=?Y{(bRssnOezTTu8&as6JsnpU@zcCs-( z<9wG-@cJGV*w>}$#|3CpH9y9qz{D-Niqbc}Y$*4#bH8V4sY`k}c?o1%o=_cW0rLS@ zJNT$yxc=x4O4AMP-m$@{Ag2 zo=$|u$^Hy8Ebxayd{cg6RQ}jQQcoc`$L+A4Z6U~EO*v7e+%i|p%F>Zbm6o`N+efQ7 zA6xx$vO!Vaam@=fx&91SO8$c9e#IpD(>i~oSov2$)w}nz*#fq`rj7*BD9%7w zAN^&!TKDjfQp54d%LrdEY!6-#->6ly@h-qmZ>!qPu1q&m`8NjMl2p%AfOCNO256*I z-W$RFs^9Mo(iGEBbUqT3#0q)X5mJU5zVam62V64%7CzoNmQYfk(J~JXpq}~5Miq`} zY_yPsAy`fPZ{cn3=f-`%ejZes%+dKSw)G_xgzRJO5UdT6Y(#n zY6bDm2|DOA=KOGrFBKk(|+B;CR5uRk(q3?44Zh z#rLBNR?adJmT9NYf?`Y99;@XWidEoXtkwfk0-FqsGj!Z8BqL} z_BsXaoqz@TTrCOR?ezxt_9k(I7>5RI0hswW*t&=%`WMSC+(-&TfU8)eQqr5Z`L-I)1c2Z z42N7^F=>ez^+QjrHQVB0H>t3vS?3J{Ga|_uJnqww8Zm`2*!S#jC*}^LUI!%>odXK@9~bE1MJzY>@ncAi0UiRKX&T zzqdvRe0pvb1`Kj7L(%s4stXznqUu-pzOVSKD=*@{%iJU8e>EbYdc}Huf63Bx^TKq0+GJhj5aj+F1XMGK?20U_o&*oT z5uituW7C@XwS85=&?~1;t;HIQ;&S4x&Y;Pv<>CAgMOF%k8x#caTpx>6LON*1me$t&D>=#uCmCsUEu9AnHWa=ey)?tU)%Z?k_RE3& zA)*)ea_@h{lyc3sgtx<&|@)< zEV{>B`tncJmq&!sHX;3n!aDj0+ox$jllplw>24MUJ(p9J7Xd?l1yommf6p%r@+j0V8EHL#+TEr;G zas>lU*6Fqy6AQZ(=}>+gd&Rlg(7j7gc+kS%?f%o!4d>kE=JujuC+HcRK8z2N8>-YQ zOxuB)zFA|}F3S_m@}Nv*TgsnacAnzIg&Hi=UeBhA%cA-SK`}uARQ|)mv`Vrf#%|wb zL}0s+k`6WV0B1wP!u?r=44RD8a3+9Ma6qF6MUYcdY-gf^?MrVlbf>CSEeET5cfW44 zq;KxZ-g=Y*?QD5G2yuYq#o_?}x-?ZhsOWme0dziUOb!;%W=n_YrSO4~n{AJ*0ogkA=3lS;6C?dS!TF_04>3C!YYqB->AOpRE@)F(|O^&imhzDfR+ zqH}WRzH*08@;D9HSFAu{?(#})6HRU<}hvZhNJH(HGY5)e)TUH0Pmc0EjDh#F2G)j)7-h(2wv7hGIY z61;f#!*<_=TY9;smKyRYZr>{3dD1J(R#{(PpL$U@b(vdUNBZiOwe9`{y8ilhbQ%eM zSmD9cwP9V!>J(VeG-%qV3>Tw*58tI*1U_*K5K5)=?ou_#WF|IF9T)5S{k|VxZRk+M zMmAxMKp5afuZ`B`mG2Cm5b0A&YHX(7smLpC-9!pd8`Tfw;zRH8VYXG zBdt~?Q$7n`GcME8{aSxc(WX@N8aoq%N8Qf!Ykm7L)xT&yxu3d^ObIF%H4XY4!ohYx zJMM-^k(&*EetB6F@|`>Ztjz+{iCMM>xog-|ytlp8JWMtR{3!-6wmfLjkgYU) z_GU3^2mGz2yT4)%1<ftvu39Hwk7w=-{l!snft?A%TLERoGplC%FDe%fJJ zTvjJ=e0nKGI+Xk*Ee1#xp~0Sv`Wu8G*spO0Jm_#(6cvK7NHU8!eoxyMQA}a-58z$Qaiz0bqy z4Rk{m;p9}K9MeSs@fS~1(^wr>G^&*Q=NYpypHGIgZqD3F@m{F;<2laK>Sl=fPPsD+ zaWEzT`i6847oA^C-G)9lru>@YYHTfnG7!Cxlfc%Rh7R2YCuG4PFHrEaBwGR{TDkN7@c?@C0?jNfaquA#GYilJhdfD_%kzl;or+Upz{%X6VA@5 zR)_Q9RAEco@+k}daVwlE^m3sw4ZRk#lbd-rT%Xmln1zHo>6q;FTcELn;PeqlX^fnp zD-F!f1O>R7bDtgu4wPQKIg&J1}9kikg6OV1_ZI2dL?ay<$WQY&`+yz_nJHEL z-n=>cW71E9egX*&kTMQ>)98dPtS?gb8@SiCnuZ>r%7DJ0iA}dnZTAIqbT)=ukpiTH z{uEpx0JDOAPbe0Q=hNK67igQq;njb`Z&2>KG5HX$4nAbdJ2B_`(|w`?9K>1gt~V=2 z&(?OLpm3a%Tt4^he36M%yTQ2fMZ1JZHx2l0KCHL;~zjKs4sL7~KgBBu~6^KKqFB`9) zBu55-nSUQ2J)j*K!i`(^*rFvLv{vTWEgAHB?mH{AD%o*hH9flBr$;BPRGPD|;hMo1 z9LbmBKrc|Y7OrzzrSiXcGd$(R-XJi z#6JRMpj-M|ZKwbMUhB7Sq1o;;d8j=WvmaglQaQxrT^(FkDZdEm&Gh{26W_3`5e^m1F-eckRJgMIgaaE;WbzhaA%f)r`||^G z;BS_ng!pfx(HbBqHw{&1hbY|$>JvgdNOj=wiz!IMuEA5`8)EK2ZH*Q}{ZVTQ6w_E7 zlv8{T%ae3s_v70>+U5^r$chU{Bg!Pgc0xO?{j=+&KyM3|CUCieLo~ZF)#a{2L@YHN zs%&zfi7)^O-b1~;Uazspyg@^bQ$^Pcp;H_z8YvmZvVZH0dO&AXbCo3n8Y*9?0?=2_ zepco(S`R7J5B-43l^Q&|Zs{TynIwlYt$Cl%gf5+cGLXjzzUmT(`a3rii+nH-Gwm4b zCue~KKGg>J*b=)NF0Me82&73ueY(vg4w5)J6Gw;#U{<|)_iZQ3;CUzz{5}(HXAIXz z7e`y;?U+NY!})CDn*swbiEOjpeDBuBRO>XerD^p`FrSp21+%Qv%d=Q}rIh3GJ+Z4~ zMK8}`AEUUFKK%Yv#S4ZFR9PIC@r5&IX^QkZjBy`ld?)B@7c5@u$OuB>GsyP!H;DB5OhK1&awRexjpq z)vKXz2GzNU_Q`42Pk{346p>3m``V+r2vm}x0u(e3g=g9`NCl$@Fz+UN28$`-_JOt! zD}Byu=wgu=)|d(^x8>Tu+M)jaPCoUY5@dXifS`Bu+^f#vf%8+Hdc_?G(9@oIJV_c( z0D!Ayo-~b!yVxGYUCk%hTC6qa`K5nZoqO9uNqq}?5HJ-s;QCN+=h*x|9K8Yo_%|c4 zHj}Bhe0T!81I2DkeM9d9!voKkAcBRzC?^K!1rt)p=L8l^OQz-+Y*7%i(6uWs0DWq} znV-n18bi$_@(}t@7!89i74G|;{>CqRfU9EWx9GV6+*R9H6;p_M&*`!HZ*z0uz$gJH z{R`+Q%i5&hu9vkuGIdq${u=N3=?u)?%`ln2Fb}+@pD&1f*5!c`>?OtK#AgtpLRH=~ zCt!a2Jy{YFZ`lNt4uCZ*E>L2Q3hX~iL3-a*M}Zz;vAu?enCYOc^qy~|ce0l=_uHi4 zbsFygAPRmMs;mEAau8igFHK3tCYM{9L`h(hSmf#JCzateu98+_@X(8-pUX@_w~-(~ z{ZNC==vP-^&D14yT8KBUmOD|mx|{Taey|TQ&=={Dn7D~kr&3rXX^~5X{5`b97EF2xhuipJd1MX2T8hz2S z6mkn$`3NcGodG2@uAWhriEs@0D$47qZFY~rA>5VK*y2%8Zc2f`FcgbG`@Ve|^k-t{ z`HPn6;C7-58o^Lw`d2|v>G294fieuR7$!)ifw7kb9fAbuZHv?>JnW~7U(Q{w4eh7?Eeh*;U197*Z&K&4^R968Y8-;(!i)XhviBF{Q$O9rr%2o z$CyqB8bt*EnfH8YO`H|n2*D)9ka3P-BUyd-hq(e)jQ__PY_S4ZCeX=s+_cp9^17Gm z-4$4HaC1Qf`T70JiIm~wGJ)2aTUawK&G)~q5e#UmfAC870mlSQoF~xM$!W0;WE4#= z-SZsvA?Y1<#xF1Cig6S&Jq%C#2Oc4;3g82&ZIQ~Zac~c=IdoE0ztnj%(tdg&sRV4h z6^OBlQ}x~ABGpp_Xlh`t&lH6`K2L3BeGhCe(C;ek5Yv7l8^13MuV-XT}3f#0H54^@0XolX(~M`D?{A z+`1n?0*Im~ku!a^eXv5(a=ry?Ox^E$a1&yp3Z&DLqD2{Tu_-V9`;9T*9y4K5`u@Ri zr@Sw~T@qHH&7}3d?GmKGQ=)!!D_warzfe^E>j@|g*vG$LBUcC@S_pm&wt)(&A;EV% zErZ||DR6k6NWH2dKAp|q$D zXgs5?Bx;G0q#0Ct3(dy{cG2P);uz@%GynPl!D^J@!x3nfxw~6IVUIu{x&sG}(pmrL zFo)9(cMk1r7?FAwBJUQ-K}(Oj8Q;$T3j%){oQXX3l?pQ}1SWG0j$MFYl7LloVKszP zMDGk#{hL8$|4;t;7p#qHa;K*imlX4@&m9A%M##FmR84Yt1jP#+0k}{3FI>BOo%(YQ zS|q$28fwj-3$AqVoSujUDltj%24|@C#`1KslVCRLyDts{ad$aa)cM8dq9Kt8p;8z8 z*mIzf8+7Od8m+Pjj#C{CmAsgDNV^K8uVY2rUbqp<4{2}sPrsC9;5D7vi~C+d{Wl!s zZ-(0wkmefFJi2M*Q?quBHk|;QmXG4LqwKoX)S8@80nkB{R1% zV(2OW^%7Ju+JEFkTPV^l4@cAf28y7$MkLJNm*6BB|69O;Y#MI9fGa{`2uK_T!5XhvD61(}e)6rE`~huCE}4u^%i7NKpZjHB2T z>jC?QTNrtuZ1M+=8}2VU1Uc;@4p=71cZXP%geW52-6b7Li8RvPhY${ZXztuR&-?qo_udcp`{fe~oW1tm zYt1$1m}88Ugw%J^t_LxV#^G=IL2E(&6sYw4k4~5Sbr2N9;k3fv{7=ERL2XHjP)UK# zcdD4EvpUtyDf2<{iQqc`-CKbHQ5*YZs$3vWBNl`UtK_yP|GusNORGIi2b z&B-f2uFEdBRIS#Y!%$xWWq(0F3k9Qq^hV$N2E1HUU(?8lmQ@vx?B;~K783v9CJ-3G zFgU0SOcDuyO(uejE~Ulq5A1KW(g;KfltGqko%ErUgwXCOH5}z8y(`e|4TAUzaIv1X z7W9tzA^HP*rikMx@!Af8sia#%&4keF5iLtW{3P<84Sk}x=NB)7B%<~2b%j=hZk_o> z87Vda$TNQD0a9fqi|yuj9#sBf=Zp&1TXTSLBOSUmSMg=j@&Ncj2$KS4z5_s-#^JC( zg7DxOa56nM6beD(V(QxS1WGw_N-snxwLGC#I?>;E>B1QkD4xMVsV}nFo=rFO?}jD- zCxM=}$){Pw6Xo0gkw{I`|L@Fq8I8}WkaGREP4ND#{g3@l8@7}W8#Mw0#N}!lvQ92e z{tx?|%{biOv@Y&nj%%+qu=9SVxYqusAm}lE5Wr0=}ALRL?e(~F9X?j zYs`_yn9c*F4FW7lN@5gkw)BJFlAo+D->GVIPFaNFIkmd@8}@wiP|IvHh#G zTd?--5x=tb1?$tgy7`KPr@mmz*)lN^tRKt$3$|zei@MzoCEfbdZqbAPJ0A z`m$Ur)XPYdL}C3h!fE+)%qNR*A8cZW^4R1d88-zs8w6*got0DmrYU061t~l{#aAE= zDExowA315cZ0*mm3!`sA5<6>Fu+Y!WyS&lLp(Ov@Zf|$@8jXrKt)wlzG?>jTgWC4@ z?_rPe=bg6!l1DW6$ZQ01ii;Ieh%4htGE7XK!QP5-hb)uJ`MH-4(Y5$i_JaVJHyb+} zJqNAF^cfHS9zgvSI8_O?$YOmX?oFZ*Nu>H*&0vtZdco3jtiERfQ_`S7Tf~vV8JZ19yGf#vVPWjOU0_!yv~i$qwp6(CfurUN-8RN8 zyj9yH6ber{WS|Ix2zvGiftQSllaD6#t|?1y378N0%^W zZf=#!moJAVhq0(J{}bc8pf@jv%wWu!F9!%e;w z0h#R2?Dz^D46y_5&cUGv)7yU6hk6?*&ocH=NKn!5o8FA31AuE&!90x21bkFa;Md^x7%OAKIw# z*Yf~`1PS-Y{8qwC#IP#Iyz$W;q-FnKRR7=f0EWbR%x7GWal!{2DkZO#alH!iT7=1$ zqaKk+6qnr(>4rUw{r^%^<{qf0+<^Riiya`fH|LY^+j3ML2=Bk!+xvP_WC4g$F@36+shYYeDGv@K89=8o1x>o zhRPqCv@SuglR&9ab?C=%z7gm(cDGfy)8X~f*nC*qbP@~gQ%fu#LTg0map3&WODora zKz3AAja4`=k=(LxFXAaadluBw)58U?jgrq+Oj=qxwBw=+ z*m>SJ?PZi!)YgtRFfjPIHw85BzG^q8>b0M^zn#eZzuU}6&`R0F%5~@;AMW`F1@Tlg zWvgZtwEGg$BE<1oMlLY%@o9t>yJ0QE`Iafr--xl%b#df%TQXm$)j)6mcWW%Uo-+sDrLGj=m&lDNdI zchB-mwi6N(nhxZ~tj97iFt9K(N^#U47TU0tmzVE1iyZ4$odj(@7>~pC2#R%GVmbo- zs{Ifz8(aIFaN?>h{*{=52N$f@k<`5x9~?cPTMd;Zl!F%I6;B}!%s2qQ4dBYVsxx>5 zxZEEGsDL&p7ZefC(ENnaX0$&?^Q-e}zm{bvUCu~;_Z&sgrXZj3n{ijC3?xgm0_ae* z9Q1fuPMGl~Y)62Y)cuM=y2a(ZS{|wihXEb-W@%a3Khb=4T&`O$!-IsHg@I|$Y0?2S zy16j5n1g=e8WH=yR^Jos$U{HU07C0`iV`oNCfK^z}gK zArVZqV%y0qYiSAI9T0U%v9t^flCZ6Pd{tA;DxC#2@c(mrejtB=q_Szcx_fLjBRRQG9MSmXO;a zkk%Dk-0l50PIS^x%ce`uNQ5T;ICo&y$dCo8P9|0eix8%ju>zKVI9&FSUHCiZmty?~ zyl;6xu;|rf(~3PxLBldec1rsqHoY3{dLM#tIyRjOWiTk3rC8#7P|=r|nAlrjC@I|o z(dMINDQM5MLhV7|2y;KfWpiF)?aQZ63W-ImG&DaK28U}rDhapRVg%F>K?rCVx^=J+ z&~Ksn!VL#g?E+g`S|aZmexQ4`GF)P$S=`WV<2Vz@OLj&Noa$r%+E#e)8^BvaxQ>;2ZFAt`N1AK&TMyW zs&L3$0vo?6RPcW8&n=j)kI zfXugA_!Kk)O@S_tzJ4(A*>rVtd8PRC582_Q6q{Z_&%#;zwG#EMwfqB}?_P$hB7vK% z+Qkj@@>dCPp%)35r>%@u9x5L1h7B~8u9jm^z4*fk-3lj^s^UC2_xTyo+`oVSW8LDT7zdb8_o#3#ULx)p z7S?Vf0;36h-aj;;=cO}M*SS9aU|{7?_=ArRd0dvAxR_X3o80^$53CVTsilzjlnYZ+ zQ^Td1L`3vhRI?cgcln&4ebe?3^z5&C%059)OAXnAW2+|?2PQl}(;aPZwDtilv^&L# z9hj>7TS<*bZCN9-^|ogC`{RL9Q;j8IV0ZOsZJI2uO;I~Q;&B8NUJ$jWXXTkLUB4sK zXm{Zm1+~>q4%DHHMbuu0V6k$^6jGwVYmEhy-u0ADqYBfvyuH2YYn<>8>B`%T(1KM( zTzE1OZ_BGb_Y1rccM5p*#ix>Q9ML@cx7VV=Id&#q~`dN6Z%1Q$-g)Eso|j`P`v`HNTuS?_D3YdD}S zC^_kK1#Vs;V@g+Jho#kk0!UauRL<_b@Q4DjKm&?qdksBI1*6cgFrzk`c{Cb*od=JS zUm3P7%>sk>mX#|!(v3RmbC)|P9y9S;48M5i5hTur$j(-?0?Bz}oeF#dx=XF}Kw(rX zc57DMri_(kSoNJh%D;#DEPZrT zdv11i0Va&ShQ1?gUhI^bL5%`1EJWla-Shg)x!(@L&0X!>X8mP?Rsch;H&c^OggZ=q z^j|X@8*<_Gb`zUB&lfzlx5P)p1}-HzQu!@uWThWi#;PFLqaI% z8U`d`;mQ>Ae7PQw9>7|MXx`+;oH0rn&@q;SdY$>$2jM!%zn9TM(Xg}UiuuF@2L~58 z`_Puz@uEle#Kgp;_yri^lP*G#(O@N>*@eW=KOo=_VkEve@b{8GvPy!)CDZ57=rm!E zedVE}Ab)>F5Us((=*?2gyKYDREKXP_bh*k0`P0BaHk)ja?8)$t5H1Y%6Z-Puc%x@V zT^>Mk5*~SYc*y0lG0R*@jh=zed-v{qdoFLGusy6%yEs@pC&i)L7DjSwNOcLa5 z!Uumj18?1Xn`xyUo|xn=*$DxTv1NE`s+QQ@p5k=LSx zW}*kq)jq)cGyhUp)$FC-vl{*##=_y6D*){ek>lMY?EnSk@1vum%n?O-tl6r|7X(^< z+XaJC`gki%L`PZ5Wd0~*_WBy%n+H+tjz5<3F2~V>(WArEMCDaPri(It-P@~t1Ua_E zAPEVH8dE|D=+a+NzQ8yBpk+kLqZ#X_OsXFqft@kP&AQ|M6&8DaTtEDsC|*cN$aBG+ z%}o}ERT1d!;{JO$kLl}%1~DDSAtSKrDQ6|djZsd&A5?y6b8ENv_*V(xFHLA07ev;SB912D|++c!!SA~Xq{{?9mRpAjE4S{7edLT%dkts z?{gfF^J-DrIX<_6#r~Oi^R}%9j|9#zD0N&J%IfXyMBG@Q-bQ$VFHhTOcz3~IIRXYS zc@~j+ipF4P7YaiC>ucnW!?fr1zd+A?p*1HWG}%T@=r&-5D!R+r1H@9H|FNViCU;uZ z+%ttH+|^PIvE^AlK++Y)@KjOAA@_301^=afao~NY40mWLK$9aKNH$GDq$!BOF+%5qwvK7nWZtRe{oEOT zkNskZfEFO`evNx7&UDZOfAL#QTCw?^z!yOvHSa!VX#`UPRzgwF(tqW70z!`fkc-(p z8U~#Pt$3s1ozx&glBFfNF~1d?jG7k>T(q z99H7Ev&Gl{v9v(=%pKnZzWpKKzL-Fb>NP(Vay}cWN^$lzx3-oq|M|tLb|mdzc@cE! zs*85t%HSP3t_~-`(Y`t(pG(H`h?>C7XIR!dgV?g|yzZU4Ye$=B^h__BeP5mnKM(045L zYBRL5krhgDkZM`bls^Pb*(LZ+Gpgo?Q5@3QLCTjU;w<=oX6Em~#vQSFNzK2%zsUyN z+DAf|UK&x)h7DgJA-Ahcp4M*xq7FaC!@g#xXSKC_pcp73OG73huA@StLaS8qpl>kU z?1vL79JKrn{;rP8J#lX-OGB6?LSL&dvdLTnL>~GBp~)5_wLAzJNgns~JgqN(B1__A zL!r+}4*~<)N$52wn5OAyK$lV!h|=T}BGAcwNm?lOTZ~!T z$fZ_ifvOyuP2B>(7`=u)(bjY-YNB9v<4XVN9%(&8y1YilV-;RgA1!%;=?2q$J zpE(#@43H&gN`4;k0K%Lp2!=y}wj|=Nz@3`cdUu}Go&jkexGnkFQmp^VQ)4U$+I+?*&kd zNW^a`Sz7wN=VJYOkvSi#RQjh$)YJ+oB@froBnWj@-$^TsQSAn_@ zouPWR0HWThuV3Z;5FIP$kaJPMZTzg^cnvgX+`5|sAgn{1Bey3~F8aaZj!RbG(I%pX zPTBsJb84yv+&XA+MCe>!x|`a9^EwigSMY+b0?xL)`nE$C;aSZqzehTI9&Z&ks z^2%%i5}R4I^DoaUEHs&S{*xg;~nLszc7X0~XTu z5PJFY;qwYvsUuW;)2Y^;@h#HbQWms#fZjcN%n|qoY|nI!&wC;o0_h&C4}SRI&gQlX zxgwJGf$kA#U_rqg_pmV$OML?5g2U$T*&ilv%GBZmaiv^4e6wWG{5`kjcy*>VR;L;f z{UE}JQwv3kUi~z2;6eAk$nF6QOa3Ch+jpqF-Dh4%@J zxR+X*YLR)3G%XIdY+Qiov(@!0jgE-m2b*lOz5{3#p0_olFDa)?hrOc=NO}O0{7(f( z04S6I&oR^=v+Ua(cmKdPQ~cDdAMz2Ro6eqfz)NEO?_`ST`pWTYgU-qvL=Cn*5XSVX z$u1~96Z1L&A#J!$*wrEuOm5NW`z}?<)8%K~c1V>Cyh94rOFfgix4(h{k=G%hdQ#1y za{Fr(oVF&u^OsZVtxq5VszSRf0fa5G<|4+uQZqs>vwqHaR6L6C(=UCliUh*oqq>}D z35`QTMhx^fPrdj|PmQ);<6570f=LPYXZ>RZ2~5l&C^u#Sf_U7K91=uf(IYJb?%GvN z_@~~|+9d3PNJ9`Pk>CQFbI&U#jTF>nx=~@tKvkrTc87^{${y@$ueK!b(ZsNSL)I4r zt4}HVj{`jq^{Xqba}hCGXz~X<_Cu;ZWAFt1N{1wX|N8nY{jWoQ>^}Z)6JuBuL6W+8 zU~d40xUrsVpxvsV=NvaE5ux27-_t9-)LT$J1ZU$QbabpRusZX=wh=T2uq!(Jg5!}? zfH`&&Bb+0P3#XvqqkdI(SI>>7u^+mHiwi)Q$t2Z}b2GYpfb48Bm5$4Ri`p&*6%Snr zgXbUGyJYplSWgDA@j;SBFnlVpI2b^DsDT|oY47*vH~5RP<+2L&_dw!#1c@7 z{ipQ%GoLeJ546%ye-Z|!*8JsRc3@viEB>_O0HY%q&C)*~{LYBBOPp4;rg(sG_tQnZ1uI~#8nS<~zl`UJk~ci{_=#6V zgx~}u99@2&8MYB!)B)y1Au2@G6lU*Gib@nbng4A15JLDEshy9z2eihaDl)xv+HCLT z2S^zqmOgv$jt2kjo+v9eMaZu$muxE~QbHh|6|DL5Pj|-@@83+T2 zc&&ZmRS=1=KeVbTk*fC*j(1G3Fe*@2|3N~9PU`hq{^M}qu;z0kly2hUcJJzbQ)sf; zIkI%4__#+}I!tk{UYT2VBLT;0HNl?AZ$7_oERouOu4*OSgN`DQ&Md$E2ZsHTZ0v%k z#>7!}CogqR;O)S6_L3)m#ZUfJ%Xw-~S3lTk^)fwlQy?;b?>JLI?QfR$!K->rcy8>! zvA#yQ#bD3*+>unY93d7V21~HHum}kFbQbslB@M*278T%<2^C{RRrQ`tR^dwfapR=} zx{S#e3541YDsz;IWH8#p-w)CW?~e6nMDV}YN%`P)BqH5Y6x_GkSIFr!Clku=qi5mB zWK`(csy|b`aAT9V1b;)VzV4Ni%cyrctehXdFQDz+Z58|x}N|>MoRC!UK-8^@9!3QNL(u0j52gx zdB19EJ7*MT+c9yndGfIt?HD{ZzQ z$cwS$=_|V<07;4VAcPj3YJ+z6bBw$JDb58!h$I6%_7GBvv?4IFc%s_>ZY+HPPr2>9 zU^P=vIwG!HP_De`%Jb(sG^@V;gRa(dEAsj@>uD+C)_uZ-t?ds)!A9M zke7pZm70g8`olX^`|_tDFEWKTW6`4nqZSA4$9i1ou@&YA8jKSc8@%#44o zu#Z>`*)*h&lz)FK65aKK`WfT$h+*X3-<84#?@c7Vj&%qavhTh5r`bhV=BTvaijS@} z0y8#N%1zp+gt9NYT{p+QocEsW=%)$)>SlZ-=U=XikyI~c^e)L%iD6%B|__LTcg*n zhr3<(Z5qD?uChc;;3z**tHT8E%GI-9!eYYiN%aSgKf_M`m1W4DQN&?#%Rz+afwm59 zUYK%KT@#EL3G=$TyJ5ui+pG%Ba9^LT-nzQ3u6NMyeD<&0JeyZ=3)48O#>?!nnQ$HR zK1pj`J7}1W6unD-@@3rFD^1o{H6k{)=9%{ZmvZNbX1X}1p3an-Ug(#qC4re(0UWo} z-S#j?X2M+xx%qEek>r%#Fzi77n2F#dk&|5B@rew3UfhA`;O!^PsdUvP=HctHNFb-& z{gFvxYy}JV*~^1i!{H-LT;GnB8uR?uc~`R`cA{uju2?%`mc#mVL#YY!%-PsPcV@3T zUWkyWUc~i#?|=x05j=lDsuZ?*ea0*6V0n~T=A`hjuX(W0S;};MlY`?>CiLcbs$XcV zAGm{sC(F))P(t`#4wtFaJ3#Ol+*)lcojT*ThjGW?(t&h3G_ZrHY6tf>nH>EBwbItY$9+_G9VrU#c&8-+WbgOv9Co!Q05dnz*>REber) z2YQV5Iq&|;3-y0Yhqkj2DWb8NejUIaTtatH0gpm&bUZ2ih9yTqT+#?8ppCk9SNDs%C$`p$PfJTtZieD%Zk6_p zxGHfE*{eqE%O)#7xdjh)+m~+qk+C@GM{?LgqT#^FT&uQ;j`N1$x8ef)VI{RPC$}o6mg1P2IjbPSDK#V27z%bs+EOPZ~or$Yi#<%{(03(DR|}3X|M5ns;-2 z&UUt`lp~wJHd+{csB);mD6G3oto9`%D09#54E}$S?*g#wWJ8g&Ap!)iGc*5gPs9(h zEETZAvlk%HdATgn&{%S=4YdVAT zmdM3eMXz}$lwBRWE{MhUx{&+iFOye}hWlF!>%EQ=m)0y@bE=$xgOEjZKEiThULzam z&_!dHV6U*mE>n1x(3M~1bJF&5j=EzhQiOIK36mV$4wR+%GqS8WQ$4Y_GL+CvyNbtY zT10ZRqgIv+Kn6-$?4fd}Q5=C9iBF%?Sa+ce@r{Rj_mY7%1bF)=M|UL()d$1@*7$3x zRu3kxEAvI~uGAU{IFs_7jkbHQGoij1ML>#cAa$RAyXIu^-JRNf@rWR=g|r(@hE7wl zbAnm5#_kU4q4tJSH^R}B4)zu6%%ul0_5j4^<_ki zgrxroR10$}TPpYD-_go&kX4k*Kgc)7)WmTtRS8+)vad&Px@|Wd2#l_xS2wXo5l3XY z$6l7$^33%)qFm18FBcv?($vk^YWLCp@V2ye>hHAih~pfYcOC>d2spq1nDmMCKILbk zeJ4sB2Z?D)$H&Xhdala{4BiJ{Jy$8Uc5-?x* z&rP5UO!ZEoQWeCL;;VB8~=z%YC^Z)i^j$ZXsP@ed#rH^MrtQ>n~4knS8!`Mn@+lCHly(ba|!z_T2N!U z95g!!ObBTEdw3Ph5!DM`k(;ZI(v1O^9#njzU`dhbfq7o~yQ1=UeYqJ+)zcfuyPG(% zPi!mU^NC>aJhJku>r~zK89Ab`!>J&*{d;Lm2KQTs!odSe1-lf~Uj#x0n#evH!YDgVIV zUH9y9Ytb=&Zccu|7@xzR?rq6X9$0@;1(8>1FHP4GfjHQ0Dgj>>ZlMv*AB*qNww2!Y zBF%Y^9!g#CI#D_dh$FwEI8`c^K{Z`t;m6MZ+XX@Rs1}L zV>DQ2x;}lj#B@%ah`3>?NK{I&1c#ijc^EIh^?$A_&%Az?CL!WoUno#*&=n*{G#*qO%>*S}3r&*=UYDl+*t zHI4Ed&m(D$5IQK_8GhS2lZMeWTaplaqVChlL+veb&OSGF>_Q>WXirD|D*DyRrfF$w zY-2lH)`!$gp@GjDBq|3cgLSz)80nhy57nJxW7V1S%ya5BOG4zw75>vAc>Wf;1CL4@ zj)pRuXXnGxzc7fy}I$VFKuFV7f&GXLi6WltOO@73Hq>F zH1pOjP@f3<-qe(x7k3ppTd`k1rsFYA78A}u+~Gxqix$EBoxe`Vt+6kAvEewxyM@D@ z;b+b3XS%-kvvghWG!?tr+PVr~_vE)I7+y&9I(cW)Y5rrzZaVis=t)S<=sw1wg}Be< zvPeu*naTI(YqWa4oyqd{kBA9%rgYL`2@O-aq^)IyP9&Fqm<; zU=wYAlZbqBC8e<*8@2QKSlP_UQ=dsyM=Sp4h^*UKR^2QMNp0nlNrAPji#R=uATZ}L zgGw-NRf(zYV;62c7x5IDzjp6(!-zjk9iv{u4?lfP(7u&im3aMzv1Q{qC7$U&gR}+* zA(e-X%SLfjH;=T8%lzTm|J-A$Y&!ZJp_RQW6tXYAPf13szemlPV)89Q>!X8K59-^8 zeZ~5px2vJ|FIHkrGsBCjOaD}F=E3e^bNTAUb5(*uIUjt)#9l-OuW%1Bf7dW!B`No% zB4qq2RDRoOZ)RdSR6*IiZn@R#XYBwzt?`q)sL8a)CLz(W1XdhuU#rO+#^9)v=5sJ? zsVBcB%-t^<%y8ayakmXUX2!! zxvAgFc~3txYrUVr$%69<)daa2Pvm?IIkt`X-G#lWEm9$We>}Ja-$CbAl-xjO=EU*# z62T?hjmMZ(VfCW!n+?)OGwB(@?`Y=K&%m$l4rGb^6aSfn$|IfRm~r<;CBbZb`rvDr zHoMIW|JXbU9vQA1kqt;RI0v_u4{!Qo(9#EZLygCMY#Rno)kET@v6CYW6Ak6r7m6)& z*%K#{mwDe!ttU6s1^fE?rW1c>SUro{TBLm85O?^-&NueKWmHJ9T~s6bm1MBt_?uGs z7#2@ z!wC}JadE*o!g}|w;ED|T%-a94`?P=c?geYy*g*O7N$`+%-CGz1g&FYSqK%vIZt6$u zaAwB8<(c;Ka#9i0`*(hZ#g(@!w6@bTy-A;xeX*F}YW35t5tv1pd6JSP@%P9A1NFrn zfG|?=Y+g`=U}U<~a9tq4+KW;-huglSdSdN1?HQDt=f}5ESy`rKY2Vpy+wcz58{~ z8P$%mEtZM#)q=xFb7}JOZ$^~6p11Ews1Ej7VlM5eX$(Jpqq>}W>0B!dv(51|5$g9; zK~I-Lo+@uftWpJuS)45T=}FGD8VkX$0*@@y$G`5^t3?0qPnvwh^u`iPxN^_R?WbJY z85E&DWzKk>CiOO+rJe=(>`G0!xZSSPTH(HVvhZEZpQZiLVVj=g`OZh|wfV|6+7VNk zms)v_+&(VZ7=6f+67s|sw$P-R9HwF7_E??AdfmZXzry~7CjK*ijMaMfjzF}Yy8qvz z#+O5he3qL7er8ewC1|YZxZ^9YP0TX~v~(+DL#^)78PwWLg=A*+z<%;8&L2~Tk<$~M z^XgNQ5JHq6Z^Y-OhB-&16%i7Xy&*xjy^FIF_@bu#9G&Z-zT0m=mzGRZJ4tcqKGL@^ zDkknImd!z1DUP3V42*px(rAyU|B z^PsDwM^lhPD|?WR3X zP|O3r^j|+ZYE)=wE_C3E2fmNW!X-YM5Q5;d&dAI&xz0E7PjMPG3gS8L>sK`u5T5ue zGw>phLo+bReKBVyMe>3t4Jh$$!T4xs63H0z(nW1$n5!HrG*u>DmhCg^z2CYzN=|nO zF|sq+?BrZ0%;?Ea_aXBeAM;q7BB#xt{e13MTVFst0g9%+@*iXSYno+t>X~d_M=I<; zYx4gQ5!+hv9Uohv_J1-!{ogencuv!yp8uNkb>%xr5jnBnVY^O9$W8jgTUZ@?%!mqN z%YJyrLaVec7VpH`S)am|>Y^vI%W#K8hh9OI6y0>pxr7K#8KC zQJUIn!YvfOsh6j0j?Y`4x^epGyvN)=qfj2MIDPxtE_)Y#`M<5!viTIpDnlrLcRsDCM(qIALn2n%!SYCT9#egYAc^Exw+FGdoSnN zS#g@gil1KUHxwSz9gQVVnLawpatNW^mtw0m;U=msz7nT*UmISn;aFstFU9>!Fn8d( zh8s76X>3M}#ezNShDv3`c<+jf#~BE`g&Fl=ciS^}Ex8Ua`_|d0X=pE3l)!paO zBlyw+r7D$dFb@-Ha00N9#st6Lj8oI8d+VEiTONPe!O_f=L4V>EN>rYgntihCSBlZi z#7TFiIHPllkOg@7bf8c)`;JxkEVs$ed}BUPUsQYl-?OsUjYSDA&y8L^@J+XQIqEm@ zbM63z!Znt-OJ_REa}wg+kjyIFdNFyoM{nAR)p2fc`P%L$GW_bNe~o)_&HfOKF8rIC!TVv}>~krXu^QWhtcjR? z!e?66i?5Q&{@k~N9enfS+x0{3=_FSVdTpdQkX(+CP(_w%S4DM$dY~li+n2e&ce?Os zYV&)Co~EnK>rnZdqDe2Zx(4tTa8d-cJWuW2tO zcPS~ANz(4>(fwFcyMUiEH#L~C>1<$bwIEnxP@7jH6a;BXL&21jz39Z`jsdk>n40qR zVIzx_hz8^Et?p9V5BLj-uDORl6_evw-&tu9oX6S!hf^}Rz8N)z!($ zr(0nxd*^d+lVMs1?Sc8_D$Q5O27mryantKAeAQaseqwS3t&d{I(MdEFn(mT!f(Z(C zW26S1$eN$U;GkZ_FsZuh&DkwWcRt?tSjSBI#g>+olrKma2T{4<&rkpIvztC(I-&~M z{5RymB)L$+SCIUvYQSw_^!Q5=@|qjJ&u+PA4}H6WQZIe+MO;3aA^N_p?>oxjkD{w zzj5XAzRncCL)YW+izH?+&bEJAd&7~{^Hn;HSSUv*65!UhSk|YDd@z{HbvF;C4hHQy zmISfJi3>_D)Eqi)*T!`<&5vG2C&u;25gSZxc=%q$oJINb+(|>z@(75SfUyZJ-I0k=7wO@hX&!{hD9%rVnR(SjF} zI=2U3uf4Hh5(}47f06`={_^+a08GLjCuDuoGrW?T#rN2fzHj%$yDyvJK!08Kaid9q9-04On4!3lGK7Wsn(A|q$2q&bDu7>a$fYp5 z!jm_)Ia=zZuJc;Ig#p}R9;LR-JVu@&WD5TAl1stKPlIV4=hVf5FWp=zbvpA2!io4` z>26BGuI2W5_fpq4WoSsagW@XUUCn_o>Y96x&WHI)YxsLI z=cOyZ^H4mIu{i%^YDj?kNIS_66?nuZZ>k@5upQOYcy;+docblHg>PA9|rj25ufq! z_EcSU_r0)87kYl+cK_j}g;l

8QD-n!V9bb#-Bgbj7QmqSJ5-xL!VdA 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

`8euIFwu;#42pKqXCkTdMC+HJ0})L1tCBWcRg zPKXd>@t$1M0bZ5c`(r<|U_+!=jF4ulOm>}dAF?xt5Uh2BA;l(_ExknrY% zvIW@QV|}p)m-!qwxcw1x1SRmeaR*1vhT8HSm-s{R@tszFf%s~h7v?f<6Zea$$`0DO zrc&<4JwFN)zm87w*KxYY{?;W?sH1t?y%}!^89GA_Gb#Ny&8{M_Q^`o*ib5 zE@-f=Ib+NM zSo|D9H!l(d^zcf*&JWdV8N+HQRbKVYJy3oQ-$qjfI(KeX>(}=9kn4cOaBdaveAU0P z!1G-Gz3~7MS&mUc0Kn&!NofYupojt&__&JPuc`qt0w|8Y%qGDU@_z@f$PfzGkxV35{1u z_ncCL19!7;`vO|b_>eKvMhrh_N76+_rlZ$3o*tW+uajtV1$5jjN#Vk9jn4(3xnGSB zGW|JAU7UR`{BWW~G9I&xv;FL`PA(8#IXC?|jJ6t}vP2OV7r$?7+fpm!E9QInbtPV& z2W^acCJ`S!zQ;vl^QODj8wGonmLt@;SX9F*Wz2~_A0`zu7Tg@|S$$youdNK9U}g59 zUF(V(A7n=Pn{E5OTlc#h+Pk5OinXbwLu)jw50XS4%;p$Xr3B=TVd}?qU+|&WPakt9ELj;$pc|X8_$Lb^`f;-*gWfN6>>(Sfan9qsR_}DsXBL$zhQA-PkLF{u zwp#XW%-^qc!Cn47X?q(B%1>}uI=Sp@iyF!=srtBPaG&bzY8h|VK_)+ZxWw;Z@*6jn zsKee$z088LVc7}-^^rfDV&VCN}soJ@&nT)h`FL%(^#^ z)eq%||0iMt)VWXu=}jI+mCdWj?4!qM&l--2`2u*ETL&D(tR%({9n2#Nu_e%_PtLOV z;lsA(R%MXcwoBtX{_o`W?0hPe3>q_vAhC7Oc;hJJnr;0ZPnnodJGW*+$ls**!p&=Z zsAg9rYHBPZn?dmZsT$Q%w%mh-rx}k6 z{sx^jkd$F?Y?RguRVANRL5+VmX1Zzo8|O^0WbmBfW{XupLe0TJM^7)>yRtxu zK6e}Ez4X2@Y285Fr^?Xq)jqauBg;D)r~B7B7>e#%xBj+P7YJ@|xW&$i4z#guf4-bh zYR7~xqm@lfKlLzA?7O0M_fACr%F46M6k!Lnd1_nU`uTc9Z6r+Z%kE; zjS*-6Q!xBr>pt8%pz8!+EOE!U2FAzlH7l)F8N6o zrsl49M%4L)HJ32w1n(N#-}u9j6d5Vm{>1!|PIbD$^{#t$cMP3lu2_$_JhltGzd%gf zamX{i`6@AQxGXGwkJ_Dyy#vM3de6r46X3sf+!r#RRQ>kL-lB_w&qmo&$W1@i3_C_= zY`FJRW!XEGWlAx)guTTws+dyioopr&Wn#a|dHDDKYw_zp{Y*wt>-X58lj#X`-n(#P zy1Ea)^|xBYSn9DSz_h2V&nMh&#Oi|2egR!o-8YD*Vz zb}X|SsMWIxwa$HP`muCrZllwskWc21AMe{d5|}SzI>>8=nDlpZ=Uu!o`gg`RTJW+7 zAA&YZUl=Xge*05w4YevpX_px0md?xe_P6A=c*6RKe|5|7Qzn=ed%{!@?_a@=_ke540U`6A&o5Hl{yca0c`xgKspto<1_ ze97=F7uv*wk8HT_fYM7PLzUHhw2Z@@SDGtbs=qaXv=mZV?4r zN~uK|?^EZiZs#dNb;?!?VQvvB_p!YW4D?esdy6$eR(U%z-*B132V=c}%0{)#nm;bX z;NkJ(`Ap;p-Aek})hd%rhv%aHh2BhoC{*HB`Uc?S!d8-o>anF}{P!O>hv`3OKsJ02 zu$0*xB36UXiaPFc(ZJ=dxywBzOQ(DAhB_;CR!02H8F4AO8)v1Iq~(>Q6hx(@l%%Bi z{%R)tza8wccWtda|NRcObvD~!hg1K11{YiVd(JNA_7DF3KFWO>oyd4=T+~*_|8Xba Fe*l2?sEPmp literal 0 HcmV?d00001 diff --git a/docs/authz.md b/docs/authz.md index a539696..62dfc3e 100644 --- a/docs/authz.md +++ b/docs/authz.md @@ -17,7 +17,7 @@ For different authorization requirements, you could choose to write a custom mod * The results of API calls to an authorization service * Policy engine evaluations, like OPA or Casbin -TODO: add diagram showing how the plugin fits in with the app +![AuthZ plugin overview](./authz-plugin.png) ## Implementing an authorization plugin From 34f886c892575b1535748377faa29a7777d16d5d Mon Sep 17 00:00:00 2001 From: Victor Rocheleau Date: Wed, 6 Nov 2024 16:45:59 -0500 Subject: [PATCH 24/31] perf: authz plugin conditional load --- transcriptomics_data_service/authz/plugin.py | 21 ++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/transcriptomics_data_service/authz/plugin.py b/transcriptomics_data_service/authz/plugin.py index 963480f..8e2f98b 100644 --- a/transcriptomics_data_service/authz/plugin.py +++ b/transcriptomics_data_service/authz/plugin.py @@ -1,6 +1,5 @@ import importlib.util - -from fastapi import Request +from types import ModuleType from transcriptomics_data_service.authz.middleware_base import BaseAuthzMiddleware from transcriptomics_data_service.config import get_config @@ -8,16 +7,18 @@ __all__ = ["authz_plugin"] +config = get_config() -def import_module_from_path(path): - spec = importlib.util.spec_from_file_location("authz_plugin", path) - module = importlib.util.module_from_spec(spec) - spec.loader.exec_module(module) - return module +def import_module_from_path(path) -> None | ModuleType: + if config.bento_authz_enabled: + spec = importlib.util.spec_from_file_location("authz_plugin", path) + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + return module.authz_middleware + else: + return None -AUTHZ_MODULE_PATH = "/tds/lib/authz.module.py" -authz_plugin_module = import_module_from_path(AUTHZ_MODULE_PATH) # Get the concrete authz middleware from the provided plugin module -authz_plugin: BaseAuthzMiddleware = authz_plugin_module.authz_middleware +authz_plugin = import_module_from_path("/tds/lib/authz.module.py") From 76372acad4cd32bdbcc242ca137f7d3a19def2a1 Mon Sep 17 00:00:00 2001 From: Victor Rocheleau Date: Thu, 7 Nov 2024 10:43:08 -0500 Subject: [PATCH 25/31] address comments --- README.md | 2 +- docs/authz.md | 2 +- etc/authz-api-key-extra-env/authz.module.py | 2 +- transcriptomics_data_service/authz/plugin.py | 3 +-- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 1385a99..6022b93 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ You can then attach VS Code to the `tds` container, and use the preconfigured `P ## Authorization plugin -The Transcriptomics-Data-Service is meant to be a reusable microservice that can be integrated in existing +The Transcriptomics Data Service is meant to be a reusable microservice that can be integrated in existing stacks. Since authorization schemes vary across projects, TDS allows adopters to code their own authorization plugin, enabling adopters to leverage their existing access control code, tools and policies. diff --git a/docs/authz.md b/docs/authz.md index 62dfc3e..35868a9 100644 --- a/docs/authz.md +++ b/docs/authz.md @@ -28,7 +28,7 @@ If authorization is enabled and there is no file at `lib/authz.module.py`, an ex will not start. Furthermore, the content of the file must follow some implementation guidelines: -- You MUST declare a concrete class that extends [BaseAuthzMiddleware](./transcriptomics_data_service/authz/middleware_base.py) +- You MUST declare a concrete class that extends [`BaseAuthzMiddleware`](./transcriptomics_data_service/authz/middleware_base.py) - In that class, you MUST implement the required functions from `BaseAuthzMiddleware`: - Finally, the script should expose an instance of your concrete authz middleware, named `authz_middleware`. diff --git a/etc/authz-api-key-extra-env/authz.module.py b/etc/authz-api-key-extra-env/authz.module.py index 8b9f2f9..959f1f3 100644 --- a/etc/authz-api-key-extra-env/authz.module.py +++ b/etc/authz-api-key-extra-env/authz.module.py @@ -58,7 +58,7 @@ async def dispatch( return JSONResponse(status_code=e.status_code, content=e.detail) return res - + # API KEY authorization def _dep_check_api_key(self): diff --git a/transcriptomics_data_service/authz/plugin.py b/transcriptomics_data_service/authz/plugin.py index 8e2f98b..1be7833 100644 --- a/transcriptomics_data_service/authz/plugin.py +++ b/transcriptomics_data_service/authz/plugin.py @@ -3,7 +3,6 @@ from transcriptomics_data_service.authz.middleware_base import BaseAuthzMiddleware from transcriptomics_data_service.config import get_config -from transcriptomics_data_service.logger import get_logger __all__ = ["authz_plugin"] @@ -21,4 +20,4 @@ def import_module_from_path(path) -> None | ModuleType: # Get the concrete authz middleware from the provided plugin module -authz_plugin = import_module_from_path("/tds/lib/authz.module.py") +authz_plugin: BaseAuthzMiddleware = import_module_from_path("/tds/lib/authz.module.py") From 7670cdbd47dce92771ebaf2c0699bd5f0c97da16 Mon Sep 17 00:00:00 2001 From: Victor Rocheleau Date: Mon, 11 Nov 2024 16:39:41 -0500 Subject: [PATCH 26/31] chore: re organise authz plugin examples --- authz_plugins/api_key/README.md | 22 +++++++++++++ .../api_key}/authz.module.py | 0 authz_plugins/api_key/example.env | 1 + authz_plugins/bento/README.md | 17 ++++++++++ .../bento/authz.module.py | 1 - authz_plugins/opa/README.md | 31 +++++++++++++++++++ .../opa}/authz.module.py | 4 +-- authz_plugins/opa/example.env | 2 ++ .../opa}/requirements.txt | 0 docs/authz.md | 14 ++++++--- 10 files changed, 84 insertions(+), 8 deletions(-) create mode 100644 authz_plugins/api_key/README.md rename {etc/authz-api-key-extra-env => authz_plugins/api_key}/authz.module.py (100%) create mode 100644 authz_plugins/api_key/example.env create mode 100644 authz_plugins/bento/README.md rename etc/bento.authz.module.py => authz_plugins/bento/authz.module.py (98%) create mode 100644 authz_plugins/opa/README.md rename {etc/authz-extra-dep => authz_plugins/opa}/authz.module.py (96%) create mode 100644 authz_plugins/opa/example.env rename {etc/authz-extra-dep => authz_plugins/opa}/requirements.txt (100%) diff --git a/authz_plugins/api_key/README.md b/authz_plugins/api_key/README.md new file mode 100644 index 0000000..41863e9 --- /dev/null +++ b/authz_plugins/api_key/README.md @@ -0,0 +1,22 @@ +# API key authorization example + +This sample authorization plugin authorizes requests with an API key header. + +## Contents +- [Authz plugin](authz.module.py) +- [Extra configuration](example.env) + +## Instructions + +```bash +# Copy the module to the mount directory +cp authz_plugins/api_key/authz.module.py lib/ + +# Copy the extra environment variables file to the mount directory +cp authz_plugins/api_key/example.env lib/.env + +# optional: modify the API key value in lib/.env + +# Start the service +docker compose up --build +``` diff --git a/etc/authz-api-key-extra-env/authz.module.py b/authz_plugins/api_key/authz.module.py similarity index 100% rename from etc/authz-api-key-extra-env/authz.module.py rename to authz_plugins/api_key/authz.module.py diff --git a/authz_plugins/api_key/example.env b/authz_plugins/api_key/example.env new file mode 100644 index 0000000..28d8c0f --- /dev/null +++ b/authz_plugins/api_key/example.env @@ -0,0 +1 @@ +API_KEY="fake-super-secret-api-key" diff --git a/authz_plugins/bento/README.md b/authz_plugins/bento/README.md new file mode 100644 index 0000000..bdcfcf7 --- /dev/null +++ b/authz_plugins/bento/README.md @@ -0,0 +1,17 @@ +# Bento authorization + +This is the authorization middleware used to authorize TDS requests with the +[Bento Authorization Service](https://github.com/bento-platform/bento_authorization_service). + +## Contents +- [Authz plugin](./authz.module.py) + +## Instructions + +```bash +# Copy the module to the mount directory +cp authz_plugins/bento/authz.module.py lib/ + +# Start the service +docker compose up --build +``` diff --git a/etc/bento.authz.module.py b/authz_plugins/bento/authz.module.py similarity index 98% rename from etc/bento.authz.module.py rename to authz_plugins/bento/authz.module.py index 489da6b..0fa1784 100644 --- a/etc/bento.authz.module.py +++ b/authz_plugins/bento/authz.module.py @@ -30,7 +30,6 @@ def _build_resource_from_id(self, experiment_result_id: str): # e.g. "----" # TODO: come up with better delimiters [project, dataset, experiment] = re.split("--", experiment_result_id) - print(project, dataset, experiment) self._logger.debug( f"Injecting resource: project={project} dataset={dataset} experiment_result_id={experiment_result_id}" ) diff --git a/authz_plugins/opa/README.md b/authz_plugins/opa/README.md new file mode 100644 index 0000000..c8e5408 --- /dev/null +++ b/authz_plugins/opa/README.md @@ -0,0 +1,31 @@ +# OPA authorization example + +This sample authorization plugin showcases how to use OPA as the authorization service for TDS. +While this could be done in pure Python with HTTP, +using the [OPA client for Python](https://github.com/Turall/OPA-python-client) can offer advantages. + +As described in the authz module docs, additional dependencies can be provided for the authorization plugin. +In this example, we include the OPA client as an additional dependency. + +Furthermore, the OPA server details are provided with extra environment configurations. + +## Contents +- [Authz plugin](authz.module.py) +- [Extra configuration](example.env) +- [Additional python dependencies](requirements.txt) + +## Instructions + +```bash +# Copy the module to the mount directory +cp authz_plugins/opa/authz.module.py lib/ + +# Copy the extra environment variable file to the mount directory +cp authz_plugins/opa/example.env lib/.env + +# Copy the additional Python dependencies to the mount directory +cp authz_plugins/opa/requirements.txt lib/ + +# Start the service +docker compose up --build +``` diff --git a/etc/authz-extra-dep/authz.module.py b/authz_plugins/opa/authz.module.py similarity index 96% rename from etc/authz-extra-dep/authz.module.py rename to authz_plugins/opa/authz.module.py index 8fd5621..827c0aa 100644 --- a/etc/authz-extra-dep/authz.module.py +++ b/authz_plugins/opa/authz.module.py @@ -21,7 +21,7 @@ from opa_client.opa import OpaClient -class ApiKeyAuthzMiddleware(BaseAuthzMiddleware): +class OPAAuthzMiddleware(BaseAuthzMiddleware): """ Concrete implementation of BaseAuthzMiddleware to authorize requests based on the provided API key. """ @@ -94,4 +94,4 @@ def dep_authz_get_experiment_result(self): return [self._dep_check_opa()] -authz_middleware = ApiKeyAuthzMiddleware(config, logger) +authz_middleware = OPAAuthzMiddleware(config, logger) diff --git a/authz_plugins/opa/example.env b/authz_plugins/opa/example.env new file mode 100644 index 0000000..8b061b9 --- /dev/null +++ b/authz_plugins/opa/example.env @@ -0,0 +1,2 @@ +OPA_HOST=opa-server-ip +OPA_HOST_PORT=8181 diff --git a/etc/authz-extra-dep/requirements.txt b/authz_plugins/opa/requirements.txt similarity index 100% rename from etc/authz-extra-dep/requirements.txt rename to authz_plugins/opa/requirements.txt diff --git a/docs/authz.md b/docs/authz.md index 35868a9..b14f730 100644 --- a/docs/authz.md +++ b/docs/authz.md @@ -5,9 +5,6 @@ Although TDS is part of the Bento platform, it is meant to be reusable in other Since authorization requirements and technology vary wildy across different projects, TDS allows adopters to write their own authorization logic in python. -For Bento, we rely on API calls to a custom authorization service, -see [etc/bento.authz.module.py](./etc/bento.authz.module.py) for an example. - For different authorization requirements, you could choose to write a custom module that performs authorization checks based on: * An API key in the request header or in a cookie * A JWT bearer token, for example you could: @@ -32,7 +29,7 @@ Furthermore, the content of the file must follow some implementation guidelines: - In that class, you MUST implement the required functions from `BaseAuthzMiddleware`: - Finally, the script should expose an instance of your concrete authz middleware, named `authz_middleware`. -Looking at [bento.authz.module.py](./etc/bento.authz.module.py), we can see an implementation that is specific to +Looking at [bento.authz.module.py](../authz_plugins/bento.authz.module.py), we can see an implementation that is specific to Bento's authorization service and libraries. Rather than directly implementing the `attach`, `dispatch` and other authorization logic, we rely on the `bento-lib` @@ -131,7 +128,7 @@ services: ## Providing extra configurations for a custom authorization plugin You can add custom settings for your authorization plugin. -Following the API key authorization plugin [example](../etc/example.authz.module.py), +Following the API key authorization plugin [example](../authz_plugins/api_key/README.md), you will notice that the API key is not hard coded in a variable, but imported from the pydantic config. The TDS pydantic settings are configured to load a `.env` file from the authz plugin mount. @@ -156,3 +153,10 @@ allowing your plugin to use them. **Note: It is the plugin implementer's responsibility to ensure that these additional dependencies don't conflict with those in [pyproject.toml](../pyproject.toml)** + +# Reference implementations + +For examples on how authorization plugins are implemented, please refer to the following: +- [Bento authorization service plugin](../authz_plugins/bento/README.md) +- [API key authorization plugin](../authz_plugins/api_key/README.md) +- [OPA authorization plugin](../authz_plugins/opa/README.md) From d3cf72e9694d95d287e24ebc44ed85579e35f964 Mon Sep 17 00:00:00 2001 From: v-rocheleau Date: Tue, 12 Nov 2024 12:11:27 -0500 Subject: [PATCH 27/31] rewording and comments --- authz_plugins/opa/README.md | 2 +- authz_plugins/opa/authz.module.py | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/authz_plugins/opa/README.md b/authz_plugins/opa/README.md index c8e5408..b30659a 100644 --- a/authz_plugins/opa/README.md +++ b/authz_plugins/opa/README.md @@ -2,7 +2,7 @@ This sample authorization plugin showcases how to use OPA as the authorization service for TDS. While this could be done in pure Python with HTTP, -using the [OPA client for Python](https://github.com/Turall/OPA-python-client) can offer advantages. +using the [OPA client for Python](https://github.com/Turall/OPA-python-client) is more convenient. As described in the authz module docs, additional dependencies can be provided for the authorization plugin. In this example, we include the OPA client as an additional dependency. diff --git a/authz_plugins/opa/authz.module.py b/authz_plugins/opa/authz.module.py index 827c0aa..3f76c1e 100644 --- a/authz_plugins/opa/authz.module.py +++ b/authz_plugins/opa/authz.module.py @@ -1,6 +1,6 @@ from logging import Logger -from typing import Annotated, Any, Awaitable, Callable, Coroutine -from fastapi import Depends, FastAPI, HTTPException, Header, Request, Response +from typing import Any, Awaitable, Callable, Coroutine +from fastapi import Depends, FastAPI, HTTPException, Request, Response from fastapi.responses import JSONResponse from transcriptomics_data_service.authz.middleware_base import BaseAuthzMiddleware @@ -23,7 +23,7 @@ class OPAAuthzMiddleware(BaseAuthzMiddleware): """ - Concrete implementation of BaseAuthzMiddleware to authorize requests based on the provided API key. + Concrete implementation of BaseAuthzMiddleware to authorize requests with OPA. """ def __init__(self, config: Config, logger: Logger) -> None: @@ -64,7 +64,7 @@ async def dispatch( return res - # OPA authorization + # OPA authorization function def _dep_check_opa(self): async def inner(request: Request): # Check the permission using the OPA client. @@ -76,7 +76,7 @@ async def inner(request: Request): return Depends(inner) - # Authz logic: only check for valid API key + # Authz logic: OPA check injected at endpoint levels def dep_authz_ingest(self): return [self._dep_check_opa()] From f3972c2e6ba64cd366cd2e5963010152358f0493 Mon Sep 17 00:00:00 2001 From: Victor Rocheleau Date: Thu, 14 Nov 2024 13:56:16 -0500 Subject: [PATCH 28/31] address comments --- .github/workflows/lint.yml | 2 +- authz_plugins/bento/authz.module.py | 2 +- transcriptomics_data_service/config.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index c7056b2..1fe7848 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -24,4 +24,4 @@ jobs: run: poetry install - name: Lint run: | - poetry run black --check transcriptomics_data_service tests + poetry run black --check transcriptomics_data_service tests authz_plugins diff --git a/authz_plugins/bento/authz.module.py b/authz_plugins/bento/authz.module.py index 0fa1784..8e8c40f 100644 --- a/authz_plugins/bento/authz.module.py +++ b/authz_plugins/bento/authz.module.py @@ -29,7 +29,7 @@ def _build_resource_from_id(self, experiment_result_id: str): # Ownsership of an experiment is baked-in the ExperimentResult's ID in Bento # e.g. "----" # TODO: come up with better delimiters - [project, dataset, experiment] = re.split("--", experiment_result_id) + [project, dataset, experiment] = experiment_result_id.split("--") self._logger.debug( f"Injecting resource: project={project} dataset={dataset} experiment_result_id={experiment_result_id}" ) diff --git a/transcriptomics_data_service/config.py b/transcriptomics_data_service/config.py index 667b934..973ce49 100644 --- a/transcriptomics_data_service/config.py +++ b/transcriptomics_data_service/config.py @@ -3,7 +3,7 @@ from functools import lru_cache from typing import Annotated -from pydantic_settings import BaseSettings, SettingsConfigDict +from pydantic_settings import SettingsConfigDict from .constants import SERVICE_GROUP, SERVICE_ARTIFACT From f982a31cd895cb8c6bb05c129eb5d0dfcadad861 Mon Sep 17 00:00:00 2001 From: Victor Rocheleau Date: Thu, 14 Nov 2024 14:35:55 -0500 Subject: [PATCH 29/31] chore: linting with ruff --- .github/workflows/lint.yml | 5 +++- authz_plugins/api_key/authz.module.py | 2 +- authz_plugins/bento/authz.module.py | 1 - authz_plugins/opa/authz.module.py | 16 ++++------ poetry.lock | 29 ++++++++++++++++++- pyproject.toml | 7 +++++ .../authz/middleware_base.py | 4 +-- .../routers/ingest.py | 5 ++-- 8 files changed, 50 insertions(+), 19 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 1fe7848..d716adc 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -22,6 +22,9 @@ jobs: run: pip install poetry - name: Install dependencies run: poetry install - - name: Lint + - name: Format check run: | poetry run black --check transcriptomics_data_service tests authz_plugins + - name: Lint check + run: | + poetry run ruff check diff --git a/authz_plugins/api_key/authz.module.py b/authz_plugins/api_key/authz.module.py index 959f1f3..e909c87 100644 --- a/authz_plugins/api_key/authz.module.py +++ b/authz_plugins/api_key/authz.module.py @@ -1,6 +1,6 @@ from logging import Logger from typing import Annotated, Any, Awaitable, Callable, Coroutine, Sequence -from fastapi import Depends, FastAPI, HTTPException, Header, Request, Response, status +from fastapi import Depends, FastAPI, HTTPException, Header, Request, Response from fastapi.responses import JSONResponse from transcriptomics_data_service.authz.middleware_base import BaseAuthzMiddleware diff --git a/authz_plugins/bento/authz.module.py b/authz_plugins/bento/authz.module.py index 8e8c40f..79801cf 100644 --- a/authz_plugins/bento/authz.module.py +++ b/authz_plugins/bento/authz.module.py @@ -8,7 +8,6 @@ from transcriptomics_data_service.logger import get_logger from transcriptomics_data_service.authz.middleware_base import BaseAuthzMiddleware -import re config = get_config() logger = get_logger(config) diff --git a/authz_plugins/opa/authz.module.py b/authz_plugins/opa/authz.module.py index 3f76c1e..1ade57c 100644 --- a/authz_plugins/opa/authz.module.py +++ b/authz_plugins/opa/authz.module.py @@ -2,6 +2,7 @@ from typing import Any, Awaitable, Callable, Coroutine from fastapi import Depends, FastAPI, HTTPException, Request, Response from fastapi.responses import JSONResponse +from opa_client.opa import OpaClient # CUSTOM PLUGIN DEPENDENCY from transcriptomics_data_service.authz.middleware_base import BaseAuthzMiddleware from transcriptomics_data_service.config import Config, get_config @@ -10,16 +11,13 @@ config = get_config() logger = get_logger(config) - """ CUSTOM PLUGIN DEPENDENCY Extra dependencies can be added if the authz plugin requires them. -In this example, the authz module imports the OPA agent. +In this example, the authz module imports the OPA client. Since OPA does not ship with TDS, a requirements.txt file must be placed under 'lib'. """ -from opa_client.opa import OpaClient - class OPAAuthzMiddleware(BaseAuthzMiddleware): """ @@ -37,12 +35,10 @@ def __init__(self, config: Config, logger: Logger) -> None: # Init the OPA client with the server self.opa_client = OpaClient(host=opa_host, port=opa_port) - try: - # Commented out as this is not pointing to a real OPA server - # self.logger.info(self.opa_client.check_connection()) - pass - except: - raise Exception("Could not establish connection to the OPA service.") + + # This is not pointing to a real OPA server. + # Will raise an exception if connection is invalid. + self.logger.info(self.opa_client.check_connection()) # Middleware lifecycle diff --git a/poetry.lock b/poetry.lock index b615015..90eaf89 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2345,6 +2345,33 @@ files = [ {file = "rpds_py-0.20.0.tar.gz", hash = "sha256:d72a210824facfdaf8768cf2d7ca25a042c30320b3020de2fa04640920d4e121"}, ] +[[package]] +name = "ruff" +version = "0.7.3" +description = "An extremely fast Python linter and code formatter, written in Rust." +optional = false +python-versions = ">=3.7" +files = [ + {file = "ruff-0.7.3-py3-none-linux_armv6l.whl", hash = "sha256:34f2339dc22687ec7e7002792d1f50712bf84a13d5152e75712ac08be565d344"}, + {file = "ruff-0.7.3-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:fb397332a1879b9764a3455a0bb1087bda876c2db8aca3a3cbb67b3dbce8cda0"}, + {file = "ruff-0.7.3-py3-none-macosx_11_0_arm64.whl", hash = "sha256:37d0b619546103274e7f62643d14e1adcbccb242efda4e4bdb9544d7764782e9"}, + {file = "ruff-0.7.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d59f0c3ee4d1a6787614e7135b72e21024875266101142a09a61439cb6e38a5"}, + {file = "ruff-0.7.3-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:44eb93c2499a169d49fafd07bc62ac89b1bc800b197e50ff4633aed212569299"}, + {file = "ruff-0.7.3-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6d0242ce53f3a576c35ee32d907475a8d569944c0407f91d207c8af5be5dae4e"}, + {file = "ruff-0.7.3-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:6b6224af8b5e09772c2ecb8dc9f3f344c1aa48201c7f07e7315367f6dd90ac29"}, + {file = "ruff-0.7.3-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c50f95a82b94421c964fae4c27c0242890a20fe67d203d127e84fbb8013855f5"}, + {file = "ruff-0.7.3-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7f3eff9961b5d2644bcf1616c606e93baa2d6b349e8aa8b035f654df252c8c67"}, + {file = "ruff-0.7.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8963cab06d130c4df2fd52c84e9f10d297826d2e8169ae0c798b6221be1d1d2"}, + {file = "ruff-0.7.3-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:61b46049d6edc0e4317fb14b33bd693245281a3007288b68a3f5b74a22a0746d"}, + {file = "ruff-0.7.3-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:10ebce7696afe4644e8c1a23b3cf8c0f2193a310c18387c06e583ae9ef284de2"}, + {file = "ruff-0.7.3-py3-none-musllinux_1_2_i686.whl", hash = "sha256:3f36d56326b3aef8eeee150b700e519880d1aab92f471eefdef656fd57492aa2"}, + {file = "ruff-0.7.3-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:5d024301109a0007b78d57ab0ba190087b43dce852e552734ebf0b0b85e4fb16"}, + {file = "ruff-0.7.3-py3-none-win32.whl", hash = "sha256:4ba81a5f0c5478aa61674c5a2194de8b02652f17addf8dfc40c8937e6e7d79fc"}, + {file = "ruff-0.7.3-py3-none-win_amd64.whl", hash = "sha256:588a9ff2fecf01025ed065fe28809cd5a53b43505f48b69a1ac7707b1b7e4088"}, + {file = "ruff-0.7.3-py3-none-win_arm64.whl", hash = "sha256:1713e2c5545863cdbfe2cbce21f69ffaf37b813bfd1fb3b90dc9a6f1963f5a8c"}, + {file = "ruff-0.7.3.tar.gz", hash = "sha256:e1d1ba2e40b6e71a61b063354d04be669ab0d39c352461f3d789cac68b54a313"}, +] + [[package]] name = "shellingham" version = "1.5.4" @@ -2979,4 +3006,4 @@ propcache = ">=0.2.0" [metadata] lock-version = "2.0" python-versions = "^3.10.0" -content-hash = "e1f14766443f4c6dec54f21e6f507ad1c0563fd718f0fcf5e1ebd068f91431ef" +content-hash = "44831e62a0a5411a7847a509a457d9a48f1edd05710bcb213fde900f04c6c2cf" diff --git a/pyproject.toml b/pyproject.toml index 2eaec1d..61fcc89 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,6 +14,7 @@ jsonschema = "^4.21.1" pydantic-settings = "^2.1.0" asyncpg = "^0.29.0" pandas = "^2.2.3" +ruff = "^0.7.3" [tool.poetry.group.dev.dependencies] aioresponses = "^0.7.6" @@ -31,5 +32,11 @@ fasta-checksum-utils = "^0.4.3" requires = ["poetry-core"] build-backend = "poetry.core.masonry.api" +# Black is for formating [tool.black] line_length = 120 + +# Ruff is for linting. +# Fully compatible with Black, as long as both use the same line-length config +[tool.ruff] +line-length = 120 diff --git a/transcriptomics_data_service/authz/middleware_base.py b/transcriptomics_data_service/authz/middleware_base.py index 0f2cfba..5705461 100644 --- a/transcriptomics_data_service/authz/middleware_base.py +++ b/transcriptomics_data_service/authz/middleware_base.py @@ -1,4 +1,4 @@ -from fastapi import Depends, FastAPI, Request, Response, status +from fastapi import Depends, FastAPI, Request, Response from typing import Awaitable, Callable, Sequence @@ -28,7 +28,7 @@ async def dispatch(self, request: Request, call_next: Callable[[Request], Awaita - Raise and catch exception based on authorization results - Handle unauthorized responses """ - raise NotImplemented() + raise NotImplementedError() def mark_authz_done(self, request: Request): """ diff --git a/transcriptomics_data_service/routers/ingest.py b/transcriptomics_data_service/routers/ingest.py index fab821b..ca895d7 100644 --- a/transcriptomics_data_service/routers/ingest.py +++ b/transcriptomics_data_service/routers/ingest.py @@ -1,6 +1,5 @@ from logging import Logger -from fastapi import APIRouter, File, HTTPException, Request, UploadFile, status -import json +from fastapi import APIRouter, File, HTTPException, UploadFile, status from io import StringIO import pandas as pd @@ -98,7 +97,7 @@ async def normalize( features_lengths_file: UploadFile = File(...), status_code=status.HTTP_200_OK, ): - features_lengths = json.load(features_lengths_file.file) + # features_lengths = json.load(features_lengths_file.file) # TODO validate shape # TODO validate experiment_result_id exists # TODO algorithm selection argument? From 733d1ca5f00fefe18486d7c68d7c85af509825e3 Mon Sep 17 00:00:00 2001 From: Victor Rocheleau Date: Thu, 14 Nov 2024 14:37:56 -0500 Subject: [PATCH 30/31] lint --- authz_plugins/opa/authz.module.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/authz_plugins/opa/authz.module.py b/authz_plugins/opa/authz.module.py index 1ade57c..bd05781 100644 --- a/authz_plugins/opa/authz.module.py +++ b/authz_plugins/opa/authz.module.py @@ -2,7 +2,7 @@ from typing import Any, Awaitable, Callable, Coroutine from fastapi import Depends, FastAPI, HTTPException, Request, Response from fastapi.responses import JSONResponse -from opa_client.opa import OpaClient # CUSTOM PLUGIN DEPENDENCY +from opa_client.opa import OpaClient # CUSTOM PLUGIN DEPENDENCY from transcriptomics_data_service.authz.middleware_base import BaseAuthzMiddleware from transcriptomics_data_service.config import Config, get_config From bfb9ac00a77297a28bf86ffc5d45ecdc65c3ca80 Mon Sep 17 00:00:00 2001 From: Victor Rocheleau Date: Thu, 14 Nov 2024 16:17:08 -0500 Subject: [PATCH 31/31] chore: replace black with ruff formater --- .github/workflows/lint.yml | 2 +- poetry.lock | 70 +------------------ pyproject.toml | 8 +-- .../authz/middleware_base.py | 1 - 4 files changed, 3 insertions(+), 78 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index d716adc..0d972cb 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -24,7 +24,7 @@ jobs: run: poetry install - name: Format check run: | - poetry run black --check transcriptomics_data_service tests authz_plugins + poetry run ruff format --check - name: Lint check run: | poetry run ruff check diff --git a/poetry.lock b/poetry.lock index 90eaf89..d365518 100644 --- a/poetry.lock +++ b/poetry.lock @@ -311,52 +311,6 @@ django = ["django (>=5.0.8,<5.2)", "djangorestframework (>=3.14.0,<3.16)"] fastapi = ["fastapi (>=0.112.1,<0.116)"] flask = ["flask (>=2.2.5,<4)"] -[[package]] -name = "black" -version = "24.10.0" -description = "The uncompromising code formatter." -optional = false -python-versions = ">=3.9" -files = [ - {file = "black-24.10.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e6668650ea4b685440857138e5fe40cde4d652633b1bdffc62933d0db4ed9812"}, - {file = "black-24.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1c536fcf674217e87b8cc3657b81809d3c085d7bf3ef262ead700da345bfa6ea"}, - {file = "black-24.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:649fff99a20bd06c6f727d2a27f401331dc0cc861fb69cde910fe95b01b5928f"}, - {file = "black-24.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:fe4d6476887de70546212c99ac9bd803d90b42fc4767f058a0baa895013fbb3e"}, - {file = "black-24.10.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5a2221696a8224e335c28816a9d331a6c2ae15a2ee34ec857dcf3e45dbfa99ad"}, - {file = "black-24.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f9da3333530dbcecc1be13e69c250ed8dfa67f43c4005fb537bb426e19200d50"}, - {file = "black-24.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4007b1393d902b48b36958a216c20c4482f601569d19ed1df294a496eb366392"}, - {file = "black-24.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:394d4ddc64782e51153eadcaaca95144ac4c35e27ef9b0a42e121ae7e57a9175"}, - {file = "black-24.10.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b5e39e0fae001df40f95bd8cc36b9165c5e2ea88900167bddf258bacef9bbdc3"}, - {file = "black-24.10.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d37d422772111794b26757c5b55a3eade028aa3fde43121ab7b673d050949d65"}, - {file = "black-24.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:14b3502784f09ce2443830e3133dacf2c0110d45191ed470ecb04d0f5f6fcb0f"}, - {file = "black-24.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:30d2c30dc5139211dda799758559d1b049f7f14c580c409d6ad925b74a4208a8"}, - {file = "black-24.10.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1cbacacb19e922a1d75ef2b6ccaefcd6e93a2c05ede32f06a21386a04cedb981"}, - {file = "black-24.10.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1f93102e0c5bb3907451063e08b9876dbeac810e7da5a8bfb7aeb5a9ef89066b"}, - {file = "black-24.10.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ddacb691cdcdf77b96f549cf9591701d8db36b2f19519373d60d31746068dbf2"}, - {file = "black-24.10.0-cp313-cp313-win_amd64.whl", hash = "sha256:680359d932801c76d2e9c9068d05c6b107f2584b2a5b88831c83962eb9984c1b"}, - {file = "black-24.10.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:17374989640fbca88b6a448129cd1745c5eb8d9547b464f281b251dd00155ccd"}, - {file = "black-24.10.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:63f626344343083322233f175aaf372d326de8436f5928c042639a4afbbf1d3f"}, - {file = "black-24.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccfa1d0cb6200857f1923b602f978386a3a2758a65b52e0950299ea014be6800"}, - {file = "black-24.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:2cd9c95431d94adc56600710f8813ee27eea544dd118d45896bb734e9d7a0dc7"}, - {file = "black-24.10.0-py3-none-any.whl", hash = "sha256:3bb2b7a1f7b685f85b11fed1ef10f8a9148bceb49853e47a294a3dd963c1dd7d"}, - {file = "black-24.10.0.tar.gz", hash = "sha256:846ea64c97afe3bc677b761787993be4991810ecc7a4a937816dd6bddedc4875"}, -] - -[package.dependencies] -click = ">=8.0.0" -mypy-extensions = ">=0.4.3" -packaging = ">=22.0" -pathspec = ">=0.9.0" -platformdirs = ">=2" -tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} -typing-extensions = {version = ">=4.0.1", markers = "python_version < \"3.11\""} - -[package.extras] -colorama = ["colorama (>=0.4.3)"] -d = ["aiohttp (>=3.10)"] -jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] -uvloop = ["uvloop (>=0.15.2)"] - [[package]] name = "cachetools" version = "5.5.0" @@ -1293,17 +1247,6 @@ files = [ [package.dependencies] typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.11\""} -[[package]] -name = "mypy-extensions" -version = "1.0.0" -description = "Type system extensions for programs checked with the mypy type checker." -optional = false -python-versions = ">=3.5" -files = [ - {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, - {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, -] - [[package]] name = "numpy" version = "2.1.2" @@ -1530,17 +1473,6 @@ sql-other = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-d test = ["hypothesis (>=6.46.1)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)"] xml = ["lxml (>=4.9.2)"] -[[package]] -name = "pathspec" -version = "0.12.1" -description = "Utility library for gitignore style pattern matching of file paths." -optional = false -python-versions = ">=3.8" -files = [ - {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, - {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, -] - [[package]] name = "platformdirs" version = "4.3.6" @@ -3006,4 +2938,4 @@ propcache = ">=0.2.0" [metadata] lock-version = "2.0" python-versions = "^3.10.0" -content-hash = "44831e62a0a5411a7847a509a457d9a48f1edd05710bcb213fde900f04c6c2cf" +content-hash = "1bd72e45304765cb9f9ab229050db265f71b1525dbab2fcda2504360e464d957" diff --git a/pyproject.toml b/pyproject.toml index 61fcc89..e86b19c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -18,7 +18,6 @@ ruff = "^0.7.3" [tool.poetry.group.dev.dependencies] aioresponses = "^0.7.6" -black = "^24.8.0" coverage = "^7.4.0" debugpy = "^1.8.1" httpx = "^0.27.0" @@ -32,11 +31,6 @@ fasta-checksum-utils = "^0.4.3" requires = ["poetry-core"] build-backend = "poetry.core.masonry.api" -# Black is for formating -[tool.black] -line_length = 120 - -# Ruff is for linting. -# Fully compatible with Black, as long as both use the same line-length config +# Linting and formating using Ruff [tool.ruff] line-length = 120 diff --git a/transcriptomics_data_service/authz/middleware_base.py b/transcriptomics_data_service/authz/middleware_base.py index 5705461..560e07f 100644 --- a/transcriptomics_data_service/authz/middleware_base.py +++ b/transcriptomics_data_service/authz/middleware_base.py @@ -4,7 +4,6 @@ class BaseAuthzMiddleware: - # Middleware lifecycle functions def attach(self, app: FastAPI):