commit f60da6fa6f6f6876505c8ca2be5f648b46d3057d Author: fn-registry agent Date: Tue Apr 28 22:13:07 2026 +0200 chore: initial sync diff --git a/.claude/CLAUDE.md b/.claude/CLAUDE.md new file mode 100644 index 0000000..36a65c7 --- /dev/null +++ b/.claude/CLAUDE.md @@ -0,0 +1,40 @@ +# JUPYTER HABILITADO EN ESTE ANALISIS + +## Reglas OBLIGATORIAS para Claude + +### 1. CODIGO INMUTABLE — NUNCA MODIFICAR CELDAS EXISTENTES +- **PROHIBIDO** usar NotebookEdit para reemplazar celdas existentes +- **SIEMPRE** anadir celdas NUEVAS al final del notebook +- Si hay un error en una celda, crear celda nueva con la correccion +- El historial de trabajo debe quedar intacto para trazabilidad + +### 2. PROGRAMACION FUNCIONAL OBLIGATORIA +- **Funciones puras**: sin efectos secundarios, mismo input -> mismo output +- **Inmutabilidad**: nunca mutar datos, crear copias transformadas +- **Composicion**: funciones pequenas que se combinan +- Preferir: `map`, `filter`, `reduce`, list comprehensions +- Evitar: loops con mutacion, `global`, modificar argumentos in-place + +### 3. SIEMPRE usar MCP jupyter para ejecutar codigo Python +- Las ejecuciones se ven en tiempo real en Jupyter Lab del usuario +- Compartimos variables y estado del kernel +- **NUNCA usar bash para ejecutar Python en este analisis** + +### 4. Verificar Jupyter activo ANTES de ejecutar +- Si no esta activo: pedir al usuario que ejecute `./run-jupyter-lab.sh` + +### 5. Gestion de notebooks +- Notebooks en la carpeta `notebooks/` o subcarpetas +- Si un notebook tiene >50 celdas, crear uno nuevo +- Nombrar descriptivamente: `01_exploracion.ipynb`, `02_limpieza.ipynb` + +### 6. Gestion de Python +- **SIEMPRE usar `uv`** para gestionar dependencias +- Anadir paquetes con `uv add nombre_paquete` + +### 7. Acceso al fn_registry +- `FN_REGISTRY_ROOT` apunta a la raiz del registry +- Para importar funciones Python: `sys.path.insert(0, os.path.join(os.environ["FN_REGISTRY_ROOT"], "python", "functions"))` +- Para consultar registry.db: `sqlite3` o `import sqlite3` con la ruta `$FN_REGISTRY_ROOT/registry.db` + + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6c9a63d --- /dev/null +++ b/.gitignore @@ -0,0 +1,12 @@ +.venv/ +.mcp.json +.jupyter-port +.jupyter/ +.jupyter_ystore.db +.ipython/ +__pycache__/ +*.pyc +.ipynb_checkpoints/ +bin/ +data/ +.DS_Store diff --git a/.python-version b/.python-version new file mode 100644 index 0000000..24ee5b1 --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.13 diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/challenges.py b/challenges.py new file mode 100644 index 0000000..824a3a0 --- /dev/null +++ b/challenges.py @@ -0,0 +1,892 @@ +""" +challenges.py — Challenges de programación de nivel production. + +Inspirados en funciones reales del fn_registry. Prueban: +- Programación funcional (pipe, compose, curry, combinators) +- Procesamiento de datos (coercion, parsing, normalization) +- Algoritmos no triviales (árboles, grafos, scheduling) +- Patterns del mundo real (retry, rate limiting, schema validation) +""" + +from eval_runner import Challenge + +# ══════════════════════════════════════════════════════════════ +# FUNCTIONAL PROGRAMMING +# ══════════════════════════════════════════════════════════════ + +FUNCTIONAL = [ + Challenge( + id="fn_pipe", + name="Pipe with error propagation", + category="functional", + difficulty="medium", + prompt="""Write a Python function: + +def pipe_safe(value, *fns): + \"\"\"Pipe a value through functions left-to-right. If any function raises, + return a tuple (None, error_string). On success return (result, None).\"\"\" + +Example: + pipe_safe(5, lambda x: x*2, lambda x: x+1) == (11, None) + pipe_safe(0, lambda x: 10/x) == (None, "division by zero") # or similar +""", + test_code=""" +# Success cases +assert pipe_safe(5, lambda x: x*2, lambda x: x+1) == (11, None) +assert pipe_safe("hello", str.upper, lambda s: s + "!") == ("HELLO!", None) +assert pipe_safe(42) == (42, None) # no functions +assert pipe_safe([3,1,2], sorted, lambda x: x[0]) == (1, None) + +# Error propagation +result, err = pipe_safe(0, lambda x: 10/x) +assert result is None +assert err is not None and "division" in err.lower() + +result, err = pipe_safe("abc", lambda x: x*2, int) +assert result is None +assert err is not None + +print("PASS: pipe_safe") +""", + ), + + Challenge( + id="fn_group_by_multi", + name="Group by with transform", + category="functional", + difficulty="medium", + prompt="""Write a Python function: + +def group_by_transform(xs: list, key_fn, value_fn=None) -> dict: + \"\"\"Group elements by key_fn. Optionally transform values with value_fn. + If value_fn is None, store raw elements. Preserves insertion order within groups.\"\"\" + +Example: + group_by_transform(["hello", "hi", "bye"], lambda s: s[0]) + # => {"h": ["hello", "hi"], "b": ["bye"]} + + group_by_transform(["hello", "hi", "bye"], lambda s: s[0], str.upper) + # => {"h": ["HELLO", "HI"], "b": ["BYE"]} +""", + test_code=""" +# Basic grouping +r = group_by_transform(["hello", "hi", "bye"], lambda s: s[0]) +assert r == {"h": ["hello", "hi"], "b": ["bye"]} + +# With value transform +r = group_by_transform(["hello", "hi", "bye"], lambda s: s[0], str.upper) +assert r == {"h": ["HELLO", "HI"], "b": ["BYE"]} + +# Numbers +r = group_by_transform([1,2,3,4,5,6], lambda x: x % 2, lambda x: x**2) +assert r == {1: [1, 9, 25], 0: [4, 16, 36]} + +# Empty +assert group_by_transform([], lambda x: x) == {} + +# Single element +assert group_by_transform([42], lambda x: "k") == {"k": [42]} + +print("PASS: group_by_transform") +""", + ), + + Challenge( + id="fn_memoize", + name="Memoize decorator with max size", + category="functional", + difficulty="hard", + prompt="""Write a Python function: + +def memoize(max_size: int = 128): + \"\"\"Decorator that memoizes function results. When cache exceeds max_size, + evict the oldest entry (FIFO). The key is (args, tuple(sorted(kwargs.items()))). + Must work with both positional and keyword arguments.\"\"\" + +Usage: + @memoize(max_size=3) + def add(a, b): + return a + b +""", + test_code=""" +call_count = 0 + +@memoize(max_size=3) +def expensive(x, y=0): + global call_count + call_count += 1 + return x + y + +# First call — computes +call_count = 0 +assert expensive(1, 2) == 3 +assert call_count == 1 + +# Cached — no recompute +assert expensive(1, 2) == 3 +assert call_count == 1 + +# Different args +assert expensive(3, 4) == 7 +assert call_count == 2 + +# Kwargs +assert expensive(1, y=2) == 3 +assert call_count == 2 # same as (1, 2) via kwargs + +# Fill cache to max_size=3 +assert expensive(10) == 10 # call 3 +assert expensive(20) == 20 # call 4, evicts (1,2) +assert call_count == 4 + +# (1,2) was evicted, must recompute +assert expensive(1, 2) == 3 +assert call_count == 5 + +print("PASS: memoize") +""", + max_tokens=1500, + ), + + Challenge( + id="fn_compose_async", + name="Partition with multiple predicates", + category="functional", + difficulty="medium", + prompt="""Write a Python function: + +def multi_partition(xs: list, *predicates) -> list[list]: + \"\"\"Partition a list into N+1 buckets where N is the number of predicates. + Each element goes into the bucket of the FIRST predicate it satisfies. + Elements matching no predicate go into the last bucket. + Returns list of N+1 lists. Does not mutate input.\"\"\" + +Example: + multi_partition([1,2,3,4,5,6,7,8,9,10], + lambda x: x % 3 == 0, + lambda x: x % 2 == 0) + # => [[3,6,9], [2,4,8,10], [1,5,7]] + # 6 goes to first bucket (div by 3) even though also div by 2 +""", + test_code=""" +# Basic +r = multi_partition([1,2,3,4,5,6,7,8,9,10], lambda x: x%3==0, lambda x: x%2==0) +assert r == [[3,6,9], [2,4,8,10], [1,5,7]], f"got {r}" + +# No predicates — everything in remainder +assert multi_partition([1,2,3]) == [[1,2,3]] + +# One predicate +r = multi_partition(["a","bb","ccc"], lambda s: len(s) > 1) +assert r == [["bb","ccc"], ["a"]] + +# All match first +r = multi_partition([2,4,6], lambda x: x%2==0, lambda x: x>0) +assert r == [[2,4,6], [], []] + +# Empty +r = multi_partition([], lambda x: True) +assert r == [[], []] + +print("PASS: multi_partition") +""", + ), +] + +# ══════════════════════════════════════════════════════════════ +# DATA PROCESSING +# ══════════════════════════════════════════════════════════════ + +DATA_PROCESSING = [ + Challenge( + id="dp_coerce", + name="Type coercion with schema", + category="data_processing", + difficulty="hard", + prompt="""Write a Python function: + +def coerce_types(data: dict, schema: dict[str, str]) -> tuple[dict, list[str]]: + \"\"\"Coerce dict values to types specified in schema. Never mutate original. + + Schema maps field names to type strings: "int", "float", "str", "bool", "list[str]". + + Rules: + - str → int: parse via float first (handle "3.0" → 3), warn if lossy ("3.7" → 3) + - str → float: standard float() + - str → bool: "true/1/yes" → True, "false/0/no" → False (case-insensitive) + - str → list[str]: split by "," and strip whitespace from each item + - Fields not in schema: pass through unchanged + - Fields in schema but not in data: skip + - Failed coercion: keep original value, add warning string to list + + Returns (new_dict, warnings_list).\"\"\" +""", + test_code=""" +# Basic coercions +d, w = coerce_types({"age": "25", "score": "3.14", "active": "yes"}, {"age": "int", "score": "float", "active": "bool"}) +assert d == {"age": 25, "score": 3.14, "active": True}, f"got {d}" +assert w == [] + +# Lossy int coercion +d, w = coerce_types({"x": "3.7"}, {"x": "int"}) +assert d["x"] == 3 +assert len(w) == 1 and "lossy" in w[0].lower() or "3.7" in w[0] + +# Bool variants +d, _ = coerce_types({"a": "TRUE", "b": "0", "c": "no"}, {"a": "bool", "b": "bool", "c": "bool"}) +assert d == {"a": True, "b": False, "c": False} + +# list[str] +d, _ = coerce_types({"tags": "a, b , c"}, {"tags": "list[str]"}) +assert d == {"tags": ["a", "b", "c"]} + +# Pass through unknown fields +d, _ = coerce_types({"name": "test", "age": "5"}, {"age": "int"}) +assert d == {"name": "test", "age": 5} + +# Failed coercion +d, w = coerce_types({"x": "not_a_number"}, {"x": "int"}) +assert d["x"] == "not_a_number" # kept original +assert len(w) == 1 + +# No mutation +original = {"x": "5"} +d, _ = coerce_types(original, {"x": "int"}) +assert original["x"] == "5" +assert d["x"] == 5 + +print("PASS: coerce_types") +""", + max_tokens=2048, + ), + + Challenge( + id="dp_frontmatter", + name="Extract YAML frontmatter", + category="data_processing", + difficulty="medium", + prompt="""Write a Python function: + +def extract_frontmatter(content: str) -> tuple[str, dict | None]: + \"\"\"Extract YAML-like frontmatter delimited by '---' from start of markdown. + + Frontmatter format: + --- + key: value + another: something + --- + + Rest of content here. + + Parse simple key:value pairs (no nested YAML needed). Values are always strings. + Do NOT use the yaml library. + + Returns (content_without_frontmatter, parsed_dict_or_None). + If no frontmatter found, return (original_content, None).\"\"\" +""", + test_code=""" +# Basic frontmatter +content = "---\\nname: test\\nversion: 1.0\\n---\\n\\nHello world" +body, meta = extract_frontmatter(content) +assert meta == {"name": "test", "version": "1.0"}, f"got {meta}" +assert body.strip() == "Hello world" + +# No frontmatter +body, meta = extract_frontmatter("Just text") +assert meta is None +assert body == "Just text" + +# Empty frontmatter +body, meta = extract_frontmatter("---\\n---\\nContent") +assert meta == {} or meta is not None +assert "Content" in body + +# Values with colons +body, meta = extract_frontmatter("---\\nurl: http://example.com\\n---\\nBody") +assert meta["url"] == "http://example.com" + +# Frontmatter must be at start +body, meta = extract_frontmatter("Some text\\n---\\nkey: val\\n---") +assert meta is None + +print("PASS: extract_frontmatter") +""", + ), + + Challenge( + id="dp_json_extract", + name="Extract JSON from LLM response", + category="data_processing", + difficulty="hard", + prompt="""Write a Python function: + +def extract_json_from_llm(content: str) -> dict: + \"\"\"Extract and parse JSON from messy LLM responses. + + Must handle: + 1. JSON inside ```json ... ``` code blocks + 2. JSON inside ``` ... ``` blocks (no language tag) + 3. Raw JSON with surrounding text + 4. Trailing commas: {"a": 1,} or [1, 2,] + 5. Python None instead of null + 6. Single-quoted strings converted to double quotes + + Returns parsed dict. Returns empty dict {} on failure. + Use only stdlib (json, re).\"\"\" +""", + test_code=""" +import json + +# Clean JSON block +assert extract_json_from_llm('```json\\n{"name": "test"}\\n```') == {"name": "test"} + +# Block without language tag +assert extract_json_from_llm('```\\n{"x": 1}\\n```') == {"x": 1} + +# JSON with surrounding text +r = extract_json_from_llm('Here is the result: {"count": 42} hope that helps!') +assert r == {"count": 42} + +# Trailing commas +assert extract_json_from_llm('{"a": 1, "b": 2,}') == {"a": 1, "b": 2} +assert extract_json_from_llm('[1, 2, 3,]') == {} or extract_json_from_llm('{"items": [1,2,]}') == {"items": [1, 2]} + +# Python None → null +assert extract_json_from_llm('{"value": None}') == {"value": None} + +# Garbage input +assert extract_json_from_llm("no json here at all") == {} +assert extract_json_from_llm("") == {} + +print("PASS: extract_json_from_llm") +""", + max_tokens=1500, + ), + + Challenge( + id="dp_smart_split", + name="Smart text splitter with token budget", + category="data_processing", + difficulty="hard", + prompt="""Write a Python function: + +def smart_split(text: str, max_chars: int = 500, overlap: int = 50) -> list[str]: + \"\"\"Split text into chunks respecting max_chars with overlap between chunks. + + Rules: + - Split at paragraph boundaries (double newline) when possible + - If a single paragraph exceeds max_chars, split at sentence boundaries (. ! ?) + - If a single sentence exceeds max_chars, hard-cut at max_chars + - Each chunk (except the first) starts with the last `overlap` characters of the previous chunk + - Strip leading/trailing whitespace from each chunk + - Never return empty chunks + + Returns list of string chunks.\"\"\" +""", + test_code=""" +# Simple paragraphs within budget +text = "First paragraph.\\n\\nSecond paragraph.\\n\\nThird paragraph." +chunks = smart_split(text, max_chars=100) +assert len(chunks) == 1 +assert text.strip() in chunks[0] + +# Force split between paragraphs +text = "A" * 100 + "\\n\\n" + "B" * 100 +chunks = smart_split(text, max_chars=120, overlap=10) +assert len(chunks) >= 2 +assert "A" * 100 in chunks[0] +assert "B" * 100 in chunks[-1] + +# Overlap present +text = "Hello world this is text.\\n\\nAnother paragraph here." +chunks = smart_split(text, max_chars=30, overlap=5) +assert len(chunks) >= 2 +for c in chunks: + assert len(c.strip()) > 0 # no empty chunks + +# Very long single paragraph splits at sentence +text = "Short sentence. " * 50 # ~850 chars +chunks = smart_split(text, max_chars=200, overlap=20) +assert all(len(c) <= 220 for c in chunks) # max_chars + overlap tolerance + +# Hard cut when no sentence boundary +text = "A" * 600 +chunks = smart_split(text, max_chars=200, overlap=20) +assert len(chunks) >= 3 +assert all(len(c) <= 220 for c in chunks) + +# Empty/whitespace +assert smart_split("") == [] or smart_split("") == [""] +assert smart_split(" \\n\\n ") == [] or len(smart_split(" \\n\\n ")) <= 1 + +print("PASS: smart_split") +""", + max_tokens=2048, + ), +] + +# ══════════════════════════════════════════════════════════════ +# ALGORITHMS +# ══════════════════════════════════════════════════════════════ + +ALGORITHMS = [ + Challenge( + id="alg_topo_sort", + name="Topological sort with cycle detection", + category="algorithm", + difficulty="hard", + prompt="""Write a Python function: + +def topo_sort(graph: dict[str, list[str]]) -> tuple[list[str], bool]: + \"\"\"Topological sort of a directed acyclic graph using Kahn's algorithm. + + graph is adjacency list: {"a": ["b", "c"]} means a → b, a → c. + Nodes with no edges should also be included. + + Returns (sorted_list, has_cycle). + - If no cycle: (topologically_sorted_nodes, False) + - If cycle detected: (partial_result, True) + + When multiple valid orderings exist, prefer lexicographic order.\"\"\" +""", + test_code=""" +# Simple DAG +order, cycle = topo_sort({"a": ["b", "c"], "b": ["d"], "c": ["d"], "d": []}) +assert not cycle +assert order.index("a") < order.index("b") +assert order.index("a") < order.index("c") +assert order.index("b") < order.index("d") +assert order.index("c") < order.index("d") + +# Lexicographic preference +order, cycle = topo_sort({"c": [], "b": [], "a": []}) +assert not cycle +assert order == ["a", "b", "c"] + +# Cycle detection +_, cycle = topo_sort({"a": ["b"], "b": ["c"], "c": ["a"]}) +assert cycle + +# Single node +order, cycle = topo_sort({"x": []}) +assert order == ["x"] +assert not cycle + +# Empty graph +order, cycle = topo_sort({}) +assert order == [] +assert not cycle + +# Linear chain +order, cycle = topo_sort({"a": ["b"], "b": ["c"], "c": []}) +assert order == ["a", "b", "c"] +assert not cycle + +print("PASS: topo_sort") +""", + ), + + Challenge( + id="alg_interval_merge", + name="Interval scheduler with priorities", + category="algorithm", + difficulty="hard", + prompt="""Write a Python function: + +def schedule_intervals(intervals: list[dict]) -> list[dict]: + \"\"\"Schedule non-overlapping intervals maximizing total priority. + + Each interval is {"id": str, "start": int, "end": int, "priority": int}. + Intervals are half-open: [start, end). Two intervals [1,3) and [3,5) do NOT overlap. + + Use weighted interval scheduling (dynamic programming). + Returns list of selected intervals sorted by start time.\"\"\" +""", + test_code=""" +# Basic: pick higher priority +result = schedule_intervals([ + {"id": "a", "start": 0, "end": 3, "priority": 2}, + {"id": "b", "start": 1, "end": 4, "priority": 5}, + {"id": "c", "start": 3, "end": 6, "priority": 3}, +]) +ids = [r["id"] for r in result] +assert "b" in ids # highest single priority +# b conflicts with a and c's start, so either [b] (5) or [a,c] (5) is valid +total = sum(r["priority"] for r in result) +assert total == 5, f"got total={total}" + +# Non-overlapping, take all +result = schedule_intervals([ + {"id": "a", "start": 0, "end": 2, "priority": 3}, + {"id": "b", "start": 2, "end": 4, "priority": 3}, + {"id": "c", "start": 4, "end": 6, "priority": 3}, +]) +assert len(result) == 3 +assert sum(r["priority"] for r in result) == 9 + +# Empty +assert schedule_intervals([]) == [] + +# Single +result = schedule_intervals([{"id": "x", "start": 0, "end": 10, "priority": 7}]) +assert len(result) == 1 and result[0]["id"] == "x" + +# Prefer two small over one big +result = schedule_intervals([ + {"id": "big", "start": 0, "end": 10, "priority": 5}, + {"id": "s1", "start": 0, "end": 5, "priority": 3}, + {"id": "s2", "start": 5, "end": 10, "priority": 3}, +]) +total = sum(r["priority"] for r in result) +assert total == 6 # s1 + s2 beats big + +# Result sorted by start +for i in range(len(result) - 1): + assert result[i]["start"] <= result[i+1]["start"] + +print("PASS: schedule_intervals") +""", + max_tokens=2048, + ), + + Challenge( + id="alg_tree_ops", + name="Tree operations suite", + category="algorithm", + difficulty="expert", + prompt="""Write three Python functions for tree manipulation: + +1. def flatten_tree(tree: dict) -> list[dict]: + \"\"\"Flatten nested tree to list. Each node is a dict with optional 'children' key. + DFS pre-order. Remove 'children' key from output nodes. Deep copy nodes.\"\"\" + +2. def find_path(tree: dict, target_id: str) -> list[str] | None: + \"\"\"Find path from root to node with given 'id' field. Returns list of ids + from root to target (inclusive), or None if not found.\"\"\" + +3. def map_tree(tree: dict, fn) -> dict: + \"\"\"Apply fn to each node (excluding 'children' key), return new tree with + same structure. fn receives a dict without 'children' and returns a new dict. + Must not mutate original.\"\"\" +""", + test_code=""" +import copy + +tree = { + "id": "root", "name": "Root", + "children": [ + {"id": "a", "name": "A", "children": [ + {"id": "a1", "name": "A1"}, + {"id": "a2", "name": "A2"}, + ]}, + {"id": "b", "name": "B"}, + ] +} +original = copy.deepcopy(tree) + +# flatten_tree +flat = flatten_tree(tree) +ids = [n["id"] for n in flat] +assert ids == ["root", "a", "a1", "a2", "b"], f"got {ids}" +assert all("children" not in n for n in flat) +assert tree == original # no mutation + +# find_path +assert find_path(tree, "a2") == ["root", "a", "a2"] +assert find_path(tree, "root") == ["root"] +assert find_path(tree, "b") == ["root", "b"] +assert find_path(tree, "nonexistent") is None + +# map_tree +result = map_tree(tree, lambda n: {**n, "name": n["name"].lower()}) +assert result["name"] == "root" +assert result["children"][0]["name"] == "a" +assert result["children"][0]["children"][0]["name"] == "a1" +assert tree == original # no mutation +assert result["id"] == "root" + +# Edge: leaf node +leaf = {"id": "solo", "val": 1} +flat = flatten_tree(leaf) +assert flat == [{"id": "solo", "val": 1}] +assert find_path(leaf, "solo") == ["solo"] + +print("PASS: tree_ops") +""", + max_tokens=2048, + ), +] + +# ══════════════════════════════════════════════════════════════ +# REAL-WORLD PATTERNS +# ══════════════════════════════════════════════════════════════ + +REAL_WORLD = [ + Challenge( + id="rw_retry", + name="Retry with exponential backoff", + category="real_world", + difficulty="hard", + prompt="""Write a Python function: + +def compute_backoff_delays(max_retries: int, base_delay: float = 1.0, + max_delay: float = 60.0, jitter: bool = False) -> list[float]: + \"\"\"Compute the sequence of backoff delays for retry logic. + + Formula: delay = min(base_delay * 2^attempt, max_delay) + If jitter=True, multiply each delay by a factor between 0.5 and 1.0 + (use deterministic half-jitter: factor = 0.75 for testability). + + attempt starts at 0. + Returns list of `max_retries` delay values.\"\"\" + +Also write: + +def classify_error(status_code: int) -> str: + \"\"\"Classify HTTP status code for retry decisions. + Returns: 'permanent' (4xx except 429), 'transient' (5xx, 429, 408), or 'success' (2xx). + Any other code returns 'unknown'.\"\"\" +""", + test_code=""" +# Basic exponential backoff +delays = compute_backoff_delays(5, base_delay=1.0, max_delay=60.0) +assert delays == [1.0, 2.0, 4.0, 8.0, 16.0], f"got {delays}" + +# Capped at max_delay +delays = compute_backoff_delays(4, base_delay=10.0, max_delay=30.0) +assert delays == [10.0, 20.0, 30.0, 30.0], f"got {delays}" + +# With jitter (deterministic 0.75 factor) +delays = compute_backoff_delays(3, base_delay=4.0, jitter=True) +assert delays == [3.0, 6.0, 12.0], f"got {delays}" + +# Zero retries +assert compute_backoff_delays(0) == [] + +# Error classification +assert classify_error(200) == "success" +assert classify_error(201) == "success" +assert classify_error(400) == "permanent" +assert classify_error(403) == "permanent" +assert classify_error(404) == "permanent" +assert classify_error(429) == "transient" # rate limit +assert classify_error(408) == "transient" # timeout +assert classify_error(500) == "transient" +assert classify_error(503) == "transient" +assert classify_error(100) == "unknown" +assert classify_error(302) == "unknown" + +print("PASS: retry_backoff") +""", + ), + + Challenge( + id="rw_schema_validate", + name="Schema validator for dicts", + category="real_world", + difficulty="expert", + prompt="""Write a Python function: + +def validate(data: dict, schema: dict) -> list[str]: + \"\"\"Validate a dict against a schema. Return list of error strings (empty = valid). + + Schema format — each key maps to a rule dict: + { + "field_name": { + "type": "str" | "int" | "float" | "bool" | "list" | "dict", + "required": True | False, # default False + "min": number, # minimum value (for int/float) or min length (for str/list) + "max": number, # maximum value or max length + "choices": [...], # allowed values + "pattern": "regex", # regex pattern (for str only) + } + } + + Error messages should be descriptive: "field_name: expected type str, got int" + Check in order: required → type → min/max → choices → pattern.\"\"\" +""", + test_code=""" +import re + +schema = { + "name": {"type": "str", "required": True, "min": 1, "max": 50}, + "age": {"type": "int", "required": True, "min": 0, "max": 150}, + "email": {"type": "str", "pattern": r".+@.+\\..+"}, + "role": {"type": "str", "choices": ["admin", "user", "guest"]}, + "tags": {"type": "list", "max": 5}, +} + +# Valid data +errors = validate({"name": "Alice", "age": 30, "email": "a@b.com", "role": "admin", "tags": ["a"]}, schema) +assert errors == [], f"got {errors}" + +# Missing required +errors = validate({"age": 25}, schema) +assert any("name" in e and "required" in e.lower() for e in errors), f"got {errors}" + +# Wrong type +errors = validate({"name": 123, "age": 25}, schema) +assert any("name" in e and "type" in e.lower() for e in errors) + +# Min/max violation +errors = validate({"name": "", "age": 25}, schema) +assert any("name" in e for e in errors) # min length 1 + +errors = validate({"name": "Bob", "age": -5}, schema) +assert any("age" in e for e in errors) # min 0 + +# Invalid choice +errors = validate({"name": "X", "age": 1, "role": "superuser"}, schema) +assert any("role" in e and "choices" in e.lower() for e in errors) + +# Pattern mismatch +errors = validate({"name": "X", "age": 1, "email": "invalid"}, schema) +assert any("email" in e and "pattern" in e.lower() for e in errors) + +# Extra fields ignored (no error) +errors = validate({"name": "X", "age": 1, "extra": "ok"}, schema) +assert not any("extra" in e for e in errors) + +# Optional missing is fine +errors = validate({"name": "Test", "age": 50}, schema) +assert not any("email" in e for e in errors) + +print("PASS: schema_validate") +""", + max_tokens=2500, + ), + + Challenge( + id="rw_rate_limiter", + name="Token bucket rate limiter", + category="real_world", + difficulty="expert", + prompt="""Write a Python class: + +class TokenBucket: + \"\"\"Token bucket rate limiter (non-threaded, for testing). + + Args: + capacity: Maximum tokens in bucket. + refill_rate: Tokens added per second. + + Methods: + consume(tokens: int = 1, current_time: float = None) -> bool: + Try to consume tokens. Returns True if allowed, False if not enough tokens. + current_time is injectable for testing (defaults to time.time()). + Before checking, refill based on elapsed time since last refill. + + tokens_available(current_time: float = None) -> float: + Return current token count after refill. + + wait_time(tokens: int = 1, current_time: float = None) -> float: + Return seconds to wait before `tokens` would be available. + Returns 0.0 if tokens are already available. + \"\"\" +""", + test_code=""" +# Basic usage +bucket = TokenBucket(capacity=10, refill_rate=1.0) + +# Starts full +assert bucket.tokens_available(current_time=0) == 10 + +# Consume some +assert bucket.consume(3, current_time=0) == True +assert bucket.tokens_available(current_time=0) == 7 + +# Consume more than available +assert bucket.consume(8, current_time=0) == False +assert bucket.tokens_available(current_time=0) == 7 # unchanged + +# Refill over time +assert bucket.tokens_available(current_time=2) == 9 # 7 + 2*1.0 + +# Consume after refill +assert bucket.consume(9, current_time=2) == True +assert bucket.tokens_available(current_time=2) == 0 + +# Don't exceed capacity +assert bucket.tokens_available(current_time=100) == 10 # capped at capacity + +# Wait time +bucket2 = TokenBucket(capacity=5, refill_rate=2.0) +bucket2.consume(5, current_time=0) +assert bucket2.tokens_available(current_time=0) == 0 +wt = bucket2.wait_time(4, current_time=0) +assert abs(wt - 2.0) < 0.01 # need 4 tokens at 2/s = 2s + +# Already available +bucket3 = TokenBucket(capacity=10, refill_rate=1.0) +assert bucket3.wait_time(5, current_time=0) == 0.0 + +# Consume more than capacity +assert bucket3.consume(11, current_time=0) == False + +print("PASS: token_bucket") +""", + max_tokens=1500, + ), + + Challenge( + id="rw_diff", + name="Simple line differ", + category="real_world", + difficulty="expert", + prompt="""Write a Python function: + +def line_diff(old: str, new: str) -> list[str]: + \"\"\"Compute line-by-line diff between old and new text. + + Returns list of diff lines: + - Lines only in old: prefixed with "- " + - Lines only in new: prefixed with "+ " + - Common lines: prefixed with " " (two spaces) + + Use longest common subsequence (LCS) to produce minimal diff. + Split input on newlines. Empty string = no lines.\"\"\" +""", + test_code=""" +# No changes +result = line_diff("a\\nb\\nc", "a\\nb\\nc") +assert result == [" a", " b", " c"] + +# Addition +result = line_diff("a\\nc", "a\\nb\\nc") +assert result == [" a", "+ b", " c"], f"got {result}" + +# Deletion +result = line_diff("a\\nb\\nc", "a\\nc") +assert result == [" a", "- b", " c"], f"got {result}" + +# Replacement +result = line_diff("a\\nb\\nc", "a\\nX\\nc") +assert result == [" a", "- b", "+ X", " c"], f"got {result}" + +# Complete change +result = line_diff("a\\nb", "c\\nd") +assert result == ["- a", "- b", "+ c", "+ d"] + +# Empty inputs +assert line_diff("", "") == [] +assert line_diff("a", "") == ["- a"] +assert line_diff("", "a") == ["+ a"] + +# Multiple additions and deletions +result = line_diff("a\\nb\\nc\\nd", "a\\nc\\nd\\ne") +assert "- b" in result +assert "+ e" in result +assert " a" in result +assert " c" in result +assert " d" in result + +print("PASS: line_diff") +""", + max_tokens=2048, + ), +] + + +# ── Todos ───────────────────────────────────────────────── + +ALL_CHALLENGES = FUNCTIONAL + DATA_PROCESSING + ALGORITHMS + REAL_WORLD diff --git a/eval_runner.py b/eval_runner.py new file mode 100644 index 0000000..a23c3da --- /dev/null +++ b/eval_runner.py @@ -0,0 +1,157 @@ +""" +eval_runner.py — Motor de evaluación de coding para modelos locales. + +Prueba si un LLM puede generar funciones de calidad production-ready +al estilo del fn_registry: puras, genéricas, testeables, composables. +""" + +import requests +import re +import subprocess +import tempfile +import time +import os +import json +from dataclasses import dataclass, field + + +API_BASE = "http://127.0.0.1:1234/v1" + + +# ── Tipos ───────────────────────────────────────────────── + +@dataclass +class Challenge: + id: str + name: str + category: str # functional, data_processing, algorithm, real_world + difficulty: str # medium, hard, expert + prompt: str + test_code: str + max_tokens: int = 2048 + +@dataclass +class Result: + challenge_id: str + name: str + category: str + difficulty: str + passed: bool + error: str + code: str + raw_response: str + latency_ms: float + completion_tokens: int + tokens_per_second: float + + +# ── Motor ───────────────────────────────────────────────── + +SYSTEM_PROMPT = """You are a senior software engineer writing production Python code for a function registry. + +Rules: +- Return ONLY the function/class code inside a single ```python block +- Use type hints on all parameters and return types +- Functions must be pure when possible: no side effects, no mutation of inputs +- Use descriptive variable names, not single letters +- Handle edge cases (empty inputs, None, boundary values) +- No imports from external packages — only Python stdlib +- No print statements, no logging, no comments explaining obvious code +- Follow the function signature EXACTLY as specified in the prompt""" + + +def query_model(model: str, prompt: str, max_tokens: int = 4096) -> dict: + t0 = time.time() + resp = requests.post(f"{API_BASE}/chat/completions", json={ + "model": model, + "messages": [ + {"role": "system", "content": SYSTEM_PROMPT}, + {"role": "user", "content": prompt}, + ], + "max_tokens": max_tokens, + "temperature": 0.0, + "top_p": 0.9, + "top_k": 20, + "min_p": 0.05, + "repetition_penalty": 1.0, + "presence_penalty": 0.0, + "frequency_penalty": 0.0, + "stop": ["<|im_end|>", "<|endoftext|>"], + }, timeout=300) + latency_ms = (time.time() - t0) * 1000 + data = resp.json() + content = data["choices"][0]["message"]["content"] + usage = data.get("usage", {}) + comp = usage.get("completion_tokens", 0) + tps = comp / (latency_ms / 1000) if latency_ms > 0 else 0 + return {"content": content, "latency_ms": latency_ms, "completion_tokens": comp, "tps": tps} + + +def extract_code(text: str) -> str: + # 1. Closed code block + for pat in [r"```python\s*\n(.*?)```", r"```\s*\n(.*?)```"]: + m = re.search(pat, text, re.DOTALL) + if m: + return m.group(1).strip() + # 2. Unclosed code block (model hit max_tokens before closing ```) + for pat in [r"```python\s*\n(.*)", r"```\s*\n(.*)"]: + m = re.search(pat, text, re.DOTALL) + if m: + return m.group(1).strip() + # 3. No code block — extract from first 'def '/'class ' to end + m = re.search(r"^((?:def |class |import |from ).*)", text, re.DOTALL | re.MULTILINE) + if m: + return m.group(1).strip() + return text.strip() + + +def run_test(code: str, test_code: str, timeout: int = 15) -> tuple[bool, str]: + full = code + "\n\n" + test_code + with tempfile.NamedTemporaryFile(mode="w", suffix=".py", delete=False) as f: + f.write(full) + f.flush() + try: + r = subprocess.run(["python3", f.name], capture_output=True, text=True, timeout=timeout) + if r.returncode == 0: + return True, "" + # Full error: stdout + stderr, keep last 800 chars for better debugging + err = (r.stdout + "\n" + r.stderr).strip() + return False, err[-800:] + except subprocess.TimeoutExpired: + return False, "TIMEOUT" + finally: + os.unlink(f.name) + + +def evaluate(model: str, challenges: list[Challenge]) -> list[Result]: + results = [] + for ch in challenges: + print(f" [{ch.id}] {ch.name} ({ch.difficulty})...", end=" ", flush=True) + try: + resp = query_model(model, ch.prompt, ch.max_tokens) + code = extract_code(resp["content"]) + passed, error = run_test(code, ch.test_code) + status = "PASS" if passed else "FAIL" + print(f"{status} {resp['latency_ms']:.0f}ms {resp['completion_tokens']}tok {resp['tps']:.1f}t/s") + if not passed: + # Show last 2 lines of error for quick diagnosis + err_lines = [l for l in error.strip().split("\n") if l.strip()] + for el in err_lines[-3:]: + print(f" | {el[:120]}") + results.append(Result( + challenge_id=ch.id, name=ch.name, category=ch.category, + difficulty=ch.difficulty, passed=passed, error=error, + code=code, raw_response=resp["content"], + latency_ms=resp["latency_ms"], + completion_tokens=resp["completion_tokens"], + tokens_per_second=resp["tps"], + )) + except Exception as e: + print(f"ERROR: {e}") + results.append(Result( + challenge_id=ch.id, name=ch.name, category=ch.category, + difficulty=ch.difficulty, passed=False, error=str(e), + code="", raw_response="", latency_ms=0, + completion_tokens=0, tokens_per_second=0, + )) + return results diff --git a/main.py b/main.py new file mode 100644 index 0000000..ef95aed --- /dev/null +++ b/main.py @@ -0,0 +1,6 @@ +def main(): + print("Hello from agent-coding-eval!") + + +if __name__ == "__main__": + main() diff --git a/notebooks/01_coding_eval.py b/notebooks/01_coding_eval.py new file mode 100644 index 0000000..f2cbe58 --- /dev/null +++ b/notebooks/01_coding_eval.py @@ -0,0 +1,621 @@ +""" +Agent Coding Evaluation - Script de evaluación de modelos locales +Evalúa capacidades de programación de modelos LLM locales via LM Studio API. + +Modelos disponibles: +- qwen/qwen3-coder-next (especializado en código) +- qwen/qwen3.5-9b (general) +- nvidia/nemotron-3-nano-4b (pequeño) +- bitnet-b1.58-2b-4t (ultra-ligero) +""" + +import requests +import json +import time +import re +import subprocess +import tempfile +import os +import traceback +from dataclasses import dataclass, field +from typing import Optional + +# ── Config ──────────────────────────────────────────────── + +API_BASE = "http://127.0.0.1:1234/v1" +MODELS = [ + "qwen/qwen3-coder-next", + "qwen/qwen3.5-9b", + "nvidia/nemotron-3-nano-4b", + "bitnet-b1.58-2b-4t", +] + +# ── Tipos ───────────────────────────────────────────────── + +@dataclass +class Challenge: + id: str + name: str + difficulty: str # easy, medium, hard + language: str # python, go, bash + prompt: str + test_code: str # código que valida la respuesta + max_tokens: int = 1024 + +@dataclass +class Result: + model: str + challenge_id: str + raw_response: str + extracted_code: str + compiled: bool + tests_passed: bool + error: str + latency_ms: float + tokens_used: int + reasoning_tokens: int = 0 + completion_tokens: int = 0 + prompt_tokens: int = 0 + tokens_per_second: float = 0.0 # completion tokens / latency + +# ── Helpers ─────────────────────────────────────────────── + +def query_model(model: str, prompt: str, max_tokens: int = 1024, temperature: float = 0) -> dict: + """Consulta un modelo via OpenAI-compatible API.""" + resp = requests.post(f"{API_BASE}/chat/completions", json={ + "model": model, + "messages": [ + {"role": "system", "content": "You are a coding assistant. Return ONLY code inside a single code block. No explanations."}, + {"role": "user", "content": prompt}, + ], + "max_tokens": max_tokens, + "temperature": temperature, + }, timeout=120) + resp.raise_for_status() + return resp.json() + + +def extract_code(text: str, language: str = "python") -> str: + """Extrae código de un bloque markdown.""" + # Buscar bloque con lenguaje específico + patterns = [ + rf"```{language}\s*\n(.*?)```", + r"```\s*\n(.*?)```", + rf"```{language}\s*\n(.*?)$", + ] + for pat in patterns: + m = re.search(pat, text, re.DOTALL) + if m: + return m.group(1).strip() + # Si no hay bloque, asumir que todo es código + return text.strip() + + +def run_python(code: str, test_code: str, timeout: int = 10) -> tuple[bool, bool, str]: + """Ejecuta código Python + tests. Retorna (compiled, tests_passed, error).""" + full_code = code + "\n\n" + test_code + with tempfile.NamedTemporaryFile(mode="w", suffix=".py", delete=False) as f: + f.write(full_code) + f.flush() + try: + result = subprocess.run( + ["python3", f.name], + capture_output=True, text=True, timeout=timeout + ) + if result.returncode == 0: + return True, True, "" + # Distinguir error de compilación vs test + err = result.stderr.strip() + if "SyntaxError" in err or "IndentationError" in err: + return False, False, err[-500:] + return True, False, err[-500:] + except subprocess.TimeoutExpired: + return True, False, "TIMEOUT" + finally: + os.unlink(f.name) + + +def run_go(code: str, test_code: str, timeout: int = 15) -> tuple[bool, bool, str]: + """Ejecuta código Go + tests. Auto-detecta imports faltantes.""" + with tempfile.TemporaryDirectory() as tmpdir: + # Init module + subprocess.run(["go", "mod", "init", "eval"], cwd=tmpdir, capture_output=True) + # Auto-detect needed stdlib imports from code + stdlib_hints = { + "strings.": "strings", "fmt.": "fmt", "strconv.": "strconv", + "sort.": "sort", "math.": "math", "regexp.": "regexp", + "io.": "io", "os.": "os", "sync.": "sync", + } + needed = set() + for hint, pkg in stdlib_hints.items(): + if hint in code: + needed.add(pkg) + # Only add imports if code doesn't already have an import block + import_block = "" + if needed and "import" not in code: + imports = "\n".join(f'\t"{p}"' for p in sorted(needed)) + import_block = f"import (\n{imports}\n)\n\n" + main_code = f"package main\n\n{import_block}{code}\n" + with open(os.path.join(tmpdir, "main.go"), "w") as f: + f.write(main_code) + # Test file + test_full = f"package main\n\nimport \"testing\"\n\n{test_code}\n" + with open(os.path.join(tmpdir, "main_test.go"), "w") as f: + f.write(test_full) + try: + # Build check + build = subprocess.run( + ["go", "build", "."], cwd=tmpdir, + capture_output=True, text=True, timeout=timeout + ) + if build.returncode != 0: + return False, False, build.stderr.strip()[-500:] + # Run tests + test = subprocess.run( + ["go", "test", "-v", "."], cwd=tmpdir, + capture_output=True, text=True, timeout=timeout + ) + if test.returncode == 0: + return True, True, "" + return True, False, (test.stdout + test.stderr).strip()[-500:] + except subprocess.TimeoutExpired: + return True, False, "TIMEOUT" + + +def run_bash(code: str, test_code: str, timeout: int = 10) -> tuple[bool, bool, str]: + """Ejecuta código Bash + tests.""" + full_code = code + "\n\n" + test_code + with tempfile.NamedTemporaryFile(mode="w", suffix=".sh", delete=False) as f: + f.write(full_code) + f.flush() + try: + result = subprocess.run( + ["bash", f.name], + capture_output=True, text=True, timeout=timeout + ) + if result.returncode == 0: + return True, True, "" + err = result.stderr.strip() + if "syntax error" in err.lower(): + return False, False, err[-500:] + return True, False, (result.stdout + err)[-500:] + except subprocess.TimeoutExpired: + return True, False, "TIMEOUT" + finally: + os.unlink(f.name) + + +RUNNERS = { + "python": run_python, + "go": run_go, + "bash": run_bash, +} + + +# ── Challenges ──────────────────────────────────────────── + +CHALLENGES = [ + # --- EASY --- + Challenge( + id="py_easy_1", + name="Fibonacci", + difficulty="easy", + language="python", + prompt="Write a Python function `fib(n: int) -> int` that returns the nth Fibonacci number (0-indexed). fib(0)=0, fib(1)=1, fib(10)=55.", + test_code=""" +assert fib(0) == 0, f"fib(0)={fib(0)}" +assert fib(1) == 1, f"fib(1)={fib(1)}" +assert fib(10) == 55, f"fib(10)={fib(10)}" +assert fib(20) == 6765, f"fib(20)={fib(20)}" +print("PASS: fibonacci") +""", + ), + Challenge( + id="py_easy_2", + name="Palindrome check", + difficulty="easy", + language="python", + prompt="Write a Python function `is_palindrome(s: str) -> bool` that checks if a string is a palindrome, ignoring case and non-alphanumeric characters. is_palindrome('A man, a plan, a canal: Panama') == True.", + test_code=""" +assert is_palindrome("A man, a plan, a canal: Panama") == True +assert is_palindrome("racecar") == True +assert is_palindrome("hello") == False +assert is_palindrome("") == True +assert is_palindrome("Was it a car or a cat I saw?") == True +print("PASS: palindrome") +""", + ), + Challenge( + id="py_easy_3", + name="FizzBuzz list", + difficulty="easy", + language="python", + prompt='Write a Python function `fizzbuzz(n: int) -> list[str]` that returns a list from 1 to n where multiples of 3 are "Fizz", multiples of 5 are "Buzz", multiples of both are "FizzBuzz", and others are the number as string.', + test_code=""" +result = fizzbuzz(15) +assert result[0] == "1", f"got {result[0]}" +assert result[2] == "Fizz", f"got {result[2]}" +assert result[4] == "Buzz", f"got {result[4]}" +assert result[14] == "FizzBuzz", f"got {result[14]}" +assert len(result) == 15 +print("PASS: fizzbuzz") +""", + ), + + # --- MEDIUM --- + Challenge( + id="py_med_1", + name="Two Sum", + difficulty="medium", + language="python", + prompt="Write a Python function `two_sum(nums: list[int], target: int) -> tuple[int, int]` that returns indices of two numbers that add up to target. Each input has exactly one solution. You may not use the same element twice. Return indices in ascending order.", + test_code=""" +assert two_sum([2, 7, 11, 15], 9) == (0, 1) +assert two_sum([3, 2, 4], 6) == (1, 2) +assert two_sum([3, 3], 6) == (0, 1) +assert two_sum([1, 5, 3, 7], 8) == (1, 2) or two_sum([1, 5, 3, 7], 8) == (0, 3) +print("PASS: two_sum") +""", + ), + Challenge( + id="py_med_2", + name="Matrix transpose", + difficulty="medium", + language="python", + prompt="Write a Python function `transpose(matrix: list[list[int]]) -> list[list[int]]` that transposes a matrix. Do NOT use numpy or zip.", + test_code=""" +assert transpose([[1,2,3],[4,5,6]]) == [[1,4],[2,5],[3,6]] +assert transpose([[1]]) == [[1]] +assert transpose([[1,2],[3,4],[5,6]]) == [[1,3,5],[2,4,6]] +print("PASS: transpose") +""", + ), + Challenge( + id="py_med_3", + name="Balanced parentheses", + difficulty="medium", + language="python", + prompt="Write a Python function `is_balanced(s: str) -> bool` that checks if a string has balanced parentheses, brackets, and braces. Only these characters matter: ()[]{}. Other characters should be ignored.", + test_code=""" +assert is_balanced("()[]{}") == True +assert is_balanced("([{}])") == True +assert is_balanced("(]") == False +assert is_balanced("([)]") == False +assert is_balanced("hello (world) [test]") == True +assert is_balanced("{[}]") == False +assert is_balanced("") == True +print("PASS: balanced") +""", + ), + Challenge( + id="py_med_4", + name="Group anagrams", + difficulty="medium", + language="python", + prompt='Write a Python function `group_anagrams(words: list[str]) -> list[list[str]]` that groups anagrams together. Each group should be sorted alphabetically, and the groups should be sorted by their first element.', + test_code=""" +result = group_anagrams(["eat", "tea", "tan", "ate", "nat", "bat"]) +# Sort each group and sort groups by first element for deterministic comparison +result = [sorted(g) for g in result] +result.sort(key=lambda g: g[0]) +assert result == [["ate", "eat", "tea"], ["bat"], ["nat", "tan"]], f"got {result}" +print("PASS: group_anagrams") +""", + ), + + # --- HARD --- + Challenge( + id="py_hard_1", + name="LRU Cache", + difficulty="hard", + language="python", + prompt="""Write a Python class `LRUCache` with: +- `__init__(self, capacity: int)` - Initialize with positive capacity. +- `get(self, key: int) -> int` - Return value if key exists, else -1. Marks as recently used. +- `put(self, key: int, value: int) -> None` - Update or insert. If over capacity, evict least recently used. +Both get and put must run in O(1) average time. Do NOT use functools.lru_cache or collections.OrderedDict.""", + test_code=""" +cache = LRUCache(2) +cache.put(1, 1) +cache.put(2, 2) +assert cache.get(1) == 1, f"got {cache.get(1)}" +cache.put(3, 3) # evicts key 2 +assert cache.get(2) == -1, f"got {cache.get(2)}" +cache.put(4, 4) # evicts key 1 +assert cache.get(1) == -1 +assert cache.get(3) == 3 +assert cache.get(4) == 4 +# Test update +cache2 = LRUCache(2) +cache2.put(1, 10) +cache2.put(1, 20) +assert cache2.get(1) == 20 +print("PASS: lru_cache") +""", + max_tokens=1500, + ), + Challenge( + id="py_hard_2", + name="Merge intervals", + difficulty="hard", + language="python", + prompt="Write a Python function `merge_intervals(intervals: list[list[int]]) -> list[list[int]]` that merges all overlapping intervals and returns sorted non-overlapping intervals.", + test_code=""" +assert merge_intervals([[1,3],[2,6],[8,10],[15,18]]) == [[1,6],[8,10],[15,18]] +assert merge_intervals([[1,4],[4,5]]) == [[1,5]] +assert merge_intervals([[1,4],[0,4]]) == [[0,4]] +assert merge_intervals([[1,4],[2,3]]) == [[1,4]] +assert merge_intervals([]) == [] +assert merge_intervals([[1,1]]) == [[1,1]] +print("PASS: merge_intervals") +""", + ), + Challenge( + id="py_hard_3", + name="Binary search tree iterator", + difficulty="hard", + language="python", + prompt="""Write Python classes: +1. `TreeNode` with attributes `val`, `left`, `right` (left and right default to None). +2. `BSTIterator` that takes a TreeNode root and implements in-order traversal: + - `has_next() -> bool` - returns True if there is a next element. + - `next_val() -> int` - returns the next smallest number. +Must use O(h) memory where h is tree height (not O(n)). Do not flatten the tree into a list.""", + test_code=""" +# Build tree: 7 +# / \\ +# 3 15 +# / \\ +# 9 20 +root = TreeNode(7, TreeNode(3), TreeNode(15, TreeNode(9), TreeNode(20))) +it = BSTIterator(root) +assert it.has_next() == True +assert it.next_val() == 3 +assert it.next_val() == 7 +assert it.has_next() == True +assert it.next_val() == 9 +assert it.next_val() == 15 +assert it.next_val() == 20 +assert it.has_next() == False +print("PASS: bst_iterator") +""", + max_tokens=1500, + ), + + # --- GO --- + Challenge( + id="go_med_1", + name="Reverse words in string", + difficulty="medium", + language="go", + prompt='Write a Go function `ReverseWords(s string) string` that reverses the order of words in a string. Words are separated by spaces. Remove leading/trailing spaces and reduce multiple spaces to single. Example: " hello world " -> "world hello".', + test_code=""" +func TestReverseWords(t *testing.T) { + cases := []struct{ in, want string }{ + {"hello world", "world hello"}, + {" hello world ", "world hello"}, + {"a", "a"}, + {" Bob Loves Alice ", "Alice Loves Bob"}, + } + for _, c := range cases { + got := ReverseWords(c.in) + if got != c.want { + t.Errorf("ReverseWords(%q) = %q, want %q", c.in, got, c.want) + } + } +} +""", + ), + + # --- BASH --- + Challenge( + id="bash_easy_1", + name="Count lines in files", + difficulty="easy", + language="bash", + prompt='Write a Bash function `count_lines` that takes a filename as argument and prints the number of lines. If the file does not exist, print "ERROR: file not found" to stderr and return 1.', + test_code=""" +# Test setup +tmpfile=$(mktemp) +echo -e "line1\\nline2\\nline3" > "$tmpfile" + +result=$(count_lines "$tmpfile") +if [ "$result" != "3" ]; then + echo "FAIL: expected 3, got $result" + exit 1 +fi + +# Test missing file +if count_lines "/nonexistent/file" 2>/dev/null; then + echo "FAIL: should return non-zero for missing file" + exit 1 +fi + +rm -f "$tmpfile" +echo "PASS: count_lines" +""", + ), +] + + +# ── Evaluator ───────────────────────────────────────────── + +def evaluate_model(model: str, challenges: list[Challenge]) -> list[Result]: + """Evalúa un modelo contra todos los challenges.""" + results = [] + for ch in challenges: + print(f" [{ch.id}] {ch.name} ({ch.difficulty})...", end=" ", flush=True) + try: + t0 = time.time() + resp = query_model(model, ch.prompt, ch.max_tokens) + latency = (time.time() - t0) * 1000 + + content = resp["choices"][0]["message"]["content"] + reasoning = resp["choices"][0]["message"].get("reasoning_content", "") + usage = resp.get("usage", {}) + tokens = usage.get("total_tokens", 0) + completion_tokens = usage.get("completion_tokens", 0) + prompt_tokens = usage.get("prompt_tokens", 0) + reasoning_tokens = usage.get("completion_tokens_details", {}).get("reasoning_tokens", 0) + # Velocidad: tokens de completion / tiempo (excluir prompt processing) + tps = (completion_tokens / (latency / 1000)) if latency > 0 else 0 + + code = extract_code(content, ch.language) + runner = RUNNERS.get(ch.language) + if runner: + compiled, passed, error = runner(code, ch.test_code) + else: + compiled, passed, error = False, False, f"No runner for {ch.language}" + + status = "PASS" if passed else ("COMPILE_ERR" if not compiled else "FAIL") + print(f"{status} ({latency:.0f}ms, {completion_tokens}tok, {tps:.1f} tok/s)") + + results.append(Result( + model=model, + challenge_id=ch.id, + raw_response=content, + extracted_code=code, + compiled=compiled, + tests_passed=passed, + error=error, + latency_ms=latency, + tokens_used=tokens, + reasoning_tokens=reasoning_tokens, + completion_tokens=completion_tokens, + prompt_tokens=prompt_tokens, + tokens_per_second=tps, + )) + except Exception as e: + print(f"ERROR: {e}") + results.append(Result( + model=model, + challenge_id=ch.id, + raw_response="", + extracted_code="", + compiled=False, + tests_passed=False, + error=str(e), + latency_ms=0, + tokens_used=0, + )) + return results + + +def print_summary(all_results: list[Result], challenges: list[Challenge]): + """Imprime tabla resumen.""" + ch_map = {c.id: c for c in challenges} + models = sorted(set(r.model for r in all_results)) + + # Header + print("\n" + "=" * 90) + print("RESULTADOS - EVALUACIÓN DE CODING") + print("=" * 90) + + # Per-model summary + for model in models: + model_results = [r for r in all_results if r.model == model] + passed = sum(1 for r in model_results if r.tests_passed) + compiled = sum(1 for r in model_results if r.compiled) + total = len(model_results) + avg_latency = sum(r.latency_ms for r in model_results) / max(total, 1) + avg_tokens = sum(r.tokens_used for r in model_results) / max(total, 1) + + avg_tps = sum(r.tokens_per_second for r in model_results) / max(total, 1) + total_reasoning = sum(r.reasoning_tokens for r in model_results) + + print(f"\n{'─' * 100}") + print(f" {model}") + print(f" Tests passed: {passed}/{total} ({100*passed/total:.0f}%) | " + f"Compiled: {compiled}/{total} | " + f"Avg latency: {avg_latency:.0f}ms | Avg speed: {avg_tps:.1f} tok/s") + if total_reasoning > 0: + print(f" Reasoning tokens total: {total_reasoning}") + print(f"{'─' * 100}") + + for diff in ["easy", "medium", "hard"]: + diff_results = [r for r in model_results if ch_map[r.challenge_id].difficulty == diff] + if not diff_results: + continue + dp = sum(1 for r in diff_results if r.tests_passed) + print(f" {diff.upper():8s} {dp}/{len(diff_results)} passed") + for r in diff_results: + ch = ch_map[r.challenge_id] + icon = "✓" if r.tests_passed else ("✗ compile" if not r.compiled else "✗ test") + err_hint = f" [{r.error[:60]}]" if r.error else "" + reason = f" (R:{r.reasoning_tokens})" if r.reasoning_tokens > 0 else "" + print(f" {icon:12s} {ch.name:30s} {r.latency_ms:6.0f}ms {r.completion_tokens:4d}tok {r.tokens_per_second:5.1f}t/s{reason}{err_hint}") + + # Comparison table + print(f"\n{'=' * 90}") + print("COMPARATIVA") + print(f"{'=' * 90}") + header = f"{'Challenge':35s}" + for m in models: + short = m.split("/")[-1][:15] + header += f" {short:>15s}" + print(header) + print("─" * (35 + 16 * len(models))) + + for ch in challenges: + row = f"{ch.name + ' (' + ch.difficulty[0] + ')':35s}" + for m in models: + r = next((r for r in all_results if r.model == m and r.challenge_id == ch.id), None) + if r and r.tests_passed: + row += f" {'PASS':>15s}" + elif r and r.compiled: + row += f" {'FAIL':>15s}" + elif r: + row += f" {'ERR':>15s}" + else: + row += f" {'---':>15s}" + print(row) + + # Speed comparison + print(f"\n{'=' * 90}") + print("VELOCIDAD (tokens/segundo)") + print(f"{'=' * 90}") + header = f"{'Model':35s} {'Avg tok/s':>10s} {'Min tok/s':>10s} {'Max tok/s':>10s} {'Avg ms':>10s}" + print(header) + print("─" * 75) + for m in models: + mrs = [r for r in all_results if r.model == m] + if not mrs: + continue + avg_tps = sum(r.tokens_per_second for r in mrs) / len(mrs) + min_tps = min(r.tokens_per_second for r in mrs) + max_tps = max(r.tokens_per_second for r in mrs) + avg_ms = sum(r.latency_ms for r in mrs) / len(mrs) + short = m.split("/")[-1] + print(f"{short:35s} {avg_tps:10.1f} {min_tps:10.1f} {max_tps:10.1f} {avg_ms:10.0f}") + + +# ── Main ────────────────────────────────────────────────── + +def run_eval(models: list[str] = None, difficulties: list[str] = None): + """Ejecuta la evaluación completa.""" + models = models or MODELS + challenges = CHALLENGES + if difficulties: + challenges = [c for c in challenges if c.difficulty in difficulties] + + print(f"Evaluando {len(models)} modelos con {len(challenges)} challenges\n") + + all_results = [] + for model in models: + print(f"\n{'═' * 60}") + print(f" MODELO: {model}") + print(f"{'═' * 60}") + results = evaluate_model(model, challenges) + all_results.extend(results) + + print_summary(all_results, challenges) + return all_results + + +if __name__ == "__main__": + import sys + # Filtrar modelos por argumento si se pasa + models = None + if len(sys.argv) > 1: + models = [m for m in MODELS if any(arg in m for arg in sys.argv[1:])] + run_eval(models=models) diff --git a/notebooks/02_qwen25_coder_eval.ipynb b/notebooks/02_qwen25_coder_eval.ipynb new file mode 100644 index 0000000..5042a46 --- /dev/null +++ b/notebooks/02_qwen25_coder_eval.ipynb @@ -0,0 +1,588 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Evaluación: Qwen2.5-Coder-7B-Abliterated\n", + "\n", + "Evaluación de capacidades de programación del modelo local `qwen2.5-coder-7b-abliterated-i1` via LM Studio API.\n", + "\n", + "**Métricas:**\n", + "- Correctitud (tests pass/fail)\n", + "- Velocidad (tokens/segundo)\n", + "- Eficiencia (tokens usados por challenge)" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Modelos disponibles: ['qwen2.5-coder-7b-abliterated-i1', 'nvidia/nemotron-3-nano-4b', 'qwen/qwen3.5-9b', 'bitnet-b1.58-2b-4t', 'text-embedding-nomic-embed-text-v1.5']\n", + "\n", + "✓ qwen2.5-coder-7b-abliterated-i1 disponible\n" + ] + } + ], + "source": [ + "import requests\n", + "import json\n", + "import time\n", + "import re\n", + "import subprocess\n", + "import tempfile\n", + "import os\n", + "import pandas as pd\n", + "\n", + "API_BASE = \"http://127.0.0.1:1234/v1\"\n", + "MODEL = \"qwen2.5-coder-7b-abliterated-i1\"\n", + "\n", + "# Verificar conexión\n", + "resp = requests.get(f\"{API_BASE}/models\")\n", + "models = [m[\"id\"] for m in resp.json()[\"data\"]]\n", + "print(f\"Modelos disponibles: {models}\")\n", + "assert MODEL in models, f\"{MODEL} no está cargado!\"\n", + "print(f\"\\n✓ {MODEL} disponible\")" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "✓ Funciones cargadas\n" + ] + } + ], + "source": [ + "# ── Funciones auxiliares ──────────────────────────────────\n", + "\n", + "def query_model(prompt, max_tokens=1024, temperature=0):\n", + " \"\"\"Consulta el modelo y retorna respuesta + métricas.\"\"\"\n", + " t0 = time.time()\n", + " resp = requests.post(f\"{API_BASE}/chat/completions\", json={\n", + " \"model\": MODEL,\n", + " \"messages\": [\n", + " {\"role\": \"system\", \"content\": \"You are a coding assistant. Return ONLY code inside a single code block. No explanations.\"},\n", + " {\"role\": \"user\", \"content\": prompt},\n", + " ],\n", + " \"max_tokens\": max_tokens,\n", + " \"temperature\": temperature,\n", + " }, timeout=120)\n", + " latency_ms = (time.time() - t0) * 1000\n", + " data = resp.json()\n", + " \n", + " content = data[\"choices\"][0][\"message\"][\"content\"]\n", + " usage = data.get(\"usage\", {})\n", + " completion_tokens = usage.get(\"completion_tokens\", 0)\n", + " prompt_tokens = usage.get(\"prompt_tokens\", 0)\n", + " tps = completion_tokens / (latency_ms / 1000) if latency_ms > 0 else 0\n", + " \n", + " return {\n", + " \"content\": content,\n", + " \"latency_ms\": latency_ms,\n", + " \"completion_tokens\": completion_tokens,\n", + " \"prompt_tokens\": prompt_tokens,\n", + " \"tokens_per_second\": tps,\n", + " }\n", + "\n", + "\n", + "def extract_code(text, language=\"python\"):\n", + " \"\"\"Extrae código de bloque markdown.\"\"\"\n", + " for pat in [rf\"```{language}\\s*\\n(.*?)```\", r\"```\\s*\\n(.*?)```\"]:\n", + " m = re.search(pat, text, re.DOTALL)\n", + " if m:\n", + " return m.group(1).strip()\n", + " return text.strip()\n", + "\n", + "\n", + "def run_python_test(code, test_code, timeout=10):\n", + " \"\"\"Ejecuta código Python + tests. Retorna (passed, error).\"\"\"\n", + " full = code + \"\\n\\n\" + test_code\n", + " with tempfile.NamedTemporaryFile(mode=\"w\", suffix=\".py\", delete=False) as f:\n", + " f.write(full)\n", + " f.flush()\n", + " try:\n", + " result = subprocess.run([\"python3\", f.name], capture_output=True, text=True, timeout=timeout)\n", + " if result.returncode == 0:\n", + " return True, \"\"\n", + " return False, result.stderr.strip()[-300:]\n", + " except subprocess.TimeoutExpired:\n", + " return False, \"TIMEOUT\"\n", + " finally:\n", + " os.unlink(f.name)\n", + "\n", + "\n", + "print(\"✓ Funciones cargadas\")" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "✓ 12 challenges definidos\n", + " easy: 4\n", + " medium: 5\n", + " hard: 3\n" + ] + } + ], + "source": [ + "# ── Challenges ────────────────────────────────────────────\n", + "\n", + "CHALLENGES = [\n", + " # EASY\n", + " {\n", + " \"id\": \"fibonacci\", \"difficulty\": \"easy\",\n", + " \"prompt\": \"Write a Python function `fib(n: int) -> int` that returns the nth Fibonacci number (0-indexed). fib(0)=0, fib(1)=1, fib(10)=55.\",\n", + " \"test\": 'assert fib(0)==0; assert fib(1)==1; assert fib(10)==55; assert fib(20)==6765; print(\"PASS\")'\n", + " },\n", + " {\n", + " \"id\": \"palindrome\", \"difficulty\": \"easy\",\n", + " \"prompt\": \"Write a Python function `is_palindrome(s: str) -> bool` that checks if a string is a palindrome, ignoring case and non-alphanumeric characters.\",\n", + " \"test\": 'assert is_palindrome(\"A man, a plan, a canal: Panama\")==True; assert is_palindrome(\"hello\")==False; assert is_palindrome(\"\")==True; print(\"PASS\")'\n", + " },\n", + " {\n", + " \"id\": \"fizzbuzz\", \"difficulty\": \"easy\",\n", + " \"prompt\": 'Write a Python function `fizzbuzz(n: int) -> list[str]` that returns a list from 1 to n where multiples of 3 are \"Fizz\", multiples of 5 are \"Buzz\", multiples of both are \"FizzBuzz\", and others are the number as string.',\n", + " \"test\": 'r=fizzbuzz(15); assert r[0]==\"1\"; assert r[2]==\"Fizz\"; assert r[4]==\"Buzz\"; assert r[14]==\"FizzBuzz\"; assert len(r)==15; print(\"PASS\")'\n", + " },\n", + " {\n", + " \"id\": \"reverse_string\", \"difficulty\": \"easy\",\n", + " \"prompt\": \"Write a Python function `reverse_words(s: str) -> str` that reverses the order of words. Remove leading/trailing spaces and reduce multiple spaces. Example: ' hello world ' -> 'world hello'.\",\n", + " \"test\": 'assert reverse_words(\"hello world\")==\"world hello\"; assert reverse_words(\" hello world \")==\"world hello\"; assert reverse_words(\"a\")==\"a\"; print(\"PASS\")'\n", + " },\n", + " # MEDIUM\n", + " {\n", + " \"id\": \"two_sum\", \"difficulty\": \"medium\",\n", + " \"prompt\": \"Write a Python function `two_sum(nums: list[int], target: int) -> tuple[int, int]` that returns indices of two numbers that add up to target. Return indices in ascending order. Each input has exactly one solution.\",\n", + " \"test\": 'assert two_sum([2,7,11,15],9)==(0,1); assert two_sum([3,2,4],6)==(1,2); assert two_sum([3,3],6)==(0,1); print(\"PASS\")'\n", + " },\n", + " {\n", + " \"id\": \"balanced_parens\", \"difficulty\": \"medium\",\n", + " \"prompt\": \"Write a Python function `is_balanced(s: str) -> bool` that checks if a string has balanced parentheses, brackets, and braces ()[]{}. Ignore other characters.\",\n", + " \"test\": 'assert is_balanced(\"()[]{}\"); assert is_balanced(\"([{}])\"); assert not is_balanced(\"(]\"); assert not is_balanced(\"([)]\"); assert is_balanced(\"\"); print(\"PASS\")'\n", + " },\n", + " {\n", + " \"id\": \"group_anagrams\", \"difficulty\": \"medium\",\n", + " \"prompt\": 'Write a Python function `group_anagrams(words: list[str]) -> list[list[str]]` that groups anagrams together. Each group sorted alphabetically, groups sorted by first element.',\n", + " \"test\": 'r=[sorted(g) for g in group_anagrams([\"eat\",\"tea\",\"tan\",\"ate\",\"nat\",\"bat\"])]; r.sort(key=lambda g:g[0]); assert r==[[\"ate\",\"eat\",\"tea\"],[\"bat\"],[\"nat\",\"tan\"]]; print(\"PASS\")'\n", + " },\n", + " {\n", + " \"id\": \"matrix_spiral\", \"difficulty\": \"medium\",\n", + " \"prompt\": \"Write a Python function `spiral_order(matrix: list[list[int]]) -> list[int]` that returns all elements of a matrix in spiral order (clockwise from top-left).\",\n", + " \"test\": 'assert spiral_order([[1,2,3],[4,5,6],[7,8,9]])==[1,2,3,6,9,8,7,4,5]; assert spiral_order([[1,2],[3,4]])==[1,2,4,3]; assert spiral_order([[1]])==[1]; print(\"PASS\")'\n", + " },\n", + " {\n", + " \"id\": \"flatten_nested\", \"difficulty\": \"medium\",\n", + " \"prompt\": \"Write a Python function `flatten(lst) -> list` that deeply flattens a nested list. Example: flatten([1, [2, [3, 4], 5], 6]) -> [1, 2, 3, 4, 5, 6]. Do NOT use itertools.\",\n", + " \"test\": 'assert flatten([1,[2,[3,4],5],6])==[1,2,3,4,5,6]; assert flatten([])==[]; assert flatten([1,2,3])==[1,2,3]; assert flatten([[[[1]]]])==[1]; print(\"PASS\")'\n", + " },\n", + " # HARD\n", + " {\n", + " \"id\": \"lru_cache\", \"difficulty\": \"hard\", \"max_tokens\": 1500,\n", + " \"prompt\": \"\"\"Write a Python class `LRUCache` with:\n", + "- `__init__(self, capacity: int)` - Initialize with positive capacity.\n", + "- `get(self, key: int) -> int` - Return value if key exists, else -1. Marks as recently used.\n", + "- `put(self, key: int, value: int) -> None` - Update or insert. If over capacity, evict least recently used.\n", + "Both get and put must run in O(1) average time. Do NOT use functools.lru_cache or collections.OrderedDict.\"\"\",\n", + " \"test\": 'c=LRUCache(2); c.put(1,1); c.put(2,2); assert c.get(1)==1; c.put(3,3); assert c.get(2)==-1; c.put(4,4); assert c.get(1)==-1; assert c.get(3)==3; assert c.get(4)==4; print(\"PASS\")'\n", + " },\n", + " {\n", + " \"id\": \"merge_intervals\", \"difficulty\": \"hard\",\n", + " \"prompt\": \"Write a Python function `merge_intervals(intervals: list[list[int]]) -> list[list[int]]` that merges all overlapping intervals and returns sorted non-overlapping intervals.\",\n", + " \"test\": 'assert merge_intervals([[1,3],[2,6],[8,10],[15,18]])==[[1,6],[8,10],[15,18]]; assert merge_intervals([[1,4],[4,5]])==[[1,5]]; assert merge_intervals([])==[]; print(\"PASS\")'\n", + " },\n", + " {\n", + " \"id\": \"longest_substr\", \"difficulty\": \"hard\",\n", + " \"prompt\": \"Write a Python function `length_of_longest_substring(s: str) -> int` that returns the length of the longest substring without repeating characters. Use sliding window, O(n) time.\",\n", + " \"test\": 'assert length_of_longest_substring(\"abcabcbb\")==3; assert length_of_longest_substring(\"bbbbb\")==1; assert length_of_longest_substring(\"pwwkew\")==3; assert length_of_longest_substring(\"\")==0; print(\"PASS\")'\n", + " },\n", + "]\n", + "\n", + "print(f\"✓ {len(CHALLENGES)} challenges definidos\")\n", + "for d in [\"easy\", \"medium\", \"hard\"]:\n", + " n = sum(1 for c in CHALLENGES if c[\"difficulty\"] == d)\n", + " print(f\" {d}: {n}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Evaluando qwen2.5-coder-7b-abliterated-i1\n", + "======================================================================\n", + "\n", + "[fibonacci] (easy)... " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "✓ PASS 6461ms 81tok 12.5t/s\n", + "[palindrome] (easy)... " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "✓ PASS 2234ms 65tok 29.1t/s\n", + "[fizzbuzz] (easy)... " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "✓ PASS 3457ms 102tok 29.5t/s\n", + "[reverse_string] (easy)... " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "✓ PASS 999ms 28tok 28.0t/s\n", + "[two_sum] (medium)... " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "✓ PASS 2337ms 70tok 29.9t/s\n", + "[balanced_parens] (medium)... " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "✓ PASS 2982ms 88tok 29.5t/s\n", + "[group_anagrams] (medium)... " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "✓ PASS 4212ms 127tok 30.2t/s\n", + "[matrix_spiral] (medium)... " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "✓ PASS 6545ms 200tok 30.6t/s\n", + "[flatten_nested] (medium)... " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "✓ PASS 1579ms 46tok 29.1t/s\n", + "[lru_cache] (hard)... " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "✓ PASS 12730ms 356tok 28.0t/s\n", + "[merge_intervals] (hard)... " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "✓ PASS 4609ms 127tok 27.6t/s\n", + "[longest_substr] (hard)... " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "✓ PASS 3392ms 95tok 28.0t/s\n", + "\n", + "======================================================================\n", + "\n", + "Total: 12/12 passed (100%)\n" + ] + } + ], + "source": [ + "# ── Ejecutar evaluación ───────────────────────────────────\n", + "\n", + "results = []\n", + "\n", + "print(f\"Evaluando {MODEL}\")\n", + "print(f\"{'='*70}\\n\")\n", + "\n", + "for ch in CHALLENGES:\n", + " max_tok = ch.get(\"max_tokens\", 1024)\n", + " print(f\"[{ch['id']}] ({ch['difficulty']})...\", end=\" \", flush=True)\n", + " \n", + " resp = query_model(ch[\"prompt\"], max_tokens=max_tok)\n", + " code = extract_code(resp[\"content\"])\n", + " passed, error = run_python_test(code, ch[\"test\"])\n", + " \n", + " status = \"✓ PASS\" if passed else \"✗ FAIL\"\n", + " print(f\"{status} {resp['latency_ms']:.0f}ms {resp['completion_tokens']}tok {resp['tokens_per_second']:.1f}t/s\")\n", + " \n", + " results.append({\n", + " \"challenge\": ch[\"id\"],\n", + " \"difficulty\": ch[\"difficulty\"],\n", + " \"passed\": passed,\n", + " \"error\": error,\n", + " \"code\": code,\n", + " \"raw_response\": resp[\"content\"],\n", + " \"latency_ms\": resp[\"latency_ms\"],\n", + " \"completion_tokens\": resp[\"completion_tokens\"],\n", + " \"prompt_tokens\": resp[\"prompt_tokens\"],\n", + " \"tokens_per_second\": resp[\"tokens_per_second\"],\n", + " })\n", + "\n", + "print(f\"\\n{'='*70}\")\n", + "passed_total = sum(1 for r in results if r[\"passed\"])\n", + "print(f\"\\nTotal: {passed_total}/{len(results)} passed ({100*passed_total/len(results):.0f}%)\")" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " challenge difficulty status latency_s completion_tokens tok_s\n", + " fibonacci easy ✓ PASS 6.5 81 12.5\n", + " palindrome easy ✓ PASS 2.2 65 29.1\n", + " fizzbuzz easy ✓ PASS 3.5 102 29.5\n", + " reverse_string easy ✓ PASS 1.0 28 28.0\n", + " two_sum medium ✓ PASS 2.3 70 29.9\n", + "balanced_parens medium ✓ PASS 3.0 88 29.5\n", + " group_anagrams medium ✓ PASS 4.2 127 30.2\n", + " matrix_spiral medium ✓ PASS 6.5 200 30.6\n", + " flatten_nested medium ✓ PASS 1.6 46 29.1\n", + " lru_cache hard ✓ PASS 12.7 356 28.0\n", + "merge_intervals hard ✓ PASS 4.6 127 27.6\n", + " longest_substr hard ✓ PASS 3.4 95 28.0\n", + "\n", + "────────────────────────────────────────────────────────────\n", + "Velocidad promedio: 27.7 tok/s\n", + "Velocidad mediana: 29.1 tok/s\n", + "Rango: 12.5 - 30.6 tok/s\n", + "Latencia promedio: 4.3s\n", + "Tokens promedio: 115\n" + ] + } + ], + "source": [ + "# ── Tabla de resultados ───────────────────────────────────\n", + "\n", + "df = pd.DataFrame(results)\n", + "df[\"status\"] = df[\"passed\"].map({True: \"✓ PASS\", False: \"✗ FAIL\"})\n", + "df[\"latency_s\"] = (df[\"latency_ms\"] / 1000).round(1)\n", + "df[\"tok_s\"] = df[\"tokens_per_second\"].round(1)\n", + "\n", + "display_cols = [\"challenge\", \"difficulty\", \"status\", \"latency_s\", \"completion_tokens\", \"tok_s\"]\n", + "print(df[display_cols].to_string(index=False))\n", + "\n", + "print(f\"\\n{'─'*60}\")\n", + "print(f\"Velocidad promedio: {df['tokens_per_second'].mean():.1f} tok/s\")\n", + "print(f\"Velocidad mediana: {df['tokens_per_second'].median():.1f} tok/s\")\n", + "print(f\"Rango: {df['tokens_per_second'].min():.1f} - {df['tokens_per_second'].max():.1f} tok/s\")\n", + "print(f\"Latencia promedio: {df['latency_ms'].mean()/1000:.1f}s\")\n", + "print(f\"Tokens promedio: {df['completion_tokens'].mean():.0f}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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kJAQI3fu3Ma+ffuStfnll18aTk5O5n1etmxZirlFSrZv325IMr799ttH1gUAZEzW7in/7d69e0Z8fLxF2ZUrV4y8efMaHTt2NJdduHDB6jWwVq1aRqlSpYzbt2+byxITE42qVasaAQEByeKpXbu2+bpuGIbRp08fw87Oznwdv3r1quHq6mpUrlzZ+Oeffyy29e/1Hrw3NozUXeetefHFF43g4OBk5WXKlDEaNGjw0HVTewzeffddw2QyWVy3L126ZHh6eia7D7d2vAsVKmS0a9fO/D21x/X8+fOGvb290aBBA4t6H3zwgSHJos3U5iVp6Wfq2rWr4eTklKq6yPiYzgU2Ubt2bXl7e8vX11ctW7aUi4uLli1bpgIFCki6/6h1kitXrujatWuqXr269u7day5Pmjf7hx9+sPpItYeHh/7880/t2rXrseL8+OOP5e3trXz58plHiX322Wd67bXXLOr9O95r167p4sWLCgkJ0fHjx3Xt2rVHbuf7779X9erVlStXLl28eNH8qV27thISErRly5ZHtpE/f36Lv3a7ubmpbdu22rdvn86ePSvp/hyhlSpV0osvvmiu5+Lioq5du+rkyZM6cOCARZvt2rWz2Lf/wsXFRZJ0/fr1/9zWkiVLZDKZ9PHHHydb9rRf2OHg4KBs2e7/6kxISNClS5fMUwn9+9/n6tWr5ePjY/FvJWfOnOratetTjQ8A8Gh2dnZq2bKlduzYYfEI8YIFC5Q3b17VqlVL0uNfnxMSErR+/Xo1adJEhQsXNpf7+PjojTfe0LZt28xTpC1ZskRlypRJcdS1tWvamTNntH//frVr107u7u7m8jp16igoKChZ/dTkVUnvLenZs6fFur17904xhgddunRJUvKn9R4mrXnJtWvX9PLLL+vQoUOKjIxU2bJlU2yzRo0a5n1OyhdXrlypu3fvPjSepNiTptEBAGROdnZ25qesExMTdfnyZd27d08VKlSwuDZac/nyZf30009q0aKFrl+/bs4PLl26pLCwMB09elR//fWXxTpdu3a1uK5Xr15dCQkJOnXqlKT7U9Vev35dAwcOlKOjo8W6j7rHTc113ppLly6leO328PDQH3/8oaNHj6a4XlqOwdq1a1WlShWL67anp+cTef/Mo47rxo0bdefOnWQv90wpv0ltXpKWfqZcuXLpn3/+0a1btx53F5GB0IkOm5gyZYo2bNigTZs26cCBAzp+/LjCwsLMy1euXKkXXnhBjo6O8vT0ND9K9e8O6ddff13VqlVT586dlTdvXrVs2VLfffedRYf6gAED5OLiokqVKikgIEDdu3dP06M0Xbt21YYNG/S///1Pffr00T///KOEhIRk9aKiolS7dm05OzvLw8ND3t7e5rnZU9OJfvToUa1du1be3t4Wn6R5yVKas/VBRYoUSXZxLVq0qKT/m4bm1KlTKlasWLJ1AwMDzcv/zd/f/5HbTa0bN25IklxdXf9zWzExMcqfP788PT3/c1tplZiYqPHjxysgIEAODg7KnTu3vL299euvv1qc61OnTqV4TlI6/gCA9Jd045Y0f+Wff/6prVu3qmXLluYXeD7u9fnChQu6deuW1WtuYmKiTp8+Len+NS2tU4ckXa8DAgKSLUtpm6nJq06dOqVs2bIlm0otrdctIw3ziac1L+ndu7d27dqljRs3pvjS0Lt372rDhg0Wj66HhISoWbNmGjZsmHLnzq3GjRtrzpw5Kb6jJCn2p/0HeQCA7UVERKh06dLm+b69vb21atWqVN2/Hzt2TIZhaPDgwclyhKSBXg/mCAULFrT4ntRxfeXKFUn/N8Xt40wnlprr/MOkdO0ePny4rl69qqJFi6pUqVJ6//339euvv5qXp+UYJN0bPyilsrR61HG1ljN5e3sn++NBavOStPQzkVtkLsyJDpuoVKmS1Xmrt27dqldeeUUvvfSSpk6dKh8fH+XIkUNz5syxeFGDk5OTtmzZok2bNmnVqlVau3atvv32W9WsWVPr16+XnZ2dAgMDdfjwYa1cuVJr167VkiVLNHXqVA0ZMkTDhg17ZJwBAQHmG+WGDRvKzs5OAwcOVI0aNczxx8TEqFatWipevLg+//xz+fr6yt7eXqtXr9b48eNT9eKxxMRE1alTR/37909xeVJneHp7UqPQJen333+XnZ3dE+2YfxhrF6mU/giSFqNHj9bgwYPVsWNHjRgxQp6ensqWLZt69+6dqnMNAMgYgoODVbx4cS1cuFAffPCBFi5cKMMwLEZFZdTrc1qkNq/6r5Lea5N00/o0NG7cWIsWLdKYMWP09ddfm58MS5I0wr9+/frmMpPJpMWLF+vnn3/W//73P61bt04dO3bUZ599pp9//tn8pNy/Y7c2Dz0AIHP45ptv1L59ezVp0kTvv/++8uTJIzs7O4WHh5s7sx8m6b6vX79+FoMB/+3BDuKkP9A/KC1/fE7Jf73Oe3l5pXjtfumllxQTE6MffvhB69ev1+zZszV+/HhNnz5dnTt3fqxj8F9Yu49/Wsf1YdLSz3TlyhXlzJnzifatwHboREeGs2TJEjk6OmrdunUWL5qYM2dOsrrZsmVTrVq1VKtWLX3++ecaPXq0PvzwQ23atMnc+e3s7KzXX39dr7/+uu7cuaOmTZtq1KhRGjRoULLHpB7lww8/1KxZs/TRRx9p7dq1kqT//e9/io+P14oVKyz+CvrvN3snsdax+/zzz+vGjRvJ3oidFkl/Cf73No4cOSJJ5rd3FypUSIcPH0627qFDh8zLn4bY2Fht3rxZVapUeSIj0Z9//nmtW7dOly9ftjoaPemvylevXrUof3BUmzXWztXixYtVo0YNffnllxblV69etbjpLlSokH7//fdk5ySl4w8AsI3WrVtr8ODB+vXXX7VgwQIFBARYvKTyca/P3t7eypkzp9VrbrZs2eTr62vexu+//56m9pOu1yk9Yv3gNlObVxUqVEiJiYmKiYmxGIWV2utW8eLFJUknTpxItszaNTWteUmTJk308ssvq3379nJ1ddW0adMslq9atUpBQUHmvOffXnjhBb3wwgsaNWqUFixYoNatW2vRokXq3LmzuU5S7EkjzgAAmdPixYtVuHBhLV261OIa9eB0odauX0lTteXIkeM/3cP/W9KTYL///nuaOp/T0n+SkuLFi2vJkiUpLvP09FSHDh3UoUMH3bhxQy+99JKGDh2qzp07p+kYFCpUSMeOHUtWnlJZrly5kt3D37lzR2fOnEnV/qS0bel+zvTvKfYuXLiQ7I8HaclLUtvPdOLECfKKTITpXJDh2NnZyWQyWfyl8eTJk1q+fLlFvcuXLydbN2mOraRHdJPm50xib2+voKAgGYbxyHkxU+Lh4aFu3bpp3bp12r9/vzleyfIvndeuXUvxouXs7JzsgiBJLVq00I4dO7Ru3bpky65evap79+49Mra///5by5YtM3+Pi4vT119/rbJlyypfvnySpPr16+uXX37Rjh07zPVu3rypmTNnys/PL8V5VP+ry5cvq1WrVkpISNCHH374RNps1qyZDMNI8WmCpPPg5uam3LlzJ5uvdurUqanahrVzZWdnl+yv2t9//32yOe/q16+vv//+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AAAAAAAAAMAKOtEBAAAAAAAAALCCTnQAAAAAAAAAAKygEx0AgCzOz89PEyZMsHUY/0n79u3VpEkTW4cBAECmQG4AAICl7LYOAAAA2NauXbvk7Oyc6vqRkZGqUaOGrly5Ig8Pj6cXGAAAsAlyAwAALNGJDgBABnXnzh3Z29s/9e14e3s/9W2kxDAMJSQkKHt20hEAAFKD3AAAANtgOhcAAB5DaGio3n33XfXu3Vu5cuVS3rx5NWvWLN28eVMdOnSQq6urihQpojVr1pjX+f3331WvXj25uLgob968atOmjS5evGjRZo8ePdS7d2/lzp1bYWFhkqQVK1YoICBAjo6OqlGjhiIiImQymXT16lXzutu2bVP16tXl5OQkX19f9ezZUzdv3kzVvjz4yLbJZNLs2bP16quvKmfOnAoICNCKFSskSSdPnlSNGjUkSbly5ZLJZFL79u0lSYmJiQoPD5e/v7+cnJxUpkwZLV682NxuZGSkTCaT1qxZo+DgYDk4OOirr76SyWTSoUOHLGIaP368nn/+eUlSQkKCOnXqZG63WLFimjhx4kP3afHixSpVqpScnJzk5eWl2rVrp/p4AADwOMgNyA0AAJkXnegAADymiIgI5c6dW7/88oveffddvf3222revLmqVq2qvXv36uWXX1abNm1069YtXb16VTVr1lS5cuW0e/durV27VufOnVOLFi2StWlvb6+oqChNnz5dJ06c0GuvvaYmTZooOjpa3bp104cffmixTkxMjOrWratmzZrp119/1bfffqtt27apR48ej71vw4YNU4sWLfTrr7+qfv36at26tS5fvixfX18tWbJEknT48GGdOXPGfNMaHh6ur7/+WtOnT9cff/yhPn366M0339TmzZst2h44cKDGjBmjgwcP6rXXXlOFChU0f/58izrz58/XG2+8Ien+Dfhzzz2n77//XgcOHNCQIUP0wQcf6Lvvvksx9jNnzqhVq1bq2LGjDh48qMjISDVt2lSGYTz28QAAIDXIDcgNAACZk8ngqqG4uDi5u7vr2rVrcnNzS/ftl9nTN923mVFEB39u6xBsgnOeNXHe09/T/P0eGhqqhIQEbd26VdL9EVHu7u5q2rSpvv76a0nS2bNn5ePjox07dmjjxo3aunWr1q1bZ27jzz//lK+vrw4fPqyiRYsqNDRUcXFx2rt3r7nOwIEDtWrV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N/pfLVq0SP369VOnTp20fv167d+/Xx06dEj2crMHH2U2mUzmF3vdvHlTYWFhcnNz0/z587Vr1y4tW7ZMUtpfkubk5CSTyWRR1q5dO+3fv18TJ07U9u3btX//fnl5eT00xqQ2UipLinvo0KH6448/1KBBA/30008KCgoyx50SBwcHubm5WXwAAPgvyA0ejdwAAPCsyNCd6JLUsGFD/fbbb7p9+7YOHjxofnwsiclk0vDhw3X27Fndvn1bGzduVNGiRW0ULQAgsylcuLBy5MihXbt2mcuuXbumI0eOPHS9wMBARUVFWZRFRUWpaNGi5pFd3t7eOnPmjHn50aNHdevWrWRt/fzzz+af7927pz179igwMPCRsUdFRalq1ap65513VK5cORUpUuSRo64edOjQIV26dEljxoxR9erVVbx48WQvDitWrFiyF3P9+3g9KsaePXuqfv365hetXbx4MU0xWlO0aFH16dNH69evV9OmTTVnzpwn0i4AIGsjNyA3AABkPRm+Ex0AAFtydXVVu3bt9P7772vTpk36448/1KlTJ2XLli3ZyKl/e++99/Tjjz9qxIgROnLkiCIiIvTFF1+oX79+5jo1a9bUF198oX379mn37t166623UnzB1ZQpU7Rs2TIdOnRI3bt315UrVyzmIrUmICBAu3fv1rp163TkyBENHjw41TewSQoWLCh7e3tNnjxZx48f14oVKzRixAiLOt26ddOhQ4c0YMAAHTlyRN9995355WMPO0ZJMc6bN08HDx7Uzp071bp1azk5OaUpxgf9888/6tGjhyIjI3Xq1ClFRUVp165dqepcAADgUcgNyA0AAFkPnegAADzC559/ripVqqhhw4aqXbu2qlWrpsDAwIdOHVa+fHl99913WrRokUqWLKkhQ4Zo+PDhFi8O++yzz+Tr66vq1avrjTfeUL9+/ZQzZ85kbY0ZM0ZjxoxRmTJltG3bNq1YsUK5c+d+ZNzdunVT06ZN9frrr6ty5cq6dOmS3nnnnTTtu7e3t+bOnavvv/9eQUFBGjNmjMaNG2dRx9/fX4sXL9bSpUtVunRpTZs2TR9++KEkPfJF3l9++aWuXLmi8uXLq02bNurZs6fy5MmTphgfZGdnp0uXLqlt27YqWrSoWrRooXr16vFyMADAE0NuQG4AAMhaTMaDE65lQXFxcXJ3d9e1a9dsMs9ZmT19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OteuXdOgQYPk6+srDw8Pde3aVefOnTMpce7dybG2bNky23V9/vnnTUqcewsWLFBwcLC8vLzk5eWl0NBQ/fe//7Uut5drCvthz22DO3ntsSczZsyQxWJReHi42VHyzP/+9z89/fTT8vX1lbu7u4KCgrR3716zY+WZzMxMTZw4Uffdd5/c3d1VpUoVTZs2TYX1Fo/23la93fFlZGRo7NixCgoKUvHixVWuXDn16tVLZ86cMS/wXaCIDgAA8P99/vnnGjFihCZPnqzY2FjVrVtXbdu21fnz582Oludq166tpKQk6+P77783O1KeSEtLU926dTV//vxbLp85c6bmzZun9957T7t27VLx4sXVtm1bXbt27R4n/Wf+7jglqV27djbXeNmyZfcwYd6Ijo7WoEGDtHPnTm3atEkZGRl6+OGHlZaWZl1n+PDhWrt2rb744gtFR0frzJkz6tKli4mpc+dOjlWSBgwYYHNdZ86caVLi3KtQoYJmzJihmJgY7d27V61atVKnTp30008/SbKfawr7YO9tgzt97bEHe/bs0X/+8x8FBwebHSXPXLp0Sc2aNVPRokX13//+Vz///LNmz56tkiVLmh0tz7z++utasGCB3nnnHR06dEivv/66Zs6cqbffftvsaLli723V2x3f1atXFRsbq4kTJyo2NlYrV65UfHy8OnbsaELSXDDgUAICAoypU6caJ06cMDsKAAAFTuPGjY1BgwZZpzMzM41y5coZERERJqbKe5MnTzbq1q1rdox8J8n46quvrNNZWVmGn5+fMWvWLOu8y5cvG66ursayZctMSJg3/nqchmEYvXv3Njp16mRKnvx0/vx5Q5IRHR1tGMaN61e0aFHjiy++sK5z6NAhQ5KxY8cOs2Lmib8eq2EYRosWLYxhw4aZFyoflSxZ0vjwww/t+pqicHKUtsFNt3rtsQdXrlwxqlWrZmzatMmuXkvHjh1rPPjgg2bHyFf//ve/jX79+tnM69Kli9GzZ0+TEuUde2+r3qqN+le7d+82JBWKOiU90R1MeHi4Vq5cqcqVK6tNmzb67LPPdP36dbNjIZ9du3ZNs2bNUvv27RUSEqIGDRrYPGAf5s2bd8cPANmlp6crJiZGrVu3ts5zcnJS69attWPHDhOT5Y+jR4+qXLlyqly5snr27KmTJ0+aHSnfJSYm6uzZszbX2NvbW02aNLHL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sIsb5gAAAAAAAJiFIrqDqV27tt577z39+9//1qZNmzRt2jRJ0pkzZ+Tr62tyOuSXbdu2mR0B91ivXr109epV1a1bVy4uLnJ3d7dZfvHiRZOSAQAAAAAAFC4U0R3M66+/rscee0yzZs1S7969rTeaXLNmjXWYF9ifFi1amB0B99ibb75pdgQAAAAAAAC7YDEMwzA7BO6tzMxMpaSkqGTJktZ5x48fV7FixVSmTBkTkyG/fPvtt7dd3rx583uUBAAAAAAAAChcKKIDDsDJKfs9hC0Wi/VnxkS3b9euXVN6errNPC8vL5PSAAAAAAAAFC4M5+KAvvzySy1fvlwnT57MVliLjY01KRXy06VLl2ymMzIytG/fPk2cOFHTp083KRXyU1pamsaOHavly5frwoUL2ZbzjxMAAAAAAIA7k717KuzavHnz1LdvX5UtW1b79u1T48aN5evrq2PHjumRRx4xOx7yibe3t82jVKlSatOmjV5//XWNGTPG7HjIB2PGjNHWrVu1YMECubq66sMPP9TUqVNVrlw5LV682Ox4AOBQWrZsqfDwcLNj2IXjx4/LYrEoLi7O7CgAAOAWaPfAXlFEdzDvvvuu3n//fb399ttycXHRmDFjtGnTJg0dOlTJyclmx8M9VrZsWcXHx5sdA/lg7dq1evfdd9W1a1cVKVJEDz30kF5++WW99tprWrJkidnxAKDQKswfDPv27auXX37Z7BgAAABAocNwLg7m5MmTatq0qSTJ3d1dV65ckSQ988wzeuCBB/TOO++YGQ/55Mcff7SZNgxDSUlJmjFjhurVq2dOKOSrixcvqnLlypJujH9+8eJFSdKDDz6oF154wcxoAAATZGZmat26dfr666/NjgIAAAAUOvREdzB+fn7WYlqlSpW0c+dOSVJiYqK4x6z9qlevnurXr6969epZf27fvr3S09P14Ycfmh0P+aBy5cpKTEyUJNWoUUPLly+XdKOHeokSJUxMBgCFV58+fRQdHa233npLFotFFotFx48fV3R0tBo3bixXV1f5+/tr3Lhx+uOPP3Lcztdffy1vb2/rN4NOnTqlbt26qUSJEvLx8VGnTp10/Phxm/127txZb7zxhvz9/eXr66tBgwYpIyPDus67776ratWqyc3NTWXLltXjjz9us88ffvhBRYsWVaNGjZSenq7BgwfL399fbm5uCggIUEREhHXdy5cv69lnn1Xp0qXl5eWlVq1aaf/+/Tbbe/XVV1WmTBl5enrq2Wef1bhx42z+MX+rHvudO3dWnz59rNOBgYF67bXX1K9fP3l6eqpSpUp6//33bZ6ze/du1a9fX25ubgoJCdG+ffuync+7Pf8AABQGX375pYKCguTu7i5fX1+1bt1aaWlpkqQPP/xQNWvWlJubm2rUqKF3333X5rk//PCD6tWrZ33/XLVqlc1waJGRkdk+F95c56YpU6aoXr16+uSTTxQYGChvb289+eST1s6Y0o17cfXq1UseHh7y9/fX7Nmzsx3HpUuX1KtXL5UsWVLFihXTI488oqNHj1qXnzhxQh06dFDJkiVVvHhx1a5dW+vXr/+npw/IcxTRHUyrVq20Zs0aSTe+0jt8+HC1adNG3bt312OPPWZyOuSXxMREHTt2TImJiUpMTNSJEyd09epV/fDDD6pRo4bZ8ZAP+vbtay14jBs3TvPnz5ebm5uGDx+u0aNHm5wOAAqnt956S6GhoRowYICSkpKUlJSkokWLqn379mrUqJH279+vBQsWaOHChXr11VdvuY2lS5eqR48eWrJkiXr27KmMjAy1bdtWnp6e+u6777R9+3Z5eHioXbt2NjeA37ZtmxISErRt2zYtWrRIkZGRioyMlCTt3btXQ4cO1SuvvKL4+Hht2LBBzZs3t9nvmjVr1KFDB1ksFs2bN09r1qzR8uXLFR8fryVLligwMNC67hNPPKHz58/rv//9r2JiYtSgQQOFhYVZO2IsWbJE06dP1+uvv66YmBhVqlRJCxYsyNU5nT17trU4/uKLL+qFF16wDjWXmpqqRx99VLVq1VJMTIymTJmiUaNG2Tz/f//7312dfwAACoOkpCT16NFD/fr106FDhxQVFaUuXbrIMAwtWbJEkyZN0vTp03Xo0CG99tprmjhxohYtWiRJSklJUYcOHRQUFKTY2FhNmzZNY8eOzVWOhIQErVq1SuvWrdO6desUHR2tGTNmWJePHj1a0dHRWr16tTZu3KioqCjFxsbabKNPnz7au3ev1qxZox07dsgwDLVv397aGWDQoEG6fv26vv32Wx04cECvv/66PDw8cnnmgHxkwKFkZmYaGRkZ1unPPvvMGDJkiDFv3jzj+vXrJiYDkJ+OHz9urFixwti/f7/ZUQCgUGvRooUxbNgw6/SECROM6tWrG1lZWdZ58+fPNzw8PIzMzEyb57zzzjuGt7e3ERUVZV33k08+yfb869evG+7u7sY333xjGIZh9O7d2wgICDD++OMP6zpPPPGE0b17d8MwDGPFihWGl5eXkZKSkmPuatWqGevWrTMMwzCGDBlitGrVymafN3333XeGl5eXce3aNZv5VapUMf7zn/8YhmEYTZo0MQYNGmSzvFmzZkbdunVzPE+GYRidOnUyevfubZ0OCAgwnn76aet0VlaWUaZMGWPBggWGYRjGf/7zH8PX19f4/fffressWLDAkGTs27fPMIw7O/8AABQ2MTExhiTj+PHj2ZZVqVLFWLp0qc28adOmGaGhoYZh3Hiv/Ov75wcffGDz/vnxxx8b3t7eNtv46quvjD+XCSdPnmwUK1bMpn0xevRoo0mTJoZhGMaVK1cMFxcXY/ny5dblFy5cMNzd3a1tgCNHjhiSjO3bt1vX+e233wx3d3fr84KCgowpU6bc6akBTMOY6A7GyclJ27dv13/+8x8dO3ZMX3zxhbp3767Fixdr9+7devDBB82OiDwyb948DRw4UG5ubpo3b95t1x06dOg9SoV7acuWLdqyZYvOnz+vrKwsm2UfffSRSakAwL4cOnRIoaGhNl9/btasmVJTU3X69GlVqlRJ0o2vZJ8/f17bt29Xo0aNrOvu379fv/zyizw9PW22e+3aNSUkJFina9euLWdnZ+u0v7+/Dhw4IElq06aNAgICVLlyZbVr107t2rXTY489pmLFilkznjlzRmFhYZJu9Ahr06aNqlevrnbt2unRRx/Vww8/bM2TmpoqX19fmzy///67NU98fLxefPFFm+WNGzfW1q1b7/r8BQcHW3+2WCzy8/PT+fPnrbmDg4Pl5uZmXSc0NNTm+Xd6/gEAKEzq1q2rsLAwBQUFqW3btnr44Yf1+OOPy8XFRQkJCerfv78GDBhgXf+PP/6Qt7e3pBvv0399/2zcuHGucgQGBtq0Ufz9/a3v0wkJCUpPT1eTJk2sy318fFS9enXr9KFDh1SkSBGbdXx9fVW9enUdOnRI0o16xAsvvKCNGzeqdevW6tq1q037ACgoKKI7mBUrVuiZZ55Rz549FRsbq+vXr0u68XWf1157jXGn7MjcuXPVs2dPubm5ae7cuTmuZ7FYKKLboalTp+qVV15RSEiI/P39bYoLAIB7r379+oqNjdVHH32kkJAQ6+tyamqqGjZsaB0f/c9Kly5t/blo0aI2yywWi/UfpJ6enoqNjVVUVJQ2btyoSZMmacqUKdqzZ49KlCihNWvWqE2bNtYP0w0aNFBiYqL++9//avPmzerWrZtat26tL7/8UqmpqfL391dUVFS2PHdzTw0nJ6ds99v58xjud3JcAAA4KmdnZ23atEk//PCDNm7cqLffflsvvfSS1q5dK0n64IMPbArTN59zpwrS+/Szzz6rtm3b6uuvv9bGjRsVERGh2bNna8iQIXm6H+CfYkx0B/Pqq6/qvffe0wcffGDzYtisWbNs41ahcEtMTLT2Irs5FvqtHseOHTM5KfLDe++9p8jISO3atUurVq3SV199ZfMAAOSOi4uLMjMzrdM1a9a0ju950/bt2+Xp6akKFSpY51WpUkXbtm3T6tWrbT4UNmjQQEePHlWZMmVUtWpVm8fNHmV3okiRImrdurVmzpypH3/8UcePH7f2DF+9erU6depks76Xl5e6d++uDz74QJ9//rlWrFihixcvqkGDBjp79qyKFCmSLU+pUqUkSdWrV9eePXtstvfX6dKlSyspKck6nZmZqYMHD97x8Ug3zu2PP/6oa9euWeft3Lkz2zp3cv4BAChsLBaLmjVrpqlTp2rfvn1ycXHR9u3bVa5cOR07dizb+/R9990n6cb79IEDB6ydJqVbv09fuXLFeqNSSdabjt6pKlWqqGjRotq1a5d13qVLl3TkyBHrdM2aNfXHH3/YrHPhwgXFx8erVq1a1nkVK1bU888/r5UrV2rkyJH64IMP7ioLcC9QRHcw8fHx2W40JUne3t66fPnyvQ8EIF+kp6eradOmZscAALsTGBioXbt26fjx4/rtt9/04osv6tSpUxoyZIgOHz6s1atXa/LkyRoxYoScnGyb2vfff7+2bdumFStWKDw8XJLUs2dPlSpVSp06ddJ3332nxMRERUVFaejQoTp9+vQdZVq3bp3mzZunuLg4nThxQosXL1ZWVpaqV6+u8+fPa+/evXr00Uet68+ZM0fLli3T4cOHdeTIEX3xxRfy8/NTiRIl1Lp1a4WGhqpz587auHGjjh8/rh9++EEvvfSS9u7dK0kaMmSIFi5cqEWLFuno0aN69dVX9eOPP9p866lVq1b6+uuv9fXXX+vw4cN64YUX7rqt+dRTT8lisWjAgAH6+eeftX79er3xxhs269zN+QcAoLDYtWuXXnvtNe3du1cnT57UypUr9euvv6pmzZqaOnWqIiIiNG/ePB05ckQHDhzQxx9/rDlz5ki68f6ZlZWlgQMH6tChQ/rmm2+s758336ubNGmiYsWKacKECUpISNDSpUutNyy/Ux4eHurfv79Gjx6trVu36uDBg+rTp4/N+2+1atXUqVMnDRgwQN9//73279+vp59+WuXLl7f+gz88PFzffPONEhMTFRsbq23btqlmzZp5cBaBvMVwLg7Gz89Pv/zyiwIDA23mf//996pcubI5oZAvRowYccfr3nyzhf149tlntXTpUk2cONHsKABgV0aNGqXevXurVq1a+v3335WYmKj169dr9OjRqlu3rnx8fNS/f3+9/PLLt3x+9erVtXXrVrVs2VLOzs6aPXu2vv32W40dO1ZdunTRlStXVL58eYWFhcnLy+uOMpUoUUIrV67UlClTdO3aNVWrVk3Lli1T7dq1tXDhQjVu3Njai1y6MfzLzJkzdfToUTk7O6tRo0Zav3699UPv+vXr9dJLL6lv37769ddf5efnp+bNm6ts2bKSbhT+jx07plGjRunatWvq1q2b+vTpo927d1v30a9fP+3fv1+9evVSkSJFNHz4cP3rX/+6q3Pt4eGhtWvX6vnnn1f9+vVVq1Ytvf766+ratat1nfLly9/V+QcAoDDw8vLSt99+qzfffFMpKSkKCAjQ7Nmz9cgjj0iSihUrplmzZmn06NEqXry4goKCrP+g9/Ly0tq1a/XCCy+oXr16CgoK0qRJk/TUU09Zh3bz8fHRp59+qtGjR+uDDz5QWFiYpkyZooEDB95VzlmzZik1NVUdOnSQp6enRo4cqeTkZJt1Pv74Yw0bNkyPPvqo0tPT1bx5c61fv946OkJmZqYGDRqk06dPy8vLS+3atbvtkLSAWSzGXwdBgl2LiIjQp59+qo8++kht2rTR+vXrdeLECQ0fPlwTJ05kzCk78tcPqrGxsfrjjz+sN/k4cuSInJ2d1bBhw1zdCAwFz5//cZKVlaVFixYpODhYwcHB2cay4x8nAOAYOnbsqAcffFBjxozJ1/20adNGfn5++uSTT/J1PwAA4O4tWbJEffv2VXJystzd3c2OAxRK9ER3MOPGjVNWVpbCwsJ09epVNW/eXK6urho1ahQFdDuzbds2689z5syRp6enFi1apJIlS0q6MVZZ37599dBDD5kVEXls3759NtP16tWTpGxj0HKTUQBwHA8++KB69OiRp9u8evWq3nvvPbVt21bOzs5atmyZNm/erE2bNuXpfgAAQO4sXrxYlStXVvny5bV//36NHTtW3bp1o4AO/AP0RHdQ6enp+uWXX5SamqpatWrJw8PD7EjIR+XLl9fGjRtVu3Ztm/kHDx7Uww8/rDNnzpiUDAAAFDa///67OnTooH379unatWuqXr26Xn75ZXXp0sXsaAAAQNLMmTP17rvv6uzZs/L391fnzp01ffp0FStWzOxoQKFFER1wAJ6enlq7dq1atmxpM3/btm3q2LGjrly5Yk4wAAAAAAAAoIDjlvWAA3jsscfUt29frVy5UqdPn9bp06e1YsUK9e/fn15jAAAAAAAAwG3QEx1wAFevXtWoUaP00UcfKSMjQ5JUpEgR9e/fX7NmzVLx4sVNTggAAAAAAAAUTBTRAQeSlpamhIQESVKVKlUongMAAAAAAAB/g+FcAAeSlJSkpKQkVatWTcWLFxf/QwMAAAAAAABujyI64AAuXLigsLAw3X///Wrfvr2SkpIkSf3799fIkSNNTgcAAAAAAAAUXBTRAQcwfPhwFS1aVCdPnlSxYsWs87t3764NGzaYmAwAAAAAAAAo2IqYHQBA/tu4caO++eYbVahQwWZ+tWrVdOLECZNSAQAAAAAAAAUfPdEBB5CWlmbTA/2mixcvytXV1YREAAAAAAAAQOFAER1wAA899JAWL15snbZYLMrKytLMmTP1r3/9y8RkAAAAAAAAQMFmMQzDMDsEgPx18OBBhYWFqUGDBtq6das6duyon376SRcvXtT27dtVpUoVsyMCAAAAAAAABRJFdMBBXL58WfPnz9f+/fuVmpqqBg0aaNCgQfL39zc7GgAAAAAAAFBgUUQHHMS1a9f0448/6vz588rKyrJZ1rFjR5NSAQAAAAAAAAVbEbMDAMh/GzZs0DPPPKOLFy/qr/83s1gsyszMNCkZAAAAAAAAULBxY1HAAQwZMkTdunXTmTNnlJWVZfOggA4AAAAAAADkjOFcAAfg5eWlffv2cQNRAAAAAAAA4C7REx1wAI8//riioqLMjgEAAAAAAAAUOvREBxzA1atX9cQTT6h06dIKCgpS0aJFbZYPHTrUpGQAAAAAAABAwUYRHXAACxcu1PPPPy83Nzf5+vrKYrFYl1ksFh07dszEdAAAAAAAAEDBRREdcAB+fn4aOnSoxo0bJycnRnECAAAAAAAA7hTVNMABpKenq3v37hTQAQAAAAAAgLtERQ1wAL1799bnn39udgwAAAAAAACg0ClidgAA+S8zM1MzZ87UN998o+Dg4Gw3Fp0zZ45JyQAAAAAAAICCjTHRAQfwr3/9K8dlFotFW7duvYdpAAAAAAAAgMKDIjoAAAAAAAAAADlgTHQAAAAAAAAAAHJAER0AAAAAAAAAgBxQRAcAAAAAAAAAIAcU0QEAAAAAAAAAyAFFdKAAatmypcLDwyVJgYGBevPNN63Lzp49qzZt2qh48eIqUaJEjvMsFotWrVqVL5kAAAAAAAAAR1HE7AAAbm/Pnj0qXry4dXru3LlKSkpSXFycvL29c5yXlJSkkiVL5luuwMBAhYeHU1gHAAAAAACAXaOIDhRwpUuXtplOSEhQw4YNVa1atdvO8/Pzu2cZAQAAAAAAAHvFcC6AydLS0tSrVy95eHjI399fs2fPtln+5+FcAgMDtWLFCi1evFgWi0V9+vS55Twp+3Aup0+fVo8ePeTj46PixYsrJCREu3btkiT16dNHnTt3ttlveHi4WrZsecvMLVu21IkTJzR8+HBZLBZZLBalpaXJy8tLX375pc26q1atUvHixXXlypVcnyMAAAAAAADALPREB0w2evRoRUdHa/Xq1SpTpowmTJig2NhY1atXL9u6e/bsUa9eveTl5aW33npL7u7uSk9Pzzbvr1JTU9WiRQuVL19ea9askZ+fn2JjY5WVlZWrzCtXrlTdunU1cOBADRgwQJJUvHhxPfnkk/r444/1+OOPW9e9Oe3p6ZmrfQEAAAAAAABmoogOmCg1NVULFy7Up59+qrCwMEnSokWLVKFChVuuX7p0abm6usrd3d1muJZbzfuzpUuX6tdff9WePXvk4+MjSapatWquc/v4+MjZ2Vmenp42+3z22WfVtGlTJSUlyd/fX+fPn9f69eu1efPmXO8LAAAAAAAAMBPDuQAmSkhIUHp6upo0aWKd5+Pjo+rVq+fpfuLi4lS/fn1rAT2/NG7cWLVr19aiRYskSZ9++qkCAgLUvHnzfN0vAAAAAAAAkF8oogMO4FZDvPyZk5OTDMOwmZeRkZGrfT377LOKjIyUdGMol759+8piseRqWwAAAAAAAIDZKKIDJqpSpYqKFi1qvcGnJF26dElHjhzJ0/0EBwcrLi5OFy9evOXy0qVLKykpyWZeXFzcbbfp4uKizMzMbPOffvppnThxQvPmzdPPP/+s3r175zo3AAAAAAAAYDaK6ICJPDw81L9/f40ePVpbt27VwYMH1adPHzk55e2fZo8ePeTn56fOnTtr+/btOnbsmFasWKEdO3ZIklq1aqW9e/dq8eLFOnr0qCZPnqyDBw/edpuBgYH69ttv9b///U+//fabdX7JkiXVpUsXjR49Wg8//HCO47sDAAAAAAAAhQFFdMBks2bN0kMPPaQOHTqodevWevDBB9WwYcM83YeLi4s2btyoMmXKqH379goKCtKMGTPk7OwsSWrbtq0mTpyoMWPGqFGjRrpy5Yp69ep1222+8sorOn78uKpUqaLSpUvbLOvfv7/S09PVr1+/PD0OAAAAAAAA4F6zGH8dCBkA/qFPPvlEw4cP15kzZ+Ti4mJ2HAAAAAAAACDXipgdAID9uHr1qpKSkjRjxgw999xzFNABAAAAAABQ6DGcC4A8M3PmTNWoUUN+fn4aP3682XEAAAAAAACAf4zhXAAAAAAAAAAAyAE90QEAAAAAAAAAyAFFdAAAAAAAAAAAckARHQAAAAAAAACAHFBEBwAAAAAAAAAgBxTRAQAAAAAAAADIAUV0AAAAAAAAAAByQBEdAAAAAAAAAIAcUEQHAAAAAAAAACAHFNEBAAAAAAAAAMjB/wNEtuG1hRGzDgAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data", + "transient": {} + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "✓ Gráfico guardado en data/eval_results.png\n" + ] + } + ], + "source": [ + "# ── Resultados por dificultad ─────────────────────────────\n", + "\n", + "import matplotlib.pyplot as plt\n", + "\n", + "fig, axes = plt.subplots(1, 3, figsize=(15, 5))\n", + "\n", + "# 1. Pass rate por dificultad\n", + "ax = axes[0]\n", + "by_diff = df.groupby(\"difficulty\")[\"passed\"].mean() * 100\n", + "by_diff = by_diff.reindex([\"easy\", \"medium\", \"hard\"])\n", + "colors = [\"#2ecc71\" if v == 100 else \"#e74c3c\" if v < 50 else \"#f39c12\" for v in by_diff]\n", + "by_diff.plot(kind=\"bar\", ax=ax, color=colors)\n", + "ax.set_title(\"Pass Rate por Dificultad\")\n", + "ax.set_ylabel(\"%\")\n", + "ax.set_ylim(0, 110)\n", + "for i, v in enumerate(by_diff):\n", + " ax.text(i, v + 2, f\"{v:.0f}%\", ha=\"center\", fontweight=\"bold\")\n", + "\n", + "# 2. Velocidad por challenge\n", + "ax = axes[1]\n", + "colors2 = [\"#2ecc71\" if r else \"#e74c3c\" for r in df[\"passed\"]]\n", + "ax.barh(df[\"challenge\"], df[\"tokens_per_second\"], color=colors2)\n", + "ax.set_title(\"Velocidad (tok/s)\")\n", + "ax.set_xlabel(\"tokens/segundo\")\n", + "\n", + "# 3. Latencia por challenge\n", + "ax = axes[2]\n", + "ax.barh(df[\"challenge\"], df[\"latency_ms\"] / 1000, color=colors2)\n", + "ax.set_title(\"Latencia (segundos)\")\n", + "ax.set_xlabel(\"segundos\")\n", + "\n", + "plt.tight_layout()\n", + "plt.savefig(\"../data/eval_results.png\", dpi=150, bbox_inches=\"tight\")\n", + "plt.show()\n", + "print(\"✓ Gráfico guardado en data/eval_results.png\")" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "🎉 Todos los challenges pasaron! No hay fallos que inspeccionar.\n" + ] + } + ], + "source": [ + "# ── Inspeccionar código de challenges fallidos ────────────\n", + "\n", + "failed = [r for r in results if not r[\"passed\"]]\n", + "if not failed:\n", + " print(\"🎉 Todos los challenges pasaron! No hay fallos que inspeccionar.\")\n", + "else:\n", + " for r in failed:\n", + " print(f\"\\n{'='*60}\")\n", + " print(f\"FALLÓ: {r['challenge']} ({r['difficulty']})\")\n", + " print(f\"{'='*60}\")\n", + " print(f\"\\nCódigo generado:\")\n", + " print(r[\"code\"])\n", + " print(f\"\\nError:\")\n", + " print(r[\"error\"])" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "════════════════════════════════════════════════════════════\n", + " RESUMEN: qwen2.5-coder-7b-abliterated-i1\n", + "════════════════════════════════════════════════════════════\n", + "\n", + " Correctitud: 12/12 (100%)\n", + " Velocidad: 27.7 tok/s (promedio)\n", + " Latencia: 4.3s (promedio)\n", + " Eficiencia: 115 tokens/challenge (promedio)\n", + "\n", + " Por dificultad:\n", + " easy 4/4 passed | 24.8 tok/s\n", + " medium 5/5 passed | 29.9 tok/s\n", + " hard 3/3 passed | 27.8 tok/s\n", + "════════════════════════════════════════════════════════════\n" + ] + } + ], + "source": [ + "# ── Resumen final ─────────────────────────────────────────\n", + "\n", + "print(f\"\\n{'═'*60}\")\n", + "print(f\" RESUMEN: {MODEL}\")\n", + "print(f\"{'═'*60}\")\n", + "print(f\"\")\n", + "print(f\" Correctitud: {passed_total}/{len(results)} ({100*passed_total/len(results):.0f}%)\")\n", + "print(f\" Velocidad: {df['tokens_per_second'].mean():.1f} tok/s (promedio)\")\n", + "print(f\" Latencia: {df['latency_ms'].mean()/1000:.1f}s (promedio)\")\n", + "print(f\" Eficiencia: {df['completion_tokens'].mean():.0f} tokens/challenge (promedio)\")\n", + "print(f\"\")\n", + "print(f\" Por dificultad:\")\n", + "for d in [\"easy\", \"medium\", \"hard\"]:\n", + " subset = [r for r in results if r[\"difficulty\"] == d]\n", + " p = sum(1 for r in subset if r[\"passed\"])\n", + " avg_tps = sum(r[\"tokens_per_second\"] for r in subset) / len(subset)\n", + " print(f\" {d:8s} {p}/{len(subset)} passed | {avg_tps:.1f} tok/s\")\n", + "print(f\"{'═'*60}\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.7" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/notebooks/03_registry_level_eval.ipynb b/notebooks/03_registry_level_eval.ipynb new file mode 100644 index 0000000..5d93766 --- /dev/null +++ b/notebooks/03_registry_level_eval.ipynb @@ -0,0 +1,1045 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Evaluación Nivel Registry — Qwen2.5-Coder-7B\n", + "\n", + "Challenges de nivel production inspirados en funciones reales del fn_registry.\n", + "\n", + "**Categorías:**\n", + "- Functional Programming: pipe, compose, memoize, partition\n", + "- Data Processing: type coercion, frontmatter parsing, JSON extraction, text splitting\n", + "- Algorithms: topological sort, interval scheduling, tree operations\n", + "- Real-World Patterns: retry backoff, schema validation, rate limiting, line diff\n", + "\n", + "**Dificultad:** medium → hard → expert" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "✓ qwen2.5-coder-7b-abliterated-i1 listo\n" + ] + } + ], + "source": [ + "import sys, os\n", + "sys.path.insert(0, os.path.join(os.getcwd(), '..'))\n", + "\n", + "import requests\n", + "API_BASE = \"http://127.0.0.1:1234/v1\"\n", + "MODEL = \"qwen2.5-coder-7b-abliterated-i1\"\n", + "\n", + "resp = requests.get(f\"{API_BASE}/models\")\n", + "models = [m[\"id\"] for m in resp.json()[\"data\"]]\n", + "assert MODEL in models, f\"{MODEL} no disponible! Modelos: {models}\"\n", + "print(f\"✓ {MODEL} listo\")" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Total challenges: 15\n", + " Functional: 4 — {'medium': 3, 'hard': 1}\n", + " Data Processing: 4 — {'hard': 3, 'medium': 1}\n", + " Algorithms: 3 — {'hard': 2, 'expert': 1}\n", + " Real-World: 4 — {'hard': 1, 'expert': 3}\n" + ] + } + ], + "source": [ + "from eval_runner import evaluate\n", + "from challenges import ALL_CHALLENGES, FUNCTIONAL, DATA_PROCESSING, ALGORITHMS, REAL_WORLD\n", + "\n", + "print(f\"Total challenges: {len(ALL_CHALLENGES)}\")\n", + "for name, group in [(\"Functional\", FUNCTIONAL), (\"Data Processing\", DATA_PROCESSING),\n", + " (\"Algorithms\", ALGORITHMS), (\"Real-World\", REAL_WORLD)]:\n", + " diffs = {}\n", + " for c in group:\n", + " diffs[c.difficulty] = diffs.get(c.difficulty, 0) + 1\n", + " print(f\" {name}: {len(group)} — {diffs}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "══════════════════════════════════════════════════════════════════════\n", + " EVALUACIÓN NIVEL REGISTRY: qwen2.5-coder-7b-abliterated-i1\n", + "══════════════════════════════════════════════════════════════════════\n", + "\n", + " [fn_pipe] Pipe with error propagation (medium)... " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "PASS 9630ms 147tok 15.3t/s\n", + " [fn_group_by_multi] Group by with transform (medium)... " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "PASS 12179ms 204tok 16.8t/s\n", + " [fn_memoize] Memoize decorator with max size (hard)... " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "FAIL 20622ms 311tok 15.1t/s\n", + " | assert \u001b[1;31mcall_count == 2\u001b[0m # same as (1, 2) via kwargs\n", + " | \u001b[1;31m^^^^^^^^^^^^^^^\u001b[0m\n", + " | \u001b[1;35mAssertionError\u001b[0m\n", + " [fn_compose_async] Partition with multiple predicates (medium)... " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "PASS 16920ms 304tok 18.0t/s\n", + " [dp_coerce] Type coercion with schema (hard)... " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "FAIL 11097ms 210tok 18.9t/s\n", + " | \u001b[1;31md, w\u001b[0m = coerce_types({\"age\": \"25\", \"score\": \"3.14\", \"active\": \"yes\"}, {\"age\": \"int\", \"score\": \"float\", \"ac\n", + " | \u001b[1;31m^^^^\u001b[0m\n", + " | \u001b[1;35mTypeError\u001b[0m: \u001b[35mcannot unpack non-iterable NoneType object\u001b[0m\n", + " [dp_frontmatter] Extract YAML frontmatter (medium)... " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "FAIL 6613ms 118tok 17.8t/s\n", + " | \u001b[1;31mbody, meta\u001b[0m = extract_frontmatter(content)\n", + " | \u001b[1;31m^^^^^^^^^^\u001b[0m\n", + " | \u001b[1;35mTypeError\u001b[0m: \u001b[35mcannot unpack non-iterable NoneType object\u001b[0m\n", + " [dp_json_extract] Extract JSON from LLM response (hard)... " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "FAIL 7794ms 142tok 18.2t/s\n", + " | assert \u001b[1;31mextract_json_from_llm('```json\\n{\"name\": \"test\"}\\n```') == {\"name\": \"test\"}\u001b[0m\n", + " | \u001b[1;31m^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\u001b[0m\n", + " | \u001b[1;35mAssertionError\u001b[0m\n", + " [dp_smart_split] Smart text splitter with token budget (hard)... " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "FAIL 15320ms 260tok 17.0t/s\n", + " | assert \u001b[1;31mlen(chunks) == 1\u001b[0m\n", + " | \u001b[1;31m^^^^^^^^^^^^^^^^\u001b[0m\n", + " | \u001b[1;35mAssertionError\u001b[0m\n", + " [alg_topo_sort] Topological sort with cycle detection (hard)... " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "FAIL 20569ms 296tok 14.4t/s\n", + " | assert \u001b[1;31mnot cycle\u001b[0m\n", + " | \u001b[1;31m^^^^^^^^^\u001b[0m\n", + " | \u001b[1;35mAssertionError\u001b[0m\n", + " [alg_interval_merge] Interval scheduler with priorities (hard)... " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "FAIL 29162ms 428tok 14.7t/s\n", + " | assert \u001b[1;31mtotal == 5\u001b[0m, f\"got total={total}\"\n", + " | \u001b[1;31m^^^^^^^^^^\u001b[0m\n", + " | \u001b[1;35mAssertionError\u001b[0m: \u001b[35mgot total=8\u001b[0m\n", + " [alg_tree_ops] Tree operations suite (expert)... " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "FAIL 25543ms 444tok 17.4t/s\n", + " | assert \u001b[31mall\u001b[0m\u001b[1;31m(\"children\" not in n for n in flat)\u001b[0m\n", + " | \u001b[31m~~~\u001b[0m\u001b[1;31m^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\u001b[0m\n", + " | \u001b[1;35mAssertionError\u001b[0m\n", + " [rw_retry] Retry with exponential backoff (hard)... " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "FAIL 22362ms 395tok 17.7t/s\n", + " | assert \u001b[1;31mclassify_error\u001b[0m(200) == \"success\"\n", + " | \u001b[1;31m^^^^^^^^^^^^^^\u001b[0m\n", + " | \u001b[1;35mNameError\u001b[0m: \u001b[35mname 'classify_error' is not defined\u001b[0m\n", + " [rw_schema_validate] Schema validator for dicts (expert)... " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "FAIL 36041ms 632tok 17.5t/s\n", + " | assert \u001b[31many\u001b[0m\u001b[1;31m(\"role\" in e and \"choices\" in e.lower() for e in errors)\u001b[0m\n", + " | \u001b[31m~~~\u001b[0m\u001b[1;31m^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\u001b[0m\n", + " | \u001b[1;35mAssertionError\u001b[0m\n", + " [rw_rate_limiter] Token bucket rate limiter (expert)... " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "FAIL 10589ms 180tok 17.0t/s\n", + " | File \u001b[35m\"/tmp/tmpohadpdim.py\"\u001b[0m, line \u001b[35m24\u001b[0m, in \u001b[35m\u001b[0m\n", + " | bucket = TokenBucket(capacity=10, refill_rate=1.0)\n", + " | \u001b[1;35mTypeError\u001b[0m: \u001b[35mTokenBucket() takes no arguments\u001b[0m\n", + " [rw_diff] Simple line differ (expert)... " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "FAIL 31928ms 596tok 18.7t/s\n", + " | assert \u001b[1;31mresult == [\" a\", \" b\", \" c\"]\u001b[0m\n", + " | \u001b[1;31m^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\u001b[0m\n", + " | \u001b[1;35mAssertionError\u001b[0m\n", + "\n", + "══════════════════════════════════════════════════════════════════════\n", + " TOTAL: 3/15 (20%)\n", + "══════════════════════════════════════════════════════════════════════\n" + ] + } + ], + "source": [ + "# ── Ejecutar TODOS los challenges ─────────────────────────\n", + "\n", + "print(f\"{'═'*70}\")\n", + "print(f\" EVALUACIÓN NIVEL REGISTRY: {MODEL}\")\n", + "print(f\"{'═'*70}\\n\")\n", + "\n", + "results = evaluate(MODEL, ALL_CHALLENGES)\n", + "\n", + "passed = sum(1 for r in results if r.passed)\n", + "total = len(results)\n", + "print(f\"\\n{'═'*70}\")\n", + "print(f\" TOTAL: {passed}/{total} ({100*passed/total:.0f}%)\")\n", + "print(f\"{'═'*70}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "status challenge category difficulty latency_s tokens tok_s\n", + " ✓ Pipe with error propagation functional medium 10.6 147 13.9\n", + " ✓ Group by with transform functional medium 12.3 204 16.6\n", + " ✗ Memoize decorator with max size functional hard 22.0 311 14.1\n", + " ✓ Partition with multiple predicates functional medium 20.8 304 14.6\n", + " ✗ Type coercion with schema data_processing hard 16.6 210 12.6\n", + " ✗ Extract YAML frontmatter data_processing medium 10.0 118 11.8\n", + " ✗ Extract JSON from LLM response data_processing hard 9.3 142 15.2\n", + " ✗ Smart text splitter with token budget data_processing hard 19.1 260 13.6\n", + " ✗ Topological sort with cycle detection algorithm hard 17.8 296 16.6\n", + " ✗ Interval scheduler with priorities algorithm hard 29.0 428 14.8\n", + " ✗ Tree operations suite algorithm expert 33.6 444 13.2\n", + " ✗ Retry with exponential backoff real_world hard 28.5 395 13.9\n", + " ✗ Schema validator for dicts real_world expert 43.9 632 14.4\n", + " ✗ Token bucket rate limiter real_world expert 11.3 180 16.0\n", + " ✗ Simple line differ real_world expert 36.9 588 15.9\n", + "\n", + "────────────────────────────────────────────────────────────\n", + "Velocidad promedio: 14.5 tok/s\n", + "Latencia promedio: 21.4s\n", + "Tokens promedio: 311\n" + ] + } + ], + "source": [ + "# ── Tabla detallada ───────────────────────────────────────\n", + "\n", + "import pandas as pd\n", + "\n", + "df = pd.DataFrame([{\n", + " \"challenge\": r.name,\n", + " \"category\": r.category,\n", + " \"difficulty\": r.difficulty,\n", + " \"passed\": r.passed,\n", + " \"latency_s\": round(r.latency_ms / 1000, 1),\n", + " \"tokens\": r.completion_tokens,\n", + " \"tok_s\": round(r.tokens_per_second, 1),\n", + "} for r in results])\n", + "\n", + "df[\"status\"] = df[\"passed\"].map({True: \"✓\", False: \"✗\"})\n", + "\n", + "print(df[[\"status\", \"challenge\", \"category\", \"difficulty\", \"latency_s\", \"tokens\", \"tok_s\"]].to_string(index=False))\n", + "\n", + "print(f\"\\n{'─'*60}\")\n", + "print(f\"Velocidad promedio: {df['tok_s'].mean():.1f} tok/s\")\n", + "print(f\"Latencia promedio: {df['latency_s'].mean():.1f}s\")\n", + "print(f\"Tokens promedio: {df['tokens'].mean():.0f}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Por categoría:\n", + " functional 3/4 passed | 14.8 tok/s\n", + " data_processing 0/4 passed | 13.3 tok/s\n", + " algorithm 0/3 passed | 14.9 tok/s\n", + " real_world 0/4 passed | 15.0 tok/s\n", + "\n", + "Por dificultad:\n", + " medium 3/4 passed | 14.2 tok/s\n", + " hard 0/7 passed | 14.4 tok/s\n", + " expert 0/4 passed | 14.9 tok/s\n" + ] + } + ], + "source": [ + "# ── Resultados por categoría y dificultad ─────────────────\n", + "\n", + "print(\"\\nPor categoría:\")\n", + "for cat in [\"functional\", \"data_processing\", \"algorithm\", \"real_world\"]:\n", + " subset = [r for r in results if r.category == cat]\n", + " p = sum(1 for r in subset if r.passed)\n", + " avg_tps = sum(r.tokens_per_second for r in subset) / max(len(subset), 1)\n", + " print(f\" {cat:20s} {p}/{len(subset)} passed | {avg_tps:.1f} tok/s\")\n", + "\n", + "print(\"\\nPor dificultad:\")\n", + "for diff in [\"medium\", \"hard\", \"expert\"]:\n", + " subset = [r for r in results if r.difficulty == diff]\n", + " if not subset:\n", + " continue\n", + " p = sum(1 for r in subset if r.passed)\n", + " avg_tps = sum(r.tokens_per_second for r in subset) / len(subset)\n", + " print(f\" {diff:10s} {p}/{len(subset)} passed | {avg_tps:.1f} tok/s\")" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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vnzauHGjBg0apFOnTmn8+PH37NuhQ4fUsmVLvfLKK2rXrp0iIyPVvHlzLV++XLVq1ZIkRUdHq1KlSrp8+bJ69eqlgIAAzZ49W40bN9b8+fP17LPP2u1z5MiRcnNz0+uvv66rV6/Kzc0txWMvWrRIkvTSSy+l6jquXLlSR48eVYcOHRQUFKS9e/fqk08+0d69e7V582Y5OTnpueee08GDB/XVV1/po48+Uo4cOSRJOXPmlCS9++67Gjx4sFq0aKHOnTvrn3/+0cSJE/XMM89o165dthEOU6dOVY8ePVS1alX17dtXUVFRatq0qbJnz668efPa+vTvv/+qWrVqOnz4sHr06KECBQpo3rx5at++vWJiYtS7d2+7c4iMjNSVK1fUpUsXubu7y9/fP8VfSFJzrgAA4NFATZuxa9p7yZcvn8LDw7V69WrFxcXJ19c32TpvvfWWihQpok8++cQ2lUbBggXvuM9OnTpp1qxZqlevnjp37qwbN25o/fr12rx5s2009/262706evSovv/+ezVv3lwFChRQdHS0pk+frvDwcO3bt0/BwcGSbtbINWvW1PHjx9WrVy8FBwfr888/188///yf+gY8NAYAkGqRkZFGkvnpp5/MP//8Y06cOGHmzp1rAgICjKenpzl58qQxxpjLly/bbXft2jVTokQJU6NGDVvbRx99ZCSZf/75547Ha9KkiXniiSfS3M9jx44ZSWb48OHmn3/+MadPnzbr1683ZcuWNZLMvHnz7Na/vb/GGFOnTh3z2GOP2bU98cQTJjw8PNm6I0eONF5eXubgwYN27QMHDjQuLi7m+PHjd+1v/vz5jSSzYMECW1tsbKzJnTu3eeqpp2xtffr0MZLM+vXrbW3x8fGmQIECJjQ01CQkJBhjjFm9erWRZB577LEUz+12zz77rJFkLly4cM91jUn5en311VdGklm3bp2t7YMPPjCSzLFjx+zWjYqKMi4uLubdd9+1a//tt9+Mq6urrf3q1asmICDAlC1b1ly/ft223qxZs4wku3sxfvx4I8l88cUXtrZr166ZihUrGm9vbxMXF2eM+f/Xhq+vrzlz5ozd8ZOWRUZGpvlcAQBAxkFN+2jWtMYYI8l07979jst79+5tJJk9e/YYY1Ku/5JeH9u2bbPbtl27diZ//vy25z///LORZHr16pXsOImJiXfc/619HTp0aLLj3lo73+leXblyxXadkhw7dsy4u7ubESNG2NqSauRvvvnG1nbp0iVTqFAhI8msXr062b4BK2GqBAC4DxEREcqZM6dCQkLUqlUreXt767vvvlOePHkkye6LnS5cuKDY2FhVrVpVO3futLUnjahcuHDhHT96lS1bNp08eVLbtm27r34OHTpUOXPmVFBQkKpWrar9+/frww8/1PPPP2+33q39jY2N1dmzZxUeHq6jR48qNjb2nseZN2+eqlatquzZs+vs2bO2R0REhBISErRu3bp77iM4ONhudIGvr6/atm2rXbt26fTp05KkpUuXqly5cqpSpYptPW9vb3Xp0kVRUVHJvim3Xbt2qfqSraSPm/n4+NxzXcn+el25ckVnz55VhQoVJMnuHt/Jt99+q8TERLVo0cLuegUFBalw4cJavXq1pJtfFnbu3Dm9/PLLcnX9/w/JtGnTJtkIk6VLlyooKMhuProsWbKoV69eunjxotauXWu3frNmzWyjf9PzXAEAgHVR09rL6DVtanh7e0uS4uPj//O+FixYICcnJw0dOjTZsvT+VJa7u7ttnt+EhASdO3fONk3Hra/PpUuXKnfu3HavlaxZs6pLly7p2j/gQWGqBAC4D5MnT9bjjz8uV1dXBQYGqkiRInZfELB48WK988472r17t938SbcWMC1bttT//vc/de7cWQMHDlTNmjX13HPP6fnnn7ft64033tBPP/2kcuXKqVChQqpdu7ZeeOEFVa5cOVX97NKli5o3b64rV67o559/1oQJE5SQkJBsvQ0bNmjo0KHatGmTLl++bLcsNjZWfn5+dz3OoUOH9Ouvv94xCEz6goO7KVSoULIC7/HHH5d08+NwQUFB+vPPP1W+fPlk2xYrVkyS9Oeff6pEiRK29gIFCtzzuJJsHxOLj49P9iUMKTl//ryGDx+uuXPnJju31PxScOjQIRljVLhw4RSXJ33xw59//inp5rW5laura7L5xf78808VLlw42RdV3HptbpXaa/NfzxUAAFgXNa29jF7TpsbFixclpX7Awt0cOXJEwcHB8vf3/8/7SqukuXWnTJmiY8eO2b0ekqb6kG5ey5TuSZEiRR5aX4H/guAWAO5DuXLl7jhn0/r169W4cWM988wzmjJlinLnzq0sWbIoMjLS7gsYPD09tW7dOq1evVpLlizR8uXL9fXXX6tGjRr68ccf5eLiomLFiunAgQNavHixli9frgULFmjKlCkaMmSIhg8ffs9+Fi5cWBEREZKkhg0bysXFRQMHDlT16tVt/T9y5Ihq1qypokWLaty4cQoJCZGbm5uWLl2qjz76KFVfxJCYmKhatWppwIABKS5PKlYfttSOTChatKgk6bfffrN92cXdtGjRQhs3blT//v1VunRpeXt7KzExUXXr1k319XJyctKyZcvk4uKSbHnSSIj0lNpr81/PFQAAWBc1rb2MXtOmxu+//y4XF5cHGgbfzZ1G3qYUvKfFe++9p8GDB6tjx44aOXKk/P395ezsrD59+lCj4pFCcAsAD9iCBQvk4eGhFStWyN3d3dYeGRmZbF1nZ2fVrFlTNWvW1Lhx4/Tee+/prbfe0urVq23FqZeXl1q2bKmWLVvq2rVreu655/Tuu+9q0KBB8vDwSFPf3nrrLc2YMUNvv/22li9fLkn64YcfdPXqVS1atEj58uWzrZv0cf1b3anwKliwoC5evGjr8/04fPiwjDF2xzh48KAk2UaX5s+fXwcOHEi27R9//GFbfj8aNWqkUaNG6YsvvrhncHvhwgWtWrVKw4cP15AhQ2zthw4dSrbu3a6XMUYFChS46y8ASedz+PBhVa9e3dZ+48YNRUVF6cknn7Rb99dff1ViYqLdSJn/cm3Scq4AAODRQk17fxxZ097L8ePHtXbtWlWsWPGBjLgtWLCgVqxYofPnz99x1G3S9F4xMTF27bd/GuxO7nSv5s+fr+rVq2vmzJl27TExMbYvBZZuXsvff/892T1J6foDVsQctwDwgLm4uMjJycnur8hRUVH6/vvv7dY7f/58sm1Lly4tSbaPop07d85uuZubm4oXLy5jjK5fv57mvmXLlk1du3bVihUrtHv3blt/JckYY1svNjY2xaLcy8srWdEl3RyVuWnTJq1YsSLZspiYGN24ceOeffv777/13Xff2Z7HxcXps88+U+nSpRUUFCRJql+/vrZu3apNmzbZ1rt06ZI++eQThYaGqnjx4vc8TkoqVqyounXr6n//+1+y+yRJ165d0+uvvy4p5eslKcVvGfby8pKUvFB97rnn5OLiouHDhyfbjzHGdt/LlCmjgIAAzZgxw+4afvnll7pw4YLddvXr19fp06f19ddf29pu3LihiRMnytvbW+Hh4Xe5AilLy7kCAIBHCzWtvYxQ097N+fPn1bp1ayUkJOitt956IPts1qyZjDEpjppOug++vr7KkSNHsvmBp0yZkqpj3Oleubi4JKtR582bp7/++suurX79+vr77781f/58W9vly5f1ySefpOr4gKMx4hYAHrAGDRpo3Lhxqlu3rl544QWdOXNGkydPVqFChfTrr7/a1hsxYoTWrVunBg0aKH/+/Dpz5oymTJmivHnz2r6ooHbt2goKClLlypUVGBio/fv3a9KkSWrQoMF9/5W8d+/eGj9+vEaPHq25c+eqdu3acnNzU6NGjdS1a1ddvHhRM2bMUK5cuXTq1Cm7bcPCwjR16lS98847KlSokHLlyqUaNWqof//+WrRokRo2bKj27dsrLCxMly5d0m+//ab58+crKirK7i/fKXn88cfVqVMnbdu2TYGBgfr0008VHR1tV2wPHDhQX331lerVq6devXrJ399fs2fP1rFjx7RgwYJk87umxWeffabatWvrueeeU6NGjVSzZk15eXnp0KFDmjt3rk6dOqWxY8fK19dXzzzzjMaMGaPr168rT548+vHHH3Xs2LFk+wwLC5N0c1RIq1atlCVLFjVq1EgFCxbUO++8o0GDBikqKkpNmzaVj4+Pjh07pu+++05dunTR66+/Ljc3Nw0bNkw9e/ZUjRo11KJFC0VFRWnWrFkqWLCg3aiBLl26aPr06Wrfvr127Nih0NBQzZ8/Xxs2bND48ePv6/WSlnMFAACPFmrajFnTSjdH+H7xxRcyxiguLk579uzRvHnzdPHiRds9fRCqV6+ul156SRMmTNChQ4dsU2mtX79e1atXV48ePSRJnTt31ujRo9W5c2eVKVNG69ats41Cvpc73auGDRtqxIgR6tChgypVqqTffvtNX375pR577DG77V9++WVNmjRJbdu21Y4dO5Q7d259/vnnypo16wO5BkC6MwCAVIuMjDSSzLZt2+663syZM03hwoWNu7u7KVq0qImMjDRDhw41t/7YXbVqlWnSpIkJDg42bm5uJjg42LRu3docPHjQts706dPNM888YwICAoy7u7spWLCg6d+/v4mNjb3r8Y8dO2YkmQ8++CDF5e3btzcuLi7m8OHDxhhjFi1aZJ588knj4eFhQkNDzfvvv28+/fRTI8kcO3bMtt3p06dNgwYNjI+Pj5FkwsPDbcvi4+PNoEGDTKFChYybm5vJkSOHqVSpkhk7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iNdlxkRwCwAWdO3aNQ0cOFCS1KxZMx09elT79++Xj4+Pzpw5o/fee0+7d+9Wrly5VLRoUVWtWlWStGfPHknS6NGjdeHCBY0ePdph54DU4V5nDtxnAAAyB97zYUW8LjMuglsAsKBt27bp7Nmzkm6+sUpScHCwKlSoIElavny5SpcurTNnzujAgQNav369JKlUqVL6448/9O6772rKlCny9fV1zAkg1bjXmQP3GQCAzIH3fFgRr8uMy9XRHQAAJHfixAnbv3PlymX7d2BgoCTp+PHjWrduneLj41W2bFn5+PjovffeU0REhMLDw9W4cWPlzp1b5cqV08GDBxUWFqbp06erUKFCD/1ccHfc68yB+wwAQObAez6siNdlxkVwCwAZiDHG9u+goCAtWrTIbvm0adP0+++/64svvlCVKlXk5uam+fPnq0WLFnrxxRe1efPmh91l3CfudebAfQYAIHPgPR9WxOvS+pgqAQAsKCQkxPbvM2fOJPt3vnz5km3z999/a+DAgRo7dqxiY2N14sQJNWnSRBEREapevbq2bNmi+Pj49O880oR7nTlwnwEAyBx4z4cV8brMuAhuAcCCypYtq4CAAEnSggULJN1840z6i2bdunWTbdO9e3eFhYWpY8eOtr+curm5SZKyZMnyMLqN+8C9zhy4zwAAZA6858OKeF1mXAS3AGBBbm5ueu+99yTdfGN97LHHVKxYMcXHxytHjhy2bwRNsmDBAq1YsUKffPKJJKlo0aLKmzevfv75Z0VHR2vDhg22uYpgLdzrzIH7DABA5sB7PqyI12XGRXALABbVpUsXffHFFypdurT+/vtvOTk56bnnntPGjRsVHBxsWy82NlY9e/bUsGHDVLBgQUk335jnzZun69evq2DBgipQoIC++OILR50K7oF7nTlwnwEAyBx4z4cV8brMmJzMrTMRAxlIXFyc/Pz8FBsbK19f3we+/4szAx74PpF23p3OOboLAAALSe/3f+BhehivZ2pa3I76GgAcKy3v/4y4BQAAAAAAAACLIbgFAAAAAAAAAIshuIVDTZ48WaGhofLw8FD58uW1detWR3cJAAAASBNqWgAAkB4IbuEwX3/9tV577TUNHTpUO3fuVKlSpVSnTh2dOXPG0V0DAAAAUoWaFgAApBe+nAwOU758eZUtW1aTJk2SJCUmJiokJEQ9e/bUwIEDk61/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atSooTNnzmjZsmUqVqyYfH199cILL+jy5cvpcq1gfYmJiXf8He5uvw9I///pqUWLFql48eJyd3fX8ePHdebMGTVq1Eienp4qUKCAvvzySwecGazsTnWqMUYRERGqU6eOjDGSpPPnzytv3rwaMmSIpP//2bZkyRI9+eST8vDwUIUKFfT777/bHeOXX36x/a4QEhKiXr166dKlS7blKdWbSYPWnnrqKTk5OdllHkgbglvAgmbPni0vLy9t2bJFY8aM0YgRI+wChHr16mnDhg364osvtG/fPo0ePVouLi6qVKmSxo8fL19fX9so39dffz3Z/hMTE9WkSROdP39ea9eu1cqVK3X06FG1bNnSbr0jR47o+++/1+LFi7V48WKtXbtWo0ePti2/dOmSXnvtNW3fvl2rVq2Ss7Oznn322Uz91+EaNWqoVKlS+vbbb21tzs7OmjBhgvbu3avZs2fr559/1oABAyTprvfs+vXrGjlypPbs2aPvv/9eUVFRat++fZr75OnpafdXz9mzZ8vNzU0bNmzQtGnT9Ndff6l+/foqW7as9uzZo6lTp2rmzJl65513bNsMGjRIo0eP1uDBg7Vv3z7NmTNHgYGB93mVMq5vvvlGRYsWVZEiRfTiiy/q008/tRVCt9uwYYNeeeUV9e7dW7t371atWrWShd3fffedevfurX79+un3339X165d1aFDB61evdpuvWHDhunZZ5/Vb7/9po4dO9otu9f/+w8//FBlypTRrl279Oqrr6pbt246cOCA3T6GDh2qt99+Wzt37pSrq6teeOEFDRgwQB9//LHWr1+vw4cP2wq8zOD333/Xxo0b5ebmJkkaNWqUPvvsM02bNk179+5V37599eKLL2rt2rWSbv5MzZs3r+bNm6d9+/ZpyJAhevPNN/XNN9+k+pjVq1fXgQMHdOrUKUnS6tWrVaVKFdWoUcMuuF29erUqVqwoDw8P7dixQy1atFCrVq3022+/adiwYRo8eHCyPyiMHTtWpUqV0q5du1KcYuHEiRN67rnn1KhRI+3evVudO3fWwIED03jVAOD+zJ49Wzly5NDWrVvVs2dPdevWTc2bN1elSpW0c+dO1a5dWy+99JIuX76smJgY1ahRQ0899ZS2b9+u5cuXKzo6Wi1atLDtr3///lq7dq0WLlyoH3/8UWvWrNHOnTsfSF+HDRumSZMmaePG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7d69Wz/99JM2btxo1z5lyhTlyJFD7du3fyj92Lp1q86ePasGDRqkeptXXnlFEyZM0M8//6waNWqkY+8AAADS5vPPP7d7/tlnn2nlypXJ2osVK/YwuwUAGQ7BLQBYXOPGjeXj46M5c+akGNwuXLhQly5dUps2bRzQu5Q5OTnJw8PD0d24p8jISOXLl08VKlRwaD+WLl2q/Pnz64knnkj1NsWKFVOJEiU0a9YsglsAAGApL774ot3zzZs3a+XKlcnaYR2XLl2Sl5eXo7sB4DZMlQAAFufp6annnntOq1at0pkzZ5ItnzNnjnx8fNS4cWNJUkxMjPr06aOQkBC5u7urUKFCev/995WYmHjPY+3atUv16tWTr6+vvL29VbNmTW3evDnZejExMerbt69CQ0Pl7u6uvHnzqm3btjp79qykO89x+/3336tEiRLy8PBQiRIl9N1336XYj7Fjx6pSpUoKCAiQp6enwsLCUpwv9urVq+rbt69y5sxpuwYnT56853ne2p8aNWrIycnJ1hYaGqq9e/dq7dq1to/xVatWzbb86NGjat68ufz9/ZU1a1ZVqFBBS5Ysueexrl69qoYNG8rPzy/ZCN8lS5bYjbbdvn276tSpoxw5csjT01MFChRQx44dk+2zVq1a+uGHH2SMSfU5AwAAWMGlS5fUr18/W81apEgRjR07NlV1zTvvvCNnZ2dNnDjR1rZs2TJVrVpVXl5e8vHxUYMGDbR371677dq3by9vb2/99ddfatq0qby9vZUzZ069/vrrSkhIsFt37ty5CgsLk4+Pj3x9fVWyZEl9/PHH9+zbuXPn9NJLL8nX11fZsmVTu3bttGfPnhRr4z/++EPPP/+8/P395eHhoTJlymjRokV268yaNUtOTk7asGGDXnvtNeXMmVNeXl569tln9c8//yQ7flquw5EjR1S/fn35+PjYBoGsX79ezZs3V758+eTu7q6QkBD17dtX//77b7Jjpba2T+29XrlypapUqaJs2bLJ29tbRYoU0ZtvvnnPaw48yhhxCwAZQJs2bTR79mx98803dl/OcP78ea1YsUKtW7eWp6enLl++rPDwcP3111/q2rWr8uXLp40bN2rQoEE6deqUxo8ff8dj7N27V1WrVpWvr68GDBigLFmyaPr06apWrZrWrl2r8uXLS5IuXryoqlWrav/+/erYsaOefvppnT17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AAAoK+RZ8ix5FgAA3ExlNnGblJSkhg0bqnr16kWW27p1q8aPH6+UlBQ9+OCD6tmzpz799FMlJycrKipKXbt2VV5e3jX7y8jIUNOmTZWcnKxPPvlEPXv21MmTJ6/a57fffqvvv/9ex44d09SpU3XvvffKZrNp3rx5kqRff/1VcXFx6tWrV4H67dq1U1xcnHJzc7Vz505lZGQoMzNTGzduVPPmzeXq6pqvfHR0tDw9PWW327V06VLz8xMnTig+Pl4JCQmaNGmSDh06VKCvq9X9448/tHXrVs2fP19Vq1bV119/re3btys5OVnp6elatGiRWTYhIcG8xjabTRMnTpQkffDBB3rssce0c+dOpaSkaOjQofLy8tLMmTPNPnv37q233npLWVlZSk5O1tatWxUbG6uFCxea7e/du1fr16/XmjVrzP4mTpyo1NRUPfjgg3r88ccVHR2t77//XnfddZc+/fTTQr8vEyZMkLu7u/mqV69eoeUAAABuBfLs/5BnybMAAKD0OczDyQ4cOCDDMOTp6am+ffuanwcHB8vT01PSxQBqsVhksVgkSRERETp8+HChAfBKLi4uioyMlCS1bNlS9957r5KSkgot261bN1WpUkXOzs569tlnzdUML7/8sj788ENJ0scff6wePXqocuXKBerbbDbFxcUpKSlJvr6+Cg0N1bp16xQXF6d27doV+5r07NlTklSzZk01aNBAP/74Y7HrRkZGysnJSZKUm5urESNGyNfXV82aNVNiYmK+/cYurYK49PWBAwckSa1bt9bHH3+s1157Td99952qVq1aaF9xcXEaMGCAypUrp0qVKql3795atWqVefyZZ55R+fLl8/VXv359SZK/v78CAgJUu3ZtSVJAQID27dtXaD+jRo1SRkaG+fr555+LfT0AAABuNvJsQeTZ/MizAACgJMps4rZZs2bav3+/jh8/Lkl68MEHZbfbNWrUKPMzSYUGycK4uLjowoUL5vtz585ds86lIFjccoGBgbr77ru1du1affTRR1d9kIHNZtPq1au1atUq2Ww2M/iWNOhWqFDB/NrZ2Vk5OTnFrnv5dZsyZYp+++03bd26VcnJyerZs2e+63O1frp06aJNmzbJ09PTXK1QHFde1yu/h1f2V9zzdHV1lZubW74XAABAWSHPXht5Nj/yLAAAKIkym7ht1KiRnnjiCT377LM6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Wcdut+vzzz8v9bEU1e6uXbt077336siRI+Zn8fHxuv/++3XixAlJUp8+feTm5qbTp0/nq+vh4aF77rlH58+fNz9bu3atnJycNHjwYEnSunXrZBjGNcd47Ngx/fWvf5VhGHrnnXdKdoJFuFnXND09XdHR0fk+mzZtWr7rCAAAcLsj0w6WRKYFAAC4FW7pituFCxfKbrebL4vFUmT5awWynJyc6xpHUe36+Pho8ODBeu655yRJZ8+eVd++ffXxxx+ratWqyszM1Ndffy1fX1998cUXBerXr19fS5cuNd9/8skn8vf3L/EYV61apcqVK8tut+u1117Ld+x6z1u6PULujZwfAADAzUamLT4yLQAAwPUr860S0tLSVLduXf3www+SpMmTJ6tDhw767bffNGbMGK1du1aGYWjgwIGSJCcnJ73xxhsKCAjQqFGjlJKSolatWsnPz09eXl56++23zbazs7M1fPhw+fj4yNfXt8h2L/fKK6/ojz/+0Jw5c/Tqq68qNDRU7du3lyR99tlnstlsGjp0qD755JMCdfv27atZs2ZJkjIyMrRlyxZ16NChRNckLi5Ow4cP15YtW2QYhuLi4hQZGal+/fqpdevW8vHxkSRNmjRJ3t7eslgsioiIUEZGhiRp7Nix6t69ux5//HF5eXkpNDRUx44dK/KavvPOO2rRooU8PDwUGxurCRMmyN/fX40aNdK6deskXQyfYWFh8vf3l7e3t3r27Gmu0Bg4cKDS0tJkGIbCw8M1btw4HT58WN27d5dhGLLb7Tp//rxGjhypwMBAGYahbt266fjx45JU6PldKSsrS5mZmfleAAAAjoBMWxCZtmCmJc8CAICScLmVnXXv3l0VK1Y038fHx8vT01OTJk1St27dNHnyZH344Yfatm2batWqpXHjxik2NlaxsbH52nF2dlZCQoIk6eTJk1q9erVcXV119uxZBQcHy2azqWXLlpowYYL27t2r7du3y9XVVUePHi2y3UvKlSunTz/9VK1atVKVKlWUlJRkHvvkk080btw4tWvXTs8//7zS0tLk6elpHv/rX/+qf/7znzp8+LCWLl2qp556Ss7OziW6TjabrcAY582bp+3bt2vjxo2qUqWKVq5cqVmzZik+Pl5Vq1ZVVFSURo4cqX/961+SpK1bt2r79u2qUaOGnn76ac2YMUOjRo266rlXrlxZW7du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/ve/ql69uipUqCBJcnFxka+vryRp9erVOnjwoKZMmSIXFxdJkmEYeu211/KtSKhdu7Z69eqV77PCpKamKiIiQj/99JMMw9CcOXM0duxYdenSRWFhYfLx8dEvv/yiuXPnymq1ymq16tFHH9WhQ4ckXVw1YLPZ1KNHD3l5eSk4OFipqal68skn1bRpU7Vv316nTp0qybenSPXr11etWrWUkJAgSZo1a5b69u171fIxMTFq27atunTpIovFom3btikhIUGhoaHy9/dXs2bN9MUXX0iSjh49qvbt28tischqtV613aysLGVmZuZ7AQAA3Erk2f8hz5JnAQDAzeVysxru3r27KlasaL6Pj4+Xp6enJk2apG7dumny5Mn68MMPtW3bNtWqVUvjxo1TbGysYmNj87Xj7OxshquTJ09q9erVcnV11dmzZxUcHCybzaaWLVtqwoQJ2rt3r7Zv3y5XV1cdPXq0yHYL8/TTT+ujjz5SgwYNFBISojZt2qhHjx6qWLGiduzYoebNm+uuu+7KVycoKCjf7WeS9Nprr6lJkyYaPHjwVfvy8vLSzJkzNXjwYPM2r7Fjxyo+Pl5JSUmqXbu2du3apeHDh2v79u2677779M4776h///5auXKlJCkhIUEpKSmqX7++evXqpccff1ybN29W7dq19dhjj+nTTz8t1VvW+vbtq1mzZsnPz0+LFi1SYmKiBg0adNXyW7duVVJSkjw9PXXixAm1bdtWK1as0F/+8hf9/vvv8vPzU3BwsBYtWqQHHnhA3333nSTp2LFjhbY3YcIEvfnmm6V2PgAAAEUhz5JnybMAAKAs3bKtEi6F3h49esjPz09hYWGaO3euatWqVWQ7/fr1M78+e/as+vfvL4vFopYtW+rgwYNmSFy2bJlefvllubq6StI12y1MnTp1lJKSovnz58tiseif//yngoODlZ2dXaJ2qlevrsGDB2v06NElHkPHjh1Vu3ZtSdLatWvVoUMH3XfffZKkQYMGac2aNeZtWkFBQapfv74kyd/fXwEBAWbdgIAA7du3r8T9F6Vz585auXKl/v3vf6tFixaqWrVqkeWDg4Pl6ekpSdq8ebN++OEHPfLIIzIMQzabTdLFVSstW7bUypUrNWzYMC1ZskSVKlUqtL1Ro0YpIyPDfP3888+len4AAACXI8+SZ8mzAACgLN20FbdXk5OTo127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kSNHmv1t3bpVMTExSk1N1T333KMZM2ZIkhYsWKC0tDTFx8drx44dioiI0KBBg4qsd88992jcuHFq27atGfivNGLECCUkJMhut2vQoEF6+eWXi/W937RpkyZOnKjU1FQ99thjioqKknTx1sPVq1drx44d2r59uxYvXmz+Z+BKEyZMkLu7u/mqV69esfoGAAAoLeRZ8ix5FgAA3Cout6KT7t27q1y5ckpLS9PUqVNVq1YtnT59WqtXr9avv/5qljt16lSRf/Hu2LGjateuLUlydnbWoEGD9OGHH+r999/Xhx9+qBdeeKHQeu3atVNcXJyOHz+uXr166aOPPtKJEycUFxenadOmFescKlSooM6dO0uSgoKCdODAgULLxcbGKiMjQ4sXL5YkZWdny8PDQ5IUEhKiZ599VsHBwZozZ465ckK6GPjatWsnSerWrZuioqL0888/Ky4uTt27dzf3JHv++ef11FNPmfU6dOigGjVqmONKSUkxx5GQkKDmzZtLuriC43JXq3ctq1at0vTp03Xy5Enl5ubmWxFRlODgYDVt2lSSFBUVpdGjR+vChQs6e/asBg0aJLvdrnLlyunnn3+W3W5Xy5YtC7QxatQoDR061HyfmZlJ2AUAALcEedZDEnmWPAsAAG6lWzJxu3DhQhmGobi4OD3++OMKDQ3VAw88IEnasmWLKlSoUKx2KleunO/9gAED5OXlpd69e2v//v0KDw8vtJ7NZtOyZct0/Phxvffee9q3b5/+/e9/a9++ffL39y9W366urnJycpJ0MWRfGRwvycvL0/Tp0/Pd9na5pKQk1apVSz///HOR/Tk5OZn9Xfn55S6/ds7OzsrJyTHHMWrUKHMlwJWuVq8oP/30k1544QUlJCTowQcfVHJyslq3bn3NekV59dVXVbNmTSUlJcnFxUWdO3fWuXPnCi3r6uoqV1fXG+oPAADgepBn/4c8mx95FgAA3Cy3dKsEm82m559/XqNHj1blypXVtm3bfE/lPXz4sP773/9Kktzc3My9r66mWrVqeuKJJ/Tkk0/queeek7Ozc6Hl2rVrp9WrVys9PV2NGzeWzWbTm2++qVatWhVapzh9X02nTp00depUnTlzRpJ05swZ7d69W5L0wQcf6Pjx49q5c6dmzJihTZs2mfXS09O1du1aSRf3C6tdu7bq1q0rm82mRYsWmftfzZgx46oh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HbRp0yZ5e3tr//79SktL07lz59SjRw+zfM2aNc2vu3fvLhcXF1WsWFGGYejAgQOSpNjYWE2aNEmGYahZs2basGGD9u/fb9br2rWrnJ2dVa1aNTVo0ECPPfaYnJycdN9996lWrVpKT0+XJK1atUpBQUHy8fHRuHHjzNUDV+rbt69mz54tSVq3bp1q1Kghi8VSojYuyczMlN1uV2RkpCTJYrGoVatW5vEff/xRjzzyiHx8fNSpUycdO3ZMP/74Y6FtxcXFKTIyUq6urnJxcdGAAQO0atUq8/hTTz2lKlWqFDmey9saMGCAypUrp0qVKql379752nrmmWdUvnz5QuuuXr1a/fv3lyTdd999V101u2zZMg0cOFDu7u6SpGrVqsnZ2blY4xs1apQyMjLM188//1ysegAAAKWBTJsfmbbkmZY8CwAASuKW7HF7SZMmTdSkSRM999xz6tChg5YuXaqwsLAi61SoUMH82tnZWTk5OZIurhBYvHixGjduXKx6hbXz008/6YUXXlBCQoIefPBBJScnq3Xr1oW2FxQUpNzcXG3btk0xMTHq27evJJWojaJcvjfa008/rXfffddcpVG9enWdO3euxO1IUuXKlUs8ltJo62bs9ebq6ipXV9dSbxcAAKAkyLRXR6YtGnkWAACUxC1ZcXvo0CFt2rTJfH/8+HH9+OOPevDBB+Xp6am7775bn332mXn8999/v2abnTp10sSJE83Qe/z48XyrE4ojIyND5cuX11/+8hfl5eXpgw8+KLJ83759NX36dC1fvlw9e/a8rjYkyc3NTc2aNdOcOXMkSbt379bGjRvN48ePH9cDDzwgSZo3b56OHz+er25GRob53mazac6cOcrOzlZOTo5mzpxZ6H5dxWGz2fTJJ58oLy9Pp0+f1ty5c4vdls1m06xZsyRd3BvsatsdhIeHKzo62jyHEydO6MKFCwXOCwAAwNGQafMj05JpAQDAzXVLJm5zcnI0btw4NW7cWIZhKCQkRH369NETTzwhFxcXLVmyRLNnzzY391+8ePE125w6dap5q5nValW7du3MW8WKy2Kx6Omnn5a3t7cCAgJUv379Isv36tVLn3/+uWw2m6pVq3ZdbVwyZ84cffTRR/Lx8dHo0aPzrWh477331LVrVzVr1kxJSUn52oyKitL48ePNBzlERUXJz89Pfn5+MgxDHh4e+R6aUBKvv/66ypcvL4vFohYtWig8PFzdunUrVt333ntPW7ZskZeXl3r37q3Q0NBCy/Xq1UtdunRRcHCwfH191bFjR2VlZclqtcrb21s+Pj5XvSUNAACgLJFpCyLTkmkBAMDN45SXl5dX1oMArkdmZqbc3d21N6ylqpS/pbt+AABQQJ2vN5T1EP4ULv3+z8jIkJubW1kPB7gh5FkAABzTzcz2Jcmzt2TFLQAAAAAAAACg+Ji4BQAAAAAAAAAHw8QtAAAAAAAAADgYJm4BAAAAAAAAwMEwcQsAAAAAAAAADoZHl+K2V3vRtzxVGgAAALct8iwAACgMK24BAAAAAAAAwMEwcQsAAAAAAAAADoaJWwAAAAAAAABwMEzcAgAAAAAAAICD4eFkuO392i1MZ8rzowwAwPWq8/WGsh4C8KdGnkVx8G81APz5sOIWAAAAAAAAABwME7cAAAAAAAAA4GCYuAUAAAAAAAAAB8PELQAAAAAAAAA4GCZuAQAAAAAAAMDBMHELAAAAAAAAAA7mlk7cGoYhwzDk5eUlZ2dn83337t0LLR8TE6NOnTrdtPG0adNGsbGxpdbe2LFjNXjw4BLVWbdunb755ptS6f/EiRN69913r6vu5dc6MTHxqt+Tolxe70bGAgAA4MjItAWRaQEAAErfLZ24tdvtstvtWrFihapUqWK+X7hw4a0chkMpScjNyckp8nhpBUt/f//r+p5cXu9GxnKt8wQAAChLZNqCyLQFkWkBAMCNcoitEubOnSur1Sqr1apHH31Uhw4dKlDm8OHDCggI0KxZs8w6LVq0kJ+fn1q3bq2dO3dKuvhXdpvNph49eshiscjf318//PDDVftevXq1AgIC1LBhQw0bNkx5eXmSCq5c6Nq1q2JiYiRJGRkZ6t+/v3x8fOTr66t+/foVaDc1NVU+Pj5auXKlJGny5MkKDAyUn5+fOnTooIMHD8putys6Olrz58+XYRgaN25cgXYiIyPVr18/tW7dWj4+PpKkiIgI+fv7m9fryJEjkqSBAwfq5MmTMgxD/v7+kqQjR46oW7duCgwMlMVi0ejRo4v8XkgXg7dhGJKk9PR0Va1aVa+//rr8/PzUqFEjbdq0SUOGDJFhGPLx8dGuXbsK1CvpWDw8PDRixAgFBgaqT58+hY4rKytLmZmZ+V4AAACOgkxLpr1WpiXPAgCAkijzidtdu3Zp+PDhWrlypZKTkxUcHKz+/fvnK5OSkqKHH35Y77zzjvr166dNmzbps88+0/r167Vjxw6988476tmzp1k+ISFB48ePV0pKimw2myZOnHjV/lNTU7V582Yl/7/27jyuqjr/4/j7sggam7uoAZqGOwqoP1xyVBpsc5vUHCpMZxzTUnMprUzrV7nk1GjTD61pxqZQy3LfNyDNlU1alMwBLTd+aYqoKMv394cP78+rqKDAvcDr+Xjcx4Oz3HM+3w96z+d8OPec1FTFx8dr0aJFt4157NixqlKlilJTU7Vv374bth8XF6fHH39c//73v/XQQw9p4cKFSktL086dO5WUlKTIyEiNHDlSbdu21YgRIxQZGamUlBS99tprhe4vMTFRa9as0YEDByRJf/vb35SQkKDU1FR17dpV06ZNkyTNmzfPetVHQkKCJCkqKkqjRo3Snj17lJycrISEBC1ZsuS2Y7zW2bNnFRISoqSkJE2aNEkRERHq3bu3UlJSFBUVpddff/2G99xJLKdOndLu3bsVExNTaBzTp0+Xt7e39XXvvfcWaxwAAAClhZqWmvaqW9W01LMAAKA4XOwdQGxsrHr16qUGDRpIkkaOHKk33nhD+fn5kqTvv/9evXv31vLlyxUUFCRJWrFihfbt26eOHTtat3P69GldvHhRkhQWFqZGjRpZf37//fdvuv+nn35arq6ucnV11ZNPPqnNmzfbFMyFWb16tXbv3i0npyt979q1a1uXbd26VevXr9fGjRvl5+cnSVq+fLn27t2rkJAQSbKOragGDBggT09P6/TChQv16aefKicnRzk5OapVq1ah7zt//ry2bNmikydPWudlZ2crLS2tWPt3d3e33issNDRUHh4e6t69uySpQ4cON220FjeWIUOGyGKx3HQbkydP1rhx46zTWVlZFLsAAMAhUNPeHjUt9SwAACgeuzdur3d9kVO/fn1dunRJW7dutRa5xhhFRUXp7bffLnQb7u7u1p+dnZ2LdX+pq/t3cXGxKUZzcnKK9P4mTZrowIED2rVrl7XINcZo8uTJGj58eJHjuJaHh4f15+3bt2vu3LnauXOn6tSpo5UrV970qoarX5HbtWuXTU6Ky83Nzfqzs7PzHeW3KLFcO86bxXFtLAAAAI6KmvZG1LTUswAAoHjsfquE7t27a/369Tp27JikK19H6tmzp5ydnSVJ1atX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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data", + "transient": {} + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "✓ Gráfico guardado\n" + ] + } + ], + "source": [ + "# ── Gráficos ──────────────────────────────────────────────\n", + "\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "\n", + "fig, axes = plt.subplots(2, 2, figsize=(14, 10))\n", + "\n", + "# 1. Pass rate por categoría\n", + "ax = axes[0][0]\n", + "cats = [\"functional\", \"data_processing\", \"algorithm\", \"real_world\"]\n", + "cat_labels = [\"Functional\", \"Data Proc.\", \"Algorithm\", \"Real-World\"]\n", + "rates = []\n", + "for cat in cats:\n", + " subset = [r for r in results if r.category == cat]\n", + " rates.append(100 * sum(1 for r in subset if r.passed) / max(len(subset), 1))\n", + "colors = [\"#2ecc71\" if v == 100 else \"#e74c3c\" if v < 50 else \"#f39c12\" for v in rates]\n", + "ax.bar(cat_labels, rates, color=colors)\n", + "ax.set_title(\"Pass Rate por Categoría\")\n", + "ax.set_ylabel(\"%\")\n", + "ax.set_ylim(0, 110)\n", + "for i, v in enumerate(rates):\n", + " ax.text(i, v + 2, f\"{v:.0f}%\", ha=\"center\", fontweight=\"bold\")\n", + "\n", + "# 2. Pass rate por dificultad\n", + "ax = axes[0][1]\n", + "diffs = [\"medium\", \"hard\", \"expert\"]\n", + "rates_d = []\n", + "for d in diffs:\n", + " subset = [r for r in results if r.difficulty == d]\n", + " rates_d.append(100 * sum(1 for r in subset if r.passed) / max(len(subset), 1))\n", + "colors_d = [\"#2ecc71\" if v == 100 else \"#e74c3c\" if v < 50 else \"#f39c12\" for v in rates_d]\n", + "ax.bar(diffs, rates_d, color=colors_d)\n", + "ax.set_title(\"Pass Rate por Dificultad\")\n", + "ax.set_ylabel(\"%\")\n", + "ax.set_ylim(0, 110)\n", + "for i, v in enumerate(rates_d):\n", + " ax.text(i, v + 2, f\"{v:.0f}%\", ha=\"center\", fontweight=\"bold\")\n", + "\n", + "# 3. Velocidad por challenge\n", + "ax = axes[1][0]\n", + "names = [r.name[:25] for r in results]\n", + "tps = [r.tokens_per_second for r in results]\n", + "bar_colors = [\"#2ecc71\" if r.passed else \"#e74c3c\" for r in results]\n", + "y_pos = np.arange(len(names))\n", + "ax.barh(y_pos, tps, color=bar_colors)\n", + "ax.set_yticks(y_pos)\n", + "ax.set_yticklabels(names, fontsize=8)\n", + "ax.set_title(\"Velocidad (tok/s)\")\n", + "ax.set_xlabel(\"tokens/segundo\")\n", + "ax.invert_yaxis()\n", + "\n", + "# 4. Tokens usados por challenge\n", + "ax = axes[1][1]\n", + "tokens = [r.completion_tokens for r in results]\n", + "ax.barh(y_pos, tokens, color=bar_colors)\n", + "ax.set_yticks(y_pos)\n", + "ax.set_yticklabels(names, fontsize=8)\n", + "ax.set_title(\"Tokens generados\")\n", + "ax.set_xlabel(\"tokens\")\n", + "ax.invert_yaxis()\n", + "\n", + "plt.tight_layout()\n", + "plt.savefig(\"../data/registry_level_eval.png\", dpi=150, bbox_inches=\"tight\")\n", + "plt.show()\n", + "print(\"✓ Gráfico guardado\")" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "12 challenges fallidos:\n", + "\n", + "======================================================================\n", + "FALLÓ: Memoize decorator with max size (functional/hard)\n", + "======================================================================\n", + "\n", + "Código generado (311 tokens):\n", + "from collections import OrderedDict\n", + "\n", + "def memoize(max_size: int = 128):\n", + " \"\"\"Decorator that memoizes function results. When cache exceeds max_size,\n", + " evict the oldest entry (FIFO). The key is (args, tuple(sorted(kwargs.items()))).\n", + " Must work with both positional and keyword arguments.\"\"\"\n", + "\n", + " def decorator(func):\n", + " cache = OrderedDict()\n", + "\n", + " def wrapper(*args, **kwargs):\n", + " key = (args, tuple(sorted(kwargs.items())))\n", + " if key in cache:\n", + " return cache[key]\n", + " result = func(*args, **kwargs)\n", + " cache[key] = result\n", + " if len(cache) > max_size:\n", + " cache.popitem(last=False)\n", + " return result\n", + "\n", + " return wrapper\n", + "\n", + " return decorator\n", + "\n", + "Error:\n", + "Traceback (most recent call last):\n", + " File \u001b[35m\"/tmp/tmp8rjeyq6u.py\"\u001b[0m, line \u001b[35m49\u001b[0m, in \u001b[35m\u001b[0m\n", + " assert \u001b[1;31mcall_count == 2\u001b[0m # same as (1, 2) via kwargs\n", + " \u001b[1;31m^^^^^^^^^^^^^^^\u001b[0m\n", + "\u001b[1;35mAssertionError\u001b[0m\n", + "\n", + "======================================================================\n", + "FALLÓ: Type coercion with schema (data_processing/hard)\n", + "======================================================================\n", + "\n", + "Código generado (210 tokens):\n", + "def coerce_types(data: dict, schema: dict[str, str]) -> tuple[dict, list[str]]:\n", + " \"\"\"Coerce dict values to types specified in schema. Never mutate original.\n", + "\n", + " Schema maps field names to type strings: \"int\", \"float\", \"str\", \"bool\", \"list[str]\".\n", + "\n", + " Rules:\n", + " - str → int: parse via float first (handle \"3.0\" → 3), warn if lossy (\"3.7\" → 3)\n", + " - str → float: standard float()\n", + " - str → bool: \"true/1/yes\" → True, \"false/0/no\" → False (case-insensitive)\n", + " - str → list[str]: split by \",\" and strip whitespace from each item\n", + " - Fields not in schema: pass through unchanged\n", + " - Fields in schema but not in data: skip\n", + " - Failed coercion: keep original value, add warning string to list\n", + "\n", + " Returns (new_dict, warnings_list).\"\"\"\n", + "\n", + "Error:\n", + "Traceback (most recent call last):\n", + " File \u001b[35m\"/tmp/tmp6_i3ueiy.py\"\u001b[0m, line \u001b[35m19\u001b[0m, in \u001b[35m\u001b[0m\n", + " \u001b[1;31md, w\u001b[0m = coerce_types({\"age\": \"25\", \"score\": \"3.14\", \"active\": \"yes\"}, {\"age\": \"int\", \"score\": \"float\", \"active\": \"bool\"})\n", + " \u001b[1;31m^^^^\u001b[0m\n", + "\u001b[1;35mTypeError\u001b[0m: \u001b[35mcannot unpack non-iterable NoneType object\u001b[0m\n", + "\n", + "======================================================================\n", + "FALLÓ: Extract YAML frontmatter (data_processing/medium)\n", + "======================================================================\n", + "\n", + "Código generado (118 tokens):\n", + "def extract_frontmatter(content: str) -> tuple[str, dict | None]:\n", + " \"\"\"Extract YAML-like frontmatter delimited by '---' from start of markdown.\n", + "\n", + " Frontmatter format:\n", + " ---\n", + " key: value\n", + " another: something\n", + " ---\n", + "\n", + " Rest of content here.\n", + "\n", + " Parse simple key:value pairs (no nested YAML needed). Values are always strings.\n", + " Do NOT use the yaml library.\n", + "\n", + " Returns (content_without_frontmatter, parsed_dict_or_None).\n", + " If no frontmatter found, return (original_content, None).\"\"\"\n", + "\n", + "Error:\n", + "Traceback (most recent call last):\n", + " File \u001b[35m\"/tmp/tmpftdwrn65.py\"\u001b[0m, line \u001b[35m21\u001b[0m, in \u001b[35m\u001b[0m\n", + " \u001b[1;31mbody, meta\u001b[0m = extract_frontmatter(content)\n", + " \u001b[1;31m^^^^^^^^^^\u001b[0m\n", + "\u001b[1;35mTypeError\u001b[0m: \u001b[35mcannot unpack non-iterable NoneType object\u001b[0m\n", + "\n", + "======================================================================\n", + "FALLÓ: Extract JSON from LLM response (data_processing/hard)\n", + "======================================================================\n", + "\n", + "Código generado (142 tokens):\n", + "def extract_json_from_llm(content: str) -> dict:\n", + " \"\"\"Extract and parse JSON from messy LLM responses.\n", + "\n", + " Must handle:\n", + " 1. JSON inside ```json ... ``` code blocks\n", + " 2. JSON inside ``` ... ``` blocks (no language tag)\n", + " 3. Raw JSON with surrounding text\n", + " 4. Trailing commas: {\"a\": 1,} or [1, 2,]\n", + " 5. Python None instead of null\n", + " 6. Single-quoted strings converted to double quotes\n", + "\n", + " Returns parsed dict. Returns empty dict {} on failure.\n", + " Use only stdlib (json, re).\"\"\"\n", + "\n", + "Error:\n", + "Traceback (most recent call last):\n", + " File \u001b[35m\"/tmp/tmp_gteve2c.py\"\u001b[0m, line \u001b[35m19\u001b[0m, in \u001b[35m\u001b[0m\n", + " assert \u001b[1;31mextract_json_from_llm('```json\\n{\"name\": \"test\"}\\n```') == {\"name\": \"test\"}\u001b[0m\n", + " \u001b[1;31m^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\u001b[0m\n", + "\u001b[1;35mAssertionError\u001b[0m\n", + "\n", + "======================================================================\n", + "FALLÓ: Smart text splitter with token budget (data_processing/hard)\n", + "======================================================================\n", + "\n", + "Código generado (260 tokens):\n", + "def smart_split(text: str, max_chars: int = 500, overlap: int = 50) -> list[str]:\n", + " paragraphs = text.split('\\n\\n')\n", + " chunks = []\n", + " \n", + " for paragraph in paragraphs:\n", + " sentences = [sentence.strip() for sentence in paragraph.split('. ') if sentence]\n", + " \n", + " current_chunk = ''\n", + " for sentence in sentences:\n", + " if len(current_chunk + ' ' + sentence) <= max_chars:\n", + " current_chunk += ' ' + sentence\n", + " else:\n", + " chunks.append(current_chunk.strip())\n", + " current_chunk = sentence\n", + " \n", + " if current_chunk and not any(chunk.endswith(current_chunk[-overlap:]) for chunk in chunks):\n", + " chunks.append(current_chunk.strip())\n", + "\n", + " return [chunk for chunk in chunks if chunk]\n", + "\n", + "Error:\n", + "Traceback (most recent call last):\n", + " File \u001b[35m\"/tmp/tmpmzy5tut_.py\"\u001b[0m, line \u001b[35m25\u001b[0m, in \u001b[35m\u001b[0m\n", + " assert \u001b[1;31mlen(chunks) == 1\u001b[0m\n", + " \u001b[1;31m^^^^^^^^^^^^^^^^\u001b[0m\n", + "\u001b[1;35mAssertionError\u001b[0m\n", + "\n", + "======================================================================\n", + "FALLÓ: Topological sort with cycle detection (algorithm/hard)\n", + "======================================================================\n", + "\n", + "Código generado (296 tokens):\n", + "from collections import deque\n", + "\n", + "def topo_sort(graph: dict[str, list[str]]) -> tuple[list[str], bool]:\n", + " in_degree = {node: 0 for node in graph}\n", + " for neighbors in graph.values():\n", + " for neighbor in neighbors:\n", + " in_degree[neighbor] += 1\n", + " \n", + " queue = deque([node for node, degree in in_degree.items() if degree == 0])\n", + " \n", + " sorted_list = []\n", + " while queue:\n", + " node = queue.popleft()\n", + " sorted_list.append(node)\n", + " \n", + " for neighbor in graph[node]:\n", + " in_degree[neighbor] -= 1\n", + " if in_degree[neighbor] == 0:\n", + " queue.append(neighbor)\n", + " \n", + " has_cycle = any(degree > 0 for degree in in_degree.values())\n", + " \n", + " return (sorted_list, not has_cycle)\n", + "\n", + "Error:\n", + "Traceback (most recent call last):\n", + " File \u001b[35m\"/tmp/tmpccyd2kz4.py\"\u001b[0m, line \u001b[35m28\u001b[0m, in \u001b[35m\u001b[0m\n", + " assert \u001b[1;31mnot cycle\u001b[0m\n", + " \u001b[1;31m^^^^^^^^^\u001b[0m\n", + "\u001b[1;35mAssertionError\u001b[0m\n", + "\n", + "======================================================================\n", + "FALLÓ: Interval scheduler with priorities (algorithm/hard)\n", + "======================================================================\n", + "\n", + "Código generado (428 tokens):\n", + "def schedule_intervals(intervals: list[dict]) -> list[dict]:\n", + " # Sort intervals by end time in ascending order\n", + " intervals.sort(key=lambda x: x[\"end\"])\n", + "\n", + " n = len(intervals)\n", + " dp = [0] * (n + 1) # Dynamic programming table\n", + "\n", + " for i in range(1, n + 1):\n", + " j = i - 1\n", + " while j >= 0 and intervals[j][\"end\"] > intervals[i-1][\"start\"]:\n", + " j -= 1\n", + " dp[i] = max(dp[i-1], dp[j+1] + intervals[i-1][\"priority\"])\n", + "\n", + " selected_intervals = []\n", + " i, j = n, n - 1\n", + "\n", + " while i >= 0:\n", + " if dp[i] == dp[i-1]:\n", + " i -= 1\n", + " else:\n", + " selected_intervals.append(intervals[i-1])\n", + " j = i - 2\n", + " while j >= 0 and intervals[j][\"end\"] > intervals[i-1][\"start\"]:\n", + " j -= 1\n", + " i = j + 1\n", + "\n", + " return sorted(selected_intervals, key=lambda x: x[\"start\"])\n", + "\n", + "Error:\n", + "Traceback (most recent call last):\n", + " File \u001b[35m\"/tmp/tmp8yr1ne_a.py\"\u001b[0m, line \u001b[35m40\u001b[0m, in \u001b[35m\u001b[0m\n", + " assert \u001b[1;31mtotal == 5\u001b[0m, f\"got total={total}\"\n", + " \u001b[1;31m^^^^^^^^^^\u001b[0m\n", + "\u001b[1;35mAssertionError\u001b[0m: \u001b[35mgot total=8\u001b[0m\n", + "\n", + "======================================================================\n", + "FALLÓ: Tree operations suite (algorithm/expert)\n", + "======================================================================\n", + "\n", + "Código generado (444 tokens):\n", + "from copy import deepcopy\n", + "\n", + "def flatten_tree(tree: dict) -> list[dict]:\n", + " \"\"\"Flatten nested tree to list. Each node is a dict with optional 'children' key.\n", + " DFS pre-order. Remove 'children' key from output nodes. Deep copy nodes.\"\"\"\n", + "\n", + " def dfs(node):\n", + " if not isinstance(node, dict):\n", + " return []\n", + " \n", + " result = [deepcopy(node)]\n", + " children = node.get('children', [])\n", + " for child in children:\n", + " result.extend(dfs(child))\n", + " return result\n", + "\n", + " return dfs(tree)\n", + "\n", + "def find_path(tree: dict, target_id: str) -> list[str] | None:\n", + " \"\"\"Find path from root to node with given 'id' field. Returns list of ids\n", + " from root to target (inclusive), or None if not found.\"\"\"\n", + "\n", + " def dfs(node, current_path):\n", + " if isinstance(node, dict):\n", + " current_path.append(node['id'])\n", + " children = node.get('children', [])\n", + " for child in children:\n", + " result = dfs(child, current_path)\n", + " if result is not None:\n", + " return result\n", + " current_path.pop()\n", + " elif node == target_id:\n", + " return current_path + [target_id]\n", + " return None\n", + "\n", + " return dfs(tree, [])\n", + "\n", + "def map_tree(tree: dict, fn) -> dict:\n", + " \"\"\"Apply fn to each node (excluding 'children' key), return new tree with\n", + " same structure. fn receives a dict without 'children' and returns a new dict.\n", + " Must not mutate original.\"\"\"\n", + "\n", + " def dfs(node):\n", + " if isinstance(node, dict):\n", + " child\n", + "\n", + "Error:\n", + "Traceback (most recent call last):\n", + " File \u001b[35m\"/tmp/tmpdb6oal4s.py\"\u001b[0m, line \u001b[35m74\u001b[0m, in \u001b[35m\u001b[0m\n", + " assert \u001b[31mall\u001b[0m\u001b[1;31m(\"children\" not in n for n in flat)\u001b[0m\n", + " \u001b[31m~~~\u001b[0m\u001b[1;31m^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\u001b[0m\n", + "\u001b[1;35mAssertionError\u001b[0m\n", + "\n", + "======================================================================\n", + "FALLÓ: Retry with exponential backoff (real_world/hard)\n", + "======================================================================\n", + "\n", + "Código generado (395 tokens):\n", + "def compute_backoff_delays(max_retries: int, base_delay: float = 1.0,\n", + " max_delay: float = 60.0, jitter: bool = False) -> list[float]:\n", + " \"\"\"Compute the sequence of backoff delays for retry logic.\n", + "\n", + " Formula: delay = min(base_delay * 2^attempt, max_delay)\n", + " If jitter=True, multiply each delay by a factor between 0.5 and 1.0\n", + " (use deterministic half-jitter: factor = 0.75 for testability).\n", + "\n", + " attempt starts at 0.\n", + " Returns list of `max_retries` delay values.\"\"\"\n", + "\n", + " delays = []\n", + " for attempt in range(max_retries):\n", + " delay = min(base_delay * 2 ** attempt, max_delay)\n", + " if jitter:\n", + " delay *= 0.75\n", + " delays.append(delay)\n", + "\n", + " return delays\n", + "\n", + "Error:\n", + "Traceback (most recent call last):\n", + " File \u001b[35m\"/tmp/tmpbk8a7fj3.py\"\u001b[0m, line \u001b[35m38\u001b[0m, in \u001b[35m\u001b[0m\n", + " assert \u001b[1;31mclassify_error\u001b[0m(200) == \"success\"\n", + " \u001b[1;31m^^^^^^^^^^^^^^\u001b[0m\n", + "\u001b[1;35mNameError\u001b[0m: \u001b[35mname 'classify_error' is not defined\u001b[0m\n", + "\n", + "======================================================================\n", + "FALLÓ: Schema validator for dicts (real_world/expert)\n", + "======================================================================\n", + "\n", + "Código generado (632 tokens):\n", + "import re\n", + "\n", + "def validate(data: dict, schema: dict) -> list[str]:\n", + " errors = []\n", + "\n", + " for field_name, rule in schema.items():\n", + " value = data.get(field_name)\n", + "\n", + " # Check if required field is missing\n", + " if rule.get(\"required\", False) and value is None:\n", + " errors.append(f\"{field_name}: required field is missing\")\n", + " continue\n", + "\n", + " # Check type of the value\n", + " expected_type = rule[\"type\"]\n", + " actual_type = type(value).__name__\n", + " if expected_type != actual_type:\n", + " errors.append(f\"{field_name}: expected type {expected_type}, got {actual_type}\")\n", + " continue\n", + "\n", + " # Check minimum and maximum values or lengths\n", + " min_value = rule.get(\"min\")\n", + " max_value = rule.get(\"max\")\n", + "\n", + " if isinstance(value, (int, float)):\n", + " if min_value is not None and value < min_value:\n", + " errors.append(f\"{field_name}: expected at least {min_value}, got {value}\")\n", + " elif max_value is not None and value > max_value:\n", + " errors.append(f\"{field_name}: expected at most {max_value}, got {value}\")\n", + "\n", + " elif isinstance(value, str):\n", + " if min_value is not None and len(value) < min_value:\n", + " errors.append(f\"{field_name}: expected at least {min_value} characters, got {len(value)}\")\n", + " elif max_value is not None and len(value) > max_value:\n", + " errors.append(f\"{field_name}: expected at most {max_value} characters, got {len(value)}\")\n", + "\n", + " elif i\n", + "\n", + "Error:\n", + "Traceback (most recent call last):\n", + " File \u001b[35m\"/tmp/tmp6op42bj8.py\"\u001b[0m, line \u001b[35m88\u001b[0m, in \u001b[35m\u001b[0m\n", + " assert \u001b[31many\u001b[0m\u001b[1;31m(\"role\" in e and \"choices\" in e.lower() for e in errors)\u001b[0m\n", + " \u001b[31m~~~\u001b[0m\u001b[1;31m^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\u001b[0m\n", + "\u001b[1;35mAssertionError\u001b[0m\n", + "\n", + "======================================================================\n", + "FALLÓ: Token bucket rate limiter (real_world/expert)\n", + "======================================================================\n", + "\n", + "Código generado (180 tokens):\n", + "class TokenBucket:\n", + " \"\"\"Token bucket rate limiter (non-threaded, for testing).\n", + "\n", + " Args:\n", + " capacity: Maximum tokens in bucket.\n", + " refill_rate: Tokens added per second.\n", + "\n", + " Methods:\n", + " consume(tokens: int = 1, current_time: float = None) -> bool:\n", + " Try to consume tokens. Returns True if allowed, False if not enough tokens.\n", + " current_time is injectable for testing (defaults to time.time()).\n", + " Before checking, refill based on elapsed time since last refill.\n", + "\n", + " tokens_available(current_time: float = None) -> float:\n", + " Return current token count after refill.\n", + "\n", + " wait_time(tokens: int = 1, current_time: float = None) -> float:\n", + " Return seconds to wait before `tokens` would be available.\n", + " Returns 0.0 if tokens are already available.\n", + " \"\"\"\n", + "\n", + "Error:\n", + "Traceback (most recent call last):\n", + " File \u001b[35m\"/tmp/tmp7jdz5i74.py\"\u001b[0m, line \u001b[35m24\u001b[0m, in \u001b[35m\u001b[0m\n", + " bucket = TokenBucket(capacity=10, refill_rate=1.0)\n", + "\u001b[1;35mTypeError\u001b[0m: \u001b[35mTokenBucket() takes no arguments\u001b[0m\n", + "\n", + "======================================================================\n", + "FALLÓ: Simple line differ (real_world/expert)\n", + "======================================================================\n", + "\n", + "Código generado (588 tokens):\n", + "def line_diff(old: str, new: str) -> list[str]:\n", + " \"\"\"Compute line-by-line diff between old and new text.\n", + "\n", + " Returns list of diff lines:\n", + " - Lines only in old: prefixed with \"- \"\n", + " - Lines only in new: prefixed with \"+ \"\n", + " - Common lines: prefixed with \" \" (two spaces)\n", + "\n", + " Use longest common subsequence (LCS) to produce minimal diff.\n", + " Split input on newlines. Empty string = no lines.\"\"\"\n", + " \n", + " # Split the text into lines\n", + " old_lines = old.split('\\n')\n", + " new_lines = new.split('\\n')\n", + "\n", + " # Compute LCS using dynamic programming\n", + " m, n = len(old_lines), len(new_lines)\n", + " dp = [[0] * (n + 1) for _ in range(m + 1)]\n", + " \n", + " for i in range(1, m + 1):\n", + " for j in range(1, n + 1):\n", + " if old_lines[i - 1] == new_lines[j - 1]:\n", + " dp[i][j] = dp[i - 1][j - 1] + 1\n", + " else:\n", + " dp[i][j] = max(dp[i - 1][j], dp[i][j - 1])\n", + " \n", + " # Reconstruct the LCS from the DP table\n", + " i, j = m, n\n", + " lcs = []\n", + " while i > 0 and j > 0:\n", + " if old_lines[i - 1] == new_lines[j - 1]:\n", + " lcs.append(old_lines[i - 1])\n", + " i -= 1\n", + " j -= 1\n", + " elif dp[i - 1][j] >= dp[i][j - 1]:\n", + " i -= 1\n", + " else:\n", + " j -= 1\n", + " \n", + " # Compute the diff by comparing LCS with original lines\n", + " diff = []\n", + " lcs_index = len(lcs) - 1\n", + " for line in old_lines + new_lines:\n", + " if lcs_index >= 0 and line == lcs[lcs_index]:\n", + " diff.append(\" \" + line)\n", + " lcs_index -= 1\n", + " elif line in \n", + "\n", + "Error:\n", + "Traceback (most recent call last):\n", + " File \u001b[35m\"/tmp/tmp_dec25hv.py\"\u001b[0m, line \u001b[35m57\u001b[0m, in \u001b[35m\u001b[0m\n", + " assert \u001b[1;31mresult == [\" a\", \" b\", \" c\"]\u001b[0m\n", + " \u001b[1;31m^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\u001b[0m\n", + "\u001b[1;35mAssertionError\u001b[0m\n", + "\n" + ] + } + ], + "source": [ + "# ── Inspeccionar fallos ───────────────────────────────────\n", + "\n", + "failed = [r for r in results if not r.passed]\n", + "if not failed:\n", + " print(\"Todos los challenges pasaron!\")\n", + "else:\n", + " print(f\"{len(failed)} challenges fallidos:\\n\")\n", + " for r in failed:\n", + " print(f\"{'='*70}\")\n", + " print(f\"FALLÓ: {r.name} ({r.category}/{r.difficulty})\")\n", + " print(f\"{'='*70}\")\n", + " print(f\"\\nCódigo generado ({r.completion_tokens} tokens):\")\n", + " print(r.code[:1500])\n", + " print(f\"\\nError:\")\n", + " print(r.error[:500])\n", + " print()" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "════════════════════════════════════════════════════════════\n", + " RESUMEN EJECUTIVO\n", + " Modelo: qwen2.5-coder-7b-abliterated-i1\n", + "════════════════════════════════════════════════════════════\n", + "\n", + " Correctitud total: 3/15 (20%)\n", + " Velocidad: 14.5 tok/s\n", + " Latencia promedio: 21.4s\n", + " Tokens promedio: 311\n", + "\n", + " Por categoría:\n", + " Functional 3/4\n", + " Data Proc. 0/4\n", + " Algorithm 0/3\n", + " Real-World 0/4\n", + "\n", + " Por dificultad:\n", + " medium 3/4\n", + " hard 0/7\n", + " expert 0/4\n", + "════════════════════════════════════════════════════════════\n" + ] + } + ], + "source": [ + "# ── Resumen ejecutivo ─────────────────────────────────────\n", + "\n", + "passed = sum(1 for r in results if r.passed)\n", + "total = len(results)\n", + "avg_tps = sum(r.tokens_per_second for r in results) / total\n", + "avg_lat = sum(r.latency_ms for r in results) / total\n", + "avg_tok = sum(r.completion_tokens for r in results) / total\n", + "\n", + "print(f\"\\n{'═'*60}\")\n", + "print(f\" RESUMEN EJECUTIVO\")\n", + "print(f\" Modelo: {MODEL}\")\n", + "print(f\"{'═'*60}\")\n", + "print(f\"\")\n", + "print(f\" Correctitud total: {passed}/{total} ({100*passed/total:.0f}%)\")\n", + "print(f\" Velocidad: {avg_tps:.1f} tok/s\")\n", + "print(f\" Latencia promedio: {avg_lat/1000:.1f}s\")\n", + "print(f\" Tokens promedio: {avg_tok:.0f}\")\n", + "print(f\"\")\n", + "print(f\" Por categoría:\")\n", + "for cat, label in [(\"functional\", \"Functional\"), (\"data_processing\", \"Data Proc.\"),\n", + " (\"algorithm\", \"Algorithm\"), (\"real_world\", \"Real-World\")]:\n", + " s = [r for r in results if r.category == cat]\n", + " p = sum(1 for r in s if r.passed)\n", + " print(f\" {label:15s} {p}/{len(s)}\")\n", + "print(f\"\")\n", + "print(f\" Por dificultad:\")\n", + "for d in [\"medium\", \"hard\", \"expert\"]:\n", + " s = [r for r in results if r.difficulty == d]\n", + " if not s: continue\n", + " p = sum(1 for r in s if r.passed)\n", + " print(f\" {d:10s} {p}/{len(s)}\")\n", + "print(f\"{'═'*60}\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.7" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..4339e25 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,16 @@ +[project] +name = "agent-coding-eval" +version = "0.1.0" +description = "Add your description here" +readme = "README.md" +requires-python = ">=3.13" +dependencies = [ + "jupyter>=1.1.1", + "jupyter-collaboration>=4.3.0", + "jupyter-mcp-server>=0.4.0", + "jupyterlab>=4.5.6", + "matplotlib>=3.10.8", + "numpy>=2.4.4", + "pandas>=3.0.2", + "requests>=2.33.1", +] diff --git a/run-jupyter-lab.sh b/run-jupyter-lab.sh new file mode 100755 index 0000000..cda2bb8 --- /dev/null +++ b/run-jupyter-lab.sh @@ -0,0 +1,45 @@ +#!/bin/bash +# Jupyter Lab — modo colaborativo con autodeteccion de puerto +# Generado por write_jupyter_launcher (fn_registry) + +find_free_port() { + for port in 8888 8889 8890 8891 8892 8893 8894 8895 8896 8897 8898 8899; do + if ! ss -tln 2>/dev/null | grep -q ":${port} " && \ + ! lsof -i:"$port" >/dev/null 2>&1; then + echo $port + return + fi + done + echo 8888 +} + +PORT=${1:-$(find_free_port)} +cd "$(dirname "$0")" + +echo $PORT > .jupyter-port + +source .venv/bin/activate 2>/dev/null || true + +if ! python -c "import jupyter_collaboration" 2>/dev/null; then + echo "ERROR: jupyter-collaboration no esta instalado" + echo "Instala con: uv add jupyter-collaboration" + exit 1 +fi + +echo "════════════════════════════════════════════════" +echo " Jupyter Lab + Colaboracion en puerto $PORT" +echo "════════════════════════════════════════════════" +echo "" +echo " Abre: http://localhost:$PORT" +echo " Ctrl+C para detener" +echo "" + +jupyter lab \ + --port=$PORT \ + --no-browser \ + --ServerApp.token='' \ + --ServerApp.password='' \ + --ServerApp.disable_check_xsrf=True \ + --ServerApp.allow_origin='*' \ + --ServerApp.root_dir="$(pwd)" \ + --collaborative diff --git a/uv.lock b/uv.lock new file mode 100644 index 0000000..451bb5b --- /dev/null +++ b/uv.lock @@ -0,0 +1,2551 @@ +version = 1 +revision = 3 +requires-python = ">=3.13" +resolution-markers = [ + "python_full_version >= '3.14' and sys_platform == 'win32'", + "python_full_version >= '3.14' and sys_platform == 'emscripten'", + "python_full_version >= '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", + "python_full_version < '3.14' and sys_platform == 'win32'", + "python_full_version < '3.14' and sys_platform == 'emscripten'", + "python_full_version < '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", +] + +[[package]] +name = "agent-coding-eval" +version = "0.1.0" +source = { virtual = "." } +dependencies = [ + { name = "jupyter" }, + { name = "jupyter-collaboration" }, + { name = "jupyter-mcp-server" }, + { name = "jupyterlab" }, + { name = "matplotlib" }, + { name = "numpy" }, + { name = "pandas" }, + { name = "requests" }, +] + +[package.metadata] +requires-dist = [ + { name = "jupyter", specifier = ">=1.1.1" }, + { name = "jupyter-collaboration", specifier = ">=4.3.0" }, + { name = "jupyter-mcp-server", specifier = ">=0.4.0" }, + { name = "jupyterlab", specifier = ">=4.5.6" }, + { name = "matplotlib", specifier = ">=3.10.8" }, + { name = "numpy", specifier = ">=2.4.4" }, + { name = "pandas", specifier = ">=3.0.2" }, + { name = "requests", specifier = ">=2.33.1" }, +] + +[[package]] +name = "annotated-doc" +version = "0.0.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/57/ba/046ceea27344560984e26a590f90bc7f4a75b06701f653222458922b558c/annotated_doc-0.0.4.tar.gz", hash = "sha256:fbcda96e87e9c92ad167c2e53839e57503ecfda18804ea28102353485033faa4", size = 7288, upload-time = "2025-11-10T22:07:42.062Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl", hash = "sha256:571ac1dc6991c450b25a9c2d84a3705e2ae7a53467b5d111c24fa8baabbed320", size = 5303, upload-time = "2025-11-10T22:07:40.673Z" }, +] + +[[package]] +name = "annotated-types" +version = "0.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081, upload-time = "2024-05-20T21:33:25.928Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643, upload-time = "2024-05-20T21:33:24.1Z" }, +] + +[[package]] +name = "anyio" +version = "4.13.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "idna" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/19/14/2c5dd9f512b66549ae92767a9c7b330ae88e1932ca57876909410251fe13/anyio-4.13.0.tar.gz", hash = "sha256:334b70e641fd2221c1505b3890c69882fe4a2df910cba14d97019b90b24439dc", size = 231622, upload-time = "2026-03-24T12:59:09.671Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/da/42/e921fccf5015463e32a3cf6ee7f980a6ed0f395ceeaa45060b61d86486c2/anyio-4.13.0-py3-none-any.whl", hash = "sha256:08b310f9e24a9594186fd75b4f73f4a4152069e3853f1ed8bfbf58369f4ad708", size = 114353, upload-time = "2026-03-24T12:59:08.246Z" }, +] + +[[package]] +name = "appnope" +version = "0.1.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/35/5d/752690df9ef5b76e169e68d6a129fa6d08a7100ca7f754c89495db3c6019/appnope-0.1.4.tar.gz", hash = "sha256:1de3860566df9caf38f01f86f65e0e13e379af54f9e4bee1e66b48f2efffd1ee", size = 4170, upload-time = "2024-02-06T09:43:11.258Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/81/29/5ecc3a15d5a33e31b26c11426c45c501e439cb865d0bff96315d86443b78/appnope-0.1.4-py2.py3-none-any.whl", hash = "sha256:502575ee11cd7a28c0205f379b525beefebab9d161b7c964670864014ed7213c", size = 4321, upload-time = "2024-02-06T09:43:09.663Z" }, +] + +[[package]] +name = "argon2-cffi" +version = "25.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "argon2-cffi-bindings" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/0e/89/ce5af8a7d472a67cc819d5d998aa8c82c5d860608c4db9f46f1162d7dab9/argon2_cffi-25.1.0.tar.gz", hash = "sha256:694ae5cc8a42f4c4e2bf2ca0e64e51e23a040c6a517a85074683d3959e1346c1", size = 45706, upload-time = "2025-06-03T06:55:32.073Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4f/d3/a8b22fa575b297cd6e3e3b0155c7e25db170edf1c74783d6a31a2490b8d9/argon2_cffi-25.1.0-py3-none-any.whl", hash = "sha256:fdc8b074db390fccb6eb4a3604ae7231f219aa669a2652e0f20e16ba513d5741", size = 14657, upload-time = "2025-06-03T06:55:30.804Z" }, +] + +[[package]] +name = "argon2-cffi-bindings" +version = "25.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cffi" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5c/2d/db8af0df73c1cf454f71b2bbe5e356b8c1f8041c979f505b3d3186e520a9/argon2_cffi_bindings-25.1.0.tar.gz", hash = "sha256:b957f3e6ea4d55d820e40ff76f450952807013d361a65d7f28acc0acbf29229d", size = 1783441, upload-time = "2025-07-30T10:02:05.147Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/60/97/3c0a35f46e52108d4707c44b95cfe2afcafc50800b5450c197454569b776/argon2_cffi_bindings-25.1.0-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:3d3f05610594151994ca9ccb3c771115bdb4daef161976a266f0dd8aa9996b8f", size = 54393, upload-time = "2025-07-30T10:01:40.97Z" }, + { url = "https://files.pythonhosted.org/packages/9d/f4/98bbd6ee89febd4f212696f13c03ca302b8552e7dbf9c8efa11ea4a388c3/argon2_cffi_bindings-25.1.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:8b8efee945193e667a396cbc7b4fb7d357297d6234d30a489905d96caabde56b", size = 29328, upload-time = "2025-07-30T10:01:41.916Z" }, + { url = "https://files.pythonhosted.org/packages/43/24/90a01c0ef12ac91a6be05969f29944643bc1e5e461155ae6559befa8f00b/argon2_cffi_bindings-25.1.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:3c6702abc36bf3ccba3f802b799505def420a1b7039862014a65db3205967f5a", size = 31269, upload-time = "2025-07-30T10:01:42.716Z" }, + { url = "https://files.pythonhosted.org/packages/d4/d3/942aa10782b2697eee7af5e12eeff5ebb325ccfb86dd8abda54174e377e4/argon2_cffi_bindings-25.1.0-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a1c70058c6ab1e352304ac7e3b52554daadacd8d453c1752e547c76e9c99ac44", size = 86558, upload-time = "2025-07-30T10:01:43.943Z" }, + { url = "https://files.pythonhosted.org/packages/0d/82/b484f702fec5536e71836fc2dbc8c5267b3f6e78d2d539b4eaa6f0db8bf8/argon2_cffi_bindings-25.1.0-cp314-cp314t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e2fd3bfbff3c5d74fef31a722f729bf93500910db650c925c2d6ef879a7e51cb", size = 92364, upload-time = "2025-07-30T10:01:44.887Z" }, + { url = "https://files.pythonhosted.org/packages/c9/c1/a606ff83b3f1735f3759ad0f2cd9e038a0ad11a3de3b6c673aa41c24bb7b/argon2_cffi_bindings-25.1.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c4f9665de60b1b0e99bcd6be4f17d90339698ce954cfd8d9cf4f91c995165a92", size = 85637, upload-time = "2025-07-30T10:01:46.225Z" }, + { url = "https://files.pythonhosted.org/packages/44/b4/678503f12aceb0262f84fa201f6027ed77d71c5019ae03b399b97caa2f19/argon2_cffi_bindings-25.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ba92837e4a9aa6a508c8d2d7883ed5a8f6c308c89a4790e1e447a220deb79a85", size = 91934, upload-time = "2025-07-30T10:01:47.203Z" }, + { url = "https://files.pythonhosted.org/packages/f0/c7/f36bd08ef9bd9f0a9cff9428406651f5937ce27b6c5b07b92d41f91ae541/argon2_cffi_bindings-25.1.0-cp314-cp314t-win32.whl", hash = "sha256:84a461d4d84ae1295871329b346a97f68eade8c53b6ed9a7ca2d7467f3c8ff6f", size = 28158, upload-time = "2025-07-30T10:01:48.341Z" }, + { url = "https://files.pythonhosted.org/packages/b3/80/0106a7448abb24a2c467bf7d527fe5413b7fdfa4ad6d6a96a43a62ef3988/argon2_cffi_bindings-25.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:b55aec3565b65f56455eebc9b9f34130440404f27fe21c3b375bf1ea4d8fbae6", size = 32597, upload-time = "2025-07-30T10:01:49.112Z" }, + { url = "https://files.pythonhosted.org/packages/05/b8/d663c9caea07e9180b2cb662772865230715cbd573ba3b5e81793d580316/argon2_cffi_bindings-25.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:87c33a52407e4c41f3b70a9c2d3f6056d88b10dad7695be708c5021673f55623", size = 28231, upload-time = "2025-07-30T10:01:49.92Z" }, + { url = "https://files.pythonhosted.org/packages/1d/57/96b8b9f93166147826da5f90376e784a10582dd39a393c99bb62cfcf52f0/argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:aecba1723ae35330a008418a91ea6cfcedf6d31e5fbaa056a166462ff066d500", size = 54121, upload-time = "2025-07-30T10:01:50.815Z" }, + { url = "https://files.pythonhosted.org/packages/0a/08/a9bebdb2e0e602dde230bdde8021b29f71f7841bd54801bcfd514acb5dcf/argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:2630b6240b495dfab90aebe159ff784d08ea999aa4b0d17efa734055a07d2f44", size = 29177, upload-time = "2025-07-30T10:01:51.681Z" }, + { url = "https://files.pythonhosted.org/packages/b6/02/d297943bcacf05e4f2a94ab6f462831dc20158614e5d067c35d4e63b9acb/argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:7aef0c91e2c0fbca6fc68e7555aa60ef7008a739cbe045541e438373bc54d2b0", size = 31090, upload-time = "2025-07-30T10:01:53.184Z" }, + { url = "https://files.pythonhosted.org/packages/c1/93/44365f3d75053e53893ec6d733e4a5e3147502663554b4d864587c7828a7/argon2_cffi_bindings-25.1.0-cp39-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1e021e87faa76ae0d413b619fe2b65ab9a037f24c60a1e6cc43457ae20de6dc6", size = 81246, upload-time = "2025-07-30T10:01:54.145Z" }, + { url = "https://files.pythonhosted.org/packages/09/52/94108adfdd6e2ddf58be64f959a0b9c7d4ef2fa71086c38356d22dc501ea/argon2_cffi_bindings-25.1.0-cp39-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d3e924cfc503018a714f94a49a149fdc0b644eaead5d1f089330399134fa028a", size = 87126, upload-time = "2025-07-30T10:01:55.074Z" }, + { url = "https://files.pythonhosted.org/packages/72/70/7a2993a12b0ffa2a9271259b79cc616e2389ed1a4d93842fac5a1f923ffd/argon2_cffi_bindings-25.1.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:c87b72589133f0346a1cb8d5ecca4b933e3c9b64656c9d175270a000e73b288d", size = 80343, upload-time = "2025-07-30T10:01:56.007Z" }, + { url = "https://files.pythonhosted.org/packages/78/9a/4e5157d893ffc712b74dbd868c7f62365618266982b64accab26bab01edc/argon2_cffi_bindings-25.1.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:1db89609c06afa1a214a69a462ea741cf735b29a57530478c06eb81dd403de99", size = 86777, upload-time = "2025-07-30T10:01:56.943Z" }, + { url = "https://files.pythonhosted.org/packages/74/cd/15777dfde1c29d96de7f18edf4cc94c385646852e7c7b0320aa91ccca583/argon2_cffi_bindings-25.1.0-cp39-abi3-win32.whl", hash = "sha256:473bcb5f82924b1becbb637b63303ec8d10e84c8d241119419897a26116515d2", size = 27180, upload-time = "2025-07-30T10:01:57.759Z" }, + { url = "https://files.pythonhosted.org/packages/e2/c6/a759ece8f1829d1f162261226fbfd2c6832b3ff7657384045286d2afa384/argon2_cffi_bindings-25.1.0-cp39-abi3-win_amd64.whl", hash = "sha256:a98cd7d17e9f7ce244c0803cad3c23a7d379c301ba618a5fa76a67d116618b98", size = 31715, upload-time = "2025-07-30T10:01:58.56Z" }, + { url = "https://files.pythonhosted.org/packages/42/b9/f8d6fa329ab25128b7e98fd83a3cb34d9db5b059a9847eddb840a0af45dd/argon2_cffi_bindings-25.1.0-cp39-abi3-win_arm64.whl", hash = "sha256:b0fdbcf513833809c882823f98dc2f931cf659d9a1429616ac3adebb49f5db94", size = 27149, upload-time = "2025-07-30T10:01:59.329Z" }, +] + +[[package]] +name = "arrow" +version = "1.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "python-dateutil" }, + { name = "tzdata" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b9/33/032cdc44182491aa708d06a68b62434140d8c50820a087fac7af37703357/arrow-1.4.0.tar.gz", hash = "sha256:ed0cc050e98001b8779e84d461b0098c4ac597e88704a655582b21d116e526d7", size = 152931, upload-time = "2025-10-18T17:46:46.761Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ed/c9/d7977eaacb9df673210491da99e6a247e93df98c715fc43fd136ce1d3d33/arrow-1.4.0-py3-none-any.whl", hash = "sha256:749f0769958ebdc79c173ff0b0670d59051a535fa26e8eba02953dc19eb43205", size = 68797, upload-time = "2025-10-18T17:46:45.663Z" }, +] + +[[package]] +name = "asttokens" +version = "3.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/be/a5/8e3f9b6771b0b408517c82d97aed8f2036509bc247d46114925e32fe33f0/asttokens-3.0.1.tar.gz", hash = "sha256:71a4ee5de0bde6a31d64f6b13f2293ac190344478f081c3d1bccfcf5eacb0cb7", size = 62308, upload-time = "2025-11-15T16:43:48.578Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d2/39/e7eaf1799466a4aef85b6a4fe7bd175ad2b1c6345066aa33f1f58d4b18d0/asttokens-3.0.1-py3-none-any.whl", hash = "sha256:15a3ebc0f43c2d0a50eeafea25e19046c68398e487b9f1f5b517f7c0f40f976a", size = 27047, upload-time = "2025-11-15T16:43:16.109Z" }, +] + +[[package]] +name = "async-lru" +version = "2.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e8/1f/989ecfef8e64109a489fff357450cb73fa73a865a92bd8c272170a6922c2/async_lru-2.3.0.tar.gz", hash = "sha256:89bdb258a0140d7313cf8f4031d816a042202faa61d0ab310a0a538baa1c24b6", size = 16332, upload-time = "2026-03-19T01:04:32.413Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e5/e2/c2e3abf398f80732e58b03be77bde9022550d221dd8781bf586bd4d97cc1/async_lru-2.3.0-py3-none-any.whl", hash = "sha256:eea27b01841909316f2cc739807acea1c623df2be8c5cfad7583286397bb8315", size = 8403, upload-time = "2026-03-19T01:04:30.883Z" }, +] + +[[package]] +name = "attrs" +version = "26.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/9a/8e/82a0fe20a541c03148528be8cac2408564a6c9a0cc7e9171802bc1d26985/attrs-26.1.0.tar.gz", hash = "sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32", size = 952055, upload-time = "2026-03-19T14:22:25.026Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/64/b4/17d4b0b2a2dc85a6df63d1157e028ed19f90d4cd97c36717afef2bc2f395/attrs-26.1.0-py3-none-any.whl", hash = "sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309", size = 67548, upload-time = "2026-03-19T14:22:23.645Z" }, +] + +[[package]] +name = "babel" +version = "2.18.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7d/b2/51899539b6ceeeb420d40ed3cd4b7a40519404f9baf3d4ac99dc413a834b/babel-2.18.0.tar.gz", hash = "sha256:b80b99a14bd085fcacfa15c9165f651fbb3406e66cc603abf11c5750937c992d", size = 9959554, upload-time = "2026-02-01T12:30:56.078Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/77/f5/21d2de20e8b8b0408f0681956ca2c69f1320a3848ac50e6e7f39c6159675/babel-2.18.0-py3-none-any.whl", hash = "sha256:e2b422b277c2b9a9630c1d7903c2a00d0830c409c59ac8cae9081c92f1aeba35", size = 10196845, upload-time = "2026-02-01T12:30:53.445Z" }, +] + +[[package]] +name = "beautifulsoup4" +version = "4.14.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "soupsieve" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c3/b0/1c6a16426d389813b48d95e26898aff79abbde42ad353958ad95cc8c9b21/beautifulsoup4-4.14.3.tar.gz", hash = "sha256:6292b1c5186d356bba669ef9f7f051757099565ad9ada5dd630bd9de5fa7fb86", size = 627737, upload-time = "2025-11-30T15:08:26.084Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1a/39/47f9197bdd44df24d67ac8893641e16f386c984a0619ef2ee4c51fbbc019/beautifulsoup4-4.14.3-py3-none-any.whl", hash = "sha256:0918bfe44902e6ad8d57732ba310582e98da931428d231a5ecb9e7c703a735bb", size = 107721, upload-time = "2025-11-30T15:08:24.087Z" }, +] + +[[package]] +name = "bleach" +version = "6.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "webencodings" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/07/18/3c8523962314be6bf4c8989c79ad9531c825210dd13a8669f6b84336e8bd/bleach-6.3.0.tar.gz", hash = "sha256:6f3b91b1c0a02bb9a78b5a454c92506aa0fdf197e1d5e114d2e00c6f64306d22", size = 203533, upload-time = "2025-10-27T17:57:39.211Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cd/3a/577b549de0cc09d95f11087ee63c739bba856cd3952697eec4c4bb91350a/bleach-6.3.0-py3-none-any.whl", hash = "sha256:fe10ec77c93ddf3d13a73b035abaac7a9f5e436513864ccdad516693213c65d6", size = 164437, upload-time = "2025-10-27T17:57:37.538Z" }, +] + +[package.optional-dependencies] +css = [ + { name = "tinycss2" }, +] + +[[package]] +name = "certifi" +version = "2026.2.25" +source = { registry = "https://pypi.org/simple" } +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/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]] +name = "cffi" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pycparser", marker = "implementation_name != 'PyPy'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/eb/56/b1ba7935a17738ae8453301356628e8147c79dbb825bcbc73dc7401f9846/cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529", size = 523588, upload-time = "2025-09-08T23:24:04.541Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4b/8d/a0a47a0c9e413a658623d014e91e74a50cdd2c423f7ccfd44086ef767f90/cffi-2.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:00bdf7acc5f795150faa6957054fbbca2439db2f775ce831222b66f192f03beb", size = 185230, upload-time = "2025-09-08T23:23:00.879Z" }, + { url = "https://files.pythonhosted.org/packages/4a/d2/a6c0296814556c68ee32009d9c2ad4f85f2707cdecfd7727951ec228005d/cffi-2.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:45d5e886156860dc35862657e1494b9bae8dfa63bf56796f2fb56e1679fc0bca", size = 181043, upload-time = "2025-09-08T23:23:02.231Z" }, + { url = "https://files.pythonhosted.org/packages/b0/1e/d22cc63332bd59b06481ceaac49d6c507598642e2230f201649058a7e704/cffi-2.0.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:07b271772c100085dd28b74fa0cd81c8fb1a3ba18b21e03d7c27f3436a10606b", size = 212446, upload-time = "2025-09-08T23:23:03.472Z" }, + { url = "https://files.pythonhosted.org/packages/a9/f5/a2c23eb03b61a0b8747f211eb716446c826ad66818ddc7810cc2cc19b3f2/cffi-2.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d48a880098c96020b02d5a1f7d9251308510ce8858940e6fa99ece33f610838b", size = 220101, upload-time = "2025-09-08T23:23:04.792Z" }, + { url = "https://files.pythonhosted.org/packages/f2/7f/e6647792fc5850d634695bc0e6ab4111ae88e89981d35ac269956605feba/cffi-2.0.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:f93fd8e5c8c0a4aa1f424d6173f14a892044054871c771f8566e4008eaa359d2", size = 207948, upload-time = "2025-09-08T23:23:06.127Z" }, + { url = "https://files.pythonhosted.org/packages/cb/1e/a5a1bd6f1fb30f22573f76533de12a00bf274abcdc55c8edab639078abb6/cffi-2.0.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:dd4f05f54a52fb558f1ba9f528228066954fee3ebe629fc1660d874d040ae5a3", size = 206422, upload-time = "2025-09-08T23:23:07.753Z" }, + { url = "https://files.pythonhosted.org/packages/98/df/0a1755e750013a2081e863e7cd37e0cdd02664372c754e5560099eb7aa44/cffi-2.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c8d3b5532fc71b7a77c09192b4a5a200ea992702734a2e9279a37f2478236f26", size = 219499, upload-time = "2025-09-08T23:23:09.648Z" }, + { url = "https://files.pythonhosted.org/packages/50/e1/a969e687fcf9ea58e6e2a928ad5e2dd88cc12f6f0ab477e9971f2309b57c/cffi-2.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d9b29c1f0ae438d5ee9acb31cadee00a58c46cc9c0b2f9038c6b0b3470877a8c", size = 222928, upload-time = "2025-09-08T23:23:10.928Z" }, + { url = "https://files.pythonhosted.org/packages/36/54/0362578dd2c9e557a28ac77698ed67323ed5b9775ca9d3fe73fe191bb5d8/cffi-2.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6d50360be4546678fc1b79ffe7a66265e28667840010348dd69a314145807a1b", size = 221302, upload-time = "2025-09-08T23:23:12.42Z" }, + { url = "https://files.pythonhosted.org/packages/eb/6d/bf9bda840d5f1dfdbf0feca87fbdb64a918a69bca42cfa0ba7b137c48cb8/cffi-2.0.0-cp313-cp313-win32.whl", hash = "sha256:74a03b9698e198d47562765773b4a8309919089150a0bb17d829ad7b44b60d27", size = 172909, upload-time = "2025-09-08T23:23:14.32Z" }, + { url = "https://files.pythonhosted.org/packages/37/18/6519e1ee6f5a1e579e04b9ddb6f1676c17368a7aba48299c3759bbc3c8b3/cffi-2.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:19f705ada2530c1167abacb171925dd886168931e0a7b78f5bffcae5c6b5be75", size = 183402, upload-time = "2025-09-08T23:23:15.535Z" }, + { url = "https://files.pythonhosted.org/packages/cb/0e/02ceeec9a7d6ee63bb596121c2c8e9b3a9e150936f4fbef6ca1943e6137c/cffi-2.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:256f80b80ca3853f90c21b23ee78cd008713787b1b1e93eae9f3d6a7134abd91", size = 177780, upload-time = "2025-09-08T23:23:16.761Z" }, + { url = "https://files.pythonhosted.org/packages/92/c4/3ce07396253a83250ee98564f8d7e9789fab8e58858f35d07a9a2c78de9f/cffi-2.0.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:fc33c5141b55ed366cfaad382df24fe7dcbc686de5be719b207bb248e3053dc5", size = 185320, upload-time = "2025-09-08T23:23:18.087Z" }, + { url = "https://files.pythonhosted.org/packages/59/dd/27e9fa567a23931c838c6b02d0764611c62290062a6d4e8ff7863daf9730/cffi-2.0.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c654de545946e0db659b3400168c9ad31b5d29593291482c43e3564effbcee13", size = 181487, upload-time = "2025-09-08T23:23:19.622Z" }, + { url = "https://files.pythonhosted.org/packages/d6/43/0e822876f87ea8a4ef95442c3d766a06a51fc5298823f884ef87aaad168c/cffi-2.0.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:24b6f81f1983e6df8db3adc38562c83f7d4a0c36162885ec7f7b77c7dcbec97b", size = 220049, upload-time = "2025-09-08T23:23:20.853Z" }, + { url = "https://files.pythonhosted.org/packages/b4/89/76799151d9c2d2d1ead63c2429da9ea9d7aac304603de0c6e8764e6e8e70/cffi-2.0.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:12873ca6cb9b0f0d3a0da705d6086fe911591737a59f28b7936bdfed27c0d47c", size = 207793, upload-time = "2025-09-08T23:23:22.08Z" }, + { url = "https://files.pythonhosted.org/packages/bb/dd/3465b14bb9e24ee24cb88c9e3730f6de63111fffe513492bf8c808a3547e/cffi-2.0.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:d9b97165e8aed9272a6bb17c01e3cc5871a594a446ebedc996e2397a1c1ea8ef", size = 206300, upload-time = "2025-09-08T23:23:23.314Z" }, + { url = "https://files.pythonhosted.org/packages/47/d9/d83e293854571c877a92da46fdec39158f8d7e68da75bf73581225d28e90/cffi-2.0.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:afb8db5439b81cf9c9d0c80404b60c3cc9c3add93e114dcae767f1477cb53775", size = 219244, upload-time = "2025-09-08T23:23:24.541Z" }, + { url = "https://files.pythonhosted.org/packages/2b/0f/1f177e3683aead2bb00f7679a16451d302c436b5cbf2505f0ea8146ef59e/cffi-2.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:737fe7d37e1a1bffe70bd5754ea763a62a066dc5913ca57e957824b72a85e205", size = 222828, upload-time = "2025-09-08T23:23:26.143Z" }, + { url = "https://files.pythonhosted.org/packages/c6/0f/cafacebd4b040e3119dcb32fed8bdef8dfe94da653155f9d0b9dc660166e/cffi-2.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:38100abb9d1b1435bc4cc340bb4489635dc2f0da7456590877030c9b3d40b0c1", size = 220926, upload-time = "2025-09-08T23:23:27.873Z" }, + { url = "https://files.pythonhosted.org/packages/3e/aa/df335faa45b395396fcbc03de2dfcab242cd61a9900e914fe682a59170b1/cffi-2.0.0-cp314-cp314-win32.whl", hash = "sha256:087067fa8953339c723661eda6b54bc98c5625757ea62e95eb4898ad5e776e9f", size = 175328, upload-time = "2025-09-08T23:23:44.61Z" }, + { url = "https://files.pythonhosted.org/packages/bb/92/882c2d30831744296ce713f0feb4c1cd30f346ef747b530b5318715cc367/cffi-2.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:203a48d1fb583fc7d78a4c6655692963b860a417c0528492a6bc21f1aaefab25", size = 185650, upload-time = "2025-09-08T23:23:45.848Z" }, + { url = "https://files.pythonhosted.org/packages/9f/2c/98ece204b9d35a7366b5b2c6539c350313ca13932143e79dc133ba757104/cffi-2.0.0-cp314-cp314-win_arm64.whl", hash = "sha256:dbd5c7a25a7cb98f5ca55d258b103a2054f859a46ae11aaf23134f9cc0d356ad", size = 180687, upload-time = "2025-09-08T23:23:47.105Z" }, + { url = "https://files.pythonhosted.org/packages/3e/61/c768e4d548bfa607abcda77423448df8c471f25dbe64fb2ef6d555eae006/cffi-2.0.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:9a67fc9e8eb39039280526379fb3a70023d77caec1852002b4da7e8b270c4dd9", size = 188773, upload-time = "2025-09-08T23:23:29.347Z" }, + { url = "https://files.pythonhosted.org/packages/2c/ea/5f76bce7cf6fcd0ab1a1058b5af899bfbef198bea4d5686da88471ea0336/cffi-2.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7a66c7204d8869299919db4d5069a82f1561581af12b11b3c9f48c584eb8743d", size = 185013, upload-time = "2025-09-08T23:23:30.63Z" }, + { url = "https://files.pythonhosted.org/packages/be/b4/c56878d0d1755cf9caa54ba71e5d049479c52f9e4afc230f06822162ab2f/cffi-2.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7cc09976e8b56f8cebd752f7113ad07752461f48a58cbba644139015ac24954c", size = 221593, upload-time = "2025-09-08T23:23:31.91Z" }, + { url = "https://files.pythonhosted.org/packages/e0/0d/eb704606dfe8033e7128df5e90fee946bbcb64a04fcdaa97321309004000/cffi-2.0.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:92b68146a71df78564e4ef48af17551a5ddd142e5190cdf2c5624d0c3ff5b2e8", size = 209354, upload-time = "2025-09-08T23:23:33.214Z" }, + { url = "https://files.pythonhosted.org/packages/d8/19/3c435d727b368ca475fb8742ab97c9cb13a0de600ce86f62eab7fa3eea60/cffi-2.0.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:b1e74d11748e7e98e2f426ab176d4ed720a64412b6a15054378afdb71e0f37dc", size = 208480, upload-time = "2025-09-08T23:23:34.495Z" }, + { url = "https://files.pythonhosted.org/packages/d0/44/681604464ed9541673e486521497406fadcc15b5217c3e326b061696899a/cffi-2.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:28a3a209b96630bca57cce802da70c266eb08c6e97e5afd61a75611ee6c64592", size = 221584, upload-time = "2025-09-08T23:23:36.096Z" }, + { url = "https://files.pythonhosted.org/packages/25/8e/342a504ff018a2825d395d44d63a767dd8ebc927ebda557fecdaca3ac33a/cffi-2.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:7553fb2090d71822f02c629afe6042c299edf91ba1bf94951165613553984512", size = 224443, upload-time = "2025-09-08T23:23:37.328Z" }, + { url = "https://files.pythonhosted.org/packages/e1/5e/b666bacbbc60fbf415ba9988324a132c9a7a0448a9a8f125074671c0f2c3/cffi-2.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6c6c373cfc5c83a975506110d17457138c8c63016b563cc9ed6e056a82f13ce4", size = 223437, upload-time = "2025-09-08T23:23:38.945Z" }, + { url = "https://files.pythonhosted.org/packages/a0/1d/ec1a60bd1a10daa292d3cd6bb0b359a81607154fb8165f3ec95fe003b85c/cffi-2.0.0-cp314-cp314t-win32.whl", hash = "sha256:1fc9ea04857caf665289b7a75923f2c6ed559b8298a1b8c49e59f7dd95c8481e", size = 180487, upload-time = "2025-09-08T23:23:40.423Z" }, + { url = "https://files.pythonhosted.org/packages/bf/41/4c1168c74fac325c0c8156f04b6749c8b6a8f405bbf91413ba088359f60d/cffi-2.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:d68b6cef7827e8641e8ef16f4494edda8b36104d79773a334beaa1e3521430f6", size = 191726, upload-time = "2025-09-08T23:23:41.742Z" }, + { url = "https://files.pythonhosted.org/packages/ae/3a/dbeec9d1ee0844c679f6bb5d6ad4e9f198b1224f4e7a32825f47f6192b0c/cffi-2.0.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0a1527a803f0a659de1af2e1fd700213caba79377e27e4693648c2923da066f9", size = 184195, upload-time = "2025-09-08T23:23:43.004Z" }, +] + +[[package]] +name = "charset-normalizer" +version = "3.4.7" +source = { registry = "https://pypi.org/simple" } +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/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/97/c8/c67cb8c70e19ef1960b97b22ed2a1567711de46c4ddf19799923adc836c2/charset_normalizer-3.4.7-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:c36c333c39be2dbca264d7803333c896ab8fa7d4d6f0ab7edb7dfd7aea6e98c0", size = 309234, upload-time = "2026-04-02T09:27:07.194Z" }, + { url = "https://files.pythonhosted.org/packages/99/85/c091fdee33f20de70d6c8b522743b6f831a2f1cd3ff86de4c6a827c48a76/charset_normalizer-3.4.7-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1c2aed2e5e41f24ea8ef1590b8e848a79b56f3a5564a65ceec43c9d692dc7d8a", size = 208042, upload-time = "2026-04-02T09:27:08.749Z" }, + { url = "https://files.pythonhosted.org/packages/87/1c/ab2ce611b984d2fd5d86a5a8a19c1ae26acac6bad967da4967562c75114d/charset_normalizer-3.4.7-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:54523e136b8948060c0fa0bc7b1b50c32c186f2fceee897a495406bb6e311d2b", size = 228706, upload-time = "2026-04-02T09:27:09.951Z" }, + { url = "https://files.pythonhosted.org/packages/a8/29/2b1d2cb00bf085f59d29eb773ce58ec2d325430f8c216804a0a5cd83cbca/charset_normalizer-3.4.7-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:715479b9a2802ecac752a3b0efa2b0b60285cf962ee38414211abdfccc233b41", size = 224727, upload-time = "2026-04-02T09:27:11.175Z" }, + { url = "https://files.pythonhosted.org/packages/47/5c/032c2d5a07fe4d4855fea851209cca2b6f03ebeb6d4e3afdb3358386a684/charset_normalizer-3.4.7-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bd6c2a1c7573c64738d716488d2cdd3c00e340e4835707d8fdb8dc1a66ef164e", size = 215882, upload-time = "2026-04-02T09:27:12.446Z" }, + { url = "https://files.pythonhosted.org/packages/2c/c2/356065d5a8b78ed04499cae5f339f091946a6a74f91e03476c33f0ab7100/charset_normalizer-3.4.7-cp314-cp314-manylinux_2_31_armv7l.whl", hash = "sha256:c45e9440fb78f8ddabcf714b68f936737a121355bf59f3907f4e17721b9d1aae", size = 200860, upload-time = "2026-04-02T09:27:13.721Z" }, + { url = "https://files.pythonhosted.org/packages/0c/cd/a32a84217ced5039f53b29f460962abb2d4420def55afabe45b1c3c7483d/charset_normalizer-3.4.7-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3534e7dcbdcf757da6b85a0bbf5b6868786d5982dd959b065e65481644817a18", size = 211564, upload-time = "2026-04-02T09:27:15.272Z" }, + { url = "https://files.pythonhosted.org/packages/44/86/58e6f13ce26cc3b8f4a36b94a0f22ae2f00a72534520f4ae6857c4b81f89/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:e8ac484bf18ce6975760921bb6148041faa8fef0547200386ea0b52b5d27bf7b", size = 211276, upload-time = "2026-04-02T09:27:16.834Z" }, + { url = "https://files.pythonhosted.org/packages/8f/fe/d17c32dc72e17e155e06883efa84514ca375f8a528ba2546bee73fc4df81/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:a5fe03b42827c13cdccd08e6c0247b6a6d4b5e3cdc53fd1749f5896adcdc2356", size = 201238, upload-time = "2026-04-02T09:27:18.229Z" }, + { url = "https://files.pythonhosted.org/packages/6a/29/f33daa50b06525a237451cdb6c69da366c381a3dadcd833fa5676bc468b3/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:2d6eb928e13016cea4f1f21d1e10c1cebd5a421bc57ddf5b1142ae3f86824fab", size = 230189, upload-time = "2026-04-02T09:27:19.445Z" }, + { url = "https://files.pythonhosted.org/packages/b6/6e/52c84015394a6a0bdcd435210a7e944c5f94ea1055f5cc5d56c5fe368e7b/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:e74327fb75de8986940def6e8dee4f127cc9752bee7355bb323cc5b2659b6d46", size = 211352, upload-time = "2026-04-02T09:27:20.79Z" }, + { url = "https://files.pythonhosted.org/packages/8c/d7/4353be581b373033fb9198bf1da3cf8f09c1082561e8e922aa7b39bf9fe8/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:d6038d37043bced98a66e68d3aa2b6a35505dc01328cd65217cefe82f25def44", size = 227024, upload-time = "2026-04-02T09:27:22.063Z" }, + { url = "https://files.pythonhosted.org/packages/30/45/99d18aa925bd1740098ccd3060e238e21115fffbfdcb8f3ece837d0ace6c/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:7579e913a5339fb8fa133f6bbcfd8e6749696206cf05acdbdca71a1b436d8e72", size = 217869, upload-time = "2026-04-02T09:27:23.486Z" }, + { url = "https://files.pythonhosted.org/packages/5c/05/5ee478aa53f4bb7996482153d4bfe1b89e0f087f0ab6b294fcf92d595873/charset_normalizer-3.4.7-cp314-cp314-win32.whl", hash = "sha256:5b77459df20e08151cd6f8b9ef8ef1f961ef73d85c21a555c7eed5b79410ec10", size = 148541, upload-time = "2026-04-02T09:27:25.146Z" }, + { url = "https://files.pythonhosted.org/packages/48/77/72dcb0921b2ce86420b2d79d454c7022bf5be40202a2a07906b9f2a35c97/charset_normalizer-3.4.7-cp314-cp314-win_amd64.whl", hash = "sha256:92a0a01ead5e668468e952e4238cccd7c537364eb7d851ab144ab6627dbbe12f", size = 159634, upload-time = "2026-04-02T09:27:26.642Z" }, + { url = "https://files.pythonhosted.org/packages/c6/a3/c2369911cd72f02386e4e340770f6e158c7980267da16af8f668217abaa0/charset_normalizer-3.4.7-cp314-cp314-win_arm64.whl", hash = "sha256:67f6279d125ca0046a7fd386d01b311c6363844deac3e5b069b514ba3e63c246", size = 148384, upload-time = "2026-04-02T09:27:28.271Z" }, + { url = "https://files.pythonhosted.org/packages/94/09/7e8a7f73d24dba1f0035fbbf014d2c36828fc1bf9c88f84093e57d315935/charset_normalizer-3.4.7-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:effc3f449787117233702311a1b7d8f59cba9ced946ba727bdc329ec69028e24", size = 330133, upload-time = "2026-04-02T09:27:29.474Z" }, + { url = "https://files.pythonhosted.org/packages/8d/da/96975ddb11f8e977f706f45cddd8540fd8242f71ecdb5d18a80723dcf62c/charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fbccdc05410c9ee21bbf16a35f4c1d16123dcdeb8a1d38f33654fa21d0234f79", size = 216257, upload-time = "2026-04-02T09:27:30.793Z" }, + { url = "https://files.pythonhosted.org/packages/e5/e8/1d63bf8ef2d388e95c64b2098f45f84758f6d102a087552da1485912637b/charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:733784b6d6def852c814bce5f318d25da2ee65dd4839a0718641c696e09a2960", size = 234851, upload-time = "2026-04-02T09:27:32.44Z" }, + { url = "https://files.pythonhosted.org/packages/9b/40/e5ff04233e70da2681fa43969ad6f66ca5611d7e669be0246c4c7aaf6dc8/charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a89c23ef8d2c6b27fd200a42aa4ac72786e7c60d40efdc76e6011260b6e949c4", size = 233393, upload-time = "2026-04-02T09:27:34.03Z" }, + { url = "https://files.pythonhosted.org/packages/be/c1/06c6c49d5a5450f76899992f1ee40b41d076aee9279b49cf9974d2f313d5/charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6c114670c45346afedc0d947faf3c7f701051d2518b943679c8ff88befe14f8e", size = 223251, upload-time = "2026-04-02T09:27:35.369Z" }, + { url = "https://files.pythonhosted.org/packages/2b/9f/f2ff16fb050946169e3e1f82134d107e5d4ae72647ec8a1b1446c148480f/charset_normalizer-3.4.7-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:a180c5e59792af262bf263b21a3c49353f25945d8d9f70628e73de370d55e1e1", size = 206609, upload-time = "2026-04-02T09:27:36.661Z" }, + { url = "https://files.pythonhosted.org/packages/69/d5/a527c0cd8d64d2eab7459784fb4169a0ac76e5a6fc5237337982fd61347e/charset_normalizer-3.4.7-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3c9a494bc5ec77d43cea229c4f6db1e4d8fe7e1bbffa8b6f0f0032430ff8ab44", size = 220014, upload-time = "2026-04-02T09:27:38.019Z" }, + { url = "https://files.pythonhosted.org/packages/7e/80/8a7b8104a3e203074dc9aa2c613d4b726c0e136bad1cc734594b02867972/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8d828b6667a32a728a1ad1d93957cdf37489c57b97ae6c4de2860fa749b8fc1e", size = 218979, upload-time = "2026-04-02T09:27:39.37Z" }, + { url = "https://files.pythonhosted.org/packages/02/9a/b759b503d507f375b2b5c153e4d2ee0a75aa215b7f2489cf314f4541f2c0/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:cf1493cd8607bec4d8a7b9b004e699fcf8f9103a9284cc94962cb73d20f9d4a3", size = 209238, upload-time = "2026-04-02T09:27:40.722Z" }, + { url = "https://files.pythonhosted.org/packages/c2/4e/0f3f5d47b86bdb79256e7290b26ac847a2832d9a4033f7eb2cd4bcf4bb5b/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:0c96c3b819b5c3e9e165495db84d41914d6894d55181d2d108cc1a69bfc9cce0", size = 236110, upload-time = "2026-04-02T09:27:42.33Z" }, + { url = "https://files.pythonhosted.org/packages/96/23/bce28734eb3ed2c91dcf93abeb8a5cf393a7b2749725030bb630e554fdd8/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:752a45dc4a6934060b3b0dab47e04edc3326575f82be64bc4fc293914566503e", size = 219824, upload-time = "2026-04-02T09:27:43.924Z" }, + { url = "https://files.pythonhosted.org/packages/2c/6f/6e897c6984cc4d41af319b077f2f600fc8214eb2fe2d6bcb79141b882400/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:8778f0c7a52e56f75d12dae53ae320fae900a8b9b4164b981b9c5ce059cd1fcb", size = 233103, upload-time = "2026-04-02T09:27:45.348Z" }, + { url = "https://files.pythonhosted.org/packages/76/22/ef7bd0fe480a0ae9b656189ec00744b60933f68b4f42a7bb06589f6f576a/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ce3412fbe1e31eb81ea42f4169ed94861c56e643189e1e75f0041f3fe7020abe", size = 225194, upload-time = "2026-04-02T09:27:46.706Z" }, + { url = "https://files.pythonhosted.org/packages/c5/a7/0e0ab3e0b5bc1219bd80a6a0d4d72ca74d9250cb2382b7c699c147e06017/charset_normalizer-3.4.7-cp314-cp314t-win32.whl", hash = "sha256:c03a41a8784091e67a39648f70c5f97b5b6a37f216896d44d2cdcb82615339a0", size = 159827, upload-time = "2026-04-02T09:27:48.053Z" }, + { url = "https://files.pythonhosted.org/packages/7a/1d/29d32e0fb40864b1f878c7f5a0b343ae676c6e2b271a2d55cc3a152391da/charset_normalizer-3.4.7-cp314-cp314t-win_amd64.whl", hash = "sha256:03853ed82eeebbce3c2abfdbc98c96dc205f32a79627688ac9a27370ea61a49c", size = 174168, upload-time = "2026-04-02T09:27:49.795Z" }, + { url = "https://files.pythonhosted.org/packages/de/32/d92444ad05c7a6e41fb2036749777c163baf7a0301a040cb672d6b2b1ae9/charset_normalizer-3.4.7-cp314-cp314t-win_arm64.whl", hash = "sha256:c35abb8bfff0185efac5878da64c45dafd2b37fb0383add1be155a763c1f083d", size = 153018, upload-time = "2026-04-02T09:27:51.116Z" }, + { 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]] +name = "click" +version = "8.3.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, +] +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/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]] +name = "colorama" +version = "0.4.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, +] + +[[package]] +name = "comm" +version = "0.2.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/4c/13/7d740c5849255756bc17888787313b61fd38a0a8304fc4f073dfc46122aa/comm-0.2.3.tar.gz", hash = "sha256:2dc8048c10962d55d7ad693be1e7045d891b7ce8d999c97963a5e3e99c055971", size = 6319, upload-time = "2025-07-25T14:02:04.452Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/60/97/891a0971e1e4a8c5d2b20bbe0e524dc04548d2307fee33cdeba148fd4fc7/comm-0.2.3-py3-none-any.whl", hash = "sha256:c615d91d75f7f04f095b30d1c1711babd43bdc6419c1be9886a85f2f4e489417", size = 7294, upload-time = "2025-07-25T14:02:02.896Z" }, +] + +[[package]] +name = "contourpy" +version = "1.3.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/58/01/1253e6698a07380cd31a736d248a3f2a50a7c88779a1813da27503cadc2a/contourpy-1.3.3.tar.gz", hash = "sha256:083e12155b210502d0bca491432bb04d56dc3432f95a979b429f2848c3dbe880", size = 13466174, upload-time = "2025-07-26T12:03:12.549Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/68/35/0167aad910bbdb9599272bd96d01a9ec6852f36b9455cf2ca67bd4cc2d23/contourpy-1.3.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:177fb367556747a686509d6fef71d221a4b198a3905fe824430e5ea0fda54eb5", size = 293257, upload-time = "2025-07-26T12:01:39.367Z" }, + { url = "https://files.pythonhosted.org/packages/96/e4/7adcd9c8362745b2210728f209bfbcf7d91ba868a2c5f40d8b58f54c509b/contourpy-1.3.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d002b6f00d73d69333dac9d0b8d5e84d9724ff9ef044fd63c5986e62b7c9e1b1", size = 274034, upload-time = "2025-07-26T12:01:40.645Z" }, + { url = "https://files.pythonhosted.org/packages/73/23/90e31ceeed1de63058a02cb04b12f2de4b40e3bef5e082a7c18d9c8ae281/contourpy-1.3.3-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:348ac1f5d4f1d66d3322420f01d42e43122f43616e0f194fc1c9f5d830c5b286", size = 334672, upload-time = "2025-07-26T12:01:41.942Z" }, + { url = "https://files.pythonhosted.org/packages/ed/93/b43d8acbe67392e659e1d984700e79eb67e2acb2bd7f62012b583a7f1b55/contourpy-1.3.3-cp313-cp313-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:655456777ff65c2c548b7c454af9c6f33f16c8884f11083244b5819cc214f1b5", size = 381234, upload-time = "2025-07-26T12:01:43.499Z" }, + { url = "https://files.pythonhosted.org/packages/46/3b/bec82a3ea06f66711520f75a40c8fc0b113b2a75edb36aa633eb11c4f50f/contourpy-1.3.3-cp313-cp313-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:644a6853d15b2512d67881586bd03f462c7ab755db95f16f14d7e238f2852c67", size = 385169, upload-time = "2025-07-26T12:01:45.219Z" }, + { url = "https://files.pythonhosted.org/packages/4b/32/e0f13a1c5b0f8572d0ec6ae2f6c677b7991fafd95da523159c19eff0696a/contourpy-1.3.3-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4debd64f124ca62069f313a9cb86656ff087786016d76927ae2cf37846b006c9", size = 362859, upload-time = "2025-07-26T12:01:46.519Z" }, + { url = "https://files.pythonhosted.org/packages/33/71/e2a7945b7de4e58af42d708a219f3b2f4cff7386e6b6ab0a0fa0033c49a9/contourpy-1.3.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a15459b0f4615b00bbd1e91f1b9e19b7e63aea7483d03d804186f278c0af2659", size = 1332062, upload-time = "2025-07-26T12:01:48.964Z" }, + { url = "https://files.pythonhosted.org/packages/12/fc/4e87ac754220ccc0e807284f88e943d6d43b43843614f0a8afa469801db0/contourpy-1.3.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ca0fdcd73925568ca027e0b17ab07aad764be4706d0a925b89227e447d9737b7", size = 1403932, upload-time = "2025-07-26T12:01:51.979Z" }, + { url = "https://files.pythonhosted.org/packages/a6/2e/adc197a37443f934594112222ac1aa7dc9a98faf9c3842884df9a9d8751d/contourpy-1.3.3-cp313-cp313-win32.whl", hash = "sha256:b20c7c9a3bf701366556e1b1984ed2d0cedf999903c51311417cf5f591d8c78d", size = 185024, upload-time = "2025-07-26T12:01:53.245Z" }, + { url = "https://files.pythonhosted.org/packages/18/0b/0098c214843213759692cc638fce7de5c289200a830e5035d1791d7a2338/contourpy-1.3.3-cp313-cp313-win_amd64.whl", hash = "sha256:1cadd8b8969f060ba45ed7c1b714fe69185812ab43bd6b86a9123fe8f99c3263", size = 226578, upload-time = "2025-07-26T12:01:54.422Z" }, + { url = "https://files.pythonhosted.org/packages/8a/9a/2f6024a0c5995243cd63afdeb3651c984f0d2bc727fd98066d40e141ad73/contourpy-1.3.3-cp313-cp313-win_arm64.whl", hash = "sha256:fd914713266421b7536de2bfa8181aa8c699432b6763a0ea64195ebe28bff6a9", size = 193524, upload-time = "2025-07-26T12:01:55.73Z" }, + { url = "https://files.pythonhosted.org/packages/c0/b3/f8a1a86bd3298513f500e5b1f5fd92b69896449f6cab6a146a5d52715479/contourpy-1.3.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:88df9880d507169449d434c293467418b9f6cbe82edd19284aa0409e7fdb933d", size = 306730, upload-time = "2025-07-26T12:01:57.051Z" }, + { url = "https://files.pythonhosted.org/packages/3f/11/4780db94ae62fc0c2053909b65dc3246bd7cecfc4f8a20d957ad43aa4ad8/contourpy-1.3.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:d06bb1f751ba5d417047db62bca3c8fde202b8c11fb50742ab3ab962c81e8216", size = 287897, upload-time = "2025-07-26T12:01:58.663Z" }, + { url = "https://files.pythonhosted.org/packages/ae/15/e59f5f3ffdd6f3d4daa3e47114c53daabcb18574a26c21f03dc9e4e42ff0/contourpy-1.3.3-cp313-cp313t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e4e6b05a45525357e382909a4c1600444e2a45b4795163d3b22669285591c1ae", size = 326751, upload-time = "2025-07-26T12:02:00.343Z" }, + { url = "https://files.pythonhosted.org/packages/0f/81/03b45cfad088e4770b1dcf72ea78d3802d04200009fb364d18a493857210/contourpy-1.3.3-cp313-cp313t-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ab3074b48c4e2cf1a960e6bbeb7f04566bf36b1861d5c9d4d8ac04b82e38ba20", size = 375486, upload-time = "2025-07-26T12:02:02.128Z" }, + { url = "https://files.pythonhosted.org/packages/0c/ba/49923366492ffbdd4486e970d421b289a670ae8cf539c1ea9a09822b371a/contourpy-1.3.3-cp313-cp313t-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6c3d53c796f8647d6deb1abe867daeb66dcc8a97e8455efa729516b997b8ed99", size = 388106, upload-time = "2025-07-26T12:02:03.615Z" }, + { url = "https://files.pythonhosted.org/packages/9f/52/5b00ea89525f8f143651f9f03a0df371d3cbd2fccd21ca9b768c7a6500c2/contourpy-1.3.3-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:50ed930df7289ff2a8d7afeb9603f8289e5704755c7e5c3bbd929c90c817164b", size = 352548, upload-time = "2025-07-26T12:02:05.165Z" }, + { url = "https://files.pythonhosted.org/packages/32/1d/a209ec1a3a3452d490f6b14dd92e72280c99ae3d1e73da74f8277d4ee08f/contourpy-1.3.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4feffb6537d64b84877da813a5c30f1422ea5739566abf0bd18065ac040e120a", size = 1322297, upload-time = "2025-07-26T12:02:07.379Z" }, + { url = "https://files.pythonhosted.org/packages/bc/9e/46f0e8ebdd884ca0e8877e46a3f4e633f6c9c8c4f3f6e72be3fe075994aa/contourpy-1.3.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:2b7e9480ffe2b0cd2e787e4df64270e3a0440d9db8dc823312e2c940c167df7e", size = 1391023, upload-time = "2025-07-26T12:02:10.171Z" }, + { url = "https://files.pythonhosted.org/packages/b9/70/f308384a3ae9cd2209e0849f33c913f658d3326900d0ff5d378d6a1422d2/contourpy-1.3.3-cp313-cp313t-win32.whl", hash = "sha256:283edd842a01e3dcd435b1c5116798d661378d83d36d337b8dde1d16a5fc9ba3", size = 196157, upload-time = "2025-07-26T12:02:11.488Z" }, + { url = "https://files.pythonhosted.org/packages/b2/dd/880f890a6663b84d9e34a6f88cded89d78f0091e0045a284427cb6b18521/contourpy-1.3.3-cp313-cp313t-win_amd64.whl", hash = "sha256:87acf5963fc2b34825e5b6b048f40e3635dd547f590b04d2ab317c2619ef7ae8", size = 240570, upload-time = "2025-07-26T12:02:12.754Z" }, + { url = "https://files.pythonhosted.org/packages/80/99/2adc7d8ffead633234817ef8e9a87115c8a11927a94478f6bb3d3f4d4f7d/contourpy-1.3.3-cp313-cp313t-win_arm64.whl", hash = "sha256:3c30273eb2a55024ff31ba7d052dde990d7d8e5450f4bbb6e913558b3d6c2301", size = 199713, upload-time = "2025-07-26T12:02:14.4Z" }, + { url = "https://files.pythonhosted.org/packages/72/8b/4546f3ab60f78c514ffb7d01a0bd743f90de36f0019d1be84d0a708a580a/contourpy-1.3.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:fde6c716d51c04b1c25d0b90364d0be954624a0ee9d60e23e850e8d48353d07a", size = 292189, upload-time = "2025-07-26T12:02:16.095Z" }, + { url = "https://files.pythonhosted.org/packages/fd/e1/3542a9cb596cadd76fcef413f19c79216e002623158befe6daa03dbfa88c/contourpy-1.3.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:cbedb772ed74ff5be440fa8eee9bd49f64f6e3fc09436d9c7d8f1c287b121d77", size = 273251, upload-time = "2025-07-26T12:02:17.524Z" }, + { url = "https://files.pythonhosted.org/packages/b1/71/f93e1e9471d189f79d0ce2497007731c1e6bf9ef6d1d61b911430c3db4e5/contourpy-1.3.3-cp314-cp314-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:22e9b1bd7a9b1d652cd77388465dc358dafcd2e217d35552424aa4f996f524f5", size = 335810, upload-time = "2025-07-26T12:02:18.9Z" }, + { url = "https://files.pythonhosted.org/packages/91/f9/e35f4c1c93f9275d4e38681a80506b5510e9327350c51f8d4a5a724d178c/contourpy-1.3.3-cp314-cp314-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a22738912262aa3e254e4f3cb079a95a67132fc5a063890e224393596902f5a4", size = 382871, upload-time = "2025-07-26T12:02:20.418Z" }, + { url = "https://files.pythonhosted.org/packages/b5/71/47b512f936f66a0a900d81c396a7e60d73419868fba959c61efed7a8ab46/contourpy-1.3.3-cp314-cp314-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:afe5a512f31ee6bd7d0dda52ec9864c984ca3d66664444f2d72e0dc4eb832e36", size = 386264, upload-time = "2025-07-26T12:02:21.916Z" }, + { url = "https://files.pythonhosted.org/packages/04/5f/9ff93450ba96b09c7c2b3f81c94de31c89f92292f1380261bd7195bea4ea/contourpy-1.3.3-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f64836de09927cba6f79dcd00fdd7d5329f3fccc633468507079c829ca4db4e3", size = 363819, upload-time = "2025-07-26T12:02:23.759Z" }, + { url = "https://files.pythonhosted.org/packages/3e/a6/0b185d4cc480ee494945cde102cb0149ae830b5fa17bf855b95f2e70ad13/contourpy-1.3.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:1fd43c3be4c8e5fd6e4f2baeae35ae18176cf2e5cced681cca908addf1cdd53b", size = 1333650, upload-time = "2025-07-26T12:02:26.181Z" }, + { url = "https://files.pythonhosted.org/packages/43/d7/afdc95580ca56f30fbcd3060250f66cedbde69b4547028863abd8aa3b47e/contourpy-1.3.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:6afc576f7b33cf00996e5c1102dc2a8f7cc89e39c0b55df93a0b78c1bd992b36", size = 1404833, upload-time = "2025-07-26T12:02:28.782Z" }, + { url = "https://files.pythonhosted.org/packages/e2/e2/366af18a6d386f41132a48f033cbd2102e9b0cf6345d35ff0826cd984566/contourpy-1.3.3-cp314-cp314-win32.whl", hash = "sha256:66c8a43a4f7b8df8b71ee1840e4211a3c8d93b214b213f590e18a1beca458f7d", size = 189692, upload-time = "2025-07-26T12:02:30.128Z" }, + { url = "https://files.pythonhosted.org/packages/7d/c2/57f54b03d0f22d4044b8afb9ca0e184f8b1afd57b4f735c2fa70883dc601/contourpy-1.3.3-cp314-cp314-win_amd64.whl", hash = "sha256:cf9022ef053f2694e31d630feaacb21ea24224be1c3ad0520b13d844274614fd", size = 232424, upload-time = "2025-07-26T12:02:31.395Z" }, + { url = "https://files.pythonhosted.org/packages/18/79/a9416650df9b525737ab521aa181ccc42d56016d2123ddcb7b58e926a42c/contourpy-1.3.3-cp314-cp314-win_arm64.whl", hash = "sha256:95b181891b4c71de4bb404c6621e7e2390745f887f2a026b2d99e92c17892339", size = 198300, upload-time = "2025-07-26T12:02:32.956Z" }, + { url = "https://files.pythonhosted.org/packages/1f/42/38c159a7d0f2b7b9c04c64ab317042bb6952b713ba875c1681529a2932fe/contourpy-1.3.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:33c82d0138c0a062380332c861387650c82e4cf1747aaa6938b9b6516762e772", size = 306769, upload-time = "2025-07-26T12:02:34.2Z" }, + { url = "https://files.pythonhosted.org/packages/c3/6c/26a8205f24bca10974e77460de68d3d7c63e282e23782f1239f226fcae6f/contourpy-1.3.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ea37e7b45949df430fe649e5de8351c423430046a2af20b1c1961cae3afcda77", size = 287892, upload-time = "2025-07-26T12:02:35.807Z" }, + { url = "https://files.pythonhosted.org/packages/66/06/8a475c8ab718ebfd7925661747dbb3c3ee9c82ac834ccb3570be49d129f4/contourpy-1.3.3-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d304906ecc71672e9c89e87c4675dc5c2645e1f4269a5063b99b0bb29f232d13", size = 326748, upload-time = "2025-07-26T12:02:37.193Z" }, + { url = "https://files.pythonhosted.org/packages/b4/a3/c5ca9f010a44c223f098fccd8b158bb1cb287378a31ac141f04730dc49be/contourpy-1.3.3-cp314-cp314t-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ca658cd1a680a5c9ea96dc61cdbae1e85c8f25849843aa799dfd3cb370ad4fbe", size = 375554, upload-time = "2025-07-26T12:02:38.894Z" }, + { url = "https://files.pythonhosted.org/packages/80/5b/68bd33ae63fac658a4145088c1e894405e07584a316738710b636c6d0333/contourpy-1.3.3-cp314-cp314t-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ab2fd90904c503739a75b7c8c5c01160130ba67944a7b77bbf36ef8054576e7f", size = 388118, upload-time = "2025-07-26T12:02:40.642Z" }, + { url = "https://files.pythonhosted.org/packages/40/52/4c285a6435940ae25d7410a6c36bda5145839bc3f0beb20c707cda18b9d2/contourpy-1.3.3-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b7301b89040075c30e5768810bc96a8e8d78085b47d8be6e4c3f5a0b4ed478a0", size = 352555, upload-time = "2025-07-26T12:02:42.25Z" }, + { url = "https://files.pythonhosted.org/packages/24/ee/3e81e1dd174f5c7fefe50e85d0892de05ca4e26ef1c9a59c2a57e43b865a/contourpy-1.3.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:2a2a8b627d5cc6b7c41a4beff6c5ad5eb848c88255fda4a8745f7e901b32d8e4", size = 1322295, upload-time = "2025-07-26T12:02:44.668Z" }, + { url = "https://files.pythonhosted.org/packages/3c/b2/6d913d4d04e14379de429057cd169e5e00f6c2af3bb13e1710bcbdb5da12/contourpy-1.3.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:fd6ec6be509c787f1caf6b247f0b1ca598bef13f4ddeaa126b7658215529ba0f", size = 1391027, upload-time = "2025-07-26T12:02:47.09Z" }, + { url = "https://files.pythonhosted.org/packages/93/8a/68a4ec5c55a2971213d29a9374913f7e9f18581945a7a31d1a39b5d2dfe5/contourpy-1.3.3-cp314-cp314t-win32.whl", hash = "sha256:e74a9a0f5e3fff48fb5a7f2fd2b9b70a3fe014a67522f79b7cca4c0c7e43c9ae", size = 202428, upload-time = "2025-07-26T12:02:48.691Z" }, + { url = "https://files.pythonhosted.org/packages/fa/96/fd9f641ffedc4fa3ace923af73b9d07e869496c9cc7a459103e6e978992f/contourpy-1.3.3-cp314-cp314t-win_amd64.whl", hash = "sha256:13b68d6a62db8eafaebb8039218921399baf6e47bf85006fd8529f2a08ef33fc", size = 250331, upload-time = "2025-07-26T12:02:50.137Z" }, + { url = "https://files.pythonhosted.org/packages/ae/8c/469afb6465b853afff216f9528ffda78a915ff880ed58813ba4faf4ba0b6/contourpy-1.3.3-cp314-cp314t-win_arm64.whl", hash = "sha256:b7448cb5a725bb1e35ce88771b86fba35ef418952474492cf7c764059933ff8b", size = 203831, upload-time = "2025-07-26T12:02:51.449Z" }, +] + +[[package]] +name = "cryptography" +version = "46.0.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cffi", marker = "platform_python_implementation != 'PyPy'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a4/ba/04b1bd4218cbc58dc90ce967106d51582371b898690f3ae0402876cc4f34/cryptography-46.0.6.tar.gz", hash = "sha256:27550628a518c5c6c903d84f637fbecf287f6cb9ced3804838a1295dc1fd0759", size = 750542, upload-time = "2026-03-25T23:34:53.396Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/47/23/9285e15e3bc57325b0a72e592921983a701efc1ee8f91c06c5f0235d86d9/cryptography-46.0.6-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:64235194bad039a10bb6d2d930ab3323baaec67e2ce36215fd0952fad0930ca8", size = 7176401, upload-time = "2026-03-25T23:33:22.096Z" }, + { url = "https://files.pythonhosted.org/packages/60/f8/e61f8f13950ab6195b31913b42d39f0f9afc7d93f76710f299b5ec286ae6/cryptography-46.0.6-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:26031f1e5ca62fcb9d1fcb34b2b60b390d1aacaa15dc8b895a9ed00968b97b30", size = 4275275, upload-time = "2026-03-25T23:33:23.844Z" }, + { url = "https://files.pythonhosted.org/packages/19/69/732a736d12c2631e140be2348b4ad3d226302df63ef64d30dfdb8db7ad1c/cryptography-46.0.6-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:9a693028b9cbe51b5a1136232ee8f2bc242e4e19d456ded3fa7c86e43c713b4a", size = 4425320, upload-time = "2026-03-25T23:33:25.703Z" }, + { url = "https://files.pythonhosted.org/packages/d4/12/123be7292674abf76b21ac1fc0e1af50661f0e5b8f0ec8285faac18eb99e/cryptography-46.0.6-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:67177e8a9f421aa2d3a170c3e56eca4e0128883cf52a071a7cbf53297f18b175", size = 4278082, upload-time = "2026-03-25T23:33:27.423Z" }, + { url = "https://files.pythonhosted.org/packages/5b/ba/d5e27f8d68c24951b0a484924a84c7cdaed7502bac9f18601cd357f8b1d2/cryptography-46.0.6-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:d9528b535a6c4f8ff37847144b8986a9a143585f0540fbcb1a98115b543aa463", size = 4926514, upload-time = "2026-03-25T23:33:29.206Z" }, + { url = "https://files.pythonhosted.org/packages/34/71/1ea5a7352ae516d5512d17babe7e1b87d9db5150b21f794b1377eac1edc0/cryptography-46.0.6-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:22259338084d6ae497a19bae5d4c66b7ca1387d3264d1c2c0e72d9e9b6a77b97", size = 4457766, upload-time = "2026-03-25T23:33:30.834Z" }, + { url = "https://files.pythonhosted.org/packages/01/59/562be1e653accee4fdad92c7a2e88fced26b3fdfce144047519bbebc299e/cryptography-46.0.6-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:760997a4b950ff00d418398ad73fbc91aa2894b5c1db7ccb45b4f68b42a63b3c", size = 3986535, upload-time = "2026-03-25T23:33:33.02Z" }, + { url = "https://files.pythonhosted.org/packages/d6/8b/b1ebfeb788bf4624d36e45ed2662b8bd43a05ff62157093c1539c1288a18/cryptography-46.0.6-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:3dfa6567f2e9e4c5dceb8ccb5a708158a2a871052fa75c8b78cb0977063f1507", size = 4277618, upload-time = "2026-03-25T23:33:34.567Z" }, + { url = "https://files.pythonhosted.org/packages/dd/52/a005f8eabdb28df57c20f84c44d397a755782d6ff6d455f05baa2785bd91/cryptography-46.0.6-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:cdcd3edcbc5d55757e5f5f3d330dd00007ae463a7e7aa5bf132d1f22a4b62b19", size = 4890802, upload-time = "2026-03-25T23:33:37.034Z" }, + { url = "https://files.pythonhosted.org/packages/ec/4d/8e7d7245c79c617d08724e2efa397737715ca0ec830ecb3c91e547302555/cryptography-46.0.6-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:d4e4aadb7fc1f88687f47ca20bb7227981b03afaae69287029da08096853b738", size = 4457425, upload-time = "2026-03-25T23:33:38.904Z" }, + { url = "https://files.pythonhosted.org/packages/1d/5c/f6c3596a1430cec6f949085f0e1a970638d76f81c3ea56d93d564d04c340/cryptography-46.0.6-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:2b417edbe8877cda9022dde3a008e2deb50be9c407eef034aeeb3a8b11d9db3c", size = 4405530, upload-time = "2026-03-25T23:33:40.842Z" }, + { url = "https://files.pythonhosted.org/packages/7e/c9/9f9cea13ee2dbde070424e0c4f621c091a91ffcc504ffea5e74f0e1daeff/cryptography-46.0.6-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:380343e0653b1c9d7e1f55b52aaa2dbb2fdf2730088d48c43ca1c7c0abb7cc2f", size = 4667896, upload-time = "2026-03-25T23:33:42.781Z" }, + { url = "https://files.pythonhosted.org/packages/ad/b5/1895bc0821226f129bc74d00eccfc6a5969e2028f8617c09790bf89c185e/cryptography-46.0.6-cp311-abi3-win32.whl", hash = "sha256:bcb87663e1f7b075e48c3be3ecb5f0b46c8fc50b50a97cf264e7f60242dca3f2", size = 3026348, upload-time = "2026-03-25T23:33:45.021Z" }, + { url = "https://files.pythonhosted.org/packages/c3/f8/c9bcbf0d3e6ad288b9d9aa0b1dee04b063d19e8c4f871855a03ab3a297ab/cryptography-46.0.6-cp311-abi3-win_amd64.whl", hash = "sha256:6739d56300662c468fddb0e5e291f9b4d084bead381667b9e654c7dd81705124", size = 3483896, upload-time = "2026-03-25T23:33:46.649Z" }, + { url = "https://files.pythonhosted.org/packages/01/41/3a578f7fd5c70611c0aacba52cd13cb364a5dee895a5c1d467208a9380b0/cryptography-46.0.6-cp314-cp314t-macosx_10_9_universal2.whl", hash = "sha256:2ef9e69886cbb137c2aef9772c2e7138dc581fad4fcbcf13cc181eb5a3ab6275", size = 7117147, upload-time = "2026-03-25T23:33:48.249Z" }, + { url = "https://files.pythonhosted.org/packages/fa/87/887f35a6fca9dde90cad08e0de0c89263a8e59b2d2ff904fd9fcd8025b6f/cryptography-46.0.6-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7f417f034f91dcec1cb6c5c35b07cdbb2ef262557f701b4ecd803ee8cefed4f4", size = 4266221, upload-time = "2026-03-25T23:33:49.874Z" }, + { url = "https://files.pythonhosted.org/packages/aa/a8/0a90c4f0b0871e0e3d1ed126aed101328a8a57fd9fd17f00fb67e82a51ca/cryptography-46.0.6-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d24c13369e856b94892a89ddf70b332e0b70ad4a5c43cf3e9cb71d6d7ffa1f7b", size = 4408952, upload-time = "2026-03-25T23:33:52.128Z" }, + { url = "https://files.pythonhosted.org/packages/16/0b/b239701eb946523e4e9f329336e4ff32b1247e109cbab32d1a7b61da8ed7/cryptography-46.0.6-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:aad75154a7ac9039936d50cf431719a2f8d4ed3d3c277ac03f3339ded1a5e707", size = 4270141, upload-time = "2026-03-25T23:33:54.11Z" }, + { url = "https://files.pythonhosted.org/packages/0f/a8/976acdd4f0f30df7b25605f4b9d3d89295351665c2091d18224f7ad5cdbf/cryptography-46.0.6-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:3c21d92ed15e9cfc6eb64c1f5a0326db22ca9c2566ca46d845119b45b4400361", size = 4904178, upload-time = "2026-03-25T23:33:55.725Z" }, + { url = "https://files.pythonhosted.org/packages/b1/1b/bf0e01a88efd0e59679b69f42d4afd5bced8700bb5e80617b2d63a3741af/cryptography-46.0.6-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:4668298aef7cddeaf5c6ecc244c2302a2b8e40f384255505c22875eebb47888b", size = 4441812, upload-time = "2026-03-25T23:33:57.364Z" }, + { url = "https://files.pythonhosted.org/packages/bb/8b/11df86de2ea389c65aa1806f331cae145f2ed18011f30234cc10ca253de8/cryptography-46.0.6-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:8ce35b77aaf02f3b59c90b2c8a05c73bac12cea5b4e8f3fbece1f5fddea5f0ca", size = 3963923, upload-time = "2026-03-25T23:33:59.361Z" }, + { url = "https://files.pythonhosted.org/packages/91/e0/207fb177c3a9ef6a8108f234208c3e9e76a6aa8cf20d51932916bd43bda0/cryptography-46.0.6-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:c89eb37fae9216985d8734c1afd172ba4927f5a05cfd9bf0e4863c6d5465b013", size = 4269695, upload-time = "2026-03-25T23:34:00.909Z" }, + { url = "https://files.pythonhosted.org/packages/21/5e/19f3260ed1e95bced52ace7501fabcd266df67077eeb382b79c81729d2d3/cryptography-46.0.6-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:ed418c37d095aeddf5336898a132fba01091f0ac5844e3e8018506f014b6d2c4", size = 4869785, upload-time = "2026-03-25T23:34:02.796Z" }, + { url = "https://files.pythonhosted.org/packages/10/38/cd7864d79aa1d92ef6f1a584281433419b955ad5a5ba8d1eb6c872165bcb/cryptography-46.0.6-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:69cf0056d6947edc6e6760e5f17afe4bea06b56a9ac8a06de9d2bd6b532d4f3a", size = 4441404, upload-time = "2026-03-25T23:34:04.35Z" }, + { url = "https://files.pythonhosted.org/packages/09/0a/4fe7a8d25fed74419f91835cf5829ade6408fd1963c9eae9c4bce390ecbb/cryptography-46.0.6-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8e7304c4f4e9490e11efe56af6713983460ee0780f16c63f219984dab3af9d2d", size = 4397549, upload-time = "2026-03-25T23:34:06.342Z" }, + { url = "https://files.pythonhosted.org/packages/5f/a0/7d738944eac6513cd60a8da98b65951f4a3b279b93479a7e8926d9cd730b/cryptography-46.0.6-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:b928a3ca837c77a10e81a814a693f2295200adb3352395fad024559b7be7a736", size = 4651874, upload-time = "2026-03-25T23:34:07.916Z" }, + { url = "https://files.pythonhosted.org/packages/cb/f1/c2326781ca05208845efca38bf714f76939ae446cd492d7613808badedf1/cryptography-46.0.6-cp314-cp314t-win32.whl", hash = "sha256:97c8115b27e19e592a05c45d0dd89c57f81f841cc9880e353e0d3bf25b2139ed", size = 3001511, upload-time = "2026-03-25T23:34:09.892Z" }, + { url = "https://files.pythonhosted.org/packages/c9/57/fe4a23eb549ac9d903bd4698ffda13383808ef0876cc912bcb2838799ece/cryptography-46.0.6-cp314-cp314t-win_amd64.whl", hash = "sha256:c797e2517cb7880f8297e2c0f43bb910e91381339336f75d2c1c2cbf811b70b4", size = 3471692, upload-time = "2026-03-25T23:34:11.613Z" }, + { url = "https://files.pythonhosted.org/packages/c4/cc/f330e982852403da79008552de9906804568ae9230da8432f7496ce02b71/cryptography-46.0.6-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:12cae594e9473bca1a7aceb90536060643128bb274fcea0fc459ab90f7d1ae7a", size = 7162776, upload-time = "2026-03-25T23:34:13.308Z" }, + { url = "https://files.pythonhosted.org/packages/49/b3/dc27efd8dcc4bff583b3f01d4a3943cd8b5821777a58b3a6a5f054d61b79/cryptography-46.0.6-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:639301950939d844a9e1c4464d7e07f902fe9a7f6b215bb0d4f28584729935d8", size = 4270529, upload-time = "2026-03-25T23:34:15.019Z" }, + { url = "https://files.pythonhosted.org/packages/e6/05/e8d0e6eb4f0d83365b3cb0e00eb3c484f7348db0266652ccd84632a3d58d/cryptography-46.0.6-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ed3775295fb91f70b4027aeba878d79b3e55c0b3e97eaa4de71f8f23a9f2eb77", size = 4414827, upload-time = "2026-03-25T23:34:16.604Z" }, + { url = "https://files.pythonhosted.org/packages/2f/97/daba0f5d2dc6d855e2dcb70733c812558a7977a55dd4a6722756628c44d1/cryptography-46.0.6-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:8927ccfbe967c7df312ade694f987e7e9e22b2425976ddbf28271d7e58845290", size = 4271265, upload-time = "2026-03-25T23:34:18.586Z" }, + { url = "https://files.pythonhosted.org/packages/89/06/fe1fce39a37ac452e58d04b43b0855261dac320a2ebf8f5260dd55b201a9/cryptography-46.0.6-cp38-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:b12c6b1e1651e42ab5de8b1e00dc3b6354fdfd778e7fa60541ddacc27cd21410", size = 4916800, upload-time = "2026-03-25T23:34:20.561Z" }, + { url = "https://files.pythonhosted.org/packages/ff/8a/b14f3101fe9c3592603339eb5d94046c3ce5f7fc76d6512a2d40efd9724e/cryptography-46.0.6-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:063b67749f338ca9c5a0b7fe438a52c25f9526b851e24e6c9310e7195aad3b4d", size = 4448771, upload-time = "2026-03-25T23:34:22.406Z" }, + { url = "https://files.pythonhosted.org/packages/01/b3/0796998056a66d1973fd52ee89dc1bb3b6581960a91ad4ac705f182d398f/cryptography-46.0.6-cp38-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:02fad249cb0e090b574e30b276a3da6a149e04ee2f049725b1f69e7b8351ec70", size = 3978333, upload-time = "2026-03-25T23:34:24.281Z" }, + { url = "https://files.pythonhosted.org/packages/c5/3d/db200af5a4ffd08918cd55c08399dc6c9c50b0bc72c00a3246e099d3a849/cryptography-46.0.6-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:7e6142674f2a9291463e5e150090b95a8519b2fb6e6aaec8917dd8d094ce750d", size = 4271069, upload-time = "2026-03-25T23:34:25.895Z" }, + { url = "https://files.pythonhosted.org/packages/d7/18/61acfd5b414309d74ee838be321c636fe71815436f53c9f0334bf19064fa/cryptography-46.0.6-cp38-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:456b3215172aeefb9284550b162801d62f5f264a081049a3e94307fe20792cfa", size = 4878358, upload-time = "2026-03-25T23:34:27.67Z" }, + { url = "https://files.pythonhosted.org/packages/8b/65/5bf43286d566f8171917cae23ac6add941654ccf085d739195a4eacf1674/cryptography-46.0.6-cp38-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:341359d6c9e68834e204ceaf25936dffeafea3829ab80e9503860dcc4f4dac58", size = 4448061, upload-time = "2026-03-25T23:34:29.375Z" }, + { url = "https://files.pythonhosted.org/packages/e0/25/7e49c0fa7205cf3597e525d156a6bce5b5c9de1fd7e8cb01120e459f205a/cryptography-46.0.6-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:9a9c42a2723999a710445bc0d974e345c32adfd8d2fac6d8a251fa829ad31cfb", size = 4399103, upload-time = "2026-03-25T23:34:32.036Z" }, + { url = "https://files.pythonhosted.org/packages/44/46/466269e833f1c4718d6cd496ffe20c56c9c8d013486ff66b4f69c302a68d/cryptography-46.0.6-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:6617f67b1606dfd9fe4dbfa354a9508d4a6d37afe30306fe6c101b7ce3274b72", size = 4659255, upload-time = "2026-03-25T23:34:33.679Z" }, + { url = "https://files.pythonhosted.org/packages/0a/09/ddc5f630cc32287d2c953fc5d32705e63ec73e37308e5120955316f53827/cryptography-46.0.6-cp38-abi3-win32.whl", hash = "sha256:7f6690b6c55e9c5332c0b59b9c8a3fb232ebf059094c17f9019a51e9827df91c", size = 3010660, upload-time = "2026-03-25T23:34:35.418Z" }, + { url = "https://files.pythonhosted.org/packages/1b/82/ca4893968aeb2709aacfb57a30dec6fa2ab25b10fa9f064b8882ce33f599/cryptography-46.0.6-cp38-abi3-win_amd64.whl", hash = "sha256:79e865c642cfc5c0b3eb12af83c35c5aeff4fa5c672dc28c43721c2c9fdd2f0f", size = 3471160, upload-time = "2026-03-25T23:34:37.191Z" }, +] + +[[package]] +name = "cycler" +version = "0.12.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a9/95/a3dbbb5028f35eafb79008e7522a75244477d2838f38cbb722248dabc2a8/cycler-0.12.1.tar.gz", hash = "sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c", size = 7615, upload-time = "2023-10-07T05:32:18.335Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl", hash = "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30", size = 8321, upload-time = "2023-10-07T05:32:16.783Z" }, +] + +[[package]] +name = "datalayer-pycrdt" +version = "0.12.17" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/6b/85/0b46dd3db445b9ac3fae859fa6ad21b4efa54ec7ac907756e7da25c236e9/datalayer_pycrdt-0.12.17.tar.gz", hash = "sha256:9eae67e39c89508746f6571852ed903e174ab72e691ead056f9a57a302b118c1", size = 74277, upload-time = "2025-05-18T16:11:11.834Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f0/e8/70b326657902bf6c711718dcb772de5b228b169e09686bcc7e5009984241/datalayer_pycrdt-0.12.17-cp313-cp313-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:ec9c7d85e8684e54544dc2189b2ae7fefbba74471632def959d46f749610831a", size = 1651291, upload-time = "2025-05-18T16:10:21.518Z" }, + { url = "https://files.pythonhosted.org/packages/01/5e/ace988fdeae105edaa8ebe386a4cc8d8115a152af39c85e8e1230aaa6257/datalayer_pycrdt-0.12.17-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8b664d49724a07d633e3285ba08a84e0fd8f5e69f99b345b1a4a99c9bede34c", size = 898974, upload-time = "2025-05-18T16:10:23.039Z" }, + { url = "https://files.pythonhosted.org/packages/a7/bb/2b8de693c32e82d61962790e0a0a655556ba8a49d01ca8502bd13d63799a/datalayer_pycrdt-0.12.17-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6d64833b4412569d08d1377430d8ccf10ceae617ef934dbf33eaa11a5732c498", size = 931622, upload-time = "2025-05-18T16:10:24.435Z" }, + { url = "https://files.pythonhosted.org/packages/1b/b5/6e9abdd06ea214e273b5c9fb520beb7d1baade9bb4cb49766baba410848e/datalayer_pycrdt-0.12.17-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae361627668c6f3e0fdfc77969039881160341c9ed2e6e89cd714396769af3e8", size = 1120492, upload-time = "2025-05-18T16:10:25.795Z" }, + { url = "https://files.pythonhosted.org/packages/3b/5e/527c592bba2552c33008f5c259fcaa300b335390b5ba0e37b8a557e0af22/datalayer_pycrdt-0.12.17-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:355d47a0715376adc23e2b95a83b5b87d64331f03a5ba9d88dedf4325791df6c", size = 976431, upload-time = "2025-05-18T16:10:27.551Z" }, + { url = "https://files.pythonhosted.org/packages/7a/b0/f7458b39e17c0e51f5039f78d54f496db6dd13fae14a6b986c3fff52baa6/datalayer_pycrdt-0.12.17-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c7645351893604edc7324fb8bba757871c0b5bc12b5d4bcbdea1d99a13fa094", size = 928779, upload-time = "2025-05-18T16:10:28.98Z" }, + { url = "https://files.pythonhosted.org/packages/e7/c0/b7b802d01530ebf58cdf4a9bcbae3a6cf363656fe7c9e9046e1390a69ad2/datalayer_pycrdt-0.12.17-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:13a77a1e13c1cf65b249487d62ddb5738840455cc78e65dabe665bc0feee08d8", size = 1001812, upload-time = "2025-05-18T16:10:30.896Z" }, + { url = "https://files.pythonhosted.org/packages/67/fa/32396a73f5434ad95a4df3b02f4d9df4854b9357640fb6a7e608fccf1e0b/datalayer_pycrdt-0.12.17-cp313-cp313-win32.whl", hash = "sha256:11565cae105c965d27b42b59bf2b3993e973a998bb7020ecfa6153f31e0231a3", size = 667055, upload-time = "2025-05-18T16:10:32.752Z" }, + { url = "https://files.pythonhosted.org/packages/9e/b1/8426abcd0bb44a7848435e012cd361884ea5cec878cb81252de2686b8360/datalayer_pycrdt-0.12.17-cp313-cp313-win_amd64.whl", hash = "sha256:10327f0715a5929f4aaa1655e8b503570e4783733f1c9986817df183eb0c0ecd", size = 723059, upload-time = "2025-05-18T16:10:34.081Z" }, +] + +[[package]] +name = "debugpy" +version = "1.8.20" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e0/b7/cd8080344452e4874aae67c40d8940e2b4d47b01601a8fd9f44786c757c7/debugpy-1.8.20.tar.gz", hash = "sha256:55bc8701714969f1ab89a6d5f2f3d40c36f91b2cbe2f65d98bf8196f6a6a2c33", size = 1645207, upload-time = "2026-01-29T23:03:28.199Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/15/e2/fc500524cc6f104a9d049abc85a0a8b3f0d14c0a39b9c140511c61e5b40b/debugpy-1.8.20-cp313-cp313-macosx_15_0_universal2.whl", hash = "sha256:5dff4bb27027821fdfcc9e8f87309a28988231165147c31730128b1c983e282a", size = 2539560, upload-time = "2026-01-29T23:03:48.738Z" }, + { url = "https://files.pythonhosted.org/packages/90/83/fb33dcea789ed6018f8da20c5a9bc9d82adc65c0c990faed43f7c955da46/debugpy-1.8.20-cp313-cp313-manylinux_2_34_x86_64.whl", hash = "sha256:84562982dd7cf5ebebfdea667ca20a064e096099997b175fe204e86817f64eaf", size = 4293272, upload-time = "2026-01-29T23:03:50.169Z" }, + { url = "https://files.pythonhosted.org/packages/a6/25/b1e4a01bfb824d79a6af24b99ef291e24189080c93576dfd9b1a2815cd0f/debugpy-1.8.20-cp313-cp313-win32.whl", hash = "sha256:da11dea6447b2cadbf8ce2bec59ecea87cc18d2c574980f643f2d2dfe4862393", size = 5331208, upload-time = "2026-01-29T23:03:51.547Z" }, + { url = "https://files.pythonhosted.org/packages/13/f7/a0b368ce54ffff9e9028c098bd2d28cfc5b54f9f6c186929083d4c60ba58/debugpy-1.8.20-cp313-cp313-win_amd64.whl", hash = "sha256:eb506e45943cab2efb7c6eafdd65b842f3ae779f020c82221f55aca9de135ed7", size = 5372930, upload-time = "2026-01-29T23:03:53.585Z" }, + { url = "https://files.pythonhosted.org/packages/33/2e/f6cb9a8a13f5058f0a20fe09711a7b726232cd5a78c6a7c05b2ec726cff9/debugpy-1.8.20-cp314-cp314-macosx_15_0_universal2.whl", hash = "sha256:9c74df62fc064cd5e5eaca1353a3ef5a5d50da5eb8058fcef63106f7bebe6173", size = 2538066, upload-time = "2026-01-29T23:03:54.999Z" }, + { url = "https://files.pythonhosted.org/packages/c5/56/6ddca50b53624e1ca3ce1d1e49ff22db46c47ea5fb4c0cc5c9b90a616364/debugpy-1.8.20-cp314-cp314-manylinux_2_34_x86_64.whl", hash = "sha256:077a7447589ee9bc1ff0cdf443566d0ecf540ac8aa7333b775ebcb8ce9f4ecad", size = 4269425, upload-time = "2026-01-29T23:03:56.518Z" }, + { url = "https://files.pythonhosted.org/packages/c5/d9/d64199c14a0d4c476df46c82470a3ce45c8d183a6796cfb5e66533b3663c/debugpy-1.8.20-cp314-cp314-win32.whl", hash = "sha256:352036a99dd35053b37b7803f748efc456076f929c6a895556932eaf2d23b07f", size = 5331407, upload-time = "2026-01-29T23:03:58.481Z" }, + { url = "https://files.pythonhosted.org/packages/e0/d9/1f07395b54413432624d61524dfd98c1a7c7827d2abfdb8829ac92638205/debugpy-1.8.20-cp314-cp314-win_amd64.whl", hash = "sha256:a98eec61135465b062846112e5ecf2eebb855305acc1dfbae43b72903b8ab5be", size = 5372521, upload-time = "2026-01-29T23:03:59.864Z" }, + { url = "https://files.pythonhosted.org/packages/e0/c3/7f67dea8ccf8fdcb9c99033bbe3e90b9e7395415843accb81428c441be2d/debugpy-1.8.20-py2.py3-none-any.whl", hash = "sha256:5be9bed9ae3be00665a06acaa48f8329d2b9632f15fd09f6a9a8c8d9907e54d7", size = 5337658, upload-time = "2026-01-29T23:04:17.404Z" }, +] + +[[package]] +name = "decorator" +version = "5.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/43/fa/6d96a0978d19e17b68d634497769987b16c8f4cd0a7a05048bec693caa6b/decorator-5.2.1.tar.gz", hash = "sha256:65f266143752f734b0a7cc83c46f4618af75b8c5911b00ccb61d0ac9b6da0360", size = 56711, upload-time = "2025-02-24T04:41:34.073Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4e/8c/f3147f5c4b73e7550fe5f9352eaa956ae838d5c51eb58e7a25b9f3e2643b/decorator-5.2.1-py3-none-any.whl", hash = "sha256:d316bb415a2d9e2d2b3abcc4084c6502fc09240e292cd76a76afc106a1c8e04a", size = 9190, upload-time = "2025-02-24T04:41:32.565Z" }, +] + +[[package]] +name = "defusedxml" +version = "0.7.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0f/d5/c66da9b79e5bdb124974bfe172b4daf3c984ebd9c2a06e2b8a4dc7331c72/defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69", size = 75520, upload-time = "2021-03-08T10:59:26.269Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/07/6c/aa3f2f849e01cb6a001cd8554a88d4c77c5c1a31c95bdf1cf9301e6d9ef4/defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61", size = 25604, upload-time = "2021-03-08T10:59:24.45Z" }, +] + +[[package]] +name = "executing" +version = "2.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cc/28/c14e053b6762b1044f34a13aab6859bbf40456d37d23aa286ac24cfd9a5d/executing-2.2.1.tar.gz", hash = "sha256:3632cc370565f6648cc328b32435bd120a1e4ebb20c77e3fdde9a13cd1e533c4", size = 1129488, upload-time = "2025-09-01T09:48:10.866Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c1/ea/53f2148663b321f21b5a606bd5f191517cf40b7072c0497d3c92c4a13b1e/executing-2.2.1-py2.py3-none-any.whl", hash = "sha256:760643d3452b4d777d295bb167ccc74c64a81df23fb5e08eff250c425a4b2017", size = 28317, upload-time = "2025-09-01T09:48:08.5Z" }, +] + +[[package]] +name = "fastjsonschema" +version = "2.21.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/20/b5/23b216d9d985a956623b6bd12d4086b60f0059b27799f23016af04a74ea1/fastjsonschema-2.21.2.tar.gz", hash = "sha256:b1eb43748041c880796cd077f1a07c3d94e93ae84bba5ed36800a33554ae05de", size = 374130, upload-time = "2025-08-14T18:49:36.666Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cb/a8/20d0723294217e47de6d9e2e40fd4a9d2f7c4b6ef974babd482a59743694/fastjsonschema-2.21.2-py3-none-any.whl", hash = "sha256:1c797122d0a86c5cace2e54bf4e819c36223b552017172f32c5c024a6b77e463", size = 24024, upload-time = "2025-08-14T18:49:34.776Z" }, +] + +[[package]] +name = "fonttools" +version = "4.62.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/9a/08/7012b00a9a5874311b639c3920270c36ee0c445b69d9989a85e5c92ebcb0/fonttools-4.62.1.tar.gz", hash = "sha256:e54c75fd6041f1122476776880f7c3c3295ffa31962dc6ebe2543c00dca58b5d", size = 3580737, upload-time = "2026-03-13T13:54:25.52Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3b/56/6f389de21c49555553d6a5aeed5ac9767631497ac836c4f076273d15bd72/fonttools-4.62.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:c22b1014017111c401469e3acc5433e6acf6ebcc6aa9efb538a533c800971c79", size = 2865155, upload-time = "2026-03-13T13:53:16.132Z" }, + { url = "https://files.pythonhosted.org/packages/03/c5/0e3966edd5ec668d41dfe418787726752bc07e2f5fd8c8f208615e61fa89/fonttools-4.62.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:68959f5fc58ed4599b44aad161c2837477d7f35f5f79402d97439974faebfebe", size = 2412802, upload-time = "2026-03-13T13:53:18.878Z" }, + { url = "https://files.pythonhosted.org/packages/52/94/e6ac4b44026de7786fe46e3bfa0c87e51d5d70a841054065d49cd62bb909/fonttools-4.62.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ef46db46c9447103b8f3ff91e8ba009d5fe181b1920a83757a5762551e32bb68", size = 5013926, upload-time = "2026-03-13T13:53:21.379Z" }, + { url = "https://files.pythonhosted.org/packages/e2/98/8b1e801939839d405f1f122e7d175cebe9aeb4e114f95bfc45e3152af9a7/fonttools-4.62.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:6706d1cb1d5e6251a97ad3c1b9347505c5615c112e66047abbef0f8545fa30d1", size = 4964575, upload-time = "2026-03-13T13:53:23.857Z" }, + { url = "https://files.pythonhosted.org/packages/46/76/7d051671e938b1881670528fec69cc4044315edd71a229c7fd712eaa5119/fonttools-4.62.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2e7abd2b1e11736f58c1de27819e1955a53267c21732e78243fa2fa2e5c1e069", size = 4953693, upload-time = "2026-03-13T13:53:26.569Z" }, + { url = "https://files.pythonhosted.org/packages/1f/ae/b41f8628ec0be3c1b934fc12b84f4576a5c646119db4d3bdd76a217c90b5/fonttools-4.62.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:403d28ce06ebfc547fbcb0cb8b7f7cc2f7a2d3e1a67ba9a34b14632df9e080f9", size = 5094920, upload-time = "2026-03-13T13:53:29.329Z" }, + { url = "https://files.pythonhosted.org/packages/f2/f6/53a1e9469331a23dcc400970a27a4caa3d9f6edbf5baab0260285238b884/fonttools-4.62.1-cp313-cp313-win32.whl", hash = "sha256:93c316e0f5301b2adbe6a5f658634307c096fd5aae60a5b3412e4f3e1728ab24", size = 2279928, upload-time = "2026-03-13T13:53:32.352Z" }, + { url = "https://files.pythonhosted.org/packages/38/60/35186529de1db3c01f5ad625bde07c1f576305eab6d86bbda4c58445f721/fonttools-4.62.1-cp313-cp313-win_amd64.whl", hash = "sha256:7aa21ff53e28a9c2157acbc44e5b401149d3c9178107130e82d74ceb500e5056", size = 2330514, upload-time = "2026-03-13T13:53:34.991Z" }, + { url = "https://files.pythonhosted.org/packages/36/f0/2888cdac391807d68d90dcb16ef858ddc1b5309bfc6966195a459dd326e2/fonttools-4.62.1-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:fa1d16210b6b10a826d71bed68dd9ec24a9e218d5a5e2797f37c573e7ec215ca", size = 2864442, upload-time = "2026-03-13T13:53:37.509Z" }, + { url = "https://files.pythonhosted.org/packages/4b/b2/e521803081f8dc35990816b82da6360fa668a21b44da4b53fc9e77efcd62/fonttools-4.62.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:aa69d10ed420d8121118e628ad47d86e4caa79ba37f968597b958f6cceab7eca", size = 2410901, upload-time = "2026-03-13T13:53:40.55Z" }, + { url = "https://files.pythonhosted.org/packages/00/a4/8c3511ff06e53110039358dbbdc1a65d72157a054638387aa2ada300a8b8/fonttools-4.62.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bd13b7999d59c5eb1c2b442eb2d0c427cb517a0b7a1f5798fc5c9e003f5ff782", size = 4999608, upload-time = "2026-03-13T13:53:42.798Z" }, + { url = "https://files.pythonhosted.org/packages/28/63/cd0c3b26afe60995a5295f37c246a93d454023726c3261cfbb3559969bb9/fonttools-4.62.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8d337fdd49a79b0d51c4da87bc38169d21c3abbf0c1aa9367eff5c6656fb6dae", size = 4912726, upload-time = "2026-03-13T13:53:45.405Z" }, + { url = "https://files.pythonhosted.org/packages/70/b9/ac677cb07c24c685cf34f64e140617d58789d67a3dd524164b63648c6114/fonttools-4.62.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:d241cdc4a67b5431c6d7f115fdf63335222414995e3a1df1a41e1182acd4bcc7", size = 4951422, upload-time = "2026-03-13T13:53:48.326Z" }, + { url = "https://files.pythonhosted.org/packages/e6/10/11c08419a14b85b7ca9a9faca321accccc8842dd9e0b1c8a72908de05945/fonttools-4.62.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:c05557a78f8fa514da0f869556eeda40887a8abc77c76ee3f74cf241778afd5a", size = 5060979, upload-time = "2026-03-13T13:53:51.366Z" }, + { url = "https://files.pythonhosted.org/packages/4e/3c/12eea4a4cf054e7ab058ed5ceada43b46809fce2bf319017c4d63ae55bb4/fonttools-4.62.1-cp314-cp314-win32.whl", hash = "sha256:49a445d2f544ce4a69338694cad575ba97b9a75fff02720da0882d1a73f12800", size = 2283733, upload-time = "2026-03-13T13:53:53.606Z" }, + { url = "https://files.pythonhosted.org/packages/6b/67/74b070029043186b5dd13462c958cb7c7f811be0d2e634309d9a1ffb1505/fonttools-4.62.1-cp314-cp314-win_amd64.whl", hash = "sha256:1eecc128c86c552fb963fe846ca4e011b1be053728f798185a1687502f6d398e", size = 2335663, upload-time = "2026-03-13T13:53:56.23Z" }, + { url = "https://files.pythonhosted.org/packages/42/c5/4d2ed3ca6e33617fc5624467da353337f06e7f637707478903c785bd8e20/fonttools-4.62.1-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:1596aeaddf7f78e21e68293c011316a25267b3effdaccaf4d59bc9159d681b82", size = 2947288, upload-time = "2026-03-13T13:53:59.397Z" }, + { url = "https://files.pythonhosted.org/packages/1f/e9/7ab11ddfda48ed0f89b13380e5595ba572619c27077be0b2c447a63ff351/fonttools-4.62.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:8f8fca95d3bb3208f59626a4b0ea6e526ee51f5a8ad5d91821c165903e8d9260", size = 2449023, upload-time = "2026-03-13T13:54:01.642Z" }, + { url = "https://files.pythonhosted.org/packages/b2/10/a800fa090b5e8819942e54e19b55fc7c21fe14a08757c3aa3ca8db358939/fonttools-4.62.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee91628c08e76f77b533d65feb3fbe6d9dad699f95be51cf0d022db94089cdc4", size = 5137599, upload-time = "2026-03-13T13:54:04.495Z" }, + { url = "https://files.pythonhosted.org/packages/37/dc/8ccd45033fffd74deb6912fa1ca524643f584b94c87a16036855b498a1ed/fonttools-4.62.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:5f37df1cac61d906e7b836abe356bc2f34c99d4477467755c216b72aa3dc748b", size = 4920933, upload-time = "2026-03-13T13:54:07.557Z" }, + { url = "https://files.pythonhosted.org/packages/99/eb/e618adefb839598d25ac8136cd577925d6c513dc0d931d93b8af956210f0/fonttools-4.62.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:92bb00a947e666169c99b43753c4305fc95a890a60ef3aeb2a6963e07902cc87", size = 5016232, upload-time = "2026-03-13T13:54:10.611Z" }, + { url = "https://files.pythonhosted.org/packages/d9/5f/9b5c9bfaa8ec82def8d8168c4f13615990d6ce5996fe52bd49bfb5e05134/fonttools-4.62.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:bdfe592802ef939a0e33106ea4a318eeb17822c7ee168c290273cbd5fabd746c", size = 5042987, upload-time = "2026-03-13T13:54:13.569Z" }, + { url = "https://files.pythonhosted.org/packages/90/aa/dfbbe24c6a6afc5c203d90cc0343e24bcbb09e76d67c4d6eef8c2558d7ba/fonttools-4.62.1-cp314-cp314t-win32.whl", hash = "sha256:b820fcb92d4655513d8402d5b219f94481c4443d825b4372c75a2072aa4b357a", size = 2348021, upload-time = "2026-03-13T13:54:16.98Z" }, + { url = "https://files.pythonhosted.org/packages/13/6f/ae9c4e4dd417948407b680855c2c7790efb52add6009aaecff1e3bc50e8e/fonttools-4.62.1-cp314-cp314t-win_amd64.whl", hash = "sha256:59b372b4f0e113d3746b88985f1c796e7bf830dd54b28374cd85c2b8acd7583e", size = 2414147, upload-time = "2026-03-13T13:54:19.416Z" }, + { url = "https://files.pythonhosted.org/packages/fd/ba/56147c165442cc5ba7e82ecf301c9a68353cede498185869e6e02b4c264f/fonttools-4.62.1-py3-none-any.whl", hash = "sha256:7487782e2113861f4ddcc07c3436450659e3caa5e470b27dc2177cade2d8e7fd", size = 1152647, upload-time = "2026-03-13T13:54:22.735Z" }, +] + +[[package]] +name = "fqdn" +version = "1.5.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/30/3e/a80a8c077fd798951169626cde3e239adeba7dab75deb3555716415bd9b0/fqdn-1.5.1.tar.gz", hash = "sha256:105ed3677e767fb5ca086a0c1f4bb66ebc3c100be518f0e0d755d9eae164d89f", size = 6015, upload-time = "2021-03-11T07:16:29.08Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cf/58/8acf1b3e91c58313ce5cb67df61001fc9dcd21be4fadb76c1a2d540e09ed/fqdn-1.5.1-py3-none-any.whl", hash = "sha256:3a179af3761e4df6eb2e026ff9e1a3033d3587bf980a0b1b2e1e5d08d7358014", size = 9121, upload-time = "2021-03-11T07:16:28.351Z" }, +] + +[[package]] +name = "h11" +version = "0.16.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/01/ee/02a2c011bdab74c6fb3c75474d40b3052059d95df7e73351460c8588d963/h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", size = 101250, upload-time = "2025-04-24T03:35:25.427Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload-time = "2025-04-24T03:35:24.344Z" }, +] + +[[package]] +name = "httpcore" +version = "1.0.9" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "h11" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/06/94/82699a10bca87a5556c9c59b5963f2d039dbd239f25bc2a63907a05a14cb/httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8", size = 85484, upload-time = "2025-04-24T22:06:22.219Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", size = 78784, upload-time = "2025-04-24T22:06:20.566Z" }, +] + +[[package]] +name = "httpx" +version = "0.28.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "certifi" }, + { name = "httpcore" }, + { name = "idna" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406, upload-time = "2024-12-06T15:37:23.222Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517, upload-time = "2024-12-06T15:37:21.509Z" }, +] + +[[package]] +name = "httpx-sse" +version = "0.4.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0f/4c/751061ffa58615a32c31b2d82e8482be8dd4a89154f003147acee90f2be9/httpx_sse-0.4.3.tar.gz", hash = "sha256:9b1ed0127459a66014aec3c56bebd93da3c1bc8bb6618c8082039a44889a755d", size = 15943, upload-time = "2025-10-10T21:48:22.271Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d2/fd/6668e5aec43ab844de6fc74927e155a3b37bf40d7c3790e49fc0406b6578/httpx_sse-0.4.3-py3-none-any.whl", hash = "sha256:0ac1c9fe3c0afad2e0ebb25a934a59f4c7823b60792691f779fad2c5568830fc", size = 8960, upload-time = "2025-10-10T21:48:21.158Z" }, +] + +[[package]] +name = "idna" +version = "3.11" +source = { registry = "https://pypi.org/simple" } +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/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 = "ipykernel" +version = "7.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "appnope", marker = "sys_platform == 'darwin'" }, + { name = "comm" }, + { name = "debugpy" }, + { name = "ipython" }, + { name = "jupyter-client" }, + { name = "jupyter-core" }, + { name = "matplotlib-inline" }, + { name = "nest-asyncio" }, + { name = "packaging" }, + { name = "psutil" }, + { name = "pyzmq" }, + { name = "tornado" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ca/8d/b68b728e2d06b9e0051019640a40a9eb7a88fcd82c2e1b5ce70bef5ff044/ipykernel-7.2.0.tar.gz", hash = "sha256:18ed160b6dee2cbb16e5f3575858bc19d8f1fe6046a9a680c708494ce31d909e", size = 176046, upload-time = "2026-02-06T16:43:27.403Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/82/b9/e73d5d9f405cba7706c539aa8b311b49d4c2f3d698d9c12f815231169c71/ipykernel-7.2.0-py3-none-any.whl", hash = "sha256:3bbd4420d2b3cc105cbdf3756bfc04500b1e52f090a90716851f3916c62e1661", size = 118788, upload-time = "2026-02-06T16:43:25.149Z" }, +] + +[[package]] +name = "ipython" +version = "9.12.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "decorator" }, + { name = "ipython-pygments-lexers" }, + { name = "jedi" }, + { name = "matplotlib-inline" }, + { name = "pexpect", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" }, + { name = "prompt-toolkit" }, + { name = "pygments" }, + { name = "stack-data" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/3a/73/7114f80a8f9cabdb13c27732dce24af945b2923dcab80723602f7c8bc2d8/ipython-9.12.0.tar.gz", hash = "sha256:01daa83f504b693ba523b5a407246cabde4eb4513285a3c6acaff11a66735ee4", size = 4428879, upload-time = "2026-03-27T09:42:45.312Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/59/22/906c8108974c673ebef6356c506cebb6870d48cedea3c41e949e2dd556bb/ipython-9.12.0-py3-none-any.whl", hash = "sha256:0f2701e8ee86e117e37f50563205d36feaa259d2e08d4a6bc6b6d74b18ce128d", size = 625661, upload-time = "2026-03-27T09:42:42.831Z" }, +] + +[[package]] +name = "ipython-pygments-lexers" +version = "1.1.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pygments" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ef/4c/5dd1d8af08107f88c7f741ead7a40854b8ac24ddf9ae850afbcf698aa552/ipython_pygments_lexers-1.1.1.tar.gz", hash = "sha256:09c0138009e56b6854f9535736f4171d855c8c08a563a0dcd8022f78355c7e81", size = 8393, upload-time = "2025-01-17T11:24:34.505Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d9/33/1f075bf72b0b747cb3288d011319aaf64083cf2efef8354174e3ed4540e2/ipython_pygments_lexers-1.1.1-py3-none-any.whl", hash = "sha256:a9462224a505ade19a605f71f8fa63c2048833ce50abc86768a0d81d876dc81c", size = 8074, upload-time = "2025-01-17T11:24:33.271Z" }, +] + +[[package]] +name = "ipywidgets" +version = "8.1.8" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "comm" }, + { name = "ipython" }, + { name = "jupyterlab-widgets" }, + { name = "traitlets" }, + { name = "widgetsnbextension" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/4c/ae/c5ce1edc1afe042eadb445e95b0671b03cee61895264357956e61c0d2ac0/ipywidgets-8.1.8.tar.gz", hash = "sha256:61f969306b95f85fba6b6986b7fe45d73124d1d9e3023a8068710d47a22ea668", size = 116739, upload-time = "2025-11-01T21:18:12.393Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/56/6d/0d9848617b9f753b87f214f1c682592f7ca42de085f564352f10f0843026/ipywidgets-8.1.8-py3-none-any.whl", hash = "sha256:ecaca67aed704a338f88f67b1181b58f821ab5dc89c1f0f5ef99db43c1c2921e", size = 139808, upload-time = "2025-11-01T21:18:10.956Z" }, +] + +[[package]] +name = "isoduration" +version = "20.11.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "arrow" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7c/1a/3c8edc664e06e6bd06cce40c6b22da5f1429aa4224d0c590f3be21c91ead/isoduration-20.11.0.tar.gz", hash = "sha256:ac2f9015137935279eac671f94f89eb00584f940f5dc49462a0c4ee692ba1bd9", size = 11649, upload-time = "2020-11-01T11:00:00.312Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7b/55/e5326141505c5d5e34c5e0935d2908a74e4561eca44108fbfb9c13d2911a/isoduration-20.11.0-py3-none-any.whl", hash = "sha256:b2904c2a4228c3d44f409c8ae8e2370eb21a26f7ac2ec5446df141dde3452042", size = 11321, upload-time = "2020-11-01T10:59:58.02Z" }, +] + +[[package]] +name = "jedi" +version = "0.19.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "parso" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/72/3a/79a912fbd4d8dd6fbb02bf69afd3bb72cf0c729bb3063c6f4498603db17a/jedi-0.19.2.tar.gz", hash = "sha256:4770dc3de41bde3966b02eb84fbcf557fb33cce26ad23da12c742fb50ecb11f0", size = 1231287, upload-time = "2024-11-11T01:41:42.873Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c0/5a/9cac0c82afec3d09ccd97c8b6502d48f165f9124db81b4bcb90b4af974ee/jedi-0.19.2-py2.py3-none-any.whl", hash = "sha256:a8ef22bde8490f57fe5c7681a3c83cb58874daf72b4784de3cce5b6ef6edb5b9", size = 1572278, upload-time = "2024-11-11T01:41:40.175Z" }, +] + +[[package]] +name = "jinja2" +version = "3.1.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markupsafe" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115, upload-time = "2025-03-05T20:05:02.478Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" }, +] + +[[package]] +name = "json5" +version = "0.14.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/9c/4b/6f8906aaf67d501e259b0adab4d312945bb7211e8b8d4dcc77c92320edaa/json5-0.14.0.tar.gz", hash = "sha256:b3f492fad9f6cdbced8b7d40b28b9b1c9701c5f561bef0d33b81c2ff433fefcb", size = 52656, upload-time = "2026-03-27T22:50:48.108Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b8/42/cf027b4ac873b076189d935b135397675dac80cb29acb13e1ab86ad6c631/json5-0.14.0-py3-none-any.whl", hash = "sha256:56cf861bab076b1178eb8c92e1311d273a9b9acea2ccc82c276abf839ebaef3a", size = 36271, upload-time = "2026-03-27T22:50:47.073Z" }, +] + +[[package]] +name = "jsonpointer" +version = "3.1.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/18/c7/af399a2e7a67fd18d63c40c5e62d3af4e67b836a2107468b6a5ea24c4304/jsonpointer-3.1.1.tar.gz", hash = "sha256:0b801c7db33a904024f6004d526dcc53bbb8a4a0f4e32bfd10beadf60adf1900", size = 9068, upload-time = "2026-03-23T22:32:32.458Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9e/6a/a83720e953b1682d2d109d3c2dbb0bc9bf28cc1cbc205be4ef4be5da709d/jsonpointer-3.1.1-py3-none-any.whl", hash = "sha256:8ff8b95779d071ba472cf5bc913028df06031797532f08a7d5b602d8b2a488ca", size = 7659, upload-time = "2026-03-23T22:32:31.568Z" }, +] + +[[package]] +name = "jsonschema" +version = "4.26.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "jsonschema-specifications" }, + { name = "referencing" }, + { name = "rpds-py" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b3/fc/e067678238fa451312d4c62bf6e6cf5ec56375422aee02f9cb5f909b3047/jsonschema-4.26.0.tar.gz", hash = "sha256:0c26707e2efad8aa1bfc5b7ce170f3fccc2e4918ff85989ba9ffa9facb2be326", size = 366583, upload-time = "2026-01-07T13:41:07.246Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/69/90/f63fb5873511e014207a475e2bb4e8b2e570d655b00ac19a9a0ca0a385ee/jsonschema-4.26.0-py3-none-any.whl", hash = "sha256:d489f15263b8d200f8387e64b4c3a75f06629559fb73deb8fdfb525f2dab50ce", size = 90630, upload-time = "2026-01-07T13:41:05.306Z" }, +] + +[package.optional-dependencies] +format-nongpl = [ + { name = "fqdn" }, + { name = "idna" }, + { name = "isoduration" }, + { name = "jsonpointer" }, + { name = "rfc3339-validator" }, + { name = "rfc3986-validator" }, + { name = "rfc3987-syntax" }, + { name = "uri-template" }, + { name = "webcolors" }, +] + +[[package]] +name = "jsonschema-specifications" +version = "2025.9.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "referencing" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/19/74/a633ee74eb36c44aa6d1095e7cc5569bebf04342ee146178e2d36600708b/jsonschema_specifications-2025.9.1.tar.gz", hash = "sha256:b540987f239e745613c7a9176f3edb72b832a4ac465cf02712288397832b5e8d", size = 32855, upload-time = "2025-09-08T01:34:59.186Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl", hash = "sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe", size = 18437, upload-time = "2025-09-08T01:34:57.871Z" }, +] + +[[package]] +name = "jupyter" +version = "1.1.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "ipykernel" }, + { name = "ipywidgets" }, + { name = "jupyter-console" }, + { name = "jupyterlab" }, + { name = "nbconvert" }, + { name = "notebook" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/58/f3/af28ea964ab8bc1e472dba2e82627d36d470c51f5cd38c37502eeffaa25e/jupyter-1.1.1.tar.gz", hash = "sha256:d55467bceabdea49d7e3624af7e33d59c37fff53ed3a350e1ac957bed731de7a", size = 5714959, upload-time = "2024-08-30T07:15:48.299Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/38/64/285f20a31679bf547b75602702f7800e74dbabae36ef324f716c02804753/jupyter-1.1.1-py2.py3-none-any.whl", hash = "sha256:7a59533c22af65439b24bbe60373a4e95af8f16ac65a6c00820ad378e3f7cc83", size = 2657, upload-time = "2024-08-30T07:15:47.045Z" }, +] + +[[package]] +name = "jupyter-client" +version = "8.8.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jupyter-core" }, + { name = "python-dateutil" }, + { name = "pyzmq" }, + { name = "tornado" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/05/e4/ba649102a3bc3fbca54e7239fb924fd434c766f855693d86de0b1f2bec81/jupyter_client-8.8.0.tar.gz", hash = "sha256:d556811419a4f2d96c869af34e854e3f059b7cc2d6d01a9cd9c85c267691be3e", size = 348020, upload-time = "2026-01-08T13:55:47.938Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2d/0b/ceb7694d864abc0a047649aec263878acb9f792e1fec3e676f22dc9015e3/jupyter_client-8.8.0-py3-none-any.whl", hash = "sha256:f93a5b99c5e23a507b773d3a1136bd6e16c67883ccdbd9a829b0bbdb98cd7d7a", size = 107371, upload-time = "2026-01-08T13:55:45.562Z" }, +] + +[[package]] +name = "jupyter-collaboration" +version = "4.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jupyter-collaboration-ui" }, + { name = "jupyter-docprovider" }, + { name = "jupyter-server-ydoc" }, + { name = "jupyterlab" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7b/b7/86b8f2aca6a554668c55c88401ba9ba6e355fdcc7d71cb3dd0bec85c330e/jupyter_collaboration-4.3.0.tar.gz", hash = "sha256:6ef03664fdda0fddf47d2904db29a659c8ef4d2f307080b89cdef72e7e7b24c9", size = 3734, upload-time = "2026-03-31T10:08:36.166Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e4/1b/b518e55344a2bb787a8025d6cb51353b91d7af07e3756cc06b2ecb88098d/jupyter_collaboration-4.3.0-py3-none-any.whl", hash = "sha256:6dd3d7129e95a04e11f1fd22915f167023bebd4badc4cf1b71f73fb2690f5648", size = 4751, upload-time = "2026-03-31T10:08:34.383Z" }, +] + +[[package]] +name = "jupyter-collaboration-ui" +version = "2.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0a/cf/bbf8f4b6f27a91c5addd3e8371bb97939a1f9bf0bf988d9961532f9c26a6/jupyter_collaboration_ui-2.3.0.tar.gz", hash = "sha256:835e818614eb39645f2f583a57b2246d8d1ecff4ffd2d481ab4a6f6b2c45b997", size = 77339, upload-time = "2026-03-31T10:08:13.898Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/36/63/a1f297c16092e44a7e143fe4f414317057b8e2acf33ce3c182cd2b08c291/jupyter_collaboration_ui-2.3.0-py3-none-any.whl", hash = "sha256:e8b9f026615e9ed448b1518bb74f044e15519ad5282976fa54c002f2572139c0", size = 46498, upload-time = "2026-03-31T10:08:12.167Z" }, +] + +[[package]] +name = "jupyter-console" +version = "6.6.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "ipykernel" }, + { name = "ipython" }, + { name = "jupyter-client" }, + { name = "jupyter-core" }, + { name = "prompt-toolkit" }, + { name = "pygments" }, + { name = "pyzmq" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/bd/2d/e2fd31e2fc41c14e2bcb6c976ab732597e907523f6b2420305f9fc7fdbdb/jupyter_console-6.6.3.tar.gz", hash = "sha256:566a4bf31c87adbfadf22cdf846e3069b59a71ed5da71d6ba4d8aaad14a53539", size = 34363, upload-time = "2023-03-06T14:13:31.02Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ca/77/71d78d58f15c22db16328a476426f7ac4a60d3a5a7ba3b9627ee2f7903d4/jupyter_console-6.6.3-py3-none-any.whl", hash = "sha256:309d33409fcc92ffdad25f0bcdf9a4a9daa61b6f341177570fdac03de5352485", size = 24510, upload-time = "2023-03-06T14:13:28.229Z" }, +] + +[[package]] +name = "jupyter-core" +version = "5.9.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "platformdirs" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/02/49/9d1284d0dc65e2c757b74c6687b6d319b02f822ad039e5c512df9194d9dd/jupyter_core-5.9.1.tar.gz", hash = "sha256:4d09aaff303b9566c3ce657f580bd089ff5c91f5f89cf7d8846c3cdf465b5508", size = 89814, upload-time = "2025-10-16T19:19:18.444Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e7/e7/80988e32bf6f73919a113473a604f5a8f09094de312b9d52b79c2df7612b/jupyter_core-5.9.1-py3-none-any.whl", hash = "sha256:ebf87fdc6073d142e114c72c9e29a9d7ca03fad818c5d300ce2adc1fb0743407", size = 29032, upload-time = "2025-10-16T19:19:16.783Z" }, +] + +[[package]] +name = "jupyter-docprovider" +version = "2.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d8/d3/45571d4a7a4a2024750e582c17c1311052476dab4a2a02dbd68c7b5d0df0/jupyter_docprovider-2.3.0.tar.gz", hash = "sha256:c09808e15e93f2ea4ff194a18c7a8c8f83d81049fa91b09de24b09adeac9d572", size = 49964, upload-time = "2026-03-31T10:08:25.383Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/74/4a/af30f008f176d38c183a107b6556ba36f9e1a9970d5f730739bed4663c4a/jupyter_docprovider-2.3.0-py3-none-any.whl", hash = "sha256:44f9a8bfa47f069154e111b869f71c0e4297f201c56fa15ff308fe4b64c50f43", size = 35575, upload-time = "2026-03-31T10:08:23.534Z" }, +] + +[[package]] +name = "jupyter-events" +version = "0.12.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jsonschema", extra = ["format-nongpl"] }, + { name = "packaging" }, + { name = "python-json-logger" }, + { name = "pyyaml" }, + { name = "referencing" }, + { name = "rfc3339-validator" }, + { name = "rfc3986-validator" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9d/c3/306d090461e4cf3cd91eceaff84bede12a8e52cd821c2d20c9a4fd728385/jupyter_events-0.12.0.tar.gz", hash = "sha256:fc3fce98865f6784c9cd0a56a20644fc6098f21c8c33834a8d9fe383c17e554b", size = 62196, upload-time = "2025-02-03T17:23:41.485Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e2/48/577993f1f99c552f18a0428731a755e06171f9902fa118c379eb7c04ea22/jupyter_events-0.12.0-py3-none-any.whl", hash = "sha256:6464b2fa5ad10451c3d35fabc75eab39556ae1e2853ad0c0cc31b656731a97fb", size = 19430, upload-time = "2025-02-03T17:23:38.643Z" }, +] + +[[package]] +name = "jupyter-kernel-client" +version = "0.9.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jupyter-client" }, + { name = "jupyter-core" }, + { name = "jupyter-mimetypes" }, + { name = "requests" }, + { name = "traitlets" }, + { name = "typing-extensions" }, + { name = "websocket-client" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/7a/68/287315ba355aa93bda2e344de5febc45e6de1b47d8f4a5b69400b24cfdfd/jupyter_kernel_client-0.9.0-py3-none-any.whl", hash = "sha256:77acb8f2f738d97625d6bd01ee8cf21c4d59790b7ba464108712db3870416f20", size = 40097, upload-time = "2026-02-11T06:42:05.133Z" }, +] + +[[package]] +name = "jupyter-lsp" +version = "2.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jupyter-server" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/36/ff/1e4a61f5170a9a1d978f3ac3872449de6c01fc71eaf89657824c878b1549/jupyter_lsp-2.3.1.tar.gz", hash = "sha256:fdf8a4aa7d85813976d6e29e95e6a2c8f752701f926f2715305249a3829805a6", size = 55677, upload-time = "2026-04-02T08:10:06.749Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/23/e8/9d61dcbd1dce8ef418f06befd4ac084b4720429c26b0b1222bc218685eff/jupyter_lsp-2.3.1-py3-none-any.whl", hash = "sha256:71b954d834e85ff3096400554f2eefaf7fe37053036f9a782b0f7c5e42dadb81", size = 77513, upload-time = "2026-04-02T08:10:01.753Z" }, +] + +[[package]] +name = "jupyter-mcp-server" +version = "0.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jupyter-kernel-client" }, + { name = "jupyter-nbmodel-client" }, + { name = "mcp", extra = ["cli"] }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/93/2f/0383d2b3b752a411abcb52dc3da7b7f064ecb8b902ed1c06dba5b57ac5c4/jupyter_mcp_server-0.4.0-py3-none-any.whl", hash = "sha256:54229b6201005f123479bdca1525a1d358af846027dd3067e4a37db128b87217", size = 7636, upload-time = "2025-06-13T07:51:11.072Z" }, +] + +[[package]] +name = "jupyter-mimetypes" +version = "0.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pyarrow" }, + { name = "typing-extensions" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/72/45/cb4671e13fed39f721066ad1a00714d4b607982b8d3e97a25f836198d1df/jupyter_mimetypes-0.2.0-py3-none-any.whl", hash = "sha256:e6dcd989258e3fc944365b656d9173191517e0e393bd878e97ce500e5b388527", size = 16724, upload-time = "2025-08-10T18:18:27.309Z" }, +] + +[[package]] +name = "jupyter-nbmodel-client" +version = "0.11.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "datalayer-pycrdt" }, + { name = "jupyter-ydoc" }, + { name = "nbformat" }, + { name = "requests" }, + { name = "websockets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/de/25/9dc9a4247fac5f4b5a13c1455f6a0e52538b26d877b5de93682a1aee3782/jupyter_nbmodel_client-0.11.2.tar.gz", hash = "sha256:fcf35823a5843ce7824f8411ab08d78fef1d07c306a5e195ce1777ba9ce0683e", size = 25761, upload-time = "2025-03-25T15:09:59.127Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d3/60/e4de22326a765696746529c355a2cedc622bd18708c40b1ebcdc6839ddcb/jupyter_nbmodel_client-0.11.2-py3-none-any.whl", hash = "sha256:dfaec212064d16532b2bc93472aaec93c54b350efde342f581ba3bfad1e718d2", size = 26061, upload-time = "2025-03-25T15:09:57.266Z" }, +] + +[[package]] +name = "jupyter-server" +version = "2.17.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "argon2-cffi" }, + { name = "jinja2" }, + { name = "jupyter-client" }, + { name = "jupyter-core" }, + { name = "jupyter-events" }, + { name = "jupyter-server-terminals" }, + { name = "nbconvert" }, + { name = "nbformat" }, + { name = "packaging" }, + { name = "prometheus-client" }, + { name = "pywinpty", marker = "os_name == 'nt'" }, + { name = "pyzmq" }, + { name = "send2trash" }, + { name = "terminado" }, + { name = "tornado" }, + { name = "traitlets" }, + { name = "websocket-client" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5b/ac/e040ec363d7b6b1f11304cc9f209dac4517ece5d5e01821366b924a64a50/jupyter_server-2.17.0.tar.gz", hash = "sha256:c38ea898566964c888b4772ae1ed58eca84592e88251d2cfc4d171f81f7e99d5", size = 731949, upload-time = "2025-08-21T14:42:54.042Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/92/80/a24767e6ca280f5a49525d987bf3e4d7552bf67c8be07e8ccf20271f8568/jupyter_server-2.17.0-py3-none-any.whl", hash = "sha256:e8cb9c7db4251f51ed307e329b81b72ccf2056ff82d50524debde1ee1870e13f", size = 388221, upload-time = "2025-08-21T14:42:52.034Z" }, +] + +[[package]] +name = "jupyter-server-fileid" +version = "0.9.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jupyter-events" }, + { name = "jupyter-server" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/0d/eb/7c2c09454bbf66b3727ba8c431d16159d642c0eb1aa179412a4f7af721cf/jupyter_server_fileid-0.9.3.tar.gz", hash = "sha256:521608bb87f606a8637fcbdce2f3d24a8b3cc89d2eef61751cb40e468d4e54be", size = 54959, upload-time = "2024-09-06T07:18:40.412Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/54/d6/5e5bca083664b1dd368e261107cbe2d350e3bdc62bdba8720fdbb9b9db39/jupyter_server_fileid-0.9.3-py3-none-any.whl", hash = "sha256:f73c01c19f90005d3fff93607b91b4955ba4e1dccdde9bfe8026646f94053791", size = 16922, upload-time = "2024-09-06T07:18:38.445Z" }, +] + +[[package]] +name = "jupyter-server-terminals" +version = "0.5.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pywinpty", marker = "os_name == 'nt'" }, + { name = "terminado" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f4/a7/bcd0a9b0cbba88986fe944aaaf91bfda603e5a50bda8ed15123f381a3b2f/jupyter_server_terminals-0.5.4.tar.gz", hash = "sha256:bbda128ed41d0be9020349f9f1f2a4ab9952a73ed5f5ac9f1419794761fb87f5", size = 31770, upload-time = "2026-01-14T16:53:20.213Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/2d/6674563f71c6320841fc300911a55143925112a72a883e2ca71fba4c618d/jupyter_server_terminals-0.5.4-py3-none-any.whl", hash = "sha256:55be353fc74a80bc7f3b20e6be50a55a61cd525626f578dcb66a5708e2007d14", size = 13704, upload-time = "2026-01-14T16:53:18.738Z" }, +] + +[[package]] +name = "jupyter-server-ydoc" +version = "2.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jsonschema" }, + { name = "jupyter-events" }, + { name = "jupyter-server" }, + { name = "jupyter-server-fileid" }, + { name = "jupyter-ydoc" }, + { name = "pycrdt" }, + { name = "pycrdt-websocket" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f1/88/f81afcbd7cfca28c4d04086360a623319220f46a87f3206c1672f0411441/jupyter_server_ydoc-2.3.0.tar.gz", hash = "sha256:36f311491e9f289f461fcdf26afb9b72cdf0eac3ceed0c0cbc8ec43afc8efebc", size = 32103, upload-time = "2026-03-31T10:08:02.176Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cd/73/18007b4fad0813a039b0c63c40b2f34f0f65f278c1d1670a323ff2d18638/jupyter_server_ydoc-2.3.0-py3-none-any.whl", hash = "sha256:888c4092592585f80d34f81e093aee4ce1b9d2e2601efb9e65eb5bdd23893a79", size = 33275, upload-time = "2026-03-31T10:08:00.239Z" }, +] + +[[package]] +name = "jupyter-ydoc" +version = "3.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "pycrdt" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/34/f5/2b68223759a2922f34ecba7aa164299ce30dfb44cafe27a84acf7a52e32a/jupyter_ydoc-3.4.0.tar.gz", hash = "sha256:d2418e42878cabf3d9208b2ecfaf5d8a6e140485fec8b738133168e60b83c89e", size = 973078, upload-time = "2026-02-06T14:13:34.512Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/27/f6/1032c5db3dc068c3e581db2ceb05486c9bf9d87f5833334ab13e802bc045/jupyter_ydoc-3.4.0-py3-none-any.whl", hash = "sha256:089a58209200cac8b90d66dae3f440e2d2c6701591732adcec274f842fdf963d", size = 14447, upload-time = "2026-02-06T14:13:33.061Z" }, +] + +[[package]] +name = "jupyterlab" +version = "4.5.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "async-lru" }, + { name = "httpx" }, + { name = "ipykernel" }, + { name = "jinja2" }, + { name = "jupyter-core" }, + { name = "jupyter-lsp" }, + { name = "jupyter-server" }, + { name = "jupyterlab-server" }, + { name = "notebook-shim" }, + { name = "packaging" }, + { name = "setuptools" }, + { name = "tornado" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ac/d5/730628e03fff2e8a8e8ccdaedde1489ab1309f9a4fa2536248884e30b7c7/jupyterlab-4.5.6.tar.gz", hash = "sha256:642fe2cfe7f0f5922a8a558ba7a0d246c7bc133b708dfe43f7b3a826d163cf42", size = 23970670, upload-time = "2026-03-11T14:17:04.531Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e1/1b/dad6fdcc658ed7af26fdf3841e7394072c9549a8b896c381ab49dd11e2d9/jupyterlab-4.5.6-py3-none-any.whl", hash = "sha256:d6b3dac883aa4d9993348e0f8e95b24624f75099aed64eab6a4351a9cdd1e580", size = 12447124, upload-time = "2026-03-11T14:17:00.229Z" }, +] + +[[package]] +name = "jupyterlab-pygments" +version = "0.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/90/51/9187be60d989df97f5f0aba133fa54e7300f17616e065d1ada7d7646b6d6/jupyterlab_pygments-0.3.0.tar.gz", hash = "sha256:721aca4d9029252b11cfa9d185e5b5af4d54772bb8072f9b7036f4170054d35d", size = 512900, upload-time = "2023-11-23T09:26:37.44Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b1/dd/ead9d8ea85bf202d90cc513b533f9c363121c7792674f78e0d8a854b63b4/jupyterlab_pygments-0.3.0-py3-none-any.whl", hash = "sha256:841a89020971da1d8693f1a99997aefc5dc424bb1b251fd6322462a1b8842780", size = 15884, upload-time = "2023-11-23T09:26:34.325Z" }, +] + +[[package]] +name = "jupyterlab-server" +version = "2.28.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "babel" }, + { name = "jinja2" }, + { name = "json5" }, + { name = "jsonschema" }, + { name = "jupyter-server" }, + { name = "packaging" }, + { name = "requests" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d6/2c/90153f189e421e93c4bb4f9e3f59802a1f01abd2ac5cf40b152d7f735232/jupyterlab_server-2.28.0.tar.gz", hash = "sha256:35baa81898b15f93573e2deca50d11ac0ae407ebb688299d3a5213265033712c", size = 76996, upload-time = "2025-10-22T13:59:18.37Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e0/07/a000fe835f76b7e1143242ab1122e6362ef1c03f23f83a045c38859c2ae0/jupyterlab_server-2.28.0-py3-none-any.whl", hash = "sha256:e4355b148fdcf34d312bbbc80f22467d6d20460e8b8736bf235577dd18506968", size = 59830, upload-time = "2025-10-22T13:59:16.767Z" }, +] + +[[package]] +name = "jupyterlab-widgets" +version = "3.0.16" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/26/2d/ef58fed122b268c69c0aa099da20bc67657cdfb2e222688d5731bd5b971d/jupyterlab_widgets-3.0.16.tar.gz", hash = "sha256:423da05071d55cf27a9e602216d35a3a65a3e41cdf9c5d3b643b814ce38c19e0", size = 897423, upload-time = "2025-11-01T21:11:29.724Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl", hash = "sha256:45fa36d9c6422cf2559198e4db481aa243c7a32d9926b500781c830c80f7ecf8", size = 914926, upload-time = "2025-11-01T21:11:28.008Z" }, +] + +[[package]] +name = "kiwisolver" +version = "1.5.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d0/67/9c61eccb13f0bdca9307614e782fec49ffdde0f7a2314935d489fa93cd9c/kiwisolver-1.5.0.tar.gz", hash = "sha256:d4193f3d9dc3f6f79aaed0e5637f45d98850ebf01f7ca20e69457f3e8946b66a", size = 103482, upload-time = "2026-03-09T13:15:53.382Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9d/69/024d6711d5ba575aa65d5538042e99964104e97fa153a9f10bc369182bc2/kiwisolver-1.5.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:fd40bb9cd0891c4c3cb1ddf83f8bbfa15731a248fdc8162669405451e2724b09", size = 123166, upload-time = "2026-03-09T13:13:48.032Z" }, + { url = "https://files.pythonhosted.org/packages/ce/48/adbb40df306f587054a348831220812b9b1d787aff714cfbc8556e38fccd/kiwisolver-1.5.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c0e1403fd7c26d77c1f03e096dc58a5c726503fa0db0456678b8668f76f521e3", size = 66395, upload-time = "2026-03-09T13:13:49.365Z" }, + { url = "https://files.pythonhosted.org/packages/a8/3a/d0a972b34e1c63e2409413104216cd1caa02c5a37cb668d1687d466c1c45/kiwisolver-1.5.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:dda366d548e89a90d88a86c692377d18d8bd64b39c1fb2b92cb31370e2896bbd", size = 64065, upload-time = "2026-03-09T13:13:50.562Z" }, + { url = "https://files.pythonhosted.org/packages/2b/0a/7b98e1e119878a27ba8618ca1e18b14f992ff1eda40f47bccccf4de44121/kiwisolver-1.5.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:332b4f0145c30b5f5ad9374881133e5aa64320428a57c2c2b61e9d891a51c2f3", size = 1477903, upload-time = "2026-03-09T13:13:52.084Z" }, + { url = "https://files.pythonhosted.org/packages/18/d8/55638d89ffd27799d5cc3d8aa28e12f4ce7a64d67b285114dbedc8ea4136/kiwisolver-1.5.0-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0c50b89ffd3e1a911c69a1dd3de7173c0cd10b130f56222e57898683841e4f96", size = 1278751, upload-time = "2026-03-09T13:13:54.673Z" }, + { url = "https://files.pythonhosted.org/packages/b8/97/b4c8d0d18421ecceba20ad8701358453b88e32414e6f6950b5a4bad54e65/kiwisolver-1.5.0-cp313-cp313-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4db576bb8c3ef9365f8b40fe0f671644de6736ae2c27a2c62d7d8a1b4329f099", size = 1296793, upload-time = "2026-03-09T13:13:56.287Z" }, + { url = "https://files.pythonhosted.org/packages/c4/10/f862f94b6389d8957448ec9df59450b81bec4abb318805375c401a1e6892/kiwisolver-1.5.0-cp313-cp313-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0b85aad90cea8ac6797a53b5d5f2e967334fa4d1149f031c4537569972596cb8", size = 1346041, upload-time = "2026-03-09T13:13:58.269Z" }, + { url = "https://files.pythonhosted.org/packages/a3/6a/f1650af35821eaf09de398ec0bc2aefc8f211f0cda50204c9f1673741ba9/kiwisolver-1.5.0-cp313-cp313-manylinux_2_39_riscv64.whl", hash = "sha256:d36ca54cb4c6c4686f7cbb7b817f66f5911c12ddb519450bbe86707155028f87", size = 987292, upload-time = "2026-03-09T13:13:59.871Z" }, + { url = "https://files.pythonhosted.org/packages/de/19/d7fb82984b9238115fe629c915007be608ebd23dc8629703d917dbfaffd4/kiwisolver-1.5.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:38f4a703656f493b0ad185211ccfca7f0386120f022066b018eb5296d8613e23", size = 2227865, upload-time = "2026-03-09T13:14:01.401Z" }, + { url = "https://files.pythonhosted.org/packages/7f/b9/46b7f386589fd222dac9e9de9c956ce5bcefe2ee73b4e79891381dda8654/kiwisolver-1.5.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:3ac2360e93cb41be81121755c6462cff3beaa9967188c866e5fce5cf13170859", size = 2324369, upload-time = "2026-03-09T13:14:02.972Z" }, + { url = "https://files.pythonhosted.org/packages/92/8b/95e237cf3d9c642960153c769ddcbe278f182c8affb20cecc1cc983e7cc5/kiwisolver-1.5.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:c95cab08d1965db3d84a121f1c7ce7479bdd4072c9b3dafd8fecce48a2e6b902", size = 1977989, upload-time = "2026-03-09T13:14:04.503Z" }, + { url = "https://files.pythonhosted.org/packages/1b/95/980c9df53501892784997820136c01f62bc1865e31b82b9560f980c0e649/kiwisolver-1.5.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:fc20894c3d21194d8041a28b65622d5b86db786da6e3cfe73f0c762951a61167", size = 2491645, upload-time = "2026-03-09T13:14:06.106Z" }, + { url = "https://files.pythonhosted.org/packages/cb/32/900647fd0840abebe1561792c6b31e6a7c0e278fc3973d30572a965ca14c/kiwisolver-1.5.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7a32f72973f0f950c1920475d5c5ea3d971b81b6f0ec53b8d0a956cc965f22e0", size = 2295237, upload-time = "2026-03-09T13:14:08.891Z" }, + { url = "https://files.pythonhosted.org/packages/be/8a/be60e3bbcf513cc5a50f4a3e88e1dcecebb79c1ad607a7222877becaa101/kiwisolver-1.5.0-cp313-cp313-win_amd64.whl", hash = "sha256:0bf3acf1419fa93064a4c2189ac0b58e3be7872bf6ee6177b0d4c63dc4cea276", size = 73573, upload-time = "2026-03-09T13:14:12.327Z" }, + { url = "https://files.pythonhosted.org/packages/4d/d2/64be2e429eb4fca7f7e1c52a91b12663aeaf25de3895e5cca0f47ef2a8d0/kiwisolver-1.5.0-cp313-cp313-win_arm64.whl", hash = "sha256:fa8eb9ecdb7efb0b226acec134e0d709e87a909fa4971a54c0c4f6e88635484c", size = 64998, upload-time = "2026-03-09T13:14:13.469Z" }, + { url = "https://files.pythonhosted.org/packages/b0/69/ce68dd0c85755ae2de490bf015b62f2cea5f6b14ff00a463f9d0774449ff/kiwisolver-1.5.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:db485b3847d182b908b483b2ed133c66d88d49cacf98fd278fadafe11b4478d1", size = 125700, upload-time = "2026-03-09T13:14:14.636Z" }, + { url = "https://files.pythonhosted.org/packages/74/aa/937aac021cf9d4349990d47eb319309a51355ed1dbdc9c077cdc9224cb11/kiwisolver-1.5.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:be12f931839a3bdfe28b584db0e640a65a8bcbc24560ae3fdb025a449b3d754e", size = 67537, upload-time = "2026-03-09T13:14:15.808Z" }, + { url = "https://files.pythonhosted.org/packages/ee/20/3a87fbece2c40ad0f6f0aefa93542559159c5f99831d596050e8afae7a9f/kiwisolver-1.5.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:16b85d37c2cbb3253226d26e64663f755d88a03439a9c47df6246b35defbdfb7", size = 65514, upload-time = "2026-03-09T13:14:18.035Z" }, + { url = "https://files.pythonhosted.org/packages/f0/7f/f943879cda9007c45e1f7dba216d705c3a18d6b35830e488b6c6a4e7cdf0/kiwisolver-1.5.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4432b835675f0ea7414aab3d37d119f7226d24869b7a829caeab49ebda407b0c", size = 1584848, upload-time = "2026-03-09T13:14:19.745Z" }, + { url = "https://files.pythonhosted.org/packages/37/f8/4d4f85cc1870c127c88d950913370dd76138482161cd07eabbc450deff01/kiwisolver-1.5.0-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1b0feb50971481a2cc44d94e88bdb02cdd497618252ae226b8eb1201b957e368", size = 1391542, upload-time = "2026-03-09T13:14:21.54Z" }, + { url = "https://files.pythonhosted.org/packages/04/0b/65dd2916c84d252b244bd405303220f729e7c17c9d7d33dca6feeff9ffc4/kiwisolver-1.5.0-cp313-cp313t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:56fa888f10d0f367155e76ce849fa1166fc9730d13bd2d65a2aa13b6f5424489", size = 1404447, upload-time = "2026-03-09T13:14:23.205Z" }, + { url = "https://files.pythonhosted.org/packages/39/5c/2606a373247babce9b1d056c03a04b65f3cf5290a8eac5d7bdead0a17e21/kiwisolver-1.5.0-cp313-cp313t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:940dda65d5e764406b9fb92761cbf462e4e63f712ab60ed98f70552e496f3bf1", size = 1455918, upload-time = "2026-03-09T13:14:24.74Z" }, + { url = "https://files.pythonhosted.org/packages/d5/d1/c6078b5756670658e9192a2ef11e939c92918833d2745f85cd14a6004bdf/kiwisolver-1.5.0-cp313-cp313t-manylinux_2_39_riscv64.whl", hash = "sha256:89fc958c702ee9a745e4700378f5d23fddbc46ff89e8fdbf5395c24d5c1452a3", size = 1072856, upload-time = "2026-03-09T13:14:26.597Z" }, + { url = "https://files.pythonhosted.org/packages/cb/c8/7def6ddf16eb2b3741d8b172bdaa9af882b03c78e9b0772975408801fa63/kiwisolver-1.5.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9027d773c4ff81487181a925945743413f6069634d0b122d0b37684ccf4f1e18", size = 2333580, upload-time = "2026-03-09T13:14:28.237Z" }, + { url = "https://files.pythonhosted.org/packages/9e/87/2ac1fce0eb1e616fcd3c35caa23e665e9b1948bb984f4764790924594128/kiwisolver-1.5.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:5b233ea3e165e43e35dba1d2b8ecc21cf070b45b65ae17dd2747d2713d942021", size = 2423018, upload-time = "2026-03-09T13:14:30.018Z" }, + { url = "https://files.pythonhosted.org/packages/67/13/c6700ccc6cc218716bfcda4935e4b2997039869b4ad8a94f364c5a3b8e63/kiwisolver-1.5.0-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:ce9bf03dad3b46408c08649c6fbd6ca28a9fce0eb32fdfffa6775a13103b5310", size = 2062804, upload-time = "2026-03-09T13:14:32.888Z" }, + { url = "https://files.pythonhosted.org/packages/1b/bd/877056304626943ff0f1f44c08f584300c199b887cb3176cd7e34f1515f1/kiwisolver-1.5.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:fc4d3f1fb9ca0ae9f97b095963bc6326f1dbfd3779d6679a1e016b9baaa153d3", size = 2597482, upload-time = "2026-03-09T13:14:34.971Z" }, + { url = "https://files.pythonhosted.org/packages/75/19/c60626c47bf0f8ac5dcf72c6c98e266d714f2fbbfd50cf6dab5ede3aaa50/kiwisolver-1.5.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f443b4825c50a51ee68585522ab4a1d1257fac65896f282b4c6763337ac9f5d2", size = 2394328, upload-time = "2026-03-09T13:14:36.816Z" }, + { url = "https://files.pythonhosted.org/packages/47/84/6a6d5e5bb8273756c27b7d810d47f7ef2f1f9b9fd23c9ee9a3f8c75c9cef/kiwisolver-1.5.0-cp313-cp313t-win_arm64.whl", hash = "sha256:893ff3a711d1b515ba9da14ee090519bad4610ed1962fbe298a434e8c5f8db53", size = 68410, upload-time = "2026-03-09T13:14:38.695Z" }, + { url = "https://files.pythonhosted.org/packages/e4/d7/060f45052f2a01ad5762c8fdecd6d7a752b43400dc29ff75cd47225a40fd/kiwisolver-1.5.0-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:8df31fe574b8b3993cc61764f40941111b25c2d9fea13d3ce24a49907cd2d615", size = 123231, upload-time = "2026-03-09T13:14:41.323Z" }, + { url = "https://files.pythonhosted.org/packages/c2/a7/78da680eadd06ff35edef6ef68a1ad273bad3e2a0936c9a885103230aece/kiwisolver-1.5.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:1d49a49ac4cbfb7c1375301cd1ec90169dfeae55ff84710d782260ce77a75a02", size = 66489, upload-time = "2026-03-09T13:14:42.534Z" }, + { url = "https://files.pythonhosted.org/packages/49/b2/97980f3ad4fae37dd7fe31626e2bf75fbf8bdf5d303950ec1fab39a12da8/kiwisolver-1.5.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:0cbe94b69b819209a62cb27bdfa5dc2a8977d8de2f89dfd97ba4f53ed3af754e", size = 64063, upload-time = "2026-03-09T13:14:44.759Z" }, + { url = "https://files.pythonhosted.org/packages/e7/f9/b06c934a6aa8bc91f566bd2a214fd04c30506c2d9e2b6b171953216a65b6/kiwisolver-1.5.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:80aa065ffd378ff784822a6d7c3212f2d5f5e9c3589614b5c228b311fd3063ac", size = 1475913, upload-time = "2026-03-09T13:14:46.247Z" }, + { url = "https://files.pythonhosted.org/packages/6b/f0/f768ae564a710135630672981231320bc403cf9152b5596ec5289de0f106/kiwisolver-1.5.0-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4e7f886f47ab881692f278ae901039a234e4025a68e6dfab514263a0b1c4ae05", size = 1282782, upload-time = "2026-03-09T13:14:48.458Z" }, + { url = "https://files.pythonhosted.org/packages/e2/9f/1de7aad00697325f05238a5f2eafbd487fb637cc27a558b5367a5f37fb7f/kiwisolver-1.5.0-cp314-cp314-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5060731cc3ed12ca3a8b57acd4aeca5bbc2f49216dd0bec1650a1acd89486bcd", size = 1300815, upload-time = "2026-03-09T13:14:50.721Z" }, + { url = "https://files.pythonhosted.org/packages/5a/c2/297f25141d2e468e0ce7f7a7b92e0cf8918143a0cbd3422c1ad627e85a06/kiwisolver-1.5.0-cp314-cp314-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7a4aa69609f40fce3cbc3f87b2061f042eee32f94b8f11db707b66a26461591a", size = 1347925, upload-time = "2026-03-09T13:14:52.304Z" }, + { url = "https://files.pythonhosted.org/packages/b9/d3/f4c73a02eb41520c47610207b21afa8cdd18fdbf64ffd94674ae21c4812d/kiwisolver-1.5.0-cp314-cp314-manylinux_2_39_riscv64.whl", hash = "sha256:d168fda2dbff7b9b5f38e693182d792a938c31db4dac3a80a4888de603c99554", size = 991322, upload-time = "2026-03-09T13:14:54.637Z" }, + { url = "https://files.pythonhosted.org/packages/7b/46/d3f2efef7732fcda98d22bf4ad5d3d71d545167a852ca710a494f4c15343/kiwisolver-1.5.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:413b820229730d358efd838ecbab79902fe97094565fdc80ddb6b0a18c18a581", size = 2232857, upload-time = "2026-03-09T13:14:56.471Z" }, + { url = "https://files.pythonhosted.org/packages/3f/ec/2d9756bf2b6d26ae4349b8d3662fb3993f16d80c1f971c179ce862b9dbae/kiwisolver-1.5.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:5124d1ea754509b09e53738ec185584cc609aae4a3b510aaf4ed6aa047ef9303", size = 2329376, upload-time = "2026-03-09T13:14:58.072Z" }, + { url = "https://files.pythonhosted.org/packages/8f/9f/876a0a0f2260f1bde92e002b3019a5fabc35e0939c7d945e0fa66185eb20/kiwisolver-1.5.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:e4415a8db000bf49a6dd1c478bf70062eaacff0f462b92b0ba68791a905861f9", size = 1982549, upload-time = "2026-03-09T13:14:59.668Z" }, + { url = "https://files.pythonhosted.org/packages/6c/4f/ba3624dfac23a64d54ac4179832860cb537c1b0af06024936e82ca4154a0/kiwisolver-1.5.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:d618fd27420381a4f6044faa71f46d8bfd911bd077c555f7138ed88729bfbe79", size = 2494680, upload-time = "2026-03-09T13:15:01.364Z" }, + { url = "https://files.pythonhosted.org/packages/39/b7/97716b190ab98911b20d10bf92eca469121ec483b8ce0edd314f51bc85af/kiwisolver-1.5.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5092eb5b1172947f57d6ea7d89b2f29650414e4293c47707eb499ec07a0ac796", size = 2297905, upload-time = "2026-03-09T13:15:03.925Z" }, + { url = "https://files.pythonhosted.org/packages/a3/36/4e551e8aa55c9188bca9abb5096805edbf7431072b76e2298e34fd3a3008/kiwisolver-1.5.0-cp314-cp314-win_amd64.whl", hash = "sha256:d76e2d8c75051d58177e762164d2e9ab92886534e3a12e795f103524f221dd8e", size = 75086, upload-time = "2026-03-09T13:15:07.775Z" }, + { url = "https://files.pythonhosted.org/packages/70/15/9b90f7df0e31a003c71649cf66ef61c3c1b862f48c81007fa2383c8bd8d7/kiwisolver-1.5.0-cp314-cp314-win_arm64.whl", hash = "sha256:fa6248cd194edff41d7ea9425ced8ca3a6f838bfb295f6f1d6e6bb694a8518df", size = 66577, upload-time = "2026-03-09T13:15:09.139Z" }, + { url = "https://files.pythonhosted.org/packages/17/01/7dc8c5443ff42b38e72731643ed7cf1ed9bf01691ae5cdca98501999ed83/kiwisolver-1.5.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:d1ffeb80b5676463d7a7d56acbe8e37a20ce725570e09549fe738e02ca6b7e1e", size = 125794, upload-time = "2026-03-09T13:15:10.525Z" }, + { url = "https://files.pythonhosted.org/packages/46/8a/b4ebe46ebaac6a303417fab10c2e165c557ddaff558f9699d302b256bc53/kiwisolver-1.5.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:bc4d8e252f532ab46a1de9349e2d27b91fce46736a9eedaa37beaca66f574ed4", size = 67646, upload-time = "2026-03-09T13:15:12.016Z" }, + { url = "https://files.pythonhosted.org/packages/60/35/10a844afc5f19d6f567359bf4789e26661755a2f36200d5d1ed8ad0126e5/kiwisolver-1.5.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6783e069732715ad0c3ce96dbf21dbc2235ab0593f2baf6338101f70371f4028", size = 65511, upload-time = "2026-03-09T13:15:13.311Z" }, + { url = "https://files.pythonhosted.org/packages/f8/8a/685b297052dd041dcebce8e8787b58923b6e78acc6115a0dc9189011c44b/kiwisolver-1.5.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:e7c4c09a490dc4d4a7f8cbee56c606a320f9dc28cf92a7157a39d1ce7676a657", size = 1584858, upload-time = "2026-03-09T13:15:15.103Z" }, + { url = "https://files.pythonhosted.org/packages/9e/80/04865e3d4638ac5bddec28908916df4a3075b8c6cc101786a96803188b96/kiwisolver-1.5.0-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2a075bd7bd19c70cf67c8badfa36cf7c5d8de3c9ddb8420c51e10d9c50e94920", size = 1392539, upload-time = "2026-03-09T13:15:16.661Z" }, + { url = "https://files.pythonhosted.org/packages/ba/01/77a19cacc0893fa13fafa46d1bba06fb4dc2360b3292baf4b56d8e067b24/kiwisolver-1.5.0-cp314-cp314t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:bdd3e53429ff02aa319ba59dfe4ceeec345bf46cf180ec2cf6fd5b942e7975e9", size = 1405310, upload-time = "2026-03-09T13:15:18.229Z" }, + { url = "https://files.pythonhosted.org/packages/53/39/bcaf5d0cca50e604cfa9b4e3ae1d64b50ca1ae5b754122396084599ef903/kiwisolver-1.5.0-cp314-cp314t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3cdcb35dc9d807259c981a85531048ede628eabcffb3239adf3d17463518992d", size = 1456244, upload-time = "2026-03-09T13:15:20.444Z" }, + { url = "https://files.pythonhosted.org/packages/d0/7a/72c187abc6975f6978c3e39b7cf67aeb8b3c0a8f9790aa7fd412855e9e1f/kiwisolver-1.5.0-cp314-cp314t-manylinux_2_39_riscv64.whl", hash = "sha256:70d593af6a6ca332d1df73d519fddb5148edb15cd90d5f0155e3746a6d4fcc65", size = 1073154, upload-time = "2026-03-09T13:15:22.039Z" }, + { url = "https://files.pythonhosted.org/packages/c7/ca/cf5b25783ebbd59143b4371ed0c8428a278abe68d6d0104b01865b1bbd0f/kiwisolver-1.5.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:377815a8616074cabbf3f53354e1d040c35815a134e01d7614b7692e4bf8acfa", size = 2334377, upload-time = "2026-03-09T13:15:23.741Z" }, + { url = "https://files.pythonhosted.org/packages/4a/e5/b1f492adc516796e88751282276745340e2a72dcd0d36cf7173e0daf3210/kiwisolver-1.5.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:0255a027391d52944eae1dbb5d4cc5903f57092f3674e8e544cdd2622826b3f0", size = 2425288, upload-time = "2026-03-09T13:15:25.789Z" }, + { url = "https://files.pythonhosted.org/packages/e6/e5/9b21fbe91a61b8f409d74a26498706e97a48008bfcd1864373d32a6ba31c/kiwisolver-1.5.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:012b1eb16e28718fa782b5e61dc6f2da1f0792ca73bd05d54de6cb9561665fc9", size = 2063158, upload-time = "2026-03-09T13:15:27.63Z" }, + { url = "https://files.pythonhosted.org/packages/b1/02/83f47986138310f95ea95531f851b2a62227c11cbc3e690ae1374fe49f0f/kiwisolver-1.5.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:0e3aafb33aed7479377e5e9a82e9d4bf87063741fc99fc7ae48b0f16e32bdd6f", size = 2597260, upload-time = "2026-03-09T13:15:29.421Z" }, + { url = "https://files.pythonhosted.org/packages/07/18/43a5f24608d8c313dd189cf838c8e68d75b115567c6279de7796197cfb6a/kiwisolver-1.5.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:e7a116ae737f0000343218c4edf5bd45893bfeaff0993c0b215d7124c9f77646", size = 2394403, upload-time = "2026-03-09T13:15:31.517Z" }, + { url = "https://files.pythonhosted.org/packages/3b/b5/98222136d839b8afabcaa943b09bd05888c2d36355b7e448550211d1fca4/kiwisolver-1.5.0-cp314-cp314t-win_amd64.whl", hash = "sha256:1dd9b0b119a350976a6d781e7278ec7aca0b201e1a9e2d23d9804afecb6ca681", size = 79687, upload-time = "2026-03-09T13:15:33.204Z" }, + { url = "https://files.pythonhosted.org/packages/99/a2/ca7dc962848040befed12732dff6acae7fb3c4f6fc4272b3f6c9a30b8713/kiwisolver-1.5.0-cp314-cp314t-win_arm64.whl", hash = "sha256:58f812017cd2985c21fbffb4864d59174d4903dd66fa23815e74bbc7a0e2dd57", size = 70032, upload-time = "2026-03-09T13:15:34.411Z" }, +] + +[[package]] +name = "lark" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/da/34/28fff3ab31ccff1fd4f6c7c7b0ceb2b6968d8ea4950663eadcb5720591a0/lark-1.3.1.tar.gz", hash = "sha256:b426a7a6d6d53189d318f2b6236ab5d6429eaf09259f1ca33eb716eed10d2905", size = 382732, upload-time = "2025-10-27T18:25:56.653Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/82/3d/14ce75ef66813643812f3093ab17e46d3a206942ce7376d31ec2d36229e7/lark-1.3.1-py3-none-any.whl", hash = "sha256:c629b661023a014c37da873b4ff58a817398d12635d3bbb2c5a03be7fe5d1e12", size = 113151, upload-time = "2025-10-27T18:25:54.882Z" }, +] + +[[package]] +name = "markdown-it-py" +version = "4.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mdurl" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5b/f5/4ec618ed16cc4f8fb3b701563655a69816155e79e24a17b651541804721d/markdown_it_py-4.0.0.tar.gz", hash = "sha256:cb0a2b4aa34f932c007117b194e945bd74e0ec24133ceb5bac59009cda1cb9f3", size = 73070, upload-time = "2025-08-11T12:57:52.854Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl", hash = "sha256:87327c59b172c5011896038353a81343b6754500a08cd7a4973bb48c6d578147", size = 87321, upload-time = "2025-08-11T12:57:51.923Z" }, +] + +[[package]] +name = "markupsafe" +version = "3.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7e/99/7690b6d4034fffd95959cbe0c02de8deb3098cc577c67bb6a24fe5d7caa7/markupsafe-3.0.3.tar.gz", hash = "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698", size = 80313, upload-time = "2025-09-27T18:37:40.426Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/38/2f/907b9c7bbba283e68f20259574b13d005c121a0fa4c175f9bed27c4597ff/markupsafe-3.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e1cf1972137e83c5d4c136c43ced9ac51d0e124706ee1c8aa8532c1287fa8795", size = 11622, upload-time = "2025-09-27T18:36:41.777Z" }, + { url = "https://files.pythonhosted.org/packages/9c/d9/5f7756922cdd676869eca1c4e3c0cd0df60ed30199ffd775e319089cb3ed/markupsafe-3.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219", size = 12029, upload-time = "2025-09-27T18:36:43.257Z" }, + { url = "https://files.pythonhosted.org/packages/00/07/575a68c754943058c78f30db02ee03a64b3c638586fba6a6dd56830b30a3/markupsafe-3.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6", size = 24374, upload-time = "2025-09-27T18:36:44.508Z" }, + { url = "https://files.pythonhosted.org/packages/a9/21/9b05698b46f218fc0e118e1f8168395c65c8a2c750ae2bab54fc4bd4e0e8/markupsafe-3.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676", size = 22980, upload-time = "2025-09-27T18:36:45.385Z" }, + { url = "https://files.pythonhosted.org/packages/7f/71/544260864f893f18b6827315b988c146b559391e6e7e8f7252839b1b846a/markupsafe-3.0.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:509fa21c6deb7a7a273d629cf5ec029bc209d1a51178615ddf718f5918992ab9", size = 21990, upload-time = "2025-09-27T18:36:46.916Z" }, + { url = "https://files.pythonhosted.org/packages/c2/28/b50fc2f74d1ad761af2f5dcce7492648b983d00a65b8c0e0cb457c82ebbe/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4afe79fb3de0b7097d81da19090f4df4f8d3a2b3adaa8764138aac2e44f3af1", size = 23784, upload-time = "2025-09-27T18:36:47.884Z" }, + { url = "https://files.pythonhosted.org/packages/ed/76/104b2aa106a208da8b17a2fb72e033a5a9d7073c68f7e508b94916ed47a9/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:795e7751525cae078558e679d646ae45574b47ed6e7771863fcc079a6171a0fc", size = 21588, upload-time = "2025-09-27T18:36:48.82Z" }, + { url = "https://files.pythonhosted.org/packages/b5/99/16a5eb2d140087ebd97180d95249b00a03aa87e29cc224056274f2e45fd6/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8485f406a96febb5140bfeca44a73e3ce5116b2501ac54fe953e488fb1d03b12", size = 23041, upload-time = "2025-09-27T18:36:49.797Z" }, + { url = "https://files.pythonhosted.org/packages/19/bc/e7140ed90c5d61d77cea142eed9f9c303f4c4806f60a1044c13e3f1471d0/markupsafe-3.0.3-cp313-cp313-win32.whl", hash = "sha256:bdd37121970bfd8be76c5fb069c7751683bdf373db1ed6c010162b2a130248ed", size = 14543, upload-time = "2025-09-27T18:36:51.584Z" }, + { url = "https://files.pythonhosted.org/packages/05/73/c4abe620b841b6b791f2edc248f556900667a5a1cf023a6646967ae98335/markupsafe-3.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5", size = 15113, upload-time = "2025-09-27T18:36:52.537Z" }, + { url = "https://files.pythonhosted.org/packages/f0/3a/fa34a0f7cfef23cf9500d68cb7c32dd64ffd58a12b09225fb03dd37d5b80/markupsafe-3.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:7e68f88e5b8799aa49c85cd116c932a1ac15caaa3f5db09087854d218359e485", size = 13911, upload-time = "2025-09-27T18:36:53.513Z" }, + { url = "https://files.pythonhosted.org/packages/e4/d7/e05cd7efe43a88a17a37b3ae96e79a19e846f3f456fe79c57ca61356ef01/markupsafe-3.0.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:218551f6df4868a8d527e3062d0fb968682fe92054e89978594c28e642c43a73", size = 11658, upload-time = "2025-09-27T18:36:54.819Z" }, + { url = "https://files.pythonhosted.org/packages/99/9e/e412117548182ce2148bdeacdda3bb494260c0b0184360fe0d56389b523b/markupsafe-3.0.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3524b778fe5cfb3452a09d31e7b5adefeea8c5be1d43c4f810ba09f2ceb29d37", size = 12066, upload-time = "2025-09-27T18:36:55.714Z" }, + { url = "https://files.pythonhosted.org/packages/bc/e6/fa0ffcda717ef64a5108eaa7b4f5ed28d56122c9a6d70ab8b72f9f715c80/markupsafe-3.0.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4e885a3d1efa2eadc93c894a21770e4bc67899e3543680313b09f139e149ab19", size = 25639, upload-time = "2025-09-27T18:36:56.908Z" }, + { url = "https://files.pythonhosted.org/packages/96/ec/2102e881fe9d25fc16cb4b25d5f5cde50970967ffa5dddafdb771237062d/markupsafe-3.0.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8709b08f4a89aa7586de0aadc8da56180242ee0ada3999749b183aa23df95025", size = 23569, upload-time = "2025-09-27T18:36:57.913Z" }, + { url = "https://files.pythonhosted.org/packages/4b/30/6f2fce1f1f205fc9323255b216ca8a235b15860c34b6798f810f05828e32/markupsafe-3.0.3-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b8512a91625c9b3da6f127803b166b629725e68af71f8184ae7e7d54686a56d6", size = 23284, upload-time = "2025-09-27T18:36:58.833Z" }, + { url = "https://files.pythonhosted.org/packages/58/47/4a0ccea4ab9f5dcb6f79c0236d954acb382202721e704223a8aafa38b5c8/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9b79b7a16f7fedff2495d684f2b59b0457c3b493778c9eed31111be64d58279f", size = 24801, upload-time = "2025-09-27T18:36:59.739Z" }, + { url = "https://files.pythonhosted.org/packages/6a/70/3780e9b72180b6fecb83a4814d84c3bf4b4ae4bf0b19c27196104149734c/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:12c63dfb4a98206f045aa9563db46507995f7ef6d83b2f68eda65c307c6829eb", size = 22769, upload-time = "2025-09-27T18:37:00.719Z" }, + { url = "https://files.pythonhosted.org/packages/98/c5/c03c7f4125180fc215220c035beac6b9cb684bc7a067c84fc69414d315f5/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8f71bc33915be5186016f675cd83a1e08523649b0e33efdb898db577ef5bb009", size = 23642, upload-time = "2025-09-27T18:37:01.673Z" }, + { url = "https://files.pythonhosted.org/packages/80/d6/2d1b89f6ca4bff1036499b1e29a1d02d282259f3681540e16563f27ebc23/markupsafe-3.0.3-cp313-cp313t-win32.whl", hash = "sha256:69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354", size = 14612, upload-time = "2025-09-27T18:37:02.639Z" }, + { url = "https://files.pythonhosted.org/packages/2b/98/e48a4bfba0a0ffcf9925fe2d69240bfaa19c6f7507b8cd09c70684a53c1e/markupsafe-3.0.3-cp313-cp313t-win_amd64.whl", hash = "sha256:1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218", size = 15200, upload-time = "2025-09-27T18:37:03.582Z" }, + { url = "https://files.pythonhosted.org/packages/0e/72/e3cc540f351f316e9ed0f092757459afbc595824ca724cbc5a5d4263713f/markupsafe-3.0.3-cp313-cp313t-win_arm64.whl", hash = "sha256:ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287", size = 13973, upload-time = "2025-09-27T18:37:04.929Z" }, + { url = "https://files.pythonhosted.org/packages/33/8a/8e42d4838cd89b7dde187011e97fe6c3af66d8c044997d2183fbd6d31352/markupsafe-3.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:eaa9599de571d72e2daf60164784109f19978b327a3910d3e9de8c97b5b70cfe", size = 11619, upload-time = "2025-09-27T18:37:06.342Z" }, + { url = "https://files.pythonhosted.org/packages/b5/64/7660f8a4a8e53c924d0fa05dc3a55c9cee10bbd82b11c5afb27d44b096ce/markupsafe-3.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026", size = 12029, upload-time = "2025-09-27T18:37:07.213Z" }, + { url = "https://files.pythonhosted.org/packages/da/ef/e648bfd021127bef5fa12e1720ffed0c6cbb8310c8d9bea7266337ff06de/markupsafe-3.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f34c41761022dd093b4b6896d4810782ffbabe30f2d443ff5f083e0cbbb8c737", size = 24408, upload-time = "2025-09-27T18:37:09.572Z" }, + { url = "https://files.pythonhosted.org/packages/41/3c/a36c2450754618e62008bf7435ccb0f88053e07592e6028a34776213d877/markupsafe-3.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:457a69a9577064c05a97c41f4e65148652db078a3a509039e64d3467b9e7ef97", size = 23005, upload-time = "2025-09-27T18:37:10.58Z" }, + { url = "https://files.pythonhosted.org/packages/bc/20/b7fdf89a8456b099837cd1dc21974632a02a999ec9bf7ca3e490aacd98e7/markupsafe-3.0.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e8afc3f2ccfa24215f8cb28dcf43f0113ac3c37c2f0f0806d8c70e4228c5cf4d", size = 22048, upload-time = "2025-09-27T18:37:11.547Z" }, + { url = "https://files.pythonhosted.org/packages/9a/a7/591f592afdc734f47db08a75793a55d7fbcc6902a723ae4cfbab61010cc5/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ec15a59cf5af7be74194f7ab02d0f59a62bdcf1a537677ce67a2537c9b87fcda", size = 23821, upload-time = "2025-09-27T18:37:12.48Z" }, + { url = "https://files.pythonhosted.org/packages/7d/33/45b24e4f44195b26521bc6f1a82197118f74df348556594bd2262bda1038/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:0eb9ff8191e8498cca014656ae6b8d61f39da5f95b488805da4bb029cccbfbaf", size = 21606, upload-time = "2025-09-27T18:37:13.485Z" }, + { url = "https://files.pythonhosted.org/packages/ff/0e/53dfaca23a69fbfbbf17a4b64072090e70717344c52eaaaa9c5ddff1e5f0/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2713baf880df847f2bece4230d4d094280f4e67b1e813eec43b4c0e144a34ffe", size = 23043, upload-time = "2025-09-27T18:37:14.408Z" }, + { url = "https://files.pythonhosted.org/packages/46/11/f333a06fc16236d5238bfe74daccbca41459dcd8d1fa952e8fbd5dccfb70/markupsafe-3.0.3-cp314-cp314-win32.whl", hash = "sha256:729586769a26dbceff69f7a7dbbf59ab6572b99d94576a5592625d5b411576b9", size = 14747, upload-time = "2025-09-27T18:37:15.36Z" }, + { url = "https://files.pythonhosted.org/packages/28/52/182836104b33b444e400b14f797212f720cbc9ed6ba34c800639d154e821/markupsafe-3.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:bdc919ead48f234740ad807933cdf545180bfbe9342c2bb451556db2ed958581", size = 15341, upload-time = "2025-09-27T18:37:16.496Z" }, + { url = "https://files.pythonhosted.org/packages/6f/18/acf23e91bd94fd7b3031558b1f013adfa21a8e407a3fdb32745538730382/markupsafe-3.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:5a7d5dc5140555cf21a6fefbdbf8723f06fcd2f63ef108f2854de715e4422cb4", size = 14073, upload-time = "2025-09-27T18:37:17.476Z" }, + { url = "https://files.pythonhosted.org/packages/3c/f0/57689aa4076e1b43b15fdfa646b04653969d50cf30c32a102762be2485da/markupsafe-3.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:1353ef0c1b138e1907ae78e2f6c63ff67501122006b0f9abad68fda5f4ffc6ab", size = 11661, upload-time = "2025-09-27T18:37:18.453Z" }, + { url = "https://files.pythonhosted.org/packages/89/c3/2e67a7ca217c6912985ec766c6393b636fb0c2344443ff9d91404dc4c79f/markupsafe-3.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1085e7fbddd3be5f89cc898938f42c0b3c711fdcb37d75221de2666af647c175", size = 12069, upload-time = "2025-09-27T18:37:19.332Z" }, + { url = "https://files.pythonhosted.org/packages/f0/00/be561dce4e6ca66b15276e184ce4b8aec61fe83662cce2f7d72bd3249d28/markupsafe-3.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1b52b4fb9df4eb9ae465f8d0c228a00624de2334f216f178a995ccdcf82c4634", size = 25670, upload-time = "2025-09-27T18:37:20.245Z" }, + { url = "https://files.pythonhosted.org/packages/50/09/c419f6f5a92e5fadde27efd190eca90f05e1261b10dbd8cbcb39cd8ea1dc/markupsafe-3.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50", size = 23598, upload-time = "2025-09-27T18:37:21.177Z" }, + { url = "https://files.pythonhosted.org/packages/22/44/a0681611106e0b2921b3033fc19bc53323e0b50bc70cffdd19f7d679bb66/markupsafe-3.0.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f190daf01f13c72eac4efd5c430a8de82489d9cff23c364c3ea822545032993e", size = 23261, upload-time = "2025-09-27T18:37:22.167Z" }, + { url = "https://files.pythonhosted.org/packages/5f/57/1b0b3f100259dc9fffe780cfb60d4be71375510e435efec3d116b6436d43/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e56b7d45a839a697b5eb268c82a71bd8c7f6c94d6fd50c3d577fa39a9f1409f5", size = 24835, upload-time = "2025-09-27T18:37:23.296Z" }, + { url = "https://files.pythonhosted.org/packages/26/6a/4bf6d0c97c4920f1597cc14dd720705eca0bf7c787aebc6bb4d1bead5388/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:f3e98bb3798ead92273dc0e5fd0f31ade220f59a266ffd8a4f6065e0a3ce0523", size = 22733, upload-time = "2025-09-27T18:37:24.237Z" }, + { url = "https://files.pythonhosted.org/packages/14/c7/ca723101509b518797fedc2fdf79ba57f886b4aca8a7d31857ba3ee8281f/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5678211cb9333a6468fb8d8be0305520aa073f50d17f089b5b4b477ea6e67fdc", size = 23672, upload-time = "2025-09-27T18:37:25.271Z" }, + { url = "https://files.pythonhosted.org/packages/fb/df/5bd7a48c256faecd1d36edc13133e51397e41b73bb77e1a69deab746ebac/markupsafe-3.0.3-cp314-cp314t-win32.whl", hash = "sha256:915c04ba3851909ce68ccc2b8e2cd691618c4dc4c4232fb7982bca3f41fd8c3d", size = 14819, upload-time = "2025-09-27T18:37:26.285Z" }, + { url = "https://files.pythonhosted.org/packages/1a/8a/0402ba61a2f16038b48b39bccca271134be00c5c9f0f623208399333c448/markupsafe-3.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4faffd047e07c38848ce017e8725090413cd80cbc23d86e55c587bf979e579c9", size = 15426, upload-time = "2025-09-27T18:37:27.316Z" }, + { url = "https://files.pythonhosted.org/packages/70/bc/6f1c2f612465f5fa89b95bead1f44dcb607670fd42891d8fdcd5d039f4f4/markupsafe-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa", size = 14146, upload-time = "2025-09-27T18:37:28.327Z" }, +] + +[[package]] +name = "matplotlib" +version = "3.10.8" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "contourpy" }, + { name = "cycler" }, + { name = "fonttools" }, + { name = "kiwisolver" }, + { name = "numpy" }, + { name = "packaging" }, + { name = "pillow" }, + { name = "pyparsing" }, + { name = "python-dateutil" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/8a/76/d3c6e3a13fe484ebe7718d14e269c9569c4eb0020a968a327acb3b9a8fe6/matplotlib-3.10.8.tar.gz", hash = "sha256:2299372c19d56bcd35cf05a2738308758d32b9eaed2371898d8f5bd33f084aa3", size = 34806269, upload-time = "2025-12-10T22:56:51.155Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3d/b9/15fd5541ef4f5b9a17eefd379356cf12175fe577424e7b1d80676516031a/matplotlib-3.10.8-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:3f2e409836d7f5ac2f1c013110a4d50b9f7edc26328c108915f9075d7d7a91b6", size = 8261076, upload-time = "2025-12-10T22:55:44.648Z" }, + { url = "https://files.pythonhosted.org/packages/8d/a0/2ba3473c1b66b9c74dc7107c67e9008cb1782edbe896d4c899d39ae9cf78/matplotlib-3.10.8-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:56271f3dac49a88d7fca5060f004d9d22b865f743a12a23b1e937a0be4818ee1", size = 8148794, upload-time = "2025-12-10T22:55:46.252Z" }, + { url = "https://files.pythonhosted.org/packages/75/97/a471f1c3eb1fd6f6c24a31a5858f443891d5127e63a7788678d14e249aea/matplotlib-3.10.8-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a0a7f52498f72f13d4a25ea70f35f4cb60642b466cbb0a9be951b5bc3f45a486", size = 8718474, upload-time = "2025-12-10T22:55:47.864Z" }, + { url = "https://files.pythonhosted.org/packages/01/be/cd478f4b66f48256f42927d0acbcd63a26a893136456cd079c0cc24fbabf/matplotlib-3.10.8-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:646d95230efb9ca614a7a594d4fcacde0ac61d25e37dd51710b36477594963ce", size = 9549637, upload-time = "2025-12-10T22:55:50.048Z" }, + { url = "https://files.pythonhosted.org/packages/5d/7c/8dc289776eae5109e268c4fb92baf870678dc048a25d4ac903683b86d5bf/matplotlib-3.10.8-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f89c151aab2e2e23cb3fe0acad1e8b82841fd265379c4cecd0f3fcb34c15e0f6", size = 9613678, upload-time = "2025-12-10T22:55:52.21Z" }, + { url = "https://files.pythonhosted.org/packages/64/40/37612487cc8a437d4dd261b32ca21fe2d79510fe74af74e1f42becb1bdb8/matplotlib-3.10.8-cp313-cp313-win_amd64.whl", hash = "sha256:e8ea3e2d4066083e264e75c829078f9e149fa119d27e19acd503de65e0b13149", size = 8142686, upload-time = "2025-12-10T22:55:54.253Z" }, + { url = "https://files.pythonhosted.org/packages/66/52/8d8a8730e968185514680c2a6625943f70269509c3dcfc0dcf7d75928cb8/matplotlib-3.10.8-cp313-cp313-win_arm64.whl", hash = "sha256:c108a1d6fa78a50646029cb6d49808ff0fc1330fda87fa6f6250c6b5369b6645", size = 8012917, upload-time = "2025-12-10T22:55:56.268Z" }, + { url = "https://files.pythonhosted.org/packages/b5/27/51fe26e1062f298af5ef66343d8ef460e090a27fea73036c76c35821df04/matplotlib-3.10.8-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:ad3d9833a64cf48cc4300f2b406c3d0f4f4724a91c0bd5640678a6ba7c102077", size = 8305679, upload-time = "2025-12-10T22:55:57.856Z" }, + { url = "https://files.pythonhosted.org/packages/2c/1e/4de865bc591ac8e3062e835f42dd7fe7a93168d519557837f0e37513f629/matplotlib-3.10.8-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:eb3823f11823deade26ce3b9f40dcb4a213da7a670013929f31d5f5ed1055b22", size = 8198336, upload-time = "2025-12-10T22:55:59.371Z" }, + { url = "https://files.pythonhosted.org/packages/c6/cb/2f7b6e75fb4dce87ef91f60cac4f6e34f4c145ab036a22318ec837971300/matplotlib-3.10.8-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d9050fee89a89ed57b4fb2c1bfac9a3d0c57a0d55aed95949eedbc42070fea39", size = 8731653, upload-time = "2025-12-10T22:56:01.032Z" }, + { url = "https://files.pythonhosted.org/packages/46/b3/bd9c57d6ba670a37ab31fb87ec3e8691b947134b201f881665b28cc039ff/matplotlib-3.10.8-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b44d07310e404ba95f8c25aa5536f154c0a8ec473303535949e52eb71d0a1565", size = 9561356, upload-time = "2025-12-10T22:56:02.95Z" }, + { url = "https://files.pythonhosted.org/packages/c0/3d/8b94a481456dfc9dfe6e39e93b5ab376e50998cddfd23f4ae3b431708f16/matplotlib-3.10.8-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:0a33deb84c15ede243aead39f77e990469fff93ad1521163305095b77b72ce4a", size = 9614000, upload-time = "2025-12-10T22:56:05.411Z" }, + { url = "https://files.pythonhosted.org/packages/bd/cd/bc06149fe5585ba800b189a6a654a75f1f127e8aab02fd2be10df7fa500c/matplotlib-3.10.8-cp313-cp313t-win_amd64.whl", hash = "sha256:3a48a78d2786784cc2413e57397981fb45c79e968d99656706018d6e62e57958", size = 8220043, upload-time = "2025-12-10T22:56:07.551Z" }, + { url = "https://files.pythonhosted.org/packages/e3/de/b22cf255abec916562cc04eef457c13e58a1990048de0c0c3604d082355e/matplotlib-3.10.8-cp313-cp313t-win_arm64.whl", hash = "sha256:15d30132718972c2c074cd14638c7f4592bd98719e2308bccea40e0538bc0cb5", size = 8062075, upload-time = "2025-12-10T22:56:09.178Z" }, + { url = "https://files.pythonhosted.org/packages/3c/43/9c0ff7a2f11615e516c3b058e1e6e8f9614ddeca53faca06da267c48345d/matplotlib-3.10.8-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:b53285e65d4fa4c86399979e956235deb900be5baa7fc1218ea67fbfaeaadd6f", size = 8262481, upload-time = "2025-12-10T22:56:10.885Z" }, + { url = "https://files.pythonhosted.org/packages/6f/ca/e8ae28649fcdf039fda5ef554b40a95f50592a3c47e6f7270c9561c12b07/matplotlib-3.10.8-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:32f8dce744be5569bebe789e46727946041199030db8aeb2954d26013a0eb26b", size = 8151473, upload-time = "2025-12-10T22:56:12.377Z" }, + { url = "https://files.pythonhosted.org/packages/f1/6f/009d129ae70b75e88cbe7e503a12a4c0670e08ed748a902c2568909e9eb5/matplotlib-3.10.8-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4cf267add95b1c88300d96ca837833d4112756045364f5c734a2276038dae27d", size = 9553896, upload-time = "2025-12-10T22:56:14.432Z" }, + { url = "https://files.pythonhosted.org/packages/f5/26/4221a741eb97967bc1fd5e4c52b9aa5a91b2f4ec05b59f6def4d820f9df9/matplotlib-3.10.8-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2cf5bd12cecf46908f286d7838b2abc6c91cda506c0445b8223a7c19a00df008", size = 9824193, upload-time = "2025-12-10T22:56:16.29Z" }, + { url = "https://files.pythonhosted.org/packages/1f/f3/3abf75f38605772cf48a9daf5821cd4f563472f38b4b828c6fba6fa6d06e/matplotlib-3.10.8-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:41703cc95688f2516b480f7f339d8851a6035f18e100ee6a32bc0b8536a12a9c", size = 9615444, upload-time = "2025-12-10T22:56:18.155Z" }, + { url = "https://files.pythonhosted.org/packages/93/a5/de89ac80f10b8dc615807ee1133cd99ac74082581196d4d9590bea10690d/matplotlib-3.10.8-cp314-cp314-win_amd64.whl", hash = "sha256:83d282364ea9f3e52363da262ce32a09dfe241e4080dcedda3c0db059d3c1f11", size = 8272719, upload-time = "2025-12-10T22:56:20.366Z" }, + { url = "https://files.pythonhosted.org/packages/69/ce/b006495c19ccc0a137b48083168a37bd056392dee02f87dba0472f2797fe/matplotlib-3.10.8-cp314-cp314-win_arm64.whl", hash = "sha256:2c1998e92cd5999e295a731bcb2911c75f597d937341f3030cc24ef2733d78a8", size = 8144205, upload-time = "2025-12-10T22:56:22.239Z" }, + { url = "https://files.pythonhosted.org/packages/68/d9/b31116a3a855bd313c6fcdb7226926d59b041f26061c6c5b1be66a08c826/matplotlib-3.10.8-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:b5a2b97dbdc7d4f353ebf343744f1d1f1cca8aa8bfddb4262fcf4306c3761d50", size = 8305785, upload-time = "2025-12-10T22:56:24.218Z" }, + { url = "https://files.pythonhosted.org/packages/1e/90/6effe8103f0272685767ba5f094f453784057072f49b393e3ea178fe70a5/matplotlib-3.10.8-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:3f5c3e4da343bba819f0234186b9004faba952cc420fbc522dc4e103c1985908", size = 8198361, upload-time = "2025-12-10T22:56:26.787Z" }, + { url = "https://files.pythonhosted.org/packages/d7/65/a73188711bea603615fc0baecca1061429ac16940e2385433cc778a9d8e7/matplotlib-3.10.8-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5f62550b9a30afde8c1c3ae450e5eb547d579dd69b25c2fc7a1c67f934c1717a", size = 9561357, upload-time = "2025-12-10T22:56:28.953Z" }, + { url = "https://files.pythonhosted.org/packages/f4/3d/b5c5d5d5be8ce63292567f0e2c43dde9953d3ed86ac2de0a72e93c8f07a1/matplotlib-3.10.8-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:495672de149445ec1b772ff2c9ede9b769e3cb4f0d0aa7fa730d7f59e2d4e1c1", size = 9823610, upload-time = "2025-12-10T22:56:31.455Z" }, + { url = "https://files.pythonhosted.org/packages/4d/4b/e7beb6bbd49f6bae727a12b270a2654d13c397576d25bd6786e47033300f/matplotlib-3.10.8-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:595ba4d8fe983b88f0eec8c26a241e16d6376fe1979086232f481f8f3f67494c", size = 9614011, upload-time = "2025-12-10T22:56:33.85Z" }, + { url = "https://files.pythonhosted.org/packages/7c/e6/76f2813d31f032e65f6f797e3f2f6e4aab95b65015924b1c51370395c28a/matplotlib-3.10.8-cp314-cp314t-win_amd64.whl", hash = "sha256:25d380fe8b1dc32cf8f0b1b448470a77afb195438bafdf1d858bfb876f3edf7b", size = 8362801, upload-time = "2025-12-10T22:56:36.107Z" }, + { url = "https://files.pythonhosted.org/packages/5d/49/d651878698a0b67f23aa28e17f45a6d6dd3d3f933fa29087fa4ce5947b5a/matplotlib-3.10.8-cp314-cp314t-win_arm64.whl", hash = "sha256:113bb52413ea508ce954a02c10ffd0d565f9c3bc7f2eddc27dfe1731e71c7b5f", size = 8192560, upload-time = "2025-12-10T22:56:38.008Z" }, +] + +[[package]] +name = "matplotlib-inline" +version = "0.2.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c7/74/97e72a36efd4ae2bccb3463284300f8953f199b5ffbc04cbbb0ec78f74b1/matplotlib_inline-0.2.1.tar.gz", hash = "sha256:e1ee949c340d771fc39e241ea75683deb94762c8fa5f2927ec57c83c4dffa9fe", size = 8110, upload-time = "2025-10-23T09:00:22.126Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/af/33/ee4519fa02ed11a94aef9559552f3b17bb863f2ecfe1a35dc7f548cde231/matplotlib_inline-0.2.1-py3-none-any.whl", hash = "sha256:d56ce5156ba6085e00a9d54fead6ed29a9c47e215cd1bba2e976ef39f5710a76", size = 9516, upload-time = "2025-10-23T09:00:20.675Z" }, +] + +[[package]] +name = "mcp" +version = "1.27.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "httpx" }, + { name = "httpx-sse" }, + { name = "jsonschema" }, + { name = "pydantic" }, + { name = "pydantic-settings" }, + { name = "pyjwt", extra = ["crypto"] }, + { name = "python-multipart" }, + { name = "pywin32", marker = "sys_platform == 'win32'" }, + { name = "sse-starlette" }, + { name = "starlette" }, + { name = "typing-extensions" }, + { name = "typing-inspection" }, + { name = "uvicorn", marker = "sys_platform != 'emscripten'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/8b/eb/c0cfc62075dc6e1ec1c64d352ae09ac051d9334311ed226f1f425312848a/mcp-1.27.0.tar.gz", hash = "sha256:d3dc35a7eec0d458c1da4976a48f982097ddaab87e278c5511d5a4a56e852b83", size = 607509, upload-time = "2026-04-02T14:48:08.88Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9c/46/f6b4ad632c67ef35209a66127e4bddc95759649dd595f71f13fba11bdf9a/mcp-1.27.0-py3-none-any.whl", hash = "sha256:5ce1fa81614958e267b21fb2aa34e0aea8e2c6ede60d52aba45fd47246b4d741", size = 215967, upload-time = "2026-04-02T14:48:07.24Z" }, +] + +[package.optional-dependencies] +cli = [ + { name = "python-dotenv" }, + { name = "typer" }, +] + +[[package]] +name = "mdurl" +version = "0.1.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" }, +] + +[[package]] +name = "mistune" +version = "3.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/9d/55/d01f0c4b45ade6536c51170b9043db8b2ec6ddf4a35c7ea3f5f559ac935b/mistune-3.2.0.tar.gz", hash = "sha256:708487c8a8cdd99c9d90eb3ed4c3ed961246ff78ac82f03418f5183ab70e398a", size = 95467, upload-time = "2025-12-23T11:36:34.994Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9b/f7/4a5e785ec9fbd65146a27b6b70b6cdc161a66f2024e4b04ac06a67f5578b/mistune-3.2.0-py3-none-any.whl", hash = "sha256:febdc629a3c78616b94393c6580551e0e34cc289987ec6c35ed3f4be42d0eee1", size = 53598, upload-time = "2025-12-23T11:36:33.211Z" }, +] + +[[package]] +name = "nbclient" +version = "0.10.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jupyter-client" }, + { name = "jupyter-core" }, + { name = "nbformat" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/56/91/1c1d5a4b9a9ebba2b4e32b8c852c2975c872aec1fe42ab5e516b2cecd193/nbclient-0.10.4.tar.gz", hash = "sha256:1e54091b16e6da39e297b0ece3e10f6f29f4ac4e8ee515d29f8a7099bd6553c9", size = 62554, upload-time = "2025-12-23T07:45:46.369Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/83/a0/5b0c2f11142ed1dddec842457d3f65eaf71a0080894eb6f018755b319c3a/nbclient-0.10.4-py3-none-any.whl", hash = "sha256:9162df5a7373d70d606527300a95a975a47c137776cd942e52d9c7e29ff83440", size = 25465, upload-time = "2025-12-23T07:45:44.51Z" }, +] + +[[package]] +name = "nbconvert" +version = "7.17.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "beautifulsoup4" }, + { name = "bleach", extra = ["css"] }, + { name = "defusedxml" }, + { name = "jinja2" }, + { name = "jupyter-core" }, + { name = "jupyterlab-pygments" }, + { name = "markupsafe" }, + { name = "mistune" }, + { name = "nbclient" }, + { name = "nbformat" }, + { name = "packaging" }, + { name = "pandocfilters" }, + { name = "pygments" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/38/47/81f886b699450d0569f7bc551df2b1673d18df7ff25cc0c21ca36ed8a5ff/nbconvert-7.17.0.tar.gz", hash = "sha256:1b2696f1b5be12309f6c7d707c24af604b87dfaf6d950794c7b07acab96dda78", size = 862855, upload-time = "2026-01-29T16:37:48.478Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0d/4b/8d5f796a792f8a25f6925a96032f098789f448571eb92011df1ae59e8ea8/nbconvert-7.17.0-py3-none-any.whl", hash = "sha256:4f99a63b337b9a23504347afdab24a11faa7d86b405e5c8f9881cd313336d518", size = 261510, upload-time = "2026-01-29T16:37:46.322Z" }, +] + +[[package]] +name = "nbformat" +version = "5.10.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "fastjsonschema" }, + { name = "jsonschema" }, + { name = "jupyter-core" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/6d/fd/91545e604bc3dad7dca9ed03284086039b294c6b3d75c0d2fa45f9e9caf3/nbformat-5.10.4.tar.gz", hash = "sha256:322168b14f937a5d11362988ecac2a4952d3d8e3a2cbeb2319584631226d5b3a", size = 142749, upload-time = "2024-04-04T11:20:37.371Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a9/82/0340caa499416c78e5d8f5f05947ae4bc3cba53c9f038ab6e9ed964e22f1/nbformat-5.10.4-py3-none-any.whl", hash = "sha256:3b48d6c8fbca4b299bf3982ea7db1af21580e4fec269ad087b9e81588891200b", size = 78454, upload-time = "2024-04-04T11:20:34.895Z" }, +] + +[[package]] +name = "nest-asyncio" +version = "1.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/83/f8/51569ac65d696c8ecbee95938f89d4abf00f47d58d48f6fbabfe8f0baefe/nest_asyncio-1.6.0.tar.gz", hash = "sha256:6f172d5449aca15afd6c646851f4e31e02c598d553a667e38cafa997cfec55fe", size = 7418, upload-time = "2024-01-21T14:25:19.227Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a0/c4/c2971a3ba4c6103a3d10c4b0f24f461ddc027f0f09763220cf35ca1401b3/nest_asyncio-1.6.0-py3-none-any.whl", hash = "sha256:87af6efd6b5e897c81050477ef65c62e2b2f35d51703cae01aff2905b1852e1c", size = 5195, upload-time = "2024-01-21T14:25:17.223Z" }, +] + +[[package]] +name = "notebook" +version = "7.5.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jupyter-server" }, + { name = "jupyterlab" }, + { name = "jupyterlab-server" }, + { name = "notebook-shim" }, + { name = "tornado" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/1f/6d/41052c48d6f6349ca0a7c4d1f6a78464de135e6d18f5829ba2510e62184c/notebook-7.5.5.tar.gz", hash = "sha256:dc0bfab0f2372c8278c457423d3256c34154ac2cc76bf20e9925260c461013c3", size = 14169167, upload-time = "2026-03-11T16:32:51.922Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f8/aa/cbd1deb9f07446241e88f8d5fecccd95b249bca0b4e5482214a4d1714c49/notebook-7.5.5-py3-none-any.whl", hash = "sha256:a7c14dbeefa6592e87f72290ca982e0c10f5bbf3786be2a600fda9da2764a2b8", size = 14578929, upload-time = "2026-03-11T16:32:48.021Z" }, +] + +[[package]] +name = "notebook-shim" +version = "0.2.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jupyter-server" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/54/d2/92fa3243712b9a3e8bafaf60aac366da1cada3639ca767ff4b5b3654ec28/notebook_shim-0.2.4.tar.gz", hash = "sha256:b4b2cfa1b65d98307ca24361f5b30fe785b53c3fd07b7a47e89acb5e6ac638cb", size = 13167, upload-time = "2024-02-14T23:35:18.353Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f9/33/bd5b9137445ea4b680023eb0469b2bb969d61303dedb2aac6560ff3d14a1/notebook_shim-0.2.4-py3-none-any.whl", hash = "sha256:411a5be4e9dc882a074ccbcae671eda64cceb068767e9a3419096986560e1cef", size = 13307, upload-time = "2024-02-14T23:35:16.286Z" }, +] + +[[package]] +name = "numpy" +version = "2.4.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d7/9f/b8cef5bffa569759033adda9481211426f12f53299629b410340795c2514/numpy-2.4.4.tar.gz", hash = "sha256:2d390634c5182175533585cc89f3608a4682ccb173cc9bb940b2881c8d6f8fa0", size = 20731587, upload-time = "2026-03-29T13:22:01.298Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/14/1d/d0a583ce4fefcc3308806a749a536c201ed6b5ad6e1322e227ee4848979d/numpy-2.4.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:08f2e31ed5e6f04b118e49821397f12767934cfdd12a1ce86a058f91e004ee50", size = 16684933, upload-time = "2026-03-29T13:19:22.47Z" }, + { url = "https://files.pythonhosted.org/packages/c1/62/2b7a48fbb745d344742c0277f01286dead15f3f68e4f359fbfcf7b48f70f/numpy-2.4.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e823b8b6edc81e747526f70f71a9c0a07ac4e7ad13020aa736bb7c9d67196115", size = 14694532, upload-time = "2026-03-29T13:19:25.581Z" }, + { url = "https://files.pythonhosted.org/packages/e5/87/499737bfba066b4a3bebff24a8f1c5b2dee410b209bc6668c9be692580f0/numpy-2.4.4-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:4a19d9dba1a76618dd86b164d608566f393f8ec6ac7c44f0cc879011c45e65af", size = 5199661, upload-time = "2026-03-29T13:19:28.31Z" }, + { url = "https://files.pythonhosted.org/packages/cd/da/464d551604320d1491bc345efed99b4b7034143a85787aab78d5691d5a0e/numpy-2.4.4-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:d2a8490669bfe99a233298348acc2d824d496dee0e66e31b66a6022c2ad74a5c", size = 6547539, upload-time = "2026-03-29T13:19:30.97Z" }, + { url = "https://files.pythonhosted.org/packages/7d/90/8d23e3b0dafd024bf31bdec225b3bb5c2dbfa6912f8a53b8659f21216cbf/numpy-2.4.4-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:45dbed2ab436a9e826e302fcdcbe9133f9b0006e5af7168afb8963a6520da103", size = 15668806, upload-time = "2026-03-29T13:19:33.887Z" }, + { url = "https://files.pythonhosted.org/packages/d1/73/a9d864e42a01896bb5974475438f16086be9ba1f0d19d0bb7a07427c4a8b/numpy-2.4.4-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c901b15172510173f5cb310eae652908340f8dede90fff9e3bf6c0d8dfd92f83", size = 16632682, upload-time = "2026-03-29T13:19:37.336Z" }, + { url = "https://files.pythonhosted.org/packages/34/fb/14570d65c3bde4e202a031210475ae9cde9b7686a2e7dc97ee67d2833b35/numpy-2.4.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:99d838547ace2c4aace6c4f76e879ddfe02bb58a80c1549928477862b7a6d6ed", size = 17019810, upload-time = "2026-03-29T13:19:40.963Z" }, + { url = "https://files.pythonhosted.org/packages/8a/77/2ba9d87081fd41f6d640c83f26fb7351e536b7ce6dd9061b6af5904e8e46/numpy-2.4.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0aec54fd785890ecca25a6003fd9a5aed47ad607bbac5cd64f836ad8666f4959", size = 18357394, upload-time = "2026-03-29T13:19:44.859Z" }, + { url = "https://files.pythonhosted.org/packages/a2/23/52666c9a41708b0853fa3b1a12c90da38c507a3074883823126d4e9d5b30/numpy-2.4.4-cp313-cp313-win32.whl", hash = "sha256:07077278157d02f65c43b1b26a3886bce886f95d20aabd11f87932750dfb14ed", size = 5959556, upload-time = "2026-03-29T13:19:47.661Z" }, + { url = "https://files.pythonhosted.org/packages/57/fb/48649b4971cde70d817cf97a2a2fdc0b4d8308569f1dd2f2611959d2e0cf/numpy-2.4.4-cp313-cp313-win_amd64.whl", hash = "sha256:5c70f1cc1c4efbe316a572e2d8b9b9cc44e89b95f79ca3331553fbb63716e2bf", size = 12317311, upload-time = "2026-03-29T13:19:50.67Z" }, + { url = "https://files.pythonhosted.org/packages/ba/d8/11490cddd564eb4de97b4579ef6bfe6a736cc07e94c1598590ae25415e01/numpy-2.4.4-cp313-cp313-win_arm64.whl", hash = "sha256:ef4059d6e5152fa1a39f888e344c73fdc926e1b2dd58c771d67b0acfbf2aa67d", size = 10222060, upload-time = "2026-03-29T13:19:54.229Z" }, + { url = "https://files.pythonhosted.org/packages/99/5d/dab4339177a905aad3e2221c915b35202f1ec30d750dd2e5e9d9a72b804b/numpy-2.4.4-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:4bbc7f303d125971f60ec0aaad5e12c62d0d2c925f0ab1273debd0e4ba37aba5", size = 14822302, upload-time = "2026-03-29T13:19:57.585Z" }, + { url = "https://files.pythonhosted.org/packages/eb/e4/0564a65e7d3d97562ed6f9b0fd0fb0a6f559ee444092f105938b50043876/numpy-2.4.4-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:4d6d57903571f86180eb98f8f0c839fa9ebbfb031356d87f1361be91e433f5b7", size = 5327407, upload-time = "2026-03-29T13:20:00.601Z" }, + { url = "https://files.pythonhosted.org/packages/29/8d/35a3a6ce5ad371afa58b4700f1c820f8f279948cca32524e0a695b0ded83/numpy-2.4.4-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:4636de7fd195197b7535f231b5de9e4b36d2c440b6e566d2e4e4746e6af0ca93", size = 6647631, upload-time = "2026-03-29T13:20:02.855Z" }, + { url = "https://files.pythonhosted.org/packages/f4/da/477731acbd5a58a946c736edfdabb2ac5b34c3d08d1ba1a7b437fa0884df/numpy-2.4.4-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ad2e2ef14e0b04e544ea2fa0a36463f847f113d314aa02e5b402fdf910ef309e", size = 15727691, upload-time = "2026-03-29T13:20:06.004Z" }, + { url = "https://files.pythonhosted.org/packages/e6/db/338535d9b152beabeb511579598418ba0212ce77cf9718edd70262cc4370/numpy-2.4.4-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a285b3b96f951841799528cd1f4f01cd70e7e0204b4abebac9463eecfcf2a40", size = 16681241, upload-time = "2026-03-29T13:20:09.417Z" }, + { url = "https://files.pythonhosted.org/packages/e2/a9/ad248e8f58beb7a0219b413c9c7d8151c5d285f7f946c3e26695bdbbe2df/numpy-2.4.4-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:f8474c4241bc18b750be2abea9d7a9ec84f46ef861dbacf86a4f6e043401f79e", size = 17085767, upload-time = "2026-03-29T13:20:13.126Z" }, + { url = "https://files.pythonhosted.org/packages/b5/1a/3b88ccd3694681356f70da841630e4725a7264d6a885c8d442a697e1146b/numpy-2.4.4-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4e874c976154687c1f71715b034739b45c7711bec81db01914770373d125e392", size = 18403169, upload-time = "2026-03-29T13:20:17.096Z" }, + { url = "https://files.pythonhosted.org/packages/c2/c9/fcfd5d0639222c6eac7f304829b04892ef51c96a75d479214d77e3ce6e33/numpy-2.4.4-cp313-cp313t-win32.whl", hash = "sha256:9c585a1790d5436a5374bac930dad6ed244c046ed91b2b2a3634eb2971d21008", size = 6083477, upload-time = "2026-03-29T13:20:20.195Z" }, + { url = "https://files.pythonhosted.org/packages/d5/e3/3938a61d1c538aaec8ed6fd6323f57b0c2d2d2219512434c5c878db76553/numpy-2.4.4-cp313-cp313t-win_amd64.whl", hash = "sha256:93e15038125dc1e5345d9b5b68aa7f996ec33b98118d18c6ca0d0b7d6198b7e8", size = 12457487, upload-time = "2026-03-29T13:20:22.946Z" }, + { url = "https://files.pythonhosted.org/packages/97/6a/7e345032cc60501721ef94e0e30b60f6b0bd601f9174ebd36389a2b86d40/numpy-2.4.4-cp313-cp313t-win_arm64.whl", hash = "sha256:0dfd3f9d3adbe2920b68b5cd3d51444e13a10792ec7154cd0a2f6e74d4ab3233", size = 10292002, upload-time = "2026-03-29T13:20:25.909Z" }, + { url = "https://files.pythonhosted.org/packages/6e/06/c54062f85f673dd5c04cbe2f14c3acb8c8b95e3384869bb8cc9bff8cb9df/numpy-2.4.4-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:f169b9a863d34f5d11b8698ead99febeaa17a13ca044961aa8e2662a6c7766a0", size = 16684353, upload-time = "2026-03-29T13:20:29.504Z" }, + { url = "https://files.pythonhosted.org/packages/4c/39/8a320264a84404c74cc7e79715de85d6130fa07a0898f67fb5cd5bd79908/numpy-2.4.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:2483e4584a1cb3092da4470b38866634bafb223cbcd551ee047633fd2584599a", size = 14704914, upload-time = "2026-03-29T13:20:33.547Z" }, + { url = "https://files.pythonhosted.org/packages/91/fb/287076b2614e1d1044235f50f03748f31fa287e3dbe6abeb35cdfa351eca/numpy-2.4.4-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:2d19e6e2095506d1736b7d80595e0f252d76b89f5e715c35e06e937679ea7d7a", size = 5210005, upload-time = "2026-03-29T13:20:36.45Z" }, + { url = "https://files.pythonhosted.org/packages/63/eb/fcc338595309910de6ecabfcef2419a9ce24399680bfb149421fa2df1280/numpy-2.4.4-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:6a246d5914aa1c820c9443ddcee9c02bec3e203b0c080349533fae17727dfd1b", size = 6544974, upload-time = "2026-03-29T13:20:39.014Z" }, + { url = "https://files.pythonhosted.org/packages/44/5d/e7e9044032a716cdfaa3fba27a8e874bf1c5f1912a1ddd4ed071bf8a14a6/numpy-2.4.4-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:989824e9faf85f96ec9c7761cd8d29c531ad857bfa1daa930cba85baaecf1a9a", size = 15684591, upload-time = "2026-03-29T13:20:42.146Z" }, + { url = "https://files.pythonhosted.org/packages/98/7c/21252050676612625449b4807d6b695b9ce8a7c9e1c197ee6216c8a65c7c/numpy-2.4.4-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:27a8d92cd10f1382a67d7cf4db7ce18341b66438bdd9f691d7b0e48d104c2a9d", size = 16637700, upload-time = "2026-03-29T13:20:46.204Z" }, + { url = "https://files.pythonhosted.org/packages/b1/29/56d2bbef9465db24ef25393383d761a1af4f446a1df9b8cded4fe3a5a5d7/numpy-2.4.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:e44319a2953c738205bf3354537979eaa3998ed673395b964c1176083dd46252", size = 17035781, upload-time = "2026-03-29T13:20:50.242Z" }, + { url = "https://files.pythonhosted.org/packages/e3/2b/a35a6d7589d21f44cea7d0a98de5ddcbb3d421b2622a5c96b1edf18707c3/numpy-2.4.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:e892aff75639bbef0d2a2cfd55535510df26ff92f63c92cd84ef8d4ba5a5557f", size = 18362959, upload-time = "2026-03-29T13:20:54.019Z" }, + { url = "https://files.pythonhosted.org/packages/64/c9/d52ec581f2390e0f5f85cbfd80fb83d965fc15e9f0e1aec2195faa142cde/numpy-2.4.4-cp314-cp314-win32.whl", hash = "sha256:1378871da56ca8943c2ba674530924bb8ca40cd228358a3b5f302ad60cf875fc", size = 6008768, upload-time = "2026-03-29T13:20:56.912Z" }, + { url = "https://files.pythonhosted.org/packages/fa/22/4cc31a62a6c7b74a8730e31a4274c5dc80e005751e277a2ce38e675e4923/numpy-2.4.4-cp314-cp314-win_amd64.whl", hash = "sha256:715d1c092715954784bc79e1174fc2a90093dc4dc84ea15eb14dad8abdcdeb74", size = 12449181, upload-time = "2026-03-29T13:20:59.548Z" }, + { url = "https://files.pythonhosted.org/packages/70/2e/14cda6f4d8e396c612d1bf97f22958e92148801d7e4f110cabebdc0eef4b/numpy-2.4.4-cp314-cp314-win_arm64.whl", hash = "sha256:2c194dd721e54ecad9ad387c1d35e63dce5c4450c6dc7dd5611283dda239aabb", size = 10496035, upload-time = "2026-03-29T13:21:02.524Z" }, + { url = "https://files.pythonhosted.org/packages/b1/e8/8fed8c8d848d7ecea092dc3469643f9d10bc3a134a815a3b033da1d2039b/numpy-2.4.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:2aa0613a5177c264ff5921051a5719d20095ea586ca88cc802c5c218d1c67d3e", size = 14824958, upload-time = "2026-03-29T13:21:05.671Z" }, + { url = "https://files.pythonhosted.org/packages/05/1a/d8007a5138c179c2bf33ef44503e83d70434d2642877ee8fbb230e7c0548/numpy-2.4.4-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:42c16925aa5a02362f986765f9ebabf20de75cdefdca827d14315c568dcab113", size = 5330020, upload-time = "2026-03-29T13:21:08.635Z" }, + { url = "https://files.pythonhosted.org/packages/99/64/ffb99ac6ae93faf117bcbd5c7ba48a7f45364a33e8e458545d3633615dda/numpy-2.4.4-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:874f200b2a981c647340f841730fc3a2b54c9d940566a3c4149099591e2c4c3d", size = 6650758, upload-time = "2026-03-29T13:21:10.949Z" }, + { url = "https://files.pythonhosted.org/packages/6e/6e/795cc078b78a384052e73b2f6281ff7a700e9bf53bcce2ee579d4f6dd879/numpy-2.4.4-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c9b39d38a9bd2ae1becd7eac1303d031c5c110ad31f2b319c6e7d98b135c934d", size = 15729948, upload-time = "2026-03-29T13:21:14.047Z" }, + { url = "https://files.pythonhosted.org/packages/5f/86/2acbda8cc2af5f3d7bfc791192863b9e3e19674da7b5e533fded124d1299/numpy-2.4.4-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b268594bccac7d7cf5844c7732e3f20c50921d94e36d7ec9b79e9857694b1b2f", size = 16679325, upload-time = "2026-03-29T13:21:17.561Z" }, + { url = "https://files.pythonhosted.org/packages/bc/59/cafd83018f4aa55e0ac6fa92aa066c0a1877b77a615ceff1711c260ffae8/numpy-2.4.4-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:ac6b31e35612a26483e20750126d30d0941f949426974cace8e6b5c58a3657b0", size = 17084883, upload-time = "2026-03-29T13:21:21.106Z" }, + { url = "https://files.pythonhosted.org/packages/f0/85/a42548db84e65ece46ab2caea3d3f78b416a47af387fcbb47ec28e660dc2/numpy-2.4.4-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:8e3ed142f2728df44263aaf5fb1f5b0b99f4070c553a0d7f033be65338329150", size = 18403474, upload-time = "2026-03-29T13:21:24.828Z" }, + { url = "https://files.pythonhosted.org/packages/ed/ad/483d9e262f4b831000062e5d8a45e342166ec8aaa1195264982bca267e62/numpy-2.4.4-cp314-cp314t-win32.whl", hash = "sha256:dddbbd259598d7240b18c9d87c56a9d2fb3b02fe266f49a7c101532e78c1d871", size = 6155500, upload-time = "2026-03-29T13:21:28.205Z" }, + { url = "https://files.pythonhosted.org/packages/c7/03/2fc4e14c7bd4ff2964b74ba90ecb8552540b6315f201df70f137faa5c589/numpy-2.4.4-cp314-cp314t-win_amd64.whl", hash = "sha256:a7164afb23be6e37ad90b2f10426149fd75aee07ca55653d2aa41e66c4ef697e", size = 12637755, upload-time = "2026-03-29T13:21:31.107Z" }, + { url = "https://files.pythonhosted.org/packages/58/78/548fb8e07b1a341746bfbecb32f2c268470f45fa028aacdbd10d9bc73aab/numpy-2.4.4-cp314-cp314t-win_arm64.whl", hash = "sha256:ba203255017337d39f89bdd58417f03c4426f12beed0440cfd933cb15f8669c7", size = 10566643, upload-time = "2026-03-29T13:21:34.339Z" }, +] + +[[package]] +name = "packaging" +version = "26.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/65/ee/299d360cdc32edc7d2cf530f3accf79c4fca01e96ffc950d8a52213bd8e4/packaging-26.0.tar.gz", hash = "sha256:00243ae351a257117b6a241061796684b084ed1c516a08c48a3f7e147a9d80b4", size = 143416, upload-time = "2026-01-21T20:50:39.064Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/b9/c538f279a4e237a006a2c98387d081e9eb060d203d8ed34467cc0f0b9b53/packaging-26.0-py3-none-any.whl", hash = "sha256:b36f1fef9334a5588b4166f8bcd26a14e521f2b55e6b9de3aaa80d3ff7a37529", size = 74366, upload-time = "2026-01-21T20:50:37.788Z" }, +] + +[[package]] +name = "pandas" +version = "3.0.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy" }, + { name = "python-dateutil" }, + { name = "tzdata", marker = "sys_platform == 'emscripten' or sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/da/99/b342345300f13440fe9fe385c3c481e2d9a595ee3bab4d3219247ac94e9a/pandas-3.0.2.tar.gz", hash = "sha256:f4753e73e34c8d83221ba58f232433fca2748be8b18dbca02d242ed153945043", size = 4645855, upload-time = "2026-03-31T06:48:30.816Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bf/ca/3e639a1ea6fcd0617ca4e8ca45f62a74de33a56ae6cd552735470b22c8d3/pandas-3.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b5918ba197c951dec132b0c5929a00c0bf05d5942f590d3c10a807f6e15a57d3", size = 10321105, upload-time = "2026-03-31T06:46:57.327Z" }, + { url = "https://files.pythonhosted.org/packages/0b/77/dbc82ff2fb0e63c6564356682bf201edff0ba16c98630d21a1fb312a8182/pandas-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d606a041c89c0a474a4702d532ab7e73a14fe35c8d427b972a625c8e46373668", size = 9864088, upload-time = "2026-03-31T06:46:59.935Z" }, + { url = "https://files.pythonhosted.org/packages/5c/2b/341f1b04bbca2e17e13cd3f08c215b70ef2c60c5356ef1e8c6857449edc7/pandas-3.0.2-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:710246ba0616e86891b58ab95f2495143bb2bc83ab6b06747c74216f583a6ac9", size = 10369066, upload-time = "2026-03-31T06:47:02.792Z" }, + { url = "https://files.pythonhosted.org/packages/12/c5/cbb1ffefb20a93d3f0e1fdcda699fb84976210d411b008f97f48bf6ce27e/pandas-3.0.2-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5d3cfe227c725b1f3dff4278b43d8c784656a42a9325b63af6b1492a8232209e", size = 10876780, upload-time = "2026-03-31T06:47:06.205Z" }, + { url = "https://files.pythonhosted.org/packages/98/fe/2249ae5e0a69bd0ddf17353d0a5d26611d70970111f5b3600cdc8be883e7/pandas-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c3b723df9087a9a9a840e263ebd9f88b64a12075d1bf2ea401a5a42f254f084d", size = 11375181, upload-time = "2026-03-31T06:47:09.383Z" }, + { url = "https://files.pythonhosted.org/packages/de/64/77a38b09e70b6464883b8d7584ab543e748e42c1b5d337a2ee088e0df741/pandas-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a3096110bf9eac0070b7208465f2740e2d8a670d5cb6530b5bb884eca495fd39", size = 11928899, upload-time = "2026-03-31T06:47:12.686Z" }, + { url = "https://files.pythonhosted.org/packages/5e/52/42855bf626868413f761addd574acc6195880ae247a5346477a4361c3acb/pandas-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:07a10f5c36512eead51bc578eb3354ad17578b22c013d89a796ab5eee90cd991", size = 9746574, upload-time = "2026-03-31T06:47:15.64Z" }, + { url = "https://files.pythonhosted.org/packages/88/39/21304ae06a25e8bf9fc820d69b29b2c495b2ae580d1e143146c309941760/pandas-3.0.2-cp313-cp313-win_arm64.whl", hash = "sha256:5fdbfa05931071aba28b408e59226186b01eb5e92bea2ab78b65863ca3228d84", size = 9047156, upload-time = "2026-03-31T06:47:18.595Z" }, + { url = "https://files.pythonhosted.org/packages/72/20/7defa8b27d4f330a903bb68eea33be07d839c5ea6bdda54174efcec0e1d2/pandas-3.0.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:dbc20dea3b9e27d0e66d74c42b2d0c1bed9c2ffe92adea33633e3bedeb5ac235", size = 10756238, upload-time = "2026-03-31T06:47:22.012Z" }, + { url = "https://files.pythonhosted.org/packages/e9/95/49433c14862c636afc0e9b2db83ff16b3ad92959364e52b2955e44c8e94c/pandas-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:b75c347eff42497452116ce05ef461822d97ce5b9ff8df6edacb8076092c855d", size = 10408520, upload-time = "2026-03-31T06:47:25.197Z" }, + { url = "https://files.pythonhosted.org/packages/3b/f8/462ad2b5881d6b8ec8e5f7ed2ea1893faa02290d13870a1600fe72ad8efc/pandas-3.0.2-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d1478075142e83a5571782ad007fb201ed074bdeac7ebcc8890c71442e96adf7", size = 10324154, upload-time = "2026-03-31T06:47:28.097Z" }, + { url = "https://files.pythonhosted.org/packages/0a/65/d1e69b649cbcddda23ad6e4c40ef935340f6f652a006e5cbc3555ac8adb3/pandas-3.0.2-cp313-cp313t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5880314e69e763d4c8b27937090de570f1fb8d027059a7ada3f7f8e98bdcb677", size = 10714449, upload-time = "2026-03-31T06:47:30.85Z" }, + { url = "https://files.pythonhosted.org/packages/47/a4/85b59bc65b8190ea3689882db6cdf32a5003c0ccd5a586c30fdcc3ffc4fc/pandas-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b5329e26898896f06035241a626d7c335daa479b9bbc82be7c2742d048e41172", size = 11338475, upload-time = "2026-03-31T06:47:34.026Z" }, + { url = "https://files.pythonhosted.org/packages/1e/c4/bc6966c6e38e5d9478b935272d124d80a589511ed1612a5d21d36f664c68/pandas-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:81526c4afd31971f8b62671442a4b2b51e0aa9acc3819c9f0f12a28b6fcf85f1", size = 11786568, upload-time = "2026-03-31T06:47:36.941Z" }, + { url = "https://files.pythonhosted.org/packages/e8/74/09298ca9740beed1d3504e073d67e128aa07e5ca5ca2824b0c674c0b8676/pandas-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:7cadd7e9a44ec13b621aec60f9150e744cfc7a3dd32924a7e2f45edff31823b0", size = 10488652, upload-time = "2026-03-31T06:47:40.612Z" }, + { url = "https://files.pythonhosted.org/packages/bb/40/c6ea527147c73b24fc15c891c3fcffe9c019793119c5742b8784a062c7db/pandas-3.0.2-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:db0dbfd2a6cdf3770aa60464d50333d8f3d9165b2f2671bcc299b72de5a6677b", size = 10326084, upload-time = "2026-03-31T06:47:43.834Z" }, + { url = "https://files.pythonhosted.org/packages/95/25/bdb9326c3b5455f8d4d3549fce7abcf967259de146fe2cf7a82368141948/pandas-3.0.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:0555c5882688a39317179ab4a0ed41d3ebc8812ab14c69364bbee8fb7a3f6288", size = 9914146, upload-time = "2026-03-31T06:47:46.67Z" }, + { url = "https://files.pythonhosted.org/packages/8d/77/3a227ff3337aa376c60d288e1d61c5d097131d0ac71f954d90a8f369e422/pandas-3.0.2-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:01f31a546acd5574ef77fe199bc90b55527c225c20ccda6601cf6b0fd5ed597c", size = 10444081, upload-time = "2026-03-31T06:47:49.681Z" }, + { url = "https://files.pythonhosted.org/packages/15/88/3cdd54fa279341afa10acf8d2b503556b1375245dccc9315659f795dd2e9/pandas-3.0.2-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:deeca1b5a931fdf0c2212c8a659ade6d3b1edc21f0914ce71ef24456ca7a6535", size = 10897535, upload-time = "2026-03-31T06:47:53.033Z" }, + { url = "https://files.pythonhosted.org/packages/06/9d/98cc7a7624f7932e40f434299260e2917b090a579d75937cb8a57b9d2de3/pandas-3.0.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:0f48afd9bb13300ffb5a3316973324c787054ba6665cda0da3fbd67f451995db", size = 11446992, upload-time = "2026-03-31T06:47:56.193Z" }, + { url = "https://files.pythonhosted.org/packages/9a/cd/19ff605cc3760e80602e6826ddef2824d8e7050ed80f2e11c4b079741dc3/pandas-3.0.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:6c4d8458b97a35717b62469a4ea0e85abd5ed8687277f5ccfc67f8a5126f8c53", size = 11968257, upload-time = "2026-03-31T06:47:59.137Z" }, + { url = "https://files.pythonhosted.org/packages/db/60/aba6a38de456e7341285102bede27514795c1eaa353bc0e7638b6b785356/pandas-3.0.2-cp314-cp314-win_amd64.whl", hash = "sha256:b35d14bb5d8285d9494fe93815a9e9307c0876e10f1e8e89ac5b88f728ec8dcf", size = 9865893, upload-time = "2026-03-31T06:48:02.038Z" }, + { url = "https://files.pythonhosted.org/packages/08/71/e5ec979dd2e8a093dacb8864598c0ff59a0cee0bbcdc0bfec16a51684d4f/pandas-3.0.2-cp314-cp314-win_arm64.whl", hash = "sha256:63d141b56ef686f7f0d714cfb8de4e320475b86bf4b620aa0b7da89af8cbdbbb", size = 9188644, upload-time = "2026-03-31T06:48:05.045Z" }, + { url = "https://files.pythonhosted.org/packages/f1/6c/7b45d85db19cae1eb524f2418ceaa9d85965dcf7b764ed151386b7c540f0/pandas-3.0.2-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:140f0cffb1fa2524e874dde5b477d9defe10780d8e9e220d259b2c0874c89d9d", size = 10776246, upload-time = "2026-03-31T06:48:07.789Z" }, + { url = "https://files.pythonhosted.org/packages/a8/3e/7b00648b086c106e81766f25322b48aa8dfa95b55e621dbdf2fdd413a117/pandas-3.0.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ae37e833ff4fed0ba352f6bdd8b73ba3ab3256a85e54edfd1ab51ae40cca0af8", size = 10424801, upload-time = "2026-03-31T06:48:10.897Z" }, + { url = "https://files.pythonhosted.org/packages/da/6e/558dd09a71b53b4008e7fc8a98ec6d447e9bfb63cdaeea10e5eb9b2dabe8/pandas-3.0.2-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4d888a5c678a419a5bb41a2a93818e8ed9fd3172246555c0b37b7cc27027effd", size = 10345643, upload-time = "2026-03-31T06:48:13.7Z" }, + { url = "https://files.pythonhosted.org/packages/be/e3/921c93b4d9a280409451dc8d07b062b503bbec0531d2627e73a756e99a82/pandas-3.0.2-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b444dc64c079e84df91baa8bf613d58405645461cabca929d9178f2cd392398d", size = 10743641, upload-time = "2026-03-31T06:48:16.659Z" }, + { url = "https://files.pythonhosted.org/packages/56/ca/fd17286f24fa3b4d067965d8d5d7e14fe557dd4f979a0b068ac0deaf8228/pandas-3.0.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:4544c7a54920de8eeacaa1466a6b7268ecfbc9bc64ab4dbb89c6bbe94d5e0660", size = 11361993, upload-time = "2026-03-31T06:48:19.475Z" }, + { url = "https://files.pythonhosted.org/packages/e4/a5/2f6ed612056819de445a433ca1f2821ac3dab7f150d569a59e9cc105de1d/pandas-3.0.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:734be7551687c00fbd760dc0522ed974f82ad230d4a10f54bf51b80d44a08702", size = 11815274, upload-time = "2026-03-31T06:48:22.695Z" }, + { url = "https://files.pythonhosted.org/packages/00/2f/b622683e99ec3ce00b0854bac9e80868592c5b051733f2cf3a868e5fea26/pandas-3.0.2-cp314-cp314t-win_amd64.whl", hash = "sha256:57a07209bebcbcf768d2d13c9b78b852f9a15978dac41b9e6421a81ad4cdd276", size = 10888530, upload-time = "2026-03-31T06:48:25.806Z" }, + { url = "https://files.pythonhosted.org/packages/cb/2b/f8434233fab2bd66a02ec014febe4e5adced20e2693e0e90a07d118ed30e/pandas-3.0.2-cp314-cp314t-win_arm64.whl", hash = "sha256:5371b72c2d4d415d08765f32d689217a43227484e81b2305b52076e328f6f482", size = 9455341, upload-time = "2026-03-31T06:48:28.418Z" }, +] + +[[package]] +name = "pandocfilters" +version = "1.5.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/70/6f/3dd4940bbe001c06a65f88e36bad298bc7a0de5036115639926b0c5c0458/pandocfilters-1.5.1.tar.gz", hash = "sha256:002b4a555ee4ebc03f8b66307e287fa492e4a77b4ea14d3f934328297bb4939e", size = 8454, upload-time = "2024-01-18T20:08:13.726Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ef/af/4fbc8cab944db5d21b7e2a5b8e9211a03a79852b1157e2c102fcc61ac440/pandocfilters-1.5.1-py2.py3-none-any.whl", hash = "sha256:93be382804a9cdb0a7267585f157e5d1731bbe5545a85b268d6f5fe6232de2bc", size = 8663, upload-time = "2024-01-18T20:08:11.28Z" }, +] + +[[package]] +name = "parso" +version = "0.8.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/81/76/a1e769043c0c0c9fe391b702539d594731a4362334cdf4dc25d0c09761e7/parso-0.8.6.tar.gz", hash = "sha256:2b9a0332696df97d454fa67b81618fd69c35a7b90327cbe6ba5c92d2c68a7bfd", size = 401621, upload-time = "2026-02-09T15:45:24.425Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b6/61/fae042894f4296ec49e3f193aff5d7c18440da9e48102c3315e1bc4519a7/parso-0.8.6-py2.py3-none-any.whl", hash = "sha256:2c549f800b70a5c4952197248825584cb00f033b29c692671d3bf08bf380baff", size = 106894, upload-time = "2026-02-09T15:45:21.391Z" }, +] + +[[package]] +name = "pexpect" +version = "4.9.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "ptyprocess", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/42/92/cc564bf6381ff43ce1f4d06852fc19a2f11d180f23dc32d9588bee2f149d/pexpect-4.9.0.tar.gz", hash = "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f", size = 166450, upload-time = "2023-11-25T09:07:26.339Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9e/c3/059298687310d527a58bb01f3b1965787ee3b40dce76752eda8b44e9a2c5/pexpect-4.9.0-py2.py3-none-any.whl", hash = "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523", size = 63772, upload-time = "2023-11-25T06:56:14.81Z" }, +] + +[[package]] +name = "pillow" +version = "12.2.0" +source = { registry = "https://pypi.org/simple" } +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/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/bf/98/4595daa2365416a86cb0d495248a393dfc84e96d62ad080c8546256cb9c0/pillow-12.2.0-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:3adc9215e8be0448ed6e814966ecf3d9952f0ea40eb14e89a102b87f450660d8", size = 4100848, upload-time = "2026-04-01T14:44:48.48Z" }, + { url = "https://files.pythonhosted.org/packages/0b/79/40184d464cf89f6663e18dfcf7ca21aae2491fff1a16127681bf1fa9b8cf/pillow-12.2.0-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:6a9adfc6d24b10f89588096364cc726174118c62130c817c2837c60cf08a392b", size = 4176515, upload-time = "2026-04-01T14:44:51.353Z" }, + { url = "https://files.pythonhosted.org/packages/b0/63/703f86fd4c422a9cf722833670f4f71418fb116b2853ff7da722ea43f184/pillow-12.2.0-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:6a6e67ea2e6feda684ed370f9a1c52e7a243631c025ba42149a2cc5934dec295", size = 3640159, upload-time = "2026-04-01T14:44:53.588Z" }, + { url = "https://files.pythonhosted.org/packages/71/e0/fb22f797187d0be2270f83500aab851536101b254bfa1eae10795709d283/pillow-12.2.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:2bb4a8d594eacdfc59d9e5ad972aa8afdd48d584ffd5f13a937a664c3e7db0ed", size = 5312185, upload-time = "2026-04-01T14:44:56.039Z" }, + { url = "https://files.pythonhosted.org/packages/ba/8c/1a9e46228571de18f8e28f16fabdfc20212a5d019f3e3303452b3f0a580d/pillow-12.2.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:80b2da48193b2f33ed0c32c38140f9d3186583ce7d516526d462645fd98660ae", size = 4695386, upload-time = "2026-04-01T14:44:58.663Z" }, + { url = "https://files.pythonhosted.org/packages/70/62/98f6b7f0c88b9addd0e87c217ded307b36be024d4ff8869a812b241d1345/pillow-12.2.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:22db17c68434de69d8ecfc2fe821569195c0c373b25cccb9cbdacf2c6e53c601", size = 6280384, upload-time = "2026-04-01T14:45:01.5Z" }, + { url = "https://files.pythonhosted.org/packages/5e/03/688747d2e91cfbe0e64f316cd2e8005698f76ada3130d0194664174fa5de/pillow-12.2.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7b14cc0106cd9aecda615dd6903840a058b4700fcb817687d0ee4fc8b6e389be", size = 8091599, upload-time = "2026-04-01T14:45:04.5Z" }, + { url = "https://files.pythonhosted.org/packages/f6/35/577e22b936fcdd66537329b33af0b4ccfefaeabd8aec04b266528cddb33c/pillow-12.2.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8cbeb542b2ebc6fcdacabf8aca8c1a97c9b3ad3927d46b8723f9d4f033288a0f", size = 6396021, upload-time = "2026-04-01T14:45:07.117Z" }, + { url = "https://files.pythonhosted.org/packages/11/8d/d2532ad2a603ca2b93ad9f5135732124e57811d0168155852f37fbce2458/pillow-12.2.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4bfd07bc812fbd20395212969e41931001fd59eb55a60658b0e5710872e95286", size = 7083360, upload-time = "2026-04-01T14:45:09.763Z" }, + { url = "https://files.pythonhosted.org/packages/5e/26/d325f9f56c7e039034897e7380e9cc202b1e368bfd04d4cbe6a441f02885/pillow-12.2.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:9aba9a17b623ef750a4d11b742cbafffeb48a869821252b30ee21b5e91392c50", size = 6507628, upload-time = "2026-04-01T14:45:12.378Z" }, + { url = "https://files.pythonhosted.org/packages/5f/f7/769d5632ffb0988f1c5e7660b3e731e30f7f8ec4318e94d0a5d674eb65a4/pillow-12.2.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:deede7c263feb25dba4e82ea23058a235dcc2fe1f6021025dc71f2b618e26104", size = 7209321, upload-time = "2026-04-01T14:45:15.122Z" }, + { url = "https://files.pythonhosted.org/packages/6a/7a/c253e3c645cd47f1aceea6a8bacdba9991bf45bb7dfe927f7c893e89c93c/pillow-12.2.0-cp314-cp314-win32.whl", hash = "sha256:632ff19b2778e43162304d50da0181ce24ac5bb8180122cbe1bf4673428328c7", size = 6479723, upload-time = "2026-04-01T14:45:17.797Z" }, + { url = "https://files.pythonhosted.org/packages/cd/8b/601e6566b957ca50e28725cb6c355c59c2c8609751efbecd980db44e0349/pillow-12.2.0-cp314-cp314-win_amd64.whl", hash = "sha256:4e6c62e9d237e9b65fac06857d511e90d8461a32adcc1b9065ea0c0fa3a28150", size = 7217400, upload-time = "2026-04-01T14:45:20.529Z" }, + { url = "https://files.pythonhosted.org/packages/d6/94/220e46c73065c3e2951bb91c11a1fb636c8c9ad427ac3ce7d7f3359b9b2f/pillow-12.2.0-cp314-cp314-win_arm64.whl", hash = "sha256:b1c1fbd8a5a1af3412a0810d060a78b5136ec0836c8a4ef9aa11807f2a22f4e1", size = 2554835, upload-time = "2026-04-01T14:45:23.162Z" }, + { url = "https://files.pythonhosted.org/packages/b6/ab/1b426a3974cb0e7da5c29ccff4807871d48110933a57207b5a676cccc155/pillow-12.2.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:57850958fe9c751670e49b2cecf6294acc99e562531f4bd317fa5ddee2068463", size = 5314225, upload-time = "2026-04-01T14:45:25.637Z" }, + { url = "https://files.pythonhosted.org/packages/19/1e/dce46f371be2438eecfee2a1960ee2a243bbe5e961890146d2dee1ff0f12/pillow-12.2.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:d5d38f1411c0ed9f97bcb49b7bd59b6b7c314e0e27420e34d99d844b9ce3b6f3", size = 4698541, upload-time = "2026-04-01T14:45:28.355Z" }, + { url = "https://files.pythonhosted.org/packages/55/c3/7fbecf70adb3a0c33b77a300dc52e424dc22ad8cdc06557a2e49523b703d/pillow-12.2.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5c0a9f29ca8e79f09de89293f82fc9b0270bb4af1d58bc98f540cc4aedf03166", size = 6322251, upload-time = "2026-04-01T14:45:30.924Z" }, + { url = "https://files.pythonhosted.org/packages/1c/3c/7fbc17cfb7e4fe0ef1642e0abc17fc6c94c9f7a16be41498e12e2ba60408/pillow-12.2.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1610dd6c61621ae1cf811bef44d77e149ce3f7b95afe66a4512f8c59f25d9ebe", size = 8127807, upload-time = "2026-04-01T14:45:33.908Z" }, + { url = "https://files.pythonhosted.org/packages/ff/c3/a8ae14d6defd2e448493ff512fae903b1e9bd40b72efb6ec55ce0048c8ce/pillow-12.2.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0a34329707af4f73cf1782a36cd2289c0368880654a2c11f027bcee9052d35dd", size = 6433935, upload-time = "2026-04-01T14:45:36.623Z" }, + { url = "https://files.pythonhosted.org/packages/6e/32/2880fb3a074847ac159d8f902cb43278a61e85f681661e7419e6596803ed/pillow-12.2.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8e9c4f5b3c546fa3458a29ab22646c1c6c787ea8f5ef51300e5a60300736905e", size = 7116720, upload-time = "2026-04-01T14:45:39.258Z" }, + { url = "https://files.pythonhosted.org/packages/46/87/495cc9c30e0129501643f24d320076f4cc54f718341df18cc70ec94c44e1/pillow-12.2.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:fb043ee2f06b41473269765c2feae53fc2e2fbf96e5e22ca94fb5ad677856f06", size = 6540498, upload-time = "2026-04-01T14:45:41.879Z" }, + { url = "https://files.pythonhosted.org/packages/18/53/773f5edca692009d883a72211b60fdaf8871cbef075eaa9d577f0a2f989e/pillow-12.2.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:f278f034eb75b4e8a13a54a876cc4a5ab39173d2cdd93a638e1b467fc545ac43", size = 7239413, upload-time = "2026-04-01T14:45:44.705Z" }, + { url = "https://files.pythonhosted.org/packages/c9/e4/4b64a97d71b2a83158134abbb2f5bd3f8a2ea691361282f010998f339ec7/pillow-12.2.0-cp314-cp314t-win32.whl", hash = "sha256:6bb77b2dcb06b20f9f4b4a8454caa581cd4dd0643a08bacf821216a16d9c8354", size = 6482084, upload-time = "2026-04-01T14:45:47.568Z" }, + { url = "https://files.pythonhosted.org/packages/ba/13/306d275efd3a3453f72114b7431c877d10b1154014c1ebbedd067770d629/pillow-12.2.0-cp314-cp314t-win_amd64.whl", hash = "sha256:6562ace0d3fb5f20ed7290f1f929cae41b25ae29528f2af1722966a0a02e2aa1", size = 7225152, upload-time = "2026-04-01T14:45:50.032Z" }, + { url = "https://files.pythonhosted.org/packages/ff/6e/cf826fae916b8658848d7b9f38d88da6396895c676e8086fc0988073aaf8/pillow-12.2.0-cp314-cp314t-win_arm64.whl", hash = "sha256:aa88ccfe4e32d362816319ed727a004423aab09c5cea43c01a4b435643fa34eb", size = 2556579, upload-time = "2026-04-01T14:45:52.529Z" }, +] + +[[package]] +name = "platformdirs" +version = "4.9.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/19/56/8d4c30c8a1d07013911a8fdbd8f89440ef9f08d07a1b50ab8ca8be5a20f9/platformdirs-4.9.4.tar.gz", hash = "sha256:1ec356301b7dc906d83f371c8f487070e99d3ccf9e501686456394622a01a934", size = 28737, upload-time = "2026-03-05T18:34:13.271Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/63/d7/97f7e3a6abb67d8080dd406fd4df842c2be0efaf712d1c899c32a075027c/platformdirs-4.9.4-py3-none-any.whl", hash = "sha256:68a9a4619a666ea6439f2ff250c12a853cd1cbd5158d258bd824a7df6be2f868", size = 21216, upload-time = "2026-03-05T18:34:12.172Z" }, +] + +[[package]] +name = "prometheus-client" +version = "0.24.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f0/58/a794d23feb6b00fc0c72787d7e87d872a6730dd9ed7c7b3e954637d8f280/prometheus_client-0.24.1.tar.gz", hash = "sha256:7e0ced7fbbd40f7b84962d5d2ab6f17ef88a72504dcf7c0b40737b43b2a461f9", size = 85616, upload-time = "2026-01-14T15:26:26.965Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/74/c3/24a2f845e3917201628ecaba4f18bab4d18a337834c1df2a159ee9d22a42/prometheus_client-0.24.1-py3-none-any.whl", hash = "sha256:150db128af71a5c2482b36e588fc8a6b95e498750da4b17065947c16070f4055", size = 64057, upload-time = "2026-01-14T15:26:24.42Z" }, +] + +[[package]] +name = "prompt-toolkit" +version = "3.0.52" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "wcwidth" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a1/96/06e01a7b38dce6fe1db213e061a4602dd6032a8a97ef6c1a862537732421/prompt_toolkit-3.0.52.tar.gz", hash = "sha256:28cde192929c8e7321de85de1ddbe736f1375148b02f2e17edd840042b1be855", size = 434198, upload-time = "2025-08-27T15:24:02.057Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/84/03/0d3ce49e2505ae70cf43bc5bb3033955d2fc9f932163e84dc0779cc47f48/prompt_toolkit-3.0.52-py3-none-any.whl", hash = "sha256:9aac639a3bbd33284347de5ad8d68ecc044b91a762dc39b7c21095fcd6a19955", size = 391431, upload-time = "2025-08-27T15:23:59.498Z" }, +] + +[[package]] +name = "psutil" +version = "7.2.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/aa/c6/d1ddf4abb55e93cebc4f2ed8b5d6dbad109ecb8d63748dd2b20ab5e57ebe/psutil-7.2.2.tar.gz", hash = "sha256:0746f5f8d406af344fd547f1c8daa5f5c33dbc293bb8d6a16d80b4bb88f59372", size = 493740, upload-time = "2026-01-28T18:14:54.428Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/51/08/510cbdb69c25a96f4ae523f733cdc963ae654904e8db864c07585ef99875/psutil-7.2.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:2edccc433cbfa046b980b0df0171cd25bcaeb3a68fe9022db0979e7aa74a826b", size = 130595, upload-time = "2026-01-28T18:14:57.293Z" }, + { url = "https://files.pythonhosted.org/packages/d6/f5/97baea3fe7a5a9af7436301f85490905379b1c6f2dd51fe3ecf24b4c5fbf/psutil-7.2.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e78c8603dcd9a04c7364f1a3e670cea95d51ee865e4efb3556a3a63adef958ea", size = 131082, upload-time = "2026-01-28T18:14:59.732Z" }, + { url = "https://files.pythonhosted.org/packages/37/d6/246513fbf9fa174af531f28412297dd05241d97a75911ac8febefa1a53c6/psutil-7.2.2-cp313-cp313t-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1a571f2330c966c62aeda00dd24620425d4b0cc86881c89861fbc04549e5dc63", size = 181476, upload-time = "2026-01-28T18:15:01.884Z" }, + { url = "https://files.pythonhosted.org/packages/b8/b5/9182c9af3836cca61696dabe4fd1304e17bc56cb62f17439e1154f225dd3/psutil-7.2.2-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:917e891983ca3c1887b4ef36447b1e0873e70c933afc831c6b6da078ba474312", size = 184062, upload-time = "2026-01-28T18:15:04.436Z" }, + { url = "https://files.pythonhosted.org/packages/16/ba/0756dca669f5a9300d0cbcbfae9a4c30e446dfc7440ffe43ded5724bfd93/psutil-7.2.2-cp313-cp313t-win_amd64.whl", hash = "sha256:ab486563df44c17f5173621c7b198955bd6b613fb87c71c161f827d3fb149a9b", size = 139893, upload-time = "2026-01-28T18:15:06.378Z" }, + { url = "https://files.pythonhosted.org/packages/1c/61/8fa0e26f33623b49949346de05ec1ddaad02ed8ba64af45f40a147dbfa97/psutil-7.2.2-cp313-cp313t-win_arm64.whl", hash = "sha256:ae0aefdd8796a7737eccea863f80f81e468a1e4cf14d926bd9b6f5f2d5f90ca9", size = 135589, upload-time = "2026-01-28T18:15:08.03Z" }, + { url = "https://files.pythonhosted.org/packages/81/69/ef179ab5ca24f32acc1dac0c247fd6a13b501fd5534dbae0e05a1c48b66d/psutil-7.2.2-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:eed63d3b4d62449571547b60578c5b2c4bcccc5387148db46e0c2313dad0ee00", size = 130664, upload-time = "2026-01-28T18:15:09.469Z" }, + { url = "https://files.pythonhosted.org/packages/7b/64/665248b557a236d3fa9efc378d60d95ef56dd0a490c2cd37dafc7660d4a9/psutil-7.2.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7b6d09433a10592ce39b13d7be5a54fbac1d1228ed29abc880fb23df7cb694c9", size = 131087, upload-time = "2026-01-28T18:15:11.724Z" }, + { url = "https://files.pythonhosted.org/packages/d5/2e/e6782744700d6759ebce3043dcfa661fb61e2fb752b91cdeae9af12c2178/psutil-7.2.2-cp314-cp314t-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1fa4ecf83bcdf6e6c8f4449aff98eefb5d0604bf88cb883d7da3d8d2d909546a", size = 182383, upload-time = "2026-01-28T18:15:13.445Z" }, + { url = "https://files.pythonhosted.org/packages/57/49/0a41cefd10cb7505cdc04dab3eacf24c0c2cb158a998b8c7b1d27ee2c1f5/psutil-7.2.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e452c464a02e7dc7822a05d25db4cde564444a67e58539a00f929c51eddda0cf", size = 185210, upload-time = "2026-01-28T18:15:16.002Z" }, + { url = "https://files.pythonhosted.org/packages/dd/2c/ff9bfb544f283ba5f83ba725a3c5fec6d6b10b8f27ac1dc641c473dc390d/psutil-7.2.2-cp314-cp314t-win_amd64.whl", hash = "sha256:c7663d4e37f13e884d13994247449e9f8f574bc4655d509c3b95e9ec9e2b9dc1", size = 141228, upload-time = "2026-01-28T18:15:18.385Z" }, + { url = "https://files.pythonhosted.org/packages/f2/fc/f8d9c31db14fcec13748d373e668bc3bed94d9077dbc17fb0eebc073233c/psutil-7.2.2-cp314-cp314t-win_arm64.whl", hash = "sha256:11fe5a4f613759764e79c65cf11ebdf26e33d6dd34336f8a337aa2996d71c841", size = 136284, upload-time = "2026-01-28T18:15:19.912Z" }, + { url = "https://files.pythonhosted.org/packages/e7/36/5ee6e05c9bd427237b11b3937ad82bb8ad2752d72c6969314590dd0c2f6e/psutil-7.2.2-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:ed0cace939114f62738d808fdcecd4c869222507e266e574799e9c0faa17d486", size = 129090, upload-time = "2026-01-28T18:15:22.168Z" }, + { url = "https://files.pythonhosted.org/packages/80/c4/f5af4c1ca8c1eeb2e92ccca14ce8effdeec651d5ab6053c589b074eda6e1/psutil-7.2.2-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:1a7b04c10f32cc88ab39cbf606e117fd74721c831c98a27dc04578deb0c16979", size = 129859, upload-time = "2026-01-28T18:15:23.795Z" }, + { url = "https://files.pythonhosted.org/packages/b5/70/5d8df3b09e25bce090399cf48e452d25c935ab72dad19406c77f4e828045/psutil-7.2.2-cp36-abi3-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:076a2d2f923fd4821644f5ba89f059523da90dc9014e85f8e45a5774ca5bc6f9", size = 155560, upload-time = "2026-01-28T18:15:25.976Z" }, + { url = "https://files.pythonhosted.org/packages/63/65/37648c0c158dc222aba51c089eb3bdfa238e621674dc42d48706e639204f/psutil-7.2.2-cp36-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b0726cecd84f9474419d67252add4ac0cd9811b04d61123054b9fb6f57df6e9e", size = 156997, upload-time = "2026-01-28T18:15:27.794Z" }, + { url = "https://files.pythonhosted.org/packages/8e/13/125093eadae863ce03c6ffdbae9929430d116a246ef69866dad94da3bfbc/psutil-7.2.2-cp36-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:fd04ef36b4a6d599bbdb225dd1d3f51e00105f6d48a28f006da7f9822f2606d8", size = 148972, upload-time = "2026-01-28T18:15:29.342Z" }, + { url = "https://files.pythonhosted.org/packages/04/78/0acd37ca84ce3ddffaa92ef0f571e073faa6d8ff1f0559ab1272188ea2be/psutil-7.2.2-cp36-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:b58fabe35e80b264a4e3bb23e6b96f9e45a3df7fb7eed419ac0e5947c61e47cc", size = 148266, upload-time = "2026-01-28T18:15:31.597Z" }, + { url = "https://files.pythonhosted.org/packages/b4/90/e2159492b5426be0c1fef7acba807a03511f97c5f86b3caeda6ad92351a7/psutil-7.2.2-cp37-abi3-win_amd64.whl", hash = "sha256:eb7e81434c8d223ec4a219b5fc1c47d0417b12be7ea866e24fb5ad6e84b3d988", size = 137737, upload-time = "2026-01-28T18:15:33.849Z" }, + { url = "https://files.pythonhosted.org/packages/8c/c7/7bb2e321574b10df20cbde462a94e2b71d05f9bbda251ef27d104668306a/psutil-7.2.2-cp37-abi3-win_arm64.whl", hash = "sha256:8c233660f575a5a89e6d4cb65d9f938126312bca76d8fe087b947b3a1aaac9ee", size = 134617, upload-time = "2026-01-28T18:15:36.514Z" }, +] + +[[package]] +name = "ptyprocess" +version = "0.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/20/e5/16ff212c1e452235a90aeb09066144d0c5a6a8c0834397e03f5224495c4e/ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220", size = 70762, upload-time = "2020-12-28T15:15:30.155Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/22/a6/858897256d0deac81a172289110f31629fc4cee19b6f01283303e18c8db3/ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35", size = 13993, upload-time = "2020-12-28T15:15:28.35Z" }, +] + +[[package]] +name = "pure-eval" +version = "0.2.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cd/05/0a34433a064256a578f1783a10da6df098ceaa4a57bbeaa96a6c0352786b/pure_eval-0.2.3.tar.gz", hash = "sha256:5f4e983f40564c576c7c8635ae88db5956bb2229d7e9237d03b3c0b0190eaf42", size = 19752, upload-time = "2024-07-21T12:58:21.801Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8e/37/efad0257dc6e593a18957422533ff0f87ede7c9c6ea010a2177d738fb82f/pure_eval-0.2.3-py3-none-any.whl", hash = "sha256:1db8e35b67b3d218d818ae653e27f06c3aa420901fa7b081ca98cbedc874e0d0", size = 11842, upload-time = "2024-07-21T12:58:20.04Z" }, +] + +[[package]] +name = "pyarrow" +version = "23.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/88/22/134986a4cc224d593c1afde5494d18ff629393d74cc2eddb176669f234a4/pyarrow-23.0.1.tar.gz", hash = "sha256:b8c5873e33440b2bc2f4a79d2b47017a89c5a24116c055625e6f2ee50523f019", size = 1167336, upload-time = "2026-02-16T10:14:12.39Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/47/10/2cbe4c6f0fb83d2de37249567373d64327a5e4d8db72f486db42875b08f6/pyarrow-23.0.1-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:6b8fda694640b00e8af3c824f99f789e836720aa8c9379fb435d4c4953a756b8", size = 34210066, upload-time = "2026-02-16T10:10:45.487Z" }, + { url = "https://files.pythonhosted.org/packages/cb/4f/679fa7e84dadbaca7a65f7cdba8d6c83febbd93ca12fa4adf40ba3b6362b/pyarrow-23.0.1-cp313-cp313-macosx_12_0_x86_64.whl", hash = "sha256:8ff51b1addc469b9444b7c6f3548e19dc931b172ab234e995a60aea9f6e6025f", size = 35825526, upload-time = "2026-02-16T10:10:52.266Z" }, + { url = "https://files.pythonhosted.org/packages/f9/63/d2747d930882c9d661e9398eefc54f15696547b8983aaaf11d4a2e8b5426/pyarrow-23.0.1-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:71c5be5cbf1e1cb6169d2a0980850bccb558ddc9b747b6206435313c47c37677", size = 44473279, upload-time = "2026-02-16T10:11:01.557Z" }, + { url = "https://files.pythonhosted.org/packages/b3/93/10a48b5e238de6d562a411af6467e71e7aedbc9b87f8d3a35f1560ae30fb/pyarrow-23.0.1-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:9b6f4f17b43bc39d56fec96e53fe89d94bac3eb134137964371b45352d40d0c2", size = 47585798, upload-time = "2026-02-16T10:11:09.401Z" }, + { url = "https://files.pythonhosted.org/packages/5c/20/476943001c54ef078dbf9542280e22741219a184a0632862bca4feccd666/pyarrow-23.0.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9fc13fc6c403d1337acab46a2c4346ca6c9dec5780c3c697cf8abfd5e19b6b37", size = 48179446, upload-time = "2026-02-16T10:11:17.781Z" }, + { url = "https://files.pythonhosted.org/packages/4b/b6/5dd0c47b335fcd8edba9bfab78ad961bd0fd55ebe53468cc393f45e0be60/pyarrow-23.0.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5c16ed4f53247fa3ffb12a14d236de4213a4415d127fe9cebed33d51671113e2", size = 50623972, upload-time = "2026-02-16T10:11:26.185Z" }, + { url = "https://files.pythonhosted.org/packages/d5/09/a532297c9591a727d67760e2e756b83905dd89adb365a7f6e9c72578bcc1/pyarrow-23.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:cecfb12ef629cf6be0b1887f9f86463b0dd3dc3195ae6224e74006be4736035a", size = 27540749, upload-time = "2026-02-16T10:12:23.297Z" }, + { url = "https://files.pythonhosted.org/packages/a5/8e/38749c4b1303e6ae76b3c80618f84861ae0c55dd3c2273842ea6f8258233/pyarrow-23.0.1-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:29f7f7419a0e30264ea261fdc0e5fe63ce5a6095003db2945d7cd78df391a7e1", size = 34471544, upload-time = "2026-02-16T10:11:32.535Z" }, + { url = "https://files.pythonhosted.org/packages/a3/73/f237b2bc8c669212f842bcfd842b04fc8d936bfc9d471630569132dc920d/pyarrow-23.0.1-cp313-cp313t-macosx_12_0_x86_64.whl", hash = "sha256:33d648dc25b51fd8055c19e4261e813dfc4d2427f068bcecc8b53d01b81b0500", size = 35949911, upload-time = "2026-02-16T10:11:39.813Z" }, + { url = "https://files.pythonhosted.org/packages/0c/86/b912195eee0903b5611bf596833def7d146ab2d301afeb4b722c57ffc966/pyarrow-23.0.1-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:cd395abf8f91c673dd3589cadc8cc1ee4e8674fa61b2e923c8dd215d9c7d1f41", size = 44520337, upload-time = "2026-02-16T10:11:47.764Z" }, + { url = "https://files.pythonhosted.org/packages/69/c2/f2a717fb824f62d0be952ea724b4f6f9372a17eed6f704b5c9526f12f2f1/pyarrow-23.0.1-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:00be9576d970c31defb5c32eb72ef585bf600ef6d0a82d5eccaae96639cf9d07", size = 47548944, upload-time = "2026-02-16T10:11:56.607Z" }, + { url = "https://files.pythonhosted.org/packages/84/a7/90007d476b9f0dc308e3bc57b832d004f848fd6c0da601375d20d92d1519/pyarrow-23.0.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:c2139549494445609f35a5cda4eb94e2c9e4d704ce60a095b342f82460c73a83", size = 48236269, upload-time = "2026-02-16T10:12:04.47Z" }, + { url = "https://files.pythonhosted.org/packages/b0/3f/b16fab3e77709856eb6ac328ce35f57a6d4a18462c7ca5186ef31b45e0e0/pyarrow-23.0.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:7044b442f184d84e2351e5084600f0d7343d6117aabcbc1ac78eb1ae11eb4125", size = 50604794, upload-time = "2026-02-16T10:12:11.797Z" }, + { url = "https://files.pythonhosted.org/packages/e9/a1/22df0620a9fac31d68397a75465c344e83c3dfe521f7612aea33e27ab6c0/pyarrow-23.0.1-cp313-cp313t-win_amd64.whl", hash = "sha256:a35581e856a2fafa12f3f54fce4331862b1cfb0bef5758347a858a4aa9d6bae8", size = 27660642, upload-time = "2026-02-16T10:12:17.746Z" }, + { url = "https://files.pythonhosted.org/packages/8d/1b/6da9a89583ce7b23ac611f183ae4843cd3a6cf54f079549b0e8c14031e73/pyarrow-23.0.1-cp314-cp314-macosx_12_0_arm64.whl", hash = "sha256:5df1161da23636a70838099d4aaa65142777185cc0cdba4037a18cee7d8db9ca", size = 34238755, upload-time = "2026-02-16T10:12:32.819Z" }, + { url = "https://files.pythonhosted.org/packages/ae/b5/d58a241fbe324dbaeb8df07be6af8752c846192d78d2272e551098f74e88/pyarrow-23.0.1-cp314-cp314-macosx_12_0_x86_64.whl", hash = "sha256:fa8e51cb04b9f8c9c5ace6bab63af9a1f88d35c0d6cbf53e8c17c098552285e1", size = 35847826, upload-time = "2026-02-16T10:12:38.949Z" }, + { url = "https://files.pythonhosted.org/packages/54/a5/8cbc83f04aba433ca7b331b38f39e000efd9f0c7ce47128670e737542996/pyarrow-23.0.1-cp314-cp314-manylinux_2_28_aarch64.whl", hash = "sha256:0b95a3994f015be13c63148fef8832e8a23938128c185ee951c98908a696e0eb", size = 44536859, upload-time = "2026-02-16T10:12:45.467Z" }, + { url = "https://files.pythonhosted.org/packages/36/2e/c0f017c405fcdc252dbccafbe05e36b0d0eb1ea9a958f081e01c6972927f/pyarrow-23.0.1-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:4982d71350b1a6e5cfe1af742c53dfb759b11ce14141870d05d9e540d13bc5d1", size = 47614443, upload-time = "2026-02-16T10:12:55.525Z" }, + { url = "https://files.pythonhosted.org/packages/af/6b/2314a78057912f5627afa13ba43809d9d653e6630859618b0fd81a4e0759/pyarrow-23.0.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c250248f1fe266db627921c89b47b7c06fee0489ad95b04d50353537d74d6886", size = 48232991, upload-time = "2026-02-16T10:13:04.729Z" }, + { url = "https://files.pythonhosted.org/packages/40/f2/1bcb1d3be3460832ef3370d621142216e15a2c7c62602a4ea19ec240dd64/pyarrow-23.0.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5f4763b83c11c16e5f4c15601ba6dfa849e20723b46aa2617cb4bffe8768479f", size = 50645077, upload-time = "2026-02-16T10:13:14.147Z" }, + { url = "https://files.pythonhosted.org/packages/eb/3f/b1da7b61cd66566a4d4c8383d376c606d1c34a906c3f1cb35c479f59d1aa/pyarrow-23.0.1-cp314-cp314-win_amd64.whl", hash = "sha256:3a4c85ef66c134161987c17b147d6bffdca4566f9a4c1d81a0a01cdf08414ea5", size = 28234271, upload-time = "2026-02-16T10:14:09.397Z" }, + { url = "https://files.pythonhosted.org/packages/b5/78/07f67434e910a0f7323269be7bfbf58699bd0c1d080b18a1ab49ba943fe8/pyarrow-23.0.1-cp314-cp314t-macosx_12_0_arm64.whl", hash = "sha256:17cd28e906c18af486a499422740298c52d7c6795344ea5002a7720b4eadf16d", size = 34488692, upload-time = "2026-02-16T10:13:21.541Z" }, + { url = "https://files.pythonhosted.org/packages/50/76/34cf7ae93ece1f740a04910d9f7e80ba166b9b4ab9596a953e9e62b90fe1/pyarrow-23.0.1-cp314-cp314t-macosx_12_0_x86_64.whl", hash = "sha256:76e823d0e86b4fb5e1cf4a58d293036e678b5a4b03539be933d3b31f9406859f", size = 35964383, upload-time = "2026-02-16T10:13:28.63Z" }, + { url = "https://files.pythonhosted.org/packages/46/90/459b827238936d4244214be7c684e1b366a63f8c78c380807ae25ed92199/pyarrow-23.0.1-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:a62e1899e3078bf65943078b3ad2a6ddcacf2373bc06379aac61b1e548a75814", size = 44538119, upload-time = "2026-02-16T10:13:35.506Z" }, + { url = "https://files.pythonhosted.org/packages/28/a1/93a71ae5881e99d1f9de1d4554a87be37da11cd6b152239fb5bd924fdc64/pyarrow-23.0.1-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:df088e8f640c9fae3b1f495b3c64755c4e719091caf250f3a74d095ddf3c836d", size = 47571199, upload-time = "2026-02-16T10:13:42.504Z" }, + { url = "https://files.pythonhosted.org/packages/88/a3/d2c462d4ef313521eaf2eff04d204ac60775263f1fb08c374b543f79f610/pyarrow-23.0.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:46718a220d64677c93bc243af1d44b55998255427588e400677d7192671845c7", size = 48259435, upload-time = "2026-02-16T10:13:49.226Z" }, + { url = "https://files.pythonhosted.org/packages/cc/f1/11a544b8c3d38a759eb3fbb022039117fd633e9a7b19e4841cc3da091915/pyarrow-23.0.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:a09f3876e87f48bc2f13583ab551f0379e5dfb83210391e68ace404181a20690", size = 50629149, upload-time = "2026-02-16T10:13:57.238Z" }, + { url = "https://files.pythonhosted.org/packages/50/f2/c0e76a0b451ffdf0cf788932e182758eb7558953f4f27f1aff8e2518b653/pyarrow-23.0.1-cp314-cp314t-win_amd64.whl", hash = "sha256:527e8d899f14bd15b740cd5a54ad56b7f98044955373a17179d5956ddb93d9ce", size = 28365807, upload-time = "2026-02-16T10:14:03.892Z" }, +] + +[[package]] +name = "pycparser" +version = "3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1b/7d/92392ff7815c21062bea51aa7b87d45576f649f16458d78b7cf94b9ab2e6/pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29", size = 103492, upload-time = "2026-01-21T14:26:51.89Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992", size = 48172, upload-time = "2026-01-21T14:26:50.693Z" }, +] + +[[package]] +name = "pycrdt" +version = "0.12.50" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5d/bd/6e049694ad7fed0baf45a62629ff2c7aa1c26e0581a4d4987e0fd39fe951/pycrdt-0.12.50.tar.gz", hash = "sha256:506d4bc00d7d566de4018dca52998ab7cf97c787363bc59440d3a3bb3336d1a0", size = 84528, upload-time = "2026-03-16T09:39:15.924Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/ea/cdc543c51971c513f3b23c34d17ae672dd2fab40977b8d94344c6e8099be/pycrdt-0.12.50-cp313-cp313-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:f75c95335cacc459dbb3c4e55afbd231f8befd333c617ffad1bbe348018021de", size = 1721432, upload-time = "2026-03-16T09:38:16.738Z" }, + { url = "https://files.pythonhosted.org/packages/b6/30/cde0c58cdfb0f2e4d523443637b11b9bb5963024f5f3cd9e889b8195eab4/pycrdt-0.12.50-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3842dff93946c1b46ea8c508f7d79f07f0a8c54fe8f8e83e6cbb1f9f35a62899", size = 944575, upload-time = "2026-03-16T09:38:18.574Z" }, + { url = "https://files.pythonhosted.org/packages/df/a8/b36e98bca96b9c9b3d554ce6984128dff076a47cb350462efb122a09613e/pycrdt-0.12.50-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fba48534acb7ba22a975c38ff531178d25a01c29d5d4ec2ecfe1c45754cde181", size = 962165, upload-time = "2026-03-16T09:38:20.112Z" }, + { url = "https://files.pythonhosted.org/packages/69/c2/38e0055416466feb9b33cfc96a95c3bd3985cdb547fdc0e556d8903e074f/pycrdt-0.12.50-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a5ca809926c3e08965b201b277c26d319c47078ba4b22178976f0455b351155b", size = 1135011, upload-time = "2026-03-16T09:38:21.952Z" }, + { url = "https://files.pythonhosted.org/packages/fe/5f/9597d1b2fcd8f1bff78308352dc8568012e1e2c2ef44a0e5ca11cd04aa81/pycrdt-0.12.50-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bffe6a7e6a59ea1c74a53a0ffa2fee27ff54e454cff333ef952922535c7c8ffa", size = 987535, upload-time = "2026-03-16T09:38:23.459Z" }, + { url = "https://files.pythonhosted.org/packages/ed/f8/882da205925f147610ca790304a025232c164256421655e19cd9eabfca06/pycrdt-0.12.50-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:688d8cb017a729719be8f9ecf488daba24781c05a1635f725ca257aa9a90acfd", size = 956238, upload-time = "2026-03-16T09:38:25.473Z" }, + { url = "https://files.pythonhosted.org/packages/78/91/6cf0db29eebdafe8d3a27ec0a9ece583acab0959d0de22968fcc43f51d75/pycrdt-0.12.50-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:71f9dfc24636dc9789246dae4c8db39f5b9b419c1a1f6f53b782ae22e8febbef", size = 1046621, upload-time = "2026-03-16T09:38:27.349Z" }, + { url = "https://files.pythonhosted.org/packages/b4/40/f1e79a74c12439a595f1986a403e08a35abedce5929c4f464be5f2ec8109/pycrdt-0.12.50-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a33635da609afe467e4ae644766416454535161ec7e1427294a59ed8a5e80015", size = 1121675, upload-time = "2026-03-16T09:38:28.991Z" }, + { url = "https://files.pythonhosted.org/packages/03/7f/b966b7c489e306070eef305b3f591e7ce7a34ee445cb55d1b8fd4fa6e338/pycrdt-0.12.50-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:f48c78ef3710c033d07d5de326362826eda8fa941859f06c146007d6122b3bb4", size = 1235939, upload-time = "2026-03-16T09:38:30.721Z" }, + { url = "https://files.pythonhosted.org/packages/c7/7a/0a4a74c68349ee72c3e92baad0cb9fbc6a94f2c122a228489357b8ad3507/pycrdt-0.12.50-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:c714c1582b804bd296f9b8530353bfab54386a145164e9693443e38b23392d69", size = 1222964, upload-time = "2026-03-16T09:38:32.323Z" }, + { url = "https://files.pythonhosted.org/packages/be/54/c96b470ebc5eaf355beeb8ffaf0235976e3e1fb9d4bc8a1169138c7e5063/pycrdt-0.12.50-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d88a146090d9d6fc64687574c6014b26be1673b8b54b450fca23f115068c2852", size = 1165811, upload-time = "2026-03-16T09:38:34.05Z" }, + { url = "https://files.pythonhosted.org/packages/78/e4/070a16212142bda9cb585571066e1aa48ffcdc2ffb3540759d96dcebd141/pycrdt-0.12.50-cp313-cp313-win32.whl", hash = "sha256:a149f0f080f19b1c9a5614885e134ebbe159ee8add9fce96b81fcb3ea261df94", size = 695256, upload-time = "2026-03-16T09:38:35.705Z" }, + { url = "https://files.pythonhosted.org/packages/03/63/e0beaeabc4bb32901cff77ac9bc0edfa1b2e81a739cc5cd3990896759f94/pycrdt-0.12.50-cp313-cp313-win_amd64.whl", hash = "sha256:96db3bff011f0f85e2c95ad3337abf9553dc08d2cafb2bba6ee4b30b53a585d0", size = 748447, upload-time = "2026-03-16T09:38:37.483Z" }, + { url = "https://files.pythonhosted.org/packages/f7/5d/ae92c859ec5ee4f63d2df3702ce7a782cb054d1cef9a72d17b15a0f787f9/pycrdt-0.12.50-cp314-cp314-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:382cf259b848db979f2cc8f37c8b1c20c46de8df10142383e8502c8eb40589ba", size = 1720667, upload-time = "2026-03-16T09:38:39.222Z" }, + { url = "https://files.pythonhosted.org/packages/f9/d7/03d5a6d806eec5cc880d17d88a2f8868bd3ddf20aea988ce9238d433cfb4/pycrdt-0.12.50-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:022450e769b8ec37027504602f3dcfc4171d0d27ebe0f04c28d9eb5a3641fdff", size = 946541, upload-time = "2026-03-16T09:38:40.918Z" }, + { url = "https://files.pythonhosted.org/packages/9a/af/4700d71886afeb406b5b6d16d36dbd15fd0d3caa37af60894aca75dc8f3e/pycrdt-0.12.50-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:41c5470f1fe5426e81986664e786508935d00050f061a5eb341af596c67c0bc7", size = 960844, upload-time = "2026-03-16T09:38:42.605Z" }, + { url = "https://files.pythonhosted.org/packages/e9/95/b3640697e6e7dd6675e8fb41c95fba89d84cf435249ed0b8c310ae7eaa10/pycrdt-0.12.50-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bccb80466c7bcaafa1591cdd44b4f4302993324dd09b16a1c4b05f6153a0a458", size = 1136447, upload-time = "2026-03-16T09:38:44.254Z" }, + { url = "https://files.pythonhosted.org/packages/f8/50/fec4bf7fdd8b82e295be28c890a856a2d80e94d4d49098e660bb2c4520bd/pycrdt-0.12.50-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b7b2061ad56d4305fce05ddfa269a662e1137997494f74f3f0633052f8beccd4", size = 986746, upload-time = "2026-03-16T09:38:45.88Z" }, + { url = "https://files.pythonhosted.org/packages/70/40/3f82b3bc35adc4ad194a2a397d0518892516e2c40663035401eca05d9bec/pycrdt-0.12.50-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b1d6a3aa808e3996cec15c2ec7d1613c39d872627eb1953877d21720e91b002", size = 957198, upload-time = "2026-03-16T09:38:47.609Z" }, + { url = "https://files.pythonhosted.org/packages/5e/5c/dfd19e979812e455add5942857a08ce2c28547fb68824dda44d4eb83c08b/pycrdt-0.12.50-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8ba83048dc394e8c0d0edf5fdee073eba5d566f372bd3cc24dc8f0f4c24a36d4", size = 1048567, upload-time = "2026-03-16T09:38:49.882Z" }, + { url = "https://files.pythonhosted.org/packages/ac/02/153f511fb0f0dd32d889aede169ea0eda52d62935728b685b6815425ce9d/pycrdt-0.12.50-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:8fbf1f7b6c8200193b602ed3307b526a9cf3db7acb63191632f77d071fb595ec", size = 1122383, upload-time = "2026-03-16T09:38:51.581Z" }, + { url = "https://files.pythonhosted.org/packages/ea/fa/3fcdb4502ced4b7795516acbb12997ec7aaf726187e360494182f533a1a1/pycrdt-0.12.50-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:6776ad64c8a6b270683cdecd1327289587160228401af454f570a9d971eec9a3", size = 1235274, upload-time = "2026-03-16T09:38:53.598Z" }, + { url = "https://files.pythonhosted.org/packages/69/e9/1a50a55b2b2424646e61b648a1bee42f73c1830479cb8095df428bb56b2a/pycrdt-0.12.50-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:f4218a1e568f9b33fd676adc1d3a92fdf4c1c5b6ec3c885f227db7b7fb680b3b", size = 1224841, upload-time = "2026-03-16T09:38:55.528Z" }, + { url = "https://files.pythonhosted.org/packages/a4/62/bd919a4cf7265b4b01c2365820a5423dbe9744880a83a680339a1bf34875/pycrdt-0.12.50-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:cde948e70e3e246638e5cd8b0156c714961fba41cd44374e7c5066e797e8ec3f", size = 1168590, upload-time = "2026-03-16T09:38:57.478Z" }, + { url = "https://files.pythonhosted.org/packages/d0/b3/d0b97dbaf7c60c6e3f6d5c9ae2cd8cca3655d8fa397c41c24c44d92dc8d2/pycrdt-0.12.50-cp314-cp314-win32.whl", hash = "sha256:1d42d7f29c1e8459cd80aefd37595e8c7062817f48c59c5e5568401527718d19", size = 694709, upload-time = "2026-03-16T09:38:59.68Z" }, + { url = "https://files.pythonhosted.org/packages/72/fc/acdb8c238f9f4a6c2757b7c2cfdb39aa3c779ac465e0b6c6862c564e6350/pycrdt-0.12.50-cp314-cp314-win_amd64.whl", hash = "sha256:a4d294295120e33fef32d51e1a7a92eab444d20c07d5bde55a5a75afe58a5d41", size = 747251, upload-time = "2026-03-16T09:39:01.435Z" }, +] + +[[package]] +name = "pycrdt-store" +version = "0.1.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "pycrdt" }, + { name = "sqlite-anyio" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/35/61/dfecafdc0c23f56d5bacc67de620b77a68f86085df21a8007628d6045248/pycrdt_store-0.1.3.tar.gz", hash = "sha256:12a0e263b2c07eb18bbe7203c828b88ba953cb93094ad37d22aeb6c619df2ef0", size = 14847, upload-time = "2025-12-11T13:29:11.454Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b9/2d/85a1b3d6e65048c0553e0d06e21b235610ff4db0ea94cbae1bd34de385d7/pycrdt_store-0.1.3-py3-none-any.whl", hash = "sha256:2e74afc856c162706d178d23d57fd3706accbe79d849e73dd413646a7025afba", size = 11948, upload-time = "2025-12-11T13:29:10.522Z" }, +] + +[[package]] +name = "pycrdt-websocket" +version = "0.16.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "pycrdt" }, + { name = "pycrdt-store" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/4f/91/a412af8792af22e7e67a7424e7b6c64baada4897777fed885a2cb825155d/pycrdt_websocket-0.16.0.tar.gz", hash = "sha256:89d4d830f41028c55cc9877635f73f94f49131ca73ffac7353d0be421150d0fd", size = 23152, upload-time = "2025-06-11T07:15:54.298Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/b7/a1dd4d149fa6279f321bd7dacab66ac31e728fbae175a7d75cf8211b1f30/pycrdt_websocket-0.16.0-py3-none-any.whl", hash = "sha256:4b9ffe47c40867b7e637922680e93471fd801b6e8d6c9f6aa688fd2a17351141", size = 14568, upload-time = "2025-06-11T07:15:52.364Z" }, +] + +[[package]] +name = "pydantic" +version = "2.12.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "annotated-types" }, + { name = "pydantic-core" }, + { name = "typing-extensions" }, + { name = "typing-inspection" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/69/44/36f1a6e523abc58ae5f928898e4aca2e0ea509b5aa6f6f392a5d882be928/pydantic-2.12.5.tar.gz", hash = "sha256:4d351024c75c0f085a9febbb665ce8c0c6ec5d30e903bdb6394b7ede26aebb49", size = 821591, upload-time = "2025-11-26T15:11:46.471Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl", hash = "sha256:e561593fccf61e8a20fc46dfc2dfe075b8be7d0188df33f221ad1f0139180f9d", size = 463580, upload-time = "2025-11-26T15:11:44.605Z" }, +] + +[[package]] +name = "pydantic-core" +version = "2.41.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/71/70/23b021c950c2addd24ec408e9ab05d59b035b39d97cdc1130e1bce647bb6/pydantic_core-2.41.5.tar.gz", hash = "sha256:08daa51ea16ad373ffd5e7606252cc32f07bc72b28284b6bc9c6df804816476e", size = 460952, upload-time = "2025-11-04T13:43:49.098Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/87/06/8806241ff1f70d9939f9af039c6c35f2360cf16e93c2ca76f184e76b1564/pydantic_core-2.41.5-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:941103c9be18ac8daf7b7adca8228f8ed6bb7a1849020f643b3a14d15b1924d9", size = 2120403, upload-time = "2025-11-04T13:40:25.248Z" }, + { url = "https://files.pythonhosted.org/packages/94/02/abfa0e0bda67faa65fef1c84971c7e45928e108fe24333c81f3bfe35d5f5/pydantic_core-2.41.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:112e305c3314f40c93998e567879e887a3160bb8689ef3d2c04b6cc62c33ac34", size = 1896206, upload-time = "2025-11-04T13:40:27.099Z" }, + { url = "https://files.pythonhosted.org/packages/15/df/a4c740c0943e93e6500f9eb23f4ca7ec9bf71b19e608ae5b579678c8d02f/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cbaad15cb0c90aa221d43c00e77bb33c93e8d36e0bf74760cd00e732d10a6a0", size = 1919307, upload-time = "2025-11-04T13:40:29.806Z" }, + { url = "https://files.pythonhosted.org/packages/9a/e3/6324802931ae1d123528988e0e86587c2072ac2e5394b4bc2bc34b61ff6e/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:03ca43e12fab6023fc79d28ca6b39b05f794ad08ec2feccc59a339b02f2b3d33", size = 2063258, upload-time = "2025-11-04T13:40:33.544Z" }, + { url = "https://files.pythonhosted.org/packages/c9/d4/2230d7151d4957dd79c3044ea26346c148c98fbf0ee6ebd41056f2d62ab5/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dc799088c08fa04e43144b164feb0c13f9a0bc40503f8df3e9fde58a3c0c101e", size = 2214917, upload-time = "2025-11-04T13:40:35.479Z" }, + { url = "https://files.pythonhosted.org/packages/e6/9f/eaac5df17a3672fef0081b6c1bb0b82b33ee89aa5cec0d7b05f52fd4a1fa/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:97aeba56665b4c3235a0e52b2c2f5ae9cd071b8a8310ad27bddb3f7fb30e9aa2", size = 2332186, upload-time = "2025-11-04T13:40:37.436Z" }, + { url = "https://files.pythonhosted.org/packages/cf/4e/35a80cae583a37cf15604b44240e45c05e04e86f9cfd766623149297e971/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:406bf18d345822d6c21366031003612b9c77b3e29ffdb0f612367352aab7d586", size = 2073164, upload-time = "2025-11-04T13:40:40.289Z" }, + { url = "https://files.pythonhosted.org/packages/bf/e3/f6e262673c6140dd3305d144d032f7bd5f7497d3871c1428521f19f9efa2/pydantic_core-2.41.5-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b93590ae81f7010dbe380cdeab6f515902ebcbefe0b9327cc4804d74e93ae69d", size = 2179146, upload-time = "2025-11-04T13:40:42.809Z" }, + { url = "https://files.pythonhosted.org/packages/75/c7/20bd7fc05f0c6ea2056a4565c6f36f8968c0924f19b7d97bbfea55780e73/pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:01a3d0ab748ee531f4ea6c3e48ad9dac84ddba4b0d82291f87248f2f9de8d740", size = 2137788, upload-time = "2025-11-04T13:40:44.752Z" }, + { url = "https://files.pythonhosted.org/packages/3a/8d/34318ef985c45196e004bc46c6eab2eda437e744c124ef0dbe1ff2c9d06b/pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:6561e94ba9dacc9c61bce40e2d6bdc3bfaa0259d3ff36ace3b1e6901936d2e3e", size = 2340133, upload-time = "2025-11-04T13:40:46.66Z" }, + { url = "https://files.pythonhosted.org/packages/9c/59/013626bf8c78a5a5d9350d12e7697d3d4de951a75565496abd40ccd46bee/pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:915c3d10f81bec3a74fbd4faebe8391013ba61e5a1a8d48c4455b923bdda7858", size = 2324852, upload-time = "2025-11-04T13:40:48.575Z" }, + { url = "https://files.pythonhosted.org/packages/1a/d9/c248c103856f807ef70c18a4f986693a46a8ffe1602e5d361485da502d20/pydantic_core-2.41.5-cp313-cp313-win32.whl", hash = "sha256:650ae77860b45cfa6e2cdafc42618ceafab3a2d9a3811fcfbd3bbf8ac3c40d36", size = 1994679, upload-time = "2025-11-04T13:40:50.619Z" }, + { url = "https://files.pythonhosted.org/packages/9e/8b/341991b158ddab181cff136acd2552c9f35bd30380422a639c0671e99a91/pydantic_core-2.41.5-cp313-cp313-win_amd64.whl", hash = "sha256:79ec52ec461e99e13791ec6508c722742ad745571f234ea6255bed38c6480f11", size = 2019766, upload-time = "2025-11-04T13:40:52.631Z" }, + { url = "https://files.pythonhosted.org/packages/73/7d/f2f9db34af103bea3e09735bb40b021788a5e834c81eedb541991badf8f5/pydantic_core-2.41.5-cp313-cp313-win_arm64.whl", hash = "sha256:3f84d5c1b4ab906093bdc1ff10484838aca54ef08de4afa9de0f5f14d69639cd", size = 1981005, upload-time = "2025-11-04T13:40:54.734Z" }, + { url = "https://files.pythonhosted.org/packages/ea/28/46b7c5c9635ae96ea0fbb779e271a38129df2550f763937659ee6c5dbc65/pydantic_core-2.41.5-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:3f37a19d7ebcdd20b96485056ba9e8b304e27d9904d233d7b1015db320e51f0a", size = 2119622, upload-time = "2025-11-04T13:40:56.68Z" }, + { url = "https://files.pythonhosted.org/packages/74/1a/145646e5687e8d9a1e8d09acb278c8535ebe9e972e1f162ed338a622f193/pydantic_core-2.41.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1d1d9764366c73f996edd17abb6d9d7649a7eb690006ab6adbda117717099b14", size = 1891725, upload-time = "2025-11-04T13:40:58.807Z" }, + { url = "https://files.pythonhosted.org/packages/23/04/e89c29e267b8060b40dca97bfc64a19b2a3cf99018167ea1677d96368273/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25e1c2af0fce638d5f1988b686f3b3ea8cd7de5f244ca147c777769e798a9cd1", size = 1915040, upload-time = "2025-11-04T13:41:00.853Z" }, + { url = "https://files.pythonhosted.org/packages/84/a3/15a82ac7bd97992a82257f777b3583d3e84bdb06ba6858f745daa2ec8a85/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:506d766a8727beef16b7adaeb8ee6217c64fc813646b424d0804d67c16eddb66", size = 2063691, upload-time = "2025-11-04T13:41:03.504Z" }, + { url = "https://files.pythonhosted.org/packages/74/9b/0046701313c6ef08c0c1cf0e028c67c770a4e1275ca73131563c5f2a310a/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4819fa52133c9aa3c387b3328f25c1facc356491e6135b459f1de698ff64d869", size = 2213897, upload-time = "2025-11-04T13:41:05.804Z" }, + { url = "https://files.pythonhosted.org/packages/8a/cd/6bac76ecd1b27e75a95ca3a9a559c643b3afcd2dd62086d4b7a32a18b169/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2b761d210c9ea91feda40d25b4efe82a1707da2ef62901466a42492c028553a2", size = 2333302, upload-time = "2025-11-04T13:41:07.809Z" }, + { url = "https://files.pythonhosted.org/packages/4c/d2/ef2074dc020dd6e109611a8be4449b98cd25e1b9b8a303c2f0fca2f2bcf7/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22f0fb8c1c583a3b6f24df2470833b40207e907b90c928cc8d3594b76f874375", size = 2064877, upload-time = "2025-11-04T13:41:09.827Z" }, + { url = "https://files.pythonhosted.org/packages/18/66/e9db17a9a763d72f03de903883c057b2592c09509ccfe468187f2a2eef29/pydantic_core-2.41.5-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2782c870e99878c634505236d81e5443092fba820f0373997ff75f90f68cd553", size = 2180680, upload-time = "2025-11-04T13:41:12.379Z" }, + { url = "https://files.pythonhosted.org/packages/d3/9e/3ce66cebb929f3ced22be85d4c2399b8e85b622db77dad36b73c5387f8f8/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:0177272f88ab8312479336e1d777f6b124537d47f2123f89cb37e0accea97f90", size = 2138960, upload-time = "2025-11-04T13:41:14.627Z" }, + { url = "https://files.pythonhosted.org/packages/a6/62/205a998f4327d2079326b01abee48e502ea739d174f0a89295c481a2272e/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:63510af5e38f8955b8ee5687740d6ebf7c2a0886d15a6d65c32814613681bc07", size = 2339102, upload-time = "2025-11-04T13:41:16.868Z" }, + { url = "https://files.pythonhosted.org/packages/3c/0d/f05e79471e889d74d3d88f5bd20d0ed189ad94c2423d81ff8d0000aab4ff/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:e56ba91f47764cc14f1daacd723e3e82d1a89d783f0f5afe9c364b8bb491ccdb", size = 2326039, upload-time = "2025-11-04T13:41:18.934Z" }, + { url = "https://files.pythonhosted.org/packages/ec/e1/e08a6208bb100da7e0c4b288eed624a703f4d129bde2da475721a80cab32/pydantic_core-2.41.5-cp314-cp314-win32.whl", hash = "sha256:aec5cf2fd867b4ff45b9959f8b20ea3993fc93e63c7363fe6851424c8a7e7c23", size = 1995126, upload-time = "2025-11-04T13:41:21.418Z" }, + { url = "https://files.pythonhosted.org/packages/48/5d/56ba7b24e9557f99c9237e29f5c09913c81eeb2f3217e40e922353668092/pydantic_core-2.41.5-cp314-cp314-win_amd64.whl", hash = "sha256:8e7c86f27c585ef37c35e56a96363ab8de4e549a95512445b85c96d3e2f7c1bf", size = 2015489, upload-time = "2025-11-04T13:41:24.076Z" }, + { url = "https://files.pythonhosted.org/packages/4e/bb/f7a190991ec9e3e0ba22e4993d8755bbc4a32925c0b5b42775c03e8148f9/pydantic_core-2.41.5-cp314-cp314-win_arm64.whl", hash = "sha256:e672ba74fbc2dc8eea59fb6d4aed6845e6905fc2a8afe93175d94a83ba2a01a0", size = 1977288, upload-time = "2025-11-04T13:41:26.33Z" }, + { url = "https://files.pythonhosted.org/packages/92/ed/77542d0c51538e32e15afe7899d79efce4b81eee631d99850edc2f5e9349/pydantic_core-2.41.5-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:8566def80554c3faa0e65ac30ab0932b9e3a5cd7f8323764303d468e5c37595a", size = 2120255, upload-time = "2025-11-04T13:41:28.569Z" }, + { url = "https://files.pythonhosted.org/packages/bb/3d/6913dde84d5be21e284439676168b28d8bbba5600d838b9dca99de0fad71/pydantic_core-2.41.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:b80aa5095cd3109962a298ce14110ae16b8c1aece8b72f9dafe81cf597ad80b3", size = 1863760, upload-time = "2025-11-04T13:41:31.055Z" }, + { url = "https://files.pythonhosted.org/packages/5a/f0/e5e6b99d4191da102f2b0eb9687aaa7f5bea5d9964071a84effc3e40f997/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3006c3dd9ba34b0c094c544c6006cc79e87d8612999f1a5d43b769b89181f23c", size = 1878092, upload-time = "2025-11-04T13:41:33.21Z" }, + { url = "https://files.pythonhosted.org/packages/71/48/36fb760642d568925953bcc8116455513d6e34c4beaa37544118c36aba6d/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:72f6c8b11857a856bcfa48c86f5368439f74453563f951e473514579d44aa612", size = 2053385, upload-time = "2025-11-04T13:41:35.508Z" }, + { url = "https://files.pythonhosted.org/packages/20/25/92dc684dd8eb75a234bc1c764b4210cf2646479d54b47bf46061657292a8/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5cb1b2f9742240e4bb26b652a5aeb840aa4b417c7748b6f8387927bc6e45e40d", size = 2218832, upload-time = "2025-11-04T13:41:37.732Z" }, + { url = "https://files.pythonhosted.org/packages/e2/09/f53e0b05023d3e30357d82eb35835d0f6340ca344720a4599cd663dca599/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bd3d54f38609ff308209bd43acea66061494157703364ae40c951f83ba99a1a9", size = 2327585, upload-time = "2025-11-04T13:41:40Z" }, + { url = "https://files.pythonhosted.org/packages/aa/4e/2ae1aa85d6af35a39b236b1b1641de73f5a6ac4d5a7509f77b814885760c/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ff4321e56e879ee8d2a879501c8e469414d948f4aba74a2d4593184eb326660", size = 2041078, upload-time = "2025-11-04T13:41:42.323Z" }, + { url = "https://files.pythonhosted.org/packages/cd/13/2e215f17f0ef326fc72afe94776edb77525142c693767fc347ed6288728d/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d0d2568a8c11bf8225044aa94409e21da0cb09dcdafe9ecd10250b2baad531a9", size = 2173914, upload-time = "2025-11-04T13:41:45.221Z" }, + { url = "https://files.pythonhosted.org/packages/02/7a/f999a6dcbcd0e5660bc348a3991c8915ce6599f4f2c6ac22f01d7a10816c/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:a39455728aabd58ceabb03c90e12f71fd30fa69615760a075b9fec596456ccc3", size = 2129560, upload-time = "2025-11-04T13:41:47.474Z" }, + { url = "https://files.pythonhosted.org/packages/3a/b1/6c990ac65e3b4c079a4fb9f5b05f5b013afa0f4ed6780a3dd236d2cbdc64/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:239edca560d05757817c13dc17c50766136d21f7cd0fac50295499ae24f90fdf", size = 2329244, upload-time = "2025-11-04T13:41:49.992Z" }, + { url = "https://files.pythonhosted.org/packages/d9/02/3c562f3a51afd4d88fff8dffb1771b30cfdfd79befd9883ee094f5b6c0d8/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:2a5e06546e19f24c6a96a129142a75cee553cc018ffee48a460059b1185f4470", size = 2331955, upload-time = "2025-11-04T13:41:54.079Z" }, + { url = "https://files.pythonhosted.org/packages/5c/96/5fb7d8c3c17bc8c62fdb031c47d77a1af698f1d7a406b0f79aaa1338f9ad/pydantic_core-2.41.5-cp314-cp314t-win32.whl", hash = "sha256:b4ececa40ac28afa90871c2cc2b9ffd2ff0bf749380fbdf57d165fd23da353aa", size = 1988906, upload-time = "2025-11-04T13:41:56.606Z" }, + { url = "https://files.pythonhosted.org/packages/22/ed/182129d83032702912c2e2d8bbe33c036f342cc735737064668585dac28f/pydantic_core-2.41.5-cp314-cp314t-win_amd64.whl", hash = "sha256:80aa89cad80b32a912a65332f64a4450ed00966111b6615ca6816153d3585a8c", size = 1981607, upload-time = "2025-11-04T13:41:58.889Z" }, + { url = "https://files.pythonhosted.org/packages/9f/ed/068e41660b832bb0b1aa5b58011dea2a3fe0ba7861ff38c4d4904c1c1a99/pydantic_core-2.41.5-cp314-cp314t-win_arm64.whl", hash = "sha256:35b44f37a3199f771c3eaa53051bc8a70cd7b54f333531c59e29fd4db5d15008", size = 1974769, upload-time = "2025-11-04T13:42:01.186Z" }, +] + +[[package]] +name = "pydantic-settings" +version = "2.13.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pydantic" }, + { name = "python-dotenv" }, + { name = "typing-inspection" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/52/6d/fffca34caecc4a3f97bda81b2098da5e8ab7efc9a66e819074a11955d87e/pydantic_settings-2.13.1.tar.gz", hash = "sha256:b4c11847b15237fb0171e1462bf540e294affb9b86db4d9aa5c01730bdbe4025", size = 223826, upload-time = "2026-02-19T13:45:08.055Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/00/4b/ccc026168948fec4f7555b9164c724cf4125eac006e176541483d2c959be/pydantic_settings-2.13.1-py3-none-any.whl", hash = "sha256:d56fd801823dbeae7f0975e1f8c8e25c258eb75d278ea7abb5d9cebb01b56237", size = 58929, upload-time = "2026-02-19T13:45:06.034Z" }, +] + +[[package]] +name = "pygments" +version = "2.20.0" +source = { registry = "https://pypi.org/simple" } +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/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 = "pyjwt" +version = "2.12.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c2/27/a3b6e5bf6ff856d2509292e95c8f57f0df7017cf5394921fc4e4ef40308a/pyjwt-2.12.1.tar.gz", hash = "sha256:c74a7a2adf861c04d002db713dd85f84beb242228e671280bf709d765b03672b", size = 102564, upload-time = "2026-03-13T19:27:37.25Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e5/7a/8dd906bd22e79e47397a61742927f6747fe93242ef86645ee9092e610244/pyjwt-2.12.1-py3-none-any.whl", hash = "sha256:28ca37c070cad8ba8cd9790cd940535d40274d22f80ab87f3ac6a713e6e8454c", size = 29726, upload-time = "2026-03-13T19:27:35.677Z" }, +] + +[package.optional-dependencies] +crypto = [ + { name = "cryptography" }, +] + +[[package]] +name = "pyparsing" +version = "3.3.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f3/91/9c6ee907786a473bf81c5f53cf703ba0957b23ab84c264080fb5a450416f/pyparsing-3.3.2.tar.gz", hash = "sha256:c777f4d763f140633dcb6d8a3eda953bf7a214dc4eff598413c070bcdc117cbc", size = 6851574, upload-time = "2026-01-21T03:57:59.36Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl", hash = "sha256:850ba148bd908d7e2411587e247a1e4f0327839c40e2e5e6d05a007ecc69911d", size = 122781, upload-time = "2026-01-21T03:57:55.912Z" }, +] + +[[package]] +name = "python-dateutil" +version = "2.9.0.post0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432, upload-time = "2024-03-01T18:36:20.211Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" }, +] + +[[package]] +name = "python-dotenv" +version = "1.2.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/82/ed/0301aeeac3e5353ef3d94b6ec08bbcabd04a72018415dcb29e588514bba8/python_dotenv-1.2.2.tar.gz", hash = "sha256:2c371a91fbd7ba082c2c1dc1f8bf89ca22564a087c2c287cd9b662adde799cf3", size = 50135, upload-time = "2026-03-01T16:00:26.196Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0b/d7/1959b9648791274998a9c3526f6d0ec8fd2233e4d4acce81bbae76b44b2a/python_dotenv-1.2.2-py3-none-any.whl", hash = "sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a", size = 22101, upload-time = "2026-03-01T16:00:25.09Z" }, +] + +[[package]] +name = "python-json-logger" +version = "4.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f7/ff/3cc9165fd44106973cd7ac9facb674a65ed853494592541d339bdc9a30eb/python_json_logger-4.1.0.tar.gz", hash = "sha256:b396b9e3ed782b09ff9d6e4f1683d46c83ad0d35d2e407c09a9ebbf038f88195", size = 17573, upload-time = "2026-03-29T04:39:56.805Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/27/be/0631a861af4d1c875f096c07d34e9a63639560a717130e7a87cbc82b7e3f/python_json_logger-4.1.0-py3-none-any.whl", hash = "sha256:132994765cf75bf44554be9aa49b06ef2345d23661a96720262716438141b6b2", size = 15021, upload-time = "2026-03-29T04:39:55.266Z" }, +] + +[[package]] +name = "python-multipart" +version = "0.0.24" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/8a/45/e23b5dc14ddb9918ae4a625379506b17b6f8fc56ca1d82db62462f59aea6/python_multipart-0.0.24.tar.gz", hash = "sha256:9574c97e1c026e00bc30340ef7c7d76739512ab4dfd428fec8c330fa6a5cc3c8", size = 37695, upload-time = "2026-04-05T20:49:13.829Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a3/73/89930efabd4da63cea44a3f438aeb753d600123570e6d6264e763617a9ce/python_multipart-0.0.24-py3-none-any.whl", hash = "sha256:9b110a98db707df01a53c194f0af075e736a770dc5058089650d70b4a182f950", size = 24420, upload-time = "2026-04-05T20:49:12.555Z" }, +] + +[[package]] +name = "pywin32" +version = "311" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { 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/c9/31/097f2e132c4f16d99a22bfb777e0fd88bd8e1c634304e102f313af69ace5/pywin32-311-cp314-cp314-win32.whl", hash = "sha256:b7a2c10b93f8986666d0c803ee19b5990885872a7de910fc460f9b0c2fbf92ee", size = 8840714, upload-time = "2025-07-14T20:13:32.449Z" }, + { url = "https://files.pythonhosted.org/packages/90/4b/07c77d8ba0e01349358082713400435347df8426208171ce297da32c313d/pywin32-311-cp314-cp314-win_amd64.whl", hash = "sha256:3aca44c046bd2ed8c90de9cb8427f581c479e594e99b5c0bb19b29c10fd6cb87", size = 9656800, upload-time = "2025-07-14T20:13:34.312Z" }, + { url = "https://files.pythonhosted.org/packages/c0/d2/21af5c535501a7233e734b8af901574572da66fcc254cb35d0609c9080dd/pywin32-311-cp314-cp314-win_arm64.whl", hash = "sha256:a508e2d9025764a8270f93111a970e1d0fbfc33f4153b388bb649b7eec4f9b42", size = 8932540, upload-time = "2025-07-14T20:13:36.379Z" }, +] + +[[package]] +name = "pywinpty" +version = "3.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f7/54/37c7370ba91f579235049dc26cd2c5e657d2a943e01820844ffc81f32176/pywinpty-3.0.3.tar.gz", hash = "sha256:523441dc34d231fb361b4b00f8c99d3f16de02f5005fd544a0183112bcc22412", size = 31309, upload-time = "2026-02-04T21:51:09.524Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e5/cb/58d6ed3fd429c96a90ef01ac9a617af10a6d41469219c25e7dc162abbb71/pywinpty-3.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:9c91dbb026050c77bdcef964e63a4f10f01a639113c4d3658332614544c467ab", size = 2112686, upload-time = "2026-02-04T21:52:03.035Z" }, + { url = "https://files.pythonhosted.org/packages/fd/50/724ed5c38c504d4e58a88a072776a1e880d970789deaeb2b9f7bd9a5141a/pywinpty-3.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:fe1f7911805127c94cf51f89ab14096c6f91ffdcacf993d2da6082b2142a2523", size = 234591, upload-time = "2026-02-04T21:52:29.821Z" }, + { url = "https://files.pythonhosted.org/packages/f7/ad/90a110538696b12b39fd8758a06d70ded899308198ad2305ac68e361126e/pywinpty-3.0.3-cp313-cp313t-win_amd64.whl", hash = "sha256:3f07a6cf1c1d470d284e614733c3d0f726d2c85e78508ea10a403140c3c0c18a", size = 2112360, upload-time = "2026-02-04T21:55:33.397Z" }, + { url = "https://files.pythonhosted.org/packages/44/0f/7ffa221757a220402bc79fda44044c3f2cc57338d878ab7d622add6f4581/pywinpty-3.0.3-cp313-cp313t-win_arm64.whl", hash = "sha256:15c7c0b6f8e9d87aabbaff76468dabf6e6121332c40fc1d83548d02a9d6a3759", size = 233107, upload-time = "2026-02-04T21:51:45.455Z" }, + { url = "https://files.pythonhosted.org/packages/28/88/2ff917caff61e55f38bcdb27de06ee30597881b2cae44fbba7627be015c4/pywinpty-3.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:d4b6b7b0fe0cdcd02e956bd57cfe9f4e5a06514eecf3b5ae174da4f951b58be9", size = 2113282, upload-time = "2026-02-04T21:52:08.188Z" }, + { url = "https://files.pythonhosted.org/packages/63/32/40a775343ace542cc43ece3f1d1fce454021521ecac41c4c4573081c2336/pywinpty-3.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:34789d685fc0d547ce0c8a65e5a70e56f77d732fa6e03c8f74fefb8cbb252019", size = 234207, upload-time = "2026-02-04T21:51:58.687Z" }, + { url = "https://files.pythonhosted.org/packages/8d/54/5d5e52f4cb75028104ca6faf36c10f9692389b1986d34471663b4ebebd6d/pywinpty-3.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:0c37e224a47a971d1a6e08649a1714dac4f63c11920780977829ed5c8cadead1", size = 2112910, upload-time = "2026-02-04T21:52:30.976Z" }, + { url = "https://files.pythonhosted.org/packages/0a/44/dcd184824e21d4620b06c7db9fbb15c3ad0a0f1fa2e6de79969fb82647ec/pywinpty-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:c4e9c3dff7d86ba81937438d5819f19f385a39d8f592d4e8af67148ceb4f6ab5", size = 233425, upload-time = "2026-02-04T21:51:56.754Z" }, +] + +[[package]] +name = "pyyaml" +version = "6.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/11/0fd08f8192109f7169db964b5707a2f1e8b745d4e239b784a5a1dd80d1db/pyyaml-6.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8", size = 181669, upload-time = "2025-09-25T21:32:23.673Z" }, + { url = "https://files.pythonhosted.org/packages/b1/16/95309993f1d3748cd644e02e38b75d50cbc0d9561d21f390a76242ce073f/pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1", size = 173252, upload-time = "2025-09-25T21:32:25.149Z" }, + { url = "https://files.pythonhosted.org/packages/50/31/b20f376d3f810b9b2371e72ef5adb33879b25edb7a6d072cb7ca0c486398/pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c", size = 767081, upload-time = "2025-09-25T21:32:26.575Z" }, + { url = "https://files.pythonhosted.org/packages/49/1e/a55ca81e949270d5d4432fbbd19dfea5321eda7c41a849d443dc92fd1ff7/pyyaml-6.0.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5", size = 841159, upload-time = "2025-09-25T21:32:27.727Z" }, + { url = "https://files.pythonhosted.org/packages/74/27/e5b8f34d02d9995b80abcef563ea1f8b56d20134d8f4e5e81733b1feceb2/pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6", size = 801626, upload-time = "2025-09-25T21:32:28.878Z" }, + { url = "https://files.pythonhosted.org/packages/f9/11/ba845c23988798f40e52ba45f34849aa8a1f2d4af4b798588010792ebad6/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6", size = 753613, upload-time = "2025-09-25T21:32:30.178Z" }, + { url = "https://files.pythonhosted.org/packages/3d/e0/7966e1a7bfc0a45bf0a7fb6b98ea03fc9b8d84fa7f2229e9659680b69ee3/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be", size = 794115, upload-time = "2025-09-25T21:32:31.353Z" }, + { url = "https://files.pythonhosted.org/packages/de/94/980b50a6531b3019e45ddeada0626d45fa85cbe22300844a7983285bed3b/pyyaml-6.0.3-cp313-cp313-win32.whl", hash = "sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26", size = 137427, upload-time = "2025-09-25T21:32:32.58Z" }, + { url = "https://files.pythonhosted.org/packages/97/c9/39d5b874e8b28845e4ec2202b5da735d0199dbe5b8fb85f91398814a9a46/pyyaml-6.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c", size = 154090, upload-time = "2025-09-25T21:32:33.659Z" }, + { url = "https://files.pythonhosted.org/packages/73/e8/2bdf3ca2090f68bb3d75b44da7bbc71843b19c9f2b9cb9b0f4ab7a5a4329/pyyaml-6.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb", size = 140246, upload-time = "2025-09-25T21:32:34.663Z" }, + { url = "https://files.pythonhosted.org/packages/9d/8c/f4bd7f6465179953d3ac9bc44ac1a8a3e6122cf8ada906b4f96c60172d43/pyyaml-6.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac", size = 181814, upload-time = "2025-09-25T21:32:35.712Z" }, + { url = "https://files.pythonhosted.org/packages/bd/9c/4d95bb87eb2063d20db7b60faa3840c1b18025517ae857371c4dd55a6b3a/pyyaml-6.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310", size = 173809, upload-time = "2025-09-25T21:32:36.789Z" }, + { url = "https://files.pythonhosted.org/packages/92/b5/47e807c2623074914e29dabd16cbbdd4bf5e9b2db9f8090fa64411fc5382/pyyaml-6.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7", size = 766454, upload-time = "2025-09-25T21:32:37.966Z" }, + { url = "https://files.pythonhosted.org/packages/02/9e/e5e9b168be58564121efb3de6859c452fccde0ab093d8438905899a3a483/pyyaml-6.0.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788", size = 836355, upload-time = "2025-09-25T21:32:39.178Z" }, + { url = "https://files.pythonhosted.org/packages/88/f9/16491d7ed2a919954993e48aa941b200f38040928474c9e85ea9e64222c3/pyyaml-6.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5", size = 794175, upload-time = "2025-09-25T21:32:40.865Z" }, + { url = "https://files.pythonhosted.org/packages/dd/3f/5989debef34dc6397317802b527dbbafb2b4760878a53d4166579111411e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764", size = 755228, upload-time = "2025-09-25T21:32:42.084Z" }, + { url = "https://files.pythonhosted.org/packages/d7/ce/af88a49043cd2e265be63d083fc75b27b6ed062f5f9fd6cdc223ad62f03e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35", size = 789194, upload-time = "2025-09-25T21:32:43.362Z" }, + { url = "https://files.pythonhosted.org/packages/23/20/bb6982b26a40bb43951265ba29d4c246ef0ff59c9fdcdf0ed04e0687de4d/pyyaml-6.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac", size = 156429, upload-time = "2025-09-25T21:32:57.844Z" }, + { url = "https://files.pythonhosted.org/packages/f4/f4/a4541072bb9422c8a883ab55255f918fa378ecf083f5b85e87fc2b4eda1b/pyyaml-6.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3", size = 143912, upload-time = "2025-09-25T21:32:59.247Z" }, + { url = "https://files.pythonhosted.org/packages/7c/f9/07dd09ae774e4616edf6cda684ee78f97777bdd15847253637a6f052a62f/pyyaml-6.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3", size = 189108, upload-time = "2025-09-25T21:32:44.377Z" }, + { url = "https://files.pythonhosted.org/packages/4e/78/8d08c9fb7ce09ad8c38ad533c1191cf27f7ae1effe5bb9400a46d9437fcf/pyyaml-6.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba", size = 183641, upload-time = "2025-09-25T21:32:45.407Z" }, + { url = "https://files.pythonhosted.org/packages/7b/5b/3babb19104a46945cf816d047db2788bcaf8c94527a805610b0289a01c6b/pyyaml-6.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c", size = 831901, upload-time = "2025-09-25T21:32:48.83Z" }, + { url = "https://files.pythonhosted.org/packages/8b/cc/dff0684d8dc44da4d22a13f35f073d558c268780ce3c6ba1b87055bb0b87/pyyaml-6.0.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702", size = 861132, upload-time = "2025-09-25T21:32:50.149Z" }, + { url = "https://files.pythonhosted.org/packages/b1/5e/f77dc6b9036943e285ba76b49e118d9ea929885becb0a29ba8a7c75e29fe/pyyaml-6.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c", size = 839261, upload-time = "2025-09-25T21:32:51.808Z" }, + { url = "https://files.pythonhosted.org/packages/ce/88/a9db1376aa2a228197c58b37302f284b5617f56a5d959fd1763fb1675ce6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065", size = 805272, upload-time = "2025-09-25T21:32:52.941Z" }, + { url = "https://files.pythonhosted.org/packages/da/92/1446574745d74df0c92e6aa4a7b0b3130706a4142b2d1a5869f2eaa423c6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65", size = 829923, upload-time = "2025-09-25T21:32:54.537Z" }, + { url = "https://files.pythonhosted.org/packages/f0/7a/1c7270340330e575b92f397352af856a8c06f230aa3e76f86b39d01b416a/pyyaml-6.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9", size = 174062, upload-time = "2025-09-25T21:32:55.767Z" }, + { url = "https://files.pythonhosted.org/packages/f1/12/de94a39c2ef588c7e6455cfbe7343d3b2dc9d6b6b2f40c4c6565744c873d/pyyaml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b", size = 149341, upload-time = "2025-09-25T21:32:56.828Z" }, +] + +[[package]] +name = "pyzmq" +version = "27.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cffi", marker = "implementation_name == 'pypy'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/04/0b/3c9baedbdf613ecaa7aa07027780b8867f57b6293b6ee50de316c9f3222b/pyzmq-27.1.0.tar.gz", hash = "sha256:ac0765e3d44455adb6ddbf4417dcce460fc40a05978c08efdf2948072f6db540", size = 281750, upload-time = "2025-09-08T23:10:18.157Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/92/e7/038aab64a946d535901103da16b953c8c9cc9c961dadcbf3609ed6428d23/pyzmq-27.1.0-cp312-abi3-macosx_10_15_universal2.whl", hash = "sha256:452631b640340c928fa343801b0d07eb0c3789a5ffa843f6e1a9cee0ba4eb4fc", size = 1306279, upload-time = "2025-09-08T23:08:03.807Z" }, + { url = "https://files.pythonhosted.org/packages/e8/5e/c3c49fdd0f535ef45eefcc16934648e9e59dace4a37ee88fc53f6cd8e641/pyzmq-27.1.0-cp312-abi3-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:1c179799b118e554b66da67d88ed66cd37a169f1f23b5d9f0a231b4e8d44a113", size = 895645, upload-time = "2025-09-08T23:08:05.301Z" }, + { url = "https://files.pythonhosted.org/packages/f8/e5/b0b2504cb4e903a74dcf1ebae157f9e20ebb6ea76095f6cfffea28c42ecd/pyzmq-27.1.0-cp312-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3837439b7f99e60312f0c926a6ad437b067356dc2bc2ec96eb395fd0fe804233", size = 652574, upload-time = "2025-09-08T23:08:06.828Z" }, + { url = "https://files.pythonhosted.org/packages/f8/9b/c108cdb55560eaf253f0cbdb61b29971e9fb34d9c3499b0e96e4e60ed8a5/pyzmq-27.1.0-cp312-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:43ad9a73e3da1fab5b0e7e13402f0b2fb934ae1c876c51d0afff0e7c052eca31", size = 840995, upload-time = "2025-09-08T23:08:08.396Z" }, + { url = "https://files.pythonhosted.org/packages/c2/bb/b79798ca177b9eb0825b4c9998c6af8cd2a7f15a6a1a4272c1d1a21d382f/pyzmq-27.1.0-cp312-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:0de3028d69d4cdc475bfe47a6128eb38d8bc0e8f4d69646adfbcd840facbac28", size = 1642070, upload-time = "2025-09-08T23:08:09.989Z" }, + { url = "https://files.pythonhosted.org/packages/9c/80/2df2e7977c4ede24c79ae39dcef3899bfc5f34d1ca7a5b24f182c9b7a9ca/pyzmq-27.1.0-cp312-abi3-musllinux_1_2_i686.whl", hash = "sha256:cf44a7763aea9298c0aa7dbf859f87ed7012de8bda0f3977b6fb1d96745df856", size = 2021121, upload-time = "2025-09-08T23:08:11.907Z" }, + { url = "https://files.pythonhosted.org/packages/46/bd/2d45ad24f5f5ae7e8d01525eb76786fa7557136555cac7d929880519e33a/pyzmq-27.1.0-cp312-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:f30f395a9e6fbca195400ce833c731e7b64c3919aa481af4d88c3759e0cb7496", size = 1878550, upload-time = "2025-09-08T23:08:13.513Z" }, + { url = "https://files.pythonhosted.org/packages/e6/2f/104c0a3c778d7c2ab8190e9db4f62f0b6957b53c9d87db77c284b69f33ea/pyzmq-27.1.0-cp312-abi3-win32.whl", hash = "sha256:250e5436a4ba13885494412b3da5d518cd0d3a278a1ae640e113c073a5f88edd", size = 559184, upload-time = "2025-09-08T23:08:15.163Z" }, + { url = "https://files.pythonhosted.org/packages/fc/7f/a21b20d577e4100c6a41795842028235998a643b1ad406a6d4163ea8f53e/pyzmq-27.1.0-cp312-abi3-win_amd64.whl", hash = "sha256:9ce490cf1d2ca2ad84733aa1d69ce6855372cb5ce9223802450c9b2a7cba0ccf", size = 619480, upload-time = "2025-09-08T23:08:17.192Z" }, + { url = "https://files.pythonhosted.org/packages/78/c2/c012beae5f76b72f007a9e91ee9401cb88c51d0f83c6257a03e785c81cc2/pyzmq-27.1.0-cp312-abi3-win_arm64.whl", hash = "sha256:75a2f36223f0d535a0c919e23615fc85a1e23b71f40c7eb43d7b1dedb4d8f15f", size = 552993, upload-time = "2025-09-08T23:08:18.926Z" }, + { url = "https://files.pythonhosted.org/packages/60/cb/84a13459c51da6cec1b7b1dc1a47e6db6da50b77ad7fd9c145842750a011/pyzmq-27.1.0-cp313-cp313-android_24_arm64_v8a.whl", hash = "sha256:93ad4b0855a664229559e45c8d23797ceac03183c7b6f5b4428152a6b06684a5", size = 1122436, upload-time = "2025-09-08T23:08:20.801Z" }, + { url = "https://files.pythonhosted.org/packages/dc/b6/94414759a69a26c3dd674570a81813c46a078767d931a6c70ad29fc585cb/pyzmq-27.1.0-cp313-cp313-android_24_x86_64.whl", hash = "sha256:fbb4f2400bfda24f12f009cba62ad5734148569ff4949b1b6ec3b519444342e6", size = 1156301, upload-time = "2025-09-08T23:08:22.47Z" }, + { url = "https://files.pythonhosted.org/packages/a5/ad/15906493fd40c316377fd8a8f6b1f93104f97a752667763c9b9c1b71d42d/pyzmq-27.1.0-cp313-cp313t-macosx_10_15_universal2.whl", hash = "sha256:e343d067f7b151cfe4eb3bb796a7752c9d369eed007b91231e817071d2c2fec7", size = 1341197, upload-time = "2025-09-08T23:08:24.286Z" }, + { url = "https://files.pythonhosted.org/packages/14/1d/d343f3ce13db53a54cb8946594e567410b2125394dafcc0268d8dda027e0/pyzmq-27.1.0-cp313-cp313t-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:08363b2011dec81c354d694bdecaef4770e0ae96b9afea70b3f47b973655cc05", size = 897275, upload-time = "2025-09-08T23:08:26.063Z" }, + { url = "https://files.pythonhosted.org/packages/69/2d/d83dd6d7ca929a2fc67d2c3005415cdf322af7751d773524809f9e585129/pyzmq-27.1.0-cp313-cp313t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d54530c8c8b5b8ddb3318f481297441af102517602b569146185fa10b63f4fa9", size = 660469, upload-time = "2025-09-08T23:08:27.623Z" }, + { url = "https://files.pythonhosted.org/packages/3e/cd/9822a7af117f4bc0f1952dbe9ef8358eb50a24928efd5edf54210b850259/pyzmq-27.1.0-cp313-cp313t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6f3afa12c392f0a44a2414056d730eebc33ec0926aae92b5ad5cf26ebb6cc128", size = 847961, upload-time = "2025-09-08T23:08:29.672Z" }, + { url = "https://files.pythonhosted.org/packages/9a/12/f003e824a19ed73be15542f172fd0ec4ad0b60cf37436652c93b9df7c585/pyzmq-27.1.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:c65047adafe573ff023b3187bb93faa583151627bc9c51fc4fb2c561ed689d39", size = 1650282, upload-time = "2025-09-08T23:08:31.349Z" }, + { url = "https://files.pythonhosted.org/packages/d5/4a/e82d788ed58e9a23995cee70dbc20c9aded3d13a92d30d57ec2291f1e8a3/pyzmq-27.1.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:90e6e9441c946a8b0a667356f7078d96411391a3b8f80980315455574177ec97", size = 2024468, upload-time = "2025-09-08T23:08:33.543Z" }, + { url = "https://files.pythonhosted.org/packages/d9/94/2da0a60841f757481e402b34bf4c8bf57fa54a5466b965de791b1e6f747d/pyzmq-27.1.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:add071b2d25f84e8189aaf0882d39a285b42fa3853016ebab234a5e78c7a43db", size = 1885394, upload-time = "2025-09-08T23:08:35.51Z" }, + { url = "https://files.pythonhosted.org/packages/4f/6f/55c10e2e49ad52d080dc24e37adb215e5b0d64990b57598abc2e3f01725b/pyzmq-27.1.0-cp313-cp313t-win32.whl", hash = "sha256:7ccc0700cfdf7bd487bea8d850ec38f204478681ea02a582a8da8171b7f90a1c", size = 574964, upload-time = "2025-09-08T23:08:37.178Z" }, + { url = "https://files.pythonhosted.org/packages/87/4d/2534970ba63dd7c522d8ca80fb92777f362c0f321900667c615e2067cb29/pyzmq-27.1.0-cp313-cp313t-win_amd64.whl", hash = "sha256:8085a9fba668216b9b4323be338ee5437a235fe275b9d1610e422ccc279733e2", size = 641029, upload-time = "2025-09-08T23:08:40.595Z" }, + { url = "https://files.pythonhosted.org/packages/f6/fa/f8aea7a28b0641f31d40dea42d7ef003fded31e184ef47db696bc74cd610/pyzmq-27.1.0-cp313-cp313t-win_arm64.whl", hash = "sha256:6bb54ca21bcfe361e445256c15eedf083f153811c37be87e0514934d6913061e", size = 561541, upload-time = "2025-09-08T23:08:42.668Z" }, + { url = "https://files.pythonhosted.org/packages/87/45/19efbb3000956e82d0331bafca5d9ac19ea2857722fa2caacefb6042f39d/pyzmq-27.1.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:ce980af330231615756acd5154f29813d553ea555485ae712c491cd483df6b7a", size = 1341197, upload-time = "2025-09-08T23:08:44.973Z" }, + { url = "https://files.pythonhosted.org/packages/48/43/d72ccdbf0d73d1343936296665826350cb1e825f92f2db9db3e61c2162a2/pyzmq-27.1.0-cp314-cp314t-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:1779be8c549e54a1c38f805e56d2a2e5c009d26de10921d7d51cfd1c8d4632ea", size = 897175, upload-time = "2025-09-08T23:08:46.601Z" }, + { url = "https://files.pythonhosted.org/packages/2f/2e/a483f73a10b65a9ef0161e817321d39a770b2acf8bcf3004a28d90d14a94/pyzmq-27.1.0-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7200bb0f03345515df50d99d3db206a0a6bee1955fbb8c453c76f5bf0e08fb96", size = 660427, upload-time = "2025-09-08T23:08:48.187Z" }, + { url = "https://files.pythonhosted.org/packages/f5/d2/5f36552c2d3e5685abe60dfa56f91169f7a2d99bbaf67c5271022ab40863/pyzmq-27.1.0-cp314-cp314t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:01c0e07d558b06a60773744ea6251f769cd79a41a97d11b8bf4ab8f034b0424d", size = 847929, upload-time = "2025-09-08T23:08:49.76Z" }, + { url = "https://files.pythonhosted.org/packages/c4/2a/404b331f2b7bf3198e9945f75c4c521f0c6a3a23b51f7a4a401b94a13833/pyzmq-27.1.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:80d834abee71f65253c91540445d37c4c561e293ba6e741b992f20a105d69146", size = 1650193, upload-time = "2025-09-08T23:08:51.7Z" }, + { url = "https://files.pythonhosted.org/packages/1c/0b/f4107e33f62a5acf60e3ded67ed33d79b4ce18de432625ce2fc5093d6388/pyzmq-27.1.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:544b4e3b7198dde4a62b8ff6685e9802a9a1ebf47e77478a5eb88eca2a82f2fd", size = 2024388, upload-time = "2025-09-08T23:08:53.393Z" }, + { url = "https://files.pythonhosted.org/packages/0d/01/add31fe76512642fd6e40e3a3bd21f4b47e242c8ba33efb6809e37076d9b/pyzmq-27.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:cedc4c68178e59a4046f97eca31b148ddcf51e88677de1ef4e78cf06c5376c9a", size = 1885316, upload-time = "2025-09-08T23:08:55.702Z" }, + { url = "https://files.pythonhosted.org/packages/c4/59/a5f38970f9bf07cee96128de79590bb354917914a9be11272cfc7ff26af0/pyzmq-27.1.0-cp314-cp314t-win32.whl", hash = "sha256:1f0b2a577fd770aa6f053211a55d1c47901f4d537389a034c690291485e5fe92", size = 587472, upload-time = "2025-09-08T23:08:58.18Z" }, + { url = "https://files.pythonhosted.org/packages/70/d8/78b1bad170f93fcf5e3536e70e8fadac55030002275c9a29e8f5719185de/pyzmq-27.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:19c9468ae0437f8074af379e986c5d3d7d7bfe033506af442e8c879732bedbe0", size = 661401, upload-time = "2025-09-08T23:08:59.802Z" }, + { url = "https://files.pythonhosted.org/packages/81/d6/4bfbb40c9a0b42fc53c7cf442f6385db70b40f74a783130c5d0a5aa62228/pyzmq-27.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:dc5dbf68a7857b59473f7df42650c621d7e8923fb03fa74a526890f4d33cc4d7", size = 575170, upload-time = "2025-09-08T23:09:01.418Z" }, +] + +[[package]] +name = "referencing" +version = "0.37.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "rpds-py" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/22/f5/df4e9027acead3ecc63e50fe1e36aca1523e1719559c499951bb4b53188f/referencing-0.37.0.tar.gz", hash = "sha256:44aefc3142c5b842538163acb373e24cce6632bd54bdb01b21ad5863489f50d8", size = 78036, upload-time = "2025-10-13T15:30:48.871Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2c/58/ca301544e1fa93ed4f80d724bf5b194f6e4b945841c5bfd555878eea9fcb/referencing-0.37.0-py3-none-any.whl", hash = "sha256:381329a9f99628c9069361716891d34ad94af76e461dcb0335825aecc7692231", size = 26766, upload-time = "2025-10-13T15:30:47.625Z" }, +] + +[[package]] +name = "requests" +version = "2.33.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "charset-normalizer" }, + { name = "idna" }, + { name = "urllib3" }, +] +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]] +name = "rfc3339-validator" +version = "0.1.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/28/ea/a9387748e2d111c3c2b275ba970b735e04e15cdb1eb30693b6b5708c4dbd/rfc3339_validator-0.1.4.tar.gz", hash = "sha256:138a2abdf93304ad60530167e51d2dfb9549521a836871b88d7f4695d0022f6b", size = 5513, upload-time = "2021-05-12T16:37:54.178Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7b/44/4e421b96b67b2daff264473f7465db72fbdf36a07e05494f50300cc7b0c6/rfc3339_validator-0.1.4-py2.py3-none-any.whl", hash = "sha256:24f6ec1eda14ef823da9e36ec7113124b39c04d50a4d3d3a3c2859577e7791fa", size = 3490, upload-time = "2021-05-12T16:37:52.536Z" }, +] + +[[package]] +name = "rfc3986-validator" +version = "0.1.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/da/88/f270de456dd7d11dcc808abfa291ecdd3f45ff44e3b549ffa01b126464d0/rfc3986_validator-0.1.1.tar.gz", hash = "sha256:3d44bde7921b3b9ec3ae4e3adca370438eccebc676456449b145d533b240d055", size = 6760, upload-time = "2019-10-28T16:00:19.144Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9e/51/17023c0f8f1869d8806b979a2bffa3f861f26a3f1a66b094288323fba52f/rfc3986_validator-0.1.1-py2.py3-none-any.whl", hash = "sha256:2f235c432ef459970b4306369336b9d5dbdda31b510ca1e327636e01f528bfa9", size = 4242, upload-time = "2019-10-28T16:00:13.976Z" }, +] + +[[package]] +name = "rfc3987-syntax" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "lark" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/2c/06/37c1a5557acf449e8e406a830a05bf885ac47d33270aec454ef78675008d/rfc3987_syntax-1.1.0.tar.gz", hash = "sha256:717a62cbf33cffdd16dfa3a497d81ce48a660ea691b1ddd7be710c22f00b4a0d", size = 14239, upload-time = "2025-07-18T01:05:05.015Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/71/44ce230e1b7fadd372515a97e32a83011f906ddded8d03e3c6aafbdedbb7/rfc3987_syntax-1.1.0-py3-none-any.whl", hash = "sha256:6c3d97604e4c5ce9f714898e05401a0445a641cfa276432b0a648c80856f6a3f", size = 8046, upload-time = "2025-07-18T01:05:03.843Z" }, +] + +[[package]] +name = "rich" +version = "14.3.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markdown-it-py" }, + { name = "pygments" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b3/c6/f3b320c27991c46f43ee9d856302c70dc2d0fb2dba4842ff739d5f46b393/rich-14.3.3.tar.gz", hash = "sha256:b8daa0b9e4eef54dd8cf7c86c03713f53241884e814f4e2f5fb342fe520f639b", size = 230582, upload-time = "2026-02-19T17:23:12.474Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/14/25/b208c5683343959b670dc001595f2f3737e051da617f66c31f7c4fa93abc/rich-14.3.3-py3-none-any.whl", hash = "sha256:793431c1f8619afa7d3b52b2cdec859562b950ea0d4b6b505397612db8d5362d", size = 310458, upload-time = "2026-02-19T17:23:13.732Z" }, +] + +[[package]] +name = "rpds-py" +version = "0.30.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/20/af/3f2f423103f1113b36230496629986e0ef7e199d2aa8392452b484b38ced/rpds_py-0.30.0.tar.gz", hash = "sha256:dd8ff7cf90014af0c0f787eea34794ebf6415242ee1d6fa91eaba725cc441e84", size = 69469, upload-time = "2025-11-30T20:24:38.837Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ed/dc/d61221eb88ff410de3c49143407f6f3147acf2538c86f2ab7ce65ae7d5f9/rpds_py-0.30.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:f83424d738204d9770830d35290ff3273fbb02b41f919870479fab14b9d303b2", size = 374887, upload-time = "2025-11-30T20:22:41.812Z" }, + { url = "https://files.pythonhosted.org/packages/fd/32/55fb50ae104061dbc564ef15cc43c013dc4a9f4527a1f4d99baddf56fe5f/rpds_py-0.30.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e7536cd91353c5273434b4e003cbda89034d67e7710eab8761fd918ec6c69cf8", size = 358904, upload-time = "2025-11-30T20:22:43.479Z" }, + { url = "https://files.pythonhosted.org/packages/58/70/faed8186300e3b9bdd138d0273109784eea2396c68458ed580f885dfe7ad/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2771c6c15973347f50fece41fc447c054b7ac2ae0502388ce3b6738cd366e3d4", size = 389945, upload-time = "2025-11-30T20:22:44.819Z" }, + { url = "https://files.pythonhosted.org/packages/bd/a8/073cac3ed2c6387df38f71296d002ab43496a96b92c823e76f46b8af0543/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0a59119fc6e3f460315fe9d08149f8102aa322299deaa5cab5b40092345c2136", size = 407783, upload-time = "2025-11-30T20:22:46.103Z" }, + { url = "https://files.pythonhosted.org/packages/77/57/5999eb8c58671f1c11eba084115e77a8899d6e694d2a18f69f0ba471ec8b/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:76fec018282b4ead0364022e3c54b60bf368b9d926877957a8624b58419169b7", size = 515021, upload-time = "2025-11-30T20:22:47.458Z" }, + { url = "https://files.pythonhosted.org/packages/e0/af/5ab4833eadc36c0a8ed2bc5c0de0493c04f6c06de223170bd0798ff98ced/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:692bef75a5525db97318e8cd061542b5a79812d711ea03dbc1f6f8dbb0c5f0d2", size = 414589, upload-time = "2025-11-30T20:22:48.872Z" }, + { url = "https://files.pythonhosted.org/packages/b7/de/f7192e12b21b9e9a68a6d0f249b4af3fdcdff8418be0767a627564afa1f1/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9027da1ce107104c50c81383cae773ef5c24d296dd11c99e2629dbd7967a20c6", size = 394025, upload-time = "2025-11-30T20:22:50.196Z" }, + { url = "https://files.pythonhosted.org/packages/91/c4/fc70cd0249496493500e7cc2de87504f5aa6509de1e88623431fec76d4b6/rpds_py-0.30.0-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:9cf69cdda1f5968a30a359aba2f7f9aa648a9ce4b580d6826437f2b291cfc86e", size = 408895, upload-time = "2025-11-30T20:22:51.87Z" }, + { url = "https://files.pythonhosted.org/packages/58/95/d9275b05ab96556fefff73a385813eb66032e4c99f411d0795372d9abcea/rpds_py-0.30.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a4796a717bf12b9da9d3ad002519a86063dcac8988b030e405704ef7d74d2d9d", size = 422799, upload-time = "2025-11-30T20:22:53.341Z" }, + { url = "https://files.pythonhosted.org/packages/06/c1/3088fc04b6624eb12a57eb814f0d4997a44b0d208d6cace713033ff1a6ba/rpds_py-0.30.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5d4c2aa7c50ad4728a094ebd5eb46c452e9cb7edbfdb18f9e1221f597a73e1e7", size = 572731, upload-time = "2025-11-30T20:22:54.778Z" }, + { url = "https://files.pythonhosted.org/packages/d8/42/c612a833183b39774e8ac8fecae81263a68b9583ee343db33ab571a7ce55/rpds_py-0.30.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ba81a9203d07805435eb06f536d95a266c21e5b2dfbf6517748ca40c98d19e31", size = 599027, upload-time = "2025-11-30T20:22:56.212Z" }, + { url = "https://files.pythonhosted.org/packages/5f/60/525a50f45b01d70005403ae0e25f43c0384369ad24ffe46e8d9068b50086/rpds_py-0.30.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:945dccface01af02675628334f7cf49c2af4c1c904748efc5cf7bbdf0b579f95", size = 563020, upload-time = "2025-11-30T20:22:58.2Z" }, + { url = "https://files.pythonhosted.org/packages/0b/5d/47c4655e9bcd5ca907148535c10e7d489044243cc9941c16ed7cd53be91d/rpds_py-0.30.0-cp313-cp313-win32.whl", hash = "sha256:b40fb160a2db369a194cb27943582b38f79fc4887291417685f3ad693c5a1d5d", size = 223139, upload-time = "2025-11-30T20:23:00.209Z" }, + { url = "https://files.pythonhosted.org/packages/f2/e1/485132437d20aa4d3e1d8b3fb5a5e65aa8139f1e097080c2a8443201742c/rpds_py-0.30.0-cp313-cp313-win_amd64.whl", hash = "sha256:806f36b1b605e2d6a72716f321f20036b9489d29c51c91f4dd29a3e3afb73b15", size = 240224, upload-time = "2025-11-30T20:23:02.008Z" }, + { url = "https://files.pythonhosted.org/packages/24/95/ffd128ed1146a153d928617b0ef673960130be0009c77d8fbf0abe306713/rpds_py-0.30.0-cp313-cp313-win_arm64.whl", hash = "sha256:d96c2086587c7c30d44f31f42eae4eac89b60dabbac18c7669be3700f13c3ce1", size = 230645, upload-time = "2025-11-30T20:23:03.43Z" }, + { url = "https://files.pythonhosted.org/packages/ff/1b/b10de890a0def2a319a2626334a7f0ae388215eb60914dbac8a3bae54435/rpds_py-0.30.0-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:eb0b93f2e5c2189ee831ee43f156ed34e2a89a78a66b98cadad955972548be5a", size = 364443, upload-time = "2025-11-30T20:23:04.878Z" }, + { url = "https://files.pythonhosted.org/packages/0d/bf/27e39f5971dc4f305a4fb9c672ca06f290f7c4e261c568f3dea16a410d47/rpds_py-0.30.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:922e10f31f303c7c920da8981051ff6d8c1a56207dbdf330d9047f6d30b70e5e", size = 353375, upload-time = "2025-11-30T20:23:06.342Z" }, + { url = "https://files.pythonhosted.org/packages/40/58/442ada3bba6e8e6615fc00483135c14a7538d2ffac30e2d933ccf6852232/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cdc62c8286ba9bf7f47befdcea13ea0e26bf294bda99758fd90535cbaf408000", size = 383850, upload-time = "2025-11-30T20:23:07.825Z" }, + { url = "https://files.pythonhosted.org/packages/14/14/f59b0127409a33c6ef6f5c1ebd5ad8e32d7861c9c7adfa9a624fc3889f6c/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:47f9a91efc418b54fb8190a6b4aa7813a23fb79c51f4bb84e418f5476c38b8db", size = 392812, upload-time = "2025-11-30T20:23:09.228Z" }, + { url = "https://files.pythonhosted.org/packages/b3/66/e0be3e162ac299b3a22527e8913767d869e6cc75c46bd844aa43fb81ab62/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1f3587eb9b17f3789ad50824084fa6f81921bbf9a795826570bda82cb3ed91f2", size = 517841, upload-time = "2025-11-30T20:23:11.186Z" }, + { url = "https://files.pythonhosted.org/packages/3d/55/fa3b9cf31d0c963ecf1ba777f7cf4b2a2c976795ac430d24a1f43d25a6ba/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:39c02563fc592411c2c61d26b6c5fe1e51eaa44a75aa2c8735ca88b0d9599daa", size = 408149, upload-time = "2025-11-30T20:23:12.864Z" }, + { url = "https://files.pythonhosted.org/packages/60/ca/780cf3b1a32b18c0f05c441958d3758f02544f1d613abf9488cd78876378/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51a1234d8febafdfd33a42d97da7a43f5dcb120c1060e352a3fbc0c6d36e2083", size = 383843, upload-time = "2025-11-30T20:23:14.638Z" }, + { url = "https://files.pythonhosted.org/packages/82/86/d5f2e04f2aa6247c613da0c1dd87fcd08fa17107e858193566048a1e2f0a/rpds_py-0.30.0-cp313-cp313t-manylinux_2_31_riscv64.whl", hash = "sha256:eb2c4071ab598733724c08221091e8d80e89064cd472819285a9ab0f24bcedb9", size = 396507, upload-time = "2025-11-30T20:23:16.105Z" }, + { url = "https://files.pythonhosted.org/packages/4b/9a/453255d2f769fe44e07ea9785c8347edaf867f7026872e76c1ad9f7bed92/rpds_py-0.30.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6bdfdb946967d816e6adf9a3d8201bfad269c67efe6cefd7093ef959683c8de0", size = 414949, upload-time = "2025-11-30T20:23:17.539Z" }, + { url = "https://files.pythonhosted.org/packages/a3/31/622a86cdc0c45d6df0e9ccb6becdba5074735e7033c20e401a6d9d0e2ca0/rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:c77afbd5f5250bf27bf516c7c4a016813eb2d3e116139aed0096940c5982da94", size = 565790, upload-time = "2025-11-30T20:23:19.029Z" }, + { url = "https://files.pythonhosted.org/packages/1c/5d/15bbf0fb4a3f58a3b1c67855ec1efcc4ceaef4e86644665fff03e1b66d8d/rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:61046904275472a76c8c90c9ccee9013d70a6d0f73eecefd38c1ae7c39045a08", size = 590217, upload-time = "2025-11-30T20:23:20.885Z" }, + { url = "https://files.pythonhosted.org/packages/6d/61/21b8c41f68e60c8cc3b2e25644f0e3681926020f11d06ab0b78e3c6bbff1/rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4c5f36a861bc4b7da6516dbdf302c55313afa09b81931e8280361a4f6c9a2d27", size = 555806, upload-time = "2025-11-30T20:23:22.488Z" }, + { url = "https://files.pythonhosted.org/packages/f9/39/7e067bb06c31de48de3eb200f9fc7c58982a4d3db44b07e73963e10d3be9/rpds_py-0.30.0-cp313-cp313t-win32.whl", hash = "sha256:3d4a69de7a3e50ffc214ae16d79d8fbb0922972da0356dcf4d0fdca2878559c6", size = 211341, upload-time = "2025-11-30T20:23:24.449Z" }, + { url = "https://files.pythonhosted.org/packages/0a/4d/222ef0b46443cf4cf46764d9c630f3fe4abaa7245be9417e56e9f52b8f65/rpds_py-0.30.0-cp313-cp313t-win_amd64.whl", hash = "sha256:f14fc5df50a716f7ece6a80b6c78bb35ea2ca47c499e422aa4463455dd96d56d", size = 225768, upload-time = "2025-11-30T20:23:25.908Z" }, + { url = "https://files.pythonhosted.org/packages/86/81/dad16382ebbd3d0e0328776d8fd7ca94220e4fa0798d1dc5e7da48cb3201/rpds_py-0.30.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:68f19c879420aa08f61203801423f6cd5ac5f0ac4ac82a2368a9fcd6a9a075e0", size = 362099, upload-time = "2025-11-30T20:23:27.316Z" }, + { url = "https://files.pythonhosted.org/packages/2b/60/19f7884db5d5603edf3c6bce35408f45ad3e97e10007df0e17dd57af18f8/rpds_py-0.30.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ec7c4490c672c1a0389d319b3a9cfcd098dcdc4783991553c332a15acf7249be", size = 353192, upload-time = "2025-11-30T20:23:29.151Z" }, + { url = "https://files.pythonhosted.org/packages/bf/c4/76eb0e1e72d1a9c4703c69607cec123c29028bff28ce41588792417098ac/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f251c812357a3fed308d684a5079ddfb9d933860fc6de89f2b7ab00da481e65f", size = 384080, upload-time = "2025-11-30T20:23:30.785Z" }, + { url = "https://files.pythonhosted.org/packages/72/87/87ea665e92f3298d1b26d78814721dc39ed8d2c74b86e83348d6b48a6f31/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac98b175585ecf4c0348fd7b29c3864bda53b805c773cbf7bfdaffc8070c976f", size = 394841, upload-time = "2025-11-30T20:23:32.209Z" }, + { url = "https://files.pythonhosted.org/packages/77/ad/7783a89ca0587c15dcbf139b4a8364a872a25f861bdb88ed99f9b0dec985/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3e62880792319dbeb7eb866547f2e35973289e7d5696c6e295476448f5b63c87", size = 516670, upload-time = "2025-11-30T20:23:33.742Z" }, + { url = "https://files.pythonhosted.org/packages/5b/3c/2882bdac942bd2172f3da574eab16f309ae10a3925644e969536553cb4ee/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4e7fc54e0900ab35d041b0601431b0a0eb495f0851a0639b6ef90f7741b39a18", size = 408005, upload-time = "2025-11-30T20:23:35.253Z" }, + { url = "https://files.pythonhosted.org/packages/ce/81/9a91c0111ce1758c92516a3e44776920b579d9a7c09b2b06b642d4de3f0f/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47e77dc9822d3ad616c3d5759ea5631a75e5809d5a28707744ef79d7a1bcfcad", size = 382112, upload-time = "2025-11-30T20:23:36.842Z" }, + { url = "https://files.pythonhosted.org/packages/cf/8e/1da49d4a107027e5fbc64daeab96a0706361a2918da10cb41769244b805d/rpds_py-0.30.0-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:b4dc1a6ff022ff85ecafef7979a2c6eb423430e05f1165d6688234e62ba99a07", size = 399049, upload-time = "2025-11-30T20:23:38.343Z" }, + { url = "https://files.pythonhosted.org/packages/df/5a/7ee239b1aa48a127570ec03becbb29c9d5a9eb092febbd1699d567cae859/rpds_py-0.30.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4559c972db3a360808309e06a74628b95eaccbf961c335c8fe0d590cf587456f", size = 415661, upload-time = "2025-11-30T20:23:40.263Z" }, + { url = "https://files.pythonhosted.org/packages/70/ea/caa143cf6b772f823bc7929a45da1fa83569ee49b11d18d0ada7f5ee6fd6/rpds_py-0.30.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:0ed177ed9bded28f8deb6ab40c183cd1192aa0de40c12f38be4d59cd33cb5c65", size = 565606, upload-time = "2025-11-30T20:23:42.186Z" }, + { url = "https://files.pythonhosted.org/packages/64/91/ac20ba2d69303f961ad8cf55bf7dbdb4763f627291ba3d0d7d67333cced9/rpds_py-0.30.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:ad1fa8db769b76ea911cb4e10f049d80bf518c104f15b3edb2371cc65375c46f", size = 591126, upload-time = "2025-11-30T20:23:44.086Z" }, + { url = "https://files.pythonhosted.org/packages/21/20/7ff5f3c8b00c8a95f75985128c26ba44503fb35b8e0259d812766ea966c7/rpds_py-0.30.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:46e83c697b1f1c72b50e5ee5adb4353eef7406fb3f2043d64c33f20ad1c2fc53", size = 553371, upload-time = "2025-11-30T20:23:46.004Z" }, + { url = "https://files.pythonhosted.org/packages/72/c7/81dadd7b27c8ee391c132a6b192111ca58d866577ce2d9b0ca157552cce0/rpds_py-0.30.0-cp314-cp314-win32.whl", hash = "sha256:ee454b2a007d57363c2dfd5b6ca4a5d7e2c518938f8ed3b706e37e5d470801ed", size = 215298, upload-time = "2025-11-30T20:23:47.696Z" }, + { url = "https://files.pythonhosted.org/packages/3e/d2/1aaac33287e8cfb07aab2e6b8ac1deca62f6f65411344f1433c55e6f3eb8/rpds_py-0.30.0-cp314-cp314-win_amd64.whl", hash = "sha256:95f0802447ac2d10bcc69f6dc28fe95fdf17940367b21d34e34c737870758950", size = 228604, upload-time = "2025-11-30T20:23:49.501Z" }, + { url = "https://files.pythonhosted.org/packages/e8/95/ab005315818cc519ad074cb7784dae60d939163108bd2b394e60dc7b5461/rpds_py-0.30.0-cp314-cp314-win_arm64.whl", hash = "sha256:613aa4771c99f03346e54c3f038e4cc574ac09a3ddfb0e8878487335e96dead6", size = 222391, upload-time = "2025-11-30T20:23:50.96Z" }, + { url = "https://files.pythonhosted.org/packages/9e/68/154fe0194d83b973cdedcdcc88947a2752411165930182ae41d983dcefa6/rpds_py-0.30.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:7e6ecfcb62edfd632e56983964e6884851786443739dbfe3582947e87274f7cb", size = 364868, upload-time = "2025-11-30T20:23:52.494Z" }, + { url = "https://files.pythonhosted.org/packages/83/69/8bbc8b07ec854d92a8b75668c24d2abcb1719ebf890f5604c61c9369a16f/rpds_py-0.30.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a1d0bc22a7cdc173fedebb73ef81e07faef93692b8c1ad3733b67e31e1b6e1b8", size = 353747, upload-time = "2025-11-30T20:23:54.036Z" }, + { url = "https://files.pythonhosted.org/packages/ab/00/ba2e50183dbd9abcce9497fa5149c62b4ff3e22d338a30d690f9af970561/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d08f00679177226c4cb8c5265012eea897c8ca3b93f429e546600c971bcbae7", size = 383795, upload-time = "2025-11-30T20:23:55.556Z" }, + { url = "https://files.pythonhosted.org/packages/05/6f/86f0272b84926bcb0e4c972262f54223e8ecc556b3224d281e6598fc9268/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5965af57d5848192c13534f90f9dd16464f3c37aaf166cc1da1cae1fd5a34898", size = 393330, upload-time = "2025-11-30T20:23:57.033Z" }, + { url = "https://files.pythonhosted.org/packages/cb/e9/0e02bb2e6dc63d212641da45df2b0bf29699d01715913e0d0f017ee29438/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9a4e86e34e9ab6b667c27f3211ca48f73dba7cd3d90f8d5b11be56e5dbc3fb4e", size = 518194, upload-time = "2025-11-30T20:23:58.637Z" }, + { url = "https://files.pythonhosted.org/packages/ee/ca/be7bca14cf21513bdf9c0606aba17d1f389ea2b6987035eb4f62bd923f25/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e5d3e6b26f2c785d65cc25ef1e5267ccbe1b069c5c21b8cc724efee290554419", size = 408340, upload-time = "2025-11-30T20:24:00.2Z" }, + { url = "https://files.pythonhosted.org/packages/c2/c7/736e00ebf39ed81d75544c0da6ef7b0998f8201b369acf842f9a90dc8fce/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:626a7433c34566535b6e56a1b39a7b17ba961e97ce3b80ec62e6f1312c025551", size = 383765, upload-time = "2025-11-30T20:24:01.759Z" }, + { url = "https://files.pythonhosted.org/packages/4a/3f/da50dfde9956aaf365c4adc9533b100008ed31aea635f2b8d7b627e25b49/rpds_py-0.30.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:acd7eb3f4471577b9b5a41baf02a978e8bdeb08b4b355273994f8b87032000a8", size = 396834, upload-time = "2025-11-30T20:24:03.687Z" }, + { url = "https://files.pythonhosted.org/packages/4e/00/34bcc2565b6020eab2623349efbdec810676ad571995911f1abdae62a3a0/rpds_py-0.30.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fe5fa731a1fa8a0a56b0977413f8cacac1768dad38d16b3a296712709476fbd5", size = 415470, upload-time = "2025-11-30T20:24:05.232Z" }, + { url = "https://files.pythonhosted.org/packages/8c/28/882e72b5b3e6f718d5453bd4d0d9cf8df36fddeb4ddbbab17869d5868616/rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:74a3243a411126362712ee1524dfc90c650a503502f135d54d1b352bd01f2404", size = 565630, upload-time = "2025-11-30T20:24:06.878Z" }, + { url = "https://files.pythonhosted.org/packages/3b/97/04a65539c17692de5b85c6e293520fd01317fd878ea1995f0367d4532fb1/rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:3e8eeb0544f2eb0d2581774be4c3410356eba189529a6b3e36bbbf9696175856", size = 591148, upload-time = "2025-11-30T20:24:08.445Z" }, + { url = "https://files.pythonhosted.org/packages/85/70/92482ccffb96f5441aab93e26c4d66489eb599efdcf96fad90c14bbfb976/rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:dbd936cde57abfee19ab3213cf9c26be06d60750e60a8e4dd85d1ab12c8b1f40", size = 556030, upload-time = "2025-11-30T20:24:10.956Z" }, + { url = "https://files.pythonhosted.org/packages/20/53/7c7e784abfa500a2b6b583b147ee4bb5a2b3747a9166bab52fec4b5b5e7d/rpds_py-0.30.0-cp314-cp314t-win32.whl", hash = "sha256:dc824125c72246d924f7f796b4f63c1e9dc810c7d9e2355864b3c3a73d59ade0", size = 211570, upload-time = "2025-11-30T20:24:12.735Z" }, + { url = "https://files.pythonhosted.org/packages/d0/02/fa464cdfbe6b26e0600b62c528b72d8608f5cc49f96b8d6e38c95d60c676/rpds_py-0.30.0-cp314-cp314t-win_amd64.whl", hash = "sha256:27f4b0e92de5bfbc6f86e43959e6edd1425c33b5e69aab0984a72047f2bcf1e3", size = 226532, upload-time = "2025-11-30T20:24:14.634Z" }, +] + +[[package]] +name = "send2trash" +version = "2.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c5/f0/184b4b5f8d00f2a92cf96eec8967a3d550b52cf94362dad1100df9e48d57/send2trash-2.1.0.tar.gz", hash = "sha256:1c72b39f09457db3c05ce1d19158c2cbef4c32b8bedd02c155e49282b7ea7459", size = 17255, upload-time = "2026-01-14T06:27:36.056Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1c/78/504fdd027da3b84ff1aecd9f6957e65f35134534ccc6da8628eb71e76d3f/send2trash-2.1.0-py3-none-any.whl", hash = "sha256:0da2f112e6d6bb22de6aa6daa7e144831a4febf2a87261451c4ad849fe9a873c", size = 17610, upload-time = "2026-01-14T06:27:35.218Z" }, +] + +[[package]] +name = "setuptools" +version = "82.0.1" +source = { registry = "https://pypi.org/simple" } +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/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 = "shellingham" +version = "1.5.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/58/15/8b3609fd3830ef7b27b655beb4b4e9c62313a4e8da8c676e142cc210d58e/shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de", size = 10310, upload-time = "2023-10-24T04:13:40.426Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", size = 9755, upload-time = "2023-10-24T04:13:38.866Z" }, +] + +[[package]] +name = "six" +version = "1.17.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" }, +] + +[[package]] +name = "soupsieve" +version = "2.8.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7b/ae/2d9c981590ed9999a0d91755b47fc74f74de286b0f5cee14c9269041e6c4/soupsieve-2.8.3.tar.gz", hash = "sha256:3267f1eeea4251fb42728b6dfb746edc9acaffc4a45b27e19450b676586e8349", size = 118627, upload-time = "2026-01-20T04:27:02.457Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/46/2c/1462b1d0a634697ae9e55b3cecdcb64788e8b7d63f54d923fcd0bb140aed/soupsieve-2.8.3-py3-none-any.whl", hash = "sha256:ed64f2ba4eebeab06cc4962affce381647455978ffc1e36bb79a545b91f45a95", size = 37016, upload-time = "2026-01-20T04:27:01.012Z" }, +] + +[[package]] +name = "sqlite-anyio" +version = "0.2.8" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/20/a3/7830c95b37f1268dbb47e559d1f1ae027f3a4c36b1f7fc1b2dc5de1c5073/sqlite_anyio-0.2.8.tar.gz", hash = "sha256:d68b51a18c01a7dfa9cedbc319871ce77ab3ed0822518fb32810bb465b52d761", size = 3271, upload-time = "2026-03-02T10:37:43.466Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/aa/182981b92659df83c3eb7d6f8fb0874984d72ad688fa4054cb96bc044bb0/sqlite_anyio-0.2.8-py3-none-any.whl", hash = "sha256:bbdfefb144aed2633d2618ee1508edd3abe67a00389379360949da4671640d86", size = 4041, upload-time = "2026-03-02T10:37:42.246Z" }, +] + +[[package]] +name = "sse-starlette" +version = "3.3.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "starlette" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/26/8c/f9290339ef6d79badbc010f067cd769d6601ec11a57d78569c683fb4dd87/sse_starlette-3.3.4.tar.gz", hash = "sha256:aaf92fc067af8a5427192895ac028e947b484ac01edbc3caf00e7e7137c7bef1", size = 32427, upload-time = "2026-03-29T09:00:23.307Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f8/7f/3de5402f39890ac5660b86bcf5c03f9d855dad5c4ed764866d7b592b46fd/sse_starlette-3.3.4-py3-none-any.whl", hash = "sha256:84bb06e58939a8b38d8341f1bc9792f06c2b53f48c608dd207582b664fc8f3c1", size = 14330, upload-time = "2026-03-29T09:00:21.846Z" }, +] + +[[package]] +name = "stack-data" +version = "0.6.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "asttokens" }, + { name = "executing" }, + { name = "pure-eval" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/28/e3/55dcc2cfbc3ca9c29519eb6884dd1415ecb53b0e934862d3559ddcb7e20b/stack_data-0.6.3.tar.gz", hash = "sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9", size = 44707, upload-time = "2023-09-30T13:58:05.479Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f1/7b/ce1eafaf1a76852e2ec9b22edecf1daa58175c090266e9f6c64afcd81d91/stack_data-0.6.3-py3-none-any.whl", hash = "sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695", size = 24521, upload-time = "2023-09-30T13:58:03.53Z" }, +] + +[[package]] +name = "starlette" +version = "1.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/81/69/17425771797c36cded50b7fe44e850315d039f28b15901ab44839e70b593/starlette-1.0.0.tar.gz", hash = "sha256:6a4beaf1f81bb472fd19ea9b918b50dc3a77a6f2e190a12954b25e6ed5eea149", size = 2655289, upload-time = "2026-03-22T18:29:46.779Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0b/c9/584bc9651441b4ba60cc4d557d8a547b5aff901af35bda3a4ee30c819b82/starlette-1.0.0-py3-none-any.whl", hash = "sha256:d3ec55e0bb321692d275455ddfd3df75fff145d009685eb40dc91fc66b03d38b", size = 72651, upload-time = "2026-03-22T18:29:45.111Z" }, +] + +[[package]] +name = "terminado" +version = "0.18.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "ptyprocess", marker = "os_name != 'nt'" }, + { name = "pywinpty", marker = "os_name == 'nt'" }, + { name = "tornado" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/8a/11/965c6fd8e5cc254f1fe142d547387da17a8ebfd75a3455f637c663fb38a0/terminado-0.18.1.tar.gz", hash = "sha256:de09f2c4b85de4765f7714688fff57d3e75bad1f909b589fde880460c753fd2e", size = 32701, upload-time = "2024-03-12T14:34:39.026Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6a/9e/2064975477fdc887e47ad42157e214526dcad8f317a948dee17e1659a62f/terminado-0.18.1-py3-none-any.whl", hash = "sha256:a4468e1b37bb318f8a86514f65814e1afc977cf29b3992a4500d9dd305dcceb0", size = 14154, upload-time = "2024-03-12T14:34:36.569Z" }, +] + +[[package]] +name = "tinycss2" +version = "1.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "webencodings" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7a/fd/7a5ee21fd08ff70d3d33a5781c255cbe779659bd03278feb98b19ee550f4/tinycss2-1.4.0.tar.gz", hash = "sha256:10c0972f6fc0fbee87c3edb76549357415e94548c1ae10ebccdea16fb404a9b7", size = 87085, upload-time = "2024-10-24T14:58:29.895Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e6/34/ebdc18bae6aa14fbee1a08b63c015c72b64868ff7dae68808ab500c492e2/tinycss2-1.4.0-py3-none-any.whl", hash = "sha256:3a49cf47b7675da0b15d0c6e1df8df4ebd96e9394bb905a5775adb0d884c5289", size = 26610, upload-time = "2024-10-24T14:58:28.029Z" }, +] + +[[package]] +name = "tornado" +version = "6.5.5" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f8/f1/3173dfa4a18db4a9b03e5d55325559dab51ee653763bb8745a75af491286/tornado-6.5.5.tar.gz", hash = "sha256:192b8f3ea91bd7f1f50c06955416ed76c6b72f96779b962f07f911b91e8d30e9", size = 516006, upload-time = "2026-03-10T21:31:02.067Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/59/8c/77f5097695f4dd8255ecbd08b2a1ed8ba8b953d337804dd7080f199e12bf/tornado-6.5.5-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:487dc9cc380e29f58c7ab88f9e27cdeef04b2140862e5076a66fb6bb68bb1bfa", size = 445983, upload-time = "2026-03-10T21:30:44.28Z" }, + { url = "https://files.pythonhosted.org/packages/ab/5e/7625b76cd10f98f1516c36ce0346de62061156352353ef2da44e5c21523c/tornado-6.5.5-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:65a7f1d46d4bb41df1ac99f5fcb685fb25c7e61613742d5108b010975a9a6521", size = 444246, upload-time = "2026-03-10T21:30:46.571Z" }, + { url = "https://files.pythonhosted.org/packages/b2/04/7b5705d5b3c0fab088f434f9c83edac1573830ca49ccf29fb83bf7178eec/tornado-6.5.5-cp39-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:e74c92e8e65086b338fd56333fb9a68b9f6f2fe7ad532645a290a464bcf46be5", size = 447229, upload-time = "2026-03-10T21:30:48.273Z" }, + { url = "https://files.pythonhosted.org/packages/34/01/74e034a30ef59afb4097ef8659515e96a39d910b712a89af76f5e4e1f93c/tornado-6.5.5-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:435319e9e340276428bbdb4e7fa732c2d399386d1de5686cb331ec8eee754f07", size = 448192, upload-time = "2026-03-10T21:30:51.22Z" }, + { url = "https://files.pythonhosted.org/packages/be/00/fe9e02c5a96429fce1a1d15a517f5d8444f9c412e0bb9eadfbe3b0fc55bf/tornado-6.5.5-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:3f54aa540bdbfee7b9eb268ead60e7d199de5021facd276819c193c0fb28ea4e", size = 448039, upload-time = "2026-03-10T21:30:53.52Z" }, + { url = "https://files.pythonhosted.org/packages/82/9e/656ee4cec0398b1d18d0f1eb6372c41c6b889722641d84948351ae19556d/tornado-6.5.5-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:36abed1754faeb80fbd6e64db2758091e1320f6bba74a4cf8c09cd18ccce8aca", size = 447445, upload-time = "2026-03-10T21:30:55.541Z" }, + { url = "https://files.pythonhosted.org/packages/5a/76/4921c00511f88af86a33de770d64141170f1cfd9c00311aea689949e274e/tornado-6.5.5-cp39-abi3-win32.whl", hash = "sha256:dd3eafaaeec1c7f2f8fdcd5f964e8907ad788fe8a5a32c4426fbbdda621223b7", size = 448582, upload-time = "2026-03-10T21:30:57.142Z" }, + { url = "https://files.pythonhosted.org/packages/2c/23/f6c6112a04d28eed765e374435fb1a9198f73e1ec4b4024184f21faeb1ad/tornado-6.5.5-cp39-abi3-win_amd64.whl", hash = "sha256:6443a794ba961a9f619b1ae926a2e900ac20c34483eea67be4ed8f1e58d3ef7b", size = 448990, upload-time = "2026-03-10T21:30:58.857Z" }, + { url = "https://files.pythonhosted.org/packages/b7/c8/876602cbc96469911f0939f703453c1157b0c826ecb05bdd32e023397d4e/tornado-6.5.5-cp39-abi3-win_arm64.whl", hash = "sha256:2c9a876e094109333f888539ddb2de4361743e5d21eece20688e3e351e4990a6", size = 448016, upload-time = "2026-03-10T21:31:00.43Z" }, +] + +[[package]] +name = "traitlets" +version = "5.14.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/eb/79/72064e6a701c2183016abbbfedaba506d81e30e232a68c9f0d6f6fcd1574/traitlets-5.14.3.tar.gz", hash = "sha256:9ed0579d3502c94b4b3732ac120375cda96f923114522847de4b3bb98b96b6b7", size = 161621, upload-time = "2024-04-19T11:11:49.746Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/00/c0/8f5d070730d7836adc9c9b6408dec68c6ced86b304a9b26a14df072a6e8c/traitlets-5.14.3-py3-none-any.whl", hash = "sha256:b74e89e397b1ed28cc831db7aea759ba6640cb3de13090ca145426688ff1ac4f", size = 85359, upload-time = "2024-04-19T11:11:46.763Z" }, +] + +[[package]] +name = "typer" +version = "0.24.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "annotated-doc" }, + { name = "click" }, + { name = "rich" }, + { name = "shellingham" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f5/24/cb09efec5cc954f7f9b930bf8279447d24618bb6758d4f6adf2574c41780/typer-0.24.1.tar.gz", hash = "sha256:e39b4732d65fbdcde189ae76cf7cd48aeae72919dea1fdfc16593be016256b45", size = 118613, upload-time = "2026-02-21T16:54:40.609Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4a/91/48db081e7a63bb37284f9fbcefda7c44c277b18b0e13fbc36ea2335b71e6/typer-0.24.1-py3-none-any.whl", hash = "sha256:112c1f0ce578bfb4cab9ffdabc68f031416ebcc216536611ba21f04e9aa84c9e", size = 56085, upload-time = "2026-02-21T16:54:41.616Z" }, +] + +[[package]] +name = "typing-extensions" +version = "4.15.0" +source = { registry = "https://pypi.org/simple" } +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/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 = "typing-inspection" +version = "0.4.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/55/e3/70399cb7dd41c10ac53367ae42139cf4b1ca5f36bb3dc6c9d33acdb43655/typing_inspection-0.4.2.tar.gz", hash = "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464", size = 75949, upload-time = "2025-10-01T02:14:41.687Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7", size = 14611, upload-time = "2025-10-01T02:14:40.154Z" }, +] + +[[package]] +name = "tzdata" +version = "2026.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/19/f5/cd531b2d15a671a40c0f66cf06bc3570a12cd56eef98960068ebbad1bf5a/tzdata-2026.1.tar.gz", hash = "sha256:67658a1903c75917309e753fdc349ac0efd8c27db7a0cb406a25be4840f87f98", size = 197639, upload-time = "2026-04-03T11:25:22.002Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b0/70/d460bd685a170790ec89317e9bd33047988e4bce507b831f5db771e142de/tzdata-2026.1-py2.py3-none-any.whl", hash = "sha256:4b1d2be7ac37ceafd7327b961aa3a54e467efbdb563a23655fbfe0d39cfc42a9", size = 348952, upload-time = "2026-04-03T11:25:20.313Z" }, +] + +[[package]] +name = "uri-template" +version = "1.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/31/c7/0336f2bd0bcbada6ccef7aaa25e443c118a704f828a0620c6fa0207c1b64/uri-template-1.3.0.tar.gz", hash = "sha256:0e00f8eb65e18c7de20d595a14336e9f337ead580c70934141624b6d1ffdacc7", size = 21678, upload-time = "2023-06-21T01:49:05.374Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e7/00/3fca040d7cf8a32776d3d81a00c8ee7457e00f80c649f1e4a863c8321ae9/uri_template-1.3.0-py3-none-any.whl", hash = "sha256:a44a133ea12d44a0c0f06d7d42a52d71282e77e2f937d8abd5655b8d56fc1363", size = 11140, upload-time = "2023-06-21T01:49:03.467Z" }, +] + +[[package]] +name = "urllib3" +version = "2.6.3" +source = { registry = "https://pypi.org/simple" } +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/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 = "uvicorn" +version = "0.44.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click", marker = "sys_platform != 'emscripten'" }, + { name = "h11", marker = "sys_platform != 'emscripten'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5e/da/6eee1ff8b6cbeed47eeb5229749168e81eb4b7b999a1a15a7176e51410c9/uvicorn-0.44.0.tar.gz", hash = "sha256:6c942071b68f07e178264b9152f1f16dfac5da85880c4ce06366a96d70d4f31e", size = 86947, upload-time = "2026-04-06T09:23:22.826Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/23/a5bbd9600dd607411fa644c06ff4951bec3a4d82c4b852374024359c19c0/uvicorn-0.44.0-py3-none-any.whl", hash = "sha256:ce937c99a2cc70279556967274414c087888e8cec9f9c94644dfca11bd3ced89", size = 69425, upload-time = "2026-04-06T09:23:21.524Z" }, +] + +[[package]] +name = "wcwidth" +version = "0.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/35/a2/8e3becb46433538a38726c948d3399905a4c7cabd0df578ede5dc51f0ec2/wcwidth-0.6.0.tar.gz", hash = "sha256:cdc4e4262d6ef9a1a57e018384cbeb1208d8abbc64176027e2c2455c81313159", size = 159684, upload-time = "2026-02-06T19:19:40.919Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/68/5a/199c59e0a824a3db2b89c5d2dade7ab5f9624dbf6448dc291b46d5ec94d3/wcwidth-0.6.0-py3-none-any.whl", hash = "sha256:1a3a1e510b553315f8e146c54764f4fb6264ffad731b3d78088cdb1478ffbdad", size = 94189, upload-time = "2026-02-06T19:19:39.646Z" }, +] + +[[package]] +name = "webcolors" +version = "25.10.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1d/7a/eb316761ec35664ea5174709a68bbd3389de60d4a1ebab8808bfc264ed67/webcolors-25.10.0.tar.gz", hash = "sha256:62abae86504f66d0f6364c2a8520de4a0c47b80c03fc3a5f1815fedbef7c19bf", size = 53491, upload-time = "2025-10-31T07:51:03.977Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e2/cc/e097523dd85c9cf5d354f78310927f1656c422bd7b2613b2db3e3f9a0f2c/webcolors-25.10.0-py3-none-any.whl", hash = "sha256:032c727334856fc0b968f63daa252a1ac93d33db2f5267756623c210e57a4f1d", size = 14905, upload-time = "2025-10-31T07:51:01.778Z" }, +] + +[[package]] +name = "webencodings" +version = "0.5.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0b/02/ae6ceac1baeda530866a85075641cec12989bd8d31af6d5ab4a3e8c92f47/webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923", size = 9721, upload-time = "2017-04-05T20:21:34.189Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/24/2a3e3df732393fed8b3ebf2ec078f05546de641fe1b667ee316ec1dcf3b7/webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78", size = 11774, upload-time = "2017-04-05T20:21:32.581Z" }, +] + +[[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 = "websockets" +version = "16.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/04/24/4b2031d72e840ce4c1ccb255f693b15c334757fc50023e4db9537080b8c4/websockets-16.0.tar.gz", hash = "sha256:5f6261a5e56e8d5c42a4497b364ea24d94d9563e8fbd44e78ac40879c60179b5", size = 179346, upload-time = "2026-01-10T09:23:47.181Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cc/9c/baa8456050d1c1b08dd0ec7346026668cbc6f145ab4e314d707bb845bf0d/websockets-16.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:878b336ac47938b474c8f982ac2f7266a540adc3fa4ad74ae96fea9823a02cc9", size = 177364, upload-time = "2026-01-10T09:22:59.333Z" }, + { url = "https://files.pythonhosted.org/packages/7e/0c/8811fc53e9bcff68fe7de2bcbe75116a8d959ac699a3200f4847a8925210/websockets-16.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:52a0fec0e6c8d9a784c2c78276a48a2bdf099e4ccc2a4cad53b27718dbfd0230", size = 175039, upload-time = "2026-01-10T09:23:01.171Z" }, + { url = "https://files.pythonhosted.org/packages/aa/82/39a5f910cb99ec0b59e482971238c845af9220d3ab9fa76dd9162cda9d62/websockets-16.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e6578ed5b6981005df1860a56e3617f14a6c307e6a71b4fff8c48fdc50f3ed2c", size = 175323, upload-time = "2026-01-10T09:23:02.341Z" }, + { url = "https://files.pythonhosted.org/packages/bd/28/0a25ee5342eb5d5f297d992a77e56892ecb65e7854c7898fb7d35e9b33bd/websockets-16.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:95724e638f0f9c350bb1c2b0a7ad0e83d9cc0c9259f3ea94e40d7b02a2179ae5", size = 184975, upload-time = "2026-01-10T09:23:03.756Z" }, + { url = "https://files.pythonhosted.org/packages/f9/66/27ea52741752f5107c2e41fda05e8395a682a1e11c4e592a809a90c6a506/websockets-16.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c0204dc62a89dc9d50d682412c10b3542d748260d743500a85c13cd1ee4bde82", size = 186203, upload-time = "2026-01-10T09:23:05.01Z" }, + { url = "https://files.pythonhosted.org/packages/37/e5/8e32857371406a757816a2b471939d51c463509be73fa538216ea52b792a/websockets-16.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:52ac480f44d32970d66763115edea932f1c5b1312de36df06d6b219f6741eed8", size = 185653, upload-time = "2026-01-10T09:23:06.301Z" }, + { url = "https://files.pythonhosted.org/packages/9b/67/f926bac29882894669368dc73f4da900fcdf47955d0a0185d60103df5737/websockets-16.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6e5a82b677f8f6f59e8dfc34ec06ca6b5b48bc4fcda346acd093694cc2c24d8f", size = 184920, upload-time = "2026-01-10T09:23:07.492Z" }, + { url = "https://files.pythonhosted.org/packages/3c/a1/3d6ccdcd125b0a42a311bcd15a7f705d688f73b2a22d8cf1c0875d35d34a/websockets-16.0-cp313-cp313-win32.whl", hash = "sha256:abf050a199613f64c886ea10f38b47770a65154dc37181bfaff70c160f45315a", size = 178255, upload-time = "2026-01-10T09:23:09.245Z" }, + { url = "https://files.pythonhosted.org/packages/6b/ae/90366304d7c2ce80f9b826096a9e9048b4bb760e44d3b873bb272cba696b/websockets-16.0-cp313-cp313-win_amd64.whl", hash = "sha256:3425ac5cf448801335d6fdc7ae1eb22072055417a96cc6b31b3861f455fbc156", size = 178689, upload-time = "2026-01-10T09:23:10.483Z" }, + { url = "https://files.pythonhosted.org/packages/f3/1d/e88022630271f5bd349ed82417136281931e558d628dd52c4d8621b4a0b2/websockets-16.0-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:8cc451a50f2aee53042ac52d2d053d08bf89bcb31ae799cb4487587661c038a0", size = 177406, upload-time = "2026-01-10T09:23:12.178Z" }, + { url = "https://files.pythonhosted.org/packages/f2/78/e63be1bf0724eeb4616efb1ae1c9044f7c3953b7957799abb5915bffd38e/websockets-16.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:daa3b6ff70a9241cf6c7fc9e949d41232d9d7d26fd3522b1ad2b4d62487e9904", size = 175085, upload-time = "2026-01-10T09:23:13.511Z" }, + { url = "https://files.pythonhosted.org/packages/bb/f4/d3c9220d818ee955ae390cf319a7c7a467beceb24f05ee7aaaa2414345ba/websockets-16.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:fd3cb4adb94a2a6e2b7c0d8d05cb94e6f1c81a0cf9dc2694fb65c7e8d94c42e4", size = 175328, upload-time = "2026-01-10T09:23:14.727Z" }, + { url = "https://files.pythonhosted.org/packages/63/bc/d3e208028de777087e6fb2b122051a6ff7bbcca0d6df9d9c2bf1dd869ae9/websockets-16.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:781caf5e8eee67f663126490c2f96f40906594cb86b408a703630f95550a8c3e", size = 185044, upload-time = "2026-01-10T09:23:15.939Z" }, + { url = "https://files.pythonhosted.org/packages/ad/6e/9a0927ac24bd33a0a9af834d89e0abc7cfd8e13bed17a86407a66773cc0e/websockets-16.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:caab51a72c51973ca21fa8a18bd8165e1a0183f1ac7066a182ff27107b71e1a4", size = 186279, upload-time = "2026-01-10T09:23:17.148Z" }, + { url = "https://files.pythonhosted.org/packages/b9/ca/bf1c68440d7a868180e11be653c85959502efd3a709323230314fda6e0b3/websockets-16.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:19c4dc84098e523fd63711e563077d39e90ec6702aff4b5d9e344a60cb3c0cb1", size = 185711, upload-time = "2026-01-10T09:23:18.372Z" }, + { url = "https://files.pythonhosted.org/packages/c4/f8/fdc34643a989561f217bb477cbc47a3a07212cbda91c0e4389c43c296ebf/websockets-16.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:a5e18a238a2b2249c9a9235466b90e96ae4795672598a58772dd806edc7ac6d3", size = 184982, upload-time = "2026-01-10T09:23:19.652Z" }, + { url = "https://files.pythonhosted.org/packages/dd/d1/574fa27e233764dbac9c52730d63fcf2823b16f0856b3329fc6268d6ae4f/websockets-16.0-cp314-cp314-win32.whl", hash = "sha256:a069d734c4a043182729edd3e9f247c3b2a4035415a9172fd0f1b71658a320a8", size = 177915, upload-time = "2026-01-10T09:23:21.458Z" }, + { url = "https://files.pythonhosted.org/packages/8a/f1/ae6b937bf3126b5134ce1f482365fde31a357c784ac51852978768b5eff4/websockets-16.0-cp314-cp314-win_amd64.whl", hash = "sha256:c0ee0e63f23914732c6d7e0cce24915c48f3f1512ec1d079ed01fc629dab269d", size = 178381, upload-time = "2026-01-10T09:23:22.715Z" }, + { url = "https://files.pythonhosted.org/packages/06/9b/f791d1db48403e1f0a27577a6beb37afae94254a8c6f08be4a23e4930bc0/websockets-16.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:a35539cacc3febb22b8f4d4a99cc79b104226a756aa7400adc722e83b0d03244", size = 177737, upload-time = "2026-01-10T09:23:24.523Z" }, + { url = "https://files.pythonhosted.org/packages/bd/40/53ad02341fa33b3ce489023f635367a4ac98b73570102ad2cdd770dacc9a/websockets-16.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:b784ca5de850f4ce93ec85d3269d24d4c82f22b7212023c974c401d4980ebc5e", size = 175268, upload-time = "2026-01-10T09:23:25.781Z" }, + { url = "https://files.pythonhosted.org/packages/74/9b/6158d4e459b984f949dcbbb0c5d270154c7618e11c01029b9bbd1bb4c4f9/websockets-16.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:569d01a4e7fba956c5ae4fc988f0d4e187900f5497ce46339c996dbf24f17641", size = 175486, upload-time = "2026-01-10T09:23:27.033Z" }, + { url = "https://files.pythonhosted.org/packages/e5/2d/7583b30208b639c8090206f95073646c2c9ffd66f44df967981a64f849ad/websockets-16.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:50f23cdd8343b984957e4077839841146f67a3d31ab0d00e6b824e74c5b2f6e8", size = 185331, upload-time = "2026-01-10T09:23:28.259Z" }, + { url = "https://files.pythonhosted.org/packages/45/b0/cce3784eb519b7b5ad680d14b9673a31ab8dcb7aad8b64d81709d2430aa8/websockets-16.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:152284a83a00c59b759697b7f9e9cddf4e3c7861dd0d964b472b70f78f89e80e", size = 186501, upload-time = "2026-01-10T09:23:29.449Z" }, + { url = "https://files.pythonhosted.org/packages/19/60/b8ebe4c7e89fb5f6cdf080623c9d92789a53636950f7abacfc33fe2b3135/websockets-16.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:bc59589ab64b0022385f429b94697348a6a234e8ce22544e3681b2e9331b5944", size = 186062, upload-time = "2026-01-10T09:23:31.368Z" }, + { url = "https://files.pythonhosted.org/packages/88/a8/a080593f89b0138b6cba1b28f8df5673b5506f72879322288b031337c0b8/websockets-16.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:32da954ffa2814258030e5a57bc73a3635463238e797c7375dc8091327434206", size = 185356, upload-time = "2026-01-10T09:23:32.627Z" }, + { url = "https://files.pythonhosted.org/packages/c2/b6/b9afed2afadddaf5ebb2afa801abf4b0868f42f8539bfe4b071b5266c9fe/websockets-16.0-cp314-cp314t-win32.whl", hash = "sha256:5a4b4cc550cb665dd8a47f868c8d04c8230f857363ad3c9caf7a0c3bf8c61ca6", size = 178085, upload-time = "2026-01-10T09:23:33.816Z" }, + { url = "https://files.pythonhosted.org/packages/9f/3e/28135a24e384493fa804216b79a6a6759a38cc4ff59118787b9fb693df93/websockets-16.0-cp314-cp314t-win_amd64.whl", hash = "sha256:b14dc141ed6d2dde437cddb216004bcac6a1df0935d79656387bd41632ba0bbd", size = 178531, upload-time = "2026-01-10T09:23:35.016Z" }, + { url = "https://files.pythonhosted.org/packages/6f/28/258ebab549c2bf3e64d2b0217b973467394a9cea8c42f70418ca2c5d0d2e/websockets-16.0-py3-none-any.whl", hash = "sha256:1637db62fad1dc833276dded54215f2c7fa46912301a24bd94d45d46a011ceec", size = 171598, upload-time = "2026-01-10T09:23:45.395Z" }, +] + +[[package]] +name = "widgetsnbextension" +version = "4.0.15" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/bd/f4/c67440c7fb409a71b7404b7aefcd7569a9c0d6bd071299bf4198ae7a5d95/widgetsnbextension-4.0.15.tar.gz", hash = "sha256:de8610639996f1567952d763a5a41af8af37f2575a41f9852a38f947eb82a3b9", size = 1097402, upload-time = "2025-11-01T21:15:55.178Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3f/0e/fa3b193432cfc60c93b42f3be03365f5f909d2b3ea410295cf36df739e31/widgetsnbextension-4.0.15-py3-none-any.whl", hash = "sha256:8156704e4346a571d9ce73b84bee86a29906c9abfd7223b7228a28899ccf3366", size = 2196503, upload-time = "2025-11-01T21:15:53.565Z" }, +]