From cdb7ea0ed8675daace02ec889058255100e6a9d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?c=C4=83t=C4=83lin?= Date: Fri, 6 Dec 2024 13:58:19 +0100 Subject: [PATCH] wip --- .gitignore | 1 + Makefile | 6 + README.md | 1 + pyproject.toml | 24 +- src/{markovbot_gui => huesoporro}/__init__.py | 0 .../libs/LICENSE | 0 .../libs/README.md | 0 .../libs/__init__.py | 0 src/{markovbot_gui => huesoporro}/libs/db.py | 7 +- .../libs/markov_chain_bot.py | 31 +- .../libs/settings.py | 0 .../libs/timer.py | 0 .../libs/tokenizer.py | 0 src/huesoporro/main.py | 254 ++++++ src/huesoporro/static/index.html | 31 + src/huesoporro/static/missing.min.css | 1 + src/huesoporro/static/mvp.css | 594 +++++++++++++ src/huesoporro/static/overlay.html | 172 ++++ src/markovbot_gui/bot_runner.py | 154 ---- src/markovbot_gui/config_window.py | 161 ---- src/markovbot_gui/log_handler.py | 10 - src/markovbot_gui/main.py | 75 -- uv.lock | 816 ++++++++++++++---- 23 files changed, 1735 insertions(+), 603 deletions(-) rename src/{markovbot_gui => huesoporro}/__init__.py (100%) rename src/{markovbot_gui => huesoporro}/libs/LICENSE (100%) rename src/{markovbot_gui => huesoporro}/libs/README.md (100%) rename src/{markovbot_gui => huesoporro}/libs/__init__.py (100%) rename src/{markovbot_gui => huesoporro}/libs/db.py (99%) rename src/{markovbot_gui => huesoporro}/libs/markov_chain_bot.py (95%) rename src/{markovbot_gui => huesoporro}/libs/settings.py (100%) rename src/{markovbot_gui => huesoporro}/libs/timer.py (100%) rename src/{markovbot_gui => huesoporro}/libs/tokenizer.py (100%) create mode 100644 src/huesoporro/main.py create mode 100644 src/huesoporro/static/index.html create mode 100644 src/huesoporro/static/missing.min.css create mode 100644 src/huesoporro/static/mvp.css create mode 100644 src/huesoporro/static/overlay.html delete mode 100644 src/markovbot_gui/bot_runner.py delete mode 100644 src/markovbot_gui/config_window.py delete mode 100644 src/markovbot_gui/log_handler.py delete mode 100644 src/markovbot_gui/main.py diff --git a/.gitignore b/.gitignore index cb81a46..ab9955b 100644 --- a/.gitignore +++ b/.gitignore @@ -110,3 +110,4 @@ reportlog.json .ruff_cache/ .pdm.toml requirements.txt +src/huesoporro/tts_files/ diff --git a/Makefile b/Makefile index 7b1af53..daabaf9 100644 --- a/Makefile +++ b/Makefile @@ -7,3 +7,9 @@ tests: uv run pytest --cov=halig -vv tests --report-log reportlog.json uv run coverage html uv run coverage xml + +compile: + uv run pyinstaller markovbot.spec + +clean-compile: + uv run pyinstaller markovbot.spec --clean diff --git a/README.md b/README.md index e69de29..22880de 100644 --- a/README.md +++ b/README.md @@ -0,0 +1 @@ +# huesoporro diff --git a/pyproject.toml b/pyproject.toml index 207f2de..ff92116 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,23 +1,24 @@ [project] -name = "markovbot-gui" +name = "huesoporro" version = "0.1.2" -description = "Markov Chain Bot GUI" +description = "Misc Twitch bots" readme = "README.md" authors = [ - { name = "tomaarsen" }, { name = "185504a9", email = "catalin@roboces.dev" } ] requires-python = ">=3.11" dependencies = [ - "kivy[base]>=2.3.0", "nltk>=3.9.1", - "pillow>=10.4.0", "platformdirs>=4.3.6", "pydantic>=2.9.2", "pydantic-settings>=2.6.0", "pyinstaller>=6.11.0", "twitchwebsocket>=1.2.1", "loguru>=0.7.2", + "ffmpeg>=1.4", + "ffmpeg-python>=0.2.0", + "gtts>=2.5.4", + "litestar[standard]>=2.13.0", ] [tool.uv] @@ -29,22 +30,13 @@ dev-dependencies = [ [[tool.mypy.overrides]] module = [ - "kivy", - "kivy.uix.widget", - "kivy.uix.popup", - "kivy.uix.button", - "kivy.uix.boxlayout", - "kivy.uix.textinput", - "kivy.uix.label", - "kivy.metrics", - "kivy.app", - "kivy.clock", "nltk", "nltk.tokenize", "nltk.tokenize.treebank", "nltk.tokenize.destructive", "TwitchWebsocket", - "tokenizer" + "tokenizer", + "gtts" ] ignore_missing_imports = true diff --git a/src/markovbot_gui/__init__.py b/src/huesoporro/__init__.py similarity index 100% rename from src/markovbot_gui/__init__.py rename to src/huesoporro/__init__.py diff --git a/src/markovbot_gui/libs/LICENSE b/src/huesoporro/libs/LICENSE similarity index 100% rename from src/markovbot_gui/libs/LICENSE rename to src/huesoporro/libs/LICENSE diff --git a/src/markovbot_gui/libs/README.md b/src/huesoporro/libs/README.md similarity index 100% rename from src/markovbot_gui/libs/README.md rename to src/huesoporro/libs/README.md diff --git a/src/markovbot_gui/libs/__init__.py b/src/huesoporro/libs/__init__.py similarity index 100% rename from src/markovbot_gui/libs/__init__.py rename to src/huesoporro/libs/__init__.py diff --git a/src/markovbot_gui/libs/db.py b/src/huesoporro/libs/db.py similarity index 99% rename from src/markovbot_gui/libs/db.py rename to src/huesoporro/libs/db.py index f547a81..1ee5484 100644 --- a/src/markovbot_gui/libs/db.py +++ b/src/huesoporro/libs/db.py @@ -191,10 +191,11 @@ class Database: fetch=True, ): logger.info("Creating backup before updating Database...") + # Connect to both the new and backup, backup, and close both def progress(status, remaining, total): - logging.debug(f"Copied {total-remaining} of {total} pages...") + logging.debug(f"Copied {total - remaining} of {total} pages...") conn = sqlite3.connect(f"MarkovChain_{channel.replace('#', '').lower()}.db") back_conn = sqlite3.connect( @@ -265,7 +266,7 @@ class Database: ); """) self.add_execute_queue( - f'INSERT INTO MarkovGrammar{first_char}{second_char} SELECT * FROM MarkovGrammar{first_char} WHERE word2 LIKE "{second_char}%";', # noqa: S608 + f'INSERT INTO MarkovGrammar{first_char}{second_char} SELECT * FROM MarkovGrammar{first_char} WHERE word2 LIKE "{second_char}%";', ) self.add_execute_queue( f'DELETE FROM MarkovGrammar{first_char} WHERE word2 LIKE "{second_char}%";', # noqa: S608 @@ -356,7 +357,7 @@ class Database: from nltk import ngrams - from src.markovbot_gui.libs.tokenizer import tokenize + from src.huesoporro.libs.tokenizer import tokenize channel = channel.replace("#", "").lower() copyfile( diff --git a/src/markovbot_gui/libs/markov_chain_bot.py b/src/huesoporro/libs/markov_chain_bot.py similarity index 95% rename from src/markovbot_gui/libs/markov_chain_bot.py rename to src/huesoporro/libs/markov_chain_bot.py index 2e661b5..5801cc5 100644 --- a/src/markovbot_gui/libs/markov_chain_bot.py +++ b/src/huesoporro/libs/markov_chain_bot.py @@ -6,10 +6,10 @@ from loguru import logger from nltk.tokenize import sent_tokenize from TwitchWebsocket import Message, TwitchWebsocket -from src.markovbot_gui.libs.db import Database -from src.markovbot_gui.libs.settings import Settings -from src.markovbot_gui.libs.timer import LoopingTimer -from src.markovbot_gui.libs.tokenizer import detokenize, tokenize +from src.huesoporro.libs.db import Database +from src.huesoporro.libs.settings import Settings +from src.huesoporro.libs.timer import LoopingTimer +from src.huesoporro.libs.tokenizer import detokenize, tokenize class Commands(StrEnum): @@ -249,6 +249,29 @@ class MarkovChain: def message_handler(self, message: Message): # noqa: C901, PLR0911, PLR0912 try: + breakpoint() + + tts_message = { + "badge-info": "subscriber/4", + "badges": "vip/1,subscriber/3,sub-gifter/5", + "color": "#F79AC6", + "custom-reward-id": "8c454446-73b0-480f-946e-d6b5f5c5e331", + "display-name": "robosap1ens__", + "emotes": "", + "first-msg": "0", + "flags": "", + "id": "6cbd37eb-49ae-41f5-b073-345275c91a07", + "mod": "0", + "returning-chatter": "0", + "room-id": "600944302", + "subscriber": "1", + "tmi-sent-ts": "1733252657689", + "turbo": "0", + "user-id": "713968248", + "user-type": "", + "vip": "1", + } + if not message.user or message.user in self.s.denied_users: logger.debug(f"User {message.user} can't send messages") return diff --git a/src/markovbot_gui/libs/settings.py b/src/huesoporro/libs/settings.py similarity index 100% rename from src/markovbot_gui/libs/settings.py rename to src/huesoporro/libs/settings.py diff --git a/src/markovbot_gui/libs/timer.py b/src/huesoporro/libs/timer.py similarity index 100% rename from src/markovbot_gui/libs/timer.py rename to src/huesoporro/libs/timer.py diff --git a/src/markovbot_gui/libs/tokenizer.py b/src/huesoporro/libs/tokenizer.py similarity index 100% rename from src/markovbot_gui/libs/tokenizer.py rename to src/huesoporro/libs/tokenizer.py diff --git a/src/huesoporro/main.py b/src/huesoporro/main.py new file mode 100644 index 0000000..31ed551 --- /dev/null +++ b/src/huesoporro/main.py @@ -0,0 +1,254 @@ +import asyncio +import os +from collections import deque +from functools import lru_cache +from hashlib import sha512 +from pathlib import Path + +import uvicorn +from gtts import gTTS +from litestar import Litestar, MediaType, WebSocket, get +from litestar.connection import ASGIConnection +from litestar.di import Provide +from litestar.exceptions import HTTPException +from litestar.handlers import BaseRouteHandler, WebsocketListener +from litestar.static_files import StaticFilesConfig +from litestar.types import Scope +from loguru import logger +from pydantic import Field, SecretStr +from pydantic_settings import BaseSettings + + +class Settings(BaseSettings): + api_key: SecretStr + port: int = 8000 + host: str = "0.0.0.0" + static_files_path: Path = Field( + default_factory=lambda: Path(__file__).parent / "static" + ) + tts_cache_path: Path = Field( + default_factory=lambda: Path(__file__).parent / "tts_files" + ) + db_filepath: Path = Field( + default_factory=lambda: Path(__file__).parent / "huesoporro.db" + ) + + @staticmethod + @lru_cache(maxsize=1) + def get(): + return Settings() + + +class TTSManager: + TEXT_MAX_LENGTH: int = 400 + + def __init__(self, base_dir="tts_files", max_queue_size=10): + # Create directory for TTS files + self.base_dir = base_dir + os.makedirs(base_dir, exist_ok=True) + + # TTS Queue + self.queue = deque(maxlen=max_queue_size) + + # Connected WebSocket clients + self._clients: list[WebSocket] = [] + + # Currently playing audio + self.current_audio = None + + # Lock to prevent race conditions + self._lock = asyncio.Lock() + + def generate_tts(self, text, language="pt", tld="com.br"): + # Generate unique filename + text = text[0 : self.TEXT_MAX_LENGTH] + filename = ( + Path(__file__).parent + / "tts_files" + / f"{sha512(text.lower().encode()).hexdigest()}.mp3" + ) + if filename.exists(): + return { + "filename": filename.name, + "text": text, + "filepath": os.path.join(self.base_dir, filename), + "language": language, + "tld": tld, + } + logger.info(f"Generating TTS for '{text}'") + # Generate TTS + tts = gTTS(text=text, lang=language, tld=tld) + tts.save(str(filename)) + + # Create audio info + audio_info = { + "filename": filename.name, + "text": text, + "filepath": filename, + "language": language, + "tld": tld, + } + + return audio_info + + @property + def clients(self): + return self._clients + + def add_client(self, socket: WebSocket): + self._clients.append(socket) + + def remove_client(self, socket: WebSocket): + self._clients.remove(socket) + + async def add_to_queue(self, text, language="pt", tld="com.br"): + """Add TTS request to queue and start processing if not already running""" + async with self._lock: + # Generate TTS file + audio_info = self.generate_tts(text, language, tld) + + # Add to queue + self.queue.append(audio_info) + + # If this is the only item, start processing + if len(self.queue) == 1: + asyncio.create_task(self.process_queue()) + + return audio_info + + async def process_queue(self): + """Process queue and stream audio to connected clients""" + while True: + async with self._lock: + # Check if queue is empty + if not self.queue: + return + + # Get next audio file + audio_info = self.queue[0] + + try: + # Read the entire audio file + with open(audio_info["filepath"], "rb") as audio_file: + # Log file details + # file_size = os.path.getsize(audio_info["filepath"]) + file_size = Path(audio_info["filepath"]).stat().st_size + logger.info( + f"Streaming file: {audio_info['filename']}, Size: {file_size} bytes" + ) + + # Stream audio to all connected clients + for client in self._clients: + try: + # Reset file pointer to beginning + audio_file.seek(0) + + # Send file size first (as a header) + await client.send_text(f"FILE_HEADER:{file_size}") + + # Stream file in chunks + chunk = audio_file.read(128) # Larger chunk size + chunk_count = 0 + while chunk: + logger.info(f"Streamed {chunk_count} chunks") + chunk_count += 1 + await client.send_bytes(chunk) + chunk = audio_file.read(128) + + # Send file footer + await client.send_text("FILE_FOOTER") + + except Exception: # noqa: BLE001 + logger.error( + f"Error streaming to client {client.client}. Removing it." + ) + if client in self._clients: + self.remove_client(client) + + except Exception as e: # noqa: BLE001 + logger.error(f"Error processing audio file: {e}") + + # Remove the processed item from the queue + async with self._lock: + if self.queue and self.queue[0] == audio_info: + self.queue.popleft() + + +def authenticate(connection: ASGIConnection, route_handler: BaseRouteHandler) -> None: + """If the client didn't send the API key, deny access""" + api_key = Settings.get().api_key.get_secret_value() + + client_api_key = connection.headers.get("X-API-KEY") or connection.query_params.get( + "api_key" + ) + + if not client_api_key or client_api_key != api_key: + raise HTTPException(status_code=401, detail="Unauthorized") + + +class WebsocketHandler(WebsocketListener): + path = "/ws" + guards = [authenticate] + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.tts_manager = TTSManager() + + async def on_accept(self, socket: WebSocket) -> None: + # Add client to the list of connected clients + self.tts_manager.add_client(socket) + logger.info( + f"Connection accepted from {socket.client.host}:{socket.client.port}" # type: ignore[union-attr] + ) + + async def on_disconnect(self, socket: WebSocket) -> None: + # Remove client from the list + if socket in self.tts_manager.clients: + self.tts_manager.remove_client(socket) + logger.info(f"Connection closed by {socket.client.host}:{socket.client.port}") # type: ignore[union-attr] + + async def on_receive(self, data: str) -> None: + # When text is received, add it to TTS queue + await self.tts_manager.add_to_queue(data) + + +@get( + "/overlay", + media_type=MediaType.HTML, + dependencies={"s": Provide(Settings.get)}, + guards=[authenticate], +) +def get_overlay(s: Settings) -> str: + with (s.static_files_path / "overlay.html").open() as f: + return f.read() + + +async def after_exception_handler(exc: Exception, scope: Scope) -> None: + """Hook function that will be invoked after each exception.""" + state = scope["app"].state + if not hasattr(state, "error_count"): + state.error_count = 1 + else: + state.error_count += 1 + + logger.info( + f"an exception of type {type(exc).__name__} has occurred for requested path {scope['path']} and the application error count is {state.error_count}.", + ) + + +def create_app(): + return Litestar( + route_handlers=[get_overlay, WebsocketHandler], + static_files_config=( + StaticFilesConfig( + path="/tts_files", directories=[Settings.get().tts_cache_path] + ), + ), + after_exception=[after_exception_handler], + ) + + +if __name__ == "__main__": + settings = Settings.get() + app = create_app() + uvicorn.run(app, host=settings.host, port=settings.port) diff --git a/src/huesoporro/static/index.html b/src/huesoporro/static/index.html new file mode 100644 index 0000000..d32d19b --- /dev/null +++ b/src/huesoporro/static/index.html @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + Huesoporro + + + +
+ +

Huesoporro🦴🍀

