From ad244ffc7ee7fcd8c44920e1ac8c6936ed7e3c93 Mon Sep 17 00:00:00 2001 From: Sander Land <48946947+sanderland@users.noreply.github.com> Date: Fri, 5 Jun 2026 13:22:00 +0200 Subject: [PATCH] v1.18.0 (#815) Co-authored-by: Artur Tamazian Co-authored-by: Javier Gonzalez --- INSTALL.md | 13 +- katrain/__main__.py | 47 +- katrain/config.json | 2 + katrain/core/constants.py | 2 +- katrain/core/engine.py | 26 +- katrain/core/remote_engine.py | 584 ++++++++++++++ katrain/gui/popups.py | 89 ++- katrain/gui/sound.py | 56 +- .../i18n/locales/cn/LC_MESSAGES/katrain.mo | Bin 18036 -> 19336 bytes .../i18n/locales/cn/LC_MESSAGES/katrain.po | 56 +- .../i18n/locales/de/LC_MESSAGES/katrain.mo | Bin 20728 -> 22210 bytes .../i18n/locales/de/LC_MESSAGES/katrain.po | 62 +- .../i18n/locales/en/LC_MESSAGES/katrain.mo | Bin 19914 -> 21230 bytes .../i18n/locales/en/LC_MESSAGES/katrain.po | 54 +- .../i18n/locales/es/LC_MESSAGES/katrain.mo | Bin 18876 -> 19749 bytes .../i18n/locales/es/LC_MESSAGES/katrain.po | 42 +- .../i18n/locales/fr/LC_MESSAGES/katrain.mo | Bin 22281 -> 23658 bytes .../i18n/locales/fr/LC_MESSAGES/katrain.po | 62 +- .../i18n/locales/jp/LC_MESSAGES/katrain.mo | Bin 22798 -> 24341 bytes .../i18n/locales/jp/LC_MESSAGES/katrain.po | 60 +- .../i18n/locales/ko/LC_MESSAGES/katrain.mo | Bin 22089 -> 23493 bytes .../i18n/locales/ko/LC_MESSAGES/katrain.po | 60 +- .../i18n/locales/ru/LC_MESSAGES/katrain.mo | Bin 28339 -> 29610 bytes .../i18n/locales/ru/LC_MESSAGES/katrain.po | 60 ++ .../i18n/locales/tr/LC_MESSAGES/katrain.mo | Bin 21980 -> 23316 bytes .../i18n/locales/tr/LC_MESSAGES/katrain.po | 62 +- .../i18n/locales/tw/LC_MESSAGES/katrain.mo | Bin 18747 -> 20026 bytes .../i18n/locales/tw/LC_MESSAGES/katrain.po | 56 +- .../i18n/locales/ua/LC_MESSAGES/katrain.mo | Bin 29391 -> 31060 bytes .../i18n/locales/ua/LC_MESSAGES/katrain.po | 62 +- katrain/popups.kv | 306 ++++--- pyproject.toml | 4 +- tests/test_remote_engine.py | 231 ++++++ uv.lock | 755 +++++++++++------- 34 files changed, 2286 insertions(+), 465 deletions(-) create mode 100644 katrain/core/remote_engine.py create mode 100644 tests/test_remote_engine.py diff --git a/INSTALL.md b/INSTALL.md index eada751..e26145f 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -15,11 +15,16 @@ The easiest way to install is probably [brew](https://brew.sh/). Simply run `brew install katrain` and it will download and install the latest pre-built .app, and also install katago if needed. -You can also find downloadable .app files for macOS [here](https://github.com/sanderland/katrain/releases). -Simply download, unzip the file, mount the .dmg and drag the .app file to your application folder, everything is included. -The first time launching the application you may need to [control-click in finder to give permission for the 'unidentified' app to launch](https://support.apple.com/guide/mac-help/open-a-mac-app-from-an-unidentified-developer-mh40616/mac). This is simply a result of Apple charging $99/year to developers to be 'identified'. +You can also find downloadable macOS installers [here](https://github.com/sanderland/katrain/releases). Recent releases include both Intel (`KaTrain-*-x86_64.dmg`) and Apple Silicon (`KaTrain-*-arm64.dmg`) installers, so download the one matching your Mac. Mount the `.dmg` and drag the `.app` to your Applications folder. -Users with the last generation M1 macs with different architecture should then `brew install katago` in addition to this. KaTrain will automatically detect this KataGo binary. +The first time you launch the app, macOS may block it as an app from an unknown developer. +Follow Apple's current guide [here](https://support.apple.com/guide/mac-help/open-a-mac-app-from-an-unidentified-developer-mh40616/mac): +1. Try opening the app once from Finder. +2. Open `System Settings > Privacy & Security`. +3. In the Security section, click `Open` and then `Open Anyway` for KaTrain. +4. Enter your password to confirm. + +This is simply a result of Apple charging $99/year to developers to be 'identified'. ### Command line install guide diff --git a/katrain/__main__.py b/katrain/__main__.py index dcdbd45..ae7bff8 100644 --- a/katrain/__main__.py +++ b/katrain/__main__.py @@ -29,6 +29,12 @@ else: Config.set("kivy", "window_icon", ICON) Config.set("input", "mouse", "mouse,multitouch_on_demand") +# Preload sounds before Window import creates the SDL2 window, +# as SoundLoader.load() deadlocks once the SDL2 window exists. +from katrain.gui.sound import preload_sounds + +preload_sounds(PATHS["PACKAGE"] + "/sounds") + # next, certificates on package builds https://github.com/sanderland/katrain/issues/414 if getattr(sys, "frozen", False): import ssl @@ -93,7 +99,7 @@ from katrain.gui.popups import ( ) from katrain.gui.sound import play_sound from katrain.core.base_katrain import KaTrainBase -from katrain.core.engine import KataGoEngine +from katrain.core.remote_engine import make_engine from katrain.core.contribute_engine import KataGoContributeEngine from katrain.core.game import Game, IllegalMoveException, KaTrainSGF, BaseGame from katrain.core.sgf_parser import Move, ParseError @@ -187,7 +193,7 @@ class KaTrainGui(Screen, KaTrainBase): if self.engine: return self.board_gui.trainer_config = self.config("trainer") - self.engine = KataGoEngine(self, self.config("engine")) + self.engine = make_engine(self, self.config("engine")) threading.Thread(target=self._message_loop_thread, daemon=True).start() sgf_args = [ f @@ -207,6 +213,20 @@ class KaTrainGui(Screen, KaTrainBase): MDApp.get_running_app().root_window.bind(focus=set_focus_event) + def restart_engine(self): + """Rebuild the analysis engine from current config and re-analyze. + Shared by the engine-settings save and the recovery popup's Retry.""" + self.log("Restarting engine", OUTPUT_INFO) + self.controls.set_status(i18n._("restarting engine"), STATUS_INFO) + old_engine = self.engine + old_engine.shutdown(finish=False) + new_engine = make_engine(self, self.config("engine")) + self.engine = new_engine + self.game.engines = {"B": new_engine, "W": new_engine} + # old engine was possibly broken, so make sure we redo any failures + self.game.analyze_all_nodes(analyze_fast=True) + self.update_state() + def update_gui(self, cn, redraw_board=False): # Handle prisoners and next player display prisoners = self.game.prisoner_count @@ -226,7 +246,7 @@ class KaTrainGui(Screen, KaTrainBase): self.controls.players["B"].captures = prisoners["B"] # update engine status dot - if not self.engine or not self.engine.katago_process or self.engine.katago_process.poll() is not None: + if not self.engine or not self.engine.check_alive(): self.board_controls.engine_status_col = Theme.ENGINE_DOWN_COLOR elif self.engine.is_idle(): self.board_controls.engine_status_col = Theme.ENGINE_READY_COLOR @@ -512,7 +532,7 @@ class KaTrainGui(Screen, KaTrainBase): self.ai_settings_popup.content.popup = self.ai_settings_popup self.ai_settings_popup.open() - def _do_engine_recovery_popup(self, error_message, code): + def _do_engine_recovery_popup(self, error_message, code, engine_type="local"): current_open = self.popup_open if current_open and isinstance(current_open.content, EngineRecoveryPopup): self.log(f"Not opening engine recovery popup with {error_message} as one is already open", OUTPUT_DEBUG) @@ -520,7 +540,7 @@ class KaTrainGui(Screen, KaTrainBase): popup = I18NPopup( title_key="engine recovery", size=[dp(600), dp(700)], - content=EngineRecoveryPopup(self, error_message=error_message, code=code), + content=EngineRecoveryPopup(self, error_message=error_message, code=code, engine_type=engine_type), ).__self__ popup.content.popup = popup popup.open() @@ -845,14 +865,19 @@ class KaTrainApp(MDApp): def is_valid_window_position(self, left, top, width, height): try: from screeninfo import get_monitors + monitors = get_monitors() for monitor in monitors: - if (left >= monitor.x and left + width <= monitor.x + monitor.width and - top >= monitor.y and top + height <= monitor.y + monitor.height): + if ( + left >= monitor.x + and left + width <= monitor.x + monitor.width + and top >= monitor.y + and top + height <= monitor.y + monitor.height + ): return True return False except Exception as e: - return True # yolo + return True # yolo def build(self): self.icon = ICON # how you're supposed to set an icon @@ -905,7 +930,11 @@ class KaTrainApp(MDApp): win_size = [1300 * window_scale_fac, 1000 * window_scale_fac] self.gui.log(f"Setting window size to {win_size} and position to {[win_left, win_top]}", OUTPUT_DEBUG) Window.size = (win_size[0], win_size[1]) - if win_left is not None and win_top is not None and self.is_valid_window_position(win_left, win_top, win_size[0], win_size[1]): + if ( + win_left is not None + and win_top is not None + and self.is_valid_window_position(win_left, win_top, win_size[0], win_size[1]) + ): Window.left = win_left Window.top = win_top diff --git a/katrain/config.json b/katrain/config.json index d4beeb5..41daf1c 100644 --- a/katrain/config.json +++ b/katrain/config.json @@ -1,7 +1,9 @@ { "engine": { + "backend": "", "katago": "", "altcommand": "", + "remote_url": "", "model": "katrain/models/kata1-b18c384nbt-s9996604416-d4316597426.bin.gz", "humanlike_model": "", "config": "katrain/KataGo/analysis_config.cfg", diff --git a/katrain/core/constants.py b/katrain/core/constants.py index b706e43..6bec82a 100644 --- a/katrain/core/constants.py +++ b/katrain/core/constants.py @@ -1,5 +1,5 @@ PROGRAM_NAME = "KaTrain" -VERSION = "1.17.1" +VERSION = "1.18.0" HOMEPAGE = "https://github.com/sanderland/katrain" CONFIG_MIN_VERSION = "1.17.0" # keep config files from this version ANALYSIS_FORMAT_VERSION = "1.0" diff --git a/katrain/core/engine.py b/katrain/core/engine.py index dc791c8..acd3d3d 100644 --- a/katrain/core/engine.py +++ b/katrain/core/engine.py @@ -26,6 +26,25 @@ from katrain.core.lang import i18n from katrain.core.sgf_parser import Move from katrain.core.utils import find_package_resource, json_truncate_arrays +ENGINE_BACKENDS = ("local", "remote", "custom") + + +def resolve_engine_backend(config) -> str: + """Which engine backend to use: 'local', 'remote' or 'custom'. + + Uses the explicit `engine/backend` setting when present (set by the engine + settings tabs). Falls back to deriving it from the legacy fields so older + configs keep working: a remote_url means remote, an altcommand means custom. + """ + backend = (config.get("backend") or "").strip().lower() + if backend in ENGINE_BACKENDS: + return backend + if (config.get("remote_url") or "").strip(): + return "remote" + if (config.get("altcommand") or "").strip(): + return "custom" + return "local" + class BaseEngine: # some common elements between analysis and contribute engine @@ -95,6 +114,7 @@ class KataGoEngine(BaseEngine): """Starts and communicates with the KataGO analysis engine""" PONDER_KEY = "_kt_continuous" + ENGINE_TYPE = "local" # passed to the recovery popup so it can tailor its advice def __init__(self, katrain, config): super().__init__(katrain, config) @@ -112,10 +132,10 @@ class KataGoEngine(BaseEngine): self.shell = False self.write_queue = queue.Queue() self.thread_lock = threading.Lock() - if config.get("altcommand", ""): + if resolve_engine_backend(config) == "custom": self.command = config["altcommand"] self.shell = True - else: + else: model = find_package_resource(config["model"]) cfg = find_package_resource(config["config"]) exe = self.get_engine_path(config.get("katago", "").strip()) @@ -146,7 +166,7 @@ class KataGoEngine(BaseEngine): def on_error(self, message, code=None, allow_popup=True): self.katrain.log(message, OUTPUT_ERROR) if self.allow_recovery and allow_popup: - self.katrain("engine_recovery_popup", message, code) + self.katrain("engine_recovery_popup", message, code, self.ENGINE_TYPE) def start(self): with self.thread_lock: diff --git a/katrain/core/remote_engine.py b/katrain/core/remote_engine.py new file mode 100644 index 0000000..0ac4c85 --- /dev/null +++ b/katrain/core/remote_engine.py @@ -0,0 +1,584 @@ +"""Remote KataGo Analysis Engine over WebSocket. + +When `engine.remote_url` is set in the config, KaTrain runs queries +against a remote KataGo Analysis Engine instead of spawning a local +subprocess. The server is expected to expose the KataGo Analysis +Engine JSON protocol over a WebSocket. + +Generic transport — any KataGo-compatible server works. KaTrain has +no awareness of who hosts the engine. +""" + +from __future__ import annotations + +import json +import queue +import threading +import time +import traceback + +import certifi +from websocket import ( # provided by `websocket-client` + ABNF, + WebSocket, + WebSocketException, + WebSocketTimeoutException, + create_connection, +) + +from katrain.core.constants import ( + OUTPUT_DEBUG, + OUTPUT_ERROR, + OUTPUT_EXTRA_DEBUG, + OUTPUT_INFO, + STATUS_INFO, +) +from katrain.core.engine import BaseEngine, KataGoEngine, resolve_engine_backend +from katrain.core.lang import i18n +from katrain.core.utils import json_truncate_arrays + + +class RemoteKataGoEngine(KataGoEngine): + """KataGo engine that talks to a remote Analysis Engine server + over a WebSocket instead of spawning a local subprocess. + + Activated when `engine.remote_url` in the config is non-empty. + The URL must be `ws://...` or `wss://...`. + """ + + ENGINE_TYPE = "remote" # recovery popup shows remote-specific advice (check URL, not executable) + + READ_TIMEOUT_S = 120 + + # A dropped WebSocket is recoverable (server restart, flaky network), + # unlike a crashed local subprocess. Reconnect transparently with + # linear backoff before falling back to the recovery popup. + RECONNECT_ATTEMPTS = 6 + RECONNECT_BACKOFF_S = 1.0 + RECONNECT_MAX_BACKOFF_S = 10.0 + + def __init__(self, katrain, config): + # Bypass KataGoEngine.__init__'s subprocess setup; initialise + # only the bookkeeping the rest of KaTrain reads. + BaseEngine.__init__(self, katrain, config) + self.allow_recovery = self.config.get("allow_recovery", True) + self.queries = {} + # query id -> JSON payload, kept so outstanding analyses can be + # re-sent after a reconnect (the server loses them on disconnect). + self.sent_payloads = {} + self.ponder_query = None + self.query_counter = 0 + self.katago_process = None # rest of the codebase checks this + self.base_priority = 0 + self.override_settings = {"reportAnalysisWinratesAs": "BLACK"} + self.write_queue = queue.Queue() + self.thread_lock = threading.Lock() + self.shell = False + self.command = "" + + self.remote_url = (config.get("remote_url") or "").strip() + if not self.remote_url: + self.on_error( + i18n._("Remote KataGo URL is empty"), + "REMOTE-URL-MISSING", + allow_popup=False, + ) + return + if not self.remote_url.startswith(("ws://", "wss://")): + self.on_error( + i18n._("Remote KataGo URL must start with ws:// or wss://"), + "REMOTE-URL-INVALID", + allow_popup=False, + ) + return + + self.ws: WebSocket | None = None + self.ws_send_lock = threading.Lock() + self.analysis_thread = None + self.write_stdin_thread = None + self.stderr_thread = None + self._closing = False + self._reported_dead = False + self._reconnecting = False + # Bumped on each (re)connect. I/O threads capture the value they + # were started with so a stale thread blocked on a dead socket + # can't trigger a reconnect that would tear down a newer one. + self._conn_id = 0 + + self.start() + + def _create_connection(self) -> WebSocket: + # macOS's bundled Python may have no configured CA bundle, + # so provide certifi explicitly for secure WebSockets. + sslopt = {"ca_certs": certifi.where()} if self.remote_url.startswith("wss://") else None + return create_connection( + self.remote_url, + timeout=self.READ_TIMEOUT_S, + enable_multithread=True, + sslopt=sslopt, + ) + + def _start_threads(self): + """Bump the connection generation and launch fresh I/O threads + bound to it. Must be called while holding thread_lock.""" + self._conn_id += 1 + conn_id = self._conn_id + self.analysis_thread = threading.Thread( + target=self._analysis_read_thread, + args=(conn_id,), + daemon=True, + ) + self.write_stdin_thread = threading.Thread( + target=self._write_stdin_thread, + args=(conn_id,), + daemon=True, + ) + # Dummy stderr thread so callers that join all three don't + # crash on None — remote engines have no stderr channel. + self.stderr_thread = threading.Thread( + target=lambda: None, + daemon=True, + ) + self.analysis_thread.start() + self.write_stdin_thread.start() + self.stderr_thread.start() + + def start(self): + with self.thread_lock: + self.write_queue = queue.Queue() + self._closing = False + self._reported_dead = False + self._reconnecting = False + try: + self.katrain.log( + f"Connecting to remote KataGo at {self.remote_url}", + OUTPUT_DEBUG, + ) + self.ws = self._create_connection() + except Exception as e: + self.on_error( + i18n._("Connecting to remote KataGo failed").format( + url=self.remote_url, + error=e, + ), + code="REMOTE-CONNECT", + ) + self.ws = None + return + + self._start_threads() + + def _handle_disconnect(self, os_error="", conn_id=None): + """Called by the read/write threads when the WebSocket drops. + Kicks off a single background reconnect attempt instead of + immediately surfacing the (local-engine-oriented) recovery popup. + + `conn_id` is the generation the calling thread was started with; + a mismatch means a newer connection already exists and this is a + stale thread, so we ignore it. + """ + with self.thread_lock: + if self._closing or self._reconnecting: + return + if conn_id is not None and conn_id != self._conn_id: + return + self._reconnecting = True + old_ws, self.ws = self.ws, None + # Closing the dead socket unblocks the sibling thread still + # parked in recv() so it exits promptly rather than hanging. + if old_ws is not None: + try: + old_ws.close() + except Exception: + pass + threading.Thread( + target=self._reconnect_thread, + args=(os_error,), + daemon=True, + ).start() + + def _reconnect_thread(self, os_error=""): + """Try to re-establish the WebSocket with linear backoff. On + success, relaunch the I/O threads and re-send outstanding + queries. Only if every attempt fails do we report the engine as + dead (which opens the recovery popup).""" + reconnected = False + try: + for attempt in range(1, self.RECONNECT_ATTEMPTS + 1): + if self._closing: + return + delay = min(self.RECONNECT_BACKOFF_S * attempt, self.RECONNECT_MAX_BACKOFF_S) + self.katrain.log( + f"Remote KataGo disconnected ({os_error}); " + f"reconnect attempt {attempt}/{self.RECONNECT_ATTEMPTS} in {delay:.0f}s", + OUTPUT_INFO, + ) + self._set_status(f"Reconnecting to remote KataGo (attempt {attempt}/{self.RECONNECT_ATTEMPTS})...") + time.sleep(delay) + if self._closing: + return + try: + ws = self._create_connection() + except Exception as e: + os_error = str(e) + continue + + with self.thread_lock: + if self._closing: + try: + ws.close() + except Exception: + pass + return + self.ws = ws + self._reported_dead = False + self._start_threads() + self.katrain.log("Reconnected to remote KataGo", OUTPUT_INFO) + self._set_status("Reconnected to remote KataGo.") + self._resend_outstanding() + reconnected = True + return + finally: + # Keep _reconnecting set across the failure report below so + # external pollers (check_alive) stay quiet and can't latch + # _reported_dead in a way that suppresses the popup. Only clear + # it here on success/shutdown. + if reconnected or self._closing: + self._reconnecting = False + + # Every attempt failed and we are not shutting down: report dead and + # open the recovery popup. _report_dead is idempotent, so a later + # poll from check_alive won't double-report. + if not self._closing: + self._report_dead(os_error, allow_popup=True) + self._reconnecting = False + + def _resend_outstanding(self): + """Re-send queries that were in flight when the connection + dropped. Keyed off self.queries so anything cleared by a new + game or an explicit terminate is not resurrected.""" + with self.thread_lock: + payloads = [self.sent_payloads[qid] for qid in self.queries if qid in self.sent_payloads] + if not payloads: + return + self.katrain.log( + f"Re-sending {len(payloads)} outstanding queries after reconnect", + OUTPUT_INFO, + ) + for query in payloads: + ws = self.ws + if ws is None: + return + try: + with self.ws_send_lock: + ws.send(json.dumps(query)) + except Exception as e: + self.katrain.log(f"Failed to re-send query after reconnect: {e}", OUTPUT_ERROR) + return + + def _set_status(self, message): + try: + self.katrain.controls.set_status(message, STATUS_INFO) + except Exception: + pass + + def on_new_game(self): + # Parent clears self.queries; drop the payloads too so a later + # reconnect doesn't resurrect a previous game's analyses. + super().on_new_game() + self.sent_payloads = {} + + def shutdown(self, finish=False): + self._closing = True + ws = self.ws + if finish and ws is not None: + self.wait_to_finish() + self.ws = None + self.sent_payloads = {} + if ws is not None: + try: + ws.close() + except Exception: + pass + if finish is not None: + for t in [self.write_stdin_thread, self.analysis_thread, self.stderr_thread]: + if t and t.is_alive(): + t.join(timeout=2.0) + + def wait_to_finish(self): + while self.queries and self.ws is not None: + time.sleep(0.1) + + def _report_dead(self, os_error, allow_popup): + """Report the engine as disconnected exactly once. Guarded by + thread_lock + _reported_dead so a poll from check_alive and the + reconnect thread's final failure report can't double-fire or race.""" + with self.thread_lock: + if self._reported_dead: + return + self._reported_dead = True + self.ws = None + self.on_error( + i18n._("Remote KataGo engine disconnected").format(error=os_error), + code="REMOTE-DISCONNECTED", + allow_popup=allow_popup, + ) + + def check_alive(self, os_error="", exception_if_dead=False, maybe_open_recovery=False): + # An in-progress auto-reconnect is recovery, not death. Callers that + # poll while the socket is briefly None (the AI move loops in ai.py + # spin on check_alive every 10ms) must not flag the engine dead. + # _reconnect_thread keeps _reconnecting set until it has reported a + # genuine failure, so the popup is never suppressed nor premature. + if self._reconnecting and not self._closing: + return True + ok = self.ws is not None and not self._closing + if not ok and exception_if_dead: + self._report_dead(os_error, allow_popup=maybe_open_recovery) + return ok + + def _read_stderr_thread(self): + # Remote engines have no stderr channel; warnings come via the + # `warning` field on responses. Override prevents the parent's + # stderr thread from reading from a None process. + return + + def _write_stdin_thread(self, conn_id): + """Pop (query, callback, error_callback, next_move, node) + tuples off write_queue, register the callback in self.queries + so the read thread can match responses by id, then send the + JSON query over the WebSocket. Ponder dedupe lives inside the + lock so rapid Ponder presses don't queue duplicate analyses. + + Bound to the connection generation `conn_id`: once a reconnect + supersedes it, this thread stops and a fresh one takes over. + """ + ws = self.ws + while ws is not None and not self._closing and conn_id == self._conn_id: + try: + query, callback, error_callback, next_move, node = self.write_queue.get( + block=True, + timeout=0.1, + ) + except queue.Empty: + continue + if self._closing or conn_id != self._conn_id: + # Superseded mid-pop: hand the item back so the current + # generation's writer sends it after reconnecting. + self.write_queue.put((query, callback, error_callback, next_move, node)) + return + with self.thread_lock: + if "id" not in query: + self.query_counter += 1 + query["id"] = f"QUERY:{self.query_counter}" + + ponder = query.pop(self.PONDER_KEY, False) + if ponder: + pq = self.ponder_query or {} + differences = { + k: (pq.get(k), query.get(k)) + for k in (query.keys() | pq.keys()) - {"id", "maxVisits", "reportDuringSearchEvery"} + if pq.get(k) != query.get(k) + } + if differences: + self.stop_pondering() + query["maxVisits"] = 10_000_000 + from katrain.core.constants import PONDERING_REPORT_DT + + query["reportDuringSearchEvery"] = PONDERING_REPORT_DT + self.ponder_query = query + else: + continue + + terminate = query.get("action") == "terminate" + if not terminate: + self.queries[query["id"]] = ( + callback, + error_callback, + time.time(), + next_move, + node, + ) + self.sent_payloads[query["id"]] = query + tag = "ponder " if ponder else ("terminate " if terminate else "") + self.katrain.log( + f"Sending {tag}query {query['id']}: {json.dumps(query)}", + OUTPUT_DEBUG, + ) + try: + payload = json.dumps(query) + with self.ws_send_lock: + ws.send(payload) + except WebSocketException as e: + self._handle_disconnect(os_error=str(e), conn_id=conn_id) + return + except Exception as e: + self.katrain.log( + f"Unexpected exception sending to remote KataGo: {e}", + OUTPUT_ERROR, + ) + traceback.print_exc() + self._handle_disconnect(os_error=str(e), conn_id=conn_id) + return + + def _analysis_read_thread(self, conn_id): + """Read JSON responses from the WebSocket and dispatch to the + matching callbacks in self.queries. + + Bound to the connection generation `conn_id` and to the socket + captured at start, so a thread left over from a previous + connection never reads from (or tears down) a newer one. + """ + ws = self.ws + while ws is not None and not self._closing and conn_id == self._conn_id: + try: + # recv_data(control_frame=True) lets us inspect non-text frames + # (e.g. close, whose payload carries the status code + reason). + opcode, data = ws.recv_data(control_frame=True) + except WebSocketTimeoutException: + continue + except WebSocketException as e: + if self._closing: + return + self._handle_disconnect(os_error=str(e), conn_id=conn_id) + return + except Exception as e: + if self._closing: + return + self.katrain.log( + f"Unexpected exception reading from remote KataGo: {e}", + OUTPUT_ERROR, + ) + traceback.print_exc() + self._handle_disconnect(os_error=str(e), conn_id=conn_id) + return + + if opcode == ABNF.OPCODE_CLOSE: + if not self._closing: + # RFC 6455 close payload: 2-byte status code + UTF-8 reason. + reason = "closed by remote" + if data and len(data) >= 2: + reason = data[2:].decode("utf-8", errors="replace").strip() or reason + self._handle_disconnect(os_error=reason, conn_id=conn_id) + return + + if opcode not in (ABNF.OPCODE_TEXT, ABNF.OPCODE_BINARY): + # ping/pong/continuation — nothing to dispatch. + continue + + if not data: + continue + + raw = data.decode("utf-8") if isinstance(data, bytes) else data + + # A frame may contain multiple newline-delimited JSON + # objects (matches KataGo's stdio framing). + for line in str(raw).splitlines(): + line = line.strip() + if not line: + continue + self._dispatch_response_line(line) + + def _dispatch_response_line(self, line: str) -> None: + """Parse one JSON response line and dispatch to the matching + query callback. Warning text is mirrored to the UI status + panel so users see notices like "visits capped" without + reading the log.""" + try: + analysis = json.loads(line) + except json.JSONDecodeError as e: + self.katrain.log( + f"Bad JSON from remote KataGo: {e} (line: {line[:200]!r})", + OUTPUT_ERROR, + ) + return + + try: + if "id" not in analysis: + self.katrain.log( + f"Error without ID {analysis} received from remote KataGo", + OUTPUT_ERROR, + ) + return + + query_id = analysis["id"] + if query_id not in self.queries: + if analysis.get("action") != "terminate": + self.katrain.log( + f"Query result {query_id} discarded -- recent new game or node reset?", + OUTPUT_DEBUG, + ) + return + + callback, error_callback, start_time, next_move, _ = self.queries[query_id] + + # Handled BEFORE the dispatch chain so analysis data + # alongside a warning still reaches the callback. + if "warning" in analysis: + warning_text = str(analysis.get("warning")) + self.katrain.log( + f"Remote KataGo warning: {warning_text}", + OUTPUT_INFO, + ) + try: + self.katrain.controls.set_status(warning_text, STATUS_INFO) + except Exception: + pass + + if "error" in analysis: + del self.queries[query_id] + self.sent_payloads.pop(query_id, None) + if error_callback: + error_callback(analysis) + elif not (next_move and "Illegal move" in analysis["error"]): + self.katrain.log( + f"{analysis} received from remote KataGo", + OUTPUT_ERROR, + ) + elif "terminateId" in analysis: + self.katrain.log( + f"{analysis} received from remote KataGo", + OUTPUT_DEBUG, + ) + else: + partial_result = analysis.get("isDuringSearch", False) + if not partial_result: + del self.queries[query_id] + self.sent_payloads.pop(query_id, None) + time_taken = time.time() - start_time + results_exist = not analysis.get("noResults", False) + self.katrain.log( + f"[{time_taken:.1f}][{query_id}][{'....' if partial_result else 'done'}] " + f"KataGo analysis received: {len(analysis.get('moveInfos', []))} " + f"candidate moves, " + f"{analysis['rootInfo']['visits'] if results_exist else 'n/a'} visits", + OUTPUT_DEBUG, + ) + self.katrain.log(json_truncate_arrays(analysis), OUTPUT_EXTRA_DEBUG) + try: + if callback and results_exist: + callback(analysis, partial_result) + except Exception as e: + self.katrain.log( + f"Error in engine callback for query {query_id}: {e}", + OUTPUT_ERROR, + ) + traceback.print_exc() + + if getattr(self.katrain, "update_state", None): + self.katrain.update_state() + except Exception as e: + self.katrain.log( + f"Unexpected exception {e} processing remote KataGo output: {line[:200]!r}", + OUTPUT_ERROR, + ) + traceback.print_exc() + + +def make_engine(katrain, config): + """Return the engine matching the selected backend (see resolve_engine_backend): + a RemoteKataGoEngine for the remote backend, otherwise a local-subprocess + KataGoEngine (which itself handles the local vs custom-command distinction).""" + if resolve_engine_backend(config) == "remote": + return RemoteKataGoEngine(katrain, config) + return KataGoEngine(katrain, config) diff --git a/katrain/gui/popups.py b/katrain/gui/popups.py index e1c645d..012b9ed 100644 --- a/katrain/gui/popups.py +++ b/katrain/gui/popups.py @@ -24,6 +24,7 @@ from kivymd.uix.selectioncontrol import MDCheckbox from kivymd.uix.textfield import MDTextField from katrain.core.ai import ai_rank_estimation, game_report +from katrain.core.engine import resolve_engine_backend from katrain.core.constants import ( AI_CONFIG_DEFAULT, AI_DEFAULT, @@ -39,7 +40,6 @@ from katrain.core.constants import ( PLAYER_HUMAN, ADDITIONAL_MOVE_ORDER, ) -from katrain.core.engine import KataGoEngine from katrain.core.lang import i18n, rank_label from katrain.core.sgf_parser import Move from katrain.core.utils import PATHS, find_package_resource, evaluation_class @@ -455,11 +455,36 @@ class ConfigAIPopup(QuickConfigGui): class EngineRecoveryPopup(QuickConfigGui): error_message = StringProperty("") code = ObjectProperty(None) + engine_type = StringProperty("local") + recovery_message = StringProperty("") - def __init__(self, katrain, error_message, code): + def __init__(self, katrain, error_message, code, engine_type="local"): super().__init__(katrain) self.error_message = str(error_message) self.code = code + self.engine_type = engine_type or "local" + self.recovery_message = self._build_message() + + def _build_message(self): + settings_link = "[color=#CCCC11][u][ref=engine_settings]" + i18n._("menu:settings") + "[/ref][/u][/color]" + help_link = "[color=#CCCC11][u][ref=engine_help]" + i18n._("link_here") + "[/ref][/u][/color]" + if self.engine_type == "remote": + opening_key = "remote engine disconnected popup opening message" + suggestion = i18n._("remote engine check url suggestion").format(link=settings_link) + else: + opening_key = "engine died popup opening message" + suggestion = i18n._("change engine suggestion").format(link=settings_link) + opening = i18n._(opening_key).format(code=self.code, error_message=self.error_message) + help_text = i18n._("go to engine help page").format(link=help_link) + return opening + "\n\n" + suggestion + "\n\n" + help_text + + def retry(self): + """Rebuild the engine from current config and re-analyze. For a + remote engine this reconnects; for a local one it respawns the + subprocess. Recovers a transient failure without changing settings.""" + if self.popup: + self.popup.dismiss() + Clock.schedule_once(lambda _dt: self.katrain.restart_engine(), 0) class BaseConfigPopup(QuickConfigGui): @@ -481,23 +506,28 @@ class BaseConfigPopup(QuickConfigGui): KATAGOS = { "win": { - "OpenCL v1.16.0": "https://github.com/lightvector/KataGo/releases/download/v1.16.0/katago-v1.16.0-opencl-windows-x64.zip", - "Eigen AVX2 (Modern CPUs) v1.16.0": "https://github.com/lightvector/KataGo/releases/download/v1.16.0/katago-v1.16.0-eigenavx2-windows-x64.zip", - "Eigen (CPU, Non-optimized) v1.16.0": "https://github.com/lightvector/KataGo/releases/download/v1.16.0/katago-v1.16.0-eigen-windows-x64.zip", - "OpenCL v1.16.0 (bigger boards)": "https://github.com/lightvector/KataGo/releases/download/v1.16.0/katago-v1.16.0-opencl-windows-x64+bs50.zip", + "OpenCL v1.16.5": "https://github.com/lightvector/KataGo/releases/download/v1.16.5/katago-v1.16.5-opencl-windows-x64.zip", + "Eigen AVX2 (Modern CPUs) v1.16.5": "https://github.com/lightvector/KataGo/releases/download/v1.16.5/katago-v1.16.5-eigenavx2-windows-x64.zip", + "Eigen (CPU, Non-optimized) v1.16.5": "https://github.com/lightvector/KataGo/releases/download/v1.16.5/katago-v1.16.5-eigen-windows-x64.zip", + "OpenCL v1.16.5 (bigger boards)": "https://github.com/lightvector/KataGo/releases/download/v1.16.5/katago-v1.16.5-opencl-windows-x64+bs50.zip", }, "linux": { - "OpenCL v1.16.0": "https://github.com/lightvector/KataGo/releases/download/v1.16.0/katago-v1.16.0-opencl-linux-x64.zip", - "Eigen AVX2 (Modern CPUs) v1.16.0": "https://github.com/lightvector/KataGo/releases/download/v1.16.0/katago-v1.16.0-eigenavx2-linux-x64.zip", - "Eigen (CPU, Non-optimized) v1.16.0": "https://github.com/lightvector/KataGo/releases/download/v1.16.0/katago-v1.16.0-eigen-linux-x64.zip", - "OpenCL v1.16.0 (bigger boards)": "https://github.com/lightvector/KataGo/releases/download/v1.16.0/katago-v1.16.0-opencl-linux-x64+bs50.zip", + "OpenCL v1.16.5": "https://github.com/lightvector/KataGo/releases/download/v1.16.5/katago-v1.16.5-opencl-linux-x64.zip", + "Eigen AVX2 (Modern CPUs) v1.16.5": "https://github.com/lightvector/KataGo/releases/download/v1.16.5/katago-v1.16.5-eigenavx2-linux-x64.zip", + "Eigen (CPU, Non-optimized) v1.16.5": "https://github.com/lightvector/KataGo/releases/download/v1.16.5/katago-v1.16.5-eigen-linux-x64.zip", + "OpenCL v1.16.5 (bigger boards)": "https://github.com/lightvector/KataGo/releases/download/v1.16.5/katago-v1.16.5-opencl-linux-x64+bs50.zip", }, "just-descriptions": {}, } def __init__(self, katrain): super().__init__(katrain) - self.paths = [self.katrain.config("engine/model"), self.katrain.config("engine/humanlike_model"), "katrain/models", DATA_FOLDER] + self.paths = [ + self.katrain.config("engine/model"), + self.katrain.config("engine/humanlike_model"), + "katrain/models", + DATA_FOLDER, + ] self.katago_paths = [self.katrain.config("engine/katago"), DATA_FOLDER] self.last_clicked_download_models = 0 @@ -561,7 +591,9 @@ class BaseConfigPopup(QuickConfigGui): key=lambda descpath: ("Recommended" not in descpath[0], " - " not in descpath[0], descpath[0]), ) humanlike_models_available_msg = i18n._("models available").format(num=len(humanlike_model_files)) - self.humanlike_model_files.values = [humanlike_models_available_msg] + [desc for desc, path in humanlike_model_files] + self.humanlike_model_files.values = [humanlike_models_available_msg] + [ + desc for desc, path in humanlike_model_files + ] self.humanlike_model_files.value_keys = [""] + [path for desc, path in humanlike_model_files] self.humanlike_model_files.text = humanlike_models_available_msg @@ -650,7 +682,9 @@ class BaseConfigPopup(QuickConfigGui): for name, url in {**self.MODELS, **dist_models}.items(): filename = os.path.split(url)[1] - if not any(os.path.split(f)[1] == filename for f in self.model_files.values + self.humanlike_model_files.values): + if not any( + os.path.split(f)[1] == filename for f in self.model_files.values + self.humanlike_model_files.values + ): savepath = os.path.expanduser(os.path.join(DATA_FOLDER, filename)) savepath_tmp = savepath + ".part" self.katrain.log(f"Downloading {name} from {url} to {savepath_tmp}", OUTPUT_INFO) @@ -759,14 +793,28 @@ class BaseConfigPopup(QuickConfigGui): class ConfigPopup(BaseConfigPopup): + ENGINE_TAB_BUTTONS = {"local": "local_tab_button", "remote": "remote_tab_button", "custom": "custom_tab_button"} + def __init__(self, katrain): super().__init__(katrain) Clock.schedule_once(self.check_katas) + Clock.schedule_once(self.select_engine_tab) MDApp.get_running_app().bind(language=self.check_models) MDApp.get_running_app().bind(language=self.check_katas) + def select_engine_tab(self, *_args): + # The active tab is authoritative for which engine is used; pick it based on the current config. + backend = resolve_engine_backend(self.katrain.config("engine")) + self.engine_sm.current = backend + getattr(self, self.ENGINE_TAB_BUTTONS[backend]).state = "down" + def update_config(self, save_to_file=True, close_popup=True): + old_backend = self.katrain.config("engine/backend", "") + backend = self.engine_sm.current + self.katrain._config["engine"]["backend"] = backend updated = super().update_config(save_to_file=save_to_file, close_popup=close_popup) + if backend != old_backend: + updated.add("engine/backend") self.katrain.debug_level = self.katrain.config("general/debug_level", OUTPUT_INFO) ignore = {"max_visits", "fast_visits", "max_time", "enable_ownership", "wide_root_noise"} @@ -774,21 +822,8 @@ class ConfigPopup(BaseConfigPopup): if detected_restart: def restart_engine(_dt): - self.katrain.controls.set_status("", STATUS_INFO) self.katrain.log(f"Restarting Engine after {detected_restart} settings change") - self.katrain.controls.set_status(i18n._("restarting engine"), STATUS_INFO) - - old_engine = self.katrain.engine # type: KataGoEngine - old_proc = old_engine.katago_process - if old_proc: - old_engine.shutdown(finish=False) - new_engine = KataGoEngine(self.katrain, self.katrain.config("engine")) - self.katrain.engine = new_engine - self.katrain.game.engines = {"B": new_engine, "W": new_engine} - self.katrain.game.analyze_all_nodes( - analyze_fast=True - ) # old engine was possibly broken, so make sure we redo any failures - self.katrain.update_state() + self.katrain.restart_engine() Clock.schedule_once(restart_engine, 0) diff --git a/katrain/gui/sound.py b/katrain/gui/sound.py index 343ac0b..7150b46 100644 --- a/katrain/gui/sound.py +++ b/katrain/gui/sound.py @@ -1,9 +1,9 @@ from kivy.clock import Clock -from kivymd.app import MDApp from kivy.core.audio import SoundLoader from kivy.utils import platform cached_sounds = {} +_audio_available = False # prefer ffpyplayer on linux, then others, avoid gst and avoid or ffpyplayer on windows ranking = [("ffplay", 98 if platform in ["win", "macosx"] else -2), ("sdl", -1), ("gst", 99), ("", 0)] @@ -13,22 +13,56 @@ except Exception as e: print("Exception sorting sound loaders: ", e) # private vars, so could break with versions etc -def play_sound(file, volume=1, cache=True): - def _play(sound): - if sound: - sound.play() - sound.seek(0) +def preload_sounds(sound_dir): + """Preload all sounds before the SDL2 window is created. + SoundLoader.load() deadlocks when no audio output device is available, + so we test audio in a subprocess first. + """ + global _audio_available + import os + import sys + import subprocess + + audio_files = [ + os.path.join(sound_dir, fn) for fn in os.listdir(sound_dir) + if fn.endswith((".wav", ".ogg", ".mp3")) + ] + if not audio_files: + return + + # Test if audio subsystem works by loading one sound in a subprocess + try: + subprocess.run( + [sys.executable, "-c", + f"from kivy.core.audio import SoundLoader; SoundLoader.load({audio_files[0]!r})"], + timeout=3, capture_output=True, + ) + except subprocess.TimeoutExpired as e: + print(f"Warning: Audio unavailable ({e}). Sounds disabled.", file=sys.stderr) + return + + # Audio works, preload all sounds + for path in audio_files: + cached_sounds[os.path.basename(path)] = SoundLoader.load(path) + _audio_available = True + + +def play_sound(file, volume=1, cache=True): + if not _audio_available: + return + + # the following import causes the creation of an SDL2 window, and if there + # is no sound device, it deadlocks. We delay the import until we know audio + # is available + from kivymd.app import MDApp app = MDApp.get_running_app() if app and app.gui and app.gui.config("timer/sound"): sound = cached_sounds.get(file) - if sound is None: - sound = SoundLoader.load(file) - if cache: - cached_sounds[file] = sound if sound is not None: sound.volume = volume - Clock.schedule_once(lambda _dt: _play(sound), 0) + sound.play() + sound.seek(0) def stop_sound(file): diff --git a/katrain/i18n/locales/cn/LC_MESSAGES/katrain.mo b/katrain/i18n/locales/cn/LC_MESSAGES/katrain.mo index 852bc1faa893949c151ee69417994ced81e4b831..6c7ed599493d703f80b1b01e8d82e7363ef6b211 100644 GIT binary patch delta 6004 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 O1G9^wLR}R}QU3!37Y$MX diff --git a/katrain/i18n/locales/de/LC_MESSAGES/katrain.po b/katrain/i18n/locales/de/LC_MESSAGES/katrain.po index bad6f00..8cc38b6 100644 --- a/katrain/i18n/locales/de/LC_MESSAGES/katrain.po +++ b/katrain/i18n/locales/de/LC_MESSAGES/katrain.po @@ -940,8 +940,9 @@ msgstr "" #. - Link in tags should not be touched. msgid "change engine suggestion" msgstr "" -"Versuchen sie erstmal KataGo Versionen runterzuladen und ob eine andere " -"ausführbare Datei in {link} hilft. " +"Drücken Sie zuerst auf Erneut versuchen, um die Engine neu zu starten. Falls" +" das nicht hilft, laden Sie KataGo-Versionen herunter und wechseln Sie in " +"{link} zu einer anderen ausführbaren Datei." #. - as in "click here" to go to this page, msgid "link_here" @@ -1067,3 +1068,60 @@ msgstr "" #. TODO msgid "engine:humanlike_model" msgstr "Path to human-like model" + +#. TODO +msgid "engine:remote_url" +msgstr "KataGo WebSocket URL" + +#. TODO +msgid "engine:remote_url:hint" +msgstr "Leave blank to use a local KataGo engine. Use ws:// or wss://." + +#. TODO +msgid "Remote KataGo URL is empty" +msgstr "Remote KataGo URL is empty" + +#. TODO +msgid "Remote KataGo URL must start with ws:// or wss://" +msgstr "Remote KataGo URL must start with ws:// or wss://" + +#. TODO +msgid "Connecting to remote KataGo failed" +msgstr "Connecting to remote KataGo at {url} failed: {error}" + +#. TODO +msgid "Remote KataGo engine disconnected" +msgstr "Remote KataGo engine disconnected: {error}" + +#. Shown instead of "engine died popup opening message" for remote +#. engines. +msgid "remote engine disconnected popup opening message" +msgstr "" +"Die Verbindung zur entfernten KataGo-Engine ging verloren und konnte nicht automatisch wiederhergestellt werden.\n" +"\n" +"Der Fehler war: [color=#CC2222]{error_message}[/color]\n" +"\n" +"Der Fehlercode war: [color=#CC2222]{code}[/color]." + +#. Button to reconnect/restart the engine from the recovery popup. +msgid "engine recovery: retry" +msgstr "Erneut versuchen" + +#. Link in tags should not be touched. Shown for remote engines. +msgid "remote engine check url suggestion" +msgstr "" +"Wenn die entfernte Engine zuvor funktioniert hat, drücken Sie auf Erneut " +"versuchen, um die Verbindung wiederherzustellen, sobald sie wieder verfügbar" +" ist. Andernfalls überprüfen Sie die URL der entfernten Engine in {link} ." + +msgid "engine:tab:local" +msgstr "Lokale Engine" + +msgid "engine:tab:remote" +msgstr "Remote-Engine" + +msgid "engine:tab:custom" +msgstr "Eigener Befehl" + +msgid "engine:backend:note" +msgstr "Der ausgewählte Reiter bestimmt die genutzte Engine." diff --git a/katrain/i18n/locales/en/LC_MESSAGES/katrain.mo b/katrain/i18n/locales/en/LC_MESSAGES/katrain.mo index fc4677bff72f1f03a90cd53be869dc3c69969d90..d227f01d66443535a30e21ad71d004013329acee 100644 GIT binary patch delta 5844 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 diff --git a/katrain/i18n/locales/en/LC_MESSAGES/katrain.po b/katrain/i18n/locales/en/LC_MESSAGES/katrain.po index 4d92836..38c9baf 100644 --- a/katrain/i18n/locales/en/LC_MESSAGES/katrain.po +++ b/katrain/i18n/locales/en/LC_MESSAGES/katrain.po @@ -653,6 +653,24 @@ msgstr "" "Full command used to start the engine. All other model options will be " "ignored." +msgid "engine:remote_url" +msgstr "KataGo WebSocket URL" + +msgid "engine:remote_url:hint" +msgstr "Leave blank to use a local KataGo engine. Use ws:// or wss://." + +msgid "Remote KataGo URL is empty" +msgstr "Remote KataGo URL is empty" + +msgid "Remote KataGo URL must start with ws:// or wss://" +msgstr "Remote KataGo URL must start with ws:// or wss://" + +msgid "Connecting to remote KataGo failed" +msgstr "Connecting to remote KataGo at {url} failed: {error}" + +msgid "Remote KataGo engine disconnected" +msgstr "Remote KataGo engine disconnected: {error}" + msgid "engine:max_visits" msgstr "Maximum number of visits in analysis" @@ -753,8 +771,28 @@ msgstr "" #. Link in tags should not be touched. msgid "change engine suggestion" msgstr "" -"First, try downloading KataGo versions and try if changing to a different " -"executable helps in {link} ." +"First, press Retry to restart the engine. If that does not help, try " +"downloading KataGo versions and changing to a different executable in {link}" +" ." + +#. Shown instead of "engine died popup opening message" for remote engines. +msgid "remote engine disconnected popup opening message" +msgstr "" +"The connection to the remote KataGo engine was lost and could not be re-established automatically.\n" +"\n" +"The error was: [color=#CC2222]{error_message}[/color]\n" +"\n" +"The error code was: [color=#CC2222]{code}[/color]." + +#. Link in tags should not be touched. Shown for remote engines. +msgid "remote engine check url suggestion" +msgstr "" +"If the remote engine has worked before, press Retry to reconnect once it is " +"back. Otherwise, double-check the remote engine URL in {link} ." + +#. Button to reconnect/restart the engine from the recovery popup. +msgid "engine recovery: retry" +msgstr "Retry" #. Link in tags should not be touched (uses link_here msgid) msgid "go to engine help page" @@ -1073,3 +1111,15 @@ msgstr "Distance of wall" #. tsumego: ko is good enough? msgid "tsumego:ko" msgstr "Ko allowed?" + +msgid "engine:tab:local" +msgstr "Local engine" + +msgid "engine:tab:remote" +msgstr "Remote engine" + +msgid "engine:tab:custom" +msgstr "Custom command" + +msgid "engine:backend:note" +msgstr "The selected tab determines the engine used." diff --git a/katrain/i18n/locales/es/LC_MESSAGES/katrain.mo b/katrain/i18n/locales/es/LC_MESSAGES/katrain.mo index 6a4c79ae7274dded0f152e75945f021c3c96ea93..4549f7895acbccdd35e43e04912f34ab7f48f412 100644 GIT binary patch delta 5678 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 Z?J7Bx6z!OPM@-aP+L{zSGjDP1e*lY|UcCSS diff --git a/katrain/i18n/locales/es/LC_MESSAGES/katrain.po b/katrain/i18n/locales/es/LC_MESSAGES/katrain.po index 0083948..61217a7 100644 --- a/katrain/i18n/locales/es/LC_MESSAGES/katrain.po +++ b/katrain/i18n/locales/es/LC_MESSAGES/katrain.po @@ -752,18 +752,18 @@ msgstr "Cache analysis in SGF" msgid "menu:save-as" msgstr "Save Game As..." -#. TODO # sgf load button +#. TODO msgid "Load File" msgstr "Load File" -#. TODO # sgf save popup +#. TODO msgid "save sgf title" msgstr "Save SGF File" -#. TODO # sgf save as button +#. TODO msgid "Save File" msgstr "Save File" @@ -1029,3 +1029,39 @@ msgstr "Ko allowed?" #. TODO - Menu option for tsumego frame around position msgid "analysis:tsumegoframe" msgstr "Tsumego Frame" + +#. TODO +msgid "engine:remote_url" +msgstr "KataGo WebSocket URL" + +#. TODO +msgid "engine:remote_url:hint" +msgstr "Leave blank to use a local KataGo engine. Use ws:// or wss://." + +#. TODO +msgid "Remote KataGo URL is empty" +msgstr "Remote KataGo URL is empty" + +#. TODO +msgid "Remote KataGo URL must start with ws:// or wss://" +msgstr "Remote KataGo URL must start with ws:// or wss://" + +#. TODO +msgid "Connecting to remote KataGo failed" +msgstr "Connecting to remote KataGo at {url} failed: {error}" + +#. TODO +msgid "Remote KataGo engine disconnected" +msgstr "Remote KataGo engine disconnected: {error}" + +msgid "engine:tab:local" +msgstr "Motor local" + +msgid "engine:tab:remote" +msgstr "Motor remoto" + +msgid "engine:tab:custom" +msgstr "Comando personalizado" + +msgid "engine:backend:note" +msgstr "La pestaña seleccionada determina el motor usado." diff --git a/katrain/i18n/locales/fr/LC_MESSAGES/katrain.mo b/katrain/i18n/locales/fr/LC_MESSAGES/katrain.mo index f45668716fbdbe9cc8e22ad5c808dbc655172182..67d0c0ca3abf6a385ec6548debfdcebe8e3d6361 100644 GIT binary patch delta 6064 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 delta 4737 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 U+H!o`Q1npIy7*{lYHIxd0Ha$UoB#j- diff --git a/katrain/i18n/locales/jp/LC_MESSAGES/katrain.po b/katrain/i18n/locales/jp/LC_MESSAGES/katrain.po index 363300c..8adb683 100644 --- a/katrain/i18n/locales/jp/LC_MESSAGES/katrain.po +++ b/katrain/i18n/locales/jp/LC_MESSAGES/katrain.po @@ -916,7 +916,9 @@ msgstr "それでもだめなら、{link}して最新のトラブルシューテ #. Link in tags should not be touched. msgid "change engine suggestion" -msgstr "まずは、{link}から別バージョンのKataGoをダウンロードしてうまくいくか試してください。" +msgstr "" +"まず「再試行」を押してエンジンを再起動してください。解決しない場合は、{link} で KataGo " +"のバージョンをダウンロードし、別の実行ファイルに変更してみてください。" #. as in "click here" to go to this page, msgid "link_here" @@ -1039,3 +1041,59 @@ msgstr "" #. TODO msgid "engine:humanlike_model" msgstr "Path to human-like model" + +#. TODO +msgid "engine:remote_url" +msgstr "KataGo WebSocket URL" + +#. TODO +msgid "engine:remote_url:hint" +msgstr "Leave blank to use a local KataGo engine. Use ws:// or wss://." + +#. TODO +msgid "Remote KataGo URL is empty" +msgstr "Remote KataGo URL is empty" + +#. TODO +msgid "Remote KataGo URL must start with ws:// or wss://" +msgstr "Remote KataGo URL must start with ws:// or wss://" + +#. TODO +msgid "Connecting to remote KataGo failed" +msgstr "Connecting to remote KataGo at {url} failed: {error}" + +#. TODO +msgid "Remote KataGo engine disconnected" +msgstr "Remote KataGo engine disconnected: {error}" + +#. Shown instead of "engine died popup opening message" for remote +#. engines. +msgid "remote engine disconnected popup opening message" +msgstr "" +"リモート KataGo エンジンへの接続が失われ、自動的に再接続できませんでした。\n" +"\n" +"エラー: [color=#CC2222]{error_message}[/color]\n" +"\n" +"エラーコード: [color=#CC2222]{code}[/color]。" + +#. Button to reconnect/restart the engine from the recovery popup. +msgid "engine recovery: retry" +msgstr "再試行" + +#. Link in tags should not be touched. Shown for remote engines. +msgid "remote engine check url suggestion" +msgstr "" +"リモートエンジンが以前は動作していた場合は、復旧後に「再試行」を押して再接続してください。そうでない場合は、{link} でリモートエンジンの URL " +"を再確認してください。" + +msgid "engine:tab:local" +msgstr "ローカルエンジン" + +msgid "engine:tab:remote" +msgstr "リモートエンジン" + +msgid "engine:tab:custom" +msgstr "カスタムコマンド" + +msgid "engine:backend:note" +msgstr "選択したタブが使用するエンジンを決定します。" diff --git a/katrain/i18n/locales/ko/LC_MESSAGES/katrain.mo b/katrain/i18n/locales/ko/LC_MESSAGES/katrain.mo index 14a87e925df530d9075737f4f50c0556dda12363..4ffd0784c3d74e2c5747c9f575745d0197418f11 100644 GIT binary patch delta 6018 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 O>cljsx_n|q^Zx-0r(2%@ delta 4724 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 delta 4577 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 M6RxYb)Ar{58xLl}i~s-t delta 4685 zcmYM$4N#R;9>?)>DCmsDMgQ?Vdpm@RD^KYT%uy zcD1O?d}QAr$56_xs0Ez2^3gBhyPFw%J^(boGR$IOtL;f|;4JxFEqpkr4q9z)N>X3nod^Xb5EI|dn9@VeP zmbaoZ_c|(bwWzJEN40B21=@ld_oBmtu2C0iufr**<3Q9z38;pXYHhEHL3^{``Z126+=^OJ7iyqx)Ye4sHL1Oi zL9Hwa^?odBqAXPE=c6WCg=F14Yu|52^{>Nl-Ty;8=urF_HBg&g;MYht&A0Y_&@lI# z?QYb49)b!y5f$h?r~sy*#w)Pzms$O&c9r)1CUlhA9Xx2_KiCFGte>G)+=fbNJF4AP z`@Y-O2Mu?(Y9OlJaMZYIsP1*os)<*3XQ4=4ZH;|eM?(I(U_s74*CU8sobQ3D-8 zP0(uVFWPb^s{i+>)c05iCAx<=6_v56s53GhHP50%$DLpq6-s3ZD&^(K`7*CrKd_!e z1>A|6@VYJcS|hz~fN`k6Q&E9WK=sSU(O7^AwA|rAFSeov+=U9{JyZ%0p(1Xv<#yD7 z|3bCDgX$m2osw~=42`m;qsGfdovA`p|HY^Poi#k@G;Tn3bnJ^)P!s$P)!|*#mIN>a zTTt!Wkc(kDP!ruor8bN!q!kW89m-_XI9aH6bMUA8|G0foiW=}aR6v_i18leN_n|V< zh&tV8Py>C5>i197mUW{h96Zt(AEsd%zK+S*jJl5BVyy0eA8IvFJSrt)a4t^5z4*MX zADhBI4V2SSXQUFj0A>ejWeuo_PGBnDzzmF|kc|bXEqWEx@ok*Q{N{5WIIt#klsj+= z22*|jm*9g~i0|NF4+CR9<*+gC%IBlb$TC}g8Yfe(LS?W4mC;kE%w52r;T3eY@en=M zeNl_VVj55rcA!=^o@E8$RMg*u96XGVp$3c^=U%T7sI3@-5jYuj=(25nzO7$m%PYo_ zf2Dq%t*F9C%3Dxh5IZmg>rn0L?fYY>30jdXo4;Zc_Tu;W>39wDxzr>5f_wr8#6+0#wbBppNHfROq3vA#&C{Ou0|4yNI3O4{RU@R%woayfA zJNLP_-~cMn)2KuC1#-^JOji zB$I>M>*rB{?Lqb5i+%90!-FPlw0?@ZJ||HTcc2bY4=SbJhd6jR8kPED)Zz1^GFOEK zSc6*F75ou8FMM)BaGVu|$$)C9}%E_@4hDBs6vcn(Kn)I4{hEYzRn zEvP_uqqgEW>W|OgQHQ%5HF5NO*AygUj>+Ib6XjrEoQDeNaqCiKyUa4|k9DY2{|S}3 z6BvnSP~%)g9kQ#o{2gimJs8KpNe{dIvmVh|VE^-YP-+&VzOjCVO7*L#h*;0=Hc(YWzgh7H6XVbvJW)&_ru-4p!nIJhh-YKWcj5 z!>AuUfrRL`(CR)3nbidezYSyz`ynXcBpnY9Y)tJ837i|ZDY{?tL0_r2>5%`);&I;U zvoqostSzo6@vbcPgWtQc*!!%n#9vzJT~XBhwy(&)p}Bs2bG?6MQE7?ysiLw{Uvs^; zqUmT^)6orUi@ht?t*tIy!H6;Bwx0PvGVJ)nS20 IA3hrPKXR-ZOaK4? diff --git a/katrain/i18n/locales/tr/LC_MESSAGES/katrain.po b/katrain/i18n/locales/tr/LC_MESSAGES/katrain.po index 2ef5cb5..20abd04 100644 --- a/katrain/i18n/locales/tr/LC_MESSAGES/katrain.po +++ b/katrain/i18n/locales/tr/LC_MESSAGES/katrain.po @@ -733,8 +733,9 @@ msgstr "" #. Link in tags should not be touched. msgid "change engine suggestion" msgstr "" -"İlk önce, KataGo sürümlerini indirmeyi deneyin ve {link} bağlantısındaki " -"farklı yürütme dosyalarını kullanmayı deneyin." +"Önce motoru yeniden başlatmak için Yeniden Dene'ye basın. Bu işe yaramazsa, " +"{link} içinde KataGo sürümlerini indirip farklı bir yürütülebilir dosyaya " +"geçmeyi deneyin." #. Link in tags should not be touched (uses link_here msgid) msgid "go to engine help page" @@ -1102,3 +1103,60 @@ msgstr "" #. TODO msgid "engine:humanlike_model" msgstr "Path to human-like model" + +#. TODO +msgid "engine:remote_url" +msgstr "KataGo WebSocket URL" + +#. TODO +msgid "engine:remote_url:hint" +msgstr "Leave blank to use a local KataGo engine. Use ws:// or wss://." + +#. TODO +msgid "Remote KataGo URL is empty" +msgstr "Remote KataGo URL is empty" + +#. TODO +msgid "Remote KataGo URL must start with ws:// or wss://" +msgstr "Remote KataGo URL must start with ws:// or wss://" + +#. TODO +msgid "Connecting to remote KataGo failed" +msgstr "Connecting to remote KataGo at {url} failed: {error}" + +#. TODO +msgid "Remote KataGo engine disconnected" +msgstr "Remote KataGo engine disconnected: {error}" + +#. Shown instead of "engine died popup opening message" for remote +#. engines. +msgid "remote engine disconnected popup opening message" +msgstr "" +"Uzak KataGo motoruyla bağlantı kesildi ve otomatik olarak yeniden kurulamadı.\n" +"\n" +"Hata: [color=#CC2222]{error_message}[/color]\n" +"\n" +"Hata kodu: [color=#CC2222]{code}[/color]." + +#. Button to reconnect/restart the engine from the recovery popup. +msgid "engine recovery: retry" +msgstr "Yeniden Dene" + +#. Link in tags should not be touched. Shown for remote engines. +msgid "remote engine check url suggestion" +msgstr "" +"Uzak motor daha önce çalıştıysa, tekrar erişilebilir olduğunda yeniden " +"bağlanmak için Yeniden Dene'ye basın. Aksi takdirde, {link} içindeki uzak " +"motor URL'sini tekrar kontrol edin." + +msgid "engine:tab:local" +msgstr "Yerel motor" + +msgid "engine:tab:remote" +msgstr "Uzak motor" + +msgid "engine:tab:custom" +msgstr "Özel komut" + +msgid "engine:backend:note" +msgstr "Seçilen sekme, kullanılacak motoru belirler." diff --git a/katrain/i18n/locales/tw/LC_MESSAGES/katrain.mo b/katrain/i18n/locales/tw/LC_MESSAGES/katrain.mo index 2ae0564ba0f011a56a4cc2404bd08261ab7ca4d0..4308c26d5d2ace92ce4ca4525c585f2c545e09da 100644 GIT binary patch delta 5983 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 RDP4gNGJhKpIFVBn@jn@AB_#j= diff --git a/katrain/i18n/locales/tw/LC_MESSAGES/katrain.po b/katrain/i18n/locales/tw/LC_MESSAGES/katrain.po index fbc2ea4..e9a979c 100644 --- a/katrain/i18n/locales/tw/LC_MESSAGES/katrain.po +++ b/katrain/i18n/locales/tw/LC_MESSAGES/katrain.po @@ -898,7 +898,7 @@ msgstr "如果你還有任何困難,請參考疑難排解頁面 {link}" #. Link in tags should not be touched. msgid "change engine suggestion" -msgstr "首先,在 {link} 中,嘗試下載且更換為不同版本的KataGo執行檔是否能解決問題。" +msgstr "請先按「重試」以重新啟動引擎。如果沒有幫助,請嘗試在 {link} 中下載 KataGo 版本並改用其他執行檔。" #. as in "click here" to go to this page, msgid "link_here" @@ -1021,3 +1021,57 @@ msgstr "" #. TODO msgid "engine:humanlike_model" msgstr "Path to human-like model" + +#. TODO +msgid "engine:remote_url" +msgstr "KataGo WebSocket URL" + +#. TODO +msgid "engine:remote_url:hint" +msgstr "Leave blank to use a local KataGo engine. Use ws:// or wss://." + +#. TODO +msgid "Remote KataGo URL is empty" +msgstr "Remote KataGo URL is empty" + +#. TODO +msgid "Remote KataGo URL must start with ws:// or wss://" +msgstr "Remote KataGo URL must start with ws:// or wss://" + +#. TODO +msgid "Connecting to remote KataGo failed" +msgstr "Connecting to remote KataGo at {url} failed: {error}" + +#. TODO +msgid "Remote KataGo engine disconnected" +msgstr "Remote KataGo engine disconnected: {error}" + +#. Shown instead of "engine died popup opening message" for remote +#. engines. +msgid "remote engine disconnected popup opening message" +msgstr "" +"與遠端 KataGo 引擎的連線中斷,且無法自動重新建立。\n" +"\n" +"錯誤為:[color=#CC2222]{error_message}[/color]\n" +"\n" +"錯誤代碼為:[color=#CC2222]{code}[/color]。" + +#. Button to reconnect/restart the engine from the recovery popup. +msgid "engine recovery: retry" +msgstr "重試" + +#. Link in tags should not be touched. Shown for remote engines. +msgid "remote engine check url suggestion" +msgstr "如果遠端引擎先前曾正常運作,請在它恢復後按「重試」以重新連線。否則,請在 {link} 中再次確認遠端引擎的網址。" + +msgid "engine:tab:local" +msgstr "本機引擎" + +msgid "engine:tab:remote" +msgstr "遠端引擎" + +msgid "engine:tab:custom" +msgstr "自訂命令" + +msgid "engine:backend:note" +msgstr "所選分頁決定使用的引擎。" diff --git a/katrain/i18n/locales/ua/LC_MESSAGES/katrain.mo b/katrain/i18n/locales/ua/LC_MESSAGES/katrain.mo index 496e7ef538295363e3e207b5132abc0a70bdd093..0f548731757bd5d767a1adbdd95be7080a57f58d 100644 GIT binary patch delta 6212 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 diff --git a/katrain/i18n/locales/ua/LC_MESSAGES/katrain.po b/katrain/i18n/locales/ua/LC_MESSAGES/katrain.po index 8f75b6d..cbbcae7 100644 --- a/katrain/i18n/locales/ua/LC_MESSAGES/katrain.po +++ b/katrain/i18n/locales/ua/LC_MESSAGES/katrain.po @@ -751,8 +751,9 @@ msgstr "" #. Link in tags should not be touched. msgid "change engine suggestion" msgstr "" -"Спочатку спробуйте завантажити інші версії KataGo і перевірте, чи допоможе " -"зміна виконуваного файлу в {link}." +"Спочатку натисніть «Повторити», щоб перезапустити рушій. Якщо це не " +"допомогло, спробуйте завантажити версії KataGo та змінити виконуваний файл у" +" {link} ." #. Link in tags should not be touched (uses link_here msgid) msgid "go to engine help page" @@ -1086,3 +1087,60 @@ msgstr "" #. TODO msgid "engine:humanlike_model" msgstr "Path to human-like model" + +#. TODO +msgid "engine:remote_url" +msgstr "KataGo WebSocket URL" + +#. TODO +msgid "engine:remote_url:hint" +msgstr "Leave blank to use a local KataGo engine. Use ws:// or wss://." + +#. TODO +msgid "Remote KataGo URL is empty" +msgstr "Remote KataGo URL is empty" + +#. TODO +msgid "Remote KataGo URL must start with ws:// or wss://" +msgstr "Remote KataGo URL must start with ws:// or wss://" + +#. TODO +msgid "Connecting to remote KataGo failed" +msgstr "Connecting to remote KataGo at {url} failed: {error}" + +#. TODO +msgid "Remote KataGo engine disconnected" +msgstr "Remote KataGo engine disconnected: {error}" + +#. Shown instead of "engine died popup opening message" for remote +#. engines. +msgid "remote engine disconnected popup opening message" +msgstr "" +"З'єднання з віддаленим рушієм KataGo втрачено й не вдалося відновити автоматично.\n" +"\n" +"Помилка: [color=#CC2222]{error_message}[/color]\n" +"\n" +"Код помилки: [color=#CC2222]{code}[/color]." + +#. Button to reconnect/restart the engine from the recovery popup. +msgid "engine recovery: retry" +msgstr "Повторити" + +#. Link in tags should not be touched. Shown for remote engines. +msgid "remote engine check url suggestion" +msgstr "" +"Якщо віддалений рушій раніше працював, натисніть «Повторити», щоб " +"під'єднатися знову, коли він стане доступним. Інакше перевірте URL-адресу " +"віддаленого рушія в {link} ." + +msgid "engine:tab:local" +msgstr "Локальний рушій" + +msgid "engine:tab:remote" +msgstr "Віддалений рушій" + +msgid "engine:tab:custom" +msgstr "Власна команда" + +msgid "engine:backend:note" +msgstr "Вибрана вкладка визначає використовуваний рушій." diff --git a/katrain/popups.kv b/katrain/popups.kv index 4a27b7a..72462f0 100644 --- a/katrain/popups.kv +++ b/katrain/popups.kv @@ -3,9 +3,11 @@ #:import expanduser os.path.expanduser #:import abspath os.path.abspath #:import kivy_version kivy.__version__ +#:import NoTransition kivy.uix.screenmanager.NoTransition #:import Theme katrain.gui.theme.Theme #:import LIGHT_GREY katrain.gui.theme.LIGHT_GREY +#:import ORANGE katrain.gui.theme.ORANGE #:set CP_SPACING Theme.CP_SPACING #:set CP_SMALL_SPACING Theme.CP_SMALL_SPACING @@ -92,131 +94,216 @@ katago_files: katago_files download_progress_box: download_progress_box katago_download_progress_box: katago_download_progress_box + engine_sm: engine_sm + local_tab_button: local_tab_button + remote_tab_button: remote_tab_button + custom_tab_button: custom_tab_button - # Top Section - KataGo Controls + # Top Section - Engine source header BoxLayout: orientation: 'horizontal' size_hint_y: None - height: dp(50) - spacing: dp(20) - padding: dp(10) + height: dp(36) + padding: dp(10), 0 DescriptionLabel: text: i18n._('katago settings') font_size: sp(Theme.DESC_FONT_SIZE) * 1.5 - size_hint_x: 0.4 + halign: 'left' - AutoSizedRoundedRectangleButton: - text: i18n._("download katago button") - on_press: root.download_katas() - size_hint: (0.3, 0.8) - - AutoSizedRoundedRectangleButton: - text: i18n._("download models button") - on_press: root.download_models() - size_hint: (0.3, 0.8) - - # Main Content Area + # Engine backend tabs, with the "tab is authoritative" note to their right MDBoxLayout: - orientation: 'vertical' + orientation: 'horizontal' + size_hint_y: None + height: dp(40) + spacing: dp(6) + padding: dp(8), 0 + + SizedRectangleToggleButton: + id: local_tab_button + size_hint: 0.22, 1 + group: 'engine_backend' + allow_no_selection: False + text: i18n._('engine:tab:local') + on_release: engine_sm.current = 'local' + + SizedRectangleToggleButton: + id: remote_tab_button + size_hint: 0.22, 1 + group: 'engine_backend' + allow_no_selection: False + text: i18n._('engine:tab:remote') + on_release: engine_sm.current = 'remote' + + SizedRectangleToggleButton: + id: custom_tab_button + size_hint: 0.22, 1 + group: 'engine_backend' + allow_no_selection: False + text: i18n._('engine:tab:custom') + on_release: engine_sm.current = 'custom' + + DescriptionLabel: + size_hint_x: 0.4 + text: i18n._('engine:backend:note') + color: ORANGE + halign: 'left' + valign: 'center' + padding: dp(10), 0 + + # Engine backend content - one screen per tab + ScreenManager: + id: engine_sm size_hint: (1, 6) - spacing: dp(15) - padding: dp(10) + transition: NoTransition() - # Model Section - ConfigSectionGridLayout: - cols: 2 - DescriptionLabel: - text: i18n._("engine:model") - size_hint: (0.33, 1) + Screen: + name: 'local' + MDBoxLayout: + orientation: 'vertical' + spacing: dp(12) + padding: dp(10) - AnchorLayout: - LabelledPathInput: - id: model_path - input_property: "engine/model" - on_text: root.check_models() + # KataGo executable - download button sits under its label + ConfigSectionGridLayout: + cols: 2 + MDBoxLayout: + orientation: 'vertical' + size_hint_x: 0.33 + spacing: dp(6) + DescriptionLabel: + text: i18n._("engine:katago") + AnchorLayout: + size_hint_y: None + height: dp(34) + AutoSizedRoundedRectangleButton: + text: i18n._("download katago button") + on_press: root.download_katas() + size_hint: None, None + height: dp(32) + MDBoxLayout: + orientation: 'vertical' + AnchorLayout: + LabelledPathInput: + id: katago_path + input_property: "engine/katago" + hint_text: i18n._("engine:katago:hint") + on_text: root.check_katas() + AnchorLayout: + KeyValueSpinner: + id: katago_files + text: '' + text_autoupdate: True + size_hint_y: 0.7 + on_select: if self.selected_index != 0: katago_path.text = self.value_keys[self.selected_index] - Label: - size_hint: (0.33, 1) + # Model - download button sits under its label + ConfigSectionGridLayout: + cols: 2 + MDBoxLayout: + orientation: 'vertical' + size_hint_x: 0.33 + spacing: dp(6) + DescriptionLabel: + text: i18n._("engine:model") + AnchorLayout: + size_hint_y: None + height: dp(34) + AutoSizedRoundedRectangleButton: + text: i18n._("download models button") + on_press: root.download_models() + size_hint: None, None + height: dp(32) + MDBoxLayout: + orientation: 'vertical' + AnchorLayout: + LabelledPathInput: + id: model_path + input_property: "engine/model" + on_text: root.check_models() + AnchorLayout: + KeyValueSpinner: + id: model_files + text: '' + text_autoupdate: True + size_hint_y: 0.7 + on_select: if self.selected_index != 0: model_path.text = self.value_keys[self.selected_index] - AnchorLayout: - KeyValueSpinner: - id: model_files - text: '' - text_autoupdate: True - size_hint_y: 0.7 - on_select: if self.selected_index != 0: model_path.text = self.value_keys[self.selected_index] + # Human-like model + ConfigSectionGridLayout: + cols: 2 + DescriptionLabel: + text: i18n._("engine:humanlike_model") + size_hint_x: 0.33 + MDBoxLayout: + orientation: 'vertical' + AnchorLayout: + LabelledPathInput: + id: humanlike_model_path + input_property: "engine/humanlike_model" + on_text: root.check_models() + AnchorLayout: + KeyValueSpinner: + id: humanlike_model_files + text: '' + text_autoupdate: True + size_hint_y: 0.7 + on_select: if self.selected_index != 0: humanlike_model_path.text = self.value_keys[self.selected_index] - # Humanlike Model Section - ConfigSectionGridLayout: - cols: 2 - DescriptionLabel: - text: i18n._("engine:humanlike_model") - size_hint: (0.33, 1) + # KataGo config file + ConfigSectionGridLayout: + cols: 2 + DescriptionLabel: + text: i18n._("engine:config") + size_hint_x: 0.33 + AnchorLayout: + LabelledPathInput: + input_property: "engine/config" - AnchorLayout: - LabelledPathInput: - id: humanlike_model_path - input_property: "engine/humanlike_model" - on_text: root.check_models() + Screen: + name: 'remote' + MDBoxLayout: + orientation: 'vertical' + spacing: dp(12) + padding: dp(10) + ConfigSectionGridLayout: + cols: 2 + size_hint_y: None + height: dp(70) + DescriptionLabel: + text: i18n._("engine:remote_url") + size_hint_x: 0.33 + AnchorLayout: + LabelledPathInput: + check_path: False + input_property: "engine/remote_url" + hint_text: i18n._("engine:remote_url:hint") + Widget: - Label: - size_hint: (0.33, 1) - - AnchorLayout: - KeyValueSpinner: - id: humanlike_model_files - text: '' - text_autoupdate: True - size_hint_y: 0.7 - on_select: if self.selected_index != 0: humanlike_model_path.text = self.value_keys[self.selected_index] - - # KataGo Engine Section - ConfigSectionGridLayout: - cols: 2 - DescriptionLabel: - text: i18n._("engine:katago") - size_hint: (0.33, 1) - - AnchorLayout: - LabelledPathInput: - id: katago_path - input_property: "engine/katago" - hint_text: i18n._("engine:katago:hint") - on_text: root.check_katas() - - Label: - size_hint: (0.33, 1) - - AnchorLayout: - KeyValueSpinner: - id: katago_files - text: '' - text_autoupdate: True - size_hint_y: 0.7 - on_select: if self.selected_index != 0: katago_path.text = self.value_keys[self.selected_index] - - ConfigSectionGridLayout: - rows: 2 - cols: 2 - DescriptionLabel: - text: i18n._("engine:config") - size_hint: 0.33, 1 - AnchorLayout: - LabelledPathInput: - input_property: "engine/config" - DescriptionLabel: - text: i18n._("engine:altcommand") - size_hint: 0.33, 1 - AnchorLayout: - LabelledPathInput: - check_path: False - input_property: "engine/altcommand" - hint_text: i18n._("engine:altcommand:hint") + Screen: + name: 'custom' + MDBoxLayout: + orientation: 'vertical' + spacing: dp(12) + padding: dp(10) + ConfigSectionGridLayout: + cols: 2 + size_hint_y: None + height: dp(70) + DescriptionLabel: + text: i18n._("engine:altcommand") + size_hint_x: 0.33 + AnchorLayout: + LabelledPathInput: + check_path: False + input_property: "engine/altcommand" + hint_text: i18n._("engine:altcommand:hint") + Widget: # Settings Headers MDBoxLayout: - size_hint_y: 0.5 + size_hint_y: None + height: dp(34) orientation: 'horizontal' padding: dp(10) spacing: dp(20) @@ -874,14 +961,23 @@ on_press: root.update_config(True) : + orientation: 'vertical' Label: + size_hint: 1, 0.85 padding: CP_PADDING, CP_PADDING*3 - text: i18n._("engine died popup opening message").format(code=root.code,error_message=root.error_message) + "\n\n" + i18n._("change engine suggestion").format(link="[color=#CCCC11][u][ref=engine_settings]"+i18n._('menu:settings')+"[/ref][/u][/color]") + "\n\n" + i18n._("go to engine help page").format(link="[color=#CCCC11][u][ref=engine_help]"+i18n._('link_here')+"[/ref][/u][/color]") + text: root.recovery_message text_size: self.size font_size: sp(Theme.DESC_FONT_SIZE) markup: True valign: 'top' on_ref_press: app.webbrowser('engine:help') if args[1]=='engine_help' else app.gui('config-popup') + AnchorLayout: + size_hint: 1, 0.15 + AutoSizedRoundedRectangleButton: + padding_x: 15 + size_hint: None, 0.66 + text: i18n._("engine recovery: retry") + on_release: root.retry() diff --git a/pyproject.toml b/pyproject.toml index fb80050..85f595d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "KaTrain" -version = "1.17.1" +version = "1.18.0" description = "Go/Baduk/Weiqi playing and teaching app with a variety of AIs" authors = [{ name = "Sander Land" }] requires-python = ">=3.9,<3.14" @@ -22,6 +22,8 @@ dependencies = [ "urllib3>=2.2.2", "kivy>=2.3.1", "kivymd==0.104.1", + "websocket-client>=1.9.0", + "certifi>=2026.2.25", ] [project.urls] diff --git a/tests/test_remote_engine.py b/tests/test_remote_engine.py new file mode 100644 index 0000000..7083869 --- /dev/null +++ b/tests/test_remote_engine.py @@ -0,0 +1,231 @@ +"""Tests for the remote (WebSocket) KataGo engine's reconnect logic. + +These use an in-process fake WebSocket so no network/server is needed: +`create_connection` is monkeypatched to hand out controllable sockets +whose recv()/send()/close() we drive from the test thread. +""" + +import queue +import threading +import time + +import pytest +from websocket import WebSocketException + +from katrain.core import remote_engine +from katrain.core.remote_engine import RemoteKataGoEngine + + +class FakeWS: + """Minimal stand-in for a websocket-client connection.""" + + def __init__(self): + self.sent = [] + self._recv = queue.Queue() + self.closed = False + + def recv_data(self, control_frame=True): + item = self._recv.get() # blocks like a real recv + if isinstance(item, BaseException): + raise item + return item + + def send(self, payload): + if self.closed: + raise WebSocketException("send on closed socket") + self.sent.append(payload) + + def close(self): + self.closed = True + self._recv.put(WebSocketException("closed")) + + def drop(self): + """Simulate the server/network dropping the connection.""" + self._recv.put(WebSocketException("connection lost")) + + +class FakeControls: + def set_status(self, *args, **kwargs): + pass + + +class FakeKatrain: + """Records calls (e.g. the engine_recovery_popup trigger).""" + + def __init__(self): + self.controls = FakeControls() + self.calls = [] + self.update_state = lambda *a, **k: None + + def log(self, *args, **kwargs): + pass + + def __call__(self, *args, **kwargs): + self.calls.append(args) + + +def wait_until(pred, timeout=5.0, interval=0.02): + end = time.time() + timeout + while time.time() < end and not pred(): + time.sleep(interval) + return pred() + + +def popup_codes(katrain): + return [args[2] for args in katrain.calls if args and args[0] == "engine_recovery_popup"] + + +@pytest.fixture +def fast_backoff(monkeypatch): + monkeypatch.setattr(RemoteKataGoEngine, "RECONNECT_BACKOFF_S", 0.01) + monkeypatch.setattr(RemoteKataGoEngine, "RECONNECT_MAX_BACKOFF_S", 0.02) + + +def test_reconnect_resends_outstanding_queries(monkeypatch, fast_backoff): + created = [] + + def factory(*args, **kwargs): + ws = FakeWS() + created.append(ws) + return ws + + monkeypatch.setattr(remote_engine, "create_connection", factory) + + katrain = FakeKatrain() + engine = RemoteKataGoEngine(katrain, {"remote_url": "ws://test", "allow_recovery": True}) + try: + assert wait_until(lambda: len(created) == 1) + ws1 = created[0] + + engine.send_query({"foo": "bar"}, lambda *a: None, None) + assert wait_until(lambda: len(ws1.sent) == 1) + assert wait_until(lambda: len(engine.queries) == 1) + + # Connection drops while a query is outstanding. + ws1.drop() + + # A new connection is established transparently... + assert wait_until(lambda: len(created) == 2) + ws2 = created[1] + assert wait_until(lambda: engine.ws is ws2) + + # ...and the in-flight query is re-sent on it. + assert wait_until(lambda: len(ws2.sent) >= 1) + + # No local-engine recovery popup was shown. + assert popup_codes(katrain) == [] + finally: + engine.shutdown() + + +def test_reconnect_failure_opens_recovery_popup(monkeypatch, fast_backoff): + monkeypatch.setattr(RemoteKataGoEngine, "RECONNECT_ATTEMPTS", 2) + first = FakeWS() + n = {"count": 0} + + def factory(*args, **kwargs): + n["count"] += 1 + if n["count"] == 1: + return first + raise WebSocketException("connection refused") + + monkeypatch.setattr(remote_engine, "create_connection", factory) + + katrain = FakeKatrain() + engine = RemoteKataGoEngine(katrain, {"remote_url": "ws://test", "allow_recovery": True}) + try: + assert wait_until(lambda: engine.ws is first) + + first.drop() + + # All reconnect attempts fail -> fall back to the recovery popup, + # tagged as a remote disconnect rather than a local crash. + assert wait_until(lambda: popup_codes(katrain) == ["REMOTE-DISCONNECTED"]) + + # The popup is told this is a remote engine so it shows remote- + # specific advice (check URL) instead of the local executable hints. + popup_call = next(args for args in katrain.calls if args and args[0] == "engine_recovery_popup") + assert popup_call[3] == "remote" + finally: + engine.shutdown() + + +def test_check_alive_polling_during_reconnect_does_not_suppress_popup(monkeypatch, fast_backoff): + # Reproduces the ai.py move loops, which spin on check_alive(exception_if_dead=True) + # every ~10ms. While reconnecting the socket is briefly None; those polls must not + # latch the engine "dead" and steal the recovery popup that fires on real failure. + monkeypatch.setattr(RemoteKataGoEngine, "RECONNECT_ATTEMPTS", 4) + first = FakeWS() + n = {"count": 0} + + def factory(*args, **kwargs): + n["count"] += 1 + if n["count"] == 1: + return first + raise WebSocketException("connection refused") + + monkeypatch.setattr(remote_engine, "create_connection", factory) + + katrain = FakeKatrain() + engine = RemoteKataGoEngine(katrain, {"remote_url": "ws://test", "allow_recovery": True}) + + stop = threading.Event() + seen_alive_while_reconnecting = {"v": False} + + def poller(): + while not stop.is_set(): + alive = engine.check_alive(exception_if_dead=True) + if engine._reconnecting and alive: + seen_alive_while_reconnecting["v"] = True + time.sleep(0.001) + + t = threading.Thread(target=poller, daemon=True) + try: + assert wait_until(lambda: engine.ws is first) + t.start() + first.drop() + + # Despite aggressive polling, the popup still fires exactly once. + assert wait_until(lambda: popup_codes(katrain) == ["REMOTE-DISCONNECTED"]) + time.sleep(0.05) # let the poller keep hammering after the report + assert popup_codes(katrain) == ["REMOTE-DISCONNECTED"] + # And check_alive reported "alive" during the reconnect window, not dead. + assert seen_alive_while_reconnecting["v"] + finally: + stop.set() + t.join(timeout=1) + engine.shutdown() + + +def test_new_game_clears_resend_backlog(monkeypatch, fast_backoff): + created = [] + + def factory(*args, **kwargs): + ws = FakeWS() + created.append(ws) + return ws + + monkeypatch.setattr(remote_engine, "create_connection", factory) + + katrain = FakeKatrain() + engine = RemoteKataGoEngine(katrain, {"remote_url": "ws://test", "allow_recovery": True}) + try: + ws1 = created[0] + engine.send_query({"foo": "bar"}, lambda *a: None, None) + assert wait_until(lambda: len(engine.sent_payloads) == 1) + + # Starting a new game drops outstanding queries; they must not be + # resurrected by a later reconnect. + engine.on_new_game() + assert engine.sent_payloads == {} + + ws1.drop() + assert wait_until(lambda: len(created) == 2) + ws2 = created[1] + assert wait_until(lambda: engine.ws is ws2) + # The previous game's analysis query is not resurrected (a leftover + # `terminate` command queued by on_new_game may still be sent). + time.sleep(0.1) + assert all("foo" not in payload for payload in ws2.sent) + finally: + engine.shutdown() diff --git a/uv.lock b/uv.lock index 5f66bc3..44fb314 100644 --- a/uv.lock +++ b/uv.lock @@ -1,5 +1,5 @@ version = 1 -revision = 2 +revision = 3 requires-python = ">=3.9, <3.14" resolution-markers = [ "python_full_version >= '3.10'", @@ -8,11 +8,11 @@ resolution-markers = [ [[package]] name = "altgraph" -version = "0.17.4" +version = "0.17.5" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/de/a8/7145824cf0b9e3c28046520480f207df47e927df83aa9555fb47f8505922/altgraph-0.17.4.tar.gz", hash = "sha256:1b5afbb98f6c4dcadb2e2ae6ab9fa994bbb8c1d75f4fa96d340f9437ae454406", size = 48418, upload-time = "2023-09-25T09:04:52.164Z" } +sdist = { url = "https://files.pythonhosted.org/packages/7e/f8/97fdf103f38fed6792a1601dbc16cc8aac56e7459a9fff08c812d8ae177a/altgraph-0.17.5.tar.gz", hash = "sha256:c87b395dd12fabde9c99573a9749d67da8d29ef9de0125c7f536699b4a9bc9e7", size = 48428, upload-time = "2025-11-21T20:35:50.583Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/4d/3f/3bc3f1d83f6e4a7fcb834d3720544ca597590425be5ba9db032b2bf322a2/altgraph-0.17.4-py2.py3-none-any.whl", hash = "sha256:642743b4750de17e655e6711601b077bc6598dbfa3ba5fa2b2a35ce12b508dff", size = 21212, upload-time = "2023-09-25T09:04:50.691Z" }, + { url = "https://files.pythonhosted.org/packages/a9/ba/000a1996d4308bc65120167c21241a3b205464a2e0b58deda26ae8ac21d1/altgraph-0.17.5-py2.py3-none-any.whl", hash = "sha256:f3a22400bce1b0c701683820ac4f3b159cd301acab067c51c653e06961600597", size = 21228, upload-time = "2025-11-21T20:35:49.444Z" }, ] [[package]] @@ -21,11 +21,12 @@ version = "24.10.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "click", version = "8.1.8", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "click", version = "8.2.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "click", version = "8.3.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "mypy-extensions" }, { name = "packaging" }, { name = "pathspec" }, - { name = "platformdirs" }, + { name = "platformdirs", version = "4.4.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "platformdirs", version = "4.9.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "tomli", marker = "python_full_version < '3.11'" }, { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] @@ -56,11 +57,11 @@ wheels = [ [[package]] name = "certifi" -version = "2025.6.15" +version = "2026.2.25" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/73/f7/f14b46d4bcd21092d7d3ccef689615220d8a08fb25e564b65d20738e672e/certifi-2025.6.15.tar.gz", hash = "sha256:d747aa5a8b9bbbb1bb8c22bb13e22bd1f18e9796defa16bab421f7f7a317323b", size = 158753, upload-time = "2025-06-15T02:45:51.329Z" } +sdist = { url = "https://files.pythonhosted.org/packages/af/2d/7bf41579a8986e348fa033a31cdd0e4121114f6bce2457e8876010b092dd/certifi-2026.2.25.tar.gz", hash = "sha256:e887ab5cee78ea814d3472169153c2d12cd43b14bd03329a39a9c6e2e80bfba7", size = 155029, upload-time = "2026-02-25T02:54:17.342Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/84/ae/320161bd181fc06471eed047ecce67b693fd7515b16d495d8932db763426/certifi-2025.6.15-py3-none-any.whl", hash = "sha256:2e0c7ce7cb5d8f8634ca55d2ba7e6ec2689a2fd6537d8dec1296a477a4910057", size = 157650, upload-time = "2025-06-15T02:45:49.977Z" }, + { url = "https://files.pythonhosted.org/packages/9a/3c/c17fb3ca2d9c3acff52e30b309f538586f9f5b9c9cf454f3845fc9af4881/certifi-2026.2.25-py3-none-any.whl", hash = "sha256:027692e4402ad994f1c42e52a4997a9763c646b73e4096e4d5d6db8af1d6f0fa", size = 153684, upload-time = "2026-02-25T02:54:15.766Z" }, ] [[package]] @@ -74,76 +75,91 @@ wheels = [ [[package]] name = "charset-normalizer" -version = "3.4.2" +version = "3.4.7" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e4/33/89c2ced2b67d1c2a61c19c6751aa8902d46ce3dacb23600a283619f5a12d/charset_normalizer-3.4.2.tar.gz", hash = "sha256:5baececa9ecba31eff645232d59845c07aa030f0c81ee70184a90d35099a0e63", size = 126367, upload-time = "2025-05-02T08:34:42.01Z" } +sdist = { url = "https://files.pythonhosted.org/packages/e7/a1/67fe25fac3c7642725500a3f6cfe5821ad557c3abb11c9d20d12c7008d3e/charset_normalizer-3.4.7.tar.gz", hash = "sha256:ae89db9e5f98a11a4bf50407d4363e7b09b31e55bc117b4f7d80aab97ba009e5", size = 144271, upload-time = "2026-04-02T09:28:39.342Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/95/28/9901804da60055b406e1a1c5ba7aac1276fb77f1dde635aabfc7fd84b8ab/charset_normalizer-3.4.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7c48ed483eb946e6c04ccbe02c6b4d1d48e51944b6db70f697e089c193404941", size = 201818, upload-time = "2025-05-02T08:31:46.725Z" }, - { url = "https://files.pythonhosted.org/packages/d9/9b/892a8c8af9110935e5adcbb06d9c6fe741b6bb02608c6513983048ba1a18/charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b2d318c11350e10662026ad0eb71bb51c7812fc8590825304ae0bdd4ac283acd", size = 144649, upload-time = "2025-05-02T08:31:48.889Z" }, - { url = "https://files.pythonhosted.org/packages/7b/a5/4179abd063ff6414223575e008593861d62abfc22455b5d1a44995b7c101/charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9cbfacf36cb0ec2897ce0ebc5d08ca44213af24265bd56eca54bee7923c48fd6", size = 155045, upload-time = "2025-05-02T08:31:50.757Z" }, - { url = "https://files.pythonhosted.org/packages/3b/95/bc08c7dfeddd26b4be8c8287b9bb055716f31077c8b0ea1cd09553794665/charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18dd2e350387c87dabe711b86f83c9c78af772c748904d372ade190b5c7c9d4d", size = 147356, upload-time = "2025-05-02T08:31:52.634Z" }, - { url = "https://files.pythonhosted.org/packages/a8/2d/7a5b635aa65284bf3eab7653e8b4151ab420ecbae918d3e359d1947b4d61/charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8075c35cd58273fee266c58c0c9b670947c19df5fb98e7b66710e04ad4e9ff86", size = 149471, upload-time = "2025-05-02T08:31:56.207Z" }, - { url = "https://files.pythonhosted.org/packages/ae/38/51fc6ac74251fd331a8cfdb7ec57beba8c23fd5493f1050f71c87ef77ed0/charset_normalizer-3.4.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5bf4545e3b962767e5c06fe1738f951f77d27967cb2caa64c28be7c4563e162c", size = 151317, upload-time = "2025-05-02T08:31:57.613Z" }, - { url = "https://files.pythonhosted.org/packages/b7/17/edee1e32215ee6e9e46c3e482645b46575a44a2d72c7dfd49e49f60ce6bf/charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:7a6ab32f7210554a96cd9e33abe3ddd86732beeafc7a28e9955cdf22ffadbab0", size = 146368, upload-time = "2025-05-02T08:31:59.468Z" }, - { url = "https://files.pythonhosted.org/packages/26/2c/ea3e66f2b5f21fd00b2825c94cafb8c326ea6240cd80a91eb09e4a285830/charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:b33de11b92e9f75a2b545d6e9b6f37e398d86c3e9e9653c4864eb7e89c5773ef", size = 154491, upload-time = "2025-05-02T08:32:01.219Z" }, - { url = "https://files.pythonhosted.org/packages/52/47/7be7fa972422ad062e909fd62460d45c3ef4c141805b7078dbab15904ff7/charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:8755483f3c00d6c9a77f490c17e6ab0c8729e39e6390328e42521ef175380ae6", size = 157695, upload-time = "2025-05-02T08:32:03.045Z" }, - { url = "https://files.pythonhosted.org/packages/2f/42/9f02c194da282b2b340f28e5fb60762de1151387a36842a92b533685c61e/charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:68a328e5f55ec37c57f19ebb1fdc56a248db2e3e9ad769919a58672958e8f366", size = 154849, upload-time = "2025-05-02T08:32:04.651Z" }, - { url = "https://files.pythonhosted.org/packages/67/44/89cacd6628f31fb0b63201a618049be4be2a7435a31b55b5eb1c3674547a/charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:21b2899062867b0e1fde9b724f8aecb1af14f2778d69aacd1a5a1853a597a5db", size = 150091, upload-time = "2025-05-02T08:32:06.719Z" }, - { url = "https://files.pythonhosted.org/packages/1f/79/4b8da9f712bc079c0f16b6d67b099b0b8d808c2292c937f267d816ec5ecc/charset_normalizer-3.4.2-cp310-cp310-win32.whl", hash = "sha256:e8082b26888e2f8b36a042a58307d5b917ef2b1cacab921ad3323ef91901c71a", size = 98445, upload-time = "2025-05-02T08:32:08.66Z" }, - { url = "https://files.pythonhosted.org/packages/7d/d7/96970afb4fb66497a40761cdf7bd4f6fca0fc7bafde3a84f836c1f57a926/charset_normalizer-3.4.2-cp310-cp310-win_amd64.whl", hash = "sha256:f69a27e45c43520f5487f27627059b64aaf160415589230992cec34c5e18a509", size = 105782, upload-time = "2025-05-02T08:32:10.46Z" }, - { url = "https://files.pythonhosted.org/packages/05/85/4c40d00dcc6284a1c1ad5de5e0996b06f39d8232f1031cd23c2f5c07ee86/charset_normalizer-3.4.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:be1e352acbe3c78727a16a455126d9ff83ea2dfdcbc83148d2982305a04714c2", size = 198794, upload-time = "2025-05-02T08:32:11.945Z" }, - { url = "https://files.pythonhosted.org/packages/41/d9/7a6c0b9db952598e97e93cbdfcb91bacd89b9b88c7c983250a77c008703c/charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa88ca0b1932e93f2d961bf3addbb2db902198dca337d88c89e1559e066e7645", size = 142846, upload-time = "2025-05-02T08:32:13.946Z" }, - { url = "https://files.pythonhosted.org/packages/66/82/a37989cda2ace7e37f36c1a8ed16c58cf48965a79c2142713244bf945c89/charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d524ba3f1581b35c03cb42beebab4a13e6cdad7b36246bd22541fa585a56cccd", size = 153350, upload-time = "2025-05-02T08:32:15.873Z" }, - { url = "https://files.pythonhosted.org/packages/df/68/a576b31b694d07b53807269d05ec3f6f1093e9545e8607121995ba7a8313/charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28a1005facc94196e1fb3e82a3d442a9d9110b8434fc1ded7a24a2983c9888d8", size = 145657, upload-time = "2025-05-02T08:32:17.283Z" }, - { url = "https://files.pythonhosted.org/packages/92/9b/ad67f03d74554bed3aefd56fe836e1623a50780f7c998d00ca128924a499/charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fdb20a30fe1175ecabed17cbf7812f7b804b8a315a25f24678bcdf120a90077f", size = 147260, upload-time = "2025-05-02T08:32:18.807Z" }, - { url = "https://files.pythonhosted.org/packages/a6/e6/8aebae25e328160b20e31a7e9929b1578bbdc7f42e66f46595a432f8539e/charset_normalizer-3.4.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0f5d9ed7f254402c9e7d35d2f5972c9bbea9040e99cd2861bd77dc68263277c7", size = 149164, upload-time = "2025-05-02T08:32:20.333Z" }, - { url = "https://files.pythonhosted.org/packages/8b/f2/b3c2f07dbcc248805f10e67a0262c93308cfa149a4cd3d1fe01f593e5fd2/charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:efd387a49825780ff861998cd959767800d54f8308936b21025326de4b5a42b9", size = 144571, upload-time = "2025-05-02T08:32:21.86Z" }, - { url = "https://files.pythonhosted.org/packages/60/5b/c3f3a94bc345bc211622ea59b4bed9ae63c00920e2e8f11824aa5708e8b7/charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f0aa37f3c979cf2546b73e8222bbfa3dc07a641585340179d768068e3455e544", size = 151952, upload-time = "2025-05-02T08:32:23.434Z" }, - { url = "https://files.pythonhosted.org/packages/e2/4d/ff460c8b474122334c2fa394a3f99a04cf11c646da895f81402ae54f5c42/charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:e70e990b2137b29dc5564715de1e12701815dacc1d056308e2b17e9095372a82", size = 155959, upload-time = "2025-05-02T08:32:24.993Z" }, - { url = "https://files.pythonhosted.org/packages/a2/2b/b964c6a2fda88611a1fe3d4c400d39c66a42d6c169c924818c848f922415/charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:0c8c57f84ccfc871a48a47321cfa49ae1df56cd1d965a09abe84066f6853b9c0", size = 153030, upload-time = "2025-05-02T08:32:26.435Z" }, - { url = "https://files.pythonhosted.org/packages/59/2e/d3b9811db26a5ebf444bc0fa4f4be5aa6d76fc6e1c0fd537b16c14e849b6/charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6b66f92b17849b85cad91259efc341dce9c1af48e2173bf38a85c6329f1033e5", size = 148015, upload-time = "2025-05-02T08:32:28.376Z" }, - { url = "https://files.pythonhosted.org/packages/90/07/c5fd7c11eafd561bb51220d600a788f1c8d77c5eef37ee49454cc5c35575/charset_normalizer-3.4.2-cp311-cp311-win32.whl", hash = "sha256:daac4765328a919a805fa5e2720f3e94767abd632ae410a9062dff5412bae65a", size = 98106, upload-time = "2025-05-02T08:32:30.281Z" }, - { url = "https://files.pythonhosted.org/packages/a8/05/5e33dbef7e2f773d672b6d79f10ec633d4a71cd96db6673625838a4fd532/charset_normalizer-3.4.2-cp311-cp311-win_amd64.whl", hash = "sha256:e53efc7c7cee4c1e70661e2e112ca46a575f90ed9ae3fef200f2a25e954f4b28", size = 105402, upload-time = "2025-05-02T08:32:32.191Z" }, - { url = "https://files.pythonhosted.org/packages/d7/a4/37f4d6035c89cac7930395a35cc0f1b872e652eaafb76a6075943754f095/charset_normalizer-3.4.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0c29de6a1a95f24b9a1aa7aefd27d2487263f00dfd55a77719b530788f75cff7", size = 199936, upload-time = "2025-05-02T08:32:33.712Z" }, - { url = "https://files.pythonhosted.org/packages/ee/8a/1a5e33b73e0d9287274f899d967907cd0bf9c343e651755d9307e0dbf2b3/charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cddf7bd982eaa998934a91f69d182aec997c6c468898efe6679af88283b498d3", size = 143790, upload-time = "2025-05-02T08:32:35.768Z" }, - { url = "https://files.pythonhosted.org/packages/66/52/59521f1d8e6ab1482164fa21409c5ef44da3e9f653c13ba71becdd98dec3/charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fcbe676a55d7445b22c10967bceaaf0ee69407fbe0ece4d032b6eb8d4565982a", size = 153924, upload-time = "2025-05-02T08:32:37.284Z" }, - { url = "https://files.pythonhosted.org/packages/86/2d/fb55fdf41964ec782febbf33cb64be480a6b8f16ded2dbe8db27a405c09f/charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d41c4d287cfc69060fa91cae9683eacffad989f1a10811995fa309df656ec214", size = 146626, upload-time = "2025-05-02T08:32:38.803Z" }, - { url = "https://files.pythonhosted.org/packages/8c/73/6ede2ec59bce19b3edf4209d70004253ec5f4e319f9a2e3f2f15601ed5f7/charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e594135de17ab3866138f496755f302b72157d115086d100c3f19370839dd3a", size = 148567, upload-time = "2025-05-02T08:32:40.251Z" }, - { url = "https://files.pythonhosted.org/packages/09/14/957d03c6dc343c04904530b6bef4e5efae5ec7d7990a7cbb868e4595ee30/charset_normalizer-3.4.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cf713fe9a71ef6fd5adf7a79670135081cd4431c2943864757f0fa3a65b1fafd", size = 150957, upload-time = "2025-05-02T08:32:41.705Z" }, - { url = "https://files.pythonhosted.org/packages/0d/c8/8174d0e5c10ccebdcb1b53cc959591c4c722a3ad92461a273e86b9f5a302/charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a370b3e078e418187da8c3674eddb9d983ec09445c99a3a263c2011993522981", size = 145408, upload-time = "2025-05-02T08:32:43.709Z" }, - { url = "https://files.pythonhosted.org/packages/58/aa/8904b84bc8084ac19dc52feb4f5952c6df03ffb460a887b42615ee1382e8/charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a955b438e62efdf7e0b7b52a64dc5c3396e2634baa62471768a64bc2adb73d5c", size = 153399, upload-time = "2025-05-02T08:32:46.197Z" }, - { url = "https://files.pythonhosted.org/packages/c2/26/89ee1f0e264d201cb65cf054aca6038c03b1a0c6b4ae998070392a3ce605/charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:7222ffd5e4de8e57e03ce2cef95a4c43c98fcb72ad86909abdfc2c17d227fc1b", size = 156815, upload-time = "2025-05-02T08:32:48.105Z" }, - { url = "https://files.pythonhosted.org/packages/fd/07/68e95b4b345bad3dbbd3a8681737b4338ff2c9df29856a6d6d23ac4c73cb/charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:bee093bf902e1d8fc0ac143c88902c3dfc8941f7ea1d6a8dd2bcb786d33db03d", size = 154537, upload-time = "2025-05-02T08:32:49.719Z" }, - { url = "https://files.pythonhosted.org/packages/77/1a/5eefc0ce04affb98af07bc05f3bac9094513c0e23b0562d64af46a06aae4/charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:dedb8adb91d11846ee08bec4c8236c8549ac721c245678282dcb06b221aab59f", size = 149565, upload-time = "2025-05-02T08:32:51.404Z" }, - { url = "https://files.pythonhosted.org/packages/37/a0/2410e5e6032a174c95e0806b1a6585eb21e12f445ebe239fac441995226a/charset_normalizer-3.4.2-cp312-cp312-win32.whl", hash = "sha256:db4c7bf0e07fc3b7d89ac2a5880a6a8062056801b83ff56d8464b70f65482b6c", size = 98357, upload-time = "2025-05-02T08:32:53.079Z" }, - { url = "https://files.pythonhosted.org/packages/6c/4f/c02d5c493967af3eda9c771ad4d2bbc8df6f99ddbeb37ceea6e8716a32bc/charset_normalizer-3.4.2-cp312-cp312-win_amd64.whl", hash = "sha256:5a9979887252a82fefd3d3ed2a8e3b937a7a809f65dcb1e068b090e165bbe99e", size = 105776, upload-time = "2025-05-02T08:32:54.573Z" }, - { url = "https://files.pythonhosted.org/packages/ea/12/a93df3366ed32db1d907d7593a94f1fe6293903e3e92967bebd6950ed12c/charset_normalizer-3.4.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:926ca93accd5d36ccdabd803392ddc3e03e6d4cd1cf17deff3b989ab8e9dbcf0", size = 199622, upload-time = "2025-05-02T08:32:56.363Z" }, - { url = "https://files.pythonhosted.org/packages/04/93/bf204e6f344c39d9937d3c13c8cd5bbfc266472e51fc8c07cb7f64fcd2de/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eba9904b0f38a143592d9fc0e19e2df0fa2e41c3c3745554761c5f6447eedabf", size = 143435, upload-time = "2025-05-02T08:32:58.551Z" }, - { url = "https://files.pythonhosted.org/packages/22/2a/ea8a2095b0bafa6c5b5a55ffdc2f924455233ee7b91c69b7edfcc9e02284/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3fddb7e2c84ac87ac3a947cb4e66d143ca5863ef48e4a5ecb83bd48619e4634e", size = 153653, upload-time = "2025-05-02T08:33:00.342Z" }, - { url = "https://files.pythonhosted.org/packages/b6/57/1b090ff183d13cef485dfbe272e2fe57622a76694061353c59da52c9a659/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98f862da73774290f251b9df8d11161b6cf25b599a66baf087c1ffe340e9bfd1", size = 146231, upload-time = "2025-05-02T08:33:02.081Z" }, - { url = "https://files.pythonhosted.org/packages/e2/28/ffc026b26f441fc67bd21ab7f03b313ab3fe46714a14b516f931abe1a2d8/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c9379d65defcab82d07b2a9dfbfc2e95bc8fe0ebb1b176a3190230a3ef0e07c", size = 148243, upload-time = "2025-05-02T08:33:04.063Z" }, - { url = "https://files.pythonhosted.org/packages/c0/0f/9abe9bd191629c33e69e47c6ef45ef99773320e9ad8e9cb08b8ab4a8d4cb/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e635b87f01ebc977342e2697d05b56632f5f879a4f15955dfe8cef2448b51691", size = 150442, upload-time = "2025-05-02T08:33:06.418Z" }, - { url = "https://files.pythonhosted.org/packages/67/7c/a123bbcedca91d5916c056407f89a7f5e8fdfce12ba825d7d6b9954a1a3c/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:1c95a1e2902a8b722868587c0e1184ad5c55631de5afc0eb96bc4b0d738092c0", size = 145147, upload-time = "2025-05-02T08:33:08.183Z" }, - { url = "https://files.pythonhosted.org/packages/ec/fe/1ac556fa4899d967b83e9893788e86b6af4d83e4726511eaaad035e36595/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ef8de666d6179b009dce7bcb2ad4c4a779f113f12caf8dc77f0162c29d20490b", size = 153057, upload-time = "2025-05-02T08:33:09.986Z" }, - { url = "https://files.pythonhosted.org/packages/2b/ff/acfc0b0a70b19e3e54febdd5301a98b72fa07635e56f24f60502e954c461/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:32fc0341d72e0f73f80acb0a2c94216bd704f4f0bce10aedea38f30502b271ff", size = 156454, upload-time = "2025-05-02T08:33:11.814Z" }, - { url = "https://files.pythonhosted.org/packages/92/08/95b458ce9c740d0645feb0e96cea1f5ec946ea9c580a94adfe0b617f3573/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:289200a18fa698949d2b39c671c2cc7a24d44096784e76614899a7ccf2574b7b", size = 154174, upload-time = "2025-05-02T08:33:13.707Z" }, - { url = "https://files.pythonhosted.org/packages/78/be/8392efc43487ac051eee6c36d5fbd63032d78f7728cb37aebcc98191f1ff/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4a476b06fbcf359ad25d34a057b7219281286ae2477cc5ff5e3f70a246971148", size = 149166, upload-time = "2025-05-02T08:33:15.458Z" }, - { url = "https://files.pythonhosted.org/packages/44/96/392abd49b094d30b91d9fbda6a69519e95802250b777841cf3bda8fe136c/charset_normalizer-3.4.2-cp313-cp313-win32.whl", hash = "sha256:aaeeb6a479c7667fbe1099af9617c83aaca22182d6cf8c53966491a0f1b7ffb7", size = 98064, upload-time = "2025-05-02T08:33:17.06Z" }, - { url = "https://files.pythonhosted.org/packages/e9/b0/0200da600134e001d91851ddc797809e2fe0ea72de90e09bec5a2fbdaccb/charset_normalizer-3.4.2-cp313-cp313-win_amd64.whl", hash = "sha256:aa6af9e7d59f9c12b33ae4e9450619cf2488e2bbe9b44030905877f0b2324980", size = 105641, upload-time = "2025-05-02T08:33:18.753Z" }, - { url = "https://files.pythonhosted.org/packages/28/f8/dfb01ff6cc9af38552c69c9027501ff5a5117c4cc18dcd27cb5259fa1888/charset_normalizer-3.4.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:005fa3432484527f9732ebd315da8da8001593e2cf46a3d817669f062c3d9ed4", size = 201671, upload-time = "2025-05-02T08:34:12.696Z" }, - { url = "https://files.pythonhosted.org/packages/32/fb/74e26ee556a9dbfe3bd264289b67be1e6d616329403036f6507bb9f3f29c/charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e92fca20c46e9f5e1bb485887d074918b13543b1c2a1185e69bb8d17ab6236a7", size = 144744, upload-time = "2025-05-02T08:34:14.665Z" }, - { url = "https://files.pythonhosted.org/packages/ad/06/8499ee5aa7addc6f6d72e068691826ff093329fe59891e83b092ae4c851c/charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:50bf98d5e563b83cc29471fa114366e6806bc06bc7a25fd59641e41445327836", size = 154993, upload-time = "2025-05-02T08:34:17.134Z" }, - { url = "https://files.pythonhosted.org/packages/f1/a2/5e4c187680728219254ef107a6949c60ee0e9a916a5dadb148c7ae82459c/charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:721c76e84fe669be19c5791da68232ca2e05ba5185575086e384352e2c309597", size = 147382, upload-time = "2025-05-02T08:34:19.081Z" }, - { url = "https://files.pythonhosted.org/packages/4c/fe/56aca740dda674f0cc1ba1418c4d84534be51f639b5f98f538b332dc9a95/charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82d8fd25b7f4675d0c47cf95b594d4e7b158aca33b76aa63d07186e13c0e0ab7", size = 149536, upload-time = "2025-05-02T08:34:21.073Z" }, - { url = "https://files.pythonhosted.org/packages/53/13/db2e7779f892386b589173dd689c1b1e304621c5792046edd8a978cbf9e0/charset_normalizer-3.4.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b3daeac64d5b371dea99714f08ffc2c208522ec6b06fbc7866a450dd446f5c0f", size = 151349, upload-time = "2025-05-02T08:34:23.193Z" }, - { url = "https://files.pythonhosted.org/packages/69/35/e52ab9a276186f729bce7a0638585d2982f50402046e4b0faa5d2c3ef2da/charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:dccab8d5fa1ef9bfba0590ecf4d46df048d18ffe3eec01eeb73a42e0d9e7a8ba", size = 146365, upload-time = "2025-05-02T08:34:25.187Z" }, - { url = "https://files.pythonhosted.org/packages/a6/d8/af7333f732fc2e7635867d56cb7c349c28c7094910c72267586947561b4b/charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:aaf27faa992bfee0264dc1f03f4c75e9fcdda66a519db6b957a3f826e285cf12", size = 154499, upload-time = "2025-05-02T08:34:27.359Z" }, - { url = "https://files.pythonhosted.org/packages/7a/3d/a5b2e48acef264d71e036ff30bcc49e51bde80219bb628ba3e00cf59baac/charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:eb30abc20df9ab0814b5a2524f23d75dcf83cde762c161917a2b4b7b55b1e518", size = 157735, upload-time = "2025-05-02T08:34:29.798Z" }, - { url = "https://files.pythonhosted.org/packages/85/d8/23e2c112532a29f3eef374375a8684a4f3b8e784f62b01da931186f43494/charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:c72fbbe68c6f32f251bdc08b8611c7b3060612236e960ef848e0a517ddbe76c5", size = 154786, upload-time = "2025-05-02T08:34:31.858Z" }, - { url = "https://files.pythonhosted.org/packages/c7/57/93e0169f08ecc20fe82d12254a200dfaceddc1c12a4077bf454ecc597e33/charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:982bb1e8b4ffda883b3d0a521e23abcd6fd17418f6d2c4118d257a10199c0ce3", size = 150203, upload-time = "2025-05-02T08:34:33.88Z" }, - { url = "https://files.pythonhosted.org/packages/2c/9d/9bf2b005138e7e060d7ebdec7503d0ef3240141587651f4b445bdf7286c2/charset_normalizer-3.4.2-cp39-cp39-win32.whl", hash = "sha256:43e0933a0eff183ee85833f341ec567c0980dae57c464d8a508e1b2ceb336471", size = 98436, upload-time = "2025-05-02T08:34:35.907Z" }, - { url = "https://files.pythonhosted.org/packages/6d/24/5849d46cf4311bbf21b424c443b09b459f5b436b1558c04e45dbb7cc478b/charset_normalizer-3.4.2-cp39-cp39-win_amd64.whl", hash = "sha256:d11b54acf878eef558599658b0ffca78138c8c3655cf4f3a4a673c437e67732e", size = 105772, upload-time = "2025-05-02T08:34:37.935Z" }, - { url = "https://files.pythonhosted.org/packages/20/94/c5790835a017658cbfabd07f3bfb549140c3ac458cfc196323996b10095a/charset_normalizer-3.4.2-py3-none-any.whl", hash = "sha256:7f56930ab0abd1c45cd15be65cc741c28b1c9a34876ce8c17a2fa107810c0af0", size = 52626, upload-time = "2025-05-02T08:34:40.053Z" }, + { url = "https://files.pythonhosted.org/packages/26/08/0f303cb0b529e456bb116f2d50565a482694fbb94340bf56d44677e7ed03/charset_normalizer-3.4.7-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cdd68a1fb318e290a2077696b7eb7a21a49163c455979c639bf5a5dcdc46617d", size = 315182, upload-time = "2026-04-02T09:25:40.673Z" }, + { url = "https://files.pythonhosted.org/packages/24/47/b192933e94b546f1b1fe4df9cc1f84fcdbf2359f8d1081d46dd029b50207/charset_normalizer-3.4.7-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e17b8d5d6a8c47c85e68ca8379def1303fd360c3e22093a807cd34a71cd082b8", size = 209329, upload-time = "2026-04-02T09:25:42.354Z" }, + { url = "https://files.pythonhosted.org/packages/c2/b4/01fa81c5ca6141024d89a8fc15968002b71da7f825dd14113207113fabbd/charset_normalizer-3.4.7-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:511ef87c8aec0783e08ac18565a16d435372bc1ac25a91e6ac7f5ef2b0bff790", size = 231230, upload-time = "2026-04-02T09:25:44.281Z" }, + { url = "https://files.pythonhosted.org/packages/20/f7/7b991776844dfa058017e600e6e55ff01984a063290ca5622c0b63162f68/charset_normalizer-3.4.7-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:007d05ec7321d12a40227aae9e2bc6dca73f3cb21058999a1df9e193555a9dcc", size = 225890, upload-time = "2026-04-02T09:25:45.475Z" }, + { url = "https://files.pythonhosted.org/packages/20/e7/bed0024a0f4ab0c8a9c64d4445f39b30c99bd1acd228291959e3de664247/charset_normalizer-3.4.7-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cf29836da5119f3c8a8a70667b0ef5fdca3bb12f80fd06487cfa575b3909b393", size = 216930, upload-time = "2026-04-02T09:25:46.58Z" }, + { url = "https://files.pythonhosted.org/packages/e2/ab/b18f0ab31cdd7b3ddb8bb76c4a414aeb8160c9810fdf1bc62f269a539d87/charset_normalizer-3.4.7-cp310-cp310-manylinux_2_31_armv7l.whl", hash = "sha256:12d8baf840cc7889b37c7c770f478adea7adce3dcb3944d02ec87508e2dcf153", size = 202109, upload-time = "2026-04-02T09:25:48.031Z" }, + { url = "https://files.pythonhosted.org/packages/82/e5/7e9440768a06dfb3075936490cb82dbf0ee20a133bf0dd8551fa096914ec/charset_normalizer-3.4.7-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d560742f3c0d62afaccf9f41fe485ed69bd7661a241f86a3ef0f0fb8b1a397af", size = 214684, upload-time = "2026-04-02T09:25:49.245Z" }, + { url = "https://files.pythonhosted.org/packages/71/94/8c61d8da9f062fdf457c80acfa25060ec22bf1d34bbeaca4350f13bcfd07/charset_normalizer-3.4.7-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:b14b2d9dac08e28bb8046a1a0434b1750eb221c8f5b87a68f4fa11a6f97b5e34", size = 212785, upload-time = "2026-04-02T09:25:50.671Z" }, + { url = "https://files.pythonhosted.org/packages/66/cd/6e9889c648e72c0ab2e5967528bb83508f354d706637bc7097190c874e13/charset_normalizer-3.4.7-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:bc17a677b21b3502a21f66a8cc64f5bfad4df8a0b8434d661666f8ce90ac3af1", size = 203055, upload-time = "2026-04-02T09:25:51.802Z" }, + { url = "https://files.pythonhosted.org/packages/92/2e/7a951d6a08aefb7eb8e1b54cdfb580b1365afdd9dd484dc4bee9e5d8f258/charset_normalizer-3.4.7-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:750e02e074872a3fad7f233b47734166440af3cdea0add3e95163110816d6752", size = 232502, upload-time = "2026-04-02T09:25:53.388Z" }, + { url = "https://files.pythonhosted.org/packages/58/d5/abcf2d83bf8e0a1286df55cd0dc1d49af0da4282aa77e986df343e7de124/charset_normalizer-3.4.7-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:4e5163c14bffd570ef2affbfdd77bba66383890797df43dc8b4cc7d6f500bf53", size = 214295, upload-time = "2026-04-02T09:25:54.765Z" }, + { url = "https://files.pythonhosted.org/packages/47/3a/7d4cd7ed54be99973a0dc176032cba5cb1f258082c31fa6df35cff46acfc/charset_normalizer-3.4.7-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:6ed74185b2db44f41ef35fd1617c5888e59792da9bbc9190d6c7300617182616", size = 227145, upload-time = "2026-04-02T09:25:55.904Z" }, + { url = "https://files.pythonhosted.org/packages/1d/98/3a45bf8247889cf28262ebd3d0872edff11565b2a1e3064ccb132db3fbb0/charset_normalizer-3.4.7-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:94e1885b270625a9a828c9793b4d52a64445299baa1fea5a173bf1d3dd9a1a5a", size = 218884, upload-time = "2026-04-02T09:25:57.074Z" }, + { url = "https://files.pythonhosted.org/packages/ad/80/2e8b7f8915ed5c9ef13aa828d82738e33888c485b65ebf744d615040c7ea/charset_normalizer-3.4.7-cp310-cp310-win32.whl", hash = "sha256:6785f414ae0f3c733c437e0f3929197934f526d19dfaa75e18fdb4f94c6fb374", size = 148343, upload-time = "2026-04-02T09:25:58.199Z" }, + { url = "https://files.pythonhosted.org/packages/35/1b/3b8c8c77184af465ee9ad88b5aea46ea6b2e1f7b9dc9502891e37af21e30/charset_normalizer-3.4.7-cp310-cp310-win_amd64.whl", hash = "sha256:6696b7688f54f5af4462118f0bfa7c1621eeb87154f77fa04b9295ce7a8f2943", size = 159174, upload-time = "2026-04-02T09:25:59.322Z" }, + { url = "https://files.pythonhosted.org/packages/be/c1/feb40dca40dbb21e0a908801782d9288c64fc8d8e562c2098e9994c8c21b/charset_normalizer-3.4.7-cp310-cp310-win_arm64.whl", hash = "sha256:66671f93accb62ed07da56613636f3641f1a12c13046ce91ffc923721f23c008", size = 147805, upload-time = "2026-04-02T09:26:00.756Z" }, + { url = "https://files.pythonhosted.org/packages/c2/d7/b5b7020a0565c2e9fa8c09f4b5fa6232feb326b8c20081ccded47ea368fd/charset_normalizer-3.4.7-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7641bb8895e77f921102f72833904dcd9901df5d6d72a2ab8f31d04b7e51e4e7", size = 309705, upload-time = "2026-04-02T09:26:02.191Z" }, + { url = "https://files.pythonhosted.org/packages/5a/53/58c29116c340e5456724ecd2fff4196d236b98f3da97b404bc5e51ac3493/charset_normalizer-3.4.7-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:202389074300232baeb53ae2569a60901f7efadd4245cf3a3bf0617d60b439d7", size = 206419, upload-time = "2026-04-02T09:26:03.583Z" }, + { url = "https://files.pythonhosted.org/packages/b2/02/e8146dc6591a37a00e5144c63f29fb7c97a734ea8a111190783c0e60ab63/charset_normalizer-3.4.7-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:30b8d1d8c52a48c2c5690e152c169b673487a2a58de1ec7393196753063fcd5e", size = 227901, upload-time = "2026-04-02T09:26:04.738Z" }, + { url = "https://files.pythonhosted.org/packages/fb/73/77486c4cd58f1267bf17db420e930c9afa1b3be3fe8c8b8ebbebc9624359/charset_normalizer-3.4.7-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:532bc9bf33a68613fd7d65e4b1c71a6a38d7d42604ecf239c77392e9b4e8998c", size = 222742, upload-time = "2026-04-02T09:26:06.36Z" }, + { url = "https://files.pythonhosted.org/packages/a1/fa/f74eb381a7d94ded44739e9d94de18dc5edc9c17fb8c11f0a6890696c0a9/charset_normalizer-3.4.7-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2fe249cb4651fd12605b7288b24751d8bfd46d35f12a20b1ba33dea122e690df", size = 214061, upload-time = "2026-04-02T09:26:08.347Z" }, + { url = "https://files.pythonhosted.org/packages/dc/92/42bd3cefcf7687253fb86694b45f37b733c97f59af3724f356fa92b8c344/charset_normalizer-3.4.7-cp311-cp311-manylinux_2_31_armv7l.whl", hash = "sha256:65bcd23054beab4d166035cabbc868a09c1a49d1efe458fe8e4361215df40265", size = 199239, upload-time = "2026-04-02T09:26:09.823Z" }, + { url = "https://files.pythonhosted.org/packages/4c/3d/069e7184e2aa3b3cddc700e3dd267413dc259854adc3380421c805c6a17d/charset_normalizer-3.4.7-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:08e721811161356f97b4059a9ba7bafb23ea5ee2255402c42881c214e173c6b4", size = 210173, upload-time = "2026-04-02T09:26:10.953Z" }, + { url = "https://files.pythonhosted.org/packages/62/51/9d56feb5f2e7074c46f93e0ebdbe61f0848ee246e2f0d89f8e20b89ebb8f/charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e060d01aec0a910bdccb8be71faf34e7799ce36950f8294c8bf612cba65a2c9e", size = 209841, upload-time = "2026-04-02T09:26:12.142Z" }, + { url = "https://files.pythonhosted.org/packages/d2/59/893d8f99cc4c837dda1fe2f1139079703deb9f321aabcb032355de13b6c7/charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:38c0109396c4cfc574d502df99742a45c72c08eff0a36158b6f04000043dbf38", size = 200304, upload-time = "2026-04-02T09:26:13.711Z" }, + { url = "https://files.pythonhosted.org/packages/7d/1d/ee6f3be3464247578d1ed5c46de545ccc3d3ff933695395c402c21fa6b77/charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:1c2a768fdd44ee4a9339a9b0b130049139b8ce3c01d2ce09f67f5a68048d477c", size = 229455, upload-time = "2026-04-02T09:26:14.941Z" }, + { url = "https://files.pythonhosted.org/packages/54/bb/8fb0a946296ea96a488928bdce8ef99023998c48e4713af533e9bb98ef07/charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:1a87ca9d5df6fe460483d9a5bbf2b18f620cbed41b432e2bddb686228282d10b", size = 210036, upload-time = "2026-04-02T09:26:16.478Z" }, + { url = "https://files.pythonhosted.org/packages/9a/bc/015b2387f913749f82afd4fcba07846d05b6d784dd16123cb66860e0237d/charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:d635aab80466bc95771bb78d5370e74d36d1fe31467b6b29b8b57b2a3cd7d22c", size = 224739, upload-time = "2026-04-02T09:26:17.751Z" }, + { url = "https://files.pythonhosted.org/packages/17/ab/63133691f56baae417493cba6b7c641571a2130eb7bceba6773367ab9ec5/charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ae196f021b5e7c78e918242d217db021ed2a6ace2bc6ae94c0fc596221c7f58d", size = 216277, upload-time = "2026-04-02T09:26:18.981Z" }, + { url = "https://files.pythonhosted.org/packages/06/6d/3be70e827977f20db77c12a97e6a9f973631a45b8d186c084527e53e77a4/charset_normalizer-3.4.7-cp311-cp311-win32.whl", hash = "sha256:adb2597b428735679446b46c8badf467b4ca5f5056aae4d51a19f9570301b1ad", size = 147819, upload-time = "2026-04-02T09:26:20.295Z" }, + { url = "https://files.pythonhosted.org/packages/20/d9/5f67790f06b735d7c7637171bbfd89882ad67201891b7275e51116ed8207/charset_normalizer-3.4.7-cp311-cp311-win_amd64.whl", hash = "sha256:8e385e4267ab76874ae30db04c627faaaf0b509e1ccc11a95b3fc3e83f855c00", size = 159281, upload-time = "2026-04-02T09:26:21.74Z" }, + { url = "https://files.pythonhosted.org/packages/ca/83/6413f36c5a34afead88ce6f66684d943d91f233d76dd083798f9602b75ae/charset_normalizer-3.4.7-cp311-cp311-win_arm64.whl", hash = "sha256:d4a48e5b3c2a489fae013b7589308a40146ee081f6f509e047e0e096084ceca1", size = 147843, upload-time = "2026-04-02T09:26:22.901Z" }, + { url = "https://files.pythonhosted.org/packages/0c/eb/4fc8d0a7110eb5fc9cc161723a34a8a6c200ce3b4fbf681bc86feee22308/charset_normalizer-3.4.7-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:eca9705049ad3c7345d574e3510665cb2cf844c2f2dcfe675332677f081cbd46", size = 311328, upload-time = "2026-04-02T09:26:24.331Z" }, + { url = "https://files.pythonhosted.org/packages/f8/e3/0fadc706008ac9d7b9b5be6dc767c05f9d3e5df51744ce4cc9605de7b9f4/charset_normalizer-3.4.7-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6178f72c5508bfc5fd446a5905e698c6212932f25bcdd4b47a757a50605a90e2", size = 208061, upload-time = "2026-04-02T09:26:25.568Z" }, + { url = "https://files.pythonhosted.org/packages/42/f0/3dd1045c47f4a4604df85ec18ad093912ae1344ac706993aff91d38773a2/charset_normalizer-3.4.7-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e1421b502d83040e6d7fb2fb18dff63957f720da3d77b2fbd3187ceb63755d7b", size = 229031, upload-time = "2026-04-02T09:26:26.865Z" }, + { url = "https://files.pythonhosted.org/packages/dc/67/675a46eb016118a2fbde5a277a5d15f4f69d5f3f5f338e5ee2f8948fcf43/charset_normalizer-3.4.7-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:edac0f1ab77644605be2cbba52e6b7f630731fc42b34cb0f634be1a6eface56a", size = 225239, upload-time = "2026-04-02T09:26:28.044Z" }, + { url = "https://files.pythonhosted.org/packages/4b/f8/d0118a2f5f23b02cd166fa385c60f9b0d4f9194f574e2b31cef350ad7223/charset_normalizer-3.4.7-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5649fd1c7bade02f320a462fdefd0b4bd3ce036065836d4f42e0de958038e116", size = 216589, upload-time = "2026-04-02T09:26:29.239Z" }, + { url = "https://files.pythonhosted.org/packages/b1/f1/6d2b0b261b6c4ceef0fcb0d17a01cc5bc53586c2d4796fa04b5c540bc13d/charset_normalizer-3.4.7-cp312-cp312-manylinux_2_31_armv7l.whl", hash = "sha256:203104ed3e428044fd943bc4bf45fa73c0730391f9621e37fe39ecf477b128cb", size = 202733, upload-time = "2026-04-02T09:26:30.5Z" }, + { url = "https://files.pythonhosted.org/packages/6f/c0/7b1f943f7e87cc3db9626ba17807d042c38645f0a1d4415c7a14afb5591f/charset_normalizer-3.4.7-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:298930cec56029e05497a76988377cbd7457ba864beeea92ad7e844fe74cd1f1", size = 212652, upload-time = "2026-04-02T09:26:31.709Z" }, + { url = "https://files.pythonhosted.org/packages/38/dd/5a9ab159fe45c6e72079398f277b7d2b523e7f716acc489726115a910097/charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:708838739abf24b2ceb208d0e22403dd018faeef86ddac04319a62ae884c4f15", size = 211229, upload-time = "2026-04-02T09:26:33.282Z" }, + { url = "https://files.pythonhosted.org/packages/d5/ff/531a1cad5ca855d1c1a8b69cb71abfd6d85c0291580146fda7c82857caa1/charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:0f7eb884681e3938906ed0434f20c63046eacd0111c4ba96f27b76084cd679f5", size = 203552, upload-time = "2026-04-02T09:26:34.845Z" }, + { url = "https://files.pythonhosted.org/packages/c1/4c/a5fb52d528a8ca41f7598cb619409ece30a169fbdf9cdce592e53b46c3a6/charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:4dc1e73c36828f982bfe79fadf5919923f8a6f4df2860804db9a98c48824ce8d", size = 230806, upload-time = "2026-04-02T09:26:36.152Z" }, + { url = "https://files.pythonhosted.org/packages/59/7a/071feed8124111a32b316b33ae4de83d36923039ef8cf48120266844285b/charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:aed52fea0513bac0ccde438c188c8a471c4e0f457c2dd20cdbf6ea7a450046c7", size = 212316, upload-time = "2026-04-02T09:26:37.672Z" }, + { url = "https://files.pythonhosted.org/packages/fd/35/f7dba3994312d7ba508e041eaac39a36b120f32d4c8662b8814dab876431/charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:fea24543955a6a729c45a73fe90e08c743f0b3334bbf3201e6c4bc1b0c7fa464", size = 227274, upload-time = "2026-04-02T09:26:38.93Z" }, + { url = "https://files.pythonhosted.org/packages/8a/2d/a572df5c9204ab7688ec1edc895a73ebded3b023bb07364710b05dd1c9be/charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:bb6d88045545b26da47aa879dd4a89a71d1dce0f0e549b1abcb31dfe4a8eac49", size = 218468, upload-time = "2026-04-02T09:26:40.17Z" }, + { url = "https://files.pythonhosted.org/packages/86/eb/890922a8b03a568ca2f336c36585a4713c55d4d67bf0f0c78924be6315ca/charset_normalizer-3.4.7-cp312-cp312-win32.whl", hash = "sha256:2257141f39fe65a3fdf38aeccae4b953e5f3b3324f4ff0daf9f15b8518666a2c", size = 148460, upload-time = "2026-04-02T09:26:41.416Z" }, + { url = "https://files.pythonhosted.org/packages/35/d9/0e7dffa06c5ab081f75b1b786f0aefc88365825dfcd0ac544bdb7b2b6853/charset_normalizer-3.4.7-cp312-cp312-win_amd64.whl", hash = "sha256:5ed6ab538499c8644b8a3e18debabcd7ce684f3fa91cf867521a7a0279cab2d6", size = 159330, upload-time = "2026-04-02T09:26:42.554Z" }, + { url = "https://files.pythonhosted.org/packages/9e/5d/481bcc2a7c88ea6b0878c299547843b2521ccbc40980cb406267088bc701/charset_normalizer-3.4.7-cp312-cp312-win_arm64.whl", hash = "sha256:56be790f86bfb2c98fb742ce566dfb4816e5a83384616ab59c49e0604d49c51d", size = 147828, upload-time = "2026-04-02T09:26:44.075Z" }, + { url = "https://files.pythonhosted.org/packages/c1/3b/66777e39d3ae1ddc77ee606be4ec6d8cbd4c801f65e5a1b6f2b11b8346dd/charset_normalizer-3.4.7-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:f496c9c3cc02230093d8330875c4c3cdfc3b73612a5fd921c65d39cbcef08063", size = 309627, upload-time = "2026-04-02T09:26:45.198Z" }, + { url = "https://files.pythonhosted.org/packages/2e/4e/b7f84e617b4854ade48a1b7915c8ccfadeba444d2a18c291f696e37f0d3b/charset_normalizer-3.4.7-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0ea948db76d31190bf08bd371623927ee1339d5f2a0b4b1b4a4439a65298703c", size = 207008, upload-time = "2026-04-02T09:26:46.824Z" }, + { url = "https://files.pythonhosted.org/packages/c4/bb/ec73c0257c9e11b268f018f068f5d00aa0ef8c8b09f7753ebd5f2880e248/charset_normalizer-3.4.7-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a277ab8928b9f299723bc1a2dabb1265911b1a76341f90a510368ca44ad9ab66", size = 228303, upload-time = "2026-04-02T09:26:48.397Z" }, + { url = "https://files.pythonhosted.org/packages/85/fb/32d1f5033484494619f701e719429c69b766bfc4dbc61aa9e9c8c166528b/charset_normalizer-3.4.7-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3bec022aec2c514d9cf199522a802bd007cd588ab17ab2525f20f9c34d067c18", size = 224282, upload-time = "2026-04-02T09:26:49.684Z" }, + { url = "https://files.pythonhosted.org/packages/fa/07/330e3a0dda4c404d6da83b327270906e9654a24f6c546dc886a0eb0ffb23/charset_normalizer-3.4.7-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e044c39e41b92c845bc815e5ae4230804e8e7bc29e399b0437d64222d92809dd", size = 215595, upload-time = "2026-04-02T09:26:50.915Z" }, + { url = "https://files.pythonhosted.org/packages/e3/7c/fc890655786e423f02556e0216d4b8c6bcb6bdfa890160dc66bf52dee468/charset_normalizer-3.4.7-cp313-cp313-manylinux_2_31_armv7l.whl", hash = "sha256:f495a1652cf3fbab2eb0639776dad966c2fb874d79d87ca07f9d5f059b8bd215", size = 201986, upload-time = "2026-04-02T09:26:52.197Z" }, + { url = "https://files.pythonhosted.org/packages/d8/97/bfb18b3db2aed3b90cf54dc292ad79fdd5ad65c4eae454099475cbeadd0d/charset_normalizer-3.4.7-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e712b419df8ba5e42b226c510472b37bd57b38e897d3eca5e8cfd410a29fa859", size = 211711, upload-time = "2026-04-02T09:26:53.49Z" }, + { url = "https://files.pythonhosted.org/packages/6f/a5/a581c13798546a7fd557c82614a5c65a13df2157e9ad6373166d2a3e645d/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7804338df6fcc08105c7745f1502ba68d900f45fd770d5bdd5288ddccb8a42d8", size = 210036, upload-time = "2026-04-02T09:26:54.975Z" }, + { url = "https://files.pythonhosted.org/packages/8c/bf/b3ab5bcb478e4193d517644b0fb2bf5497fbceeaa7a1bc0f4d5b50953861/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:481551899c856c704d58119b5025793fa6730adda3571971af568f66d2424bb5", size = 202998, upload-time = "2026-04-02T09:26:56.303Z" }, + { url = "https://files.pythonhosted.org/packages/e7/4e/23efd79b65d314fa320ec6017b4b5834d5c12a58ba4610aa353af2e2f577/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:f59099f9b66f0d7145115e6f80dd8b1d847176df89b234a5a6b3f00437aa0832", size = 230056, upload-time = "2026-04-02T09:26:57.554Z" }, + { url = "https://files.pythonhosted.org/packages/b9/9f/1e1941bc3f0e01df116e68dc37a55c4d249df5e6fa77f008841aef68264f/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:f59ad4c0e8f6bba240a9bb85504faa1ab438237199d4cce5f622761507b8f6a6", size = 211537, upload-time = "2026-04-02T09:26:58.843Z" }, + { url = "https://files.pythonhosted.org/packages/80/0f/088cbb3020d44428964a6c97fe1edfb1b9550396bf6d278330281e8b709c/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:3dedcc22d73ec993f42055eff4fcfed9318d1eeb9a6606c55892a26964964e48", size = 226176, upload-time = "2026-04-02T09:27:00.437Z" }, + { url = "https://files.pythonhosted.org/packages/6a/9f/130394f9bbe06f4f63e22641d32fc9b202b7e251c9aef4db044324dac493/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:64f02c6841d7d83f832cd97ccf8eb8a906d06eb95d5276069175c696b024b60a", size = 217723, upload-time = "2026-04-02T09:27:02.021Z" }, + { url = "https://files.pythonhosted.org/packages/73/55/c469897448a06e49f8fa03f6caae97074fde823f432a98f979cc42b90e69/charset_normalizer-3.4.7-cp313-cp313-win32.whl", hash = "sha256:4042d5c8f957e15221d423ba781e85d553722fc4113f523f2feb7b188cc34c5e", size = 148085, upload-time = "2026-04-02T09:27:03.192Z" }, + { url = "https://files.pythonhosted.org/packages/5d/78/1b74c5bbb3f99b77a1715c91b3e0b5bdb6fe302d95ace4f5b1bec37b0167/charset_normalizer-3.4.7-cp313-cp313-win_amd64.whl", hash = "sha256:3946fa46a0cf3e4c8cb1cc52f56bb536310d34f25f01ca9b6c16afa767dab110", size = 158819, upload-time = "2026-04-02T09:27:04.454Z" }, + { url = "https://files.pythonhosted.org/packages/68/86/46bd42279d323deb8687c4a5a811fd548cb7d1de10cf6535d099877a9a9f/charset_normalizer-3.4.7-cp313-cp313-win_arm64.whl", hash = "sha256:80d04837f55fc81da168b98de4f4b797ef007fc8a79ab71c6ec9bc4dd662b15b", size = 147915, upload-time = "2026-04-02T09:27:05.971Z" }, + { url = "https://files.pythonhosted.org/packages/01/1b/ef725f8eb19b5a261b30f78efa9252ef9d017985cb499102f6f49834cd12/charset_normalizer-3.4.7-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:177a0ba5f0211d488e295aaf82707237e331c24788d8d76c96c5a41594723217", size = 299121, upload-time = "2026-04-02T09:28:14.372Z" }, + { url = "https://files.pythonhosted.org/packages/a3/22/2f12878fbc680fbbb52386cd39a379801f62eaca74fc8b323381325f0f04/charset_normalizer-3.4.7-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6e0d51f618228538a3e8f46bd246f87a6cd030565e015803691603f55e12afb5", size = 200612, upload-time = "2026-04-02T09:28:16.162Z" }, + { url = "https://files.pythonhosted.org/packages/bc/b6/10c84e789126ca97d4a7228863a30481e786980a8b8cfcbf4f30658ca63c/charset_normalizer-3.4.7-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:14265bfe1f09498b9d8ec91e9ec9fa52775edf90fcbde092b25f4a33d444fea9", size = 221041, upload-time = "2026-04-02T09:28:17.554Z" }, + { url = "https://files.pythonhosted.org/packages/21/7b/c414866a138400b2e81973d006da7f694cfeaf895ef07d2cba9a8743841a/charset_normalizer-3.4.7-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:87fad7d9ba98c86bcb41b2dc8dbb326619be2562af1f8ff50776a39e55721c5a", size = 216323, upload-time = "2026-04-02T09:28:18.863Z" }, + { url = "https://files.pythonhosted.org/packages/2e/92/bdcf94997e06b223d826df3abed45a5ad6e17f609b7df9d25cd23b5bde30/charset_normalizer-3.4.7-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f22dec1690b584cea26fade98b2435c132c1b5f68e39f5a0b7627cd7ae31f1dc", size = 208419, upload-time = "2026-04-02T09:28:20.332Z" }, + { url = "https://files.pythonhosted.org/packages/1a/64/3f9142293c88b1b10e199649ed1330f070c2a68e305335a5819fa7f25fa7/charset_normalizer-3.4.7-cp39-cp39-manylinux_2_31_armv7l.whl", hash = "sha256:d61f00a0869d77422d9b2aba989e2d24afa6ffd552af442e0e58de4f35ea6d00", size = 195016, upload-time = "2026-04-02T09:28:21.657Z" }, + { url = "https://files.pythonhosted.org/packages/c1/d1/d8a6b7dd5c5636b76ce0d080bc57d8e56c7bbd6bc2ac941529a35e41d84a/charset_normalizer-3.4.7-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:6370e8686f662e6a3941ee48ed4742317cafbe5707e36406e9df792cdb535776", size = 206115, upload-time = "2026-04-02T09:28:23.259Z" }, + { url = "https://files.pythonhosted.org/packages/dd/8c/60ebe912379627d023eb96995b40bc50308729f210f43d66109ca0a7bbd2/charset_normalizer-3.4.7-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:a6c5863edfbe888d9eff9c8b8087354e27618d9da76425c119293f11712a6319", size = 204022, upload-time = "2026-04-02T09:28:24.779Z" }, + { url = "https://files.pythonhosted.org/packages/d5/2a/41816ceda78a551cbfdfbeab6f3891152b0e3f758ce6580c2c18c829f774/charset_normalizer-3.4.7-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:ed065083d0898c9d5b4bbec7b026fd755ff7454e6e8b73a67f8c744b13986e24", size = 195914, upload-time = "2026-04-02T09:28:26.181Z" }, + { url = "https://files.pythonhosted.org/packages/8f/9b/7c7f4b7f11525fcbdfba752455314ac60646bae91cdd671d531c1f7a97c6/charset_normalizer-3.4.7-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:2cd4a60d0e2fb04537162c62bbbb4182f53541fe0ede35cdf270a1c1e723cc42", size = 222159, upload-time = "2026-04-02T09:28:27.504Z" }, + { url = "https://files.pythonhosted.org/packages/9f/57/301682e7469bdbfa2ce219a804f0668b2266ab8520570d85d3b3ef483ea3/charset_normalizer-3.4.7-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:813c0e0132266c08eb87469a642cb30aaff57c5f426255419572aaeceeaa7bf4", size = 206154, upload-time = "2026-04-02T09:28:28.848Z" }, + { url = "https://files.pythonhosted.org/packages/20/ec/90339ff5cdc598b265748c1f231c7d7fbd9123a92cee10f757e0b1448de4/charset_normalizer-3.4.7-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:07d9e39b01743c3717745f4c530a6349eadbfa043c7577eef86c502c15df2c67", size = 217423, upload-time = "2026-04-02T09:28:30.248Z" }, + { url = "https://files.pythonhosted.org/packages/2e/e7/a7a6147f8e3375676309cf584b25c72a3bab784ea4085b0011fa07b23aeb/charset_normalizer-3.4.7-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c0f081d69a6e58272819b70288d3221a6ee64b98df852631c80f293514d3b274", size = 210604, upload-time = "2026-04-02T09:28:31.736Z" }, + { url = "https://files.pythonhosted.org/packages/1a/62/d9340c7a79c393e57807d7fb6c57e82060687891f81b74d3201958b919c1/charset_normalizer-3.4.7-cp39-cp39-win32.whl", hash = "sha256:8751d2787c9131302398b11e6c8068053dcb55d5a8964e114b6e196cf16cb366", size = 144631, upload-time = "2026-04-02T09:28:33.158Z" }, + { url = "https://files.pythonhosted.org/packages/21/e7/92901117e2ddc8facfe8235a3ecd4eb482185b2ad5d5b6606b37c1afea06/charset_normalizer-3.4.7-cp39-cp39-win_amd64.whl", hash = "sha256:12a6fff75f6bc66711b73a2f0addfc4c8c15a20e805146a02d147a318962c444", size = 154710, upload-time = "2026-04-02T09:28:34.557Z" }, + { url = "https://files.pythonhosted.org/packages/cc/4f/e1fb138201ad9a32499dd9a98aa4a5a5441fbf7f56b52b619a54b7ee8777/charset_normalizer-3.4.7-cp39-cp39-win_arm64.whl", hash = "sha256:bb8cc7534f51d9a017b93e3e85b260924f909601c3df002bcdb58ddb4dc41a5c", size = 143716, upload-time = "2026-04-02T09:28:35.908Z" }, + { url = "https://files.pythonhosted.org/packages/db/8f/61959034484a4a7c527811f4721e75d02d653a35afb0b6054474d8185d4c/charset_normalizer-3.4.7-py3-none-any.whl", hash = "sha256:3dce51d0f5e7951f8bb4900c257dad282f49190fdbebecd4ba99bcc41fef404d", size = 61958, upload-time = "2026-04-02T09:28:37.794Z" }, ] [[package]] @@ -163,7 +179,7 @@ wheels = [ [[package]] name = "click" -version = "8.2.1" +version = "8.3.2" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version >= '3.10'", @@ -171,9 +187,9 @@ resolution-markers = [ dependencies = [ { name = "colorama", marker = "python_full_version >= '3.10' and sys_platform == 'win32'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/60/6c/8ca2efa64cf75a977a0d7fac081354553ebe483345c734fb6b6515d96bbc/click-8.2.1.tar.gz", hash = "sha256:27c491cc05d968d271d5a1db13e3b5a184636d9d930f148c50b038f0d0646202", size = 286342, upload-time = "2025-05-20T23:19:49.832Z" } +sdist = { url = "https://files.pythonhosted.org/packages/57/75/31212c6bf2503fdf920d87fee5d7a86a2e3bcf444984126f13d8e4016804/click-8.3.2.tar.gz", hash = "sha256:14162b8b3b3550a7d479eafa77dfd3c38d9dc8951f6f69c78913a8f9a7540fd5", size = 302856, upload-time = "2026-04-03T19:14:45.118Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/85/32/10bb5764d90a8eee674e9dc6f4db6a0ab47c8c4d0d83c27f7c39ac415a4d/click-8.2.1-py3-none-any.whl", hash = "sha256:61a3265b914e850b85317d0b3109c7f8cd35a670f963866005d6ef1d5175a12b", size = 102215, upload-time = "2025-05-20T23:19:47.796Z" }, + { url = "https://files.pythonhosted.org/packages/e4/20/71885d8b97d4f3dde17b1fdb92dbd4908b00541c5a3379787137285f602e/click-8.3.2-py3-none-any.whl", hash = "sha256:1924d2c27c5653561cd2cae4548d1406039cb79b858b747cfea24924bbc1616d", size = 108379, upload-time = "2026-04-03T19:14:43.505Z" }, ] [[package]] @@ -187,23 +203,23 @@ wheels = [ [[package]] name = "docutils" -version = "0.21.2" +version = "0.22.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, upload-time = "2024-04-23T18:57:18.24Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ae/b6/03bb70946330e88ffec97aefd3ea75ba575cb2e762061e0e62a213befee8/docutils-0.22.4.tar.gz", hash = "sha256:4db53b1fde9abecbb74d91230d32ab626d94f6badfc575d6db9194a49df29968", size = 2291750, upload-time = "2025-12-18T19:00:26.443Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/8f/d7/9322c609343d929e75e7e5e6255e614fcc67572cfd083959cdef3b7aad79/docutils-0.21.2-py3-none-any.whl", hash = "sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2", size = 587408, upload-time = "2024-04-23T18:57:14.835Z" }, + { url = "https://files.pythonhosted.org/packages/02/10/5da547df7a391dcde17f59520a231527b8571e6f46fc8efb02ccb370ab12/docutils-0.22.4-py3-none-any.whl", hash = "sha256:d0013f540772d1420576855455d050a2180186c91c15779301ac2ccb3eeb68de", size = 633196, upload-time = "2025-12-18T19:00:18.077Z" }, ] [[package]] name = "exceptiongroup" -version = "1.3.0" +version = "1.3.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions", marker = "python_full_version < '3.13'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/0b/9f/a65090624ecf468cdca03533906e7c69ed7588582240cfe7cc9e770b50eb/exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88", size = 29749, upload-time = "2025-05-10T17:42:51.123Z" } +sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/36/f4/c6e662dade71f56cd2f3735141b265c3c79293c109549c1e6933b0651ffc/exceptiongroup-1.3.0-py3-none-any.whl", hash = "sha256:4d111e6e0c13d0644cad6ddaa7ed0261a0b36971f6d23e7ec9b4b9097da78a10", size = 16674, upload-time = "2025-05-10T17:42:49.33Z" }, + { url = "https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598", size = 16740, upload-time = "2025-11-21T23:01:53.443Z" }, ] [[package]] @@ -255,39 +271,55 @@ wheels = [ [[package]] name = "idna" -version = "3.10" +version = "3.11" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490, upload-time = "2024-09-15T18:07:39.745Z" } +sdist = { url = "https://files.pythonhosted.org/packages/6f/6d/0703ccc57f3a7233505399edb88de3cbd678da106337b9fcde432b65ed60/idna-3.11.tar.gz", hash = "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902", size = 194582, upload-time = "2025-10-12T14:55:20.501Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442, upload-time = "2024-09-15T18:07:37.964Z" }, + { url = "https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea", size = 71008, upload-time = "2025-10-12T14:55:18.883Z" }, ] [[package]] name = "importlib-metadata" -version = "8.7.0" +version = "8.7.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "zipp" }, + { name = "zipp", marker = "python_full_version < '3.10'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/76/66/650a33bd90f786193e4de4b3ad86ea60b53c89b669a5c7be931fac31cdb0/importlib_metadata-8.7.0.tar.gz", hash = "sha256:d13b81ad223b890aa16c5471f2ac3056cf76c5f10f82d6f9292f0b415f389000", size = 56641, upload-time = "2025-04-27T15:29:01.736Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f3/49/3b30cad09e7771a4982d9975a8cbf64f00d4a1ececb53297f1d9a7be1b10/importlib_metadata-8.7.1.tar.gz", hash = "sha256:49fef1ae6440c182052f407c8d34a68f72efc36db9ca90dc0113398f2fdde8bb", size = 57107, upload-time = "2025-12-21T10:00:19.278Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/20/b0/36bd937216ec521246249be3bf9855081de4c5e06a0c9b4219dbeda50373/importlib_metadata-8.7.0-py3-none-any.whl", hash = "sha256:e5dd1551894c77868a30651cef00984d50e1002d06942a7101d34870c5f02afd", size = 27656, upload-time = "2025-04-27T15:29:00.214Z" }, + { url = "https://files.pythonhosted.org/packages/fa/5e/f8e9a1d23b9c20a551a8a02ea3637b4642e22c2626e3a13a9a29cdea99eb/importlib_metadata-8.7.1-py3-none-any.whl", hash = "sha256:5a1f80bf1daa489495071efbb095d75a634cf28a8bc299581244063b53176151", size = 27865, upload-time = "2025-12-21T10:00:18.329Z" }, ] [[package]] name = "iniconfig" version = "2.1.0" source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.10'", +] sdist = { url = "https://files.pythonhosted.org/packages/f2/97/ebf4da567aa6827c909642694d71c9fcf53e5b504f2d96afea02718862f3/iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7", size = 4793, upload-time = "2025-03-19T20:09:59.721Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/2c/e1/e6716421ea10d38022b952c159d5161ca1193197fb744506875fbb87ea7b/iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760", size = 6050, upload-time = "2025-03-19T20:10:01.071Z" }, ] +[[package]] +name = "iniconfig" +version = "2.3.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.10'", +] +sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" }, +] + [[package]] name = "katrain" -version = "1.17.1" +version = "1.17.2" source = { editable = "." } dependencies = [ + { name = "certifi" }, { name = "chardet" }, { name = "docutils" }, { name = "ffpyplayer" }, @@ -295,7 +327,9 @@ dependencies = [ { name = "kivymd" }, { name = "pygame", marker = "sys_platform == 'darwin'" }, { name = "screeninfo", marker = "sys_platform != 'darwin'" }, - { name = "urllib3" }, + { name = "urllib3", version = "2.6.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "urllib3", version = "2.7.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "websocket-client" }, ] [package.dev-dependencies] @@ -309,6 +343,7 @@ dev = [ [package.metadata] requires-dist = [ + { name = "certifi", specifier = ">=2026.2.25" }, { name = "chardet", specifier = ">=5.2.0,<6" }, { name = "docutils", specifier = ">=0.21.2" }, { name = "ffpyplayer", specifier = ">=4.5.1" }, @@ -317,6 +352,7 @@ requires-dist = [ { name = "pygame", marker = "sys_platform == 'darwin'", specifier = "~=2.0" }, { name = "screeninfo", marker = "sys_platform != 'darwin'", specifier = ">=0.8.1,<0.9" }, { name = "urllib3", specifier = ">=2.2.2" }, + { name = "websocket-client", specifier = ">=1.9.0" }, ] [package.metadata.requires-dev] @@ -341,7 +377,8 @@ dependencies = [ { name = "kivy-garden" }, { name = "pygments" }, { name = "pypiwin32", marker = "sys_platform == 'win32'" }, - { name = "requests" }, + { name = "requests", version = "2.32.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "requests", version = "2.33.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/de/48/c40f023dc103bdbd56db11facbb2d0ecbf4b019f7392875ee2a8227cb51e/Kivy-2.3.1.tar.gz", hash = "sha256:0833949e3502cdb4abcf9c1da4384674045ad7d85644313aa1ee7573f3b4f9d9", size = 23967306, upload-time = "2024-12-26T16:13:49.299Z" } wheels = [ @@ -416,7 +453,8 @@ name = "kivy-garden" version = "0.1.5" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "requests" }, + { name = "requests", version = "2.32.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "requests", version = "2.33.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, ] wheels = [ { url = "https://files.pythonhosted.org/packages/6a/55/cd1555bde62f809219cbc5d8a0836b0293399da2f4ba4e8ee84b6a7cc393/Kivy_Garden-0.1.5-py3-none-any.whl", hash = "sha256:ef50f44b96358cf10ac5665f27a4751bb34ef54051c54b93af891f80afe42929", size = 4623, upload-time = "2022-03-23T23:25:33.752Z" }, @@ -428,8 +466,10 @@ version = "0.104.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "kivy" }, - { name = "pillow" }, - { name = "requests" }, + { name = "pillow", version = "11.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "pillow", version = "12.2.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "requests", version = "2.32.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "requests", version = "2.33.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/37/a1/460313db291c9cd4a128d4f58f08faf2bf3e4c9dc5ca935b489e06efd7f4/kivymd-0.104.1.tar.gz", hash = "sha256:9dcbc2cb8affde9c82572198fddb32c814cdd57254a0e4b00c53882db2c8d6a6", size = 2347484, upload-time = "2020-04-27T20:04:28.274Z" } wheels = [ @@ -438,14 +478,14 @@ wheels = [ [[package]] name = "macholib" -version = "1.16.3" +version = "1.16.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "altgraph" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/95/ee/af1a3842bdd5902ce133bd246eb7ffd4375c38642aeb5dc0ae3a0329dfa2/macholib-1.16.3.tar.gz", hash = "sha256:07ae9e15e8e4cd9a788013d81f5908b3609aa76f9b1421bae9c4d7606ec86a30", size = 59309, upload-time = "2023-09-25T09:10:16.155Z" } +sdist = { url = "https://files.pythonhosted.org/packages/10/2f/97589876ea967487978071c9042518d28b958d87b17dceb7cdc1d881f963/macholib-1.16.4.tar.gz", hash = "sha256:f408c93ab2e995cd2c46e34fe328b130404be143469e41bc366c807448979362", size = 59427, upload-time = "2025-11-22T08:28:38.373Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d1/5d/c059c180c84f7962db0aeae7c3b9303ed1d73d76f2bfbc32bc231c8be314/macholib-1.16.3-py2.py3-none-any.whl", hash = "sha256:0e315d7583d38b8c77e815b1ecbdbf504a8258d8b3e17b61165c6feb60d18f2c", size = 38094, upload-time = "2023-09-25T09:10:14.188Z" }, + { url = "https://files.pythonhosted.org/packages/c7/d1/a9f36f8ecdf0fb7c9b1e78c8d7af12b8c8754e74851ac7b94a8305540fc7/macholib-1.16.4-py2.py3-none-any.whl", hash = "sha256:da1a3fa8266e30f0ce7e97c6a54eefaae8edd1e5f86f3eb8b95457cae90265ea", size = 38117, upload-time = "2025-11-22T08:28:36.939Z" }, ] [[package]] @@ -459,126 +499,223 @@ wheels = [ [[package]] name = "packaging" -version = "25.0" +version = "26.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727, upload-time = "2025-04-19T11:48:59.673Z" } +sdist = { url = "https://files.pythonhosted.org/packages/df/de/0d2b39fb4af88a0258f3bac87dfcbb48e73fbdea4a2ed0e2213f9a4c2f9a/packaging-26.1.tar.gz", hash = "sha256:f042152b681c4bfac5cae2742a55e103d27ab2ec0f3d88037136b6bfe7c9c5de", size = 215519, upload-time = "2026-04-14T21:12:49.362Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" }, + { url = "https://files.pythonhosted.org/packages/7a/c2/920ef838e2f0028c8262f16101ec09ebd5969864e5a64c4c05fad0617c56/packaging-26.1-py3-none-any.whl", hash = "sha256:5d9c0669c6285e491e0ced2eee587eaf67b670d94a19e94e3984a481aba6802f", size = 95831, upload-time = "2026-04-14T21:12:47.56Z" }, ] [[package]] name = "pathspec" -version = "0.12.1" +version = "1.0.4" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ca/bc/f35b8446f4531a7cb215605d100cd88b7ac6f44ab3fc94870c120ab3adbf/pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712", size = 51043, upload-time = "2023-12-10T22:30:45Z" } +sdist = { url = "https://files.pythonhosted.org/packages/fa/36/e27608899f9b8d4dff0617b2d9ab17ca5608956ca44461ac14ac48b44015/pathspec-1.0.4.tar.gz", hash = "sha256:0210e2ae8a21a9137c0d470578cb0e595af87edaa6ebf12ff176f14a02e0e645", size = 131200, upload-time = "2026-01-27T03:59:46.938Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191, upload-time = "2023-12-10T22:30:43.14Z" }, + { url = "https://files.pythonhosted.org/packages/ef/3c/2c197d226f9ea224a9ab8d197933f9da0ae0aac5b6e0f884e2b8d9c8e9f7/pathspec-1.0.4-py3-none-any.whl", hash = "sha256:fb6ae2fd4e7c921a165808a552060e722767cfa526f99ca5156ed2ce45a5c723", size = 55206, upload-time = "2026-01-27T03:59:45.137Z" }, ] [[package]] name = "pefile" -version = "2023.2.7" +version = "2024.8.26" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/78/c5/3b3c62223f72e2360737fd2a57c30e5b2adecd85e70276879609a7403334/pefile-2023.2.7.tar.gz", hash = "sha256:82e6114004b3d6911c77c3953e3838654b04511b8b66e8583db70c65998017dc", size = 74854, upload-time = "2023-02-07T12:23:55.958Z" } +sdist = { url = "https://files.pythonhosted.org/packages/03/4f/2750f7f6f025a1507cd3b7218691671eecfd0bbebebe8b39aa0fe1d360b8/pefile-2024.8.26.tar.gz", hash = "sha256:3ff6c5d8b43e8c37bb6e6dd5085658d658a7a0bdcd20b6a07b1fcfc1c4e9d632", size = 76008, upload-time = "2024-08-26T20:58:38.155Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/55/26/d0ad8b448476d0a1e8d3ea5622dc77b916db84c6aa3cb1e1c0965af948fc/pefile-2023.2.7-py3-none-any.whl", hash = "sha256:da185cd2af68c08a6cd4481f7325ed600a88f6a813bad9dea07ab3ef73d8d8d6", size = 71791, upload-time = "2023-02-07T12:28:36.678Z" }, + { url = "https://files.pythonhosted.org/packages/54/16/12b82f791c7f50ddec566873d5bdd245baa1491bac11d15ffb98aecc8f8b/pefile-2024.8.26-py3-none-any.whl", hash = "sha256:76f8b485dcd3b1bb8166f1128d395fa3d87af26360c2358fb75b80019b957c6f", size = 74766, upload-time = "2024-08-26T21:01:02.632Z" }, ] [[package]] name = "pillow" -version = "11.2.1" +version = "11.3.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/af/cb/bb5c01fcd2a69335b86c22142b2bccfc3464087efb7fd382eee5ffc7fdf7/pillow-11.2.1.tar.gz", hash = "sha256:a64dd61998416367b7ef979b73d3a85853ba9bec4c2925f74e588879a58716b6", size = 47026707, upload-time = "2025-04-12T17:50:03.289Z" } +resolution-markers = [ + "python_full_version < '3.10'", +] +sdist = { url = "https://files.pythonhosted.org/packages/f3/0d/d0d6dea55cd152ce3d6767bb38a8fc10e33796ba4ba210cbab9354b6d238/pillow-11.3.0.tar.gz", hash = "sha256:3828ee7586cd0b2091b6209e5ad53e20d0649bbe87164a459d0676e035e8f523", size = 47113069, upload-time = "2025-07-01T09:16:30.666Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/0d/8b/b158ad57ed44d3cc54db8d68ad7c0a58b8fc0e4c7a3f995f9d62d5b464a1/pillow-11.2.1-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:d57a75d53922fc20c165016a20d9c44f73305e67c351bbc60d1adaf662e74047", size = 3198442, upload-time = "2025-04-12T17:47:10.666Z" }, - { url = "https://files.pythonhosted.org/packages/b1/f8/bb5d956142f86c2d6cc36704943fa761f2d2e4c48b7436fd0a85c20f1713/pillow-11.2.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:127bf6ac4a5b58b3d32fc8289656f77f80567d65660bc46f72c0d77e6600cc95", size = 3030553, upload-time = "2025-04-12T17:47:13.153Z" }, - { url = "https://files.pythonhosted.org/packages/22/7f/0e413bb3e2aa797b9ca2c5c38cb2e2e45d88654e5b12da91ad446964cfae/pillow-11.2.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b4ba4be812c7a40280629e55ae0b14a0aafa150dd6451297562e1764808bbe61", size = 4405503, upload-time = "2025-04-12T17:47:15.36Z" }, - { url = "https://files.pythonhosted.org/packages/f3/b4/cc647f4d13f3eb837d3065824aa58b9bcf10821f029dc79955ee43f793bd/pillow-11.2.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c8bd62331e5032bc396a93609982a9ab6b411c05078a52f5fe3cc59234a3abd1", size = 4490648, upload-time = "2025-04-12T17:47:17.37Z" }, - { url = "https://files.pythonhosted.org/packages/c2/6f/240b772a3b35cdd7384166461567aa6713799b4e78d180c555bd284844ea/pillow-11.2.1-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:562d11134c97a62fe3af29581f083033179f7ff435f78392565a1ad2d1c2c45c", size = 4508937, upload-time = "2025-04-12T17:47:19.066Z" }, - { url = "https://files.pythonhosted.org/packages/f3/5e/7ca9c815ade5fdca18853db86d812f2f188212792780208bdb37a0a6aef4/pillow-11.2.1-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:c97209e85b5be259994eb5b69ff50c5d20cca0f458ef9abd835e262d9d88b39d", size = 4599802, upload-time = "2025-04-12T17:47:21.404Z" }, - { url = "https://files.pythonhosted.org/packages/02/81/c3d9d38ce0c4878a77245d4cf2c46d45a4ad0f93000227910a46caff52f3/pillow-11.2.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:0c3e6d0f59171dfa2e25d7116217543310908dfa2770aa64b8f87605f8cacc97", size = 4576717, upload-time = "2025-04-12T17:47:23.571Z" }, - { url = "https://files.pythonhosted.org/packages/42/49/52b719b89ac7da3185b8d29c94d0e6aec8140059e3d8adcaa46da3751180/pillow-11.2.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:cc1c3bc53befb6096b84165956e886b1729634a799e9d6329a0c512ab651e579", size = 4654874, upload-time = "2025-04-12T17:47:25.783Z" }, - { url = "https://files.pythonhosted.org/packages/5b/0b/ede75063ba6023798267023dc0d0401f13695d228194d2242d5a7ba2f964/pillow-11.2.1-cp310-cp310-win32.whl", hash = "sha256:312c77b7f07ab2139924d2639860e084ec2a13e72af54d4f08ac843a5fc9c79d", size = 2331717, upload-time = "2025-04-12T17:47:28.922Z" }, - { url = "https://files.pythonhosted.org/packages/ed/3c/9831da3edea527c2ed9a09f31a2c04e77cd705847f13b69ca60269eec370/pillow-11.2.1-cp310-cp310-win_amd64.whl", hash = "sha256:9bc7ae48b8057a611e5fe9f853baa88093b9a76303937449397899385da06fad", size = 2676204, upload-time = "2025-04-12T17:47:31.283Z" }, - { url = "https://files.pythonhosted.org/packages/01/97/1f66ff8a1503d8cbfc5bae4dc99d54c6ec1e22ad2b946241365320caabc2/pillow-11.2.1-cp310-cp310-win_arm64.whl", hash = "sha256:2728567e249cdd939f6cc3d1f049595c66e4187f3c34078cbc0a7d21c47482d2", size = 2414767, upload-time = "2025-04-12T17:47:34.655Z" }, - { url = "https://files.pythonhosted.org/packages/68/08/3fbf4b98924c73037a8e8b4c2c774784805e0fb4ebca6c5bb60795c40125/pillow-11.2.1-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:35ca289f712ccfc699508c4658a1d14652e8033e9b69839edf83cbdd0ba39e70", size = 3198450, upload-time = "2025-04-12T17:47:37.135Z" }, - { url = "https://files.pythonhosted.org/packages/84/92/6505b1af3d2849d5e714fc75ba9e69b7255c05ee42383a35a4d58f576b16/pillow-11.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e0409af9f829f87a2dfb7e259f78f317a5351f2045158be321fd135973fff7bf", size = 3030550, upload-time = "2025-04-12T17:47:39.345Z" }, - { url = "https://files.pythonhosted.org/packages/3c/8c/ac2f99d2a70ff966bc7eb13dacacfaab57c0549b2ffb351b6537c7840b12/pillow-11.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4e5c5edee874dce4f653dbe59db7c73a600119fbea8d31f53423586ee2aafd7", size = 4415018, upload-time = "2025-04-12T17:47:41.128Z" }, - { url = "https://files.pythonhosted.org/packages/1f/e3/0a58b5d838687f40891fff9cbaf8669f90c96b64dc8f91f87894413856c6/pillow-11.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b93a07e76d13bff9444f1a029e0af2964e654bfc2e2c2d46bfd080df5ad5f3d8", size = 4498006, upload-time = "2025-04-12T17:47:42.912Z" }, - { url = "https://files.pythonhosted.org/packages/21/f5/6ba14718135f08fbfa33308efe027dd02b781d3f1d5c471444a395933aac/pillow-11.2.1-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:e6def7eed9e7fa90fde255afaf08060dc4b343bbe524a8f69bdd2a2f0018f600", size = 4517773, upload-time = "2025-04-12T17:47:44.611Z" }, - { url = "https://files.pythonhosted.org/packages/20/f2/805ad600fc59ebe4f1ba6129cd3a75fb0da126975c8579b8f57abeb61e80/pillow-11.2.1-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:8f4f3724c068be008c08257207210c138d5f3731af6c155a81c2b09a9eb3a788", size = 4607069, upload-time = "2025-04-12T17:47:46.46Z" }, - { url = "https://files.pythonhosted.org/packages/71/6b/4ef8a288b4bb2e0180cba13ca0a519fa27aa982875882392b65131401099/pillow-11.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a0a6709b47019dff32e678bc12c63008311b82b9327613f534e496dacaefb71e", size = 4583460, upload-time = "2025-04-12T17:47:49.255Z" }, - { url = "https://files.pythonhosted.org/packages/62/ae/f29c705a09cbc9e2a456590816e5c234382ae5d32584f451c3eb41a62062/pillow-11.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f6b0c664ccb879109ee3ca702a9272d877f4fcd21e5eb63c26422fd6e415365e", size = 4661304, upload-time = "2025-04-12T17:47:51.067Z" }, - { url = "https://files.pythonhosted.org/packages/6e/1a/c8217b6f2f73794a5e219fbad087701f412337ae6dbb956db37d69a9bc43/pillow-11.2.1-cp311-cp311-win32.whl", hash = "sha256:cc5d875d56e49f112b6def6813c4e3d3036d269c008bf8aef72cd08d20ca6df6", size = 2331809, upload-time = "2025-04-12T17:47:54.425Z" }, - { url = "https://files.pythonhosted.org/packages/e2/72/25a8f40170dc262e86e90f37cb72cb3de5e307f75bf4b02535a61afcd519/pillow-11.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:0f5c7eda47bf8e3c8a283762cab94e496ba977a420868cb819159980b6709193", size = 2676338, upload-time = "2025-04-12T17:47:56.535Z" }, - { url = "https://files.pythonhosted.org/packages/06/9e/76825e39efee61efea258b479391ca77d64dbd9e5804e4ad0fa453b4ba55/pillow-11.2.1-cp311-cp311-win_arm64.whl", hash = "sha256:4d375eb838755f2528ac8cbc926c3e31cc49ca4ad0cf79cff48b20e30634a4a7", size = 2414918, upload-time = "2025-04-12T17:47:58.217Z" }, - { url = "https://files.pythonhosted.org/packages/c7/40/052610b15a1b8961f52537cc8326ca6a881408bc2bdad0d852edeb6ed33b/pillow-11.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:78afba22027b4accef10dbd5eed84425930ba41b3ea0a86fa8d20baaf19d807f", size = 3190185, upload-time = "2025-04-12T17:48:00.417Z" }, - { url = "https://files.pythonhosted.org/packages/e5/7e/b86dbd35a5f938632093dc40d1682874c33dcfe832558fc80ca56bfcb774/pillow-11.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:78092232a4ab376a35d68c4e6d5e00dfd73454bd12b230420025fbe178ee3b0b", size = 3030306, upload-time = "2025-04-12T17:48:02.391Z" }, - { url = "https://files.pythonhosted.org/packages/a4/5c/467a161f9ed53e5eab51a42923c33051bf8d1a2af4626ac04f5166e58e0c/pillow-11.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25a5f306095c6780c52e6bbb6109624b95c5b18e40aab1c3041da3e9e0cd3e2d", size = 4416121, upload-time = "2025-04-12T17:48:04.554Z" }, - { url = "https://files.pythonhosted.org/packages/62/73/972b7742e38ae0e2ac76ab137ca6005dcf877480da0d9d61d93b613065b4/pillow-11.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c7b29dbd4281923a2bfe562acb734cee96bbb129e96e6972d315ed9f232bef4", size = 4501707, upload-time = "2025-04-12T17:48:06.831Z" }, - { url = "https://files.pythonhosted.org/packages/e4/3a/427e4cb0b9e177efbc1a84798ed20498c4f233abde003c06d2650a6d60cb/pillow-11.2.1-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:3e645b020f3209a0181a418bffe7b4a93171eef6c4ef6cc20980b30bebf17b7d", size = 4522921, upload-time = "2025-04-12T17:48:09.229Z" }, - { url = "https://files.pythonhosted.org/packages/fe/7c/d8b1330458e4d2f3f45d9508796d7caf0c0d3764c00c823d10f6f1a3b76d/pillow-11.2.1-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:b2dbea1012ccb784a65349f57bbc93730b96e85b42e9bf7b01ef40443db720b4", size = 4612523, upload-time = "2025-04-12T17:48:11.631Z" }, - { url = "https://files.pythonhosted.org/packages/b3/2f/65738384e0b1acf451de5a573d8153fe84103772d139e1e0bdf1596be2ea/pillow-11.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:da3104c57bbd72948d75f6a9389e6727d2ab6333c3617f0a89d72d4940aa0443", size = 4587836, upload-time = "2025-04-12T17:48:13.592Z" }, - { url = "https://files.pythonhosted.org/packages/6a/c5/e795c9f2ddf3debb2dedd0df889f2fe4b053308bb59a3cc02a0cd144d641/pillow-11.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:598174aef4589af795f66f9caab87ba4ff860ce08cd5bb447c6fc553ffee603c", size = 4669390, upload-time = "2025-04-12T17:48:15.938Z" }, - { url = "https://files.pythonhosted.org/packages/96/ae/ca0099a3995976a9fce2f423166f7bff9b12244afdc7520f6ed38911539a/pillow-11.2.1-cp312-cp312-win32.whl", hash = "sha256:1d535df14716e7f8776b9e7fee118576d65572b4aad3ed639be9e4fa88a1cad3", size = 2332309, upload-time = "2025-04-12T17:48:17.885Z" }, - { url = "https://files.pythonhosted.org/packages/7c/18/24bff2ad716257fc03da964c5e8f05d9790a779a8895d6566e493ccf0189/pillow-11.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:14e33b28bf17c7a38eede290f77db7c664e4eb01f7869e37fa98a5aa95978941", size = 2676768, upload-time = "2025-04-12T17:48:19.655Z" }, - { url = "https://files.pythonhosted.org/packages/da/bb/e8d656c9543276517ee40184aaa39dcb41e683bca121022f9323ae11b39d/pillow-11.2.1-cp312-cp312-win_arm64.whl", hash = "sha256:21e1470ac9e5739ff880c211fc3af01e3ae505859392bf65458c224d0bf283eb", size = 2415087, upload-time = "2025-04-12T17:48:21.991Z" }, - { url = "https://files.pythonhosted.org/packages/36/9c/447528ee3776e7ab8897fe33697a7ff3f0475bb490c5ac1456a03dc57956/pillow-11.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:fdec757fea0b793056419bca3e9932eb2b0ceec90ef4813ea4c1e072c389eb28", size = 3190098, upload-time = "2025-04-12T17:48:23.915Z" }, - { url = "https://files.pythonhosted.org/packages/b5/09/29d5cd052f7566a63e5b506fac9c60526e9ecc553825551333e1e18a4858/pillow-11.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b0e130705d568e2f43a17bcbe74d90958e8a16263868a12c3e0d9c8162690830", size = 3030166, upload-time = "2025-04-12T17:48:25.738Z" }, - { url = "https://files.pythonhosted.org/packages/71/5d/446ee132ad35e7600652133f9c2840b4799bbd8e4adba881284860da0a36/pillow-11.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bdb5e09068332578214cadd9c05e3d64d99e0e87591be22a324bdbc18925be0", size = 4408674, upload-time = "2025-04-12T17:48:27.908Z" }, - { url = "https://files.pythonhosted.org/packages/69/5f/cbe509c0ddf91cc3a03bbacf40e5c2339c4912d16458fcb797bb47bcb269/pillow-11.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d189ba1bebfbc0c0e529159631ec72bb9e9bc041f01ec6d3233d6d82eb823bc1", size = 4496005, upload-time = "2025-04-12T17:48:29.888Z" }, - { url = "https://files.pythonhosted.org/packages/f9/b3/dd4338d8fb8a5f312021f2977fb8198a1184893f9b00b02b75d565c33b51/pillow-11.2.1-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:191955c55d8a712fab8934a42bfefbf99dd0b5875078240943f913bb66d46d9f", size = 4518707, upload-time = "2025-04-12T17:48:31.874Z" }, - { url = "https://files.pythonhosted.org/packages/13/eb/2552ecebc0b887f539111c2cd241f538b8ff5891b8903dfe672e997529be/pillow-11.2.1-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:ad275964d52e2243430472fc5d2c2334b4fc3ff9c16cb0a19254e25efa03a155", size = 4610008, upload-time = "2025-04-12T17:48:34.422Z" }, - { url = "https://files.pythonhosted.org/packages/72/d1/924ce51bea494cb6e7959522d69d7b1c7e74f6821d84c63c3dc430cbbf3b/pillow-11.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:750f96efe0597382660d8b53e90dd1dd44568a8edb51cb7f9d5d918b80d4de14", size = 4585420, upload-time = "2025-04-12T17:48:37.641Z" }, - { url = "https://files.pythonhosted.org/packages/43/ab/8f81312d255d713b99ca37479a4cb4b0f48195e530cdc1611990eb8fd04b/pillow-11.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fe15238d3798788d00716637b3d4e7bb6bde18b26e5d08335a96e88564a36b6b", size = 4667655, upload-time = "2025-04-12T17:48:39.652Z" }, - { url = "https://files.pythonhosted.org/packages/94/86/8f2e9d2dc3d308dfd137a07fe1cc478df0a23d42a6c4093b087e738e4827/pillow-11.2.1-cp313-cp313-win32.whl", hash = "sha256:3fe735ced9a607fee4f481423a9c36701a39719252a9bb251679635f99d0f7d2", size = 2332329, upload-time = "2025-04-12T17:48:41.765Z" }, - { url = "https://files.pythonhosted.org/packages/6d/ec/1179083b8d6067a613e4d595359b5fdea65d0a3b7ad623fee906e1b3c4d2/pillow-11.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:74ee3d7ecb3f3c05459ba95eed5efa28d6092d751ce9bf20e3e253a4e497e691", size = 2676388, upload-time = "2025-04-12T17:48:43.625Z" }, - { url = "https://files.pythonhosted.org/packages/23/f1/2fc1e1e294de897df39fa8622d829b8828ddad938b0eaea256d65b84dd72/pillow-11.2.1-cp313-cp313-win_arm64.whl", hash = "sha256:5119225c622403afb4b44bad4c1ca6c1f98eed79db8d3bc6e4e160fc6339d66c", size = 2414950, upload-time = "2025-04-12T17:48:45.475Z" }, - { url = "https://files.pythonhosted.org/packages/c4/3e/c328c48b3f0ead7bab765a84b4977acb29f101d10e4ef57a5e3400447c03/pillow-11.2.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:8ce2e8411c7aaef53e6bb29fe98f28cd4fbd9a1d9be2eeea434331aac0536b22", size = 3192759, upload-time = "2025-04-12T17:48:47.866Z" }, - { url = "https://files.pythonhosted.org/packages/18/0e/1c68532d833fc8b9f404d3a642991441d9058eccd5606eab31617f29b6d4/pillow-11.2.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:9ee66787e095127116d91dea2143db65c7bb1e232f617aa5957c0d9d2a3f23a7", size = 3033284, upload-time = "2025-04-12T17:48:50.189Z" }, - { url = "https://files.pythonhosted.org/packages/b7/cb/6faf3fb1e7705fd2db74e070f3bf6f88693601b0ed8e81049a8266de4754/pillow-11.2.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9622e3b6c1d8b551b6e6f21873bdcc55762b4b2126633014cea1803368a9aa16", size = 4445826, upload-time = "2025-04-12T17:48:52.346Z" }, - { url = "https://files.pythonhosted.org/packages/07/94/8be03d50b70ca47fb434a358919d6a8d6580f282bbb7af7e4aa40103461d/pillow-11.2.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63b5dff3a68f371ea06025a1a6966c9a1e1ee452fc8020c2cd0ea41b83e9037b", size = 4527329, upload-time = "2025-04-12T17:48:54.403Z" }, - { url = "https://files.pythonhosted.org/packages/fd/a4/bfe78777076dc405e3bd2080bc32da5ab3945b5a25dc5d8acaa9de64a162/pillow-11.2.1-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:31df6e2d3d8fc99f993fd253e97fae451a8db2e7207acf97859732273e108406", size = 4549049, upload-time = "2025-04-12T17:48:56.383Z" }, - { url = "https://files.pythonhosted.org/packages/65/4d/eaf9068dc687c24979e977ce5677e253624bd8b616b286f543f0c1b91662/pillow-11.2.1-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:062b7a42d672c45a70fa1f8b43d1d38ff76b63421cbbe7f88146b39e8a558d91", size = 4635408, upload-time = "2025-04-12T17:48:58.782Z" }, - { url = "https://files.pythonhosted.org/packages/1d/26/0fd443365d9c63bc79feb219f97d935cd4b93af28353cba78d8e77b61719/pillow-11.2.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4eb92eca2711ef8be42fd3f67533765d9fd043b8c80db204f16c8ea62ee1a751", size = 4614863, upload-time = "2025-04-12T17:49:00.709Z" }, - { url = "https://files.pythonhosted.org/packages/49/65/dca4d2506be482c2c6641cacdba5c602bc76d8ceb618fd37de855653a419/pillow-11.2.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f91ebf30830a48c825590aede79376cb40f110b387c17ee9bd59932c961044f9", size = 4692938, upload-time = "2025-04-12T17:49:02.946Z" }, - { url = "https://files.pythonhosted.org/packages/b3/92/1ca0c3f09233bd7decf8f7105a1c4e3162fb9142128c74adad0fb361b7eb/pillow-11.2.1-cp313-cp313t-win32.whl", hash = "sha256:e0b55f27f584ed623221cfe995c912c61606be8513bfa0e07d2c674b4516d9dd", size = 2335774, upload-time = "2025-04-12T17:49:04.889Z" }, - { url = "https://files.pythonhosted.org/packages/a5/ac/77525347cb43b83ae905ffe257bbe2cc6fd23acb9796639a1f56aa59d191/pillow-11.2.1-cp313-cp313t-win_amd64.whl", hash = "sha256:36d6b82164c39ce5482f649b437382c0fb2395eabc1e2b1702a6deb8ad647d6e", size = 2681895, upload-time = "2025-04-12T17:49:06.635Z" }, - { url = "https://files.pythonhosted.org/packages/67/32/32dc030cfa91ca0fc52baebbba2e009bb001122a1daa8b6a79ad830b38d3/pillow-11.2.1-cp313-cp313t-win_arm64.whl", hash = "sha256:225c832a13326e34f212d2072982bb1adb210e0cc0b153e688743018c94a2681", size = 2417234, upload-time = "2025-04-12T17:49:08.399Z" }, - { url = "https://files.pythonhosted.org/packages/21/3a/c1835d1c7cf83559e95b4f4ed07ab0bb7acc689712adfce406b3f456e9fd/pillow-11.2.1-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:7491cf8a79b8eb867d419648fff2f83cb0b3891c8b36da92cc7f1931d46108c8", size = 3198391, upload-time = "2025-04-12T17:49:10.122Z" }, - { url = "https://files.pythonhosted.org/packages/b6/4d/dcb7a9af3fc1e8653267c38ed622605d9d1793349274b3ef7af06457e257/pillow-11.2.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8b02d8f9cb83c52578a0b4beadba92e37d83a4ef11570a8688bbf43f4ca50909", size = 3030573, upload-time = "2025-04-12T17:49:11.938Z" }, - { url = "https://files.pythonhosted.org/packages/9d/29/530ca098c1a1eb31d4e163d317d0e24e6d2ead907991c69ca5b663de1bc5/pillow-11.2.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:014ca0050c85003620526b0ac1ac53f56fc93af128f7546623cc8e31875ab928", size = 4398677, upload-time = "2025-04-12T17:49:13.861Z" }, - { url = "https://files.pythonhosted.org/packages/8b/ee/0e5e51db34de1690264e5f30dcd25328c540aa11d50a3bc0b540e2a445b6/pillow-11.2.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3692b68c87096ac6308296d96354eddd25f98740c9d2ab54e1549d6c8aea9d79", size = 4484986, upload-time = "2025-04-12T17:49:15.948Z" }, - { url = "https://files.pythonhosted.org/packages/93/7d/bc723b41ce3d2c28532c47678ec988974f731b5c6fadd5b3a4fba9015e4f/pillow-11.2.1-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:f781dcb0bc9929adc77bad571b8621ecb1e4cdef86e940fe2e5b5ee24fd33b35", size = 4501897, upload-time = "2025-04-12T17:49:17.839Z" }, - { url = "https://files.pythonhosted.org/packages/be/0b/532e31abc7389617ddff12551af625a9b03cd61d2989fa595e43c470ec67/pillow-11.2.1-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:2b490402c96f907a166615e9a5afacf2519e28295f157ec3a2bb9bd57de638cb", size = 4592618, upload-time = "2025-04-12T17:49:19.7Z" }, - { url = "https://files.pythonhosted.org/packages/4c/f0/21ed6499a6216fef753e2e2254a19d08bff3747108ba042422383f3e9faa/pillow-11.2.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:dd6b20b93b3ccc9c1b597999209e4bc5cf2853f9ee66e3fc9a400a78733ffc9a", size = 4570493, upload-time = "2025-04-12T17:49:21.703Z" }, - { url = "https://files.pythonhosted.org/packages/68/de/17004ddb8ab855573fe1127ab0168d11378cdfe4a7ee2a792a70ff2e9ba7/pillow-11.2.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:4b835d89c08a6c2ee7781b8dd0a30209a8012b5f09c0a665b65b0eb3560b6f36", size = 4647748, upload-time = "2025-04-12T17:49:23.579Z" }, - { url = "https://files.pythonhosted.org/packages/c7/23/82ecb486384bb3578115c509d4a00bb52f463ee700a5ca1be53da3c88c19/pillow-11.2.1-cp39-cp39-win32.whl", hash = "sha256:b10428b3416d4f9c61f94b494681280be7686bda15898a3a9e08eb66a6d92d67", size = 2331731, upload-time = "2025-04-12T17:49:25.58Z" }, - { url = "https://files.pythonhosted.org/packages/58/bb/87efd58b3689537a623d44dbb2550ef0bb5ff6a62769707a0fe8b1a7bdeb/pillow-11.2.1-cp39-cp39-win_amd64.whl", hash = "sha256:6ebce70c3f486acf7591a3d73431fa504a4e18a9b97ff27f5f47b7368e4b9dd1", size = 2676346, upload-time = "2025-04-12T17:49:27.342Z" }, - { url = "https://files.pythonhosted.org/packages/80/08/dc268475b22887b816e5dcfae31bce897f524b4646bab130c2142c9b2400/pillow-11.2.1-cp39-cp39-win_arm64.whl", hash = "sha256:c27476257b2fdcd7872d54cfd119b3a9ce4610fb85c8e32b70b42e3680a29a1e", size = 2414623, upload-time = "2025-04-12T17:49:29.139Z" }, - { url = "https://files.pythonhosted.org/packages/33/49/c8c21e4255b4f4a2c0c68ac18125d7f5460b109acc6dfdef1a24f9b960ef/pillow-11.2.1-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:9b7b0d4fd2635f54ad82785d56bc0d94f147096493a79985d0ab57aedd563156", size = 3181727, upload-time = "2025-04-12T17:49:31.898Z" }, - { url = "https://files.pythonhosted.org/packages/6d/f1/f7255c0838f8c1ef6d55b625cfb286835c17e8136ce4351c5577d02c443b/pillow-11.2.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:aa442755e31c64037aa7c1cb186e0b369f8416c567381852c63444dd666fb772", size = 2999833, upload-time = "2025-04-12T17:49:34.2Z" }, - { url = "https://files.pythonhosted.org/packages/e2/57/9968114457bd131063da98d87790d080366218f64fa2943b65ac6739abb3/pillow-11.2.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f0d3348c95b766f54b76116d53d4cb171b52992a1027e7ca50c81b43b9d9e363", size = 3437472, upload-time = "2025-04-12T17:49:36.294Z" }, - { url = "https://files.pythonhosted.org/packages/b2/1b/e35d8a158e21372ecc48aac9c453518cfe23907bb82f950d6e1c72811eb0/pillow-11.2.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85d27ea4c889342f7e35f6d56e7e1cb345632ad592e8c51b693d7b7556043ce0", size = 3459976, upload-time = "2025-04-12T17:49:38.988Z" }, - { url = "https://files.pythonhosted.org/packages/26/da/2c11d03b765efff0ccc473f1c4186dc2770110464f2177efaed9cf6fae01/pillow-11.2.1-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:bf2c33d6791c598142f00c9c4c7d47f6476731c31081331664eb26d6ab583e01", size = 3527133, upload-time = "2025-04-12T17:49:40.985Z" }, - { url = "https://files.pythonhosted.org/packages/79/1a/4e85bd7cadf78412c2a3069249a09c32ef3323650fd3005c97cca7aa21df/pillow-11.2.1-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e616e7154c37669fc1dfc14584f11e284e05d1c650e1c0f972f281c4ccc53193", size = 3571555, upload-time = "2025-04-12T17:49:42.964Z" }, - { url = "https://files.pythonhosted.org/packages/69/03/239939915216de1e95e0ce2334bf17a7870ae185eb390fab6d706aadbfc0/pillow-11.2.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:39ad2e0f424394e3aebc40168845fee52df1394a4673a6ee512d840d14ab3013", size = 2674713, upload-time = "2025-04-12T17:49:44.944Z" }, - { url = "https://files.pythonhosted.org/packages/a4/ad/2613c04633c7257d9481ab21d6b5364b59fc5d75faafd7cb8693523945a3/pillow-11.2.1-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:80f1df8dbe9572b4b7abdfa17eb5d78dd620b1d55d9e25f834efdbee872d3aed", size = 3181734, upload-time = "2025-04-12T17:49:46.789Z" }, - { url = "https://files.pythonhosted.org/packages/a4/fd/dcdda4471ed667de57bb5405bb42d751e6cfdd4011a12c248b455c778e03/pillow-11.2.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:ea926cfbc3957090becbcbbb65ad177161a2ff2ad578b5a6ec9bb1e1cd78753c", size = 2999841, upload-time = "2025-04-12T17:49:48.812Z" }, - { url = "https://files.pythonhosted.org/packages/ac/89/8a2536e95e77432833f0db6fd72a8d310c8e4272a04461fb833eb021bf94/pillow-11.2.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:738db0e0941ca0376804d4de6a782c005245264edaa253ffce24e5a15cbdc7bd", size = 3437470, upload-time = "2025-04-12T17:49:50.831Z" }, - { url = "https://files.pythonhosted.org/packages/9d/8f/abd47b73c60712f88e9eda32baced7bfc3e9bd6a7619bb64b93acff28c3e/pillow-11.2.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9db98ab6565c69082ec9b0d4e40dd9f6181dab0dd236d26f7a50b8b9bfbd5076", size = 3460013, upload-time = "2025-04-12T17:49:53.278Z" }, - { url = "https://files.pythonhosted.org/packages/f6/20/5c0a0aa83b213b7a07ec01e71a3d6ea2cf4ad1d2c686cc0168173b6089e7/pillow-11.2.1-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:036e53f4170e270ddb8797d4c590e6dd14d28e15c7da375c18978045f7e6c37b", size = 3527165, upload-time = "2025-04-12T17:49:55.164Z" }, - { url = "https://files.pythonhosted.org/packages/58/0e/2abab98a72202d91146abc839e10c14f7cf36166f12838ea0c4db3ca6ecb/pillow-11.2.1-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:14f73f7c291279bd65fda51ee87affd7c1e097709f7fdd0188957a16c264601f", size = 3571586, upload-time = "2025-04-12T17:49:57.171Z" }, - { url = "https://files.pythonhosted.org/packages/21/2c/5e05f58658cf49b6667762cca03d6e7d85cededde2caf2ab37b81f80e574/pillow-11.2.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:208653868d5c9ecc2b327f9b9ef34e0e42a4cdd172c2988fd81d62d2bc9bc044", size = 2674751, upload-time = "2025-04-12T17:49:59.628Z" }, + { url = "https://files.pythonhosted.org/packages/4c/5d/45a3553a253ac8763f3561371432a90bdbe6000fbdcf1397ffe502aa206c/pillow-11.3.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:1b9c17fd4ace828b3003dfd1e30bff24863e0eb59b535e8f80194d9cc7ecf860", size = 5316554, upload-time = "2025-07-01T09:13:39.342Z" }, + { url = "https://files.pythonhosted.org/packages/7c/c8/67c12ab069ef586a25a4a79ced553586748fad100c77c0ce59bb4983ac98/pillow-11.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:65dc69160114cdd0ca0f35cb434633c75e8e7fad4cf855177a05bf38678f73ad", size = 4686548, upload-time = "2025-07-01T09:13:41.835Z" }, + { url = "https://files.pythonhosted.org/packages/2f/bd/6741ebd56263390b382ae4c5de02979af7f8bd9807346d068700dd6d5cf9/pillow-11.3.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7107195ddc914f656c7fc8e4a5e1c25f32e9236ea3ea860f257b0436011fddd0", size = 5859742, upload-time = "2025-07-03T13:09:47.439Z" }, + { url = "https://files.pythonhosted.org/packages/ca/0b/c412a9e27e1e6a829e6ab6c2dca52dd563efbedf4c9c6aa453d9a9b77359/pillow-11.3.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:cc3e831b563b3114baac7ec2ee86819eb03caa1a2cef0b481a5675b59c4fe23b", size = 7633087, upload-time = "2025-07-03T13:09:51.796Z" }, + { url = "https://files.pythonhosted.org/packages/59/9d/9b7076aaf30f5dd17e5e5589b2d2f5a5d7e30ff67a171eb686e4eecc2adf/pillow-11.3.0-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f1f182ebd2303acf8c380a54f615ec883322593320a9b00438eb842c1f37ae50", size = 5963350, upload-time = "2025-07-01T09:13:43.865Z" }, + { url = "https://files.pythonhosted.org/packages/f0/16/1a6bf01fb622fb9cf5c91683823f073f053005c849b1f52ed613afcf8dae/pillow-11.3.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4445fa62e15936a028672fd48c4c11a66d641d2c05726c7ec1f8ba6a572036ae", size = 6631840, upload-time = "2025-07-01T09:13:46.161Z" }, + { url = "https://files.pythonhosted.org/packages/7b/e6/6ff7077077eb47fde78739e7d570bdcd7c10495666b6afcd23ab56b19a43/pillow-11.3.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:71f511f6b3b91dd543282477be45a033e4845a40278fa8dcdbfdb07109bf18f9", size = 6074005, upload-time = "2025-07-01T09:13:47.829Z" }, + { url = "https://files.pythonhosted.org/packages/c3/3a/b13f36832ea6d279a697231658199e0a03cd87ef12048016bdcc84131601/pillow-11.3.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:040a5b691b0713e1f6cbe222e0f4f74cd233421e105850ae3b3c0ceda520f42e", size = 6708372, upload-time = "2025-07-01T09:13:52.145Z" }, + { url = "https://files.pythonhosted.org/packages/6c/e4/61b2e1a7528740efbc70b3d581f33937e38e98ef3d50b05007267a55bcb2/pillow-11.3.0-cp310-cp310-win32.whl", hash = "sha256:89bd777bc6624fe4115e9fac3352c79ed60f3bb18651420635f26e643e3dd1f6", size = 6277090, upload-time = "2025-07-01T09:13:53.915Z" }, + { url = "https://files.pythonhosted.org/packages/a9/d3/60c781c83a785d6afbd6a326ed4d759d141de43aa7365725cbcd65ce5e54/pillow-11.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:19d2ff547c75b8e3ff46f4d9ef969a06c30ab2d4263a9e287733aa8b2429ce8f", size = 6985988, upload-time = "2025-07-01T09:13:55.699Z" }, + { url = "https://files.pythonhosted.org/packages/9f/28/4f4a0203165eefb3763939c6789ba31013a2e90adffb456610f30f613850/pillow-11.3.0-cp310-cp310-win_arm64.whl", hash = "sha256:819931d25e57b513242859ce1876c58c59dc31587847bf74cfe06b2e0cb22d2f", size = 2422899, upload-time = "2025-07-01T09:13:57.497Z" }, + { url = "https://files.pythonhosted.org/packages/db/26/77f8ed17ca4ffd60e1dcd220a6ec6d71210ba398cfa33a13a1cd614c5613/pillow-11.3.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:1cd110edf822773368b396281a2293aeb91c90a2db00d78ea43e7e861631b722", size = 5316531, upload-time = "2025-07-01T09:13:59.203Z" }, + { url = "https://files.pythonhosted.org/packages/cb/39/ee475903197ce709322a17a866892efb560f57900d9af2e55f86db51b0a5/pillow-11.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9c412fddd1b77a75aa904615ebaa6001f169b26fd467b4be93aded278266b288", size = 4686560, upload-time = "2025-07-01T09:14:01.101Z" }, + { url = "https://files.pythonhosted.org/packages/d5/90/442068a160fd179938ba55ec8c97050a612426fae5ec0a764e345839f76d/pillow-11.3.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7d1aa4de119a0ecac0a34a9c8bde33f34022e2e8f99104e47a3ca392fd60e37d", size = 5870978, upload-time = "2025-07-03T13:09:55.638Z" }, + { url = "https://files.pythonhosted.org/packages/13/92/dcdd147ab02daf405387f0218dcf792dc6dd5b14d2573d40b4caeef01059/pillow-11.3.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:91da1d88226663594e3f6b4b8c3c8d85bd504117d043740a8e0ec449087cc494", size = 7641168, upload-time = "2025-07-03T13:10:00.37Z" }, + { url = "https://files.pythonhosted.org/packages/6e/db/839d6ba7fd38b51af641aa904e2960e7a5644d60ec754c046b7d2aee00e5/pillow-11.3.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:643f189248837533073c405ec2f0bb250ba54598cf80e8c1e043381a60632f58", size = 5973053, upload-time = "2025-07-01T09:14:04.491Z" }, + { url = "https://files.pythonhosted.org/packages/f2/2f/d7675ecae6c43e9f12aa8d58b6012683b20b6edfbdac7abcb4e6af7a3784/pillow-11.3.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:106064daa23a745510dabce1d84f29137a37224831d88eb4ce94bb187b1d7e5f", size = 6640273, upload-time = "2025-07-01T09:14:06.235Z" }, + { url = "https://files.pythonhosted.org/packages/45/ad/931694675ede172e15b2ff03c8144a0ddaea1d87adb72bb07655eaffb654/pillow-11.3.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:cd8ff254faf15591e724dc7c4ddb6bf4793efcbe13802a4ae3e863cd300b493e", size = 6082043, upload-time = "2025-07-01T09:14:07.978Z" }, + { url = "https://files.pythonhosted.org/packages/3a/04/ba8f2b11fc80d2dd462d7abec16351b45ec99cbbaea4387648a44190351a/pillow-11.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:932c754c2d51ad2b2271fd01c3d121daaa35e27efae2a616f77bf164bc0b3e94", size = 6715516, upload-time = "2025-07-01T09:14:10.233Z" }, + { url = "https://files.pythonhosted.org/packages/48/59/8cd06d7f3944cc7d892e8533c56b0acb68399f640786313275faec1e3b6f/pillow-11.3.0-cp311-cp311-win32.whl", hash = "sha256:b4b8f3efc8d530a1544e5962bd6b403d5f7fe8b9e08227c6b255f98ad82b4ba0", size = 6274768, upload-time = "2025-07-01T09:14:11.921Z" }, + { url = "https://files.pythonhosted.org/packages/f1/cc/29c0f5d64ab8eae20f3232da8f8571660aa0ab4b8f1331da5c2f5f9a938e/pillow-11.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:1a992e86b0dd7aeb1f053cd506508c0999d710a8f07b4c791c63843fc6a807ac", size = 6986055, upload-time = "2025-07-01T09:14:13.623Z" }, + { url = "https://files.pythonhosted.org/packages/c6/df/90bd886fabd544c25addd63e5ca6932c86f2b701d5da6c7839387a076b4a/pillow-11.3.0-cp311-cp311-win_arm64.whl", hash = "sha256:30807c931ff7c095620fe04448e2c2fc673fcbb1ffe2a7da3fb39613489b1ddd", size = 2423079, upload-time = "2025-07-01T09:14:15.268Z" }, + { url = "https://files.pythonhosted.org/packages/40/fe/1bc9b3ee13f68487a99ac9529968035cca2f0a51ec36892060edcc51d06a/pillow-11.3.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:fdae223722da47b024b867c1ea0be64e0df702c5e0a60e27daad39bf960dd1e4", size = 5278800, upload-time = "2025-07-01T09:14:17.648Z" }, + { url = "https://files.pythonhosted.org/packages/2c/32/7e2ac19b5713657384cec55f89065fb306b06af008cfd87e572035b27119/pillow-11.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:921bd305b10e82b4d1f5e802b6850677f965d8394203d182f078873851dada69", size = 4686296, upload-time = "2025-07-01T09:14:19.828Z" }, + { url = "https://files.pythonhosted.org/packages/8e/1e/b9e12bbe6e4c2220effebc09ea0923a07a6da1e1f1bfbc8d7d29a01ce32b/pillow-11.3.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:eb76541cba2f958032d79d143b98a3a6b3ea87f0959bbe256c0b5e416599fd5d", size = 5871726, upload-time = "2025-07-03T13:10:04.448Z" }, + { url = "https://files.pythonhosted.org/packages/8d/33/e9200d2bd7ba00dc3ddb78df1198a6e80d7669cce6c2bdbeb2530a74ec58/pillow-11.3.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:67172f2944ebba3d4a7b54f2e95c786a3a50c21b88456329314caaa28cda70f6", size = 7644652, upload-time = "2025-07-03T13:10:10.391Z" }, + { url = "https://files.pythonhosted.org/packages/41/f1/6f2427a26fc683e00d985bc391bdd76d8dd4e92fac33d841127eb8fb2313/pillow-11.3.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:97f07ed9f56a3b9b5f49d3661dc9607484e85c67e27f3e8be2c7d28ca032fec7", size = 5977787, upload-time = "2025-07-01T09:14:21.63Z" }, + { url = "https://files.pythonhosted.org/packages/e4/c9/06dd4a38974e24f932ff5f98ea3c546ce3f8c995d3f0985f8e5ba48bba19/pillow-11.3.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:676b2815362456b5b3216b4fd5bd89d362100dc6f4945154ff172e206a22c024", size = 6645236, upload-time = "2025-07-01T09:14:23.321Z" }, + { url = "https://files.pythonhosted.org/packages/40/e7/848f69fb79843b3d91241bad658e9c14f39a32f71a301bcd1d139416d1be/pillow-11.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3e184b2f26ff146363dd07bde8b711833d7b0202e27d13540bfe2e35a323a809", size = 6086950, upload-time = "2025-07-01T09:14:25.237Z" }, + { url = "https://files.pythonhosted.org/packages/0b/1a/7cff92e695a2a29ac1958c2a0fe4c0b2393b60aac13b04a4fe2735cad52d/pillow-11.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6be31e3fc9a621e071bc17bb7de63b85cbe0bfae91bb0363c893cbe67247780d", size = 6723358, upload-time = "2025-07-01T09:14:27.053Z" }, + { url = "https://files.pythonhosted.org/packages/26/7d/73699ad77895f69edff76b0f332acc3d497f22f5d75e5360f78cbcaff248/pillow-11.3.0-cp312-cp312-win32.whl", hash = "sha256:7b161756381f0918e05e7cb8a371fff367e807770f8fe92ecb20d905d0e1c149", size = 6275079, upload-time = "2025-07-01T09:14:30.104Z" }, + { url = "https://files.pythonhosted.org/packages/8c/ce/e7dfc873bdd9828f3b6e5c2bbb74e47a98ec23cc5c74fc4e54462f0d9204/pillow-11.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:a6444696fce635783440b7f7a9fc24b3ad10a9ea3f0ab66c5905be1c19ccf17d", size = 6986324, upload-time = "2025-07-01T09:14:31.899Z" }, + { url = "https://files.pythonhosted.org/packages/16/8f/b13447d1bf0b1f7467ce7d86f6e6edf66c0ad7cf44cf5c87a37f9bed9936/pillow-11.3.0-cp312-cp312-win_arm64.whl", hash = "sha256:2aceea54f957dd4448264f9bf40875da0415c83eb85f55069d89c0ed436e3542", size = 2423067, upload-time = "2025-07-01T09:14:33.709Z" }, + { url = "https://files.pythonhosted.org/packages/1e/93/0952f2ed8db3a5a4c7a11f91965d6184ebc8cd7cbb7941a260d5f018cd2d/pillow-11.3.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:1c627742b539bba4309df89171356fcb3cc5a9178355b2727d1b74a6cf155fbd", size = 2128328, upload-time = "2025-07-01T09:14:35.276Z" }, + { url = "https://files.pythonhosted.org/packages/4b/e8/100c3d114b1a0bf4042f27e0f87d2f25e857e838034e98ca98fe7b8c0a9c/pillow-11.3.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:30b7c02f3899d10f13d7a48163c8969e4e653f8b43416d23d13d1bbfdc93b9f8", size = 2170652, upload-time = "2025-07-01T09:14:37.203Z" }, + { url = "https://files.pythonhosted.org/packages/aa/86/3f758a28a6e381758545f7cdb4942e1cb79abd271bea932998fc0db93cb6/pillow-11.3.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:7859a4cc7c9295f5838015d8cc0a9c215b77e43d07a25e460f35cf516df8626f", size = 2227443, upload-time = "2025-07-01T09:14:39.344Z" }, + { url = "https://files.pythonhosted.org/packages/01/f4/91d5b3ffa718df2f53b0dc109877993e511f4fd055d7e9508682e8aba092/pillow-11.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ec1ee50470b0d050984394423d96325b744d55c701a439d2bd66089bff963d3c", size = 5278474, upload-time = "2025-07-01T09:14:41.843Z" }, + { url = "https://files.pythonhosted.org/packages/f9/0e/37d7d3eca6c879fbd9dba21268427dffda1ab00d4eb05b32923d4fbe3b12/pillow-11.3.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7db51d222548ccfd274e4572fdbf3e810a5e66b00608862f947b163e613b67dd", size = 4686038, upload-time = "2025-07-01T09:14:44.008Z" }, + { url = "https://files.pythonhosted.org/packages/ff/b0/3426e5c7f6565e752d81221af9d3676fdbb4f352317ceafd42899aaf5d8a/pillow-11.3.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:2d6fcc902a24ac74495df63faad1884282239265c6839a0a6416d33faedfae7e", size = 5864407, upload-time = "2025-07-03T13:10:15.628Z" }, + { url = "https://files.pythonhosted.org/packages/fc/c1/c6c423134229f2a221ee53f838d4be9d82bab86f7e2f8e75e47b6bf6cd77/pillow-11.3.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f0f5d8f4a08090c6d6d578351a2b91acf519a54986c055af27e7a93feae6d3f1", size = 7639094, upload-time = "2025-07-03T13:10:21.857Z" }, + { url = "https://files.pythonhosted.org/packages/ba/c9/09e6746630fe6372c67c648ff9deae52a2bc20897d51fa293571977ceb5d/pillow-11.3.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c37d8ba9411d6003bba9e518db0db0c58a680ab9fe5179f040b0463644bc9805", size = 5973503, upload-time = "2025-07-01T09:14:45.698Z" }, + { url = "https://files.pythonhosted.org/packages/d5/1c/a2a29649c0b1983d3ef57ee87a66487fdeb45132df66ab30dd37f7dbe162/pillow-11.3.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:13f87d581e71d9189ab21fe0efb5a23e9f28552d5be6979e84001d3b8505abe8", size = 6642574, upload-time = "2025-07-01T09:14:47.415Z" }, + { url = "https://files.pythonhosted.org/packages/36/de/d5cc31cc4b055b6c6fd990e3e7f0f8aaf36229a2698501bcb0cdf67c7146/pillow-11.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:023f6d2d11784a465f09fd09a34b150ea4672e85fb3d05931d89f373ab14abb2", size = 6084060, upload-time = "2025-07-01T09:14:49.636Z" }, + { url = "https://files.pythonhosted.org/packages/d5/ea/502d938cbaeec836ac28a9b730193716f0114c41325db428e6b280513f09/pillow-11.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:45dfc51ac5975b938e9809451c51734124e73b04d0f0ac621649821a63852e7b", size = 6721407, upload-time = "2025-07-01T09:14:51.962Z" }, + { url = "https://files.pythonhosted.org/packages/45/9c/9c5e2a73f125f6cbc59cc7087c8f2d649a7ae453f83bd0362ff7c9e2aee2/pillow-11.3.0-cp313-cp313-win32.whl", hash = "sha256:a4d336baed65d50d37b88ca5b60c0fa9d81e3a87d4a7930d3880d1624d5b31f3", size = 6273841, upload-time = "2025-07-01T09:14:54.142Z" }, + { url = "https://files.pythonhosted.org/packages/23/85/397c73524e0cd212067e0c969aa245b01d50183439550d24d9f55781b776/pillow-11.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:0bce5c4fd0921f99d2e858dc4d4d64193407e1b99478bc5cacecba2311abde51", size = 6978450, upload-time = "2025-07-01T09:14:56.436Z" }, + { url = "https://files.pythonhosted.org/packages/17/d2/622f4547f69cd173955194b78e4d19ca4935a1b0f03a302d655c9f6aae65/pillow-11.3.0-cp313-cp313-win_arm64.whl", hash = "sha256:1904e1264881f682f02b7f8167935cce37bc97db457f8e7849dc3a6a52b99580", size = 2423055, upload-time = "2025-07-01T09:14:58.072Z" }, + { url = "https://files.pythonhosted.org/packages/dd/80/a8a2ac21dda2e82480852978416cfacd439a4b490a501a288ecf4fe2532d/pillow-11.3.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:4c834a3921375c48ee6b9624061076bc0a32a60b5532b322cc0ea64e639dd50e", size = 5281110, upload-time = "2025-07-01T09:14:59.79Z" }, + { url = "https://files.pythonhosted.org/packages/44/d6/b79754ca790f315918732e18f82a8146d33bcd7f4494380457ea89eb883d/pillow-11.3.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:5e05688ccef30ea69b9317a9ead994b93975104a677a36a8ed8106be9260aa6d", size = 4689547, upload-time = "2025-07-01T09:15:01.648Z" }, + { url = "https://files.pythonhosted.org/packages/49/20/716b8717d331150cb00f7fdd78169c01e8e0c219732a78b0e59b6bdb2fd6/pillow-11.3.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:1019b04af07fc0163e2810167918cb5add8d74674b6267616021ab558dc98ced", size = 5901554, upload-time = "2025-07-03T13:10:27.018Z" }, + { url = "https://files.pythonhosted.org/packages/74/cf/a9f3a2514a65bb071075063a96f0a5cf949c2f2fce683c15ccc83b1c1cab/pillow-11.3.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f944255db153ebb2b19c51fe85dd99ef0ce494123f21b9db4877ffdfc5590c7c", size = 7669132, upload-time = "2025-07-03T13:10:33.01Z" }, + { url = "https://files.pythonhosted.org/packages/98/3c/da78805cbdbee9cb43efe8261dd7cc0b4b93f2ac79b676c03159e9db2187/pillow-11.3.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1f85acb69adf2aaee8b7da124efebbdb959a104db34d3a2cb0f3793dbae422a8", size = 6005001, upload-time = "2025-07-01T09:15:03.365Z" }, + { url = "https://files.pythonhosted.org/packages/6c/fa/ce044b91faecf30e635321351bba32bab5a7e034c60187fe9698191aef4f/pillow-11.3.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:05f6ecbeff5005399bb48d198f098a9b4b6bdf27b8487c7f38ca16eeb070cd59", size = 6668814, upload-time = "2025-07-01T09:15:05.655Z" }, + { url = "https://files.pythonhosted.org/packages/7b/51/90f9291406d09bf93686434f9183aba27b831c10c87746ff49f127ee80cb/pillow-11.3.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a7bc6e6fd0395bc052f16b1a8670859964dbd7003bd0af2ff08342eb6e442cfe", size = 6113124, upload-time = "2025-07-01T09:15:07.358Z" }, + { url = "https://files.pythonhosted.org/packages/cd/5a/6fec59b1dfb619234f7636d4157d11fb4e196caeee220232a8d2ec48488d/pillow-11.3.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:83e1b0161c9d148125083a35c1c5a89db5b7054834fd4387499e06552035236c", size = 6747186, upload-time = "2025-07-01T09:15:09.317Z" }, + { url = "https://files.pythonhosted.org/packages/49/6b/00187a044f98255225f172de653941e61da37104a9ea60e4f6887717e2b5/pillow-11.3.0-cp313-cp313t-win32.whl", hash = "sha256:2a3117c06b8fb646639dce83694f2f9eac405472713fcb1ae887469c0d4f6788", size = 6277546, upload-time = "2025-07-01T09:15:11.311Z" }, + { url = "https://files.pythonhosted.org/packages/e8/5c/6caaba7e261c0d75bab23be79f1d06b5ad2a2ae49f028ccec801b0e853d6/pillow-11.3.0-cp313-cp313t-win_amd64.whl", hash = "sha256:857844335c95bea93fb39e0fa2726b4d9d758850b34075a7e3ff4f4fa3aa3b31", size = 6985102, upload-time = "2025-07-01T09:15:13.164Z" }, + { url = "https://files.pythonhosted.org/packages/f3/7e/b623008460c09a0cb38263c93b828c666493caee2eb34ff67f778b87e58c/pillow-11.3.0-cp313-cp313t-win_arm64.whl", hash = "sha256:8797edc41f3e8536ae4b10897ee2f637235c94f27404cac7297f7b607dd0716e", size = 2424803, upload-time = "2025-07-01T09:15:15.695Z" }, + { url = "https://files.pythonhosted.org/packages/9e/8e/9c089f01677d1264ab8648352dcb7773f37da6ad002542760c80107da816/pillow-11.3.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:48d254f8a4c776de343051023eb61ffe818299eeac478da55227d96e241de53f", size = 5316478, upload-time = "2025-07-01T09:15:52.209Z" }, + { url = "https://files.pythonhosted.org/packages/b5/a9/5749930caf674695867eb56a581e78eb5f524b7583ff10b01b6e5048acb3/pillow-11.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7aee118e30a4cf54fdd873bd3a29de51e29105ab11f9aad8c32123f58c8f8081", size = 4686522, upload-time = "2025-07-01T09:15:54.162Z" }, + { url = "https://files.pythonhosted.org/packages/43/46/0b85b763eb292b691030795f9f6bb6fcaf8948c39413c81696a01c3577f7/pillow-11.3.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:23cff760a9049c502721bdb743a7cb3e03365fafcdfc2ef9784610714166e5a4", size = 5853376, upload-time = "2025-07-03T13:11:01.066Z" }, + { url = "https://files.pythonhosted.org/packages/5e/c6/1a230ec0067243cbd60bc2dad5dc3ab46a8a41e21c15f5c9b52b26873069/pillow-11.3.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:6359a3bc43f57d5b375d1ad54a0074318a0844d11b76abccf478c37c986d3cfc", size = 7626020, upload-time = "2025-07-03T13:11:06.479Z" }, + { url = "https://files.pythonhosted.org/packages/63/dd/f296c27ffba447bfad76c6a0c44c1ea97a90cb9472b9304c94a732e8dbfb/pillow-11.3.0-cp39-cp39-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:092c80c76635f5ecb10f3f83d76716165c96f5229addbd1ec2bdbbda7d496e06", size = 5956732, upload-time = "2025-07-01T09:15:56.111Z" }, + { url = "https://files.pythonhosted.org/packages/a5/a0/98a3630f0b57f77bae67716562513d3032ae70414fcaf02750279c389a9e/pillow-11.3.0-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cadc9e0ea0a2431124cde7e1697106471fc4c1da01530e679b2391c37d3fbb3a", size = 6624404, upload-time = "2025-07-01T09:15:58.245Z" }, + { url = "https://files.pythonhosted.org/packages/de/e6/83dfba5646a290edd9a21964da07674409e410579c341fc5b8f7abd81620/pillow-11.3.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:6a418691000f2a418c9135a7cf0d797c1bb7d9a485e61fe8e7722845b95ef978", size = 6067760, upload-time = "2025-07-01T09:16:00.003Z" }, + { url = "https://files.pythonhosted.org/packages/bc/41/15ab268fe6ee9a2bc7391e2bbb20a98d3974304ab1a406a992dcb297a370/pillow-11.3.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:97afb3a00b65cc0804d1c7abddbf090a81eaac02768af58cbdcaaa0a931e0b6d", size = 6700534, upload-time = "2025-07-01T09:16:02.29Z" }, + { url = "https://files.pythonhosted.org/packages/64/79/6d4f638b288300bed727ff29f2a3cb63db054b33518a95f27724915e3fbc/pillow-11.3.0-cp39-cp39-win32.whl", hash = "sha256:ea944117a7974ae78059fcc1800e5d3295172bb97035c0c1d9345fca1419da71", size = 6277091, upload-time = "2025-07-01T09:16:04.4Z" }, + { url = "https://files.pythonhosted.org/packages/46/05/4106422f45a05716fd34ed21763f8ec182e8ea00af6e9cb05b93a247361a/pillow-11.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:e5c5858ad8ec655450a7c7df532e9842cf8df7cc349df7225c60d5d348c8aada", size = 6986091, upload-time = "2025-07-01T09:16:06.342Z" }, + { url = "https://files.pythonhosted.org/packages/63/c6/287fd55c2c12761d0591549d48885187579b7c257bef0c6660755b0b59ae/pillow-11.3.0-cp39-cp39-win_arm64.whl", hash = "sha256:6abdbfd3aea42be05702a8dd98832329c167ee84400a1d1f61ab11437f1717eb", size = 2422632, upload-time = "2025-07-01T09:16:08.142Z" }, + { url = "https://files.pythonhosted.org/packages/6f/8b/209bd6b62ce8367f47e68a218bffac88888fdf2c9fcf1ecadc6c3ec1ebc7/pillow-11.3.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:3cee80663f29e3843b68199b9d6f4f54bd1d4a6b59bdd91bceefc51238bcb967", size = 5270556, upload-time = "2025-07-01T09:16:09.961Z" }, + { url = "https://files.pythonhosted.org/packages/2e/e6/231a0b76070c2cfd9e260a7a5b504fb72da0a95279410fa7afd99d9751d6/pillow-11.3.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:b5f56c3f344f2ccaf0dd875d3e180f631dc60a51b314295a3e681fe8cf851fbe", size = 4654625, upload-time = "2025-07-01T09:16:11.913Z" }, + { url = "https://files.pythonhosted.org/packages/13/f4/10cf94fda33cb12765f2397fc285fa6d8eb9c29de7f3185165b702fc7386/pillow-11.3.0-pp310-pypy310_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:e67d793d180c9df62f1f40aee3accca4829d3794c95098887edc18af4b8b780c", size = 4874207, upload-time = "2025-07-03T13:11:10.201Z" }, + { url = "https://files.pythonhosted.org/packages/72/c9/583821097dc691880c92892e8e2d41fe0a5a3d6021f4963371d2f6d57250/pillow-11.3.0-pp310-pypy310_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d000f46e2917c705e9fb93a3606ee4a819d1e3aa7a9b442f6444f07e77cf5e25", size = 6583939, upload-time = "2025-07-03T13:11:15.68Z" }, + { url = "https://files.pythonhosted.org/packages/3b/8e/5c9d410f9217b12320efc7c413e72693f48468979a013ad17fd690397b9a/pillow-11.3.0-pp310-pypy310_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:527b37216b6ac3a12d7838dc3bd75208ec57c1c6d11ef01902266a5a0c14fc27", size = 4957166, upload-time = "2025-07-01T09:16:13.74Z" }, + { url = "https://files.pythonhosted.org/packages/62/bb/78347dbe13219991877ffb3a91bf09da8317fbfcd4b5f9140aeae020ad71/pillow-11.3.0-pp310-pypy310_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:be5463ac478b623b9dd3937afd7fb7ab3d79dd290a28e2b6df292dc75063eb8a", size = 5581482, upload-time = "2025-07-01T09:16:16.107Z" }, + { url = "https://files.pythonhosted.org/packages/d9/28/1000353d5e61498aaeaaf7f1e4b49ddb05f2c6575f9d4f9f914a3538b6e1/pillow-11.3.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:8dc70ca24c110503e16918a658b869019126ecfe03109b754c402daff12b3d9f", size = 6984596, upload-time = "2025-07-01T09:16:18.07Z" }, + { url = "https://files.pythonhosted.org/packages/9e/e3/6fa84033758276fb31da12e5fb66ad747ae83b93c67af17f8c6ff4cc8f34/pillow-11.3.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7c8ec7a017ad1bd562f93dbd8505763e688d388cde6e4a010ae1486916e713e6", size = 5270566, upload-time = "2025-07-01T09:16:19.801Z" }, + { url = "https://files.pythonhosted.org/packages/5b/ee/e8d2e1ab4892970b561e1ba96cbd59c0d28cf66737fc44abb2aec3795a4e/pillow-11.3.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:9ab6ae226de48019caa8074894544af5b53a117ccb9d3b3dcb2871464c829438", size = 4654618, upload-time = "2025-07-01T09:16:21.818Z" }, + { url = "https://files.pythonhosted.org/packages/f2/6d/17f80f4e1f0761f02160fc433abd4109fa1548dcfdca46cfdadaf9efa565/pillow-11.3.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:fe27fb049cdcca11f11a7bfda64043c37b30e6b91f10cb5bab275806c32f6ab3", size = 4874248, upload-time = "2025-07-03T13:11:20.738Z" }, + { url = "https://files.pythonhosted.org/packages/de/5f/c22340acd61cef960130585bbe2120e2fd8434c214802f07e8c03596b17e/pillow-11.3.0-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:465b9e8844e3c3519a983d58b80be3f668e2a7a5db97f2784e7079fbc9f9822c", size = 6583963, upload-time = "2025-07-03T13:11:26.283Z" }, + { url = "https://files.pythonhosted.org/packages/31/5e/03966aedfbfcbb4d5f8aa042452d3361f325b963ebbadddac05b122e47dd/pillow-11.3.0-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5418b53c0d59b3824d05e029669efa023bbef0f3e92e75ec8428f3799487f361", size = 4957170, upload-time = "2025-07-01T09:16:23.762Z" }, + { url = "https://files.pythonhosted.org/packages/cc/2d/e082982aacc927fc2cab48e1e731bdb1643a1406acace8bed0900a61464e/pillow-11.3.0-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:504b6f59505f08ae014f724b6207ff6222662aab5cc9542577fb084ed0676ac7", size = 5581505, upload-time = "2025-07-01T09:16:25.593Z" }, + { url = "https://files.pythonhosted.org/packages/34/e7/ae39f538fd6844e982063c3a5e4598b8ced43b9633baa3a85ef33af8c05c/pillow-11.3.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:c84d689db21a1c397d001aa08241044aa2069e7587b398c8cc63020390b1c1b8", size = 6984598, upload-time = "2025-07-01T09:16:27.732Z" }, +] + +[[package]] +name = "pillow" +version = "12.2.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.10'", +] +sdist = { url = "https://files.pythonhosted.org/packages/8c/21/c2bcdd5906101a30244eaffc1b6e6ce71a31bd0742a01eb89e660ebfac2d/pillow-12.2.0.tar.gz", hash = "sha256:a830b1a40919539d07806aa58e1b114df53ddd43213d9c8b75847eee6c0182b5", size = 46987819, upload-time = "2026-04-01T14:46:17.687Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3a/aa/d0b28e1c811cd4d5f5c2bfe2e022292bd255ae5744a3b9ac7d6c8f72dd75/pillow-12.2.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:a4e8f36e677d3336f35089648c8955c51c6d386a13cf6ee9c189c5f5bd713a9f", size = 5354355, upload-time = "2026-04-01T14:42:15.402Z" }, + { url = "https://files.pythonhosted.org/packages/27/8e/1d5b39b8ae2bd7650d0c7b6abb9602d16043ead9ebbfef4bc4047454da2a/pillow-12.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2e589959f10d9824d39b350472b92f0ce3b443c0a3442ebf41c40cb8361c5b97", size = 4695871, upload-time = "2026-04-01T14:42:18.234Z" }, + { url = "https://files.pythonhosted.org/packages/f0/c5/dcb7a6ca6b7d3be41a76958e90018d56c8462166b3ef223150360850c8da/pillow-12.2.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:a52edc8bfff4429aaabdf4d9ee0daadbbf8562364f940937b941f87a4290f5ff", size = 6269734, upload-time = "2026-04-01T14:42:20.608Z" }, + { url = "https://files.pythonhosted.org/packages/ea/f1/aa1bb13b2f4eba914e9637893c73f2af8e48d7d4023b9d3750d4c5eb2d0c/pillow-12.2.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:975385f4776fafde056abb318f612ef6285b10a1f12b8570f3647ad0d74b48ec", size = 8076080, upload-time = "2026-04-01T14:42:23.095Z" }, + { url = "https://files.pythonhosted.org/packages/a1/2a/8c79d6a53169937784604a8ae8d77e45888c41537f7f6f65ed1f407fe66d/pillow-12.2.0-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bd9c0c7a0c681a347b3194c500cb1e6ca9cab053ea4d82a5cf45b6b754560136", size = 6382236, upload-time = "2026-04-01T14:42:25.82Z" }, + { url = "https://files.pythonhosted.org/packages/b5/42/bbcb6051030e1e421d103ce7a8ecadf837aa2f39b8f82ef1a8d37c3d4ebc/pillow-12.2.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:88d387ff40b3ff7c274947ed3125dedf5262ec6919d83946753b5f3d7c67ea4c", size = 7070220, upload-time = "2026-04-01T14:42:28.68Z" }, + { url = "https://files.pythonhosted.org/packages/3f/e1/c2a7d6dd8cfa6b231227da096fd2d58754bab3603b9d73bf609d3c18b64f/pillow-12.2.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:51c4167c34b0d8ba05b547a3bb23578d0ba17b80a5593f93bd8ecb123dd336a3", size = 6493124, upload-time = "2026-04-01T14:42:31.579Z" }, + { url = "https://files.pythonhosted.org/packages/5f/41/7c8617da5d32e1d2f026e509484fdb6f3ad7efaef1749a0c1928adbb099e/pillow-12.2.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:34c0d99ecccea270c04882cb3b86e7b57296079c9a4aff88cb3b33563d95afaa", size = 7194324, upload-time = "2026-04-01T14:42:34.615Z" }, + { url = "https://files.pythonhosted.org/packages/2d/de/a777627e19fd6d62f84070ee1521adde5eeda4855b5cf60fe0b149118bca/pillow-12.2.0-cp310-cp310-win32.whl", hash = "sha256:b85f66ae9eb53e860a873b858b789217ba505e5e405a24b85c0464822fe88032", size = 6376363, upload-time = "2026-04-01T14:42:37.19Z" }, + { url = "https://files.pythonhosted.org/packages/e7/34/fc4cb5204896465842767b96d250c08410f01f2f28afc43b257de842eed5/pillow-12.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:673aa32138f3e7531ccdbca7b3901dba9b70940a19ccecc6a37c77d5fdeb05b5", size = 7083523, upload-time = "2026-04-01T14:42:39.62Z" }, + { url = "https://files.pythonhosted.org/packages/2d/a0/32852d36bc7709f14dc3f64f929a275e958ad8c19a6deba9610d458e28b3/pillow-12.2.0-cp310-cp310-win_arm64.whl", hash = "sha256:3e080565d8d7c671db5802eedfb438e5565ffa40115216eabb8cd52d0ecce024", size = 2463318, upload-time = "2026-04-01T14:42:42.063Z" }, + { url = "https://files.pythonhosted.org/packages/68/e1/748f5663efe6edcfc4e74b2b93edfb9b8b99b67f21a854c3ae416500a2d9/pillow-12.2.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:8be29e59487a79f173507c30ddf57e733a357f67881430449bb32614075a40ab", size = 5354347, upload-time = "2026-04-01T14:42:44.255Z" }, + { url = "https://files.pythonhosted.org/packages/47/a1/d5ff69e747374c33a3b53b9f98cca7889fce1fd03d79cdc4e1bccc6c5a87/pillow-12.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:71cde9a1e1551df7d34a25462fc60325e8a11a82cc2e2f54578e5e9a1e153d65", size = 4695873, upload-time = "2026-04-01T14:42:46.452Z" }, + { url = "https://files.pythonhosted.org/packages/df/21/e3fbdf54408a973c7f7f89a23b2cb97a7ef30c61ab4142af31eee6aebc88/pillow-12.2.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f490f9368b6fc026f021db16d7ec2fbf7d89e2edb42e8ec09d2c60505f5729c7", size = 6280168, upload-time = "2026-04-01T14:42:49.228Z" }, + { url = "https://files.pythonhosted.org/packages/d3/f1/00b7278c7dd52b17ad4329153748f87b6756ec195ff786c2bdf12518337d/pillow-12.2.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8bd7903a5f2a4545f6fd5935c90058b89d30045568985a71c79f5fd6edf9b91e", size = 8088188, upload-time = "2026-04-01T14:42:51.735Z" }, + { url = "https://files.pythonhosted.org/packages/ad/cf/220a5994ef1b10e70e85748b75649d77d506499352be135a4989c957b701/pillow-12.2.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3997232e10d2920a68d25191392e3a4487d8183039e1c74c2297f00ed1c50705", size = 6394401, upload-time = "2026-04-01T14:42:54.343Z" }, + { url = "https://files.pythonhosted.org/packages/e9/bd/e51a61b1054f09437acfbc2ff9106c30d1eb76bc1453d428399946781253/pillow-12.2.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e74473c875d78b8e9d5da2a70f7099549f9eb37ded4e2f6a463e60125bccd176", size = 7079655, upload-time = "2026-04-01T14:42:56.954Z" }, + { url = "https://files.pythonhosted.org/packages/6b/3d/45132c57d5fb4b5744567c3817026480ac7fc3ce5d4c47902bc0e7f6f853/pillow-12.2.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:56a3f9c60a13133a98ecff6197af34d7824de9b7b38c3654861a725c970c197b", size = 6503105, upload-time = "2026-04-01T14:42:59.847Z" }, + { url = "https://files.pythonhosted.org/packages/7d/2e/9df2fc1e82097b1df3dce58dc43286aa01068e918c07574711fcc53e6fb4/pillow-12.2.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:90e6f81de50ad6b534cab6e5aef77ff6e37722b2f5d908686f4a5c9eba17a909", size = 7203402, upload-time = "2026-04-01T14:43:02.664Z" }, + { url = "https://files.pythonhosted.org/packages/bd/2e/2941e42858ebb67e50ae741473de81c2984e6eff7b397017623c676e2e8d/pillow-12.2.0-cp311-cp311-win32.whl", hash = "sha256:8c984051042858021a54926eb597d6ee3012393ce9c181814115df4c60b9a808", size = 6378149, upload-time = "2026-04-01T14:43:05.274Z" }, + { url = "https://files.pythonhosted.org/packages/69/42/836b6f3cd7f3e5fa10a1f1a5420447c17966044c8fbf589cc0452d5502db/pillow-12.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:6e6b2a0c538fc200b38ff9eb6628228b77908c319a005815f2dde585a0664b60", size = 7082626, upload-time = "2026-04-01T14:43:08.557Z" }, + { url = "https://files.pythonhosted.org/packages/c2/88/549194b5d6f1f494b485e493edc6693c0a16f4ada488e5bd974ed1f42fad/pillow-12.2.0-cp311-cp311-win_arm64.whl", hash = "sha256:9a8a34cc89c67a65ea7437ce257cea81a9dad65b29805f3ecee8c8fe8ff25ffe", size = 2463531, upload-time = "2026-04-01T14:43:10.743Z" }, + { url = "https://files.pythonhosted.org/packages/58/be/7482c8a5ebebbc6470b3eb791812fff7d5e0216c2be3827b30b8bb6603ed/pillow-12.2.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2d192a155bbcec180f8564f693e6fd9bccff5a7af9b32e2e4bf8c9c69dbad6b5", size = 5308279, upload-time = "2026-04-01T14:43:13.246Z" }, + { url = "https://files.pythonhosted.org/packages/d8/95/0a351b9289c2b5cbde0bacd4a83ebc44023e835490a727b2a3bd60ddc0f4/pillow-12.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f3f40b3c5a968281fd507d519e444c35f0ff171237f4fdde090dd60699458421", size = 4695490, upload-time = "2026-04-01T14:43:15.584Z" }, + { url = "https://files.pythonhosted.org/packages/de/af/4e8e6869cbed569d43c416fad3dc4ecb944cb5d9492defaed89ddd6fe871/pillow-12.2.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:03e7e372d5240cc23e9f07deca4d775c0817bffc641b01e9c3af208dbd300987", size = 6284462, upload-time = "2026-04-01T14:43:18.268Z" }, + { url = "https://files.pythonhosted.org/packages/e9/9e/c05e19657fd57841e476be1ab46c4d501bffbadbafdc31a6d665f8b737b6/pillow-12.2.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b86024e52a1b269467a802258c25521e6d742349d760728092e1bc2d135b4d76", size = 8094744, upload-time = "2026-04-01T14:43:20.716Z" }, + { url = "https://files.pythonhosted.org/packages/2b/54/1789c455ed10176066b6e7e6da1b01e50e36f94ba584dc68d9eebfe9156d/pillow-12.2.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7371b48c4fa448d20d2714c9a1f775a81155050d383333e0a6c15b1123dda005", size = 6398371, upload-time = "2026-04-01T14:43:23.443Z" }, + { url = "https://files.pythonhosted.org/packages/43/e3/fdc657359e919462369869f1c9f0e973f353f9a9ee295a39b1fea8ee1a77/pillow-12.2.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:62f5409336adb0663b7caa0da5c7d9e7bdbaae9ce761d34669420c2a801b2780", size = 7087215, upload-time = "2026-04-01T14:43:26.758Z" }, + { url = "https://files.pythonhosted.org/packages/8b/f8/2f6825e441d5b1959d2ca5adec984210f1ec086435b0ed5f52c19b3b8a6e/pillow-12.2.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:01afa7cf67f74f09523699b4e88c73fb55c13346d212a59a2db1f86b0a63e8c5", size = 6509783, upload-time = "2026-04-01T14:43:29.56Z" }, + { url = "https://files.pythonhosted.org/packages/67/f9/029a27095ad20f854f9dba026b3ea6428548316e057e6fc3545409e86651/pillow-12.2.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fc3d34d4a8fbec3e88a79b92e5465e0f9b842b628675850d860b8bd300b159f5", size = 7212112, upload-time = "2026-04-01T14:43:32.091Z" }, + { url = "https://files.pythonhosted.org/packages/be/42/025cfe05d1be22dbfdb4f264fe9de1ccda83f66e4fc3aac94748e784af04/pillow-12.2.0-cp312-cp312-win32.whl", hash = "sha256:58f62cc0f00fd29e64b29f4fd923ffdb3859c9f9e6105bfc37ba1d08994e8940", size = 6378489, upload-time = "2026-04-01T14:43:34.601Z" }, + { url = "https://files.pythonhosted.org/packages/5d/7b/25a221d2c761c6a8ae21bfa3874988ff2583e19cf8a27bf2fee358df7942/pillow-12.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:7f84204dee22a783350679a0333981df803dac21a0190d706a50475e361c93f5", size = 7084129, upload-time = "2026-04-01T14:43:37.213Z" }, + { url = "https://files.pythonhosted.org/packages/10/e1/542a474affab20fd4a0f1836cb234e8493519da6b76899e30bcc5d990b8b/pillow-12.2.0-cp312-cp312-win_arm64.whl", hash = "sha256:af73337013e0b3b46f175e79492d96845b16126ddf79c438d7ea7ff27783a414", size = 2463612, upload-time = "2026-04-01T14:43:39.421Z" }, + { url = "https://files.pythonhosted.org/packages/4a/01/53d10cf0dbad820a8db274d259a37ba50b88b24768ddccec07355382d5ad/pillow-12.2.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:8297651f5b5679c19968abefd6bb84d95fe30ef712eb1b2d9b2d31ca61267f4c", size = 4100837, upload-time = "2026-04-01T14:43:41.506Z" }, + { url = "https://files.pythonhosted.org/packages/0f/98/f3a6657ecb698c937f6c76ee564882945f29b79bad496abcba0e84659ec5/pillow-12.2.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:50d8520da2a6ce0af445fa6d648c4273c3eeefbc32d7ce049f22e8b5c3daecc2", size = 4176528, upload-time = "2026-04-01T14:43:43.773Z" }, + { url = "https://files.pythonhosted.org/packages/69/bc/8986948f05e3ea490b8442ea1c1d4d990b24a7e43d8a51b2c7d8b1dced36/pillow-12.2.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:766cef22385fa1091258ad7e6216792b156dc16d8d3fa607e7545b2b72061f1c", size = 3640401, upload-time = "2026-04-01T14:43:45.87Z" }, + { url = "https://files.pythonhosted.org/packages/34/46/6c717baadcd62bc8ed51d238d521ab651eaa74838291bda1f86fe1f864c9/pillow-12.2.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5d2fd0fa6b5d9d1de415060363433f28da8b1526c1c129020435e186794b3795", size = 5308094, upload-time = "2026-04-01T14:43:48.438Z" }, + { url = "https://files.pythonhosted.org/packages/71/43/905a14a8b17fdb1ccb58d282454490662d2cb89a6bfec26af6d3520da5ec/pillow-12.2.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:56b25336f502b6ed02e889f4ece894a72612fe885889a6e8c4c80239ff6e5f5f", size = 4695402, upload-time = "2026-04-01T14:43:51.292Z" }, + { url = "https://files.pythonhosted.org/packages/73/dd/42107efcb777b16fa0393317eac58f5b5cf30e8392e266e76e51cff28c3d/pillow-12.2.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f1c943e96e85df3d3478f7b691f229887e143f81fedab9b20205349ab04d73ed", size = 6280005, upload-time = "2026-04-01T14:43:54.242Z" }, + { url = "https://files.pythonhosted.org/packages/a8/68/b93e09e5e8549019e61acf49f65b1a8530765a7f812c77a7461bca7e4494/pillow-12.2.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:03f6fab9219220f041c74aeaa2939ff0062bd5c364ba9ce037197f4c6d498cd9", size = 8090669, upload-time = "2026-04-01T14:43:57.335Z" }, + { url = "https://files.pythonhosted.org/packages/4b/6e/3ccb54ce8ec4ddd1accd2d89004308b7b0b21c4ac3d20fa70af4760a4330/pillow-12.2.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5cdfebd752ec52bf5bb4e35d9c64b40826bc5b40a13df7c3cda20a2c03a0f5ed", size = 6395194, upload-time = "2026-04-01T14:43:59.864Z" }, + { url = "https://files.pythonhosted.org/packages/67/ee/21d4e8536afd1a328f01b359b4d3997b291ffd35a237c877b331c1c3b71c/pillow-12.2.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:eedf4b74eda2b5a4b2b2fb4c006d6295df3bf29e459e198c90ea48e130dc75c3", size = 7082423, upload-time = "2026-04-01T14:44:02.74Z" }, + { url = "https://files.pythonhosted.org/packages/78/5f/e9f86ab0146464e8c133fe85df987ed9e77e08b29d8d35f9f9f4d6f917ba/pillow-12.2.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:00a2865911330191c0b818c59103b58a5e697cae67042366970a6b6f1b20b7f9", size = 6505667, upload-time = "2026-04-01T14:44:05.381Z" }, + { url = "https://files.pythonhosted.org/packages/ed/1e/409007f56a2fdce61584fd3acbc2bbc259857d555196cedcadc68c015c82/pillow-12.2.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1e1757442ed87f4912397c6d35a0db6a7b52592156014706f17658ff58bbf795", size = 7208580, upload-time = "2026-04-01T14:44:08.39Z" }, + { url = "https://files.pythonhosted.org/packages/23/c4/7349421080b12fb35414607b8871e9534546c128a11965fd4a7002ccfbee/pillow-12.2.0-cp313-cp313-win32.whl", hash = "sha256:144748b3af2d1b358d41286056d0003f47cb339b8c43a9ea42f5fea4d8c66b6e", size = 6375896, upload-time = "2026-04-01T14:44:11.197Z" }, + { url = "https://files.pythonhosted.org/packages/3f/82/8a3739a5e470b3c6cbb1d21d315800d8e16bff503d1f16b03a4ec3212786/pillow-12.2.0-cp313-cp313-win_amd64.whl", hash = "sha256:390ede346628ccc626e5730107cde16c42d3836b89662a115a921f28440e6a3b", size = 7081266, upload-time = "2026-04-01T14:44:13.947Z" }, + { url = "https://files.pythonhosted.org/packages/c3/25/f968f618a062574294592f668218f8af564830ccebdd1fa6200f598e65c5/pillow-12.2.0-cp313-cp313-win_arm64.whl", hash = "sha256:8023abc91fba39036dbce14a7d6535632f99c0b857807cbbbf21ecc9f4717f06", size = 2463508, upload-time = "2026-04-01T14:44:16.312Z" }, + { url = "https://files.pythonhosted.org/packages/4d/a4/b342930964e3cb4dce5038ae34b0eab4653334995336cd486c5a8c25a00c/pillow-12.2.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:042db20a421b9bafecc4b84a8b6e444686bd9d836c7fd24542db3e7df7baad9b", size = 5309927, upload-time = "2026-04-01T14:44:18.89Z" }, + { url = "https://files.pythonhosted.org/packages/9f/de/23198e0a65a9cf06123f5435a5d95cea62a635697f8f03d134d3f3a96151/pillow-12.2.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:dd025009355c926a84a612fecf58bb315a3f6814b17ead51a8e48d3823d9087f", size = 4698624, upload-time = "2026-04-01T14:44:21.115Z" }, + { url = "https://files.pythonhosted.org/packages/01/a6/1265e977f17d93ea37aa28aa81bad4fa597933879fac2520d24e021c8da3/pillow-12.2.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:88ddbc66737e277852913bd1e07c150cc7bb124539f94c4e2df5344494e0a612", size = 6321252, upload-time = "2026-04-01T14:44:23.663Z" }, + { url = "https://files.pythonhosted.org/packages/3c/83/5982eb4a285967baa70340320be9f88e57665a387e3a53a7f0db8231a0cd/pillow-12.2.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d362d1878f00c142b7e1a16e6e5e780f02be8195123f164edf7eddd911eefe7c", size = 8126550, upload-time = "2026-04-01T14:44:26.772Z" }, + { url = "https://files.pythonhosted.org/packages/4e/48/6ffc514adce69f6050d0753b1a18fd920fce8cac87620d5a31231b04bfc5/pillow-12.2.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2c727a6d53cb0018aadd8018c2b938376af27914a68a492f59dfcaca650d5eea", size = 6433114, upload-time = "2026-04-01T14:44:29.615Z" }, + { url = "https://files.pythonhosted.org/packages/36/a3/f9a77144231fb8d40ee27107b4463e205fa4677e2ca2548e14da5cf18dce/pillow-12.2.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:efd8c21c98c5cc60653bcb311bef2ce0401642b7ce9d09e03a7da87c878289d4", size = 7115667, upload-time = "2026-04-01T14:44:32.773Z" }, + { url = "https://files.pythonhosted.org/packages/c1/fc/ac4ee3041e7d5a565e1c4fd72a113f03b6394cc72ab7089d27608f8aaccb/pillow-12.2.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9f08483a632889536b8139663db60f6724bfcb443c96f1b18855860d7d5c0fd4", size = 6538966, upload-time = "2026-04-01T14:44:35.252Z" }, + { url = "https://files.pythonhosted.org/packages/c0/a8/27fb307055087f3668f6d0a8ccb636e7431d56ed0750e07a60547b1e083e/pillow-12.2.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:dac8d77255a37e81a2efcbd1fc05f1c15ee82200e6c240d7e127e25e365c39ea", size = 7238241, upload-time = "2026-04-01T14:44:37.875Z" }, + { url = "https://files.pythonhosted.org/packages/ad/4b/926ab182c07fccae9fcb120043464e1ff1564775ec8864f21a0ebce6ac25/pillow-12.2.0-cp313-cp313t-win32.whl", hash = "sha256:ee3120ae9dff32f121610bb08e4313be87e03efeadfc6c0d18f89127e24d0c24", size = 6379592, upload-time = "2026-04-01T14:44:40.336Z" }, + { url = "https://files.pythonhosted.org/packages/c2/c4/f9e476451a098181b30050cc4c9a3556b64c02cf6497ea421ac047e89e4b/pillow-12.2.0-cp313-cp313t-win_amd64.whl", hash = "sha256:325ca0528c6788d2a6c3d40e3568639398137346c3d6e66bb61db96b96511c98", size = 7085542, upload-time = "2026-04-01T14:44:43.251Z" }, + { url = "https://files.pythonhosted.org/packages/00/a4/285f12aeacbe2d6dc36c407dfbbe9e96d4a80b0fb710a337f6d2ad978c75/pillow-12.2.0-cp313-cp313t-win_arm64.whl", hash = "sha256:2e5a76d03a6c6dcef67edabda7a52494afa4035021a79c8558e14af25313d453", size = 2465765, upload-time = "2026-04-01T14:44:45.996Z" }, + { url = "https://files.pythonhosted.org/packages/4e/b7/2437044fb910f499610356d1352e3423753c98e34f915252aafecc64889f/pillow-12.2.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0538bd5e05efec03ae613fd89c4ce0368ecd2ba239cc25b9f9be7ed426b0af1f", size = 5273969, upload-time = "2026-04-01T14:45:55.538Z" }, + { url = "https://files.pythonhosted.org/packages/f6/f4/8316e31de11b780f4ac08ef3654a75555e624a98db1056ecb2122d008d5a/pillow-12.2.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:394167b21da716608eac917c60aa9b969421b5dcbbe02ae7f013e7b85811c69d", size = 4659674, upload-time = "2026-04-01T14:45:58.093Z" }, + { url = "https://files.pythonhosted.org/packages/d4/37/664fca7201f8bb2aa1d20e2c3d5564a62e6ae5111741966c8319ca802361/pillow-12.2.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5d04bfa02cc2d23b497d1e90a0f927070043f6cbf303e738300532379a4b4e0f", size = 5288479, upload-time = "2026-04-01T14:46:01.141Z" }, + { url = "https://files.pythonhosted.org/packages/49/62/5b0ed78fce87346be7a5cfcfaaad91f6a1f98c26f86bdbafa2066c647ef6/pillow-12.2.0-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0c838a5125cee37e68edec915651521191cef1e6aa336b855f495766e77a366e", size = 7032230, upload-time = "2026-04-01T14:46:03.874Z" }, + { url = "https://files.pythonhosted.org/packages/c3/28/ec0fc38107fc32536908034e990c47914c57cd7c5a3ece4d8d8f7ffd7e27/pillow-12.2.0-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4a6c9fa44005fa37a91ebfc95d081e8079757d2e904b27103f4f5fa6f0bf78c0", size = 5355404, upload-time = "2026-04-01T14:46:06.33Z" }, + { url = "https://files.pythonhosted.org/packages/5e/8b/51b0eddcfa2180d60e41f06bd6d0a62202b20b59c68f5a132e615b75aecf/pillow-12.2.0-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:25373b66e0dd5905ed63fa3cae13c82fbddf3079f2c8bf15c6fb6a35586324c1", size = 6002215, upload-time = "2026-04-01T14:46:08.83Z" }, + { url = "https://files.pythonhosted.org/packages/bc/60/5382c03e1970de634027cee8e1b7d39776b778b81812aaf45b694dfe9e28/pillow-12.2.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:bfa9c230d2fe991bed5318a5f119bd6780cda2915cca595393649fc118ab895e", size = 7080946, upload-time = "2026-04-01T14:46:11.734Z" }, ] [[package]] name = "platformdirs" -version = "4.3.8" +version = "4.4.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/fe/8b/3c73abc9c759ecd3f1f7ceff6685840859e8070c4d947c93fae71f6a0bf2/platformdirs-4.3.8.tar.gz", hash = "sha256:3d512d96e16bcb959a814c9f348431070822a6496326a4be0911c40b5a74c2bc", size = 21362, upload-time = "2025-05-07T22:47:42.121Z" } +resolution-markers = [ + "python_full_version < '3.10'", +] +sdist = { url = "https://files.pythonhosted.org/packages/23/e8/21db9c9987b0e728855bd57bff6984f67952bea55d6f75e055c46b5383e8/platformdirs-4.4.0.tar.gz", hash = "sha256:ca753cf4d81dc309bc67b0ea38fd15dc97bc30ce419a7f58d13eb3bf14c4febf", size = 21634, upload-time = "2025-08-26T14:32:04.268Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/fe/39/979e8e21520d4e47a0bbe349e2713c0aac6f3d853d0e5b34d76206c439aa/platformdirs-4.3.8-py3-none-any.whl", hash = "sha256:ff7059bb7eb1179e2685604f4aaf157cfd9535242bd23742eadc3c13542139b4", size = 18567, upload-time = "2025-05-07T22:47:40.376Z" }, + { url = "https://files.pythonhosted.org/packages/40/4b/2028861e724d3bd36227adfa20d3fd24c3fc6d52032f4a93c133be5d17ce/platformdirs-4.4.0-py3-none-any.whl", hash = "sha256:abd01743f24e5287cd7a5db3752faf1a2d65353f38ec26d98e25a6db65958c85", size = 18654, upload-time = "2025-08-26T14:32:02.735Z" }, +] + +[[package]] +name = "platformdirs" +version = "4.9.6" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.10'", +] +sdist = { url = "https://files.pythonhosted.org/packages/9f/4a/0883b8e3802965322523f0b200ecf33d31f10991d0401162f4b23c698b42/platformdirs-4.9.6.tar.gz", hash = "sha256:3bfa75b0ad0db84096ae777218481852c0ebc6c727b3168c1b9e0118e458cf0a", size = 29400, upload-time = "2026-04-09T00:04:10.812Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/75/a6/a0a304dc33b49145b21f4808d763822111e67d1c3a32b524a1baf947b6e1/platformdirs-4.9.6-py3-none-any.whl", hash = "sha256:e61adb1d5e5cb3441b4b7710bea7e4c12250ca49439228cc1021c00dcfac0917", size = 21348, upload-time = "2026-04-09T00:04:09.463Z" }, ] [[package]] @@ -620,16 +757,16 @@ wheels = [ [[package]] name = "pygments" -version = "2.19.1" +version = "2.20.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/7c/2d/c3338d48ea6cc0feb8446d8e6937e1408088a72a39937982cc6111d17f84/pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f", size = 4968581, upload-time = "2025-01-06T17:26:30.443Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991, upload-time = "2026-03-29T13:29:33.898Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/8a/0b/9fcc47d19c48b59121088dd6da2488a49d5f72dacf8262e2790a1d2c7d15/pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c", size = 1225293, upload-time = "2025-01-06T17:26:25.553Z" }, + { url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" }, ] [[package]] name = "pyinstaller" -version = "6.14.1" +version = "6.19.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "altgraph" }, @@ -641,33 +778,33 @@ dependencies = [ { name = "pywin32-ctypes", marker = "sys_platform == 'win32'" }, { name = "setuptools" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/9f/4a/d66d3a9c34349d73eb099401060e2591da8ccc5ed427e54fff3961302513/pyinstaller-6.14.1.tar.gz", hash = "sha256:35d5c06a668e21f0122178dbf20e40fd21012dc8f6170042af6050c4e7b3edca", size = 4284317, upload-time = "2025-06-08T18:45:46.367Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c8/63/fd62472b6371d89dc138d40c36d87a50dc2de18a035803bbdc376b4ffac4/pyinstaller-6.19.0.tar.gz", hash = "sha256:ec73aeb8bd9b7f2f1240d328a4542e90b3c6e6fbc106014778431c616592a865", size = 4036072, upload-time = "2026-02-14T18:06:28.718Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/43/f6/fa56e547fe849db4b8da0acaad6101a6382c18370c7e0f378a1cf0ea89f0/pyinstaller-6.14.1-py3-none-macosx_10_13_universal2.whl", hash = "sha256:da559cfe4f7a20a7ebdafdf12ea2a03ea94d3caa49736ef53ee2c155d78422c9", size = 999937, upload-time = "2025-06-08T18:44:26.429Z" }, - { url = "https://files.pythonhosted.org/packages/af/a6/a2814978f47ae038b1ce112717adbdcfd8dfb9504e5c52437902331cde1a/pyinstaller-6.14.1-py3-none-manylinux2014_aarch64.whl", hash = "sha256:f040d1e3d42af3730104078d10d4a8ca3350bd1c78de48f12e1b26f761e0cbc3", size = 719569, upload-time = "2025-06-08T18:44:30.948Z" }, - { url = "https://files.pythonhosted.org/packages/35/f0/86391a4c0f558aef43a7dac8f678d46f4e5b84bd133308e3ea81f7384ab9/pyinstaller-6.14.1-py3-none-manylinux2014_i686.whl", hash = "sha256:7b8813fb2d5a82ef4ceffc342ed9a11a6fc1ef21e68e833dbd8fedb8a188d3f5", size = 729824, upload-time = "2025-06-08T18:44:34.983Z" }, - { url = "https://files.pythonhosted.org/packages/e5/88/446814e335d937406e6e1ae4a77ed922b8eea8b90f3aaf69427a16b58ed2/pyinstaller-6.14.1-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:e2cfdbc6dd41d19872054fc233da18856ec422a7fdea899b6985ae04f980376a", size = 727937, upload-time = "2025-06-08T18:44:38.954Z" }, - { url = "https://files.pythonhosted.org/packages/c6/0f/5aa891c61d303ad4a794b7e2f864aacf64fe0f6f5559e2aec0f742595fad/pyinstaller-6.14.1-py3-none-manylinux2014_s390x.whl", hash = "sha256:a4d53b3ecb5786b097b79bda88c4089186fc1498ef7eaa6cee57599ae459241e", size = 724762, upload-time = "2025-06-08T18:44:42.768Z" }, - { url = "https://files.pythonhosted.org/packages/c5/92/e32ec0a1754852a8ed5a60f6746c6483e3da68aee97d314f3a3a99e0ed9e/pyinstaller-6.14.1-py3-none-manylinux2014_x86_64.whl", hash = "sha256:c48dd257f77f61ebea2d1fdbaf11243730f2271873c88d3b5ecb7869525d3bcb", size = 724957, upload-time = "2025-06-08T18:44:46.829Z" }, - { url = "https://files.pythonhosted.org/packages/c3/66/1260f384e47bf939f6238f791d4cda7edb94771d2fa0a451e0edb21ac9c7/pyinstaller-6.14.1-py3-none-musllinux_1_1_aarch64.whl", hash = "sha256:5b05cbb2ffc033b4681268159b82bac94b875475c339603c7e605f00a73c8746", size = 724132, upload-time = "2025-06-08T18:44:51.081Z" }, - { url = "https://files.pythonhosted.org/packages/d2/8b/8570ab94ec07e0b2b1203f45840353ee76aa067a2540c97da43d43477b26/pyinstaller-6.14.1-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:d5fd73757c8ea9adb2f9c1f81656335ba9890029ede3031835d768fde36e89f0", size = 723847, upload-time = "2025-06-08T18:44:54.896Z" }, - { url = "https://files.pythonhosted.org/packages/d5/43/6c68dc9e53b09ff948d6e46477932b387832bbb920c48061d734ef089368/pyinstaller-6.14.1-py3-none-win32.whl", hash = "sha256:547f7a93592e408cbfd093ce9fd9631215387dab0dbf3130351d3b0b1186a534", size = 1299744, upload-time = "2025-06-08T18:45:00.781Z" }, - { url = "https://files.pythonhosted.org/packages/7c/dd/bb8d5bcb0592f7f5d454ad308051d00ed34f8b08d5003400b825cfe35513/pyinstaller-6.14.1-py3-none-win_amd64.whl", hash = "sha256:0794290b4b56ef9d35858334deb29f36ec1e1f193b0f825212a0aa5a1bec5a2f", size = 1357625, upload-time = "2025-06-08T18:45:06.826Z" }, - { url = "https://files.pythonhosted.org/packages/89/57/8a8979737980e50aa5031b77318ce783759bf25be2956317f2e1d7a65a09/pyinstaller-6.14.1-py3-none-win_arm64.whl", hash = "sha256:d9d99695827f892cb19644106da30681363e8ff27b8326ac8416d62890ab9c74", size = 1298607, upload-time = "2025-06-08T18:45:12.766Z" }, + { url = "https://files.pythonhosted.org/packages/e3/eb/23374721fecfa72677e79800921cb6aceefa6ba48574dc404f3f6c6c3be7/pyinstaller-6.19.0-py3-none-macosx_10_13_universal2.whl", hash = "sha256:4190e76b74f0c4b5c5f11ac360928cd2e36ec8e3194d437bf6b8648c7bc0c134", size = 1040563, upload-time = "2026-02-14T18:05:22.436Z" }, + { url = "https://files.pythonhosted.org/packages/cd/7e/dfd724b0b533f5aaec0ee5df406fe2319987ed6964480a706f85478b12ea/pyinstaller-6.19.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:8bd68abd812d8a6ba33b9f1810e91fee0f325969733721b78151f0065319ca11", size = 735477, upload-time = "2026-02-14T18:05:27.143Z" }, + { url = "https://files.pythonhosted.org/packages/88/c9/ee3a4101c31f26344e66896c73c1fd6ed8282bf871473365b7f8674af406/pyinstaller-6.19.0-py3-none-manylinux2014_i686.whl", hash = "sha256:1ec54ef967996ca61dacba676227e2b23219878ccce5ee9d6f3aada7b8ed8abf", size = 747143, upload-time = "2026-02-14T18:05:31.488Z" }, + { url = "https://files.pythonhosted.org/packages/da/0a/fc77e9f861be8cf300ac37155f59cc92aff99b29f2ddd78546f563a5b5a6/pyinstaller-6.19.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:4ab2bb52e58448e14ddf9450601bdedd66800465043501c1d8f1cab87b60b122", size = 744849, upload-time = "2026-02-14T18:05:35.492Z" }, + { url = "https://files.pythonhosted.org/packages/6d/e3/6872e020ee758afe0b821663858492c10745608b07150e5e2c824a5b3e1c/pyinstaller-6.19.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:da6d5c6391ccefe73554b9fa29b86001c8e378e0f20c2a4004f836ba537eff63", size = 741590, upload-time = "2026-02-14T18:05:39.59Z" }, + { url = "https://files.pythonhosted.org/packages/53/60/b8db5f1a4b0fb228175f2ea0aa33f949adcc097fbe981cc524f9faf85777/pyinstaller-6.19.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:a0fc5f6b3c55aa54353f0c74ffa59b1115433c1850c6f655d62b461a2ed6cbbe", size = 741448, upload-time = "2026-02-14T18:05:45.636Z" }, + { url = "https://files.pythonhosted.org/packages/6f/4d/63b0600f2694e9141b83129fbc1c488ec84d5a0770b1448ec154dcd0fee9/pyinstaller-6.19.0-py3-none-musllinux_1_1_aarch64.whl", hash = "sha256:e649ba6bd1b0b89b210ad92adb5fbdc8a42dd2c5ca4f72ef3a0bfec83a424b83", size = 740613, upload-time = "2026-02-14T18:05:49.726Z" }, + { url = "https://files.pythonhosted.org/packages/01/d4/e812ad36178093a0e9fd4b8127577748dd85b0cb71de912229dca21fd741/pyinstaller-6.19.0-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:481a909c8e60c8692fc60fcb1344d984b44b943f8bc9682f2fcdae305ad297e6", size = 740350, upload-time = "2026-02-14T18:05:54.093Z" }, + { url = "https://files.pythonhosted.org/packages/52/03/b2c2ee41fb8e10fd2a45d21f5ec2ef25852cfb978dbf762972eed59e3d63/pyinstaller-6.19.0-py3-none-win32.whl", hash = "sha256:3c5c251054fe4cfaa04c34a363dcfbf811545438cb7198304cd444756bc2edd2", size = 1324317, upload-time = "2026-02-14T18:06:00.085Z" }, + { url = "https://files.pythonhosted.org/packages/9c/d3/6d5e62b8270e2b53a6065e281b3a7785079b00e9019c8019952828dd1669/pyinstaller-6.19.0-py3-none-win_amd64.whl", hash = "sha256:b5bb6536c6560330d364d91522250f254b107cf69129d9cbcd0e6727c570be33", size = 1384894, upload-time = "2026-02-14T18:06:06.425Z" }, + { url = "https://files.pythonhosted.org/packages/81/65/458cd523308a101a22fd2742893405030cc24994cc74b1b767cecf137160/pyinstaller-6.19.0-py3-none-win_arm64.whl", hash = "sha256:c2d5a539b0bfe6159d5522c8c70e1c0e487f22c2badae0f97d45246223b798ea", size = 1325374, upload-time = "2026-02-14T18:06:12.804Z" }, ] [[package]] name = "pyinstaller-hooks-contrib" -version = "2025.5" +version = "2026.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "importlib-metadata", marker = "python_full_version < '3.10'" }, { name = "packaging" }, { name = "setuptools" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/5f/ff/e3376595935d5f8135964d2177cd3e3e0c1b5a6237497d9775237c247a5d/pyinstaller_hooks_contrib-2025.5.tar.gz", hash = "sha256:707386770b8fe066c04aad18a71bc483c7b25e18b4750a756999f7da2ab31982", size = 163124, upload-time = "2025-06-08T18:47:53.26Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c7/fe/9278c29394bf69169febc21f96b4252c3ee7c8ec22c2fc545004bed47e71/pyinstaller_hooks_contrib-2026.4.tar.gz", hash = "sha256:766c281acb1ecc32e21c8c667056d7ebf5da0aabd5e30c219f9c2a283620eeaa", size = 173050, upload-time = "2026-03-31T14:10:51.188Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/0c/2c/b4d317534e17dd1df95c394d4b37febb15ead006a1c07c2bb006481fb5e7/pyinstaller_hooks_contrib-2025.5-py3-none-any.whl", hash = "sha256:ebfae1ba341cb0002fb2770fad0edf2b3e913c2728d92df7ad562260988ca373", size = 437246, upload-time = "2025-06-08T18:47:51.516Z" }, + { url = "https://files.pythonhosted.org/packages/88/f4/035fb8c06deff827f540a9a4ed9122c54e5376fca3e42eddf0c263730775/pyinstaller_hooks_contrib-2026.4-py3-none-any.whl", hash = "sha256:1de1a5e49a878122010b88c7e295502bc69776c157c4a4dc78741a4e6178b00f", size = 455496, upload-time = "2026-03-31T14:10:49.867Z" }, ] [[package]] @@ -684,41 +821,43 @@ wheels = [ [[package]] name = "pytest" -version = "8.4.1" +version = "8.4.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, - { name = "iniconfig" }, + { name = "iniconfig", version = "2.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "iniconfig", version = "2.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "packaging" }, { name = "pluggy" }, { name = "pygments" }, { name = "tomli", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/08/ba/45911d754e8eba3d5a841a5ce61a65a685ff1798421ac054f85aa8747dfb/pytest-8.4.1.tar.gz", hash = "sha256:7c67fd69174877359ed9371ec3af8a3d2b04741818c51e5e99cc1742251fa93c", size = 1517714, upload-time = "2025-06-18T05:48:06.109Z" } +sdist = { url = "https://files.pythonhosted.org/packages/a3/5c/00a0e072241553e1a7496d638deababa67c5058571567b92a7eaa258397c/pytest-8.4.2.tar.gz", hash = "sha256:86c0d0b93306b961d58d62a4db4879f27fe25513d4b969df351abdddb3c30e01", size = 1519618, upload-time = "2025-09-04T14:34:22.711Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/29/16/c8a903f4c4dffe7a12843191437d7cd8e32751d5de349d45d3fe69544e87/pytest-8.4.1-py3-none-any.whl", hash = "sha256:539c70ba6fcead8e78eebbf1115e8b589e7565830d7d006a8723f19ac8a0afb7", size = 365474, upload-time = "2025-06-18T05:48:03.955Z" }, + { url = "https://files.pythonhosted.org/packages/a8/a4/20da314d277121d6534b3a980b29035dcd51e6744bd79075a6ce8fa4eb8d/pytest-8.4.2-py3-none-any.whl", hash = "sha256:872f880de3fc3a5bdc88a11b39c9710c3497a547cfa9320bc3c5e62fbf272e79", size = 365750, upload-time = "2025-09-04T14:34:20.226Z" }, ] [[package]] name = "pywin32" -version = "310" +version = "311" source = { registry = "https://pypi.org/simple" } wheels = [ - { url = "https://files.pythonhosted.org/packages/95/da/a5f38fffbba2fb99aa4aa905480ac4b8e83ca486659ac8c95bce47fb5276/pywin32-310-cp310-cp310-win32.whl", hash = "sha256:6dd97011efc8bf51d6793a82292419eba2c71cf8e7250cfac03bba284454abc1", size = 8848240, upload-time = "2025-03-17T00:55:46.783Z" }, - { url = "https://files.pythonhosted.org/packages/aa/fe/d873a773324fa565619ba555a82c9dabd677301720f3660a731a5d07e49a/pywin32-310-cp310-cp310-win_amd64.whl", hash = "sha256:c3e78706e4229b915a0821941a84e7ef420bf2b77e08c9dae3c76fd03fd2ae3d", size = 9601854, upload-time = "2025-03-17T00:55:48.783Z" }, - { url = "https://files.pythonhosted.org/packages/3c/84/1a8e3d7a15490d28a5d816efa229ecb4999cdc51a7c30dd8914f669093b8/pywin32-310-cp310-cp310-win_arm64.whl", hash = "sha256:33babed0cf0c92a6f94cc6cc13546ab24ee13e3e800e61ed87609ab91e4c8213", size = 8522963, upload-time = "2025-03-17T00:55:50.969Z" }, - { url = "https://files.pythonhosted.org/packages/f7/b1/68aa2986129fb1011dabbe95f0136f44509afaf072b12b8f815905a39f33/pywin32-310-cp311-cp311-win32.whl", hash = "sha256:1e765f9564e83011a63321bb9d27ec456a0ed90d3732c4b2e312b855365ed8bd", size = 8784284, upload-time = "2025-03-17T00:55:53.124Z" }, - { url = "https://files.pythonhosted.org/packages/b3/bd/d1592635992dd8db5bb8ace0551bc3a769de1ac8850200cfa517e72739fb/pywin32-310-cp311-cp311-win_amd64.whl", hash = "sha256:126298077a9d7c95c53823934f000599f66ec9296b09167810eb24875f32689c", size = 9520748, upload-time = "2025-03-17T00:55:55.203Z" }, - { url = "https://files.pythonhosted.org/packages/90/b1/ac8b1ffce6603849eb45a91cf126c0fa5431f186c2e768bf56889c46f51c/pywin32-310-cp311-cp311-win_arm64.whl", hash = "sha256:19ec5fc9b1d51c4350be7bb00760ffce46e6c95eaf2f0b2f1150657b1a43c582", size = 8455941, upload-time = "2025-03-17T00:55:57.048Z" }, - { url = "https://files.pythonhosted.org/packages/6b/ec/4fdbe47932f671d6e348474ea35ed94227fb5df56a7c30cbbb42cd396ed0/pywin32-310-cp312-cp312-win32.whl", hash = "sha256:8a75a5cc3893e83a108c05d82198880704c44bbaee4d06e442e471d3c9ea4f3d", size = 8796239, upload-time = "2025-03-17T00:55:58.807Z" }, - { url = "https://files.pythonhosted.org/packages/e3/e5/b0627f8bb84e06991bea89ad8153a9e50ace40b2e1195d68e9dff6b03d0f/pywin32-310-cp312-cp312-win_amd64.whl", hash = "sha256:bf5c397c9a9a19a6f62f3fb821fbf36cac08f03770056711f765ec1503972060", size = 9503839, upload-time = "2025-03-17T00:56:00.8Z" }, - { url = "https://files.pythonhosted.org/packages/1f/32/9ccf53748df72301a89713936645a664ec001abd35ecc8578beda593d37d/pywin32-310-cp312-cp312-win_arm64.whl", hash = "sha256:2349cc906eae872d0663d4d6290d13b90621eaf78964bb1578632ff20e152966", size = 8459470, upload-time = "2025-03-17T00:56:02.601Z" }, - { url = "https://files.pythonhosted.org/packages/1c/09/9c1b978ffc4ae53999e89c19c77ba882d9fce476729f23ef55211ea1c034/pywin32-310-cp313-cp313-win32.whl", hash = "sha256:5d241a659c496ada3253cd01cfaa779b048e90ce4b2b38cd44168ad555ce74ab", size = 8794384, upload-time = "2025-03-17T00:56:04.383Z" }, - { url = "https://files.pythonhosted.org/packages/45/3c/b4640f740ffebadd5d34df35fecba0e1cfef8fde9f3e594df91c28ad9b50/pywin32-310-cp313-cp313-win_amd64.whl", hash = "sha256:667827eb3a90208ddbdcc9e860c81bde63a135710e21e4cb3348968e4bd5249e", size = 9503039, upload-time = "2025-03-17T00:56:06.207Z" }, - { url = "https://files.pythonhosted.org/packages/b4/f4/f785020090fb050e7fb6d34b780f2231f302609dc964672f72bfaeb59a28/pywin32-310-cp313-cp313-win_arm64.whl", hash = "sha256:e308f831de771482b7cf692a1f308f8fca701b2d8f9dde6cc440c7da17e47b33", size = 8458152, upload-time = "2025-03-17T00:56:07.819Z" }, - { url = "https://files.pythonhosted.org/packages/a2/cd/d09d434630edb6a0c44ad5079611279a67530296cfe0451e003de7f449ff/pywin32-310-cp39-cp39-win32.whl", hash = "sha256:851c8d927af0d879221e616ae1f66145253537bbdd321a77e8ef701b443a9a1a", size = 8848099, upload-time = "2025-03-17T00:55:42.415Z" }, - { url = "https://files.pythonhosted.org/packages/93/ff/2a8c10315ffbdee7b3883ac0d1667e267ca8b3f6f640d81d43b87a82c0c7/pywin32-310-cp39-cp39-win_amd64.whl", hash = "sha256:96867217335559ac619f00ad70e513c0fcf84b8a3af9fc2bba3b59b97da70475", size = 9602031, upload-time = "2025-03-17T00:55:44.512Z" }, + { url = "https://files.pythonhosted.org/packages/7b/40/44efbb0dfbd33aca6a6483191dae0716070ed99e2ecb0c53683f400a0b4f/pywin32-311-cp310-cp310-win32.whl", hash = "sha256:d03ff496d2a0cd4a5893504789d4a15399133fe82517455e78bad62efbb7f0a3", size = 8760432, upload-time = "2025-07-14T20:13:05.9Z" }, + { url = "https://files.pythonhosted.org/packages/5e/bf/360243b1e953bd254a82f12653974be395ba880e7ec23e3731d9f73921cc/pywin32-311-cp310-cp310-win_amd64.whl", hash = "sha256:797c2772017851984b97180b0bebe4b620bb86328e8a884bb626156295a63b3b", size = 9590103, upload-time = "2025-07-14T20:13:07.698Z" }, + { url = "https://files.pythonhosted.org/packages/57/38/d290720e6f138086fb3d5ffe0b6caa019a791dd57866940c82e4eeaf2012/pywin32-311-cp310-cp310-win_arm64.whl", hash = "sha256:0502d1facf1fed4839a9a51ccbcc63d952cf318f78ffc00a7e78528ac27d7a2b", size = 8778557, upload-time = "2025-07-14T20:13:11.11Z" }, + { url = "https://files.pythonhosted.org/packages/7c/af/449a6a91e5d6db51420875c54f6aff7c97a86a3b13a0b4f1a5c13b988de3/pywin32-311-cp311-cp311-win32.whl", hash = "sha256:184eb5e436dea364dcd3d2316d577d625c0351bf237c4e9a5fabbcfa5a58b151", size = 8697031, upload-time = "2025-07-14T20:13:13.266Z" }, + { url = "https://files.pythonhosted.org/packages/51/8f/9bb81dd5bb77d22243d33c8397f09377056d5c687aa6d4042bea7fbf8364/pywin32-311-cp311-cp311-win_amd64.whl", hash = "sha256:3ce80b34b22b17ccbd937a6e78e7225d80c52f5ab9940fe0506a1a16f3dab503", size = 9508308, upload-time = "2025-07-14T20:13:15.147Z" }, + { url = "https://files.pythonhosted.org/packages/44/7b/9c2ab54f74a138c491aba1b1cd0795ba61f144c711daea84a88b63dc0f6c/pywin32-311-cp311-cp311-win_arm64.whl", hash = "sha256:a733f1388e1a842abb67ffa8e7aad0e70ac519e09b0f6a784e65a136ec7cefd2", size = 8703930, upload-time = "2025-07-14T20:13:16.945Z" }, + { url = "https://files.pythonhosted.org/packages/e7/ab/01ea1943d4eba0f850c3c61e78e8dd59757ff815ff3ccd0a84de5f541f42/pywin32-311-cp312-cp312-win32.whl", hash = "sha256:750ec6e621af2b948540032557b10a2d43b0cee2ae9758c54154d711cc852d31", size = 8706543, upload-time = "2025-07-14T20:13:20.765Z" }, + { url = "https://files.pythonhosted.org/packages/d1/a8/a0e8d07d4d051ec7502cd58b291ec98dcc0c3fff027caad0470b72cfcc2f/pywin32-311-cp312-cp312-win_amd64.whl", hash = "sha256:b8c095edad5c211ff31c05223658e71bf7116daa0ecf3ad85f3201ea3190d067", size = 9495040, upload-time = "2025-07-14T20:13:22.543Z" }, + { url = "https://files.pythonhosted.org/packages/ba/3a/2ae996277b4b50f17d61f0603efd8253cb2d79cc7ae159468007b586396d/pywin32-311-cp312-cp312-win_arm64.whl", hash = "sha256:e286f46a9a39c4a18b319c28f59b61de793654af2f395c102b4f819e584b5852", size = 8710102, upload-time = "2025-07-14T20:13:24.682Z" }, + { url = "https://files.pythonhosted.org/packages/a5/be/3fd5de0979fcb3994bfee0d65ed8ca9506a8a1260651b86174f6a86f52b3/pywin32-311-cp313-cp313-win32.whl", hash = "sha256:f95ba5a847cba10dd8c4d8fefa9f2a6cf283b8b88ed6178fa8a6c1ab16054d0d", size = 8705700, upload-time = "2025-07-14T20:13:26.471Z" }, + { url = "https://files.pythonhosted.org/packages/e3/28/e0a1909523c6890208295a29e05c2adb2126364e289826c0a8bc7297bd5c/pywin32-311-cp313-cp313-win_amd64.whl", hash = "sha256:718a38f7e5b058e76aee1c56ddd06908116d35147e133427e59a3983f703a20d", size = 9494700, upload-time = "2025-07-14T20:13:28.243Z" }, + { url = "https://files.pythonhosted.org/packages/04/bf/90339ac0f55726dce7d794e6d79a18a91265bdf3aa70b6b9ca52f35e022a/pywin32-311-cp313-cp313-win_arm64.whl", hash = "sha256:7b4075d959648406202d92a2310cb990fea19b535c7f4a78d3f5e10b926eeb8a", size = 8709318, upload-time = "2025-07-14T20:13:30.348Z" }, + { url = "https://files.pythonhosted.org/packages/59/42/b86689aac0cdaee7ae1c58d464b0ff04ca909c19bb6502d4973cdd9f9544/pywin32-311-cp39-cp39-win32.whl", hash = "sha256:aba8f82d551a942cb20d4a83413ccbac30790b50efb89a75e4f586ac0bb8056b", size = 8760837, upload-time = "2025-07-14T20:12:59.59Z" }, + { url = "https://files.pythonhosted.org/packages/9f/8a/1403d0353f8c5a2f0829d2b1c4becbf9da2f0a4d040886404fc4a5431e4d/pywin32-311-cp39-cp39-win_amd64.whl", hash = "sha256:e0c4cfb0621281fe40387df582097fd796e80430597cb9944f0ae70447bacd91", size = 9590187, upload-time = "2025-07-14T20:13:01.419Z" }, + { url = "https://files.pythonhosted.org/packages/60/22/e0e8d802f124772cec9c75430b01a212f86f9de7546bda715e54140d5aeb/pywin32-311-cp39-cp39-win_arm64.whl", hash = "sha256:62ea666235135fee79bb154e695f3ff67370afefd71bd7fea7512fc70ef31e3d", size = 8778162, upload-time = "2025-07-14T20:13:03.544Z" }, ] [[package]] @@ -732,17 +871,38 @@ wheels = [ [[package]] name = "requests" -version = "2.32.4" +version = "2.32.5" source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "certifi" }, - { name = "charset-normalizer" }, - { name = "idna" }, - { name = "urllib3" }, +resolution-markers = [ + "python_full_version < '3.10'", ] -sdist = { url = "https://files.pythonhosted.org/packages/e1/0a/929373653770d8a0d7ea76c37de6e41f11eb07559b103b1c02cafb3f7cf8/requests-2.32.4.tar.gz", hash = "sha256:27d0316682c8a29834d3264820024b62a36942083d52caf2f14c0591336d3422", size = 135258, upload-time = "2025-06-09T16:43:07.34Z" } +dependencies = [ + { name = "certifi", marker = "python_full_version < '3.10'" }, + { name = "charset-normalizer", marker = "python_full_version < '3.10'" }, + { name = "idna", marker = "python_full_version < '3.10'" }, + { name = "urllib3", version = "2.6.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c9/74/b3ff8e6c8446842c3f5c837e9c3dfcfe2018ea6ecef224c710c85ef728f4/requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf", size = 134517, upload-time = "2025-08-18T20:46:02.573Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/7c/e4/56027c4a6b4ae70ca9de302488c5ca95ad4a39e190093d6c1a8ace08341b/requests-2.32.4-py3-none-any.whl", hash = "sha256:27babd3cda2a6d50b30443204ee89830707d396671944c998b5975b031ac2b2c", size = 64847, upload-time = "2025-06-09T16:43:05.728Z" }, + { url = "https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6", size = 64738, upload-time = "2025-08-18T20:46:00.542Z" }, +] + +[[package]] +name = "requests" +version = "2.33.1" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.10'", +] +dependencies = [ + { name = "certifi", marker = "python_full_version >= '3.10'" }, + { name = "charset-normalizer", marker = "python_full_version >= '3.10'" }, + { name = "idna", marker = "python_full_version >= '3.10'" }, + { name = "urllib3", version = "2.7.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5f/a4/98b9c7c6428a668bf7e42ebb7c79d576a1c3c1e3ae2d47e674b468388871/requests-2.33.1.tar.gz", hash = "sha256:18817f8c57c6263968bc123d237e3b8b08ac046f5456bd1e307ee8f4250d3517", size = 134120, upload-time = "2026-03-30T16:09:15.531Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d7/8e/7540e8a2036f79a125c1d2ebadf69ed7901608859186c856fa0388ef4197/requests-2.33.1-py3-none-any.whl", hash = "sha256:4e6d1ef462f3626a1f0a0a9c42dd93c63bad33f9f1c1937509b8c5c8718ab56a", size = 64947, upload-time = "2026-03-30T16:09:13.83Z" }, ] [[package]] @@ -756,75 +916,96 @@ wheels = [ [[package]] name = "setuptools" -version = "80.9.0" +version = "82.0.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/18/5d/3bf57dcd21979b887f014ea83c24ae194cfcd12b9e0fda66b957c69d1fca/setuptools-80.9.0.tar.gz", hash = "sha256:f36b47402ecde768dbfafc46e8e4207b4360c654f1f3bb84475f0a28628fb19c", size = 1319958, upload-time = "2025-05-27T00:56:51.443Z" } +sdist = { url = "https://files.pythonhosted.org/packages/4f/db/cfac1baf10650ab4d1c111714410d2fbb77ac5a616db26775db562c8fab2/setuptools-82.0.1.tar.gz", hash = "sha256:7d872682c5d01cfde07da7bccc7b65469d3dca203318515ada1de5eda35efbf9", size = 1152316, upload-time = "2026-03-09T12:47:17.221Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a3/dc/17031897dae0efacfea57dfd3a82fdd2a2aeb58e0ff71b77b87e44edc772/setuptools-80.9.0-py3-none-any.whl", hash = "sha256:062d34222ad13e0cc312a4c02d73f059e86a4acbfbdea8f8f76b28c99f306922", size = 1201486, upload-time = "2025-05-27T00:56:49.664Z" }, + { url = "https://files.pythonhosted.org/packages/9d/76/f789f7a86709c6b087c5a2f52f911838cad707cc613162401badc665acfe/setuptools-82.0.1-py3-none-any.whl", hash = "sha256:a59e362652f08dcd477c78bb6e7bd9d80a7995bc73ce773050228a348ce2e5bb", size = 1006223, upload-time = "2026-03-09T12:47:15.026Z" }, ] [[package]] name = "tomli" -version = "2.2.1" +version = "2.4.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/18/87/302344fed471e44a87289cf4967697d07e532f2421fdaf868a303cbae4ff/tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff", size = 17175, upload-time = "2024-11-27T22:38:36.873Z" } +sdist = { url = "https://files.pythonhosted.org/packages/22/de/48c59722572767841493b26183a0d1cc411d54fd759c5607c4590b6563a6/tomli-2.4.1.tar.gz", hash = "sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f", size = 17543, upload-time = "2026-03-25T20:22:03.828Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/43/ca/75707e6efa2b37c77dadb324ae7d9571cb424e61ea73fad7c56c2d14527f/tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249", size = 131077, upload-time = "2024-11-27T22:37:54.956Z" }, - { url = "https://files.pythonhosted.org/packages/c7/16/51ae563a8615d472fdbffc43a3f3d46588c264ac4f024f63f01283becfbb/tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6", size = 123429, upload-time = "2024-11-27T22:37:56.698Z" }, - { url = "https://files.pythonhosted.org/packages/f1/dd/4f6cd1e7b160041db83c694abc78e100473c15d54620083dbd5aae7b990e/tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a", size = 226067, upload-time = "2024-11-27T22:37:57.63Z" }, - { url = "https://files.pythonhosted.org/packages/a9/6b/c54ede5dc70d648cc6361eaf429304b02f2871a345bbdd51e993d6cdf550/tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee", size = 236030, upload-time = "2024-11-27T22:37:59.344Z" }, - { url = "https://files.pythonhosted.org/packages/1f/47/999514fa49cfaf7a92c805a86c3c43f4215621855d151b61c602abb38091/tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e", size = 240898, upload-time = "2024-11-27T22:38:00.429Z" }, - { url = "https://files.pythonhosted.org/packages/73/41/0a01279a7ae09ee1573b423318e7934674ce06eb33f50936655071d81a24/tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4", size = 229894, upload-time = "2024-11-27T22:38:02.094Z" }, - { url = "https://files.pythonhosted.org/packages/55/18/5d8bc5b0a0362311ce4d18830a5d28943667599a60d20118074ea1b01bb7/tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106", size = 245319, upload-time = "2024-11-27T22:38:03.206Z" }, - { url = "https://files.pythonhosted.org/packages/92/a3/7ade0576d17f3cdf5ff44d61390d4b3febb8a9fc2b480c75c47ea048c646/tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8", size = 238273, upload-time = "2024-11-27T22:38:04.217Z" }, - { url = "https://files.pythonhosted.org/packages/72/6f/fa64ef058ac1446a1e51110c375339b3ec6be245af9d14c87c4a6412dd32/tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff", size = 98310, upload-time = "2024-11-27T22:38:05.908Z" }, - { url = "https://files.pythonhosted.org/packages/6a/1c/4a2dcde4a51b81be3530565e92eda625d94dafb46dbeb15069df4caffc34/tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b", size = 108309, upload-time = "2024-11-27T22:38:06.812Z" }, - { url = "https://files.pythonhosted.org/packages/52/e1/f8af4c2fcde17500422858155aeb0d7e93477a0d59a98e56cbfe75070fd0/tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea", size = 132762, upload-time = "2024-11-27T22:38:07.731Z" }, - { url = "https://files.pythonhosted.org/packages/03/b8/152c68bb84fc00396b83e7bbddd5ec0bd3dd409db4195e2a9b3e398ad2e3/tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8", size = 123453, upload-time = "2024-11-27T22:38:09.384Z" }, - { url = "https://files.pythonhosted.org/packages/c8/d6/fc9267af9166f79ac528ff7e8c55c8181ded34eb4b0e93daa767b8841573/tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192", size = 233486, upload-time = "2024-11-27T22:38:10.329Z" }, - { url = "https://files.pythonhosted.org/packages/5c/51/51c3f2884d7bab89af25f678447ea7d297b53b5a3b5730a7cb2ef6069f07/tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222", size = 242349, upload-time = "2024-11-27T22:38:11.443Z" }, - { url = "https://files.pythonhosted.org/packages/ab/df/bfa89627d13a5cc22402e441e8a931ef2108403db390ff3345c05253935e/tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77", size = 252159, upload-time = "2024-11-27T22:38:13.099Z" }, - { url = "https://files.pythonhosted.org/packages/9e/6e/fa2b916dced65763a5168c6ccb91066f7639bdc88b48adda990db10c8c0b/tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6", size = 237243, upload-time = "2024-11-27T22:38:14.766Z" }, - { url = "https://files.pythonhosted.org/packages/b4/04/885d3b1f650e1153cbb93a6a9782c58a972b94ea4483ae4ac5cedd5e4a09/tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd", size = 259645, upload-time = "2024-11-27T22:38:15.843Z" }, - { url = "https://files.pythonhosted.org/packages/9c/de/6b432d66e986e501586da298e28ebeefd3edc2c780f3ad73d22566034239/tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e", size = 244584, upload-time = "2024-11-27T22:38:17.645Z" }, - { url = "https://files.pythonhosted.org/packages/1c/9a/47c0449b98e6e7d1be6cbac02f93dd79003234ddc4aaab6ba07a9a7482e2/tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98", size = 98875, upload-time = "2024-11-27T22:38:19.159Z" }, - { url = "https://files.pythonhosted.org/packages/ef/60/9b9638f081c6f1261e2688bd487625cd1e660d0a85bd469e91d8db969734/tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4", size = 109418, upload-time = "2024-11-27T22:38:20.064Z" }, - { url = "https://files.pythonhosted.org/packages/04/90/2ee5f2e0362cb8a0b6499dc44f4d7d48f8fff06d28ba46e6f1eaa61a1388/tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7", size = 132708, upload-time = "2024-11-27T22:38:21.659Z" }, - { url = "https://files.pythonhosted.org/packages/c0/ec/46b4108816de6b385141f082ba99e315501ccd0a2ea23db4a100dd3990ea/tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c", size = 123582, upload-time = "2024-11-27T22:38:22.693Z" }, - { url = "https://files.pythonhosted.org/packages/a0/bd/b470466d0137b37b68d24556c38a0cc819e8febe392d5b199dcd7f578365/tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13", size = 232543, upload-time = "2024-11-27T22:38:24.367Z" }, - { url = "https://files.pythonhosted.org/packages/d9/e5/82e80ff3b751373f7cead2815bcbe2d51c895b3c990686741a8e56ec42ab/tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281", size = 241691, upload-time = "2024-11-27T22:38:26.081Z" }, - { url = "https://files.pythonhosted.org/packages/05/7e/2a110bc2713557d6a1bfb06af23dd01e7dde52b6ee7dadc589868f9abfac/tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272", size = 251170, upload-time = "2024-11-27T22:38:27.921Z" }, - { url = "https://files.pythonhosted.org/packages/64/7b/22d713946efe00e0adbcdfd6d1aa119ae03fd0b60ebed51ebb3fa9f5a2e5/tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140", size = 236530, upload-time = "2024-11-27T22:38:29.591Z" }, - { url = "https://files.pythonhosted.org/packages/38/31/3a76f67da4b0cf37b742ca76beaf819dca0ebef26d78fc794a576e08accf/tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2", size = 258666, upload-time = "2024-11-27T22:38:30.639Z" }, - { url = "https://files.pythonhosted.org/packages/07/10/5af1293da642aded87e8a988753945d0cf7e00a9452d3911dd3bb354c9e2/tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744", size = 243954, upload-time = "2024-11-27T22:38:31.702Z" }, - { url = "https://files.pythonhosted.org/packages/5b/b9/1ed31d167be802da0fc95020d04cd27b7d7065cc6fbefdd2f9186f60d7bd/tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec", size = 98724, upload-time = "2024-11-27T22:38:32.837Z" }, - { url = "https://files.pythonhosted.org/packages/c7/32/b0963458706accd9afcfeb867c0f9175a741bf7b19cd424230714d722198/tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69", size = 109383, upload-time = "2024-11-27T22:38:34.455Z" }, - { url = "https://files.pythonhosted.org/packages/6e/c2/61d3e0f47e2b74ef40a68b9e6ad5984f6241a942f7cd3bbfbdbd03861ea9/tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc", size = 14257, upload-time = "2024-11-27T22:38:35.385Z" }, + { url = "https://files.pythonhosted.org/packages/f4/11/db3d5885d8528263d8adc260bb2d28ebf1270b96e98f0e0268d32b8d9900/tomli-2.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f8f0fc26ec2cc2b965b7a3b87cd19c5c6b8c5e5f436b984e85f486d652285c30", size = 154704, upload-time = "2026-03-25T20:21:10.473Z" }, + { url = "https://files.pythonhosted.org/packages/6d/f7/675db52c7e46064a9aa928885a9b20f4124ecb9bc2e1ce74c9106648d202/tomli-2.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4ab97e64ccda8756376892c53a72bd1f964e519c77236368527f758fbc36a53a", size = 149454, upload-time = "2026-03-25T20:21:12.036Z" }, + { url = "https://files.pythonhosted.org/packages/61/71/81c50943cf953efa35bce7646caab3cf457a7d8c030b27cfb40d7235f9ee/tomli-2.4.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:96481a5786729fd470164b47cdb3e0e58062a496f455ee41b4403be77cb5a076", size = 237561, upload-time = "2026-03-25T20:21:13.098Z" }, + { url = "https://files.pythonhosted.org/packages/48/c1/f41d9cb618acccca7df82aaf682f9b49013c9397212cb9f53219e3abac37/tomli-2.4.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a881ab208c0baf688221f8cecc5401bd291d67e38a1ac884d6736cbcd8247e9", size = 243824, upload-time = "2026-03-25T20:21:14.569Z" }, + { url = "https://files.pythonhosted.org/packages/22/e4/5a816ecdd1f8ca51fb756ef684b90f2780afc52fc67f987e3c61d800a46d/tomli-2.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:47149d5bd38761ac8be13a84864bf0b7b70bc051806bc3669ab1cbc56216b23c", size = 242227, upload-time = "2026-03-25T20:21:15.712Z" }, + { url = "https://files.pythonhosted.org/packages/6b/49/2b2a0ef529aa6eec245d25f0c703e020a73955ad7edf73e7f54ddc608aa5/tomli-2.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ec9bfaf3ad2df51ace80688143a6a4ebc09a248f6ff781a9945e51937008fcbc", size = 247859, upload-time = "2026-03-25T20:21:17.001Z" }, + { url = "https://files.pythonhosted.org/packages/83/bd/6c1a630eaca337e1e78c5903104f831bda934c426f9231429396ce3c3467/tomli-2.4.1-cp311-cp311-win32.whl", hash = "sha256:ff2983983d34813c1aeb0fa89091e76c3a22889ee83ab27c5eeb45100560c049", size = 97204, upload-time = "2026-03-25T20:21:18.079Z" }, + { url = "https://files.pythonhosted.org/packages/42/59/71461df1a885647e10b6bb7802d0b8e66480c61f3f43079e0dcd315b3954/tomli-2.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:5ee18d9ebdb417e384b58fe414e8d6af9f4e7a0ae761519fb50f721de398dd4e", size = 108084, upload-time = "2026-03-25T20:21:18.978Z" }, + { url = "https://files.pythonhosted.org/packages/b8/83/dceca96142499c069475b790e7913b1044c1a4337e700751f48ed723f883/tomli-2.4.1-cp311-cp311-win_arm64.whl", hash = "sha256:c2541745709bad0264b7d4705ad453b76ccd191e64aa6f0fc66b69a293a45ece", size = 95285, upload-time = "2026-03-25T20:21:20.309Z" }, + { url = "https://files.pythonhosted.org/packages/c1/ba/42f134a3fe2b370f555f44b1d72feebb94debcab01676bf918d0cb70e9aa/tomli-2.4.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c742f741d58a28940ce01d58f0ab2ea3ced8b12402f162f4d534dfe18ba1cd6a", size = 155924, upload-time = "2026-03-25T20:21:21.626Z" }, + { url = "https://files.pythonhosted.org/packages/dc/c7/62d7a17c26487ade21c5422b646110f2162f1fcc95980ef7f63e73c68f14/tomli-2.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7f86fd587c4ed9dd76f318225e7d9b29cfc5a9d43de44e5754db8d1128487085", size = 150018, upload-time = "2026-03-25T20:21:23.002Z" }, + { url = "https://files.pythonhosted.org/packages/5c/05/79d13d7c15f13bdef410bdd49a6485b1c37d28968314eabee452c22a7fda/tomli-2.4.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ff18e6a727ee0ab0388507b89d1bc6a22b138d1e2fa56d1ad494586d61d2eae9", size = 244948, upload-time = "2026-03-25T20:21:24.04Z" }, + { url = "https://files.pythonhosted.org/packages/10/90/d62ce007a1c80d0b2c93e02cab211224756240884751b94ca72df8a875ca/tomli-2.4.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:136443dbd7e1dee43c68ac2694fde36b2849865fa258d39bf822c10e8068eac5", size = 253341, upload-time = "2026-03-25T20:21:25.177Z" }, + { url = "https://files.pythonhosted.org/packages/1a/7e/caf6496d60152ad4ed09282c1885cca4eea150bfd007da84aea07bcc0a3e/tomli-2.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5e262d41726bc187e69af7825504c933b6794dc3fbd5945e41a79bb14c31f585", size = 248159, upload-time = "2026-03-25T20:21:26.364Z" }, + { url = "https://files.pythonhosted.org/packages/99/e7/c6f69c3120de34bbd882c6fba7975f3d7a746e9218e56ab46a1bc4b42552/tomli-2.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5cb41aa38891e073ee49d55fbc7839cfdb2bc0e600add13874d048c94aadddd1", size = 253290, upload-time = "2026-03-25T20:21:27.46Z" }, + { url = "https://files.pythonhosted.org/packages/d6/2f/4a3c322f22c5c66c4b836ec58211641a4067364f5dcdd7b974b4c5da300c/tomli-2.4.1-cp312-cp312-win32.whl", hash = "sha256:da25dc3563bff5965356133435b757a795a17b17d01dbc0f42fb32447ddfd917", size = 98141, upload-time = "2026-03-25T20:21:28.492Z" }, + { url = "https://files.pythonhosted.org/packages/24/22/4daacd05391b92c55759d55eaee21e1dfaea86ce5c571f10083360adf534/tomli-2.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:52c8ef851d9a240f11a88c003eacb03c31fc1c9c4ec64a99a0f922b93874fda9", size = 108847, upload-time = "2026-03-25T20:21:29.386Z" }, + { url = "https://files.pythonhosted.org/packages/68/fd/70e768887666ddd9e9f5d85129e84910f2db2796f9096aa02b721a53098d/tomli-2.4.1-cp312-cp312-win_arm64.whl", hash = "sha256:f758f1b9299d059cc3f6546ae2af89670cb1c4d48ea29c3cacc4fe7de3058257", size = 95088, upload-time = "2026-03-25T20:21:30.677Z" }, + { url = "https://files.pythonhosted.org/packages/07/06/b823a7e818c756d9a7123ba2cda7d07bc2dd32835648d1a7b7b7a05d848d/tomli-2.4.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:36d2bd2ad5fb9eaddba5226aa02c8ec3fa4f192631e347b3ed28186d43be6b54", size = 155866, upload-time = "2026-03-25T20:21:31.65Z" }, + { url = "https://files.pythonhosted.org/packages/14/6f/12645cf7f08e1a20c7eb8c297c6f11d31c1b50f316a7e7e1e1de6e2e7b7e/tomli-2.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:eb0dc4e38e6a1fd579e5d50369aa2e10acfc9cace504579b2faabb478e76941a", size = 149887, upload-time = "2026-03-25T20:21:33.028Z" }, + { url = "https://files.pythonhosted.org/packages/5c/e0/90637574e5e7212c09099c67ad349b04ec4d6020324539297b634a0192b0/tomli-2.4.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c7f2c7f2b9ca6bdeef8f0fa897f8e05085923eb091721675170254cbc5b02897", size = 243704, upload-time = "2026-03-25T20:21:34.51Z" }, + { url = "https://files.pythonhosted.org/packages/10/8f/d3ddb16c5a4befdf31a23307f72828686ab2096f068eaf56631e136c1fdd/tomli-2.4.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f3c6818a1a86dd6dca7ddcaaf76947d5ba31aecc28cb1b67009a5877c9a64f3f", size = 251628, upload-time = "2026-03-25T20:21:36.012Z" }, + { url = "https://files.pythonhosted.org/packages/e3/f1/dbeeb9116715abee2485bf0a12d07a8f31af94d71608c171c45f64c0469d/tomli-2.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d312ef37c91508b0ab2cee7da26ec0b3ed2f03ce12bd87a588d771ae15dcf82d", size = 247180, upload-time = "2026-03-25T20:21:37.136Z" }, + { url = "https://files.pythonhosted.org/packages/d3/74/16336ffd19ed4da28a70959f92f506233bd7cfc2332b20bdb01591e8b1d1/tomli-2.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:51529d40e3ca50046d7606fa99ce3956a617f9b36380da3b7f0dd3dd28e68cb5", size = 251674, upload-time = "2026-03-25T20:21:38.298Z" }, + { url = "https://files.pythonhosted.org/packages/16/f9/229fa3434c590ddf6c0aa9af64d3af4b752540686cace29e6281e3458469/tomli-2.4.1-cp313-cp313-win32.whl", hash = "sha256:2190f2e9dd7508d2a90ded5ed369255980a1bcdd58e52f7fe24b8162bf9fedbd", size = 97976, upload-time = "2026-03-25T20:21:39.316Z" }, + { url = "https://files.pythonhosted.org/packages/6a/1e/71dfd96bcc1c775420cb8befe7a9d35f2e5b1309798f009dca17b7708c1e/tomli-2.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:8d65a2fbf9d2f8352685bc1364177ee3923d6baf5e7f43ea4959d7d8bc326a36", size = 108755, upload-time = "2026-03-25T20:21:40.248Z" }, + { url = "https://files.pythonhosted.org/packages/83/7a/d34f422a021d62420b78f5c538e5b102f62bea616d1d75a13f0a88acb04a/tomli-2.4.1-cp313-cp313-win_arm64.whl", hash = "sha256:4b605484e43cdc43f0954ddae319fb75f04cc10dd80d830540060ee7cd0243cd", size = 95265, upload-time = "2026-03-25T20:21:41.219Z" }, + { url = "https://files.pythonhosted.org/packages/7b/61/cceae43728b7de99d9b847560c262873a1f6c98202171fd5ed62640b494b/tomli-2.4.1-py3-none-any.whl", hash = "sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe", size = 14583, upload-time = "2026-03-25T20:22:03.012Z" }, ] [[package]] name = "typing-extensions" -version = "4.14.0" +version = "4.15.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d1/bc/51647cd02527e87d05cb083ccc402f93e441606ff1f01739a62c8ad09ba5/typing_extensions-4.14.0.tar.gz", hash = "sha256:8676b788e32f02ab42d9e7c61324048ae4c6d844a399eebace3d4979d75ceef4", size = 107423, upload-time = "2025-06-02T14:52:11.399Z" } +sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/69/e0/552843e0d356fbb5256d21449fa957fa4eff3bbc135a74a691ee70c7c5da/typing_extensions-4.14.0-py3-none-any.whl", hash = "sha256:a1514509136dd0b477638fc68d6a91497af5076466ad0fa6c338e44e359944af", size = 43839, upload-time = "2025-06-02T14:52:10.026Z" }, + { url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" }, ] [[package]] name = "urllib3" -version = "2.5.0" +version = "2.6.3" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/15/22/9ee70a2574a4f4599c47dd506532914ce044817c7752a79b6a51286319bc/urllib3-2.5.0.tar.gz", hash = "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760", size = 393185, upload-time = "2025-06-18T14:07:41.644Z" } +resolution-markers = [ + "python_full_version < '3.10'", +] +sdist = { url = "https://files.pythonhosted.org/packages/c7/24/5f1b3bdffd70275f6661c76461e25f024d5a38a46f04aaca912426a2b1d3/urllib3-2.6.3.tar.gz", hash = "sha256:1b62b6884944a57dbe321509ab94fd4d3b307075e0c2eae991ac71ee15ad38ed", size = 435556, upload-time = "2026-01-07T16:24:43.925Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a7/c2/fe1e52489ae3122415c51f387e221dd0773709bad6c6cdaa599e8a2c5185/urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc", size = 129795, upload-time = "2025-06-18T14:07:40.39Z" }, + { url = "https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl", hash = "sha256:bf272323e553dfb2e87d9bfd225ca7b0f467b919d7bbd355436d3fd37cb0acd4", size = 131584, upload-time = "2026-01-07T16:24:42.685Z" }, +] + +[[package]] +name = "urllib3" +version = "2.7.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.10'", +] +sdist = { url = "https://files.pythonhosted.org/packages/53/0c/06f8b233b8fd13b9e5ee11424ef85419ba0d8ba0b3138bf360be2ff56953/urllib3-2.7.0.tar.gz", hash = "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c", size = 433602, upload-time = "2026-05-07T16:13:18.596Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7f/3e/5db95bcf282c52709639744ca2a8b149baccf648e39c8cc87553df9eae0c/urllib3-2.7.0-py3-none-any.whl", hash = "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897", size = 131087, upload-time = "2026-05-07T16:13:17.151Z" }, +] + +[[package]] +name = "websocket-client" +version = "1.9.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/2c/41/aa4bf9664e4cda14c3b39865b12251e8e7d239f4cd0e3cc1b6c2ccde25c1/websocket_client-1.9.0.tar.gz", hash = "sha256:9e813624b6eb619999a97dc7958469217c3176312b3a16a4bd1bc7e08a46ec98", size = 70576, upload-time = "2025-10-07T21:16:36.495Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/34/db/b10e48aa8fff7407e67470363eac595018441cf32d5e1001567a7aeba5d2/websocket_client-1.9.0-py3-none-any.whl", hash = "sha256:af248a825037ef591efbf6ed20cc5faa03d3b47b9e5a2230a529eeee1c1fc3ef", size = 82616, upload-time = "2025-10-07T21:16:34.951Z" }, ] [[package]] name = "zipp" -version = "3.23.0" +version = "3.23.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e3/02/0f2892c661036d50ede074e376733dca2ae7c6eb617489437771209d4180/zipp-3.23.0.tar.gz", hash = "sha256:a07157588a12518c9d4034df3fbbee09c814741a33ff63c05fa29d26a2404166", size = 25547, upload-time = "2025-06-08T17:06:39.4Z" } +sdist = { url = "https://files.pythonhosted.org/packages/30/21/093488dfc7cc8964ded15ab726fad40f25fd3d788fd741cc1c5a17d78ee8/zipp-3.23.1.tar.gz", hash = "sha256:32120e378d32cd9714ad503c1d024619063ec28aad2248dc6672ad13edfa5110", size = 25965, upload-time = "2026-04-13T23:21:46.6Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/2e/54/647ade08bf0db230bfea292f893923872fd20be6ac6f53b2b936ba839d75/zipp-3.23.0-py3-none-any.whl", hash = "sha256:071652d6115ed432f5ce1d34c336c0adfd6a884660d1e9712a256d3d3bd4b14e", size = 10276, upload-time = "2025-06-08T17:06:38.034Z" }, + { url = "https://files.pythonhosted.org/packages/08/8a/0861bec20485572fbddf3dfba2910e38fe249796cb73ecdeb74e07eeb8d3/zipp-3.23.1-py3-none-any.whl", hash = "sha256:0b3596c50a5c700c9cb40ba8d86d9f2cc4807e9bedb06bcdf7fac85633e444dc", size = 10378, upload-time = "2026-04-13T23:21:45.386Z" }, ]