diff --git a/flixpy/examples/revision_a_panel.py b/flixpy/examples/revision_a_panel.py index 9147a65..e476c14 100644 --- a/flixpy/examples/revision_a_panel.py +++ b/flixpy/examples/revision_a_panel.py @@ -7,6 +7,7 @@ from __future__ import annotations import asyncio +import os from pathlib import Path import flix @@ -14,8 +15,8 @@ # Authentication data HOSTNAME = "localhost" PORT = 8080 -USERNAME = "admin" -PASSWORD = "admin" +API_KEY = os.getenv("FLIX_API_KEY") +API_SECRET = os.getenv("FLIX_API_SECRET") # Flix IDs SHOW_ID = 1 @@ -28,9 +29,7 @@ async def main() -> None: - async with flix.Client(HOSTNAME, PORT) as client: - # Log into the Flix server - await client.authenticate(USERNAME, PASSWORD) + async with flix.Client(HOSTNAME, PORT, api_key=API_KEY, api_secret=API_SECRET) as client: # Get the show from the server show = await client.get_show(SHOW_ID) # Create an 'artwork' media object with the file and transcode it to create a thumbnail diff --git a/flixpy/examples/shotgrid_create_show.py b/flixpy/examples/shotgrid_create_show.py index 660e4ab..cfce75c 100644 --- a/flixpy/examples/shotgrid_create_show.py +++ b/flixpy/examples/shotgrid_create_show.py @@ -15,6 +15,7 @@ import asyncio import logging +import os import re from typing import TypedDict, cast @@ -31,8 +32,8 @@ # Flix server and credentials for creating the new show FLIX_HOSTNAME = "localhost" FLIX_PORT = 8080 -FLIX_USERNAME = "admin" -FLIX_PASSWORD = "admin" +FLIX_API_KEY = os.getenv("FLIX_API_KEY") +FLIX_API_SECRET = os.getenv("FLIX_API_SECRET") # optional statically typed schemas for our ShotGrid data, @@ -83,9 +84,9 @@ async def import_sg_show() -> None: finally: sg.close() - async with flix.Client(FLIX_HOSTNAME, FLIX_PORT) as client: - await client.authenticate(FLIX_USERNAME, FLIX_PASSWORD) - + async with flix.Client( + FLIX_HOSTNAME, FLIX_PORT, api_key=FLIX_API_KEY, api_secret=FLIX_API_SECRET + ) as client: # create a new show with the appropriate tracking code, # title and description; default values will be used for # the frame rate (24 fps) and aspect ratio (1.77) diff --git a/flixpy/examples/shotgrid_version_sequence.py b/flixpy/examples/shotgrid_version_sequence.py index 4e947ee..85686a5 100644 --- a/flixpy/examples/shotgrid_version_sequence.py +++ b/flixpy/examples/shotgrid_version_sequence.py @@ -20,6 +20,7 @@ import asyncio import contextlib import logging +import os import tempfile from typing import TYPE_CHECKING, Literal, TypedDict, cast @@ -40,8 +41,8 @@ # Flix server and credentials for exporting the QuickTime FLIX_HOSTNAME = "localhost" FLIX_PORT = 8080 -FLIX_USERNAME = "admin" -FLIX_PASSWORD = "admin" +FLIX_API_KEY = os.getenv("FLIX_API_KEY") +FLIX_API_SECRET = os.getenv("FLIX_API_SECRET") # create long-lived ShotGrid client so we don't need # to create a new one for each event @@ -172,8 +173,8 @@ async def run_publish_webhook() -> None: client_options={ "hostname": FLIX_HOSTNAME, "port": FLIX_PORT, - "username": FLIX_USERNAME, - "password": FLIX_PASSWORD, + "api_key": FLIX_API_KEY, + "api_secret": FLIX_API_SECRET, }, ) diff --git a/flixpy/examples/update_sequence_metadata.py b/flixpy/examples/update_sequence_metadata.py index 95d2eb1..71ce4fd 100644 --- a/flixpy/examples/update_sequence_metadata.py +++ b/flixpy/examples/update_sequence_metadata.py @@ -11,13 +11,14 @@ import asyncio import datetime +import os import flix HOSTNAME = "localhost" PORT = 8080 -USERNAME = "admin" -PASSWORD = "admin" +API_KEY = os.getenv("FLIX_API_KEY") +API_SECRET = os.getenv("FLIX_API_SECRET") SHOW_ID = 478 SEQUENCE_ID = 415 @@ -25,10 +26,7 @@ async def update_sequence_metadata() -> None: """Updates metadata for an existing sequence.""" - async with flix.Client(HOSTNAME, PORT) as client: - # authenticate with the Flix server - await client.authenticate(USERNAME, PASSWORD) - + async with flix.Client(HOSTNAME, PORT, api_key=API_KEY, api_secret=API_SECRET) as client: # fetch show and sequence show = await client.get_show(SHOW_ID) sequence = await show.get_sequence(SEQUENCE_ID) diff --git a/flixpy/examples/webhook_add.py b/flixpy/examples/webhook_add.py index 535a39c..3f83b98 100644 --- a/flixpy/examples/webhook_add.py +++ b/flixpy/examples/webhook_add.py @@ -7,14 +7,19 @@ from __future__ import annotations import asyncio +import os import flix +HOSTNAME = "localhost" +PORT = 8080 +API_KEY = os.getenv("FLIX_API_KEY") +API_SECRET = os.getenv("FLIX_API_SECRET") + async def register_webhook() -> None: """Register a webhook with Flix.""" - async with flix.Client("localhost", 8080) as client: - await client.authenticate("admin", "admin") + async with flix.Client(HOSTNAME, PORT, api_key=API_KEY, api_secret=API_SECRET) as client: webhook = await client.post( "/webhook", body={ diff --git a/flixpy/flix/cli/interactive_client.py b/flixpy/flix/cli/interactive_client.py index dde1efa..5c82481 100644 --- a/flixpy/flix/cli/interactive_client.py +++ b/flixpy/flix/cli/interactive_client.py @@ -2,12 +2,11 @@ from __future__ import annotations -import contextlib from typing import TYPE_CHECKING, Any import asyncclick as click -from ..lib import client, errors +from ..lib import client, errors, models if TYPE_CHECKING: import aiohttp @@ -31,33 +30,27 @@ def __init__( config: dict[str, Any], username: str | None = None, password: str | None = None, + access_key: models.AccessKey | None = None, ) -> None: - try: - access_key = client.AccessKey(config["access_key"]) - except KeyError: - access_key = None - super().__init__( hostname, port, ssl=ssl, - access_key=access_key, + access_key=client.AccessKey(access_key) if access_key else None, disable_ssl_validation=config.get("disable_ssl_validation", False), ) - self._config = config - self._username = username - self._password = password + self.__config = config + self.__username = username + self.__password = password async def _sign_in(self) -> None: click.echo("Not signed in, attempting to authenticate...", err=True) + self.__config.pop("access_key", None) - with contextlib.suppress(KeyError): - del self._config["access_key"] - - username = self._username or click.prompt("Username", type=str, err=True) - password = self._password or click.prompt("Password", type=str, hide_input=True, err=True) + username = self.__username or click.prompt("Username", type=str, err=True) + password = self.__password or click.prompt("Password", type=str, hide_input=True, err=True) access_key = await self.authenticate(username, password) - self._config["access_key"] = access_key.to_json() + self.__config["access_key"] = access_key.to_json() async def request(self, *args: Any, **kwargs: Any) -> aiohttp.ClientResponse: try: diff --git a/flixpy/flix/cli/main.py b/flixpy/flix/cli/main.py index 9550e46..2c67f7f 100644 --- a/flixpy/flix/cli/main.py +++ b/flixpy/flix/cli/main.py @@ -52,16 +52,24 @@ async def get_client(ctx: click.Context, server: str | None = None) -> client.Cl config=ctx.obj["config"], username=ctx.obj.get("username"), password=ctx.obj.get("password"), + access_key=ctx.obj.get("access_key"), ) @click.group() @click.option("-s", "--server", type=str, help="The URL of the Flix server.") -@click.option("-u", "--username", type=str, help="The username to authenticate with.") -@click.option("-p", "--password", type=str, help="The password to authenticate with.") +@click.option("--key", type=str, help="The API key to authenticate with.") +@click.option("--secret", type=str, help="The API key secret to authenticate with.") +@click.option("-u", "--username", type=str, help="The username to authenticate with (deprecated).") +@click.option("-p", "--password", type=str, help="The password to authenticate with (deprecated).") @click.pass_context async def flix_cli( - ctx: click.Context, server: str | None, username: str | None, password: str | None + ctx: click.Context, + server: str | None, + username: str | None, + password: str | None, + key: str | None, + secret: str | None, ) -> None: cfg = read_config() ctx.ensure_object(dict) @@ -69,6 +77,12 @@ async def flix_cli( ctx.obj["server"] = server or cfg.get("server") ctx.obj["username"] = username or cfg.get("username") ctx.obj["password"] = password or cfg.get("password") + if key or secret: + if not key or not secret: + raise click.ClickException("Must provide both --key and --secret.") + ctx.obj["access_key"] = models.AccessKey(id=key, secret_access_key=secret) + else: + ctx.obj["access_key"] = cfg.get("access_key") @flix_cli.result_callback() @@ -79,8 +93,10 @@ def save_config(ctx: click.Context, /, *_args: Any, **_kwargs: Any) -> None: @flix_cli.command("config", help="Set default configuration values.") @click.option("-s", "--server", type=str, help="The default server URL.") -@click.option("-u", "--username", type=str, help="The default username.") -@click.option("-p", "--password", type=str, help="The default password.") +@click.option("--key", type=str, help="The API key to authenticate with.") +@click.option("--secret", type=str, help="The API key secret to authenticate with.") +@click.option("-u", "--username", type=str, help="The default username (deprecated).") +@click.option("-p", "--password", type=str, help="The default password (deprecated).") @click.option( "--disable-ssl-validation", type=bool, @@ -91,6 +107,8 @@ def save_config(ctx: click.Context, /, *_args: Any, **_kwargs: Any) -> None: def config( ctx: click.Context, server: str | None, + key: str | None, + secret: str | None, username: str | None, password: str | None, disable_ssl_validation: bool, @@ -104,6 +122,12 @@ def config( cfg["username"] = username if password: cfg["password"] = password + if key or secret: + if not key or not secret: + raise click.ClickException("Must provide both --key and --secret.") + cfg["access_key"] = models.AccessKey(id=key, secret_access_key=secret) + cfg.pop("username", None) + cfg.pop("password", None) if clear: cfg = {} ctx.obj["config"] = cfg diff --git a/flixpy/flix/lib/client.py b/flixpy/flix/lib/client.py index 0553525..608379f 100644 --- a/flixpy/flix/lib/client.py +++ b/flixpy/flix/lib/client.py @@ -5,10 +5,10 @@ import asyncio import base64 import contextlib -import dataclasses import datetime import json import logging +import typing import urllib.parse import warnings from collections.abc import AsyncIterator, Mapping @@ -17,6 +17,7 @@ import aiohttp import dateutil.parser +from typing_extensions import Unpack from . import _utils, errors, forms, models, signing, types, websocket @@ -28,11 +29,10 @@ logger = logging.getLogger(__name__) -@dataclasses.dataclass class AccessKey: """Holds information about a user session.""" - def __init__(self, access_key: dict[str, Any]) -> None: + def __init__(self, access_key: models.AccessKey) -> None: """Constructs a new AccessKey object. Args: @@ -42,16 +42,21 @@ def __init__(self, access_key: dict[str, Any]) -> None: """The ID used to identify the access key.""" self.secret_access_key: str = access_key["secret_access_key"] """The secret used to sign requests.""" - self.created_date = dateutil.parser.parse(access_key["created_date"]) + self.created_date = ( + dateutil.parser.parse(v) if (v := access_key.get("created_date")) else None + ) """When the access key was created.""" - self.expiry_date = dateutil.parser.parse(access_key["expiry_date"]) + self.expiry_date = ( + dateutil.parser.parse(v) if (v := access_key.get("expiry_date")) else None + ) """When the access key expires.""" @property def has_expired(self) -> bool: """Whether this access key has expired.""" - now = datetime.datetime.now(datetime.timezone.utc) - return self.expiry_date < now + return self.expiry_date is not None and self.expiry_date < datetime.datetime.now( + datetime.timezone.utc + ) def to_json(self) -> dict[str, Any]: """Returns a JSON-serialisable representation of this access key. @@ -62,19 +67,27 @@ def to_json(self) -> dict[str, Any]: return { "id": self.id, "secret_access_key": self.secret_access_key, - "created_date": self.created_date.isoformat(), - "expiry_date": self.expiry_date.isoformat(), + "created_date": self.created_date.isoformat() if self.created_date else None, + "expiry_date": self.expiry_date.isoformat() if self.expiry_date else None, } ClientSelf = TypeVar("ClientSelf", bound="BaseClient") +class DeprecatedOptions(typing.TypedDict, total=False): + """Additional deprecated/discouraged client options which may be removed in the future.""" + + auto_extend_session: bool + username: str | None + password: str | None + + class BaseClient: """Base class for [flix.Client][]. A thin wrapper around aiohttp.ClientSession that provides - automatic signing of Flix requests and a helper function for authenticating.. + automatic signing of Flix requests and a helper function for authenticating. """ def __init__( @@ -84,10 +97,10 @@ def __init__( ssl: bool = False, disable_ssl_validation: bool = False, *, - username: str | None = None, - password: str | None = None, - auto_extend_session: bool = True, + api_key: str | None = None, + api_secret: str | None = None, access_key: AccessKey | None = None, + **kwargs: Unpack[DeprecatedOptions], ) -> None: """Instantiate a new Flix client. @@ -97,21 +110,32 @@ def __init__( ssl: Whether to use HTTPS to communicate with the server. disable_ssl_validation: Whether to disable validation of SSL certificates. Enables MITM attacks. - username: The user to authenticate as. If provided, the client will automatically - authenticate whenever we don't have a valid session. - password: The password for the user to authenticate as. Must be provided - if ``username`` is provided. - auto_extend_session: Automatically keep the session alive by periodically extending - the access key validity time following a successful authentication. + api_key: The public ID of the API key, visible in the list of API keys + within the Flix client. + api_secret: The secret part of the API key, only shown when initially + creating the API key. access_key: The access key of an already authenticated user. + kwargs: Additional deprecated options. """ + username = kwargs.get("username") + password = kwargs.get("password") + if username is not None or password is not None: + logger.warning( + "Using a username and password for authentication is not recommended. " + "Consider using an API key instead." + ) + if api_key is not None and api_secret is not None: + if access_key is not None: + logger.warning("Both API key and access key provided; ignoring access key.") + access_key = AccessKey({"id": api_key, "secret_access_key": api_secret}) + self._hostname = hostname self._port = port self._ssl = ssl self._disable_ssl_validation = disable_ssl_validation self._username = username self._password = password - self._auto_extend_session = auto_extend_session + self._auto_extend_session = kwargs.get("auto_extend_session", True) self._access_key = access_key self._session = aiohttp.ClientSession() @@ -373,6 +397,9 @@ async def authenticate(self, user: str, password: str) -> AccessKey: On a successful authentication, this will set access_key. + Deprecated: Prefer passing an API key when constructing a client + instead of using user credentials. + Args: user: The username of the user to authenticate as. password: The password of the user to authenticate as. @@ -384,12 +411,16 @@ async def authenticate(self, user: str, password: str) -> AccessKey: Returns: A new access key for the user. """ + warnings.warn( + "Provide an API key when creating a Client instead", DeprecationWarning, stacklevel=1 + ) self._access_key = None # call _request directly to avoid recursion when automatically authenticating response = await self._request( "POST", "/authenticate", auth=aiohttp.BasicAuth(user, password) ) - self._access_key = AccessKey(await response.json()) + access_key = cast(models.AccessKey, await response.json()) + self._access_key = AccessKey(access_key) if self._refresh_token_task is None and self._auto_extend_session: self._refresh_token_task = asyncio.create_task(self._periodically_refresh_token()) @@ -424,7 +455,8 @@ async def extend_session(self) -> None: # a FlixNotVerifiedError means the access key has expired, # in which case we'll reauthenticate before the next request with contextlib.suppress(errors.FlixNotVerifiedError): - self._access_key = AccessKey(await self.post("/authenticate/extend")) + access_key = cast(models.AccessKey, await self.post("/authenticate/extend")) + self._access_key = AccessKey(access_key) async def _periodically_refresh_token(self) -> None: """Try to extend the session once an hour.""" @@ -477,9 +509,12 @@ class Client(BaseClient): Example: ```python - async with Client("localhost", 8080) as client: - await client.authenticate("admin", "admin") - + async with Client( + "localhost", + 8080, + api_key="2268759986af4173898e", + api_secret="e7263d6a190644339f4e234aaf2a9bf38e761813", + ) as client: # print the tracking code of all shows shows = await client.get_all_shows() for show in shows: @@ -494,10 +529,10 @@ def __init__( ssl: bool = False, disable_ssl_validation: bool = False, *, - username: str | None = None, - password: str | None = None, - auto_extend_session: bool = True, + api_key: str | None = None, + api_secret: str | None = None, access_key: AccessKey | None = None, + **kwargs: Unpack[DeprecatedOptions], ) -> None: """Instantiate a new Flix client. @@ -507,23 +542,22 @@ def __init__( ssl: Whether to use HTTPS to communicate with the server. disable_ssl_validation: Whether to disable validation of SSL certificates. Enables MITM attacks. - username: The user to authenticate as. If provided, the client will automatically - authenticate whenever we don't have a valid session. - password: The password for the user to authenticate as. Must be provided - if ``username`` is provided. - auto_extend_session: Automatically keep the session alive by periodically extending - the access key validity time following a successful authentication. + api_key: The public ID of the API key, visible in the list of API keys + within the Flix client. + api_secret: The secret part of the API key, only shown when initially + creating the API key. access_key: The access key of an already authenticated user. + kwargs: Additional deprecated options. """ super().__init__( hostname=hostname, port=port, ssl=ssl, disable_ssl_validation=disable_ssl_validation, - username=username, - password=password, - auto_extend_session=auto_extend_session, + api_key=api_key, + api_secret=api_secret, access_key=access_key, + **kwargs, ) @contextlib.asynccontextmanager diff --git a/flixpy/flix/lib/models.py b/flixpy/flix/lib/models.py index f9f50c0..2ec74ed 100644 --- a/flixpy/flix/lib/models.py +++ b/flixpy/flix/lib/models.py @@ -379,3 +379,10 @@ class Server(TypedDict): db_ident: str is_ssl: bool transfer_port: int + + +class AccessKey(TypedDict): + id: str + secret_access_key: str + created_date: NotRequired[str] + expiry_date: NotRequired[str] diff --git a/flixpy/flix/lib/webhooks.py b/flixpy/flix/lib/webhooks.py index e4a29f1..7dac329 100644 --- a/flixpy/flix/lib/webhooks.py +++ b/flixpy/flix/lib/webhooks.py @@ -382,16 +382,15 @@ def decorator(f: WebhookHandlerType[WebhookEvent]) -> WebhookHandler: return decorator -class ClientOptions(TypedDict, total=False): +class ClientOptions(_client.DeprecatedOptions, total=False): """Options to pass to [Client][flix.Client].""" hostname: Required[str] port: Required[int] ssl: bool disable_ssl_validation: bool - username: str - password: str - auto_extend_session: bool + api_key: str | None + api_secret: str | None access_key: _client.AccessKey diff --git a/flixpy/poetry.lock b/flixpy/poetry.lock index ecb9541..434a808 100644 --- a/flixpy/poetry.lock +++ b/flixpy/poetry.lock @@ -849,6 +849,91 @@ MarkupSafe = ">=2.0" [package.extras] i18n = ["Babel (>=2.7)"] +[[package]] +name = "librt" +version = "0.7.8" +description = "Mypyc runtime library" +optional = false +python-versions = ">=3.9" +files = [ + {file = "librt-0.7.8-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b45306a1fc5f53c9330fbee134d8b3227fe5da2ab09813b892790400aa49352d"}, + {file = "librt-0.7.8-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:864c4b7083eeee250ed55135d2127b260d7eb4b5e953a9e5df09c852e327961b"}, + {file = "librt-0.7.8-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:6938cc2de153bc927ed8d71c7d2f2ae01b4e96359126c602721340eb7ce1a92d"}, + {file = "librt-0.7.8-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:66daa6ac5de4288a5bbfbe55b4caa7bf0cd26b3269c7a476ffe8ce45f837f87d"}, + {file = "librt-0.7.8-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4864045f49dc9c974dadb942ac56a74cd0479a2aafa51ce272c490a82322ea3c"}, + {file = "librt-0.7.8-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a36515b1328dc5b3ffce79fe204985ca8572525452eacabee2166f44bb387b2c"}, + {file = "librt-0.7.8-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:b7e7f140c5169798f90b80d6e607ed2ba5059784968a004107c88ad61fb3641d"}, + {file = "librt-0.7.8-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ff71447cb778a4f772ddc4ce360e6ba9c95527ed84a52096bd1bbf9fee2ec7c0"}, + {file = "librt-0.7.8-cp310-cp310-win32.whl", hash = "sha256:047164e5f68b7a8ebdf9fae91a3c2161d3192418aadd61ddd3a86a56cbe3dc85"}, + {file = "librt-0.7.8-cp310-cp310-win_amd64.whl", hash = "sha256:d6f254d096d84156a46a84861183c183d30734e52383602443292644d895047c"}, + {file = "librt-0.7.8-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ff3e9c11aa260c31493d4b3197d1e28dd07768594a4f92bec4506849d736248f"}, + {file = "librt-0.7.8-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ddb52499d0b3ed4aa88746aaf6f36a08314677d5c346234c3987ddc506404eac"}, + {file = "librt-0.7.8-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:e9c0afebbe6ce177ae8edba0c7c4d626f2a0fc12c33bb993d163817c41a7a05c"}, + {file = "librt-0.7.8-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:631599598e2c76ded400c0a8722dec09217c89ff64dc54b060f598ed68e7d2a8"}, + {file = "librt-0.7.8-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9c1ba843ae20db09b9d5c80475376168feb2640ce91cd9906414f23cc267a1ff"}, + {file = "librt-0.7.8-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b5b007bb22ea4b255d3ee39dfd06d12534de2fcc3438567d9f48cdaf67ae1ae3"}, + {file = "librt-0.7.8-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:dbd79caaf77a3f590cbe32dc2447f718772d6eea59656a7dcb9311161b10fa75"}, + {file = "librt-0.7.8-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:87808a8d1e0bd62a01cafc41f0fd6818b5a5d0ca0d8a55326a81643cdda8f873"}, + {file = "librt-0.7.8-cp311-cp311-win32.whl", hash = "sha256:31724b93baa91512bd0a376e7cf0b59d8b631ee17923b1218a65456fa9bda2e7"}, + {file = "librt-0.7.8-cp311-cp311-win_amd64.whl", hash = "sha256:978e8b5f13e52cf23a9e80f3286d7546baa70bc4ef35b51d97a709d0b28e537c"}, + {file = "librt-0.7.8-cp311-cp311-win_arm64.whl", hash = "sha256:20e3946863d872f7cabf7f77c6c9d370b8b3d74333d3a32471c50d3a86c0a232"}, + {file = "librt-0.7.8-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:9b6943885b2d49c48d0cff23b16be830ba46b0152d98f62de49e735c6e655a63"}, + {file = "librt-0.7.8-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:46ef1f4b9b6cc364b11eea0ecc0897314447a66029ee1e55859acb3dd8757c93"}, + {file = "librt-0.7.8-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:907ad09cfab21e3c86e8f1f87858f7049d1097f77196959c033612f532b4e592"}, + {file = "librt-0.7.8-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2991b6c3775383752b3ca0204842743256f3ad3deeb1d0adc227d56b78a9a850"}, + {file = "librt-0.7.8-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:03679b9856932b8c8f674e87aa3c55ea11c9274301f76ae8dc4d281bda55cf62"}, + {file = "librt-0.7.8-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3968762fec1b2ad34ce57458b6de25dbb4142713e9ca6279a0d352fa4e9f452b"}, + {file = "librt-0.7.8-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:bb7a7807523a31f03061288cc4ffc065d684c39db7644c676b47d89553c0d714"}, + {file = "librt-0.7.8-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad64a14b1e56e702e19b24aae108f18ad1bf7777f3af5fcd39f87d0c5a814449"}, + {file = "librt-0.7.8-cp312-cp312-win32.whl", hash = "sha256:0241a6ed65e6666236ea78203a73d800dbed896cf12ae25d026d75dc1fcd1dac"}, + {file = "librt-0.7.8-cp312-cp312-win_amd64.whl", hash = "sha256:6db5faf064b5bab9675c32a873436b31e01d66ca6984c6f7f92621656033a708"}, + {file = "librt-0.7.8-cp312-cp312-win_arm64.whl", hash = "sha256:57175aa93f804d2c08d2edb7213e09276bd49097611aefc37e3fa38d1fb99ad0"}, + {file = "librt-0.7.8-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4c3995abbbb60b3c129490fa985dfe6cac11d88fc3c36eeb4fb1449efbbb04fc"}, + {file = "librt-0.7.8-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:44e0c2cbc9bebd074cf2cdbe472ca185e824be4e74b1c63a8e934cea674bebf2"}, + {file = "librt-0.7.8-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:4d2f1e492cae964b3463a03dc77a7fe8742f7855d7258c7643f0ee32b6651dd3"}, + {file = "librt-0.7.8-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:451e7ffcef8f785831fdb791bd69211f47e95dc4c6ddff68e589058806f044c6"}, + {file = "librt-0.7.8-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3469e1af9f1380e093ae06bedcbdd11e407ac0b303a56bbe9afb1d6824d4982d"}, + {file = "librt-0.7.8-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f11b300027ce19a34f6d24ebb0a25fd0e24a9d53353225a5c1e6cadbf2916b2e"}, + {file = "librt-0.7.8-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:4adc73614f0d3c97874f02f2c7fd2a27854e7e24ad532ea6b965459c5b757eca"}, + {file = "librt-0.7.8-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:60c299e555f87e4c01b2eca085dfccda1dde87f5a604bb45c2906b8305819a93"}, + {file = "librt-0.7.8-cp313-cp313-win32.whl", hash = "sha256:b09c52ed43a461994716082ee7d87618096851319bf695d57ec123f2ab708951"}, + {file = "librt-0.7.8-cp313-cp313-win_amd64.whl", hash = "sha256:f8f4a901a3fa28969d6e4519deceab56c55a09d691ea7b12ca830e2fa3461e34"}, + {file = "librt-0.7.8-cp313-cp313-win_arm64.whl", hash = "sha256:43d4e71b50763fcdcf64725ac680d8cfa1706c928b844794a7aa0fa9ac8e5f09"}, + {file = "librt-0.7.8-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:be927c3c94c74b05128089a955fba86501c3b544d1d300282cc1b4bd370cb418"}, + {file = "librt-0.7.8-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:7b0803e9008c62a7ef79058233db7ff6f37a9933b8f2573c05b07ddafa226611"}, + {file = "librt-0.7.8-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:79feb4d00b2a4e0e05c9c56df707934f41fcb5fe53fd9efb7549068d0495b758"}, + {file = "librt-0.7.8-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b9122094e3f24aa759c38f46bd8863433820654927370250f460ae75488b66ea"}, + {file = "librt-0.7.8-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7e03bea66af33c95ce3addf87a9bf1fcad8d33e757bc479957ddbc0e4f7207ac"}, + {file = "librt-0.7.8-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:f1ade7f31675db00b514b98f9ab9a7698c7282dad4be7492589109471852d398"}, + {file = "librt-0.7.8-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:a14229ac62adcf1b90a15992f1ab9c69ae8b99ffb23cb64a90878a6e8a2f5b81"}, + {file = "librt-0.7.8-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5bcaaf624fd24e6a0cb14beac37677f90793a96864c67c064a91458611446e83"}, + {file = "librt-0.7.8-cp314-cp314-win32.whl", hash = "sha256:7aa7d5457b6c542ecaed79cec4ad98534373c9757383973e638ccced0f11f46d"}, + {file = "librt-0.7.8-cp314-cp314-win_amd64.whl", hash = "sha256:3d1322800771bee4a91f3b4bd4e49abc7d35e65166821086e5afd1e6c0d9be44"}, + {file = "librt-0.7.8-cp314-cp314-win_arm64.whl", hash = "sha256:5363427bc6a8c3b1719f8f3845ea53553d301382928a86e8fab7984426949bce"}, + {file = "librt-0.7.8-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:ca916919793a77e4a98d4a1701e345d337ce53be4a16620f063191f7322ac80f"}, + {file = "librt-0.7.8-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:54feb7b4f2f6706bb82325e836a01be805770443e2400f706e824e91f6441dde"}, + {file = "librt-0.7.8-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:39a4c76fee41007070f872b648cc2f711f9abf9a13d0c7162478043377b52c8e"}, + {file = "librt-0.7.8-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ac9c8a458245c7de80bc1b9765b177055efff5803f08e548dd4bb9ab9a8d789b"}, + {file = "librt-0.7.8-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:95b67aa7eff150f075fda09d11f6bfb26edffd300f6ab1666759547581e8f666"}, + {file = "librt-0.7.8-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:535929b6eff670c593c34ff435d5440c3096f20fa72d63444608a5aef64dd581"}, + {file = "librt-0.7.8-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:63937bd0f4d1cb56653dc7ae900d6c52c41f0015e25aaf9902481ee79943b33a"}, + {file = "librt-0.7.8-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:cf243da9e42d914036fd362ac3fa77d80a41cadcd11ad789b1b5eec4daaf67ca"}, + {file = "librt-0.7.8-cp314-cp314t-win32.whl", hash = "sha256:171ca3a0a06c643bd0a2f62a8944e1902c94aa8e5da4db1ea9a8daf872685365"}, + {file = "librt-0.7.8-cp314-cp314t-win_amd64.whl", hash = "sha256:445b7304145e24c60288a2f172b5ce2ca35c0f81605f5299f3fa567e189d2e32"}, + {file = "librt-0.7.8-cp314-cp314t-win_arm64.whl", hash = "sha256:8766ece9de08527deabcd7cb1b4f1a967a385d26e33e536d6d8913db6ef74f06"}, + {file = "librt-0.7.8-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c7e8f88f79308d86d8f39c491773cbb533d6cb7fa6476f35d711076ee04fceb6"}, + {file = "librt-0.7.8-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:389bd25a0db916e1d6bcb014f11aa9676cedaa485e9ec3752dfe19f196fd377b"}, + {file = "librt-0.7.8-cp39-cp39-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:73fd300f501a052f2ba52ede721232212f3b06503fa12665408ecfc9d8fd149c"}, + {file = "librt-0.7.8-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6d772edc6a5f7835635c7562f6688e031f0b97e31d538412a852c49c9a6c92d5"}, + {file = "librt-0.7.8-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bfde8a130bd0f239e45503ab39fab239ace094d63ee1d6b67c25a63d741c0f71"}, + {file = "librt-0.7.8-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:fdec6e2368ae4f796fc72fad7fd4bd1753715187e6d870932b0904609e7c878e"}, + {file = "librt-0.7.8-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:00105e7d541a8f2ee5be52caacea98a005e0478cfe78c8080fbb7b5d2b340c63"}, + {file = "librt-0.7.8-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c6f8947d3dfd7f91066c5b4385812c18be26c9d5a99ca56667547f2c39149d94"}, + {file = "librt-0.7.8-cp39-cp39-win32.whl", hash = "sha256:41d7bb1e07916aeb12ae4a44e3025db3691c4149ab788d0315781b4d29b86afb"}, + {file = "librt-0.7.8-cp39-cp39-win_amd64.whl", hash = "sha256:e90a8e237753c83b8e484d478d9a996dc5e39fd5bd4c6ce32563bc8123f132be"}, + {file = "librt-0.7.8.tar.gz", hash = "sha256:1a4ede613941d9c3470b0368be851df6bb78ab218635512d0370b27a277a0862"}, +] + [[package]] name = "markupsafe" version = "2.1.3" @@ -1003,53 +1088,55 @@ files = [ [[package]] name = "mypy" -version = "1.14.1" +version = "1.19.1" description = "Optional static typing for Python" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "mypy-1.14.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:52686e37cf13d559f668aa398dd7ddf1f92c5d613e4f8cb262be2fb4fedb0fcb"}, - {file = "mypy-1.14.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1fb545ca340537d4b45d3eecdb3def05e913299ca72c290326be19b3804b39c0"}, - {file = "mypy-1.14.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:90716d8b2d1f4cd503309788e51366f07c56635a3309b0f6a32547eaaa36a64d"}, - {file = "mypy-1.14.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2ae753f5c9fef278bcf12e1a564351764f2a6da579d4a81347e1d5a15819997b"}, - {file = "mypy-1.14.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e0fe0f5feaafcb04505bcf439e991c6d8f1bf8b15f12b05feeed96e9e7bf1427"}, - {file = "mypy-1.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:7d54bd85b925e501c555a3227f3ec0cfc54ee8b6930bd6141ec872d1c572f81f"}, - {file = "mypy-1.14.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f995e511de847791c3b11ed90084a7a0aafdc074ab88c5a9711622fe4751138c"}, - {file = "mypy-1.14.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d64169ec3b8461311f8ce2fd2eb5d33e2d0f2c7b49116259c51d0d96edee48d1"}, - {file = "mypy-1.14.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ba24549de7b89b6381b91fbc068d798192b1b5201987070319889e93038967a8"}, - {file = "mypy-1.14.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:183cf0a45457d28ff9d758730cd0210419ac27d4d3f285beda038c9083363b1f"}, - {file = "mypy-1.14.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f2a0ecc86378f45347f586e4163d1769dd81c5a223d577fe351f26b179e148b1"}, - {file = "mypy-1.14.1-cp311-cp311-win_amd64.whl", hash = "sha256:ad3301ebebec9e8ee7135d8e3109ca76c23752bac1e717bc84cd3836b4bf3eae"}, - {file = "mypy-1.14.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:30ff5ef8519bbc2e18b3b54521ec319513a26f1bba19a7582e7b1f58a6e69f14"}, - {file = "mypy-1.14.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cb9f255c18052343c70234907e2e532bc7e55a62565d64536dbc7706a20b78b9"}, - {file = "mypy-1.14.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8b4e3413e0bddea671012b063e27591b953d653209e7a4fa5e48759cda77ca11"}, - {file = "mypy-1.14.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:553c293b1fbdebb6c3c4030589dab9fafb6dfa768995a453d8a5d3b23784af2e"}, - {file = "mypy-1.14.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fad79bfe3b65fe6a1efaed97b445c3d37f7be9fdc348bdb2d7cac75579607c89"}, - {file = "mypy-1.14.1-cp312-cp312-win_amd64.whl", hash = "sha256:8fa2220e54d2946e94ab6dbb3ba0a992795bd68b16dc852db33028df2b00191b"}, - {file = "mypy-1.14.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:92c3ed5afb06c3a8e188cb5da4984cab9ec9a77ba956ee419c68a388b4595255"}, - {file = "mypy-1.14.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:dbec574648b3e25f43d23577309b16534431db4ddc09fda50841f1e34e64ed34"}, - {file = "mypy-1.14.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8c6d94b16d62eb3e947281aa7347d78236688e21081f11de976376cf010eb31a"}, - {file = "mypy-1.14.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d4b19b03fdf54f3c5b2fa474c56b4c13c9dbfb9a2db4370ede7ec11a2c5927d9"}, - {file = "mypy-1.14.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0c911fde686394753fff899c409fd4e16e9b294c24bfd5e1ea4675deae1ac6fd"}, - {file = "mypy-1.14.1-cp313-cp313-win_amd64.whl", hash = "sha256:8b21525cb51671219f5307be85f7e646a153e5acc656e5cebf64bfa076c50107"}, - {file = "mypy-1.14.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7084fb8f1128c76cd9cf68fe5971b37072598e7c31b2f9f95586b65c741a9d31"}, - {file = "mypy-1.14.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8f845a00b4f420f693f870eaee5f3e2692fa84cc8514496114649cfa8fd5e2c6"}, - {file = "mypy-1.14.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:44bf464499f0e3a2d14d58b54674dee25c031703b2ffc35064bd0df2e0fac319"}, - {file = "mypy-1.14.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c99f27732c0b7dc847adb21c9d47ce57eb48fa33a17bc6d7d5c5e9f9e7ae5bac"}, - {file = "mypy-1.14.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:bce23c7377b43602baa0bd22ea3265c49b9ff0b76eb315d6c34721af4cdf1d9b"}, - {file = "mypy-1.14.1-cp38-cp38-win_amd64.whl", hash = "sha256:8edc07eeade7ebc771ff9cf6b211b9a7d93687ff892150cb5692e4f4272b0837"}, - {file = "mypy-1.14.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3888a1816d69f7ab92092f785a462944b3ca16d7c470d564165fe703b0970c35"}, - {file = "mypy-1.14.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:46c756a444117c43ee984bd055db99e498bc613a70bbbc120272bd13ca579fbc"}, - {file = "mypy-1.14.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:27fc248022907e72abfd8e22ab1f10e903915ff69961174784a3900a8cba9ad9"}, - {file = "mypy-1.14.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:499d6a72fb7e5de92218db961f1a66d5f11783f9ae549d214617edab5d4dbdbb"}, - {file = "mypy-1.14.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:57961db9795eb566dc1d1b4e9139ebc4c6b0cb6e7254ecde69d1552bf7613f60"}, - {file = "mypy-1.14.1-cp39-cp39-win_amd64.whl", hash = "sha256:07ba89fdcc9451f2ebb02853deb6aaaa3d2239a236669a63ab3801bbf923ef5c"}, - {file = "mypy-1.14.1-py3-none-any.whl", hash = "sha256:b66a60cc4073aeb8ae00057f9c1f64d49e90f918fbcef9a977eb121da8b8f1d1"}, - {file = "mypy-1.14.1.tar.gz", hash = "sha256:7ec88144fe9b510e8475ec2f5f251992690fcf89ccb4500b214b4226abcd32d6"}, + {file = "mypy-1.19.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5f05aa3d375b385734388e844bc01733bd33c644ab48e9684faa54e5389775ec"}, + {file = "mypy-1.19.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:022ea7279374af1a5d78dfcab853fe6a536eebfda4b59deab53cd21f6cd9f00b"}, + {file = "mypy-1.19.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee4c11e460685c3e0c64a4c5de82ae143622410950d6be863303a1c4ba0e36d6"}, + {file = "mypy-1.19.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:de759aafbae8763283b2ee5869c7255391fbc4de3ff171f8f030b5ec48381b74"}, + {file = "mypy-1.19.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ab43590f9cd5108f41aacf9fca31841142c786827a74ab7cc8a2eacb634e09a1"}, + {file = "mypy-1.19.1-cp310-cp310-win_amd64.whl", hash = "sha256:2899753e2f61e571b3971747e302d5f420c3fd09650e1951e99f823bc3089dac"}, + {file = "mypy-1.19.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d8dfc6ab58ca7dda47d9237349157500468e404b17213d44fc1cb77bce532288"}, + {file = "mypy-1.19.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e3f276d8493c3c97930e354b2595a44a21348b320d859fb4a2b9f66da9ed27ab"}, + {file = "mypy-1.19.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2abb24cf3f17864770d18d673c85235ba52456b36a06b6afc1e07c1fdcd3d0e6"}, + {file = "mypy-1.19.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a009ffa5a621762d0c926a078c2d639104becab69e79538a494bcccb62cc0331"}, + {file = "mypy-1.19.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f7cee03c9a2e2ee26ec07479f38ea9c884e301d42c6d43a19d20fb014e3ba925"}, + {file = "mypy-1.19.1-cp311-cp311-win_amd64.whl", hash = "sha256:4b84a7a18f41e167f7995200a1d07a4a6810e89d29859df936f1c3923d263042"}, + {file = "mypy-1.19.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a8174a03289288c1f6c46d55cef02379b478bfbc8e358e02047487cad44c6ca1"}, + {file = "mypy-1.19.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ffcebe56eb09ff0c0885e750036a095e23793ba6c2e894e7e63f6d89ad51f22e"}, + {file = "mypy-1.19.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b64d987153888790bcdb03a6473d321820597ab8dd9243b27a92153c4fa50fd2"}, + {file = "mypy-1.19.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c35d298c2c4bba75feb2195655dfea8124d855dfd7343bf8b8c055421eaf0cf8"}, + {file = "mypy-1.19.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:34c81968774648ab5ac09c29a375fdede03ba253f8f8287847bd480782f73a6a"}, + {file = "mypy-1.19.1-cp312-cp312-win_amd64.whl", hash = "sha256:b10e7c2cd7870ba4ad9b2d8a6102eb5ffc1f16ca35e3de6bfa390c1113029d13"}, + {file = "mypy-1.19.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e3157c7594ff2ef1634ee058aafc56a82db665c9438fd41b390f3bde1ab12250"}, + {file = "mypy-1.19.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bdb12f69bcc02700c2b47e070238f42cb87f18c0bc1fc4cdb4fb2bc5fd7a3b8b"}, + {file = "mypy-1.19.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f859fb09d9583a985be9a493d5cfc5515b56b08f7447759a0c5deaf68d80506e"}, + {file = "mypy-1.19.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c9a6538e0415310aad77cb94004ca6482330fece18036b5f360b62c45814c4ef"}, + {file = "mypy-1.19.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:da4869fc5e7f62a88f3fe0b5c919d1d9f7ea3cef92d3689de2823fd27e40aa75"}, + {file = "mypy-1.19.1-cp313-cp313-win_amd64.whl", hash = "sha256:016f2246209095e8eda7538944daa1d60e1e8134d98983b9fc1e92c1fc0cb8dd"}, + {file = "mypy-1.19.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:06e6170bd5836770e8104c8fdd58e5e725cfeb309f0a6c681a811f557e97eac1"}, + {file = "mypy-1.19.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:804bd67b8054a85447c8954215a906d6eff9cabeabe493fb6334b24f4bfff718"}, + {file = "mypy-1.19.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:21761006a7f497cb0d4de3d8ef4ca70532256688b0523eee02baf9eec895e27b"}, + {file = "mypy-1.19.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:28902ee51f12e0f19e1e16fbe2f8f06b6637f482c459dd393efddd0ec7f82045"}, + {file = "mypy-1.19.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:481daf36a4c443332e2ae9c137dfee878fcea781a2e3f895d54bd3002a900957"}, + {file = "mypy-1.19.1-cp314-cp314-win_amd64.whl", hash = "sha256:8bb5c6f6d043655e055be9b542aa5f3bdd30e4f3589163e85f93f3640060509f"}, + {file = "mypy-1.19.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7bcfc336a03a1aaa26dfce9fff3e287a3ba99872a157561cbfcebe67c13308e3"}, + {file = "mypy-1.19.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b7951a701c07ea584c4fe327834b92a30825514c868b1f69c30445093fdd9d5a"}, + {file = "mypy-1.19.1-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b13cfdd6c87fc3efb69ea4ec18ef79c74c3f98b4e5498ca9b85ab3b2c2329a67"}, + {file = "mypy-1.19.1-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4f28f99c824ecebcdaa2e55d82953e38ff60ee5ec938476796636b86afa3956e"}, + {file = "mypy-1.19.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c608937067d2fc5a4dd1a5ce92fd9e1398691b8c5d012d66e1ddd430e9244376"}, + {file = "mypy-1.19.1-cp39-cp39-win_amd64.whl", hash = "sha256:409088884802d511ee52ca067707b90c883426bd95514e8cfda8281dc2effe24"}, + {file = "mypy-1.19.1-py3-none-any.whl", hash = "sha256:f1235f5ea01b7db5468d53ece6aaddf1ad0b88d9e7462b86ef96fe04995d7247"}, + {file = "mypy-1.19.1.tar.gz", hash = "sha256:19d88bb05303fe63f71dd2c6270daca27cb9401c4ca8255fe50d1d920e0eb9ba"}, ] [package.dependencies] +librt = {version = ">=0.6.2", markers = "platform_python_implementation != \"PyPy\""} mypy_extensions = ">=1.0.0" +pathspec = ">=0.9.0" tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} typing_extensions = ">=4.6.0" @@ -1897,4 +1984,4 @@ propcache = ">=0.2.0" [metadata] lock-version = "2.0" python-versions = ">=3.10,<4.0" -content-hash = "08d95be3b544b4aaef5e5872def21216b14d4fde92f889daff79dc07cf78359d" +content-hash = "a147643bad28d6da9d7cd472dd5247d3e928bb6f6a87ed6aa1604265d9c8bbff" diff --git a/flixpy/pyproject.toml b/flixpy/pyproject.toml index 1fe9e5d..8b25f38 100644 --- a/flixpy/pyproject.toml +++ b/flixpy/pyproject.toml @@ -14,7 +14,7 @@ python = ">=3.10,<4.0" aiohttp = "^3.8.5" appdirs = "^1.4.4" python-dateutil = "^2.8.2" -asyncclick = "^8.1.3.4" +asyncclick = "<8.2" anyio = "^3.7.1" grpcio = "^1.57.0" protobuf = "^4.24.1"