+
+
+
+ + + diff --git a/src/huesoporro/static/missing.min.css b/src/huesoporro/static/missing.min.css new file mode 100644 index 0000000..3060761 --- /dev/null +++ b/src/huesoporro/static/missing.min.css @@ -0,0 +1 @@ +*,:before,:after{box-sizing:border-box;background-repeat:no-repeat}:before,:after{-webkit-text-decoration:inherit;text-decoration:inherit;vertical-align:inherit}:root{cursor:default;overflow-wrap:break-word;-webkit-tap-highlight-color:transparent;-webkit-text-size-adjust:none;-moz-text-size-adjust:none;text-size-adjust:none}abbr[title]{text-decoration:underline dotted}strong,b{font-weight:bolder}small{font-size:80%}audio,canvas,iframe,img,svg,video{vertical-align:middle}svg:not([fill]){fill:currentColor}table{border-collapse:collapse;text-indent:0;border-color:currentColor}button,input,select{margin:0}fieldset{border:1px solid #a0a0a0}progress{vertical-align:baseline}textarea{margin:0}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-inner-spin-button{block-size:auto}::-webkit-outer-spin-button{block-size:auto}::-webkit-input-placeholder{color:inherit;opacity:.54}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}[hidden]{display:none!important}:focus-visible{outline:.2em solid var(--accent);z-index:32}iframe:focus-visible,html:focus-visible,body:focus-visible{outline:none}:target{outline:.2em solid var(--fg);z-index:2}details>summary:first-of-type{display:list-item}[aria-busy=true]{cursor:progress}[aria-disabled=true],[disabled]{cursor:not-allowed}datalist{display:none!important}:root{--gray-0:#f8fafb;--gray-1:#f2f4f6;--gray-2:#ebedef;--gray-3:#e0e4e5;--gray-4:#d1d6d8;--gray-5:#b1b6b9;--gray-6:#979b9d;--gray-7:#7e8282;--gray-8:#666968;--gray-9:#50514f;--gray-10:#3a3a37;--gray-11:#252521;--gray-12:#121210;--red-0:#fff5f5;--red-1:#ffe3e3;--red-2:#ffc9c9;--red-3:#ffa8a8;--red-4:#ff8787;--red-5:#ff6b6b;--red-6:#fa5252;--red-7:#f03e3e;--red-8:#e03131;--red-9:#c92a2a;--red-10:#b02525;--red-11:#962020;--red-12:#7d1a1a;--pink-0:#fff0f6;--pink-1:#ffdeeb;--pink-2:#fcc2d7;--pink-3:#faa2c1;--pink-4:#f783ac;--pink-5:#f06595;--pink-6:#e64980;--pink-7:#d6336c;--pink-8:#c2255c;--pink-9:#a61e4d;--pink-10:#8c1941;--pink-11:#731536;--pink-12:#59102a;--purple-0:#f8f0fc;--purple-1:#f3d9fa;--purple-2:#eebefa;--purple-3:#e599f7;--purple-4:#da77f2;--purple-5:#cc5de8;--purple-6:#be4bdb;--purple-7:#ae3ec9;--purple-8:#9c36b5;--purple-9:#862e9c;--purple-10:#702682;--purple-11:#5a1e69;--purple-12:#44174f;--violet-0:#f3f0ff;--violet-1:#e5dbff;--violet-2:#d0bfff;--violet-3:#b197fc;--violet-4:#9775fa;--violet-5:#845ef7;--violet-6:#7950f2;--violet-7:#7048e8;--violet-8:#6741d9;--violet-9:#5f3dc4;--violet-10:#5235ab;--violet-11:#462d91;--violet-12:#3a2578;--indigo-0:#edf2ff;--indigo-1:#dbe4ff;--indigo-2:#bac8ff;--indigo-3:#91a7ff;--indigo-4:#748ffc;--indigo-5:#5c7cfa;--indigo-6:#4c6ef5;--indigo-7:#4263eb;--indigo-8:#3b5bdb;--indigo-9:#364fc7;--indigo-10:#2f44ad;--indigo-11:#283a94;--indigo-12:#21307a;--blue-0:#e7f5ff;--blue-1:#d0ebff;--blue-2:#a5d8ff;--blue-3:#74c0fc;--blue-4:#4dabf7;--blue-5:#339af0;--blue-6:#228be6;--blue-7:#1c7ed6;--blue-8:#1971c2;--blue-9:#1864ab;--blue-10:#145591;--blue-11:#114678;--blue-12:#0d375e;--cyan-0:#e3fafc;--cyan-1:#c5f6fa;--cyan-2:#99e9f2;--cyan-3:#66d9e8;--cyan-4:#3bc9db;--cyan-5:#22b8cf;--cyan-6:#15aabf;--cyan-7:#1098ad;--cyan-8:#0c8599;--cyan-9:#0b7285;--cyan-10:#095c6b;--cyan-11:#074652;--cyan-12:#053038;--teal-0:#e6fcf5;--teal-1:#c3fae8;--teal-2:#96f2d7;--teal-3:#63e6be;--teal-4:#38d9a9;--teal-5:#20c997;--teal-6:#12b886;--teal-7:#0ca678;--teal-8:#099268;--teal-9:#087f5b;--teal-10:#066649;--teal-11:#054d37;--teal-12:#033325;--green-0:#ebfbee;--green-1:#d3f9d8;--green-2:#b2f2bb;--green-3:#8ce99a;--green-4:#69db7c;--green-5:#51cf66;--green-6:#40c057;--green-7:#37b24d;--green-8:#2f9e44;--green-9:#2b8a3e;--green-10:#237032;--green-11:#1b5727;--green-12:#133d1b;--lime-0:#f4fce3;--lime-1:#e9fac8;--lime-2:#d8f5a2;--lime-3:#c0eb75;--lime-4:#a9e34b;--lime-5:#94d82d;--lime-6:#82c91e;--lime-7:#74b816;--lime-8:#66a80f;--lime-9:#5c940d;--lime-10:#4c7a0b;--lime-11:#3c6109;--lime-12:#2c4706;--yellow-0:#fff9db;--yellow-1:#fff3bf;--yellow-2:#ffec99;--yellow-3:#ffe066;--yellow-4:#ffd43b;--yellow-5:#fcc419;--yellow-6:#fab005;--yellow-7:#f59f00;--yellow-8:#f08c00;--yellow-9:#e67700;--yellow-10:#b35c00;--yellow-11:#804200;--yellow-12:#663500;--orange-0:#fff4e6;--orange-1:#ffe8cc;--orange-2:#ffd8a8;--orange-3:#ffc078;--orange-4:#ffa94d;--orange-5:#ff922b;--orange-6:#fd7e14;--orange-7:#f76707;--orange-8:#e8590c;--orange-9:#d9480f;--orange-10:#bf400d;--orange-11:#99330b;--orange-12:#802b09;--choco-0:#fff8dc;--choco-1:#fce1bc;--choco-2:#f7ca9e;--choco-3:#f1b280;--choco-4:#e99b62;--choco-5:#df8545;--choco-6:#d46e25;--choco-7:#bd5f1b;--choco-8:#a45117;--choco-9:#8a4513;--choco-10:#703a13;--choco-11:#572f12;--choco-12:#3d210d;--brown-0:#faf4eb;--brown-1:#ede0d1;--brown-2:#e0cab7;--brown-3:#d3b79e;--brown-4:#c5a285;--brown-5:#b78f6d;--brown-6:#a87c56;--brown-7:#956b47;--brown-8:#825b3a;--brown-9:#6f4b2d;--brown-10:#5e3a21;--brown-11:#4e2b15;--brown-12:#422412;--sand-0:#f8fafb;--sand-1:#e6e4dc;--sand-2:#d5cfbd;--sand-3:#c2b9a0;--sand-4:#aea58c;--sand-5:#9a9178;--sand-6:#867c65;--sand-7:#736a53;--sand-8:#5f5746;--sand-9:#4b4639;--sand-10:#38352d;--sand-11:#252521;--sand-12:#121210;--camo-0:#f9fbe7;--camo-1:#e8ed9c;--camo-2:#d2df4e;--camo-3:#c2ce34;--camo-4:#b5bb2e;--camo-5:#a7a827;--camo-6:#999621;--camo-7:#8c851c;--camo-8:#7e7416;--camo-9:#6d6414;--camo-10:#5d5411;--camo-11:#4d460e;--camo-12:#36300a;--jungle-0:#ecfeb0;--jungle-1:#def39a;--jungle-2:#d0e884;--jungle-3:#c2dd6e;--jungle-4:#b5d15b;--jungle-5:#a8c648;--jungle-6:#9bbb36;--jungle-7:#8fb024;--jungle-8:#84a513;--jungle-9:#7a9908;--jungle-10:#658006;--jungle-11:#516605;--jungle-12:#3d4d04}html{font-family:var(--main-font);line-height:var(--rhythm);background:var(--bg);color:var(--fg);scroll-padding-block-start:calc(4*var(--gap))}body{margin:0}header,footer,section+section{margin-block:calc(2*var(--gap))}nav :is(a:not(.\),.\){color:var(--accent);text-decoration:none}aside{font-size:.8em;line-height:calc(var(--rhythm)*2/3);--gap:calc(var(--rhythm)*var(--density)*2/3);border-block:1px solid var(--graphical-fg);padding-block:var(--gap);margin-block:calc(var(--gap)*3/2)}aside.bg{padding-inline:var(--gap)}aside h1,aside h2,aside h3,aside h4,aside h5,aside h6{text-transform:none;letter-spacing:none;font-size:1em}aside.big{border:none;border-inline-start:1px solid var(--muted-fg);color:var(--accent);padding:0;background:0 0;border-radius:0;padding-inline-start:var(--rhythm);font-style:italic}h1,h2,h3,h4,h5,h6,.\,.\,.\,.\,.\,.\{font-family:var(--display-font);margin-block-start:calc(2*var(--gap));margin-block-end:var(--gap);font-size:1em;position:relative}h1,.\{text-transform:none;font-size:2em;line-height:calc(2*var(--rhythm));letter-spacing:0}h2,.\{text-transform:none;font-size:1.6em;line-height:calc(1.5*var(--rhythm));letter-spacing:0}h3,.\{font-size:1.17em;line-height:calc(1*var(--rhythm))}h4,.\,h5,.\,h6,.\{text-transform:none;font-size:1em;line-height:calc(1*var(--rhythm));letter-spacing:0;margin-block-start:var(--gap)}h1+h2,h2+h3,h3+h4,h4+h5,h5+h6,h1:first-child,h2:first-child,h3:first-child,h4:first-child,h5:first-child,h6:first-child{margin-block-start:var(--gap)}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{outline:none}:is(h1:target,h2:target,h3:target,h4:target,h5:target,h6:target):before{content:"";background:var(--accent);width:4px;height:100%;display:block;position:absolute;left:-.5em}header{font-family:var(--display-font);border-block-end:1px solid var(--graphical-fg)}footer{font-family:var(--secondary-font);font-size:.8em;line-height:calc(var(--rhythm)*2/3);border-block-start:1px solid var(--graphical-fg)}body>header,body>footer,main+footer{padding:var(--rhythm)calc((100% - var(--eff-line-length))/2)}address{--density:0}p{margin-block:var(--gap)}hr{color:inherit;margin-inline:0;margin-block:var(--gap);border-inline-start:1px solid var(--accent);border-block-start:1px solid var(--accent);border-block-end:none;border-inline-end:none;flex:0 1 0;block-size:auto}pre{font-family:var(--mono-font);font-size:.9em;line-height:var(--rhythm);tab-size:2;margin:var(--gap)0;scrollbar-width:thin;scrollbar-color:var(--accent)transparent;overflow-x:auto}blockquote{margin-inline:0 var(--gap);padding-inline:var(--gap)0;margin-block:var(--gap);font-size:1.1em;line-height:var(--rhythm);border-inline-start:1px solid var(--graphical-fg);color:var(--muted-fg);font-style:italic}blockquote em,blockquote cite,blockquote dfn,blockquote var,blockquote i,blockquote address{font-style:normal}blockquote footer{text-align:right;text-align:end}ul,ol{margin-block:var(--gap);padding-inline-start:var(--rhythm)}:is(ul,ol) :is(ul,ol){padding-inline-start:var(--gap)}:is(ul,ol)[role=list],:is(ul,ol)[role=listbox]{padding-inline-start:0;list-style:none}ol{list-style:decimal}dl{margin-block:var(--gap)}dt{font-weight:700;font-family:var(--secondary-font)}dd{margin-inline-start:var(--rhythm)}li::marker{font-family:var(--secondary-font)}figure{max-width:100%;margin-inline:0}figcaption{margin-block:var(--gap);font-family:var(--secondary-font);color:var(--muted-fg)}main{max-inline-size:var(--eff-line-length);inline-size:100%;margin-inline:auto}main:first-child{padding-top:var(--gap)}a,.\{color:var(--link-fg,var(--accent));border-radius:var(--border-radius);outline-offset:1px;background:0 0;border:none;font-family:inherit;font-size:1em;text-decoration:underline 1px dotted}.list-of-links :is(a,.\){text-decoration:none}:is(a,.\):hover,:is(a,.\):focus{cursor:pointer;outline:none;text-decoration:underline 2px}small[role=note]{float:inline-end;clear:inline-end;--sidenote-width:20ch;max-inline-size:var(--sidenote-width);font-family:var(--secondary-font);background:var(--bg);border:1px solid #0000;margin-block-end:var(--rhythm);margin-inline-end:calc(1em - var(--sidenote-width));padding-inline:1.5ch 1ch;transition:transform .1s ease-in-out;display:block}small[role=note]:hover,small[role=note]:focus-within{border:1px solid var(--graphical-fg);border-radius:var(--border-radius);transform:translateX(calc(0px - var(--sidenote-width) + min(var(--gutter-width),var(--sidenote-width))))}small,.\{font-size:.8em;line-height:calc(var(--rhythm)*2/3)}s{color:var(--bad-fg)}q{font-style:italic}q em,q cite,q dfn,q var,q i,q address{font-style:normal}time{font-variant-numeric:tabular-nums}code,samp,kbd{font-family:var(--mono-font);font-style:normal}samp{color:var(--ok-fg)}kbd kbd{background:var(--interactive-bg);border:1px outset var(--graphical-fg);border-radius:var(--border-radius);border-block-end-width:3px;padding:0 .3em;font-size:.8em;line-height:1.1em;display:inline-block}sub{vertical-align:bottom;line-height:1}sup{vertical-align:top;line-height:1}mark{background:var(--warn-bg);color:var(--warn-fg)}ins{background:var(--ok-bg);color:var(--ok-fg)}del{background:var(--bad-bg);color:var(--bad-fg)}img,video,audio,iframe,object,embed{block-size:auto;inline-size:max-content;max-inline-size:100%}table{font-variant-numeric:tabular-nums;font:inherit}caption{text-align:start;font-family:var(--secondary-font);font-style:italic}tbody{border-block:1px solid var(--faded-fg)}td,th{vertical-align:top}:is(td,th):not(:last-child){padding-inline-end:var(--rhythm)}th{font-family:var(--secondary-font);text-align:start}input{display:block}label :is(input,select):not([specificity-hack]){padding-block:0;display:inline}:where(button,input[type=submit],input[type=reset],input[type=button],.\):not(.\){padding:0 calc(var(--rhythm)/4);vertical-align:middle;box-sizing:border-box;font-size:.8rem;line-height:1.125em;font-family:var(--secondary-font);min-height:var(--rhythm);background:var(--interactive-bg);color:var(--fg);border:1px solid var(--muted-fg);box-shadow:0 2px 4px -2px var(--fg);border-radius:var(--border-radius);justify-content:center;align-items:center;text-decoration:none;display:inline-flex}input::file-selector-button{padding:0 calc(var(--rhythm)/4);vertical-align:middle;box-sizing:border-box;font-size:.8rem;line-height:1.125em;font-family:var(--secondary-font);min-height:var(--rhythm);background:var(--interactive-bg);color:var(--fg);border:1px solid var(--muted-fg);box-shadow:0 2px 4px -2px var(--fg);border-radius:var(--border-radius);justify-content:center;align-items:center;text-decoration:none;display:inline-flex}input::file-selector-button:is(){cursor:default}input::file-selector-button:hover{filter:brightness(1.1);box-shadow:0 3px 6px -2px var(--fg);text-decoration:none}input::file-selector-button:focus-visible{filter:brightness(1.1);box-shadow:0 3px 6px -2px var(--fg);text-decoration:none}input::file-selector-button:active{box-shadow:none}:is(strong>:is()){background:var(--accent);color:var(--bg);border:none;font-weight:700}:is(strong>:is())[disabled]{color:var(--muted-accent)}:where(button,input[type=submit],input[type=reset],input[type=button],.\):not(.\):is(a){cursor:default}:where(button,input[type=submit],input[type=reset],input[type=button],.\):not(.\):hover,:where(button,input[type=submit],input[type=reset],input[type=button],.\):not(.\):focus-visible{filter:brightness(1.1);box-shadow:0 3px 6px -2px var(--fg);text-decoration:none}:where(button,input[type=submit],input[type=reset],input[type=button],.\):not(.\):active{box-shadow:none}:is(strong>:where(button,input[type=submit],input[type=reset],input[type=button],.\):not(.\)){background:var(--accent);color:var(--bg);border:none;font-weight:700}:is(strong>:where(button,input[type=submit],input[type=reset],input[type=button],.\):not(.\))[disabled]{color:var(--muted-accent)}:where(button,input[type=submit],input[type=reset],input[type=button],.\):not(.\):active:is([aria-pressed],[aria-expanded]){color:var(--accent);box-shadow:0 1px 5px -1px var(--fg)inset}:where(button,input[type=submit],input[type=reset],input[type=button],.\):not(.\):where([aria-pressed=true],[aria-expanded=true]){box-shadow:0 2px 4px -1px var(--fg)inset;background:var(--pressed-interactive-bg);color:var(--accent)}:where(button,input[type=submit],input[type=reset],input[type=button],.\):not(.\):where([aria-pressed=true],[aria-expanded=true]):hover,:where(button,input[type=submit],input[type=reset],input[type=button],.\):not(.\):where([aria-pressed=true],[aria-expanded=true]):focus-visible{box-shadow:0 1px 3px -1px var(--fg)inset}:where(button,input[type=submit],input[type=reset],input[type=button],.\):not(.\).big{min-block-size:calc(1.5*var(--rhythm));padding-inline:calc(.5*var(--rhythm));font-size:1rem;line-height:var(--rhythm)}:where(button,input[type=submit],input[type=reset],input[type=button],.\):not(.\):disabled{color:var(--muted-fg);box-shadow:none}input:not([type]),input[type=text],input[type=search],input[type=tel],input[type=url],input[type=email],input[type=password],input[type=date],input[type=month],input[type=week],input[type=time],input[type=datetime],input[type=datetime-local],input[type=number],select,textarea{padding:calc(var(--rhythm)/4);vertical-align:top;font-size:1rem;line-height:inherit;font-family:var(--main-font);background:var(--bg);color:var(--fg);border:1px solid var(--graphical-fg);border-radius:var(--border-radius);vertical-align:top}:is(input:not([type]),input[type=text],input[type=search],input[type=tel],input[type=url],input[type=email],input[type=password],input[type=date],input[type=month],input[type=week],input[type=time],input[type=datetime],input[type=datetime-local],input[type=number],select,textarea):focus-visible{border:1px solid var(--accent)}:is(input:not([type]),input[type=text],input[type=search],input[type=tel],input[type=url],input[type=email],input[type=password],input[type=date],input[type=month],input[type=week],input[type=time],input[type=datetime],input[type=datetime-local],input[type=number],select,textarea)::placeholder{color:var(--muted-fg);opacity:1;text-align:end}input[type=range]{padding:calc(var(--gap)/4);width:100%}input[type=color]{height:calc(1.5*var(--rhythm));background:0 0;border:none;margin:0;padding:0}input[type=file]{padding:calc(var(--gap)/4)0;font:inherit;line-height:calc(var(--rhythm)/2)}input[type=file]::file-selector-button{margin-block:.1em 0;margin-inline-end:1ch}select[multiple]{vertical-align:top}optgroup:before{color:var(--muted-fg);font-style:normal}label[for]{padding-block:calc(var(--gap)/4);display:block}fieldset{padding:var(--gap);margin:var(--gap)0;border-radius:var(--border-radius);border:1px solid var(--graphical-fg);width:100%;position:relative}fieldset>legend+*{margin-block-start:0}details:not(specificity-hack){padding-block-start:0}details:not(specificity-hack):not([open]){padding-block-end:0}summary{margin:calc(0px - var(--gap));margin-top:calc(0px - var(--gap));padding-inline:var(--gap);font-family:var(--secondary-font);cursor:pointer;margin-bottom:0;font-weight:700}summary:focus-visible,summary:active{filter:brightness(.8);outline:none}dialog{inline-inset:0;background-color:var(--bg);color:var(--fg);border-color:var(--fg);block-size:fit-content;inline-size:fit-content;margin:auto!important}dialog[open]::backdrop{opacity:.4;background:#000;animation:2s bg;display:block}@keyframes bg{0%{background:0 0}}dialog:not([open]){display:none}.box,[role=menu],.sidebar-layout>header,[role=tabpanel],figure,details,:where(dialog){margin:var(--gap)0;padding:var(--gap);border-radius:var(--border-radius);background:var(--box-bg);border:1px solid var(--graphical-fg);overflow:clip}.titlebar{margin-inline:calc(0px - var(--gap));padding-inline:var(--gap);font:inherit;font-family:var(--secondary-font);translate:0 calc(-1px - var(--gap));background:var(--graphical-fg);color:var(--bg);text-shadow:0 .1em .2em var(--fg);border-bottom:1px solid;border-bottom-color:inherit;margin-block-end:calc(0px - var(--gap));font-weight:700}.sub-title,sub-title{color:var(--muted-fg);font-weight:400;display:block}.tool-bar,[role=toolbar]{gap:calc(var(--gap)/2);flex-flow:wrap;display:flex}:is(.tool-bar,[role=toolbar])>*{margin:0}.sidebar-layout header li{margin-block:calc(.5*var(--gap))}.sidebar-layout header a{font-weight:700}@media (width>=75ch){.sidebar-layout{grid-template-columns:25ch auto;display:grid;inset:0}.sidebar-layout>header{border-block:none;border-inline-start:none;margin:0}.sidebar-layout>:nth-child(2){--full-width:calc(100vw - 25ch);margin-top:var(--gap);overflow:auto}}.breadcrumbs[aria-label]{font-family:var(--secondary-font)}.breadcrumbs[aria-label] ul,.breadcrumbs[aria-label] ol{padding-inline-start:0;list-style:none}.breadcrumbs[aria-label] li{display:inline}.breadcrumbs[aria-label] li+li:before{content:" / "/"";content:" / ";display:inline}.breadcrumbs[aria-label] [aria-current=page]{font-weight:700}.chip,chip{font-family:var(--secondary-font);border:1px solid var(--accent);background:var(--box-bg);border-radius:calc(var(--rhythm)/2);padding-inline:calc(var(--rhythm)/2)}.navbar{padding:var(--rhythm);font-family:var(--secondary-font);background:var(--box-bg);border-block-end:1px solid var(--accent);scrollbar-width:thin;z-index:5;align-items:center;gap:var(--gap);flex-flow:row;display:flex;position:sticky;top:0;left:0;right:0;overflow-x:auto}.navbar.expanded{flex-flow:column;align-items:start;max-height:90vh;overflow-y:auto}.navbar.expanded ul[role=list]{flex-flow:column}.navbar *{flex-shrink:0;margin-block:0}.navbar:not(.expanded)>:first-child,.navbar:not(.expanded) nav>:first-child{margin-inline-start:auto}.navbar:not(.expanded)>:last-child,.navbar:not(.expanded) nav>:last-child{margin-inline-end:auto}.navbar hr{align-self:stretch}.navbar nav ul[role=list]{gap:var(--rhythm);flex-flow:row;display:flex}.navbar nav ul[role=list] *{flex-shrink:0}.navbar nav ul[role=list]{padding-inline-start:0}.navbar :is(a:not(.\,.chip),.\){padding-inline:.2em;font-weight:700;text-decoration:none}.navbar :is(a:not(.\,.chip),.\):hover,.navbar :is(a:not(.\,.chip),.\):focus{text-decoration:underline}.navbar [aria-current=page]{position:relative}.navbar [aria-current=page]:after{content:"";bottom:calc(-1*var(--gap));background:currentColor;width:100%;height:6px;display:block;position:absolute}.navbar.expanded [aria-current=page]:after{left:calc(-1*var(--gap));width:6px;height:100%;position:absolute;top:0}.permalink-anchor{display:none}:hover>.permalink-anchor{display:initial}button.iconbutton{color:currentColor;box-shadow:none;line-height:var(--rhythm);text-align:center;background:0 0;border:none;border-radius:50%;width:24px;height:24px;padding:0;font-size:24px;transition:font-weight .2s ease-in-out;display:inline-block}button.iconbutton:hover,button.iconbutton:focus-visible{box-shadow:none;outline:1px solid var(--accent);outline-offset:6px}button.iconbutton:active{box-shadow:none;outline-offset:3px;background:0 0}button.iconbutton[aria-pressed=true]{box-shadow:none;transform:none}[role=tablist]{scrollbar-width:thin;gap:.5ch;display:flex}[role=tab][role=tab]{all:initial;font-family:var(--secondary-font);padding:0 calc(var(--rhythm)/4);min-height:var(--rhythm);color:var(--fg);border:solid var(--graphical-fg);background:var(--interactive-bg);border-width:1px;border-start-start-radius:.4em;border-start-end-radius:.4em;margin:0;position:relative;bottom:-1px}[role=tab][role=tab]:active,[role=tab][role=tab][aria-selected=true]{background:var(--box-bg);border-block-end:1px solid #0000}[role=tab][role=tab]:hover{background-color:var(--box-bg);box-shadow:none}[role=tab][role=tab]:focus-visible{box-shadow:none;color:var(--accent);text-decoration:underline}[role=tabpanel]{z-index:1;border-start-start-radius:0;border-start-end-radius:0;margin-block-start:0}[role=menu]{z-index:10;padding:calc(var(--gap)/2)0;flex-flow:column;margin:1px 0 0;display:flex;position:absolute}[role=menuitem]{padding:0 calc(var(--gap)/2);color:var(--fg);border-radius:0;text-decoration:none;display:block}[role=menuitem]:focus,[role=menuitem]:active{background:var(--accent);color:var(--bg)}[role=listbox]{list-style:none}[role=listbox] [role=option]{margin-inline:calc(-1*var(--gap));padding-inline:var(--gap);border-radius:0}[role=listbox] [role=option][aria-selected=true]{background:var(--interactive-bg)}[role=listbox] [role=option].active{--temporary-bg:var(--accent);--temporary-fg:var(--bg);--temporary-accent:parent-var(--muted-accent);--temporary-muted-accent:parent-var(--box-bg);background:var(--temporary-bg);color:var(--temporary-fg)}[role=listbox] [role=option].active>*{--bg:var(--temporary-bg);--fg:var(--temporary-fg);--accent:var(--temporary-accent);--muted-accent:var(--temporary-muted-accent)}[aria-orientation=vertical]{text-align:center;flex-direction:column;width:fit-content}.plain{--box-bg:var(--plain-bg);--accent:var(--plain-fg);--graphical-fg:var(--plain-graphical-fg)}.info{--box-bg:var(--info-bg);--accent:var(--info-fg);--graphical-fg:var(--info-graphical-fg)}.ok{--box-bg:var(--ok-bg);--accent:var(--ok-fg);--graphical-fg:var(--ok-graphical-fg)}.warn{--box-bg:var(--warn-bg);--accent:var(--warn-fg);--graphical-fg:var(--warn-graphical-fg)}.bad{--box-bg:var(--bad-bg);--accent:var(--bad-fg);--graphical-fg:var(--bad-graphical-fg)}.color{color:var(--accent)}.bg{background:var(--box-bg)}.border{border-style:solid;border-color:var(--graphical-fg)}:root{--fg:var(--gray-12);--muted-fg:var(--gray-10);--faded-fg:var(--gray-6);--graphical-fg:var(--plain-graphical-fg);--plain-fg:var(--blue-10);--info-fg:var(--blue-11);--ok-fg:var(--green-11);--bad-fg:var(--red-11);--warn-fg:var(--yellow-11);--plain-graphical-fg:var(--gray-6);--info-graphical-fg:var(--blue-6);--ok-graphical-fg:var(--green-6);--bad-graphical-fg:var(--red-6);--warn-graphical-fg:var(--yellow-6);--bg:var(--gray-0);--box-bg:var(--plain-bg);--interactive-bg:var(--gray-4);--plain-bg:var(--gray-1);--info-bg:var(--blue-1);--ok-bg:var(--green-1);--bad-bg:var(--red-1);--warn-bg:var(--yellow-1);--accent:var(--blue-10);--muted-accent:var(--blue-7);--rhythm:1.4rem;--line-length:40rem;--border-radius:.2rem;--main-font:"Source Sans 3","Source Sans Pro",-apple-system,system-ui,sans-serif;--secondary-font:var(--main-font);--display-font:var(--secondary-font);--mono-font:"M Plus Code Latin",monospace,monospace;--density:1;--full-width:100vw;--eff-line-length:min(calc(var(--full-width) - (2*var(--rhythm))),var(--line-length));--gutter-width:calc(( var(--full-width) - var(--eff-line-length))/2)}:root.-dark-theme{--fg:var(--gray-0);--muted-fg:var(--gray-2);--faded-fg:var(--gray-7);--plain-bg:var(--gray-11);--info-bg:var(--blue-12);--ok-bg:var(--green-12);--bad-bg:var(--red-12);--warn-bg:var(--yellow-12);--plain-faded-fg:var(--blue-6);--info-faded-fg:var(--blue-6);--ok-faded-fg:var(--green-6);--bad-faded-fg:var(--red-6);--warn-faded-fg:var(--yellow-6);--bg:var(--gray-12);--box-bg:var(--gray-10);--interactive-bg:var(--gray-8);--plain-fg:var(--blue-2);--info-fg:var(--blue-2);--ok-fg:var(--green-2);--bad-fg:var(--red-2);--warn-fg:var(--yellow-2);--accent:var(--blue-2);--muted-accent:var(--blue-5)}@media (prefers-color-scheme:dark){:root:not(.-no-dark-theme){--fg:var(--gray-0);--muted-fg:var(--gray-2);--faded-fg:var(--gray-7);--plain-bg:var(--gray-11);--info-bg:var(--blue-12);--ok-bg:var(--green-12);--bad-bg:var(--red-12);--warn-bg:var(--yellow-12);--plain-faded-fg:var(--blue-6);--info-faded-fg:var(--blue-6);--ok-faded-fg:var(--green-6);--bad-faded-fg:var(--red-6);--warn-faded-fg:var(--yellow-6);--bg:var(--gray-12);--box-bg:var(--gray-10);--interactive-bg:var(--gray-8);--plain-fg:var(--blue-2);--info-fg:var(--blue-2);--ok-fg:var(--green-2);--bad-fg:var(--red-2);--warn-fg:var(--yellow-2);--accent:var(--blue-2);--muted-accent:var(--blue-5)}}*{--gap:calc(var(--rhythm)*var(--density));accent-color:var(--accent)}.textcolumns{--col-width:30ch;column-width:var(--col-width);column-gap:var(--gap);margin-block:var(--gap)}.textcolumns :first-child{margin-block-start:0!important}.text-align\:center{text-align:center}.center{place-items:center;display:grid}.container{max-inline-size:var(--eff-line-length);margin-inline:auto}.fullbleed{width:var(--full-width);transform:translateX(calc(-.5*var(--full-width)));border-inline:none;border-radius:0;position:relative;left:50%}.fullscreen{border-inline:none;border-radius:0;width:100vw;height:100vh;position:relative;left:50%;transform:translate(-50vw)}.width\:100\%{width:100%;max-width:100%}.height\:100\%{height:100%;max-height:100%}:is(body,.box,[role=menu],.sidebar-layout>header,[role=tabpanel],figure,details,dialog,aside,fieldset,dd,td,th)>:first-child:first-child:first-child:first-child,:is(body,.box,[role=menu],.sidebar-layout>header,[role=tabpanel],figure,details,dialog,aside,fieldset,dd,td,th)>:first-child>:first-child:first-child:first-child,:is(body,.box,[role=menu],.sidebar-layout>header,[role=tabpanel],figure,details,dialog,aside,fieldset,dd,td,th)>:first-child>:first-child>:first-child:first-child,:is(body,.box,[role=menu],.sidebar-layout>header,[role=tabpanel],figure,details,dialog,aside,fieldset,dd,td,th)>:first-child>:first-child>:first-child>:first-child{margin-block-start:0}:is(body,.box,[role=menu],.sidebar-layout>header,[role=tabpanel],figure,details,dialog,aside,fieldset,dd,td,th)>:last-child:last-child:last-child:last-child,:is(body,.box,[role=menu],.sidebar-layout>header,[role=tabpanel],figure,details,dialog,aside,fieldset,dd,td,th)>:last-child>:last-child:last-child:last-child,:is(body,.box,[role=menu],.sidebar-layout>header,[role=tabpanel],figure,details,dialog,aside,fieldset,dd,td,th)>:last-child>:last-child>:last-child:last-child,:is(body,.box,[role=menu],.sidebar-layout>header,[role=tabpanel],figure,details,dialog,aside,fieldset,dd,td,th)>:last-child>:last-child>:last-child>:last-child{margin-block-end:0}.padding{padding:var(--gap)}.padding-block{padding-block:var(--gap)}.padding-block-start{padding-block-start:var(--gap)}.padding-block-end{padding-block-end:var(--gap)}.padding-inline{padding-inline:var(--gap)}.padding-inline-start{padding-inline-start:var(--gap)}.padding-inline-end{padding-inline-end:var(--gap)}.margin{margin:var(--gap)}.margin-block{margin-block:var(--gap)}.margin-block-start{margin-block-start:var(--gap)}.margin-block-end{margin-block-end:var(--gap)}.margin-inline{margin-inline:var(--gap)}.margin-inline-start{margin-inline-start:var(--gap)}.margin-inline-end{margin-inline-end:var(--gap)}.flow-gap>:not(:last-child){margin-bottom:var(--gap)}.inline{display:inline}.block{display:block}.contents{display:contents}.table{width:100%;margin:0;display:table}.row,.rows>*{display:table-row}:is(.row,.rows>*):not(:last-child):not([specificity-hack])>*{margin-bottom:var(--gap)}:is(.row,.rows>*)>:not([specificity-hack]){vertical-align:top;display:table-cell}:is(.row,.rows>*)>*+:not([specificity-hack]){margin-inline-start:var(--gap);display:inline-block}.big{font-size:1.4em;line-height:calc(1.5*var(--rhythm))}.nested-list ul,.nested-list ol{margin-block:0}.fixed{position:fixed}.sticky{position:sticky}.top{top:0}.right{right:0}.bottom{bottom:0}.left{left:0}.float\:left{float:left}.float\:right{float:right}.overflow\:auto{overflow:auto}.overflow\:scroll{overflow:scroll}.airy{--density:3}.spacious{--density:2}.dense{--density:1}.crowded{--density:.5}.packed{--density:0}.autodensity{--density:1}@media (width>=768px){.autodensity{--density:2}}@media (width>=1024px){.autodensity{--density:3}}.vh,v-h{clip:rect(0 0 0 0);-webkit-clip-path:inset(50%);clip-path:inset(50%);white-space:nowrap;block-size:1px;inline-size:1px;overflow:hidden}.all\:initial{all:initial}.bold{font-weight:700}.italic{font-style:italic}.italic em,.italic cite,.italic dfn,.italic var,.italic i,.italic address{font-style:normal}.allcaps{text-transform:uppercase;letter-spacing:.1rem}.main-font,.primary-font{font-family:var(--main-font)}.secondary-font{font-family:var(--secondary-font)}.display-font{font-family:var(--display-font)}.mono-font,.monospace{font-family:var(--mono-font)}.massivetext{font-size:calc(.13*var(--eff-line-length));letter-spacing:0;line-height:1em}.aestheticbreak{height:calc(.5*var(--gap));margin:0;padding:0;display:block}.f-row{gap:var(--gap);flex-direction:row;display:flex}.f-row>*{margin:0}.f-col{gap:var(--gap);flex-direction:column;display:flex}.f-col>*{margin:0}.f-switch{gap:var(--gap);--f-switch-threshold:55ch;flex-wrap:wrap;display:flex}.f-switch>*{flex-grow:1;flex-basis:calc((var(--f-switch-threshold) - 100%)*999);margin:0}.justify-content\:start{justify-content:start}.justify-content\:end{justify-content:end}.justify-content\:baseline{justify-content:baseline}.justify-content\:center{justify-content:center}.justify-content\:stretch{justify-content:stretch}.justify-content\:space-between{justify-content:space-between}.justify-content\:space-around{justify-content:space-around}.justify-content\:space-evenly{justify-content:space-evenly}.align-items\:start{align-items:start}.align-items\:end{align-items:end}.align-items\:baseline{align-items:baseline}.align-items\:center{align-items:center}.align-items\:stretch{align-items:stretch}.align-self\:start{align-self:start}.align-self\:end{align-self:end}.align-self\:baseline{align-self:baseline}.align-self\:center{align-self:center}.align-self\:stretch{align-self:stretch}.flex-grow\:0{flex-grow:0}.flex-grow\:1{flex-grow:1}.flex-grow\:2{flex-grow:2}.flex-grow\:3{flex-grow:3}.flex-grow\:4{flex-grow:4}.flex-grow\:5{flex-grow:5}.flex-grow\:6{flex-grow:6}.flex-grow\:7{flex-grow:7}.flex-grow\:8{flex-grow:8}.flex-grow\:9{flex-grow:9}.flex-grow\:10{flex-grow:10}.flex-grow\:11{flex-grow:11}.flex-grow\:12{flex-grow:12}.flex-wrap\:wrap{flex-wrap:wrap}.flex-wrap\:nowrap{flex-wrap:nowrap}.grid{grid-auto-columns:var(--grid-col-width,1fr);grid-auto-rows:var(--grid-row-width,auto);gap:var(--gap);display:grid}.grid>*{margin:0}.grid-even-rows{--grid-row-width:1fr}.grid-variable-cols{--grid-col-width:auto}[data-cols^="1 "]{grid-column-start:1}[data-cols$=\ 1]{grid-column-end:2}[data-cols="1"]{grid-column:1}[data-cols^="2 "]{grid-column-start:2}[data-cols$=\ 2]{grid-column-end:3}[data-cols="2"]{grid-column:2}[data-cols^="3 "]{grid-column-start:3}[data-cols$=\ 3]{grid-column-end:4}[data-cols="3"]{grid-column:3}[data-cols^="4 "]{grid-column-start:4}[data-cols$=\ 4]{grid-column-end:5}[data-cols="4"]{grid-column:4}[data-cols^="5 "]{grid-column-start:5}[data-cols$=\ 5]{grid-column-end:6}[data-cols="5"]{grid-column:5}[data-cols^="6 "]{grid-column-start:6}[data-cols$=\ 6]{grid-column-end:7}[data-cols="6"]{grid-column:6}[data-cols^="7 "]{grid-column-start:7}[data-cols$=\ 7]{grid-column-end:8}[data-cols="7"]{grid-column:7}[data-cols^="8 "]{grid-column-start:8}[data-cols$=\ 8]{grid-column-end:9}[data-cols="8"]{grid-column:8}[data-cols^="9 "]{grid-column-start:9}[data-cols$=\ 9]{grid-column-end:10}[data-cols="9"]{grid-column:9}[data-cols^="10 "]{grid-column-start:10}[data-cols$=\ 10]{grid-column-end:11}[data-cols="10"]{grid-column:10}[data-cols^="11 "]{grid-column-start:11}[data-cols$=\ 11]{grid-column-end:12}[data-cols="11"]{grid-column:11}[data-cols^="12 "]{grid-column-start:12}[data-cols$=\ 12]{grid-column-end:13}[data-cols="12"]{grid-column:12}[data-rows^="1 "]{grid-row-start:1}[data-rows$=\ 1]{grid-row-end:2}[data-rows="1"]{grid-row:1}[data-rows^="2 "]{grid-row-start:2}[data-rows$=\ 2]{grid-row-end:3}[data-rows="2"]{grid-row:2}[data-rows^="3 "]{grid-row-start:3}[data-rows$=\ 3]{grid-row-end:4}[data-rows="3"]{grid-row:3}[data-rows^="4 "]{grid-row-start:4}[data-rows$=\ 4]{grid-row-end:5}[data-rows="4"]{grid-row:4}[data-rows^="5 "]{grid-row-start:5}[data-rows$=\ 5]{grid-row-end:6}[data-rows="5"]{grid-row:5}[data-rows^="6 "]{grid-row-start:6}[data-rows$=\ 6]{grid-row-end:7}[data-rows="6"]{grid-row:6}[data-rows^="7 "]{grid-row-start:7}[data-rows$=\ 7]{grid-row-end:8}[data-rows="7"]{grid-row:7}[data-rows^="8 "]{grid-row-start:8}[data-rows$=\ 8]{grid-row-end:9}[data-rows="8"]{grid-row:8}[data-rows^="9 "]{grid-row-start:9}[data-rows$=\ 9]{grid-row-end:10}[data-rows="9"]{grid-row:9}[data-rows^="10 "]{grid-row-start:10}[data-rows$=\ 10]{grid-row-end:11}[data-rows="10"]{grid-row:10}[data-rows^="11 "]{grid-row-start:11}[data-rows$=\ 11]{grid-row-end:12}[data-rows="11"]{grid-row:11}[data-rows^="12 "]{grid-row-start:12}[data-rows$=\ 12]{grid-row-end:13}[data-rows="12"]{grid-row:12}@media (width<=768px){[data-cols\@s^="1 "]{grid-column-start:1}[data-cols\@s$=\ 1]{grid-column-end:2}[data-cols\@s="1"]{grid-column:1}[data-cols\@s^="2 "]{grid-column-start:2}[data-cols\@s$=\ 2]{grid-column-end:3}[data-cols\@s="2"]{grid-column:2}[data-cols\@s^="3 "]{grid-column-start:3}[data-cols\@s$=\ 3]{grid-column-end:4}[data-cols\@s="3"]{grid-column:3}[data-cols\@s^="4 "]{grid-column-start:4}[data-cols\@s$=\ 4]{grid-column-end:5}[data-cols\@s="4"]{grid-column:4}[data-cols\@s^="5 "]{grid-column-start:5}[data-cols\@s$=\ 5]{grid-column-end:6}[data-cols\@s="5"]{grid-column:5}[data-cols\@s^="6 "]{grid-column-start:6}[data-cols\@s$=\ 6]{grid-column-end:7}[data-cols\@s="6"]{grid-column:6}[data-cols\@s^="7 "]{grid-column-start:7}[data-cols\@s$=\ 7]{grid-column-end:8}[data-cols\@s="7"]{grid-column:7}[data-cols\@s^="8 "]{grid-column-start:8}[data-cols\@s$=\ 8]{grid-column-end:9}[data-cols\@s="8"]{grid-column:8}[data-cols\@s^="9 "]{grid-column-start:9}[data-cols\@s$=\ 9]{grid-column-end:10}[data-cols\@s="9"]{grid-column:9}[data-cols\@s^="10 "]{grid-column-start:10}[data-cols\@s$=\ 10]{grid-column-end:11}[data-cols\@s="10"]{grid-column:10}[data-cols\@s^="11 "]{grid-column-start:11}[data-cols\@s$=\ 11]{grid-column-end:12}[data-cols\@s="11"]{grid-column:11}[data-cols\@s^="12 "]{grid-column-start:12}[data-cols\@s$=\ 12]{grid-column-end:13}[data-cols\@s="12"]{grid-column:12}[data-rows\@s^="1 "]{grid-row-start:1}[data-rows\@s$=\ 1]{grid-row-end:2}[data-rows\@s="1"]{grid-row:1}[data-rows\@s^="2 "]{grid-row-start:2}[data-rows\@s$=\ 2]{grid-row-end:3}[data-rows\@s="2"]{grid-row:2}[data-rows\@s^="3 "]{grid-row-start:3}[data-rows\@s$=\ 3]{grid-row-end:4}[data-rows\@s="3"]{grid-row:3}[data-rows\@s^="4 "]{grid-row-start:4}[data-rows\@s$=\ 4]{grid-row-end:5}[data-rows\@s="4"]{grid-row:4}[data-rows\@s^="5 "]{grid-row-start:5}[data-rows\@s$=\ 5]{grid-row-end:6}[data-rows\@s="5"]{grid-row:5}[data-rows\@s^="6 "]{grid-row-start:6}[data-rows\@s$=\ 6]{grid-row-end:7}[data-rows\@s="6"]{grid-row:6}[data-rows\@s^="7 "]{grid-row-start:7}[data-rows\@s$=\ 7]{grid-row-end:8}[data-rows\@s="7"]{grid-row:7}[data-rows\@s^="8 "]{grid-row-start:8}[data-rows\@s$=\ 8]{grid-row-end:9}[data-rows\@s="8"]{grid-row:8}[data-rows\@s^="9 "]{grid-row-start:9}[data-rows\@s$=\ 9]{grid-row-end:10}[data-rows\@s="9"]{grid-row:9}[data-rows\@s^="10 "]{grid-row-start:10}[data-rows\@s$=\ 10]{grid-row-end:11}[data-rows\@s="10"]{grid-row:10}[data-rows\@s^="11 "]{grid-row-start:11}[data-rows\@s$=\ 11]{grid-row-end:12}[data-rows\@s="11"]{grid-row:11}[data-rows\@s^="12 "]{grid-row-start:12}[data-rows\@s$=\ 12]{grid-row-end:13}[data-rows\@s="12"]{grid-row:12}}@media (width>=1024px){[data-cols\@l^="1 "]{grid-column-start:1}[data-cols\@l$=\ 1]{grid-column-end:2}[data-cols\@l="1"]{grid-column:1}[data-cols\@l^="2 "]{grid-column-start:2}[data-cols\@l$=\ 2]{grid-column-end:3}[data-cols\@l="2"]{grid-column:2}[data-cols\@l^="3 "]{grid-column-start:3}[data-cols\@l$=\ 3]{grid-column-end:4}[data-cols\@l="3"]{grid-column:3}[data-cols\@l^="4 "]{grid-column-start:4}[data-cols\@l$=\ 4]{grid-column-end:5}[data-cols\@l="4"]{grid-column:4}[data-cols\@l^="5 "]{grid-column-start:5}[data-cols\@l$=\ 5]{grid-column-end:6}[data-cols\@l="5"]{grid-column:5}[data-cols\@l^="6 "]{grid-column-start:6}[data-cols\@l$=\ 6]{grid-column-end:7}[data-cols\@l="6"]{grid-column:6}[data-cols\@l^="7 "]{grid-column-start:7}[data-cols\@l$=\ 7]{grid-column-end:8}[data-cols\@l="7"]{grid-column:7}[data-cols\@l^="8 "]{grid-column-start:8}[data-cols\@l$=\ 8]{grid-column-end:9}[data-cols\@l="8"]{grid-column:8}[data-cols\@l^="9 "]{grid-column-start:9}[data-cols\@l$=\ 9]{grid-column-end:10}[data-cols\@l="9"]{grid-column:9}[data-cols\@l^="10 "]{grid-column-start:10}[data-cols\@l$=\ 10]{grid-column-end:11}[data-cols\@l="10"]{grid-column:10}[data-cols\@l^="11 "]{grid-column-start:11}[data-cols\@l$=\ 11]{grid-column-end:12}[data-cols\@l="11"]{grid-column:11}[data-cols\@l^="12 "]{grid-column-start:12}[data-cols\@l$=\ 12]{grid-column-end:13}[data-cols\@l="12"]{grid-column:12}[data-rows\@l^="1 "]{grid-row-start:1}[data-rows\@l$=\ 1]{grid-row-end:2}[data-rows\@l="1"]{grid-row:1}[data-rows\@l^="2 "]{grid-row-start:2}[data-rows\@l$=\ 2]{grid-row-end:3}[data-rows\@l="2"]{grid-row:2}[data-rows\@l^="3 "]{grid-row-start:3}[data-rows\@l$=\ 3]{grid-row-end:4}[data-rows\@l="3"]{grid-row:3}[data-rows\@l^="4 "]{grid-row-start:4}[data-rows\@l$=\ 4]{grid-row-end:5}[data-rows\@l="4"]{grid-row:4}[data-rows\@l^="5 "]{grid-row-start:5}[data-rows\@l$=\ 5]{grid-row-end:6}[data-rows\@l="5"]{grid-row:5}[data-rows\@l^="6 "]{grid-row-start:6}[data-rows\@l$=\ 6]{grid-row-end:7}[data-rows\@l="6"]{grid-row:6}[data-rows\@l^="7 "]{grid-row-start:7}[data-rows\@l$=\ 7]{grid-row-end:8}[data-rows\@l="7"]{grid-row:7}[data-rows\@l^="8 "]{grid-row-start:8}[data-rows\@l$=\ 8]{grid-row-end:9}[data-rows\@l="8"]{grid-row:8}[data-rows\@l^="9 "]{grid-row-start:9}[data-rows\@l$=\ 9]{grid-row-end:10}[data-rows\@l="9"]{grid-row:9}[data-rows\@l^="10 "]{grid-row-start:10}[data-rows\@l$=\ 10]{grid-row-end:11}[data-rows\@l="10"]{grid-row:10}[data-rows\@l^="11 "]{grid-row-start:11}[data-rows\@l$=\ 11]{grid-row-end:12}[data-rows\@l="11"]{grid-row:11}[data-rows\@l^="12 "]{grid-row-start:12}[data-rows\@l$=\ 12]{grid-row-end:13}[data-rows\@l="12"]{grid-row:12}} diff --git a/src/huesoporro/static/mvp.css b/src/huesoporro/static/mvp.css new file mode 100644 index 0000000..da3d654 --- /dev/null +++ b/src/huesoporro/static/mvp.css @@ -0,0 +1,594 @@ +/* MVP.css v1.17 - https://github.com/andybrewer/mvp */ + +:root { + --active-brightness: 0.85; + --border-radius: 5px; + --box-shadow: 2px 2px 10px; + --color-accent: #118bee15; + --color-bg: #fff; + --color-bg-secondary: #e9e9e9; + --color-link: #118bee; + --color-secondary: #920de9; + --color-secondary-accent: #920de90b; + --color-shadow: #f4f4f4; + --color-table: #118bee; + --color-text: #000; + --color-text-secondary: #999; + --color-scrollbar: #cacae8; + --font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; + --hover-brightness: 1.2; + --justify-important: center; + --justify-normal: left; + --line-height: 1.5; + --width-card: 285px; + --width-card-medium: 460px; + --width-card-wide: 800px; + --width-content: 1080px; +} + +@media (prefers-color-scheme: dark) { + :root[color-mode="user"] { + --color-accent: #0097fc4f; + --color-bg: #333; + --color-bg-secondary: #555; + --color-link: #0097fc; + --color-secondary: #e20de9; + --color-secondary-accent: #e20de94f; + --color-shadow: #bbbbbb20; + --color-table: #0097fc; + --color-text: #f7f7f7; + --color-text-secondary: #aaa; + } +} + +html { + scroll-behavior: smooth; +} + +@media (prefers-reduced-motion: reduce) { + html { + scroll-behavior: auto; + } +} + +/* Layout */ +article aside { + background: var(--color-secondary-accent); + border-left: 4px solid var(--color-secondary); + padding: 0.01rem 0.8rem; +} + +body { + background: var(--color-bg); + color: var(--color-text); + font-family: var(--font-family); + line-height: var(--line-height); + margin: 0; + overflow-x: hidden; + padding: 0; +} + +footer, +header, +main { + margin: 0 auto; + max-width: var(--width-content); + padding: 3rem 1rem; +} + +hr { + background-color: var(--color-bg-secondary); + border: none; + height: 1px; + margin: 4rem 0; + width: 100%; +} + +section { + display: flex; + flex-wrap: wrap; + justify-content: var(--justify-important); +} + +section img, +article img { + max-width: 100%; +} + +section pre { + overflow: auto; +} + +section aside { + border: 1px solid var(--color-bg-secondary); + border-radius: var(--border-radius); + box-shadow: var(--box-shadow) var(--color-shadow); + margin: 1rem; + padding: 1.25rem; + width: var(--width-card); +} + +section aside:hover { + box-shadow: var(--box-shadow) var(--color-bg-secondary); +} + +[hidden] { + display: none; +} + +/* Headers */ +article header, +div header, +main header { + padding-top: 0; +} + +header { + text-align: var(--justify-important); +} + +header a b, +header a em, +header a i, +header a strong { + margin-left: 0.5rem; + margin-right: 0.5rem; +} + +header nav img { + margin: 1rem 0; +} + +section header { + padding-top: 0; + width: 100%; +} + +/* Nav */ +nav { + align-items: center; + display: flex; + font-weight: bold; + justify-content: space-between; + margin-bottom: 7rem; +} + +nav ul { + list-style: none; + padding: 0; +} + +nav ul li { + display: inline-block; + margin: 0 0.5rem; + position: relative; + text-align: left; +} + +/* Nav Dropdown */ +nav ul li:hover ul { + display: block; +} + +nav ul li ul { + background: var(--color-bg); + border: 1px solid var(--color-bg-secondary); + border-radius: var(--border-radius); + box-shadow: var(--box-shadow) var(--color-shadow); + display: none; + height: auto; + left: -2px; + padding: 0.5rem 1rem; + position: absolute; + top: 1.7rem; + white-space: nowrap; + width: auto; + z-index: 1; +} + +nav ul li ul::before { + /* fill gap above to make mousing over them easier */ + content: ""; + position: absolute; + left: 0; + right: 0; + top: -0.5rem; + height: 0.5rem; +} + +nav ul li ul li, +nav ul li ul li a { + display: block; +} + +/* Nav for Mobile */ +@media (max-width: 768px) { + nav { + flex-wrap: wrap; + } + + nav ul li { + width: calc(100% - 1em); + } + + nav ul li ul { + border: none; + box-shadow: none; + display: block; + position: static; + } +} + +/* Typography */ +code, +samp { + background-color: var(--color-accent); + border-radius: var(--border-radius); + color: var(--color-text); + display: inline-block; + margin: 0 0.1rem; + padding: 0 0.5rem; +} + +details { + margin: 1.3rem 0; +} + +details summary { + font-weight: bold; + cursor: pointer; +} + +h1, +h2, +h3, +h4, +h5, +h6 { + line-height: var(--line-height); + text-wrap: balance; +} + +mark { + padding: 0.1rem; +} + +ol li, +ul li { + padding: 0.2rem 0; +} + +p { + margin: 0.75rem 0; + padding: 0; + width: 100%; +} + +pre { + margin: 1rem 0; + max-width: var(--width-card-wide); + padding: 1rem 0; +} + +pre code, +pre samp { + display: block; + max-width: var(--width-card-wide); + padding: 0.5rem 2rem; + white-space: pre-wrap; +} + +small { + color: var(--color-text-secondary); +} + +sup { + background-color: var(--color-secondary); + border-radius: var(--border-radius); + color: var(--color-bg); + font-size: xx-small; + font-weight: bold; + margin: 0.2rem; + padding: 0.2rem 0.3rem; + position: relative; + top: -2px; +} + +/* Links */ +a { + color: var(--color-link); + display: inline-block; + font-weight: bold; + text-decoration: underline; +} + +a:hover { + filter: brightness(var(--hover-brightness)); +} + +a:active { + filter: brightness(var(--active-brightness)); +} + +a b, +a em, +a i, +a strong, +button, +input[type="submit"] { + border-radius: var(--border-radius); + display: inline-block; + font-size: medium; + font-weight: bold; + line-height: var(--line-height); + margin: 0.5rem 0; + padding: 1rem 2rem; +} + +button, +input[type="submit"] { + font-family: var(--font-family); +} + +button:hover, +input[type="submit"]:hover { + cursor: pointer; + filter: brightness(var(--hover-brightness)); +} + +button:active, +input[type="submit"]:active { + filter: brightness(var(--active-brightness)); +} + +a b, +a strong, +button, +input[type="submit"] { + background-color: var(--color-link); + border: 2px solid var(--color-link); + color: var(--color-bg); +} + +a em, +a i { + border: 2px solid var(--color-link); + border-radius: var(--border-radius); + color: var(--color-link); + display: inline-block; + padding: 1rem 2rem; +} + +article aside a { + color: var(--color-secondary); +} + +/* Images */ +figure { + margin: 0; + padding: 0; +} + +figure img { + max-width: 100%; +} + +figure figcaption { + color: var(--color-text-secondary); +} + +/* Forms */ +button:disabled, +input:disabled { + background: var(--color-bg-secondary); + border-color: var(--color-bg-secondary); + color: var(--color-text-secondary); + cursor: not-allowed; +} + +button[disabled]:hover, +input[type="submit"][disabled]:hover { + filter: none; +} + +form { + border: 1px solid var(--color-bg-secondary); + border-radius: var(--border-radius); + box-shadow: var(--box-shadow) var(--color-shadow); + display: block; + max-width: var(--width-card-wide); + min-width: var(--width-card); + padding: 1.5rem; + text-align: var(--justify-normal); +} + +form header { + margin: 1.5rem 0; + padding: 1.5rem 0; +} + +input, +label, +select, +textarea { + display: block; + font-size: inherit; + max-width: var(--width-card-wide); +} + +input[type="checkbox"], +input[type="radio"] { + display: inline-block; +} + +input[type="checkbox"] + label, +input[type="radio"] + label { + display: inline-block; + font-weight: normal; + position: relative; + top: 1px; +} + +input[type="range"] { + padding: 0.4rem 0; +} + +input, +select, +textarea { + border: 1px solid var(--color-bg-secondary); + border-radius: var(--border-radius); + margin-bottom: 1rem; + padding: 0.4rem 0.8rem; +} + +input[type="text"], +input[type="password"], +textarea { + width: calc(100% - 1.6rem); +} + +input[readonly], +textarea[readonly] { + background-color: var(--color-bg-secondary); +} + +label { + font-weight: bold; + margin-bottom: 0.2rem; +} + +/* Popups */ +dialog { + max-width: 90%; + max-height: 85dvh; + margin: auto; + padding: 0; + border: 1px solid var(--color-bg-secondary); + border-radius: 0.5rem; + overscroll-behavior: contain; + scroll-behavior: smooth; + scrollbar-width: none; /* Hide scrollbar for Firefox */ + -ms-overflow-style: none; /* Hide scrollbar for IE and Edge */ + scrollbar-color: transparent transparent; + animation: bottom-to-top 0.25s ease-in-out forwards; +} + +dialog::-webkit-scrollbar { + width: 0; + display: none; +} + +dialog::-webkit-scrollbar-track { + background: transparent; +} + +dialog::-webkit-scrollbar-thumb { + background-color: transparent; +} + +@media (min-width: 650px) { + dialog { + max-width: 39rem; + } +} + +dialog::backdrop { + background-color: rgba(0, 0, 0, 0.5); +} + +@keyframes bottom-to-top { + 0% { + opacity: 0; + transform: translateY(10%); + } + + 100% { + opacity: 1; + transform: translateY(0); + } +} + +/* Tables */ +table { + border: 1px solid var(--color-bg-secondary); + border-radius: var(--border-radius); + border-spacing: 0; + display: inline-block; + max-width: 100%; + overflow-x: auto; + padding: 0; + white-space: nowrap; +} + +table td, +table th, +table tr { + padding: 0.4rem 0.8rem; + text-align: var(--justify-important); +} + +table thead { + background-color: var(--color-table); + border-collapse: collapse; + border-radius: var(--border-radius); + color: var(--color-bg); + margin: 0; + padding: 0; +} + +table thead tr:first-child th:first-child { + border-top-left-radius: var(--border-radius); +} + +table thead tr:first-child th:last-child { + border-top-right-radius: var(--border-radius); +} + +table thead th:first-child, +table tr td:first-child { + text-align: var(--justify-normal); +} + +table tr:nth-child(even) { + background-color: var(--color-accent); +} + +/* Quotes */ +blockquote { + display: block; + font-size: x-large; + line-height: var(--line-height); + margin: 1rem auto; + max-width: var(--width-card-medium); + padding: 1.5rem 1rem; + text-align: var(--justify-important); +} + +blockquote footer { + color: var(--color-text-secondary); + display: block; + font-size: small; + line-height: var(--line-height); + padding: 1.5rem 0; +} + +/* Scrollbars */ +* { + scrollbar-width: thin; + scrollbar-color: var(--color-scrollbar) transparent; +} + +*::-webkit-scrollbar { + width: 5px; + height: 5px; +} + +*::-webkit-scrollbar-track { + background: transparent; +} + +*::-webkit-scrollbar-thumb { + background-color: var(--color-scrollbar); + border-radius: 10px; +} diff --git a/src/huesoporro/static/overlay.html b/src/huesoporro/static/overlay.html new file mode 100644 index 0000000..13197b2 --- /dev/null +++ b/src/huesoporro/static/overlay.html @@ -0,0 +1,172 @@ + + + + + Huesoporro speaks + + + + +
+

TTS

+
+ +
+ + + + +
+
+ +
+ Log +
+
+
+ + + diff --git a/src/markovbot_gui/bot_runner.py b/src/markovbot_gui/bot_runner.py deleted file mode 100644 index 9e82a38..0000000 --- a/src/markovbot_gui/bot_runner.py +++ /dev/null @@ -1,154 +0,0 @@ -import queue -import threading -from pathlib import Path -from traceback import print_exc - -from kivy.clock import Clock -from kivy.metrics import dp -from kivy.uix.boxlayout import BoxLayout -from kivy.uix.button import Button -from kivy.uix.textinput import TextInput -from loguru import logger - -from src.markovbot_gui.libs.markov_chain_bot import MarkovChain -from src.markovbot_gui.libs.settings import Settings - - -class QueueHandler: - def __init__(self, queue): - self.queue = queue - - def write(self, message): - self.queue.put(message) - - def flush(self): - pass - - -class BotRunner(BoxLayout): - def __init__(self, settings_path: Path, **kwargs): - super().__init__(**kwargs) - self.settings_path = settings_path - self.orientation = "vertical" - self.spacing = dp(10) - self.padding = dp(20) - self.bot_thread = None - self.log_queue: queue.Queue = queue.Queue() - self.settings = Settings.read(self.settings_path) - - self.queue_handler = QueueHandler(self.log_queue) - logger.remove() - logger.add( - self.queue_handler, - format="{time:YYYY-MM-DD HH:mm:ss} | {level} | {message}", - level=self.settings.log_level, - ) - - self.log_display = TextInput( - multiline=True, - readonly=True, - size_hint=(1, 1), - background_color=[0.1, 0.1, 0.1, 1], # Dark background - foreground_color=[0.9, 0.9, 0.9, 1], # Light text - ) - self.add_widget(self.log_display) - - # Create button layout - button_layout = BoxLayout( - orientation="horizontal", - size_hint=(1, None), - height=dp(40), - spacing=dp(10), - ) - - # Create start button - self.start_button = Button( - text="Start Bot", - size_hint=(None, None), - size=(dp(100), dp(40)), - ) - self.start_button.bind(on_release=self.start_bot) - button_layout.add_widget(self.start_button) - - # Create stop button - self.stop_button = Button( - text="Stop Bot", - size_hint=(None, None), - size=(dp(100), dp(40)), - disabled=True, - ) - self.stop_button.bind(on_release=self.stop_bot) - button_layout.add_widget(self.stop_button) - - # Create clear log button - self.clear_button = Button( - text="Clear Log", - size_hint=(None, None), - size=(dp(100), dp(40)), - ) - self.clear_button.bind(on_release=self.clear_log) - button_layout.add_widget(self.clear_button) - - self.add_widget(button_layout) - - Clock.schedule_interval(self.update_log, 0.1) - - def start_bot(self, instance=None): - try: - # Create and start bot thread - self.bot_thread = threading.Thread(target=self.run_bot_thread, daemon=True) - self.bot_thread.start() - - self.start_button.disabled = True - self.stop_button.disabled = False - - logger.info("Starting bot...") - - except Exception as e: # noqa: BLE001 - logger.error(f"Failed to start bot: {e}") - - def run_bot_thread(self): - try: - self.bot = MarkovChain(self.settings) - self.bot.run_bot() - except Exception: # noqa: BLE001 - logger.exception("Bot error") - finally: - Clock.schedule_once(lambda dt: self.reset_button_states(), 0) - - def stop_bot(self, _=None): - self.bot.stop_bot() - - # Wait for thread to finish - if self.bot_thread and self.bot_thread.is_alive(): - self.bot_thread.join(timeout=3.0) - - logger.info("Bot stopped") - self.reset_button_states() - - def reset_button_states(self): - self.start_button.disabled = False - self.stop_button.disabled = True - - def clear_log(self, instance=None): - self.log_display.text = "" - logger.info("Log cleared") - - def update_log(self, dt): - try: - while not self.log_queue.empty(): - message = self.log_queue.get_nowait() - if message.strip(): # Only add non-empty messages - self.log_display.text += message - - # Keep only the last 1000 lines to prevent memory issues - lines = self.log_display.text.split("\n") - if len(lines) > 1000: # noqa: PLR2004 - self.log_display.text = "\n".join(lines[-1000:]) + "\n" - - # Auto-scroll to bottom - self.log_display.cursor = (0, len(self.log_display.text)) - except queue.Empty: - pass - except Exception: # noqa: BLE001 - print_exc() diff --git a/src/markovbot_gui/config_window.py b/src/markovbot_gui/config_window.py deleted file mode 100644 index 8e51961..0000000 --- a/src/markovbot_gui/config_window.py +++ /dev/null @@ -1,161 +0,0 @@ -from pathlib import Path - -from kivy.clock import Clock -from kivy.metrics import dp -from kivy.uix.boxlayout import BoxLayout -from kivy.uix.button import Button -from kivy.uix.label import Label -from kivy.uix.popup import Popup -from kivy.uix.textinput import TextInput - -from src.markovbot_gui.libs.settings import Settings -from src.markovbot_gui.libs.timer import logger - - -class ConfigWindow(BoxLayout): - def __init__(self, config_path: Path, **kwargs): - super().__init__(**kwargs) - self.config_path = config_path - self.orientation = "vertical" - self.spacing = dp(10) - self.padding = dp(20) - - # Load existing configuration - default_config = { - "Host": "irc.chat.twitch.tv", - "Port": 6667, - "Channel": "#", - "Nickname": "", - "Authentication": "oauth:", - "DeniedUsers": ["StreamElements", "Nightbot", "Moobot", "Marbiebot"], - "Cooldown": 20, - "KeyLength": 2, - "MaxSentenceWordAmount": 25, - "MinSentenceWordAmount": -1, - "HelpMessageTimer": 60 * 60 * 5, # 18000 seconds, 5 hours - "AutomaticGenerationTimer": -1, - "WhisperCooldown": True, - "EnableGenerateCommand": True, - "SentenceSeparator": " - ", - "AllowGenerateParams": True, - } - - if config_path.exists(): - self.s = Settings.read(config_path) - else: - self.s = Settings(**default_config) # type: ignore[arg-type] - self.s.write(config_path) - - # Create widgets - # Channel input - channel_layout = BoxLayout( - orientation="horizontal", - size_hint_y=None, - height=dp(40), - ) - channel_label = Label(text="Channel:", size_hint_x=0.3) - self.channel_input = TextInput( - multiline=False, - size_hint_x=0.7, - text=self.s.channel, - ) - channel_layout.add_widget(channel_label) - channel_layout.add_widget(self.channel_input) - - # Nickname input - nickname_layout = BoxLayout( - orientation="horizontal", - size_hint_y=None, - height=dp(40), - ) - nickname_label = Label(text="Nickname:", size_hint_x=0.3) - self.nickname_input = TextInput( - multiline=False, - size_hint_x=0.7, - text=self.s.nickname, - ) - nickname_layout.add_widget(nickname_label) - nickname_layout.add_widget(self.nickname_input) - - # Authentication input - auth_layout = BoxLayout( - orientation="horizontal", - size_hint_y=None, - height=dp(40), - ) - auth_label = Label(text="Auth:", size_hint_x=0.3) - self.auth_input = TextInput( - multiline=False, - size_hint_x=0.7, - password=True, - text=self.s.authentication, - ) - auth_layout.add_widget(auth_label) - auth_layout.add_widget(self.auth_input) - - automatic_generation_label = Label(text="Automatic generation (seconds): ") - self.automatic_generation_input = TextInput( - multiline=False, - size_hint_x=0.7, - text=str(self.s.automatic_generation_timer), - ) - automatic_generation_layout = BoxLayout( - orientation="horizontal", - size_hint_y=None, - height=dp(40), - ) - automatic_generation_layout.add_widget(automatic_generation_label) - automatic_generation_layout.add_widget(self.automatic_generation_input) - - # Save button - save_button = Button( - text="Save", - size_hint=(None, None), - size=(dp(100), dp(40)), - pos_hint={"center_x": 0.5}, - ) - save_button.bind(on_release=self.save_config) - - # Add all widgets to the layout - self.add_widget(channel_layout) - self.add_widget(nickname_layout) - self.add_widget(auth_layout) - self.add_widget(automatic_generation_layout) - self.add_widget(save_button) - - def save_config(self, instance): - try: - self.s.channel = self.channel_input.text.strip() - self.s.nickname = self.nickname_input.text.strip() - self.s.authentication = self.auth_input.text.strip() - self.s.automatic_generation_timer = int( - self.automatic_generation_input.text - ) - if 0 < self.s.automatic_generation_timer < 29: # noqa: PLR2004 - raise ValueError( - "Value for 'Automatic generation' must be at least 30 seconds, " # noqa: EM101 - "or a negative number for no automatic generations." - ) - self.s.write(self.config_path) - - # Show success message - success_popup = Popup( - title="Success", - content=Label(text="Configuration saved successfully"), - size_hint=(None, None), - size=(dp(250), dp(100)), - ) - success_popup.open() - - Clock.schedule_once(success_popup.dismiss, 1) - - except Exception as e: # noqa: BLE001 - self.show_error_message(f"Failed to save configuration:\n{e!s}") - error_popup = Popup( - title="Error", - content=Label(text=f"Failed to save configuration:\n{e!s}"), - size_hint=(None, None), - size=(dp(400), dp(150)), - ) - error_popup.open() - logger.exception("Failed to save configuration") diff --git a/src/markovbot_gui/log_handler.py b/src/markovbot_gui/log_handler.py deleted file mode 100644 index ae7d0c4..0000000 --- a/src/markovbot_gui/log_handler.py +++ /dev/null @@ -1,10 +0,0 @@ -import logging - - -class LogHandler(logging.Handler): - def __init__(self, log_queue): - super().__init__() - self.log_queue = log_queue - - def emit(self, record): - self.log_queue.put(self.format(record)) diff --git a/src/markovbot_gui/main.py b/src/markovbot_gui/main.py deleted file mode 100644 index d7ffdee..0000000 --- a/src/markovbot_gui/main.py +++ /dev/null @@ -1,75 +0,0 @@ -import platformdirs -from kivy.app import App -from kivy.metrics import dp -from kivy.uix.boxlayout import BoxLayout -from kivy.uix.button import Button -from kivy.uix.popup import Popup -from kivy.uix.widget import Widget - -from src.markovbot_gui.bot_runner import BotRunner -from src.markovbot_gui.config_window import ConfigWindow - - -class BotApp(App): - def __init__(self, **kwargs): - super().__init__(**kwargs) - self.config_path = ( - platformdirs.user_config_path("markovbot_gui") / "settings.json" - ) - self.data_path = platformdirs.user_data_path("markovbot_gui") - - def run_bot(self, instance): - bot_runner = BotRunner(settings_path=self.config_path) - popup = Popup( - title=f"Bot runner, database available at {self.data_path}", - content=bot_runner, - size_hint=(None, None), - size=(dp(600), dp(600)), - auto_dismiss=False, - ) - popup.open() - - def run_config(self, instance): - config_window = ConfigWindow(config_path=self.config_path) - popup = Popup( - title=f"Bot configuration, available at {self.config_path}", - content=config_window, - size_hint=(None, None), - size=(dp(600), dp(400)), - auto_dismiss=False, - ) - - # Add close button - close_button = Button( - text="Close", - size_hint=(None, None), - size=(dp(100), dp(40)), - pos_hint={"center_x": 0.5}, - ) - close_button.bind(on_release=popup.dismiss) - config_window.add_widget(close_button) - - popup.open() - - def build(self): - widget = Widget() - - layout = BoxLayout(size_hint=(1, None), height=50) - - run_button = Button(text="Run bot") - run_button.bind(on_release=self.run_bot) - layout.add_widget(run_button) - - config_button = Button(text="Open config") - config_button.bind(on_release=self.run_config) - layout.add_widget(config_button) - - root = BoxLayout(orientation="vertical") - root.add_widget(widget) - root.add_widget(layout) - - return root - - -if __name__ == "__main__": - BotApp().run() diff --git a/uv.lock b/uv.lock index 3f9f0ad..b3092eb 100644 --- a/uv.lock +++ b/uv.lock @@ -1,7 +1,8 @@ version = 1 requires-python = ">=3.11" resolution-markers = [ - "python_full_version < '3.13'", + "python_full_version < '3.12'", + "python_full_version == '3.12.*'", "python_full_version >= '3.13'", ] @@ -23,6 +24,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643 }, ] +[[package]] +name = "anyio" +version = "4.6.2.post1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "idna" }, + { name = "sniffio" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9f/09/45b9b7a6d4e45c6bcb5bf61d19e3ab87df68e0601fa8c5293de3542546cc/anyio-4.6.2.post1.tar.gz", hash = "sha256:4c8bc31ccdb51c7f7bd251f51c609e038d63e34219b44aa86e47576389880b4c", size = 173422 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e4/f5/f2b75d2fc6f1a260f340f0e7c6a060f4dd2961cc16884ed851b0d18da06a/anyio-4.6.2.post1-py3-none-any.whl", hash = "sha256:6d170c36fba3bdd840c73d3868c1e777e33676a69c3a72cf0a0d5d6d8009b61d", size = 90377 }, +] + [[package]] name = "certifi" version = "2024.8.30" @@ -108,12 +122,198 @@ wheels = [ ] [[package]] -name = "docutils" -version = "0.21.2" +name = "editorconfig" +version = "0.12.4" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ae/ed/aefcc8cd0ba62a0560c3c18c33925362d46c6075480bfa4df87b28e169a9/docutils-0.21.2.tar.gz", hash = "sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f", size = 2204444 } +sdist = { url = "https://files.pythonhosted.org/packages/3d/85/7b5c2fac7fdc37d959fab714b13b9acb75884490dcc0e8b1dc5e64105084/EditorConfig-0.12.4.tar.gz", hash = "sha256:24857fa1793917dd9ccf0c7810a07e05404ce9b823521c7dce22a4fb5d125f80", size = 13278 } + +[[package]] +name = "faker" +version = "33.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "python-dateutil" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/1e/9f/012fd6049fc86029951cba5112d32c7ba076c4290d7e8873b0413655b808/faker-33.1.0.tar.gz", hash = "sha256:1c925fc0e86a51fc46648b504078c88d0cd48da1da2595c4e712841cab43a1e4", size = 1850515 } wheels = [ - { url = "https://files.pythonhosted.org/packages/8f/d7/9322c609343d929e75e7e5e6255e614fcc67572cfd083959cdef3b7aad79/docutils-0.21.2-py3-none-any.whl", hash = "sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2", size = 587408 }, + { url = "https://files.pythonhosted.org/packages/08/9c/2bba87fbfa42503ddd9653e3546ffc4ed18b14ecab7a07ee86491b886486/Faker-33.1.0-py3-none-any.whl", hash = "sha256:d30c5f0e2796b8970de68978365247657486eb0311c5abe88d0b895b68dff05d", size = 1889127 }, +] + +[[package]] +name = "fast-query-parsers" +version = "1.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/dd/20/3a00b889a196e8dc5bede2f168d4a14edc8b5bccc3978a9f497f0f863e79/fast_query_parsers-1.0.3.tar.gz", hash = "sha256:5200a9e02997ad51d4d76a60ea1b256a68a184b04359540eb6310a15013df68f", size = 25275 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/43/18/4179ac7064b4216ca42f2ed6f74e71254454acf2ec25ce6bb3ffbfda4aa6/fast_query_parsers-1.0.3-cp38-abi3-macosx_10_7_x86_64.whl", hash = "sha256:afbf71c1b4398dacfb9d84755eb026f8e759f68a066f1f3cc19e471fc342e74f", size = 766210 }, + { url = "https://files.pythonhosted.org/packages/c5/21/c8c160f61a740efc4577079eb5747a6b2cb8d1168a84a0bfda6044113768/fast_query_parsers-1.0.3-cp38-abi3-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:42f26875311d1b151c3406adfa39ec2db98df111a369d75f6fa243ec8462f147", size = 1466147 }, + { url = "https://files.pythonhosted.org/packages/51/5b/b10719598dbd14201271efd0b950c6a09efa0a3f6246fec3c192c6b7a8d2/fast_query_parsers-1.0.3-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:66630ad423b5b1f5709f82a4d8482cd6aa2f3fa73d2c779ff1877f25dee08d55", size = 764016 }, + { url = "https://files.pythonhosted.org/packages/75/06/8861197982909bec00b180527df1e0e9791715271bfb84c8be389b6bf077/fast_query_parsers-1.0.3-cp38-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a6e3d816c572a6fad1ae9b93713b2db0d3db6e8f594e035ad52361d668dd94a8", size = 729912 }, + { url = "https://files.pythonhosted.org/packages/f0/35/7a9a0c50588033edd9efba48f21e251dfcf77eaec2aff470988f622fbd3a/fast_query_parsers-1.0.3-cp38-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:0bdcc0ddb4cc69d823c2c0dedd8f5affc71042db39908ad2ca06261bf388cac6", size = 1003340 }, + { url = "https://files.pythonhosted.org/packages/41/9b/5a42ddd23b85357be6764e14daa607d9b16bc6a395aae2c1cc2077e0a11d/fast_query_parsers-1.0.3-cp38-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6720505f2d2a764c76bcc4f3730a9dff69d9871740e46264f6605d73f9ce3794", size = 969496 }, + { url = "https://files.pythonhosted.org/packages/c3/9f/4dfa29d74276fa07c40689bfaa3b21d057249314aeb20150f0f41373d16d/fast_query_parsers-1.0.3-cp38-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e947e7251769593da93832a10861f59565a46149fa117ebdf25377e7b2853936", size = 939972 }, + { url = "https://files.pythonhosted.org/packages/74/34/950b6d799839c11e93566aef426b67f0a446c4906e45e592026fde894459/fast_query_parsers-1.0.3-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:55a30b7cee0a53cddf9016b86fdad87221980d5a02a6126c491bd309755e6de9", size = 828557 }, + { url = "https://files.pythonhosted.org/packages/81/a8/ee95263abc9806c81d77be8a3420d1f4dde467a10030dde8b0fa0e63f700/fast_query_parsers-1.0.3-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9bc2b457caa38371df1a30cfdfc57bd9bfdf348367abdaf6f36533416a0b0e93", size = 863119 }, + { url = "https://files.pythonhosted.org/packages/05/d4/5eb8c9d400230b9a45a0ce47a443e9fe37b0902729f9440adef677af1f0d/fast_query_parsers-1.0.3-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:5736d3c32d6ba23995fa569fe572feabcfcfc30ac9e4709e94cff6f2c456a3d1", size = 911046 }, + { url = "https://files.pythonhosted.org/packages/f8/b8/bf5e44588f6ebd81d0c53ba49c79999dc54cb0fe81ad6dde6fed2cd45b56/fast_query_parsers-1.0.3-cp38-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:3a6377eb0c5b172fbc77c3f96deaf1e51708b4b96d27ce173658bf11c1c00b20", size = 962966 }, + { url = "https://files.pythonhosted.org/packages/6f/a9/132572b9f40c2635fdedb7a1cb6cedd9c880f8ffbbfdd6215ee493bb6936/fast_query_parsers-1.0.3-cp38-abi3-musllinux_1_2_i686.whl", hash = "sha256:7ca6be04f443a1b055e910ccad01b1d72212f269a530415df99a87c5f1e9c927", size = 965422 }, + { url = "https://files.pythonhosted.org/packages/ea/58/942327d3f2694b8f1a2fffaaaef1cc3147571852473a80070ebd6156a62e/fast_query_parsers-1.0.3-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a70d4d8852606f2dd5b798ab628b9d8dc6970ddfdd9e96f4543eb0cc89a74fb5", size = 967734 }, + { url = "https://files.pythonhosted.org/packages/0a/e3/21bc18edc003b54a2069eb854b9f92cacb5acc99e03c609487a23a673755/fast_query_parsers-1.0.3-cp38-abi3-win32.whl", hash = "sha256:14b3fab7e9a6ac1c1efaf66c3fd2a3fd1e25ede03ed14118035e530433830a11", size = 646366 }, + { url = "https://files.pythonhosted.org/packages/ae/4b/07fe4d7b5c458bdde9b0bfd8e8cb5762341af6c9727b43c2331c0cb0dbc3/fast_query_parsers-1.0.3-cp38-abi3-win_amd64.whl", hash = "sha256:21ae5f3a209aee7d3b84bdcdb33dd79f39fc8cb608b3ae8cfcb78123758c1a16", size = 689717 }, +] + +[[package]] +name = "ffmpeg" +version = "1.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f0/cc/3b7408b8ecf7c1d20ad480c3eaed7619857bf1054b690226e906fdf14258/ffmpeg-1.4.tar.gz", hash = "sha256:6931692c890ff21d39938433c2189747815dca0c60ddc7f9bb97f199dba0b5b9", size = 5055 } + +[[package]] +name = "ffmpeg-python" +version = "0.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "future" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/dd/5e/d5f9105d59c1325759d838af4e973695081fbbc97182baf73afc78dec266/ffmpeg-python-0.2.0.tar.gz", hash = "sha256:65225db34627c578ef0e11c8b1eb528bb35e024752f6f10b78c011f6f64c4127", size = 21543 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d7/0c/56be52741f75bad4dc6555991fabd2e07b432d333da82c11ad701123888a/ffmpeg_python-0.2.0-py3-none-any.whl", hash = "sha256:ac441a0404e053f8b6a1113a77c0f452f1cfc62f6344a769475ffdc0f56c23c5", size = 25024 }, +] + +[[package]] +name = "future" +version = "1.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a7/b2/4140c69c6a66432916b26158687e821ba631a4c9273c474343badf84d3ba/future-1.0.0.tar.gz", hash = "sha256:bd2968309307861edae1458a4f8a4f3598c03be43b97521076aebf5d94c07b05", size = 1228490 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/da/71/ae30dadffc90b9006d77af76b393cb9dfbfc9629f339fc1574a1c52e6806/future-1.0.0-py3-none-any.whl", hash = "sha256:929292d34f5872e70396626ef385ec22355a1fae8ad29e1a734c3e43f9fbc216", size = 491326 }, +] + +[[package]] +name = "gtts" +version = "2.5.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "requests" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/57/79/5ddb1dfcd663581d0d3fca34ccb1d8d841b47c22a24dc8dce416e3d87dfa/gtts-2.5.4.tar.gz", hash = "sha256:f5737b585f6442f677dbe8773424fd50697c75bdf3e36443585e30a8d48c1884", size = 24018 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e3/6c/8b8b1fdcaee7e268536f1bb00183a5894627726b54a9ddc6fc9909888447/gTTS-2.5.4-py3-none-any.whl", hash = "sha256:5dd579377f9f5546893bc26315ab1f846933dc27a054764b168f141065ca8436", size = 29184 }, +] + +[[package]] +name = "h11" +version = "0.14.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f5/38/3af3d3633a34a3316095b39c8e8fb4853a28a536e55d347bd8d8e9a14b03/h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d", size = 100418 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/95/04/ff642e65ad6b90db43e668d70ffb6736436c7ce41fcc549f4e9472234127/h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761", size = 58259 }, +] + +[[package]] +name = "httpcore" +version = "1.0.7" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "h11" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/6a/41/d7d0a89eb493922c37d343b607bc1b5da7f5be7e383740b4753ad8943e90/httpcore-1.0.7.tar.gz", hash = "sha256:8551cb62a169ec7162ac7be8d4817d561f60e08eaa485234898414bb5a8a0b4c", size = 85196 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/87/f5/72347bc88306acb359581ac4d52f23c0ef445b57157adedb9aee0cd689d2/httpcore-1.0.7-py3-none-any.whl", hash = "sha256:a3fff8f43dc260d5bd363d9f9cf1830fa3a458b332856f34282de498ed420edd", size = 78551 }, +] + +[[package]] +name = "httptools" +version = "0.6.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a7/9a/ce5e1f7e131522e6d3426e8e7a490b3a01f39a6696602e1c4f33f9e94277/httptools-0.6.4.tar.gz", hash = "sha256:4e93eee4add6493b59a5c514da98c939b244fce4a0d8879cd3f466562f4b7d5c", size = 240639 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7b/26/bb526d4d14c2774fe07113ca1db7255737ffbb119315839af2065abfdac3/httptools-0.6.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f47f8ed67cc0ff862b84a1189831d1d33c963fb3ce1ee0c65d3b0cbe7b711069", size = 199029 }, + { url = "https://files.pythonhosted.org/packages/a6/17/3e0d3e9b901c732987a45f4f94d4e2c62b89a041d93db89eafb262afd8d5/httptools-0.6.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0614154d5454c21b6410fdf5262b4a3ddb0f53f1e1721cfd59d55f32138c578a", size = 103492 }, + { url = "https://files.pythonhosted.org/packages/b7/24/0fe235d7b69c42423c7698d086d4db96475f9b50b6ad26a718ef27a0bce6/httptools-0.6.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8787367fbdfccae38e35abf7641dafc5310310a5987b689f4c32cc8cc3ee975", size = 462891 }, + { url = "https://files.pythonhosted.org/packages/b1/2f/205d1f2a190b72da6ffb5f41a3736c26d6fa7871101212b15e9b5cd8f61d/httptools-0.6.4-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40b0f7fe4fd38e6a507bdb751db0379df1e99120c65fbdc8ee6c1d044897a636", size = 459788 }, + { url = "https://files.pythonhosted.org/packages/6e/4c/d09ce0eff09057a206a74575ae8f1e1e2f0364d20e2442224f9e6612c8b9/httptools-0.6.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:40a5ec98d3f49904b9fe36827dcf1aadfef3b89e2bd05b0e35e94f97c2b14721", size = 433214 }, + { url = "https://files.pythonhosted.org/packages/3e/d2/84c9e23edbccc4a4c6f96a1b8d99dfd2350289e94f00e9ccc7aadde26fb5/httptools-0.6.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:dacdd3d10ea1b4ca9df97a0a303cbacafc04b5cd375fa98732678151643d4988", size = 434120 }, + { url = "https://files.pythonhosted.org/packages/d0/46/4d8e7ba9581416de1c425b8264e2cadd201eb709ec1584c381f3e98f51c1/httptools-0.6.4-cp311-cp311-win_amd64.whl", hash = "sha256:288cd628406cc53f9a541cfaf06041b4c71d751856bab45e3702191f931ccd17", size = 88565 }, + { url = "https://files.pythonhosted.org/packages/bb/0e/d0b71465c66b9185f90a091ab36389a7352985fe857e352801c39d6127c8/httptools-0.6.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:df017d6c780287d5c80601dafa31f17bddb170232d85c066604d8558683711a2", size = 200683 }, + { url = "https://files.pythonhosted.org/packages/e2/b8/412a9bb28d0a8988de3296e01efa0bd62068b33856cdda47fe1b5e890954/httptools-0.6.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:85071a1e8c2d051b507161f6c3e26155b5c790e4e28d7f236422dbacc2a9cc44", size = 104337 }, + { url = "https://files.pythonhosted.org/packages/9b/01/6fb20be3196ffdc8eeec4e653bc2a275eca7f36634c86302242c4fbb2760/httptools-0.6.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69422b7f458c5af875922cdb5bd586cc1f1033295aa9ff63ee196a87519ac8e1", size = 508796 }, + { url = "https://files.pythonhosted.org/packages/f7/d8/b644c44acc1368938317d76ac991c9bba1166311880bcc0ac297cb9d6bd7/httptools-0.6.4-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:16e603a3bff50db08cd578d54f07032ca1631450ceb972c2f834c2b860c28ea2", size = 510837 }, + { url = "https://files.pythonhosted.org/packages/52/d8/254d16a31d543073a0e57f1c329ca7378d8924e7e292eda72d0064987486/httptools-0.6.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ec4f178901fa1834d4a060320d2f3abc5c9e39766953d038f1458cb885f47e81", size = 485289 }, + { url = "https://files.pythonhosted.org/packages/5f/3c/4aee161b4b7a971660b8be71a92c24d6c64372c1ab3ae7f366b3680df20f/httptools-0.6.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f9eb89ecf8b290f2e293325c646a211ff1c2493222798bb80a530c5e7502494f", size = 489779 }, + { url = "https://files.pythonhosted.org/packages/12/b7/5cae71a8868e555f3f67a50ee7f673ce36eac970f029c0c5e9d584352961/httptools-0.6.4-cp312-cp312-win_amd64.whl", hash = "sha256:db78cb9ca56b59b016e64b6031eda5653be0589dba2b1b43453f6e8b405a0970", size = 88634 }, + { url = "https://files.pythonhosted.org/packages/94/a3/9fe9ad23fd35f7de6b91eeb60848986058bd8b5a5c1e256f5860a160cc3e/httptools-0.6.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ade273d7e767d5fae13fa637f4d53b6e961fb7fd93c7797562663f0171c26660", size = 197214 }, + { url = "https://files.pythonhosted.org/packages/ea/d9/82d5e68bab783b632023f2fa31db20bebb4e89dfc4d2293945fd68484ee4/httptools-0.6.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:856f4bc0478ae143bad54a4242fccb1f3f86a6e1be5548fecfd4102061b3a083", size = 102431 }, + { url = "https://files.pythonhosted.org/packages/96/c1/cb499655cbdbfb57b577734fde02f6fa0bbc3fe9fb4d87b742b512908dff/httptools-0.6.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:322d20ea9cdd1fa98bd6a74b77e2ec5b818abdc3d36695ab402a0de8ef2865a3", size = 473121 }, + { url = "https://files.pythonhosted.org/packages/af/71/ee32fd358f8a3bb199b03261f10921716990808a675d8160b5383487a317/httptools-0.6.4-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4d87b29bd4486c0093fc64dea80231f7c7f7eb4dc70ae394d70a495ab8436071", size = 473805 }, + { url = "https://files.pythonhosted.org/packages/8a/0a/0d4df132bfca1507114198b766f1737d57580c9ad1cf93c1ff673e3387be/httptools-0.6.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:342dd6946aa6bda4b8f18c734576106b8a31f2fe31492881a9a160ec84ff4bd5", size = 448858 }, + { url = "https://files.pythonhosted.org/packages/1e/6a/787004fdef2cabea27bad1073bf6a33f2437b4dbd3b6fb4a9d71172b1c7c/httptools-0.6.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4b36913ba52008249223042dca46e69967985fb4051951f94357ea681e1f5dc0", size = 452042 }, + { url = "https://files.pythonhosted.org/packages/4d/dc/7decab5c404d1d2cdc1bb330b1bf70e83d6af0396fd4fc76fc60c0d522bf/httptools-0.6.4-cp313-cp313-win_amd64.whl", hash = "sha256:28908df1b9bb8187393d5b5db91435ccc9c8e891657f9cbb42a2541b44c82fc8", size = 87682 }, +] + +[[package]] +name = "httpx" +version = "0.28.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "certifi" }, + { name = "httpcore" }, + { name = "idna" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/10/df/676b7cf674dd1bdc71a64ad393c89879f75e4a0ab8395165b498262ae106/httpx-0.28.0.tar.gz", hash = "sha256:0858d3bab51ba7e386637f22a61d8ccddaeec5f3fe4209da3a6168dbb91573e0", size = 141307 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8f/fb/a19866137577ba60c6d8b69498dc36be479b13ba454f691348ddf428f185/httpx-0.28.0-py3-none-any.whl", hash = "sha256:dc0b419a0cfeb6e8b34e85167c0da2671206f5095f1baa9663d23bcfd6b535fc", size = 73551 }, +] + +[[package]] +name = "huesoporro" +version = "0.1.2" +source = { virtual = "." } +dependencies = [ + { name = "ffmpeg" }, + { name = "ffmpeg-python" }, + { name = "gtts" }, + { name = "litestar", extra = ["standard"] }, + { name = "loguru" }, + { name = "nltk" }, + { name = "platformdirs" }, + { name = "pydantic" }, + { name = "pydantic-settings" }, + { name = "pyinstaller" }, + { name = "twitchwebsocket" }, +] + +[package.dev-dependencies] +dev = [ + { name = "mypy" }, + { name = "pyright" }, + { name = "ruff" }, +] + +[package.metadata] +requires-dist = [ + { name = "ffmpeg", specifier = ">=1.4" }, + { name = "ffmpeg-python", specifier = ">=0.2.0" }, + { name = "gtts", specifier = ">=2.5.4" }, + { name = "litestar", extras = ["standard"], specifier = ">=2.13.0" }, + { name = "loguru", specifier = ">=0.7.2" }, + { name = "nltk", specifier = ">=3.9.1" }, + { name = "platformdirs", specifier = ">=4.3.6" }, + { name = "pydantic", specifier = ">=2.9.2" }, + { name = "pydantic-settings", specifier = ">=2.6.0" }, + { name = "pyinstaller", specifier = ">=6.11.0" }, + { name = "twitchwebsocket", specifier = ">=1.2.1" }, +] + +[package.metadata.requires-dev] +dev = [ + { name = "mypy", specifier = ">=1.13.0" }, + { name = "pyright", specifier = ">=1.1.387" }, + { name = "ruff", specifier = ">=0.7.0" }, ] [[package]] @@ -125,6 +325,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442 }, ] +[[package]] +name = "jinja2" +version = "3.1.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markupsafe" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ed/55/39036716d19cab0747a5020fc7e907f362fbf48c984b14e62127f7e68e5d/jinja2-3.1.4.tar.gz", hash = "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369", size = 240245 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/31/80/3a54838c3fb461f6fec263ebf3a3a41771bd05190238de3486aae8540c36/jinja2-3.1.4-py3-none-any.whl", hash = "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d", size = 133271 }, +] + [[package]] name = "joblib" version = "1.4.2" @@ -135,88 +347,53 @@ wheels = [ ] [[package]] -name = "kivy" -version = "2.3.0" +name = "jsbeautifier" +version = "1.15.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "docutils" }, - { name = "kivy-deps-angle", marker = "sys_platform == 'win32'" }, - { name = "kivy-deps-glew", marker = "sys_platform == 'win32'" }, - { name = "kivy-deps-sdl2", marker = "sys_platform == 'win32'" }, - { name = "kivy-garden" }, - { name = "pygments" }, - { name = "pypiwin32", marker = "sys_platform == 'win32'" }, + { name = "editorconfig" }, + { name = "six" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/b0/8d/262e921d3cdfdca4c0fba6834235aa2abb6d569f781924a850d191cd23f1/Kivy-2.3.0.tar.gz", hash = "sha256:e8b8610c7f8ef6db908a139d369b247378f18105c96981e492eab2b4706c79d5", size = 23965268 } +sdist = { url = "https://files.pythonhosted.org/packages/69/3e/dd37e1a7223247e3ef94714abf572415b89c4e121c4af48e9e4c392e2ca0/jsbeautifier-1.15.1.tar.gz", hash = "sha256:ebd733b560704c602d744eafc839db60a1ee9326e30a2a80c4adb8718adc1b24", size = 75606 } + +[[package]] +name = "litestar" +version = "2.13.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "click" }, + { name = "httpx" }, + { name = "litestar-htmx" }, + { name = "msgspec" }, + { name = "multidict" }, + { name = "polyfactory" }, + { name = "pyyaml" }, + { name = "rich" }, + { name = "rich-click" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/53/0c/c17fc38194d63c538d65cf4bdfbfe6dfc476579c39732664858b6e5dbddc/litestar-2.13.0.tar.gz", hash = "sha256:51a3ab60b7bc8de2c126f3ad907c2ba6f9d22194bdf1be9df52253e57ed80f0e", size = 725824 } wheels = [ - { url = "https://files.pythonhosted.org/packages/78/a6/e5fc5e60ad6de274f758407d1aa7983680d9c50ee837ea0f0cf95755ab3c/Kivy-2.3.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ec36ab3b74a525fa463b61895d3a2d76e9e4d206641233defae0d604e75df7ad", size = 11303894 }, - { url = "https://files.pythonhosted.org/packages/78/ef/3beacbd7ee3f7b0352842f6debf40366ef7b17bbfa36dc5932ab54b97662/Kivy-2.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd3e923397779776ac97ad87a1b9dd603b7f1c911a6ae04f1d1658712eaaf7cb", size = 22727711 }, - { url = "https://files.pythonhosted.org/packages/21/c6/95f74cb29f7c9d191ab77f2b3c45443fd844317f813cd1398ca5a83629b4/Kivy-2.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7766baac2509d699df84b284579fa25ee31383d48893660cd8dba62081453a29", size = 22936178 }, - { url = "https://files.pythonhosted.org/packages/04/bb/3080154a7caac49a9853c11012f2e760924ef672166e4fdf4863a225f815/Kivy-2.3.0-cp311-cp311-win32.whl", hash = "sha256:d654aaec6ddf9ca0edf73abd79e6aea423299c825a7ac432df17b031adaa7900", size = 4255107 }, - { url = "https://files.pythonhosted.org/packages/41/7d/31896c7d9e99a2d2cc03ebbffcb80114fca318b2b9ea1963eec2e9ef62b3/Kivy-2.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:33dca85a520fe958e7134b96025b0625eb769adfb8829359959c8b314b7bc8d4", size = 4599341 }, - { url = "https://files.pythonhosted.org/packages/53/d2/7916fda4b13069db5b4e164bfce7d9f8dfaa03ad8b74ef95d75c9256968b/Kivy-2.3.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:7b1307521843d316265481d963344e85870ae5fa0c7d0881129749acfe61da7b", size = 11263537 }, - { url = "https://files.pythonhosted.org/packages/37/37/198850f839b56383b91471af9641b0fd6f70e188f2c6a0710147a1fbb426/Kivy-2.3.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:521105a4ca1db3e1203c3cdba4abe737533874d9c29bbfb1e1ae941238507440", size = 22652477 }, - { url = "https://files.pythonhosted.org/packages/ce/ba/3d9df24f504e23783f9be377f70f2cb8430ae1d67a437c5b8a5440d6d775/Kivy-2.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6672959894f652856d1dfcbcdcc09263de5f1cbed768b997dc8dcecab4385a4f", size = 23013742 }, - { url = "https://files.pythonhosted.org/packages/8a/18/e287b46d3e0998c3cd02b8d436e5cc0bf6c48ff9524f23715fb387501037/Kivy-2.3.0-cp312-cp312-win32.whl", hash = "sha256:cf0bccc95b1344b79fbfdf54155d40438490f9801fd77279f068a4f66db72e4e", size = 4224022 }, - { url = "https://files.pythonhosted.org/packages/f2/95/79dce0bbfb66895c68f0844d54212149665b8b1d5e1247151fa9514055d9/Kivy-2.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:710648c987a63e37c723e6622853efe0278767596631a38728a54474b2cb77f2", size = 4568579 }, + { url = "https://files.pythonhosted.org/packages/43/1b/31c8d75c98f69748c49d7b4196539d0e56b3c785f2b6b8e6b4686e6a934a/litestar-2.13.0-py3-none-any.whl", hash = "sha256:a40765644115639015a54e8cd7e7bdbe597a58d3f2d8f6d21afe9f343df43916", size = 555532 }, ] [package.optional-dependencies] -base = [ - { name = "docutils" }, - { name = "kivy-deps-angle", marker = "sys_platform == 'win32'" }, - { name = "kivy-deps-glew", marker = "sys_platform == 'win32'" }, - { name = "kivy-deps-sdl2", marker = "sys_platform == 'win32'" }, - { name = "pillow" }, - { name = "pygments" }, - { name = "pypiwin32", marker = "sys_platform == 'win32'" }, - { name = "requests" }, +standard = [ + { name = "fast-query-parsers" }, + { name = "jinja2" }, + { name = "jsbeautifier" }, + { name = "uvicorn", extra = ["standard"] }, + { name = "uvloop", marker = "sys_platform != 'win32'" }, ] [[package]] -name = "kivy-deps-angle" -version = "0.4.0" +name = "litestar-htmx" +version = "0.4.1" source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c9/0c/06ab03ee497d207dd8cb7588d1940be0b373a8ffdc7be3ec6d7e91c17ae2/litestar_htmx-0.4.1.tar.gz", hash = "sha256:ba2537008eb8cc18bfc8bee5cecb280924c7818bb1c066d79eae4b221696ca08", size = 101877 } wheels = [ - { url = "https://files.pythonhosted.org/packages/e8/1a/038c0844aa46fc49dcf8a657e890729f8960bfcac72e9c09c10cc18b32f2/kivy_deps.angle-0.4.0-cp311-cp311-win32.whl", hash = "sha256:c3899ff1f3886b80b155955bad07bfa33bbebd97718cdf46dfd788dc467124bc", size = 4588968 }, - { url = "https://files.pythonhosted.org/packages/c3/b1/d1ca22a7b18e7b2b90152a78a0c2d09a96fdb924f87be1914d70d9bee543/kivy_deps.angle-0.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:574381d4e66f3198bc48aa10f238e7a3816ad56b80ec939f5d56fb33a378d0b1", size = 5130936 }, - { url = "https://files.pythonhosted.org/packages/c1/89/bb8b9a0fee422972fcf38a406ee9d0b1636968d7d2b5e97aafea8fdec251/kivy_deps.angle-0.4.0-cp312-cp312-win32.whl", hash = "sha256:4fa7a6366899fba13f7624baf4645787165f45731db08d14557da29c12ee48f0", size = 4588969 }, - { url = "https://files.pythonhosted.org/packages/c7/f2/d1500b880d3079454af0f935408ddd37cfce4fd11f53d0917e169d478869/kivy_deps.angle-0.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:668e670d4afd2551af0af2c627ceb0feac884bd799fb6a3dff78fdbfa2ea0451", size = 5130935 }, - { url = "https://files.pythonhosted.org/packages/47/7e/ad805773fb76f07cb1bdf5147e66ba264a94f5ac54553cd9dee809a161bb/kivy_deps.angle-0.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:9afbf702f8bb9a993c48f39c018ca3b4d2ec381a5d3f82fe65bdaa6af0bba29b", size = 5133260 }, -] - -[[package]] -name = "kivy-deps-glew" -version = "0.3.1" -source = { registry = "https://pypi.org/simple" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/5d/4e/4300963410a49c4ab6eaadefce3e09c5e17421bc042b072862a27413b08c/kivy_deps.glew-0.3.1-cp311-cp311-win32.whl", hash = "sha256:ee2f80ef7ac70f4b61c50da8101b024308a8c59a57f7f25a6e09762b6c48f942", size = 126457 }, - { url = "https://files.pythonhosted.org/packages/d6/37/884034260818569547347cc2ba89780ff3f83a9ce6b9a894360c1d86e82c/kivy_deps.glew-0.3.1-cp311-cp311-win_amd64.whl", hash = "sha256:22e155ec59ce717387f5d8804811206d200a023ba3d0bc9bbf1393ee28d0053e", size = 123574 }, - { url = "https://files.pythonhosted.org/packages/2b/3b/a960053dccd627e4483db4765fa84318a831cbf3af648aee20297ae56815/kivy_deps.glew-0.3.1-cp312-cp312-win32.whl", hash = "sha256:b64ee4e445a04bc7c848c0261a6045fc2f0944cc05d7f953e3860b49f2703424", size = 126458 }, - { url = "https://files.pythonhosted.org/packages/ad/3a/37a0a051dd3c7298d9e149a489457a6196665444c1a1473ad4fa617e05af/kivy_deps.glew-0.3.1-cp312-cp312-win_amd64.whl", hash = "sha256:3acbbd30da05fc10c185b5d4bb75fbbc882a6ef2192963050c1c94d60a6e795a", size = 123573 }, - { url = "https://files.pythonhosted.org/packages/21/99/e3478c34afed7a820b3348ce7fefc53f2034fa340348dca57162695e69d9/kivy_deps.glew-0.3.1-cp313-cp313-win_amd64.whl", hash = "sha256:f4aa8322078359862ccd9e16e5cea61976d75fb43125d87922e20c916fa31a11", size = 123595 }, -] - -[[package]] -name = "kivy-deps-sdl2" -version = "0.7.0" -source = { registry = "https://pypi.org/simple" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/4d/d2/42a3f6f96c3a1a072fab5e0fbf58e7b27da5284023ae63383a5b55cb92cb/kivy_deps.sdl2-0.7.0-cp311-cp311-win32.whl", hash = "sha256:b727123d059c0c00c7d13cc1db8c8cfd0e48388cf24c11ec71cc6783811063c8", size = 3038046 }, - { url = "https://files.pythonhosted.org/packages/b7/ce/ca95180d14bb86cdbfe06774e6f5b2dd79bc8a88c525959e193dee81ec15/kivy_deps.sdl2-0.7.0-cp311-cp311-win_amd64.whl", hash = "sha256:fd946ca4e36a403bcafbe202033948c17f54bd5d28a343d98efd61f976822855", size = 3508367 }, - { url = "https://files.pythonhosted.org/packages/47/4c/f4bc3d3ae226137e391642286421cc20baa54f3c3c6560289380b1253b9f/kivy_deps.sdl2-0.7.0-cp312-cp312-win32.whl", hash = "sha256:2a8f23fe201dea368b47adfecf8fb9133315788d314ad32f33000254aa2388e4", size = 3038046 }, - { url = "https://files.pythonhosted.org/packages/92/36/f7ccf4dd8ac06e25284e1ae9d5c4d3b5de87fbc05fb86a8ca83252bc52b7/kivy_deps.sdl2-0.7.0-cp312-cp312-win_amd64.whl", hash = "sha256:e56d5d651f81545c24f920f6f6e5d67b4100802152521022ccde53e822c507a2", size = 3508366 }, -] - -[[package]] -name = "kivy-garden" -version = "0.1.5" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "requests" }, -] -wheels = [ - { url = "https://files.pythonhosted.org/packages/6a/55/cd1555bde62f809219cbc5d8a0836b0293399da2f4ba4e8ee84b6a7cc393/Kivy_Garden-0.1.5-py3-none-any.whl", hash = "sha256:ef50f44b96358cf10ac5665f27a4751bb34ef54051c54b93af891f80afe42929", size = 4623 }, + { url = "https://files.pythonhosted.org/packages/9d/99/3ea64a79a2f4fea5225ccd0128201a3b8eab5e216b8fba8b778b8c462f29/litestar_htmx-0.4.1-py3-none-any.whl", hash = "sha256:ba2a8ff1e210f21980735b9cde13d239a2b7c3627cb4aeb425d66f4a314d1a59", size = 9970 }, ] [[package]] @@ -245,46 +422,148 @@ wheels = [ ] [[package]] -name = "markovbot-gui" -version = "0.1.2" -source = { virtual = "." } +name = "markdown-it-py" +version = "3.0.0" +source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "kivy", extra = ["base"] }, - { name = "loguru" }, - { name = "nltk" }, - { name = "pillow" }, - { name = "platformdirs" }, - { name = "pydantic" }, - { name = "pydantic-settings" }, - { name = "pyinstaller" }, - { name = "twitchwebsocket" }, + { name = "mdurl" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/38/71/3b932df36c1a044d397a1f92d1cf91ee0a503d91e470cbd670aa66b07ed0/markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb", size = 74596 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", size = 87528 }, ] -[package.dev-dependencies] -dev = [ - { name = "mypy" }, - { name = "pyright" }, - { name = "ruff" }, +[[package]] +name = "markupsafe" +version = "3.0.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b2/97/5d42485e71dfc078108a86d6de8fa46db44a1a9295e89c5d6d4a06e23a62/markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0", size = 20537 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6b/28/bbf83e3f76936960b850435576dd5e67034e200469571be53f69174a2dfd/MarkupSafe-3.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d", size = 14353 }, + { url = "https://files.pythonhosted.org/packages/6c/30/316d194b093cde57d448a4c3209f22e3046c5bb2fb0820b118292b334be7/MarkupSafe-3.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93", size = 12392 }, + { url = "https://files.pythonhosted.org/packages/f2/96/9cdafba8445d3a53cae530aaf83c38ec64c4d5427d975c974084af5bc5d2/MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832", size = 23984 }, + { url = "https://files.pythonhosted.org/packages/f1/a4/aefb044a2cd8d7334c8a47d3fb2c9f328ac48cb349468cc31c20b539305f/MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84", size = 23120 }, + { url = "https://files.pythonhosted.org/packages/8d/21/5e4851379f88f3fad1de30361db501300d4f07bcad047d3cb0449fc51f8c/MarkupSafe-3.0.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca", size = 23032 }, + { url = "https://files.pythonhosted.org/packages/00/7b/e92c64e079b2d0d7ddf69899c98842f3f9a60a1ae72657c89ce2655c999d/MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798", size = 24057 }, + { url = "https://files.pythonhosted.org/packages/f9/ac/46f960ca323037caa0a10662ef97d0a4728e890334fc156b9f9e52bcc4ca/MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e", size = 23359 }, + { url = "https://files.pythonhosted.org/packages/69/84/83439e16197337b8b14b6a5b9c2105fff81d42c2a7c5b58ac7b62ee2c3b1/MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4", size = 23306 }, + { url = "https://files.pythonhosted.org/packages/9a/34/a15aa69f01e2181ed8d2b685c0d2f6655d5cca2c4db0ddea775e631918cd/MarkupSafe-3.0.2-cp311-cp311-win32.whl", hash = "sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d", size = 15094 }, + { url = "https://files.pythonhosted.org/packages/da/b8/3a3bd761922d416f3dc5d00bfbed11f66b1ab89a0c2b6e887240a30b0f6b/MarkupSafe-3.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b", size = 15521 }, + { url = "https://files.pythonhosted.org/packages/22/09/d1f21434c97fc42f09d290cbb6350d44eb12f09cc62c9476effdb33a18aa/MarkupSafe-3.0.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf", size = 14274 }, + { url = "https://files.pythonhosted.org/packages/6b/b0/18f76bba336fa5aecf79d45dcd6c806c280ec44538b3c13671d49099fdd0/MarkupSafe-3.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225", size = 12348 }, + { url = "https://files.pythonhosted.org/packages/e0/25/dd5c0f6ac1311e9b40f4af06c78efde0f3b5cbf02502f8ef9501294c425b/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028", size = 24149 }, + { url = "https://files.pythonhosted.org/packages/f3/f0/89e7aadfb3749d0f52234a0c8c7867877876e0a20b60e2188e9850794c17/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8", size = 23118 }, + { url = "https://files.pythonhosted.org/packages/d5/da/f2eeb64c723f5e3777bc081da884b414671982008c47dcc1873d81f625b6/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c", size = 22993 }, + { url = "https://files.pythonhosted.org/packages/da/0e/1f32af846df486dce7c227fe0f2398dc7e2e51d4a370508281f3c1c5cddc/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557", size = 24178 }, + { url = "https://files.pythonhosted.org/packages/c4/f6/bb3ca0532de8086cbff5f06d137064c8410d10779c4c127e0e47d17c0b71/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22", size = 23319 }, + { url = "https://files.pythonhosted.org/packages/a2/82/8be4c96ffee03c5b4a034e60a31294daf481e12c7c43ab8e34a1453ee48b/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48", size = 23352 }, + { url = "https://files.pythonhosted.org/packages/51/ae/97827349d3fcffee7e184bdf7f41cd6b88d9919c80f0263ba7acd1bbcb18/MarkupSafe-3.0.2-cp312-cp312-win32.whl", hash = "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30", size = 15097 }, + { url = "https://files.pythonhosted.org/packages/c1/80/a61f99dc3a936413c3ee4e1eecac96c0da5ed07ad56fd975f1a9da5bc630/MarkupSafe-3.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87", size = 15601 }, + { url = "https://files.pythonhosted.org/packages/83/0e/67eb10a7ecc77a0c2bbe2b0235765b98d164d81600746914bebada795e97/MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd", size = 14274 }, + { url = "https://files.pythonhosted.org/packages/2b/6d/9409f3684d3335375d04e5f05744dfe7e9f120062c9857df4ab490a1031a/MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430", size = 12352 }, + { url = "https://files.pythonhosted.org/packages/d2/f5/6eadfcd3885ea85fe2a7c128315cc1bb7241e1987443d78c8fe712d03091/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094", size = 24122 }, + { url = "https://files.pythonhosted.org/packages/0c/91/96cf928db8236f1bfab6ce15ad070dfdd02ed88261c2afafd4b43575e9e9/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396", size = 23085 }, + { url = "https://files.pythonhosted.org/packages/c2/cf/c9d56af24d56ea04daae7ac0940232d31d5a8354f2b457c6d856b2057d69/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79", size = 22978 }, + { url = "https://files.pythonhosted.org/packages/2a/9f/8619835cd6a711d6272d62abb78c033bda638fdc54c4e7f4272cf1c0962b/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a", size = 24208 }, + { url = "https://files.pythonhosted.org/packages/f9/bf/176950a1792b2cd2102b8ffeb5133e1ed984547b75db47c25a67d3359f77/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca", size = 23357 }, + { url = "https://files.pythonhosted.org/packages/ce/4f/9a02c1d335caabe5c4efb90e1b6e8ee944aa245c1aaaab8e8a618987d816/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c", size = 23344 }, + { url = "https://files.pythonhosted.org/packages/ee/55/c271b57db36f748f0e04a759ace9f8f759ccf22b4960c270c78a394f58be/MarkupSafe-3.0.2-cp313-cp313-win32.whl", hash = "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1", size = 15101 }, + { url = "https://files.pythonhosted.org/packages/29/88/07df22d2dd4df40aba9f3e402e6dc1b8ee86297dddbad4872bd5e7b0094f/MarkupSafe-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f", size = 15603 }, + { url = "https://files.pythonhosted.org/packages/62/6a/8b89d24db2d32d433dffcd6a8779159da109842434f1dd2f6e71f32f738c/MarkupSafe-3.0.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c", size = 14510 }, + { url = "https://files.pythonhosted.org/packages/7a/06/a10f955f70a2e5a9bf78d11a161029d278eeacbd35ef806c3fd17b13060d/MarkupSafe-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb", size = 12486 }, + { url = "https://files.pythonhosted.org/packages/34/cf/65d4a571869a1a9078198ca28f39fba5fbb910f952f9dbc5220afff9f5e6/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c", size = 25480 }, + { url = "https://files.pythonhosted.org/packages/0c/e3/90e9651924c430b885468b56b3d597cabf6d72be4b24a0acd1fa0e12af67/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d", size = 23914 }, + { url = "https://files.pythonhosted.org/packages/66/8c/6c7cf61f95d63bb866db39085150df1f2a5bd3335298f14a66b48e92659c/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe", size = 23796 }, + { url = "https://files.pythonhosted.org/packages/bb/35/cbe9238ec3f47ac9a7c8b3df7a808e7cb50fe149dc7039f5f454b3fba218/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5", size = 25473 }, + { url = "https://files.pythonhosted.org/packages/e6/32/7621a4382488aa283cc05e8984a9c219abad3bca087be9ec77e89939ded9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a", size = 24114 }, + { url = "https://files.pythonhosted.org/packages/0d/80/0985960e4b89922cb5a0bac0ed39c5b96cbc1a536a99f30e8c220a996ed9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9", size = 24098 }, + { url = "https://files.pythonhosted.org/packages/82/78/fedb03c7d5380df2427038ec8d973587e90561b2d90cd472ce9254cf348b/MarkupSafe-3.0.2-cp313-cp313t-win32.whl", hash = "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6", size = 15208 }, + { url = "https://files.pythonhosted.org/packages/4f/65/6079a46068dfceaeabb5dcad6d674f5f5c61a6fa5673746f42a9f4c233b3/MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f", size = 15739 }, ] -[package.metadata] -requires-dist = [ - { name = "kivy", extras = ["base"], specifier = ">=2.3.0" }, - { name = "loguru", specifier = ">=0.7.2" }, - { name = "nltk", specifier = ">=3.9.1" }, - { name = "pillow", specifier = ">=10.4.0" }, - { name = "platformdirs", specifier = ">=4.3.6" }, - { name = "pydantic", specifier = ">=2.9.2" }, - { name = "pydantic-settings", specifier = ">=2.6.0" }, - { name = "pyinstaller", specifier = ">=6.11.0" }, - { name = "twitchwebsocket", specifier = ">=1.2.1" }, +[[package]] +name = "mdurl" +version = "0.1.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979 }, ] -[package.metadata.requires-dev] -dev = [ - { name = "mypy", specifier = ">=1.13.0" }, - { name = "pyright", specifier = ">=1.1.387" }, - { name = "ruff", specifier = ">=0.7.0" }, +[[package]] +name = "msgspec" +version = "0.18.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5e/fb/42b1865063fddb14dbcbb6e74e0a366ecf1ba371c4948664dde0b0e10f95/msgspec-0.18.6.tar.gz", hash = "sha256:a59fc3b4fcdb972d09138cb516dbde600c99d07c38fd9372a6ef500d2d031b4e", size = 216757 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/15/20/278def3822dec807be1e2a734ba9547500ff06667be9dda00ab5d277d605/msgspec-0.18.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e77e56ffe2701e83a96e35770c6adb655ffc074d530018d1b584a8e635b4f36f", size = 200058 }, + { url = "https://files.pythonhosted.org/packages/25/8c/75bfafb040934dd3eb46234a2bd4d8fcc7b646f77440866f954b60e0886b/msgspec-0.18.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d5351afb216b743df4b6b147691523697ff3a2fc5f3d54f771e91219f5c23aaa", size = 189108 }, + { url = "https://files.pythonhosted.org/packages/0d/e6/5dd960a7678cbaf90dc910611a0e700775ee341876f029c3c987122afe84/msgspec-0.18.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c3232fabacef86fe8323cecbe99abbc5c02f7698e3f5f2e248e3480b66a3596b", size = 208138 }, + { url = "https://files.pythonhosted.org/packages/6a/73/1b2f991dc26899d2f999c938cbc82c858b3cb7e3ccaad317b32760dbe1da/msgspec-0.18.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e3b524df6ea9998bbc99ea6ee4d0276a101bcc1aa8d14887bb823914d9f60d07", size = 209538 }, + { url = "https://files.pythonhosted.org/packages/29/d4/2fb2d40b3bde566fd14bf02bf503eea20a912a02cdf7ff100629906c9094/msgspec-0.18.6-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:37f67c1d81272131895bb20d388dd8d341390acd0e192a55ab02d4d6468b434c", size = 213571 }, + { url = "https://files.pythonhosted.org/packages/59/5a/c2aeeefd78946713047637f0c422c0b8b31182eb9bbed0068e906cc8aca0/msgspec-0.18.6-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d0feb7a03d971c1c0353de1a8fe30bb6579c2dc5ccf29b5f7c7ab01172010492", size = 215785 }, + { url = "https://files.pythonhosted.org/packages/51/c6/0a8ae23c91ba1e6d58ddb089bba4ce8dad5815411b4a2bb40a5f15d2ab73/msgspec-0.18.6-cp311-cp311-win_amd64.whl", hash = "sha256:41cf758d3f40428c235c0f27bc6f322d43063bc32da7b9643e3f805c21ed57b4", size = 185877 }, + { url = "https://files.pythonhosted.org/packages/1d/b5/c8fbf1db814eb29eda402952374b594b2559419ba7ec6d0997a9e5687530/msgspec-0.18.6-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d86f5071fe33e19500920333c11e2267a31942d18fed4d9de5bc2fbab267d28c", size = 202109 }, + { url = "https://files.pythonhosted.org/packages/d7/9a/235d2dbab078a0b8e6f338205dc59be0b027ce000554ee6a9c41b19339e5/msgspec-0.18.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce13981bfa06f5eb126a3a5a38b1976bddb49a36e4f46d8e6edecf33ccf11df1", size = 190281 }, + { url = "https://files.pythonhosted.org/packages/0e/f2/f864ed36a8a62c26b57c3e08d212bd8f3d12a3ca3ef64600be5452aa3c82/msgspec-0.18.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e97dec6932ad5e3ee1e3c14718638ba333befc45e0661caa57033cd4cc489466", size = 210305 }, + { url = "https://files.pythonhosted.org/packages/73/16/dfef780ced7d690dd5497846ed242ef3e27e319d59d1ddaae816a4f2c15e/msgspec-0.18.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad237100393f637b297926cae1868b0d500f764ccd2f0623a380e2bcfb2809ca", size = 212510 }, + { url = "https://files.pythonhosted.org/packages/c1/90/f5b3a788c4b3d92190e3345d1afa3dd107d5f16b8194e1f61b72582ee9bd/msgspec-0.18.6-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:db1d8626748fa5d29bbd15da58b2d73af25b10aa98abf85aab8028119188ed57", size = 214844 }, + { url = "https://files.pythonhosted.org/packages/ce/0b/d4cc1b09f8dfcc6cc4cc9739c13a86e093fe70257b941ea9feb15df22996/msgspec-0.18.6-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:d70cb3d00d9f4de14d0b31d38dfe60c88ae16f3182988246a9861259c6722af6", size = 217113 }, + { url = "https://files.pythonhosted.org/packages/3f/76/30d8f152299f65c85c46a2cbeaf95ad1d18516b5ce730acdaef696d4cfe6/msgspec-0.18.6-cp312-cp312-win_amd64.whl", hash = "sha256:1003c20bfe9c6114cc16ea5db9c5466e49fae3d7f5e2e59cb70693190ad34da0", size = 187184 }, +] + +[[package]] +name = "multidict" +version = "6.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d6/be/504b89a5e9ca731cd47487e91c469064f8ae5af93b7259758dcfc2b9c848/multidict-6.1.0.tar.gz", hash = "sha256:22ae2ebf9b0c69d206c003e2f6a914ea33f0a932d4aa16f236afc049d9958f4a", size = 64002 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/93/13/df3505a46d0cd08428e4c8169a196131d1b0c4b515c3649829258843dde6/multidict-6.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:3efe2c2cb5763f2f1b275ad2bf7a287d3f7ebbef35648a9726e3b69284a4f3d6", size = 48570 }, + { url = "https://files.pythonhosted.org/packages/f0/e1/a215908bfae1343cdb72f805366592bdd60487b4232d039c437fe8f5013d/multidict-6.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c7053d3b0353a8b9de430a4f4b4268ac9a4fb3481af37dfe49825bf45ca24156", size = 29316 }, + { url = "https://files.pythonhosted.org/packages/70/0f/6dc70ddf5d442702ed74f298d69977f904960b82368532c88e854b79f72b/multidict-6.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:27e5fc84ccef8dfaabb09d82b7d179c7cf1a3fbc8a966f8274fcb4ab2eb4cadb", size = 29640 }, + { url = "https://files.pythonhosted.org/packages/d8/6d/9c87b73a13d1cdea30b321ef4b3824449866bd7f7127eceed066ccb9b9ff/multidict-6.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0e2b90b43e696f25c62656389d32236e049568b39320e2735d51f08fd362761b", size = 131067 }, + { url = "https://files.pythonhosted.org/packages/cc/1e/1b34154fef373371fd6c65125b3d42ff5f56c7ccc6bfff91b9b3c60ae9e0/multidict-6.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d83a047959d38a7ff552ff94be767b7fd79b831ad1cd9920662db05fec24fe72", size = 138507 }, + { url = "https://files.pythonhosted.org/packages/fb/e0/0bc6b2bac6e461822b5f575eae85da6aae76d0e2a79b6665d6206b8e2e48/multidict-6.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d1a9dd711d0877a1ece3d2e4fea11a8e75741ca21954c919406b44e7cf971304", size = 133905 }, + { url = "https://files.pythonhosted.org/packages/ba/af/73d13b918071ff9b2205fcf773d316e0f8fefb4ec65354bbcf0b10908cc6/multidict-6.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec2abea24d98246b94913b76a125e855eb5c434f7c46546046372fe60f666351", size = 129004 }, + { url = "https://files.pythonhosted.org/packages/74/21/23960627b00ed39643302d81bcda44c9444ebcdc04ee5bedd0757513f259/multidict-6.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4867cafcbc6585e4b678876c489b9273b13e9fff9f6d6d66add5e15d11d926cb", size = 121308 }, + { url = "https://files.pythonhosted.org/packages/8b/5c/cf282263ffce4a596ed0bb2aa1a1dddfe1996d6a62d08842a8d4b33dca13/multidict-6.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:5b48204e8d955c47c55b72779802b219a39acc3ee3d0116d5080c388970b76e3", size = 132608 }, + { url = "https://files.pythonhosted.org/packages/d7/3e/97e778c041c72063f42b290888daff008d3ab1427f5b09b714f5a8eff294/multidict-6.1.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:d8fff389528cad1618fb4b26b95550327495462cd745d879a8c7c2115248e399", size = 127029 }, + { url = "https://files.pythonhosted.org/packages/47/ac/3efb7bfe2f3aefcf8d103e9a7162572f01936155ab2f7ebcc7c255a23212/multidict-6.1.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:a7a9541cd308eed5e30318430a9c74d2132e9a8cb46b901326272d780bf2d423", size = 137594 }, + { url = "https://files.pythonhosted.org/packages/42/9b/6c6e9e8dc4f915fc90a9b7798c44a30773dea2995fdcb619870e705afe2b/multidict-6.1.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:da1758c76f50c39a2efd5e9859ce7d776317eb1dd34317c8152ac9251fc574a3", size = 134556 }, + { url = "https://files.pythonhosted.org/packages/1d/10/8e881743b26aaf718379a14ac58572a240e8293a1c9d68e1418fb11c0f90/multidict-6.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c943a53e9186688b45b323602298ab727d8865d8c9ee0b17f8d62d14b56f0753", size = 130993 }, + { url = "https://files.pythonhosted.org/packages/45/84/3eb91b4b557442802d058a7579e864b329968c8d0ea57d907e7023c677f2/multidict-6.1.0-cp311-cp311-win32.whl", hash = "sha256:90f8717cb649eea3504091e640a1b8568faad18bd4b9fcd692853a04475a4b80", size = 26405 }, + { url = "https://files.pythonhosted.org/packages/9f/0b/ad879847ecbf6d27e90a6eabb7eff6b62c129eefe617ea45eae7c1f0aead/multidict-6.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:82176036e65644a6cc5bd619f65f6f19781e8ec2e5330f51aa9ada7504cc1926", size = 28795 }, + { url = "https://files.pythonhosted.org/packages/fd/16/92057c74ba3b96d5e211b553895cd6dc7cc4d1e43d9ab8fafc727681ef71/multidict-6.1.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:b04772ed465fa3cc947db808fa306d79b43e896beb677a56fb2347ca1a49c1fa", size = 48713 }, + { url = "https://files.pythonhosted.org/packages/94/3d/37d1b8893ae79716179540b89fc6a0ee56b4a65fcc0d63535c6f5d96f217/multidict-6.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:6180c0ae073bddeb5a97a38c03f30c233e0a4d39cd86166251617d1bbd0af436", size = 29516 }, + { url = "https://files.pythonhosted.org/packages/a2/12/adb6b3200c363062f805275b4c1e656be2b3681aada66c80129932ff0bae/multidict-6.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:071120490b47aa997cca00666923a83f02c7fbb44f71cf7f136df753f7fa8761", size = 29557 }, + { url = "https://files.pythonhosted.org/packages/47/e9/604bb05e6e5bce1e6a5cf80a474e0f072e80d8ac105f1b994a53e0b28c42/multidict-6.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50b3a2710631848991d0bf7de077502e8994c804bb805aeb2925a981de58ec2e", size = 130170 }, + { url = "https://files.pythonhosted.org/packages/7e/13/9efa50801785eccbf7086b3c83b71a4fb501a4d43549c2f2f80b8787d69f/multidict-6.1.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b58c621844d55e71c1b7f7c498ce5aa6985d743a1a59034c57a905b3f153c1ef", size = 134836 }, + { url = "https://files.pythonhosted.org/packages/bf/0f/93808b765192780d117814a6dfcc2e75de6dcc610009ad408b8814dca3ba/multidict-6.1.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55b6d90641869892caa9ca42ff913f7ff1c5ece06474fbd32fb2cf6834726c95", size = 133475 }, + { url = "https://files.pythonhosted.org/packages/d3/c8/529101d7176fe7dfe1d99604e48d69c5dfdcadb4f06561f465c8ef12b4df/multidict-6.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b820514bfc0b98a30e3d85462084779900347e4d49267f747ff54060cc33925", size = 131049 }, + { url = "https://files.pythonhosted.org/packages/ca/0c/fc85b439014d5a58063e19c3a158a889deec399d47b5269a0f3b6a2e28bc/multidict-6.1.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:10a9b09aba0c5b48c53761b7c720aaaf7cf236d5fe394cd399c7ba662d5f9966", size = 120370 }, + { url = "https://files.pythonhosted.org/packages/db/46/d4416eb20176492d2258fbd47b4abe729ff3b6e9c829ea4236f93c865089/multidict-6.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1e16bf3e5fc9f44632affb159d30a437bfe286ce9e02754759be5536b169b305", size = 125178 }, + { url = "https://files.pythonhosted.org/packages/5b/46/73697ad7ec521df7de5531a32780bbfd908ded0643cbe457f981a701457c/multidict-6.1.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:76f364861c3bfc98cbbcbd402d83454ed9e01a5224bb3a28bf70002a230f73e2", size = 119567 }, + { url = "https://files.pythonhosted.org/packages/cd/ed/51f060e2cb0e7635329fa6ff930aa5cffa17f4c7f5c6c3ddc3500708e2f2/multidict-6.1.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:820c661588bd01a0aa62a1283f20d2be4281b086f80dad9e955e690c75fb54a2", size = 129822 }, + { url = "https://files.pythonhosted.org/packages/df/9e/ee7d1954b1331da3eddea0c4e08d9142da5f14b1321c7301f5014f49d492/multidict-6.1.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:0e5f362e895bc5b9e67fe6e4ded2492d8124bdf817827f33c5b46c2fe3ffaca6", size = 128656 }, + { url = "https://files.pythonhosted.org/packages/77/00/8538f11e3356b5d95fa4b024aa566cde7a38aa7a5f08f4912b32a037c5dc/multidict-6.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3ec660d19bbc671e3a6443325f07263be452c453ac9e512f5eb935e7d4ac28b3", size = 125360 }, + { url = "https://files.pythonhosted.org/packages/be/05/5d334c1f2462d43fec2363cd00b1c44c93a78c3925d952e9a71caf662e96/multidict-6.1.0-cp312-cp312-win32.whl", hash = "sha256:58130ecf8f7b8112cdb841486404f1282b9c86ccb30d3519faf301b2e5659133", size = 26382 }, + { url = "https://files.pythonhosted.org/packages/a3/bf/f332a13486b1ed0496d624bcc7e8357bb8053823e8cd4b9a18edc1d97e73/multidict-6.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:188215fc0aafb8e03341995e7c4797860181562380f81ed0a87ff455b70bf1f1", size = 28529 }, + { url = "https://files.pythonhosted.org/packages/22/67/1c7c0f39fe069aa4e5d794f323be24bf4d33d62d2a348acdb7991f8f30db/multidict-6.1.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:d569388c381b24671589335a3be6e1d45546c2988c2ebe30fdcada8457a31008", size = 48771 }, + { url = "https://files.pythonhosted.org/packages/3c/25/c186ee7b212bdf0df2519eacfb1981a017bda34392c67542c274651daf23/multidict-6.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:052e10d2d37810b99cc170b785945421141bf7bb7d2f8799d431e7db229c385f", size = 29533 }, + { url = "https://files.pythonhosted.org/packages/67/5e/04575fd837e0958e324ca035b339cea174554f6f641d3fb2b4f2e7ff44a2/multidict-6.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f90c822a402cb865e396a504f9fc8173ef34212a342d92e362ca498cad308e28", size = 29595 }, + { url = "https://files.pythonhosted.org/packages/d3/b2/e56388f86663810c07cfe4a3c3d87227f3811eeb2d08450b9e5d19d78876/multidict-6.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b225d95519a5bf73860323e633a664b0d85ad3d5bede6d30d95b35d4dfe8805b", size = 130094 }, + { url = "https://files.pythonhosted.org/packages/6c/ee/30ae9b4186a644d284543d55d491fbd4239b015d36b23fea43b4c94f7052/multidict-6.1.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:23bfd518810af7de1116313ebd9092cb9aa629beb12f6ed631ad53356ed6b86c", size = 134876 }, + { url = "https://files.pythonhosted.org/packages/84/c7/70461c13ba8ce3c779503c70ec9d0345ae84de04521c1f45a04d5f48943d/multidict-6.1.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c09fcfdccdd0b57867577b719c69e347a436b86cd83747f179dbf0cc0d4c1f3", size = 133500 }, + { url = "https://files.pythonhosted.org/packages/4a/9f/002af221253f10f99959561123fae676148dd730e2daa2cd053846a58507/multidict-6.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf6bea52ec97e95560af5ae576bdac3aa3aae0b6758c6efa115236d9e07dae44", size = 131099 }, + { url = "https://files.pythonhosted.org/packages/82/42/d1c7a7301d52af79d88548a97e297f9d99c961ad76bbe6f67442bb77f097/multidict-6.1.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57feec87371dbb3520da6192213c7d6fc892d5589a93db548331954de8248fd2", size = 120403 }, + { url = "https://files.pythonhosted.org/packages/68/f3/471985c2c7ac707547553e8f37cff5158030d36bdec4414cb825fbaa5327/multidict-6.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0c3f390dc53279cbc8ba976e5f8035eab997829066756d811616b652b00a23a3", size = 125348 }, + { url = "https://files.pythonhosted.org/packages/67/2c/e6df05c77e0e433c214ec1d21ddd203d9a4770a1f2866a8ca40a545869a0/multidict-6.1.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:59bfeae4b25ec05b34f1956eaa1cb38032282cd4dfabc5056d0a1ec4d696d3aa", size = 119673 }, + { url = "https://files.pythonhosted.org/packages/c5/cd/bc8608fff06239c9fb333f9db7743a1b2eafe98c2666c9a196e867a3a0a4/multidict-6.1.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:b2f59caeaf7632cc633b5cf6fc449372b83bbdf0da4ae04d5be36118e46cc0aa", size = 129927 }, + { url = "https://files.pythonhosted.org/packages/44/8e/281b69b7bc84fc963a44dc6e0bbcc7150e517b91df368a27834299a526ac/multidict-6.1.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:37bb93b2178e02b7b618893990941900fd25b6b9ac0fa49931a40aecdf083fe4", size = 128711 }, + { url = "https://files.pythonhosted.org/packages/12/a4/63e7cd38ed29dd9f1881d5119f272c898ca92536cdb53ffe0843197f6c85/multidict-6.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4e9f48f58c2c523d5a06faea47866cd35b32655c46b443f163d08c6d0ddb17d6", size = 125519 }, + { url = "https://files.pythonhosted.org/packages/38/e0/4f5855037a72cd8a7a2f60a3952d9aa45feedb37ae7831642102604e8a37/multidict-6.1.0-cp313-cp313-win32.whl", hash = "sha256:3a37ffb35399029b45c6cc33640a92bef403c9fd388acce75cdc88f58bd19a81", size = 26426 }, + { url = "https://files.pythonhosted.org/packages/7e/a5/17ee3a4db1e310b7405f5d25834460073a8ccd86198ce044dfaf69eac073/multidict-6.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:e9aa71e15d9d9beaad2c6b9319edcdc0a49a43ef5c0a4c8265ca9ee7d6c67774", size = 28531 }, + { url = "https://files.pythonhosted.org/packages/99/b7/b9e70fde2c0f0c9af4cc5277782a89b66d35948ea3369ec9f598358c3ac5/multidict-6.1.0-py3-none-any.whl", hash = "sha256:48e171e52d1c4d33888e529b999e5900356b9ae588c2f09a52dcefb158b27506", size = 10051 }, ] [[package]] @@ -366,47 +645,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/55/26/d0ad8b448476d0a1e8d3ea5622dc77b916db84c6aa3cb1e1c0965af948fc/pefile-2023.2.7-py3-none-any.whl", hash = "sha256:da185cd2af68c08a6cd4481f7325ed600a88f6a813bad9dea07ab3ef73d8d8d6", size = 71791 }, ] -[[package]] -name = "pillow" -version = "10.4.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/cd/74/ad3d526f3bf7b6d3f408b73fde271ec69dfac8b81341a318ce825f2b3812/pillow-10.4.0.tar.gz", hash = "sha256:166c1cd4d24309b30d61f79f4a9114b7b2313d7450912277855ff5dfd7cd4a06", size = 46555059 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a7/62/c9449f9c3043c37f73e7487ec4ef0c03eb9c9afc91a92b977a67b3c0bbc5/pillow-10.4.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:0a9ec697746f268507404647e531e92889890a087e03681a3606d9b920fbee3c", size = 3509265 }, - { url = "https://files.pythonhosted.org/packages/f4/5f/491dafc7bbf5a3cc1845dc0430872e8096eb9e2b6f8161509d124594ec2d/pillow-10.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dfe91cb65544a1321e631e696759491ae04a2ea11d36715eca01ce07284738be", size = 3375655 }, - { url = "https://files.pythonhosted.org/packages/73/d5/c4011a76f4207a3c151134cd22a1415741e42fa5ddecec7c0182887deb3d/pillow-10.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5dc6761a6efc781e6a1544206f22c80c3af4c8cf461206d46a1e6006e4429ff3", size = 4340304 }, - { url = "https://files.pythonhosted.org/packages/ac/10/c67e20445a707f7a610699bba4fe050583b688d8cd2d202572b257f46600/pillow-10.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e84b6cc6a4a3d76c153a6b19270b3526a5a8ed6b09501d3af891daa2a9de7d6", size = 4452804 }, - { url = "https://files.pythonhosted.org/packages/a9/83/6523837906d1da2b269dee787e31df3b0acb12e3d08f024965a3e7f64665/pillow-10.4.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:bbc527b519bd3aa9d7f429d152fea69f9ad37c95f0b02aebddff592688998abe", size = 4365126 }, - { url = "https://files.pythonhosted.org/packages/ba/e5/8c68ff608a4203085158cff5cc2a3c534ec384536d9438c405ed6370d080/pillow-10.4.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:76a911dfe51a36041f2e756b00f96ed84677cdeb75d25c767f296c1c1eda1319", size = 4533541 }, - { url = "https://files.pythonhosted.org/packages/f4/7c/01b8dbdca5bc6785573f4cee96e2358b0918b7b2c7b60d8b6f3abf87a070/pillow-10.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:59291fb29317122398786c2d44427bbd1a6d7ff54017075b22be9d21aa59bd8d", size = 4471616 }, - { url = "https://files.pythonhosted.org/packages/c8/57/2899b82394a35a0fbfd352e290945440e3b3785655a03365c0ca8279f351/pillow-10.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:416d3a5d0e8cfe4f27f574362435bc9bae57f679a7158e0096ad2beb427b8696", size = 4600802 }, - { url = "https://files.pythonhosted.org/packages/4d/d7/a44f193d4c26e58ee5d2d9db3d4854b2cfb5b5e08d360a5e03fe987c0086/pillow-10.4.0-cp311-cp311-win32.whl", hash = "sha256:7086cc1d5eebb91ad24ded9f58bec6c688e9f0ed7eb3dbbf1e4800280a896496", size = 2235213 }, - { url = "https://files.pythonhosted.org/packages/c1/d0/5866318eec2b801cdb8c82abf190c8343d8a1cd8bf5a0c17444a6f268291/pillow-10.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:cbed61494057c0f83b83eb3a310f0bf774b09513307c434d4366ed64f4128a91", size = 2554498 }, - { url = "https://files.pythonhosted.org/packages/d4/c8/310ac16ac2b97e902d9eb438688de0d961660a87703ad1561fd3dfbd2aa0/pillow-10.4.0-cp311-cp311-win_arm64.whl", hash = "sha256:f5f0c3e969c8f12dd2bb7e0b15d5c468b51e5017e01e2e867335c81903046a22", size = 2243219 }, - { url = "https://files.pythonhosted.org/packages/05/cb/0353013dc30c02a8be34eb91d25e4e4cf594b59e5a55ea1128fde1e5f8ea/pillow-10.4.0-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:673655af3eadf4df6b5457033f086e90299fdd7a47983a13827acf7459c15d94", size = 3509350 }, - { url = "https://files.pythonhosted.org/packages/e7/cf/5c558a0f247e0bf9cec92bff9b46ae6474dd736f6d906315e60e4075f737/pillow-10.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:866b6942a92f56300012f5fbac71f2d610312ee65e22f1aa2609e491284e5597", size = 3374980 }, - { url = "https://files.pythonhosted.org/packages/84/48/6e394b86369a4eb68b8a1382c78dc092245af517385c086c5094e3b34428/pillow-10.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:29dbdc4207642ea6aad70fbde1a9338753d33fb23ed6956e706936706f52dd80", size = 4343799 }, - { url = "https://files.pythonhosted.org/packages/3b/f3/a8c6c11fa84b59b9df0cd5694492da8c039a24cd159f0f6918690105c3be/pillow-10.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf2342ac639c4cf38799a44950bbc2dfcb685f052b9e262f446482afaf4bffca", size = 4459973 }, - { url = "https://files.pythonhosted.org/packages/7d/1b/c14b4197b80150fb64453585247e6fb2e1d93761fa0fa9cf63b102fde822/pillow-10.4.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:f5b92f4d70791b4a67157321c4e8225d60b119c5cc9aee8ecf153aace4aad4ef", size = 4370054 }, - { url = "https://files.pythonhosted.org/packages/55/77/40daddf677897a923d5d33329acd52a2144d54a9644f2a5422c028c6bf2d/pillow-10.4.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:86dcb5a1eb778d8b25659d5e4341269e8590ad6b4e8b44d9f4b07f8d136c414a", size = 4539484 }, - { url = "https://files.pythonhosted.org/packages/40/54/90de3e4256b1207300fb2b1d7168dd912a2fb4b2401e439ba23c2b2cabde/pillow-10.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:780c072c2e11c9b2c7ca37f9a2ee8ba66f44367ac3e5c7832afcfe5104fd6d1b", size = 4477375 }, - { url = "https://files.pythonhosted.org/packages/13/24/1bfba52f44193860918ff7c93d03d95e3f8748ca1de3ceaf11157a14cf16/pillow-10.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:37fb69d905be665f68f28a8bba3c6d3223c8efe1edf14cc4cfa06c241f8c81d9", size = 4608773 }, - { url = "https://files.pythonhosted.org/packages/55/04/5e6de6e6120451ec0c24516c41dbaf80cce1b6451f96561235ef2429da2e/pillow-10.4.0-cp312-cp312-win32.whl", hash = "sha256:7dfecdbad5c301d7b5bde160150b4db4c659cee2b69589705b6f8a0c509d9f42", size = 2235690 }, - { url = "https://files.pythonhosted.org/packages/74/0a/d4ce3c44bca8635bd29a2eab5aa181b654a734a29b263ca8efe013beea98/pillow-10.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:1d846aea995ad352d4bdcc847535bd56e0fd88d36829d2c90be880ef1ee4668a", size = 2554951 }, - { url = "https://files.pythonhosted.org/packages/b5/ca/184349ee40f2e92439be9b3502ae6cfc43ac4b50bc4fc6b3de7957563894/pillow-10.4.0-cp312-cp312-win_arm64.whl", hash = "sha256:e553cad5179a66ba15bb18b353a19020e73a7921296a7979c4a2b7f6a5cd57f9", size = 2243427 }, - { url = "https://files.pythonhosted.org/packages/c3/00/706cebe7c2c12a6318aabe5d354836f54adff7156fd9e1bd6c89f4ba0e98/pillow-10.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8bc1a764ed8c957a2e9cacf97c8b2b053b70307cf2996aafd70e91a082e70df3", size = 3525685 }, - { url = "https://files.pythonhosted.org/packages/cf/76/f658cbfa49405e5ecbfb9ba42d07074ad9792031267e782d409fd8fe7c69/pillow-10.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6209bb41dc692ddfee4942517c19ee81b86c864b626dbfca272ec0f7cff5d9fb", size = 3374883 }, - { url = "https://files.pythonhosted.org/packages/46/2b/99c28c4379a85e65378211971c0b430d9c7234b1ec4d59b2668f6299e011/pillow-10.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bee197b30783295d2eb680b311af15a20a8b24024a19c3a26431ff83eb8d1f70", size = 4339837 }, - { url = "https://files.pythonhosted.org/packages/f1/74/b1ec314f624c0c43711fdf0d8076f82d9d802afd58f1d62c2a86878e8615/pillow-10.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ef61f5dd14c300786318482456481463b9d6b91ebe5ef12f405afbba77ed0be", size = 4455562 }, - { url = "https://files.pythonhosted.org/packages/4a/2a/4b04157cb7b9c74372fa867096a1607e6fedad93a44deeff553ccd307868/pillow-10.4.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:297e388da6e248c98bc4a02e018966af0c5f92dfacf5a5ca22fa01cb3179bca0", size = 4366761 }, - { url = "https://files.pythonhosted.org/packages/ac/7b/8f1d815c1a6a268fe90481232c98dd0e5fa8c75e341a75f060037bd5ceae/pillow-10.4.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:e4db64794ccdf6cb83a59d73405f63adbe2a1887012e308828596100a0b2f6cc", size = 4536767 }, - { url = "https://files.pythonhosted.org/packages/e5/77/05fa64d1f45d12c22c314e7b97398ffb28ef2813a485465017b7978b3ce7/pillow-10.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bd2880a07482090a3bcb01f4265f1936a903d70bc740bfcb1fd4e8a2ffe5cf5a", size = 4477989 }, - { url = "https://files.pythonhosted.org/packages/12/63/b0397cfc2caae05c3fb2f4ed1b4fc4fc878f0243510a7a6034ca59726494/pillow-10.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4b35b21b819ac1dbd1233317adeecd63495f6babf21b7b2512d244ff6c6ce309", size = 4610255 }, - { url = "https://files.pythonhosted.org/packages/7b/f9/cfaa5082ca9bc4a6de66ffe1c12c2d90bf09c309a5f52b27759a596900e7/pillow-10.4.0-cp313-cp313-win32.whl", hash = "sha256:551d3fd6e9dc15e4c1eb6fc4ba2b39c0c7933fa113b220057a34f4bb3268a060", size = 2235603 }, - { url = "https://files.pythonhosted.org/packages/01/6a/30ff0eef6e0c0e71e55ded56a38d4859bf9d3634a94a88743897b5f96936/pillow-10.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:030abdbe43ee02e0de642aee345efa443740aa4d828bfe8e2eb11922ea6a21ea", size = 2554972 }, - { url = "https://files.pythonhosted.org/packages/48/2c/2e0a52890f269435eee38b21c8218e102c621fe8d8df8b9dd06fabf879ba/pillow-10.4.0-cp313-cp313-win_arm64.whl", hash = "sha256:5b001114dd152cfd6b23befeb28d7aee43553e2402c9f159807bf55f33af8a8d", size = 2243375 }, -] - [[package]] name = "platformdirs" version = "4.3.6" @@ -416,6 +654,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/3c/a6/bc1012356d8ece4d66dd75c4b9fc6c1f6650ddd5991e421177d9f8f671be/platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb", size = 18439 }, ] +[[package]] +name = "polyfactory" +version = "2.18.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "faker" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/4f/0c/12b4e50ab0d165f34ae65fbf26bd93debc8d6c4e00ea62a0b086c9eb58d0/polyfactory-2.18.1.tar.gz", hash = "sha256:17c9db18afe4fb8d7dd8e5ba296e69da0fcf7d0f3b63d1840eb10d135aed5aad", size = 185001 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/80/e0bfd57b64009f476112fa81056eb64d9c95bbbbf5bb3257ad010f89907a/polyfactory-2.18.1-py3-none-any.whl", hash = "sha256:1a2b0715e08bfe9f14abc838fc013ab8772cb90e66f2e601e15e1127f0bc1b18", size = 59335 }, +] + [[package]] name = "pydantic" version = "2.9.2" @@ -540,18 +791,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/57/b4/23338112c76750f494a2fded981d40ebd723585b2b6eadde6a821ddc7208/pyinstaller_hooks_contrib-2024.9-py3-none-any.whl", hash = "sha256:1ddf9ba21d586afa84e505bb5c65fca10b22500bf3fdb89ee2965b99da53b891", size = 336956 }, ] -[[package]] -name = "pypiwin32" -version = "223" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "pywin32" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/13/e8/4f38eb30c4dae36634a53c5b2cd73b517ea3607e10d00f61f2494449cec0/pypiwin32-223.tar.gz", hash = "sha256:71be40c1fbd28594214ecaecb58e7aa8b708eabfa0125c8a109ebd51edbd776a", size = 622 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d0/1b/2f292bbd742e369a100c91faa0483172cd91a1a422a6692055ac920946c5/pypiwin32-223-py3-none-any.whl", hash = "sha256:67adf399debc1d5d14dffc1ab5acacb800da569754fafdc576b2a039485aa775", size = 1674 }, -] - [[package]] name = "pyright" version = "1.1.387" @@ -565,6 +804,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/a0/18/c497df36641b0572f5bd59ae147b08ccaa6b8086397d50e1af97cc2ddcf6/pyright-1.1.387-py3-none-any.whl", hash = "sha256:6a1f495a261a72e12ad17e20d1ae3df4511223c773b19407cfa006229b1b08a5", size = 18577 }, ] +[[package]] +name = "python-dateutil" +version = "2.9.0.post0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892 }, +] + [[package]] name = "python-dotenv" version = "1.0.1" @@ -574,22 +825,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/6a/3e/b68c118422ec867fa7ab88444e1274aa40681c606d59ac27de5a5588f082/python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a", size = 19863 }, ] -[[package]] -name = "pywin32" -version = "308" -source = { registry = "https://pypi.org/simple" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/eb/e2/02652007469263fe1466e98439831d65d4ca80ea1a2df29abecedf7e47b7/pywin32-308-cp311-cp311-win32.whl", hash = "sha256:5d8c8015b24a7d6855b1550d8e660d8daa09983c80e5daf89a273e5c6fb5095a", size = 5928156 }, - { url = "https://files.pythonhosted.org/packages/48/ef/f4fb45e2196bc7ffe09cad0542d9aff66b0e33f6c0954b43e49c33cad7bd/pywin32-308-cp311-cp311-win_amd64.whl", hash = "sha256:575621b90f0dc2695fec346b2d6302faebd4f0f45c05ea29404cefe35d89442b", size = 6559559 }, - { url = "https://files.pythonhosted.org/packages/79/ef/68bb6aa865c5c9b11a35771329e95917b5559845bd75b65549407f9fc6b4/pywin32-308-cp311-cp311-win_arm64.whl", hash = "sha256:100a5442b7332070983c4cd03f2e906a5648a5104b8a7f50175f7906efd16bb6", size = 7972495 }, - { url = "https://files.pythonhosted.org/packages/00/7c/d00d6bdd96de4344e06c4afbf218bc86b54436a94c01c71a8701f613aa56/pywin32-308-cp312-cp312-win32.whl", hash = "sha256:587f3e19696f4bf96fde9d8a57cec74a57021ad5f204c9e627e15c33ff568897", size = 5939729 }, - { url = "https://files.pythonhosted.org/packages/21/27/0c8811fbc3ca188f93b5354e7c286eb91f80a53afa4e11007ef661afa746/pywin32-308-cp312-cp312-win_amd64.whl", hash = "sha256:00b3e11ef09ede56c6a43c71f2d31857cf7c54b0ab6e78ac659497abd2834f47", size = 6543015 }, - { url = "https://files.pythonhosted.org/packages/9d/0f/d40f8373608caed2255781a3ad9a51d03a594a1248cd632d6a298daca693/pywin32-308-cp312-cp312-win_arm64.whl", hash = "sha256:9b4de86c8d909aed15b7011182c8cab38c8850de36e6afb1f0db22b8959e3091", size = 7976033 }, - { url = "https://files.pythonhosted.org/packages/a9/a4/aa562d8935e3df5e49c161b427a3a2efad2ed4e9cf81c3de636f1fdddfd0/pywin32-308-cp313-cp313-win32.whl", hash = "sha256:1c44539a37a5b7b21d02ab34e6a4d314e0788f1690d65b48e9b0b89f31abbbed", size = 5938579 }, - { url = "https://files.pythonhosted.org/packages/c7/50/b0efb8bb66210da67a53ab95fd7a98826a97ee21f1d22949863e6d588b22/pywin32-308-cp313-cp313-win_amd64.whl", hash = "sha256:fd380990e792eaf6827fcb7e187b2b4b1cede0585e3d0c9e84201ec27b9905e4", size = 6542056 }, - { url = "https://files.pythonhosted.org/packages/26/df/2b63e3e4f2df0224f8aaf6d131f54fe4e8c96400eb9df563e2aae2e1a1f9/pywin32-308-cp313-cp313-win_arm64.whl", hash = "sha256:ef313c46d4c18dfb82a2431e3051ac8f112ccee1a34f29c263c583c568db63cd", size = 7974986 }, -] - [[package]] name = "pywin32-ctypes" version = "0.2.3" @@ -599,6 +834,41 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/de/3d/8161f7711c017e01ac9f008dfddd9410dff3674334c233bde66e7ba65bbf/pywin32_ctypes-0.2.3-py3-none-any.whl", hash = "sha256:8a1513379d709975552d202d942d9837758905c8d01eb82b8bcc30918929e7b8", size = 30756 }, ] +[[package]] +name = "pyyaml" +version = "6.0.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/54/ed/79a089b6be93607fa5cdaedf301d7dfb23af5f25c398d5ead2525b063e17/pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e", size = 130631 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f8/aa/7af4e81f7acba21a4c6be026da38fd2b872ca46226673c89a758ebdc4fd2/PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774", size = 184612 }, + { url = "https://files.pythonhosted.org/packages/8b/62/b9faa998fd185f65c1371643678e4d58254add437edb764a08c5a98fb986/PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee", size = 172040 }, + { url = "https://files.pythonhosted.org/packages/ad/0c/c804f5f922a9a6563bab712d8dcc70251e8af811fce4524d57c2c0fd49a4/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c", size = 736829 }, + { url = "https://files.pythonhosted.org/packages/51/16/6af8d6a6b210c8e54f1406a6b9481febf9c64a3109c541567e35a49aa2e7/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317", size = 764167 }, + { url = "https://files.pythonhosted.org/packages/75/e4/2c27590dfc9992f73aabbeb9241ae20220bd9452df27483b6e56d3975cc5/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85", size = 762952 }, + { url = "https://files.pythonhosted.org/packages/9b/97/ecc1abf4a823f5ac61941a9c00fe501b02ac3ab0e373c3857f7d4b83e2b6/PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4", size = 735301 }, + { url = "https://files.pythonhosted.org/packages/45/73/0f49dacd6e82c9430e46f4a027baa4ca205e8b0a9dce1397f44edc23559d/PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e", size = 756638 }, + { url = "https://files.pythonhosted.org/packages/22/5f/956f0f9fc65223a58fbc14459bf34b4cc48dec52e00535c79b8db361aabd/PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5", size = 143850 }, + { url = "https://files.pythonhosted.org/packages/ed/23/8da0bbe2ab9dcdd11f4f4557ccaf95c10b9811b13ecced089d43ce59c3c8/PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44", size = 161980 }, + { url = "https://files.pythonhosted.org/packages/86/0c/c581167fc46d6d6d7ddcfb8c843a4de25bdd27e4466938109ca68492292c/PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab", size = 183873 }, + { url = "https://files.pythonhosted.org/packages/a8/0c/38374f5bb272c051e2a69281d71cba6fdb983413e6758b84482905e29a5d/PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725", size = 173302 }, + { url = "https://files.pythonhosted.org/packages/c3/93/9916574aa8c00aa06bbac729972eb1071d002b8e158bd0e83a3b9a20a1f7/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5", size = 739154 }, + { url = "https://files.pythonhosted.org/packages/95/0f/b8938f1cbd09739c6da569d172531567dbcc9789e0029aa070856f123984/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425", size = 766223 }, + { url = "https://files.pythonhosted.org/packages/b9/2b/614b4752f2e127db5cc206abc23a8c19678e92b23c3db30fc86ab731d3bd/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476", size = 767542 }, + { url = "https://files.pythonhosted.org/packages/d4/00/dd137d5bcc7efea1836d6264f049359861cf548469d18da90cd8216cf05f/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48", size = 731164 }, + { url = "https://files.pythonhosted.org/packages/c9/1f/4f998c900485e5c0ef43838363ba4a9723ac0ad73a9dc42068b12aaba4e4/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b", size = 756611 }, + { url = "https://files.pythonhosted.org/packages/df/d1/f5a275fdb252768b7a11ec63585bc38d0e87c9e05668a139fea92b80634c/PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4", size = 140591 }, + { url = "https://files.pythonhosted.org/packages/0c/e8/4f648c598b17c3d06e8753d7d13d57542b30d56e6c2dedf9c331ae56312e/PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8", size = 156338 }, + { url = "https://files.pythonhosted.org/packages/ef/e3/3af305b830494fa85d95f6d95ef7fa73f2ee1cc8ef5b495c7c3269fb835f/PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba", size = 181309 }, + { url = "https://files.pythonhosted.org/packages/45/9f/3b1c20a0b7a3200524eb0076cc027a970d320bd3a6592873c85c92a08731/PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1", size = 171679 }, + { url = "https://files.pythonhosted.org/packages/7c/9a/337322f27005c33bcb656c655fa78325b730324c78620e8328ae28b64d0c/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133", size = 733428 }, + { url = "https://files.pythonhosted.org/packages/a3/69/864fbe19e6c18ea3cc196cbe5d392175b4cf3d5d0ac1403ec3f2d237ebb5/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484", size = 763361 }, + { url = "https://files.pythonhosted.org/packages/04/24/b7721e4845c2f162d26f50521b825fb061bc0a5afcf9a386840f23ea19fa/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5", size = 759523 }, + { url = "https://files.pythonhosted.org/packages/2b/b2/e3234f59ba06559c6ff63c4e10baea10e5e7df868092bf9ab40e5b9c56b6/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc", size = 726660 }, + { url = "https://files.pythonhosted.org/packages/fe/0f/25911a9f080464c59fab9027482f822b86bf0608957a5fcc6eaac85aa515/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652", size = 751597 }, + { url = "https://files.pythonhosted.org/packages/14/0d/e2c3b43bbce3cf6bd97c840b46088a3031085179e596d4929729d8d68270/PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183", size = 140527 }, + { url = "https://files.pythonhosted.org/packages/fa/de/02b54f42487e3d3c6efb3f89428677074ca7bf43aae402517bc7cca949f3/PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", size = 156446 }, +] + [[package]] name = "regex" version = "2024.9.11" @@ -654,7 +924,7 @@ wheels = [ [[package]] name = "requests" -version = "2.32.3" +version = "2.31.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "certifi" }, @@ -662,9 +932,36 @@ dependencies = [ { name = "idna" }, { name = "urllib3" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/63/70/2bf7780ad2d390a8d301ad0b550f1581eadbd9a20f896afe06353c2a2913/requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760", size = 131218 } +sdist = { url = "https://files.pythonhosted.org/packages/9d/be/10918a2eac4ae9f02f6cfe6414b7a155ccd8f7f9d4380d62fd5b955065c3/requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1", size = 110794 } wheels = [ - { url = "https://files.pythonhosted.org/packages/f9/9b/335f9764261e915ed497fcdeb11df5dfd6f7bf257d4a6a2a686d80da4d54/requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6", size = 64928 }, + { url = "https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f", size = 62574 }, +] + +[[package]] +name = "rich" +version = "13.9.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markdown-it-py" }, + { name = "pygments" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ab/3a/0316b28d0761c6734d6bc14e770d85506c986c85ffb239e688eeaab2c2bc/rich-13.9.4.tar.gz", hash = "sha256:439594978a49a09530cff7ebc4b5c7103ef57baf48d5ea3184f21d9a2befa098", size = 223149 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/19/71/39c7c0d87f8d4e6c020a393182060eaefeeae6c01dab6a84ec346f2567df/rich-13.9.4-py3-none-any.whl", hash = "sha256:6049d5e6ec054bf2779ab3358186963bac2ea89175919d699e378b99738c2a90", size = 242424 }, +] + +[[package]] +name = "rich-click" +version = "1.8.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "rich" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9a/31/103501e85e885e3e202c087fa612cfe450693210372766552ce1ab5b57b9/rich_click-1.8.5.tar.gz", hash = "sha256:a3eebe81da1c9da3c32f3810017c79bd687ff1b3fa35bfc9d8a3338797f1d1a1", size = 38229 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/aa/0b/e2de98c538c0ee9336211d260f88b7e69affab44969750aaca0b48a697c8/rich_click-1.8.5-py3-none-any.whl", hash = "sha256:0fab7bb5b66c15da17c210b4104277cd45f3653a7322e0098820a169880baee0", size = 35081 }, ] [[package]] @@ -701,6 +998,24 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/31/2d/90165d51ecd38f9a02c6832198c13a4e48652485e2ccf863ebb942c531b6/setuptools-75.2.0-py3-none-any.whl", hash = "sha256:a7fcb66f68b4d9e8e66b42f9876150a3371558f98fa32222ffaa5bced76406f8", size = 1249825 }, ] +[[package]] +name = "six" +version = "1.16.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/71/39/171f1c67cd00715f190ba0b100d606d440a28c93c7714febeca8b79af85e/six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", size = 34041 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254", size = 11053 }, +] + +[[package]] +name = "sniffio" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235 }, +] + [[package]] name = "tqdm" version = "4.66.5" @@ -740,6 +1055,147 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ce/d9/5f4c13cecde62396b0d3fe530a50ccea91e7dfc1ccf0e09c228841bb5ba8/urllib3-2.2.3-py3-none-any.whl", hash = "sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac", size = 126338 }, ] +[[package]] +name = "uvicorn" +version = "0.32.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "h11" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/6a/3c/21dba3e7d76138725ef307e3d7ddd29b763119b3aa459d02cc05fefcff75/uvicorn-0.32.1.tar.gz", hash = "sha256:ee9519c246a72b1c084cea8d3b44ed6026e78a4a309cbedae9c37e4cb9fbb175", size = 77630 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/50/c1/2d27b0a15826c2b71dcf6e2f5402181ef85acf439617bb2f1453125ce1f3/uvicorn-0.32.1-py3-none-any.whl", hash = "sha256:82ad92fd58da0d12af7482ecdb5f2470a04c9c9a53ced65b9bbb4a205377602e", size = 63828 }, +] + +[package.optional-dependencies] +standard = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "httptools" }, + { name = "python-dotenv" }, + { name = "pyyaml" }, + { name = "uvloop", marker = "platform_python_implementation != 'PyPy' and sys_platform != 'cygwin' and sys_platform != 'win32'" }, + { name = "watchfiles" }, + { name = "websockets" }, +] + +[[package]] +name = "uvloop" +version = "0.21.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/af/c0/854216d09d33c543f12a44b393c402e89a920b1a0a7dc634c42de91b9cf6/uvloop-0.21.0.tar.gz", hash = "sha256:3bf12b0fda68447806a7ad847bfa591613177275d35b6724b1ee573faa3704e3", size = 2492741 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/57/a7/4cf0334105c1160dd6819f3297f8700fda7fc30ab4f61fbf3e725acbc7cc/uvloop-0.21.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:c0f3fa6200b3108919f8bdabb9a7f87f20e7097ea3c543754cabc7d717d95cf8", size = 1447410 }, + { url = "https://files.pythonhosted.org/packages/8c/7c/1517b0bbc2dbe784b563d6ab54f2ef88c890fdad77232c98ed490aa07132/uvloop-0.21.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0878c2640cf341b269b7e128b1a5fed890adc4455513ca710d77d5e93aa6d6a0", size = 805476 }, + { url = "https://files.pythonhosted.org/packages/ee/ea/0bfae1aceb82a503f358d8d2fa126ca9dbdb2ba9c7866974faec1cb5875c/uvloop-0.21.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9fb766bb57b7388745d8bcc53a359b116b8a04c83a2288069809d2b3466c37e", size = 3960855 }, + { url = "https://files.pythonhosted.org/packages/8a/ca/0864176a649838b838f36d44bf31c451597ab363b60dc9e09c9630619d41/uvloop-0.21.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8a375441696e2eda1c43c44ccb66e04d61ceeffcd76e4929e527b7fa401b90fb", size = 3973185 }, + { url = "https://files.pythonhosted.org/packages/30/bf/08ad29979a936d63787ba47a540de2132169f140d54aa25bc8c3df3e67f4/uvloop-0.21.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:baa0e6291d91649c6ba4ed4b2f982f9fa165b5bbd50a9e203c416a2797bab3c6", size = 3820256 }, + { url = "https://files.pythonhosted.org/packages/da/e2/5cf6ef37e3daf2f06e651aae5ea108ad30df3cb269102678b61ebf1fdf42/uvloop-0.21.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4509360fcc4c3bd2c70d87573ad472de40c13387f5fda8cb58350a1d7475e58d", size = 3937323 }, + { url = "https://files.pythonhosted.org/packages/8c/4c/03f93178830dc7ce8b4cdee1d36770d2f5ebb6f3d37d354e061eefc73545/uvloop-0.21.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:359ec2c888397b9e592a889c4d72ba3d6befba8b2bb01743f72fffbde663b59c", size = 1471284 }, + { url = "https://files.pythonhosted.org/packages/43/3e/92c03f4d05e50f09251bd8b2b2b584a2a7f8fe600008bcc4523337abe676/uvloop-0.21.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f7089d2dc73179ce5ac255bdf37c236a9f914b264825fdaacaded6990a7fb4c2", size = 821349 }, + { url = "https://files.pythonhosted.org/packages/a6/ef/a02ec5da49909dbbfb1fd205a9a1ac4e88ea92dcae885e7c961847cd51e2/uvloop-0.21.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:baa4dcdbd9ae0a372f2167a207cd98c9f9a1ea1188a8a526431eef2f8116cc8d", size = 4580089 }, + { url = "https://files.pythonhosted.org/packages/06/a7/b4e6a19925c900be9f98bec0a75e6e8f79bb53bdeb891916609ab3958967/uvloop-0.21.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86975dca1c773a2c9864f4c52c5a55631038e387b47eaf56210f873887b6c8dc", size = 4693770 }, + { url = "https://files.pythonhosted.org/packages/ce/0c/f07435a18a4b94ce6bd0677d8319cd3de61f3a9eeb1e5f8ab4e8b5edfcb3/uvloop-0.21.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:461d9ae6660fbbafedd07559c6a2e57cd553b34b0065b6550685f6653a98c1cb", size = 4451321 }, + { url = "https://files.pythonhosted.org/packages/8f/eb/f7032be105877bcf924709c97b1bf3b90255b4ec251f9340cef912559f28/uvloop-0.21.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:183aef7c8730e54c9a3ee3227464daed66e37ba13040bb3f350bc2ddc040f22f", size = 4659022 }, + { url = "https://files.pythonhosted.org/packages/3f/8d/2cbef610ca21539f0f36e2b34da49302029e7c9f09acef0b1c3b5839412b/uvloop-0.21.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:bfd55dfcc2a512316e65f16e503e9e450cab148ef11df4e4e679b5e8253a5281", size = 1468123 }, + { url = "https://files.pythonhosted.org/packages/93/0d/b0038d5a469f94ed8f2b2fce2434a18396d8fbfb5da85a0a9781ebbdec14/uvloop-0.21.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:787ae31ad8a2856fc4e7c095341cccc7209bd657d0e71ad0dc2ea83c4a6fa8af", size = 819325 }, + { url = "https://files.pythonhosted.org/packages/50/94/0a687f39e78c4c1e02e3272c6b2ccdb4e0085fda3b8352fecd0410ccf915/uvloop-0.21.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ee4d4ef48036ff6e5cfffb09dd192c7a5027153948d85b8da7ff705065bacc6", size = 4582806 }, + { url = "https://files.pythonhosted.org/packages/d2/19/f5b78616566ea68edd42aacaf645adbf71fbd83fc52281fba555dc27e3f1/uvloop-0.21.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3df876acd7ec037a3d005b3ab85a7e4110422e4d9c1571d4fc89b0fc41b6816", size = 4701068 }, + { url = "https://files.pythonhosted.org/packages/47/57/66f061ee118f413cd22a656de622925097170b9380b30091b78ea0c6ea75/uvloop-0.21.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bd53ecc9a0f3d87ab847503c2e1552b690362e005ab54e8a48ba97da3924c0dc", size = 4454428 }, + { url = "https://files.pythonhosted.org/packages/63/9a/0962b05b308494e3202d3f794a6e85abe471fe3cafdbcf95c2e8c713aabd/uvloop-0.21.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a5c39f217ab3c663dc699c04cbd50c13813e31d917642d459fdcec07555cc553", size = 4660018 }, +] + +[[package]] +name = "watchfiles" +version = "1.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9e/5e/5a9dfb8594b075d7c225d5fb628d498001c5dfae62298e9eb85b8754668f/watchfiles-1.0.0.tar.gz", hash = "sha256:37566c844c9ce3b5deb964fe1a23378e575e74b114618d211fbda8f59d7b5dab", size = 38187 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a7/10/10759faea3f011b86867a534a47c9aedca667a4b3806ffeac7d8a4c8adee/watchfiles-1.0.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:fbd0ab7a9943bbddb87cbc2bf2f09317e74c77dc55b1f5657f81d04666c25269", size = 394139 }, + { url = "https://files.pythonhosted.org/packages/b9/71/b76be784f3e48bb1929e2c1376f227608be9bda4f7ba0c06832f0d190bed/watchfiles-1.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:774ef36b16b7198669ce655d4f75b4c3d370e7f1cbdfb997fb10ee98717e2058", size = 382832 }, + { url = "https://files.pythonhosted.org/packages/d6/88/393b33c6da4963933e810eb0b8d6b44c7ba52ed2aaf6bb7709db377289f8/watchfiles-1.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9b4fb98100267e6a5ebaff6aaa5d20aea20240584647470be39fe4823012ac96", size = 441232 }, + { url = "https://files.pythonhosted.org/packages/35/2c/2d2c131866f7c49ec68c504565d2336f40a595bcd857cd464a68ea0fdb42/watchfiles-1.0.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0fc3bf0effa2d8075b70badfdd7fb839d7aa9cea650d17886982840d71fdeabf", size = 447569 }, + { url = "https://files.pythonhosted.org/packages/ab/08/373713cc4859958cdf0a38ad85740010dbbf5617441edc3480d37387024c/watchfiles-1.0.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:648e2b6db53eca6ef31245805cd528a16f56fa4cc15aeec97795eaf713c11435", size = 472439 }, + { url = "https://files.pythonhosted.org/packages/2b/df/8e209910e260f58f005974a60423bb6fc243d26e8793103462870502c744/watchfiles-1.0.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fa13d604fcb9417ae5f2e3de676e66aa97427d888e83662ad205bed35a313176", size = 492707 }, + { url = "https://files.pythonhosted.org/packages/83/4d/d0673571c223a784849f45c4da6de2af960602ba5061a2f033f96606a118/watchfiles-1.0.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:936f362e7ff28311b16f0b97ec51e8f2cc451763a3264640c6ed40fb252d1ee4", size = 489294 }, + { url = "https://files.pythonhosted.org/packages/32/ed/0c96c714408c8edab862e816b45be51dbe4e77dc7518c29b0dccc02961a8/watchfiles-1.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:245fab124b9faf58430da547512d91734858df13f2ddd48ecfa5e493455ffccb", size = 442559 }, + { url = "https://files.pythonhosted.org/packages/3d/2b/665bf9aefd0f22a265f7b93e69aa4dc068d8ac5ad9ecbd974305eaeff2c0/watchfiles-1.0.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:4ff9c7e84e8b644a8f985c42bcc81457240316f900fc72769aaedec9d088055a", size = 614531 }, + { url = "https://files.pythonhosted.org/packages/9f/41/fd125e824a195219adb204b54f3affce5615f5f1b3889acd441f28d2fbd2/watchfiles-1.0.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9c9a8d8fd97defe935ef8dd53d562e68942ad65067cd1c54d6ed8a088b1d931d", size = 612852 }, + { url = "https://files.pythonhosted.org/packages/dc/ac/750bf3625f4d3172ee7acfd952552070a88fd697935cfead79a68eb8d69d/watchfiles-1.0.0-cp311-none-win32.whl", hash = "sha256:a0abf173975eb9dd17bb14c191ee79999e650997cc644562f91df06060610e62", size = 272294 }, + { url = "https://files.pythonhosted.org/packages/bd/04/8c18986b79d106a88f54629f8f901cd725d76227c9a9191ada8ce8c962e8/watchfiles-1.0.0-cp311-none-win_amd64.whl", hash = "sha256:2a825ba4b32c214e3855b536eb1a1f7b006511d8e64b8215aac06eb680642d84", size = 285435 }, + { url = "https://files.pythonhosted.org/packages/b4/38/7e64929e8ca2b2a94cb9d8ddf6be9c06be8be870b6014d0f06e76b72f9cf/watchfiles-1.0.0-cp311-none-win_arm64.whl", hash = "sha256:a5a7a06cfc65e34fd0a765a7623c5ba14707a0870703888e51d3d67107589817", size = 276512 }, + { url = "https://files.pythonhosted.org/packages/37/0a/75491ba001f1495d2a12d7f6b90738f20badac78291ca5d56bf7990c859a/watchfiles-1.0.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:28fb64b5843d94e2c2483f7b024a1280662a44409bedee8f2f51439767e2d107", size = 394139 }, + { url = "https://files.pythonhosted.org/packages/5a/ee/935095538ff08ab68555de2bbc18acaf91f4cce8518bf32196f1ff9b8326/watchfiles-1.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:e3750434c83b61abb3163b49c64b04180b85b4dabb29a294513faec57f2ffdb7", size = 382832 }, + { url = "https://files.pythonhosted.org/packages/74/40/86787dca3ea251aabb3abfbe4beeffe9c7ae6e69de56a25d572aecde580e/watchfiles-1.0.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bedf84835069f51c7b026b3ca04e2e747ea8ed0a77c72006172c72d28c9f69fc", size = 441232 }, + { url = "https://files.pythonhosted.org/packages/59/e2/08db1ba48a30462ec7e382c2b1de5400b09a2a7c95fe3f16d3e7da844f0c/watchfiles-1.0.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:90004553be36427c3d06ec75b804233f8f816374165d5225b93abd94ba6e7234", size = 447569 }, + { url = "https://files.pythonhosted.org/packages/73/54/10adf42f203d876076cf0684726c102b3dba82b1c7eea2d82e5991875f62/watchfiles-1.0.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b46e15c34d4e401e976d6949ad3a74d244600d5c4b88c827a3fdf18691a46359", size = 472439 }, + { url = "https://files.pythonhosted.org/packages/29/77/d0d3b5ec6224800cd77f5d058473d0a844d753a3dad9f53f369bc98946bc/watchfiles-1.0.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:487d15927f1b0bd24e7df921913399bb1ab94424c386bea8b267754d698f8f0e", size = 492707 }, + { url = "https://files.pythonhosted.org/packages/c8/74/616bd8edfa7b0aaee96e4b3ad7edd0ccf0f4213a06050e965d68e0cdbaef/watchfiles-1.0.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1ff236d7a3f4b0a42f699a22fc374ba526bc55048a70cbb299661158e1bb5e1f", size = 489293 }, + { url = "https://files.pythonhosted.org/packages/9c/1e/5335eaf5fb9a9516722c7f63f477ca1e361d8159fe46e03d96539cb80f5b/watchfiles-1.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c01446626574561756067f00b37e6b09c8622b0fc1e9fdbc7cbcea328d4e514", size = 442559 }, + { url = "https://files.pythonhosted.org/packages/c7/1c/df716e9acf7931b52f48bd9b2eec9a26ff55c73b43bfdbc03ea985543d01/watchfiles-1.0.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b551c465a59596f3d08170bd7e1c532c7260dd90ed8135778038e13c5d48aa81", size = 614531 }, + { url = "https://files.pythonhosted.org/packages/8d/38/c97d572e147234dd5f107179854efbf9ac6470db11db96f690cdb80e9b1b/watchfiles-1.0.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e1ed613ee107269f66c2df631ec0fc8efddacface85314d392a4131abe299f00", size = 612853 }, + { url = "https://files.pythonhosted.org/packages/2d/1d/161eb1caa7e63b60428b2439efb0a87f0db4d5f4b91dd8712b6eca689954/watchfiles-1.0.0-cp312-none-win32.whl", hash = "sha256:5f75cd42e7e2254117cf37ff0e68c5b3f36c14543756b2da621408349bd9ca7c", size = 272337 }, + { url = "https://files.pythonhosted.org/packages/fc/1d/62acefeb546d24971e8f77cf5c475307054da4c21e9c49ec1917b293368b/watchfiles-1.0.0-cp312-none-win_amd64.whl", hash = "sha256:cf517701a4a872417f4e02a136e929537743461f9ec6cdb8184d9a04f4843545", size = 285572 }, + { url = "https://files.pythonhosted.org/packages/41/08/e20f3dbd2db59067596acc9b81345ac68a9c762352d38e789b2516719876/watchfiles-1.0.0-cp312-none-win_arm64.whl", hash = "sha256:8a2127cd68950787ee36753e6d401c8ea368f73beaeb8e54df5516a06d1ecd82", size = 276513 }, + { url = "https://files.pythonhosted.org/packages/c6/14/e14eb2ad369b306be70423fbf6da47bc39333d2beeafb14f23d2f37fdd79/watchfiles-1.0.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:95de85c254f7fe8cbdf104731f7f87f7f73ae229493bebca3722583160e6b152", size = 394141 }, + { url = "https://files.pythonhosted.org/packages/81/c3/738aeb2a01cbdf5fa823f702694ac72879a97fa5873d15d4607a877c7082/watchfiles-1.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:533a7cbfe700e09780bb31c06189e39c65f06c7f447326fee707fd02f9a6e945", size = 382833 }, + { url = "https://files.pythonhosted.org/packages/ed/aa/1cc14d11be667eb7189a2daa0adf307b93d6624fee5b80b8e84c23fb2486/watchfiles-1.0.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a2218e78e2c6c07b1634a550095ac2a429026b2d5cbcd49a594f893f2bb8c936", size = 441231 }, + { url = "https://files.pythonhosted.org/packages/c5/38/96f4c3485094a164ced67ae444f3e890bdaad17d1b62c894aa8439443d81/watchfiles-1.0.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9122b8fdadc5b341315d255ab51d04893f417df4e6c1743b0aac8bf34e96e025", size = 447570 }, + { url = "https://files.pythonhosted.org/packages/9e/ce/0e35e0191517fa1d876ce0b4e23c818cf3a50d825305dcb7471da8774da7/watchfiles-1.0.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9272fdbc0e9870dac3b505bce1466d386b4d8d6d2bacf405e603108d50446940", size = 472440 }, + { url = "https://files.pythonhosted.org/packages/2c/b5/eb9c799c6e14f25f26573ac08734225035a8821f7dd9161c69df882fc119/watchfiles-1.0.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4a3b33c3aefe9067ebd87846806cd5fc0b017ab70d628aaff077ab9abf4d06b3", size = 492706 }, + { url = "https://files.pythonhosted.org/packages/84/fa/985d4cbfe99a56d7277c0e522fd138fe5fc4d8ea6351ee3302e93ed67e63/watchfiles-1.0.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bc338ce9f8846543d428260fa0f9a716626963148edc937d71055d01d81e1525", size = 489295 }, + { url = "https://files.pythonhosted.org/packages/94/1a/8bc18a170eb621a30fb01f4902d60ce362c88b1f65f3b15d45f53b467200/watchfiles-1.0.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ac778a460ea22d63c7e6fb0bc0f5b16780ff0b128f7f06e57aaec63bd339285", size = 442560 }, + { url = "https://files.pythonhosted.org/packages/e9/e0/07ce46f1770ca1d229635efb5393ff593c41762f389532ae9c7b2ced79b0/watchfiles-1.0.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:53ae447f06f8f29f5ab40140f19abdab822387a7c426a369eb42184b021e97eb", size = 614532 }, + { url = "https://files.pythonhosted.org/packages/7b/56/cdd2847d24249e879a001e6aed9ddeeaa24a80aabfdcb9c19389d0837dfe/watchfiles-1.0.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:1f73c2147a453315d672c1ad907abe6d40324e34a185b51e15624bc793f93cc6", size = 612852 }, + { url = "https://files.pythonhosted.org/packages/72/c9/89a3df27c97eeef5890591a95f7afd266a32dfe55bce1f3bea3390fa56f5/watchfiles-1.0.0-cp313-none-win32.whl", hash = "sha256:eba98901a2eab909dbd79681190b9049acc650f6111fde1845484a4450761e98", size = 271721 }, + { url = "https://files.pythonhosted.org/packages/ef/e9/6e1bd83a08d254b0394500a2bb691b7940f09fcd849f400d01491932f641/watchfiles-1.0.0-cp313-none-win_amd64.whl", hash = "sha256:d562a6114ddafb09c33246c6ace7effa71ca4b6a2324a47f4b09b6445ea78941", size = 284809 }, +] + +[[package]] +name = "websockets" +version = "14.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f4/1b/380b883ce05bb5f45a905b61790319a28958a9ab1e4b6b95ff5464b60ca1/websockets-14.1.tar.gz", hash = "sha256:398b10c77d471c0aab20a845e7a60076b6390bfdaac7a6d2edb0d2c59d75e8d8", size = 162840 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/97/ed/c0d03cb607b7fe1f7ff45e2cd4bb5cd0f9e3299ced79c2c303a6fff44524/websockets-14.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:449d77d636f8d9c17952628cc7e3b8faf6e92a17ec581ec0c0256300717e1512", size = 161949 }, + { url = "https://files.pythonhosted.org/packages/06/91/bf0a44e238660d37a2dda1b4896235d20c29a2d0450f3a46cd688f43b239/websockets-14.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a35f704be14768cea9790d921c2c1cc4fc52700410b1c10948511039be824aac", size = 159606 }, + { url = "https://files.pythonhosted.org/packages/ff/b8/7185212adad274c2b42b6a24e1ee6b916b7809ed611cbebc33b227e5c215/websockets-14.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b1f3628a0510bd58968c0f60447e7a692933589b791a6b572fcef374053ca280", size = 159854 }, + { url = "https://files.pythonhosted.org/packages/5a/8a/0849968d83474be89c183d8ae8dcb7f7ada1a3c24f4d2a0d7333c231a2c3/websockets-14.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c3deac3748ec73ef24fc7be0b68220d14d47d6647d2f85b2771cb35ea847aa1", size = 169402 }, + { url = "https://files.pythonhosted.org/packages/bd/4f/ef886e37245ff6b4a736a09b8468dae05d5d5c99de1357f840d54c6f297d/websockets-14.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7048eb4415d46368ef29d32133134c513f507fff7d953c18c91104738a68c3b3", size = 168406 }, + { url = "https://files.pythonhosted.org/packages/11/43/e2dbd4401a63e409cebddedc1b63b9834de42f51b3c84db885469e9bdcef/websockets-14.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6cf0ad281c979306a6a34242b371e90e891bce504509fb6bb5246bbbf31e7b6", size = 168776 }, + { url = "https://files.pythonhosted.org/packages/6d/d6/7063e3f5c1b612e9f70faae20ebaeb2e684ffa36cb959eb0862ee2809b32/websockets-14.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:cc1fc87428c1d18b643479caa7b15db7d544652e5bf610513d4a3478dbe823d0", size = 169083 }, + { url = "https://files.pythonhosted.org/packages/49/69/e6f3d953f2fa0f8a723cf18cd011d52733bd7f6e045122b24e0e7f49f9b0/websockets-14.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f95ba34d71e2fa0c5d225bde3b3bdb152e957150100e75c86bc7f3964c450d89", size = 168529 }, + { url = "https://files.pythonhosted.org/packages/70/ff/f31fa14561fc1d7b8663b0ed719996cf1f581abee32c8fb2f295a472f268/websockets-14.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9481a6de29105d73cf4515f2bef8eb71e17ac184c19d0b9918a3701c6c9c4f23", size = 168475 }, + { url = "https://files.pythonhosted.org/packages/f1/15/b72be0e4bf32ff373aa5baef46a4c7521b8ea93ad8b49ca8c6e8e764c083/websockets-14.1-cp311-cp311-win32.whl", hash = "sha256:368a05465f49c5949e27afd6fbe0a77ce53082185bbb2ac096a3a8afaf4de52e", size = 162833 }, + { url = "https://files.pythonhosted.org/packages/bc/ef/2d81679acbe7057ffe2308d422f744497b52009ea8bab34b6d74a2657d1d/websockets-14.1-cp311-cp311-win_amd64.whl", hash = "sha256:6d24fc337fc055c9e83414c94e1ee0dee902a486d19d2a7f0929e49d7d604b09", size = 163263 }, + { url = "https://files.pythonhosted.org/packages/55/64/55698544ce29e877c9188f1aee9093712411a8fc9732cca14985e49a8e9c/websockets-14.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:ed907449fe5e021933e46a3e65d651f641975a768d0649fee59f10c2985529ed", size = 161957 }, + { url = "https://files.pythonhosted.org/packages/a2/b1/b088f67c2b365f2c86c7b48edb8848ac27e508caf910a9d9d831b2f343cb/websockets-14.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:87e31011b5c14a33b29f17eb48932e63e1dcd3fa31d72209848652310d3d1f0d", size = 159620 }, + { url = "https://files.pythonhosted.org/packages/c1/89/2a09db1bbb40ba967a1b8225b07b7df89fea44f06de9365f17f684d0f7e6/websockets-14.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:bc6ccf7d54c02ae47a48ddf9414c54d48af9c01076a2e1023e3b486b6e72c707", size = 159852 }, + { url = "https://files.pythonhosted.org/packages/ca/c1/f983138cd56e7d3079f1966e81f77ce6643f230cd309f73aa156bb181749/websockets-14.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9777564c0a72a1d457f0848977a1cbe15cfa75fa2f67ce267441e465717dcf1a", size = 169675 }, + { url = "https://files.pythonhosted.org/packages/c1/c8/84191455d8660e2a0bdb33878d4ee5dfa4a2cedbcdc88bbd097303b65bfa/websockets-14.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a655bde548ca98f55b43711b0ceefd2a88a71af6350b0c168aa77562104f3f45", size = 168619 }, + { url = "https://files.pythonhosted.org/packages/8d/a7/62e551fdcd7d44ea74a006dc193aba370505278ad76efd938664531ce9d6/websockets-14.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a3dfff83ca578cada2d19e665e9c8368e1598d4e787422a460ec70e531dbdd58", size = 169042 }, + { url = "https://files.pythonhosted.org/packages/ad/ed/1532786f55922c1e9c4d329608e36a15fdab186def3ca9eb10d7465bc1cc/websockets-14.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6a6c9bcf7cdc0fd41cc7b7944447982e8acfd9f0d560ea6d6845428ed0562058", size = 169345 }, + { url = "https://files.pythonhosted.org/packages/ea/fb/160f66960d495df3de63d9bcff78e1b42545b2a123cc611950ffe6468016/websockets-14.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:4b6caec8576e760f2c7dd878ba817653144d5f369200b6ddf9771d64385b84d4", size = 168725 }, + { url = "https://files.pythonhosted.org/packages/cf/53/1bf0c06618b5ac35f1d7906444b9958f8485682ab0ea40dee7b17a32da1e/websockets-14.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:eb6d38971c800ff02e4a6afd791bbe3b923a9a57ca9aeab7314c21c84bf9ff05", size = 168712 }, + { url = "https://files.pythonhosted.org/packages/e5/22/5ec2f39fff75f44aa626f86fa7f20594524a447d9c3be94d8482cd5572ef/websockets-14.1-cp312-cp312-win32.whl", hash = "sha256:1d045cbe1358d76b24d5e20e7b1878efe578d9897a25c24e6006eef788c0fdf0", size = 162838 }, + { url = "https://files.pythonhosted.org/packages/74/27/28f07df09f2983178db7bf6c9cccc847205d2b92ced986cd79565d68af4f/websockets-14.1-cp312-cp312-win_amd64.whl", hash = "sha256:90f4c7a069c733d95c308380aae314f2cb45bd8a904fb03eb36d1a4983a4993f", size = 163277 }, + { url = "https://files.pythonhosted.org/packages/34/77/812b3ba5110ed8726eddf9257ab55ce9e85d97d4aa016805fdbecc5e5d48/websockets-14.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:3630b670d5057cd9e08b9c4dab6493670e8e762a24c2c94ef312783870736ab9", size = 161966 }, + { url = "https://files.pythonhosted.org/packages/8d/24/4fcb7aa6986ae7d9f6d083d9d53d580af1483c5ec24bdec0978307a0f6ac/websockets-14.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:36ebd71db3b89e1f7b1a5deaa341a654852c3518ea7a8ddfdf69cc66acc2db1b", size = 159625 }, + { url = "https://files.pythonhosted.org/packages/f8/47/2a0a3a2fc4965ff5b9ce9324d63220156bd8bedf7f90824ab92a822e65fd/websockets-14.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5b918d288958dc3fa1c5a0b9aa3256cb2b2b84c54407f4813c45d52267600cd3", size = 159857 }, + { url = "https://files.pythonhosted.org/packages/dd/c8/d7b425011a15e35e17757e4df75b25e1d0df64c0c315a44550454eaf88fc/websockets-14.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:00fe5da3f037041da1ee0cf8e308374e236883f9842c7c465aa65098b1c9af59", size = 169635 }, + { url = "https://files.pythonhosted.org/packages/93/39/6e3b5cffa11036c40bd2f13aba2e8e691ab2e01595532c46437b56575678/websockets-14.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8149a0f5a72ca36720981418eeffeb5c2729ea55fa179091c81a0910a114a5d2", size = 168578 }, + { url = "https://files.pythonhosted.org/packages/cf/03/8faa5c9576299b2adf34dcccf278fc6bbbcda8a3efcc4d817369026be421/websockets-14.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77569d19a13015e840b81550922056acabc25e3f52782625bc6843cfa034e1da", size = 169018 }, + { url = "https://files.pythonhosted.org/packages/8c/05/ea1fec05cc3a60defcdf0bb9f760c3c6bd2dd2710eff7ac7f891864a22ba/websockets-14.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cf5201a04550136ef870aa60ad3d29d2a59e452a7f96b94193bee6d73b8ad9a9", size = 169383 }, + { url = "https://files.pythonhosted.org/packages/21/1d/eac1d9ed787f80754e51228e78855f879ede1172c8b6185aca8cef494911/websockets-14.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:88cf9163ef674b5be5736a584c999e98daf3aabac6e536e43286eb74c126b9c7", size = 168773 }, + { url = "https://files.pythonhosted.org/packages/0e/1b/e808685530185915299740d82b3a4af3f2b44e56ccf4389397c7a5d95d39/websockets-14.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:836bef7ae338a072e9d1863502026f01b14027250a4545672673057997d5c05a", size = 168757 }, + { url = "https://files.pythonhosted.org/packages/b6/19/6ab716d02a3b068fbbeb6face8a7423156e12c446975312f1c7c0f4badab/websockets-14.1-cp313-cp313-win32.whl", hash = "sha256:0d4290d559d68288da9f444089fd82490c8d2744309113fc26e2da6e48b65da6", size = 162834 }, + { url = "https://files.pythonhosted.org/packages/6c/fd/ab6b7676ba712f2fc89d1347a4b5bdc6aa130de10404071f2b2606450209/websockets-14.1-cp313-cp313-win_amd64.whl", hash = "sha256:8621a07991add373c3c5c2cf89e1d277e49dc82ed72c75e3afc74bd0acc446f0", size = 163277 }, + { url = "https://files.pythonhosted.org/packages/b0/0b/c7e5d11020242984d9d37990310520ed663b942333b83a033c2f20191113/websockets-14.1-py3-none-any.whl", hash = "sha256:4d4fc827a20abe6d544a119896f6b78ee13fe81cbfef416f3f2ddf09a03f0e2e", size = 156277 }, +] + [[package]] name = "win32-setctime" version = "1.1.0"