From e152bcfe619b09ef4939d05dc0f4d95d4f9d67cf Mon Sep 17 00:00:00 2001 From: Oskar Weser Date: Mon, 16 Mar 2026 12:04:07 +0100 Subject: [PATCH 01/19] chore: update ruff config, add YAML formatter Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .pre-commit-config.yaml | 9 +++++++-- pyproject.toml | 4 +++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6926e95a..3fb4e1c2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -13,9 +13,9 @@ repos: ) - id: check-merge-conflict # Check for files that contain merge conflict - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.12.2 + rev: v0.15.4 hooks: - - id: ruff # better black/flake/isort + - id: ruff-check # better black/flake/isort files: ^src/ args: - --select @@ -24,6 +24,11 @@ repos: - --exit-non-zero-on-fix - id: ruff-format files: ^backend/ +- repo: https://github.com/macisamuele/language-formatters-pre-commit-hooks + rev: v2.16.0 + hooks: + - id: pretty-format-yaml + args: [--autofix, --preserve-quotes] ci: autoupdate_schedule: monthly autoupdate_commit_msg: "chore(deps): pre-commit.ci autoupdate" diff --git a/pyproject.toml b/pyproject.toml index 488551d0..c91dff68 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -66,5 +66,7 @@ testpaths = ["tests/"] addopts = "-n8" [tool.ruff] -line-length = 140 +line-length = 120 +lint.select = [ "E", "F", "I" ] +lint.isort.force-single-line = true lint.ignore = [ "E722", "E731", "E741" ] From 433dbf7f477b5dd7bae3387db7e5b28c39298d1f Mon Sep 17 00:00:00 2001 From: Oskar Weser Date: Mon, 16 Mar 2026 13:12:19 +0100 Subject: [PATCH 02/19] chore: apply standardized ruff lint select settings Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- pyproject.toml | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index c91dff68..e54d1749 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -67,6 +67,32 @@ addopts = "-n8" [tool.ruff] line-length = 120 -lint.select = [ "E", "F", "I" ] -lint.isort.force-single-line = true -lint.ignore = [ "E722", "E731", "E741" ] + +[tool.ruff.lint] +ignore = [ + "D1", # pydocstyle: Missing Docstrings + "D107", # pydocstyle: numpy convention + "D203", + "D205", + "D212", + "D213", + "D401", + "D402", + "D413", + "D415", + "D416", + "D417", + "E722", + "E731", + "E741", +] +select = [ + "F", # pyflakes + "E", # pycodestyle + "W", # pycodestyle warnings + "I", # isort + "D", # pydocstyle +] + +[tool.ruff.lint.isort] +force-single-line = true From b5d82d88633f707e45b5ac9f7c58546c04f50316 Mon Sep 17 00:00:00 2001 From: Oskar Weser Date: Mon, 16 Mar 2026 13:26:21 +0100 Subject: [PATCH 03/19] chore: use yamlfmt, standardize ruff-check args Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .pre-commit-config.yaml | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3fb4e1c2..cf856ac8 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -15,20 +15,18 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit rev: v0.15.4 hooks: - - id: ruff-check # better black/flake/isort - files: ^src/ + - id: ruff-check + exclude: '(dev/.*|.*_)\.py$' args: - - --select - - I # isorting - - --fix - - --exit-non-zero-on-fix + - --line-length=120 + - --fix + - --exit-non-zero-on-fix + - --preview - id: ruff-format - files: ^backend/ -- repo: https://github.com/macisamuele/language-formatters-pre-commit-hooks - rev: v2.16.0 +- repo: https://github.com/google/yamlfmt + rev: v0.13.0 hooks: - - id: pretty-format-yaml - args: [--autofix, --preserve-quotes] + - id: yamlfmt ci: autoupdate_schedule: monthly autoupdate_commit_msg: "chore(deps): pre-commit.ci autoupdate" From 70b3d78a98fff51c1b198505395cdaaaa9d71a51 Mon Sep 17 00:00:00 2001 From: Oskar Weser Date: Mon, 16 Mar 2026 13:31:22 +0100 Subject: [PATCH 04/19] chore: use macisamuele formatter for YAML and TOML Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .pre-commit-config.yaml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index cf856ac8..412c5350 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -23,10 +23,13 @@ repos: - --exit-non-zero-on-fix - --preview - id: ruff-format -- repo: https://github.com/google/yamlfmt - rev: v0.13.0 +- repo: https://github.com/macisamuele/language-formatters-pre-commit-hooks + rev: v2.16.0 hooks: - - id: yamlfmt + - id: pretty-format-yaml + args: [--autofix, --preserve-quotes] + - id: pretty-format-toml + args: [--autofix] ci: autoupdate_schedule: monthly autoupdate_commit_msg: "chore(deps): pre-commit.ci autoupdate" From 8addc95fba3071ff00028322808d4475eb9f9543 Mon Sep 17 00:00:00 2001 From: Oskar Weser Date: Mon, 16 Mar 2026 13:50:54 +0100 Subject: [PATCH 05/19] chore: use yamlfmt for YAML, pyproject-fmt for TOML Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .pre-commit-config.yaml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 412c5350..da027bc8 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -23,13 +23,14 @@ repos: - --exit-non-zero-on-fix - --preview - id: ruff-format -- repo: https://github.com/macisamuele/language-formatters-pre-commit-hooks - rev: v2.16.0 +- repo: https://github.com/google/yamlfmt + rev: v0.13.0 hooks: - - id: pretty-format-yaml - args: [--autofix, --preserve-quotes] - - id: pretty-format-toml - args: [--autofix] + - id: yamlfmt +- repo: https://github.com/tox-dev/pyproject-fmt + rev: "v2.5.0" + hooks: + - id: pyproject-fmt ci: autoupdate_schedule: monthly autoupdate_commit_msg: "chore(deps): pre-commit.ci autoupdate" From c5a52e3a88616321e81810e58a97b9b462e58c95 Mon Sep 17 00:00:00 2001 From: Oskar Weser Date: Mon, 16 Mar 2026 14:15:35 +0100 Subject: [PATCH 06/19] chore: use macisamuele formatter for YAML and TOML Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .pre-commit-config.yaml | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index da027bc8..412c5350 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -23,14 +23,13 @@ repos: - --exit-non-zero-on-fix - --preview - id: ruff-format -- repo: https://github.com/google/yamlfmt - rev: v0.13.0 +- repo: https://github.com/macisamuele/language-formatters-pre-commit-hooks + rev: v2.16.0 hooks: - - id: yamlfmt -- repo: https://github.com/tox-dev/pyproject-fmt - rev: "v2.5.0" - hooks: - - id: pyproject-fmt + - id: pretty-format-yaml + args: [--autofix, --preserve-quotes] + - id: pretty-format-toml + args: [--autofix] ci: autoupdate_schedule: monthly autoupdate_commit_msg: "chore(deps): pre-commit.ci autoupdate" From 4d86c47d5ae0d98bf698c74cb51d7bf936d56b47 Mon Sep 17 00:00:00 2001 From: Oskar Weser Date: Mon, 16 Mar 2026 15:32:11 +0100 Subject: [PATCH 07/19] change isort settings --- pyproject.toml | 3 --- 1 file changed, 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index e54d1749..02ce936c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -93,6 +93,3 @@ select = [ "I", # isort "D", # pydocstyle ] - -[tool.ruff.lint.isort] -force-single-line = true From fed88228def15bcceea511d0a7975643d43222a4 Mon Sep 17 00:00:00 2001 From: Oskar Weser Date: Mon, 16 Mar 2026 15:33:25 +0100 Subject: [PATCH 08/19] applied the automatic formatting --- .github/workflows/macos-test.yml | 22 +- .github/workflows/test-pypi.yml | 2 +- .pre-commit-config.yaml | 8 +- benchmarks/scenario-shm_throughput.py | 4 +- benchmarks/scheduling/sat_experiments.py | 4 +- docs/benchmarking/run1/analysis.ipynb | 77 +- docs/benchmarking/run1/analysis.py | 27 +- docs/benchmarking/run2/analysis.ipynb | 78 +- docs/benchmarking/run2/analysis.py | 23 +- docs/benchmarking/run3/tasklanes.ipynb | 91 +- docs/benchmarking/run3/tasklanes.py | 13 +- docs/ensemble_percentiles.ipynb | 156 +- docs/examples/arrayapi.ipynb | 31 +- docs/examples/xarray.ipynb | 3 +- .../cascade-job_building/t00_execute.py | 1 + .../cascade-job_building/t00_generate.py | 5 +- .../tutorials/cascade-job_building/t01_low.py | 12 +- .../cascade-job_building/t03_custom.py | 52 +- integration_tests/base.py | 1 + integration_tests/benchmarks_old/anemoi.py | 13 +- integration_tests/benchmarks_old/dask.py | 8 +- integration_tests/benchmarks_old/dist.py | 10 +- .../benchmarks_old/generators.py | 4 +- integration_tests/benchmarks_old/job1.py | 17 +- integration_tests/benchmarks_old/matmul.py | 3 +- integration_tests/benchmarks_old/plotting.py | 32 +- integration_tests/benchmarks_old/reporting.py | 34 +- integration_tests/benchmarks_old/util.py | 18 +- integration_tests/harness.py | 6 +- integration_tests/job_runnerRestarts.py | 20 +- integration_tests/runtime/__init__.py | 1 + pyproject.toml | 87 +- src/cascade/controller/act.py | 16 +- src/cascade/controller/core.py | 19 +- src/cascade/controller/impl.py | 6 +- src/cascade/deployment/__init__.py | 2 +- src/cascade/deployment/logging/__init__.py | 17 +- src/cascade/deployment/logging/defaults.py | 14 +- .../deployment/logging/json_formatter.py | 7 +- src/cascade/executor/bridge.py | 30 +- src/cascade/executor/checkpoints.py | 30 +- src/cascade/executor/comms.py | 9 +- src/cascade/executor/data_server.py | 30 +- src/cascade/executor/executor.py | 23 +- src/cascade/executor/msg.py | 17 +- src/cascade/executor/platform.py | 6 +- src/cascade/executor/runner/entrypoint.py | 28 +- src/cascade/executor/runner/memory.py | 8 +- src/cascade/executor/runner/packages.py | 9 +- src/cascade/executor/serde.py | 2 + src/cascade/gateway/__main__.py | 1 + src/cascade/gateway/client.py | 1 - src/cascade/gateway/router.py | 14 +- src/cascade/gateway/spawning.py | 4 +- src/cascade/low/builders.py | 43 +- src/cascade/low/core.py | 29 +- src/cascade/low/exceptions.py | 21 +- src/cascade/low/func.py | 1 - src/cascade/low/tracing.py | 8 +- src/cascade/main.py | 9 +- src/cascade/scheduler/api.py | 12 +- src/cascade/scheduler/assign.py | 26 +- src/cascade/scheduler/checkpoints.py | 68 +- src/cascade/scheduler/core.py | 8 +- src/cascade/scheduler/precompute.py | 16 +- src/cascade/shm/api.py | 8 +- src/cascade/shm/disk.py | 6 +- src/cascade/shm/func.py | 2 + src/earthkit/workflows/_qubed.py | 8 +- src/earthkit/workflows/adapters.py | 3 +- src/earthkit/workflows/backends/__init__.py | 8 +- src/earthkit/workflows/backends/earthkit.py | 38 +- src/earthkit/workflows/backends/xarray.py | 32 +- src/earthkit/workflows/compilers.py | 4 +- src/earthkit/workflows/fluent.py | 135 +- src/earthkit/workflows/graph/expand.py | 22 +- src/earthkit/workflows/graph/export.py | 17 +- src/earthkit/workflows/graph/fuse.py | 4 +- src/earthkit/workflows/graph/graph.py | 6 +- src/earthkit/workflows/graph/graphviz.py | 6 +- src/earthkit/workflows/graph/networkx.py | 4 +- src/earthkit/workflows/graph/nodes.py | 9 +- src/earthkit/workflows/graph/pyvis.py | 9 +- src/earthkit/workflows/graph/rename.py | 5 +- src/earthkit/workflows/graph/samplegraphs.py | 12 +- src/earthkit/workflows/graph/split.py | 4 +- src/earthkit/workflows/nodetree.py | 17 +- src/earthkit/workflows/taskgraph.py | 12 +- src/earthkit/workflows/utility.py | 5 +- tests/cascade/benchmarks/image_processing.py | 13 +- tests/cascade/controller/test_run.py | 46 +- tests/cascade/executor/test_callables.py | 4 +- tests/cascade/executor/test_checkpoints.py | 21 +- tests/cascade/executor/test_executor.py | 28 +- tests/cascade/executor/test_packages.py | 43 +- tests/cascade/executor/test_runner.py | 12 +- tests/cascade/executor/util.py | 29 +- tests/cascade/gateway/test_run.py | 27 +- tests/cascade/low/test_builders.py | 10 +- tests/cascade/low/test_core.py | 1 + tests/cascade/low/test_exceptions.py | 18 +- tests/cascade/scheduler/test_checkpoints.py | 15 +- tests/cascade/scheduler/util.py | 39 +- tests/cascade/shm/test_shm.py | 6 +- .../backends/generic_tests.py | 15 +- .../backends/test_arrayapi.py | 12 +- .../backends/test_earthkit.py | 4 +- .../backends/test_xarray.py | 9 +- tests/earthkit_workflows/graph/test_fuse.py | 6 +- tests/earthkit_workflows/graph/test_graph.py | 4 +- tests/earthkit_workflows/graph/test_split.py | 15 +- .../graph/test_transform.py | 8 +- tests/earthkit_workflows/graph/test_visit.py | 24 +- tests/earthkit_workflows/helpers.py | 4 +- tests/earthkit_workflows/test_fluent.py | 16 +- .../test_qubed_expansion.py | 84 +- uv.lock | 3318 ++++++++--------- 117 files changed, 2641 insertions(+), 2963 deletions(-) diff --git a/.github/workflows/macos-test.yml b/.github/workflows/macos-test.yml index 4e546b69..72d23de9 100644 --- a/.github/workflows/macos-test.yml +++ b/.github/workflows/macos-test.yml @@ -2,14 +2,14 @@ name: CI # TODO rename the file in a standalone PR, its not macos-test, but ci on: # Trigger the workflow manually - workflow_dispatch: ~ + workflow_dispatch: push: branches: - - 'main' - - 'develop' + - 'main' + - 'develop' - pull_request: ~ + pull_request: jobs: ci: @@ -21,12 +21,12 @@ jobs: runs-on: "${{ fromJSON('{\"linux-x86\": [\"self-hosted\", \"Linux\", \"platform-builder-Rocky-8.6\"], \"macos-ARM64\": [\"self-hosted\", \"macOS\", \"ARM64\"]}')[matrix.arch_type] }}" timeout-minutes: 20 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v4 # NOTE if setup uv used, make sure to configure uv cache correctly, to not fill home. But should be already installed and configured # - uses: astral-sh/setup-uv@v7 - - uses: extractions/setup-just@v3 - - run: | - echo "uv version is $(uv --version)" - uv sync --python "${{ matrix.python_version }}" - just fmt - just val + - uses: extractions/setup-just@v3 + - run: | + echo "uv version is $(uv --version)" + uv sync --python "${{ matrix.python_version }}" + just fmt + just val diff --git a/.github/workflows/test-pypi.yml b/.github/workflows/test-pypi.yml index eb899c45..b7b6a2b0 100644 --- a/.github/workflows/test-pypi.yml +++ b/.github/workflows/test-pypi.yml @@ -1,7 +1,7 @@ name: cd on: - workflow_dispatch: ~ + workflow_dispatch: jobs: deploy: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 412c5350..ccda0b7a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -18,10 +18,10 @@ repos: - id: ruff-check exclude: '(dev/.*|.*_)\.py$' args: - - --line-length=120 - - --fix - - --exit-non-zero-on-fix - - --preview + - --line-length=120 + - --fix + - --exit-non-zero-on-fix + - --preview - id: ruff-format - repo: https://github.com/macisamuele/language-formatters-pre-commit-hooks rev: v2.16.0 diff --git a/benchmarks/scenario-shm_throughput.py b/benchmarks/scenario-shm_throughput.py index 237dd738..c5c5684b 100644 --- a/benchmarks/scenario-shm_throughput.py +++ b/benchmarks/scenario-shm_throughput.py @@ -27,9 +27,7 @@ def track(cls, label: str): @classmethod def report(cls): - rpt = ( - lambda t1, t2: f"from {t1[0]} to {t2[0]} took {(t2[1]-t1[1]) / 1e6:.3f} ms" - ) + rpt = lambda t1, t2: f"from {t1[0]} to {t2[0]} took {(t2[1] - t1[1]) / 1e6:.3f} ms" print(rpt(cls.steps[0], cls.steps[-1])) for i in range(len(cls.steps) - 1): print(rpt(cls.steps[i], cls.steps[i + 1])) diff --git a/benchmarks/scheduling/sat_experiments.py b/benchmarks/scheduling/sat_experiments.py index 409e5ed8..57e2cdca 100644 --- a/benchmarks/scheduling/sat_experiments.py +++ b/benchmarks/scheduling/sat_experiments.py @@ -78,9 +78,7 @@ def graph2sat(g: SimplifiedGraph, workers: list[str]): for worker in workers: coschLoc = model.new_int_var(0, 1, f"{tasks[i]}~{tasks[j]}@{worker}") loc.append(coschLoc) - model.add_multiplication_equality( - coschLoc, [w2t[(tasks[i], worker)], w2t[(tasks[j], worker)]] - ) + model.add_multiplication_equality(coschLoc, [w2t[(tasks[i], worker)], w2t[(tasks[j], worker)]]) # coscheduled variable constraint model.add(sum(loc) == cosch) # respect worker parallelism diff --git a/docs/benchmarking/run1/analysis.ipynb b/docs/benchmarking/run1/analysis.ipynb index 444b8ad0..ea2bb29f 100644 --- a/docs/benchmarking/run1/analysis.ipynb +++ b/docs/benchmarking/run1/analysis.ipynb @@ -33,8 +33,8 @@ "metadata": {}, "outputs": [], "source": [ - "import pandas as pd\n", - "import numpy as np" + "import numpy as np\n", + "import pandas as pd" ] }, { @@ -45,8 +45,8 @@ "outputs": [], "source": [ "def fixWorker(df):\n", - " rows = df['host'] != 'controller'\n", - " df.loc[rows, 'worker'] = df.loc[rows, 'host'] + ':' + df.loc[rows, 'worker'] " + " rows = df[\"host\"] != \"controller\"\n", + " df.loc[rows, \"worker\"] = df.loc[rows, \"host\"] + \":\" + df.loc[rows, \"worker\"]" ] }, { @@ -56,13 +56,13 @@ "metadata": {}, "outputs": [], "source": [ - "f1 = pd.read_json('lA_F_1.jsonl', lines=True)\n", - "f4 = pd.read_json('lA_F_4.jsonl', lines=True)\n", - "m1_4 = pd.read_json('lA_M_1_4.jsonl', lines=True)\n", + "f1 = pd.read_json(\"lA_F_1.jsonl\", lines=True)\n", + "f4 = pd.read_json(\"lA_F_4.jsonl\", lines=True)\n", + "m1_4 = pd.read_json(\"lA_M_1_4.jsonl\", lines=True)\n", "fixWorker(m1_4)\n", - "m4_1 = pd.read_json('lA_M_4_1.jsonl', lines=True)\n", + "m4_1 = pd.read_json(\"lA_M_4_1.jsonl\", lines=True)\n", "fixWorker(m4_1)\n", - "m2_2 = pd.read_json('lA_M_2_2.jsonl', lines=True)\n", + "m2_2 = pd.read_json(\"lA_M_2_2.jsonl\", lines=True)\n", "fixWorker(m2_2)" ] }, @@ -75,47 +75,51 @@ "source": [ "def fixMode(df):\n", " rows = ~df.dataset.isna()\n", - " proj = df[rows & ~df['mode'].isna()].set_index(['dataset', 'worker'])['mode']\n", - " lookup = proj[~proj.index.duplicated(keep='last')]\n", - " return df.set_index(['dataset', 'worker']).drop(columns='mode').join(lookup).reset_index()\n", + " proj = df[rows & ~df[\"mode\"].isna()].set_index([\"dataset\", \"worker\"])[\"mode\"]\n", + " lookup = proj[~proj.index.duplicated(keep=\"last\")]\n", + " return df.set_index([\"dataset\", \"worker\"]).drop(columns=\"mode\").join(lookup).reset_index()\n", + "\n", "\n", "def ensureColumns(df, columns):\n", " for column in columns:\n", - " if not column in df.columns:\n", + " if column not in df.columns:\n", " df = df.assign(**{column: np.nan})\n", " return df\n", - " \n", - " \n", + "\n", + "\n", "def transmitDurations(df):\n", " df = fixMode(df)\n", - " datasets = df[~df.dataset.isna()].drop(columns='task')\n", - " durations = datasets.pivot(index=['dataset', 'worker', 'mode'], columns=['action'], values=['at'])\n", - " durations.columns = [name[1][len('transmit'):] for name in durations.columns]\n", + " datasets = df[~df.dataset.isna()].drop(columns=\"task\")\n", + " durations = datasets.pivot(index=[\"dataset\", \"worker\", \"mode\"], columns=[\"action\"], values=[\"at\"])\n", + " durations.columns = [name[1][len(\"transmit\") :] for name in durations.columns]\n", " durations = durations.reset_index()\n", - " localFix = durations['mode'] == 'local'\n", - " durations.loc[localFix, 'Started'] = durations.loc[localFix, 'Finished']\n", - " durations.loc[localFix, 'Loaded'] = durations.loc[localFix, 'Finished']\n", + " localFix = durations[\"mode\"] == \"local\"\n", + " durations.loc[localFix, \"Started\"] = durations.loc[localFix, \"Finished\"]\n", + " durations.loc[localFix, \"Loaded\"] = durations.loc[localFix, \"Finished\"]\n", " durations = durations.assign(total=durations.Finished - durations.Planned)\n", - " durations = durations.assign(commDelay=durations.Started-durations.Planned)\n", - " durations = durations.assign(loadDelay=durations.Loaded-durations.Started)\n", - " durations = durations.assign(transmitDelay=durations.Finished-durations.Loaded)\n", + " durations = durations.assign(commDelay=durations.Started - durations.Planned)\n", + " durations = durations.assign(loadDelay=durations.Loaded - durations.Started)\n", + " durations = durations.assign(transmitDelay=durations.Finished - durations.Loaded)\n", " return durations\n", "\n", + "\n", "def taskDurations(df):\n", " tasks = df[~df.task.isna()]\n", - " durations = tasks.pivot(index=['task', 'worker'], columns=['action'], values=['at'])\n", - " durations.columns = [name[1][len('task'):] for name in durations.columns]\n", + " durations = tasks.pivot(index=[\"task\", \"worker\"], columns=[\"action\"], values=[\"at\"])\n", + " durations.columns = [name[1][len(\"task\") :] for name in durations.columns]\n", " durations = durations.reset_index()\n", " durations = durations.assign(total=durations.Finished - durations.Planned)\n", - " durations = durations.assign(commDelay = durations.Enqueued - durations.Planned)\n", - " durations = durations.assign(queueDelay = durations.Started - durations.Enqueued)\n", - " durations = durations.assign(runtimes = durations.Finished - durations.Started)\n", - " durations = durations.assign(onWorker = durations.Finished - durations.Enqueued)\n", + " durations = durations.assign(commDelay=durations.Enqueued - durations.Planned)\n", + " durations = durations.assign(queueDelay=durations.Started - durations.Enqueued)\n", + " durations = durations.assign(runtimes=durations.Finished - durations.Started)\n", + " durations = durations.assign(onWorker=durations.Finished - durations.Enqueued)\n", " return durations\n", "\n", + "\n", "def fmn(n):\n", " return f\"{n:.3e}\"\n", "\n", + "\n", "def analyzeTransmits(df):\n", " durations = transmitDurations(df)\n", " print(f\"total transmit duration: {fmn(durations.total.sum())}\")\n", @@ -136,7 +140,8 @@ " print(f\"mean transmit delay: {fmn(remotes.transmitDelay.mean())}\")\n", " print(f\"max transmit delay: {fmn(remotes.transmitDelay.max())}\")\n", " print(\" *** \")\n", - " \n", + "\n", + "\n", "def analyzeTasks(df):\n", " durations = taskDurations(df)\n", " print(f\"total task duration: {fmn(durations.total.sum())}\")\n", @@ -489,9 +494,13 @@ } ], "source": [ - "taskCompareF1F4 = task_f1.set_index(['task'])[['total']].rename(columns={'total': 'total1'}).join(task_f4.set_index(['task'])[['total']].rename(columns={'total': 'total4'}))\n", - "taskCompareF1F4 = taskCompareF1F4.assign(dif = taskCompareF1F4.total4 - taskCompareF1F4.total1)\n", - "taskCompareF1F4 = taskCompareF1F4.assign(rel = taskCompareF1F4.dif / taskCompareF1F4.total4)\n", + "taskCompareF1F4 = (\n", + " task_f1.set_index([\"task\"])[[\"total\"]]\n", + " .rename(columns={\"total\": \"total1\"})\n", + " .join(task_f4.set_index([\"task\"])[[\"total\"]].rename(columns={\"total\": \"total4\"}))\n", + ")\n", + "taskCompareF1F4 = taskCompareF1F4.assign(dif=taskCompareF1F4.total4 - taskCompareF1F4.total1)\n", + "taskCompareF1F4 = taskCompareF1F4.assign(rel=taskCompareF1F4.dif / taskCompareF1F4.total4)\n", "taskCompareF1F4.sort_values(by=\"rel\")" ] }, diff --git a/docs/benchmarking/run1/analysis.py b/docs/benchmarking/run1/analysis.py index d69d2bc0..c8feec91 100644 --- a/docs/benchmarking/run1/analysis.py +++ b/docs/benchmarking/run1/analysis.py @@ -55,12 +55,7 @@ def fixMode(df): rows = ~df.dataset.isna() proj = df[rows & ~df["mode"].isna()].set_index(["dataset", "worker"])["mode"] lookup = proj[~proj.index.duplicated(keep="last")] - return ( - df.set_index(["dataset", "worker"]) - .drop(columns="mode") - .join(lookup) - .reset_index() - ) + return df.set_index(["dataset", "worker"]).drop(columns="mode").join(lookup).reset_index() def ensureColumns(df, columns): @@ -73,9 +68,7 @@ def ensureColumns(df, columns): def transmitDurations(df): df = fixMode(df) datasets = df[~df.dataset.isna()].drop(columns="task") - durations = datasets.pivot( - index=["dataset", "worker", "mode"], columns=["action"], values=["at"] - ) + durations = datasets.pivot(index=["dataset", "worker", "mode"], columns=["action"], values=["at"]) durations.columns = [name[1][len("transmit") :] for name in durations.columns] durations = durations.reset_index() localFix = durations["mode"] == "local" @@ -110,9 +103,7 @@ def analyzeTransmits(df): print(f"total transmit duration: {fmn(durations.total.sum())}") print(" *** ") print(f"mode counts: {durations['mode'].value_counts()}") - print( - f"per-mode transmit duration: {durations[['mode', 'total']].groupby('mode').sum()}" - ) + print(f"per-mode transmit duration: {durations[['mode', 'total']].groupby('mode').sum()}") print(" *** ") print(f"total comm delay: {fmn(durations.commDelay.sum())}") print(f"mean comm delay: {fmn(durations.commDelay.mean())}") @@ -133,9 +124,7 @@ def analyzeTasks(df): durations = taskDurations(df) print(f"total task duration: {fmn(durations.total.sum())}") print(" *** ") - print( - f"total task duration per worker: {durations.groupby('worker').onWorker.agg(['mean', 'sum'])}" - ) + print(f"total task duration per worker: {durations.groupby('worker').onWorker.agg(['mean', 'sum'])}") print(" *** ") print(f"total comm delay: {fmn(durations.commDelay.sum())}") print(f"mean comm delay: {fmn(durations.commDelay.mean())}") @@ -188,12 +177,8 @@ def analyzeTasks(df): .rename(columns={"total": "total1"}) .join(task_f4.set_index(["task"])[["total"]].rename(columns={"total": "total4"})) ) -taskCompareF1F4 = taskCompareF1F4.assign( - dif=taskCompareF1F4.total4 - taskCompareF1F4.total1 -) -taskCompareF1F4 = taskCompareF1F4.assign( - rel=taskCompareF1F4.dif / taskCompareF1F4.total4 -) +taskCompareF1F4 = taskCompareF1F4.assign(dif=taskCompareF1F4.total4 - taskCompareF1F4.total1) +taskCompareF1F4 = taskCompareF1F4.assign(rel=taskCompareF1F4.dif / taskCompareF1F4.total4) taskCompareF1F4.sort_values(by="rel") diff --git a/docs/benchmarking/run2/analysis.ipynb b/docs/benchmarking/run2/analysis.ipynb index 73e216a0..d28369e1 100644 --- a/docs/benchmarking/run2/analysis.ipynb +++ b/docs/benchmarking/run2/analysis.ipynb @@ -27,8 +27,8 @@ "metadata": {}, "outputs": [], "source": [ - "import pandas as pd\n", - "import numpy as np" + "import numpy as np\n", + "import pandas as pd" ] }, { @@ -39,14 +39,15 @@ "outputs": [], "source": [ "def fixWorker(df):\n", - " rows = df['host'] != 'controller'\n", - " df.loc[rows, 'worker'] = df.loc[rows, 'host'] + ':' + df.loc[rows, 'worker'] \n", + " rows = df[\"host\"] != \"controller\"\n", + " df.loc[rows, \"worker\"] = df.loc[rows, \"host\"] + \":\" + df.loc[rows, \"worker\"]\n", + "\n", "\n", "def readAll(base):\n", " c = pd.read_json(f\"{base}.controller.jsonl\", lines=True)\n", " t = pd.read_json(f\"{base}.tasks.jsonl\", lines=True)\n", " d = pd.read_json(f\"{base}.datasets.jsonl\", lines=True)\n", - " if 'M' in base:\n", + " if \"M\" in base:\n", " fixWorker(t)\n", " if d.shape[0] > 0:\n", " fixWorker(d)\n", @@ -60,15 +61,15 @@ "metadata": {}, "outputs": [], "source": [ - "f1c, f1t, f1d = readAll('lA_F_1')\n", - "f4c, f4t, f4d = readAll('lA_F_4')\n", - "m14c, m14t, m14d = readAll('lA_M_1_4')\n", - "m41c, m41t, m41d = readAll('lA_M_4_1')\n", - "m22c, m22t, m22d = readAll('lA_M_2_2')\n", + "f1c, f1t, f1d = readAll(\"lA_F_1\")\n", + "f4c, f4t, f4d = readAll(\"lA_F_4\")\n", + "m14c, m14t, m14d = readAll(\"lA_M_1_4\")\n", + "m41c, m41t, m41d = readAll(\"lA_M_4_1\")\n", + "m22c, m22t, m22d = readAll(\"lA_M_2_2\")\n", "# after making the transmit non-blocking\n", - "n14c, n14t, n14d = readAll('lB_M_1_4')\n", - "n41c, n41t, n41d = readAll('lB_M_4_1')\n", - "n22c, n22t, n22d = readAll('lB_M_2_2')" + "n14c, n14t, n14d = readAll(\"lB_M_1_4\")\n", + "n41c, n41t, n41d = readAll(\"lB_M_4_1\")\n", + "n22c, n22t, n22d = readAll(\"lB_M_2_2\")" ] }, { @@ -84,53 +85,59 @@ "source": [ "def fixMode(df):\n", " rows = ~df.dataset.isna()\n", - " proj = df[rows & ~df['mode'].isna()].set_index(['dataset', 'worker'])['mode']\n", - " lookup = proj[~proj.index.duplicated(keep='last')]\n", - " return df.set_index(['dataset', 'worker']).drop(columns='mode').join(lookup).reset_index()\n", + " proj = df[rows & ~df[\"mode\"].isna()].set_index([\"dataset\", \"worker\"])[\"mode\"]\n", + " lookup = proj[~proj.index.duplicated(keep=\"last\")]\n", + " return df.set_index([\"dataset\", \"worker\"]).drop(columns=\"mode\").join(lookup).reset_index()\n", + "\n", "\n", - "def fmn(n): # TODO set some central\n", + "def fmn(n): # TODO set some central\n", " return f\"{n:.3e}\"\n", "\n", + "\n", "def ensureColumns(df, columns):\n", " for column in columns:\n", - " if not column in df.columns:\n", + " if column not in df.columns:\n", " df = df.assign(**{column: np.nan})\n", " return df\n", "\n", + "\n", "def analyzeController(df):\n", " print(f\"phases: {df.shape[0]}\")\n", " print(f\"total waits duration: {fmn(df.waitDuration.sum())}\")\n", " print(f\"total act duration: {fmn(df.actDuration.sum())}\")\n", " print(f\"transmits issued: {df.actionsTransmit.sum()}, transmits received: {df.eventsTransmited.sum()}\")\n", " print(f\"busy-during-wait: {fmn((df.busyWorkers * df.waitDuration).sum())}\")\n", - " \n", + "\n", + "\n", "def transmitDurations(df):\n", " datasets = fixMode(df)\n", - " durations = datasets.pivot(index=['dataset', 'worker', 'mode'], columns=['action'], values=['at'])\n", - " durations.columns = [name[1][len('transmit'):] for name in durations.columns]\n", + " durations = datasets.pivot(index=[\"dataset\", \"worker\", \"mode\"], columns=[\"action\"], values=[\"at\"])\n", + " durations.columns = [name[1][len(\"transmit\") :] for name in durations.columns]\n", " durations = durations.reset_index()\n", - " localFix = durations['mode'] == 'local'\n", - " durations.loc[localFix, 'Started'] = durations.loc[localFix, 'Finished']\n", - " durations.loc[localFix, 'Loaded'] = durations.loc[localFix, 'Finished']\n", + " localFix = durations[\"mode\"] == \"local\"\n", + " durations.loc[localFix, \"Started\"] = durations.loc[localFix, \"Finished\"]\n", + " durations.loc[localFix, \"Loaded\"] = durations.loc[localFix, \"Finished\"]\n", " durations = durations.assign(total=durations.Finished - durations.Planned)\n", - " durations = durations.assign(commDelay=durations.Started-durations.Planned)\n", - " durations = durations.assign(loadDelay=durations.Loaded-durations.Started)\n", - " durations = durations.assign(transmitDelay=durations.Finished-durations.Loaded)\n", + " durations = durations.assign(commDelay=durations.Started - durations.Planned)\n", + " durations = durations.assign(loadDelay=durations.Loaded - durations.Started)\n", + " durations = durations.assign(transmitDelay=durations.Finished - durations.Loaded)\n", " return durations\n", "\n", + "\n", "def taskDurations(df):\n", " tasks = df[~df.task.isna()]\n", - " durations = tasks.pivot(index=['task', 'worker'], columns=['action'], values=['at'])\n", - " durations.columns = [name[1][len('task'):] for name in durations.columns]\n", + " durations = tasks.pivot(index=[\"task\", \"worker\"], columns=[\"action\"], values=[\"at\"])\n", + " durations.columns = [name[1][len(\"task\") :] for name in durations.columns]\n", " durations = durations.reset_index()\n", " durations = durations.assign(total=durations.Finished - durations.Planned)\n", - " durations = durations.assign(commDelay = durations.Enqueued - durations.Planned)\n", - " durations = durations.assign(queueDelay = durations.Started - durations.Enqueued)\n", - " durations = durations.assign(loadDelay = durations.Loaded - durations.Started)\n", - " durations = durations.assign(runtimes = durations.Finished - durations.Loaded)\n", - " durations = durations.assign(onWorker = durations.Finished - durations.Enqueued)\n", + " durations = durations.assign(commDelay=durations.Enqueued - durations.Planned)\n", + " durations = durations.assign(queueDelay=durations.Started - durations.Enqueued)\n", + " durations = durations.assign(loadDelay=durations.Loaded - durations.Started)\n", + " durations = durations.assign(runtimes=durations.Finished - durations.Loaded)\n", + " durations = durations.assign(onWorker=durations.Finished - durations.Enqueued)\n", " return durations\n", "\n", + "\n", "def analyzeTransmits(df):\n", " durations = transmitDurations(df)\n", " print(f\"total transmit duration: {fmn(durations.total.sum())}\")\n", @@ -151,7 +158,8 @@ " print(f\"mean transmit delay: {fmn(remotes.transmitDelay.mean())}\")\n", " print(f\"max transmit delay: {fmn(remotes.transmitDelay.max())}\")\n", " print(\" *** \")\n", - " \n", + "\n", + "\n", "def analyzeTasks(df):\n", " durations = taskDurations(df)\n", " print(f\"total task duration: {fmn(durations.total.sum())}\")\n", diff --git a/docs/benchmarking/run2/analysis.py b/docs/benchmarking/run2/analysis.py index 1fd752c0..c249ffee 100644 --- a/docs/benchmarking/run2/analysis.py +++ b/docs/benchmarking/run2/analysis.py @@ -62,12 +62,7 @@ def fixMode(df): rows = ~df.dataset.isna() proj = df[rows & ~df["mode"].isna()].set_index(["dataset", "worker"])["mode"] lookup = proj[~proj.index.duplicated(keep="last")] - return ( - df.set_index(["dataset", "worker"]) - .drop(columns="mode") - .join(lookup) - .reset_index() - ) + return df.set_index(["dataset", "worker"]).drop(columns="mode").join(lookup).reset_index() def fmn(n): # TODO set some central @@ -85,17 +80,13 @@ def analyzeController(df): print(f"phases: {df.shape[0]}") print(f"total waits duration: {fmn(df.waitDuration.sum())}") print(f"total act duration: {fmn(df.actDuration.sum())}") - print( - f"transmits issued: {df.actionsTransmit.sum()}, transmits received: {df.eventsTransmited.sum()}" - ) + print(f"transmits issued: {df.actionsTransmit.sum()}, transmits received: {df.eventsTransmited.sum()}") print(f"busy-during-wait: {fmn((df.busyWorkers * df.waitDuration).sum())}") def transmitDurations(df): datasets = fixMode(df) - durations = datasets.pivot( - index=["dataset", "worker", "mode"], columns=["action"], values=["at"] - ) + durations = datasets.pivot(index=["dataset", "worker", "mode"], columns=["action"], values=["at"]) durations.columns = [name[1][len("transmit") :] for name in durations.columns] durations = durations.reset_index() localFix = durations["mode"] == "local" @@ -127,9 +118,7 @@ def analyzeTransmits(df): print(f"total transmit duration: {fmn(durations.total.sum())}") print(" *** ") print(f"mode counts: {durations['mode'].value_counts()}") - print( - f"per-mode transmit duration: {durations[['mode', 'total']].groupby('mode').sum()}" - ) + print(f"per-mode transmit duration: {durations[['mode', 'total']].groupby('mode').sum()}") print(" *** ") print(f"total comm delay: {fmn(durations.commDelay.sum())}") print(f"mean comm delay: {fmn(durations.commDelay.mean())}") @@ -150,9 +139,7 @@ def analyzeTasks(df): durations = taskDurations(df) print(f"total task duration: {fmn(durations.total.sum())}") print(" *** ") - print( - f"total task duration per worker: {durations.groupby('worker').onWorker.agg(['mean', 'sum'])}" - ) + print(f"total task duration per worker: {durations.groupby('worker').onWorker.agg(['mean', 'sum'])}") print(" *** ") print(f"total comm delay: {fmn(durations.commDelay.sum())}") print(f"mean comm delay: {fmn(durations.commDelay.mean())}") diff --git a/docs/benchmarking/run3/tasklanes.ipynb b/docs/benchmarking/run3/tasklanes.ipynb index 9a9b31a4..e6ffcad3 100644 --- a/docs/benchmarking/run3/tasklanes.ipynb +++ b/docs/benchmarking/run3/tasklanes.ipynb @@ -349,11 +349,9 @@ } ], "source": [ - "from cascade.benchmarks.reporting import logParse\n", - "import pandas as pd\n", - "from bokeh.io import curdoc, show\n", + "from bokeh.io import curdoc, output_notebook, show\n", "from bokeh.models import ColumnDataSource, Grid, HBar, LinearAxis, Plot, VSpan\n", - "from bokeh.io import output_notebook\n", + "from cascade.benchmarks.reporting import logParse\n", "\n", "output_notebook()" ] @@ -366,75 +364,78 @@ "outputs": [], "source": [ "def plotTaskLane(data: dict, scale, width):\n", - " Td = data['task_durations']\n", - " nc = ['planned', 'enqueued', 'started', 'loaded', 'computed', 'published', 'completed']\n", - " df = (Td[nc]/scale).astype(int)\n", + " Td = data[\"task_durations\"]\n", + " nc = [\"planned\", \"enqueued\", \"started\", \"loaded\", \"computed\", \"published\", \"completed\"]\n", + " df = (Td[nc] / scale).astype(int)\n", " zero = df.planned.min()\n", " df = df - zero\n", " df = df.assign(worker=Td.worker)\n", "\n", " workerToLane = {e: i for i, e in enumerate(Td.worker.drop_duplicates().sort_values())}\n", - " print(workerToLane) # TODO use the labels in the if instead\n", + " print(workerToLane) # TODO use the labels in the if instead\n", "\n", " plot = Plot(\n", - " title=None, width=width, height=500,\n", - " min_border=0, toolbar_location=None,\n", - " ) # TODO derive width from data\n", + " title=None,\n", + " width=width,\n", + " height=500,\n", + " min_border=0,\n", + " toolbar_location=None,\n", + " ) # TODO derive width from data\n", "\n", " def boxTask(left, right, color):\n", - " source = ColumnDataSource(dict(y=df.worker.map(workerToLane), left=left, right=right)) \n", + " source = ColumnDataSource(dict(y=df.worker.map(workerToLane), left=left, right=right))\n", " glyph = HBar(y=\"y\", right=\"right\", left=\"left\", height=0.5, fill_color=color)\n", " plot.add_glyph(source, glyph)\n", "\n", " def boxTransmit(worker, left, right, color):\n", - " source = ColumnDataSource(dict(y=worker.map(workerToLane) - 0.5, left=left, right=right)) \n", + " source = ColumnDataSource(dict(y=worker.map(workerToLane) - 0.5, left=left, right=right))\n", " glyph = HBar(y=\"y\", right=\"right\", left=\"left\", height=0.25, fill_color=color)\n", - " plot.add_glyph(source, glyph) \n", - " \n", + " plot.add_glyph(source, glyph)\n", + "\n", " def barController(df, action, color):\n", " df = df.query(f\"action == '{action}'\")\n", - " df = (df[['at']] / scale).astype(int) - zero\n", + " df = (df[[\"at\"]] / scale).astype(int) - zero\n", " df = df.assign(width=2)\n", - " source = ColumnDataSource(dict(x=df['at'], width=df.width))\n", + " source = ColumnDataSource(dict(x=df[\"at\"], width=df.width))\n", " glyph = VSpan(x=\"x\", line_width=\"width\", line_color=color)\n", " plot.add_glyph(source, glyph)\n", "\n", - " Ctrl = data['controller']\n", - " barController(Ctrl, \"plan\", '#00aa00')\n", - " barController(Ctrl, \"act\", '#0000aa')\n", - " barController(Ctrl, \"wait\", '#aa0000')\n", - " barController(Ctrl, \"shutdown\", '#000000')\n", - " \n", - " boxTask(df.planned, df.enqueued, '#111111')\n", - " boxTask(df.enqueued, df.started, '#dd1111')\n", - " boxTask(df.started, df.loaded, '#1111dd')\n", - " boxTask(df.loaded, df.computed, '#11dd11')\n", - " boxTask(df.computed, df.published, '#1111dd')\n", - " boxTask(df.published, df.completed, '#444444')\n", + " Ctrl = data[\"controller\"]\n", + " barController(Ctrl, \"plan\", \"#00aa00\")\n", + " barController(Ctrl, \"act\", \"#0000aa\")\n", + " barController(Ctrl, \"wait\", \"#aa0000\")\n", + " barController(Ctrl, \"shutdown\", \"#000000\")\n", + "\n", + " boxTask(df.planned, df.enqueued, \"#111111\")\n", + " boxTask(df.enqueued, df.started, \"#dd1111\")\n", + " boxTask(df.started, df.loaded, \"#1111dd\")\n", + " boxTask(df.loaded, df.computed, \"#11dd11\")\n", + " boxTask(df.computed, df.published, \"#1111dd\")\n", + " boxTask(df.published, df.completed, \"#444444\")\n", "\n", - " Rd = data['transmit_durations']\n", - " nc = ['planned', 'started', 'loaded', 'received', 'unloaded', 'completed']\n", - " df = (Rd[nc]/scale).astype(int)\n", + " Rd = data[\"transmit_durations\"]\n", + " nc = [\"planned\", \"started\", \"loaded\", \"received\", \"unloaded\", \"completed\"]\n", + " df = (Rd[nc] / scale).astype(int)\n", " df = df - zero\n", " df = df.assign(target=Rd.target, source=Rd.source)\n", - " boxTransmit(df.target, df.planned, df.received, '#111111') # target waiting\n", - " boxTransmit(df.target, df.received, df.unloaded, '#1111dd') # target memcpy\n", - " boxTransmit(df.target, df.unloaded, df.completed, '#444444') # target callback\n", - " boxTransmit(df.source, df.planned, df.started, '#111111') # ctrl2source comm delay\n", - " boxTransmit(df.source, df.started, df.loaded, '#1111dd') # source memcpy\n", - " boxTransmit(df.source, df.loaded, df.received, '#444444') # source memcpy + network\n", - " \n", + " boxTransmit(df.target, df.planned, df.received, \"#111111\") # target waiting\n", + " boxTransmit(df.target, df.received, df.unloaded, \"#1111dd\") # target memcpy\n", + " boxTransmit(df.target, df.unloaded, df.completed, \"#444444\") # target callback\n", + " boxTransmit(df.source, df.planned, df.started, \"#111111\") # ctrl2source comm delay\n", + " boxTransmit(df.source, df.started, df.loaded, \"#1111dd\") # source memcpy\n", + " boxTransmit(df.source, df.loaded, df.received, \"#444444\") # source memcpy + network\n", + "\n", " xaxis = LinearAxis()\n", - " plot.add_layout(xaxis, 'below')\n", - " \n", + " plot.add_layout(xaxis, \"below\")\n", + "\n", " yaxis = LinearAxis()\n", - " plot.add_layout(yaxis, 'left')\n", - " \n", + " plot.add_layout(yaxis, \"left\")\n", + "\n", " plot.add_layout(Grid(dimension=0, ticker=xaxis.ticker))\n", " plot.add_layout(Grid(dimension=1, ticker=yaxis.ticker))\n", - " \n", + "\n", " curdoc().add_root(plot)\n", - " \n", + "\n", " return show(plot)" ] }, diff --git a/docs/benchmarking/run3/tasklanes.py b/docs/benchmarking/run3/tasklanes.py index d9cb23f5..efb7b0bf 100644 --- a/docs/benchmarking/run3/tasklanes.py +++ b/docs/benchmarking/run3/tasklanes.py @@ -6,7 +6,6 @@ from bokeh.io import curdoc, output_notebook, show from bokeh.models import ColumnDataSource, Grid, HBar, LinearAxis, Plot, VSpan - from cascade.benchmarks.reporting import logParse output_notebook() @@ -31,9 +30,7 @@ def plotTaskLane(data: dict, scale, width): df = df - zero df = df.assign(worker=Td.worker) - workerToLane = { - e: i for i, e in enumerate(Td.worker.drop_duplicates().sort_values()) - } + workerToLane = {e: i for i, e in enumerate(Td.worker.drop_duplicates().sort_values())} print(workerToLane) # TODO use the labels in the if instead plot = Plot( @@ -45,16 +42,12 @@ def plotTaskLane(data: dict, scale, width): ) # TODO derive width from data def boxTask(left, right, color): - source = ColumnDataSource( - dict(y=df.worker.map(workerToLane), left=left, right=right) - ) + source = ColumnDataSource(dict(y=df.worker.map(workerToLane), left=left, right=right)) glyph = HBar(y="y", right="right", left="left", height=0.5, fill_color=color) plot.add_glyph(source, glyph) def boxTransmit(worker, left, right, color): - source = ColumnDataSource( - dict(y=worker.map(workerToLane) - 0.5, left=left, right=right) - ) + source = ColumnDataSource(dict(y=worker.map(workerToLane) - 0.5, left=left, right=right)) glyph = HBar(y="y", right="right", left="left", height=0.25, fill_color=color) plot.add_glyph(source, glyph) diff --git a/docs/ensemble_percentiles.ipynb b/docs/ensemble_percentiles.ipynb index 17553dd6..2c4b56c2 100644 --- a/docs/ensemble_percentiles.ipynb +++ b/docs/ensemble_percentiles.ipynb @@ -19,15 +19,15 @@ "metadata": {}, "outputs": [], "source": [ - "import os\n", "import logging as log\n", + "import os\n", "\n", "import numpy as np\n", - "import xarray as xr\n", "import pandas as pd\n", + "import xarray as xr\n", + "from cascade.fluent import Node, Payload, from_source\n", "\n", - "from cascade import Cascade\n", - "from cascade.fluent import from_source, Payload, Node" + "from cascade import Cascade" ] }, { @@ -39,33 +39,39 @@ "def create_test_data_files(n_members=3, n_leadtimes=7, shape=(4500, 5000)):\n", " \"\"\"Create a test dataset with random data.\"\"\"\n", " import tempfile\n", + "\n", " data = np.random.rand(n_members, n_leadtimes, *shape) * 100\n", " coords = {\n", - " 'member': np.arange(n_members),\n", - " 'leadtime': pd.date_range(\"20240419T1200\", freq='h', periods=n_leadtimes),\n", - " 'y': np.linspace(-90, 90, shape[0]),\n", - " 'x': np.linspace(-180, 180, shape[1]),\n", + " \"member\": np.arange(n_members),\n", + " \"leadtime\": pd.date_range(\"20240419T1200\", freq=\"h\", periods=n_leadtimes),\n", + " \"y\": np.linspace(-90, 90, shape[0]),\n", + " \"x\": np.linspace(-180, 180, shape[1]),\n", " }\n", " ds = xr.Dataset(\n", " data_vars={\n", - " 'rainfall': (('member', 'leadtime', 'y', 'x'), data),\n", + " \"rainfall\": ((\"member\", \"leadtime\", \"y\", \"x\"), data),\n", " },\n", " coords=coords,\n", - " attrs={'source': 'test', 'description': 'random data'}\n", + " attrs={\"source\": \"test\", \"description\": \"random data\"},\n", " )\n", " tempdir = tempfile.mkdtemp()\n", " outpaths, datasets = [], []\n", " for mem in range(n_members):\n", - " outpaths += [os.path.join(tempdir, f'rainfall_ENS{mem:02d}.nc')]\n", - " datasets += [ds.sel(member=mem).drop_vars('member')]\n", + " outpaths += [os.path.join(tempdir, f\"rainfall_ENS{mem:02d}.nc\")]\n", + " datasets += [ds.sel(member=mem).drop_vars(\"member\")]\n", " xr.save_mfdataset(datasets, outpaths, compute=True)\n", " return outpaths\n", "\n", + "\n", "def write_netcdf(\n", - " nparray:np.ndarray, filename:str,\n", - " dims:list, coords:np.ndarray,\n", - " varname:str = 'rainfall', attrs:dict = {}, **kwargs\n", - " ):\n", + " nparray: np.ndarray,\n", + " filename: str,\n", + " dims: list,\n", + " coords: np.ndarray,\n", + " varname: str = \"rainfall\",\n", + " attrs: dict = {},\n", + " **kwargs,\n", + "):\n", "\n", " xr.DataArray(\n", " nparray,\n", @@ -75,9 +81,10 @@ " attrs=attrs,\n", " ).to_netcdf(filename, **kwargs)\n", "\n", + "\n", "def compute_percentile(da: xr.DataArray, q: float | np.ndarray, **kwargs):\n", - " log.info(f'input array {da}')\n", - " return da.quantile(q, **kwargs)\n" + " log.info(f\"input array {da}\")\n", + " return da.quantile(q, **kwargs)" ] }, { @@ -96,10 +103,10 @@ "outputs": [], "source": [ "# replace this by a list of actual files and test on your own datasets\n", - "members=3\n", - "n_steps=7\n", - "OUTFILE='rainfall_perc80.nc'\n", - "quantiles=0.8\n", + "members = 3\n", + "n_steps = 7\n", + "OUTFILE = \"rainfall_perc80.nc\"\n", + "quantiles = 0.8\n", "file_list = create_test_data_files(members, n_steps)" ] }, @@ -120,23 +127,20 @@ "source": [ "payloads = []\n", "for fname in file_list:\n", - " payloads += [\n", - " Payload(\n", - " xr.open_dataarray,\n", - " [fname],\n", - " dict(mask_and_scale=False)\n", - " )\n", - " ]\n", + " payloads += [Payload(xr.open_dataarray, [fname], dict(mask_and_scale=False))]\n", "inputs = (\n", " from_source(\n", " payloads,\n", - " dims=['member'],\n", + " dims=[\"member\"],\n", " )\n", " # we split the file over the forecast time steps\n", " .expand(\n", - " dim='step', dim_size=n_steps, internal_dim=0, axis=0,\n", + " dim=\"step\",\n", + " dim_size=n_steps,\n", + " internal_dim=0,\n", + " axis=0,\n", " )\n", - ")\n" + ")" ] }, { @@ -152,24 +156,21 @@ "metadata": {}, "outputs": [], "source": [ - "\n", "prev_node = None\n", "for step in range(n_steps):\n", " # we first select the nodes from different ensemble members and same time step\n", - " step_nodes = inputs.select({'step': step}, drop=False)\n", + " step_nodes = inputs.select({\"step\": step}, drop=False)\n", " # then we stack them along a member dimension\n", " res = (\n", " step_nodes.stack(\n", - " dim='member',\n", + " dim=\"member\",\n", " keep_dim=False,\n", " axis=0,\n", - " backend_kwargs=dict(dim='member'),\n", + " backend_kwargs=dict(dim=\"member\"),\n", " )\n", " # here we define the actual computation\n", " .map(\n", - " Payload(\n", - " compute_percentile,\n", - " kwargs=dict(q=quantiles, dim='member', skipna=False)),\n", + " Payload(compute_percentile, kwargs=dict(q=quantiles, dim=\"member\", skipna=False)),\n", " )\n", " )\n", " if prev_node is None:\n", @@ -177,8 +178,8 @@ " else:\n", " prev_node = prev_node.join(\n", " other_action=res,\n", - " dim='step',\n", - " )\n" + " dim=\"step\",\n", + " )" ] }, { @@ -194,38 +195,26 @@ "metadata": {}, "outputs": [], "source": [ - "\n", "# output template\n", - "tmplt_da = (\n", - " xr.open_dataset(file_list[0], chunks='auto')['rainfall']\n", - ")\n", + "tmplt_da = xr.open_dataset(file_list[0], chunks=\"auto\")[\"rainfall\"]\n", "coords = tmplt_da.coords\n", "dims = tmplt_da.dims\n", "attrs = tmplt_da.attrs\n", "\n", - "actions = (\n", - " prev_node\n", - " .stack(\n", - " dim='step',\n", - " keep_dim=False,\n", - " axis=0,\n", - " backend_kwargs=dict(dim='leadtime'),\n", - " )\n", - " .map(\n", - " Payload(\n", - " write_netcdf,\n", - " [Node.input_name(0)],\n", - " kwargs=dict(\n", - " dims=dims,\n", - " attrs=attrs,\n", - " coords=coords,\n", - " varname='rainfall',\n", - " filename=OUTFILE,\n", - " mode='w', engine='netcdf4'\n", - " ),\n", - " )\n", + "actions = prev_node.stack(\n", + " dim=\"step\",\n", + " keep_dim=False,\n", + " axis=0,\n", + " backend_kwargs=dict(dim=\"leadtime\"),\n", + ").map(\n", + " Payload(\n", + " write_netcdf,\n", + " [Node.input_name(0)],\n", + " kwargs=dict(\n", + " dims=dims, attrs=attrs, coords=coords, varname=\"rainfall\", filename=OUTFILE, mode=\"w\", engine=\"netcdf4\"\n", + " ),\n", " )\n", - ")\n" + ")" ] }, { @@ -241,9 +230,8 @@ "metadata": {}, "outputs": [], "source": [ - "\n", "cascade = Cascade.from_actions([actions])\n", - "cascade.visualise(\"cascadegraph_percentile.html\", cdn_resources='in_line')" + "cascade.visualise(\"cascadegraph_percentile.html\", cdn_resources=\"in_line\")" ] }, { @@ -254,7 +242,8 @@ "source": [ "%%time\n", "\n", - "from cascade.executors.dask import DaskLocalExecutor \n", + "from cascade.executors.dask import DaskLocalExecutor\n", + "\n", "if os.path.exists(OUTFILE):\n", " os.remove(OUTFILE)\n", "\n", @@ -277,24 +266,24 @@ "source": [ "ds = xr.open_mfdataset(\n", " file_list,\n", - " concat_dim='member',\n", - " combine='nested',\n", + " concat_dim=\"member\",\n", + " combine=\"nested\",\n", " mask_and_scale=False,\n", - " chunks={'leadtime': 1},\n", + " chunks={\"leadtime\": 1},\n", ")\n", - "ds = ds.chunk({'member': -1})\n", + "ds = ds.chunk({\"member\": -1})\n", "\n", "res = list()\n", "for step in range(7):\n", - " da = ds['rainfall'].isel(leadtime=step).transpose('member', 'y', 'x')\n", - " perc = da.quantile(q=.80, dim='member', skipna=False)\n", + " da = ds[\"rainfall\"].isel(leadtime=step).transpose(\"member\", \"y\", \"x\")\n", + " perc = da.quantile(q=0.80, dim=\"member\", skipna=False)\n", " res.append(perc)\n", "ref = (\n", - " xr.combine_nested(res, concat_dim='leadtime')\n", - " .assign_coords({'leadtime':coords['leadtime']})\n", - " .drop_vars(['quantile'])\n", + " xr.combine_nested(res, concat_dim=\"leadtime\")\n", + " .assign_coords({\"leadtime\": coords[\"leadtime\"]})\n", + " .drop_vars([\"quantile\"])\n", ")\n", - "ref.to_netcdf('dask_results.nc')\n", + "ref.to_netcdf(\"dask_results.nc\")\n", "ref" ] }, @@ -304,7 +293,7 @@ "metadata": {}, "outputs": [], "source": [ - "ref.data.visualize('daskgraph_percentile.png') # you may need to install graphviz to make this work" + "ref.data.visualize(\"daskgraph_percentile.png\") # you may need to install graphviz to make this work" ] }, { @@ -313,9 +302,10 @@ "metadata": {}, "outputs": [], "source": [ - "%%time \n", + "%%time\n", "\n", "from dask.diagnostics import ProgressBar\n", + "\n", "with ProgressBar():\n", " ref.compute()" ] @@ -336,7 +326,7 @@ "metadata": {}, "outputs": [], "source": [ - "ref = xr.open_dataset('dask_results.nc', mask_and_scale=False)" + "ref = xr.open_dataset(\"dask_results.nc\", mask_and_scale=False)" ] }, { diff --git a/docs/examples/arrayapi.ipynb b/docs/examples/arrayapi.ipynb index 5d1775eb..108a995d 100644 --- a/docs/examples/arrayapi.ipynb +++ b/docs/examples/arrayapi.ipynb @@ -29,12 +29,13 @@ }, "outputs": [], "source": [ - "import numpy as np \n", "import functools\n", + "\n", + "import numpy as np\n", "from cascade.fluent import from_source\n", "\n", "payload = functools.partial(np.random.rand, 2, 3)\n", - "start = from_source(np.full((4, 5), payload), coords={\"x\": list(range(4)), \"y\": 3*np.array(range(5))})\n", + "start = from_source(np.full((4, 5), payload), coords={\"x\": list(range(4)), \"y\": 3 * np.array(range(5))})\n", "start" ] }, @@ -149,7 +150,7 @@ }, "outputs": [], "source": [ - "# Or we can scale the array in each node by a different value \n", + "# Or we can scale the array in each node by a different value\n", "mapped = expanded.map([lambda x, a=a: x * a for a in range(1, 4)])" ] }, @@ -177,11 +178,13 @@ "source": [ "from cascade.fluent import Action\n", "\n", + "\n", "def _example_transform(action: Action, threshold: float) -> Action:\n", " ret = action.map(lambda x: x if x > threshold else 0)\n", " ret._add_dimension(\"threshold\", threshold)\n", " return ret\n", "\n", + "\n", "mapped.transform(_example_transform, [(0,), (1,), (10,)], \"threshold\").nodes" ] }, @@ -207,9 +210,9 @@ }, "outputs": [], "source": [ - "import numpy as np \n", - "import xarray as xr\n", "import functools\n", + "\n", + "import numpy as np\n", "from cascade.fluent import from_source\n", "\n", "payload = functools.partial(np.random.rand, 2, 3)\n", @@ -226,8 +229,7 @@ "outputs": [], "source": [ "graph = (\n", - " initial_action\n", - " .mean(\"x\")\n", + " initial_action.mean(\"x\")\n", " .min(\"y\")\n", " .expand(\"z\", internal_dim=1, dim_size=3, axis=0)\n", " .map([lambda x, a=a: x * a for a in range(1, 4)])\n", @@ -243,7 +245,7 @@ }, "outputs": [], "source": [ - "from cascade.visualise import visualise \n", + "from cascade.visualise import visualise\n", "\n", "visualise(graph, \"graph.html\")" ] @@ -328,20 +330,20 @@ }, "outputs": [], "source": [ - "import numpy as np\n", - "import cupy as cp \n", - "import xarray as xr\n", "import functools\n", + "\n", + "import cupy as cp\n", + "import numpy as np\n", "from cascade.fluent import from_source\n", "\n", "payload = functools.partial(cp.random.rand, 2, 3)\n", "graph = (\n", - " from_source(np.full((4, 5), payload), coords={\"x\": list(range(4)), \"y\": 3*np.array(range(5))})\n", + " from_source(np.full((4, 5), payload), coords={\"x\": list(range(4)), \"y\": 3 * np.array(range(5))})\n", " .mean(\"x\")\n", " .min(\"y\")\n", " .expand(\"z\", internal_dim=1, dim_size=3, axis=0)\n", " .map([lambda x, a=a: x * a for a in range(1, 4)])\n", - " .map(lambda x: x.get()) # Move to CPU\n", + " .map(lambda x: x.get()) # Move to CPU\n", " .graph()\n", ")" ] @@ -355,9 +357,10 @@ "outputs": [], "source": [ "import os\n", + "\n", "from cascade.cascade import Cascade\n", "\n", - "os.environ[\"DASK_LOGGING__DISTRIBUTED\"]=\"debug\"\n", + "os.environ[\"DASK_LOGGING__DISTRIBUTED\"] = \"debug\"\n", "cas = Cascade(graph)\n", "cas.execute()" ] diff --git a/docs/examples/xarray.ipynb b/docs/examples/xarray.ipynb index 73960249..867b39c0 100644 --- a/docs/examples/xarray.ipynb +++ b/docs/examples/xarray.ipynb @@ -29,7 +29,7 @@ "source": [ "import xarray as xr\n", "\n", - "ds = xr.load_dataset('rasm.nc')\n", + "ds = xr.load_dataset(\"rasm.nc\")\n", "print(ds)" ] }, @@ -42,6 +42,7 @@ "outputs": [], "source": [ "import functools\n", + "\n", "from cascade.fluent import from_source\n", "\n", "graph = (\n", diff --git a/docs/tutorials/cascade-job_building/t00_execute.py b/docs/tutorials/cascade-job_building/t00_execute.py index 18b9b952..17300e9f 100644 --- a/docs/tutorials/cascade-job_building/t00_execute.py +++ b/docs/tutorials/cascade-job_building/t00_execute.py @@ -4,6 +4,7 @@ from typing import Any from cascade.benchmarks.util import run_locally + from cascade.low.core import DatasetId, JobInstance diff --git a/docs/tutorials/cascade-job_building/t00_generate.py b/docs/tutorials/cascade-job_building/t00_generate.py index 70ebcace..36ac7500 100644 --- a/docs/tutorials/cascade-job_building/t00_generate.py +++ b/docs/tutorials/cascade-job_building/t00_generate.py @@ -15,8 +15,5 @@ def generate_data() -> xr.Dataset: "temper": np.random.rand(10, 10, 24), } return xr.Dataset( - { - key: xr.DataArray(value, dims=tuple(coords.keys()), coords=coords) - for key, value in variables.items() - } + {key: xr.DataArray(value, dims=tuple(coords.keys()), coords=coords) for key, value in variables.items()} ) diff --git a/docs/tutorials/cascade-job_building/t01_low.py b/docs/tutorials/cascade-job_building/t01_low.py index 5bcfd50b..4ab478ca 100644 --- a/docs/tutorials/cascade-job_building/t01_low.py +++ b/docs/tutorials/cascade-job_building/t01_low.py @@ -60,15 +60,9 @@ def task3_callable(a: np.ndarray) -> np.ndarray: # one task definition can be used multiple times with different static parameters, # so theres one extra wrapping -task1_instance = TaskInstance( - definition=task1_definition, static_input_kw={}, static_input_ps={} -) -task2_instance = TaskInstance( - definition=task2_definition, static_input_kw={}, static_input_ps={} -) -task3_instance = TaskInstance( - definition=task3_definition, static_input_kw={}, static_input_ps={} -) +task1_instance = TaskInstance(definition=task1_definition, static_input_kw={}, static_input_ps={}) +task2_instance = TaskInstance(definition=task2_definition, static_input_kw={}, static_input_ps={}) +task3_instance = TaskInstance(definition=task3_definition, static_input_kw={}, static_input_ps={}) # now we glue tasks together edge1to2 = Task2TaskEdge( diff --git a/docs/tutorials/cascade-job_building/t03_custom.py b/docs/tutorials/cascade-job_building/t03_custom.py index 1e320c5a..6df96b03 100644 --- a/docs/tutorials/cascade-job_building/t03_custom.py +++ b/docs/tutorials/cascade-job_building/t03_custom.py @@ -65,22 +65,16 @@ def _validate(i: xr.Dataset, dims: list[str], variables: list[str]) -> xr.Datase assert set(variables) == set(i.keys()) return i - def __init__( - self, kallable: Callable, dims: list[str], variables: list[str] - ) -> Self: + def __init__(self, kallable: Callable, dims: list[str], variables: list[str]) -> Self: self.dims = dims self.variables = variables # note that now we have two tasks here! One that reads the data, another that validates self.implementation = ( JobBuilder() - .with_node( - "read", TaskBuilder.from_callable(kallable, environment=["xarray"]) - ) + .with_node("read", TaskBuilder.from_callable(kallable, environment=["xarray"])) .with_node( "validate", - TaskBuilder.from_callable(Source._validate).with_values( - dims=dims, variables=variables - ), + TaskBuilder.from_callable(Source._validate).with_values(dims=dims, variables=variables), ) .with_edge("read", "validate", "i") ) @@ -108,9 +102,7 @@ def _apply(f: Callable, i: (str, xr.DataArray), over_dims: list[str]) -> xr.Data axis = tuple(idx for idx, e in enumerate(array.dims) if e in over_dims) raw = f(array.to_numpy(), axis=axis) remainingDims = [e for e in array.dims if e not in over_dims] - result = xr.DataArray( - raw, dims=remainingDims, coords={d: array.coords[d] for d in remainingDims} - ) + result = xr.DataArray(raw, dims=remainingDims, coords={d: array.coords[d] for d in remainingDims}) # we need to wrap so that possible downstream actions can parse return xr.Dataset({varName: result}) @@ -120,9 +112,7 @@ def _project_one(i: xr.Dataset, variables: list[str]) -> tuple[str, xr.DataArray return variables[0], i[variables[0]] @staticmethod - def _project_gen( - i: xr.Dataset, variables: list[str] - ) -> Iterator[tuple[str, xr.DataArray]]: + def _project_gen(i: xr.Dataset, variables: list[str]) -> Iterator[tuple[str, xr.DataArray]]: for v in variables: print(f"yielding for {v}") yield v, i[v] @@ -146,29 +136,17 @@ def __init__( for source, variables in frum.projection.items(): if target := [v for v in variables if v in over_variables]: - kallable = ( - ApplyNumpyReduce._project_one - if len(target) == 1 - else ApplyNumpyReduce._project_gen - ) - projectT = TaskBuilder.from_callable(kallable).with_values( - variables=target - ) - projectT.definition.output_schema = [ - (f"{i}", "tuple[str, xr.DataArray]") for i in range(len(target)) - ] + kallable = ApplyNumpyReduce._project_one if len(target) == 1 else ApplyNumpyReduce._project_gen + projectT = TaskBuilder.from_callable(kallable).with_values(variables=target) + projectT.definition.output_schema = [(f"{i}", "tuple[str, xr.DataArray]") for i in range(len(target))] projectN = f"project_{uuid.uuid4()}" - self.implementation = self.implementation.with_node( - projectN, projectT - ).with_edge(source, projectN, "i") + self.implementation = self.implementation.with_node(projectN, projectT).with_edge(source, projectN, "i") for i, v in enumerate(target): - applyT = TaskBuilder.from_callable( - ApplyNumpyReduce._apply - ).with_values(f=f, over_dims=over_dims) + applyT = TaskBuilder.from_callable(ApplyNumpyReduce._apply).with_values(f=f, over_dims=over_dims) applyN = f"apply_{uuid.uuid4()}" - self.implementation = self.implementation.with_node( - applyN, applyT - ).with_edge(projectN, applyN, "i", f"{i}") + self.implementation = self.implementation.with_node(applyN, applyT).with_edge( + projectN, applyN, "i", f"{i}" + ) self.projection[applyN] = {v} @@ -187,9 +165,7 @@ def __init__( temperMeanOfMaxes = ApplyNumpyReduce(["temper"], ["x", "y"], np.mean, temperMaxAtPlace) # or process two variables within a single job -meanForEachVariableOverTime = ApplyNumpyReduce( - ["precip", "temper"], ["x", "y"], np.mean, source -) +meanForEachVariableOverTime = ApplyNumpyReduce(["precip", "temper"], ["x", "y"], np.mean, source) if __name__ == "__main__": # print(run_job(temperMeanOfMaxes.as_instance())) diff --git a/integration_tests/base.py b/integration_tests/base.py index 96b7608c..5a2ddad7 100644 --- a/integration_tests/base.py +++ b/integration_tests/base.py @@ -1,5 +1,6 @@ from dataclasses import dataclass + @dataclass(frozen=True, eq=True, slots=True) class JobSpec: workers: int diff --git a/integration_tests/benchmarks_old/anemoi.py b/integration_tests/benchmarks_old/anemoi.py index 8cce2259..c123acb5 100644 --- a/integration_tests/benchmarks_old/anemoi.py +++ b/integration_tests/benchmarks_old/anemoi.py @@ -12,20 +12,13 @@ def get_graph(lead_time, ensemble_members, CKPT=None, date="2024-12-02T00:00"): import anemoicascade as ac # ty: ignore[unresolved-import] - CKPT = ( - CKPT - or "/lus/h2resw01/hpcperm/ecm0672/pub/anemoi-ckpt/inference-aifs-0.2.1-anemoi.ckpt" - ) + CKPT = CKPT or "/lus/h2resw01/hpcperm/ecm0672/pub/anemoi-ckpt/inference-aifs-0.2.1-anemoi.ckpt" - model_action = ac.fluent.from_input( - CKPT, "mars", date, lead_time=lead_time, ensemble_members=ensemble_members - ) + model_action = ac.fluent.from_input(CKPT, "mars", date, lead_time=lead_time, ensemble_members=ensemble_members) result = model_action.mean(dim="ensemble_member") result = result.map(print) cascade_model = Cascade.from_actions([result.sel(param="2t")]) - cascade_model.visualise( - "model_running.html", preset="blob", cdn_resources="in_line" - ) + cascade_model.visualise("model_running.html", preset="blob", cdn_resources="in_line") return cascade_model._graph diff --git a/integration_tests/benchmarks_old/dask.py b/integration_tests/benchmarks_old/dask.py index dc62a9b1..80c519e2 100644 --- a/integration_tests/benchmarks_old/dask.py +++ b/integration_tests/benchmarks_old/dask.py @@ -17,17 +17,13 @@ def add(x, y): dl = {"a": 1, "b": 2, "c": (add, "a", "b")} dn = convert_legacy_graph(dl) job = graph2job(dn) - job.ext_outputs = [ - dataset for task in job.tasks for dataset in job.outputs_of(task) - ] + job.ext_outputs = [dataset for task in job.tasks for dataset in job.outputs_of(task)] return job elif job_name == "groupby": df = dd.DataFrame.from_dict({"x": [0, 0, 1, 1], "y": [1, 2, 3, 4]}) df = df.groupby("x").sum() job = graph2job(df.__dask_graph__()) - job.ext_outputs = [ - dataset for task in job.tasks for dataset in job.outputs_of(task) - ] + job.ext_outputs = [dataset for task in job.tasks for dataset in job.outputs_of(task)] return job else: raise NotImplementedError(job_name) diff --git a/integration_tests/benchmarks_old/dist.py b/integration_tests/benchmarks_old/dist.py index 9d07d56d..ac0ed534 100644 --- a/integration_tests/benchmarks_old/dist.py +++ b/integration_tests/benchmarks_old/dist.py @@ -109,13 +109,11 @@ def get_job() -> JobInstance: for i in range(L): job = ( - job.with_node(f"proc{i}", node) - .with_edge("source", f"proc{i}", "a") - .with_edge(f"proc{i}", "sink", f"v{i}") + job.with_node(f"proc{i}", node).with_edge("source", f"proc{i}", "a").with_edge(f"proc{i}", "sink", f"v{i}") + ) + job.nodes["sink"].definition.input_schema[f"v{i}"] = ( + "int" # TODO put some allow_kw into TaskDefinition instead to allow this ) - job.nodes["sink"].definition.input_schema[ - f"v{i}" - ] = "int" # TODO put some allow_kw into TaskDefinition instead to allow this job = job.build().get_or_raise() job.ext_outputs = list(job.outputs_of("sink")) diff --git a/integration_tests/benchmarks_old/generators.py b/integration_tests/benchmarks_old/generators.py index f07e2f8a..b13604a0 100644 --- a/integration_tests/benchmarks_old/generators.py +++ b/integration_tests/benchmarks_old/generators.py @@ -46,9 +46,7 @@ def consumer(i: np.ndarray) -> np.ndarray: input_schema={}, output_schema=[(f"{i}", "ndarray") for i in range(N)], ) - generator_i = TaskInstance( - definition=generator_d, static_input_kw={}, static_input_ps={} - ) + generator_i = TaskInstance(definition=generator_d, static_input_kw={}, static_input_ps={}) builder = JobBuilder() builder = builder.with_node("generator", generator_i) diff --git a/integration_tests/benchmarks_old/job1.py b/integration_tests/benchmarks_old/job1.py index f6cbe527..eb9f7d08 100644 --- a/integration_tests/benchmarks_old/job1.py +++ b/integration_tests/benchmarks_old/job1.py @@ -16,10 +16,11 @@ import os import earthkit.data -from earthkit.workflows.fluent import Payload from earthkit.workflows.plugins.pproc.fluent import from_source # ty: ignore from earthkit.workflows.plugins.pproc.utils.window import Range # ty: ignore +from earthkit.workflows.fluent import Payload + # *** PARAMS *** # eg "/ec/res4/hpcperm/ecm6012/gribs/casc_g01/" @@ -70,8 +71,7 @@ def get_prob(): prob_windows = [Range(f"{x}-{x}", [x]) for x in range(0, END_STEP + 1, 24)] + [ - Range(f"{x}-{x + 120}", list(range(x + 6, x + 121, 6))) - for x in range(0, END_STEP - 119, 120) + Range(f"{x}-{x + 120}", list(range(x + 6, x + 121, 6))) for x in range(0, END_STEP - 119, 120) ] return ( inputs.window_operation("min", prob_windows, dim="step", batch_size=2) @@ -91,10 +91,7 @@ def get_ensms(): def get_efi(): - efi_windows = [ - Range(f"{x}-{x+24}", list(range(x + 6, x + 25, 6))) - for x in range(0, END_STEP - 23, 24) - ] + efi_windows = [Range(f"{x}-{x + 24}", list(range(x + 6, x + 25, 6))) for x in range(0, END_STEP - 23, 24)] return ( inputs.window_operation("mean", efi_windows, dim="step", batch_size=2) .ensemble_extreme( @@ -136,7 +133,7 @@ def download_inputs(): } data = earthkit.data.from_source("mars", **ekp) with open(f"{data_root}/data_{number}_{step}.grib", "wb") as f: - data.write(f) # ty: ignore + data.write(f) # ty: ignore def download_climatology(): @@ -151,12 +148,12 @@ def download_climatology(): "levtype": "sfc", "type": "cd", "quantile": [f"{x}:100" for x in range(101)], - "step": f"{step}-{step+24}", + "step": f"{step}-{step + 24}", "grid": GRID, } data = earthkit.data.from_source("mars", **ekp) with open(f"{data_root}/data_clim_{step}.grib", "wb") as f: - data.write(f) # ty: ignore + data.write(f) # ty: ignore if __name__ == "__main__": diff --git a/integration_tests/benchmarks_old/matmul.py b/integration_tests/benchmarks_old/matmul.py index f93d7da8..dc1eb6ff 100644 --- a/integration_tests/benchmarks_old/matmul.py +++ b/integration_tests/benchmarks_old/matmul.py @@ -65,7 +65,8 @@ def execute_locally(): from multiprocessing.shared_memory import SharedMemory - mem = SharedMemory("benchmark_tmp", create=True, size=m0.nbytes); assert mem.buf is not None + mem = SharedMemory("benchmark_tmp", create=True, size=m0.nbytes) + assert mem.buf is not None mem.buf[:] = m0.tobytes() diff --git a/integration_tests/benchmarks_old/plotting.py b/integration_tests/benchmarks_old/plotting.py index ec36be73..6ec67f4f 100644 --- a/integration_tests/benchmarks_old/plotting.py +++ b/integration_tests/benchmarks_old/plotting.py @@ -21,9 +21,7 @@ output_notebook() -def plotTaskLane( - data: dict, scale, width, isBarController=False, allowFailed=False, vizTrans=True -): +def plotTaskLane(data: dict, scale, width, isBarController=False, allowFailed=False, vizTrans=True): Td = data["task_durations"].dropna() nc = [ "planned", @@ -39,9 +37,7 @@ def plotTaskLane( df = df - zero df = df.assign(worker=Td.worker) - workerToLane = { - e: i for i, e in enumerate(Td.worker.drop_duplicates().sort_values()) - } + workerToLane = {e: i for i, e in enumerate(Td.worker.drop_duplicates().sort_values())} print(workerToLane) # TODO use the labels in the if instead plot = Plot( @@ -53,16 +49,12 @@ def plotTaskLane( ) # TODO derive width from data def boxTask(left, right, color): - source = ColumnDataSource( - dict(y=df.worker.map(workerToLane), left=left, right=right) - ) + source = ColumnDataSource(dict(y=df.worker.map(workerToLane), left=left, right=right)) glyph = HBar(y="y", right="right", left="left", height=0.5, fill_color=color) plot.add_glyph(source, glyph) def boxTransmit(worker, left, right, color): - source = ColumnDataSource( - dict(y=worker.map(workerToLane) - 0.5, left=left, right=right) - ) + source = ColumnDataSource(dict(y=worker.map(workerToLane) - 0.5, left=left, right=right)) glyph = HBar(y="y", right="right", left="left", height=0.25, fill_color=color) plot.add_glyph(source, glyph) @@ -95,19 +87,11 @@ def barController(df, action, color): df = df - zero df = df.assign(target=Rd.target + ".w0", source=Rd.source) boxTransmit(df.target, df.planned, df.received, "#ff1111") # target waiting RED - boxTransmit( - df.target, df.received, df.unloaded, "#1111ff" - ) # target memcpy BLUE - boxTransmit( - df.target, df.unloaded, df.completed, "#444444" - ) # target callback GREY - boxTransmit( - df.source, df.planned, df.started, "#aaaa11" - ) # ctrl2source comm delay YELLOW + boxTransmit(df.target, df.received, df.unloaded, "#1111ff") # target memcpy BLUE + boxTransmit(df.target, df.unloaded, df.completed, "#444444") # target callback GREY + boxTransmit(df.source, df.planned, df.started, "#aaaa11") # ctrl2source comm delay YELLOW boxTransmit(df.source, df.started, df.loaded, "#1111aa") # source memcpy BLUE - boxTransmit( - df.source, df.loaded, df.received, "#444444" - ) # source memcpy + network GREY + boxTransmit(df.source, df.loaded, df.received, "#444444") # source memcpy + network GREY xaxis = LinearAxis() plot.add_layout(xaxis, "below") diff --git a/integration_tests/benchmarks_old/reporting.py b/integration_tests/benchmarks_old/reporting.py index 3df8654d..eae1bb32 100644 --- a/integration_tests/benchmarks_old/reporting.py +++ b/integration_tests/benchmarks_old/reporting.py @@ -47,32 +47,16 @@ def transmitDurations(transmits: pd.DataFrame) -> pd.DataFrame: if transmits.shape[0] == 0: return transmits - mode_fix = transmits[~transmits["mode"].isna()].set_index(["dataset", "target"])[ - "mode" - ] + mode_fix = transmits[~transmits["mode"].isna()].set_index(["dataset", "target"])["mode"] lookup = mode_fix[~mode_fix.index.duplicated(keep="last")] - transmits = ( - transmits.set_index(["dataset", "target"]) - .drop(columns="mode") - .join(lookup) - .reset_index() - ) + transmits = transmits.set_index(["dataset", "target"]).drop(columns="mode").join(lookup).reset_index() # we'd have received and unloaded missing source - source_fix = transmits[~transmits["source"].isna()].set_index( - ["dataset", "target"] - )["source"] + source_fix = transmits[~transmits["source"].isna()].set_index(["dataset", "target"])["source"] lookup = source_fix[~source_fix.index.duplicated(keep="last")] - transmits = ( - transmits.set_index(["dataset", "target"]) - .drop(columns="source") - .join(lookup) - .reset_index() - ) - - durations = transmits.pivot( - index=["dataset", "target", "source", "mode"], columns=["action"], values=["at"] - ) + transmits = transmits.set_index(["dataset", "target"]).drop(columns="source").join(lookup).reset_index() + + durations = transmits.pivot(index=["dataset", "target", "source", "mode"], columns=["action"], values=["at"]) durations.columns = [name[1] for name in durations.columns] # type: ignore durations = durations.reset_index() @@ -119,11 +103,7 @@ def logParse(files: Iterable[str]) -> dict[str, pd.DataFrame]: "kind": k.value, "duration_ns_sum": v.duration_ns_sum, "duration_ns_cnt": v.duration_ns_cnt, - "duration_ns_avg": ( - v.duration_ns_sum / v.duration_ns_cnt - if v.duration_ns_cnt > 0 - else math.nan - ), + "duration_ns_avg": (v.duration_ns_sum / v.duration_ns_cnt if v.duration_ns_cnt > 0 else math.nan), } for k, v in microtraces.items() ] diff --git a/integration_tests/benchmarks_old/util.py b/integration_tests/benchmarks_old/util.py index 2e614231..016f2617 100644 --- a/integration_tests/benchmarks_old/util.py +++ b/integration_tests/benchmarks_old/util.py @@ -9,26 +9,11 @@ """Contains utility methods for benchmark definitions""" import logging -import logging.config -import os -import subprocess -import sys -from concurrent.futures import ThreadPoolExecutor -from time import perf_counter_ns -from typing import Any import orjson -import cascade.executor.platform as platform -from cascade.controller.impl import run -from cascade.executor.bridge import Bridge -from cascade.executor.comms import callback -from cascade.executor.config import logging_config, logging_config_filehandler -from cascade.executor.executor import Executor -from cascade.executor.msg import BackboneAddress, ExecutorShutdown -from cascade.low.core import DatasetId, JobInstance, JobInstanceRich +from cascade.low.core import JobInstance, JobInstanceRich from cascade.low.func import msum -from cascade.scheduler.precompute import precompute logger = logging.getLogger("cascade.benchmarks") @@ -37,6 +22,7 @@ def get_job(benchmark: str | None, instance_path: str | None) -> JobInstanceRich # NOTE we dont want to import these at the top level to prevent imports pollution of executor import cascade.low.into from earthkit.workflows.graph import Graph, deduplicate_nodes + # NOTE because of os.environ, we don't import all... ideally we'd have some file-based init/config mech instead if benchmark is not None and instance_path is not None: raise TypeError("specified both benchmark name and job instance") diff --git a/integration_tests/harness.py b/integration_tests/harness.py index d5fd950d..d2bd3a5e 100644 --- a/integration_tests/harness.py +++ b/integration_tests/harness.py @@ -1,8 +1,8 @@ -from cascade.main import run_locally import importlib -import sys -from base import JobSpec import logging +import sys + +from cascade.main import run_locally logger = logging.getLogger("cascade.benchmarks.harness") diff --git a/integration_tests/job_runnerRestarts.py b/integration_tests/job_runnerRestarts.py index 6f697b32..bf53e81e 100644 --- a/integration_tests/job_runnerRestarts.py +++ b/integration_tests/job_runnerRestarts.py @@ -1,17 +1,27 @@ -from cascade.low.builders import TaskBuilder, JobBuilder -from cascade.low.core import JobInstance, JobInstanceRich from base import JobSpec +from cascade.low.builders import JobBuilder, TaskBuilder +from cascade.low.core import JobInstanceRich + + def job() -> JobInstanceRich: fac = lambda version: TaskBuilder.from_entrypoint( "runtime.check_numpy_version", {"expected": "str"}, "bool", [f"numpy=={version}"], - ).with_values(expected=version) + ).with_values(expected=version) - ji = JobBuilder().with_node("t1", fac("2.0.1")).with_node("t2", fac("2.4.1")).with_node("t3", fac("2.4.2")).build().get_or_raise() + ji = ( + JobBuilder() + .with_node("t1", fac("2.0.1")) + .with_node("t2", fac("2.4.1")) + .with_node("t3", fac("2.4.2")) + .build() + .get_or_raise() + ) return JobInstanceRich(jobInstance=ji, checkpointSpec=None) -def spc() -> JobSpec: + +def spc() -> JobSpec: return JobSpec(workers=1, hosts=1) diff --git a/integration_tests/runtime/__init__.py b/integration_tests/runtime/__init__.py index 91e57072..926db9b8 100644 --- a/integration_tests/runtime/__init__.py +++ b/integration_tests/runtime/__init__.py @@ -3,6 +3,7 @@ def check_numpy_version(expected: str) -> bool: import numpy + if numpy.__version__ != expected: raise ValueError(f"version check failure, {numpy.__version__=} != {expected=}") return True diff --git a/pyproject.toml b/pyproject.toml index 02ce936c..004bcf29 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,63 +7,47 @@ # nor does it submit to any jurisdiction. [build-system] -requires = ["setuptools>=80", "setuptools_scm[toml]>=6.2", "packaging>=25"] build-backend = "setuptools.build_meta" +requires = ["setuptools>=80", "setuptools_scm[toml]>=6.2", "packaging>=25"] + +[dependency-groups] +dev = ["pytest", "pytest-xdist>=3.8", "prek", "ty==0.0.2", "build", "bokeh"] [project] -name = "earthkit-workflows" -description = "Earthkit Workflows is a Python library for declaring earthkit task DAGs, as well as scheduling and executing them on heterogeneous computing systems." authors = [ - { name = "European Centre for Medium-Range Weather Forecasts (ECMWF)", email = "software.support@ecmwf.int" }, + {name = "European Centre for Medium-Range Weather Forecasts (ECMWF)", email = "software.support@ecmwf.int"} ] -license = "Apache-2.0" -license-files = ["LICENSE"] -requires-python = ">=3.11" dependencies = [ - "earthkit-data", - "cloudpickle", - "numpy", - "xarray", - "networkx", - "array-api-compat", - "sortedcontainers", - "pyvis", - "dill", - "pyrsistent", - "pydantic", - "pyzmq", - "fire", - "orjson", - "qubed>=0.3.0", + "earthkit-data", + "cloudpickle", + "numpy", + "xarray", + "networkx", + "array-api-compat", + "sortedcontainers", + "pyvis", + "dill", + "pyrsistent", + "pydantic", + "pyzmq", + "fire", + "orjson", + "qubed>=0.3.0" ] +description = "Earthkit Workflows is a Python library for declaring earthkit task DAGs, as well as scheduling and executing them on heterogeneous computing systems." # version provided via setuptools_scm module, which derives it from git tag dynamic = ["version"] +license = "Apache-2.0" +license-files = ["LICENSE"] +name = "earthkit-workflows" readme = "README.md" - -[dependency-groups] -dev = ["pytest", "pytest-xdist>=3.8", "prek", "ty==0.0.2", "build", "bokeh"] - - -[tool.setuptools] -include-package-data = true -zip-safe = false - -[tool.setuptools_scm] -write_to = "src/earthkit/workflows/_version.py" -write_to_template = '''# Do not change! Do not track in version control! -__version__ = "{version}" -''' -local_scheme = "no-local-version" - -[tool.setuptools.packages.find] -include = ["earthkit.workflows*", "cascade*"] -where = ["src"] +requires-python = ">=3.11" [tool.pytest.ini_options] +addopts = "-n8" log_cli = true log_cli_level = "DEBUG" testpaths = ["tests/"] -addopts = "-n8" [tool.ruff] line-length = 120 @@ -84,12 +68,27 @@ ignore = [ "D417", "E722", "E731", - "E741", + "E741" ] select = [ "F", # pyflakes "E", # pycodestyle "W", # pycodestyle warnings "I", # isort - "D", # pydocstyle + "D" # pydocstyle ] + +[tool.setuptools] +include-package-data = true +zip-safe = false + +[tool.setuptools.packages.find] +include = ["earthkit.workflows*", "cascade*"] +where = ["src"] + +[tool.setuptools_scm] +local_scheme = "no-local-version" +write_to = "src/earthkit/workflows/_version.py" +write_to_template = '''# Do not change! Do not track in version control! +__version__ = "{version}" +''' diff --git a/src/cascade/controller/act.py b/src/cascade/controller/act.py index 83d3ebe0..5eaa6e9f 100644 --- a/src/cascade/controller/act.py +++ b/src/cascade/controller/act.py @@ -27,18 +27,13 @@ def act(bridge: Bridge, assignment: Assignment) -> None: """Converts an assignment to one or more actions which are sent to the bridge, and returned for tracing/updating purposes. Does *not* mutate State, but executors behind the Bridge *are* mutated. """ - for prep in assignment.prep: ds = prep[0] source_host = prep[1] if assignment.worker.host == source_host: - logger.debug( - f"dataset {ds} should be locally available at {assignment.worker.host}, doing no-op" - ) + logger.debug(f"dataset {ds} should be locally available at {assignment.worker.host}, doing no-op") continue - logger.debug( - f"sending transmit ({ds}: {source_host}=>{assignment.worker.host}) to bridge" - ) + logger.debug(f"sending transmit ({ds}: {source_host}=>{assignment.worker.host}) to bridge") mark( { "dataset": repr(ds), @@ -75,7 +70,6 @@ def flush_queues(bridge: Bridge, state: State, context: JobExecutionContext): changes in Context, sends commands via Bridge. Mutates State, JobExecutionContext, and via bridge the Executors. """ - for dataset, host in state.drain_fetching_queue(): if host != VirtualCheckpointHost: bridge.fetch(dataset, host) @@ -83,7 +77,7 @@ def flush_queues(bridge: Bridge, state: State, context: JobExecutionContext): # NOTE we would rather not be here, but we dont generally expect # checkpointed datasets to be outputs. If needbe, send a command # to any worker, or spawn a thread with this - logger.warning(f"execute checkpoint retrieve on controller") + logger.warning("execute checkpoint retrieve on controller") # NOTE the host is the virtual one so the message is not really valid, but no big deal virtual_command = build_retrieve_command(bridge.checkpoint_spec, dataset, host) buffer = retrieve_dataset(virtual_command) @@ -108,10 +102,12 @@ def flush_queues(bridge: Bridge, state: State, context: JobExecutionContext): return state + def virtual_checkpoint_publish(datasets: Iterable[DatasetId]) -> Iterator[DatasetPublished]: """Virtual in the sense of not actually sending any message, but instead simulating a response so that controller.notify can bring the contexts into the right state. - Invoked once, at the job start, after the checkpoint has been listed""" + Invoked once, at the job start, after the checkpoint has been listed + """ return ( DatasetPublished( origin=VirtualCheckpointHost, diff --git a/src/cascade/controller/core.py b/src/cascade/controller/core.py index 3cbe7133..de09b615 100644 --- a/src/cascade/controller/core.py +++ b/src/cascade/controller/core.py @@ -8,9 +8,7 @@ from typing import Any, Iterator import cascade.executor.serde as serde -from cascade.executor.msg import DatasetPersistSuccess, DatasetTransmitPayload from cascade.low.core import DatasetId, HostId, TaskId -from cascade.low.execution_context import VirtualCheckpointHost logger = logging.getLogger(__name__) @@ -44,7 +42,7 @@ def _consider_purge(self, dataset: DatasetId) -> None: """If dataset not required anymore, add to purging_queue""" no_dependants = not self.purging_tracker.get(dataset, None) not_required_output = self.outputs.get(dataset, 1) is not None - not_required_persist = not dataset in self.to_persist + not_required_persist = dataset not in self.to_persist if all((no_dependants, not_required_output, not_required_persist)): logger.debug(f"adding {dataset=} to purging queue") if dataset in self.purging_tracker: @@ -53,19 +51,12 @@ def _consider_purge(self, dataset: DatasetId) -> None: def consider_fetch(self, dataset: DatasetId, at: HostId) -> None: """If required as output and not yet arrived, add to fetching queue""" - if ( - dataset in self.outputs - and self.outputs[dataset] is None - and dataset not in self.fetching_queue - ): + if dataset in self.outputs and self.outputs[dataset] is None and dataset not in self.fetching_queue: self.fetching_queue[dataset] = at def consider_persist(self, dataset: DatasetId, at: HostId) -> None: """If required as persist and not yet acknowledged, add to persist queue""" - if ( - dataset in self.to_persist - and dataset not in self.persist_queue - ): + if dataset in self.to_persist and dataset not in self.persist_queue: self.persist_queue[dataset] = at def receive_payload(self, ds: DatasetId, payload: bytes, deser_fun: str) -> None: @@ -102,9 +93,7 @@ def drain_persist_queue(self) -> Iterator[tuple[DatasetId, HostId]]: def init_state(outputs: set[DatasetId], to_persist: set[DatasetId], edge_o: dict[DatasetId, set[TaskId]]) -> State: - purging_tracker = { - ds: {task for task in dependants} for ds, dependants in edge_o.items() - } + purging_tracker = {ds: {task for task in dependants} for ds, dependants in edge_o.items()} return State( outputs={e: None for e in outputs}, diff --git a/src/cascade/controller/impl.py b/src/cascade/controller/impl.py index b439b2b6..be41dc47 100644 --- a/src/cascade/controller/impl.py +++ b/src/cascade/controller/impl.py @@ -15,7 +15,7 @@ from cascade.controller.report import Reporter from cascade.executor.bridge import Bridge, Event from cascade.executor.checkpoints import list_persisted_datasets -from cascade.low.core import JobInstance, JobInstanceRich, type_dec +from cascade.low.core import JobInstanceRich, type_dec from cascade.low.exceptions import CascadeError, CascadeInfrastructureError, CascadeUserError from cascade.low.execution_context import init_context from cascade.low.tracing import ControllerPhases, Microtrace, label, mark, timer @@ -75,7 +75,9 @@ def run( mark({"action": ControllerPhases.wait}) if state.has_awaitable() or context.has_awaitable(): - logger.debug(f"about to await bridge with {context.ongoing_total=}, {context.remaining=} and {state.has_awaitable()=}") + logger.debug( + f"about to await bridge with {context.ongoing_total=}, {context.remaining=} and {state.has_awaitable()=}" + ) events = timer(bridge.recv_events, Microtrace.ctrl_wait)() timer(notify_wrapper, Microtrace.ctrl_notify)(events) logger.debug(f"received {len(events)} events") diff --git a/src/cascade/deployment/__init__.py b/src/cascade/deployment/__init__.py index a5cdde71..81d1b877 100644 --- a/src/cascade/deployment/__init__.py +++ b/src/cascade/deployment/__init__.py @@ -7,6 +7,6 @@ # nor does it submit to any jurisdiction. """ -Configuration and utilities pertaining to deployment. Currently handles: +Configuration and utilities pertaining to deployment. Currently handles: - logging. """ diff --git a/src/cascade/deployment/logging/__init__.py b/src/cascade/deployment/logging/__init__.py index bbb9021d..aee2cb12 100644 --- a/src/cascade/deployment/logging/__init__.py +++ b/src/cascade/deployment/logging/__init__.py @@ -46,16 +46,16 @@ class LoggingConfig(BaseModel): formatter: Literal["line", "json"] """Line is standard python logging, json uses structured logging""" - path_base: str|None + path_base: str | None """If None log to stdout, otherwise log into files in path_base directory, with each process having its own files. Expected to have been created beforehand""" def ser_cliparam(self) -> str: - return base64.b64encode(self.model_dump_json().encode('utf-8')).decode('utf-8') + return base64.b64encode(self.model_dump_json().encode("utf-8")).decode("utf-8") def withContext(self, context_kv: str) -> Self: if self.path_base is not None: - return self.model_copy(update={'path_base': self.path_base + f"{context_kv}."}) + return self.model_copy(update={"path_base": self.path_base + f"{context_kv}."}) else: # TODO handle context in the stdout loggers. Not critical because all # logs of zmq messages have context in them anyway @@ -64,25 +64,28 @@ def withContext(self, context_kv: str) -> Self: DefaultLoggingConfig = LoggingConfig(formatter="line", path_base=None) + def as_dict_config(loggingConfig: LoggingConfig, hostAndRole: str) -> dict: if loggingConfig.path_base: filename = f"{loggingConfig.path_base}{hostAndRole}.txt" - handler = defaults.handlers['filename'](filename) # ty:ignore[call-non-callable] # sloppy typing on my side + handler = defaults.handlers["filename"](filename) # ty:ignore[call-non-callable] # sloppy typing on my side else: - handler = defaults.handlers['stdout'] + handler = defaults.handlers["stdout"] return { **defaults.base, **handler, **defaults.formatters[loggingConfig.formatter], } + def init_from_obj(loggingConfig: LoggingConfig, hostAndRole: str) -> None: dictConfig = as_dict_config(loggingConfig, hostAndRole) logging.config.dictConfig(dictConfig) -def init_from_cliparam(cliparam: str|None, hostAndRole: str) -> LoggingConfig: + +def init_from_cliparam(cliparam: str | None, hostAndRole: str) -> LoggingConfig: if cliparam is not None: - loggingConfig = LoggingConfig(**orjson.loads(base64.b64decode(cliparam.encode('utf-8')))) + loggingConfig = LoggingConfig(**orjson.loads(base64.b64decode(cliparam.encode("utf-8")))) else: loggingConfig = DefaultLoggingConfig logging.getLogger(__name__).warning(f"using default config for logging at {hostAndRole}") diff --git a/src/cascade/deployment/logging/defaults.py b/src/cascade/deployment/logging/defaults.py index a544ec37..20b2ca2e 100644 --- a/src/cascade/deployment/logging/defaults.py +++ b/src/cascade/deployment/logging/defaults.py @@ -32,14 +32,14 @@ }, }, "filename": lambda filename: { - "handlers": { - "default": { - "formatter": "default", - "class": "logging.FileHandler", - "filename": filename, - }, + "handlers": { + "default": { + "formatter": "default", + "class": "logging.FileHandler", + "filename": filename, }, }, + }, } formatters = { @@ -54,7 +54,7 @@ "json": { "formatters": { "default": { - "()": "__main__.JSONFormatter", + "()": "__main__.JSONFormatter", }, }, }, diff --git a/src/cascade/deployment/logging/json_formatter.py b/src/cascade/deployment/logging/json_formatter.py index ad272b54..6b59dc81 100644 --- a/src/cascade/deployment/logging/json_formatter.py +++ b/src/cascade/deployment/logging/json_formatter.py @@ -9,7 +9,6 @@ """Custom json formatter, felt easier than struggling with another 3rd party lib""" import logging -import logging.config import orjson @@ -23,14 +22,14 @@ def format(self, record): "process": record.process, "message": record.getMessage(), } - + # NOTE standard_attrs = { # 'name', 'msg', 'args', 'levelname', 'levelno', 'pathname', 'filename', # 'module', 'exc_info', 'exc_text', 'stack_info', 'lineno', 'funcName', # 'created', 'msecs', 'relativeCreated', 'thread', 'threadName', # 'processName', 'process', 'message', 'asctime', 'taskName', - #} - + # } + if record.exc_info: log_data["exception"] = self.formatException(record.exc_info) diff --git a/src/cascade/executor/bridge.py b/src/cascade/executor/bridge.py index fe1f2ca5..c72fc00b 100644 --- a/src/cascade/executor/bridge.py +++ b/src/cascade/executor/bridge.py @@ -11,7 +11,7 @@ import logging import time -from cascade.executor.checkpoints import build_persist_command, build_retrieve_command, serialize_params +from cascade.executor.checkpoints import build_persist_command, build_retrieve_command from cascade.executor.comms import GraceWatcher, Listener, ReliableSender from cascade.executor.comms import default_message_resend_ms as resend_grace_ms from cascade.executor.executor import heartbeat_grace_ms as executor_heartbeat_grace_ms @@ -22,7 +22,6 @@ DatasetPersistSuccess, DatasetPublished, DatasetPurge, - DatasetRetrieveCommand, DatasetRetrieveFailure, DatasetRetrieveSuccess, DatasetTransmitCommand, @@ -44,14 +43,25 @@ logger = logging.getLogger(__name__) -Event = DatasetPublished | DatasetTransmitPayload | DatasetPersistSuccess | DatasetRetrieveSuccess | RunnerRestartRequest +Event = ( + DatasetPublished | DatasetTransmitPayload | DatasetPersistSuccess | DatasetRetrieveSuccess | RunnerRestartRequest +) # TODO consider retries here, esp on the Persist/Retrieve Failures -ToShutdown = TaskFailure | ExecutorFailure | DatasetRetrieveFailure | DatasetTransmitFailure | DatasetPersistFailure | ExecutorExit +ToShutdown = ( + TaskFailure + | ExecutorFailure + | DatasetRetrieveFailure + | DatasetTransmitFailure + | DatasetPersistFailure + | ExecutorExit +) Unsupported = TaskSequence | DatasetPurge | DatasetTransmitCommand | DatasetPersistCommand | ExecutorShutdown class Bridge: - def __init__(self, controller_url: str, expected_executors: int, checkpoint_spec: CheckpointSpec | None = None) -> None: + def __init__( + self, controller_url: str, expected_executors: int, checkpoint_spec: CheckpointSpec | None = None + ) -> None: self.checkpoint_spec = checkpoint_spec self.mlistener = Listener(controller_url) self.heartbeat_checker: dict[HostId, GraceWatcher] = {} @@ -74,7 +84,9 @@ def __init__(self, controller_url: str, expected_executors: int, checkpoint_spec self.sender.add_host(message.host, message.maddress) self.sender.add_host("data." + message.host, message.daddress) for worker in message.workers: - self.environment.workers[worker.worker_id] = Worker(cpu=worker.cpu, gpu=worker.gpu, memory_mb=worker.memory_mb) + self.environment.workers[worker.worker_id] = Worker( + cpu=worker.cpu, gpu=worker.gpu, memory_mb=worker.memory_mb + ) self.environment.host_url_base[message.host] = message.url_base registered += 1 self.heartbeat_checker[message.host] = GraceWatcher(2 * executor_heartbeat_grace_ms) @@ -131,7 +143,11 @@ def recv_events(self) -> list[Event]: if isinstance(shutdown_reason, CascadeError): raise shutdown_reason - elif isinstance(shutdown_reason, Message) and hasattr(shutdown_reason, 'detail') and isinstance(shutdown_reason.detail, str): + elif ( + isinstance(shutdown_reason, Message) + and hasattr(shutdown_reason, "detail") + and isinstance(shutdown_reason.detail, str) + ): raise des(shutdown_reason.detail) else: # unknown at this stage is assumed to be InfrastructureError diff --git a/src/cascade/executor/checkpoints.py b/src/cascade/executor/checkpoints.py index ee8e7e11..3fd36b99 100644 --- a/src/cascade/executor/checkpoints.py +++ b/src/cascade/executor/checkpoints.py @@ -33,21 +33,25 @@ def serialize_params(spec: CheckpointSpec, id_: str) -> str: case "fs": if not isinstance(spec.storage_params, str): # we are in control of how these are created -> InternalError - raise CascadeInternalError(f"expected checkpoint storage params to be str, gotten {spec.storage_params.__class__}") + raise CascadeInternalError( + f"expected checkpoint storage params to be str, gotten {spec.storage_params.__class__}" + ) root = pathlib.Path(spec.storage_params) return str(root / id_) case s: assert_never(s) -def build_persist_command(checkpoint_spec: CheckpointSpec | None, ds: DatasetId, hostId: HostId) -> DatasetPersistCommand: +def build_persist_command( + checkpoint_spec: CheckpointSpec | None, ds: DatasetId, hostId: HostId +) -> DatasetPersistCommand: if checkpoint_spec is None: # should have been validated prior -> InternalError - raise CascadeInternalError(f"unexpected persist need when checkpoint storage not configured") + raise CascadeInternalError("unexpected persist need when checkpoint storage not configured") id_ = checkpoint_spec.persist_id if not id_: # should have been validated prior -> InternalError - raise CascadeInternalError(f"unexpected persist need when there is no persist id") + raise CascadeInternalError("unexpected persist need when there is no persist id") persist_params = serialize_params(checkpoint_spec, id_) return DatasetPersistCommand( source=hostId, @@ -84,14 +88,16 @@ def list_persisted_datasets(spec: CheckpointSpec) -> list[DatasetId]: assert_never(s) -def build_retrieve_command(checkpoint_spec: CheckpointSpec | None, ds: DatasetId, hostId: HostId) -> DatasetRetrieveCommand: +def build_retrieve_command( + checkpoint_spec: CheckpointSpec | None, ds: DatasetId, hostId: HostId +) -> DatasetRetrieveCommand: if checkpoint_spec is None: # should have been validated prior -> InternalError - raise CascadeInternalError(f"unexpected retrieve need when checkpoint storage not configured") + raise CascadeInternalError("unexpected retrieve need when checkpoint storage not configured") id_ = checkpoint_spec.retrieve_id if not id_: # should have been validated prior -> InternalError - raise CascadeInternalError(f"unexpected retrieve when there is no retrive id") + raise CascadeInternalError("unexpected retrieve when there is no retrive id") retrieve_params = serialize_params(checkpoint_spec, id_) return DatasetRetrieveCommand( target=hostId, @@ -128,16 +134,18 @@ def possible_repersist(dataset: DatasetId, checkpointSpec: CheckpointSpec | None # If needbe, spawn a thread or something. In that case needs a completion callback if not checkpointSpec: # should have been validated prior -> InternalError - raise CascadeInternalError(f"unexpected repersist when checkpoint storage not configured") + raise CascadeInternalError("unexpected repersist when checkpoint storage not configured") if not checkpointSpec.retrieve_id: # should have been validated prior -> InternalError - raise CascadeInternalError(f"unexpected repersist when no retrieve id") + raise CascadeInternalError("unexpected repersist when no retrieve id") if not checkpointSpec.persist_id: # should have been validated prior -> InternalError - raise CascadeInternalError(f"unexpected repersist when no persist id") + raise CascadeInternalError("unexpected repersist when no persist id") if checkpointSpec.retrieve_id == checkpointSpec.persist_id: # we assume reproducibility---bold!---so we better warn about it - logger.warning(f"no-op for persist of {dataset} as was already persisted under the same id {checkpointSpec.retrieve_id}") + logger.warning( + f"no-op for persist of {dataset} as was already persisted under the same id {checkpointSpec.retrieve_id}" + ) return # NOTE the host is the virtual one so the message is not really valid, but no big deal diff --git a/src/cascade/executor/comms.py b/src/cascade/executor/comms.py index 34640a18..cd754b6a 100644 --- a/src/cascade/executor/comms.py +++ b/src/cascade/executor/comms.py @@ -224,13 +224,16 @@ def maybe_retry(self) -> None: watermark = time.time_ns() - self.resend_grace for idx, record in self.inflight.items(): if record.at < watermark: - logger.warning(f"retrying message {idx} ({record.clazz}) due to no confirmation after {watermark - record.at}ns") + logger.warning( + f"retrying message {idx} ({record.clazz}) due to no confirmation after {watermark - record.at}ns" + ) if (socket := self.hosts.get(record.host, None)) is not None: socket[0].send_multipart(record.message) self.inflight[idx].at = time.time_ns() self.inflight[idx].remaining -= 1 if self.inflight[idx].remaining <= 0: - raise CascadeInfrastructureError(f"message {idx} ({record.clazz}) retried too many times") else: - logger.warning(f"{record.host=} not present, cannot retry message {idx=}. Presumably we are at shutdown") + logger.warning( + f"{record.host=} not present, cannot retry message {idx=}. Presumably we are at shutdown" + ) diff --git a/src/cascade/executor/data_server.py b/src/cascade/executor/data_server.py index 55b4e48d..36361ebe 100644 --- a/src/cascade/executor/data_server.py +++ b/src/cascade/executor/data_server.py @@ -70,8 +70,12 @@ def __init__( DatasetTransmitCommand | DatasetTransmitPayload | DatasetPersistCommand | DatasetRetrieveCommand, Future ] = {} self.awaiting_confirmation: dict[int, tuple[DatasetTransmitCommand, int]] = {} - self.invalid: set[DatasetId] = set() # for preventing out-of-order stores/transmits for datasets that have already been purged - self.acks: set[int] = set() # it could happen that Ack arrives before respective Future finishes, so we need to store separately + self.invalid: set[DatasetId] = ( + set() + ) # for preventing out-of-order stores/transmits for datasets that have already been purged + self.acks: set[int] = ( + set() + ) # it could happen that Ack arrives before respective Future finishes, so we need to store separately # TODO the two above should be eventually purged, see comms.Listener.acked for a similar concern def maybe_clean(self) -> None: @@ -83,7 +87,7 @@ def maybe_clean(self) -> None: if fut.done(): ex = fut.exception() if ex: - ex = cast(Exception, ex) # NOTE ty consider ex BaseException & ~AlwaysFalsy + ex = cast(Exception, ex) # NOTE ty consider ex BaseException & ~AlwaysFalsy callback( self.maddress, DatasetTransmitFailure(host=self.host, detail=ser(ex, repr(key))), @@ -245,9 +249,13 @@ def recv_loop(self) -> None: logger.debug(f"received message {type(m)}") if isinstance(m, DatasetTransmitCommand): if m.idx in self.awaiting_confirmation: - raise CascadeInternalError(f"transmit idx conflict: {m}, {self.awaiting_confirmation[m.idx]}") + raise CascadeInternalError( + f"transmit idx conflict: {m}, {self.awaiting_confirmation[m.idx]}" + ) if m.ds in self.invalid: - raise CascadeInternalError(f"unexpected transmit command {m} as the dataset was already purged") + raise CascadeInternalError( + f"unexpected transmit command {m} as the dataset was already purged" + ) mark( { "dataset": repr(m.ds), @@ -260,7 +268,9 @@ def recv_loop(self) -> None: self.futs_in_progress[m] = fut elif isinstance(m, DatasetPersistCommand): if m.ds in self.invalid: - raise CascadeInternalError(description=f"unexpected persist command {m} as the dataset was already purged") + raise CascadeInternalError( + description=f"unexpected persist command {m} as the dataset was already purged" + ) # TODO mark? fut = self.ds_proc_tp.submit(self._persist_dataset, m) self.futs_in_progress[m] = fut @@ -270,9 +280,7 @@ def recv_loop(self) -> None: self.futs_in_progress[m] = fut elif isinstance(m, DatasetTransmitPayload): if m.header.ds in self.invalid: - logger.warning( - f"ignoring transmit payload {m.header} as the dataset was already purged" - ) + logger.warning(f"ignoring transmit payload {m.header} as the dataset was already purged") continue mark( { @@ -291,7 +299,9 @@ def recv_loop(self) -> None: # TODO submit this as a future? This actively blocks the whole server to_wait = [] for commandProg, fut in self.futs_in_progress.items(): - if isinstance(commandProg, DatasetTransmitCommand | DatasetPersistCommand | DatasetRetrieveCommand): + if isinstance( + commandProg, DatasetTransmitCommand | DatasetPersistCommand | DatasetRetrieveCommand + ): val = commandProg.ds elif isinstance(commandProg, DatasetTransmitPayload): val = commandProg.header.ds diff --git a/src/cascade/executor/executor.py b/src/cascade/executor/executor.py index 0729f939..83463483 100644 --- a/src/cascade/executor/executor.py +++ b/src/cascade/executor/executor.py @@ -32,7 +32,6 @@ from cascade.executor.comms import GraceWatcher, Listener, ReliableSender, callback from cascade.executor.comms import default_message_resend_ms as resend_grace_ms from cascade.executor.comms import default_timeout_ms as comms_default_timeout_ms -from cascade.executor.config import logging_config, logging_config_filehandler from cascade.executor.data_server import start_data_server from cascade.executor.msg import ( Ack, @@ -57,8 +56,8 @@ WorkerShutdown, ) from cascade.executor.runner.entrypoint import RunnerContext, entrypoint, worker_address -from cascade.low.core import DatasetId, HostId, JobInstance, TaskId, WorkerId -from cascade.low.exceptions import CascadeError, CascadeInfrastructureError, CascadeInternalError, CascadeUserError, ser +from cascade.low.core import DatasetId, HostId, JobInstance, WorkerId +from cascade.low.exceptions import CascadeInfrastructureError, CascadeInternalError, CascadeUserError, ser from cascade.low.tracing import TaskLifecycle, mark from cascade.low.views import param_source from cascade.shm.server import entrypoint as shm_server @@ -67,7 +66,9 @@ heartbeat_grace_ms = 2 * comms_default_timeout_ms # messages from the data server which need to go to controller, but have no additional logic here -JustForwardToController = DatasetTransmitFailure | DatasetPersistSuccess | DatasetPersistFailure | DatasetRetrieveFailure +JustForwardToController = ( + DatasetTransmitFailure | DatasetPersistSuccess | DatasetPersistFailure | DatasetRetrieveFailure +) def address_of(port: int) -> BackboneAddress: @@ -256,13 +257,19 @@ def healthcheck(self) -> None: raise CascadeInternalError(f"process on {k} is not alive") elif procFail(e.process.exitcode): # we assume low memory setting or callable issue -> UserError - raise CascadeUserError(f"process on {k} failed to terminate correctly: {e.process.pid} -> {e.process.exitcode}") + raise CascadeUserError( + f"process on {k} failed to terminate correctly: {e.process.pid} -> {e.process.exitcode}" + ) if procFail(self.shm_process.exitcode): # possibly low memory setting but this is system config -> InfrastructureError - raise CascadeInfrastructureError(f"shm server {self.shm_process.pid} failed with {self.shm_process.exitcode}") + raise CascadeInfrastructureError( + f"shm server {self.shm_process.pid} failed with {self.shm_process.exitcode}" + ) if procFail(self.data_server.exitcode): # unknown issue, it failed to report its own -> InfrastructureError - raise CascadeInfrastructureError(f"data server {self.data_server.pid} failed with {self.data_server.exitcode}") + raise CascadeInfrastructureError( + f"data server {self.data_server.pid} failed with {self.data_server.exitcode}" + ) if self.heartbeat_watcher.is_breach() > 0: logger.debug( f"grace elapsed without message by {self.heartbeat_watcher.elapsed_ms()} -> sending explicit heartbeat at {self.host}" @@ -320,7 +327,7 @@ def recv_loop(self) -> None: break # from entrypoint elif isinstance(m, WorkerReady): - if not m.worker in self.worker_awaits: + if m.worker not in self.worker_awaits: logger.warning(f"unexpectedly gotten WorkerReady from {m.worker}, assuming double send") else: maybe_seq = self.worker_awaits.pop(m.worker) diff --git a/src/cascade/executor/msg.py b/src/cascade/executor/msg.py index 29dbdc90..b16698cd 100644 --- a/src/cascade/executor/msg.py +++ b/src/cascade/executor/msg.py @@ -21,7 +21,7 @@ from cascade.low.core import CheckpointStorageType, DatasetId, HostId, TaskId, WorkerId -## Meta +# Meta VERSION = 1 # for serde compatibility @@ -52,7 +52,7 @@ def message(clazz): BackboneAddress = str # eg zmq address -## Msgs +# Msgs @dataclass(frozen=True) @@ -80,6 +80,7 @@ class TaskFailure: task: TaskId | None detail: str + @dataclass(frozen=True) class RunnerRestartRequest: # Sent by runner when it realizes it cant continue but a restart may help @@ -108,12 +109,14 @@ class DatasetTransmitCommand: ds: DatasetId idx: int # TODO consider using in tracing all over. Would need scheduler to assign it + @dataclass(frozen=True) class DatasetPersistCommand: source: HostId ds: DatasetId storage_type: CheckpointStorageType - persist_params: str # storage-type-specific serialization of params + persist_params: str # storage-type-specific serialization of params + @dataclass(frozen=True) class DatasetTransmitPayloadHeader: @@ -135,33 +138,39 @@ class DatasetTransmitFailure: host: HostId detail: str + @dataclass(frozen=True) class DatasetPersistFailure: host: HostId detail: str + @dataclass(frozen=True) class DatasetPersistSuccess: host: HostId ds: DatasetId + @dataclass(frozen=True) class DatasetRetrieveCommand: target: HostId ds: DatasetId storage_type: CheckpointStorageType - retrieve_params: str # storage-type-specific serialization of params + retrieve_params: str # storage-type-specific serialization of params + @dataclass(frozen=True) class DatasetRetrieveFailure: host: HostId detail: str + @dataclass(frozen=True) class DatasetRetrieveSuccess: host: HostId ds: DatasetId + @dataclass(frozen=True) class ExecutorFailure: host: HostId diff --git a/src/cascade/executor/platform.py b/src/cascade/executor/platform.py index 98d7538c..8923a434 100644 --- a/src/cascade/executor/platform.py +++ b/src/cascade/executor/platform.py @@ -20,7 +20,6 @@ def get_bindabble_self(): """Returns a hostname such that zmq can bind to it""" - if sys.platform == "darwin": # NOTE on macos, getfqdn usually returns like '66246.local', which can't then be bound to # This is a stopper for running a cluster of macos devices -- but we don't plan that yet @@ -43,7 +42,9 @@ def gpu_init(worker_num: int): _MpSituation = typing.get_args(MpSituation) -def get_mp_ctx(situation: MpSituation) -> mp.context.ForkContext | mp.context.SpawnContext | mp.context.ForkServerContext: +def get_mp_ctx( + situation: MpSituation, +) -> mp.context.ForkContext | mp.context.SpawnContext | mp.context.ForkServerContext: """Generally, forking is safe everywhere as we try to be careful not to initialize non-safe objects prior to forking. However, combination of mac + mps + anemoi + pickled callables causes xpc_error_connection_invalid, @@ -53,7 +54,6 @@ def get_mp_ctx(situation: MpSituation) -> mp.context.ForkContext | mp.context.Sp We distinguish in which situation is this method called, as fine graining may be (eventually) possible """ - if situation not in _MpSituation: raise CascadeInternalError(f"{situation=} is not in {_MpSituation}") if sys.platform == "darwin": diff --git a/src/cascade/executor/runner/entrypoint.py b/src/cascade/executor/runner/entrypoint.py index fcc2e406..4836340c 100644 --- a/src/cascade/executor/runner/entrypoint.py +++ b/src/cascade/executor/runner/entrypoint.py @@ -9,14 +9,11 @@ """The entrypoint itself""" import logging -import logging.config import os from dataclasses import dataclass -from typing import Any import cloudpickle import zmq -from typing_extensions import Self import cascade.executor.platform as platform import cascade.executor.serde as serde @@ -36,7 +33,7 @@ from cascade.executor.runner.packages import PackagesEnv, PostinstallException from cascade.executor.runner.runner import ExecutionContext, run from cascade.low.core import DatasetId, JobInstance, TaskId, WorkerId, type_dec -from cascade.low.exceptions import CascadeError, CascadeInfrastructureError, CascadeInternalError, ser +from cascade.low.exceptions import CascadeInternalError, ser from cascade.low.tracing import label logger = logging.getLogger(__name__) @@ -75,9 +72,12 @@ def project(self, taskSequence: TaskSequence) -> ExecutionContext: ) -def task_sequence_postmortem(ctx: RunnerContext, taskSequence: TaskSequence, cut: TaskId) -> list[tuple[DatasetId, str]]: +def task_sequence_postmortem( + ctx: RunnerContext, taskSequence: TaskSequence, cut: TaskId +) -> list[tuple[DatasetId, str]]: """Assuming a failure at task Cut, identify which datasets from the beginning of - the sequence should be additionaly published. Returns datasetid + its type""" + the sequence should be additionaly published. Returns datasetid + its type + """ finished = set() required = set() found = False @@ -95,7 +95,8 @@ def task_sequence_postmortem(ctx: RunnerContext, taskSequence: TaskSequence, cut def task_sequence_remainder(taskSequence: TaskSequence, cut: TaskId) -> TaskSequence: """Assuming a failure at task Cut, calculate new task sequence which starts with Cut - that represents the still-to-be-done-in-new-worker calculation""" + that represents the still-to-be-done-in-new-worker calculation + """ remainder = [] for task in taskSequence.tasks: if task == cut or remainder: @@ -140,7 +141,8 @@ def execute_sequence( runnerContext: RunnerContext, ) -> bool: """Returns whether ended successfully. If not, it means a failure callback - was issued, and the outer loop should only wait for WorkerShutdown message.""" + was issued, and the outer loop should only wait for WorkerShutdown message. + """ taskId: TaskId | None = None try: for key, value in taskSequence.extra_env: @@ -178,7 +180,7 @@ def execute_sequence( def entrypoint(runnerContextClpkl: bytes): - """runnerContext is a cloudpickled instance of RunnerContext -- needed for forkserver mp context due to defautdicts""" + """RunnerContext is a cloudpickled instance of RunnerContext -- needed for forkserver mp context due to defautdicts""" runnerContext = cloudpickle.loads(runnerContextClpkl) init_from_obj(runnerContext.loggingConfig, f"worker_{runnerContext.workerId.worker}") ctx = zmq.Context() @@ -227,8 +229,12 @@ def entrypoint(runnerContextClpkl: bytes): elif isinstance(mDes, TaskSequence): if waiting_ts is not None: raise CascadeInternalError(f"double task sequence enqueued: 1/ {waiting_ts}, 2/ {mDes}") - required = {dataset_id for task in mDes.tasks for dataset_id in runnerContext.param_source[task].values()} - { - DatasetId(task, key) for task in mDes.tasks for key, _ in runnerContext.job.tasks[task].definition.output_schema + required = { + dataset_id for task in mDes.tasks for dataset_id in runnerContext.param_source[task].values() + } - { + DatasetId(task, key) + for task in mDes.tasks + for key, _ in runnerContext.job.tasks[task].definition.output_schema } missing_ds = required - availab_ds if Config.pretask_flush: diff --git a/src/cascade/executor/runner/memory.py b/src/cascade/executor/runner/memory.py index e0512c5e..c3f42ed5 100644 --- a/src/cascade/executor/runner/memory.py +++ b/src/cascade/executor/runner/memory.py @@ -64,7 +64,9 @@ def additional_publish_local(self, outputIds: Iterable[tuple[DatasetId, str]]): def handle(self, outputId: DatasetId, outputSchema: str, outputValue: Any, isPublish: bool) -> None: if outputId == NO_OUTPUT_PLACEHOLDER: if outputValue is not None: - logger.warning(f"gotten output of type {type(outputValue)} where none was expected, updating annotation") + logger.warning( + f"gotten output of type {type(outputValue)} where none was expected, updating annotation" + ) outputSchema = "Any" else: outputValue = "ok" @@ -113,7 +115,9 @@ def flush(self, datasets: set[DatasetId] = set()) -> None: # after every taskSequence. In principle, we could purge some locals earlier, and ideally scheduler # would invoke some targeted purges to also remove some published ones earlier (eg, they are still # needed somewhere but not here) - purgeable = [inputId for inputId in self.local if inputId not in self.bufs and (not datasets or inputId in datasets)] + purgeable = [ + inputId for inputId in self.local if inputId not in self.bufs and (not datasets or inputId in datasets) + ] logger.debug(f"will flush {len(purgeable)} datasets") for inputId in purgeable: self.local.pop(inputId) diff --git a/src/cascade/executor/runner/packages.py b/src/cascade/executor/runner/packages.py index ae67c937..20114e49 100644 --- a/src/cascade/executor/runner/packages.py +++ b/src/cascade/executor/runner/packages.py @@ -91,7 +91,8 @@ def new_venv() -> tempfile.TemporaryDirectory: def _parse_pip_install(pip_output: str) -> dict[str, Version]: """Assumed input like: 'Using Python 3.11.8 environment at: \nResolved 1 package in 5ms\nUninstalled 1 package in 12ms\nInstalled 1 package in 18ms\n - numpy==2.4.2\n + numpy==2.4.1\n' - Provided output: {'numpy': '2.4.1'}""" + Provided output: {'numpy': '2.4.1'} + """ rv = {} for line in pip_output.splitlines(): clean_line = line.strip() @@ -134,7 +135,9 @@ def _maybe_module_version(mod_name: str) -> Version | None: try: return Version(mod.__version__) except Exception as e: - logger.warning(f"failed to parse module {mod_name} version {mod.__version__} due to {repr(e)}-- ignoring!") + logger.warning( + f"failed to parse module {mod_name} version {mod.__version__} due to {repr(e)}-- ignoring!" + ) else: logging.warning(f"Module '{mod_name}' is loaded, but has no __version__ attribute -- ignoring") @@ -223,7 +226,7 @@ def maybe_tuple(kv: str) -> None | tuple[str, str]: else: logger.warning(f"will upgrade a package {package} -- may cause issues in post-verify") yield package_spec - except Exception as e: + except Exception: logger.warning(f"failed to discern preference for package {package} -- continuing") yield package diff --git a/src/cascade/executor/serde.py b/src/cascade/executor/serde.py index b6754c33..5c85d5d4 100644 --- a/src/cascade/executor/serde.py +++ b/src/cascade/executor/serde.py @@ -52,8 +52,10 @@ def register(cls, t: Type, ser: str, des: str) -> None: des, ) + DefaultSerde = "cloudpickle.loads" + def ser_output(v: Any, annotation: str) -> tuple[bytes, str]: """Utilizes `custom_ser` attr if present, otherwise defaults to cloudpickle as the most robust general purpose serde diff --git a/src/cascade/gateway/__main__.py b/src/cascade/gateway/__main__.py index 71b2c20f..7e3ceddb 100644 --- a/src/cascade/gateway/__main__.py +++ b/src/cascade/gateway/__main__.py @@ -23,5 +23,6 @@ def main_cli( loggingConfig = init_from_cliparam(loggingConfigSer, roleLoggingStr()) serve(url, loggingConfig, troika_config, max_jobs) + if __name__ == "__main__": fire.Fire(main_cli) diff --git a/src/cascade/gateway/client.py b/src/cascade/gateway/client.py index 6b5858b9..c899cb48 100644 --- a/src/cascade/gateway/client.py +++ b/src/cascade/gateway/client.py @@ -23,7 +23,6 @@ def request_response(m: api.CascadeGatewayAPI, url: str, timeout_ms: int = 1000) -> api.CascadeGatewayAPI: """Sends a Request message, provides a corresponding Response message in a blocking manner""" - local = threading.local() if not hasattr(local, "context"): local.context = zmq.Context() diff --git a/src/cascade/gateway/router.py b/src/cascade/gateway/router.py index 9d6c6a51..91720dbb 100644 --- a/src/cascade/gateway/router.py +++ b/src/cascade/gateway/router.py @@ -79,9 +79,7 @@ def maybe_spawn(self) -> None: logger.debug(f"will spawn job {job_id} and listen on {full_addr}") self.poller.register(socket, flags=zmq.POLLIN) self.jobs[job_id] = Job(socket, JobProgressStarted, -1, {}) - self.procs[job_id] = spawn_subprocess( - job_spec, full_addr, job_id, self.loggingConfig, self.troika_config - ) + self.procs[job_id] = spawn_subprocess(job_spec, full_addr, job_id, self.loggingConfig, self.troika_config) self.active_jobs += 1 def enqueue_job(self, job_spec: JobSpec) -> JobId: @@ -106,19 +104,13 @@ def progress_of( progresses[job_id] = JobProgressEnqueued else: progresses[job_id] = None - datasets = { - job_id: list(self.jobs[job_id].results.keys()) - for job_id in job_ids - if job_id in self.jobs - } + datasets = {job_id: list(self.jobs[job_id].results.keys()) for job_id in job_ids if job_id in self.jobs} return progresses, datasets, len(self.jobs_queue) def get_result(self, job_id: JobId, dataset_id: DatasetId) -> bytes: return self.jobs[job_id].results[dataset_id] - def maybe_update( - self, job_id: JobId, progress: JobProgress | None, timestamp: int - ) -> None: + def maybe_update(self, job_id: JobId, progress: JobProgress | None, timestamp: int) -> None: if progress is None: return job = self.jobs[job_id] diff --git a/src/cascade/gateway/spawning.py b/src/cascade/gateway/spawning.py index e0b860a2..8aa2eca2 100644 --- a/src/cascade/gateway/spawning.py +++ b/src/cascade/gateway/spawning.py @@ -30,7 +30,9 @@ local_job_port = 12345 -def _spawn_troika_singlehost(job_spec: JobSpec, addr: str, job_id: JobId, troika: TroikaSpec, troika_config: str) -> subprocess.Popen: +def _spawn_troika_singlehost( + job_spec: JobSpec, addr: str, job_id: JobId, troika: TroikaSpec, troika_config: str +) -> subprocess.Popen: script = "#!/bin/bash\n" script += f"source {troika.venv}\n" for k, v in job_spec.envvars.items(): diff --git a/src/cascade/low/builders.py b/src/cascade/low/builders.py index 6f8ae9fb..0a2c8e39 100644 --- a/src/cascade/low/builders.py +++ b/src/cascade/low/builders.py @@ -46,14 +46,12 @@ def type2str(t: str | Type) -> str: input_schema = { p.name: type2str(p.annotation) for p in sig.parameters.values() - if p.kind - in {inspect.Parameter.KEYWORD_ONLY, inspect.Parameter.POSITIONAL_OR_KEYWORD} + if p.kind in {inspect.Parameter.KEYWORD_ONLY, inspect.Parameter.POSITIONAL_OR_KEYWORD} } static_input_kw = { p.name: p.default for p in sig.parameters.values() - if p.kind - in {inspect.Parameter.KEYWORD_ONLY, inspect.Parameter.POSITIONAL_OR_KEYWORD} + if p.kind in {inspect.Parameter.KEYWORD_ONLY, inspect.Parameter.POSITIONAL_OR_KEYWORD} and p.default != inspect.Parameter.empty } @@ -64,9 +62,7 @@ def type2str(t: str | Type) -> str: input_schema=input_schema, output_schema=[(DefaultTaskOutput, type2str(sig.return_annotation))], ) - return cls( - definition=definition, static_input_kw=static_input_kw, static_input_ps={} - ) + return cls(definition=definition, static_input_kw=static_input_kw, static_input_ps={}) @classmethod def from_entrypoint( @@ -92,9 +88,7 @@ def with_values(self, *args, **kwargs) -> Self: new_kwargs = {**self.static_input_kw, **kwargs} ps_args = {str(k): v for k, v in dict(enumerate(args)).items()} new_args = {**self.static_input_ps, **ps_args} - return self.model_copy( - update={"static_input_kw": new_kwargs, "static_input_ps": new_args} - ) + return self.model_copy(update={"static_input_kw": new_kwargs, "static_input_ps": new_args}) @dataclass @@ -109,9 +103,7 @@ def with_node(self, name: str, task: TaskInstance) -> Self: def with_output(self, task: str, output: str = DefaultTaskOutput) -> Self: return replace(self, outputs=self.outputs.append(DatasetId(task, output))) - def with_edge( - self, source: str, sink: str, into: str | int, frum: str = DefaultTaskOutput - ) -> Self: + def with_edge(self, source: str, sink: str, into: str | int, frum: str = DefaultTaskOutput) -> Self: new_edge = Task2TaskEdge( source=DatasetId(source, frum), sink_task=sink, @@ -120,7 +112,7 @@ def with_edge( ) return replace(self, edges=self.edges.append(new_edge)) - def build(self) -> Either[JobInstance, list[str]]: # ty: ignore[invalid-type-arguments] + def build(self) -> Either[JobInstance, list[str]]: # ty: ignore[invalid-type-arguments] # TODO replace `_isinstance` with a smarter check for self-reg types, reuse fiab/type_system skipped = { "latitude", @@ -133,9 +125,7 @@ def build(self) -> Either[JobInstance, list[str]]: # ty: ignore[invalid-type-arg def getType( fqn: str, - ) -> ( - Any - ): # NOTE: typing.Type return type is tempting but not true for builtin aliases + ) -> Any: # NOTE: typing.Type return type is tempting but not true for builtin aliases if fqn.startswith("tuple"): # TODO recursive parsing of tuples etc! return tuple @@ -145,9 +135,7 @@ def getType( else: return eval(fqn) - _isinstance = ( - lambda v, t: t == "Any" or t in skipped or isinstance(v, getType(t)) - ) + _isinstance = lambda v, t: t == "Any" or t in skipped or isinstance(v, getType(t)) # static input types static_kw_errors: Iterable[str] = ( @@ -175,29 +163,24 @@ def get_edge_errors(edge: Task2TaskEdge) -> Iterator[str]: else: if edge.sink_input_kw is None: return - input_param = sink_task.definition.input_schema.get( - edge.sink_input_kw, None - ) + input_param = sink_task.definition.input_schema.get(edge.sink_input_kw, None) if not input_param: yield f"edge pointing to non-existent param {edge.sink_input_kw}" if not output_param or not input_param: return # TODO replace `issubclass` with a smarter check for self-reg types legits = {("grib.earthkit", "grib.mir"), ("grib.mir", "grib.earthkit")} - _issubclass = ( - lambda t1, t2: t2 == "Any" + _issubclass = lambda t1, t2: ( + t2 == "Any" or t1 == t2 or (t1, t2) in legits - or t1 - == "typing.Iterator" # TODO replace with type extraction *and* check that this is multi-output + or t1 == "typing.Iterator" # TODO replace with type extraction *and* check that this is multi-output or issubclass(getType(t1), getType(t2)) ) if not _issubclass(output_param, input_param): yield f"edge connects two incompatible nodes: {edge}" - edge_errors: Iterable[str] = ( - error for edge in self.edges for error in get_edge_errors(edge) - ) + edge_errors: Iterable[str] = (error for edge in self.edges for error in get_edge_errors(edge)) # all inputs present # TODO diff --git a/src/cascade/low/core.py b/src/cascade/low/core.py index f234f6d2..71ad4f63 100644 --- a/src/cascade/low/core.py +++ b/src/cascade/low/core.py @@ -28,7 +28,7 @@ NO_OUTPUT_PLACEHOLDER = "__NO_OUTPUT__" # name of the output of the task in case the task has exactly one, ie, the callable is not a generator -DefaultTaskOutput = "0" +DefaultTaskOutput = "0" # Definitions @@ -51,9 +51,7 @@ class TaskDefinition(BaseModel): output_schema: list[tuple[str, str]] = Field( description="kv of outputs and their types (fqn of class). Assumes listing in func output order" ) - needs_gpu: bool = Field( - False - ) # NOTE unstable contract, will change. Note we support at most one GPU per task + needs_gpu: bool = Field(False) # NOTE unstable contract, will change. Note we support at most one GPU per task @staticmethod def func_dec(f: str) -> Callable: @@ -76,7 +74,7 @@ def __repr__(self) -> str: return f"{self.task}.{self.output}" def ser(self) -> str: - pref = len(self.task).to_bytes(length=1, byteorder='big').hex() + pref = len(self.task).to_bytes(length=1, byteorder="big").hex() # NOTE this raises if the task id is too long, but we dont want to have that long fnames anyway # if that poses a problem, we need to switch into short hashes and a lookup file persisted separately # NOTE we cant pick any safe separator between task and output, because either can contain any char @@ -84,8 +82,8 @@ def ser(self) -> str: @classmethod def des(cls, value: str) -> Self: - pref, suf = value.split('.', 1) - task_len = int.from_bytes(bytes.fromhex(pref), byteorder='big') + pref, suf = value.split(".", 1) + task_len = int.from_bytes(bytes.fromhex(pref), byteorder="big") return cls(task=suf[:task_len], output=suf[task_len:]) @@ -145,10 +143,7 @@ class JobInstance(BaseModel): ) def outputs_of(self, task_id: TaskId) -> set[DatasetId]: - return { - DatasetId(task_id, output) - for output, _ in self.tasks[task_id].definition.output_schema - } + return {DatasetId(task_id, output) for output, _ in self.tasks[task_id].definition.output_schema} HostId = str @@ -189,12 +184,8 @@ class Environment(BaseModel): class TaskExecutionRecord(BaseModel): # NOTE rather crude -- we may want to granularize cpuseconds - cpuseconds: int = Field( - description="as measured from process start to process end, assuming full cpu util" - ) - memory_mb: int = Field( - description="observed rss peak held by the process minus sizes of shared memory inputs" - ) + cpuseconds: int = Field(description="as measured from process start to process end, assuming full cpu util") + memory_mb: int = Field(description="observed rss peak held by the process minus sizes of shared memory inputs") # possibly made configurable, overridable -- quite job dependent @@ -203,9 +194,7 @@ class TaskExecutionRecord(BaseModel): class JobExecutionRecord(BaseModel): - tasks: dict[TaskId, TaskExecutionRecord] = Field( - default_factory=lambda: defaultdict(lambda: no_record_ts) - ) + tasks: dict[TaskId, TaskExecutionRecord] = Field(default_factory=lambda: defaultdict(lambda: no_record_ts)) datasets_mb: dict[DatasetId, int] = Field( default_factory=lambda: defaultdict(lambda: no_record_ds) ) # keyed by (task, output) diff --git a/src/cascade/low/exceptions.py b/src/cascade/low/exceptions.py index b7038508..887e775a 100644 --- a/src/cascade/low/exceptions.py +++ b/src/cascade/low/exceptions.py @@ -51,7 +51,7 @@ class CascadeUserError(CascadeError): pass -def ser(e: Exception, extra_context: str|None = None) -> str: +def ser(e: Exception, extra_context: str | None = None) -> str: """Serialize error to a string representation, converting to CascadeError first if needed.""" # we go with InternalError, because context-aware conversions should have happened prior e = e if isinstance(e, CascadeError) else CascadeInternalError(description=repr(e), parent=e) @@ -59,24 +59,29 @@ def ser(e: Exception, extra_context: str|None = None) -> str: e.add_context(extra_context) return repr(e) + def des(s: str) -> CascadeError: """Deserialize a string back to a CascadeError. - + Attempts to parse the string as '()'. If successful, constructs the appropriate exception class. Otherwise, returns CascadeInternalError with the input string. Parent field is always set to None. """ import re - + # Try to match pattern: ClassName('detail') or ClassName("detail") # We need to handle both single and double quotes, and escaped quotes - match = re.match(r"^(CascadeError|CascadeInternalError|CascadeInfrastructureError|CascadeUserError)\((['\"])(.+?)\2(?:, parent=.*)?\)$", s, re.DOTALL) - + match = re.match( + r"^(CascadeError|CascadeInternalError|CascadeInfrastructureError|CascadeUserError)\((['\"])(.+?)\2(?:, parent=.*)?\)$", + s, + re.DOTALL, + ) + if match: class_name = match.group(1) detail = match.group(3) - + # Map class name to actual class class_map = { "CascadeError": CascadeError, @@ -84,10 +89,10 @@ def des(s: str) -> CascadeError: "CascadeInfrastructureError": CascadeInfrastructureError, "CascadeUserError": CascadeUserError, } - + exc_class = class_map.get(class_name) if exc_class: return exc_class(description=detail, parent=None) - + # If parsing fails, return as CascadeInternalError return CascadeInternalError(description=s, parent=None) diff --git a/src/cascade/low/func.py b/src/cascade/low/func.py index e8f22d02..3b7a205d 100644 --- a/src/cascade/low/func.py +++ b/src/cascade/low/func.py @@ -170,7 +170,6 @@ def pydantic_recursive_collect(base: BaseModel | Iterable, attr: str, prefix: st of the issuer -- eg if base has BaseModel field `x` whose `attr` yields [1, 2], then this returns [(.x, 1), (.x, 2)] """ - # NOTE a bit ugly, instead of attr it would be better to accept a signature/protocol type results: list[tuple[str, Any]] = [] diff --git a/src/cascade/low/tracing.py b/src/cascade/low/tracing.py index da0a21b6..eb6e0bd2 100644 --- a/src/cascade/low/tracing.py +++ b/src/cascade/low/tracing.py @@ -28,15 +28,11 @@ class TaskLifecycle(str, Enum): planned = "task_planned" # controller planned the task to run at a worker - enqueued = ( - "task_enqueued" # worker received the task and put into its internal queue - ) + enqueued = "task_enqueued" # worker received the task and put into its internal queue started = "task_started" # a process executing this task is ready and imported loaded = "task_loaded" # all task's inputs are in process memory and deserialized computed = "task_computed" # the task callable itself has finished - published = ( - "task_published" # the results have been serialized and put to shared memory - ) + published = "task_published" # the results have been serialized and put to shared memory completed = "task_completed" # the controller marked this task as completed diff --git a/src/cascade/main.py b/src/cascade/main.py index 425af14d..75ee3ba9 100644 --- a/src/cascade/main.py +++ b/src/cascade/main.py @@ -25,12 +25,11 @@ from cascade.deployment.logging import DefaultLoggingConfig, LoggingConfig, init_from_cliparam, init_from_obj from cascade.executor.bridge import Bridge from cascade.executor.comms import callback -from cascade.executor.config import logging_config, logging_config_filehandler +from cascade.executor.config import logging_config from cascade.executor.executor import Executor from cascade.executor.msg import BackboneAddress, ExecutorShutdown -from cascade.low.core import DatasetId, JobInstance, JobInstanceRich +from cascade.low.core import DatasetId, JobInstanceRich from cascade.low.exceptions import CascadeError, CascadeInfrastructureError -from cascade.low.func import msum from cascade.scheduler.precompute import precompute logger = logging.getLogger(__name__) @@ -46,7 +45,9 @@ def _get_cuda_count() -> int: return visible_count gpus = sum( 1 - for l in subprocess.run(["nvidia-smi", "--list-gpus"], check=True, capture_output=True).stdout.decode("ascii").split("\n") + for l in subprocess.run(["nvidia-smi", "--list-gpus"], check=True, capture_output=True) + .stdout.decode("ascii") + .split("\n") if "GPU" in l ) except: diff --git a/src/cascade/scheduler/api.py b/src/cascade/scheduler/api.py index f5b323db..aaa0ee11 100644 --- a/src/cascade/scheduler/api.py +++ b/src/cascade/scheduler/api.py @@ -37,7 +37,9 @@ def gang_check_ready(task: TaskId, gang_prep: GangPreparation): """ for gang in gang_prep.lookup[task]: if gang not in gang_prep.countdown: - raise CascadeInternalError(description=f"after {task=} marked computable, {gang=} not found -- double compuptable mark?") + raise CascadeInternalError( + description=f"after {task=} marked computable, {gang=} not found -- double compuptable mark?" + ) remaining = gang_prep.countdown[gang] if task not in remaining: raise CascadeInternalError( @@ -118,7 +120,6 @@ def assign(schedule: Schedule, context: JobExecutionContext) -> Iterator[Assignm Performance critical section, we need to output an assignment asap. Steps taking longer should be deferred to `plan` """ - # step I: assign within existing components component2workers: dict[ComponentId, list[WorkerId]] = defaultdict(list) for worker in context.idle_workers: @@ -133,7 +134,11 @@ def assign(schedule: Schedule, context: JobExecutionContext) -> Iterator[Assignm return # step II: assign remaining workers to new components - components = [(component.weight, component_id) for component_id, component in enumerate(schedule.components) if component.weight > 0] + components = [ + (component.weight, component_id) + for component_id, component in enumerate(schedule.components) + if component.weight > 0 + ] if not components: return @@ -159,7 +164,6 @@ def plan(schedule: Schedule, context: JobExecutionContext, assignments: list[Ass and planning for future assignments. Unlike `assign`, this is less performance critical, so slightly longer calculations can happen here. """ - # TODO when considering `children` below, filter for near-computable? Ie, either already in computable # or all inputs are already in preparing state? May not be worth it tho diff --git a/src/cascade/scheduler/assign.py b/src/cascade/scheduler/assign.py index 0552cd02..43eb03d0 100644 --- a/src/cascade/scheduler/assign.py +++ b/src/cascade/scheduler/assign.py @@ -57,7 +57,11 @@ def build_assignment(worker: WorkerId, task: TaskId, context: JobExecutionContex else: # TODO instead of any, pick the best host -- business, distance, etc # Note also that one of the hosts may be the VirtualCheckpointHost - if any(candidate := host for host, status in context.ds2host[dataset].items() if status in eligible_transmit): + if any( + candidate := host + for host, status in context.ds2host[dataset].items() + if status in eligible_transmit + ): prep.append((dataset, candidate)) # ty: ignore[unresolved-reference] # candidate walrus context.dataset_preparing(dataset, worker) else: @@ -83,7 +87,9 @@ def build_assignment(worker: WorkerId, task: TaskId, context: JobExecutionContex # trim for only the necessary ones: 1/ having any edge outside of this assignment 2/ global output 3/ persistable all_outputs = {ds for task in assigned for ds in context.task_o[task]} assigned_tasks = set(assigned) - trimmed_outputs = {ds for ds in all_outputs if (context.edge_o[ds] - assigned_tasks) or context.publication_mandatory(ds)} + trimmed_outputs = { + ds for ds in all_outputs if (context.edge_o[ds] - assigned_tasks) or context.publication_mandatory(ds) + } return Assignment( worker=worker, @@ -163,7 +169,9 @@ def _try_assign_gang( coordinator = None # similarly to _assignment_heuristic, a greedy algorithm - candidates = [(schedule.worker2task_overhead[w][t], component.core.value[t], w, t) for w in gpu_workers for t in gpu_tasks] + candidates = [ + (schedule.worker2task_overhead[w][t], component.core.value[t], w, t) for w in gpu_workers for t in gpu_tasks + ] candidates.sort(key=lambda e: (e[0], e[1])) for _, _, worker, task in candidates: if task in gpu_tasks and worker in gpu_workers: @@ -188,7 +196,9 @@ def _try_assign_gang( raise CascadeInternalError(description=f"expected to assign all gang gpu tasks, yet {gpu_tasks} remain") all_workers = cpu_workers.union(gpu_workers) - candidates = [(schedule.worker2task_overhead[w][t], component.core.value[t], w, t) for w in all_workers for t in cpu_tasks] + candidates = [ + (schedule.worker2task_overhead[w][t], component.core.value[t], w, t) for w in all_workers for t in cpu_tasks + ] candidates.sort(key=lambda e: (e[0], e[1])) for _, _, worker, task in candidates: if task in cpu_tasks and worker in all_workers: @@ -253,7 +263,9 @@ def _assignment_heuristic( # second, sort task-worker combination by first overhead, second value, and pick greedily remaining_t = set(unassigned) remaining_w = set(workers) - candidates = [(schedule.worker2task_overhead[w][t], component.core.value[t], w, t) for w in workers for t in remaining_t] + candidates = [ + (schedule.worker2task_overhead[w][t], component.core.value[t], w, t) for w in workers for t in remaining_t + ] candidates.sort(key=lambda e: (e[0], e[1])) for _, _, worker, task in candidates: if task in remaining_t and worker in remaining_w: @@ -315,7 +327,9 @@ def assign_within_component( cpu_t.append(task) # tasks immediately needing a gpu - eligible_w = [worker for worker in workers if context.environment.workers[worker].gpu > 0 and worker in context.idle_workers] + eligible_w = [ + worker for worker in workers if context.environment.workers[worker].gpu > 0 and worker in context.idle_workers + ] logger.debug( f"considering {len(gpu_t)}# gpu tasks, {len(opu_t)}# maybe-gpu tasks, {len(cpu_t)}# cpu tasks, with {len(workers)}# workers out of which {len(eligible_w)} have gpu" ) diff --git a/src/cascade/scheduler/checkpoints.py b/src/cascade/scheduler/checkpoints.py index 46770f1a..81cb791c 100644 --- a/src/cascade/scheduler/checkpoints.py +++ b/src/cascade/scheduler/checkpoints.py @@ -7,11 +7,11 @@ # nor does it submit to any jurisdiction. """Scheduling-related checkpoint utilities, namely: - - trim_with_persisted -- given a graph and a set of nodes which are persisted, - discard everything that doesnt need to be computed - - virtual_update_schedule -- as we start executing, we virtually publish all - checkpointed datasets. That on its own would break some invariants in - the schedule, so we do all the corrections in this function +- trim_with_persisted -- given a graph and a set of nodes which are persisted, +discard everything that doesnt need to be computed +- virtual_update_schedule -- as we start executing, we virtually publish all +checkpointed datasets. That on its own would break some invariants in +the schedule, so we do all the corrections in this function """ import logging @@ -23,17 +23,15 @@ logger = logging.getLogger(__name__) + def _filter_invalid(job: JobInstance, persisted: set[DatasetId]) -> tuple[set[TaskId], set[DatasetId]]: """Filters out those persisted datasets that overlap partially with a gang or provide only partial outputs - of a task""" + of a task + """ persisted_per_task = defaultdict(set) for ds in persisted: persisted_per_task[ds.task].add(ds) - persisted_tasks = { - task - for task, dss in persisted_per_task.items() - if job.outputs_of(task) == dss - } + persisted_tasks = {task for task, dss in persisted_per_task.items() if job.outputs_of(task) == dss} rem = set(persisted_per_task.keys()) - persisted_tasks if rem: logger.warning(f"ignoring persisted outputs of tasks {rem} because of output partiality") @@ -43,13 +41,10 @@ def _filter_invalid(job: JobInstance, persisted: set[DatasetId]) -> tuple[set[Ta if rem != gang_set: persisted_tasks = persisted_tasks - rem logger.warning(f"ignoring persisted outputs of tasks {rem} because of gang partiality") - persisted_datasets = { - dataset - for task in persisted_tasks - for dataset in persisted_per_task[task] - } + persisted_datasets = {dataset for task in persisted_tasks for dataset in persisted_per_task[task]} return persisted_tasks, persisted_datasets + def _get_parents(component: ComponentCore, preschedule: Preschedule) -> dict[TaskId, set[TaskId]]: """Just convert edge_i into a task-task dict""" parents: dict[TaskId, set[TaskId]] = defaultdict(set) @@ -58,9 +53,15 @@ def _get_parents(component: ComponentCore, preschedule: Preschedule) -> dict[Tas parents[node].add(dataset.task) return parents -def _discover_component(component: ComponentCore, parents: dict[TaskId, set[TaskId]], job: JobInstance, preschedule: Preschedule, persisted_tasks: set[TaskId]) -> set[TaskId]: - """Returns only the valid nodes, ie, those that are either persisted or should be computed""" +def _discover_component( + component: ComponentCore, + parents: dict[TaskId, set[TaskId]], + job: JobInstance, + preschedule: Preschedule, + persisted_tasks: set[TaskId], +) -> set[TaskId]: + """Returns only the valid nodes, ie, those that are either persisted or should be computed""" visitable = defaultdict(set) for node in component.nodes: for d in job.outputs_of(node): @@ -79,17 +80,17 @@ def _discover_component(component: ComponentCore, parents: dict[TaskId, set[Task queue.append(parent) return is_valid -def _trim_component(component: ComponentCore, parents: dict[TaskId, set[TaskId]], preserved_tasks: set[TaskId]) -> ComponentCore: + +def _trim_component( + component: ComponentCore, parents: dict[TaskId, set[TaskId]], preserved_tasks: set[TaskId] +) -> ComponentCore: """Restricts the component only to preserved tasks""" nodes = list(preserved_tasks) - value={node: component.value[node] for node in nodes} + value = {node: component.value[node] for node in nodes} return ComponentCore( nodes=nodes, sources=[node for node in nodes if not parents[node]], - distance_matrix={ - a: {b: component.distance_matrix[a][b] for b in nodes} - for a in nodes - }, + distance_matrix={a: {b: component.distance_matrix[a][b] for b in nodes} for a in nodes}, value=value, depth=max(value.values()), fusing_opportunities={ @@ -102,13 +103,17 @@ def _trim_component(component: ComponentCore, parents: dict[TaskId, set[TaskId]] gpu_fused_distance={node: component.gpu_fused_distance[node] for node in nodes}, ) -def trim_with_persisted(jobRich: JobInstanceRich, preschedule: Preschedule, persisted: set[DatasetId]) -> tuple[JobInstance, Preschedule, set[DatasetId]]: + +def trim_with_persisted( + jobRich: JobInstanceRich, preschedule: Preschedule, persisted: set[DatasetId] +) -> tuple[JobInstance, Preschedule, set[DatasetId]]: """Removes from job and preschedule everything that does not need to be computed anymore, ie, lies in the subgraph of nodes for which every path to a sink goes through a persisted dataset Some persisted sets may be ignored, such as if they are only a part of a gang, or only - a part of a task's output -- we thus return the modified persisted set""" + a part of a task's output -- we thus return the modified persisted set + """ job = jobRich.jobInstance persisted_tasks, persisted_datasets = _filter_invalid(job, persisted) @@ -137,17 +142,22 @@ def trim_with_persisted(jobRich: JobInstanceRich, preschedule: Preschedule, pers job_mod = JobInstance( tasks={taskId: taskInstance for taskId, taskInstance in job.tasks.items() if taskId in preserved_tasks_all}, - edges=[edge for edge in job.edges if edge.source.task in preserved_tasks_all and edge.sink_task in preserved_tasks_all], + edges=[ + edge + for edge in job.edges + if edge.source.task in preserved_tasks_all and edge.sink_task in preserved_tasks_all + ], serdes=job.serdes, ext_outputs=[dataset for dataset in job.ext_outputs if dataset.task in preserved_tasks_all], constraints=[constraint for constraint in job.constraints if set(constraint) <= preserved_tasks_all], ) return job_mod, preschedule_mod, persisted_datasets + def virtual_update_schedule(datasets: set[DatasetId], schedule: Schedule, context: JobExecutionContext) -> None: """Include all tasks that are children of these datasets in the worker2task_values - of the component, and remove the tasks corresponding to these datasets from there and from computable.""" - + of the component, and remove the tasks corresponding to these datasets from there and from computable. + """ # TODO order by component and make this more efficient finished_tasks = set(ds.task for ds in datasets) diff --git a/src/cascade/scheduler/core.py b/src/cascade/scheduler/core.py index 39e22c88..0c613e31 100644 --- a/src/cascade/scheduler/core.py +++ b/src/cascade/scheduler/core.py @@ -46,15 +46,11 @@ class Preschedule: @dataclass class GangPreparation: - ready: list[ - frozenset[TaskId] - ] # used by scheduler to see if any gangs can be assigned/started + ready: list[frozenset[TaskId]] # used by scheduler to see if any gangs can be assigned/started countdown: dict[ frozenset[TaskId], set[TaskId] ] # used to check after a task completion whether a gang can be moved to ready - lookup: dict[ - TaskId, list[frozenset[TaskId]] - ] # used to decrease countdown after a task completion + lookup: dict[TaskId, list[frozenset[TaskId]]] # used to decrease countdown after a task completion @dataclass diff --git a/src/cascade/scheduler/precompute.py b/src/cascade/scheduler/precompute.py index 9aed4ab6..11e99a77 100644 --- a/src/cascade/scheduler/precompute.py +++ b/src/cascade/scheduler/precompute.py @@ -115,9 +115,7 @@ def _enrich( gangs: set[TaskId], ) -> ComponentCore: nodes, sources = plain_component - logger.debug( - f"enrich component start; {len(nodes)} nodes, of that {len(sources)} sources" - ) + logger.debug(f"enrich component start; {len(nodes)} nodes, of that {len(sources)} sources") sinks = [v for v in nodes if not edge_o[v]] remaining = {v: len(edge_o[v]) for v in nodes if edge_o[v]} @@ -218,16 +216,8 @@ def precompute(job_instance: JobInstance) -> Preschedule: for vert, inps in edge_i.items(): edge_i_proj[vert] = {dataset.task for dataset in inps} - needs_gpu = { - task_id - for task_id, task in job_instance.tasks.items() - if task.definition.needs_gpu - } - gangs = { - task_id - for constraint in job_instance.constraints - for task_id in constraint.gang - } + needs_gpu = {task_id for task_id, task in job_instance.tasks.items() if task.definition.needs_gpu} + gangs = {task_id for constraint in job_instance.constraints for task_id in constraint.gang} with ThreadPoolExecutor(max_workers=4) as tp: # TODO if coptrs is not used, then this doesnt make sense diff --git a/src/cascade/shm/api.py b/src/cascade/shm/api.py index 7271139e..a4b765d4 100644 --- a/src/cascade/shm/api.py +++ b/src/cascade/shm/api.py @@ -110,7 +110,13 @@ class GetResponse: deser_fun: str def ser(self) -> bytes: - return self.l.to_bytes(4, "big") + ser_str(self.deser_fun) + ser_str(self.shmid) + ser_str(self.rdid) + ser_str(self.error) + return ( + self.l.to_bytes(4, "big") + + ser_str(self.deser_fun) + + ser_str(self.shmid) + + ser_str(self.rdid) + + ser_str(self.error) + ) @classmethod def deser(cls, data: memoryview) -> Self: diff --git a/src/cascade/shm/disk.py b/src/cascade/shm/disk.py index 705c4992..93d8edea 100644 --- a/src/cascade/shm/disk.py +++ b/src/cascade/shm/disk.py @@ -27,7 +27,8 @@ def __init__(self) -> None: def _page_in(self, shmid: str, size: int, callback: Callable[[bool], None]) -> None: try: chunk_size = 4096 - shm = SharedMemory(shmid, create=True, size=size); assert shm.buf is not None + shm = SharedMemory(shmid, create=True, size=size) + assert shm.buf is not None with open(f"{self.root.name}/{shmid}", "rb") as f: i = 0 while True: @@ -51,7 +52,8 @@ def page_in(self, shmid: str, size: int, callback: Callable) -> None: def _page_out(self, shmid: str, callback: Callable[[bool], None]) -> None: try: - shm = SharedMemory(shmid, create=False); assert shm.buf is not None + shm = SharedMemory(shmid, create=False) + assert shm.buf is not None with open(f"{self.root.name}/{shmid}", "wb") as f: f.write(shm.buf[:]) shm.unlink() diff --git a/src/cascade/shm/func.py b/src/cascade/shm/func.py index e720bd27..ad3e4071 100644 --- a/src/cascade/shm/func.py +++ b/src/cascade/shm/func.py @@ -14,9 +14,11 @@ class ShmInternalError(ValueError): pass + class ShmInfrastructureError(ValueError): pass + def assert_never(v: Any) -> NoReturn: """For exhaustive enumm checks etc""" raise TypeError(f"unexpected value in exhaustive check: {v!r}") diff --git a/src/earthkit/workflows/_qubed.py b/src/earthkit/workflows/_qubed.py index dc0e163e..b659ed37 100644 --- a/src/earthkit/workflows/_qubed.py +++ b/src/earthkit/workflows/_qubed.py @@ -18,6 +18,7 @@ from earthkit.workflows.fluent import Action + def _convert_num_to_abc(num: int) -> str: """Convert a number to its corresponding alphabetical representation. 0 -> 'a', 1 -> 'b', ..., 25 -> 'z', 26 -> 'aa', etc. @@ -31,12 +32,14 @@ def _convert_num_to_abc(num: int) -> str: num -= 1 return result + def get_name(child: "Qube", index: int) -> str: if "name" in child.metadata: name_meta = child.metadata["name"] return str(np.unique_values(name_meta).flatten()[0]) return _convert_num_to_abc(index) + def expand_as_qube(action: "Action", qube: "Qube") -> "Action": """Expand an action according to a qube structure. @@ -108,7 +111,6 @@ def expand_as_qube(action: "Action", qube: "Qube") -> "Action": >>> expanded_action = expand_as_qube(action, qube_without_step) # Action expanded over param dimension only """ - leaves: dict[str, Action] = {} def expand_fn(action: "Action", qube: "Qube", path: str) -> "Action": @@ -126,9 +128,9 @@ def expand_fn(action: "Action", qube: "Qube", path: str) -> "Action": case _: # Multiple children, need to split into branches for i, child in enumerate(qube.children): expand_fn(action, child, f"{path}/{get_name(child, i)}") - + return fluent.merge(**leaves) - + if not qube.children: return action return expand_fn(action, qube, "") diff --git a/src/earthkit/workflows/adapters.py b/src/earthkit/workflows/adapters.py index a9097a72..cc50964f 100644 --- a/src/earthkit/workflows/adapters.py +++ b/src/earthkit/workflows/adapters.py @@ -14,10 +14,9 @@ Currently, only cascade is supported. """ -import logging - try: from cascade.low.core import DefaultTaskOutput + DefaultNodeOutput = DefaultTaskOutput except ImportError: logger.error("failed to import any execution engine! Defaulting to dummy impl") diff --git a/src/earthkit/workflows/backends/__init__.py b/src/earthkit/workflows/backends/__init__.py index 6b84ec36..cfc9b7ae 100644 --- a/src/earthkit/workflows/backends/__init__.py +++ b/src/earthkit/workflows/backends/__init__.py @@ -27,9 +27,7 @@ def register(type, backend): if type in BACKENDS: - logger.warning( - f"Overwriting backend for {type}. Existing backend {BACKENDS[type]}." - ) + logger.warning(f"Overwriting backend for {type}. Existing backend {BACKENDS[type]}.") BACKENDS[type] = backend @@ -88,9 +86,7 @@ def decorator(func: Callable) -> Callable: def check_num_args(*args, **kwargs): if accept_nested and len(args) == 1: args = args[0] - assert ( - len(args) == expect - ), f"{func.__name__} expects two input arguments, got {len(args)}" + assert len(args) == expect, f"{func.__name__} expects two input arguments, got {len(args)}" return func(*args, **kwargs) return check_num_args diff --git a/src/earthkit/workflows/backends/earthkit.py b/src/earthkit/workflows/backends/earthkit.py index 1940de66..6db43fe3 100644 --- a/src/earthkit/workflows/backends/earthkit.py +++ b/src/earthkit/workflows/backends/earthkit.py @@ -9,9 +9,9 @@ from typing import TypeAlias import array_api_compat - from earthkit.data import FieldList from earthkit.data.core.metadata import Metadata as ekdMetadata + from earthkit.workflows.backends import num_args @@ -47,9 +47,7 @@ def resolve_metadata(metadata: Metadata, *args) -> dict: def new_fieldlist(data, metadata: list[ekdMetadata], overrides: dict): if len(overrides) > 0: try: - new_metadata = [ - metadata[x].override(overrides) for x in range(len(metadata)) - ] + new_metadata = [metadata[x].override(overrides) for x in range(len(metadata))] return FieldList.from_array( standardise_output(data), new_metadata, @@ -78,9 +76,7 @@ def _merge(*fieldlists: list[FieldList]): xp = array_api_compat.array_namespace(*values) return xp.asarray(values) - def multi_arg_function( - func: str, *arrays: list[FieldList], metadata: Metadata = None - ) -> FieldList: + def multi_arg_function(func: str, *arrays: list[FieldList], metadata: Metadata = None) -> FieldList: merged_array = FieldListBackend._merge(*arrays) xp = array_api_compat.array_namespace(*merged_array) res = standardise_output(getattr(xp, func)(merged_array, axis=0)) @@ -90,13 +86,9 @@ def multi_arg_function( resolve_metadata(metadata, *arrays), ) - def two_arg_function( - func: str, *arrays: FieldList, metadata: Metadata = None - ) -> FieldList: + def two_arg_function(func: str, *arrays: FieldList, metadata: Metadata = None) -> FieldList: # First argument must be FieldList - assert isinstance( - arrays[0], FieldList - ), f"Expected FieldList type, got {type(arrays[0])}" + assert isinstance(arrays[0], FieldList), f"Expected FieldList type, got {type(arrays[0])}" val1 = arrays[0].values if isinstance(arrays[1], FieldList): val2 = arrays[1].values @@ -107,9 +99,7 @@ def two_arg_function( metadata = resolve_metadata(metadata, arrays[0]) xp = array_api_compat.array_namespace(val1) res = getattr(xp, func)(val1, val2) - return new_fieldlist( - res, [arrays[0][x].metadata() for x in range(len(res))], metadata - ) + return new_fieldlist(res, [arrays[0][x].metadata() for x in range(len(res))], metadata) def mean(*arrays: list[FieldList], metadata: Metadata = None) -> FieldList: return FieldListBackend.multi_arg_function("mean", *arrays, metadata=metadata) @@ -135,9 +125,7 @@ def var(*arrays: list[FieldList], metadata: Metadata = None) -> FieldList: def stack(*arrays: list[FieldList], axis: int = 0) -> FieldList: if axis != 0: raise ValueError("Can not stack FieldList along axis != 0") - assert all( - [len(x) == 1 for x in arrays] - ), "Can not stack FieldLists with more than one element, use concat" + assert all([len(x) == 1 for x in arrays]), "Can not stack FieldLists with more than one element, use concat" return FieldListBackend.concat(*arrays) def add(*arrays: list[FieldList], metadata: Metadata = None) -> FieldList: @@ -148,9 +136,7 @@ def subtract(*arrays: list[FieldList], metadata: Metadata = None) -> FieldList: @num_args(2) def diff(*arrays: list[FieldList], metadata: Metadata = None) -> FieldList: - return FieldListBackend.multiply( - FieldListBackend.subtract(*arrays, metadata=metadata), -1 - ) + return FieldListBackend.multiply(FieldListBackend.subtract(*arrays, metadata=metadata), -1) def multiply(*arrays: list[FieldList], metadata: Metadata = None) -> FieldList: return FieldListBackend.two_arg_function("multiply", *arrays, metadata=metadata) @@ -194,9 +180,7 @@ def take( ret = array[indices] else: if not isinstance(dim, str): - raise ValueError( - "To perform isel/sel on FieldList, dim must be a string" - ) + raise ValueError("To perform isel/sel on FieldList, dim must be a string") if method == "isel": ret = array.isel(**{dim: indices}, **kwargs) elif method == "sel": @@ -228,9 +212,7 @@ def filter( xp = array_api_compat.array_namespace(arr1.values, arr2.values) condition = comp_str2func(xp, comparison)(arr2.values, threshold) res = xp.where(condition, replacement, arr1.values) - return new_fieldlist( - res, arr1.metadata(), resolve_metadata(metadata, arr1, arr2) - ) + return new_fieldlist(res, arr1.metadata(), resolve_metadata(metadata, arr1, arr2)) def set_metadata(data: FieldList, metadata: dict) -> FieldList: return new_fieldlist(data.values, data.metadata(), metadata) diff --git a/src/earthkit/workflows/backends/xarray.py b/src/earthkit/workflows/backends/xarray.py index c680a741..5eb8d5ef 100644 --- a/src/earthkit/workflows/backends/xarray.py +++ b/src/earthkit/workflows/backends/xarray.py @@ -12,9 +12,7 @@ class XArrayBackend: @staticmethod - def multi_arg_function( - name: str, *arrays: xr.DataArray | xr.Dataset, **method_kwargs - ) -> xr.DataArray | xr.Dataset: + def multi_arg_function(name: str, *arrays: xr.DataArray | xr.Dataset, **method_kwargs) -> xr.DataArray | xr.Dataset: """Apply named function on DataArrays or Datasets. If only a single DataArrays or Datasetst then function is applied along an dimension specified in method_kwargs. If multiple DataArrays @@ -122,9 +120,7 @@ def concat( **method_kwargs: dict, ) -> xr.DataArray | xr.Dataset: if not np.any([dim in a.sizes for a in arrays]): - raise ValueError( - "Concat must be used on existing dimensions only. Try stack instead." - ) + raise ValueError("Concat must be used on existing dimensions only. Try stack instead.") return xr.concat(arrays, dim=dim, **method_kwargs) # type: ignore # xr/mypy dont coop @staticmethod @@ -135,9 +131,7 @@ def stack( **method_kwargs: dict, ) -> xr.DataArray | xr.Dataset: if np.any([dim in a.sizes for a in arrays]): - raise ValueError( - "Stack must be used on non-existing dimensions only. Try concat instead." - ) + raise ValueError("Stack must be used on non-existing dimensions only. Try concat instead.") ret = xr.concat(arrays, dim=dim, **method_kwargs) # type: ignore # xr/mypy dont coop dims = list(ret.sizes.keys()) @@ -153,9 +147,7 @@ def add( keep_attrs: bool | str = False, **method_kwargs, ): - return XArrayBackend.two_arg_function( - "add", *arrays, keep_attrs=keep_attrs, **method_kwargs - ) + return XArrayBackend.two_arg_function("add", *arrays, keep_attrs=keep_attrs, **method_kwargs) @staticmethod def subtract( @@ -163,9 +155,7 @@ def subtract( keep_attrs: bool | str = False, **method_kwargs, ): - return XArrayBackend.two_arg_function( - "subtract", *arrays, keep_attrs=keep_attrs, **method_kwargs - ) + return XArrayBackend.two_arg_function("subtract", *arrays, keep_attrs=keep_attrs, **method_kwargs) @staticmethod def multiply( @@ -173,9 +163,7 @@ def multiply( keep_attrs: bool | str = False, **method_kwargs, ): - return XArrayBackend.two_arg_function( - "multiply", *arrays, keep_attrs=keep_attrs, **method_kwargs - ) + return XArrayBackend.two_arg_function("multiply", *arrays, keep_attrs=keep_attrs, **method_kwargs) @staticmethod def pow( @@ -183,9 +171,7 @@ def pow( keep_attrs: bool | str = False, **method_kwargs, ): - return XArrayBackend.two_arg_function( - "power", *arrays, keep_attrs=keep_attrs, **method_kwargs - ) + return XArrayBackend.two_arg_function("power", *arrays, keep_attrs=keep_attrs, **method_kwargs) @staticmethod def divide( @@ -193,9 +179,7 @@ def divide( keep_attrs: bool | str = False, **method_kwargs, ): - return XArrayBackend.two_arg_function( - "divide", *arrays, keep_attrs=keep_attrs, **method_kwargs - ) + return XArrayBackend.two_arg_function("divide", *arrays, keep_attrs=keep_attrs, **method_kwargs) @staticmethod def take( diff --git a/src/earthkit/workflows/compilers.py b/src/earthkit/workflows/compilers.py index ab6cff03..e0c8be37 100644 --- a/src/earthkit/workflows/compilers.py +++ b/src/earthkit/workflows/compilers.py @@ -14,7 +14,6 @@ Currently, only cascade is supported. """ -import logging from typing import Any, Literal from earthkit.workflows.graph import Graph, serialise @@ -24,12 +23,15 @@ from cascade.low.into import graph2job as cascadeInto except ImportError: logger.error("failed to import any execution engine! Defaulting to dummy impl") + def cascadeInto(graph: dict) -> Any: raise NotImplementedError("failed to import cascade execution engine") + JobInstance = Any Engine = Literal["cascade"] + def graph2job(graph: Graph, engine: Engine = "cascade") -> JobInstance: ser = serialise(graph) if engine != "cascade": diff --git a/src/earthkit/workflows/fluent.py b/src/earthkit/workflows/fluent.py index 09f40e94..751652ee 100644 --- a/src/earthkit/workflows/fluent.py +++ b/src/earthkit/workflows/fluent.py @@ -149,16 +149,12 @@ def __init__( if name is None: name = payload.name() name += ":" + custom_hash( - f'{payload}{[x.name if isinstance(x, BaseNode) else f"{x.parent.name}.{x.name}" for x in inputs]}' + f"{payload}{[x.name if isinstance(x, BaseNode) else f'{x.parent.name}.{x.name}' for x in inputs]}" ) super().__init__( name, - outputs=( - None - if num_outputs == 1 - else [f"{x:0{len(str(num_outputs - 1))}d}" for x in range(num_outputs)] - ), + outputs=(None if num_outputs == 1 else [f"{x:0{len(str(num_outputs - 1))}d}" for x in range(num_outputs)]), payload=payload, **{self.input_name(x): node for x, node in enumerate(inputs)}, ) @@ -176,7 +172,6 @@ def copy(self) -> "Node": class Action: - REGISTRY: dict[str, type[Action]] = {} def __init__(self, nodetree: xr.DataTree, yields: Optional[Coord] = None): @@ -231,7 +226,6 @@ def register(cls, name: str, obj: type[Action]): ValueError If `name` is an attr on `obj` or `name` is already registered """ - if not issubclass(obj, Action): raise TypeError(f"obj must be a type of Action, not {type(obj)}") @@ -239,9 +233,7 @@ def register(cls, name: str, obj: type[Action]): raise ValueError(f"{name} already registered, will not override") if hasattr(obj, name): - raise ValueError( - f"Action class {obj} already has an attribute {name}, will not override" - ) + raise ValueError(f"Action class {obj} already has an attribute {name}, will not override") cls.REGISTRY[name] = obj @@ -266,15 +258,11 @@ def join( if match_coord_values: for coord, values in narray.coords.items(): if coord in oarray.coords: - assigned = oarray.assign_coords( - **{str(coord): values} - ) + assigned = oarray.assign_coords(**{str(coord): values}) other_action.nodes[npath] = assigned.to_dataset() node_arrays[npath] = xr.concat( [narray, oarray], - dim=( - dim if isinstance(dim, str) else xr.DataArray(dim[1], name=dim[0]) - ), + dim=(dim if isinstance(dim, str) else xr.DataArray(dim[1], name=dim[0])), join="exact", combine_attrs="no_conflicts", coords="minimal", @@ -331,9 +319,7 @@ def transform( res._squeeze_dimension(dim_name, path=path) # Modify node array path to contain new nodes new_nodes = {npath: narray for npath, narray in nodetree_arrays(self.nodes)} - new_nodes.update( - {npath: narray for npath, narray in nodetree_arrays(res.nodes)} - ) + new_nodes.update({npath: narray for npath, narray in nodetree_arrays(res.nodes)}) return type(self)(nodetree_from_dict(new_nodes)) def broadcast( @@ -360,9 +346,9 @@ def broadcast( # Ensure coordinates in existing dimensions match, otherwise obtain NaNs for key, values in narray.coords.items(): if key in array.coords and (exclude is None or key not in exclude): - assert np.all( - values.data == array.coords[key].data - ), f"Existing coordinates must match for broadcast. Found mismatch in {key}!" + assert np.all(values.data == array.coords[key].data), ( + f"Existing coordinates must match for broadcast. Found mismatch in {key}!" + ) broadcasted_nodes = array.broadcast_like(narray, exclude=exclude) new_nodes = np.empty(broadcasted_nodes.shape, dtype=object) it = np.nditer( @@ -378,7 +364,7 @@ def broadcast( dims=broadcasted_nodes.dims, attrs=array.attrs, ) - + new_nodes = {npath: narray for npath, narray in nodetree_arrays(self.nodes)} new_nodes.update(node_arrays) return type(self)(nodetree_from_dict(new_nodes)) @@ -414,19 +400,15 @@ def expand( """ if isinstance(internal_dim, (int, str)): if dim_size is None: - raise TypeError( - "If `internal_dim` is str or int, then `dim_size` must be provided" - ) + raise TypeError("If `internal_dim` is str or int, then `dim_size` must be provided") params = [(i, internal_dim, backend_kwargs) for i in range(dim_size)] else: params = [(x, internal_dim[0], backend_kwargs) for x in internal_dim[1]] if not isinstance(dim, str) and len(params) != len(dim[1]): - raise ValueError( - "Length of values in `dim` must match `dim_size` or length of values in `internal_dim`" - ) + raise ValueError("Length of values in `dim` must match `dim_size` or length of values in `internal_dim`") return self.transform(_expand_transform, params, dim, axis=axis, path=path) - + expand_as_qube = expand_as_qube def map( @@ -561,19 +543,11 @@ def reduce( it = np.nditer(new_nodes, flags=["multi_index", "refs_ok"]) for _ in it: inputs = transposed_nodes[(slice(None, None, 1), *it.multi_index)].data - new_nodes[it.multi_index] = Node( - payload, inputs, num_outputs=len(yields[1]) if yields else 1 - ) + new_nodes[it.multi_index] = Node(payload, inputs, num_outputs=len(yields[1]) if yields else 1) new_coords = {key: batched_narray.coords[key] for key in new_dims} # Propagate scalar coords - new_coords.update( - { - k: v - for k, v in batched_narray.coords.items() - if k not in batched_narray.dims - } - ) + new_coords.update({k: v for k, v in batched_narray.coords.items() if k not in batched_narray.dims}) nodes = xr.DataArray( new_nodes, coords=new_coords, @@ -586,7 +560,7 @@ def reduce( nodes.dims.index(dim), ) node_arrays[npath] = nodes - + new_nodes = {npath: narray for npath, narray in nodetree_arrays(self.nodes)} new_nodes.update(node_arrays) return type(batched)(nodetree_from_dict(new_nodes), yields) @@ -631,12 +605,9 @@ def set_path(self, path: str) -> "Action": NotImplementedError if multiple node arrays are present """ if len(self.nodes.leaves) > 1: - raise NotImplementedError( - "Multiple node arrays present, can not set single path" - ) + raise NotImplementedError("Multiple node arrays present, can not set single path") return type(self)(nodetree_from_dict({path: nodetree_array(self.nodes)})) - def split(self, expansion: Optional[dict[str, PayloadFunc | Payload]] = None) -> "Action": """Create action containing new node arrays by splitting an existing node array by the specified functions in expansion @@ -662,7 +633,6 @@ def split(self, expansion: Optional[dict[str, PayloadFunc | Payload]] = None) -> node_arrays[path] = nodetree_array(action.map(func).nodes, parent) return type(self)(nodetree_from_dict(node_arrays)) - def _validate_criteria(cls, array: xr.DataArray, criteria: dict) -> tuple[bool, dict]: keys = list(criteria.keys()) new_criteria = criteria.copy() @@ -698,7 +668,7 @@ def select( nodes = self.nodes if path is None else self.nodes[path] new_nodes = {} - for npath, narray in nodetree_arrays(nodes): + for npath, narray in nodetree_arrays(nodes): valid, new_criteria = self._validate_criteria(narray, crit) if valid: try: @@ -736,7 +706,7 @@ def iselect( nodes = self.nodes if path is None else self.nodes[path] new_nodes = {} - for npath, narray in nodetree_arrays(nodes): + for npath, narray in nodetree_arrays(nodes): valid, new_criteria = self._validate_criteria(narray, crit) if valid: try: @@ -759,9 +729,7 @@ def concatenate( path: Optional[str] = None, backend_kwargs: dict = {}, ) -> "Action": - return _combine_nodes( - self, "concat", dim, batch_size, keep_dim, path, backend_kwargs - ) + return _combine_nodes(self, "concat", dim, batch_size, keep_dim, path, backend_kwargs) @capture_payload_metadata def stack( @@ -812,7 +780,6 @@ def mean( action = self for npath, narray in nodetree_arrays(self.select(path=path).nodes): - if len(dim) == 0: dim = str(narray.dims[0]) size = narray.sizes[dim] @@ -845,15 +812,12 @@ def std( ) -> "Action": action = self for npath, narray in nodetree_arrays(self.select(path=path).nodes): - if len(dim) == 0: dim = str(narray.dims[0]) size = narray.sizes[dim] if batch_size <= 1 or batch_size >= size: - action = action.reduce( - Payload(backends.std, kwargs=backend_kwargs), dim=dim, path=npath - ) + action = action.reduce(Payload(backends.std, kwargs=backend_kwargs), dim=dim, path=npath) else: mean_sq = action.mean( @@ -939,9 +903,7 @@ def __two_arg_method( return self.join(other, "**datatype**", match_coord_values=True).reduce( Payload(method, kwargs=kwargs), dim="**datatype**", path=path ) - return self.map( - Payload(method, args=(Node.input_name(0), other), kwargs=kwargs), path=path - ) + return self.map(Payload(method, args=(Node.input_name(0), other), kwargs=kwargs), path=path) @capture_payload_metadata def subtract( @@ -950,9 +912,7 @@ def subtract( path: Optional[str] = None, backend_kwargs: dict = {}, ) -> "Action": - return self.__two_arg_method( - backends.subtract, other, path=path, **backend_kwargs - ) + return self.__two_arg_method(backends.subtract, other, path=path, **backend_kwargs) @capture_payload_metadata def divide( @@ -961,9 +921,7 @@ def divide( path: Optional[str] = None, backend_kwargs: dict = {}, ) -> "Action": - return self.__two_arg_method( - backends.divide, other, path=path, **backend_kwargs - ) + return self.__two_arg_method(backends.divide, other, path=path, **backend_kwargs) @capture_payload_metadata def add( @@ -981,9 +939,7 @@ def multiply( path: Optional[str] = None, backend_kwargs: dict = {}, ) -> "Action": - return self.__two_arg_method( - backends.multiply, other, path=path, **backend_kwargs - ) + return self.__two_arg_method(backends.multiply, other, path=path, **backend_kwargs) @capture_payload_metadata def power( @@ -998,9 +954,7 @@ def add_attributes(self, attrs: dict): self.nodes.attrs.update(attrs) def _add_dimension(self, name: str, value: Any, axis: int = 0, path: Optional[str] = None): - new_tree = self.nodes.map_over_datasets( - lambda ds: ds.expand_dims({name: [value]}, axis) - ) + new_tree = self.nodes.map_over_datasets(lambda ds: ds.expand_dims({name: [value]}, axis)) assert isinstance(new_tree, xr.DataTree) if path is not None: self.nodes[path] = new_tree[path] @@ -1009,11 +963,7 @@ def _add_dimension(self, name: str, value: Any, axis: int = 0, path: Optional[st def _squeeze_dimension(self, dim_name: str, drop: bool = False, path: Optional[str] = None): new_tree = self.nodes.map_over_datasets( - lambda ds: ( - ds.squeeze(dim_name, drop=drop) - if dim_name in ds.dims and len(ds.coords[dim_name]) == 1 - else ds - ) + lambda ds: ds.squeeze(dim_name, drop=drop) if dim_name in ds.dims and len(ds.coords[dim_name]) == 1 else ds ) assert isinstance(new_tree, xr.DataTree) if path is not None: @@ -1023,9 +973,7 @@ def _squeeze_dimension(self, dim_name: str, drop: bool = False, path: Optional[s def __getattr__(self, attr): if attr in Action.REGISTRY: - return RegisteredAction( - attr, Action.REGISTRY[attr], self - ) # When the attr is a registered action class + return RegisteredAction(attr, Action.REGISTRY[attr], self) # When the attr is a registered action class raise AttributeError(f"{self.__class__.__name__} has no attribute {attr!r}") @@ -1055,9 +1003,7 @@ def __repr__(self): return f"Registered action: {self._name!r} at {self.action.__qualname__}" -def _batch_transform( - action: Action, selection: dict, payload: PayloadFunc | Payload -) -> Action: +def _batch_transform(action: Action, selection: dict, payload: PayloadFunc | Payload) -> Action: selected = action.select(selection, drop=True) dim = list(selection.keys())[0] for npath, narray in nodetree_arrays(selected.nodes): @@ -1070,14 +1016,8 @@ def _batch_transform( return selected -def _expand_transform( - action: Action, index: int | Hashable, dim: int | str, backend_kwargs: dict = {} -) -> Action: - ret = action.map( - Payload( - backends.take, [Node.input_name(0), index], {"dim": dim, **backend_kwargs} - ) - ) +def _expand_transform(action: Action, index: int | Hashable, dim: int | str, backend_kwargs: dict = {}) -> Action: + ret = action.map(Payload(backends.take, [Node.input_name(0), index], {"dim": dim, **backend_kwargs})) return ret @@ -1105,9 +1045,7 @@ def _combine_nodes( def from_source( - payloads_list: ( - np.ndarray[Any, Any] | dict[str, np.ndarray[Any, Any]] - ), # values are Callables + payloads_list: (np.ndarray[Any, Any] | dict[str, np.ndarray[Any, Any]]), # values are Callables yields: Coord | None = None, dims: list | None = None, coords: dict | None = None, @@ -1119,9 +1057,7 @@ def from_source( node_arrays = {} for nindex, (path, parray) in enumerate(payloads_list.items()): payloads = xr.DataArray(parray, dims=dims, coords=coords) - nodes = xr.DataArray( - np.empty(payloads.shape, dtype=object), dims=dims, coords=coords - ) + nodes = xr.DataArray(np.empty(payloads.shape, dtype=object), dims=dims, coords=coords) it = np.nditer(payloads, flags=["multi_index", "refs_ok"]) # Ensure all source nodes have a unique name node_names = set() @@ -1135,9 +1071,7 @@ def from_source( if name in node_names: name += str(it.multi_index) node_names.add(name) - nodes[it.multi_index] = Node( - payload, name=name, num_outputs=len(yields[1]) if yields else 1 - ) + nodes[it.multi_index] = Node(payload, name=name, num_outputs=len(yields[1]) if yields else 1) node_arrays[path] = nodes return action( @@ -1175,6 +1109,7 @@ def merge(*args, **kwargs) -> Action: action_type = args[0].__class__ if len(args) > 0 else list(kwargs.values())[0].__class__ return action_type(nodetree_from_dict(new_nodes)) + Action.register("default", Action) __all__ = [ diff --git a/src/earthkit/workflows/graph/expand.py b/src/earthkit/workflows/graph/expand.py index e3aa003c..6d4e4c71 100644 --- a/src/earthkit/workflows/graph/expand.py +++ b/src/earthkit/workflows/graph/expand.py @@ -42,12 +42,8 @@ def get_output(self, name: str | None = None) -> Output: if lname in self.leaves: return self.leaves[lname].get_output() if name == Node.DEFAULT_OUTPUT: - raise AttributeError( - f"No default output node found in sub-graph {self.name!r}" - ) - raise AttributeError( - f"No output node named {name!r} in sub-graph {self.name!r}" - ) + raise AttributeError(f"No default output node found in sub-graph {self.name!r}") + raise AttributeError(f"No output node named {name!r} in sub-graph {self.name!r}") class Splicer(Transformer): @@ -84,11 +80,7 @@ def __init__( output_map: dict[str, str] | None, ): self.name = name - self.inputs = ( - inputs - if input_map is None - else {iname: inputs[mname] for iname, mname in input_map.items()} - ) + self.inputs = inputs if input_map is None else {iname: inputs[mname] for iname, mname in input_map.items()} if output_map is None: self.outputs = {oname: oname for oname in outputs} else: @@ -168,9 +160,7 @@ def splice_sink(self, name: str, s: Node, **inputs: Output) -> Node: return Node(name, outputs=None, payload=s.payload, **inputs) -ExpanderType = Callable[ - [Node], Graph | tuple[Graph, dict[str, str] | None, dict[str, str | None]] | None -] +ExpanderType = Callable[[Node], Graph | tuple[Graph, dict[str, str] | None, dict[str, str | None]] | None] SplicerType = Callable[ [ str, @@ -215,9 +205,7 @@ def graph(self, graph: Graph, sinks: list[Node | _Subgraph]) -> Graph: return Graph(new_sinks) -def expand_graph( - expand: ExpanderType, graph: Graph, splicer: SplicerType = Splicer -) -> Graph: +def expand_graph(expand: ExpanderType, graph: Graph, splicer: SplicerType = Splicer) -> Graph: """Expand a graph by replacing nodes with sub-graphs The expansion is controlled by the ``expand`` callback, called for every diff --git a/src/earthkit/workflows/graph/export.py b/src/earthkit/workflows/graph/export.py index 07cdf467..c5b06b40 100644 --- a/src/earthkit/workflows/graph/export.py +++ b/src/earthkit/workflows/graph/export.py @@ -15,15 +15,11 @@ class NodeFactory(Protocol): - def __call__( - self, name: str, outputs: list[str], payload: Any, **inputs: Output - ) -> Node: + def __call__(self, name: str, outputs: list[str], payload: Any, **inputs: Output) -> Node: pass -def default_node_factory( - name: str, outputs: list[str], payload: Any, **inputs: Output -) -> Node: +def default_node_factory(name: str, outputs: list[str], payload: Any, **inputs: Output) -> Node: # NOTE this logic is rather fragile; necessary due to the existence of default output. Remove it and simplify here if not outputs: return Node(name, payload=payload, outputs=[], **inputs) @@ -70,10 +66,7 @@ def deserialise(data: dict, node_factory: NodeFactory = default_node_factory) -> bare `Node` objects """ deps = { - name: [ - inp if isinstance(inp, str) else inp[0] - for inp in node.get("inputs", {}).values() - ] + name: [inp if isinstance(inp, str) else inp[0] for inp in node.get("inputs", {}).values()] for name, node in data.items() } @@ -89,9 +82,7 @@ def deserialise(data: dict, node_factory: NodeFactory = default_node_factory) -> else: parent, oname = src node_inputs[iname] = nodes[parent].get_output(oname) - nodes[name] = _deserialise_node( - name, node_data, node_factory=node_factory, **node_inputs - ) + nodes[name] = _deserialise_node(name, node_data, node_factory=node_factory, **node_inputs) if (sink := nodes[name]).is_sink(): sinks.append(sink) return Graph(sinks) diff --git a/src/earthkit/workflows/graph/fuse.py b/src/earthkit/workflows/graph/fuse.py index fbd14e19..8985ebd0 100644 --- a/src/earthkit/workflows/graph/fuse.py +++ b/src/earthkit/workflows/graph/fuse.py @@ -46,9 +46,7 @@ def graph(self, g: Graph, sinks: list[Node]) -> Graph: return Graph(sinks) def transform(self, graph: Graph) -> Graph: - self.counter = Counter( - isrc.parent for node in graph.nodes() for isrc in node.inputs.values() - ) + self.counter = Counter(isrc.parent for node in graph.nodes() for isrc in node.inputs.values()) return super().transform(graph) diff --git a/src/earthkit/workflows/graph/graph.py b/src/earthkit/workflows/graph/graph.py index aeeb78b5..b26f7f8c 100644 --- a/src/earthkit/workflows/graph/graph.py +++ b/src/earthkit/workflows/graph/graph.py @@ -134,11 +134,7 @@ def get_predecessors(self, node: Node) -> dict[str, Node | tuple[Node, str]]: output), or (parent, output name) tuples. """ return { - iname: ( - isrc.parent - if isrc.name == Node.DEFAULT_OUTPUT - else (isrc.parent, isrc.name) - ) + iname: (isrc.parent if isrc.name == Node.DEFAULT_OUTPUT else (isrc.parent, isrc.name)) for iname, isrc in node.inputs.items() } diff --git a/src/earthkit/workflows/graph/graphviz.py b/src/earthkit/workflows/graph/graphviz.py index 652370a4..e7fbd8df 100644 --- a/src/earthkit/workflows/graph/graphviz.py +++ b/src/earthkit/workflows/graph/graphviz.py @@ -36,11 +36,7 @@ def to_dot(graph: Graph) -> str: if oname != Node.DEFAULT_OUTPUT: attrs["taillabel"] = _quote(oname) attrs["headlabel"] = _quote(iname) - astr = ( - " [" + ", ".join(f"{k}={v}" for k, v in attrs.items()) + "]" - if attrs - else "" - ) + astr = " [" + ", ".join(f"{k}={v}" for k, v in attrs.items()) + "]" if attrs else "" out.append(f"{_quote(pname)} -> {_quote(nname)}{astr}") return "digraph {\n" + textwrap.indent("\n".join(out), " ") + "\n}" diff --git a/src/earthkit/workflows/graph/networkx.py b/src/earthkit/workflows/graph/networkx.py index 6dca6d3b..ce889b0c 100644 --- a/src/earthkit/workflows/graph/networkx.py +++ b/src/earthkit/workflows/graph/networkx.py @@ -55,9 +55,7 @@ def draw_graph( g, pos, edge_labels={ - e: (a["source_out"] if a["source_out"] != Node.DEFAULT_OUTPUT else "") - + "->" - + a["dest_in"] + e: (a["source_out"] if a["source_out"] != Node.DEFAULT_OUTPUT else "") + "->" + a["dest_in"] for e, a in g.edges.items() }, ) diff --git a/src/earthkit/workflows/graph/nodes.py b/src/earthkit/workflows/graph/nodes.py index db838b35..74d43987 100644 --- a/src/earthkit/workflows/graph/nodes.py +++ b/src/earthkit/workflows/graph/nodes.py @@ -85,10 +85,7 @@ def __init__( self.name = name self.outputs = [Node.DEFAULT_OUTPUT] if outputs is None else outputs self.payload = payload - self.inputs = { - iname: (inp if isinstance(inp, Output) else inp.get_output()) - for iname, inp in kwargs.items() - } + self.inputs = {iname: (inp if isinstance(inp, Output) else inp.get_output()) for iname, inp in kwargs.items()} def __getattr__(self, name: str) -> Output: return self.get_output(name) @@ -145,6 +142,4 @@ def is_sink(self) -> bool: def copy(self) -> Self: """Shallow copy of the node (the payload is not copied)""" - return self.__class__( - self.name, self.outputs.copy(), self.payload, **self.inputs - ) + return self.__class__(self.name, self.outputs.copy(), self.payload, **self.inputs) diff --git a/src/earthkit/workflows/graph/pyvis.py b/src/earthkit/workflows/graph/pyvis.py index 32843049..3d3cdb97 100644 --- a/src/earthkit/workflows/graph/pyvis.py +++ b/src/earthkit/workflows/graph/pyvis.py @@ -76,9 +76,7 @@ def node_info(node): labels.append(f"Output{'' if len(node.outputs) == 1 else 's'}: {outputs_s}") shape = random.Random(node.name.split(":")[0]).choice(AVAILABLE_SHAPES) - colour = random.Random(f"{node.name.split(':')[0]}-{str(node.outputs)}").choice( - AVAILABLE_COLOURS - ) + colour = random.Random(f"{node.name.split(':')[0]}-{str(node.outputs)}").choice(AVAILABLE_COLOURS) return { "title": "\n".join(labels), @@ -149,7 +147,6 @@ def none() -> dict: def truncate_name(name: str, max_length: int = 10) -> str: """Truncate a name to a maximum length""" - if ":" not in name: return name @@ -205,9 +202,7 @@ def to_pyvis( f"{truncate_name(node.name)}.{truncate_name(iname)}", node, ) - net.add_edge( - truncate_name(isrc.parent.name), truncate_name(node.name), **eattrs - ) + net.add_edge(truncate_name(isrc.parent.name), truncate_name(node.name), **eattrs) options = options or {} preset_options = getattr(VisualisationPresets, preset)() diff --git a/src/earthkit/workflows/graph/rename.py b/src/earthkit/workflows/graph/rename.py index 6efffdf5..b41789fe 100644 --- a/src/earthkit/workflows/graph/rename.py +++ b/src/earthkit/workflows/graph/rename.py @@ -67,8 +67,5 @@ def join_namespaced(**graphs: Graph) -> Graph: """ return reduce( add, - ( - rename_nodes((lambda n: f"{namespace}.{n}"), graph) - for namespace, graph in graphs.items() - ), + (rename_nodes((lambda n: f"{namespace}.{n}"), graph) for namespace, graph in graphs.items()), ) diff --git a/src/earthkit/workflows/graph/samplegraphs.py b/src/earthkit/workflows/graph/samplegraphs.py index bb15e191..01ae1e20 100644 --- a/src/earthkit/workflows/graph/samplegraphs.py +++ b/src/earthkit/workflows/graph/samplegraphs.py @@ -83,21 +83,17 @@ def multi(nread: int = 5, nout1: int = 3, nout2: int = 2) -> Graph: p0 = Node("process-0", outputs=[f"output{i}" for i in range(nout1)], **p0i) p1s = [] for i in range(2, nout1): - p = Node( - f"process-{i-1}", input1=p0.output0, input2=p0.get_output(f"output{i}") - ) + p = Node(f"process-{i - 1}", input1=p0.output0, input2=p0.get_output(f"output{i}")) p1s.append(p) p2 = Node( - f"process-{nout1-1}", + f"process-{nout1 - 1}", outputs=[f"output{i}" for i in range(nout2)], input1=p0.output1, input2=rs[min(2, nread - 1)], ) _ws = ((inp, out) for out in range(nout2) for inp in p1s) ws: list[Node] = [ - Node( - f"writer-{j}", outputs=[], input1=inp, input2=p2.get_output(f"output{out}") - ) + Node(f"writer-{j}", outputs=[], input1=inp, input2=p2.get_output(f"output{out}")) for j, (inp, out) in enumerate(_ws) ] return Graph(ws) @@ -128,6 +124,6 @@ def comb(nteeth: int = 5, nproc: int = 0): if tip is None: tip = tooth else: - tip = Node(f"join-{i-1}", input1=tip, input2=tooth) + tip = Node(f"join-{i - 1}", input1=tip, input2=tooth) assert tip is not None return Graph([Node("writer", outputs=[], input=tip)]) diff --git a/src/earthkit/workflows/graph/split.py b/src/earthkit/workflows/graph/split.py index 04179435..3a9d21ec 100644 --- a/src/earthkit/workflows/graph/split.py +++ b/src/earthkit/workflows/graph/split.py @@ -75,9 +75,7 @@ def output(self, tnode: tuple[K, Node], output: str) -> tuple[K, Output]: k, node = tnode return (k, node.get_output(output)) - def graph( - self, graph: Graph, sinks: list[tuple[K, Node]] - ) -> tuple[dict[K, Graph], list[CutEdge[K]]]: + def graph(self, graph: Graph, sinks: list[tuple[K, Node]]) -> tuple[dict[K, Graph], list[CutEdge[K]]]: for k, sink in sinks: self.sinks.setdefault(k, []).append(sink) return {k: Graph(s) for k, s in self.sinks.items()}, self.cuts diff --git a/src/earthkit/workflows/nodetree.py b/src/earthkit/workflows/nodetree.py index 005a516d..5cb446dc 100644 --- a/src/earthkit/workflows/nodetree.py +++ b/src/earthkit/workflows/nodetree.py @@ -12,9 +12,7 @@ import xarray as xr -def nodetree_from_dict( - data: dict[str, xr.DataArray] | dict[str, xr.Dataset], *args, **kwargs -) -> xr.DataTree: +def nodetree_from_dict(data: dict[str, xr.DataArray] | dict[str, xr.Dataset], *args, **kwargs) -> xr.DataTree: new_data = {} for nindex, (k, v) in enumerate(data.items()): if isinstance(v, xr.Dataset): @@ -22,17 +20,12 @@ def nodetree_from_dict( elif isinstance(v, xr.DataArray): new_data[k] = v.to_dataset(name=f"nodeset{nindex}") else: - raise ValueError( - "NodeTree can only be created from dict of xr.DataArray or xr.Dataset" - ) + raise ValueError("NodeTree can only be created from dict of xr.DataArray or xr.Dataset") tree = xr.DataTree.from_dict(new_data, *args, **kwargs) for leaf in tree.leaves: var = list(leaf.dataset.data_vars.keys())[0] if np.any(leaf[var].isnull()): - raise ValueError( - "Nodes in Action can not contain NaNs. " - f"Found NaN in nodeset {leaf.path}, variable {var}" - ) + raise ValueError(f"Nodes in Action can not contain NaNs. Found NaN in nodeset {leaf.path}, variable {var}") if not tree.is_hollow: raise ValueError("Nodes in Action must be hollow datatree") return tree @@ -47,9 +40,7 @@ def nodetree_arrays(nodetree: xr.DataTree) -> Iterable[Tuple[str, xr.DataArray]] def nodetree_array(nodetree: xr.DataTree, path: Optional[str] = None) -> xr.DataArray: if path is None: if len(nodetree.leaves) != 1: - raise ValueError( - "Multiple node arrays present, path must be specified to retrieve one" - ) + raise ValueError("Multiple node arrays present, path must be specified to retrieve one") leaf = nodetree.leaves[0] else: if path not in nodetree.leaves: diff --git a/src/earthkit/workflows/taskgraph.py b/src/earthkit/workflows/taskgraph.py index c82eff8f..d3b0c991 100644 --- a/src/earthkit/workflows/taskgraph.py +++ b/src/earthkit/workflows/taskgraph.py @@ -70,9 +70,7 @@ def cpu_cycles(self, value: int): self.resources.cpu_cycles = value def copy(self) -> "Task": - newnode = Task( - self.name, self.outputs.copy(), self.payload, self.resources, **self.inputs - ) + newnode = Task(self.name, self.outputs.copy(), self.payload, self.resources, **self.inputs) return newnode @@ -125,9 +123,7 @@ def accumulated_duration(self, task: Node) -> float: if task in self._accumulated_duration: return self._accumulated_duration[task] - duration = cast( - Task, task - ).duration # nodes seem to be runtime patched to tasks + duration = cast(Task, task).duration # nodes seem to be runtime patched to tasks for child in predecessors(self, task): if child in self._accumulated_duration: duration += self._accumulated_duration[child] @@ -137,9 +133,7 @@ def accumulated_duration(self, task: Node) -> float: class ExecutionGraph(TaskGraph): - def _make_communication_task( - self, source: Node, target: Node, state: Callable | None = None - ): + def _make_communication_task(self, source: Node, target: Node, state: Callable | None = None): t = Communication( f"{source.name}-{target.name}", source, diff --git a/src/earthkit/workflows/utility.py b/src/earthkit/workflows/utility.py index eccdd442..3b198719 100644 --- a/src/earthkit/workflows/utility.py +++ b/src/earthkit/workflows/utility.py @@ -35,7 +35,4 @@ def successors(graph: Graph, node: Node) -> list[Node]: def predecessors(graph: Graph, node: Node) -> list[Node]: - return [ - x if isinstance(x, Node) else x[0] - for x in graph.get_predecessors(node).values() - ] + return [x if isinstance(x, Node) else x[0] for x in graph.get_predecessors(node).values()] diff --git a/tests/cascade/benchmarks/image_processing.py b/tests/cascade/benchmarks/image_processing.py index 81224427..8e2dc563 100644 --- a/tests/cascade/benchmarks/image_processing.py +++ b/tests/cascade/benchmarks/image_processing.py @@ -8,13 +8,12 @@ import io -import matplotlib.pyplot as plt# ty: ignore[unresolved-import] +import matplotlib.pyplot as plt # ty: ignore[unresolved-import] import numpy as np -from PIL import Image - -from cascade.cascade import Cascade # ty: ignore[unresolved-import] +from cascade.cascade import Cascade # ty: ignore[unresolved-import] from cascade.fluent import Fluent, Payload # ty: ignore[unresolved-import] -from cascade.visualise import visualise # ty: ignore[unresolved-import] +from cascade.visualise import visualise # ty: ignore[unresolved-import] +from PIL import Image def mandelbrot(c, max_iter): @@ -29,9 +28,7 @@ def mandelbrot(c, max_iter): return n + 1 - np.log(np.log2(abs(z))) -def generate_fractal_image( - xmin=0, xmax=100, ymin=0, ymax=100, width=200, height=200, max_iter=5 -): +def generate_fractal_image(xmin=0, xmax=100, ymin=0, ymax=100, width=200, height=200, max_iter=5): """Generate a fractal image of the Mandelbrot set.""" r1 = np.linspace(xmin, xmax, width) r2 = np.linspace(ymin, ymax, height) diff --git a/tests/cascade/controller/test_run.py b/tests/cascade/controller/test_run.py index 14713bfb..2dd34569 100644 --- a/tests/cascade/controller/test_run.py +++ b/tests/cascade/controller/test_run.py @@ -14,24 +14,23 @@ # by setting RUN_ALL_TESTS=1, as on CI is particularly flaky and incompatible # with xdist etc - import os +import pathlib +import pickle +import tempfile from logging.config import dictConfig from multiprocessing import Process from time import sleep -import tempfile -import pathlib -import pickle -from cascade.deployment.logging import DefaultLoggingConfig from cascade.controller.impl import run +from cascade.deployment.logging import DefaultLoggingConfig from cascade.executor.bridge import Bridge from cascade.executor.comms import callback from cascade.executor.config import logging_config from cascade.executor.executor import Executor from cascade.executor.msg import BackboneAddress, ExecutorShutdown from cascade.low.builders import JobBuilder, TaskBuilder -from cascade.low.core import JobInstance, JobInstanceRich, CheckpointSpec, DatasetId +from cascade.low.core import CheckpointSpec, DatasetId, JobInstance, JobInstanceRich from cascade.scheduler.core import Preschedule from cascade.scheduler.precompute import precompute @@ -76,7 +75,7 @@ def run_cluster( if not preschedule: preschedule = precompute(job.jobInstance) c = f"tcp://localhost:{portBase}" - m = f"tcp://localhost:{portBase+1}" + m = f"tcp://localhost:{portBase + 1}" ps = [] for i, executor in enumerate(range(executors)): p = Process(target=launch_executor, args=(job.jobInstance, c, portBase + 1 + i * 10, i)) @@ -167,24 +166,25 @@ def test_para4(): run_cluster(job, 12400, 4) sleep(1) # improves stability + def test_para1_persist(): if not run_all_tests: return job = get_job() with tempfile.TemporaryDirectory() as td: spec = CheckpointSpec( - storage_type="fs", - storage_params=td, - retrieve_id=None, - persist_id="run1", - to_persist=[DatasetId(task="c2i1", output="0")], + storage_type="fs", + storage_params=td, + retrieve_id=None, + persist_id="run1", + to_persist=[DatasetId(task="c2i1", output="0")], ) job.checkpointSpec = spec run_cluster(job, 12600, 1) root = pathlib.Path(td) - run1 = root / 'run1' - dts1 = run1 / 'c2i1.0' + run1 = root / "run1" + dts1 = run1 / "c2i1.0" assert [str(e) for e in root.iterdir()] == [str(run1)] assert [str(e) for e in run1.iterdir()] == [str(dts1)] content = dts1.read_bytes() @@ -230,24 +230,26 @@ def test_fusing(): run_cluster(jobInstanceRich, 12800, 2, preschedule) sleep(1) # improves stability + def test_checkpoints(): """This takes a job with a checkpoint config, and runs it twice, - in a way that recognizes whether it checkpointed or not""" - + in a way that recognizes whether it checkpointed or not + """ with tempfile.TemporaryDirectory() as tmp_root, tempfile.TemporaryDirectory() as ckpt_root: sourcetask_code = f"import pathlib; f = pathlib.Path('{tmp_root}') / 'file.txt'; f.write_text('ok') if not f.exists() else 1/0;" jobInstance = ( - JobBuilder() + ( + JobBuilder() .with_node( "source", TaskBuilder.from_callable(exec).with_values(sourcetask_code), ) - .with_node( - "product", - TaskBuilder.from_callable(lambda e: e) - ) + .with_node("product", TaskBuilder.from_callable(lambda e: e)) .with_edge("source", "product", 0) - ).build().get_or_raise() + ) + .build() + .get_or_raise() + ) preschedule = precompute(jobInstance) diff --git a/tests/cascade/executor/test_callables.py b/tests/cascade/executor/test_callables.py index acfde69d..8a7482d4 100644 --- a/tests/cascade/executor/test_callables.py +++ b/tests/cascade/executor/test_callables.py @@ -18,8 +18,6 @@ def myfunc(l: int) -> float: return np.arange(l).sum() - ci = CallableInstance( - func=myfunc, kwargs={"l": 4}, args=[], env=["numpy"], exp_output=6 - ) + ci = CallableInstance(func=myfunc, kwargs={"l": 4}, args=[], env=["numpy"], exp_output=6) run_test(ci, "numpyTest1", 2) diff --git a/tests/cascade/executor/test_checkpoints.py b/tests/cascade/executor/test_checkpoints.py index 84ff12c0..c4ca48fb 100644 --- a/tests/cascade/executor/test_checkpoints.py +++ b/tests/cascade/executor/test_checkpoints.py @@ -1,12 +1,20 @@ -from cascade.low.core import CheckpointSpec, DatasetId -from cascade.shm.client import AllocatedBuffer -from cascade.low.execution_context import VirtualCheckpointHost -from cascade.executor.checkpoints import build_persist_command, list_persisted_datasets, persist_dataset, build_retrieve_command, retrieve_dataset -from cascade.executor.serde import DefaultSerde import pathlib import tempfile from unittest.mock import patch +from cascade.executor.checkpoints import ( + build_persist_command, + build_retrieve_command, + list_persisted_datasets, + persist_dataset, + retrieve_dataset, +) +from cascade.executor.serde import DefaultSerde +from cascade.low.core import CheckpointSpec, DatasetId +from cascade.low.execution_context import VirtualCheckpointHost +from cascade.shm.client import AllocatedBuffer + + def test_rw(): with tempfile.TemporaryDirectory() as td: ds1 = DatasetId(task="1", output="0") @@ -23,7 +31,7 @@ def test_rw(): # we manually create because we dont have an shm server running data = AllocatedBuffer("testCascExecChckptRW_1", 64, True, None, DefaultSerde) try: - data.view()[:] = b'a' * 64 + data.view()[:] = b"a" * 64 persist_dataset(command_persist, data) assert list_persisted_datasets(spec) == [ds1] @@ -46,4 +54,3 @@ def test_rw(): if data.shm is not None: data.shm.unlink() data.close() - diff --git a/tests/cascade/executor/test_executor.py b/tests/cascade/executor/test_executor.py index 21f34027..2b0cbf5d 100644 --- a/tests/cascade/executor/test_executor.py +++ b/tests/cascade/executor/test_executor.py @@ -16,9 +16,9 @@ import numpy as np -from cascade.deployment.logging import DefaultLoggingConfig import cascade.executor.platform as platform import cascade.executor.serde as serde +from cascade.deployment.logging import DefaultLoggingConfig from cascade.executor.comms import Listener, callback, send_data from cascade.executor.config import logging_config from cascade.executor.executor import Executor @@ -49,9 +49,7 @@ logger = logging.getLogger(__name__) -def launch_executor( - job_instance: JobInstance, controller_address: BackboneAddress, portBase: int -): +def launch_executor(job_instance: JobInstance, controller_address: BackboneAddress, portBase: int): dictConfig(logging_config) executor = Executor( job_instance, @@ -92,11 +90,7 @@ def test_func(x: np.ndarray) -> np.ndarray: sink_o = DatasetId("sink", "o") job = JobInstance( tasks={"source": source, "sink": sink}, - edges=[ - Task2TaskEdge( - source=source_o, sink_task="sink", sink_input_kw="x", sink_input_ps=None - ) - ], + edges=[Task2TaskEdge(source=source_o, sink_task="sink", sink_input_kw="x", sink_input_ps=None)], ) # cluster setup @@ -135,9 +129,7 @@ def test_func(x: np.ndarray) -> np.ndarray: w0 = WorkerId("test_executor", "w0") callback( m1, - TaskSequence( - worker=w0, tasks=["source", "sink"], publish={sink_o}, extra_env=[] - ), + TaskSequence(worker=w0, tasks=["source", "sink"], publish={sink_o}, extra_env=[]), ) # NOTE we need to expect source_o dataset too, because of no finegraining for host-wide and worker-only expected = { @@ -147,9 +139,7 @@ def test_func(x: np.ndarray) -> np.ndarray: while expected: ms = l.recv_messages() for m in ms: - if not isinstance( - m, ExecutorRegistration - ): # there may be extra due to retries + if not isinstance(m, ExecutorRegistration): # there may be extra due to retries expected.remove(m) # retrieve result @@ -175,9 +165,7 @@ def test_func(x: np.ndarray) -> np.ndarray: callback(m1, DatasetPurge(ds=sink_o)) value, deser_fun = serde.ser_output(np.array([10.0]), "ndarray") payload = DatasetTransmitPayload( - header=DatasetTransmitPayloadHeader( - ds=source_o, confirm_idx=1, confirm_address=c1, deser_fun=deser_fun - ), + header=DatasetTransmitPayloadHeader(ds=source_o, confirm_idx=1, confirm_address=c1, deser_fun=deser_fun), value=value, ) syn = Syn(1, c1) @@ -191,9 +179,7 @@ def test_func(x: np.ndarray) -> np.ndarray: for m in ms: logger.debug(f"about to remove received message {m}") expected.remove(m) - callback( - m1, TaskSequence(worker=w0, tasks=["sink"], publish={sink_o}, extra_env=[]) - ) + callback(m1, TaskSequence(worker=w0, tasks=["sink"], publish={sink_o}, extra_env=[])) expected = [ DatasetPublished(w0, ds=sink_o, transmit_idx=None), ] diff --git a/tests/cascade/executor/test_packages.py b/tests/cascade/executor/test_packages.py index 2d552669..b1f261ea 100644 --- a/tests/cascade/executor/test_packages.py +++ b/tests/cascade/executor/test_packages.py @@ -1,10 +1,18 @@ import re import pytest +from packaging.version import Version +from cascade.executor.runner.packages import ( + InstallIssue, + _get_dist_modules, + _maybe_module_version, + _parse_pip_install, + _postinstall_verify, + _prefer_installed, + run_command, +) from cascade.low.exceptions import CascadeInternalError, CascadeUserError -from cascade.executor.runner.packages import run_command, _parse_pip_install, _get_dist_modules, _maybe_module_version, _postinstall_verify, InstallIssue, _prefer_installed -from packaging.version import Version def test_run_command() -> None: @@ -16,7 +24,9 @@ def test_run_command() -> None: with pytest.raises( CascadeInternalError, - match=re.escape("command failure: [Errno 2] No such file or directory: 'you' (caused by FileNotFoundError(2, 'No such file or directory'))") + match=re.escape( + "command failure: [Errno 2] No such file or directory: 'you' (caused by FileNotFoundError(2, 'No such file or directory'))" + ), ): run_command(bad1_command) with pytest.raises( @@ -25,43 +35,54 @@ def test_run_command() -> None: ): run_command(bad2_command) + def test_parse_pip_install() -> None: - assumed = 'Using Python 3.11.8 environment at: \nResolved 1 package in 5ms\nUninstalled 1 package in 12ms\nInstalled 1 package in 18ms\n - numpy==2.4.2\n + numpy==2.4.1\n' - expected = {'numpy': Version('2.4.1')} + assumed = "Using Python 3.11.8 environment at: \nResolved 1 package in 5ms\nUninstalled 1 package in 12ms\nInstalled 1 package in 18ms\n - numpy==2.4.2\n + numpy==2.4.1\n" + expected = {"numpy": Version("2.4.1")} assert _parse_pip_install(assumed) == expected, "failed to parse assumed uv output" import numpy + _, actual = run_command(["uv", "pip", "install", f"numpy=={numpy.__version__}"]) expected = {} assert _parse_pip_install(actual) == expected, "failed to parse actual uv output" # TODO it would be nice to actually do some pip install here, but im reluctant to do that in a unit test. Some for test_postinstall_verify + def test_get_dist_modules() -> None: assert _get_dist_modules("numpy") == ["numpy"] assert sorted(_get_dist_modules("earthkit-workflows")) == sorted(["cascade", "earthkit"]) + def test_maybe_module_version() -> None: import numpy + assert _maybe_module_version("numpy") == Version(numpy.__version__) - import cascade - assert _maybe_module_version("cascade") == None # whoopsie, we dont declare __version__ on cascade + assert _maybe_module_version("cascade") == None # whoopsie, we dont declare __version__ on cascade import earthkit.workflows + if not hasattr(earthkit.workflows, "__version__"): - assert False # just to satisfy ty + assert False # just to satisfy ty assert _maybe_module_version("earthkit.workflows") == Version(earthkit.workflows.__version__) + def test_postinstall_verify() -> None: import numpy - goodie = 'Using Python 3.11.8 environment at: \nResolved 1 package in 5ms\nUninstalled 1 package in 12ms\nInstalled 1 package in 18ms\n - numpy==2.4.2\n + numpy=={numpy.__version__}\n' + + goodie = "Using Python 3.11.8 environment at: \nResolved 1 package in 5ms\nUninstalled 1 package in 12ms\nInstalled 1 package in 18ms\n - numpy==2.4.2\n + numpy=={numpy.__version__}\n" issues = _postinstall_verify(goodie) assert not issues - baddie = 'Using Python 3.11.8 environment at: \nResolved 1 package in 5ms\nUninstalled 1 package in 12ms\nInstalled 1 package in 18ms\n - numpy==2.4.2\n + numpy==1.0.0\n' + baddie = "Using Python 3.11.8 environment at: \nResolved 1 package in 5ms\nUninstalled 1 package in 12ms\nInstalled 1 package in 18ms\n - numpy==2.4.2\n + numpy==1.0.0\n" issues = _postinstall_verify(baddie) assert issues == [ - InstallIssue(dist_name='numpy', desired_version=Version('1.0.0'), mod_issues=[('numpy', Version(numpy.__version__))]) + InstallIssue( + dist_name="numpy", desired_version=Version("1.0.0"), mod_issues=[("numpy", Version(numpy.__version__))] + ) ] + def test_prefer_installed() -> None: import numpy + assert list(_prefer_installed(["numpy"])) == [f"numpy=={numpy.__version__}"] assert list(_prefer_installed(["numpy==1.0.0"])) == ["numpy==1.0.0"] assert list(_prefer_installed([f"numpy>={numpy.__version__}"])) == [f"numpy=={numpy.__version__}"] diff --git a/tests/cascade/executor/test_runner.py b/tests/cascade/executor/test_runner.py index fdfa45f3..11e9f14e 100644 --- a/tests/cascade/executor/test_runner.py +++ b/tests/cascade/executor/test_runner.py @@ -11,12 +11,12 @@ from multiprocessing.shared_memory import SharedMemory from typing import Any -from cascade.deployment.logging import DefaultLoggingConfig import cascade.executor.runner.entrypoint as entrypoint import cascade.executor.runner.memory as memory import cascade.executor.serde as serde import cascade.shm.api as shm_api import cascade.shm.client as shm_cli +from cascade.deployment.logging import DefaultLoggingConfig from cascade.executor.msg import DatasetPublished, TaskSequence from cascade.executor.runner.packages import PackagesEnv from cascade.low.core import ( @@ -48,9 +48,7 @@ def verify_msg(address, msg): purging_tracker = set() key2shmid = lambda key: f"test_{key}" - def _send_command( - comm: shm_api.Comm, resp_class: Any, timeout_sec: float = 60.0 - ) -> Any: + def _send_command(comm: shm_api.Comm, resp_class: Any, timeout_sec: float = 60.0) -> Any: if isinstance(comm, shm_api.AllocateRequest): key = key2shmid(comm.key) if key in opened_buffers or key in purging_tracker: @@ -163,11 +161,7 @@ def test_func(x): ) twoTaskJob = JobInstance( tasks={"t3a": t3a, "t3b": t3b}, - edges=[ - Task2TaskEdge( - source=t3i, sink_task="t3b", sink_input_kw="x", sink_input_ps=None - ) - ], + edges=[Task2TaskEdge(source=t3i, sink_task="t3b", sink_input_kw="x", sink_input_ps=None)], ) twoTaskRc = entrypoint.RunnerContext( workerId=worker, diff --git a/tests/cascade/executor/util.py b/tests/cascade/executor/util.py index 202f3791..55e8d7e5 100644 --- a/tests/cascade/executor/util.py +++ b/tests/cascade/executor/util.py @@ -35,6 +35,7 @@ logger = logging.getLogger(__name__) + @dataclass class CallableInstance: func: Callable @@ -44,7 +45,6 @@ class CallableInstance: exp_output: Any - @contextmanager def setup_shm(testId: str): mp_ctx = platform.get_mp_ctx("executor-aux") @@ -91,21 +91,11 @@ def simple_runner(callback: BackboneAddress, executionContext: ExecutionContext) memory.flush() - - -def callable2ctx( - callableInstance: CallableInstance, callback: BackboneAddress -) -> ExecutionContext: - taskInstance = TaskBuilder.from_callable( - callableInstance.func, callableInstance.env - ) +def callable2ctx(callableInstance: CallableInstance, callback: BackboneAddress) -> ExecutionContext: + taskInstance = TaskBuilder.from_callable(callableInstance.func, callableInstance.env) param_source = {} - params = [ - (key, DatasetId("taskId", f"kwarg.{key}"), value) - for key, value in callableInstance.kwargs.items() - ] + [ - (key, DatasetId("taskId", f"pos.{key}"), value) - for key, value in callableInstance.args + params = [(key, DatasetId("taskId", f"kwarg.{key}"), value) for key, value in callableInstance.kwargs.items()] + [ + (key, DatasetId("taskId", f"pos.{key}"), value) for key, value in callableInstance.args ] for key, ds_key, value in params: raw = cloudpickle.dumps(value) @@ -119,16 +109,11 @@ def callable2ctx( tasks={"taskId": taskInstance}, param_source={"taskId": param_source}, callback=callback, - publish={ - DatasetId("taskId", output) - for output, _ in taskInstance.definition.output_schema - }, + publish={DatasetId("taskId", output) for output, _ in taskInstance.definition.output_schema}, ) -def run_test( - callableInstance: CallableInstance, testId: str, max_runtime_sec: int -) -> Any: +def run_test(callableInstance: CallableInstance, testId: str, max_runtime_sec: int) -> Any: with setup_shm(testId): addr = f"ipc:///tmp/tc{testId}" listener = ZmqListener(addr) diff --git a/tests/cascade/gateway/test_run.py b/tests/cascade/gateway/test_run.py index 29d6079c..bdbba1ce 100644 --- a/tests/cascade/gateway/test_run.py +++ b/tests/cascade/gateway/test_run.py @@ -29,14 +29,7 @@ def get_job_succ() -> JobInstanceRich: ) sii = TaskInstance(definition=sid, static_input_kw={}, static_input_ps={}) - ji = ( - JobBuilder() - .with_node("so", soi) - .with_node("si", sii) - .with_edge("so", "si", 0, "o") - .build() - .get_or_raise() - ) + ji = JobBuilder().with_node("so", soi).with_node("si", sii).with_edge("so", "si", 0, "o").build().get_or_raise() ji.ext_outputs = [DatasetId("si", "o")] return JobInstanceRich(jobInstance=ji, checkpointSpec=None) @@ -99,7 +92,7 @@ def test_job(): job_progress_res = client.request_response(job_progress_req, url) assert isinstance(job_progress_res, api.JobProgressResponse) assert job_progress_res.error is None - is_computed = job_progress_res.progresses[job_id].pct == "100.00" # ty: ignore[possibly-missing-attribute] + is_computed = job_progress_res.progresses[job_id].pct == "100.00" # ty: ignore[possibly-missing-attribute] is_datasets = ji.jobInstance.ext_outputs[0] in job_progress_res.datasets[job_id] if is_computed and is_datasets: break @@ -110,9 +103,7 @@ def test_job(): time.sleep(2) assert tries < tries_limit - result_retrieval_req = api.ResultRetrievalRequest( - job_id=job_id, dataset_id=ji.jobInstance.ext_outputs[0] - ) + result_retrieval_req = api.ResultRetrievalRequest(job_id=job_id, dataset_id=ji.jobInstance.ext_outputs[0]) result_retrieval_res = client.request_response(result_retrieval_req, url) assert isinstance(result_retrieval_res, api.ResultRetrievalResponse) assert result_retrieval_res.error is None @@ -120,9 +111,7 @@ def test_job(): deser = api.decoded_result(result_retrieval_res, ji.jobInstance) assert deser == job_func(init_value) - result_deletion_req = api.ResultDeletionRequest( - datasets={job_id: [ji.jobInstance.ext_outputs[0]]} - ) + result_deletion_req = api.ResultDeletionRequest(datasets={job_id: [ji.jobInstance.ext_outputs[0]]}) result_deletion_res = client.request_response(result_deletion_req, url) assert isinstance(result_deletion_res, api.ResultDeletionResponse) assert result_deletion_res.error is None @@ -150,8 +139,8 @@ def test_job(): job_progress_res = client.request_response(job_progress_req, url) assert isinstance(job_progress_res, api.JobProgressResponse) assert job_progress_res.error is None - assert job_progress_res.progresses[job_id].pct != "100.00" # ty: ignore[possibly-missing-attribute] - if job_progress_res.progresses[job_id].failure is not None: # ty: ignore[possibly-missing-attribute] + assert job_progress_res.progresses[job_id].pct != "100.00" # ty: ignore[possibly-missing-attribute] + if job_progress_res.progresses[job_id].failure is not None: # ty: ignore[possibly-missing-attribute] break else: tries += 1 @@ -188,7 +177,7 @@ def test_job(): assert isinstance(job_progress_res, api.JobProgressResponse) assert job_progress_res.error is None is_computed = ( - lambda job_id: job_progress_res.progresses[job_id].pct == "100.00" # ty: ignore[possibly-missing-attribute] + lambda job_id: job_progress_res.progresses[job_id].pct == "100.00" # ty: ignore[possibly-missing-attribute] ) if all(is_computed(job_id) for job_id in job_ids): break @@ -202,7 +191,7 @@ def test_job(): # gw shutdown shutdown_req = api.ShutdownRequest() shutdown_res = client.request_response(shutdown_req, url, 3000) - assert hasattr(shutdown_res, 'error') and shutdown_res.error is None + assert hasattr(shutdown_res, "error") and shutdown_res.error is None gw.join(5) assert gw.exitcode == 0 diff --git a/tests/cascade/low/test_builders.py b/tests/cascade/low/test_builders.py index a2176656..db684a33 100644 --- a/tests/cascade/low/test_builders.py +++ b/tests/cascade/low/test_builders.py @@ -19,23 +19,19 @@ def test_func(x: int, y: str) -> int: "invalid static input for task: x needs int, got ", "invalid static input for task: y needs str, got ", ] - assert sorted(job.e) == sorted(expected) # ty: ignore[invalid-argument-type] + assert sorted(job.e) == sorted(expected) # ty: ignore[invalid-argument-type] task_good = TaskBuilder.from_callable(test_func).with_values(x=1, y="yes") _ = JobBuilder().with_node("task", task_good).build().get_or_raise() sink_bad = TaskBuilder.from_callable(test_func).with_values(x=1) job = ( - JobBuilder() - .with_node("source", task_good) - .with_node("sink", sink_bad) - .with_edge("source", "sink", "y") - .build() + JobBuilder().with_node("source", task_good).with_node("sink", sink_bad).with_edge("source", "sink", "y").build() ) expected = [ "edge connects two incompatible nodes: source=source.0 sink_task='sink' sink_input_kw='y' sink_input_ps=None", # noqa: E501 ] - assert sorted(job.e) == sorted(expected) # ty: ignore[invalid-argument-type] + assert sorted(job.e) == sorted(expected) # ty: ignore[invalid-argument-type] sink_good = TaskBuilder.from_callable(test_func).with_values(y="yes") _ = ( diff --git a/tests/cascade/low/test_core.py b/tests/cascade/low/test_core.py index c506df72..7d69820d 100644 --- a/tests/cascade/low/test_core.py +++ b/tests/cascade/low/test_core.py @@ -1,5 +1,6 @@ from cascade.low.core import DatasetId + def test_datasetid_serde(): cases = [ DatasetId(task="basic", output="0"), diff --git a/tests/cascade/low/test_exceptions.py b/tests/cascade/low/test_exceptions.py index 601a1d67..af7b1758 100644 --- a/tests/cascade/low/test_exceptions.py +++ b/tests/cascade/low/test_exceptions.py @@ -8,8 +8,6 @@ """Tests for cascade exception serialization/deserialization.""" -import pytest - from cascade.low.exceptions import ( CascadeError, CascadeInfrastructureError, @@ -25,7 +23,7 @@ def test_ser_des_cascade_internal_error(): exc = CascadeInternalError("something went wrong") serialized = ser(exc) deserialized = des(serialized) - + assert isinstance(deserialized, CascadeInternalError) assert deserialized.description == "something went wrong" assert deserialized.parent is None @@ -36,7 +34,7 @@ def test_ser_des_cascade_infrastructure_error(): exc = CascadeInfrastructureError("network failure") serialized = ser(exc) deserialized = des(serialized) - + assert isinstance(deserialized, CascadeInfrastructureError) assert deserialized.description == "network failure" assert deserialized.parent is None @@ -47,7 +45,7 @@ def test_ser_des_cascade_user_error(): exc = CascadeUserError("invalid configuration") serialized = ser(exc) deserialized = des(serialized) - + assert isinstance(deserialized, CascadeUserError) assert deserialized.description == "invalid configuration" assert deserialized.parent is None @@ -58,7 +56,7 @@ def test_ser_des_cascade_error(): exc = CascadeError("general error") serialized = ser(exc) deserialized = des(serialized) - + assert isinstance(deserialized, CascadeError) assert deserialized.description == "general error" assert deserialized.parent is None @@ -70,7 +68,7 @@ def test_ser_des_with_parent(): exc = CascadeInternalError("child error", parent=parent_exc) serialized = ser(exc) deserialized = des(serialized) - + assert isinstance(deserialized, CascadeInternalError) assert deserialized.description == "child error" assert deserialized.parent is None @@ -80,7 +78,7 @@ def test_des_invalid_string(): """Test deserialization of invalid string returns CascadeInternalError.""" invalid_str = "not a valid exception format" deserialized = des(invalid_str) - + assert isinstance(deserialized, CascadeInternalError) assert deserialized.description == invalid_str assert deserialized.parent is None @@ -90,7 +88,7 @@ def test_des_unknown_exception_class(): """Test deserialization of unknown exception class returns CascadeInternalError.""" invalid_str = "UnknownError('some error')" deserialized = des(invalid_str) - + assert isinstance(deserialized, CascadeInternalError) assert deserialized.description == invalid_str assert deserialized.parent is None @@ -104,7 +102,7 @@ def test_ser_des_roundtrip_all_types(): CascadeInfrastructureError("infra error"), CascadeUserError("user error"), ] - + for exc in exceptions: serialized = ser(exc) deserialized = des(serialized) diff --git a/tests/cascade/scheduler/test_checkpoints.py b/tests/cascade/scheduler/test_checkpoints.py index 3bd28180..d3115b2a 100644 --- a/tests/cascade/scheduler/test_checkpoints.py +++ b/tests/cascade/scheduler/test_checkpoints.py @@ -1,7 +1,8 @@ from cascade.low.builders import JobBuilder, TaskBuilder -from cascade.scheduler.precompute import precompute +from cascade.low.core import DatasetId, JobInstanceRich from cascade.scheduler.checkpoints import trim_with_persisted -from cascade.low.core import JobInstanceRich, DatasetId +from cascade.scheduler.precompute import precompute + def test_trim_with_checkpoints(): # we have a graph with @@ -12,7 +13,8 @@ def test_trim_with_checkpoints(): # We will checkpoint on the transform, meaning 1 source should be trimmed jobInstanceOrig = ( - JobBuilder() + ( + JobBuilder() .with_node( "source1", TaskBuilder.from_entrypoint("whatever", {}, "Any"), @@ -43,11 +45,14 @@ def test_trim_with_checkpoints(): ) .with_edge("product1", "sink", "i1") .with_edge("product2", "sink", "i2") - ).build().get_or_raise() + ) + .build() + .get_or_raise() + ) jobRich = JobInstanceRich(jobInstance=jobInstanceOrig, checkpointSpec=None) preschedule = precompute(jobRich.jobInstance) persisted = {DatasetId(task="transform", output="0")} jobInstanceNew, preschedule, persisted_valid = trim_with_persisted(jobRich, preschedule, persisted) assert persisted_valid == persisted - assert set(jobInstanceNew.tasks.keys()) == {'source2', 'transform', 'product1', 'product2', 'sink'} + assert set(jobInstanceNew.tasks.keys()) == {"source2", "transform", "product1", "product2", "sink"} diff --git a/tests/cascade/scheduler/util.py b/tests/cascade/scheduler/util.py index c0a52d97..0fe5a86f 100644 --- a/tests/cascade/scheduler/util.py +++ b/tests/cascade/scheduler/util.py @@ -20,11 +20,11 @@ from cascade.low.builders import JobBuilder, TaskBuilder from cascade.low.core import ( - JobInstanceRich, DatasetId, Environment, JobExecutionRecord, JobInstance, + JobInstanceRich, TaskExecutionRecord, Worker, WorkerId, @@ -33,7 +33,7 @@ # NOTE ideally we replace it with representative real world usecases -## *** graph builders *** +# *** graph builders *** def mapMonad(b: bytes) -> bytes: @@ -55,19 +55,13 @@ def sinkFunc(*args) -> str: @dataclass class BuilderGroup: job: JobBuilder = field(default_factory=lambda: JobBuilder()) - record: JobExecutionRecord = field( - default_factory=lambda: JobExecutionRecord(tasks={}, datasets_mb={}) - ) + record: JobExecutionRecord = field(default_factory=lambda: JobExecutionRecord(tasks={}, datasets_mb={})) layers: list[int] = field(default_factory=list) -def add_large_source( - builder: BuilderGroup, runtime: int, runmem: int, outsize: int -) -> None: +def add_large_source(builder: BuilderGroup, runtime: int, runmem: int, outsize: int) -> None: builder.job = builder.job.with_node("source", TaskBuilder.from_callable(sourceFunc)) - builder.record.tasks["source"] = TaskExecutionRecord( - cpuseconds=runtime, memory_mb=runmem - ) + builder.record.tasks["source"] = TaskExecutionRecord(cpuseconds=runtime, memory_mb=runmem) builder.record.datasets_mb[DatasetId("source", Node.DEFAULT_OUTPUT)] = outsize builder.layers = [1] @@ -83,22 +77,16 @@ def add_postproc( for i in range(n): node = f"pproc{len(builder.layers)}-{i}" if from_layer == 0: - builder.job = builder.job.with_node( - node, TaskBuilder.from_callable(mapMonad) - ) + builder.job = builder.job.with_node(node, TaskBuilder.from_callable(mapMonad)) builder.job = builder.job.with_edge("source", node, "b") else: - e1 = f"pproc{from_layer}-{(i+131)%builder.layers[from_layer]}" - e2 = f"pproc{from_layer}-{(i+53)%builder.layers[from_layer]}" - builder.job = builder.job.with_node( - node, TaskBuilder.from_callable(mapDiad) - ) + e1 = f"pproc{from_layer}-{(i + 131) % builder.layers[from_layer]}" + e2 = f"pproc{from_layer}-{(i + 53) % builder.layers[from_layer]}" + builder.job = builder.job.with_node(node, TaskBuilder.from_callable(mapDiad)) builder.job = builder.job.with_edge(e1, node, "a") builder.job = builder.job.with_edge(e2, node, "b") # print(f"adding {node} with edges {e1}, {e2}") - builder.record.tasks[node] = TaskExecutionRecord( - cpuseconds=runtime, memory_mb=runmem - ) + builder.record.tasks[node] = TaskExecutionRecord(cpuseconds=runtime, memory_mb=runmem) builder.record.datasets_mb[DatasetId(node, Node.DEFAULT_OUTPUT)] = outsize builder.layers.append(n) @@ -116,9 +104,8 @@ def add_sink( for i in range(builder.layers[from_layer] // frac): source = ((i * frac) + 157) % builder.layers[from_layer] builder.job = builder.job.with_edge(f"pproc{from_layer}-{source}", node, i) - builder.record.tasks[node] = TaskExecutionRecord( - cpuseconds=runtime, memory_mb=runmem - ) + builder.record.tasks[node] = TaskExecutionRecord(cpuseconds=runtime, memory_mb=runmem) + def enrich_instance(job: JobInstance) -> JobInstanceRich: return JobInstanceRich( @@ -159,7 +146,7 @@ def get_job1() -> tuple[JobInstanceRich, JobExecutionRecord]: return enrich_instance(builder.job.build().get_or_raise()), builder.record -## *** environment builders *** +# *** environment builders *** def get_env(hosts: int, workers_per_host: int) -> Environment: return Environment( workers={ diff --git a/tests/cascade/shm/test_shm.py b/tests/cascade/shm/test_shm.py index 4eb5768e..e3cfd5cc 100644 --- a/tests/cascade/shm/test_shm.py +++ b/tests/cascade/shm/test_shm.py @@ -7,7 +7,6 @@ # nor does it submit to any jurisdiction. import re -from multiprocessing import Process import pytest @@ -23,10 +22,11 @@ # forkserver right away, because the os.environ changes are not reflected after # the mp manager gets launched. + @pytest.mark.parametrize("shm_addr", [12345, "/tmp/shmport12345"]) def test_shm_simple(shm_addr): api.publish_socket_addr(shm_addr) - pref = f"cTi{shm_addr%10}" if isinstance(shm_addr, int) else f"cTu{shm_addr[-1]}" + pref = f"cTi{shm_addr % 10}" if isinstance(shm_addr, int) else f"cTu{shm_addr[-1]}" serverP = get_mp_ctx("executor-aux").Process( target=server.entrypoint, kwargs={"logging_config": logging_config, "shm_pref": pref}, @@ -60,7 +60,7 @@ def test_shm_simple(shm_addr): @pytest.mark.parametrize("shm_addr", [12346, "/tmp/shmport12346"]) def test_shm_disk(shm_addr): capacity = 4 - pref = f"cTi{shm_addr%10}" if isinstance(shm_addr, int) else f"cTu{shm_addr[-1]}" + pref = f"cTi{shm_addr % 10}" if isinstance(shm_addr, int) else f"cTu{shm_addr[-1]}" api.publish_socket_addr(shm_addr) serverP = get_mp_ctx("executor-aux").Process( diff --git a/tests/earthkit_workflows/backends/generic_tests.py b/tests/earthkit_workflows/backends/generic_tests.py index 23344c86..1626059b 100644 --- a/tests/earthkit_workflows/backends/generic_tests.py +++ b/tests/earthkit_workflows/backends/generic_tests.py @@ -28,11 +28,7 @@ def shape(self, array): def test_multi_arg(self, num_inputs, input_shape, kwargs, output_shape): for func in ["mean", "std", "max", "min", "sum", "prod", "var"]: assert ( - self.shape( - getattr(backends, func)( - *self.input_generator(num_inputs, input_shape), **kwargs - ) - ) + self.shape(getattr(backends, func)(*self.input_generator(num_inputs, input_shape), **kwargs)) == output_shape ) @@ -44,14 +40,7 @@ def test_multi_arg(self, num_inputs, input_shape, kwargs, output_shape): ) def test_two_arg(self, num_inputs, input_shape, output_shape): for func in ["add", "subtract", "multiply", "divide", "pow"]: - assert ( - self.shape( - getattr(backends, func)( - *self.input_generator(num_inputs, input_shape) - ) - ) - == output_shape - ) + assert self.shape(getattr(backends, func)(*self.input_generator(num_inputs, input_shape))) == output_shape @pytest.mark.parametrize( ["num_inputs", "shape"], diff --git a/tests/earthkit_workflows/backends/test_arrayapi.py b/tests/earthkit_workflows/backends/test_arrayapi.py index d6c19164..7f83885f 100644 --- a/tests/earthkit_workflows/backends/test_arrayapi.py +++ b/tests/earthkit_workflows/backends/test_arrayapi.py @@ -30,10 +30,7 @@ def shape(self, array): def test_multi_arg_axis(self, num_inputs, input_shape, kwargs, output_shape): for func in ["mean", "std", "max", "min", "sum", "prod", "var"]: assert ( - getattr(backends, func)( - *self.input_generator(num_inputs, input_shape), **kwargs - ).shape - == output_shape + getattr(backends, func)(*self.input_generator(num_inputs, input_shape), **kwargs).shape == output_shape ) @pytest.mark.parametrize( @@ -45,12 +42,7 @@ def test_multi_arg_axis(self, num_inputs, input_shape, kwargs, output_shape): ) def test_two_arg_single(self, num_inputs, input_shape, output_shape): for func in ["add", "subtract", "multiply", "divide"]: - assert ( - getattr(backends, func)( - *self.input_generator(num_inputs, input_shape) - ).shape - == output_shape - ) + assert getattr(backends, func)(*self.input_generator(num_inputs, input_shape)).shape == output_shape def test_concatenate(self): input = self.input_generator(3) + self.input_generator(2, (2, 1)) diff --git a/tests/earthkit_workflows/backends/test_earthkit.py b/tests/earthkit_workflows/backends/test_earthkit.py index 858b060d..547b2def 100644 --- a/tests/earthkit_workflows/backends/test_earthkit.py +++ b/tests/earthkit_workflows/backends/test_earthkit.py @@ -21,9 +21,7 @@ def __init__(self, *args, **kwargs): def random_fieldlist(*shape) -> SimpleFieldList: - return FieldList.from_array( - random.rand(*shape), [MockMetaData() for x in range(shape[0])] - ) + return FieldList.from_array(random.rand(*shape), [MockMetaData() for x in range(shape[0])]) def to_array(fl: SimpleFieldList): diff --git a/tests/earthkit_workflows/backends/test_xarray.py b/tests/earthkit_workflows/backends/test_xarray.py index 29e5e844..20b1f3d4 100644 --- a/tests/earthkit_workflows/backends/test_xarray.py +++ b/tests/earthkit_workflows/backends/test_xarray.py @@ -24,10 +24,7 @@ class XarrayBackend(BackendBase): ) def test_multi_arg_dim(self, num_inputs, kwargs, output_shape): for func in ["mean", "std", "max", "min", "sum", "prod", "var"]: - assert self.shape( - (getattr(backends, func)(*self.input_generator(num_inputs), **kwargs)) - == output_shape - ) + assert self.shape((getattr(backends, func)(*self.input_generator(num_inputs), **kwargs)) == output_shape) def test_concatenate(self): input = self.input_generator(3) + self.input_generator(2, (2, 1)) @@ -61,9 +58,7 @@ def test_stack(self): # With dim and axis y = backends.stack(*input, axis=2, dim="NEW", coords="minimal") assert np.all(x.transpose("dim0", "dim1", "NEW") == y) - assert self.shape( - backends.stack(*self.input_generator(1), axis=0, dim="NEW") - ) == ( + assert self.shape(backends.stack(*self.input_generator(1), axis=0, dim="NEW")) == ( 1, 2, 3, diff --git a/tests/earthkit_workflows/graph/test_fuse.py b/tests/earthkit_workflows/graph/test_fuse.py index fed12f37..9e32181a 100644 --- a/tests/earthkit_workflows/graph/test_fuse.py +++ b/tests/earthkit_workflows/graph/test_fuse.py @@ -32,9 +32,7 @@ def fuse_linear(parent: Node, pout: str, child: Node, cin: str) -> Node | None: payload.extend(parent.payload) payload.append(child.name) print(f"Fuse {parent.name} ({parent.payload}) with {child.name} -> {payload}") - return Node( - f"{parent.name}+{child.name}", child.outputs, payload=payload, **parent.inputs - ) + return Node(f"{parent.name}+{child.name}", child.outputs, payload=payload, **parent.inputs) def test_fuse_linear(): @@ -94,7 +92,7 @@ def test_nofuse_comb(): "accum-5": { "inputs": { "input0": "accum-4", - **{f"input{i-3}": f"reader-{i}" for i in range(4, N)}, + **{f"input{i - 3}": f"reader-{i}" for i in range(4, N)}, }, "outputs": [D], }, diff --git a/tests/earthkit_workflows/graph/test_graph.py b/tests/earthkit_workflows/graph/test_graph.py index e248f59a..52425212 100644 --- a/tests/earthkit_workflows/graph/test_graph.py +++ b/tests/earthkit_workflows/graph/test_graph.py @@ -266,7 +266,5 @@ def test_has_cycle(): g = multi(5, NO1, 2) assert not g.has_cycle() - g.get_node("process-0").inputs["input0"] = g.get_node( - f"process-{NO1-1}" - ).get_output("output0") + g.get_node("process-0").inputs["input0"] = g.get_node(f"process-{NO1 - 1}").get_output("output0") assert g.has_cycle() diff --git a/tests/earthkit_workflows/graph/test_split.py b/tests/earthkit_workflows/graph/test_split.py index 69d5708b..95439c11 100644 --- a/tests/earthkit_workflows/graph/test_split.py +++ b/tests/earthkit_workflows/graph/test_split.py @@ -68,10 +68,7 @@ def splitter(node: Node) -> int: "inputs": {f"input{i}": f"reader-{i}" for i in range(NR)}, "outputs": [f"output{i}" for i in range(NO1)], } - assert s0 == { - cut.name: {"inputs": {"input": cut.source}, "outputs": []} - for cut in cuts_from[0] - } + assert s0 == {cut.name: {"inputs": {"input": cut.source}, "outputs": []} for cut in cuts_from[0]} s1 = serialise(parts[1]) p1_inp = {} @@ -84,10 +81,7 @@ def splitter(node: Node) -> int: w0_inp[cut.dest_input] = cut.name assert s1.pop("process-1") == {"inputs": p1_inp, "outputs": [D]} assert s1.pop("writer-0") == {"inputs": w0_inp, "outputs": []} - assert s1 == { - cut.name: {"inputs": {"input": cut.source}, "outputs": []} - for cut in cuts_from[1] - } + assert s1 == {cut.name: {"inputs": {"input": cut.source}, "outputs": []} for cut in cuts_from[1]} s2 = serialise(parts[2]) p2_inp = {} @@ -100,7 +94,4 @@ def splitter(node: Node) -> int: w1_inp[cut.dest_input] = cut.name assert s2.pop("process-2") == {"inputs": p2_inp, "outputs": ["output0", "output1"]} assert s2.pop("writer-1") == {"inputs": w1_inp, "outputs": []} - assert s2 == { - cut.name: {"inputs": {"input": cut.source}, "outputs": []} - for cut in cuts_from[2] - } + assert s2 == {cut.name: {"inputs": {"input": cut.source}, "outputs": []} for cut in cuts_from[2]} diff --git a/tests/earthkit_workflows/graph/test_transform.py b/tests/earthkit_workflows/graph/test_transform.py index 794ad89e..3fa0b7fa 100644 --- a/tests/earthkit_workflows/graph/test_transform.py +++ b/tests/earthkit_workflows/graph/test_transform.py @@ -30,9 +30,7 @@ def processor(self, p: Node, **inputs: Any) -> tuple[str, dict[str, Any]]: def sink(self, s: Node, **inputs: Any) -> tuple[str, dict[str, Any]]: return s.name, inputs - def output( - self, node: str | tuple[str, Any], name: str - ) -> str | tuple[str, dict[str, Any]]: + def output(self, node: str | tuple[str, Any], name: str) -> str | tuple[str, dict[str, Any]]: if isinstance(node, str): # source return f"{node}.{name}" pname, inputs = node # processor @@ -105,9 +103,7 @@ def node(self, n: Node, **inputs: tuple[str, str, DepDict]) -> tuple[str, DepDic res[n.name] = ndeps return n.name, res - def output( - self, ntrans: tuple[str, DepDict], oname: str - ) -> tuple[str, str, DepDict]: + def output(self, ntrans: tuple[str, DepDict], oname: str) -> tuple[str, str, DepDict]: nname, ndeps = ntrans return nname, oname, ndeps diff --git a/tests/earthkit_workflows/graph/test_visit.py b/tests/earthkit_workflows/graph/test_visit.py index 9160a465..c70f2fa0 100644 --- a/tests/earthkit_workflows/graph/test_visit.py +++ b/tests/earthkit_workflows/graph/test_visit.py @@ -56,9 +56,7 @@ def test_visit_disc(): names = gnames(g) assert len(names) == 5 + 5 + 5 assert set(names) == set( - [f"reader-{i}" for i in range(5)] - + [f"process-{i}" for i in range(5)] - + [f"writer-{i}" for i in range(5)] + [f"reader-{i}" for i in range(5)] + [f"process-{i}" for i in range(5)] + [f"writer-{i}" for i in range(5)] ) @@ -67,9 +65,7 @@ def test_visit_simple(): names = gnames(g) assert len(names) == 5 + 3 + 3 assert set(names) == set( - [f"reader-{i}" for i in range(5)] - + [f"process-{i}" for i in range(3)] - + [f"writer-{i}" for i in range(3)] + [f"reader-{i}" for i in range(5)] + [f"process-{i}" for i in range(3)] + [f"writer-{i}" for i in range(3)] ) @@ -78,9 +74,7 @@ def test_visit_multi(): names = gnames(g) assert len(names) == 5 + 3 + 2 * (3 - 2) assert set(names) == set( - [f"reader-{i}" for i in range(5)] - + [f"process-{i}" for i in range(3)] - + [f"writer-{i}" for i in range(2)] + [f"reader-{i}" for i in range(5)] + [f"process-{i}" for i in range(3)] + [f"writer-{i}" for i in range(2)] ) @@ -112,9 +106,7 @@ def test_visit_sources(): assert set(snames) == set(f"reader-{i}" for i in range(6)) onames = [n.name for n in v.others] assert len(onames) == 2 + 2 - assert set(onames) == set( - [f"process-{i}" for i in range(2)] + [f"writer-{i}" for i in range(2)] - ) + assert set(onames) == set([f"process-{i}" for i in range(2)] + [f"writer-{i}" for i in range(2)]) class ProcessorLister(Visitor): @@ -145,9 +137,7 @@ def test_visit_processors(): assert set(pnames) == set(f"process-{i}" for i in range(4)) onames = [n.name for n in v.others] assert len(onames) == 7 + 4 - assert set(onames) == set( - [f"reader-{i}" for i in range(7)] + [f"writer-{i}" for i in range(4)] - ) + assert set(onames) == set([f"reader-{i}" for i in range(7)] + [f"writer-{i}" for i in range(4)]) class SinkLister(Visitor): @@ -178,9 +168,7 @@ def test_visit_sinks(): assert set(snames) == set(f"writer-{i}" for i in range(5)) onames = [n.name for n in v.others] assert len(onames) == 9 + 5 - assert set(onames) == set( - [f"reader-{i}" for i in range(9)] + [f"process-{i}" for i in range(5)] - ) + assert set(onames) == set([f"reader-{i}" for i in range(9)] + [f"process-{i}" for i in range(5)]) class SegregatedLister(Visitor): diff --git a/tests/earthkit_workflows/helpers.py b/tests/earthkit_workflows/helpers.py index 90d45821..91bf4495 100644 --- a/tests/earthkit_workflows/helpers.py +++ b/tests/earthkit_workflows/helpers.py @@ -23,7 +23,5 @@ def mock_action(shape: tuple) -> Action: it = np.nditer(nodes, flags=["multi_index", "refs_ok"]) for _ in it: nodes[it.multi_index] = MockNode(f"{it.multi_index}") - nodes_xr = xr.DataArray( - nodes, coords={f"dim_{x}": list(range(dim)) for x, dim in enumerate(shape)} - ) + nodes_xr = xr.DataArray(nodes, coords={f"dim_{x}": list(range(dim)) for x, dim in enumerate(shape)}) return Action(nodetree_from_dict({"/": nodes_xr})) diff --git a/tests/earthkit_workflows/test_fluent.py b/tests/earthkit_workflows/test_fluent.py index 4bc1db41..aa76d641 100644 --- a/tests/earthkit_workflows/test_fluent.py +++ b/tests/earthkit_workflows/test_fluent.py @@ -123,9 +123,9 @@ def test_broadcast(): it = np.nditer(out_array, flags=["multi_index", "refs_ok"]) for _ in it: print(it.multi_index) - assert out_array[it.multi_index].item(0).inputs[ - "input0" - ].parent == nodetree_array(input_action.nodes)[it.multi_index[:2]].item(0) + assert out_array[it.multi_index].item(0).inputs["input0"].parent == nodetree_array(input_action.nodes)[ + it.multi_index[:2] + ].item(0) def test_flatten_expand(): @@ -282,15 +282,13 @@ def test_func(length: int, *multipliers): for val in range(length): yield val * sum([1, *multipliers]) - action = from_source( - functools.partial(test_func, 10), ("val", list(range(0, 100, 10))) - ) + action = from_source(functools.partial(test_func, 10), ("val", list(range(0, 100, 10)))) narray = nodetree_array(action.nodes) assert narray.shape == (10,) assert narray.dims == ("val",) - cas = action.map( - functools.partial(test_func, length=5), ("map", list(range(5))) - ).reduce(functools.partial(test_func, length=2), ("reduce", ["a", "b"])) + cas = action.map(functools.partial(test_func, length=5), ("map", list(range(5)))).reduce( + functools.partial(test_func, length=2), ("reduce", ["a", "b"]) + ) new_narray = nodetree_array(cas.nodes) assert new_narray.dims == ("map", "reduce") expected_coords = {"map": list(range(5)), "reduce": ["a", "b"]} diff --git a/tests/earthkit_workflows/test_qubed_expansion.py b/tests/earthkit_workflows/test_qubed_expansion.py index 667a25b3..3baf9f5c 100644 --- a/tests/earthkit_workflows/test_qubed_expansion.py +++ b/tests/earthkit_workflows/test_qubed_expansion.py @@ -11,8 +11,9 @@ import pytest from qubed import Qube -from earthkit.workflows.nodetree import nodetree_array from earthkit.workflows._qubed import _convert_num_to_abc, expand_as_qube +from earthkit.workflows.nodetree import nodetree_array + from .helpers import mock_action # ============================================================================ @@ -62,17 +63,21 @@ def hierarchical_qube(): After expansion, children should have BOTH step AND their own dims. """ # Create children with step dimension AND their own dimensions - surface = Qube.from_datacube({ - "step": [6, 12], - "param": ["100u", "100v", "10u", "10v", "2d", "2t"], - }) + surface = Qube.from_datacube( + { + "step": [6, 12], + "param": ["100u", "100v", "10u", "10v", "2d", "2t"], + } + ) surface.add_metadata({"name": "surface"}) - pressure = Qube.from_datacube({ - "step": [6, 12], - "param": ["q", "t", "u", "v"], - "level": [50, 100, 150, 200, 250], - }) + pressure = Qube.from_datacube( + { + "step": [6, 12], + "param": ["q", "t", "u", "v"], + "level": [50, 100, 150, 200, 250], + } + ) pressure.add_metadata({"name": "pressure"}) # Combine: both children have step, so parent will have step @@ -99,23 +104,18 @@ def multi_level_qube(): All children have step dimension in the qube, which creates step dimension on parent. After expansion, all branches should have step dimension. """ - child1 = Qube.from_datacube({ - "step": [1, 2, 3], - "param": ["a", "b"] - }) + child1 = Qube.from_datacube({"step": [1, 2, 3], "param": ["a", "b"]}) child1.add_metadata({"name": "group1"}) - child2 = Qube.from_datacube({ - "step": [1, 2, 3], - "param": ["c", "d"], - "class" : "od" - }) + child2 = Qube.from_datacube({"step": [1, 2, 3], "param": ["c", "d"], "class": "od"}) - nested = Qube.from_datacube({ - "step": [1, 2, 3], - "param": ["c", "d"], - "level": [100, 200], - }) + nested = Qube.from_datacube( + { + "step": [1, 2, 3], + "param": ["c", "d"], + "level": [100, 200], + } + ) # Combine: child2 and nested both have step+param, so child2|nested will have those child2_with_nested = child2 | nested @@ -126,6 +126,7 @@ def multi_level_qube(): return qube + @pytest.fixture def empty_qube(): """Create an empty qube.""" @@ -482,31 +483,38 @@ def test_expand_as_qube_with_real_action(): assert "step" in result.nodes.to_dataset().dims -@pytest.mark.parametrize("qube_fixture", [ - "pressure_level_qube", - "hierarchical_qube", -]) +@pytest.mark.parametrize( + "qube_fixture", + [ + "pressure_level_qube", + "hierarchical_qube", + ], +) def test_expand_as_qube_with_real_action_post_select(qube_fixture, request): qube = request.getfixturevalue(qube_fixture) action = mock_action(shape=(2, 2)) result = expand_as_qube(action, qube) - subset = result.select(param='t') - + subset = result.select(param="t") + da = nodetree_array(subset.nodes) assert "step" in da.dims assert "param" not in da.dims assert "param" in da.coords - - assert da.param == 't' + + assert da.param == "t" with pytest.raises(KeyError): - subset = result.select(param='nonexistent_param') + subset = result.select(param="nonexistent_param") -@pytest.mark.parametrize("qube_fixture", [ - "pressure_level_qube", - "hierarchical_qube", -]) + +@pytest.mark.parametrize( + "qube_fixture", + [ + "pressure_level_qube", + "hierarchical_qube", + ], +) def test_expand_as_qube_with_real_action_post_select_level(qube_fixture, request): qube = request.getfixturevalue(qube_fixture) action = mock_action(shape=(2, 2)) @@ -522,4 +530,4 @@ def test_expand_as_qube_with_real_action_post_select_level(qube_fixture, request assert da.level == 50 with pytest.raises(KeyError): - subset = result.select(param='nonexistent_param') + subset = result.select(param="nonexistent_param") diff --git a/uv.lock b/uv.lock index 8daf7a7e..ee9cf449 100644 --- a/uv.lock +++ b/uv.lock @@ -1,2289 +1,2289 @@ -version = 1 -revision = 3 requires-python = ">=3.11" resolution-markers = [ - "python_full_version >= '3.14' and platform_machine == 'ARM64' and sys_platform == 'win32'", - "python_full_version < '3.14' and platform_machine == 'ARM64' and sys_platform == 'win32'", - "python_full_version >= '3.14' and platform_machine != 'ARM64' 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 platform_machine != 'ARM64' 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 platform_machine == 'ARM64' and sys_platform == 'win32'", + "python_full_version < '3.14' and platform_machine == 'ARM64' and sys_platform == 'win32'", + "python_full_version >= '3.14' and platform_machine != 'ARM64' 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 platform_machine != 'ARM64' 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'" ] +revision = 3 +version = 1 [[package]] name = "annotated-types" +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"} +source = {registry = "https://pypi.org/simple"} 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" }, + {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 = "array-api-compat" +sdist = {url = "https://files.pythonhosted.org/packages/68/36/f799b36d7025a92a23819f9f06541babdb84b6fd0bd4253f8be2eca348a4/array_api_compat-1.13.0.tar.gz", hash = "sha256:8b83a56aa8b9477472fee37f7731968dd213e20c198a05ac49caeff9b03f48a6", size = 103065, upload-time = "2025-12-28T11:26:57.734Z"} +source = {registry = "https://pypi.org/simple"} version = "1.13.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/68/36/f799b36d7025a92a23819f9f06541babdb84b6fd0bd4253f8be2eca348a4/array_api_compat-1.13.0.tar.gz", hash = "sha256:8b83a56aa8b9477472fee37f7731968dd213e20c198a05ac49caeff9b03f48a6", size = 103065, upload-time = "2025-12-28T11:26:57.734Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/df/5d/493b1b5528ab5072feae30821ff3a07b7a0474213d548efb1fdf135f85c1/array_api_compat-1.13.0-py3-none-any.whl", hash = "sha256:c15026a0ddec42815383f07da285472e1b1ff2e632eb7afbcfe9b08fcbad9bf1", size = 58585, upload-time = "2025-12-28T11:26:56.081Z" }, + {url = "https://files.pythonhosted.org/packages/df/5d/493b1b5528ab5072feae30821ff3a07b7a0474213d548efb1fdf135f85c1/array_api_compat-1.13.0-py3-none-any.whl", hash = "sha256:c15026a0ddec42815383f07da285472e1b1ff2e632eb7afbcfe9b08fcbad9bf1", size = 58585, upload-time = "2025-12-28T11:26:56.081Z"} ] [[package]] name = "asttokens" +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"} +source = {registry = "https://pypi.org/simple"} 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" }, + {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 = "attrs" +sdist = {url = "https://files.pythonhosted.org/packages/6b/5c/685e6633917e101e5dcb62b9dd76946cbb57c26e133bae9e0cd36033c0a9/attrs-25.4.0.tar.gz", hash = "sha256:16d5969b87f0859ef33a48b35d55ac1be6e42ae49d5e853b597db70c35c57e11", size = 934251, upload-time = "2025-10-06T13:54:44.725Z"} +source = {registry = "https://pypi.org/simple"} version = "25.4.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/6b/5c/685e6633917e101e5dcb62b9dd76946cbb57c26e133bae9e0cd36033c0a9/attrs-25.4.0.tar.gz", hash = "sha256:16d5969b87f0859ef33a48b35d55ac1be6e42ae49d5e853b597db70c35c57e11", size = 934251, upload-time = "2025-10-06T13:54:44.725Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/3a/2a/7cc015f5b9f5db42b7d48157e23356022889fc354a2813c15934b7cb5c0e/attrs-25.4.0-py3-none-any.whl", hash = "sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373", size = 67615, upload-time = "2025-10-06T13:54:43.17Z" }, + {url = "https://files.pythonhosted.org/packages/3a/2a/7cc015f5b9f5db42b7d48157e23356022889fc354a2813c15934b7cb5c0e/attrs-25.4.0-py3-none-any.whl", hash = "sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373", size = 67615, upload-time = "2025-10-06T13:54:43.17Z"} ] [[package]] -name = "bokeh" -version = "3.9.0" -source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "contourpy" }, - { name = "jinja2" }, - { name = "narwhals" }, - { name = "numpy" }, - { name = "packaging" }, - { name = "pillow" }, - { name = "pyyaml" }, - { name = "tornado", marker = "sys_platform != 'emscripten'" }, - { name = "xyzservices" }, + {name = "contourpy"}, + {name = "jinja2"}, + {name = "narwhals"}, + {name = "numpy"}, + {name = "packaging"}, + {name = "pillow"}, + {name = "pyyaml"}, + {name = "tornado", marker = "sys_platform != 'emscripten'"}, + {name = "xyzservices"} ] -sdist = { url = "https://files.pythonhosted.org/packages/bf/0d/fabb70707646217e4b0e3943e05730eab8c1f7b7e7485145f8594b52e606/bokeh-3.9.0.tar.gz", hash = "sha256:775219714a8496973ddbae16b1861606ba19fe670a421e4d43267b41148e07a3", size = 5740345, upload-time = "2026-03-11T17:58:34.062Z" } +name = "bokeh" +sdist = {url = "https://files.pythonhosted.org/packages/bf/0d/fabb70707646217e4b0e3943e05730eab8c1f7b7e7485145f8594b52e606/bokeh-3.9.0.tar.gz", hash = "sha256:775219714a8496973ddbae16b1861606ba19fe670a421e4d43267b41148e07a3", size = 5740345, upload-time = "2026-03-11T17:58:34.062Z"} +source = {registry = "https://pypi.org/simple"} +version = "3.9.0" wheels = [ - { url = "https://files.pythonhosted.org/packages/47/0b/bdf449df87be3f07b23091ceafee8c3ef569cf6d2fb7edec6e3b12b3faa4/bokeh-3.9.0-py3-none-any.whl", hash = "sha256:b252bfb16a505f0e0c57d532d0df308ae1667235bafc622aa9441fe9e7c5ce4a", size = 6396068, upload-time = "2026-03-11T17:58:31.645Z" }, + {url = "https://files.pythonhosted.org/packages/47/0b/bdf449df87be3f07b23091ceafee8c3ef569cf6d2fb7edec6e3b12b3faa4/bokeh-3.9.0-py3-none-any.whl", hash = "sha256:b252bfb16a505f0e0c57d532d0df308ae1667235bafc622aa9441fe9e7c5ce4a", size = 6396068, upload-time = "2026-03-11T17:58:31.645Z"} ] [[package]] -name = "build" -version = "1.4.0" -source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "colorama", marker = "os_name == 'nt'" }, - { name = "packaging" }, - { name = "pyproject-hooks" }, + {name = "colorama", marker = "os_name == 'nt'"}, + {name = "packaging"}, + {name = "pyproject-hooks"} ] -sdist = { url = "https://files.pythonhosted.org/packages/42/18/94eaffda7b329535d91f00fe605ab1f1e5cd68b2074d03f255c7d250687d/build-1.4.0.tar.gz", hash = "sha256:f1b91b925aa322be454f8330c6fb48b465da993d1e7e7e6fa35027ec49f3c936", size = 50054, upload-time = "2026-01-08T16:41:47.696Z" } +name = "build" +sdist = {url = "https://files.pythonhosted.org/packages/42/18/94eaffda7b329535d91f00fe605ab1f1e5cd68b2074d03f255c7d250687d/build-1.4.0.tar.gz", hash = "sha256:f1b91b925aa322be454f8330c6fb48b465da993d1e7e7e6fa35027ec49f3c936", size = 50054, upload-time = "2026-01-08T16:41:47.696Z"} +source = {registry = "https://pypi.org/simple"} +version = "1.4.0" wheels = [ - { url = "https://files.pythonhosted.org/packages/c5/0d/84a4380f930db0010168e0aa7b7a8fed9ba1835a8fbb1472bc6d0201d529/build-1.4.0-py3-none-any.whl", hash = "sha256:6a07c1b8eb6f2b311b96fcbdbce5dab5fe637ffda0fd83c9cac622e927501596", size = 24141, upload-time = "2026-01-08T16:41:46.453Z" }, + {url = "https://files.pythonhosted.org/packages/c5/0d/84a4380f930db0010168e0aa7b7a8fed9ba1835a8fbb1472bc6d0201d529/build-1.4.0-py3-none-any.whl", hash = "sha256:6a07c1b8eb6f2b311b96fcbdbce5dab5fe637ffda0fd83c9cac622e927501596", size = 24141, upload-time = "2026-01-08T16:41:46.453Z"} ] [[package]] name = "certifi" +sdist = {url = "https://files.pythonhosted.org/packages/e0/2d/a891ca51311197f6ad14a7ef42e2399f36cf2f9bd44752b3dc4eab60fdc5/certifi-2026.1.4.tar.gz", hash = "sha256:ac726dd470482006e014ad384921ed6438c457018f4b3d204aea4281258b2120", size = 154268, upload-time = "2026-01-04T02:42:41.825Z"} +source = {registry = "https://pypi.org/simple"} version = "2026.1.4" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e0/2d/a891ca51311197f6ad14a7ef42e2399f36cf2f9bd44752b3dc4eab60fdc5/certifi-2026.1.4.tar.gz", hash = "sha256:ac726dd470482006e014ad384921ed6438c457018f4b3d204aea4281258b2120", size = 154268, upload-time = "2026-01-04T02:42:41.825Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e6/ad/3cc14f097111b4de0040c83a525973216457bbeeb63739ef1ed275c1c021/certifi-2026.1.4-py3-none-any.whl", hash = "sha256:9943707519e4add1115f44c2bc244f782c0249876bf51b6599fee1ffbedd685c", size = 152900, upload-time = "2026-01-04T02:42:40.15Z" }, + {url = "https://files.pythonhosted.org/packages/e6/ad/3cc14f097111b4de0040c83a525973216457bbeeb63739ef1ed275c1c021/certifi-2026.1.4-py3-none-any.whl", hash = "sha256:9943707519e4add1115f44c2bc244f782c0249876bf51b6599fee1ffbedd685c", size = 152900, upload-time = "2026-01-04T02:42:40.15Z"} ] [[package]] +dependencies = [ + {name = "pycparser", marker = "implementation_name != 'PyPy'"} +] name = "cffi" +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"} +source = {registry = "https://pypi.org/simple"} 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/12/4a/3dfd5f7850cbf0d06dc84ba9aa00db766b52ca38d8b86e3a38314d52498c/cffi-2.0.0-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:b4c854ef3adc177950a8dfc81a86f5115d2abd545751a304c5bcf2c2c7283cfe", size = 184344, upload-time = "2025-09-08T23:22:26.456Z" }, - { url = "https://files.pythonhosted.org/packages/4f/8b/f0e4c441227ba756aafbe78f117485b25bb26b1c059d01f137fa6d14896b/cffi-2.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2de9a304e27f7596cd03d16f1b7c72219bd944e99cc52b84d0145aefb07cbd3c", size = 180560, upload-time = "2025-09-08T23:22:28.197Z" }, - { url = "https://files.pythonhosted.org/packages/b1/b7/1200d354378ef52ec227395d95c2576330fd22a869f7a70e88e1447eb234/cffi-2.0.0-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:baf5215e0ab74c16e2dd324e8ec067ef59e41125d3eade2b863d294fd5035c92", size = 209613, upload-time = "2025-09-08T23:22:29.475Z" }, - { url = "https://files.pythonhosted.org/packages/b8/56/6033f5e86e8cc9bb629f0077ba71679508bdf54a9a5e112a3c0b91870332/cffi-2.0.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:730cacb21e1bdff3ce90babf007d0a0917cc3e6492f336c2f0134101e0944f93", size = 216476, upload-time = "2025-09-08T23:22:31.063Z" }, - { url = "https://files.pythonhosted.org/packages/dc/7f/55fecd70f7ece178db2f26128ec41430d8720f2d12ca97bf8f0a628207d5/cffi-2.0.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:6824f87845e3396029f3820c206e459ccc91760e8fa24422f8b0c3d1731cbec5", size = 203374, upload-time = "2025-09-08T23:22:32.507Z" }, - { url = "https://files.pythonhosted.org/packages/84/ef/a7b77c8bdc0f77adc3b46888f1ad54be8f3b7821697a7b89126e829e676a/cffi-2.0.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:9de40a7b0323d889cf8d23d1ef214f565ab154443c42737dfe52ff82cf857664", size = 202597, upload-time = "2025-09-08T23:22:34.132Z" }, - { url = "https://files.pythonhosted.org/packages/d7/91/500d892b2bf36529a75b77958edfcd5ad8e2ce4064ce2ecfeab2125d72d1/cffi-2.0.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8941aaadaf67246224cee8c3803777eed332a19d909b47e29c9842ef1e79ac26", size = 215574, upload-time = "2025-09-08T23:22:35.443Z" }, - { url = "https://files.pythonhosted.org/packages/44/64/58f6255b62b101093d5df22dcb752596066c7e89dd725e0afaed242a61be/cffi-2.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a05d0c237b3349096d3981b727493e22147f934b20f6f125a3eba8f994bec4a9", size = 218971, upload-time = "2025-09-08T23:22:36.805Z" }, - { url = "https://files.pythonhosted.org/packages/ab/49/fa72cebe2fd8a55fbe14956f9970fe8eb1ac59e5df042f603ef7c8ba0adc/cffi-2.0.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:94698a9c5f91f9d138526b48fe26a199609544591f859c870d477351dc7b2414", size = 211972, upload-time = "2025-09-08T23:22:38.436Z" }, - { url = "https://files.pythonhosted.org/packages/0b/28/dd0967a76aab36731b6ebfe64dec4e981aff7e0608f60c2d46b46982607d/cffi-2.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:5fed36fccc0612a53f1d4d9a816b50a36702c28a2aa880cb8a122b3466638743", size = 217078, upload-time = "2025-09-08T23:22:39.776Z" }, - { url = "https://files.pythonhosted.org/packages/2b/c0/015b25184413d7ab0a410775fdb4a50fca20f5589b5dab1dbbfa3baad8ce/cffi-2.0.0-cp311-cp311-win32.whl", hash = "sha256:c649e3a33450ec82378822b3dad03cc228b8f5963c0c12fc3b1e0ab940f768a5", size = 172076, upload-time = "2025-09-08T23:22:40.95Z" }, - { url = "https://files.pythonhosted.org/packages/ae/8f/dc5531155e7070361eb1b7e4c1a9d896d0cb21c49f807a6c03fd63fc877e/cffi-2.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:66f011380d0e49ed280c789fbd08ff0d40968ee7b665575489afa95c98196ab5", size = 182820, upload-time = "2025-09-08T23:22:42.463Z" }, - { url = "https://files.pythonhosted.org/packages/95/5c/1b493356429f9aecfd56bc171285a4c4ac8697f76e9bbbbb105e537853a1/cffi-2.0.0-cp311-cp311-win_arm64.whl", hash = "sha256:c6638687455baf640e37344fe26d37c404db8b80d037c3d29f58fe8d1c3b194d", size = 177635, upload-time = "2025-09-08T23:22:43.623Z" }, - { url = "https://files.pythonhosted.org/packages/ea/47/4f61023ea636104d4f16ab488e268b93008c3d0bb76893b1b31db1f96802/cffi-2.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6d02d6655b0e54f54c4ef0b94eb6be0607b70853c45ce98bd278dc7de718be5d", size = 185271, upload-time = "2025-09-08T23:22:44.795Z" }, - { url = "https://files.pythonhosted.org/packages/df/a2/781b623f57358e360d62cdd7a8c681f074a71d445418a776eef0aadb4ab4/cffi-2.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8eca2a813c1cb7ad4fb74d368c2ffbbb4789d377ee5bb8df98373c2cc0dee76c", size = 181048, upload-time = "2025-09-08T23:22:45.938Z" }, - { url = "https://files.pythonhosted.org/packages/ff/df/a4f0fbd47331ceeba3d37c2e51e9dfc9722498becbeec2bd8bc856c9538a/cffi-2.0.0-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:21d1152871b019407d8ac3985f6775c079416c282e431a4da6afe7aefd2bccbe", size = 212529, upload-time = "2025-09-08T23:22:47.349Z" }, - { url = "https://files.pythonhosted.org/packages/d5/72/12b5f8d3865bf0f87cf1404d8c374e7487dcf097a1c91c436e72e6badd83/cffi-2.0.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b21e08af67b8a103c71a250401c78d5e0893beff75e28c53c98f4de42f774062", size = 220097, upload-time = "2025-09-08T23:22:48.677Z" }, - { url = "https://files.pythonhosted.org/packages/c2/95/7a135d52a50dfa7c882ab0ac17e8dc11cec9d55d2c18dda414c051c5e69e/cffi-2.0.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:1e3a615586f05fc4065a8b22b8152f0c1b00cdbc60596d187c2a74f9e3036e4e", size = 207983, upload-time = "2025-09-08T23:22:50.06Z" }, - { url = "https://files.pythonhosted.org/packages/3a/c8/15cb9ada8895957ea171c62dc78ff3e99159ee7adb13c0123c001a2546c1/cffi-2.0.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:81afed14892743bbe14dacb9e36d9e0e504cd204e0b165062c488942b9718037", size = 206519, upload-time = "2025-09-08T23:22:51.364Z" }, - { url = "https://files.pythonhosted.org/packages/78/2d/7fa73dfa841b5ac06c7b8855cfc18622132e365f5b81d02230333ff26e9e/cffi-2.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3e17ed538242334bf70832644a32a7aae3d83b57567f9fd60a26257e992b79ba", size = 219572, upload-time = "2025-09-08T23:22:52.902Z" }, - { url = "https://files.pythonhosted.org/packages/07/e0/267e57e387b4ca276b90f0434ff88b2c2241ad72b16d31836adddfd6031b/cffi-2.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3925dd22fa2b7699ed2617149842d2e6adde22b262fcbfada50e3d195e4b3a94", size = 222963, upload-time = "2025-09-08T23:22:54.518Z" }, - { url = "https://files.pythonhosted.org/packages/b6/75/1f2747525e06f53efbd878f4d03bac5b859cbc11c633d0fb81432d98a795/cffi-2.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2c8f814d84194c9ea681642fd164267891702542f028a15fc97d4674b6206187", size = 221361, upload-time = "2025-09-08T23:22:55.867Z" }, - { url = "https://files.pythonhosted.org/packages/7b/2b/2b6435f76bfeb6bbf055596976da087377ede68df465419d192acf00c437/cffi-2.0.0-cp312-cp312-win32.whl", hash = "sha256:da902562c3e9c550df360bfa53c035b2f241fed6d9aef119048073680ace4a18", size = 172932, upload-time = "2025-09-08T23:22:57.188Z" }, - { url = "https://files.pythonhosted.org/packages/f8/ed/13bd4418627013bec4ed6e54283b1959cf6db888048c7cf4b4c3b5b36002/cffi-2.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:da68248800ad6320861f129cd9c1bf96ca849a2771a59e0344e88681905916f5", size = 183557, upload-time = "2025-09-08T23:22:58.351Z" }, - { url = "https://files.pythonhosted.org/packages/95/31/9f7f93ad2f8eff1dbc1c3656d7ca5bfd8fb52c9d786b4dcf19b2d02217fa/cffi-2.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:4671d9dd5ec934cb9a73e7ee9676f9362aba54f7f34910956b84d727b0d73fb6", size = 177762, upload-time = "2025-09-08T23:22:59.668Z" }, - { 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" }, +wheels = [ + {url = "https://files.pythonhosted.org/packages/12/4a/3dfd5f7850cbf0d06dc84ba9aa00db766b52ca38d8b86e3a38314d52498c/cffi-2.0.0-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:b4c854ef3adc177950a8dfc81a86f5115d2abd545751a304c5bcf2c2c7283cfe", size = 184344, upload-time = "2025-09-08T23:22:26.456Z"}, + {url = "https://files.pythonhosted.org/packages/4f/8b/f0e4c441227ba756aafbe78f117485b25bb26b1c059d01f137fa6d14896b/cffi-2.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2de9a304e27f7596cd03d16f1b7c72219bd944e99cc52b84d0145aefb07cbd3c", size = 180560, upload-time = "2025-09-08T23:22:28.197Z"}, + {url = "https://files.pythonhosted.org/packages/b1/b7/1200d354378ef52ec227395d95c2576330fd22a869f7a70e88e1447eb234/cffi-2.0.0-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:baf5215e0ab74c16e2dd324e8ec067ef59e41125d3eade2b863d294fd5035c92", size = 209613, upload-time = "2025-09-08T23:22:29.475Z"}, + {url = "https://files.pythonhosted.org/packages/b8/56/6033f5e86e8cc9bb629f0077ba71679508bdf54a9a5e112a3c0b91870332/cffi-2.0.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:730cacb21e1bdff3ce90babf007d0a0917cc3e6492f336c2f0134101e0944f93", size = 216476, upload-time = "2025-09-08T23:22:31.063Z"}, + {url = "https://files.pythonhosted.org/packages/dc/7f/55fecd70f7ece178db2f26128ec41430d8720f2d12ca97bf8f0a628207d5/cffi-2.0.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:6824f87845e3396029f3820c206e459ccc91760e8fa24422f8b0c3d1731cbec5", size = 203374, upload-time = "2025-09-08T23:22:32.507Z"}, + {url = "https://files.pythonhosted.org/packages/84/ef/a7b77c8bdc0f77adc3b46888f1ad54be8f3b7821697a7b89126e829e676a/cffi-2.0.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:9de40a7b0323d889cf8d23d1ef214f565ab154443c42737dfe52ff82cf857664", size = 202597, upload-time = "2025-09-08T23:22:34.132Z"}, + {url = "https://files.pythonhosted.org/packages/d7/91/500d892b2bf36529a75b77958edfcd5ad8e2ce4064ce2ecfeab2125d72d1/cffi-2.0.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8941aaadaf67246224cee8c3803777eed332a19d909b47e29c9842ef1e79ac26", size = 215574, upload-time = "2025-09-08T23:22:35.443Z"}, + {url = "https://files.pythonhosted.org/packages/44/64/58f6255b62b101093d5df22dcb752596066c7e89dd725e0afaed242a61be/cffi-2.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a05d0c237b3349096d3981b727493e22147f934b20f6f125a3eba8f994bec4a9", size = 218971, upload-time = "2025-09-08T23:22:36.805Z"}, + {url = "https://files.pythonhosted.org/packages/ab/49/fa72cebe2fd8a55fbe14956f9970fe8eb1ac59e5df042f603ef7c8ba0adc/cffi-2.0.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:94698a9c5f91f9d138526b48fe26a199609544591f859c870d477351dc7b2414", size = 211972, upload-time = "2025-09-08T23:22:38.436Z"}, + {url = "https://files.pythonhosted.org/packages/0b/28/dd0967a76aab36731b6ebfe64dec4e981aff7e0608f60c2d46b46982607d/cffi-2.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:5fed36fccc0612a53f1d4d9a816b50a36702c28a2aa880cb8a122b3466638743", size = 217078, upload-time = "2025-09-08T23:22:39.776Z"}, + {url = "https://files.pythonhosted.org/packages/2b/c0/015b25184413d7ab0a410775fdb4a50fca20f5589b5dab1dbbfa3baad8ce/cffi-2.0.0-cp311-cp311-win32.whl", hash = "sha256:c649e3a33450ec82378822b3dad03cc228b8f5963c0c12fc3b1e0ab940f768a5", size = 172076, upload-time = "2025-09-08T23:22:40.95Z"}, + {url = "https://files.pythonhosted.org/packages/ae/8f/dc5531155e7070361eb1b7e4c1a9d896d0cb21c49f807a6c03fd63fc877e/cffi-2.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:66f011380d0e49ed280c789fbd08ff0d40968ee7b665575489afa95c98196ab5", size = 182820, upload-time = "2025-09-08T23:22:42.463Z"}, + {url = "https://files.pythonhosted.org/packages/95/5c/1b493356429f9aecfd56bc171285a4c4ac8697f76e9bbbbb105e537853a1/cffi-2.0.0-cp311-cp311-win_arm64.whl", hash = "sha256:c6638687455baf640e37344fe26d37c404db8b80d037c3d29f58fe8d1c3b194d", size = 177635, upload-time = "2025-09-08T23:22:43.623Z"}, + {url = "https://files.pythonhosted.org/packages/ea/47/4f61023ea636104d4f16ab488e268b93008c3d0bb76893b1b31db1f96802/cffi-2.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6d02d6655b0e54f54c4ef0b94eb6be0607b70853c45ce98bd278dc7de718be5d", size = 185271, upload-time = "2025-09-08T23:22:44.795Z"}, + {url = "https://files.pythonhosted.org/packages/df/a2/781b623f57358e360d62cdd7a8c681f074a71d445418a776eef0aadb4ab4/cffi-2.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8eca2a813c1cb7ad4fb74d368c2ffbbb4789d377ee5bb8df98373c2cc0dee76c", size = 181048, upload-time = "2025-09-08T23:22:45.938Z"}, + {url = "https://files.pythonhosted.org/packages/ff/df/a4f0fbd47331ceeba3d37c2e51e9dfc9722498becbeec2bd8bc856c9538a/cffi-2.0.0-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:21d1152871b019407d8ac3985f6775c079416c282e431a4da6afe7aefd2bccbe", size = 212529, upload-time = "2025-09-08T23:22:47.349Z"}, + {url = "https://files.pythonhosted.org/packages/d5/72/12b5f8d3865bf0f87cf1404d8c374e7487dcf097a1c91c436e72e6badd83/cffi-2.0.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b21e08af67b8a103c71a250401c78d5e0893beff75e28c53c98f4de42f774062", size = 220097, upload-time = "2025-09-08T23:22:48.677Z"}, + {url = "https://files.pythonhosted.org/packages/c2/95/7a135d52a50dfa7c882ab0ac17e8dc11cec9d55d2c18dda414c051c5e69e/cffi-2.0.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:1e3a615586f05fc4065a8b22b8152f0c1b00cdbc60596d187c2a74f9e3036e4e", size = 207983, upload-time = "2025-09-08T23:22:50.06Z"}, + {url = "https://files.pythonhosted.org/packages/3a/c8/15cb9ada8895957ea171c62dc78ff3e99159ee7adb13c0123c001a2546c1/cffi-2.0.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:81afed14892743bbe14dacb9e36d9e0e504cd204e0b165062c488942b9718037", size = 206519, upload-time = "2025-09-08T23:22:51.364Z"}, + {url = "https://files.pythonhosted.org/packages/78/2d/7fa73dfa841b5ac06c7b8855cfc18622132e365f5b81d02230333ff26e9e/cffi-2.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3e17ed538242334bf70832644a32a7aae3d83b57567f9fd60a26257e992b79ba", size = 219572, upload-time = "2025-09-08T23:22:52.902Z"}, + {url = "https://files.pythonhosted.org/packages/07/e0/267e57e387b4ca276b90f0434ff88b2c2241ad72b16d31836adddfd6031b/cffi-2.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3925dd22fa2b7699ed2617149842d2e6adde22b262fcbfada50e3d195e4b3a94", size = 222963, upload-time = "2025-09-08T23:22:54.518Z"}, + {url = "https://files.pythonhosted.org/packages/b6/75/1f2747525e06f53efbd878f4d03bac5b859cbc11c633d0fb81432d98a795/cffi-2.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2c8f814d84194c9ea681642fd164267891702542f028a15fc97d4674b6206187", size = 221361, upload-time = "2025-09-08T23:22:55.867Z"}, + {url = "https://files.pythonhosted.org/packages/7b/2b/2b6435f76bfeb6bbf055596976da087377ede68df465419d192acf00c437/cffi-2.0.0-cp312-cp312-win32.whl", hash = "sha256:da902562c3e9c550df360bfa53c035b2f241fed6d9aef119048073680ace4a18", size = 172932, upload-time = "2025-09-08T23:22:57.188Z"}, + {url = "https://files.pythonhosted.org/packages/f8/ed/13bd4418627013bec4ed6e54283b1959cf6db888048c7cf4b4c3b5b36002/cffi-2.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:da68248800ad6320861f129cd9c1bf96ca849a2771a59e0344e88681905916f5", size = 183557, upload-time = "2025-09-08T23:22:58.351Z"}, + {url = "https://files.pythonhosted.org/packages/95/31/9f7f93ad2f8eff1dbc1c3656d7ca5bfd8fb52c9d786b4dcf19b2d02217fa/cffi-2.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:4671d9dd5ec934cb9a73e7ee9676f9362aba54f7f34910956b84d727b0d73fb6", size = 177762, upload-time = "2025-09-08T23:22:59.668Z"}, + {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 = "cfgrib" -version = "0.9.15.1" -source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "attrs" }, - { name = "click" }, - { name = "eccodes" }, - { name = "numpy" }, + {name = "attrs"}, + {name = "click"}, + {name = "eccodes"}, + {name = "numpy"} ] -sdist = { url = "https://files.pythonhosted.org/packages/4a/51/cace2747a517667bbbe5fcab1f35958ad05c778251a452c461b8b3649dbe/cfgrib-0.9.15.1.tar.gz", hash = "sha256:d959d8b97e55a63646fa86686b297905ff7f2918a91e3a11d6292dab09598e4d", size = 9746591, upload-time = "2025-09-30T22:46:14.133Z" } +name = "cfgrib" +sdist = {url = "https://files.pythonhosted.org/packages/4a/51/cace2747a517667bbbe5fcab1f35958ad05c778251a452c461b8b3649dbe/cfgrib-0.9.15.1.tar.gz", hash = "sha256:d959d8b97e55a63646fa86686b297905ff7f2918a91e3a11d6292dab09598e4d", size = 9746591, upload-time = "2025-09-30T22:46:14.133Z"} +source = {registry = "https://pypi.org/simple"} +version = "0.9.15.1" wheels = [ - { url = "https://files.pythonhosted.org/packages/6d/e8/16c58c57c9ce1474dd1e50090ebd78b008c70fc4f06793da65f9a0aba391/cfgrib-0.9.15.1-py3-none-any.whl", hash = "sha256:f1bee90e86917389be9f767051bf32d00f95f6f4e4312b344567511b3cfd62d2", size = 49123, upload-time = "2025-09-30T22:46:12.206Z" }, + {url = "https://files.pythonhosted.org/packages/6d/e8/16c58c57c9ce1474dd1e50090ebd78b008c70fc4f06793da65f9a0aba391/cfgrib-0.9.15.1-py3-none-any.whl", hash = "sha256:f1bee90e86917389be9f767051bf32d00f95f6f4e4312b344567511b3cfd62d2", size = 49123, upload-time = "2025-09-30T22:46:12.206Z"} ] [[package]] +dependencies = [ + {name = "numpy"} +] name = "cftime" +sdist = {url = "https://files.pythonhosted.org/packages/65/dc/470ffebac2eb8c54151eb893055024fe81b1606e7c6ff8449a588e9cd17f/cftime-1.6.5.tar.gz", hash = "sha256:8225fed6b9b43fb87683ebab52130450fc1730011150d3092096a90e54d1e81e", size = 326605, upload-time = "2025-10-13T18:56:26.352Z"} +source = {registry = "https://pypi.org/simple"} version = "1.6.5" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "numpy" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/65/dc/470ffebac2eb8c54151eb893055024fe81b1606e7c6ff8449a588e9cd17f/cftime-1.6.5.tar.gz", hash = "sha256:8225fed6b9b43fb87683ebab52130450fc1730011150d3092096a90e54d1e81e", size = 326605, upload-time = "2025-10-13T18:56:26.352Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e4/f6/9da7aba9548ede62d25936b8b448acd7e53e5dcc710896f66863dcc9a318/cftime-1.6.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:474e728f5a387299418f8d7cb9c52248dcd5d977b2a01de7ec06bba572e26b02", size = 512733, upload-time = "2025-10-13T18:56:00.189Z" }, - { url = "https://files.pythonhosted.org/packages/1f/d5/d86ad95fc1fd89947c34b495ff6487b6d361cf77500217423b4ebcb1f0c2/cftime-1.6.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ab9e80d4de815cac2e2d88a2335231254980e545d0196eb34ee8f7ed612645f1", size = 492946, upload-time = "2025-10-13T18:56:01.262Z" }, - { url = "https://files.pythonhosted.org/packages/4f/93/d7e8dd76b03a9d5be41a3b3185feffc7ea5359228bdffe7aa43ac772a75b/cftime-1.6.5-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ad24a563784e4795cb3d04bd985895b5db49ace2cbb71fcf1321fd80141f9a52", size = 1689856, upload-time = "2025-10-13T19:39:12.873Z" }, - { url = "https://files.pythonhosted.org/packages/3e/8d/86586c0d75110f774e46e2bd6d134e2d1cca1dedc9bb08c388fa3df76acd/cftime-1.6.5-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a3cda6fd12c7fb25eff40a6a857a2bf4d03e8cc71f80485d8ddc65ccbd80f16a", size = 1718573, upload-time = "2025-10-13T18:56:02.788Z" }, - { url = "https://files.pythonhosted.org/packages/bb/fe/7956914cfc135992e89098ebbc67d683c51ace5366ba4b114fef1de89b21/cftime-1.6.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:28cda78d685397ba23d06273b9c916c3938d8d9e6872a537e76b8408a321369b", size = 1788563, upload-time = "2025-10-13T18:56:04.075Z" }, - { url = "https://files.pythonhosted.org/packages/e5/c7/6669708fcfe1bb7b2a7ce693b8cc67165eac00d3ac5a5e8f6ce1be551ff9/cftime-1.6.5-cp311-cp311-win_amd64.whl", hash = "sha256:93ead088e3a216bdeb9368733a0ef89a7451dfc1d2de310c1c0366a56ad60dc8", size = 473631, upload-time = "2025-10-13T18:56:05.159Z" }, - { url = "https://files.pythonhosted.org/packages/82/c5/d70cb1ab533ca790d7c9b69f98215fa4fead17f05547e928c8f2b8f96e54/cftime-1.6.5-cp311-cp311-win_arm64.whl", hash = "sha256:3384d69a0a7f3d45bded21a8cbcce66c8ba06c13498eac26c2de41b1b9b6e890", size = 459383, upload-time = "2026-01-02T21:16:47.317Z" }, - { url = "https://files.pythonhosted.org/packages/b6/c1/e8cb7f78a3f87295450e7300ebaecf83076d96a99a76190593d4e1d2be40/cftime-1.6.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:eef25caed5ebd003a38719bd3ff8847cd52ef2ea56c3ebdb2c9345ba131fc7c5", size = 504175, upload-time = "2025-10-13T18:56:06.398Z" }, - { url = "https://files.pythonhosted.org/packages/50/1a/86e1072b09b2f9049bb7378869f64b6747f96a4f3008142afed8955b52a4/cftime-1.6.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c87d2f3b949e45463e559233c69e6a9cf691b2b378c1f7556166adfabbd1c6b0", size = 485980, upload-time = "2025-10-13T18:56:08.669Z" }, - { url = "https://files.pythonhosted.org/packages/35/28/d3177b60da3f308b60dee2aef2eb69997acfab1e863f0bf0d2a418396ce5/cftime-1.6.5-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:82cb413973cc51b55642b3a1ca5b28db5b93a294edbef7dc049c074b478b4647", size = 1591166, upload-time = "2025-10-13T19:39:14.109Z" }, - { url = "https://files.pythonhosted.org/packages/d1/fd/a7266970312df65e68b5641b86e0540a739182f5e9c62eec6dbd29f18055/cftime-1.6.5-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:85ba8e7356d239cfe56ef7707ac30feaf67964642ac760a82e507ee3c5db4ac4", size = 1642614, upload-time = "2025-10-13T18:56:09.815Z" }, - { url = "https://files.pythonhosted.org/packages/c4/73/f0035a4bc2df8885bb7bd5fe63659686ea1ec7d0cc74b4e3d50e447402e5/cftime-1.6.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:456039af7907a3146689bb80bfd8edabd074c7f3b4eca61f91b9c2670addd7ad", size = 1688090, upload-time = "2025-10-13T18:56:11.442Z" }, - { url = "https://files.pythonhosted.org/packages/88/15/8856a0ab76708553ff597dd2e617b088c734ba87dc3fd395e2b2f3efffe8/cftime-1.6.5-cp312-cp312-win_amd64.whl", hash = "sha256:da84534c43699960dc980a9a765c33433c5de1a719a4916748c2d0e97a071e44", size = 464840, upload-time = "2025-10-13T18:56:12.506Z" }, - { url = "https://files.pythonhosted.org/packages/3a/85/451009a986d9273d2208fc0898aa00262275b5773259bf3f942f6716a9e7/cftime-1.6.5-cp312-cp312-win_arm64.whl", hash = "sha256:c62cd8db9ea40131eea7d4523691c5d806d3265d31279e4a58574a42c28acd77", size = 450534, upload-time = "2026-01-02T21:16:48.784Z" }, - { url = "https://files.pythonhosted.org/packages/2e/60/74ea344b3b003fada346ed98a6899085d6fd4c777df608992d90c458fda6/cftime-1.6.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4aba66fd6497711a47c656f3a732c2d1755ad15f80e323c44a8716ebde39ddd5", size = 502453, upload-time = "2025-10-13T18:56:13.545Z" }, - { url = "https://files.pythonhosted.org/packages/1e/14/adb293ac6127079b49ff11c05cf3d5ce5c1f17d097f326dc02d74ddfcb6e/cftime-1.6.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:89e7cba699242366e67d6fb5aee579440e791063f92a93853610c91647167c0d", size = 484541, upload-time = "2025-10-13T18:56:14.612Z" }, - { url = "https://files.pythonhosted.org/packages/4f/74/bb8a4566af8d0ef3f045d56c462a9115da4f04b07c7fbbf2b4875223eebd/cftime-1.6.5-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:2f1eb43d7a7b919ec99aee709fb62ef87ef1cf0679829ef93d37cc1c725781e9", size = 1591014, upload-time = "2025-10-13T19:39:15.346Z" }, - { url = "https://files.pythonhosted.org/packages/ba/08/52f06ff2f04d376f9cd2c211aefcf2b37f1978e43289341f362fc99f6a0e/cftime-1.6.5-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:e02a1d80ffc33fe469c7db68aa24c4a87f01da0c0c621373e5edadc92964900b", size = 1633625, upload-time = "2025-10-13T18:56:15.745Z" }, - { url = "https://files.pythonhosted.org/packages/cf/33/03e0b23d58ea8fab94ecb4f7c5b721e844a0800c13694876149d98830a73/cftime-1.6.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:18ab754805233cdd889614b2b3b86a642f6d51a57a1ec327c48053f3414f87d8", size = 1684269, upload-time = "2025-10-13T18:56:17.04Z" }, - { url = "https://files.pythonhosted.org/packages/a4/60/a0cfba63847b43599ef1cdbbf682e61894994c22b9a79fd9e1e8c7e9de41/cftime-1.6.5-cp313-cp313-win_amd64.whl", hash = "sha256:6c27add8f907f4a4cd400e89438f2ea33e2eb5072541a157a4d013b7dbe93f9c", size = 465364, upload-time = "2025-10-13T18:56:18.05Z" }, - { url = "https://files.pythonhosted.org/packages/3d/e8/ec32f2aef22c15604e6fda39ff8d581a00b5469349f8fba61640d5358d2c/cftime-1.6.5-cp313-cp313-win_arm64.whl", hash = "sha256:31d1ff8f6bbd4ca209099d24459ec16dea4fb4c9ab740fbb66dd057ccbd9b1b9", size = 450468, upload-time = "2026-01-02T21:16:50.193Z" }, - { url = "https://files.pythonhosted.org/packages/ea/6c/a9618f589688358e279720f5c0fe67ef0077fba07334ce26895403ebc260/cftime-1.6.5-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:c69ce3bdae6a322cbb44e9ebc20770d47748002fb9d68846a1e934f1bd5daf0b", size = 502725, upload-time = "2025-10-13T18:56:19.424Z" }, - { url = "https://files.pythonhosted.org/packages/d8/e3/da3c36398bfb730b96248d006cabaceed87e401ff56edafb2a978293e228/cftime-1.6.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:e62e9f2943e014c5ef583245bf2e878398af131c97e64f8cd47c1d7baef5c4e2", size = 485445, upload-time = "2025-10-13T18:56:20.853Z" }, - { url = "https://files.pythonhosted.org/packages/32/93/b05939e5abd14bd1ab69538bbe374b4ee2a15467b189ff895e9a8cdaddf6/cftime-1.6.5-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7da5fdaa4360d8cb89b71b8ded9314f2246aa34581e8105c94ad58d6102d9e4f", size = 1584434, upload-time = "2025-10-13T19:39:17.084Z" }, - { url = "https://files.pythonhosted.org/packages/7f/89/648397f9936e0b330999c4e776ebf296ec3c6a65f9901687dbca4ab820da/cftime-1.6.5-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:bff865b4ea4304f2744a1ad2b8149b8328b321dd7a2b9746ef926d229bd7cd49", size = 1609812, upload-time = "2025-10-13T18:56:21.971Z" }, - { url = "https://files.pythonhosted.org/packages/e7/0f/901b4835aa67ad3e915605d4e01d0af80a44b114eefab74ae33de6d36933/cftime-1.6.5-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:e552c5d1c8a58f25af7521e49237db7ca52ed2953e974fe9f7c4491e95fdd36c", size = 1669768, upload-time = "2025-10-13T18:56:24.027Z" }, - { url = "https://files.pythonhosted.org/packages/22/d5/e605e4b28363e7a9ae98ed12cabbda5b155b6009270e6a231d8f10182a17/cftime-1.6.5-cp314-cp314-win_amd64.whl", hash = "sha256:e645b095dc50a38ac454b7e7f0742f639e7d7f6b108ad329358544a6ff8c9ba2", size = 463818, upload-time = "2025-10-13T18:56:25.376Z" }, - { url = "https://files.pythonhosted.org/packages/3d/89/a8f85ae697ff10206ec401c2621f5ca9f327554f586d62f244739ceeb347/cftime-1.6.5-cp314-cp314-win_arm64.whl", hash = "sha256:b9044d7ac82d3d8af189df1032fdc871bbd3f3dd41a6ec79edceb5029b71e6e0", size = 459862, upload-time = "2026-01-02T20:45:02.625Z" }, - { url = "https://files.pythonhosted.org/packages/ab/05/7410e12fd03a0c52717e74e6a1b49958810807dda212e23b65d43ea99676/cftime-1.6.5-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:9ef56460cb0576e1a9161e1428c9e1a633f809a23fa9d598f313748c1ae5064e", size = 533781, upload-time = "2026-01-02T20:45:04.818Z" }, - { url = "https://files.pythonhosted.org/packages/44/ba/10e3546426d3ed9f9cc82e4a99836bb6fac1642c7830f7bdd0ac1c3f0805/cftime-1.6.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:4f4873d38b10032f9f3111c547a1d485519ae64eee6a7a2d091f1f8b08e1ba50", size = 515218, upload-time = "2026-01-02T20:45:06.788Z" }, - { url = "https://files.pythonhosted.org/packages/bd/68/efa11eae867749e921bfec6a865afdba8166e96188112dde70bb8bb49254/cftime-1.6.5-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ccce0f4c9d3f38dd948a117e578b50d0e0db11e2ca9435fb358fd524813e4b61", size = 1579932, upload-time = "2026-01-02T20:45:11.194Z" }, - { url = "https://files.pythonhosted.org/packages/9d/6c/0971e602c1390a423e6621dfbad9f1d375186bdaf9c9c7f75e06f1fbf355/cftime-1.6.5-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:19cbfc5152fb0b34ce03acf9668229af388d7baa63a78f936239cb011ccbe6b1", size = 1555894, upload-time = "2026-01-02T20:45:16.351Z" }, - { url = "https://files.pythonhosted.org/packages/ad/fc/8475a15b7c3209a4a68b563dfc5e01ce74f2d8b9822372c3d30c68ab7f39/cftime-1.6.5-cp314-cp314t-win_amd64.whl", hash = "sha256:4470cd5ef3c2514566f53efbcbb64dd924fa0584637d90285b2f983bd4ee7d97", size = 513027, upload-time = "2026-01-02T20:45:20.023Z" }, - { url = "https://files.pythonhosted.org/packages/f7/80/4ecbda8318fbf40ad4e005a4a93aebba69e81382e5b4c6086251cd5d0ee8/cftime-1.6.5-cp314-cp314t-win_arm64.whl", hash = "sha256:034c15a67144a0a5590ef150c99f844897618b148b87131ed34fda7072614662", size = 469065, upload-time = "2026-01-02T20:45:23.398Z" }, +wheels = [ + {url = "https://files.pythonhosted.org/packages/e4/f6/9da7aba9548ede62d25936b8b448acd7e53e5dcc710896f66863dcc9a318/cftime-1.6.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:474e728f5a387299418f8d7cb9c52248dcd5d977b2a01de7ec06bba572e26b02", size = 512733, upload-time = "2025-10-13T18:56:00.189Z"}, + {url = "https://files.pythonhosted.org/packages/1f/d5/d86ad95fc1fd89947c34b495ff6487b6d361cf77500217423b4ebcb1f0c2/cftime-1.6.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ab9e80d4de815cac2e2d88a2335231254980e545d0196eb34ee8f7ed612645f1", size = 492946, upload-time = "2025-10-13T18:56:01.262Z"}, + {url = "https://files.pythonhosted.org/packages/4f/93/d7e8dd76b03a9d5be41a3b3185feffc7ea5359228bdffe7aa43ac772a75b/cftime-1.6.5-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ad24a563784e4795cb3d04bd985895b5db49ace2cbb71fcf1321fd80141f9a52", size = 1689856, upload-time = "2025-10-13T19:39:12.873Z"}, + {url = "https://files.pythonhosted.org/packages/3e/8d/86586c0d75110f774e46e2bd6d134e2d1cca1dedc9bb08c388fa3df76acd/cftime-1.6.5-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a3cda6fd12c7fb25eff40a6a857a2bf4d03e8cc71f80485d8ddc65ccbd80f16a", size = 1718573, upload-time = "2025-10-13T18:56:02.788Z"}, + {url = "https://files.pythonhosted.org/packages/bb/fe/7956914cfc135992e89098ebbc67d683c51ace5366ba4b114fef1de89b21/cftime-1.6.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:28cda78d685397ba23d06273b9c916c3938d8d9e6872a537e76b8408a321369b", size = 1788563, upload-time = "2025-10-13T18:56:04.075Z"}, + {url = "https://files.pythonhosted.org/packages/e5/c7/6669708fcfe1bb7b2a7ce693b8cc67165eac00d3ac5a5e8f6ce1be551ff9/cftime-1.6.5-cp311-cp311-win_amd64.whl", hash = "sha256:93ead088e3a216bdeb9368733a0ef89a7451dfc1d2de310c1c0366a56ad60dc8", size = 473631, upload-time = "2025-10-13T18:56:05.159Z"}, + {url = "https://files.pythonhosted.org/packages/82/c5/d70cb1ab533ca790d7c9b69f98215fa4fead17f05547e928c8f2b8f96e54/cftime-1.6.5-cp311-cp311-win_arm64.whl", hash = "sha256:3384d69a0a7f3d45bded21a8cbcce66c8ba06c13498eac26c2de41b1b9b6e890", size = 459383, upload-time = "2026-01-02T21:16:47.317Z"}, + {url = "https://files.pythonhosted.org/packages/b6/c1/e8cb7f78a3f87295450e7300ebaecf83076d96a99a76190593d4e1d2be40/cftime-1.6.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:eef25caed5ebd003a38719bd3ff8847cd52ef2ea56c3ebdb2c9345ba131fc7c5", size = 504175, upload-time = "2025-10-13T18:56:06.398Z"}, + {url = "https://files.pythonhosted.org/packages/50/1a/86e1072b09b2f9049bb7378869f64b6747f96a4f3008142afed8955b52a4/cftime-1.6.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c87d2f3b949e45463e559233c69e6a9cf691b2b378c1f7556166adfabbd1c6b0", size = 485980, upload-time = "2025-10-13T18:56:08.669Z"}, + {url = "https://files.pythonhosted.org/packages/35/28/d3177b60da3f308b60dee2aef2eb69997acfab1e863f0bf0d2a418396ce5/cftime-1.6.5-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:82cb413973cc51b55642b3a1ca5b28db5b93a294edbef7dc049c074b478b4647", size = 1591166, upload-time = "2025-10-13T19:39:14.109Z"}, + {url = "https://files.pythonhosted.org/packages/d1/fd/a7266970312df65e68b5641b86e0540a739182f5e9c62eec6dbd29f18055/cftime-1.6.5-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:85ba8e7356d239cfe56ef7707ac30feaf67964642ac760a82e507ee3c5db4ac4", size = 1642614, upload-time = "2025-10-13T18:56:09.815Z"}, + {url = "https://files.pythonhosted.org/packages/c4/73/f0035a4bc2df8885bb7bd5fe63659686ea1ec7d0cc74b4e3d50e447402e5/cftime-1.6.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:456039af7907a3146689bb80bfd8edabd074c7f3b4eca61f91b9c2670addd7ad", size = 1688090, upload-time = "2025-10-13T18:56:11.442Z"}, + {url = "https://files.pythonhosted.org/packages/88/15/8856a0ab76708553ff597dd2e617b088c734ba87dc3fd395e2b2f3efffe8/cftime-1.6.5-cp312-cp312-win_amd64.whl", hash = "sha256:da84534c43699960dc980a9a765c33433c5de1a719a4916748c2d0e97a071e44", size = 464840, upload-time = "2025-10-13T18:56:12.506Z"}, + {url = "https://files.pythonhosted.org/packages/3a/85/451009a986d9273d2208fc0898aa00262275b5773259bf3f942f6716a9e7/cftime-1.6.5-cp312-cp312-win_arm64.whl", hash = "sha256:c62cd8db9ea40131eea7d4523691c5d806d3265d31279e4a58574a42c28acd77", size = 450534, upload-time = "2026-01-02T21:16:48.784Z"}, + {url = "https://files.pythonhosted.org/packages/2e/60/74ea344b3b003fada346ed98a6899085d6fd4c777df608992d90c458fda6/cftime-1.6.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4aba66fd6497711a47c656f3a732c2d1755ad15f80e323c44a8716ebde39ddd5", size = 502453, upload-time = "2025-10-13T18:56:13.545Z"}, + {url = "https://files.pythonhosted.org/packages/1e/14/adb293ac6127079b49ff11c05cf3d5ce5c1f17d097f326dc02d74ddfcb6e/cftime-1.6.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:89e7cba699242366e67d6fb5aee579440e791063f92a93853610c91647167c0d", size = 484541, upload-time = "2025-10-13T18:56:14.612Z"}, + {url = "https://files.pythonhosted.org/packages/4f/74/bb8a4566af8d0ef3f045d56c462a9115da4f04b07c7fbbf2b4875223eebd/cftime-1.6.5-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:2f1eb43d7a7b919ec99aee709fb62ef87ef1cf0679829ef93d37cc1c725781e9", size = 1591014, upload-time = "2025-10-13T19:39:15.346Z"}, + {url = "https://files.pythonhosted.org/packages/ba/08/52f06ff2f04d376f9cd2c211aefcf2b37f1978e43289341f362fc99f6a0e/cftime-1.6.5-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:e02a1d80ffc33fe469c7db68aa24c4a87f01da0c0c621373e5edadc92964900b", size = 1633625, upload-time = "2025-10-13T18:56:15.745Z"}, + {url = "https://files.pythonhosted.org/packages/cf/33/03e0b23d58ea8fab94ecb4f7c5b721e844a0800c13694876149d98830a73/cftime-1.6.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:18ab754805233cdd889614b2b3b86a642f6d51a57a1ec327c48053f3414f87d8", size = 1684269, upload-time = "2025-10-13T18:56:17.04Z"}, + {url = "https://files.pythonhosted.org/packages/a4/60/a0cfba63847b43599ef1cdbbf682e61894994c22b9a79fd9e1e8c7e9de41/cftime-1.6.5-cp313-cp313-win_amd64.whl", hash = "sha256:6c27add8f907f4a4cd400e89438f2ea33e2eb5072541a157a4d013b7dbe93f9c", size = 465364, upload-time = "2025-10-13T18:56:18.05Z"}, + {url = "https://files.pythonhosted.org/packages/3d/e8/ec32f2aef22c15604e6fda39ff8d581a00b5469349f8fba61640d5358d2c/cftime-1.6.5-cp313-cp313-win_arm64.whl", hash = "sha256:31d1ff8f6bbd4ca209099d24459ec16dea4fb4c9ab740fbb66dd057ccbd9b1b9", size = 450468, upload-time = "2026-01-02T21:16:50.193Z"}, + {url = "https://files.pythonhosted.org/packages/ea/6c/a9618f589688358e279720f5c0fe67ef0077fba07334ce26895403ebc260/cftime-1.6.5-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:c69ce3bdae6a322cbb44e9ebc20770d47748002fb9d68846a1e934f1bd5daf0b", size = 502725, upload-time = "2025-10-13T18:56:19.424Z"}, + {url = "https://files.pythonhosted.org/packages/d8/e3/da3c36398bfb730b96248d006cabaceed87e401ff56edafb2a978293e228/cftime-1.6.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:e62e9f2943e014c5ef583245bf2e878398af131c97e64f8cd47c1d7baef5c4e2", size = 485445, upload-time = "2025-10-13T18:56:20.853Z"}, + {url = "https://files.pythonhosted.org/packages/32/93/b05939e5abd14bd1ab69538bbe374b4ee2a15467b189ff895e9a8cdaddf6/cftime-1.6.5-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7da5fdaa4360d8cb89b71b8ded9314f2246aa34581e8105c94ad58d6102d9e4f", size = 1584434, upload-time = "2025-10-13T19:39:17.084Z"}, + {url = "https://files.pythonhosted.org/packages/7f/89/648397f9936e0b330999c4e776ebf296ec3c6a65f9901687dbca4ab820da/cftime-1.6.5-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:bff865b4ea4304f2744a1ad2b8149b8328b321dd7a2b9746ef926d229bd7cd49", size = 1609812, upload-time = "2025-10-13T18:56:21.971Z"}, + {url = "https://files.pythonhosted.org/packages/e7/0f/901b4835aa67ad3e915605d4e01d0af80a44b114eefab74ae33de6d36933/cftime-1.6.5-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:e552c5d1c8a58f25af7521e49237db7ca52ed2953e974fe9f7c4491e95fdd36c", size = 1669768, upload-time = "2025-10-13T18:56:24.027Z"}, + {url = "https://files.pythonhosted.org/packages/22/d5/e605e4b28363e7a9ae98ed12cabbda5b155b6009270e6a231d8f10182a17/cftime-1.6.5-cp314-cp314-win_amd64.whl", hash = "sha256:e645b095dc50a38ac454b7e7f0742f639e7d7f6b108ad329358544a6ff8c9ba2", size = 463818, upload-time = "2025-10-13T18:56:25.376Z"}, + {url = "https://files.pythonhosted.org/packages/3d/89/a8f85ae697ff10206ec401c2621f5ca9f327554f586d62f244739ceeb347/cftime-1.6.5-cp314-cp314-win_arm64.whl", hash = "sha256:b9044d7ac82d3d8af189df1032fdc871bbd3f3dd41a6ec79edceb5029b71e6e0", size = 459862, upload-time = "2026-01-02T20:45:02.625Z"}, + {url = "https://files.pythonhosted.org/packages/ab/05/7410e12fd03a0c52717e74e6a1b49958810807dda212e23b65d43ea99676/cftime-1.6.5-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:9ef56460cb0576e1a9161e1428c9e1a633f809a23fa9d598f313748c1ae5064e", size = 533781, upload-time = "2026-01-02T20:45:04.818Z"}, + {url = "https://files.pythonhosted.org/packages/44/ba/10e3546426d3ed9f9cc82e4a99836bb6fac1642c7830f7bdd0ac1c3f0805/cftime-1.6.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:4f4873d38b10032f9f3111c547a1d485519ae64eee6a7a2d091f1f8b08e1ba50", size = 515218, upload-time = "2026-01-02T20:45:06.788Z"}, + {url = "https://files.pythonhosted.org/packages/bd/68/efa11eae867749e921bfec6a865afdba8166e96188112dde70bb8bb49254/cftime-1.6.5-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ccce0f4c9d3f38dd948a117e578b50d0e0db11e2ca9435fb358fd524813e4b61", size = 1579932, upload-time = "2026-01-02T20:45:11.194Z"}, + {url = "https://files.pythonhosted.org/packages/9d/6c/0971e602c1390a423e6621dfbad9f1d375186bdaf9c9c7f75e06f1fbf355/cftime-1.6.5-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:19cbfc5152fb0b34ce03acf9668229af388d7baa63a78f936239cb011ccbe6b1", size = 1555894, upload-time = "2026-01-02T20:45:16.351Z"}, + {url = "https://files.pythonhosted.org/packages/ad/fc/8475a15b7c3209a4a68b563dfc5e01ce74f2d8b9822372c3d30c68ab7f39/cftime-1.6.5-cp314-cp314t-win_amd64.whl", hash = "sha256:4470cd5ef3c2514566f53efbcbb64dd924fa0584637d90285b2f983bd4ee7d97", size = 513027, upload-time = "2026-01-02T20:45:20.023Z"}, + {url = "https://files.pythonhosted.org/packages/f7/80/4ecbda8318fbf40ad4e005a4a93aebba69e81382e5b4c6086251cd5d0ee8/cftime-1.6.5-cp314-cp314t-win_arm64.whl", hash = "sha256:034c15a67144a0a5590ef150c99f844897618b148b87131ed34fda7072614662", size = 469065, upload-time = "2026-01-02T20:45:23.398Z"} ] [[package]] name = "charset-normalizer" +sdist = {url = "https://files.pythonhosted.org/packages/13/69/33ddede1939fdd074bce5434295f38fae7136463422fe4fd3e0e89b98062/charset_normalizer-3.4.4.tar.gz", hash = "sha256:94537985111c35f28720e43603b8e7b43a6ecfb2ce1d3058bbe955b73404e21a", size = 129418, upload-time = "2025-10-14T04:42:32.879Z"} +source = {registry = "https://pypi.org/simple"} version = "3.4.4" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/13/69/33ddede1939fdd074bce5434295f38fae7136463422fe4fd3e0e89b98062/charset_normalizer-3.4.4.tar.gz", hash = "sha256:94537985111c35f28720e43603b8e7b43a6ecfb2ce1d3058bbe955b73404e21a", size = 129418, upload-time = "2025-10-14T04:42:32.879Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ed/27/c6491ff4954e58a10f69ad90aca8a1b6fe9c5d3c6f380907af3c37435b59/charset_normalizer-3.4.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6e1fcf0720908f200cd21aa4e6750a48ff6ce4afe7ff5a79a90d5ed8a08296f8", size = 206988, upload-time = "2025-10-14T04:40:33.79Z" }, - { url = "https://files.pythonhosted.org/packages/94/59/2e87300fe67ab820b5428580a53cad894272dbb97f38a7a814a2a1ac1011/charset_normalizer-3.4.4-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5f819d5fe9234f9f82d75bdfa9aef3a3d72c4d24a6e57aeaebba32a704553aa0", size = 147324, upload-time = "2025-10-14T04:40:34.961Z" }, - { url = "https://files.pythonhosted.org/packages/07/fb/0cf61dc84b2b088391830f6274cb57c82e4da8bbc2efeac8c025edb88772/charset_normalizer-3.4.4-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:a59cb51917aa591b1c4e6a43c132f0cdc3c76dbad6155df4e28ee626cc77a0a3", size = 142742, upload-time = "2025-10-14T04:40:36.105Z" }, - { url = "https://files.pythonhosted.org/packages/62/8b/171935adf2312cd745d290ed93cf16cf0dfe320863ab7cbeeae1dcd6535f/charset_normalizer-3.4.4-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8ef3c867360f88ac904fd3f5e1f902f13307af9052646963ee08ff4f131adafc", size = 160863, upload-time = "2025-10-14T04:40:37.188Z" }, - { url = "https://files.pythonhosted.org/packages/09/73/ad875b192bda14f2173bfc1bc9a55e009808484a4b256748d931b6948442/charset_normalizer-3.4.4-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d9e45d7faa48ee908174d8fe84854479ef838fc6a705c9315372eacbc2f02897", size = 157837, upload-time = "2025-10-14T04:40:38.435Z" }, - { url = "https://files.pythonhosted.org/packages/6d/fc/de9cce525b2c5b94b47c70a4b4fb19f871b24995c728e957ee68ab1671ea/charset_normalizer-3.4.4-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:840c25fb618a231545cbab0564a799f101b63b9901f2569faecd6b222ac72381", size = 151550, upload-time = "2025-10-14T04:40:40.053Z" }, - { url = "https://files.pythonhosted.org/packages/55/c2/43edd615fdfba8c6f2dfbd459b25a6b3b551f24ea21981e23fb768503ce1/charset_normalizer-3.4.4-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ca5862d5b3928c4940729dacc329aa9102900382fea192fc5e52eb69d6093815", size = 149162, upload-time = "2025-10-14T04:40:41.163Z" }, - { url = "https://files.pythonhosted.org/packages/03/86/bde4ad8b4d0e9429a4e82c1e8f5c659993a9a863ad62c7df05cf7b678d75/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d9c7f57c3d666a53421049053eaacdd14bbd0a528e2186fcb2e672effd053bb0", size = 150019, upload-time = "2025-10-14T04:40:42.276Z" }, - { url = "https://files.pythonhosted.org/packages/1f/86/a151eb2af293a7e7bac3a739b81072585ce36ccfb4493039f49f1d3cae8c/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:277e970e750505ed74c832b4bf75dac7476262ee2a013f5574dd49075879e161", size = 143310, upload-time = "2025-10-14T04:40:43.439Z" }, - { url = "https://files.pythonhosted.org/packages/b5/fe/43dae6144a7e07b87478fdfc4dbe9efd5defb0e7ec29f5f58a55aeef7bf7/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:31fd66405eaf47bb62e8cd575dc621c56c668f27d46a61d975a249930dd5e2a4", size = 162022, upload-time = "2025-10-14T04:40:44.547Z" }, - { url = "https://files.pythonhosted.org/packages/80/e6/7aab83774f5d2bca81f42ac58d04caf44f0cc2b65fc6db2b3b2e8a05f3b3/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:0d3d8f15c07f86e9ff82319b3d9ef6f4bf907608f53fe9d92b28ea9ae3d1fd89", size = 149383, upload-time = "2025-10-14T04:40:46.018Z" }, - { url = "https://files.pythonhosted.org/packages/4f/e8/b289173b4edae05c0dde07f69f8db476a0b511eac556dfe0d6bda3c43384/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:9f7fcd74d410a36883701fafa2482a6af2ff5ba96b9a620e9e0721e28ead5569", size = 159098, upload-time = "2025-10-14T04:40:47.081Z" }, - { url = "https://files.pythonhosted.org/packages/d8/df/fe699727754cae3f8478493c7f45f777b17c3ef0600e28abfec8619eb49c/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ebf3e58c7ec8a8bed6d66a75d7fb37b55e5015b03ceae72a8e7c74495551e224", size = 152991, upload-time = "2025-10-14T04:40:48.246Z" }, - { url = "https://files.pythonhosted.org/packages/1a/86/584869fe4ddb6ffa3bd9f491b87a01568797fb9bd8933f557dba9771beaf/charset_normalizer-3.4.4-cp311-cp311-win32.whl", hash = "sha256:eecbc200c7fd5ddb9a7f16c7decb07b566c29fa2161a16cf67b8d068bd21690a", size = 99456, upload-time = "2025-10-14T04:40:49.376Z" }, - { url = "https://files.pythonhosted.org/packages/65/f6/62fdd5feb60530f50f7e38b4f6a1d5203f4d16ff4f9f0952962c044e919a/charset_normalizer-3.4.4-cp311-cp311-win_amd64.whl", hash = "sha256:5ae497466c7901d54b639cf42d5b8c1b6a4fead55215500d2f486d34db48d016", size = 106978, upload-time = "2025-10-14T04:40:50.844Z" }, - { url = "https://files.pythonhosted.org/packages/7a/9d/0710916e6c82948b3be62d9d398cb4fcf4e97b56d6a6aeccd66c4b2f2bd5/charset_normalizer-3.4.4-cp311-cp311-win_arm64.whl", hash = "sha256:65e2befcd84bc6f37095f5961e68a6f077bf44946771354a28ad434c2cce0ae1", size = 99969, upload-time = "2025-10-14T04:40:52.272Z" }, - { url = "https://files.pythonhosted.org/packages/f3/85/1637cd4af66fa687396e757dec650f28025f2a2f5a5531a3208dc0ec43f2/charset_normalizer-3.4.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0a98e6759f854bd25a58a73fa88833fba3b7c491169f86ce1180c948ab3fd394", size = 208425, upload-time = "2025-10-14T04:40:53.353Z" }, - { url = "https://files.pythonhosted.org/packages/9d/6a/04130023fef2a0d9c62d0bae2649b69f7b7d8d24ea5536feef50551029df/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b5b290ccc2a263e8d185130284f8501e3e36c5e02750fc6b6bdeb2e9e96f1e25", size = 148162, upload-time = "2025-10-14T04:40:54.558Z" }, - { url = "https://files.pythonhosted.org/packages/78/29/62328d79aa60da22c9e0b9a66539feae06ca0f5a4171ac4f7dc285b83688/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:74bb723680f9f7a6234dcf67aea57e708ec1fbdf5699fb91dfd6f511b0a320ef", size = 144558, upload-time = "2025-10-14T04:40:55.677Z" }, - { url = "https://files.pythonhosted.org/packages/86/bb/b32194a4bf15b88403537c2e120b817c61cd4ecffa9b6876e941c3ee38fe/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f1e34719c6ed0b92f418c7c780480b26b5d9c50349e9a9af7d76bf757530350d", size = 161497, upload-time = "2025-10-14T04:40:57.217Z" }, - { url = "https://files.pythonhosted.org/packages/19/89/a54c82b253d5b9b111dc74aca196ba5ccfcca8242d0fb64146d4d3183ff1/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2437418e20515acec67d86e12bf70056a33abdacb5cb1655042f6538d6b085a8", size = 159240, upload-time = "2025-10-14T04:40:58.358Z" }, - { url = "https://files.pythonhosted.org/packages/c0/10/d20b513afe03acc89ec33948320a5544d31f21b05368436d580dec4e234d/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:11d694519d7f29d6cd09f6ac70028dba10f92f6cdd059096db198c283794ac86", size = 153471, upload-time = "2025-10-14T04:40:59.468Z" }, - { url = "https://files.pythonhosted.org/packages/61/fa/fbf177b55bdd727010f9c0a3c49eefa1d10f960e5f09d1d887bf93c2e698/charset_normalizer-3.4.4-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ac1c4a689edcc530fc9d9aa11f5774b9e2f33f9a0c6a57864e90908f5208d30a", size = 150864, upload-time = "2025-10-14T04:41:00.623Z" }, - { url = "https://files.pythonhosted.org/packages/05/12/9fbc6a4d39c0198adeebbde20b619790e9236557ca59fc40e0e3cebe6f40/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:21d142cc6c0ec30d2efee5068ca36c128a30b0f2c53c1c07bd78cb6bc1d3be5f", size = 150647, upload-time = "2025-10-14T04:41:01.754Z" }, - { url = "https://files.pythonhosted.org/packages/ad/1f/6a9a593d52e3e8c5d2b167daf8c6b968808efb57ef4c210acb907c365bc4/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:5dbe56a36425d26d6cfb40ce79c314a2e4dd6211d51d6d2191c00bed34f354cc", size = 145110, upload-time = "2025-10-14T04:41:03.231Z" }, - { url = "https://files.pythonhosted.org/packages/30/42/9a52c609e72471b0fc54386dc63c3781a387bb4fe61c20231a4ebcd58bdd/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:5bfbb1b9acf3334612667b61bd3002196fe2a1eb4dd74d247e0f2a4d50ec9bbf", size = 162839, upload-time = "2025-10-14T04:41:04.715Z" }, - { url = "https://files.pythonhosted.org/packages/c4/5b/c0682bbf9f11597073052628ddd38344a3d673fda35a36773f7d19344b23/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:d055ec1e26e441f6187acf818b73564e6e6282709e9bcb5b63f5b23068356a15", size = 150667, upload-time = "2025-10-14T04:41:05.827Z" }, - { url = "https://files.pythonhosted.org/packages/e4/24/a41afeab6f990cf2daf6cb8c67419b63b48cf518e4f56022230840c9bfb2/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:af2d8c67d8e573d6de5bc30cdb27e9b95e49115cd9baad5ddbd1a6207aaa82a9", size = 160535, upload-time = "2025-10-14T04:41:06.938Z" }, - { url = "https://files.pythonhosted.org/packages/2a/e5/6a4ce77ed243c4a50a1fecca6aaaab419628c818a49434be428fe24c9957/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:780236ac706e66881f3b7f2f32dfe90507a09e67d1d454c762cf642e6e1586e0", size = 154816, upload-time = "2025-10-14T04:41:08.101Z" }, - { url = "https://files.pythonhosted.org/packages/a8/ef/89297262b8092b312d29cdb2517cb1237e51db8ecef2e9af5edbe7b683b1/charset_normalizer-3.4.4-cp312-cp312-win32.whl", hash = "sha256:5833d2c39d8896e4e19b689ffc198f08ea58116bee26dea51e362ecc7cd3ed26", size = 99694, upload-time = "2025-10-14T04:41:09.23Z" }, - { url = "https://files.pythonhosted.org/packages/3d/2d/1e5ed9dd3b3803994c155cd9aacb60c82c331bad84daf75bcb9c91b3295e/charset_normalizer-3.4.4-cp312-cp312-win_amd64.whl", hash = "sha256:a79cfe37875f822425b89a82333404539ae63dbdddf97f84dcbc3d339aae9525", size = 107131, upload-time = "2025-10-14T04:41:10.467Z" }, - { url = "https://files.pythonhosted.org/packages/d0/d9/0ed4c7098a861482a7b6a95603edce4c0d9db2311af23da1fb2b75ec26fc/charset_normalizer-3.4.4-cp312-cp312-win_arm64.whl", hash = "sha256:376bec83a63b8021bb5c8ea75e21c4ccb86e7e45ca4eb81146091b56599b80c3", size = 100390, upload-time = "2025-10-14T04:41:11.915Z" }, - { url = "https://files.pythonhosted.org/packages/97/45/4b3a1239bbacd321068ea6e7ac28875b03ab8bc0aa0966452db17cd36714/charset_normalizer-3.4.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:e1f185f86a6f3403aa2420e815904c67b2f9ebc443f045edd0de921108345794", size = 208091, upload-time = "2025-10-14T04:41:13.346Z" }, - { url = "https://files.pythonhosted.org/packages/7d/62/73a6d7450829655a35bb88a88fca7d736f9882a27eacdca2c6d505b57e2e/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b39f987ae8ccdf0d2642338faf2abb1862340facc796048b604ef14919e55ed", size = 147936, upload-time = "2025-10-14T04:41:14.461Z" }, - { url = "https://files.pythonhosted.org/packages/89/c5/adb8c8b3d6625bef6d88b251bbb0d95f8205831b987631ab0c8bb5d937c2/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3162d5d8ce1bb98dd51af660f2121c55d0fa541b46dff7bb9b9f86ea1d87de72", size = 144180, upload-time = "2025-10-14T04:41:15.588Z" }, - { url = "https://files.pythonhosted.org/packages/91/ed/9706e4070682d1cc219050b6048bfd293ccf67b3d4f5a4f39207453d4b99/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:81d5eb2a312700f4ecaa977a8235b634ce853200e828fbadf3a9c50bab278328", size = 161346, upload-time = "2025-10-14T04:41:16.738Z" }, - { url = "https://files.pythonhosted.org/packages/d5/0d/031f0d95e4972901a2f6f09ef055751805ff541511dc1252ba3ca1f80cf5/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5bd2293095d766545ec1a8f612559f6b40abc0eb18bb2f5d1171872d34036ede", size = 158874, upload-time = "2025-10-14T04:41:17.923Z" }, - { url = "https://files.pythonhosted.org/packages/f5/83/6ab5883f57c9c801ce5e5677242328aa45592be8a00644310a008d04f922/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a8a8b89589086a25749f471e6a900d3f662d1d3b6e2e59dcecf787b1cc3a1894", size = 153076, upload-time = "2025-10-14T04:41:19.106Z" }, - { url = "https://files.pythonhosted.org/packages/75/1e/5ff781ddf5260e387d6419959ee89ef13878229732732ee73cdae01800f2/charset_normalizer-3.4.4-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc7637e2f80d8530ee4a78e878bce464f70087ce73cf7c1caf142416923b98f1", size = 150601, upload-time = "2025-10-14T04:41:20.245Z" }, - { url = "https://files.pythonhosted.org/packages/d7/57/71be810965493d3510a6ca79b90c19e48696fb1ff964da319334b12677f0/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f8bf04158c6b607d747e93949aa60618b61312fe647a6369f88ce2ff16043490", size = 150376, upload-time = "2025-10-14T04:41:21.398Z" }, - { url = "https://files.pythonhosted.org/packages/e5/d5/c3d057a78c181d007014feb7e9f2e65905a6c4ef182c0ddf0de2924edd65/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:554af85e960429cf30784dd47447d5125aaa3b99a6f0683589dbd27e2f45da44", size = 144825, upload-time = "2025-10-14T04:41:22.583Z" }, - { url = "https://files.pythonhosted.org/packages/e6/8c/d0406294828d4976f275ffbe66f00266c4b3136b7506941d87c00cab5272/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:74018750915ee7ad843a774364e13a3db91682f26142baddf775342c3f5b1133", size = 162583, upload-time = "2025-10-14T04:41:23.754Z" }, - { url = "https://files.pythonhosted.org/packages/d7/24/e2aa1f18c8f15c4c0e932d9287b8609dd30ad56dbe41d926bd846e22fb8d/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:c0463276121fdee9c49b98908b3a89c39be45d86d1dbaa22957e38f6321d4ce3", size = 150366, upload-time = "2025-10-14T04:41:25.27Z" }, - { url = "https://files.pythonhosted.org/packages/e4/5b/1e6160c7739aad1e2df054300cc618b06bf784a7a164b0f238360721ab86/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:362d61fd13843997c1c446760ef36f240cf81d3ebf74ac62652aebaf7838561e", size = 160300, upload-time = "2025-10-14T04:41:26.725Z" }, - { url = "https://files.pythonhosted.org/packages/7a/10/f882167cd207fbdd743e55534d5d9620e095089d176d55cb22d5322f2afd/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9a26f18905b8dd5d685d6d07b0cdf98a79f3c7a918906af7cc143ea2e164c8bc", size = 154465, upload-time = "2025-10-14T04:41:28.322Z" }, - { url = "https://files.pythonhosted.org/packages/89/66/c7a9e1b7429be72123441bfdbaf2bc13faab3f90b933f664db506dea5915/charset_normalizer-3.4.4-cp313-cp313-win32.whl", hash = "sha256:9b35f4c90079ff2e2edc5b26c0c77925e5d2d255c42c74fdb70fb49b172726ac", size = 99404, upload-time = "2025-10-14T04:41:29.95Z" }, - { url = "https://files.pythonhosted.org/packages/c4/26/b9924fa27db384bdcd97ab83b4f0a8058d96ad9626ead570674d5e737d90/charset_normalizer-3.4.4-cp313-cp313-win_amd64.whl", hash = "sha256:b435cba5f4f750aa6c0a0d92c541fb79f69a387c91e61f1795227e4ed9cece14", size = 107092, upload-time = "2025-10-14T04:41:31.188Z" }, - { url = "https://files.pythonhosted.org/packages/af/8f/3ed4bfa0c0c72a7ca17f0380cd9e4dd842b09f664e780c13cff1dcf2ef1b/charset_normalizer-3.4.4-cp313-cp313-win_arm64.whl", hash = "sha256:542d2cee80be6f80247095cc36c418f7bddd14f4a6de45af91dfad36d817bba2", size = 100408, upload-time = "2025-10-14T04:41:32.624Z" }, - { url = "https://files.pythonhosted.org/packages/2a/35/7051599bd493e62411d6ede36fd5af83a38f37c4767b92884df7301db25d/charset_normalizer-3.4.4-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:da3326d9e65ef63a817ecbcc0df6e94463713b754fe293eaa03da99befb9a5bd", size = 207746, upload-time = "2025-10-14T04:41:33.773Z" }, - { url = "https://files.pythonhosted.org/packages/10/9a/97c8d48ef10d6cd4fcead2415523221624bf58bcf68a802721a6bc807c8f/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8af65f14dc14a79b924524b1e7fffe304517b2bff5a58bf64f30b98bbc5079eb", size = 147889, upload-time = "2025-10-14T04:41:34.897Z" }, - { url = "https://files.pythonhosted.org/packages/10/bf/979224a919a1b606c82bd2c5fa49b5c6d5727aa47b4312bb27b1734f53cd/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:74664978bb272435107de04e36db5a9735e78232b85b77d45cfb38f758efd33e", size = 143641, upload-time = "2025-10-14T04:41:36.116Z" }, - { url = "https://files.pythonhosted.org/packages/ba/33/0ad65587441fc730dc7bd90e9716b30b4702dc7b617e6ba4997dc8651495/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:752944c7ffbfdd10c074dc58ec2d5a8a4cd9493b314d367c14d24c17684ddd14", size = 160779, upload-time = "2025-10-14T04:41:37.229Z" }, - { url = "https://files.pythonhosted.org/packages/67/ed/331d6b249259ee71ddea93f6f2f0a56cfebd46938bde6fcc6f7b9a3d0e09/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d1f13550535ad8cff21b8d757a3257963e951d96e20ec82ab44bc64aeb62a191", size = 159035, upload-time = "2025-10-14T04:41:38.368Z" }, - { url = "https://files.pythonhosted.org/packages/67/ff/f6b948ca32e4f2a4576aa129d8bed61f2e0543bf9f5f2b7fc3758ed005c9/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ecaae4149d99b1c9e7b88bb03e3221956f68fd6d50be2ef061b2381b61d20838", size = 152542, upload-time = "2025-10-14T04:41:39.862Z" }, - { url = "https://files.pythonhosted.org/packages/16/85/276033dcbcc369eb176594de22728541a925b2632f9716428c851b149e83/charset_normalizer-3.4.4-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cb6254dc36b47a990e59e1068afacdcd02958bdcce30bb50cc1700a8b9d624a6", size = 149524, upload-time = "2025-10-14T04:41:41.319Z" }, - { url = "https://files.pythonhosted.org/packages/9e/f2/6a2a1f722b6aba37050e626530a46a68f74e63683947a8acff92569f979a/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c8ae8a0f02f57a6e61203a31428fa1d677cbe50c93622b4149d5c0f319c1d19e", size = 150395, upload-time = "2025-10-14T04:41:42.539Z" }, - { url = "https://files.pythonhosted.org/packages/60/bb/2186cb2f2bbaea6338cad15ce23a67f9b0672929744381e28b0592676824/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:47cc91b2f4dd2833fddaedd2893006b0106129d4b94fdb6af1f4ce5a9965577c", size = 143680, upload-time = "2025-10-14T04:41:43.661Z" }, - { url = "https://files.pythonhosted.org/packages/7d/a5/bf6f13b772fbb2a90360eb620d52ed8f796f3c5caee8398c3b2eb7b1c60d/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:82004af6c302b5d3ab2cfc4cc5f29db16123b1a8417f2e25f9066f91d4411090", size = 162045, upload-time = "2025-10-14T04:41:44.821Z" }, - { url = "https://files.pythonhosted.org/packages/df/c5/d1be898bf0dc3ef9030c3825e5d3b83f2c528d207d246cbabe245966808d/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:2b7d8f6c26245217bd2ad053761201e9f9680f8ce52f0fcd8d0755aeae5b2152", size = 149687, upload-time = "2025-10-14T04:41:46.442Z" }, - { url = "https://files.pythonhosted.org/packages/a5/42/90c1f7b9341eef50c8a1cb3f098ac43b0508413f33affd762855f67a410e/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:799a7a5e4fb2d5898c60b640fd4981d6a25f1c11790935a44ce38c54e985f828", size = 160014, upload-time = "2025-10-14T04:41:47.631Z" }, - { url = "https://files.pythonhosted.org/packages/76/be/4d3ee471e8145d12795ab655ece37baed0929462a86e72372fd25859047c/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:99ae2cffebb06e6c22bdc25801d7b30f503cc87dbd283479e7b606f70aff57ec", size = 154044, upload-time = "2025-10-14T04:41:48.81Z" }, - { url = "https://files.pythonhosted.org/packages/b0/6f/8f7af07237c34a1defe7defc565a9bc1807762f672c0fde711a4b22bf9c0/charset_normalizer-3.4.4-cp314-cp314-win32.whl", hash = "sha256:f9d332f8c2a2fcbffe1378594431458ddbef721c1769d78e2cbc06280d8155f9", size = 99940, upload-time = "2025-10-14T04:41:49.946Z" }, - { url = "https://files.pythonhosted.org/packages/4b/51/8ade005e5ca5b0d80fb4aff72a3775b325bdc3d27408c8113811a7cbe640/charset_normalizer-3.4.4-cp314-cp314-win_amd64.whl", hash = "sha256:8a6562c3700cce886c5be75ade4a5db4214fda19fede41d9792d100288d8f94c", size = 107104, upload-time = "2025-10-14T04:41:51.051Z" }, - { url = "https://files.pythonhosted.org/packages/da/5f/6b8f83a55bb8278772c5ae54a577f3099025f9ade59d0136ac24a0df4bde/charset_normalizer-3.4.4-cp314-cp314-win_arm64.whl", hash = "sha256:de00632ca48df9daf77a2c65a484531649261ec9f25489917f09e455cb09ddb2", size = 100743, upload-time = "2025-10-14T04:41:52.122Z" }, - { url = "https://files.pythonhosted.org/packages/0a/4c/925909008ed5a988ccbb72dcc897407e5d6d3bd72410d69e051fc0c14647/charset_normalizer-3.4.4-py3-none-any.whl", hash = "sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f", size = 53402, upload-time = "2025-10-14T04:42:31.76Z" }, +wheels = [ + {url = "https://files.pythonhosted.org/packages/ed/27/c6491ff4954e58a10f69ad90aca8a1b6fe9c5d3c6f380907af3c37435b59/charset_normalizer-3.4.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6e1fcf0720908f200cd21aa4e6750a48ff6ce4afe7ff5a79a90d5ed8a08296f8", size = 206988, upload-time = "2025-10-14T04:40:33.79Z"}, + {url = "https://files.pythonhosted.org/packages/94/59/2e87300fe67ab820b5428580a53cad894272dbb97f38a7a814a2a1ac1011/charset_normalizer-3.4.4-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5f819d5fe9234f9f82d75bdfa9aef3a3d72c4d24a6e57aeaebba32a704553aa0", size = 147324, upload-time = "2025-10-14T04:40:34.961Z"}, + {url = "https://files.pythonhosted.org/packages/07/fb/0cf61dc84b2b088391830f6274cb57c82e4da8bbc2efeac8c025edb88772/charset_normalizer-3.4.4-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:a59cb51917aa591b1c4e6a43c132f0cdc3c76dbad6155df4e28ee626cc77a0a3", size = 142742, upload-time = "2025-10-14T04:40:36.105Z"}, + {url = "https://files.pythonhosted.org/packages/62/8b/171935adf2312cd745d290ed93cf16cf0dfe320863ab7cbeeae1dcd6535f/charset_normalizer-3.4.4-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8ef3c867360f88ac904fd3f5e1f902f13307af9052646963ee08ff4f131adafc", size = 160863, upload-time = "2025-10-14T04:40:37.188Z"}, + {url = "https://files.pythonhosted.org/packages/09/73/ad875b192bda14f2173bfc1bc9a55e009808484a4b256748d931b6948442/charset_normalizer-3.4.4-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d9e45d7faa48ee908174d8fe84854479ef838fc6a705c9315372eacbc2f02897", size = 157837, upload-time = "2025-10-14T04:40:38.435Z"}, + {url = "https://files.pythonhosted.org/packages/6d/fc/de9cce525b2c5b94b47c70a4b4fb19f871b24995c728e957ee68ab1671ea/charset_normalizer-3.4.4-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:840c25fb618a231545cbab0564a799f101b63b9901f2569faecd6b222ac72381", size = 151550, upload-time = "2025-10-14T04:40:40.053Z"}, + {url = "https://files.pythonhosted.org/packages/55/c2/43edd615fdfba8c6f2dfbd459b25a6b3b551f24ea21981e23fb768503ce1/charset_normalizer-3.4.4-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ca5862d5b3928c4940729dacc329aa9102900382fea192fc5e52eb69d6093815", size = 149162, upload-time = "2025-10-14T04:40:41.163Z"}, + {url = "https://files.pythonhosted.org/packages/03/86/bde4ad8b4d0e9429a4e82c1e8f5c659993a9a863ad62c7df05cf7b678d75/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d9c7f57c3d666a53421049053eaacdd14bbd0a528e2186fcb2e672effd053bb0", size = 150019, upload-time = "2025-10-14T04:40:42.276Z"}, + {url = "https://files.pythonhosted.org/packages/1f/86/a151eb2af293a7e7bac3a739b81072585ce36ccfb4493039f49f1d3cae8c/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:277e970e750505ed74c832b4bf75dac7476262ee2a013f5574dd49075879e161", size = 143310, upload-time = "2025-10-14T04:40:43.439Z"}, + {url = "https://files.pythonhosted.org/packages/b5/fe/43dae6144a7e07b87478fdfc4dbe9efd5defb0e7ec29f5f58a55aeef7bf7/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:31fd66405eaf47bb62e8cd575dc621c56c668f27d46a61d975a249930dd5e2a4", size = 162022, upload-time = "2025-10-14T04:40:44.547Z"}, + {url = "https://files.pythonhosted.org/packages/80/e6/7aab83774f5d2bca81f42ac58d04caf44f0cc2b65fc6db2b3b2e8a05f3b3/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:0d3d8f15c07f86e9ff82319b3d9ef6f4bf907608f53fe9d92b28ea9ae3d1fd89", size = 149383, upload-time = "2025-10-14T04:40:46.018Z"}, + {url = "https://files.pythonhosted.org/packages/4f/e8/b289173b4edae05c0dde07f69f8db476a0b511eac556dfe0d6bda3c43384/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:9f7fcd74d410a36883701fafa2482a6af2ff5ba96b9a620e9e0721e28ead5569", size = 159098, upload-time = "2025-10-14T04:40:47.081Z"}, + {url = "https://files.pythonhosted.org/packages/d8/df/fe699727754cae3f8478493c7f45f777b17c3ef0600e28abfec8619eb49c/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ebf3e58c7ec8a8bed6d66a75d7fb37b55e5015b03ceae72a8e7c74495551e224", size = 152991, upload-time = "2025-10-14T04:40:48.246Z"}, + {url = "https://files.pythonhosted.org/packages/1a/86/584869fe4ddb6ffa3bd9f491b87a01568797fb9bd8933f557dba9771beaf/charset_normalizer-3.4.4-cp311-cp311-win32.whl", hash = "sha256:eecbc200c7fd5ddb9a7f16c7decb07b566c29fa2161a16cf67b8d068bd21690a", size = 99456, upload-time = "2025-10-14T04:40:49.376Z"}, + {url = "https://files.pythonhosted.org/packages/65/f6/62fdd5feb60530f50f7e38b4f6a1d5203f4d16ff4f9f0952962c044e919a/charset_normalizer-3.4.4-cp311-cp311-win_amd64.whl", hash = "sha256:5ae497466c7901d54b639cf42d5b8c1b6a4fead55215500d2f486d34db48d016", size = 106978, upload-time = "2025-10-14T04:40:50.844Z"}, + {url = "https://files.pythonhosted.org/packages/7a/9d/0710916e6c82948b3be62d9d398cb4fcf4e97b56d6a6aeccd66c4b2f2bd5/charset_normalizer-3.4.4-cp311-cp311-win_arm64.whl", hash = "sha256:65e2befcd84bc6f37095f5961e68a6f077bf44946771354a28ad434c2cce0ae1", size = 99969, upload-time = "2025-10-14T04:40:52.272Z"}, + {url = "https://files.pythonhosted.org/packages/f3/85/1637cd4af66fa687396e757dec650f28025f2a2f5a5531a3208dc0ec43f2/charset_normalizer-3.4.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0a98e6759f854bd25a58a73fa88833fba3b7c491169f86ce1180c948ab3fd394", size = 208425, upload-time = "2025-10-14T04:40:53.353Z"}, + {url = "https://files.pythonhosted.org/packages/9d/6a/04130023fef2a0d9c62d0bae2649b69f7b7d8d24ea5536feef50551029df/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b5b290ccc2a263e8d185130284f8501e3e36c5e02750fc6b6bdeb2e9e96f1e25", size = 148162, upload-time = "2025-10-14T04:40:54.558Z"}, + {url = "https://files.pythonhosted.org/packages/78/29/62328d79aa60da22c9e0b9a66539feae06ca0f5a4171ac4f7dc285b83688/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:74bb723680f9f7a6234dcf67aea57e708ec1fbdf5699fb91dfd6f511b0a320ef", size = 144558, upload-time = "2025-10-14T04:40:55.677Z"}, + {url = "https://files.pythonhosted.org/packages/86/bb/b32194a4bf15b88403537c2e120b817c61cd4ecffa9b6876e941c3ee38fe/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f1e34719c6ed0b92f418c7c780480b26b5d9c50349e9a9af7d76bf757530350d", size = 161497, upload-time = "2025-10-14T04:40:57.217Z"}, + {url = "https://files.pythonhosted.org/packages/19/89/a54c82b253d5b9b111dc74aca196ba5ccfcca8242d0fb64146d4d3183ff1/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2437418e20515acec67d86e12bf70056a33abdacb5cb1655042f6538d6b085a8", size = 159240, upload-time = "2025-10-14T04:40:58.358Z"}, + {url = "https://files.pythonhosted.org/packages/c0/10/d20b513afe03acc89ec33948320a5544d31f21b05368436d580dec4e234d/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:11d694519d7f29d6cd09f6ac70028dba10f92f6cdd059096db198c283794ac86", size = 153471, upload-time = "2025-10-14T04:40:59.468Z"}, + {url = "https://files.pythonhosted.org/packages/61/fa/fbf177b55bdd727010f9c0a3c49eefa1d10f960e5f09d1d887bf93c2e698/charset_normalizer-3.4.4-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ac1c4a689edcc530fc9d9aa11f5774b9e2f33f9a0c6a57864e90908f5208d30a", size = 150864, upload-time = "2025-10-14T04:41:00.623Z"}, + {url = "https://files.pythonhosted.org/packages/05/12/9fbc6a4d39c0198adeebbde20b619790e9236557ca59fc40e0e3cebe6f40/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:21d142cc6c0ec30d2efee5068ca36c128a30b0f2c53c1c07bd78cb6bc1d3be5f", size = 150647, upload-time = "2025-10-14T04:41:01.754Z"}, + {url = "https://files.pythonhosted.org/packages/ad/1f/6a9a593d52e3e8c5d2b167daf8c6b968808efb57ef4c210acb907c365bc4/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:5dbe56a36425d26d6cfb40ce79c314a2e4dd6211d51d6d2191c00bed34f354cc", size = 145110, upload-time = "2025-10-14T04:41:03.231Z"}, + {url = "https://files.pythonhosted.org/packages/30/42/9a52c609e72471b0fc54386dc63c3781a387bb4fe61c20231a4ebcd58bdd/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:5bfbb1b9acf3334612667b61bd3002196fe2a1eb4dd74d247e0f2a4d50ec9bbf", size = 162839, upload-time = "2025-10-14T04:41:04.715Z"}, + {url = "https://files.pythonhosted.org/packages/c4/5b/c0682bbf9f11597073052628ddd38344a3d673fda35a36773f7d19344b23/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:d055ec1e26e441f6187acf818b73564e6e6282709e9bcb5b63f5b23068356a15", size = 150667, upload-time = "2025-10-14T04:41:05.827Z"}, + {url = "https://files.pythonhosted.org/packages/e4/24/a41afeab6f990cf2daf6cb8c67419b63b48cf518e4f56022230840c9bfb2/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:af2d8c67d8e573d6de5bc30cdb27e9b95e49115cd9baad5ddbd1a6207aaa82a9", size = 160535, upload-time = "2025-10-14T04:41:06.938Z"}, + {url = "https://files.pythonhosted.org/packages/2a/e5/6a4ce77ed243c4a50a1fecca6aaaab419628c818a49434be428fe24c9957/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:780236ac706e66881f3b7f2f32dfe90507a09e67d1d454c762cf642e6e1586e0", size = 154816, upload-time = "2025-10-14T04:41:08.101Z"}, + {url = "https://files.pythonhosted.org/packages/a8/ef/89297262b8092b312d29cdb2517cb1237e51db8ecef2e9af5edbe7b683b1/charset_normalizer-3.4.4-cp312-cp312-win32.whl", hash = "sha256:5833d2c39d8896e4e19b689ffc198f08ea58116bee26dea51e362ecc7cd3ed26", size = 99694, upload-time = "2025-10-14T04:41:09.23Z"}, + {url = "https://files.pythonhosted.org/packages/3d/2d/1e5ed9dd3b3803994c155cd9aacb60c82c331bad84daf75bcb9c91b3295e/charset_normalizer-3.4.4-cp312-cp312-win_amd64.whl", hash = "sha256:a79cfe37875f822425b89a82333404539ae63dbdddf97f84dcbc3d339aae9525", size = 107131, upload-time = "2025-10-14T04:41:10.467Z"}, + {url = "https://files.pythonhosted.org/packages/d0/d9/0ed4c7098a861482a7b6a95603edce4c0d9db2311af23da1fb2b75ec26fc/charset_normalizer-3.4.4-cp312-cp312-win_arm64.whl", hash = "sha256:376bec83a63b8021bb5c8ea75e21c4ccb86e7e45ca4eb81146091b56599b80c3", size = 100390, upload-time = "2025-10-14T04:41:11.915Z"}, + {url = "https://files.pythonhosted.org/packages/97/45/4b3a1239bbacd321068ea6e7ac28875b03ab8bc0aa0966452db17cd36714/charset_normalizer-3.4.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:e1f185f86a6f3403aa2420e815904c67b2f9ebc443f045edd0de921108345794", size = 208091, upload-time = "2025-10-14T04:41:13.346Z"}, + {url = "https://files.pythonhosted.org/packages/7d/62/73a6d7450829655a35bb88a88fca7d736f9882a27eacdca2c6d505b57e2e/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b39f987ae8ccdf0d2642338faf2abb1862340facc796048b604ef14919e55ed", size = 147936, upload-time = "2025-10-14T04:41:14.461Z"}, + {url = "https://files.pythonhosted.org/packages/89/c5/adb8c8b3d6625bef6d88b251bbb0d95f8205831b987631ab0c8bb5d937c2/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3162d5d8ce1bb98dd51af660f2121c55d0fa541b46dff7bb9b9f86ea1d87de72", size = 144180, upload-time = "2025-10-14T04:41:15.588Z"}, + {url = "https://files.pythonhosted.org/packages/91/ed/9706e4070682d1cc219050b6048bfd293ccf67b3d4f5a4f39207453d4b99/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:81d5eb2a312700f4ecaa977a8235b634ce853200e828fbadf3a9c50bab278328", size = 161346, upload-time = "2025-10-14T04:41:16.738Z"}, + {url = "https://files.pythonhosted.org/packages/d5/0d/031f0d95e4972901a2f6f09ef055751805ff541511dc1252ba3ca1f80cf5/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5bd2293095d766545ec1a8f612559f6b40abc0eb18bb2f5d1171872d34036ede", size = 158874, upload-time = "2025-10-14T04:41:17.923Z"}, + {url = "https://files.pythonhosted.org/packages/f5/83/6ab5883f57c9c801ce5e5677242328aa45592be8a00644310a008d04f922/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a8a8b89589086a25749f471e6a900d3f662d1d3b6e2e59dcecf787b1cc3a1894", size = 153076, upload-time = "2025-10-14T04:41:19.106Z"}, + {url = "https://files.pythonhosted.org/packages/75/1e/5ff781ddf5260e387d6419959ee89ef13878229732732ee73cdae01800f2/charset_normalizer-3.4.4-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc7637e2f80d8530ee4a78e878bce464f70087ce73cf7c1caf142416923b98f1", size = 150601, upload-time = "2025-10-14T04:41:20.245Z"}, + {url = "https://files.pythonhosted.org/packages/d7/57/71be810965493d3510a6ca79b90c19e48696fb1ff964da319334b12677f0/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f8bf04158c6b607d747e93949aa60618b61312fe647a6369f88ce2ff16043490", size = 150376, upload-time = "2025-10-14T04:41:21.398Z"}, + {url = "https://files.pythonhosted.org/packages/e5/d5/c3d057a78c181d007014feb7e9f2e65905a6c4ef182c0ddf0de2924edd65/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:554af85e960429cf30784dd47447d5125aaa3b99a6f0683589dbd27e2f45da44", size = 144825, upload-time = "2025-10-14T04:41:22.583Z"}, + {url = "https://files.pythonhosted.org/packages/e6/8c/d0406294828d4976f275ffbe66f00266c4b3136b7506941d87c00cab5272/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:74018750915ee7ad843a774364e13a3db91682f26142baddf775342c3f5b1133", size = 162583, upload-time = "2025-10-14T04:41:23.754Z"}, + {url = "https://files.pythonhosted.org/packages/d7/24/e2aa1f18c8f15c4c0e932d9287b8609dd30ad56dbe41d926bd846e22fb8d/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:c0463276121fdee9c49b98908b3a89c39be45d86d1dbaa22957e38f6321d4ce3", size = 150366, upload-time = "2025-10-14T04:41:25.27Z"}, + {url = "https://files.pythonhosted.org/packages/e4/5b/1e6160c7739aad1e2df054300cc618b06bf784a7a164b0f238360721ab86/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:362d61fd13843997c1c446760ef36f240cf81d3ebf74ac62652aebaf7838561e", size = 160300, upload-time = "2025-10-14T04:41:26.725Z"}, + {url = "https://files.pythonhosted.org/packages/7a/10/f882167cd207fbdd743e55534d5d9620e095089d176d55cb22d5322f2afd/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9a26f18905b8dd5d685d6d07b0cdf98a79f3c7a918906af7cc143ea2e164c8bc", size = 154465, upload-time = "2025-10-14T04:41:28.322Z"}, + {url = "https://files.pythonhosted.org/packages/89/66/c7a9e1b7429be72123441bfdbaf2bc13faab3f90b933f664db506dea5915/charset_normalizer-3.4.4-cp313-cp313-win32.whl", hash = "sha256:9b35f4c90079ff2e2edc5b26c0c77925e5d2d255c42c74fdb70fb49b172726ac", size = 99404, upload-time = "2025-10-14T04:41:29.95Z"}, + {url = "https://files.pythonhosted.org/packages/c4/26/b9924fa27db384bdcd97ab83b4f0a8058d96ad9626ead570674d5e737d90/charset_normalizer-3.4.4-cp313-cp313-win_amd64.whl", hash = "sha256:b435cba5f4f750aa6c0a0d92c541fb79f69a387c91e61f1795227e4ed9cece14", size = 107092, upload-time = "2025-10-14T04:41:31.188Z"}, + {url = "https://files.pythonhosted.org/packages/af/8f/3ed4bfa0c0c72a7ca17f0380cd9e4dd842b09f664e780c13cff1dcf2ef1b/charset_normalizer-3.4.4-cp313-cp313-win_arm64.whl", hash = "sha256:542d2cee80be6f80247095cc36c418f7bddd14f4a6de45af91dfad36d817bba2", size = 100408, upload-time = "2025-10-14T04:41:32.624Z"}, + {url = "https://files.pythonhosted.org/packages/2a/35/7051599bd493e62411d6ede36fd5af83a38f37c4767b92884df7301db25d/charset_normalizer-3.4.4-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:da3326d9e65ef63a817ecbcc0df6e94463713b754fe293eaa03da99befb9a5bd", size = 207746, upload-time = "2025-10-14T04:41:33.773Z"}, + {url = "https://files.pythonhosted.org/packages/10/9a/97c8d48ef10d6cd4fcead2415523221624bf58bcf68a802721a6bc807c8f/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8af65f14dc14a79b924524b1e7fffe304517b2bff5a58bf64f30b98bbc5079eb", size = 147889, upload-time = "2025-10-14T04:41:34.897Z"}, + {url = "https://files.pythonhosted.org/packages/10/bf/979224a919a1b606c82bd2c5fa49b5c6d5727aa47b4312bb27b1734f53cd/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:74664978bb272435107de04e36db5a9735e78232b85b77d45cfb38f758efd33e", size = 143641, upload-time = "2025-10-14T04:41:36.116Z"}, + {url = "https://files.pythonhosted.org/packages/ba/33/0ad65587441fc730dc7bd90e9716b30b4702dc7b617e6ba4997dc8651495/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:752944c7ffbfdd10c074dc58ec2d5a8a4cd9493b314d367c14d24c17684ddd14", size = 160779, upload-time = "2025-10-14T04:41:37.229Z"}, + {url = "https://files.pythonhosted.org/packages/67/ed/331d6b249259ee71ddea93f6f2f0a56cfebd46938bde6fcc6f7b9a3d0e09/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d1f13550535ad8cff21b8d757a3257963e951d96e20ec82ab44bc64aeb62a191", size = 159035, upload-time = "2025-10-14T04:41:38.368Z"}, + {url = "https://files.pythonhosted.org/packages/67/ff/f6b948ca32e4f2a4576aa129d8bed61f2e0543bf9f5f2b7fc3758ed005c9/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ecaae4149d99b1c9e7b88bb03e3221956f68fd6d50be2ef061b2381b61d20838", size = 152542, upload-time = "2025-10-14T04:41:39.862Z"}, + {url = "https://files.pythonhosted.org/packages/16/85/276033dcbcc369eb176594de22728541a925b2632f9716428c851b149e83/charset_normalizer-3.4.4-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cb6254dc36b47a990e59e1068afacdcd02958bdcce30bb50cc1700a8b9d624a6", size = 149524, upload-time = "2025-10-14T04:41:41.319Z"}, + {url = "https://files.pythonhosted.org/packages/9e/f2/6a2a1f722b6aba37050e626530a46a68f74e63683947a8acff92569f979a/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c8ae8a0f02f57a6e61203a31428fa1d677cbe50c93622b4149d5c0f319c1d19e", size = 150395, upload-time = "2025-10-14T04:41:42.539Z"}, + {url = "https://files.pythonhosted.org/packages/60/bb/2186cb2f2bbaea6338cad15ce23a67f9b0672929744381e28b0592676824/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:47cc91b2f4dd2833fddaedd2893006b0106129d4b94fdb6af1f4ce5a9965577c", size = 143680, upload-time = "2025-10-14T04:41:43.661Z"}, + {url = "https://files.pythonhosted.org/packages/7d/a5/bf6f13b772fbb2a90360eb620d52ed8f796f3c5caee8398c3b2eb7b1c60d/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:82004af6c302b5d3ab2cfc4cc5f29db16123b1a8417f2e25f9066f91d4411090", size = 162045, upload-time = "2025-10-14T04:41:44.821Z"}, + {url = "https://files.pythonhosted.org/packages/df/c5/d1be898bf0dc3ef9030c3825e5d3b83f2c528d207d246cbabe245966808d/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:2b7d8f6c26245217bd2ad053761201e9f9680f8ce52f0fcd8d0755aeae5b2152", size = 149687, upload-time = "2025-10-14T04:41:46.442Z"}, + {url = "https://files.pythonhosted.org/packages/a5/42/90c1f7b9341eef50c8a1cb3f098ac43b0508413f33affd762855f67a410e/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:799a7a5e4fb2d5898c60b640fd4981d6a25f1c11790935a44ce38c54e985f828", size = 160014, upload-time = "2025-10-14T04:41:47.631Z"}, + {url = "https://files.pythonhosted.org/packages/76/be/4d3ee471e8145d12795ab655ece37baed0929462a86e72372fd25859047c/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:99ae2cffebb06e6c22bdc25801d7b30f503cc87dbd283479e7b606f70aff57ec", size = 154044, upload-time = "2025-10-14T04:41:48.81Z"}, + {url = "https://files.pythonhosted.org/packages/b0/6f/8f7af07237c34a1defe7defc565a9bc1807762f672c0fde711a4b22bf9c0/charset_normalizer-3.4.4-cp314-cp314-win32.whl", hash = "sha256:f9d332f8c2a2fcbffe1378594431458ddbef721c1769d78e2cbc06280d8155f9", size = 99940, upload-time = "2025-10-14T04:41:49.946Z"}, + {url = "https://files.pythonhosted.org/packages/4b/51/8ade005e5ca5b0d80fb4aff72a3775b325bdc3d27408c8113811a7cbe640/charset_normalizer-3.4.4-cp314-cp314-win_amd64.whl", hash = "sha256:8a6562c3700cce886c5be75ade4a5db4214fda19fede41d9792d100288d8f94c", size = 107104, upload-time = "2025-10-14T04:41:51.051Z"}, + {url = "https://files.pythonhosted.org/packages/da/5f/6b8f83a55bb8278772c5ae54a577f3099025f9ade59d0136ac24a0df4bde/charset_normalizer-3.4.4-cp314-cp314-win_arm64.whl", hash = "sha256:de00632ca48df9daf77a2c65a484531649261ec9f25489917f09e455cb09ddb2", size = 100743, upload-time = "2025-10-14T04:41:52.122Z"}, + {url = "https://files.pythonhosted.org/packages/0a/4c/925909008ed5a988ccbb72dcc897407e5d6d3bd72410d69e051fc0c14647/charset_normalizer-3.4.4-py3-none-any.whl", hash = "sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f", size = 53402, upload-time = "2025-10-14T04:42:31.76Z"} ] [[package]] -name = "click" -version = "8.3.1" -source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "colorama", marker = "sys_platform == 'win32'" }, + {name = "colorama", marker = "sys_platform == 'win32'"} ] -sdist = { url = "https://files.pythonhosted.org/packages/3d/fa/656b739db8587d7b5dfa22e22ed02566950fbfbcdc20311993483657a5c0/click-8.3.1.tar.gz", hash = "sha256:12ff4785d337a1bb490bb7e9c2b1ee5da3112e94a8622f26a6c77f5d2fc6842a", size = 295065, upload-time = "2025-11-15T20:45:42.706Z" } +name = "click" +sdist = {url = "https://files.pythonhosted.org/packages/3d/fa/656b739db8587d7b5dfa22e22ed02566950fbfbcdc20311993483657a5c0/click-8.3.1.tar.gz", hash = "sha256:12ff4785d337a1bb490bb7e9c2b1ee5da3112e94a8622f26a6c77f5d2fc6842a", size = 295065, upload-time = "2025-11-15T20:45:42.706Z"} +source = {registry = "https://pypi.org/simple"} +version = "8.3.1" wheels = [ - { url = "https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl", hash = "sha256:981153a64e25f12d547d3426c367a4857371575ee7ad18df2a6183ab0545b2a6", size = 108274, upload-time = "2025-11-15T20:45:41.139Z" }, + {url = "https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl", hash = "sha256:981153a64e25f12d547d3426c367a4857371575ee7ad18df2a6183ab0545b2a6", size = 108274, upload-time = "2025-11-15T20:45:41.139Z"} ] [[package]] name = "cloudpickle" +sdist = {url = "https://files.pythonhosted.org/packages/27/fb/576f067976d320f5f0114a8d9fa1215425441bb35627b1993e5afd8111e5/cloudpickle-3.1.2.tar.gz", hash = "sha256:7fda9eb655c9c230dab534f1983763de5835249750e85fbcef43aaa30a9a2414", size = 22330, upload-time = "2025-11-03T09:25:26.604Z"} +source = {registry = "https://pypi.org/simple"} version = "3.1.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/27/fb/576f067976d320f5f0114a8d9fa1215425441bb35627b1993e5afd8111e5/cloudpickle-3.1.2.tar.gz", hash = "sha256:7fda9eb655c9c230dab534f1983763de5835249750e85fbcef43aaa30a9a2414", size = 22330, upload-time = "2025-11-03T09:25:26.604Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl", hash = "sha256:9acb47f6afd73f60dc1df93bb801b472f05ff42fa6c84167d25cb206be1fbf4a", size = 22228, upload-time = "2025-11-03T09:25:25.534Z" }, + {url = "https://files.pythonhosted.org/packages/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl", hash = "sha256:9acb47f6afd73f60dc1df93bb801b472f05ff42fa6c84167d25cb206be1fbf4a", size = 22228, upload-time = "2025-11-03T09:25:25.534Z"} ] [[package]] name = "colorama" +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"} +source = {registry = "https://pypi.org/simple"} 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" }, + {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]] +dependencies = [ + {name = "numpy"} +] name = "contourpy" +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"} +source = {registry = "https://pypi.org/simple"} 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/91/2e/c4390a31919d8a78b90e8ecf87cd4b4c4f05a5b48d05ec17db8e5404c6f4/contourpy-1.3.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:709a48ef9a690e1343202916450bc48b9e51c049b089c7f79a267b46cffcdaa1", size = 288773, upload-time = "2025-07-26T12:01:02.277Z" }, - { url = "https://files.pythonhosted.org/packages/0d/44/c4b0b6095fef4dc9c420e041799591e3b63e9619e3044f7f4f6c21c0ab24/contourpy-1.3.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:23416f38bfd74d5d28ab8429cc4d63fa67d5068bd711a85edb1c3fb0c3e2f381", size = 270149, upload-time = "2025-07-26T12:01:04.072Z" }, - { url = "https://files.pythonhosted.org/packages/30/2e/dd4ced42fefac8470661d7cb7e264808425e6c5d56d175291e93890cce09/contourpy-1.3.3-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:929ddf8c4c7f348e4c0a5a3a714b5c8542ffaa8c22954862a46ca1813b667ee7", size = 329222, upload-time = "2025-07-26T12:01:05.688Z" }, - { url = "https://files.pythonhosted.org/packages/f2/74/cc6ec2548e3d276c71389ea4802a774b7aa3558223b7bade3f25787fafc2/contourpy-1.3.3-cp311-cp311-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9e999574eddae35f1312c2b4b717b7885d4edd6cb46700e04f7f02db454e67c1", size = 377234, upload-time = "2025-07-26T12:01:07.054Z" }, - { url = "https://files.pythonhosted.org/packages/03/b3/64ef723029f917410f75c09da54254c5f9ea90ef89b143ccadb09df14c15/contourpy-1.3.3-cp311-cp311-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0bf67e0e3f482cb69779dd3061b534eb35ac9b17f163d851e2a547d56dba0a3a", size = 380555, upload-time = "2025-07-26T12:01:08.801Z" }, - { url = "https://files.pythonhosted.org/packages/5f/4b/6157f24ca425b89fe2eb7e7be642375711ab671135be21e6faa100f7448c/contourpy-1.3.3-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:51e79c1f7470158e838808d4a996fa9bac72c498e93d8ebe5119bc1e6becb0db", size = 355238, upload-time = "2025-07-26T12:01:10.319Z" }, - { url = "https://files.pythonhosted.org/packages/98/56/f914f0dd678480708a04cfd2206e7c382533249bc5001eb9f58aa693e200/contourpy-1.3.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:598c3aaece21c503615fd59c92a3598b428b2f01bfb4b8ca9c4edeecc2438620", size = 1326218, upload-time = "2025-07-26T12:01:12.659Z" }, - { url = "https://files.pythonhosted.org/packages/fb/d7/4a972334a0c971acd5172389671113ae82aa7527073980c38d5868ff1161/contourpy-1.3.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:322ab1c99b008dad206d406bb61d014cf0174df491ae9d9d0fac6a6fda4f977f", size = 1392867, upload-time = "2025-07-26T12:01:15.533Z" }, - { url = "https://files.pythonhosted.org/packages/75/3e/f2cc6cd56dc8cff46b1a56232eabc6feea52720083ea71ab15523daab796/contourpy-1.3.3-cp311-cp311-win32.whl", hash = "sha256:fd907ae12cd483cd83e414b12941c632a969171bf90fc937d0c9f268a31cafff", size = 183677, upload-time = "2025-07-26T12:01:17.088Z" }, - { url = "https://files.pythonhosted.org/packages/98/4b/9bd370b004b5c9d8045c6c33cf65bae018b27aca550a3f657cdc99acdbd8/contourpy-1.3.3-cp311-cp311-win_amd64.whl", hash = "sha256:3519428f6be58431c56581f1694ba8e50626f2dd550af225f82fb5f5814d2a42", size = 225234, upload-time = "2025-07-26T12:01:18.256Z" }, - { url = "https://files.pythonhosted.org/packages/d9/b6/71771e02c2e004450c12b1120a5f488cad2e4d5b590b1af8bad060360fe4/contourpy-1.3.3-cp311-cp311-win_arm64.whl", hash = "sha256:15ff10bfada4bf92ec8b31c62bf7c1834c244019b4a33095a68000d7075df470", size = 193123, upload-time = "2025-07-26T12:01:19.848Z" }, - { url = "https://files.pythonhosted.org/packages/be/45/adfee365d9ea3d853550b2e735f9d66366701c65db7855cd07621732ccfc/contourpy-1.3.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b08a32ea2f8e42cf1d4be3169a98dd4be32bafe4f22b6c4cb4ba810fa9e5d2cb", size = 293419, upload-time = "2025-07-26T12:01:21.16Z" }, - { url = "https://files.pythonhosted.org/packages/53/3e/405b59cfa13021a56bba395a6b3aca8cec012b45bf177b0eaf7a202cde2c/contourpy-1.3.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:556dba8fb6f5d8742f2923fe9457dbdd51e1049c4a43fd3986a0b14a1d815fc6", size = 273979, upload-time = "2025-07-26T12:01:22.448Z" }, - { url = "https://files.pythonhosted.org/packages/d4/1c/a12359b9b2ca3a845e8f7f9ac08bdf776114eb931392fcad91743e2ea17b/contourpy-1.3.3-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:92d9abc807cf7d0e047b95ca5d957cf4792fcd04e920ca70d48add15c1a90ea7", size = 332653, upload-time = "2025-07-26T12:01:24.155Z" }, - { url = "https://files.pythonhosted.org/packages/63/12/897aeebfb475b7748ea67b61e045accdfcf0d971f8a588b67108ed7f5512/contourpy-1.3.3-cp312-cp312-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b2e8faa0ed68cb29af51edd8e24798bb661eac3bd9f65420c1887b6ca89987c8", size = 379536, upload-time = "2025-07-26T12:01:25.91Z" }, - { url = "https://files.pythonhosted.org/packages/43/8a/a8c584b82deb248930ce069e71576fc09bd7174bbd35183b7943fb1064fd/contourpy-1.3.3-cp312-cp312-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:626d60935cf668e70a5ce6ff184fd713e9683fb458898e4249b63be9e28286ea", size = 384397, upload-time = "2025-07-26T12:01:27.152Z" }, - { url = "https://files.pythonhosted.org/packages/cc/8f/ec6289987824b29529d0dfda0d74a07cec60e54b9c92f3c9da4c0ac732de/contourpy-1.3.3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4d00e655fcef08aba35ec9610536bfe90267d7ab5ba944f7032549c55a146da1", size = 362601, upload-time = "2025-07-26T12:01:28.808Z" }, - { url = "https://files.pythonhosted.org/packages/05/0a/a3fe3be3ee2dceb3e615ebb4df97ae6f3828aa915d3e10549ce016302bd1/contourpy-1.3.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:451e71b5a7d597379ef572de31eeb909a87246974d960049a9848c3bc6c41bf7", size = 1331288, upload-time = "2025-07-26T12:01:31.198Z" }, - { url = "https://files.pythonhosted.org/packages/33/1d/acad9bd4e97f13f3e2b18a3977fe1b4a37ecf3d38d815333980c6c72e963/contourpy-1.3.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:459c1f020cd59fcfe6650180678a9993932d80d44ccde1fa1868977438f0b411", size = 1403386, upload-time = "2025-07-26T12:01:33.947Z" }, - { url = "https://files.pythonhosted.org/packages/cf/8f/5847f44a7fddf859704217a99a23a4f6417b10e5ab1256a179264561540e/contourpy-1.3.3-cp312-cp312-win32.whl", hash = "sha256:023b44101dfe49d7d53932be418477dba359649246075c996866106da069af69", size = 185018, upload-time = "2025-07-26T12:01:35.64Z" }, - { url = "https://files.pythonhosted.org/packages/19/e8/6026ed58a64563186a9ee3f29f41261fd1828f527dd93d33b60feca63352/contourpy-1.3.3-cp312-cp312-win_amd64.whl", hash = "sha256:8153b8bfc11e1e4d75bcb0bff1db232f9e10b274e0929de9d608027e0d34ff8b", size = 226567, upload-time = "2025-07-26T12:01:36.804Z" }, - { url = "https://files.pythonhosted.org/packages/d1/e2/f05240d2c39a1ed228d8328a78b6f44cd695f7ef47beb3e684cf93604f86/contourpy-1.3.3-cp312-cp312-win_arm64.whl", hash = "sha256:07ce5ed73ecdc4a03ffe3e1b3e3c1166db35ae7584be76f65dbbe28a7791b0cc", size = 193655, upload-time = "2025-07-26T12:01:37.999Z" }, - { 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" }, - { url = "https://files.pythonhosted.org/packages/a5/29/8dcfe16f0107943fa92388c23f6e05cff0ba58058c4c95b00280d4c75a14/contourpy-1.3.3-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:cd5dfcaeb10f7b7f9dc8941717c6c2ade08f587be2226222c12b25f0483ed497", size = 278809, upload-time = "2025-07-26T12:02:52.74Z" }, - { url = "https://files.pythonhosted.org/packages/85/a9/8b37ef4f7dafeb335daee3c8254645ef5725be4d9c6aa70b50ec46ef2f7e/contourpy-1.3.3-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:0c1fc238306b35f246d61a1d416a627348b5cf0648648a031e14bb8705fcdfe8", size = 261593, upload-time = "2025-07-26T12:02:54.037Z" }, - { url = "https://files.pythonhosted.org/packages/0a/59/ebfb8c677c75605cc27f7122c90313fd2f375ff3c8d19a1694bda74aaa63/contourpy-1.3.3-pp311-pypy311_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:70f9aad7de812d6541d29d2bbf8feb22ff7e1c299523db288004e3157ff4674e", size = 302202, upload-time = "2025-07-26T12:02:55.947Z" }, - { url = "https://files.pythonhosted.org/packages/3c/37/21972a15834d90bfbfb009b9d004779bd5a07a0ec0234e5ba8f64d5736f4/contourpy-1.3.3-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5ed3657edf08512fc3fe81b510e35c2012fbd3081d2e26160f27ca28affec989", size = 329207, upload-time = "2025-07-26T12:02:57.468Z" }, - { url = "https://files.pythonhosted.org/packages/0c/58/bd257695f39d05594ca4ad60df5bcb7e32247f9951fd09a9b8edb82d1daa/contourpy-1.3.3-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:3d1a3799d62d45c18bafd41c5fa05120b96a28079f2393af559b843d1a966a77", size = 225315, upload-time = "2025-07-26T12:02:58.801Z" }, +wheels = [ + {url = "https://files.pythonhosted.org/packages/91/2e/c4390a31919d8a78b90e8ecf87cd4b4c4f05a5b48d05ec17db8e5404c6f4/contourpy-1.3.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:709a48ef9a690e1343202916450bc48b9e51c049b089c7f79a267b46cffcdaa1", size = 288773, upload-time = "2025-07-26T12:01:02.277Z"}, + {url = "https://files.pythonhosted.org/packages/0d/44/c4b0b6095fef4dc9c420e041799591e3b63e9619e3044f7f4f6c21c0ab24/contourpy-1.3.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:23416f38bfd74d5d28ab8429cc4d63fa67d5068bd711a85edb1c3fb0c3e2f381", size = 270149, upload-time = "2025-07-26T12:01:04.072Z"}, + {url = "https://files.pythonhosted.org/packages/30/2e/dd4ced42fefac8470661d7cb7e264808425e6c5d56d175291e93890cce09/contourpy-1.3.3-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:929ddf8c4c7f348e4c0a5a3a714b5c8542ffaa8c22954862a46ca1813b667ee7", size = 329222, upload-time = "2025-07-26T12:01:05.688Z"}, + {url = "https://files.pythonhosted.org/packages/f2/74/cc6ec2548e3d276c71389ea4802a774b7aa3558223b7bade3f25787fafc2/contourpy-1.3.3-cp311-cp311-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9e999574eddae35f1312c2b4b717b7885d4edd6cb46700e04f7f02db454e67c1", size = 377234, upload-time = "2025-07-26T12:01:07.054Z"}, + {url = "https://files.pythonhosted.org/packages/03/b3/64ef723029f917410f75c09da54254c5f9ea90ef89b143ccadb09df14c15/contourpy-1.3.3-cp311-cp311-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0bf67e0e3f482cb69779dd3061b534eb35ac9b17f163d851e2a547d56dba0a3a", size = 380555, upload-time = "2025-07-26T12:01:08.801Z"}, + {url = "https://files.pythonhosted.org/packages/5f/4b/6157f24ca425b89fe2eb7e7be642375711ab671135be21e6faa100f7448c/contourpy-1.3.3-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:51e79c1f7470158e838808d4a996fa9bac72c498e93d8ebe5119bc1e6becb0db", size = 355238, upload-time = "2025-07-26T12:01:10.319Z"}, + {url = "https://files.pythonhosted.org/packages/98/56/f914f0dd678480708a04cfd2206e7c382533249bc5001eb9f58aa693e200/contourpy-1.3.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:598c3aaece21c503615fd59c92a3598b428b2f01bfb4b8ca9c4edeecc2438620", size = 1326218, upload-time = "2025-07-26T12:01:12.659Z"}, + {url = "https://files.pythonhosted.org/packages/fb/d7/4a972334a0c971acd5172389671113ae82aa7527073980c38d5868ff1161/contourpy-1.3.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:322ab1c99b008dad206d406bb61d014cf0174df491ae9d9d0fac6a6fda4f977f", size = 1392867, upload-time = "2025-07-26T12:01:15.533Z"}, + {url = "https://files.pythonhosted.org/packages/75/3e/f2cc6cd56dc8cff46b1a56232eabc6feea52720083ea71ab15523daab796/contourpy-1.3.3-cp311-cp311-win32.whl", hash = "sha256:fd907ae12cd483cd83e414b12941c632a969171bf90fc937d0c9f268a31cafff", size = 183677, upload-time = "2025-07-26T12:01:17.088Z"}, + {url = "https://files.pythonhosted.org/packages/98/4b/9bd370b004b5c9d8045c6c33cf65bae018b27aca550a3f657cdc99acdbd8/contourpy-1.3.3-cp311-cp311-win_amd64.whl", hash = "sha256:3519428f6be58431c56581f1694ba8e50626f2dd550af225f82fb5f5814d2a42", size = 225234, upload-time = "2025-07-26T12:01:18.256Z"}, + {url = "https://files.pythonhosted.org/packages/d9/b6/71771e02c2e004450c12b1120a5f488cad2e4d5b590b1af8bad060360fe4/contourpy-1.3.3-cp311-cp311-win_arm64.whl", hash = "sha256:15ff10bfada4bf92ec8b31c62bf7c1834c244019b4a33095a68000d7075df470", size = 193123, upload-time = "2025-07-26T12:01:19.848Z"}, + {url = "https://files.pythonhosted.org/packages/be/45/adfee365d9ea3d853550b2e735f9d66366701c65db7855cd07621732ccfc/contourpy-1.3.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b08a32ea2f8e42cf1d4be3169a98dd4be32bafe4f22b6c4cb4ba810fa9e5d2cb", size = 293419, upload-time = "2025-07-26T12:01:21.16Z"}, + {url = "https://files.pythonhosted.org/packages/53/3e/405b59cfa13021a56bba395a6b3aca8cec012b45bf177b0eaf7a202cde2c/contourpy-1.3.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:556dba8fb6f5d8742f2923fe9457dbdd51e1049c4a43fd3986a0b14a1d815fc6", size = 273979, upload-time = "2025-07-26T12:01:22.448Z"}, + {url = "https://files.pythonhosted.org/packages/d4/1c/a12359b9b2ca3a845e8f7f9ac08bdf776114eb931392fcad91743e2ea17b/contourpy-1.3.3-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:92d9abc807cf7d0e047b95ca5d957cf4792fcd04e920ca70d48add15c1a90ea7", size = 332653, upload-time = "2025-07-26T12:01:24.155Z"}, + {url = "https://files.pythonhosted.org/packages/63/12/897aeebfb475b7748ea67b61e045accdfcf0d971f8a588b67108ed7f5512/contourpy-1.3.3-cp312-cp312-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b2e8faa0ed68cb29af51edd8e24798bb661eac3bd9f65420c1887b6ca89987c8", size = 379536, upload-time = "2025-07-26T12:01:25.91Z"}, + {url = "https://files.pythonhosted.org/packages/43/8a/a8c584b82deb248930ce069e71576fc09bd7174bbd35183b7943fb1064fd/contourpy-1.3.3-cp312-cp312-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:626d60935cf668e70a5ce6ff184fd713e9683fb458898e4249b63be9e28286ea", size = 384397, upload-time = "2025-07-26T12:01:27.152Z"}, + {url = "https://files.pythonhosted.org/packages/cc/8f/ec6289987824b29529d0dfda0d74a07cec60e54b9c92f3c9da4c0ac732de/contourpy-1.3.3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4d00e655fcef08aba35ec9610536bfe90267d7ab5ba944f7032549c55a146da1", size = 362601, upload-time = "2025-07-26T12:01:28.808Z"}, + {url = "https://files.pythonhosted.org/packages/05/0a/a3fe3be3ee2dceb3e615ebb4df97ae6f3828aa915d3e10549ce016302bd1/contourpy-1.3.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:451e71b5a7d597379ef572de31eeb909a87246974d960049a9848c3bc6c41bf7", size = 1331288, upload-time = "2025-07-26T12:01:31.198Z"}, + {url = "https://files.pythonhosted.org/packages/33/1d/acad9bd4e97f13f3e2b18a3977fe1b4a37ecf3d38d815333980c6c72e963/contourpy-1.3.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:459c1f020cd59fcfe6650180678a9993932d80d44ccde1fa1868977438f0b411", size = 1403386, upload-time = "2025-07-26T12:01:33.947Z"}, + {url = "https://files.pythonhosted.org/packages/cf/8f/5847f44a7fddf859704217a99a23a4f6417b10e5ab1256a179264561540e/contourpy-1.3.3-cp312-cp312-win32.whl", hash = "sha256:023b44101dfe49d7d53932be418477dba359649246075c996866106da069af69", size = 185018, upload-time = "2025-07-26T12:01:35.64Z"}, + {url = "https://files.pythonhosted.org/packages/19/e8/6026ed58a64563186a9ee3f29f41261fd1828f527dd93d33b60feca63352/contourpy-1.3.3-cp312-cp312-win_amd64.whl", hash = "sha256:8153b8bfc11e1e4d75bcb0bff1db232f9e10b274e0929de9d608027e0d34ff8b", size = 226567, upload-time = "2025-07-26T12:01:36.804Z"}, + {url = "https://files.pythonhosted.org/packages/d1/e2/f05240d2c39a1ed228d8328a78b6f44cd695f7ef47beb3e684cf93604f86/contourpy-1.3.3-cp312-cp312-win_arm64.whl", hash = "sha256:07ce5ed73ecdc4a03ffe3e1b3e3c1166db35ae7584be76f65dbbe28a7791b0cc", size = 193655, upload-time = "2025-07-26T12:01:37.999Z"}, + {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"}, + {url = "https://files.pythonhosted.org/packages/a5/29/8dcfe16f0107943fa92388c23f6e05cff0ba58058c4c95b00280d4c75a14/contourpy-1.3.3-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:cd5dfcaeb10f7b7f9dc8941717c6c2ade08f587be2226222c12b25f0483ed497", size = 278809, upload-time = "2025-07-26T12:02:52.74Z"}, + {url = "https://files.pythonhosted.org/packages/85/a9/8b37ef4f7dafeb335daee3c8254645ef5725be4d9c6aa70b50ec46ef2f7e/contourpy-1.3.3-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:0c1fc238306b35f246d61a1d416a627348b5cf0648648a031e14bb8705fcdfe8", size = 261593, upload-time = "2025-07-26T12:02:54.037Z"}, + {url = "https://files.pythonhosted.org/packages/0a/59/ebfb8c677c75605cc27f7122c90313fd2f375ff3c8d19a1694bda74aaa63/contourpy-1.3.3-pp311-pypy311_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:70f9aad7de812d6541d29d2bbf8feb22ff7e1c299523db288004e3157ff4674e", size = 302202, upload-time = "2025-07-26T12:02:55.947Z"}, + {url = "https://files.pythonhosted.org/packages/3c/37/21972a15834d90bfbfb009b9d004779bd5a07a0ec0234e5ba8f64d5736f4/contourpy-1.3.3-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5ed3657edf08512fc3fe81b510e35c2012fbd3081d2e26160f27ca28affec989", size = 329207, upload-time = "2025-07-26T12:02:57.468Z"}, + {url = "https://files.pythonhosted.org/packages/0c/58/bd257695f39d05594ca4ad60df5bcb7e32247f9951fd09a9b8edb82d1daa/contourpy-1.3.3-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:3d1a3799d62d45c18bafd41c5fa05120b96a28079f2393af559b843d1a966a77", size = 225315, upload-time = "2025-07-26T12:02:58.801Z"} ] [[package]] -name = "dask" -version = "2026.1.2" -source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "click" }, - { name = "cloudpickle" }, - { name = "fsspec" }, - { name = "importlib-metadata", marker = "python_full_version < '3.12'" }, - { name = "packaging" }, - { name = "partd" }, - { name = "pyyaml" }, - { name = "toolz" }, + {name = "click"}, + {name = "cloudpickle"}, + {name = "fsspec"}, + {name = "importlib-metadata", marker = "python_full_version < '3.12'"}, + {name = "packaging"}, + {name = "partd"}, + {name = "pyyaml"}, + {name = "toolz"} ] -sdist = { url = "https://files.pythonhosted.org/packages/bd/52/b0f9172b22778def907db1ff173249e4eb41f054b46a9c83b1528aaf811f/dask-2026.1.2.tar.gz", hash = "sha256:1136683de2750d98ea792670f7434e6c1cfce90cab2cc2f2495a9e60fd25a4fc", size = 10997838, upload-time = "2026-01-30T21:04:20.54Z" } +name = "dask" +sdist = {url = "https://files.pythonhosted.org/packages/bd/52/b0f9172b22778def907db1ff173249e4eb41f054b46a9c83b1528aaf811f/dask-2026.1.2.tar.gz", hash = "sha256:1136683de2750d98ea792670f7434e6c1cfce90cab2cc2f2495a9e60fd25a4fc", size = 10997838, upload-time = "2026-01-30T21:04:20.54Z"} +source = {registry = "https://pypi.org/simple"} +version = "2026.1.2" wheels = [ - { url = "https://files.pythonhosted.org/packages/e5/23/d39ccc4ed76222db31530b0a7d38876fdb7673e23f838e8d8f0ed4651a4f/dask-2026.1.2-py3-none-any.whl", hash = "sha256:46a0cf3b8d87f78a3d2e6b145aea4418a6d6d606fe6a16c79bd8ca2bb862bc91", size = 1482084, upload-time = "2026-01-30T21:04:18.363Z" }, + {url = "https://files.pythonhosted.org/packages/e5/23/d39ccc4ed76222db31530b0a7d38876fdb7673e23f838e8d8f0ed4651a4f/dask-2026.1.2-py3-none-any.whl", hash = "sha256:46a0cf3b8d87f78a3d2e6b145aea4418a6d6d606fe6a16c79bd8ca2bb862bc91", size = 1482084, upload-time = "2026-01-30T21:04:18.363Z"} ] [[package]] name = "decorator" +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"} +source = {registry = "https://pypi.org/simple"} 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" }, + {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 = "deprecation" -version = "2.1.0" -source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "packaging" }, + {name = "packaging"} ] -sdist = { url = "https://files.pythonhosted.org/packages/5a/d3/8ae2869247df154b64c1884d7346d412fed0c49df84db635aab2d1c40e62/deprecation-2.1.0.tar.gz", hash = "sha256:72b3bde64e5d778694b0cf68178aed03d15e15477116add3fb773e581f9518ff", size = 173788, upload-time = "2020-04-20T14:23:38.738Z" } +name = "deprecation" +sdist = {url = "https://files.pythonhosted.org/packages/5a/d3/8ae2869247df154b64c1884d7346d412fed0c49df84db635aab2d1c40e62/deprecation-2.1.0.tar.gz", hash = "sha256:72b3bde64e5d778694b0cf68178aed03d15e15477116add3fb773e581f9518ff", size = 173788, upload-time = "2020-04-20T14:23:38.738Z"} +source = {registry = "https://pypi.org/simple"} +version = "2.1.0" wheels = [ - { url = "https://files.pythonhosted.org/packages/02/c3/253a89ee03fc9b9682f1541728eb66db7db22148cd94f89ab22528cd1e1b/deprecation-2.1.0-py2.py3-none-any.whl", hash = "sha256:a10811591210e1fb0e768a8c25517cabeabcba6f0bf96564f8ff45189f90b14a", size = 11178, upload-time = "2020-04-20T14:23:36.581Z" }, + {url = "https://files.pythonhosted.org/packages/02/c3/253a89ee03fc9b9682f1541728eb66db7db22148cd94f89ab22528cd1e1b/deprecation-2.1.0-py2.py3-none-any.whl", hash = "sha256:a10811591210e1fb0e768a8c25517cabeabcba6f0bf96564f8ff45189f90b14a", size = 11178, upload-time = "2020-04-20T14:23:36.581Z"} ] [[package]] name = "dill" +sdist = {url = "https://files.pythonhosted.org/packages/81/e1/56027a71e31b02ddc53c7d65b01e68edf64dea2932122fe7746a516f75d5/dill-0.4.1.tar.gz", hash = "sha256:423092df4182177d4d8ba8290c8a5b640c66ab35ec7da59ccfa00f6fa3eea5fa", size = 187315, upload-time = "2026-01-19T02:36:56.85Z"} +source = {registry = "https://pypi.org/simple"} version = "0.4.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/81/e1/56027a71e31b02ddc53c7d65b01e68edf64dea2932122fe7746a516f75d5/dill-0.4.1.tar.gz", hash = "sha256:423092df4182177d4d8ba8290c8a5b640c66ab35ec7da59ccfa00f6fa3eea5fa", size = 187315, upload-time = "2026-01-19T02:36:56.85Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/1e/77/dc8c558f7593132cf8fefec57c4f60c83b16941c574ac5f619abb3ae7933/dill-0.4.1-py3-none-any.whl", hash = "sha256:1e1ce33e978ae97fcfcff5638477032b801c46c7c65cf717f95fbc2248f79a9d", size = 120019, upload-time = "2026-01-19T02:36:55.663Z" }, + {url = "https://files.pythonhosted.org/packages/1e/77/dc8c558f7593132cf8fefec57c4f60c83b16941c574ac5f619abb3ae7933/dill-0.4.1-py3-none-any.whl", hash = "sha256:1e1ce33e978ae97fcfcff5638477032b801c46c7c65cf717f95fbc2248f79a9d", size = 120019, upload-time = "2026-01-19T02:36:55.663Z"} ] [[package]] +dependencies = [ + {name = "cfgrib"}, + {name = "dask"}, + {name = "deprecation"}, + {name = "earthkit-meteo"}, + {name = "earthkit-utils"}, + {name = "eccodes"}, + {name = "entrypoints"}, + {name = "filelock"}, + {name = "jinja2"}, + {name = "jsonschema"}, + {name = "lru-dict"}, + {name = "markdown"}, + {name = "multiurl"}, + {name = "netcdf4"}, + {name = "pandas"}, + {name = "pdbufr"}, + {name = "pyyaml"}, + {name = "tqdm"}, + {name = "xarray"} +] name = "earthkit-data" +sdist = {url = "https://files.pythonhosted.org/packages/9d/5a/8bb64690a3e920a39ec45c031dde104a3de0ebb86c24376e98cf332ecb9a/earthkit_data-0.19.0.tar.gz", hash = "sha256:2dedfc97a207b28c752ba0ed754313485b46adc40d244062504efb808267c58a", size = 5653925, upload-time = "2026-02-16T10:24:47.766Z"} +source = {registry = "https://pypi.org/simple"} version = "0.19.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "cfgrib" }, - { name = "dask" }, - { name = "deprecation" }, - { name = "earthkit-meteo" }, - { name = "earthkit-utils" }, - { name = "eccodes" }, - { name = "entrypoints" }, - { name = "filelock" }, - { name = "jinja2" }, - { name = "jsonschema" }, - { name = "lru-dict" }, - { name = "markdown" }, - { name = "multiurl" }, - { name = "netcdf4" }, - { name = "pandas" }, - { name = "pdbufr" }, - { name = "pyyaml" }, - { name = "tqdm" }, - { name = "xarray" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/9d/5a/8bb64690a3e920a39ec45c031dde104a3de0ebb86c24376e98cf332ecb9a/earthkit_data-0.19.0.tar.gz", hash = "sha256:2dedfc97a207b28c752ba0ed754313485b46adc40d244062504efb808267c58a", size = 5653925, upload-time = "2026-02-16T10:24:47.766Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/eb/b7/e6b466edd0438b9e3d875a98d0aeb2cdf89acbfd4eaaf5906d2456341e2c/earthkit_data-0.19.0-py3-none-any.whl", hash = "sha256:3697238beeeec94209ecb86ac133bdd6c3f66dad734955edd3c0fd07bc5875e1", size = 396017, upload-time = "2026-02-16T10:24:46.212Z" }, +wheels = [ + {url = "https://files.pythonhosted.org/packages/eb/b7/e6b466edd0438b9e3d875a98d0aeb2cdf89acbfd4eaaf5906d2456341e2c/earthkit_data-0.19.0-py3-none-any.whl", hash = "sha256:3697238beeeec94209ecb86ac133bdd6c3f66dad734955edd3c0fd07bc5875e1", size = 396017, upload-time = "2026-02-16T10:24:46.212Z"} ] [[package]] -name = "earthkit-meteo" -version = "0.6.1" -source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "earthkit-utils" }, - { name = "numpy" }, + {name = "earthkit-utils"}, + {name = "numpy"} ] -sdist = { url = "https://files.pythonhosted.org/packages/43/89/324733e6b2a02d4c336e4579c8899d301ba3b576a8a540071cd095b38183/earthkit_meteo-0.6.1.tar.gz", hash = "sha256:82a89983c8ed9302ca07fc040c2787033c98188ce75fe9332f5ca7808379c60e", size = 370291, upload-time = "2026-02-18T16:04:11.567Z" } +name = "earthkit-meteo" +sdist = {url = "https://files.pythonhosted.org/packages/43/89/324733e6b2a02d4c336e4579c8899d301ba3b576a8a540071cd095b38183/earthkit_meteo-0.6.1.tar.gz", hash = "sha256:82a89983c8ed9302ca07fc040c2787033c98188ce75fe9332f5ca7808379c60e", size = 370291, upload-time = "2026-02-18T16:04:11.567Z"} +source = {registry = "https://pypi.org/simple"} +version = "0.6.1" wheels = [ - { url = "https://files.pythonhosted.org/packages/34/eb/c10deda542516f679a20f1cb641a13094fc9e80bc13e54f4cebcfb9f8173/earthkit_meteo-0.6.1-py3-none-any.whl", hash = "sha256:fcb425e23d1827d2fd85ad4b31bfd41eb8f1dcfc7fb78da4b03d69037e8e1d49", size = 57080, upload-time = "2026-02-18T16:04:10.074Z" }, + {url = "https://files.pythonhosted.org/packages/34/eb/c10deda542516f679a20f1cb641a13094fc9e80bc13e54f4cebcfb9f8173/earthkit_meteo-0.6.1-py3-none-any.whl", hash = "sha256:fcb425e23d1827d2fd85ad4b31bfd41eb8f1dcfc7fb78da4b03d69037e8e1d49", size = 57080, upload-time = "2026-02-18T16:04:10.074Z"} ] [[package]] -name = "earthkit-utils" -version = "0.2.1" -source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "array-api-compat" }, + {name = "array-api-compat"} ] -sdist = { url = "https://files.pythonhosted.org/packages/96/6c/f78f7288f3e7a5ba376ec2e35c051f567e796ab7eef75695b02044e81c2c/earthkit_utils-0.2.1.tar.gz", hash = "sha256:f7607aa5d9d418554dc53dc1e140fbd86cdf5f26a6a009168834742ef779f323", size = 24475, upload-time = "2026-02-17T12:58:41.354Z" } +name = "earthkit-utils" +sdist = {url = "https://files.pythonhosted.org/packages/96/6c/f78f7288f3e7a5ba376ec2e35c051f567e796ab7eef75695b02044e81c2c/earthkit_utils-0.2.1.tar.gz", hash = "sha256:f7607aa5d9d418554dc53dc1e140fbd86cdf5f26a6a009168834742ef779f323", size = 24475, upload-time = "2026-02-17T12:58:41.354Z"} +source = {registry = "https://pypi.org/simple"} +version = "0.2.1" wheels = [ - { url = "https://files.pythonhosted.org/packages/ac/24/1f869196bceb97a702e938a36f0e24593b640cebe4fffae9b39975d24ab9/earthkit_utils-0.2.1-py3-none-any.whl", hash = "sha256:0a26cad5d6505afb187afd0f3f50545cd81c65a590f41302b292caba179d81da", size = 25410, upload-time = "2026-02-17T12:58:40.423Z" }, + {url = "https://files.pythonhosted.org/packages/ac/24/1f869196bceb97a702e938a36f0e24593b640cebe4fffae9b39975d24ab9/earthkit_utils-0.2.1-py3-none-any.whl", hash = "sha256:0a26cad5d6505afb187afd0f3f50545cd81c65a590f41302b292caba179d81da", size = 25410, upload-time = "2026-02-17T12:58:40.423Z"} ] [[package]] -name = "earthkit-workflows" -source = { editable = "." } dependencies = [ - { name = "array-api-compat" }, - { name = "cloudpickle" }, - { name = "dill" }, - { name = "earthkit-data" }, - { name = "fire" }, - { name = "networkx" }, - { name = "numpy" }, - { name = "orjson" }, - { name = "pydantic" }, - { name = "pyrsistent" }, - { name = "pyvis" }, - { name = "pyzmq" }, - { name = "qubed" }, - { name = "sortedcontainers" }, - { name = "xarray" }, + {name = "array-api-compat"}, + {name = "cloudpickle"}, + {name = "dill"}, + {name = "earthkit-data"}, + {name = "fire"}, + {name = "networkx"}, + {name = "numpy"}, + {name = "orjson"}, + {name = "pydantic"}, + {name = "pyrsistent"}, + {name = "pyvis"}, + {name = "pyzmq"}, + {name = "qubed"}, + {name = "sortedcontainers"}, + {name = "xarray"} ] +name = "earthkit-workflows" +source = {editable = "."} [package.dev-dependencies] dev = [ - { name = "bokeh" }, - { name = "build" }, - { name = "prek" }, - { name = "pytest" }, - { name = "pytest-xdist" }, - { name = "ty" }, + {name = "bokeh"}, + {name = "build"}, + {name = "prek"}, + {name = "pytest"}, + {name = "pytest-xdist"}, + {name = "ty"} ] [package.metadata] requires-dist = [ - { name = "array-api-compat" }, - { name = "cloudpickle" }, - { name = "dill" }, - { name = "earthkit-data" }, - { name = "fire" }, - { name = "networkx" }, - { name = "numpy" }, - { name = "orjson" }, - { name = "pydantic" }, - { name = "pyrsistent" }, - { name = "pyvis" }, - { name = "pyzmq" }, - { name = "qubed", specifier = ">=0.3.0" }, - { name = "sortedcontainers" }, - { name = "xarray" }, + {name = "array-api-compat"}, + {name = "cloudpickle"}, + {name = "dill"}, + {name = "earthkit-data"}, + {name = "fire"}, + {name = "networkx"}, + {name = "numpy"}, + {name = "orjson"}, + {name = "pydantic"}, + {name = "pyrsistent"}, + {name = "pyvis"}, + {name = "pyzmq"}, + {name = "qubed", specifier = ">=0.3.0"}, + {name = "sortedcontainers"}, + {name = "xarray"} ] [package.metadata.requires-dev] dev = [ - { name = "bokeh" }, - { name = "build" }, - { name = "prek" }, - { name = "pytest" }, - { name = "pytest-xdist", specifier = ">=3.8" }, - { name = "ty", specifier = "==0.0.2" }, + {name = "bokeh"}, + {name = "build"}, + {name = "prek"}, + {name = "pytest"}, + {name = "pytest-xdist", specifier = ">=3.8"}, + {name = "ty", specifier = "==0.0.2"} ] [[package]] -name = "eccodes" -version = "2.45.0" -source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "attrs" }, - { name = "cffi" }, - { name = "findlibs" }, - { name = "numpy" }, + {name = "attrs"}, + {name = "cffi"}, + {name = "findlibs"}, + {name = "numpy"} ] -sdist = { url = "https://files.pythonhosted.org/packages/e5/c3/41378ba5547fbbb08db9efc7c520bfd0ccf2684bf7fbba0e09eab53b9eff/eccodes-2.45.0.tar.gz", hash = "sha256:08fe1544e6fa597a416bde9a630af4b6e34a021bc3c209f0ece4f7ed5990f992", size = 2466789, upload-time = "2026-01-15T16:27:08.418Z" } +name = "eccodes" +sdist = {url = "https://files.pythonhosted.org/packages/e5/c3/41378ba5547fbbb08db9efc7c520bfd0ccf2684bf7fbba0e09eab53b9eff/eccodes-2.45.0.tar.gz", hash = "sha256:08fe1544e6fa597a416bde9a630af4b6e34a021bc3c209f0ece4f7ed5990f992", size = 2466789, upload-time = "2026-01-15T16:27:08.418Z"} +source = {registry = "https://pypi.org/simple"} +version = "2.45.0" wheels = [ - { url = "https://files.pythonhosted.org/packages/ad/1b/903f014d0645811253384f2056f00e9a1c8936a4c158c83f69acf564a4ec/eccodes-2.45.0-cp311-cp311-win_amd64.whl", hash = "sha256:99162409c6ff7e1c2a4836ad246c54ffab8157b6a738e4ed856cf236ea0a8c6e", size = 7406737, upload-time = "2026-01-15T16:26:39.928Z" }, - { url = "https://files.pythonhosted.org/packages/76/2a/721b05d551f90ed198aa05c2455fd056f4f1742967cee154347eaada2745/eccodes-2.45.0-cp312-cp312-win_amd64.whl", hash = "sha256:b661ce2d0e73ce0724f137606bf6b579fb2eba4db0f5b466b4345170cb4bf5f2", size = 7406814, upload-time = "2026-01-15T16:26:42.454Z" }, - { url = "https://files.pythonhosted.org/packages/6b/33/3dceb280fbbacb10f8f1e2e1a249a7fd80ce7cc532b69d56c981df21a348/eccodes-2.45.0-cp313-cp313-win_amd64.whl", hash = "sha256:2f07d8892cca722cf67528d3f82d25c851f298cb9b9c6de4c79cb8698857a8ef", size = 7406811, upload-time = "2026-01-15T16:26:39.689Z" }, - { url = "https://files.pythonhosted.org/packages/7f/40/0a42c7441d76c373a7bef7ec1f535f26910a8c82a37e745ffcd3ea0cdf79/eccodes-2.45.0-py3-none-any.whl", hash = "sha256:0ba61dbd2844843f1fd466c8ca24107932cc40088338f6176428cf38c533c08c", size = 91433, upload-time = "2026-01-15T16:27:06.601Z" }, + {url = "https://files.pythonhosted.org/packages/ad/1b/903f014d0645811253384f2056f00e9a1c8936a4c158c83f69acf564a4ec/eccodes-2.45.0-cp311-cp311-win_amd64.whl", hash = "sha256:99162409c6ff7e1c2a4836ad246c54ffab8157b6a738e4ed856cf236ea0a8c6e", size = 7406737, upload-time = "2026-01-15T16:26:39.928Z"}, + {url = "https://files.pythonhosted.org/packages/76/2a/721b05d551f90ed198aa05c2455fd056f4f1742967cee154347eaada2745/eccodes-2.45.0-cp312-cp312-win_amd64.whl", hash = "sha256:b661ce2d0e73ce0724f137606bf6b579fb2eba4db0f5b466b4345170cb4bf5f2", size = 7406814, upload-time = "2026-01-15T16:26:42.454Z"}, + {url = "https://files.pythonhosted.org/packages/6b/33/3dceb280fbbacb10f8f1e2e1a249a7fd80ce7cc532b69d56c981df21a348/eccodes-2.45.0-cp313-cp313-win_amd64.whl", hash = "sha256:2f07d8892cca722cf67528d3f82d25c851f298cb9b9c6de4c79cb8698857a8ef", size = 7406811, upload-time = "2026-01-15T16:26:39.689Z"}, + {url = "https://files.pythonhosted.org/packages/7f/40/0a42c7441d76c373a7bef7ec1f535f26910a8c82a37e745ffcd3ea0cdf79/eccodes-2.45.0-py3-none-any.whl", hash = "sha256:0ba61dbd2844843f1fd466c8ca24107932cc40088338f6176428cf38c533c08c", size = 91433, upload-time = "2026-01-15T16:27:06.601Z"} ] [[package]] name = "entrypoints" +sdist = {url = "https://files.pythonhosted.org/packages/ea/8d/a7121ffe5f402dc015277d2d31eb82d2187334503a011c18f2e78ecbb9b2/entrypoints-0.4.tar.gz", hash = "sha256:b706eddaa9218a19ebcd67b56818f05bb27589b1ca9e8d797b74affad4ccacd4", size = 13974, upload-time = "2022-02-02T21:30:28.172Z"} +source = {registry = "https://pypi.org/simple"} version = "0.4" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ea/8d/a7121ffe5f402dc015277d2d31eb82d2187334503a011c18f2e78ecbb9b2/entrypoints-0.4.tar.gz", hash = "sha256:b706eddaa9218a19ebcd67b56818f05bb27589b1ca9e8d797b74affad4ccacd4", size = 13974, upload-time = "2022-02-02T21:30:28.172Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/35/a8/365059bbcd4572cbc41de17fd5b682be5868b218c3c5479071865cab9078/entrypoints-0.4-py3-none-any.whl", hash = "sha256:f174b5ff827504fd3cd97cc3f8649f3693f51538c7e4bdf3ef002c8429d42f9f", size = 5294, upload-time = "2022-02-02T21:30:26.024Z" }, + {url = "https://files.pythonhosted.org/packages/35/a8/365059bbcd4572cbc41de17fd5b682be5868b218c3c5479071865cab9078/entrypoints-0.4-py3-none-any.whl", hash = "sha256:f174b5ff827504fd3cd97cc3f8649f3693f51538c7e4bdf3ef002c8429d42f9f", size = 5294, upload-time = "2022-02-02T21:30:26.024Z"} ] [[package]] name = "execnet" +sdist = {url = "https://files.pythonhosted.org/packages/bf/89/780e11f9588d9e7128a3f87788354c7946a9cbb1401ad38a48c4db9a4f07/execnet-2.1.2.tar.gz", hash = "sha256:63d83bfdd9a23e35b9c6a3261412324f964c2ec8dcd8d3c6916ee9373e0befcd", size = 166622, upload-time = "2025-11-12T09:56:37.75Z"} +source = {registry = "https://pypi.org/simple"} version = "2.1.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/bf/89/780e11f9588d9e7128a3f87788354c7946a9cbb1401ad38a48c4db9a4f07/execnet-2.1.2.tar.gz", hash = "sha256:63d83bfdd9a23e35b9c6a3261412324f964c2ec8dcd8d3c6916ee9373e0befcd", size = 166622, upload-time = "2025-11-12T09:56:37.75Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ab/84/02fc1827e8cdded4aa65baef11296a9bbe595c474f0d6d758af082d849fd/execnet-2.1.2-py3-none-any.whl", hash = "sha256:67fba928dd5a544b783f6056f449e5e3931a5c378b128bc18501f7ea79e296ec", size = 40708, upload-time = "2025-11-12T09:56:36.333Z" }, + {url = "https://files.pythonhosted.org/packages/ab/84/02fc1827e8cdded4aa65baef11296a9bbe595c474f0d6d758af082d849fd/execnet-2.1.2-py3-none-any.whl", hash = "sha256:67fba928dd5a544b783f6056f449e5e3931a5c378b128bc18501f7ea79e296ec", size = 40708, upload-time = "2025-11-12T09:56:36.333Z"} ] [[package]] name = "executing" +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"} +source = {registry = "https://pypi.org/simple"} 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" }, + {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 = "filelock" +sdist = {url = "https://files.pythonhosted.org/packages/73/92/a8e2479937ff39185d20dd6a851c1a63e55849e447a55e798cc2e1f49c65/filelock-3.24.3.tar.gz", hash = "sha256:011a5644dc937c22699943ebbfc46e969cdde3e171470a6e40b9533e5a72affa", size = 37935, upload-time = "2026-02-19T00:48:20.543Z"} +source = {registry = "https://pypi.org/simple"} version = "3.24.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/73/92/a8e2479937ff39185d20dd6a851c1a63e55849e447a55e798cc2e1f49c65/filelock-3.24.3.tar.gz", hash = "sha256:011a5644dc937c22699943ebbfc46e969cdde3e171470a6e40b9533e5a72affa", size = 37935, upload-time = "2026-02-19T00:48:20.543Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/9c/0f/5d0c71a1aefeb08efff26272149e07ab922b64f46c63363756224bd6872e/filelock-3.24.3-py3-none-any.whl", hash = "sha256:426e9a4660391f7f8a810d71b0555bce9008b0a1cc342ab1f6947d37639e002d", size = 24331, upload-time = "2026-02-19T00:48:18.465Z" }, + {url = "https://files.pythonhosted.org/packages/9c/0f/5d0c71a1aefeb08efff26272149e07ab922b64f46c63363756224bd6872e/filelock-3.24.3-py3-none-any.whl", hash = "sha256:426e9a4660391f7f8a810d71b0555bce9008b0a1cc342ab1f6947d37639e002d", size = 24331, upload-time = "2026-02-19T00:48:18.465Z"} ] [[package]] name = "findlibs" +sdist = {url = "https://files.pythonhosted.org/packages/22/ef/345b0f88b8e9d9e12051142a9cdcf590bf70206d20d81c3f773ade8d9e32/findlibs-0.1.2.tar.gz", hash = "sha256:1f56d220c69686392ebdc4c65b32ee344818bca633643a8c97592957d1728122", size = 11302, upload-time = "2025-07-28T09:15:03.675Z"} +source = {registry = "https://pypi.org/simple"} version = "0.1.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/22/ef/345b0f88b8e9d9e12051142a9cdcf590bf70206d20d81c3f773ade8d9e32/findlibs-0.1.2.tar.gz", hash = "sha256:1f56d220c69686392ebdc4c65b32ee344818bca633643a8c97592957d1728122", size = 11302, upload-time = "2025-07-28T09:15:03.675Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/2f/ff/76dd547e129206899e4e26446c3ca7aeaff948c31b05250e9b8690e76883/findlibs-0.1.2-py3-none-any.whl", hash = "sha256:5348bbc7055d2a505962576c2e285b6c0aae6d749f82ba71296e7d41336e66e8", size = 10707, upload-time = "2025-07-28T09:15:02.733Z" }, + {url = "https://files.pythonhosted.org/packages/2f/ff/76dd547e129206899e4e26446c3ca7aeaff948c31b05250e9b8690e76883/findlibs-0.1.2-py3-none-any.whl", hash = "sha256:5348bbc7055d2a505962576c2e285b6c0aae6d749f82ba71296e7d41336e66e8", size = 10707, upload-time = "2025-07-28T09:15:02.733Z"} ] [[package]] -name = "fire" -version = "0.7.1" -source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "termcolor" }, + {name = "termcolor"} ] -sdist = { url = "https://files.pythonhosted.org/packages/c0/00/f8d10588d2019d6d6452653def1ee807353b21983db48550318424b5ff18/fire-0.7.1.tar.gz", hash = "sha256:3b208f05c736de98fb343310d090dcc4d8c78b2a89ea4f32b837c586270a9cbf", size = 88720, upload-time = "2025-08-16T20:20:24.175Z" } +name = "fire" +sdist = {url = "https://files.pythonhosted.org/packages/c0/00/f8d10588d2019d6d6452653def1ee807353b21983db48550318424b5ff18/fire-0.7.1.tar.gz", hash = "sha256:3b208f05c736de98fb343310d090dcc4d8c78b2a89ea4f32b837c586270a9cbf", size = 88720, upload-time = "2025-08-16T20:20:24.175Z"} +source = {registry = "https://pypi.org/simple"} +version = "0.7.1" wheels = [ - { url = "https://files.pythonhosted.org/packages/e5/4c/93d0f85318da65923e4b91c1c2ff03d8a458cbefebe3bc612a6693c7906d/fire-0.7.1-py3-none-any.whl", hash = "sha256:e43fd8a5033a9001e7e2973bab96070694b9f12f2e0ecf96d4683971b5ab1882", size = 115945, upload-time = "2025-08-16T20:20:22.87Z" }, + {url = "https://files.pythonhosted.org/packages/e5/4c/93d0f85318da65923e4b91c1c2ff03d8a458cbefebe3bc612a6693c7906d/fire-0.7.1-py3-none-any.whl", hash = "sha256:e43fd8a5033a9001e7e2973bab96070694b9f12f2e0ecf96d4683971b5ab1882", size = 115945, upload-time = "2025-08-16T20:20:22.87Z"} ] [[package]] -name = "flexcache" -version = "0.3" -source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions" }, + {name = "typing-extensions"} ] -sdist = { url = "https://files.pythonhosted.org/packages/55/b0/8a21e330561c65653d010ef112bf38f60890051d244ede197ddaa08e50c1/flexcache-0.3.tar.gz", hash = "sha256:18743bd5a0621bfe2cf8d519e4c3bfdf57a269c15d1ced3fb4b64e0ff4600656", size = 15816, upload-time = "2024-03-09T03:21:07.555Z" } +name = "flexcache" +sdist = {url = "https://files.pythonhosted.org/packages/55/b0/8a21e330561c65653d010ef112bf38f60890051d244ede197ddaa08e50c1/flexcache-0.3.tar.gz", hash = "sha256:18743bd5a0621bfe2cf8d519e4c3bfdf57a269c15d1ced3fb4b64e0ff4600656", size = 15816, upload-time = "2024-03-09T03:21:07.555Z"} +source = {registry = "https://pypi.org/simple"} +version = "0.3" wheels = [ - { url = "https://files.pythonhosted.org/packages/27/cd/c883e1a7c447479d6e13985565080e3fea88ab5a107c21684c813dba1875/flexcache-0.3-py3-none-any.whl", hash = "sha256:d43c9fea82336af6e0115e308d9d33a185390b8346a017564611f1466dcd2e32", size = 13263, upload-time = "2024-03-09T03:21:05.635Z" }, + {url = "https://files.pythonhosted.org/packages/27/cd/c883e1a7c447479d6e13985565080e3fea88ab5a107c21684c813dba1875/flexcache-0.3-py3-none-any.whl", hash = "sha256:d43c9fea82336af6e0115e308d9d33a185390b8346a017564611f1466dcd2e32", size = 13263, upload-time = "2024-03-09T03:21:05.635Z"} ] [[package]] -name = "flexparser" -version = "0.4" -source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions" }, + {name = "typing-extensions"} ] -sdist = { url = "https://files.pythonhosted.org/packages/82/99/b4de7e39e8eaf8207ba1a8fa2241dd98b2ba72ae6e16960d8351736d8702/flexparser-0.4.tar.gz", hash = "sha256:266d98905595be2ccc5da964fe0a2c3526fbbffdc45b65b3146d75db992ef6b2", size = 31799, upload-time = "2024-11-07T02:00:56.249Z" } +name = "flexparser" +sdist = {url = "https://files.pythonhosted.org/packages/82/99/b4de7e39e8eaf8207ba1a8fa2241dd98b2ba72ae6e16960d8351736d8702/flexparser-0.4.tar.gz", hash = "sha256:266d98905595be2ccc5da964fe0a2c3526fbbffdc45b65b3146d75db992ef6b2", size = 31799, upload-time = "2024-11-07T02:00:56.249Z"} +source = {registry = "https://pypi.org/simple"} +version = "0.4" wheels = [ - { url = "https://files.pythonhosted.org/packages/fe/5e/3be305568fe5f34448807976dc82fc151d76c3e0e03958f34770286278c1/flexparser-0.4-py3-none-any.whl", hash = "sha256:3738b456192dcb3e15620f324c447721023c0293f6af9955b481e91d00179846", size = 27625, upload-time = "2024-11-07T02:00:54.523Z" }, + {url = "https://files.pythonhosted.org/packages/fe/5e/3be305568fe5f34448807976dc82fc151d76c3e0e03958f34770286278c1/flexparser-0.4-py3-none-any.whl", hash = "sha256:3738b456192dcb3e15620f324c447721023c0293f6af9955b481e91d00179846", size = 27625, upload-time = "2024-11-07T02:00:54.523Z"} ] [[package]] name = "frozendict" +sdist = {url = "https://files.pythonhosted.org/packages/90/b2/2a3d1374b7780999d3184e171e25439a8358c47b481f68be883c14086b4c/frozendict-2.4.7.tar.gz", hash = "sha256:e478fb2a1391a56c8a6e10cc97c4a9002b410ecd1ac28c18d780661762e271bd", size = 317082, upload-time = "2025-11-11T22:40:14.251Z"} +source = {registry = "https://pypi.org/simple"} version = "2.4.7" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/90/b2/2a3d1374b7780999d3184e171e25439a8358c47b481f68be883c14086b4c/frozendict-2.4.7.tar.gz", hash = "sha256:e478fb2a1391a56c8a6e10cc97c4a9002b410ecd1ac28c18d780661762e271bd", size = 317082, upload-time = "2025-11-11T22:40:14.251Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/38/74/f94141b38a51a553efef7f510fc213894161ae49b88bffd037f8d2a7cb2f/frozendict-2.4.7-py3-none-any.whl", hash = "sha256:972af65924ea25cf5b4d9326d549e69a9a4918d8a76a9d3a7cd174d98b237550", size = 16264, upload-time = "2025-11-11T22:40:12.836Z" }, + {url = "https://files.pythonhosted.org/packages/38/74/f94141b38a51a553efef7f510fc213894161ae49b88bffd037f8d2a7cb2f/frozendict-2.4.7-py3-none-any.whl", hash = "sha256:972af65924ea25cf5b4d9326d549e69a9a4918d8a76a9d3a7cd174d98b237550", size = 16264, upload-time = "2025-11-11T22:40:12.836Z"} ] [[package]] name = "fsspec" +sdist = {url = "https://files.pythonhosted.org/packages/51/7c/f60c259dcbf4f0c47cc4ddb8f7720d2dcdc8888c8e5ad84c73ea4531cc5b/fsspec-2026.2.0.tar.gz", hash = "sha256:6544e34b16869f5aacd5b90bdf1a71acb37792ea3ddf6125ee69a22a53fb8bff", size = 313441, upload-time = "2026-02-05T21:50:53.743Z"} +source = {registry = "https://pypi.org/simple"} version = "2026.2.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/51/7c/f60c259dcbf4f0c47cc4ddb8f7720d2dcdc8888c8e5ad84c73ea4531cc5b/fsspec-2026.2.0.tar.gz", hash = "sha256:6544e34b16869f5aacd5b90bdf1a71acb37792ea3ddf6125ee69a22a53fb8bff", size = 313441, upload-time = "2026-02-05T21:50:53.743Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e6/ab/fb21f4c939bb440104cc2b396d3be1d9b7a9fd3c6c2a53d98c45b3d7c954/fsspec-2026.2.0-py3-none-any.whl", hash = "sha256:98de475b5cb3bd66bedd5c4679e87b4fdfe1a3bf4d707b151b3c07e58c9a2437", size = 202505, upload-time = "2026-02-05T21:50:51.819Z" }, + {url = "https://files.pythonhosted.org/packages/e6/ab/fb21f4c939bb440104cc2b396d3be1d9b7a9fd3c6c2a53d98c45b3d7c954/fsspec-2026.2.0-py3-none-any.whl", hash = "sha256:98de475b5cb3bd66bedd5c4679e87b4fdfe1a3bf4d707b151b3c07e58c9a2437", size = 202505, upload-time = "2026-02-05T21:50:51.819Z"} ] [[package]] name = "humanize" +sdist = {url = "https://files.pythonhosted.org/packages/ba/66/a3921783d54be8a6870ac4ccffcd15c4dc0dd7fcce51c6d63b8c63935276/humanize-4.15.0.tar.gz", hash = "sha256:1dd098483eb1c7ee8e32eb2e99ad1910baefa4b75c3aff3a82f4d78688993b10", size = 83599, upload-time = "2025-12-20T20:16:13.19Z"} +source = {registry = "https://pypi.org/simple"} version = "4.15.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ba/66/a3921783d54be8a6870ac4ccffcd15c4dc0dd7fcce51c6d63b8c63935276/humanize-4.15.0.tar.gz", hash = "sha256:1dd098483eb1c7ee8e32eb2e99ad1910baefa4b75c3aff3a82f4d78688993b10", size = 83599, upload-time = "2025-12-20T20:16:13.19Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c5/7b/bca5613a0c3b542420cf92bd5e5fb8ebd5435ce1011a091f66bb7693285e/humanize-4.15.0-py3-none-any.whl", hash = "sha256:b1186eb9f5a9749cd9cb8565aee77919dd7c8d076161cf44d70e59e3301e1769", size = 132203, upload-time = "2025-12-20T20:16:11.67Z" }, + {url = "https://files.pythonhosted.org/packages/c5/7b/bca5613a0c3b542420cf92bd5e5fb8ebd5435ce1011a091f66bb7693285e/humanize-4.15.0-py3-none-any.whl", hash = "sha256:b1186eb9f5a9749cd9cb8565aee77919dd7c8d076161cf44d70e59e3301e1769", size = 132203, upload-time = "2025-12-20T20:16:11.67Z"} ] [[package]] name = "idna" +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"} +source = {registry = "https://pypi.org/simple"} 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" }, + {url = "https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea", size = 71008, upload-time = "2025-10-12T14:55:18.883Z"} ] [[package]] -name = "importlib-metadata" -version = "8.7.1" -source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "zipp", marker = "python_full_version < '3.14'" }, + {name = "zipp", marker = "python_full_version < '3.14'"} ] -sdist = { url = "https://files.pythonhosted.org/packages/f3/49/3b30cad09e7771a4982d9975a8cbf64f00d4a1ececb53297f1d9a7be1b10/importlib_metadata-8.7.1.tar.gz", hash = "sha256:49fef1ae6440c182052f407c8d34a68f72efc36db9ca90dc0113398f2fdde8bb", size = 57107, upload-time = "2025-12-21T10:00:19.278Z" } +name = "importlib-metadata" +sdist = {url = "https://files.pythonhosted.org/packages/f3/49/3b30cad09e7771a4982d9975a8cbf64f00d4a1ececb53297f1d9a7be1b10/importlib_metadata-8.7.1.tar.gz", hash = "sha256:49fef1ae6440c182052f407c8d34a68f72efc36db9ca90dc0113398f2fdde8bb", size = 57107, upload-time = "2025-12-21T10:00:19.278Z"} +source = {registry = "https://pypi.org/simple"} +version = "8.7.1" wheels = [ - { url = "https://files.pythonhosted.org/packages/fa/5e/f8e9a1d23b9c20a551a8a02ea3637b4642e22c2626e3a13a9a29cdea99eb/importlib_metadata-8.7.1-py3-none-any.whl", hash = "sha256:5a1f80bf1daa489495071efbb095d75a634cf28a8bc299581244063b53176151", size = 27865, upload-time = "2025-12-21T10:00:18.329Z" }, + {url = "https://files.pythonhosted.org/packages/fa/5e/f8e9a1d23b9c20a551a8a02ea3637b4642e22c2626e3a13a9a29cdea99eb/importlib_metadata-8.7.1-py3-none-any.whl", hash = "sha256:5a1f80bf1daa489495071efbb095d75a634cf28a8bc299581244063b53176151", size = 27865, upload-time = "2025-12-21T10:00:18.329Z"} ] [[package]] name = "iniconfig" +sdist = {url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z"} +source = {registry = "https://pypi.org/simple"} version = "2.3.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" }, + {url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z"} ] [[package]] -name = "ipython" -version = "9.10.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" }, - { name = "typing-extensions", marker = "python_full_version < '3.12'" }, + {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"}, + {name = "typing-extensions", marker = "python_full_version < '3.12'"} ] -sdist = { url = "https://files.pythonhosted.org/packages/a6/60/2111715ea11f39b1535bed6024b7dec7918b71e5e5d30855a5b503056b50/ipython-9.10.0.tar.gz", hash = "sha256:cd9e656be97618a0676d058134cd44e6dc7012c0e5cb36a9ce96a8c904adaf77", size = 4426526, upload-time = "2026-02-02T10:00:33.594Z" } +name = "ipython" +sdist = {url = "https://files.pythonhosted.org/packages/a6/60/2111715ea11f39b1535bed6024b7dec7918b71e5e5d30855a5b503056b50/ipython-9.10.0.tar.gz", hash = "sha256:cd9e656be97618a0676d058134cd44e6dc7012c0e5cb36a9ce96a8c904adaf77", size = 4426526, upload-time = "2026-02-02T10:00:33.594Z"} +source = {registry = "https://pypi.org/simple"} +version = "9.10.0" wheels = [ - { url = "https://files.pythonhosted.org/packages/3d/aa/898dec789a05731cd5a9f50605b7b44a72bd198fd0d4528e11fc610177cc/ipython-9.10.0-py3-none-any.whl", hash = "sha256:c6ab68cc23bba8c7e18e9b932797014cc61ea7fd6f19de180ab9ba73e65ee58d", size = 622774, upload-time = "2026-02-02T10:00:31.503Z" }, + {url = "https://files.pythonhosted.org/packages/3d/aa/898dec789a05731cd5a9f50605b7b44a72bd198fd0d4528e11fc610177cc/ipython-9.10.0-py3-none-any.whl", hash = "sha256:c6ab68cc23bba8c7e18e9b932797014cc61ea7fd6f19de180ab9ba73e65ee58d", size = 622774, upload-time = "2026-02-02T10:00:31.503Z"} ] [[package]] -name = "ipython-pygments-lexers" -version = "1.1.1" -source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "pygments" }, + {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" } +name = "ipython-pygments-lexers" +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"} +source = {registry = "https://pypi.org/simple"} +version = "1.1.1" 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" }, + {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 = "jedi" -version = "0.19.2" -source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "parso" }, + {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" } +name = "jedi" +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"} +source = {registry = "https://pypi.org/simple"} +version = "0.19.2" 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" }, + {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" }, + {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" } +name = "jinja2" +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"} +source = {registry = "https://pypi.org/simple"} +version = "3.1.6" 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" }, + {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 = "jsonpickle" +sdist = {url = "https://files.pythonhosted.org/packages/e4/a6/d07afcfdef402900229bcca795f80506b207af13a838d4d99ad45abf530c/jsonpickle-4.1.1.tar.gz", hash = "sha256:f86e18f13e2b96c1c1eede0b7b90095bbb61d99fedc14813c44dc2f361dbbae1", size = 316885, upload-time = "2025-06-02T20:36:11.57Z"} +source = {registry = "https://pypi.org/simple"} version = "4.1.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e4/a6/d07afcfdef402900229bcca795f80506b207af13a838d4d99ad45abf530c/jsonpickle-4.1.1.tar.gz", hash = "sha256:f86e18f13e2b96c1c1eede0b7b90095bbb61d99fedc14813c44dc2f361dbbae1", size = 316885, upload-time = "2025-06-02T20:36:11.57Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c1/73/04df8a6fa66d43a9fd45c30f283cc4afff17da671886e451d52af60bdc7e/jsonpickle-4.1.1-py3-none-any.whl", hash = "sha256:bb141da6057898aa2438ff268362b126826c812a1721e31cf08a6e142910dc91", size = 47125, upload-time = "2025-06-02T20:36:08.647Z" }, + {url = "https://files.pythonhosted.org/packages/c1/73/04df8a6fa66d43a9fd45c30f283cc4afff17da671886e451d52af60bdc7e/jsonpickle-4.1.1-py3-none-any.whl", hash = "sha256:bb141da6057898aa2438ff268362b126826c812a1721e31cf08a6e142910dc91", size = 47125, upload-time = "2025-06-02T20:36:08.647Z"} ] [[package]] -name = "jsonschema" -version = "4.26.0" -source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "attrs" }, - { name = "jsonschema-specifications" }, - { name = "referencing" }, - { name = "rpds-py" }, + {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" } +name = "jsonschema" +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"} +source = {registry = "https://pypi.org/simple"} +version = "4.26.0" 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" }, + {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]] -name = "jsonschema-specifications" -version = "2025.9.1" -source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "referencing" }, + {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" } +name = "jsonschema-specifications" +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"} +source = {registry = "https://pypi.org/simple"} +version = "2025.9.1" 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" }, + {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 = "locket" +sdist = {url = "https://files.pythonhosted.org/packages/2f/83/97b29fe05cb6ae28d2dbd30b81e2e402a3eed5f460c26e9eaa5895ceacf5/locket-1.0.0.tar.gz", hash = "sha256:5c0d4c052a8bbbf750e056a8e65ccd309086f4f0f18a2eac306a8dfa4112a632", size = 4350, upload-time = "2022-04-20T22:04:44.312Z"} +source = {registry = "https://pypi.org/simple"} version = "1.0.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/2f/83/97b29fe05cb6ae28d2dbd30b81e2e402a3eed5f460c26e9eaa5895ceacf5/locket-1.0.0.tar.gz", hash = "sha256:5c0d4c052a8bbbf750e056a8e65ccd309086f4f0f18a2eac306a8dfa4112a632", size = 4350, upload-time = "2022-04-20T22:04:44.312Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/db/bc/83e112abc66cd466c6b83f99118035867cecd41802f8d044638aa78a106e/locket-1.0.0-py2.py3-none-any.whl", hash = "sha256:b6c819a722f7b6bd955b80781788e4a66a55628b858d347536b7e81325a3a5e3", size = 4398, upload-time = "2022-04-20T22:04:42.23Z" }, + {url = "https://files.pythonhosted.org/packages/db/bc/83e112abc66cd466c6b83f99118035867cecd41802f8d044638aa78a106e/locket-1.0.0-py2.py3-none-any.whl", hash = "sha256:b6c819a722f7b6bd955b80781788e4a66a55628b858d347536b7e81325a3a5e3", size = 4398, upload-time = "2022-04-20T22:04:42.23Z"} ] [[package]] name = "lru-dict" +sdist = {url = "https://files.pythonhosted.org/packages/06/0a/dec86efe38b350314c49a8d39ef01ba7cf8bbbef1d177646320eedea7159/lru_dict-1.4.1.tar.gz", hash = "sha256:cc518ff2d38cc7a8ab56f9a6ae557f91e2e1524b57ed8e598e97f45a2bd708fc", size = 13439, upload-time = "2025-11-02T10:02:13.548Z"} +source = {registry = "https://pypi.org/simple"} version = "1.4.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/06/0a/dec86efe38b350314c49a8d39ef01ba7cf8bbbef1d177646320eedea7159/lru_dict-1.4.1.tar.gz", hash = "sha256:cc518ff2d38cc7a8ab56f9a6ae557f91e2e1524b57ed8e598e97f45a2bd708fc", size = 13439, upload-time = "2025-11-02T10:02:13.548Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/4c/ff/1d02bc444174f07d3ce747568989969c97dc77d0513f4c3b8b6224cb976f/lru_dict-1.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:cc74c49cf1c26d6c28d8f6988cf0354696ca38a4f6012fa63055d2800791784b", size = 16760, upload-time = "2025-11-02T10:01:06.492Z" }, - { url = "https://files.pythonhosted.org/packages/0b/d8/e2e970272ea5fe7ba6349a5e7d0bb0fd814f5d1b88a53bc72b8c2a5e034f/lru_dict-1.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0158db85dfb2cd2fd2ddaa47709bdb073f814e0a8a149051b70b07e59ac83231", size = 11249, upload-time = "2025-11-02T10:01:07.261Z" }, - { url = "https://files.pythonhosted.org/packages/a5/26/860b5e60f339f8038118028388926224c8b70779e8243d68772e0e0d0ab3/lru_dict-1.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c8ac5cfd56e036bd8d7199626147044485fa64a163a5bde96bfa5a1c7fea2273", size = 11728, upload-time = "2025-11-02T10:01:08.185Z" }, - { url = "https://files.pythonhosted.org/packages/61/55/fc8f71953fd343ede33810b0a000b4130e03635ae09b28569e45735ded2f/lru_dict-1.4.1-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:2eb2058cb7b329b4b72baee4cd1bb322af1feec73de79e68edb35d333c90b698", size = 30795, upload-time = "2025-11-02T10:01:08.862Z" }, - { url = "https://files.pythonhosted.org/packages/4c/26/ad549550e6a236818a91434570d38d7a93824b0410d3db1c845a53238e1f/lru_dict-1.4.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6ffbb6f3c1e906e92d9129c14a88d81358be1e0b60195c1729b215a52e9670de", size = 31807, upload-time = "2025-11-02T10:01:09.581Z" }, - { url = "https://files.pythonhosted.org/packages/7c/39/72dae9ac0e95a8576a45e3bd62a6fc3e7dbb116794efa1337c7b450d4836/lru_dict-1.4.1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:11b289d78a48a086846e46d2275707d33523f5d543475336c29c56fd5d0e65dc", size = 33437, upload-time = "2025-11-02T10:01:10.676Z" }, - { url = "https://files.pythonhosted.org/packages/a8/46/221479834703a5397fa32f07212ace38f104a31ad1af8a921cf25e053677/lru_dict-1.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3fe10c1f45712e191eecb2a69604d566c64ddfe01136fd467c890ed558c3ad40", size = 31168, upload-time = "2025-11-02T10:01:11.47Z" }, - { url = "https://files.pythonhosted.org/packages/6e/13/98d36e2522fda7f6625c15332562f81f1465161a5ae021d9b3b408f8c427/lru_dict-1.4.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:e04820e3473bd7f55440f24c946ca4335e392d5e3e0e1e948020e94cd1954372", size = 32454, upload-time = "2025-11-02T10:01:12.522Z" }, - { url = "https://files.pythonhosted.org/packages/49/18/345ff2a98d27cddae40c84cf0466fcc329f3965cd21322bb561a94e4d332/lru_dict-1.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:edc004c88911a8f9715e716116d2520c13db89afd6c37cc0f28042ba10635163", size = 30574, upload-time = "2025-11-02T10:01:13.293Z" }, - { url = "https://files.pythonhosted.org/packages/d7/92/dfea71402a7ca46332bcb854827ee68bbc9be205e2558c3a40293eca9782/lru_dict-1.4.1-cp311-cp311-win32.whl", hash = "sha256:b0b5360264b37676c405ea0a560744d7dcb2d47adff1e7837113c15fabcc7a71", size = 13031, upload-time = "2025-11-02T10:01:13.96Z" }, - { url = "https://files.pythonhosted.org/packages/3a/7b/4c7d566d77ec3ad9128f07407494c2aec57909f8dd59f0c9910bd4c05840/lru_dict-1.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:bb4b37daad9fe4e796c462f4876cf34e52564630902bdf59a271bc482b48a361", size = 14007, upload-time = "2025-11-02T10:01:14.857Z" }, - { url = "https://files.pythonhosted.org/packages/4f/a8/89e4c26e0e751321b41b0a3007384f97d9eae7a863c49af1c68c43005ca3/lru_dict-1.4.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:7fa342c6e6bc811ee6a17eb569d37b149340d5aa5a637a53438e316a95783838", size = 16683, upload-time = "2025-11-02T10:01:15.891Z" }, - { url = "https://files.pythonhosted.org/packages/f1/34/b3c6fdd120af68b6eeb524d0de3293ff27918ec57f45eed6bef1789fd085/lru_dict-1.4.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:bd86bd202a7c1585d9dc7e5b0c3d52cf76dc56b261b4bbecfeefbbae31a5c97d", size = 11216, upload-time = "2025-11-02T10:01:16.867Z" }, - { url = "https://files.pythonhosted.org/packages/e9/7e/280267ae23f1ec1074ddaab787c5e041e090220e8e37828d51ff4e681dfd/lru_dict-1.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4617554f3e42a8f520c8494842c23b98f5b7f4d5e0410e91a4c3ad0ea5f7e094", size = 11687, upload-time = "2025-11-02T10:01:17.485Z" }, - { url = "https://files.pythonhosted.org/packages/ca/18/fec42416ceff98ae2760067ec72b0b9fc02840e729bbc18059c6a02cb01f/lru_dict-1.4.1-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:40927a6a4284d437047f547e652b15f6f0f40210deb6b9e5b77e556ff0faea0f", size = 31960, upload-time = "2025-11-02T10:01:18.158Z" }, - { url = "https://files.pythonhosted.org/packages/c2/ef/38e7ee1a5d32b9b1629d045fa5a495375383aacfb2945f4d9535b9af9630/lru_dict-1.4.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e2c07ecb6d42494e45d00c2541e6b0ae7659fc3cf89681521ba94b15c682d4fe", size = 32882, upload-time = "2025-11-02T10:01:18.841Z" }, - { url = "https://files.pythonhosted.org/packages/72/82/d56653ca144c291ab37bea5f23c5078ffbe64f7f5b466f91d400590b9106/lru_dict-1.4.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:85b28aa2de7c5f1f6c68221857accd084438df98edbd4f57595795734225770c", size = 34268, upload-time = "2025-11-02T10:01:19.564Z" }, - { url = "https://files.pythonhosted.org/packages/94/ae/382651533d60f0b598757efda56dc87cad5ac311fba8e61f86fb916bf236/lru_dict-1.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:cbbbb4b51e2529ccf7ee8a3c3b834052dbd54871a216cfd229dd2b1194ff293a", size = 32156, upload-time = "2025-11-02T10:01:20.22Z" }, - { url = "https://files.pythonhosted.org/packages/aa/d1/d9df7e9272ccbc96f04c477dfb9abb91fa8fabde86b7fa190cb7b3c7a024/lru_dict-1.4.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:e47040421a13de8bc6404557b3700c33f1f2683cbcce22fe5cacec4c938ce54b", size = 33395, upload-time = "2025-11-02T10:01:20.901Z" }, - { url = "https://files.pythonhosted.org/packages/e9/6e/dafe0f5943a7b3ab24d3429032ff85873acd626087934b8161b55340c13a/lru_dict-1.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:451f7249866cb9564bb40d73bec7ac865574dafd0a4cc91627bbf35be7e99291", size = 31591, upload-time = "2025-11-02T10:01:21.606Z" }, - { url = "https://files.pythonhosted.org/packages/a6/4d/9dd35444592bfb6805548e15971cfce821400966a51130b78dc021ee8f03/lru_dict-1.4.1-cp312-cp312-win32.whl", hash = "sha256:e8996f3f94870ecb236c55d280839390edae7f201858fee770267eac27b8b47d", size = 13119, upload-time = "2025-11-02T10:01:22.61Z" }, - { url = "https://files.pythonhosted.org/packages/8d/82/7e72e30d6c15d65466b3baca87cce15e20848ba6a488868aa54e901141a6/lru_dict-1.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:d90774db1b60c0d5c829cfa5d7fda6db96ed1519296f626575598f9f170cca37", size = 14109, upload-time = "2025-11-02T10:01:23.322Z" }, - { url = "https://files.pythonhosted.org/packages/85/95/ee171a68ae381ab988c50e3b7b136b1c598f5f683ba4a1e10c51e2480408/lru_dict-1.4.1-cp313-cp313-android_21_arm64_v8a.whl", hash = "sha256:2a5644bb1db0514abdad5e2f3d8f1beb6f7560c8cceb62079c40a4269de34b3c", size = 12248, upload-time = "2025-11-02T10:01:24.291Z" }, - { url = "https://files.pythonhosted.org/packages/a1/82/8de8e8fd96c44d46891415834ceb9f51c552840bda2d118394aca5e3153a/lru_dict-1.4.1-cp313-cp313-android_21_x86_64.whl", hash = "sha256:4209864be09ec20f6059fef8544697eb3d3729d63a983bf66457054bf3e40601", size = 12243, upload-time = "2025-11-02T10:01:25.254Z" }, - { url = "https://files.pythonhosted.org/packages/53/97/251cfb357c547a8fd06c2bc40db8a7f7eed7dbacef30d8d7e543522360e1/lru_dict-1.4.1-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:8fef8dd72484b4280799c502c116acfdfcf0dedf3508bc9d0d19e684a6a23267", size = 10938, upload-time = "2025-11-02T10:01:25.89Z" }, - { url = "https://files.pythonhosted.org/packages/58/14/602791d219bc87197ae80f5fa0f77ca0af8e83e9a06c7cdb89db5575839e/lru_dict-1.4.1-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:d64ddbe4c426fdc4cfc1abaea71d587d439397386a7b35d588f4fd64b695a83d", size = 11261, upload-time = "2025-11-02T10:01:26.879Z" }, - { url = "https://files.pythonhosted.org/packages/10/5d/a30a6fad150f20f084de8e243882a0488ad4929db41a2c8ce9be6cf56563/lru_dict-1.4.1-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:000ba9a2ab4dd1ad2d91764a6d5cce75a59de51534cdda478d1ddaa3cd8d5c48", size = 10801, upload-time = "2025-11-02T10:01:27.553Z" }, - { url = "https://files.pythonhosted.org/packages/64/4d/cee327e024d42972c598b7e0cd5063a1b1d7451efba31f7de7b6ca91e7d0/lru_dict-1.4.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ffad2758ce21d8fd6f0ae2628b31330732db8429a4b5994d2e107bed0ee11e68", size = 16688, upload-time = "2025-11-02T10:01:28.17Z" }, - { url = "https://files.pythonhosted.org/packages/58/c8/2f86a1e448c5257b31424b96bf1385e7f96ec7841c2376db02811bbd395f/lru_dict-1.4.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1671e8d92fe35dfb38d3505a56338792d3e225032f8e94888b6e95b323120380", size = 11214, upload-time = "2025-11-02T10:01:28.888Z" }, - { url = "https://files.pythonhosted.org/packages/06/41/507c615cffaba67c35affd77dec25d3183bb87f404b41c8bb2b3053481ac/lru_dict-1.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d5f01ada0cf0c1aa2bdc684e5ac0f6548be7eccc3ce8b4c0361db8445f867f04", size = 11689, upload-time = "2025-11-02T10:01:29.508Z" }, - { url = "https://files.pythonhosted.org/packages/4e/c1/35aa1359f80174016b389f8be5fd48c4a5af0a04a73afb4906e5d4279f4a/lru_dict-1.4.1-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:74204239e30b8ec7976257c5b64565d7e3e8aea0cad0dd50a9b99e171aaf3898", size = 32034, upload-time = "2025-11-02T10:01:30.164Z" }, - { url = "https://files.pythonhosted.org/packages/c2/93/46301015bddd4552a1b76982ef788a7fb2a886efff83ad2c178cc7e68349/lru_dict-1.4.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a7da0e451faa4d6dcae21c0f2527c540000b2f23ed8326a0bc1d870130fd12b1", size = 32919, upload-time = "2025-11-02T10:01:30.971Z" }, - { url = "https://files.pythonhosted.org/packages/e6/cb/6d67145619d8ec3bba15fe145ff702ecf44991e33345d38c763501c1608a/lru_dict-1.4.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:071468a716768a9afca64659c390c1abb6d937b1897e07a0b70383f75637fce0", size = 34334, upload-time = "2025-11-02T10:01:31.663Z" }, - { url = "https://files.pythonhosted.org/packages/a5/44/50daaec6793ec2042079ed6a8b6a687b4be51b270b1d8ec5efd280116493/lru_dict-1.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e77d209bcd396eb236c197bf4c95fab6848c61e0c1a5031cdde7f5c787e209f4", size = 32211, upload-time = "2025-11-02T10:01:32.468Z" }, - { url = "https://files.pythonhosted.org/packages/bd/53/355397949215e6b77b6771b973ee1dbc21fdd9f955925e47dce50d9d4727/lru_dict-1.4.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:b21688fd7ece56d04c0c13b42fd9f904d46fc9ff21e3de87d98f3f5a14c67f74", size = 33461, upload-time = "2025-11-02T10:01:33.2Z" }, - { url = "https://files.pythonhosted.org/packages/ff/fa/d660fa63144f38a0fd5b437a140517e3cff482d955ef6b9b4cf7651b9d85/lru_dict-1.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:989ef7352b347c82e5d5047f3b7ddf34b5a938e3f7b08775cacc9f28e97dd2a8", size = 31651, upload-time = "2025-11-02T10:01:33.874Z" }, - { url = "https://files.pythonhosted.org/packages/2e/77/0fae8d0702f7546f436efe06a684b301aad5c8a167bb2df6e42b0f821de5/lru_dict-1.4.1-cp313-cp313-win32.whl", hash = "sha256:a36e6e95b5d474ef90d04a5e3ad81ca362b473ec9534ed964222f3c0444138b8", size = 13120, upload-time = "2025-11-02T10:01:34.595Z" }, - { url = "https://files.pythonhosted.org/packages/4a/20/56a3f0d74c8fe32c01d3978387f66c9fb180c7f15bfd9fcecaa01b4e7736/lru_dict-1.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:8e73a1ec2d0f476d666ce7c91464b22854086951b319544d1850c508f5ce381f", size = 14112, upload-time = "2025-11-02T10:01:35.268Z" }, - { url = "https://files.pythonhosted.org/packages/98/02/8e04a8d744b466d4153502e2d92b453c2e5a549d49bf7fabfdca1621828a/lru_dict-1.4.1-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:7b770c7db258625e57b6ea8e2e0503ba0fbbdcde374baacf9adb256eb9c5adfa", size = 11119, upload-time = "2025-11-02T10:01:36.239Z" }, - { url = "https://files.pythonhosted.org/packages/50/f8/ee96f30127ff47c29966603f040e0485700fe0ca0e7d7b1ecbc9bf999eea/lru_dict-1.4.1-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:45d4dc338237cedcbacedab1afd9707b8f9867d8b601ec04e0395ec73f57405c", size = 11435, upload-time = "2025-11-02T10:01:36.857Z" }, - { url = "https://files.pythonhosted.org/packages/a0/5a/897b33ba1974b6487848cafa5de7e93a7c4f5d9d3f43319ee010f6882830/lru_dict-1.4.1-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:5b31e9b6636f8945ad69c630c1891d810d62a91d99e792ef0b9ca865b6c26745", size = 10988, upload-time = "2025-11-02T10:01:37.531Z" }, - { url = "https://files.pythonhosted.org/packages/19/8e/b87d0f2bfcad0169afc00e23e014bad9af252206ec2cbc6079f12bece58e/lru_dict-1.4.1-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:f9335d46c83882a1b5deffed8098a2dd9ad66d2bd6263f416fc4c73f63e26904", size = 16733, upload-time = "2025-11-02T10:01:38.194Z" }, - { url = "https://files.pythonhosted.org/packages/ab/19/d2384266864b1e5b1cc20527ae468550d3b23a71636371b40e4663276294/lru_dict-1.4.1-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:17844b4f8dd996144d53380395d73832e2508159ad49ed4fbcb62f1787a5feaf", size = 11222, upload-time = "2025-11-02T10:01:39.093Z" }, - { url = "https://files.pythonhosted.org/packages/66/8a/94dec42ae6b5c8bdc53a86867924fa22634516434f129dca187ccc0853b8/lru_dict-1.4.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:2b569c7813adb753b7b631097c34e6dbc194cb1814f22299c2d2a94894779877", size = 11733, upload-time = "2025-11-02T10:01:39.739Z" }, - { url = "https://files.pythonhosted.org/packages/3f/19/0b6de1db804cf094e201c5541d58e6a96359eb5beed048fa64d0589b6520/lru_dict-1.4.1-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:33cf1eb368d3989b8f00945937cfbfc2095d8ad2b1d2274ce1bde0af6f6d1e66", size = 32251, upload-time = "2025-11-02T10:01:40.421Z" }, - { url = "https://files.pythonhosted.org/packages/97/38/89d9425dde436b9bd894234171988289b259aeeab5965bd2c21d5104cb41/lru_dict-1.4.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:22d5879ec5d5955f9dde105997bdf7ec9e0522bf99612a80b55b09f356a08368", size = 33405, upload-time = "2025-11-02T10:01:41.917Z" }, - { url = "https://files.pythonhosted.org/packages/0e/24/f1a189399ee107a64f955c9d6c84d3b0aee9b64b31fc5684b1eaeb3a6fc0/lru_dict-1.4.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2084363e4488aa5b4f8b26bd3cc148d70a15be92e3d347621a5b830b2b1e0a82", size = 35135, upload-time = "2025-11-02T10:01:42.935Z" }, - { url = "https://files.pythonhosted.org/packages/f8/57/58e9dcf0853d639e2995e5d9f84649ff8d6792a04a418628672a130137f4/lru_dict-1.4.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:8198ab8ad7cc81b86340243ddd5cca882ead87daed0c9fa6cce377a10a7f2e47", size = 32620, upload-time = "2025-11-02T10:01:43.627Z" }, - { url = "https://files.pythonhosted.org/packages/a9/bb/664922f0cf076b1e3c2e43e8258582d507b07c19bd441a72dd5547a483e9/lru_dict-1.4.1-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:f1f4ae6967d5873e684ce8b986e2e43985d0a1be735b09584737ad5634ff48f3", size = 34077, upload-time = "2025-11-02T10:01:44.694Z" }, - { url = "https://files.pythonhosted.org/packages/58/38/b7a6fa85b150232cada26a50c89dc4bcf9acd6ada00e987b074c3b4e57f2/lru_dict-1.4.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:a9bb130b5eaddd6453ca3dc38ce4a75f743512ad135b6f3994999dde0680bd79", size = 31905, upload-time = "2025-11-02T10:01:45.668Z" }, - { url = "https://files.pythonhosted.org/packages/86/7d/9c86393946d621f4aec852d543df4023241d85106e9e1e2a0e4057861f71/lru_dict-1.4.1-cp314-cp314-win32.whl", hash = "sha256:5534c69a52add5757714456d08ce3831d36b86c98972394ba900493bb0bd97f8", size = 13435, upload-time = "2025-11-02T10:01:46.397Z" }, - { url = "https://files.pythonhosted.org/packages/20/3f/b017cbeea55a8a1d18037840a8a9c9cdae29554e9985b55d4e8694305035/lru_dict-1.4.1-cp314-cp314-win_amd64.whl", hash = "sha256:96fd677b6d912229f2d02ba61a5a1210176963c4770c1bb765b8da937cec3834", size = 14423, upload-time = "2025-11-02T10:01:47.473Z" }, - { url = "https://files.pythonhosted.org/packages/aa/73/13132af7a5155edde66979b53eb509465304e6e5a2b00769246448479c73/lru_dict-1.4.1-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:6699bfebbf11dd9ff1387be7996fac6d1009fe6a6f48091ef6e069e6f19c7bce", size = 17184, upload-time = "2025-11-02T10:01:48.161Z" }, - { url = "https://files.pythonhosted.org/packages/ef/82/094985beb3e49461bf65a3c40df8de2018b8484e4ef129295090460ca5d9/lru_dict-1.4.1-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:a276f8f6f43861c3f05986824741d00e3133a973c3396598375310129535382d", size = 11459, upload-time = "2025-11-02T10:01:48.823Z" }, - { url = "https://files.pythonhosted.org/packages/14/29/836abc49f8c2b6c2efccd2ac2b2c0ad3e55b7d75a05a20cc061f17871e39/lru_dict-1.4.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:090c7b6a3d54fa7f3d69ba4802abe2f33c9583b16b33f52bcb521c701f7ea46c", size = 11938, upload-time = "2025-11-02T10:01:49.448Z" }, - { url = "https://files.pythonhosted.org/packages/c2/83/1bb4e8fbc0b753fea825564d9d96180813a71715d46a9b6bb30a6dea4ce0/lru_dict-1.4.1-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b21d06dec64fb1952385262d9fcefaec147921dc0b55210007091a79da440d93", size = 36389, upload-time = "2025-11-02T10:01:50.49Z" }, - { url = "https://files.pythonhosted.org/packages/54/f2/7df3b6d0dbc66f3be9aa6261750967cdc5619c89a563420c52200d2dd547/lru_dict-1.4.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b9613908a38cf8aa47f6c138ba031a8ac4ed38460299e84a2b07dba7b3b45aae", size = 38706, upload-time = "2025-11-02T10:01:51.197Z" }, - { url = "https://files.pythonhosted.org/packages/97/5f/e3ba3eeb9b864a09b92e24fbf179aef4ef48588e763a9d8d2bc10bd2c6f8/lru_dict-1.4.1-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7558302ce8bbfcd29f08e695e07bf7a0d799c2979636d6a6a0b4e207f840969f", size = 38892, upload-time = "2025-11-02T10:01:51.899Z" }, - { url = "https://files.pythonhosted.org/packages/e8/e3/12e0888aab0bf3ab9ce35e9849f239994a0feff6fe49380859bf57124a17/lru_dict-1.4.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:3910396142322fb2718546115bb2a56f50ebc9144b5140327053cca084e0d375", size = 37254, upload-time = "2025-11-02T10:01:52.587Z" }, - { url = "https://files.pythonhosted.org/packages/cc/dc/06cd981718d039eb07a9c03263094aca6269721c470f765a292b24381a20/lru_dict-1.4.1-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:f3f4fad5c4a9458954b275de6a6e31c67a26fbef7037c6a7354e22523a77db26", size = 37422, upload-time = "2025-11-02T10:01:53.271Z" }, - { url = "https://files.pythonhosted.org/packages/e8/82/ea88e618f39d78ff3c15b71f01a0b1a6c6ac2034ce5c6428ae41b1c30ea5/lru_dict-1.4.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:85fc29363e2d3ba0a5f87b5e17f54b1078aea6d24c6dfc792725854b9d0f8d17", size = 35909, upload-time = "2025-11-02T10:01:54.356Z" }, - { url = "https://files.pythonhosted.org/packages/89/36/1dd91c602f623839cec24d6c77fa3fd1a8878bf2d716871197cd3bf084dc/lru_dict-1.4.1-cp314-cp314t-win32.whl", hash = "sha256:b3853518dfa50f28af0d6e2dcf8bb8b0a1687c5f4eb913c0b35b0da5c6d276ce", size = 13816, upload-time = "2025-11-02T10:01:55.417Z" }, - { url = "https://files.pythonhosted.org/packages/ce/a3/113410f7b2e61e9d6f13f1f17c584dbd08b5796e65d772ecd5b063fab3af/lru_dict-1.4.1-cp314-cp314t-win_amd64.whl", hash = "sha256:ff3af42922205620fdc920dcdf580c4c16b32c84a537a03b04b523e5c641a8a9", size = 15204, upload-time = "2025-11-02T10:01:56.06Z" }, - { url = "https://files.pythonhosted.org/packages/8e/47/08c61cad038706b3a89b8c7587ec74ed9731c1e536329745cccb6c840916/lru_dict-1.4.1-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:9219f13e4101c064f70e1815d7c51f9be9e053983e74dfb7bcfdf92f5fcbb0e0", size = 10384, upload-time = "2025-11-02T10:02:09.656Z" }, - { url = "https://files.pythonhosted.org/packages/6b/a1/022c4d7c68c076370231488c97cf7451131fb9ca0d60d1b2785e7baa1f5b/lru_dict-1.4.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:b7e1ac7fb6e91e4d3212e153f9e2d98d163a4439b9bf9df247c22519262c26fe", size = 10822, upload-time = "2025-11-02T10:02:10.609Z" }, - { url = "https://files.pythonhosted.org/packages/65/b4/4c0a0877a77fececa9f58d804569e2aac1bfbe588e3a70e79647b5d8f7d4/lru_dict-1.4.1-pp311-pypy311_pp73-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:23424321b761c43f3021a596565f8205ecec0e175822e7a5d9b2a175578aa7de", size = 12968, upload-time = "2025-11-02T10:02:11.405Z" }, - { url = "https://files.pythonhosted.org/packages/22/06/d7e393d07dc31e656330d5a058f34e972bf590e7dc882922b426f3aec4a0/lru_dict-1.4.1-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:804ee76f98afc3d50e9a2e9c835a6820877aa6391f2add520a57f86b3f55ec3a", size = 13904, upload-time = "2025-11-02T10:02:12.144Z" }, - { url = "https://files.pythonhosted.org/packages/e8/1e/0eee8bcc16bf01b265ac83e4b870596e2f3bcc40d88aa7ec25407180fe44/lru_dict-1.4.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:3be24e24c8998302ea1c28f997505fa6843f507aad3c7d5c3a82cc01c5c11be4", size = 14062, upload-time = "2025-11-02T10:02:12.878Z" }, +wheels = [ + {url = "https://files.pythonhosted.org/packages/4c/ff/1d02bc444174f07d3ce747568989969c97dc77d0513f4c3b8b6224cb976f/lru_dict-1.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:cc74c49cf1c26d6c28d8f6988cf0354696ca38a4f6012fa63055d2800791784b", size = 16760, upload-time = "2025-11-02T10:01:06.492Z"}, + {url = "https://files.pythonhosted.org/packages/0b/d8/e2e970272ea5fe7ba6349a5e7d0bb0fd814f5d1b88a53bc72b8c2a5e034f/lru_dict-1.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0158db85dfb2cd2fd2ddaa47709bdb073f814e0a8a149051b70b07e59ac83231", size = 11249, upload-time = "2025-11-02T10:01:07.261Z"}, + {url = "https://files.pythonhosted.org/packages/a5/26/860b5e60f339f8038118028388926224c8b70779e8243d68772e0e0d0ab3/lru_dict-1.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c8ac5cfd56e036bd8d7199626147044485fa64a163a5bde96bfa5a1c7fea2273", size = 11728, upload-time = "2025-11-02T10:01:08.185Z"}, + {url = "https://files.pythonhosted.org/packages/61/55/fc8f71953fd343ede33810b0a000b4130e03635ae09b28569e45735ded2f/lru_dict-1.4.1-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:2eb2058cb7b329b4b72baee4cd1bb322af1feec73de79e68edb35d333c90b698", size = 30795, upload-time = "2025-11-02T10:01:08.862Z"}, + {url = "https://files.pythonhosted.org/packages/4c/26/ad549550e6a236818a91434570d38d7a93824b0410d3db1c845a53238e1f/lru_dict-1.4.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6ffbb6f3c1e906e92d9129c14a88d81358be1e0b60195c1729b215a52e9670de", size = 31807, upload-time = "2025-11-02T10:01:09.581Z"}, + {url = "https://files.pythonhosted.org/packages/7c/39/72dae9ac0e95a8576a45e3bd62a6fc3e7dbb116794efa1337c7b450d4836/lru_dict-1.4.1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:11b289d78a48a086846e46d2275707d33523f5d543475336c29c56fd5d0e65dc", size = 33437, upload-time = "2025-11-02T10:01:10.676Z"}, + {url = "https://files.pythonhosted.org/packages/a8/46/221479834703a5397fa32f07212ace38f104a31ad1af8a921cf25e053677/lru_dict-1.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3fe10c1f45712e191eecb2a69604d566c64ddfe01136fd467c890ed558c3ad40", size = 31168, upload-time = "2025-11-02T10:01:11.47Z"}, + {url = "https://files.pythonhosted.org/packages/6e/13/98d36e2522fda7f6625c15332562f81f1465161a5ae021d9b3b408f8c427/lru_dict-1.4.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:e04820e3473bd7f55440f24c946ca4335e392d5e3e0e1e948020e94cd1954372", size = 32454, upload-time = "2025-11-02T10:01:12.522Z"}, + {url = "https://files.pythonhosted.org/packages/49/18/345ff2a98d27cddae40c84cf0466fcc329f3965cd21322bb561a94e4d332/lru_dict-1.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:edc004c88911a8f9715e716116d2520c13db89afd6c37cc0f28042ba10635163", size = 30574, upload-time = "2025-11-02T10:01:13.293Z"}, + {url = "https://files.pythonhosted.org/packages/d7/92/dfea71402a7ca46332bcb854827ee68bbc9be205e2558c3a40293eca9782/lru_dict-1.4.1-cp311-cp311-win32.whl", hash = "sha256:b0b5360264b37676c405ea0a560744d7dcb2d47adff1e7837113c15fabcc7a71", size = 13031, upload-time = "2025-11-02T10:01:13.96Z"}, + {url = "https://files.pythonhosted.org/packages/3a/7b/4c7d566d77ec3ad9128f07407494c2aec57909f8dd59f0c9910bd4c05840/lru_dict-1.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:bb4b37daad9fe4e796c462f4876cf34e52564630902bdf59a271bc482b48a361", size = 14007, upload-time = "2025-11-02T10:01:14.857Z"}, + {url = "https://files.pythonhosted.org/packages/4f/a8/89e4c26e0e751321b41b0a3007384f97d9eae7a863c49af1c68c43005ca3/lru_dict-1.4.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:7fa342c6e6bc811ee6a17eb569d37b149340d5aa5a637a53438e316a95783838", size = 16683, upload-time = "2025-11-02T10:01:15.891Z"}, + {url = "https://files.pythonhosted.org/packages/f1/34/b3c6fdd120af68b6eeb524d0de3293ff27918ec57f45eed6bef1789fd085/lru_dict-1.4.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:bd86bd202a7c1585d9dc7e5b0c3d52cf76dc56b261b4bbecfeefbbae31a5c97d", size = 11216, upload-time = "2025-11-02T10:01:16.867Z"}, + {url = "https://files.pythonhosted.org/packages/e9/7e/280267ae23f1ec1074ddaab787c5e041e090220e8e37828d51ff4e681dfd/lru_dict-1.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4617554f3e42a8f520c8494842c23b98f5b7f4d5e0410e91a4c3ad0ea5f7e094", size = 11687, upload-time = "2025-11-02T10:01:17.485Z"}, + {url = "https://files.pythonhosted.org/packages/ca/18/fec42416ceff98ae2760067ec72b0b9fc02840e729bbc18059c6a02cb01f/lru_dict-1.4.1-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:40927a6a4284d437047f547e652b15f6f0f40210deb6b9e5b77e556ff0faea0f", size = 31960, upload-time = "2025-11-02T10:01:18.158Z"}, + {url = "https://files.pythonhosted.org/packages/c2/ef/38e7ee1a5d32b9b1629d045fa5a495375383aacfb2945f4d9535b9af9630/lru_dict-1.4.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e2c07ecb6d42494e45d00c2541e6b0ae7659fc3cf89681521ba94b15c682d4fe", size = 32882, upload-time = "2025-11-02T10:01:18.841Z"}, + {url = "https://files.pythonhosted.org/packages/72/82/d56653ca144c291ab37bea5f23c5078ffbe64f7f5b466f91d400590b9106/lru_dict-1.4.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:85b28aa2de7c5f1f6c68221857accd084438df98edbd4f57595795734225770c", size = 34268, upload-time = "2025-11-02T10:01:19.564Z"}, + {url = "https://files.pythonhosted.org/packages/94/ae/382651533d60f0b598757efda56dc87cad5ac311fba8e61f86fb916bf236/lru_dict-1.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:cbbbb4b51e2529ccf7ee8a3c3b834052dbd54871a216cfd229dd2b1194ff293a", size = 32156, upload-time = "2025-11-02T10:01:20.22Z"}, + {url = "https://files.pythonhosted.org/packages/aa/d1/d9df7e9272ccbc96f04c477dfb9abb91fa8fabde86b7fa190cb7b3c7a024/lru_dict-1.4.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:e47040421a13de8bc6404557b3700c33f1f2683cbcce22fe5cacec4c938ce54b", size = 33395, upload-time = "2025-11-02T10:01:20.901Z"}, + {url = "https://files.pythonhosted.org/packages/e9/6e/dafe0f5943a7b3ab24d3429032ff85873acd626087934b8161b55340c13a/lru_dict-1.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:451f7249866cb9564bb40d73bec7ac865574dafd0a4cc91627bbf35be7e99291", size = 31591, upload-time = "2025-11-02T10:01:21.606Z"}, + {url = "https://files.pythonhosted.org/packages/a6/4d/9dd35444592bfb6805548e15971cfce821400966a51130b78dc021ee8f03/lru_dict-1.4.1-cp312-cp312-win32.whl", hash = "sha256:e8996f3f94870ecb236c55d280839390edae7f201858fee770267eac27b8b47d", size = 13119, upload-time = "2025-11-02T10:01:22.61Z"}, + {url = "https://files.pythonhosted.org/packages/8d/82/7e72e30d6c15d65466b3baca87cce15e20848ba6a488868aa54e901141a6/lru_dict-1.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:d90774db1b60c0d5c829cfa5d7fda6db96ed1519296f626575598f9f170cca37", size = 14109, upload-time = "2025-11-02T10:01:23.322Z"}, + {url = "https://files.pythonhosted.org/packages/85/95/ee171a68ae381ab988c50e3b7b136b1c598f5f683ba4a1e10c51e2480408/lru_dict-1.4.1-cp313-cp313-android_21_arm64_v8a.whl", hash = "sha256:2a5644bb1db0514abdad5e2f3d8f1beb6f7560c8cceb62079c40a4269de34b3c", size = 12248, upload-time = "2025-11-02T10:01:24.291Z"}, + {url = "https://files.pythonhosted.org/packages/a1/82/8de8e8fd96c44d46891415834ceb9f51c552840bda2d118394aca5e3153a/lru_dict-1.4.1-cp313-cp313-android_21_x86_64.whl", hash = "sha256:4209864be09ec20f6059fef8544697eb3d3729d63a983bf66457054bf3e40601", size = 12243, upload-time = "2025-11-02T10:01:25.254Z"}, + {url = "https://files.pythonhosted.org/packages/53/97/251cfb357c547a8fd06c2bc40db8a7f7eed7dbacef30d8d7e543522360e1/lru_dict-1.4.1-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:8fef8dd72484b4280799c502c116acfdfcf0dedf3508bc9d0d19e684a6a23267", size = 10938, upload-time = "2025-11-02T10:01:25.89Z"}, + {url = "https://files.pythonhosted.org/packages/58/14/602791d219bc87197ae80f5fa0f77ca0af8e83e9a06c7cdb89db5575839e/lru_dict-1.4.1-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:d64ddbe4c426fdc4cfc1abaea71d587d439397386a7b35d588f4fd64b695a83d", size = 11261, upload-time = "2025-11-02T10:01:26.879Z"}, + {url = "https://files.pythonhosted.org/packages/10/5d/a30a6fad150f20f084de8e243882a0488ad4929db41a2c8ce9be6cf56563/lru_dict-1.4.1-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:000ba9a2ab4dd1ad2d91764a6d5cce75a59de51534cdda478d1ddaa3cd8d5c48", size = 10801, upload-time = "2025-11-02T10:01:27.553Z"}, + {url = "https://files.pythonhosted.org/packages/64/4d/cee327e024d42972c598b7e0cd5063a1b1d7451efba31f7de7b6ca91e7d0/lru_dict-1.4.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ffad2758ce21d8fd6f0ae2628b31330732db8429a4b5994d2e107bed0ee11e68", size = 16688, upload-time = "2025-11-02T10:01:28.17Z"}, + {url = "https://files.pythonhosted.org/packages/58/c8/2f86a1e448c5257b31424b96bf1385e7f96ec7841c2376db02811bbd395f/lru_dict-1.4.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1671e8d92fe35dfb38d3505a56338792d3e225032f8e94888b6e95b323120380", size = 11214, upload-time = "2025-11-02T10:01:28.888Z"}, + {url = "https://files.pythonhosted.org/packages/06/41/507c615cffaba67c35affd77dec25d3183bb87f404b41c8bb2b3053481ac/lru_dict-1.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d5f01ada0cf0c1aa2bdc684e5ac0f6548be7eccc3ce8b4c0361db8445f867f04", size = 11689, upload-time = "2025-11-02T10:01:29.508Z"}, + {url = "https://files.pythonhosted.org/packages/4e/c1/35aa1359f80174016b389f8be5fd48c4a5af0a04a73afb4906e5d4279f4a/lru_dict-1.4.1-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:74204239e30b8ec7976257c5b64565d7e3e8aea0cad0dd50a9b99e171aaf3898", size = 32034, upload-time = "2025-11-02T10:01:30.164Z"}, + {url = "https://files.pythonhosted.org/packages/c2/93/46301015bddd4552a1b76982ef788a7fb2a886efff83ad2c178cc7e68349/lru_dict-1.4.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a7da0e451faa4d6dcae21c0f2527c540000b2f23ed8326a0bc1d870130fd12b1", size = 32919, upload-time = "2025-11-02T10:01:30.971Z"}, + {url = "https://files.pythonhosted.org/packages/e6/cb/6d67145619d8ec3bba15fe145ff702ecf44991e33345d38c763501c1608a/lru_dict-1.4.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:071468a716768a9afca64659c390c1abb6d937b1897e07a0b70383f75637fce0", size = 34334, upload-time = "2025-11-02T10:01:31.663Z"}, + {url = "https://files.pythonhosted.org/packages/a5/44/50daaec6793ec2042079ed6a8b6a687b4be51b270b1d8ec5efd280116493/lru_dict-1.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e77d209bcd396eb236c197bf4c95fab6848c61e0c1a5031cdde7f5c787e209f4", size = 32211, upload-time = "2025-11-02T10:01:32.468Z"}, + {url = "https://files.pythonhosted.org/packages/bd/53/355397949215e6b77b6771b973ee1dbc21fdd9f955925e47dce50d9d4727/lru_dict-1.4.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:b21688fd7ece56d04c0c13b42fd9f904d46fc9ff21e3de87d98f3f5a14c67f74", size = 33461, upload-time = "2025-11-02T10:01:33.2Z"}, + {url = "https://files.pythonhosted.org/packages/ff/fa/d660fa63144f38a0fd5b437a140517e3cff482d955ef6b9b4cf7651b9d85/lru_dict-1.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:989ef7352b347c82e5d5047f3b7ddf34b5a938e3f7b08775cacc9f28e97dd2a8", size = 31651, upload-time = "2025-11-02T10:01:33.874Z"}, + {url = "https://files.pythonhosted.org/packages/2e/77/0fae8d0702f7546f436efe06a684b301aad5c8a167bb2df6e42b0f821de5/lru_dict-1.4.1-cp313-cp313-win32.whl", hash = "sha256:a36e6e95b5d474ef90d04a5e3ad81ca362b473ec9534ed964222f3c0444138b8", size = 13120, upload-time = "2025-11-02T10:01:34.595Z"}, + {url = "https://files.pythonhosted.org/packages/4a/20/56a3f0d74c8fe32c01d3978387f66c9fb180c7f15bfd9fcecaa01b4e7736/lru_dict-1.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:8e73a1ec2d0f476d666ce7c91464b22854086951b319544d1850c508f5ce381f", size = 14112, upload-time = "2025-11-02T10:01:35.268Z"}, + {url = "https://files.pythonhosted.org/packages/98/02/8e04a8d744b466d4153502e2d92b453c2e5a549d49bf7fabfdca1621828a/lru_dict-1.4.1-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:7b770c7db258625e57b6ea8e2e0503ba0fbbdcde374baacf9adb256eb9c5adfa", size = 11119, upload-time = "2025-11-02T10:01:36.239Z"}, + {url = "https://files.pythonhosted.org/packages/50/f8/ee96f30127ff47c29966603f040e0485700fe0ca0e7d7b1ecbc9bf999eea/lru_dict-1.4.1-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:45d4dc338237cedcbacedab1afd9707b8f9867d8b601ec04e0395ec73f57405c", size = 11435, upload-time = "2025-11-02T10:01:36.857Z"}, + {url = "https://files.pythonhosted.org/packages/a0/5a/897b33ba1974b6487848cafa5de7e93a7c4f5d9d3f43319ee010f6882830/lru_dict-1.4.1-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:5b31e9b6636f8945ad69c630c1891d810d62a91d99e792ef0b9ca865b6c26745", size = 10988, upload-time = "2025-11-02T10:01:37.531Z"}, + {url = "https://files.pythonhosted.org/packages/19/8e/b87d0f2bfcad0169afc00e23e014bad9af252206ec2cbc6079f12bece58e/lru_dict-1.4.1-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:f9335d46c83882a1b5deffed8098a2dd9ad66d2bd6263f416fc4c73f63e26904", size = 16733, upload-time = "2025-11-02T10:01:38.194Z"}, + {url = "https://files.pythonhosted.org/packages/ab/19/d2384266864b1e5b1cc20527ae468550d3b23a71636371b40e4663276294/lru_dict-1.4.1-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:17844b4f8dd996144d53380395d73832e2508159ad49ed4fbcb62f1787a5feaf", size = 11222, upload-time = "2025-11-02T10:01:39.093Z"}, + {url = "https://files.pythonhosted.org/packages/66/8a/94dec42ae6b5c8bdc53a86867924fa22634516434f129dca187ccc0853b8/lru_dict-1.4.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:2b569c7813adb753b7b631097c34e6dbc194cb1814f22299c2d2a94894779877", size = 11733, upload-time = "2025-11-02T10:01:39.739Z"}, + {url = "https://files.pythonhosted.org/packages/3f/19/0b6de1db804cf094e201c5541d58e6a96359eb5beed048fa64d0589b6520/lru_dict-1.4.1-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:33cf1eb368d3989b8f00945937cfbfc2095d8ad2b1d2274ce1bde0af6f6d1e66", size = 32251, upload-time = "2025-11-02T10:01:40.421Z"}, + {url = "https://files.pythonhosted.org/packages/97/38/89d9425dde436b9bd894234171988289b259aeeab5965bd2c21d5104cb41/lru_dict-1.4.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:22d5879ec5d5955f9dde105997bdf7ec9e0522bf99612a80b55b09f356a08368", size = 33405, upload-time = "2025-11-02T10:01:41.917Z"}, + {url = "https://files.pythonhosted.org/packages/0e/24/f1a189399ee107a64f955c9d6c84d3b0aee9b64b31fc5684b1eaeb3a6fc0/lru_dict-1.4.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2084363e4488aa5b4f8b26bd3cc148d70a15be92e3d347621a5b830b2b1e0a82", size = 35135, upload-time = "2025-11-02T10:01:42.935Z"}, + {url = "https://files.pythonhosted.org/packages/f8/57/58e9dcf0853d639e2995e5d9f84649ff8d6792a04a418628672a130137f4/lru_dict-1.4.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:8198ab8ad7cc81b86340243ddd5cca882ead87daed0c9fa6cce377a10a7f2e47", size = 32620, upload-time = "2025-11-02T10:01:43.627Z"}, + {url = "https://files.pythonhosted.org/packages/a9/bb/664922f0cf076b1e3c2e43e8258582d507b07c19bd441a72dd5547a483e9/lru_dict-1.4.1-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:f1f4ae6967d5873e684ce8b986e2e43985d0a1be735b09584737ad5634ff48f3", size = 34077, upload-time = "2025-11-02T10:01:44.694Z"}, + {url = "https://files.pythonhosted.org/packages/58/38/b7a6fa85b150232cada26a50c89dc4bcf9acd6ada00e987b074c3b4e57f2/lru_dict-1.4.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:a9bb130b5eaddd6453ca3dc38ce4a75f743512ad135b6f3994999dde0680bd79", size = 31905, upload-time = "2025-11-02T10:01:45.668Z"}, + {url = "https://files.pythonhosted.org/packages/86/7d/9c86393946d621f4aec852d543df4023241d85106e9e1e2a0e4057861f71/lru_dict-1.4.1-cp314-cp314-win32.whl", hash = "sha256:5534c69a52add5757714456d08ce3831d36b86c98972394ba900493bb0bd97f8", size = 13435, upload-time = "2025-11-02T10:01:46.397Z"}, + {url = "https://files.pythonhosted.org/packages/20/3f/b017cbeea55a8a1d18037840a8a9c9cdae29554e9985b55d4e8694305035/lru_dict-1.4.1-cp314-cp314-win_amd64.whl", hash = "sha256:96fd677b6d912229f2d02ba61a5a1210176963c4770c1bb765b8da937cec3834", size = 14423, upload-time = "2025-11-02T10:01:47.473Z"}, + {url = "https://files.pythonhosted.org/packages/aa/73/13132af7a5155edde66979b53eb509465304e6e5a2b00769246448479c73/lru_dict-1.4.1-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:6699bfebbf11dd9ff1387be7996fac6d1009fe6a6f48091ef6e069e6f19c7bce", size = 17184, upload-time = "2025-11-02T10:01:48.161Z"}, + {url = "https://files.pythonhosted.org/packages/ef/82/094985beb3e49461bf65a3c40df8de2018b8484e4ef129295090460ca5d9/lru_dict-1.4.1-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:a276f8f6f43861c3f05986824741d00e3133a973c3396598375310129535382d", size = 11459, upload-time = "2025-11-02T10:01:48.823Z"}, + {url = "https://files.pythonhosted.org/packages/14/29/836abc49f8c2b6c2efccd2ac2b2c0ad3e55b7d75a05a20cc061f17871e39/lru_dict-1.4.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:090c7b6a3d54fa7f3d69ba4802abe2f33c9583b16b33f52bcb521c701f7ea46c", size = 11938, upload-time = "2025-11-02T10:01:49.448Z"}, + {url = "https://files.pythonhosted.org/packages/c2/83/1bb4e8fbc0b753fea825564d9d96180813a71715d46a9b6bb30a6dea4ce0/lru_dict-1.4.1-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b21d06dec64fb1952385262d9fcefaec147921dc0b55210007091a79da440d93", size = 36389, upload-time = "2025-11-02T10:01:50.49Z"}, + {url = "https://files.pythonhosted.org/packages/54/f2/7df3b6d0dbc66f3be9aa6261750967cdc5619c89a563420c52200d2dd547/lru_dict-1.4.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b9613908a38cf8aa47f6c138ba031a8ac4ed38460299e84a2b07dba7b3b45aae", size = 38706, upload-time = "2025-11-02T10:01:51.197Z"}, + {url = "https://files.pythonhosted.org/packages/97/5f/e3ba3eeb9b864a09b92e24fbf179aef4ef48588e763a9d8d2bc10bd2c6f8/lru_dict-1.4.1-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7558302ce8bbfcd29f08e695e07bf7a0d799c2979636d6a6a0b4e207f840969f", size = 38892, upload-time = "2025-11-02T10:01:51.899Z"}, + {url = "https://files.pythonhosted.org/packages/e8/e3/12e0888aab0bf3ab9ce35e9849f239994a0feff6fe49380859bf57124a17/lru_dict-1.4.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:3910396142322fb2718546115bb2a56f50ebc9144b5140327053cca084e0d375", size = 37254, upload-time = "2025-11-02T10:01:52.587Z"}, + {url = "https://files.pythonhosted.org/packages/cc/dc/06cd981718d039eb07a9c03263094aca6269721c470f765a292b24381a20/lru_dict-1.4.1-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:f3f4fad5c4a9458954b275de6a6e31c67a26fbef7037c6a7354e22523a77db26", size = 37422, upload-time = "2025-11-02T10:01:53.271Z"}, + {url = "https://files.pythonhosted.org/packages/e8/82/ea88e618f39d78ff3c15b71f01a0b1a6c6ac2034ce5c6428ae41b1c30ea5/lru_dict-1.4.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:85fc29363e2d3ba0a5f87b5e17f54b1078aea6d24c6dfc792725854b9d0f8d17", size = 35909, upload-time = "2025-11-02T10:01:54.356Z"}, + {url = "https://files.pythonhosted.org/packages/89/36/1dd91c602f623839cec24d6c77fa3fd1a8878bf2d716871197cd3bf084dc/lru_dict-1.4.1-cp314-cp314t-win32.whl", hash = "sha256:b3853518dfa50f28af0d6e2dcf8bb8b0a1687c5f4eb913c0b35b0da5c6d276ce", size = 13816, upload-time = "2025-11-02T10:01:55.417Z"}, + {url = "https://files.pythonhosted.org/packages/ce/a3/113410f7b2e61e9d6f13f1f17c584dbd08b5796e65d772ecd5b063fab3af/lru_dict-1.4.1-cp314-cp314t-win_amd64.whl", hash = "sha256:ff3af42922205620fdc920dcdf580c4c16b32c84a537a03b04b523e5c641a8a9", size = 15204, upload-time = "2025-11-02T10:01:56.06Z"}, + {url = "https://files.pythonhosted.org/packages/8e/47/08c61cad038706b3a89b8c7587ec74ed9731c1e536329745cccb6c840916/lru_dict-1.4.1-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:9219f13e4101c064f70e1815d7c51f9be9e053983e74dfb7bcfdf92f5fcbb0e0", size = 10384, upload-time = "2025-11-02T10:02:09.656Z"}, + {url = "https://files.pythonhosted.org/packages/6b/a1/022c4d7c68c076370231488c97cf7451131fb9ca0d60d1b2785e7baa1f5b/lru_dict-1.4.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:b7e1ac7fb6e91e4d3212e153f9e2d98d163a4439b9bf9df247c22519262c26fe", size = 10822, upload-time = "2025-11-02T10:02:10.609Z"}, + {url = "https://files.pythonhosted.org/packages/65/b4/4c0a0877a77fececa9f58d804569e2aac1bfbe588e3a70e79647b5d8f7d4/lru_dict-1.4.1-pp311-pypy311_pp73-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:23424321b761c43f3021a596565f8205ecec0e175822e7a5d9b2a175578aa7de", size = 12968, upload-time = "2025-11-02T10:02:11.405Z"}, + {url = "https://files.pythonhosted.org/packages/22/06/d7e393d07dc31e656330d5a058f34e972bf590e7dc882922b426f3aec4a0/lru_dict-1.4.1-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:804ee76f98afc3d50e9a2e9c835a6820877aa6391f2add520a57f86b3f55ec3a", size = 13904, upload-time = "2025-11-02T10:02:12.144Z"}, + {url = "https://files.pythonhosted.org/packages/e8/1e/0eee8bcc16bf01b265ac83e4b870596e2f3bcc40d88aa7ec25407180fe44/lru_dict-1.4.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:3be24e24c8998302ea1c28f997505fa6843f507aad3c7d5c3a82cc01c5c11be4", size = 14062, upload-time = "2025-11-02T10:02:12.878Z"} ] [[package]] name = "markdown" +sdist = {url = "https://files.pythonhosted.org/packages/2b/f4/69fa6ed85ae003c2378ffa8f6d2e3234662abd02c10d216c0ba96081a238/markdown-3.10.2.tar.gz", hash = "sha256:994d51325d25ad8aa7ce4ebaec003febcce822c3f8c911e3b17c52f7f589f950", size = 368805, upload-time = "2026-02-09T14:57:26.942Z"} +source = {registry = "https://pypi.org/simple"} version = "3.10.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/2b/f4/69fa6ed85ae003c2378ffa8f6d2e3234662abd02c10d216c0ba96081a238/markdown-3.10.2.tar.gz", hash = "sha256:994d51325d25ad8aa7ce4ebaec003febcce822c3f8c911e3b17c52f7f589f950", size = 368805, upload-time = "2026-02-09T14:57:26.942Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/de/1f/77fa3081e4f66ca3576c896ae5d31c3002ac6607f9747d2e3aa49227e464/markdown-3.10.2-py3-none-any.whl", hash = "sha256:e91464b71ae3ee7afd3017d9f358ef0baf158fd9a298db92f1d4761133824c36", size = 108180, upload-time = "2026-02-09T14:57:25.787Z" }, + {url = "https://files.pythonhosted.org/packages/de/1f/77fa3081e4f66ca3576c896ae5d31c3002ac6607f9747d2e3aa49227e464/markdown-3.10.2-py3-none-any.whl", hash = "sha256:e91464b71ae3ee7afd3017d9f358ef0baf158fd9a298db92f1d4761133824c36", size = 108180, upload-time = "2026-02-09T14:57:25.787Z"} ] [[package]] name = "markupsafe" +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"} +source = {registry = "https://pypi.org/simple"} 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/08/db/fefacb2136439fc8dd20e797950e749aa1f4997ed584c62cfb8ef7c2be0e/markupsafe-3.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1cc7ea17a6824959616c525620e387f6dd30fec8cb44f649e31712db02123dad", size = 11631, upload-time = "2025-09-27T18:36:18.185Z" }, - { url = "https://files.pythonhosted.org/packages/e1/2e/5898933336b61975ce9dc04decbc0a7f2fee78c30353c5efba7f2d6ff27a/markupsafe-3.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4bd4cd07944443f5a265608cc6aab442e4f74dff8088b0dfc8238647b8f6ae9a", size = 12058, upload-time = "2025-09-27T18:36:19.444Z" }, - { url = "https://files.pythonhosted.org/packages/1d/09/adf2df3699d87d1d8184038df46a9c80d78c0148492323f4693df54e17bb/markupsafe-3.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b5420a1d9450023228968e7e6a9ce57f65d148ab56d2313fcd589eee96a7a50", size = 24287, upload-time = "2025-09-27T18:36:20.768Z" }, - { url = "https://files.pythonhosted.org/packages/30/ac/0273f6fcb5f42e314c6d8cd99effae6a5354604d461b8d392b5ec9530a54/markupsafe-3.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0bf2a864d67e76e5c9a34dc26ec616a66b9888e25e7b9460e1c76d3293bd9dbf", size = 22940, upload-time = "2025-09-27T18:36:22.249Z" }, - { url = "https://files.pythonhosted.org/packages/19/ae/31c1be199ef767124c042c6c3e904da327a2f7f0cd63a0337e1eca2967a8/markupsafe-3.0.3-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc51efed119bc9cfdf792cdeaa4d67e8f6fcccab66ed4bfdd6bde3e59bfcbb2f", size = 21887, upload-time = "2025-09-27T18:36:23.535Z" }, - { url = "https://files.pythonhosted.org/packages/b2/76/7edcab99d5349a4532a459e1fe64f0b0467a3365056ae550d3bcf3f79e1e/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:068f375c472b3e7acbe2d5318dea141359e6900156b5b2ba06a30b169086b91a", size = 23692, upload-time = "2025-09-27T18:36:24.823Z" }, - { url = "https://files.pythonhosted.org/packages/a4/28/6e74cdd26d7514849143d69f0bf2399f929c37dc2b31e6829fd2045b2765/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:7be7b61bb172e1ed687f1754f8e7484f1c8019780f6f6b0786e76bb01c2ae115", size = 21471, upload-time = "2025-09-27T18:36:25.95Z" }, - { url = "https://files.pythonhosted.org/packages/62/7e/a145f36a5c2945673e590850a6f8014318d5577ed7e5920a4b3448e0865d/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a", size = 22923, upload-time = "2025-09-27T18:36:27.109Z" }, - { url = "https://files.pythonhosted.org/packages/0f/62/d9c46a7f5c9adbeeeda52f5b8d802e1094e9717705a645efc71b0913a0a8/markupsafe-3.0.3-cp311-cp311-win32.whl", hash = "sha256:0db14f5dafddbb6d9208827849fad01f1a2609380add406671a26386cdf15a19", size = 14572, upload-time = "2025-09-27T18:36:28.045Z" }, - { url = "https://files.pythonhosted.org/packages/83/8a/4414c03d3f891739326e1783338e48fb49781cc915b2e0ee052aa490d586/markupsafe-3.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:de8a88e63464af587c950061a5e6a67d3632e36df62b986892331d4620a35c01", size = 15077, upload-time = "2025-09-27T18:36:29.025Z" }, - { url = "https://files.pythonhosted.org/packages/35/73/893072b42e6862f319b5207adc9ae06070f095b358655f077f69a35601f0/markupsafe-3.0.3-cp311-cp311-win_arm64.whl", hash = "sha256:3b562dd9e9ea93f13d53989d23a7e775fdfd1066c33494ff43f5418bc8c58a5c", size = 13876, upload-time = "2025-09-27T18:36:29.954Z" }, - { url = "https://files.pythonhosted.org/packages/5a/72/147da192e38635ada20e0a2e1a51cf8823d2119ce8883f7053879c2199b5/markupsafe-3.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d53197da72cc091b024dd97249dfc7794d6a56530370992a5e1a08983ad9230e", size = 11615, upload-time = "2025-09-27T18:36:30.854Z" }, - { url = "https://files.pythonhosted.org/packages/9a/81/7e4e08678a1f98521201c3079f77db69fb552acd56067661f8c2f534a718/markupsafe-3.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1872df69a4de6aead3491198eaf13810b565bdbeec3ae2dc8780f14458ec73ce", size = 12020, upload-time = "2025-09-27T18:36:31.971Z" }, - { url = "https://files.pythonhosted.org/packages/1e/2c/799f4742efc39633a1b54a92eec4082e4f815314869865d876824c257c1e/markupsafe-3.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3a7e8ae81ae39e62a41ec302f972ba6ae23a5c5396c8e60113e9066ef893da0d", size = 24332, upload-time = "2025-09-27T18:36:32.813Z" }, - { url = "https://files.pythonhosted.org/packages/3c/2e/8d0c2ab90a8c1d9a24f0399058ab8519a3279d1bd4289511d74e909f060e/markupsafe-3.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d6dd0be5b5b189d31db7cda48b91d7e0a9795f31430b7f271219ab30f1d3ac9d", size = 22947, upload-time = "2025-09-27T18:36:33.86Z" }, - { url = "https://files.pythonhosted.org/packages/2c/54/887f3092a85238093a0b2154bd629c89444f395618842e8b0c41783898ea/markupsafe-3.0.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:94c6f0bb423f739146aec64595853541634bde58b2135f27f61c1ffd1cd4d16a", size = 21962, upload-time = "2025-09-27T18:36:35.099Z" }, - { url = "https://files.pythonhosted.org/packages/c9/2f/336b8c7b6f4a4d95e91119dc8521402461b74a485558d8f238a68312f11c/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:be8813b57049a7dc738189df53d69395eba14fb99345e0a5994914a3864c8a4b", size = 23760, upload-time = "2025-09-27T18:36:36.001Z" }, - { url = "https://files.pythonhosted.org/packages/32/43/67935f2b7e4982ffb50a4d169b724d74b62a3964bc1a9a527f5ac4f1ee2b/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:83891d0e9fb81a825d9a6d61e3f07550ca70a076484292a70fde82c4b807286f", size = 21529, upload-time = "2025-09-27T18:36:36.906Z" }, - { url = "https://files.pythonhosted.org/packages/89/e0/4486f11e51bbba8b0c041098859e869e304d1c261e59244baa3d295d47b7/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:77f0643abe7495da77fb436f50f8dab76dbc6e5fd25d39589a0f1fe6548bfa2b", size = 23015, upload-time = "2025-09-27T18:36:37.868Z" }, - { url = "https://files.pythonhosted.org/packages/2f/e1/78ee7a023dac597a5825441ebd17170785a9dab23de95d2c7508ade94e0e/markupsafe-3.0.3-cp312-cp312-win32.whl", hash = "sha256:d88b440e37a16e651bda4c7c2b930eb586fd15ca7406cb39e211fcff3bf3017d", size = 14540, upload-time = "2025-09-27T18:36:38.761Z" }, - { url = "https://files.pythonhosted.org/packages/aa/5b/bec5aa9bbbb2c946ca2733ef9c4ca91c91b6a24580193e891b5f7dbe8e1e/markupsafe-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:26a5784ded40c9e318cfc2bdb30fe164bdb8665ded9cd64d500a34fb42067b1c", size = 15105, upload-time = "2025-09-27T18:36:39.701Z" }, - { url = "https://files.pythonhosted.org/packages/e5/f1/216fc1bbfd74011693a4fd837e7026152e89c4bcf3e77b6692fba9923123/markupsafe-3.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:35add3b638a5d900e807944a078b51922212fb3dedb01633a8defc4b01a3c85f", size = 13906, upload-time = "2025-09-27T18:36:40.689Z" }, - { 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" }, +wheels = [ + {url = "https://files.pythonhosted.org/packages/08/db/fefacb2136439fc8dd20e797950e749aa1f4997ed584c62cfb8ef7c2be0e/markupsafe-3.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1cc7ea17a6824959616c525620e387f6dd30fec8cb44f649e31712db02123dad", size = 11631, upload-time = "2025-09-27T18:36:18.185Z"}, + {url = "https://files.pythonhosted.org/packages/e1/2e/5898933336b61975ce9dc04decbc0a7f2fee78c30353c5efba7f2d6ff27a/markupsafe-3.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4bd4cd07944443f5a265608cc6aab442e4f74dff8088b0dfc8238647b8f6ae9a", size = 12058, upload-time = "2025-09-27T18:36:19.444Z"}, + {url = "https://files.pythonhosted.org/packages/1d/09/adf2df3699d87d1d8184038df46a9c80d78c0148492323f4693df54e17bb/markupsafe-3.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b5420a1d9450023228968e7e6a9ce57f65d148ab56d2313fcd589eee96a7a50", size = 24287, upload-time = "2025-09-27T18:36:20.768Z"}, + {url = "https://files.pythonhosted.org/packages/30/ac/0273f6fcb5f42e314c6d8cd99effae6a5354604d461b8d392b5ec9530a54/markupsafe-3.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0bf2a864d67e76e5c9a34dc26ec616a66b9888e25e7b9460e1c76d3293bd9dbf", size = 22940, upload-time = "2025-09-27T18:36:22.249Z"}, + {url = "https://files.pythonhosted.org/packages/19/ae/31c1be199ef767124c042c6c3e904da327a2f7f0cd63a0337e1eca2967a8/markupsafe-3.0.3-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc51efed119bc9cfdf792cdeaa4d67e8f6fcccab66ed4bfdd6bde3e59bfcbb2f", size = 21887, upload-time = "2025-09-27T18:36:23.535Z"}, + {url = "https://files.pythonhosted.org/packages/b2/76/7edcab99d5349a4532a459e1fe64f0b0467a3365056ae550d3bcf3f79e1e/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:068f375c472b3e7acbe2d5318dea141359e6900156b5b2ba06a30b169086b91a", size = 23692, upload-time = "2025-09-27T18:36:24.823Z"}, + {url = "https://files.pythonhosted.org/packages/a4/28/6e74cdd26d7514849143d69f0bf2399f929c37dc2b31e6829fd2045b2765/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:7be7b61bb172e1ed687f1754f8e7484f1c8019780f6f6b0786e76bb01c2ae115", size = 21471, upload-time = "2025-09-27T18:36:25.95Z"}, + {url = "https://files.pythonhosted.org/packages/62/7e/a145f36a5c2945673e590850a6f8014318d5577ed7e5920a4b3448e0865d/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a", size = 22923, upload-time = "2025-09-27T18:36:27.109Z"}, + {url = "https://files.pythonhosted.org/packages/0f/62/d9c46a7f5c9adbeeeda52f5b8d802e1094e9717705a645efc71b0913a0a8/markupsafe-3.0.3-cp311-cp311-win32.whl", hash = "sha256:0db14f5dafddbb6d9208827849fad01f1a2609380add406671a26386cdf15a19", size = 14572, upload-time = "2025-09-27T18:36:28.045Z"}, + {url = "https://files.pythonhosted.org/packages/83/8a/4414c03d3f891739326e1783338e48fb49781cc915b2e0ee052aa490d586/markupsafe-3.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:de8a88e63464af587c950061a5e6a67d3632e36df62b986892331d4620a35c01", size = 15077, upload-time = "2025-09-27T18:36:29.025Z"}, + {url = "https://files.pythonhosted.org/packages/35/73/893072b42e6862f319b5207adc9ae06070f095b358655f077f69a35601f0/markupsafe-3.0.3-cp311-cp311-win_arm64.whl", hash = "sha256:3b562dd9e9ea93f13d53989d23a7e775fdfd1066c33494ff43f5418bc8c58a5c", size = 13876, upload-time = "2025-09-27T18:36:29.954Z"}, + {url = "https://files.pythonhosted.org/packages/5a/72/147da192e38635ada20e0a2e1a51cf8823d2119ce8883f7053879c2199b5/markupsafe-3.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d53197da72cc091b024dd97249dfc7794d6a56530370992a5e1a08983ad9230e", size = 11615, upload-time = "2025-09-27T18:36:30.854Z"}, + {url = "https://files.pythonhosted.org/packages/9a/81/7e4e08678a1f98521201c3079f77db69fb552acd56067661f8c2f534a718/markupsafe-3.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1872df69a4de6aead3491198eaf13810b565bdbeec3ae2dc8780f14458ec73ce", size = 12020, upload-time = "2025-09-27T18:36:31.971Z"}, + {url = "https://files.pythonhosted.org/packages/1e/2c/799f4742efc39633a1b54a92eec4082e4f815314869865d876824c257c1e/markupsafe-3.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3a7e8ae81ae39e62a41ec302f972ba6ae23a5c5396c8e60113e9066ef893da0d", size = 24332, upload-time = "2025-09-27T18:36:32.813Z"}, + {url = "https://files.pythonhosted.org/packages/3c/2e/8d0c2ab90a8c1d9a24f0399058ab8519a3279d1bd4289511d74e909f060e/markupsafe-3.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d6dd0be5b5b189d31db7cda48b91d7e0a9795f31430b7f271219ab30f1d3ac9d", size = 22947, upload-time = "2025-09-27T18:36:33.86Z"}, + {url = "https://files.pythonhosted.org/packages/2c/54/887f3092a85238093a0b2154bd629c89444f395618842e8b0c41783898ea/markupsafe-3.0.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:94c6f0bb423f739146aec64595853541634bde58b2135f27f61c1ffd1cd4d16a", size = 21962, upload-time = "2025-09-27T18:36:35.099Z"}, + {url = "https://files.pythonhosted.org/packages/c9/2f/336b8c7b6f4a4d95e91119dc8521402461b74a485558d8f238a68312f11c/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:be8813b57049a7dc738189df53d69395eba14fb99345e0a5994914a3864c8a4b", size = 23760, upload-time = "2025-09-27T18:36:36.001Z"}, + {url = "https://files.pythonhosted.org/packages/32/43/67935f2b7e4982ffb50a4d169b724d74b62a3964bc1a9a527f5ac4f1ee2b/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:83891d0e9fb81a825d9a6d61e3f07550ca70a076484292a70fde82c4b807286f", size = 21529, upload-time = "2025-09-27T18:36:36.906Z"}, + {url = "https://files.pythonhosted.org/packages/89/e0/4486f11e51bbba8b0c041098859e869e304d1c261e59244baa3d295d47b7/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:77f0643abe7495da77fb436f50f8dab76dbc6e5fd25d39589a0f1fe6548bfa2b", size = 23015, upload-time = "2025-09-27T18:36:37.868Z"}, + {url = "https://files.pythonhosted.org/packages/2f/e1/78ee7a023dac597a5825441ebd17170785a9dab23de95d2c7508ade94e0e/markupsafe-3.0.3-cp312-cp312-win32.whl", hash = "sha256:d88b440e37a16e651bda4c7c2b930eb586fd15ca7406cb39e211fcff3bf3017d", size = 14540, upload-time = "2025-09-27T18:36:38.761Z"}, + {url = "https://files.pythonhosted.org/packages/aa/5b/bec5aa9bbbb2c946ca2733ef9c4ca91c91b6a24580193e891b5f7dbe8e1e/markupsafe-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:26a5784ded40c9e318cfc2bdb30fe164bdb8665ded9cd64d500a34fb42067b1c", size = 15105, upload-time = "2025-09-27T18:36:39.701Z"}, + {url = "https://files.pythonhosted.org/packages/e5/f1/216fc1bbfd74011693a4fd837e7026152e89c4bcf3e77b6692fba9923123/markupsafe-3.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:35add3b638a5d900e807944a078b51922212fb3dedb01633a8defc4b01a3c85f", size = 13906, upload-time = "2025-09-27T18:36:40.689Z"}, + {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-inline" -version = "0.2.1" -source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "traitlets" }, + {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" } +name = "matplotlib-inline" +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"} +source = {registry = "https://pypi.org/simple"} +version = "0.2.1" 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" }, + {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 = "multiurl" -version = "0.3.7" -source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "python-dateutil" }, - { name = "pytz" }, - { name = "requests" }, - { name = "tqdm" }, + {name = "python-dateutil"}, + {name = "pytz"}, + {name = "requests"}, + {name = "tqdm"} ] -sdist = { url = "https://files.pythonhosted.org/packages/6c/ce/a00c9b44f43c4620ca004e4acb4c1e266b1ab48d2f6ad9e402f6bdbe44d4/multiurl-0.3.7.tar.gz", hash = "sha256:4201563fc8989baca7b525fdc69d4cd5a6c0cef4f303559710b9890021aab6d9", size = 18945, upload-time = "2025-07-29T11:57:04.109Z" } +name = "multiurl" +sdist = {url = "https://files.pythonhosted.org/packages/6c/ce/a00c9b44f43c4620ca004e4acb4c1e266b1ab48d2f6ad9e402f6bdbe44d4/multiurl-0.3.7.tar.gz", hash = "sha256:4201563fc8989baca7b525fdc69d4cd5a6c0cef4f303559710b9890021aab6d9", size = 18945, upload-time = "2025-07-29T11:57:04.109Z"} +source = {registry = "https://pypi.org/simple"} +version = "0.3.7" wheels = [ - { url = "https://files.pythonhosted.org/packages/93/cf/be4e93afbfa0def2cd6fac9302071db0bd6d0617999ecbf53f92b9398de3/multiurl-0.3.7-py3-none-any.whl", hash = "sha256:054f42974064f103be0ed55b43f0c32fc435a47dc7353a9adaffa643b99fa380", size = 21524, upload-time = "2025-07-29T11:57:03.191Z" }, + {url = "https://files.pythonhosted.org/packages/93/cf/be4e93afbfa0def2cd6fac9302071db0bd6d0617999ecbf53f92b9398de3/multiurl-0.3.7-py3-none-any.whl", hash = "sha256:054f42974064f103be0ed55b43f0c32fc435a47dc7353a9adaffa643b99fa380", size = 21524, upload-time = "2025-07-29T11:57:03.191Z"} ] [[package]] name = "narwhals" +sdist = {url = "https://files.pythonhosted.org/packages/75/59/81d0f4cad21484083466f278e6b392addd9f4205b48d45b5c8771670ebf8/narwhals-2.17.0.tar.gz", hash = "sha256:ebd5bc95bcfa2f8e89a8ac09e2765a63055162837208e67b42d6eeb6651d5e67", size = 620306, upload-time = "2026-02-23T09:44:34.142Z"} +source = {registry = "https://pypi.org/simple"} version = "2.17.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/75/59/81d0f4cad21484083466f278e6b392addd9f4205b48d45b5c8771670ebf8/narwhals-2.17.0.tar.gz", hash = "sha256:ebd5bc95bcfa2f8e89a8ac09e2765a63055162837208e67b42d6eeb6651d5e67", size = 620306, upload-time = "2026-02-23T09:44:34.142Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/4b/27/20770bd6bf8fbe1e16f848ba21da9df061f38d2e6483952c29d2bb5d1d8b/narwhals-2.17.0-py3-none-any.whl", hash = "sha256:2ac5307b7c2b275a7d66eeda906b8605e3d7a760951e188dcfff86e8ebe083dd", size = 444897, upload-time = "2026-02-23T09:44:32.006Z" }, + {url = "https://files.pythonhosted.org/packages/4b/27/20770bd6bf8fbe1e16f848ba21da9df061f38d2e6483952c29d2bb5d1d8b/narwhals-2.17.0-py3-none-any.whl", hash = "sha256:2ac5307b7c2b275a7d66eeda906b8605e3d7a760951e188dcfff86e8ebe083dd", size = 444897, upload-time = "2026-02-23T09:44:32.006Z"} ] [[package]] +dependencies = [ + {name = "certifi"}, + {name = "cftime"}, + {name = "numpy"} +] name = "netcdf4" +sdist = {url = "https://files.pythonhosted.org/packages/34/b6/0370bb3af66a12098da06dc5843f3b349b7c83ccbdf7306e7afa6248b533/netcdf4-1.7.4.tar.gz", hash = "sha256:cdbfdc92d6f4d7192ca8506c9b3d4c1d9892969ff28d8e8e1fc97ca08bf12164", size = 838352, upload-time = "2026-01-05T02:27:38.593Z"} +source = {registry = "https://pypi.org/simple"} version = "1.7.4" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "certifi" }, - { name = "cftime" }, - { name = "numpy" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/34/b6/0370bb3af66a12098da06dc5843f3b349b7c83ccbdf7306e7afa6248b533/netcdf4-1.7.4.tar.gz", hash = "sha256:cdbfdc92d6f4d7192ca8506c9b3d4c1d9892969ff28d8e8e1fc97ca08bf12164", size = 838352, upload-time = "2026-01-05T02:27:38.593Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/38/de/38ed7e1956943d28e8ea74161e97c3a00fb98d6d08943b4fd21bae32c240/netcdf4-1.7.4-cp311-abi3-macosx_13_0_x86_64.whl", hash = "sha256:dec70e809cc65b04ebe95113ee9c85ba46a51c3a37c058d2b2b0cadc4d3052d8", size = 23427499, upload-time = "2026-01-05T02:27:06.568Z" }, - { url = "https://files.pythonhosted.org/packages/e5/70/2f73c133b71709c412bc81d8b721e28dc6237ba9d7dad861b7bfbb70408a/netcdf4-1.7.4-cp311-abi3-macosx_14_0_arm64.whl", hash = "sha256:75cf59100f0775bc4d6b9d4aca7cbabd12e2b8cf3b9a4fb16d810b92743a315a", size = 22847667, upload-time = "2026-01-05T02:27:09.421Z" }, - { url = "https://files.pythonhosted.org/packages/77/ce/43a3c0c41a6e2e940d87feea79d29aa88302211ac122604838f8a5a48de6/netcdf4-1.7.4-cp311-abi3-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ddfc7e9d261125c74708119440c85ea288b5fee41db676d2ba1ce9be11f96932", size = 10274769, upload-time = "2026-01-05T21:31:19.243Z" }, - { url = "https://files.pythonhosted.org/packages/7b/7a/a8d32501bb95ecff342004a674720164f95ad616f269450b3bc13dc88ae3/netcdf4-1.7.4-cp311-abi3-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a72c9f58767779ec14cb7451c3b56bdd8fdc027a792fac2062b14e090c5617f3", size = 10123122, upload-time = "2026-01-05T21:31:22.773Z" }, - { url = "https://files.pythonhosted.org/packages/18/68/e89b4fa9242e59326c849c39ce0f49eb68499603c639405a8449900a4f15/netcdf4-1.7.4-cp311-abi3-win_amd64.whl", hash = "sha256:9476e1f23161ae5159cd1548c50c8a37922e77d76583e247133f256ef7b825fc", size = 21299637, upload-time = "2026-01-05T02:27:11.856Z" }, - { url = "https://files.pythonhosted.org/packages/6c/fc/edd41a3607241027aa4533e7f18e0cd647e74dde10a63274c65350f59967/netcdf4-1.7.4-cp311-abi3-win_arm64.whl", hash = "sha256:876ad9d58f09c98741c066c726164c45a098a58fb90e5fac9e74de4bb8a793fd", size = 2386377, upload-time = "2026-01-05T02:27:13.808Z" }, - { url = "https://files.pythonhosted.org/packages/f1/3e/1e83534ba68459bc5ae39df46fa71003984df58aabf31f7dcd6e22ecddb0/netcdf4-1.7.4-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:56688c03444fffe0d0c7512cb45245e650389cd841c955b30e4552fa681c4cd9", size = 10519821, upload-time = "2026-01-05T02:27:15.413Z" }, - { url = "https://files.pythonhosted.org/packages/c0/8c/a15d6fe97f81d6d5202b17838a9a298b5955b3e9971e20609195112829b5/netcdf4-1.7.4-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7ecf471ba8a6ddb2200121949bedfa0095db228822f38227d5da680694a38358", size = 10371133, upload-time = "2026-01-05T02:27:17.224Z" }, - { url = "https://files.pythonhosted.org/packages/d8/2b/684b15dd4791f8be295b2f6fa97377bbc07a768478a63b7d3c4951712e36/netcdf4-1.7.4-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a5841de0735e8e4875b367c668e81d334287858d64dd9f3e3e2261e808c84922", size = 10395635, upload-time = "2026-01-05T02:27:19.655Z" }, - { url = "https://files.pythonhosted.org/packages/37/dc/44d21524cf1b1c64254f92e22395a7a10f70c18f3a13a18ac9db258760f7/netcdf4-1.7.4-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:86fac03a8c5b250d57866e7d98918a64742e4b0de1681c5c86bac5726bab8aee", size = 10237725, upload-time = "2026-01-05T02:27:22.298Z" }, - { url = "https://files.pythonhosted.org/packages/d4/9d/c3ddf54296ad8f18f02f77f23452bdb0971aece1b87e84bab9d734bf72cc/netcdf4-1.7.4-cp314-cp314t-macosx_13_0_x86_64.whl", hash = "sha256:ad083d260301b5add74b1669c75ab0df03bdf986decfcc092cb45eec2615b5f1", size = 23515258, upload-time = "2026-01-05T02:27:24.837Z" }, - { url = "https://files.pythonhosted.org/packages/dd/44/bc0346e995d436d03fab682b7fbd2a9adcf0db6a05790b8f24853bf08170/netcdf4-1.7.4-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:7f22014092cc9da3f056b0368e2e38c42afd5725c87ad4843eb2f467e16dd4f6", size = 22910171, upload-time = "2026-01-05T02:27:27.166Z" }, - { url = "https://files.pythonhosted.org/packages/30/6b/f9bc3f43c55e2dac72ee9f98d77860789bdd5d50c29adf164a6bdb303078/netcdf4-1.7.4-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:224a15434c165a5e0225e5831f591edf62533044b1ce62fdfee815195bbd077d", size = 10567579, upload-time = "2026-01-05T02:27:29.382Z" }, - { url = "https://files.pythonhosted.org/packages/6d/d5/e7685c66b7f011c73cd746127f986358a26c642a4e4a1aa5ab51481b6586/netcdf4-1.7.4-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:31a2318305de6831a18df25ad0df9f03b6d68666af0356d4f6057d66c02ffeb6", size = 10255032, upload-time = "2026-01-05T02:27:31.744Z" }, - { url = "https://files.pythonhosted.org/packages/a6/14/7506738bb6c8bc373b01e5af8f3b727f83f4f496c6b108490ea2609dc2cf/netcdf4-1.7.4-cp314-cp314t-win_amd64.whl", hash = "sha256:6c4a0aa9446c3a616ef3be015b629dc6173643f8b09546de26a4e40e272cd1ed", size = 22289653, upload-time = "2026-01-05T02:27:34.294Z" }, - { url = "https://files.pythonhosted.org/packages/af/2e/39d5e9179c543f2e6e149a65908f83afd9b6d64379a90789b323111761db/netcdf4-1.7.4-cp314-cp314t-win_arm64.whl", hash = "sha256:034220887d48da032cb2db5958f69759dbb04eb33e279ec6390571d4aea734fe", size = 2531682, upload-time = "2026-01-05T02:27:37.062Z" }, +wheels = [ + {url = "https://files.pythonhosted.org/packages/38/de/38ed7e1956943d28e8ea74161e97c3a00fb98d6d08943b4fd21bae32c240/netcdf4-1.7.4-cp311-abi3-macosx_13_0_x86_64.whl", hash = "sha256:dec70e809cc65b04ebe95113ee9c85ba46a51c3a37c058d2b2b0cadc4d3052d8", size = 23427499, upload-time = "2026-01-05T02:27:06.568Z"}, + {url = "https://files.pythonhosted.org/packages/e5/70/2f73c133b71709c412bc81d8b721e28dc6237ba9d7dad861b7bfbb70408a/netcdf4-1.7.4-cp311-abi3-macosx_14_0_arm64.whl", hash = "sha256:75cf59100f0775bc4d6b9d4aca7cbabd12e2b8cf3b9a4fb16d810b92743a315a", size = 22847667, upload-time = "2026-01-05T02:27:09.421Z"}, + {url = "https://files.pythonhosted.org/packages/77/ce/43a3c0c41a6e2e940d87feea79d29aa88302211ac122604838f8a5a48de6/netcdf4-1.7.4-cp311-abi3-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ddfc7e9d261125c74708119440c85ea288b5fee41db676d2ba1ce9be11f96932", size = 10274769, upload-time = "2026-01-05T21:31:19.243Z"}, + {url = "https://files.pythonhosted.org/packages/7b/7a/a8d32501bb95ecff342004a674720164f95ad616f269450b3bc13dc88ae3/netcdf4-1.7.4-cp311-abi3-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a72c9f58767779ec14cb7451c3b56bdd8fdc027a792fac2062b14e090c5617f3", size = 10123122, upload-time = "2026-01-05T21:31:22.773Z"}, + {url = "https://files.pythonhosted.org/packages/18/68/e89b4fa9242e59326c849c39ce0f49eb68499603c639405a8449900a4f15/netcdf4-1.7.4-cp311-abi3-win_amd64.whl", hash = "sha256:9476e1f23161ae5159cd1548c50c8a37922e77d76583e247133f256ef7b825fc", size = 21299637, upload-time = "2026-01-05T02:27:11.856Z"}, + {url = "https://files.pythonhosted.org/packages/6c/fc/edd41a3607241027aa4533e7f18e0cd647e74dde10a63274c65350f59967/netcdf4-1.7.4-cp311-abi3-win_arm64.whl", hash = "sha256:876ad9d58f09c98741c066c726164c45a098a58fb90e5fac9e74de4bb8a793fd", size = 2386377, upload-time = "2026-01-05T02:27:13.808Z"}, + {url = "https://files.pythonhosted.org/packages/f1/3e/1e83534ba68459bc5ae39df46fa71003984df58aabf31f7dcd6e22ecddb0/netcdf4-1.7.4-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:56688c03444fffe0d0c7512cb45245e650389cd841c955b30e4552fa681c4cd9", size = 10519821, upload-time = "2026-01-05T02:27:15.413Z"}, + {url = "https://files.pythonhosted.org/packages/c0/8c/a15d6fe97f81d6d5202b17838a9a298b5955b3e9971e20609195112829b5/netcdf4-1.7.4-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7ecf471ba8a6ddb2200121949bedfa0095db228822f38227d5da680694a38358", size = 10371133, upload-time = "2026-01-05T02:27:17.224Z"}, + {url = "https://files.pythonhosted.org/packages/d8/2b/684b15dd4791f8be295b2f6fa97377bbc07a768478a63b7d3c4951712e36/netcdf4-1.7.4-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a5841de0735e8e4875b367c668e81d334287858d64dd9f3e3e2261e808c84922", size = 10395635, upload-time = "2026-01-05T02:27:19.655Z"}, + {url = "https://files.pythonhosted.org/packages/37/dc/44d21524cf1b1c64254f92e22395a7a10f70c18f3a13a18ac9db258760f7/netcdf4-1.7.4-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:86fac03a8c5b250d57866e7d98918a64742e4b0de1681c5c86bac5726bab8aee", size = 10237725, upload-time = "2026-01-05T02:27:22.298Z"}, + {url = "https://files.pythonhosted.org/packages/d4/9d/c3ddf54296ad8f18f02f77f23452bdb0971aece1b87e84bab9d734bf72cc/netcdf4-1.7.4-cp314-cp314t-macosx_13_0_x86_64.whl", hash = "sha256:ad083d260301b5add74b1669c75ab0df03bdf986decfcc092cb45eec2615b5f1", size = 23515258, upload-time = "2026-01-05T02:27:24.837Z"}, + {url = "https://files.pythonhosted.org/packages/dd/44/bc0346e995d436d03fab682b7fbd2a9adcf0db6a05790b8f24853bf08170/netcdf4-1.7.4-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:7f22014092cc9da3f056b0368e2e38c42afd5725c87ad4843eb2f467e16dd4f6", size = 22910171, upload-time = "2026-01-05T02:27:27.166Z"}, + {url = "https://files.pythonhosted.org/packages/30/6b/f9bc3f43c55e2dac72ee9f98d77860789bdd5d50c29adf164a6bdb303078/netcdf4-1.7.4-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:224a15434c165a5e0225e5831f591edf62533044b1ce62fdfee815195bbd077d", size = 10567579, upload-time = "2026-01-05T02:27:29.382Z"}, + {url = "https://files.pythonhosted.org/packages/6d/d5/e7685c66b7f011c73cd746127f986358a26c642a4e4a1aa5ab51481b6586/netcdf4-1.7.4-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:31a2318305de6831a18df25ad0df9f03b6d68666af0356d4f6057d66c02ffeb6", size = 10255032, upload-time = "2026-01-05T02:27:31.744Z"}, + {url = "https://files.pythonhosted.org/packages/a6/14/7506738bb6c8bc373b01e5af8f3b727f83f4f496c6b108490ea2609dc2cf/netcdf4-1.7.4-cp314-cp314t-win_amd64.whl", hash = "sha256:6c4a0aa9446c3a616ef3be015b629dc6173643f8b09546de26a4e40e272cd1ed", size = 22289653, upload-time = "2026-01-05T02:27:34.294Z"}, + {url = "https://files.pythonhosted.org/packages/af/2e/39d5e9179c543f2e6e149a65908f83afd9b6d64379a90789b323111761db/netcdf4-1.7.4-cp314-cp314t-win_arm64.whl", hash = "sha256:034220887d48da032cb2db5958f69759dbb04eb33e279ec6390571d4aea734fe", size = 2531682, upload-time = "2026-01-05T02:27:37.062Z"} ] [[package]] name = "networkx" +sdist = {url = "https://files.pythonhosted.org/packages/6a/51/63fe664f3908c97be9d2e4f1158eb633317598cfa6e1fc14af5383f17512/networkx-3.6.1.tar.gz", hash = "sha256:26b7c357accc0c8cde558ad486283728b65b6a95d85ee1cd66bafab4c8168509", size = 2517025, upload-time = "2025-12-08T17:02:39.908Z"} +source = {registry = "https://pypi.org/simple"} version = "3.6.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/6a/51/63fe664f3908c97be9d2e4f1158eb633317598cfa6e1fc14af5383f17512/networkx-3.6.1.tar.gz", hash = "sha256:26b7c357accc0c8cde558ad486283728b65b6a95d85ee1cd66bafab4c8168509", size = 2517025, upload-time = "2025-12-08T17:02:39.908Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/9e/c9/b2622292ea83fbb4ec318f5b9ab867d0a28ab43c5717bb85b0a5f6b3b0a4/networkx-3.6.1-py3-none-any.whl", hash = "sha256:d47fbf302e7d9cbbb9e2555a0d267983d2aa476bac30e90dfbe5669bd57f3762", size = 2068504, upload-time = "2025-12-08T17:02:38.159Z" }, + {url = "https://files.pythonhosted.org/packages/9e/c9/b2622292ea83fbb4ec318f5b9ab867d0a28ab43c5717bb85b0a5f6b3b0a4/networkx-3.6.1-py3-none-any.whl", hash = "sha256:d47fbf302e7d9cbbb9e2555a0d267983d2aa476bac30e90dfbe5669bd57f3762", size = 2068504, upload-time = "2025-12-08T17:02:38.159Z"} ] [[package]] name = "numpy" +sdist = {url = "https://files.pythonhosted.org/packages/57/fd/0005efbd0af48e55eb3c7208af93f2862d4b1a56cd78e84309a2d959208d/numpy-2.4.2.tar.gz", hash = "sha256:659a6107e31a83c4e33f763942275fd278b21d095094044eb35569e86a21ddae", size = 20723651, upload-time = "2026-01-31T23:13:10.135Z"} +source = {registry = "https://pypi.org/simple"} version = "2.4.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/57/fd/0005efbd0af48e55eb3c7208af93f2862d4b1a56cd78e84309a2d959208d/numpy-2.4.2.tar.gz", hash = "sha256:659a6107e31a83c4e33f763942275fd278b21d095094044eb35569e86a21ddae", size = 20723651, upload-time = "2026-01-31T23:13:10.135Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d3/44/71852273146957899753e69986246d6a176061ea183407e95418c2aa4d9a/numpy-2.4.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e7e88598032542bd49af7c4747541422884219056c268823ef6e5e89851c8825", size = 16955478, upload-time = "2026-01-31T23:10:25.623Z" }, - { url = "https://files.pythonhosted.org/packages/74/41/5d17d4058bd0cd96bcbd4d9ff0fb2e21f52702aab9a72e4a594efa18692f/numpy-2.4.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7edc794af8b36ca37ef5fcb5e0d128c7e0595c7b96a2318d1badb6fcd8ee86b1", size = 14965467, upload-time = "2026-01-31T23:10:28.186Z" }, - { url = "https://files.pythonhosted.org/packages/49/48/fb1ce8136c19452ed15f033f8aee91d5defe515094e330ce368a0647846f/numpy-2.4.2-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:6e9f61981ace1360e42737e2bae58b27bf28a1b27e781721047d84bd754d32e7", size = 5475172, upload-time = "2026-01-31T23:10:30.848Z" }, - { url = "https://files.pythonhosted.org/packages/40/a9/3feb49f17bbd1300dd2570432961f5c8a4ffeff1db6f02c7273bd020a4c9/numpy-2.4.2-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:cb7bbb88aa74908950d979eeaa24dbdf1a865e3c7e45ff0121d8f70387b55f73", size = 6805145, upload-time = "2026-01-31T23:10:32.352Z" }, - { url = "https://files.pythonhosted.org/packages/3f/39/fdf35cbd6d6e2fcad42fcf85ac04a85a0d0fbfbf34b30721c98d602fd70a/numpy-2.4.2-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4f069069931240b3fc703f1e23df63443dbd6390614c8c44a87d96cd0ec81eb1", size = 15966084, upload-time = "2026-01-31T23:10:34.502Z" }, - { url = "https://files.pythonhosted.org/packages/1b/46/6fa4ea94f1ddf969b2ee941290cca6f1bfac92b53c76ae5f44afe17ceb69/numpy-2.4.2-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c02ef4401a506fb60b411467ad501e1429a3487abca4664871d9ae0b46c8ba32", size = 16899477, upload-time = "2026-01-31T23:10:37.075Z" }, - { url = "https://files.pythonhosted.org/packages/09/a1/2a424e162b1a14a5bd860a464ab4e07513916a64ab1683fae262f735ccd2/numpy-2.4.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2653de5c24910e49c2b106499803124dde62a5a1fe0eedeaecf4309a5f639390", size = 17323429, upload-time = "2026-01-31T23:10:39.704Z" }, - { url = "https://files.pythonhosted.org/packages/ce/a2/73014149ff250628df72c58204822ac01d768697913881aacf839ff78680/numpy-2.4.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1ae241bbfc6ae276f94a170b14785e561cb5e7f626b6688cf076af4110887413", size = 18635109, upload-time = "2026-01-31T23:10:41.924Z" }, - { url = "https://files.pythonhosted.org/packages/6c/0c/73e8be2f1accd56df74abc1c5e18527822067dced5ec0861b5bb882c2ce0/numpy-2.4.2-cp311-cp311-win32.whl", hash = "sha256:df1b10187212b198dd45fa943d8985a3c8cf854aed4923796e0e019e113a1bda", size = 6237915, upload-time = "2026-01-31T23:10:45.26Z" }, - { url = "https://files.pythonhosted.org/packages/76/ae/e0265e0163cf127c24c3969d29f1c4c64551a1e375d95a13d32eab25d364/numpy-2.4.2-cp311-cp311-win_amd64.whl", hash = "sha256:b9c618d56a29c9cb1c4da979e9899be7578d2e0b3c24d52079c166324c9e8695", size = 12607972, upload-time = "2026-01-31T23:10:47.021Z" }, - { url = "https://files.pythonhosted.org/packages/29/a5/c43029af9b8014d6ea157f192652c50042e8911f4300f8f6ed3336bf437f/numpy-2.4.2-cp311-cp311-win_arm64.whl", hash = "sha256:47c5a6ed21d9452b10227e5e8a0e1c22979811cad7dcc19d8e3e2fb8fa03f1a3", size = 10485763, upload-time = "2026-01-31T23:10:50.087Z" }, - { url = "https://files.pythonhosted.org/packages/51/6e/6f394c9c77668153e14d4da83bcc247beb5952f6ead7699a1a2992613bea/numpy-2.4.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:21982668592194c609de53ba4933a7471880ccbaadcc52352694a59ecc860b3a", size = 16667963, upload-time = "2026-01-31T23:10:52.147Z" }, - { url = "https://files.pythonhosted.org/packages/1f/f8/55483431f2b2fd015ae6ed4fe62288823ce908437ed49db5a03d15151678/numpy-2.4.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40397bda92382fcec844066efb11f13e1c9a3e2a8e8f318fb72ed8b6db9f60f1", size = 14693571, upload-time = "2026-01-31T23:10:54.789Z" }, - { url = "https://files.pythonhosted.org/packages/2f/20/18026832b1845cdc82248208dd929ca14c9d8f2bac391f67440707fff27c/numpy-2.4.2-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:b3a24467af63c67829bfaa61eecf18d5432d4f11992688537be59ecd6ad32f5e", size = 5203469, upload-time = "2026-01-31T23:10:57.343Z" }, - { url = "https://files.pythonhosted.org/packages/7d/33/2eb97c8a77daaba34eaa3fa7241a14ac5f51c46a6bd5911361b644c4a1e2/numpy-2.4.2-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:805cc8de9fd6e7a22da5aed858e0ab16be5a4db6c873dde1d7451c541553aa27", size = 6550820, upload-time = "2026-01-31T23:10:59.429Z" }, - { url = "https://files.pythonhosted.org/packages/b1/91/b97fdfd12dc75b02c44e26c6638241cc004d4079a0321a69c62f51470c4c/numpy-2.4.2-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6d82351358ffbcdcd7b686b90742a9b86632d6c1c051016484fa0b326a0a1548", size = 15663067, upload-time = "2026-01-31T23:11:01.291Z" }, - { url = "https://files.pythonhosted.org/packages/f5/c6/a18e59f3f0b8071cc85cbc8d80cd02d68aa9710170b2553a117203d46936/numpy-2.4.2-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9e35d3e0144137d9fdae62912e869136164534d64a169f86438bc9561b6ad49f", size = 16619782, upload-time = "2026-01-31T23:11:03.669Z" }, - { url = "https://files.pythonhosted.org/packages/b7/83/9751502164601a79e18847309f5ceec0b1446d7b6aa12305759b72cf98b2/numpy-2.4.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:adb6ed2ad29b9e15321d167d152ee909ec73395901b70936f029c3bc6d7f4460", size = 17013128, upload-time = "2026-01-31T23:11:05.913Z" }, - { url = "https://files.pythonhosted.org/packages/61/c4/c4066322256ec740acc1c8923a10047818691d2f8aec254798f3dd90f5f2/numpy-2.4.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8906e71fd8afcb76580404e2a950caef2685df3d2a57fe82a86ac8d33cc007ba", size = 18345324, upload-time = "2026-01-31T23:11:08.248Z" }, - { url = "https://files.pythonhosted.org/packages/ab/af/6157aa6da728fa4525a755bfad486ae7e3f76d4c1864138003eb84328497/numpy-2.4.2-cp312-cp312-win32.whl", hash = "sha256:ec055f6dae239a6299cace477b479cca2fc125c5675482daf1dd886933a1076f", size = 5960282, upload-time = "2026-01-31T23:11:10.497Z" }, - { url = "https://files.pythonhosted.org/packages/92/0f/7ceaaeaacb40567071e94dbf2c9480c0ae453d5bb4f52bea3892c39dc83c/numpy-2.4.2-cp312-cp312-win_amd64.whl", hash = "sha256:209fae046e62d0ce6435fcfe3b1a10537e858249b3d9b05829e2a05218296a85", size = 12314210, upload-time = "2026-01-31T23:11:12.176Z" }, - { url = "https://files.pythonhosted.org/packages/2f/a3/56c5c604fae6dd40fa2ed3040d005fca97e91bd320d232ac9931d77ba13c/numpy-2.4.2-cp312-cp312-win_arm64.whl", hash = "sha256:fbde1b0c6e81d56f5dccd95dd4a711d9b95df1ae4009a60887e56b27e8d903fa", size = 10220171, upload-time = "2026-01-31T23:11:14.684Z" }, - { url = "https://files.pythonhosted.org/packages/a1/22/815b9fe25d1d7ae7d492152adbc7226d3eff731dffc38fe970589fcaaa38/numpy-2.4.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:25f2059807faea4b077a2b6837391b5d830864b3543627f381821c646f31a63c", size = 16663696, upload-time = "2026-01-31T23:11:17.516Z" }, - { url = "https://files.pythonhosted.org/packages/09/f0/817d03a03f93ba9c6c8993de509277d84e69f9453601915e4a69554102a1/numpy-2.4.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bd3a7a9f5847d2fb8c2c6d1c862fa109c31a9abeca1a3c2bd5a64572955b2979", size = 14688322, upload-time = "2026-01-31T23:11:19.883Z" }, - { url = "https://files.pythonhosted.org/packages/da/b4/f805ab79293c728b9a99438775ce51885fd4f31b76178767cfc718701a39/numpy-2.4.2-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:8e4549f8a3c6d13d55041925e912bfd834285ef1dd64d6bc7d542583355e2e98", size = 5198157, upload-time = "2026-01-31T23:11:22.375Z" }, - { url = "https://files.pythonhosted.org/packages/74/09/826e4289844eccdcd64aac27d13b0fd3f32039915dd5b9ba01baae1f436c/numpy-2.4.2-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:aea4f66ff44dfddf8c2cffd66ba6538c5ec67d389285292fe428cb2c738c8aef", size = 6546330, upload-time = "2026-01-31T23:11:23.958Z" }, - { url = "https://files.pythonhosted.org/packages/19/fb/cbfdbfa3057a10aea5422c558ac57538e6acc87ec1669e666d32ac198da7/numpy-2.4.2-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c3cd545784805de05aafe1dde61752ea49a359ccba9760c1e5d1c88a93bbf2b7", size = 15660968, upload-time = "2026-01-31T23:11:25.713Z" }, - { url = "https://files.pythonhosted.org/packages/04/dc/46066ce18d01645541f0186877377b9371b8fa8017fa8262002b4ef22612/numpy-2.4.2-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d0d9b7c93578baafcbc5f0b83eaf17b79d345c6f36917ba0c67f45226911d499", size = 16607311, upload-time = "2026-01-31T23:11:28.117Z" }, - { url = "https://files.pythonhosted.org/packages/14/d9/4b5adfc39a43fa6bf918c6d544bc60c05236cc2f6339847fc5b35e6cb5b0/numpy-2.4.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f74f0f7779cc7ae07d1810aab8ac6b1464c3eafb9e283a40da7309d5e6e48fbb", size = 17012850, upload-time = "2026-01-31T23:11:30.888Z" }, - { url = "https://files.pythonhosted.org/packages/b7/20/adb6e6adde6d0130046e6fdfb7675cc62bc2f6b7b02239a09eb58435753d/numpy-2.4.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:c7ac672d699bf36275c035e16b65539931347d68b70667d28984c9fb34e07fa7", size = 18334210, upload-time = "2026-01-31T23:11:33.214Z" }, - { url = "https://files.pythonhosted.org/packages/78/0e/0a73b3dff26803a8c02baa76398015ea2a5434d9b8265a7898a6028c1591/numpy-2.4.2-cp313-cp313-win32.whl", hash = "sha256:8e9afaeb0beff068b4d9cd20d322ba0ee1cecfb0b08db145e4ab4dd44a6b5110", size = 5958199, upload-time = "2026-01-31T23:11:35.385Z" }, - { url = "https://files.pythonhosted.org/packages/43/bc/6352f343522fcb2c04dbaf94cb30cca6fd32c1a750c06ad6231b4293708c/numpy-2.4.2-cp313-cp313-win_amd64.whl", hash = "sha256:7df2de1e4fba69a51c06c28f5a3de36731eb9639feb8e1cf7e4a7b0daf4cf622", size = 12310848, upload-time = "2026-01-31T23:11:38.001Z" }, - { url = "https://files.pythonhosted.org/packages/6e/8d/6da186483e308da5da1cc6918ce913dcfe14ffde98e710bfeff2a6158d4e/numpy-2.4.2-cp313-cp313-win_arm64.whl", hash = "sha256:0fece1d1f0a89c16b03442eae5c56dc0be0c7883b5d388e0c03f53019a4bfd71", size = 10221082, upload-time = "2026-01-31T23:11:40.392Z" }, - { url = "https://files.pythonhosted.org/packages/25/a1/9510aa43555b44781968935c7548a8926274f815de42ad3997e9e83680dd/numpy-2.4.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:5633c0da313330fd20c484c78cdd3f9b175b55e1a766c4a174230c6b70ad8262", size = 14815866, upload-time = "2026-01-31T23:11:42.495Z" }, - { url = "https://files.pythonhosted.org/packages/36/30/6bbb5e76631a5ae46e7923dd16ca9d3f1c93cfa8d4ed79a129814a9d8db3/numpy-2.4.2-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:d9f64d786b3b1dd742c946c42d15b07497ed14af1a1f3ce840cce27daa0ce913", size = 5325631, upload-time = "2026-01-31T23:11:44.7Z" }, - { url = "https://files.pythonhosted.org/packages/46/00/3a490938800c1923b567b3a15cd17896e68052e2145d8662aaf3e1ffc58f/numpy-2.4.2-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:b21041e8cb6a1eb5312dd1d2f80a94d91efffb7a06b70597d44f1bd2dfc315ab", size = 6646254, upload-time = "2026-01-31T23:11:46.341Z" }, - { url = "https://files.pythonhosted.org/packages/d3/e9/fac0890149898a9b609caa5af7455a948b544746e4b8fe7c212c8edd71f8/numpy-2.4.2-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:00ab83c56211a1d7c07c25e3217ea6695e50a3e2f255053686b081dc0b091a82", size = 15720138, upload-time = "2026-01-31T23:11:48.082Z" }, - { url = "https://files.pythonhosted.org/packages/ea/5c/08887c54e68e1e28df53709f1893ce92932cc6f01f7c3d4dc952f61ffd4e/numpy-2.4.2-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2fb882da679409066b4603579619341c6d6898fc83a8995199d5249f986e8e8f", size = 16655398, upload-time = "2026-01-31T23:11:50.293Z" }, - { url = "https://files.pythonhosted.org/packages/4d/89/253db0fa0e66e9129c745e4ef25631dc37d5f1314dad2b53e907b8538e6d/numpy-2.4.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:66cb9422236317f9d44b67b4d18f44efe6e9c7f8794ac0462978513359461554", size = 17079064, upload-time = "2026-01-31T23:11:52.927Z" }, - { url = "https://files.pythonhosted.org/packages/2a/d5/cbade46ce97c59c6c3da525e8d95b7abe8a42974a1dc5c1d489c10433e88/numpy-2.4.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:0f01dcf33e73d80bd8dc0f20a71303abbafa26a19e23f6b68d1aa9990af90257", size = 18379680, upload-time = "2026-01-31T23:11:55.22Z" }, - { url = "https://files.pythonhosted.org/packages/40/62/48f99ae172a4b63d981babe683685030e8a3df4f246c893ea5c6ef99f018/numpy-2.4.2-cp313-cp313t-win32.whl", hash = "sha256:52b913ec40ff7ae845687b0b34d8d93b60cb66dcee06996dd5c99f2fc9328657", size = 6082433, upload-time = "2026-01-31T23:11:58.096Z" }, - { url = "https://files.pythonhosted.org/packages/07/38/e054a61cfe48ad9f1ed0d188e78b7e26859d0b60ef21cd9de4897cdb5326/numpy-2.4.2-cp313-cp313t-win_amd64.whl", hash = "sha256:5eea80d908b2c1f91486eb95b3fb6fab187e569ec9752ab7d9333d2e66bf2d6b", size = 12451181, upload-time = "2026-01-31T23:11:59.782Z" }, - { url = "https://files.pythonhosted.org/packages/6e/a4/a05c3a6418575e185dd84d0b9680b6bb2e2dc3e4202f036b7b4e22d6e9dc/numpy-2.4.2-cp313-cp313t-win_arm64.whl", hash = "sha256:fd49860271d52127d61197bb50b64f58454e9f578cb4b2c001a6de8b1f50b0b1", size = 10290756, upload-time = "2026-01-31T23:12:02.438Z" }, - { url = "https://files.pythonhosted.org/packages/18/88/b7df6050bf18fdcfb7046286c6535cabbdd2064a3440fca3f069d319c16e/numpy-2.4.2-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:444be170853f1f9d528428eceb55f12918e4fda5d8805480f36a002f1415e09b", size = 16663092, upload-time = "2026-01-31T23:12:04.521Z" }, - { url = "https://files.pythonhosted.org/packages/25/7a/1fee4329abc705a469a4afe6e69b1ef7e915117747886327104a8493a955/numpy-2.4.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:d1240d50adff70c2a88217698ca844723068533f3f5c5fa6ee2e3220e3bdb000", size = 14698770, upload-time = "2026-01-31T23:12:06.96Z" }, - { url = "https://files.pythonhosted.org/packages/fb/0b/f9e49ba6c923678ad5bc38181c08ac5e53b7a5754dbca8e581aa1a56b1ff/numpy-2.4.2-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:7cdde6de52fb6664b00b056341265441192d1291c130e99183ec0d4b110ff8b1", size = 5208562, upload-time = "2026-01-31T23:12:09.632Z" }, - { url = "https://files.pythonhosted.org/packages/7d/12/d7de8f6f53f9bb76997e5e4c069eda2051e3fe134e9181671c4391677bb2/numpy-2.4.2-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:cda077c2e5b780200b6b3e09d0b42205a3d1c68f30c6dceb90401c13bff8fe74", size = 6543710, upload-time = "2026-01-31T23:12:11.969Z" }, - { url = "https://files.pythonhosted.org/packages/09/63/c66418c2e0268a31a4cf8a8b512685748200f8e8e8ec6c507ce14e773529/numpy-2.4.2-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d30291931c915b2ab5717c2974bb95ee891a1cf22ebc16a8006bd59cd210d40a", size = 15677205, upload-time = "2026-01-31T23:12:14.33Z" }, - { url = "https://files.pythonhosted.org/packages/5d/6c/7f237821c9642fb2a04d2f1e88b4295677144ca93285fd76eff3bcba858d/numpy-2.4.2-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bba37bc29d4d85761deed3954a1bc62be7cf462b9510b51d367b769a8c8df325", size = 16611738, upload-time = "2026-01-31T23:12:16.525Z" }, - { url = "https://files.pythonhosted.org/packages/c2/a7/39c4cdda9f019b609b5c473899d87abff092fc908cfe4d1ecb2fcff453b0/numpy-2.4.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:b2f0073ed0868db1dcd86e052d37279eef185b9c8db5bf61f30f46adac63c909", size = 17028888, upload-time = "2026-01-31T23:12:19.306Z" }, - { url = "https://files.pythonhosted.org/packages/da/b3/e84bb64bdfea967cc10950d71090ec2d84b49bc691df0025dddb7c26e8e3/numpy-2.4.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:7f54844851cdb630ceb623dcec4db3240d1ac13d4990532446761baede94996a", size = 18339556, upload-time = "2026-01-31T23:12:21.816Z" }, - { url = "https://files.pythonhosted.org/packages/88/f5/954a291bc1192a27081706862ac62bb5920fbecfbaa302f64682aa90beed/numpy-2.4.2-cp314-cp314-win32.whl", hash = "sha256:12e26134a0331d8dbd9351620f037ec470b7c75929cb8a1537f6bfe411152a1a", size = 6006899, upload-time = "2026-01-31T23:12:24.14Z" }, - { url = "https://files.pythonhosted.org/packages/05/cb/eff72a91b2efdd1bc98b3b8759f6a1654aa87612fc86e3d87d6fe4f948c4/numpy-2.4.2-cp314-cp314-win_amd64.whl", hash = "sha256:068cdb2d0d644cdb45670810894f6a0600797a69c05f1ac478e8d31670b8ee75", size = 12443072, upload-time = "2026-01-31T23:12:26.33Z" }, - { url = "https://files.pythonhosted.org/packages/37/75/62726948db36a56428fce4ba80a115716dc4fad6a3a4352487f8bb950966/numpy-2.4.2-cp314-cp314-win_arm64.whl", hash = "sha256:6ed0be1ee58eef41231a5c943d7d1375f093142702d5723ca2eb07db9b934b05", size = 10494886, upload-time = "2026-01-31T23:12:28.488Z" }, - { url = "https://files.pythonhosted.org/packages/36/2f/ee93744f1e0661dc267e4b21940870cabfae187c092e1433b77b09b50ac4/numpy-2.4.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:98f16a80e917003a12c0580f97b5f875853ebc33e2eaa4bccfc8201ac6869308", size = 14818567, upload-time = "2026-01-31T23:12:30.709Z" }, - { url = "https://files.pythonhosted.org/packages/a7/24/6535212add7d76ff938d8bdc654f53f88d35cddedf807a599e180dcb8e66/numpy-2.4.2-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:20abd069b9cda45874498b245c8015b18ace6de8546bf50dfa8cea1696ed06ef", size = 5328372, upload-time = "2026-01-31T23:12:32.962Z" }, - { url = "https://files.pythonhosted.org/packages/5e/9d/c48f0a035725f925634bf6b8994253b43f2047f6778a54147d7e213bc5a7/numpy-2.4.2-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:e98c97502435b53741540a5717a6749ac2ada901056c7db951d33e11c885cc7d", size = 6649306, upload-time = "2026-01-31T23:12:34.797Z" }, - { url = "https://files.pythonhosted.org/packages/81/05/7c73a9574cd4a53a25907bad38b59ac83919c0ddc8234ec157f344d57d9a/numpy-2.4.2-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:da6cad4e82cb893db4b69105c604d805e0c3ce11501a55b5e9f9083b47d2ffe8", size = 15722394, upload-time = "2026-01-31T23:12:36.565Z" }, - { url = "https://files.pythonhosted.org/packages/35/fa/4de10089f21fc7d18442c4a767ab156b25c2a6eaf187c0db6d9ecdaeb43f/numpy-2.4.2-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9e4424677ce4b47fe73c8b5556d876571f7c6945d264201180db2dc34f676ab5", size = 16653343, upload-time = "2026-01-31T23:12:39.188Z" }, - { url = "https://files.pythonhosted.org/packages/b8/f9/d33e4ffc857f3763a57aa85650f2e82486832d7492280ac21ba9efda80da/numpy-2.4.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:2b8f157c8a6f20eb657e240f8985cc135598b2b46985c5bccbde7616dc9c6b1e", size = 17078045, upload-time = "2026-01-31T23:12:42.041Z" }, - { url = "https://files.pythonhosted.org/packages/c8/b8/54bdb43b6225badbea6389fa038c4ef868c44f5890f95dd530a218706da3/numpy-2.4.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5daf6f3914a733336dab21a05cdec343144600e964d2fcdabaac0c0269874b2a", size = 18380024, upload-time = "2026-01-31T23:12:44.331Z" }, - { url = "https://files.pythonhosted.org/packages/a5/55/6e1a61ded7af8df04016d81b5b02daa59f2ea9252ee0397cb9f631efe9e5/numpy-2.4.2-cp314-cp314t-win32.whl", hash = "sha256:8c50dd1fc8826f5b26a5ee4d77ca55d88a895f4e4819c7ecc2a9f5905047a443", size = 6153937, upload-time = "2026-01-31T23:12:47.229Z" }, - { url = "https://files.pythonhosted.org/packages/45/aa/fa6118d1ed6d776b0983f3ceac9b1a5558e80df9365b1c3aa6d42bf9eee4/numpy-2.4.2-cp314-cp314t-win_amd64.whl", hash = "sha256:fcf92bee92742edd401ba41135185866f7026c502617f422eb432cfeca4fe236", size = 12631844, upload-time = "2026-01-31T23:12:48.997Z" }, - { url = "https://files.pythonhosted.org/packages/32/0a/2ec5deea6dcd158f254a7b372fb09cfba5719419c8d66343bab35237b3fb/numpy-2.4.2-cp314-cp314t-win_arm64.whl", hash = "sha256:1f92f53998a17265194018d1cc321b2e96e900ca52d54c7c77837b71b9465181", size = 10565379, upload-time = "2026-01-31T23:12:51.345Z" }, - { url = "https://files.pythonhosted.org/packages/f4/f8/50e14d36d915ef64d8f8bc4a087fc8264d82c785eda6711f80ab7e620335/numpy-2.4.2-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:89f7268c009bc492f506abd6f5265defa7cb3f7487dc21d357c3d290add45082", size = 16833179, upload-time = "2026-01-31T23:12:53.5Z" }, - { url = "https://files.pythonhosted.org/packages/17/17/809b5cad63812058a8189e91a1e2d55a5a18fd04611dbad244e8aeae465c/numpy-2.4.2-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:e6dee3bb76aa4009d5a912180bf5b2de012532998d094acee25d9cb8dee3e44a", size = 14889755, upload-time = "2026-01-31T23:12:55.933Z" }, - { url = "https://files.pythonhosted.org/packages/3e/ea/181b9bcf7627fc8371720316c24db888dcb9829b1c0270abf3d288b2e29b/numpy-2.4.2-pp311-pypy311_pp73-macosx_14_0_arm64.whl", hash = "sha256:cd2bd2bbed13e213d6b55dc1d035a4f91748a7d3edc9480c13898b0353708920", size = 5399500, upload-time = "2026-01-31T23:12:58.671Z" }, - { url = "https://files.pythonhosted.org/packages/33/9f/413adf3fc955541ff5536b78fcf0754680b3c6d95103230252a2c9408d23/numpy-2.4.2-pp311-pypy311_pp73-macosx_14_0_x86_64.whl", hash = "sha256:cf28c0c1d4c4bf00f509fa7eb02c58d7caf221b50b467bcb0d9bbf1584d5c821", size = 6714252, upload-time = "2026-01-31T23:13:00.518Z" }, - { url = "https://files.pythonhosted.org/packages/91/da/643aad274e29ccbdf42ecd94dafe524b81c87bcb56b83872d54827f10543/numpy-2.4.2-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e04ae107ac591763a47398bb45b568fc38f02dbc4aa44c063f67a131f99346cb", size = 15797142, upload-time = "2026-01-31T23:13:02.219Z" }, - { url = "https://files.pythonhosted.org/packages/66/27/965b8525e9cb5dc16481b30a1b3c21e50c7ebf6e9dbd48d0c4d0d5089c7e/numpy-2.4.2-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:602f65afdef699cda27ec0b9224ae5dc43e328f4c24c689deaf77133dbee74d0", size = 16727979, upload-time = "2026-01-31T23:13:04.62Z" }, - { url = "https://files.pythonhosted.org/packages/de/e5/b7d20451657664b07986c2f6e3be564433f5dcaf3482d68eaecd79afaf03/numpy-2.4.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:be71bf1edb48ebbbf7f6337b5bfd2f895d1902f6335a5830b20141fc126ffba0", size = 12502577, upload-time = "2026-01-31T23:13:07.08Z" }, +wheels = [ + {url = "https://files.pythonhosted.org/packages/d3/44/71852273146957899753e69986246d6a176061ea183407e95418c2aa4d9a/numpy-2.4.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e7e88598032542bd49af7c4747541422884219056c268823ef6e5e89851c8825", size = 16955478, upload-time = "2026-01-31T23:10:25.623Z"}, + {url = "https://files.pythonhosted.org/packages/74/41/5d17d4058bd0cd96bcbd4d9ff0fb2e21f52702aab9a72e4a594efa18692f/numpy-2.4.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7edc794af8b36ca37ef5fcb5e0d128c7e0595c7b96a2318d1badb6fcd8ee86b1", size = 14965467, upload-time = "2026-01-31T23:10:28.186Z"}, + {url = "https://files.pythonhosted.org/packages/49/48/fb1ce8136c19452ed15f033f8aee91d5defe515094e330ce368a0647846f/numpy-2.4.2-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:6e9f61981ace1360e42737e2bae58b27bf28a1b27e781721047d84bd754d32e7", size = 5475172, upload-time = "2026-01-31T23:10:30.848Z"}, + {url = "https://files.pythonhosted.org/packages/40/a9/3feb49f17bbd1300dd2570432961f5c8a4ffeff1db6f02c7273bd020a4c9/numpy-2.4.2-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:cb7bbb88aa74908950d979eeaa24dbdf1a865e3c7e45ff0121d8f70387b55f73", size = 6805145, upload-time = "2026-01-31T23:10:32.352Z"}, + {url = "https://files.pythonhosted.org/packages/3f/39/fdf35cbd6d6e2fcad42fcf85ac04a85a0d0fbfbf34b30721c98d602fd70a/numpy-2.4.2-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4f069069931240b3fc703f1e23df63443dbd6390614c8c44a87d96cd0ec81eb1", size = 15966084, upload-time = "2026-01-31T23:10:34.502Z"}, + {url = "https://files.pythonhosted.org/packages/1b/46/6fa4ea94f1ddf969b2ee941290cca6f1bfac92b53c76ae5f44afe17ceb69/numpy-2.4.2-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c02ef4401a506fb60b411467ad501e1429a3487abca4664871d9ae0b46c8ba32", size = 16899477, upload-time = "2026-01-31T23:10:37.075Z"}, + {url = "https://files.pythonhosted.org/packages/09/a1/2a424e162b1a14a5bd860a464ab4e07513916a64ab1683fae262f735ccd2/numpy-2.4.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2653de5c24910e49c2b106499803124dde62a5a1fe0eedeaecf4309a5f639390", size = 17323429, upload-time = "2026-01-31T23:10:39.704Z"}, + {url = "https://files.pythonhosted.org/packages/ce/a2/73014149ff250628df72c58204822ac01d768697913881aacf839ff78680/numpy-2.4.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1ae241bbfc6ae276f94a170b14785e561cb5e7f626b6688cf076af4110887413", size = 18635109, upload-time = "2026-01-31T23:10:41.924Z"}, + {url = "https://files.pythonhosted.org/packages/6c/0c/73e8be2f1accd56df74abc1c5e18527822067dced5ec0861b5bb882c2ce0/numpy-2.4.2-cp311-cp311-win32.whl", hash = "sha256:df1b10187212b198dd45fa943d8985a3c8cf854aed4923796e0e019e113a1bda", size = 6237915, upload-time = "2026-01-31T23:10:45.26Z"}, + {url = "https://files.pythonhosted.org/packages/76/ae/e0265e0163cf127c24c3969d29f1c4c64551a1e375d95a13d32eab25d364/numpy-2.4.2-cp311-cp311-win_amd64.whl", hash = "sha256:b9c618d56a29c9cb1c4da979e9899be7578d2e0b3c24d52079c166324c9e8695", size = 12607972, upload-time = "2026-01-31T23:10:47.021Z"}, + {url = "https://files.pythonhosted.org/packages/29/a5/c43029af9b8014d6ea157f192652c50042e8911f4300f8f6ed3336bf437f/numpy-2.4.2-cp311-cp311-win_arm64.whl", hash = "sha256:47c5a6ed21d9452b10227e5e8a0e1c22979811cad7dcc19d8e3e2fb8fa03f1a3", size = 10485763, upload-time = "2026-01-31T23:10:50.087Z"}, + {url = "https://files.pythonhosted.org/packages/51/6e/6f394c9c77668153e14d4da83bcc247beb5952f6ead7699a1a2992613bea/numpy-2.4.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:21982668592194c609de53ba4933a7471880ccbaadcc52352694a59ecc860b3a", size = 16667963, upload-time = "2026-01-31T23:10:52.147Z"}, + {url = "https://files.pythonhosted.org/packages/1f/f8/55483431f2b2fd015ae6ed4fe62288823ce908437ed49db5a03d15151678/numpy-2.4.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40397bda92382fcec844066efb11f13e1c9a3e2a8e8f318fb72ed8b6db9f60f1", size = 14693571, upload-time = "2026-01-31T23:10:54.789Z"}, + {url = "https://files.pythonhosted.org/packages/2f/20/18026832b1845cdc82248208dd929ca14c9d8f2bac391f67440707fff27c/numpy-2.4.2-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:b3a24467af63c67829bfaa61eecf18d5432d4f11992688537be59ecd6ad32f5e", size = 5203469, upload-time = "2026-01-31T23:10:57.343Z"}, + {url = "https://files.pythonhosted.org/packages/7d/33/2eb97c8a77daaba34eaa3fa7241a14ac5f51c46a6bd5911361b644c4a1e2/numpy-2.4.2-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:805cc8de9fd6e7a22da5aed858e0ab16be5a4db6c873dde1d7451c541553aa27", size = 6550820, upload-time = "2026-01-31T23:10:59.429Z"}, + {url = "https://files.pythonhosted.org/packages/b1/91/b97fdfd12dc75b02c44e26c6638241cc004d4079a0321a69c62f51470c4c/numpy-2.4.2-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6d82351358ffbcdcd7b686b90742a9b86632d6c1c051016484fa0b326a0a1548", size = 15663067, upload-time = "2026-01-31T23:11:01.291Z"}, + {url = "https://files.pythonhosted.org/packages/f5/c6/a18e59f3f0b8071cc85cbc8d80cd02d68aa9710170b2553a117203d46936/numpy-2.4.2-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9e35d3e0144137d9fdae62912e869136164534d64a169f86438bc9561b6ad49f", size = 16619782, upload-time = "2026-01-31T23:11:03.669Z"}, + {url = "https://files.pythonhosted.org/packages/b7/83/9751502164601a79e18847309f5ceec0b1446d7b6aa12305759b72cf98b2/numpy-2.4.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:adb6ed2ad29b9e15321d167d152ee909ec73395901b70936f029c3bc6d7f4460", size = 17013128, upload-time = "2026-01-31T23:11:05.913Z"}, + {url = "https://files.pythonhosted.org/packages/61/c4/c4066322256ec740acc1c8923a10047818691d2f8aec254798f3dd90f5f2/numpy-2.4.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8906e71fd8afcb76580404e2a950caef2685df3d2a57fe82a86ac8d33cc007ba", size = 18345324, upload-time = "2026-01-31T23:11:08.248Z"}, + {url = "https://files.pythonhosted.org/packages/ab/af/6157aa6da728fa4525a755bfad486ae7e3f76d4c1864138003eb84328497/numpy-2.4.2-cp312-cp312-win32.whl", hash = "sha256:ec055f6dae239a6299cace477b479cca2fc125c5675482daf1dd886933a1076f", size = 5960282, upload-time = "2026-01-31T23:11:10.497Z"}, + {url = "https://files.pythonhosted.org/packages/92/0f/7ceaaeaacb40567071e94dbf2c9480c0ae453d5bb4f52bea3892c39dc83c/numpy-2.4.2-cp312-cp312-win_amd64.whl", hash = "sha256:209fae046e62d0ce6435fcfe3b1a10537e858249b3d9b05829e2a05218296a85", size = 12314210, upload-time = "2026-01-31T23:11:12.176Z"}, + {url = "https://files.pythonhosted.org/packages/2f/a3/56c5c604fae6dd40fa2ed3040d005fca97e91bd320d232ac9931d77ba13c/numpy-2.4.2-cp312-cp312-win_arm64.whl", hash = "sha256:fbde1b0c6e81d56f5dccd95dd4a711d9b95df1ae4009a60887e56b27e8d903fa", size = 10220171, upload-time = "2026-01-31T23:11:14.684Z"}, + {url = "https://files.pythonhosted.org/packages/a1/22/815b9fe25d1d7ae7d492152adbc7226d3eff731dffc38fe970589fcaaa38/numpy-2.4.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:25f2059807faea4b077a2b6837391b5d830864b3543627f381821c646f31a63c", size = 16663696, upload-time = "2026-01-31T23:11:17.516Z"}, + {url = "https://files.pythonhosted.org/packages/09/f0/817d03a03f93ba9c6c8993de509277d84e69f9453601915e4a69554102a1/numpy-2.4.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bd3a7a9f5847d2fb8c2c6d1c862fa109c31a9abeca1a3c2bd5a64572955b2979", size = 14688322, upload-time = "2026-01-31T23:11:19.883Z"}, + {url = "https://files.pythonhosted.org/packages/da/b4/f805ab79293c728b9a99438775ce51885fd4f31b76178767cfc718701a39/numpy-2.4.2-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:8e4549f8a3c6d13d55041925e912bfd834285ef1dd64d6bc7d542583355e2e98", size = 5198157, upload-time = "2026-01-31T23:11:22.375Z"}, + {url = "https://files.pythonhosted.org/packages/74/09/826e4289844eccdcd64aac27d13b0fd3f32039915dd5b9ba01baae1f436c/numpy-2.4.2-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:aea4f66ff44dfddf8c2cffd66ba6538c5ec67d389285292fe428cb2c738c8aef", size = 6546330, upload-time = "2026-01-31T23:11:23.958Z"}, + {url = "https://files.pythonhosted.org/packages/19/fb/cbfdbfa3057a10aea5422c558ac57538e6acc87ec1669e666d32ac198da7/numpy-2.4.2-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c3cd545784805de05aafe1dde61752ea49a359ccba9760c1e5d1c88a93bbf2b7", size = 15660968, upload-time = "2026-01-31T23:11:25.713Z"}, + {url = "https://files.pythonhosted.org/packages/04/dc/46066ce18d01645541f0186877377b9371b8fa8017fa8262002b4ef22612/numpy-2.4.2-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d0d9b7c93578baafcbc5f0b83eaf17b79d345c6f36917ba0c67f45226911d499", size = 16607311, upload-time = "2026-01-31T23:11:28.117Z"}, + {url = "https://files.pythonhosted.org/packages/14/d9/4b5adfc39a43fa6bf918c6d544bc60c05236cc2f6339847fc5b35e6cb5b0/numpy-2.4.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f74f0f7779cc7ae07d1810aab8ac6b1464c3eafb9e283a40da7309d5e6e48fbb", size = 17012850, upload-time = "2026-01-31T23:11:30.888Z"}, + {url = "https://files.pythonhosted.org/packages/b7/20/adb6e6adde6d0130046e6fdfb7675cc62bc2f6b7b02239a09eb58435753d/numpy-2.4.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:c7ac672d699bf36275c035e16b65539931347d68b70667d28984c9fb34e07fa7", size = 18334210, upload-time = "2026-01-31T23:11:33.214Z"}, + {url = "https://files.pythonhosted.org/packages/78/0e/0a73b3dff26803a8c02baa76398015ea2a5434d9b8265a7898a6028c1591/numpy-2.4.2-cp313-cp313-win32.whl", hash = "sha256:8e9afaeb0beff068b4d9cd20d322ba0ee1cecfb0b08db145e4ab4dd44a6b5110", size = 5958199, upload-time = "2026-01-31T23:11:35.385Z"}, + {url = "https://files.pythonhosted.org/packages/43/bc/6352f343522fcb2c04dbaf94cb30cca6fd32c1a750c06ad6231b4293708c/numpy-2.4.2-cp313-cp313-win_amd64.whl", hash = "sha256:7df2de1e4fba69a51c06c28f5a3de36731eb9639feb8e1cf7e4a7b0daf4cf622", size = 12310848, upload-time = "2026-01-31T23:11:38.001Z"}, + {url = "https://files.pythonhosted.org/packages/6e/8d/6da186483e308da5da1cc6918ce913dcfe14ffde98e710bfeff2a6158d4e/numpy-2.4.2-cp313-cp313-win_arm64.whl", hash = "sha256:0fece1d1f0a89c16b03442eae5c56dc0be0c7883b5d388e0c03f53019a4bfd71", size = 10221082, upload-time = "2026-01-31T23:11:40.392Z"}, + {url = "https://files.pythonhosted.org/packages/25/a1/9510aa43555b44781968935c7548a8926274f815de42ad3997e9e83680dd/numpy-2.4.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:5633c0da313330fd20c484c78cdd3f9b175b55e1a766c4a174230c6b70ad8262", size = 14815866, upload-time = "2026-01-31T23:11:42.495Z"}, + {url = "https://files.pythonhosted.org/packages/36/30/6bbb5e76631a5ae46e7923dd16ca9d3f1c93cfa8d4ed79a129814a9d8db3/numpy-2.4.2-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:d9f64d786b3b1dd742c946c42d15b07497ed14af1a1f3ce840cce27daa0ce913", size = 5325631, upload-time = "2026-01-31T23:11:44.7Z"}, + {url = "https://files.pythonhosted.org/packages/46/00/3a490938800c1923b567b3a15cd17896e68052e2145d8662aaf3e1ffc58f/numpy-2.4.2-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:b21041e8cb6a1eb5312dd1d2f80a94d91efffb7a06b70597d44f1bd2dfc315ab", size = 6646254, upload-time = "2026-01-31T23:11:46.341Z"}, + {url = "https://files.pythonhosted.org/packages/d3/e9/fac0890149898a9b609caa5af7455a948b544746e4b8fe7c212c8edd71f8/numpy-2.4.2-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:00ab83c56211a1d7c07c25e3217ea6695e50a3e2f255053686b081dc0b091a82", size = 15720138, upload-time = "2026-01-31T23:11:48.082Z"}, + {url = "https://files.pythonhosted.org/packages/ea/5c/08887c54e68e1e28df53709f1893ce92932cc6f01f7c3d4dc952f61ffd4e/numpy-2.4.2-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2fb882da679409066b4603579619341c6d6898fc83a8995199d5249f986e8e8f", size = 16655398, upload-time = "2026-01-31T23:11:50.293Z"}, + {url = "https://files.pythonhosted.org/packages/4d/89/253db0fa0e66e9129c745e4ef25631dc37d5f1314dad2b53e907b8538e6d/numpy-2.4.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:66cb9422236317f9d44b67b4d18f44efe6e9c7f8794ac0462978513359461554", size = 17079064, upload-time = "2026-01-31T23:11:52.927Z"}, + {url = "https://files.pythonhosted.org/packages/2a/d5/cbade46ce97c59c6c3da525e8d95b7abe8a42974a1dc5c1d489c10433e88/numpy-2.4.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:0f01dcf33e73d80bd8dc0f20a71303abbafa26a19e23f6b68d1aa9990af90257", size = 18379680, upload-time = "2026-01-31T23:11:55.22Z"}, + {url = "https://files.pythonhosted.org/packages/40/62/48f99ae172a4b63d981babe683685030e8a3df4f246c893ea5c6ef99f018/numpy-2.4.2-cp313-cp313t-win32.whl", hash = "sha256:52b913ec40ff7ae845687b0b34d8d93b60cb66dcee06996dd5c99f2fc9328657", size = 6082433, upload-time = "2026-01-31T23:11:58.096Z"}, + {url = "https://files.pythonhosted.org/packages/07/38/e054a61cfe48ad9f1ed0d188e78b7e26859d0b60ef21cd9de4897cdb5326/numpy-2.4.2-cp313-cp313t-win_amd64.whl", hash = "sha256:5eea80d908b2c1f91486eb95b3fb6fab187e569ec9752ab7d9333d2e66bf2d6b", size = 12451181, upload-time = "2026-01-31T23:11:59.782Z"}, + {url = "https://files.pythonhosted.org/packages/6e/a4/a05c3a6418575e185dd84d0b9680b6bb2e2dc3e4202f036b7b4e22d6e9dc/numpy-2.4.2-cp313-cp313t-win_arm64.whl", hash = "sha256:fd49860271d52127d61197bb50b64f58454e9f578cb4b2c001a6de8b1f50b0b1", size = 10290756, upload-time = "2026-01-31T23:12:02.438Z"}, + {url = "https://files.pythonhosted.org/packages/18/88/b7df6050bf18fdcfb7046286c6535cabbdd2064a3440fca3f069d319c16e/numpy-2.4.2-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:444be170853f1f9d528428eceb55f12918e4fda5d8805480f36a002f1415e09b", size = 16663092, upload-time = "2026-01-31T23:12:04.521Z"}, + {url = "https://files.pythonhosted.org/packages/25/7a/1fee4329abc705a469a4afe6e69b1ef7e915117747886327104a8493a955/numpy-2.4.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:d1240d50adff70c2a88217698ca844723068533f3f5c5fa6ee2e3220e3bdb000", size = 14698770, upload-time = "2026-01-31T23:12:06.96Z"}, + {url = "https://files.pythonhosted.org/packages/fb/0b/f9e49ba6c923678ad5bc38181c08ac5e53b7a5754dbca8e581aa1a56b1ff/numpy-2.4.2-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:7cdde6de52fb6664b00b056341265441192d1291c130e99183ec0d4b110ff8b1", size = 5208562, upload-time = "2026-01-31T23:12:09.632Z"}, + {url = "https://files.pythonhosted.org/packages/7d/12/d7de8f6f53f9bb76997e5e4c069eda2051e3fe134e9181671c4391677bb2/numpy-2.4.2-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:cda077c2e5b780200b6b3e09d0b42205a3d1c68f30c6dceb90401c13bff8fe74", size = 6543710, upload-time = "2026-01-31T23:12:11.969Z"}, + {url = "https://files.pythonhosted.org/packages/09/63/c66418c2e0268a31a4cf8a8b512685748200f8e8e8ec6c507ce14e773529/numpy-2.4.2-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d30291931c915b2ab5717c2974bb95ee891a1cf22ebc16a8006bd59cd210d40a", size = 15677205, upload-time = "2026-01-31T23:12:14.33Z"}, + {url = "https://files.pythonhosted.org/packages/5d/6c/7f237821c9642fb2a04d2f1e88b4295677144ca93285fd76eff3bcba858d/numpy-2.4.2-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bba37bc29d4d85761deed3954a1bc62be7cf462b9510b51d367b769a8c8df325", size = 16611738, upload-time = "2026-01-31T23:12:16.525Z"}, + {url = "https://files.pythonhosted.org/packages/c2/a7/39c4cdda9f019b609b5c473899d87abff092fc908cfe4d1ecb2fcff453b0/numpy-2.4.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:b2f0073ed0868db1dcd86e052d37279eef185b9c8db5bf61f30f46adac63c909", size = 17028888, upload-time = "2026-01-31T23:12:19.306Z"}, + {url = "https://files.pythonhosted.org/packages/da/b3/e84bb64bdfea967cc10950d71090ec2d84b49bc691df0025dddb7c26e8e3/numpy-2.4.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:7f54844851cdb630ceb623dcec4db3240d1ac13d4990532446761baede94996a", size = 18339556, upload-time = "2026-01-31T23:12:21.816Z"}, + {url = "https://files.pythonhosted.org/packages/88/f5/954a291bc1192a27081706862ac62bb5920fbecfbaa302f64682aa90beed/numpy-2.4.2-cp314-cp314-win32.whl", hash = "sha256:12e26134a0331d8dbd9351620f037ec470b7c75929cb8a1537f6bfe411152a1a", size = 6006899, upload-time = "2026-01-31T23:12:24.14Z"}, + {url = "https://files.pythonhosted.org/packages/05/cb/eff72a91b2efdd1bc98b3b8759f6a1654aa87612fc86e3d87d6fe4f948c4/numpy-2.4.2-cp314-cp314-win_amd64.whl", hash = "sha256:068cdb2d0d644cdb45670810894f6a0600797a69c05f1ac478e8d31670b8ee75", size = 12443072, upload-time = "2026-01-31T23:12:26.33Z"}, + {url = "https://files.pythonhosted.org/packages/37/75/62726948db36a56428fce4ba80a115716dc4fad6a3a4352487f8bb950966/numpy-2.4.2-cp314-cp314-win_arm64.whl", hash = "sha256:6ed0be1ee58eef41231a5c943d7d1375f093142702d5723ca2eb07db9b934b05", size = 10494886, upload-time = "2026-01-31T23:12:28.488Z"}, + {url = "https://files.pythonhosted.org/packages/36/2f/ee93744f1e0661dc267e4b21940870cabfae187c092e1433b77b09b50ac4/numpy-2.4.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:98f16a80e917003a12c0580f97b5f875853ebc33e2eaa4bccfc8201ac6869308", size = 14818567, upload-time = "2026-01-31T23:12:30.709Z"}, + {url = "https://files.pythonhosted.org/packages/a7/24/6535212add7d76ff938d8bdc654f53f88d35cddedf807a599e180dcb8e66/numpy-2.4.2-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:20abd069b9cda45874498b245c8015b18ace6de8546bf50dfa8cea1696ed06ef", size = 5328372, upload-time = "2026-01-31T23:12:32.962Z"}, + {url = "https://files.pythonhosted.org/packages/5e/9d/c48f0a035725f925634bf6b8994253b43f2047f6778a54147d7e213bc5a7/numpy-2.4.2-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:e98c97502435b53741540a5717a6749ac2ada901056c7db951d33e11c885cc7d", size = 6649306, upload-time = "2026-01-31T23:12:34.797Z"}, + {url = "https://files.pythonhosted.org/packages/81/05/7c73a9574cd4a53a25907bad38b59ac83919c0ddc8234ec157f344d57d9a/numpy-2.4.2-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:da6cad4e82cb893db4b69105c604d805e0c3ce11501a55b5e9f9083b47d2ffe8", size = 15722394, upload-time = "2026-01-31T23:12:36.565Z"}, + {url = "https://files.pythonhosted.org/packages/35/fa/4de10089f21fc7d18442c4a767ab156b25c2a6eaf187c0db6d9ecdaeb43f/numpy-2.4.2-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9e4424677ce4b47fe73c8b5556d876571f7c6945d264201180db2dc34f676ab5", size = 16653343, upload-time = "2026-01-31T23:12:39.188Z"}, + {url = "https://files.pythonhosted.org/packages/b8/f9/d33e4ffc857f3763a57aa85650f2e82486832d7492280ac21ba9efda80da/numpy-2.4.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:2b8f157c8a6f20eb657e240f8985cc135598b2b46985c5bccbde7616dc9c6b1e", size = 17078045, upload-time = "2026-01-31T23:12:42.041Z"}, + {url = "https://files.pythonhosted.org/packages/c8/b8/54bdb43b6225badbea6389fa038c4ef868c44f5890f95dd530a218706da3/numpy-2.4.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5daf6f3914a733336dab21a05cdec343144600e964d2fcdabaac0c0269874b2a", size = 18380024, upload-time = "2026-01-31T23:12:44.331Z"}, + {url = "https://files.pythonhosted.org/packages/a5/55/6e1a61ded7af8df04016d81b5b02daa59f2ea9252ee0397cb9f631efe9e5/numpy-2.4.2-cp314-cp314t-win32.whl", hash = "sha256:8c50dd1fc8826f5b26a5ee4d77ca55d88a895f4e4819c7ecc2a9f5905047a443", size = 6153937, upload-time = "2026-01-31T23:12:47.229Z"}, + {url = "https://files.pythonhosted.org/packages/45/aa/fa6118d1ed6d776b0983f3ceac9b1a5558e80df9365b1c3aa6d42bf9eee4/numpy-2.4.2-cp314-cp314t-win_amd64.whl", hash = "sha256:fcf92bee92742edd401ba41135185866f7026c502617f422eb432cfeca4fe236", size = 12631844, upload-time = "2026-01-31T23:12:48.997Z"}, + {url = "https://files.pythonhosted.org/packages/32/0a/2ec5deea6dcd158f254a7b372fb09cfba5719419c8d66343bab35237b3fb/numpy-2.4.2-cp314-cp314t-win_arm64.whl", hash = "sha256:1f92f53998a17265194018d1cc321b2e96e900ca52d54c7c77837b71b9465181", size = 10565379, upload-time = "2026-01-31T23:12:51.345Z"}, + {url = "https://files.pythonhosted.org/packages/f4/f8/50e14d36d915ef64d8f8bc4a087fc8264d82c785eda6711f80ab7e620335/numpy-2.4.2-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:89f7268c009bc492f506abd6f5265defa7cb3f7487dc21d357c3d290add45082", size = 16833179, upload-time = "2026-01-31T23:12:53.5Z"}, + {url = "https://files.pythonhosted.org/packages/17/17/809b5cad63812058a8189e91a1e2d55a5a18fd04611dbad244e8aeae465c/numpy-2.4.2-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:e6dee3bb76aa4009d5a912180bf5b2de012532998d094acee25d9cb8dee3e44a", size = 14889755, upload-time = "2026-01-31T23:12:55.933Z"}, + {url = "https://files.pythonhosted.org/packages/3e/ea/181b9bcf7627fc8371720316c24db888dcb9829b1c0270abf3d288b2e29b/numpy-2.4.2-pp311-pypy311_pp73-macosx_14_0_arm64.whl", hash = "sha256:cd2bd2bbed13e213d6b55dc1d035a4f91748a7d3edc9480c13898b0353708920", size = 5399500, upload-time = "2026-01-31T23:12:58.671Z"}, + {url = "https://files.pythonhosted.org/packages/33/9f/413adf3fc955541ff5536b78fcf0754680b3c6d95103230252a2c9408d23/numpy-2.4.2-pp311-pypy311_pp73-macosx_14_0_x86_64.whl", hash = "sha256:cf28c0c1d4c4bf00f509fa7eb02c58d7caf221b50b467bcb0d9bbf1584d5c821", size = 6714252, upload-time = "2026-01-31T23:13:00.518Z"}, + {url = "https://files.pythonhosted.org/packages/91/da/643aad274e29ccbdf42ecd94dafe524b81c87bcb56b83872d54827f10543/numpy-2.4.2-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e04ae107ac591763a47398bb45b568fc38f02dbc4aa44c063f67a131f99346cb", size = 15797142, upload-time = "2026-01-31T23:13:02.219Z"}, + {url = "https://files.pythonhosted.org/packages/66/27/965b8525e9cb5dc16481b30a1b3c21e50c7ebf6e9dbd48d0c4d0d5089c7e/numpy-2.4.2-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:602f65afdef699cda27ec0b9224ae5dc43e328f4c24c689deaf77133dbee74d0", size = 16727979, upload-time = "2026-01-31T23:13:04.62Z"}, + {url = "https://files.pythonhosted.org/packages/de/e5/b7d20451657664b07986c2f6e3be564433f5dcaf3482d68eaecd79afaf03/numpy-2.4.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:be71bf1edb48ebbbf7f6337b5bfd2f895d1902f6335a5830b20141fc126ffba0", size = 12502577, upload-time = "2026-01-31T23:13:07.08Z"} ] [[package]] name = "objsize" +sdist = {url = "https://files.pythonhosted.org/packages/9d/42/2de8994fbea1112d076d71aefaebad888ff01e5b52616895d510b73c3b96/objsize-0.8.0.tar.gz", hash = "sha256:df17998cf6ef4b24d52abee5020484491230e3f4af71a8ff0098c7455ad4d91c", size = 16593, upload-time = "2026-01-18T12:55:14.199Z"} +source = {registry = "https://pypi.org/simple"} version = "0.8.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/9d/42/2de8994fbea1112d076d71aefaebad888ff01e5b52616895d510b73c3b96/objsize-0.8.0.tar.gz", hash = "sha256:df17998cf6ef4b24d52abee5020484491230e3f4af71a8ff0098c7455ad4d91c", size = 16593, upload-time = "2026-01-18T12:55:14.199Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/14/53/157f8f4df3f43fdfdc627a56fa46135e4dcf806eb5bc6088811d968f8a21/objsize-0.8.0-py3-none-any.whl", hash = "sha256:afea5e61ba1e3e40c23b546028cdc1df88c5b097d2b0d6c6b8a4bf44fa7a3e1b", size = 11599, upload-time = "2026-01-18T12:55:12.626Z" }, + {url = "https://files.pythonhosted.org/packages/14/53/157f8f4df3f43fdfdc627a56fa46135e4dcf806eb5bc6088811d968f8a21/objsize-0.8.0-py3-none-any.whl", hash = "sha256:afea5e61ba1e3e40c23b546028cdc1df88c5b097d2b0d6c6b8a4bf44fa7a3e1b", size = 11599, upload-time = "2026-01-18T12:55:12.626Z"} ] [[package]] name = "orjson" +sdist = {url = "https://files.pythonhosted.org/packages/53/45/b268004f745ede84e5798b48ee12b05129d19235d0e15267aa57dcdb400b/orjson-3.11.7.tar.gz", hash = "sha256:9b1a67243945819ce55d24a30b59d6a168e86220452d2c96f4d1f093e71c0c49", size = 6144992, upload-time = "2026-02-02T15:38:49.29Z"} +source = {registry = "https://pypi.org/simple"} version = "3.11.7" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/53/45/b268004f745ede84e5798b48ee12b05129d19235d0e15267aa57dcdb400b/orjson-3.11.7.tar.gz", hash = "sha256:9b1a67243945819ce55d24a30b59d6a168e86220452d2c96f4d1f093e71c0c49", size = 6144992, upload-time = "2026-02-02T15:38:49.29Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/37/02/da6cb01fc6087048d7f61522c327edf4250f1683a58a839fdcc435746dd5/orjson-3.11.7-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9487abc2c2086e7c8eb9a211d2ce8855bae0e92586279d0d27b341d5ad76c85c", size = 228664, upload-time = "2026-02-02T15:37:25.542Z" }, - { url = "https://files.pythonhosted.org/packages/c1/c2/5885e7a5881dba9a9af51bc564e8967225a642b3e03d089289a35054e749/orjson-3.11.7-cp311-cp311-macosx_15_0_arm64.whl", hash = "sha256:79cacb0b52f6004caf92405a7e1f11e6e2de8bdf9019e4f76b44ba045125cd6b", size = 125344, upload-time = "2026-02-02T15:37:26.92Z" }, - { url = "https://files.pythonhosted.org/packages/a4/1d/4e7688de0a92d1caf600dfd5fb70b4c5bfff51dfa61ac555072ef2d0d32a/orjson-3.11.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c2e85fe4698b6a56d5e2ebf7ae87544d668eb6bde1ad1226c13f44663f20ec9e", size = 128404, upload-time = "2026-02-02T15:37:28.108Z" }, - { url = "https://files.pythonhosted.org/packages/2f/b2/ec04b74ae03a125db7bd69cffd014b227b7f341e3261bf75b5eb88a1aa92/orjson-3.11.7-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b8d14b71c0b12963fe8a62aac87119f1afdf4cb88a400f61ca5ae581449efcb5", size = 123677, upload-time = "2026-02-02T15:37:30.287Z" }, - { url = "https://files.pythonhosted.org/packages/4c/69/f95bdf960605f08f827f6e3291fe243d8aa9c5c9ff017a8d7232209184c3/orjson-3.11.7-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:91c81ef070c8f3220054115e1ef468b1c9ce8497b4e526cb9f68ab4dc0a7ac62", size = 128950, upload-time = "2026-02-02T15:37:31.595Z" }, - { url = "https://files.pythonhosted.org/packages/a4/1b/de59c57bae1d148ef298852abd31909ac3089cff370dfd4cd84cc99cbc42/orjson-3.11.7-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:411ebaf34d735e25e358a6d9e7978954a9c9d58cfb47bc6683cdc3964cd2f910", size = 141756, upload-time = "2026-02-02T15:37:32.985Z" }, - { url = "https://files.pythonhosted.org/packages/ee/9e/9decc59f4499f695f65c650f6cfa6cd4c37a3fbe8fa235a0a3614cb54386/orjson-3.11.7-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a16bcd08ab0bcdfc7e8801d9c4a9cc17e58418e4d48ddc6ded4e9e4b1a94062b", size = 130812, upload-time = "2026-02-02T15:37:34.204Z" }, - { url = "https://files.pythonhosted.org/packages/28/e6/59f932bcabd1eac44e334fe8e3281a92eacfcb450586e1f4bde0423728d8/orjson-3.11.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c0b51672e466fd7e56230ffbae7f1639e18d0ce023351fb75da21b71bc2c960", size = 133444, upload-time = "2026-02-02T15:37:35.446Z" }, - { url = "https://files.pythonhosted.org/packages/f1/36/b0f05c0eaa7ca30bc965e37e6a2956b0d67adb87a9872942d3568da846ae/orjson-3.11.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:136dcd6a2e796dfd9ffca9fc027d778567b0b7c9968d092842d3c323cef88aa8", size = 138609, upload-time = "2026-02-02T15:37:36.657Z" }, - { url = "https://files.pythonhosted.org/packages/b8/03/58ec7d302b8d86944c60c7b4b82975d5161fcce4c9bc8c6cb1d6741b6115/orjson-3.11.7-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:7ba61079379b0ae29e117db13bda5f28d939766e410d321ec1624afc6a0b0504", size = 408918, upload-time = "2026-02-02T15:37:38.076Z" }, - { url = "https://files.pythonhosted.org/packages/06/3a/868d65ef9a8b99be723bd510de491349618abd9f62c826cf206d962db295/orjson-3.11.7-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:0527a4510c300e3b406591b0ba69b5dc50031895b0a93743526a3fc45f59d26e", size = 143998, upload-time = "2026-02-02T15:37:39.706Z" }, - { url = "https://files.pythonhosted.org/packages/5b/c7/1e18e1c83afe3349f4f6dc9e14910f0ae5f82eac756d1412ea4018938535/orjson-3.11.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a709e881723c9b18acddcfb8ba357322491ad553e277cf467e1e7e20e2d90561", size = 134802, upload-time = "2026-02-02T15:37:41.002Z" }, - { url = "https://files.pythonhosted.org/packages/d4/0b/ccb7ee1a65b37e8eeb8b267dc953561d72370e85185e459616d4345bab34/orjson-3.11.7-cp311-cp311-win32.whl", hash = "sha256:c43b8b5bab288b6b90dac410cca7e986a4fa747a2e8f94615aea407da706980d", size = 127828, upload-time = "2026-02-02T15:37:42.241Z" }, - { url = "https://files.pythonhosted.org/packages/af/9e/55c776dffda3f381e0f07d010a4f5f3902bf48eaba1bb7684d301acd4924/orjson-3.11.7-cp311-cp311-win_amd64.whl", hash = "sha256:6543001328aa857187f905308a028935864aefe9968af3848401b6fe80dbb471", size = 124941, upload-time = "2026-02-02T15:37:43.444Z" }, - { url = "https://files.pythonhosted.org/packages/aa/8e/424a620fa7d263b880162505fb107ef5e0afaa765b5b06a88312ac291560/orjson-3.11.7-cp311-cp311-win_arm64.whl", hash = "sha256:1ee5cc7160a821dfe14f130bc8e63e7611051f964b463d9e2a3a573204446a4d", size = 126245, upload-time = "2026-02-02T15:37:45.18Z" }, - { url = "https://files.pythonhosted.org/packages/80/bf/76f4f1665f6983385938f0e2a5d7efa12a58171b8456c252f3bae8a4cf75/orjson-3.11.7-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:bd03ea7606833655048dab1a00734a2875e3e86c276e1d772b2a02556f0d895f", size = 228545, upload-time = "2026-02-02T15:37:46.376Z" }, - { url = "https://files.pythonhosted.org/packages/79/53/6c72c002cb13b5a978a068add59b25a8bdf2800ac1c9c8ecdb26d6d97064/orjson-3.11.7-cp312-cp312-macosx_15_0_arm64.whl", hash = "sha256:89e440ebc74ce8ab5c7bc4ce6757b4a6b1041becb127df818f6997b5c71aa60b", size = 125224, upload-time = "2026-02-02T15:37:47.697Z" }, - { url = "https://files.pythonhosted.org/packages/2c/83/10e48852865e5dd151bdfe652c06f7da484578ed02c5fca938e3632cb0b8/orjson-3.11.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ede977b5fe5ac91b1dffc0a517ca4542d2ec8a6a4ff7b2652d94f640796342a", size = 128154, upload-time = "2026-02-02T15:37:48.954Z" }, - { url = "https://files.pythonhosted.org/packages/6e/52/a66e22a2b9abaa374b4a081d410edab6d1e30024707b87eab7c734afe28d/orjson-3.11.7-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b7b1dae39230a393df353827c855a5f176271c23434cfd2db74e0e424e693e10", size = 123548, upload-time = "2026-02-02T15:37:50.187Z" }, - { url = "https://files.pythonhosted.org/packages/de/38/605d371417021359f4910c496f764c48ceb8997605f8c25bf1dfe58c0ebe/orjson-3.11.7-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ed46f17096e28fb28d2975834836a639af7278aa87c84f68ab08fbe5b8bd75fa", size = 129000, upload-time = "2026-02-02T15:37:51.426Z" }, - { url = "https://files.pythonhosted.org/packages/44/98/af32e842b0ffd2335c89714d48ca4e3917b42f5d6ee5537832e069a4b3ac/orjson-3.11.7-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3726be79e36e526e3d9c1aceaadbfb4a04ee80a72ab47b3f3c17fefb9812e7b8", size = 141686, upload-time = "2026-02-02T15:37:52.607Z" }, - { url = "https://files.pythonhosted.org/packages/96/0b/fc793858dfa54be6feee940c1463370ece34b3c39c1ca0aa3845f5ba9892/orjson-3.11.7-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0724e265bc548af1dedebd9cb3d24b4e1c1e685a343be43e87ba922a5c5fff2f", size = 130812, upload-time = "2026-02-02T15:37:53.944Z" }, - { url = "https://files.pythonhosted.org/packages/dc/91/98a52415059db3f374757d0b7f0f16e3b5cd5976c90d1c2b56acaea039e6/orjson-3.11.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e7745312efa9e11c17fbd3cb3097262d079da26930ae9ae7ba28fb738367cbad", size = 133440, upload-time = "2026-02-02T15:37:55.615Z" }, - { url = "https://files.pythonhosted.org/packages/dc/b6/cb540117bda61791f46381f8c26c8f93e802892830a6055748d3bb1925ab/orjson-3.11.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f904c24bdeabd4298f7a977ef14ca2a022ca921ed670b92ecd16ab6f3d01f867", size = 138386, upload-time = "2026-02-02T15:37:56.814Z" }, - { url = "https://files.pythonhosted.org/packages/63/1a/50a3201c334a7f17c231eee5f841342190723794e3b06293f26e7cf87d31/orjson-3.11.7-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:b9fc4d0f81f394689e0814617aadc4f2ea0e8025f38c226cbf22d3b5ddbf025d", size = 408853, upload-time = "2026-02-02T15:37:58.291Z" }, - { url = "https://files.pythonhosted.org/packages/87/cd/8de1c67d0be44fdc22701e5989c0d015a2adf391498ad42c4dc589cd3013/orjson-3.11.7-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:849e38203e5be40b776ed2718e587faf204d184fc9a008ae441f9442320c0cab", size = 144130, upload-time = "2026-02-02T15:38:00.163Z" }, - { url = "https://files.pythonhosted.org/packages/0f/fe/d605d700c35dd55f51710d159fc54516a280923cd1b7e47508982fbb387d/orjson-3.11.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:4682d1db3bcebd2b64757e0ddf9e87ae5f00d29d16c5cdf3a62f561d08cc3dd2", size = 134818, upload-time = "2026-02-02T15:38:01.507Z" }, - { url = "https://files.pythonhosted.org/packages/e4/e4/15ecc67edb3ddb3e2f46ae04475f2d294e8b60c1825fbe28a428b93b3fbd/orjson-3.11.7-cp312-cp312-win32.whl", hash = "sha256:f4f7c956b5215d949a1f65334cf9d7612dde38f20a95f2315deef167def91a6f", size = 127923, upload-time = "2026-02-02T15:38:02.75Z" }, - { url = "https://files.pythonhosted.org/packages/34/70/2e0855361f76198a3965273048c8e50a9695d88cd75811a5b46444895845/orjson-3.11.7-cp312-cp312-win_amd64.whl", hash = "sha256:bf742e149121dc5648ba0a08ea0871e87b660467ef168a3a5e53bc1fbd64bb74", size = 125007, upload-time = "2026-02-02T15:38:04.032Z" }, - { url = "https://files.pythonhosted.org/packages/68/40/c2051bd19fc467610fed469dc29e43ac65891571138f476834ca192bc290/orjson-3.11.7-cp312-cp312-win_arm64.whl", hash = "sha256:26c3b9132f783b7d7903bf1efb095fed8d4a3a85ec0d334ee8beff3d7a4749d5", size = 126089, upload-time = "2026-02-02T15:38:05.297Z" }, - { url = "https://files.pythonhosted.org/packages/89/25/6e0e52cac5aab51d7b6dcd257e855e1dec1c2060f6b28566c509b4665f62/orjson-3.11.7-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:1d98b30cc1313d52d4af17d9c3d307b08389752ec5f2e5febdfada70b0f8c733", size = 228390, upload-time = "2026-02-02T15:38:06.8Z" }, - { url = "https://files.pythonhosted.org/packages/a5/29/a77f48d2fc8a05bbc529e5ff481fb43d914f9e383ea2469d4f3d51df3d00/orjson-3.11.7-cp313-cp313-macosx_15_0_arm64.whl", hash = "sha256:d897e81f8d0cbd2abb82226d1860ad2e1ab3ff16d7b08c96ca00df9d45409ef4", size = 125189, upload-time = "2026-02-02T15:38:08.181Z" }, - { url = "https://files.pythonhosted.org/packages/89/25/0a16e0729a0e6a1504f9d1a13cdd365f030068aab64cec6958396b9969d7/orjson-3.11.7-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:814be4b49b228cfc0b3c565acf642dd7d13538f966e3ccde61f4f55be3e20785", size = 128106, upload-time = "2026-02-02T15:38:09.41Z" }, - { url = "https://files.pythonhosted.org/packages/66/da/a2e505469d60666a05ab373f1a6322eb671cb2ba3a0ccfc7d4bc97196787/orjson-3.11.7-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d06e5c5fed5caedd2e540d62e5b1c25e8c82431b9e577c33537e5fa4aa909539", size = 123363, upload-time = "2026-02-02T15:38:10.73Z" }, - { url = "https://files.pythonhosted.org/packages/23/bf/ed73f88396ea35c71b38961734ea4a4746f7ca0768bf28fd551d37e48dd0/orjson-3.11.7-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:31c80ce534ac4ea3739c5ee751270646cbc46e45aea7576a38ffec040b4029a1", size = 129007, upload-time = "2026-02-02T15:38:12.138Z" }, - { url = "https://files.pythonhosted.org/packages/73/3c/b05d80716f0225fc9008fbf8ab22841dcc268a626aa550561743714ce3bf/orjson-3.11.7-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f50979824bde13d32b4320eedd513431c921102796d86be3eee0b58e58a3ecd1", size = 141667, upload-time = "2026-02-02T15:38:13.398Z" }, - { url = "https://files.pythonhosted.org/packages/61/e8/0be9b0addd9bf86abfc938e97441dcd0375d494594b1c8ad10fe57479617/orjson-3.11.7-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9e54f3808e2b6b945078c41aa8d9b5834b28c50843846e97807e5adb75fa9705", size = 130832, upload-time = "2026-02-02T15:38:14.698Z" }, - { url = "https://files.pythonhosted.org/packages/c9/ec/c68e3b9021a31d9ec15a94931db1410136af862955854ed5dd7e7e4f5bff/orjson-3.11.7-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a12b80df61aab7b98b490fe9e4879925ba666fccdfcd175252ce4d9035865ace", size = 133373, upload-time = "2026-02-02T15:38:16.109Z" }, - { url = "https://files.pythonhosted.org/packages/d2/45/f3466739aaafa570cc8e77c6dbb853c48bf56e3b43738020e2661e08b0ac/orjson-3.11.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:996b65230271f1a97026fd0e6a753f51fbc0c335d2ad0c6201f711b0da32693b", size = 138307, upload-time = "2026-02-02T15:38:17.453Z" }, - { url = "https://files.pythonhosted.org/packages/e1/84/9f7f02288da1ffb31405c1be07657afd1eecbcb4b64ee2817b6fe0f785fa/orjson-3.11.7-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:ab49d4b2a6a1d415ddb9f37a21e02e0d5dbfe10b7870b21bf779fc21e9156157", size = 408695, upload-time = "2026-02-02T15:38:18.831Z" }, - { url = "https://files.pythonhosted.org/packages/18/07/9dd2f0c0104f1a0295ffbe912bc8d63307a539b900dd9e2c48ef7810d971/orjson-3.11.7-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:390a1dce0c055ddf8adb6aa94a73b45a4a7d7177b5c584b8d1c1947f2ba60fb3", size = 144099, upload-time = "2026-02-02T15:38:20.28Z" }, - { url = "https://files.pythonhosted.org/packages/a5/66/857a8e4a3292e1f7b1b202883bcdeb43a91566cf59a93f97c53b44bd6801/orjson-3.11.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1eb80451a9c351a71dfaf5b7ccc13ad065405217726b59fdbeadbcc544f9d223", size = 134806, upload-time = "2026-02-02T15:38:22.186Z" }, - { url = "https://files.pythonhosted.org/packages/0a/5b/6ebcf3defc1aab3a338ca777214966851e92efb1f30dc7fc8285216e6d1b/orjson-3.11.7-cp313-cp313-win32.whl", hash = "sha256:7477aa6a6ec6139c5cb1cc7b214643592169a5494d200397c7fc95d740d5fcf3", size = 127914, upload-time = "2026-02-02T15:38:23.511Z" }, - { url = "https://files.pythonhosted.org/packages/00/04/c6f72daca5092e3117840a1b1e88dfc809cc1470cf0734890d0366b684a1/orjson-3.11.7-cp313-cp313-win_amd64.whl", hash = "sha256:b9f95dcdea9d4f805daa9ddf02617a89e484c6985fa03055459f90e87d7a0757", size = 124986, upload-time = "2026-02-02T15:38:24.836Z" }, - { url = "https://files.pythonhosted.org/packages/03/ba/077a0f6f1085d6b806937246860fafbd5b17f3919c70ee3f3d8d9c713f38/orjson-3.11.7-cp313-cp313-win_arm64.whl", hash = "sha256:800988273a014a0541483dc81021247d7eacb0c845a9d1a34a422bc718f41539", size = 126045, upload-time = "2026-02-02T15:38:26.216Z" }, - { url = "https://files.pythonhosted.org/packages/e9/1e/745565dca749813db9a093c5ebc4bac1a9475c64d54b95654336ac3ed961/orjson-3.11.7-cp314-cp314-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:de0a37f21d0d364954ad5de1970491d7fbd0fb1ef7417d4d56a36dc01ba0c0a0", size = 228391, upload-time = "2026-02-02T15:38:27.757Z" }, - { url = "https://files.pythonhosted.org/packages/46/19/e40f6225da4d3aa0c8dc6e5219c5e87c2063a560fe0d72a88deb59776794/orjson-3.11.7-cp314-cp314-macosx_15_0_arm64.whl", hash = "sha256:c2428d358d85e8da9d37cba18b8c4047c55222007a84f97156a5b22028dfbfc0", size = 125188, upload-time = "2026-02-02T15:38:29.241Z" }, - { url = "https://files.pythonhosted.org/packages/9d/7e/c4de2babef2c0817fd1f048fd176aa48c37bec8aef53d2fa932983032cce/orjson-3.11.7-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c4bc6c6ac52cdaa267552544c73e486fecbd710b7ac09bc024d5a78555a22f6", size = 128097, upload-time = "2026-02-02T15:38:30.618Z" }, - { url = "https://files.pythonhosted.org/packages/eb/74/233d360632bafd2197f217eee7fb9c9d0229eac0c18128aee5b35b0014fe/orjson-3.11.7-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bd0d68edd7dfca1b2eca9361a44ac9f24b078de3481003159929a0573f21a6bf", size = 123364, upload-time = "2026-02-02T15:38:32.363Z" }, - { url = "https://files.pythonhosted.org/packages/79/51/af79504981dd31efe20a9e360eb49c15f06df2b40e7f25a0a52d9ae888e8/orjson-3.11.7-cp314-cp314-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:623ad1b9548ef63886319c16fa317848e465a21513b31a6ad7b57443c3e0dcf5", size = 129076, upload-time = "2026-02-02T15:38:33.68Z" }, - { url = "https://files.pythonhosted.org/packages/67/e2/da898eb68b72304f8de05ca6715870d09d603ee98d30a27e8a9629abc64b/orjson-3.11.7-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6e776b998ac37c0396093d10290e60283f59cfe0fc3fccbd0ccc4bd04dd19892", size = 141705, upload-time = "2026-02-02T15:38:34.989Z" }, - { url = "https://files.pythonhosted.org/packages/c5/89/15364d92acb3d903b029e28d834edb8780c2b97404cbf7929aa6b9abdb24/orjson-3.11.7-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:652c6c3af76716f4a9c290371ba2e390ede06f6603edb277b481daf37f6f464e", size = 130855, upload-time = "2026-02-02T15:38:36.379Z" }, - { url = "https://files.pythonhosted.org/packages/c2/8b/ecdad52d0b38d4b8f514be603e69ccd5eacf4e7241f972e37e79792212ec/orjson-3.11.7-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a56df3239294ea5964adf074c54bcc4f0ccd21636049a2cf3ca9cf03b5d03cf1", size = 133386, upload-time = "2026-02-02T15:38:37.704Z" }, - { url = "https://files.pythonhosted.org/packages/b9/0e/45e1dcf10e17d0924b7c9162f87ec7b4ca79e28a0548acf6a71788d3e108/orjson-3.11.7-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:bda117c4148e81f746655d5a3239ae9bd00cb7bc3ca178b5fc5a5997e9744183", size = 138295, upload-time = "2026-02-02T15:38:39.096Z" }, - { url = "https://files.pythonhosted.org/packages/63/d7/4d2e8b03561257af0450f2845b91fbd111d7e526ccdf737267108075e0ba/orjson-3.11.7-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:23d6c20517a97a9daf1d48b580fcdc6f0516c6f4b5038823426033690b4d2650", size = 408720, upload-time = "2026-02-02T15:38:40.634Z" }, - { url = "https://files.pythonhosted.org/packages/78/cf/d45343518282108b29c12a65892445fc51f9319dc3c552ceb51bb5905ed2/orjson-3.11.7-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:8ff206156006da5b847c9304b6308a01e8cdbc8cce824e2779a5ba71c3def141", size = 144152, upload-time = "2026-02-02T15:38:42.262Z" }, - { url = "https://files.pythonhosted.org/packages/a9/3a/d6001f51a7275aacd342e77b735c71fa04125a3f93c36fee4526bc8c654e/orjson-3.11.7-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:962d046ee1765f74a1da723f4b33e3b228fe3a48bd307acce5021dfefe0e29b2", size = 134814, upload-time = "2026-02-02T15:38:43.627Z" }, - { url = "https://files.pythonhosted.org/packages/1d/d3/f19b47ce16820cc2c480f7f1723e17f6d411b3a295c60c8ad3aa9ff1c96a/orjson-3.11.7-cp314-cp314-win32.whl", hash = "sha256:89e13dd3f89f1c38a9c9eba5fbf7cdc2d1feca82f5f290864b4b7a6aac704576", size = 127997, upload-time = "2026-02-02T15:38:45.06Z" }, - { url = "https://files.pythonhosted.org/packages/12/df/172771902943af54bf661a8d102bdf2e7f932127968080632bda6054b62c/orjson-3.11.7-cp314-cp314-win_amd64.whl", hash = "sha256:845c3e0d8ded9c9271cd79596b9b552448b885b97110f628fb687aee2eed11c1", size = 124985, upload-time = "2026-02-02T15:38:46.388Z" }, - { url = "https://files.pythonhosted.org/packages/6f/1c/f2a8d8a1b17514660a614ce5f7aac74b934e69f5abc2700cc7ced882a009/orjson-3.11.7-cp314-cp314-win_arm64.whl", hash = "sha256:4a2e9c5be347b937a2e0203866f12bba36082e89b402ddb9e927d5822e43088d", size = 126038, upload-time = "2026-02-02T15:38:47.703Z" }, +wheels = [ + {url = "https://files.pythonhosted.org/packages/37/02/da6cb01fc6087048d7f61522c327edf4250f1683a58a839fdcc435746dd5/orjson-3.11.7-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9487abc2c2086e7c8eb9a211d2ce8855bae0e92586279d0d27b341d5ad76c85c", size = 228664, upload-time = "2026-02-02T15:37:25.542Z"}, + {url = "https://files.pythonhosted.org/packages/c1/c2/5885e7a5881dba9a9af51bc564e8967225a642b3e03d089289a35054e749/orjson-3.11.7-cp311-cp311-macosx_15_0_arm64.whl", hash = "sha256:79cacb0b52f6004caf92405a7e1f11e6e2de8bdf9019e4f76b44ba045125cd6b", size = 125344, upload-time = "2026-02-02T15:37:26.92Z"}, + {url = "https://files.pythonhosted.org/packages/a4/1d/4e7688de0a92d1caf600dfd5fb70b4c5bfff51dfa61ac555072ef2d0d32a/orjson-3.11.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c2e85fe4698b6a56d5e2ebf7ae87544d668eb6bde1ad1226c13f44663f20ec9e", size = 128404, upload-time = "2026-02-02T15:37:28.108Z"}, + {url = "https://files.pythonhosted.org/packages/2f/b2/ec04b74ae03a125db7bd69cffd014b227b7f341e3261bf75b5eb88a1aa92/orjson-3.11.7-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b8d14b71c0b12963fe8a62aac87119f1afdf4cb88a400f61ca5ae581449efcb5", size = 123677, upload-time = "2026-02-02T15:37:30.287Z"}, + {url = "https://files.pythonhosted.org/packages/4c/69/f95bdf960605f08f827f6e3291fe243d8aa9c5c9ff017a8d7232209184c3/orjson-3.11.7-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:91c81ef070c8f3220054115e1ef468b1c9ce8497b4e526cb9f68ab4dc0a7ac62", size = 128950, upload-time = "2026-02-02T15:37:31.595Z"}, + {url = "https://files.pythonhosted.org/packages/a4/1b/de59c57bae1d148ef298852abd31909ac3089cff370dfd4cd84cc99cbc42/orjson-3.11.7-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:411ebaf34d735e25e358a6d9e7978954a9c9d58cfb47bc6683cdc3964cd2f910", size = 141756, upload-time = "2026-02-02T15:37:32.985Z"}, + {url = "https://files.pythonhosted.org/packages/ee/9e/9decc59f4499f695f65c650f6cfa6cd4c37a3fbe8fa235a0a3614cb54386/orjson-3.11.7-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a16bcd08ab0bcdfc7e8801d9c4a9cc17e58418e4d48ddc6ded4e9e4b1a94062b", size = 130812, upload-time = "2026-02-02T15:37:34.204Z"}, + {url = "https://files.pythonhosted.org/packages/28/e6/59f932bcabd1eac44e334fe8e3281a92eacfcb450586e1f4bde0423728d8/orjson-3.11.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c0b51672e466fd7e56230ffbae7f1639e18d0ce023351fb75da21b71bc2c960", size = 133444, upload-time = "2026-02-02T15:37:35.446Z"}, + {url = "https://files.pythonhosted.org/packages/f1/36/b0f05c0eaa7ca30bc965e37e6a2956b0d67adb87a9872942d3568da846ae/orjson-3.11.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:136dcd6a2e796dfd9ffca9fc027d778567b0b7c9968d092842d3c323cef88aa8", size = 138609, upload-time = "2026-02-02T15:37:36.657Z"}, + {url = "https://files.pythonhosted.org/packages/b8/03/58ec7d302b8d86944c60c7b4b82975d5161fcce4c9bc8c6cb1d6741b6115/orjson-3.11.7-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:7ba61079379b0ae29e117db13bda5f28d939766e410d321ec1624afc6a0b0504", size = 408918, upload-time = "2026-02-02T15:37:38.076Z"}, + {url = "https://files.pythonhosted.org/packages/06/3a/868d65ef9a8b99be723bd510de491349618abd9f62c826cf206d962db295/orjson-3.11.7-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:0527a4510c300e3b406591b0ba69b5dc50031895b0a93743526a3fc45f59d26e", size = 143998, upload-time = "2026-02-02T15:37:39.706Z"}, + {url = "https://files.pythonhosted.org/packages/5b/c7/1e18e1c83afe3349f4f6dc9e14910f0ae5f82eac756d1412ea4018938535/orjson-3.11.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a709e881723c9b18acddcfb8ba357322491ad553e277cf467e1e7e20e2d90561", size = 134802, upload-time = "2026-02-02T15:37:41.002Z"}, + {url = "https://files.pythonhosted.org/packages/d4/0b/ccb7ee1a65b37e8eeb8b267dc953561d72370e85185e459616d4345bab34/orjson-3.11.7-cp311-cp311-win32.whl", hash = "sha256:c43b8b5bab288b6b90dac410cca7e986a4fa747a2e8f94615aea407da706980d", size = 127828, upload-time = "2026-02-02T15:37:42.241Z"}, + {url = "https://files.pythonhosted.org/packages/af/9e/55c776dffda3f381e0f07d010a4f5f3902bf48eaba1bb7684d301acd4924/orjson-3.11.7-cp311-cp311-win_amd64.whl", hash = "sha256:6543001328aa857187f905308a028935864aefe9968af3848401b6fe80dbb471", size = 124941, upload-time = "2026-02-02T15:37:43.444Z"}, + {url = "https://files.pythonhosted.org/packages/aa/8e/424a620fa7d263b880162505fb107ef5e0afaa765b5b06a88312ac291560/orjson-3.11.7-cp311-cp311-win_arm64.whl", hash = "sha256:1ee5cc7160a821dfe14f130bc8e63e7611051f964b463d9e2a3a573204446a4d", size = 126245, upload-time = "2026-02-02T15:37:45.18Z"}, + {url = "https://files.pythonhosted.org/packages/80/bf/76f4f1665f6983385938f0e2a5d7efa12a58171b8456c252f3bae8a4cf75/orjson-3.11.7-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:bd03ea7606833655048dab1a00734a2875e3e86c276e1d772b2a02556f0d895f", size = 228545, upload-time = "2026-02-02T15:37:46.376Z"}, + {url = "https://files.pythonhosted.org/packages/79/53/6c72c002cb13b5a978a068add59b25a8bdf2800ac1c9c8ecdb26d6d97064/orjson-3.11.7-cp312-cp312-macosx_15_0_arm64.whl", hash = "sha256:89e440ebc74ce8ab5c7bc4ce6757b4a6b1041becb127df818f6997b5c71aa60b", size = 125224, upload-time = "2026-02-02T15:37:47.697Z"}, + {url = "https://files.pythonhosted.org/packages/2c/83/10e48852865e5dd151bdfe652c06f7da484578ed02c5fca938e3632cb0b8/orjson-3.11.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ede977b5fe5ac91b1dffc0a517ca4542d2ec8a6a4ff7b2652d94f640796342a", size = 128154, upload-time = "2026-02-02T15:37:48.954Z"}, + {url = "https://files.pythonhosted.org/packages/6e/52/a66e22a2b9abaa374b4a081d410edab6d1e30024707b87eab7c734afe28d/orjson-3.11.7-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b7b1dae39230a393df353827c855a5f176271c23434cfd2db74e0e424e693e10", size = 123548, upload-time = "2026-02-02T15:37:50.187Z"}, + {url = "https://files.pythonhosted.org/packages/de/38/605d371417021359f4910c496f764c48ceb8997605f8c25bf1dfe58c0ebe/orjson-3.11.7-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ed46f17096e28fb28d2975834836a639af7278aa87c84f68ab08fbe5b8bd75fa", size = 129000, upload-time = "2026-02-02T15:37:51.426Z"}, + {url = "https://files.pythonhosted.org/packages/44/98/af32e842b0ffd2335c89714d48ca4e3917b42f5d6ee5537832e069a4b3ac/orjson-3.11.7-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3726be79e36e526e3d9c1aceaadbfb4a04ee80a72ab47b3f3c17fefb9812e7b8", size = 141686, upload-time = "2026-02-02T15:37:52.607Z"}, + {url = "https://files.pythonhosted.org/packages/96/0b/fc793858dfa54be6feee940c1463370ece34b3c39c1ca0aa3845f5ba9892/orjson-3.11.7-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0724e265bc548af1dedebd9cb3d24b4e1c1e685a343be43e87ba922a5c5fff2f", size = 130812, upload-time = "2026-02-02T15:37:53.944Z"}, + {url = "https://files.pythonhosted.org/packages/dc/91/98a52415059db3f374757d0b7f0f16e3b5cd5976c90d1c2b56acaea039e6/orjson-3.11.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e7745312efa9e11c17fbd3cb3097262d079da26930ae9ae7ba28fb738367cbad", size = 133440, upload-time = "2026-02-02T15:37:55.615Z"}, + {url = "https://files.pythonhosted.org/packages/dc/b6/cb540117bda61791f46381f8c26c8f93e802892830a6055748d3bb1925ab/orjson-3.11.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f904c24bdeabd4298f7a977ef14ca2a022ca921ed670b92ecd16ab6f3d01f867", size = 138386, upload-time = "2026-02-02T15:37:56.814Z"}, + {url = "https://files.pythonhosted.org/packages/63/1a/50a3201c334a7f17c231eee5f841342190723794e3b06293f26e7cf87d31/orjson-3.11.7-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:b9fc4d0f81f394689e0814617aadc4f2ea0e8025f38c226cbf22d3b5ddbf025d", size = 408853, upload-time = "2026-02-02T15:37:58.291Z"}, + {url = "https://files.pythonhosted.org/packages/87/cd/8de1c67d0be44fdc22701e5989c0d015a2adf391498ad42c4dc589cd3013/orjson-3.11.7-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:849e38203e5be40b776ed2718e587faf204d184fc9a008ae441f9442320c0cab", size = 144130, upload-time = "2026-02-02T15:38:00.163Z"}, + {url = "https://files.pythonhosted.org/packages/0f/fe/d605d700c35dd55f51710d159fc54516a280923cd1b7e47508982fbb387d/orjson-3.11.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:4682d1db3bcebd2b64757e0ddf9e87ae5f00d29d16c5cdf3a62f561d08cc3dd2", size = 134818, upload-time = "2026-02-02T15:38:01.507Z"}, + {url = "https://files.pythonhosted.org/packages/e4/e4/15ecc67edb3ddb3e2f46ae04475f2d294e8b60c1825fbe28a428b93b3fbd/orjson-3.11.7-cp312-cp312-win32.whl", hash = "sha256:f4f7c956b5215d949a1f65334cf9d7612dde38f20a95f2315deef167def91a6f", size = 127923, upload-time = "2026-02-02T15:38:02.75Z"}, + {url = "https://files.pythonhosted.org/packages/34/70/2e0855361f76198a3965273048c8e50a9695d88cd75811a5b46444895845/orjson-3.11.7-cp312-cp312-win_amd64.whl", hash = "sha256:bf742e149121dc5648ba0a08ea0871e87b660467ef168a3a5e53bc1fbd64bb74", size = 125007, upload-time = "2026-02-02T15:38:04.032Z"}, + {url = "https://files.pythonhosted.org/packages/68/40/c2051bd19fc467610fed469dc29e43ac65891571138f476834ca192bc290/orjson-3.11.7-cp312-cp312-win_arm64.whl", hash = "sha256:26c3b9132f783b7d7903bf1efb095fed8d4a3a85ec0d334ee8beff3d7a4749d5", size = 126089, upload-time = "2026-02-02T15:38:05.297Z"}, + {url = "https://files.pythonhosted.org/packages/89/25/6e0e52cac5aab51d7b6dcd257e855e1dec1c2060f6b28566c509b4665f62/orjson-3.11.7-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:1d98b30cc1313d52d4af17d9c3d307b08389752ec5f2e5febdfada70b0f8c733", size = 228390, upload-time = "2026-02-02T15:38:06.8Z"}, + {url = "https://files.pythonhosted.org/packages/a5/29/a77f48d2fc8a05bbc529e5ff481fb43d914f9e383ea2469d4f3d51df3d00/orjson-3.11.7-cp313-cp313-macosx_15_0_arm64.whl", hash = "sha256:d897e81f8d0cbd2abb82226d1860ad2e1ab3ff16d7b08c96ca00df9d45409ef4", size = 125189, upload-time = "2026-02-02T15:38:08.181Z"}, + {url = "https://files.pythonhosted.org/packages/89/25/0a16e0729a0e6a1504f9d1a13cdd365f030068aab64cec6958396b9969d7/orjson-3.11.7-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:814be4b49b228cfc0b3c565acf642dd7d13538f966e3ccde61f4f55be3e20785", size = 128106, upload-time = "2026-02-02T15:38:09.41Z"}, + {url = "https://files.pythonhosted.org/packages/66/da/a2e505469d60666a05ab373f1a6322eb671cb2ba3a0ccfc7d4bc97196787/orjson-3.11.7-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d06e5c5fed5caedd2e540d62e5b1c25e8c82431b9e577c33537e5fa4aa909539", size = 123363, upload-time = "2026-02-02T15:38:10.73Z"}, + {url = "https://files.pythonhosted.org/packages/23/bf/ed73f88396ea35c71b38961734ea4a4746f7ca0768bf28fd551d37e48dd0/orjson-3.11.7-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:31c80ce534ac4ea3739c5ee751270646cbc46e45aea7576a38ffec040b4029a1", size = 129007, upload-time = "2026-02-02T15:38:12.138Z"}, + {url = "https://files.pythonhosted.org/packages/73/3c/b05d80716f0225fc9008fbf8ab22841dcc268a626aa550561743714ce3bf/orjson-3.11.7-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f50979824bde13d32b4320eedd513431c921102796d86be3eee0b58e58a3ecd1", size = 141667, upload-time = "2026-02-02T15:38:13.398Z"}, + {url = "https://files.pythonhosted.org/packages/61/e8/0be9b0addd9bf86abfc938e97441dcd0375d494594b1c8ad10fe57479617/orjson-3.11.7-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9e54f3808e2b6b945078c41aa8d9b5834b28c50843846e97807e5adb75fa9705", size = 130832, upload-time = "2026-02-02T15:38:14.698Z"}, + {url = "https://files.pythonhosted.org/packages/c9/ec/c68e3b9021a31d9ec15a94931db1410136af862955854ed5dd7e7e4f5bff/orjson-3.11.7-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a12b80df61aab7b98b490fe9e4879925ba666fccdfcd175252ce4d9035865ace", size = 133373, upload-time = "2026-02-02T15:38:16.109Z"}, + {url = "https://files.pythonhosted.org/packages/d2/45/f3466739aaafa570cc8e77c6dbb853c48bf56e3b43738020e2661e08b0ac/orjson-3.11.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:996b65230271f1a97026fd0e6a753f51fbc0c335d2ad0c6201f711b0da32693b", size = 138307, upload-time = "2026-02-02T15:38:17.453Z"}, + {url = "https://files.pythonhosted.org/packages/e1/84/9f7f02288da1ffb31405c1be07657afd1eecbcb4b64ee2817b6fe0f785fa/orjson-3.11.7-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:ab49d4b2a6a1d415ddb9f37a21e02e0d5dbfe10b7870b21bf779fc21e9156157", size = 408695, upload-time = "2026-02-02T15:38:18.831Z"}, + {url = "https://files.pythonhosted.org/packages/18/07/9dd2f0c0104f1a0295ffbe912bc8d63307a539b900dd9e2c48ef7810d971/orjson-3.11.7-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:390a1dce0c055ddf8adb6aa94a73b45a4a7d7177b5c584b8d1c1947f2ba60fb3", size = 144099, upload-time = "2026-02-02T15:38:20.28Z"}, + {url = "https://files.pythonhosted.org/packages/a5/66/857a8e4a3292e1f7b1b202883bcdeb43a91566cf59a93f97c53b44bd6801/orjson-3.11.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1eb80451a9c351a71dfaf5b7ccc13ad065405217726b59fdbeadbcc544f9d223", size = 134806, upload-time = "2026-02-02T15:38:22.186Z"}, + {url = "https://files.pythonhosted.org/packages/0a/5b/6ebcf3defc1aab3a338ca777214966851e92efb1f30dc7fc8285216e6d1b/orjson-3.11.7-cp313-cp313-win32.whl", hash = "sha256:7477aa6a6ec6139c5cb1cc7b214643592169a5494d200397c7fc95d740d5fcf3", size = 127914, upload-time = "2026-02-02T15:38:23.511Z"}, + {url = "https://files.pythonhosted.org/packages/00/04/c6f72daca5092e3117840a1b1e88dfc809cc1470cf0734890d0366b684a1/orjson-3.11.7-cp313-cp313-win_amd64.whl", hash = "sha256:b9f95dcdea9d4f805daa9ddf02617a89e484c6985fa03055459f90e87d7a0757", size = 124986, upload-time = "2026-02-02T15:38:24.836Z"}, + {url = "https://files.pythonhosted.org/packages/03/ba/077a0f6f1085d6b806937246860fafbd5b17f3919c70ee3f3d8d9c713f38/orjson-3.11.7-cp313-cp313-win_arm64.whl", hash = "sha256:800988273a014a0541483dc81021247d7eacb0c845a9d1a34a422bc718f41539", size = 126045, upload-time = "2026-02-02T15:38:26.216Z"}, + {url = "https://files.pythonhosted.org/packages/e9/1e/745565dca749813db9a093c5ebc4bac1a9475c64d54b95654336ac3ed961/orjson-3.11.7-cp314-cp314-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:de0a37f21d0d364954ad5de1970491d7fbd0fb1ef7417d4d56a36dc01ba0c0a0", size = 228391, upload-time = "2026-02-02T15:38:27.757Z"}, + {url = "https://files.pythonhosted.org/packages/46/19/e40f6225da4d3aa0c8dc6e5219c5e87c2063a560fe0d72a88deb59776794/orjson-3.11.7-cp314-cp314-macosx_15_0_arm64.whl", hash = "sha256:c2428d358d85e8da9d37cba18b8c4047c55222007a84f97156a5b22028dfbfc0", size = 125188, upload-time = "2026-02-02T15:38:29.241Z"}, + {url = "https://files.pythonhosted.org/packages/9d/7e/c4de2babef2c0817fd1f048fd176aa48c37bec8aef53d2fa932983032cce/orjson-3.11.7-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c4bc6c6ac52cdaa267552544c73e486fecbd710b7ac09bc024d5a78555a22f6", size = 128097, upload-time = "2026-02-02T15:38:30.618Z"}, + {url = "https://files.pythonhosted.org/packages/eb/74/233d360632bafd2197f217eee7fb9c9d0229eac0c18128aee5b35b0014fe/orjson-3.11.7-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bd0d68edd7dfca1b2eca9361a44ac9f24b078de3481003159929a0573f21a6bf", size = 123364, upload-time = "2026-02-02T15:38:32.363Z"}, + {url = "https://files.pythonhosted.org/packages/79/51/af79504981dd31efe20a9e360eb49c15f06df2b40e7f25a0a52d9ae888e8/orjson-3.11.7-cp314-cp314-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:623ad1b9548ef63886319c16fa317848e465a21513b31a6ad7b57443c3e0dcf5", size = 129076, upload-time = "2026-02-02T15:38:33.68Z"}, + {url = "https://files.pythonhosted.org/packages/67/e2/da898eb68b72304f8de05ca6715870d09d603ee98d30a27e8a9629abc64b/orjson-3.11.7-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6e776b998ac37c0396093d10290e60283f59cfe0fc3fccbd0ccc4bd04dd19892", size = 141705, upload-time = "2026-02-02T15:38:34.989Z"}, + {url = "https://files.pythonhosted.org/packages/c5/89/15364d92acb3d903b029e28d834edb8780c2b97404cbf7929aa6b9abdb24/orjson-3.11.7-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:652c6c3af76716f4a9c290371ba2e390ede06f6603edb277b481daf37f6f464e", size = 130855, upload-time = "2026-02-02T15:38:36.379Z"}, + {url = "https://files.pythonhosted.org/packages/c2/8b/ecdad52d0b38d4b8f514be603e69ccd5eacf4e7241f972e37e79792212ec/orjson-3.11.7-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a56df3239294ea5964adf074c54bcc4f0ccd21636049a2cf3ca9cf03b5d03cf1", size = 133386, upload-time = "2026-02-02T15:38:37.704Z"}, + {url = "https://files.pythonhosted.org/packages/b9/0e/45e1dcf10e17d0924b7c9162f87ec7b4ca79e28a0548acf6a71788d3e108/orjson-3.11.7-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:bda117c4148e81f746655d5a3239ae9bd00cb7bc3ca178b5fc5a5997e9744183", size = 138295, upload-time = "2026-02-02T15:38:39.096Z"}, + {url = "https://files.pythonhosted.org/packages/63/d7/4d2e8b03561257af0450f2845b91fbd111d7e526ccdf737267108075e0ba/orjson-3.11.7-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:23d6c20517a97a9daf1d48b580fcdc6f0516c6f4b5038823426033690b4d2650", size = 408720, upload-time = "2026-02-02T15:38:40.634Z"}, + {url = "https://files.pythonhosted.org/packages/78/cf/d45343518282108b29c12a65892445fc51f9319dc3c552ceb51bb5905ed2/orjson-3.11.7-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:8ff206156006da5b847c9304b6308a01e8cdbc8cce824e2779a5ba71c3def141", size = 144152, upload-time = "2026-02-02T15:38:42.262Z"}, + {url = "https://files.pythonhosted.org/packages/a9/3a/d6001f51a7275aacd342e77b735c71fa04125a3f93c36fee4526bc8c654e/orjson-3.11.7-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:962d046ee1765f74a1da723f4b33e3b228fe3a48bd307acce5021dfefe0e29b2", size = 134814, upload-time = "2026-02-02T15:38:43.627Z"}, + {url = "https://files.pythonhosted.org/packages/1d/d3/f19b47ce16820cc2c480f7f1723e17f6d411b3a295c60c8ad3aa9ff1c96a/orjson-3.11.7-cp314-cp314-win32.whl", hash = "sha256:89e13dd3f89f1c38a9c9eba5fbf7cdc2d1feca82f5f290864b4b7a6aac704576", size = 127997, upload-time = "2026-02-02T15:38:45.06Z"}, + {url = "https://files.pythonhosted.org/packages/12/df/172771902943af54bf661a8d102bdf2e7f932127968080632bda6054b62c/orjson-3.11.7-cp314-cp314-win_amd64.whl", hash = "sha256:845c3e0d8ded9c9271cd79596b9b552448b885b97110f628fb687aee2eed11c1", size = 124985, upload-time = "2026-02-02T15:38:46.388Z"}, + {url = "https://files.pythonhosted.org/packages/6f/1c/f2a8d8a1b17514660a614ce5f7aac74b934e69f5abc2700cc7ced882a009/orjson-3.11.7-cp314-cp314-win_arm64.whl", hash = "sha256:4a2e9c5be347b937a2e0203866f12bba36082e89b402ddb9e927d5822e43088d", size = 126038, upload-time = "2026-02-02T15:38:47.703Z"} ] [[package]] name = "packaging" +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"} +source = {registry = "https://pypi.org/simple"} 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" }, + {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]] +dependencies = [ + {name = "numpy"}, + {name = "python-dateutil"}, + {name = "tzdata", marker = "sys_platform == 'emscripten' or sys_platform == 'win32'"} +] name = "pandas" +sdist = {url = "https://files.pythonhosted.org/packages/2e/0c/b28ed414f080ee0ad153f848586d61d1878f91689950f037f976ce15f6c8/pandas-3.0.1.tar.gz", hash = "sha256:4186a699674af418f655dbd420ed87f50d56b4cd6603784279d9eef6627823c8", size = 4641901, upload-time = "2026-02-17T22:20:16.434Z"} +source = {registry = "https://pypi.org/simple"} version = "3.0.1" -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/2e/0c/b28ed414f080ee0ad153f848586d61d1878f91689950f037f976ce15f6c8/pandas-3.0.1.tar.gz", hash = "sha256:4186a699674af418f655dbd420ed87f50d56b4cd6603784279d9eef6627823c8", size = 4641901, upload-time = "2026-02-17T22:20:16.434Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ff/07/c7087e003ceee9b9a82539b40414ec557aa795b584a1a346e89180853d79/pandas-3.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:de09668c1bf3b925c07e5762291602f0d789eca1b3a781f99c1c78f6cac0e7ea", size = 10323380, upload-time = "2026-02-17T22:18:16.133Z" }, - { url = "https://files.pythonhosted.org/packages/c1/27/90683c7122febeefe84a56f2cde86a9f05f68d53885cebcc473298dfc33e/pandas-3.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:24ba315ba3d6e5806063ac6eb717504e499ce30bd8c236d8693a5fd3f084c796", size = 9923455, upload-time = "2026-02-17T22:18:19.13Z" }, - { url = "https://files.pythonhosted.org/packages/0e/f1/ed17d927f9950643bc7631aa4c99ff0cc83a37864470bc419345b656a41f/pandas-3.0.1-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:406ce835c55bac912f2a0dcfaf27c06d73c6b04a5dde45f1fd3169ce31337389", size = 10753464, upload-time = "2026-02-17T22:18:21.134Z" }, - { url = "https://files.pythonhosted.org/packages/2e/7c/870c7e7daec2a6c7ff2ac9e33b23317230d4e4e954b35112759ea4a924a7/pandas-3.0.1-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:830994d7e1f31dd7e790045235605ab61cff6c94defc774547e8b7fdfbff3dc7", size = 11255234, upload-time = "2026-02-17T22:18:24.175Z" }, - { url = "https://files.pythonhosted.org/packages/5c/39/3653fe59af68606282b989c23d1a543ceba6e8099cbcc5f1d506a7bae2aa/pandas-3.0.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a64ce8b0f2de1d2efd2ae40b0abe7f8ae6b29fbfb3812098ed5a6f8e235ad9bf", size = 11767299, upload-time = "2026-02-17T22:18:26.824Z" }, - { url = "https://files.pythonhosted.org/packages/9b/31/1daf3c0c94a849c7a8dab8a69697b36d313b229918002ba3e409265c7888/pandas-3.0.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9832c2c69da24b602c32e0c7b1b508a03949c18ba08d4d9f1c1033426685b447", size = 12333292, upload-time = "2026-02-17T22:18:28.996Z" }, - { url = "https://files.pythonhosted.org/packages/1f/67/af63f83cd6ca603a00fe8530c10a60f0879265b8be00b5930e8e78c5b30b/pandas-3.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:84f0904a69e7365f79a0c77d3cdfccbfb05bf87847e3a51a41e1426b0edb9c79", size = 9892176, upload-time = "2026-02-17T22:18:31.79Z" }, - { url = "https://files.pythonhosted.org/packages/79/ab/9c776b14ac4b7b4140788eca18468ea39894bc7340a408f1d1e379856a6b/pandas-3.0.1-cp311-cp311-win_arm64.whl", hash = "sha256:4a68773d5a778afb31d12e34f7dd4612ab90de8c6fb1d8ffe5d4a03b955082a1", size = 9151328, upload-time = "2026-02-17T22:18:35.721Z" }, - { url = "https://files.pythonhosted.org/packages/37/51/b467209c08dae2c624873d7491ea47d2b47336e5403309d433ea79c38571/pandas-3.0.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:476f84f8c20c9f5bc47252b66b4bb25e1a9fc2fa98cead96744d8116cb85771d", size = 10344357, upload-time = "2026-02-17T22:18:38.262Z" }, - { url = "https://files.pythonhosted.org/packages/7c/f1/e2567ffc8951ab371db2e40b2fe068e36b81d8cf3260f06ae508700e5504/pandas-3.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0ab749dfba921edf641d4036c4c21c0b3ea70fea478165cb98a998fb2a261955", size = 9884543, upload-time = "2026-02-17T22:18:41.476Z" }, - { url = "https://files.pythonhosted.org/packages/d7/39/327802e0b6d693182403c144edacbc27eb82907b57062f23ef5a4c4a5ea7/pandas-3.0.1-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b8e36891080b87823aff3640c78649b91b8ff6eea3c0d70aeabd72ea43ab069b", size = 10396030, upload-time = "2026-02-17T22:18:43.822Z" }, - { url = "https://files.pythonhosted.org/packages/3d/fe/89d77e424365280b79d99b3e1e7d606f5165af2f2ecfaf0c6d24c799d607/pandas-3.0.1-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:532527a701281b9dd371e2f582ed9094f4c12dd9ffb82c0c54ee28d8ac9520c4", size = 10876435, upload-time = "2026-02-17T22:18:45.954Z" }, - { url = "https://files.pythonhosted.org/packages/b5/a6/2a75320849dd154a793f69c951db759aedb8d1dd3939eeacda9bdcfa1629/pandas-3.0.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:356e5c055ed9b0da1580d465657bc7d00635af4fd47f30afb23025352ba764d1", size = 11405133, upload-time = "2026-02-17T22:18:48.533Z" }, - { url = "https://files.pythonhosted.org/packages/58/53/1d68fafb2e02d7881df66aa53be4cd748d25cbe311f3b3c85c93ea5d30ca/pandas-3.0.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:9d810036895f9ad6345b8f2a338dd6998a74e8483847403582cab67745bff821", size = 11932065, upload-time = "2026-02-17T22:18:50.837Z" }, - { url = "https://files.pythonhosted.org/packages/75/08/67cc404b3a966b6df27b38370ddd96b3b023030b572283d035181854aac5/pandas-3.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:536232a5fe26dd989bd633e7a0c450705fdc86a207fec7254a55e9a22950fe43", size = 9741627, upload-time = "2026-02-17T22:18:53.905Z" }, - { url = "https://files.pythonhosted.org/packages/86/4f/caf9952948fb00d23795f09b893d11f1cacb384e666854d87249530f7cbe/pandas-3.0.1-cp312-cp312-win_arm64.whl", hash = "sha256:0f463ebfd8de7f326d38037c7363c6dacb857c5881ab8961fb387804d6daf2f7", size = 9052483, upload-time = "2026-02-17T22:18:57.31Z" }, - { url = "https://files.pythonhosted.org/packages/0b/48/aad6ec4f8d007534c091e9a7172b3ec1b1ee6d99a9cbb936b5eab6c6cf58/pandas-3.0.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5272627187b5d9c20e55d27caf5f2cd23e286aba25cadf73c8590e432e2b7262", size = 10317509, upload-time = "2026-02-17T22:18:59.498Z" }, - { url = "https://files.pythonhosted.org/packages/a8/14/5990826f779f79148ae9d3a2c39593dc04d61d5d90541e71b5749f35af95/pandas-3.0.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:661e0f665932af88c7877f31da0dc743fe9c8f2524bdffe23d24fdcb67ef9d56", size = 9860561, upload-time = "2026-02-17T22:19:02.265Z" }, - { url = "https://files.pythonhosted.org/packages/fa/80/f01ff54664b6d70fed71475543d108a9b7c888e923ad210795bef04ffb7d/pandas-3.0.1-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:75e6e292ff898679e47a2199172593d9f6107fd2dd3617c22c2946e97d5df46e", size = 10365506, upload-time = "2026-02-17T22:19:05.017Z" }, - { url = "https://files.pythonhosted.org/packages/f2/85/ab6d04733a7d6ff32bfc8382bf1b07078228f5d6ebec5266b91bfc5c4ff7/pandas-3.0.1-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1ff8cf1d2896e34343197685f432450ec99a85ba8d90cce2030c5eee2ef98791", size = 10873196, upload-time = "2026-02-17T22:19:07.204Z" }, - { url = "https://files.pythonhosted.org/packages/48/a9/9301c83d0b47c23ac5deab91c6b39fd98d5b5db4d93b25df8d381451828f/pandas-3.0.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:eca8b4510f6763f3d37359c2105df03a7a221a508f30e396a51d0713d462e68a", size = 11370859, upload-time = "2026-02-17T22:19:09.436Z" }, - { url = "https://files.pythonhosted.org/packages/59/fe/0c1fc5bd2d29c7db2ab372330063ad555fb83e08422829c785f5ec2176ca/pandas-3.0.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:06aff2ad6f0b94a17822cf8b83bbb563b090ed82ff4fe7712db2ce57cd50d9b8", size = 11924584, upload-time = "2026-02-17T22:19:11.562Z" }, - { url = "https://files.pythonhosted.org/packages/d6/7d/216a1588b65a7aa5f4535570418a599d943c85afb1d95b0876fc00aa1468/pandas-3.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:9fea306c783e28884c29057a1d9baa11a349bbf99538ec1da44c8476563d1b25", size = 9742769, upload-time = "2026-02-17T22:19:13.926Z" }, - { url = "https://files.pythonhosted.org/packages/c4/cb/810a22a6af9a4e97c8ab1c946b47f3489c5bca5adc483ce0ffc84c9cc768/pandas-3.0.1-cp313-cp313-win_arm64.whl", hash = "sha256:a8d37a43c52917427e897cb2e429f67a449327394396a81034a4449b99afda59", size = 9043855, upload-time = "2026-02-17T22:19:16.09Z" }, - { url = "https://files.pythonhosted.org/packages/92/fa/423c89086cca1f039cf1253c3ff5b90f157b5b3757314aa635f6bf3e30aa/pandas-3.0.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:d54855f04f8246ed7b6fc96b05d4871591143c46c0b6f4af874764ed0d2d6f06", size = 10752673, upload-time = "2026-02-17T22:19:18.304Z" }, - { url = "https://files.pythonhosted.org/packages/22/23/b5a08ec1f40020397f0faba72f1e2c11f7596a6169c7b3e800abff0e433f/pandas-3.0.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:4e1b677accee34a09e0dc2ce5624e4a58a1870ffe56fc021e9caf7f23cd7668f", size = 10404967, upload-time = "2026-02-17T22:19:20.726Z" }, - { url = "https://files.pythonhosted.org/packages/5c/81/94841f1bb4afdc2b52a99daa895ac2c61600bb72e26525ecc9543d453ebc/pandas-3.0.1-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a9cabbdcd03f1b6cd254d6dda8ae09b0252524be1592594c00b7895916cb1324", size = 10320575, upload-time = "2026-02-17T22:19:24.919Z" }, - { url = "https://files.pythonhosted.org/packages/0a/8b/2ae37d66a5342a83adadfd0cb0b4bf9c3c7925424dd5f40d15d6cfaa35ee/pandas-3.0.1-cp313-cp313t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5ae2ab1f166668b41e770650101e7090824fd34d17915dd9cd479f5c5e0065e9", size = 10710921, upload-time = "2026-02-17T22:19:27.181Z" }, - { url = "https://files.pythonhosted.org/packages/a2/61/772b2e2757855e232b7ccf7cb8079a5711becb3a97f291c953def15a833f/pandas-3.0.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6bf0603c2e30e2cafac32807b06435f28741135cb8697eae8b28c7d492fc7d76", size = 11334191, upload-time = "2026-02-17T22:19:29.411Z" }, - { url = "https://files.pythonhosted.org/packages/1b/08/b16c6df3ef555d8495d1d265a7963b65be166785d28f06a350913a4fac78/pandas-3.0.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6c426422973973cae1f4a23e51d4ae85974f44871b24844e4f7de752dd877098", size = 11782256, upload-time = "2026-02-17T22:19:32.34Z" }, - { url = "https://files.pythonhosted.org/packages/55/80/178af0594890dee17e239fca96d3d8670ba0f5ff59b7d0439850924a9c09/pandas-3.0.1-cp313-cp313t-win_amd64.whl", hash = "sha256:b03f91ae8c10a85c1613102c7bef5229b5379f343030a3ccefeca8a33414cf35", size = 10485047, upload-time = "2026-02-17T22:19:34.605Z" }, - { url = "https://files.pythonhosted.org/packages/bb/8b/4bb774a998b97e6c2fd62a9e6cfdaae133b636fd1c468f92afb4ae9a447a/pandas-3.0.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:99d0f92ed92d3083d140bf6b97774f9f13863924cf3f52a70711f4e7588f9d0a", size = 10322465, upload-time = "2026-02-17T22:19:36.803Z" }, - { url = "https://files.pythonhosted.org/packages/72/3a/5b39b51c64159f470f1ca3b1c2a87da290657ca022f7cd11442606f607d1/pandas-3.0.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:3b66857e983208654294bb6477b8a63dee26b37bdd0eb34d010556e91261784f", size = 9910632, upload-time = "2026-02-17T22:19:39.001Z" }, - { url = "https://files.pythonhosted.org/packages/4e/f7/b449ffb3f68c11da12fc06fbf6d2fa3a41c41e17d0284d23a79e1c13a7e4/pandas-3.0.1-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:56cf59638bf24dc9bdf2154c81e248b3289f9a09a6d04e63608c159022352749", size = 10440535, upload-time = "2026-02-17T22:19:41.157Z" }, - { url = "https://files.pythonhosted.org/packages/55/77/6ea82043db22cb0f2bbfe7198da3544000ddaadb12d26be36e19b03a2dc5/pandas-3.0.1-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c1a9f55e0f46951874b863d1f3906dcb57df2d9be5c5847ba4dfb55b2c815249", size = 10893940, upload-time = "2026-02-17T22:19:43.493Z" }, - { url = "https://files.pythonhosted.org/packages/03/30/f1b502a72468c89412c1b882a08f6eed8a4ee9dc033f35f65d0663df6081/pandas-3.0.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:1849f0bba9c8a2fb0f691d492b834cc8dadf617e29015c66e989448d58d011ee", size = 11442711, upload-time = "2026-02-17T22:19:46.074Z" }, - { url = "https://files.pythonhosted.org/packages/0d/f0/ebb6ddd8fc049e98cabac5c2924d14d1dda26a20adb70d41ea2e428d3ec4/pandas-3.0.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:c3d288439e11b5325b02ae6e9cc83e6805a62c40c5a6220bea9beb899c073b1c", size = 11963918, upload-time = "2026-02-17T22:19:48.838Z" }, - { url = "https://files.pythonhosted.org/packages/09/f8/8ce132104074f977f907442790eaae24e27bce3b3b454e82faa3237ff098/pandas-3.0.1-cp314-cp314-win_amd64.whl", hash = "sha256:93325b0fe372d192965f4cca88d97667f49557398bbf94abdda3bf1b591dbe66", size = 9862099, upload-time = "2026-02-17T22:19:51.081Z" }, - { url = "https://files.pythonhosted.org/packages/e6/b7/6af9aac41ef2456b768ef0ae60acf8abcebb450a52043d030a65b4b7c9bd/pandas-3.0.1-cp314-cp314-win_arm64.whl", hash = "sha256:97ca08674e3287c7148f4858b01136f8bdfe7202ad25ad04fec602dd1d29d132", size = 9185333, upload-time = "2026-02-17T22:19:53.266Z" }, - { url = "https://files.pythonhosted.org/packages/66/fc/848bb6710bc6061cb0c5badd65b92ff75c81302e0e31e496d00029fe4953/pandas-3.0.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:58eeb1b2e0fb322befcf2bbc9ba0af41e616abadb3d3414a6bc7167f6cbfce32", size = 10772664, upload-time = "2026-02-17T22:19:55.806Z" }, - { url = "https://files.pythonhosted.org/packages/69/5c/866a9bbd0f79263b4b0db6ec1a341be13a1473323f05c122388e0f15b21d/pandas-3.0.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:cd9af1276b5ca9e298bd79a26bda32fa9cc87ed095b2a9a60978d2ca058eaf87", size = 10421286, upload-time = "2026-02-17T22:19:58.091Z" }, - { url = "https://files.pythonhosted.org/packages/51/a4/2058fb84fb1cfbfb2d4a6d485e1940bb4ad5716e539d779852494479c580/pandas-3.0.1-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:94f87a04984d6b63788327cd9f79dda62b7f9043909d2440ceccf709249ca988", size = 10342050, upload-time = "2026-02-17T22:20:01.376Z" }, - { url = "https://files.pythonhosted.org/packages/22/1b/674e89996cc4be74db3c4eb09240c4bb549865c9c3f5d9b086ff8fcfbf00/pandas-3.0.1-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:85fe4c4df62e1e20f9db6ebfb88c844b092c22cd5324bdcf94bfa2fc1b391221", size = 10740055, upload-time = "2026-02-17T22:20:04.328Z" }, - { url = "https://files.pythonhosted.org/packages/d0/f8/e954b750764298c22fa4614376531fe63c521ef517e7059a51f062b87dca/pandas-3.0.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:331ca75a2f8672c365ae25c0b29e46f5ac0c6551fdace8eec4cd65e4fac271ff", size = 11357632, upload-time = "2026-02-17T22:20:06.647Z" }, - { url = "https://files.pythonhosted.org/packages/6d/02/c6e04b694ffd68568297abd03588b6d30295265176a5c01b7459d3bc35a3/pandas-3.0.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:15860b1fdb1973fffade772fdb931ccf9b2f400a3f5665aef94a00445d7d8dd5", size = 11810974, upload-time = "2026-02-17T22:20:08.946Z" }, - { url = "https://files.pythonhosted.org/packages/89/41/d7dfb63d2407f12055215070c42fc6ac41b66e90a2946cdc5e759058398b/pandas-3.0.1-cp314-cp314t-win_amd64.whl", hash = "sha256:44f1364411d5670efa692b146c748f4ed013df91ee91e9bec5677fb1fd58b937", size = 10884622, upload-time = "2026-02-17T22:20:11.711Z" }, - { url = "https://files.pythonhosted.org/packages/68/b0/34937815889fa982613775e4b97fddd13250f11012d769949c5465af2150/pandas-3.0.1-cp314-cp314t-win_arm64.whl", hash = "sha256:108dd1790337a494aa80e38def654ca3f0968cf4f362c85f44c15e471667102d", size = 9452085, upload-time = "2026-02-17T22:20:14.331Z" }, +wheels = [ + {url = "https://files.pythonhosted.org/packages/ff/07/c7087e003ceee9b9a82539b40414ec557aa795b584a1a346e89180853d79/pandas-3.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:de09668c1bf3b925c07e5762291602f0d789eca1b3a781f99c1c78f6cac0e7ea", size = 10323380, upload-time = "2026-02-17T22:18:16.133Z"}, + {url = "https://files.pythonhosted.org/packages/c1/27/90683c7122febeefe84a56f2cde86a9f05f68d53885cebcc473298dfc33e/pandas-3.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:24ba315ba3d6e5806063ac6eb717504e499ce30bd8c236d8693a5fd3f084c796", size = 9923455, upload-time = "2026-02-17T22:18:19.13Z"}, + {url = "https://files.pythonhosted.org/packages/0e/f1/ed17d927f9950643bc7631aa4c99ff0cc83a37864470bc419345b656a41f/pandas-3.0.1-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:406ce835c55bac912f2a0dcfaf27c06d73c6b04a5dde45f1fd3169ce31337389", size = 10753464, upload-time = "2026-02-17T22:18:21.134Z"}, + {url = "https://files.pythonhosted.org/packages/2e/7c/870c7e7daec2a6c7ff2ac9e33b23317230d4e4e954b35112759ea4a924a7/pandas-3.0.1-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:830994d7e1f31dd7e790045235605ab61cff6c94defc774547e8b7fdfbff3dc7", size = 11255234, upload-time = "2026-02-17T22:18:24.175Z"}, + {url = "https://files.pythonhosted.org/packages/5c/39/3653fe59af68606282b989c23d1a543ceba6e8099cbcc5f1d506a7bae2aa/pandas-3.0.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a64ce8b0f2de1d2efd2ae40b0abe7f8ae6b29fbfb3812098ed5a6f8e235ad9bf", size = 11767299, upload-time = "2026-02-17T22:18:26.824Z"}, + {url = "https://files.pythonhosted.org/packages/9b/31/1daf3c0c94a849c7a8dab8a69697b36d313b229918002ba3e409265c7888/pandas-3.0.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9832c2c69da24b602c32e0c7b1b508a03949c18ba08d4d9f1c1033426685b447", size = 12333292, upload-time = "2026-02-17T22:18:28.996Z"}, + {url = "https://files.pythonhosted.org/packages/1f/67/af63f83cd6ca603a00fe8530c10a60f0879265b8be00b5930e8e78c5b30b/pandas-3.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:84f0904a69e7365f79a0c77d3cdfccbfb05bf87847e3a51a41e1426b0edb9c79", size = 9892176, upload-time = "2026-02-17T22:18:31.79Z"}, + {url = "https://files.pythonhosted.org/packages/79/ab/9c776b14ac4b7b4140788eca18468ea39894bc7340a408f1d1e379856a6b/pandas-3.0.1-cp311-cp311-win_arm64.whl", hash = "sha256:4a68773d5a778afb31d12e34f7dd4612ab90de8c6fb1d8ffe5d4a03b955082a1", size = 9151328, upload-time = "2026-02-17T22:18:35.721Z"}, + {url = "https://files.pythonhosted.org/packages/37/51/b467209c08dae2c624873d7491ea47d2b47336e5403309d433ea79c38571/pandas-3.0.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:476f84f8c20c9f5bc47252b66b4bb25e1a9fc2fa98cead96744d8116cb85771d", size = 10344357, upload-time = "2026-02-17T22:18:38.262Z"}, + {url = "https://files.pythonhosted.org/packages/7c/f1/e2567ffc8951ab371db2e40b2fe068e36b81d8cf3260f06ae508700e5504/pandas-3.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0ab749dfba921edf641d4036c4c21c0b3ea70fea478165cb98a998fb2a261955", size = 9884543, upload-time = "2026-02-17T22:18:41.476Z"}, + {url = "https://files.pythonhosted.org/packages/d7/39/327802e0b6d693182403c144edacbc27eb82907b57062f23ef5a4c4a5ea7/pandas-3.0.1-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b8e36891080b87823aff3640c78649b91b8ff6eea3c0d70aeabd72ea43ab069b", size = 10396030, upload-time = "2026-02-17T22:18:43.822Z"}, + {url = "https://files.pythonhosted.org/packages/3d/fe/89d77e424365280b79d99b3e1e7d606f5165af2f2ecfaf0c6d24c799d607/pandas-3.0.1-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:532527a701281b9dd371e2f582ed9094f4c12dd9ffb82c0c54ee28d8ac9520c4", size = 10876435, upload-time = "2026-02-17T22:18:45.954Z"}, + {url = "https://files.pythonhosted.org/packages/b5/a6/2a75320849dd154a793f69c951db759aedb8d1dd3939eeacda9bdcfa1629/pandas-3.0.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:356e5c055ed9b0da1580d465657bc7d00635af4fd47f30afb23025352ba764d1", size = 11405133, upload-time = "2026-02-17T22:18:48.533Z"}, + {url = "https://files.pythonhosted.org/packages/58/53/1d68fafb2e02d7881df66aa53be4cd748d25cbe311f3b3c85c93ea5d30ca/pandas-3.0.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:9d810036895f9ad6345b8f2a338dd6998a74e8483847403582cab67745bff821", size = 11932065, upload-time = "2026-02-17T22:18:50.837Z"}, + {url = "https://files.pythonhosted.org/packages/75/08/67cc404b3a966b6df27b38370ddd96b3b023030b572283d035181854aac5/pandas-3.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:536232a5fe26dd989bd633e7a0c450705fdc86a207fec7254a55e9a22950fe43", size = 9741627, upload-time = "2026-02-17T22:18:53.905Z"}, + {url = "https://files.pythonhosted.org/packages/86/4f/caf9952948fb00d23795f09b893d11f1cacb384e666854d87249530f7cbe/pandas-3.0.1-cp312-cp312-win_arm64.whl", hash = "sha256:0f463ebfd8de7f326d38037c7363c6dacb857c5881ab8961fb387804d6daf2f7", size = 9052483, upload-time = "2026-02-17T22:18:57.31Z"}, + {url = "https://files.pythonhosted.org/packages/0b/48/aad6ec4f8d007534c091e9a7172b3ec1b1ee6d99a9cbb936b5eab6c6cf58/pandas-3.0.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5272627187b5d9c20e55d27caf5f2cd23e286aba25cadf73c8590e432e2b7262", size = 10317509, upload-time = "2026-02-17T22:18:59.498Z"}, + {url = "https://files.pythonhosted.org/packages/a8/14/5990826f779f79148ae9d3a2c39593dc04d61d5d90541e71b5749f35af95/pandas-3.0.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:661e0f665932af88c7877f31da0dc743fe9c8f2524bdffe23d24fdcb67ef9d56", size = 9860561, upload-time = "2026-02-17T22:19:02.265Z"}, + {url = "https://files.pythonhosted.org/packages/fa/80/f01ff54664b6d70fed71475543d108a9b7c888e923ad210795bef04ffb7d/pandas-3.0.1-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:75e6e292ff898679e47a2199172593d9f6107fd2dd3617c22c2946e97d5df46e", size = 10365506, upload-time = "2026-02-17T22:19:05.017Z"}, + {url = "https://files.pythonhosted.org/packages/f2/85/ab6d04733a7d6ff32bfc8382bf1b07078228f5d6ebec5266b91bfc5c4ff7/pandas-3.0.1-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1ff8cf1d2896e34343197685f432450ec99a85ba8d90cce2030c5eee2ef98791", size = 10873196, upload-time = "2026-02-17T22:19:07.204Z"}, + {url = "https://files.pythonhosted.org/packages/48/a9/9301c83d0b47c23ac5deab91c6b39fd98d5b5db4d93b25df8d381451828f/pandas-3.0.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:eca8b4510f6763f3d37359c2105df03a7a221a508f30e396a51d0713d462e68a", size = 11370859, upload-time = "2026-02-17T22:19:09.436Z"}, + {url = "https://files.pythonhosted.org/packages/59/fe/0c1fc5bd2d29c7db2ab372330063ad555fb83e08422829c785f5ec2176ca/pandas-3.0.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:06aff2ad6f0b94a17822cf8b83bbb563b090ed82ff4fe7712db2ce57cd50d9b8", size = 11924584, upload-time = "2026-02-17T22:19:11.562Z"}, + {url = "https://files.pythonhosted.org/packages/d6/7d/216a1588b65a7aa5f4535570418a599d943c85afb1d95b0876fc00aa1468/pandas-3.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:9fea306c783e28884c29057a1d9baa11a349bbf99538ec1da44c8476563d1b25", size = 9742769, upload-time = "2026-02-17T22:19:13.926Z"}, + {url = "https://files.pythonhosted.org/packages/c4/cb/810a22a6af9a4e97c8ab1c946b47f3489c5bca5adc483ce0ffc84c9cc768/pandas-3.0.1-cp313-cp313-win_arm64.whl", hash = "sha256:a8d37a43c52917427e897cb2e429f67a449327394396a81034a4449b99afda59", size = 9043855, upload-time = "2026-02-17T22:19:16.09Z"}, + {url = "https://files.pythonhosted.org/packages/92/fa/423c89086cca1f039cf1253c3ff5b90f157b5b3757314aa635f6bf3e30aa/pandas-3.0.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:d54855f04f8246ed7b6fc96b05d4871591143c46c0b6f4af874764ed0d2d6f06", size = 10752673, upload-time = "2026-02-17T22:19:18.304Z"}, + {url = "https://files.pythonhosted.org/packages/22/23/b5a08ec1f40020397f0faba72f1e2c11f7596a6169c7b3e800abff0e433f/pandas-3.0.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:4e1b677accee34a09e0dc2ce5624e4a58a1870ffe56fc021e9caf7f23cd7668f", size = 10404967, upload-time = "2026-02-17T22:19:20.726Z"}, + {url = "https://files.pythonhosted.org/packages/5c/81/94841f1bb4afdc2b52a99daa895ac2c61600bb72e26525ecc9543d453ebc/pandas-3.0.1-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a9cabbdcd03f1b6cd254d6dda8ae09b0252524be1592594c00b7895916cb1324", size = 10320575, upload-time = "2026-02-17T22:19:24.919Z"}, + {url = "https://files.pythonhosted.org/packages/0a/8b/2ae37d66a5342a83adadfd0cb0b4bf9c3c7925424dd5f40d15d6cfaa35ee/pandas-3.0.1-cp313-cp313t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5ae2ab1f166668b41e770650101e7090824fd34d17915dd9cd479f5c5e0065e9", size = 10710921, upload-time = "2026-02-17T22:19:27.181Z"}, + {url = "https://files.pythonhosted.org/packages/a2/61/772b2e2757855e232b7ccf7cb8079a5711becb3a97f291c953def15a833f/pandas-3.0.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6bf0603c2e30e2cafac32807b06435f28741135cb8697eae8b28c7d492fc7d76", size = 11334191, upload-time = "2026-02-17T22:19:29.411Z"}, + {url = "https://files.pythonhosted.org/packages/1b/08/b16c6df3ef555d8495d1d265a7963b65be166785d28f06a350913a4fac78/pandas-3.0.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6c426422973973cae1f4a23e51d4ae85974f44871b24844e4f7de752dd877098", size = 11782256, upload-time = "2026-02-17T22:19:32.34Z"}, + {url = "https://files.pythonhosted.org/packages/55/80/178af0594890dee17e239fca96d3d8670ba0f5ff59b7d0439850924a9c09/pandas-3.0.1-cp313-cp313t-win_amd64.whl", hash = "sha256:b03f91ae8c10a85c1613102c7bef5229b5379f343030a3ccefeca8a33414cf35", size = 10485047, upload-time = "2026-02-17T22:19:34.605Z"}, + {url = "https://files.pythonhosted.org/packages/bb/8b/4bb774a998b97e6c2fd62a9e6cfdaae133b636fd1c468f92afb4ae9a447a/pandas-3.0.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:99d0f92ed92d3083d140bf6b97774f9f13863924cf3f52a70711f4e7588f9d0a", size = 10322465, upload-time = "2026-02-17T22:19:36.803Z"}, + {url = "https://files.pythonhosted.org/packages/72/3a/5b39b51c64159f470f1ca3b1c2a87da290657ca022f7cd11442606f607d1/pandas-3.0.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:3b66857e983208654294bb6477b8a63dee26b37bdd0eb34d010556e91261784f", size = 9910632, upload-time = "2026-02-17T22:19:39.001Z"}, + {url = "https://files.pythonhosted.org/packages/4e/f7/b449ffb3f68c11da12fc06fbf6d2fa3a41c41e17d0284d23a79e1c13a7e4/pandas-3.0.1-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:56cf59638bf24dc9bdf2154c81e248b3289f9a09a6d04e63608c159022352749", size = 10440535, upload-time = "2026-02-17T22:19:41.157Z"}, + {url = "https://files.pythonhosted.org/packages/55/77/6ea82043db22cb0f2bbfe7198da3544000ddaadb12d26be36e19b03a2dc5/pandas-3.0.1-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c1a9f55e0f46951874b863d1f3906dcb57df2d9be5c5847ba4dfb55b2c815249", size = 10893940, upload-time = "2026-02-17T22:19:43.493Z"}, + {url = "https://files.pythonhosted.org/packages/03/30/f1b502a72468c89412c1b882a08f6eed8a4ee9dc033f35f65d0663df6081/pandas-3.0.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:1849f0bba9c8a2fb0f691d492b834cc8dadf617e29015c66e989448d58d011ee", size = 11442711, upload-time = "2026-02-17T22:19:46.074Z"}, + {url = "https://files.pythonhosted.org/packages/0d/f0/ebb6ddd8fc049e98cabac5c2924d14d1dda26a20adb70d41ea2e428d3ec4/pandas-3.0.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:c3d288439e11b5325b02ae6e9cc83e6805a62c40c5a6220bea9beb899c073b1c", size = 11963918, upload-time = "2026-02-17T22:19:48.838Z"}, + {url = "https://files.pythonhosted.org/packages/09/f8/8ce132104074f977f907442790eaae24e27bce3b3b454e82faa3237ff098/pandas-3.0.1-cp314-cp314-win_amd64.whl", hash = "sha256:93325b0fe372d192965f4cca88d97667f49557398bbf94abdda3bf1b591dbe66", size = 9862099, upload-time = "2026-02-17T22:19:51.081Z"}, + {url = "https://files.pythonhosted.org/packages/e6/b7/6af9aac41ef2456b768ef0ae60acf8abcebb450a52043d030a65b4b7c9bd/pandas-3.0.1-cp314-cp314-win_arm64.whl", hash = "sha256:97ca08674e3287c7148f4858b01136f8bdfe7202ad25ad04fec602dd1d29d132", size = 9185333, upload-time = "2026-02-17T22:19:53.266Z"}, + {url = "https://files.pythonhosted.org/packages/66/fc/848bb6710bc6061cb0c5badd65b92ff75c81302e0e31e496d00029fe4953/pandas-3.0.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:58eeb1b2e0fb322befcf2bbc9ba0af41e616abadb3d3414a6bc7167f6cbfce32", size = 10772664, upload-time = "2026-02-17T22:19:55.806Z"}, + {url = "https://files.pythonhosted.org/packages/69/5c/866a9bbd0f79263b4b0db6ec1a341be13a1473323f05c122388e0f15b21d/pandas-3.0.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:cd9af1276b5ca9e298bd79a26bda32fa9cc87ed095b2a9a60978d2ca058eaf87", size = 10421286, upload-time = "2026-02-17T22:19:58.091Z"}, + {url = "https://files.pythonhosted.org/packages/51/a4/2058fb84fb1cfbfb2d4a6d485e1940bb4ad5716e539d779852494479c580/pandas-3.0.1-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:94f87a04984d6b63788327cd9f79dda62b7f9043909d2440ceccf709249ca988", size = 10342050, upload-time = "2026-02-17T22:20:01.376Z"}, + {url = "https://files.pythonhosted.org/packages/22/1b/674e89996cc4be74db3c4eb09240c4bb549865c9c3f5d9b086ff8fcfbf00/pandas-3.0.1-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:85fe4c4df62e1e20f9db6ebfb88c844b092c22cd5324bdcf94bfa2fc1b391221", size = 10740055, upload-time = "2026-02-17T22:20:04.328Z"}, + {url = "https://files.pythonhosted.org/packages/d0/f8/e954b750764298c22fa4614376531fe63c521ef517e7059a51f062b87dca/pandas-3.0.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:331ca75a2f8672c365ae25c0b29e46f5ac0c6551fdace8eec4cd65e4fac271ff", size = 11357632, upload-time = "2026-02-17T22:20:06.647Z"}, + {url = "https://files.pythonhosted.org/packages/6d/02/c6e04b694ffd68568297abd03588b6d30295265176a5c01b7459d3bc35a3/pandas-3.0.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:15860b1fdb1973fffade772fdb931ccf9b2f400a3f5665aef94a00445d7d8dd5", size = 11810974, upload-time = "2026-02-17T22:20:08.946Z"}, + {url = "https://files.pythonhosted.org/packages/89/41/d7dfb63d2407f12055215070c42fc6ac41b66e90a2946cdc5e759058398b/pandas-3.0.1-cp314-cp314t-win_amd64.whl", hash = "sha256:44f1364411d5670efa692b146c748f4ed013df91ee91e9bec5677fb1fd58b937", size = 10884622, upload-time = "2026-02-17T22:20:11.711Z"}, + {url = "https://files.pythonhosted.org/packages/68/b0/34937815889fa982613775e4b97fddd13250f11012d769949c5465af2150/pandas-3.0.1-cp314-cp314t-win_arm64.whl", hash = "sha256:108dd1790337a494aa80e38def654ca3f0968cf4f362c85f44c15e471667102d", size = 9452085, upload-time = "2026-02-17T22:20:14.331Z"} ] [[package]] name = "parso" +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"} +source = {registry = "https://pypi.org/simple"} 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" }, + {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 = "partd" -version = "1.4.2" -source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "locket" }, - { name = "toolz" }, + {name = "locket"}, + {name = "toolz"} ] -sdist = { url = "https://files.pythonhosted.org/packages/b2/3a/3f06f34820a31257ddcabdfafc2672c5816be79c7e353b02c1f318daa7d4/partd-1.4.2.tar.gz", hash = "sha256:d022c33afbdc8405c226621b015e8067888173d85f7f5ecebb3cafed9a20f02c", size = 21029, upload-time = "2024-05-06T19:51:41.945Z" } +name = "partd" +sdist = {url = "https://files.pythonhosted.org/packages/b2/3a/3f06f34820a31257ddcabdfafc2672c5816be79c7e353b02c1f318daa7d4/partd-1.4.2.tar.gz", hash = "sha256:d022c33afbdc8405c226621b015e8067888173d85f7f5ecebb3cafed9a20f02c", size = 21029, upload-time = "2024-05-06T19:51:41.945Z"} +source = {registry = "https://pypi.org/simple"} +version = "1.4.2" wheels = [ - { url = "https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-py3-none-any.whl", hash = "sha256:978e4ac767ec4ba5b86c6eaa52e5a2a3bc748a2ca839e8cc798f1cc6ce6efb0f", size = 18905, upload-time = "2024-05-06T19:51:39.271Z" }, + {url = "https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-py3-none-any.whl", hash = "sha256:978e4ac767ec4ba5b86c6eaa52e5a2a3bc748a2ca839e8cc798f1cc6ce6efb0f", size = 18905, upload-time = "2024-05-06T19:51:39.271Z"} ] [[package]] -name = "pdbufr" -version = "0.14.1" -source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "attrs" }, - { name = "eccodes" }, - { name = "pandas" }, - { name = "pint" }, + {name = "attrs"}, + {name = "eccodes"}, + {name = "pandas"}, + {name = "pint"} ] -sdist = { url = "https://files.pythonhosted.org/packages/88/b6/3018e711d1c79140ee80f755adff825cf35a5689b857713e1fd15a26f64d/pdbufr-0.14.1.tar.gz", hash = "sha256:e7d0c4a7da1bafa59dc9c5f69e260f4932293acfcfee3a707f8aabc9acbc3b34", size = 8761618, upload-time = "2025-12-16T15:20:17.883Z" } +name = "pdbufr" +sdist = {url = "https://files.pythonhosted.org/packages/88/b6/3018e711d1c79140ee80f755adff825cf35a5689b857713e1fd15a26f64d/pdbufr-0.14.1.tar.gz", hash = "sha256:e7d0c4a7da1bafa59dc9c5f69e260f4932293acfcfee3a707f8aabc9acbc3b34", size = 8761618, upload-time = "2025-12-16T15:20:17.883Z"} +source = {registry = "https://pypi.org/simple"} +version = "0.14.1" wheels = [ - { url = "https://files.pythonhosted.org/packages/95/02/ec4aa5da22b8856bb66433b568f3201347b1dd4df35d92377b93d0367371/pdbufr-0.14.1-py3-none-any.whl", hash = "sha256:b22aa0125e7e626751d6050b739ac952957fe46f57bc966416ce9ce97eab911c", size = 52642, upload-time = "2025-12-16T15:20:16.628Z" }, + {url = "https://files.pythonhosted.org/packages/95/02/ec4aa5da22b8856bb66433b568f3201347b1dd4df35d92377b93d0367371/pdbufr-0.14.1-py3-none-any.whl", hash = "sha256:b22aa0125e7e626751d6050b739ac952957fe46f57bc966416ce9ce97eab911c", size = 52642, upload-time = "2025-12-16T15:20:16.628Z"} ] [[package]] -name = "pexpect" -version = "4.9.0" -source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "ptyprocess", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" }, + {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" } +name = "pexpect" +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"} +source = {registry = "https://pypi.org/simple"} +version = "4.9.0" 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" }, + {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" +sdist = {url = "https://files.pythonhosted.org/packages/1f/42/5c74462b4fd957fcd7b13b04fb3205ff8349236ea74c7c375766d6c82288/pillow-12.1.1.tar.gz", hash = "sha256:9ad8fa5937ab05218e2b6a4cff30295ad35afd2f83ac592e68c0d871bb0fdbc4", size = 46980264, upload-time = "2026-02-11T04:23:07.146Z"} +source = {registry = "https://pypi.org/simple"} version = "12.1.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/1f/42/5c74462b4fd957fcd7b13b04fb3205ff8349236ea74c7c375766d6c82288/pillow-12.1.1.tar.gz", hash = "sha256:9ad8fa5937ab05218e2b6a4cff30295ad35afd2f83ac592e68c0d871bb0fdbc4", size = 46980264, upload-time = "2026-02-11T04:23:07.146Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/2b/46/5da1ec4a5171ee7bf1a0efa064aba70ba3d6e0788ce3f5acd1375d23c8c0/pillow-12.1.1-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:e879bb6cd5c73848ef3b2b48b8af9ff08c5b71ecda8048b7dd22d8a33f60be32", size = 5304084, upload-time = "2026-02-11T04:20:27.501Z" }, - { url = "https://files.pythonhosted.org/packages/78/93/a29e9bc02d1cf557a834da780ceccd54e02421627200696fcf805ebdc3fb/pillow-12.1.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:365b10bb9417dd4498c0e3b128018c4a624dc11c7b97d8cc54effe3b096f4c38", size = 4657866, upload-time = "2026-02-11T04:20:29.827Z" }, - { url = "https://files.pythonhosted.org/packages/13/84/583a4558d492a179d31e4aae32eadce94b9acf49c0337c4ce0b70e0a01f2/pillow-12.1.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d4ce8e329c93845720cd2014659ca67eac35f6433fd3050393d85f3ecef0dad5", size = 6232148, upload-time = "2026-02-11T04:20:31.329Z" }, - { url = "https://files.pythonhosted.org/packages/d5/e2/53c43334bbbb2d3b938978532fbda8e62bb6e0b23a26ce8592f36bcc4987/pillow-12.1.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fc354a04072b765eccf2204f588a7a532c9511e8b9c7f900e1b64e3e33487090", size = 8038007, upload-time = "2026-02-11T04:20:34.225Z" }, - { url = "https://files.pythonhosted.org/packages/b8/a6/3d0e79c8a9d58150dd98e199d7c1c56861027f3829a3a60b3c2784190180/pillow-12.1.1-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7e7976bf1910a8116b523b9f9f58bf410f3e8aa330cd9a2bb2953f9266ab49af", size = 6345418, upload-time = "2026-02-11T04:20:35.858Z" }, - { url = "https://files.pythonhosted.org/packages/a2/c8/46dfeac5825e600579157eea177be43e2f7ff4a99da9d0d0a49533509ac5/pillow-12.1.1-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:597bd9c8419bc7c6af5604e55847789b69123bbe25d65cc6ad3012b4f3c98d8b", size = 7034590, upload-time = "2026-02-11T04:20:37.91Z" }, - { url = "https://files.pythonhosted.org/packages/af/bf/e6f65d3db8a8bbfeaf9e13cc0417813f6319863a73de934f14b2229ada18/pillow-12.1.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2c1fc0f2ca5f96a3c8407e41cca26a16e46b21060fe6d5b099d2cb01412222f5", size = 6458655, upload-time = "2026-02-11T04:20:39.496Z" }, - { url = "https://files.pythonhosted.org/packages/f9/c2/66091f3f34a25894ca129362e510b956ef26f8fb67a0e6417bc5744e56f1/pillow-12.1.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:578510d88c6229d735855e1f278aa305270438d36a05031dfaae5067cc8eb04d", size = 7159286, upload-time = "2026-02-11T04:20:41.139Z" }, - { url = "https://files.pythonhosted.org/packages/7b/5a/24bc8eb526a22f957d0cec6243146744966d40857e3d8deb68f7902ca6c1/pillow-12.1.1-cp311-cp311-win32.whl", hash = "sha256:7311c0a0dcadb89b36b7025dfd8326ecfa36964e29913074d47382706e516a7c", size = 6328663, upload-time = "2026-02-11T04:20:43.184Z" }, - { url = "https://files.pythonhosted.org/packages/31/03/bef822e4f2d8f9d7448c133d0a18185d3cce3e70472774fffefe8b0ed562/pillow-12.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:fbfa2a7c10cc2623f412753cddf391c7f971c52ca40a3f65dc5039b2939e8563", size = 7031448, upload-time = "2026-02-11T04:20:44.696Z" }, - { url = "https://files.pythonhosted.org/packages/49/70/f76296f53610bd17b2e7d31728b8b7825e3ac3b5b3688b51f52eab7c0818/pillow-12.1.1-cp311-cp311-win_arm64.whl", hash = "sha256:b81b5e3511211631b3f672a595e3221252c90af017e399056d0faabb9538aa80", size = 2453651, upload-time = "2026-02-11T04:20:46.243Z" }, - { url = "https://files.pythonhosted.org/packages/07/d3/8df65da0d4df36b094351dce696f2989bec731d4f10e743b1c5f4da4d3bf/pillow-12.1.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ab323b787d6e18b3d91a72fc99b1a2c28651e4358749842b8f8dfacd28ef2052", size = 5262803, upload-time = "2026-02-11T04:20:47.653Z" }, - { url = "https://files.pythonhosted.org/packages/d6/71/5026395b290ff404b836e636f51d7297e6c83beceaa87c592718747e670f/pillow-12.1.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:adebb5bee0f0af4909c30db0d890c773d1a92ffe83da908e2e9e720f8edf3984", size = 4657601, upload-time = "2026-02-11T04:20:49.328Z" }, - { url = "https://files.pythonhosted.org/packages/b1/2e/1001613d941c67442f745aff0f7cc66dd8df9a9c084eb497e6a543ee6f7e/pillow-12.1.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:bb66b7cc26f50977108790e2456b7921e773f23db5630261102233eb355a3b79", size = 6234995, upload-time = "2026-02-11T04:20:51.032Z" }, - { url = "https://files.pythonhosted.org/packages/07/26/246ab11455b2549b9233dbd44d358d033a2f780fa9007b61a913c5b2d24e/pillow-12.1.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:aee2810642b2898bb187ced9b349e95d2a7272930796e022efaf12e99dccd293", size = 8045012, upload-time = "2026-02-11T04:20:52.882Z" }, - { url = "https://files.pythonhosted.org/packages/b2/8b/07587069c27be7535ac1fe33874e32de118fbd34e2a73b7f83436a88368c/pillow-12.1.1-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a0b1cd6232e2b618adcc54d9882e4e662a089d5768cd188f7c245b4c8c44a397", size = 6349638, upload-time = "2026-02-11T04:20:54.444Z" }, - { url = "https://files.pythonhosted.org/packages/ff/79/6df7b2ee763d619cda2fb4fea498e5f79d984dae304d45a8999b80d6cf5c/pillow-12.1.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7aac39bcf8d4770d089588a2e1dd111cbaa42df5a94be3114222057d68336bd0", size = 7041540, upload-time = "2026-02-11T04:20:55.97Z" }, - { url = "https://files.pythonhosted.org/packages/2c/5e/2ba19e7e7236d7529f4d873bdaf317a318896bac289abebd4bb00ef247f0/pillow-12.1.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ab174cd7d29a62dd139c44bf74b698039328f45cb03b4596c43473a46656b2f3", size = 6462613, upload-time = "2026-02-11T04:20:57.542Z" }, - { url = "https://files.pythonhosted.org/packages/03/03/31216ec124bb5c3dacd74ce8efff4cc7f52643653bad4825f8f08c697743/pillow-12.1.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:339ffdcb7cbeaa08221cd401d517d4b1fe7a9ed5d400e4a8039719238620ca35", size = 7166745, upload-time = "2026-02-11T04:20:59.196Z" }, - { url = "https://files.pythonhosted.org/packages/1f/e7/7c4552d80052337eb28653b617eafdef39adfb137c49dd7e831b8dc13bc5/pillow-12.1.1-cp312-cp312-win32.whl", hash = "sha256:5d1f9575a12bed9e9eedd9a4972834b08c97a352bd17955ccdebfeca5913fa0a", size = 6328823, upload-time = "2026-02-11T04:21:01.385Z" }, - { url = "https://files.pythonhosted.org/packages/3d/17/688626d192d7261bbbf98846fc98995726bddc2c945344b65bec3a29d731/pillow-12.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:21329ec8c96c6e979cd0dfd29406c40c1d52521a90544463057d2aaa937d66a6", size = 7033367, upload-time = "2026-02-11T04:21:03.536Z" }, - { url = "https://files.pythonhosted.org/packages/ed/fe/a0ef1f73f939b0eca03ee2c108d0043a87468664770612602c63266a43c4/pillow-12.1.1-cp312-cp312-win_arm64.whl", hash = "sha256:af9a332e572978f0218686636610555ae3defd1633597be015ed50289a03c523", size = 2453811, upload-time = "2026-02-11T04:21:05.116Z" }, - { url = "https://files.pythonhosted.org/packages/d5/11/6db24d4bd7685583caeae54b7009584e38da3c3d4488ed4cd25b439de486/pillow-12.1.1-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:d242e8ac078781f1de88bf823d70c1a9b3c7950a44cdf4b7c012e22ccbcd8e4e", size = 4062689, upload-time = "2026-02-11T04:21:06.804Z" }, - { url = "https://files.pythonhosted.org/packages/33/c0/ce6d3b1fe190f0021203e0d9b5b99e57843e345f15f9ef22fcd43842fd21/pillow-12.1.1-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:02f84dfad02693676692746df05b89cf25597560db2857363a208e393429f5e9", size = 4138535, upload-time = "2026-02-11T04:21:08.452Z" }, - { url = "https://files.pythonhosted.org/packages/a0/c6/d5eb6a4fb32a3f9c21a8c7613ec706534ea1cf9f4b3663e99f0d83f6fca8/pillow-12.1.1-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:e65498daf4b583091ccbb2556c7000abf0f3349fcd57ef7adc9a84a394ed29f6", size = 3601364, upload-time = "2026-02-11T04:21:10.194Z" }, - { url = "https://files.pythonhosted.org/packages/14/a1/16c4b823838ba4c9c52c0e6bbda903a3fe5a1bdbf1b8eb4fff7156f3e318/pillow-12.1.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:6c6db3b84c87d48d0088943bf33440e0c42370b99b1c2a7989216f7b42eede60", size = 5262561, upload-time = "2026-02-11T04:21:11.742Z" }, - { url = "https://files.pythonhosted.org/packages/bb/ad/ad9dc98ff24f485008aa5cdedaf1a219876f6f6c42a4626c08bc4e80b120/pillow-12.1.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8b7e5304e34942bf62e15184219a7b5ad4ff7f3bb5cca4d984f37df1a0e1aee2", size = 4657460, upload-time = "2026-02-11T04:21:13.786Z" }, - { url = "https://files.pythonhosted.org/packages/9e/1b/f1a4ea9a895b5732152789326202a82464d5254759fbacae4deea3069334/pillow-12.1.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:18e5bddd742a44b7e6b1e773ab5db102bd7a94c32555ba656e76d319d19c3850", size = 6232698, upload-time = "2026-02-11T04:21:15.949Z" }, - { url = "https://files.pythonhosted.org/packages/95/f4/86f51b8745070daf21fd2e5b1fe0eb35d4db9ca26e6d58366562fb56a743/pillow-12.1.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fc44ef1f3de4f45b50ccf9136999d71abb99dca7706bc75d222ed350b9fd2289", size = 8041706, upload-time = "2026-02-11T04:21:17.723Z" }, - { url = "https://files.pythonhosted.org/packages/29/9b/d6ecd956bb1266dd1045e995cce9b8d77759e740953a1c9aad9502a0461e/pillow-12.1.1-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5a8eb7ed8d4198bccbd07058416eeec51686b498e784eda166395a23eb99138e", size = 6346621, upload-time = "2026-02-11T04:21:19.547Z" }, - { url = "https://files.pythonhosted.org/packages/71/24/538bff45bde96535d7d998c6fed1a751c75ac7c53c37c90dc2601b243893/pillow-12.1.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:47b94983da0c642de92ced1702c5b6c292a84bd3a8e1d1702ff923f183594717", size = 7038069, upload-time = "2026-02-11T04:21:21.378Z" }, - { url = "https://files.pythonhosted.org/packages/94/0e/58cb1a6bc48f746bc4cb3adb8cabff73e2742c92b3bf7a220b7cf69b9177/pillow-12.1.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:518a48c2aab7ce596d3bf79d0e275661b846e86e4d0e7dec34712c30fe07f02a", size = 6460040, upload-time = "2026-02-11T04:21:23.148Z" }, - { url = "https://files.pythonhosted.org/packages/6c/57/9045cb3ff11eeb6c1adce3b2d60d7d299d7b273a2e6c8381a524abfdc474/pillow-12.1.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a550ae29b95c6dc13cf69e2c9dc5747f814c54eeb2e32d683e5e93af56caa029", size = 7164523, upload-time = "2026-02-11T04:21:25.01Z" }, - { url = "https://files.pythonhosted.org/packages/73/f2/9be9cb99f2175f0d4dbadd6616ce1bf068ee54a28277ea1bf1fbf729c250/pillow-12.1.1-cp313-cp313-win32.whl", hash = "sha256:a003d7422449f6d1e3a34e3dd4110c22148336918ddbfc6a32581cd54b2e0b2b", size = 6332552, upload-time = "2026-02-11T04:21:27.238Z" }, - { url = "https://files.pythonhosted.org/packages/3f/eb/b0834ad8b583d7d9d42b80becff092082a1c3c156bb582590fcc973f1c7c/pillow-12.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:344cf1e3dab3be4b1fa08e449323d98a2a3f819ad20f4b22e77a0ede31f0faa1", size = 7040108, upload-time = "2026-02-11T04:21:29.462Z" }, - { url = "https://files.pythonhosted.org/packages/d5/7d/fc09634e2aabdd0feabaff4a32f4a7d97789223e7c2042fd805ea4b4d2c2/pillow-12.1.1-cp313-cp313-win_arm64.whl", hash = "sha256:5c0dd1636633e7e6a0afe7bf6a51a14992b7f8e60de5789018ebbdfae55b040a", size = 2453712, upload-time = "2026-02-11T04:21:31.072Z" }, - { url = "https://files.pythonhosted.org/packages/19/2a/b9d62794fc8a0dd14c1943df68347badbd5511103e0d04c035ffe5cf2255/pillow-12.1.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0330d233c1a0ead844fc097a7d16c0abff4c12e856c0b325f231820fee1f39da", size = 5264880, upload-time = "2026-02-11T04:21:32.865Z" }, - { url = "https://files.pythonhosted.org/packages/26/9d/e03d857d1347fa5ed9247e123fcd2a97b6220e15e9cb73ca0a8d91702c6e/pillow-12.1.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:5dae5f21afb91322f2ff791895ddd8889e5e947ff59f71b46041c8ce6db790bc", size = 4660616, upload-time = "2026-02-11T04:21:34.97Z" }, - { url = "https://files.pythonhosted.org/packages/f7/ec/8a6d22afd02570d30954e043f09c32772bfe143ba9285e2fdb11284952cd/pillow-12.1.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:2e0c664be47252947d870ac0d327fea7e63985a08794758aa8af5b6cb6ec0c9c", size = 6269008, upload-time = "2026-02-11T04:21:36.623Z" }, - { url = "https://files.pythonhosted.org/packages/3d/1d/6d875422c9f28a4a361f495a5f68d9de4a66941dc2c619103ca335fa6446/pillow-12.1.1-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:691ab2ac363b8217f7d31b3497108fb1f50faab2f75dfb03284ec2f217e87bf8", size = 8073226, upload-time = "2026-02-11T04:21:38.585Z" }, - { url = "https://files.pythonhosted.org/packages/a1/cd/134b0b6ee5eda6dc09e25e24b40fdafe11a520bc725c1d0bbaa5e00bf95b/pillow-12.1.1-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e9e8064fb1cc019296958595f6db671fba95209e3ceb0c4734c9baf97de04b20", size = 6380136, upload-time = "2026-02-11T04:21:40.562Z" }, - { url = "https://files.pythonhosted.org/packages/7a/a9/7628f013f18f001c1b98d8fffe3452f306a70dc6aba7d931019e0492f45e/pillow-12.1.1-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:472a8d7ded663e6162dafdf20015c486a7009483ca671cece7a9279b512fcb13", size = 7067129, upload-time = "2026-02-11T04:21:42.521Z" }, - { url = "https://files.pythonhosted.org/packages/1e/f8/66ab30a2193b277785601e82ee2d49f68ea575d9637e5e234faaa98efa4c/pillow-12.1.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:89b54027a766529136a06cfebeecb3a04900397a3590fd252160b888479517bf", size = 6491807, upload-time = "2026-02-11T04:21:44.22Z" }, - { url = "https://files.pythonhosted.org/packages/da/0b/a877a6627dc8318fdb84e357c5e1a758c0941ab1ddffdafd231983788579/pillow-12.1.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:86172b0831b82ce4f7877f280055892b31179e1576aa00d0df3bb1bbf8c3e524", size = 7190954, upload-time = "2026-02-11T04:21:46.114Z" }, - { url = "https://files.pythonhosted.org/packages/83/43/6f732ff85743cf746b1361b91665d9f5155e1483817f693f8d57ea93147f/pillow-12.1.1-cp313-cp313t-win32.whl", hash = "sha256:44ce27545b6efcf0fdbdceb31c9a5bdea9333e664cda58a7e674bb74608b3986", size = 6336441, upload-time = "2026-02-11T04:21:48.22Z" }, - { url = "https://files.pythonhosted.org/packages/3b/44/e865ef3986611bb75bfabdf94a590016ea327833f434558801122979cd0e/pillow-12.1.1-cp313-cp313t-win_amd64.whl", hash = "sha256:a285e3eb7a5a45a2ff504e31f4a8d1b12ef62e84e5411c6804a42197c1cf586c", size = 7045383, upload-time = "2026-02-11T04:21:50.015Z" }, - { url = "https://files.pythonhosted.org/packages/a8/c6/f4fb24268d0c6908b9f04143697ea18b0379490cb74ba9e8d41b898bd005/pillow-12.1.1-cp313-cp313t-win_arm64.whl", hash = "sha256:cc7d296b5ea4d29e6570dabeaed58d31c3fea35a633a69679fb03d7664f43fb3", size = 2456104, upload-time = "2026-02-11T04:21:51.633Z" }, - { url = "https://files.pythonhosted.org/packages/03/d0/bebb3ffbf31c5a8e97241476c4cf8b9828954693ce6744b4a2326af3e16b/pillow-12.1.1-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:417423db963cb4be8bac3fc1204fe61610f6abeed1580a7a2cbb2fbda20f12af", size = 4062652, upload-time = "2026-02-11T04:21:53.19Z" }, - { url = "https://files.pythonhosted.org/packages/2d/c0/0e16fb0addda4851445c28f8350d8c512f09de27bbb0d6d0bbf8b6709605/pillow-12.1.1-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:b957b71c6b2387610f556a7eb0828afbe40b4a98036fc0d2acfa5a44a0c2036f", size = 4138823, upload-time = "2026-02-11T04:22:03.088Z" }, - { url = "https://files.pythonhosted.org/packages/6b/fb/6170ec655d6f6bb6630a013dd7cf7bc218423d7b5fa9071bf63dc32175ae/pillow-12.1.1-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:097690ba1f2efdeb165a20469d59d8bb03c55fb6621eb2041a060ae8ea3e9642", size = 3601143, upload-time = "2026-02-11T04:22:04.909Z" }, - { url = "https://files.pythonhosted.org/packages/59/04/dc5c3f297510ba9a6837cbb318b87dd2b8f73eb41a43cc63767f65cb599c/pillow-12.1.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:2815a87ab27848db0321fb78c7f0b2c8649dee134b7f2b80c6a45c6831d75ccd", size = 5266254, upload-time = "2026-02-11T04:22:07.656Z" }, - { url = "https://files.pythonhosted.org/packages/05/30/5db1236b0d6313f03ebf97f5e17cda9ca060f524b2fcc875149a8360b21c/pillow-12.1.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:f7ed2c6543bad5a7d5530eb9e78c53132f93dfa44a28492db88b41cdab885202", size = 4657499, upload-time = "2026-02-11T04:22:09.613Z" }, - { url = "https://files.pythonhosted.org/packages/6f/18/008d2ca0eb612e81968e8be0bbae5051efba24d52debf930126d7eaacbba/pillow-12.1.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:652a2c9ccfb556235b2b501a3a7cf3742148cd22e04b5625c5fe057ea3e3191f", size = 6232137, upload-time = "2026-02-11T04:22:11.434Z" }, - { url = "https://files.pythonhosted.org/packages/70/f1/f14d5b8eeb4b2cd62b9f9f847eb6605f103df89ef619ac68f92f748614ea/pillow-12.1.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d6e4571eedf43af33d0fc233a382a76e849badbccdf1ac438841308652a08e1f", size = 8042721, upload-time = "2026-02-11T04:22:13.321Z" }, - { url = "https://files.pythonhosted.org/packages/5a/d6/17824509146e4babbdabf04d8171491fa9d776f7061ff6e727522df9bd03/pillow-12.1.1-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b574c51cf7d5d62e9be37ba446224b59a2da26dc4c1bb2ecbe936a4fb1a7cb7f", size = 6347798, upload-time = "2026-02-11T04:22:15.449Z" }, - { url = "https://files.pythonhosted.org/packages/d1/ee/c85a38a9ab92037a75615aba572c85ea51e605265036e00c5b67dfafbfe2/pillow-12.1.1-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a37691702ed687799de29a518d63d4682d9016932db66d4e90c345831b02fb4e", size = 7039315, upload-time = "2026-02-11T04:22:17.24Z" }, - { url = "https://files.pythonhosted.org/packages/ec/f3/bc8ccc6e08a148290d7523bde4d9a0d6c981db34631390dc6e6ec34cacf6/pillow-12.1.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:f95c00d5d6700b2b890479664a06e754974848afaae5e21beb4d83c106923fd0", size = 6462360, upload-time = "2026-02-11T04:22:19.111Z" }, - { url = "https://files.pythonhosted.org/packages/f6/ab/69a42656adb1d0665ab051eec58a41f169ad295cf81ad45406963105408f/pillow-12.1.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:559b38da23606e68681337ad74622c4dbba02254fc9cb4488a305dd5975c7eeb", size = 7165438, upload-time = "2026-02-11T04:22:21.041Z" }, - { url = "https://files.pythonhosted.org/packages/02/46/81f7aa8941873f0f01d4b55cc543b0a3d03ec2ee30d617a0448bf6bd6dec/pillow-12.1.1-cp314-cp314-win32.whl", hash = "sha256:03edcc34d688572014ff223c125a3f77fb08091e4607e7745002fc214070b35f", size = 6431503, upload-time = "2026-02-11T04:22:22.833Z" }, - { url = "https://files.pythonhosted.org/packages/40/72/4c245f7d1044b67affc7f134a09ea619d4895333d35322b775b928180044/pillow-12.1.1-cp314-cp314-win_amd64.whl", hash = "sha256:50480dcd74fa63b8e78235957d302d98d98d82ccbfac4c7e12108ba9ecbdba15", size = 7176748, upload-time = "2026-02-11T04:22:24.64Z" }, - { url = "https://files.pythonhosted.org/packages/e4/ad/8a87bdbe038c5c698736e3348af5c2194ffb872ea52f11894c95f9305435/pillow-12.1.1-cp314-cp314-win_arm64.whl", hash = "sha256:5cb1785d97b0c3d1d1a16bc1d710c4a0049daefc4935f3a8f31f827f4d3d2e7f", size = 2544314, upload-time = "2026-02-11T04:22:26.685Z" }, - { url = "https://files.pythonhosted.org/packages/6c/9d/efd18493f9de13b87ede7c47e69184b9e859e4427225ea962e32e56a49bc/pillow-12.1.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:1f90cff8aa76835cba5769f0b3121a22bd4eb9e6884cfe338216e557a9a548b8", size = 5268612, upload-time = "2026-02-11T04:22:29.884Z" }, - { url = "https://files.pythonhosted.org/packages/f8/f1/4f42eb2b388eb2ffc660dcb7f7b556c1015c53ebd5f7f754965ef997585b/pillow-12.1.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1f1be78ce9466a7ee64bfda57bdba0f7cc499d9794d518b854816c41bf0aa4e9", size = 4660567, upload-time = "2026-02-11T04:22:31.799Z" }, - { url = "https://files.pythonhosted.org/packages/01/54/df6ef130fa43e4b82e32624a7b821a2be1c5653a5fdad8469687a7db4e00/pillow-12.1.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:42fc1f4677106188ad9a55562bbade416f8b55456f522430fadab3cef7cd4e60", size = 6269951, upload-time = "2026-02-11T04:22:33.921Z" }, - { url = "https://files.pythonhosted.org/packages/a9/48/618752d06cc44bb4aae8ce0cd4e6426871929ed7b46215638088270d9b34/pillow-12.1.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:98edb152429ab62a1818039744d8fbb3ccab98a7c29fc3d5fcef158f3f1f68b7", size = 8074769, upload-time = "2026-02-11T04:22:35.877Z" }, - { url = "https://files.pythonhosted.org/packages/c3/bd/f1d71eb39a72fa088d938655afba3e00b38018d052752f435838961127d8/pillow-12.1.1-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d470ab1178551dd17fdba0fef463359c41aaa613cdcd7ff8373f54be629f9f8f", size = 6381358, upload-time = "2026-02-11T04:22:37.698Z" }, - { url = "https://files.pythonhosted.org/packages/64/ef/c784e20b96674ed36a5af839305f55616f8b4f8aa8eeccf8531a6e312243/pillow-12.1.1-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6408a7b064595afcab0a49393a413732a35788f2a5092fdc6266952ed67de586", size = 7068558, upload-time = "2026-02-11T04:22:39.597Z" }, - { url = "https://files.pythonhosted.org/packages/73/cb/8059688b74422ae61278202c4e1ad992e8a2e7375227be0a21c6b87ca8d5/pillow-12.1.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5d8c41325b382c07799a3682c1c258469ea2ff97103c53717b7893862d0c98ce", size = 6493028, upload-time = "2026-02-11T04:22:42.73Z" }, - { url = "https://files.pythonhosted.org/packages/c6/da/e3c008ed7d2dd1f905b15949325934510b9d1931e5df999bb15972756818/pillow-12.1.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:c7697918b5be27424e9ce568193efd13d925c4481dd364e43f5dff72d33e10f8", size = 7191940, upload-time = "2026-02-11T04:22:44.543Z" }, - { url = "https://files.pythonhosted.org/packages/01/4a/9202e8d11714c1fc5951f2e1ef362f2d7fbc595e1f6717971d5dd750e969/pillow-12.1.1-cp314-cp314t-win32.whl", hash = "sha256:d2912fd8114fc5545aa3a4b5576512f64c55a03f3ebcca4c10194d593d43ea36", size = 6438736, upload-time = "2026-02-11T04:22:46.347Z" }, - { url = "https://files.pythonhosted.org/packages/f3/ca/cbce2327eb9885476b3957b2e82eb12c866a8b16ad77392864ad601022ce/pillow-12.1.1-cp314-cp314t-win_amd64.whl", hash = "sha256:4ceb838d4bd9dab43e06c363cab2eebf63846d6a4aeaea283bbdfd8f1a8ed58b", size = 7182894, upload-time = "2026-02-11T04:22:48.114Z" }, - { url = "https://files.pythonhosted.org/packages/ec/d2/de599c95ba0a973b94410477f8bf0b6f0b5e67360eb89bcb1ad365258beb/pillow-12.1.1-cp314-cp314t-win_arm64.whl", hash = "sha256:7b03048319bfc6170e93bd60728a1af51d3dd7704935feb228c4d4faab35d334", size = 2546446, upload-time = "2026-02-11T04:22:50.342Z" }, - { url = "https://files.pythonhosted.org/packages/56/11/5d43209aa4cb58e0cc80127956ff1796a68b928e6324bbf06ef4db34367b/pillow-12.1.1-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:600fd103672b925fe62ed08e0d874ea34d692474df6f4bf7ebe148b30f89f39f", size = 5228606, upload-time = "2026-02-11T04:22:52.106Z" }, - { url = "https://files.pythonhosted.org/packages/5f/d5/3b005b4e4fda6698b371fa6c21b097d4707585d7db99e98d9b0b87ac612a/pillow-12.1.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:665e1b916b043cef294bc54d47bf02d87e13f769bc4bc5fa225a24b3a6c5aca9", size = 4622321, upload-time = "2026-02-11T04:22:53.827Z" }, - { url = "https://files.pythonhosted.org/packages/df/36/ed3ea2d594356fd8037e5a01f6156c74bc8d92dbb0fa60746cc96cabb6e8/pillow-12.1.1-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:495c302af3aad1ca67420ddd5c7bd480c8867ad173528767d906428057a11f0e", size = 5247579, upload-time = "2026-02-11T04:22:56.094Z" }, - { url = "https://files.pythonhosted.org/packages/54/9a/9cc3e029683cf6d20ae5085da0dafc63148e3252c2f13328e553aaa13cfb/pillow-12.1.1-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8fd420ef0c52c88b5a035a0886f367748c72147b2b8f384c9d12656678dfdfa9", size = 6989094, upload-time = "2026-02-11T04:22:58.288Z" }, - { url = "https://files.pythonhosted.org/packages/00/98/fc53ab36da80b88df0967896b6c4b4cd948a0dc5aa40a754266aa3ae48b3/pillow-12.1.1-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f975aa7ef9684ce7e2c18a3aa8f8e2106ce1e46b94ab713d156b2898811651d3", size = 5313850, upload-time = "2026-02-11T04:23:00.554Z" }, - { url = "https://files.pythonhosted.org/packages/30/02/00fa585abfd9fe9d73e5f6e554dc36cc2b842898cbfc46d70353dae227f8/pillow-12.1.1-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8089c852a56c2966cf18835db62d9b34fef7ba74c726ad943928d494fa7f4735", size = 5963343, upload-time = "2026-02-11T04:23:02.934Z" }, - { url = "https://files.pythonhosted.org/packages/f2/26/c56ce33ca856e358d27fda9676c055395abddb82c35ac0f593877ed4562e/pillow-12.1.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:cb9bb857b2d057c6dfc72ac5f3b44836924ba15721882ef103cecb40d002d80e", size = 7029880, upload-time = "2026-02-11T04:23:04.783Z" }, +wheels = [ + {url = "https://files.pythonhosted.org/packages/2b/46/5da1ec4a5171ee7bf1a0efa064aba70ba3d6e0788ce3f5acd1375d23c8c0/pillow-12.1.1-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:e879bb6cd5c73848ef3b2b48b8af9ff08c5b71ecda8048b7dd22d8a33f60be32", size = 5304084, upload-time = "2026-02-11T04:20:27.501Z"}, + {url = "https://files.pythonhosted.org/packages/78/93/a29e9bc02d1cf557a834da780ceccd54e02421627200696fcf805ebdc3fb/pillow-12.1.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:365b10bb9417dd4498c0e3b128018c4a624dc11c7b97d8cc54effe3b096f4c38", size = 4657866, upload-time = "2026-02-11T04:20:29.827Z"}, + {url = "https://files.pythonhosted.org/packages/13/84/583a4558d492a179d31e4aae32eadce94b9acf49c0337c4ce0b70e0a01f2/pillow-12.1.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d4ce8e329c93845720cd2014659ca67eac35f6433fd3050393d85f3ecef0dad5", size = 6232148, upload-time = "2026-02-11T04:20:31.329Z"}, + {url = "https://files.pythonhosted.org/packages/d5/e2/53c43334bbbb2d3b938978532fbda8e62bb6e0b23a26ce8592f36bcc4987/pillow-12.1.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fc354a04072b765eccf2204f588a7a532c9511e8b9c7f900e1b64e3e33487090", size = 8038007, upload-time = "2026-02-11T04:20:34.225Z"}, + {url = "https://files.pythonhosted.org/packages/b8/a6/3d0e79c8a9d58150dd98e199d7c1c56861027f3829a3a60b3c2784190180/pillow-12.1.1-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7e7976bf1910a8116b523b9f9f58bf410f3e8aa330cd9a2bb2953f9266ab49af", size = 6345418, upload-time = "2026-02-11T04:20:35.858Z"}, + {url = "https://files.pythonhosted.org/packages/a2/c8/46dfeac5825e600579157eea177be43e2f7ff4a99da9d0d0a49533509ac5/pillow-12.1.1-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:597bd9c8419bc7c6af5604e55847789b69123bbe25d65cc6ad3012b4f3c98d8b", size = 7034590, upload-time = "2026-02-11T04:20:37.91Z"}, + {url = "https://files.pythonhosted.org/packages/af/bf/e6f65d3db8a8bbfeaf9e13cc0417813f6319863a73de934f14b2229ada18/pillow-12.1.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2c1fc0f2ca5f96a3c8407e41cca26a16e46b21060fe6d5b099d2cb01412222f5", size = 6458655, upload-time = "2026-02-11T04:20:39.496Z"}, + {url = "https://files.pythonhosted.org/packages/f9/c2/66091f3f34a25894ca129362e510b956ef26f8fb67a0e6417bc5744e56f1/pillow-12.1.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:578510d88c6229d735855e1f278aa305270438d36a05031dfaae5067cc8eb04d", size = 7159286, upload-time = "2026-02-11T04:20:41.139Z"}, + {url = "https://files.pythonhosted.org/packages/7b/5a/24bc8eb526a22f957d0cec6243146744966d40857e3d8deb68f7902ca6c1/pillow-12.1.1-cp311-cp311-win32.whl", hash = "sha256:7311c0a0dcadb89b36b7025dfd8326ecfa36964e29913074d47382706e516a7c", size = 6328663, upload-time = "2026-02-11T04:20:43.184Z"}, + {url = "https://files.pythonhosted.org/packages/31/03/bef822e4f2d8f9d7448c133d0a18185d3cce3e70472774fffefe8b0ed562/pillow-12.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:fbfa2a7c10cc2623f412753cddf391c7f971c52ca40a3f65dc5039b2939e8563", size = 7031448, upload-time = "2026-02-11T04:20:44.696Z"}, + {url = "https://files.pythonhosted.org/packages/49/70/f76296f53610bd17b2e7d31728b8b7825e3ac3b5b3688b51f52eab7c0818/pillow-12.1.1-cp311-cp311-win_arm64.whl", hash = "sha256:b81b5e3511211631b3f672a595e3221252c90af017e399056d0faabb9538aa80", size = 2453651, upload-time = "2026-02-11T04:20:46.243Z"}, + {url = "https://files.pythonhosted.org/packages/07/d3/8df65da0d4df36b094351dce696f2989bec731d4f10e743b1c5f4da4d3bf/pillow-12.1.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ab323b787d6e18b3d91a72fc99b1a2c28651e4358749842b8f8dfacd28ef2052", size = 5262803, upload-time = "2026-02-11T04:20:47.653Z"}, + {url = "https://files.pythonhosted.org/packages/d6/71/5026395b290ff404b836e636f51d7297e6c83beceaa87c592718747e670f/pillow-12.1.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:adebb5bee0f0af4909c30db0d890c773d1a92ffe83da908e2e9e720f8edf3984", size = 4657601, upload-time = "2026-02-11T04:20:49.328Z"}, + {url = "https://files.pythonhosted.org/packages/b1/2e/1001613d941c67442f745aff0f7cc66dd8df9a9c084eb497e6a543ee6f7e/pillow-12.1.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:bb66b7cc26f50977108790e2456b7921e773f23db5630261102233eb355a3b79", size = 6234995, upload-time = "2026-02-11T04:20:51.032Z"}, + {url = "https://files.pythonhosted.org/packages/07/26/246ab11455b2549b9233dbd44d358d033a2f780fa9007b61a913c5b2d24e/pillow-12.1.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:aee2810642b2898bb187ced9b349e95d2a7272930796e022efaf12e99dccd293", size = 8045012, upload-time = "2026-02-11T04:20:52.882Z"}, + {url = "https://files.pythonhosted.org/packages/b2/8b/07587069c27be7535ac1fe33874e32de118fbd34e2a73b7f83436a88368c/pillow-12.1.1-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a0b1cd6232e2b618adcc54d9882e4e662a089d5768cd188f7c245b4c8c44a397", size = 6349638, upload-time = "2026-02-11T04:20:54.444Z"}, + {url = "https://files.pythonhosted.org/packages/ff/79/6df7b2ee763d619cda2fb4fea498e5f79d984dae304d45a8999b80d6cf5c/pillow-12.1.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7aac39bcf8d4770d089588a2e1dd111cbaa42df5a94be3114222057d68336bd0", size = 7041540, upload-time = "2026-02-11T04:20:55.97Z"}, + {url = "https://files.pythonhosted.org/packages/2c/5e/2ba19e7e7236d7529f4d873bdaf317a318896bac289abebd4bb00ef247f0/pillow-12.1.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ab174cd7d29a62dd139c44bf74b698039328f45cb03b4596c43473a46656b2f3", size = 6462613, upload-time = "2026-02-11T04:20:57.542Z"}, + {url = "https://files.pythonhosted.org/packages/03/03/31216ec124bb5c3dacd74ce8efff4cc7f52643653bad4825f8f08c697743/pillow-12.1.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:339ffdcb7cbeaa08221cd401d517d4b1fe7a9ed5d400e4a8039719238620ca35", size = 7166745, upload-time = "2026-02-11T04:20:59.196Z"}, + {url = "https://files.pythonhosted.org/packages/1f/e7/7c4552d80052337eb28653b617eafdef39adfb137c49dd7e831b8dc13bc5/pillow-12.1.1-cp312-cp312-win32.whl", hash = "sha256:5d1f9575a12bed9e9eedd9a4972834b08c97a352bd17955ccdebfeca5913fa0a", size = 6328823, upload-time = "2026-02-11T04:21:01.385Z"}, + {url = "https://files.pythonhosted.org/packages/3d/17/688626d192d7261bbbf98846fc98995726bddc2c945344b65bec3a29d731/pillow-12.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:21329ec8c96c6e979cd0dfd29406c40c1d52521a90544463057d2aaa937d66a6", size = 7033367, upload-time = "2026-02-11T04:21:03.536Z"}, + {url = "https://files.pythonhosted.org/packages/ed/fe/a0ef1f73f939b0eca03ee2c108d0043a87468664770612602c63266a43c4/pillow-12.1.1-cp312-cp312-win_arm64.whl", hash = "sha256:af9a332e572978f0218686636610555ae3defd1633597be015ed50289a03c523", size = 2453811, upload-time = "2026-02-11T04:21:05.116Z"}, + {url = "https://files.pythonhosted.org/packages/d5/11/6db24d4bd7685583caeae54b7009584e38da3c3d4488ed4cd25b439de486/pillow-12.1.1-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:d242e8ac078781f1de88bf823d70c1a9b3c7950a44cdf4b7c012e22ccbcd8e4e", size = 4062689, upload-time = "2026-02-11T04:21:06.804Z"}, + {url = "https://files.pythonhosted.org/packages/33/c0/ce6d3b1fe190f0021203e0d9b5b99e57843e345f15f9ef22fcd43842fd21/pillow-12.1.1-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:02f84dfad02693676692746df05b89cf25597560db2857363a208e393429f5e9", size = 4138535, upload-time = "2026-02-11T04:21:08.452Z"}, + {url = "https://files.pythonhosted.org/packages/a0/c6/d5eb6a4fb32a3f9c21a8c7613ec706534ea1cf9f4b3663e99f0d83f6fca8/pillow-12.1.1-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:e65498daf4b583091ccbb2556c7000abf0f3349fcd57ef7adc9a84a394ed29f6", size = 3601364, upload-time = "2026-02-11T04:21:10.194Z"}, + {url = "https://files.pythonhosted.org/packages/14/a1/16c4b823838ba4c9c52c0e6bbda903a3fe5a1bdbf1b8eb4fff7156f3e318/pillow-12.1.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:6c6db3b84c87d48d0088943bf33440e0c42370b99b1c2a7989216f7b42eede60", size = 5262561, upload-time = "2026-02-11T04:21:11.742Z"}, + {url = "https://files.pythonhosted.org/packages/bb/ad/ad9dc98ff24f485008aa5cdedaf1a219876f6f6c42a4626c08bc4e80b120/pillow-12.1.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8b7e5304e34942bf62e15184219a7b5ad4ff7f3bb5cca4d984f37df1a0e1aee2", size = 4657460, upload-time = "2026-02-11T04:21:13.786Z"}, + {url = "https://files.pythonhosted.org/packages/9e/1b/f1a4ea9a895b5732152789326202a82464d5254759fbacae4deea3069334/pillow-12.1.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:18e5bddd742a44b7e6b1e773ab5db102bd7a94c32555ba656e76d319d19c3850", size = 6232698, upload-time = "2026-02-11T04:21:15.949Z"}, + {url = "https://files.pythonhosted.org/packages/95/f4/86f51b8745070daf21fd2e5b1fe0eb35d4db9ca26e6d58366562fb56a743/pillow-12.1.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fc44ef1f3de4f45b50ccf9136999d71abb99dca7706bc75d222ed350b9fd2289", size = 8041706, upload-time = "2026-02-11T04:21:17.723Z"}, + {url = "https://files.pythonhosted.org/packages/29/9b/d6ecd956bb1266dd1045e995cce9b8d77759e740953a1c9aad9502a0461e/pillow-12.1.1-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5a8eb7ed8d4198bccbd07058416eeec51686b498e784eda166395a23eb99138e", size = 6346621, upload-time = "2026-02-11T04:21:19.547Z"}, + {url = "https://files.pythonhosted.org/packages/71/24/538bff45bde96535d7d998c6fed1a751c75ac7c53c37c90dc2601b243893/pillow-12.1.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:47b94983da0c642de92ced1702c5b6c292a84bd3a8e1d1702ff923f183594717", size = 7038069, upload-time = "2026-02-11T04:21:21.378Z"}, + {url = "https://files.pythonhosted.org/packages/94/0e/58cb1a6bc48f746bc4cb3adb8cabff73e2742c92b3bf7a220b7cf69b9177/pillow-12.1.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:518a48c2aab7ce596d3bf79d0e275661b846e86e4d0e7dec34712c30fe07f02a", size = 6460040, upload-time = "2026-02-11T04:21:23.148Z"}, + {url = "https://files.pythonhosted.org/packages/6c/57/9045cb3ff11eeb6c1adce3b2d60d7d299d7b273a2e6c8381a524abfdc474/pillow-12.1.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a550ae29b95c6dc13cf69e2c9dc5747f814c54eeb2e32d683e5e93af56caa029", size = 7164523, upload-time = "2026-02-11T04:21:25.01Z"}, + {url = "https://files.pythonhosted.org/packages/73/f2/9be9cb99f2175f0d4dbadd6616ce1bf068ee54a28277ea1bf1fbf729c250/pillow-12.1.1-cp313-cp313-win32.whl", hash = "sha256:a003d7422449f6d1e3a34e3dd4110c22148336918ddbfc6a32581cd54b2e0b2b", size = 6332552, upload-time = "2026-02-11T04:21:27.238Z"}, + {url = "https://files.pythonhosted.org/packages/3f/eb/b0834ad8b583d7d9d42b80becff092082a1c3c156bb582590fcc973f1c7c/pillow-12.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:344cf1e3dab3be4b1fa08e449323d98a2a3f819ad20f4b22e77a0ede31f0faa1", size = 7040108, upload-time = "2026-02-11T04:21:29.462Z"}, + {url = "https://files.pythonhosted.org/packages/d5/7d/fc09634e2aabdd0feabaff4a32f4a7d97789223e7c2042fd805ea4b4d2c2/pillow-12.1.1-cp313-cp313-win_arm64.whl", hash = "sha256:5c0dd1636633e7e6a0afe7bf6a51a14992b7f8e60de5789018ebbdfae55b040a", size = 2453712, upload-time = "2026-02-11T04:21:31.072Z"}, + {url = "https://files.pythonhosted.org/packages/19/2a/b9d62794fc8a0dd14c1943df68347badbd5511103e0d04c035ffe5cf2255/pillow-12.1.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0330d233c1a0ead844fc097a7d16c0abff4c12e856c0b325f231820fee1f39da", size = 5264880, upload-time = "2026-02-11T04:21:32.865Z"}, + {url = "https://files.pythonhosted.org/packages/26/9d/e03d857d1347fa5ed9247e123fcd2a97b6220e15e9cb73ca0a8d91702c6e/pillow-12.1.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:5dae5f21afb91322f2ff791895ddd8889e5e947ff59f71b46041c8ce6db790bc", size = 4660616, upload-time = "2026-02-11T04:21:34.97Z"}, + {url = "https://files.pythonhosted.org/packages/f7/ec/8a6d22afd02570d30954e043f09c32772bfe143ba9285e2fdb11284952cd/pillow-12.1.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:2e0c664be47252947d870ac0d327fea7e63985a08794758aa8af5b6cb6ec0c9c", size = 6269008, upload-time = "2026-02-11T04:21:36.623Z"}, + {url = "https://files.pythonhosted.org/packages/3d/1d/6d875422c9f28a4a361f495a5f68d9de4a66941dc2c619103ca335fa6446/pillow-12.1.1-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:691ab2ac363b8217f7d31b3497108fb1f50faab2f75dfb03284ec2f217e87bf8", size = 8073226, upload-time = "2026-02-11T04:21:38.585Z"}, + {url = "https://files.pythonhosted.org/packages/a1/cd/134b0b6ee5eda6dc09e25e24b40fdafe11a520bc725c1d0bbaa5e00bf95b/pillow-12.1.1-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e9e8064fb1cc019296958595f6db671fba95209e3ceb0c4734c9baf97de04b20", size = 6380136, upload-time = "2026-02-11T04:21:40.562Z"}, + {url = "https://files.pythonhosted.org/packages/7a/a9/7628f013f18f001c1b98d8fffe3452f306a70dc6aba7d931019e0492f45e/pillow-12.1.1-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:472a8d7ded663e6162dafdf20015c486a7009483ca671cece7a9279b512fcb13", size = 7067129, upload-time = "2026-02-11T04:21:42.521Z"}, + {url = "https://files.pythonhosted.org/packages/1e/f8/66ab30a2193b277785601e82ee2d49f68ea575d9637e5e234faaa98efa4c/pillow-12.1.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:89b54027a766529136a06cfebeecb3a04900397a3590fd252160b888479517bf", size = 6491807, upload-time = "2026-02-11T04:21:44.22Z"}, + {url = "https://files.pythonhosted.org/packages/da/0b/a877a6627dc8318fdb84e357c5e1a758c0941ab1ddffdafd231983788579/pillow-12.1.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:86172b0831b82ce4f7877f280055892b31179e1576aa00d0df3bb1bbf8c3e524", size = 7190954, upload-time = "2026-02-11T04:21:46.114Z"}, + {url = "https://files.pythonhosted.org/packages/83/43/6f732ff85743cf746b1361b91665d9f5155e1483817f693f8d57ea93147f/pillow-12.1.1-cp313-cp313t-win32.whl", hash = "sha256:44ce27545b6efcf0fdbdceb31c9a5bdea9333e664cda58a7e674bb74608b3986", size = 6336441, upload-time = "2026-02-11T04:21:48.22Z"}, + {url = "https://files.pythonhosted.org/packages/3b/44/e865ef3986611bb75bfabdf94a590016ea327833f434558801122979cd0e/pillow-12.1.1-cp313-cp313t-win_amd64.whl", hash = "sha256:a285e3eb7a5a45a2ff504e31f4a8d1b12ef62e84e5411c6804a42197c1cf586c", size = 7045383, upload-time = "2026-02-11T04:21:50.015Z"}, + {url = "https://files.pythonhosted.org/packages/a8/c6/f4fb24268d0c6908b9f04143697ea18b0379490cb74ba9e8d41b898bd005/pillow-12.1.1-cp313-cp313t-win_arm64.whl", hash = "sha256:cc7d296b5ea4d29e6570dabeaed58d31c3fea35a633a69679fb03d7664f43fb3", size = 2456104, upload-time = "2026-02-11T04:21:51.633Z"}, + {url = "https://files.pythonhosted.org/packages/03/d0/bebb3ffbf31c5a8e97241476c4cf8b9828954693ce6744b4a2326af3e16b/pillow-12.1.1-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:417423db963cb4be8bac3fc1204fe61610f6abeed1580a7a2cbb2fbda20f12af", size = 4062652, upload-time = "2026-02-11T04:21:53.19Z"}, + {url = "https://files.pythonhosted.org/packages/2d/c0/0e16fb0addda4851445c28f8350d8c512f09de27bbb0d6d0bbf8b6709605/pillow-12.1.1-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:b957b71c6b2387610f556a7eb0828afbe40b4a98036fc0d2acfa5a44a0c2036f", size = 4138823, upload-time = "2026-02-11T04:22:03.088Z"}, + {url = "https://files.pythonhosted.org/packages/6b/fb/6170ec655d6f6bb6630a013dd7cf7bc218423d7b5fa9071bf63dc32175ae/pillow-12.1.1-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:097690ba1f2efdeb165a20469d59d8bb03c55fb6621eb2041a060ae8ea3e9642", size = 3601143, upload-time = "2026-02-11T04:22:04.909Z"}, + {url = "https://files.pythonhosted.org/packages/59/04/dc5c3f297510ba9a6837cbb318b87dd2b8f73eb41a43cc63767f65cb599c/pillow-12.1.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:2815a87ab27848db0321fb78c7f0b2c8649dee134b7f2b80c6a45c6831d75ccd", size = 5266254, upload-time = "2026-02-11T04:22:07.656Z"}, + {url = "https://files.pythonhosted.org/packages/05/30/5db1236b0d6313f03ebf97f5e17cda9ca060f524b2fcc875149a8360b21c/pillow-12.1.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:f7ed2c6543bad5a7d5530eb9e78c53132f93dfa44a28492db88b41cdab885202", size = 4657499, upload-time = "2026-02-11T04:22:09.613Z"}, + {url = "https://files.pythonhosted.org/packages/6f/18/008d2ca0eb612e81968e8be0bbae5051efba24d52debf930126d7eaacbba/pillow-12.1.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:652a2c9ccfb556235b2b501a3a7cf3742148cd22e04b5625c5fe057ea3e3191f", size = 6232137, upload-time = "2026-02-11T04:22:11.434Z"}, + {url = "https://files.pythonhosted.org/packages/70/f1/f14d5b8eeb4b2cd62b9f9f847eb6605f103df89ef619ac68f92f748614ea/pillow-12.1.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d6e4571eedf43af33d0fc233a382a76e849badbccdf1ac438841308652a08e1f", size = 8042721, upload-time = "2026-02-11T04:22:13.321Z"}, + {url = "https://files.pythonhosted.org/packages/5a/d6/17824509146e4babbdabf04d8171491fa9d776f7061ff6e727522df9bd03/pillow-12.1.1-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b574c51cf7d5d62e9be37ba446224b59a2da26dc4c1bb2ecbe936a4fb1a7cb7f", size = 6347798, upload-time = "2026-02-11T04:22:15.449Z"}, + {url = "https://files.pythonhosted.org/packages/d1/ee/c85a38a9ab92037a75615aba572c85ea51e605265036e00c5b67dfafbfe2/pillow-12.1.1-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a37691702ed687799de29a518d63d4682d9016932db66d4e90c345831b02fb4e", size = 7039315, upload-time = "2026-02-11T04:22:17.24Z"}, + {url = "https://files.pythonhosted.org/packages/ec/f3/bc8ccc6e08a148290d7523bde4d9a0d6c981db34631390dc6e6ec34cacf6/pillow-12.1.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:f95c00d5d6700b2b890479664a06e754974848afaae5e21beb4d83c106923fd0", size = 6462360, upload-time = "2026-02-11T04:22:19.111Z"}, + {url = "https://files.pythonhosted.org/packages/f6/ab/69a42656adb1d0665ab051eec58a41f169ad295cf81ad45406963105408f/pillow-12.1.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:559b38da23606e68681337ad74622c4dbba02254fc9cb4488a305dd5975c7eeb", size = 7165438, upload-time = "2026-02-11T04:22:21.041Z"}, + {url = "https://files.pythonhosted.org/packages/02/46/81f7aa8941873f0f01d4b55cc543b0a3d03ec2ee30d617a0448bf6bd6dec/pillow-12.1.1-cp314-cp314-win32.whl", hash = "sha256:03edcc34d688572014ff223c125a3f77fb08091e4607e7745002fc214070b35f", size = 6431503, upload-time = "2026-02-11T04:22:22.833Z"}, + {url = "https://files.pythonhosted.org/packages/40/72/4c245f7d1044b67affc7f134a09ea619d4895333d35322b775b928180044/pillow-12.1.1-cp314-cp314-win_amd64.whl", hash = "sha256:50480dcd74fa63b8e78235957d302d98d98d82ccbfac4c7e12108ba9ecbdba15", size = 7176748, upload-time = "2026-02-11T04:22:24.64Z"}, + {url = "https://files.pythonhosted.org/packages/e4/ad/8a87bdbe038c5c698736e3348af5c2194ffb872ea52f11894c95f9305435/pillow-12.1.1-cp314-cp314-win_arm64.whl", hash = "sha256:5cb1785d97b0c3d1d1a16bc1d710c4a0049daefc4935f3a8f31f827f4d3d2e7f", size = 2544314, upload-time = "2026-02-11T04:22:26.685Z"}, + {url = "https://files.pythonhosted.org/packages/6c/9d/efd18493f9de13b87ede7c47e69184b9e859e4427225ea962e32e56a49bc/pillow-12.1.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:1f90cff8aa76835cba5769f0b3121a22bd4eb9e6884cfe338216e557a9a548b8", size = 5268612, upload-time = "2026-02-11T04:22:29.884Z"}, + {url = "https://files.pythonhosted.org/packages/f8/f1/4f42eb2b388eb2ffc660dcb7f7b556c1015c53ebd5f7f754965ef997585b/pillow-12.1.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1f1be78ce9466a7ee64bfda57bdba0f7cc499d9794d518b854816c41bf0aa4e9", size = 4660567, upload-time = "2026-02-11T04:22:31.799Z"}, + {url = "https://files.pythonhosted.org/packages/01/54/df6ef130fa43e4b82e32624a7b821a2be1c5653a5fdad8469687a7db4e00/pillow-12.1.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:42fc1f4677106188ad9a55562bbade416f8b55456f522430fadab3cef7cd4e60", size = 6269951, upload-time = "2026-02-11T04:22:33.921Z"}, + {url = "https://files.pythonhosted.org/packages/a9/48/618752d06cc44bb4aae8ce0cd4e6426871929ed7b46215638088270d9b34/pillow-12.1.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:98edb152429ab62a1818039744d8fbb3ccab98a7c29fc3d5fcef158f3f1f68b7", size = 8074769, upload-time = "2026-02-11T04:22:35.877Z"}, + {url = "https://files.pythonhosted.org/packages/c3/bd/f1d71eb39a72fa088d938655afba3e00b38018d052752f435838961127d8/pillow-12.1.1-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d470ab1178551dd17fdba0fef463359c41aaa613cdcd7ff8373f54be629f9f8f", size = 6381358, upload-time = "2026-02-11T04:22:37.698Z"}, + {url = "https://files.pythonhosted.org/packages/64/ef/c784e20b96674ed36a5af839305f55616f8b4f8aa8eeccf8531a6e312243/pillow-12.1.1-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6408a7b064595afcab0a49393a413732a35788f2a5092fdc6266952ed67de586", size = 7068558, upload-time = "2026-02-11T04:22:39.597Z"}, + {url = "https://files.pythonhosted.org/packages/73/cb/8059688b74422ae61278202c4e1ad992e8a2e7375227be0a21c6b87ca8d5/pillow-12.1.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5d8c41325b382c07799a3682c1c258469ea2ff97103c53717b7893862d0c98ce", size = 6493028, upload-time = "2026-02-11T04:22:42.73Z"}, + {url = "https://files.pythonhosted.org/packages/c6/da/e3c008ed7d2dd1f905b15949325934510b9d1931e5df999bb15972756818/pillow-12.1.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:c7697918b5be27424e9ce568193efd13d925c4481dd364e43f5dff72d33e10f8", size = 7191940, upload-time = "2026-02-11T04:22:44.543Z"}, + {url = "https://files.pythonhosted.org/packages/01/4a/9202e8d11714c1fc5951f2e1ef362f2d7fbc595e1f6717971d5dd750e969/pillow-12.1.1-cp314-cp314t-win32.whl", hash = "sha256:d2912fd8114fc5545aa3a4b5576512f64c55a03f3ebcca4c10194d593d43ea36", size = 6438736, upload-time = "2026-02-11T04:22:46.347Z"}, + {url = "https://files.pythonhosted.org/packages/f3/ca/cbce2327eb9885476b3957b2e82eb12c866a8b16ad77392864ad601022ce/pillow-12.1.1-cp314-cp314t-win_amd64.whl", hash = "sha256:4ceb838d4bd9dab43e06c363cab2eebf63846d6a4aeaea283bbdfd8f1a8ed58b", size = 7182894, upload-time = "2026-02-11T04:22:48.114Z"}, + {url = "https://files.pythonhosted.org/packages/ec/d2/de599c95ba0a973b94410477f8bf0b6f0b5e67360eb89bcb1ad365258beb/pillow-12.1.1-cp314-cp314t-win_arm64.whl", hash = "sha256:7b03048319bfc6170e93bd60728a1af51d3dd7704935feb228c4d4faab35d334", size = 2546446, upload-time = "2026-02-11T04:22:50.342Z"}, + {url = "https://files.pythonhosted.org/packages/56/11/5d43209aa4cb58e0cc80127956ff1796a68b928e6324bbf06ef4db34367b/pillow-12.1.1-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:600fd103672b925fe62ed08e0d874ea34d692474df6f4bf7ebe148b30f89f39f", size = 5228606, upload-time = "2026-02-11T04:22:52.106Z"}, + {url = "https://files.pythonhosted.org/packages/5f/d5/3b005b4e4fda6698b371fa6c21b097d4707585d7db99e98d9b0b87ac612a/pillow-12.1.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:665e1b916b043cef294bc54d47bf02d87e13f769bc4bc5fa225a24b3a6c5aca9", size = 4622321, upload-time = "2026-02-11T04:22:53.827Z"}, + {url = "https://files.pythonhosted.org/packages/df/36/ed3ea2d594356fd8037e5a01f6156c74bc8d92dbb0fa60746cc96cabb6e8/pillow-12.1.1-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:495c302af3aad1ca67420ddd5c7bd480c8867ad173528767d906428057a11f0e", size = 5247579, upload-time = "2026-02-11T04:22:56.094Z"}, + {url = "https://files.pythonhosted.org/packages/54/9a/9cc3e029683cf6d20ae5085da0dafc63148e3252c2f13328e553aaa13cfb/pillow-12.1.1-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8fd420ef0c52c88b5a035a0886f367748c72147b2b8f384c9d12656678dfdfa9", size = 6989094, upload-time = "2026-02-11T04:22:58.288Z"}, + {url = "https://files.pythonhosted.org/packages/00/98/fc53ab36da80b88df0967896b6c4b4cd948a0dc5aa40a754266aa3ae48b3/pillow-12.1.1-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f975aa7ef9684ce7e2c18a3aa8f8e2106ce1e46b94ab713d156b2898811651d3", size = 5313850, upload-time = "2026-02-11T04:23:00.554Z"}, + {url = "https://files.pythonhosted.org/packages/30/02/00fa585abfd9fe9d73e5f6e554dc36cc2b842898cbfc46d70353dae227f8/pillow-12.1.1-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8089c852a56c2966cf18835db62d9b34fef7ba74c726ad943928d494fa7f4735", size = 5963343, upload-time = "2026-02-11T04:23:02.934Z"}, + {url = "https://files.pythonhosted.org/packages/f2/26/c56ce33ca856e358d27fda9676c055395abddb82c35ac0f593877ed4562e/pillow-12.1.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:cb9bb857b2d057c6dfc72ac5f3b44836924ba15721882ef103cecb40d002d80e", size = 7029880, upload-time = "2026-02-11T04:23:04.783Z"} ] [[package]] -name = "pint" -version = "0.25.2" -source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "flexcache" }, - { name = "flexparser" }, - { name = "platformdirs" }, - { name = "typing-extensions" }, + {name = "flexcache"}, + {name = "flexparser"}, + {name = "platformdirs"}, + {name = "typing-extensions"} ] -sdist = { url = "https://files.pythonhosted.org/packages/5f/74/bc3f671997158aef171194c3c4041e549946f4784b8690baa0626a0a164b/pint-0.25.2.tar.gz", hash = "sha256:85a45d1da8fe9c9f7477fed8aef59ad2b939af3d6611507e1a9cbdacdcd3450a", size = 254467, upload-time = "2025-11-06T22:08:09.184Z" } +name = "pint" +sdist = {url = "https://files.pythonhosted.org/packages/5f/74/bc3f671997158aef171194c3c4041e549946f4784b8690baa0626a0a164b/pint-0.25.2.tar.gz", hash = "sha256:85a45d1da8fe9c9f7477fed8aef59ad2b939af3d6611507e1a9cbdacdcd3450a", size = 254467, upload-time = "2025-11-06T22:08:09.184Z"} +source = {registry = "https://pypi.org/simple"} +version = "0.25.2" wheels = [ - { url = "https://files.pythonhosted.org/packages/ab/88/550d41e81e6d43335603a960cd9c75c1d88f9cf01bc9d4ee8e86290aba7d/pint-0.25.2-py3-none-any.whl", hash = "sha256:ca35ab1d8eeeb6f7d9942b3cb5f34ca42b61cdd5fb3eae79531553dcca04dda7", size = 306762, upload-time = "2025-11-06T22:08:07.745Z" }, + {url = "https://files.pythonhosted.org/packages/ab/88/550d41e81e6d43335603a960cd9c75c1d88f9cf01bc9d4ee8e86290aba7d/pint-0.25.2-py3-none-any.whl", hash = "sha256:ca35ab1d8eeeb6f7d9942b3cb5f34ca42b61cdd5fb3eae79531553dcca04dda7", size = 306762, upload-time = "2025-11-06T22:08:07.745Z"} ] [[package]] name = "platformdirs" +sdist = {url = "https://files.pythonhosted.org/packages/1b/04/fea538adf7dbbd6d186f551d595961e564a3b6715bdf276b477460858672/platformdirs-4.9.2.tar.gz", hash = "sha256:9a33809944b9db043ad67ca0db94b14bf452cc6aeaac46a88ea55b26e2e9d291", size = 28394, upload-time = "2026-02-16T03:56:10.574Z"} +source = {registry = "https://pypi.org/simple"} version = "4.9.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/1b/04/fea538adf7dbbd6d186f551d595961e564a3b6715bdf276b477460858672/platformdirs-4.9.2.tar.gz", hash = "sha256:9a33809944b9db043ad67ca0db94b14bf452cc6aeaac46a88ea55b26e2e9d291", size = 28394, upload-time = "2026-02-16T03:56:10.574Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/48/31/05e764397056194206169869b50cf2fee4dbbbc71b344705b9c0d878d4d8/platformdirs-4.9.2-py3-none-any.whl", hash = "sha256:9170634f126f8efdae22fb58ae8a0eaa86f38365bc57897a6c4f781d1f5875bd", size = 21168, upload-time = "2026-02-16T03:56:08.891Z" }, + {url = "https://files.pythonhosted.org/packages/48/31/05e764397056194206169869b50cf2fee4dbbbc71b344705b9c0d878d4d8/platformdirs-4.9.2-py3-none-any.whl", hash = "sha256:9170634f126f8efdae22fb58ae8a0eaa86f38365bc57897a6c4f781d1f5875bd", size = 21168, upload-time = "2026-02-16T03:56:08.891Z"} ] [[package]] name = "pluggy" +sdist = {url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z"} +source = {registry = "https://pypi.org/simple"} version = "1.6.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" }, + {url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z"} ] [[package]] name = "prek" +sdist = {url = "https://files.pythonhosted.org/packages/bf/f1/7613dc8347a33e40fc5b79eec6bc7d458d8bbc339782333d8433b665f86f/prek-0.3.3.tar.gz", hash = "sha256:117bd46ebeb39def24298ce021ccc73edcf697b81856fcff36d762dd56093f6f", size = 343697, upload-time = "2026-02-15T13:33:28.723Z"} +source = {registry = "https://pypi.org/simple"} version = "0.3.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/bf/f1/7613dc8347a33e40fc5b79eec6bc7d458d8bbc339782333d8433b665f86f/prek-0.3.3.tar.gz", hash = "sha256:117bd46ebeb39def24298ce021ccc73edcf697b81856fcff36d762dd56093f6f", size = 343697, upload-time = "2026-02-15T13:33:28.723Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/2d/8b/dce13d2a3065fd1e8ffce593a0e51c4a79c3cde9c9a15dc0acc8d9d1573d/prek-0.3.3-py3-none-linux_armv6l.whl", hash = "sha256:e8629cac4bdb131be8dc6e5a337f0f76073ad34a8305f3fe2bc1ab6201ede0a4", size = 4644636, upload-time = "2026-02-15T13:33:43.609Z" }, - { url = "https://files.pythonhosted.org/packages/01/30/06ab4dbe7ce02a8ce833e92deb1d9a8e85ae9d40e33d1959a2070b7494c6/prek-0.3.3-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:4b9e819b9e4118e1e785047b1c8bd9aec7e4d836ed034cb58b7db5bcaaf49437", size = 4651410, upload-time = "2026-02-15T13:33:34.277Z" }, - { url = "https://files.pythonhosted.org/packages/d4/fc/da3bc5cb38471e7192eda06b7a26b7c24ef83e82da2c1dbc145f2bf33640/prek-0.3.3-py3-none-macosx_11_0_arm64.whl", hash = "sha256:bf29db3b5657c083eb8444c25aadeeec5167dc492e9019e188f87932f01ea50a", size = 4273163, upload-time = "2026-02-15T13:33:42.106Z" }, - { url = "https://files.pythonhosted.org/packages/b4/74/47839395091e2937beced81a5dd2f8ea9c8239c853da8611aaf78ee21a8b/prek-0.3.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:ae09736149815b26e64a9d350ca05692bab32c2afdf2939114d3211aaad68a3e", size = 4631808, upload-time = "2026-02-15T13:33:20.076Z" }, - { url = "https://files.pythonhosted.org/packages/e2/89/3f5ef6f7c928c017cb63b029349d6bc03598ab7f6979d4a770ce02575f82/prek-0.3.3-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:856c2b55c51703c366bb4ce81c6a91102b70573a9fc8637db2ac61c66e4565f9", size = 4548959, upload-time = "2026-02-15T13:33:36.325Z" }, - { url = "https://files.pythonhosted.org/packages/b2/18/80002c4c4475f90ca025f27739a016927a0e5d905c60612fc95da1c56ab7/prek-0.3.3-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3acdf13a018f685beaff0a71d4b0d2ccbab4eaa1aced6d08fd471c1a654183eb", size = 4862256, upload-time = "2026-02-15T13:33:37.754Z" }, - { url = "https://files.pythonhosted.org/packages/c5/25/648bf084c2468fa7cfcdbbe9e59956bbb31b81f36e113bc9107d80af26a7/prek-0.3.3-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0f035667a8bd0a77b2bfa2b2e125da8cb1793949e9eeef0d8daab7f8ac8b57fe", size = 5404486, upload-time = "2026-02-15T13:33:39.239Z" }, - { url = "https://files.pythonhosted.org/packages/8b/43/261fb60a11712a327da345912bd8b338dc5a050199de800faafa278a6133/prek-0.3.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d09b2ad14332eede441d977de08eb57fb3f61226ed5fd2ceb7aadf5afcdb6794", size = 4887513, upload-time = "2026-02-15T13:33:40.702Z" }, - { url = "https://files.pythonhosted.org/packages/c7/2c/581e757ee57ec6046b32e0ee25660fc734bc2622c319f57119c49c0cab58/prek-0.3.3-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:c0c3ffac16e37a9daba43a7e8316778f5809b70254be138761a8b5b9ef0df28e", size = 4632336, upload-time = "2026-02-15T13:33:25.867Z" }, - { url = "https://files.pythonhosted.org/packages/d5/d8/aa276ce5d11b77882da4102ca0cb7161095831105043ae7979bbfdcc3dc4/prek-0.3.3-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:a3dc7720b580c07c0386e17af2486a5b4bc2f6cc57034a288a614dcbc4abe555", size = 4679370, upload-time = "2026-02-15T13:33:22.247Z" }, - { url = "https://files.pythonhosted.org/packages/70/19/9d4fa7bde428e58d9f48a74290c08736d42aeb5690dcdccc7a713e34a449/prek-0.3.3-py3-none-musllinux_1_1_armv7l.whl", hash = "sha256:60e0fa15da5020a03df2ee40268145ec5b88267ec2141a205317ad4df8c992d6", size = 4540316, upload-time = "2026-02-15T13:33:24.088Z" }, - { url = "https://files.pythonhosted.org/packages/25/b5/973cce29257e0b47b16cc9b4c162772ea01dbb7c080791ea0c068e106e05/prek-0.3.3-py3-none-musllinux_1_1_i686.whl", hash = "sha256:553515da9586d9624dc42db32b744fdb91cf62b053753037a0cadb3c2d8d82a2", size = 4724566, upload-time = "2026-02-15T13:33:29.832Z" }, - { url = "https://files.pythonhosted.org/packages/d6/8b/ad8b2658895a8ed2b0bc630bf38686fe38b7ff2c619c58953a80e4de3048/prek-0.3.3-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:9512cf370e0d1496503463a4a65621480efb41b487841a9e9ff1661edf14b238", size = 4995072, upload-time = "2026-02-15T13:33:27.417Z" }, - { url = "https://files.pythonhosted.org/packages/fd/b7/0540c101c00882adb9d30319d22d8f879413598269ecc60235e41875efd4/prek-0.3.3-py3-none-win32.whl", hash = "sha256:b2b328c7c6dc14ccdc79785348589aa39850f47baff33d8f199f2dee80ff774c", size = 4293144, upload-time = "2026-02-15T13:33:46.013Z" }, - { url = "https://files.pythonhosted.org/packages/97/c7/e4f11da653093040efba2d835aa0995d78940aea30887287aeaebe34a545/prek-0.3.3-py3-none-win_amd64.whl", hash = "sha256:3d7d7acf7ca8db65ba0943c52326c898f84bab0b1c26a35c87e0d177f574ca5f", size = 4652761, upload-time = "2026-02-15T13:33:32.962Z" }, - { url = "https://files.pythonhosted.org/packages/11/e4/d99dec54c6a5fb2763488bff6078166383169a93f3af27d2edae88379a39/prek-0.3.3-py3-none-win_arm64.whl", hash = "sha256:8aa87ee7628cd74482c0dd6537a3def1f162b25cd642d78b1b35dd3e81817f60", size = 4367520, upload-time = "2026-02-15T13:33:31.664Z" }, +wheels = [ + {url = "https://files.pythonhosted.org/packages/2d/8b/dce13d2a3065fd1e8ffce593a0e51c4a79c3cde9c9a15dc0acc8d9d1573d/prek-0.3.3-py3-none-linux_armv6l.whl", hash = "sha256:e8629cac4bdb131be8dc6e5a337f0f76073ad34a8305f3fe2bc1ab6201ede0a4", size = 4644636, upload-time = "2026-02-15T13:33:43.609Z"}, + {url = "https://files.pythonhosted.org/packages/01/30/06ab4dbe7ce02a8ce833e92deb1d9a8e85ae9d40e33d1959a2070b7494c6/prek-0.3.3-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:4b9e819b9e4118e1e785047b1c8bd9aec7e4d836ed034cb58b7db5bcaaf49437", size = 4651410, upload-time = "2026-02-15T13:33:34.277Z"}, + {url = "https://files.pythonhosted.org/packages/d4/fc/da3bc5cb38471e7192eda06b7a26b7c24ef83e82da2c1dbc145f2bf33640/prek-0.3.3-py3-none-macosx_11_0_arm64.whl", hash = "sha256:bf29db3b5657c083eb8444c25aadeeec5167dc492e9019e188f87932f01ea50a", size = 4273163, upload-time = "2026-02-15T13:33:42.106Z"}, + {url = "https://files.pythonhosted.org/packages/b4/74/47839395091e2937beced81a5dd2f8ea9c8239c853da8611aaf78ee21a8b/prek-0.3.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:ae09736149815b26e64a9d350ca05692bab32c2afdf2939114d3211aaad68a3e", size = 4631808, upload-time = "2026-02-15T13:33:20.076Z"}, + {url = "https://files.pythonhosted.org/packages/e2/89/3f5ef6f7c928c017cb63b029349d6bc03598ab7f6979d4a770ce02575f82/prek-0.3.3-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:856c2b55c51703c366bb4ce81c6a91102b70573a9fc8637db2ac61c66e4565f9", size = 4548959, upload-time = "2026-02-15T13:33:36.325Z"}, + {url = "https://files.pythonhosted.org/packages/b2/18/80002c4c4475f90ca025f27739a016927a0e5d905c60612fc95da1c56ab7/prek-0.3.3-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3acdf13a018f685beaff0a71d4b0d2ccbab4eaa1aced6d08fd471c1a654183eb", size = 4862256, upload-time = "2026-02-15T13:33:37.754Z"}, + {url = "https://files.pythonhosted.org/packages/c5/25/648bf084c2468fa7cfcdbbe9e59956bbb31b81f36e113bc9107d80af26a7/prek-0.3.3-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0f035667a8bd0a77b2bfa2b2e125da8cb1793949e9eeef0d8daab7f8ac8b57fe", size = 5404486, upload-time = "2026-02-15T13:33:39.239Z"}, + {url = "https://files.pythonhosted.org/packages/8b/43/261fb60a11712a327da345912bd8b338dc5a050199de800faafa278a6133/prek-0.3.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d09b2ad14332eede441d977de08eb57fb3f61226ed5fd2ceb7aadf5afcdb6794", size = 4887513, upload-time = "2026-02-15T13:33:40.702Z"}, + {url = "https://files.pythonhosted.org/packages/c7/2c/581e757ee57ec6046b32e0ee25660fc734bc2622c319f57119c49c0cab58/prek-0.3.3-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:c0c3ffac16e37a9daba43a7e8316778f5809b70254be138761a8b5b9ef0df28e", size = 4632336, upload-time = "2026-02-15T13:33:25.867Z"}, + {url = "https://files.pythonhosted.org/packages/d5/d8/aa276ce5d11b77882da4102ca0cb7161095831105043ae7979bbfdcc3dc4/prek-0.3.3-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:a3dc7720b580c07c0386e17af2486a5b4bc2f6cc57034a288a614dcbc4abe555", size = 4679370, upload-time = "2026-02-15T13:33:22.247Z"}, + {url = "https://files.pythonhosted.org/packages/70/19/9d4fa7bde428e58d9f48a74290c08736d42aeb5690dcdccc7a713e34a449/prek-0.3.3-py3-none-musllinux_1_1_armv7l.whl", hash = "sha256:60e0fa15da5020a03df2ee40268145ec5b88267ec2141a205317ad4df8c992d6", size = 4540316, upload-time = "2026-02-15T13:33:24.088Z"}, + {url = "https://files.pythonhosted.org/packages/25/b5/973cce29257e0b47b16cc9b4c162772ea01dbb7c080791ea0c068e106e05/prek-0.3.3-py3-none-musllinux_1_1_i686.whl", hash = "sha256:553515da9586d9624dc42db32b744fdb91cf62b053753037a0cadb3c2d8d82a2", size = 4724566, upload-time = "2026-02-15T13:33:29.832Z"}, + {url = "https://files.pythonhosted.org/packages/d6/8b/ad8b2658895a8ed2b0bc630bf38686fe38b7ff2c619c58953a80e4de3048/prek-0.3.3-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:9512cf370e0d1496503463a4a65621480efb41b487841a9e9ff1661edf14b238", size = 4995072, upload-time = "2026-02-15T13:33:27.417Z"}, + {url = "https://files.pythonhosted.org/packages/fd/b7/0540c101c00882adb9d30319d22d8f879413598269ecc60235e41875efd4/prek-0.3.3-py3-none-win32.whl", hash = "sha256:b2b328c7c6dc14ccdc79785348589aa39850f47baff33d8f199f2dee80ff774c", size = 4293144, upload-time = "2026-02-15T13:33:46.013Z"}, + {url = "https://files.pythonhosted.org/packages/97/c7/e4f11da653093040efba2d835aa0995d78940aea30887287aeaebe34a545/prek-0.3.3-py3-none-win_amd64.whl", hash = "sha256:3d7d7acf7ca8db65ba0943c52326c898f84bab0b1c26a35c87e0d177f574ca5f", size = 4652761, upload-time = "2026-02-15T13:33:32.962Z"}, + {url = "https://files.pythonhosted.org/packages/11/e4/d99dec54c6a5fb2763488bff6078166383169a93f3af27d2edae88379a39/prek-0.3.3-py3-none-win_arm64.whl", hash = "sha256:8aa87ee7628cd74482c0dd6537a3def1f162b25cd642d78b1b35dd3e81817f60", size = 4367520, upload-time = "2026-02-15T13:33:31.664Z"} ] [[package]] -name = "prompt-toolkit" -version = "3.0.52" -source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "wcwidth" }, + {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" } +name = "prompt-toolkit" +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"} +source = {registry = "https://pypi.org/simple"} +version = "3.0.52" 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" }, + {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 = "protobuf" +sdist = {url = "https://files.pythonhosted.org/packages/ba/25/7c72c307aafc96fa87062aa6291d9f7c94836e43214d43722e86037aac02/protobuf-6.33.5.tar.gz", hash = "sha256:6ddcac2a081f8b7b9642c09406bc6a4290128fce5f471cddd165960bb9119e5c", size = 444465, upload-time = "2026-01-29T21:51:33.494Z"} +source = {registry = "https://pypi.org/simple"} version = "6.33.5" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ba/25/7c72c307aafc96fa87062aa6291d9f7c94836e43214d43722e86037aac02/protobuf-6.33.5.tar.gz", hash = "sha256:6ddcac2a081f8b7b9642c09406bc6a4290128fce5f471cddd165960bb9119e5c", size = 444465, upload-time = "2026-01-29T21:51:33.494Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b1/79/af92d0a8369732b027e6d6084251dd8e782c685c72da161bd4a2e00fbabb/protobuf-6.33.5-cp310-abi3-win32.whl", hash = "sha256:d71b040839446bac0f4d162e758bea99c8251161dae9d0983a3b88dee345153b", size = 425769, upload-time = "2026-01-29T21:51:21.751Z" }, - { url = "https://files.pythonhosted.org/packages/55/75/bb9bc917d10e9ee13dee8607eb9ab963b7cf8be607c46e7862c748aa2af7/protobuf-6.33.5-cp310-abi3-win_amd64.whl", hash = "sha256:3093804752167bcab3998bec9f1048baae6e29505adaf1afd14a37bddede533c", size = 437118, upload-time = "2026-01-29T21:51:24.022Z" }, - { url = "https://files.pythonhosted.org/packages/a2/6b/e48dfc1191bc5b52950246275bf4089773e91cb5ba3592621723cdddca62/protobuf-6.33.5-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:a5cb85982d95d906df1e2210e58f8e4f1e3cdc088e52c921a041f9c9a0386de5", size = 427766, upload-time = "2026-01-29T21:51:25.413Z" }, - { url = "https://files.pythonhosted.org/packages/4e/b1/c79468184310de09d75095ed1314b839eb2f72df71097db9d1404a1b2717/protobuf-6.33.5-cp39-abi3-manylinux2014_aarch64.whl", hash = "sha256:9b71e0281f36f179d00cbcb119cb19dec4d14a81393e5ea220f64b286173e190", size = 324638, upload-time = "2026-01-29T21:51:26.423Z" }, - { url = "https://files.pythonhosted.org/packages/c5/f5/65d838092fd01c44d16037953fd4c2cc851e783de9b8f02b27ec4ffd906f/protobuf-6.33.5-cp39-abi3-manylinux2014_s390x.whl", hash = "sha256:8afa18e1d6d20af15b417e728e9f60f3aa108ee76f23c3b2c07a2c3b546d3afd", size = 339411, upload-time = "2026-01-29T21:51:27.446Z" }, - { url = "https://files.pythonhosted.org/packages/9b/53/a9443aa3ca9ba8724fdfa02dd1887c1bcd8e89556b715cfbacca6b63dbec/protobuf-6.33.5-cp39-abi3-manylinux2014_x86_64.whl", hash = "sha256:cbf16ba3350fb7b889fca858fb215967792dc125b35c7976ca4818bee3521cf0", size = 323465, upload-time = "2026-01-29T21:51:28.925Z" }, - { url = "https://files.pythonhosted.org/packages/57/bf/2086963c69bdac3d7cff1cc7ff79b8ce5ea0bec6797a017e1be338a46248/protobuf-6.33.5-py3-none-any.whl", hash = "sha256:69915a973dd0f60f31a08b8318b73eab2bd6a392c79184b3612226b0a3f8ec02", size = 170687, upload-time = "2026-01-29T21:51:32.557Z" }, + {url = "https://files.pythonhosted.org/packages/b1/79/af92d0a8369732b027e6d6084251dd8e782c685c72da161bd4a2e00fbabb/protobuf-6.33.5-cp310-abi3-win32.whl", hash = "sha256:d71b040839446bac0f4d162e758bea99c8251161dae9d0983a3b88dee345153b", size = 425769, upload-time = "2026-01-29T21:51:21.751Z"}, + {url = "https://files.pythonhosted.org/packages/55/75/bb9bc917d10e9ee13dee8607eb9ab963b7cf8be607c46e7862c748aa2af7/protobuf-6.33.5-cp310-abi3-win_amd64.whl", hash = "sha256:3093804752167bcab3998bec9f1048baae6e29505adaf1afd14a37bddede533c", size = 437118, upload-time = "2026-01-29T21:51:24.022Z"}, + {url = "https://files.pythonhosted.org/packages/a2/6b/e48dfc1191bc5b52950246275bf4089773e91cb5ba3592621723cdddca62/protobuf-6.33.5-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:a5cb85982d95d906df1e2210e58f8e4f1e3cdc088e52c921a041f9c9a0386de5", size = 427766, upload-time = "2026-01-29T21:51:25.413Z"}, + {url = "https://files.pythonhosted.org/packages/4e/b1/c79468184310de09d75095ed1314b839eb2f72df71097db9d1404a1b2717/protobuf-6.33.5-cp39-abi3-manylinux2014_aarch64.whl", hash = "sha256:9b71e0281f36f179d00cbcb119cb19dec4d14a81393e5ea220f64b286173e190", size = 324638, upload-time = "2026-01-29T21:51:26.423Z"}, + {url = "https://files.pythonhosted.org/packages/c5/f5/65d838092fd01c44d16037953fd4c2cc851e783de9b8f02b27ec4ffd906f/protobuf-6.33.5-cp39-abi3-manylinux2014_s390x.whl", hash = "sha256:8afa18e1d6d20af15b417e728e9f60f3aa108ee76f23c3b2c07a2c3b546d3afd", size = 339411, upload-time = "2026-01-29T21:51:27.446Z"}, + {url = "https://files.pythonhosted.org/packages/9b/53/a9443aa3ca9ba8724fdfa02dd1887c1bcd8e89556b715cfbacca6b63dbec/protobuf-6.33.5-cp39-abi3-manylinux2014_x86_64.whl", hash = "sha256:cbf16ba3350fb7b889fca858fb215967792dc125b35c7976ca4818bee3521cf0", size = 323465, upload-time = "2026-01-29T21:51:28.925Z"}, + {url = "https://files.pythonhosted.org/packages/57/bf/2086963c69bdac3d7cff1cc7ff79b8ce5ea0bec6797a017e1be338a46248/protobuf-6.33.5-py3-none-any.whl", hash = "sha256:69915a973dd0f60f31a08b8318b73eab2bd6a392c79184b3612226b0a3f8ec02", size = 170687, upload-time = "2026-01-29T21:51:32.557Z"} ] [[package]] name = "ptyprocess" +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"} +source = {registry = "https://pypi.org/simple"} 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" }, + {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" +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"} +source = {registry = "https://pypi.org/simple"} 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" }, + {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 = "pycparser" +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"} +source = {registry = "https://pypi.org/simple"} 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" }, + {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 = "pydantic" -version = "2.12.5" -source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "annotated-types" }, - { name = "pydantic-core" }, - { name = "typing-extensions" }, - { name = "typing-inspection" }, + {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" } +name = "pydantic" +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"} +source = {registry = "https://pypi.org/simple"} +version = "2.12.5" 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" }, + {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]] +dependencies = [ + {name = "typing-extensions"} +] name = "pydantic-core" +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"} +source = {registry = "https://pypi.org/simple"} 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/e8/72/74a989dd9f2084b3d9530b0915fdda64ac48831c30dbf7c72a41a5232db8/pydantic_core-2.41.5-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:a3a52f6156e73e7ccb0f8cced536adccb7042be67cb45f9562e12b319c119da6", size = 2105873, upload-time = "2025-11-04T13:39:31.373Z" }, - { url = "https://files.pythonhosted.org/packages/12/44/37e403fd9455708b3b942949e1d7febc02167662bf1a7da5b78ee1ea2842/pydantic_core-2.41.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7f3bf998340c6d4b0c9a2f02d6a400e51f123b59565d74dc60d252ce888c260b", size = 1899826, upload-time = "2025-11-04T13:39:32.897Z" }, - { url = "https://files.pythonhosted.org/packages/33/7f/1d5cab3ccf44c1935a359d51a8a2a9e1a654b744b5e7f80d41b88d501eec/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:378bec5c66998815d224c9ca994f1e14c0c21cb95d2f52b6021cc0b2a58f2a5a", size = 1917869, upload-time = "2025-11-04T13:39:34.469Z" }, - { url = "https://files.pythonhosted.org/packages/6e/6a/30d94a9674a7fe4f4744052ed6c5e083424510be1e93da5bc47569d11810/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e7b576130c69225432866fe2f4a469a85a54ade141d96fd396dffcf607b558f8", size = 2063890, upload-time = "2025-11-04T13:39:36.053Z" }, - { url = "https://files.pythonhosted.org/packages/50/be/76e5d46203fcb2750e542f32e6c371ffa9b8ad17364cf94bb0818dbfb50c/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6cb58b9c66f7e4179a2d5e0f849c48eff5c1fca560994d6eb6543abf955a149e", size = 2229740, upload-time = "2025-11-04T13:39:37.753Z" }, - { url = "https://files.pythonhosted.org/packages/d3/ee/fed784df0144793489f87db310a6bbf8118d7b630ed07aa180d6067e653a/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:88942d3a3dff3afc8288c21e565e476fc278902ae4d6d134f1eeda118cc830b1", size = 2350021, upload-time = "2025-11-04T13:39:40.94Z" }, - { url = "https://files.pythonhosted.org/packages/c8/be/8fed28dd0a180dca19e72c233cbf58efa36df055e5b9d90d64fd1740b828/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f31d95a179f8d64d90f6831d71fa93290893a33148d890ba15de25642c5d075b", size = 2066378, upload-time = "2025-11-04T13:39:42.523Z" }, - { url = "https://files.pythonhosted.org/packages/b0/3b/698cf8ae1d536a010e05121b4958b1257f0b5522085e335360e53a6b1c8b/pydantic_core-2.41.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c1df3d34aced70add6f867a8cf413e299177e0c22660cc767218373d0779487b", size = 2175761, upload-time = "2025-11-04T13:39:44.553Z" }, - { url = "https://files.pythonhosted.org/packages/b8/ba/15d537423939553116dea94ce02f9c31be0fa9d0b806d427e0308ec17145/pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:4009935984bd36bd2c774e13f9a09563ce8de4abaa7226f5108262fa3e637284", size = 2146303, upload-time = "2025-11-04T13:39:46.238Z" }, - { url = "https://files.pythonhosted.org/packages/58/7f/0de669bf37d206723795f9c90c82966726a2ab06c336deba4735b55af431/pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:34a64bc3441dc1213096a20fe27e8e128bd3ff89921706e83c0b1ac971276594", size = 2340355, upload-time = "2025-11-04T13:39:48.002Z" }, - { url = "https://files.pythonhosted.org/packages/e5/de/e7482c435b83d7e3c3ee5ee4451f6e8973cff0eb6007d2872ce6383f6398/pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c9e19dd6e28fdcaa5a1de679aec4141f691023916427ef9bae8584f9c2fb3b0e", size = 2319875, upload-time = "2025-11-04T13:39:49.705Z" }, - { url = "https://files.pythonhosted.org/packages/fe/e6/8c9e81bb6dd7560e33b9053351c29f30c8194b72f2d6932888581f503482/pydantic_core-2.41.5-cp311-cp311-win32.whl", hash = "sha256:2c010c6ded393148374c0f6f0bf89d206bf3217f201faa0635dcd56bd1520f6b", size = 1987549, upload-time = "2025-11-04T13:39:51.842Z" }, - { url = "https://files.pythonhosted.org/packages/11/66/f14d1d978ea94d1bc21fc98fcf570f9542fe55bfcc40269d4e1a21c19bf7/pydantic_core-2.41.5-cp311-cp311-win_amd64.whl", hash = "sha256:76ee27c6e9c7f16f47db7a94157112a2f3a00e958bc626e2f4ee8bec5c328fbe", size = 2011305, upload-time = "2025-11-04T13:39:53.485Z" }, - { url = "https://files.pythonhosted.org/packages/56/d8/0e271434e8efd03186c5386671328154ee349ff0354d83c74f5caaf096ed/pydantic_core-2.41.5-cp311-cp311-win_arm64.whl", hash = "sha256:4bc36bbc0b7584de96561184ad7f012478987882ebf9f9c389b23f432ea3d90f", size = 1972902, upload-time = "2025-11-04T13:39:56.488Z" }, - { url = "https://files.pythonhosted.org/packages/5f/5d/5f6c63eebb5afee93bcaae4ce9a898f3373ca23df3ccaef086d0233a35a7/pydantic_core-2.41.5-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:f41a7489d32336dbf2199c8c0a215390a751c5b014c2c1c5366e817202e9cdf7", size = 2110990, upload-time = "2025-11-04T13:39:58.079Z" }, - { url = "https://files.pythonhosted.org/packages/aa/32/9c2e8ccb57c01111e0fd091f236c7b371c1bccea0fa85247ac55b1e2b6b6/pydantic_core-2.41.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:070259a8818988b9a84a449a2a7337c7f430a22acc0859c6b110aa7212a6d9c0", size = 1896003, upload-time = "2025-11-04T13:39:59.956Z" }, - { url = "https://files.pythonhosted.org/packages/68/b8/a01b53cb0e59139fbc9e4fda3e9724ede8de279097179be4ff31f1abb65a/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e96cea19e34778f8d59fe40775a7a574d95816eb150850a85a7a4c8f4b94ac69", size = 1919200, upload-time = "2025-11-04T13:40:02.241Z" }, - { url = "https://files.pythonhosted.org/packages/38/de/8c36b5198a29bdaade07b5985e80a233a5ac27137846f3bc2d3b40a47360/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ed2e99c456e3fadd05c991f8f437ef902e00eedf34320ba2b0842bd1c3ca3a75", size = 2052578, upload-time = "2025-11-04T13:40:04.401Z" }, - { url = "https://files.pythonhosted.org/packages/00/b5/0e8e4b5b081eac6cb3dbb7e60a65907549a1ce035a724368c330112adfdd/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:65840751b72fbfd82c3c640cff9284545342a4f1eb1586ad0636955b261b0b05", size = 2208504, upload-time = "2025-11-04T13:40:06.072Z" }, - { url = "https://files.pythonhosted.org/packages/77/56/87a61aad59c7c5b9dc8caad5a41a5545cba3810c3e828708b3d7404f6cef/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e536c98a7626a98feb2d3eaf75944ef6f3dbee447e1f841eae16f2f0a72d8ddc", size = 2335816, upload-time = "2025-11-04T13:40:07.835Z" }, - { url = "https://files.pythonhosted.org/packages/0d/76/941cc9f73529988688a665a5c0ecff1112b3d95ab48f81db5f7606f522d3/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eceb81a8d74f9267ef4081e246ffd6d129da5d87e37a77c9bde550cb04870c1c", size = 2075366, upload-time = "2025-11-04T13:40:09.804Z" }, - { url = "https://files.pythonhosted.org/packages/d3/43/ebef01f69baa07a482844faaa0a591bad1ef129253ffd0cdaa9d8a7f72d3/pydantic_core-2.41.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d38548150c39b74aeeb0ce8ee1d8e82696f4a4e16ddc6de7b1d8823f7de4b9b5", size = 2171698, upload-time = "2025-11-04T13:40:12.004Z" }, - { url = "https://files.pythonhosted.org/packages/b1/87/41f3202e4193e3bacfc2c065fab7706ebe81af46a83d3e27605029c1f5a6/pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c23e27686783f60290e36827f9c626e63154b82b116d7fe9adba1fda36da706c", size = 2132603, upload-time = "2025-11-04T13:40:13.868Z" }, - { url = "https://files.pythonhosted.org/packages/49/7d/4c00df99cb12070b6bccdef4a195255e6020a550d572768d92cc54dba91a/pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:482c982f814460eabe1d3bb0adfdc583387bd4691ef00b90575ca0d2b6fe2294", size = 2329591, upload-time = "2025-11-04T13:40:15.672Z" }, - { url = "https://files.pythonhosted.org/packages/cc/6a/ebf4b1d65d458f3cda6a7335d141305dfa19bdc61140a884d165a8a1bbc7/pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:bfea2a5f0b4d8d43adf9d7b8bf019fb46fdd10a2e5cde477fbcb9d1fa08c68e1", size = 2319068, upload-time = "2025-11-04T13:40:17.532Z" }, - { url = "https://files.pythonhosted.org/packages/49/3b/774f2b5cd4192d5ab75870ce4381fd89cf218af999515baf07e7206753f0/pydantic_core-2.41.5-cp312-cp312-win32.whl", hash = "sha256:b74557b16e390ec12dca509bce9264c3bbd128f8a2c376eaa68003d7f327276d", size = 1985908, upload-time = "2025-11-04T13:40:19.309Z" }, - { url = "https://files.pythonhosted.org/packages/86/45/00173a033c801cacf67c190fef088789394feaf88a98a7035b0e40d53dc9/pydantic_core-2.41.5-cp312-cp312-win_amd64.whl", hash = "sha256:1962293292865bca8e54702b08a4f26da73adc83dd1fcf26fbc875b35d81c815", size = 2020145, upload-time = "2025-11-04T13:40:21.548Z" }, - { url = "https://files.pythonhosted.org/packages/f9/22/91fbc821fa6d261b376a3f73809f907cec5ca6025642c463d3488aad22fb/pydantic_core-2.41.5-cp312-cp312-win_arm64.whl", hash = "sha256:1746d4a3d9a794cacae06a5eaaccb4b8643a131d45fbc9af23e353dc0a5ba5c3", size = 1976179, upload-time = "2025-11-04T13:40:23.393Z" }, - { 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" }, - { url = "https://files.pythonhosted.org/packages/11/72/90fda5ee3b97e51c494938a4a44c3a35a9c96c19bba12372fb9c634d6f57/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:b96d5f26b05d03cc60f11a7761a5ded1741da411e7fe0909e27a5e6a0cb7b034", size = 2115441, upload-time = "2025-11-04T13:42:39.557Z" }, - { url = "https://files.pythonhosted.org/packages/1f/53/8942f884fa33f50794f119012dc6a1a02ac43a56407adaac20463df8e98f/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:634e8609e89ceecea15e2d61bc9ac3718caaaa71963717bf3c8f38bfde64242c", size = 1930291, upload-time = "2025-11-04T13:42:42.169Z" }, - { url = "https://files.pythonhosted.org/packages/79/c8/ecb9ed9cd942bce09fc888ee960b52654fbdbede4ba6c2d6e0d3b1d8b49c/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:93e8740d7503eb008aa2df04d3b9735f845d43ae845e6dcd2be0b55a2da43cd2", size = 1948632, upload-time = "2025-11-04T13:42:44.564Z" }, - { url = "https://files.pythonhosted.org/packages/2e/1b/687711069de7efa6af934e74f601e2a4307365e8fdc404703afc453eab26/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f15489ba13d61f670dcc96772e733aad1a6f9c429cc27574c6cdaed82d0146ad", size = 2138905, upload-time = "2025-11-04T13:42:47.156Z" }, - { url = "https://files.pythonhosted.org/packages/09/32/59b0c7e63e277fa7911c2fc70ccfb45ce4b98991e7ef37110663437005af/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:7da7087d756b19037bc2c06edc6c170eeef3c3bafcb8f532ff17d64dc427adfd", size = 2110495, upload-time = "2025-11-04T13:42:49.689Z" }, - { url = "https://files.pythonhosted.org/packages/aa/81/05e400037eaf55ad400bcd318c05bb345b57e708887f07ddb2d20e3f0e98/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:aabf5777b5c8ca26f7824cb4a120a740c9588ed58df9b2d196ce92fba42ff8dc", size = 1915388, upload-time = "2025-11-04T13:42:52.215Z" }, - { url = "https://files.pythonhosted.org/packages/6e/0d/e3549b2399f71d56476b77dbf3cf8937cec5cd70536bdc0e374a421d0599/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c007fe8a43d43b3969e8469004e9845944f1a80e6acd47c150856bb87f230c56", size = 1942879, upload-time = "2025-11-04T13:42:56.483Z" }, - { url = "https://files.pythonhosted.org/packages/f7/07/34573da085946b6a313d7c42f82f16e8920bfd730665de2d11c0c37a74b5/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:76d0819de158cd855d1cbb8fcafdf6f5cf1eb8e470abe056d5d161106e38062b", size = 2139017, upload-time = "2025-11-04T13:42:59.471Z" }, - { url = "https://files.pythonhosted.org/packages/5f/9b/1b3f0e9f9305839d7e84912f9e8bfbd191ed1b1ef48083609f0dabde978c/pydantic_core-2.41.5-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b2379fa7ed44ddecb5bfe4e48577d752db9fc10be00a6b7446e9663ba143de26", size = 2101980, upload-time = "2025-11-04T13:43:25.97Z" }, - { url = "https://files.pythonhosted.org/packages/a4/ed/d71fefcb4263df0da6a85b5d8a7508360f2f2e9b3bf5814be9c8bccdccc1/pydantic_core-2.41.5-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:266fb4cbf5e3cbd0b53669a6d1b039c45e3ce651fd5442eff4d07c2cc8d66808", size = 1923865, upload-time = "2025-11-04T13:43:28.763Z" }, - { url = "https://files.pythonhosted.org/packages/ce/3a/626b38db460d675f873e4444b4bb030453bbe7b4ba55df821d026a0493c4/pydantic_core-2.41.5-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58133647260ea01e4d0500089a8c4f07bd7aa6ce109682b1426394988d8aaacc", size = 2134256, upload-time = "2025-11-04T13:43:31.71Z" }, - { url = "https://files.pythonhosted.org/packages/83/d9/8412d7f06f616bbc053d30cb4e5f76786af3221462ad5eee1f202021eb4e/pydantic_core-2.41.5-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:287dad91cfb551c363dc62899a80e9e14da1f0e2b6ebde82c806612ca2a13ef1", size = 2174762, upload-time = "2025-11-04T13:43:34.744Z" }, - { url = "https://files.pythonhosted.org/packages/55/4c/162d906b8e3ba3a99354e20faa1b49a85206c47de97a639510a0e673f5da/pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:03b77d184b9eb40240ae9fd676ca364ce1085f203e1b1256f8ab9984dca80a84", size = 2143141, upload-time = "2025-11-04T13:43:37.701Z" }, - { url = "https://files.pythonhosted.org/packages/1f/f2/f11dd73284122713f5f89fc940f370d035fa8e1e078d446b3313955157fe/pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:a668ce24de96165bb239160b3d854943128f4334822900534f2fe947930e5770", size = 2330317, upload-time = "2025-11-04T13:43:40.406Z" }, - { url = "https://files.pythonhosted.org/packages/88/9d/b06ca6acfe4abb296110fb1273a4d848a0bfb2ff65f3ee92127b3244e16b/pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f14f8f046c14563f8eb3f45f499cc658ab8d10072961e07225e507adb700e93f", size = 2316992, upload-time = "2025-11-04T13:43:43.602Z" }, - { url = "https://files.pythonhosted.org/packages/36/c7/cfc8e811f061c841d7990b0201912c3556bfeb99cdcb7ed24adc8d6f8704/pydantic_core-2.41.5-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:56121965f7a4dc965bff783d70b907ddf3d57f6eba29b6d2e5dabfaf07799c51", size = 2145302, upload-time = "2025-11-04T13:43:46.64Z" }, +wheels = [ + {url = "https://files.pythonhosted.org/packages/e8/72/74a989dd9f2084b3d9530b0915fdda64ac48831c30dbf7c72a41a5232db8/pydantic_core-2.41.5-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:a3a52f6156e73e7ccb0f8cced536adccb7042be67cb45f9562e12b319c119da6", size = 2105873, upload-time = "2025-11-04T13:39:31.373Z"}, + {url = "https://files.pythonhosted.org/packages/12/44/37e403fd9455708b3b942949e1d7febc02167662bf1a7da5b78ee1ea2842/pydantic_core-2.41.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7f3bf998340c6d4b0c9a2f02d6a400e51f123b59565d74dc60d252ce888c260b", size = 1899826, upload-time = "2025-11-04T13:39:32.897Z"}, + {url = "https://files.pythonhosted.org/packages/33/7f/1d5cab3ccf44c1935a359d51a8a2a9e1a654b744b5e7f80d41b88d501eec/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:378bec5c66998815d224c9ca994f1e14c0c21cb95d2f52b6021cc0b2a58f2a5a", size = 1917869, upload-time = "2025-11-04T13:39:34.469Z"}, + {url = "https://files.pythonhosted.org/packages/6e/6a/30d94a9674a7fe4f4744052ed6c5e083424510be1e93da5bc47569d11810/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e7b576130c69225432866fe2f4a469a85a54ade141d96fd396dffcf607b558f8", size = 2063890, upload-time = "2025-11-04T13:39:36.053Z"}, + {url = "https://files.pythonhosted.org/packages/50/be/76e5d46203fcb2750e542f32e6c371ffa9b8ad17364cf94bb0818dbfb50c/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6cb58b9c66f7e4179a2d5e0f849c48eff5c1fca560994d6eb6543abf955a149e", size = 2229740, upload-time = "2025-11-04T13:39:37.753Z"}, + {url = "https://files.pythonhosted.org/packages/d3/ee/fed784df0144793489f87db310a6bbf8118d7b630ed07aa180d6067e653a/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:88942d3a3dff3afc8288c21e565e476fc278902ae4d6d134f1eeda118cc830b1", size = 2350021, upload-time = "2025-11-04T13:39:40.94Z"}, + {url = "https://files.pythonhosted.org/packages/c8/be/8fed28dd0a180dca19e72c233cbf58efa36df055e5b9d90d64fd1740b828/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f31d95a179f8d64d90f6831d71fa93290893a33148d890ba15de25642c5d075b", size = 2066378, upload-time = "2025-11-04T13:39:42.523Z"}, + {url = "https://files.pythonhosted.org/packages/b0/3b/698cf8ae1d536a010e05121b4958b1257f0b5522085e335360e53a6b1c8b/pydantic_core-2.41.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c1df3d34aced70add6f867a8cf413e299177e0c22660cc767218373d0779487b", size = 2175761, upload-time = "2025-11-04T13:39:44.553Z"}, + {url = "https://files.pythonhosted.org/packages/b8/ba/15d537423939553116dea94ce02f9c31be0fa9d0b806d427e0308ec17145/pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:4009935984bd36bd2c774e13f9a09563ce8de4abaa7226f5108262fa3e637284", size = 2146303, upload-time = "2025-11-04T13:39:46.238Z"}, + {url = "https://files.pythonhosted.org/packages/58/7f/0de669bf37d206723795f9c90c82966726a2ab06c336deba4735b55af431/pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:34a64bc3441dc1213096a20fe27e8e128bd3ff89921706e83c0b1ac971276594", size = 2340355, upload-time = "2025-11-04T13:39:48.002Z"}, + {url = "https://files.pythonhosted.org/packages/e5/de/e7482c435b83d7e3c3ee5ee4451f6e8973cff0eb6007d2872ce6383f6398/pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c9e19dd6e28fdcaa5a1de679aec4141f691023916427ef9bae8584f9c2fb3b0e", size = 2319875, upload-time = "2025-11-04T13:39:49.705Z"}, + {url = "https://files.pythonhosted.org/packages/fe/e6/8c9e81bb6dd7560e33b9053351c29f30c8194b72f2d6932888581f503482/pydantic_core-2.41.5-cp311-cp311-win32.whl", hash = "sha256:2c010c6ded393148374c0f6f0bf89d206bf3217f201faa0635dcd56bd1520f6b", size = 1987549, upload-time = "2025-11-04T13:39:51.842Z"}, + {url = "https://files.pythonhosted.org/packages/11/66/f14d1d978ea94d1bc21fc98fcf570f9542fe55bfcc40269d4e1a21c19bf7/pydantic_core-2.41.5-cp311-cp311-win_amd64.whl", hash = "sha256:76ee27c6e9c7f16f47db7a94157112a2f3a00e958bc626e2f4ee8bec5c328fbe", size = 2011305, upload-time = "2025-11-04T13:39:53.485Z"}, + {url = "https://files.pythonhosted.org/packages/56/d8/0e271434e8efd03186c5386671328154ee349ff0354d83c74f5caaf096ed/pydantic_core-2.41.5-cp311-cp311-win_arm64.whl", hash = "sha256:4bc36bbc0b7584de96561184ad7f012478987882ebf9f9c389b23f432ea3d90f", size = 1972902, upload-time = "2025-11-04T13:39:56.488Z"}, + {url = "https://files.pythonhosted.org/packages/5f/5d/5f6c63eebb5afee93bcaae4ce9a898f3373ca23df3ccaef086d0233a35a7/pydantic_core-2.41.5-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:f41a7489d32336dbf2199c8c0a215390a751c5b014c2c1c5366e817202e9cdf7", size = 2110990, upload-time = "2025-11-04T13:39:58.079Z"}, + {url = "https://files.pythonhosted.org/packages/aa/32/9c2e8ccb57c01111e0fd091f236c7b371c1bccea0fa85247ac55b1e2b6b6/pydantic_core-2.41.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:070259a8818988b9a84a449a2a7337c7f430a22acc0859c6b110aa7212a6d9c0", size = 1896003, upload-time = "2025-11-04T13:39:59.956Z"}, + {url = "https://files.pythonhosted.org/packages/68/b8/a01b53cb0e59139fbc9e4fda3e9724ede8de279097179be4ff31f1abb65a/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e96cea19e34778f8d59fe40775a7a574d95816eb150850a85a7a4c8f4b94ac69", size = 1919200, upload-time = "2025-11-04T13:40:02.241Z"}, + {url = "https://files.pythonhosted.org/packages/38/de/8c36b5198a29bdaade07b5985e80a233a5ac27137846f3bc2d3b40a47360/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ed2e99c456e3fadd05c991f8f437ef902e00eedf34320ba2b0842bd1c3ca3a75", size = 2052578, upload-time = "2025-11-04T13:40:04.401Z"}, + {url = "https://files.pythonhosted.org/packages/00/b5/0e8e4b5b081eac6cb3dbb7e60a65907549a1ce035a724368c330112adfdd/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:65840751b72fbfd82c3c640cff9284545342a4f1eb1586ad0636955b261b0b05", size = 2208504, upload-time = "2025-11-04T13:40:06.072Z"}, + {url = "https://files.pythonhosted.org/packages/77/56/87a61aad59c7c5b9dc8caad5a41a5545cba3810c3e828708b3d7404f6cef/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e536c98a7626a98feb2d3eaf75944ef6f3dbee447e1f841eae16f2f0a72d8ddc", size = 2335816, upload-time = "2025-11-04T13:40:07.835Z"}, + {url = "https://files.pythonhosted.org/packages/0d/76/941cc9f73529988688a665a5c0ecff1112b3d95ab48f81db5f7606f522d3/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eceb81a8d74f9267ef4081e246ffd6d129da5d87e37a77c9bde550cb04870c1c", size = 2075366, upload-time = "2025-11-04T13:40:09.804Z"}, + {url = "https://files.pythonhosted.org/packages/d3/43/ebef01f69baa07a482844faaa0a591bad1ef129253ffd0cdaa9d8a7f72d3/pydantic_core-2.41.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d38548150c39b74aeeb0ce8ee1d8e82696f4a4e16ddc6de7b1d8823f7de4b9b5", size = 2171698, upload-time = "2025-11-04T13:40:12.004Z"}, + {url = "https://files.pythonhosted.org/packages/b1/87/41f3202e4193e3bacfc2c065fab7706ebe81af46a83d3e27605029c1f5a6/pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c23e27686783f60290e36827f9c626e63154b82b116d7fe9adba1fda36da706c", size = 2132603, upload-time = "2025-11-04T13:40:13.868Z"}, + {url = "https://files.pythonhosted.org/packages/49/7d/4c00df99cb12070b6bccdef4a195255e6020a550d572768d92cc54dba91a/pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:482c982f814460eabe1d3bb0adfdc583387bd4691ef00b90575ca0d2b6fe2294", size = 2329591, upload-time = "2025-11-04T13:40:15.672Z"}, + {url = "https://files.pythonhosted.org/packages/cc/6a/ebf4b1d65d458f3cda6a7335d141305dfa19bdc61140a884d165a8a1bbc7/pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:bfea2a5f0b4d8d43adf9d7b8bf019fb46fdd10a2e5cde477fbcb9d1fa08c68e1", size = 2319068, upload-time = "2025-11-04T13:40:17.532Z"}, + {url = "https://files.pythonhosted.org/packages/49/3b/774f2b5cd4192d5ab75870ce4381fd89cf218af999515baf07e7206753f0/pydantic_core-2.41.5-cp312-cp312-win32.whl", hash = "sha256:b74557b16e390ec12dca509bce9264c3bbd128f8a2c376eaa68003d7f327276d", size = 1985908, upload-time = "2025-11-04T13:40:19.309Z"}, + {url = "https://files.pythonhosted.org/packages/86/45/00173a033c801cacf67c190fef088789394feaf88a98a7035b0e40d53dc9/pydantic_core-2.41.5-cp312-cp312-win_amd64.whl", hash = "sha256:1962293292865bca8e54702b08a4f26da73adc83dd1fcf26fbc875b35d81c815", size = 2020145, upload-time = "2025-11-04T13:40:21.548Z"}, + {url = "https://files.pythonhosted.org/packages/f9/22/91fbc821fa6d261b376a3f73809f907cec5ca6025642c463d3488aad22fb/pydantic_core-2.41.5-cp312-cp312-win_arm64.whl", hash = "sha256:1746d4a3d9a794cacae06a5eaaccb4b8643a131d45fbc9af23e353dc0a5ba5c3", size = 1976179, upload-time = "2025-11-04T13:40:23.393Z"}, + {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"}, + {url = "https://files.pythonhosted.org/packages/11/72/90fda5ee3b97e51c494938a4a44c3a35a9c96c19bba12372fb9c634d6f57/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:b96d5f26b05d03cc60f11a7761a5ded1741da411e7fe0909e27a5e6a0cb7b034", size = 2115441, upload-time = "2025-11-04T13:42:39.557Z"}, + {url = "https://files.pythonhosted.org/packages/1f/53/8942f884fa33f50794f119012dc6a1a02ac43a56407adaac20463df8e98f/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:634e8609e89ceecea15e2d61bc9ac3718caaaa71963717bf3c8f38bfde64242c", size = 1930291, upload-time = "2025-11-04T13:42:42.169Z"}, + {url = "https://files.pythonhosted.org/packages/79/c8/ecb9ed9cd942bce09fc888ee960b52654fbdbede4ba6c2d6e0d3b1d8b49c/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:93e8740d7503eb008aa2df04d3b9735f845d43ae845e6dcd2be0b55a2da43cd2", size = 1948632, upload-time = "2025-11-04T13:42:44.564Z"}, + {url = "https://files.pythonhosted.org/packages/2e/1b/687711069de7efa6af934e74f601e2a4307365e8fdc404703afc453eab26/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f15489ba13d61f670dcc96772e733aad1a6f9c429cc27574c6cdaed82d0146ad", size = 2138905, upload-time = "2025-11-04T13:42:47.156Z"}, + {url = "https://files.pythonhosted.org/packages/09/32/59b0c7e63e277fa7911c2fc70ccfb45ce4b98991e7ef37110663437005af/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:7da7087d756b19037bc2c06edc6c170eeef3c3bafcb8f532ff17d64dc427adfd", size = 2110495, upload-time = "2025-11-04T13:42:49.689Z"}, + {url = "https://files.pythonhosted.org/packages/aa/81/05e400037eaf55ad400bcd318c05bb345b57e708887f07ddb2d20e3f0e98/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:aabf5777b5c8ca26f7824cb4a120a740c9588ed58df9b2d196ce92fba42ff8dc", size = 1915388, upload-time = "2025-11-04T13:42:52.215Z"}, + {url = "https://files.pythonhosted.org/packages/6e/0d/e3549b2399f71d56476b77dbf3cf8937cec5cd70536bdc0e374a421d0599/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c007fe8a43d43b3969e8469004e9845944f1a80e6acd47c150856bb87f230c56", size = 1942879, upload-time = "2025-11-04T13:42:56.483Z"}, + {url = "https://files.pythonhosted.org/packages/f7/07/34573da085946b6a313d7c42f82f16e8920bfd730665de2d11c0c37a74b5/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:76d0819de158cd855d1cbb8fcafdf6f5cf1eb8e470abe056d5d161106e38062b", size = 2139017, upload-time = "2025-11-04T13:42:59.471Z"}, + {url = "https://files.pythonhosted.org/packages/5f/9b/1b3f0e9f9305839d7e84912f9e8bfbd191ed1b1ef48083609f0dabde978c/pydantic_core-2.41.5-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b2379fa7ed44ddecb5bfe4e48577d752db9fc10be00a6b7446e9663ba143de26", size = 2101980, upload-time = "2025-11-04T13:43:25.97Z"}, + {url = "https://files.pythonhosted.org/packages/a4/ed/d71fefcb4263df0da6a85b5d8a7508360f2f2e9b3bf5814be9c8bccdccc1/pydantic_core-2.41.5-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:266fb4cbf5e3cbd0b53669a6d1b039c45e3ce651fd5442eff4d07c2cc8d66808", size = 1923865, upload-time = "2025-11-04T13:43:28.763Z"}, + {url = "https://files.pythonhosted.org/packages/ce/3a/626b38db460d675f873e4444b4bb030453bbe7b4ba55df821d026a0493c4/pydantic_core-2.41.5-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58133647260ea01e4d0500089a8c4f07bd7aa6ce109682b1426394988d8aaacc", size = 2134256, upload-time = "2025-11-04T13:43:31.71Z"}, + {url = "https://files.pythonhosted.org/packages/83/d9/8412d7f06f616bbc053d30cb4e5f76786af3221462ad5eee1f202021eb4e/pydantic_core-2.41.5-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:287dad91cfb551c363dc62899a80e9e14da1f0e2b6ebde82c806612ca2a13ef1", size = 2174762, upload-time = "2025-11-04T13:43:34.744Z"}, + {url = "https://files.pythonhosted.org/packages/55/4c/162d906b8e3ba3a99354e20faa1b49a85206c47de97a639510a0e673f5da/pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:03b77d184b9eb40240ae9fd676ca364ce1085f203e1b1256f8ab9984dca80a84", size = 2143141, upload-time = "2025-11-04T13:43:37.701Z"}, + {url = "https://files.pythonhosted.org/packages/1f/f2/f11dd73284122713f5f89fc940f370d035fa8e1e078d446b3313955157fe/pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:a668ce24de96165bb239160b3d854943128f4334822900534f2fe947930e5770", size = 2330317, upload-time = "2025-11-04T13:43:40.406Z"}, + {url = "https://files.pythonhosted.org/packages/88/9d/b06ca6acfe4abb296110fb1273a4d848a0bfb2ff65f3ee92127b3244e16b/pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f14f8f046c14563f8eb3f45f499cc658ab8d10072961e07225e507adb700e93f", size = 2316992, upload-time = "2025-11-04T13:43:43.602Z"}, + {url = "https://files.pythonhosted.org/packages/36/c7/cfc8e811f061c841d7990b0201912c3556bfeb99cdcb7ed24adc8d6f8704/pydantic_core-2.41.5-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:56121965f7a4dc965bff783d70b907ddf3d57f6eba29b6d2e5dabfaf07799c51", size = 2145302, upload-time = "2025-11-04T13:43:46.64Z"} ] [[package]] name = "pygments" +sdist = {url = "https://files.pythonhosted.org/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631, upload-time = "2025-06-21T13:39:12.283Z"} +source = {registry = "https://pypi.org/simple"} version = "2.19.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631, upload-time = "2025-06-21T13:39:12.283Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" }, + {url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z"} ] [[package]] name = "pyproject-hooks" +sdist = {url = "https://files.pythonhosted.org/packages/e7/82/28175b2414effca1cdac8dc99f76d660e7a4fb0ceefa4b4ab8f5f6742925/pyproject_hooks-1.2.0.tar.gz", hash = "sha256:1e859bd5c40fae9448642dd871adf459e5e2084186e8d2c2a79a824c970da1f8", size = 19228, upload-time = "2024-09-29T09:24:13.293Z"} +source = {registry = "https://pypi.org/simple"} version = "1.2.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e7/82/28175b2414effca1cdac8dc99f76d660e7a4fb0ceefa4b4ab8f5f6742925/pyproject_hooks-1.2.0.tar.gz", hash = "sha256:1e859bd5c40fae9448642dd871adf459e5e2084186e8d2c2a79a824c970da1f8", size = 19228, upload-time = "2024-09-29T09:24:13.293Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl", hash = "sha256:9e5c6bfa8dcc30091c74b0cf803c81fdd29d94f01992a7707bc97babb1141913", size = 10216, upload-time = "2024-09-29T09:24:11.978Z" }, + {url = "https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl", hash = "sha256:9e5c6bfa8dcc30091c74b0cf803c81fdd29d94f01992a7707bc97babb1141913", size = 10216, upload-time = "2024-09-29T09:24:11.978Z"} ] [[package]] name = "pyrsistent" +sdist = {url = "https://files.pythonhosted.org/packages/ce/3a/5031723c09068e9c8c2f0bc25c3a9245f2b1d1aea8396c787a408f2b95ca/pyrsistent-0.20.0.tar.gz", hash = "sha256:4c48f78f62ab596c679086084d0dd13254ae4f3d6c72a83ffdf5ebdef8f265a4", size = 103642, upload-time = "2023-10-25T21:06:56.342Z"} +source = {registry = "https://pypi.org/simple"} version = "0.20.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ce/3a/5031723c09068e9c8c2f0bc25c3a9245f2b1d1aea8396c787a408f2b95ca/pyrsistent-0.20.0.tar.gz", hash = "sha256:4c48f78f62ab596c679086084d0dd13254ae4f3d6c72a83ffdf5ebdef8f265a4", size = 103642, upload-time = "2023-10-25T21:06:56.342Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/df/63/7544dc7d0953294882a5c587fb1b10a26e0c23d9b92281a14c2514bac1f7/pyrsistent-0.20.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0f3b1bcaa1f0629c978b355a7c37acd58907390149b7311b5db1b37648eb6958", size = 83481, upload-time = "2023-10-25T21:06:15.238Z" }, - { url = "https://files.pythonhosted.org/packages/ae/a0/49249bc14d71b1bf2ffe89703acfa86f2017c25cfdabcaea532b8c8a5810/pyrsistent-0.20.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5cdd7ef1ea7a491ae70d826b6cc64868de09a1d5ff9ef8d574250d0940e275b8", size = 120222, upload-time = "2023-10-25T21:06:17.144Z" }, - { url = "https://files.pythonhosted.org/packages/a1/94/9808e8c9271424120289b9028a657da336ad7e43da0647f62e4f6011d19b/pyrsistent-0.20.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cae40a9e3ce178415040a0383f00e8d68b569e97f31928a3a8ad37e3fde6df6a", size = 120002, upload-time = "2023-10-25T21:06:18.727Z" }, - { url = "https://files.pythonhosted.org/packages/3f/f6/9ecfb78b2fc8e2540546db0fe19df1fae0f56664a5958c21ff8861b0f8da/pyrsistent-0.20.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6288b3fa6622ad8a91e6eb759cfc48ff3089e7c17fb1d4c59a919769314af224", size = 116850, upload-time = "2023-10-25T21:06:20.424Z" }, - { url = "https://files.pythonhosted.org/packages/83/c8/e6d28bc27a0719f8eaae660357df9757d6e9ca9be2691595721de9e8adfc/pyrsistent-0.20.0-cp311-cp311-win32.whl", hash = "sha256:7d29c23bdf6e5438c755b941cef867ec2a4a172ceb9f50553b6ed70d50dfd656", size = 60775, upload-time = "2023-10-25T21:06:21.815Z" }, - { url = "https://files.pythonhosted.org/packages/98/87/c6ef52ff30388f357922d08de012abdd3dc61e09311d88967bdae23ab657/pyrsistent-0.20.0-cp311-cp311-win_amd64.whl", hash = "sha256:59a89bccd615551391f3237e00006a26bcf98a4d18623a19909a2c48b8e986ee", size = 63306, upload-time = "2023-10-25T21:06:22.874Z" }, - { url = "https://files.pythonhosted.org/packages/15/ee/ff2ed52032ac1ce2e7ba19e79bd5b05d152ebfb77956cf08fcd6e8d760ea/pyrsistent-0.20.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:09848306523a3aba463c4b49493a760e7a6ca52e4826aa100ee99d8d39b7ad1e", size = 83537, upload-time = "2023-10-25T21:06:24.17Z" }, - { url = "https://files.pythonhosted.org/packages/80/f1/338d0050b24c3132bcfc79b68c3a5f54bce3d213ecef74d37e988b971d8a/pyrsistent-0.20.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a14798c3005ec892bbada26485c2eea3b54109cb2533713e355c806891f63c5e", size = 122615, upload-time = "2023-10-25T21:06:25.815Z" }, - { url = "https://files.pythonhosted.org/packages/07/3a/e56d6431b713518094fae6ff833a04a6f49ad0fbe25fb7c0dc7408e19d20/pyrsistent-0.20.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b14decb628fac50db5e02ee5a35a9c0772d20277824cfe845c8a8b717c15daa3", size = 122335, upload-time = "2023-10-25T21:06:28.631Z" }, - { url = "https://files.pythonhosted.org/packages/4a/bb/5f40a4d5e985a43b43f607250e766cdec28904682c3505eb0bd343a4b7db/pyrsistent-0.20.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e2c116cc804d9b09ce9814d17df5edf1df0c624aba3b43bc1ad90411487036d", size = 118510, upload-time = "2023-10-25T21:06:30.718Z" }, - { url = "https://files.pythonhosted.org/packages/1c/13/e6a22f40f5800af116c02c28e29f15c06aa41cb2036f6a64ab124647f28b/pyrsistent-0.20.0-cp312-cp312-win32.whl", hash = "sha256:e78d0c7c1e99a4a45c99143900ea0546025e41bb59ebc10182e947cf1ece9174", size = 60865, upload-time = "2023-10-25T21:06:32.742Z" }, - { url = "https://files.pythonhosted.org/packages/75/ef/2fa3b55023ec07c22682c957808f9a41836da4cd006b5f55ec76bf0fbfa6/pyrsistent-0.20.0-cp312-cp312-win_amd64.whl", hash = "sha256:4021a7f963d88ccd15b523787d18ed5e5269ce57aa4037146a2377ff607ae87d", size = 63239, upload-time = "2023-10-25T21:06:34.035Z" }, - { url = "https://files.pythonhosted.org/packages/23/88/0acd180010aaed4987c85700b7cc17f9505f3edb4e5873e4dc67f613e338/pyrsistent-0.20.0-py3-none-any.whl", hash = "sha256:c55acc4733aad6560a7f5f818466631f07efc001fd023f34a6c203f8b6df0f0b", size = 58106, upload-time = "2023-10-25T21:06:54.387Z" }, + {url = "https://files.pythonhosted.org/packages/df/63/7544dc7d0953294882a5c587fb1b10a26e0c23d9b92281a14c2514bac1f7/pyrsistent-0.20.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0f3b1bcaa1f0629c978b355a7c37acd58907390149b7311b5db1b37648eb6958", size = 83481, upload-time = "2023-10-25T21:06:15.238Z"}, + {url = "https://files.pythonhosted.org/packages/ae/a0/49249bc14d71b1bf2ffe89703acfa86f2017c25cfdabcaea532b8c8a5810/pyrsistent-0.20.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5cdd7ef1ea7a491ae70d826b6cc64868de09a1d5ff9ef8d574250d0940e275b8", size = 120222, upload-time = "2023-10-25T21:06:17.144Z"}, + {url = "https://files.pythonhosted.org/packages/a1/94/9808e8c9271424120289b9028a657da336ad7e43da0647f62e4f6011d19b/pyrsistent-0.20.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cae40a9e3ce178415040a0383f00e8d68b569e97f31928a3a8ad37e3fde6df6a", size = 120002, upload-time = "2023-10-25T21:06:18.727Z"}, + {url = "https://files.pythonhosted.org/packages/3f/f6/9ecfb78b2fc8e2540546db0fe19df1fae0f56664a5958c21ff8861b0f8da/pyrsistent-0.20.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6288b3fa6622ad8a91e6eb759cfc48ff3089e7c17fb1d4c59a919769314af224", size = 116850, upload-time = "2023-10-25T21:06:20.424Z"}, + {url = "https://files.pythonhosted.org/packages/83/c8/e6d28bc27a0719f8eaae660357df9757d6e9ca9be2691595721de9e8adfc/pyrsistent-0.20.0-cp311-cp311-win32.whl", hash = "sha256:7d29c23bdf6e5438c755b941cef867ec2a4a172ceb9f50553b6ed70d50dfd656", size = 60775, upload-time = "2023-10-25T21:06:21.815Z"}, + {url = "https://files.pythonhosted.org/packages/98/87/c6ef52ff30388f357922d08de012abdd3dc61e09311d88967bdae23ab657/pyrsistent-0.20.0-cp311-cp311-win_amd64.whl", hash = "sha256:59a89bccd615551391f3237e00006a26bcf98a4d18623a19909a2c48b8e986ee", size = 63306, upload-time = "2023-10-25T21:06:22.874Z"}, + {url = "https://files.pythonhosted.org/packages/15/ee/ff2ed52032ac1ce2e7ba19e79bd5b05d152ebfb77956cf08fcd6e8d760ea/pyrsistent-0.20.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:09848306523a3aba463c4b49493a760e7a6ca52e4826aa100ee99d8d39b7ad1e", size = 83537, upload-time = "2023-10-25T21:06:24.17Z"}, + {url = "https://files.pythonhosted.org/packages/80/f1/338d0050b24c3132bcfc79b68c3a5f54bce3d213ecef74d37e988b971d8a/pyrsistent-0.20.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a14798c3005ec892bbada26485c2eea3b54109cb2533713e355c806891f63c5e", size = 122615, upload-time = "2023-10-25T21:06:25.815Z"}, + {url = "https://files.pythonhosted.org/packages/07/3a/e56d6431b713518094fae6ff833a04a6f49ad0fbe25fb7c0dc7408e19d20/pyrsistent-0.20.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b14decb628fac50db5e02ee5a35a9c0772d20277824cfe845c8a8b717c15daa3", size = 122335, upload-time = "2023-10-25T21:06:28.631Z"}, + {url = "https://files.pythonhosted.org/packages/4a/bb/5f40a4d5e985a43b43f607250e766cdec28904682c3505eb0bd343a4b7db/pyrsistent-0.20.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e2c116cc804d9b09ce9814d17df5edf1df0c624aba3b43bc1ad90411487036d", size = 118510, upload-time = "2023-10-25T21:06:30.718Z"}, + {url = "https://files.pythonhosted.org/packages/1c/13/e6a22f40f5800af116c02c28e29f15c06aa41cb2036f6a64ab124647f28b/pyrsistent-0.20.0-cp312-cp312-win32.whl", hash = "sha256:e78d0c7c1e99a4a45c99143900ea0546025e41bb59ebc10182e947cf1ece9174", size = 60865, upload-time = "2023-10-25T21:06:32.742Z"}, + {url = "https://files.pythonhosted.org/packages/75/ef/2fa3b55023ec07c22682c957808f9a41836da4cd006b5f55ec76bf0fbfa6/pyrsistent-0.20.0-cp312-cp312-win_amd64.whl", hash = "sha256:4021a7f963d88ccd15b523787d18ed5e5269ce57aa4037146a2377ff607ae87d", size = 63239, upload-time = "2023-10-25T21:06:34.035Z"}, + {url = "https://files.pythonhosted.org/packages/23/88/0acd180010aaed4987c85700b7cc17f9505f3edb4e5873e4dc67f613e338/pyrsistent-0.20.0-py3-none-any.whl", hash = "sha256:c55acc4733aad6560a7f5f818466631f07efc001fd023f34a6c203f8b6df0f0b", size = 58106, upload-time = "2023-10-25T21:06:54.387Z"} ] [[package]] -name = "pytest" -version = "9.0.2" -source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "colorama", marker = "sys_platform == 'win32'" }, - { name = "iniconfig" }, - { name = "packaging" }, - { name = "pluggy" }, - { name = "pygments" }, + {name = "colorama", marker = "sys_platform == 'win32'"}, + {name = "iniconfig"}, + {name = "packaging"}, + {name = "pluggy"}, + {name = "pygments"} ] -sdist = { url = "https://files.pythonhosted.org/packages/d1/db/7ef3487e0fb0049ddb5ce41d3a49c235bf9ad299b6a25d5780a89f19230f/pytest-9.0.2.tar.gz", hash = "sha256:75186651a92bd89611d1d9fc20f0b4345fd827c41ccd5c299a868a05d70edf11", size = 1568901, upload-time = "2025-12-06T21:30:51.014Z" } +name = "pytest" +sdist = {url = "https://files.pythonhosted.org/packages/d1/db/7ef3487e0fb0049ddb5ce41d3a49c235bf9ad299b6a25d5780a89f19230f/pytest-9.0.2.tar.gz", hash = "sha256:75186651a92bd89611d1d9fc20f0b4345fd827c41ccd5c299a868a05d70edf11", size = 1568901, upload-time = "2025-12-06T21:30:51.014Z"} +source = {registry = "https://pypi.org/simple"} +version = "9.0.2" wheels = [ - { url = "https://files.pythonhosted.org/packages/3b/ab/b3226f0bd7cdcf710fbede2b3548584366da3b19b5021e74f5bde2a8fa3f/pytest-9.0.2-py3-none-any.whl", hash = "sha256:711ffd45bf766d5264d487b917733b453d917afd2b0ad65223959f59089f875b", size = 374801, upload-time = "2025-12-06T21:30:49.154Z" }, + {url = "https://files.pythonhosted.org/packages/3b/ab/b3226f0bd7cdcf710fbede2b3548584366da3b19b5021e74f5bde2a8fa3f/pytest-9.0.2-py3-none-any.whl", hash = "sha256:711ffd45bf766d5264d487b917733b453d917afd2b0ad65223959f59089f875b", size = 374801, upload-time = "2025-12-06T21:30:49.154Z"} ] [[package]] -name = "pytest-xdist" -version = "3.8.0" -source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "execnet" }, - { name = "pytest" }, + {name = "execnet"}, + {name = "pytest"} ] -sdist = { url = "https://files.pythonhosted.org/packages/78/b4/439b179d1ff526791eb921115fca8e44e596a13efeda518b9d845a619450/pytest_xdist-3.8.0.tar.gz", hash = "sha256:7e578125ec9bc6050861aa93f2d59f1d8d085595d6551c2c90b6f4fad8d3a9f1", size = 88069, upload-time = "2025-07-01T13:30:59.346Z" } +name = "pytest-xdist" +sdist = {url = "https://files.pythonhosted.org/packages/78/b4/439b179d1ff526791eb921115fca8e44e596a13efeda518b9d845a619450/pytest_xdist-3.8.0.tar.gz", hash = "sha256:7e578125ec9bc6050861aa93f2d59f1d8d085595d6551c2c90b6f4fad8d3a9f1", size = 88069, upload-time = "2025-07-01T13:30:59.346Z"} +source = {registry = "https://pypi.org/simple"} +version = "3.8.0" wheels = [ - { url = "https://files.pythonhosted.org/packages/ca/31/d4e37e9e550c2b92a9cbc2e4d0b7420a27224968580b5a447f420847c975/pytest_xdist-3.8.0-py3-none-any.whl", hash = "sha256:202ca578cfeb7370784a8c33d6d05bc6e13b4f25b5053c30a152269fd10f0b88", size = 46396, upload-time = "2025-07-01T13:30:56.632Z" }, + {url = "https://files.pythonhosted.org/packages/ca/31/d4e37e9e550c2b92a9cbc2e4d0b7420a27224968580b5a447f420847c975/pytest_xdist-3.8.0-py3-none-any.whl", hash = "sha256:202ca578cfeb7370784a8c33d6d05bc6e13b4f25b5053c30a152269fd10f0b88", size = 46396, upload-time = "2025-07-01T13:30:56.632Z"} ] [[package]] -name = "python-dateutil" -version = "2.9.0.post0" -source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "six" }, + {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" } +name = "python-dateutil" +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"} +source = {registry = "https://pypi.org/simple"} +version = "2.9.0.post0" 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" }, + {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 = "pytz" +sdist = {url = "https://files.pythonhosted.org/packages/f8/bf/abbd3cdfb8fbc7fb3d4d38d320f2441b1e7cbe29be4f23797b4a2b5d8aac/pytz-2025.2.tar.gz", hash = "sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3", size = 320884, upload-time = "2025-03-25T02:25:00.538Z"} +source = {registry = "https://pypi.org/simple"} version = "2025.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f8/bf/abbd3cdfb8fbc7fb3d4d38d320f2441b1e7cbe29be4f23797b4a2b5d8aac/pytz-2025.2.tar.gz", hash = "sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3", size = 320884, upload-time = "2025-03-25T02:25:00.538Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl", hash = "sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00", size = 509225, upload-time = "2025-03-25T02:24:58.468Z" }, + {url = "https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl", hash = "sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00", size = 509225, upload-time = "2025-03-25T02:24:58.468Z"} ] [[package]] -name = "pyvis" -version = "0.3.2" -source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "ipython" }, - { name = "jinja2" }, - { name = "jsonpickle" }, - { name = "networkx" }, + {name = "ipython"}, + {name = "jinja2"}, + {name = "jsonpickle"}, + {name = "networkx"} ] +name = "pyvis" +source = {registry = "https://pypi.org/simple"} +version = "0.3.2" wheels = [ - { url = "https://files.pythonhosted.org/packages/ab/4b/e37e4e5d5ee1179694917b445768bdbfb084f5a59ecd38089d3413d4c70f/pyvis-0.3.2-py3-none-any.whl", hash = "sha256:5720c4ca8161dc5d9ab352015723abb7a8bb8fb443edeb07f7a322db34a97555", size = 756038, upload-time = "2023-02-24T20:29:46.758Z" }, + {url = "https://files.pythonhosted.org/packages/ab/4b/e37e4e5d5ee1179694917b445768bdbfb084f5a59ecd38089d3413d4c70f/pyvis-0.3.2-py3-none-any.whl", hash = "sha256:5720c4ca8161dc5d9ab352015723abb7a8bb8fb443edeb07f7a322db34a97555", size = 756038, upload-time = "2023-02-24T20:29:46.758Z"} ] [[package]] name = "pyyaml" +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"} +source = {registry = "https://pypi.org/simple"} 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/6d/16/a95b6757765b7b031c9374925bb718d55e0a9ba8a1b6a12d25962ea44347/pyyaml-6.0.3-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:44edc647873928551a01e7a563d7452ccdebee747728c1080d881d68af7b997e", size = 185826, upload-time = "2025-09-25T21:31:58.655Z" }, - { url = "https://files.pythonhosted.org/packages/16/19/13de8e4377ed53079ee996e1ab0a9c33ec2faf808a4647b7b4c0d46dd239/pyyaml-6.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:652cb6edd41e718550aad172851962662ff2681490a8a711af6a4d288dd96824", size = 175577, upload-time = "2025-09-25T21:32:00.088Z" }, - { url = "https://files.pythonhosted.org/packages/0c/62/d2eb46264d4b157dae1275b573017abec435397aa59cbcdab6fc978a8af4/pyyaml-6.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:10892704fc220243f5305762e276552a0395f7beb4dbf9b14ec8fd43b57f126c", size = 775556, upload-time = "2025-09-25T21:32:01.31Z" }, - { url = "https://files.pythonhosted.org/packages/10/cb/16c3f2cf3266edd25aaa00d6c4350381c8b012ed6f5276675b9eba8d9ff4/pyyaml-6.0.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:850774a7879607d3a6f50d36d04f00ee69e7fc816450e5f7e58d7f17f1ae5c00", size = 882114, upload-time = "2025-09-25T21:32:03.376Z" }, - { url = "https://files.pythonhosted.org/packages/71/60/917329f640924b18ff085ab889a11c763e0b573da888e8404ff486657602/pyyaml-6.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b8bb0864c5a28024fac8a632c443c87c5aa6f215c0b126c449ae1a150412f31d", size = 806638, upload-time = "2025-09-25T21:32:04.553Z" }, - { url = "https://files.pythonhosted.org/packages/dd/6f/529b0f316a9fd167281a6c3826b5583e6192dba792dd55e3203d3f8e655a/pyyaml-6.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1d37d57ad971609cf3c53ba6a7e365e40660e3be0e5175fa9f2365a379d6095a", size = 767463, upload-time = "2025-09-25T21:32:06.152Z" }, - { url = "https://files.pythonhosted.org/packages/f2/6a/b627b4e0c1dd03718543519ffb2f1deea4a1e6d42fbab8021936a4d22589/pyyaml-6.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:37503bfbfc9d2c40b344d06b2199cf0e96e97957ab1c1b546fd4f87e53e5d3e4", size = 794986, upload-time = "2025-09-25T21:32:07.367Z" }, - { url = "https://files.pythonhosted.org/packages/45/91/47a6e1c42d9ee337c4839208f30d9f09caa9f720ec7582917b264defc875/pyyaml-6.0.3-cp311-cp311-win32.whl", hash = "sha256:8098f252adfa6c80ab48096053f512f2321f0b998f98150cea9bd23d83e1467b", size = 142543, upload-time = "2025-09-25T21:32:08.95Z" }, - { url = "https://files.pythonhosted.org/packages/da/e3/ea007450a105ae919a72393cb06f122f288ef60bba2dc64b26e2646fa315/pyyaml-6.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:9f3bfb4965eb874431221a3ff3fdcddc7e74e3b07799e0e84ca4a0f867d449bf", size = 158763, upload-time = "2025-09-25T21:32:09.96Z" }, - { url = "https://files.pythonhosted.org/packages/d1/33/422b98d2195232ca1826284a76852ad5a86fe23e31b009c9886b2d0fb8b2/pyyaml-6.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7f047e29dcae44602496db43be01ad42fc6f1cc0d8cd6c83d342306c32270196", size = 182063, upload-time = "2025-09-25T21:32:11.445Z" }, - { url = "https://files.pythonhosted.org/packages/89/a0/6cf41a19a1f2f3feab0e9c0b74134aa2ce6849093d5517a0c550fe37a648/pyyaml-6.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0", size = 173973, upload-time = "2025-09-25T21:32:12.492Z" }, - { url = "https://files.pythonhosted.org/packages/ed/23/7a778b6bd0b9a8039df8b1b1d80e2e2ad78aa04171592c8a5c43a56a6af4/pyyaml-6.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28", size = 775116, upload-time = "2025-09-25T21:32:13.652Z" }, - { url = "https://files.pythonhosted.org/packages/65/30/d7353c338e12baef4ecc1b09e877c1970bd3382789c159b4f89d6a70dc09/pyyaml-6.0.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5fdec68f91a0c6739b380c83b951e2c72ac0197ace422360e6d5a959d8d97b2c", size = 844011, upload-time = "2025-09-25T21:32:15.21Z" }, - { url = "https://files.pythonhosted.org/packages/8b/9d/b3589d3877982d4f2329302ef98a8026e7f4443c765c46cfecc8858c6b4b/pyyaml-6.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc", size = 807870, upload-time = "2025-09-25T21:32:16.431Z" }, - { url = "https://files.pythonhosted.org/packages/05/c0/b3be26a015601b822b97d9149ff8cb5ead58c66f981e04fedf4e762f4bd4/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8dc52c23056b9ddd46818a57b78404882310fb473d63f17b07d5c40421e47f8e", size = 761089, upload-time = "2025-09-25T21:32:17.56Z" }, - { url = "https://files.pythonhosted.org/packages/be/8e/98435a21d1d4b46590d5459a22d88128103f8da4c2d4cb8f14f2a96504e1/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:41715c910c881bc081f1e8872880d3c650acf13dfa8214bad49ed4cede7c34ea", size = 790181, upload-time = "2025-09-25T21:32:18.834Z" }, - { url = "https://files.pythonhosted.org/packages/74/93/7baea19427dcfbe1e5a372d81473250b379f04b1bd3c4c5ff825e2327202/pyyaml-6.0.3-cp312-cp312-win32.whl", hash = "sha256:96b533f0e99f6579b3d4d4995707cf36df9100d67e0c8303a0c55b27b5f99bc5", size = 137658, upload-time = "2025-09-25T21:32:20.209Z" }, - { url = "https://files.pythonhosted.org/packages/86/bf/899e81e4cce32febab4fb42bb97dcdf66bc135272882d1987881a4b519e9/pyyaml-6.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:5fcd34e47f6e0b794d17de1b4ff496c00986e1c83f7ab2fb8fcfe9616ff7477b", size = 154003, upload-time = "2025-09-25T21:32:21.167Z" }, - { url = "https://files.pythonhosted.org/packages/1a/08/67bd04656199bbb51dbed1439b7f27601dfb576fb864099c7ef0c3e55531/pyyaml-6.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:64386e5e707d03a7e172c0701abfb7e10f0fb753ee1d773128192742712a98fd", size = 140344, upload-time = "2025-09-25T21:32:22.617Z" }, - { 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" }, +wheels = [ + {url = "https://files.pythonhosted.org/packages/6d/16/a95b6757765b7b031c9374925bb718d55e0a9ba8a1b6a12d25962ea44347/pyyaml-6.0.3-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:44edc647873928551a01e7a563d7452ccdebee747728c1080d881d68af7b997e", size = 185826, upload-time = "2025-09-25T21:31:58.655Z"}, + {url = "https://files.pythonhosted.org/packages/16/19/13de8e4377ed53079ee996e1ab0a9c33ec2faf808a4647b7b4c0d46dd239/pyyaml-6.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:652cb6edd41e718550aad172851962662ff2681490a8a711af6a4d288dd96824", size = 175577, upload-time = "2025-09-25T21:32:00.088Z"}, + {url = "https://files.pythonhosted.org/packages/0c/62/d2eb46264d4b157dae1275b573017abec435397aa59cbcdab6fc978a8af4/pyyaml-6.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:10892704fc220243f5305762e276552a0395f7beb4dbf9b14ec8fd43b57f126c", size = 775556, upload-time = "2025-09-25T21:32:01.31Z"}, + {url = "https://files.pythonhosted.org/packages/10/cb/16c3f2cf3266edd25aaa00d6c4350381c8b012ed6f5276675b9eba8d9ff4/pyyaml-6.0.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:850774a7879607d3a6f50d36d04f00ee69e7fc816450e5f7e58d7f17f1ae5c00", size = 882114, upload-time = "2025-09-25T21:32:03.376Z"}, + {url = "https://files.pythonhosted.org/packages/71/60/917329f640924b18ff085ab889a11c763e0b573da888e8404ff486657602/pyyaml-6.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b8bb0864c5a28024fac8a632c443c87c5aa6f215c0b126c449ae1a150412f31d", size = 806638, upload-time = "2025-09-25T21:32:04.553Z"}, + {url = "https://files.pythonhosted.org/packages/dd/6f/529b0f316a9fd167281a6c3826b5583e6192dba792dd55e3203d3f8e655a/pyyaml-6.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1d37d57ad971609cf3c53ba6a7e365e40660e3be0e5175fa9f2365a379d6095a", size = 767463, upload-time = "2025-09-25T21:32:06.152Z"}, + {url = "https://files.pythonhosted.org/packages/f2/6a/b627b4e0c1dd03718543519ffb2f1deea4a1e6d42fbab8021936a4d22589/pyyaml-6.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:37503bfbfc9d2c40b344d06b2199cf0e96e97957ab1c1b546fd4f87e53e5d3e4", size = 794986, upload-time = "2025-09-25T21:32:07.367Z"}, + {url = "https://files.pythonhosted.org/packages/45/91/47a6e1c42d9ee337c4839208f30d9f09caa9f720ec7582917b264defc875/pyyaml-6.0.3-cp311-cp311-win32.whl", hash = "sha256:8098f252adfa6c80ab48096053f512f2321f0b998f98150cea9bd23d83e1467b", size = 142543, upload-time = "2025-09-25T21:32:08.95Z"}, + {url = "https://files.pythonhosted.org/packages/da/e3/ea007450a105ae919a72393cb06f122f288ef60bba2dc64b26e2646fa315/pyyaml-6.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:9f3bfb4965eb874431221a3ff3fdcddc7e74e3b07799e0e84ca4a0f867d449bf", size = 158763, upload-time = "2025-09-25T21:32:09.96Z"}, + {url = "https://files.pythonhosted.org/packages/d1/33/422b98d2195232ca1826284a76852ad5a86fe23e31b009c9886b2d0fb8b2/pyyaml-6.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7f047e29dcae44602496db43be01ad42fc6f1cc0d8cd6c83d342306c32270196", size = 182063, upload-time = "2025-09-25T21:32:11.445Z"}, + {url = "https://files.pythonhosted.org/packages/89/a0/6cf41a19a1f2f3feab0e9c0b74134aa2ce6849093d5517a0c550fe37a648/pyyaml-6.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0", size = 173973, upload-time = "2025-09-25T21:32:12.492Z"}, + {url = "https://files.pythonhosted.org/packages/ed/23/7a778b6bd0b9a8039df8b1b1d80e2e2ad78aa04171592c8a5c43a56a6af4/pyyaml-6.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28", size = 775116, upload-time = "2025-09-25T21:32:13.652Z"}, + {url = "https://files.pythonhosted.org/packages/65/30/d7353c338e12baef4ecc1b09e877c1970bd3382789c159b4f89d6a70dc09/pyyaml-6.0.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5fdec68f91a0c6739b380c83b951e2c72ac0197ace422360e6d5a959d8d97b2c", size = 844011, upload-time = "2025-09-25T21:32:15.21Z"}, + {url = "https://files.pythonhosted.org/packages/8b/9d/b3589d3877982d4f2329302ef98a8026e7f4443c765c46cfecc8858c6b4b/pyyaml-6.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc", size = 807870, upload-time = "2025-09-25T21:32:16.431Z"}, + {url = "https://files.pythonhosted.org/packages/05/c0/b3be26a015601b822b97d9149ff8cb5ead58c66f981e04fedf4e762f4bd4/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8dc52c23056b9ddd46818a57b78404882310fb473d63f17b07d5c40421e47f8e", size = 761089, upload-time = "2025-09-25T21:32:17.56Z"}, + {url = "https://files.pythonhosted.org/packages/be/8e/98435a21d1d4b46590d5459a22d88128103f8da4c2d4cb8f14f2a96504e1/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:41715c910c881bc081f1e8872880d3c650acf13dfa8214bad49ed4cede7c34ea", size = 790181, upload-time = "2025-09-25T21:32:18.834Z"}, + {url = "https://files.pythonhosted.org/packages/74/93/7baea19427dcfbe1e5a372d81473250b379f04b1bd3c4c5ff825e2327202/pyyaml-6.0.3-cp312-cp312-win32.whl", hash = "sha256:96b533f0e99f6579b3d4d4995707cf36df9100d67e0c8303a0c55b27b5f99bc5", size = 137658, upload-time = "2025-09-25T21:32:20.209Z"}, + {url = "https://files.pythonhosted.org/packages/86/bf/899e81e4cce32febab4fb42bb97dcdf66bc135272882d1987881a4b519e9/pyyaml-6.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:5fcd34e47f6e0b794d17de1b4ff496c00986e1c83f7ab2fb8fcfe9616ff7477b", size = 154003, upload-time = "2025-09-25T21:32:21.167Z"}, + {url = "https://files.pythonhosted.org/packages/1a/08/67bd04656199bbb51dbed1439b7f27601dfb576fb864099c7ef0c3e55531/pyyaml-6.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:64386e5e707d03a7e172c0701abfb7e10f0fb753ee1d773128192742712a98fd", size = 140344, upload-time = "2025-09-25T21:32:22.617Z"}, + {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]] +dependencies = [ + {name = "cffi", marker = "implementation_name == 'pypy'"} +] name = "pyzmq" +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"} +source = {registry = "https://pypi.org/simple"} 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/06/5d/305323ba86b284e6fcb0d842d6adaa2999035f70f8c38a9b6d21ad28c3d4/pyzmq-27.1.0-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:226b091818d461a3bef763805e75685e478ac17e9008f49fce2d3e52b3d58b86", size = 1333328, upload-time = "2025-09-08T23:07:45.946Z" }, - { url = "https://files.pythonhosted.org/packages/bd/a0/fc7e78a23748ad5443ac3275943457e8452da67fda347e05260261108cbc/pyzmq-27.1.0-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:0790a0161c281ca9723f804871b4027f2e8b5a528d357c8952d08cd1a9c15581", size = 908803, upload-time = "2025-09-08T23:07:47.551Z" }, - { url = "https://files.pythonhosted.org/packages/7e/22/37d15eb05f3bdfa4abea6f6d96eb3bb58585fbd3e4e0ded4e743bc650c97/pyzmq-27.1.0-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c895a6f35476b0c3a54e3eb6ccf41bf3018de937016e6e18748317f25d4e925f", size = 668836, upload-time = "2025-09-08T23:07:49.436Z" }, - { url = "https://files.pythonhosted.org/packages/b1/c4/2a6fe5111a01005fc7af3878259ce17684fabb8852815eda6225620f3c59/pyzmq-27.1.0-cp311-cp311-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5bbf8d3630bf96550b3be8e1fc0fea5cbdc8d5466c1192887bd94869da17a63e", size = 857038, upload-time = "2025-09-08T23:07:51.234Z" }, - { url = "https://files.pythonhosted.org/packages/cb/eb/bfdcb41d0db9cd233d6fb22dc131583774135505ada800ebf14dfb0a7c40/pyzmq-27.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:15c8bd0fe0dabf808e2d7a681398c4e5ded70a551ab47482067a572c054c8e2e", size = 1657531, upload-time = "2025-09-08T23:07:52.795Z" }, - { url = "https://files.pythonhosted.org/packages/ab/21/e3180ca269ed4a0de5c34417dfe71a8ae80421198be83ee619a8a485b0c7/pyzmq-27.1.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:bafcb3dd171b4ae9f19ee6380dfc71ce0390fefaf26b504c0e5f628d7c8c54f2", size = 2034786, upload-time = "2025-09-08T23:07:55.047Z" }, - { url = "https://files.pythonhosted.org/packages/3b/b1/5e21d0b517434b7f33588ff76c177c5a167858cc38ef740608898cd329f2/pyzmq-27.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e829529fcaa09937189178115c49c504e69289abd39967cd8a4c215761373394", size = 1894220, upload-time = "2025-09-08T23:07:57.172Z" }, - { url = "https://files.pythonhosted.org/packages/03/f2/44913a6ff6941905efc24a1acf3d3cb6146b636c546c7406c38c49c403d4/pyzmq-27.1.0-cp311-cp311-win32.whl", hash = "sha256:6df079c47d5902af6db298ec92151db82ecb557af663098b92f2508c398bb54f", size = 567155, upload-time = "2025-09-08T23:07:59.05Z" }, - { url = "https://files.pythonhosted.org/packages/23/6d/d8d92a0eb270a925c9b4dd039c0b4dc10abc2fcbc48331788824ef113935/pyzmq-27.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:190cbf120fbc0fc4957b56866830def56628934a9d112aec0e2507aa6a032b97", size = 633428, upload-time = "2025-09-08T23:08:00.663Z" }, - { url = "https://files.pythonhosted.org/packages/ae/14/01afebc96c5abbbd713ecfc7469cfb1bc801c819a74ed5c9fad9a48801cb/pyzmq-27.1.0-cp311-cp311-win_arm64.whl", hash = "sha256:eca6b47df11a132d1745eb3b5b5e557a7dae2c303277aa0e69c6ba91b8736e07", size = 559497, upload-time = "2025-09-08T23:08:02.15Z" }, - { 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" }, - { url = "https://files.pythonhosted.org/packages/4c/c6/c4dcdecdbaa70969ee1fdced6d7b8f60cfabe64d25361f27ac4665a70620/pyzmq-27.1.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:18770c8d3563715387139060d37859c02ce40718d1faf299abddcdcc6a649066", size = 836265, upload-time = "2025-09-08T23:09:49.376Z" }, - { url = "https://files.pythonhosted.org/packages/3e/79/f38c92eeaeb03a2ccc2ba9866f0439593bb08c5e3b714ac1d553e5c96e25/pyzmq-27.1.0-pp311-pypy311_pp73-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:ac25465d42f92e990f8d8b0546b01c391ad431c3bf447683fdc40565941d0604", size = 800208, upload-time = "2025-09-08T23:09:51.073Z" }, - { url = "https://files.pythonhosted.org/packages/49/0e/3f0d0d335c6b3abb9b7b723776d0b21fa7f3a6c819a0db6097059aada160/pyzmq-27.1.0-pp311-pypy311_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:53b40f8ae006f2734ee7608d59ed661419f087521edbfc2149c3932e9c14808c", size = 567747, upload-time = "2025-09-08T23:09:52.698Z" }, - { url = "https://files.pythonhosted.org/packages/a1/cf/f2b3784d536250ffd4be70e049f3b60981235d70c6e8ce7e3ef21e1adb25/pyzmq-27.1.0-pp311-pypy311_pp73-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f605d884e7c8be8fe1aa94e0a783bf3f591b84c24e4bc4f3e7564c82ac25e271", size = 747371, upload-time = "2025-09-08T23:09:54.563Z" }, - { url = "https://files.pythonhosted.org/packages/01/1b/5dbe84eefc86f48473947e2f41711aded97eecef1231f4558f1f02713c12/pyzmq-27.1.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:c9f7f6e13dff2e44a6afeaf2cf54cee5929ad64afaf4d40b50f93c58fc687355", size = 544862, upload-time = "2025-09-08T23:09:56.509Z" }, +wheels = [ + {url = "https://files.pythonhosted.org/packages/06/5d/305323ba86b284e6fcb0d842d6adaa2999035f70f8c38a9b6d21ad28c3d4/pyzmq-27.1.0-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:226b091818d461a3bef763805e75685e478ac17e9008f49fce2d3e52b3d58b86", size = 1333328, upload-time = "2025-09-08T23:07:45.946Z"}, + {url = "https://files.pythonhosted.org/packages/bd/a0/fc7e78a23748ad5443ac3275943457e8452da67fda347e05260261108cbc/pyzmq-27.1.0-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:0790a0161c281ca9723f804871b4027f2e8b5a528d357c8952d08cd1a9c15581", size = 908803, upload-time = "2025-09-08T23:07:47.551Z"}, + {url = "https://files.pythonhosted.org/packages/7e/22/37d15eb05f3bdfa4abea6f6d96eb3bb58585fbd3e4e0ded4e743bc650c97/pyzmq-27.1.0-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c895a6f35476b0c3a54e3eb6ccf41bf3018de937016e6e18748317f25d4e925f", size = 668836, upload-time = "2025-09-08T23:07:49.436Z"}, + {url = "https://files.pythonhosted.org/packages/b1/c4/2a6fe5111a01005fc7af3878259ce17684fabb8852815eda6225620f3c59/pyzmq-27.1.0-cp311-cp311-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5bbf8d3630bf96550b3be8e1fc0fea5cbdc8d5466c1192887bd94869da17a63e", size = 857038, upload-time = "2025-09-08T23:07:51.234Z"}, + {url = "https://files.pythonhosted.org/packages/cb/eb/bfdcb41d0db9cd233d6fb22dc131583774135505ada800ebf14dfb0a7c40/pyzmq-27.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:15c8bd0fe0dabf808e2d7a681398c4e5ded70a551ab47482067a572c054c8e2e", size = 1657531, upload-time = "2025-09-08T23:07:52.795Z"}, + {url = "https://files.pythonhosted.org/packages/ab/21/e3180ca269ed4a0de5c34417dfe71a8ae80421198be83ee619a8a485b0c7/pyzmq-27.1.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:bafcb3dd171b4ae9f19ee6380dfc71ce0390fefaf26b504c0e5f628d7c8c54f2", size = 2034786, upload-time = "2025-09-08T23:07:55.047Z"}, + {url = "https://files.pythonhosted.org/packages/3b/b1/5e21d0b517434b7f33588ff76c177c5a167858cc38ef740608898cd329f2/pyzmq-27.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e829529fcaa09937189178115c49c504e69289abd39967cd8a4c215761373394", size = 1894220, upload-time = "2025-09-08T23:07:57.172Z"}, + {url = "https://files.pythonhosted.org/packages/03/f2/44913a6ff6941905efc24a1acf3d3cb6146b636c546c7406c38c49c403d4/pyzmq-27.1.0-cp311-cp311-win32.whl", hash = "sha256:6df079c47d5902af6db298ec92151db82ecb557af663098b92f2508c398bb54f", size = 567155, upload-time = "2025-09-08T23:07:59.05Z"}, + {url = "https://files.pythonhosted.org/packages/23/6d/d8d92a0eb270a925c9b4dd039c0b4dc10abc2fcbc48331788824ef113935/pyzmq-27.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:190cbf120fbc0fc4957b56866830def56628934a9d112aec0e2507aa6a032b97", size = 633428, upload-time = "2025-09-08T23:08:00.663Z"}, + {url = "https://files.pythonhosted.org/packages/ae/14/01afebc96c5abbbd713ecfc7469cfb1bc801c819a74ed5c9fad9a48801cb/pyzmq-27.1.0-cp311-cp311-win_arm64.whl", hash = "sha256:eca6b47df11a132d1745eb3b5b5e557a7dae2c303277aa0e69c6ba91b8736e07", size = 559497, upload-time = "2025-09-08T23:08:02.15Z"}, + {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"}, + {url = "https://files.pythonhosted.org/packages/4c/c6/c4dcdecdbaa70969ee1fdced6d7b8f60cfabe64d25361f27ac4665a70620/pyzmq-27.1.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:18770c8d3563715387139060d37859c02ce40718d1faf299abddcdcc6a649066", size = 836265, upload-time = "2025-09-08T23:09:49.376Z"}, + {url = "https://files.pythonhosted.org/packages/3e/79/f38c92eeaeb03a2ccc2ba9866f0439593bb08c5e3b714ac1d553e5c96e25/pyzmq-27.1.0-pp311-pypy311_pp73-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:ac25465d42f92e990f8d8b0546b01c391ad431c3bf447683fdc40565941d0604", size = 800208, upload-time = "2025-09-08T23:09:51.073Z"}, + {url = "https://files.pythonhosted.org/packages/49/0e/3f0d0d335c6b3abb9b7b723776d0b21fa7f3a6c819a0db6097059aada160/pyzmq-27.1.0-pp311-pypy311_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:53b40f8ae006f2734ee7608d59ed661419f087521edbfc2149c3932e9c14808c", size = 567747, upload-time = "2025-09-08T23:09:52.698Z"}, + {url = "https://files.pythonhosted.org/packages/a1/cf/f2b3784d536250ffd4be70e049f3b60981235d70c6e8ce7e3ef21e1adb25/pyzmq-27.1.0-pp311-pypy311_pp73-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f605d884e7c8be8fe1aa94e0a783bf3f591b84c24e4bc4f3e7564c82ac25e271", size = 747371, upload-time = "2025-09-08T23:09:54.563Z"}, + {url = "https://files.pythonhosted.org/packages/01/1b/5dbe84eefc86f48473947e2f41711aded97eecef1231f4558f1f02713c12/pyzmq-27.1.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:c9f7f6e13dff2e44a6afeaf2cf54cee5929ad64afaf4d40b50f93c58fc687355", size = 544862, upload-time = "2025-09-08T23:09:56.509Z"} ] [[package]] +dependencies = [ + {name = "frozendict"}, + {name = "humanize"}, + {name = "numpy"}, + {name = "objsize"}, + {name = "pandas"}, + {name = "protobuf"}, + {name = "requests"} +] name = "qubed" +sdist = {url = "https://files.pythonhosted.org/packages/12/a2/d4cd7fbc41fef2b308f10ed3f9c5bb1cf40f338ff3a0e37692325ba28b77/qubed-0.3.1.tar.gz", hash = "sha256:fadcf4be1668f0cfc58fcf430a15613e0f53f0df4e07fd05694c9caba39e8258", size = 15152020, upload-time = "2026-02-04T13:27:38.081Z"} +source = {registry = "https://pypi.org/simple"} version = "0.3.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "frozendict" }, - { name = "humanize" }, - { name = "numpy" }, - { name = "objsize" }, - { name = "pandas" }, - { name = "protobuf" }, - { name = "requests" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/12/a2/d4cd7fbc41fef2b308f10ed3f9c5bb1cf40f338ff3a0e37692325ba28b77/qubed-0.3.1.tar.gz", hash = "sha256:fadcf4be1668f0cfc58fcf430a15613e0f53f0df4e07fd05694c9caba39e8258", size = 15152020, upload-time = "2026-02-04T13:27:38.081Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/53/ae/8817f6db21335200da65434aaf1adb7ab86c38f7ac88cfbaaab9a50df335/qubed-0.3.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:8a5ba2af717c5225b733ec6695bc848a6507e5590ea47310c36a204b03604da8", size = 392905, upload-time = "2026-02-04T13:26:57.846Z" }, - { url = "https://files.pythonhosted.org/packages/3c/b2/253ddba74f5703677d5ee2232b1925578266e4023f7a3aaec6a17e5fd6b4/qubed-0.3.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d2f0ac5b238de53baac98ea66e1e2a21fa729baf69789fb657b578e7d1dbda5d", size = 379845, upload-time = "2026-02-04T13:26:53.467Z" }, - { url = "https://files.pythonhosted.org/packages/95/53/06c4c8f59b587b5ce087c796d362ecd57fea6a67fb73f380c7f8f4b5403e/qubed-0.3.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6de0a6783af5f6342f7f124c5a159fc0b84c78d95d2866801d9a280cba447a46", size = 417330, upload-time = "2026-02-04T13:26:01.262Z" }, - { url = "https://files.pythonhosted.org/packages/a1/43/33caa7eefa46c21c6b9b3d3dd96f56772a46530a27577c63a273699b0bb1/qubed-0.3.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4e2f16a2c6fbf52049cde9931d2cb6777e7b63c9a2e68b949a7bd06f6bbd6e66", size = 425131, upload-time = "2026-02-04T13:26:11.324Z" }, - { url = "https://files.pythonhosted.org/packages/e9/01/7165694535259dfacff7d78377eb66b6e4187b69decbc81558a7170a8aa4/qubed-0.3.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b2202d3f948231254d6c0ad19d10577ed663983c08b92a9ca8da00989465b013", size = 544973, upload-time = "2026-02-04T13:26:22.725Z" }, - { url = "https://files.pythonhosted.org/packages/f3/85/9a7914ccfea96d24f15df68a93dbb99ff14b4e75f1dd326df58286b38a20/qubed-0.3.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a783825a8b5415ac4ba15d3495a8330a4d78882715b90869f66ae1ee147826a4", size = 453565, upload-time = "2026-02-04T13:26:34.094Z" }, - { url = "https://files.pythonhosted.org/packages/b9/32/9c7cf964bea589da50bb572ee3bcd07641bf7e75961a14558dbee4b1a85c/qubed-0.3.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc2edde67d3710ce780b85b18eab0749ebe1c77f92251e3d0c6efbd88ae7d661", size = 428033, upload-time = "2026-02-04T13:26:48.038Z" }, - { url = "https://files.pythonhosted.org/packages/c4/2d/458d060268a5a38635994b854507e01038186a4d96cc5b5112680d70ca3c/qubed-0.3.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c576d6bf4fd6e6b6e44c5ef67b107fb3a0bf75bac89f25eeffdb7cd846e081cb", size = 451273, upload-time = "2026-02-04T13:26:41.923Z" }, - { url = "https://files.pythonhosted.org/packages/be/2a/abfbeaa8590c39af25e71ff6c84fc3dbd77a18629046b2ae5dc05f1b5e9f/qubed-0.3.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ae99b8d994a26452b308ecc2e7f40b3209bdcc827a9966c9451dc6e124aab0a1", size = 592940, upload-time = "2026-02-04T13:27:02.719Z" }, - { url = "https://files.pythonhosted.org/packages/59/33/84d0b4d21a5153131b4e8a321bb959ab0309a220a875001bcb3901393564/qubed-0.3.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:b0819d34638e5a31891576feaa6889f4b16aa0f159876c83694281c86b628363", size = 694999, upload-time = "2026-02-04T13:27:10.953Z" }, - { url = "https://files.pythonhosted.org/packages/6f/87/8d1dea898d0e70a46a9c788fee66c07fdfed08ab46b99849962458a1945e/qubed-0.3.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:c9a047da1cd4ee8b6c8e84e8d26cae383c46033ae7af4c8b8641a36f5b1d9c43", size = 662808, upload-time = "2026-02-04T13:27:20.788Z" }, - { url = "https://files.pythonhosted.org/packages/35/61/ac065cd10f6109e27b57b498d539be67ac1e594e7ede519124696d5175be/qubed-0.3.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1db61763554caf12adf40095fc6fb951bd115665ac692655ceed3c3dc9aaeeeb", size = 633806, upload-time = "2026-02-04T13:27:29.057Z" }, - { url = "https://files.pythonhosted.org/packages/72/55/3761a4acd6169fed3cbe5cf809efada6ef14aa9c6cdb7007033a5f8f300b/qubed-0.3.1-cp311-cp311-win_amd64.whl", hash = "sha256:8a3734e6ee8954da87ebbf319402a0ab0e16e0d64a10b5b1a1e6ee13d0eec244", size = 274537, upload-time = "2026-02-04T13:27:40.483Z" }, - { url = "https://files.pythonhosted.org/packages/f5/e1/ade8497e74afd3e6dae8ea1d79fec46ea0c284ae25e6f96ccb1b5c687496/qubed-0.3.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:2f7ad49d36086114a9c48c5bbd774ec2fe9e4fbe7064e5af70eeeed1a1696444", size = 388382, upload-time = "2026-02-04T13:26:58.926Z" }, - { url = "https://files.pythonhosted.org/packages/48/96/00629bd9796c7438b613dbeca97ae4349694ce45a9f1998ff45d3f3f7aab/qubed-0.3.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d6832cc6010c2f0fffbca3751c0204876da03e5feae294d2896acaea9482f3e6", size = 376862, upload-time = "2026-02-04T13:26:54.841Z" }, - { url = "https://files.pythonhosted.org/packages/f5/ae/b94eee7a2de48c1fe5fcff2abeb1f0b66f0e2959d8f8319b358814be896d/qubed-0.3.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7f9273475076dafcb45bb8a510dc7a3a44c81d486edaf8fda88a3da414a318cb", size = 416993, upload-time = "2026-02-04T13:26:02.472Z" }, - { url = "https://files.pythonhosted.org/packages/ea/cc/832aa8537960349d4bb043762d57171e1256611ebda815381cabb7f92ce1/qubed-0.3.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8825a2d7e0ddaf3b841f3a746669ca8a195a86e4a0a04a5a0ce26987f4b976b1", size = 424594, upload-time = "2026-02-04T13:26:12.328Z" }, - { url = "https://files.pythonhosted.org/packages/d8/cd/21bc5fed290401da7774fc05b32cf045dae07b208b3169924ecbb59069fb/qubed-0.3.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0758cd417772386f7ba3972c6b4a23258569e654ef5cc77f15d0d19c1db8d7d8", size = 544629, upload-time = "2026-02-04T13:26:23.789Z" }, - { url = "https://files.pythonhosted.org/packages/8b/f1/0c291803b21b811c1398d8d1133dc3fabc2d6a8aab1804c2b8788af5eaee/qubed-0.3.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a5f3999551b6d888320002a7c7c978c75efbce8f2ad449a2ddafbf3df89f4cfd", size = 453413, upload-time = "2026-02-04T13:26:35.125Z" }, - { url = "https://files.pythonhosted.org/packages/ac/84/8ce812bae0fc382715eaf831bc3d6fbdd10683e1c9d47e0b7f0b62df60b7/qubed-0.3.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c71e33a38e02b632efb454ae2ca90e818201e6f6706485f2ac1d45e69f977f1c", size = 427902, upload-time = "2026-02-04T13:26:49.156Z" }, - { url = "https://files.pythonhosted.org/packages/69/40/40845475c5153521783adbf80f2455fbb33ff625c29b6ba8e57555970afc/qubed-0.3.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d9de33e0a06bde6068ef1f2dc1df354826c9a1e63e8263cba4be55db3e24dd7a", size = 450608, upload-time = "2026-02-04T13:26:42.944Z" }, - { url = "https://files.pythonhosted.org/packages/6b/c0/100edf7a233d917f2979fbbe3a18e20d515df4f7564847452e71cc8e914b/qubed-0.3.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4ed3902eaf6ffaf248cdd680f52cc48ca7a9c6a259738c013c382d6d9ae9a0bf", size = 592941, upload-time = "2026-02-04T13:27:03.839Z" }, - { url = "https://files.pythonhosted.org/packages/ec/50/18bd283574ad125576b267e37cb906399abb80a3b30eda70cf629ea0d65b/qubed-0.3.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:fb8344fd7942086f1878c355f5fa3bfd7241022b3264384d72af9dc21083da9e", size = 694756, upload-time = "2026-02-04T13:27:12.072Z" }, - { url = "https://files.pythonhosted.org/packages/c7/44/c8154bb943855c3def9537b9643a901e4be827581b1240a69846ff6811a5/qubed-0.3.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:7a3c85eebed4bc4b229793fb27a2cad19caddd36df4115cbe62e3f2762ac94a6", size = 662092, upload-time = "2026-02-04T13:27:21.837Z" }, - { url = "https://files.pythonhosted.org/packages/19/69/017821dda7e5fe9b69cf5ae962668c632c83448f47c4be1a1256ac7c7fae/qubed-0.3.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b2e2ad894d86d07181d7345c7555835c3fbbf16655a3adbc15368b44b407c570", size = 634032, upload-time = "2026-02-04T13:27:30.397Z" }, - { url = "https://files.pythonhosted.org/packages/7b/be/3e853dd96781110b82e2d5ba51a14884ef7518a85578f19db1fdfee5f74e/qubed-0.3.1-cp312-cp312-win_amd64.whl", hash = "sha256:71541f0d98df10e22e40c11f54867df3272436f87758e1c10c49d074571b821d", size = 274558, upload-time = "2026-02-04T13:27:41.563Z" }, - { url = "https://files.pythonhosted.org/packages/f6/78/00920a7dab93468c6abd4364900372adf5a6e02373874fee8a048b173e2f/qubed-0.3.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:0982545641cb7877c25ceefc788e2e0c5918b8d942419b1b3ebecf8ef64aa6c1", size = 388026, upload-time = "2026-02-04T13:26:59.877Z" }, - { url = "https://files.pythonhosted.org/packages/17/32/763131474decd86745ba83d5c7c77dcb95fc6144e44d61ac26c4970c8bc3/qubed-0.3.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:26432bf22b7aeab036c763639c1874471eea8f58b69bcc789c746fcf6a0135e0", size = 376678, upload-time = "2026-02-04T13:26:55.884Z" }, - { url = "https://files.pythonhosted.org/packages/ec/33/859744b54e692514c18d7d1c356b0dd49e01308990962b3d05edacf421f0/qubed-0.3.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5144c5f0e9929ef0219b5a06d43d58c5c111c165a21313f98892200d23a46e40", size = 417055, upload-time = "2026-02-04T13:26:03.989Z" }, - { url = "https://files.pythonhosted.org/packages/7b/52/d3fcd58088922485566dac0c613ce54b5afb411a47ac1c0fc30f394e4d56/qubed-0.3.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7be7875347f1fab4342e503f69f2cf7ec77e23134c17ee119489a26c6abf81dc", size = 424312, upload-time = "2026-02-04T13:26:13.767Z" }, - { url = "https://files.pythonhosted.org/packages/6b/46/0159a2f0f3a9ac907454cf5e7e9de53409470535feeab1f005a57cff9869/qubed-0.3.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b6b44d86229cd4b43b524eab440ae8b3e4a1e7706815d9393c56bf02c09f25f4", size = 544218, upload-time = "2026-02-04T13:26:25.249Z" }, - { url = "https://files.pythonhosted.org/packages/aa/06/b890c192d4d05a9ceeaacfec2c9ef1bc7f4ed5a9a88613442cd409a7103c/qubed-0.3.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e0426c2cc15f126584a64df6e27ee0162d44d413493689218544b444972d67b2", size = 453095, upload-time = "2026-02-04T13:26:36.147Z" }, - { url = "https://files.pythonhosted.org/packages/01/88/31e64cd98f079243157ced5d0a6ca3c0637e3e93982269bff5d6accd36fa/qubed-0.3.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:04ed84be17ecff54a813b159b0ade5b6fe1daf9d0d3e8cce58160a71898de084", size = 427903, upload-time = "2026-02-04T13:26:50.046Z" }, - { url = "https://files.pythonhosted.org/packages/a4/c3/6fcdde26e45c18dfaf67cad426580d9efd8b44b839db29755cc10dde7e52/qubed-0.3.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3ee277521885d362a2f4282874aadaa7b5b021473cf18b62ccbab49d02490738", size = 450209, upload-time = "2026-02-04T13:26:44.927Z" }, - { url = "https://files.pythonhosted.org/packages/87/63/8eb2f83b994ed59c6526f09b72fa8898188a0023ad0348d14bbcfdfc715c/qubed-0.3.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5e716bd15a5e614da853a0b835ad16a9c57a13f9243194abd4d7a4aabbf82dd0", size = 592620, upload-time = "2026-02-04T13:27:04.995Z" }, - { url = "https://files.pythonhosted.org/packages/4a/be/4fe1e7634101016eef06843805633c9ec6b8e69bc40ef50190de4284271d/qubed-0.3.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:71f18b847fa9bc205368dcd176cc27e1c5c0cd4cfd74d3e2770ba422b3b14ff0", size = 694654, upload-time = "2026-02-04T13:27:13.7Z" }, - { url = "https://files.pythonhosted.org/packages/7c/17/84cf9d4615ea0e29d8709346ffd5bed5bcfdb29baf8101949181c5239cc8/qubed-0.3.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:eeeb96bf930b2bd944c0b3145c18dda22673dcbe98af1b4fca0429c96eeefae3", size = 661802, upload-time = "2026-02-04T13:27:22.87Z" }, - { url = "https://files.pythonhosted.org/packages/7c/27/4826d44a5a47ed4d3ba3d64f519d6ce65511239dbd613081a2b5b03a425e/qubed-0.3.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:2c2a3519538aae695c2a129006010d1291bf387e86b2477587dd421d07d0d111", size = 634066, upload-time = "2026-02-04T13:27:31.613Z" }, - { url = "https://files.pythonhosted.org/packages/c9/cf/97f4ea7ca129eea1d97139e56c3af415f082f6b063a0d3da537c4cf77984/qubed-0.3.1-cp313-cp313-win_amd64.whl", hash = "sha256:677f12a55d20a43beade986c45508668d93762072a7f8710dc768263832305f2", size = 274355, upload-time = "2026-02-04T13:27:42.559Z" }, - { url = "https://files.pythonhosted.org/packages/1c/25/2d77b2aa954c7581dfe614e4edc9e213e0bc537a791567955cc89c908ea3/qubed-0.3.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1bce5c3ca22b4125f7b2337072892562949c66b22060f1458f0ffc8914dea664", size = 415858, upload-time = "2026-02-04T13:26:05.072Z" }, - { url = "https://files.pythonhosted.org/packages/cd/38/145f404396aedeb65ea110d14a74f02ab5f2c64fcf0441f196a8b509394c/qubed-0.3.1-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c7eeb24e4d156df188000388b8b93b8659b8ff56a3a0204eb868a63d43c9fb5d", size = 423639, upload-time = "2026-02-04T13:26:15.08Z" }, - { url = "https://files.pythonhosted.org/packages/52/54/04beadee9ce2fb42d9cd9dead26aebfd614f01d9c57287b07406abfbc567/qubed-0.3.1-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:57bb442de810879c2e0801b6b9e32e9ec30d37dbd02b464809523ea5294fe655", size = 543014, upload-time = "2026-02-04T13:26:27.385Z" }, - { url = "https://files.pythonhosted.org/packages/e6/f6/37e2e0efb56b29f16d533b0bfa56fdbff94289e527e0a529e9a6547ef8b7/qubed-0.3.1-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:738ab71e1a714f3a3e3110e3eaac2778a5684f21515196b6b3c83843f9c5243b", size = 452627, upload-time = "2026-02-04T13:26:37.269Z" }, - { url = "https://files.pythonhosted.org/packages/e9/aa/699a433b495665b99c4bb2dd37f4c8a15147dc955174d4a4eec3a2105fc7/qubed-0.3.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:af5e093933172f0820860b2fb4d909a6bb8b17043bf40c143088bf1529da0d26", size = 591409, upload-time = "2026-02-04T13:27:06.111Z" }, - { url = "https://files.pythonhosted.org/packages/b2/fe/0d701edc6db7c16f50c3d41387791eae38c475d3f63677823ec5549a9b1d/qubed-0.3.1-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:f0a5caf87d9fc853adde336759ef88e174be84b74bc29d582788fe70735dbba4", size = 694115, upload-time = "2026-02-04T13:27:14.784Z" }, - { url = "https://files.pythonhosted.org/packages/dd/5b/3a91f3ee0de53bcdb4a6c80590243952acb891c088ddcaf066d4a209d0df/qubed-0.3.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:8144ab517ef48f43c49b97d07c05d230015222f8c091bb1daac00ef62bfc74d9", size = 661144, upload-time = "2026-02-04T13:27:24.061Z" }, - { url = "https://files.pythonhosted.org/packages/34/3e/28ab2031409540bc38f3f6e2db1d546b9d7c242755b6bf5c1ad4b7cab85a/qubed-0.3.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:e164e030591f2ed0eb5525efe785ff04fc7080f0ef4ccfe8d83e25091006d709", size = 633167, upload-time = "2026-02-04T13:27:33.18Z" }, - { url = "https://files.pythonhosted.org/packages/a3/90/8651f479d7a726bc5f25cb90f99f33420fec6355b71248eb9b266753bce9/qubed-0.3.1-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:49b0eec981057347991bc80b3886501ca45ee0e426843c0450a8b0710d444659", size = 387842, upload-time = "2026-02-04T13:27:00.858Z" }, - { url = "https://files.pythonhosted.org/packages/1d/69/679e544a4fe1505b9f78f047ce1c81cf6db84b382c58d4a6ca46cfa48327/qubed-0.3.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:97f9c034ae3ad1d7123e269c7fba225c20dbbaeebdd80803c77a69f3b010f8ff", size = 376202, upload-time = "2026-02-04T13:26:56.852Z" }, - { url = "https://files.pythonhosted.org/packages/0b/1d/d4a5fa3a40e697f1ec8337e152cc241ec6aeff84f7514a6cfbee6b6536f5/qubed-0.3.1-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4d154b12afffb5891beb06157b5bfc31e33d579d6a8682d866eb848bb18cc55f", size = 416737, upload-time = "2026-02-04T13:26:06.481Z" }, - { url = "https://files.pythonhosted.org/packages/6e/66/efc34b57ee3d21334d6127b187e51a249a37484b707cbed393d464419d09/qubed-0.3.1-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac14223782c4f346167a23511408347cf2a5c109c07f4319a9eb8f08bb4cdd53", size = 424440, upload-time = "2026-02-04T13:26:16.861Z" }, - { url = "https://files.pythonhosted.org/packages/c2/11/27f13777d9a4f2f0425c32cdc4f6fb528393e238768c185124abe15ff024/qubed-0.3.1-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e80a636152fa172ac298cb87bdae96412fa5f9e9a2149d1cb94bb4068508c941", size = 540728, upload-time = "2026-02-04T13:26:28.82Z" }, - { url = "https://files.pythonhosted.org/packages/9a/9c/8ed6325f5c9c8ff96a41adef53f111bcf5dec51d2687afd2fac8504f19fc/qubed-0.3.1-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2cb088a6846416ca092be5793c5191df97a94a3c3e5c43468be42b811ef14020", size = 453464, upload-time = "2026-02-04T13:26:38.885Z" }, - { url = "https://files.pythonhosted.org/packages/b1/d6/c0dac0a00e3730130f897389d263042c26b2dd182cbffb2960b93c64007d/qubed-0.3.1-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a5e0cae1aba8bd95d020bc127bc404211c96a0ff66502f2bd5ff04a8fa06643", size = 427694, upload-time = "2026-02-04T13:26:51.557Z" }, - { url = "https://files.pythonhosted.org/packages/de/e6/51e368c70bc5d3ee557b92e059fe1280330ed70d537cf8739ba71f316319/qubed-0.3.1-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:409c6475c99f28e372e48c9fc13284a48fffadfb6f54e531aad59d608457de41", size = 451222, upload-time = "2026-02-04T13:26:45.98Z" }, - { url = "https://files.pythonhosted.org/packages/3a/74/5deba084e718c14509af8a4bb676785d91dc6516ac633e1b72dbf0598216/qubed-0.3.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:246332f045e37f6e88c773d4c8684441d0ec2a40c8ede7bae896c8ac6d513471", size = 592438, upload-time = "2026-02-04T13:27:07.033Z" }, - { url = "https://files.pythonhosted.org/packages/28/c6/f41468881fde149c23df5bf568bac54bce9409374c76043ba19f159185c2/qubed-0.3.1-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:2caf36b5cba258fb2f6301f879d4a16ad1a74648a0593d9f057c6b6aff603fd5", size = 694800, upload-time = "2026-02-04T13:27:16.309Z" }, - { url = "https://files.pythonhosted.org/packages/f2/76/409605ac8bf26382d51d0e9df55344fa3cede74feaaebaf75a9fc07b221e/qubed-0.3.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:4c5ce4d40840f45d2c359649a49a4fb271ec1650a162d20d5fea1c7106cb375d", size = 661966, upload-time = "2026-02-04T13:27:25.271Z" }, - { url = "https://files.pythonhosted.org/packages/83/56/6efbbf4df4d483390c679456f87daed5e80c8f663d4d5065689ae6e8fc27/qubed-0.3.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b5aa6c0d749a3186f1d4fb38e5ece4ba3513ee9cf24d182156e35fc7d637ce08", size = 634051, upload-time = "2026-02-04T13:27:34.241Z" }, - { url = "https://files.pythonhosted.org/packages/d3/8b/65aef7336037d71978ea2e33da4a6c43262f2e31b84ee74c32e85f2aff4e/qubed-0.3.1-cp314-cp314-win32.whl", hash = "sha256:f4b7f53c722d0550a6be0e1ac148a79228f0cda2f3c32e9297b86bdd61c228d9", size = 257945, upload-time = "2026-02-04T13:27:44.705Z" }, - { url = "https://files.pythonhosted.org/packages/9b/89/0249375839f15086a08f213d25c0aa3828e16808cf68bdb088eb01125520/qubed-0.3.1-cp314-cp314-win_amd64.whl", hash = "sha256:c861104640c86883a5e0c8ae8682eb5eb417f4506282d36adfa9329bad26a3a7", size = 274944, upload-time = "2026-02-04T13:27:43.771Z" }, - { url = "https://files.pythonhosted.org/packages/9a/3a/4694ed8a3a70b5ea484d8e82cb1988ddc5b19aebf9433ea5ced28263b64f/qubed-0.3.1-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e1ba620950ed169f9d9652597181b03fe37b7febef65c18956c5032006d06886", size = 416016, upload-time = "2026-02-04T13:26:07.498Z" }, - { url = "https://files.pythonhosted.org/packages/43/2c/56fcd7992f12856ffb6b01aa3f17b0e799ddeec6cae97eb5e632413750c3/qubed-0.3.1-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f76e96ae183a5f72a03f36681e995db7b9b6ecd2bce6b880135ef5f0dba51ad5", size = 423689, upload-time = "2026-02-04T13:26:18.458Z" }, - { url = "https://files.pythonhosted.org/packages/8e/40/0a3d024e77ec6223e7256dcb92013a1ba139e569cba5dcd1470679171f1a/qubed-0.3.1-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d256f1db00336ce347e1d646d2e1065bdfe1d8de9b06cc60ab1e81aa5a135363", size = 544069, upload-time = "2026-02-04T13:26:30.318Z" }, - { url = "https://files.pythonhosted.org/packages/51/de/c32a46fbe272b436681bdda6d3073308598e98af4a74f6c26e1d07c0ddf4/qubed-0.3.1-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0c38414c20f17128d0c62de60515e54d280fb35c13a576aa0d4bbf8e8b6b7ff7", size = 452810, upload-time = "2026-02-04T13:26:39.827Z" }, - { url = "https://files.pythonhosted.org/packages/f5/e9/3059877538ad438428d12200141e155a5e3521fbeacb361a7d95c187fb2d/qubed-0.3.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:6dba1d9c479c79605c1d0ddb841f93b5fac94f80085a9cbdca3319b1111baadd", size = 591547, upload-time = "2026-02-04T13:27:08.312Z" }, - { url = "https://files.pythonhosted.org/packages/2d/0d/10ac0b1f602b6f54bc57b49bb9e672b9dacb70fff960206bcd52aff0de3b/qubed-0.3.1-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:ee0f20cd860ca67136765ef12cdcb04fafc15c0eab33ed9d733603d237d5e328", size = 693845, upload-time = "2026-02-04T13:27:17.444Z" }, - { url = "https://files.pythonhosted.org/packages/5f/47/3ed547c0fce3f7d5e794f739783ee758f72061b792053f68d99db89d852f/qubed-0.3.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:9923d183c0c71a8c2a1b3e95a40df128141cedd7cd21f73c9d9a2aa34ad58f5a", size = 661304, upload-time = "2026-02-04T13:27:26.375Z" }, - { url = "https://files.pythonhosted.org/packages/b7/cc/fb5e887dfe9561a96bcd9969f8412736aaf8b40ea7fc76edb7f6791b7787/qubed-0.3.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:e9d5fcee6ee49265f43fb986860f105b7a2c735e8f7c80feeb02f618f1354ab1", size = 633291, upload-time = "2026-02-04T13:27:35.261Z" }, - { url = "https://files.pythonhosted.org/packages/8a/a4/61c0893c62b70b3ae7096b51071134939ce3a7a8dc6d3be3485a14c704ef/qubed-0.3.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0525ea3e7286a2e1306c2d53cde122d596fe32c97c4b77ffb791647b6d06df40", size = 417314, upload-time = "2026-02-04T13:26:10.193Z" }, - { url = "https://files.pythonhosted.org/packages/97/88/75d5cea6fa9af6b25e93a6fb6775199601020193c813eba624d626265b6c/qubed-0.3.1-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:97b8e5a1ceabf68032b8c38a1a0fa2b425e2f137e1ae0b29d27a9b2c640d2923", size = 424549, upload-time = "2026-02-04T13:26:21.319Z" }, - { url = "https://files.pythonhosted.org/packages/0a/79/c14068df38c8bcadb81c204e06eb4f33388c40061792346b46c55864ec6c/qubed-0.3.1-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:536e9479355758596d552314b29185f8e9606ee1fa7551b9ad71d575fe41bfa0", size = 543966, upload-time = "2026-02-04T13:26:32.643Z" }, - { url = "https://files.pythonhosted.org/packages/34/6d/ead34b0f6aa8049b29db20bdc38c3378a1a71e6a4b3ef4d4b2b658b54774/qubed-0.3.1-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:288446a11cb22d194322858ebed1882d48cde40e65c40a5b2bee4d1eb204a7e0", size = 453255, upload-time = "2026-02-04T13:26:40.813Z" }, - { url = "https://files.pythonhosted.org/packages/6c/69/e0616ec49e8bbf7b2f365b93336b63ade3e10c377a0f7921f4f78da1cc5b/qubed-0.3.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:164eed7d512094c9f6bedcbf62dcc15d78cfcf42133fb594fc68494dac0dde9b", size = 427645, upload-time = "2026-02-04T13:26:52.492Z" }, - { url = "https://files.pythonhosted.org/packages/ed/34/3455baea73fd18b29884c9e30806b20fffaccff1b57d533091e6cf849b4a/qubed-0.3.1-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:48790481e503e6e65d0acd2afdc085bef6cc9f876d9d6ff791c1f6ece99b1e9f", size = 450995, upload-time = "2026-02-04T13:26:47.013Z" }, - { url = "https://files.pythonhosted.org/packages/97/d2/57842a201a430afa1f6eec433f51cfcd08601486daaf074b42a1a4047314/qubed-0.3.1-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:c7583848ea8e79d7b78427979fe7100fd0c271cf14efadfa5cd25e9878c67850", size = 593098, upload-time = "2026-02-04T13:27:09.828Z" }, - { url = "https://files.pythonhosted.org/packages/09/b3/dacad16f12ce515f8ad3c61ed7b6d1749f90b9c36b1a0947ef5bace5ed0c/qubed-0.3.1-pp311-pypy311_pp73-musllinux_1_2_armv7l.whl", hash = "sha256:ab4475288640f2e380f3704fb7b44f4e6d8a8987041f6fb3cc76ecdc02e333cd", size = 694846, upload-time = "2026-02-04T13:27:18.574Z" }, - { url = "https://files.pythonhosted.org/packages/84/e6/78473835a64ba33c2e6963c120eeff496182f81006f955c19ca7ea17e25f/qubed-0.3.1-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:25d8d3603b16e3202b53145150bcb8ebedce14fc42fd076d17feaf3a0de897a2", size = 662539, upload-time = "2026-02-04T13:27:27.404Z" }, - { url = "https://files.pythonhosted.org/packages/60/7f/ab8d6582ba660b03da7617bab310f1db095a3ce622fdfcc5c2e50778208c/qubed-0.3.1-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:cd90899b3182ecf6bfac689664be37726a1f28d06200a8b15b22fdc3b79cd72b", size = 633528, upload-time = "2026-02-04T13:27:36.452Z" }, +wheels = [ + {url = "https://files.pythonhosted.org/packages/53/ae/8817f6db21335200da65434aaf1adb7ab86c38f7ac88cfbaaab9a50df335/qubed-0.3.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:8a5ba2af717c5225b733ec6695bc848a6507e5590ea47310c36a204b03604da8", size = 392905, upload-time = "2026-02-04T13:26:57.846Z"}, + {url = "https://files.pythonhosted.org/packages/3c/b2/253ddba74f5703677d5ee2232b1925578266e4023f7a3aaec6a17e5fd6b4/qubed-0.3.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d2f0ac5b238de53baac98ea66e1e2a21fa729baf69789fb657b578e7d1dbda5d", size = 379845, upload-time = "2026-02-04T13:26:53.467Z"}, + {url = "https://files.pythonhosted.org/packages/95/53/06c4c8f59b587b5ce087c796d362ecd57fea6a67fb73f380c7f8f4b5403e/qubed-0.3.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6de0a6783af5f6342f7f124c5a159fc0b84c78d95d2866801d9a280cba447a46", size = 417330, upload-time = "2026-02-04T13:26:01.262Z"}, + {url = "https://files.pythonhosted.org/packages/a1/43/33caa7eefa46c21c6b9b3d3dd96f56772a46530a27577c63a273699b0bb1/qubed-0.3.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4e2f16a2c6fbf52049cde9931d2cb6777e7b63c9a2e68b949a7bd06f6bbd6e66", size = 425131, upload-time = "2026-02-04T13:26:11.324Z"}, + {url = "https://files.pythonhosted.org/packages/e9/01/7165694535259dfacff7d78377eb66b6e4187b69decbc81558a7170a8aa4/qubed-0.3.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b2202d3f948231254d6c0ad19d10577ed663983c08b92a9ca8da00989465b013", size = 544973, upload-time = "2026-02-04T13:26:22.725Z"}, + {url = "https://files.pythonhosted.org/packages/f3/85/9a7914ccfea96d24f15df68a93dbb99ff14b4e75f1dd326df58286b38a20/qubed-0.3.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a783825a8b5415ac4ba15d3495a8330a4d78882715b90869f66ae1ee147826a4", size = 453565, upload-time = "2026-02-04T13:26:34.094Z"}, + {url = "https://files.pythonhosted.org/packages/b9/32/9c7cf964bea589da50bb572ee3bcd07641bf7e75961a14558dbee4b1a85c/qubed-0.3.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc2edde67d3710ce780b85b18eab0749ebe1c77f92251e3d0c6efbd88ae7d661", size = 428033, upload-time = "2026-02-04T13:26:48.038Z"}, + {url = "https://files.pythonhosted.org/packages/c4/2d/458d060268a5a38635994b854507e01038186a4d96cc5b5112680d70ca3c/qubed-0.3.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c576d6bf4fd6e6b6e44c5ef67b107fb3a0bf75bac89f25eeffdb7cd846e081cb", size = 451273, upload-time = "2026-02-04T13:26:41.923Z"}, + {url = "https://files.pythonhosted.org/packages/be/2a/abfbeaa8590c39af25e71ff6c84fc3dbd77a18629046b2ae5dc05f1b5e9f/qubed-0.3.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ae99b8d994a26452b308ecc2e7f40b3209bdcc827a9966c9451dc6e124aab0a1", size = 592940, upload-time = "2026-02-04T13:27:02.719Z"}, + {url = "https://files.pythonhosted.org/packages/59/33/84d0b4d21a5153131b4e8a321bb959ab0309a220a875001bcb3901393564/qubed-0.3.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:b0819d34638e5a31891576feaa6889f4b16aa0f159876c83694281c86b628363", size = 694999, upload-time = "2026-02-04T13:27:10.953Z"}, + {url = "https://files.pythonhosted.org/packages/6f/87/8d1dea898d0e70a46a9c788fee66c07fdfed08ab46b99849962458a1945e/qubed-0.3.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:c9a047da1cd4ee8b6c8e84e8d26cae383c46033ae7af4c8b8641a36f5b1d9c43", size = 662808, upload-time = "2026-02-04T13:27:20.788Z"}, + {url = "https://files.pythonhosted.org/packages/35/61/ac065cd10f6109e27b57b498d539be67ac1e594e7ede519124696d5175be/qubed-0.3.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1db61763554caf12adf40095fc6fb951bd115665ac692655ceed3c3dc9aaeeeb", size = 633806, upload-time = "2026-02-04T13:27:29.057Z"}, + {url = "https://files.pythonhosted.org/packages/72/55/3761a4acd6169fed3cbe5cf809efada6ef14aa9c6cdb7007033a5f8f300b/qubed-0.3.1-cp311-cp311-win_amd64.whl", hash = "sha256:8a3734e6ee8954da87ebbf319402a0ab0e16e0d64a10b5b1a1e6ee13d0eec244", size = 274537, upload-time = "2026-02-04T13:27:40.483Z"}, + {url = "https://files.pythonhosted.org/packages/f5/e1/ade8497e74afd3e6dae8ea1d79fec46ea0c284ae25e6f96ccb1b5c687496/qubed-0.3.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:2f7ad49d36086114a9c48c5bbd774ec2fe9e4fbe7064e5af70eeeed1a1696444", size = 388382, upload-time = "2026-02-04T13:26:58.926Z"}, + {url = "https://files.pythonhosted.org/packages/48/96/00629bd9796c7438b613dbeca97ae4349694ce45a9f1998ff45d3f3f7aab/qubed-0.3.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d6832cc6010c2f0fffbca3751c0204876da03e5feae294d2896acaea9482f3e6", size = 376862, upload-time = "2026-02-04T13:26:54.841Z"}, + {url = "https://files.pythonhosted.org/packages/f5/ae/b94eee7a2de48c1fe5fcff2abeb1f0b66f0e2959d8f8319b358814be896d/qubed-0.3.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7f9273475076dafcb45bb8a510dc7a3a44c81d486edaf8fda88a3da414a318cb", size = 416993, upload-time = "2026-02-04T13:26:02.472Z"}, + {url = "https://files.pythonhosted.org/packages/ea/cc/832aa8537960349d4bb043762d57171e1256611ebda815381cabb7f92ce1/qubed-0.3.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8825a2d7e0ddaf3b841f3a746669ca8a195a86e4a0a04a5a0ce26987f4b976b1", size = 424594, upload-time = "2026-02-04T13:26:12.328Z"}, + {url = "https://files.pythonhosted.org/packages/d8/cd/21bc5fed290401da7774fc05b32cf045dae07b208b3169924ecbb59069fb/qubed-0.3.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0758cd417772386f7ba3972c6b4a23258569e654ef5cc77f15d0d19c1db8d7d8", size = 544629, upload-time = "2026-02-04T13:26:23.789Z"}, + {url = "https://files.pythonhosted.org/packages/8b/f1/0c291803b21b811c1398d8d1133dc3fabc2d6a8aab1804c2b8788af5eaee/qubed-0.3.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a5f3999551b6d888320002a7c7c978c75efbce8f2ad449a2ddafbf3df89f4cfd", size = 453413, upload-time = "2026-02-04T13:26:35.125Z"}, + {url = "https://files.pythonhosted.org/packages/ac/84/8ce812bae0fc382715eaf831bc3d6fbdd10683e1c9d47e0b7f0b62df60b7/qubed-0.3.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c71e33a38e02b632efb454ae2ca90e818201e6f6706485f2ac1d45e69f977f1c", size = 427902, upload-time = "2026-02-04T13:26:49.156Z"}, + {url = "https://files.pythonhosted.org/packages/69/40/40845475c5153521783adbf80f2455fbb33ff625c29b6ba8e57555970afc/qubed-0.3.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d9de33e0a06bde6068ef1f2dc1df354826c9a1e63e8263cba4be55db3e24dd7a", size = 450608, upload-time = "2026-02-04T13:26:42.944Z"}, + {url = "https://files.pythonhosted.org/packages/6b/c0/100edf7a233d917f2979fbbe3a18e20d515df4f7564847452e71cc8e914b/qubed-0.3.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4ed3902eaf6ffaf248cdd680f52cc48ca7a9c6a259738c013c382d6d9ae9a0bf", size = 592941, upload-time = "2026-02-04T13:27:03.839Z"}, + {url = "https://files.pythonhosted.org/packages/ec/50/18bd283574ad125576b267e37cb906399abb80a3b30eda70cf629ea0d65b/qubed-0.3.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:fb8344fd7942086f1878c355f5fa3bfd7241022b3264384d72af9dc21083da9e", size = 694756, upload-time = "2026-02-04T13:27:12.072Z"}, + {url = "https://files.pythonhosted.org/packages/c7/44/c8154bb943855c3def9537b9643a901e4be827581b1240a69846ff6811a5/qubed-0.3.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:7a3c85eebed4bc4b229793fb27a2cad19caddd36df4115cbe62e3f2762ac94a6", size = 662092, upload-time = "2026-02-04T13:27:21.837Z"}, + {url = "https://files.pythonhosted.org/packages/19/69/017821dda7e5fe9b69cf5ae962668c632c83448f47c4be1a1256ac7c7fae/qubed-0.3.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b2e2ad894d86d07181d7345c7555835c3fbbf16655a3adbc15368b44b407c570", size = 634032, upload-time = "2026-02-04T13:27:30.397Z"}, + {url = "https://files.pythonhosted.org/packages/7b/be/3e853dd96781110b82e2d5ba51a14884ef7518a85578f19db1fdfee5f74e/qubed-0.3.1-cp312-cp312-win_amd64.whl", hash = "sha256:71541f0d98df10e22e40c11f54867df3272436f87758e1c10c49d074571b821d", size = 274558, upload-time = "2026-02-04T13:27:41.563Z"}, + {url = "https://files.pythonhosted.org/packages/f6/78/00920a7dab93468c6abd4364900372adf5a6e02373874fee8a048b173e2f/qubed-0.3.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:0982545641cb7877c25ceefc788e2e0c5918b8d942419b1b3ebecf8ef64aa6c1", size = 388026, upload-time = "2026-02-04T13:26:59.877Z"}, + {url = "https://files.pythonhosted.org/packages/17/32/763131474decd86745ba83d5c7c77dcb95fc6144e44d61ac26c4970c8bc3/qubed-0.3.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:26432bf22b7aeab036c763639c1874471eea8f58b69bcc789c746fcf6a0135e0", size = 376678, upload-time = "2026-02-04T13:26:55.884Z"}, + {url = "https://files.pythonhosted.org/packages/ec/33/859744b54e692514c18d7d1c356b0dd49e01308990962b3d05edacf421f0/qubed-0.3.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5144c5f0e9929ef0219b5a06d43d58c5c111c165a21313f98892200d23a46e40", size = 417055, upload-time = "2026-02-04T13:26:03.989Z"}, + {url = "https://files.pythonhosted.org/packages/7b/52/d3fcd58088922485566dac0c613ce54b5afb411a47ac1c0fc30f394e4d56/qubed-0.3.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7be7875347f1fab4342e503f69f2cf7ec77e23134c17ee119489a26c6abf81dc", size = 424312, upload-time = "2026-02-04T13:26:13.767Z"}, + {url = "https://files.pythonhosted.org/packages/6b/46/0159a2f0f3a9ac907454cf5e7e9de53409470535feeab1f005a57cff9869/qubed-0.3.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b6b44d86229cd4b43b524eab440ae8b3e4a1e7706815d9393c56bf02c09f25f4", size = 544218, upload-time = "2026-02-04T13:26:25.249Z"}, + {url = "https://files.pythonhosted.org/packages/aa/06/b890c192d4d05a9ceeaacfec2c9ef1bc7f4ed5a9a88613442cd409a7103c/qubed-0.3.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e0426c2cc15f126584a64df6e27ee0162d44d413493689218544b444972d67b2", size = 453095, upload-time = "2026-02-04T13:26:36.147Z"}, + {url = "https://files.pythonhosted.org/packages/01/88/31e64cd98f079243157ced5d0a6ca3c0637e3e93982269bff5d6accd36fa/qubed-0.3.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:04ed84be17ecff54a813b159b0ade5b6fe1daf9d0d3e8cce58160a71898de084", size = 427903, upload-time = "2026-02-04T13:26:50.046Z"}, + {url = "https://files.pythonhosted.org/packages/a4/c3/6fcdde26e45c18dfaf67cad426580d9efd8b44b839db29755cc10dde7e52/qubed-0.3.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3ee277521885d362a2f4282874aadaa7b5b021473cf18b62ccbab49d02490738", size = 450209, upload-time = "2026-02-04T13:26:44.927Z"}, + {url = "https://files.pythonhosted.org/packages/87/63/8eb2f83b994ed59c6526f09b72fa8898188a0023ad0348d14bbcfdfc715c/qubed-0.3.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5e716bd15a5e614da853a0b835ad16a9c57a13f9243194abd4d7a4aabbf82dd0", size = 592620, upload-time = "2026-02-04T13:27:04.995Z"}, + {url = "https://files.pythonhosted.org/packages/4a/be/4fe1e7634101016eef06843805633c9ec6b8e69bc40ef50190de4284271d/qubed-0.3.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:71f18b847fa9bc205368dcd176cc27e1c5c0cd4cfd74d3e2770ba422b3b14ff0", size = 694654, upload-time = "2026-02-04T13:27:13.7Z"}, + {url = "https://files.pythonhosted.org/packages/7c/17/84cf9d4615ea0e29d8709346ffd5bed5bcfdb29baf8101949181c5239cc8/qubed-0.3.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:eeeb96bf930b2bd944c0b3145c18dda22673dcbe98af1b4fca0429c96eeefae3", size = 661802, upload-time = "2026-02-04T13:27:22.87Z"}, + {url = "https://files.pythonhosted.org/packages/7c/27/4826d44a5a47ed4d3ba3d64f519d6ce65511239dbd613081a2b5b03a425e/qubed-0.3.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:2c2a3519538aae695c2a129006010d1291bf387e86b2477587dd421d07d0d111", size = 634066, upload-time = "2026-02-04T13:27:31.613Z"}, + {url = "https://files.pythonhosted.org/packages/c9/cf/97f4ea7ca129eea1d97139e56c3af415f082f6b063a0d3da537c4cf77984/qubed-0.3.1-cp313-cp313-win_amd64.whl", hash = "sha256:677f12a55d20a43beade986c45508668d93762072a7f8710dc768263832305f2", size = 274355, upload-time = "2026-02-04T13:27:42.559Z"}, + {url = "https://files.pythonhosted.org/packages/1c/25/2d77b2aa954c7581dfe614e4edc9e213e0bc537a791567955cc89c908ea3/qubed-0.3.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1bce5c3ca22b4125f7b2337072892562949c66b22060f1458f0ffc8914dea664", size = 415858, upload-time = "2026-02-04T13:26:05.072Z"}, + {url = "https://files.pythonhosted.org/packages/cd/38/145f404396aedeb65ea110d14a74f02ab5f2c64fcf0441f196a8b509394c/qubed-0.3.1-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c7eeb24e4d156df188000388b8b93b8659b8ff56a3a0204eb868a63d43c9fb5d", size = 423639, upload-time = "2026-02-04T13:26:15.08Z"}, + {url = "https://files.pythonhosted.org/packages/52/54/04beadee9ce2fb42d9cd9dead26aebfd614f01d9c57287b07406abfbc567/qubed-0.3.1-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:57bb442de810879c2e0801b6b9e32e9ec30d37dbd02b464809523ea5294fe655", size = 543014, upload-time = "2026-02-04T13:26:27.385Z"}, + {url = "https://files.pythonhosted.org/packages/e6/f6/37e2e0efb56b29f16d533b0bfa56fdbff94289e527e0a529e9a6547ef8b7/qubed-0.3.1-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:738ab71e1a714f3a3e3110e3eaac2778a5684f21515196b6b3c83843f9c5243b", size = 452627, upload-time = "2026-02-04T13:26:37.269Z"}, + {url = "https://files.pythonhosted.org/packages/e9/aa/699a433b495665b99c4bb2dd37f4c8a15147dc955174d4a4eec3a2105fc7/qubed-0.3.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:af5e093933172f0820860b2fb4d909a6bb8b17043bf40c143088bf1529da0d26", size = 591409, upload-time = "2026-02-04T13:27:06.111Z"}, + {url = "https://files.pythonhosted.org/packages/b2/fe/0d701edc6db7c16f50c3d41387791eae38c475d3f63677823ec5549a9b1d/qubed-0.3.1-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:f0a5caf87d9fc853adde336759ef88e174be84b74bc29d582788fe70735dbba4", size = 694115, upload-time = "2026-02-04T13:27:14.784Z"}, + {url = "https://files.pythonhosted.org/packages/dd/5b/3a91f3ee0de53bcdb4a6c80590243952acb891c088ddcaf066d4a209d0df/qubed-0.3.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:8144ab517ef48f43c49b97d07c05d230015222f8c091bb1daac00ef62bfc74d9", size = 661144, upload-time = "2026-02-04T13:27:24.061Z"}, + {url = "https://files.pythonhosted.org/packages/34/3e/28ab2031409540bc38f3f6e2db1d546b9d7c242755b6bf5c1ad4b7cab85a/qubed-0.3.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:e164e030591f2ed0eb5525efe785ff04fc7080f0ef4ccfe8d83e25091006d709", size = 633167, upload-time = "2026-02-04T13:27:33.18Z"}, + {url = "https://files.pythonhosted.org/packages/a3/90/8651f479d7a726bc5f25cb90f99f33420fec6355b71248eb9b266753bce9/qubed-0.3.1-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:49b0eec981057347991bc80b3886501ca45ee0e426843c0450a8b0710d444659", size = 387842, upload-time = "2026-02-04T13:27:00.858Z"}, + {url = "https://files.pythonhosted.org/packages/1d/69/679e544a4fe1505b9f78f047ce1c81cf6db84b382c58d4a6ca46cfa48327/qubed-0.3.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:97f9c034ae3ad1d7123e269c7fba225c20dbbaeebdd80803c77a69f3b010f8ff", size = 376202, upload-time = "2026-02-04T13:26:56.852Z"}, + {url = "https://files.pythonhosted.org/packages/0b/1d/d4a5fa3a40e697f1ec8337e152cc241ec6aeff84f7514a6cfbee6b6536f5/qubed-0.3.1-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4d154b12afffb5891beb06157b5bfc31e33d579d6a8682d866eb848bb18cc55f", size = 416737, upload-time = "2026-02-04T13:26:06.481Z"}, + {url = "https://files.pythonhosted.org/packages/6e/66/efc34b57ee3d21334d6127b187e51a249a37484b707cbed393d464419d09/qubed-0.3.1-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac14223782c4f346167a23511408347cf2a5c109c07f4319a9eb8f08bb4cdd53", size = 424440, upload-time = "2026-02-04T13:26:16.861Z"}, + {url = "https://files.pythonhosted.org/packages/c2/11/27f13777d9a4f2f0425c32cdc4f6fb528393e238768c185124abe15ff024/qubed-0.3.1-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e80a636152fa172ac298cb87bdae96412fa5f9e9a2149d1cb94bb4068508c941", size = 540728, upload-time = "2026-02-04T13:26:28.82Z"}, + {url = "https://files.pythonhosted.org/packages/9a/9c/8ed6325f5c9c8ff96a41adef53f111bcf5dec51d2687afd2fac8504f19fc/qubed-0.3.1-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2cb088a6846416ca092be5793c5191df97a94a3c3e5c43468be42b811ef14020", size = 453464, upload-time = "2026-02-04T13:26:38.885Z"}, + {url = "https://files.pythonhosted.org/packages/b1/d6/c0dac0a00e3730130f897389d263042c26b2dd182cbffb2960b93c64007d/qubed-0.3.1-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a5e0cae1aba8bd95d020bc127bc404211c96a0ff66502f2bd5ff04a8fa06643", size = 427694, upload-time = "2026-02-04T13:26:51.557Z"}, + {url = "https://files.pythonhosted.org/packages/de/e6/51e368c70bc5d3ee557b92e059fe1280330ed70d537cf8739ba71f316319/qubed-0.3.1-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:409c6475c99f28e372e48c9fc13284a48fffadfb6f54e531aad59d608457de41", size = 451222, upload-time = "2026-02-04T13:26:45.98Z"}, + {url = "https://files.pythonhosted.org/packages/3a/74/5deba084e718c14509af8a4bb676785d91dc6516ac633e1b72dbf0598216/qubed-0.3.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:246332f045e37f6e88c773d4c8684441d0ec2a40c8ede7bae896c8ac6d513471", size = 592438, upload-time = "2026-02-04T13:27:07.033Z"}, + {url = "https://files.pythonhosted.org/packages/28/c6/f41468881fde149c23df5bf568bac54bce9409374c76043ba19f159185c2/qubed-0.3.1-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:2caf36b5cba258fb2f6301f879d4a16ad1a74648a0593d9f057c6b6aff603fd5", size = 694800, upload-time = "2026-02-04T13:27:16.309Z"}, + {url = "https://files.pythonhosted.org/packages/f2/76/409605ac8bf26382d51d0e9df55344fa3cede74feaaebaf75a9fc07b221e/qubed-0.3.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:4c5ce4d40840f45d2c359649a49a4fb271ec1650a162d20d5fea1c7106cb375d", size = 661966, upload-time = "2026-02-04T13:27:25.271Z"}, + {url = "https://files.pythonhosted.org/packages/83/56/6efbbf4df4d483390c679456f87daed5e80c8f663d4d5065689ae6e8fc27/qubed-0.3.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b5aa6c0d749a3186f1d4fb38e5ece4ba3513ee9cf24d182156e35fc7d637ce08", size = 634051, upload-time = "2026-02-04T13:27:34.241Z"}, + {url = "https://files.pythonhosted.org/packages/d3/8b/65aef7336037d71978ea2e33da4a6c43262f2e31b84ee74c32e85f2aff4e/qubed-0.3.1-cp314-cp314-win32.whl", hash = "sha256:f4b7f53c722d0550a6be0e1ac148a79228f0cda2f3c32e9297b86bdd61c228d9", size = 257945, upload-time = "2026-02-04T13:27:44.705Z"}, + {url = "https://files.pythonhosted.org/packages/9b/89/0249375839f15086a08f213d25c0aa3828e16808cf68bdb088eb01125520/qubed-0.3.1-cp314-cp314-win_amd64.whl", hash = "sha256:c861104640c86883a5e0c8ae8682eb5eb417f4506282d36adfa9329bad26a3a7", size = 274944, upload-time = "2026-02-04T13:27:43.771Z"}, + {url = "https://files.pythonhosted.org/packages/9a/3a/4694ed8a3a70b5ea484d8e82cb1988ddc5b19aebf9433ea5ced28263b64f/qubed-0.3.1-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e1ba620950ed169f9d9652597181b03fe37b7febef65c18956c5032006d06886", size = 416016, upload-time = "2026-02-04T13:26:07.498Z"}, + {url = "https://files.pythonhosted.org/packages/43/2c/56fcd7992f12856ffb6b01aa3f17b0e799ddeec6cae97eb5e632413750c3/qubed-0.3.1-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f76e96ae183a5f72a03f36681e995db7b9b6ecd2bce6b880135ef5f0dba51ad5", size = 423689, upload-time = "2026-02-04T13:26:18.458Z"}, + {url = "https://files.pythonhosted.org/packages/8e/40/0a3d024e77ec6223e7256dcb92013a1ba139e569cba5dcd1470679171f1a/qubed-0.3.1-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d256f1db00336ce347e1d646d2e1065bdfe1d8de9b06cc60ab1e81aa5a135363", size = 544069, upload-time = "2026-02-04T13:26:30.318Z"}, + {url = "https://files.pythonhosted.org/packages/51/de/c32a46fbe272b436681bdda6d3073308598e98af4a74f6c26e1d07c0ddf4/qubed-0.3.1-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0c38414c20f17128d0c62de60515e54d280fb35c13a576aa0d4bbf8e8b6b7ff7", size = 452810, upload-time = "2026-02-04T13:26:39.827Z"}, + {url = "https://files.pythonhosted.org/packages/f5/e9/3059877538ad438428d12200141e155a5e3521fbeacb361a7d95c187fb2d/qubed-0.3.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:6dba1d9c479c79605c1d0ddb841f93b5fac94f80085a9cbdca3319b1111baadd", size = 591547, upload-time = "2026-02-04T13:27:08.312Z"}, + {url = "https://files.pythonhosted.org/packages/2d/0d/10ac0b1f602b6f54bc57b49bb9e672b9dacb70fff960206bcd52aff0de3b/qubed-0.3.1-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:ee0f20cd860ca67136765ef12cdcb04fafc15c0eab33ed9d733603d237d5e328", size = 693845, upload-time = "2026-02-04T13:27:17.444Z"}, + {url = "https://files.pythonhosted.org/packages/5f/47/3ed547c0fce3f7d5e794f739783ee758f72061b792053f68d99db89d852f/qubed-0.3.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:9923d183c0c71a8c2a1b3e95a40df128141cedd7cd21f73c9d9a2aa34ad58f5a", size = 661304, upload-time = "2026-02-04T13:27:26.375Z"}, + {url = "https://files.pythonhosted.org/packages/b7/cc/fb5e887dfe9561a96bcd9969f8412736aaf8b40ea7fc76edb7f6791b7787/qubed-0.3.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:e9d5fcee6ee49265f43fb986860f105b7a2c735e8f7c80feeb02f618f1354ab1", size = 633291, upload-time = "2026-02-04T13:27:35.261Z"}, + {url = "https://files.pythonhosted.org/packages/8a/a4/61c0893c62b70b3ae7096b51071134939ce3a7a8dc6d3be3485a14c704ef/qubed-0.3.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0525ea3e7286a2e1306c2d53cde122d596fe32c97c4b77ffb791647b6d06df40", size = 417314, upload-time = "2026-02-04T13:26:10.193Z"}, + {url = "https://files.pythonhosted.org/packages/97/88/75d5cea6fa9af6b25e93a6fb6775199601020193c813eba624d626265b6c/qubed-0.3.1-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:97b8e5a1ceabf68032b8c38a1a0fa2b425e2f137e1ae0b29d27a9b2c640d2923", size = 424549, upload-time = "2026-02-04T13:26:21.319Z"}, + {url = "https://files.pythonhosted.org/packages/0a/79/c14068df38c8bcadb81c204e06eb4f33388c40061792346b46c55864ec6c/qubed-0.3.1-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:536e9479355758596d552314b29185f8e9606ee1fa7551b9ad71d575fe41bfa0", size = 543966, upload-time = "2026-02-04T13:26:32.643Z"}, + {url = "https://files.pythonhosted.org/packages/34/6d/ead34b0f6aa8049b29db20bdc38c3378a1a71e6a4b3ef4d4b2b658b54774/qubed-0.3.1-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:288446a11cb22d194322858ebed1882d48cde40e65c40a5b2bee4d1eb204a7e0", size = 453255, upload-time = "2026-02-04T13:26:40.813Z"}, + {url = "https://files.pythonhosted.org/packages/6c/69/e0616ec49e8bbf7b2f365b93336b63ade3e10c377a0f7921f4f78da1cc5b/qubed-0.3.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:164eed7d512094c9f6bedcbf62dcc15d78cfcf42133fb594fc68494dac0dde9b", size = 427645, upload-time = "2026-02-04T13:26:52.492Z"}, + {url = "https://files.pythonhosted.org/packages/ed/34/3455baea73fd18b29884c9e30806b20fffaccff1b57d533091e6cf849b4a/qubed-0.3.1-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:48790481e503e6e65d0acd2afdc085bef6cc9f876d9d6ff791c1f6ece99b1e9f", size = 450995, upload-time = "2026-02-04T13:26:47.013Z"}, + {url = "https://files.pythonhosted.org/packages/97/d2/57842a201a430afa1f6eec433f51cfcd08601486daaf074b42a1a4047314/qubed-0.3.1-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:c7583848ea8e79d7b78427979fe7100fd0c271cf14efadfa5cd25e9878c67850", size = 593098, upload-time = "2026-02-04T13:27:09.828Z"}, + {url = "https://files.pythonhosted.org/packages/09/b3/dacad16f12ce515f8ad3c61ed7b6d1749f90b9c36b1a0947ef5bace5ed0c/qubed-0.3.1-pp311-pypy311_pp73-musllinux_1_2_armv7l.whl", hash = "sha256:ab4475288640f2e380f3704fb7b44f4e6d8a8987041f6fb3cc76ecdc02e333cd", size = 694846, upload-time = "2026-02-04T13:27:18.574Z"}, + {url = "https://files.pythonhosted.org/packages/84/e6/78473835a64ba33c2e6963c120eeff496182f81006f955c19ca7ea17e25f/qubed-0.3.1-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:25d8d3603b16e3202b53145150bcb8ebedce14fc42fd076d17feaf3a0de897a2", size = 662539, upload-time = "2026-02-04T13:27:27.404Z"}, + {url = "https://files.pythonhosted.org/packages/60/7f/ab8d6582ba660b03da7617bab310f1db095a3ce622fdfcc5c2e50778208c/qubed-0.3.1-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:cd90899b3182ecf6bfac689664be37726a1f28d06200a8b15b22fdc3b79cd72b", size = 633528, upload-time = "2026-02-04T13:27:36.452Z"} ] [[package]] -name = "referencing" -version = "0.37.0" -source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "attrs" }, - { name = "rpds-py" }, - { name = "typing-extensions", marker = "python_full_version < '3.13'" }, + {name = "attrs"}, + {name = "rpds-py"}, + {name = "typing-extensions", marker = "python_full_version < '3.13'"} ] -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" } +name = "referencing" +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"} +source = {registry = "https://pypi.org/simple"} +version = "0.37.0" 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" }, + {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.32.5" -source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "certifi" }, - { name = "charset-normalizer" }, - { name = "idna" }, - { name = "urllib3" }, + {name = "certifi"}, + {name = "charset-normalizer"}, + {name = "idna"}, + {name = "urllib3"} ] -sdist = { url = "https://files.pythonhosted.org/packages/c9/74/b3ff8e6c8446842c3f5c837e9c3dfcfe2018ea6ecef224c710c85ef728f4/requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf", size = 134517, upload-time = "2025-08-18T20:46:02.573Z" } +name = "requests" +sdist = {url = "https://files.pythonhosted.org/packages/c9/74/b3ff8e6c8446842c3f5c837e9c3dfcfe2018ea6ecef224c710c85ef728f4/requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf", size = 134517, upload-time = "2025-08-18T20:46:02.573Z"} +source = {registry = "https://pypi.org/simple"} +version = "2.32.5" wheels = [ - { url = "https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6", size = 64738, upload-time = "2025-08-18T20:46:00.542Z" }, + {url = "https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6", size = 64738, upload-time = "2025-08-18T20:46:00.542Z"} ] [[package]] name = "rpds-py" +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"} +source = {registry = "https://pypi.org/simple"} 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/4d/6e/f964e88b3d2abee2a82c1ac8366da848fce1c6d834dc2132c3fda3970290/rpds_py-0.30.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:a2bffea6a4ca9f01b3f8e548302470306689684e61602aa3d141e34da06cf425", size = 370157, upload-time = "2025-11-30T20:21:53.789Z" }, - { url = "https://files.pythonhosted.org/packages/94/ba/24e5ebb7c1c82e74c4e4f33b2112a5573ddc703915b13a073737b59b86e0/rpds_py-0.30.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dc4f992dfe1e2bc3ebc7444f6c7051b4bc13cd8e33e43511e8ffd13bf407010d", size = 359676, upload-time = "2025-11-30T20:21:55.475Z" }, - { url = "https://files.pythonhosted.org/packages/84/86/04dbba1b087227747d64d80c3b74df946b986c57af0a9f0c98726d4d7a3b/rpds_py-0.30.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:422c3cb9856d80b09d30d2eb255d0754b23e090034e1deb4083f8004bd0761e4", size = 389938, upload-time = "2025-11-30T20:21:57.079Z" }, - { url = "https://files.pythonhosted.org/packages/42/bb/1463f0b1722b7f45431bdd468301991d1328b16cffe0b1c2918eba2c4eee/rpds_py-0.30.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:07ae8a593e1c3c6b82ca3292efbe73c30b61332fd612e05abee07c79359f292f", size = 402932, upload-time = "2025-11-30T20:21:58.47Z" }, - { url = "https://files.pythonhosted.org/packages/99/ee/2520700a5c1f2d76631f948b0736cdf9b0acb25abd0ca8e889b5c62ac2e3/rpds_py-0.30.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:12f90dd7557b6bd57f40abe7747e81e0c0b119bef015ea7726e69fe550e394a4", size = 525830, upload-time = "2025-11-30T20:21:59.699Z" }, - { url = "https://files.pythonhosted.org/packages/e0/ad/bd0331f740f5705cc555a5e17fdf334671262160270962e69a2bdef3bf76/rpds_py-0.30.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:99b47d6ad9a6da00bec6aabe5a6279ecd3c06a329d4aa4771034a21e335c3a97", size = 412033, upload-time = "2025-11-30T20:22:00.991Z" }, - { url = "https://files.pythonhosted.org/packages/f8/1e/372195d326549bb51f0ba0f2ecb9874579906b97e08880e7a65c3bef1a99/rpds_py-0.30.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:33f559f3104504506a44bb666b93a33f5d33133765b0c216a5bf2f1e1503af89", size = 390828, upload-time = "2025-11-30T20:22:02.723Z" }, - { url = "https://files.pythonhosted.org/packages/ab/2b/d88bb33294e3e0c76bc8f351a3721212713629ffca1700fa94979cb3eae8/rpds_py-0.30.0-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:946fe926af6e44f3697abbc305ea168c2c31d3e3ef1058cf68f379bf0335a78d", size = 404683, upload-time = "2025-11-30T20:22:04.367Z" }, - { url = "https://files.pythonhosted.org/packages/50/32/c759a8d42bcb5289c1fac697cd92f6fe01a018dd937e62ae77e0e7f15702/rpds_py-0.30.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:495aeca4b93d465efde585977365187149e75383ad2684f81519f504f5c13038", size = 421583, upload-time = "2025-11-30T20:22:05.814Z" }, - { url = "https://files.pythonhosted.org/packages/2b/81/e729761dbd55ddf5d84ec4ff1f47857f4374b0f19bdabfcf929164da3e24/rpds_py-0.30.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d9a0ca5da0386dee0655b4ccdf46119df60e0f10da268d04fe7cc87886872ba7", size = 572496, upload-time = "2025-11-30T20:22:07.713Z" }, - { url = "https://files.pythonhosted.org/packages/14/f6/69066a924c3557c9c30baa6ec3a0aa07526305684c6f86c696b08860726c/rpds_py-0.30.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8d6d1cc13664ec13c1b84241204ff3b12f9bb82464b8ad6e7a5d3486975c2eed", size = 598669, upload-time = "2025-11-30T20:22:09.312Z" }, - { url = "https://files.pythonhosted.org/packages/5f/48/905896b1eb8a05630d20333d1d8ffd162394127b74ce0b0784ae04498d32/rpds_py-0.30.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3896fa1be39912cf0757753826bc8bdc8ca331a28a7c4ae46b7a21280b06bb85", size = 561011, upload-time = "2025-11-30T20:22:11.309Z" }, - { url = "https://files.pythonhosted.org/packages/22/16/cd3027c7e279d22e5eb431dd3c0fbc677bed58797fe7581e148f3f68818b/rpds_py-0.30.0-cp311-cp311-win32.whl", hash = "sha256:55f66022632205940f1827effeff17c4fa7ae1953d2b74a8581baaefb7d16f8c", size = 221406, upload-time = "2025-11-30T20:22:13.101Z" }, - { url = "https://files.pythonhosted.org/packages/fa/5b/e7b7aa136f28462b344e652ee010d4de26ee9fd16f1bfd5811f5153ccf89/rpds_py-0.30.0-cp311-cp311-win_amd64.whl", hash = "sha256:a51033ff701fca756439d641c0ad09a41d9242fa69121c7d8769604a0a629825", size = 236024, upload-time = "2025-11-30T20:22:14.853Z" }, - { url = "https://files.pythonhosted.org/packages/14/a6/364bba985e4c13658edb156640608f2c9e1d3ea3c81b27aa9d889fff0e31/rpds_py-0.30.0-cp311-cp311-win_arm64.whl", hash = "sha256:47b0ef6231c58f506ef0b74d44e330405caa8428e770fec25329ed2cb971a229", size = 229069, upload-time = "2025-11-30T20:22:16.577Z" }, - { url = "https://files.pythonhosted.org/packages/03/e7/98a2f4ac921d82f33e03f3835f5bf3a4a40aa1bfdc57975e74a97b2b4bdd/rpds_py-0.30.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a161f20d9a43006833cd7068375a94d035714d73a172b681d8881820600abfad", size = 375086, upload-time = "2025-11-30T20:22:17.93Z" }, - { url = "https://files.pythonhosted.org/packages/4d/a1/bca7fd3d452b272e13335db8d6b0b3ecde0f90ad6f16f3328c6fb150c889/rpds_py-0.30.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6abc8880d9d036ecaafe709079969f56e876fcf107f7a8e9920ba6d5a3878d05", size = 359053, upload-time = "2025-11-30T20:22:19.297Z" }, - { url = "https://files.pythonhosted.org/packages/65/1c/ae157e83a6357eceff62ba7e52113e3ec4834a84cfe07fa4b0757a7d105f/rpds_py-0.30.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca28829ae5f5d569bb62a79512c842a03a12576375d5ece7d2cadf8abe96ec28", size = 390763, upload-time = "2025-11-30T20:22:21.661Z" }, - { url = "https://files.pythonhosted.org/packages/d4/36/eb2eb8515e2ad24c0bd43c3ee9cd74c33f7ca6430755ccdb240fd3144c44/rpds_py-0.30.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a1010ed9524c73b94d15919ca4d41d8780980e1765babf85f9a2f90d247153dd", size = 408951, upload-time = "2025-11-30T20:22:23.408Z" }, - { url = "https://files.pythonhosted.org/packages/d6/65/ad8dc1784a331fabbd740ef6f71ce2198c7ed0890dab595adb9ea2d775a1/rpds_py-0.30.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f8d1736cfb49381ba528cd5baa46f82fdc65c06e843dab24dd70b63d09121b3f", size = 514622, upload-time = "2025-11-30T20:22:25.16Z" }, - { url = "https://files.pythonhosted.org/packages/63/8e/0cfa7ae158e15e143fe03993b5bcd743a59f541f5952e1546b1ac1b5fd45/rpds_py-0.30.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d948b135c4693daff7bc2dcfc4ec57237a29bd37e60c2fabf5aff2bbacf3e2f1", size = 414492, upload-time = "2025-11-30T20:22:26.505Z" }, - { url = "https://files.pythonhosted.org/packages/60/1b/6f8f29f3f995c7ffdde46a626ddccd7c63aefc0efae881dc13b6e5d5bb16/rpds_py-0.30.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47f236970bccb2233267d89173d3ad2703cd36a0e2a6e92d0560d333871a3d23", size = 394080, upload-time = "2025-11-30T20:22:27.934Z" }, - { url = "https://files.pythonhosted.org/packages/6d/d5/a266341051a7a3ca2f4b750a3aa4abc986378431fc2da508c5034d081b70/rpds_py-0.30.0-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:2e6ecb5a5bcacf59c3f912155044479af1d0b6681280048b338b28e364aca1f6", size = 408680, upload-time = "2025-11-30T20:22:29.341Z" }, - { url = "https://files.pythonhosted.org/packages/10/3b/71b725851df9ab7a7a4e33cf36d241933da66040d195a84781f49c50490c/rpds_py-0.30.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a8fa71a2e078c527c3e9dc9fc5a98c9db40bcc8a92b4e8858e36d329f8684b51", size = 423589, upload-time = "2025-11-30T20:22:31.469Z" }, - { url = "https://files.pythonhosted.org/packages/00/2b/e59e58c544dc9bd8bd8384ecdb8ea91f6727f0e37a7131baeff8d6f51661/rpds_py-0.30.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:73c67f2db7bc334e518d097c6d1e6fed021bbc9b7d678d6cc433478365d1d5f5", size = 573289, upload-time = "2025-11-30T20:22:32.997Z" }, - { url = "https://files.pythonhosted.org/packages/da/3e/a18e6f5b460893172a7d6a680e86d3b6bc87a54c1f0b03446a3c8c7b588f/rpds_py-0.30.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:5ba103fb455be00f3b1c2076c9d4264bfcb037c976167a6047ed82f23153f02e", size = 599737, upload-time = "2025-11-30T20:22:34.419Z" }, - { url = "https://files.pythonhosted.org/packages/5c/e2/714694e4b87b85a18e2c243614974413c60aa107fd815b8cbc42b873d1d7/rpds_py-0.30.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7cee9c752c0364588353e627da8a7e808a66873672bcb5f52890c33fd965b394", size = 563120, upload-time = "2025-11-30T20:22:35.903Z" }, - { url = "https://files.pythonhosted.org/packages/6f/ab/d5d5e3bcedb0a77f4f613706b750e50a5a3ba1c15ccd3665ecc636c968fd/rpds_py-0.30.0-cp312-cp312-win32.whl", hash = "sha256:1ab5b83dbcf55acc8b08fc62b796ef672c457b17dbd7820a11d6c52c06839bdf", size = 223782, upload-time = "2025-11-30T20:22:37.271Z" }, - { url = "https://files.pythonhosted.org/packages/39/3b/f786af9957306fdc38a74cef405b7b93180f481fb48453a114bb6465744a/rpds_py-0.30.0-cp312-cp312-win_amd64.whl", hash = "sha256:a090322ca841abd453d43456ac34db46e8b05fd9b3b4ac0c78bcde8b089f959b", size = 240463, upload-time = "2025-11-30T20:22:39.021Z" }, - { url = "https://files.pythonhosted.org/packages/f3/d2/b91dc748126c1559042cfe41990deb92c4ee3e2b415f6b5234969ffaf0cc/rpds_py-0.30.0-cp312-cp312-win_arm64.whl", hash = "sha256:669b1805bd639dd2989b281be2cfd951c6121b65e729d9b843e9639ef1fd555e", size = 230868, upload-time = "2025-11-30T20:22:40.493Z" }, - { 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" }, - { url = "https://files.pythonhosted.org/packages/69/71/3f34339ee70521864411f8b6992e7ab13ac30d8e4e3309e07c7361767d91/rpds_py-0.30.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:c2262bdba0ad4fc6fb5545660673925c2d2a5d9e2e0fb603aad545427be0fc58", size = 372292, upload-time = "2025-11-30T20:24:16.537Z" }, - { url = "https://files.pythonhosted.org/packages/57/09/f183df9b8f2d66720d2ef71075c59f7e1b336bec7ee4c48f0a2b06857653/rpds_py-0.30.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:ee6af14263f25eedc3bb918a3c04245106a42dfd4f5c2285ea6f997b1fc3f89a", size = 362128, upload-time = "2025-11-30T20:24:18.086Z" }, - { url = "https://files.pythonhosted.org/packages/7a/68/5c2594e937253457342e078f0cc1ded3dd7b2ad59afdbf2d354869110a02/rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3adbb8179ce342d235c31ab8ec511e66c73faa27a47e076ccc92421add53e2bb", size = 391542, upload-time = "2025-11-30T20:24:20.092Z" }, - { url = "https://files.pythonhosted.org/packages/49/5c/31ef1afd70b4b4fbdb2800249f34c57c64beb687495b10aec0365f53dfc4/rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:250fa00e9543ac9b97ac258bd37367ff5256666122c2d0f2bc97577c60a1818c", size = 404004, upload-time = "2025-11-30T20:24:22.231Z" }, - { url = "https://files.pythonhosted.org/packages/e3/63/0cfbea38d05756f3440ce6534d51a491d26176ac045e2707adc99bb6e60a/rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9854cf4f488b3d57b9aaeb105f06d78e5529d3145b1e4a41750167e8c213c6d3", size = 527063, upload-time = "2025-11-30T20:24:24.302Z" }, - { url = "https://files.pythonhosted.org/packages/42/e6/01e1f72a2456678b0f618fc9a1a13f882061690893c192fcad9f2926553a/rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:993914b8e560023bc0a8bf742c5f303551992dcb85e247b1e5c7f4a7d145bda5", size = 413099, upload-time = "2025-11-30T20:24:25.916Z" }, - { url = "https://files.pythonhosted.org/packages/b8/25/8df56677f209003dcbb180765520c544525e3ef21ea72279c98b9aa7c7fb/rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58edca431fb9b29950807e301826586e5bbf24163677732429770a697ffe6738", size = 392177, upload-time = "2025-11-30T20:24:27.834Z" }, - { url = "https://files.pythonhosted.org/packages/4a/b4/0a771378c5f16f8115f796d1f437950158679bcd2a7c68cf251cfb00ed5b/rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_31_riscv64.whl", hash = "sha256:dea5b552272a944763b34394d04577cf0f9bd013207bc32323b5a89a53cf9c2f", size = 406015, upload-time = "2025-11-30T20:24:29.457Z" }, - { url = "https://files.pythonhosted.org/packages/36/d8/456dbba0af75049dc6f63ff295a2f92766b9d521fa00de67a2bd6427d57a/rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ba3af48635eb83d03f6c9735dfb21785303e73d22ad03d489e88adae6eab8877", size = 423736, upload-time = "2025-11-30T20:24:31.22Z" }, - { url = "https://files.pythonhosted.org/packages/13/64/b4d76f227d5c45a7e0b796c674fd81b0a6c4fbd48dc29271857d8219571c/rpds_py-0.30.0-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:dff13836529b921e22f15cb099751209a60009731a68519630a24d61f0b1b30a", size = 573981, upload-time = "2025-11-30T20:24:32.934Z" }, - { url = "https://files.pythonhosted.org/packages/20/91/092bacadeda3edf92bf743cc96a7be133e13a39cdbfd7b5082e7ab638406/rpds_py-0.30.0-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:1b151685b23929ab7beec71080a8889d4d6d9fa9a983d213f07121205d48e2c4", size = 599782, upload-time = "2025-11-30T20:24:35.169Z" }, - { url = "https://files.pythonhosted.org/packages/d1/b7/b95708304cd49b7b6f82fdd039f1748b66ec2b21d6a45180910802f1abf1/rpds_py-0.30.0-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:ac37f9f516c51e5753f27dfdef11a88330f04de2d564be3991384b2f3535d02e", size = 562191, upload-time = "2025-11-30T20:24:36.853Z" }, +wheels = [ + {url = "https://files.pythonhosted.org/packages/4d/6e/f964e88b3d2abee2a82c1ac8366da848fce1c6d834dc2132c3fda3970290/rpds_py-0.30.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:a2bffea6a4ca9f01b3f8e548302470306689684e61602aa3d141e34da06cf425", size = 370157, upload-time = "2025-11-30T20:21:53.789Z"}, + {url = "https://files.pythonhosted.org/packages/94/ba/24e5ebb7c1c82e74c4e4f33b2112a5573ddc703915b13a073737b59b86e0/rpds_py-0.30.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dc4f992dfe1e2bc3ebc7444f6c7051b4bc13cd8e33e43511e8ffd13bf407010d", size = 359676, upload-time = "2025-11-30T20:21:55.475Z"}, + {url = "https://files.pythonhosted.org/packages/84/86/04dbba1b087227747d64d80c3b74df946b986c57af0a9f0c98726d4d7a3b/rpds_py-0.30.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:422c3cb9856d80b09d30d2eb255d0754b23e090034e1deb4083f8004bd0761e4", size = 389938, upload-time = "2025-11-30T20:21:57.079Z"}, + {url = "https://files.pythonhosted.org/packages/42/bb/1463f0b1722b7f45431bdd468301991d1328b16cffe0b1c2918eba2c4eee/rpds_py-0.30.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:07ae8a593e1c3c6b82ca3292efbe73c30b61332fd612e05abee07c79359f292f", size = 402932, upload-time = "2025-11-30T20:21:58.47Z"}, + {url = "https://files.pythonhosted.org/packages/99/ee/2520700a5c1f2d76631f948b0736cdf9b0acb25abd0ca8e889b5c62ac2e3/rpds_py-0.30.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:12f90dd7557b6bd57f40abe7747e81e0c0b119bef015ea7726e69fe550e394a4", size = 525830, upload-time = "2025-11-30T20:21:59.699Z"}, + {url = "https://files.pythonhosted.org/packages/e0/ad/bd0331f740f5705cc555a5e17fdf334671262160270962e69a2bdef3bf76/rpds_py-0.30.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:99b47d6ad9a6da00bec6aabe5a6279ecd3c06a329d4aa4771034a21e335c3a97", size = 412033, upload-time = "2025-11-30T20:22:00.991Z"}, + {url = "https://files.pythonhosted.org/packages/f8/1e/372195d326549bb51f0ba0f2ecb9874579906b97e08880e7a65c3bef1a99/rpds_py-0.30.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:33f559f3104504506a44bb666b93a33f5d33133765b0c216a5bf2f1e1503af89", size = 390828, upload-time = "2025-11-30T20:22:02.723Z"}, + {url = "https://files.pythonhosted.org/packages/ab/2b/d88bb33294e3e0c76bc8f351a3721212713629ffca1700fa94979cb3eae8/rpds_py-0.30.0-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:946fe926af6e44f3697abbc305ea168c2c31d3e3ef1058cf68f379bf0335a78d", size = 404683, upload-time = "2025-11-30T20:22:04.367Z"}, + {url = "https://files.pythonhosted.org/packages/50/32/c759a8d42bcb5289c1fac697cd92f6fe01a018dd937e62ae77e0e7f15702/rpds_py-0.30.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:495aeca4b93d465efde585977365187149e75383ad2684f81519f504f5c13038", size = 421583, upload-time = "2025-11-30T20:22:05.814Z"}, + {url = "https://files.pythonhosted.org/packages/2b/81/e729761dbd55ddf5d84ec4ff1f47857f4374b0f19bdabfcf929164da3e24/rpds_py-0.30.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d9a0ca5da0386dee0655b4ccdf46119df60e0f10da268d04fe7cc87886872ba7", size = 572496, upload-time = "2025-11-30T20:22:07.713Z"}, + {url = "https://files.pythonhosted.org/packages/14/f6/69066a924c3557c9c30baa6ec3a0aa07526305684c6f86c696b08860726c/rpds_py-0.30.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8d6d1cc13664ec13c1b84241204ff3b12f9bb82464b8ad6e7a5d3486975c2eed", size = 598669, upload-time = "2025-11-30T20:22:09.312Z"}, + {url = "https://files.pythonhosted.org/packages/5f/48/905896b1eb8a05630d20333d1d8ffd162394127b74ce0b0784ae04498d32/rpds_py-0.30.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3896fa1be39912cf0757753826bc8bdc8ca331a28a7c4ae46b7a21280b06bb85", size = 561011, upload-time = "2025-11-30T20:22:11.309Z"}, + {url = "https://files.pythonhosted.org/packages/22/16/cd3027c7e279d22e5eb431dd3c0fbc677bed58797fe7581e148f3f68818b/rpds_py-0.30.0-cp311-cp311-win32.whl", hash = "sha256:55f66022632205940f1827effeff17c4fa7ae1953d2b74a8581baaefb7d16f8c", size = 221406, upload-time = "2025-11-30T20:22:13.101Z"}, + {url = "https://files.pythonhosted.org/packages/fa/5b/e7b7aa136f28462b344e652ee010d4de26ee9fd16f1bfd5811f5153ccf89/rpds_py-0.30.0-cp311-cp311-win_amd64.whl", hash = "sha256:a51033ff701fca756439d641c0ad09a41d9242fa69121c7d8769604a0a629825", size = 236024, upload-time = "2025-11-30T20:22:14.853Z"}, + {url = "https://files.pythonhosted.org/packages/14/a6/364bba985e4c13658edb156640608f2c9e1d3ea3c81b27aa9d889fff0e31/rpds_py-0.30.0-cp311-cp311-win_arm64.whl", hash = "sha256:47b0ef6231c58f506ef0b74d44e330405caa8428e770fec25329ed2cb971a229", size = 229069, upload-time = "2025-11-30T20:22:16.577Z"}, + {url = "https://files.pythonhosted.org/packages/03/e7/98a2f4ac921d82f33e03f3835f5bf3a4a40aa1bfdc57975e74a97b2b4bdd/rpds_py-0.30.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a161f20d9a43006833cd7068375a94d035714d73a172b681d8881820600abfad", size = 375086, upload-time = "2025-11-30T20:22:17.93Z"}, + {url = "https://files.pythonhosted.org/packages/4d/a1/bca7fd3d452b272e13335db8d6b0b3ecde0f90ad6f16f3328c6fb150c889/rpds_py-0.30.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6abc8880d9d036ecaafe709079969f56e876fcf107f7a8e9920ba6d5a3878d05", size = 359053, upload-time = "2025-11-30T20:22:19.297Z"}, + {url = "https://files.pythonhosted.org/packages/65/1c/ae157e83a6357eceff62ba7e52113e3ec4834a84cfe07fa4b0757a7d105f/rpds_py-0.30.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca28829ae5f5d569bb62a79512c842a03a12576375d5ece7d2cadf8abe96ec28", size = 390763, upload-time = "2025-11-30T20:22:21.661Z"}, + {url = "https://files.pythonhosted.org/packages/d4/36/eb2eb8515e2ad24c0bd43c3ee9cd74c33f7ca6430755ccdb240fd3144c44/rpds_py-0.30.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a1010ed9524c73b94d15919ca4d41d8780980e1765babf85f9a2f90d247153dd", size = 408951, upload-time = "2025-11-30T20:22:23.408Z"}, + {url = "https://files.pythonhosted.org/packages/d6/65/ad8dc1784a331fabbd740ef6f71ce2198c7ed0890dab595adb9ea2d775a1/rpds_py-0.30.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f8d1736cfb49381ba528cd5baa46f82fdc65c06e843dab24dd70b63d09121b3f", size = 514622, upload-time = "2025-11-30T20:22:25.16Z"}, + {url = "https://files.pythonhosted.org/packages/63/8e/0cfa7ae158e15e143fe03993b5bcd743a59f541f5952e1546b1ac1b5fd45/rpds_py-0.30.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d948b135c4693daff7bc2dcfc4ec57237a29bd37e60c2fabf5aff2bbacf3e2f1", size = 414492, upload-time = "2025-11-30T20:22:26.505Z"}, + {url = "https://files.pythonhosted.org/packages/60/1b/6f8f29f3f995c7ffdde46a626ddccd7c63aefc0efae881dc13b6e5d5bb16/rpds_py-0.30.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47f236970bccb2233267d89173d3ad2703cd36a0e2a6e92d0560d333871a3d23", size = 394080, upload-time = "2025-11-30T20:22:27.934Z"}, + {url = "https://files.pythonhosted.org/packages/6d/d5/a266341051a7a3ca2f4b750a3aa4abc986378431fc2da508c5034d081b70/rpds_py-0.30.0-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:2e6ecb5a5bcacf59c3f912155044479af1d0b6681280048b338b28e364aca1f6", size = 408680, upload-time = "2025-11-30T20:22:29.341Z"}, + {url = "https://files.pythonhosted.org/packages/10/3b/71b725851df9ab7a7a4e33cf36d241933da66040d195a84781f49c50490c/rpds_py-0.30.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a8fa71a2e078c527c3e9dc9fc5a98c9db40bcc8a92b4e8858e36d329f8684b51", size = 423589, upload-time = "2025-11-30T20:22:31.469Z"}, + {url = "https://files.pythonhosted.org/packages/00/2b/e59e58c544dc9bd8bd8384ecdb8ea91f6727f0e37a7131baeff8d6f51661/rpds_py-0.30.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:73c67f2db7bc334e518d097c6d1e6fed021bbc9b7d678d6cc433478365d1d5f5", size = 573289, upload-time = "2025-11-30T20:22:32.997Z"}, + {url = "https://files.pythonhosted.org/packages/da/3e/a18e6f5b460893172a7d6a680e86d3b6bc87a54c1f0b03446a3c8c7b588f/rpds_py-0.30.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:5ba103fb455be00f3b1c2076c9d4264bfcb037c976167a6047ed82f23153f02e", size = 599737, upload-time = "2025-11-30T20:22:34.419Z"}, + {url = "https://files.pythonhosted.org/packages/5c/e2/714694e4b87b85a18e2c243614974413c60aa107fd815b8cbc42b873d1d7/rpds_py-0.30.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7cee9c752c0364588353e627da8a7e808a66873672bcb5f52890c33fd965b394", size = 563120, upload-time = "2025-11-30T20:22:35.903Z"}, + {url = "https://files.pythonhosted.org/packages/6f/ab/d5d5e3bcedb0a77f4f613706b750e50a5a3ba1c15ccd3665ecc636c968fd/rpds_py-0.30.0-cp312-cp312-win32.whl", hash = "sha256:1ab5b83dbcf55acc8b08fc62b796ef672c457b17dbd7820a11d6c52c06839bdf", size = 223782, upload-time = "2025-11-30T20:22:37.271Z"}, + {url = "https://files.pythonhosted.org/packages/39/3b/f786af9957306fdc38a74cef405b7b93180f481fb48453a114bb6465744a/rpds_py-0.30.0-cp312-cp312-win_amd64.whl", hash = "sha256:a090322ca841abd453d43456ac34db46e8b05fd9b3b4ac0c78bcde8b089f959b", size = 240463, upload-time = "2025-11-30T20:22:39.021Z"}, + {url = "https://files.pythonhosted.org/packages/f3/d2/b91dc748126c1559042cfe41990deb92c4ee3e2b415f6b5234969ffaf0cc/rpds_py-0.30.0-cp312-cp312-win_arm64.whl", hash = "sha256:669b1805bd639dd2989b281be2cfd951c6121b65e729d9b843e9639ef1fd555e", size = 230868, upload-time = "2025-11-30T20:22:40.493Z"}, + {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"}, + {url = "https://files.pythonhosted.org/packages/69/71/3f34339ee70521864411f8b6992e7ab13ac30d8e4e3309e07c7361767d91/rpds_py-0.30.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:c2262bdba0ad4fc6fb5545660673925c2d2a5d9e2e0fb603aad545427be0fc58", size = 372292, upload-time = "2025-11-30T20:24:16.537Z"}, + {url = "https://files.pythonhosted.org/packages/57/09/f183df9b8f2d66720d2ef71075c59f7e1b336bec7ee4c48f0a2b06857653/rpds_py-0.30.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:ee6af14263f25eedc3bb918a3c04245106a42dfd4f5c2285ea6f997b1fc3f89a", size = 362128, upload-time = "2025-11-30T20:24:18.086Z"}, + {url = "https://files.pythonhosted.org/packages/7a/68/5c2594e937253457342e078f0cc1ded3dd7b2ad59afdbf2d354869110a02/rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3adbb8179ce342d235c31ab8ec511e66c73faa27a47e076ccc92421add53e2bb", size = 391542, upload-time = "2025-11-30T20:24:20.092Z"}, + {url = "https://files.pythonhosted.org/packages/49/5c/31ef1afd70b4b4fbdb2800249f34c57c64beb687495b10aec0365f53dfc4/rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:250fa00e9543ac9b97ac258bd37367ff5256666122c2d0f2bc97577c60a1818c", size = 404004, upload-time = "2025-11-30T20:24:22.231Z"}, + {url = "https://files.pythonhosted.org/packages/e3/63/0cfbea38d05756f3440ce6534d51a491d26176ac045e2707adc99bb6e60a/rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9854cf4f488b3d57b9aaeb105f06d78e5529d3145b1e4a41750167e8c213c6d3", size = 527063, upload-time = "2025-11-30T20:24:24.302Z"}, + {url = "https://files.pythonhosted.org/packages/42/e6/01e1f72a2456678b0f618fc9a1a13f882061690893c192fcad9f2926553a/rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:993914b8e560023bc0a8bf742c5f303551992dcb85e247b1e5c7f4a7d145bda5", size = 413099, upload-time = "2025-11-30T20:24:25.916Z"}, + {url = "https://files.pythonhosted.org/packages/b8/25/8df56677f209003dcbb180765520c544525e3ef21ea72279c98b9aa7c7fb/rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58edca431fb9b29950807e301826586e5bbf24163677732429770a697ffe6738", size = 392177, upload-time = "2025-11-30T20:24:27.834Z"}, + {url = "https://files.pythonhosted.org/packages/4a/b4/0a771378c5f16f8115f796d1f437950158679bcd2a7c68cf251cfb00ed5b/rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_31_riscv64.whl", hash = "sha256:dea5b552272a944763b34394d04577cf0f9bd013207bc32323b5a89a53cf9c2f", size = 406015, upload-time = "2025-11-30T20:24:29.457Z"}, + {url = "https://files.pythonhosted.org/packages/36/d8/456dbba0af75049dc6f63ff295a2f92766b9d521fa00de67a2bd6427d57a/rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ba3af48635eb83d03f6c9735dfb21785303e73d22ad03d489e88adae6eab8877", size = 423736, upload-time = "2025-11-30T20:24:31.22Z"}, + {url = "https://files.pythonhosted.org/packages/13/64/b4d76f227d5c45a7e0b796c674fd81b0a6c4fbd48dc29271857d8219571c/rpds_py-0.30.0-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:dff13836529b921e22f15cb099751209a60009731a68519630a24d61f0b1b30a", size = 573981, upload-time = "2025-11-30T20:24:32.934Z"}, + {url = "https://files.pythonhosted.org/packages/20/91/092bacadeda3edf92bf743cc96a7be133e13a39cdbfd7b5082e7ab638406/rpds_py-0.30.0-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:1b151685b23929ab7beec71080a8889d4d6d9fa9a983d213f07121205d48e2c4", size = 599782, upload-time = "2025-11-30T20:24:35.169Z"}, + {url = "https://files.pythonhosted.org/packages/d1/b7/b95708304cd49b7b6f82fdd039f1748b66ec2b21d6a45180910802f1abf1/rpds_py-0.30.0-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:ac37f9f516c51e5753f27dfdef11a88330f04de2d564be3991384b2f3535d02e", size = 562191, upload-time = "2025-11-30T20:24:36.853Z"} ] [[package]] name = "six" +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"} +source = {registry = "https://pypi.org/simple"} 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" }, + {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 = "sortedcontainers" +sdist = {url = "https://files.pythonhosted.org/packages/e8/c4/ba2f8066cceb6f23394729afe52f3bf7adec04bf9ed2c820b39e19299111/sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88", size = 30594, upload-time = "2021-05-16T22:03:42.897Z"} +source = {registry = "https://pypi.org/simple"} version = "2.4.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e8/c4/ba2f8066cceb6f23394729afe52f3bf7adec04bf9ed2c820b39e19299111/sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88", size = 30594, upload-time = "2021-05-16T22:03:42.897Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/32/46/9cb0e58b2deb7f82b84065f37f3bffeb12413f947f9388e4cac22c4621ce/sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0", size = 29575, upload-time = "2021-05-16T22:03:41.177Z" }, + {url = "https://files.pythonhosted.org/packages/32/46/9cb0e58b2deb7f82b84065f37f3bffeb12413f947f9388e4cac22c4621ce/sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0", size = 29575, upload-time = "2021-05-16T22:03:41.177Z"} ] [[package]] -name = "stack-data" -version = "0.6.3" -source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "asttokens" }, - { name = "executing" }, - { name = "pure-eval" }, + {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" } +name = "stack-data" +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"} +source = {registry = "https://pypi.org/simple"} +version = "0.6.3" 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" }, + {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 = "termcolor" +sdist = {url = "https://files.pythonhosted.org/packages/46/79/cf31d7a93a8fdc6aa0fbb665be84426a8c5a557d9240b6239e9e11e35fc5/termcolor-3.3.0.tar.gz", hash = "sha256:348871ca648ec6a9a983a13ab626c0acce02f515b9e1983332b17af7979521c5", size = 14434, upload-time = "2025-12-29T12:55:21.882Z"} +source = {registry = "https://pypi.org/simple"} version = "3.3.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/46/79/cf31d7a93a8fdc6aa0fbb665be84426a8c5a557d9240b6239e9e11e35fc5/termcolor-3.3.0.tar.gz", hash = "sha256:348871ca648ec6a9a983a13ab626c0acce02f515b9e1983332b17af7979521c5", size = 14434, upload-time = "2025-12-29T12:55:21.882Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/33/d1/8bb87d21e9aeb323cc03034f5eaf2c8f69841e40e4853c2627edf8111ed3/termcolor-3.3.0-py3-none-any.whl", hash = "sha256:cf642efadaf0a8ebbbf4bc7a31cec2f9b5f21a9f726f4ccbb08192c9c26f43a5", size = 7734, upload-time = "2025-12-29T12:55:20.718Z" }, + {url = "https://files.pythonhosted.org/packages/33/d1/8bb87d21e9aeb323cc03034f5eaf2c8f69841e40e4853c2627edf8111ed3/termcolor-3.3.0-py3-none-any.whl", hash = "sha256:cf642efadaf0a8ebbbf4bc7a31cec2f9b5f21a9f726f4ccbb08192c9c26f43a5", size = 7734, upload-time = "2025-12-29T12:55:20.718Z"} ] [[package]] name = "toolz" +sdist = {url = "https://files.pythonhosted.org/packages/11/d6/114b492226588d6ff54579d95847662fc69196bdeec318eb45393b24c192/toolz-1.1.0.tar.gz", hash = "sha256:27a5c770d068c110d9ed9323f24f1543e83b2f300a687b7891c1a6d56b697b5b", size = 52613, upload-time = "2025-10-17T04:03:21.661Z"} +source = {registry = "https://pypi.org/simple"} version = "1.1.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/11/d6/114b492226588d6ff54579d95847662fc69196bdeec318eb45393b24c192/toolz-1.1.0.tar.gz", hash = "sha256:27a5c770d068c110d9ed9323f24f1543e83b2f300a687b7891c1a6d56b697b5b", size = 52613, upload-time = "2025-10-17T04:03:21.661Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-py3-none-any.whl", hash = "sha256:15ccc861ac51c53696de0a5d6d4607f99c210739caf987b5d2054f3efed429d8", size = 58093, upload-time = "2025-10-17T04:03:20.435Z" }, + {url = "https://files.pythonhosted.org/packages/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-py3-none-any.whl", hash = "sha256:15ccc861ac51c53696de0a5d6d4607f99c210739caf987b5d2054f3efed429d8", size = 58093, upload-time = "2025-10-17T04:03:20.435Z"} ] [[package]] name = "tornado" +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"} +source = {registry = "https://pypi.org/simple"} 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" }, + {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 = "tqdm" -version = "4.67.3" -source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "colorama", marker = "sys_platform == 'win32'" }, + {name = "colorama", marker = "sys_platform == 'win32'"} ] -sdist = { url = "https://files.pythonhosted.org/packages/09/a9/6ba95a270c6f1fbcd8dac228323f2777d886cb206987444e4bce66338dd4/tqdm-4.67.3.tar.gz", hash = "sha256:7d825f03f89244ef73f1d4ce193cb1774a8179fd96f31d7e1dcde62092b960bb", size = 169598, upload-time = "2026-02-03T17:35:53.048Z" } +name = "tqdm" +sdist = {url = "https://files.pythonhosted.org/packages/09/a9/6ba95a270c6f1fbcd8dac228323f2777d886cb206987444e4bce66338dd4/tqdm-4.67.3.tar.gz", hash = "sha256:7d825f03f89244ef73f1d4ce193cb1774a8179fd96f31d7e1dcde62092b960bb", size = 169598, upload-time = "2026-02-03T17:35:53.048Z"} +source = {registry = "https://pypi.org/simple"} +version = "4.67.3" wheels = [ - { url = "https://files.pythonhosted.org/packages/16/e1/3079a9ff9b8e11b846c6ac5c8b5bfb7ff225eee721825310c91b3b50304f/tqdm-4.67.3-py3-none-any.whl", hash = "sha256:ee1e4c0e59148062281c49d80b25b67771a127c85fc9676d3be5f243206826bf", size = 78374, upload-time = "2026-02-03T17:35:50.982Z" }, + {url = "https://files.pythonhosted.org/packages/16/e1/3079a9ff9b8e11b846c6ac5c8b5bfb7ff225eee721825310c91b3b50304f/tqdm-4.67.3-py3-none-any.whl", hash = "sha256:ee1e4c0e59148062281c49d80b25b67771a127c85fc9676d3be5f243206826bf", size = 78374, upload-time = "2026-02-03T17:35:50.982Z"} ] [[package]] name = "traitlets" +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"} +source = {registry = "https://pypi.org/simple"} 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" }, + {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 = "ty" +sdist = {url = "https://files.pythonhosted.org/packages/47/e5/15b6aceefcd64b53997fe2002b6fa055f0b1afd23ff6fc3f55f3da944530/ty-0.0.2.tar.gz", hash = "sha256:e02dc50b65dc58d6cb8e8b0d563833f81bf03ed8a7d0b15c6396d486489a7e1d", size = 4762024, upload-time = "2025-12-16T20:13:41.07Z"} +source = {registry = "https://pypi.org/simple"} version = "0.0.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/47/e5/15b6aceefcd64b53997fe2002b6fa055f0b1afd23ff6fc3f55f3da944530/ty-0.0.2.tar.gz", hash = "sha256:e02dc50b65dc58d6cb8e8b0d563833f81bf03ed8a7d0b15c6396d486489a7e1d", size = 4762024, upload-time = "2025-12-16T20:13:41.07Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/6b/86/65d4826677d966cf226662767a4a597ebb4b02c432f413673c8d5d3d1ce8/ty-0.0.2-py3-none-linux_armv6l.whl", hash = "sha256:0954a0e0b6f7e06229dd1da3a9989ee9b881a26047139a88eb7c134c585ad22e", size = 9771409, upload-time = "2025-12-16T20:13:28.964Z" }, - { url = "https://files.pythonhosted.org/packages/d4/bc/6ab06b7c109cec608c24ea182cc8b4714e746a132f70149b759817092665/ty-0.0.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:d6044b491d66933547033cecc87cb7eb599ba026a3ef347285add6b21107a648", size = 9580025, upload-time = "2025-12-16T20:13:34.507Z" }, - { url = "https://files.pythonhosted.org/packages/54/de/d826804e304b2430f17bb27ae15bcf02380e7f67f38b5033047e3d2523e6/ty-0.0.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:fbca7f08e671a35229f6f400d73da92e2dc0a440fba53a74fe8233079a504358", size = 9098660, upload-time = "2025-12-16T20:13:01.278Z" }, - { url = "https://files.pythonhosted.org/packages/b7/8e/5cd87944ceee02bb0826f19ced54e30c6bb971e985a22768f6be6b1a042f/ty-0.0.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3abd61153dac0b93b284d305e6f96085013a25c3a7ab44e988d24f0a5fcce729", size = 9567693, upload-time = "2025-12-16T20:13:12.559Z" }, - { url = "https://files.pythonhosted.org/packages/c6/b1/062aab2c62c5ae01c05d27b97ba022d9ff66f14a3cb9030c5ad1dca797ec/ty-0.0.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:21a9f28caafb5742e7d594104e2fe2ebd64590da31aed4745ae8bc5be67a7b85", size = 9556471, upload-time = "2025-12-16T20:13:07.771Z" }, - { url = "https://files.pythonhosted.org/packages/0e/07/856f6647a9dd6e36560d182d35d3b5fb21eae98a8bfb516cd879d0e509f3/ty-0.0.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d3ec63fd23ab48e0f838fb54a47ec362a972ee80979169a7edfa6f5c5034849d", size = 9971914, upload-time = "2025-12-16T20:13:18.852Z" }, - { url = "https://files.pythonhosted.org/packages/2e/82/c2e3957dbf33a23f793a9239cfd8bd04b6defd999bd0f6e74d6a5afb9f42/ty-0.0.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:e5e2e0293a259c9a53f668c9c13153cc2f1403cb0fe2b886ca054be4ac76517c", size = 10840905, upload-time = "2025-12-16T20:13:37.098Z" }, - { url = "https://files.pythonhosted.org/packages/3b/17/49bd74e3d577e6c88b8074581b7382f532a9d40552cc7c48ceaa83f1d950/ty-0.0.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fd2511ac02a83d0dc45d4570c7e21ec0c919be7a7263bad9914800d0cde47817", size = 10570251, upload-time = "2025-12-16T20:13:10.319Z" }, - { url = "https://files.pythonhosted.org/packages/2b/9b/26741834069722033a1a0963fcbb63ea45925c6697357e64e361753c6166/ty-0.0.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c482bfbfb8ad18b2e62427d02a0c934ac510c414188a3cf00e16b8acc35482f0", size = 10369078, upload-time = "2025-12-16T20:13:20.851Z" }, - { url = "https://files.pythonhosted.org/packages/94/fc/1d34ec891900d9337169ff9f8252fcaa633ae5c4d36b67effd849ed4f9ac/ty-0.0.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb514711eed3f56d7a130d4885f4b5d8e490fdcd2adac098e5cf175573a0dda3", size = 10121064, upload-time = "2025-12-16T20:13:23.095Z" }, - { url = "https://files.pythonhosted.org/packages/e5/02/e640325956172355ef8deb9b08d991f229230bf9d07f1dbda8c6665a3a43/ty-0.0.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:b2c37fa26c39e9fbed7c73645ba721968ab44f28b2bfe2f79a4e15965a1c426f", size = 9553817, upload-time = "2025-12-16T20:13:27.057Z" }, - { url = "https://files.pythonhosted.org/packages/35/13/c93d579ece84895da9b0aae5d34d84100bbff63ad9f60c906a533a087175/ty-0.0.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:13b264833ac5f3b214693fca38e380e78ee7327e09beaa5ff2e47d75fcab9692", size = 9577512, upload-time = "2025-12-16T20:13:16.956Z" }, - { url = "https://files.pythonhosted.org/packages/85/53/93ab1570adc799cd9120ea187d5b4c00d821e86eca069943b179fe0d3e83/ty-0.0.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:08658d6dbbf8bdef80c0a77eda56a22ab6737002ba129301b7bbd36bcb7acd75", size = 9692726, upload-time = "2025-12-16T20:13:31.169Z" }, - { url = "https://files.pythonhosted.org/packages/9a/07/5fff5335858a14196776207d231c32e23e48a5c912a7d52c80e7a3fa6f8f/ty-0.0.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:4a21b5b012061cb13d47edfff6be70052694308dba633b4c819b70f840e6c158", size = 10213996, upload-time = "2025-12-16T20:13:14.606Z" }, - { url = "https://files.pythonhosted.org/packages/a0/d3/896b1439ab765c57a8d732f73c105ec41142c417a582600638385c2bee85/ty-0.0.2-py3-none-win32.whl", hash = "sha256:d773fdad5d2b30f26313204e6b191cdd2f41ab440a6c241fdb444f8c6593c288", size = 9204906, upload-time = "2025-12-16T20:13:25.099Z" }, - { url = "https://files.pythonhosted.org/packages/5d/0a/f30981e7d637f78e3d08e77d63b818752d23db1bc4b66f9e82e2cb3d34f8/ty-0.0.2-py3-none-win_amd64.whl", hash = "sha256:d1c9ac78a8aa60d0ce89acdccf56c3cc0fcb2de07f1ecf313754d83518e8e8c5", size = 10066640, upload-time = "2025-12-16T20:13:04.045Z" }, - { url = "https://files.pythonhosted.org/packages/5a/c4/97958503cf62bfb7908d2a77b03b91a20499a7ff405f5a098c4989589f34/ty-0.0.2-py3-none-win_arm64.whl", hash = "sha256:fbdef644ade0cd4420c4ec14b604b7894cefe77bfd8659686ac2f6aba9d1a306", size = 9572022, upload-time = "2025-12-16T20:13:39.189Z" }, +wheels = [ + {url = "https://files.pythonhosted.org/packages/6b/86/65d4826677d966cf226662767a4a597ebb4b02c432f413673c8d5d3d1ce8/ty-0.0.2-py3-none-linux_armv6l.whl", hash = "sha256:0954a0e0b6f7e06229dd1da3a9989ee9b881a26047139a88eb7c134c585ad22e", size = 9771409, upload-time = "2025-12-16T20:13:28.964Z"}, + {url = "https://files.pythonhosted.org/packages/d4/bc/6ab06b7c109cec608c24ea182cc8b4714e746a132f70149b759817092665/ty-0.0.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:d6044b491d66933547033cecc87cb7eb599ba026a3ef347285add6b21107a648", size = 9580025, upload-time = "2025-12-16T20:13:34.507Z"}, + {url = "https://files.pythonhosted.org/packages/54/de/d826804e304b2430f17bb27ae15bcf02380e7f67f38b5033047e3d2523e6/ty-0.0.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:fbca7f08e671a35229f6f400d73da92e2dc0a440fba53a74fe8233079a504358", size = 9098660, upload-time = "2025-12-16T20:13:01.278Z"}, + {url = "https://files.pythonhosted.org/packages/b7/8e/5cd87944ceee02bb0826f19ced54e30c6bb971e985a22768f6be6b1a042f/ty-0.0.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3abd61153dac0b93b284d305e6f96085013a25c3a7ab44e988d24f0a5fcce729", size = 9567693, upload-time = "2025-12-16T20:13:12.559Z"}, + {url = "https://files.pythonhosted.org/packages/c6/b1/062aab2c62c5ae01c05d27b97ba022d9ff66f14a3cb9030c5ad1dca797ec/ty-0.0.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:21a9f28caafb5742e7d594104e2fe2ebd64590da31aed4745ae8bc5be67a7b85", size = 9556471, upload-time = "2025-12-16T20:13:07.771Z"}, + {url = "https://files.pythonhosted.org/packages/0e/07/856f6647a9dd6e36560d182d35d3b5fb21eae98a8bfb516cd879d0e509f3/ty-0.0.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d3ec63fd23ab48e0f838fb54a47ec362a972ee80979169a7edfa6f5c5034849d", size = 9971914, upload-time = "2025-12-16T20:13:18.852Z"}, + {url = "https://files.pythonhosted.org/packages/2e/82/c2e3957dbf33a23f793a9239cfd8bd04b6defd999bd0f6e74d6a5afb9f42/ty-0.0.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:e5e2e0293a259c9a53f668c9c13153cc2f1403cb0fe2b886ca054be4ac76517c", size = 10840905, upload-time = "2025-12-16T20:13:37.098Z"}, + {url = "https://files.pythonhosted.org/packages/3b/17/49bd74e3d577e6c88b8074581b7382f532a9d40552cc7c48ceaa83f1d950/ty-0.0.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fd2511ac02a83d0dc45d4570c7e21ec0c919be7a7263bad9914800d0cde47817", size = 10570251, upload-time = "2025-12-16T20:13:10.319Z"}, + {url = "https://files.pythonhosted.org/packages/2b/9b/26741834069722033a1a0963fcbb63ea45925c6697357e64e361753c6166/ty-0.0.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c482bfbfb8ad18b2e62427d02a0c934ac510c414188a3cf00e16b8acc35482f0", size = 10369078, upload-time = "2025-12-16T20:13:20.851Z"}, + {url = "https://files.pythonhosted.org/packages/94/fc/1d34ec891900d9337169ff9f8252fcaa633ae5c4d36b67effd849ed4f9ac/ty-0.0.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb514711eed3f56d7a130d4885f4b5d8e490fdcd2adac098e5cf175573a0dda3", size = 10121064, upload-time = "2025-12-16T20:13:23.095Z"}, + {url = "https://files.pythonhosted.org/packages/e5/02/e640325956172355ef8deb9b08d991f229230bf9d07f1dbda8c6665a3a43/ty-0.0.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:b2c37fa26c39e9fbed7c73645ba721968ab44f28b2bfe2f79a4e15965a1c426f", size = 9553817, upload-time = "2025-12-16T20:13:27.057Z"}, + {url = "https://files.pythonhosted.org/packages/35/13/c93d579ece84895da9b0aae5d34d84100bbff63ad9f60c906a533a087175/ty-0.0.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:13b264833ac5f3b214693fca38e380e78ee7327e09beaa5ff2e47d75fcab9692", size = 9577512, upload-time = "2025-12-16T20:13:16.956Z"}, + {url = "https://files.pythonhosted.org/packages/85/53/93ab1570adc799cd9120ea187d5b4c00d821e86eca069943b179fe0d3e83/ty-0.0.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:08658d6dbbf8bdef80c0a77eda56a22ab6737002ba129301b7bbd36bcb7acd75", size = 9692726, upload-time = "2025-12-16T20:13:31.169Z"}, + {url = "https://files.pythonhosted.org/packages/9a/07/5fff5335858a14196776207d231c32e23e48a5c912a7d52c80e7a3fa6f8f/ty-0.0.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:4a21b5b012061cb13d47edfff6be70052694308dba633b4c819b70f840e6c158", size = 10213996, upload-time = "2025-12-16T20:13:14.606Z"}, + {url = "https://files.pythonhosted.org/packages/a0/d3/896b1439ab765c57a8d732f73c105ec41142c417a582600638385c2bee85/ty-0.0.2-py3-none-win32.whl", hash = "sha256:d773fdad5d2b30f26313204e6b191cdd2f41ab440a6c241fdb444f8c6593c288", size = 9204906, upload-time = "2025-12-16T20:13:25.099Z"}, + {url = "https://files.pythonhosted.org/packages/5d/0a/f30981e7d637f78e3d08e77d63b818752d23db1bc4b66f9e82e2cb3d34f8/ty-0.0.2-py3-none-win_amd64.whl", hash = "sha256:d1c9ac78a8aa60d0ce89acdccf56c3cc0fcb2de07f1ecf313754d83518e8e8c5", size = 10066640, upload-time = "2025-12-16T20:13:04.045Z"}, + {url = "https://files.pythonhosted.org/packages/5a/c4/97958503cf62bfb7908d2a77b03b91a20499a7ff405f5a098c4989589f34/ty-0.0.2-py3-none-win_arm64.whl", hash = "sha256:fbdef644ade0cd4420c4ec14b604b7894cefe77bfd8659686ac2f6aba9d1a306", size = 9572022, upload-time = "2025-12-16T20:13:39.189Z"} ] [[package]] name = "typing-extensions" +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"} +source = {registry = "https://pypi.org/simple"} 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" }, + {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" }, + {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" } +name = "typing-inspection" +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"} +source = {registry = "https://pypi.org/simple"} +version = "0.4.2" 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" }, + {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" +sdist = {url = "https://files.pythonhosted.org/packages/5e/a7/c202b344c5ca7daf398f3b8a477eeb205cf3b6f32e7ec3a6bac0629ca975/tzdata-2025.3.tar.gz", hash = "sha256:de39c2ca5dc7b0344f2eba86f49d614019d29f060fc4ebc8a417896a620b56a7", size = 196772, upload-time = "2025-12-13T17:45:35.667Z"} +source = {registry = "https://pypi.org/simple"} version = "2025.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/5e/a7/c202b344c5ca7daf398f3b8a477eeb205cf3b6f32e7ec3a6bac0629ca975/tzdata-2025.3.tar.gz", hash = "sha256:de39c2ca5dc7b0344f2eba86f49d614019d29f060fc4ebc8a417896a620b56a7", size = 196772, upload-time = "2025-12-13T17:45:35.667Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl", hash = "sha256:06a47e5700f3081aab02b2e513160914ff0694bce9947d6b76ebd6bf57cfc5d1", size = 348521, upload-time = "2025-12-13T17:45:33.889Z" }, + {url = "https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl", hash = "sha256:06a47e5700f3081aab02b2e513160914ff0694bce9947d6b76ebd6bf57cfc5d1", size = 348521, upload-time = "2025-12-13T17:45:33.889Z"} ] [[package]] name = "urllib3" +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"} +source = {registry = "https://pypi.org/simple"} 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" }, + {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 = "wcwidth" +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"} +source = {registry = "https://pypi.org/simple"} 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" }, + {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 = "xarray" -version = "2026.2.0" -source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "numpy" }, - { name = "packaging" }, - { name = "pandas" }, + {name = "numpy"}, + {name = "packaging"}, + {name = "pandas"} ] -sdist = { url = "https://files.pythonhosted.org/packages/0f/03/e3353b72e518574b32993989d8f696277bf878e9d508c7dd22e86c0dab5b/xarray-2026.2.0.tar.gz", hash = "sha256:978b6acb018770554f8fd964af4eb02f9bcc165d4085dbb7326190d92aa74bcf", size = 3111388, upload-time = "2026-02-13T22:20:50.18Z" } +name = "xarray" +sdist = {url = "https://files.pythonhosted.org/packages/0f/03/e3353b72e518574b32993989d8f696277bf878e9d508c7dd22e86c0dab5b/xarray-2026.2.0.tar.gz", hash = "sha256:978b6acb018770554f8fd964af4eb02f9bcc165d4085dbb7326190d92aa74bcf", size = 3111388, upload-time = "2026-02-13T22:20:50.18Z"} +source = {registry = "https://pypi.org/simple"} +version = "2026.2.0" wheels = [ - { url = "https://files.pythonhosted.org/packages/99/92/545eb2ca17fc0e05456728d7e4378bfee48d66433ae3b7e71948e46826fb/xarray-2026.2.0-py3-none-any.whl", hash = "sha256:e927d7d716ea71dea78a13417970850a640447d8dd2ceeb65c5687f6373837c9", size = 1405358, upload-time = "2026-02-13T22:20:47.847Z" }, + {url = "https://files.pythonhosted.org/packages/99/92/545eb2ca17fc0e05456728d7e4378bfee48d66433ae3b7e71948e46826fb/xarray-2026.2.0-py3-none-any.whl", hash = "sha256:e927d7d716ea71dea78a13417970850a640447d8dd2ceeb65c5687f6373837c9", size = 1405358, upload-time = "2026-02-13T22:20:47.847Z"} ] [[package]] name = "xyzservices" +sdist = {url = "https://files.pythonhosted.org/packages/ee/0f/022795fc1201e7c29e742a509913badb53ce0b38f64b6db859e2f6339da9/xyzservices-2025.11.0.tar.gz", hash = "sha256:2fc72b49502b25023fd71e8f532fb4beddbbf0aa124d90ea25dba44f545e17ce", size = 1135703, upload-time = "2025-11-22T11:31:51.82Z"} +source = {registry = "https://pypi.org/simple"} version = "2025.11.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ee/0f/022795fc1201e7c29e742a509913badb53ce0b38f64b6db859e2f6339da9/xyzservices-2025.11.0.tar.gz", hash = "sha256:2fc72b49502b25023fd71e8f532fb4beddbbf0aa124d90ea25dba44f545e17ce", size = 1135703, upload-time = "2025-11-22T11:31:51.82Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ef/5c/2c189d18d495dd0fa3f27ccc60762bbc787eed95b9b0147266e72bb76585/xyzservices-2025.11.0-py3-none-any.whl", hash = "sha256:de66a7599a8d6dad63980b77defd1d8f5a5a9cb5fc8774ea1c6e89ca7c2a3d2f", size = 93916, upload-time = "2025-11-22T11:31:50.525Z" }, + {url = "https://files.pythonhosted.org/packages/ef/5c/2c189d18d495dd0fa3f27ccc60762bbc787eed95b9b0147266e72bb76585/xyzservices-2025.11.0-py3-none-any.whl", hash = "sha256:de66a7599a8d6dad63980b77defd1d8f5a5a9cb5fc8774ea1c6e89ca7c2a3d2f", size = 93916, upload-time = "2025-11-22T11:31:50.525Z"} ] [[package]] name = "zipp" +sdist = {url = "https://files.pythonhosted.org/packages/e3/02/0f2892c661036d50ede074e376733dca2ae7c6eb617489437771209d4180/zipp-3.23.0.tar.gz", hash = "sha256:a07157588a12518c9d4034df3fbbee09c814741a33ff63c05fa29d26a2404166", size = 25547, upload-time = "2025-06-08T17:06:39.4Z"} +source = {registry = "https://pypi.org/simple"} version = "3.23.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e3/02/0f2892c661036d50ede074e376733dca2ae7c6eb617489437771209d4180/zipp-3.23.0.tar.gz", hash = "sha256:a07157588a12518c9d4034df3fbbee09c814741a33ff63c05fa29d26a2404166", size = 25547, upload-time = "2025-06-08T17:06:39.4Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/2e/54/647ade08bf0db230bfea292f893923872fd20be6ac6f53b2b936ba839d75/zipp-3.23.0-py3-none-any.whl", hash = "sha256:071652d6115ed432f5ce1d34c336c0adfd6a884660d1e9712a256d3d3bd4b14e", size = 10276, upload-time = "2025-06-08T17:06:38.034Z" }, + {url = "https://files.pythonhosted.org/packages/2e/54/647ade08bf0db230bfea292f893923872fd20be6ac6f53b2b936ba839d75/zipp-3.23.0-py3-none-any.whl", hash = "sha256:071652d6115ed432f5ce1d34c336c0adfd6a884660d1e9712a256d3d3bd4b14e", size = 10276, upload-time = "2025-06-08T17:06:38.034Z"} ] From 337b021df6198993dc4fc3688253c291a1192875 Mon Sep 17 00:00:00 2001 From: Oskar Weser Date: Mon, 16 Mar 2026 15:35:50 +0100 Subject: [PATCH 09/19] applied automatic ruff fixes --- benchmarks/scenario-shm_throughput.py | 4 +-- .../cascade-job_building/t00_execute.py | 2 +- .../cascade-job_building/t00_generate.py | 2 +- .../tutorials/cascade-job_building/t01_low.py | 2 +- .../cascade-job_building/t02_builders.py | 2 +- .../cascade-job_building/t03_custom.py | 6 ++--- .../benchmarks_old/generators.py | 4 +-- integration_tests/benchmarks_old/job1.py | 2 +- integration_tests/benchmarks_old/plotting.py | 2 +- integration_tests/benchmarks_old/reporting.py | 2 +- integration_tests/benchmarks_old/util.py | 2 +- integration_tests/runtime/__init__.py | 2 +- src/cascade/controller/act.py | 4 +-- src/cascade/controller/core.py | 14 +++++----- src/cascade/controller/notify.py | 2 +- src/cascade/controller/report.py | 2 +- src/cascade/deployment/logging/__init__.py | 2 +- .../deployment/logging/json_formatter.py | 2 +- src/cascade/executor/bridge.py | 2 +- src/cascade/executor/checkpoints.py | 4 +-- src/cascade/executor/comms.py | 10 +++---- src/cascade/executor/data_server.py | 2 +- src/cascade/executor/executor.py | 2 +- src/cascade/executor/msg.py | 6 ++--- src/cascade/executor/platform.py | 4 +-- src/cascade/executor/runner/__init__.py | 2 +- src/cascade/executor/runner/entrypoint.py | 10 +++---- src/cascade/executor/runner/memory.py | 4 +-- src/cascade/executor/runner/packages.py | 6 ++--- src/cascade/executor/runner/runner.py | 4 +-- src/cascade/executor/serde.py | 4 +-- src/cascade/gateway/__main__.py | 1 - src/cascade/gateway/api.py | 2 +- src/cascade/gateway/client.py | 4 +-- src/cascade/gateway/router.py | 2 +- src/cascade/gateway/server.py | 2 +- src/cascade/gateway/spawning.py | 2 +- src/cascade/low/core.py | 8 +++--- src/cascade/low/execution_context.py | 6 ++--- src/cascade/low/func.py | 12 ++++----- src/cascade/low/into.py | 2 +- src/cascade/low/tracing.py | 6 ++--- src/cascade/low/views.py | 6 ++--- src/cascade/main.py | 2 +- src/cascade/scheduler/api.py | 4 +-- src/cascade/scheduler/assign.py | 8 +++--- src/cascade/scheduler/checkpoints.py | 12 ++++----- src/cascade/shm/__init__.py | 2 +- src/cascade/shm/algorithms.py | 2 +- src/cascade/shm/client.py | 2 +- src/cascade/shm/dataset.py | 2 +- src/cascade/shm/disk.py | 2 +- src/cascade/shm/func.py | 2 +- src/cascade/shm/server.py | 2 +- src/earthkit/workflows/backends/__init__.py | 3 ++- src/earthkit/workflows/backends/earthkit.py | 4 +-- src/earthkit/workflows/backends/xarray.py | 2 +- src/earthkit/workflows/fluent.py | 26 +++++++++---------- src/earthkit/workflows/graph/copy.py | 2 +- src/earthkit/workflows/graph/deduplicate.py | 2 +- src/earthkit/workflows/graph/expand.py | 8 +++--- src/earthkit/workflows/graph/export.py | 8 +++--- src/earthkit/workflows/graph/fuse.py | 2 +- src/earthkit/workflows/graph/graph.py | 16 ++++++------ src/earthkit/workflows/graph/graphviz.py | 4 +-- src/earthkit/workflows/graph/networkx.py | 4 +-- src/earthkit/workflows/graph/nodes.py | 18 ++++++------- src/earthkit/workflows/graph/pyvis.py | 6 ++--- src/earthkit/workflows/graph/rename.py | 4 +-- src/earthkit/workflows/graph/samplegraphs.py | 12 ++++----- src/earthkit/workflows/graph/split.py | 6 ++--- src/earthkit/workflows/graph/transform.py | 4 +-- src/earthkit/workflows/graph/visit.py | 6 ++--- src/earthkit/workflows/plugins/__init__.py | 2 +- src/earthkit/workflows/visualise.py | 2 +- tests/cascade/controller/test_run.py | 4 +-- tests/cascade/executor/test_callables.py | 2 +- tests/cascade/executor/test_packages.py | 2 +- tests/cascade/executor/test_runner.py | 2 +- tests/cascade/executor/util.py | 2 +- tests/cascade/scheduler/test_api.py | 2 +- tests/cascade/scheduler/util.py | 6 ++--- tests/earthkit_workflows/test_decorators.py | 2 +- tests/earthkit_workflows/test_metadata.py | 6 ++--- 84 files changed, 190 insertions(+), 190 deletions(-) diff --git a/benchmarks/scenario-shm_throughput.py b/benchmarks/scenario-shm_throughput.py index c5c5684b..b824b28b 100644 --- a/benchmarks/scenario-shm_throughput.py +++ b/benchmarks/scenario-shm_throughput.py @@ -1,4 +1,4 @@ -"""Benchmark shm in isolation (without cascade) by just invoking a lot of reads and writes in a limited memory setting""" +"""Benchmark shm in isolation (without cascade) by just invoking a lot of reads and writes in a limited memory setting.""" import multiprocessing as mp import random @@ -82,7 +82,7 @@ def scenario1(): def scenario2(): - """Start 1024MB shm, allocate 128 * 8MB (so that all fits), then 128 ** 2 gets to simulate high load""" + """Start 1024MB shm, allocate 128 * 8MB (so that all fits), then 128 ** 2 gets to simulate high load.""" start_shm(1024) c.ensure() diff --git a/docs/tutorials/cascade-job_building/t00_execute.py b/docs/tutorials/cascade-job_building/t00_execute.py index 17300e9f..188cdaca 100644 --- a/docs/tutorials/cascade-job_building/t00_execute.py +++ b/docs/tutorials/cascade-job_building/t00_execute.py @@ -1,4 +1,4 @@ -"""Simplified interface for job submission""" +"""Simplified interface for job submission.""" import random from typing import Any diff --git a/docs/tutorials/cascade-job_building/t00_generate.py b/docs/tutorials/cascade-job_building/t00_generate.py index 36ac7500..680521db 100644 --- a/docs/tutorials/cascade-job_building/t00_generate.py +++ b/docs/tutorials/cascade-job_building/t00_generate.py @@ -1,4 +1,4 @@ -"""Generate dummy data -- sorta like meteo data but small and easy to generate locally""" +"""Generate dummy data -- sorta like meteo data but small and easy to generate locally.""" import numpy as np import xarray as xr diff --git a/docs/tutorials/cascade-job_building/t01_low.py b/docs/tutorials/cascade-job_building/t01_low.py index 4ab478ca..ee3caac1 100644 --- a/docs/tutorials/cascade-job_building/t01_low.py +++ b/docs/tutorials/cascade-job_building/t01_low.py @@ -1,5 +1,5 @@ """Build a job using the most low level interface possible. This will be verbose and unwieldy, -but exposes all the available toggles +but exposes all the available toggles. For start, we want to generate data, then calculate mean of a single variable over time these two conceptual tasks translate into three computational steps: diff --git a/docs/tutorials/cascade-job_building/t02_builders.py b/docs/tutorials/cascade-job_building/t02_builders.py index 211077b3..4e9a5dcd 100644 --- a/docs/tutorials/cascade-job_building/t02_builders.py +++ b/docs/tutorials/cascade-job_building/t02_builders.py @@ -1,5 +1,5 @@ """We will craft the same job which ultimately allows the same customizability, -derives much more + has more defaults, but still operates on individual task level +derives much more + has more defaults, but still operates on individual task level. """ from t00_execute import run_job diff --git a/docs/tutorials/cascade-job_building/t03_custom.py b/docs/tutorials/cascade-job_building/t03_custom.py index 6df96b03..c9ddd2da 100644 --- a/docs/tutorials/cascade-job_building/t03_custom.py +++ b/docs/tutorials/cascade-job_building/t03_custom.py @@ -1,4 +1,4 @@ -"""So builders are neat but with task per dimension x chunk x computation, thats still a lot to type +"""So builders are neat but with task per dimension x chunk x computation, thats still a lot to type. And if you want to "just apply mean", you need to handle all the edgy business of what glues to what, the projections, the concatenates, ... @@ -56,7 +56,7 @@ def as_instance(self) -> JobInstance: class Source(DatasetSubgraph): - """Creates a no-inputs DatasetSubgraph using the provided `kallable`""" + """Creates a no-inputs DatasetSubgraph using the provided `kallable`.""" @staticmethod def _validate(i: xr.Dataset, dims: list[str], variables: list[str]) -> xr.Dataset: @@ -93,7 +93,7 @@ def __init__(self, kallable: Callable, dims: list[str], variables: list[str]) -> class ApplyNumpyReduce(DatasetSubgraph): - """Reduces `over_dims` for each `over_variables` individually via `f`""" + """Reduces `over_dims` for each `over_variables` individually via `f`.""" @staticmethod def _apply(f: Callable, i: (str, xr.DataArray), over_dims: list[str]) -> xr.Dataset: diff --git a/integration_tests/benchmarks_old/generators.py b/integration_tests/benchmarks_old/generators.py index b13604a0..e8f881bd 100644 --- a/integration_tests/benchmarks_old/generators.py +++ b/integration_tests/benchmarks_old/generators.py @@ -6,7 +6,7 @@ # granted to it by virtue of its status as an intergovernmental organisation # nor does it submit to any jurisdiction. -"""A completely artificial job to showcase a use of Generator in the output of a task +"""A completely artificial job to showcase a use of Generator in the output of a task. There is one source which belches out N matrices of size 2**K, and the consumer tasks just compute their Lth power @@ -22,7 +22,7 @@ def ser_numpy(a: np.ndarray) -> memoryview: # bytes: - """Exists just because numpy.ndarray cant be imported""" + """Exists just because numpy.ndarray cant be imported.""" # return a.tobytes() # beware, this includes a big copy return a.data.cast("B") diff --git a/integration_tests/benchmarks_old/job1.py b/integration_tests/benchmarks_old/job1.py index eb9f7d08..4c57baaf 100644 --- a/integration_tests/benchmarks_old/job1.py +++ b/integration_tests/benchmarks_old/job1.py @@ -6,7 +6,7 @@ # granted to it by virtue of its status as an intergovernmental organisation # nor does it submit to any jurisdiction. -"""One particular job suite for benchmarking: prob, efi ensms +"""One particular job suite for benchmarking: prob, efi ensms. When executed as a module, downloads the datasets as local files diff --git a/integration_tests/benchmarks_old/plotting.py b/integration_tests/benchmarks_old/plotting.py index 6ec67f4f..08df6fcb 100644 --- a/integration_tests/benchmarks_old/plotting.py +++ b/integration_tests/benchmarks_old/plotting.py @@ -6,7 +6,7 @@ # granted to it by virtue of its status as an intergovernmental organisation # nor does it submit to any jurisdiction. -"""Intended to be run inside a jupyter notebook +"""Intended to be run inside a jupyter notebook. Run `dirTaskLane()` """ diff --git a/integration_tests/benchmarks_old/reporting.py b/integration_tests/benchmarks_old/reporting.py index eae1bb32..d53811f9 100644 --- a/integration_tests/benchmarks_old/reporting.py +++ b/integration_tests/benchmarks_old/reporting.py @@ -6,7 +6,7 @@ # granted to it by virtue of its status as an intergovernmental organisation # nor does it submit to any jurisdiction. -"""Utilities for log parsing and performance reporting""" +"""Utilities for log parsing and performance reporting.""" import math from dataclasses import dataclass diff --git a/integration_tests/benchmarks_old/util.py b/integration_tests/benchmarks_old/util.py index 016f2617..7c8851f0 100644 --- a/integration_tests/benchmarks_old/util.py +++ b/integration_tests/benchmarks_old/util.py @@ -6,7 +6,7 @@ # granted to it by virtue of its status as an intergovernmental organisation # nor does it submit to any jurisdiction. -"""Contains utility methods for benchmark definitions""" +"""Contains utility methods for benchmark definitions.""" import logging diff --git a/integration_tests/runtime/__init__.py b/integration_tests/runtime/__init__.py index 926db9b8..e1cceb80 100644 --- a/integration_tests/runtime/__init__.py +++ b/integration_tests/runtime/__init__.py @@ -1,4 +1,4 @@ -"""Module to be imported from at runtime, ie, the callables definitions""" +"""Module to be imported from at runtime, ie, the callables definitions.""" def check_numpy_version(expected: str) -> bool: diff --git a/src/cascade/controller/act.py b/src/cascade/controller/act.py index 5eaa6e9f..2346a8c6 100644 --- a/src/cascade/controller/act.py +++ b/src/cascade/controller/act.py @@ -6,7 +6,7 @@ # granted to it by virtue of its status as an intergovernmental organisation # nor does it submit to any jurisdiction. -"""Implements the invocation of Bridge/Executor methods given a sequence of Actions""" +"""Implements the invocation of Bridge/Executor methods given a sequence of Actions.""" import logging from typing import Iterable, Iterator, cast @@ -106,7 +106,7 @@ def flush_queues(bridge: Bridge, state: State, context: JobExecutionContext): def virtual_checkpoint_publish(datasets: Iterable[DatasetId]) -> Iterator[DatasetPublished]: """Virtual in the sense of not actually sending any message, but instead simulating a response so that controller.notify can bring the contexts into the right state. - Invoked once, at the job start, after the checkpoint has been listed + Invoked once, at the job start, after the checkpoint has been listed. """ return ( DatasetPublished( diff --git a/src/cascade/controller/core.py b/src/cascade/controller/core.py index de09b615..6fb2495c 100644 --- a/src/cascade/controller/core.py +++ b/src/cascade/controller/core.py @@ -1,6 +1,6 @@ """Declares core data structures and methods -- most notably Controller's state, which handles dynamic work outside of scheduler control, such as dataset purging -or outputs retrieval +or outputs retrieval. """ import logging @@ -39,7 +39,7 @@ def has_awaitable(self) -> bool: return False def _consider_purge(self, dataset: DatasetId) -> None: - """If dataset not required anymore, add to purging_queue""" + """If dataset not required anymore, add to purging_queue.""" no_dependants = not self.purging_tracker.get(dataset, None) not_required_output = self.outputs.get(dataset, 1) is not None not_required_persist = dataset not in self.to_persist @@ -50,28 +50,28 @@ def _consider_purge(self, dataset: DatasetId) -> None: self.purging_queue.append(dataset) def consider_fetch(self, dataset: DatasetId, at: HostId) -> None: - """If required as output and not yet arrived, add to fetching queue""" + """If required as output and not yet arrived, add to fetching queue.""" if dataset in self.outputs and self.outputs[dataset] is None and dataset not in self.fetching_queue: self.fetching_queue[dataset] = at def consider_persist(self, dataset: DatasetId, at: HostId) -> None: - """If required as persist and not yet acknowledged, add to persist queue""" + """If required as persist and not yet acknowledged, add to persist queue.""" if dataset in self.to_persist and dataset not in self.persist_queue: self.persist_queue[dataset] = at def receive_payload(self, ds: DatasetId, payload: bytes, deser_fun: str) -> None: - """Stores deserialized value into outputs, considers purge""" + """Stores deserialized value into outputs, considers purge.""" # NOTE ifneedbe get annotation from job.tasks[event.ds.task].definition.output_schema[event.ds.output] self.outputs[ds] = serde.des_output(payload, "Any", deser_fun) self._consider_purge(ds) def acknowledge_persist(self, ds: DatasetId) -> None: - """Marks acknowledged, considers purge""" + """Marks acknowledged, considers purge.""" self.to_persist.discard(ds) self._consider_purge(ds) def task_done(self, task: TaskId, inputs: set[DatasetId]) -> None: - """Marks that the inputs are not needed for this task anymore, considers purge of each""" + """Marks that the inputs are not needed for this task anymore, considers purge of each.""" for sourceDataset in inputs: self.purging_tracker[sourceDataset].remove(task) self._consider_purge(sourceDataset) diff --git a/src/cascade/controller/notify.py b/src/cascade/controller/notify.py index 6185fa55..8b2fc878 100644 --- a/src/cascade/controller/notify.py +++ b/src/cascade/controller/notify.py @@ -6,7 +6,7 @@ # granted to it by virtue of its status as an intergovernmental organisation # nor does it submit to any jurisdiction. -"""Implements the mutation of State after Executors have reported some Events""" +"""Implements the mutation of State after Executors have reported some Events.""" # NOTE currently the implementation is mutating, but we may replace with pyrsistent etc. # Thus the caller always *must* use the return value and cease using the input. diff --git a/src/cascade/controller/report.py b/src/cascade/controller/report.py index 337e2d57..9d55836f 100644 --- a/src/cascade/controller/report.py +++ b/src/cascade/controller/report.py @@ -6,7 +6,7 @@ # granted to it by virtue of its status as an intergovernmental organisation # nor does it submit to any jurisdiction. -"""Handles reporting to gateway""" +"""Handles reporting to gateway.""" import logging import pickle diff --git a/src/cascade/deployment/logging/__init__.py b/src/cascade/deployment/logging/__init__.py index aee2cb12..3bb54b97 100644 --- a/src/cascade/deployment/logging/__init__.py +++ b/src/cascade/deployment/logging/__init__.py @@ -7,7 +7,7 @@ # nor does it submit to any jurisdiction. """ -Logging setup and configuration for any process and deployment +Logging setup and configuration for any process and deployment. Assumed to propagate in a cascading manner: - infrastructure operator configures gateway with logging as cli param, diff --git a/src/cascade/deployment/logging/json_formatter.py b/src/cascade/deployment/logging/json_formatter.py index 6b59dc81..593f2b12 100644 --- a/src/cascade/deployment/logging/json_formatter.py +++ b/src/cascade/deployment/logging/json_formatter.py @@ -6,7 +6,7 @@ # granted to it by virtue of its status as an intergovernmental organisation # nor does it submit to any jurisdiction. -"""Custom json formatter, felt easier than struggling with another 3rd party lib""" +"""Custom json formatter, felt easier than struggling with another 3rd party lib.""" import logging diff --git a/src/cascade/executor/bridge.py b/src/cascade/executor/bridge.py index c72fc00b..51e9b05d 100644 --- a/src/cascade/executor/bridge.py +++ b/src/cascade/executor/bridge.py @@ -6,7 +6,7 @@ # granted to it by virtue of its status as an intergovernmental organisation # nor does it submit to any jurisdiction. -"""Handles communication between controller and remote executors""" +"""Handles communication between controller and remote executors.""" import logging import time diff --git a/src/cascade/executor/checkpoints.py b/src/cascade/executor/checkpoints.py index 3fd36b99..f0a69993 100644 --- a/src/cascade/executor/checkpoints.py +++ b/src/cascade/executor/checkpoints.py @@ -6,7 +6,7 @@ # granted to it by virtue of its status as an intergovernmental organisation # nor does it submit to any jurisdiction. -"""Handles the checkpoint management: storage, retrieval""" +"""Handles the checkpoint management: storage, retrieval.""" import io import logging @@ -27,7 +27,7 @@ def serialize_params(spec: CheckpointSpec, id_: str) -> str: - """id_ is either the persist id or retrieve id from the spec""" + """id_ is either the persist id or retrieve id from the spec.""" # NOTE we call this every time we store, ideally call this once when building `low.execution_context` match spec.storage_type: case "fs": diff --git a/src/cascade/executor/comms.py b/src/cascade/executor/comms.py index cd754b6a..76627533 100644 --- a/src/cascade/executor/comms.py +++ b/src/cascade/executor/comms.py @@ -6,7 +6,7 @@ # granted to it by virtue of its status as an intergovernmental organisation # nor does it submit to any jurisdiction. -"""This module handles basic communication structures and functions""" +"""This module handles basic communication structures and functions.""" import logging import pickle @@ -34,7 +34,7 @@ class GraceWatcher: - """For watching whether certain event occurred more than `grace_ms` ago""" + """For watching whether certain event occurred more than `grace_ms` ago.""" def __init__(self, grace_ms: int): self.step_time_ms = 0 @@ -45,14 +45,14 @@ def _now(self) -> int: return int(time.time_ns() / 1_000_000) def step(self) -> None: - """Notify that event has occurred recently""" + """Notify that event has occurred recently.""" self.step_time_ms = self._now() def is_breach(self) -> int: """If the last `step()` occurred less than `grace_ms` ago, returns = 0, otherwise > 0. If the last return of > 0 occurred more than `grace_ms` ago, return 2, otherwise 1. The 2-vs-1 should be used for rate limiting logs, whereas business logic should heed - 0-vs-non0 + 0-vs-non0. """ now = self._now() breachStep = self._now() > self.step_time_ms + self.grace_ms @@ -66,7 +66,7 @@ def is_breach(self) -> int: return 0 def elapsed_ms(self) -> int: - """How many ms elapsed since last `step()`""" + """How many ms elapsed since last `step()`.""" return self._now() - self.step_time_ms diff --git a/src/cascade/executor/data_server.py b/src/cascade/executor/data_server.py index 36361ebe..a7b499da 100644 --- a/src/cascade/executor/data_server.py +++ b/src/cascade/executor/data_server.py @@ -79,7 +79,7 @@ def __init__( # TODO the two above should be eventually purged, see comms.Listener.acked for a similar concern def maybe_clean(self) -> None: - """Cleans out completed futures, waits if too many in progress""" + """Cleans out completed futures, waits if too many in progress.""" while True: keys = list(self.futs_in_progress.keys()) for key in keys: diff --git a/src/cascade/executor/executor.py b/src/cascade/executor/executor.py index 83463483..0306ce05 100644 --- a/src/cascade/executor/executor.py +++ b/src/cascade/executor/executor.py @@ -248,7 +248,7 @@ def register(self) -> None: def healthcheck(self) -> None: """Checks that no process died, and sends a heartbeat message in case the last message to controller - was too long ago + was too long ago. """ procFail = lambda ex: ex is not None and ex != 0 for k, e in self.workers.items(): diff --git a/src/cascade/executor/msg.py b/src/cascade/executor/msg.py index b16698cd..f248517e 100644 --- a/src/cascade/executor/msg.py +++ b/src/cascade/executor/msg.py @@ -7,7 +7,7 @@ # nor does it submit to any jurisdiction. """This module defines all messages used to communicate in between executor instances, as well -as externally to eg Controller or Runner +as externally to eg Controller or Runner. """ # TODO split into message categories: worker-only, data-only, regular -- or smth like that @@ -38,13 +38,13 @@ def __sdver__(self) -> int: def element(clazz): - """Any non-primitive class that can appear in a message""" + """Any non-primitive class that can appear in a message.""" # NOTE possibly add more ext like forcing __slot__ return dataclass(frozen=True)(clazz) def message(clazz): - """A top-level standalone message that can be serialized""" + """A top-level standalone message that can be serialized.""" clazz = element(clazz) clazz.__sdver__ = VERSION return clazz diff --git a/src/cascade/executor/platform.py b/src/cascade/executor/platform.py index 8923a434..1c317671 100644 --- a/src/cascade/executor/platform.py +++ b/src/cascade/executor/platform.py @@ -6,7 +6,7 @@ # granted to it by virtue of its status as an intergovernmental organisation # nor does it submit to any jurisdiction. -"""Macos-vs-Linux specific code""" +"""Macos-vs-Linux specific code.""" import fcntl import multiprocessing as mp @@ -19,7 +19,7 @@ def get_bindabble_self(): - """Returns a hostname such that zmq can bind to it""" + """Returns a hostname such that zmq can bind to it.""" if sys.platform == "darwin": # NOTE on macos, getfqdn usually returns like '66246.local', which can't then be bound to # This is a stopper for running a cluster of macos devices -- but we don't plan that yet diff --git a/src/cascade/executor/runner/__init__.py b/src/cascade/executor/runner/__init__.py index ed49c5cd..1fce8806 100644 --- a/src/cascade/executor/runner/__init__.py +++ b/src/cascade/executor/runner/__init__.py @@ -10,7 +10,7 @@ - getting & deserializing the inputs - serializing & storing the outputs - invoking callback to report task success, dataset publication, failures - - setting up the environment: packages and envvars + - setting up the environment: packages and envvars. The runner is a long-lived process, spawned by the executor module, with TaskSequence command being sent to it over ipc zmq. diff --git a/src/cascade/executor/runner/entrypoint.py b/src/cascade/executor/runner/entrypoint.py index 4836340c..3772db06 100644 --- a/src/cascade/executor/runner/entrypoint.py +++ b/src/cascade/executor/runner/entrypoint.py @@ -6,7 +6,7 @@ # granted to it by virtue of its status as an intergovernmental organisation # nor does it submit to any jurisdiction. -"""The entrypoint itself""" +"""The entrypoint itself.""" import logging import os @@ -41,7 +41,7 @@ @dataclass(frozen=True, slots=True) class RunnerContext: - """The static runner configuration""" + """The static runner configuration.""" workerId: WorkerId workerAttemptCnt: int @@ -76,7 +76,7 @@ def task_sequence_postmortem( ctx: RunnerContext, taskSequence: TaskSequence, cut: TaskId ) -> list[tuple[DatasetId, str]]: """Assuming a failure at task Cut, identify which datasets from the beginning of - the sequence should be additionaly published. Returns datasetid + its type + the sequence should be additionaly published. Returns datasetid + its type. """ finished = set() required = set() @@ -95,7 +95,7 @@ def task_sequence_postmortem( def task_sequence_remainder(taskSequence: TaskSequence, cut: TaskId) -> TaskSequence: """Assuming a failure at task Cut, calculate new task sequence which starts with Cut - that represents the still-to-be-done-in-new-worker calculation + that represents the still-to-be-done-in-new-worker calculation. """ remainder = [] for task in taskSequence.tasks: @@ -180,7 +180,7 @@ def execute_sequence( def entrypoint(runnerContextClpkl: bytes): - """RunnerContext is a cloudpickled instance of RunnerContext -- needed for forkserver mp context due to defautdicts""" + """RunnerContext is a cloudpickled instance of RunnerContext -- needed for forkserver mp context due to defautdicts.""" runnerContext = cloudpickle.loads(runnerContextClpkl) init_from_obj(runnerContext.loggingConfig, f"worker_{runnerContext.workerId.worker}") ctx = zmq.Context() diff --git a/src/cascade/executor/runner/memory.py b/src/cascade/executor/runner/memory.py index c3f42ed5..cccd0769 100644 --- a/src/cascade/executor/runner/memory.py +++ b/src/cascade/executor/runner/memory.py @@ -7,7 +7,7 @@ # nor does it submit to any jurisdiction. """Managing datasets in memory -- inputs and outputs of the executed job -Interaction with shm +Interaction with shm. """ import hashlib @@ -82,7 +82,7 @@ def handle(self, outputId: DatasetId, outputSchema: str, outputValue: Any, isPub # and worker-only publishes at the `controller.notify` level, to not cause # incorrect shm.purge calls at worklow end, which log an annoying key error logger.debug(f"fake publish of {outputId} for the sake of task completion") - shmid = ds2shmid(outputId) + ds2shmid(outputId) callback( self.callback, DatasetPublished(ds=outputId, origin=self.worker, transmit_idx=None), diff --git a/src/cascade/executor/runner/packages.py b/src/cascade/executor/runner/packages.py index 20114e49..7f1ea7c1 100644 --- a/src/cascade/executor/runner/packages.py +++ b/src/cascade/executor/runner/packages.py @@ -6,7 +6,7 @@ # granted to it by virtue of its status as an intergovernmental organisation # nor does it submit to any jurisdiction. -"""Extending venv with packages required by the executed job +"""Extending venv with packages required by the executed job. Note that venv itself is left untouched after the run finishes -- we extend sys path with a temporary directory and install in there @@ -90,8 +90,8 @@ def new_venv() -> tempfile.TemporaryDirectory: def _parse_pip_install(pip_output: str) -> dict[str, Version]: - """Assumed input like: 'Using Python 3.11.8 environment at: \nResolved 1 package in 5ms\nUninstalled 1 package in 12ms\nInstalled 1 package in 18ms\n - numpy==2.4.2\n + numpy==2.4.1\n' - Provided output: {'numpy': '2.4.1'} + r"""Assumed input like: 'Using Python 3.11.8 environment at: \nResolved 1 package in 5ms\nUninstalled 1 package in 12ms\nInstalled 1 package in 18ms\n - numpy==2.4.2\n + numpy==2.4.1\n' + Provided output: {'numpy': '2.4.1'}. """ rv = {} for line in pip_output.splitlines(): diff --git a/src/cascade/executor/runner/runner.py b/src/cascade/executor/runner/runner.py index 521c3f2e..43f170b9 100644 --- a/src/cascade/executor/runner/runner.py +++ b/src/cascade/executor/runner/runner.py @@ -6,7 +6,7 @@ # granted to it by virtue of its status as an intergovernmental organisation # nor does it submit to any jurisdiction. -"""Thin wrapper over a single Task/Callable +"""Thin wrapper over a single Task/Callable. Just io handling (ie, using Memory api), tracing and callable invocation """ @@ -29,7 +29,7 @@ @dataclass(frozen=True) class ExecutionContext: - """A projection of JobInstance relevant to particular TaskSequence""" + """A projection of JobInstance relevant to particular TaskSequence.""" # NOTE once we have long lived workers, this would be replaced by full JobInstance present at the worker tasks: dict[TaskId, TaskInstance] diff --git a/src/cascade/executor/serde.py b/src/cascade/executor/serde.py index 5c85d5d4..09783954 100644 --- a/src/cascade/executor/serde.py +++ b/src/cascade/executor/serde.py @@ -6,7 +6,7 @@ # granted to it by virtue of its status as an intergovernmental organisation # nor does it submit to any jurisdiction. -"""This module is responsible for Serialization & Deserialization of messages and outputs""" +"""This module is responsible for Serialization & Deserialization of messages and outputs.""" import pickle from typing import Any, Callable, Type @@ -58,7 +58,7 @@ def register(cls, t: Type, ser: str, des: str) -> None: def ser_output(v: Any, annotation: str) -> tuple[bytes, str]: """Utilizes `custom_ser` attr if present, otherwise defaults to cloudpickle as the most - robust general purpose serde + robust general purpose serde. """ if (serde := SerdeRegistry.serde.get(type(v), None)) is not None: value, deser_fun = serde[0](v), serde[1] diff --git a/src/cascade/gateway/__main__.py b/src/cascade/gateway/__main__.py index 7e3ceddb..94fa606e 100644 --- a/src/cascade/gateway/__main__.py +++ b/src/cascade/gateway/__main__.py @@ -6,7 +6,6 @@ # granted to it by virtue of its status as an intergovernmental organisation # nor does it submit to any jurisdiction. -import logging.config import fire diff --git a/src/cascade/gateway/api.py b/src/cascade/gateway/api.py index 56d0a399..4d63e916 100644 --- a/src/cascade/gateway/api.py +++ b/src/cascade/gateway/api.py @@ -25,7 +25,7 @@ class TroikaSpec: """Requires the gateway to have been started with --troika_config pointing to some config.yml troika file. The connection must work (passwordlessly), and must allow for script being copied. The remote host must have a venv - already in place, and must be able to resolve gateway's fqdn + already in place, and must be able to resolve gateway's fqdn. """ venv: str # remote host path to venv -- *do* include the bin/activate diff --git a/src/cascade/gateway/client.py b/src/cascade/gateway/client.py index c899cb48..9217d768 100644 --- a/src/cascade/gateway/client.py +++ b/src/cascade/gateway/client.py @@ -6,7 +6,7 @@ # granted to it by virtue of its status as an intergovernmental organisation # nor does it submit to any jurisdiction. -"""Handles request & response communication for classes in gateway.api""" +"""Handles request & response communication for classes in gateway.api.""" import logging import threading @@ -22,7 +22,7 @@ def request_response(m: api.CascadeGatewayAPI, url: str, timeout_ms: int = 1000) -> api.CascadeGatewayAPI: - """Sends a Request message, provides a corresponding Response message in a blocking manner""" + """Sends a Request message, provides a corresponding Response message in a blocking manner.""" local = threading.local() if not hasattr(local, "context"): local.context = zmq.Context() diff --git a/src/cascade/gateway/router.py b/src/cascade/gateway/router.py index 91720dbb..203b23a7 100644 --- a/src/cascade/gateway/router.py +++ b/src/cascade/gateway/router.py @@ -10,7 +10,7 @@ - routes the SubmitJobRequest to the appropriate spawn command - exposes a port for jobs to report progress, keeps these reports in memory - exposes a port for jobs to upload outputs, keeps these outputs in memory -- directly responds to JobProgressRequest and ResultRetrievalRequest from memory +- directly responds to JobProgressRequest and ResultRetrievalRequest from memory. """ import logging diff --git a/src/cascade/gateway/server.py b/src/cascade/gateway/server.py index e39ac77e..bbc700ba 100644 --- a/src/cascade/gateway/server.py +++ b/src/cascade/gateway/server.py @@ -7,7 +7,7 @@ # nor does it submit to any jurisdiction. """The recv-loop of `gateway`, as well as basic deser. Actual business logic happens in `gateway.router`, -here we just match the right method of `gateway.router` based on what message we parsed +here we just match the right method of `gateway.router` based on what message we parsed. """ import base64 diff --git a/src/cascade/gateway/spawning.py b/src/cascade/gateway/spawning.py index 8aa2eca2..f6d1e0a0 100644 --- a/src/cascade/gateway/spawning.py +++ b/src/cascade/gateway/spawning.py @@ -6,7 +6,7 @@ # granted to it by virtue of its status as an intergovernmental organisation # nor does it submit to any jurisdiction. -"""Spawning new processes for each SubmitJobRequest, locally or remotely""" +"""Spawning new processes for each SubmitJobRequest, locally or remotely.""" import base64 import itertools diff --git a/src/cascade/low/core.py b/src/cascade/low/core.py index 71ad4f63..88ac9822 100644 --- a/src/cascade/low/core.py +++ b/src/cascade/low/core.py @@ -6,7 +6,7 @@ # granted to it by virtue of its status as an intergovernmental organisation # nor does it submit to any jurisdiction. -"""Core graph data structures -- prescribes most of the API""" +"""Core graph data structures -- prescribes most of the API.""" import re from base64 import b64decode, b64encode @@ -163,7 +163,7 @@ def from_repr(cls, value: str) -> Self: return cls(host=host, worker=worker) def worker_num(self) -> int: - """Used eg for gpu allocation""" + """Used eg for gpu allocation.""" # TODO this should actually be precalculated at *Environment* construction, to modulo by gpu count etc return int(cast(re.Match[str], re.match("[^0-9]*([0-9]*)", self.worker))[1]) @@ -208,7 +208,7 @@ class JobExecutionRecord(BaseModel): class CheckpointSpec(BaseModel): """For configuring storage/retrieval of checkpoints, to allow job restarts - with some datasets already computed + with some datasets already computed. """ storage_type: CheckpointStorageType @@ -223,7 +223,7 @@ class CheckpointSpec(BaseModel): class JobInstanceRich(BaseModel): """Whereas JobInstance is the plain "compute these tasks", this class additionally holds execution-related data of more ephemeral nature, - like CheckpointConfig, ProfilingInformation, etc + like CheckpointConfig, ProfilingInformation, etc. """ jobInstance: JobInstance diff --git a/src/cascade/low/execution_context.py b/src/cascade/low/execution_context.py index 1cf84c49..4ef728f2 100644 --- a/src/cascade/low/execution_context.py +++ b/src/cascade/low/execution_context.py @@ -7,7 +7,7 @@ # nor does it submit to any jurisdiction. """Common data structures and utility methods that form the interface between scheduler and controller. -Primarily manifesting in the JobExecutionContext class -- a proto-scheduler of sorts +Primarily manifesting in the JobExecutionContext class -- a proto-scheduler of sorts. """ from collections import defaultdict @@ -48,7 +48,7 @@ class TaskStatus(int, Enum): @dataclass class JobExecutionContext: """Captures what is where -- datasets, running tasks, ... Used for decision making and progress tracking. - Broad interface between (generic) scheduler and controller + Broad interface between (generic) scheduler and controller. """ # static @@ -93,7 +93,7 @@ def publication_mandatory(self, ds: DatasetId) -> bool: return to_output or to_persist def purge_dataset(self, ds: DatasetId) -> Iterator[HostId]: - """Drop dataset from all tracking structures, yields hosts that should be sent purge command""" + """Drop dataset from all tracking structures, yields hosts that should be sent purge command.""" for host in self.ds2host[ds]: self.host2ds[host].pop(ds) for worker in self.host2workers[host]: diff --git a/src/cascade/low/func.py b/src/cascade/low/func.py index 3b7a205d..2efa3815 100644 --- a/src/cascade/low/func.py +++ b/src/cascade/low/func.py @@ -41,7 +41,7 @@ def maybe_head(v: Iterable[T]) -> Optional[T]: def assert_never(v: Any) -> NoReturn: - """For exhaustive enumm checks etc""" + """For exhaustive enumm checks etc.""" # TODO once we switch to ecpy util this needs to be redone/preserved from cascade.low.exceptions import CascadeInternalError # *exceptional in-body import* @@ -50,7 +50,7 @@ def assert_never(v: Any) -> NoReturn: @runtime_checkable class Semigroup(Protocol): - """Basically 'has plus'""" + """Basically 'has plus'.""" @abstractmethod def __add__(self, other: Self) -> Self: @@ -62,7 +62,7 @@ def __add__(self, other: Self) -> Self: class Either(Generic[T, E]): - """Mostly for lazy gathering of errors during validation. Looks fancier than actually is""" + """Mostly for lazy gathering of errors during validation. Looks fancier than actually is.""" def __init__(self, t: Optional[T] = None, e: Optional[E] = None): self.t = t @@ -133,7 +133,7 @@ def msum(i: Iterable[TMonoid], t: Type[TMonoid]) -> TMonoid: def pyd_replace(model: B, **kwargs) -> B: - """Like dataclasses.replace but for pydantic""" + """Like dataclasses.replace but for pydantic.""" return model.model_copy(update=kwargs) @@ -154,7 +154,7 @@ def next_uuid(s: Container[T], g: Callable[[], T]) -> T: def resolve_callable(s: str) -> Callable: - """For s = `a.b.func`, imports `a.b` and retrieves `func` Callable object""" + """For s = `a.b.func`, imports `a.b` and retrieves `func` Callable object.""" if "." not in s: # this branch is for builtins return eval(s) else: @@ -168,7 +168,7 @@ def pydantic_recursive_collect(base: BaseModel | Iterable, attr: str, prefix: st and collecting results. Assumes the `attr` has signature `Callable[[self], list[T]]`. The collected results are (source, item), where item is returned by `attr` and source is the dot-separated path of the issuer -- eg if base has BaseModel field `x` whose `attr` yields [1, 2], then this returns - [(.x, 1), (.x, 2)] + [(.x, 1), (.x, 2)]. """ # NOTE a bit ugly, instead of attr it would be better to accept a signature/protocol type diff --git a/src/cascade/low/into.py b/src/cascade/low/into.py index dcad81be..42d68a89 100644 --- a/src/cascade/low/into.py +++ b/src/cascade/low/into.py @@ -6,7 +6,7 @@ # granted to it by virtue of its status as an intergovernmental organisation # nor does it submit to any jurisdiction. -"""Lowering of the earthkit.workflows.graph structures into cascade.low representation""" +"""Lowering of the earthkit.workflows.graph structures into cascade.low representation.""" import logging from typing import Any, Callable, cast diff --git a/src/cascade/low/tracing.py b/src/cascade/low/tracing.py index eb6e0bd2..9cfbafdb 100644 --- a/src/cascade/low/tracing.py +++ b/src/cascade/low/tracing.py @@ -6,7 +6,7 @@ # granted to it by virtue of its status as an intergovernmental organisation # nor does it submit to any jurisdiction. -"""Interface for tracing important events that can be used for extracting performance information +"""Interface for tracing important events that can be used for extracting performance information. Currently, the export is handled just by logging, assuming to be parsed later. We log at debug level since this is assumed to be high level tracing @@ -96,7 +96,7 @@ def _labels(labels: Labels) -> str: def label(key: str, value: str) -> None: """Makes all subsequent marks contain this KV. Carries over to later-forked subprocesses, but - not to forkspawned + not to forkspawned. """ global d d[key] = value @@ -114,7 +114,7 @@ def trace(kind: Microtrace, value: int): def timer(f, kind: Microtrace): - """Don't use for distributed tracing as this relies on unsync time""" + """Don't use for distributed tracing as this relies on unsync time.""" @wraps(f) def wrapper(*args, **kwargs): diff --git a/src/cascade/low/views.py b/src/cascade/low/views.py index fa5a4da8..e9a7c829 100644 --- a/src/cascade/low/views.py +++ b/src/cascade/low/views.py @@ -6,7 +6,7 @@ # granted to it by virtue of its status as an intergovernmental organisation # nor does it submit to any jurisdiction. -"""Utility functions and transformers for the core graph objects""" +"""Utility functions and transformers for the core graph objects.""" from collections import defaultdict @@ -17,7 +17,7 @@ def param_source( edges: list[Task2TaskEdge], ) -> dict[TaskId, dict[int | str, DatasetId]]: - """Returns map[sink_task][sink_input] = (source_task, source_output)""" + """Returns map[sink_task][sink_input] = (source_task, source_output).""" rv: dict[TaskId, dict[int | str, DatasetId]] = defaultdict(lambda: defaultdict(lambda: {})) # type: ignore for e in edges: sink_input: int | str @@ -36,7 +36,7 @@ def param_source( def dependants(edges: list[Task2TaskEdge]) -> dict[DatasetId, set[TaskId]]: - """Returns map[(source_task, source_output)] = set(sink_task)""" + """Returns map[(source_task, source_output)] = set(sink_task).""" rv: dict[DatasetId, set[TaskId]] = defaultdict(set) for e in edges: rv[e.source].add(e.sink_task) diff --git a/src/cascade/main.py b/src/cascade/main.py index 75ee3ba9..9505f3d1 100644 --- a/src/cascade/main.py +++ b/src/cascade/main.py @@ -6,7 +6,7 @@ # granted to it by virtue of its status as an intergovernmental organisation # nor does it submit to any jurisdiction. -"""Main entrypoints for cluster or local starting for executors and controllers""" +"""Main entrypoints for cluster or local starting for executors and controllers.""" import logging import logging.config diff --git a/src/cascade/scheduler/api.py b/src/cascade/scheduler/api.py index aaa0ee11..905733d9 100644 --- a/src/cascade/scheduler/api.py +++ b/src/cascade/scheduler/api.py @@ -33,7 +33,7 @@ def gang_check_ready(task: TaskId, gang_prep: GangPreparation): """When a task becomes computable, mutate the gang_prep to possibly - transition some gangs to `ready` + transition some gangs to `ready`. """ for gang in gang_prep.lookup[task]: if gang not in gang_prep.countdown: @@ -118,7 +118,7 @@ def assign(schedule: Schedule, context: JobExecutionContext) -> Iterator[Assignm - changes host2component. Yields, to allow for immediate async sending to workers. Performance critical section, we need to output an assignment asap. Steps taking longer - should be deferred to `plan` + should be deferred to `plan`. """ # step I: assign within existing components component2workers: dict[ComponentId, list[WorkerId]] = defaultdict(list) diff --git a/src/cascade/scheduler/assign.py b/src/cascade/scheduler/assign.py index 43eb03d0..48f94c6e 100644 --- a/src/cascade/scheduler/assign.py +++ b/src/cascade/scheduler/assign.py @@ -7,7 +7,7 @@ # nor does it submit to any jurisdiction. """Utility functions for handling assignments -- invocation assumed from scheduler.api module, -for all other purposes this should be treated private +for all other purposes this should be treated private. """ import logging @@ -135,7 +135,7 @@ def _try_assign_gang( context: JobExecutionContext, fail_acc: list[frozenset[TaskId]], ) -> Iterator[Assignment]: - """We greedily assign by descending worker-task distance""" + """We greedily assign by descending worker-task distance.""" global gang_port if len(gang) > len(workers): logger.debug(f"not enough workers ({len(workers)}) for {gang=}") @@ -296,7 +296,7 @@ def assign_within_component( 2/ tasks requiring a gpu, 3/ tasks whose fusable child requires a gpu, 4/ all other tasks, - using the same algorithm for cases 2-4 and a naive for case 1 + using the same algorithm for cases 2-4 and a naive for case 1. """ # TODO rework into a more systematic multicriterial opt solution that is able to consider all groups # at once, using a generic value/cost framework and matching algorithm. It should additionally be able @@ -407,7 +407,7 @@ def migrate_to_component( context: JobExecutionContext, ): """Assuming original component assigned to the host didn't have enough tasks anymore, - we invoke this function and update state to reflect it + we invoke this function and update state to reflect it. """ schedule.host2component[host] = component_id component = schedule.components[component_id] diff --git a/src/cascade/scheduler/checkpoints.py b/src/cascade/scheduler/checkpoints.py index 81cb791c..d876ac34 100644 --- a/src/cascade/scheduler/checkpoints.py +++ b/src/cascade/scheduler/checkpoints.py @@ -11,7 +11,7 @@ discard everything that doesnt need to be computed - virtual_update_schedule -- as we start executing, we virtually publish all checkpointed datasets. That on its own would break some invariants in -the schedule, so we do all the corrections in this function +the schedule, so we do all the corrections in this function. """ import logging @@ -26,7 +26,7 @@ def _filter_invalid(job: JobInstance, persisted: set[DatasetId]) -> tuple[set[TaskId], set[DatasetId]]: """Filters out those persisted datasets that overlap partially with a gang or provide only partial outputs - of a task + of a task. """ persisted_per_task = defaultdict(set) for ds in persisted: @@ -46,7 +46,7 @@ def _filter_invalid(job: JobInstance, persisted: set[DatasetId]) -> tuple[set[Ta def _get_parents(component: ComponentCore, preschedule: Preschedule) -> dict[TaskId, set[TaskId]]: - """Just convert edge_i into a task-task dict""" + """Just convert edge_i into a task-task dict.""" parents: dict[TaskId, set[TaskId]] = defaultdict(set) for node in component.nodes: for dataset in preschedule.edge_i[node]: @@ -61,7 +61,7 @@ def _discover_component( preschedule: Preschedule, persisted_tasks: set[TaskId], ) -> set[TaskId]: - """Returns only the valid nodes, ie, those that are either persisted or should be computed""" + """Returns only the valid nodes, ie, those that are either persisted or should be computed.""" visitable = defaultdict(set) for node in component.nodes: for d in job.outputs_of(node): @@ -84,7 +84,7 @@ def _discover_component( def _trim_component( component: ComponentCore, parents: dict[TaskId, set[TaskId]], preserved_tasks: set[TaskId] ) -> ComponentCore: - """Restricts the component only to preserved tasks""" + """Restricts the component only to preserved tasks.""" nodes = list(preserved_tasks) value = {node: component.value[node] for node in nodes} return ComponentCore( @@ -109,7 +109,7 @@ def trim_with_persisted( ) -> tuple[JobInstance, Preschedule, set[DatasetId]]: """Removes from job and preschedule everything that does not need to be computed anymore, ie, lies in the subgraph of nodes for which every path to a sink goes through a persisted - dataset + dataset. Some persisted sets may be ignored, such as if they are only a part of a gang, or only a part of a task's output -- we thus return the modified persisted set diff --git a/src/cascade/shm/__init__.py b/src/cascade/shm/__init__.py index 4e6e6082..728acd55 100644 --- a/src/cascade/shm/__init__.py +++ b/src/cascade/shm/__init__.py @@ -11,7 +11,7 @@ Does not handle cross-worker coms on its own, but participates -- thats expected to work via 1. controller issues command 2. source worker gets the data from its shm and ships over to target worker - 3. target worker puts to its shm + 3. target worker puts to its shm. Features: - uses python's SharedMemory -- no overhead, zero-copy sharing diff --git a/src/cascade/shm/algorithms.py b/src/cascade/shm/algorithms.py index 65e2bace..eea76efa 100644 --- a/src/cascade/shm/algorithms.py +++ b/src/cascade/shm/algorithms.py @@ -6,7 +6,7 @@ # granted to it by virtue of its status as an intergovernmental organisation # nor does it submit to any jurisdiction. -"""Pageout algorithms -- selection of which datasets to send from shm to disk +"""Pageout algorithms -- selection of which datasets to send from shm to disk. Logic: - first those that have been accessed *exactly* once, ordered by created asc diff --git a/src/cascade/shm/client.py b/src/cascade/shm/client.py index 05cfecf7..a142e865 100644 --- a/src/cascade/shm/client.py +++ b/src/cascade/shm/client.py @@ -163,7 +163,7 @@ def shutdown(timeout_sec: float = 2.0) -> None: def ensure() -> None: - """Loop StatusInquiry until shm server responds with Ok""" + """Loop StatusInquiry until shm server responds with Ok.""" logger.debug("entering shm ensure loop") comm = api.StatusInquiry() while True: diff --git a/src/cascade/shm/dataset.py b/src/cascade/shm/dataset.py index 4320dcb3..f0bf45e2 100644 --- a/src/cascade/shm/dataset.py +++ b/src/cascade/shm/dataset.py @@ -10,7 +10,7 @@ - shared memory id - size - state (in shm / on disk) -- lru metadata +- lru metadata. Manages the to-disk-and-back persistence """ diff --git a/src/cascade/shm/disk.py b/src/cascade/shm/disk.py index 93d8edea..5d5b0074 100644 --- a/src/cascade/shm/disk.py +++ b/src/cascade/shm/disk.py @@ -6,7 +6,7 @@ # granted to it by virtue of its status as an intergovernmental organisation # nor does it submit to any jurisdiction. -"""Handles disk operations""" +"""Handles disk operations.""" import logging import multiprocessing.resource_tracker diff --git a/src/cascade/shm/func.py b/src/cascade/shm/func.py index ad3e4071..864bf989 100644 --- a/src/cascade/shm/func.py +++ b/src/cascade/shm/func.py @@ -20,5 +20,5 @@ class ShmInfrastructureError(ValueError): def assert_never(v: Any) -> NoReturn: - """For exhaustive enumm checks etc""" + """For exhaustive enumm checks etc.""" raise TypeError(f"unexpected value in exhaustive check: {v!r}") diff --git a/src/cascade/shm/server.py b/src/cascade/shm/server.py index 28f29279..2b281c18 100644 --- a/src/cascade/shm/server.py +++ b/src/cascade/shm/server.py @@ -20,7 +20,7 @@ class LocalServer: - """Handles the socket communication, and the invocation of dataset.Manager which has the business logic""" + """Handles the socket communication, and the invocation of dataset.Manager which has the business logic.""" def __init__(self, shm_pref: str, capacity: int | None = None): self.sock = api.get_server_socket() diff --git a/src/earthkit/workflows/backends/__init__.py b/src/earthkit/workflows/backends/__init__.py index cfc9b7ae..b3c0fab7 100644 --- a/src/earthkit/workflows/backends/__init__.py +++ b/src/earthkit/workflows/backends/__init__.py @@ -152,7 +152,7 @@ def stack(*args, axis: int = 0, **kwargs): @batchable def concat(*args, **kwargs): - """Join along existing axis in one of the inputs + """Join along existing axis in one of the inputs. Parameters ---------- @@ -207,6 +207,7 @@ def take(array, indices, **kwargs): try: from earthkit.data import FieldList, SimpleFieldList + from earthkit.workflows.backends.earthkit import FieldListBackend BACKENDS[SimpleFieldList] = FieldListBackend diff --git a/src/earthkit/workflows/backends/earthkit.py b/src/earthkit/workflows/backends/earthkit.py index 6db43fe3..3a502f7b 100644 --- a/src/earthkit/workflows/backends/earthkit.py +++ b/src/earthkit/workflows/backends/earthkit.py @@ -67,7 +67,7 @@ class FieldListBackend: def _merge(*fieldlists: list[FieldList]): """Merge fieldlist elements into a single array. fieldlists with different number of fields must be concatenated, otherwise, the - elements in each fieldlist are stacked along a new dimension + elements in each fieldlist are stacked along a new dimension. """ if len(fieldlists) == 1: return fieldlists[0].values @@ -149,7 +149,7 @@ def pow(*arrays: list[FieldList], metadata: Metadata = None) -> FieldList: def concat(*arrays: list[FieldList]) -> FieldList: """Concatenates the list of fields inside each FieldList into a single - FieldList object + FieldList object. Parameters ---------- diff --git a/src/earthkit/workflows/backends/xarray.py b/src/earthkit/workflows/backends/xarray.py index 5eb8d5ef..0d68360a 100644 --- a/src/earthkit/workflows/backends/xarray.py +++ b/src/earthkit/workflows/backends/xarray.py @@ -17,7 +17,7 @@ def multi_arg_function(name: str, *arrays: xr.DataArray | xr.Dataset, **method_k DataArrays or Datasetst then function is applied along an dimension specified in method_kwargs. If multiple DataArrays or Datasets then these are first stacked before function is applied on the - stack + stack. Parameters ---------- diff --git a/src/earthkit/workflows/fluent.py b/src/earthkit/workflows/fluent.py index 751652ee..a659fca1 100644 --- a/src/earthkit/workflows/fluent.py +++ b/src/earthkit/workflows/fluent.py @@ -35,7 +35,7 @@ class Payload: - """Class for detailing function, args and kwargs to be computing in a graph node""" + """Class for detailing function, args and kwargs to be computing in a graph node.""" def __init__( self, @@ -105,7 +105,7 @@ def custom_hash(string: str) -> str: def capture_payload_metadata(func: Callable[P, R]) -> Callable[P, R]: """Wrap a function which returns a new action and insert - given `payload_metadata` + given `payload_metadata`. """ # @functools.wraps(func) @@ -210,7 +210,7 @@ def graph(self) -> Graph: @classmethod def register(cls, name: str, obj: type[Action]): - """Register an Action class under `name` + """Register an Action class under `name`. Will be accessible from the fluent API as `Action().` @@ -239,11 +239,11 @@ def register(cls, name: str, obj: type[Action]): @classmethod def flush_registry(cls): - """Flush the registry of all registered actions""" + """Flush the registry of all registered actions.""" cls.REGISTRY = {} def as_action(self, other) -> Action: - """Parse action into another action class""" + """Parse action into another action class.""" return other(self.nodes) def join( @@ -328,7 +328,7 @@ def broadcast( exclude: list[str] | None = None, path: Optional[str] = None, ) -> "Action": - """Broadcast nodes against nodes in other_action + """Broadcast nodes against nodes in other_action. Parameters ---------- @@ -419,7 +419,7 @@ def map( ) -> "Action": """Apply specified payload on all nodes. If argument is an array of payloads, this must be the same size as the array of nodes and each node gets a - unique payload from the array + unique payload from the array. Parameters ---------- @@ -594,7 +594,7 @@ def flatten( ) def set_path(self, path: str) -> "Action": - """Create path for current node array + """Create path for current node array. Parameters ---------- @@ -610,7 +610,7 @@ def set_path(self, path: str) -> "Action": def split(self, expansion: Optional[dict[str, PayloadFunc | Payload]] = None) -> "Action": """Create action containing new node arrays by splitting an existing node array - by the specified functions in expansion + by the specified functions in expansion. Parameters ---------- @@ -651,7 +651,7 @@ def select( path: Optional[str] = None, **kwargs, ) -> "Action": - """Create action contaning nodes match selection criteria + """Create action contaning nodes match selection criteria. Parameters ---------- @@ -689,7 +689,7 @@ def iselect( path: Optional[str] = None, **kwargs, ) -> "Action": - """Create action contaning nodes match index selection criteria + """Create action contaning nodes match index selection criteria. Parameters ---------- @@ -978,7 +978,7 @@ def __getattr__(self, attr): class RegisteredAction: - """Wrapper around registered actions""" + """Wrapper around registered actions.""" def __init__(self, name: str, action: type[Action], root_action: Action) -> None: self._name = name @@ -1082,7 +1082,7 @@ def from_source( def merge(*args, **kwargs) -> Action: """Merge node arrays in actions. If provided as keyword arguments, the key - is used as the root path for the action's node arrays + is used as the root path for the action's node arrays. Return diff --git a/src/earthkit/workflows/graph/copy.py b/src/earthkit/workflows/graph/copy.py index 4056cb23..54967c6e 100644 --- a/src/earthkit/workflows/graph/copy.py +++ b/src/earthkit/workflows/graph/copy.py @@ -22,5 +22,5 @@ def graph(self, graph: Graph, sinks: list[Node]) -> Graph: def copy_graph(g: Graph) -> Graph: - """Create a shallow copy of a whole graph (payloads are not copied)""" + """Create a shallow copy of a whole graph (payloads are not copied).""" return _Copier().transform(g) diff --git a/src/earthkit/workflows/graph/deduplicate.py b/src/earthkit/workflows/graph/deduplicate.py index 2e3f8442..28509747 100644 --- a/src/earthkit/workflows/graph/deduplicate.py +++ b/src/earthkit/workflows/graph/deduplicate.py @@ -66,7 +66,7 @@ def same_payload(a: Node, b: Node): def deduplicate_nodes(graph: Graph, pred: PredicateType = same_payload) -> Graph: - """Deduplicate graph nodes + """Deduplicate graph nodes. Two nodes are considered identical if: - They have the same outputs diff --git a/src/earthkit/workflows/graph/expand.py b/src/earthkit/workflows/graph/expand.py index 6d4e4c71..5d9861cf 100644 --- a/src/earthkit/workflows/graph/expand.py +++ b/src/earthkit/workflows/graph/expand.py @@ -47,7 +47,7 @@ def get_output(self, name: str | None = None) -> Output: class Splicer(Transformer): - """Transformer to connect a sub-graph in place of an expanded node + """Transformer to connect a sub-graph in place of an expanded node. Subclasses can override the `splice_source` and `splice_sink` methods to control how sources and sinks of the sub-graph are converted to processors @@ -116,7 +116,7 @@ def graph(self, g: Graph, sinks: list[Node]) -> _Subgraph: return _Subgraph(self.name, leaves, self.outputs, inner_sinks) def splice_source(self, name: str, s: Node, input: Output) -> Node: - """Create a processor node to replace a source in the sub-graph + """Create a processor node to replace a source in the sub-graph. The default implementation creates a bare Node with the original source's name, payload and outputs. @@ -138,7 +138,7 @@ def splice_source(self, name: str, s: Node, input: Output) -> Node: return Node(name, s.outputs, s.payload, input=input) def splice_sink(self, name: str, s: Node, **inputs: Output) -> Node: - """Create a processor node to replace a sink in the sub-graph + """Create a processor node to replace a sink in the sub-graph. The default implementation creates a bare Node with the original sink's name, payload and inputs. @@ -206,7 +206,7 @@ def graph(self, graph: Graph, sinks: list[Node | _Subgraph]) -> Graph: def expand_graph(expand: ExpanderType, graph: Graph, splicer: SplicerType = Splicer) -> Graph: - """Expand a graph by replacing nodes with sub-graphs + """Expand a graph by replacing nodes with sub-graphs. The expansion is controlled by the ``expand`` callback, called for every node in topological order. For each node: diff --git a/src/earthkit/workflows/graph/export.py b/src/earthkit/workflows/graph/export.py index c5b06b40..9c83f804 100644 --- a/src/earthkit/workflows/graph/export.py +++ b/src/earthkit/workflows/graph/export.py @@ -39,7 +39,7 @@ def _deserialise_node( def serialise(graph: Graph) -> dict: - """Convert a graph to a serialisable representation + """Convert a graph to a serialisable representation. See also `Node.serialise` """ @@ -51,7 +51,7 @@ def serialise(graph: Graph) -> dict: def to_json(graph: Graph) -> str: - """Serialise a graph as JSON + """Serialise a graph as JSON. See also `serialise` """ @@ -59,7 +59,7 @@ def to_json(graph: Graph) -> str: def deserialise(data: dict, node_factory: NodeFactory = default_node_factory) -> Graph: - """Build a graph from a serialisable representation + """Build a graph from a serialisable representation. An optional node factory function can be provided to create a node with the given name, outputs, payload and inputs. The default factory will create @@ -89,7 +89,7 @@ def deserialise(data: dict, node_factory: NodeFactory = default_node_factory) -> def from_json(data: str) -> Graph: - """Build a graph from JSON + """Build a graph from JSON. See also `deserialise` """ diff --git a/src/earthkit/workflows/graph/fuse.py b/src/earthkit/workflows/graph/fuse.py index 8985ebd0..bd878225 100644 --- a/src/earthkit/workflows/graph/fuse.py +++ b/src/earthkit/workflows/graph/fuse.py @@ -51,7 +51,7 @@ def transform(self, graph: Graph) -> Graph: def fuse_nodes(func: FuseCallback, g: Graph) -> Graph: - """Fuse compatible nodes of a graph + """Fuse compatible nodes of a graph. Candidates for fusion are 4-tuples: (parent node, parent output, current node, current input). One such tuple is considered only if the parent node diff --git a/src/earthkit/workflows/graph/graph.py b/src/earthkit/workflows/graph/graph.py index b26f7f8c..d8b5841a 100644 --- a/src/earthkit/workflows/graph/graph.py +++ b/src/earthkit/workflows/graph/graph.py @@ -12,7 +12,7 @@ class Graph: - """Graph class + """Graph class. A graph is represented by the list of its sinks. @@ -72,11 +72,11 @@ def __iadd__(self, other: object) -> "Graph": @classmethod def empty(cls) -> "Graph": - """Just making this a monoid""" + """Just making this a monoid.""" return cls(sinks=[]) def nodes(self, forwards=False) -> Iterator[Node]: - """Iterate over nodes of the graph + """Iterate over nodes of the graph. If ``forwards`` is true, iterate in topological order. Otherwise, iterate backwards starting from the sinks. @@ -113,11 +113,11 @@ def nodes(self, forwards=False) -> Iterator[Node]: done.add(node) def sources(self) -> Iterator[Node]: - """Iterate over the sources in the graph""" + """Iterate over the sources in the graph.""" return (n for n in self.nodes(forwards=True) if n.is_source()) def get_node(self, name: str) -> Node: - """Get a node by name + """Get a node by name. Raises `KeyError` if not found. """ @@ -127,7 +127,7 @@ def get_node(self, name: str) -> Node: raise KeyError(name) def get_predecessors(self, node: Node) -> dict[str, Node | tuple[Node, str]]: - """Get the predecessors (parents) of a node + """Get the predecessors (parents) of a node. The result is a dict where keys are the given node's input names, and values are node outputs, encoded as either the node itself (default @@ -139,7 +139,7 @@ def get_predecessors(self, node: Node) -> dict[str, Node | tuple[Node, str]]: } def get_successors(self, node: Node) -> dict[str, list[tuple[Node, str]]]: - """Get the successors (children) of a node + """Get the successors (children) of a node. The result is a dict where keys are the given node's output names, and values are lists of (child, input name) tuples. @@ -153,7 +153,7 @@ def get_successors(self, node: Node) -> dict[str, list[tuple[Node, str]]]: return succ def has_cycle(self) -> bool: - """Check whether a graph contains cycles""" + """Check whether a graph contains cycles.""" done: set[Node] = set() todo: list[tuple[Node, list[Node]]] = [(sink, []) for sink in self.sinks] diff --git a/src/earthkit/workflows/graph/graphviz.py b/src/earthkit/workflows/graph/graphviz.py index e7fbd8df..a7a29c53 100644 --- a/src/earthkit/workflows/graph/graphviz.py +++ b/src/earthkit/workflows/graph/graphviz.py @@ -25,7 +25,7 @@ def _quote(s: str) -> str: def to_dot(graph: Graph) -> str: - """Convert a graph to GraphViz's 'dot' format""" + """Convert a graph to GraphViz's 'dot' format.""" out = [] for node in graph.nodes(): nname = node.name @@ -42,7 +42,7 @@ def to_dot(graph: Graph) -> str: def render_graph(graph: Graph, **kwargs) -> str: - """Render a graph using GraphViz + """Render a graph using GraphViz. Keyword arguments are passed to `graphviz.Source.render`. """ diff --git a/src/earthkit/workflows/graph/networkx.py b/src/earthkit/workflows/graph/networkx.py index ce889b0c..bdca34e9 100644 --- a/src/earthkit/workflows/graph/networkx.py +++ b/src/earthkit/workflows/graph/networkx.py @@ -15,7 +15,7 @@ def to_networkx(graph: Graph, serialise=False) -> nx.MultiDiGraph: - """Convert a graph to a NetworkX graph + """Convert a graph to a NetworkX graph. If ``serialise`` is true, the node payloads in the output graph are the serialised values of the corresponding nodes of the input graph. Otherwise, @@ -46,7 +46,7 @@ def draw_graph( pos: dict[str, Sequence[float]] | None = None, with_edge_labels: bool = False, ): - """Draw a graph using NetworkX""" + """Draw a graph using NetworkX.""" g = to_networkx(graph) if isinstance(graph, Graph) else graph pos = topological_layout(g) if pos is None else pos nx.draw(g, pos, with_labels=True) diff --git a/src/earthkit/workflows/graph/nodes.py b/src/earthkit/workflows/graph/nodes.py index 74d43987..b0e051f0 100644 --- a/src/earthkit/workflows/graph/nodes.py +++ b/src/earthkit/workflows/graph/nodes.py @@ -14,7 +14,7 @@ class Output: - """Helper class to refer to node outputs""" + """Helper class to refer to node outputs.""" parent: "Node" name: str @@ -24,7 +24,7 @@ def __init__(self, parent: "Node", name: str): self.name = name def serialise(self) -> str | tuple[str, str]: - """Convert the reference to a serialisable type""" + """Convert the reference to a serialisable type.""" if self.name == Node.DEFAULT_OUTPUT: return self.parent.name return self.parent.name, self.name @@ -41,7 +41,7 @@ def __str__(self) -> str: class Node: - """Base class for graph nodes + """Base class for graph nodes. A node is defined with references to its actual inputs, and can have either one default output, or any number of named outputs (including zero). Named @@ -91,7 +91,7 @@ def __getattr__(self, name: str) -> Output: return self.get_output(name) def get_output(self, name: str | None = None) -> Output: - """Get an output from the node + """Get an output from the node. If ``name`` is ``None``, the node is expected to have a default output, which is returned. Otherwise the output with the given name is returned. @@ -109,7 +109,7 @@ def _make_output(self, name: str) -> Output: return Output(self, name) def serialise(self) -> dict[str, Any]: - """Convert the node to a serialisable value + """Convert the node to a serialisable value. If the payload object has a ``serialise`` method, it is called without arguments to get its serialised form, otherwise the payload is assumed @@ -129,17 +129,17 @@ def __repr__(self) -> str: return f"<{self.__class__.__name__} {self.name!r} at {id(self):#x}>" def is_source(self) -> bool: - """Check whether the node is a source (i.e. has no inputs)""" + """Check whether the node is a source (i.e. has no inputs).""" return not self.inputs def is_processor(self) -> bool: - """Check whether the node is a processor (i.e. has both inputs and outputs)""" + """Check whether the node is a processor (i.e. has both inputs and outputs).""" return (not self.is_sink()) and (not self.is_source()) def is_sink(self) -> bool: - """Check whether the node is a sink (i.e. has no outputs)""" + """Check whether the node is a sink (i.e. has no outputs).""" return not self.outputs def copy(self) -> Self: - """Shallow copy of the node (the payload is not copied)""" + """Shallow copy of the node (the payload is not copied).""" return self.__class__(self.name, self.outputs.copy(), self.payload, **self.inputs) diff --git a/src/earthkit/workflows/graph/pyvis.py b/src/earthkit/workflows/graph/pyvis.py index 3d3cdb97..1dca1d57 100644 --- a/src/earthkit/workflows/graph/pyvis.py +++ b/src/earthkit/workflows/graph/pyvis.py @@ -86,7 +86,7 @@ def node_info(node): def edge_info(sname, snode, dname, dnode): - """Simple edge info function showing the names of the output and input as edge title""" + """Simple edge info function showing the names of the output and input as edge title.""" return {"title": f"From: {sname}\nTo: {dname}"} @@ -146,7 +146,7 @@ def none() -> dict: def truncate_name(name: str, max_length: int = 10) -> str: - """Truncate a name to a maximum length""" + """Truncate a name to a maximum length.""" if ":" not in name: return name @@ -165,7 +165,7 @@ def to_pyvis( options: dict[str, Any] | None = None, **kwargs: Any, ) -> Network: - """Convert a graph to a PyVis network + """Convert a graph to a PyVis network. Parameters ---------- diff --git a/src/earthkit/workflows/graph/rename.py b/src/earthkit/workflows/graph/rename.py index b41789fe..0d245937 100644 --- a/src/earthkit/workflows/graph/rename.py +++ b/src/earthkit/workflows/graph/rename.py @@ -33,7 +33,7 @@ def graph(self, g: Graph, sinks: list[Node]) -> Graph: def rename_nodes(func: RenamerFunc, graph: Graph) -> Graph: - """Rename nodes of a graph + """Rename nodes of a graph. Parameters ---------- @@ -52,7 +52,7 @@ def rename_nodes(func: RenamerFunc, graph: Graph) -> Graph: def join_namespaced(**graphs: Graph) -> Graph: - """Join graphs by prefixing the names of their nodes + """Join graphs by prefixing the names of their nodes. Parameters ---------- diff --git a/src/earthkit/workflows/graph/samplegraphs.py b/src/earthkit/workflows/graph/samplegraphs.py index 01ae1e20..090555e7 100644 --- a/src/earthkit/workflows/graph/samplegraphs.py +++ b/src/earthkit/workflows/graph/samplegraphs.py @@ -12,12 +12,12 @@ def empty() -> Graph: - """Empty graph""" + """Empty graph.""" return Graph([]) def linear(nproc: int = 5) -> Graph: - """Linear graph + """Linear graph. reader -> process-0 -> ... -> process-{nproc-1} -> writer """ @@ -30,7 +30,7 @@ def linear(nproc: int = 5) -> Graph: def disconnected(nchains: int = 5, nproc: int = 1) -> Graph: - """Disconnected graph + """Disconnected graph. reader-0 -> process-0.0 -> ... -> process-0.{nproc-1} -> writer-0 : @@ -48,7 +48,7 @@ def disconnected(nchains: int = 5, nproc: int = 1) -> Graph: def simple(nread: int = 5, nproc: int = 3) -> Graph: - """Simple graph + """Simple graph. `nread` sources (reader-{i} for i in range(nread)) `nproc` processors reading from all readers (process-{i} for i in range(nproc)) @@ -66,7 +66,7 @@ def simple(nread: int = 5, nproc: int = 3) -> Graph: def multi(nread: int = 5, nout1: int = 3, nout2: int = 2) -> Graph: - """Graph with multi-output nodes + """Graph with multi-output nodes. `nread` readers (reader-{i} for i in range(nread)) `nout1` processors (process-{i} for i in range(nout1), nout1 must be at least 3) @@ -100,7 +100,7 @@ def multi(nread: int = 5, nout1: int = 3, nout2: int = 2) -> Graph: def comb(nteeth: int = 5, nproc: int = 0): - """Comb graph + """Comb graph. `nteeth` readers (reader-{i} for i in range(nteeth)) `(nproc + 1) * nteeth - 1` processors ( diff --git a/src/earthkit/workflows/graph/split.py b/src/earthkit/workflows/graph/split.py index 3a9d21ec..67da3e23 100644 --- a/src/earthkit/workflows/graph/split.py +++ b/src/earthkit/workflows/graph/split.py @@ -41,7 +41,7 @@ def source(self) -> str | tuple[str, str]: class Splitter(Transformer, Generic[K]): - """Transformer to perform graph splitting + """Transformer to perform graph splitting. Subclasses can override the `cut_edge` method to control how the cut edges are replaced by a sink and a source on either side. @@ -81,7 +81,7 @@ def graph(self, graph: Graph, sinks: list[tuple[K, Node]]) -> tuple[dict[K, Grap return {k: Graph(s) for k, s in self.sinks.items()}, self.cuts def cut_edge(self, cut: CutEdge[K], sink_in: Output) -> tuple[Node, Node]: - """Create nodes to replace a cut edge + """Create nodes to replace a cut edge. Parameters ---------- @@ -106,7 +106,7 @@ def cut_edge(self, cut: CutEdge[K], sink_in: Output) -> tuple[Node, Node]: def split_graph( key: KeyFunc[K], graph: Graph, splitter: SplitterType[K] = Splitter ) -> tuple[dict[K, Graph], list[CutEdge[K]]]: - """Split a graph according to some key + """Split a graph according to some key. Each sub-graph in the split will consist of nodes with the same key. The key type ``K`` must be hashable and support the ``==`` operator. diff --git a/src/earthkit/workflows/graph/transform.py b/src/earthkit/workflows/graph/transform.py index 02174bf4..e06bae81 100644 --- a/src/earthkit/workflows/graph/transform.py +++ b/src/earthkit/workflows/graph/transform.py @@ -14,7 +14,7 @@ class Transformer: - """Graph transformer base class + """Graph transformer base class. When `transform` is called on a graph, the graph will be visited in topological order. A callback method will be called on each node, and the @@ -50,7 +50,7 @@ class Transformer: """ def transform(self, graph: Graph) -> Any: - """Apply the transformation to the given graph + """Apply the transformation to the given graph. See ``Transformer`` for details. """ diff --git a/src/earthkit/workflows/graph/visit.py b/src/earthkit/workflows/graph/visit.py index cf767e8b..bd5d581a 100644 --- a/src/earthkit/workflows/graph/visit.py +++ b/src/earthkit/workflows/graph/visit.py @@ -13,7 +13,7 @@ def node_visit(impl: Any, node: Node, inputs: dict[str, Any]): - """Helper method shared by Visitor and Transformer""" + """Helper method shared by Visitor and Transformer.""" if node.is_source() and hasattr(impl, "source"): return impl.source(node) elif node.is_sink() and hasattr(impl, "sink"): @@ -26,7 +26,7 @@ def node_visit(impl: Any, node: Node, inputs: dict[str, Any]): class Visitor: - """Graph visitor base class + """Graph visitor base class. When `visit` is called on a graph, the graph will be visited in arbitrary order. A callback method will be called on each node, depending on its type. @@ -41,7 +41,7 @@ class Visitor: """ def visit(self, graph: Graph): - """Visit the given graph + """Visit the given graph. See `Visitor` for details. """ diff --git a/src/earthkit/workflows/plugins/__init__.py b/src/earthkit/workflows/plugins/__init__.py index 4130c9da..8e4083c7 100644 --- a/src/earthkit/workflows/plugins/__init__.py +++ b/src/earthkit/workflows/plugins/__init__.py @@ -1,4 +1,4 @@ -"""Placeholder module to be populated by -plugin packages""" +"""Placeholder module to be populated by -plugin packages.""" import pkgutil diff --git a/src/earthkit/workflows/visualise.py b/src/earthkit/workflows/visualise.py index 7d3cfab4..7c53afa3 100644 --- a/src/earthkit/workflows/visualise.py +++ b/src/earthkit/workflows/visualise.py @@ -49,7 +49,7 @@ def visualise( preset: PRESET_OPTIONS = "hierarchical", **kwargs, ): - """Visualise a graph with PyVis + """Visualise a graph with PyVis. Parameters ---------- diff --git a/tests/cascade/controller/test_run.py b/tests/cascade/controller/test_run.py index 2dd34569..4dec0812 100644 --- a/tests/cascade/controller/test_run.py +++ b/tests/cascade/controller/test_run.py @@ -6,7 +6,7 @@ # granted to it by virtue of its status as an intergovernmental organisation # nor does it submit to any jurisdiction. -"""For a given graph and instant executor, check that things complete""" +"""For a given graph and instant executor, check that things complete.""" # NOTE this is a very bulky test, prone to flakyness, interference, incompatible # with xdist etc. Consider removing from pytest altogether, and reframing @@ -233,7 +233,7 @@ def test_fusing(): def test_checkpoints(): """This takes a job with a checkpoint config, and runs it twice, - in a way that recognizes whether it checkpointed or not + in a way that recognizes whether it checkpointed or not. """ with tempfile.TemporaryDirectory() as tmp_root, tempfile.TemporaryDirectory() as ckpt_root: sourcetask_code = f"import pathlib; f = pathlib.Path('{tmp_root}') / 'file.txt'; f.write_text('ok') if not f.exists() else 1/0;" diff --git a/tests/cascade/executor/test_callables.py b/tests/cascade/executor/test_callables.py index 8a7482d4..6d269b18 100644 --- a/tests/cascade/executor/test_callables.py +++ b/tests/cascade/executor/test_callables.py @@ -6,7 +6,7 @@ # granted to it by virtue of its status as an intergovernmental organisation # nor does it submit to any jurisdiction. -"""Intended to test that various 3rd-party callables work under cascade""" +"""Intended to test that various 3rd-party callables work under cascade.""" from .util import CallableInstance, run_test diff --git a/tests/cascade/executor/test_packages.py b/tests/cascade/executor/test_packages.py index b1f261ea..e23588d5 100644 --- a/tests/cascade/executor/test_packages.py +++ b/tests/cascade/executor/test_packages.py @@ -57,7 +57,7 @@ def test_maybe_module_version() -> None: import numpy assert _maybe_module_version("numpy") == Version(numpy.__version__) - assert _maybe_module_version("cascade") == None # whoopsie, we dont declare __version__ on cascade + assert _maybe_module_version("cascade") is None # whoopsie, we dont declare __version__ on cascade import earthkit.workflows if not hasattr(earthkit.workflows, "__version__"): diff --git a/tests/cascade/executor/test_runner.py b/tests/cascade/executor/test_runner.py index 11e9f14e..bcd71cda 100644 --- a/tests/cascade/executor/test_runner.py +++ b/tests/cascade/executor/test_runner.py @@ -6,7 +6,7 @@ # granted to it by virtue of its status as an intergovernmental organisation # nor does it submit to any jurisdiction. -"""Tests running a Callable in the same process""" +"""Tests running a Callable in the same process.""" from multiprocessing.shared_memory import SharedMemory from typing import Any diff --git a/tests/cascade/executor/util.py b/tests/cascade/executor/util.py index 55e8d7e5..52d1b180 100644 --- a/tests/cascade/executor/util.py +++ b/tests/cascade/executor/util.py @@ -6,7 +6,7 @@ # granted to it by virtue of its status as an intergovernmental organisation # nor does it submit to any jurisdiction. -"""Module for simplifying writing tests +"""Module for simplifying writing tests. It is capable, for a single given task, to spin an shm server, put all task's inputs into it, execute the task, store outputs in memory, and retrieve the result. See the `demo()` function at the very end diff --git a/tests/cascade/scheduler/test_api.py b/tests/cascade/scheduler/test_api.py index ec48f5be..d138643d 100644 --- a/tests/cascade/scheduler/test_api.py +++ b/tests/cascade/scheduler/test_api.py @@ -6,7 +6,7 @@ # granted to it by virtue of its status as an intergovernmental organisation # nor does it submit to any jurisdiction. -"""Tests calculation of preschedule, state initialize & first assign and plan""" +"""Tests calculation of preschedule, state initialize & first assign and plan.""" from cascade.low.core import DatasetId, WorkerId from cascade.low.execution_context import TaskStatus, init_context diff --git a/tests/cascade/scheduler/util.py b/tests/cascade/scheduler/util.py index 0fe5a86f..05a681d0 100644 --- a/tests/cascade/scheduler/util.py +++ b/tests/cascade/scheduler/util.py @@ -6,7 +6,7 @@ # granted to it by virtue of its status as an intergovernmental organisation # nor does it submit to any jurisdiction. -"""Util functions for generating larger graphs + their execution records +"""Util functions for generating larger graphs + their execution records. Generates graphs that look like this: - one big source node @@ -115,7 +115,7 @@ def enrich_instance(job: JobInstance) -> JobInstanceRich: def get_job0() -> tuple[JobInstanceRich, JobExecutionRecord]: - """One source, one pproc, one sink""" + """One source, one pproc, one sink.""" builder = BuilderGroup() add_large_source(builder, 10, 6, 4) add_postproc(builder, 0, 1, 1, 1, 1) @@ -124,7 +124,7 @@ def get_job0() -> tuple[JobInstanceRich, JobExecutionRecord]: def get_job1() -> tuple[JobInstanceRich, JobExecutionRecord]: - """One large source branching out into two sets of sinks""" + """One large source branching out into two sets of sinks.""" builder = BuilderGroup() # data source: 10 minutes consuming 6G mem and producing 4G output add_large_source(builder, 10, 6, 4) diff --git a/tests/earthkit_workflows/test_decorators.py b/tests/earthkit_workflows/test_decorators.py index 80b149d3..616f2a35 100644 --- a/tests/earthkit_workflows/test_decorators.py +++ b/tests/earthkit_workflows/test_decorators.py @@ -19,7 +19,7 @@ def mock_payload_function(x, y, *, keyword): def test_as_payload(): - """Test the `as_payload` decorator""" + """Test the `as_payload` decorator.""" payload = mock_payload_function(metadata={"test_metadata": True}, keyword="test") assert isinstance(payload, Payload) diff --git a/tests/earthkit_workflows/test_metadata.py b/tests/earthkit_workflows/test_metadata.py index 5f394d34..c15f3608 100644 --- a/tests/earthkit_workflows/test_metadata.py +++ b/tests/earthkit_workflows/test_metadata.py @@ -17,7 +17,7 @@ def test_payload_metadata(): - """Test payload metadata is passed to the action""" + """Test payload metadata is passed to the action.""" action = mock_action((1, 1)) test_payload = Payload(lambda x: x, metadata={"test_metadata": True}) @@ -33,7 +33,7 @@ def test_payload_metadata(): def test_payload_metadata_with_function(): - """Test payload metadata is passed to the action""" + """Test payload metadata is passed to the action.""" action = mock_action((1, 1)) mult_action = action.multiply(2, payload_metadata={"test_metadata": True}) @@ -47,7 +47,7 @@ def test_payload_metadata_with_function(): def test_payload_metadata_from_marks_generic(): - """Test payload metadata from generic mark""" + """Test payload metadata from generic mark.""" action = mock_action((1, 1)) @ekw_mark.add_execution_metadata(test_metadata=True) From 655dc8659dbdae765e479da2c863d69acf43abbd Mon Sep 17 00:00:00 2001 From: Oskar Weser Date: Mon, 16 Mar 2026 15:45:52 +0100 Subject: [PATCH 10/19] fix: wrap long lines to comply with E501 (max 120 chars) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- benchmarks/scenario-shm_throughput.py | 3 +- benchmarks/scheduling/sat_experiments.py | 3 +- docs/benchmarking/run1/analysis.py | 30 ++++++++++++------- docs/benchmarking/run2/analysis.py | 6 ++-- .../cascade-job_building/t03_custom.py | 18 +++++++---- src/cascade/controller/impl.py | 3 +- src/cascade/controller/notify.py | 3 +- src/cascade/executor/executor.py | 3 +- src/cascade/executor/msg.py | 3 +- src/cascade/executor/runner/entrypoint.py | 5 +++- src/cascade/executor/runner/packages.py | 16 ++++++++-- src/cascade/gateway/__init__.py | 3 +- src/cascade/low/core.py | 3 +- src/cascade/low/exceptions.py | 3 +- src/cascade/low/tracing.py | 3 +- src/cascade/scheduler/assign.py | 6 ++-- src/cascade/scheduler/core.py | 3 +- src/cascade/scheduler/precompute.py | 3 +- src/cascade/shm/func.py | 3 +- tests/cascade/controller/test_run.py | 5 +++- tests/cascade/executor/test_executor.py | 6 ++-- tests/cascade/executor/test_packages.py | 21 +++++++++---- tests/cascade/executor/util.py | 3 +- 23 files changed, 109 insertions(+), 46 deletions(-) diff --git a/benchmarks/scenario-shm_throughput.py b/benchmarks/scenario-shm_throughput.py index b824b28b..72618984 100644 --- a/benchmarks/scenario-shm_throughput.py +++ b/benchmarks/scenario-shm_throughput.py @@ -1,4 +1,5 @@ -"""Benchmark shm in isolation (without cascade) by just invoking a lot of reads and writes in a limited memory setting.""" +"""Benchmark shm in isolation (without cascade) by just invoking a lot of reads and writes +in a limited memory setting.""" import multiprocessing as mp import random diff --git a/benchmarks/scheduling/sat_experiments.py b/benchmarks/scheduling/sat_experiments.py index 57e2cdca..06a82fbc 100644 --- a/benchmarks/scheduling/sat_experiments.py +++ b/benchmarks/scheduling/sat_experiments.py @@ -129,7 +129,8 @@ def solve(problem: Problem): if solver.value(problem.worker2task[(task, worker)]) == 1: target = worker print( - f"{task=} => from {solver.value(problem.taskIntervals[task][0])} to {solver.value(problem.taskIntervals[task][1])} at {target}" + f"{task=} => from {solver.value(problem.taskIntervals[task][0])}" + f" to {solver.value(problem.taskIntervals[task][1])} at {target}" ) print(f"end = {solver.value(problem.end)}") diff --git a/docs/benchmarking/run1/analysis.py b/docs/benchmarking/run1/analysis.py index c8feec91..7213134a 100644 --- a/docs/benchmarking/run1/analysis.py +++ b/docs/benchmarking/run1/analysis.py @@ -2,8 +2,10 @@ # coding: utf-8 # ### Major mysteries -# * Why is the wall time inside the tasks so much higher for m1_4 and f4, but less so for m2_2/m4_1? What sort of cpu contention we have? -# * What to measure so that we have a clear indicator for m2_2/m4_1 taking much longer than m1_4/f4? How to separate m1_4 and f4 cleanly? +# * Why is the wall time inside the tasks so much higher for m1_4 and f4, but less so for m2_2/m4_1? +# What sort of cpu contention we have? +# * What to measure so that we have a clear indicator for m2_2/m4_1 taking much longer than m1_4/f4? +# How to separate m1_4 and f4 cleanly? # # ### Other data (extracted manually from logs) # - number of controller iterations (plan-act-await), number of events @@ -12,9 +14,12 @@ # - m_4_1 -> 66; 135 # - m_2_2 -> 65; 165 # - m_1_4 -> 103; 232 -# - there is much more event queuing in the multihost scenario, presumably because of the comm delay. Meaning the controller decides with less granularity -# - the event counts are underreported here because of a *bug* (remote transfer doesnt succ mark the input as present) -# - there is about the same number of data transmits in f4 and m1_4, meaning the final schedules are not that much different +# - there is much more event queuing in the multihost scenario, presumably because of the comm delay. +# Meaning the controller decides with less granularity +# - the event counts are underreported here because of a *bug* +# (remote transfer doesnt succ mark the input as present) +# - there is about the same number of data transmits in f4 and m1_4, +# meaning the final schedules are not that much different # # ### Next steps # - (feature) replace remote transfers with local ones when it is possible @@ -189,11 +194,14 @@ def analyzeTasks(df): # ## Task Takeaways: -# * There is a big difference between f1 and f4 in pure runtimes of tasks, 17e9 vs 28e9, suggesting some contention happening -# * Comparing individual tasks, we see only small relative/abs differences in concats and disk-accessing retrieves, but big in compute intensive sot or efi, suggesting there is some CPU contention +# * There is a big difference between f1 and f4 in pure runtimes of tasks, 17e9 vs 28e9, +# suggesting some contention happening +# * Comparing individual tasks, we see only small relative/abs differences in concats and disk-accessing retrieves, +# but big in compute intensive sot or efi, suggesting there is some CPU contention # * The difference is also visible for m scenarios -- m1_4 is expectedly like f4, but m2_2 and m4_1 are 20e9 being thus closer to f1. It could be that there is less overlap in those scenarios, as the scheduling is more gappy due to interleaved http comms? # noqa:E501 # * Queue delay exhibits no real difference over f/m scenarios -# * Comm delays are 1e7 for f scenarios, 1e8 for m4_1, and 1e9 for m2_2 and m1_4 -- m4_1 being midway looks more like a glitch +# * Comm delays are 1e7 for f scenarios, 1e8 for m4_1, and 1e9 for m2_2 and m1_4 +# -- m4_1 being midway looks more like a glitch # * m2_2 is showing a slight disbalance of one worker being less utilised than the others, all others look balanced # In[284]: @@ -229,9 +237,11 @@ def analyzeTasks(df): # ## Transmit Takeaways -# * The number of redundant transfers is low, just 8, in the 2-2 scenario. However, they still contributed 1e9 to the total runtime! +# * The number of redundant transfers is low, just 8, in the 2-2 scenario. +# However, they still contributed 1e9 to the total runtime! # * Much more remote than local transfers in the 2-2 scenario -- 166 vs 27 -# * Mean comm delay for m1_4 is 9e6 whereas for m4_1 its 1e7 -- suggesting number of hosts is not that important on this front +# * Mean comm delay for m1_4 is 9e6 whereas for m4_1 its 1e7 +# -- suggesting number of hosts is not that important on this front # In[274]: diff --git a/docs/benchmarking/run2/analysis.py b/docs/benchmarking/run2/analysis.py index c249ffee..29d5e2a3 100644 --- a/docs/benchmarking/run2/analysis.py +++ b/docs/benchmarking/run2/analysis.py @@ -5,7 +5,8 @@ # * Controller reports available as well, showing that a lot of time is spent in the `act` phase of sending (sequentially!) the commands to the hosts. I realize now that the `act` is blocking, so the transmit are effectively serialized at the controller! # noqa: E501 # * Redundant local transports mostly vanished -- there are times when the planner decides in a single step that a dataset is needed at two workers on a host so issues two transmit commands. We could thus replace the redundant sent by idle time, to save network etc. It happens only 3 times out of 55 in the 2,2 scenario # noqa: E501 # -# The `lA` logs here represent the code/measurements _before_ transmits were reworked to happen async, the `lB` the _after_. +# The `lA` logs here represent the code/measurements _before_ transmits were reworked to happen async, +# the `lB` the _after_. # The `act` phase duration has shortened considerably, but the overall duration has increased -- possibly due to increased contention, due to introduction of locks, etc. But the overall amount of transmits has stayed roughly the same (even dripped a tiny bit). In particular, duration of the longest transmit has increased 4 times in the 2-host 2-worker scenario, **from 1 second to 4 seconds**. During that time, both sides of the transmit were doing other things as well (transmitting other datasets, computing tasks, etc). # noqa: E501 # # ### Next steps @@ -13,7 +14,8 @@ # * Fuse the multi-transmit # * When picking transmit, prefer local ones # * Create a tooling for worker's timeline visualisation/exploration, to understand the contention -# * Possibly parametrize the contention: how many concurrent transmits to allow, whether to allow transmits concurrent to task, pick least busy worker for transmits... +# * Possibly parametrize the contention: how many concurrent transmits to allow, +# whether to allow transmits concurrent to task, pick least busy worker for transmits... # # In[1]: diff --git a/docs/tutorials/cascade-job_building/t03_custom.py b/docs/tutorials/cascade-job_building/t03_custom.py index c9ddd2da..acbdc139 100644 --- a/docs/tutorials/cascade-job_building/t03_custom.py +++ b/docs/tutorials/cascade-job_building/t03_custom.py @@ -106,7 +106,8 @@ def _apply(f: Callable, i: (str, xr.DataArray), over_dims: list[str]) -> xr.Data # we need to wrap so that possible downstream actions can parse return xr.Dataset({varName: result}) - # there are two project methods, required because of how cascade/python act on generator functions. I need to fix this so that only the generator is required + # there are two project methods, required because of how cascade/python act on generator functions. + # I need to fix this so that only the generator is required @staticmethod def _project_one(i: xr.Dataset, variables: list[str]) -> tuple[str, xr.DataArray]: return variables[0], i[variables[0]] @@ -181,11 +182,16 @@ def __init__( """ (thought) exercises for the reader -1. ApplyNumpyReduce assumes reduction in coordinates -- what would we need to do to allow for an apply that preserves dims? -2. We dont set ext_outputs anywhere, meaning nothing is returned when we run the job! How would we best go about it? -3. Imagine we want a job that outputs temperMeanOfMaxes *and* precipMeanOverTime at once, ie, the Source is shared -- what would we need to change? +1. ApplyNumpyReduce assumes reduction in coordinates -- what would we need to do to allow for an apply + that preserves dims? +2. We dont set ext_outputs anywhere, meaning nothing is returned when we run the job! + How would we best go about it? +3. Imagine we want a job that outputs temperMeanOfMaxes *and* precipMeanOverTime at once, + ie, the Source is shared -- what would we need to change? note: try to come up with two distinct solutions here, hint: "merge" vs "singleton" -4. Implement a NumpyCombine, ie, a class that takes a callable and *two* DatasetSubgraphs, and the `f` takes two xr.DatasetArrays. For example, `sum`. +4. Implement a NumpyCombine, ie, a class that takes a callable and *two* DatasetSubgraphs, + and the `f` takes two xr.DatasetArrays. For example, `sum`. note: each of the two distinct solutions from previous exercise can be used as a stepping stone here -5. Implement each of the precipMeanOverTime, temperMeanOfMaxes, etc, using the ekw.fluent module, ie, our mature solution of the framework problem +5. Implement each of the precipMeanOverTime, temperMeanOfMaxes, etc, using the ekw.fluent module, + ie, our mature solution of the framework problem """ diff --git a/src/cascade/controller/impl.py b/src/cascade/controller/impl.py index be41dc47..02073e57 100644 --- a/src/cascade/controller/impl.py +++ b/src/cascade/controller/impl.py @@ -76,7 +76,8 @@ def run( mark({"action": ControllerPhases.wait}) if state.has_awaitable() or context.has_awaitable(): logger.debug( - f"about to await bridge with {context.ongoing_total=}, {context.remaining=} and {state.has_awaitable()=}" + f"about to await bridge with {context.ongoing_total=}," + f" {context.remaining=} and {state.has_awaitable()=}" ) events = timer(bridge.recv_events, Microtrace.ctrl_wait)() timer(notify_wrapper, Microtrace.ctrl_notify)(events) diff --git a/src/cascade/controller/notify.py b/src/cascade/controller/notify.py index 8b2fc878..069b8d32 100644 --- a/src/cascade/controller/notify.py +++ b/src/cascade/controller/notify.py @@ -89,7 +89,8 @@ def notify( for event in events: if isinstance(event, DatasetPublished): logger.debug(f"received {event=}") - # NOTE here we'll need to distinguish memory-only and host-wide (shm) publications, currently all events mean shm + # NOTE here we'll need to distinguish memory-only and host-wide (shm) publications, + # currently all events mean shm host = event.origin if isinstance(event.origin, HostId) else event.origin.host context.host2ds[host][event.ds] = DatasetStatus.available context.ds2host[event.ds][host] = DatasetStatus.available diff --git a/src/cascade/executor/executor.py b/src/cascade/executor/executor.py index 0306ce05..f18f4e62 100644 --- a/src/cascade/executor/executor.py +++ b/src/cascade/executor/executor.py @@ -272,7 +272,8 @@ def healthcheck(self) -> None: ) if self.heartbeat_watcher.is_breach() > 0: logger.debug( - f"grace elapsed without message by {self.heartbeat_watcher.elapsed_ms()} -> sending explicit heartbeat at {self.host}" + f"grace elapsed without message by {self.heartbeat_watcher.elapsed_ms()}" + f" -> sending explicit heartbeat at {self.host}" ) # NOTE we send registration in place of heartbeat -- it makes the startup more reliable, # and the registration's size overhead is negligible diff --git a/src/cascade/executor/msg.py b/src/cascade/executor/msg.py index f248517e..150e24d4 100644 --- a/src/cascade/executor/msg.py +++ b/src/cascade/executor/msg.py @@ -25,7 +25,8 @@ VERSION = 1 # for serde compatibility -# TODO use dataclass_transform to get mypy understand that @message/@element produces dataclasses, and that @message produces Messages +# TODO use dataclass_transform to get mypy understand that @message/@element produces dataclasses, +# and that @message produces Messages # Then replace the `@dataclass`es below with @message/@element # NOTE how would we deal with existing dataclasses like WorkerId? diff --git a/src/cascade/executor/runner/entrypoint.py b/src/cascade/executor/runner/entrypoint.py index 3772db06..6cce7914 100644 --- a/src/cascade/executor/runner/entrypoint.py +++ b/src/cascade/executor/runner/entrypoint.py @@ -180,7 +180,10 @@ def execute_sequence( def entrypoint(runnerContextClpkl: bytes): - """RunnerContext is a cloudpickled instance of RunnerContext -- needed for forkserver mp context due to defautdicts.""" + """RunnerContext is a cloudpickled instance of RunnerContext. + + Needed for forkserver mp context due to defautdicts. + """ runnerContext = cloudpickle.loads(runnerContextClpkl) init_from_obj(runnerContext.loggingConfig, f"worker_{runnerContext.workerId.worker}") ctx = zmq.Context() diff --git a/src/cascade/executor/runner/packages.py b/src/cascade/executor/runner/packages.py index 7f1ea7c1..8ca9b5c5 100644 --- a/src/cascade/executor/runner/packages.py +++ b/src/cascade/executor/runner/packages.py @@ -56,7 +56,10 @@ def run_command(command: list[str]) -> tuple[str, str]: # either badly deployed or code bug of calling bad command -> InternalError raise CascadeInternalError(f"command failure: {ex}", parent=ex) from ex if result.returncode != 0: - msg = f"command failed with {result.returncode}. Stderr: {result.stderr}, Stdout: {result.stdout}, Args: {result.args}" + msg = ( + f"command failed with {result.returncode}. Stderr: {result.stderr}," + f" Stdout: {result.stdout}, Args: {result.args}" + ) logger.error(msg) if "was not found in the package registry" in result.stderr: @@ -90,7 +93,13 @@ def new_venv() -> tempfile.TemporaryDirectory: def _parse_pip_install(pip_output: str) -> dict[str, Version]: - r"""Assumed input like: 'Using Python 3.11.8 environment at: \nResolved 1 package in 5ms\nUninstalled 1 package in 12ms\nInstalled 1 package in 18ms\n - numpy==2.4.2\n + numpy==2.4.1\n' + r"""Parse uv pip install output. + + Assumed input like:: + + 'Using Python 3.11.8 environment at: \nResolved 1 package in 5ms\n + Uninstalled 1 package in 12ms\nInstalled 1 package in 18ms\n - numpy==2.4.2\n + numpy==2.4.1\n' + Provided output: {'numpy': '2.4.1'}. """ rv = {} @@ -254,7 +263,8 @@ def extend(self, packages: list[str]) -> None: _, install_output = run_command(install_command) logger.debug(f"install result: {install_output}") - # NOTE this is wrong because we would need to reliably unload modules, but that apparently aint possible in python + # NOTE this is wrong because we would need to reliably unload modules, + # but that apparently aint possible in python # importlib.invalidate_caches() install_issues = _postinstall_verify(install_output) if install_issues: diff --git a/src/cascade/gateway/__init__.py b/src/cascade/gateway/__init__.py index eb709d61..ffe350fc 100644 --- a/src/cascade/gateway/__init__.py +++ b/src/cascade/gateway/__init__.py @@ -12,5 +12,6 @@ - receiving progress updates and data results from the jobs, - serving progress/result queries, presumably from a frontend. -It is a standalone single process, with multiple zmq sockets (large data requests, regular request-response, update stream, ...). +It is a standalone single process, with multiple zmq sockets +(large data requests, regular request-response, update stream, ...). """ diff --git a/src/cascade/low/core.py b/src/cascade/low/core.py index 88ac9822..a731cee8 100644 --- a/src/cascade/low/core.py +++ b/src/cascade/low/core.py @@ -131,7 +131,8 @@ class JobInstance(BaseModel): edges: list[Task2TaskEdge] serdes: dict[str, tuple[str, str]] = Field( default_factory=lambda: {}, - description="for each Type with custom serde, add entry here. The string is fully qualified name of the ser/des functions", + description="for each Type with custom serde, add entry here." + " The string is fully qualified name of the ser/des functions", ) ext_outputs: list[DatasetId] = Field( default_factory=lambda: [], diff --git a/src/cascade/low/exceptions.py b/src/cascade/low/exceptions.py index 887e775a..ef38eaaa 100644 --- a/src/cascade/low/exceptions.py +++ b/src/cascade/low/exceptions.py @@ -73,7 +73,8 @@ def des(s: str) -> CascadeError: # Try to match pattern: ClassName('detail') or ClassName("detail") # We need to handle both single and double quotes, and escaped quotes match = re.match( - r"^(CascadeError|CascadeInternalError|CascadeInfrastructureError|CascadeUserError)\((['\"])(.+?)\2(?:, parent=.*)?\)$", + r"^(CascadeError|CascadeInternalError|CascadeInfrastructureError|CascadeUserError)" + r"\((['\"])(.+?)\2(?:, parent=.*)?\)$", s, re.DOTALL, ) diff --git a/src/cascade/low/tracing.py b/src/cascade/low/tracing.py index 9cfbafdb..8f7e6ae8 100644 --- a/src/cascade/low/tracing.py +++ b/src/cascade/low/tracing.py @@ -47,7 +47,8 @@ class TransmitLifecycle(str, Enum): class ControllerPhases(str, Enum): # ordered exactly as controller cycles through - assign = "ctrl_assign" # assignment of tasks to workers and submitting to executor, reports how many events were awaited prior + assign = "ctrl_assign" # assignment of tasks to workers and submitting to executor, + # reports how many events were awaited prior plan = "ctrl_plan" # planning, ie, update of schedule; reports how many actions were sent in `assign` flush = "ctrl_flush" # calculate dataset purges and fetches, submit to executor wait = "ctrl_wait" # await on executor results diff --git a/src/cascade/scheduler/assign.py b/src/cascade/scheduler/assign.py index 48f94c6e..90146f0b 100644 --- a/src/cascade/scheduler/assign.py +++ b/src/cascade/scheduler/assign.py @@ -68,7 +68,8 @@ def build_assignment(worker: WorkerId, task: TaskId, context: JobExecutionContex # if we are dealing with the first task to assign, we don't expect to be here! if not assigned: raise CascadeInternalError(description=f"{dataset=} not found anywhere!") - # if we are already trying some fusing opportunities, it is legit to not find the dataset anywhere + # if we are already trying some fusing opportunities, it is legit + # to not find the dataset anywhere else: # TODO rollback preps done for this one task exhausted = True @@ -331,7 +332,8 @@ def assign_within_component( worker for worker in workers if context.environment.workers[worker].gpu > 0 and worker in context.idle_workers ] logger.debug( - f"considering {len(gpu_t)}# gpu tasks, {len(opu_t)}# maybe-gpu tasks, {len(cpu_t)}# cpu tasks, with {len(workers)}# workers out of which {len(eligible_w)} have gpu" + f"considering {len(gpu_t)}# gpu tasks, {len(opu_t)}# maybe-gpu tasks, {len(cpu_t)}# cpu tasks," + f" with {len(workers)}# workers out of which {len(eligible_w)} have gpu" ) yield from _assignment_heuristic(schedule, gpu_t, eligible_w, component_id, context) # tasks whose fusing opportunity needs a gpu diff --git a/src/cascade/scheduler/core.py b/src/cascade/scheduler/core.py index 0c613e31..2c26764d 100644 --- a/src/cascade/scheduler/core.py +++ b/src/cascade/scheduler/core.py @@ -65,7 +65,8 @@ class ComponentSchedule: # tasks that are either computable or that are among outputs of currently prepared tasks (as those # could become computable without any further planning) worker2task_distance: Worker2TaskDistance - # eligible values -- a cached value. Used when migrating new workers to the component, inserted whenever a parent of this task gets `preparing`, removed when this task is assigned + # eligible values -- a cached value. Used when migrating new workers to the component, + # inserted whenever a parent of this task gets `preparing`, removed when this task is assigned worker2task_values: set[TaskId] gang_preparation: GangPreparation diff --git a/src/cascade/scheduler/precompute.py b/src/cascade/scheduler/precompute.py index 11e99a77..bc695c32 100644 --- a/src/cascade/scheduler/precompute.py +++ b/src/cascade/scheduler/precompute.py @@ -37,7 +37,8 @@ def _nearest_common_descendant( remaining_children = {v: len(children[v]) for v in nodes} queue = [v for v in nodes if remaining_children[v] == 0] - # for each pair of vertices V & U, we store here their so-far-nearest common descendant D + max(dist(V, D), dist(U, D)) + # for each pair of vertices V & U, we store here their so-far-nearest common descendant D + # + max(dist(V, D), dist(U, D)) # we need to keep track of D while we build this to be able to recalculate, but we'll drop it in the end result: dict[TaskId, dict[TaskId, tuple[TaskId, int]]] = {} while queue: diff --git a/src/cascade/shm/func.py b/src/cascade/shm/func.py index 864bf989..3afe2086 100644 --- a/src/cascade/shm/func.py +++ b/src/cascade/shm/func.py @@ -6,7 +6,8 @@ # granted to it by virtue of its status as an intergovernmental organisation # nor does it submit to any jurisdiction. -# NOTE Copy of cascade.low.{func, exceptions} -- dont want to create dependency in either direction. Ideally one func typing util lib +# NOTE Copy of cascade.low.{func, exceptions} -- dont want to create dependency in either direction. +# Ideally one func typing util lib from typing import Any, NoReturn diff --git a/tests/cascade/controller/test_run.py b/tests/cascade/controller/test_run.py index 4dec0812..a3d7c651 100644 --- a/tests/cascade/controller/test_run.py +++ b/tests/cascade/controller/test_run.py @@ -236,7 +236,10 @@ def test_checkpoints(): in a way that recognizes whether it checkpointed or not. """ with tempfile.TemporaryDirectory() as tmp_root, tempfile.TemporaryDirectory() as ckpt_root: - sourcetask_code = f"import pathlib; f = pathlib.Path('{tmp_root}') / 'file.txt'; f.write_text('ok') if not f.exists() else 1/0;" + sourcetask_code = ( + f"import pathlib; f = pathlib.Path('{tmp_root}') / 'file.txt';" + " f.write_text('ok') if not f.exists() else 1/0;" + ) jobInstance = ( ( JobBuilder() diff --git a/tests/cascade/executor/test_executor.py b/tests/cascade/executor/test_executor.py index 2b0cbf5d..7e420ef2 100644 --- a/tests/cascade/executor/test_executor.py +++ b/tests/cascade/executor/test_executor.py @@ -198,8 +198,10 @@ def test_func(x: np.ndarray) -> np.ndarray: daddress=c1, ), ) - # NOTE the below ceased to work since we introduced retries. Now recomputation of a result after a purge is not possible - # assert len(ms) == 1 and isinstance(ms[0], DatasetTransmitPayload) and ms[0].header.ds == DatasetId(task='sink', output='o') + # NOTE the below ceased to work since we introduced retries. + # Now recomputation of a result after a purge is not possible + # assert len(ms) == 1 and isinstance(ms[0], DatasetTransmitPayload) and \ + # ms[0].header.ds == DatasetId(task='sink', output='o') # assert serde.des_output(ms[0].value, 'ndarray', ms[0].header.deser_fun)[0] == 11. # callback(ms[0].header.confirm_address, DatasetTransmitConfirm(idx=ms[0].header.confirm_idx)) diff --git a/tests/cascade/executor/test_packages.py b/tests/cascade/executor/test_packages.py index e23588d5..f77513ba 100644 --- a/tests/cascade/executor/test_packages.py +++ b/tests/cascade/executor/test_packages.py @@ -25,7 +25,8 @@ def test_run_command() -> None: with pytest.raises( CascadeInternalError, match=re.escape( - "command failure: [Errno 2] No such file or directory: 'you' (caused by FileNotFoundError(2, 'No such file or directory'))" + "command failure: [Errno 2] No such file or directory: 'you'" + " (caused by FileNotFoundError(2, 'No such file or directory'))" ), ): run_command(bad1_command) @@ -37,7 +38,10 @@ def test_run_command() -> None: def test_parse_pip_install() -> None: - assumed = "Using Python 3.11.8 environment at: \nResolved 1 package in 5ms\nUninstalled 1 package in 12ms\nInstalled 1 package in 18ms\n - numpy==2.4.2\n + numpy==2.4.1\n" + assumed = ( + "Using Python 3.11.8 environment at: \nResolved 1 package in 5ms\n" + "Uninstalled 1 package in 12ms\nInstalled 1 package in 18ms\n - numpy==2.4.2\n + numpy==2.4.1\n" + ) expected = {"numpy": Version("2.4.1")} assert _parse_pip_install(assumed) == expected, "failed to parse assumed uv output" import numpy @@ -45,7 +49,8 @@ def test_parse_pip_install() -> None: _, actual = run_command(["uv", "pip", "install", f"numpy=={numpy.__version__}"]) expected = {} assert _parse_pip_install(actual) == expected, "failed to parse actual uv output" - # TODO it would be nice to actually do some pip install here, but im reluctant to do that in a unit test. Some for test_postinstall_verify + # TODO it would be nice to actually do some pip install here, but im reluctant to do that in a unit test. + # Same for test_postinstall_verify def test_get_dist_modules() -> None: @@ -68,10 +73,16 @@ def test_maybe_module_version() -> None: def test_postinstall_verify() -> None: import numpy - goodie = "Using Python 3.11.8 environment at: \nResolved 1 package in 5ms\nUninstalled 1 package in 12ms\nInstalled 1 package in 18ms\n - numpy==2.4.2\n + numpy=={numpy.__version__}\n" + goodie = ( + "Using Python 3.11.8 environment at: \nResolved 1 package in 5ms\n" + f"Uninstalled 1 package in 12ms\nInstalled 1 package in 18ms\n - numpy==2.4.2\n + numpy=={numpy.__version__}\n" + ) issues = _postinstall_verify(goodie) assert not issues - baddie = "Using Python 3.11.8 environment at: \nResolved 1 package in 5ms\nUninstalled 1 package in 12ms\nInstalled 1 package in 18ms\n - numpy==2.4.2\n + numpy==1.0.0\n" + baddie = ( + "Using Python 3.11.8 environment at: \nResolved 1 package in 5ms\n" + "Uninstalled 1 package in 12ms\nInstalled 1 package in 18ms\n - numpy==2.4.2\n + numpy==1.0.0\n" + ) issues = _postinstall_verify(baddie) assert issues == [ InstallIssue( diff --git a/tests/cascade/executor/util.py b/tests/cascade/executor/util.py index 52d1b180..ccf9653e 100644 --- a/tests/cascade/executor/util.py +++ b/tests/cascade/executor/util.py @@ -8,7 +8,8 @@ """Module for simplifying writing tests. -It is capable, for a single given task, to spin an shm server, put all task's inputs into it, execute the task, store outputs in memory, and retrieve the result. +It is capable, for a single given task, to spin an shm server, put all task's inputs into it, +execute the task, store outputs in memory, and retrieve the result. See the `demo()` function at the very end """ From 130d4947bee390acac322740733728647ec44d5a Mon Sep 17 00:00:00 2001 From: Oskar Weser Date: Mon, 16 Mar 2026 16:22:49 +0100 Subject: [PATCH 11/19] fixed ruff problems manually (or ignored them) --- benchmarks/scenario-shm_throughput.py | 3 ++- pyproject.toml | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/benchmarks/scenario-shm_throughput.py b/benchmarks/scenario-shm_throughput.py index 72618984..919a8cb2 100644 --- a/benchmarks/scenario-shm_throughput.py +++ b/benchmarks/scenario-shm_throughput.py @@ -1,5 +1,6 @@ """Benchmark shm in isolation (without cascade) by just invoking a lot of reads and writes -in a limited memory setting.""" +in a limited memory setting. +""" import multiprocessing as mp import random diff --git a/pyproject.toml b/pyproject.toml index 004bcf29..e221b703 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -62,6 +62,7 @@ ignore = [ "D213", "D401", "D402", + "D404", "D413", "D415", "D416", From d8b1b3dc64a7c11d79ac84a61b1060cc19d05556 Mon Sep 17 00:00:00 2001 From: Oskar Weser Date: Tue, 17 Mar 2026 16:55:30 +0100 Subject: [PATCH 12/19] fixed undefined names --- .pre-commit-config.yaml | 2 -- pyproject.toml | 2 +- src/earthkit/workflows/adapters.py | 4 ++++ src/earthkit/workflows/compilers.py | 7 +++++-- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ccda0b7a..73bdfa72 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -18,10 +18,8 @@ repos: - id: ruff-check exclude: '(dev/.*|.*_)\.py$' args: - - --line-length=120 - --fix - --exit-non-zero-on-fix - - --preview - id: ruff-format - repo: https://github.com/macisamuele/language-formatters-pre-commit-hooks rev: v2.16.0 diff --git a/pyproject.toml b/pyproject.toml index e221b703..eef1d2bf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -51,11 +51,11 @@ testpaths = ["tests/"] [tool.ruff] line-length = 120 +preview = true [tool.ruff.lint] ignore = [ "D1", # pydocstyle: Missing Docstrings - "D107", # pydocstyle: numpy convention "D203", "D205", "D212", diff --git a/src/earthkit/workflows/adapters.py b/src/earthkit/workflows/adapters.py index cc50964f..2251d4d6 100644 --- a/src/earthkit/workflows/adapters.py +++ b/src/earthkit/workflows/adapters.py @@ -14,6 +14,10 @@ Currently, only cascade is supported. """ +import logging + +logger = logging.getLogger(__name__) + try: from cascade.low.core import DefaultTaskOutput diff --git a/src/earthkit/workflows/compilers.py b/src/earthkit/workflows/compilers.py index e0c8be37..d82f9b8e 100644 --- a/src/earthkit/workflows/compilers.py +++ b/src/earthkit/workflows/compilers.py @@ -14,18 +14,21 @@ Currently, only cascade is supported. """ +import logging from typing import Any, Literal from earthkit.workflows.graph import Graph, serialise +logger = logging.getLogger(__name__) + try: from cascade.low.core import JobInstance from cascade.low.into import graph2job as cascadeInto except ImportError: - logger.error("failed to import any execution engine! Defaulting to dummy impl") + logger.error("Failed to import any execution engine! Defaulting to dummy implementation") def cascadeInto(graph: dict) -> Any: - raise NotImplementedError("failed to import cascade execution engine") + raise NotImplementedError("Failed to import cascade execution engine") JobInstance = Any From f86b931a12adcc960893f306080678365d449a79 Mon Sep 17 00:00:00 2001 From: Oskar Weser Date: Tue, 17 Mar 2026 16:56:33 +0100 Subject: [PATCH 13/19] fixed remaining ruff problems --- src/cascade/deployment/logging/__init__.py | 1 - tests/cascade/low/test_exceptions.py | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/cascade/deployment/logging/__init__.py b/src/cascade/deployment/logging/__init__.py index 3bb54b97..83847f49 100644 --- a/src/cascade/deployment/logging/__init__.py +++ b/src/cascade/deployment/logging/__init__.py @@ -33,7 +33,6 @@ import base64 import logging import logging.config -import os from typing import Literal import orjson diff --git a/tests/cascade/low/test_exceptions.py b/tests/cascade/low/test_exceptions.py index af7b1758..5ddf909a 100644 --- a/tests/cascade/low/test_exceptions.py +++ b/tests/cascade/low/test_exceptions.py @@ -106,6 +106,6 @@ def test_ser_des_roundtrip_all_types(): for exc in exceptions: serialized = ser(exc) deserialized = des(serialized) - assert type(deserialized) == type(exc) + assert type(deserialized) is type(exc) assert deserialized.description == exc.description assert deserialized.parent is None From 44b91bca06655e7076259825607c90b2e84b5c5c Mon Sep 17 00:00:00 2001 From: Oskar Weser Date: Tue, 24 Mar 2026 11:27:46 +0100 Subject: [PATCH 14/19] fixed small issues --- src/cascade/scheduler/api.py | 2 +- src/cascade/shm/func.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cascade/scheduler/api.py b/src/cascade/scheduler/api.py index 905733d9..87abf46e 100644 --- a/src/cascade/scheduler/api.py +++ b/src/cascade/scheduler/api.py @@ -38,7 +38,7 @@ def gang_check_ready(task: TaskId, gang_prep: GangPreparation): for gang in gang_prep.lookup[task]: if gang not in gang_prep.countdown: raise CascadeInternalError( - description=f"after {task=} marked computable, {gang=} not found -- double compuptable mark?" + description=f"after {task=} marked computable, {gang=} not found -- double computable mark?" ) remaining = gang_prep.countdown[gang] if task not in remaining: diff --git a/src/cascade/shm/func.py b/src/cascade/shm/func.py index 3afe2086..7e134603 100644 --- a/src/cascade/shm/func.py +++ b/src/cascade/shm/func.py @@ -21,5 +21,5 @@ class ShmInfrastructureError(ValueError): def assert_never(v: Any) -> NoReturn: - """For exhaustive enumm checks etc.""" + """For exhaustive enum checks etc.""" raise TypeError(f"unexpected value in exhaustive check: {v!r}") From b4a2fc16e3dc71464710f9a5d08d0220807645ae Mon Sep 17 00:00:00 2001 From: Oskar Weser Date: Tue, 24 Mar 2026 11:30:34 +0100 Subject: [PATCH 15/19] final formatting --- docs/benchmarking/run1/analysis.ipynb | 3 +- docs/benchmarking/run1/analysis.py | 3 +- docs/ensemble_percentiles.ipynb | 3 +- docs/examples/arrayapi.ipynb | 3 +- docs/introduction.md | 13 ++-- .../cascade-job_building/t00_generate.py | 6 +- integration_tests/benchmarks_old/job1.py | 40 ++++++----- src/cascade/controller/act.py | 30 ++++---- src/cascade/controller/notify.py | 28 ++++---- src/cascade/executor/data_server.py | 68 ++++++++----------- src/cascade/executor/executor.py | 12 ++-- src/cascade/executor/platform.py | 1 + src/cascade/gateway/spawning.py | 22 +++--- src/cascade/main.py | 3 +- src/earthkit/workflows/fluent.py | 3 +- .../backends/test_register.py | 8 +-- .../backends/test_xarray.py | 16 ++--- .../graph/test_transform.py | 12 ++-- tests/earthkit_workflows/test_fluent.py | 50 ++++++-------- .../test_qubed_expansion.py | 56 +++++++-------- 20 files changed, 167 insertions(+), 213 deletions(-) diff --git a/docs/benchmarking/run1/analysis.ipynb b/docs/benchmarking/run1/analysis.ipynb index ea2bb29f..e5aaeb30 100644 --- a/docs/benchmarking/run1/analysis.ipynb +++ b/docs/benchmarking/run1/analysis.ipynb @@ -495,7 +495,8 @@ ], "source": [ "taskCompareF1F4 = (\n", - " task_f1.set_index([\"task\"])[[\"total\"]]\n", + " task_f1\n", + " .set_index([\"task\"])[[\"total\"]]\n", " .rename(columns={\"total\": \"total1\"})\n", " .join(task_f4.set_index([\"task\"])[[\"total\"]].rename(columns={\"total\": \"total4\"}))\n", ")\n", diff --git a/docs/benchmarking/run1/analysis.py b/docs/benchmarking/run1/analysis.py index 7213134a..738883d7 100644 --- a/docs/benchmarking/run1/analysis.py +++ b/docs/benchmarking/run1/analysis.py @@ -178,7 +178,8 @@ def analyzeTasks(df): taskCompareF1F4 = ( - task_f1.set_index(["task"])[["total"]] + task_f1 + .set_index(["task"])[["total"]] .rename(columns={"total": "total1"}) .join(task_f4.set_index(["task"])[["total"]].rename(columns={"total": "total4"})) ) diff --git a/docs/ensemble_percentiles.ipynb b/docs/ensemble_percentiles.ipynb index 2c4b56c2..b18bcabb 100644 --- a/docs/ensemble_percentiles.ipynb +++ b/docs/ensemble_percentiles.ipynb @@ -279,7 +279,8 @@ " perc = da.quantile(q=0.80, dim=\"member\", skipna=False)\n", " res.append(perc)\n", "ref = (\n", - " xr.combine_nested(res, concat_dim=\"leadtime\")\n", + " xr\n", + " .combine_nested(res, concat_dim=\"leadtime\")\n", " .assign_coords({\"leadtime\": coords[\"leadtime\"]})\n", " .drop_vars([\"quantile\"])\n", ")\n", diff --git a/docs/examples/arrayapi.ipynb b/docs/examples/arrayapi.ipynb index 108a995d..760cde85 100644 --- a/docs/examples/arrayapi.ipynb +++ b/docs/examples/arrayapi.ipynb @@ -229,7 +229,8 @@ "outputs": [], "source": [ "graph = (\n", - " initial_action.mean(\"x\")\n", + " initial_action\n", + " .mean(\"x\")\n", " .min(\"y\")\n", " .expand(\"z\", internal_dim=1, dim_size=3, axis=0)\n", " .map([lambda x, a=a: x * a for a in range(1, 4)])\n", diff --git a/docs/introduction.md b/docs/introduction.md index 193cd5a8..17a17772 100644 --- a/docs/introduction.md +++ b/docs/introduction.md @@ -39,7 +39,7 @@ applied across the `parameter` dimension. The ``fluent`` module provides a ``from_source`` method for creating the initial node array by specifying an array of functions. For example to create a single node that opens a xarray dataset ```python -import xarray as xr +import xarray as xr import functools from cascade.fluent import from_source @@ -48,7 +48,7 @@ initial_action = from_source(func) ``` To create multiple nodes, supply an array of functions to be executed in each node, and optionally dims and coordinates for labelling the axis of the node array. For example, ```python -import numpy as np +import numpy as np import functools from cascade.fluent import from_source @@ -79,13 +79,11 @@ The graphs constructing using the Casacde API do not contain any annotations for from cascade.transformers import to_taskgraph from cascade.taskgraph import Resources -task_graph = to_taskgraph(graph, { - x.name: Resources(100, 50) for x in graph.nodes() -}) +task_graph = to_taskgraph(graph, {x.name: Resources(100, 50) for x in graph.nodes()}) ``` Alternatively, the graph can be executed and profiled to determine the duration and memory requirements of each task using memray. ```python -from cascade.profiler import profile +from cascade.profiler import profile from cascade.executors.dask import LocalDaskExecutor executor = LocalDaskExecutor() @@ -114,8 +112,7 @@ To execute a graph using the ``DaskLocalExecutor``, do the following: ```python from cascade.executors.dask import DaskLocalExecutor -results = DaskLocalExecutor(n_workers=2, threads_per_worker=1, processes=True, - memory_limit="10G").execute(graph) +results = DaskLocalExecutor(n_workers=2, threads_per_worker=1, processes=True, memory_limit="10G").execute(graph) ``` The ``graph`` variable can be ``Graph`` or a ``Schedule``. If a ``Schedule`` is provided, then the executor will modify the task graph in order for Dask to execute it according to the predefined diff --git a/docs/tutorials/cascade-job_building/t00_generate.py b/docs/tutorials/cascade-job_building/t00_generate.py index 680521db..4ef9273a 100644 --- a/docs/tutorials/cascade-job_building/t00_generate.py +++ b/docs/tutorials/cascade-job_building/t00_generate.py @@ -14,6 +14,6 @@ def generate_data() -> xr.Dataset: "precip": np.random.rand(10, 10, 24), "temper": np.random.rand(10, 10, 24), } - return xr.Dataset( - {key: xr.DataArray(value, dims=tuple(coords.keys()), coords=coords) for key, value in variables.items()} - ) + return xr.Dataset({ + key: xr.DataArray(value, dims=tuple(coords.keys()), coords=coords) for key, value in variables.items() + }) diff --git a/integration_tests/benchmarks_old/job1.py b/integration_tests/benchmarks_old/job1.py index 4c57baaf..a42c89ab 100644 --- a/integration_tests/benchmarks_old/job1.py +++ b/integration_tests/benchmarks_old/job1.py @@ -48,25 +48,21 @@ ) for f in files ] -inputs = from_source( - [ - { - "source": "fileset", - "location": data_root + "/data_{number}_{step}.grib", - "number": list(range(1, NUM_ENSEMBLES + 1)), - "step": list(range(0, END_STEP + 1, 3)), - } - ] -) -climatology = from_source( - [ - { - "source": "fileset", - "location": data_root + "/data_clim_{stepRange}.grib", - "stepRange": ["0-24", "24-48"], # list(range(0, END_STEP - 23, 24)), - } - ] -) +inputs = from_source([ + { + "source": "fileset", + "location": data_root + "/data_{number}_{step}.grib", + "number": list(range(1, NUM_ENSEMBLES + 1)), + "step": list(range(0, END_STEP + 1, 3)), + } +]) +climatology = from_source([ + { + "source": "fileset", + "location": data_root + "/data_clim_{stepRange}.grib", + "stepRange": ["0-24", "24-48"], # list(range(0, END_STEP - 23, 24)), + } +]) def get_prob(): @@ -74,7 +70,8 @@ def get_prob(): Range(f"{x}-{x + 120}", list(range(x + 6, x + 121, 6))) for x in range(0, END_STEP - 119, 120) ] return ( - inputs.window_operation("min", prob_windows, dim="step", batch_size=2) + inputs + .window_operation("min", prob_windows, dim="step", batch_size=2) .ensemble_operation( "threshold_prob", comparison="<=", @@ -93,7 +90,8 @@ def get_ensms(): def get_efi(): efi_windows = [Range(f"{x}-{x + 24}", list(range(x + 6, x + 25, 6))) for x in range(0, END_STEP - 23, 24)] return ( - inputs.window_operation("mean", efi_windows, dim="step", batch_size=2) + inputs + .window_operation("mean", efi_windows, dim="step", batch_size=2) .ensemble_extreme( "extreme", climatology, diff --git a/src/cascade/controller/act.py b/src/cascade/controller/act.py index 2346a8c6..f2dcb0e6 100644 --- a/src/cascade/controller/act.py +++ b/src/cascade/controller/act.py @@ -34,15 +34,13 @@ def act(bridge: Bridge, assignment: Assignment) -> None: logger.debug(f"dataset {ds} should be locally available at {assignment.worker.host}, doing no-op") continue logger.debug(f"sending transmit ({ds}: {source_host}=>{assignment.worker.host}) to bridge") - mark( - { - "dataset": repr(ds), - "action": TransmitLifecycle.planned, - "source": source_host, - "target": assignment.worker.host, - "host": "controller", - } - ) + mark({ + "dataset": repr(ds), + "action": TransmitLifecycle.planned, + "source": source_host, + "target": assignment.worker.host, + "host": "controller", + }) bridge.transmit(ds, source_host, assignment.worker.host) task_sequence = TaskSequence( @@ -53,14 +51,12 @@ def act(bridge: Bridge, assignment: Assignment) -> None: ) for task in assignment.tasks: - mark( - { - "task": task, - "action": TaskLifecycle.planned, - "worker": repr(assignment.worker), - "host": "controller", - } - ) + mark({ + "task": task, + "action": TaskLifecycle.planned, + "worker": repr(assignment.worker), + "host": "controller", + }) logger.debug(f"sending {task_sequence} to bridge") bridge.task_sequence(task_sequence) diff --git a/src/cascade/controller/notify.py b/src/cascade/controller/notify.py index 069b8d32..373d1f17 100644 --- a/src/cascade/controller/notify.py +++ b/src/cascade/controller/notify.py @@ -98,14 +98,12 @@ def notify( state.consider_persist(event.ds, host) consider_computable(schedule, state, context, event.ds, host) if event.transmit_idx is not None: - mark( - { - "dataset": repr(event.ds), - "action": TransmitLifecycle.completed, - "target": host, - "host": "controller", - } - ) + mark({ + "dataset": repr(event.ds), + "action": TransmitLifecycle.completed, + "target": host, + "host": "controller", + }) elif context.is_last_output_of(event.ds): worker = event.origin task = event.ds.task @@ -116,14 +114,12 @@ def notify( logger.debug(f"last output of {task}, assuming completion") state.task_done(task, context.edge_i.get(event.ds.task, set())) if isWorker: - mark( - { - "task": task, - "action": TaskLifecycle.completed, - "worker": repr(worker), - "host": "controller", - } - ) + mark({ + "task": task, + "action": TaskLifecycle.completed, + "worker": repr(worker), + "host": "controller", + }) worker = cast(WorkerId, worker) # ty cant yet derive this to be true context.task_done_at(task, worker) else: diff --git a/src/cascade/executor/data_server.py b/src/cascade/executor/data_server.py index a7b499da..142a8e97 100644 --- a/src/cascade/executor/data_server.py +++ b/src/cascade/executor/data_server.py @@ -113,14 +113,12 @@ def _store_payload(self, payload: DatasetTransmitPayload) -> int: except shm_client.ConflictError as e: # NOTE this branch is for situations where the controller issued redundantly two transmits logger.warning(f"store of {payload.header.ds} failed with {e}, presumably already computed; continuing") - mark( - { - "dataset": repr(payload.header.ds), - "action": TransmitLifecycle.unloaded, - "target": self.host, - "mode": "redundant", - } - ) + mark({ + "dataset": repr(payload.header.ds), + "action": TransmitLifecycle.unloaded, + "target": self.host, + "mode": "redundant", + }) return time_ns() buf.view()[:l] = payload.value buf.close() @@ -132,14 +130,12 @@ def _store_payload(self, payload: DatasetTransmitPayload) -> int: transmit_idx=payload.header.confirm_idx, ), ) - mark( - { - "dataset": repr(payload.header.ds), - "action": TransmitLifecycle.unloaded, - "target": self.host, - "mode": "remote", - } - ) + mark({ + "dataset": repr(payload.header.ds), + "action": TransmitLifecycle.unloaded, + "target": self.host, + "mode": "remote", + }) except Exception as e: logger.exception("failed to store payload of {payload.header.ds}, reporting up") callback( @@ -203,15 +199,13 @@ def _send_payload(self, command: DatasetTransmitCommand) -> int: if command.target == self.host or command.source != self.host: raise CascadeInternalError(f"invalid {command=}") buf = shm_client.get(key=ds2shmid(command.ds)) - mark( - { - "dataset": repr(command.ds), - "action": TransmitLifecycle.loaded, - "target": command.target, - "source": self.host, - "mode": "remote", - } - ) + mark({ + "dataset": repr(command.ds), + "action": TransmitLifecycle.loaded, + "target": command.target, + "source": self.host, + "mode": "remote", + }) header = DatasetTransmitPayloadHeader( confirm_address=self.daddress, confirm_idx=command.idx, @@ -256,13 +250,11 @@ def recv_loop(self) -> None: raise CascadeInternalError( f"unexpected transmit command {m} as the dataset was already purged" ) - mark( - { - "dataset": repr(m.ds), - "action": TransmitLifecycle.started, - "target": m.target, - } - ) + mark({ + "dataset": repr(m.ds), + "action": TransmitLifecycle.started, + "target": m.target, + }) self.awaiting_confirmation[m.idx] = (m, -1) fut = self.ds_proc_tp.submit(self._send_payload, m) self.futs_in_progress[m] = fut @@ -282,13 +274,11 @@ def recv_loop(self) -> None: if m.header.ds in self.invalid: logger.warning(f"ignoring transmit payload {m.header} as the dataset was already purged") continue - mark( - { - "dataset": repr(m.header.ds), - "action": TransmitLifecycle.received, - "target": self.host, - } - ) + mark({ + "dataset": repr(m.header.ds), + "action": TransmitLifecycle.received, + "target": self.host, + }) fut = self.ds_proc_tp.submit(self._store_payload, m) self.futs_in_progress[m] = fut elif isinstance(m, Ack): diff --git a/src/cascade/executor/executor.py b/src/cascade/executor/executor.py index f18f4e62..5a108fb4 100644 --- a/src/cascade/executor/executor.py +++ b/src/cascade/executor/executor.py @@ -292,13 +292,11 @@ def recv_loop(self) -> None: # from controller if isinstance(m, TaskSequence): for task in m.tasks: - mark( - { - "task": task, - "worker": repr(m.worker), - "action": TaskLifecycle.enqueued, - } - ) + mark({ + "task": task, + "worker": repr(m.worker), + "action": TaskLifecycle.enqueued, + }) handle = self.workers[m.worker] if handle is None or handle.process.exitcode is not None: # unexpected exit -> InfrastructureError diff --git a/src/cascade/executor/platform.py b/src/cascade/executor/platform.py index 1c317671..99d94996 100644 --- a/src/cascade/executor/platform.py +++ b/src/cascade/executor/platform.py @@ -79,6 +79,7 @@ def advise_seqread(fd: int) -> None: fcntl.fcntl(fd, F_RDADVISE, 1) except OSError: pass + else: def advise_seqread(fd: int) -> None: diff --git a/src/cascade/gateway/spawning.py b/src/cascade/gateway/spawning.py index f6d1e0a0..ff6fed4e 100644 --- a/src/cascade/gateway/spawning.py +++ b/src/cascade/gateway/spawning.py @@ -60,18 +60,16 @@ def _spawn_troika_singlehost( script_path, stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH | stat.S_IWUSR | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH, ) - return subprocess.Popen( - [ - "troika", - "-c", - troika_config, - "submit", - "-o", - f"/tmp/output.{job_id}.txt", - troika.conn, - script_path, - ] - ) + return subprocess.Popen([ + "troika", + "-c", + troika_config, + "submit", + "-o", + f"/tmp/output.{job_id}.txt", + troika.conn, + script_path, + ]) def _spawn_local( diff --git a/src/cascade/main.py b/src/cascade/main.py index 9505f3d1..b7e23e41 100644 --- a/src/cascade/main.py +++ b/src/cascade/main.py @@ -45,7 +45,8 @@ def _get_cuda_count() -> int: return visible_count gpus = sum( 1 - for l in subprocess.run(["nvidia-smi", "--list-gpus"], check=True, capture_output=True) + for l in subprocess + .run(["nvidia-smi", "--list-gpus"], check=True, capture_output=True) .stdout.decode("ascii") .split("\n") if "GPU" in l diff --git a/src/earthkit/workflows/fluent.py b/src/earthkit/workflows/fluent.py index a659fca1..bc92132f 100644 --- a/src/earthkit/workflows/fluent.py +++ b/src/earthkit/workflows/fluent.py @@ -828,7 +828,8 @@ def std( **backend_kwargs, ).power(2, path=npath) norm = ( - action.power(2, path=npath) + action + .power(2, path=npath) .sum( dim=dim, path=npath, diff --git a/tests/earthkit_workflows/backends/test_register.py b/tests/earthkit_workflows/backends/test_register.py index d03e18d9..7f24e2e1 100644 --- a/tests/earthkit_workflows/backends/test_register.py +++ b/tests/earthkit_workflows/backends/test_register.py @@ -29,11 +29,9 @@ def empty_backend(): """Fixture to reset the BACKENDS dictionary before each test.""" BACKEND_COPY = backends.BACKENDS.copy() backends.BACKENDS.clear() - backends.BACKENDS.update( - { - object: ArrayAPIBackend, - } - ) + backends.BACKENDS.update({ + object: ArrayAPIBackend, + }) yield backends.BACKENDS.clear() backends.BACKENDS.update(BACKEND_COPY) diff --git a/tests/earthkit_workflows/backends/test_xarray.py b/tests/earthkit_workflows/backends/test_xarray.py index 20b1f3d4..437fb1b9 100644 --- a/tests/earthkit_workflows/backends/test_xarray.py +++ b/tests/earthkit_workflows/backends/test_xarray.py @@ -100,15 +100,13 @@ def values(self, array): class TestXarrayDatasetBackend(XarrayBackend): def input_generator(self, number: int, shape=(2, 3)): return [ - xr.Dataset( - { - "test": xr.DataArray( - np.random.rand(*shape), - dims=[f"dim{x}" for x in range(len(shape))], - coords={f"dim{x}": range(shape[x]) for x in range(len(shape))}, - ) - } - ) + xr.Dataset({ + "test": xr.DataArray( + np.random.rand(*shape), + dims=[f"dim{x}" for x in range(len(shape))], + coords={f"dim{x}": range(shape[x]) for x in range(len(shape))}, + ) + }) for _ in range(number) ] diff --git a/tests/earthkit_workflows/graph/test_transform.py b/tests/earthkit_workflows/graph/test_transform.py index 3fa0b7fa..75bfcb49 100644 --- a/tests/earthkit_workflows/graph/test_transform.py +++ b/tests/earthkit_workflows/graph/test_transform.py @@ -142,13 +142,11 @@ def test_depdict_disc(): deps = to_depdict(g) edeps = {} for i in range(6): - edeps.update( - { - f"writer-{i}": {"input": (f"process-{i}", D)}, - f"process-{i}": {"input": (f"reader-{i}", D)}, - f"reader-{i}": {}, - } - ) + edeps.update({ + f"writer-{i}": {"input": (f"process-{i}", D)}, + f"process-{i}": {"input": (f"reader-{i}", D)}, + f"reader-{i}": {}, + }) assert deps == edeps diff --git a/tests/earthkit_workflows/test_fluent.py b/tests/earthkit_workflows/test_fluent.py index aa76d641..463be811 100644 --- a/tests/earthkit_workflows/test_fluent.py +++ b/tests/earthkit_workflows/test_fluent.py @@ -302,22 +302,18 @@ def test_func(length: int, *multipliers): def test_split(): input_action = mock_action((3, 4)) - branches = input_action.split( - { - "/branch1": lambda data: np.where(data <= 0, data, np.nan), - "/branch2": lambda data: np.where(data > 0, data, np.nan), - } - ) + branches = input_action.split({ + "/branch1": lambda data: np.where(data <= 0, data, np.nan), + "/branch2": lambda data: np.where(data > 0, data, np.nan), + }) for npath, narray in nodetree_arrays(branches.nodes): assert narray.shape == (3, 4) assert "branch" in npath - subbranches = branches.split( - { - "/branch1/subbranch1": lambda data: np.where(data < 0, data, np.nan), - "/branch1/subbranch2": lambda data: np.where(data == 0, data, np.nan), - } - ) + subbranches = branches.split({ + "/branch1/subbranch1": lambda data: np.where(data < 0, data, np.nan), + "/branch1/subbranch2": lambda data: np.where(data == 0, data, np.nan), + }) assert [x[0] for x in nodetree_arrays(subbranches.nodes)] == [ "/branch2", "/branch1/subbranch1", @@ -329,12 +325,10 @@ def test_split(): with_root = input_action.set_path("/root") with pytest.raises(ValueError): - with_root.split( - { - "/branch1": lambda data: np.where(data <= 0, data, np.nan), - "/branch2": lambda data: np.where(data > 0, data, np.nan), - } - ) + with_root.split({ + "/branch1": lambda data: np.where(data <= 0, data, np.nan), + "/branch2": lambda data: np.where(data > 0, data, np.nan), + }) @pytest.mark.parametrize( @@ -354,12 +348,10 @@ def test_select(selection, num_arrays, shapes_or_error): branch1=mock_action((3, 4)), branch2=mock_action((3, 5)), ) - subbranches = branches.split( - { - "/branch1/subbranch1": lambda data: np.where(data < 0, data, np.nan), - "/branch1/subbranch2": lambda data: np.where(data == 0, data, np.nan), - } - ) + subbranches = branches.split({ + "/branch1/subbranch1": lambda data: np.where(data < 0, data, np.nan), + "/branch1/subbranch2": lambda data: np.where(data == 0, data, np.nan), + }) subbranches.nodes["/branch2"].coords["type"] = "A" if num_arrays > 0: select_dim = subbranches.sel(**selection) @@ -387,12 +379,10 @@ def test_iselect(selection, num_arrays, shapes_or_error): branch1=mock_action((3, 4)), branch2=mock_action((3, 5)), ) - subbranches = branches.split( - { - "/branch1/subbranch1": lambda data: np.where(data < 0, data, np.nan), - "/branch1/subbranch2": lambda data: np.where(data == 0, data, np.nan), - } - ) + subbranches = branches.split({ + "/branch1/subbranch1": lambda data: np.where(data < 0, data, np.nan), + "/branch1/subbranch2": lambda data: np.where(data == 0, data, np.nan), + }) if num_arrays > 0: select_dim = subbranches.isel(**selection) assert len(list(nodetree_arrays(select_dim.nodes))) == num_arrays diff --git a/tests/earthkit_workflows/test_qubed_expansion.py b/tests/earthkit_workflows/test_qubed_expansion.py index 3baf9f5c..669f1d35 100644 --- a/tests/earthkit_workflows/test_qubed_expansion.py +++ b/tests/earthkit_workflows/test_qubed_expansion.py @@ -30,24 +30,20 @@ def simple_qube(): @pytest.fixture def surface_variables_qube(): """Create a qube representing surface variables.""" - return Qube.from_datacube( - { - "step": [6, 12], - "param": ["100u", "100v", "10u", "10v", "2d", "2t"], - } - ) + return Qube.from_datacube({ + "step": [6, 12], + "param": ["100u", "100v", "10u", "10v", "2d", "2t"], + }) @pytest.fixture def pressure_level_qube(): """Create a qube representing pressure level variables.""" - return Qube.from_datacube( - { - "step": [6, 12], - "param": ["q", "t", "u", "v"], - "level": [50, 100, 150, 200, 250], - } - ) + return Qube.from_datacube({ + "step": [6, 12], + "param": ["q", "t", "u", "v"], + "level": [50, 100, 150, 200, 250], + }) @pytest.fixture @@ -63,21 +59,17 @@ def hierarchical_qube(): After expansion, children should have BOTH step AND their own dims. """ # Create children with step dimension AND their own dimensions - surface = Qube.from_datacube( - { - "step": [6, 12], - "param": ["100u", "100v", "10u", "10v", "2d", "2t"], - } - ) + surface = Qube.from_datacube({ + "step": [6, 12], + "param": ["100u", "100v", "10u", "10v", "2d", "2t"], + }) surface.add_metadata({"name": "surface"}) - pressure = Qube.from_datacube( - { - "step": [6, 12], - "param": ["q", "t", "u", "v"], - "level": [50, 100, 150, 200, 250], - } - ) + pressure = Qube.from_datacube({ + "step": [6, 12], + "param": ["q", "t", "u", "v"], + "level": [50, 100, 150, 200, 250], + }) pressure.add_metadata({"name": "pressure"}) # Combine: both children have step, so parent will have step @@ -109,13 +101,11 @@ def multi_level_qube(): child2 = Qube.from_datacube({"step": [1, 2, 3], "param": ["c", "d"], "class": "od"}) - nested = Qube.from_datacube( - { - "step": [1, 2, 3], - "param": ["c", "d"], - "level": [100, 200], - } - ) + nested = Qube.from_datacube({ + "step": [1, 2, 3], + "param": ["c", "d"], + "level": [100, 200], + }) # Combine: child2 and nested both have step+param, so child2|nested will have those child2_with_nested = child2 | nested From bf42f0a8184b91987a2e0e091fd97d35a5841677 Mon Sep 17 00:00:00 2001 From: Oskar Weser Date: Tue, 24 Mar 2026 11:34:22 +0100 Subject: [PATCH 16/19] made pre-commit hook less tolerant --- .pre-commit-config.yaml | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 73bdfa72..42b60f95 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,16 +2,17 @@ repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: v6.0.0 hooks: - - id: check-yaml # Check YAML files for syntax errors only - args: [--unsafe, --allow-multiple-documents] -# - id: no-commit-to-branch # NOTE prevents commit to main/master, but since we run prek on that branch it makes no sense + - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-json + - id: check-yaml + - id: check-toml - id: check-added-large-files - exclude: | - (?x)( - .*uv.lock| - .*pylock.toml - ) - - id: check-merge-conflict # Check for files that contain merge conflict + - id: check-merge-conflict + - id: debug-statements + - id: mixed-line-ending + - id: no-commit-to-branch + args: [--branch, main] - repo: https://github.com/astral-sh/ruff-pre-commit rev: v0.15.4 hooks: From 64a17dc4bb892faec9cd027d4ece8d9df24eb763 Mon Sep 17 00:00:00 2001 From: Oskar Weser Date: Tue, 24 Mar 2026 11:40:13 +0100 Subject: [PATCH 17/19] fix trailing whitespaces --- AGENTS.md | 2 +- LICENSE | 2 +- docs/benchmarking/slurm_entrypoint.sh | 4 ++-- docs/benchmarking/slurm_submit.sh | 1 - docs/introduction.md | 33 +++++++++++++-------------- 5 files changed, 20 insertions(+), 22 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 388fc7b3..4cd05502 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -4,7 +4,7 @@ * there are two python modules -- cascade which is a low level execution engine, and earthkit.workflows which is a higher level abstraction on top of it. Each has its own subdirectory in tests * always use type annotations, it is enforced * when working with a package with bad typing coverage like sqlalchemy, use ty:ignore comment - * when ty is not powerful enough, use ty:ignore + * when ty is not powerful enough, use ty:ignore * use typing.cast when the code logic is implicitly erasing the type information * prioritize using pydantic.BaseModel or dataclasses.dataclass object for capturing contracts and interfaces. * ideally keep them plain, stateless, frozen, without functions -- we end up serializing those objects often over to other python processes or different languages diff --git a/LICENSE b/LICENSE index 74a60543..32d3e94a 100644 --- a/LICENSE +++ b/LICENSE @@ -198,4 +198,4 @@ distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and - limitations under the License. \ No newline at end of file + limitations under the License. diff --git a/docs/benchmarking/slurm_entrypoint.sh b/docs/benchmarking/slurm_entrypoint.sh index 45097af1..8a691e15 100644 --- a/docs/benchmarking/slurm_entrypoint.sh +++ b/docs/benchmarking/slurm_entrypoint.sh @@ -16,14 +16,14 @@ source ~/venv/casc/bin/activate # TODO make this externally sourcable config # *** ------ *** -# *** job prep *** +# *** job prep *** echo "starting procid.jobid $SLURM_PROCID.$SLURM_JOBID with param $1 at host $(hostname) with nodes $SLURM_NODELIST" WORKER_NODES=$((SLURM_NTASKS-1)) CONTROLLER="$(echo $SLURM_NODELIST | sed 's/\(ac.-\)\[\?\([0-9]*\).*/\1\2/')" CONTROLLER_URL="tcp://$CONTROLLER:5555" echo "selected controller $CONTROLLER at $CONTROLLER_URL, expecting $WORKER_NODES" mkdir -p $LOGGING_ROOT/$SLURM_JOBID -# *** -------- *** +# *** -------- *** # *** job run *** if [ "$(hostname | cut -f 1 -d.)" == "$CONTROLLER" ] ; then diff --git a/docs/benchmarking/slurm_submit.sh b/docs/benchmarking/slurm_submit.sh index 1c401308..9695ecdd 100644 --- a/docs/benchmarking/slurm_submit.sh +++ b/docs/benchmarking/slurm_submit.sh @@ -8,4 +8,3 @@ srun -J cascade-devel-01 --nodes=$((EXECUTOR_HOSTS+1)) --ntasks-per-node=1 --qos # - executor hosts should be param # - the config part of the entrypoint should be sourced # - correct the entrypoint path - diff --git a/docs/introduction.md b/docs/introduction.md index 17a17772..910e9d3f 100644 --- a/docs/introduction.md +++ b/docs/introduction.md @@ -4,21 +4,21 @@ Introduction Cascade has three main components: - **Action** defines the language for constructing task graphs and the accompanying backend objects the graph operations on - **Schedulers** for scheduling the task graphs based on task resource requirements -- **Executors** for executing the task graph +- **Executors** for executing the task graph Fluent ------ The function cascading API for constructing graphs consists low level methods such as: - ``reduce`` -- ``join`` +- ``join`` - ``broadcast`` - ``expand`` - ``transform`` - ``map`` - ``flatten`` -which operate on the array of nodes in the graph, creating new nodes, and return another action object. +which operate on the array of nodes in the graph, creating new nodes, and return another action object. The figure below shows a ``Action.reduce`` operation on a three-dimensional array of nodes over the `parameter` dimension, which returns ``Action`` containing a two-dimensional array of nodes on the right-hand side. @@ -26,11 +26,11 @@ dimension, which returns ``Action`` containing a two-dimensional array of nodes -Most of the methods require a ``Callable`` which specifies the function to be applied on the array of nodes. For example, for ``Action.reduce`` the signature is +Most of the methods require a ``Callable`` which specifies the function to be applied on the array of nodes. For example, for ``Action.reduce`` the signature is ```python def reduce(self, payload: Callable, dim: str = "") -> "Action": ``` -where an example could be +where an example could be ```python payload = lambda x, y, z: x**2 + y**2 + z**2 ``` @@ -46,7 +46,7 @@ from cascade.fluent import from_source func = functools.partial(xr.open_dataset, "/path/to/dataset") initial_action = from_source(func) ``` -To create multiple nodes, supply an array of functions to be executed in each node, and optionally dims and coordinates for labelling the axis of the node array. For example, +To create multiple nodes, supply an array of functions to be executed in each node, and optionally dims and coordinates for labelling the axis of the node array. For example, ```python import numpy as np import functools @@ -55,7 +55,7 @@ from cascade.fluent import from_source func = functools(np.random.rand, 2, 3) initial_action = from_source(np.full((2, 2), func), dims=["x", "y"]) ``` -In this case, `initial_action` would contain a (2, 2) array of nodes with dimension "x" and "y", each containing (2, 3) random numpy array. +In this case, `initial_action` would contain a (2, 2) array of nodes with dimension "x" and "y", each containing (2, 3) random numpy array. One can then construct a graph from this point using the function cascading API: ```python @@ -71,10 +71,10 @@ graph = ( ) ``` -Resources +Resources --------- -The graphs constructing using the Casacde API do not contain any annotations for resource usage of the tasks in each node. To manually attach resources to the tasks, we transform the graph into a ``TaskGraph`` object, providing a dictionary of `Resources`, containing CPU cost and memory, for each node name. +The graphs constructing using the Casacde API do not contain any annotations for resource usage of the tasks in each node. To manually attach resources to the tasks, we transform the graph into a ``TaskGraph`` object, providing a dictionary of `Resources`, containing CPU cost and memory, for each node name. ```python from cascade.transformers import to_taskgraph from cascade.taskgraph import Resources @@ -97,16 +97,16 @@ Schedulers The schedulers assign the tasks in the graph to workers according to a ``ContextGraph`` and the resource requirements of the tasks in the ``TaskGraph``. Currently, two schedulers are available: - ``DepthFirstScheduler``: assigns tasks according using a similated run of execution proceeding via a depth first traversal of the graph -- ``AnnealingScheduler``: schedules the graph using a simulated annealing algorithm, with the initial +- ``AnnealingScheduler``: schedules the graph using a simulated annealing algorithm, with the initial schedule determined by the ``DepthFirstScheduler`` Executors --------- -The available executors are based on the Dask distributed local executor and Kubernetes executor. Both have been adapted to either use the dynamic scheduler provided by Dask or execute according to a provided schedule. +The available executors are based on the Dask distributed local executor and Kubernetes executor. Both have been adapted to either use the dynamic scheduler provided by Dask or execute according to a provided schedule. -**Does not currently create workers according to ``ContextGraph``** +**Does not currently create workers according to ``ContextGraph``** To execute a graph using the ``DaskLocalExecutor``, do the following: ```python @@ -114,10 +114,9 @@ from cascade.executors.dask import DaskLocalExecutor results = DaskLocalExecutor(n_workers=2, threads_per_worker=1, processes=True, memory_limit="10G").execute(graph) ``` -The ``graph`` variable can be ``Graph`` or a ``Schedule``. If a ``Schedule`` is provided, then the -executor will modify the task graph in order for Dask to execute it according to the predefined -schedule. The method returns a dictionary of node names and associated contents of the sinks in the +The ``graph`` variable can be ``Graph`` or a ``Schedule``. If a ``Schedule`` is provided, then the +executor will modify the task graph in order for Dask to execute it according to the predefined +schedule. The method returns a dictionary of node names and associated contents of the sinks in the graph. -The execution also produces a Dask performance report, which is a html file containing information about the resources used during the run and a task stream for each worker. - +The execution also produces a Dask performance report, which is a html file containing information about the resources used during the run and a task stream for each worker. From 852bbd60ff0d76d9b5060014f696708ca6b8198f Mon Sep 17 00:00:00 2001 From: Oskar Weser Date: Wed, 25 Mar 2026 10:19:36 +0100 Subject: [PATCH 18/19] added back in the exclude --- .pre-commit-config.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 42b60f95..2805dce8 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -8,6 +8,11 @@ repos: - id: check-yaml - id: check-toml - id: check-added-large-files + exclude: | + (?x)( + .*uv.lock| + .*pylock.toml + ) - id: check-merge-conflict - id: debug-statements - id: mixed-line-ending From 3f2d0143acf6edae3a18ede79388e7a440dabbd1 Mon Sep 17 00:00:00 2001 From: Oskar Weser Date: Wed, 25 Mar 2026 10:22:08 +0100 Subject: [PATCH 19/19] go back to 140 max line length --- benchmarks/scheduling/sat_experiments.py | 3 +-- docs/ensemble_percentiles.ipynb | 11 ++------ .../cascade-job_building/t00_generate.py | 4 +-- .../cascade-job_building/t03_custom.py | 4 +-- integration_tests/benchmarks_old/dist.py | 8 ++---- integration_tests/benchmarks_old/job1.py | 6 +---- integration_tests/benchmarks_old/util.py | 4 +-- integration_tests/job_runnerRestarts.py | 9 +------ pyproject.toml | 2 +- src/cascade/controller/impl.py | 5 +--- src/cascade/executor/bridge.py | 27 ++++--------------- src/cascade/executor/checkpoints.py | 16 +++-------- src/cascade/executor/comms.py | 8 ++---- src/cascade/executor/data_server.py | 24 +++++------------ src/cascade/executor/executor.py | 19 ++++--------- src/cascade/executor/runner/entrypoint.py | 12 +++------ src/cascade/executor/runner/memory.py | 8 ++---- src/cascade/executor/runner/packages.py | 9 ++----- src/cascade/gateway/router.py | 4 +-- src/cascade/gateway/spawning.py | 4 +-- src/cascade/low/builders.py | 3 +-- src/cascade/low/core.py | 23 +++++----------- src/cascade/main.py | 5 +--- src/cascade/scheduler/api.py | 10 ++----- src/cascade/scheduler/assign.py | 26 +++++------------- src/cascade/scheduler/checkpoints.py | 10 ++----- src/cascade/scheduler/core.py | 8 ++---- src/cascade/scheduler/precompute.py | 4 +-- src/cascade/shm/api.py | 8 +----- src/earthkit/workflows/fluent.py | 11 +++----- src/earthkit/workflows/graph/export.py | 5 +--- src/earthkit/workflows/graph/graph.py | 3 +-- src/earthkit/workflows/graph/networkx.py | 8 ++---- src/earthkit/workflows/graph/samplegraphs.py | 5 +--- src/earthkit/workflows/graph/split.py | 4 +-- tests/cascade/controller/test_run.py | 14 ++-------- tests/cascade/executor/test_executor.py | 6 +---- tests/cascade/executor/test_packages.py | 9 ++----- tests/cascade/executor/util.py | 4 +-- tests/cascade/low/test_builders.py | 13 ++------- tests/cascade/scheduler/util.py | 6 +---- .../backends/generic_tests.py | 5 +--- .../backends/test_arrayapi.py | 4 +-- tests/earthkit_workflows/graph/test_visit.py | 12 +++------ tests/earthkit_workflows/test_fluent.py | 4 +-- 45 files changed, 89 insertions(+), 308 deletions(-) diff --git a/benchmarks/scheduling/sat_experiments.py b/benchmarks/scheduling/sat_experiments.py index 06a82fbc..57e2cdca 100644 --- a/benchmarks/scheduling/sat_experiments.py +++ b/benchmarks/scheduling/sat_experiments.py @@ -129,8 +129,7 @@ def solve(problem: Problem): if solver.value(problem.worker2task[(task, worker)]) == 1: target = worker print( - f"{task=} => from {solver.value(problem.taskIntervals[task][0])}" - f" to {solver.value(problem.taskIntervals[task][1])} at {target}" + f"{task=} => from {solver.value(problem.taskIntervals[task][0])} to {solver.value(problem.taskIntervals[task][1])} at {target}" ) print(f"end = {solver.value(problem.end)}") diff --git a/docs/ensemble_percentiles.ipynb b/docs/ensemble_percentiles.ipynb index b18bcabb..7b8b5cbc 100644 --- a/docs/ensemble_percentiles.ipynb +++ b/docs/ensemble_percentiles.ipynb @@ -210,9 +210,7 @@ " Payload(\n", " write_netcdf,\n", " [Node.input_name(0)],\n", - " kwargs=dict(\n", - " dims=dims, attrs=attrs, coords=coords, varname=\"rainfall\", filename=OUTFILE, mode=\"w\", engine=\"netcdf4\"\n", - " ),\n", + " kwargs=dict(dims=dims, attrs=attrs, coords=coords, varname=\"rainfall\", filename=OUTFILE, mode=\"w\", engine=\"netcdf4\"),\n", " )\n", ")" ] @@ -278,12 +276,7 @@ " da = ds[\"rainfall\"].isel(leadtime=step).transpose(\"member\", \"y\", \"x\")\n", " perc = da.quantile(q=0.80, dim=\"member\", skipna=False)\n", " res.append(perc)\n", - "ref = (\n", - " xr\n", - " .combine_nested(res, concat_dim=\"leadtime\")\n", - " .assign_coords({\"leadtime\": coords[\"leadtime\"]})\n", - " .drop_vars([\"quantile\"])\n", - ")\n", + "ref = xr.combine_nested(res, concat_dim=\"leadtime\").assign_coords({\"leadtime\": coords[\"leadtime\"]}).drop_vars([\"quantile\"])\n", "ref.to_netcdf(\"dask_results.nc\")\n", "ref" ] diff --git a/docs/tutorials/cascade-job_building/t00_generate.py b/docs/tutorials/cascade-job_building/t00_generate.py index 4ef9273a..5ed0782f 100644 --- a/docs/tutorials/cascade-job_building/t00_generate.py +++ b/docs/tutorials/cascade-job_building/t00_generate.py @@ -14,6 +14,4 @@ def generate_data() -> xr.Dataset: "precip": np.random.rand(10, 10, 24), "temper": np.random.rand(10, 10, 24), } - return xr.Dataset({ - key: xr.DataArray(value, dims=tuple(coords.keys()), coords=coords) for key, value in variables.items() - }) + return xr.Dataset({key: xr.DataArray(value, dims=tuple(coords.keys()), coords=coords) for key, value in variables.items()}) diff --git a/docs/tutorials/cascade-job_building/t03_custom.py b/docs/tutorials/cascade-job_building/t03_custom.py index acbdc139..7d8647d9 100644 --- a/docs/tutorials/cascade-job_building/t03_custom.py +++ b/docs/tutorials/cascade-job_building/t03_custom.py @@ -145,9 +145,7 @@ def __init__( for i, v in enumerate(target): applyT = TaskBuilder.from_callable(ApplyNumpyReduce._apply).with_values(f=f, over_dims=over_dims) applyN = f"apply_{uuid.uuid4()}" - self.implementation = self.implementation.with_node(applyN, applyT).with_edge( - projectN, applyN, "i", f"{i}" - ) + self.implementation = self.implementation.with_node(applyN, applyT).with_edge(projectN, applyN, "i", f"{i}") self.projection[applyN] = {v} diff --git a/integration_tests/benchmarks_old/dist.py b/integration_tests/benchmarks_old/dist.py index ac0ed534..f3a8d5df 100644 --- a/integration_tests/benchmarks_old/dist.py +++ b/integration_tests/benchmarks_old/dist.py @@ -108,12 +108,8 @@ def get_job() -> JobInstance: node = TaskBuilder.from_callable(build_dist_func(IMPL)) for i in range(L): - job = ( - job.with_node(f"proc{i}", node).with_edge("source", f"proc{i}", "a").with_edge(f"proc{i}", "sink", f"v{i}") - ) - job.nodes["sink"].definition.input_schema[f"v{i}"] = ( - "int" # TODO put some allow_kw into TaskDefinition instead to allow this - ) + job = job.with_node(f"proc{i}", node).with_edge("source", f"proc{i}", "a").with_edge(f"proc{i}", "sink", f"v{i}") + job.nodes["sink"].definition.input_schema[f"v{i}"] = "int" # TODO put some allow_kw into TaskDefinition instead to allow this job = job.build().get_or_raise() job.ext_outputs = list(job.outputs_of("sink")) diff --git a/integration_tests/benchmarks_old/job1.py b/integration_tests/benchmarks_old/job1.py index a42c89ab..f73da3cf 100644 --- a/integration_tests/benchmarks_old/job1.py +++ b/integration_tests/benchmarks_old/job1.py @@ -36,11 +36,7 @@ # ** JOB DEFINITIONS *** -files = [ - f"{data_root}/data_{number}_{step}.grib" - for number in range(1, NUM_ENSEMBLES + 1) - for step in range(0, END_STEP + 1, 3) -] +files = [f"{data_root}/data_{number}_{step}.grib" for number in range(1, NUM_ENSEMBLES + 1) for step in range(0, END_STEP + 1, 3)] payloads = [ Payload( lambda f: earthkit.data.from_source("file", f), diff --git a/integration_tests/benchmarks_old/util.py b/integration_tests/benchmarks_old/util.py index 7c8851f0..056789b8 100644 --- a/integration_tests/benchmarks_old/util.py +++ b/integration_tests/benchmarks_old/util.py @@ -40,9 +40,7 @@ def get_job(benchmark: str | None, instance_path: str | None) -> JobInstanceRich "j1.ensms": job1.get_ensms(), "j1.efi": job1.get_efi(), } - union = lambda prefix: deduplicate_nodes( - msum((v for k, v in graphs.items() if k.startswith(prefix)), Graph) - ) + union = lambda prefix: deduplicate_nodes(msum((v for k, v in graphs.items() if k.startswith(prefix)), Graph)) graphs["j1.all"] = union("j1.") instance = cascade.low.into.graph2job(graphs[benchmark]) elif benchmark.startswith("generators"): diff --git a/integration_tests/job_runnerRestarts.py b/integration_tests/job_runnerRestarts.py index bf53e81e..d642fcbe 100644 --- a/integration_tests/job_runnerRestarts.py +++ b/integration_tests/job_runnerRestarts.py @@ -12,14 +12,7 @@ def job() -> JobInstanceRich: [f"numpy=={version}"], ).with_values(expected=version) - ji = ( - JobBuilder() - .with_node("t1", fac("2.0.1")) - .with_node("t2", fac("2.4.1")) - .with_node("t3", fac("2.4.2")) - .build() - .get_or_raise() - ) + ji = JobBuilder().with_node("t1", fac("2.0.1")).with_node("t2", fac("2.4.1")).with_node("t3", fac("2.4.2")).build().get_or_raise() return JobInstanceRich(jobInstance=ji, checkpointSpec=None) diff --git a/pyproject.toml b/pyproject.toml index eef1d2bf..cd3a33f5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -50,7 +50,7 @@ log_cli_level = "DEBUG" testpaths = ["tests/"] [tool.ruff] -line-length = 120 +line-length = 140 preview = true [tool.ruff.lint] diff --git a/src/cascade/controller/impl.py b/src/cascade/controller/impl.py index 02073e57..c4533820 100644 --- a/src/cascade/controller/impl.py +++ b/src/cascade/controller/impl.py @@ -75,10 +75,7 @@ def run( mark({"action": ControllerPhases.wait}) if state.has_awaitable() or context.has_awaitable(): - logger.debug( - f"about to await bridge with {context.ongoing_total=}," - f" {context.remaining=} and {state.has_awaitable()=}" - ) + logger.debug(f"about to await bridge with {context.ongoing_total=}, {context.remaining=} and {state.has_awaitable()=}") events = timer(bridge.recv_events, Microtrace.ctrl_wait)() timer(notify_wrapper, Microtrace.ctrl_notify)(events) logger.debug(f"received {len(events)} events") diff --git a/src/cascade/executor/bridge.py b/src/cascade/executor/bridge.py index 51e9b05d..47ec6cd3 100644 --- a/src/cascade/executor/bridge.py +++ b/src/cascade/executor/bridge.py @@ -43,25 +43,14 @@ logger = logging.getLogger(__name__) -Event = ( - DatasetPublished | DatasetTransmitPayload | DatasetPersistSuccess | DatasetRetrieveSuccess | RunnerRestartRequest -) +Event = DatasetPublished | DatasetTransmitPayload | DatasetPersistSuccess | DatasetRetrieveSuccess | RunnerRestartRequest # TODO consider retries here, esp on the Persist/Retrieve Failures -ToShutdown = ( - TaskFailure - | ExecutorFailure - | DatasetRetrieveFailure - | DatasetTransmitFailure - | DatasetPersistFailure - | ExecutorExit -) +ToShutdown = TaskFailure | ExecutorFailure | DatasetRetrieveFailure | DatasetTransmitFailure | DatasetPersistFailure | ExecutorExit Unsupported = TaskSequence | DatasetPurge | DatasetTransmitCommand | DatasetPersistCommand | ExecutorShutdown class Bridge: - def __init__( - self, controller_url: str, expected_executors: int, checkpoint_spec: CheckpointSpec | None = None - ) -> None: + def __init__(self, controller_url: str, expected_executors: int, checkpoint_spec: CheckpointSpec | None = None) -> None: self.checkpoint_spec = checkpoint_spec self.mlistener = Listener(controller_url) self.heartbeat_checker: dict[HostId, GraceWatcher] = {} @@ -84,9 +73,7 @@ def __init__( self.sender.add_host(message.host, message.maddress) self.sender.add_host("data." + message.host, message.daddress) for worker in message.workers: - self.environment.workers[worker.worker_id] = Worker( - cpu=worker.cpu, gpu=worker.gpu, memory_mb=worker.memory_mb - ) + self.environment.workers[worker.worker_id] = Worker(cpu=worker.cpu, gpu=worker.gpu, memory_mb=worker.memory_mb) self.environment.host_url_base[message.host] = message.url_base registered += 1 self.heartbeat_checker[message.host] = GraceWatcher(2 * executor_heartbeat_grace_ms) @@ -143,11 +130,7 @@ def recv_events(self) -> list[Event]: if isinstance(shutdown_reason, CascadeError): raise shutdown_reason - elif ( - isinstance(shutdown_reason, Message) - and hasattr(shutdown_reason, "detail") - and isinstance(shutdown_reason.detail, str) - ): + elif isinstance(shutdown_reason, Message) and hasattr(shutdown_reason, "detail") and isinstance(shutdown_reason.detail, str): raise des(shutdown_reason.detail) else: # unknown at this stage is assumed to be InfrastructureError diff --git a/src/cascade/executor/checkpoints.py b/src/cascade/executor/checkpoints.py index f0a69993..7f7880df 100644 --- a/src/cascade/executor/checkpoints.py +++ b/src/cascade/executor/checkpoints.py @@ -33,18 +33,14 @@ def serialize_params(spec: CheckpointSpec, id_: str) -> str: case "fs": if not isinstance(spec.storage_params, str): # we are in control of how these are created -> InternalError - raise CascadeInternalError( - f"expected checkpoint storage params to be str, gotten {spec.storage_params.__class__}" - ) + raise CascadeInternalError(f"expected checkpoint storage params to be str, gotten {spec.storage_params.__class__}") root = pathlib.Path(spec.storage_params) return str(root / id_) case s: assert_never(s) -def build_persist_command( - checkpoint_spec: CheckpointSpec | None, ds: DatasetId, hostId: HostId -) -> DatasetPersistCommand: +def build_persist_command(checkpoint_spec: CheckpointSpec | None, ds: DatasetId, hostId: HostId) -> DatasetPersistCommand: if checkpoint_spec is None: # should have been validated prior -> InternalError raise CascadeInternalError("unexpected persist need when checkpoint storage not configured") @@ -88,9 +84,7 @@ def list_persisted_datasets(spec: CheckpointSpec) -> list[DatasetId]: assert_never(s) -def build_retrieve_command( - checkpoint_spec: CheckpointSpec | None, ds: DatasetId, hostId: HostId -) -> DatasetRetrieveCommand: +def build_retrieve_command(checkpoint_spec: CheckpointSpec | None, ds: DatasetId, hostId: HostId) -> DatasetRetrieveCommand: if checkpoint_spec is None: # should have been validated prior -> InternalError raise CascadeInternalError("unexpected retrieve need when checkpoint storage not configured") @@ -143,9 +137,7 @@ def possible_repersist(dataset: DatasetId, checkpointSpec: CheckpointSpec | None raise CascadeInternalError("unexpected repersist when no persist id") if checkpointSpec.retrieve_id == checkpointSpec.persist_id: # we assume reproducibility---bold!---so we better warn about it - logger.warning( - f"no-op for persist of {dataset} as was already persisted under the same id {checkpointSpec.retrieve_id}" - ) + logger.warning(f"no-op for persist of {dataset} as was already persisted under the same id {checkpointSpec.retrieve_id}") return # NOTE the host is the virtual one so the message is not really valid, but no big deal diff --git a/src/cascade/executor/comms.py b/src/cascade/executor/comms.py index 76627533..40e85538 100644 --- a/src/cascade/executor/comms.py +++ b/src/cascade/executor/comms.py @@ -224,9 +224,7 @@ def maybe_retry(self) -> None: watermark = time.time_ns() - self.resend_grace for idx, record in self.inflight.items(): if record.at < watermark: - logger.warning( - f"retrying message {idx} ({record.clazz}) due to no confirmation after {watermark - record.at}ns" - ) + logger.warning(f"retrying message {idx} ({record.clazz}) due to no confirmation after {watermark - record.at}ns") if (socket := self.hosts.get(record.host, None)) is not None: socket[0].send_multipart(record.message) self.inflight[idx].at = time.time_ns() @@ -234,6 +232,4 @@ def maybe_retry(self) -> None: if self.inflight[idx].remaining <= 0: raise CascadeInfrastructureError(f"message {idx} ({record.clazz}) retried too many times") else: - logger.warning( - f"{record.host=} not present, cannot retry message {idx=}. Presumably we are at shutdown" - ) + logger.warning(f"{record.host=} not present, cannot retry message {idx=}. Presumably we are at shutdown") diff --git a/src/cascade/executor/data_server.py b/src/cascade/executor/data_server.py index 142a8e97..c5c55169 100644 --- a/src/cascade/executor/data_server.py +++ b/src/cascade/executor/data_server.py @@ -70,12 +70,8 @@ def __init__( DatasetTransmitCommand | DatasetTransmitPayload | DatasetPersistCommand | DatasetRetrieveCommand, Future ] = {} self.awaiting_confirmation: dict[int, tuple[DatasetTransmitCommand, int]] = {} - self.invalid: set[DatasetId] = ( - set() - ) # for preventing out-of-order stores/transmits for datasets that have already been purged - self.acks: set[int] = ( - set() - ) # it could happen that Ack arrives before respective Future finishes, so we need to store separately + self.invalid: set[DatasetId] = set() # for preventing out-of-order stores/transmits for datasets that have already been purged + self.acks: set[int] = set() # it could happen that Ack arrives before respective Future finishes, so we need to store separately # TODO the two above should be eventually purged, see comms.Listener.acked for a similar concern def maybe_clean(self) -> None: @@ -243,13 +239,9 @@ def recv_loop(self) -> None: logger.debug(f"received message {type(m)}") if isinstance(m, DatasetTransmitCommand): if m.idx in self.awaiting_confirmation: - raise CascadeInternalError( - f"transmit idx conflict: {m}, {self.awaiting_confirmation[m.idx]}" - ) + raise CascadeInternalError(f"transmit idx conflict: {m}, {self.awaiting_confirmation[m.idx]}") if m.ds in self.invalid: - raise CascadeInternalError( - f"unexpected transmit command {m} as the dataset was already purged" - ) + raise CascadeInternalError(f"unexpected transmit command {m} as the dataset was already purged") mark({ "dataset": repr(m.ds), "action": TransmitLifecycle.started, @@ -260,9 +252,7 @@ def recv_loop(self) -> None: self.futs_in_progress[m] = fut elif isinstance(m, DatasetPersistCommand): if m.ds in self.invalid: - raise CascadeInternalError( - description=f"unexpected persist command {m} as the dataset was already purged" - ) + raise CascadeInternalError(description=f"unexpected persist command {m} as the dataset was already purged") # TODO mark? fut = self.ds_proc_tp.submit(self._persist_dataset, m) self.futs_in_progress[m] = fut @@ -289,9 +279,7 @@ def recv_loop(self) -> None: # TODO submit this as a future? This actively blocks the whole server to_wait = [] for commandProg, fut in self.futs_in_progress.items(): - if isinstance( - commandProg, DatasetTransmitCommand | DatasetPersistCommand | DatasetRetrieveCommand - ): + if isinstance(commandProg, DatasetTransmitCommand | DatasetPersistCommand | DatasetRetrieveCommand): val = commandProg.ds elif isinstance(commandProg, DatasetTransmitPayload): val = commandProg.header.ds diff --git a/src/cascade/executor/executor.py b/src/cascade/executor/executor.py index 5a108fb4..ef169a3c 100644 --- a/src/cascade/executor/executor.py +++ b/src/cascade/executor/executor.py @@ -66,9 +66,7 @@ heartbeat_grace_ms = 2 * comms_default_timeout_ms # messages from the data server which need to go to controller, but have no additional logic here -JustForwardToController = ( - DatasetTransmitFailure | DatasetPersistSuccess | DatasetPersistFailure | DatasetRetrieveFailure -) +JustForwardToController = DatasetTransmitFailure | DatasetPersistSuccess | DatasetPersistFailure | DatasetRetrieveFailure def address_of(port: int) -> BackboneAddress: @@ -257,23 +255,16 @@ def healthcheck(self) -> None: raise CascadeInternalError(f"process on {k} is not alive") elif procFail(e.process.exitcode): # we assume low memory setting or callable issue -> UserError - raise CascadeUserError( - f"process on {k} failed to terminate correctly: {e.process.pid} -> {e.process.exitcode}" - ) + raise CascadeUserError(f"process on {k} failed to terminate correctly: {e.process.pid} -> {e.process.exitcode}") if procFail(self.shm_process.exitcode): # possibly low memory setting but this is system config -> InfrastructureError - raise CascadeInfrastructureError( - f"shm server {self.shm_process.pid} failed with {self.shm_process.exitcode}" - ) + raise CascadeInfrastructureError(f"shm server {self.shm_process.pid} failed with {self.shm_process.exitcode}") if procFail(self.data_server.exitcode): # unknown issue, it failed to report its own -> InfrastructureError - raise CascadeInfrastructureError( - f"data server {self.data_server.pid} failed with {self.data_server.exitcode}" - ) + raise CascadeInfrastructureError(f"data server {self.data_server.pid} failed with {self.data_server.exitcode}") if self.heartbeat_watcher.is_breach() > 0: logger.debug( - f"grace elapsed without message by {self.heartbeat_watcher.elapsed_ms()}" - f" -> sending explicit heartbeat at {self.host}" + f"grace elapsed without message by {self.heartbeat_watcher.elapsed_ms()} -> sending explicit heartbeat at {self.host}" ) # NOTE we send registration in place of heartbeat -- it makes the startup more reliable, # and the registration's size overhead is negligible diff --git a/src/cascade/executor/runner/entrypoint.py b/src/cascade/executor/runner/entrypoint.py index 6cce7914..168fcfa4 100644 --- a/src/cascade/executor/runner/entrypoint.py +++ b/src/cascade/executor/runner/entrypoint.py @@ -72,9 +72,7 @@ def project(self, taskSequence: TaskSequence) -> ExecutionContext: ) -def task_sequence_postmortem( - ctx: RunnerContext, taskSequence: TaskSequence, cut: TaskId -) -> list[tuple[DatasetId, str]]: +def task_sequence_postmortem(ctx: RunnerContext, taskSequence: TaskSequence, cut: TaskId) -> list[tuple[DatasetId, str]]: """Assuming a failure at task Cut, identify which datasets from the beginning of the sequence should be additionaly published. Returns datasetid + its type. """ @@ -232,12 +230,8 @@ def entrypoint(runnerContextClpkl: bytes): elif isinstance(mDes, TaskSequence): if waiting_ts is not None: raise CascadeInternalError(f"double task sequence enqueued: 1/ {waiting_ts}, 2/ {mDes}") - required = { - dataset_id for task in mDes.tasks for dataset_id in runnerContext.param_source[task].values() - } - { - DatasetId(task, key) - for task in mDes.tasks - for key, _ in runnerContext.job.tasks[task].definition.output_schema + required = {dataset_id for task in mDes.tasks for dataset_id in runnerContext.param_source[task].values()} - { + DatasetId(task, key) for task in mDes.tasks for key, _ in runnerContext.job.tasks[task].definition.output_schema } missing_ds = required - availab_ds if Config.pretask_flush: diff --git a/src/cascade/executor/runner/memory.py b/src/cascade/executor/runner/memory.py index cccd0769..10cafba2 100644 --- a/src/cascade/executor/runner/memory.py +++ b/src/cascade/executor/runner/memory.py @@ -64,9 +64,7 @@ def additional_publish_local(self, outputIds: Iterable[tuple[DatasetId, str]]): def handle(self, outputId: DatasetId, outputSchema: str, outputValue: Any, isPublish: bool) -> None: if outputId == NO_OUTPUT_PLACEHOLDER: if outputValue is not None: - logger.warning( - f"gotten output of type {type(outputValue)} where none was expected, updating annotation" - ) + logger.warning(f"gotten output of type {type(outputValue)} where none was expected, updating annotation") outputSchema = "Any" else: outputValue = "ok" @@ -115,9 +113,7 @@ def flush(self, datasets: set[DatasetId] = set()) -> None: # after every taskSequence. In principle, we could purge some locals earlier, and ideally scheduler # would invoke some targeted purges to also remove some published ones earlier (eg, they are still # needed somewhere but not here) - purgeable = [ - inputId for inputId in self.local if inputId not in self.bufs and (not datasets or inputId in datasets) - ] + purgeable = [inputId for inputId in self.local if inputId not in self.bufs and (not datasets or inputId in datasets)] logger.debug(f"will flush {len(purgeable)} datasets") for inputId in purgeable: self.local.pop(inputId) diff --git a/src/cascade/executor/runner/packages.py b/src/cascade/executor/runner/packages.py index 8ca9b5c5..84aa1bc1 100644 --- a/src/cascade/executor/runner/packages.py +++ b/src/cascade/executor/runner/packages.py @@ -56,10 +56,7 @@ def run_command(command: list[str]) -> tuple[str, str]: # either badly deployed or code bug of calling bad command -> InternalError raise CascadeInternalError(f"command failure: {ex}", parent=ex) from ex if result.returncode != 0: - msg = ( - f"command failed with {result.returncode}. Stderr: {result.stderr}," - f" Stdout: {result.stdout}, Args: {result.args}" - ) + msg = f"command failed with {result.returncode}. Stderr: {result.stderr}, Stdout: {result.stdout}, Args: {result.args}" logger.error(msg) if "was not found in the package registry" in result.stderr: @@ -144,9 +141,7 @@ def _maybe_module_version(mod_name: str) -> Version | None: try: return Version(mod.__version__) except Exception as e: - logger.warning( - f"failed to parse module {mod_name} version {mod.__version__} due to {repr(e)}-- ignoring!" - ) + logger.warning(f"failed to parse module {mod_name} version {mod.__version__} due to {repr(e)}-- ignoring!") else: logging.warning(f"Module '{mod_name}' is loaded, but has no __version__ attribute -- ignoring") diff --git a/src/cascade/gateway/router.py b/src/cascade/gateway/router.py index 203b23a7..671f89a9 100644 --- a/src/cascade/gateway/router.py +++ b/src/cascade/gateway/router.py @@ -91,9 +91,7 @@ def enqueue_job(self, job_spec: JobSpec) -> JobId: self.maybe_spawn() return job_id - def progress_of( - self, job_ids: Iterable[JobId] - ) -> tuple[dict[JobId, JobProgress], dict[JobId, list[DatasetId]], int]: + def progress_of(self, job_ids: Iterable[JobId]) -> tuple[dict[JobId, JobProgress], dict[JobId, list[DatasetId]], int]: if not job_ids: job_ids = set(self.jobs.keys()).union(self.jobs_queue.keys()) progresses = {} diff --git a/src/cascade/gateway/spawning.py b/src/cascade/gateway/spawning.py index ff6fed4e..41e99fc2 100644 --- a/src/cascade/gateway/spawning.py +++ b/src/cascade/gateway/spawning.py @@ -30,9 +30,7 @@ local_job_port = 12345 -def _spawn_troika_singlehost( - job_spec: JobSpec, addr: str, job_id: JobId, troika: TroikaSpec, troika_config: str -) -> subprocess.Popen: +def _spawn_troika_singlehost(job_spec: JobSpec, addr: str, job_id: JobId, troika: TroikaSpec, troika_config: str) -> subprocess.Popen: script = "#!/bin/bash\n" script += f"source {troika.venv}\n" for k, v in job_spec.envvars.items(): diff --git a/src/cascade/low/builders.py b/src/cascade/low/builders.py index 0a2c8e39..a3b8d152 100644 --- a/src/cascade/low/builders.py +++ b/src/cascade/low/builders.py @@ -51,8 +51,7 @@ def type2str(t: str | Type) -> str: static_input_kw = { p.name: p.default for p in sig.parameters.values() - if p.kind in {inspect.Parameter.KEYWORD_ONLY, inspect.Parameter.POSITIONAL_OR_KEYWORD} - and p.default != inspect.Parameter.empty + if p.kind in {inspect.Parameter.KEYWORD_ONLY, inspect.Parameter.POSITIONAL_OR_KEYWORD} and p.default != inspect.Parameter.empty } definition = TaskDefinition( diff --git a/src/cascade/low/core.py b/src/cascade/low/core.py index a731cee8..53a8d080 100644 --- a/src/cascade/low/core.py +++ b/src/cascade/low/core.py @@ -41,13 +41,9 @@ class TaskDefinition(BaseModel): None, description="a cloud-pickled callable. Prefered over `entrypoint` if given", ) - environment: list[str] = Field( - description="pip-installable packages, as required by entrypoint/func. Version pins supported" - ) + environment: list[str] = Field(description="pip-installable packages, as required by entrypoint/func. Version pins supported") # NOTE we could accept eg has_kwargs, has_args, etc... or serialize the whole inspect.signature here? - input_schema: dict[str, str] = Field( - description="kv of input kw params and their types (fqn of class). Non-kw params not validated" - ) + input_schema: dict[str, str] = Field(description="kv of input kw params and their types (fqn of class). Non-kw params not validated") output_schema: list[tuple[str, str]] = Field( description="kv of outputs and their types (fqn of class). Assumes listing in func output order" ) @@ -103,12 +99,8 @@ class JobDefinition(BaseModel): # Instances class TaskInstance(BaseModel): definition: TaskDefinition - static_input_kw: dict[str, Any] = Field( - description="input parameters for the entrypoint. Must be json/msgpack-serializable" - ) - static_input_ps: dict[str, Any] = Field( - description="input parameters for the entrypoint. Must be json/msgpack-serializable" - ) + static_input_kw: dict[str, Any] = Field(description="input parameters for the entrypoint. Must be json/msgpack-serializable") + static_input_ps: dict[str, Any] = Field(description="input parameters for the entrypoint. Must be json/msgpack-serializable") # Type can't be json serialized directly -- use these two functions with `serdes` on JobInstance @@ -131,8 +123,7 @@ class JobInstance(BaseModel): edges: list[Task2TaskEdge] serdes: dict[str, tuple[str, str]] = Field( default_factory=lambda: {}, - description="for each Type with custom serde, add entry here." - " The string is fully qualified name of the ser/des functions", + description="for each Type with custom serde, add entry here. The string is fully qualified name of the ser/des functions", ) ext_outputs: list[DatasetId] = Field( default_factory=lambda: [], @@ -196,9 +187,7 @@ class TaskExecutionRecord(BaseModel): class JobExecutionRecord(BaseModel): tasks: dict[TaskId, TaskExecutionRecord] = Field(default_factory=lambda: defaultdict(lambda: no_record_ts)) - datasets_mb: dict[DatasetId, int] = Field( - default_factory=lambda: defaultdict(lambda: no_record_ds) - ) # keyed by (task, output) + datasets_mb: dict[DatasetId, int] = Field(default_factory=lambda: defaultdict(lambda: no_record_ds)) # keyed by (task, output) # TODO extend this with some approximation/default from TaskInstance only diff --git a/src/cascade/main.py b/src/cascade/main.py index b7e23e41..71bd196b 100644 --- a/src/cascade/main.py +++ b/src/cascade/main.py @@ -45,10 +45,7 @@ def _get_cuda_count() -> int: return visible_count gpus = sum( 1 - for l in subprocess - .run(["nvidia-smi", "--list-gpus"], check=True, capture_output=True) - .stdout.decode("ascii") - .split("\n") + for l in subprocess.run(["nvidia-smi", "--list-gpus"], check=True, capture_output=True).stdout.decode("ascii").split("\n") if "GPU" in l ) except: diff --git a/src/cascade/scheduler/api.py b/src/cascade/scheduler/api.py index 87abf46e..b030985f 100644 --- a/src/cascade/scheduler/api.py +++ b/src/cascade/scheduler/api.py @@ -37,9 +37,7 @@ def gang_check_ready(task: TaskId, gang_prep: GangPreparation): """ for gang in gang_prep.lookup[task]: if gang not in gang_prep.countdown: - raise CascadeInternalError( - description=f"after {task=} marked computable, {gang=} not found -- double computable mark?" - ) + raise CascadeInternalError(description=f"after {task=} marked computable, {gang=} not found -- double computable mark?") remaining = gang_prep.countdown[gang] if task not in remaining: raise CascadeInternalError( @@ -134,11 +132,7 @@ def assign(schedule: Schedule, context: JobExecutionContext) -> Iterator[Assignm return # step II: assign remaining workers to new components - components = [ - (component.weight, component_id) - for component_id, component in enumerate(schedule.components) - if component.weight > 0 - ] + components = [(component.weight, component_id) for component_id, component in enumerate(schedule.components) if component.weight > 0] if not components: return diff --git a/src/cascade/scheduler/assign.py b/src/cascade/scheduler/assign.py index 90146f0b..fdcec841 100644 --- a/src/cascade/scheduler/assign.py +++ b/src/cascade/scheduler/assign.py @@ -57,11 +57,7 @@ def build_assignment(worker: WorkerId, task: TaskId, context: JobExecutionContex else: # TODO instead of any, pick the best host -- business, distance, etc # Note also that one of the hosts may be the VirtualCheckpointHost - if any( - candidate := host - for host, status in context.ds2host[dataset].items() - if status in eligible_transmit - ): + if any(candidate := host for host, status in context.ds2host[dataset].items() if status in eligible_transmit): prep.append((dataset, candidate)) # ty: ignore[unresolved-reference] # candidate walrus context.dataset_preparing(dataset, worker) else: @@ -88,9 +84,7 @@ def build_assignment(worker: WorkerId, task: TaskId, context: JobExecutionContex # trim for only the necessary ones: 1/ having any edge outside of this assignment 2/ global output 3/ persistable all_outputs = {ds for task in assigned for ds in context.task_o[task]} assigned_tasks = set(assigned) - trimmed_outputs = { - ds for ds in all_outputs if (context.edge_o[ds] - assigned_tasks) or context.publication_mandatory(ds) - } + trimmed_outputs = {ds for ds in all_outputs if (context.edge_o[ds] - assigned_tasks) or context.publication_mandatory(ds)} return Assignment( worker=worker, @@ -170,9 +164,7 @@ def _try_assign_gang( coordinator = None # similarly to _assignment_heuristic, a greedy algorithm - candidates = [ - (schedule.worker2task_overhead[w][t], component.core.value[t], w, t) for w in gpu_workers for t in gpu_tasks - ] + candidates = [(schedule.worker2task_overhead[w][t], component.core.value[t], w, t) for w in gpu_workers for t in gpu_tasks] candidates.sort(key=lambda e: (e[0], e[1])) for _, _, worker, task in candidates: if task in gpu_tasks and worker in gpu_workers: @@ -197,9 +189,7 @@ def _try_assign_gang( raise CascadeInternalError(description=f"expected to assign all gang gpu tasks, yet {gpu_tasks} remain") all_workers = cpu_workers.union(gpu_workers) - candidates = [ - (schedule.worker2task_overhead[w][t], component.core.value[t], w, t) for w in all_workers for t in cpu_tasks - ] + candidates = [(schedule.worker2task_overhead[w][t], component.core.value[t], w, t) for w in all_workers for t in cpu_tasks] candidates.sort(key=lambda e: (e[0], e[1])) for _, _, worker, task in candidates: if task in cpu_tasks and worker in all_workers: @@ -264,9 +254,7 @@ def _assignment_heuristic( # second, sort task-worker combination by first overhead, second value, and pick greedily remaining_t = set(unassigned) remaining_w = set(workers) - candidates = [ - (schedule.worker2task_overhead[w][t], component.core.value[t], w, t) for w in workers for t in remaining_t - ] + candidates = [(schedule.worker2task_overhead[w][t], component.core.value[t], w, t) for w in workers for t in remaining_t] candidates.sort(key=lambda e: (e[0], e[1])) for _, _, worker, task in candidates: if task in remaining_t and worker in remaining_w: @@ -328,9 +316,7 @@ def assign_within_component( cpu_t.append(task) # tasks immediately needing a gpu - eligible_w = [ - worker for worker in workers if context.environment.workers[worker].gpu > 0 and worker in context.idle_workers - ] + eligible_w = [worker for worker in workers if context.environment.workers[worker].gpu > 0 and worker in context.idle_workers] logger.debug( f"considering {len(gpu_t)}# gpu tasks, {len(opu_t)}# maybe-gpu tasks, {len(cpu_t)}# cpu tasks," f" with {len(workers)}# workers out of which {len(eligible_w)} have gpu" diff --git a/src/cascade/scheduler/checkpoints.py b/src/cascade/scheduler/checkpoints.py index d876ac34..9df58642 100644 --- a/src/cascade/scheduler/checkpoints.py +++ b/src/cascade/scheduler/checkpoints.py @@ -81,9 +81,7 @@ def _discover_component( return is_valid -def _trim_component( - component: ComponentCore, parents: dict[TaskId, set[TaskId]], preserved_tasks: set[TaskId] -) -> ComponentCore: +def _trim_component(component: ComponentCore, parents: dict[TaskId, set[TaskId]], preserved_tasks: set[TaskId]) -> ComponentCore: """Restricts the component only to preserved tasks.""" nodes = list(preserved_tasks) value = {node: component.value[node] for node in nodes} @@ -142,11 +140,7 @@ def trim_with_persisted( job_mod = JobInstance( tasks={taskId: taskInstance for taskId, taskInstance in job.tasks.items() if taskId in preserved_tasks_all}, - edges=[ - edge - for edge in job.edges - if edge.source.task in preserved_tasks_all and edge.sink_task in preserved_tasks_all - ], + edges=[edge for edge in job.edges if edge.source.task in preserved_tasks_all and edge.sink_task in preserved_tasks_all], serdes=job.serdes, ext_outputs=[dataset for dataset in job.ext_outputs if dataset.task in preserved_tasks_all], constraints=[constraint for constraint in job.constraints if set(constraint) <= preserved_tasks_all], diff --git a/src/cascade/scheduler/core.py b/src/cascade/scheduler/core.py index 2c26764d..106d8814 100644 --- a/src/cascade/scheduler/core.py +++ b/src/cascade/scheduler/core.py @@ -23,9 +23,7 @@ class ComponentCore: value: TaskValue # closer to a sink -> higher value depth: int # maximum value fusing_opportunities: dict[TaskId, list[TaskId]] - gpu_fused_distance: dict[ - TaskId, int | None - ] # closer to a gpu task -> lower value. Using fusing_opportunities paths only + gpu_fused_distance: dict[TaskId, int | None] # closer to a gpu task -> lower value. Using fusing_opportunities paths only def weight(self) -> int: # TODO eventually replace with runtime sum or smth @@ -47,9 +45,7 @@ class Preschedule: @dataclass class GangPreparation: ready: list[frozenset[TaskId]] # used by scheduler to see if any gangs can be assigned/started - countdown: dict[ - frozenset[TaskId], set[TaskId] - ] # used to check after a task completion whether a gang can be moved to ready + countdown: dict[frozenset[TaskId], set[TaskId]] # used to check after a task completion whether a gang can be moved to ready lookup: dict[TaskId, list[frozenset[TaskId]]] # used to decrease countdown after a task completion diff --git a/src/cascade/scheduler/precompute.py b/src/cascade/scheduler/precompute.py index bc695c32..721cd14a 100644 --- a/src/cascade/scheduler/precompute.py +++ b/src/cascade/scheduler/precompute.py @@ -222,9 +222,7 @@ def precompute(job_instance: JobInstance) -> Preschedule: with ThreadPoolExecutor(max_workers=4) as tp: # TODO if coptrs is not used, then this doesnt make sense - f = lambda plain_component: timer(_enrich, Microtrace.presched_enrich)( - plain_component, edge_i_proj, edge_o_proj, needs_gpu, gangs - ) + f = lambda plain_component: timer(_enrich, Microtrace.presched_enrich)(plain_component, edge_i_proj, edge_o_proj, needs_gpu, gangs) plain_components = ( plain_component for plain_component in timer(_decompose, Microtrace.presched_decompose)( diff --git a/src/cascade/shm/api.py b/src/cascade/shm/api.py index a4b765d4..7271139e 100644 --- a/src/cascade/shm/api.py +++ b/src/cascade/shm/api.py @@ -110,13 +110,7 @@ class GetResponse: deser_fun: str def ser(self) -> bytes: - return ( - self.l.to_bytes(4, "big") - + ser_str(self.deser_fun) - + ser_str(self.shmid) - + ser_str(self.rdid) - + ser_str(self.error) - ) + return self.l.to_bytes(4, "big") + ser_str(self.deser_fun) + ser_str(self.shmid) + ser_str(self.rdid) + ser_str(self.error) @classmethod def deser(cls, data: memoryview) -> Self: diff --git a/src/earthkit/workflows/fluent.py b/src/earthkit/workflows/fluent.py index bc92132f..ec87b2d0 100644 --- a/src/earthkit/workflows/fluent.py +++ b/src/earthkit/workflows/fluent.py @@ -148,9 +148,7 @@ def __init__( if name is None: name = payload.name() - name += ":" + custom_hash( - f"{payload}{[x.name if isinstance(x, BaseNode) else f'{x.parent.name}.{x.name}' for x in inputs]}" - ) + name += ":" + custom_hash(f"{payload}{[x.name if isinstance(x, BaseNode) else f'{x.parent.name}.{x.name}' for x in inputs]}") super().__init__( name, @@ -444,8 +442,7 @@ def map( if not isinstance(payload, PayloadFunc | Payload): # type: ignore payload = np.asarray(payload) assert payload.shape == narray.shape, ( - f"For unique payloads for each node, payload shape {payload.shape}" - f"must match node array shape {narray.shape}" + f"For unique payloads for each node, payload shape {payload.shape}must match node array shape {narray.shape}" ) # Applies operation to every node, keeping node array structure @@ -518,9 +515,7 @@ def reduce( raise ValueError("Can not batch the execution of a generator") if batch_size > 1 and batch_size < nodetree_array(batched.nodes).sizes[dim]: if not getattr(payload.func, "batchable", False): - raise ValueError( - f"Function {payload.func.name()} is not batchable, but batch_size {batch_size} is specified" - ) + raise ValueError(f"Function {payload.func.name()} is not batchable, but batch_size {batch_size} is specified") while batch_size < nodetree_array(batched.nodes).sizes[dim]: lst = nodetree_array(batched.nodes).coords[dim].data diff --git a/src/earthkit/workflows/graph/export.py b/src/earthkit/workflows/graph/export.py index 9c83f804..3af841c6 100644 --- a/src/earthkit/workflows/graph/export.py +++ b/src/earthkit/workflows/graph/export.py @@ -65,10 +65,7 @@ def deserialise(data: dict, node_factory: NodeFactory = default_node_factory) -> given name, outputs, payload and inputs. The default factory will create bare `Node` objects """ - deps = { - name: [inp if isinstance(inp, str) else inp[0] for inp in node.get("inputs", {}).values()] - for name, node in data.items() - } + deps = {name: [inp if isinstance(inp, str) else inp[0] for inp in node.get("inputs", {}).values()] for name, node in data.items()} ts = graphlib.TopologicalSorter(deps) nodes: dict[str, Any] = {} diff --git a/src/earthkit/workflows/graph/graph.py b/src/earthkit/workflows/graph/graph.py index d8b5841a..7b6365ab 100644 --- a/src/earthkit/workflows/graph/graph.py +++ b/src/earthkit/workflows/graph/graph.py @@ -134,8 +134,7 @@ def get_predecessors(self, node: Node) -> dict[str, Node | tuple[Node, str]]: output), or (parent, output name) tuples. """ return { - iname: (isrc.parent if isrc.name == Node.DEFAULT_OUTPUT else (isrc.parent, isrc.name)) - for iname, isrc in node.inputs.items() + iname: (isrc.parent if isrc.name == Node.DEFAULT_OUTPUT else (isrc.parent, isrc.name)) for iname, isrc in node.inputs.items() } def get_successors(self, node: Node) -> dict[str, list[tuple[Node, str]]]: diff --git a/src/earthkit/workflows/graph/networkx.py b/src/earthkit/workflows/graph/networkx.py index bdca34e9..5721a2c3 100644 --- a/src/earthkit/workflows/graph/networkx.py +++ b/src/earthkit/workflows/graph/networkx.py @@ -26,10 +26,7 @@ def to_networkx(graph: Graph, serialise=False) -> nx.MultiDiGraph: for node in graph.nodes(): node_s = node.serialise() if serialise else node g.add_node(node.name, node=node_s) - g.add_edges_from( - (isrc.parent.name, node.name, {"source_out": isrc.name, "dest_in": iname}) - for iname, isrc in node.inputs.items() - ) + g.add_edges_from((isrc.parent.name, node.name, {"source_out": isrc.name, "dest_in": iname}) for iname, isrc in node.inputs.items()) return g @@ -55,7 +52,6 @@ def draw_graph( g, pos, edge_labels={ - e: (a["source_out"] if a["source_out"] != Node.DEFAULT_OUTPUT else "") + "->" + a["dest_in"] - for e, a in g.edges.items() + e: (a["source_out"] if a["source_out"] != Node.DEFAULT_OUTPUT else "") + "->" + a["dest_in"] for e, a in g.edges.items() }, ) diff --git a/src/earthkit/workflows/graph/samplegraphs.py b/src/earthkit/workflows/graph/samplegraphs.py index 090555e7..cc05e0c9 100644 --- a/src/earthkit/workflows/graph/samplegraphs.py +++ b/src/earthkit/workflows/graph/samplegraphs.py @@ -92,10 +92,7 @@ def multi(nread: int = 5, nout1: int = 3, nout2: int = 2) -> Graph: input2=rs[min(2, nread - 1)], ) _ws = ((inp, out) for out in range(nout2) for inp in p1s) - ws: list[Node] = [ - Node(f"writer-{j}", outputs=[], input1=inp, input2=p2.get_output(f"output{out}")) - for j, (inp, out) in enumerate(_ws) - ] + ws: list[Node] = [Node(f"writer-{j}", outputs=[], input1=inp, input2=p2.get_output(f"output{out}")) for j, (inp, out) in enumerate(_ws)] return Graph(ws) diff --git a/src/earthkit/workflows/graph/split.py b/src/earthkit/workflows/graph/split.py index 67da3e23..f6613e51 100644 --- a/src/earthkit/workflows/graph/split.py +++ b/src/earthkit/workflows/graph/split.py @@ -103,9 +103,7 @@ def cut_edge(self, cut: CutEdge[K], sink_in: Output) -> tuple[Node, Node]: SplitterType = Callable[[KeyFunc[K]], Splitter[K]] -def split_graph( - key: KeyFunc[K], graph: Graph, splitter: SplitterType[K] = Splitter -) -> tuple[dict[K, Graph], list[CutEdge[K]]]: +def split_graph(key: KeyFunc[K], graph: Graph, splitter: SplitterType[K] = Splitter) -> tuple[dict[K, Graph], list[CutEdge[K]]]: """Split a graph according to some key. Each sub-graph in the split will consist of nodes with the same key. The key diff --git a/tests/cascade/controller/test_run.py b/tests/cascade/controller/test_run.py index a3d7c651..eb9ca433 100644 --- a/tests/cascade/controller/test_run.py +++ b/tests/cascade/controller/test_run.py @@ -101,14 +101,7 @@ def test_simple(): # 2-node graph task1 = TaskBuilder.from_callable(_payload).with_values(a=1, b=2) task2 = TaskBuilder.from_callable(_payload).with_values(a=1) - job = ( - JobBuilder() - .with_node("task1", task1) - .with_node("task2", task2) - .with_edge("task1", "task2", "b") - .build() - .get_or_raise() - ) + job = JobBuilder().with_node("task1", task1).with_node("task2", task2).with_edge("task1", "task2", "b").build().get_or_raise() run_cluster(JobInstanceRich(jobInstance=job, checkpointSpec=None), 12000, 1) sleep(1) # improves stability @@ -236,10 +229,7 @@ def test_checkpoints(): in a way that recognizes whether it checkpointed or not. """ with tempfile.TemporaryDirectory() as tmp_root, tempfile.TemporaryDirectory() as ckpt_root: - sourcetask_code = ( - f"import pathlib; f = pathlib.Path('{tmp_root}') / 'file.txt';" - " f.write_text('ok') if not f.exists() else 1/0;" - ) + sourcetask_code = f"import pathlib; f = pathlib.Path('{tmp_root}') / 'file.txt'; f.write_text('ok') if not f.exists() else 1/0;" jobInstance = ( ( JobBuilder() diff --git a/tests/cascade/executor/test_executor.py b/tests/cascade/executor/test_executor.py index 7e420ef2..46733c11 100644 --- a/tests/cascade/executor/test_executor.py +++ b/tests/cascade/executor/test_executor.py @@ -154,11 +154,7 @@ def test_func(x: np.ndarray) -> np.ndarray: ), ) ms = l.recv_messages() - assert ( - len(ms) == 1 - and isinstance(ms[0], DatasetTransmitPayload) - and ms[0].header.ds == DatasetId(task="sink", output="o") - ) + assert len(ms) == 1 and isinstance(ms[0], DatasetTransmitPayload) and ms[0].header.ds == DatasetId(task="sink", output="o") assert serde.des_output(ms[0].value, "int", ms[0].header.deser_fun)[0] == 3.0 # purge, store, run partial and fetch again diff --git a/tests/cascade/executor/test_packages.py b/tests/cascade/executor/test_packages.py index f77513ba..660e29b6 100644 --- a/tests/cascade/executor/test_packages.py +++ b/tests/cascade/executor/test_packages.py @@ -25,8 +25,7 @@ def test_run_command() -> None: with pytest.raises( CascadeInternalError, match=re.escape( - "command failure: [Errno 2] No such file or directory: 'you'" - " (caused by FileNotFoundError(2, 'No such file or directory'))" + "command failure: [Errno 2] No such file or directory: 'you' (caused by FileNotFoundError(2, 'No such file or directory'))" ), ): run_command(bad1_command) @@ -84,11 +83,7 @@ def test_postinstall_verify() -> None: "Uninstalled 1 package in 12ms\nInstalled 1 package in 18ms\n - numpy==2.4.2\n + numpy==1.0.0\n" ) issues = _postinstall_verify(baddie) - assert issues == [ - InstallIssue( - dist_name="numpy", desired_version=Version("1.0.0"), mod_issues=[("numpy", Version(numpy.__version__))] - ) - ] + assert issues == [InstallIssue(dist_name="numpy", desired_version=Version("1.0.0"), mod_issues=[("numpy", Version(numpy.__version__))])] def test_prefer_installed() -> None: diff --git a/tests/cascade/executor/util.py b/tests/cascade/executor/util.py index ccf9653e..154d8fd0 100644 --- a/tests/cascade/executor/util.py +++ b/tests/cascade/executor/util.py @@ -127,9 +127,7 @@ def run_test(callableInstance: CallableInstance, testId: str, max_runtime_sec: i end = perf_counter_ns() + max_runtime_sec * int(1e9) while perf_counter_ns() < end: mess = listener.recv_messages() - if mess == [ - DatasetPublished(origin=WorkerId(host="testHost", worker="testWorker"), ds=output, transmit_idx=None) - ]: + if mess == [DatasetPublished(origin=WorkerId(host="testHost", worker="testWorker"), ds=output, transmit_idx=None)]: break elif not mess: continue diff --git a/tests/cascade/low/test_builders.py b/tests/cascade/low/test_builders.py index db684a33..701e2c87 100644 --- a/tests/cascade/low/test_builders.py +++ b/tests/cascade/low/test_builders.py @@ -25,20 +25,11 @@ def test_func(x: int, y: str) -> int: _ = JobBuilder().with_node("task", task_good).build().get_or_raise() sink_bad = TaskBuilder.from_callable(test_func).with_values(x=1) - job = ( - JobBuilder().with_node("source", task_good).with_node("sink", sink_bad).with_edge("source", "sink", "y").build() - ) + job = JobBuilder().with_node("source", task_good).with_node("sink", sink_bad).with_edge("source", "sink", "y").build() expected = [ "edge connects two incompatible nodes: source=source.0 sink_task='sink' sink_input_kw='y' sink_input_ps=None", # noqa: E501 ] assert sorted(job.e) == sorted(expected) # ty: ignore[invalid-argument-type] sink_good = TaskBuilder.from_callable(test_func).with_values(y="yes") - _ = ( - JobBuilder() - .with_node("source", task_good) - .with_node("sink", sink_good) - .with_edge("source", "sink", "x") - .build() - .get_or_raise() - ) + _ = JobBuilder().with_node("source", task_good).with_node("sink", sink_good).with_edge("source", "sink", "x").build().get_or_raise() diff --git a/tests/cascade/scheduler/util.py b/tests/cascade/scheduler/util.py index 05a681d0..a06fbd29 100644 --- a/tests/cascade/scheduler/util.py +++ b/tests/cascade/scheduler/util.py @@ -149,10 +149,6 @@ def get_job1() -> tuple[JobInstanceRich, JobExecutionRecord]: # *** environment builders *** def get_env(hosts: int, workers_per_host: int) -> Environment: return Environment( - workers={ - WorkerId(f"h{h}", f"w{w}"): Worker(cpu=1, gpu=0, memory_mb=1000) - for h in range(hosts) - for w in range(workers_per_host) - }, + workers={WorkerId(f"h{h}", f"w{w}"): Worker(cpu=1, gpu=0, memory_mb=1000) for h in range(hosts) for w in range(workers_per_host)}, host_url_base={f"h{h}": "tcp://localhost" for h in range(hosts)}, ) diff --git a/tests/earthkit_workflows/backends/generic_tests.py b/tests/earthkit_workflows/backends/generic_tests.py index 1626059b..5194c293 100644 --- a/tests/earthkit_workflows/backends/generic_tests.py +++ b/tests/earthkit_workflows/backends/generic_tests.py @@ -27,10 +27,7 @@ def shape(self, array): ) def test_multi_arg(self, num_inputs, input_shape, kwargs, output_shape): for func in ["mean", "std", "max", "min", "sum", "prod", "var"]: - assert ( - self.shape(getattr(backends, func)(*self.input_generator(num_inputs, input_shape), **kwargs)) - == output_shape - ) + assert self.shape(getattr(backends, func)(*self.input_generator(num_inputs, input_shape), **kwargs)) == output_shape @pytest.mark.parametrize( ["num_inputs", "input_shape", "output_shape"], diff --git a/tests/earthkit_workflows/backends/test_arrayapi.py b/tests/earthkit_workflows/backends/test_arrayapi.py index 7f83885f..31d666c6 100644 --- a/tests/earthkit_workflows/backends/test_arrayapi.py +++ b/tests/earthkit_workflows/backends/test_arrayapi.py @@ -29,9 +29,7 @@ def shape(self, array): ) def test_multi_arg_axis(self, num_inputs, input_shape, kwargs, output_shape): for func in ["mean", "std", "max", "min", "sum", "prod", "var"]: - assert ( - getattr(backends, func)(*self.input_generator(num_inputs, input_shape), **kwargs).shape == output_shape - ) + assert getattr(backends, func)(*self.input_generator(num_inputs, input_shape), **kwargs).shape == output_shape @pytest.mark.parametrize( ["num_inputs", "input_shape", "output_shape"], diff --git a/tests/earthkit_workflows/graph/test_visit.py b/tests/earthkit_workflows/graph/test_visit.py index c70f2fa0..752c09f3 100644 --- a/tests/earthkit_workflows/graph/test_visit.py +++ b/tests/earthkit_workflows/graph/test_visit.py @@ -55,27 +55,21 @@ def test_visit_disc(): g = disconnected(5) names = gnames(g) assert len(names) == 5 + 5 + 5 - assert set(names) == set( - [f"reader-{i}" for i in range(5)] + [f"process-{i}" for i in range(5)] + [f"writer-{i}" for i in range(5)] - ) + assert set(names) == set([f"reader-{i}" for i in range(5)] + [f"process-{i}" for i in range(5)] + [f"writer-{i}" for i in range(5)]) def test_visit_simple(): g = simple(5, 3) names = gnames(g) assert len(names) == 5 + 3 + 3 - assert set(names) == set( - [f"reader-{i}" for i in range(5)] + [f"process-{i}" for i in range(3)] + [f"writer-{i}" for i in range(3)] - ) + assert set(names) == set([f"reader-{i}" for i in range(5)] + [f"process-{i}" for i in range(3)] + [f"writer-{i}" for i in range(3)]) def test_visit_multi(): g = multi(5, 3, 2) names = gnames(g) assert len(names) == 5 + 3 + 2 * (3 - 2) - assert set(names) == set( - [f"reader-{i}" for i in range(5)] + [f"process-{i}" for i in range(3)] + [f"writer-{i}" for i in range(2)] - ) + assert set(names) == set([f"reader-{i}" for i in range(5)] + [f"process-{i}" for i in range(3)] + [f"writer-{i}" for i in range(2)]) class SourceLister(Visitor): diff --git a/tests/earthkit_workflows/test_fluent.py b/tests/earthkit_workflows/test_fluent.py index 463be811..7f7a7874 100644 --- a/tests/earthkit_workflows/test_fluent.py +++ b/tests/earthkit_workflows/test_fluent.py @@ -123,9 +123,7 @@ def test_broadcast(): it = np.nditer(out_array, flags=["multi_index", "refs_ok"]) for _ in it: print(it.multi_index) - assert out_array[it.multi_index].item(0).inputs["input0"].parent == nodetree_array(input_action.nodes)[ - it.multi_index[:2] - ].item(0) + assert out_array[it.multi_index].item(0).inputs["input0"].parent == nodetree_array(input_action.nodes)[it.multi_index[:2]].item(0) def test_flatten_expand():