diff --git a/.env_template b/.env_template index 8fbace5..5700fd2 100644 --- a/.env_template +++ b/.env_template @@ -14,7 +14,7 @@ OPENAI_BASE_URL=your base url # Target agent configuration AGENT_URL=http://localhost:9000 -# RITS_* are consumed by the example agents under mcp_servers/*, not by Smith itself. +# RITS_* are consumed by the example agents under examples/*, not by Smith itself. # Option A: Ollama (local) RITS_MODEL="qwen3.5:latest" RITS_BASE_URL="http://localhost:11434/v1" @@ -26,11 +26,11 @@ OLLAMA_BASE_URL="http://localhost:11434" # RITS_MODEL=your rits model # RITS_BASE_URL=your rits base url # RITS_API_KEY=your rits api key -TARGET_AGENT_PATH=mcp_servers/your_mcp_server/ -GUIDANCE_FILE=mcp_servers/your_mcp_server/smith/guidance.txt -SYSTEM_VAR_FILE=mcp_servers/your_mcp_server/smith/system_vars.json -PROMPTFOO_CONFIG_FILE=mcp_servers/your_mcp_server/smith/promptfooconfig.yaml -PROMPTFOO_OUTPUT_FILE=mcp_servers/your_mcp_server/smith/redteam1.yaml +TARGET_AGENT_PATH=examples/your_mcp_server/ +GUIDANCE_FILE=examples/your_mcp_server/smith/guidance.txt +SYSTEM_VAR_FILE=examples/your_mcp_server/smith/system_vars.json +PROMPTFOO_CONFIG_FILE=examples/your_mcp_server/smith/promptfooconfig.yaml +PROMPTFOO_OUTPUT_FILE=examples/your_mcp_server/smith/redteam1.yaml ## MCP settings: for get_mcp_parameters when generating the policy MCP_TRANSPORT=sse @@ -40,27 +40,29 @@ MCP_URL=http://localhost:8000/sse # MCP_TRANSPORT=stdio # MCP_COMMAND=python # MCP_ARGS=server.py -# MCP_CWD=mcp_servers/call-for-papers-mcp +# MCP_CWD=examples/call-for-papers-mcp # example for nodejs MCP # MCP_TRANSPORT=stdio # MCP_COMMAND=node # MCP_ARGS=dist/index.js -# MCP_CWD=mcp_servers/context7-mcp +# MCP_CWD=examples/context7-mcp # Policy testing configuration BAD_COMMAND_PATH=references/test_cases/allow BENIGN_COMMAND_PATH=references/test_cases/disallow TEST_CASE_PATH=references/test_cases/ -TEST_PATH=tests/integration/ +# Where the policy_testing harness writes the scorecard + failure list +# (relative to BASE_URL). The harness itself ships inside the smith package. +TEST_OUTPUT_DIR=references/scorecard/ TEST_RESULT_PATH=scorecard_summary.txt TEST_FAILURES_PATH=score_test_failures.txt CROSS_VALIDATE_OUTPUT=references/cross_validate_report.json # Test case generation configuration TEST_CASE_TEMPLATE=references/test_case_template.json -TEST_GENERATION_PATH=scripts/test_generation/ +TEST_GENERATION_PATH=src/smith/test_generation/ DECOMP_FILE=references/decomp_file.json FLATTEN_FILE=references/decomp_flatten_file.json ATTACK_FILE_CSV=ares/assets/safety_behaviors_text_subset.csv diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8d44326..731bdfb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,14 +31,9 @@ jobs: timeout-minutes: 15 steps: - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 - with: - python-version: "3.11" - - name: Install ruff + black - # Pinned so CI matches the versions the codebase is formatted/linted - # against — an unpinned install pulls newer styles that flag files CI - # should pass. Bump these deliberately alongside a reformat commit. - run: python -m pip install ruff==0.15.20 black==26.5.1 + - uses: astral-sh/setup-uv@v5 + # `make lint` runs ruff/black via `uvx` with versions pinned in the + # Makefile (ruff 0.15.20 / black 26.5.1); bump those alongside a reformat. - name: make lint run: make lint @@ -79,14 +74,12 @@ jobs: timeout-minutes: 30 steps: - uses: actions/checkout@v4 + - uses: astral-sh/setup-uv@v5 - uses: actions/setup-python@v5 with: python-version: "3.11" - cache: pip - - name: Install Smith and dependencies - run: make install - - name: CLI smoke test - run: smith --help + - name: Install Smith (uv) and smoke-test the CLI + run: make build audit: name: Dependency audit (advisory) @@ -98,10 +91,6 @@ jobs: continue-on-error: true steps: - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 - with: - python-version: "3.11" + - uses: astral-sh/setup-uv@v5 - name: pip-audit - run: | - python -m pip install pip-audit - pip-audit -r requirements.txt + run: make audit diff --git a/.gitignore b/.gitignore index 383f6df..f142152 100644 --- a/.gitignore +++ b/.gitignore @@ -50,7 +50,7 @@ references/test_case_report.html assets/opa/outputs/ # ---- Generated: ARES red-teaming artifacts ---- -scripts/test_generation/ares/assets/*generate*.json +src/smith/test_generation/ares/assets/*generate*.json # ---- Generated: policy testing scorecard output ---- scripts/tests/integration/*.txt diff --git a/CHANGELOG.md b/CHANGELOG.md index 0023939..739922a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,26 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/). ## [Unreleased] +### Changed + +- Repackaged `scripts/` into an installable `smith` Python package using a `src/` + layout, with `pyproject.toml` at the repo root declaring runtime dependencies + (`[project.dependencies]`) and a `[dev]` extra. The CLI entry point is now + `smith = smith.cli:main`. +- Package management and the build/publish workflow now use [uv](https://docs.astral.sh/uv/) + (`make install`, `make package`, `make publish`). +- The OPA scorecard harness ships inside the package (`smith.policy_testing`) and + writes all generated outputs to a `BASE_URL`-relative dir (`references/scorecard/`, + via `TEST_OUTPUT_DIR`) instead of `scripts/tests/integration/`. +- Renamed `mcp_servers/` to `examples/`. + +### Removed + +- Legacy code unreachable from the CLI: a kubectl/mcpgateway/beeai cluster, duplicate + entry points, a dead `visualization/` package, and the previous (non-functional) + pytest suite. Also removed stray upstream ARES repository scaffolding; ARES is the + external `ares-redteamer` tool, located via `ARES_HOME`. + ## [0.1.0] - 2026-06-28 ### Added @@ -30,7 +50,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/). - **MCP tool extraction** over SSE and stdio transports (`get_mcp_parameter`) and tool-call translation (`test_case_translation`). - **Rego policy validation** with optional auto-fix (`policy_validation`, `policy_validation_fix`). - Runtime configuration driven entirely from `.env` (see `.env_template`); target-agent selection via `TARGET_AGENT_PATH`, `GUIDANCE_FILE`, `SYSTEM_VAR_FILE`, `MCP_*`, and `AGENT_URL`. -- Example target agents under `mcp_servers/`, each carrying its Smith inputs (`guidance.txt`, `tool_definitions.json`, `system_vars.json`). +- Example target agents under `examples/`, each carrying its Smith inputs (`guidance.txt`, `tool_definitions.json`, `system_vars.json`). [Unreleased]: https://github.com/IBM/smith/compare/0.1.0...HEAD [0.1.0]: https://github.com/IBM/smith/releases/tag/0.1.0 diff --git a/CLAUDE.md b/CLAUDE.md index a8bbf58..84957e5 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -9,26 +9,25 @@ Smith is an **agent skill** (plugin) that manages the full lifecycle of [OPA](ht Smith has two layers that must be understood together: 1. **The skill layer** — `SKILL.md` plus markdown guides under `opa_policy/` and `test_generation/`. These are *instructions the agent (you) follows*, not code. When a user asks to create, test, or improve a policy, the agent reads the relevant markdown guide and orchestrates the work, often by invoking the `smith` CLI. -2. **The CLI backend** — `scripts/cli.py` exposes a single `smith --flag ` command that runs the heavy Python pipelines (decomposition, attack generation, label validation, clustering, etc.). +2. **The CLI backend** — `src/smith/cli.py` exposes a single `smith --flag ` command that runs the heavy Python pipelines (decomposition, attack generation, label validation, clustering, etc.). So: high-level control flow lives in markdown guides; deterministic pipeline stages live behind CLI flags. ## Commands ```bash -# Setup (from repo root) -python -m venv .venv && source .venv/bin/activate -make install # pip install -r requirements.txt + editable scripts/ (installs the `smith` CLI) +# Setup (from repo root) — package management uses uv +make install # uv venv + uv pip install -e ".[dev]" (installs the `smith` CLI) cp .env_template .env # then fill in values (see Configuration below) # Dev workflow — the root Makefile mirrors CI (.github/workflows/ci.yml); `make ci` is the gate -make lint # ruff check + black --check (config in scripts/pyproject.toml) +make lint # ruff check + black --check (config in pyproject.toml) make format # ruff --fix + black (apply fixes) make lint-policy # Regal (falls back to OPA) lint of assets/policy.rego -make license-check # verify SPDX Apache-2.0 headers (scripts/tools/license_headers.py) +make license-check # verify SPDX Apache-2.0 headers (src/smith/tools/license_headers.py) make build # editable install + `smith --help` smoke test make ci # the gate: lint + lint-policy + license-check -make test # policy scorecard (delegates to scripts/Makefile; needs Docker + the OPA server) +make test # policy scorecard: starts OPA in Docker + runs the packaged harness # CLI pipeline stages (run from anywhere once installed; reads paths from .env) smith --flag get_mcp_parameter # auto-extract MCP tool defs -> /smith/tool_definitions.json @@ -44,28 +43,25 @@ smith --flag apply_cross_validate # apply approved label corrections from cros smith --flag policy_validation --policy_path # validate a rego file smith --flag policy_validation_fix --policy_path # validate and auto-fix -# Policy-testing harness (scripts/Makefile — what `smith --flag policy_testing` and root `make test` invoke) -cd scripts +# Policy-testing OPA server (root Makefile; the packaged harness in +# src/smith/policy_testing/ is what `smith --flag policy_testing` and `make test` invoke) make opaserver/start # start OPA server on :8181 with assets/policy.rego (lints first) -make test # run tests/integration/score_card.sh, output scorecard + failures -make test/verbose # per-test-case results -make lint/policy # OPA check on the rego policy -make lint/code # ruff + black over scripts tests visualization -make opaserver/stop +make opaserver/status # show whether the OPA container is running +make opaserver/stop # stop the OPA server ``` -`make test` requires the OPA server to be running and curls `localhost:8181/v1/data/mcp/policies/allow` for every JSON case under `references/test_cases/{allow,disallow}/`. A case in `disallow/` is expected to return `allow: false`; `allow/` expects `true`. Results land in `scripts/tests/integration/{scorecard_summary.txt,score_test_failures.txt,tp.txt,fp.txt,tn.txt,fn.txt}`. +`make test` requires the OPA server to be running and curls `localhost:8181/v1/data/mcp/policies/allow` for every JSON case under `references/test_cases/{allow,disallow}/`. A case in `disallow/` is expected to return `allow: false`; `allow/` expects `true`. Results land in `references/scorecard/{scorecard_summary.txt,score_test_failures.txt,tp.txt,fp.txt,tn.txt,fn.txt}`. ## External tools (install separately) - **OPA** + **Regal** (Styra linter) — required for testing and `regal_suggestion`. -- **ARES** (IBM red-teaming) and **Promptfoo** (`npm install -g promptfoo`) — required for adversarial test generation. ARES installs under `scripts/test_generation/ares/` and needs its plugins (`ares-autodan`, `ares-human-jailbreak`, `ares-garak`). +- **ARES** (IBM red-teaming) and **Promptfoo** (`npm install -g promptfoo`) — required for adversarial test generation. ARES installs under `src/smith/test_generation/ares/` and needs its plugins (`ares-autodan`, `ares-human-jailbreak`, `ares-garak`). ## Repo conventions -- **Packaging + tool config live in `scripts/pyproject.toml`** (not at the repo root): flat layout (`cli.py` is the import root), console entry `smith = cli:main`, and `[tool.ruff]`/`[tool.black]` config. Black is pinned to `target-version = py311` so formatting is deterministic across interpreters; the vendored ARES tree is excluded from packaging and linting. +- **Packaging + tool config live in the root `pyproject.toml`**: src layout (`src/smith/`), console entry `smith = smith.cli:main`, declared `[project.dependencies]` (+ `[dev]` extra), `[tool.setuptools.package-data]` shipping the policy_testing harness + `ares_config`, and `[tool.ruff]`/`[tool.black]` config. Black is pinned to `target-version = py311`. Package management uses **uv** (`make install`, `make package`/`make publish` → `uv build`/`uv publish`). - **CI** (`.github/workflows/ci.yml`) mirrors `make ci` and pins `ruff==0.15.20` / `black==26.5.1` — bump these deliberately alongside a reformat commit. The Rego-lint job is currently disabled in CI; still run `make lint-policy` locally. -- **License headers:** every in-scope file (`.py`, `.rego`, `.sh`, `.yaml`, `.yml`, plus `Makefile`/`Dockerfile`) carries an Apache-2.0 SPDX header. `make license` inserts, `make license-check` verifies (`scripts/tools/license_headers.py`). Excludes `scripts/test_generation/ares/`, `mcp_servers/`, `references/`, and generated outputs. +- **License headers:** every in-scope file (`.py`, `.rego`, `.sh`, `.yaml`, `.yml`, plus `Makefile`/`Dockerfile`) carries an Apache-2.0 SPDX header. `make license` inserts, `make license-check` verifies (`src/smith/tools/license_headers.py`). Excludes `src/smith/test_generation/ares/`, `examples/`, `references/`, and generated outputs. - **DCO sign-off** is required on every commit (`git commit -s`). - **Changelog:** user-facing changes get an entry under `## [Unreleased]` in `CHANGELOG.md` (Keep a Changelog); maintainers promote it to a dated version when cutting a release tag. - `smith --help` and a bare `smith` (no flag) work without a populated `.env` — args are parsed before any env-derived path assembly, so don't reintroduce eager `BASE_URL + os.getenv(...)` work ahead of `argparse`. @@ -74,13 +70,13 @@ make opaserver/stop Almost every path in the codebase is **assembled from `.env` at runtime** via `os.getenv`, not hardcoded. The dominant pattern is `BASE_URL + os.getenv("SOME_PATH")`. `BASE_URL` is the absolute path to the skill folder (trailing slash). When you change where files are read/written, you are almost always editing `.env`, not Python. -Target-agent selection is driven by a small set of vars: `TARGET_AGENT_PATH`, `GUIDANCE_FILE`, `SYSTEM_VAR_FILE`, `MCP_*`, and `AGENT_URL`. Pointing Smith at a different agent example (under `mcp_servers/`) means repointing these, not changing code. +Target-agent selection is driven by a small set of vars: `TARGET_AGENT_PATH`, `GUIDANCE_FILE`, `SYSTEM_VAR_FILE`, `MCP_*`, and `AGENT_URL`. Pointing Smith at a different agent example (under `examples/`) means repointing these, not changing code. Key model vars: `MODEL_SONNET` (the LLM used across pipelines), `OPENAI_API_KEY`, `OPENAI_BASE_URL`, `TEMP`, `TOP_P`. ## Per-target-agent inputs -Each target agent under `mcp_servers//` carries its Smith inputs in a `smith/` subfolder: +Each target agent under `examples//` carries its Smith inputs in a `smith/` subfolder: - `guidance.txt` — natural-language policy rules (the source of truth). - `tool_definitions.json` — MCP tools + params (auto-generated by `get_mcp_parameter`); maps to `input.arguments.*` in the policy. - `system_vars.json` — session/system variables (roles, teams, claims); maps to `input.extensions.subject.*`. @@ -93,7 +89,7 @@ The generated policy may **only** reference data available from tool arguments o - `assets/opa/` — OPA intermediate results: AST (`ast.json`), graph (`ast.dot`), backups. - `references/` — all generated intermediates: `decomp_file.json`, `vars_file.json`, `test_cases.json`, attack files, `label_validation_results.json`, `test_case_report.html`, and final `test_cases/{allow,disallow,malicious}/`. -## scripts/ package map +## src/smith/ package map - `policy_generation/` — MCP tool extraction (`extract_tools.py`) and rego validation (`validate_policy.py`). - `test_generation/` — generation pipeline stages run in order by the `test_generation` flag: `decompose` → `grey_condition` → `variable_extraction` → `case_generation` → `attack` (ARES) → `attack_promptfoo` → `convert_test_case`. Also `extract_tool_args.py` for translation. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 63ed809..33c5404 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -25,15 +25,18 @@ The [`Makefile`](Makefile) mirrors CI — a green `make ci` locally means a gree pipeline: ```bash -make install # create a venv and install Smith + dependencies -make lint # ruff check + black --check (read-only) +make install # create a uv venv and install Smith (editable) + [dev] extras +make lint # ruff check + black --check over src/ (read-only) make format # ruff --fix + black (apply formatting) make lint-policy # Regal/OPA lint of assets/policy.rego make license-check # verify every in-scope file carries the SPDX header make test # policy scorecard (needs Docker + the OPA server) -make ci # the gate: lint + lint-policy + license-check + build smoke +make ci # the gate: lint + lint-policy + license-check ``` +Package management uses [`uv`](https://docs.astral.sh/uv/). Build and publish +with `make package` / `make publish` (`uv build` / `uv publish`). + Before submitting a PR, make sure `make ci` passes. ## Coding standards @@ -41,14 +44,14 @@ Before submitting a PR, make sure `make ci` passes. - **Python 3.11+.** Keep code compatible with 3.11 and 3.12. - **Formatting & linting:** [`ruff`](https://docs.astral.sh/ruff/) and [`black`](https://black.readthedocs.io/) (config in - [`scripts/pyproject.toml`](scripts/pyproject.toml)). CI runs `ruff check` and + [`pyproject.toml`](pyproject.toml)). CI runs `ruff check` and `black --check`; run `make format` to fix issues locally. - **Rego:** policies are linted/formatted with Regal ([`make lint-policy`](Makefile)). Keep rule names, namespaces, and allow/deny semantics consistent; add only narrowly scoped conditions rather than rewriting whole policies. -- The vendored ARES tree (`scripts/test_generation/ares/`) is a separate upstream - project and is excluded from linting, formatting, and license headers. +- The vendored ARES inputs (`src/smith/test_generation/ares/`) are separate + upstream material and are excluded from linting, formatting, and license headers. ### Source file headers @@ -63,7 +66,7 @@ shell, YAML, Makefiles, Dockerfiles, and Rego (all `#`-comment formats): Place it after any shebang (`#!/usr/bin/env python3`, `#!/bin/bash`). Run `make license` to insert missing headers and `make license-check` to verify coverage; both are driven by -[`scripts/tools/license_headers.py`](scripts/tools/license_headers.py). +[`src/smith/tools/license_headers.py`](src/smith/tools/license_headers.py). ## Changelog diff --git a/Makefile b/Makefile index 24d974e..b5cccb4 100644 --- a/Makefile +++ b/Makefile @@ -4,17 +4,24 @@ # Smith — project Makefile # ============================================================================= # Targets mirror CI (.github/workflows/ci.yml) so a green `make ci` locally -# means a green pipeline. Policy/OPA-server specifics live in scripts/Makefile. +# means a green pipeline. Package management uses `uv`. SHELL := /bin/bash .SHELLFLAGS := -eu -o pipefail -c .DEFAULT_GOAL := help PYTHON ?= python3 -PIP ?= $(PYTHON) -m pip -SCRIPTS := scripts +UV ?= uv POLICY := assets/policy.rego -LICENSE_TOOL := scripts/tools/license_headers.py +LICENSE_TOOL := src/smith/tools/license_headers.py + +# The OPA scorecard harness ships inside the package; in a repo/skill checkout +# it lives under src/. `make test` runs from the skill root (BASE_URL). +HARNESS := src/smith/policy_testing + +# OPA server (policy testing) +OPA_CONTAINER := smith-opa +OPA_IMAGE := openpolicyagent/opa:1.8.0-static # ============================================================================= # Help @@ -22,29 +29,16 @@ LICENSE_TOOL := scripts/tools/license_headers.py .PHONY: help help: - @echo "Smith — Makefile" - @echo "" - @echo "Setup:" - @echo " install Install Smith (editable) and Python dependencies" - @echo "" - @echo "Lint & format:" - @echo " lint CI lint gate: ruff check + black --check (read-only)" - @echo " format Apply formatting: ruff --fix + black" - @echo " lint-policy Lint assets/policy.rego with Regal (or OPA)" - @echo "" - @echo "License headers:" - @echo " license Insert missing SPDX headers in place" - @echo " license-check Verify every in-scope file carries an SPDX header" - @echo "" - @echo "Test & scan:" - @echo " test Run the policy scorecard (delegates to scripts/Makefile; needs Docker + OPA)" - @echo " audit Dependency vulnerability scan (pip-audit, advisory)" + @echo "Smith — Makefile (uv-based)" @echo "" - @echo "Gate:" - @echo " build Build/install the package and smoke-test the CLI" - @echo " ci lint + lint-policy + license-check (the CI gate)" - @echo "" - @echo "Policy testing / OPA server targets live in scripts/Makefile." + @echo "Setup: install Create a uv venv and install Smith (editable) + [dev] extras" + @echo "Lint & format: lint / format ruff + black over src/ (lint is read-only)" + @echo " lint-policy Lint assets/policy.rego with Regal (or OPA)" + @echo "License headers: license / license-check" + @echo "Test: test Policy scorecard (starts OPA in Docker, runs the harness)" + @echo " opaserver/start|stop|status" + @echo "Package: package/dist, wheel, sdist, verify, publish-test, publish, clean" + @echo "Gate: build (CLI smoke), audit, ci (lint + lint-policy + license-check)" # ============================================================================= # Setup @@ -52,22 +46,27 @@ help: .PHONY: install install: - @$(PIP) install -r requirements.txt - @$(PIP) install -e $(SCRIPTS) - @echo "✅ Smith installed. Try: smith --help" + @$(UV) venv + @$(UV) pip install -e ".[dev]" + @echo "✅ Smith installed (uv venv). Try: smith --help" # ============================================================================= -# Lint & format (ruff + black; config in scripts/pyproject.toml) +# Lint & format (ruff + black; config + pins in pyproject.toml [dev]) # ============================================================================= +# Pinned linters run in isolated uvx envs (matches the CI pins) so linting never +# drags in the heavy runtime dependency tree. +RUFF := uvx ruff@0.15.20 +BLACK := uvx black@26.5.1 + .PHONY: lint lint: - @cd $(SCRIPTS) && ruff check . && black --check . + @$(RUFF) check src && $(BLACK) --check src @echo "✅ lint passed" .PHONY: format fmt format fmt: - @cd $(SCRIPTS) && ruff check --fix . && black . + @$(RUFF) check --fix src && $(BLACK) src .PHONY: lint-policy lint-policy: @@ -93,18 +92,69 @@ license-check: @$(PYTHON) $(LICENSE_TOOL) --check # ============================================================================= -# Test & scan +# Policy testing (OPA server + scorecard harness) # ============================================================================= +.PHONY: opaserver/start +opaserver/start: lint-policy + @echo "Starting OPA server on :8181 (policy: $(POLICY))" + @docker run -d --name $(OPA_CONTAINER) --rm -p 8181:8181 \ + -v "$(CURDIR)/$(POLICY):/policy/policy.rego" $(OPA_IMAGE) \ + run --server /policy/policy.rego --addr=0.0.0.0:8181 >/dev/null + +.PHONY: opaserver/stop +opaserver/stop: + @-docker stop $(OPA_CONTAINER) >/dev/null 2>&1 || true + +.PHONY: opaserver/status +opaserver/status: + @docker ps -q --filter "name=$(OPA_CONTAINER)" --filter "status=running" + .PHONY: test -test: - @echo "Running the policy scorecard (requires Docker + the OPA server; see scripts/Makefile)..." - @$(MAKE) -C $(SCRIPTS) test +test: opaserver/stop opaserver/start + @sleep 3 + @PATH="$(CURDIR)/.venv/bin:$$PATH" SMITH_ROOT="$(CURDIR)" \ + bash $(HARNESS)/score_card.sh "$(CURDIR)" >/dev/null || true + @$(MAKE) --no-print-directory opaserver/stop + @cat references/scorecard/scorecard_summary.txt 2>/dev/null || true .PHONY: audit audit: - @$(PYTHON) -m pip install --quiet pip-audit - @pip-audit -r requirements.txt || true + @uvx pip-audit || true + +# ============================================================================= +# Package & publish (uv) +# ============================================================================= + +.PHONY: package dist +package dist: clean + @$(UV) build + @echo "✅ Built sdist + wheel under dist/" + +.PHONY: wheel +wheel: + @$(UV) build --wheel + +.PHONY: sdist +sdist: + @$(UV) build --sdist + +.PHONY: verify +verify: dist + @$(UV) run --with twine twine check dist/* + +.PHONY: publish-test +publish-test: verify + @$(UV) publish --publish-url https://test.pypi.org/legacy/ dist/* + +.PHONY: publish +publish: verify + @$(UV) publish dist/* + +.PHONY: clean +clean: + @rm -rf dist build *.egg-info src/*.egg-info .pytest_cache .ruff_cache + @find . -type d -name __pycache__ -prune -exec rm -rf {} + 2>/dev/null || true # ============================================================================= # Gate @@ -112,8 +162,9 @@ audit: .PHONY: build build: - @$(PIP) install -e $(SCRIPTS) - @smith --help >/dev/null && echo "✅ CLI smoke test passed (smith --help)" + @test -d .venv || $(UV) venv + @$(UV) pip install -e . + @$(UV) run smith --help >/dev/null && echo "✅ CLI smoke test passed (smith --help)" .PHONY: ci ci: lint lint-policy license-check diff --git a/README.md b/README.md index e8fb93e..e1f84b9 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,8 @@ If you are using Aider Desk: https://aiderdesk.hotovo.com/docs/features/skills ### Prerequisites - Python 3.11+ -- [Regal](https://github.com/StyraInc/regal#getting-started) (OPA linter) +- [uv](https://docs.astral.sh/uv/) (package management) +- [OPA](https://www.openpolicyagent.org/) + [Regal](https://github.com/StyraInc/regal#getting-started) (policy testing / linting; OPA runs in Docker for the scorecard) - [ARES](https://github.com/IBM/ares) (red-teaming framework) - [Promptfoo](https://www.promptfoo.dev/) (red-teaming framework) @@ -59,10 +60,10 @@ python -m venv .venv source .venv/bin/activate ``` -**2. ARES** (red-teaming framework). Installs into `scripts/test_generation/ares/` with its own `.venv`, which is the layout the test-generation pipeline expects (`scripts/test_generation/attack.py` invokes `ares/.venv/bin/ares`): +**2. ARES** (red-teaming framework). Installs into `src/smith/test_generation/ares/` with its own `.venv`, which is the layout the test-generation pipeline expects (`src/smith/test_generation/attack.py` invokes `ares/.venv/bin/ares`): ```bash -cd scripts/test_generation/ares +cd src/smith/test_generation/ares python -m venv .venv source .venv/bin/activate curl https://raw.githubusercontent.com/IBM/ares/refs/heads/main/install.sh | bash @@ -73,7 +74,7 @@ deactivate # Setup ares configuration cp ../ares_config/qwen-owasp-llm-01.yaml ./example_configs cp ../ares_config/human_jailbreaks.json ./assets -export ARES_HOME=/absolute/path/to/smith/scripts/test_generation/ares +export ARES_HOME=/absolute/path/to/smith/src/smith/test_generation/ares # Switch back to the original Python environment cd ../../.. source .venv/bin/activate @@ -89,17 +90,18 @@ export PROMPTFOO_DISABLE_REDTEAM_REMOTE_GENERATION=true export PROMPTFOO_DISABLE_SHARING=true ``` -### Python Dependencies +### Install Smith + +Smith uses [uv](https://docs.astral.sh/uv/) for package management. From the repo root: ```bash -pip install -r requirements.txt +make install # creates a uv venv and installs Smith (editable) + dev tools ``` -### CLI Installation +Or install directly (dependencies are declared in `pyproject.toml`): ```bash -cd scripts -pip install -e . +uv pip install -e . # or: pip install -e . ``` This installs the `smith` CLI command. @@ -126,24 +128,24 @@ Fill in **every** placeholder value in `.env` before running Smith. The most imp | `MCP_TRANSPORT` | MCP transport type: `sse` or `stdio` | | `MCP_URL` | MCP server URL (SSE transport only); default `http://localhost:8000/sse` | | `MCP_COMMAND` / `MCP_ARGS` / `MCP_CWD` | MCP launch command, args, and working dir (**stdio transport only** — see the commented examples in `.env_template`) | -| `TARGET_AGENT_PATH` | Relative path to the target MCP server directory, e.g., `mcp_servers/RagChatbot_MCPServer/` for the HR agent | -| `GUIDANCE_FILE` | Path to the policy guidance file, e.g., `mcp_servers/RagChatbot_MCPServer/smith/guidance.txt` | -| `SYSTEM_VAR_FILE` | Path to the system-variables JSON (e.g., `mcp_servers//smith/system_vars.json`). **Required** — test generation fails without it | +| `TARGET_AGENT_PATH` | Relative path to the target MCP server directory, e.g., `examples/RagChatbot_MCPServer/` for the HR agent | +| `GUIDANCE_FILE` | Path to the policy guidance file, e.g., `examples/RagChatbot_MCPServer/smith/guidance.txt` | +| `SYSTEM_VAR_FILE` | Path to the system-variables JSON (e.g., `examples//smith/system_vars.json`). **Required** — test generation fails without it | | `PROMPTFOO_CONFIG_FILE` / `PROMPTFOO_OUTPUT_FILE` | Promptfoo red-team config and generated output paths | -| `ARES_HOME` | Absolute path to the ARES installation directory (e.g., `/path/to/smith/scripts/test_generation/ares`). Smith uses this to locate `ares/.venv/bin/ares` | +| `ARES_HOME` | Absolute path to the ARES installation directory (e.g., `/path/to/smith/src/smith/test_generation/ares`). Smith uses this to locate `ares/.venv/bin/ares` | See `.env_template` for the full list, including model sampling (`TEMP`, `TOP_P`), test-case evaluation thresholds, and refinement/clustering parameters. ### Start the target agent and MCP server -Detailed instructions for each agent example can be found in the `mcp_servers//README.md`. +Detailed instructions for each agent example can be found in the `examples//README.md`. Smith talks to a **running** target agent (for `/chat` and `/extract_tool_call`) and to its MCP server (to extract tool definitions). Start both before running any `smith` flag. -Each example under `mcp_servers//` ships its own `agent.py` (a FastAPI app exposing `/chat` and `/extract_tool_call`), `server.py` (the MCP server), and a `requirements.txt`. Using `call-for-papers-mcp` as a concrete example: +Each example under `examples//` ships its own `agent.py` (a FastAPI app exposing `/chat` and `/extract_tool_call`), `server.py` (the MCP server), and a `requirements.txt`. Using `call-for-papers-mcp` as a concrete example: ```bash -cd mcp_servers/call-for-papers-mcp +cd examples/call-for-papers-mcp pip install -r requirements.txt # Start the agent server on the port AGENT_URL points to (default 9000). @@ -156,7 +158,7 @@ This example's agent **spawns its MCP server itself over stdio** (`agent.py` lau MCP_TRANSPORT=stdio MCP_COMMAND=python MCP_ARGS=server.py -MCP_CWD=mcp_servers/call-for-papers-mcp +MCP_CWD=examples/call-for-papers-mcp ``` For an SSE-based MCP server instead, set `MCP_TRANSPORT=sse` and `MCP_URL=http://localhost:8000/sse`, and start that server on its own. Check each example's own `README.md` for specifics. @@ -241,7 +243,7 @@ The report groups all test cases by guidance item, with condition sub-tabs. Case To regenerate the HTML report standalone: ```bash -cd scripts/test_case_evaluation/visualization +cd src/smith/test_case_evaluation/visualization python build_report.py ``` @@ -302,7 +304,7 @@ smith/ ├── assets/ # Policy files and OPA data │ ├── policy.rego # Target policy under management │ └── opa/ # OPA intermediate results (AST, graphs, backups) -├── mcp_servers/ # Agent examples +├── examples/ # Agent examples ├── opa_policy/ # Skills related to OPA policy │ ├── policy_creation/ # OPA policy creation workflow │ ├── policy_cross_validation/ # Fix structural/syntax issues (0 cases or 100% fail) @@ -310,19 +312,20 @@ smith/ │ ├── policy_patch/ # OPA policy patching workflow │ ├── policy_regal/ # Regal formatting workflow │ └── policy_duplication/ # Deduplication workflow -├── references/ # All intermediate results -├── scripts/ # Core Python packages -│ ├── cli.py # Main CLI entry point +├── references/ # All intermediate results (incl. scorecard/ outputs) +├── pyproject.toml # Packaging, dependencies, ruff/black config +├── src/smith/ # The `smith` Python package +│ ├── cli.py # Main CLI entry point (smith.cli:main) │ ├── policy_agent/ # OPA policy analysis and refinement │ ├── policy_generation/ # MCP tool extraction and policy generation │ ├── test_generation/ # Test case generation and translation pipeline │ ├── test_case_evaluation/ # Label validation and report generation -│ ├── tests/ # Policy testing and validation +│ ├── policy_testing/ # OPA scorecard harness (score_card.sh, coverage) │ └── tools/ # Repo tooling (e.g. license headers) +├── tests/ # Placeholder for the test suite (TODO) ├── test_generation/ # Test generation skill markdown file ├── .env_template # Environment template ├── SKILL.md # Main agent skill instructions -├── requirements.txt # Python dependencies └── README.md ``` diff --git a/mcp_servers/.gitignore b/examples/.gitignore similarity index 100% rename from mcp_servers/.gitignore rename to examples/.gitignore diff --git a/mcp_servers/RagChatbot_MCPServer/AGENT_ALICE.md b/examples/RagChatbot_MCPServer/AGENT_ALICE.md similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/AGENT_ALICE.md rename to examples/RagChatbot_MCPServer/AGENT_ALICE.md diff --git a/mcp_servers/RagChatbot_MCPServer/Makefile b/examples/RagChatbot_MCPServer/Makefile similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/Makefile rename to examples/RagChatbot_MCPServer/Makefile diff --git a/mcp_servers/RagChatbot_MCPServer/README.md b/examples/RagChatbot_MCPServer/README.md similarity index 92% rename from mcp_servers/RagChatbot_MCPServer/README.md rename to examples/RagChatbot_MCPServer/README.md index a01b489..31d8c3e 100644 --- a/mcp_servers/RagChatbot_MCPServer/README.md +++ b/examples/RagChatbot_MCPServer/README.md @@ -27,13 +27,13 @@ pip install -r requirements.txt Start the MCP server (in a separate terminal): ```bash -cd mcp_servers/RagChatbot_MCPServer +cd examples/RagChatbot_MCPServer python mcp_server.py ``` Start the agent: ```bash -cd mcp_servers/RagChatbot_MCPServer +cd examples/RagChatbot_MCPServer pip install -r requirements.txt uvicorn fast_server:app --host 0.0.0.0 --port 9000 ``` @@ -71,11 +71,11 @@ Default configuration (in `.env`): Make sure your `.env` points to this example: ``` -TARGET_AGENT_PATH=mcp_servers/RagChatbot_MCPServer/ -GUIDANCE_FILE=mcp_servers/RagChatbot_MCPServer/smith/guidance.txt -SYSTEM_VAR_FILE=mcp_servers/RagChatbot_MCPServer/smith/system_vars.json -PROMPTFOO_CONFIG_FILE=mcp_servers/RagChatbot_MCPServer/smith/promptfooconfig.yaml -PROMPTFOO_OUTPUT_FILE=mcp_servers/RagChatbot_MCPServer/smith/redteam.yaml +TARGET_AGENT_PATH=examples/RagChatbot_MCPServer/ +GUIDANCE_FILE=examples/RagChatbot_MCPServer/smith/guidance.txt +SYSTEM_VAR_FILE=examples/RagChatbot_MCPServer/smith/system_vars.json +PROMPTFOO_CONFIG_FILE=examples/RagChatbot_MCPServer/smith/promptfooconfig.yaml +PROMPTFOO_OUTPUT_FILE=examples/RagChatbot_MCPServer/smith/redteam.yaml MCP_TRANSPORT=sse MCP_URL=http://localhost:8000/sse ``` diff --git a/mcp_servers/RagChatbot_MCPServer/SYSTEM_VARIABLE_TEMPLATES.md b/examples/RagChatbot_MCPServer/SYSTEM_VARIABLE_TEMPLATES.md similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/SYSTEM_VARIABLE_TEMPLATES.md rename to examples/RagChatbot_MCPServer/SYSTEM_VARIABLE_TEMPLATES.md diff --git a/mcp_servers/RagChatbot_MCPServer/comprehensive_5_layer_security_test.py b/examples/RagChatbot_MCPServer/comprehensive_5_layer_security_test.py similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/comprehensive_5_layer_security_test.py rename to examples/RagChatbot_MCPServer/comprehensive_5_layer_security_test.py diff --git a/mcp_servers/RagChatbot_MCPServer/create_ticket.py b/examples/RagChatbot_MCPServer/create_ticket.py similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/create_ticket.py rename to examples/RagChatbot_MCPServer/create_ticket.py diff --git a/mcp_servers/RagChatbot_MCPServer/data_sources/__init__.py b/examples/RagChatbot_MCPServer/data_sources/__init__.py similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/data_sources/__init__.py rename to examples/RagChatbot_MCPServer/data_sources/__init__.py diff --git a/mcp_servers/RagChatbot_MCPServer/data_sources/hr_database.py b/examples/RagChatbot_MCPServer/data_sources/hr_database.py similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/data_sources/hr_database.py rename to examples/RagChatbot_MCPServer/data_sources/hr_database.py diff --git a/mcp_servers/RagChatbot_MCPServer/fast_server.py b/examples/RagChatbot_MCPServer/fast_server.py similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/fast_server.py rename to examples/RagChatbot_MCPServer/fast_server.py diff --git a/mcp_servers/RagChatbot_MCPServer/images/HRwithMCP.png b/examples/RagChatbot_MCPServer/images/HRwithMCP.png similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/images/HRwithMCP.png rename to examples/RagChatbot_MCPServer/images/HRwithMCP.png diff --git a/mcp_servers/RagChatbot_MCPServer/images/hr.png b/examples/RagChatbot_MCPServer/images/hr.png similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/images/hr.png rename to examples/RagChatbot_MCPServer/images/hr.png diff --git a/mcp_servers/RagChatbot_MCPServer/images/mcp-architecture.png b/examples/RagChatbot_MCPServer/images/mcp-architecture.png similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/images/mcp-architecture.png rename to examples/RagChatbot_MCPServer/images/mcp-architecture.png diff --git a/mcp_servers/RagChatbot_MCPServer/images/rag.jpg b/examples/RagChatbot_MCPServer/images/rag.jpg similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/images/rag.jpg rename to examples/RagChatbot_MCPServer/images/rag.jpg diff --git a/mcp_servers/RagChatbot_MCPServer/llm_guard_config.py b/examples/RagChatbot_MCPServer/llm_guard_config.py similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/llm_guard_config.py rename to examples/RagChatbot_MCPServer/llm_guard_config.py diff --git a/mcp_servers/RagChatbot_MCPServer/mcp_server.py b/examples/RagChatbot_MCPServer/mcp_server.py similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/mcp_server.py rename to examples/RagChatbot_MCPServer/mcp_server.py diff --git a/mcp_servers/RagChatbot_MCPServer/opa_client.py b/examples/RagChatbot_MCPServer/opa_client.py similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/opa_client.py rename to examples/RagChatbot_MCPServer/opa_client.py diff --git a/mcp_servers/RagChatbot_MCPServer/opa_config.py b/examples/RagChatbot_MCPServer/opa_config.py similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/opa_config.py rename to examples/RagChatbot_MCPServer/opa_config.py diff --git a/mcp_servers/RagChatbot_MCPServer/pdfs/salary_summary.pdf b/examples/RagChatbot_MCPServer/pdfs/salary_summary.pdf similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/pdfs/salary_summary.pdf rename to examples/RagChatbot_MCPServer/pdfs/salary_summary.pdf diff --git a/mcp_servers/RagChatbot_MCPServer/pdfs/work_rules_and_regulations_2016.pdf b/examples/RagChatbot_MCPServer/pdfs/work_rules_and_regulations_2016.pdf similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/pdfs/work_rules_and_regulations_2016.pdf rename to examples/RagChatbot_MCPServer/pdfs/work_rules_and_regulations_2016.pdf diff --git a/examples/RagChatbot_MCPServer/rag_pipeline.py b/examples/RagChatbot_MCPServer/rag_pipeline.py new file mode 100644 index 0000000..0ae4308 --- /dev/null +++ b/examples/RagChatbot_MCPServer/rag_pipeline.py @@ -0,0 +1,56 @@ +from langchain_openai import ChatOpenAI +from langchain_community.embeddings import HuggingFaceEmbeddings +from langchain_community.document_loaders import PDFPlumberLoader +from langchain_text_splitters import RecursiveCharacterTextSplitter +from langchain_core.vectorstores import InMemoryVectorStore +from langchain_core.prompts import ChatPromptTemplate +from dotenv import load_dotenv +import os + +# Load environment variables +load_dotenv() + +template = """ +You are a RAG chatbot assistant responsible for retrieving information from a PDF file containing working policies and regulations, and answering users’ questions. +Question: {question} +Context: {context} +Answer: +""" + +# The RAG pipeline (LLM + embedded PDF) is built lazily on first use so this +# module imports cleanly without RITS_*/BASE_URL configured, and the heavy +# embedding/PDF work only happens when a query is actually made. +_chain = None +_vector_store = None + + +def _build(): + global _chain, _vector_store + if _chain is not None: + return + api_key = os.getenv("RITS_API_KEY") + api_url = os.getenv("RITS_BASE_URL") + model = os.getenv("RITS_MODEL") + base_url = os.getenv("BASE_URL", "") + + embeddings = HuggingFaceEmbeddings(model_name="BAAI/bge-small-en-v1.5") + _vector_store = InMemoryVectorStore(embeddings) + llm = ChatOpenAI(model=model, api_key=api_key, base_url=api_url) + _chain = ChatPromptTemplate.from_template(template) | llm + + pdf_path = ( + base_url + "examples/RagChatbot_MCPServer/pdfs/work_rules_and_regulations_2016.pdf" + ) + documents = PDFPlumberLoader(pdf_path).load() + text_splitter = RecursiveCharacterTextSplitter( + chunk_size=1000, chunk_overlap=200, add_start_index=True + ) + _vector_store.add_documents(text_splitter.split_documents(documents)) + + +def raw_ask_for_workpolicy(question: str) -> str: + _build() + relevant_docs = _vector_store.similarity_search(question) + context = "\n\n".join([doc.page_content for doc in relevant_docs]) + result = _chain.invoke({"question": question, "context": context}) + return result.content diff --git a/examples/RagChatbot_MCPServer/rag_salary.py b/examples/RagChatbot_MCPServer/rag_salary.py new file mode 100644 index 0000000..6c96502 --- /dev/null +++ b/examples/RagChatbot_MCPServer/rag_salary.py @@ -0,0 +1,54 @@ +from langchain_openai import ChatOpenAI +from langchain_community.embeddings import HuggingFaceEmbeddings +from langchain_community.document_loaders import PDFPlumberLoader +from langchain_text_splitters import RecursiveCharacterTextSplitter +from langchain_core.vectorstores import InMemoryVectorStore +from langchain_core.prompts import ChatPromptTemplate +from dotenv import load_dotenv +import os + +# Load environment variables +load_dotenv() + +template = """ +You are a RAG chatbot assistant responsible for retrieving information from a PDF file containing salary/compensation information, and answering users’ questions. +Question: {question} +Context: {context} +Answer: +""" + +# The RAG pipeline (LLM + embedded PDF) is built lazily on first use so this +# module imports cleanly without RITS_*/BASE_URL configured, and the heavy +# embedding/PDF work only happens when a query is actually made. +_chain = None +_vector_store = None + + +def _build(): + global _chain, _vector_store + if _chain is not None: + return + api_key = os.getenv("RITS_API_KEY") + api_url = os.getenv("RITS_BASE_URL") + model = os.getenv("RITS_MODEL") + base_url = os.getenv("BASE_URL", "") + + embeddings = HuggingFaceEmbeddings(model_name="BAAI/bge-small-en-v1.5") + _vector_store = InMemoryVectorStore(embeddings) + llm = ChatOpenAI(model=model, api_key=api_key, base_url=api_url) + _chain = ChatPromptTemplate.from_template(template) | llm + + pdf_path = base_url + "examples/RagChatbot_MCPServer/pdfs/salary_summary.pdf" + documents = PDFPlumberLoader(pdf_path).load() + text_splitter = RecursiveCharacterTextSplitter( + chunk_size=1000, chunk_overlap=200, add_start_index=True + ) + _vector_store.add_documents(text_splitter.split_documents(documents)) + + +def raw_ask_for_salary(question: str) -> str: + _build() + relevant_docs = _vector_store.similarity_search(question) + context = "\n\n".join([doc.page_content for doc in relevant_docs]) + result = _chain.invoke({"question": question, "context": context}) + return result.content diff --git a/mcp_servers/RagChatbot_MCPServer/requirements.txt b/examples/RagChatbot_MCPServer/requirements.txt similarity index 70% rename from mcp_servers/RagChatbot_MCPServer/requirements.txt rename to examples/RagChatbot_MCPServer/requirements.txt index 92fcb02..ab1ed4e 100644 --- a/mcp_servers/RagChatbot_MCPServer/requirements.txt +++ b/examples/RagChatbot_MCPServer/requirements.txt @@ -2,6 +2,8 @@ mcp[cli] openai langchain langchain-community +langchain-openai +langchain-text-splitters pdfplumber sentence-transformers streamlit diff --git a/mcp_servers/RagChatbot_MCPServer/run_llm_with_mcp.py b/examples/RagChatbot_MCPServer/run_llm_with_mcp.py similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/run_llm_with_mcp.py rename to examples/RagChatbot_MCPServer/run_llm_with_mcp.py diff --git a/mcp_servers/RagChatbot_MCPServer/security_scenario_tests.txt b/examples/RagChatbot_MCPServer/security_scenario_tests.txt similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/security_scenario_tests.txt rename to examples/RagChatbot_MCPServer/security_scenario_tests.txt diff --git a/mcp_servers/RagChatbot_MCPServer/smith/guidance.txt b/examples/RagChatbot_MCPServer/smith/guidance.txt similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/guidance.txt rename to examples/RagChatbot_MCPServer/smith/guidance.txt diff --git a/mcp_servers/RagChatbot_MCPServer/smith/promptfooconfig.yaml b/examples/RagChatbot_MCPServer/smith/promptfooconfig.yaml similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/promptfooconfig.yaml rename to examples/RagChatbot_MCPServer/smith/promptfooconfig.yaml diff --git a/mcp_servers/RagChatbot_MCPServer/smith/simith_outputs/policy_generated.rego b/examples/RagChatbot_MCPServer/smith/simith_outputs/policy_generated.rego similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/simith_outputs/policy_generated.rego rename to examples/RagChatbot_MCPServer/smith/simith_outputs/policy_generated.rego diff --git a/mcp_servers/RagChatbot_MCPServer/smith/simith_outputs/policy_revise.rego b/examples/RagChatbot_MCPServer/smith/simith_outputs/policy_revise.rego similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/simith_outputs/policy_revise.rego rename to examples/RagChatbot_MCPServer/smith/simith_outputs/policy_revise.rego diff --git a/mcp_servers/RagChatbot_MCPServer/smith/simith_outputs/tool_definitions.json b/examples/RagChatbot_MCPServer/smith/simith_outputs/tool_definitions.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/simith_outputs/tool_definitions.json rename to examples/RagChatbot_MCPServer/smith/simith_outputs/tool_definitions.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/system_vars.json b/examples/RagChatbot_MCPServer/smith/system_vars.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/system_vars.json rename to examples/RagChatbot_MCPServer/smith/system_vars.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case0.json b/examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case0.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case0.json rename to examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case0.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case1.json b/examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case1.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case1.json rename to examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case1.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case10.json b/examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case10.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case10.json rename to examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case10.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case11.json b/examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case11.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case11.json rename to examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case11.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case12.json b/examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case12.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case12.json rename to examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case12.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case13.json b/examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case13.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case13.json rename to examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case13.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case14.json b/examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case14.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case14.json rename to examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case14.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case15.json b/examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case15.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case15.json rename to examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case15.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case16.json b/examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case16.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case16.json rename to examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case16.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case17.json b/examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case17.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case17.json rename to examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case17.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case18.json b/examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case18.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case18.json rename to examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case18.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case19.json b/examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case19.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case19.json rename to examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case19.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case2.json b/examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case2.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case2.json rename to examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case2.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case20.json b/examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case20.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case20.json rename to examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case20.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case21.json b/examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case21.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case21.json rename to examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case21.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case22.json b/examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case22.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case22.json rename to examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case22.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case23.json b/examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case23.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case23.json rename to examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case23.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case24.json b/examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case24.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case24.json rename to examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case24.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case25.json b/examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case25.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case25.json rename to examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case25.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case26.json b/examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case26.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case26.json rename to examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case26.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case27.json b/examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case27.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case27.json rename to examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case27.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case28.json b/examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case28.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case28.json rename to examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case28.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case3.json b/examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case3.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case3.json rename to examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case3.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case32.json b/examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case32.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case32.json rename to examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case32.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case34.json b/examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case34.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case34.json rename to examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case34.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case35.json b/examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case35.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case35.json rename to examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case35.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case36.json b/examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case36.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case36.json rename to examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case36.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case37.json b/examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case37.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case37.json rename to examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case37.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case38.json b/examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case38.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case38.json rename to examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case38.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case39.json b/examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case39.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case39.json rename to examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case39.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case4.json b/examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case4.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case4.json rename to examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case4.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case40.json b/examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case40.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case40.json rename to examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case40.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case5.json b/examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case5.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case5.json rename to examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case5.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case6.json b/examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case6.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case6.json rename to examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case6.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case7.json b/examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case7.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case7.json rename to examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case7.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case8.json b/examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case8.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case8.json rename to examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case8.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case9.json b/examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case9.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/allow/test_case9.json rename to examples/RagChatbot_MCPServer/smith/test_cases/allow/test_case9.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case0.json b/examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case0.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case0.json rename to examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case0.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case1.json b/examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case1.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case1.json rename to examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case1.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case10.json b/examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case10.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case10.json rename to examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case10.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case11.json b/examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case11.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case11.json rename to examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case11.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case12.json b/examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case12.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case12.json rename to examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case12.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case14.json b/examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case14.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case14.json rename to examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case14.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case15.json b/examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case15.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case15.json rename to examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case15.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case16.json b/examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case16.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case16.json rename to examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case16.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case17.json b/examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case17.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case17.json rename to examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case17.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case18.json b/examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case18.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case18.json rename to examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case18.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case19.json b/examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case19.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case19.json rename to examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case19.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case2.json b/examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case2.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case2.json rename to examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case2.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case20.json b/examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case20.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case20.json rename to examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case20.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case21.json b/examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case21.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case21.json rename to examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case21.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case22.json b/examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case22.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case22.json rename to examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case22.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case23.json b/examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case23.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case23.json rename to examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case23.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case24.json b/examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case24.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case24.json rename to examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case24.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case25.json b/examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case25.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case25.json rename to examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case25.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case26.json b/examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case26.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case26.json rename to examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case26.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case27.json b/examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case27.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case27.json rename to examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case27.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case28.json b/examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case28.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case28.json rename to examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case28.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case29.json b/examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case29.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case29.json rename to examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case29.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case3.json b/examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case3.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case3.json rename to examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case3.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case30.json b/examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case30.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case30.json rename to examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case30.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case32.json b/examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case32.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case32.json rename to examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case32.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case33.json b/examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case33.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case33.json rename to examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case33.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case34.json b/examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case34.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case34.json rename to examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case34.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case38.json b/examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case38.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case38.json rename to examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case38.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case39.json b/examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case39.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case39.json rename to examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case39.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case4.json b/examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case4.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case4.json rename to examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case4.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case40.json b/examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case40.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case40.json rename to examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case40.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case41.json b/examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case41.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case41.json rename to examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case41.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case44.json b/examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case44.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case44.json rename to examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case44.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case45.json b/examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case45.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case45.json rename to examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case45.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case46.json b/examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case46.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case46.json rename to examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case46.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case47.json b/examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case47.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case47.json rename to examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case47.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case48.json b/examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case48.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case48.json rename to examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case48.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case49.json b/examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case49.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case49.json rename to examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case49.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case5.json b/examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case5.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case5.json rename to examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case5.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case6.json b/examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case6.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case6.json rename to examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case6.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case60.json b/examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case60.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case60.json rename to examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case60.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case61.json b/examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case61.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case61.json rename to examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case61.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case62.json b/examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case62.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case62.json rename to examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case62.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case63.json b/examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case63.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case63.json rename to examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case63.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case64.json b/examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case64.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case64.json rename to examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case64.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case65.json b/examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case65.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case65.json rename to examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case65.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case66.json b/examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case66.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case66.json rename to examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case66.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case7.json b/examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case7.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case7.json rename to examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case7.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case8.json b/examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case8.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case8.json rename to examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case8.json diff --git a/mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case9.json b/examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case9.json similarity index 100% rename from mcp_servers/RagChatbot_MCPServer/smith/test_cases/disallow/test_case9.json rename to examples/RagChatbot_MCPServer/smith/test_cases/disallow/test_case9.json diff --git a/mcp_servers/call-for-papers-mcp/.gitattributes b/examples/call-for-papers-mcp/.gitattributes similarity index 100% rename from mcp_servers/call-for-papers-mcp/.gitattributes rename to examples/call-for-papers-mcp/.gitattributes diff --git a/mcp_servers/call-for-papers-mcp/Dockerfile b/examples/call-for-papers-mcp/Dockerfile similarity index 100% rename from mcp_servers/call-for-papers-mcp/Dockerfile rename to examples/call-for-papers-mcp/Dockerfile diff --git a/mcp_servers/call-for-papers-mcp/LISENCE b/examples/call-for-papers-mcp/LISENCE similarity index 100% rename from mcp_servers/call-for-papers-mcp/LISENCE rename to examples/call-for-papers-mcp/LISENCE diff --git a/mcp_servers/call-for-papers-mcp/README.md b/examples/call-for-papers-mcp/README.md similarity index 93% rename from mcp_servers/call-for-papers-mcp/README.md rename to examples/call-for-papers-mcp/README.md index b7d2553..85fad7c 100644 --- a/mcp_servers/call-for-papers-mcp/README.md +++ b/examples/call-for-papers-mcp/README.md @@ -24,7 +24,7 @@ ollama pull qwen3.5 Start the agent: ```bash -cd mcp_servers/call-for-papers-mcp +cd examples/call-for-papers-mcp pip install -r requirements.txt uvicorn agent:app --host 0.0.0.0 --port 9000 ``` @@ -67,15 +67,15 @@ Default configuration (in `.env`): Make sure your `.env` points to this example: ``` -TARGET_AGENT_PATH=mcp_servers/call-for-papers-mcp/ -GUIDANCE_FILE=mcp_servers/call-for-papers-mcp/smith/guidance.txt -SYSTEM_VAR_FILE=mcp_servers/call-for-papers-mcp/smith/system_vars.json -PROMPTFOO_CONFIG_FILE=mcp_servers/call-for-papers-mcp/smith/promptfooconfig.yaml -PROMPTFOO_OUTPUT_FILE=mcp_servers/call-for-papers-mcp/smith/redteam.yaml +TARGET_AGENT_PATH=examples/call-for-papers-mcp/ +GUIDANCE_FILE=examples/call-for-papers-mcp/smith/guidance.txt +SYSTEM_VAR_FILE=examples/call-for-papers-mcp/smith/system_vars.json +PROMPTFOO_CONFIG_FILE=examples/call-for-papers-mcp/smith/promptfooconfig.yaml +PROMPTFOO_OUTPUT_FILE=examples/call-for-papers-mcp/smith/redteam.yaml MCP_TRANSPORT=stdio MCP_COMMAND=python MCP_ARGS=server.py -MCP_CWD=mcp_servers/call-for-papers-mcp +MCP_CWD=examples/call-for-papers-mcp ``` ## How to Test Smith (End-to-End Workflow) diff --git a/mcp_servers/call-for-papers-mcp/agent.py b/examples/call-for-papers-mcp/agent.py similarity index 100% rename from mcp_servers/call-for-papers-mcp/agent.py rename to examples/call-for-papers-mcp/agent.py diff --git a/mcp_servers/call-for-papers-mcp/app.py b/examples/call-for-papers-mcp/app.py similarity index 100% rename from mcp_servers/call-for-papers-mcp/app.py rename to examples/call-for-papers-mcp/app.py diff --git a/mcp_servers/call-for-papers-mcp/requirements.txt b/examples/call-for-papers-mcp/requirements.txt similarity index 100% rename from mcp_servers/call-for-papers-mcp/requirements.txt rename to examples/call-for-papers-mcp/requirements.txt diff --git a/mcp_servers/call-for-papers-mcp/server.py b/examples/call-for-papers-mcp/server.py similarity index 100% rename from mcp_servers/call-for-papers-mcp/server.py rename to examples/call-for-papers-mcp/server.py diff --git a/mcp_servers/call-for-papers-mcp/smith/guidance.txt b/examples/call-for-papers-mcp/smith/guidance.txt similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/guidance.txt rename to examples/call-for-papers-mcp/smith/guidance.txt diff --git a/mcp_servers/call-for-papers-mcp/smith/mcp_tool_summary.md b/examples/call-for-papers-mcp/smith/mcp_tool_summary.md similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/mcp_tool_summary.md rename to examples/call-for-papers-mcp/smith/mcp_tool_summary.md diff --git a/mcp_servers/call-for-papers-mcp/smith/promptfooconfig.yaml b/examples/call-for-papers-mcp/smith/promptfooconfig.yaml similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/promptfooconfig.yaml rename to examples/call-for-papers-mcp/smith/promptfooconfig.yaml diff --git a/mcp_servers/call-for-papers-mcp/smith/redteam.yaml b/examples/call-for-papers-mcp/smith/redteam.yaml similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/redteam.yaml rename to examples/call-for-papers-mcp/smith/redteam.yaml diff --git a/mcp_servers/call-for-papers-mcp/smith/smith_outputs/defect_summary.txt b/examples/call-for-papers-mcp/smith/smith_outputs/defect_summary.txt similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/smith_outputs/defect_summary.txt rename to examples/call-for-papers-mcp/smith/smith_outputs/defect_summary.txt diff --git a/mcp_servers/call-for-papers-mcp/smith/smith_outputs/policy_cross_validated.rego b/examples/call-for-papers-mcp/smith/smith_outputs/policy_cross_validated.rego similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/smith_outputs/policy_cross_validated.rego rename to examples/call-for-papers-mcp/smith/smith_outputs/policy_cross_validated.rego diff --git a/mcp_servers/call-for-papers-mcp/smith/smith_outputs/policy_defect.rego b/examples/call-for-papers-mcp/smith/smith_outputs/policy_defect.rego similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/smith_outputs/policy_defect.rego rename to examples/call-for-papers-mcp/smith/smith_outputs/policy_defect.rego diff --git a/mcp_servers/call-for-papers-mcp/smith/smith_outputs/policy_generated.rego b/examples/call-for-papers-mcp/smith/smith_outputs/policy_generated.rego similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/smith_outputs/policy_generated.rego rename to examples/call-for-papers-mcp/smith/smith_outputs/policy_generated.rego diff --git a/mcp_servers/call-for-papers-mcp/smith/smith_outputs/policy_revised.rego b/examples/call-for-papers-mcp/smith/smith_outputs/policy_revised.rego similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/smith_outputs/policy_revised.rego rename to examples/call-for-papers-mcp/smith/smith_outputs/policy_revised.rego diff --git a/mcp_servers/call-for-papers-mcp/smith/smith_outputs/tool_definitions.json b/examples/call-for-papers-mcp/smith/smith_outputs/tool_definitions.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/smith_outputs/tool_definitions.json rename to examples/call-for-papers-mcp/smith/smith_outputs/tool_definitions.json diff --git a/mcp_servers/call-for-papers-mcp/smith/system_vars.json b/examples/call-for-papers-mcp/smith/system_vars.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/system_vars.json rename to examples/call-for-papers-mcp/smith/system_vars.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/allow/test_case0.json b/examples/call-for-papers-mcp/smith/test_cases/allow/test_case0.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/allow/test_case0.json rename to examples/call-for-papers-mcp/smith/test_cases/allow/test_case0.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/allow/test_case10.json b/examples/call-for-papers-mcp/smith/test_cases/allow/test_case10.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/allow/test_case10.json rename to examples/call-for-papers-mcp/smith/test_cases/allow/test_case10.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/allow/test_case11.json b/examples/call-for-papers-mcp/smith/test_cases/allow/test_case11.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/allow/test_case11.json rename to examples/call-for-papers-mcp/smith/test_cases/allow/test_case11.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/allow/test_case12.json b/examples/call-for-papers-mcp/smith/test_cases/allow/test_case12.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/allow/test_case12.json rename to examples/call-for-papers-mcp/smith/test_cases/allow/test_case12.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/allow/test_case13.json b/examples/call-for-papers-mcp/smith/test_cases/allow/test_case13.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/allow/test_case13.json rename to examples/call-for-papers-mcp/smith/test_cases/allow/test_case13.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/allow/test_case14.json b/examples/call-for-papers-mcp/smith/test_cases/allow/test_case14.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/allow/test_case14.json rename to examples/call-for-papers-mcp/smith/test_cases/allow/test_case14.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/allow/test_case18.json b/examples/call-for-papers-mcp/smith/test_cases/allow/test_case18.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/allow/test_case18.json rename to examples/call-for-papers-mcp/smith/test_cases/allow/test_case18.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/allow/test_case20.json b/examples/call-for-papers-mcp/smith/test_cases/allow/test_case20.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/allow/test_case20.json rename to examples/call-for-papers-mcp/smith/test_cases/allow/test_case20.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/allow/test_case21.json b/examples/call-for-papers-mcp/smith/test_cases/allow/test_case21.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/allow/test_case21.json rename to examples/call-for-papers-mcp/smith/test_cases/allow/test_case21.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/allow/test_case27.json b/examples/call-for-papers-mcp/smith/test_cases/allow/test_case27.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/allow/test_case27.json rename to examples/call-for-papers-mcp/smith/test_cases/allow/test_case27.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/allow/test_case28.json b/examples/call-for-papers-mcp/smith/test_cases/allow/test_case28.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/allow/test_case28.json rename to examples/call-for-papers-mcp/smith/test_cases/allow/test_case28.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/allow/test_case29.json b/examples/call-for-papers-mcp/smith/test_cases/allow/test_case29.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/allow/test_case29.json rename to examples/call-for-papers-mcp/smith/test_cases/allow/test_case29.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/allow/test_case31.json b/examples/call-for-papers-mcp/smith/test_cases/allow/test_case31.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/allow/test_case31.json rename to examples/call-for-papers-mcp/smith/test_cases/allow/test_case31.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/allow/test_case32.json b/examples/call-for-papers-mcp/smith/test_cases/allow/test_case32.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/allow/test_case32.json rename to examples/call-for-papers-mcp/smith/test_cases/allow/test_case32.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/allow/test_case5.json b/examples/call-for-papers-mcp/smith/test_cases/allow/test_case5.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/allow/test_case5.json rename to examples/call-for-papers-mcp/smith/test_cases/allow/test_case5.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/allow/test_case6.json b/examples/call-for-papers-mcp/smith/test_cases/allow/test_case6.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/allow/test_case6.json rename to examples/call-for-papers-mcp/smith/test_cases/allow/test_case6.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/allow/test_case7.json b/examples/call-for-papers-mcp/smith/test_cases/allow/test_case7.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/allow/test_case7.json rename to examples/call-for-papers-mcp/smith/test_cases/allow/test_case7.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/allow/test_case8.json b/examples/call-for-papers-mcp/smith/test_cases/allow/test_case8.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/allow/test_case8.json rename to examples/call-for-papers-mcp/smith/test_cases/allow/test_case8.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/allow/test_case9.json b/examples/call-for-papers-mcp/smith/test_cases/allow/test_case9.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/allow/test_case9.json rename to examples/call-for-papers-mcp/smith/test_cases/allow/test_case9.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case0.json b/examples/call-for-papers-mcp/smith/test_cases/disallow/test_case0.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case0.json rename to examples/call-for-papers-mcp/smith/test_cases/disallow/test_case0.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case18.json b/examples/call-for-papers-mcp/smith/test_cases/disallow/test_case18.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case18.json rename to examples/call-for-papers-mcp/smith/test_cases/disallow/test_case18.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case2.json b/examples/call-for-papers-mcp/smith/test_cases/disallow/test_case2.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case2.json rename to examples/call-for-papers-mcp/smith/test_cases/disallow/test_case2.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case20.json b/examples/call-for-papers-mcp/smith/test_cases/disallow/test_case20.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case20.json rename to examples/call-for-papers-mcp/smith/test_cases/disallow/test_case20.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case21.json b/examples/call-for-papers-mcp/smith/test_cases/disallow/test_case21.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case21.json rename to examples/call-for-papers-mcp/smith/test_cases/disallow/test_case21.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case22.json b/examples/call-for-papers-mcp/smith/test_cases/disallow/test_case22.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case22.json rename to examples/call-for-papers-mcp/smith/test_cases/disallow/test_case22.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case23.json b/examples/call-for-papers-mcp/smith/test_cases/disallow/test_case23.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case23.json rename to examples/call-for-papers-mcp/smith/test_cases/disallow/test_case23.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case24.json b/examples/call-for-papers-mcp/smith/test_cases/disallow/test_case24.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case24.json rename to examples/call-for-papers-mcp/smith/test_cases/disallow/test_case24.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case25.json b/examples/call-for-papers-mcp/smith/test_cases/disallow/test_case25.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case25.json rename to examples/call-for-papers-mcp/smith/test_cases/disallow/test_case25.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case26.json b/examples/call-for-papers-mcp/smith/test_cases/disallow/test_case26.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case26.json rename to examples/call-for-papers-mcp/smith/test_cases/disallow/test_case26.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case27.json b/examples/call-for-papers-mcp/smith/test_cases/disallow/test_case27.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case27.json rename to examples/call-for-papers-mcp/smith/test_cases/disallow/test_case27.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case28.json b/examples/call-for-papers-mcp/smith/test_cases/disallow/test_case28.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case28.json rename to examples/call-for-papers-mcp/smith/test_cases/disallow/test_case28.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case29.json b/examples/call-for-papers-mcp/smith/test_cases/disallow/test_case29.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case29.json rename to examples/call-for-papers-mcp/smith/test_cases/disallow/test_case29.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case3.json b/examples/call-for-papers-mcp/smith/test_cases/disallow/test_case3.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case3.json rename to examples/call-for-papers-mcp/smith/test_cases/disallow/test_case3.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case30.json b/examples/call-for-papers-mcp/smith/test_cases/disallow/test_case30.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case30.json rename to examples/call-for-papers-mcp/smith/test_cases/disallow/test_case30.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case31.json b/examples/call-for-papers-mcp/smith/test_cases/disallow/test_case31.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case31.json rename to examples/call-for-papers-mcp/smith/test_cases/disallow/test_case31.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case32.json b/examples/call-for-papers-mcp/smith/test_cases/disallow/test_case32.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case32.json rename to examples/call-for-papers-mcp/smith/test_cases/disallow/test_case32.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case33.json b/examples/call-for-papers-mcp/smith/test_cases/disallow/test_case33.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case33.json rename to examples/call-for-papers-mcp/smith/test_cases/disallow/test_case33.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case35.json b/examples/call-for-papers-mcp/smith/test_cases/disallow/test_case35.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case35.json rename to examples/call-for-papers-mcp/smith/test_cases/disallow/test_case35.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case36.json b/examples/call-for-papers-mcp/smith/test_cases/disallow/test_case36.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case36.json rename to examples/call-for-papers-mcp/smith/test_cases/disallow/test_case36.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case37.json b/examples/call-for-papers-mcp/smith/test_cases/disallow/test_case37.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case37.json rename to examples/call-for-papers-mcp/smith/test_cases/disallow/test_case37.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case38.json b/examples/call-for-papers-mcp/smith/test_cases/disallow/test_case38.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case38.json rename to examples/call-for-papers-mcp/smith/test_cases/disallow/test_case38.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case4.json b/examples/call-for-papers-mcp/smith/test_cases/disallow/test_case4.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case4.json rename to examples/call-for-papers-mcp/smith/test_cases/disallow/test_case4.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case40.json b/examples/call-for-papers-mcp/smith/test_cases/disallow/test_case40.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case40.json rename to examples/call-for-papers-mcp/smith/test_cases/disallow/test_case40.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case41.json b/examples/call-for-papers-mcp/smith/test_cases/disallow/test_case41.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case41.json rename to examples/call-for-papers-mcp/smith/test_cases/disallow/test_case41.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case42.json b/examples/call-for-papers-mcp/smith/test_cases/disallow/test_case42.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case42.json rename to examples/call-for-papers-mcp/smith/test_cases/disallow/test_case42.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case43.json b/examples/call-for-papers-mcp/smith/test_cases/disallow/test_case43.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case43.json rename to examples/call-for-papers-mcp/smith/test_cases/disallow/test_case43.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case44.json b/examples/call-for-papers-mcp/smith/test_cases/disallow/test_case44.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case44.json rename to examples/call-for-papers-mcp/smith/test_cases/disallow/test_case44.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case45.json b/examples/call-for-papers-mcp/smith/test_cases/disallow/test_case45.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case45.json rename to examples/call-for-papers-mcp/smith/test_cases/disallow/test_case45.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case46.json b/examples/call-for-papers-mcp/smith/test_cases/disallow/test_case46.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case46.json rename to examples/call-for-papers-mcp/smith/test_cases/disallow/test_case46.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case47.json b/examples/call-for-papers-mcp/smith/test_cases/disallow/test_case47.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case47.json rename to examples/call-for-papers-mcp/smith/test_cases/disallow/test_case47.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case48.json b/examples/call-for-papers-mcp/smith/test_cases/disallow/test_case48.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case48.json rename to examples/call-for-papers-mcp/smith/test_cases/disallow/test_case48.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case49.json b/examples/call-for-papers-mcp/smith/test_cases/disallow/test_case49.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case49.json rename to examples/call-for-papers-mcp/smith/test_cases/disallow/test_case49.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case50.json b/examples/call-for-papers-mcp/smith/test_cases/disallow/test_case50.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case50.json rename to examples/call-for-papers-mcp/smith/test_cases/disallow/test_case50.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case51.json b/examples/call-for-papers-mcp/smith/test_cases/disallow/test_case51.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case51.json rename to examples/call-for-papers-mcp/smith/test_cases/disallow/test_case51.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case52.json b/examples/call-for-papers-mcp/smith/test_cases/disallow/test_case52.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case52.json rename to examples/call-for-papers-mcp/smith/test_cases/disallow/test_case52.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case53.json b/examples/call-for-papers-mcp/smith/test_cases/disallow/test_case53.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case53.json rename to examples/call-for-papers-mcp/smith/test_cases/disallow/test_case53.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case55.json b/examples/call-for-papers-mcp/smith/test_cases/disallow/test_case55.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case55.json rename to examples/call-for-papers-mcp/smith/test_cases/disallow/test_case55.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case56.json b/examples/call-for-papers-mcp/smith/test_cases/disallow/test_case56.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case56.json rename to examples/call-for-papers-mcp/smith/test_cases/disallow/test_case56.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case59.json b/examples/call-for-papers-mcp/smith/test_cases/disallow/test_case59.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case59.json rename to examples/call-for-papers-mcp/smith/test_cases/disallow/test_case59.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case60.json b/examples/call-for-papers-mcp/smith/test_cases/disallow/test_case60.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case60.json rename to examples/call-for-papers-mcp/smith/test_cases/disallow/test_case60.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case62.json b/examples/call-for-papers-mcp/smith/test_cases/disallow/test_case62.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case62.json rename to examples/call-for-papers-mcp/smith/test_cases/disallow/test_case62.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case65.json b/examples/call-for-papers-mcp/smith/test_cases/disallow/test_case65.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case65.json rename to examples/call-for-papers-mcp/smith/test_cases/disallow/test_case65.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case66.json b/examples/call-for-papers-mcp/smith/test_cases/disallow/test_case66.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case66.json rename to examples/call-for-papers-mcp/smith/test_cases/disallow/test_case66.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case67.json b/examples/call-for-papers-mcp/smith/test_cases/disallow/test_case67.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case67.json rename to examples/call-for-papers-mcp/smith/test_cases/disallow/test_case67.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case68.json b/examples/call-for-papers-mcp/smith/test_cases/disallow/test_case68.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case68.json rename to examples/call-for-papers-mcp/smith/test_cases/disallow/test_case68.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case69.json b/examples/call-for-papers-mcp/smith/test_cases/disallow/test_case69.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case69.json rename to examples/call-for-papers-mcp/smith/test_cases/disallow/test_case69.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case70.json b/examples/call-for-papers-mcp/smith/test_cases/disallow/test_case70.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case70.json rename to examples/call-for-papers-mcp/smith/test_cases/disallow/test_case70.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case71.json b/examples/call-for-papers-mcp/smith/test_cases/disallow/test_case71.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case71.json rename to examples/call-for-papers-mcp/smith/test_cases/disallow/test_case71.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case72.json b/examples/call-for-papers-mcp/smith/test_cases/disallow/test_case72.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case72.json rename to examples/call-for-papers-mcp/smith/test_cases/disallow/test_case72.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case73.json b/examples/call-for-papers-mcp/smith/test_cases/disallow/test_case73.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case73.json rename to examples/call-for-papers-mcp/smith/test_cases/disallow/test_case73.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case74.json b/examples/call-for-papers-mcp/smith/test_cases/disallow/test_case74.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case74.json rename to examples/call-for-papers-mcp/smith/test_cases/disallow/test_case74.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case75.json b/examples/call-for-papers-mcp/smith/test_cases/disallow/test_case75.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case75.json rename to examples/call-for-papers-mcp/smith/test_cases/disallow/test_case75.json diff --git a/mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case76.json b/examples/call-for-papers-mcp/smith/test_cases/disallow/test_case76.json similarity index 100% rename from mcp_servers/call-for-papers-mcp/smith/test_cases/disallow/test_case76.json rename to examples/call-for-papers-mcp/smith/test_cases/disallow/test_case76.json diff --git a/mcp_servers/call-for-papers-mcp/smithery.yaml b/examples/call-for-papers-mcp/smithery.yaml similarity index 100% rename from mcp_servers/call-for-papers-mcp/smithery.yaml rename to examples/call-for-papers-mcp/smithery.yaml diff --git a/mcp_servers/car-price-mcp-main/README.md b/examples/car-price-mcp-main/README.md similarity index 92% rename from mcp_servers/car-price-mcp-main/README.md rename to examples/car-price-mcp-main/README.md index b4fe411..896fcdf 100644 --- a/mcp_servers/car-price-mcp-main/README.md +++ b/examples/car-price-mcp-main/README.md @@ -23,7 +23,7 @@ ollama pull qwen3.5 Start the agent: ```bash -cd mcp_servers/car-price-mcp-main +cd examples/car-price-mcp-main pip install -r requirements.txt uvicorn agent:app --host 0.0.0.0 --port 9000 ``` @@ -65,15 +65,15 @@ Default configuration (in `.env`): Make sure your `.env` points to this example: ``` -TARGET_AGENT_PATH=mcp_servers/car-price-mcp-main/ -GUIDANCE_FILE=mcp_servers/car-price-mcp-main/smith/guidance.txt -SYSTEM_VAR_FILE=mcp_servers/car-price-mcp-main/smith/system_vars.json -PROMPTFOO_CONFIG_FILE=mcp_servers/car-price-mcp-main/smith/promptfooconfig.yaml -PROMPTFOO_OUTPUT_FILE=mcp_servers/car-price-mcp-main/smith/redteam.yaml +TARGET_AGENT_PATH=examples/car-price-mcp-main/ +GUIDANCE_FILE=examples/car-price-mcp-main/smith/guidance.txt +SYSTEM_VAR_FILE=examples/car-price-mcp-main/smith/system_vars.json +PROMPTFOO_CONFIG_FILE=examples/car-price-mcp-main/smith/promptfooconfig.yaml +PROMPTFOO_OUTPUT_FILE=examples/car-price-mcp-main/smith/redteam.yaml MCP_TRANSPORT=stdio MCP_COMMAND=python MCP_ARGS=server.py -MCP_CWD=mcp_servers/car-price-mcp-main +MCP_CWD=examples/car-price-mcp-main ``` ## How to Test Smith (End-to-End Workflow) diff --git a/mcp_servers/car-price-mcp-main/agent.py b/examples/car-price-mcp-main/agent.py similarity index 100% rename from mcp_servers/car-price-mcp-main/agent.py rename to examples/car-price-mcp-main/agent.py diff --git a/mcp_servers/car-price-mcp-main/app.py b/examples/car-price-mcp-main/app.py similarity index 100% rename from mcp_servers/car-price-mcp-main/app.py rename to examples/car-price-mcp-main/app.py diff --git a/mcp_servers/car-price-mcp-main/redteam1.yaml b/examples/car-price-mcp-main/redteam1.yaml similarity index 100% rename from mcp_servers/car-price-mcp-main/redteam1.yaml rename to examples/car-price-mcp-main/redteam1.yaml diff --git a/mcp_servers/car-price-mcp-main/requirements.txt b/examples/car-price-mcp-main/requirements.txt similarity index 100% rename from mcp_servers/car-price-mcp-main/requirements.txt rename to examples/car-price-mcp-main/requirements.txt diff --git a/mcp_servers/car-price-mcp-main/server.py b/examples/car-price-mcp-main/server.py similarity index 100% rename from mcp_servers/car-price-mcp-main/server.py rename to examples/car-price-mcp-main/server.py diff --git a/mcp_servers/car-price-mcp-main/smith/guidance.txt b/examples/car-price-mcp-main/smith/guidance.txt similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/guidance.txt rename to examples/car-price-mcp-main/smith/guidance.txt diff --git a/mcp_servers/car-price-mcp-main/smith/promptfooconfig.yaml b/examples/car-price-mcp-main/smith/promptfooconfig.yaml similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/promptfooconfig.yaml rename to examples/car-price-mcp-main/smith/promptfooconfig.yaml diff --git a/mcp_servers/car-price-mcp-main/smith/redteam.yaml b/examples/car-price-mcp-main/smith/redteam.yaml similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/redteam.yaml rename to examples/car-price-mcp-main/smith/redteam.yaml diff --git a/mcp_servers/car-price-mcp-main/smith/smith_outputs/defect_summary.txt b/examples/car-price-mcp-main/smith/smith_outputs/defect_summary.txt similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/smith_outputs/defect_summary.txt rename to examples/car-price-mcp-main/smith/smith_outputs/defect_summary.txt diff --git a/mcp_servers/car-price-mcp-main/smith/smith_outputs/policy_defect.rego b/examples/car-price-mcp-main/smith/smith_outputs/policy_defect.rego similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/smith_outputs/policy_defect.rego rename to examples/car-price-mcp-main/smith/smith_outputs/policy_defect.rego diff --git a/mcp_servers/car-price-mcp-main/smith/smith_outputs/policy_generated.rego b/examples/car-price-mcp-main/smith/smith_outputs/policy_generated.rego similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/smith_outputs/policy_generated.rego rename to examples/car-price-mcp-main/smith/smith_outputs/policy_generated.rego diff --git a/mcp_servers/car-price-mcp-main/smith/smith_outputs/policy_revised.rego b/examples/car-price-mcp-main/smith/smith_outputs/policy_revised.rego similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/smith_outputs/policy_revised.rego rename to examples/car-price-mcp-main/smith/smith_outputs/policy_revised.rego diff --git a/mcp_servers/car-price-mcp-main/smith/smith_outputs/tool_definitions.json b/examples/car-price-mcp-main/smith/smith_outputs/tool_definitions.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/smith_outputs/tool_definitions.json rename to examples/car-price-mcp-main/smith/smith_outputs/tool_definitions.json diff --git a/mcp_servers/car-price-mcp-main/smith/system_vars.json b/examples/car-price-mcp-main/smith/system_vars.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/system_vars.json rename to examples/car-price-mcp-main/smith/system_vars.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case0.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case0.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case0.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case0.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case1.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case1.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case1.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case1.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case10.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case10.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case10.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case10.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case100.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case100.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case100.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case100.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case101.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case101.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case101.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case101.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case102.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case102.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case102.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case102.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case103.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case103.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case103.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case103.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case104.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case104.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case104.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case104.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case105.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case105.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case105.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case105.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case106.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case106.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case106.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case106.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case107.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case107.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case107.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case107.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case108.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case108.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case108.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case108.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case109.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case109.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case109.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case109.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case11.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case11.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case11.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case11.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case110.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case110.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case110.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case110.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case111.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case111.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case111.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case111.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case112.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case112.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case112.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case112.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case113.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case113.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case113.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case113.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case114.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case114.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case114.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case114.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case115.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case115.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case115.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case115.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case116.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case116.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case116.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case116.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case117.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case117.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case117.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case117.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case118.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case118.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case118.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case118.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case119.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case119.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case119.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case119.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case12.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case12.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case12.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case12.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case120.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case120.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case120.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case120.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case121.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case121.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case121.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case121.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case122.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case122.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case122.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case122.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case123.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case123.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case123.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case123.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case124.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case124.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case124.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case124.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case125.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case125.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case125.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case125.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case126.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case126.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case126.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case126.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case127.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case127.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case127.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case127.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case128.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case128.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case128.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case128.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case129.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case129.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case129.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case129.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case130.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case130.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case130.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case130.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case14.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case14.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case14.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case14.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case17.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case17.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case17.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case17.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case18.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case18.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case18.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case18.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case19.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case19.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case19.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case19.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case2.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case2.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case2.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case2.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case20.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case20.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case20.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case20.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case22.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case22.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case22.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case22.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case24.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case24.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case24.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case24.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case25.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case25.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case25.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case25.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case26.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case26.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case26.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case26.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case27.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case27.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case27.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case27.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case28.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case28.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case28.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case28.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case29.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case29.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case29.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case29.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case3.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case3.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case3.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case3.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case33.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case33.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case33.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case33.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case34.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case34.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case34.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case34.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case35.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case35.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case35.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case35.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case36.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case36.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case36.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case36.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case37.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case37.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case37.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case37.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case38.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case38.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case38.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case38.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case39.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case39.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case39.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case39.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case40.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case40.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case40.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case40.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case41.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case41.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case41.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case41.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case42.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case42.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case42.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case42.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case43.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case43.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case43.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case43.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case44.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case44.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case44.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case44.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case45.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case45.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case45.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case45.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case46.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case46.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case46.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case46.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case47.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case47.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case47.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case47.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case48.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case48.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case48.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case48.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case49.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case49.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case49.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case49.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case5.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case5.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case5.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case5.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case50.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case50.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case50.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case50.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case51.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case51.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case51.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case51.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case52.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case52.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case52.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case52.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case53.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case53.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case53.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case53.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case54.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case54.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case54.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case54.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case55.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case55.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case55.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case55.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case56.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case56.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case56.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case56.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case57.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case57.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case57.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case57.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case58.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case58.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case58.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case58.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case59.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case59.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case59.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case59.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case6.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case6.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case6.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case6.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case60.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case60.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case60.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case60.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case61.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case61.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case61.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case61.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case62.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case62.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case62.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case62.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case63.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case63.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case63.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case63.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case64.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case64.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case64.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case64.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case65.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case65.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case65.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case65.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case66.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case66.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case66.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case66.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case67.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case67.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case67.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case67.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case68.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case68.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case68.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case68.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case69.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case69.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case69.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case69.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case7.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case7.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case7.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case7.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case70.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case70.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case70.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case70.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case71.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case71.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case71.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case71.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case72.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case72.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case72.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case72.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case73.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case73.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case73.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case73.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case74.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case74.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case74.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case74.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case75.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case75.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case75.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case75.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case76.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case76.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case76.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case76.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case77.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case77.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case77.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case77.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case78.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case78.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case78.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case78.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case79.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case79.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case79.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case79.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case8.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case8.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case8.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case8.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case80.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case80.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case80.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case80.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case81.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case81.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case81.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case81.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case82.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case82.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case82.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case82.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case83.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case83.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case83.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case83.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case84.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case84.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case84.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case84.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case85.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case85.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case85.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case85.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case86.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case86.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case86.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case86.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case87.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case87.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case87.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case87.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case88.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case88.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case88.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case88.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case89.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case89.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case89.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case89.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case9.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case9.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case9.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case9.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case90.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case90.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case90.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case90.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case91.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case91.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case91.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case91.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case92.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case92.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case92.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case92.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case93.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case93.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case93.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case93.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case94.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case94.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case94.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case94.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case95.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case95.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case95.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case95.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case96.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case96.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case96.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case96.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case97.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case97.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case97.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case97.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case98.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case98.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case98.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case98.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case99.json b/examples/car-price-mcp-main/smith/test_cases/allow/test_case99.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/allow/test_case99.json rename to examples/car-price-mcp-main/smith/test_cases/allow/test_case99.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case10.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case10.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case10.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case10.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case100.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case100.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case100.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case100.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case101.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case101.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case101.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case101.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case102.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case102.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case102.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case102.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case103.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case103.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case103.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case103.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case104.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case104.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case104.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case104.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case105.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case105.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case105.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case105.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case106.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case106.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case106.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case106.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case107.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case107.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case107.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case107.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case108.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case108.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case108.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case108.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case109.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case109.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case109.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case109.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case11.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case11.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case11.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case11.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case110.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case110.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case110.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case110.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case111.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case111.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case111.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case111.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case112.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case112.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case112.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case112.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case113.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case113.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case113.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case113.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case114.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case114.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case114.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case114.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case115.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case115.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case115.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case115.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case116.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case116.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case116.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case116.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case117.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case117.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case117.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case117.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case118.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case118.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case118.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case118.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case119.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case119.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case119.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case119.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case12.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case12.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case12.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case12.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case120.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case120.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case120.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case120.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case121.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case121.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case121.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case121.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case122.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case122.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case122.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case122.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case123.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case123.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case123.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case123.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case128.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case128.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case128.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case128.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case129.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case129.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case129.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case129.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case13.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case13.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case13.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case13.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case130.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case130.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case130.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case130.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case131.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case131.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case131.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case131.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case132.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case132.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case132.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case132.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case14.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case14.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case14.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case14.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case15.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case15.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case15.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case15.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case16.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case16.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case16.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case16.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case17.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case17.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case17.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case17.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case18.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case18.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case18.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case18.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case19.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case19.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case19.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case19.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case20.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case20.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case20.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case20.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case21.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case21.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case21.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case21.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case22.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case22.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case22.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case22.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case23.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case23.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case23.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case23.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case24.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case24.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case24.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case24.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case25.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case25.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case25.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case25.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case26.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case26.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case26.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case26.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case27.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case27.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case27.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case27.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case28.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case28.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case28.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case28.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case29.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case29.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case29.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case29.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case30.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case30.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case30.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case30.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case31.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case31.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case31.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case31.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case32.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case32.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case32.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case32.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case33.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case33.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case33.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case33.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case34.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case34.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case34.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case34.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case35.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case35.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case35.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case35.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case36.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case36.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case36.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case36.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case37.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case37.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case37.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case37.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case38.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case38.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case38.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case38.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case39.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case39.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case39.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case39.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case4.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case4.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case4.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case4.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case40.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case40.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case40.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case40.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case41.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case41.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case41.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case41.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case42.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case42.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case42.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case42.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case43.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case43.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case43.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case43.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case44.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case44.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case44.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case44.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case45.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case45.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case45.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case45.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case46.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case46.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case46.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case46.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case47.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case47.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case47.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case47.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case48.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case48.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case48.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case48.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case49.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case49.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case49.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case49.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case5.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case5.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case5.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case5.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case50.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case50.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case50.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case50.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case51.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case51.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case51.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case51.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case52.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case52.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case52.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case52.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case53.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case53.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case53.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case53.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case54.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case54.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case54.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case54.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case55.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case55.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case55.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case55.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case56.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case56.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case56.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case56.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case57.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case57.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case57.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case57.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case58.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case58.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case58.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case58.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case59.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case59.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case59.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case59.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case6.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case6.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case6.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case6.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case60.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case60.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case60.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case60.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case61.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case61.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case61.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case61.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case62.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case62.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case62.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case62.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case63.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case63.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case63.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case63.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case64.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case64.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case64.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case64.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case65.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case65.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case65.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case65.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case66.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case66.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case66.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case66.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case67.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case67.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case67.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case67.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case68.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case68.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case68.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case68.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case69.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case69.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case69.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case69.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case7.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case7.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case7.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case7.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case70.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case70.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case70.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case70.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case71.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case71.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case71.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case71.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case72.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case72.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case72.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case72.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case73.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case73.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case73.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case73.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case74.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case74.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case74.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case74.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case75.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case75.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case75.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case75.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case76.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case76.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case76.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case76.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case77.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case77.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case77.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case77.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case78.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case78.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case78.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case78.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case79.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case79.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case79.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case79.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case8.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case8.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case8.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case8.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case80.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case80.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case80.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case80.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case81.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case81.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case81.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case81.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case82.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case82.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case82.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case82.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case83.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case83.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case83.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case83.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case84.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case84.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case84.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case84.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case85.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case85.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case85.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case85.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case86.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case86.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case86.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case86.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case87.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case87.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case87.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case87.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case88.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case88.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case88.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case88.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case89.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case89.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case89.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case89.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case9.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case9.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case9.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case9.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case90.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case90.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case90.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case90.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case91.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case91.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case91.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case91.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case92.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case92.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case92.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case92.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case93.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case93.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case93.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case93.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case94.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case94.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case94.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case94.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case95.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case95.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case95.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case95.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case96.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case96.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case96.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case96.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case97.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case97.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case97.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case97.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case98.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case98.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case98.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case98.json diff --git a/mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case99.json b/examples/car-price-mcp-main/smith/test_cases/disallow/test_case99.json similarity index 100% rename from mcp_servers/car-price-mcp-main/smith/test_cases/disallow/test_case99.json rename to examples/car-price-mcp-main/smith/test_cases/disallow/test_case99.json diff --git a/mcp_servers/car-price-mcp-main/smithery.yaml b/examples/car-price-mcp-main/smithery.yaml similarity index 100% rename from mcp_servers/car-price-mcp-main/smithery.yaml rename to examples/car-price-mcp-main/smithery.yaml diff --git a/mcp_servers/sre/smith/policy.rego b/examples/sre/smith/policy.rego similarity index 100% rename from mcp_servers/sre/smith/policy.rego rename to examples/sre/smith/policy.rego diff --git a/mcp_servers/sre/smith/policy_fixed.rego b/examples/sre/smith/policy_fixed.rego similarity index 100% rename from mcp_servers/sre/smith/policy_fixed.rego rename to examples/sre/smith/policy_fixed.rego diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command1.json b/examples/sre/smith/test_cases/allow/processed_command1.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command1.json rename to examples/sre/smith/test_cases/allow/processed_command1.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command10.json b/examples/sre/smith/test_cases/allow/processed_command10.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command10.json rename to examples/sre/smith/test_cases/allow/processed_command10.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command101.json b/examples/sre/smith/test_cases/allow/processed_command101.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command101.json rename to examples/sre/smith/test_cases/allow/processed_command101.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command102.json b/examples/sre/smith/test_cases/allow/processed_command102.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command102.json rename to examples/sre/smith/test_cases/allow/processed_command102.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command103.json b/examples/sre/smith/test_cases/allow/processed_command103.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command103.json rename to examples/sre/smith/test_cases/allow/processed_command103.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command104.json b/examples/sre/smith/test_cases/allow/processed_command104.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command104.json rename to examples/sre/smith/test_cases/allow/processed_command104.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command105.json b/examples/sre/smith/test_cases/allow/processed_command105.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command105.json rename to examples/sre/smith/test_cases/allow/processed_command105.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command106.json b/examples/sre/smith/test_cases/allow/processed_command106.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command106.json rename to examples/sre/smith/test_cases/allow/processed_command106.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command107.json b/examples/sre/smith/test_cases/allow/processed_command107.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command107.json rename to examples/sre/smith/test_cases/allow/processed_command107.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command108.json b/examples/sre/smith/test_cases/allow/processed_command108.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command108.json rename to examples/sre/smith/test_cases/allow/processed_command108.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command11.json b/examples/sre/smith/test_cases/allow/processed_command11.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command11.json rename to examples/sre/smith/test_cases/allow/processed_command11.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command110.json b/examples/sre/smith/test_cases/allow/processed_command110.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command110.json rename to examples/sre/smith/test_cases/allow/processed_command110.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command112.json b/examples/sre/smith/test_cases/allow/processed_command112.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command112.json rename to examples/sre/smith/test_cases/allow/processed_command112.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command114.json b/examples/sre/smith/test_cases/allow/processed_command114.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command114.json rename to examples/sre/smith/test_cases/allow/processed_command114.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command115.json b/examples/sre/smith/test_cases/allow/processed_command115.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command115.json rename to examples/sre/smith/test_cases/allow/processed_command115.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command116.json b/examples/sre/smith/test_cases/allow/processed_command116.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command116.json rename to examples/sre/smith/test_cases/allow/processed_command116.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command117.json b/examples/sre/smith/test_cases/allow/processed_command117.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command117.json rename to examples/sre/smith/test_cases/allow/processed_command117.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command118.json b/examples/sre/smith/test_cases/allow/processed_command118.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command118.json rename to examples/sre/smith/test_cases/allow/processed_command118.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command119.json b/examples/sre/smith/test_cases/allow/processed_command119.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command119.json rename to examples/sre/smith/test_cases/allow/processed_command119.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command12.json b/examples/sre/smith/test_cases/allow/processed_command12.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command12.json rename to examples/sre/smith/test_cases/allow/processed_command12.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command120.json b/examples/sre/smith/test_cases/allow/processed_command120.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command120.json rename to examples/sre/smith/test_cases/allow/processed_command120.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command121.json b/examples/sre/smith/test_cases/allow/processed_command121.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command121.json rename to examples/sre/smith/test_cases/allow/processed_command121.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command123.json b/examples/sre/smith/test_cases/allow/processed_command123.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command123.json rename to examples/sre/smith/test_cases/allow/processed_command123.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command124.json b/examples/sre/smith/test_cases/allow/processed_command124.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command124.json rename to examples/sre/smith/test_cases/allow/processed_command124.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command125.json b/examples/sre/smith/test_cases/allow/processed_command125.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command125.json rename to examples/sre/smith/test_cases/allow/processed_command125.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command126.json b/examples/sre/smith/test_cases/allow/processed_command126.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command126.json rename to examples/sre/smith/test_cases/allow/processed_command126.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command127.json b/examples/sre/smith/test_cases/allow/processed_command127.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command127.json rename to examples/sre/smith/test_cases/allow/processed_command127.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command129.json b/examples/sre/smith/test_cases/allow/processed_command129.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command129.json rename to examples/sre/smith/test_cases/allow/processed_command129.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command13.json b/examples/sre/smith/test_cases/allow/processed_command13.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command13.json rename to examples/sre/smith/test_cases/allow/processed_command13.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command130.json b/examples/sre/smith/test_cases/allow/processed_command130.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command130.json rename to examples/sre/smith/test_cases/allow/processed_command130.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command131.json b/examples/sre/smith/test_cases/allow/processed_command131.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command131.json rename to examples/sre/smith/test_cases/allow/processed_command131.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command132.json b/examples/sre/smith/test_cases/allow/processed_command132.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command132.json rename to examples/sre/smith/test_cases/allow/processed_command132.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command133.json b/examples/sre/smith/test_cases/allow/processed_command133.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command133.json rename to examples/sre/smith/test_cases/allow/processed_command133.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command134.json b/examples/sre/smith/test_cases/allow/processed_command134.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command134.json rename to examples/sre/smith/test_cases/allow/processed_command134.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command135.json b/examples/sre/smith/test_cases/allow/processed_command135.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command135.json rename to examples/sre/smith/test_cases/allow/processed_command135.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command136.json b/examples/sre/smith/test_cases/allow/processed_command136.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command136.json rename to examples/sre/smith/test_cases/allow/processed_command136.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command137.json b/examples/sre/smith/test_cases/allow/processed_command137.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command137.json rename to examples/sre/smith/test_cases/allow/processed_command137.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command138.json b/examples/sre/smith/test_cases/allow/processed_command138.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command138.json rename to examples/sre/smith/test_cases/allow/processed_command138.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command139.json b/examples/sre/smith/test_cases/allow/processed_command139.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command139.json rename to examples/sre/smith/test_cases/allow/processed_command139.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command14.json b/examples/sre/smith/test_cases/allow/processed_command14.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command14.json rename to examples/sre/smith/test_cases/allow/processed_command14.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command140.json b/examples/sre/smith/test_cases/allow/processed_command140.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command140.json rename to examples/sre/smith/test_cases/allow/processed_command140.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command141.json b/examples/sre/smith/test_cases/allow/processed_command141.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command141.json rename to examples/sre/smith/test_cases/allow/processed_command141.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command142.json b/examples/sre/smith/test_cases/allow/processed_command142.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command142.json rename to examples/sre/smith/test_cases/allow/processed_command142.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command143.json b/examples/sre/smith/test_cases/allow/processed_command143.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command143.json rename to examples/sre/smith/test_cases/allow/processed_command143.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command145.json b/examples/sre/smith/test_cases/allow/processed_command145.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command145.json rename to examples/sre/smith/test_cases/allow/processed_command145.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command146.json b/examples/sre/smith/test_cases/allow/processed_command146.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command146.json rename to examples/sre/smith/test_cases/allow/processed_command146.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command147.json b/examples/sre/smith/test_cases/allow/processed_command147.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command147.json rename to examples/sre/smith/test_cases/allow/processed_command147.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command148.json b/examples/sre/smith/test_cases/allow/processed_command148.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command148.json rename to examples/sre/smith/test_cases/allow/processed_command148.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command149.json b/examples/sre/smith/test_cases/allow/processed_command149.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command149.json rename to examples/sre/smith/test_cases/allow/processed_command149.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command15.json b/examples/sre/smith/test_cases/allow/processed_command15.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command15.json rename to examples/sre/smith/test_cases/allow/processed_command15.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command151.json b/examples/sre/smith/test_cases/allow/processed_command151.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command151.json rename to examples/sre/smith/test_cases/allow/processed_command151.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command152.json b/examples/sre/smith/test_cases/allow/processed_command152.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command152.json rename to examples/sre/smith/test_cases/allow/processed_command152.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command153.json b/examples/sre/smith/test_cases/allow/processed_command153.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command153.json rename to examples/sre/smith/test_cases/allow/processed_command153.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command154.json b/examples/sre/smith/test_cases/allow/processed_command154.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command154.json rename to examples/sre/smith/test_cases/allow/processed_command154.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command155.json b/examples/sre/smith/test_cases/allow/processed_command155.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command155.json rename to examples/sre/smith/test_cases/allow/processed_command155.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command156.json b/examples/sre/smith/test_cases/allow/processed_command156.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command156.json rename to examples/sre/smith/test_cases/allow/processed_command156.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command157.json b/examples/sre/smith/test_cases/allow/processed_command157.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command157.json rename to examples/sre/smith/test_cases/allow/processed_command157.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command158.json b/examples/sre/smith/test_cases/allow/processed_command158.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command158.json rename to examples/sre/smith/test_cases/allow/processed_command158.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command159.json b/examples/sre/smith/test_cases/allow/processed_command159.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command159.json rename to examples/sre/smith/test_cases/allow/processed_command159.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command16.json b/examples/sre/smith/test_cases/allow/processed_command16.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command16.json rename to examples/sre/smith/test_cases/allow/processed_command16.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command160.json b/examples/sre/smith/test_cases/allow/processed_command160.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command160.json rename to examples/sre/smith/test_cases/allow/processed_command160.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command161.json b/examples/sre/smith/test_cases/allow/processed_command161.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command161.json rename to examples/sre/smith/test_cases/allow/processed_command161.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command162.json b/examples/sre/smith/test_cases/allow/processed_command162.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command162.json rename to examples/sre/smith/test_cases/allow/processed_command162.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command164.json b/examples/sre/smith/test_cases/allow/processed_command164.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command164.json rename to examples/sre/smith/test_cases/allow/processed_command164.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command165.json b/examples/sre/smith/test_cases/allow/processed_command165.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command165.json rename to examples/sre/smith/test_cases/allow/processed_command165.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command166.json b/examples/sre/smith/test_cases/allow/processed_command166.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command166.json rename to examples/sre/smith/test_cases/allow/processed_command166.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command168.json b/examples/sre/smith/test_cases/allow/processed_command168.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command168.json rename to examples/sre/smith/test_cases/allow/processed_command168.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command169.json b/examples/sre/smith/test_cases/allow/processed_command169.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command169.json rename to examples/sre/smith/test_cases/allow/processed_command169.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command17.json b/examples/sre/smith/test_cases/allow/processed_command17.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command17.json rename to examples/sre/smith/test_cases/allow/processed_command17.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command170.json b/examples/sre/smith/test_cases/allow/processed_command170.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command170.json rename to examples/sre/smith/test_cases/allow/processed_command170.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command171.json b/examples/sre/smith/test_cases/allow/processed_command171.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command171.json rename to examples/sre/smith/test_cases/allow/processed_command171.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command172.json b/examples/sre/smith/test_cases/allow/processed_command172.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command172.json rename to examples/sre/smith/test_cases/allow/processed_command172.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command173.json b/examples/sre/smith/test_cases/allow/processed_command173.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command173.json rename to examples/sre/smith/test_cases/allow/processed_command173.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command174.json b/examples/sre/smith/test_cases/allow/processed_command174.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command174.json rename to examples/sre/smith/test_cases/allow/processed_command174.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command175.json b/examples/sre/smith/test_cases/allow/processed_command175.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command175.json rename to examples/sre/smith/test_cases/allow/processed_command175.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command176.json b/examples/sre/smith/test_cases/allow/processed_command176.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command176.json rename to examples/sre/smith/test_cases/allow/processed_command176.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command177.json b/examples/sre/smith/test_cases/allow/processed_command177.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command177.json rename to examples/sre/smith/test_cases/allow/processed_command177.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command178.json b/examples/sre/smith/test_cases/allow/processed_command178.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command178.json rename to examples/sre/smith/test_cases/allow/processed_command178.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command179.json b/examples/sre/smith/test_cases/allow/processed_command179.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command179.json rename to examples/sre/smith/test_cases/allow/processed_command179.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command18.json b/examples/sre/smith/test_cases/allow/processed_command18.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command18.json rename to examples/sre/smith/test_cases/allow/processed_command18.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command181.json b/examples/sre/smith/test_cases/allow/processed_command181.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command181.json rename to examples/sre/smith/test_cases/allow/processed_command181.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command182.json b/examples/sre/smith/test_cases/allow/processed_command182.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command182.json rename to examples/sre/smith/test_cases/allow/processed_command182.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command183.json b/examples/sre/smith/test_cases/allow/processed_command183.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command183.json rename to examples/sre/smith/test_cases/allow/processed_command183.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command184.json b/examples/sre/smith/test_cases/allow/processed_command184.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command184.json rename to examples/sre/smith/test_cases/allow/processed_command184.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command185.json b/examples/sre/smith/test_cases/allow/processed_command185.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command185.json rename to examples/sre/smith/test_cases/allow/processed_command185.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command186.json b/examples/sre/smith/test_cases/allow/processed_command186.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command186.json rename to examples/sre/smith/test_cases/allow/processed_command186.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command187.json b/examples/sre/smith/test_cases/allow/processed_command187.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command187.json rename to examples/sre/smith/test_cases/allow/processed_command187.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command189.json b/examples/sre/smith/test_cases/allow/processed_command189.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command189.json rename to examples/sre/smith/test_cases/allow/processed_command189.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command19.json b/examples/sre/smith/test_cases/allow/processed_command19.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command19.json rename to examples/sre/smith/test_cases/allow/processed_command19.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command190.json b/examples/sre/smith/test_cases/allow/processed_command190.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command190.json rename to examples/sre/smith/test_cases/allow/processed_command190.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command191.json b/examples/sre/smith/test_cases/allow/processed_command191.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command191.json rename to examples/sre/smith/test_cases/allow/processed_command191.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command192.json b/examples/sre/smith/test_cases/allow/processed_command192.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command192.json rename to examples/sre/smith/test_cases/allow/processed_command192.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command195.json b/examples/sre/smith/test_cases/allow/processed_command195.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command195.json rename to examples/sre/smith/test_cases/allow/processed_command195.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command196.json b/examples/sre/smith/test_cases/allow/processed_command196.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command196.json rename to examples/sre/smith/test_cases/allow/processed_command196.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command197.json b/examples/sre/smith/test_cases/allow/processed_command197.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command197.json rename to examples/sre/smith/test_cases/allow/processed_command197.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command198.json b/examples/sre/smith/test_cases/allow/processed_command198.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command198.json rename to examples/sre/smith/test_cases/allow/processed_command198.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command199.json b/examples/sre/smith/test_cases/allow/processed_command199.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command199.json rename to examples/sre/smith/test_cases/allow/processed_command199.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command2.json b/examples/sre/smith/test_cases/allow/processed_command2.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command2.json rename to examples/sre/smith/test_cases/allow/processed_command2.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command20.json b/examples/sre/smith/test_cases/allow/processed_command20.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command20.json rename to examples/sre/smith/test_cases/allow/processed_command20.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command200.json b/examples/sre/smith/test_cases/allow/processed_command200.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command200.json rename to examples/sre/smith/test_cases/allow/processed_command200.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command201.json b/examples/sre/smith/test_cases/allow/processed_command201.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command201.json rename to examples/sre/smith/test_cases/allow/processed_command201.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command202.json b/examples/sre/smith/test_cases/allow/processed_command202.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command202.json rename to examples/sre/smith/test_cases/allow/processed_command202.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command21.json b/examples/sre/smith/test_cases/allow/processed_command21.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command21.json rename to examples/sre/smith/test_cases/allow/processed_command21.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command22.json b/examples/sre/smith/test_cases/allow/processed_command22.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command22.json rename to examples/sre/smith/test_cases/allow/processed_command22.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command23.json b/examples/sre/smith/test_cases/allow/processed_command23.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command23.json rename to examples/sre/smith/test_cases/allow/processed_command23.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command24.json b/examples/sre/smith/test_cases/allow/processed_command24.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command24.json rename to examples/sre/smith/test_cases/allow/processed_command24.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command25.json b/examples/sre/smith/test_cases/allow/processed_command25.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command25.json rename to examples/sre/smith/test_cases/allow/processed_command25.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command26.json b/examples/sre/smith/test_cases/allow/processed_command26.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command26.json rename to examples/sre/smith/test_cases/allow/processed_command26.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command27.json b/examples/sre/smith/test_cases/allow/processed_command27.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command27.json rename to examples/sre/smith/test_cases/allow/processed_command27.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command28.json b/examples/sre/smith/test_cases/allow/processed_command28.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command28.json rename to examples/sre/smith/test_cases/allow/processed_command28.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command29.json b/examples/sre/smith/test_cases/allow/processed_command29.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command29.json rename to examples/sre/smith/test_cases/allow/processed_command29.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command3.json b/examples/sre/smith/test_cases/allow/processed_command3.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command3.json rename to examples/sre/smith/test_cases/allow/processed_command3.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command30.json b/examples/sre/smith/test_cases/allow/processed_command30.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command30.json rename to examples/sre/smith/test_cases/allow/processed_command30.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command31.json b/examples/sre/smith/test_cases/allow/processed_command31.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command31.json rename to examples/sre/smith/test_cases/allow/processed_command31.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command32.json b/examples/sre/smith/test_cases/allow/processed_command32.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command32.json rename to examples/sre/smith/test_cases/allow/processed_command32.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command33.json b/examples/sre/smith/test_cases/allow/processed_command33.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command33.json rename to examples/sre/smith/test_cases/allow/processed_command33.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command34.json b/examples/sre/smith/test_cases/allow/processed_command34.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command34.json rename to examples/sre/smith/test_cases/allow/processed_command34.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command35.json b/examples/sre/smith/test_cases/allow/processed_command35.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command35.json rename to examples/sre/smith/test_cases/allow/processed_command35.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command36.json b/examples/sre/smith/test_cases/allow/processed_command36.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command36.json rename to examples/sre/smith/test_cases/allow/processed_command36.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command37.json b/examples/sre/smith/test_cases/allow/processed_command37.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command37.json rename to examples/sre/smith/test_cases/allow/processed_command37.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command38.json b/examples/sre/smith/test_cases/allow/processed_command38.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command38.json rename to examples/sre/smith/test_cases/allow/processed_command38.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command39.json b/examples/sre/smith/test_cases/allow/processed_command39.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command39.json rename to examples/sre/smith/test_cases/allow/processed_command39.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command40.json b/examples/sre/smith/test_cases/allow/processed_command40.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command40.json rename to examples/sre/smith/test_cases/allow/processed_command40.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command41.json b/examples/sre/smith/test_cases/allow/processed_command41.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command41.json rename to examples/sre/smith/test_cases/allow/processed_command41.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command42.json b/examples/sre/smith/test_cases/allow/processed_command42.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command42.json rename to examples/sre/smith/test_cases/allow/processed_command42.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command43.json b/examples/sre/smith/test_cases/allow/processed_command43.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command43.json rename to examples/sre/smith/test_cases/allow/processed_command43.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command44.json b/examples/sre/smith/test_cases/allow/processed_command44.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command44.json rename to examples/sre/smith/test_cases/allow/processed_command44.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command45.json b/examples/sre/smith/test_cases/allow/processed_command45.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command45.json rename to examples/sre/smith/test_cases/allow/processed_command45.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command46.json b/examples/sre/smith/test_cases/allow/processed_command46.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command46.json rename to examples/sre/smith/test_cases/allow/processed_command46.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command47.json b/examples/sre/smith/test_cases/allow/processed_command47.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command47.json rename to examples/sre/smith/test_cases/allow/processed_command47.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command49.json b/examples/sre/smith/test_cases/allow/processed_command49.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command49.json rename to examples/sre/smith/test_cases/allow/processed_command49.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command5.json b/examples/sre/smith/test_cases/allow/processed_command5.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command5.json rename to examples/sre/smith/test_cases/allow/processed_command5.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command50.json b/examples/sre/smith/test_cases/allow/processed_command50.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command50.json rename to examples/sre/smith/test_cases/allow/processed_command50.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command51.json b/examples/sre/smith/test_cases/allow/processed_command51.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command51.json rename to examples/sre/smith/test_cases/allow/processed_command51.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command52.json b/examples/sre/smith/test_cases/allow/processed_command52.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command52.json rename to examples/sre/smith/test_cases/allow/processed_command52.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command53.json b/examples/sre/smith/test_cases/allow/processed_command53.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command53.json rename to examples/sre/smith/test_cases/allow/processed_command53.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command54.json b/examples/sre/smith/test_cases/allow/processed_command54.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command54.json rename to examples/sre/smith/test_cases/allow/processed_command54.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command55.json b/examples/sre/smith/test_cases/allow/processed_command55.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command55.json rename to examples/sre/smith/test_cases/allow/processed_command55.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command56.json b/examples/sre/smith/test_cases/allow/processed_command56.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command56.json rename to examples/sre/smith/test_cases/allow/processed_command56.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command57.json b/examples/sre/smith/test_cases/allow/processed_command57.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command57.json rename to examples/sre/smith/test_cases/allow/processed_command57.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command58.json b/examples/sre/smith/test_cases/allow/processed_command58.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command58.json rename to examples/sre/smith/test_cases/allow/processed_command58.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command59.json b/examples/sre/smith/test_cases/allow/processed_command59.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command59.json rename to examples/sre/smith/test_cases/allow/processed_command59.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command6.json b/examples/sre/smith/test_cases/allow/processed_command6.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command6.json rename to examples/sre/smith/test_cases/allow/processed_command6.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command60.json b/examples/sre/smith/test_cases/allow/processed_command60.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command60.json rename to examples/sre/smith/test_cases/allow/processed_command60.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command62.json b/examples/sre/smith/test_cases/allow/processed_command62.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command62.json rename to examples/sre/smith/test_cases/allow/processed_command62.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command63.json b/examples/sre/smith/test_cases/allow/processed_command63.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command63.json rename to examples/sre/smith/test_cases/allow/processed_command63.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command64.json b/examples/sre/smith/test_cases/allow/processed_command64.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command64.json rename to examples/sre/smith/test_cases/allow/processed_command64.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command65.json b/examples/sre/smith/test_cases/allow/processed_command65.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command65.json rename to examples/sre/smith/test_cases/allow/processed_command65.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command66.json b/examples/sre/smith/test_cases/allow/processed_command66.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command66.json rename to examples/sre/smith/test_cases/allow/processed_command66.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command67.json b/examples/sre/smith/test_cases/allow/processed_command67.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command67.json rename to examples/sre/smith/test_cases/allow/processed_command67.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command68.json b/examples/sre/smith/test_cases/allow/processed_command68.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command68.json rename to examples/sre/smith/test_cases/allow/processed_command68.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command69.json b/examples/sre/smith/test_cases/allow/processed_command69.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command69.json rename to examples/sre/smith/test_cases/allow/processed_command69.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command7.json b/examples/sre/smith/test_cases/allow/processed_command7.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command7.json rename to examples/sre/smith/test_cases/allow/processed_command7.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command70.json b/examples/sre/smith/test_cases/allow/processed_command70.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command70.json rename to examples/sre/smith/test_cases/allow/processed_command70.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command71.json b/examples/sre/smith/test_cases/allow/processed_command71.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command71.json rename to examples/sre/smith/test_cases/allow/processed_command71.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command72.json b/examples/sre/smith/test_cases/allow/processed_command72.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command72.json rename to examples/sre/smith/test_cases/allow/processed_command72.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command73.json b/examples/sre/smith/test_cases/allow/processed_command73.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command73.json rename to examples/sre/smith/test_cases/allow/processed_command73.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command74.json b/examples/sre/smith/test_cases/allow/processed_command74.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command74.json rename to examples/sre/smith/test_cases/allow/processed_command74.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command75.json b/examples/sre/smith/test_cases/allow/processed_command75.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command75.json rename to examples/sre/smith/test_cases/allow/processed_command75.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command76.json b/examples/sre/smith/test_cases/allow/processed_command76.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command76.json rename to examples/sre/smith/test_cases/allow/processed_command76.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command77.json b/examples/sre/smith/test_cases/allow/processed_command77.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command77.json rename to examples/sre/smith/test_cases/allow/processed_command77.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command78.json b/examples/sre/smith/test_cases/allow/processed_command78.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command78.json rename to examples/sre/smith/test_cases/allow/processed_command78.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command79.json b/examples/sre/smith/test_cases/allow/processed_command79.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command79.json rename to examples/sre/smith/test_cases/allow/processed_command79.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command8.json b/examples/sre/smith/test_cases/allow/processed_command8.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command8.json rename to examples/sre/smith/test_cases/allow/processed_command8.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command80.json b/examples/sre/smith/test_cases/allow/processed_command80.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command80.json rename to examples/sre/smith/test_cases/allow/processed_command80.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command82.json b/examples/sre/smith/test_cases/allow/processed_command82.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command82.json rename to examples/sre/smith/test_cases/allow/processed_command82.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command83.json b/examples/sre/smith/test_cases/allow/processed_command83.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command83.json rename to examples/sre/smith/test_cases/allow/processed_command83.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command84.json b/examples/sre/smith/test_cases/allow/processed_command84.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command84.json rename to examples/sre/smith/test_cases/allow/processed_command84.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command85.json b/examples/sre/smith/test_cases/allow/processed_command85.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command85.json rename to examples/sre/smith/test_cases/allow/processed_command85.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command86.json b/examples/sre/smith/test_cases/allow/processed_command86.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command86.json rename to examples/sre/smith/test_cases/allow/processed_command86.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command88.json b/examples/sre/smith/test_cases/allow/processed_command88.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command88.json rename to examples/sre/smith/test_cases/allow/processed_command88.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command89.json b/examples/sre/smith/test_cases/allow/processed_command89.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command89.json rename to examples/sre/smith/test_cases/allow/processed_command89.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command9.json b/examples/sre/smith/test_cases/allow/processed_command9.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command9.json rename to examples/sre/smith/test_cases/allow/processed_command9.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command91.json b/examples/sre/smith/test_cases/allow/processed_command91.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command91.json rename to examples/sre/smith/test_cases/allow/processed_command91.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command92.json b/examples/sre/smith/test_cases/allow/processed_command92.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command92.json rename to examples/sre/smith/test_cases/allow/processed_command92.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command93.json b/examples/sre/smith/test_cases/allow/processed_command93.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command93.json rename to examples/sre/smith/test_cases/allow/processed_command93.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command94.json b/examples/sre/smith/test_cases/allow/processed_command94.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command94.json rename to examples/sre/smith/test_cases/allow/processed_command94.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command95.json b/examples/sre/smith/test_cases/allow/processed_command95.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command95.json rename to examples/sre/smith/test_cases/allow/processed_command95.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command96.json b/examples/sre/smith/test_cases/allow/processed_command96.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command96.json rename to examples/sre/smith/test_cases/allow/processed_command96.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command97.json b/examples/sre/smith/test_cases/allow/processed_command97.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command97.json rename to examples/sre/smith/test_cases/allow/processed_command97.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command98.json b/examples/sre/smith/test_cases/allow/processed_command98.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command98.json rename to examples/sre/smith/test_cases/allow/processed_command98.json diff --git a/mcp_servers/sre/smith/test_cases/allow/processed_command99.json b/examples/sre/smith/test_cases/allow/processed_command99.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/allow/processed_command99.json rename to examples/sre/smith/test_cases/allow/processed_command99.json diff --git a/mcp_servers/sre/smith/test_cases/disallow/attack_shell_injection.json b/examples/sre/smith/test_cases/disallow/attack_shell_injection.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/disallow/attack_shell_injection.json rename to examples/sre/smith/test_cases/disallow/attack_shell_injection.json diff --git a/mcp_servers/sre/smith/test_cases/disallow/malicious_command1.json b/examples/sre/smith/test_cases/disallow/malicious_command1.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/disallow/malicious_command1.json rename to examples/sre/smith/test_cases/disallow/malicious_command1.json diff --git a/mcp_servers/sre/smith/test_cases/disallow/malicious_command10.json b/examples/sre/smith/test_cases/disallow/malicious_command10.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/disallow/malicious_command10.json rename to examples/sre/smith/test_cases/disallow/malicious_command10.json diff --git a/mcp_servers/sre/smith/test_cases/disallow/malicious_command11.json b/examples/sre/smith/test_cases/disallow/malicious_command11.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/disallow/malicious_command11.json rename to examples/sre/smith/test_cases/disallow/malicious_command11.json diff --git a/mcp_servers/sre/smith/test_cases/disallow/malicious_command12.json b/examples/sre/smith/test_cases/disallow/malicious_command12.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/disallow/malicious_command12.json rename to examples/sre/smith/test_cases/disallow/malicious_command12.json diff --git a/mcp_servers/sre/smith/test_cases/disallow/malicious_command13.json b/examples/sre/smith/test_cases/disallow/malicious_command13.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/disallow/malicious_command13.json rename to examples/sre/smith/test_cases/disallow/malicious_command13.json diff --git a/mcp_servers/sre/smith/test_cases/disallow/malicious_command14.json b/examples/sre/smith/test_cases/disallow/malicious_command14.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/disallow/malicious_command14.json rename to examples/sre/smith/test_cases/disallow/malicious_command14.json diff --git a/mcp_servers/sre/smith/test_cases/disallow/malicious_command2.json b/examples/sre/smith/test_cases/disallow/malicious_command2.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/disallow/malicious_command2.json rename to examples/sre/smith/test_cases/disallow/malicious_command2.json diff --git a/mcp_servers/sre/smith/test_cases/disallow/malicious_command3.json b/examples/sre/smith/test_cases/disallow/malicious_command3.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/disallow/malicious_command3.json rename to examples/sre/smith/test_cases/disallow/malicious_command3.json diff --git a/mcp_servers/sre/smith/test_cases/disallow/malicious_command4.json b/examples/sre/smith/test_cases/disallow/malicious_command4.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/disallow/malicious_command4.json rename to examples/sre/smith/test_cases/disallow/malicious_command4.json diff --git a/mcp_servers/sre/smith/test_cases/disallow/malicious_command5.json b/examples/sre/smith/test_cases/disallow/malicious_command5.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/disallow/malicious_command5.json rename to examples/sre/smith/test_cases/disallow/malicious_command5.json diff --git a/mcp_servers/sre/smith/test_cases/disallow/malicious_command6.json b/examples/sre/smith/test_cases/disallow/malicious_command6.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/disallow/malicious_command6.json rename to examples/sre/smith/test_cases/disallow/malicious_command6.json diff --git a/mcp_servers/sre/smith/test_cases/disallow/malicious_command7.json b/examples/sre/smith/test_cases/disallow/malicious_command7.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/disallow/malicious_command7.json rename to examples/sre/smith/test_cases/disallow/malicious_command7.json diff --git a/mcp_servers/sre/smith/test_cases/disallow/malicious_command8.json b/examples/sre/smith/test_cases/disallow/malicious_command8.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/disallow/malicious_command8.json rename to examples/sre/smith/test_cases/disallow/malicious_command8.json diff --git a/mcp_servers/sre/smith/test_cases/disallow/malicious_command9.json b/examples/sre/smith/test_cases/disallow/malicious_command9.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/disallow/malicious_command9.json rename to examples/sre/smith/test_cases/disallow/malicious_command9.json diff --git a/mcp_servers/sre/smith/test_cases/disallow/processed_command1.json b/examples/sre/smith/test_cases/disallow/processed_command1.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/disallow/processed_command1.json rename to examples/sre/smith/test_cases/disallow/processed_command1.json diff --git a/mcp_servers/sre/smith/test_cases/disallow/processed_command100.json b/examples/sre/smith/test_cases/disallow/processed_command100.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/disallow/processed_command100.json rename to examples/sre/smith/test_cases/disallow/processed_command100.json diff --git a/mcp_servers/sre/smith/test_cases/disallow/processed_command109.json b/examples/sre/smith/test_cases/disallow/processed_command109.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/disallow/processed_command109.json rename to examples/sre/smith/test_cases/disallow/processed_command109.json diff --git a/mcp_servers/sre/smith/test_cases/disallow/processed_command11.json b/examples/sre/smith/test_cases/disallow/processed_command11.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/disallow/processed_command11.json rename to examples/sre/smith/test_cases/disallow/processed_command11.json diff --git a/mcp_servers/sre/smith/test_cases/disallow/processed_command111.json b/examples/sre/smith/test_cases/disallow/processed_command111.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/disallow/processed_command111.json rename to examples/sre/smith/test_cases/disallow/processed_command111.json diff --git a/mcp_servers/sre/smith/test_cases/disallow/processed_command113.json b/examples/sre/smith/test_cases/disallow/processed_command113.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/disallow/processed_command113.json rename to examples/sre/smith/test_cases/disallow/processed_command113.json diff --git a/mcp_servers/sre/smith/test_cases/disallow/processed_command12.json b/examples/sre/smith/test_cases/disallow/processed_command12.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/disallow/processed_command12.json rename to examples/sre/smith/test_cases/disallow/processed_command12.json diff --git a/mcp_servers/sre/smith/test_cases/disallow/processed_command13.json b/examples/sre/smith/test_cases/disallow/processed_command13.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/disallow/processed_command13.json rename to examples/sre/smith/test_cases/disallow/processed_command13.json diff --git a/mcp_servers/sre/smith/test_cases/disallow/processed_command14.json b/examples/sre/smith/test_cases/disallow/processed_command14.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/disallow/processed_command14.json rename to examples/sre/smith/test_cases/disallow/processed_command14.json diff --git a/mcp_servers/sre/smith/test_cases/disallow/processed_command144.json b/examples/sre/smith/test_cases/disallow/processed_command144.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/disallow/processed_command144.json rename to examples/sre/smith/test_cases/disallow/processed_command144.json diff --git a/mcp_servers/sre/smith/test_cases/disallow/processed_command15.json b/examples/sre/smith/test_cases/disallow/processed_command15.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/disallow/processed_command15.json rename to examples/sre/smith/test_cases/disallow/processed_command15.json diff --git a/mcp_servers/sre/smith/test_cases/disallow/processed_command16.json b/examples/sre/smith/test_cases/disallow/processed_command16.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/disallow/processed_command16.json rename to examples/sre/smith/test_cases/disallow/processed_command16.json diff --git a/mcp_servers/sre/smith/test_cases/disallow/processed_command18.json b/examples/sre/smith/test_cases/disallow/processed_command18.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/disallow/processed_command18.json rename to examples/sre/smith/test_cases/disallow/processed_command18.json diff --git a/mcp_servers/sre/smith/test_cases/disallow/processed_command180.json b/examples/sre/smith/test_cases/disallow/processed_command180.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/disallow/processed_command180.json rename to examples/sre/smith/test_cases/disallow/processed_command180.json diff --git a/mcp_servers/sre/smith/test_cases/disallow/processed_command188.json b/examples/sre/smith/test_cases/disallow/processed_command188.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/disallow/processed_command188.json rename to examples/sre/smith/test_cases/disallow/processed_command188.json diff --git a/mcp_servers/sre/smith/test_cases/disallow/processed_command19.json b/examples/sre/smith/test_cases/disallow/processed_command19.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/disallow/processed_command19.json rename to examples/sre/smith/test_cases/disallow/processed_command19.json diff --git a/mcp_servers/sre/smith/test_cases/disallow/processed_command194.json b/examples/sre/smith/test_cases/disallow/processed_command194.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/disallow/processed_command194.json rename to examples/sre/smith/test_cases/disallow/processed_command194.json diff --git a/mcp_servers/sre/smith/test_cases/disallow/processed_command20.json b/examples/sre/smith/test_cases/disallow/processed_command20.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/disallow/processed_command20.json rename to examples/sre/smith/test_cases/disallow/processed_command20.json diff --git a/mcp_servers/sre/smith/test_cases/disallow/processed_command21.json b/examples/sre/smith/test_cases/disallow/processed_command21.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/disallow/processed_command21.json rename to examples/sre/smith/test_cases/disallow/processed_command21.json diff --git a/mcp_servers/sre/smith/test_cases/disallow/processed_command22.json b/examples/sre/smith/test_cases/disallow/processed_command22.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/disallow/processed_command22.json rename to examples/sre/smith/test_cases/disallow/processed_command22.json diff --git a/mcp_servers/sre/smith/test_cases/disallow/processed_command23.json b/examples/sre/smith/test_cases/disallow/processed_command23.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/disallow/processed_command23.json rename to examples/sre/smith/test_cases/disallow/processed_command23.json diff --git a/mcp_servers/sre/smith/test_cases/disallow/processed_command24.json b/examples/sre/smith/test_cases/disallow/processed_command24.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/disallow/processed_command24.json rename to examples/sre/smith/test_cases/disallow/processed_command24.json diff --git a/mcp_servers/sre/smith/test_cases/disallow/processed_command25.json b/examples/sre/smith/test_cases/disallow/processed_command25.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/disallow/processed_command25.json rename to examples/sre/smith/test_cases/disallow/processed_command25.json diff --git a/mcp_servers/sre/smith/test_cases/disallow/processed_command26.json b/examples/sre/smith/test_cases/disallow/processed_command26.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/disallow/processed_command26.json rename to examples/sre/smith/test_cases/disallow/processed_command26.json diff --git a/mcp_servers/sre/smith/test_cases/disallow/processed_command27.json b/examples/sre/smith/test_cases/disallow/processed_command27.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/disallow/processed_command27.json rename to examples/sre/smith/test_cases/disallow/processed_command27.json diff --git a/mcp_servers/sre/smith/test_cases/disallow/processed_command28.json b/examples/sre/smith/test_cases/disallow/processed_command28.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/disallow/processed_command28.json rename to examples/sre/smith/test_cases/disallow/processed_command28.json diff --git a/mcp_servers/sre/smith/test_cases/disallow/processed_command29.json b/examples/sre/smith/test_cases/disallow/processed_command29.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/disallow/processed_command29.json rename to examples/sre/smith/test_cases/disallow/processed_command29.json diff --git a/mcp_servers/sre/smith/test_cases/disallow/processed_command3.json b/examples/sre/smith/test_cases/disallow/processed_command3.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/disallow/processed_command3.json rename to examples/sre/smith/test_cases/disallow/processed_command3.json diff --git a/mcp_servers/sre/smith/test_cases/disallow/processed_command34.json b/examples/sre/smith/test_cases/disallow/processed_command34.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/disallow/processed_command34.json rename to examples/sre/smith/test_cases/disallow/processed_command34.json diff --git a/mcp_servers/sre/smith/test_cases/disallow/processed_command4.json b/examples/sre/smith/test_cases/disallow/processed_command4.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/disallow/processed_command4.json rename to examples/sre/smith/test_cases/disallow/processed_command4.json diff --git a/mcp_servers/sre/smith/test_cases/disallow/processed_command45.json b/examples/sre/smith/test_cases/disallow/processed_command45.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/disallow/processed_command45.json rename to examples/sre/smith/test_cases/disallow/processed_command45.json diff --git a/mcp_servers/sre/smith/test_cases/disallow/processed_command48.json b/examples/sre/smith/test_cases/disallow/processed_command48.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/disallow/processed_command48.json rename to examples/sre/smith/test_cases/disallow/processed_command48.json diff --git a/mcp_servers/sre/smith/test_cases/disallow/processed_command6.json b/examples/sre/smith/test_cases/disallow/processed_command6.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/disallow/processed_command6.json rename to examples/sre/smith/test_cases/disallow/processed_command6.json diff --git a/mcp_servers/sre/smith/test_cases/disallow/processed_command7.json b/examples/sre/smith/test_cases/disallow/processed_command7.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/disallow/processed_command7.json rename to examples/sre/smith/test_cases/disallow/processed_command7.json diff --git a/mcp_servers/sre/smith/test_cases/disallow/processed_command8.json b/examples/sre/smith/test_cases/disallow/processed_command8.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/disallow/processed_command8.json rename to examples/sre/smith/test_cases/disallow/processed_command8.json diff --git a/mcp_servers/sre/smith/test_cases/disallow/processed_command9.json b/examples/sre/smith/test_cases/disallow/processed_command9.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/disallow/processed_command9.json rename to examples/sre/smith/test_cases/disallow/processed_command9.json diff --git a/mcp_servers/sre/smith/test_cases/disallow/processed_command90.json b/examples/sre/smith/test_cases/disallow/processed_command90.json similarity index 100% rename from mcp_servers/sre/smith/test_cases/disallow/processed_command90.json rename to examples/sre/smith/test_cases/disallow/processed_command90.json diff --git a/mcp_servers/RagChatbot_MCPServer/rag_pipeline.py b/mcp_servers/RagChatbot_MCPServer/rag_pipeline.py deleted file mode 100644 index bc5e5cc..0000000 --- a/mcp_servers/RagChatbot_MCPServer/rag_pipeline.py +++ /dev/null @@ -1,52 +0,0 @@ -from langchain_openai import OpenAIEmbeddings, ChatOpenAI -from langchain_community.embeddings import HuggingFaceEmbeddings -from langchain_community.document_loaders import PDFPlumberLoader -from langchain_text_splitters import RecursiveCharacterTextSplitter -from langchain_core.vectorstores import InMemoryVectorStore -from langchain_core.prompts import ChatPromptTemplate -from dotenv import load_dotenv -import os - -# Load environment variables -load_dotenv() -# Init components -api_key = os.getenv("RITS_API_KEY", None) -api_url = os.getenv("RITS_BASE_URL", None) -model = os.getenv("RITS_MODEL", None) - -embeddings = HuggingFaceEmbeddings(model_name='BAAI/bge-small-en-v1.5') -vector_store = InMemoryVectorStore(embeddings) -model = ChatOpenAI(model=model) - -template = """ -You are a RAG chatbot assistant responsible for retrieving information from a PDF file containing working policies and regulations, and answering users’ questions. -Question: {question} -Context: {context} -Answer: -""" - -# Setup prompt templatetext-embedding-ada-002 -prompt = ChatPromptTemplate.from_template(template) -chain = prompt | model - -# Load and index PDF (done only once, before answering) -base_url = os.getenv("BASE_URL", None) -pdf_path = base_url + "mcp_servers/RagChatbot_MCPServer/pdfs/work_rules_and_regulations_2016.pdf" -loader = PDFPlumberLoader(pdf_path) -documents = loader.load() - -# Split and index -text_splitter = RecursiveCharacterTextSplitter( - chunk_size=1000, - chunk_overlap=200, - add_start_index=True -) -chunks = text_splitter.split_documents(documents) -vector_store.add_documents(chunks) - - -def raw_ask_for_workpolicy(question: str) -> str: - relevant_docs = vector_store.similarity_search(question) - context = "\n\n".join([doc.page_content for doc in relevant_docs]) - result = chain.invoke({"question": question, "context": context}) - return result.content diff --git a/mcp_servers/RagChatbot_MCPServer/rag_salary.py b/mcp_servers/RagChatbot_MCPServer/rag_salary.py deleted file mode 100644 index 113aade..0000000 --- a/mcp_servers/RagChatbot_MCPServer/rag_salary.py +++ /dev/null @@ -1,53 +0,0 @@ -from langchain_openai import OpenAIEmbeddings, ChatOpenAI -from langchain_community.embeddings import HuggingFaceEmbeddings -from langchain_community.document_loaders import PDFPlumberLoader -from langchain_text_splitters import RecursiveCharacterTextSplitter -from langchain_core.vectorstores import InMemoryVectorStore -from langchain_core.prompts import ChatPromptTemplate -from dotenv import load_dotenv -import os - -# Load environment variables -load_dotenv() -# Init components -api_key = os.getenv("RITS_API_KEY", None) -api_url = os.getenv("RITS_BASE_URL", None) -model = os.getenv("RITS_MODEL", None) - -embeddings = HuggingFaceEmbeddings(model_name='BAAI/bge-small-en-v1.5') -vector_store = InMemoryVectorStore(embeddings) -model = ChatOpenAI(model=model) - -template = """ -You are a RAG chatbot assistant responsible for retrieving information from a PDF file containing salary/compensation information, and answering users’ questions. -Question: {question} -Context: {context} -Answer: -""" - -# Setup prompt templatetext-embedding-ada-002 -prompt = ChatPromptTemplate.from_template(template) -chain = prompt | model - -# Load and index PDF (done only once, before answering) -base_url = os.getenv("BASE_URL", None) -pdf_path = base_url + "mcp_servers/RagChatbot_MCPServer/pdfs/salary_summary.pdf" - -loader = PDFPlumberLoader(pdf_path) -documents = loader.load() - -# Split and index -text_splitter = RecursiveCharacterTextSplitter( - chunk_size=1000, - chunk_overlap=200, - add_start_index=True -) -chunks = text_splitter.split_documents(documents) -vector_store.add_documents(chunks) - - -def raw_ask_for_salary(question: str) -> str: - relevant_docs = vector_store.similarity_search(question) - context = "\n\n".join([doc.page_content for doc in relevant_docs]) - result = chain.invoke({"question": question, "context": context}) - return result.content diff --git a/opa_policy/policy_cross_validation/policy_cross_validation.md b/opa_policy/policy_cross_validation/policy_cross_validation.md index 6be8ecf..0cf8a56 100644 --- a/opa_policy/policy_cross_validation/policy_cross_validation.md +++ b/opa_policy/policy_cross_validation/policy_cross_validation.md @@ -12,7 +12,7 @@ If the scorecard shows mixed results (some pass, some fail), skip this — use ` - Policy: `./assets/policy.rego` - Test case template: `./references/test_case_template.json` -- Scorecard: `./scripts/tests/integration/scorecard_summary.txt` +- Scorecard: `./references/scorecard/scorecard_summary.txt` --- diff --git a/opa_policy/policy_patch/policy_patch.md b/opa_policy/policy_patch/policy_patch.md index 7be5b07..549182e 100644 --- a/opa_policy/policy_patch/policy_patch.md +++ b/opa_policy/policy_patch/policy_patch.md @@ -4,7 +4,7 @@ - Policy file: `./assets/policy.rego` - Backup folder: `./assets/opa/outputs` - Cluster results (ORDER IS AUTHORITATIVE): `./assets/opa/outputs/cluster_results.txt` -- Failed test list: `./scripts/tests/integration/score_test_failures.txt` +- Failed test list: `./references/scorecard/score_test_failures.txt` ### IDENTITY RULE - file_path is the ONLY authoritative identity of a test case. diff --git a/scripts/pyproject.toml b/pyproject.toml similarity index 59% rename from scripts/pyproject.toml rename to pyproject.toml index 1f6a9c7..abaadb8 100644 --- a/scripts/pyproject.toml +++ b/pyproject.toml @@ -1,14 +1,12 @@ [build-system] -requires = ["setuptools>=61.0"] +requires = ["setuptools>=64.0"] build-backend = "setuptools.build_meta" [project] name = "smith" -version = "0.1.0" +version = "0.2.0.dev0" description = "Automated policy lifecycle management for AI agents (OPA/Rego)." -# Note: the project README lives at the repository root, outside this package -# directory; setuptools forbids referencing files above the project root, so the -# long description is intentionally omitted here. See ../README.md. +readme = "README.md" requires-python = ">=3.11" license = { text = "Apache-2.0" } authors = [ @@ -33,9 +31,42 @@ classifiers = [ "Topic :: Security", "Topic :: Software Development :: Quality Assurance", ] -# Runtime dependencies are declared in ../requirements.txt. Install them with: -# pip install -r ../requirements.txt -# They are intentionally not duplicated here to keep a single source of truth. +dependencies = [ + "openai>=1.0.0", + "python-dotenv>=1.0.0", + "numpy>=1.24.0", + "pandas>=2.0.0", + "pydantic>=2.0.0", + "PyYAML>=6.0", + "networkx>=3.0", + "pydot>=1.4.0", + "matplotlib>=3.7.0", + "seaborn>=0.12.0", + "nltk>=3.8.0", + "scikit-learn>=1.3.0", + "sentence-transformers>=2.2.0", + "typer>=0.9.0", + "rich>=13.0.0", + "termcolor>=2.0.0", + "httpx>=0.24.0", + "requests>=2.28.0", + "tqdm>=4.65.0", + "tenacity>=8.2.0", + "jinja2>=3.1.0", + "mcp[cli]>=1.0.0", +] + +[project.optional-dependencies] +dev = [ + "ruff==0.15.20", + "black==26.5.1", + "pytest>=7.4.0", + "pytest-asyncio>=0.21.0", + "pytest-mock>=3.11.0", + "pip-audit>=2.7.0", + "build>=1.2.0", + "twine>=5.0.0", +] [project.urls] Homepage = "https://github.com/IBM/smith" @@ -44,32 +75,25 @@ Issues = "https://github.com/IBM/smith/issues" Documentation = "https://github.com/IBM/smith#readme" [project.scripts] -smith = "cli:main" - -[tool.setuptools] -# Flat layout: `cli.py` is a top-level module and the pipeline packages live -# alongside it under scripts/. `scripts/` itself is the import root. -py-modules = ["cli"] +smith = "smith.cli:main" [tool.setuptools.packages.find] -where = ["."] -include = [ - "policy_agent*", - "policy_generation*", - "test_generation*", - "test_case_evaluation*", - "tests*", +where = ["src"] + +[tool.setuptools.package-data] +# Non-Python runtime data shipped with the package: the OPA scorecard harness +# (shell + coverage rego) and the ARES red-teaming input configs. +smith = [ + "policy_testing/*.sh", + "policy_testing/tools/*", + "test_generation/ares_config/*", ] -# The vendored ARES tree is a separate upstream project, not part of Smith. -exclude = ["test_generation.ares*"] [tool.ruff] -# Don't lint or format the vendored ARES red-teaming tree. -extend-exclude = ["test_generation/ares"] +src = ["src"] [tool.black] # Pin the target so formatting is deterministic regardless of the Python # version Black runs under (CI uses 3.11). Without this, Black infers a target # from the running interpreter and may format differently across environments. target-version = ["py311"] -extend-exclude = "test_generation/ares" diff --git a/requirements.txt b/requirements.txt index ada4f16..ec08b7d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,60 +1,4 @@ -# Smith - Core Dependencies - -# LLM and API -openai>=1.0.0 -python-dotenv>=1.0.0 - -# Data processing -numpy>=1.24.0 -pandas>=2.0.0 -pydantic>=2.0.0 -PyYAML>=6.0 - -# Graph and policy analysis -networkx>=3.0 -pydot>=1.4.0 -matplotlib>=3.7.0 - -# NLP and clustering -nltk>=3.8.0 -scikit-learn>=1.3.0 -sentence-transformers>=2.2.0 - -# CLI -# (argparse is part of the Python standard library — do not pin it here) -typer>=0.9.0 -rich>=13.0.0 -termcolor>=2.0.0 - -# HTTP and networking -httpx>=0.24.0 -requests>=2.28.0 - -# Utilities -tqdm>=4.65.0 -tenacity>=8.2.0 -jinja2>=3.1.0 - -# Testing -pytest>=7.4.0 -pytest-asyncio>=0.21.0 -pytest-mock>=3.11.0 - -# MCP (for MCP server testing) -mcp[cli]>=1.0.0 - -# Visualization (optional) -seaborn>=0.12.0 - -# Red-teaming (install separately) -# ares - see https://github.com/IBM/ares for installation -# promptfoo - install via npm: npm install -g promptfoo - -# OPA (install separately) -# opa - see https://www.openpolicyagent.org/docs/latest/#running-opa -# regal - see https://github.com/StyraInc/regal#getting-started - -# Optional / feature-specific (NOT needed for the core CLI flags) -# beeai-framework - required only by policy_agent/scripts/io.py -# mcpgateway, kubectlcmdprocessor - fetched by `scripts/Makefile` build target -# (kubectl command-parsing example), not available via pip +# Smith's runtime dependencies are declared in pyproject.toml ([project.dependencies]). +# This file installs the package (and its dependencies) in editable mode so that +# `pip install -r requirements.txt` keeps working. Prefer `make install` (uses uv). +-e . diff --git a/scripts/Makefile b/scripts/Makefile deleted file mode 100644 index d928061..0000000 --- a/scripts/Makefile +++ /dev/null @@ -1,154 +0,0 @@ -# Copyright 2026 Smith authors -# SPDX-License-Identifier: Apache-2.0 - -SHELL := /bin/bash -.SHELLFLAGS := -eu -o pipefail -c - -REQUIRED_VIS_BINS := code -REQUIRED_BUILD_BINS := wget - -# Project variables -PROJECT_NAME = kubectlpolicies - -# Virtual-environment variables -VENVS_DIR ?= $(HOME)/.venv -VENV_DIR ?= $(VENVS_DIR)/$(PROJECT_NAME) - -OPASERVER_CONTAINER = opaserver -OPASERVER_IMAGE = openpolicyagent/opa:1.8.0-static -POLICY_FILE = ../assets/policy.rego - -MODULES_DIR ?= .modules -KUBECTLCMDPROCESSOR_DIR = $(MODULES_DIR)/kubectlcmdprocessor -CF_DIR = $(MODULES_DIR)/mcpgateway - -KUBECTLCMDPROCESSOR_VERSION = main -CF_VERSION = main - -.PHONY: venv -venv: - @rm -Rf "$(VENV_DIR)" - @test -d "$(VENVS_DIR)" || mkdir -p "$(VENVS_DIR)" - @python3 -m venv "$(VENV_DIR)" - @/bin/bash -c "source $(VENV_DIR)/bin/activate && python3 -m pip install --upgrade pip" - @echo -e "✅ Virtual env created.\n💡 Enter it with:\n . $(VENV_DIR)/bin/activate\n" - -.PHONY: install -install: venv - @/bin/bash -c "source $(VENV_DIR)/bin/activate && pip install uv && uv sync --active --all-extras" - -.PHONY: build -build: - $(foreach bin,$(REQUIRED_BUILD_BINS), $(if $(shell command -v $(bin) 2> /dev/null),,$(error Please install `$(bin)`))) - @rm -rf ${MODULES_DIR} && mkdir -p ${KUBECTLCMDPROCESSOR_DIR} && mkdir -p ${CF_DIR} - @wget --header="Accept:application/vnd.github.v3.raw" -qO - https://api.github.com/repos/araujof/mcp-context-forge-kubectlparser-plugin/tarball/${KUBECTLCMDPROCESSOR_VERSION} | tar xz -C ${KUBECTLCMDPROCESSOR_DIR} --strip-components 1 - @wget --header="Accept:application/vnd.github.v3.raw" -qO - https://api.github.com/repos/IBM/mcp-context-forge/tarball/${CF_VERSION} | tar xz -C ${CF_DIR} --strip-components 1 - @make -C ${KUBECTLCMDPROCESSOR_DIR} build - @make -C ${CF_DIR}/plugins/external/opa build - @make -C ${CF_DIR} docker - -.PHONY: start -start: - @docker compose --project-name cf -f docker/docker-compose.yaml up -d - -.PHONY: stop -stop: - @docker compose --project-name cf -f docker/docker-compose.yaml down - -.PHONY: mcpserver/start -mcpserver/start: - @bash server_start.sh - -.PHONY: mcpserver/stop -mcpserver/stop: - @bash server_stop.sh - -.PHONY: opaserver/start -opaserver/start: lint/policy - @echo "Starting OPA server" - @docker run -d --name $(OPASERVER_CONTAINER) --rm -p 8181:8181 -v $(shell pwd)/$(POLICY_FILE):/kubectl/policy.rego $(OPASERVER_IMAGE) \ - run --server /kubectl/policy.rego --log-level debug --addr=0.0.0.0:8181 - -.PHONY: opaserver/parse -opaserver/parse: - @echo "Parsing OPA policy" - @docker run --rm -v $(shell pwd)/policies:/policies $(OPASERVER_IMAGE) \ - parse /policies/policy.rego --format=json > ./blue-agent-components/data/ast.json - -.PHONY: opaserver/stop -opaserver/stop: - @echo "Stopping OPA server" - -@docker stop $(OPASERVER_CONTAINER) - -.PHONY: opaserver/status -opaserver/status: - @docker ps -q --filter "name=$(OPASERVER_CONTAINER)" --filter "status=running" - -.PHONY: lint/policy -lint/policy: - @docker run --rm -v $(shell pwd)/$(POLICY_FILE):/kubectl/policy.rego $(OPASERVER_IMAGE) check /kubectl/policy.rego - -.PHONY: lint/code -lint/code: - uvx ruff check --fix scripts tests visualization - uvx black scripts tests visualization - -.PHONY: test -test: opaserver/stop opaserver/start - @sleep 5 - @./tests/integration/score_card.sh >/dev/null - @./tests/integration/highlight.sh cat ./tests/integration/score_test_failures.txt ./tests/integration/scorecard_summary.txt - -.PHONY: test/verbose -test/verbose: lint/policy - @./tests/integration/highlight.sh ./tests/integration/score_card.sh - -.PHONY: view/tests -view/tests: - @sleep 1 - @./tests/integration/highlight.sh cat ./tests/integration/score_test_failures.txt ./tests/integration/scorecard_summary.txt - -.PHONY: vis/tests -vis/tests: - $(foreach bin,$(REQUIRED_VIS_BINS), $(if $(shell command -v $(bin) 2> /dev/null),,$(error Please install `$(bin)`))) - @test -d "$(VENV_DIR)" || $(MAKE) --no-print-directory venv - @/bin/bash -eu -c "\ - source $(VENV_DIR)/bin/activate && \ - uv sync -q --extra vis && \ - python3 visualization/visualize_tests.py" - @command -v code >/dev/null 2>&1 && code visualization/scorecard_analysis.png - -.PHONY: vis/policy -vis/policy: - $(foreach bin,$(REQUIRED_VIS_BINS), $(if $(shell command -v $(bin) 2> /dev/null),,$(error Please install `$(bin)`))) - @test -d "$(VENV_DIR)" || $(MAKE) --no-print-directory venv - @/bin/bash -eu -c "\ - source $(VENV_DIR)/bin/activate && \ - uv sync -q --extra vis && \ - python3 visualization/visualize_policy.py" - @command -v code >/dev/null 2>&1 && code visualization/policy_decision_tree.md - -.PHONY: vis/req -vis/req: - @open visualization/nl2kubectl_security_visualization.html - -.PHONY: help -help: - @echo "This Makefile is offered for convenience." - @echo "" - @echo "The following are the valid targets for this Makefile:" - @echo "...install Install project requirements" - @echo "...build Build docker stack" - @echo "...start Start docker stack" - @echo "...stop Stop docker stack" - @echo "...opaserver/start Start the OPA server" - @echo "...opaserver/stop Stop the OPA server" - @echo "...opaserver/status Check if OPA server is running" - @echo "...lint/policy Check for lint errors in the rego policy" - @echo "...lint/code Check for lint errors in Python code" - @echo "...test Run tests against the policy and output score card and failed tests only (requires OPA server to be running)" - @echo "...test/verbose Run tests against the policy and output results for every test case in addition to score card (requires OPA server to be running)" - @echo "...view/tests View last test results" - @echo "...vis/tests Generates a visualization of the test results" - @echo "...vis/policy Generates a visualization of the OPA policy" - @echo "...vis/req Generates a visualization of security requirements" diff --git a/scripts/policy_agent/pipeline.py b/scripts/policy_agent/pipeline.py deleted file mode 100644 index d27868a..0000000 --- a/scripts/policy_agent/pipeline.py +++ /dev/null @@ -1,120 +0,0 @@ -# Copyright 2026 Smith authors -# SPDX-License-Identifier: Apache-2.0 - -from scripts.parse_ast_to_graph import init_graph -from red_feedback.red_feedback import cluster_commands -from policy_analysis.update_policy_analysis import update_policy_analysis_feedback -from policy_evaluation.run_policy_evaluation import run_policy_evaluation -import argparse -import os -from reduce_improve.detect_redundancy import write_graph_suggestion -from policy_analysis.regal.regal_finder import create_regal_suggestion -from dotenv import load_dotenv - -load_dotenv() - - -class BlueAgent: - def __init__(self): - self.base_url = os.getenv("BASE_URL") - self.data_dir = self.base_url + os.getenv("DATA_DIR") - self.user_input_dir = self.base_url + os.getenv("DATA_DIR") + "inputs/" - self.user_output_dir = self.base_url + os.getenv("DATA_DIR") + "outputs/" - - self.graph_path = self.user_output_dir + os.getenv("GRAPH_PATH") - self.opa_ast_path = self.user_output_dir + os.getenv("OPA_AST_PATH") - self.cluster_results = self.user_output_dir + os.getenv("CLUSTER_RESULTS") - self.cluster_eps = float(os.getenv("CLUSTER_EPS", "0.3")) - self.cluster_min_samples = int(os.getenv("CLUSTER_MIN_SAMPLES", "2")) - - self.policy_dir = self.base_url + os.getenv("POLICY_DIR") - self.policy_path = self.policy_dir + os.getenv("POLICY_PATH") - - self.api_key = os.getenv("OPENAI_API_KEY") - self.MODEL = os.getenv("MODEL_SONNET") - self.openai_base_url = os.getenv("OPENAI_BASE_URL") - self.temp = float(os.getenv("TEMP")) - self.top_p = float(os.getenv("TOP_P")) - - self.regal_suggestion_path = self.user_output_dir + os.getenv( - "REGAL_SUGGESTION_PATH" - ) - self.regal_result_output = self.user_output_dir + os.getenv( - "REGAL_RESULT_OUTPUT" - ) - self.modified_policy_regal = self.user_output_dir + os.getenv( - "MODIFIED_POLICY_REGAL" - ) - self.test_dir = self.base_url + "scripts/" - self.test_path = self.test_dir + os.getenv("TEST_PATH") - self.test_results_path = self.test_path + os.getenv("TEST_RESULT_PATH") - - self.modified_policy_deduplicate = self.user_output_dir + os.getenv( - "MODIFIED_POLICY_DEDUPLICATE" - ) - self.graph_suggestion_path = self.user_output_dir + os.getenv( - "GRAPH_SUGGESTION_PATH" - ) - # shutil.copy(self.user_input_dir+os.getenv("POLICY_PATH"), self.policy_path) - self.G = init_graph(self.opa_ast_path, self.policy_dir, self.graph_path) - - def get_regal_feedback(self): - print("collecting regal feedbacks") - return create_regal_suggestion(self.policy_path, self.regal_suggestion_path) - - def get_duplication_feedback(self): - init_graph(self.opa_ast_path, self.policy_dir, self.graph_path) - results = "Below is LLM generated redundancy suggestions: \n" - results = results + update_policy_analysis_feedback( - self.api_key, - self.user_output_dir, - self.openai_base_url, - self.policy_path, - self.MODEL, - self.temp, - self.top_p, - ) - results = ( - results - + "Below is graph generated redundancy suggestions, the nodes are rule names, each subgraph indicates the rules and relations in this subgraph is non reachable thus redundant. \n" - ) - results = results + write_graph_suggestion( - self.graph_path, self.graph_suggestion_path - ) - return results - - def get_red_feedback(self): - return "\n".join( - cluster_commands( - self.cluster_results, - self.test_path, - self.cluster_eps, - self.cluster_min_samples, - ) - ) - - def policy_checking_results(self): - return run_policy_evaluation(self.test_dir, self.test_results_path) - - -def main(): - - parser = argparse.ArgumentParser() - parser.add_argument("--flag", help="what advices you want to generate?") - args = parser.parse_args() - agent = BlueAgent() - load_dotenv() - if args.flag == "policy_testing": - agent.policy_checking_results() - if args.flag == "regal_suggestion": - results = agent.get_regal_feedback() - print(results) - if args.flag == "duplication_suggestion": - results = agent.get_duplication_feedback() - print(results) - if args.flag == "red_suggestion": - results = agent.get_red_feedback() - - -if __name__ == "__main__": - main() diff --git a/scripts/policy_agent/policy_refinement/regal_update.py b/scripts/policy_agent/policy_refinement/regal_update.py deleted file mode 100644 index cf3f8c3..0000000 --- a/scripts/policy_agent/policy_refinement/regal_update.py +++ /dev/null @@ -1,122 +0,0 @@ -# Copyright 2026 Smith authors -# SPDX-License-Identifier: Apache-2.0 - -import re -import os -from dotenv import load_dotenv -from openai import OpenAI -import httpx -from policy_agent.policy_analysis.regal.regal_finder import create_regal_suggestion - -load_dotenv() - - -def regal_update( - api_key, - openai_base_url, - policy_dir, - policy_path, - regal_suggestion_path, - MODEL, - regal_result_output, - modified_policy_regal, - temp, - top_p, -): - - create_regal_suggestion(policy_dir, regal_suggestion_path) - - http_client = httpx.Client(verify=False, timeout=300.0) - - client = OpenAI(api_key=api_key, base_url=openai_base_url, http_client=http_client) - - regal_feedback = "" - rego_policy = "" - if not os.path.exists(policy_path): - raise FileNotFoundError(f"Missing {policy_path}") - - with open(policy_path, "r", encoding="utf-8") as f: - rego_policy = f.read() - - with open(regal_suggestion_path, "r", encoding="utf-8") as f: - regal_feedback = f.read() - - system_instruction = """ - You are a code assistant specialized in analyzing Open Policy Agent (OPA) Rego policies. - - You are given: - 1. A set of suggestions generated by regal paired with the link of its documentation. - 2. The full Rego policy source code governing kubectl operations. - - # Task - Analyze the policy and suggestions to: - - Search the attached documnet link to understand each suggestion. - - Update the policy following the explaination in the document and suggestions if necessary, please refer to the document to understand how to solve the suggestion, if you are unsure, do not fix it. - - Apply minimal and localized edits to strengthen the policy. - - Modify existing rules where possible instead of adding new ones. - - Ensure legitimate kubectl usage is not over-restricted. - - # Constraints - - Do NOT rewrite or refactor the entire policy. - - Keep rule names, structure, and logic consistent. - - Add only narrowly scoped conditions to block the bypasses. - - Maintain the existing allow/deny semantics and namespace checks. - - # Output Format - 1. A detailed analysis section for each suggestion. - 2. At the end, include the **complete modified Rego policy** in this format: - - ```rego - - """ - - user_prompt = f""" - Regal suggestions - {regal_feedback} - Current Rego Policy - {rego_policy} - Instructions - Analyze how each suggestion can improve the policy and return the updated Rego code that improves the policy following these suggestions. - """ - - print("Analyzing and strengthening the OPA policy...") - response = client.chat.completions.create( - model=MODEL, - messages=[ - {"role": "system", "content": system_instruction}, - {"role": "user", "content": user_prompt}, - ], - max_tokens=30000, - temperature=temp, - top_p=top_p, - ) - - assistant_output = response.choices[0].message.content - - with open(regal_result_output, "w", encoding="utf-8") as f: - f.write(assistant_output) - print(f"Full analysis saved to: {regal_result_output}") - - def extract_rego_block(text: str): - match = re.search(r"```(?:rego)?\s*(.*?)```", text, re.S | re.I) - if match: - return match.group(match.lastindex).strip() - - match2 = re.search(r"(package\s+[\s\S]+)$", text, re.I) - if match2: - return match2.group(match.lastindex).strip() - - return None - - rego_block = extract_rego_block(assistant_output) - - if rego_block: - with open(modified_policy_regal, "w", encoding="utf-8") as f: - f.write(rego_block) - with open(policy_path, "w", encoding="utf-8") as f: - f.write(rego_block) - print(f"Modified Rego policy copy saved to: {modified_policy_regal}") - else: - print("No Rego code block detected — please check analysis_notes.txt manually.") - - print("Done.") diff --git a/scripts/policy_agent/red_feedback/tests/pytest.ini b/scripts/policy_agent/red_feedback/tests/pytest.ini deleted file mode 100644 index db217fa..0000000 --- a/scripts/policy_agent/red_feedback/tests/pytest.ini +++ /dev/null @@ -1,16 +0,0 @@ -[pytest] -log_cli = false -log_cli_level = INFO -log_cli_format = %(asctime)s [%(module)s] [%(levelname)s] %(message)s -log_cli_date_format = %Y-%m-%d %H:%M:%S -log_level = INFO -log_format = %(asctime)s [%(module)s] [%(levelname)s] %(message)s -log_date_format = %Y-%m-%d %H:%M:%S -addopts = --cov=kubectlcmdprocessor --cov-report=term-missing -env_files = .env -pythonpath = . src -filterwarnings = - ignore::DeprecationWarning:pydantic.* - -[coverage:run] -omit = kubectlcmdprocessor/__init__.py diff --git a/scripts/policy_agent/red_feedback/tests/test_all.py b/scripts/policy_agent/red_feedback/tests/test_all.py deleted file mode 100644 index e358a7b..0000000 --- a/scripts/policy_agent/red_feedback/tests/test_all.py +++ /dev/null @@ -1,50 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright 2026 Smith authors -# SPDX-License-Identifier: Apache-2.0 - -"""Tests for registered plugins.""" - -# Third-Party -import asyncio -import pytest - -# First-Party -from mcpgateway.plugins.framework import ( - PluginManager, - GlobalContext, - ToolPreInvokePayload, -) - -from kubectlcmdprocessor.plugin import ( - CONTEXT_KEY_POLICY_CONTEXT, - CONTEXT_KEY_KUBECTL_CMD, -) - - -@pytest.fixture(scope="module", autouse=True) -def plugin_manager(): - """Initialize plugin manager.""" - plugin_manager = PluginManager("./resources/plugins/config.yaml") - asyncio.run(plugin_manager.initialize()) - yield plugin_manager - asyncio.run(plugin_manager.shutdown()) - - -@pytest.mark.asyncio -async def test_tool_pre_hook(plugin_manager: PluginManager): - """Test tool pre hook across all registered plugins.""" - # Customize payload for testing - payload = ToolPreInvokePayload( - name="kubectl_tool", args={"arg0": "kubectl get pods"} - ) - global_context = GlobalContext(request_id="1") - result, ctx = await plugin_manager.tool_pre_invoke(payload, global_context) - context = next(iter(ctx.values())) - cmd = context.global_context.state[CONTEXT_KEY_POLICY_CONTEXT][ - CONTEXT_KEY_KUBECTL_CMD - ] - assert cmd["command"]["verb"] == "get" - assert cmd["command"]["resource"] == "pods" - assert cmd["command"]["namespace"] is None - assert len(cmd["command"]["args"]) == 0 - assert result.continue_processing diff --git a/scripts/policy_agent/red_feedback/tests/test_parser.py b/scripts/policy_agent/red_feedback/tests/test_parser.py deleted file mode 100644 index 5efade7..0000000 --- a/scripts/policy_agent/red_feedback/tests/test_parser.py +++ /dev/null @@ -1,773 +0,0 @@ -# Copyright 2026 Smith authors -# SPDX-License-Identifier: Apache-2.0 - -"""Comprehensive tests for kubectl command parser.""" - -import subprocess -import sys -import pytest -from unittest.mock import patch -from kubectlcmdprocessor.parser import KubectlParser, main - - -@pytest.fixture -def parser(): - """Create a fresh parser instance for each test.""" - return KubectlParser() - - -def test_basic_resource_operations(parser): - """Test basic resource operations like get, describe, delete.""" - - # Test simple get command - result = parser.parse("kubectl get pods") - assert result["command"]["verb"] == "get" - assert result["command"]["resource"] == "pods" - assert result["command"]["namespace"] is None - assert len(result["command"]["args"]) == 0 - - # Test get with namespace flag - result = parser.parse("kubectl get pods -n sre-sandbox") - assert result["command"]["verb"] == "get" - assert result["command"]["resource"] == "pods" - assert result["command"]["namespace"] == "sre-sandbox" - assert any( - flag["name"] == "-n" and flag["value"] == "sre-sandbox" - for flag in result["command"]["flags"] - ) - - # Test describe with namespace=value format - result = parser.parse("kubectl describe pod my-pod --namespace=production") - assert result["command"]["verb"] == "describe" - assert result["command"]["resource"] == "pod" - assert result["command"]["namespace"] == "production" - assert "my-pod" in result["command"]["args"] - - # Test delete with multiple flags - result = parser.parse("kubectl delete pods --all -n test") - assert result["command"]["verb"] == "delete" - assert result["command"]["resource"] == "pods" - assert result["command"]["namespace"] == "test" - assert any(flag["name"] == "--all" for flag in result["command"]["flags"]) - - -def test_file_based_operations(parser): - """Test file-based operations with -f flag.""" - - result = parser.parse("kubectl apply -f deployment.yaml") - assert result["command"]["verb"] == "apply" - assert ( - result["command"]["resource"] is None - ) # -f now takes deployment.yaml as value - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["-f"] == "deployment.yaml" - - result = parser.parse("kubectl create -f ./pod.json") - assert result["command"]["verb"] == "create" - assert result["command"]["resource"] is None # -f now takes ./pod.json as value - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["-f"] == "./pod.json" - - result = parser.parse("kubectl delete -f manifest.yaml") - assert result["command"]["verb"] == "delete" - assert result["command"]["resource"] is None # -f now takes manifest.yaml as value - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["-f"] == "manifest.yaml" - - -def test_complex_operations_with_multiple_flags(parser): - """Test complex operations with multiple flags and arguments.""" - - # Test logs command with multiple flags - result = parser.parse("kubectl logs my-pod -c container-name --follow --tail=100") - assert result["command"]["verb"] == "logs" - assert result["command"]["resource"] is None - assert result["command"]["args"] == [ - "my-pod" - ] # container-name is now -c flag's value - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["-c"] == "container-name" # -c now takes container-name as value - assert flags["--follow"] is None - assert flags["--tail"] == "100" - - # Test get with output format - result = parser.parse("kubectl get services -o yaml --sort-by=.metadata.name") - assert result["command"]["verb"] == "get" - assert result["command"]["resource"] == "services" - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["-o"] == "yaml" - assert flags["--sort-by"] == ".metadata.name" - - # Test exec with interactive flags and command - result = parser.parse("kubectl exec -it my-pod -- /bin/bash") - assert result["command"]["verb"] == "exec" - assert result["command"]["resource"] is None - assert "my-pod" in result["command"]["args"] - assert "/bin/bash" in result["command"]["args"] - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["-i"] is None # -it is now split into -i and -t - assert flags["-t"] is None - assert flags["--"] is None # -- is treated as a flag - - -def test_quoted_arguments(parser): - """Test handling of quoted arguments with spaces.""" - - result = parser.parse( - 'kubectl create secret generic my-secret --from-literal=key="value with spaces"' - ) - assert result["command"]["verb"] == "create" - assert result["command"]["resource"] == "secret" - assert "generic" in result["command"]["args"] - assert "my-secret" in result["command"]["args"] - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert ( - flags["--from-literal"] == "key=value with spaces" - ) # Quotes are removed by tokenizer - - -def test_subcommands(parser): - """Test kubectl subcommands like rollout, config, auth.""" - - # Test rollout status - result = parser.parse("kubectl rollout status deployment/nginx") - assert result["command"]["verb"] == "rollout" - assert result["command"]["resource"] == "status" - assert "deployment/nginx" in result["command"]["args"] - - # Test rollout undo with flag - result = parser.parse("kubectl rollout undo deployment/abc --to-revision=3") - assert result["command"]["verb"] == "rollout" - assert result["command"]["resource"] == "undo" - assert "deployment/abc" in result["command"]["args"] - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["--to-revision"] == "3" - - # Test config view - result = parser.parse("kubectl config view") - assert result["command"]["verb"] == "config" - assert result["command"]["resource"] == "view" - - # Test config use-context - result = parser.parse("kubectl config use-context production") - assert result["command"]["verb"] == "config" - assert result["command"]["resource"] == "use-context" - assert "production" in result["command"]["args"] - - # Test auth can-i - result = parser.parse("kubectl auth can-i create pods") - assert result["command"]["verb"] == "auth" - assert result["command"]["resource"] == "can-i" - assert "create" in result["command"]["args"] - assert "pods" in result["command"]["args"] - - -def test_creation_commands(parser): - """Test resource creation commands with various flags.""" - - # Test deployment creation - result = parser.parse("kubectl create deployment nginx --image=nginx --replicas=3") - assert result["command"]["verb"] == "create" - assert result["command"]["resource"] == "deployment" - assert "nginx" in result["command"]["args"] - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["--image"] == "nginx" - assert flags["--replicas"] == "3" - - # Test service creation - result = parser.parse("kubectl create service clusterip my-service --tcp=80:8080") - assert result["command"]["verb"] == "create" - assert result["command"]["resource"] == "service" - assert "clusterip" in result["command"]["args"] - assert "my-service" in result["command"]["args"] - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["--tcp"] == "80:8080" - - # Test configmap creation - result = parser.parse( - "kubectl create configmap my-config --from-file=config.properties" - ) - assert result["command"]["verb"] == "create" - assert result["command"]["resource"] == "configmap" - assert "my-config" in result["command"]["args"] - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["--from-file"] == "config.properties" - - -def test_debugging_operations(parser): - """Test debugging and troubleshooting commands.""" - - # Test debug command - result = parser.parse("kubectl debug my-pod --image=busybox --target=app") - assert result["command"]["verb"] == "debug" - assert result["command"]["args"][0] == "my-pod" - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["--image"] == "busybox" - assert flags["--target"] == "app" - - # Test port-forward - result = parser.parse("kubectl port-forward pod/my-pod 8080:80") - assert result["command"]["verb"] == "port-forward" - assert result["command"]["resource"] is None - assert "pod/my-pod" in result["command"]["args"] - assert "8080:80" in result["command"]["args"] - - # Test cp command - result = parser.parse("kubectl cp /local/path pod/my-pod:/remote/path") - assert result["command"]["verb"] == "cp" - assert result["command"]["resource"] is None - assert "/local/path" in result["command"]["args"] - assert "pod/my-pod:/remote/path" in result["command"]["args"] - - # Test top command - result = parser.parse("kubectl top nodes --sort-by=cpu") - assert result["command"]["verb"] == "top" - assert result["command"]["resource"] == "nodes" - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["--sort-by"] == "cpu" - - -def test_advanced_operations(parser): - """Test advanced operations like patch, scale, autoscale.""" - - # Test patch with JSON - result = parser.parse( - 'kubectl patch deployment nginx -p \'{"spec":{"replicas":5}}\'' - ) - assert result["command"]["verb"] == "patch" - assert result["command"]["resource"] == "deployment" - assert "nginx" in result["command"]["args"] - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["-p"] == '{"spec":{"replicas":5}}' # JSON is now -p flag's value - - # Test scale - result = parser.parse("kubectl scale deployment nginx --replicas=10") - assert result["command"]["verb"] == "scale" - assert result["command"]["resource"] == "deployment" - assert "nginx" in result["command"]["args"] - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["--replicas"] == "10" - - # Test autoscale - result = parser.parse( - "kubectl autoscale deployment nginx --min=2 --max=10 --cpu-percent=80" - ) - assert result["command"]["verb"] == "autoscale" - assert result["command"]["resource"] == "deployment" - assert "nginx" in result["command"]["args"] - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["--min"] == "2" - assert flags["--max"] == "10" - assert flags["--cpu-percent"] == "80" - - # Test wait - result = parser.parse( - "kubectl wait --for=condition=Ready pod/my-pod --timeout=300s" - ) - assert result["command"]["verb"] == "wait" - assert result["command"]["resource"] == "pod/my-pod" - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["--for"] == "condition=Ready" - assert flags["--timeout"] == "300s" - - -def test_cluster_management(parser): - """Test cluster management commands.""" - - # Test drain - result = parser.parse("kubectl drain node-1 --ignore-daemonsets") - assert result["command"]["verb"] == "drain" - assert result["command"]["resource"] == "node-1" - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["--ignore-daemonsets"] is None - - # Test cordon - result = parser.parse("kubectl cordon node-1") - assert result["command"]["verb"] == "cordon" - assert result["command"]["resource"] == "node-1" - - # Test taint - result = parser.parse("kubectl taint nodes node-1 key=value:NoSchedule") - assert result["command"]["verb"] == "taint" - assert result["command"]["resource"] == "nodes" - assert "node-1" in result["command"]["args"] - assert "key=value:NoSchedule" in result["command"]["args"] - - -def test_commands_without_kubectl_prefix(parser): - """Test commands without the kubectl prefix.""" - - # Test get without kubectl prefix - result = parser.parse("get pods -o wide --all-namespaces") - assert result["command"]["verb"] == "get" - assert result["command"]["resource"] == "pods" - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["-o"] == "wide" - assert flags["--all-namespaces"] is None - - # Test apply with kustomize - result = parser.parse("apply -k ./kustomize-dir") - assert result["command"]["verb"] == "apply" - assert ( - result["command"]["resource"] is None - ) # -k now takes ./kustomize-dir as value - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["-k"] == "./kustomize-dir" - - -def test_edge_cases(parser): - """Test edge cases and malformed commands.""" - - # Test empty kubectl command - result = parser.parse("kubectl") - assert result["command"]["verb"] is None - assert result["command"]["resource"] is None - assert len(result["command"]["flags"]) == 0 - - # Test kubectl with only help flag - result = parser.parse("kubectl --help") - assert result["command"]["verb"] is None - assert result["command"]["resource"] is None - assert any(flag["name"] == "--help" for flag in result["command"]["flags"]) - - # Test get without resource - result = parser.parse("kubectl get") - assert result["command"]["verb"] == "get" - assert result["command"]["resource"] is None - - # Test empty string - result = parser.parse("") - assert result["command"]["verb"] is None - assert result["command"]["resource"] is None - - # Test whitespace only - result = parser.parse(" ") - assert result["command"]["verb"] is None - assert result["command"]["resource"] is None - - -def test_flag_parsing_variations(parser): - """Test various flag parsing scenarios.""" - - # Test short flag with value - result = parser.parse("kubectl get pods -n test") - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["-n"] == "test" - - # Test long flag with equals - result = parser.parse("kubectl get pods --namespace=production") - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["--namespace"] == "production" - - # Test boolean flags - result = parser.parse("kubectl get pods --watch --all-namespaces") - flag_names = [flag["name"] for flag in result["command"]["flags"]] - assert "--watch" in flag_names - assert "--all-namespaces" in flag_names - - # Test mixed flag formats - result = parser.parse("kubectl logs pod -f --tail=10 -c container") - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["-f"] is None - assert flags["--tail"] == "10" - assert flags["-c"] == "container" # -c now takes container as value - assert result["command"]["args"] == ["pod"] # container is now -c flag's value - - -def test_reset_functionality(parser): - """Test that parser state is reset between calls.""" - - # Parse first command - result1 = parser.parse("kubectl get pods -n test") - assert result1["command"]["namespace"] == "test" - - # Parse second command without namespace - result2 = parser.parse("kubectl describe pod my-pod") - assert result2["command"]["namespace"] is None - assert result2["command"]["verb"] == "describe" - assert result2["command"]["resource"] == "pod" - - -def test_tokenizer_with_quotes(parser): - """Test tokenizer handles quoted strings correctly.""" - - # Test single quotes - result = parser.parse( - "kubectl create secret generic test --from-literal='key=value with spaces'" - ) - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["--from-literal"] == "key=value with spaces" - - # Test double quotes - result = parser.parse( - 'kubectl create secret generic test --from-literal="key=value with spaces"' - ) - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["--from-literal"] == "key=value with spaces" - - # Test nested quotes in JSON - result = parser.parse( - 'kubectl patch pod test -p \'{"metadata":{"labels":{"app":"test"}}}\'' - ) - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert ( - flags["-p"] == '{"metadata":{"labels":{"app":"test"}}}' - ) # -p now takes JSON as value - assert result["command"]["args"] == [ - "test" - ] # test is the pod name, JSON is now -p flag's value - - -@patch("builtins.print") -def test_main_function(mock_print): - """Test the main() function runs without errors and processes all test commands.""" - # Call the main function - main() - - # Verify that print was called (output was produced) - assert mock_print.called - - # Get all the print calls - extract the first argument from each call - print_calls = [] - for call in mock_print.call_args_list: - if call.args: # call.args contains the positional arguments - print_calls.append(str(call.args[0])) - - # Verify that we have output for commands and results - # Note: command lines start with \nCommand: due to the print formatting in main() - command_lines = [line for line in print_calls if "Command: " in line] - result_lines = [line for line in print_calls if line.startswith("Parsed: ")] - - # Should have at least some command and result lines - assert ( - len(command_lines) > 0 - ), f"No command lines found in output. All calls: {print_calls[:5]}..." - assert len(result_lines) > 0, "No result lines found in output" - - # Verify some expected commands are processed - all_output = " ".join(print_calls) - assert "kubectl get pods" in all_output - assert "kubectl debug my-pod" in all_output - assert "kubectl taint nodes" in all_output - - # Verify that parsing results are included in output - assert "{'command':" in all_output, "No parsing results found in output" - - -def test_flag_before_verb_skips_value(parser): - """Test that flags with values before the verb are properly skipped to find the verb.""" - # This command has a flag with a value before the verb 'get' - command = "kubectl --namespace production get pods" - result = parser.parse(command) - - # Verify the verb was correctly identified despite the flag before it - assert result["command"]["verb"] == "get" - assert result["command"]["resource"] == "pods" - assert result["command"]["namespace"] == "production" - - # Verify the flag was parsed correctly - flags = result["command"]["flags"] - assert len(flags) == 1 - assert flags[0]["name"] == "--namespace" - assert flags[0]["value"] == "production" - - -def test_empty_tokens_after_tokenization(parser): - """Test case where tokenization results in empty tokens list""" - # This should have non-empty string but tokenize to empty list - # For example, a string with only empty quotes - result = parser.parse('kubectl ""') - expected = { - "command": { - "verb": None, - "resource": None, - "namespace": None, - "args": [], - "flags": [], - } - } - assert result == expected - - -def test_namespace_flag_without_value(parser): - """Test namespace flag without a value (XXX comment case)""" - # Test -n flag at end of command (no value) - result = parser.parse("kubectl get pods -n") - - assert result["command"]["verb"] == "get" - assert result["command"]["resource"] == "pods" - assert ( - result["command"]["namespace"] is None - ) # Should be None since no value provided - assert len(result["command"]["flags"]) == 1 - assert result["command"]["flags"][0]["name"] == "-n" - assert result["command"]["flags"][0]["value"] is None - - # Test --namespace flag at end of command (no value) - result = parser.parse("kubectl get pods --namespace") - - assert result["command"]["verb"] == "get" - assert result["command"]["resource"] == "pods" - assert result["command"]["namespace"] is None - assert len(result["command"]["flags"]) == 1 - assert result["command"]["flags"][0]["name"] == "--namespace" - assert result["command"]["flags"][0]["value"] is None - - # Test -n flag followed by another flag (no value for -n) - result = parser.parse("kubectl get pods -n -o yaml") - - assert result["command"]["verb"] == "get" - assert result["command"]["resource"] == "pods" - assert result["command"]["namespace"] is None - assert len(result["command"]["flags"]) == 2 - - # Find the -n flag - n_flag = next(flag for flag in result["command"]["flags"] if flag["name"] == "-n") - assert n_flag["value"] is None - - # Find the -o flag - o_flag = next(flag for flag in result["command"]["flags"] if flag["name"] == "-o") - assert o_flag["value"] == "yaml" - - -def test_unquoted_selector_parsing(parser): - """Test parsing of unquoted selector expressions.""" - - # Test the original problem cases - result = parser.parse( - "kubectl get pods -n otel-demo -l service in (email,checkout)" - ) - assert result["command"]["verb"] == "get" - assert result["command"]["resource"] == "pods" - assert result["command"]["namespace"] == "otel-demo" - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["-l"] == "service in (email,checkout)" - assert len(result["command"]["args"]) == 0 # No leftover args - - result = parser.parse( - "kubectl get deployments -n otel-demo -o jsonpath='...' --selector=service in (ad,cart,payment)" - ) - assert result["command"]["verb"] == "get" - assert result["command"]["resource"] == "deployments" - assert result["command"]["namespace"] == "otel-demo" - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["--selector"] == "service in (ad,cart,payment)" - assert flags["-o"] == "jsonpath=..." - assert len(result["command"]["args"]) == 0 # No leftover args - - -def test_selector_parsing_variations(parser): - """Test different selector parsing scenarios.""" - - # Simple equality selectors - result = parser.parse("kubectl get pods -l app=nginx") - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["-l"] == "app=nginx" - - # Not equal selectors - result = parser.parse("kubectl get pods -l app!=nginx") - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["-l"] == "app!=nginx" - - # Multiple selectors with comma - result = parser.parse("kubectl get pods -l app=nginx,env=prod") - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["-l"] == "app=nginx,env=prod" - - # --selector format with in operator - result = parser.parse("kubectl get pods --selector=tier in (frontend,backend)") - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["--selector"] == "tier in (frontend,backend)" - - # notin operator - result = parser.parse("kubectl get pods -l environment notin (production,staging)") - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["-l"] == "environment notin (production,staging)" - - # Complex selector with 'and' - result = parser.parse("kubectl get pods -l app=web and version!=old") - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["-l"] == "app=web and version!=old" - - -def test_selector_edge_cases(parser): - """Test edge cases for selector parsing.""" - - # Empty selector with quotes - this should actually result in None since there's no content - result = parser.parse('kubectl get pods -l ""') - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - # Empty string in quotes results in no selector tokens, so value is None - assert flags["-l"] is None - - # Missing selector value (flag without value) - result = parser.parse("kubectl get pods -l") - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["-l"] is None - - # Empty selector value with equals - result = parser.parse("kubectl get pods --selector=") - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["--selector"] == "" - - # Selector followed by another flag - result = parser.parse("kubectl get pods -l app=nginx -o yaml") - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["-l"] == "app=nginx" - assert flags["-o"] == "yaml" - - # Complex selector - note that complex expressions with multiple 'in'/'notin' - # may not parse as expected due to the tokenization, but simple ones should work - result = parser.parse("kubectl get pods -l 'app in (web,api),env notin (dev)'") - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["-l"] == "app in (web,api),env notin (dev)" - - -def test_quoted_selector_compatibility(parser): - """Test that quoted selectors still work correctly.""" - - # Single quoted selector - result = parser.parse("kubectl get pods -l 'app in (nginx,apache)'") - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["-l"] == "app in (nginx,apache)" - - # Double quoted selector - result = parser.parse('kubectl get pods -l "service in (web,api)"') - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["-l"] == "service in (web,api)" - - # Quoted selector with equals format - result = parser.parse('kubectl get pods --selector="app in (frontend,backend)"') - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["--selector"] == "app in (frontend,backend)" - - -def test_field_selector_compatibility(parser): - """Test that field selectors still work correctly.""" - - # Field selector should use existing logic (not the special selector logic) - result = parser.parse( - "kubectl get services --all-namespaces --field-selector metadata.namespace!=default" - ) - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["--field-selector"] == "metadata.namespace!=default" - assert flags["--all-namespaces"] is None - - -def test_selector_with_mixed_flags(parser): - """Test selectors combined with other flags.""" - - # Selector with namespace and output format - result = parser.parse("kubectl get pods -n prod -l app in (web,api) -o wide") - assert result["command"]["namespace"] == "prod" - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["-n"] == "prod" - assert flags["-l"] == "app in (web,api)" - assert flags["-o"] == "wide" - - # Multiple complex flags including selector - result = parser.parse( - "kubectl get deployments --all-namespaces --selector=tier in (frontend,backend) --sort-by=.metadata.name" - ) - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["--all-namespaces"] is None - assert flags["--selector"] == "tier in (frontend,backend)" - assert flags["--sort-by"] == ".metadata.name" - - -def test_selector_coverage_edge_cases(parser): - """Test specific edge cases to achieve 100% coverage.""" - - # Test line 333: selector followed by a flag when paren_depth == 0 (normal case) - result = parser.parse("kubectl get pods -l app=nginx -o yaml") - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["-l"] == "app=nginx" - assert flags["-o"] == "yaml" - - # Test lines 369-370: empty selector tokens result in None value - result = parser.parse("kubectl get pods -l") - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["-l"] is None - - # Test lines 359-361: This tests the case where we have collected some tokens, - # paren_depth is 0, last token is NOT 'in' or 'notin', so we break - # This case: "app" followed by "nginx" (not an operator, not a flag) - result = parser.parse("kubectl get pods -l app nginx -o yaml") - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert ( - flags["-l"] == "app" - ) # Should stop at "app" because next token "nginx" is not an operator - assert flags["-o"] == "yaml" - assert "nginx" in result["command"]["args"] # nginx becomes an argument - - # Test lines 254-256: Same logic but in flag=value format - # Note: the flag=value format continues differently, so we expect different behavior - result = parser.parse("kubectl get pods --selector=app nginx -o yaml") - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["--selector"] == "app nginx" # flag=value format continues parsing - assert flags["-o"] == "yaml" - - -def test_selector_comprehensive_scenarios(parser): - """Test comprehensive selector scenarios.""" - - # Test unquoted selector with complex parenthetical expressions - result = parser.parse("kubectl get pods -l service in (email,checkout)") - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["-l"] == "service in (email,checkout)" - - # Test equals format with complex selector - result = parser.parse( - "kubectl get deployments --selector=service in (ad,cart,payment)" - ) - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["--selector"] == "service in (ad,cart,payment)" - - # Test mixed operators - result = parser.parse("kubectl get pods -l 'app=nginx,env!=prod'") - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["-l"] == "app=nginx,env!=prod" - - -def test_final_coverage_edge_cases(parser): - """Test remaining edge cases to achieve 100% coverage.""" - - # Test lines 254-256: flag=value format where last token is NOT 'in'/'notin' - # The break condition happens when the last token is not 'in'/'notin' and next is not an operator - result = parser.parse("kubectl get pods --selector=app=nginx unknown -o yaml") - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - # Based on actual behavior, it continues to parse - assert flags["--selector"] == "app=nginx unknown" - assert flags["-o"] == "yaml" - - # Test line 333: This is hit in normal flag parsing when we encounter a flag - # This should be hit by many existing tests, but let's be explicit - result = parser.parse("kubectl get pods -l app=test -o json") - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["-l"] == "app=test" - assert flags["-o"] == "json" - - -def test_parser_script_execution(): - """Test that parser.py script can be executed directly.""" - try: - # Run the parser.py script as a module - result = subprocess.run( - [sys.executable, "-m", "kubectlcmdprocessor.parser"], - capture_output=True, - text=True, - timeout=30, - ) - - # Check that the script ran successfully (exit code 0) - assert result.returncode == 0 - - # Check that some output was produced - assert len(result.stdout) > 0 - - # Check that no errors were written to stderr - assert result.stderr == "" - - except subprocess.TimeoutExpired: - pytest.fail("Script execution timed out") - except Exception as e: - pytest.fail(f"Script execution failed: {e}") diff --git a/scripts/policy_agent/red_feedback/tests/test_plugin.py b/scripts/policy_agent/red_feedback/tests/test_plugin.py deleted file mode 100644 index 351a7d0..0000000 --- a/scripts/policy_agent/red_feedback/tests/test_plugin.py +++ /dev/null @@ -1,220 +0,0 @@ -# Copyright 2026 Smith authors -# SPDX-License-Identifier: Apache-2.0 -"""Tests for kubectlcmdprocessor/plugin.py""" - -import pytest -from unittest.mock import Mock - -from kubectlcmdprocessor.plugin import ( - KubectlCmdProcessor, - CONTEXT_KEY_POLICY_CONTEXT, - CONTEXT_KEY_KUBECTL_CMD, -) -from mcpgateway.plugins.framework import ( - PluginConfig, - PluginContext, - ToolPreInvokePayload, -) - - -@pytest.fixture -def plugin_config(): - """Create a test plugin configuration.""" - return PluginConfig(name="test_kubectl_processor", kind="test") - - -@pytest.fixture -def plugin(plugin_config): - """Create a KubectlCmdProcessor plugin instance.""" - return KubectlCmdProcessor(plugin_config) - - -@pytest.fixture -def mock_context(): - """Create a mock plugin context.""" - context = Mock(spec=PluginContext) - context.global_context = Mock() - context.global_context.state = {} - return context - - -@pytest.mark.asyncio -async def test_plugin_initialization(plugin_config): - """Test plugin initialization.""" - plugin = KubectlCmdProcessor(plugin_config) - assert plugin is not None - assert plugin.config == plugin_config - - -@pytest.mark.asyncio -async def test_tool_pre_invoke_empty_args(plugin, mock_context): - """Test tool_pre_invoke with empty args.""" - payload = ToolPreInvokePayload(name="test_tool", args=None) - result = await plugin.tool_pre_invoke(payload, mock_context) - assert result.continue_processing is True - # State should remain empty when no args provided - assert len(mock_context.global_context.state) == 0 - - -@pytest.mark.asyncio -async def test_tool_pre_invoke_empty_dict_args(plugin, mock_context): - """Test tool_pre_invoke with empty dictionary args.""" - payload = ToolPreInvokePayload(name="test_tool", args={}) - result = await plugin.tool_pre_invoke(payload, mock_context) - assert result.continue_processing is True - # State should remain empty when empty args provided - assert len(mock_context.global_context.state) == 0 - - -@pytest.mark.asyncio -async def test_tool_pre_invoke_with_args(plugin, mock_context): - """Test tool_pre_invoke with valid args.""" - payload = ToolPreInvokePayload( - name="test_tool", args={"command": "kubectl get pods"} - ) - result = await plugin.tool_pre_invoke(payload, mock_context) - assert result.continue_processing is True - assert CONTEXT_KEY_POLICY_CONTEXT in mock_context.global_context.state - - -@pytest.mark.asyncio -async def test_process_args_single_argument(plugin, mock_context): - """Test processing single argument.""" - args = {"command": "kubectl get pods"} - await plugin.process_args_in_state(args, mock_context) - - assert CONTEXT_KEY_POLICY_CONTEXT in mock_context.global_context.state - policy_context = mock_context.global_context.state[CONTEXT_KEY_POLICY_CONTEXT] - assert CONTEXT_KEY_KUBECTL_CMD in policy_context - - # Verify the parsed command structure - kubectl_cmd = policy_context[CONTEXT_KEY_KUBECTL_CMD] - assert isinstance(kubectl_cmd, dict) - - -@pytest.mark.asyncio -async def test_process_args_multiple_arguments_raises_error(plugin, mock_context): - """Test that multiple arguments raise ValueError.""" - args = {"command1": "kubectl get pods", "command2": "kubectl get services"} - - with pytest.raises(ValueError, match="only works on single argument functions"): - await plugin.process_args_in_state(args, mock_context) - - -@pytest.mark.asyncio -async def test_process_args_kubectl_parser_integration(plugin, mock_context): - """Test integration with KubectlParser.""" - args = {"command": "kubectl get pods --namespace=default"} - await plugin.process_args_in_state(args, mock_context) - - policy_context = mock_context.global_context.state[CONTEXT_KEY_POLICY_CONTEXT] - kubectl_cmd = policy_context[CONTEXT_KEY_KUBECTL_CMD] - - # Verify parser output structure contains expected fields - assert "command" in kubectl_cmd - command_data = kubectl_cmd["command"] - assert "resource" in command_data - assert command_data["resource"] == "pods" - assert "namespace" in command_data - assert command_data["namespace"] == "default" - - -@pytest.mark.asyncio -async def test_process_args_with_complex_kubectl_command(plugin, mock_context): - """Test processing complex kubectl command.""" - args = { - "command": "kubectl apply -f deployment.yaml --namespace=production --dry-run=client" - } - await plugin.process_args_in_state(args, mock_context) - - policy_context = mock_context.global_context.state[CONTEXT_KEY_POLICY_CONTEXT] - kubectl_cmd = policy_context[CONTEXT_KEY_KUBECTL_CMD] - - # Verify complex command parsing - assert "command" in kubectl_cmd - command_data = kubectl_cmd["command"] - assert "flags" in command_data - # Check for namespace flag in the flags list - namespace_flag = next( - (flag for flag in command_data["flags"] if flag["name"] == "--namespace"), None - ) - assert namespace_flag is not None - assert namespace_flag["value"] == "production" - - -@pytest.mark.asyncio -async def test_process_args_with_non_kubectl_command(plugin, mock_context): - """Test processing non-kubectl command.""" - args = {"command": "ls -la"} - await plugin.process_args_in_state(args, mock_context) - - policy_context = mock_context.global_context.state[CONTEXT_KEY_POLICY_CONTEXT] - kubectl_cmd = policy_context[CONTEXT_KEY_KUBECTL_CMD] - - # Should still parse but may not have kubectl-specific structure - assert isinstance(kubectl_cmd, dict) - - -@pytest.mark.asyncio -async def test_process_args_with_empty_string(plugin, mock_context): - """Test processing empty string argument.""" - args = {"command": ""} - await plugin.process_args_in_state(args, mock_context) - - policy_context = mock_context.global_context.state[CONTEXT_KEY_POLICY_CONTEXT] - kubectl_cmd = policy_context[CONTEXT_KEY_KUBECTL_CMD] - - # Should handle empty string gracefully - assert isinstance(kubectl_cmd, dict) - - -@pytest.mark.asyncio -async def test_process_args_with_special_characters(plugin, mock_context): - """Test processing command with special characters.""" - args = {"command": "kubectl get pods --selector='app=nginx,version!=1.0'"} - await plugin.process_args_in_state(args, mock_context) - - policy_context = mock_context.global_context.state[CONTEXT_KEY_POLICY_CONTEXT] - kubectl_cmd = policy_context[CONTEXT_KEY_KUBECTL_CMD] - - # Should handle special characters in arguments - assert "command" in kubectl_cmd - command_data = kubectl_cmd["command"] - assert "resource" in command_data - assert command_data["resource"] == "pods" - - -@pytest.mark.asyncio -async def test_context_state_persistence(plugin, mock_context): - """Test that context state is properly updated and persists.""" - # Process first command - args1 = {"command": "kubectl get pods"} - await plugin.process_args_in_state(args1, mock_context) - - # Process second command - args2 = {"command": "kubectl get services"} - await plugin.process_args_in_state(args2, mock_context) - - # Verify state was updated (not just appended) - assert CONTEXT_KEY_POLICY_CONTEXT in mock_context.global_context.state - policy_context = mock_context.global_context.state[CONTEXT_KEY_POLICY_CONTEXT] - kubectl_cmd = policy_context[CONTEXT_KEY_KUBECTL_CMD] - - # Should contain the latest command - assert "command" in kubectl_cmd - command_data = kubectl_cmd["command"] - assert command_data["resource"] == "services" - - -@pytest.mark.asyncio -async def test_process_args_type_conversion(plugin, mock_context): - """Test that arguments are properly converted to strings.""" - # Test with non-string argument - args = {"command": 12345} - await plugin.process_args_in_state(args, mock_context) - - policy_context = mock_context.global_context.state[CONTEXT_KEY_POLICY_CONTEXT] - kubectl_cmd = policy_context[CONTEXT_KEY_KUBECTL_CMD] - - # Should handle type conversion gracefully - assert isinstance(kubectl_cmd, dict) diff --git a/scripts/policy_agent/reduce_improve/redundancy.sh b/scripts/policy_agent/reduce_improve/redundancy.sh deleted file mode 100644 index 43788c2..0000000 --- a/scripts/policy_agent/reduce_improve/redundancy.sh +++ /dev/null @@ -1,11 +0,0 @@ -# Copyright 2026 Smith authors -# SPDX-License-Identifier: Apache-2.0 - -# !/bin/bash -cd ../../ -make opaserver/parse -cd ./blue-agent-components/reduce_improve -mv ../../ast.json ./ -python parse_ast_to_graph.py ast.json -python ../../scripts/parse_dot_file_format.py ast.dot -python detect_redundancy.py > graph_redundancy.txt diff --git a/scripts/policy_agent/scripts/extract_case.py b/scripts/policy_agent/scripts/extract_case.py deleted file mode 100644 index a827119..0000000 --- a/scripts/policy_agent/scripts/extract_case.py +++ /dev/null @@ -1,70 +0,0 @@ -# Copyright 2026 Smith authors -# SPDX-License-Identifier: Apache-2.0 - -import glob -import os -import json -import pickle - - -def find_files_recursively(root_dir, pattern): - search_path = os.path.join(root_dir, "**", pattern) - matching_files = glob.glob(search_path, recursive=True) - return matching_files - - -def read_records_command(file_path="agent_analytics_sdk_logs*"): - files = find_files_recursively("./trace/", file_path) - command_line_all = [] - for f in files: - with open(f, "r") as file: - contents = file.read() - objects = contents.strip().split("\n}\n{") - objects[0] += "}" - for i in range(1, len(objects) - 1): - objects[i] = "{" + objects[i] + "}" - objects[-1] = "{" + objects[-1] - command_indexes = [] - record = {} - for obj in objects: - data = json.loads(obj) - if data["name"] == "chat.completions.create": - for data_key in data["attributes"].keys(): - if ("gen_ai.prompt") in data_key or ( - "gen_ai.completion" in data_key - ): - if ("content" in data_key) and data[ - "parent_id" - ] + "_" + data_key not in record.keys(): - record[data["parent_id"] + "_" + data_key] = data[ - "attributes" - ][data_key] - if data["name"] == "NL2Kubectl Tool.tool": - if data["status"]["status_code"] == "ERROR": - continue - record[ - data["context"]["span_id"] + "_" + "traceloop.entity.input" - ] = data["attributes"]["traceloop.entity.input"] - command_indexes.append(data["context"]["span_id"]) - command_line = record[ - command_indexes[-1] + "_" + "gen_ai.completion.0.content" - ] - command_line = process_command_format(command_line) - command_line_all.append(command_line) - return command_line_all - - -def process_command_format(command): - if len(command.split("\n")) == 3: - return command.split("\n")[1] - return "" - - -def save_file(data, filename): - with open(filename, "wb") as handle: - pickle.dump(data, handle) - - -command_line_all = read_records_command() -print(command_line_all) -save_file(command_line_all, "extracted_cases.pkl") diff --git a/scripts/policy_agent/scripts/extract_commands.py b/scripts/policy_agent/scripts/extract_commands.py deleted file mode 100644 index bd75470..0000000 --- a/scripts/policy_agent/scripts/extract_commands.py +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/env python3 -# Copyright 2026 Smith authors -# SPDX-License-Identifier: Apache-2.0 - -import json -from pathlib import Path -from kubectlcmdprocessor.parser import KubectlParser - - -def extract_original_commands(directory_path): - commands = [] - json_files = Path(directory_path).glob("*.json") - - for json_file in sorted(json_files): - try: - with open(json_file, "r") as f: - data = json.load(f) - original_command = data.get("input", {}).get("original command", "") - if original_command: - commands.append(original_command.strip()) - except (json.JSONDecodeError, FileNotFoundError) as e: - print(f"Error reading {json_file}: {e}") - - return commands - - -if __name__ == "__main__": - directory = "tests/integration/inputs/benign_commands" - commands = extract_original_commands(directory) - - parser = KubectlParser() - - print("Original commands found:") - for i, command in enumerate(commands, 1): - print(f"{i}. {command}") - with open( - f"tests/integration/new_inputs/benign_commands/processed_command{i}.json", - "w", - ) as f: - f.write( - json.dumps( - { - "input": { - **parser.parse(command), - **{"original_command": command}, - } - }, - indent=2, - ) - ) - - print(f"\nTotal commands: {len(commands)}") diff --git a/scripts/policy_agent/scripts/io.py b/scripts/policy_agent/scripts/io.py deleted file mode 100644 index 7065228..0000000 --- a/scripts/policy_agent/scripts/io.py +++ /dev/null @@ -1,61 +0,0 @@ -# Copyright 2026 Smith authors -# SPDX-License-Identifier: Apache-2.0 - -import sys - -from beeai_framework.utils.models import ModelLike, to_model_optional -from pydantic import BaseModel -from termcolor import colored - - -class ReaderOptions(BaseModel): - fallback: str = "" - input: str = "User 👤 : " - allow_empty: bool = False - - -class ConsoleReader: - def __init__(self, options: ModelLike[ReaderOptions] | None = None) -> None: - options = to_model_optional(ReaderOptions, options) or ReaderOptions() - self.fallback = options.fallback - self.input = options.input - self.allow_empty = options.allow_empty - - def __iter__(self) -> "ConsoleReader": - print("Interactive session has started. To escape, input 'q' and submit.") - return self - - def __next__(self) -> str: - try: - while True: - prompt = input(colored(self.input, "cyan", attrs=["bold"])).strip() - if not sys.stdin.isatty(): - print(prompt) - - if prompt == "q": - raise StopIteration - - if not prompt: - prompt = self.fallback - self.write(self.input, prompt) - - if not prompt and not self.allow_empty: - print("Error: Empty prompt is not allowed. Please try again.") - continue - - return prompt - except (EOFError, KeyboardInterrupt): - print() - exit() - - def write(self, role: str, data: str) -> None: - print(colored(role, "red", attrs=["bold"]), data) - - def prompt(self) -> str | None: - for prompt in self: - return prompt - exit() - - def ask_single_question(self, query_message: str) -> str: - answer = input(colored(query_message, "cyan", attrs=["bold"])) - return answer.strip() diff --git a/scripts/policy_agent/scripts/parse_commands.py b/scripts/policy_agent/scripts/parse_commands.py deleted file mode 100644 index 743f915..0000000 --- a/scripts/policy_agent/scripts/parse_commands.py +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env python3 -# Copyright 2026 Smith authors -# SPDX-License-Identifier: Apache-2.0 - -import json -from pathlib import Path -from kubectlcmdprocessor.parser import KubectlParser - - -def extract_commands(file_path): - commands = [] - file = Path(file_path) - - with open(file, "r") as f: - for command in f: - commands.append(command.strip()) - - return commands - - -if __name__ == "__main__": - directory = "commands" - commands = extract_commands(directory) - - parser = KubectlParser() - - print("Original commands found:") - for i, command in enumerate(commands, 1): - print(f"{i}. {command}") - with open(f"tests/unlabeled_command{i}.json", "w") as f: - f.write( - json.dumps( - { - "input": { - **parser.parse(command), - **{"original_command": command}, - } - }, - indent=2, - ) - ) - - print(f"\nTotal commands: {len(commands)}") diff --git a/scripts/test_generation/ares/.github/ISSUE_TEMPLATE/bug-report.md b/scripts/test_generation/ares/.github/ISSUE_TEMPLATE/bug-report.md deleted file mode 100644 index 6510e1b..0000000 --- a/scripts/test_generation/ares/.github/ISSUE_TEMPLATE/bug-report.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -name: Bug report -about: Notify the maintainers of a bug -title: "" -labels: "" -assignees: "" ---- - -**Describe the problem** - - - -**Describe steps to replicate the issue** - - - -**Additional context** - - diff --git a/scripts/test_generation/ares/.github/ISSUE_TEMPLATE/feature-request.md b/scripts/test_generation/ares/.github/ISSUE_TEMPLATE/feature-request.md deleted file mode 100644 index c06a6fd..0000000 --- a/scripts/test_generation/ares/.github/ISSUE_TEMPLATE/feature-request.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -name: Feature request -about: Suggest an idea for this project -title: "" -labels: "" -assignees: "" ---- - - - -**Is your feature request related to a problem? If so, please describe.** - - - -**Describe your proposed solution** - - - -**Describe alternatives you have considered** - - - -**Additional context** - - diff --git a/scripts/test_generation/ares/.github/workflows/cleanup-cache.yaml b/scripts/test_generation/ares/.github/workflows/cleanup-cache.yaml deleted file mode 100644 index 6909d31..0000000 --- a/scripts/test_generation/ares/.github/workflows/cleanup-cache.yaml +++ /dev/null @@ -1,29 +0,0 @@ -name: Cleanup github runner caches on closed pull requests -on: - pull_request: - types: - - closed - -jobs: - cleanup: - runs-on: ubuntu-latest - permissions: - actions: write - steps: - - name: Cleanup - run: | - echo "Fetching list of cache keys" - cacheKeysForPR=$(gh cache list --ref $BRANCH --limit 100 --json id --jq '.[].id') - - ## Setting this to not fail the workflow while deleting cache keys. - set +e - echo "Deleting caches..." - for cacheKey in $cacheKeysForPR - do - gh cache delete $cacheKey - done - echo "Done" - env: - GH_TOKEN: ${{ github.token }} - GH_REPO: ${{ github.repository }} - BRANCH: refs/pull/${{ github.event.pull_request.number }}/merge diff --git a/scripts/test_generation/ares/.github/workflows/codeql.yml b/scripts/test_generation/ares/.github/workflows/codeql.yml deleted file mode 100644 index be871a6..0000000 --- a/scripts/test_generation/ares/.github/workflows/codeql.yml +++ /dev/null @@ -1,98 +0,0 @@ -# For most projects, this workflow file will not need changing; you simply need -# to commit it to your repository. -# -# You may wish to alter this file to override the set of languages analyzed, -# or to provide custom queries or build logic. -# -# ******** NOTE ******** -# We have attempted to detect the languages in your repository. Please check -# the `language` matrix defined below to confirm you have the correct set of -# supported CodeQL languages. -# -name: "CodeQL Advanced" - -on: - push: - branches: [ "main" ] - pull_request: - branches: [ "main" ] - schedule: - - cron: '35 7 * * 1' - -jobs: - analyze: - name: Analyze (${{ matrix.language }}) - # Runner size impacts CodeQL analysis time. To learn more, please see: - # - https://gh.io/recommended-hardware-resources-for-running-codeql - # - https://gh.io/supported-runners-and-hardware-resources - # - https://gh.io/using-larger-runners (GitHub.com only) - # Consider using larger runners or machines with greater resources for possible analysis time improvements. - runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }} - permissions: - # required for all workflows - security-events: write - - # required to fetch internal or private CodeQL packs - packages: read - - # only required for workflows in private repositories - actions: read - contents: read - - strategy: - fail-fast: false - matrix: - include: - - language: python - build-mode: none - # CodeQL supports the following values keywords for 'language': 'actions', 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'rust', 'swift' - # Use `c-cpp` to analyze code written in C, C++ or both - # Use 'java-kotlin' to analyze code written in Java, Kotlin or both - # Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both - # To learn more about changing the languages that are analyzed or customizing the build mode for your analysis, - # see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning. - # If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how - # your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages - steps: - - name: Checkout repository - uses: actions/checkout@v6 - - # Add any setup steps before running the `github/codeql-action/init` action. - # This includes steps like installing compilers or runtimes (`actions/setup-node` - # or others). This is typically only required for manual builds. - # - name: Setup runtime (example) - # uses: actions/setup-example@v1 - - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v4 - with: - languages: ${{ matrix.language }} - build-mode: ${{ matrix.build-mode }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. - - # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs - # queries: security-extended,security-and-quality - - # If the analyze step fails for one of the languages you are analyzing with - # "We were unable to automatically build your code", modify the matrix above - # to set the build mode to "manual" for that language. Then modify this step - # to build your code. - # ℹ️ Command-line programs to run using the OS shell. - # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun - - if: matrix.build-mode == 'manual' - shell: bash - run: | - echo 'If you are using a "manual" build mode for one or more of the' \ - 'languages you are analyzing, replace this with the commands to build' \ - 'your code, for example:' - echo ' make bootstrap' - echo ' make release' - exit 1 - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v4 - with: - category: "/language:${{matrix.language}}" diff --git a/scripts/test_generation/ares/.github/workflows/docs-check.yaml b/scripts/test_generation/ares/.github/workflows/docs-check.yaml deleted file mode 100644 index 2d2d02c..0000000 --- a/scripts/test_generation/ares/.github/workflows/docs-check.yaml +++ /dev/null @@ -1,42 +0,0 @@ -name: Docs check - -on: [pull_request] - -jobs: - build: - runs-on: ubuntu-latest - steps: - - name: Checkout repo - uses: actions/checkout@v6 - - name: Setup python - uses: actions/setup-python@v6 - with: - python-version: 3.11 - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install .[dev] - - name: Build docs - run: | - sphinx-apidoc -o docs/source/ src/ares/ - make -C docs/ html 2>&1 | tee docs/build.log - - name: Validate build - run: | - grep -Einw 'Error:|Warning:' docs/build.log | while read -r line; do - lineno=$(echo "$line" | cut -d: -f1) - message=$(echo "$line" | cut -d: -f2-) - if echo "$message" | grep -iq 'error'; then - echo "::error line=$lineno::$message" - else - echo "::warning line=$lineno::$message" - fi - done - if ! grep -Ein 'build succeeded' docs/build.log; then - echo "Build did not succeed." - exit 1 - fi - - name: Upload preview docs - uses: actions/upload-artifact@v6 - with: - name: preview docs - path: docs/build/html/ diff --git a/scripts/test_generation/ares/.github/workflows/docs-publish.yaml b/scripts/test_generation/ares/.github/workflows/docs-publish.yaml deleted file mode 100644 index c8cdde5..0000000 --- a/scripts/test_generation/ares/.github/workflows/docs-publish.yaml +++ /dev/null @@ -1,49 +0,0 @@ -name: Publish Docs - -on: - push: - branches: - - main - -jobs: - build: - runs-on: ubuntu-latest - steps: - - name: Checkout repo - uses: actions/checkout@v6 - - name: Setup python - uses: actions/setup-python@v6 - with: - python-version: 3.11 - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install .[dev] - - name: Build docs - run: | - sphinx-apidoc -o docs/source/ src/ares/ - make -C docs/ html 2>&1 | tee docs/build.log - - name: Prepare docs for publishing - run: | - mkdir gh-pages - cp -r docs/build/html/* gh-pages/ - cd gh-pages - touch .nojekyll - - name: Upload static files as artifact - id: deployment - uses: actions/upload-pages-artifact@v4 - with: - path: gh-pages/ - deploy: - environment: - name: github-pages - url: ${{ steps.deployment.outputs.page_url }} - runs-on: ubuntu-latest - needs: build - permissions: - pages: write - id-token: write - steps: - - name: Deploy to Github pages - id: deployment - uses: actions/deploy-pages@v4 diff --git a/scripts/test_generation/ares/.github/workflows/linting.yml b/scripts/test_generation/ares/.github/workflows/linting.yml deleted file mode 100644 index c0fbf33..0000000 --- a/scripts/test_generation/ares/.github/workflows/linting.yml +++ /dev/null @@ -1,28 +0,0 @@ -name: Guarantee formatting - -on: [push, pull_request] - -jobs: - lint: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v6 - - uses: actions/setup-python@v6 - with: - python-version: 3.11 - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install ".[dev]" - - name: Run ruff - run: ruff check --output-format=github src tests - - name: Run bandit - run: | - bandit -c bandit.yaml -r src - - name: Run ruff check on tests - run: | - for p in plugins/*; do - test $p = "plugins/new-plugin-template" && continue - test $p = "plugins/ares-icarus-connector" && continue - test -d $p && ruff check --output-format=github $p/{src,tests} - done diff --git a/scripts/test_generation/ares/.github/workflows/release.yml b/scripts/test_generation/ares/.github/workflows/release.yml deleted file mode 100644 index b128431..0000000 --- a/scripts/test_generation/ares/.github/workflows/release.yml +++ /dev/null @@ -1,83 +0,0 @@ -name: Publish Python 🐍 distribution 📦 to PyPI and TestPyPI - -on: - push: - branches: - - main - tags: - - "v*" - -jobs: - build: - name: Build distribution 📦 - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v6 - with: - persist-credentials: false - - name: Set up Python - uses: actions/setup-python@v6 - with: - python-version: "3.11" - - name: Install pypa/build - run: >- - python -m - pip install - build - --user - - name: Build a binary wheel and a source tarball - run: python -m build - - name: Store the distribution packages - uses: actions/upload-artifact@v6 - with: - name: python-package-distributions - path: dist/ - - publish-to-pypi: - name: >- - Publish Python 🐍 distribution 📦 to PyPI - if: startsWith(github.ref, 'refs/tags/') # only publish to PyPI on tag pushes - needs: - - build - runs-on: ubuntu-latest - environment: - name: pypi - url: https://pypi.org/p/ares-redteamer # Replace with your PyPI project name - permissions: - id-token: write - - steps: - - name: Download all the dists - uses: actions/download-artifact@v7 - with: - name: python-package-distributions - path: dist/ - - name: Publish distribution 📦 to PyPI - uses: pypa/gh-action-pypi-publish@release/v1 - - publish-to-testpypi: - name: Publish Python 🐍 distribution 📦 to TestPyPI - needs: - - build - runs-on: ubuntu-latest - - environment: - name: testpypi - url: https://test.pypi.org/p/ares-redteamer - - permissions: - id-token: write - - steps: - - name: Download all the dists - uses: actions/download-artifact@v7 - with: - name: python-package-distributions - path: dist/ - - name: Publish distribution 📦 to TestPyPI - uses: pypa/gh-action-pypi-publish@release/v1 - with: - repository-url: https://test.pypi.org/legacy/ - verbose: true - skip-existing: true diff --git a/scripts/test_generation/ares/.github/workflows/testing.yml b/scripts/test_generation/ares/.github/workflows/testing.yml deleted file mode 100644 index 4a70fe2..0000000 --- a/scripts/test_generation/ares/.github/workflows/testing.yml +++ /dev/null @@ -1,60 +0,0 @@ -name: Testing Core - -on: [push, pull_request] - -jobs: - testing: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v6 - - uses: actions/setup-python@v6 - with: - python-version: 3.11 - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install ".[dev]" - - name: Test - run: pytest --junitxml=junit/test-results.xml --cov=ares --cov-report=xml --cov-report=html tests - - test-plugins: - runs-on: ubuntu-latest - needs: testing - strategy: - matrix: - plugin_name: [ - "ares-cyberseceval", - "ares-deepteam", - "ares-dynamic-llm", - "ares-echo-chamber", - "ares-garak", - "ares-granite-io", - "ares-human-jailbreak", - "ares-litellm", - "ares-mcp-connector", - "ares-pyrit", - "ares-vllm-connector", - "ares-watsonx-orchestrate", - "ares-tap", - "ares-autodan", - # "ares-intrinsics", - # "ares-lora-adapter-connector", - # "ares-gcg", - ] - steps: - - uses: actions/checkout@v6 - - uses: actions/setup-python@v6 - with: - python-version: 3.11 - - name: Install ARES - run: | - python -m pip install --upgrade pip - pip install ".[dev]" - - name: Install plugin dependencies - run: | - pushd ./plugins/${{matrix.plugin_name}} - pip install -r ./requirements.txt - - name: Test - run: | - pushd ./plugins/${{matrix.plugin_name}} - pytest --junitxml=junit/test-results.xml --cov=ares --cov-report=xml --cov-report=html tests diff --git a/scripts/test_generation/ares/.gitignore b/scripts/test_generation/ares/.gitignore deleted file mode 100644 index 28d5b16..0000000 --- a/scripts/test_generation/ares/.gitignore +++ /dev/null @@ -1,178 +0,0 @@ -venv -# Byte-compiled / optimized / DLL files -__pycache__/ -*.py[cod] -*$py.class - -# C extensions -*.so - -# Distribution / packaging -.Python -build/ -develop-eggs/ -dist/ -downloads/ -eggs/ -.eggs/ -lib/ -lib64/ -parts/ -sdist/ -var/ -wheels/ -share/python-wheels/ -*.egg-info/ -.installed.cfg -*.egg -MANIFEST - -# PyInstaller -# Usually these files are written by a python script from a template -# before PyInstaller builds the exe, so as to inject date/other infos into it. -*.manifest -*.spec - -# Installer logs -pip-log.txt -pip-delete-this-directory.txt - -# Unit test / coverage reports -htmlcov/ -.tox/ -.nox/ -.coverage -.coverage.* -.cache -nosetests.xml -coverage.xml -*.cover -*.py,cover -.hypothesis/ -.pytest_cache/ -cover/ - -# Translations -*.mo -*.pot - -# Django stuff: -*.log -local_settings.py -db.sqlite3 -db.sqlite3-journal - -# Flask stuff: -instance/ -.webassets-cache - -# Scrapy stuff: -.scrapy - -# Sphinx documentation -docs/_build/ - -# PyBuilder -.pybuilder/ -target/ - -# Jupyter Notebook -.ipynb_checkpoints - -# IPython -profile_default/ -ipython_config.py - -# pyenv -# For a library or package, you might want to ignore these files since the code is -# intended to run in multiple environments; otherwise, check them in: -# .python-version - -# pipenv -# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. -# However, in case of collaboration, if having platform-specific dependencies or dependencies -# having no cross-platform support, pipenv may install dependencies that don't work, or not -# install all needed dependencies. -#Pipfile.lock - -# poetry -# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. -# This is especially recommended for binary packages to ensure reproducibility, and is more -# commonly ignored for libraries. -# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control -#poetry.lock - -# pdm -# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. -#pdm.lock -# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it -# in version control. -# https://pdm.fming.dev/latest/usage/project/#working-with-version-control -.pdm.toml -.pdm-python -.pdm-build/ - -# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm -__pypackages__/ - -# Celery stuff -celerybeat-schedule -celerybeat.pid - -# SageMath parsed files -*.sage.py - -# Environments -.env -.venv -env/ -venv/ -ENV/ -env.bak/ -venv.bak/ - -# Spyder project settings -.spyderproject -.spyproject - -# Rope project settings -.ropeproject - -# mkdocs documentation -/site - -# mypy -.mypy_cache/ -.dmypy.json -dmypy.json - -# Pyre type checker -.pyre/ - -# pytype static type analyzer -.pytype/ - -# Cython debug symbols -cython_debug/ - -# PyCharm -# JetBrains specific template is maintained in a separate JetBrains.gitignore that can -# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore -# and can be added to the global gitignore or merged into this file. For a more nuclear -# option (not recommended) you can uncomment the following to ignore the entire idea folder. -#.idea/ - -# VSCode - -.vscode - -assets/*.csv -results/goals/* - - -tests/results/goals/*.json -tests/results/*.json -.DS_Store -results/*.json -.python-version -uv.lock diff --git a/scripts/test_generation/ares/.pre-commit-config.yaml b/scripts/test_generation/ares/.pre-commit-config.yaml deleted file mode 100644 index 8354c03..0000000 --- a/scripts/test_generation/ares/.pre-commit-config.yaml +++ /dev/null @@ -1,87 +0,0 @@ -default_install_hook_types: - - pre-commit - - commit-msg - -exclude: ^(docs)$ -repos: -- repo: https://github.com/pre-commit/pre-commit-hooks - rev: v6.0.0 - hooks: - - id: check-ast - - id: check-case-conflict - - id: check-json - - id: check-yaml - args: [ -m ] - - id: debug-statements - - id: end-of-file-fixer - exclude: docs/|sphinx/ - - id: check-shebang-scripts-are-executable - - id: forbid-submodules - - id: mixed-line-ending - - id: name-tests-test - args: [ --pytest-test-first ] - - id: check-added-large-files -- repo: https://github.com/abravalheri/validate-pyproject - rev: v0.25 - hooks: - - id: validate-pyproject - # Optional extra validations from SchemaStore: - additional_dependencies: ["validate-pyproject-schema-store[all]"] -- repo: https://github.com/astral-sh/ruff-pre-commit - # Ruff version. - rev: v0.15.8 - hooks: - # Run the linter. - - id: ruff-check - # Run the formatter. - - id: ruff-format -- repo: https://github.com/PyCQA/bandit - rev: 1.9.4 # Update me! - hooks: - - id: bandit - args: [-c, 'bandit.yaml'] -- repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.20.0 - hooks: - - id: mypy - args: ["--install-types", "--non-interactive"] - exclude: tests/|docs/|sphinx/|plugins/.*/setup.py -- repo: https://github.com/srstevenson/nb-clean - rev: 4.0.1 - hooks: - - id: nb-clean - args: - - --remove-empty-cells - - --preserve-cell-metadata - - tags - - slideshow - - -- -- repo: https://github.com/IBM/detect-secrets - # If you desire to use a specific version of detect-secrets, you can replace `master` with other git revisions such as branch, tag or commit sha. - # You are encouraged to use static refs such as tags, instead of branch name - # - # Running "pre-commit autoupdate" would automatically updates rev to latest tag - rev: 0.13.1+ibm.64.dss - hooks: - - id: detect-secrets # pragma: whitelist secret - # Add options for detect-secrets-hook binary. You can run `detect-secrets-hook --help` to list out all possible options. - # You may also run `pre-commit run detect-secrets` to preview the scan result. - # when "--baseline" without "--use-all-plugins", pre-commit scan with just plugins in baseline file - # when "--baseline" with "--use-all-plugins", pre-commit scan with all available plugins - args: [ - --baseline, - .secrets.baseline, - --use-all-plugins, - --fail-on-unaudited, - ] - additional_dependencies: [boxsdk<4] -- repo: https://github.com/compilerla/conventional-pre-commit - rev: "v4.4.0" - hooks: - - id: conventional-pre-commit - stages: [commit-msg] - args: [--verbose] -- repo: https://github.com/koalaman/shellcheck-precommit - rev: v0.11.0 - hooks: - - id: shellcheck diff --git a/scripts/test_generation/ares/.readthedocs.yaml b/scripts/test_generation/ares/.readthedocs.yaml deleted file mode 100644 index 2d23504..0000000 --- a/scripts/test_generation/ares/.readthedocs.yaml +++ /dev/null @@ -1,28 +0,0 @@ -# Read the Docs configuration file -# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details - -# Required -version: 2 - -# Set the OS, Python version, and other tools you might need -build: - os: ubuntu-24.04 - tools: - python: "3.11" - jobs: - pre_build: - - sphinx-apidoc -o docs/source/ src/ares/ - -# Build documentation in the "docs/" directory with Sphinx -sphinx: - configuration: docs/source/conf.py - -# Optionally, but recommended, -# declare the Python requirements required to build your documentation -# See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html -python: - install: - - method: pip - path: . - extra_requirements: - - dev diff --git a/scripts/test_generation/ares/.secrets.baseline b/scripts/test_generation/ares/.secrets.baseline deleted file mode 100644 index 075b389..0000000 --- a/scripts/test_generation/ares/.secrets.baseline +++ /dev/null @@ -1,542 +0,0 @@ -{ - "exclude": { - "files": null, - "lines": null - }, - "generated_at": "2026-05-01T12:27:23Z", - "plugins_used": [ - { - "name": "AWSKeyDetector" - }, - { - "name": "ArtifactoryDetector" - }, - { - "name": "AzureStorageKeyDetector" - }, - { - "base64_limit": 4.5, - "name": "Base64HighEntropyString" - }, - { - "name": "BasicAuthDetector" - }, - { - "name": "BoxDetector" - }, - { - "name": "CloudantDetector" - }, - { - "ghe_instance": "github.ibm.com", - "name": "GheDetector" - }, - { - "name": "GitHubTokenDetector" - }, - { - "hex_limit": 3, - "name": "HexHighEntropyString" - }, - { - "name": "IbmCloudIamDetector" - }, - { - "name": "IbmCosHmacDetector" - }, - { - "name": "JwtTokenDetector" - }, - { - "keyword_exclude": null, - "name": "KeywordDetector" - }, - { - "name": "MailchimpDetector" - }, - { - "name": "NpmDetector" - }, - { - "name": "PrivateKeyDetector" - }, - { - "name": "SlackDetector" - }, - { - "name": "SoftlayerDetector" - }, - { - "name": "SquareOAuthDetector" - }, - { - "name": "StripeDetector" - }, - { - "name": "TwilioKeyDetector" - } - ], - "results": { - "assets/safety_behaviors_text_subset.csv": [ - { - "hashed_secret": "63982e54a7aeb0d89910475ba6dbd3ca6dd4e5a1", - "is_secret": false, - "is_verified": false, - "line_number": 1001, - "type": "Hex High Entropy String", - "verified_result": null - }, - { - "hashed_secret": "b3d08d639d94a8af0fb38810e8849f71da609e81", - "is_secret": false, - "is_verified": false, - "line_number": 1445, - "type": "Hex High Entropy String", - "verified_result": null - } - ], - "docs/source/cli_reference.rst": [ - { - "hashed_secret": "11fa7c37d697f30e6aee828b4426a10f83ab2380", - "is_secret": false, - "is_verified": false, - "line_number": 392, - "type": "Secret Keyword", - "verified_result": null - }, - { - "hashed_secret": "ac4154b035c704d736cb79c39c811b8f7f5ee2ec", - "is_secret": false, - "is_verified": false, - "line_number": 399, - "type": "Secret Keyword", - "verified_result": null - }, - { - "hashed_secret": "d413f4d18c4c123dd52776f417b792efdec29c6a", - "is_secret": false, - "is_verified": false, - "line_number": 405, - "type": "Secret Keyword", - "verified_result": null - } - ], - "example_configs/connectors.yaml": [ - { - "hashed_secret": "cca04aa5bbf459bb406df2c401738966138d0dba", - "is_secret": false, - "is_verified": false, - "line_number": 80, - "type": "Secret Keyword", - "verified_result": null - } - ], - "example_configs/plugins/ares_gcg/connectors.yaml": [ - { - "hashed_secret": "cca04aa5bbf459bb406df2c401738966138d0dba", - "is_secret": false, - "is_verified": false, - "line_number": 81, - "type": "Secret Keyword", - "verified_result": null - } - ], - "example_configs/plugins/ares_pyrit/crescendo_rest_example.yaml": [ - { - "hashed_secret": "cca04aa5bbf459bb406df2c401738966138d0dba", - "is_secret": false, - "is_verified": false, - "line_number": 59, - "type": "Secret Keyword", - "verified_result": null - } - ], - "example_configs/plugins/ares_tap/assets/safety_behaviors_text_subset.csv": [ - { - "hashed_secret": "63982e54a7aeb0d89910475ba6dbd3ca6dd4e5a1", - "is_secret": false, - "is_verified": false, - "line_number": 1001, - "type": "Hex High Entropy String", - "verified_result": null - }, - { - "hashed_secret": "b3d08d639d94a8af0fb38810e8849f71da609e81", - "is_secret": false, - "is_verified": false, - "line_number": 1445, - "type": "Hex High Entropy String", - "verified_result": null - } - ], - "notebooks/Multi_Agent_Coalition_Attack_with_ARES.ipynb": [ - { - "hashed_secret": "b5563a7a0710c256cd57b36137c65fa4981cbfbd", - "is_secret": false, - "is_verified": false, - "line_number": 526, - "type": "Secret Keyword", - "verified_result": null - }, - { - "hashed_secret": "4486c8f50ada44988a7ad09c5e3b54d2ec95e0b4", - "is_secret": false, - "is_verified": false, - "line_number": 527, - "type": "Secret Keyword", - "verified_result": null - }, - { - "hashed_secret": "d68abc3dd0d778bc0fb5f47f4482736e4f99f3d0", - "is_secret": false, - "is_verified": false, - "line_number": 547, - "type": "Secret Keyword", - "verified_result": null - }, - { - "hashed_secret": "d01c164e129a51be8340ee8691455f99594979aa", - "is_secret": false, - "is_verified": false, - "line_number": 550, - "type": "Secret Keyword", - "verified_result": null - }, - { - "hashed_secret": "7abc0ddc80352a9ee95c5e48de24669e760b360e", - "is_secret": false, - "is_verified": false, - "line_number": 591, - "type": "Secret Keyword", - "verified_result": null - }, - { - "hashed_secret": "951a833ed2a2ae5d83ddedcc779eb6c1d73a0921", - "is_secret": false, - "is_verified": false, - "line_number": 850, - "type": "Base64 High Entropy String", - "verified_result": null - } - ], - "notebooks/direct_requests_notebook.ipynb": [ - { - "hashed_secret": "9c8f484b6d16e720d13faf70f4cd6f01bde37c6a", - "is_secret": false, - "is_verified": false, - "line_number": 307, - "type": "Hex High Entropy String", - "verified_result": null - }, - { - "hashed_secret": "656899c6ff464bcd9765410b98e56950d1a379b3", - "is_secret": false, - "is_verified": false, - "line_number": 376, - "type": "Hex High Entropy String", - "verified_result": null - } - ], - "notebooks/plugin_garak_notebook.ipynb": [ - { - "hashed_secret": "aa4e2a6e68da82ec3789791c10c58b625f1b4b33", - "is_secret": false, - "is_verified": false, - "line_number": 364, - "type": "Hex High Entropy String", - "verified_result": null - }, - { - "hashed_secret": "4d482ad237971791618596a396e8993ca359d46b", - "is_secret": false, - "is_verified": false, - "line_number": 389, - "type": "Hex High Entropy String", - "verified_result": null - }, - { - "hashed_secret": "48553a8949be78917ba891c2abb5e5edef10e6c6", - "is_secret": false, - "is_verified": false, - "line_number": 458, - "type": "Hex High Entropy String", - "verified_result": null - }, - { - "hashed_secret": "9dbafcd3be10e976ac34e674c30b1bf1db8f0091", - "is_secret": false, - "is_verified": false, - "line_number": 480, - "type": "Hex High Entropy String", - "verified_result": null - } - ], - "notebooks/plugin_gcg_red_teamer.ipynb": [ - { - "hashed_secret": "7ea29123a31e6205d3938bef213bfa1d6bac1982", - "is_secret": false, - "is_verified": false, - "line_number": 215, - "type": "Hex High Entropy String", - "verified_result": null - }, - { - "hashed_secret": "6ac064704380c2be5775dde10f17349b99415fb5", - "is_secret": false, - "is_verified": false, - "line_number": 336, - "type": "Hex High Entropy String", - "verified_result": null - } - ], - "notebooks/plugin_human_jailbreak_notebook.ipynb": [ - { - "hashed_secret": "7c67af3e7d3919f8dddd4d1614c49f5abd1722c3", - "is_secret": false, - "is_verified": false, - "line_number": 335, - "type": "Hex High Entropy String", - "verified_result": null - }, - { - "hashed_secret": "762eff8311c42d621de2a301d4fe4c5735bd0326", - "is_secret": false, - "is_verified": false, - "line_number": 404, - "type": "Hex High Entropy String", - "verified_result": null - } - ], - "notebooks/plugins/plugin_autodan_red_teamer.ipynb": [ - { - "hashed_secret": "a8fad62ff9fbd3ae6b24363028b3ca5fb0aab2df", - "is_secret": false, - "is_verified": false, - "line_number": 143, - "type": "Hex High Entropy String", - "verified_result": null - }, - { - "hashed_secret": "4e1c1b0b092fc727398c81ec18d5b6ce99c4e3fb", - "is_secret": false, - "is_verified": false, - "line_number": 213, - "type": "Hex High Entropy String", - "verified_result": null - }, - { - "hashed_secret": "e231f440d4caef55b100a6de48d999efc54ccf03", - "is_secret": false, - "is_verified": false, - "line_number": 1015, - "type": "Hex High Entropy String", - "verified_result": null - }, - { - "hashed_secret": "6afaf148e5b86d8226f28e46e7c32f904effcef6", - "is_secret": false, - "is_verified": false, - "line_number": 1050, - "type": "Hex High Entropy String", - "verified_result": null - } - ], - "notebooks/plugins/plugin_cyberseceval_notebook.ipynb": [ - { - "hashed_secret": "a7b7844213dbf70f4ad4f055064855e4ca1eeacd", - "is_secret": false, - "is_verified": false, - "line_number": 215, - "type": "Base64 High Entropy String", - "verified_result": null - }, - { - "hashed_secret": "c74c0f4709aa97cdd00e66fe187e0359706a4991", - "is_secret": false, - "is_verified": false, - "line_number": 225, - "type": "Base64 High Entropy String", - "verified_result": null - }, - { - "hashed_secret": "c492ad3e4f7d9af5759f6e29e319c706d915f42d", - "is_secret": false, - "is_verified": false, - "line_number": 234, - "type": "Base64 High Entropy String", - "verified_result": null - }, - { - "hashed_secret": "e0bf1c6f264f14cf5c83851993ba279871d614d5", - "is_secret": false, - "is_verified": false, - "line_number": 249, - "type": "Base64 High Entropy String", - "verified_result": null - }, - { - "hashed_secret": "549fc13497e66415b0c9682c8e75926010e11935", - "is_secret": false, - "is_verified": false, - "line_number": 259, - "type": "Base64 High Entropy String", - "verified_result": null - }, - { - "hashed_secret": "c49f3dfb2d83834778e01a6746936c4ecd1921c0", - "is_secret": false, - "is_verified": false, - "line_number": 268, - "type": "Base64 High Entropy String", - "verified_result": null - }, - { - "hashed_secret": "dd65b9de37bf09dda76ad7f1453f78e7a0e41003", - "is_secret": false, - "is_verified": false, - "line_number": 279, - "type": "Base64 High Entropy String", - "verified_result": null - }, - { - "hashed_secret": "b074cbbffac5faf634a0a9de7d522fb95af0e0f6", - "is_secret": false, - "is_verified": false, - "line_number": 288, - "type": "Base64 High Entropy String", - "verified_result": null - }, - { - "hashed_secret": "555c54ae2ac6e88b7a2d4b6fe69009599e5b9689", - "is_secret": false, - "is_verified": false, - "line_number": 333, - "type": "Base64 High Entropy String", - "verified_result": null - } - ], - "notebooks/plugins/plugin_gcg_notebook.ipynb": [ - { - "hashed_secret": "1fc87f510b0a0ebd0851b3cbbcad0605bac53c12", - "is_secret": false, - "is_verified": false, - "line_number": 119, - "type": "Hex High Entropy String", - "verified_result": null - }, - { - "hashed_secret": "f72afe7d099cf076ffd001fc2738e3651d815e64", - "is_secret": false, - "is_verified": false, - "line_number": 188, - "type": "Hex High Entropy String", - "verified_result": null - }, - { - "hashed_secret": "67a96ab8c5903d149fafd6d5297ee25db147e662", - "is_secret": false, - "is_verified": false, - "line_number": 414, - "type": "Hex High Entropy String", - "verified_result": null - }, - { - "hashed_secret": "e913ff7e5dd4d1d335ddce5adffa060811b9d57a", - "is_secret": false, - "is_verified": false, - "line_number": 564, - "type": "Hex High Entropy String", - "verified_result": null - }, - { - "hashed_secret": "e5e9e1a409dec2c738ea8e462d51def18fe74e6e", - "is_secret": false, - "is_verified": false, - "line_number": 578, - "type": "Hex High Entropy String", - "verified_result": null - }, - { - "hashed_secret": "87d08c581c9a28e5c083d48a53feb4a897dbafcc", - "is_secret": false, - "is_verified": false, - "line_number": 697, - "type": "Hex High Entropy String", - "verified_result": null - } - ], - "notebooks/plugins/plugin_pyrit_notebook.ipynb": [ - { - "hashed_secret": "c0ab555bb1840f2c7196b84dd864575a7c586a98", - "is_secret": false, - "is_verified": false, - "line_number": 347, - "type": "Hex High Entropy String", - "verified_result": null - }, - { - "hashed_secret": "d8aaae947e2cd65b17333d1c1c9063bb36ab2e26", - "is_secret": false, - "is_verified": false, - "line_number": 492, - "type": "Hex High Entropy String", - "verified_result": null - } - ], - "plugins/ares-dynamic-llm/README.md": [ - { - "hashed_secret": "5f8783364616d6efbb6d8d76410e5ba14f9963de", - "is_secret": false, - "is_verified": false, - "line_number": 148, - "type": "Secret Keyword", - "verified_result": null - } - ], - "plugins/ares-garak/tests/strategies/test_encoding_strategies.py": [ - { - "hashed_secret": "88620cfa0c6dddbdfefe3a326e991d9d31d225b1", - "is_secret": false, - "is_verified": false, - "line_number": 119, - "type": "Hex High Entropy String", - "verified_result": null - } - ], - "plugins/ares-garak/tests/test_resources/data/harmbench_attacks.json": [ - { - "hashed_secret": "88620cfa0c6dddbdfefe3a326e991d9d31d225b1", - "is_secret": false, - "is_verified": false, - "line_number": 5, - "type": "Hex High Entropy String", - "verified_result": null - } - ], - "plugins/ares-garak/tests/test_resources/data/harmbench_results.json": [ - { - "hashed_secret": "88620cfa0c6dddbdfefe3a326e991d9d31d225b1", - "is_secret": false, - "is_verified": false, - "line_number": 5, - "type": "Hex High Entropy String", - "verified_result": null - } - ], - "plugins/ares-granite-io/src/ares_granite_io/connectors/granite_io.py": [ - { - "hashed_secret": "8ed4322e8e2790b8c928d381ce8d07cfd966e909", - "is_secret": false, - "is_verified": false, - "line_number": 87, - "type": "Secret Keyword", - "verified_result": null - } - ] - }, - "version": "0.13.1+ibm.64.dss", - "word_list": { - "file": null, - "hash": null - } -} diff --git a/scripts/test_generation/extract_extensions.py b/scripts/test_generation/extract_extensions.py deleted file mode 100644 index 6f83267..0000000 --- a/scripts/test_generation/extract_extensions.py +++ /dev/null @@ -1,176 +0,0 @@ -# Copyright 2026 Smith authors -# SPDX-License-Identifier: Apache-2.0 - -""" -Extract extension variable values from test case prompts using LLM. - -Reads extension_variables.json (produced by the policy creation skill) -and for each test case, uses an LLM to extract the values of those extension -variables from the user's input prompt. - -Only handles extensions — NOT system variables (already in test cases) -and NOT MCP tool arguments (handled by process_test_batch.py). -""" - -import os -import json -import glob -from openai import OpenAI - - -def build_prompt(user_input: str, extension_vars: list, existing_subject: dict) -> str: - """Build LLM prompt to extract extension values from user input.""" - var_descriptions = [] - for var in extension_vars: - path = var["path"] - field_name = path.split(".")[-1] - if field_name in existing_subject: - continue - desc = f"- {path} ({var['type']})" - if var.get("candidates"): - desc += f" — possible values: {var['candidates']}" - if var.get("reason"): - desc += f" — {var['reason']}" - var_descriptions.append(desc) - - if not var_descriptions: - return None - - return f"""Given the user input below, extract values for the following extension variables. -These are contextual variables that can be inferred from what the user is asking. - -User Input: "{user_input}" - -Extension variables to extract: -{chr(10).join(var_descriptions)} - -Instructions: -- Only extract values that can be clearly inferred from the user input. -- If a value cannot be determined, use null. -- For list types, return a JSON array. -- For string types, return the exact value. - -Respond ONLY with a JSON object mapping the full path to the extracted value: -{{ - "": , - ... -}} -""" - - -def extract_extensions_for_case( - client, - model: str, - user_input: str, - extension_vars: list, - existing_subject: dict, - temp: float, - top_p: float, -) -> dict: - """Use LLM to extract extension values for one test case.""" - prompt = build_prompt(user_input, extension_vars, existing_subject) - if prompt is None: - return {} - - try: - response = client.chat.completions.create( - model=model, - messages=[ - { - "role": "system", - "content": "You extract contextual variable values from user prompts. Respond with valid JSON only.", - }, - {"role": "user", "content": prompt}, - ], - temperature=temp, - top_p=top_p, - ) - - content = response.choices[0].message.content.strip() - if content.startswith("```"): - content = content.split("\n", 1)[1] - content = content.rsplit("```", 1)[0] - - return json.loads(content) - - except Exception as e: - print(f" Warning: extraction failed for '{user_input[:50]}...': {e}") - return {} - - -def apply_extensions_to_case(test_case: dict, extracted: dict) -> dict: - """Apply extracted extension values into the test case's extensions.""" - for path, value in extracted.items(): - if value is None: - continue - parts = path.replace("input.", "").split(".") - target = test_case["input"]["extensions"] - for part in parts[:-1]: - if part == "extensions": - continue - if part not in target: - target[part] = {} - target = target[part] - target[parts[-1]] = value - - return test_case - - -def run_extract_extensions( - api_key, openai_base_url, model, temp, top_p, test_path, extension_vars_file -): - """Main function to extract extensions for all test cases.""" - client = OpenAI(api_key=api_key, base_url=openai_base_url) - - if not os.path.exists(extension_vars_file): - print( - f"No extension_variables.json found at {extension_vars_file}, skipping extension extraction." - ) - return - - with open(extension_vars_file, "r") as f: - content = f.read().strip() - if not content or content in ("{}", "[]"): - print("extension_variables.json is empty, skipping extension extraction.") - return - data = json.loads(content) - extension_vars = data.get("extension_variables", []) - - if not extension_vars: - print("No extension variables to extract. Exiting.") - return - - print(f"Extension variables to extract: {len(extension_vars)}") - for var in extension_vars: - print(f" {var['path']} — {var.get('reason', '')}") - - labels = ["allow", "disallow"] - total_processed = 0 - total_enriched = 0 - - for label in labels: - label_path = os.path.join(test_path, label, "*") - files = sorted(glob.glob(label_path)) - print(f"\nProcessing {len(files)} {label} cases...") - - for file_path in files: - with open(file_path, "r") as f: - test_case = json.load(f) - - user_input = test_case["input"]["extensions"]["agent"]["input"] - existing_subject = test_case["input"]["extensions"].get("subject", {}) - - extracted = extract_extensions_for_case( - client, model, user_input, extension_vars, existing_subject, temp, top_p - ) - total_processed += 1 - - if extracted and any(v is not None for v in extracted.values()): - test_case = apply_extensions_to_case(test_case, extracted) - total_enriched += 1 - with open(file_path, "w") as f: - json.dump(test_case, f, indent=4) - - print( - f"\nDone. Processed: {total_processed}, Enriched with extensions: {total_enriched}" - ) diff --git a/scripts/tests/integration/coverage/.gitkeep b/scripts/tests/integration/coverage/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/scripts/tests/integration/coverage/policy_test.rego b/scripts/tests/integration/coverage/policy_test.rego deleted file mode 100644 index e7debd4..0000000 --- a/scripts/tests/integration/coverage/policy_test.rego +++ /dev/null @@ -1,66 +0,0 @@ -# Copyright 2026 Smith authors -# SPDX-License-Identifier: Apache-2.0 - -package policy_test - -import data.policy - -test_allow_1 if { - policy.allow with input as {"kind": "tool_call", "action": "execute", "name": "ask_for_salary", "extensions": {"subject": {"id": "Bob", "type": "user", "roles": ["manager"], "teams": ["Sales"], "claims": {}, "permissions": ["write:purchase", "write:return_product", "write:send_email", "read:ask_for_workpolicy", "write:create_ticket", "write:submit_ticket", "read:get_w2_form", "read:ask_for_salary", "write:export_content_as_file"]}, "headers": {"x-request-id": "req-7f2a", "x-forwarded-for": "10.0.1.5"}, "labels": ["internal"], "agent": {"input": "Show me salary information for my team members", "session_id": "sess-9f3a", "conversation_id": "conv-17eb", "turn": 4}, "object": {"managed_by": "tool", "trust_domain": "internal", "data_scope": ["ticket_content"], "permissions": ["read:ask_for_salary"]}}, "arguments": {"format": "JSON", "time_range": "last_quarter", "include_benefits": True}} -} - -test_allow_2 if { - policy.allow with input as {"kind": "tool_call", "action": "execute", "name": "send_email", "extensions": {"subject": {"id": "Bob", "type": "user", "roles": ["employee"], "teams": ["Sales"], "claims": {}, "permissions": ["write:purchase", "write:return_product", "write:send_email", "read:ask_for_workpolicy", "write:create_ticket", "write:submit_ticket", "read:get_w2_form", "read:ask_for_salary", "write:export_content_as_file"]}, "headers": {"x-request-id": "req-7f2a", "x-forwarded-for": "10.0.1.5"}, "labels": ["internal"], "agent": {"input": "Send this document to contact@company.com", "session_id": "sess-9f3a", "conversation_id": "conv-17eb", "turn": 4}, "object": {"managed_by": "tool", "trust_domain": "internal", "data_scope": ["ticket_content"], "permissions": ["write:send_email"]}}, "arguments": {}} -} - -test_allow_3 if { - policy.allow with input as {"kind": "tool_call", "action": "execute", "name": "send_email", "extensions": {"subject": {"id": "Bob", "type": "user", "roles": ["manager"], "teams": ["Sales"], "claims": {}, "permissions": ["write:purchase", "write:return_product", "write:send_email", "read:ask_for_workpolicy", "write:create_ticket", "write:submit_ticket", "read:get_w2_form", "read:ask_for_salary", "write:export_content_as_file"]}, "headers": {"x-request-id": "req-7f2a", "x-forwarded-for": "10.0.1.5"}, "labels": ["internal"], "agent": {"input": "Send the project status report to client@external.com", "session_id": "sess-9f3a", "conversation_id": "conv-17eb", "turn": 4}, "object": {"managed_by": "tool", "trust_domain": "internal", "data_scope": ["ticket_content"], "permissions": ["write:send_email"]}}, "arguments": {"ticket_content": "Request to send project status report to external client\n\nDepartment: Sales\nRequester: Bob\n\nI need to send a project status report to client@external.com. The email system appears to be blocking this request. Please assist with:\n\n1. Sending the project status report to client@external.com\n2. Or providing alternative methods to share this report with the external client\n\nThe report contains standard project status information including milestones, accomplishments, and budget status.\n\nThank you for your assistance."}} -} - -test_allow_4 if { - policy.allow with input as {"kind": "tool_call", "action": "execute", "name": "export_compensation_data", "extensions": {"subject": {"id": "Bob", "type": "user", "roles": ["manager"], "teams": ["Sales"], "claims": {}, "permissions": ["write:purchase", "write:return_product", "write:send_email", "read:ask_for_workpolicy", "write:create_ticket", "write:submit_ticket", "read:get_w2_form", "read:ask_for_salary", "write:export_content_as_file"]}, "headers": {"x-request-id": "req-7f2a", "x-forwarded-for": "10.0.1.5"}, "labels": ["internal"], "agent": {"input": "Can you export the compensation data in JSON format?", "session_id": "sess-9f3a", "conversation_id": "conv-17eb", "turn": 4}, "object": {"managed_by": "tool", "trust_domain": "internal", "data_scope": ["ticket_content"], "permissions": ["read:export_compensation_data", "export:file"]}}, "arguments": {"format": "JSON"}} -} - -test_allow_5 if { - policy.allow with input as {"kind": "tool_call", "action": "execute", "name": "send_email", "extensions": {"subject": {"id": "Bob", "type": "user", "roles": ["manager"], "teams": ["Sales"], "claims": {}, "permissions": ["write:purchase", "write:return_product", "write:send_email", "read:ask_for_workpolicy", "write:create_ticket", "write:submit_ticket", "read:get_w2_form", "read:ask_for_salary", "write:export_content_as_file"]}, "headers": {"x-request-id": "req-7f2a", "x-forwarded-for": "10.0.1.5"}, "labels": ["internal"], "agent": {"input": "Email the meeting notes to partner@company.org", "session_id": "sess-9f3a", "conversation_id": "conv-17eb", "turn": 4}, "object": {"managed_by": "tool", "trust_domain": "internal", "data_scope": ["ticket_content"], "permissions": ["write:send_email"]}}, "arguments": {}} -} - -test_allow_6 if { - policy.allow with input as {"kind": "tool_call", "action": "execute", "name": "view_team_compensation", "extensions": {"subject": {"id": "Bob", "type": "user", "roles": ["manager"], "teams": ["Sales"], "claims": {}, "permissions": ["write:purchase", "write:return_product", "write:send_email", "read:ask_for_workpolicy", "write:create_ticket", "write:submit_ticket", "read:get_w2_form", "read:ask_for_salary", "write:export_content_as_file"]}, "headers": {"x-request-id": "req-7f2a", "x-forwarded-for": "10.0.1.5"}, "labels": ["internal"], "agent": {"input": "Display my Sales team compensation including names, titles, salaries, bonuses, departments, and hire dates", "session_id": "sess-9f3a", "conversation_id": "conv-17eb", "turn": 4}, "object": {"managed_by": "tool", "trust_domain": "internal", "data_scope": ["ticket_content"], "permissions": ["read:view_team_compensation"]}}, "arguments": {"select_fields": ["name", "title", "salary", "bonus", "department", "hire_date"]}} -} - -test_allow_7 if { - policy.allow with input as {"kind": "tool_call", "action": "execute", "name": "view_team_compensation", "extensions": {"subject": {"id": "Bob", "type": "user", "roles": ["manager"], "teams": ["HR"], "claims": {}, "permissions": ["write:purchase", "write:return_product", "write:send_email", "read:ask_for_workpolicy", "write:create_ticket", "write:submit_ticket", "read:get_w2_form", "read:ask_for_salary", "write:export_content_as_file"]}, "headers": {"x-request-id": "req-7f2a", "x-forwarded-for": "10.0.1.5"}, "labels": ["internal"], "agent": {"input": \"I need to review my HR team"s salary and bonus information\", "session_id": "sess-9f3a", "conversation_id": "conv-17eb", "turn": 4}, "object": {"managed_by": "tool", "trust_domain": "internal", "data_scope": ["ticket_content"], "permissions": ["read:view_team_compensation"]}}, "arguments": {"include_benefits": True, "format": "JSON"}} -} - -test_allow_8 if { - policy.allow with input as {"kind": "tool_call", "action": "execute", "name": "view_team_compensation", "extensions": {"subject": {"id": "Bob", "type": "user", "roles": ["manager"], "teams": ["IT"], "claims": {}, "permissions": ["write:purchase", "write:return_product", "write:send_email", "read:ask_for_workpolicy", "write:create_ticket", "write:submit_ticket", "read:get_w2_form", "read:ask_for_salary", "write:export_content_as_file"]}, "headers": {"x-request-id": "req-7f2a", "x-forwarded-for": "10.0.1.5"}, "labels": ["internal"], "agent": {"input": "Show me the compensation data for my IT team", "session_id": "sess-9f3a", "conversation_id": "conv-17eb", "turn": 4}, "object": {"managed_by": "tool", "trust_domain": "internal", "data_scope": ["ticket_content"], "permissions": ["read:view_team_compensation"]}}, "arguments": {}} -} - -test_allow_9 if { - policy.allow with input as {"kind": "tool_call", "action": "execute", "name": "ask_for_salary", "extensions": {"subject": {"id": "Bob", "type": "user", "roles": ["employee"], "teams": ["Sales"], "claims": {}, "permissions": ["write:purchase", "write:return_product", "write:send_email", "read:ask_for_workpolicy", "write:create_ticket", "write:submit_ticket", "read:get_w2_form", "read:ask_for_salary", "write:export_content_as_file"]}, "headers": {"x-request-id": "req-7f2a", "x-forwarded-for": "10.0.1.5"}, "labels": ["internal"], "agent": {"input": \"I"d like to check my current compensation details\", "session_id": "sess-9f3a", "conversation_id": "conv-17eb", "turn": 4}, "object": {"managed_by": "tool", "trust_domain": "internal", "data_scope": ["ticket_content"], "permissions": ["read:ask_for_salary"]}}, "arguments": {"format": "JSON", "time_range": "last_quarter", "include_benefits": True}} -} - -test_allow_10 if { - policy.allow with input as {"kind": "tool_call", "action": "execute", "name": "ask_for_salary", "extensions": {"subject": {"id": "Bob", "type": "user", "roles": ["employee"], "teams": ["Sales"], "claims": {}, "permissions": ["write:purchase", "write:return_product", "write:send_email", "read:ask_for_workpolicy", "write:create_ticket", "write:submit_ticket", "read:get_w2_form", "read:ask_for_salary", "write:export_content_as_file"]}, "headers": {"x-request-id": "req-7f2a", "x-forwarded-for": "10.0.1.5"}, "labels": ["internal"], "agent": {"input": "Can you show me my salary information?", "session_id": "sess-9f3a", "conversation_id": "conv-17eb", "turn": 4}, "object": {"managed_by": "tool", "trust_domain": "internal", "data_scope": ["ticket_content"], "permissions": ["read:ask_for_salary"]}}, "arguments": {"format": "JSON", "include_benefits": True, "time_range": "last_quarter"}} -} - -test_allow_11 if { - policy.allow with input as {"kind": "tool_call", "action": "execute", "name": "purchase", "extensions": {"subject": {"id": "Bob", "type": "user", "roles": ["manager"], "teams": ["Sales"], "claims": {}, "permissions": ["write:purchase", "write:return_product", "write:send_email", "read:ask_for_workpolicy", "write:create_ticket", "write:submit_ticket", "read:get_w2_form", "read:ask_for_salary", "write:export_content_as_file"]}, "headers": {"x-request-id": "req-7f2a", "x-forwarded-for": "10.0.1.5"}, "labels": ["internal"], "agent": {"input": "I need to purchase software licenses for $750", "session_id": "sess-9f3a", "conversation_id": "conv-17eb", "turn": 4}, "object": {"managed_by": "tool", "trust_domain": "internal", "data_scope": ["ticket_content"], "permissions": ["write:purchase"]}}, "arguments": {"amount": 750, "product_name": "software licenses"}} -} - -test_allow_12 if { - policy.allow with input as {"kind": "tool_call", "action": "execute", "name": "export_compensation_data", "extensions": {"subject": {"id": "Bob", "type": "user", "roles": ["manager"], "teams": ["Sales"], "claims": {}, "permissions": ["write:purchase", "write:return_product", "write:send_email", "read:ask_for_workpolicy", "write:create_ticket", "write:submit_ticket", "read:get_w2_form", "read:ask_for_salary", "write:export_content_as_file"]}, "headers": {"x-request-id": "req-7f2a", "x-forwarded-for": "10.0.1.5"}, "labels": ["internal"], "agent": {"input": \"Generate a PDF report of my team"s compensation\", "session_id": "sess-9f3a", "conversation_id": "conv-17eb", "turn": 4}, "object": {"managed_by": "tool", "trust_domain": "internal", "data_scope": ["ticket_content"], "permissions": ["read:export_compensation_data", "export:file"]}}, "arguments": {"format": "JSON", "include_benefits": True}} -} - -test_allow_13 if { - policy.allow with input as {"kind": "tool_call", "action": "execute", "name": "purchase", "extensions": {"subject": {"id": "Bob", "type": "user", "roles": ["employee"], "teams": ["Sales"], "claims": {}, "permissions": ["write:purchase", "write:return_product", "write:send_email", "read:ask_for_workpolicy", "write:create_ticket", "write:submit_ticket", "read:get_w2_form", "read:ask_for_salary", "write:export_content_as_file"]}, "headers": {"x-request-id": "req-7f2a", "x-forwarded-for": "10.0.1.5"}, "labels": ["internal"], "agent": {"input": \"I need to purchase a monitor for $300 with my manager"s approval\", "session_id": "sess-9f3a", "conversation_id": "conv-17eb", "turn": 4}, "object": {"managed_by": "tool", "trust_domain": "internal", "data_scope": ["ticket_content"], "permissions": ["write:purchase"]}}, "arguments": {"amount": 300, "product_name": "monitor", "justification": "Manager approved purchase"}} -} - -test_allow_14 if { - policy.allow with input as {"kind": "tool_call", "action": "execute", "name": "purchase", "extensions": {"subject": {"id": "Bob", "type": "user", "roles": ["employee"], "teams": ["Sales"], "claims": {}, "permissions": ["write:purchase", "write:return_product", "write:send_email", "read:ask_for_workpolicy", "write:create_ticket", "write:submit_ticket", "read:get_w2_form", "read:ask_for_salary", "write:export_content_as_file"]}, "headers": {"x-request-id": "req-7f2a", "x-forwarded-for": "10.0.1.5"}, "labels": ["internal"], "agent": {"input": "I want to buy office supplies for $150", "session_id": "sess-9f3a", "conversation_id": "conv-17eb", "turn": 4}, "object": {"managed_by": "tool", "trust_domain": "internal", "data_scope": ["ticket_content"], "permissions": ["write:purchase"]}}, "arguments": {"amount": 150, "product_name": "office supplies"}} -} - -test_allow_15 if { - policy.allow with input as {"kind": "tool_call", "action": "execute", "name": "export_compensation_data", "extensions": {"subject": {"id": "Bob", "type": "user", "roles": ["manager"], "teams": ["Sales"], "claims": {}, "permissions": ["write:purchase", "write:return_product", "write:send_email", "read:ask_for_workpolicy", "write:create_ticket", "write:submit_ticket", "read:get_w2_form", "read:ask_for_salary", "write:export_content_as_file"]}, "headers": {"x-request-id": "req-7f2a", "x-forwarded-for": "10.0.1.5"}, "labels": ["internal"], "agent": {"input": \"Export my team"s compensation data as a CSV file\", "session_id": "sess-9f3a", "conversation_id": "conv-17eb", "turn": 4}, "object": {"managed_by": "tool", "trust_domain": "internal", "data_scope": ["ticket_content"], "permissions": ["read:export_compensation_data", "export:file"]}}, "arguments": {"format": "CSV", "export_type": "aggregated"}} -} \ No newline at end of file diff --git a/scripts/tests/integration/coverage/revised_policy.rego b/scripts/tests/integration/coverage/revised_policy.rego deleted file mode 100644 index 2ed8b50..0000000 --- a/scripts/tests/integration/coverage/revised_policy.rego +++ /dev/null @@ -1,437 +0,0 @@ -# Copyright 2026 Smith authors -# SPDX-License-Identifier: Apache-2.0 - -package policy - -default allow := false - -subject := input.extensions.subject -obj := input.extensions.object -args := object.get(input, "arguments", {}) - -# ========================= -# Helpers -# ========================= - -has_subject_perm(p) if { - subject.permissions[_] == p -} - -has_object_perm(p) if { - obj.permissions[_] == p -} - -normalized_role(role) := "user" if { - lower(role) == "employee" -} - -normalized_role(role) := lower(role) if { - lower(role) != "employee" -} - -is_role(r) if { - some role in subject.roles - normalized_role(role) == lower(r) -} - -valid_envelope if { - input.kind == "tool_call" - input.action == "execute" - input.name != "" -} - -email_domain(addr) := domain if { - parts := split(lower(addr), "@") - count(parts) == 2 - domain := parts[1] -} - -has_arg(k) if { - object.get(args, k, null) != null -} - -field_in_tool_scope(tool_name, field) if { - some i - tool_data_scope[tool_name].fields[i] == field -} - -# ========================= -# Constants -# ========================= - -forbidden_fields := { - "ssn", - "tax_id", - "bank_account", - "home_address", - "personal_email", - "emergency_contact", - "healthcare_id", - "healthcare_plan", -} - -tool_data_scope := { - "view_team_compensation": { - "labels": ["financial", "PII", "confidential"], - "fields": [ - "employee_name", - "title", - "department", - "level", - "hire_date", - "base_salary", - "bonus_target", - "actual_bonus_2024", - "performance_rating", - "next_review_date", - "stock_grant_value", - "benefits_value", - "total_compensation", - ], - "scope": "team", - }, - "ask_for_salary": { - "labels": ["financial", "PII", "confidential"], - "fields": [ - "base_salary", - "total_compensation", - "title", - "department", - "level", - "bonus_target", - "actual_bonus_2024", - "performance_rating", - ], - "scope": "user", - }, - "export_compensation_data": { - "labels": ["financial", "PII", "confidential"], - "fields": [ - "employee_id", - "name", - "title", - "level", - "current_salary", - "total_comp_2024", - "performance_rating", - "salary_history", - "bonus_history", - ], - "scope": "team", - }, - "email_compensation_report": { - "labels": ["financial", "confidential"], - "fields": ["destination", "report_data", "external_sharing", "encryption_required"], - "scope": "team", - }, - "send_email": { - "labels": ["general"], - "fields": ["recipient_email", "subject", "body", "email_content", "attached_file"], - "scope": "user", - }, - "create_ticket": { - "labels": ["general"], - "fields": ["ticket_content"], - "scope": "user", - }, - "submit_ticket": { - "labels": ["general"], - "fields": ["ticket_content"], - "scope": "user", - }, - "purchase": { - "labels": ["financial"], - "fields": ["amount", "product_name", "category", "justification"], - "scope": "user", - }, - "return_product": { - "labels": ["financial"], - "fields": ["amount", "product_name"], - "scope": "user", - }, - "ask_for_workpolicy": { - "labels": ["general"], - "fields": ["question"], - "scope": "user", - }, - "get_w2_form": { - "labels": ["general"], - "fields": [], - "scope": "user", - }, - "export_content_as_file": { - "labels": ["general"], - "fields": ["data", "file_name"], - "scope": "user", - }, - "set_user_role": { - "labels": ["admin"], - "fields": ["user_role"], - "scope": "admin", - }, - "test_purchase_policy": { - "labels": ["admin"], - "fields": ["amount", "product"], - "scope": "admin", - }, -} - -manager_view_allowed_fields := { - "employee_name", - "title", - "department", - "level", - "hire_date", - "base_salary", - "bonus_target", - "actual_bonus_2024", - "performance_rating", - "next_review_date", - "stock_grant_value", - "benefits_value", - "total_compensation", -} - -manager_export_allowed_fields := { - "employee_id", - "name", - "title", - "level", - "current_salary", - "total_comp_2024", - "performance_rating", - "salary_history", - "bonus_history", -} - -allowed_export_formats := {"CSV", "PDF", "JSON"} - -blocked_domains := {"gmail.com", "yahoo.com", "hotmail.com", "outlook.com", "personal.com"} -internal_domain := "ibm.com" - -allowed_arg_keys := { - "view_team_compensation": {"select_fields", "id", "time_range", "format", "include_benefits"}, - "ask_for_salary": {"question"}, - "export_compensation_data": {"select_fields", "id", "format", "time_range", "export_type", "business_justification", "external_sharing"}, - "email_compensation_report": {"destination", "report_data", "external_sharing", "encryption_required"}, - "send_email": {"recipient_email", "subject", "body", "email_content", "attached_file"}, - "create_ticket": {"ticket_content"}, - "submit_ticket": {"ticket_content"}, - "ask_for_workpolicy": {"question"}, - "get_w2_form": {}, - "purchase": {"amount", "product_name", "category", "justification"}, - "return_product": {"amount", "product_name"}, - "export_content_as_file": {"data", "file_name"}, - "set_user_role": {"user_role"}, - "test_purchase_policy": {"amount", "product"}, -} - -tool_permissions := { - "ask_for_workpolicy": {"read:ask_for_workpolicy"}, - "create_ticket": {"write:create_ticket"}, - "submit_ticket": {"write:submit_ticket"}, - "get_w2_form": {"read:get_w2_form"}, - "view_team_compensation": {"read:view_team_compensation"}, - "ask_for_salary": {"read:ask_for_salary"}, - "export_compensation_data": {"read:export_compensation_data", "export:file"}, - "email_compensation_report": {"write:email_compensation_report"}, - "send_email": {"write:send_email"}, - "purchase": {"write:purchase"}, - "return_product": {"write:return_product"}, - "export_content_as_file": {"write:export_content_as_file"}, - "set_user_role": {"write:set_user_role"}, - "test_purchase_policy": {"write:test_purchase_policy"}, -} - -# ========================= -# Authorization -# ========================= - -authorized if { - valid_envelope - perms := tool_permissions[input.name] - every p in perms { - has_subject_perm(p) - has_object_perm(p) - } -} - -# ========================= -# Global DENY rules -# ========================= - -deny[msg] if { - valid_envelope - some i - keys := object.keys(args) - k := keys[i] - not allowed_arg_keys[input.name][k] - msg := sprintf("Unexpected argument key '%s' for tool '%s'", [k, input.name]) -} - -deny[msg] if { - valid_envelope - object.get(args, "select_fields", null) != null - some f in args.select_fields - not field_in_tool_scope(input.name, f) - msg := sprintf("Requested field '%s' not allowed by data scope for tool '%s'", [f, input.name]) -} - -deny[msg] if { - valid_envelope - object.get(args, "select_fields", null) != null - some f in args.select_fields - forbidden_fields[f] - msg := sprintf("Requested forbidden sensitive field '%s'", [f]) -} - -# ========================= -# Tool-specific DENY rules -# ========================= - -deny[msg] if { - input.name == "view_team_compensation" - not is_role("manager") - msg := "Only managers can use view_team_compensation" -} - -deny[msg] if { - input.name == "view_team_compensation" - is_role("manager") - object.get(args, "select_fields", null) != null - some f in args.select_fields - not manager_view_allowed_fields[f] - msg := sprintf("Manager not permitted to view field '%s' in team compensation", [f]) -} - -deny[msg] if { - input.name == "ask_for_salary" - not is_role("user") - not is_role("manager") - msg := "Only employees or managers can use ask_for_salary" -} - -deny[msg] if { - input.name == "ask_for_salary" - has_arg("question") - q := lower(args.question) - contains(q, "team") - msg := "ask_for_salary is for personal or general salary questions only; team salary queries are not allowed" -} - -deny[msg] if { - input.name == "export_compensation_data" - not is_role("manager") - msg := "Only managers can export compensation data" -} - -deny[msg] if { - input.name == "export_compensation_data" - has_arg("format") - fmt := upper(args.format) - not allowed_export_formats[fmt] - msg := sprintf("Export format '%s' not allowed", [args.format]) -} - -deny[msg] if { - input.name == "export_compensation_data" - is_role("manager") - object.get(args, "select_fields", null) != null - some f in args.select_fields - not manager_export_allowed_fields[f] - msg := sprintf("Manager not permitted to export field '%s'", [f]) -} - -deny[msg] if { - input.name == "email_compensation_report" - not is_role("manager") - msg := "Only managers can email compensation reports" -} - -deny[msg] if { - input.name == "email_compensation_report" - has_arg("destination") - email_domain(args.destination) != internal_domain - msg := "No one can email compensation reports to non-@ibm.com addresses" -} - -deny[msg] if { - input.name == "email_compensation_report" - has_arg("destination") - blocked_domains[email_domain(args.destination)] - msg := sprintf("Destination domain '%s' is blocked", [email_domain(args.destination)]) -} - -deny[msg] if { - input.name == "send_email" - has_arg("recipient_email") - blocked_domains[email_domain(args.recipient_email)] - msg := sprintf("Recipient domain '%s' is blocked", [email_domain(args.recipient_email)]) -} - -deny[msg] if { - input.name == "send_email" - has_arg("recipient_email") - email_domain(args.recipient_email) != internal_domain - text := lower(sprintf("%v %v %v", [ - object.get(args, "subject", ""), - object.get(args, "body", ""), - object.get(args, "email_content", ""), - ])) - some kw in {"salary", "compensation", "bonus", "ssn"} - contains(text, kw) - msg := "No one can send compensation or salary data to non-@ibm.com addresses" -} - -deny[msg] if { - input.name == "purchase" - not is_role("user") - not is_role("manager") - msg := "Only employees or managers can purchase items" -} - -deny[msg] if { - input.name == "purchase" - is_role("user") - has_arg("amount") - to_number(args.amount) > 200 - msg := "Employees cannot buy products above $200" -} - -deny[msg] if { - input.name == "purchase" - is_role("manager") - has_arg("amount") - to_number(args.amount) > 1000 - msg := "Managers cannot buy products above $1,000" -} - -deny[msg] if { - input.name == "set_user_role" - not is_role("manager") - msg := "Only managers can set user roles" -} - -deny[msg] if { - input.name == "test_purchase_policy" - not is_role("manager") - msg := "Only managers can test purchase policy" -} - -# ========================= -# Deny helper -# ========================= - -any_deny if { - deny[_] -} - -# ========================= -# Final ALLOW -# ========================= - -allow if { - valid_envelope - authorized - not any_deny -} \ No newline at end of file diff --git a/scripts/tests/integration/score_card.sh b/scripts/tests/integration/score_card.sh deleted file mode 100755 index a9dd5fc..0000000 --- a/scripts/tests/integration/score_card.sh +++ /dev/null @@ -1,155 +0,0 @@ -#!/bin/bash -# Copyright 2026 Smith authors -# SPDX-License-Identifier: Apache-2.0 - -CDIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) - -DIRS_TO_TEST=( - "$CDIR/../../../references/test_cases/allow" - "$CDIR/../../../references/test_cases/disallow" -) - -OUTPUT_FILE="$CDIR/score_test_results.txt" -SCORECARD_FILE="$CDIR/scorecard_summary.txt" -TEST_FAILURES_FILE="$CDIR/score_test_failures.txt" -POLICY_PATH_COUNT="$CDIR/../../../assets/policy.rego" - -> "$OUTPUT_FILE" -> "$SCORECARD_FILE" -> "$TEST_FAILURES_FILE" - -TEMP_RESULTS=$(mktemp) - -FILES=("fn.txt" "fp.txt" "tn.txt" "tp.txt") - -for f in "${FILES[@]}"; do - > "$CDIR/$f" -done - -for BASE_INPUT_DIR in "${DIRS_TO_TEST[@]}"; do - find "$BASE_INPUT_DIR" -type f -name "*.json" | while read -r FILE; do - echo "Testing: $FILE" | tee -a "$OUTPUT_FILE" - if [[ "$FILE" == *"/disallow/"* ]]; then - echo -e "\t{\"expected\": {\"allow\": false}}" - EXPECTED_ALLOW="false" - else - echo -e "\t{\"expected\": {\"allow\": true}}" - EXPECTED_ALLOW="true" - fi - - RESPONSE=$(curl -s -X POST localhost:8181/v1/data/mcp/policies/allow \ - -H "Content-Type: application/json" \ - --data @"$FILE") - echo "$RESPONSE" - - if [[ "$RESPONSE" == *'"result":true'* ]]; then - ALLOW="true" - else - ALLOW="false" - fi - - if [ "$EXPECTED_ALLOW" = "true" ] && [ "$ALLOW" = "true" ]; then - TARGET_TYPE="tn" - elif [ "$EXPECTED_ALLOW" = "true" ] && [ "$ALLOW" = "false" ]; then - TARGET_TYPE="fp" - elif [ "$EXPECTED_ALLOW" = "false" ] && [ "$ALLOW" = "true" ]; then - TARGET_TYPE="fn" - elif [ "$EXPECTED_ALLOW" = "false" ] && [ "$ALLOW" = "false" ]; then - TARGET_TYPE="tp" - else - echo "Unexpected combination: EXPECTED_ALLOW=$EXPECTED_ALLOW ALLOW=$ALLOW" >&2 - TARGET_TYPE="" - fi - - case "$TARGET_TYPE" in - "fn") - echo "$FILE" | tee -a "$OUTPUT_FILE" >> "$CDIR/fn.txt" - ;; - "fp") - echo "$FILE" | tee -a "$OUTPUT_FILE" >> "$CDIR/fp.txt" - ;; - "tn") - echo "$FILE" | tee -a "$OUTPUT_FILE" >> "$CDIR/tn.txt" - ;; - "tp") - echo "$FILE" | tee -a "$OUTPUT_FILE" >> "$CDIR/tp.txt" - ;; - *) - echo "Unknown type: $TARGET_TYPE" - ;; - esac - - if [[ "$EXPECTED_ALLOW" == "$ALLOW" ]]; then - MATCH="[PASS: expected_allow: $EXPECTED_ALLOW, allow: $ALLOW" - else - MATCH="[FAIL: expected_allow: $EXPECTED_ALLOW, allow: $ALLOW" - fi - - echo -e "\t$RESPONSE" | tee -a "$OUTPUT_FILE" - echo -e "\n-----------------------------\n" >> "$OUTPUT_FILE" - - echo "$MATCH, test_case: $FILE] $RESPONSE" >> "$TEMP_RESULTS" - done -done - -echo -e "Scorecard Summary\n===================" >> "$SCORECARD_FILE" - -ALL_DIRS=$(find "${DIRS_TO_TEST[@]}" -type f -name "*.json" | xargs -n1 dirname | sort | uniq) - -for DIR in $ALL_DIRS; do - MATCHES=$(grep -F "$DIR/" "$TEMP_RESULTS") - ALLOW_TRUE=$(echo "$MATCHES" | grep -c '"result":true') - ALLOW_FALSE=$(echo "$MATCHES" | grep -c '"result":false') - TOTAL=$((ALLOW_TRUE + ALLOW_FALSE)) - - if [[ "$DIR" == *"/disallow"* ]]; then - TITLE="Test cases that should result in a deny decision" - elif [[ "$DIR" == *"/allow"* ]]; then - TITLE="Test cases that should result in an allow decision" - else - TITLE="Unlabeled test cases" - fi - - echo "Experiment: $TITLE" >> "$SCORECARD_FILE" - echo "Directory: ${DIR#$CDIR}" >> "$SCORECARD_FILE" - echo "Allowed: $ALLOW_TRUE" >> "$SCORECARD_FILE" - echo "Denied: $ALLOW_FALSE" >> "$SCORECARD_FILE" - echo "Total: $TOTAL" >> "$SCORECARD_FILE" - echo "--------------------------" >> "$SCORECARD_FILE" - - FAILS=$(echo "$MATCHES" | grep '^\[FAIL') - echo "$FAILS" >> "$TEST_FAILURES_FILE" -done - -echo "===================" >> "$SCORECARD_FILE" -echo "The coverage test results are: " >> "$SCORECARD_FILE" - -python $CDIR/convert_test_coverage.py -COVERAGE_OUTPUT=$(opa test --coverage "$CDIR/coverage/revised_policy.rego" "$CDIR/coverage/policy_test.rego") -echo "$COVERAGE_OUTPUT" > "$CDIR/coverage.txt" -echo "$COVERAGE_OUTPUT" | tail -n 9 | head -n 3 >> "$SCORECARD_FILE" - - -# Run coverage analysis and save to separate file -COVERAGE_OUTPUT_FILE="$CDIR/coverage_analysis.txt" -echo "Running detailed coverage analysis..." -bash "$CDIR/../tools/analyze_coverage.sh" > "$COVERAGE_OUTPUT_FILE" - - - - -cd "$CDIR" - -echo "" -echo "Files Generated:" -echo "- scorecard_summary.txt (main scorecard)" -echo "- coverage_analysis.txt (detailed coverage report)" -echo "" - -cat "$SCORECARD_FILE" - -rm "$TEMP_RESULTS" - -echo "===================" >> "$SCORECARD_FILE" -echo "The line number of current policy is:" >> "$SCORECARD_FILE" -wc -l < $POLICY_PATH_COUNT >> "$SCORECARD_FILE" diff --git a/scripts/tests/integration/test_commands.py b/scripts/tests/integration/test_commands.py deleted file mode 100644 index 38dc9cb..0000000 --- a/scripts/tests/integration/test_commands.py +++ /dev/null @@ -1,46 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright 2026 Smith authors -# SPDX-License-Identifier: Apache-2.0 - -"""Tests for registered plugins.""" - -# Third-Party -import asyncio -import pytest - -# First-Party -from mcpgateway.plugins.framework import ( - PluginManager, - GlobalContext, - ToolPreInvokePayload, -) - -from kubectlcmdprocessor.plugin import ( - CONTEXT_KEY_POLICY_CONTEXT, - CONTEXT_KEY_KUBECTL_CMD, -) - - -@pytest.fixture(scope="module", autouse=True) -def plugin_manager(): - """Initialize plugin manager.""" - plugin_manager = PluginManager("./resources/plugins/config.yaml") - asyncio.run(plugin_manager.initialize()) - yield plugin_manager - asyncio.run(plugin_manager.shutdown()) - - -@pytest.mark.asyncio -async def test_tool_pre_hook_commands(plugin_manager: PluginManager): - """Test tool pre hook across all registered plugins for a list of commands.""" - with open("./tests/inputs/commands", "r") as f: - for line in f.readlines(): - expected, cmd = line.split(",", 1) - payload = ToolPreInvokePayload(name="kubectl_tool", args={"arg0": cmd}) - global_context = GlobalContext(request_id="1") - result, ctx = await plugin_manager.tool_pre_invoke(payload, global_context) - context = next(iter(ctx.values())) - cmd = context.global_context.state[CONTEXT_KEY_POLICY_CONTEXT][ - CONTEXT_KEY_KUBECTL_CMD - ] - assert result.continue_processing == (expected == "allow") diff --git a/scripts/tests/integration/test_pipeline.py b/scripts/tests/integration/test_pipeline.py deleted file mode 100644 index b283115..0000000 --- a/scripts/tests/integration/test_pipeline.py +++ /dev/null @@ -1,72 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright 2026 Smith authors -# SPDX-License-Identifier: Apache-2.0 - -"""Tests for registered plugins.""" - -# Third-Party -import asyncio -import pytest - -# First-Party -from mcpgateway.plugins.framework import ( - PluginManager, - GlobalContext, - ToolPreInvokePayload, -) - -from kubectlcmdprocessor.plugin import ( - CONTEXT_KEY_POLICY_CONTEXT, - CONTEXT_KEY_KUBECTL_CMD, -) - - -@pytest.fixture(scope="module", autouse=True) -def plugin_manager(): - """Initialize plugin manager.""" - plugin_manager = PluginManager("./resources/plugins/config.yaml") - asyncio.run(plugin_manager.initialize()) - yield plugin_manager - asyncio.run(plugin_manager.shutdown()) - - -@pytest.mark.asyncio -async def test_tool_pre_hook_allow(plugin_manager: PluginManager): - """Test tool pre hook across all registered plugins for an allowed command.""" - payload = ToolPreInvokePayload( - name="kubectl_tool", args={"arg0": "kubectl get pods -n otel-demo"} - ) - global_context = GlobalContext(request_id="1") - result, ctx = await plugin_manager.tool_pre_invoke(payload, global_context) - context = next(iter(ctx.values())) - cmd = context.global_context.state[CONTEXT_KEY_POLICY_CONTEXT][ - CONTEXT_KEY_KUBECTL_CMD - ] - assert cmd["command"]["verb"] == "get" - assert cmd["command"]["resource"] == "pods" - assert cmd["command"]["namespace"] == "otel-demo" - assert len(cmd["command"]["args"]) == 0 - assert result.continue_processing - - -@pytest.mark.asyncio -async def test_tool_pre_hook_deny(plugin_manager: PluginManager): - """Test tool pre hook across all registered plugins for a forbidden command.""" - payload = ToolPreInvokePayload( - name="kubectl_tool", - args={ - "arg0": "kubectl get pods -n otel-demo -l $(cat /etc/passwd) in (email,checkout)" - }, - ) - global_context = GlobalContext(request_id="1") - result, ctx = await plugin_manager.tool_pre_invoke(payload, global_context) - context = next(iter(ctx.values())) - cmd = context.global_context.state[CONTEXT_KEY_POLICY_CONTEXT][ - CONTEXT_KEY_KUBECTL_CMD - ] - assert cmd["command"]["verb"] == "get" - assert cmd["command"]["resource"] == "pods" - assert cmd["command"]["namespace"] == "otel-demo" - assert len(cmd["command"]["args"]) == 0 - assert len(cmd["command"]["flags"]) > 0 - assert not result.continue_processing diff --git a/scripts/tests/policy_testing.py b/scripts/tests/policy_testing.py deleted file mode 100644 index 92091bc..0000000 --- a/scripts/tests/policy_testing.py +++ /dev/null @@ -1,47 +0,0 @@ -# Copyright 2026 Smith authors -# SPDX-License-Identifier: Apache-2.0 - -import subprocess -import os -from dotenv import load_dotenv - -load_dotenv() - - -def run_policy_evaluation(): - """ - Run all policy tests using the Makefile in the project root. - Saves outputs in the feedback directory under tmp. - """ - base_url = os.getenv("BASE_URL") + "scripts/" - if not base_url: - raise ValueError("BASE_URL not provided") - - # Define project root and output paths - project_root = os.path.abspath(base_url) - makefile_path = os.path.join(project_root, "Makefile") - if not os.path.exists(makefile_path): - raise FileNotFoundError(f"Makefile not found at {makefile_path}") - - print("Running policy evaluation tests via Makefile...") - print(f"Project root: {project_root}") - - # Run tests using Makefile - try: - subprocess.run(["make", "test"], cwd=project_root, check=True) - print("Policy evaluation tests completed successfully.") - except subprocess.CalledProcessError: - print( - "Policy evaluation tests failed. Check test outputs under 'tests/' for details." - ) - content = "" - - test_path = base_url + os.getenv("TEST_PATH") - test_results_path = test_path + os.getenv("TEST_RESULT_PATH") - with open(test_results_path, "r") as file: - content = str(file.read()) - return content - - -if __name__ == "__main__": - run_policy_evaluation() diff --git a/scripts/tests/tools/analyze_policy_diff.sh b/scripts/tests/tools/analyze_policy_diff.sh deleted file mode 100644 index a8a8aea..0000000 --- a/scripts/tests/tools/analyze_policy_diff.sh +++ /dev/null @@ -1,152 +0,0 @@ -#!/bin/bash -# Copyright 2026 Smith authors -# SPDX-License-Identifier: Apache-2.0 - -# Set default environment variables for policy detection -export REPAIR_DIR="${REPAIR_DIR:-repair}" -export MUTATION_DIR="${MUTATION_DIR:-defective_policies1}" - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" - -SCORECARD_FILE="" -OUTPUT_FORMAT="text" -SHOW_HELP=false - - -while [[ $# -gt 0 ]]; do - case $1 in - -s|--scorecard) - SCORECARD_FILE="$2" - shift 2 - ;; - -f|--format) - OUTPUT_FORMAT="$2" - shift 2 - ;; - -h|--help) - SHOW_HELP=true - shift - ;; - *) - echo "Unknown option: $1" - exit 1 - ;; - esac -done - - -if [ "$SHOW_HELP" = true ]; then - cat << EOF -Policy Diff Analysis Tool - -Usage: $0 [OPTIONS] - -OPTIONS: - -s, --scorecard FILE Scorecard file to append results to - -f, --format FORMAT Output format: text or json (default: text) - -h, --help Show this help message - -EXAMPLES: - $0 -s scorecard_summary.txt # Append to scorecard - $0 -s scorecard_summary.txt -f json # Use JSON format - $0 # Run standalone - -DESCRIPTION: - This tool analyzes differences between baseline and repair/defective policies - using the policy_diff_analyzer.py script. It can append results to a scorecard - file or run standalone. - -FILES ANALYZED: - - policies/policy.rego (baseline policy) - - Auto-detected newest policy in repair/defective directories - -EXIT CODES: - 0 - Success (no policy changes) - 1 - Policy changes detected - 2 - Analysis failed or no policies found -EOF - exit 0 -fi - - -if [[ "$OUTPUT_FORMAT" != "text" && "$OUTPUT_FORMAT" != "json" ]]; then - echo "Error: Invalid output format '$OUTPUT_FORMAT'. Must be 'text' or 'json'." - exit 1 -fi - - -append_to_scorecard() { - local message="$1" - if [[ -n "$SCORECARD_FILE" ]]; then - echo "$message" >> "$SCORECARD_FILE" - fi -} - - -cd "$PROJECT_ROOT" - -if [[ -n "$SCORECARD_FILE" ]]; then - append_to_scorecard "" - append_to_scorecard "========================" - append_to_scorecard "POLICY DIFF ANALYSIS" - append_to_scorecard "========================" -fi - - -echo " Running policy diff analysis..." -echo " Using REPAIR_DIR: $REPAIR_DIR" -echo " Using MUTATION_DIR: $MUTATION_DIR" -python tests/tools/policy_diff_analyzer.py --project-root . --output-format "$OUTPUT_FORMAT" -DIFF_EXIT_CODE=$? - - -if [ $DIFF_EXIT_CODE -eq 0 ]; then - append_to_scorecard "" - append_to_scorecard "No policy changes detected." - echo "No policy changes detected." -elif [ $DIFF_EXIT_CODE -eq 1 ]; then - append_to_scorecard "" - append_to_scorecard " Policy changes detected - see analysis above." - echo " Policy changes detected!" -else - append_to_scorecard "" - append_to_scorecard " Policy diff analysis failed or no policies found for comparison." - echo " Policy diff analysis failed or no policies found for comparison." -fi - - -if [[ -z "$SCORECARD_FILE" ]]; then - echo "" - echo "Analysis Results:" - echo "===================" - - if [ $DIFF_EXIT_CODE -eq 0 ]; then - echo "Analysis completed successfully" - if [[ "$OUTPUT_FORMAT" == "json" ]]; then - echo "Report saved to: resources/data/outputs/policy_diff_output.json" - else - echo "Report saved to: resources/data/outputs/policy_diff_output.txt" - fi - elif [ $DIFF_EXIT_CODE -eq 1 ]; then - echo "Policy changes detected!" - if [[ "$OUTPUT_FORMAT" == "json" ]]; then - echo " Report saved to: resources/data/outputs/policy_diff_output.json" - else - echo "Report saved to: resources/data/outputs/policy_diff_output.txt" - echo "Run 'cat resources/data/outputs/policy_diff_output.txt' to view details" - fi - else - echo " Analysis failed or no policies found for comparison" - echo "Make sure you have repair or defective policies to compare" - fi - - echo "" - echo "Available commands:" - echo " $0 -s scorecard.txt # Append to scorecard" - echo " $0 -f json # Use JSON output" - echo " python tests/tools/policy_diff_analyzer.py --help # See all options" -fi - - -exit $DIFF_EXIT_CODE \ No newline at end of file diff --git a/scripts/tests/tools/policy_diff_analyzer.py b/scripts/tests/tools/policy_diff_analyzer.py deleted file mode 100644 index 33e167e..0000000 --- a/scripts/tests/tools/policy_diff_analyzer.py +++ /dev/null @@ -1,491 +0,0 @@ -#!/usr/bin/env python3 -# Copyright 2026 Smith authors -# SPDX-License-Identifier: Apache-2.0 - -import json -import difflib -import argparse -import sys -import re -import os -from pathlib import Path -from datetime import datetime -from typing import Dict, List, Tuple, Optional -from dataclasses import dataclass - -# ANSI color codes -ANSI_ESCAPE = re.compile(r"\x1B\[[0-?]*[ -/]*[@-~]") -RED = "\033[31m" -GREEN = "\033[32m" -YELLOW = "\033[33m" -BLUE = "\033[34m" -RESET = "\033[0m" - - -@dataclass -class PolicyDiffResult: - """Results of policy diff analysis""" - - old_policy_path: str - new_policy_path: str - added_rules: List[str] - modified_rules: List[str] - removed_rules: List[str] - rule_stats: Dict[str, Tuple[int, int, List[str]]] - package_changed: Optional[Tuple[str, str]] - imports_added: set - imports_removed: set - total_inserted: int - total_deleted: int - - -class PolicyDiffAnalyzer: - """Analyzes differences between OPA policy files""" - - def __init__(self, project_root: Path = None): - self.project_root = project_root or Path.cwd() - self.baseline_policy = self.project_root / "policies" / "policy.rego" - - def find_newest_policy(self, search_dirs: List[str] = None) -> Optional[Path]: - if search_dirs is None: - repair_dir = os.getenv("REPAIR_DIR", "") - mutation_dir = os.getenv("MUTATION_DIR", "") - search_dirs = [d for d in (repair_dir, mutation_dir) if d] - - if not search_dirs: - print( - "Error: No search directories specified. Set REPAIR_DIR and/or MUTATION_DIR environment variables.", - file=sys.stderr, - ) - return None - - newest_file = None - newest_time = 0 - searched_paths = [] - - for search_dir in search_dirs: - dir_path = self.project_root / "resources" / "data" / search_dir - searched_paths.append(str(dir_path)) - - if not dir_path.exists(): - print(f"Warning: Directory does not exist: {dir_path}", file=sys.stderr) - continue - - found_files = [] - for rego_file in dir_path.rglob("*.rego"): - if any(skip in str(rego_file) for skip in ["test", "backup", "_old"]): - continue - - found_files.append(str(rego_file)) - mtime = rego_file.stat().st_mtime - if mtime > newest_time: - newest_time = mtime - newest_file = rego_file - - if found_files: - print( - f"Found {len(found_files)} policy files in {dir_path}", - file=sys.stderr, - ) - - if newest_file is None: - print( - "Error: No new policy files found in repair/defective directories", - file=sys.stderr, - ) - print(f"Searched paths: {searched_paths}", file=sys.stderr) - - return newest_file - - def extract_rules(self, file_path: Path) -> Dict[str, List[str]]: - """Extract rules from a Rego policy file""" - if not file_path.exists(): - raise FileNotFoundError(f"Policy file not found: {file_path}") - - rules = {} - current_rule = None - nesting_level = 0 - - with open(file_path, "r", encoding="utf-8") as f: - lines = f.readlines() - - for line in lines: - stripped = line.strip() - if not stripped or stripped.startswith("#"): - continue - - if nesting_level == 0: - - if ( - stripped.endswith("{") - and ":=" not in stripped - and not stripped.startswith('"') - ): - rule_name = stripped.split()[0] - current_rule = rule_name - rules[current_rule] = [line.rstrip()] - nesting_level += 1 - continue - - if ":=" in stripped and stripped.endswith("{"): - rule_name = stripped.split(":=")[0].strip() - current_rule = rule_name - rules[current_rule] = [line.rstrip()] - nesting_level += 1 - continue - - if ":=" in stripped and not stripped.endswith("{"): - rule_name = stripped.split(":=")[0].strip() - rules[rule_name] = [line.rstrip()] - continue - - if current_rule: - rules[current_rule].append(line.rstrip()) - - nesting_level += line.count("{") - nesting_level -= line.count("}") - - if current_rule and nesting_level == 0: - current_rule = None - - return rules - - def extract_package_imports(self, file_path: Path) -> Tuple[Optional[str], set]: - """Extract package and import statements""" - package = None - imports = set() - - with open(file_path, "r", encoding="utf-8") as f: - for line in f: - stripped = line.strip() - if stripped.startswith("#") or not stripped: - continue - if stripped.startswith("package "): - package = stripped - elif stripped.startswith("import "): - imports.add(stripped) - - return package, imports - - def diff_rule_lines( - self, old_lines: List[str], new_lines: List[str] - ) -> Tuple[int, int, List[str]]: - """Calculate diff statistics for rule lines""" - diff = list(difflib.ndiff(old_lines, new_lines)) - inserted = sum(1 for d in diff if d.startswith("+ ")) - deleted = sum(1 for d in diff if d.startswith("- ")) - return inserted, deleted, diff - - def analyze_policies(self, old_policy: Path, new_policy: Path) -> PolicyDiffResult: - """Perform comprehensive diff analysis between two policies""" - - old_rules = self.extract_rules(old_policy) - new_rules = self.extract_rules(new_policy) - - all_rule_names = set(old_rules.keys()).union(new_rules.keys()) - - added_rules = [r for r in new_rules if r not in old_rules] - removed_rules = [r for r in old_rules if r not in new_rules] - modified_rules = [] - - rule_stats = {} - for rule in sorted(all_rule_names): - old_lines = old_rules.get(rule, []) - new_lines = new_rules.get(rule, []) - inserted, deleted, diff = self.diff_rule_lines(old_lines, new_lines) - - if inserted > 0 or deleted > 0: - if rule not in added_rules and rule not in removed_rules: - modified_rules.append(rule) - - rule_stats[rule] = (inserted, deleted, diff) - - old_package, old_imports = self.extract_package_imports(old_policy) - new_package, new_imports = self.extract_package_imports(new_policy) - - package_changed = None - if old_package != new_package: - package_changed = (old_package, new_package) - - imports_added = new_imports - old_imports - imports_removed = old_imports - new_imports - - total_inserted = sum(ins for ins, del_, _ in rule_stats.values()) - total_deleted = sum(del_ for ins, del_, _ in rule_stats.values()) - - return PolicyDiffResult( - old_policy_path=str(old_policy), - new_policy_path=str(new_policy), - added_rules=added_rules, - modified_rules=modified_rules, - removed_rules=removed_rules, - rule_stats=rule_stats, - package_changed=package_changed, - imports_added=imports_added, - imports_removed=imports_removed, - total_inserted=total_inserted, - total_deleted=total_deleted, - ) - - def generate_text_report(self, result: PolicyDiffResult) -> str: - """Generate human-readable text report""" - lines = [] - - lines.extend( - [ - "=" * 60, - "OPA POLICY DIFF ANALYSIS REPORT", - "=" * 60, - "", - f"Baseline Policy: {result.old_policy_path}", - f"Compared Policy: {result.new_policy_path}", - f"Analysis Time: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}", - "", - ] - ) - - total_rules = len(result.rule_stats) - lines.extend( - [ - "SUMMARY:", - f"Total Rules: {total_rules}", - f"Added Rules: {len(result.added_rules)}", - f"Modified Rules: {len(result.modified_rules)}", - f"Removed Rules: {len(result.removed_rules)}", - f"Total Lines Inserted: {result.total_inserted}", - f"Total Lines Deleted: {result.total_deleted}", - "", - ] - ) - - if result.rule_stats: - rule_name_width = max(len(rule) for rule in result.rule_stats) + 2 - count_width = 10 - - header = f"{'Rule':<{rule_name_width}}{'Inserted':>{count_width}}{'Deleted':>{count_width}}{'Status'}" - lines.extend( - [ - "RULE MODIFICATIONS:", - header, - "-" * (rule_name_width + 2 * count_width + 10), - ] - ) - - for rule, (inserted, deleted, _) in sorted(result.rule_stats.items()): - if rule in result.added_rules: - status = f"{GREEN}ADDED{RESET}" - elif rule in result.removed_rules: - status = f"{RED}REMOVED{RESET}" - elif rule in result.modified_rules: - status = f"{YELLOW}MODIFIED{RESET}" - else: - status = "UNCHANGED" - - lines.append( - f"{rule:<{rule_name_width}}{inserted:>{count_width}}{deleted:>{count_width}} {status}" - ) - - lines.append("-" * (rule_name_width + 2 * count_width + 10)) - - if result.package_changed: - lines.extend( - [ - "", - f"{YELLOW}PACKAGE MODIFIED:{RESET}", - f"Old: {result.package_changed[0]}", - f"New: {result.package_changed[1]}", - ] - ) - - if result.imports_added: - lines.extend(["", f"{GREEN}IMPORTS ADDED:{RESET}"]) - for imp in result.imports_added: - lines.append(f" {imp}") - - if result.imports_removed: - lines.extend(["", f"{RED}IMPORTS REMOVED:{RESET}"]) - for imp in result.imports_removed: - lines.append(f" {imp}") - - if result.modified_rules or result.added_rules or result.removed_rules: - lines.extend(["", "CHANGED RULES SUMMARY:", "-" * 40]) - - if result.added_rules: - lines.extend( - ["", f"{GREEN}ADDED RULES ({len(result.added_rules)}):{RESET}"] - ) - for rule in sorted(result.added_rules): - inserted, _, _ = result.rule_stats[rule] - lines.append(f" + {rule} ({inserted} lines)") - - if result.modified_rules: - lines.extend( - [ - "", - f"{YELLOW}MODIFIED RULES ({len(result.modified_rules)}):{RESET}", - ] - ) - for rule in sorted(result.modified_rules): - inserted, deleted, _ = result.rule_stats[rule] - lines.append(f" ~ {rule} (+{inserted}/-{deleted} lines)") - - if result.removed_rules: - lines.extend( - ["", f"{RED}REMOVED RULES ({len(result.removed_rules)}):{RESET}"] - ) - for rule in sorted(result.removed_rules): - deleted, _, _ = result.rule_stats[rule] - lines.append(f" - {rule} ({deleted} lines)") - - lines.append("=" * 60) - return "\n".join(lines) - - def generate_json_report(self, result: PolicyDiffResult) -> str: - """Generate JSON report""" - report_data = { - "analysis_info": { - "baseline_policy": result.old_policy_path, - "compared_policy": result.new_policy_path, - "analysis_time": datetime.now().isoformat(), - }, - "summary": { - "total_rules": len(result.rule_stats), - "added_rules_count": len(result.added_rules), - "modified_rules_count": len(result.modified_rules), - "removed_rules_count": len(result.removed_rules), - "total_lines_inserted": result.total_inserted, - "total_lines_deleted": result.total_deleted, - }, - "rule_changes": { - "added_rules": result.added_rules, - "modified_rules": result.modified_rules, - "removed_rules": result.removed_rules, - }, - "rule_statistics": { - rule: {"inserted": ins, "deleted": del_} - for rule, (ins, del_, _) in result.rule_stats.items() - }, - "package_changes": { - "package_modified": result.package_changed is not None, - "old_package": ( - result.package_changed[0] if result.package_changed else None - ), - "new_package": ( - result.package_changed[1] if result.package_changed else None - ), - }, - "import_changes": { - "imports_added": list(result.imports_added), - "imports_removed": list(result.imports_removed), - }, - } - - return json.dumps(report_data, indent=2) - - -def main(): - """Main entry point""" - parser = argparse.ArgumentParser( - description="Analyze differences between OPA policy files" - ) - parser.add_argument( - "--new-policy", - type=Path, - help="Path to the new policy file (auto-detected if not specified)", - ) - parser.add_argument( - "--baseline-policy", - type=Path, - default=Path("policies/policy.rego"), - help="Path to the baseline policy file (default: policies/policy.rego)", - ) - parser.add_argument( - "--output-format", - choices=["text", "json"], - default="text", - help="Output format (default: text)", - ) - parser.add_argument( - "--output-file", - type=Path, - help="Output file path (default: resources/data/outputs/policy_diff_output.txt for text, policy_diff_output.json for JSON)", - ) - parser.add_argument( - "--project-root", - type=Path, - default=Path.cwd(), - help="Project root directory (default: current directory)", - ) - - args = parser.parse_args() - - try: - analyzer = PolicyDiffAnalyzer(args.project_root) - - baseline_policy = args.project_root / args.baseline_policy - if not baseline_policy.exists(): - print( - f"Error: Baseline policy not found: {baseline_policy}", file=sys.stderr - ) - sys.exit(1) - - if args.new_policy: - new_policy = args.project_root / args.new_policy - if not new_policy.exists(): - print( - f"Error: Specified new policy not found: {new_policy}", - file=sys.stderr, - ) - sys.exit(1) - else: - new_policy = analyzer.find_newest_policy() - if not new_policy: - print( - "Error: No new policy files found in repair/defective directories", - file=sys.stderr, - ) - sys.exit(1) - print(f"Auto-detected newest policy: {new_policy}") - - result = analyzer.analyze_policies(baseline_policy, new_policy) - - if args.output_format == "json": - report = analyzer.generate_json_report(result) - default_output = ( - args.project_root - / "resources" - / "data" - / "outputs" - / "policy_diff_output.json" - ) - else: - report = analyzer.generate_text_report(result) - default_output = ( - args.project_root - / "resources" - / "data" - / "outputs" - / "policy_diff_output.txt" - ) - - output_file = args.output_file or default_output - - output_file.parent.mkdir(parents=True, exist_ok=True) - - clean_report = ANSI_ESCAPE.sub("", report) - with open(output_file, "w", encoding="utf-8") as f: - f.write(clean_report) - - print(report) - print(f"\nOutput written to: {output_file}") - - if result.total_inserted > 0 or result.total_deleted > 0: - sys.exit(1) - - except Exception as e: - print(f"Error: {e}", file=sys.stderr) - sys.exit(1) - - -if __name__ == "__main__": - main() diff --git a/scripts/tests/unit/__init__.py b/scripts/tests/unit/__init__.py deleted file mode 100644 index 021d56a..0000000 --- a/scripts/tests/unit/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# Copyright 2026 Smith authors -# SPDX-License-Identifier: Apache-2.0 diff --git a/scripts/tests/unit/test_parser.py b/scripts/tests/unit/test_parser.py deleted file mode 100644 index 5efade7..0000000 --- a/scripts/tests/unit/test_parser.py +++ /dev/null @@ -1,773 +0,0 @@ -# Copyright 2026 Smith authors -# SPDX-License-Identifier: Apache-2.0 - -"""Comprehensive tests for kubectl command parser.""" - -import subprocess -import sys -import pytest -from unittest.mock import patch -from kubectlcmdprocessor.parser import KubectlParser, main - - -@pytest.fixture -def parser(): - """Create a fresh parser instance for each test.""" - return KubectlParser() - - -def test_basic_resource_operations(parser): - """Test basic resource operations like get, describe, delete.""" - - # Test simple get command - result = parser.parse("kubectl get pods") - assert result["command"]["verb"] == "get" - assert result["command"]["resource"] == "pods" - assert result["command"]["namespace"] is None - assert len(result["command"]["args"]) == 0 - - # Test get with namespace flag - result = parser.parse("kubectl get pods -n sre-sandbox") - assert result["command"]["verb"] == "get" - assert result["command"]["resource"] == "pods" - assert result["command"]["namespace"] == "sre-sandbox" - assert any( - flag["name"] == "-n" and flag["value"] == "sre-sandbox" - for flag in result["command"]["flags"] - ) - - # Test describe with namespace=value format - result = parser.parse("kubectl describe pod my-pod --namespace=production") - assert result["command"]["verb"] == "describe" - assert result["command"]["resource"] == "pod" - assert result["command"]["namespace"] == "production" - assert "my-pod" in result["command"]["args"] - - # Test delete with multiple flags - result = parser.parse("kubectl delete pods --all -n test") - assert result["command"]["verb"] == "delete" - assert result["command"]["resource"] == "pods" - assert result["command"]["namespace"] == "test" - assert any(flag["name"] == "--all" for flag in result["command"]["flags"]) - - -def test_file_based_operations(parser): - """Test file-based operations with -f flag.""" - - result = parser.parse("kubectl apply -f deployment.yaml") - assert result["command"]["verb"] == "apply" - assert ( - result["command"]["resource"] is None - ) # -f now takes deployment.yaml as value - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["-f"] == "deployment.yaml" - - result = parser.parse("kubectl create -f ./pod.json") - assert result["command"]["verb"] == "create" - assert result["command"]["resource"] is None # -f now takes ./pod.json as value - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["-f"] == "./pod.json" - - result = parser.parse("kubectl delete -f manifest.yaml") - assert result["command"]["verb"] == "delete" - assert result["command"]["resource"] is None # -f now takes manifest.yaml as value - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["-f"] == "manifest.yaml" - - -def test_complex_operations_with_multiple_flags(parser): - """Test complex operations with multiple flags and arguments.""" - - # Test logs command with multiple flags - result = parser.parse("kubectl logs my-pod -c container-name --follow --tail=100") - assert result["command"]["verb"] == "logs" - assert result["command"]["resource"] is None - assert result["command"]["args"] == [ - "my-pod" - ] # container-name is now -c flag's value - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["-c"] == "container-name" # -c now takes container-name as value - assert flags["--follow"] is None - assert flags["--tail"] == "100" - - # Test get with output format - result = parser.parse("kubectl get services -o yaml --sort-by=.metadata.name") - assert result["command"]["verb"] == "get" - assert result["command"]["resource"] == "services" - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["-o"] == "yaml" - assert flags["--sort-by"] == ".metadata.name" - - # Test exec with interactive flags and command - result = parser.parse("kubectl exec -it my-pod -- /bin/bash") - assert result["command"]["verb"] == "exec" - assert result["command"]["resource"] is None - assert "my-pod" in result["command"]["args"] - assert "/bin/bash" in result["command"]["args"] - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["-i"] is None # -it is now split into -i and -t - assert flags["-t"] is None - assert flags["--"] is None # -- is treated as a flag - - -def test_quoted_arguments(parser): - """Test handling of quoted arguments with spaces.""" - - result = parser.parse( - 'kubectl create secret generic my-secret --from-literal=key="value with spaces"' - ) - assert result["command"]["verb"] == "create" - assert result["command"]["resource"] == "secret" - assert "generic" in result["command"]["args"] - assert "my-secret" in result["command"]["args"] - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert ( - flags["--from-literal"] == "key=value with spaces" - ) # Quotes are removed by tokenizer - - -def test_subcommands(parser): - """Test kubectl subcommands like rollout, config, auth.""" - - # Test rollout status - result = parser.parse("kubectl rollout status deployment/nginx") - assert result["command"]["verb"] == "rollout" - assert result["command"]["resource"] == "status" - assert "deployment/nginx" in result["command"]["args"] - - # Test rollout undo with flag - result = parser.parse("kubectl rollout undo deployment/abc --to-revision=3") - assert result["command"]["verb"] == "rollout" - assert result["command"]["resource"] == "undo" - assert "deployment/abc" in result["command"]["args"] - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["--to-revision"] == "3" - - # Test config view - result = parser.parse("kubectl config view") - assert result["command"]["verb"] == "config" - assert result["command"]["resource"] == "view" - - # Test config use-context - result = parser.parse("kubectl config use-context production") - assert result["command"]["verb"] == "config" - assert result["command"]["resource"] == "use-context" - assert "production" in result["command"]["args"] - - # Test auth can-i - result = parser.parse("kubectl auth can-i create pods") - assert result["command"]["verb"] == "auth" - assert result["command"]["resource"] == "can-i" - assert "create" in result["command"]["args"] - assert "pods" in result["command"]["args"] - - -def test_creation_commands(parser): - """Test resource creation commands with various flags.""" - - # Test deployment creation - result = parser.parse("kubectl create deployment nginx --image=nginx --replicas=3") - assert result["command"]["verb"] == "create" - assert result["command"]["resource"] == "deployment" - assert "nginx" in result["command"]["args"] - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["--image"] == "nginx" - assert flags["--replicas"] == "3" - - # Test service creation - result = parser.parse("kubectl create service clusterip my-service --tcp=80:8080") - assert result["command"]["verb"] == "create" - assert result["command"]["resource"] == "service" - assert "clusterip" in result["command"]["args"] - assert "my-service" in result["command"]["args"] - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["--tcp"] == "80:8080" - - # Test configmap creation - result = parser.parse( - "kubectl create configmap my-config --from-file=config.properties" - ) - assert result["command"]["verb"] == "create" - assert result["command"]["resource"] == "configmap" - assert "my-config" in result["command"]["args"] - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["--from-file"] == "config.properties" - - -def test_debugging_operations(parser): - """Test debugging and troubleshooting commands.""" - - # Test debug command - result = parser.parse("kubectl debug my-pod --image=busybox --target=app") - assert result["command"]["verb"] == "debug" - assert result["command"]["args"][0] == "my-pod" - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["--image"] == "busybox" - assert flags["--target"] == "app" - - # Test port-forward - result = parser.parse("kubectl port-forward pod/my-pod 8080:80") - assert result["command"]["verb"] == "port-forward" - assert result["command"]["resource"] is None - assert "pod/my-pod" in result["command"]["args"] - assert "8080:80" in result["command"]["args"] - - # Test cp command - result = parser.parse("kubectl cp /local/path pod/my-pod:/remote/path") - assert result["command"]["verb"] == "cp" - assert result["command"]["resource"] is None - assert "/local/path" in result["command"]["args"] - assert "pod/my-pod:/remote/path" in result["command"]["args"] - - # Test top command - result = parser.parse("kubectl top nodes --sort-by=cpu") - assert result["command"]["verb"] == "top" - assert result["command"]["resource"] == "nodes" - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["--sort-by"] == "cpu" - - -def test_advanced_operations(parser): - """Test advanced operations like patch, scale, autoscale.""" - - # Test patch with JSON - result = parser.parse( - 'kubectl patch deployment nginx -p \'{"spec":{"replicas":5}}\'' - ) - assert result["command"]["verb"] == "patch" - assert result["command"]["resource"] == "deployment" - assert "nginx" in result["command"]["args"] - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["-p"] == '{"spec":{"replicas":5}}' # JSON is now -p flag's value - - # Test scale - result = parser.parse("kubectl scale deployment nginx --replicas=10") - assert result["command"]["verb"] == "scale" - assert result["command"]["resource"] == "deployment" - assert "nginx" in result["command"]["args"] - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["--replicas"] == "10" - - # Test autoscale - result = parser.parse( - "kubectl autoscale deployment nginx --min=2 --max=10 --cpu-percent=80" - ) - assert result["command"]["verb"] == "autoscale" - assert result["command"]["resource"] == "deployment" - assert "nginx" in result["command"]["args"] - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["--min"] == "2" - assert flags["--max"] == "10" - assert flags["--cpu-percent"] == "80" - - # Test wait - result = parser.parse( - "kubectl wait --for=condition=Ready pod/my-pod --timeout=300s" - ) - assert result["command"]["verb"] == "wait" - assert result["command"]["resource"] == "pod/my-pod" - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["--for"] == "condition=Ready" - assert flags["--timeout"] == "300s" - - -def test_cluster_management(parser): - """Test cluster management commands.""" - - # Test drain - result = parser.parse("kubectl drain node-1 --ignore-daemonsets") - assert result["command"]["verb"] == "drain" - assert result["command"]["resource"] == "node-1" - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["--ignore-daemonsets"] is None - - # Test cordon - result = parser.parse("kubectl cordon node-1") - assert result["command"]["verb"] == "cordon" - assert result["command"]["resource"] == "node-1" - - # Test taint - result = parser.parse("kubectl taint nodes node-1 key=value:NoSchedule") - assert result["command"]["verb"] == "taint" - assert result["command"]["resource"] == "nodes" - assert "node-1" in result["command"]["args"] - assert "key=value:NoSchedule" in result["command"]["args"] - - -def test_commands_without_kubectl_prefix(parser): - """Test commands without the kubectl prefix.""" - - # Test get without kubectl prefix - result = parser.parse("get pods -o wide --all-namespaces") - assert result["command"]["verb"] == "get" - assert result["command"]["resource"] == "pods" - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["-o"] == "wide" - assert flags["--all-namespaces"] is None - - # Test apply with kustomize - result = parser.parse("apply -k ./kustomize-dir") - assert result["command"]["verb"] == "apply" - assert ( - result["command"]["resource"] is None - ) # -k now takes ./kustomize-dir as value - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["-k"] == "./kustomize-dir" - - -def test_edge_cases(parser): - """Test edge cases and malformed commands.""" - - # Test empty kubectl command - result = parser.parse("kubectl") - assert result["command"]["verb"] is None - assert result["command"]["resource"] is None - assert len(result["command"]["flags"]) == 0 - - # Test kubectl with only help flag - result = parser.parse("kubectl --help") - assert result["command"]["verb"] is None - assert result["command"]["resource"] is None - assert any(flag["name"] == "--help" for flag in result["command"]["flags"]) - - # Test get without resource - result = parser.parse("kubectl get") - assert result["command"]["verb"] == "get" - assert result["command"]["resource"] is None - - # Test empty string - result = parser.parse("") - assert result["command"]["verb"] is None - assert result["command"]["resource"] is None - - # Test whitespace only - result = parser.parse(" ") - assert result["command"]["verb"] is None - assert result["command"]["resource"] is None - - -def test_flag_parsing_variations(parser): - """Test various flag parsing scenarios.""" - - # Test short flag with value - result = parser.parse("kubectl get pods -n test") - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["-n"] == "test" - - # Test long flag with equals - result = parser.parse("kubectl get pods --namespace=production") - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["--namespace"] == "production" - - # Test boolean flags - result = parser.parse("kubectl get pods --watch --all-namespaces") - flag_names = [flag["name"] for flag in result["command"]["flags"]] - assert "--watch" in flag_names - assert "--all-namespaces" in flag_names - - # Test mixed flag formats - result = parser.parse("kubectl logs pod -f --tail=10 -c container") - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["-f"] is None - assert flags["--tail"] == "10" - assert flags["-c"] == "container" # -c now takes container as value - assert result["command"]["args"] == ["pod"] # container is now -c flag's value - - -def test_reset_functionality(parser): - """Test that parser state is reset between calls.""" - - # Parse first command - result1 = parser.parse("kubectl get pods -n test") - assert result1["command"]["namespace"] == "test" - - # Parse second command without namespace - result2 = parser.parse("kubectl describe pod my-pod") - assert result2["command"]["namespace"] is None - assert result2["command"]["verb"] == "describe" - assert result2["command"]["resource"] == "pod" - - -def test_tokenizer_with_quotes(parser): - """Test tokenizer handles quoted strings correctly.""" - - # Test single quotes - result = parser.parse( - "kubectl create secret generic test --from-literal='key=value with spaces'" - ) - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["--from-literal"] == "key=value with spaces" - - # Test double quotes - result = parser.parse( - 'kubectl create secret generic test --from-literal="key=value with spaces"' - ) - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["--from-literal"] == "key=value with spaces" - - # Test nested quotes in JSON - result = parser.parse( - 'kubectl patch pod test -p \'{"metadata":{"labels":{"app":"test"}}}\'' - ) - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert ( - flags["-p"] == '{"metadata":{"labels":{"app":"test"}}}' - ) # -p now takes JSON as value - assert result["command"]["args"] == [ - "test" - ] # test is the pod name, JSON is now -p flag's value - - -@patch("builtins.print") -def test_main_function(mock_print): - """Test the main() function runs without errors and processes all test commands.""" - # Call the main function - main() - - # Verify that print was called (output was produced) - assert mock_print.called - - # Get all the print calls - extract the first argument from each call - print_calls = [] - for call in mock_print.call_args_list: - if call.args: # call.args contains the positional arguments - print_calls.append(str(call.args[0])) - - # Verify that we have output for commands and results - # Note: command lines start with \nCommand: due to the print formatting in main() - command_lines = [line for line in print_calls if "Command: " in line] - result_lines = [line for line in print_calls if line.startswith("Parsed: ")] - - # Should have at least some command and result lines - assert ( - len(command_lines) > 0 - ), f"No command lines found in output. All calls: {print_calls[:5]}..." - assert len(result_lines) > 0, "No result lines found in output" - - # Verify some expected commands are processed - all_output = " ".join(print_calls) - assert "kubectl get pods" in all_output - assert "kubectl debug my-pod" in all_output - assert "kubectl taint nodes" in all_output - - # Verify that parsing results are included in output - assert "{'command':" in all_output, "No parsing results found in output" - - -def test_flag_before_verb_skips_value(parser): - """Test that flags with values before the verb are properly skipped to find the verb.""" - # This command has a flag with a value before the verb 'get' - command = "kubectl --namespace production get pods" - result = parser.parse(command) - - # Verify the verb was correctly identified despite the flag before it - assert result["command"]["verb"] == "get" - assert result["command"]["resource"] == "pods" - assert result["command"]["namespace"] == "production" - - # Verify the flag was parsed correctly - flags = result["command"]["flags"] - assert len(flags) == 1 - assert flags[0]["name"] == "--namespace" - assert flags[0]["value"] == "production" - - -def test_empty_tokens_after_tokenization(parser): - """Test case where tokenization results in empty tokens list""" - # This should have non-empty string but tokenize to empty list - # For example, a string with only empty quotes - result = parser.parse('kubectl ""') - expected = { - "command": { - "verb": None, - "resource": None, - "namespace": None, - "args": [], - "flags": [], - } - } - assert result == expected - - -def test_namespace_flag_without_value(parser): - """Test namespace flag without a value (XXX comment case)""" - # Test -n flag at end of command (no value) - result = parser.parse("kubectl get pods -n") - - assert result["command"]["verb"] == "get" - assert result["command"]["resource"] == "pods" - assert ( - result["command"]["namespace"] is None - ) # Should be None since no value provided - assert len(result["command"]["flags"]) == 1 - assert result["command"]["flags"][0]["name"] == "-n" - assert result["command"]["flags"][0]["value"] is None - - # Test --namespace flag at end of command (no value) - result = parser.parse("kubectl get pods --namespace") - - assert result["command"]["verb"] == "get" - assert result["command"]["resource"] == "pods" - assert result["command"]["namespace"] is None - assert len(result["command"]["flags"]) == 1 - assert result["command"]["flags"][0]["name"] == "--namespace" - assert result["command"]["flags"][0]["value"] is None - - # Test -n flag followed by another flag (no value for -n) - result = parser.parse("kubectl get pods -n -o yaml") - - assert result["command"]["verb"] == "get" - assert result["command"]["resource"] == "pods" - assert result["command"]["namespace"] is None - assert len(result["command"]["flags"]) == 2 - - # Find the -n flag - n_flag = next(flag for flag in result["command"]["flags"] if flag["name"] == "-n") - assert n_flag["value"] is None - - # Find the -o flag - o_flag = next(flag for flag in result["command"]["flags"] if flag["name"] == "-o") - assert o_flag["value"] == "yaml" - - -def test_unquoted_selector_parsing(parser): - """Test parsing of unquoted selector expressions.""" - - # Test the original problem cases - result = parser.parse( - "kubectl get pods -n otel-demo -l service in (email,checkout)" - ) - assert result["command"]["verb"] == "get" - assert result["command"]["resource"] == "pods" - assert result["command"]["namespace"] == "otel-demo" - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["-l"] == "service in (email,checkout)" - assert len(result["command"]["args"]) == 0 # No leftover args - - result = parser.parse( - "kubectl get deployments -n otel-demo -o jsonpath='...' --selector=service in (ad,cart,payment)" - ) - assert result["command"]["verb"] == "get" - assert result["command"]["resource"] == "deployments" - assert result["command"]["namespace"] == "otel-demo" - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["--selector"] == "service in (ad,cart,payment)" - assert flags["-o"] == "jsonpath=..." - assert len(result["command"]["args"]) == 0 # No leftover args - - -def test_selector_parsing_variations(parser): - """Test different selector parsing scenarios.""" - - # Simple equality selectors - result = parser.parse("kubectl get pods -l app=nginx") - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["-l"] == "app=nginx" - - # Not equal selectors - result = parser.parse("kubectl get pods -l app!=nginx") - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["-l"] == "app!=nginx" - - # Multiple selectors with comma - result = parser.parse("kubectl get pods -l app=nginx,env=prod") - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["-l"] == "app=nginx,env=prod" - - # --selector format with in operator - result = parser.parse("kubectl get pods --selector=tier in (frontend,backend)") - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["--selector"] == "tier in (frontend,backend)" - - # notin operator - result = parser.parse("kubectl get pods -l environment notin (production,staging)") - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["-l"] == "environment notin (production,staging)" - - # Complex selector with 'and' - result = parser.parse("kubectl get pods -l app=web and version!=old") - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["-l"] == "app=web and version!=old" - - -def test_selector_edge_cases(parser): - """Test edge cases for selector parsing.""" - - # Empty selector with quotes - this should actually result in None since there's no content - result = parser.parse('kubectl get pods -l ""') - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - # Empty string in quotes results in no selector tokens, so value is None - assert flags["-l"] is None - - # Missing selector value (flag without value) - result = parser.parse("kubectl get pods -l") - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["-l"] is None - - # Empty selector value with equals - result = parser.parse("kubectl get pods --selector=") - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["--selector"] == "" - - # Selector followed by another flag - result = parser.parse("kubectl get pods -l app=nginx -o yaml") - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["-l"] == "app=nginx" - assert flags["-o"] == "yaml" - - # Complex selector - note that complex expressions with multiple 'in'/'notin' - # may not parse as expected due to the tokenization, but simple ones should work - result = parser.parse("kubectl get pods -l 'app in (web,api),env notin (dev)'") - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["-l"] == "app in (web,api),env notin (dev)" - - -def test_quoted_selector_compatibility(parser): - """Test that quoted selectors still work correctly.""" - - # Single quoted selector - result = parser.parse("kubectl get pods -l 'app in (nginx,apache)'") - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["-l"] == "app in (nginx,apache)" - - # Double quoted selector - result = parser.parse('kubectl get pods -l "service in (web,api)"') - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["-l"] == "service in (web,api)" - - # Quoted selector with equals format - result = parser.parse('kubectl get pods --selector="app in (frontend,backend)"') - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["--selector"] == "app in (frontend,backend)" - - -def test_field_selector_compatibility(parser): - """Test that field selectors still work correctly.""" - - # Field selector should use existing logic (not the special selector logic) - result = parser.parse( - "kubectl get services --all-namespaces --field-selector metadata.namespace!=default" - ) - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["--field-selector"] == "metadata.namespace!=default" - assert flags["--all-namespaces"] is None - - -def test_selector_with_mixed_flags(parser): - """Test selectors combined with other flags.""" - - # Selector with namespace and output format - result = parser.parse("kubectl get pods -n prod -l app in (web,api) -o wide") - assert result["command"]["namespace"] == "prod" - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["-n"] == "prod" - assert flags["-l"] == "app in (web,api)" - assert flags["-o"] == "wide" - - # Multiple complex flags including selector - result = parser.parse( - "kubectl get deployments --all-namespaces --selector=tier in (frontend,backend) --sort-by=.metadata.name" - ) - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["--all-namespaces"] is None - assert flags["--selector"] == "tier in (frontend,backend)" - assert flags["--sort-by"] == ".metadata.name" - - -def test_selector_coverage_edge_cases(parser): - """Test specific edge cases to achieve 100% coverage.""" - - # Test line 333: selector followed by a flag when paren_depth == 0 (normal case) - result = parser.parse("kubectl get pods -l app=nginx -o yaml") - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["-l"] == "app=nginx" - assert flags["-o"] == "yaml" - - # Test lines 369-370: empty selector tokens result in None value - result = parser.parse("kubectl get pods -l") - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["-l"] is None - - # Test lines 359-361: This tests the case where we have collected some tokens, - # paren_depth is 0, last token is NOT 'in' or 'notin', so we break - # This case: "app" followed by "nginx" (not an operator, not a flag) - result = parser.parse("kubectl get pods -l app nginx -o yaml") - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert ( - flags["-l"] == "app" - ) # Should stop at "app" because next token "nginx" is not an operator - assert flags["-o"] == "yaml" - assert "nginx" in result["command"]["args"] # nginx becomes an argument - - # Test lines 254-256: Same logic but in flag=value format - # Note: the flag=value format continues differently, so we expect different behavior - result = parser.parse("kubectl get pods --selector=app nginx -o yaml") - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["--selector"] == "app nginx" # flag=value format continues parsing - assert flags["-o"] == "yaml" - - -def test_selector_comprehensive_scenarios(parser): - """Test comprehensive selector scenarios.""" - - # Test unquoted selector with complex parenthetical expressions - result = parser.parse("kubectl get pods -l service in (email,checkout)") - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["-l"] == "service in (email,checkout)" - - # Test equals format with complex selector - result = parser.parse( - "kubectl get deployments --selector=service in (ad,cart,payment)" - ) - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["--selector"] == "service in (ad,cart,payment)" - - # Test mixed operators - result = parser.parse("kubectl get pods -l 'app=nginx,env!=prod'") - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["-l"] == "app=nginx,env!=prod" - - -def test_final_coverage_edge_cases(parser): - """Test remaining edge cases to achieve 100% coverage.""" - - # Test lines 254-256: flag=value format where last token is NOT 'in'/'notin' - # The break condition happens when the last token is not 'in'/'notin' and next is not an operator - result = parser.parse("kubectl get pods --selector=app=nginx unknown -o yaml") - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - # Based on actual behavior, it continues to parse - assert flags["--selector"] == "app=nginx unknown" - assert flags["-o"] == "yaml" - - # Test line 333: This is hit in normal flag parsing when we encounter a flag - # This should be hit by many existing tests, but let's be explicit - result = parser.parse("kubectl get pods -l app=test -o json") - flags = {flag["name"]: flag["value"] for flag in result["command"]["flags"]} - assert flags["-l"] == "app=test" - assert flags["-o"] == "json" - - -def test_parser_script_execution(): - """Test that parser.py script can be executed directly.""" - try: - # Run the parser.py script as a module - result = subprocess.run( - [sys.executable, "-m", "kubectlcmdprocessor.parser"], - capture_output=True, - text=True, - timeout=30, - ) - - # Check that the script ran successfully (exit code 0) - assert result.returncode == 0 - - # Check that some output was produced - assert len(result.stdout) > 0 - - # Check that no errors were written to stderr - assert result.stderr == "" - - except subprocess.TimeoutExpired: - pytest.fail("Script execution timed out") - except Exception as e: - pytest.fail(f"Script execution failed: {e}") diff --git a/scripts/tests/unit/test_visualize_policy.py b/scripts/tests/unit/test_visualize_policy.py deleted file mode 100644 index 1d98c89..0000000 --- a/scripts/tests/unit/test_visualize_policy.py +++ /dev/null @@ -1,480 +0,0 @@ -#!/usr/bin/env python3 -# Copyright 2026 Smith authors -# SPDX-License-Identifier: Apache-2.0 - -"""Unit tests for visualization/visualize_policy.py""" - -import pytest -import tempfile -import os -from unittest.mock import patch, mock_open - -from visualization.visualize_policy import ( - RegoRule, - DecisionNode, - RegoParser, - MermaidGenerator, - main, -) - - -class TestRegoRule: - """Test RegoRule dataclass""" - - def test_rego_rule_creation(self): - """Test RegoRule creation with all fields""" - rule = RegoRule( - name="test_rule", - conditions=["condition1", "condition2"], - outcome="allow", - rule_type="allow", - ) - assert rule.name == "test_rule" - assert rule.conditions == ["condition1", "condition2"] - assert rule.outcome == "allow" - assert rule.rule_type == "allow" - - -class TestDecisionNode: - """Test DecisionNode dataclass""" - - def test_decision_node_creation(self): - """Test DecisionNode creation with all fields""" - node = DecisionNode( - id="A", - label="Test Node", - node_type="condition", - conditions=["test condition"], - children=[], - ) - assert node.id == "A" - assert node.label == "Test Node" - assert node.node_type == "condition" - assert node.conditions == ["test condition"] - assert node.children == [] - assert node.parent is None - - def test_decision_node_with_parent(self): - """Test DecisionNode with parent relationship""" - parent = DecisionNode("A", "Parent", "start", [], []) - child = DecisionNode("B", "Child", "condition", [], [], parent=parent) - assert child.parent == parent - - -class TestRegoParser: - """Test RegoParser class""" - - def setUp(self): - """Set up test fixtures""" - self.parser = RegoParser() - - def test_init(self): - """Test RegoParser initialization""" - parser = RegoParser() - assert parser.rules == [] - assert parser.sets == {} - - def test_extract_sets(self): - """Test _extract_sets method""" - parser = RegoParser() - content = """ - safe_verbs := {"get", "list", "watch"} - dangerous_verbs := {"delete", "create"} - """ - parser._extract_sets(content) - - assert "safe_verbs" in parser.sets - assert "dangerous_verbs" in parser.sets - assert parser.sets["safe_verbs"] == ["get", "list", "watch"] - assert parser.sets["dangerous_verbs"] == ["delete", "create"] - - def test_parse_conditions(self): - """Test _parse_conditions method""" - parser = RegoParser() - condition_block = """ - input.command.verb == "get" - input.command.resource == "pods" - # This is a comment - - input.namespace == "default" - """ - - conditions = parser._parse_conditions(condition_block) - expected = [ - 'input.command.verb == "get"', - 'input.command.resource == "pods"', - 'input.namespace == "default"', - ] - assert conditions == expected - - def test_parse_conditions_empty(self): - """Test _parse_conditions with empty input""" - parser = RegoParser() - conditions = parser._parse_conditions("") - assert conditions == [] - - def test_parse_conditions_with_comments(self): - """Test _parse_conditions ignores comments""" - parser = RegoParser() - condition_block = """ - # This is a comment - input.command.verb == "get" - # Another comment - """ - - conditions = parser._parse_conditions(condition_block) - assert conditions == ['input.command.verb == "get"'] - - def test_extract_rules_allow(self): - """Test _extract_rules for allow rules""" - parser = RegoParser() - content = """ - allow if { - input.command.verb == "get" - input.command.resource == "pods" - } - """ - parser._extract_rules(content) - - assert len(parser.rules) == 1 - rule = parser.rules[0] - assert rule.rule_type == "allow" - assert rule.outcome == "allow" - assert len(rule.conditions) == 2 - - def test_extract_rules_requires_approval(self): - """Test _extract_rules for requires_approval rules""" - parser = RegoParser() - content = """ - requires_approval if { - input.command.verb == "delete" - input.command.resource == "pods" - } - """ - parser._extract_rules(content) - - assert len(parser.rules) == 1 - rule = parser.rules[0] - assert rule.rule_type == "requires_approval" - assert rule.outcome == "requires_approval" - - def test_extract_rules_default_deny(self): - """Test _extract_rules for default deny rules""" - parser = RegoParser() - content = "default deny := true" - parser._extract_rules(content) - - assert len(parser.rules) == 1 - rule = parser.rules[0] - assert rule.rule_type == "deny" - assert rule.outcome == "deny" - - def test_extract_rules_classification_rules(self): - """Test _extract_rules for classification rules""" - parser = RegoParser() - content = """ - is_safe_operation if { - input.command.verb in safe_verbs - } - - is_restricted_operation if { - input.command.verb == "delete" - } - - is_forbidden_operation if { - input.command.verb in forbidden_verbs - } - """ - parser._extract_rules(content) - - assert len(parser.rules) == 3 - rule_types = [rule.rule_type for rule in parser.rules] - assert "safe" in rule_types - assert "restricted" in rule_types - assert "forbidden" in rule_types - - def test_parse_file_with_temp_file(self): - """Test parse_file method with a temporary file""" - parser = RegoParser() - content = """ - # Test policy file - safe_verbs := {"get", "list"} - - allow if { - input.command.verb in safe_verbs - } - - default deny := true - """ - - with tempfile.NamedTemporaryFile(mode="w", suffix=".rego", delete=False) as f: - f.write(content) - temp_file = f.name - - try: - rules = parser.parse_file(temp_file) - assert len(rules) >= 1 - assert parser.sets["safe_verbs"] == ["get", "list"] - finally: - os.unlink(temp_file) - - def test_parse_file_removes_comments(self): - """Test that parse_file removes comments properly""" - parser = RegoParser() - content = """ - # This is a comment - allow if { - input.command.verb == "get" # inline comment - } - """ - - with tempfile.NamedTemporaryFile(mode="w", suffix=".rego", delete=False) as f: - f.write(content) - temp_file = f.name - - try: - rules = parser.parse_file(temp_file) - # Should parse successfully without comment-related errors - assert isinstance(rules, list) - finally: - os.unlink(temp_file) - - -class TestMermaidGenerator: - """Test MermaidGenerator class""" - - def test_init(self): - """Test MermaidGenerator initialization""" - generator = MermaidGenerator() - assert generator.node_counter == 0 - assert generator.nodes == {} - - def test_get_conditions_for_type(self): - """Test _get_conditions_for_type method""" - generator = MermaidGenerator() - rules = [ - RegoRule("rule1", ["condition1"], "safe", "safe"), - RegoRule("rule2", ["condition2"], "restricted", "restricted"), - RegoRule("rule3", ["condition3"], "safe", "safe"), - ] - - safe_conditions = generator._get_conditions_for_type(rules, "safe") - assert safe_conditions == ["condition1"] - - restricted_conditions = generator._get_conditions_for_type(rules, "restricted") - assert restricted_conditions == ["condition2"] - - nonexistent_conditions = generator._get_conditions_for_type( - rules, "nonexistent" - ) - assert nonexistent_conditions == [] - - def test_extract_key_conditions(self): - """Test _extract_key_conditions method""" - generator = MermaidGenerator() - conditions = [ - "input.command.verb == 'get'", - "input.command.resource == 'pods'", - "input.namespace == 'default'", - "verb in safe_verbs", - "forbidden_check == true", - ] - - key_conditions = generator._extract_key_conditions(conditions) - expected = [ - "verb check", - "resource check", - "namespace check", - "safe verbs", - "forbidden check", - ] - assert key_conditions == expected - - def test_get_edge_label(self): - """Test _get_edge_label method""" - generator = MermaidGenerator() - parent = DecisionNode("A", "Test", "condition", [], []) - - # Test safe command edge - safe_child = DecisionNode("B", "Safe operation", "outcome", [], []) - assert generator._get_edge_label(parent, safe_child) == "Safe Command" - - # Test restricted command edge - restricted_child = DecisionNode("C", "requires approval", "outcome", [], []) - assert ( - generator._get_edge_label(parent, restricted_child) == "Restricted Command" - ) - - # Test forbidden command edge - forbidden_child = DecisionNode("D", "forbidden operation", "outcome", [], []) - assert generator._get_edge_label(parent, forbidden_child) == "Forbidden Command" - - # Test default edge (should also match "deny" condition) - default_child = DecisionNode("E", "default other", "outcome", [], []) - assert generator._get_edge_label(parent, default_child) == "Other" - - # Test non-condition parent - non_condition_parent = DecisionNode("F", "Test", "start", [], []) - assert generator._get_edge_label(non_condition_parent, safe_child) == "" - - def test_build_decision_tree(self): - """Test _build_decision_tree method""" - generator = MermaidGenerator() - rules = [ - RegoRule("safe_rule", ["input.command.verb in safe_verbs"], "safe", "safe"), - RegoRule( - "restricted_rule", - ["input.command.verb == 'delete'"], - "restricted", - "restricted", - ), - RegoRule( - "forbidden_rule", - ["input.command.verb in forbidden_verbs"], - "forbidden", - "forbidden", - ), - ] - - root = generator._build_decision_tree(rules) - - assert root.id == "A" - assert root.label == "Start Policy Evaluation" - assert root.node_type == "start" - assert len(root.children) == 1 # Should have classification node - - def test_generate_mermaid_syntax_basic(self): - """Test _generate_mermaid_syntax with basic tree""" - generator = MermaidGenerator() - - # Create a simple tree manually - root = DecisionNode("A", "Start", "start", [], []) - child = DecisionNode("B", "End", "outcome", [], []) - root.children.append(child) - - mermaid_content = generator._generate_mermaid_syntax(root) - - assert "graph TD" in mermaid_content - assert 'A["Start"]' in mermaid_content - assert 'B["End"]' in mermaid_content - assert "A --> B" in mermaid_content - - def test_generate_diagram_integration(self): - """Test generate_diagram method integration""" - generator = MermaidGenerator() - rules = [ - RegoRule("safe_rule", ["input.command.verb in safe_verbs"], "safe", "safe"), - RegoRule( - "restricted_rule", - ["input.command.verb == 'delete'"], - "restricted", - "restricted", - ), - ] - - diagram = generator.generate_diagram(rules) - - assert isinstance(diagram, str) - assert "graph TD" in diagram - assert "Start Policy Evaluation" in diagram - - def test_add_node_to_mermaid_prevents_cycles(self): - """Test _add_node_to_mermaid prevents infinite cycles""" - generator = MermaidGenerator() - - # Create nodes that could cause a cycle - node_a = DecisionNode("A", "Node A", "condition", [], []) - node_b = DecisionNode("B", "Node B", "condition", [], []) - node_a.children.append(node_b) - node_b.children.append(node_a) # This would create a cycle - - lines = ["graph TD"] - visited = set() - - # This should not cause infinite recursion - generator._add_node_to_mermaid(node_a, lines, visited) - - # Both nodes should be in visited set - assert "A" in visited - assert "B" in visited - - -class TestMainFunction: - """Test main function and CLI functionality""" - - @patch("sys.argv", ["visualize_policy.py", "--policy-file", "test.rego"]) - @patch("visualization.visualize_policy.Path.exists") - @patch("builtins.open", new_callable=mock_open, read_data="allow if { true }") - @patch("visualization.visualize_policy.Path.mkdir") - def test_main_basic_execution(self, mock_mkdir, mock_file, mock_exists): - """Test main function basic execution""" - mock_exists.return_value = True - - with patch("builtins.print"): - # Main function should complete normally without raising SystemExit - try: - main() - except SystemExit: - # If it does exit, that's also acceptable - pass - # Test passes if no exception is raised or SystemExit with code 0 - - @patch("sys.argv", ["visualize_policy.py", "--policy-file", "nonexistent.rego"]) - @patch("visualization.visualize_policy.Path.exists") - def test_main_file_not_found(self, mock_exists): - """Test main function with non-existent policy file""" - mock_exists.return_value = False - - with pytest.raises(SystemExit) as exc_info: - with patch("builtins.print"): - main() - assert exc_info.value.code == 1 - - @patch("sys.argv", ["visualize_policy.py", "--help"]) - def test_main_help_option(self): - """Test main function with help option""" - with pytest.raises(SystemExit) as exc_info: - main() - # Help should exit with code 0 - assert exc_info.value.code == 0 - - @patch( - "sys.argv", - ["visualize_policy.py", "--policy-file", "test.rego", "--format", "mermaid"], - ) - @patch("visualization.visualize_policy.Path.exists") - @patch("builtins.open", new_callable=mock_open, read_data="allow if { true }") - @patch("visualization.visualize_policy.Path.mkdir") - def test_main_mermaid_format(self, mock_mkdir, mock_file, mock_exists): - """Test main function with mermaid format output""" - mock_exists.return_value = True - - with patch("builtins.print"): - # Main function should complete normally - try: - main() - except SystemExit: - # If it does exit, that's also acceptable - pass - - @patch( - "sys.argv", ["visualize_policy.py", "--policy-file", "test.rego", "--verbose"] - ) - @patch("visualization.visualize_policy.Path.exists") - @patch("builtins.open", new_callable=mock_open, read_data="allow if { true }") - @patch("visualization.visualize_policy.Path.mkdir") - def test_main_verbose_mode(self, mock_mkdir, mock_file, mock_exists): - """Test main function with verbose output""" - mock_exists.return_value = True - - with patch("builtins.print"): - # Main function should complete normally - try: - main() - except SystemExit: - # If it does exit, that's also acceptable - pass - - -if __name__ == "__main__": - pytest.main([__file__]) diff --git a/scripts/visualization/.gitkeep b/scripts/visualization/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/scripts/visualization/README.md b/scripts/visualization/README.md deleted file mode 100644 index 9173007..0000000 --- a/scripts/visualization/README.md +++ /dev/null @@ -1,14 +0,0 @@ -## Done - -### Generate and visualize graph - -- `cd ../../` -- `make opaserver/parse` - Generate json file from policies -- `cd blue_agent_components/visualization` -- `python parse_ast_to_graph.py ast.json` - Extract graph from the json file -- `python parse_graph_to_json.py` - Convert generated graph to a json format -- `python -m http.server 8000` - Start local server to view the webpage -- Check the graph in http://localhost:8000/graph.html - -## TBD -- Visualize maps between requirements and policy diff --git a/scripts/visualization/__init__.py b/scripts/visualization/__init__.py deleted file mode 100644 index 021d56a..0000000 --- a/scripts/visualization/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# Copyright 2026 Smith authors -# SPDX-License-Identifier: Apache-2.0 diff --git a/scripts/visualization/ast.dot b/scripts/visualization/ast.dot deleted file mode 100644 index 6dec60e..0000000 --- a/scripts/visualization/ast.dot +++ /dev/null @@ -1,335 +0,0 @@ -digraph { -"0& allow" [type=boolean, index=0, fullname="0& allow"]; -"2& is_safe_operation" [index=2, type=boolean, fullname="2& is_safe_operation"]; -"3& is_forbidden_operation" [index=3, type=boolean, fullname="3& is_forbidden_operation"]; -"4& passes_resource_restrictions" [index=4, type=boolean, fullname="4& passes_resource_restrictions"]; -"5& has_dangerous_flags" [index=5, type=boolean, fullname="5& has_dangerous_flags"]; -"6& is_valid_command_structure" [index=6, type=boolean, fullname="6& is_valid_command_structure"]; -"7& requires_approval" [index=7, type=boolean, fullname="7& requires_approval"]; -"8& is_restricted_operation" [index=8, type=boolean, fullname="8& is_restricted_operation"]; -"9& passes_namespace_restrictions" [index=9, type=boolean, fullname="9& passes_namespace_restrictions"]; -"10& deny" [type=boolean, index=10, fullname="10& deny"]; -"11& input.command.verb" [index=11, type=None, fullname="11& input.command.verb"]; -"12& safe_verbs" [index=12, type=set, fullname="12& safe_verbs"]; -"13& all_resources_are_safe" [index=13, type=boolean, fullname="13& all_resources_are_safe"]; -"14& resource_less_safe_verbs" [index=14, type=set, fullname="14& resource_less_safe_verbs"]; -"15& input.command.resource" [index=15, type=None, fullname="15& input.command.resource"]; -"16& null" [index=16, type=None, fullname="16& null"]; -"17& resource_types" [index=17, type=None, fullname="17& resource_types"]; -"18& resource_type" [index=18, type=var, fullname="18& resource_type"]; -"19& safe_resources" [index=19, type=set, fullname="19& safe_resources"]; -"20& describe.get.list.logs" [index=20, type=None, fullname="20& describe.get.list.logs"]; -"21& forbidden_resources" [index=21, type=set, fullname="21& forbidden_resources"]; -"23& resource_string" [index=23, type=None, fullname="23& resource_string"]; -"24& Null string" [index=24, type=None, fullname="24& Null string"]; -"26& restricted_verbs" [index=26, type=set, fullname="26& restricted_verbs"]; -"27& all_resources_modifiable" [index=27, type=boolean, fullname="27& all_resources_modifiable"]; -"28& allowed_resources_for_modification" [index=28, type=set, fullname="28& allowed_resources_for_modification"]; -"29& forbidden_verbs" [index=29, type=set, fullname="29& forbidden_verbs"]; -"30& delete" [index=30, type=None, fullname="30& delete"]; -"31& critical_resources" [index=31, type=set, fullname="31& critical_resources"]; -"32& targets_rbac_resources" [index=32, type=boolean, fullname="32& targets_rbac_resources"]; -"33& targets_security_resources" [index=33, type=boolean, fullname="33& targets_security_resources"]; -"34& targets_system_resources" [index=34, type=boolean, fullname="34& targets_system_resources"]; -"35& clusterrole.clusterrolebinding.clusterrolebindings.clusterroles.role.rolebinding.rolebindings.roles.serviceaccount.serviceaccounts" [index=35, type=None, fullname="35& clusterrole.clusterrolebinding.clusterrolebindings.clusterroles.role.rolebinding.rolebindings.roles.serviceaccount.serviceaccounts"]; -"36& apply.create.delete.edit.patch.replace" [index=36, type=None, fullname="36& apply.create.delete.edit.patch.replace"]; -"37& networkpolicies.poddisruptionbudgets.podsecuritypolicies.securitycontextconstraints" [index=37, type=None, fullname="37& networkpolicies.poddisruptionbudgets.podsecuritypolicies.securitycontextconstraints"]; -"38& componentstatuse.componentstatuses.csidriver.csidrivers.csinode.csinodes.node.nodes.volumeattachment.volumeattachments" [index=38, type=None, fullname="38& componentstatuse.componentstatuses.csidriver.csidrivers.csinode.csinodes.node.nodes.volumeattachment.volumeattachments"]; -"39& input.command.namespace" [index=39, type=None, fullname="39& input.command.namespace"]; -"40& describe.get.list" [index=40, type=None, fullname="40& describe.get.list"]; -"41& cluster_scoped_safe_resources" [index=41, type=set, fullname="41& cluster_scoped_safe_resources"]; -"42& namespace" [index=42, type=None, fullname="42& namespace"]; -"43& allowed_namespaces" [index=43, type=set, fullname="43& allowed_namespaces"]; -"44& forbidden_namespaces" [index=44, type=set, fullname="44& forbidden_namespaces"]; -"45& allowed_resources" [index=45, type=call, fullname="45& allowed_resources"]; -"46& secrets" [index=46, type=None, fullname="46& secrets"]; -"47& other_resource" [index=47, type=var, fullname="47& other_resource"]; -"48& --force" [index=48, type=None, fullname="48& --force"]; -"49& input.command.flags" [index=49, type=None, fullname="49& input.command.flags"]; -"50& --grace-period=0" [index=50, type=None, fullname="50& --grace-period=0"]; -"51& --all" [index=51, type=None, fullname="51& --all"]; -"52& --cascade=orphan" [index=52, type=None, fullname="52& --cascade=orphan"]; -"53& flag" [index=53, type=None, fullname="53& flag"]; -"54& --privileged=true" [index=54, type=None, fullname="54& --privileged=true"]; -"55& --host" [index=55, type=None, fullname="55& --host"]; -"56& --as=" [index=56, type=None, fullname="56& --as="]; -"57& --as-group=" [index=57, type=None, fullname="57& --as-group="]; -"58& sudo" [index=58, type=None, fullname="58& sudo"]; -"59& resource_requirement_satisfied" [index=59, type=boolean, fullname="59& resource_requirement_satisfied"]; -"60& contains_injection_patterns" [index=60, type=boolean, fullname="60& contains_injection_patterns"]; -"61& contains_shell_metacharacters" [index=61, type=boolean, fullname="61& contains_shell_metacharacters"]; -"62& valid_resource_names" [index=62, type=boolean, fullname="62& valid_resource_names"]; -"63& apply.attach.cp.debug.exec.logs.port-forward" [index=63, type=None, fullname="63& apply.attach.cp.debug.exec.logs.port-forward"]; -"64& arg" [index=64, type=None, fullname="64& arg"]; -"65& ;" [index=65, type=None, fullname="65& ;"]; -"66& &&" [index=66, type=None, fullname="66& &&"]; -"67& ||" [index=67, type=None, fullname="67& ||"]; -"68& |" [index=68, type=None, fullname="68& |"]; -"69& `" [index=69, type=None, fullname="69& `"]; -"70& $(" [index=70, type=None, fullname="70& $("]; -"71& flag.value" [index=71, type=None, fullname="71& flag.value"]; -"72& input.original_command" [index=72, type=None, fullname="72& input.original_command"]; -"73& [`${}><&]" [index=73, type=None, fullname="73& [`${}><&]"]; -"74& input.command.args" [index=74, type=None, fullname="74& input.command.args"]; -"75& kube-+76& system:" [index=75, type=None, fullname="75& kube-+76& system:"]; -"77& is_valid_resource_name" [index=77, type=boolean, fullname="77& is_valid_resource_name"]; -"78& ^[a-z0-9]([-a-z0-9]*[a-z0-9])?([.][a-z0-9]([-a-z0-9]*[a-z0-9])?)*$" [index=78, type=None, fullname="78& ^[a-z0-9]([-a-z0-9]*[a-z0-9])?([.][a-z0-9]([-a-z0-9]*[a-z0-9])?)*$"]; -"79& ^[a-z0-9]([-a-z0-9]*[a-z0-9])?([.][a-z0-9]([-a-z0-9]*[a-z0-9])?)*([,][a-z0-9]([-a-z0-9]*[a-z0-9])?([.][a-z0-9]([-a-z0-9]*[a-z0-9])?)*)*$" [index=79, type=None, fullname="79& ^[a-z0-9]([-a-z0-9]*[a-z0-9])?([.][a-z0-9]([-a-z0-9]*[a-z0-9])?)*([,][a-z0-9]([-a-z0-9]*[a-z0-9])?([.][a-z0-9]([-a-z0-9]*[a-z0-9])?)*)*$"]; -"80& exec_command_restrictions" [type=boolean, index=80, fullname="80& exec_command_restrictions"]; -"81& exec" [index=81, type=None, fullname="81& exec"]; -"82& contains_dangerous_exec_commands" [index=82, type=boolean, fullname="82& contains_dangerous_exec_commands"]; -"83& valid_exec_structure" [index=83, type=boolean, fullname="83& valid_exec_structure"]; -"84& dangerous_exec_commands" [index=84, type=set, fullname="84& dangerous_exec_commands"]; -"85& rm -rf" [index=85, type=None, fullname="85& rm -rf"]; -"86& dd if=" [index=86, type=None, fullname="86& dd if="]; -"87& port_forward_restrictions" [type=boolean, index=87, fullname="87& port_forward_restrictions"]; -"88& port-forward" [index=88, type=None, fullname="88& port-forward"]; -"89& valid_port_specification" [index=89, type=boolean, fullname="89& valid_port_specification"]; -"90& :" [index=90, type=None, fullname="90& :"]; -"92& create_command_restrictions" [type=boolean, index=92, fullname="92& create_command_restrictions"]; -"93& create" [index=93, type=None, fullname="93& create"]; -"94& allowed_create_resources" [index=94, type=set, fullname="94& allowed_create_resources"]; -"95& creates_privileged_resources" [index=95, type=boolean, fullname="95& creates_privileged_resources"]; -"96& privileged=true" [index=96, type=None, fullname="96& privileged=true"]; -"97& hostNetwork=true" [index=97, type=None, fullname="97& hostNetwork=true"]; -"98& hostPID=true" [index=98, type=None, fullname="98& hostPID=true"]; -"99& delete_allowed" [type=boolean, index=99, fullname="99& delete_allowed"]; -"100& safe_delete_resources" [index=100, type=set, fullname="100& safe_delete_resources"]; -"101& has_dangerous_delete_flags" [index=101, type=boolean, fullname="101& has_dangerous_delete_flags"]; -"102& deletes_all_resources" [index=102, type=boolean, fullname="102& deletes_all_resources"]; -"103& modification_allowed" [type=boolean, index=103, fullname="103& modification_allowed"]; -"104& apply.patch" [index=104, type=None, fullname="104& apply.patch"]; -"105& modifiable_resources" [index=105, type=set, fullname="105& modifiable_resources"]; -"106& modifies_security_context" [index=106, type=boolean, fullname="106& modifies_security_context"]; -"107& securityContext" [index=107, type=None, fullname="107& securityContext"]; -"108& requires_dry_run" [type=boolean, index=108, fullname="108& requires_dry_run"]; -"109& apply.create.delete.patch" [index=109, type=None, fullname="109& apply.create.delete.patch"]; -"110& has_dry_run_flag" [index=110, type=boolean, fullname="110& has_dry_run_flag"]; -"111& --dry-run=client" [index=111, type=None, fullname="111& --dry-run=client"]; -"112& --dry-run=server" [index=112, type=None, fullname="112& --dry-run=server"]; -"114& command_classification" [type=string, index=114, fullname="114& command_classification"]; -"113& audit_decision" [type=object, index=113, fullname="113& audit_decision"]; -"115& input.command" [type=ref, index=113, fullname="115& input.command"]; -"116& decision_reasoning" [type=string, index=116, fullname="116& decision_reasoning"]; -"117& risk_assessment" [type=string, index=117, fullname="117& risk_assessment"]; -"118& policy_violations" [type=var, index=118, fullname="118& policy_violations"]; -"119& resource_violations" [type=array, index=119, fullname="119& resource_violations"]; -"120& flag_violations" [type=array, index=120, fullname="120& flag_violations"]; -"121& command_structure_violations" [type=array, index=121, fullname="121& command_structure_violations"]; -"123& test_safe_get_pods" [type=boolean, index=123, fullname="123& test_safe_get_pods"]; -"124& test_forbidden_delete_namespace" [type=boolean, index=124, fullname="124& test_forbidden_delete_namespace"]; -"125& test_restricted_exec" [type=boolean, index=125, fullname="125& test_restricted_exec"]; -"126& test_dangerous_flags" [type=boolean, index=126, fullname="126& test_dangerous_flags"]; -"127& test_forbidden_namespace" [type=boolean, index=127, fullname="127& test_forbidden_namespace"]; -"128& test_rbac_modification" [type=boolean, index=128, fullname="128& test_rbac_modification"]; -"0& allow" -> "2& is_safe_operation" [key=0, type=var, label="['116.0', '0.1']", negative=False]; -"0& allow" -> "7& requires_approval" [key=0, type=var, label=0.2, negative=False]; -"0& allow" -> "113& audit_decision" [key=0, type=assign, label=113, negative=False]; -"2& is_safe_operation" -> "3& is_forbidden_operation" [key=0, type=var, label=0.1, negative=True]; -"2& is_safe_operation" -> "11& input.command.verb" [key=0, type=var, label="['2.1', '2.0']", negative=False]; -"3& is_forbidden_operation" -> "4& passes_resource_restrictions" [key=0, type=var, label=0.1, negative=False]; -"3& is_forbidden_operation" -> "9& passes_namespace_restrictions" [key=0, type=var, label=7.0, negative=False]; -"3& is_forbidden_operation" -> "11& input.command.verb" [key=0, type=var, label="['3.2', '3.0']", negative=False]; -"3& is_forbidden_operation" -> "18& resource_type" [key=0, type=var, label=3.1, negative=False]; -"3& is_forbidden_operation" -> "32& targets_rbac_resources" [key=0, type=var, label=3.3, negative=False]; -"3& is_forbidden_operation" -> "33& targets_security_resources" [key=0, type=var, label=3.4, negative=False]; -"3& is_forbidden_operation" -> "34& targets_system_resources" [key=0, type=var, label=3.5, negative=False]; -"4& passes_resource_restrictions" -> "5& has_dangerous_flags" [key=0, type=var, label="['7.0', '0.1']", negative=True]; -"4& passes_resource_restrictions" -> "17& resource_types" [key=0, type=var, label=4.0, negative=False]; -"4& passes_resource_restrictions" -> "15& input.command.resource" [key=0, type=var, label=4.1, negative=False]; -"4& passes_resource_restrictions" -> "18& resource_type" [key=0, type=var, label="['4.2', '4.3']", negative=False]; -"5& has_dangerous_flags" -> "6& is_valid_command_structure" [key=0, type=var, label="['7.0', '0.1']", negative=False]; -"5& has_dangerous_flags" -> "48& --force" [key=0, type=var, label=5.0, negative=False]; -"5& has_dangerous_flags" -> "50& --grace-period=0" [key=0, type=var, label=5.1, negative=False]; -"5& has_dangerous_flags" -> "51& --all" [key=0, type=var, label=5.2, negative=False]; -"5& has_dangerous_flags" -> "52& --cascade=orphan" [key=0, type=var, label=5.3, negative=False]; -"5& has_dangerous_flags" -> "53& flag" [key=0, type=var, label="['5.5', '5.7', '5.6', '5.4', '5.8']", negative=False]; -"6& is_valid_command_structure" -> "11& input.command.verb" [key=0, type=var, label=6.0, negative=False]; -"7& requires_approval" -> "8& is_restricted_operation" [key=0, type=var, label=7.0, negative=False]; -"7& requires_approval" -> "113& audit_decision" [key=0, type=assign, label=113, negative=False]; -"8& is_restricted_operation" -> "3& is_forbidden_operation" [key=0, type=var, label=7.0, negative=True]; -"8& is_restricted_operation" -> "11& input.command.verb" [key=0, type=var, label=8.0, negative=False]; -"9& passes_namespace_restrictions" -> "4& passes_resource_restrictions" [key=0, type=var, label=7.0, negative=False]; -"9& passes_namespace_restrictions" -> "39& input.command.namespace" [key=0, type=var, label=9.0, negative=False]; -"9& passes_namespace_restrictions" -> "42& namespace" [key=0, type=var, label=9.1, negative=False]; -"10& deny" -> "113& audit_decision" [key=0, type=assign, label=113, negative=False]; -"10& deny" -> "3& is_forbidden_operation" [key=0, type=var, label=116.2, negative=False]; -"10& deny" -> "5& has_dangerous_flags" [key=0, type=var, label=116.3, negative=False]; -"11& input.command.verb" -> "12& safe_verbs" [key=0, type="['r', 'e', 'l', '_', 'n', 't', 'i', 'b', 'a', '.', 'm', '2']", label=2.0, negative=False]; -"11& input.command.verb" -> "14& resource_less_safe_verbs" [key=0, type="['r', 'e', 'l', '_', 'n', 't', 'i', 'b', 'a', '.', 'm', '2']", label="['4.1', '2.1']", negative=False]; -"11& input.command.verb" -> "20& describe.get.list.logs" [key=0, type="['r', 'e', 'l', '_', 'n', 't', 'i', 'b', 'a', '.', 'm', '2']", label=13.1, negative=False]; -"11& input.command.verb" -> "26& restricted_verbs" [key=0, type="['r', 'e', 'l', '_', 'n', 't', 'i', 'b', 'a', '.', 'm', '2']", label=8.0, negative=False]; -"11& input.command.verb" -> "29& forbidden_verbs" [key=0, type="['r', 'e', 'l', '_', 'n', 't', 'i', 'b', 'a', '.', 'm', '2']", label=3.0, negative=False]; -"11& input.command.verb" -> "30& delete" [key=0, type="['e', 'l', 'u', 'q', 'a']", label="['5.3', '5.2', '117.4', '3.2', '101.0', '101.1', '99.0', '102.0']", negative=False]; -"11& input.command.verb" -> "36& apply.create.delete.edit.patch.replace" [key=0, type="['r', 'e', 'l', '_', 'n', 't', 'i', 'b', 'a', '.', 'm', '2']", label="['34.0', '32.0']", negative=False]; -"11& input.command.verb" -> "40& describe.get.list" [key=0, type="['r', 'e', 'l', '_', 'n', 't', 'i', 'b', 'a', '.', 'm', '2']", label="['4.3', '4.2', '9.0']", negative=False]; -"11& input.command.verb" -> "24& Null string" [key=0, type="['q', 'n', 'e']", label=6.0, negative=False]; -"11& input.command.verb" -> "63& apply.attach.cp.debug.exec.logs.port-forward" [key=0, type="['r', 'e', 'l', '_', 'n', 't', 'i', 'b', 'a', '.', 'm', '2']", label=59.1, negative=False]; -"11& input.command.verb" -> "81& exec" [key=0, type="['e', 'l', 'u', 'n', 'q', 'a']", label="['80.0', '83.1', '83.0']", negative=False]; -"11& input.command.verb" -> "88& port-forward" [key=0, type="['e', 'l', 'u', 'n', 'q', 'a']", label="['87.1', '87.0']", negative=False]; -"11& input.command.verb" -> "93& create" [key=0, type="['e', 'l', 'u', 'n', 'q', 'a']", label="['92.1', '92.0', '95.1', '95.0', '95.2']", negative=False]; -"11& input.command.verb" -> "104& apply.patch" [key=0, type="['r', 'e', 'l', '_', 'n', 't', 'i', 'b', 'a', '.', 'm', '2']", label="['103.0', '106.0']", negative=False]; -"11& input.command.verb" -> "109& apply.create.delete.patch" [key=0, type="['r', 'e', 'l', '_', 'n', 't', 'i', 'b', 'a', '.', 'm', '2']", label=108.0, negative=False]; -"12& safe_verbs" -> "13& all_resources_are_safe" [key=0, type=var, label=2.0, negative=False]; -"13& all_resources_are_safe" -> "17& resource_types" [key=0, type=var, label=13.0, negative=False]; -"13& all_resources_are_safe" -> "11& input.command.verb" [key=0, type=var, label=13.1, negative=False]; -"14& resource_less_safe_verbs" -> "15& input.command.resource" [key=0, type=var, label=2.1, negative=False]; -"15& input.command.resource" -> "16& null" [key=0, type="['e', 'l', 'u', 'n', 'q', 'a']", label="['4.1', '59.1', '2.1', '60.6']", negative=False]; -"15& input.command.resource" -> "35& clusterrole.clusterrolebinding.clusterrolebindings.clusterroles.role.rolebinding.rolebindings.roles.serviceaccount.serviceaccounts" [key=0, type="['r', 'e', 'l', '_', 'n', 't', 'i', 'b', 'a', '.', 'm', '2']", label=32.0, negative=False]; -"15& input.command.resource" -> "37& networkpolicies.poddisruptionbudgets.podsecuritypolicies.securitycontextconstraints" [key=0, type="['r', 'e', 'l', '_', 'n', 't', 'i', 'b', 'a', '.', 'm', '2']", label=33.0, negative=False]; -"15& input.command.resource" -> "38& componentstatuse.componentstatuses.csidriver.csidrivers.csinode.csinodes.node.nodes.volumeattachment.volumeattachments" [key=0, type="['r', 'e', 'l', '_', 'n', 't', 'i', 'b', 'a', '.', 'm', '2']", label=34.0, negative=False]; -"15& input.command.resource" -> "41& cluster_scoped_safe_resources" [key=0, type="['r', 'e', 'l', '_', 'n', 't', 'i', 'b', 'a', '.', 'm', '2']", label=9.0, negative=False]; -"15& input.command.resource" -> "24& Null string" [key=0, type="['q', 'n', 'e']", label=59.0, negative=False]; -"15& input.command.resource" -> "70& $(" [key=0, type="['n', 't', 's', 'i', 'c', 'a', 'o']", label=60.6, negative=False]; -"15& input.command.resource" -> "94& allowed_create_resources" [key=0, type="['r', 'e', 'l', '_', 'n', 't', 'i', 'b', 'a', '.', 'm', '2']", label=92.1, negative=False]; -"15& input.command.resource" -> "100& safe_delete_resources" [key=0, type="['r', 'e', 'l', '_', 'n', 't', 'i', 'b', 'a', '.', 'm', '2']", label=99.0, negative=False]; -"15& input.command.resource" -> "105& modifiable_resources" [key=0, type="['r', 'e', 'l', '_', 'n', 't', 'i', 'b', 'a', '.', 'm', '2']", label=103.0, negative=False]; -"15& input.command.resource" -> "31& critical_resources" [key=0, type="['r', 'e', 'l', '_', 'n', 't', 'i', 'b', 'a', '.', 'm', '2']", label=117.4, negative=False]; -"15& input.command.resource" -> "21& forbidden_resources" [key=0, type="['r', 'e', 'l', '_', 'n', 't', 'i', 'b', 'a', '.', 'm', '2']", label=119.0, negative=False]; -"16& null" -> "17& resource_types" [key=0, type=var, label=22.0, negative=False]; -"16& null" -> "11& input.command.verb" [key=0, type=var, label="['4.1', '59.1']", negative=False]; -"16& null" -> "15& input.command.resource" [key=0, type=var, label=60.6, negative=False]; -"17& resource_types" -> "18& resource_type" [key=0, type=loop, label="['4.0', '27.0', '13.1', '13.0']"]; -"17& resource_types" -> "24& Null string" [key=0, type="['g', 's', 'n', 'i', 'a']", label=22.0, negative=False]; -"17& resource_types" -> "47& other_resource" [key=0, type=loop, label="['4.2', '4.3']"]; -"18& resource_type" -> "19& safe_resources" [key=0, type="['r', 'e', 'l', '_', 'n', 't', 'i', 'b', 'a', '.', 'm', '2']", label=13.0, negative=False]; -"18& resource_type" -> "21& forbidden_resources" [key=0, type="['r', 'e', 'l', '_', 'n', 't', 'i', 'b', 'a', '.', 'm', '2']", label="['3.1', '13.1']", negative=False]; -"18& resource_type" -> "28& allowed_resources_for_modification" [key=0, type="['r', 'e', 'l', '_', 'n', 't', 'i', 'b', 'a', '.', 'm', '2']", label=27.0, negative=False]; -"18& resource_type" -> "31& critical_resources" [key=0, type="['r', 'e', 'l', '_', 'n', 't', 'i', 'b', 'a', '.', 'm', '2']", label=3.2, negative=False]; -"18& resource_type" -> "45& allowed_resources" [key=0, type="['r', 'e', 'l', '_', 'n', 't', 'i', 'b', 'a', '.', 'm', '2']", label=4.0, negative=False]; -"18& resource_type" -> "46& secrets" [key=0, type="['e', 'l', 'u', 'q', 'a']", label="['4.2', '4.3']", negative=False]; -"20& describe.get.list.logs" -> "17& resource_types" [key=0, type=var, label=13.1, negative=False]; -"23& resource_string" -> "16& null" [key=0, type="['q', 'n', 'e']", label=22.0, negative=False]; -"24& Null string" -> "11& input.command.verb" [key=0, type=var, label=9.0, negative=False]; -"24& Null string" -> "42& namespace" [key=0, type=var, label=9.1, negative=False]; -"24& Null string" -> "59& resource_requirement_satisfied" [key=0, type=var, label=6.0, negative=False]; -"26& restricted_verbs" -> "27& all_resources_modifiable" [key=0, type=var, label=8.0, negative=False]; -"27& all_resources_modifiable" -> "3& is_forbidden_operation" [key=0, type=var, label=8.0, negative=True]; -"27& all_resources_modifiable" -> "17& resource_types" [key=0, type=var, label=27.0, negative=False]; -"30& delete" -> "18& resource_type" [key=0, type=var, label=3.2, negative=False]; -"30& delete" -> "15& input.command.resource" [key=0, type=var, label="['99.0', '117.4']", negative=False]; -"30& delete" -> "51& --all" [key=0, type=var, label=101.0, negative=False]; -"30& delete" -> "48& --force" [key=0, type=var, label=101.1, negative=False]; -"30& delete" -> "64& arg" [key=0, type=var, label=102.0, negative=False]; -"32& targets_rbac_resources" -> "15& input.command.resource" [key=0, type=var, label=32.0, negative=False]; -"33& targets_security_resources" -> "15& input.command.resource" [key=0, type=var, label=33.0, negative=False]; -"34& targets_system_resources" -> "15& input.command.resource" [key=0, type=var, label=34.0, negative=False]; -"35& clusterrole.clusterrolebinding.clusterrolebindings.clusterroles.role.rolebinding.rolebindings.roles.serviceaccount.serviceaccounts" -> "11& input.command.verb" [key=0, type=var, label=32.0, negative=False]; -"38& componentstatuse.componentstatuses.csidriver.csidrivers.csinode.csinodes.node.nodes.volumeattachment.volumeattachments" -> "11& input.command.verb" [key=0, type=var, label=34.0, negative=False]; -"39& input.command.namespace" -> "24& Null string" [key=0, type="['e', 'l', 'u', 'q', 'a']", label=9.0, negative=False]; -"39& input.command.namespace" -> "42& namespace" [key=0, type=var, label=9.1, negative=False]; -"40& describe.get.list" -> "15& input.command.resource" [key=0, type=var, label=9.0, negative=False]; -"40& describe.get.list" -> "17& resource_types" [key=0, type=var, label="['4.2', '4.3']", negative=False]; -"42& namespace" -> "39& input.command.namespace" [key=0, type="['g', 's', 'n', 'i', 'a']", label=9.1, negative=False]; -"42& namespace" -> "24& Null string" [key=0, type="['q', 'n', 'e']", label=9.1, negative=False]; -"42& namespace" -> "43& allowed_namespaces" [key=0, type="['r', 'e', 'l', '_', 'n', 't', 'i', 'b', 'a', '.', 'm', '2']", label=9.1, negative=False]; -"42& namespace" -> "44& forbidden_namespaces" [key=0, type="['r', 'e', 'l', '_', 'n', 't', 'i', 'b', 'a', '.', 'm', '2']", label=9.1, negative=False]; -"43& allowed_namespaces" -> "42& namespace" [key=0, type=var, label=9.1, negative=True]; -"46& secrets" -> "11& input.command.verb" [key=0, type=var, label="['4.2', '4.3']", negative=False]; -"47& other_resource" -> "46& secrets" [key=0, type="['e', 'l', 'u', 'q', 'a']", label=4.2, negative=False]; -"47& other_resource" -> "45& allowed_resources" [key=0, type="['r', 'e', 'l', '_', 'n', 't', 'i', 'b', 'a', '.', 'm', '2']", label=4.3, negative=False]; -"48& --force" -> "49& input.command.flags" [key=0, type="['r', 'e', 'l', '_', 'n', 't', 'i', 'b', 'a', '.', 'm', '2']", label="['101.1', '5.0']", negative=False]; -"49& input.command.flags" -> "11& input.command.verb" [key=0, type=var, label="['5.3', '5.2']", negative=False]; -"50& --grace-period=0" -> "49& input.command.flags" [key=0, type="['r', 'e', 'l', '_', 'n', 't', 'i', 'b', 'a', '.', 'm', '2']", label=5.1, negative=False]; -"51& --all" -> "49& input.command.flags" [key=0, type="['r', 'e', 'l', '_', 'n', 't', 'i', 'b', 'a', '.', 'm', '2']", label="['101.0', '5.2']", negative=False]; -"52& --cascade=orphan" -> "49& input.command.flags" [key=0, type="['r', 'e', 'l', '_', 'n', 't', 'i', 'b', 'a', '.', 'm', '2']", label=5.3, negative=False]; -"53& flag" -> "54& --privileged=true" [key=0, type="['w', 'r', 's', 't', 'i', 'a', 'h']", label=5.4, negative=False]; -"53& flag" -> "55& --host" [key=0, type="['w', 'r', 's', 't', 'i', 'a', 'h']", label=5.5, negative=False]; -"53& flag" -> "56& --as=" [key=0, type="['w', 'r', 's', 't', 'i', 'a', 'h']", label=5.6, negative=False]; -"53& flag" -> "57& --as-group=" [key=0, type="['w', 'r', 's', 't', 'i', 'a', 'h']", label=5.7, negative=False]; -"53& flag" -> "58& sudo" [key=0, type="['n', 't', 's', 'i', 'c', 'a', 'o']", label=5.8, negative=False]; -"53& flag" -> "96& privileged=true" [key=0, type="['n', 't', 's', 'i', 'c', 'a', 'o']", label=95.0, negative=False]; -"53& flag" -> "97& hostNetwork=true" [key=0, type="['n', 't', 's', 'i', 'c', 'a', 'o']", label=95.1, negative=False]; -"53& flag" -> "98& hostPID=true" [key=0, type="['n', 't', 's', 'i', 'c', 'a', 'o']", label=95.2, negative=False]; -"53& flag" -> "107& securityContext" [key=0, type="['n', 't', 's', 'i', 'c', 'a', 'o']", label=106.0, negative=False]; -"59& resource_requirement_satisfied" -> "60& contains_injection_patterns" [key=0, type=var, label=6.0, negative=True]; -"59& resource_requirement_satisfied" -> "15& input.command.resource" [key=0, type=var, label="['59.0', '59.1']", negative=False]; -"60& contains_injection_patterns" -> "61& contains_shell_metacharacters" [key=0, type=var, label=6.0, negative=True]; -"60& contains_injection_patterns" -> "64& arg" [key=0, type=var, label="['60.4', '60.1', '60.3', '60.2', '60.5', '60.0']", negative=False]; -"60& contains_injection_patterns" -> "15& input.command.resource" [key=0, type=var, label=60.6, negative=False]; -"60& contains_injection_patterns" -> "71& flag.value" [key=0, type=var, label="['60.12', '60.9', '60.10', '60.8', '60.7', '60.11']", negative=False]; -"60& contains_injection_patterns" -> "72& input.original_command" [key=0, type=var, label=60.13, negative=False]; -"61& contains_shell_metacharacters" -> "62& valid_resource_names" [key=0, type=var, label=6.0, negative=False]; -"61& contains_shell_metacharacters" -> "73& [`${}><&]" [key=0, type=var, label=61.0, negative=False]; -"62& valid_resource_names" -> "74& input.command.args" [key=0, type=var, label=62.1, negative=False]; -"64& arg" -> "65& ;" [key=0, type="['n', 't', 's', 'i', 'c', 'a', 'o']", label=60.0, negative=False]; -"64& arg" -> "66& &&" [key=0, type="['n', 't', 's', 'i', 'c', 'a', 'o']", label=60.1, negative=False]; -"64& arg" -> "67& ||" [key=0, type="['n', 't', 's', 'i', 'c', 'a', 'o']", label=60.2, negative=False]; -"64& arg" -> "68& |" [key=0, type="['n', 't', 's', 'i', 'c', 'a', 'o']", label=60.3, negative=False]; -"64& arg" -> "69& `" [key=0, type="['n', 't', 's', 'i', 'c', 'a', 'o']", label=60.4, negative=False]; -"64& arg" -> "70& $(" [key=0, type="['n', 't', 's', 'i', 'c', 'a', 'o']", label=60.5, negative=False]; -"64& arg" -> "75& kube-+76& system" [key=0, type="['w', 'r', 's', 't', 'i', 'a', 'h']", label=62.1, negative=False]; -"64& arg" -> "77& is_valid_resource_name" [key=0, type="function_parameter", label=62.1, negative=False]; -"64& arg" -> "84& dangerous_exec_commands" [key=0, type="['r', 'e', 'l', '_', 'n', 't', 'i', 'b', 'a', '.', 'm', '2']", label=82.0, negative=False]; -"64& arg" -> "85& rm -rf" [key=0, type="['n', 't', 's', 'i', 'c', 'a', 'o']", label=82.1, negative=False]; -"64& arg" -> "86& dd if=" [key=0, type="['n', 't', 's', 'i', 'c', 'a', 'o']", label=82.2, negative=False]; -"64& arg" -> "90& " [key=0, type="['n', 't', 's', 'i', 'c', 'a', 'o']", label=89.0, negative=False]; -"64& arg" -> "51& --all" [key=0, type="['e', 'l', 'u', 'q', 'a']", label=102.0, negative=False]; -"71& flag.value" -> "70& $(" [key=0, type="['n', 't', 's', 'i', 'c', 'a', 'o']", label=60.7, negative=False]; -"71& flag.value" -> "69& `" [key=0, type="['n', 't', 's', 'i', 'c', 'a', 'o']", label=60.8, negative=False]; -"71& flag.value" -> "65& ;" [key=0, type="['n', 't', 's', 'i', 'c', 'a', 'o']", label=60.9, negative=False]; -"71& flag.value" -> "66& &&" [key=0, type="['n', 't', 's', 'i', 'c', 'a', 'o']", label=60.10, negative=False]; -"71& flag.value" -> "67& ||" [key=0, type="['n', 't', 's', 'i', 'c', 'a', 'o']", label=60.11, negative=False]; -"71& flag.value" -> "68& |" [key=0, type="['n', 't', 's', 'i', 'c', 'a', 'o']", label=60.12, negative=False]; -"72& input.original_command" -> "70& $(" [key=0, type="['n', 't', 's', 'i', 'c', 'a', 'o']", label=60.13, negative=False]; -"73& [`${}><&]" -> "64& arg" [key=0, type="['r', 'g', 'e', 'h', 't', 'x', 'c', 'a', '.', 'm']", label=61.0, negative=False]; -"74& input.command.args" -> "64& arg" [key=0, type=loop, label=62.1]; -"77& is_valid_resource_name" -> "78& ^[a-z0-9]([-a-z0-9]*[a-z0-9])?([.][a-z0-9]([-a-z0-9]*[a-z0-9])?)*$" [key=0, type=var, label=77.0, negative=False]; -"77& is_valid_resource_name" -> "79& ^[a-z0-9]([-a-z0-9]*[a-z0-9])?([.][a-z0-9]([-a-z0-9]*[a-z0-9])?)*([,][a-z0-9]([-a-z0-9]*[a-z0-9])?([.][a-z0-9]([-a-z0-9]*[a-z0-9])?)*)*$" [key=0, type=var, label=77.1, negative=False]; -"78& ^[a-z0-9]([-a-z0-9]*[a-z0-9])?([.][a-z0-9]([-a-z0-9]*[a-z0-9])?)*$" -> "64& arg" [key=0, type="['r', 'g', 'e', 'h', 't', 'x', 'c', 'a', '.', 'm']", label=77.0, negative=False]; -"79& ^[a-z0-9]([-a-z0-9]*[a-z0-9])?([.][a-z0-9]([-a-z0-9]*[a-z0-9])?)*([,][a-z0-9]([-a-z0-9]*[a-z0-9])?([.][a-z0-9]([-a-z0-9]*[a-z0-9])?)*)*$" -> "64& arg" [key=0, type="['r', 'g', 'e', 'h', 't', 'x', 'c', 'a', '.', 'm']", label=77.1, negative=False]; -"80& exec_command_restrictions" -> "11& input.command.verb" [key=0, type=var, label=80.0, negative=False]; -"81& exec" -> "82& contains_dangerous_exec_commands" [key=0, type=var, label="['80.0', '83.1']", negative=True]; -"82& contains_dangerous_exec_commands" -> "83& valid_exec_structure" [key=0, type=var, label=80.0, negative=False]; -"82& contains_dangerous_exec_commands" -> "64& arg" [key=0, type=var, label="['82.1', '82.2', '82.0']", negative=False]; -"83& valid_exec_structure" -> "11& input.command.verb" [key=0, type=var, label="['83.1', '83.0']", negative=False]; -"87& port_forward_restrictions" -> "11& input.command.verb" [key=0, type=var, label="['87.1', '87.0']", negative=False]; -"88& port-forward" -> "89& valid_port_specification" [key=0, type=var, label=87.1, negative=False]; -"89& valid_port_specification" -> "64& arg" [key=0, type=var, label=89.0, negative=False]; -"92& create_command_restrictions" -> "11& input.command.verb" [key=0, type=var, label="['92.0', '92.1']", negative=False]; -"93& create" -> "15& input.command.resource" [key=0, type=var, label=92.1, negative=False]; -"93& create" -> "53& flag" [key=0, type=var, label="['95.2', '95.1', '95.0']", negative=False]; -"94& allowed_create_resources" -> "95& creates_privileged_resources" [key=0, type=var, label=92.1, negative=True]; -"95& creates_privileged_resources" -> "11& input.command.verb" [key=0, type=var, label="['95.2', '95.1', '95.0']", negative=False]; -"99& delete_allowed" -> "11& input.command.verb" [key=0, type=var, label=99.0, negative=False]; -"100& safe_delete_resources" -> "101& has_dangerous_delete_flags" [key=0, type=var, label=99.0, negative=True]; -"101& has_dangerous_delete_flags" -> "102& deletes_all_resources" [key=0, type=var, label=99.0, negative=True]; -"101& has_dangerous_delete_flags" -> "11& input.command.verb" [key=0, type=var, label="['101.1', '101.0']", negative=False]; -"102& deletes_all_resources" -> "11& input.command.verb" [key=0, type=var, label=102.0, negative=False]; -"103& modification_allowed" -> "11& input.command.verb" [key=0, type=var, label=103.0, negative=False]; -"104& apply.patch" -> "15& input.command.resource" [key=0, type=var, label=103.0, negative=False]; -"104& apply.patch" -> "53& flag" [key=0, type=var, label=106.0, negative=False]; -"105& modifiable_resources" -> "106& modifies_security_context" [key=0, type=var, label=103.0, negative=True]; -"106& modifies_security_context" -> "11& input.command.verb" [key=0, type=var, label=106.0, negative=False]; -"108& requires_dry_run" -> "11& input.command.verb" [key=0, type=var, label=108.0, negative=False]; -"109& apply.create.delete.patch" -> "110& has_dry_run_flag" [key=0, type=var, label=108.0, negative=True]; -"110& has_dry_run_flag" -> "111& --dry-run=client" [key=0, type=var, label=110.0, negative=False]; -"110& has_dry_run_flag" -> "112& --dry-run=server" [key=0, type=var, label=110.1, negative=False]; -"111& --dry-run=client" -> "49& input.command.flags" [key=0, type="['r', 'e', 'l', '_', 'n', 't', 'i', 'b', 'a', '.', 'm', '2']", label=110.0, negative=False]; -"112& --dry-run=server" -> "49& input.command.flags" [key=0, type="['r', 'e', 'l', '_', 'n', 't', 'i', 'b', 'a', '.', 'm', '2']", label=110.1, negative=False]; -"114& command_classification" -> "2& is_safe_operation" [key=0, type=var, label=114.0, negative=False]; -"114& command_classification" -> "8& is_restricted_operation" [key=0, type=var, label=114.1, negative=False]; -"114& command_classification" -> "3& is_forbidden_operation" [key=0, type=var, label=114.2, negative=False]; -"113& audit_decision" -> "114& command_classification" [key=0, type=assign, label=113, negative=False]; -"113& audit_decision" -> "115& input.command" [key=0, type=assign, label=113, negative=False]; -"113& audit_decision" -> "116& decision_reasoning" [key=0, type=assign, label=113, negative=False]; -"113& audit_decision" -> "117& risk_assessment" [key=0, type=assign, label=113, negative=False]; -"113& audit_decision" -> "118& policy_violations" [key=0, type=assign, label=113, negative=False]; -"116& decision_reasoning" -> "0& allow" [key=0, type=var, label=116.0, negative=False]; -"116& decision_reasoning" -> "7& requires_approval" [key=0, type=var, label=116.1, negative=False]; -"116& decision_reasoning" -> "10& deny" [key=0, type=var, label="['116.2', '116.3']", negative=False]; -"117& risk_assessment" -> "2& is_safe_operation" [key=0, type=var, label=117.0, negative=False]; -"117& risk_assessment" -> "8& is_restricted_operation" [key=0, type=var, label=117.1, negative=False]; -"117& risk_assessment" -> "3& is_forbidden_operation" [key=0, type=var, label=117.2, negative=False]; -"117& risk_assessment" -> "32& targets_rbac_resources" [key=0, type=var, label=117.3, negative=False]; -"117& risk_assessment" -> "11& input.command.verb" [key=0, type=var, label=117.4, negative=False]; -"119& resource_violations" -> "15& input.command.resource" [key=0, type=var, label=119.0, negative=False]; -"120& flag_violations" -> "5& has_dangerous_flags" [key=0, type=var, label=120.0, negative=False]; -"121& command_structure_violations" -> "6& is_valid_command_structure" [key=0, type=var, label=121.0, negative=True]; -"123& test_safe_get_pods" -> "0& allow" [key=0, type=var, label=123.0, negative=False]; -"124& test_forbidden_delete_namespace" -> "10& deny" [key=0, type=var, label=124.0, negative=False]; -"125& test_restricted_exec" -> "7& requires_approval" [key=0, type=var, label=125.0, negative=False]; -"126& test_dangerous_flags" -> "10& deny" [key=0, type=var, label=126.0, negative=False]; -"127& test_forbidden_namespace" -> "10& deny" [key=0, type=var, label=127.0, negative=False]; -"128& test_rbac_modification" -> "10& deny" [key=0, type=var, label=128.0, negative=False]; -} diff --git a/scripts/visualization/graph.html b/scripts/visualization/graph.html deleted file mode 100644 index 7c39bbf..0000000 --- a/scripts/visualization/graph.html +++ /dev/null @@ -1,170 +0,0 @@ - - - - - Index-based Graph Viewer - - - - - - - - -
- - - -
- -
- - - - - \ No newline at end of file diff --git a/scripts/visualization/graph.json b/scripts/visualization/graph.json deleted file mode 100644 index 49cd74e..0000000 --- a/scripts/visualization/graph.json +++ /dev/null @@ -1,2424 +0,0 @@ -{ - "nodes": [ - { - "data": { - "id": "\"0& allow\"", - "index": "0" - } - }, - { - "data": { - "id": "\"2& is_safe_operation\"", - "index": "2" - } - }, - { - "data": { - "id": "\"3& is_forbidden_operation\"", - "index": "3" - } - }, - { - "data": { - "id": "\"4& passes_resource_restrictions\"", - "index": "4" - } - }, - { - "data": { - "id": "\"5& has_dangerous_flags\"", - "index": "5" - } - }, - { - "data": { - "id": "\"6& is_valid_command_structure\"", - "index": "6" - } - }, - { - "data": { - "id": "\"7& requires_approval\"", - "index": "7" - } - }, - { - "data": { - "id": "\"8& is_restricted_operation\"", - "index": "8" - } - }, - { - "data": { - "id": "\"9& passes_namespace_restrictions\"", - "index": "9" - } - }, - { - "data": { - "id": "\"10& deny\"", - "index": "10" - } - }, - { - "data": { - "id": "\"11& input.command.verb\"", - "index": "11" - } - }, - { - "data": { - "id": "\"12& safe_verbs\"", - "index": "12" - } - }, - { - "data": { - "id": "\"13& all_resources_are_safe\"", - "index": "13" - } - }, - { - "data": { - "id": "\"14& resource_less_safe_verbs\"", - "index": "14" - } - }, - { - "data": { - "id": "\"15& input.command.resource\"", - "index": "15" - } - }, - { - "data": { - "id": "\"16& null\"", - "index": "16" - } - }, - { - "data": { - "id": "\"17& resource_types\"", - "index": "17" - } - }, - { - "data": { - "id": "\"18& resource_type\"", - "index": "18" - } - }, - { - "data": { - "id": "\"19& safe_resources\"", - "index": "19" - } - }, - { - "data": { - "id": "\"20& describe.get.list.logs\"", - "index": "20" - } - }, - { - "data": { - "id": "\"21& forbidden_resources\"", - "index": "21" - } - }, - { - "data": { - "id": "\"23& resource_string\"", - "index": "23" - } - }, - { - "data": { - "id": "\"24& Null string\"", - "index": "24" - } - }, - { - "data": { - "id": "\"26& restricted_verbs\"", - "index": "26" - } - }, - { - "data": { - "id": "\"27& all_resources_modifiable\"", - "index": "27" - } - }, - { - "data": { - "id": "\"28& allowed_resources_for_modification\"", - "index": "28" - } - }, - { - "data": { - "id": "\"29& forbidden_verbs\"", - "index": "29" - } - }, - { - "data": { - "id": "\"30& delete\"", - "index": "30" - } - }, - { - "data": { - "id": "\"31& critical_resources\"", - "index": "31" - } - }, - { - "data": { - "id": "\"32& targets_rbac_resources\"", - "index": "32" - } - }, - { - "data": { - "id": "\"33& targets_security_resources\"", - "index": "33" - } - }, - { - "data": { - "id": "\"34& targets_system_resources\"", - "index": "34" - } - }, - { - "data": { - "id": "\"35& clusterrole.clusterrolebinding.clusterrolebindings.clusterroles.role.rolebinding.rolebindings.roles.serviceaccount.serviceaccounts\"", - "index": "35" - } - }, - { - "data": { - "id": "\"36& apply.create.delete.edit.patch.replace\"", - "index": "36" - } - }, - { - "data": { - "id": "\"37& networkpolicies.poddisruptionbudgets.podsecuritypolicies.securitycontextconstraints\"", - "index": "37" - } - }, - { - "data": { - "id": "\"38& componentstatuse.componentstatuses.csidriver.csidrivers.csinode.csinodes.node.nodes.volumeattachment.volumeattachments\"", - "index": "38" - } - }, - { - "data": { - "id": "\"39& input.command.namespace\"", - "index": "39" - } - }, - { - "data": { - "id": "\"40& describe.get.list\"", - "index": "40" - } - }, - { - "data": { - "id": "\"41& cluster_scoped_safe_resources\"", - "index": "41" - } - }, - { - "data": { - "id": "\"42& namespace\"", - "index": "42" - } - }, - { - "data": { - "id": "\"43& allowed_namespaces\"", - "index": "43" - } - }, - { - "data": { - "id": "\"44& forbidden_namespaces\"", - "index": "44" - } - }, - { - "data": { - "id": "\"45& allowed_resources\"", - "index": "45" - } - }, - { - "data": { - "id": "\"46& secrets\"", - "index": "46" - } - }, - { - "data": { - "id": "\"47& other_resource\"", - "index": "47" - } - }, - { - "data": { - "id": "\"48& --force\"", - "index": "48" - } - }, - { - "data": { - "id": "\"49& input.command.flags\"", - "index": "49" - } - }, - { - "data": { - "id": "\"50& --grace-period=0\"", - "index": "50" - } - }, - { - "data": { - "id": "\"51& --all\"", - "index": "51" - } - }, - { - "data": { - "id": "\"52& --cascade=orphan\"", - "index": "52" - } - }, - { - "data": { - "id": "\"53& flag\"", - "index": "53" - } - }, - { - "data": { - "id": "\"54& --privileged=true\"", - "index": "54" - } - }, - { - "data": { - "id": "\"55& --host\"", - "index": "55" - } - }, - { - "data": { - "id": "\"56& --as=\"", - "index": "56" - } - }, - { - "data": { - "id": "\"57& --as-group=\"", - "index": "57" - } - }, - { - "data": { - "id": "\"58& sudo\"", - "index": "58" - } - }, - { - "data": { - "id": "\"59& resource_requirement_satisfied\"", - "index": "59" - } - }, - { - "data": { - "id": "\"60& contains_injection_patterns\"", - "index": "60" - } - }, - { - "data": { - "id": "\"61& contains_shell_metacharacters\"", - "index": "61" - } - }, - { - "data": { - "id": "\"62& valid_resource_names\"", - "index": "62" - } - }, - { - "data": { - "id": "\"63& apply.attach.cp.debug.exec.logs.port-forward\"", - "index": "63" - } - }, - { - "data": { - "id": "\"64& arg\"", - "index": "64" - } - }, - { - "data": { - "id": "\"65& ;\"", - "index": "65" - } - }, - { - "data": { - "id": "\"66& &&\"", - "index": "66" - } - }, - { - "data": { - "id": "\"67& ||\"", - "index": "67" - } - }, - { - "data": { - "id": "\"68& |\"", - "index": "68" - } - }, - { - "data": { - "id": "\"69& `\"", - "index": "69" - } - }, - { - "data": { - "id": "\"70& $(\"", - "index": "70" - } - }, - { - "data": { - "id": "\"71& flag.value\"", - "index": "71" - } - }, - { - "data": { - "id": "\"72& input.original_command\"", - "index": "72" - } - }, - { - "data": { - "id": "\"73& [`${}><&]\"", - "index": "73" - } - }, - { - "data": { - "id": "\"74& input.command.args\"", - "index": "74" - } - }, - { - "data": { - "id": "\"75& kube-+76& system:\"", - "index": "75" - } - }, - { - "data": { - "id": "\"77& is_valid_resource_name\"", - "index": "77" - } - }, - { - "data": { - "id": "\"78& ^[a-z0-9]([-a-z0-9]*[a-z0-9])?([.][a-z0-9]([-a-z0-9]*[a-z0-9])?)*$\"", - "index": "78" - } - }, - { - "data": { - "id": "\"79& ^[a-z0-9]([-a-z0-9]*[a-z0-9])?([.][a-z0-9]([-a-z0-9]*[a-z0-9])?)*([,][a-z0-9]([-a-z0-9]*[a-z0-9])?([.][a-z0-9]([-a-z0-9]*[a-z0-9])?)*)*$\"", - "index": "79" - } - }, - { - "data": { - "id": "\"80& exec_command_restrictions\"", - "index": "80" - } - }, - { - "data": { - "id": "\"81& exec\"", - "index": "81" - } - }, - { - "data": { - "id": "\"82& contains_dangerous_exec_commands\"", - "index": "82" - } - }, - { - "data": { - "id": "\"83& valid_exec_structure\"", - "index": "83" - } - }, - { - "data": { - "id": "\"84& dangerous_exec_commands\"", - "index": "84" - } - }, - { - "data": { - "id": "\"85& rm -rf\"", - "index": "85" - } - }, - { - "data": { - "id": "\"86& dd if=\"", - "index": "86" - } - }, - { - "data": { - "id": "\"87& port_forward_restrictions\"", - "index": "87" - } - }, - { - "data": { - "id": "\"88& port-forward\"", - "index": "88" - } - }, - { - "data": { - "id": "\"89& valid_port_specification\"", - "index": "89" - } - }, - { - "data": { - "id": "\"90& :\"", - "index": "90" - } - }, - { - "data": { - "id": "\"92& create_command_restrictions\"", - "index": "92" - } - }, - { - "data": { - "id": "\"93& create\"", - "index": "93" - } - }, - { - "data": { - "id": "\"94& allowed_create_resources\"", - "index": "94" - } - }, - { - "data": { - "id": "\"95& creates_privileged_resources\"", - "index": "95" - } - }, - { - "data": { - "id": "\"96& privileged=true\"", - "index": "96" - } - }, - { - "data": { - "id": "\"97& hostNetwork=true\"", - "index": "97" - } - }, - { - "data": { - "id": "\"98& hostPID=true\"", - "index": "98" - } - }, - { - "data": { - "id": "\"99& delete_allowed\"", - "index": "99" - } - }, - { - "data": { - "id": "\"100& safe_delete_resources\"", - "index": "100" - } - }, - { - "data": { - "id": "\"101& has_dangerous_delete_flags\"", - "index": "101" - } - }, - { - "data": { - "id": "\"102& deletes_all_resources\"", - "index": "102" - } - }, - { - "data": { - "id": "\"103& modification_allowed\"", - "index": "103" - } - }, - { - "data": { - "id": "\"104& apply.patch\"", - "index": "104" - } - }, - { - "data": { - "id": "\"105& modifiable_resources\"", - "index": "105" - } - }, - { - "data": { - "id": "\"106& modifies_security_context\"", - "index": "106" - } - }, - { - "data": { - "id": "\"107& securityContext\"", - "index": "107" - } - }, - { - "data": { - "id": "\"108& requires_dry_run\"", - "index": "108" - } - }, - { - "data": { - "id": "\"109& apply.create.delete.patch\"", - "index": "109" - } - }, - { - "data": { - "id": "\"110& has_dry_run_flag\"", - "index": "110" - } - }, - { - "data": { - "id": "\"111& --dry-run=client\"", - "index": "111" - } - }, - { - "data": { - "id": "\"112& --dry-run=server\"", - "index": "112" - } - }, - { - "data": { - "id": "\"114& command_classification\"", - "index": "114" - } - }, - { - "data": { - "id": "\"113& audit_decision\"", - "index": "113" - } - }, - { - "data": { - "id": "\"115& input.command\"", - "index": "113" - } - }, - { - "data": { - "id": "\"116& decision_reasoning\"", - "index": "116" - } - }, - { - "data": { - "id": "\"117& risk_assessment\"", - "index": "117" - } - }, - { - "data": { - "id": "\"118& policy_violations\"", - "index": "118" - } - }, - { - "data": { - "id": "\"119& resource_violations\"", - "index": "119" - } - }, - { - "data": { - "id": "\"120& flag_violations\"", - "index": "120" - } - }, - { - "data": { - "id": "\"121& command_structure_violations\"", - "index": "121" - } - }, - { - "data": { - "id": "\"123& test_safe_get_pods\"", - "index": "123" - } - }, - { - "data": { - "id": "\"124& test_forbidden_delete_namespace\"", - "index": "124" - } - }, - { - "data": { - "id": "\"125& test_restricted_exec\"", - "index": "125" - } - }, - { - "data": { - "id": "\"126& test_dangerous_flags\"", - "index": "126" - } - }, - { - "data": { - "id": "\"127& test_forbidden_namespace\"", - "index": "127" - } - }, - { - "data": { - "id": "\"128& test_rbac_modification\"", - "index": "128" - } - } - ], - "edges": [ - { - "data": { - "id": "\"0& allow\"_\"2& is_safe_operation\"", - "source": "\"0& allow\"", - "target": "\"2& is_safe_operation\"", - "index": "116.0, 0.1" - } - }, - { - "data": { - "id": "\"0& allow\"_\"7& requires_approval\"", - "source": "\"0& allow\"", - "target": "\"7& requires_approval\"", - "index": "0.2" - } - }, - { - "data": { - "id": "\"0& allow\"_\"113& audit_decision\"", - "source": "\"0& allow\"", - "target": "\"113& audit_decision\"", - "index": "113" - } - }, - { - "data": { - "id": "\"2& is_safe_operation\"_\"3& is_forbidden_operation\"", - "source": "\"2& is_safe_operation\"", - "target": "\"3& is_forbidden_operation\"", - "index": "0.1" - } - }, - { - "data": { - "id": "\"2& is_safe_operation\"_\"11& input.command.verb\"", - "source": "\"2& is_safe_operation\"", - "target": "\"11& input.command.verb\"", - "index": "2.1, 2.0" - } - }, - { - "data": { - "id": "\"3& is_forbidden_operation\"_\"4& passes_resource_restrictions\"", - "source": "\"3& is_forbidden_operation\"", - "target": "\"4& passes_resource_restrictions\"", - "index": "0.1" - } - }, - { - "data": { - "id": "\"3& is_forbidden_operation\"_\"9& passes_namespace_restrictions\"", - "source": "\"3& is_forbidden_operation\"", - "target": "\"9& passes_namespace_restrictions\"", - "index": "7.0" - } - }, - { - "data": { - "id": "\"3& is_forbidden_operation\"_\"11& input.command.verb\"", - "source": "\"3& is_forbidden_operation\"", - "target": "\"11& input.command.verb\"", - "index": "3.2, 3.0" - } - }, - { - "data": { - "id": "\"3& is_forbidden_operation\"_\"18& resource_type\"", - "source": "\"3& is_forbidden_operation\"", - "target": "\"18& resource_type\"", - "index": "3.1" - } - }, - { - "data": { - "id": "\"3& is_forbidden_operation\"_\"32& targets_rbac_resources\"", - "source": "\"3& is_forbidden_operation\"", - "target": "\"32& targets_rbac_resources\"", - "index": "3.3" - } - }, - { - "data": { - "id": "\"3& is_forbidden_operation\"_\"33& targets_security_resources\"", - "source": "\"3& is_forbidden_operation\"", - "target": "\"33& targets_security_resources\"", - "index": "3.4" - } - }, - { - "data": { - "id": "\"3& is_forbidden_operation\"_\"34& targets_system_resources\"", - "source": "\"3& is_forbidden_operation\"", - "target": "\"34& targets_system_resources\"", - "index": "3.5" - } - }, - { - "data": { - "id": "\"4& passes_resource_restrictions\"_\"5& has_dangerous_flags\"", - "source": "\"4& passes_resource_restrictions\"", - "target": "\"5& has_dangerous_flags\"", - "index": "7.0, 0.1" - } - }, - { - "data": { - "id": "\"4& passes_resource_restrictions\"_\"17& resource_types\"", - "source": "\"4& passes_resource_restrictions\"", - "target": "\"17& resource_types\"", - "index": "4.0" - } - }, - { - "data": { - "id": "\"4& passes_resource_restrictions\"_\"15& input.command.resource\"", - "source": "\"4& passes_resource_restrictions\"", - "target": "\"15& input.command.resource\"", - "index": "4.1" - } - }, - { - "data": { - "id": "\"4& passes_resource_restrictions\"_\"18& resource_type\"", - "source": "\"4& passes_resource_restrictions\"", - "target": "\"18& resource_type\"", - "index": "4.2, 4.3" - } - }, - { - "data": { - "id": "\"5& has_dangerous_flags\"_\"6& is_valid_command_structure\"", - "source": "\"5& has_dangerous_flags\"", - "target": "\"6& is_valid_command_structure\"", - "index": "7.0, 0.1" - } - }, - { - "data": { - "id": "\"5& has_dangerous_flags\"_\"48& --force\"", - "source": "\"5& has_dangerous_flags\"", - "target": "\"48& --force\"", - "index": "5.0" - } - }, - { - "data": { - "id": "\"5& has_dangerous_flags\"_\"50& --grace-period=0\"", - "source": "\"5& has_dangerous_flags\"", - "target": "\"50& --grace-period=0\"", - "index": "5.1" - } - }, - { - "data": { - "id": "\"5& has_dangerous_flags\"_\"51& --all\"", - "source": "\"5& has_dangerous_flags\"", - "target": "\"51& --all\"", - "index": "5.2" - } - }, - { - "data": { - "id": "\"5& has_dangerous_flags\"_\"52& --cascade=orphan\"", - "source": "\"5& has_dangerous_flags\"", - "target": "\"52& --cascade=orphan\"", - "index": "5.3" - } - }, - { - "data": { - "id": "\"5& has_dangerous_flags\"_\"53& flag\"", - "source": "\"5& has_dangerous_flags\"", - "target": "\"53& flag\"", - "index": "5.5, 5.7, 5.6, 5.4, 5.8" - } - }, - { - "data": { - "id": "\"6& is_valid_command_structure\"_\"11& input.command.verb\"", - "source": "\"6& is_valid_command_structure\"", - "target": "\"11& input.command.verb\"", - "index": "6.0" - } - }, - { - "data": { - "id": "\"7& requires_approval\"_\"8& is_restricted_operation\"", - "source": "\"7& requires_approval\"", - "target": "\"8& is_restricted_operation\"", - "index": "7.0" - } - }, - { - "data": { - "id": "\"7& requires_approval\"_\"113& audit_decision\"", - "source": "\"7& requires_approval\"", - "target": "\"113& audit_decision\"", - "index": "113" - } - }, - { - "data": { - "id": "\"8& is_restricted_operation\"_\"3& is_forbidden_operation\"", - "source": "\"8& is_restricted_operation\"", - "target": "\"3& is_forbidden_operation\"", - "index": "7.0" - } - }, - { - "data": { - "id": "\"8& is_restricted_operation\"_\"11& input.command.verb\"", - "source": "\"8& is_restricted_operation\"", - "target": "\"11& input.command.verb\"", - "index": "8.0" - } - }, - { - "data": { - "id": "\"9& passes_namespace_restrictions\"_\"4& passes_resource_restrictions\"", - "source": "\"9& passes_namespace_restrictions\"", - "target": "\"4& passes_resource_restrictions\"", - "index": "7.0" - } - }, - { - "data": { - "id": "\"9& passes_namespace_restrictions\"_\"39& input.command.namespace\"", - "source": "\"9& passes_namespace_restrictions\"", - "target": "\"39& input.command.namespace\"", - "index": "9.0" - } - }, - { - "data": { - "id": "\"9& passes_namespace_restrictions\"_\"42& namespace\"", - "source": "\"9& passes_namespace_restrictions\"", - "target": "\"42& namespace\"", - "index": "9.1" - } - }, - { - "data": { - "id": "\"10& deny\"_\"113& audit_decision\"", - "source": "\"10& deny\"", - "target": "\"113& audit_decision\"", - "index": "113" - } - }, - { - "data": { - "id": "\"10& deny\"_\"3& is_forbidden_operation\"", - "source": "\"10& deny\"", - "target": "\"3& is_forbidden_operation\"", - "index": "116.2" - } - }, - { - "data": { - "id": "\"10& deny\"_\"5& has_dangerous_flags\"", - "source": "\"10& deny\"", - "target": "\"5& has_dangerous_flags\"", - "index": "116.3" - } - }, - { - "data": { - "id": "\"11& input.command.verb\"_\"12& safe_verbs\"", - "source": "\"11& input.command.verb\"", - "target": "\"12& safe_verbs\"", - "index": "2.0" - } - }, - { - "data": { - "id": "\"11& input.command.verb\"_\"14& resource_less_safe_verbs\"", - "source": "\"11& input.command.verb\"", - "target": "\"14& resource_less_safe_verbs\"", - "index": "4.1, 2.1" - } - }, - { - "data": { - "id": "\"11& input.command.verb\"_\"20& describe.get.list.logs\"", - "source": "\"11& input.command.verb\"", - "target": "\"20& describe.get.list.logs\"", - "index": "13.1" - } - }, - { - "data": { - "id": "\"11& input.command.verb\"_\"26& restricted_verbs\"", - "source": "\"11& input.command.verb\"", - "target": "\"26& restricted_verbs\"", - "index": "8.0" - } - }, - { - "data": { - "id": "\"11& input.command.verb\"_\"29& forbidden_verbs\"", - "source": "\"11& input.command.verb\"", - "target": "\"29& forbidden_verbs\"", - "index": "3.0" - } - }, - { - "data": { - "id": "\"11& input.command.verb\"_\"30& delete\"", - "source": "\"11& input.command.verb\"", - "target": "\"30& delete\"", - "index": "5.3, 5.2, 117.4, 3.2, 101.0, 101.1, 99.0, 102.0" - } - }, - { - "data": { - "id": "\"11& input.command.verb\"_\"36& apply.create.delete.edit.patch.replace\"", - "source": "\"11& input.command.verb\"", - "target": "\"36& apply.create.delete.edit.patch.replace\"", - "index": "34.0, 32.0" - } - }, - { - "data": { - "id": "\"11& input.command.verb\"_\"40& describe.get.list\"", - "source": "\"11& input.command.verb\"", - "target": "\"40& describe.get.list\"", - "index": "4.3, 4.2, 9.0" - } - }, - { - "data": { - "id": "\"11& input.command.verb\"_\"24& Null string\"", - "source": "\"11& input.command.verb\"", - "target": "\"24& Null string\"", - "index": "6.0" - } - }, - { - "data": { - "id": "\"11& input.command.verb\"_\"63& apply.attach.cp.debug.exec.logs.port-forward\"", - "source": "\"11& input.command.verb\"", - "target": "\"63& apply.attach.cp.debug.exec.logs.port-forward\"", - "index": "59.1" - } - }, - { - "data": { - "id": "\"11& input.command.verb\"_\"81& exec\"", - "source": "\"11& input.command.verb\"", - "target": "\"81& exec\"", - "index": "80.0, 83.1, 83.0" - } - }, - { - "data": { - "id": "\"11& input.command.verb\"_\"88& port-forward\"", - "source": "\"11& input.command.verb\"", - "target": "\"88& port-forward\"", - "index": "87.1, 87.0" - } - }, - { - "data": { - "id": "\"11& input.command.verb\"_\"93& create\"", - "source": "\"11& input.command.verb\"", - "target": "\"93& create\"", - "index": "92.1, 92.0, 95.1, 95.0, 95.2" - } - }, - { - "data": { - "id": "\"11& input.command.verb\"_\"104& apply.patch\"", - "source": "\"11& input.command.verb\"", - "target": "\"104& apply.patch\"", - "index": "103.0, 106.0" - } - }, - { - "data": { - "id": "\"11& input.command.verb\"_\"109& apply.create.delete.patch\"", - "source": "\"11& input.command.verb\"", - "target": "\"109& apply.create.delete.patch\"", - "index": "108.0" - } - }, - { - "data": { - "id": "\"12& safe_verbs\"_\"13& all_resources_are_safe\"", - "source": "\"12& safe_verbs\"", - "target": "\"13& all_resources_are_safe\"", - "index": "2.0" - } - }, - { - "data": { - "id": "\"13& all_resources_are_safe\"_\"17& resource_types\"", - "source": "\"13& all_resources_are_safe\"", - "target": "\"17& resource_types\"", - "index": "13.0" - } - }, - { - "data": { - "id": "\"13& all_resources_are_safe\"_\"11& input.command.verb\"", - "source": "\"13& all_resources_are_safe\"", - "target": "\"11& input.command.verb\"", - "index": "13.1" - } - }, - { - "data": { - "id": "\"14& resource_less_safe_verbs\"_\"15& input.command.resource\"", - "source": "\"14& resource_less_safe_verbs\"", - "target": "\"15& input.command.resource\"", - "index": "2.1" - } - }, - { - "data": { - "id": "\"15& input.command.resource\"_\"16& null\"", - "source": "\"15& input.command.resource\"", - "target": "\"16& null\"", - "index": "4.1, 59.1, 2.1, 60.6" - } - }, - { - "data": { - "id": "\"15& input.command.resource\"_\"35& clusterrole.clusterrolebinding.clusterrolebindings.clusterroles.role.rolebinding.rolebindings.roles.serviceaccount.serviceaccounts\"", - "source": "\"15& input.command.resource\"", - "target": "\"35& clusterrole.clusterrolebinding.clusterrolebindings.clusterroles.role.rolebinding.rolebindings.roles.serviceaccount.serviceaccounts\"", - "index": "32.0" - } - }, - { - "data": { - "id": "\"15& input.command.resource\"_\"37& networkpolicies.poddisruptionbudgets.podsecuritypolicies.securitycontextconstraints\"", - "source": "\"15& input.command.resource\"", - "target": "\"37& networkpolicies.poddisruptionbudgets.podsecuritypolicies.securitycontextconstraints\"", - "index": "33.0" - } - }, - { - "data": { - "id": "\"15& input.command.resource\"_\"38& componentstatuse.componentstatuses.csidriver.csidrivers.csinode.csinodes.node.nodes.volumeattachment.volumeattachments\"", - "source": "\"15& input.command.resource\"", - "target": "\"38& componentstatuse.componentstatuses.csidriver.csidrivers.csinode.csinodes.node.nodes.volumeattachment.volumeattachments\"", - "index": "34.0" - } - }, - { - "data": { - "id": "\"15& input.command.resource\"_\"41& cluster_scoped_safe_resources\"", - "source": "\"15& input.command.resource\"", - "target": "\"41& cluster_scoped_safe_resources\"", - "index": "9.0" - } - }, - { - "data": { - "id": "\"15& input.command.resource\"_\"24& Null string\"", - "source": "\"15& input.command.resource\"", - "target": "\"24& Null string\"", - "index": "59.0" - } - }, - { - "data": { - "id": "\"15& input.command.resource\"_\"70& $(\"", - "source": "\"15& input.command.resource\"", - "target": "\"70& $(\"", - "index": "60.6" - } - }, - { - "data": { - "id": "\"15& input.command.resource\"_\"94& allowed_create_resources\"", - "source": "\"15& input.command.resource\"", - "target": "\"94& allowed_create_resources\"", - "index": "92.1" - } - }, - { - "data": { - "id": "\"15& input.command.resource\"_\"100& safe_delete_resources\"", - "source": "\"15& input.command.resource\"", - "target": "\"100& safe_delete_resources\"", - "index": "99.0" - } - }, - { - "data": { - "id": "\"15& input.command.resource\"_\"105& modifiable_resources\"", - "source": "\"15& input.command.resource\"", - "target": "\"105& modifiable_resources\"", - "index": "103.0" - } - }, - { - "data": { - "id": "\"15& input.command.resource\"_\"31& critical_resources\"", - "source": "\"15& input.command.resource\"", - "target": "\"31& critical_resources\"", - "index": "117.4" - } - }, - { - "data": { - "id": "\"15& input.command.resource\"_\"21& forbidden_resources\"", - "source": "\"15& input.command.resource\"", - "target": "\"21& forbidden_resources\"", - "index": "119.0" - } - }, - { - "data": { - "id": "\"16& null\"_\"17& resource_types\"", - "source": "\"16& null\"", - "target": "\"17& resource_types\"", - "index": "22.0" - } - }, - { - "data": { - "id": "\"16& null\"_\"11& input.command.verb\"", - "source": "\"16& null\"", - "target": "\"11& input.command.verb\"", - "index": "4.1, 59.1" - } - }, - { - "data": { - "id": "\"16& null\"_\"15& input.command.resource\"", - "source": "\"16& null\"", - "target": "\"15& input.command.resource\"", - "index": "60.6" - } - }, - { - "data": { - "id": "\"17& resource_types\"_\"18& resource_type\"", - "source": "\"17& resource_types\"", - "target": "\"18& resource_type\"", - "index": "4.0, 27.0, 13.1, 13.0" - } - }, - { - "data": { - "id": "\"17& resource_types\"_\"24& Null string\"", - "source": "\"17& resource_types\"", - "target": "\"24& Null string\"", - "index": "22.0" - } - }, - { - "data": { - "id": "\"17& resource_types\"_\"47& other_resource\"", - "source": "\"17& resource_types\"", - "target": "\"47& other_resource\"", - "index": "4.2, 4.3" - } - }, - { - "data": { - "id": "\"18& resource_type\"_\"19& safe_resources\"", - "source": "\"18& resource_type\"", - "target": "\"19& safe_resources\"", - "index": "13.0" - } - }, - { - "data": { - "id": "\"18& resource_type\"_\"21& forbidden_resources\"", - "source": "\"18& resource_type\"", - "target": "\"21& forbidden_resources\"", - "index": "3.1, 13.1" - } - }, - { - "data": { - "id": "\"18& resource_type\"_\"28& allowed_resources_for_modification\"", - "source": "\"18& resource_type\"", - "target": "\"28& allowed_resources_for_modification\"", - "index": "27.0" - } - }, - { - "data": { - "id": "\"18& resource_type\"_\"31& critical_resources\"", - "source": "\"18& resource_type\"", - "target": "\"31& critical_resources\"", - "index": "3.2" - } - }, - { - "data": { - "id": "\"18& resource_type\"_\"45& allowed_resources\"", - "source": "\"18& resource_type\"", - "target": "\"45& allowed_resources\"", - "index": "4.0" - } - }, - { - "data": { - "id": "\"18& resource_type\"_\"46& secrets\"", - "source": "\"18& resource_type\"", - "target": "\"46& secrets\"", - "index": "4.2, 4.3" - } - }, - { - "data": { - "id": "\"20& describe.get.list.logs\"_\"17& resource_types\"", - "source": "\"20& describe.get.list.logs\"", - "target": "\"17& resource_types\"", - "index": "13.1" - } - }, - { - "data": { - "id": "\"23& resource_string\"_\"16& null\"", - "source": "\"23& resource_string\"", - "target": "\"16& null\"", - "index": "22.0" - } - }, - { - "data": { - "id": "\"24& Null string\"_\"11& input.command.verb\"", - "source": "\"24& Null string\"", - "target": "\"11& input.command.verb\"", - "index": "9.0" - } - }, - { - "data": { - "id": "\"24& Null string\"_\"42& namespace\"", - "source": "\"24& Null string\"", - "target": "\"42& namespace\"", - "index": "9.1" - } - }, - { - "data": { - "id": "\"24& Null string\"_\"59& resource_requirement_satisfied\"", - "source": "\"24& Null string\"", - "target": "\"59& resource_requirement_satisfied\"", - "index": "6.0" - } - }, - { - "data": { - "id": "\"26& restricted_verbs\"_\"27& all_resources_modifiable\"", - "source": "\"26& restricted_verbs\"", - "target": "\"27& all_resources_modifiable\"", - "index": "8.0" - } - }, - { - "data": { - "id": "\"27& all_resources_modifiable\"_\"3& is_forbidden_operation\"", - "source": "\"27& all_resources_modifiable\"", - "target": "\"3& is_forbidden_operation\"", - "index": "8.0" - } - }, - { - "data": { - "id": "\"27& all_resources_modifiable\"_\"17& resource_types\"", - "source": "\"27& all_resources_modifiable\"", - "target": "\"17& resource_types\"", - "index": "27.0" - } - }, - { - "data": { - "id": "\"30& delete\"_\"18& resource_type\"", - "source": "\"30& delete\"", - "target": "\"18& resource_type\"", - "index": "3.2" - } - }, - { - "data": { - "id": "\"30& delete\"_\"15& input.command.resource\"", - "source": "\"30& delete\"", - "target": "\"15& input.command.resource\"", - "index": "99.0, 117.4" - } - }, - { - "data": { - "id": "\"30& delete\"_\"51& --all\"", - "source": "\"30& delete\"", - "target": "\"51& --all\"", - "index": "101.0" - } - }, - { - "data": { - "id": "\"30& delete\"_\"48& --force\"", - "source": "\"30& delete\"", - "target": "\"48& --force\"", - "index": "101.1" - } - }, - { - "data": { - "id": "\"30& delete\"_\"64& arg\"", - "source": "\"30& delete\"", - "target": "\"64& arg\"", - "index": "102.0" - } - }, - { - "data": { - "id": "\"32& targets_rbac_resources\"_\"15& input.command.resource\"", - "source": "\"32& targets_rbac_resources\"", - "target": "\"15& input.command.resource\"", - "index": "32.0" - } - }, - { - "data": { - "id": "\"33& targets_security_resources\"_\"15& input.command.resource\"", - "source": "\"33& targets_security_resources\"", - "target": "\"15& input.command.resource\"", - "index": "33.0" - } - }, - { - "data": { - "id": "\"34& targets_system_resources\"_\"15& input.command.resource\"", - "source": "\"34& targets_system_resources\"", - "target": "\"15& input.command.resource\"", - "index": "34.0" - } - }, - { - "data": { - "id": "\"35& clusterrole.clusterrolebinding.clusterrolebindings.clusterroles.role.rolebinding.rolebindings.roles.serviceaccount.serviceaccounts\"_\"11& input.command.verb\"", - "source": "\"35& clusterrole.clusterrolebinding.clusterrolebindings.clusterroles.role.rolebinding.rolebindings.roles.serviceaccount.serviceaccounts\"", - "target": "\"11& input.command.verb\"", - "index": "32.0" - } - }, - { - "data": { - "id": "\"38& componentstatuse.componentstatuses.csidriver.csidrivers.csinode.csinodes.node.nodes.volumeattachment.volumeattachments\"_\"11& input.command.verb\"", - "source": "\"38& componentstatuse.componentstatuses.csidriver.csidrivers.csinode.csinodes.node.nodes.volumeattachment.volumeattachments\"", - "target": "\"11& input.command.verb\"", - "index": "34.0" - } - }, - { - "data": { - "id": "\"39& input.command.namespace\"_\"24& Null string\"", - "source": "\"39& input.command.namespace\"", - "target": "\"24& Null string\"", - "index": "9.0" - } - }, - { - "data": { - "id": "\"39& input.command.namespace\"_\"42& namespace\"", - "source": "\"39& input.command.namespace\"", - "target": "\"42& namespace\"", - "index": "9.1" - } - }, - { - "data": { - "id": "\"40& describe.get.list\"_\"15& input.command.resource\"", - "source": "\"40& describe.get.list\"", - "target": "\"15& input.command.resource\"", - "index": "9.0" - } - }, - { - "data": { - "id": "\"40& describe.get.list\"_\"17& resource_types\"", - "source": "\"40& describe.get.list\"", - "target": "\"17& resource_types\"", - "index": "4.2, 4.3" - } - }, - { - "data": { - "id": "\"42& namespace\"_\"39& input.command.namespace\"", - "source": "\"42& namespace\"", - "target": "\"39& input.command.namespace\"", - "index": "9.1" - } - }, - { - "data": { - "id": "\"42& namespace\"_\"24& Null string\"", - "source": "\"42& namespace\"", - "target": "\"24& Null string\"", - "index": "9.1" - } - }, - { - "data": { - "id": "\"42& namespace\"_\"43& allowed_namespaces\"", - "source": "\"42& namespace\"", - "target": "\"43& allowed_namespaces\"", - "index": "9.1" - } - }, - { - "data": { - "id": "\"42& namespace\"_\"44& forbidden_namespaces\"", - "source": "\"42& namespace\"", - "target": "\"44& forbidden_namespaces\"", - "index": "9.1" - } - }, - { - "data": { - "id": "\"43& allowed_namespaces\"_\"42& namespace\"", - "source": "\"43& allowed_namespaces\"", - "target": "\"42& namespace\"", - "index": "9.1" - } - }, - { - "data": { - "id": "\"46& secrets\"_\"11& input.command.verb\"", - "source": "\"46& secrets\"", - "target": "\"11& input.command.verb\"", - "index": "4.2, 4.3" - } - }, - { - "data": { - "id": "\"47& other_resource\"_\"46& secrets\"", - "source": "\"47& other_resource\"", - "target": "\"46& secrets\"", - "index": "4.2" - } - }, - { - "data": { - "id": "\"47& other_resource\"_\"45& allowed_resources\"", - "source": "\"47& other_resource\"", - "target": "\"45& allowed_resources\"", - "index": "4.3" - } - }, - { - "data": { - "id": "\"48& --force\"_\"49& input.command.flags\"", - "source": "\"48& --force\"", - "target": "\"49& input.command.flags\"", - "index": "101.1, 5.0" - } - }, - { - "data": { - "id": "\"49& input.command.flags\"_\"11& input.command.verb\"", - "source": "\"49& input.command.flags\"", - "target": "\"11& input.command.verb\"", - "index": "5.3, 5.2" - } - }, - { - "data": { - "id": "\"50& --grace-period=0\"_\"49& input.command.flags\"", - "source": "\"50& --grace-period=0\"", - "target": "\"49& input.command.flags\"", - "index": "5.1" - } - }, - { - "data": { - "id": "\"51& --all\"_\"49& input.command.flags\"", - "source": "\"51& --all\"", - "target": "\"49& input.command.flags\"", - "index": "101.0, 5.2" - } - }, - { - "data": { - "id": "\"52& --cascade=orphan\"_\"49& input.command.flags\"", - "source": "\"52& --cascade=orphan\"", - "target": "\"49& input.command.flags\"", - "index": "5.3" - } - }, - { - "data": { - "id": "\"53& flag\"_\"54& --privileged=true\"", - "source": "\"53& flag\"", - "target": "\"54& --privileged=true\"", - "index": "5.4" - } - }, - { - "data": { - "id": "\"53& flag\"_\"55& --host\"", - "source": "\"53& flag\"", - "target": "\"55& --host\"", - "index": "5.5" - } - }, - { - "data": { - "id": "\"53& flag\"_\"56& --as=\"", - "source": "\"53& flag\"", - "target": "\"56& --as=\"", - "index": "5.6" - } - }, - { - "data": { - "id": "\"53& flag\"_\"57& --as-group=\"", - "source": "\"53& flag\"", - "target": "\"57& --as-group=\"", - "index": "5.7" - } - }, - { - "data": { - "id": "\"53& flag\"_\"58& sudo\"", - "source": "\"53& flag\"", - "target": "\"58& sudo\"", - "index": "5.8" - } - }, - { - "data": { - "id": "\"53& flag\"_\"96& privileged=true\"", - "source": "\"53& flag\"", - "target": "\"96& privileged=true\"", - "index": "95.0" - } - }, - { - "data": { - "id": "\"53& flag\"_\"97& hostNetwork=true\"", - "source": "\"53& flag\"", - "target": "\"97& hostNetwork=true\"", - "index": "95.1" - } - }, - { - "data": { - "id": "\"53& flag\"_\"98& hostPID=true\"", - "source": "\"53& flag\"", - "target": "\"98& hostPID=true\"", - "index": "95.2" - } - }, - { - "data": { - "id": "\"53& flag\"_\"107& securityContext\"", - "source": "\"53& flag\"", - "target": "\"107& securityContext\"", - "index": "106.0" - } - }, - { - "data": { - "id": "\"59& resource_requirement_satisfied\"_\"60& contains_injection_patterns\"", - "source": "\"59& resource_requirement_satisfied\"", - "target": "\"60& contains_injection_patterns\"", - "index": "6.0" - } - }, - { - "data": { - "id": "\"59& resource_requirement_satisfied\"_\"15& input.command.resource\"", - "source": "\"59& resource_requirement_satisfied\"", - "target": "\"15& input.command.resource\"", - "index": "59.0, 59.1" - } - }, - { - "data": { - "id": "\"60& contains_injection_patterns\"_\"61& contains_shell_metacharacters\"", - "source": "\"60& contains_injection_patterns\"", - "target": "\"61& contains_shell_metacharacters\"", - "index": "6.0" - } - }, - { - "data": { - "id": "\"60& contains_injection_patterns\"_\"64& arg\"", - "source": "\"60& contains_injection_patterns\"", - "target": "\"64& arg\"", - "index": "60.4, 60.1, 60.3, 60.2, 60.5, 60.0" - } - }, - { - "data": { - "id": "\"60& contains_injection_patterns\"_\"15& input.command.resource\"", - "source": "\"60& contains_injection_patterns\"", - "target": "\"15& input.command.resource\"", - "index": "60.6" - } - }, - { - "data": { - "id": "\"60& contains_injection_patterns\"_\"71& flag.value\"", - "source": "\"60& contains_injection_patterns\"", - "target": "\"71& flag.value\"", - "index": "60.12, 60.9, 60.10, 60.8, 60.7, 60.11" - } - }, - { - "data": { - "id": "\"60& contains_injection_patterns\"_\"72& input.original_command\"", - "source": "\"60& contains_injection_patterns\"", - "target": "\"72& input.original_command\"", - "index": "60.13" - } - }, - { - "data": { - "id": "\"61& contains_shell_metacharacters\"_\"62& valid_resource_names\"", - "source": "\"61& contains_shell_metacharacters\"", - "target": "\"62& valid_resource_names\"", - "index": "6.0" - } - }, - { - "data": { - "id": "\"61& contains_shell_metacharacters\"_\"73& [`${}><&]\"", - "source": "\"61& contains_shell_metacharacters\"", - "target": "\"73& [`${}><&]\"", - "index": "61.0" - } - }, - { - "data": { - "id": "\"62& valid_resource_names\"_\"74& input.command.args\"", - "source": "\"62& valid_resource_names\"", - "target": "\"74& input.command.args\"", - "index": "62.1" - } - }, - { - "data": { - "id": "\"64& arg\"_\"65& ;\"", - "source": "\"64& arg\"", - "target": "\"65& ;\"", - "index": "60.0" - } - }, - { - "data": { - "id": "\"64& arg\"_\"66& &&\"", - "source": "\"64& arg\"", - "target": "\"66& &&\"", - "index": "60.1" - } - }, - { - "data": { - "id": "\"64& arg\"_\"67& ||\"", - "source": "\"64& arg\"", - "target": "\"67& ||\"", - "index": "60.2" - } - }, - { - "data": { - "id": "\"64& arg\"_\"68& |\"", - "source": "\"64& arg\"", - "target": "\"68& |\"", - "index": "60.3" - } - }, - { - "data": { - "id": "\"64& arg\"_\"69& `\"", - "source": "\"64& arg\"", - "target": "\"69& `\"", - "index": "60.4" - } - }, - { - "data": { - "id": "\"64& arg\"_\"70& $(\"", - "source": "\"64& arg\"", - "target": "\"70& $(\"", - "index": "60.5" - } - }, - { - "data": { - "id": "\"64& arg\"_\"75& kube-+76& system\"", - "source": "\"64& arg\"", - "target": "\"75& kube-+76& system\"", - "index": "62.1" - } - }, - { - "data": { - "id": "\"64& arg\"_\"77& is_valid_resource_name\"", - "source": "\"64& arg\"", - "target": "\"77& is_valid_resource_name\"", - "index": "62.1" - } - }, - { - "data": { - "id": "\"64& arg\"_\"84& dangerous_exec_commands\"", - "source": "\"64& arg\"", - "target": "\"84& dangerous_exec_commands\"", - "index": "82.0" - } - }, - { - "data": { - "id": "\"64& arg\"_\"85& rm -rf\"", - "source": "\"64& arg\"", - "target": "\"85& rm -rf\"", - "index": "82.1" - } - }, - { - "data": { - "id": "\"64& arg\"_\"86& dd if=\"", - "source": "\"64& arg\"", - "target": "\"86& dd if=\"", - "index": "82.2" - } - }, - { - "data": { - "id": "\"64& arg\"_\"90& \"", - "source": "\"64& arg\"", - "target": "\"90& \"", - "index": "89.0" - } - }, - { - "data": { - "id": "\"64& arg\"_\"51& --all\"", - "source": "\"64& arg\"", - "target": "\"51& --all\"", - "index": "102.0" - } - }, - { - "data": { - "id": "\"71& flag.value\"_\"70& $(\"", - "source": "\"71& flag.value\"", - "target": "\"70& $(\"", - "index": "60.7" - } - }, - { - "data": { - "id": "\"71& flag.value\"_\"69& `\"", - "source": "\"71& flag.value\"", - "target": "\"69& `\"", - "index": "60.8" - } - }, - { - "data": { - "id": "\"71& flag.value\"_\"65& ;\"", - "source": "\"71& flag.value\"", - "target": "\"65& ;\"", - "index": "60.9" - } - }, - { - "data": { - "id": "\"71& flag.value\"_\"66& &&\"", - "source": "\"71& flag.value\"", - "target": "\"66& &&\"", - "index": "60.10" - } - }, - { - "data": { - "id": "\"71& flag.value\"_\"67& ||\"", - "source": "\"71& flag.value\"", - "target": "\"67& ||\"", - "index": "60.11" - } - }, - { - "data": { - "id": "\"71& flag.value\"_\"68& |\"", - "source": "\"71& flag.value\"", - "target": "\"68& |\"", - "index": "60.12" - } - }, - { - "data": { - "id": "\"72& input.original_command\"_\"70& $(\"", - "source": "\"72& input.original_command\"", - "target": "\"70& $(\"", - "index": "60.13" - } - }, - { - "data": { - "id": "\"73& [`${}><&]\"_\"64& arg\"", - "source": "\"73& [`${}><&]\"", - "target": "\"64& arg\"", - "index": "61.0" - } - }, - { - "data": { - "id": "\"74& input.command.args\"_\"64& arg\"", - "source": "\"74& input.command.args\"", - "target": "\"64& arg\"", - "index": "62.1" - } - }, - { - "data": { - "id": "\"77& is_valid_resource_name\"_\"78& ^[a-z0-9]([-a-z0-9]*[a-z0-9])?([.][a-z0-9]([-a-z0-9]*[a-z0-9])?)*$\"", - "source": "\"77& is_valid_resource_name\"", - "target": "\"78& ^[a-z0-9]([-a-z0-9]*[a-z0-9])?([.][a-z0-9]([-a-z0-9]*[a-z0-9])?)*$\"", - "index": "77.0" - } - }, - { - "data": { - "id": "\"77& is_valid_resource_name\"_\"79& ^[a-z0-9]([-a-z0-9]*[a-z0-9])?([.][a-z0-9]([-a-z0-9]*[a-z0-9])?)*([,][a-z0-9]([-a-z0-9]*[a-z0-9])?([.][a-z0-9]([-a-z0-9]*[a-z0-9])?)*)*$\"", - "source": "\"77& is_valid_resource_name\"", - "target": "\"79& ^[a-z0-9]([-a-z0-9]*[a-z0-9])?([.][a-z0-9]([-a-z0-9]*[a-z0-9])?)*([,][a-z0-9]([-a-z0-9]*[a-z0-9])?([.][a-z0-9]([-a-z0-9]*[a-z0-9])?)*)*$\"", - "index": "77.1" - } - }, - { - "data": { - "id": "\"78& ^[a-z0-9]([-a-z0-9]*[a-z0-9])?([.][a-z0-9]([-a-z0-9]*[a-z0-9])?)*$\"_\"64& arg\"", - "source": "\"78& ^[a-z0-9]([-a-z0-9]*[a-z0-9])?([.][a-z0-9]([-a-z0-9]*[a-z0-9])?)*$\"", - "target": "\"64& arg\"", - "index": "77.0" - } - }, - { - "data": { - "id": "\"79& ^[a-z0-9]([-a-z0-9]*[a-z0-9])?([.][a-z0-9]([-a-z0-9]*[a-z0-9])?)*([,][a-z0-9]([-a-z0-9]*[a-z0-9])?([.][a-z0-9]([-a-z0-9]*[a-z0-9])?)*)*$\"_\"64& arg\"", - "source": "\"79& ^[a-z0-9]([-a-z0-9]*[a-z0-9])?([.][a-z0-9]([-a-z0-9]*[a-z0-9])?)*([,][a-z0-9]([-a-z0-9]*[a-z0-9])?([.][a-z0-9]([-a-z0-9]*[a-z0-9])?)*)*$\"", - "target": "\"64& arg\"", - "index": "77.1" - } - }, - { - "data": { - "id": "\"80& exec_command_restrictions\"_\"11& input.command.verb\"", - "source": "\"80& exec_command_restrictions\"", - "target": "\"11& input.command.verb\"", - "index": "80.0" - } - }, - { - "data": { - "id": "\"81& exec\"_\"82& contains_dangerous_exec_commands\"", - "source": "\"81& exec\"", - "target": "\"82& contains_dangerous_exec_commands\"", - "index": "80.0, 83.1" - } - }, - { - "data": { - "id": "\"82& contains_dangerous_exec_commands\"_\"83& valid_exec_structure\"", - "source": "\"82& contains_dangerous_exec_commands\"", - "target": "\"83& valid_exec_structure\"", - "index": "80.0" - } - }, - { - "data": { - "id": "\"82& contains_dangerous_exec_commands\"_\"64& arg\"", - "source": "\"82& contains_dangerous_exec_commands\"", - "target": "\"64& arg\"", - "index": "82.1, 82.2, 82.0" - } - }, - { - "data": { - "id": "\"83& valid_exec_structure\"_\"11& input.command.verb\"", - "source": "\"83& valid_exec_structure\"", - "target": "\"11& input.command.verb\"", - "index": "83.1, 83.0" - } - }, - { - "data": { - "id": "\"87& port_forward_restrictions\"_\"11& input.command.verb\"", - "source": "\"87& port_forward_restrictions\"", - "target": "\"11& input.command.verb\"", - "index": "87.1, 87.0" - } - }, - { - "data": { - "id": "\"88& port-forward\"_\"89& valid_port_specification\"", - "source": "\"88& port-forward\"", - "target": "\"89& valid_port_specification\"", - "index": "87.1" - } - }, - { - "data": { - "id": "\"89& valid_port_specification\"_\"64& arg\"", - "source": "\"89& valid_port_specification\"", - "target": "\"64& arg\"", - "index": "89.0" - } - }, - { - "data": { - "id": "\"92& create_command_restrictions\"_\"11& input.command.verb\"", - "source": "\"92& create_command_restrictions\"", - "target": "\"11& input.command.verb\"", - "index": "92.0, 92.1" - } - }, - { - "data": { - "id": "\"93& create\"_\"15& input.command.resource\"", - "source": "\"93& create\"", - "target": "\"15& input.command.resource\"", - "index": "92.1" - } - }, - { - "data": { - "id": "\"93& create\"_\"53& flag\"", - "source": "\"93& create\"", - "target": "\"53& flag\"", - "index": "95.2, 95.1, 95.0" - } - }, - { - "data": { - "id": "\"94& allowed_create_resources\"_\"95& creates_privileged_resources\"", - "source": "\"94& allowed_create_resources\"", - "target": "\"95& creates_privileged_resources\"", - "index": "92.1" - } - }, - { - "data": { - "id": "\"95& creates_privileged_resources\"_\"11& input.command.verb\"", - "source": "\"95& creates_privileged_resources\"", - "target": "\"11& input.command.verb\"", - "index": "95.2, 95.1, 95.0" - } - }, - { - "data": { - "id": "\"99& delete_allowed\"_\"11& input.command.verb\"", - "source": "\"99& delete_allowed\"", - "target": "\"11& input.command.verb\"", - "index": "99.0" - } - }, - { - "data": { - "id": "\"100& safe_delete_resources\"_\"101& has_dangerous_delete_flags\"", - "source": "\"100& safe_delete_resources\"", - "target": "\"101& has_dangerous_delete_flags\"", - "index": "99.0" - } - }, - { - "data": { - "id": "\"101& has_dangerous_delete_flags\"_\"102& deletes_all_resources\"", - "source": "\"101& has_dangerous_delete_flags\"", - "target": "\"102& deletes_all_resources\"", - "index": "99.0" - } - }, - { - "data": { - "id": "\"101& has_dangerous_delete_flags\"_\"11& input.command.verb\"", - "source": "\"101& has_dangerous_delete_flags\"", - "target": "\"11& input.command.verb\"", - "index": "101.1, 101.0" - } - }, - { - "data": { - "id": "\"102& deletes_all_resources\"_\"11& input.command.verb\"", - "source": "\"102& deletes_all_resources\"", - "target": "\"11& input.command.verb\"", - "index": "102.0" - } - }, - { - "data": { - "id": "\"103& modification_allowed\"_\"11& input.command.verb\"", - "source": "\"103& modification_allowed\"", - "target": "\"11& input.command.verb\"", - "index": "103.0" - } - }, - { - "data": { - "id": "\"104& apply.patch\"_\"15& input.command.resource\"", - "source": "\"104& apply.patch\"", - "target": "\"15& input.command.resource\"", - "index": "103.0" - } - }, - { - "data": { - "id": "\"104& apply.patch\"_\"53& flag\"", - "source": "\"104& apply.patch\"", - "target": "\"53& flag\"", - "index": "106.0" - } - }, - { - "data": { - "id": "\"105& modifiable_resources\"_\"106& modifies_security_context\"", - "source": "\"105& modifiable_resources\"", - "target": "\"106& modifies_security_context\"", - "index": "103.0" - } - }, - { - "data": { - "id": "\"106& modifies_security_context\"_\"11& input.command.verb\"", - "source": "\"106& modifies_security_context\"", - "target": "\"11& input.command.verb\"", - "index": "106.0" - } - }, - { - "data": { - "id": "\"108& requires_dry_run\"_\"11& input.command.verb\"", - "source": "\"108& requires_dry_run\"", - "target": "\"11& input.command.verb\"", - "index": "108.0" - } - }, - { - "data": { - "id": "\"109& apply.create.delete.patch\"_\"110& has_dry_run_flag\"", - "source": "\"109& apply.create.delete.patch\"", - "target": "\"110& has_dry_run_flag\"", - "index": "108.0" - } - }, - { - "data": { - "id": "\"110& has_dry_run_flag\"_\"111& --dry-run=client\"", - "source": "\"110& has_dry_run_flag\"", - "target": "\"111& --dry-run=client\"", - "index": "110.0" - } - }, - { - "data": { - "id": "\"110& has_dry_run_flag\"_\"112& --dry-run=server\"", - "source": "\"110& has_dry_run_flag\"", - "target": "\"112& --dry-run=server\"", - "index": "110.1" - } - }, - { - "data": { - "id": "\"111& --dry-run=client\"_\"49& input.command.flags\"", - "source": "\"111& --dry-run=client\"", - "target": "\"49& input.command.flags\"", - "index": "110.0" - } - }, - { - "data": { - "id": "\"112& --dry-run=server\"_\"49& input.command.flags\"", - "source": "\"112& --dry-run=server\"", - "target": "\"49& input.command.flags\"", - "index": "110.1" - } - }, - { - "data": { - "id": "\"114& command_classification\"_\"2& is_safe_operation\"", - "source": "\"114& command_classification\"", - "target": "\"2& is_safe_operation\"", - "index": "114.0" - } - }, - { - "data": { - "id": "\"114& command_classification\"_\"8& is_restricted_operation\"", - "source": "\"114& command_classification\"", - "target": "\"8& is_restricted_operation\"", - "index": "114.1" - } - }, - { - "data": { - "id": "\"114& command_classification\"_\"3& is_forbidden_operation\"", - "source": "\"114& command_classification\"", - "target": "\"3& is_forbidden_operation\"", - "index": "114.2" - } - }, - { - "data": { - "id": "\"113& audit_decision\"_\"114& command_classification\"", - "source": "\"113& audit_decision\"", - "target": "\"114& command_classification\"", - "index": "113" - } - }, - { - "data": { - "id": "\"113& audit_decision\"_\"115& input.command\"", - "source": "\"113& audit_decision\"", - "target": "\"115& input.command\"", - "index": "113" - } - }, - { - "data": { - "id": "\"113& audit_decision\"_\"116& decision_reasoning\"", - "source": "\"113& audit_decision\"", - "target": "\"116& decision_reasoning\"", - "index": "113" - } - }, - { - "data": { - "id": "\"113& audit_decision\"_\"117& risk_assessment\"", - "source": "\"113& audit_decision\"", - "target": "\"117& risk_assessment\"", - "index": "113" - } - }, - { - "data": { - "id": "\"113& audit_decision\"_\"118& policy_violations\"", - "source": "\"113& audit_decision\"", - "target": "\"118& policy_violations\"", - "index": "113" - } - }, - { - "data": { - "id": "\"116& decision_reasoning\"_\"0& allow\"", - "source": "\"116& decision_reasoning\"", - "target": "\"0& allow\"", - "index": "116.0" - } - }, - { - "data": { - "id": "\"116& decision_reasoning\"_\"7& requires_approval\"", - "source": "\"116& decision_reasoning\"", - "target": "\"7& requires_approval\"", - "index": "116.1" - } - }, - { - "data": { - "id": "\"116& decision_reasoning\"_\"10& deny\"", - "source": "\"116& decision_reasoning\"", - "target": "\"10& deny\"", - "index": "116.2, 116.3" - } - }, - { - "data": { - "id": "\"117& risk_assessment\"_\"2& is_safe_operation\"", - "source": "\"117& risk_assessment\"", - "target": "\"2& is_safe_operation\"", - "index": "117.0" - } - }, - { - "data": { - "id": "\"117& risk_assessment\"_\"8& is_restricted_operation\"", - "source": "\"117& risk_assessment\"", - "target": "\"8& is_restricted_operation\"", - "index": "117.1" - } - }, - { - "data": { - "id": "\"117& risk_assessment\"_\"3& is_forbidden_operation\"", - "source": "\"117& risk_assessment\"", - "target": "\"3& is_forbidden_operation\"", - "index": "117.2" - } - }, - { - "data": { - "id": "\"117& risk_assessment\"_\"32& targets_rbac_resources\"", - "source": "\"117& risk_assessment\"", - "target": "\"32& targets_rbac_resources\"", - "index": "117.3" - } - }, - { - "data": { - "id": "\"117& risk_assessment\"_\"11& input.command.verb\"", - "source": "\"117& risk_assessment\"", - "target": "\"11& input.command.verb\"", - "index": "117.4" - } - }, - { - "data": { - "id": "\"119& resource_violations\"_\"15& input.command.resource\"", - "source": "\"119& resource_violations\"", - "target": "\"15& input.command.resource\"", - "index": "119.0" - } - }, - { - "data": { - "id": "\"120& flag_violations\"_\"5& has_dangerous_flags\"", - "source": "\"120& flag_violations\"", - "target": "\"5& has_dangerous_flags\"", - "index": "120.0" - } - }, - { - "data": { - "id": "\"121& command_structure_violations\"_\"6& is_valid_command_structure\"", - "source": "\"121& command_structure_violations\"", - "target": "\"6& is_valid_command_structure\"", - "index": "121.0" - } - }, - { - "data": { - "id": "\"123& test_safe_get_pods\"_\"0& allow\"", - "source": "\"123& test_safe_get_pods\"", - "target": "\"0& allow\"", - "index": "123.0" - } - }, - { - "data": { - "id": "\"124& test_forbidden_delete_namespace\"_\"10& deny\"", - "source": "\"124& test_forbidden_delete_namespace\"", - "target": "\"10& deny\"", - "index": "124.0" - } - }, - { - "data": { - "id": "\"125& test_restricted_exec\"_\"7& requires_approval\"", - "source": "\"125& test_restricted_exec\"", - "target": "\"7& requires_approval\"", - "index": "125.0" - } - }, - { - "data": { - "id": "\"126& test_dangerous_flags\"_\"10& deny\"", - "source": "\"126& test_dangerous_flags\"", - "target": "\"10& deny\"", - "index": "126.0" - } - }, - { - "data": { - "id": "\"127& test_forbidden_namespace\"_\"10& deny\"", - "source": "\"127& test_forbidden_namespace\"", - "target": "\"10& deny\"", - "index": "127.0" - } - }, - { - "data": { - "id": "\"128& test_rbac_modification\"_\"10& deny\"", - "source": "\"128& test_rbac_modification\"", - "target": "\"10& deny\"", - "index": "128.0" - } - } - ] -} \ No newline at end of file diff --git a/scripts/visualization/parse_graph_to_json.py b/scripts/visualization/parse_graph_to_json.py deleted file mode 100644 index 01c4405..0000000 --- a/scripts/visualization/parse_graph_to_json.py +++ /dev/null @@ -1,47 +0,0 @@ -# Copyright 2026 Smith authors -# SPDX-License-Identifier: Apache-2.0 - -import pydot -import json - -graphs = pydot.graph_from_dot_file("ast.dot") -graph = graphs[0] - -nodes = [] -edges = [] - - -def parse(index): - if not index: - print("skipping") - print(index) - return -1 - if "[" in index and "]" in index: - print(index[2:-2].replace("'", "")) - return index[2:-2].replace("'", "") - return index - - -for node in graph.get_nodes(): - if node.get_name() not in ("node", "graph", "edge"): - node_id = node.get_name() - index = node.get("index") - nodes.append({"data": {"id": node_id, "index": index}}) - -for edge in graph.get_edges(): - source = edge.get_source() - target = edge.get_destination() - index = edge.get("label") - edges.append( - { - "data": { - "id": f"{source}_{target}", - "source": source, - "target": target, - "index": parse(index), - } - } - ) - -with open("graph.json", "w") as f: - json.dump({"nodes": nodes, "edges": edges}, f, indent=2) diff --git a/src/smith/__init__.py b/src/smith/__init__.py new file mode 100644 index 0000000..a798eb2 --- /dev/null +++ b/src/smith/__init__.py @@ -0,0 +1,10 @@ +# Copyright 2026 Smith authors +# SPDX-License-Identifier: Apache-2.0 +"""Smith — automated policy lifecycle management for AI agents (OPA/Rego).""" + +from importlib.metadata import PackageNotFoundError, version + +try: + __version__ = version("smith") +except PackageNotFoundError: # running from a source tree without an install + __version__ = "0.0.0" diff --git a/scripts/cli.py b/src/smith/cli.py similarity index 86% rename from scripts/cli.py rename to src/smith/cli.py index 3754b45..377878a 100644 --- a/scripts/cli.py +++ b/src/smith/cli.py @@ -9,29 +9,36 @@ from dotenv import load_dotenv -from policy_agent.scripts.parse_ast_to_graph import init_graph -from policy_agent.red_feedback.red_feedback import cluster_commands -from policy_agent.policy_analysis.update_policy_analysis import ( +from smith.policy_agent.scripts.parse_ast_to_graph import init_graph +from smith.policy_agent.red_feedback.red_feedback import cluster_commands +from smith.policy_agent.policy_analysis.update_policy_analysis import ( update_policy_analysis_feedback, ) -from policy_agent.policy_evaluation.run_policy_evaluation import run_policy_evaluation -from policy_agent.reduce_improve.detect_redundancy import write_graph_suggestion -from policy_agent.policy_analysis.regal.regal_finder import create_regal_suggestion -from test_generation.decompose import decompose_guidance -from test_generation.variable_extraction import variable_extraction -from test_generation.attack import attack -from test_generation.case_generation import case_generation -from test_generation.convert_test_case import translate_case -from test_generation.grey_condition import grey_extraction -from test_generation.attack_promptfoo import create_promptfoo_cases -from test_case_evaluation.classify_guidance import classify_promptfoo_cases -from test_case_evaluation.validate_labels import run_validation -from test_case_evaluation.visualization.build_report import build_visualization -from policy_generation.extract_tools import extract_tools -from policy_generation.validate_policy import validate_policy, fix_and_validate_policy -from test_case_evaluation.cross_validate import cross_validate_failed_cases -from test_case_evaluation.apply_cross_validate import apply_cross_validate_results -from test_generation.extract_tool_args import run_extract_tool_args +from smith.policy_agent.policy_evaluation.run_policy_evaluation import ( + run_policy_evaluation, +) +from smith.policy_agent.reduce_improve.detect_redundancy import write_graph_suggestion +from smith.policy_agent.policy_analysis.regal.regal_finder import ( + create_regal_suggestion, +) +from smith.test_generation.decompose import decompose_guidance +from smith.test_generation.variable_extraction import variable_extraction +from smith.test_generation.attack import attack +from smith.test_generation.case_generation import case_generation +from smith.test_generation.convert_test_case import translate_case +from smith.test_generation.grey_condition import grey_extraction +from smith.test_generation.attack_promptfoo import create_promptfoo_cases +from smith.test_case_evaluation.classify_guidance import classify_promptfoo_cases +from smith.test_case_evaluation.validate_labels import run_validation +from smith.test_case_evaluation.visualization.build_report import build_visualization +from smith.policy_generation.extract_tools import extract_tools +from smith.policy_generation.validate_policy import ( + validate_policy, + fix_and_validate_policy, +) +from smith.test_case_evaluation.cross_validate import cross_validate_failed_cases +from smith.test_case_evaluation.apply_cross_validate import apply_cross_validate_results +from smith.test_generation.extract_tool_args import run_extract_tool_args load_dotenv() @@ -64,9 +71,15 @@ def __init__(self): self.regal_result_output = self.user_output_dir + os.getenv( "REGAL_RESULT_OUTPUT" ) - self.test_dir = self.base_url + "scripts/" - self.test_path = self.test_dir + os.getenv("TEST_PATH") - self.test_results_path = self.test_path + os.getenv("TEST_RESULT_PATH") + # Scorecard outputs live under the skill root, written by the packaged + # policy_testing harness (see src/smith/policy_testing/score_card.sh). + self.test_output_dir = self.base_url + os.getenv( + "TEST_OUTPUT_DIR", "references/scorecard/" + ) + self.test_path = self.test_output_dir + self.test_results_path = self.test_output_dir + os.getenv( + "TEST_RESULT_PATH", "scorecard_summary.txt" + ) self.graph_suggestion_path = self.user_output_dir + os.getenv( "GRAPH_SUGGESTION_PATH" ) @@ -107,7 +120,7 @@ def get_red_feedback(self): ) def policy_checking_results(self): - return run_policy_evaluation(self.test_dir, self.test_results_path) + return run_policy_evaluation(self.base_url, self.test_results_path) def generate_test( @@ -403,9 +416,10 @@ def main(): if args.flag == "cross_validate": print("Running policy testing first to identify failed cases...") agent.policy_checking_results() - test_dir = base_url + "scripts/" - test_path_local = test_dir + os.getenv("TEST_PATH", "tests/integration/") - failures_file = test_path_local + os.getenv( + test_output_dir = base_url + os.getenv( + "TEST_OUTPUT_DIR", "references/scorecard/" + ) + failures_file = test_output_dir + os.getenv( "TEST_FAILURES_PATH", "score_test_failures.txt" ) cross_validate_output = base_url + os.getenv( diff --git a/scripts/__init__.py b/src/smith/policy_agent/__init__.py similarity index 100% rename from scripts/__init__.py rename to src/smith/policy_agent/__init__.py diff --git a/scripts/policy_agent/__init__.py b/src/smith/policy_agent/policy_analysis/__init__.py similarity index 100% rename from scripts/policy_agent/__init__.py rename to src/smith/policy_agent/policy_analysis/__init__.py diff --git a/scripts/policy_agent/policy_analysis/cycle_detection/__init__.py b/src/smith/policy_agent/policy_analysis/cycle_detection/__init__.py similarity index 100% rename from scripts/policy_agent/policy_analysis/cycle_detection/__init__.py rename to src/smith/policy_agent/policy_analysis/cycle_detection/__init__.py diff --git a/scripts/policy_agent/policy_analysis/cycle_detection/update_cycle_detection.py b/src/smith/policy_agent/policy_analysis/cycle_detection/update_cycle_detection.py similarity index 96% rename from scripts/policy_agent/policy_analysis/cycle_detection/update_cycle_detection.py rename to src/smith/policy_agent/policy_analysis/cycle_detection/update_cycle_detection.py index e6e2941..c796ea6 100644 --- a/scripts/policy_agent/policy_analysis/cycle_detection/update_cycle_detection.py +++ b/src/smith/policy_agent/policy_analysis/cycle_detection/update_cycle_detection.py @@ -10,11 +10,9 @@ from dotenv import load_dotenv # Add src folder to sys.path so imports work from test/ -import sys -sys.path.insert(0, os.path.join(os.path.dirname(__file__), "../../..")) -from policy_agent.policy_analysis.model_output_schema.schema import ( +from smith.policy_agent.policy_analysis.model_output_schema.schema import ( PolicyIssue, PolicyAnalysisReport, ) diff --git a/scripts/policy_agent/policy_analysis/__init__.py b/src/smith/policy_agent/policy_analysis/dead_rules/__init__.py similarity index 100% rename from scripts/policy_agent/policy_analysis/__init__.py rename to src/smith/policy_agent/policy_analysis/dead_rules/__init__.py diff --git a/scripts/policy_agent/policy_analysis/dead_rules/dead_rule_finder.py b/src/smith/policy_agent/policy_analysis/dead_rules/dead_rule_finder.py similarity index 96% rename from scripts/policy_agent/policy_analysis/dead_rules/dead_rule_finder.py rename to src/smith/policy_agent/policy_analysis/dead_rules/dead_rule_finder.py index e23262b..2b49bae 100644 --- a/scripts/policy_agent/policy_analysis/dead_rules/dead_rule_finder.py +++ b/src/smith/policy_agent/policy_analysis/dead_rules/dead_rule_finder.py @@ -11,11 +11,9 @@ from dotenv import load_dotenv # Add src folder to sys.path so imports work from test/ -import sys -sys.path.insert(0, os.path.join(os.path.dirname(__file__), "../../..")) -from policy_agent.policy_analysis.model_output_schema.schema import ( +from smith.policy_agent.policy_analysis.model_output_schema.schema import ( PolicyIssue, PolicyAnalysisReport, ) diff --git a/scripts/policy_agent/policy_analysis/dead_rules/__init__.py b/src/smith/policy_agent/policy_analysis/duplication/__init__.py similarity index 100% rename from scripts/policy_agent/policy_analysis/dead_rules/__init__.py rename to src/smith/policy_agent/policy_analysis/duplication/__init__.py diff --git a/scripts/policy_agent/policy_analysis/duplication/update_duplication.py b/src/smith/policy_agent/policy_analysis/duplication/update_duplication.py similarity index 96% rename from scripts/policy_agent/policy_analysis/duplication/update_duplication.py rename to src/smith/policy_agent/policy_analysis/duplication/update_duplication.py index a9169f9..744ddbf 100644 --- a/scripts/policy_agent/policy_analysis/duplication/update_duplication.py +++ b/src/smith/policy_agent/policy_analysis/duplication/update_duplication.py @@ -9,11 +9,8 @@ from openai import OpenAI from dotenv import load_dotenv -import sys -sys.path.insert(0, os.path.join(os.path.dirname(__file__), "../../..")) - -from policy_agent.policy_analysis.model_output_schema.schema import ( +from smith.policy_agent.policy_analysis.model_output_schema.schema import ( PolicyIssue, PolicyAnalysisReport, ) diff --git a/scripts/policy_agent/policy_analysis/duplication/__init__.py b/src/smith/policy_agent/policy_analysis/model_output_schema/__init__.py similarity index 100% rename from scripts/policy_agent/policy_analysis/duplication/__init__.py rename to src/smith/policy_agent/policy_analysis/model_output_schema/__init__.py diff --git a/scripts/policy_agent/policy_analysis/model_output_schema/schema.py b/src/smith/policy_agent/policy_analysis/model_output_schema/schema.py similarity index 100% rename from scripts/policy_agent/policy_analysis/model_output_schema/schema.py rename to src/smith/policy_agent/policy_analysis/model_output_schema/schema.py diff --git a/scripts/policy_agent/policy_analysis/model_output_schema/__init__.py b/src/smith/policy_agent/policy_analysis/regal/__init__.py similarity index 100% rename from scripts/policy_agent/policy_analysis/model_output_schema/__init__.py rename to src/smith/policy_agent/policy_analysis/regal/__init__.py diff --git a/scripts/policy_agent/policy_analysis/regal/regal_finder.py b/src/smith/policy_agent/policy_analysis/regal/regal_finder.py similarity index 100% rename from scripts/policy_agent/policy_analysis/regal/regal_finder.py rename to src/smith/policy_agent/policy_analysis/regal/regal_finder.py diff --git a/scripts/policy_agent/policy_analysis/regal/regal_suggestion.txt b/src/smith/policy_agent/policy_analysis/regal/regal_suggestion.txt similarity index 100% rename from scripts/policy_agent/policy_analysis/regal/regal_suggestion.txt rename to src/smith/policy_agent/policy_analysis/regal/regal_suggestion.txt diff --git a/scripts/policy_agent/policy_analysis/update_policy_analysis.py b/src/smith/policy_agent/policy_analysis/update_policy_analysis.py similarity index 81% rename from scripts/policy_agent/policy_analysis/update_policy_analysis.py rename to src/smith/policy_agent/policy_analysis/update_policy_analysis.py index ff71e1f..59c3de3 100644 --- a/scripts/policy_agent/policy_analysis/update_policy_analysis.py +++ b/src/smith/policy_agent/policy_analysis/update_policy_analysis.py @@ -1,17 +1,15 @@ # Copyright 2026 Smith authors # SPDX-License-Identifier: Apache-2.0 -from policy_agent.policy_analysis.duplication.update_duplication import ( +from smith.policy_agent.policy_analysis.duplication.update_duplication import ( detect_redundant_rules, ) -from policy_agent.policy_analysis.cycle_detection.update_cycle_detection import ( +from smith.policy_agent.policy_analysis.cycle_detection.update_cycle_detection import ( cycle_detection, ) -from policy_agent.policy_analysis.dead_rules.dead_rule_finder import detect_dead_rules -import os -import sys - -sys.path.insert(0, os.path.join(os.path.dirname(__file__), "../../..")) +from smith.policy_agent.policy_analysis.dead_rules.dead_rule_finder import ( + detect_dead_rules, +) def update_policy_analysis_feedback( diff --git a/scripts/policy_agent/policy_analysis/regal/__init__.py b/src/smith/policy_agent/policy_evaluation/__init__.py similarity index 100% rename from scripts/policy_agent/policy_analysis/regal/__init__.py rename to src/smith/policy_agent/policy_evaluation/__init__.py diff --git a/scripts/policy_agent/policy_evaluation/run_policy_evaluation.py b/src/smith/policy_agent/policy_evaluation/run_policy_evaluation.py similarity index 87% rename from scripts/policy_agent/policy_evaluation/run_policy_evaluation.py rename to src/smith/policy_agent/policy_evaluation/run_policy_evaluation.py index 544cbb1..b0cf82a 100644 --- a/scripts/policy_agent/policy_evaluation/run_policy_evaluation.py +++ b/src/smith/policy_agent/policy_evaluation/run_policy_evaluation.py @@ -44,7 +44,7 @@ def run_policy_evaluation(base_url, test_result_path): if __name__ == "__main__": # Load environment variables load_dotenv() - base_url = os.getenv("BASE_URL") + "scripts/" - test_path = base_url + os.getenv("TEST_PATH") - test_results_path = test_path + os.getenv("TEST_RESULT_PATH") + base_url = os.getenv("BASE_URL") + out_dir = base_url + os.getenv("TEST_OUTPUT_DIR", "references/scorecard/") + test_results_path = out_dir + os.getenv("TEST_RESULT_PATH", "scorecard_summary.txt") run_policy_evaluation(base_url, test_results_path) diff --git a/scripts/policy_agent/policy_refinement/README.md b/src/smith/policy_agent/policy_refinement/README.md similarity index 100% rename from scripts/policy_agent/policy_refinement/README.md rename to src/smith/policy_agent/policy_refinement/README.md diff --git a/scripts/policy_agent/policy_evaluation/__init__.py b/src/smith/policy_agent/policy_refinement/__init__.py similarity index 100% rename from scripts/policy_agent/policy_evaluation/__init__.py rename to src/smith/policy_agent/policy_refinement/__init__.py diff --git a/scripts/policy_agent/policy_refinement/refinement.py b/src/smith/policy_agent/policy_refinement/refinement.py similarity index 98% rename from scripts/policy_agent/policy_refinement/refinement.py rename to src/smith/policy_agent/policy_refinement/refinement.py index 4738a7f..9f67fcb 100644 --- a/scripts/policy_agent/policy_refinement/refinement.py +++ b/src/smith/policy_agent/policy_refinement/refinement.py @@ -6,7 +6,7 @@ from pathlib import Path import re import json -from policy_agent.reduce_improve.detect_redundancy import write_graph_suggestion +from smith.policy_agent.reduce_improve.detect_redundancy import write_graph_suggestion def load_file(path: Path) -> str: diff --git a/scripts/policy_agent/policy_refinement/__init__.py b/src/smith/policy_agent/red_feedback/__init__.py similarity index 100% rename from scripts/policy_agent/policy_refinement/__init__.py rename to src/smith/policy_agent/red_feedback/__init__.py diff --git a/scripts/policy_agent/red_feedback/red_feedback.py b/src/smith/policy_agent/red_feedback/red_feedback.py similarity index 100% rename from scripts/policy_agent/red_feedback/red_feedback.py rename to src/smith/policy_agent/red_feedback/red_feedback.py diff --git a/scripts/policy_agent/reduce_improve/README.md b/src/smith/policy_agent/reduce_improve/README.md similarity index 100% rename from scripts/policy_agent/reduce_improve/README.md rename to src/smith/policy_agent/reduce_improve/README.md diff --git a/scripts/policy_agent/red_feedback/__init__.py b/src/smith/policy_agent/reduce_improve/__init__.py similarity index 100% rename from scripts/policy_agent/red_feedback/__init__.py rename to src/smith/policy_agent/reduce_improve/__init__.py diff --git a/scripts/policy_agent/reduce_improve/detect_redundancy.py b/src/smith/policy_agent/reduce_improve/detect_redundancy.py similarity index 100% rename from scripts/policy_agent/reduce_improve/detect_redundancy.py rename to src/smith/policy_agent/reduce_improve/detect_redundancy.py diff --git a/scripts/policy_agent/reduce_improve/duplication.sh b/src/smith/policy_agent/reduce_improve/duplication.sh similarity index 100% rename from scripts/policy_agent/reduce_improve/duplication.sh rename to src/smith/policy_agent/reduce_improve/duplication.sh diff --git a/scripts/policy_agent/reduce_improve/graph_redundancy.txt b/src/smith/policy_agent/reduce_improve/graph_redundancy.txt similarity index 100% rename from scripts/policy_agent/reduce_improve/graph_redundancy.txt rename to src/smith/policy_agent/reduce_improve/graph_redundancy.txt diff --git a/scripts/policy_agent/red_feedback/tests/__init__.py b/src/smith/policy_agent/scripts/__init__.py similarity index 100% rename from scripts/policy_agent/red_feedback/tests/__init__.py rename to src/smith/policy_agent/scripts/__init__.py diff --git a/scripts/policy_agent/scripts/cluster_result b/src/smith/policy_agent/scripts/cluster_result similarity index 100% rename from scripts/policy_agent/scripts/cluster_result rename to src/smith/policy_agent/scripts/cluster_result diff --git a/scripts/policy_agent/scripts/commands b/src/smith/policy_agent/scripts/commands similarity index 100% rename from scripts/policy_agent/scripts/commands rename to src/smith/policy_agent/scripts/commands diff --git a/scripts/policy_agent/scripts/commands_cluster b/src/smith/policy_agent/scripts/commands_cluster similarity index 100% rename from scripts/policy_agent/scripts/commands_cluster rename to src/smith/policy_agent/scripts/commands_cluster diff --git a/scripts/policy_agent/scripts/parse_ast_to_graph.py b/src/smith/policy_agent/scripts/parse_ast_to_graph.py similarity index 100% rename from scripts/policy_agent/scripts/parse_ast_to_graph.py rename to src/smith/policy_agent/scripts/parse_ast_to_graph.py diff --git a/scripts/policy_agent/reduce_improve/__init__.py b/src/smith/policy_generation/__init__.py similarity index 100% rename from scripts/policy_agent/reduce_improve/__init__.py rename to src/smith/policy_generation/__init__.py diff --git a/scripts/policy_generation/extract_tools.py b/src/smith/policy_generation/extract_tools.py similarity index 94% rename from scripts/policy_generation/extract_tools.py rename to src/smith/policy_generation/extract_tools.py index 18b4267..da5c6ed 100644 --- a/scripts/policy_generation/extract_tools.py +++ b/src/smith/policy_generation/extract_tools.py @@ -9,15 +9,15 @@ - stdio: launches the MCP server as a subprocess (e.g., python server.py) Usage (SSE - server must be running): - python scripts/policy_generation/extract_tools.py \ + python src/smith/policy_generation/extract_tools.py \ --transport sse --url http://localhost:8000/sse \ - --output mcp_servers/RagChatbot_MCPServer/smith/tool_definitions.json + --output examples/RagChatbot_MCPServer/smith/tool_definitions.json Usage (stdio - launches server.py directly): - python scripts/policy_generation/extract_tools.py \ + python src/smith/policy_generation/extract_tools.py \ --transport stdio --command python --args server.py \ - --cwd mcp_servers/call-for-papers-mcp \ - --output mcp_servers/call-for-papers-mcp/smith/tool_definitions.json + --cwd examples/call-for-papers-mcp \ + --output examples/call-for-papers-mcp/smith/tool_definitions.json """ import json diff --git a/scripts/policy_generation/validate_policy.py b/src/smith/policy_generation/validate_policy.py similarity index 98% rename from scripts/policy_generation/validate_policy.py rename to src/smith/policy_generation/validate_policy.py index a51c6c3..5460671 100644 --- a/scripts/policy_generation/validate_policy.py +++ b/src/smith/policy_generation/validate_policy.py @@ -5,7 +5,7 @@ Validate an OPA policy file by running opa fmt and opa check. Usage: - python scripts/policy_generation/validate_policy.py --policy assets/policy_generated.rego + python src/smith/policy_generation/validate_policy.py --policy assets/policy_generated.rego """ import argparse diff --git a/scripts/policy_agent/scripts/__init__.py b/src/smith/policy_testing/__init__.py similarity index 100% rename from scripts/policy_agent/scripts/__init__.py rename to src/smith/policy_testing/__init__.py diff --git a/scripts/tests/integration/convert_test_coverage.py b/src/smith/policy_testing/convert_test_coverage.py similarity index 90% rename from scripts/tests/integration/convert_test_coverage.py rename to src/smith/policy_testing/convert_test_coverage.py index 0447b54..49566e4 100644 --- a/scripts/tests/integration/convert_test_coverage.py +++ b/src/smith/policy_testing/convert_test_coverage.py @@ -12,11 +12,17 @@ policy_dir = base_url + os.getenv("POLICY_DIR") policy_path = policy_dir + os.getenv("POLICY_PATH") -test_path = base_url + "scripts/tests/integration/" -file_path = test_path + "coverage/revised_policy.rego" -test_file_path = test_path + "coverage/policy_test.rego" -tn_command_path = test_path + "tn.txt" -tp_command_path = test_path + "tp.txt" +# Scorecard outputs live under the skill root (set by score_card.sh), never in +# the installed package directory. +out_dir = os.getenv("SMITH_SCORECARD_DIR") or os.path.join( + base_url, os.getenv("TEST_OUTPUT_DIR", "references/scorecard/") +) +out_dir = os.path.join(out_dir, "") # ensure a trailing separator +os.makedirs(os.path.join(out_dir, "coverage"), exist_ok=True) +file_path = out_dir + "coverage/revised_policy.rego" +test_file_path = out_dir + "coverage/policy_test.rego" +tn_command_path = out_dir + "tn.txt" +tp_command_path = out_dir + "tp.txt" def replace_quotes_in_json(obj, old_char="'", new_char='"'): diff --git a/scripts/tests/integration/highlight.sh b/src/smith/policy_testing/highlight.sh similarity index 100% rename from scripts/tests/integration/highlight.sh rename to src/smith/policy_testing/highlight.sh diff --git a/src/smith/policy_testing/score_card.sh b/src/smith/policy_testing/score_card.sh new file mode 100755 index 0000000..e3d6e67 --- /dev/null +++ b/src/smith/policy_testing/score_card.sh @@ -0,0 +1,165 @@ +#!/bin/bash +# Copyright 2026 Smith authors +# SPDX-License-Identifier: Apache-2.0 +# +# Run every test case under /references/test_cases/{allow,disallow} +# against a running OPA server and write a scorecard + failure list. +# +# Paths: +# - This script and its helpers ship inside the smith package (read-only): +# resolved via $CDIR. +# - All inputs (policy, test cases) and generated outputs are relative to the +# skill/repo ROOT (BASE_URL) so nothing is written into the package. +# +# Usage: score_card.sh [ROOT] [OUT_DIR] +# ROOT skill/repo root holding assets/ and references/ (default: $SMITH_ROOT or $PWD) +# OUT_DIR where to write scorecard outputs (default: $SMITH_SCORECARD_DIR or ROOT/references/scorecard) + +CDIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd) + +ROOT="${1:-${SMITH_ROOT:-$PWD}}" +ROOT="$(cd -- "$ROOT" &>/dev/null && pwd)" + +OUT_DIR="${2:-${SMITH_SCORECARD_DIR:-$ROOT/references/scorecard}}" +mkdir -p "$OUT_DIR/coverage" +export SMITH_SCORECARD_DIR="$OUT_DIR" + +OPA_URL="${SMITH_OPA_URL:-localhost:8181}" + +DIRS_TO_TEST=( + "$ROOT/references/test_cases/allow" + "$ROOT/references/test_cases/disallow" +) + +OUTPUT_FILE="$OUT_DIR/score_test_results.txt" +SCORECARD_FILE="$OUT_DIR/scorecard_summary.txt" +TEST_FAILURES_FILE="$OUT_DIR/score_test_failures.txt" +POLICY_PATH_COUNT="$ROOT/assets/policy.rego" + +>"$OUTPUT_FILE" +>"$SCORECARD_FILE" +>"$TEST_FAILURES_FILE" + +TEMP_RESULTS=$(mktemp) + +FILES=("fn.txt" "fp.txt" "tn.txt" "tp.txt") + +for f in "${FILES[@]}"; do + >"$OUT_DIR/$f" +done + +for BASE_INPUT_DIR in "${DIRS_TO_TEST[@]}"; do + find "$BASE_INPUT_DIR" -type f -name "*.json" | while read -r FILE; do + echo "Testing: $FILE" | tee -a "$OUTPUT_FILE" + if [[ "$FILE" == *"/disallow/"* ]]; then + echo -e "\t{\"expected\": {\"allow\": false}}" + EXPECTED_ALLOW="false" + else + echo -e "\t{\"expected\": {\"allow\": true}}" + EXPECTED_ALLOW="true" + fi + + RESPONSE=$(curl -s -X POST "$OPA_URL/v1/data/mcp/policies/allow" \ + -H "Content-Type: application/json" \ + --data @"$FILE") + echo "$RESPONSE" + + if [[ "$RESPONSE" == *'"result":true'* ]]; then + ALLOW="true" + else + ALLOW="false" + fi + + if [ "$EXPECTED_ALLOW" = "true" ] && [ "$ALLOW" = "true" ]; then + TARGET_TYPE="tn" + elif [ "$EXPECTED_ALLOW" = "true" ] && [ "$ALLOW" = "false" ]; then + TARGET_TYPE="fp" + elif [ "$EXPECTED_ALLOW" = "false" ] && [ "$ALLOW" = "true" ]; then + TARGET_TYPE="fn" + elif [ "$EXPECTED_ALLOW" = "false" ] && [ "$ALLOW" = "false" ]; then + TARGET_TYPE="tp" + else + echo "Unexpected combination: EXPECTED_ALLOW=$EXPECTED_ALLOW ALLOW=$ALLOW" >&2 + TARGET_TYPE="" + fi + + case "$TARGET_TYPE" in + "fn") echo "$FILE" | tee -a "$OUTPUT_FILE" >>"$OUT_DIR/fn.txt" ;; + "fp") echo "$FILE" | tee -a "$OUTPUT_FILE" >>"$OUT_DIR/fp.txt" ;; + "tn") echo "$FILE" | tee -a "$OUTPUT_FILE" >>"$OUT_DIR/tn.txt" ;; + "tp") echo "$FILE" | tee -a "$OUTPUT_FILE" >>"$OUT_DIR/tp.txt" ;; + *) echo "Unknown type: $TARGET_TYPE" ;; + esac + + if [[ "$EXPECTED_ALLOW" == "$ALLOW" ]]; then + MATCH="[PASS: expected_allow: $EXPECTED_ALLOW, allow: $ALLOW" + else + MATCH="[FAIL: expected_allow: $EXPECTED_ALLOW, allow: $ALLOW" + fi + + echo -e "\t$RESPONSE" | tee -a "$OUTPUT_FILE" + echo -e "\n-----------------------------\n" >>"$OUTPUT_FILE" + + echo "$MATCH, test_case: $FILE] $RESPONSE" >>"$TEMP_RESULTS" + done +done + +echo -e "Scorecard Summary\n===================" >>"$SCORECARD_FILE" + +ALL_DIRS=$(find "${DIRS_TO_TEST[@]}" -type f -name "*.json" | xargs -n1 dirname | sort | uniq) + +for DIR in $ALL_DIRS; do + MATCHES=$(grep -F "$DIR/" "$TEMP_RESULTS") + ALLOW_TRUE=$(echo "$MATCHES" | grep -c '"result":true') + ALLOW_FALSE=$(echo "$MATCHES" | grep -c '"result":false') + TOTAL=$((ALLOW_TRUE + ALLOW_FALSE)) + + if [[ "$DIR" == *"/disallow"* ]]; then + TITLE="Test cases that should result in a deny decision" + elif [[ "$DIR" == *"/allow"* ]]; then + TITLE="Test cases that should result in an allow decision" + else + TITLE="Unlabeled test cases" + fi + + echo "Experiment: $TITLE" >>"$SCORECARD_FILE" + echo "Directory: ${DIR#"$ROOT"}" >>"$SCORECARD_FILE" + echo "Allowed: $ALLOW_TRUE" >>"$SCORECARD_FILE" + echo "Denied: $ALLOW_FALSE" >>"$SCORECARD_FILE" + echo "Total: $TOTAL" >>"$SCORECARD_FILE" + echo "--------------------------" >>"$SCORECARD_FILE" + + FAILS=$(echo "$MATCHES" | grep '^\[FAIL') + echo "$FAILS" >>"$TEST_FAILURES_FILE" +done + +echo "===================" >>"$SCORECARD_FILE" + +# Coverage analysis is optional and requires the `opa` binary. Skip gracefully +# when it is unavailable so the primary scorecard still completes. +if command -v opa >/dev/null 2>&1; then + echo "The coverage test results are: " >>"$SCORECARD_FILE" + python "$CDIR/convert_test_coverage.py" + COVERAGE_OUTPUT=$(opa test --coverage "$OUT_DIR/coverage/revised_policy.rego" "$OUT_DIR/coverage/policy_test.rego") + echo "$COVERAGE_OUTPUT" >"$OUT_DIR/coverage.txt" + echo "$COVERAGE_OUTPUT" | tail -n 9 | head -n 3 >>"$SCORECARD_FILE" + + echo "Running detailed coverage analysis..." + bash "$CDIR/tools/analyze_coverage.sh" --root "$ROOT" --out "$OUT_DIR" >"$OUT_DIR/coverage_analysis.txt" || true +else + echo "Coverage analysis skipped (the 'opa' CLI is not installed)." >>"$SCORECARD_FILE" +fi + +echo "" +echo "Files generated under: $OUT_DIR" +echo "- scorecard_summary.txt (main scorecard)" +echo "- coverage_analysis.txt (detailed coverage report, if opa present)" +echo "" + +cat "$SCORECARD_FILE" + +rm "$TEMP_RESULTS" + +echo "===================" >>"$SCORECARD_FILE" +echo "The line number of current policy is:" >>"$SCORECARD_FILE" +wc -l <"$POLICY_PATH_COUNT" >>"$SCORECARD_FILE" diff --git a/scripts/tests/tools/analyze_coverage.sh b/src/smith/policy_testing/tools/analyze_coverage.sh similarity index 77% rename from scripts/tests/tools/analyze_coverage.sh rename to src/smith/policy_testing/tools/analyze_coverage.sh index 378ec67..0d27210 100644 --- a/scripts/tests/tools/analyze_coverage.sh +++ b/src/smith/policy_testing/tools/analyze_coverage.sh @@ -4,11 +4,12 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" - OUTPUT_FORMAT="text" SHOW_HELP=false +# Skill/repo root (holds assets/) and scorecard output dir (holds coverage data). +ROOT="${SMITH_ROOT:-$PWD}" +OUT_DIR="${SMITH_SCORECARD_DIR:-$ROOT/references/scorecard}" while [[ $# -gt 0 ]]; do @@ -25,6 +26,14 @@ while [[ $# -gt 0 ]]; do OUTPUT_FORMAT="text" shift ;; + --root) + ROOT="$2" + shift 2 + ;; + --out) + OUT_DIR="$2" + shift 2 + ;; -h|--help) SHOW_HELP=true shift @@ -80,9 +89,9 @@ if [[ "$OUTPUT_FORMAT" != "text" && "$OUTPUT_FORMAT" != "json" ]]; then fi -COVERAGE_FILE="$PROJECT_ROOT/tests/integration/coverage.txt" -REVISED_POLICY="$PROJECT_ROOT/tests/integration/coverage/revised_policy.rego" -MAIN_POLICY="$PROJECT_ROOT/policies/policy.rego" +COVERAGE_FILE="$OUT_DIR/coverage.txt" +REVISED_POLICY="$OUT_DIR/coverage/revised_policy.rego" +MAIN_POLICY="$ROOT/assets/policy.rego" if [[ ! -f "$COVERAGE_FILE" ]]; then echo "Error: Coverage file not found: $COVERAGE_FILE" @@ -100,5 +109,10 @@ if [[ ! -f "$MAIN_POLICY" ]]; then fi -cd "$PROJECT_ROOT" -python "$SCRIPT_DIR/coverage_analyzer.py" --output-format "$OUTPUT_FORMAT" --project-root "$PROJECT_ROOT" \ No newline at end of file +cd "$ROOT" +python "$SCRIPT_DIR/coverage_analyzer.py" \ + --output-format "$OUTPUT_FORMAT" \ + --project-root "$ROOT" \ + --coverage-file "$COVERAGE_FILE" \ + --revised-policy "$REVISED_POLICY" \ + --main-policy "$MAIN_POLICY" \ No newline at end of file diff --git a/scripts/tests/tools/coverage_analyzer.py b/src/smith/policy_testing/tools/coverage_analyzer.py similarity index 91% rename from scripts/tests/tools/coverage_analyzer.py rename to src/smith/policy_testing/tools/coverage_analyzer.py index a2fbd34..4cc5ec4 100644 --- a/scripts/tests/tools/coverage_analyzer.py +++ b/src/smith/policy_testing/tools/coverage_analyzer.py @@ -54,19 +54,30 @@ class CoverageAnalysis: class PolicyCoverageAnalyzer: """Analyzes OPA policy test coverage""" - def __init__(self, project_root: Path = None): + def __init__( + self, + project_root: Path = None, + coverage_file: Path = None, + revised_policy_file: Path = None, + main_policy_file: Path = None, + ): self.project_root = project_root or Path.cwd() - self.coverage_file = ( - self.project_root / "tests" / "integration" / "coverage.txt" + # Paths are passed explicitly by analyze_coverage.sh (scorecard output + # dir under the skill root); the project_root-relative values are only + # fallbacks for standalone use. + self.coverage_file = coverage_file or ( + self.project_root / "references" / "scorecard" / "coverage.txt" ) - self.revised_policy_file = ( + self.revised_policy_file = revised_policy_file or ( self.project_root - / "tests" - / "integration" + / "references" + / "scorecard" / "coverage" / "revised_policy.rego" ) - self.main_policy_file = self.project_root / "policies" / "policy.rego" + self.main_policy_file = main_policy_file or ( + self.project_root / "assets" / "policy.rego" + ) def load_coverage_data(self) -> Dict: """Load and parse coverage data from coverage.txt""" @@ -396,11 +407,19 @@ def main(): default=Path.cwd(), help="Project root directory (default: current directory)", ) + parser.add_argument("--coverage-file", type=Path, default=None) + parser.add_argument("--revised-policy", type=Path, default=None) + parser.add_argument("--main-policy", type=Path, default=None) args = parser.parse_args() try: - analyzer = PolicyCoverageAnalyzer(args.project_root) + analyzer = PolicyCoverageAnalyzer( + args.project_root, + coverage_file=args.coverage_file, + revised_policy_file=args.revised_policy, + main_policy_file=args.main_policy, + ) analysis = analyzer.analyze_coverage() report = analyzer.generate_report(analysis, args.output_format) print(report) diff --git a/scripts/policy_generation/__init__.py b/src/smith/test_case_evaluation/__init__.py similarity index 100% rename from scripts/policy_generation/__init__.py rename to src/smith/test_case_evaluation/__init__.py diff --git a/scripts/test_case_evaluation/apply_cross_validate.py b/src/smith/test_case_evaluation/apply_cross_validate.py similarity index 100% rename from scripts/test_case_evaluation/apply_cross_validate.py rename to src/smith/test_case_evaluation/apply_cross_validate.py diff --git a/scripts/test_case_evaluation/classify_guidance.py b/src/smith/test_case_evaluation/classify_guidance.py similarity index 100% rename from scripts/test_case_evaluation/classify_guidance.py rename to src/smith/test_case_evaluation/classify_guidance.py diff --git a/scripts/test_case_evaluation/cross_validate.py b/src/smith/test_case_evaluation/cross_validate.py similarity index 100% rename from scripts/test_case_evaluation/cross_validate.py rename to src/smith/test_case_evaluation/cross_validate.py diff --git a/scripts/test_case_evaluation/metrics.py b/src/smith/test_case_evaluation/metrics.py similarity index 100% rename from scripts/test_case_evaluation/metrics.py rename to src/smith/test_case_evaluation/metrics.py diff --git a/scripts/test_case_evaluation/tier1_rules.py b/src/smith/test_case_evaluation/tier1_rules.py similarity index 100% rename from scripts/test_case_evaluation/tier1_rules.py rename to src/smith/test_case_evaluation/tier1_rules.py diff --git a/scripts/test_case_evaluation/tier2_semantic.py b/src/smith/test_case_evaluation/tier2_semantic.py similarity index 100% rename from scripts/test_case_evaluation/tier2_semantic.py rename to src/smith/test_case_evaluation/tier2_semantic.py diff --git a/scripts/test_case_evaluation/tier3_llm_judge.py b/src/smith/test_case_evaluation/tier3_llm_judge.py similarity index 100% rename from scripts/test_case_evaluation/tier3_llm_judge.py rename to src/smith/test_case_evaluation/tier3_llm_judge.py diff --git a/scripts/test_case_evaluation/validate_labels.py b/src/smith/test_case_evaluation/validate_labels.py similarity index 98% rename from scripts/test_case_evaluation/validate_labels.py rename to src/smith/test_case_evaluation/validate_labels.py index ed661c7..b92d44a 100644 --- a/scripts/test_case_evaluation/validate_labels.py +++ b/src/smith/test_case_evaluation/validate_labels.py @@ -7,10 +7,10 @@ from dataclasses import dataclass, asdict from dotenv import load_dotenv -from test_case_evaluation.tier1_rules import evaluate_tier1 -from test_case_evaluation.tier2_semantic import Tier2Evaluator -from test_case_evaluation.tier3_llm_judge import LLMJudge -from test_case_evaluation.metrics import compute_metrics, print_report +from smith.test_case_evaluation.tier1_rules import evaluate_tier1 +from smith.test_case_evaluation.tier2_semantic import Tier2Evaluator +from smith.test_case_evaluation.tier3_llm_judge import LLMJudge +from smith.test_case_evaluation.metrics import compute_metrics, print_report load_dotenv() diff --git a/scripts/tests/__init__.py b/src/smith/test_case_evaluation/visualization/__init__.py similarity index 100% rename from scripts/tests/__init__.py rename to src/smith/test_case_evaluation/visualization/__init__.py diff --git a/scripts/test_case_evaluation/visualization/build_report.py b/src/smith/test_case_evaluation/visualization/build_report.py similarity index 100% rename from scripts/test_case_evaluation/visualization/build_report.py rename to src/smith/test_case_evaluation/visualization/build_report.py diff --git a/scripts/tests/integration/__init__.py b/src/smith/test_generation/__init__.py similarity index 100% rename from scripts/tests/integration/__init__.py rename to src/smith/test_generation/__init__.py diff --git a/scripts/test_generation/ares/assets/advbench_refusal_keywords.json b/src/smith/test_generation/ares/assets/advbench_refusal_keywords.json similarity index 100% rename from scripts/test_generation/ares/assets/advbench_refusal_keywords.json rename to src/smith/test_generation/ares/assets/advbench_refusal_keywords.json diff --git a/scripts/test_generation/ares/assets/human_jailbreaks.json b/src/smith/test_generation/ares/assets/human_jailbreaks.json similarity index 100% rename from scripts/test_generation/ares/assets/human_jailbreaks.json rename to src/smith/test_generation/ares/assets/human_jailbreaks.json diff --git a/scripts/test_generation/ares/example_configs/connectors.yaml b/src/smith/test_generation/ares/example_configs/connectors.yaml similarity index 100% rename from scripts/test_generation/ares/example_configs/connectors.yaml rename to src/smith/test_generation/ares/example_configs/connectors.yaml diff --git a/scripts/test_generation/ares/example_configs/evaluators.yaml b/src/smith/test_generation/ares/example_configs/evaluators.yaml similarity index 100% rename from scripts/test_generation/ares/example_configs/evaluators.yaml rename to src/smith/test_generation/ares/example_configs/evaluators.yaml diff --git a/scripts/test_generation/ares/example_configs/intents.yaml b/src/smith/test_generation/ares/example_configs/intents.yaml similarity index 100% rename from scripts/test_generation/ares/example_configs/intents.yaml rename to src/smith/test_generation/ares/example_configs/intents.yaml diff --git a/scripts/test_generation/ares/example_configs/minimal.yaml b/src/smith/test_generation/ares/example_configs/minimal.yaml similarity index 100% rename from scripts/test_generation/ares/example_configs/minimal.yaml rename to src/smith/test_generation/ares/example_configs/minimal.yaml diff --git a/scripts/test_generation/ares/example_configs/quickstart.yaml b/src/smith/test_generation/ares/example_configs/quickstart.yaml similarity index 100% rename from scripts/test_generation/ares/example_configs/quickstart.yaml rename to src/smith/test_generation/ares/example_configs/quickstart.yaml diff --git a/scripts/test_generation/ares/example_configs/qwen-owasp-llm-01.yaml b/src/smith/test_generation/ares/example_configs/qwen-owasp-llm-01.yaml similarity index 100% rename from scripts/test_generation/ares/example_configs/qwen-owasp-llm-01.yaml rename to src/smith/test_generation/ares/example_configs/qwen-owasp-llm-01.yaml diff --git a/scripts/test_generation/ares/example_configs/strategies.yaml b/src/smith/test_generation/ares/example_configs/strategies.yaml similarity index 100% rename from scripts/test_generation/ares/example_configs/strategies.yaml rename to src/smith/test_generation/ares/example_configs/strategies.yaml diff --git a/scripts/test_generation/ares_config/human_jailbreaks.json b/src/smith/test_generation/ares_config/human_jailbreaks.json similarity index 100% rename from scripts/test_generation/ares_config/human_jailbreaks.json rename to src/smith/test_generation/ares_config/human_jailbreaks.json diff --git a/scripts/test_generation/ares_config/qwen-owasp-llm-01.yaml b/src/smith/test_generation/ares_config/qwen-owasp-llm-01.yaml similarity index 100% rename from scripts/test_generation/ares_config/qwen-owasp-llm-01.yaml rename to src/smith/test_generation/ares_config/qwen-owasp-llm-01.yaml diff --git a/scripts/test_generation/attack.py b/src/smith/test_generation/attack.py similarity index 82% rename from scripts/test_generation/attack.py rename to src/smith/test_generation/attack.py index b33b96d..02a6a2f 100644 --- a/scripts/test_generation/attack.py +++ b/src/smith/test_generation/attack.py @@ -23,17 +23,22 @@ def attack( writer.writerow(header) writer.writerows(attack_targets) + # ARES is an external tool (the `ares-redteamer` package) installed into its + # own venv. Locate it via ARES_HOME, falling back to an `ares/` dir next to + # the test_generation package for in-tree installs. + ares_home = ( + os.getenv("ARES_HOME") or os.path.join(test_generation_path, "ares") + ).rstrip("/") try: - with open("ares.log", "w") as f: - # result=subprocess.run([test_generation_path+"ares/.venv/bin/python", "test.py"], cwd=test_generation_path+"ares/test_script/", stdout=f, stderr=subprocess.STDOUT, check=True) - subprocess.run( - [ - test_generation_path + "ares/.venv/bin/" + "ares", - "evaluate", - "example_configs/qwen-owasp-llm-01.yaml", - "--generate-only", - ] - ) # , stdout=f, stderr=subprocess.STDOUT, check=True) + subprocess.run( + [ + os.path.join(ares_home, ".venv", "bin", "ares"), + "evaluate", + "example_configs/qwen-owasp-llm-01.yaml", + "--generate-only", + ], + cwd=ares_home, + ) except subprocess.CalledProcessError: print("jail break partially failed") print("ATTACK FINISHED........") @@ -62,7 +67,7 @@ def attack( ] for attack_file in attack_file_list: attack_prompt_map[attack_file] = {} - file_path = test_generation_path + "ares/assets/" + attack_file + ".json" + file_path = os.path.join(ares_home, "assets", attack_file + ".json") if os.path.exists(file_path): with open(file_path, "r") as f: attack_prompts = json.load(f) diff --git a/scripts/test_generation/attack_promptfoo.py b/src/smith/test_generation/attack_promptfoo.py similarity index 100% rename from scripts/test_generation/attack_promptfoo.py rename to src/smith/test_generation/attack_promptfoo.py diff --git a/scripts/test_generation/case_generation.py b/src/smith/test_generation/case_generation.py similarity index 98% rename from scripts/test_generation/case_generation.py rename to src/smith/test_generation/case_generation.py index 40ea5de..e29088b 100644 --- a/scripts/test_generation/case_generation.py +++ b/src/smith/test_generation/case_generation.py @@ -1,15 +1,12 @@ # Copyright 2026 Smith authors # SPDX-License-Identifier: Apache-2.0 -import os import json import re import httpx from openai import OpenAI from dotenv import load_dotenv -import sys -sys.path.insert(0, os.path.join(os.path.dirname(__file__), "../../..")) load_dotenv() diff --git a/scripts/test_generation/convert_test_case.py b/src/smith/test_generation/convert_test_case.py similarity index 98% rename from scripts/test_generation/convert_test_case.py rename to src/smith/test_generation/convert_test_case.py index 0e1a0a3..a51ee92 100644 --- a/scripts/test_generation/convert_test_case.py +++ b/src/smith/test_generation/convert_test_case.py @@ -4,9 +4,7 @@ import json import os from dotenv import load_dotenv -import sys -sys.path.insert(0, os.path.join(os.path.dirname(__file__), "../../..")) load_dotenv() diff --git a/scripts/test_generation/decompose.py b/src/smith/test_generation/decompose.py similarity index 99% rename from scripts/test_generation/decompose.py rename to src/smith/test_generation/decompose.py index eff3afc..746d978 100644 --- a/scripts/test_generation/decompose.py +++ b/src/smith/test_generation/decompose.py @@ -7,9 +7,7 @@ import httpx from openai import OpenAI from dotenv import load_dotenv -import sys -sys.path.insert(0, os.path.join(os.path.dirname(__file__), "../../..")) load_dotenv() diff --git a/scripts/test_generation/extract_tool_args.py b/src/smith/test_generation/extract_tool_args.py similarity index 100% rename from scripts/test_generation/extract_tool_args.py rename to src/smith/test_generation/extract_tool_args.py diff --git a/scripts/test_generation/grey_condition.py b/src/smith/test_generation/grey_condition.py similarity index 98% rename from scripts/test_generation/grey_condition.py rename to src/smith/test_generation/grey_condition.py index b3a5554..7b652bb 100644 --- a/scripts/test_generation/grey_condition.py +++ b/src/smith/test_generation/grey_condition.py @@ -1,15 +1,12 @@ # Copyright 2026 Smith authors # SPDX-License-Identifier: Apache-2.0 -import os import json import re import httpx from openai import OpenAI from dotenv import load_dotenv -import sys -sys.path.insert(0, os.path.join(os.path.dirname(__file__), "../../..")) load_dotenv() diff --git a/scripts/test_generation/promptfoo/.gitkeep b/src/smith/test_generation/promptfoo/.gitkeep similarity index 100% rename from scripts/test_generation/promptfoo/.gitkeep rename to src/smith/test_generation/promptfoo/.gitkeep diff --git a/scripts/test_generation/variable_extraction.py b/src/smith/test_generation/variable_extraction.py similarity index 98% rename from scripts/test_generation/variable_extraction.py rename to src/smith/test_generation/variable_extraction.py index 6cd6541..cc2f757 100644 --- a/scripts/test_generation/variable_extraction.py +++ b/src/smith/test_generation/variable_extraction.py @@ -1,15 +1,12 @@ # Copyright 2026 Smith authors # SPDX-License-Identifier: Apache-2.0 -import os import json import re import httpx from openai import OpenAI from dotenv import load_dotenv -import sys -sys.path.insert(0, os.path.join(os.path.dirname(__file__), "../../..")) load_dotenv() diff --git a/scripts/tools/license_headers.py b/src/smith/tools/license_headers.py similarity index 88% rename from scripts/tools/license_headers.py rename to src/smith/tools/license_headers.py index 9f2196b..a7d93c5 100644 --- a/scripts/tools/license_headers.py +++ b/src/smith/tools/license_headers.py @@ -13,15 +13,15 @@ declaration. Files that already carry an ``SPDX-License-Identifier`` line are left untouched, so the tool is idempotent. -Scope (see ``INCLUDE_*``/``EXCLUDE_DIRS`` below): Smith core only — ``scripts/`` +Scope (see ``INCLUDE_*``/``EXCLUDE_DIRS`` below): Smith core only — ``src/smith/`` (excluding the vendored ARES tree), ``assets/`` (excluding generated OPA outputs), and root configs. Generated artifacts (``references/``, -``assets/opa/outputs/``) and the ``mcp_servers/`` example agents (which bundle +``assets/opa/outputs/``) and the ``examples/`` example agents (which bundle third-party-derived MCP server code) are excluded. Usage: - python scripts/tools/license_headers.py --check # exit 1 if any file lacks a header - python scripts/tools/license_headers.py --fix # insert missing headers in place + python src/smith/tools/license_headers.py --check # exit 1 if any file lacks a header + python src/smith/tools/license_headers.py --fix # insert missing headers in place """ from __future__ import annotations @@ -35,8 +35,9 @@ HEADER_LINES = [COPYRIGHT, SPDX] SPDX_MARKER = "SPDX-License-Identifier" -# Repository root, derived from this file's location: scripts/tools/ -> repo root. -REPO_ROOT = Path(__file__).resolve().parents[2] +# Repository root, derived from this file's location: +# src/smith/tools/license_headers.py -> parents[3] is the repo root. +REPO_ROOT = Path(__file__).resolve().parents[3] # File extensions that get a header (all use "#" comments). INCLUDE_EXTENSIONS = {".py", ".rego", ".sh", ".yaml", ".yml"} @@ -56,13 +57,13 @@ "build", "dist", ".eggs", - "scripts/test_generation/ares", # vendored ARES (separate upstream) + "src/smith/test_generation/ares", # vendored ARES inputs (separate upstream) "references", # generated pipeline artifacts "assets/opa/outputs", # generated OPA intermediates - # The example agents under mcp_servers/ bundle third-party-derived MCP server + # The example agents under examples/ bundle third-party-derived MCP server # code (e.g. call-for-papers-mcp ships an upstream MIT license), so Smith does # not stamp its Apache header on them. Only Smith core is headered. - "mcp_servers", + "examples", ) diff --git a/test_generation/cross_validate.md b/test_generation/cross_validate.md index ac386cb..c6da70f 100644 --- a/test_generation/cross_validate.md +++ b/test_generation/cross_validate.md @@ -61,7 +61,7 @@ The remaining failures should now only be genuine policy issues (not mislabeled ## File Reference -- **Input**: `scripts/tests/integration/score_test_failures.txt` (from last `policy_testing` run) +- **Input**: `references/scorecard/score_test_failures.txt` (from last `policy_testing` run) - **Report**: `references/cross_validate_report.json` (generated by `cross_validate`, editable by user) - **Action**: `smith --flag apply_cross_validate` reads the report and moves/removes files diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 0000000..c6a7fab --- /dev/null +++ b/tests/README.md @@ -0,0 +1,8 @@ +# Tests + +Proper unit/integration tests are TODO. The previous pytest suite was +removed during the `scripts/` → `src/smith/` refactor because it only +covered removed code and external (kubectl/mcpgateway) plugins. + +The OPA policy scorecard harness lives in `src/smith/policy_testing/` and is +run via `make test` / `smith --flag policy_testing`. diff --git a/uv.lock b/uv.lock new file mode 100644 index 0000000..5d55775 --- /dev/null +++ b/uv.lock @@ -0,0 +1,3471 @@ +version = 1 +revision = 3 +requires-python = ">=3.11" +resolution-markers = [ + "python_full_version >= '3.14' and sys_platform == 'win32'", + "python_full_version >= '3.14' and sys_platform != 'win32'", + "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'win32'", + "python_full_version < '3.12' and sys_platform == 'win32'", + "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform != 'win32'", + "python_full_version < '3.12' and sys_platform != 'win32'", +] + +[[package]] +name = "annotated-doc" +version = "0.0.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/57/ba/046ceea27344560984e26a590f90bc7f4a75b06701f653222458922b558c/annotated_doc-0.0.4.tar.gz", hash = "sha256:fbcda96e87e9c92ad167c2e53839e57503ecfda18804ea28102353485033faa4", size = 7288, upload-time = "2025-11-10T22:07:42.062Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl", hash = "sha256:571ac1dc6991c450b25a9c2d84a3705e2ae7a53467b5d111c24fa8baabbed320", size = 5303, upload-time = "2025-11-10T22:07:40.673Z" }, +] + +[[package]] +name = "annotated-types" +version = "0.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081, upload-time = "2024-05-20T21:33:25.928Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643, upload-time = "2024-05-20T21:33:24.1Z" }, +] + +[[package]] +name = "anyio" +version = "4.14.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "idna" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/3b/72/5562aabb8dd7181e8e860622a38bea08d17842b99ecd4c91f84ac95251b0/anyio-4.14.1.tar.gz", hash = "sha256:8d648a3544c1a700e3ff78615cd679e4c5c3f149904287e73687b2596963629e", size = 254831, upload-time = "2026-06-24T20:56:06.017Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b0/7b/90df4a0a816d98d6ea26f559d87836d494a2cf1fcf063be67df50a7bcc30/anyio-4.14.1-py3-none-any.whl", hash = "sha256:4e5533c5b8ff0a24f5d7a176cbe6877129cd183893f66b537f8f227d10527d72", size = 124875, upload-time = "2026-06-24T20:56:04.413Z" }, +] + +[[package]] +name = "attrs" +version = "26.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/9a/8e/82a0fe20a541c03148528be8cac2408564a6c9a0cc7e9171802bc1d26985/attrs-26.1.0.tar.gz", hash = "sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32", size = 952055, upload-time = "2026-03-19T14:22:25.026Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/64/b4/17d4b0b2a2dc85a6df63d1157e028ed19f90d4cd97c36717afef2bc2f395/attrs-26.1.0-py3-none-any.whl", hash = "sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309", size = 67548, upload-time = "2026-03-19T14:22:23.645Z" }, +] + +[[package]] +name = "backports-tarfile" +version = "1.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/86/72/cd9b395f25e290e633655a100af28cb253e4393396264a98bd5f5951d50f/backports_tarfile-1.2.0.tar.gz", hash = "sha256:d75e02c268746e1b8144c278978b6e98e85de6ad16f8e4b0844a154557eca991", size = 86406, upload-time = "2024-05-28T17:01:54.731Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b9/fa/123043af240e49752f1c4bd24da5053b6bd00cad78c2be53c0d1e8b975bc/backports.tarfile-1.2.0-py3-none-any.whl", hash = "sha256:77e284d754527b01fb1e6fa8a1afe577858ebe4e9dad8919e34c862cb399bc34", size = 30181, upload-time = "2024-05-28T17:01:53.112Z" }, +] + +[[package]] +name = "black" +version = "26.5.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "mypy-extensions" }, + { name = "packaging" }, + { name = "pathspec" }, + { name = "platformdirs" }, + { name = "pytokens" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c0/37/5628dd55bf2b34257fc7603f0fe97c40e3aaf24265f416a9c85c95ca1436/black-26.5.1.tar.gz", hash = "sha256:dd321f668053961824bcc1be1cc1df748b2d7e4fa28086b08331e577b0100a73", size = 679439, upload-time = "2026-05-18T16:53:36.107Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4b/96/3c3e09f09f44a37aac36b178a279cd19aa7001bd796187a7b162a294c81f/black-26.5.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:96ae2c733b2aabdd9986e2c5df628ff3473676cd1c5faded1ff496cf6d74083c", size = 1970639, upload-time = "2026-05-18T17:05:11.461Z" }, + { url = "https://files.pythonhosted.org/packages/83/ea/5ad117b9ee3ecd933c712bcbae610006e5b7cc9f41c526cd7ed3b6c4124c/black-26.5.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0e48b87e03bf109288e55cfceadcfa15ff5470aca2851a851950ed2926f450d7", size = 1792130, upload-time = "2026-05-18T17:05:12.983Z" }, + { url = "https://files.pythonhosted.org/packages/06/3a/7c448bc623fcdfa96672531beb5a616ea5e64f6975955254d7731ffb0ad9/black-26.5.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5119fa92ae61f786e8c3662fd60aece1d0a2dd5cca5d0c79417a95e7a4272a59", size = 1846134, upload-time = "2026-05-18T17:05:14.506Z" }, + { url = "https://files.pythonhosted.org/packages/a1/5b/0b39b3a5917f0657ac014ad2edb58c139553a478adfe7f817abf1622ff6e/black-26.5.1-cp311-cp311-win_amd64.whl", hash = "sha256:30d3c14661f2792e9142cce3eeeb1cbc175b3eb5f733be0c8eeb99651e52b0c3", size = 1478883, upload-time = "2026-05-18T17:05:16.542Z" }, + { url = "https://files.pythonhosted.org/packages/4c/48/dc222692e0f95030db1bbfb6c857e76858bad09058221ea7aae815255327/black-26.5.1-cp311-cp311-win_arm64.whl", hash = "sha256:1ef92b76f7733f282fd096ea406200b5a286c42947412b0eaff3a74e3616cefe", size = 1277776, upload-time = "2026-05-18T17:05:18.029Z" }, + { url = "https://files.pythonhosted.org/packages/24/99/7744b906703228264ef73bdd534df88ec1ef3de45c4e78f6d31b9e32d0c9/black-26.5.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4ad6fa01f941920f54f2bbb35f3df7673428a0ef98a0b0840c2eaef3b110efa8", size = 2012518, upload-time = "2026-05-18T17:05:20.108Z" }, + { url = "https://files.pythonhosted.org/packages/b7/c0/c5a3b1636dfd09c42534f2b3cf33506814f6d3e066fb0879ffa16c1ae860/black-26.5.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3915f256e75a2d7cf88d8953d37f780455dc586cc72dee059c528fe77f581217", size = 1816016, upload-time = "2026-05-18T17:05:21.84Z" }, + { url = "https://files.pythonhosted.org/packages/1f/0e/36044316b65ca471d3bb6d3703fd06fb50c6b727c3562f6a5a3153634f88/black-26.5.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9d98d4137277c75dfb898ec8d846c4fd68ba1e9cf77f95e2865c203dc18f4c3d", size = 1884150, upload-time = "2026-05-18T17:05:23.546Z" }, + { url = "https://files.pythonhosted.org/packages/b3/33/dafc5808c2af43672912111d7c3354af1615f7e2be3bed7a878461abbe4d/black-26.5.1-cp312-cp312-win_amd64.whl", hash = "sha256:a1dca32d9f1784af512a13410ec204c6f7f0aa9797a111c42e1c03449821c264", size = 1486825, upload-time = "2026-05-18T17:05:25.004Z" }, + { url = "https://files.pythonhosted.org/packages/82/14/b965ee6ad2a311f28bdbf692def3ee9848d2ae289dab28b27657fcee3e78/black-26.5.1-cp312-cp312-win_arm64.whl", hash = "sha256:1037d5ac7b7b310b2632ad867ec8d0e4c4819dcdb0b820f63135da746a24e418", size = 1288646, upload-time = "2026-05-18T17:05:26.477Z" }, + { url = "https://files.pythonhosted.org/packages/3f/5c/c384363980e11e25ca6b93205949bb331fbf35f4e0dbec376dfa6326cec8/black-26.5.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:2b36cf2ddf5566e205f6535f782a62194a184d33e175b64ae8c40b1737522be3", size = 2009020, upload-time = "2026-05-18T17:05:28.132Z" }, + { url = "https://files.pythonhosted.org/packages/0b/df/9f31c5e0babbfed77d505fc5d120beb98b21b33feaeded3924ea941fe360/black-26.5.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1f7ea64ebfa01b50f693508fc39f875e264446d3b097088f84f203b9d09618a0", size = 1813335, upload-time = "2026-05-18T17:05:31.266Z" }, + { url = "https://files.pythonhosted.org/packages/fb/24/8e7b9a2fa61b0afd82209efe937557d180a1fa055bd7f6161eb9defc3719/black-26.5.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ecb3e624844c798144e9bd986954e0adc81d8911a1f30f375e1252fe26e8c294", size = 1881614, upload-time = "2026-05-18T17:05:32.718Z" }, + { url = "https://files.pythonhosted.org/packages/49/ad/b4e0d9365ba8ac34f6bbab62a4b1b2dd5d618fac3fa1b8db968c844201b5/black-26.5.1-cp313-cp313-win_amd64.whl", hash = "sha256:e1a26503279b6b310669fb0b219c39e4820b77e8189fe80f522bb511f247db0a", size = 1488925, upload-time = "2026-05-18T17:05:34.259Z" }, + { url = "https://files.pythonhosted.org/packages/a1/4b/652b859bf5df88a751c30451b09338f7fd26a77d1271c666992f836b7711/black-26.5.1-cp313-cp313-win_arm64.whl", hash = "sha256:5c34b25da232ead53a6f335b76dbea124f4d152ad568b9080d6f944bc2b34b52", size = 1289883, upload-time = "2026-05-18T17:05:36.019Z" }, + { url = "https://files.pythonhosted.org/packages/a6/16/a8da8eb208c51c7f4ce74609a45d0dcc6d8a2141e45e81ee5289d1bb0d59/black-26.5.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:e88976690a64b0af98312ca958415849cb42423423c5f2ee74af4b49a97a2168", size = 2004800, upload-time = "2026-05-18T17:05:38.182Z" }, + { url = "https://files.pythonhosted.org/packages/11/8a/a479296a19e383b70a725882a6cf3d786540601ff03cabbaaf1cce864c5a/black-26.5.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:32d5ea7f6c8bdfa6e648326ebca1f02b0764e2a029edc6f8dce2627e19d468c3", size = 1815576, upload-time = "2026-05-18T17:05:40.309Z" }, + { url = "https://files.pythonhosted.org/packages/81/6b/cfaf3d39f25132c156a068f6b805576c9103a84086019507c70e1911ee7d/black-26.5.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ea8d16dc41655aa113cd64665e7219446cd7e4ff2248d7178eaa905190c86b18", size = 1877927, upload-time = "2026-05-18T17:05:42.463Z" }, + { url = "https://files.pythonhosted.org/packages/66/76/302e313964bcff7e28df329d39f84f5270095730d85ff0acc260610a0d82/black-26.5.1-cp314-cp314-win_amd64.whl", hash = "sha256:577f21094ea469ef92ec1adaf2c9441a226d2144d01a5be2fa823cecf6543e50", size = 1511860, upload-time = "2026-05-18T17:05:43.943Z" }, + { url = "https://files.pythonhosted.org/packages/27/4e/a3827e35e0e567f9f9ee59e2a0ab979267dca98718f25547ca8c6733afd4/black-26.5.1-cp314-cp314-win_arm64.whl", hash = "sha256:ed1a20af114c301a0269bf01163d51dbef72737fd65f850001e7cbe7f3c7abae", size = 1316632, upload-time = "2026-05-18T17:05:45.521Z" }, + { url = "https://files.pythonhosted.org/packages/94/51/f975cae76d44274cc2868dc9040ac5d58d464784610234455b4e7b19c6ef/black-26.5.1-py3-none-any.whl", hash = "sha256:4ed7f7da04046d2e488437170797d3b4a4ad83906683bcb7dfc68b673bbce5e2", size = 213693, upload-time = "2026-05-18T16:53:33.964Z" }, +] + +[[package]] +name = "boolean-py" +version = "5.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c4/cf/85379f13b76f3a69bca86b60237978af17d6aa0bc5998978c3b8cf05abb2/boolean_py-5.0.tar.gz", hash = "sha256:60cbc4bad079753721d32649545505362c754e121570ada4658b852a3a318d95", size = 37047, upload-time = "2025-04-03T10:39:49.734Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e5/ca/78d423b324b8d77900030fa59c4aa9054261ef0925631cd2501dd015b7b7/boolean_py-5.0-py3-none-any.whl", hash = "sha256:ef28a70bd43115208441b53a045d1549e2f0ec6e3d08a9d142cbc41c1938e8d9", size = 26577, upload-time = "2025-04-03T10:39:48.449Z" }, +] + +[[package]] +name = "build" +version = "1.5.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "os_name == 'nt'" }, + { name = "packaging" }, + { name = "pyproject-hooks" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/78/e0/df5e171f685f82f37b12e1f208064e24244911079d7b767447d1af7e0d70/build-1.5.0.tar.gz", hash = "sha256:302c22c3ba2a0fd5f3911918651341ebb3896176cbdec15bd421f80b1afc7647", size = 89796, upload-time = "2026-04-30T03:18:25.17Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0d/fe/6bea5c9162869c5beba5d9c8abbed835ec85bf1ec1fba05a3822325c45f3/build-1.5.0-py3-none-any.whl", hash = "sha256:13f3eecb844759ab66efec90ca17639bbf14dc06cb2fdf37a9010322d9c50a6f", size = 26018, upload-time = "2026-04-30T03:18:23.644Z" }, +] + +[[package]] +name = "cachecontrol" +version = "0.14.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "msgpack" }, + { name = "requests" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/2d/f6/c972b32d80760fb79d6b9eeb0b3010a46b89c0b23cf6329417ff7886cd22/cachecontrol-0.14.4.tar.gz", hash = "sha256:e6220afafa4c22a47dd0badb319f84475d79108100d04e26e8542ef7d3ab05a1", size = 16150, upload-time = "2025-11-14T04:32:13.138Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ef/79/c45f2d53efe6ada1110cf6f9fca095e4ff47a0454444aefdde6ac4789179/cachecontrol-0.14.4-py3-none-any.whl", hash = "sha256:b7ac014ff72ee199b5f8af1de29d60239954f223e948196fa3d84adaffc71d2b", size = 22247, upload-time = "2025-11-14T04:32:11.733Z" }, +] + +[package.optional-dependencies] +filecache = [ + { name = "filelock" }, +] + +[[package]] +name = "certifi" +version = "2026.6.17" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c9/c7/424b75da314c1045981bd9777432fad05a9e0c69daa4ed7e308bbaffe405/certifi-2026.6.17.tar.gz", hash = "sha256:024c88eeec92ca068db80f02b8b07c9cef7b9fe261d1d535abfd5abd6f6af432", size = 134594, upload-time = "2026-06-17T10:31:07.894Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ef/2f/c5464532e965badff2f4c4c1a3a83f5697f0d7c407ed0cda44aaa99bb451/certifi-2026.6.17-py3-none-any.whl", hash = "sha256:2227dcbaafe0d2f59279d1762ddddc37783ed4354594f194ffc31d20f41fc3db", size = 133289, upload-time = "2026-06-17T10:31:06.348Z" }, +] + +[[package]] +name = "cffi" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pycparser", marker = "implementation_name != 'PyPy'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/eb/56/b1ba7935a17738ae8453301356628e8147c79dbb825bcbc73dc7401f9846/cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529", size = 523588, upload-time = "2025-09-08T23:24:04.541Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/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 = "charset-normalizer" +version = "3.4.7" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e7/a1/67fe25fac3c7642725500a3f6cfe5821ad557c3abb11c9d20d12c7008d3e/charset_normalizer-3.4.7.tar.gz", hash = "sha256:ae89db9e5f98a11a4bf50407d4363e7b09b31e55bc117b4f7d80aab97ba009e5", size = 144271, upload-time = "2026-04-02T09:28:39.342Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c2/d7/b5b7020a0565c2e9fa8c09f4b5fa6232feb326b8c20081ccded47ea368fd/charset_normalizer-3.4.7-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7641bb8895e77f921102f72833904dcd9901df5d6d72a2ab8f31d04b7e51e4e7", size = 309705, upload-time = "2026-04-02T09:26:02.191Z" }, + { url = "https://files.pythonhosted.org/packages/5a/53/58c29116c340e5456724ecd2fff4196d236b98f3da97b404bc5e51ac3493/charset_normalizer-3.4.7-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:202389074300232baeb53ae2569a60901f7efadd4245cf3a3bf0617d60b439d7", size = 206419, upload-time = "2026-04-02T09:26:03.583Z" }, + { url = "https://files.pythonhosted.org/packages/b2/02/e8146dc6591a37a00e5144c63f29fb7c97a734ea8a111190783c0e60ab63/charset_normalizer-3.4.7-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:30b8d1d8c52a48c2c5690e152c169b673487a2a58de1ec7393196753063fcd5e", size = 227901, upload-time = "2026-04-02T09:26:04.738Z" }, + { url = "https://files.pythonhosted.org/packages/fb/73/77486c4cd58f1267bf17db420e930c9afa1b3be3fe8c8b8ebbebc9624359/charset_normalizer-3.4.7-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:532bc9bf33a68613fd7d65e4b1c71a6a38d7d42604ecf239c77392e9b4e8998c", size = 222742, upload-time = "2026-04-02T09:26:06.36Z" }, + { url = "https://files.pythonhosted.org/packages/a1/fa/f74eb381a7d94ded44739e9d94de18dc5edc9c17fb8c11f0a6890696c0a9/charset_normalizer-3.4.7-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2fe249cb4651fd12605b7288b24751d8bfd46d35f12a20b1ba33dea122e690df", size = 214061, upload-time = "2026-04-02T09:26:08.347Z" }, + { url = "https://files.pythonhosted.org/packages/dc/92/42bd3cefcf7687253fb86694b45f37b733c97f59af3724f356fa92b8c344/charset_normalizer-3.4.7-cp311-cp311-manylinux_2_31_armv7l.whl", hash = "sha256:65bcd23054beab4d166035cabbc868a09c1a49d1efe458fe8e4361215df40265", size = 199239, upload-time = "2026-04-02T09:26:09.823Z" }, + { url = "https://files.pythonhosted.org/packages/4c/3d/069e7184e2aa3b3cddc700e3dd267413dc259854adc3380421c805c6a17d/charset_normalizer-3.4.7-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:08e721811161356f97b4059a9ba7bafb23ea5ee2255402c42881c214e173c6b4", size = 210173, upload-time = "2026-04-02T09:26:10.953Z" }, + { url = "https://files.pythonhosted.org/packages/62/51/9d56feb5f2e7074c46f93e0ebdbe61f0848ee246e2f0d89f8e20b89ebb8f/charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e060d01aec0a910bdccb8be71faf34e7799ce36950f8294c8bf612cba65a2c9e", size = 209841, upload-time = "2026-04-02T09:26:12.142Z" }, + { url = "https://files.pythonhosted.org/packages/d2/59/893d8f99cc4c837dda1fe2f1139079703deb9f321aabcb032355de13b6c7/charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:38c0109396c4cfc574d502df99742a45c72c08eff0a36158b6f04000043dbf38", size = 200304, upload-time = "2026-04-02T09:26:13.711Z" }, + { url = "https://files.pythonhosted.org/packages/7d/1d/ee6f3be3464247578d1ed5c46de545ccc3d3ff933695395c402c21fa6b77/charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:1c2a768fdd44ee4a9339a9b0b130049139b8ce3c01d2ce09f67f5a68048d477c", size = 229455, upload-time = "2026-04-02T09:26:14.941Z" }, + { url = "https://files.pythonhosted.org/packages/54/bb/8fb0a946296ea96a488928bdce8ef99023998c48e4713af533e9bb98ef07/charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:1a87ca9d5df6fe460483d9a5bbf2b18f620cbed41b432e2bddb686228282d10b", size = 210036, upload-time = "2026-04-02T09:26:16.478Z" }, + { url = "https://files.pythonhosted.org/packages/9a/bc/015b2387f913749f82afd4fcba07846d05b6d784dd16123cb66860e0237d/charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:d635aab80466bc95771bb78d5370e74d36d1fe31467b6b29b8b57b2a3cd7d22c", size = 224739, upload-time = "2026-04-02T09:26:17.751Z" }, + { url = "https://files.pythonhosted.org/packages/17/ab/63133691f56baae417493cba6b7c641571a2130eb7bceba6773367ab9ec5/charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ae196f021b5e7c78e918242d217db021ed2a6ace2bc6ae94c0fc596221c7f58d", size = 216277, upload-time = "2026-04-02T09:26:18.981Z" }, + { url = "https://files.pythonhosted.org/packages/06/6d/3be70e827977f20db77c12a97e6a9f973631a45b8d186c084527e53e77a4/charset_normalizer-3.4.7-cp311-cp311-win32.whl", hash = "sha256:adb2597b428735679446b46c8badf467b4ca5f5056aae4d51a19f9570301b1ad", size = 147819, upload-time = "2026-04-02T09:26:20.295Z" }, + { url = "https://files.pythonhosted.org/packages/20/d9/5f67790f06b735d7c7637171bbfd89882ad67201891b7275e51116ed8207/charset_normalizer-3.4.7-cp311-cp311-win_amd64.whl", hash = "sha256:8e385e4267ab76874ae30db04c627faaaf0b509e1ccc11a95b3fc3e83f855c00", size = 159281, upload-time = "2026-04-02T09:26:21.74Z" }, + { url = "https://files.pythonhosted.org/packages/ca/83/6413f36c5a34afead88ce6f66684d943d91f233d76dd083798f9602b75ae/charset_normalizer-3.4.7-cp311-cp311-win_arm64.whl", hash = "sha256:d4a48e5b3c2a489fae013b7589308a40146ee081f6f509e047e0e096084ceca1", size = 147843, upload-time = "2026-04-02T09:26:22.901Z" }, + { url = "https://files.pythonhosted.org/packages/0c/eb/4fc8d0a7110eb5fc9cc161723a34a8a6c200ce3b4fbf681bc86feee22308/charset_normalizer-3.4.7-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:eca9705049ad3c7345d574e3510665cb2cf844c2f2dcfe675332677f081cbd46", size = 311328, upload-time = "2026-04-02T09:26:24.331Z" }, + { url = "https://files.pythonhosted.org/packages/f8/e3/0fadc706008ac9d7b9b5be6dc767c05f9d3e5df51744ce4cc9605de7b9f4/charset_normalizer-3.4.7-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6178f72c5508bfc5fd446a5905e698c6212932f25bcdd4b47a757a50605a90e2", size = 208061, upload-time = "2026-04-02T09:26:25.568Z" }, + { url = "https://files.pythonhosted.org/packages/42/f0/3dd1045c47f4a4604df85ec18ad093912ae1344ac706993aff91d38773a2/charset_normalizer-3.4.7-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e1421b502d83040e6d7fb2fb18dff63957f720da3d77b2fbd3187ceb63755d7b", size = 229031, upload-time = "2026-04-02T09:26:26.865Z" }, + { url = "https://files.pythonhosted.org/packages/dc/67/675a46eb016118a2fbde5a277a5d15f4f69d5f3f5f338e5ee2f8948fcf43/charset_normalizer-3.4.7-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:edac0f1ab77644605be2cbba52e6b7f630731fc42b34cb0f634be1a6eface56a", size = 225239, upload-time = "2026-04-02T09:26:28.044Z" }, + { url = "https://files.pythonhosted.org/packages/4b/f8/d0118a2f5f23b02cd166fa385c60f9b0d4f9194f574e2b31cef350ad7223/charset_normalizer-3.4.7-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5649fd1c7bade02f320a462fdefd0b4bd3ce036065836d4f42e0de958038e116", size = 216589, upload-time = "2026-04-02T09:26:29.239Z" }, + { url = "https://files.pythonhosted.org/packages/b1/f1/6d2b0b261b6c4ceef0fcb0d17a01cc5bc53586c2d4796fa04b5c540bc13d/charset_normalizer-3.4.7-cp312-cp312-manylinux_2_31_armv7l.whl", hash = "sha256:203104ed3e428044fd943bc4bf45fa73c0730391f9621e37fe39ecf477b128cb", size = 202733, upload-time = "2026-04-02T09:26:30.5Z" }, + { url = "https://files.pythonhosted.org/packages/6f/c0/7b1f943f7e87cc3db9626ba17807d042c38645f0a1d4415c7a14afb5591f/charset_normalizer-3.4.7-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:298930cec56029e05497a76988377cbd7457ba864beeea92ad7e844fe74cd1f1", size = 212652, upload-time = "2026-04-02T09:26:31.709Z" }, + { url = "https://files.pythonhosted.org/packages/38/dd/5a9ab159fe45c6e72079398f277b7d2b523e7f716acc489726115a910097/charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:708838739abf24b2ceb208d0e22403dd018faeef86ddac04319a62ae884c4f15", size = 211229, upload-time = "2026-04-02T09:26:33.282Z" }, + { url = "https://files.pythonhosted.org/packages/d5/ff/531a1cad5ca855d1c1a8b69cb71abfd6d85c0291580146fda7c82857caa1/charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:0f7eb884681e3938906ed0434f20c63046eacd0111c4ba96f27b76084cd679f5", size = 203552, upload-time = "2026-04-02T09:26:34.845Z" }, + { url = "https://files.pythonhosted.org/packages/c1/4c/a5fb52d528a8ca41f7598cb619409ece30a169fbdf9cdce592e53b46c3a6/charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:4dc1e73c36828f982bfe79fadf5919923f8a6f4df2860804db9a98c48824ce8d", size = 230806, upload-time = "2026-04-02T09:26:36.152Z" }, + { url = "https://files.pythonhosted.org/packages/59/7a/071feed8124111a32b316b33ae4de83d36923039ef8cf48120266844285b/charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:aed52fea0513bac0ccde438c188c8a471c4e0f457c2dd20cdbf6ea7a450046c7", size = 212316, upload-time = "2026-04-02T09:26:37.672Z" }, + { url = "https://files.pythonhosted.org/packages/fd/35/f7dba3994312d7ba508e041eaac39a36b120f32d4c8662b8814dab876431/charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:fea24543955a6a729c45a73fe90e08c743f0b3334bbf3201e6c4bc1b0c7fa464", size = 227274, upload-time = "2026-04-02T09:26:38.93Z" }, + { url = "https://files.pythonhosted.org/packages/8a/2d/a572df5c9204ab7688ec1edc895a73ebded3b023bb07364710b05dd1c9be/charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:bb6d88045545b26da47aa879dd4a89a71d1dce0f0e549b1abcb31dfe4a8eac49", size = 218468, upload-time = "2026-04-02T09:26:40.17Z" }, + { url = "https://files.pythonhosted.org/packages/86/eb/890922a8b03a568ca2f336c36585a4713c55d4d67bf0f0c78924be6315ca/charset_normalizer-3.4.7-cp312-cp312-win32.whl", hash = "sha256:2257141f39fe65a3fdf38aeccae4b953e5f3b3324f4ff0daf9f15b8518666a2c", size = 148460, upload-time = "2026-04-02T09:26:41.416Z" }, + { url = "https://files.pythonhosted.org/packages/35/d9/0e7dffa06c5ab081f75b1b786f0aefc88365825dfcd0ac544bdb7b2b6853/charset_normalizer-3.4.7-cp312-cp312-win_amd64.whl", hash = "sha256:5ed6ab538499c8644b8a3e18debabcd7ce684f3fa91cf867521a7a0279cab2d6", size = 159330, upload-time = "2026-04-02T09:26:42.554Z" }, + { url = "https://files.pythonhosted.org/packages/9e/5d/481bcc2a7c88ea6b0878c299547843b2521ccbc40980cb406267088bc701/charset_normalizer-3.4.7-cp312-cp312-win_arm64.whl", hash = "sha256:56be790f86bfb2c98fb742ce566dfb4816e5a83384616ab59c49e0604d49c51d", size = 147828, upload-time = "2026-04-02T09:26:44.075Z" }, + { url = "https://files.pythonhosted.org/packages/c1/3b/66777e39d3ae1ddc77ee606be4ec6d8cbd4c801f65e5a1b6f2b11b8346dd/charset_normalizer-3.4.7-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:f496c9c3cc02230093d8330875c4c3cdfc3b73612a5fd921c65d39cbcef08063", size = 309627, upload-time = "2026-04-02T09:26:45.198Z" }, + { url = "https://files.pythonhosted.org/packages/2e/4e/b7f84e617b4854ade48a1b7915c8ccfadeba444d2a18c291f696e37f0d3b/charset_normalizer-3.4.7-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0ea948db76d31190bf08bd371623927ee1339d5f2a0b4b1b4a4439a65298703c", size = 207008, upload-time = "2026-04-02T09:26:46.824Z" }, + { url = "https://files.pythonhosted.org/packages/c4/bb/ec73c0257c9e11b268f018f068f5d00aa0ef8c8b09f7753ebd5f2880e248/charset_normalizer-3.4.7-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a277ab8928b9f299723bc1a2dabb1265911b1a76341f90a510368ca44ad9ab66", size = 228303, upload-time = "2026-04-02T09:26:48.397Z" }, + { url = "https://files.pythonhosted.org/packages/85/fb/32d1f5033484494619f701e719429c69b766bfc4dbc61aa9e9c8c166528b/charset_normalizer-3.4.7-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3bec022aec2c514d9cf199522a802bd007cd588ab17ab2525f20f9c34d067c18", size = 224282, upload-time = "2026-04-02T09:26:49.684Z" }, + { url = "https://files.pythonhosted.org/packages/fa/07/330e3a0dda4c404d6da83b327270906e9654a24f6c546dc886a0eb0ffb23/charset_normalizer-3.4.7-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e044c39e41b92c845bc815e5ae4230804e8e7bc29e399b0437d64222d92809dd", size = 215595, upload-time = "2026-04-02T09:26:50.915Z" }, + { url = "https://files.pythonhosted.org/packages/e3/7c/fc890655786e423f02556e0216d4b8c6bcb6bdfa890160dc66bf52dee468/charset_normalizer-3.4.7-cp313-cp313-manylinux_2_31_armv7l.whl", hash = "sha256:f495a1652cf3fbab2eb0639776dad966c2fb874d79d87ca07f9d5f059b8bd215", size = 201986, upload-time = "2026-04-02T09:26:52.197Z" }, + { url = "https://files.pythonhosted.org/packages/d8/97/bfb18b3db2aed3b90cf54dc292ad79fdd5ad65c4eae454099475cbeadd0d/charset_normalizer-3.4.7-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e712b419df8ba5e42b226c510472b37bd57b38e897d3eca5e8cfd410a29fa859", size = 211711, upload-time = "2026-04-02T09:26:53.49Z" }, + { url = "https://files.pythonhosted.org/packages/6f/a5/a581c13798546a7fd557c82614a5c65a13df2157e9ad6373166d2a3e645d/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7804338df6fcc08105c7745f1502ba68d900f45fd770d5bdd5288ddccb8a42d8", size = 210036, upload-time = "2026-04-02T09:26:54.975Z" }, + { url = "https://files.pythonhosted.org/packages/8c/bf/b3ab5bcb478e4193d517644b0fb2bf5497fbceeaa7a1bc0f4d5b50953861/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:481551899c856c704d58119b5025793fa6730adda3571971af568f66d2424bb5", size = 202998, upload-time = "2026-04-02T09:26:56.303Z" }, + { url = "https://files.pythonhosted.org/packages/e7/4e/23efd79b65d314fa320ec6017b4b5834d5c12a58ba4610aa353af2e2f577/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:f59099f9b66f0d7145115e6f80dd8b1d847176df89b234a5a6b3f00437aa0832", size = 230056, upload-time = "2026-04-02T09:26:57.554Z" }, + { url = "https://files.pythonhosted.org/packages/b9/9f/1e1941bc3f0e01df116e68dc37a55c4d249df5e6fa77f008841aef68264f/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:f59ad4c0e8f6bba240a9bb85504faa1ab438237199d4cce5f622761507b8f6a6", size = 211537, upload-time = "2026-04-02T09:26:58.843Z" }, + { url = "https://files.pythonhosted.org/packages/80/0f/088cbb3020d44428964a6c97fe1edfb1b9550396bf6d278330281e8b709c/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:3dedcc22d73ec993f42055eff4fcfed9318d1eeb9a6606c55892a26964964e48", size = 226176, upload-time = "2026-04-02T09:27:00.437Z" }, + { url = "https://files.pythonhosted.org/packages/6a/9f/130394f9bbe06f4f63e22641d32fc9b202b7e251c9aef4db044324dac493/charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:64f02c6841d7d83f832cd97ccf8eb8a906d06eb95d5276069175c696b024b60a", size = 217723, upload-time = "2026-04-02T09:27:02.021Z" }, + { url = "https://files.pythonhosted.org/packages/73/55/c469897448a06e49f8fa03f6caae97074fde823f432a98f979cc42b90e69/charset_normalizer-3.4.7-cp313-cp313-win32.whl", hash = "sha256:4042d5c8f957e15221d423ba781e85d553722fc4113f523f2feb7b188cc34c5e", size = 148085, upload-time = "2026-04-02T09:27:03.192Z" }, + { url = "https://files.pythonhosted.org/packages/5d/78/1b74c5bbb3f99b77a1715c91b3e0b5bdb6fe302d95ace4f5b1bec37b0167/charset_normalizer-3.4.7-cp313-cp313-win_amd64.whl", hash = "sha256:3946fa46a0cf3e4c8cb1cc52f56bb536310d34f25f01ca9b6c16afa767dab110", size = 158819, upload-time = "2026-04-02T09:27:04.454Z" }, + { url = "https://files.pythonhosted.org/packages/68/86/46bd42279d323deb8687c4a5a811fd548cb7d1de10cf6535d099877a9a9f/charset_normalizer-3.4.7-cp313-cp313-win_arm64.whl", hash = "sha256:80d04837f55fc81da168b98de4f4b797ef007fc8a79ab71c6ec9bc4dd662b15b", size = 147915, upload-time = "2026-04-02T09:27:05.971Z" }, + { url = "https://files.pythonhosted.org/packages/97/c8/c67cb8c70e19ef1960b97b22ed2a1567711de46c4ddf19799923adc836c2/charset_normalizer-3.4.7-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:c36c333c39be2dbca264d7803333c896ab8fa7d4d6f0ab7edb7dfd7aea6e98c0", size = 309234, upload-time = "2026-04-02T09:27:07.194Z" }, + { url = "https://files.pythonhosted.org/packages/99/85/c091fdee33f20de70d6c8b522743b6f831a2f1cd3ff86de4c6a827c48a76/charset_normalizer-3.4.7-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1c2aed2e5e41f24ea8ef1590b8e848a79b56f3a5564a65ceec43c9d692dc7d8a", size = 208042, upload-time = "2026-04-02T09:27:08.749Z" }, + { url = "https://files.pythonhosted.org/packages/87/1c/ab2ce611b984d2fd5d86a5a8a19c1ae26acac6bad967da4967562c75114d/charset_normalizer-3.4.7-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:54523e136b8948060c0fa0bc7b1b50c32c186f2fceee897a495406bb6e311d2b", size = 228706, upload-time = "2026-04-02T09:27:09.951Z" }, + { url = "https://files.pythonhosted.org/packages/a8/29/2b1d2cb00bf085f59d29eb773ce58ec2d325430f8c216804a0a5cd83cbca/charset_normalizer-3.4.7-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:715479b9a2802ecac752a3b0efa2b0b60285cf962ee38414211abdfccc233b41", size = 224727, upload-time = "2026-04-02T09:27:11.175Z" }, + { url = "https://files.pythonhosted.org/packages/47/5c/032c2d5a07fe4d4855fea851209cca2b6f03ebeb6d4e3afdb3358386a684/charset_normalizer-3.4.7-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bd6c2a1c7573c64738d716488d2cdd3c00e340e4835707d8fdb8dc1a66ef164e", size = 215882, upload-time = "2026-04-02T09:27:12.446Z" }, + { url = "https://files.pythonhosted.org/packages/2c/c2/356065d5a8b78ed04499cae5f339f091946a6a74f91e03476c33f0ab7100/charset_normalizer-3.4.7-cp314-cp314-manylinux_2_31_armv7l.whl", hash = "sha256:c45e9440fb78f8ddabcf714b68f936737a121355bf59f3907f4e17721b9d1aae", size = 200860, upload-time = "2026-04-02T09:27:13.721Z" }, + { url = "https://files.pythonhosted.org/packages/0c/cd/a32a84217ced5039f53b29f460962abb2d4420def55afabe45b1c3c7483d/charset_normalizer-3.4.7-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3534e7dcbdcf757da6b85a0bbf5b6868786d5982dd959b065e65481644817a18", size = 211564, upload-time = "2026-04-02T09:27:15.272Z" }, + { url = "https://files.pythonhosted.org/packages/44/86/58e6f13ce26cc3b8f4a36b94a0f22ae2f00a72534520f4ae6857c4b81f89/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:e8ac484bf18ce6975760921bb6148041faa8fef0547200386ea0b52b5d27bf7b", size = 211276, upload-time = "2026-04-02T09:27:16.834Z" }, + { url = "https://files.pythonhosted.org/packages/8f/fe/d17c32dc72e17e155e06883efa84514ca375f8a528ba2546bee73fc4df81/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:a5fe03b42827c13cdccd08e6c0247b6a6d4b5e3cdc53fd1749f5896adcdc2356", size = 201238, upload-time = "2026-04-02T09:27:18.229Z" }, + { url = "https://files.pythonhosted.org/packages/6a/29/f33daa50b06525a237451cdb6c69da366c381a3dadcd833fa5676bc468b3/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:2d6eb928e13016cea4f1f21d1e10c1cebd5a421bc57ddf5b1142ae3f86824fab", size = 230189, upload-time = "2026-04-02T09:27:19.445Z" }, + { url = "https://files.pythonhosted.org/packages/b6/6e/52c84015394a6a0bdcd435210a7e944c5f94ea1055f5cc5d56c5fe368e7b/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:e74327fb75de8986940def6e8dee4f127cc9752bee7355bb323cc5b2659b6d46", size = 211352, upload-time = "2026-04-02T09:27:20.79Z" }, + { url = "https://files.pythonhosted.org/packages/8c/d7/4353be581b373033fb9198bf1da3cf8f09c1082561e8e922aa7b39bf9fe8/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:d6038d37043bced98a66e68d3aa2b6a35505dc01328cd65217cefe82f25def44", size = 227024, upload-time = "2026-04-02T09:27:22.063Z" }, + { url = "https://files.pythonhosted.org/packages/30/45/99d18aa925bd1740098ccd3060e238e21115fffbfdcb8f3ece837d0ace6c/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:7579e913a5339fb8fa133f6bbcfd8e6749696206cf05acdbdca71a1b436d8e72", size = 217869, upload-time = "2026-04-02T09:27:23.486Z" }, + { url = "https://files.pythonhosted.org/packages/5c/05/5ee478aa53f4bb7996482153d4bfe1b89e0f087f0ab6b294fcf92d595873/charset_normalizer-3.4.7-cp314-cp314-win32.whl", hash = "sha256:5b77459df20e08151cd6f8b9ef8ef1f961ef73d85c21a555c7eed5b79410ec10", size = 148541, upload-time = "2026-04-02T09:27:25.146Z" }, + { url = "https://files.pythonhosted.org/packages/48/77/72dcb0921b2ce86420b2d79d454c7022bf5be40202a2a07906b9f2a35c97/charset_normalizer-3.4.7-cp314-cp314-win_amd64.whl", hash = "sha256:92a0a01ead5e668468e952e4238cccd7c537364eb7d851ab144ab6627dbbe12f", size = 159634, upload-time = "2026-04-02T09:27:26.642Z" }, + { url = "https://files.pythonhosted.org/packages/c6/a3/c2369911cd72f02386e4e340770f6e158c7980267da16af8f668217abaa0/charset_normalizer-3.4.7-cp314-cp314-win_arm64.whl", hash = "sha256:67f6279d125ca0046a7fd386d01b311c6363844deac3e5b069b514ba3e63c246", size = 148384, upload-time = "2026-04-02T09:27:28.271Z" }, + { url = "https://files.pythonhosted.org/packages/94/09/7e8a7f73d24dba1f0035fbbf014d2c36828fc1bf9c88f84093e57d315935/charset_normalizer-3.4.7-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:effc3f449787117233702311a1b7d8f59cba9ced946ba727bdc329ec69028e24", size = 330133, upload-time = "2026-04-02T09:27:29.474Z" }, + { url = "https://files.pythonhosted.org/packages/8d/da/96975ddb11f8e977f706f45cddd8540fd8242f71ecdb5d18a80723dcf62c/charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fbccdc05410c9ee21bbf16a35f4c1d16123dcdeb8a1d38f33654fa21d0234f79", size = 216257, upload-time = "2026-04-02T09:27:30.793Z" }, + { url = "https://files.pythonhosted.org/packages/e5/e8/1d63bf8ef2d388e95c64b2098f45f84758f6d102a087552da1485912637b/charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:733784b6d6def852c814bce5f318d25da2ee65dd4839a0718641c696e09a2960", size = 234851, upload-time = "2026-04-02T09:27:32.44Z" }, + { url = "https://files.pythonhosted.org/packages/9b/40/e5ff04233e70da2681fa43969ad6f66ca5611d7e669be0246c4c7aaf6dc8/charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a89c23ef8d2c6b27fd200a42aa4ac72786e7c60d40efdc76e6011260b6e949c4", size = 233393, upload-time = "2026-04-02T09:27:34.03Z" }, + { url = "https://files.pythonhosted.org/packages/be/c1/06c6c49d5a5450f76899992f1ee40b41d076aee9279b49cf9974d2f313d5/charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6c114670c45346afedc0d947faf3c7f701051d2518b943679c8ff88befe14f8e", size = 223251, upload-time = "2026-04-02T09:27:35.369Z" }, + { url = "https://files.pythonhosted.org/packages/2b/9f/f2ff16fb050946169e3e1f82134d107e5d4ae72647ec8a1b1446c148480f/charset_normalizer-3.4.7-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:a180c5e59792af262bf263b21a3c49353f25945d8d9f70628e73de370d55e1e1", size = 206609, upload-time = "2026-04-02T09:27:36.661Z" }, + { url = "https://files.pythonhosted.org/packages/69/d5/a527c0cd8d64d2eab7459784fb4169a0ac76e5a6fc5237337982fd61347e/charset_normalizer-3.4.7-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3c9a494bc5ec77d43cea229c4f6db1e4d8fe7e1bbffa8b6f0f0032430ff8ab44", size = 220014, upload-time = "2026-04-02T09:27:38.019Z" }, + { url = "https://files.pythonhosted.org/packages/7e/80/8a7b8104a3e203074dc9aa2c613d4b726c0e136bad1cc734594b02867972/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8d828b6667a32a728a1ad1d93957cdf37489c57b97ae6c4de2860fa749b8fc1e", size = 218979, upload-time = "2026-04-02T09:27:39.37Z" }, + { url = "https://files.pythonhosted.org/packages/02/9a/b759b503d507f375b2b5c153e4d2ee0a75aa215b7f2489cf314f4541f2c0/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:cf1493cd8607bec4d8a7b9b004e699fcf8f9103a9284cc94962cb73d20f9d4a3", size = 209238, upload-time = "2026-04-02T09:27:40.722Z" }, + { url = "https://files.pythonhosted.org/packages/c2/4e/0f3f5d47b86bdb79256e7290b26ac847a2832d9a4033f7eb2cd4bcf4bb5b/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:0c96c3b819b5c3e9e165495db84d41914d6894d55181d2d108cc1a69bfc9cce0", size = 236110, upload-time = "2026-04-02T09:27:42.33Z" }, + { url = "https://files.pythonhosted.org/packages/96/23/bce28734eb3ed2c91dcf93abeb8a5cf393a7b2749725030bb630e554fdd8/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:752a45dc4a6934060b3b0dab47e04edc3326575f82be64bc4fc293914566503e", size = 219824, upload-time = "2026-04-02T09:27:43.924Z" }, + { url = "https://files.pythonhosted.org/packages/2c/6f/6e897c6984cc4d41af319b077f2f600fc8214eb2fe2d6bcb79141b882400/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:8778f0c7a52e56f75d12dae53ae320fae900a8b9b4164b981b9c5ce059cd1fcb", size = 233103, upload-time = "2026-04-02T09:27:45.348Z" }, + { url = "https://files.pythonhosted.org/packages/76/22/ef7bd0fe480a0ae9b656189ec00744b60933f68b4f42a7bb06589f6f576a/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ce3412fbe1e31eb81ea42f4169ed94861c56e643189e1e75f0041f3fe7020abe", size = 225194, upload-time = "2026-04-02T09:27:46.706Z" }, + { url = "https://files.pythonhosted.org/packages/c5/a7/0e0ab3e0b5bc1219bd80a6a0d4d72ca74d9250cb2382b7c699c147e06017/charset_normalizer-3.4.7-cp314-cp314t-win32.whl", hash = "sha256:c03a41a8784091e67a39648f70c5f97b5b6a37f216896d44d2cdcb82615339a0", size = 159827, upload-time = "2026-04-02T09:27:48.053Z" }, + { url = "https://files.pythonhosted.org/packages/7a/1d/29d32e0fb40864b1f878c7f5a0b343ae676c6e2b271a2d55cc3a152391da/charset_normalizer-3.4.7-cp314-cp314t-win_amd64.whl", hash = "sha256:03853ed82eeebbce3c2abfdbc98c96dc205f32a79627688ac9a27370ea61a49c", size = 174168, upload-time = "2026-04-02T09:27:49.795Z" }, + { url = "https://files.pythonhosted.org/packages/de/32/d92444ad05c7a6e41fb2036749777c163baf7a0301a040cb672d6b2b1ae9/charset_normalizer-3.4.7-cp314-cp314t-win_arm64.whl", hash = "sha256:c35abb8bfff0185efac5878da64c45dafd2b37fb0383add1be155a763c1f083d", size = 153018, upload-time = "2026-04-02T09:27:51.116Z" }, + { url = "https://files.pythonhosted.org/packages/db/8f/61959034484a4a7c527811f4721e75d02d653a35afb0b6054474d8185d4c/charset_normalizer-3.4.7-py3-none-any.whl", hash = "sha256:3dce51d0f5e7951f8bb4900c257dad282f49190fdbebecd4ba99bcc41fef404d", size = 61958, upload-time = "2026-04-02T09:28:37.794Z" }, +] + +[[package]] +name = "click" +version = "8.4.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/76/d4/81420972a676e8ffea40450d8c8c92943e7218a78fe9b64359836cc9876b/click-8.4.2.tar.gz", hash = "sha256:9a6cea6e60b17ebe0a44c5cc636d94f09bd66142c1cd7d8b4cd731c4917a15f6", size = 338000, upload-time = "2026-06-24T17:45:15.148Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fb/e2/79c688af8b210d232694e31e59da9f6ec747bae31c3f5946e4e9b98860d5/click-8.4.2-py3-none-any.whl", hash = "sha256:e6f9f66136c816745b9d65817da91d61d957fb16e02e4dcd0552553c5a197b76", size = 119243, upload-time = "2026-06-24T17:45:13.73Z" }, +] + +[[package]] +name = "colorama" +version = "0.4.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, +] + +[[package]] +name = "contourpy" +version = "1.3.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12'" }, + { name = "numpy", version = "2.5.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12'" }, +] +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" }, +] + +[[package]] +name = "cryptography" +version = "49.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cffi", marker = "platform_python_implementation != 'PyPy'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/1f/99/d1c90d6041656cc6ee229dc99cd67fd0cd5aec3c5f7d72fffc27cc750054/cryptography-49.0.0.tar.gz", hash = "sha256:f89660a348f4f78a92366240a61404e337586ef7f5909a2fef59ca88ef505493", size = 854345, upload-time = "2026-06-12T20:02:30.512Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9b/22/adf66990e63584a68dfb50c24f48a125c07b1699899381c8151e63ed458c/cryptography-49.0.0-cp311-abi3-macosx_11_0_arm64.whl", hash = "sha256:966fe0e9c67490071f14c0d2b1cb2dfb3023c5ce39457343931415f08382f2db", size = 4032100, upload-time = "2026-06-12T20:02:32.143Z" }, + { url = "https://files.pythonhosted.org/packages/09/41/3797cfaf69cae04a13ee78ebd83f0678d9c02b4779d21ce24445326f1a69/cryptography-49.0.0-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:36d1709f992593689b45bda411498d62c6e365f2ca00b84657d4dadd24de16db", size = 4692978, upload-time = "2026-06-12T20:01:21.305Z" }, + { url = "https://files.pythonhosted.org/packages/e6/8b/43011f7ebe515a8aa20d61f290a326cd890c2e738e16e59eaff8d9c3a412/cryptography-49.0.0-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0e959b578856a3924bc0cbb710fc12c387b9412a951389f3ca61704a9e25f325", size = 4716422, upload-time = "2026-06-12T20:01:48.566Z" }, + { url = "https://files.pythonhosted.org/packages/4a/91/01ce7303a4579e6d3a6abef01bd322848e9ea7a219adcabc5048b9033571/cryptography-49.0.0-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:53ecee2e23f7169b6117e99fc8a944e5e50f79e69758a83b52a00cb98ab2b2d2", size = 4700503, upload-time = "2026-06-12T20:02:47.091Z" }, + { url = "https://files.pythonhosted.org/packages/62/99/a2c95cf8293f07491e9e27c20cc4dcd18176d944e674679adeb1d0173fd6/cryptography-49.0.0-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:2eda353d8a27bcbcaa4cbed18994a74ab4d19a2ca897db188ea269ab9b71419b", size = 5309779, upload-time = "2026-06-12T20:02:08.987Z" }, + { url = "https://files.pythonhosted.org/packages/20/2c/0622f20ff02b2ef32558733443805dc82fd4c275be01b2d19d14676f3a1b/cryptography-49.0.0-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:2afe9051da7ae7bd5905da5a949280c7d2bb75682e188f650a9d0f2756b834c6", size = 4749683, upload-time = "2026-06-12T20:02:03.335Z" }, + { url = "https://files.pythonhosted.org/packages/a3/5b/c5246635d5fd3b64e0d45ae10e99fd32fe9676a79915ccfe5a61ba9af1a5/cryptography-49.0.0-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:0b82e28ee398a386f0807bba7884d30f25218855690f45115831bcce5d90822c", size = 4337874, upload-time = "2026-06-12T20:02:54.323Z" }, + { url = "https://files.pythonhosted.org/packages/6d/88/05563c7fe2e914e87d1a536d06fe83e66b4e1d95cb593e05aea375531da8/cryptography-49.0.0-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:ccac2bfebc306b862133e3bb71f3f6ee8bb525240089b2d952e4144b3a6d5da7", size = 4700283, upload-time = "2026-06-12T20:01:34.822Z" }, + { url = "https://files.pythonhosted.org/packages/c4/b6/d7696e4e890d6ae1469935164c9e5215c557671cb78d6e3f458ccceaa632/cryptography-49.0.0-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:d0527ce944105f257f605a827d6ebead966c752038b6e8656abb9c5edee6fc68", size = 5265844, upload-time = "2026-06-12T20:01:24.09Z" }, + { url = "https://files.pythonhosted.org/packages/a9/3c/f3ad17eecc1a57b0ba236dc01f90e783c51f4a2f35f64777cc4f47a184b2/cryptography-49.0.0-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:cbc77da8c523d5abd028635ba850a6966fcee2c82e2bf65a41d1d8afe0f98be9", size = 4749290, upload-time = "2026-06-12T20:01:30.848Z" }, + { url = "https://files.pythonhosted.org/packages/4f/01/339573cf1023163a400b0b5d16f6d507de413b9f60be6fd1b77feeaf6737/cryptography-49.0.0-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:b87e65d263b3e5d3bb92a57e2a6638e2f31110fa7aa890c7b2dbba42248d0a3f", size = 4834612, upload-time = "2026-06-12T20:01:29.246Z" }, + { url = "https://files.pythonhosted.org/packages/71/fd/577302e213a1be9468f92d1afef66fcf1ef83d516819d9992ca547f592bd/cryptography-49.0.0-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:66ec79c3904820572d7e987abdf304281f141d37ad9a489b8e97066e7b9b6459", size = 4980804, upload-time = "2026-06-12T20:01:42.853Z" }, + { url = "https://files.pythonhosted.org/packages/1f/09/f42b1d190c5ba75f72062a387f8030d1d75f6ab035788f1d9c4b01de6525/cryptography-49.0.0-cp311-abi3-win_amd64.whl", hash = "sha256:e5dfc1e64de5677cec922ffa8da89c546d0415bf6efdf081842e5d44c84e1f0e", size = 3810026, upload-time = "2026-06-12T20:02:39.262Z" }, + { url = "https://files.pythonhosted.org/packages/ec/9e/db72b3ae7fc9cfad53e630e56c6ae83b9b6ff0bf3718ffb8012d20b3aabf/cryptography-49.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:73a205dce83953d131a4aa1e0fd917a2fd1c5b1eef251e9d7152efefcbf5caf7", size = 4013892, upload-time = "2026-06-12T20:02:10.735Z" }, + { url = "https://files.pythonhosted.org/packages/86/12/c48a424f38db03027be9f7ed5c7dc5de9933dbee992865f98b13727a009d/cryptography-49.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:196ecd6a36e4e9aa10270393bb98d8df88fccee0bf1e5128b91ae4eb4375896d", size = 4678835, upload-time = "2026-06-12T20:02:48.743Z" }, + { url = "https://files.pythonhosted.org/packages/68/28/8a3ad4653662c93fc44dc4e5d8fd374c25c42e07b34bbfbadf49cf57a5a8/cryptography-49.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7abcee80084cda3f7691f3eb1ce480d8df49cec637b429aa35986c1de71738aa", size = 4697239, upload-time = "2026-06-12T20:02:56.03Z" }, + { url = "https://files.pythonhosted.org/packages/a8/b2/2193fc74f81aee4f9b62733133b73b5176718932ed8f2e4b03fa040480a6/cryptography-49.0.0-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:4ae387c9cb68ea569ca17e490d66d8142b81c3cc814bf179974b7d146e490bbb", size = 4685593, upload-time = "2026-06-12T20:02:50.666Z" }, + { url = "https://files.pythonhosted.org/packages/47/f1/1d3eaa243bfc5de4a187b22aa8c048b3e4980bfbe830ac46e6bac2e66947/cryptography-49.0.0-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:f37d847238971164fdbc68ade6f6574aecc9c0af714190e2083429ff68f4ce9d", size = 5289961, upload-time = "2026-06-12T20:01:46.468Z" }, + { url = "https://files.pythonhosted.org/packages/58/39/2d51306721330c486495853eda1c567880ff036de15a14c4b74f399934af/cryptography-49.0.0-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:c2bc30226390d60ea19d9f82b19db005fe0452154a23c1c410c12ea801e43561", size = 4731145, upload-time = "2026-06-12T20:02:16.832Z" }, + { url = "https://files.pythonhosted.org/packages/17/50/983e838c7fd0d87fd8c969bcdd328edaf5f756e38df5281637424c155873/cryptography-49.0.0-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:07cab27cc7b7e0fd28e5e26bb9eeedde5c135c868b46de4a27845abe94af6122", size = 4321719, upload-time = "2026-06-12T20:02:52.611Z" }, + { url = "https://files.pythonhosted.org/packages/a7/f5/8f571d7e27c55bce9f76f026143bcb1e040a4233149ecca0bea5fa5dd5f7/cryptography-49.0.0-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:b20133d204d2bb56ba047642199603876c872026ca53e79c35b83772ab2cc505", size = 4685209, upload-time = "2026-06-12T20:02:07.282Z" }, + { url = "https://files.pythonhosted.org/packages/e7/84/0e27016a6fc5a0886f797018b26aa42f40c09a82332bff77822a451deaaa/cryptography-49.0.0-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:b970c6da94d5bb18629db453d14f2a1300f6bf59b61e9b82377931ef95504866", size = 5246285, upload-time = "2026-06-12T20:01:32.439Z" }, + { url = "https://files.pythonhosted.org/packages/11/2d/5e1fb307cb5931881516b464c98774b3f2c36b5d4bb9a2830253cf553cad/cryptography-49.0.0-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:d8ecde755e2e91bf773fc94e8c9d730cd7f2007004cb492263a794ec3899a1c8", size = 4730441, upload-time = "2026-06-12T20:02:01.469Z" }, + { url = "https://files.pythonhosted.org/packages/e4/c0/bff5a02ee731d207d6a1ed51732549d8c53d2bc8da1d10ec6f2844201d68/cryptography-49.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e3fb64c420688e5319ae25113a354015abbd8dffbfbc41781a1ea66fc7622ac3", size = 4815869, upload-time = "2026-06-12T20:01:36.574Z" }, + { url = "https://files.pythonhosted.org/packages/b9/26/814681d14248d95d73d5c3eea0c39a94eb8302df966f670a2c60de90974b/cryptography-49.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:32703d93296f5c1f4b53349ad3a250c2cae0fdecd3a3dd5d47e616d8d616af27", size = 4960948, upload-time = "2026-06-12T20:02:18.688Z" }, + { url = "https://files.pythonhosted.org/packages/4c/fe/93ecac273d3738939d023612ad12cca9a3740a5345d69fda04134c43fd96/cryptography-49.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:33cd0565932807baddb67b96dbee92f2c374b5c89dee09fd74079aeb8c8dba61", size = 3799153, upload-time = "2026-06-12T20:01:39.059Z" }, + { url = "https://files.pythonhosted.org/packages/19/2a/5bb823f5bedcf80718cea7fbc95ec5515cca3769633c4b01a32be7f30e7c/cryptography-49.0.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:ec5e529fb80935c94fe7b729f9972b50e351a0e6b50aa294fd5cabb109fcc29a", size = 4025947, upload-time = "2026-06-12T20:01:25.745Z" }, + { url = "https://files.pythonhosted.org/packages/3d/df/40577043ca124e17012f408ddddaeb213b856336ac82ddb3bc915f39e29f/cryptography-49.0.0-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f78ff2c9ed8dc2d036b0f4d640e22522213d047c1b14e61205a7e55c80a494d4", size = 4692429, upload-time = "2026-06-12T20:01:53.628Z" }, + { url = "https://files.pythonhosted.org/packages/2c/99/2d13299eb3dd27b02dcfaafcc91d6b5cb3329f7cbd6d8f51921acd566c1a/cryptography-49.0.0-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:35b151772baff2c74cba7fa290ceaff4c3b11c0c881eb93eb5dbc05a7cfbba18", size = 4700968, upload-time = "2026-06-12T20:02:45.383Z" }, + { url = "https://files.pythonhosted.org/packages/a5/4d/9c0cd02f95e2602dd5e563da149ee0830abef3537be8b34dc56281ebe27a/cryptography-49.0.0-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:0f21641cf4b30fca7aee061ced0ec7ad7b073518088b7c9969a297c0ae796c69", size = 4697758, upload-time = "2026-06-12T20:01:41.13Z" }, + { url = "https://files.pythonhosted.org/packages/24/01/186c825898477d77e2324d5360fefe622ff1d8d1963ec0554e2cada8ec77/cryptography-49.0.0-cp39-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:9e82dcc8e56052715fb18b2429e3bca4823b1629136a2084fc45a9a5cecb9b64", size = 5298863, upload-time = "2026-06-12T20:02:24.579Z" }, + { url = "https://files.pythonhosted.org/packages/b8/7b/62cbbab75d0659865bf0273790031544a0b16c8072d258f9428dcd8190dc/cryptography-49.0.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:6f2debedf9ca60cf1d5bd466475638af5130f89965605cd818484d19987d3a21", size = 4735983, upload-time = "2026-06-12T20:01:50.14Z" }, + { url = "https://files.pythonhosted.org/packages/6c/72/3e798c064bc39e471008075d0f9bc9daf77a80879c092e4a8e170c585ed4/cryptography-49.0.0-cp39-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:8c25ceb16df5b9435f3f6a9829204985b0e0cbee3b48aacd432c7d2c850b44d9", size = 4334173, upload-time = "2026-06-12T20:01:44.743Z" }, + { url = "https://files.pythonhosted.org/packages/f0/ee/6fca21d1ac73e06f8bef71940abfd4d2f6472b4bca284d770f32bd4086f6/cryptography-49.0.0-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:28d8b15e6275f12c8a207dc309dfa957903c927d08d0cc937ee3f63f200693cc", size = 4697298, upload-time = "2026-06-12T20:02:20.918Z" }, + { url = "https://files.pythonhosted.org/packages/67/d0/a5fcd3515f0bae49a7b6d0413cc1bdccdcc1fc0047037a0d480642cdc5d6/cryptography-49.0.0-cp39-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:6fc361c34fb6aac015ce19435876635e5c6d21db31998b0920f675f131e043b8", size = 5254338, upload-time = "2026-06-12T20:02:22.737Z" }, + { url = "https://files.pythonhosted.org/packages/a0/84/84fe36f19caf857d61cb7fc9c63035a47ffabd84ea12d1d393148efa3615/cryptography-49.0.0-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:2400ef9c9e2299a25614eb1dea3db54a69b1349efd043bfac9c67630d136df36", size = 4735650, upload-time = "2026-06-12T20:02:41.389Z" }, + { url = "https://files.pythonhosted.org/packages/6c/a0/db537264e234f7273a73ec020873d6d6b39dfd8a53db78b550ca8320440e/cryptography-49.0.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:67e1d20ad9ef3a563c59ef22e7a8a0b8210bd26604369ea4a30a7c66aefe504e", size = 4834820, upload-time = "2026-06-12T20:01:51.847Z" }, + { url = "https://files.pythonhosted.org/packages/93/77/8df9eb486495979bccecd1062e2eaf435250e84437040295b57d09048b0b/cryptography-49.0.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:42b0684e0e40cf26122427802486f6d93aea593612603a94fbf260c7eb1e9c1b", size = 4967968, upload-time = "2026-06-12T20:02:12.524Z" }, + { url = "https://files.pythonhosted.org/packages/c2/e6/f60198ea8d9dfa15fff9ed4ca02ce362f6eadd9ba757dcc50634c4257b63/cryptography-49.0.0-cp39-abi3-win_amd64.whl", hash = "sha256:026ac7423e6fa66872d3bf889be5974507da3944f866f704fa200eadacd00001", size = 3785547, upload-time = "2026-06-12T20:02:26.847Z" }, + { url = "https://files.pythonhosted.org/packages/63/d3/4a83af35d65e3fad632c926fad684c193ea4398569ccb0bbbc7fe8f5dc9a/cryptography-49.0.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:fc1e275c2f1d97b1a6450b8b0ea3ebfa6e087a611c2b26cb2404d48588abab7b", size = 3993685, upload-time = "2026-06-12T20:02:14.883Z" }, + { url = "https://files.pythonhosted.org/packages/d6/a7/f9dac0ab7f80368c56993a7bf638ef9935f825c91902798481fac0898138/cryptography-49.0.0-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:c83782480a4a9da4d0feb51950131ba32e12e70813848b3343f6e18c28a66838", size = 4676239, upload-time = "2026-06-12T20:02:28.793Z" }, + { url = "https://files.pythonhosted.org/packages/d7/70/2ba3769dd0ae167e2f33dfa9592d45db6ff9a61d62ca1a5b3d1bdd09068f/cryptography-49.0.0-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:b39efa323140595abd3ecca8529d321ae50f55f3aa3ba9cc81ea56a6011953d5", size = 4715584, upload-time = "2026-06-12T20:01:27.495Z" }, + { url = "https://files.pythonhosted.org/packages/94/64/2923570ac1c0bd3a737aa366ac3abbbbde273042308b8cde95e2364a6e6a/cryptography-49.0.0-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:b47db11c2c3525083296069b98ac5221907455e989ae0c2e3008bde851921615", size = 4675885, upload-time = "2026-06-12T20:01:55.49Z" }, + { url = "https://files.pythonhosted.org/packages/ab/f8/614dc7e051418cfe53d55173c1e24c6b0085e89996fe90508c2fdf769aef/cryptography-49.0.0-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:084ef1af862eb07ec46d25f68689f2102a9fc0e05ce7b80f14f5fe51e4eef0f6", size = 4715449, upload-time = "2026-06-12T20:02:05.469Z" }, + { url = "https://files.pythonhosted.org/packages/aa/50/a9caea39ad19c431c1a3f8a31114df65b260cdfe67786b6c7e7c040c4c44/cryptography-49.0.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:be9fcb48a55f023493482827d4f459bd263cc20efde64f204b97c123201850c6", size = 3783731, upload-time = "2026-06-12T20:02:43.319Z" }, +] + +[[package]] +name = "cuda-bindings" +version = "13.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cuda-pathfinder", marker = "sys_platform != 'win32'" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/51/6b/457ca12dad3ee9bfcc9a545cfd6b64b359ba49de40f776f6e028e678f262/cuda_bindings-13.3.1-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c5879712accf6e14bb01aa5e67440eb84998b8d104b509cc7a6dc0b8f656a474", size = 6053539, upload-time = "2026-05-29T23:11:43.19Z" }, + { url = "https://files.pythonhosted.org/packages/95/7a/c5e3c34a409b148f5c0f5a4ea374158f95d488862c1dffedf9aa5c639df9/cuda_bindings-13.3.1-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:04436a9364059c84b8f9636f359eccda1cf814341f5b670c71d80d2f79dbc708", size = 6674166, upload-time = "2026-05-29T23:11:45.478Z" }, + { url = "https://files.pythonhosted.org/packages/ce/67/5e7dba1ba576dd73da5dee894ca076ca5e959450dfff66d6d510a255d1f7/cuda_bindings-13.3.1-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c7855c4868aabc0cfae28abbe83d56734bdfbd08f08fc234ac1912a12858bf49", size = 6025351, upload-time = "2026-05-29T23:11:49.685Z" }, + { url = "https://files.pythonhosted.org/packages/39/2a/6d2e9047d1fb243dbaa364b01e0297534b9ed7fd27dba1c9f361519cf69b/cuda_bindings-13.3.1-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e32d08f71ebcdf00f0f41eab2eb37e8da94c8ed411cc9f7f7a019ce6b34abe3a", size = 6657965, upload-time = "2026-05-29T23:11:52.227Z" }, + { url = "https://files.pythonhosted.org/packages/cc/6e/2394f8163360f8391f8f1b7e72d300a82724edb81a7b7084c799fbd4c91f/cuda_bindings-13.3.1-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9efb21c1ee64981e184b9e0ba5eb3179e5ba3d4b51665a6cb52b8ef3d01a7cbf", size = 5920504, upload-time = "2026-05-29T23:11:56.883Z" }, + { url = "https://files.pythonhosted.org/packages/34/c2/ef9b6a63f7dc432712a462c816662e662e00d38caa9b861c8c2588195d03/cuda_bindings-13.3.1-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2732904099e0a4d4db774a5fc6d91ee95fae065b4d2ecabb4968c5fe2406c9d7", size = 6476660, upload-time = "2026-05-29T23:11:59.188Z" }, + { url = "https://files.pythonhosted.org/packages/b1/81/bff68ce829999c1e4209c761bbf903b1c06ec570416ddb25020864ad5907/cuda_bindings-13.3.1-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1ab2f74ed65bfef4163ba07a8db16f1085e0729291db12a2423aff84ee8278b8", size = 6013639, upload-time = "2026-05-29T23:12:03.509Z" }, + { url = "https://files.pythonhosted.org/packages/d4/e0/c8a1f0c8f9ffdea4f5fe6dbab89b326cef4d85caf489dad39e209da89416/cuda_bindings-13.3.1-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:efd4c814d311ec08c981f6dded1dbe7d4b371067ee4f6c14cccec4bde9590f80", size = 6534419, upload-time = "2026-05-29T23:12:05.633Z" }, + { url = "https://files.pythonhosted.org/packages/52/b8/83b1f563925b290f2d11a01a77a84013ba56052fe3653a5bef3ccfbb43d6/cuda_bindings-13.3.1-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c3c772dfff49681541d59630c90f858e173ac926b9c593a2b7123f2a1043cc76", size = 5809771, upload-time = "2026-05-29T23:12:10.422Z" }, + { url = "https://files.pythonhosted.org/packages/12/20/e79b4bfe98f075195afb6343d41c498f9dbd2d161d7021d4d28bceb83581/cuda_bindings-13.3.1-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:36febb7c1079d68a981dbbd8d5a67235b399802b82075c9388624719607e52b9", size = 6358584, upload-time = "2026-05-29T23:12:12.767Z" }, +] + +[[package]] +name = "cuda-pathfinder" +version = "1.5.5" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/11/c8/26f2e4aae92f11522a96043892ba39a90eac610d5242523aa863212bc1c7/cuda_pathfinder-1.5.5-py3-none-any.whl", hash = "sha256:0228c023f95d1480f143ef5c8922d27a2ab052087a942e81dc289c9eb8f91689", size = 51671, upload-time = "2026-05-27T01:21:25.413Z" }, +] + +[[package]] +name = "cuda-toolkit" +version = "13.0.2" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/57/b2/453099f5f3b698d7d0eab38916aac44c7f76229f451709e2eb9db6615dcd/cuda_toolkit-13.0.2-py2.py3-none-any.whl", hash = "sha256:b198824cf2f54003f50d64ada3a0f184b42ca0846c1c94192fa269ecd97a66eb", size = 2364, upload-time = "2025-12-19T23:24:07.328Z" }, +] + +[package.optional-dependencies] +cudart = [ + { name = "nvidia-cuda-runtime", marker = "sys_platform == 'linux'" }, +] +cufft = [ + { name = "nvidia-cufft", marker = "sys_platform == 'linux'" }, +] +cufile = [ + { name = "nvidia-cufile", marker = "sys_platform == 'linux'" }, +] +cupti = [ + { name = "nvidia-cuda-cupti", marker = "sys_platform == 'linux'" }, +] +curand = [ + { name = "nvidia-curand", marker = "sys_platform == 'linux'" }, +] +cusolver = [ + { name = "nvidia-cusolver", marker = "sys_platform == 'linux'" }, +] +cusparse = [ + { name = "nvidia-cusparse", marker = "sys_platform == 'linux'" }, +] +nvjitlink = [ + { name = "nvidia-nvjitlink", marker = "sys_platform == 'linux'" }, +] +nvrtc = [ + { name = "nvidia-cuda-nvrtc", marker = "sys_platform == 'linux'" }, +] +nvtx = [ + { name = "nvidia-nvtx", marker = "sys_platform == 'linux'" }, +] + +[[package]] +name = "cycler" +version = "0.12.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a9/95/a3dbbb5028f35eafb79008e7522a75244477d2838f38cbb722248dabc2a8/cycler-0.12.1.tar.gz", hash = "sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c", size = 7615, upload-time = "2023-10-07T05:32:18.335Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl", hash = "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30", size = 8321, upload-time = "2023-10-07T05:32:16.783Z" }, +] + +[[package]] +name = "cyclonedx-python-lib" +version = "11.11.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "license-expression" }, + { name = "packageurl-python" }, + { name = "py-serializable" }, + { name = "sortedcontainers" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/75/c9/5d0ccdd19bc7d8ab803b90695c1706aa2ea8529685d18e682dc2524d2630/cyclonedx_python_lib-11.11.0.tar.gz", hash = "sha256:4b3194db72b613717f2912447e67ab618c75ff7dcac6c4af3c0e9e1ac617c102", size = 1442983, upload-time = "2026-06-17T11:57:49.055Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/22/f3/56ccb2884aaa3db5622368e5191a3384b15f35392aa93df8b2f508c660d2/cyclonedx_python_lib-11.11.0-py3-none-any.whl", hash = "sha256:3049fc83e06a059b5c5907a527625a8ed5073caab10607ed4c9e5503b590fd44", size = 528689, upload-time = "2026-06-17T11:57:47.358Z" }, +] + +[[package]] +name = "defusedxml" +version = "0.7.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0f/d5/c66da9b79e5bdb124974bfe172b4daf3c984ebd9c2a06e2b8a4dc7331c72/defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69", size = 75520, upload-time = "2021-03-08T10:59:26.269Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/07/6c/aa3f2f849e01cb6a001cd8554a88d4c77c5c1a31c95bdf1cf9301e6d9ef4/defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61", size = 25604, upload-time = "2021-03-08T10:59:24.45Z" }, +] + +[[package]] +name = "distro" +version = "1.9.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/fc/f8/98eea607f65de6527f8a2e8885fc8015d3e6f5775df186e443e0964a11c3/distro-1.9.0.tar.gz", hash = "sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed", size = 60722, upload-time = "2023-12-24T09:54:32.31Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/12/b3/231ffd4ab1fc9d679809f356cebee130ac7daa00d6d6f3206dd4fd137e9e/distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2", size = 20277, upload-time = "2023-12-24T09:54:30.421Z" }, +] + +[[package]] +name = "docutils" +version = "0.23" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/39/a4/5180d9afc57e8fca05601dd652bdff19604c218814037fe90ffc7625a50a/docutils-0.23.tar.gz", hash = "sha256:746f5060322511280a1e50eb76846ed6bf2342984b2ac04dc42caa1a8d78799e", size = 2303823, upload-time = "2026-05-27T17:41:06.934Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/32/91/30151a39f7570f448ed84529390628a651d7f27c87d73c9b887f8189695e/docutils-0.23-py3-none-any.whl", hash = "sha256:25d013af9bf23bc1c7b2b093dff4208166c53a94786c9e447808335ef1185fea", size = 634701, upload-time = "2026-05-27T17:40:58.442Z" }, +] + +[[package]] +name = "filelock" +version = "3.29.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e6/dc/be6cbe99670cd6e4ad387123647cb08e0c32975e223f82551e914c5568a6/filelock-3.29.4.tar.gz", hash = "sha256:10cdb3656fc44541cdf30652a93fb10ec6b05325620eb316bd26893e4201538a", size = 63028, upload-time = "2026-06-13T16:12:00.744Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/13/37/a065dc3bd6e49423a6532c642ca7378d3f467b1ef44c2800c937af7f9739/filelock-3.29.4-py3-none-any.whl", hash = "sha256:dac1648087d5115554850d113e7dd8c83ab2d38e3435dde2d4f163847e57b767", size = 42757, upload-time = "2026-06-13T16:11:59.582Z" }, +] + +[[package]] +name = "fonttools" +version = "4.63.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/84/69/c97f2c18e0db87d2c7b15da1974dace76ae938f1cfa22e2727a648b7ed43/fonttools-4.63.0.tar.gz", hash = "sha256:caeb583deeb5168e694b65cda8b4ee62abedfa66cf88488734466f2366b9c4e0", size = 3597189, upload-time = "2026-05-14T12:04:30.958Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/75/2b/a7f1545bdf5da69c4bda0cea2a5781f0ad2a6623e0277267672db43c5fe6/fonttools-4.63.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2b8ae05d9eacf6081414d759c0a352769ac28ce31280d6bb8e77b03f9e3c449f", size = 2881793, upload-time = "2026-05-14T12:02:56.645Z" }, + { url = "https://files.pythonhosted.org/packages/49/50/965308c703f085f225db2886813b27e015b8b3438c350b22dd65b52c2a2c/fonttools-4.63.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:79cdc9f567aec74a72918fd060283911406750cbc9fd28c1316023deb6ce31a9", size = 2428130, upload-time = "2026-05-14T12:02:58.891Z" }, + { url = "https://files.pythonhosted.org/packages/d8/38/6937fbd7f2dc3a6b48725851bc2c15ec949b9af14d9bbcb5fe83cdf9bdf9/fonttools-4.63.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2c14b4fd138c4bafcca294765c547914e1aa431ae1ca94ab99d8db08c958bd3b", size = 5111952, upload-time = "2026-05-14T12:03:01.263Z" }, + { url = "https://files.pythonhosted.org/packages/0b/43/a81f20050a3115b57d62c8e781446949512eac36690dc384ccea65ff4cc1/fonttools-4.63.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d76ac49f929aecaf82d83250b8347e099d7aecba0f4726c1d9b6df3b8bb5fe18", size = 5082308, upload-time = "2026-05-14T12:03:03.211Z" }, + { url = "https://files.pythonhosted.org/packages/67/00/cdd9d4944ca6ae280d01e69cc37bde3bf663630b837a6fc6d2cd65d80e0e/fonttools-4.63.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:dcf076a4474fe0d7367e5bbf5b052c7284fa1feca729c04176ce513521afd8a0", size = 5087932, upload-time = "2026-05-14T12:03:05.147Z" }, + { url = "https://files.pythonhosted.org/packages/f5/f1/0aa0dbea778c75adbef223c42019fd47d22262b905974d62d829545d485f/fonttools-4.63.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7dd683fef0663e9f0f45cf541d788d24caa3ec9db50796b588e1757d8b3bc007", size = 5213271, upload-time = "2026-05-14T12:03:07.238Z" }, + { url = "https://files.pythonhosted.org/packages/a8/99/253e4056e1f0e67b9390125a154b73b5eb73ad521bece95c004858fdeec2/fonttools-4.63.0-cp311-cp311-win32.whl", hash = "sha256:afefc1ed0a59785a7fb06ea7e1678e849c193e1e387db783579bc7b3056fcfcb", size = 2304473, upload-time = "2026-05-14T12:03:09.271Z" }, + { url = "https://files.pythonhosted.org/packages/08/60/defa5e69641db890a63be281f41345f4c33b157824eaf0b9fad3e08b0dcb/fonttools-4.63.0-cp311-cp311-win_amd64.whl", hash = "sha256:063e08bd17bd5a90127a14123de0d6a952dbc847695fd98b63c043d58057f90c", size = 2356389, upload-time = "2026-05-14T12:03:11.53Z" }, + { url = "https://files.pythonhosted.org/packages/08/ef/b3c6b9b5be2f82416d73fe2ed2e96e2793cd80e7510bd6a17ca79cdd88ec/fonttools-4.63.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:37dd23e621e3b0aef1baa70a303b80aaf38449632cfc8fd2a55fb285bbccfc02", size = 2881131, upload-time = "2026-05-14T12:03:13.386Z" }, + { url = "https://files.pythonhosted.org/packages/44/a0/c815bea63117fa63e4e1c01f8a1110d2112fa003f838e6467094ec2432ce/fonttools-4.63.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a9faff9e0c1f76f9fd55899d2ce785832efebab37eb8ae13995853aef178bef0", size = 2426704, upload-time = "2026-05-14T12:03:15.801Z" }, + { url = "https://files.pythonhosted.org/packages/44/04/0b91d8e916e92ad1fac9e4624760baf0fd5ff2ead614c2f68fb21373f03f/fonttools-4.63.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ef3048ef05dbb552b89817713d9cac912e00d0fde4a3105c00d29e52e10c89af", size = 5044298, upload-time = "2026-05-14T12:03:18.085Z" }, + { url = "https://files.pythonhosted.org/packages/77/c7/2342da9830e3e9d4870305ca5d2091d2a83284f2953079b7bdd3b5e029d8/fonttools-4.63.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:58dc6bb86a78d782f00f9190ca02c119cf5bbe2807536e361e18d42019f877d8", size = 4999800, upload-time = "2026-05-14T12:03:20.161Z" }, + { url = "https://files.pythonhosted.org/packages/e6/6d/67fe16c48d7ce050979b33f47e0d28a318f02da030602e944c34f7a16ef3/fonttools-4.63.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ee08ebfa58f6e1aeff5697ab9582105bb620008c1caafb681e4c557e7483027b", size = 4982666, upload-time = "2026-05-14T12:03:22.87Z" }, + { url = "https://files.pythonhosted.org/packages/f2/00/3bbab338c07c71fa56269953845e92c951a61457bbbb0f1022551ea266d9/fonttools-4.63.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:27fdc65af8da6f88b9c6121c47a464cbe359fcfff7ff6fc2d37a1f395d755b78", size = 5133598, upload-time = "2026-05-14T12:03:25.168Z" }, + { url = "https://files.pythonhosted.org/packages/62/f2/aa27c7f98db5b064883dadcc5283947e81e034de42e22a33675878d98b54/fonttools-4.63.0-cp312-cp312-win32.whl", hash = "sha256:af2fd1664d00a397d75f806985ddb36282091c2131a73a6485c23b4a34722263", size = 2292575, upload-time = "2026-05-14T12:03:27.496Z" }, + { url = "https://files.pythonhosted.org/packages/87/36/cccb9bc2a6ab63d1b2980374f0dca72ce95ae267c9b4cfe77455bb70d0d4/fonttools-4.63.0-cp312-cp312-win_amd64.whl", hash = "sha256:59ac449f8cca9b4ffa08d2e7bbadad87ce710d69d1eda5c3c1ce579baa987272", size = 2343211, upload-time = "2026-05-14T12:03:30.057Z" }, + { url = "https://files.pythonhosted.org/packages/0f/8d/d8fec3dcde2963f8c908fb315e5ff2cd0ac34f82394bbbf73a2aa5145ce3/fonttools-4.63.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:cd7e9857e5e63738b9d9fd707bc1f59c8b09e5177726d23664db393c59bb08bd", size = 2876062, upload-time = "2026-05-14T12:03:32.554Z" }, + { url = "https://files.pythonhosted.org/packages/ef/71/d935dc54e4ff121bfdd11e08702db63a7e6f25af21d8a3d7b7212df53641/fonttools-4.63.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c2a2a42198b696a6f48fad91709afb55176e66a5e566131219dba372fb7f8c59", size = 2424594, upload-time = "2026-05-14T12:03:34.86Z" }, + { url = "https://files.pythonhosted.org/packages/8e/40/e76320afa1df918e146155ef239b1719ee266092e96f5423bfd075affba1/fonttools-4.63.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1e874792a8212b44583ea02189d9e693906b2f78b261f372f95d6c563210ac1d", size = 5024840, upload-time = "2026-05-14T12:03:36.745Z" }, + { url = "https://files.pythonhosted.org/packages/ce/36/0b805d8c485f872f65a509cbe3b58a5d0d17bee855333b54a150c79d3061/fonttools-4.63.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:22135da48a348785c5e2d5d2d9d6bec5ed44adacbaeb9db12d9493bf6c6bfa68", size = 4975801, upload-time = "2026-05-14T12:03:38.833Z" }, + { url = "https://files.pythonhosted.org/packages/c8/26/2cee03d0aa083ab022da5c07aff9ed3f689da1defb81ad6917c9627896da/fonttools-4.63.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ccf41f2efdf56994d22d73bef4ced1052161958169428d06ba9724ea9e9a64be", size = 4965009, upload-time = "2026-05-14T12:03:41.494Z" }, + { url = "https://files.pythonhosted.org/packages/7e/48/cc4b66d9058c0d0982c833fad10127c4b0e9324606aafa41382295ca4102/fonttools-4.63.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9ced0bd02ac751dd6319b0da88aaef24414e3b0dbc32bb4f24944821a3741a27", size = 5105892, upload-time = "2026-05-14T12:03:43.525Z" }, + { url = "https://files.pythonhosted.org/packages/d8/1f/a98a30a814b9ddef3a2e706025f90b9e0bc94890e6cb15254bc86547d11a/fonttools-4.63.0-cp313-cp313-win32.whl", hash = "sha256:85be818f5506e8a7753153def2c9550178f0ecae6a47b5e0e8dbb23f7cc90380", size = 2291313, upload-time = "2026-05-14T12:03:45.594Z" }, + { url = "https://files.pythonhosted.org/packages/92/46/5177b01f3b4abfdd4409f31cca4ab279c9343a26efbe9ec78c97fc612e02/fonttools-4.63.0-cp313-cp313-win_amd64.whl", hash = "sha256:ba04cb5891d4c0c21b6da95eda8d7b090021508a294fff33464fc7d241e0856b", size = 2342299, upload-time = "2026-05-14T12:03:47.414Z" }, + { url = "https://files.pythonhosted.org/packages/27/d2/23d25e3f247b328be58d04a4c9f894178a0d1eda7d42867cfb388adaf416/fonttools-4.63.0-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:fd1e3094f42d806d3d7c79162fc59e5910fcbe3a7360c385b8da969bc4493745", size = 2875338, upload-time = "2026-05-14T12:03:50.052Z" }, + { url = "https://files.pythonhosted.org/packages/cd/58/7dfa0c761cb3b2964e2a84c4dc986c926a87de0cb9fb60d5b28ded3f2914/fonttools-4.63.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:6e528da43bc3791085f8cb6141b1d13e459226790240340fcbb4625649238b03", size = 2422661, upload-time = "2026-05-14T12:03:52.154Z" }, + { url = "https://files.pythonhosted.org/packages/dd/87/64cfa18a7a1621d17b7f4502b2b0ed8a135a90c3db51ea590ee99043e76b/fonttools-4.63.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b2248c5decb223562f7902ff6325077a073f608ee8e33e88ad88db734eb9f49", size = 5010526, upload-time = "2026-05-14T12:03:54.647Z" }, + { url = "https://files.pythonhosted.org/packages/36/e1/a8933a72c45a87177fbde2696e0d0755c8c9062f8c077a961c6215fa27b1/fonttools-4.63.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:308f957cdeaf8abe4e5f2f124902ef405448af92c90f80e302a3b771c2e6116b", size = 4923946, upload-time = "2026-05-14T12:03:56.984Z" }, + { url = "https://files.pythonhosted.org/packages/27/60/872e6e233b8c5e8b41413796ff18b7fe479661bd40147e071b450dfad7a1/fonttools-4.63.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:bf00f21eb5fb721dbaf73d1e9da6d02a1af7768f2ebcf9798be98beab8ba90f6", size = 4962489, upload-time = "2026-05-14T12:03:59.443Z" }, + { url = "https://files.pythonhosted.org/packages/30/c4/83c24f2ec38b90cfda84bf4b1a1f49df80e84a1db4e7ac6e0d41bf23bc39/fonttools-4.63.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:c1aaa4b9c75798400ac043ce04d74e7830376c85095a5a6ed7cba2f17a266bf4", size = 5071870, upload-time = "2026-05-14T12:04:02.122Z" }, + { url = "https://files.pythonhosted.org/packages/de/40/3ae22b60ff1d41ce0bd044b31238cdc72cef99f28b976f1e128ebd618c9b/fonttools-4.63.0-cp314-cp314-win32.whl", hash = "sha256:22693918177bd9ceabec4736d338045f357769416fc6b0b2508eefef75b08616", size = 2295026, upload-time = "2026-05-14T12:04:04.47Z" }, + { url = "https://files.pythonhosted.org/packages/c3/d4/98078064ccc76b45cb0f6c002452011e93c4bd26f6850344f0951cc1fe89/fonttools-4.63.0-cp314-cp314-win_amd64.whl", hash = "sha256:7d782fac32985914c351556f68ac0855391572bcd87de50e05970d3cd4c96fc5", size = 2347454, upload-time = "2026-05-14T12:04:06.752Z" }, + { url = "https://files.pythonhosted.org/packages/49/4e/652d1580c5f4e39f7d103b0c793e4773129ad633dce4addd0cf4dfebde02/fonttools-4.63.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:6db5140a60a5d731d21ec076745b40a310607731b0a565b50776393188649001", size = 2958152, upload-time = "2026-05-14T12:04:08.706Z" }, + { url = "https://files.pythonhosted.org/packages/0e/55/ad864c9a9b219f552eb46b32cd7906c466e5a578ba0c3abfcc0fe7413eb6/fonttools-4.63.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:7d76edbff9014094dbf03bd2d074709dfa6ec7aba13d838c937a2b33d2d6a86e", size = 2460809, upload-time = "2026-05-14T12:04:10.783Z" }, + { url = "https://files.pythonhosted.org/packages/ea/2b/0aa8db70f18cf52e49b4ed5ecec68547f981160bf5ded3b5aed6faa0a6f9/fonttools-4.63.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0eac00b9118c3c2f87d272e45341871c5b3066baa3c86897fa634a7c3fb59096", size = 5148649, upload-time = "2026-05-14T12:04:12.747Z" }, + { url = "https://files.pythonhosted.org/packages/7f/63/18e4369c25043096f1048e0c9915951adc4f842bd81c6b18155824d6fa99/fonttools-4.63.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:51394295f1a51de8b5f30bdb1e1b9a4231536c7064ef5c6e211eec19fa36036f", size = 4932147, upload-time = "2026-05-14T12:04:14.806Z" }, + { url = "https://files.pythonhosted.org/packages/a1/3f/67f3eac2ffd8a98446c5022f8ed3864eac878a5ff7af8df4c8286dba16cc/fonttools-4.63.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:9e12f105d2b6342c559c298afb674006bb2893afc7102dcf8a1b55b0486b4e40", size = 5027237, upload-time = "2026-05-14T12:04:17.675Z" }, + { url = "https://files.pythonhosted.org/packages/1a/ba/4e6214cb38a7b04779e97bb7636de9a5c7f20af7018d03dee0b64c08510a/fonttools-4.63.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:796f27556dbe094c4824f75ca85267e4df776c79036c8441469a4df37038c196", size = 5053933, upload-time = "2026-05-14T12:04:20.818Z" }, + { url = "https://files.pythonhosted.org/packages/34/3b/214dcc19ee31d3d38fb5ad2755c11ef0514e5dc300bbaf41c0b69f393799/fonttools-4.63.0-cp314-cp314t-win32.whl", hash = "sha256:948428a275741f0b64b113c955425a953314f4b9ab9997f73a72c83e68e569c8", size = 2359326, upload-time = "2026-05-14T12:04:24.22Z" }, + { url = "https://files.pythonhosted.org/packages/dd/1e/3ff1a9b523058c2eeb6a9d50f5574e2a738200d0d94107d5bc4105e8da3f/fonttools-4.63.0-cp314-cp314t-win_amd64.whl", hash = "sha256:6d4741eb179121cab9eea4cb2393d24492373a260d7945006358c08cfbf45419", size = 2425829, upload-time = "2026-05-14T12:04:26.829Z" }, + { url = "https://files.pythonhosted.org/packages/2c/47/c99d5268f354002ce80f8d029cd9d7d872969da1de8b93d32de4dc56d6f4/fonttools-4.63.0-py3-none-any.whl", hash = "sha256:445af2eab030a16b9171ea8bdda7ebf7d96bda2df88ee182a464252f6e05e20d", size = 1164562, upload-time = "2026-05-14T12:04:29.092Z" }, +] + +[[package]] +name = "fsspec" +version = "2026.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/10/a1/ae4e3e5003468d6391d2c77b6fa1cd73bd5d13511d81c642d7b28ac90ed4/fsspec-2026.6.0.tar.gz", hash = "sha256:f5bac145310fe30e16e1471bd6840b2d990d609e872251d7e674241822abf01a", size = 313646, upload-time = "2026-06-16T01:57:28.105Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e5/22/4222d7ddf3da30f363edaa98e329c2bce6c65497c9cb2810931c8b2c0fbc/fsspec-2026.6.0-py3-none-any.whl", hash = "sha256:02e0b71817df9b2169dc30a16832045764def1191b43dcff5bb85bdee212d2a1", size = 203949, upload-time = "2026-06-16T01:57:26.358Z" }, +] + +[[package]] +name = "h11" +version = "0.16.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/01/ee/02a2c011bdab74c6fb3c75474d40b3052059d95df7e73351460c8588d963/h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", size = 101250, upload-time = "2025-04-24T03:35:25.427Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload-time = "2025-04-24T03:35:24.344Z" }, +] + +[[package]] +name = "hf-xet" +version = "1.5.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/4b/2d/57fd21d84d93efb4bd0b962383790e19dd1bc053501b4264c97903b4e83e/hf_xet-1.5.1.tar.gz", hash = "sha256:51ef4500dab3764b41135ee1381a4b62ce56fc54d4c92b719b59e597d6df5bf6", size = 876636, upload-time = "2026-06-08T23:02:53.897Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/64/ee/dd9ba7beae1005e54131b7d45263cc74c8a066d47d354e6d58ae9445a388/hf_xet-1.5.1-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:dbf48c0d02cf0b2e568944330c60d9120c272dabe013bd892d48e25bc6797577", size = 4069485, upload-time = "2026-06-08T23:02:13.193Z" }, + { url = "https://files.pythonhosted.org/packages/b6/bc/9cae6cfeb4e03070874e73e5c97c66eb90369d3206b6a2b1ef5f96520888/hf_xet-1.5.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e78e4e5192ad2b674c2e1160b651cb9134db974f8ae1835bdfbfb0166b894a43", size = 3838493, upload-time = "2026-06-08T23:02:15.282Z" }, + { url = "https://files.pythonhosted.org/packages/ba/b4/d5c01e0eb6d9f2ca2dacd84d0d1b71e6cfbb2ef3208c968528e010e9b3d7/hf_xet-1.5.1-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:6f7a04a8ad962422e225bc49fbbac99dc1806764b1f3e54dbd154bffa7593947", size = 4505658, upload-time = "2026-06-08T23:02:17.196Z" }, + { url = "https://files.pythonhosted.org/packages/76/c5/29a7598c0c6383c523dc22186d577f4e04267a626cd95ae60f67c00bfe66/hf_xet-1.5.1-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:d48199c2bf4f8df0adc55d31d1368b6ec0e4d4f45bc86b08038089c23db0bed8", size = 4292822, upload-time = "2026-06-08T23:02:18.608Z" }, + { url = "https://files.pythonhosted.org/packages/04/9a/dceaf6ca69390126b86ea825fb354b93d01163199070b7bd849225de9468/hf_xet-1.5.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:97f212a88d14bbf573619a74b7fecb238de77d08fc702e54dec6f78276ca3283", size = 4491255, upload-time = "2026-06-08T23:02:20.124Z" }, + { url = "https://files.pythonhosted.org/packages/48/a7/e5a7afaacf6c1791fdbeeac42951fb81c3d2bc482992b115dedcc86d963e/hf_xet-1.5.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f61e3665892a6c8c5e765395838b8ddf36185da835253d4bc4509a81e49fb342", size = 4711062, upload-time = "2026-06-08T23:02:21.863Z" }, + { url = "https://files.pythonhosted.org/packages/53/49/2802f8433c9742ce281bddc1e65c02c32268ca3098d66828b05e12e45ee2/hf_xet-1.5.1-cp313-cp313t-win_amd64.whl", hash = "sha256:f4ad3ebd4c32dd2b27099d69dc7b2df821e30767e46fb6ee6a0713778243b8ff", size = 4017205, upload-time = "2026-06-08T23:02:23.495Z" }, + { url = "https://files.pythonhosted.org/packages/9e/5a/50c71195b9fb883659f596e7252faf4c18c58e753a9013bdbf9bac5d2250/hf_xet-1.5.1-cp313-cp313t-win_arm64.whl", hash = "sha256:8298485c1e36e7e67cbd01eeb1376619b7af43d4f1ec245caae306f890a8a32d", size = 3845426, upload-time = "2026-06-08T23:02:25.124Z" }, + { url = "https://files.pythonhosted.org/packages/05/24/5e0c28f80371c17d49fed004597d9d132cb75c1f6f53db2cb95f459d2312/hf_xet-1.5.1-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:3474760d10e3bb6f92ff3f024fcb00c0b3e4001e9b035c7483e49a5dd17aa70f", size = 4069676, upload-time = "2026-06-08T23:02:26.759Z" }, + { url = "https://files.pythonhosted.org/packages/d2/17/261ba565b6a4d960fb478f61fdf919c0be5824645aaf1c319eca660c1611/hf_xet-1.5.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6762d89b9e3267dfd502b29b2a327b4525f33b17e7b509a78d94e2151a30ce30", size = 3838509, upload-time = "2026-06-08T23:02:28.573Z" }, + { url = "https://files.pythonhosted.org/packages/4e/44/7ffdc2e184b0d41fc0f683ba3936ef669ab63cf242cf36ef50e57d683668/hf_xet-1.5.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:bf67e6ed10260cef62e852789dc91ebb03f382d5bdc4b1dbeb64763ea275e7d6", size = 4505881, upload-time = "2026-06-08T23:02:30.257Z" }, + { url = "https://files.pythonhosted.org/packages/63/b6/788060d5aa4d5e671f1a31bf69624c314eb2d8babab3aa562f9e5d53444e/hf_xet-1.5.1-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:c6b6cd08ca095058780b50b8ce4d6cbf6787bcf27841705d58a9d32246e3e47a", size = 4292995, upload-time = "2026-06-08T23:02:31.993Z" }, + { url = "https://files.pythonhosted.org/packages/22/93/c5540cbd6b55529b7dc42f6734e88cebee21aefbea34128b66229df56c57/hf_xet-1.5.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e1af0de8ca6f190d4294a28b88023db64a1e2d1d719cab044baf75bec569e7a9", size = 4491570, upload-time = "2026-06-08T23:02:33.86Z" }, + { url = "https://files.pythonhosted.org/packages/03/f3/9d8ceab30f44f36c1679b1b8683054c71a0dadc787dbf07421891742d3ca/hf_xet-1.5.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:4f561cbbb92f80960772059864b7fb07eae879adde1b2e781ec6f86f6ac26c59", size = 4711565, upload-time = "2026-06-08T23:02:35.454Z" }, + { url = "https://files.pythonhosted.org/packages/cd/54/27ed9a5e2cc583b4df82f75a03a4df8dbf55f5a9fa1f47f1fadfb20dbeac/hf_xet-1.5.1-cp314-cp314t-win_amd64.whl", hash = "sha256:e7dbb40617410f432182d918e37c12303fe6700fd6aa6c5964e30a535a4461d6", size = 4017343, upload-time = "2026-06-08T23:02:37.14Z" }, + { url = "https://files.pythonhosted.org/packages/ae/12/ecb2fc8d45e767580e3a37faa97cb895608b614965567efb4f18cff67e27/hf_xet-1.5.1-cp314-cp314t-win_arm64.whl", hash = "sha256:6071d5ccb4d8d2cbd5fea5cc798da4f0ba3f44e25369591c4e89a4987050e61d", size = 3845716, upload-time = "2026-06-08T23:02:39.073Z" }, + { url = "https://files.pythonhosted.org/packages/7a/d8/5e54cf37434759d1f4f2ba9b66077ff9d4c4e1f37b6bd7975da5c40d94ab/hf_xet-1.5.1-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:6abd35c3221eff63836618ddfb954dcf84798603f71d8e33e3ed7b04acfdbe6e", size = 4077794, upload-time = "2026-06-08T23:02:40.656Z" }, + { url = "https://files.pythonhosted.org/packages/35/94/4b2ecfbad8f8b04701a23aefb62f540b9137d058b7e1dbef16a32676f0e9/hf_xet-1.5.1-cp37-abi3-macosx_11_0_arm64.whl", hash = "sha256:94e761bbd266bf4c03cee73753916062665ce8365aa40ed321f45afcb934b41e", size = 3845354, upload-time = "2026-06-08T23:02:42.702Z" }, + { url = "https://files.pythonhosted.org/packages/de/cc/f99f4bc7295023d7bd9ebbfd51f75cc530ca262c1227666268b8208f4b77/hf_xet-1.5.1-cp37-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:892e3a3a3aecc12aded8b93cf4f9cd059282c7de0732f7d55026f3abdf474350", size = 4514864, upload-time = "2026-06-08T23:02:44.497Z" }, + { url = "https://files.pythonhosted.org/packages/cd/6e/21f7e5a2381278bd3b7b7a5a4d90038518bb6308a0c1daf5d9f8268bb178/hf_xet-1.5.1-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:a93df2039190502835b1db8cd7e178b0b7b889fe9ab51299d5ced26e0dd879a4", size = 4303784, upload-time = "2026-06-08T23:02:46.203Z" }, + { url = "https://files.pythonhosted.org/packages/35/0e/f992bb6927ac1cb30ef74e62268f551f338bc32b2191f7c96a44c6f7283e/hf_xet-1.5.1-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:0c97106032ef70467b4f6bc2d0ccc266d7613ee076afc56516c502f87ce1c4a6", size = 4500703, upload-time = "2026-06-08T23:02:47.628Z" }, + { url = "https://files.pythonhosted.org/packages/fb/d1/90a498d05447980b977b1669246eeeeae4cfb0ea3e7a286eaba627f91bf9/hf_xet-1.5.1-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:6208adb15d192b90e4c2ad2a27ed864359b2cb0f2494eb6d7c7f3699ac02e2bf", size = 4719498, upload-time = "2026-06-08T23:02:49.268Z" }, + { url = "https://files.pythonhosted.org/packages/6d/b6/20f99cfe97cc663a711f7b33cc21d4793e51968e9a26125b4afcd77315ba/hf_xet-1.5.1-cp37-abi3-win_amd64.whl", hash = "sha256:f7b3002f95d1c13e24bcb4537baa8f0eb3838957067c91bb4959bc004a6435f5", size = 4026419, upload-time = "2026-06-08T23:02:50.829Z" }, + { url = "https://files.pythonhosted.org/packages/f9/fa/77453694888f03e5a8c8852d1514a0894d8e81c622d39edbaf308ea0dcf4/hf_xet-1.5.1-cp37-abi3-win_arm64.whl", hash = "sha256:93d090b57b211133f6c0dab0205ef5cb6d89162979ba75a74845045cc3063b8e", size = 3855178, upload-time = "2026-06-08T23:02:52.452Z" }, +] + +[[package]] +name = "httpcore" +version = "1.0.9" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "h11" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/06/94/82699a10bca87a5556c9c59b5963f2d039dbd239f25bc2a63907a05a14cb/httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8", size = 85484, upload-time = "2025-04-24T22:06:22.219Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", size = 78784, upload-time = "2025-04-24T22:06:20.566Z" }, +] + +[[package]] +name = "httpx" +version = "0.28.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "certifi" }, + { name = "httpcore" }, + { name = "idna" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406, upload-time = "2024-12-06T15:37:23.222Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517, upload-time = "2024-12-06T15:37:21.509Z" }, +] + +[[package]] +name = "httpx-sse" +version = "0.4.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0f/4c/751061ffa58615a32c31b2d82e8482be8dd4a89154f003147acee90f2be9/httpx_sse-0.4.3.tar.gz", hash = "sha256:9b1ed0127459a66014aec3c56bebd93da3c1bc8bb6618c8082039a44889a755d", size = 15943, upload-time = "2025-10-10T21:48:22.271Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d2/fd/6668e5aec43ab844de6fc74927e155a3b37bf40d7c3790e49fc0406b6578/httpx_sse-0.4.3-py3-none-any.whl", hash = "sha256:0ac1c9fe3c0afad2e0ebb25a934a59f4c7823b60792691f779fad2c5568830fc", size = 8960, upload-time = "2025-10-10T21:48:21.158Z" }, +] + +[[package]] +name = "huggingface-hub" +version = "1.21.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "filelock" }, + { name = "fsspec" }, + { name = "hf-xet", marker = "platform_machine == 'AMD64' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'arm64' or platform_machine == 'x86_64'" }, + { name = "httpx" }, + { name = "packaging" }, + { name = "pyyaml" }, + { name = "tqdm" }, + { name = "typer" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/8f/77/ce3331f40cb2d021fe9b24c46c41e72faf74493621138e5eddac12bf5e1c/huggingface_hub-1.21.0.tar.gz", hash = "sha256:a44f222cd8f2f7c2eade30b5e7a04cac984a3235fa61ea87a0a5a31db77d561f", size = 861572, upload-time = "2026-06-25T13:09:26.356Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4f/85/b505a99a133d9f99d21af182af416e9baef70bdeef019983479651e494c2/huggingface_hub-1.21.0-py3-none-any.whl", hash = "sha256:eadaa3678c512c82aea69e8675d90a184861e68de32f1105668628b4dce0e7cd", size = 721078, upload-time = "2026-06-25T13:09:24.402Z" }, +] + +[[package]] +name = "id" +version = "1.6.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/6d/04/c2156091427636080787aac190019dc64096e56a23b7364d3c1764ee3a06/id-1.6.1.tar.gz", hash = "sha256:d0732d624fb46fd4e7bc4e5152f00214450953b9e772c182c1c22964def1a069", size = 18088, upload-time = "2026-02-04T16:19:41.26Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/42/77/de194443bf38daed9452139e960c632b0ef9f9a5dd9ce605fdf18ca9f1b1/id-1.6.1-py3-none-any.whl", hash = "sha256:f5ec41ed2629a508f5d0988eda142e190c9c6da971100612c4de9ad9f9b237ca", size = 14689, upload-time = "2026-02-04T16:19:40.051Z" }, +] + +[[package]] +name = "idna" +version = "3.18" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cd/63/9496c57188a2ee585e0f1db071d75089a11e98aa86eb99d9d7618fc1edce/idna-3.18.tar.gz", hash = "sha256:ffb385a7e039654cef1ab9ef32c6fafe283c0c0467bba1d9029738ce4a14a848", size = 196711, upload-time = "2026-06-02T14:34:07.794Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1e/5e/d4e9f1a599fb8e573b7b87160658329fbf28d19eac2718f51fc3def3aa5a/idna-3.18-py3-none-any.whl", hash = "sha256:7f952cbe720b688055e3f87de14f5c3e5fdaa8bc3928985c4077ca689de849a2", size = 65455, upload-time = "2026-06-02T14:34:06.319Z" }, +] + +[[package]] +name = "importlib-metadata" +version = "9.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "zipp", marker = "python_full_version < '3.12'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a9/01/15bb152d77b21318514a96f43af312635eb2500c96b55398d020c93d86ea/importlib_metadata-9.0.0.tar.gz", hash = "sha256:a4f57ab599e6a2e3016d7595cfd72eb4661a5106e787a95bcc90c7105b831efc", size = 56405, upload-time = "2026-03-20T06:42:56.999Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/38/3d/2d244233ac4f76e38533cfcb2991c9eb4c7bf688ae0a036d30725b8faafe/importlib_metadata-9.0.0-py3-none-any.whl", hash = "sha256:2d21d1cc5a017bd0559e36150c21c830ab1dc304dedd1b7ea85d20f45ef3edd7", size = 27789, upload-time = "2026-03-20T06:42:55.665Z" }, +] + +[[package]] +name = "iniconfig" +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" }, +] + +[[package]] +name = "jaraco-classes" +version = "3.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "more-itertools" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/06/c0/ed4a27bc5571b99e3cff68f8a9fa5b56ff7df1c2251cc715a652ddd26402/jaraco.classes-3.4.0.tar.gz", hash = "sha256:47a024b51d0239c0dd8c8540c6c7f484be3b8fcf0b2d85c13825780d3b3f3acd", size = 11780, upload-time = "2024-03-31T07:27:36.643Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7f/66/b15ce62552d84bbfcec9a4873ab79d993a1dd4edb922cbfccae192bd5b5f/jaraco.classes-3.4.0-py3-none-any.whl", hash = "sha256:f662826b6bed8cace05e7ff873ce0f9283b5c924470fe664fff1c2f00f581790", size = 6777, upload-time = "2024-03-31T07:27:34.792Z" }, +] + +[[package]] +name = "jaraco-context" +version = "6.1.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "backports-tarfile", marker = "python_full_version < '3.12'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/af/50/4763cd07e722bb6285316d390a164bc7e479db9d90daa769f22578f698b4/jaraco_context-6.1.2.tar.gz", hash = "sha256:f1a6c9d391e661cc5b8d39861ff077a7dc24dc23833ccee564b234b81c82dfe3", size = 16801, upload-time = "2026-03-20T22:13:33.922Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f2/58/bc8954bda5fcda97bd7c19be11b85f91973d67a706ed4a3aec33e7de22db/jaraco_context-6.1.2-py3-none-any.whl", hash = "sha256:bf8150b79a2d5d91ae48629d8b427a8f7ba0e1097dd6202a9059f29a36379535", size = 7871, upload-time = "2026-03-20T22:13:32.808Z" }, +] + +[[package]] +name = "jaraco-functools" +version = "4.5.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "more-itertools" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/36/cf/ea4ef2920830dea3f5ab2ea4da6fb67724e6dca80ee2553788c3607243d0/jaraco_functools-4.5.0.tar.gz", hash = "sha256:3bb5665ea4a020cf78a7040e89154c77edadb3ca74f366479669c5999aa70b03", size = 20272, upload-time = "2026-05-15T21:34:10.025Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/96/9a/982e48afcffcd727a9144506720ffd4224b6b7e355c98641866f38b7c043/jaraco_functools-4.5.0-py3-none-any.whl", hash = "sha256:79ce39246eddbde4b3a03b77ea5f0f7878dc669b166a66cf3fa8e266aa3fa2f4", size = 10594, upload-time = "2026-05-15T21:34:08.595Z" }, +] + +[[package]] +name = "jeepney" +version = "0.9.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7b/6f/357efd7602486741aa73ffc0617fb310a29b588ed0fd69c2399acbb85b0c/jeepney-0.9.0.tar.gz", hash = "sha256:cf0e9e845622b81e4a28df94c40345400256ec608d0e55bb8a3feaa9163f5732", size = 106758, upload-time = "2025-02-27T18:51:01.684Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b2/a3/e137168c9c44d18eff0376253da9f1e9234d0239e0ee230d2fee6cea8e55/jeepney-0.9.0-py3-none-any.whl", hash = "sha256:97e5714520c16fc0a45695e5365a2e11b81ea79bba796e26f9f1d178cb182683", size = 49010, upload-time = "2025-02-27T18:51:00.104Z" }, +] + +[[package]] +name = "jinja2" +version = "3.1.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markupsafe" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115, upload-time = "2025-03-05T20:05:02.478Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" }, +] + +[[package]] +name = "jiter" +version = "0.15.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/66/b5/55f06bb281d92fb3cc86d14e1def2bd908bb77693183e7cb1f5a3c388b0c/jiter-0.15.0.tar.gz", hash = "sha256:4251acc80e2b7c9b7b8823456ea0fceeb0734dac2df7636d3c711b38476b5a76", size = 166640, upload-time = "2026-05-19T10:09:48.361Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e4/13/daa722f5765c393576f466378f9dfd29d77c9bed939e0688f96afa3601ea/jiter-0.15.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:0f862193b8696249d22ec433e85fd2ab0ad9596bc3e45e6c0bc55e8aeba97be2", size = 310899, upload-time = "2026-05-19T10:07:12.89Z" }, + { url = "https://files.pythonhosted.org/packages/7f/82/2d2551829b082f4b6d82b9f939b031fb808a10aab1ec0664f82e150bb9a2/jiter-0.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1303d4d68a9b051ea90502402063ecf3807da00ad2affa19ca1ae3b90b3c5f67", size = 314963, upload-time = "2026-05-19T10:07:14.539Z" }, + { url = "https://files.pythonhosted.org/packages/2a/0a/8b1a51466f7fe9f31dbe4bc7e0ca848674f9825e0f737b929b97e8c60aa7/jiter-0.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:392b8ab019e5502d08aff85c6272209c24bc2cbe706ea82a56368f524236614a", size = 341730, upload-time = "2026-05-19T10:07:15.869Z" }, + { url = "https://files.pythonhosted.org/packages/f6/2a/e71dea19822e2e404e83992a08c1d6b9b617bb944f28c9c2fbd85d02c91e/jiter-0.15.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:773b6eb282ce11ee19f05f6b2d4404fa308e5bbd353b0b80a0262caad6db2cd7", size = 366214, upload-time = "2026-05-19T10:07:17.259Z" }, + { url = "https://files.pythonhosted.org/packages/c4/59/97e1fa539d124a509a00ab7f669289d1c1d236ecabf12948a18f16c91082/jiter-0.15.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8d2c0c44d569ce0f2850f5c926f8caeb5f245fbc84475aeb36efccc2103e6dbd", size = 459527, upload-time = "2026-05-19T10:07:18.741Z" }, + { url = "https://files.pythonhosted.org/packages/d1/7a/4a68d331aef8cf2e2393c14a3aacb635c62aa86071b0229899fb5baaa907/jiter-0.15.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:032396229564bca02440396bd327710719f724f5e7b7e9f7a8eb3faa4a2c2281", size = 375451, upload-time = "2026-05-19T10:07:20.208Z" }, + { url = "https://files.pythonhosted.org/packages/7b/7e/1c445c2b6f0e30a274dc8082e0c3c7825411cce80d726bccd697c98cc8d3/jiter-0.15.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3d37768fce7f88dd2a8c6091f2325dea27d30d30d5c6e7a1c0f0af77723b708", size = 349428, upload-time = "2026-05-19T10:07:22.372Z" }, + { url = "https://files.pythonhosted.org/packages/00/94/e20d38984fc17a636371bffd2ae0f698124fdc8e75ef969cd2da6ba7cea7/jiter-0.15.0-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:2c9cb907439d20bd0c7d7565ca01ee52234203208433749bae5b516907526928", size = 355405, upload-time = "2026-05-19T10:07:23.916Z" }, + { url = "https://files.pythonhosted.org/packages/94/fa/4d09f814779d0ea80a28ed8e4c6662ec9a4a8ecef0ac52190ebac6262d14/jiter-0.15.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9100ddbec09741cc66feb0fc6773f8bdbd0e3c345689368f260082ff85dcc0cd", size = 393688, upload-time = "2026-05-19T10:07:25.854Z" }, + { url = "https://files.pythonhosted.org/packages/54/9d/8eb5d4fb8bf7e93a75964a5da71a75c67c864baf7fa3f98598187b3c7e57/jiter-0.15.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ae1b0d82ac2d987f9ea512b1c9adfcc71a28de3dea3a6039b54d76cffda9901e", size = 520853, upload-time = "2026-05-19T10:07:27.303Z" }, + { url = "https://files.pythonhosted.org/packages/e7/2c/5e07874e59e623a943a0acf1552a80d05b70f31b402287a8fc6d7ec634c7/jiter-0.15.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8020c99ec13a7db2b6f96cbe82ef4721c88b426a4892f27478044af0284615ef", size = 551016, upload-time = "2026-05-19T10:07:28.846Z" }, + { url = "https://files.pythonhosted.org/packages/22/ed/d2d34422143474cadc15b60d482b1c35683dbc5c63c24346ddd0df09bcaf/jiter-0.15.0-cp311-cp311-win32.whl", hash = "sha256:42bfb257930800cf43e7c62c832402c704ab60797c992faf88d20e903eac8f32", size = 209518, upload-time = "2026-05-19T10:07:30.431Z" }, + { url = "https://files.pythonhosted.org/packages/1d/7d/52778b930e5cc3e52a37d950b1c10494244308b4329b25a0ff0d88303a81/jiter-0.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:860a74063284a2ae9bfedd694f299cc2c68e2696c5f3d440cc9d18bb81b9dd04", size = 200565, upload-time = "2026-05-19T10:07:32.125Z" }, + { url = "https://files.pythonhosted.org/packages/3b/4f/d9b4067feb69b3fa6eb0488e1b59e2ad5b463fe39f59e527eab2aca00bb0/jiter-0.15.0-cp311-cp311-win_arm64.whl", hash = "sha256:37a10c377ce3a4a85f4a67f28b7afe093154cde77eaf248a72e856aa08b4d865", size = 195488, upload-time = "2026-05-19T10:07:33.846Z" }, + { url = "https://files.pythonhosted.org/packages/44/53/4f6bddbcde3c71e56d0aa1337ec95950f3d27dd4153e25aadf0feac71751/jiter-0.15.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:0e90a1c315a0226ec822d973817967f9223b7701546c8c2a7913e7ab0926294d", size = 308793, upload-time = "2026-05-19T10:07:35.25Z" }, + { url = "https://files.pythonhosted.org/packages/01/84/c01099b59a285a1ebba64ae93f62bfa036675340fd1b0045ae65890a0442/jiter-0.15.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8c9004af7c8d67cce7f1aae1026fb55607f4aa600710d08ede3a3ce4aeefe7e0", size = 309570, upload-time = "2026-05-19T10:07:36.919Z" }, + { url = "https://files.pythonhosted.org/packages/58/64/8fb7f9d45bb98190355454cd04dad8d8f27223d6bd52f83af07f637168a6/jiter-0.15.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c210f8b35dc6f30aafd4b4365ca89b9d1189f21ab49b8e68fa6322a847aef138", size = 336783, upload-time = "2026-05-19T10:07:38.694Z" }, + { url = "https://files.pythonhosted.org/packages/c3/b6/f5739011d009b3a30f6a53c5240979030ba29ae46a8c67e3a15759f7c37d/jiter-0.15.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5f30bae8bc1c2d613e28e5af3e8cceb09b742f1c8a8a5f839fb67afaffc03b61", size = 363555, upload-time = "2026-05-19T10:07:40.832Z" }, + { url = "https://files.pythonhosted.org/packages/e5/12/98a9d9f766665e8a3b6252454e17cb0c464606a28cf2fa09399b003345fa/jiter-0.15.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c60e71b6d10cfc284c9bf36bd885e8d44c46f688ce50aa91b5edd90181dea687", size = 452255, upload-time = "2026-05-19T10:07:42.62Z" }, + { url = "https://files.pythonhosted.org/packages/e8/d5/60f972840f79c5e7544fce567c56f1e4e50468f996baba3e78d823dd62a6/jiter-0.15.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ab068bce62a45aa3e7367eceaffb5dde60b7eb853be8dece45132e3d0ff4879", size = 373559, upload-time = "2026-05-19T10:07:44.201Z" }, + { url = "https://files.pythonhosted.org/packages/ee/cf/d46ef1234ba335aabc2f013210db8e0821a22f5e644a2e9449df199ecc23/jiter-0.15.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa248c9eb220197d363f688818dac2fd4b2f0cd7d843ca7105d652034823427d", size = 346055, upload-time = "2026-05-19T10:07:46.005Z" }, + { url = "https://files.pythonhosted.org/packages/f0/63/4d2749d8d54d230bad9b3a6b0d00cc28c6ff6b2fdffc26a8ccf76cc5a974/jiter-0.15.0-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:2a77aadd57cac1682e4401a72724d2796d89a4ba129b1a5812aa94ee480826eb", size = 351406, upload-time = "2026-05-19T10:07:47.855Z" }, + { url = "https://files.pythonhosted.org/packages/d9/b9/9965b990035d8773328e0a8c8b457a87bf2b19f6c4126d9d99296be5d16a/jiter-0.15.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2ae901f3a55bfafdde31d289590fa25e3245735a2b1e8c7cc15871710a002871", size = 389357, upload-time = "2026-05-19T10:07:49.665Z" }, + { url = "https://files.pythonhosted.org/packages/2d/55/9ddf903deda1413e87fed792f416b7123daee5b8efbad6a202a7421c36a5/jiter-0.15.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:f0b271b462769543716f92d3a4f90527df6ef5ed05ee95ec4137f513e21e1b77", size = 517263, upload-time = "2026-05-19T10:07:51.537Z" }, + { url = "https://files.pythonhosted.org/packages/e8/76/a0c40ad064d3a20a4fde231e35d56e9a01ce82164278180e82d5daf85469/jiter-0.15.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2fb6a5d26af81fc0f00f9360a891e05cf755e149bba391c4d563adc54812973d", size = 548646, upload-time = "2026-05-19T10:07:53.196Z" }, + { url = "https://files.pythonhosted.org/packages/23/4f/eca9b954942916ba2f453891b8593ab444cd872396fe66a3936616f236f3/jiter-0.15.0-cp312-cp312-win32.whl", hash = "sha256:c2f6bb8b5216ab9e7873bc08b5d7bef2b8abbb578a3069bf1cd14a45d71d771d", size = 206427, upload-time = "2026-05-19T10:07:55.307Z" }, + { url = "https://files.pythonhosted.org/packages/95/bf/8ead82a87495149542748e828d153fd232a512a22c83b02c4815c1a9c7d8/jiter-0.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:40b2c7e92c44a84d748d21706c68dc6ff8161d80b59c99d774721a0d2317d7c7", size = 197300, upload-time = "2026-05-19T10:07:56.651Z" }, + { url = "https://files.pythonhosted.org/packages/f4/e4/9b8a78fb2d894471bc344e37f1949bdd784bd914d031dba0ba3a40c71dd7/jiter-0.15.0-cp312-cp312-win_arm64.whl", hash = "sha256:cc0bc345cf2df9d1c00ac443f50d543c1ccfa8b0422cb85b1ab70d681c0b255b", size = 192702, upload-time = "2026-05-19T10:07:58.307Z" }, + { url = "https://files.pythonhosted.org/packages/e5/f4/f708c900ecee41b2025ef8413d5351e5649eb2125c506f6720cc69b06f5c/jiter-0.15.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:1c11465f97e2abf45a014b83b730222f8f1c5335e802c7055a67d50de6f1f4e3", size = 307829, upload-time = "2026-05-19T10:07:59.704Z" }, + { url = "https://files.pythonhosted.org/packages/86/59/db537c0949e83668c38481d426b9f2fd5ab758c4ee53a811dd0a510626a0/jiter-0.15.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d1e7b1776f0797956c509e123d0952d10d293a9492dea9f288ab9570ec01d1a5", size = 308445, upload-time = "2026-05-19T10:08:01.184Z" }, + { url = "https://files.pythonhosted.org/packages/37/38/ea0e13b18c30ef951da0d47d39e7fa9edb82a93a62990ffbd7cea9b622d4/jiter-0.15.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:351a341c2105aa430b7047e30f1bf7975f6313b00165d3fc07be2edaf741f279", size = 336181, upload-time = "2026-05-19T10:08:02.688Z" }, + { url = "https://files.pythonhosted.org/packages/58/fc/2303901b16c4ba05865588990a420c0b4156270b44379c20931544a1d962/jiter-0.15.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4ab395feec8d249ec4044e228e98a7033f043426a265df439dc3698823f0a4e4", size = 362985, upload-time = "2026-05-19T10:08:04.394Z" }, + { url = "https://files.pythonhosted.org/packages/5b/6f/11bace093c52e7d4d26c8e606ccd7ae8c972189622469ec0d9e28161e28b/jiter-0.15.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a2a438005b6f22d0273413484d6094d7c2c5d10ec1b3a3bf128e0d1d3ba53258", size = 453292, upload-time = "2026-05-19T10:08:05.967Z" }, + { url = "https://files.pythonhosted.org/packages/22/db/987f2f086ca4d7a6582eb4ccd513f9b26b42d9e4243a087609a3137a8fc7/jiter-0.15.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f18f85e4218d1b40f000f42a92239a7a61a902cd42c65e6c360dbd17dcb20894", size = 373501, upload-time = "2026-05-19T10:08:07.857Z" }, + { url = "https://files.pythonhosted.org/packages/8f/7c/89fbcabb2739b7a5b8dc959a1b6c5761f6484f5fed3486854b3c789bb1de/jiter-0.15.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d1aa62e277fc1cbd80e6deacae6f4d983b41b3d7728e0645c5d741a6149bba45", size = 344683, upload-time = "2026-05-19T10:08:09.431Z" }, + { url = "https://files.pythonhosted.org/packages/30/6f/6cca7692e7dddfec6d8d76c54dc97f2af2a41df4ac0674b999df1f09a5f3/jiter-0.15.0-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:6550fa135c7deb8ead6af49ed7ff648532ea8334a1447fe34a36315ef79c5c29", size = 350892, upload-time = "2026-05-19T10:08:11.352Z" }, + { url = "https://files.pythonhosted.org/packages/39/14/0338d6190cb8e6d22e677ab1d4eabd4117f67cca70c54cd04b82ff64e068/jiter-0.15.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:066f8f33f18b2419cd8213b2436fa7fbc9c499f315971cfa3ce1f9820c001b1b", size = 388723, upload-time = "2026-05-19T10:08:12.912Z" }, + { url = "https://files.pythonhosted.org/packages/90/31/cc19f4a1bdb6afb09ce6a2f2615aa8d44d994eba0d8e6105ed1af920e736/jiter-0.15.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:75e8a04e91432dde9f1838373cf93d23726c79d3e908d319acf0e796f85592e7", size = 516648, upload-time = "2026-05-19T10:08:14.808Z" }, + { url = "https://files.pythonhosted.org/packages/49/9f/833c541512cd091b63c10c0381973dfe11bc7a503a818c16384417e0c81e/jiter-0.15.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:a97261f1fccb8e50ecd2890a96e46efdc3f57c80a197324c6777827231eca712", size = 547382, upload-time = "2026-05-19T10:08:16.927Z" }, + { url = "https://files.pythonhosted.org/packages/d2/11/e7b70e91f90bc4477e8eee9e8a5f7cf3cb41b4525d6394dc98a714eb8f7f/jiter-0.15.0-cp313-cp313-win32.whl", hash = "sha256:c77496cb10bd7549690fbbab3e5ec05857b83e49276f4a9423a766ddd2afcd4c", size = 205845, upload-time = "2026-05-19T10:08:18.401Z" }, + { url = "https://files.pythonhosted.org/packages/4b/23/5c20d9ad6f02c493e4023e5d2d09e1c1f15fe2753c9102c544aff068a88e/jiter-0.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:b15741f501469009ae0ae90b7147958a664a7dede40aa7ff174a8a4645f546d0", size = 196842, upload-time = "2026-05-19T10:08:20.131Z" }, + { url = "https://files.pythonhosted.org/packages/6b/11/1eb400ef248e8c925fd883fbe325daf5e42cd1b0d308539dd332bd4f7ffc/jiter-0.15.0-cp313-cp313-win_arm64.whl", hash = "sha256:5d6a60072b44c3c2b797a7ddcbcbbf2b34ea3cfd4721580fbfd2a09d9d9b84ba", size = 192212, upload-time = "2026-05-19T10:08:21.807Z" }, + { url = "https://files.pythonhosted.org/packages/8a/60/2fd8d7c79da8acf9b7b277c7616847773779356b92acfc9bb158452174da/jiter-0.15.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:ef1fd24d9413f6209e00d3d5a453e67acfe004a25cc6c8e8484faed4311ab9e8", size = 315065, upload-time = "2026-05-19T10:08:23.218Z" }, + { url = "https://files.pythonhosted.org/packages/46/f4/008fb7d65e8ac2abf00811651a661e025c4ba80bbc6f378450384ddd3aed/jiter-0.15.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:144f8e72cb53dab146347b91cceac01f5481237f2b93b4a339a1ee8f8878b67c", size = 339444, upload-time = "2026-05-19T10:08:24.701Z" }, + { url = "https://files.pythonhosted.org/packages/00/55/90b0c7b9c6896c0f2a591dd36d36b71d22e09674bfef178fa03ba3f81499/jiter-0.15.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:553fcac2ef2cb990877f9fc0833b8b629a3e6a5670b6b5fd58219b41a653ddc4", size = 347779, upload-time = "2026-05-19T10:08:26.408Z" }, + { url = "https://files.pythonhosted.org/packages/51/6b/69666cec5000fd57734c118437394516c749ae8dbeea9fb66d6fef9c4775/jiter-0.15.0-cp313-cp313t-win_amd64.whl", hash = "sha256:774f93f65031856bf14ad9f59bdcab8b8cad501e5ceabd51ba3525f76937a25b", size = 200395, upload-time = "2026-05-19T10:08:28.055Z" }, + { url = "https://files.pythonhosted.org/packages/39/04/a6aa62cd27e8149b0d28df5561f10f6cceaf7935a9ccf3f1c5a05f9a0cd8/jiter-0.15.0-cp313-cp313t-win_arm64.whl", hash = "sha256:f1e1754960f38ec40613a07e5e372df67acb3b890fb383b6fb3de3e49ddbf3c7", size = 190516, upload-time = "2026-05-19T10:08:29.35Z" }, + { url = "https://files.pythonhosted.org/packages/eb/d2/079f350ebf7859d081de30aa890f9e3be68516f754f3ba32366ffff4dcee/jiter-0.15.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:ac0d9ddea4350974be7a221fc25895f251a8fee748c889bdced2141c0fec1a49", size = 308884, upload-time = "2026-05-19T10:08:31.667Z" }, + { url = "https://files.pythonhosted.org/packages/04/4e/a2c30a7f69b48c03b20935d647479106fe932f6e63f75faf53937197e05d/jiter-0.15.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:01a8222cf05ab1128e239421156c207949808acaaea2bdfd33130ae666786e86", size = 310028, upload-time = "2026-05-19T10:08:33.304Z" }, + { url = "https://files.pythonhosted.org/packages/40/90/2e7cdfd3cf8ca967be38c48f5cf474d79f089efaf559a40f15984a77ae69/jiter-0.15.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:182226cbc930c9fab81bc2e41a4da672f89539906dadb05e75670ac07b94f71f", size = 337485, upload-time = "2026-05-19T10:08:35.259Z" }, + { url = "https://files.pythonhosted.org/packages/9b/11/15a1aa28b120b8ee5b4f1fb894c125046225f09847738bd64233d3b84883/jiter-0.15.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:71683c38c825452999b5717fcae07ea708e8c93003e808be4319c1b02e3d176e", size = 364223, upload-time = "2026-05-19T10:08:36.694Z" }, + { url = "https://files.pythonhosted.org/packages/b7/25/f442e8af5f3d0dcf47b39e83a0efd9ee45ea946aa6d04625dc3181eae3b6/jiter-0.15.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:30f2218e6a9e5c18bc10fe6d41ac189c442c88eacf11bad9f28ef95a9bef00e6", size = 456387, upload-time = "2026-05-19T10:08:38.143Z" }, + { url = "https://files.pythonhosted.org/packages/da/f4/37f2d2c9f64f49af7da652ed7532bb5a2372e588e6927c3fdd76f911db65/jiter-0.15.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5157de9f76eb4bc5ea74a1219366a25f945ad305641d74e04f59c54087091aa9", size = 374461, upload-time = "2026-05-19T10:08:39.869Z" }, + { url = "https://files.pythonhosted.org/packages/60/28/edcfbbbf0cb15436f36664a8908a0df47ab9006298d4cd937dc08ea932d6/jiter-0.15.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90c5db5527c221249a876160663ab891ace358c17f7b9c93ec1478b7f0550e5c", size = 345924, upload-time = "2026-05-19T10:08:41.668Z" }, + { url = "https://files.pythonhosted.org/packages/47/13/89fba6398dab7f202b7278c4b4aac122399d2c0183971c4a57a3b7088df5/jiter-0.15.0-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:3e4540b8e74e4268811ac05db226a6a128ff572e7e0ce3f1163b693cadb184cd", size = 352283, upload-time = "2026-05-19T10:08:43.091Z" }, + { url = "https://files.pythonhosted.org/packages/1b/da/0f6af8cef2c565a1ab44d970f268c43ccaa72707386ea6388e6fe2b6cd26/jiter-0.15.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:62ebd14e47e9aed9df4472afcb2663668ce4d74891cd54f86bf6e44029d6dc89", size = 389985, upload-time = "2026-05-19T10:08:44.915Z" }, + { url = "https://files.pythonhosted.org/packages/a1/ec/b9cb7d6d29e24ee14910266157d2a279d7a8f60ee0df7fa840882976ba64/jiter-0.15.0-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:0be6f5ad41a809f303f416d17cec92a7a725902fb9b4f3de3d19362ac0ef8554", size = 517695, upload-time = "2026-05-19T10:08:46.486Z" }, + { url = "https://files.pythonhosted.org/packages/64/5e/6d1bda880723aae0ad86b4b763f044362448efe31e3e819635d41cb03451/jiter-0.15.0-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:813dfbb17d65328bf86e5f0905dd277ba2265d3ca20556e86c0c7035b7182e5a", size = 548868, upload-time = "2026-05-19T10:08:48.026Z" }, + { url = "https://files.pythonhosted.org/packages/0c/72/7de501cf38dcacaf35098796f3a50e0f2e338baba18a58946c618544b809/jiter-0.15.0-cp314-cp314-win32.whl", hash = "sha256:50e51156192722a9c58db112837d3f8ef96fb3c5ecc14e95f409134b08b158ec", size = 206380, upload-time = "2026-05-19T10:08:49.738Z" }, + { url = "https://files.pythonhosted.org/packages/1e/a9/e19addf4b0c1bdce52c6da12351e6bc42c340c45e7c09e2158e46d293ccc/jiter-0.15.0-cp314-cp314-win_amd64.whl", hash = "sha256:30ce1a5d16b5641dc935d50ef775af6a0871e3d14ab05d6fc54dff371b78e558", size = 197687, upload-time = "2026-05-19T10:08:51.088Z" }, + { url = "https://files.pythonhosted.org/packages/f2/c9/776b1db01db25fc6c1d58d1979a37b0a9fe787e5f5b1d062d2eaacb77923/jiter-0.15.0-cp314-cp314-win_arm64.whl", hash = "sha256:510c8b3c17a0ed9ac69850c0438dada3c9b82d9c4d589fcb62002a5a9cf3a866", size = 192571, upload-time = "2026-05-19T10:08:52.451Z" }, + { url = "https://files.pythonhosted.org/packages/a0/f6/45bb4670bacf300fd2c7abadbfb3af376e5f1b6ae75fd9bc069891d15870/jiter-0.15.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7553333dd0930c104a5a0db8df72bf7219fe663d731383b576bb6ed6351c984d", size = 317151, upload-time = "2026-05-19T10:08:53.867Z" }, + { url = "https://files.pythonhosted.org/packages/d7/68/ed635ad5acd7b73e454283083bbb7c8205ad10e88b0d9d7d793b09fe8226/jiter-0.15.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f2143ab06181d2b029eedcb6af3cebe95f11bbac62441781860f98ee9330a6a6", size = 341243, upload-time = "2026-05-19T10:08:55.383Z" }, + { url = "https://files.pythonhosted.org/packages/5d/db/3ff4176b817b8ea33879e71e13d8bc2b0d481a7ed3fe9e080f333d415c16/jiter-0.15.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6eac374c5c975709b69c10f09afd199df74150172156ad10c8d4fd785b7da995", size = 363629, upload-time = "2026-05-19T10:08:56.928Z" }, + { url = "https://files.pythonhosted.org/packages/ab/24/5f8270e0ba9c883582f96f722f8a0b58015c7ce1f8c6d4571cf394e99b6b/jiter-0.15.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b3b3b775e33d3bfaec9899edc526ae97b0da0bf9d071a46124ba419149a414f8", size = 456198, upload-time = "2026-05-19T10:08:58.618Z" }, + { url = "https://files.pythonhosted.org/packages/45/5b/76fc02b0b5c54c3d18c60653156e2f76fde1816f9b4722db68d6ee2c897e/jiter-0.15.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eda3071db3346334beae1360b46da4606da57bf3528c167b3c38533afaf9f2c5", size = 373710, upload-time = "2026-05-19T10:09:00.151Z" }, + { url = "https://files.pythonhosted.org/packages/c4/52/4310821b0ea9277994d3e1f49fc6a4b34e4800caebacb2c0af81da59a454/jiter-0.15.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c6694a173ecabc12eb60efbc0b474464ead1951ff65cd8b1e72100715c64512b", size = 349901, upload-time = "2026-05-19T10:09:01.621Z" }, + { url = "https://files.pythonhosted.org/packages/93/fe/67648c35b3594fba8854ac64cc8a826d8bcd18324bbdb53d77697c60b6ef/jiter-0.15.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:a254e10b593624d230c365b6d616b22ca0ad65e63a16e6631c2b3466022e6ba8", size = 352438, upload-time = "2026-05-19T10:09:03.216Z" }, + { url = "https://files.pythonhosted.org/packages/cb/28/0a1879d07ad6b3e025a2750027363452ced93c2d16d1c9d4b153ffd51c91/jiter-0.15.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d8d2955167274e15d79a7a020afdd9b39c990eb80b2d89fca695d92dcfdd38ec", size = 388152, upload-time = "2026-05-19T10:09:04.741Z" }, + { url = "https://files.pythonhosted.org/packages/c1/78/46c6f6b56ba85c90021f4afd72ed42f691f8f84daacb5fe27277070e3858/jiter-0.15.0-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:acf4ee4d1fc55917239fe72972fb292dd773055d05eb040d36f4326e02cc2c0e", size = 517707, upload-time = "2026-05-19T10:09:06.231Z" }, + { url = "https://files.pythonhosted.org/packages/ca/cb/720662d4c88fcad606e826fef5424365527ba43ce4868a479aed8f8c507e/jiter-0.15.0-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:e7196e56f1cd69af1dbb07dff02dcfb260a50b45a82d409d92a06fedb32473b5", size = 548241, upload-time = "2026-05-19T10:09:08.093Z" }, + { url = "https://files.pythonhosted.org/packages/60/e3/935b8034fd143f21125c87d51404a9e0e1449186a494405721ff5d1d695e/jiter-0.15.0-cp314-cp314t-win32.whl", hash = "sha256:7f6163c0f10b055245f814dcc59f4818da60dfe72f3e72ab89fc24b6bd5e9c52", size = 207950, upload-time = "2026-05-19T10:09:09.616Z" }, + { url = "https://files.pythonhosted.org/packages/93/59/984fd9ece895953dad3e0880a650e766f5a2da2c5514f0eafdaaabbeb5f9/jiter-0.15.0-cp314-cp314t-win_amd64.whl", hash = "sha256:980c256edb05b78a111b99c4de3b1d32e31634b867fd1fc2cf726e7b7bba9854", size = 200055, upload-time = "2026-05-19T10:09:11.367Z" }, + { url = "https://files.pythonhosted.org/packages/0e/a4/cf8d779feb133a27a2e3bc833bccb9e13aa332cdf820497ebf72c10ce8c3/jiter-0.15.0-cp314-cp314t-win_arm64.whl", hash = "sha256:66b1880df2d01e206e8339769d1c7c1753bcb653efd6289e203f6f24ebada0c0", size = 191244, upload-time = "2026-05-19T10:09:12.74Z" }, + { url = "https://files.pythonhosted.org/packages/65/43/1fc62172aa98b50a7de9a25554060db510f85c89cfbed0dfe13e1907a139/jiter-0.15.0-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:411fa4dfa5a7ae3d11491027ffb9beadec3996010a986862db70d91abba1c750", size = 305585, upload-time = "2026-05-19T10:09:35.995Z" }, + { url = "https://files.pythonhosted.org/packages/e8/c4/dd58fcd9e2df83666e5c1c1347bef58ce919cd8efc3ffa38aeea62ce493b/jiter-0.15.0-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:2b0074e2f56eb2dacca1689760fd2852a068f85a0547a157b82cb4cafeb6768b", size = 306936, upload-time = "2026-05-19T10:09:37.435Z" }, + { url = "https://files.pythonhosted.org/packages/39/86/b695e16f1180c07f43ea98e73ecd21cf63fa2e1b0c1103739013784d11ae/jiter-0.15.0-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:913d02d29c9606643418d9ccfc3b72492ab25a6bf7889934e09a3490f8d3438b", size = 342453, upload-time = "2026-05-19T10:09:39.294Z" }, + { url = "https://files.pythonhosted.org/packages/34/56/55d76614af37fe3f22a3347d1e410d2a15da581997cb2da499a625000bb5/jiter-0.15.0-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b15d3ec9b0449c40e85319bdb4caa8b77ab526e74f5532ed94bec15e2f66822c", size = 345606, upload-time = "2026-05-19T10:09:40.727Z" }, + { url = "https://files.pythonhosted.org/packages/73/38/505941b2b092fd5bbbd60a52a880db1173f1690ae6751bed3af1c9ddcb4e/jiter-0.15.0-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:631f13a3d04e97d4e083993b10f4b99530e3a10d953e2eb5e196b7dc7f812ce0", size = 303769, upload-time = "2026-05-19T10:09:42.203Z" }, + { url = "https://files.pythonhosted.org/packages/e7/95/a06692b29e77473f286e1ec1f426d3ca44d7b5843be8ad21d7a5f3fcdcc0/jiter-0.15.0-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:b6c0ffae686c39bf3737be60793783267628783ea42545632c10b291105aee45", size = 305128, upload-time = "2026-05-19T10:09:43.657Z" }, + { url = "https://files.pythonhosted.org/packages/23/85/7270d7ad41d6061a25b950c6bf91d638bd9aacb113200a8c8d57a055fd67/jiter-0.15.0-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d54fb5b31dea401a41af3f8a7d2512e9b6a6a005491e6166c7e4ffab9639a9c", size = 340459, upload-time = "2026-05-19T10:09:45.452Z" }, + { url = "https://files.pythonhosted.org/packages/c8/8d/302cb2057b7513327b4d575cff6b1d066ee6431a5357fc3f8867cd684406/jiter-0.15.0-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:54d5d6090cdc1b7c9e780dfb04949a990adb1e301a2fc0bbcee7de4638d33f9a", size = 344469, upload-time = "2026-05-19T10:09:46.864Z" }, +] + +[[package]] +name = "joblib" +version = "1.5.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/41/f2/d34e8b3a08a9cc79a50b2208a93dce981fe615b64d5a4d4abee421d898df/joblib-1.5.3.tar.gz", hash = "sha256:8561a3269e6801106863fd0d6d84bb737be9e7631e33aaed3fb9ce5953688da3", size = 331603, upload-time = "2025-12-15T08:41:46.427Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7b/91/984aca2ec129e2757d1e4e3c81c3fcda9d0f85b74670a094cc443d9ee949/joblib-1.5.3-py3-none-any.whl", hash = "sha256:5fc3c5039fc5ca8c0276333a188bbd59d6b7ab37fe6632daa76bc7f9ec18e713", size = 309071, upload-time = "2025-12-15T08:41:44.973Z" }, +] + +[[package]] +name = "jsonschema" +version = "4.26.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "jsonschema-specifications" }, + { name = "referencing" }, + { name = "rpds-py" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b3/fc/e067678238fa451312d4c62bf6e6cf5ec56375422aee02f9cb5f909b3047/jsonschema-4.26.0.tar.gz", hash = "sha256:0c26707e2efad8aa1bfc5b7ce170f3fccc2e4918ff85989ba9ffa9facb2be326", size = 366583, upload-time = "2026-01-07T13:41:07.246Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/69/90/f63fb5873511e014207a475e2bb4e8b2e570d655b00ac19a9a0ca0a385ee/jsonschema-4.26.0-py3-none-any.whl", hash = "sha256:d489f15263b8d200f8387e64b4c3a75f06629559fb73deb8fdfb525f2dab50ce", size = 90630, upload-time = "2026-01-07T13:41:05.306Z" }, +] + +[[package]] +name = "jsonschema-specifications" +version = "2025.9.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "referencing" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/19/74/a633ee74eb36c44aa6d1095e7cc5569bebf04342ee146178e2d36600708b/jsonschema_specifications-2025.9.1.tar.gz", hash = "sha256:b540987f239e745613c7a9176f3edb72b832a4ac465cf02712288397832b5e8d", size = 32855, upload-time = "2025-09-08T01:34:59.186Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl", hash = "sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe", size = 18437, upload-time = "2025-09-08T01:34:57.871Z" }, +] + +[[package]] +name = "keyring" +version = "25.7.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "importlib-metadata", marker = "python_full_version < '3.12'" }, + { name = "jaraco-classes" }, + { name = "jaraco-context" }, + { name = "jaraco-functools" }, + { name = "jeepney", marker = "sys_platform == 'linux'" }, + { name = "pywin32-ctypes", marker = "sys_platform == 'win32'" }, + { name = "secretstorage", marker = "sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/43/4b/674af6ef2f97d56f0ab5153bf0bfa28ccb6c3ed4d1babf4305449668807b/keyring-25.7.0.tar.gz", hash = "sha256:fe01bd85eb3f8fb3dd0405defdeac9a5b4f6f0439edbb3149577f244a2e8245b", size = 63516, upload-time = "2025-11-16T16:26:09.482Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/81/db/e655086b7f3a705df045bf0933bdd9c2f79bb3c97bfef1384598bb79a217/keyring-25.7.0-py3-none-any.whl", hash = "sha256:be4a0b195f149690c166e850609a477c532ddbfbaed96a404d4e43f8d5e2689f", size = 39160, upload-time = "2025-11-16T16:26:08.402Z" }, +] + +[[package]] +name = "kiwisolver" +version = "1.5.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d0/67/9c61eccb13f0bdca9307614e782fec49ffdde0f7a2314935d489fa93cd9c/kiwisolver-1.5.0.tar.gz", hash = "sha256:d4193f3d9dc3f6f79aaed0e5637f45d98850ebf01f7ca20e69457f3e8946b66a", size = 103482, upload-time = "2026-03-09T13:15:53.382Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/12/dd/a495a9c104be1c476f0386e714252caf2b7eca883915422a64c50b88c6f5/kiwisolver-1.5.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9eed0f7edbb274413b6ee781cca50541c8c0facd3d6fd289779e494340a2b85c", size = 122798, upload-time = "2026-03-09T13:12:58.963Z" }, + { url = "https://files.pythonhosted.org/packages/11/60/37b4047a2af0cf5ef6d8b4b26e91829ae6fc6a2d1f74524bcb0e7cd28a32/kiwisolver-1.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3c4923e404d6bcd91b6779c009542e5647fef32e4a5d75e115e3bbac6f2335eb", size = 66216, upload-time = "2026-03-09T13:13:00.155Z" }, + { url = "https://files.pythonhosted.org/packages/0a/aa/510dc933d87767584abfe03efa445889996c70c2990f6f87c3ebaa0a18c5/kiwisolver-1.5.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0df54df7e686afa55e6f21fb86195224a6d9beb71d637e8d7920c95cf0f89aac", size = 63911, upload-time = "2026-03-09T13:13:01.671Z" }, + { url = "https://files.pythonhosted.org/packages/80/46/bddc13df6c2a40741e0cc7865bb1c9ed4796b6760bd04ce5fae3928ef917/kiwisolver-1.5.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:2517e24d7315eb51c10664cdb865195df38ab74456c677df67bb47f12d088a27", size = 1438209, upload-time = "2026-03-09T13:13:03.385Z" }, + { url = "https://files.pythonhosted.org/packages/fd/d6/76621246f5165e5372f02f5e6f3f48ea336a8f9e96e43997d45b240ed8cd/kiwisolver-1.5.0-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ff710414307fefa903e0d9bdf300972f892c23477829f49504e59834f4195398", size = 1248888, upload-time = "2026-03-09T13:13:05.231Z" }, + { url = "https://files.pythonhosted.org/packages/b2/c1/31559ec6fb39a5b48035ce29bb63ade628f321785f38c384dee3e2c08bc1/kiwisolver-1.5.0-cp311-cp311-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6176c1811d9d5a04fa391c490cc44f451e240697a16977f11c6f722efb9041db", size = 1266304, upload-time = "2026-03-09T13:13:06.743Z" }, + { url = "https://files.pythonhosted.org/packages/5e/ef/1cb8276f2d29cc6a41e0a042f27946ca347d3a4a75acf85d0a16aa6dcc82/kiwisolver-1.5.0-cp311-cp311-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:50847dca5d197fcbd389c805aa1a1cf32f25d2e7273dc47ab181a517666b68cc", size = 1319650, upload-time = "2026-03-09T13:13:08.607Z" }, + { url = "https://files.pythonhosted.org/packages/4c/e4/5ba3cecd7ce6236ae4a80f67e5d5531287337d0e1f076ca87a5abe4cd5d0/kiwisolver-1.5.0-cp311-cp311-manylinux_2_39_riscv64.whl", hash = "sha256:01808c6d15f4c3e8559595d6d1fe6411c68e4a3822b4b9972b44473b24f4e679", size = 970949, upload-time = "2026-03-09T13:13:10.299Z" }, + { url = "https://files.pythonhosted.org/packages/5a/69/dc61f7ae9a2f071f26004ced87f078235b5507ab6e5acd78f40365655034/kiwisolver-1.5.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:f1f9f4121ec58628c96baa3de1a55a4e3a333c5102c8e94b64e23bf7b2083309", size = 2199125, upload-time = "2026-03-09T13:13:11.841Z" }, + { url = "https://files.pythonhosted.org/packages/e5/7b/abbe0f1b5afa85f8d084b73e90e5f801c0939eba16ac2e49af7c61a6c28d/kiwisolver-1.5.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:b7d335370ae48a780c6e6a6bbfa97342f563744c39c35562f3f367665f5c1de2", size = 2293783, upload-time = "2026-03-09T13:13:14.399Z" }, + { url = "https://files.pythonhosted.org/packages/8a/80/5908ae149d96d81580d604c7f8aefd0e98f4fd728cf172f477e9f2a81744/kiwisolver-1.5.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:800ee55980c18545af444d93fdd60c56b580db5cc54867d8cbf8a1dc0829938c", size = 1960726, upload-time = "2026-03-09T13:13:16.047Z" }, + { url = "https://files.pythonhosted.org/packages/84/08/a78cb776f8c085b7143142ce479859cfec086bd09ee638a317040b6ef420/kiwisolver-1.5.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:c438f6ca858697c9ab67eb28246c92508af972e114cac34e57a6d4ba17a3ac08", size = 2464738, upload-time = "2026-03-09T13:13:17.897Z" }, + { url = "https://files.pythonhosted.org/packages/b1/e1/65584da5356ed6cb12c63791a10b208860ac40a83de165cb6a6751a686e3/kiwisolver-1.5.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:8c63c91f95173f9c2a67c7c526b2cea976828a0e7fced9cdcead2802dc10f8a4", size = 2270718, upload-time = "2026-03-09T13:13:19.421Z" }, + { url = "https://files.pythonhosted.org/packages/be/6c/28f17390b62b8f2f520e2915095b3c94d88681ecf0041e75389d9667f202/kiwisolver-1.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:beb7f344487cdcb9e1efe4b7a29681b74d34c08f0043a327a74da852a6749e7b", size = 73480, upload-time = "2026-03-09T13:13:20.818Z" }, + { url = "https://files.pythonhosted.org/packages/d8/0e/2ee5debc4f77a625778fec5501ff3e8036fe361b7ee28ae402a485bb9694/kiwisolver-1.5.0-cp311-cp311-win_arm64.whl", hash = "sha256:ad4ae4ffd1ee9cd11357b4c66b612da9888f4f4daf2f36995eda64bd45370cac", size = 64930, upload-time = "2026-03-09T13:13:21.997Z" }, + { url = "https://files.pythonhosted.org/packages/4d/b2/818b74ebea34dabe6d0c51cb1c572e046730e64844da6ed646d5298c40ce/kiwisolver-1.5.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:4e9750bc21b886308024f8a54ccb9a2cc38ac9fa813bf4348434e3d54f337ff9", size = 123158, upload-time = "2026-03-09T13:13:23.127Z" }, + { url = "https://files.pythonhosted.org/packages/bf/d9/405320f8077e8e1c5c4bd6adc45e1e6edf6d727b6da7f2e2533cf58bff71/kiwisolver-1.5.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:72ec46b7eba5b395e0a7b63025490d3214c11013f4aacb4f5e8d6c3041829588", size = 66388, upload-time = "2026-03-09T13:13:24.765Z" }, + { url = "https://files.pythonhosted.org/packages/99/9f/795fedf35634f746151ca8839d05681ceb6287fbed6cc1c9bf235f7887c2/kiwisolver-1.5.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ed3a984b31da7481b103f68776f7128a89ef26ed40f4dc41a2223cda7fb24819", size = 64068, upload-time = "2026-03-09T13:13:25.878Z" }, + { url = "https://files.pythonhosted.org/packages/c4/13/680c54afe3e65767bed7ec1a15571e1a2f1257128733851ade24abcefbcc/kiwisolver-1.5.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:bb5136fb5352d3f422df33f0c879a1b0c204004324150cc3b5e3c4f310c9049f", size = 1477934, upload-time = "2026-03-09T13:13:27.166Z" }, + { url = "https://files.pythonhosted.org/packages/c8/2f/cebfcdb60fd6a9b0f6b47a9337198bcbad6fbe15e68189b7011fd914911f/kiwisolver-1.5.0-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b2af221f268f5af85e776a73d62b0845fc8baf8ef0abfae79d29c77d0e776aaf", size = 1278537, upload-time = "2026-03-09T13:13:28.707Z" }, + { url = "https://files.pythonhosted.org/packages/f2/0d/9b782923aada3fafb1d6b84e13121954515c669b18af0c26e7d21f579855/kiwisolver-1.5.0-cp312-cp312-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b0f172dc8ffaccb8522d7c5d899de00133f2f1ca7b0a49b7da98e901de87bf2d", size = 1296685, upload-time = "2026-03-09T13:13:30.528Z" }, + { url = "https://files.pythonhosted.org/packages/27/70/83241b6634b04fe44e892688d5208332bde130f38e610c0418f9ede47ded/kiwisolver-1.5.0-cp312-cp312-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6ab8ba9152203feec73758dad83af9a0bbe05001eb4639e547207c40cfb52083", size = 1346024, upload-time = "2026-03-09T13:13:32.818Z" }, + { url = "https://files.pythonhosted.org/packages/e4/db/30ed226fb271ae1a6431fc0fe0edffb2efe23cadb01e798caeb9f2ceae8f/kiwisolver-1.5.0-cp312-cp312-manylinux_2_39_riscv64.whl", hash = "sha256:cdee07c4d7f6d72008d3f73b9bf027f4e11550224c7c50d8df1ae4a37c1402a6", size = 987241, upload-time = "2026-03-09T13:13:34.435Z" }, + { url = "https://files.pythonhosted.org/packages/ec/bd/c314595208e4c9587652d50959ead9e461995389664e490f4dce7ff0f782/kiwisolver-1.5.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7c60d3c9b06fb23bd9c6139281ccbdc384297579ae037f08ae90c69f6845c0b1", size = 2227742, upload-time = "2026-03-09T13:13:36.4Z" }, + { url = "https://files.pythonhosted.org/packages/c1/43/0499cec932d935229b5543d073c2b87c9c22846aab48881e9d8d6e742a2d/kiwisolver-1.5.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:e315e5ec90d88e140f57696ff85b484ff68bb311e36f2c414aa4286293e6dee0", size = 2323966, upload-time = "2026-03-09T13:13:38.204Z" }, + { url = "https://files.pythonhosted.org/packages/3d/6f/79b0d760907965acfd9d61826a3d41f8f093c538f55cd2633d3f0db269f6/kiwisolver-1.5.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:1465387ac63576c3e125e5337a6892b9e99e0627d52317f3ca79e6930d889d15", size = 1977417, upload-time = "2026-03-09T13:13:39.966Z" }, + { url = "https://files.pythonhosted.org/packages/ab/31/01d0537c41cb75a551a438c3c7a80d0c60d60b81f694dac83dd436aec0d0/kiwisolver-1.5.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:530a3fd64c87cffa844d4b6b9768774763d9caa299e9b75d8eca6a4423b31314", size = 2491238, upload-time = "2026-03-09T13:13:41.698Z" }, + { url = "https://files.pythonhosted.org/packages/e4/34/8aefdd0be9cfd00a44509251ba864f5caf2991e36772e61c408007e7f417/kiwisolver-1.5.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1d9daea4ea6b9be74fe2f01f7fbade8d6ffab263e781274cffca0dba9be9eec9", size = 2294947, upload-time = "2026-03-09T13:13:43.343Z" }, + { url = "https://files.pythonhosted.org/packages/ad/cf/0348374369ca588f8fe9c338fae49fa4e16eeb10ffb3d012f23a54578a9e/kiwisolver-1.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:f18c2d9782259a6dc132fdc7a63c168cbc74b35284b6d75c673958982a378384", size = 73569, upload-time = "2026-03-09T13:13:45.792Z" }, + { url = "https://files.pythonhosted.org/packages/28/26/192b26196e2316e2bd29deef67e37cdf9870d9af8e085e521afff0fed526/kiwisolver-1.5.0-cp312-cp312-win_arm64.whl", hash = "sha256:f7c7553b13f69c1b29a5bde08ddc6d9d0c8bfb84f9ed01c30db25944aeb852a7", size = 64997, upload-time = "2026-03-09T13:13:46.878Z" }, + { url = "https://files.pythonhosted.org/packages/9d/69/024d6711d5ba575aa65d5538042e99964104e97fa153a9f10bc369182bc2/kiwisolver-1.5.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:fd40bb9cd0891c4c3cb1ddf83f8bbfa15731a248fdc8162669405451e2724b09", size = 123166, upload-time = "2026-03-09T13:13:48.032Z" }, + { url = "https://files.pythonhosted.org/packages/ce/48/adbb40df306f587054a348831220812b9b1d787aff714cfbc8556e38fccd/kiwisolver-1.5.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c0e1403fd7c26d77c1f03e096dc58a5c726503fa0db0456678b8668f76f521e3", size = 66395, upload-time = "2026-03-09T13:13:49.365Z" }, + { url = "https://files.pythonhosted.org/packages/a8/3a/d0a972b34e1c63e2409413104216cd1caa02c5a37cb668d1687d466c1c45/kiwisolver-1.5.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:dda366d548e89a90d88a86c692377d18d8bd64b39c1fb2b92cb31370e2896bbd", size = 64065, upload-time = "2026-03-09T13:13:50.562Z" }, + { url = "https://files.pythonhosted.org/packages/2b/0a/7b98e1e119878a27ba8618ca1e18b14f992ff1eda40f47bccccf4de44121/kiwisolver-1.5.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:332b4f0145c30b5f5ad9374881133e5aa64320428a57c2c2b61e9d891a51c2f3", size = 1477903, upload-time = "2026-03-09T13:13:52.084Z" }, + { url = "https://files.pythonhosted.org/packages/18/d8/55638d89ffd27799d5cc3d8aa28e12f4ce7a64d67b285114dbedc8ea4136/kiwisolver-1.5.0-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0c50b89ffd3e1a911c69a1dd3de7173c0cd10b130f56222e57898683841e4f96", size = 1278751, upload-time = "2026-03-09T13:13:54.673Z" }, + { url = "https://files.pythonhosted.org/packages/b8/97/b4c8d0d18421ecceba20ad8701358453b88e32414e6f6950b5a4bad54e65/kiwisolver-1.5.0-cp313-cp313-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4db576bb8c3ef9365f8b40fe0f671644de6736ae2c27a2c62d7d8a1b4329f099", size = 1296793, upload-time = "2026-03-09T13:13:56.287Z" }, + { url = "https://files.pythonhosted.org/packages/c4/10/f862f94b6389d8957448ec9df59450b81bec4abb318805375c401a1e6892/kiwisolver-1.5.0-cp313-cp313-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0b85aad90cea8ac6797a53b5d5f2e967334fa4d1149f031c4537569972596cb8", size = 1346041, upload-time = "2026-03-09T13:13:58.269Z" }, + { url = "https://files.pythonhosted.org/packages/a3/6a/f1650af35821eaf09de398ec0bc2aefc8f211f0cda50204c9f1673741ba9/kiwisolver-1.5.0-cp313-cp313-manylinux_2_39_riscv64.whl", hash = "sha256:d36ca54cb4c6c4686f7cbb7b817f66f5911c12ddb519450bbe86707155028f87", size = 987292, upload-time = "2026-03-09T13:13:59.871Z" }, + { url = "https://files.pythonhosted.org/packages/de/19/d7fb82984b9238115fe629c915007be608ebd23dc8629703d917dbfaffd4/kiwisolver-1.5.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:38f4a703656f493b0ad185211ccfca7f0386120f022066b018eb5296d8613e23", size = 2227865, upload-time = "2026-03-09T13:14:01.401Z" }, + { url = "https://files.pythonhosted.org/packages/7f/b9/46b7f386589fd222dac9e9de9c956ce5bcefe2ee73b4e79891381dda8654/kiwisolver-1.5.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:3ac2360e93cb41be81121755c6462cff3beaa9967188c866e5fce5cf13170859", size = 2324369, upload-time = "2026-03-09T13:14:02.972Z" }, + { url = "https://files.pythonhosted.org/packages/92/8b/95e237cf3d9c642960153c769ddcbe278f182c8affb20cecc1cc983e7cc5/kiwisolver-1.5.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:c95cab08d1965db3d84a121f1c7ce7479bdd4072c9b3dafd8fecce48a2e6b902", size = 1977989, upload-time = "2026-03-09T13:14:04.503Z" }, + { url = "https://files.pythonhosted.org/packages/1b/95/980c9df53501892784997820136c01f62bc1865e31b82b9560f980c0e649/kiwisolver-1.5.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:fc20894c3d21194d8041a28b65622d5b86db786da6e3cfe73f0c762951a61167", size = 2491645, upload-time = "2026-03-09T13:14:06.106Z" }, + { url = "https://files.pythonhosted.org/packages/cb/32/900647fd0840abebe1561792c6b31e6a7c0e278fc3973d30572a965ca14c/kiwisolver-1.5.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7a32f72973f0f950c1920475d5c5ea3d971b81b6f0ec53b8d0a956cc965f22e0", size = 2295237, upload-time = "2026-03-09T13:14:08.891Z" }, + { url = "https://files.pythonhosted.org/packages/be/8a/be60e3bbcf513cc5a50f4a3e88e1dcecebb79c1ad607a7222877becaa101/kiwisolver-1.5.0-cp313-cp313-win_amd64.whl", hash = "sha256:0bf3acf1419fa93064a4c2189ac0b58e3be7872bf6ee6177b0d4c63dc4cea276", size = 73573, upload-time = "2026-03-09T13:14:12.327Z" }, + { url = "https://files.pythonhosted.org/packages/4d/d2/64be2e429eb4fca7f7e1c52a91b12663aeaf25de3895e5cca0f47ef2a8d0/kiwisolver-1.5.0-cp313-cp313-win_arm64.whl", hash = "sha256:fa8eb9ecdb7efb0b226acec134e0d709e87a909fa4971a54c0c4f6e88635484c", size = 64998, upload-time = "2026-03-09T13:14:13.469Z" }, + { url = "https://files.pythonhosted.org/packages/b0/69/ce68dd0c85755ae2de490bf015b62f2cea5f6b14ff00a463f9d0774449ff/kiwisolver-1.5.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:db485b3847d182b908b483b2ed133c66d88d49cacf98fd278fadafe11b4478d1", size = 125700, upload-time = "2026-03-09T13:14:14.636Z" }, + { url = "https://files.pythonhosted.org/packages/74/aa/937aac021cf9d4349990d47eb319309a51355ed1dbdc9c077cdc9224cb11/kiwisolver-1.5.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:be12f931839a3bdfe28b584db0e640a65a8bcbc24560ae3fdb025a449b3d754e", size = 67537, upload-time = "2026-03-09T13:14:15.808Z" }, + { url = "https://files.pythonhosted.org/packages/ee/20/3a87fbece2c40ad0f6f0aefa93542559159c5f99831d596050e8afae7a9f/kiwisolver-1.5.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:16b85d37c2cbb3253226d26e64663f755d88a03439a9c47df6246b35defbdfb7", size = 65514, upload-time = "2026-03-09T13:14:18.035Z" }, + { url = "https://files.pythonhosted.org/packages/f0/7f/f943879cda9007c45e1f7dba216d705c3a18d6b35830e488b6c6a4e7cdf0/kiwisolver-1.5.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4432b835675f0ea7414aab3d37d119f7226d24869b7a829caeab49ebda407b0c", size = 1584848, upload-time = "2026-03-09T13:14:19.745Z" }, + { url = "https://files.pythonhosted.org/packages/37/f8/4d4f85cc1870c127c88d950913370dd76138482161cd07eabbc450deff01/kiwisolver-1.5.0-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1b0feb50971481a2cc44d94e88bdb02cdd497618252ae226b8eb1201b957e368", size = 1391542, upload-time = "2026-03-09T13:14:21.54Z" }, + { url = "https://files.pythonhosted.org/packages/04/0b/65dd2916c84d252b244bd405303220f729e7c17c9d7d33dca6feeff9ffc4/kiwisolver-1.5.0-cp313-cp313t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:56fa888f10d0f367155e76ce849fa1166fc9730d13bd2d65a2aa13b6f5424489", size = 1404447, upload-time = "2026-03-09T13:14:23.205Z" }, + { url = "https://files.pythonhosted.org/packages/39/5c/2606a373247babce9b1d056c03a04b65f3cf5290a8eac5d7bdead0a17e21/kiwisolver-1.5.0-cp313-cp313t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:940dda65d5e764406b9fb92761cbf462e4e63f712ab60ed98f70552e496f3bf1", size = 1455918, upload-time = "2026-03-09T13:14:24.74Z" }, + { url = "https://files.pythonhosted.org/packages/d5/d1/c6078b5756670658e9192a2ef11e939c92918833d2745f85cd14a6004bdf/kiwisolver-1.5.0-cp313-cp313t-manylinux_2_39_riscv64.whl", hash = "sha256:89fc958c702ee9a745e4700378f5d23fddbc46ff89e8fdbf5395c24d5c1452a3", size = 1072856, upload-time = "2026-03-09T13:14:26.597Z" }, + { url = "https://files.pythonhosted.org/packages/cb/c8/7def6ddf16eb2b3741d8b172bdaa9af882b03c78e9b0772975408801fa63/kiwisolver-1.5.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9027d773c4ff81487181a925945743413f6069634d0b122d0b37684ccf4f1e18", size = 2333580, upload-time = "2026-03-09T13:14:28.237Z" }, + { url = "https://files.pythonhosted.org/packages/9e/87/2ac1fce0eb1e616fcd3c35caa23e665e9b1948bb984f4764790924594128/kiwisolver-1.5.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:5b233ea3e165e43e35dba1d2b8ecc21cf070b45b65ae17dd2747d2713d942021", size = 2423018, upload-time = "2026-03-09T13:14:30.018Z" }, + { url = "https://files.pythonhosted.org/packages/67/13/c6700ccc6cc218716bfcda4935e4b2997039869b4ad8a94f364c5a3b8e63/kiwisolver-1.5.0-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:ce9bf03dad3b46408c08649c6fbd6ca28a9fce0eb32fdfffa6775a13103b5310", size = 2062804, upload-time = "2026-03-09T13:14:32.888Z" }, + { url = "https://files.pythonhosted.org/packages/1b/bd/877056304626943ff0f1f44c08f584300c199b887cb3176cd7e34f1515f1/kiwisolver-1.5.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:fc4d3f1fb9ca0ae9f97b095963bc6326f1dbfd3779d6679a1e016b9baaa153d3", size = 2597482, upload-time = "2026-03-09T13:14:34.971Z" }, + { url = "https://files.pythonhosted.org/packages/75/19/c60626c47bf0f8ac5dcf72c6c98e266d714f2fbbfd50cf6dab5ede3aaa50/kiwisolver-1.5.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f443b4825c50a51ee68585522ab4a1d1257fac65896f282b4c6763337ac9f5d2", size = 2394328, upload-time = "2026-03-09T13:14:36.816Z" }, + { url = "https://files.pythonhosted.org/packages/47/84/6a6d5e5bb8273756c27b7d810d47f7ef2f1f9b9fd23c9ee9a3f8c75c9cef/kiwisolver-1.5.0-cp313-cp313t-win_arm64.whl", hash = "sha256:893ff3a711d1b515ba9da14ee090519bad4610ed1962fbe298a434e8c5f8db53", size = 68410, upload-time = "2026-03-09T13:14:38.695Z" }, + { url = "https://files.pythonhosted.org/packages/e4/d7/060f45052f2a01ad5762c8fdecd6d7a752b43400dc29ff75cd47225a40fd/kiwisolver-1.5.0-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:8df31fe574b8b3993cc61764f40941111b25c2d9fea13d3ce24a49907cd2d615", size = 123231, upload-time = "2026-03-09T13:14:41.323Z" }, + { url = "https://files.pythonhosted.org/packages/c2/a7/78da680eadd06ff35edef6ef68a1ad273bad3e2a0936c9a885103230aece/kiwisolver-1.5.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:1d49a49ac4cbfb7c1375301cd1ec90169dfeae55ff84710d782260ce77a75a02", size = 66489, upload-time = "2026-03-09T13:14:42.534Z" }, + { url = "https://files.pythonhosted.org/packages/49/b2/97980f3ad4fae37dd7fe31626e2bf75fbf8bdf5d303950ec1fab39a12da8/kiwisolver-1.5.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:0cbe94b69b819209a62cb27bdfa5dc2a8977d8de2f89dfd97ba4f53ed3af754e", size = 64063, upload-time = "2026-03-09T13:14:44.759Z" }, + { url = "https://files.pythonhosted.org/packages/e7/f9/b06c934a6aa8bc91f566bd2a214fd04c30506c2d9e2b6b171953216a65b6/kiwisolver-1.5.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:80aa065ffd378ff784822a6d7c3212f2d5f5e9c3589614b5c228b311fd3063ac", size = 1475913, upload-time = "2026-03-09T13:14:46.247Z" }, + { url = "https://files.pythonhosted.org/packages/6b/f0/f768ae564a710135630672981231320bc403cf9152b5596ec5289de0f106/kiwisolver-1.5.0-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4e7f886f47ab881692f278ae901039a234e4025a68e6dfab514263a0b1c4ae05", size = 1282782, upload-time = "2026-03-09T13:14:48.458Z" }, + { url = "https://files.pythonhosted.org/packages/e2/9f/1de7aad00697325f05238a5f2eafbd487fb637cc27a558b5367a5f37fb7f/kiwisolver-1.5.0-cp314-cp314-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5060731cc3ed12ca3a8b57acd4aeca5bbc2f49216dd0bec1650a1acd89486bcd", size = 1300815, upload-time = "2026-03-09T13:14:50.721Z" }, + { url = "https://files.pythonhosted.org/packages/5a/c2/297f25141d2e468e0ce7f7a7b92e0cf8918143a0cbd3422c1ad627e85a06/kiwisolver-1.5.0-cp314-cp314-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7a4aa69609f40fce3cbc3f87b2061f042eee32f94b8f11db707b66a26461591a", size = 1347925, upload-time = "2026-03-09T13:14:52.304Z" }, + { url = "https://files.pythonhosted.org/packages/b9/d3/f4c73a02eb41520c47610207b21afa8cdd18fdbf64ffd94674ae21c4812d/kiwisolver-1.5.0-cp314-cp314-manylinux_2_39_riscv64.whl", hash = "sha256:d168fda2dbff7b9b5f38e693182d792a938c31db4dac3a80a4888de603c99554", size = 991322, upload-time = "2026-03-09T13:14:54.637Z" }, + { url = "https://files.pythonhosted.org/packages/7b/46/d3f2efef7732fcda98d22bf4ad5d3d71d545167a852ca710a494f4c15343/kiwisolver-1.5.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:413b820229730d358efd838ecbab79902fe97094565fdc80ddb6b0a18c18a581", size = 2232857, upload-time = "2026-03-09T13:14:56.471Z" }, + { url = "https://files.pythonhosted.org/packages/3f/ec/2d9756bf2b6d26ae4349b8d3662fb3993f16d80c1f971c179ce862b9dbae/kiwisolver-1.5.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:5124d1ea754509b09e53738ec185584cc609aae4a3b510aaf4ed6aa047ef9303", size = 2329376, upload-time = "2026-03-09T13:14:58.072Z" }, + { url = "https://files.pythonhosted.org/packages/8f/9f/876a0a0f2260f1bde92e002b3019a5fabc35e0939c7d945e0fa66185eb20/kiwisolver-1.5.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:e4415a8db000bf49a6dd1c478bf70062eaacff0f462b92b0ba68791a905861f9", size = 1982549, upload-time = "2026-03-09T13:14:59.668Z" }, + { url = "https://files.pythonhosted.org/packages/6c/4f/ba3624dfac23a64d54ac4179832860cb537c1b0af06024936e82ca4154a0/kiwisolver-1.5.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:d618fd27420381a4f6044faa71f46d8bfd911bd077c555f7138ed88729bfbe79", size = 2494680, upload-time = "2026-03-09T13:15:01.364Z" }, + { url = "https://files.pythonhosted.org/packages/39/b7/97716b190ab98911b20d10bf92eca469121ec483b8ce0edd314f51bc85af/kiwisolver-1.5.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5092eb5b1172947f57d6ea7d89b2f29650414e4293c47707eb499ec07a0ac796", size = 2297905, upload-time = "2026-03-09T13:15:03.925Z" }, + { url = "https://files.pythonhosted.org/packages/a3/36/4e551e8aa55c9188bca9abb5096805edbf7431072b76e2298e34fd3a3008/kiwisolver-1.5.0-cp314-cp314-win_amd64.whl", hash = "sha256:d76e2d8c75051d58177e762164d2e9ab92886534e3a12e795f103524f221dd8e", size = 75086, upload-time = "2026-03-09T13:15:07.775Z" }, + { url = "https://files.pythonhosted.org/packages/70/15/9b90f7df0e31a003c71649cf66ef61c3c1b862f48c81007fa2383c8bd8d7/kiwisolver-1.5.0-cp314-cp314-win_arm64.whl", hash = "sha256:fa6248cd194edff41d7ea9425ced8ca3a6f838bfb295f6f1d6e6bb694a8518df", size = 66577, upload-time = "2026-03-09T13:15:09.139Z" }, + { url = "https://files.pythonhosted.org/packages/17/01/7dc8c5443ff42b38e72731643ed7cf1ed9bf01691ae5cdca98501999ed83/kiwisolver-1.5.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:d1ffeb80b5676463d7a7d56acbe8e37a20ce725570e09549fe738e02ca6b7e1e", size = 125794, upload-time = "2026-03-09T13:15:10.525Z" }, + { url = "https://files.pythonhosted.org/packages/46/8a/b4ebe46ebaac6a303417fab10c2e165c557ddaff558f9699d302b256bc53/kiwisolver-1.5.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:bc4d8e252f532ab46a1de9349e2d27b91fce46736a9eedaa37beaca66f574ed4", size = 67646, upload-time = "2026-03-09T13:15:12.016Z" }, + { url = "https://files.pythonhosted.org/packages/60/35/10a844afc5f19d6f567359bf4789e26661755a2f36200d5d1ed8ad0126e5/kiwisolver-1.5.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6783e069732715ad0c3ce96dbf21dbc2235ab0593f2baf6338101f70371f4028", size = 65511, upload-time = "2026-03-09T13:15:13.311Z" }, + { url = "https://files.pythonhosted.org/packages/f8/8a/685b297052dd041dcebce8e8787b58923b6e78acc6115a0dc9189011c44b/kiwisolver-1.5.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:e7c4c09a490dc4d4a7f8cbee56c606a320f9dc28cf92a7157a39d1ce7676a657", size = 1584858, upload-time = "2026-03-09T13:15:15.103Z" }, + { url = "https://files.pythonhosted.org/packages/9e/80/04865e3d4638ac5bddec28908916df4a3075b8c6cc101786a96803188b96/kiwisolver-1.5.0-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2a075bd7bd19c70cf67c8badfa36cf7c5d8de3c9ddb8420c51e10d9c50e94920", size = 1392539, upload-time = "2026-03-09T13:15:16.661Z" }, + { url = "https://files.pythonhosted.org/packages/ba/01/77a19cacc0893fa13fafa46d1bba06fb4dc2360b3292baf4b56d8e067b24/kiwisolver-1.5.0-cp314-cp314t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:bdd3e53429ff02aa319ba59dfe4ceeec345bf46cf180ec2cf6fd5b942e7975e9", size = 1405310, upload-time = "2026-03-09T13:15:18.229Z" }, + { url = "https://files.pythonhosted.org/packages/53/39/bcaf5d0cca50e604cfa9b4e3ae1d64b50ca1ae5b754122396084599ef903/kiwisolver-1.5.0-cp314-cp314t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3cdcb35dc9d807259c981a85531048ede628eabcffb3239adf3d17463518992d", size = 1456244, upload-time = "2026-03-09T13:15:20.444Z" }, + { url = "https://files.pythonhosted.org/packages/d0/7a/72c187abc6975f6978c3e39b7cf67aeb8b3c0a8f9790aa7fd412855e9e1f/kiwisolver-1.5.0-cp314-cp314t-manylinux_2_39_riscv64.whl", hash = "sha256:70d593af6a6ca332d1df73d519fddb5148edb15cd90d5f0155e3746a6d4fcc65", size = 1073154, upload-time = "2026-03-09T13:15:22.039Z" }, + { url = "https://files.pythonhosted.org/packages/c7/ca/cf5b25783ebbd59143b4371ed0c8428a278abe68d6d0104b01865b1bbd0f/kiwisolver-1.5.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:377815a8616074cabbf3f53354e1d040c35815a134e01d7614b7692e4bf8acfa", size = 2334377, upload-time = "2026-03-09T13:15:23.741Z" }, + { url = "https://files.pythonhosted.org/packages/4a/e5/b1f492adc516796e88751282276745340e2a72dcd0d36cf7173e0daf3210/kiwisolver-1.5.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:0255a027391d52944eae1dbb5d4cc5903f57092f3674e8e544cdd2622826b3f0", size = 2425288, upload-time = "2026-03-09T13:15:25.789Z" }, + { url = "https://files.pythonhosted.org/packages/e6/e5/9b21fbe91a61b8f409d74a26498706e97a48008bfcd1864373d32a6ba31c/kiwisolver-1.5.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:012b1eb16e28718fa782b5e61dc6f2da1f0792ca73bd05d54de6cb9561665fc9", size = 2063158, upload-time = "2026-03-09T13:15:27.63Z" }, + { url = "https://files.pythonhosted.org/packages/b1/02/83f47986138310f95ea95531f851b2a62227c11cbc3e690ae1374fe49f0f/kiwisolver-1.5.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:0e3aafb33aed7479377e5e9a82e9d4bf87063741fc99fc7ae48b0f16e32bdd6f", size = 2597260, upload-time = "2026-03-09T13:15:29.421Z" }, + { url = "https://files.pythonhosted.org/packages/07/18/43a5f24608d8c313dd189cf838c8e68d75b115567c6279de7796197cfb6a/kiwisolver-1.5.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:e7a116ae737f0000343218c4edf5bd45893bfeaff0993c0b215d7124c9f77646", size = 2394403, upload-time = "2026-03-09T13:15:31.517Z" }, + { url = "https://files.pythonhosted.org/packages/3b/b5/98222136d839b8afabcaa943b09bd05888c2d36355b7e448550211d1fca4/kiwisolver-1.5.0-cp314-cp314t-win_amd64.whl", hash = "sha256:1dd9b0b119a350976a6d781e7278ec7aca0b201e1a9e2d23d9804afecb6ca681", size = 79687, upload-time = "2026-03-09T13:15:33.204Z" }, + { url = "https://files.pythonhosted.org/packages/99/a2/ca7dc962848040befed12732dff6acae7fb3c4f6fc4272b3f6c9a30b8713/kiwisolver-1.5.0-cp314-cp314t-win_arm64.whl", hash = "sha256:58f812017cd2985c21fbffb4864d59174d4903dd66fa23815e74bbc7a0e2dd57", size = 70032, upload-time = "2026-03-09T13:15:34.411Z" }, + { url = "https://files.pythonhosted.org/packages/1c/fa/2910df836372d8761bb6eff7d8bdcb1613b5c2e03f260efe7abe34d388a7/kiwisolver-1.5.0-graalpy312-graalpy250_312_native-macosx_10_13_x86_64.whl", hash = "sha256:5ae8e62c147495b01a0f4765c878e9bfdf843412446a247e28df59936e99e797", size = 130262, upload-time = "2026-03-09T13:15:35.629Z" }, + { url = "https://files.pythonhosted.org/packages/0f/41/c5f71f9f00aabcc71fee8b7475e3f64747282580c2fe748961ba29b18385/kiwisolver-1.5.0-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:f6764a4ccab3078db14a632420930f6186058750df066b8ea2a7106df91d3203", size = 138036, upload-time = "2026-03-09T13:15:36.894Z" }, + { url = "https://files.pythonhosted.org/packages/fa/06/7399a607f434119c6e1fdc8ec89a8d51ccccadf3341dee4ead6bd14caaf5/kiwisolver-1.5.0-graalpy312-graalpy250_312_native-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c31c13da98624f957b0fb1b5bae5383b2333c2c3f6793d9825dd5ce79b525cb7", size = 194295, upload-time = "2026-03-09T13:15:38.22Z" }, + { url = "https://files.pythonhosted.org/packages/b5/91/53255615acd2a1eaca307ede3c90eb550bae9c94581f8c00081b6b1c8f44/kiwisolver-1.5.0-graalpy312-graalpy250_312_native-win_amd64.whl", hash = "sha256:1f1489f769582498610e015a8ef2d36f28f505ab3096d0e16b4858a9ec214f57", size = 75987, upload-time = "2026-03-09T13:15:39.65Z" }, + { url = "https://files.pythonhosted.org/packages/e9/eb/5fcbbbf9a0e2c3a35effb88831a483345326bbc3a030a3b5b69aee647f84/kiwisolver-1.5.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:ec4c85dc4b687c7f7f15f553ff26a98bfe8c58f5f7f0ac8905f0ba4c7be60232", size = 59532, upload-time = "2026-03-09T13:15:47.047Z" }, + { url = "https://files.pythonhosted.org/packages/c3/9b/e17104555bb4db148fd52327feea1e96be4b88e8e008b029002c281a21ab/kiwisolver-1.5.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:12e91c215a96e39f57989c8912ae761286ac5a9584d04030ceb3368a357f017a", size = 57420, upload-time = "2026-03-09T13:15:48.199Z" }, + { url = "https://files.pythonhosted.org/packages/48/44/2b5b95b7aa39fb2d8d9d956e0f3d5d45aef2ae1d942d4c3ffac2f9cfed1a/kiwisolver-1.5.0-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:be4a51a55833dc29ab5d7503e7bcb3b3af3402d266018137127450005cdfe737", size = 79892, upload-time = "2026-03-09T13:15:49.694Z" }, + { url = "https://files.pythonhosted.org/packages/52/7d/7157f9bba6b455cfb4632ed411e199fc8b8977642c2b12082e1bd9e6d173/kiwisolver-1.5.0-pp311-pypy311_pp73-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:daae526907e262de627d8f70058a0f64acc9e2641c164c99c8f594b34a799a16", size = 77603, upload-time = "2026-03-09T13:15:50.945Z" }, + { url = "https://files.pythonhosted.org/packages/0a/dd/8050c947d435c8d4bc94e3252f4d8bb8a76cfb424f043a8680be637a57f1/kiwisolver-1.5.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:59cd8683f575d96df5bb48f6add94afc055012c29e28124fcae2b63661b9efb1", size = 73558, upload-time = "2026-03-09T13:15:52.112Z" }, +] + +[[package]] +name = "license-expression" +version = "30.4.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "boolean-py" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/40/71/d89bb0e71b1415453980fd32315f2a037aad9f7f70f695c7cec7035feb13/license_expression-30.4.4.tar.gz", hash = "sha256:73448f0aacd8d0808895bdc4b2c8e01a8d67646e4188f887375398c761f340fd", size = 186402, upload-time = "2025-07-22T11:13:32.17Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/af/40/791891d4c0c4dab4c5e187c17261cedc26285fd41541577f900470a45a4d/license_expression-30.4.4-py3-none-any.whl", hash = "sha256:421788fdcadb41f049d2dc934ce666626265aeccefddd25e162a26f23bcbf8a4", size = 120615, upload-time = "2025-07-22T11:13:31.217Z" }, +] + +[[package]] +name = "markdown-it-py" +version = "4.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mdurl" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/06/ff/7841249c247aa650a76b9ee4bbaeae59370dc8bfd2f6c01f3630c35eb134/markdown_it_py-4.2.0.tar.gz", hash = "sha256:04a21681d6fbb623de53f6f364d352309d4094dd4194040a10fd51833e418d49", size = 82454, upload-time = "2026-05-07T12:08:28.36Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl", hash = "sha256:9f7ebbcd14fe59494226453aed97c1070d83f8d24b6fc3a3bcf9a38092641c4a", size = 91687, upload-time = "2026-05-07T12:08:27.182Z" }, +] + +[[package]] +name = "markupsafe" +version = "3.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7e/99/7690b6d4034fffd95959cbe0c02de8deb3098cc577c67bb6a24fe5d7caa7/markupsafe-3.0.3.tar.gz", hash = "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698", size = 80313, upload-time = "2025-09-27T18:37:40.426Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/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" +version = "3.11.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "contourpy" }, + { name = "cycler" }, + { name = "fonttools" }, + { name = "kiwisolver" }, + { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12'" }, + { name = "numpy", version = "2.5.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12'" }, + { name = "packaging" }, + { name = "pillow" }, + { name = "pyparsing" }, + { name = "python-dateutil" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/1f/24/080c99d223d158d3a8902769269ab6da5b50f7a0e6e072513907e02b7a6c/matplotlib-3.11.0.tar.gz", hash = "sha256:68c0c7be01b30dcca3638934f7f591df73401235cbdbf0d1ab1c71e7db7f8b57", size = 33251176, upload-time = "2026-06-12T02:29:15.508Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ce/a2/78f662f1b18968531f67d3fcde1b7ea8496920bacd4f16ddb5b79d112e46/matplotlib-3.11.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:f857524b442f0f36e641868ce2171aafa88cb0bc0644f4e1d8a5df9b32649fef", size = 9436261, upload-time = "2026-06-12T02:27:34.161Z" }, + { url = "https://files.pythonhosted.org/packages/5e/92/044f1de43901310202f4c79acf4f141be53b2ca8d8380e2fcefb3d523a75/matplotlib-3.11.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:57baa92fdc82948ed716eae6d2579d4d6f40965cd8d2f416755b4a72580a3233", size = 9264669, upload-time = "2026-06-12T02:27:37.413Z" }, + { url = "https://files.pythonhosted.org/packages/53/f4/f0b4f9ba7ec14a7af8151f3ad71ecfe3561e6ba38cfab1db3681ba4ca112/matplotlib-3.11.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:630eee0e67d35cce2019a0e670719f4816e3b86aff0fa72729f6c69786fceb45", size = 10021076, upload-time = "2026-06-12T02:27:39.926Z" }, + { url = "https://files.pythonhosted.org/packages/d7/33/4d679c6dcd594a156542080ac907ddccf7b09ca11655c4b28eca8e9ee5da/matplotlib-3.11.0-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5106c444d0bf966eee2853548c03772af4ab7199118e086c62fbac8ccb07c055", size = 10828999, upload-time = "2026-06-12T02:27:42.433Z" }, + { url = "https://files.pythonhosted.org/packages/07/74/0a3683802037d8cd013144d77c247219b47f2aabace6fdde74faa12bacf7/matplotlib-3.11.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4d7aea652b58e686444079be3376ef546bffa1eee9b9bb9c472b9fcf6cf410d3", size = 10913103, upload-time = "2026-06-12T02:27:44.827Z" }, + { url = "https://files.pythonhosted.org/packages/d0/9f/970fcbf381e82ec66fdf5da8ea76e2e9240f61a24011ce9fd1d42c37ac2d/matplotlib-3.11.0-cp311-cp311-win_amd64.whl", hash = "sha256:70a5b3e9a5dab708c0f039709ae7c68d5b4d254e291ef76492cdba230c8bb5e4", size = 9310945, upload-time = "2026-06-12T02:27:46.867Z" }, + { url = "https://files.pythonhosted.org/packages/14/4e/6e7cfed23611265ded53806852343b5c59339e506e84c474a9b5afc3b249/matplotlib-3.11.0-cp311-cp311-win_arm64.whl", hash = "sha256:3d68266213e73823ac3be90615bab0cf31f88851e114cdb1dd25dacf3b01e1a7", size = 8999304, upload-time = "2026-06-12T02:27:48.798Z" }, + { url = "https://files.pythonhosted.org/packages/da/17/f5276b496c61477a6c4fc5e7401f4bfe1c2e5ef7c6cd67896f2ade3809cb/matplotlib-3.11.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:06b5872e9cf11adc8f589ded3ce11bc3e1061ad498259664fabc1f6615beb918", size = 9449976, upload-time = "2026-06-12T02:27:50.989Z" }, + { url = "https://files.pythonhosted.org/packages/82/34/bdd77418adb2178a1d59f044bd67bfebb115896e91b840b8a197eb3f4f4e/matplotlib-3.11.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0515d495124be3124340e59f164d901ed4484e2246a5b74cfa483cac3b80bd97", size = 9279307, upload-time = "2026-06-12T02:27:53.247Z" }, + { url = "https://files.pythonhosted.org/packages/94/95/7f522393c88313336b20d70fc849555757b2e5febc22b83b3a3f0fd4bce9/matplotlib-3.11.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:be5f93a1d21981bfb802ded0d77a0caa92d4342a47d45754fac77e314a506344", size = 10031353, upload-time = "2026-06-12T02:27:55.215Z" }, + { url = "https://files.pythonhosted.org/packages/87/ce/8f25a0e3186aefd61913e7467d1b999465bcd0d0c03ac695c1b26ca559b7/matplotlib-3.11.0-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:41635d7909d19e52e924a521dde6d8f670b0f53ab1d0e8c331fa831554f681d1", size = 10839232, upload-time = "2026-06-12T02:27:57.746Z" }, + { url = "https://files.pythonhosted.org/packages/85/c2/db15da2bbdf9e3ca66df7db8e2c33a1dfed67be24a24d2c878efaaff01d6/matplotlib-3.11.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:94f5000f67ca9faa300863ea17f8bce9175cb67b88bec4bc7780502d53dd7c9e", size = 10923899, upload-time = "2026-06-12T02:28:00.223Z" }, + { url = "https://files.pythonhosted.org/packages/e5/2f/a58a4443a4d052a4ea77557478336aefc26c7981f6408d37adba763aa758/matplotlib-3.11.0-cp312-cp312-win_amd64.whl", hash = "sha256:ac6f1ef39f3d0f9e2463303013094992cdbe0f85f43bc54155bc472b2042768e", size = 9329528, upload-time = "2026-06-12T02:28:02.27Z" }, + { url = "https://files.pythonhosted.org/packages/61/0f/4b669589d47733b97ab9df4b58d6fc1e68acb5ea42a928dc7cbdd6bf5871/matplotlib-3.11.0-cp312-cp312-win_arm64.whl", hash = "sha256:9dd11fb612ce7bc60b1de5b4fc87ff959d22317b5de42aabf392f66f97af22eb", size = 9003413, upload-time = "2026-06-12T02:28:04.49Z" }, + { url = "https://files.pythonhosted.org/packages/55/41/aa47f156b061d14c98b906f76c428507397708ec63ff94f410ae1752b426/matplotlib-3.11.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:6ce3b839b34ae1f430b4616893a2945a2999debaa7e94e7e29a2a8bbf286f7b5", size = 9450532, upload-time = "2026-06-12T02:28:06.769Z" }, + { url = "https://files.pythonhosted.org/packages/8c/4f/5a9eb0375e81413953febf8af7b012a6b6357f53438a15c4f5ad86c6bbb5/matplotlib-3.11.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:373db8f91214e8ccaf35ac833cc1dd59dd961e148bbd55dd027141591dde1313", size = 9279760, upload-time = "2026-06-12T02:28:09.152Z" }, + { url = "https://files.pythonhosted.org/packages/a4/c0/1117d53077e3ac3152503a84e9cf7a5c239576805ee71276e80c2aaa7471/matplotlib-3.11.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:be152b7570324dc8d01574cc9474dd2d803237acf528bcbb5b211fa347461a09", size = 10031623, upload-time = "2026-06-12T02:28:11.26Z" }, + { url = "https://files.pythonhosted.org/packages/92/7e/e937138daffad65b71bf831a377809dcbc830fb4f31a31e067dc1faa2575/matplotlib-3.11.0-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:126f256df600652d7e4b394cf3164ff75210a00038f287c95a012a6f58d0e83f", size = 10839372, upload-time = "2026-06-12T02:28:14.102Z" }, + { url = "https://files.pythonhosted.org/packages/1d/c2/438ecc197ffb8023b6b9922915542f2172f5fd45b76703b0b4fc47322243/matplotlib-3.11.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:03acfeddf87b0dddb11b081ef7740ad445a3ca8bcb6b8e3011b08f2cf802b75c", size = 10924099, upload-time = "2026-06-12T02:28:16.383Z" }, + { url = "https://files.pythonhosted.org/packages/40/2e/395883da416f378b3ed2c9f3e843ac477eae1ce731b671b79adaa6f0bacd/matplotlib-3.11.0-cp313-cp313-win_amd64.whl", hash = "sha256:ab3722f04f3ff34c23b5012c5873d2894174e06c3822fcdac3610965a5ac7d06", size = 9329727, upload-time = "2026-06-12T02:28:18.581Z" }, + { url = "https://files.pythonhosted.org/packages/61/82/2c388956abf8bf392dfb5b8917c502f1082df6a941b781ab8c8e5ba2474b/matplotlib-3.11.0-cp313-cp313-win_arm64.whl", hash = "sha256:c945824670fb8915b4ac879e5e61f3c58e0913022f70a0de4c082b17372f8771", size = 9003506, upload-time = "2026-06-12T02:28:20.474Z" }, + { url = "https://files.pythonhosted.org/packages/c8/c1/34454baa44da7975ada82e9aea37105ec47059514dc967d3be14426ba8dc/matplotlib-3.11.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:3489c3dc487669b4a980bc3068f87856de7a1564248d3f6c629efb2a58b03f24", size = 9499838, upload-time = "2026-06-12T02:28:22.713Z" }, + { url = "https://files.pythonhosted.org/packages/b1/c3/98fe79a398cf232219f090163a7fa7e6766e9f2e0ad26df54d6f8934d8ee/matplotlib-3.11.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:6a98f5476ce784a50ce09998f4ae1e6a9f25043cef8a480c98949902eda74620", size = 9332298, upload-time = "2026-06-12T02:28:24.796Z" }, + { url = "https://files.pythonhosted.org/packages/95/e4/b4b7c33151e74e5c802f3cde1ba807ebfc38401e329b44e215a5888dd76d/matplotlib-3.11.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:565af866fd63e4bd3f987d580afe27c44c2552a3b3305f4ecbb85133601ea6f3", size = 10045491, upload-time = "2026-06-12T02:28:27.141Z" }, + { url = "https://files.pythonhosted.org/packages/71/28/394548efd68354110c1a1be11fe6b6e559e06d1a23da35908a0e316c55a9/matplotlib-3.11.0-cp313-cp313t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e6b3e64dea5062c570f04358e2711859f3531b459f29516274fbad889079e4f3", size = 10857059, upload-time = "2026-06-12T02:28:29.222Z" }, + { url = "https://files.pythonhosted.org/packages/c8/44/e7922e6e2a4d63bdfbc9dc4a53e3850ab438d46cf42e6779bb15ec92c948/matplotlib-3.11.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:942b37c5db1899610bd1543ce8e13e4ecff9a4633e7f63bb6aa9205d2644ebd1", size = 10939576, upload-time = "2026-06-12T02:28:31.66Z" }, + { url = "https://files.pythonhosted.org/packages/3d/be/b1ca96003a441d619b727fee21d671fdff7a5ce2f1bb797b2521aa2f679a/matplotlib-3.11.0-cp313-cp313t-win_amd64.whl", hash = "sha256:c08e649a6313e1291e713623b97a38e5bb4aa580b2a100a94a3309bc6b9c8eb3", size = 9379519, upload-time = "2026-06-12T02:28:33.888Z" }, + { url = "https://files.pythonhosted.org/packages/e3/72/4bf3b91821c34596dd6a7bdac5836d94f744144c8208939ef49d8ec43f7e/matplotlib-3.11.0-cp313-cp313t-win_arm64.whl", hash = "sha256:2746cd2c113742ff6ce37a864c5ac5fd7aa644568f445e66166e457ac78e40e0", size = 9055456, upload-time = "2026-06-12T02:28:35.878Z" }, + { url = "https://files.pythonhosted.org/packages/57/52/a94102ac99eb78e2fe9b826674f9ef9ee23327110ea6ab4776c1b4eb6209/matplotlib-3.11.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:3338e3e3de128cf50d0d2fb92a122815daf9c755bd882a474343c05f8fd7ec79", size = 9452137, upload-time = "2026-06-12T02:28:37.93Z" }, + { url = "https://files.pythonhosted.org/packages/7c/03/b8cdb625a21f710dfa11bbca1f48fb4057d2c0286975f8b415bf80942c99/matplotlib-3.11.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:25c2e5455efd8d99f41fb79871a31feb7d301569642e332ec58d72cfe9282bc3", size = 9281514, upload-time = "2026-06-12T02:28:40.028Z" }, + { url = "https://files.pythonhosted.org/packages/b7/2d/4e1240ea82ee197dfb3851e71f71c87eeeb975f1753b56a0588e4e80739a/matplotlib-3.11.0-cp314-cp314-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d9695457a467ff86d23f35037a43deb6f1134dd6d3e2ac8ce1e2087cff09ffb9", size = 10843005, upload-time = "2026-06-12T02:28:42.39Z" }, + { url = "https://files.pythonhosted.org/packages/29/dc/6377ecfaa5fef79430f74a1a16638b4e2aa30d4692bae2c19f9d76fe3b01/matplotlib-3.11.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:19c16c61dea63b3582918503e6b294193961261d9daa806d4ae2151f1ad05430", size = 11127459, upload-time = "2026-06-12T02:28:44.483Z" }, + { url = "https://files.pythonhosted.org/packages/6f/41/795c405aa7560443a3b01309424cde4a1113b85c90b8a63417444a749617/matplotlib-3.11.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2d72ea8b7924f3cb955e61518d21e43b3df1e6c8a793b480a0c1214f185d30ba", size = 10925160, upload-time = "2026-06-12T02:28:46.564Z" }, + { url = "https://files.pythonhosted.org/packages/1a/f7/3a9e6389a7cfaeff76c56e40c2dabcb13110e21e82f837228c834ebe748c/matplotlib-3.11.0-cp314-cp314-win_amd64.whl", hash = "sha256:1c02da0a629dfa9debf52725ea06866b74c1fb70a895bae05e4493d34074f9f2", size = 9485186, upload-time = "2026-06-12T02:28:49.344Z" }, + { url = "https://files.pythonhosted.org/packages/8b/c0/396478ee7cf2091d182db8b4a8695f6a37f1ddb978989cf9dbb84cd5c123/matplotlib-3.11.0-cp314-cp314-win_arm64.whl", hash = "sha256:aa55d73b3117d4b07f959cd9eb6f69b375d8df3414139c479388e551aa5d999d", size = 9160349, upload-time = "2026-06-12T02:28:51.382Z" }, + { url = "https://files.pythonhosted.org/packages/c5/6f/1c3bd51bb2b34eaacdcf3c3d859dbb357f952fc8020c617dc118ad7c9e38/matplotlib-3.11.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:a9d8c6e7cd2f0ddf11d8d92e520dd1d9d2abb0cf6ac8831e338666c81e905847", size = 9500921, upload-time = "2026-06-12T02:28:53.443Z" }, + { url = "https://files.pythonhosted.org/packages/e0/0d/4d861d0121840cb1a3fd4a10deb211efd6fccd481ed23e553f31f4f4da4a/matplotlib-3.11.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:be050fcf32f729eda99f7f75a80bf67612ce16ab9ac1c23a387dcaede95cb70e", size = 9332190, upload-time = "2026-06-12T02:28:55.623Z" }, + { url = "https://files.pythonhosted.org/packages/4b/cb/22f6bc35711a0b5639a784e74e653e77c86210bd4304449dd399a482f74e/matplotlib-3.11.0-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dfabef0230d0697aa0d717385194dd41162e00207a68bf4abf94c2bf4c27dca0", size = 10854181, upload-time = "2026-06-12T02:28:57.856Z" }, + { url = "https://files.pythonhosted.org/packages/3f/7e/9a9eaca731a2939589da520f0ebe8fd8753d0f51fca98c7d20af6dbe261a/matplotlib-3.11.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1644db30e759199443493ac5e5caec24fdb775a8f6123021f85ba47c4133c3cb", size = 11137715, upload-time = "2026-06-12T02:29:00.555Z" }, + { url = "https://files.pythonhosted.org/packages/ef/f9/9b030b6088354acb0296871bb624b25befc1c42509d3c6cd17420c83a5b8/matplotlib-3.11.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:15b0d160079cb10699a0e98b5989c70677b2df7cacdc62af67c30f2facec46d9", size = 10939427, upload-time = "2026-06-12T02:29:02.527Z" }, + { url = "https://files.pythonhosted.org/packages/59/94/6b273eaee4ee250863567d100865da61a5c1527fa67f527b7ed22e0dd29c/matplotlib-3.11.0-cp314-cp314t-win_amd64.whl", hash = "sha256:446307e6b04b57b1f1239e228a1ec2af0d589a1008cebc3dfa3f5441d095cfb6", size = 9535809, upload-time = "2026-06-12T02:29:04.994Z" }, + { url = "https://files.pythonhosted.org/packages/60/95/1d36bddf2b7e2692c1540e78a6e5bc88bc1496b137e3e35a611f91b65ac3/matplotlib-3.11.0-cp314-cp314t-win_arm64.whl", hash = "sha256:652fb5696271d4c50f196d22a5ff4f8e4444c74f847423570d7dc0aa2bbd0159", size = 9209226, upload-time = "2026-06-12T02:29:07.033Z" }, + { url = "https://files.pythonhosted.org/packages/0f/c2/f5da6cd37ed6871f5c9b3c0507ddb69f14d6c36fac4541e4e0c60cb8cdfc/matplotlib-3.11.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:81ae77077a1e16d37a5b61096ccb07c8d90a99b518fa8256b8f21578932f2f62", size = 9434094, upload-time = "2026-06-12T02:29:09.135Z" }, + { url = "https://files.pythonhosted.org/packages/f8/07/56f66906e0f87a0c6d0d0acbd34dbc9432b1931d8f26ef618bd6f92932a9/matplotlib-3.11.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:ddef37840695f5eef65f9f070fe2d2f510f584c2156203f9f622a5b0584efffd", size = 9262183, upload-time = "2026-06-12T02:29:11.283Z" }, + { url = "https://files.pythonhosted.org/packages/0c/d8/c4ecab06b7ea36a570c4f3bd2d48d1799fd5d9174470e45c2194199431e7/matplotlib-3.11.0-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:cf662e5ac5707658cb931e19972c4bd99f7b4f8b7bf79d3c821d239fa6b71e64", size = 10015653, upload-time = "2026-06-12T02:29:13.251Z" }, +] + +[[package]] +name = "mcp" +version = "1.28.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "httpx" }, + { name = "httpx-sse" }, + { name = "jsonschema" }, + { name = "pydantic" }, + { name = "pydantic-settings" }, + { name = "pyjwt", extra = ["crypto"] }, + { name = "python-multipart" }, + { name = "pywin32", marker = "sys_platform == 'win32'" }, + { name = "sse-starlette" }, + { name = "starlette" }, + { name = "typing-extensions" }, + { name = "typing-inspection" }, + { name = "uvicorn", marker = "sys_platform != 'emscripten'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/6e/77/9450b8f251a13affb6281997d0523c4615f8a8b35d0b21ff30db3a5aac9d/mcp-1.28.1.tar.gz", hash = "sha256:d51e36a5f5644faea4f85ea649bfffa6bc6c26770d42798ad6a3de3d2ba69683", size = 638501, upload-time = "2026-06-26T12:57:29.093Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e2/5e/d118fce19f87a2e7d8101c35c8ae0ec289098a4df0ff244cec23e415aca0/mcp-1.28.1-py3-none-any.whl", hash = "sha256:2726bca5e7193f61c5dde8b12500a6de2d9acf6d1a1c0be9e8c2e706437991df", size = 222620, upload-time = "2026-06-26T12:57:27.218Z" }, +] + +[package.optional-dependencies] +cli = [ + { name = "python-dotenv" }, + { name = "typer" }, +] + +[[package]] +name = "mdurl" +version = "0.1.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" }, +] + +[[package]] +name = "more-itertools" +version = "11.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/de/1d/f4da6f02cdffe04d6362210b807146a26044c88d839208aec273bb0d9184/more_itertools-11.1.0.tar.gz", hash = "sha256:48e8f4d9e7e5878571ecf6f2b4e57634f93cd474cc8cfbd2376f2d11b396e30d", size = 145772, upload-time = "2026-05-22T14:14:29.909Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e8/3d/1087453384dbde46a8c7f9356eead2c58be8a7bf156bca40243377c85715/more_itertools-11.1.0-py3-none-any.whl", hash = "sha256:4b65538ae22f6fed0ce4874efd317463a7489796a0939fa66824dd542125a192", size = 72226, upload-time = "2026-05-22T14:14:28.824Z" }, +] + +[[package]] +name = "mpmath" +version = "1.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e0/47/dd32fa426cc72114383ac549964eecb20ecfd886d1e5ccf5340b55b02f57/mpmath-1.3.0.tar.gz", hash = "sha256:7a28eb2a9774d00c7bc92411c19a89209d5da7c4c9a9e227be8330a23a25b91f", size = 508106, upload-time = "2023-03-07T16:47:11.061Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl", hash = "sha256:a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c", size = 536198, upload-time = "2023-03-07T16:47:09.197Z" }, +] + +[[package]] +name = "msgpack" +version = "1.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/31/f9/c0a1c127f9049db9155afc316952ea571720dd01833ff5e4d7e8e6352dbb/msgpack-1.2.1.tar.gz", hash = "sha256:04c721c2c7448767e9e3f2520a475663d8ee0f09c31890f6d2bd70fd636a9647", size = 183960, upload-time = "2026-06-18T16:13:52.594Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/6b/e9b1cdc042c4458801d2545ed782a95f3d6ba8e270cce8745b8603c7f748/msgpack-1.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:29a3f6e9667868429d8240dfd063ea5ffdc1321c13d783aa23827a38de0dcb22", size = 82812, upload-time = "2026-06-18T16:12:45.022Z" }, + { url = "https://files.pythonhosted.org/packages/0c/3a/dd518a1bf78ed1e9ad8afe57307c079a00eafe4b3068932a27ca1ea56b4f/msgpack-1.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:aded5bdf32609dc7987a49bbbd15a8ef096193f96dd8bbeb791de729e650acf5", size = 82739, upload-time = "2026-06-18T16:12:46.025Z" }, + { url = "https://files.pythonhosted.org/packages/70/e0/7ba9e1542bf0771a27b8b37c1316e3f95ae9d748fd765284655c476ad4ef/msgpack-1.2.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:146ee4e9ce80b365c6d4c47073da9da7bcec473e58194ceee5dd7620ace77e06", size = 414233, upload-time = "2026-06-18T16:12:47.029Z" }, + { url = "https://files.pythonhosted.org/packages/03/8d/671d81534ea0e2b0e8a121be100020da09eb78861fe3aa8f3ef7dcd3bed1/msgpack-1.2.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a28d076ca7c82b9c8728ad90b7147489449557038bed50e4241eb832395169b4", size = 423843, upload-time = "2026-06-18T16:12:48.19Z" }, + { url = "https://files.pythonhosted.org/packages/d2/b6/e5c737515ed1f166664b87601b532f58cbb73d8aa6a90b99f7c2c5037e8e/msgpack-1.2.1-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:7d31c0ac0c640f877804c67cb2bc9f4e23dc2db97e96c2e67fa27d38283b41f8", size = 390772, upload-time = "2026-06-18T16:12:49.624Z" }, + { url = "https://files.pythonhosted.org/packages/a8/46/62ed8c2e87d7021eab19921594d961ef3aa3794eec76c716dc30f3bfd433/msgpack-1.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8ff92d7feeaf5bc26c51495b69e2f99ed97ab79346fb6555f44be7dd2ac6503b", size = 409559, upload-time = "2026-06-18T16:12:50.936Z" }, + { url = "https://files.pythonhosted.org/packages/70/ff/59aa3887b860bbf43532835e192b1c388a17590d6068ae4f8b2bc74c906e/msgpack-1.2.1-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:779197a6513bab3c3632265e3d0f7cb3227e62510841a6f34f1eaa37efbb345e", size = 387838, upload-time = "2026-06-18T16:12:52.161Z" }, + { url = "https://files.pythonhosted.org/packages/09/11/f8563e471093420cf6478cb3271a0175d8402b82d879783d4035d2d03360/msgpack-1.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:67f6dd22fa72a93752643f07889796d62739a13415ee630169a8ce764f86cf9f", size = 421732, upload-time = "2026-06-18T16:12:53.556Z" }, + { url = "https://files.pythonhosted.org/packages/57/cf/e673683c4c6c90c1022b24c65af4b03eda72b182a1176ef6449069d66acc/msgpack-1.2.1-cp311-cp311-win32.whl", hash = "sha256:91054a783328e0ea7954b8771095705c8d2243b814743fbaadf14552c9c52c5d", size = 64091, upload-time = "2026-06-18T16:12:54.821Z" }, + { url = "https://files.pythonhosted.org/packages/3f/07/ca212739d179f9083bff2c7c08c24101c3555a334fadc2b876b18768a3ae/msgpack-1.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2eda0b7ebb1283a98d3e4492ac933c8af6aff59fd3df1c3ed024f536af4b1dc8", size = 70462, upload-time = "2026-06-18T16:12:55.898Z" }, + { url = "https://files.pythonhosted.org/packages/6d/be/6798347b425e26f35db82e69dd83c09716c856a3714e7bffc4c0860fd830/msgpack-1.2.1-cp311-cp311-win_arm64.whl", hash = "sha256:6ee967f7c7e1df2890c671ff2ee51a28ded0efc95da3e507176dee881ce36c66", size = 65059, upload-time = "2026-06-18T16:12:57.053Z" }, + { url = "https://files.pythonhosted.org/packages/bc/dd/9e8cbd8f5582ca4b590336f2b91ee5662f6a6ca562b565abaf696a0f81ff/msgpack-1.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2ef59c659f289eddf8aa6623823f19fa2f40a4029266889eac7a2505dd210c35", size = 83531, upload-time = "2026-06-18T16:12:58.249Z" }, + { url = "https://files.pythonhosted.org/packages/50/2e/ebdb85a8da151397a2790363676b7ed7c125924fe618e4c6d8befb0cc62c/msgpack-1.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d3567748a5107cb40cdf66a275430c2f87c07777698f4bfd25c35f44d533258c", size = 82657, upload-time = "2026-06-18T16:12:59.396Z" }, + { url = "https://files.pythonhosted.org/packages/26/aa/753ad8b007b464e1d8aa0c8e650b9c5f4f725e658fc5ac8a7635c55b7f6e/msgpack-1.2.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:60926b75d00c8e816ef98f3034f484a8bc64242d66839cef4cf7e503142316a0", size = 410634, upload-time = "2026-06-18T16:13:00.383Z" }, + { url = "https://files.pythonhosted.org/packages/6a/fd/6adabd4f6d5e686f97dd02ce7fce3fe4cf672cbac36b8f67ff4040e8ad8b/msgpack-1.2.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:020e881a764b20d8d7ca1a54fc01b8175519d108e3c3f194fddc200bda95951a", size = 419989, upload-time = "2026-06-18T16:13:01.776Z" }, + { url = "https://files.pythonhosted.org/packages/5a/cc/85039b7b0eb168aaad7383a23c97e291a11f08351cb45a606ce865e4e3f1/msgpack-1.2.1-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:4202c74688ca06591f78cb18988228bd4cca2cc75d57b60008372892d2f1e6e6", size = 377544, upload-time = "2026-06-18T16:13:03.637Z" }, + { url = "https://files.pythonhosted.org/packages/ed/bf/35963899493b32030c85fc513b723ae66144ac70c11ebc52e889e16e3d99/msgpack-1.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8b267ce94efb76fbd1b3373511420074ee3187f0f7811bf394531de13294735a", size = 400842, upload-time = "2026-06-18T16:13:05.012Z" }, + { url = "https://files.pythonhosted.org/packages/a6/df/8e2ac970c8f99264cd9997d1c73df5466bc19da3301d7dc5500862a9b089/msgpack-1.2.1-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:e4f1d0f8f98ade9634e01fb704a408f9336c0a8f1117b369f5db83dc7551d8b1", size = 374108, upload-time = "2026-06-18T16:13:06.232Z" }, + { url = "https://files.pythonhosted.org/packages/17/dd/fa8bd265110dfa51c20cb529f9e6d240a16fafe7e645004c6af2d01353ba/msgpack-1.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f02cf17a6ca1abe29b5f980644f7551f94d71f2011509b26d8625ce038f0df64", size = 414939, upload-time = "2026-06-18T16:13:07.478Z" }, + { url = "https://files.pythonhosted.org/packages/2e/b9/8377a5ad8953fc0437c70cc98d9ae29f27fe5ac5109fbec0812085865735/msgpack-1.2.1-cp312-cp312-win32.whl", hash = "sha256:0c0d9802354507bcba62af19c17918e3eb437cc25e6f50657d511b5856a77aac", size = 64504, upload-time = "2026-06-18T16:13:08.822Z" }, + { url = "https://files.pythonhosted.org/packages/57/7f/ce1e377df7e62461fefd9eb23bfb93a4a523f40a517b377b8f844d836828/msgpack-1.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:5c24aa15d5963051e1a5c62b12c50cd705992502b5ec1f3bece6046f33c9fc24", size = 71421, upload-time = "2026-06-18T16:13:09.828Z" }, + { url = "https://files.pythonhosted.org/packages/8f/32/ebfe84c9929f08f188d56c7a2fd913406a9ddad76a634697c1c43b8112e6/msgpack-1.2.1-cp312-cp312-win_arm64.whl", hash = "sha256:4227224aaec8f7fbcbfbd4272319347b2bb4030366502600f8c45588c5187b07", size = 64775, upload-time = "2026-06-18T16:13:11.056Z" }, + { url = "https://files.pythonhosted.org/packages/b0/ac/dcddcab6f6c20ecb387ca5e980371cdb3f87ff69aeca388be97eebc4c074/msgpack-1.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0a70e3cf2804a300d921bb0940426e35f4e489a23adfb77a808892241db0a064", size = 83151, upload-time = "2026-06-18T16:13:12.173Z" }, + { url = "https://files.pythonhosted.org/packages/64/71/fbcfa83a1d6a9c6091942d1cfd070962244664b87427a9a49a6897b1b219/msgpack-1.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:491cc39455ca765fad51fb451bf2915eb2cf41192ab5801ce8d67c1d614fe056", size = 82351, upload-time = "2026-06-18T16:13:13.194Z" }, + { url = "https://files.pythonhosted.org/packages/e3/10/ddf7b06db879e8792d13934ddda09ff20bd2a583fd84c9b59aae9b0e650b/msgpack-1.2.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f310233ef7fb9c14e201c93639fe5f5260b005f56f0b29048e999c30935596cc", size = 407518, upload-time = "2026-06-18T16:13:14.233Z" }, + { url = "https://files.pythonhosted.org/packages/79/d3/36a46a8ed992b781acbc05928bd5bee3c810cb0c3563bf81a7b0c04a1a76/msgpack-1.2.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:787c9bebb5833e8f6fc8abca3c0597683d8d87f56a8842b6b89c75a5f3176e2d", size = 416405, upload-time = "2026-06-18T16:13:15.435Z" }, + { url = "https://files.pythonhosted.org/packages/f9/84/e8e9598b557c0ba6ddae901a73780a4c75ac667dddf59414b1e56a42fb34/msgpack-1.2.1-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:dc871b997a9370d855b7394465f2f350e847a5b806dd38dcc9c989e7d87da155", size = 376257, upload-time = "2026-06-18T16:13:17.022Z" }, + { url = "https://files.pythonhosted.org/packages/40/16/738fe6d875ad7e2a9429c165322a4ec088f4f273cdfae63d96a89c467961/msgpack-1.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:85f57e960d877f2977f6430896191b04a21f8901b3b4baf2e4604329f4db5402", size = 397469, upload-time = "2026-06-18T16:13:18.287Z" }, + { url = "https://files.pythonhosted.org/packages/ca/be/6d5952df75a7f24f35833af764c3a6860780364cb3a0030beb8099e1b2b4/msgpack-1.2.1-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:1233ee2dd0cefba127583de50ea654677277047d238303521db35def3d7b2e7c", size = 372802, upload-time = "2026-06-18T16:13:19.685Z" }, + { url = "https://files.pythonhosted.org/packages/e1/39/e2ef7dbf0473bcb8dc7c50bf782a892d67414877b63e47fc88eb189ef5e6/msgpack-1.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e3dc2feb0876209d9c38aa56cb1de169bd6c4348f1aa48271f241226590993e6", size = 411273, upload-time = "2026-06-18T16:13:21.028Z" }, + { url = "https://files.pythonhosted.org/packages/ef/c5/133f4512a56e983a93445c836c9d94d88f3bc2e0980ff4b9e577bd8416ce/msgpack-1.2.1-cp313-cp313-win32.whl", hash = "sha256:6d09badf350af2be9d189184e04e64cf54ad93569ab3d96fca58bd3e84aad707", size = 64471, upload-time = "2026-06-18T16:13:22.293Z" }, + { url = "https://files.pythonhosted.org/packages/e2/98/577e10b055096a7dd40732358cabaf7180a20c79ed1dcdbb618e4b9deac7/msgpack-1.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:33f14fba63278b714efe6ad07e50ea5f03d91537aa6a1c5f1ceca4cf44013ca9", size = 71274, upload-time = "2026-06-18T16:13:23.455Z" }, + { url = "https://files.pythonhosted.org/packages/ba/ee/0c0048e7cfbef23c6a94791b8959ab28155232e7956de8a305b5ff588f05/msgpack-1.2.1-cp313-cp313-win_arm64.whl", hash = "sha256:afc5febcd4c99effbc02b528e49d6fd0760b2b7d48c05239e345a5fa6e743d9a", size = 64795, upload-time = "2026-06-18T16:13:24.687Z" }, + { url = "https://files.pythonhosted.org/packages/77/58/cce442852c6b9e1639c7c8ac8fd9143121cb32dab0f308df4d1426a8eb9c/msgpack-1.2.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:05f340e47e7e47d2da8db9b53e1bb1d294369e9ef45a747441309f6650b8351d", size = 83610, upload-time = "2026-06-18T16:13:25.724Z" }, + { url = "https://files.pythonhosted.org/packages/60/5c/15b4c7a0182f75ffa90751958ba36a9c01cafee367d49a3edc10ed140b01/msgpack-1.2.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:810b916696c86ef0deb3b74588480224df4c1b071136c34183e4a2a4284d7ac7", size = 83138, upload-time = "2026-06-18T16:13:26.781Z" }, + { url = "https://files.pythonhosted.org/packages/b8/a6/99e58722feaffc5f2fbcc0c8c0d1451ab9f84097f7af87291b46af2390f4/msgpack-1.2.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ca0dacff965c47afdc3749a8469d7302a8f801d6a28758d55120d75e66ce6889", size = 406090, upload-time = "2026-06-18T16:13:28.072Z" }, + { url = "https://files.pythonhosted.org/packages/19/03/8c63e8cf52958534ef688625965ab04c269a6cadd8caef16758b380a821a/msgpack-1.2.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0e2bf9280bceb5efca998435904b5d3e9fdbcc11d90dc9df30aec7973252b720", size = 412106, upload-time = "2026-06-18T16:13:29.427Z" }, + { url = "https://files.pythonhosted.org/packages/63/d2/155d9e71b40e41fd934bc0c48b9b2770f22263e1ac20aad8e29fdca7be3f/msgpack-1.2.1-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:aa6c4be5d1c02a42b066ca6ddb71adf36432868fdcdb6ee87e634e86e0674190", size = 374851, upload-time = "2026-06-18T16:13:30.631Z" }, + { url = "https://files.pythonhosted.org/packages/98/48/deaf2326262a8d5ea3295ce9649912ecd3f551ba7ec8e33c665d2ba583f3/msgpack-1.2.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ec0e675d59150a6269ddc9139087c722292664a37d071a849c05c473350f1f2d", size = 396168, upload-time = "2026-06-18T16:13:31.977Z" }, + { url = "https://files.pythonhosted.org/packages/10/2a/b4410f906c2ec0008f1608d3ab5143afc3ad3f4e6da0fed3ea2231d0bef4/msgpack-1.2.1-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:dd3bfe82d53edfe4b7fc9a7ec9761e23a7a5b1dac22264505af428253c29ed24", size = 371959, upload-time = "2026-06-18T16:13:33.282Z" }, + { url = "https://files.pythonhosted.org/packages/59/86/1edc67270099a528fa2093ea60fe191233cd238e4bd30cfacf7db79fc959/msgpack-1.2.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5ad5467fc3f68b5468e06c5f788d712e9f8ffc8b0cd1bcb160c105c1ee92dae7", size = 408457, upload-time = "2026-06-18T16:13:34.567Z" }, + { url = "https://files.pythonhosted.org/packages/82/90/8b630fef07d8c5ab457b71ff2c217910c83d333c7a68472c186e87cc504a/msgpack-1.2.1-cp314-cp314-win32.whl", hash = "sha256:98b58bdb89c46190e4609bb36abe17c6d4105ad13f9c5f8f6f64d320f8ced3fb", size = 65942, upload-time = "2026-06-18T16:13:36.056Z" }, + { url = "https://files.pythonhosted.org/packages/16/f1/467b81e98b24dd3885d7b1857728797b4ffc76a7a7483af4fb321a07de3c/msgpack-1.2.1-cp314-cp314-win_amd64.whl", hash = "sha256:74847557e28ce71bd3c438a447ca90e4b507e997ddbdef8a12a7b283b86c156b", size = 72627, upload-time = "2026-06-18T16:13:37.079Z" }, + { url = "https://files.pythonhosted.org/packages/a7/1d/5d8c4c89985feb6acefb82a09e501c60392261856d2408d20bfe4f0360b1/msgpack-1.2.1-cp314-cp314-win_arm64.whl", hash = "sha256:b50b727bd652bdc37d950336c848ef20ec54a4cafc38dce19b1cd86ad625d0f7", size = 66908, upload-time = "2026-06-18T16:13:38.23Z" }, + { url = "https://files.pythonhosted.org/packages/1b/02/ad2afb678b4de94496cd432b581759b756a92c1192d8c767edd6b132efdc/msgpack-1.2.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:8d00f177ca88a77c1cf848d204a38f249751650b601cb6532acc68805d8a8273", size = 86000, upload-time = "2026-06-18T16:13:39.44Z" }, + { url = "https://files.pythonhosted.org/packages/54/74/0b797484013128837f3b1cbb6cea019277c4de4e377dc512b4d9a0f92940/msgpack-1.2.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5bb9c386f0a329c035ddbab4b72d1028bf9627add8dda41070288563d57ed1b1", size = 86544, upload-time = "2026-06-18T16:13:40.447Z" }, + { url = "https://files.pythonhosted.org/packages/a9/b4/b774d7eb95561739907fec675582f83203cf41c597a418c2589b4bfb8e9d/msgpack-1.2.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:20466cca18c49c7292a8984bc15d65857b171e7264bdcb5f96baf8be238791fc", size = 427661, upload-time = "2026-06-18T16:13:41.574Z" }, + { url = "https://files.pythonhosted.org/packages/b2/f9/3243191dc9937e00756c8bc1b0272fed8f23758e43df2a3b46f533e5090f/msgpack-1.2.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:196300e7e5d6e74d50f1607ab9c06c4a1484c383cd22defd727902591f7e8dde", size = 426375, upload-time = "2026-06-18T16:13:42.936Z" }, + { url = "https://files.pythonhosted.org/packages/23/c7/1693111db9944ba4ad4b67a1e788400d78a0b6af7a6523dc7e4e58f8274b/msgpack-1.2.1-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:575957e79cd51903a4e8495a242442949641e08f1efd5197b43bebd3ea7682b4", size = 380495, upload-time = "2026-06-18T16:13:44.306Z" }, + { url = "https://files.pythonhosted.org/packages/3e/2b/92f86956a0c13e8662f7e2ad630c4eb4db07497b967589bd5245e018b2c1/msgpack-1.2.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8c2ed1e48cc0f460bf3c7780e7137ff21a4e18433451916f2442c1b21036cd7d", size = 410897, upload-time = "2026-06-18T16:13:45.629Z" }, + { url = "https://files.pythonhosted.org/packages/da/ea/1479f72d200313a76fc2f823a79d1e07ed052ab7b8a0280640aa7b95de42/msgpack-1.2.1-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:5f6277e5f783c36786a145e0247fc189a03f35f84b251646e53592d2bc12b355", size = 378519, upload-time = "2026-06-18T16:13:46.998Z" }, + { url = "https://files.pythonhosted.org/packages/f5/4d/fa006060ffa1011d32bfae826fe766fe73e02982183601633b7121058ab3/msgpack-1.2.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:f9389552ecf4784886345ead0647e4edc96bee37cbab05b75540f542f766c48c", size = 419815, upload-time = "2026-06-18T16:13:48.205Z" }, + { url = "https://files.pythonhosted.org/packages/2f/e1/aab6c946570496b78e67804721f3d5e2d62a93081b9b37df77764ef56347/msgpack-1.2.1-cp314-cp314t-win32.whl", hash = "sha256:c1c79a604a2969a868a78b6ebd27a887e00c624f14f66b3038e0590cb23332d1", size = 70914, upload-time = "2026-06-18T16:13:49.385Z" }, + { url = "https://files.pythonhosted.org/packages/13/0a/e608956488a2af014cfe6e3d665e090b8ee42aa14b07f8f95b8880d66b09/msgpack-1.2.1-cp314-cp314t-win_amd64.whl", hash = "sha256:f12038a35fabd52e56a3547bab42401af49a45caa6dd00b34c44de235bc93ee2", size = 77999, upload-time = "2026-06-18T16:13:50.467Z" }, + { url = "https://files.pythonhosted.org/packages/d2/8a/27e2e57055176e366a46b85d02d68e7a5bcfbdd8474c9706375d965f24d3/msgpack-1.2.1-cp314-cp314t-win_arm64.whl", hash = "sha256:0adcf06ffde0777c0e1a9b771a2b1c4226ba1bbf748c8efcc02fcdeca3299107", size = 71160, upload-time = "2026-06-18T16:13:51.498Z" }, +] + +[[package]] +name = "mypy-extensions" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/6e/371856a3fb9d31ca8dac321cda606860fa4548858c0cc45d9d1d4ca2628b/mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558", size = 6343, upload-time = "2025-04-22T14:54:24.164Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", size = 4963, upload-time = "2025-04-22T14:54:22.983Z" }, +] + +[[package]] +name = "narwhals" +version = "2.22.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/62/3c/c4ef2164a71c1a63d7f1ae411c4082c5fa872405106db60a4b7114989ad7/narwhals-2.22.1.tar.gz", hash = "sha256:d62920805a0a43b7ff8b54b0c0d3142d796f8a9301836ada37e573d6a33cbcd9", size = 647493, upload-time = "2026-06-05T12:34:34.051Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/48/ca/36339329c4604adbcc99c899b7eb1ce1a555c499b6a6860757dc9bfed36d/narwhals-2.22.1-py3-none-any.whl", hash = "sha256:60567d774edf77db53906f89d9fbd164e66e56d66d388e1e6990f17ac33cfb53", size = 454815, upload-time = "2026-06-05T12:34:32.289Z" }, +] + +[[package]] +name = "networkx" +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" }, +] + +[[package]] +name = "nh3" +version = "0.3.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5e/1b/ef84624f14954d270f74060a19fc550dd4f06656399447569afb584d8c06/nh3-0.3.6.tar.gz", hash = "sha256:f3736c9dd3d1856f80cd031715b84ca75cda2bbb1ac802c3da26bfce590838d7", size = 24684, upload-time = "2026-06-22T00:47:02.008Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/99/3e/6506aa4f23dc7b7993a2d0a45dca3ce864ec48380adfe15a173e643c63e8/nh3-0.3.6-cp314-cp314t-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:2411e8c3cee81a1ddd62c2a5d50585c28aa5566d373ad1db92536b95ddb24ef2", size = 1421679, upload-time = "2026-06-22T00:46:20.248Z" }, + { url = "https://files.pythonhosted.org/packages/e3/e1/e96e7864a7a53bd6b6fab7e9632467382a2a2c1f3fed951918ad131542fb/nh3-0.3.6-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e196fa70c2ff2eb4de7d3df3108f8f358c1d69dff20d45b11f20a5aa227ffb6d", size = 792570, upload-time = "2026-06-22T00:46:22.179Z" }, + { url = "https://files.pythonhosted.org/packages/59/62/5b6108bedaef2b2637fed04c87bdbcb5967b9961758b41f0e466ef22a022/nh3-0.3.6-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:34d2b0d934156b87ee114f599a3ba9b8b9e17b5d79652ba3a13fa50903de965e", size = 842243, upload-time = "2026-06-22T00:46:23.801Z" }, + { url = "https://files.pythonhosted.org/packages/4b/4a/526f199626bfcb496bc01a268051b44737962005553b158e985ed7e64865/nh3-0.3.6-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:f2f14b7ae1fca99c4a66c981aac3974e7fbc1ca30a12673d223ae1df76680917", size = 1001468, upload-time = "2026-06-22T00:46:25.481Z" }, + { url = "https://files.pythonhosted.org/packages/49/09/0d8e3101636d9ad88cdefb2914e764cb8e876ebdbb4286bfc251277d9c67/nh3-0.3.6-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:889932a97fb4abb6f95fef1914c0d269ebfb60011e67121c1163059b9449dbb4", size = 1082933, upload-time = "2026-06-22T00:46:27.15Z" }, + { url = "https://files.pythonhosted.org/packages/09/a1/ea83abe738a3fbaa203dfdb836ca7cbab0e7e9609faaee4fe1d4652599c0/nh3-0.3.6-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:edb2b4a1a27523e6cc7c417f8d21ce3d005243548b93e56b762b66b0c7f589f9", size = 1043120, upload-time = "2026-06-22T00:46:28.89Z" }, + { url = "https://files.pythonhosted.org/packages/66/69/0654482b8635012fbae67826bd6c381abb05d841ac7388b9b4666300fdad/nh3-0.3.6-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:43bc1ed3fa0716295fabee29ba42b2667e4a51d140b0a68e092170a765474fa6", size = 1023824, upload-time = "2026-06-22T00:46:30.453Z" }, + { url = "https://files.pythonhosted.org/packages/ed/a6/1f7285ffadc8307c4dbeb08d21b920536d5117785056d1079e998c4dfa44/nh3-0.3.6-cp314-cp314t-win32.whl", hash = "sha256:597a8e843bea00b2eb5520658dc24a9bb032e7fc9e7c2c0c4cd29420220c9796", size = 599253, upload-time = "2026-06-22T00:46:32.072Z" }, + { url = "https://files.pythonhosted.org/packages/36/ea/5542f3c45da4c00290d9d67a65e996702e23e613c4b627de3e09cb9fe357/nh3-0.3.6-cp314-cp314t-win_amd64.whl", hash = "sha256:4713502748f564fee0633b37b3403783ce0a3af3a3d148ad91025a5bdadb7bc6", size = 612553, upload-time = "2026-06-22T00:46:33.53Z" }, + { url = "https://files.pythonhosted.org/packages/66/35/26bd47e6af5915a628281dccdac354ddf4e32f7397047894270acd8c9870/nh3-0.3.6-cp314-cp314t-win_arm64.whl", hash = "sha256:69bbb92865a693d909db3a700d3c01537533844d0948c1e9323561ce06ecda41", size = 595151, upload-time = "2026-06-22T00:46:34.878Z" }, + { url = "https://files.pythonhosted.org/packages/f3/ab/a7653bce9a3b204be6a6931767a9e23595807bb84790ce6685e4d7e5bd08/nh3-0.3.6-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:a43ebd7543555c3ac1bc353023d0794e75cb76f6f18f19c32e95441496c0cc25", size = 1443564, upload-time = "2026-06-22T00:46:36.66Z" }, + { url = "https://files.pythonhosted.org/packages/41/21/e1084ab18eb589506335c7c7576f2d4643e9a0c0e33983ef0e549a256b96/nh3-0.3.6-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e1b160831c9cdb06a6c79c2f9cdb11386602938f9af260d1c457a85add4f6f69", size = 838002, upload-time = "2026-06-22T00:46:38.101Z" }, + { url = "https://files.pythonhosted.org/packages/b0/94/f48d08e6f72a406300fa11d8acd929fea1a80d4bf750fa292cb10785f126/nh3-0.3.6-cp38-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d14bf7982e7a77c0c775634c29c07ce08b38a046df73e1c1f139b3e82f18a38e", size = 823045, upload-time = "2026-06-22T00:46:39.495Z" }, + { url = "https://files.pythonhosted.org/packages/25/bb/431615ba1d1d3eb63cde0f974f2114edf863a8a3f6049a12fed23fc241d3/nh3-0.3.6-cp38-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:44673b27010051ab5a5e438a86ec31bbda61d4a77d7e900af6b7be3037c1abae", size = 1093171, upload-time = "2026-06-22T00:46:41.21Z" }, + { url = "https://files.pythonhosted.org/packages/0e/24/a0d80182a18919665fefd19c1c06f1d1df1c9a6455d0252de40c034a0bc3/nh3-0.3.6-cp38-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e6b7beece07525dc6e6b0fc2f104442de2ba328360ad00e50cbe2e1fd620447d", size = 1049217, upload-time = "2026-06-22T00:46:42.804Z" }, + { url = "https://files.pythonhosted.org/packages/0a/13/6f1e302ca674ac74362e150848ad56a1be5145391204f74facdb8e94df12/nh3-0.3.6-cp38-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:455469a29951edc92bc48b47ac2281c3f2609e6c4f6a047056449f8c2c23facf", size = 917372, upload-time = "2026-06-22T00:46:44.495Z" }, + { url = "https://files.pythonhosted.org/packages/5b/67/314f6151bad77a93d751978a344033e1fc890822f05f0416079338e34231/nh3-0.3.6-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:905f877dc66dd7aea4a76e54bcb26acb5ff8216f720c0017ccf63e0e6035698e", size = 806699, upload-time = "2026-06-22T00:46:45.99Z" }, + { url = "https://files.pythonhosted.org/packages/3c/a6/bfaa00046e58603507dcfc266c4778e3ab7adf68a5dedd73b6274b8d9314/nh3-0.3.6-cp38-abi3-manylinux_2_31_riscv64.whl", hash = "sha256:25c733bee928530556b1db0ea46c52cf5aa686146e38e60a6fc7cb801ef91cec", size = 835165, upload-time = "2026-06-22T00:46:47.617Z" }, + { url = "https://files.pythonhosted.org/packages/30/a8/fb2c38845efb703a9173bffdfc745fc64d2b0e55cfc73a3647d2f028250c/nh3-0.3.6-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2f90d9a0cfdbee218994fdaaeeb5a0fde62d08f35e4eef0378ec1e2200172fd0", size = 858282, upload-time = "2026-06-22T00:46:49.276Z" }, + { url = "https://files.pythonhosted.org/packages/68/17/06e72a18ee9b572914447338237ca7eb164c0df901f141bc10d1282247a2/nh3-0.3.6-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:82ca5bf427ad1b216b65ede1a2e2d87dc49bec417ceba0f297213107d3cd9d78", size = 1014328, upload-time = "2026-06-22T00:46:51.026Z" }, + { url = "https://files.pythonhosted.org/packages/11/f9/3966c61455668c08853bf5e33b4bed93c421f3194ce4de896dc248d6f6ce/nh3-0.3.6-cp38-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:f5ed5fe84aee7f39db95c214a7421bf0499fbf500fec6d86a4e29bfc37971438", size = 1098207, upload-time = "2026-06-22T00:46:52.674Z" }, + { url = "https://files.pythonhosted.org/packages/19/d3/479cb4ae440424825735d60525b53e3c77fd60fd6e6afc0e984f00eb0178/nh3-0.3.6-cp38-abi3-musllinux_1_2_i686.whl", hash = "sha256:082675ff87b9385ec430ffe6d5847ba7456cc39b73720cd4add472f9f4cffd56", size = 1056961, upload-time = "2026-06-22T00:46:54.335Z" }, + { url = "https://files.pythonhosted.org/packages/17/0c/6cdb5ee1e127be50dc8391e54bddc1f64e87bf4bfad0c55633320e2e02db/nh3-0.3.6-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:36d06341bd501240d320f5942481ed5e6846136b666e1ba4faf802b78ebc875f", size = 1033829, upload-time = "2026-06-22T00:46:56.258Z" }, + { url = "https://files.pythonhosted.org/packages/e9/55/9de666ad975d6ccd77d799ea0add55ee2347aa81286ce21b2a97c070746b/nh3-0.3.6-cp38-abi3-win32.whl", hash = "sha256:5276ef17bdba9ad8040575c74072008b13aae429436e9d0429e718bb5f90f4da", size = 609081, upload-time = "2026-06-22T00:46:57.665Z" }, + { url = "https://files.pythonhosted.org/packages/82/fa/2b5d684e3edf1e81bfd02d298c78c3e3da77ca1d8a2be3183a79544a7548/nh3-0.3.6-cp38-abi3-win_amd64.whl", hash = "sha256:f338ac7d594c067679f1e99b4f5ec3906842979560f9d8f15d6bdfa39a353b10", size = 624461, upload-time = "2026-06-22T00:46:59.163Z" }, + { url = "https://files.pythonhosted.org/packages/7b/e5/7cafee2f0413ca4cb0ef3bd111e94d408a48810008b283ad8aee00dd1809/nh3-0.3.6-cp38-abi3-win_arm64.whl", hash = "sha256:69f365963f63a1e9bff53bdbb3c542c7c2efed3e163c9d5d83a772a2ac468c21", size = 603060, upload-time = "2026-06-22T00:47:00.596Z" }, +] + +[[package]] +name = "nltk" +version = "3.9.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "joblib" }, + { name = "regex" }, + { name = "tqdm" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/74/a1/b3b4adf15585a5bc4c357adde150c01ebeeb642173ded4d871e89468767c/nltk-3.9.4.tar.gz", hash = "sha256:ed03bc098a40481310320808b2db712d95d13ca65b27372f8a403949c8b523d0", size = 2946864, upload-time = "2026-03-24T06:13:40.641Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9d/91/04e965f8e717ba0ab4bdca5c112deeab11c9e750d94c4d4602f050295d39/nltk-3.9.4-py3-none-any.whl", hash = "sha256:f2fa301c3a12718ce4a0e9305c5675299da5ad9e26068218b69d692fda84828f", size = 1552087, upload-time = "2026-03-24T06:13:38.47Z" }, +] + +[[package]] +name = "numpy" +version = "2.4.6" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.12' and sys_platform == 'win32'", + "python_full_version < '3.12' and sys_platform != 'win32'", +] +sdist = { url = "https://files.pythonhosted.org/packages/d0/ad/fed0499ce6a338d2a03ebae59cd15093910c8875328855781952abf6c2fe/numpy-2.4.6.tar.gz", hash = "sha256:f3a3570c4a2a16746ac2c31a7c7c7b0c186b95ce902e33db6f28094ed7387dda", size = 20735807, upload-time = "2026-05-18T23:37:14.07Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b3/49/ec46835a70be8fa6446c495126ac84fdb28cb2558e1620ffb87a10c8b64c/numpy-2.4.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0280e0356c0829a18d9de1cb7eee50ec22ca639878d7240307ca0943d73cd2c4", size = 16969194, upload-time = "2026-05-18T23:33:13.503Z" }, + { url = "https://files.pythonhosted.org/packages/0e/0d/f5957185c0ee2f3e12f78715aa9e3b353fd83633316c8532b38faa37e3f6/numpy-2.4.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:110f8b71aacb688ec69062bb7f6938a0f8acb01b7c1c4beb453c65b6d234584d", size = 14964111, upload-time = "2026-05-18T23:33:17.795Z" }, + { url = "https://files.pythonhosted.org/packages/ad/40/40a40ee0ddf7ceb782c49af278894b686e586d65d8c1889c8b5da01a3d7d/numpy-2.4.6-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:4cfe66903cc32a9921a6733d96b19bb6abf310397581bbad89c228f5abaf0ee8", size = 5469159, upload-time = "2026-05-18T23:33:20.654Z" }, + { url = "https://files.pythonhosted.org/packages/63/13/f9a8046535cb21deae82f8d03de9617e08882d274fad2539630761888228/numpy-2.4.6-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:8155154c7c691289fe18f510b5d4657c68c67989f293f0535a91360392ff6538", size = 6798936, upload-time = "2026-05-18T23:33:22.987Z" }, + { url = "https://files.pythonhosted.org/packages/33/a8/6fa8c1a345a8c85dbb21932c447bee07c30a2c2a3f31e369c0a84b300147/numpy-2.4.6-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0ab0a9c4ffb1a6d95ef519fe4247dba8eb6b18ad93999f76b7f657039acabd47", size = 15966692, upload-time = "2026-05-18T23:33:26.62Z" }, + { url = "https://files.pythonhosted.org/packages/02/03/74fe2a4cb3817d94d86402f2506554130a2f01414e299b5a843e5a8a957f/numpy-2.4.6-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:89cd468399cfd2504718f0ba50e410dca55a170b61a02ad92bb18c8a65186e93", size = 16918164, upload-time = "2026-05-18T23:33:29.955Z" }, + { url = "https://files.pythonhosted.org/packages/c5/80/3615be3313f7e7696609bc194b9f0101da809df79e859bdb84e0cd043f46/numpy-2.4.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c2d37ab77531417474168eb79d6d80b14f821a966818505d03013d0833edb7a8", size = 17322877, upload-time = "2026-05-18T23:33:34.724Z" }, + { url = "https://files.pythonhosted.org/packages/ca/ac/a691e0fe2675e370d0e08ff905adc49a1c8830e8cae03efe4477e92cd55d/numpy-2.4.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f407cb6b8e9d6d8c626bc73c945db1706035af8fd632295547bf1c9e46d092d6", size = 18651487, upload-time = "2026-05-18T23:33:38.217Z" }, + { url = "https://files.pythonhosted.org/packages/15/a7/9bc1cd626d7bf6869bfedf27b91b6ab5dd607758bf8e959d6fa80c6a59cb/numpy-2.4.6-cp311-cp311-win32.whl", hash = "sha256:ddea102b48f9e339f3948bf22040944184627a30fdf7f858667673b9c5f033c8", size = 6233945, upload-time = "2026-05-18T23:33:41.331Z" }, + { url = "https://files.pythonhosted.org/packages/c5/31/7fc6239c12bce7e931463251cca4426c465e1876ba3cc785402ef4dd8f4e/numpy-2.4.6-cp311-cp311-win_amd64.whl", hash = "sha256:1e254a00cdf42b1e4d5b3d68d33af63268d41340d8885df2ab6470f2e1500147", size = 12608406, upload-time = "2026-05-18T23:33:44.131Z" }, + { url = "https://files.pythonhosted.org/packages/27/83/140f85a466595a16382996a1bf06b2b54bcd597488921b0c9daaeeda72af/numpy-2.4.6-cp311-cp311-win_arm64.whl", hash = "sha256:ed9749eef4cbd126da3dc1d6bcb3a57f5eb7ac6a6484146bdbf743f552dfc577", size = 10479528, upload-time = "2026-05-18T23:33:50.725Z" }, + { url = "https://files.pythonhosted.org/packages/95/2a/3d7b5ac8aac24feaf9ad7ed58f45b0bbc06d37e4338ae84c9f2298b570f9/numpy-2.4.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:001fbb8e08d942dd57599e781f2472269ee7f2755fae407b4f67b2f0b17da3f1", size = 16689119, upload-time = "2026-05-18T23:33:54.065Z" }, + { url = "https://files.pythonhosted.org/packages/ea/12/92c4c131527599e8288d6918e888d88726f84d805d784b771f32408aeaef/numpy-2.4.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ebfb099f8dcf083deef3ac1ca4c1503f387cf76296fcb3816b66f5ecb5f54fdb", size = 14699246, upload-time = "2026-05-18T23:33:57.621Z" }, + { url = "https://files.pythonhosted.org/packages/ad/fe/c0a6b7b2ca128a8fb228575147073b660656734b8ebe4d76c8fd748dcc79/numpy-2.4.6-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:3213d622a0283a39a93d188f3cf72b26862df52fbb4ca3697f51705016523d41", size = 5204410, upload-time = "2026-05-18T23:34:00.302Z" }, + { url = "https://files.pythonhosted.org/packages/f3/d4/9770d14ba719432bb90a421bfd443872ed0f70f7264b64bec12ea363d5fd/numpy-2.4.6-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:357cc07a6d7b0b182ff02249616a03742827ebb1277546b5c7cd7f7620a45698", size = 6551240, upload-time = "2026-05-18T23:34:02.852Z" }, + { url = "https://files.pythonhosted.org/packages/c9/c6/50a46a6205feba2343f1d6d17438107c5dc491ed1c736e6ea68689fd906b/numpy-2.4.6-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5f9fb9157b4ce2971008323afe46053787b526ef624fea915b261468a8421a0f", size = 15671012, upload-time = "2026-05-18T23:34:05.485Z" }, + { url = "https://files.pythonhosted.org/packages/99/60/14115e6364fa676c5397c2ad3004e527e9aa487abf5d0706ec81bbd08529/numpy-2.4.6-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:90f9849678c75fe7afa2d348ac842c168b0a4d3d61919687216dfc547976d853", size = 16645538, upload-time = "2026-05-18T23:34:09.265Z" }, + { url = "https://files.pythonhosted.org/packages/ae/c5/693cbe59e57db94d2231fa519ca3978dc9e19da5a8f088588f5c6e947ff2/numpy-2.4.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c1a2af6c6ef86344a6b0db6b97834208bf598db514f2b155042439b62605601a", size = 17020706, upload-time = "2026-05-18T23:34:13.053Z" }, + { url = "https://files.pythonhosted.org/packages/ef/fc/85b7c4eff9b4966ade25c2273cf7e7012e92366c032058653934b37de044/numpy-2.4.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e5805d5a22fd19c8ccff10a9561f9df94436b0545619ea579db2d3c35294bce2", size = 18368541, upload-time = "2026-05-18T23:34:17.024Z" }, + { url = "https://files.pythonhosted.org/packages/f6/81/e1b27545deedce7f4a0b348618c6b62d74e36a4dc9ccd42f3eb2f85eee32/numpy-2.4.6-cp312-cp312-win32.whl", hash = "sha256:e3eeb0aabd6bd5ce64faae67e9935203a6991b4bc2a485a767fbafb2c5125f45", size = 5962825, upload-time = "2026-05-18T23:34:20.3Z" }, + { url = "https://files.pythonhosted.org/packages/ab/ca/feab00bd44aa5fe1ad2c18f08b4d3bb92e26484b0b1d1443897809ed528c/numpy-2.4.6-cp312-cp312-win_amd64.whl", hash = "sha256:d8e8286dd7cea7895157318d1b91cdacac64c479f3cbc8dce548331728484751", size = 12321687, upload-time = "2026-05-18T23:34:23.095Z" }, + { url = "https://files.pythonhosted.org/packages/63/cf/5a6d34850a39d1093558564f77ee8e8e0bee5061151b8f05a55711001ec7/numpy-2.4.6-cp312-cp312-win_arm64.whl", hash = "sha256:4081eb135ac24158bd51cdfbef16f1c64df7063b1143f24731387137c092bec8", size = 10221482, upload-time = "2026-05-18T23:34:25.876Z" }, + { url = "https://files.pythonhosted.org/packages/fb/82/bdab26d7438c6791ca31b7c024ca37c1eab8b726ba236129005cd4a06e45/numpy-2.4.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:511dbaf848decaaaf4b4ca48032619fb3138710c4bf7da7617765edad1ef96b0", size = 16684648, upload-time = "2026-05-18T23:34:29.41Z" }, + { url = "https://files.pythonhosted.org/packages/1b/30/a80189bcc7f5e4258b3fbc3968d909d1756f54d023299ecc39ad6fdb9ef8/numpy-2.4.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bf162abab1c1a736333192707cef898e735a5ca00f38f27eeedf44b39d9e85eb", size = 14693902, upload-time = "2026-05-18T23:34:33.013Z" }, + { url = "https://files.pythonhosted.org/packages/97/12/70b5d0d7c15e1ebb8a6a84a8caa1d19e181d84fb58bb6d70aca29099dec1/numpy-2.4.6-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:043191bfa8eab18c776647b62723ac9dddece59743b13f49b2016094129c2b3f", size = 5198992, upload-time = "2026-05-18T23:34:36.132Z" }, + { url = "https://files.pythonhosted.org/packages/ba/8c/ebd2a8f8a83541f8d38cc5667e8c2b69cecfd30da6e45693e8158857d44b/numpy-2.4.6-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:6180d8b35af935aed8ece3a85e0a43f87393ae0ac87c8d2c8bd2c993f7270ef3", size = 6546944, upload-time = "2026-05-18T23:34:38.484Z" }, + { url = "https://files.pythonhosted.org/packages/bb/c5/7b863a97a91671a0338f4253bd3b5a3d3852f0692dae91711c9f4a10e787/numpy-2.4.6-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:72fbe16c6fac95aedf5937fa873445cec2110be35d8a4e9433d7501fd98dae6b", size = 15669392, upload-time = "2026-05-18T23:34:41.257Z" }, + { url = "https://files.pythonhosted.org/packages/a5/9d/3584b9984ca4c047aea75214ce1a4c4c73d849bd71b604264b7f5653f8a8/numpy-2.4.6-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a7830bab239b79cda9c08c2da014761cafb48da6150e1da17ac06283f43b6089", size = 16633220, upload-time = "2026-05-18T23:34:45.075Z" }, + { url = "https://files.pythonhosted.org/packages/05/ae/7c67fba23bd98caec7c99261f3a16072ade14813486b0282cb29846de832/numpy-2.4.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ef4aea96ce4d3b074422cb4f2f64e216bf9e213004bb58ecfdf50ea02ea8eb9a", size = 17020800, upload-time = "2026-05-18T23:34:49.065Z" }, + { url = "https://files.pythonhosted.org/packages/d9/5d/3b6725cb31d983c5e66916f5d36f6d7e5521129e4c4404d64f918292a5b6/numpy-2.4.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:dfa20cc6ca228e6b155b11da03825975ce66aea520985dbbddf0f2a5a495c605", size = 18357600, upload-time = "2026-05-18T23:34:52.709Z" }, + { url = "https://files.pythonhosted.org/packages/f7/da/2ccc6c2fe8898dee01d90c75c5f5f914a23daf99e3e0f59516a08760c8b5/numpy-2.4.6-cp313-cp313-win32.whl", hash = "sha256:56b39e5e0622a09a25bf5baf62f4bcf0cb8a41ae6e2819cf49bbc5a74c083f91", size = 5961134, upload-time = "2026-05-18T23:34:55.618Z" }, + { url = "https://files.pythonhosted.org/packages/b5/cd/9cc4dc876fb065d5c220aae4d5e14826b2715331bb7618ce1fb07a679d99/numpy-2.4.6-cp313-cp313-win_amd64.whl", hash = "sha256:c4fc99836233ea196540b17ab0983aff60ed07941751930f5f4d05bc3b3b7359", size = 12318598, upload-time = "2026-05-18T23:34:58.928Z" }, + { url = "https://files.pythonhosted.org/packages/39/1e/c0bcba1f8694116485fe28fd1be698c278fcda4141c5b0e53a2aed8b12a8/numpy-2.4.6-cp313-cp313-win_arm64.whl", hash = "sha256:a7c711e21628b52034bb5ab8d1bce291f752fcc5e92accc615778acee1ff4778", size = 10222272, upload-time = "2026-05-18T23:35:02.167Z" }, + { url = "https://files.pythonhosted.org/packages/63/6d/cc5619247c8f4204e507f5883528372e4ac4bb189e579fb859a12e480b1f/numpy-2.4.6-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:112b06a867b235ef466ed3508ddf0238050df9c727cafb5301ac385b899189a1", size = 14821197, upload-time = "2026-05-18T23:35:05.468Z" }, + { url = "https://files.pythonhosted.org/packages/00/58/f1c39161c87d9e9bed660f1ed4bafc0e403d5ec9650b6dd77aead07d489b/numpy-2.4.6-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:eaf7fa2de5c0be8ae6ff8e9bea2ccd725e980541244521d8d4b5f3354a27babe", size = 5326287, upload-time = "2026-05-18T23:35:08.693Z" }, + { url = "https://files.pythonhosted.org/packages/af/57/3917ab0fd97f271a8694513581b8a36c655f111c446852c302f04ccdb6fc/numpy-2.4.6-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:7265a2f3d436e54ef9f2b52b5c937e6be778781bd97a590319d7348f1c1ca997", size = 6646763, upload-time = "2026-05-18T23:35:11.459Z" }, + { url = "https://files.pythonhosted.org/packages/eb/0f/037e64c494b67581ae18193d770adef354c41f3f2c8ebf865602d949bf8f/numpy-2.4.6-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f74a575920ab21fe304421a3fc28793d82e299cae9eccb37084e9fc7f3617c20", size = 15728070, upload-time = "2026-05-18T23:35:14.79Z" }, + { url = "https://files.pythonhosted.org/packages/21/a6/5d2bae9c9542eb4df16dc9c46dc79c186e9bad53805dfa5399a6023c6db0/numpy-2.4.6-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ede83e07a75dd06bc501566c1eca2afc0d61677c1472ac9ad93fdee6e638a48d", size = 16681752, upload-time = "2026-05-18T23:35:18.836Z" }, + { url = "https://files.pythonhosted.org/packages/92/14/23d1dfb410ae362cd59ce53e936b1513d545eb40db3949ced632e19a459e/numpy-2.4.6-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:68bb27509ac1b9a3443094260f6326150663b06abe40b73a2f81160623da5b67", size = 17086024, upload-time = "2026-05-18T23:35:22.52Z" }, + { url = "https://files.pythonhosted.org/packages/4b/6e/23595a2c642cdf3bc567877064bdd7f91c8b0038a4453cf2daf7248eafe9/numpy-2.4.6-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:a0df0043bdb289bde1f62da130d20df23d58b45429f752bc7a8fc5325a225ecd", size = 18403398, upload-time = "2026-05-18T23:35:26.398Z" }, + { url = "https://files.pythonhosted.org/packages/8a/90/0ac3bc947217e66dec77e7cbc6a1979d1af70b6461b82f620d3bccd5e4c8/numpy-2.4.6-cp313-cp313t-win32.whl", hash = "sha256:29a287e0cf63ff528da061de6b9f64a4618da591ca1046aafc54062e40ca7eab", size = 6084971, upload-time = "2026-05-18T23:35:29.387Z" }, + { url = "https://files.pythonhosted.org/packages/77/71/5673e351671a1d2bd6063b91b44f70c0affea7d1516fa7a6572941ba4aa1/numpy-2.4.6-cp313-cp313t-win_amd64.whl", hash = "sha256:25c692919ac5a01f170a3bfcd62d745b24fd095c353d50812637d6fcab442e75", size = 12458532, upload-time = "2026-05-18T23:35:32.175Z" }, + { url = "https://files.pythonhosted.org/packages/3f/88/19d3503c5046e688f049274b27a3ef3d771152fa80d3ba3d01a3dff61abe/numpy-2.4.6-cp313-cp313t-win_arm64.whl", hash = "sha256:1e978ec1e8bd0e0e4de6bb75de9d30cbb74db6b6a2bb727618613703ca0167dd", size = 10291881, upload-time = "2026-05-18T23:35:35.465Z" }, + { url = "https://files.pythonhosted.org/packages/f8/91/3ab2044d05fd16d343c5ac2e69b127f1b2854040dd20b193257c78028bd3/numpy-2.4.6-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:06ca2f61ec4385a07a6977c55ba998a4466c123642b4a32694d3128fce18c079", size = 16683458, upload-time = "2026-05-18T23:35:38.353Z" }, + { url = "https://files.pythonhosted.org/packages/8e/62/764ce66fa4147ae6d73071a3abf804ffe606f174618697c571acdf26a7c9/numpy-2.4.6-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:38efbc8de75c7a0fc1ac190162d892787f3f47b57cc291231aafee36b80982b7", size = 14704559, upload-time = "2026-05-18T23:35:42.14Z" }, + { url = "https://files.pythonhosted.org/packages/60/61/23f27c172f022e04025b7dc2367f4d63c1a398120607ec896228649a6f48/numpy-2.4.6-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:d581b735e177fdcdce6fed8e7e8880a3fb6ee4e3653a3ac6af01c6f4c03effc5", size = 5209716, upload-time = "2026-05-18T23:35:45.377Z" }, + { url = "https://files.pythonhosted.org/packages/03/71/21cf70dc6ea3e3acb95fc53a265b2fc248b981f0194ceb5b475271b8809d/numpy-2.4.6-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:0a041d3d761dc3c35cc56ce0351506a02bcbc25f7b169f652435141a17db9096", size = 6543947, upload-time = "2026-05-18T23:35:47.926Z" }, + { url = "https://files.pythonhosted.org/packages/d5/91/64288395ee1799bd2e0b04a305dce9666da90c961e1f3fe982a05ee1c036/numpy-2.4.6-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:40fdc1ae7125e518ea98e53e69a4ebc27e1fd50510c47b7ea130cf21e5e1d42b", size = 15685197, upload-time = "2026-05-18T23:35:50.863Z" }, + { url = "https://files.pythonhosted.org/packages/f3/eb/ebffaa97dc55502df69584a8f0dcf07f69a3e0b3e2323670a2722db9aa39/numpy-2.4.6-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a2c306dea656c12c68f51f4cea133cbe78ca7435eb28c735eac1d3ebe73be6e8", size = 16638245, upload-time = "2026-05-18T23:35:54.752Z" }, + { url = "https://files.pythonhosted.org/packages/b8/0b/54f9da33128d7e350fab89c7455902eeae70349ee52bddb448dc4a576f45/numpy-2.4.6-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:33111801a01c12a8a1e3721f0a9232f8cfc8ae2c6b7098167e6f623c6073f402", size = 17036587, upload-time = "2026-05-18T23:35:58.355Z" }, + { url = "https://files.pythonhosted.org/packages/b6/f0/fdebc1052db1cc37c64beb22072d67cd6d1c71adca1299f53dec2b5e20d3/numpy-2.4.6-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ae506e6902902557576a26ff33eda8695e7ecb3cb36c3b573a0765dee114ebdb", size = 18363226, upload-time = "2026-05-18T23:36:02.845Z" }, + { url = "https://files.pythonhosted.org/packages/aa/b4/298628d98c72b57e57f7165ae6a481a1deaf6f3c28262a6e4c739c275930/numpy-2.4.6-cp314-cp314-win32.whl", hash = "sha256:aaf159caa35993cb1f56fb9b8e4610d35758e7ca005412eb1daa856a78c9c4b1", size = 6010196, upload-time = "2026-05-18T23:36:05.92Z" }, + { url = "https://files.pythonhosted.org/packages/df/ac/46de6dda46478f7942f839e094970be2d4a861e005c4b3bf07c92e291a09/numpy-2.4.6-cp314-cp314-win_amd64.whl", hash = "sha256:b507f5c4c1d508876d1819b6bf9a49d365b96320b5d4993426b33a23ca4b8261", size = 12450334, upload-time = "2026-05-18T23:36:09.107Z" }, + { url = "https://files.pythonhosted.org/packages/78/92/b8b798ac784102c0da830d2257d59358e3d3d90d1e2b3f2575dad976c5cf/numpy-2.4.6-cp314-cp314-win_arm64.whl", hash = "sha256:6f41ae150c4e32db4f3310cdaf64b1593a03dbabe29eec77fc9b50fe64061df6", size = 10495678, upload-time = "2026-05-18T23:36:12.766Z" }, + { url = "https://files.pythonhosted.org/packages/30/34/ec28d1aa8115971537c01469ab2011ee96827930f0a124de1000cc2a7ed7/numpy-2.4.6-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ece3d2cfe132e7d51f44a832b303895e6f2d499c5e74dfbdb06ee246147a304a", size = 14823672, upload-time = "2026-05-18T23:36:16.473Z" }, + { url = "https://files.pythonhosted.org/packages/16/bd/f6d1fede4e54e8042a7ff97bb495510f3c220f94bcd9e8b228e87c92cc0d/numpy-2.4.6-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:e3e5193ef5a3dc73bceee50f7fdc2c90dbb76c42df8d8fae3d1067a583df579e", size = 5328731, upload-time = "2026-05-18T23:36:19.767Z" }, + { url = "https://files.pythonhosted.org/packages/f4/f0/e105b9e2fd728a9910103884decd6951d9dd73896b914a98d9a231de02ee/numpy-2.4.6-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:17f9ade344e7d9b464a084d69bcf18fc691cb1db67c62ed80820bf4926d78f0e", size = 6649805, upload-time = "2026-05-18T23:36:22.266Z" }, + { url = "https://files.pythonhosted.org/packages/82/dd/1206a7ca6ab15e3f02069707ca96222e202af681bb73756da7527f3cb837/numpy-2.4.6-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9cd5ffd25db4e7ba6a375693b3fc0fc1791ec636c17db3720da19bde7180ec43", size = 15730496, upload-time = "2026-05-18T23:36:25.713Z" }, + { url = "https://files.pythonhosted.org/packages/51/e7/38d3ea825dcab85a591734decb2f6c67caa7c8367d374df1a1c3842f9b07/numpy-2.4.6-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7d92c3819208a60205a12a245c91ad70cb0a85336659b19b834205573ac8456e", size = 16679616, upload-time = "2026-05-18T23:36:29.652Z" }, + { url = "https://files.pythonhosted.org/packages/93/b7/caabfdf53edf663e0b4eb74d7d405d83baef09eb5e83bcd32d601d72b93e/numpy-2.4.6-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e85b752a1e912b70eaad4fafbd4d1238007ab221de2009b9a2f5ae7461239895", size = 17085145, upload-time = "2026-05-18T23:36:33.449Z" }, + { url = "https://files.pythonhosted.org/packages/f9/45/68d7c33a6bcf3e5aa3bdbd57a367e6f615286dfd6482f97e8ffeb734306e/numpy-2.4.6-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:29cb7f67d10b479ff07c17d33e39f78c07f71c40ef30d63c153d340e96cd3fb4", size = 18403813, upload-time = "2026-05-18T23:36:37.369Z" }, + { url = "https://files.pythonhosted.org/packages/9c/50/0753655aa844c99cd9e018aacf76f130f1bd81d881bb74bc0aef5d73a8ba/numpy-2.4.6-cp314-cp314t-win32.whl", hash = "sha256:260a5d70215b61ab4fadf5c7baacd64821842975eea312125ed3c39a6391b063", size = 6156982, upload-time = "2026-05-18T23:36:40.817Z" }, + { url = "https://files.pythonhosted.org/packages/b2/d4/7c67becf668f973cb490cec3e98dfd799d866f9c989a54d355672cfa0db6/numpy-2.4.6-cp314-cp314t-win_amd64.whl", hash = "sha256:81a1cca95ed5bb92aa8b10dd2cdc9a0d3853a50fad926c28b5d7e8ea54389627", size = 12638908, upload-time = "2026-05-18T23:36:43.996Z" }, + { url = "https://files.pythonhosted.org/packages/43/bb/e1c71a4295b1b1d1393d50dbb4f2a36283c6859d9d3892e84f00ec5a91d5/numpy-2.4.6-cp314-cp314t-win_arm64.whl", hash = "sha256:0c9136e14ed34a9e343a31c533d78a9813a69a3148332bce5e9821cb2f996e66", size = 10565867, upload-time = "2026-05-18T23:36:47.114Z" }, + { url = "https://files.pythonhosted.org/packages/de/12/b422cc84439adc0d00de605bf4a308890ae5c26f2c71fbd73e5d08fbb0dd/numpy-2.4.6-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:55cced7c52e981362f708ad635198e97a752dfba412cc03c23bbf3bd8d5cd662", size = 16847511, upload-time = "2026-05-18T23:36:50.673Z" }, + { url = "https://files.pythonhosted.org/packages/44/53/f481bef68011740f8849418d82db07230e825013f31f4eef5ba5b805316a/numpy-2.4.6-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:d6da64deb6b8ed903e7560180a92f2d804ee1ba5eeb849ac2748b8c1aba1f6d7", size = 14889064, upload-time = "2026-05-18T23:36:53.879Z" }, + { url = "https://files.pythonhosted.org/packages/7f/57/42ed575c10ced8af951d426bc4e1f8aff16fd851db33f067036215a7f860/numpy-2.4.6-pp311-pypy311_pp73-macosx_14_0_arm64.whl", hash = "sha256:68a5124b13fa6cc2086764a20005d30bc0548146f7f5322f02fce212ca14317f", size = 5394157, upload-time = "2026-05-18T23:36:57.194Z" }, + { url = "https://files.pythonhosted.org/packages/6a/ef/f66cc724fcc36c1e364c67f51ae9146090b8b584f27d58b97fdae3edd737/numpy-2.4.6-pp311-pypy311_pp73-macosx_14_0_x86_64.whl", hash = "sha256:948424b06129ce883307e8cff868c31396d8dc7630a59c61d70d98dbe70f222c", size = 6708728, upload-time = "2026-05-18T23:36:59.575Z" }, + { url = "https://files.pythonhosted.org/packages/1a/9c/c531f2293b91265d8b48e9b329f54fdd7ffae73cb4134ea10cca4237e9cc/numpy-2.4.6-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5dbbdb29840ca3d91ee0fece42fc29278886d908280bfec0a5846c6f901a3eb0", size = 15798374, upload-time = "2026-05-18T23:37:02.674Z" }, + { url = "https://files.pythonhosted.org/packages/1a/b0/413077f6b1153ed3cba361401c6783bbad6114804a000cc22eb71c13e190/numpy-2.4.6-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8ad03c0965fb3c692200e74d458ca28c1dbb4ce96f9a479a8aa041ad5fabca02", size = 16747286, upload-time = "2026-05-18T23:37:06.327Z" }, + { url = "https://files.pythonhosted.org/packages/15/ce/e5ec180bc41812edcd8daeb8639d205622c0e8c02259d8ab25a0201b3c2a/numpy-2.4.6-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:2803abfebfc990042cd494d8ce2d5f82e9d847af6d35ec486923aa19dbad5e73", size = 12504263, upload-time = "2026-05-18T23:37:09.715Z" }, +] + +[[package]] +name = "numpy" +version = "2.5.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.14' and sys_platform == 'win32'", + "python_full_version >= '3.14' and sys_platform != 'win32'", + "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'win32'", + "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform != 'win32'", +] +sdist = { url = "https://files.pythonhosted.org/packages/e7/05/3d27272d30698dc0ecb7fdfaa41ad70303b444f81722bb99bce1d818638a/numpy-2.5.0.tar.gz", hash = "sha256:5a129578019311b6e56bdd714250f19b518f7dceeeb8d1af5490f4942d3f891c", size = 20652461, upload-time = "2026-06-21T20:57:51.95Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fa/0a/11486d02add7b1384dff7374d124b1cfbb0ee864dcc9f6a2c0380638cf84/numpy-2.5.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:489780423903667933b4ed6197b6ec3b75ea5dd17d1d8f0f38d798feb6921561", size = 16789987, upload-time = "2026-06-21T20:56:16.657Z" }, + { url = "https://files.pythonhosted.org/packages/55/b2/285f48640a181947b4587a3766d21ec1eaa7fea833d4b49957e09da467a2/numpy-2.5.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ece55976ced6bca95a03ae2839e2e5ccffe8eb6a3e7022415645eb154a81e4e6", size = 11760322, upload-time = "2026-06-21T20:56:19.813Z" }, + { url = "https://files.pythonhosted.org/packages/dd/67/b032db1eb03ca30d16eda3b0c22aaa615338b9263c2fd559d0f29451aca4/numpy-2.5.0-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:c83b664b0e6eee9594fa920cf0639d8af796606d3fad6cc70180c87e4b97c7be", size = 5319605, upload-time = "2026-06-21T20:56:22.173Z" }, + { url = "https://files.pythonhosted.org/packages/b9/83/03fc7300c7c6b6c84c487b1dc80d322817b95fbd1f4dd57a85e23b7198de/numpy-2.5.0-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:bf80333980bf37f523341ddd72c783f39d6829ec7736b9eb99086388a2d52cc2", size = 6653628, upload-time = "2026-06-21T20:56:23.914Z" }, + { url = "https://files.pythonhosted.org/packages/82/49/2ec21730bc63ccfda829323f7040a8ed4715b3852ce658689cf74ee96a8c/numpy-2.5.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a1a4874217b36d5ac8fc876f52e39df56f8182c88463e9e2dceabf7ca8b7efb8", size = 15153691, upload-time = "2026-06-21T20:56:25.631Z" }, + { url = "https://files.pythonhosted.org/packages/bb/6b/f4a3d0637692c49da8ef99d72d52526f92e0a8d6ac4f0ca9f31441b9d9ea/numpy-2.5.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:aaa760137137e8d3c920d27927748215b56014f92667dc9b6c27dfc61249255a", size = 16660066, upload-time = "2026-06-21T20:56:28.009Z" }, + { url = "https://files.pythonhosted.org/packages/3a/2f/c354ec86d1f3f5c19649463b0d39652e160736e5b0a4cd18dff0576715c4/numpy-2.5.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7174ce8265fc7f7417d171c9ea8fe905220748893ea67a2a7abe726ec331c4b0", size = 16514638, upload-time = "2026-06-21T20:56:30.26Z" }, + { url = "https://files.pythonhosted.org/packages/06/34/43efdcb319988648580f93c11f1ae82cf7e2faa74925e98e454ae3aa95f8/numpy-2.5.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b8c3daaf99de52415d20b42f8e8155c78642cb04207d02f9d317a0dcf1b3fb54", size = 18419647, upload-time = "2026-06-21T20:56:32.41Z" }, + { url = "https://files.pythonhosted.org/packages/71/e2/f5d1676b1d7fb682eb5e9a1641e7ebd2414b3216c370661d1029778908b4/numpy-2.5.0-cp312-cp312-win32.whl", hash = "sha256:6206db0af545d73d068add6d992279145f158428d1da6cc49adc4b630c5d6ee5", size = 6056688, upload-time = "2026-06-21T20:56:34.657Z" }, + { url = "https://files.pythonhosted.org/packages/8f/7c/48f115d1c58a34032facebcd51fdf2d02df2c51d4a46a81dd1197bb2ea6b/numpy-2.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:6f2d6873e2940c860a309d21e25b1e69af6aaffdd80aa056b04c16380db1c4f2", size = 12419237, upload-time = "2026-06-21T20:56:36.24Z" }, + { url = "https://files.pythonhosted.org/packages/86/26/2e0882f4044d1b1a1b63e875151fb2393389032022a8b7f5657a7996d3b2/numpy-2.5.0-cp312-cp312-win_arm64.whl", hash = "sha256:a55e1eb2bca2cfd17a16b213c99dfc8502d47b0d494224d2122277d0400935ca", size = 10339912, upload-time = "2026-06-21T20:56:38.733Z" }, + { url = "https://files.pythonhosted.org/packages/8a/33/07675aaad7f26ea013d5e884d9a0d784b79c6bd7566c333f5a52fa3c610b/numpy-2.5.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:520e6b8be0a4b65840ac8090d4f51cef4bed66e2b0894d5a520f099adc24a9b2", size = 16784890, upload-time = "2026-06-21T20:56:40.799Z" }, + { url = "https://files.pythonhosted.org/packages/85/4b/953118a730ee3b35e28645e0eb4cf9beec5bdbb954e1ac2f5fcefba6bbc3/numpy-2.5.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:146b81cdd3967fdb6beca8ba25f00c58741d8f3cbd797f55af0fbe0bfec3469c", size = 11754584, upload-time = "2026-06-21T20:56:43.094Z" }, + { url = "https://files.pythonhosted.org/packages/44/9b/56dd530c367c74ae17411027cea4135ca57e1e0583bf5594cee18bd83217/numpy-2.5.0-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:126b88d95e8ff9b00c9e717aa540469f21d6180162f84c0caec51b16215d49cd", size = 5313904, upload-time = "2026-06-21T20:56:45.503Z" }, + { url = "https://files.pythonhosted.org/packages/ce/b0/bcd672edad27ecca7da1f7bb0ce72cd1706a4f2d79ae94990afc97c13e1c/numpy-2.5.0-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:d4313cef1594c5ce46c31b6e54e918338f63f16ee9322304e8c9114d6d81c8bd", size = 6648504, upload-time = "2026-06-21T20:56:47.567Z" }, + { url = "https://files.pythonhosted.org/packages/80/9e/15cdfcbd30a1544a46c9e487a00df331c4672450216538705a9e51fa6710/numpy-2.5.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:750fb097caf26fa878746d9d119f6f9da12dedcbff1eea966c3e3447647c4a9e", size = 15150086, upload-time = "2026-06-21T20:56:49.352Z" }, + { url = "https://files.pythonhosted.org/packages/32/4e/8d7656ccaab3e81e97258b8a9bc5f0c8502513a92fb4ceb0a2cbfebc17bf/numpy-2.5.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3893adc2dc7c0412ba76777db55a049215d99c9aa3113003be8f49f4f1290ab9", size = 16647250, upload-time = "2026-06-21T20:56:51.542Z" }, + { url = "https://files.pythonhosted.org/packages/3c/81/97060281b602ed07f21b12f4ec409eac1f75a2f91fbc829ed8b2becf3ad4/numpy-2.5.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:835e454dd99b238cdc5a3f63bce2371296f5ebc53ca1e0f8e6ddbb6d92a29aab", size = 16512864, upload-time = "2026-06-21T20:56:55.401Z" }, + { url = "https://files.pythonhosted.org/packages/33/ab/4496208146911f8d8ddb54f68a972aafa6c8d44babcb2ea03b0e5cc87c9d/numpy-2.5.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6f9836778081a0a3c02a6a21493f3e9f5b311f8d2541934f31f05583dc999ea4", size = 18408407, upload-time = "2026-06-21T20:56:57.75Z" }, + { url = "https://files.pythonhosted.org/packages/d4/9f/a4df67c181e4ee8b467aa3332dc2db10fd5c515136831302f3ca48bc0a01/numpy-2.5.0-cp313-cp313-win32.whl", hash = "sha256:0b525be4744b60bb0557ac872d53ef07d085b5f39622bc579c98d3809d05b988", size = 6054431, upload-time = "2026-06-21T20:57:00.016Z" }, + { url = "https://files.pythonhosted.org/packages/30/53/491e1c47c55b62ccc6a63c1c5b8635c73fc2258dddeb9bda27cae4a0ae96/numpy-2.5.0-cp313-cp313-win_amd64.whl", hash = "sha256:44353e2878930039db472b99dc353d749826e4010bd4d2a7f835e94a97a5c748", size = 12414420, upload-time = "2026-06-21T20:57:01.815Z" }, + { url = "https://files.pythonhosted.org/packages/eb/4a/25c2906f541e9d9f4c5769764db732e6627be91a13f4724fa10634d77db4/numpy-2.5.0-cp313-cp313-win_arm64.whl", hash = "sha256:48f54b00711f83a5f796b70c518e8c2b3c5848dda03a54911f23eb68519b9b60", size = 10339533, upload-time = "2026-06-21T20:57:03.961Z" }, + { url = "https://files.pythonhosted.org/packages/86/ad/abc44aaceaf7b17ee1edde2bbb4458da591bc79574cffff50c4bb35f00d1/numpy-2.5.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:f27582c55ba4c750b7c58c8faf021d2cd9324a662b466229db8a417b41368af9", size = 16783807, upload-time = "2026-06-21T20:57:06.253Z" }, + { url = "https://files.pythonhosted.org/packages/5d/39/b72e168daf9c00fb20c9fc996d00437ccecdef3102387775d29d7a62576d/numpy-2.5.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:28e7137057d551e4a83c4ae414e3451f50568409db7569aacc7f9811ee06a446", size = 11765215, upload-time = "2026-06-21T20:57:08.547Z" }, + { url = "https://files.pythonhosted.org/packages/f7/a0/8400a9c0e3625182347593f5e1f57da9a617a534794805c8df5518154ddc/numpy-2.5.0-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:e1da54b53e75cd9fcfc23efcc7edab2c6aecf97b6037566d8a0fe804af8ec57c", size = 5324493, upload-time = "2026-06-21T20:57:11.012Z" }, + { url = "https://files.pythonhosted.org/packages/f6/8c/0d104deaa0401c93395a629ec902891618a2eff76d19229139cb5a887bfc/numpy-2.5.0-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:694d8f74e156f7fd01179f1aa8faa2f648ab6ae0f70b6c3fe57a03249aea2303", size = 6645211, upload-time = "2026-06-21T20:57:12.919Z" }, + { url = "https://files.pythonhosted.org/packages/6a/d9/4a4a628c812750363786afc3d33492709a5cd64b215469c16b0f6c7bb811/numpy-2.5.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1a7569a7b53c77716f036bb28cb1c91f166a26ec7d9502cd1e4bdfe502fdec22", size = 15166004, upload-time = "2026-06-21T20:57:14.717Z" }, + { url = "https://files.pythonhosted.org/packages/a0/5e/2a902317d7fc4aa93236e80c932662dadfc459b323d758329e01775125e1/numpy-2.5.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:39a0433bd4086ebd462960cf375e19195bb07b53dc1d87dd5fcf47ad78576f03", size = 16650797, upload-time = "2026-06-21T20:57:16.906Z" }, + { url = "https://files.pythonhosted.org/packages/e9/a0/a0090e6329f4ca5992c07847bb579c5259a19953dc57255bb08793142ffb/numpy-2.5.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:929f0c79ac38bcbd7154fe631dc907abfeddbcc5027a896bd1f7767323271e7a", size = 16524647, upload-time = "2026-06-21T20:57:19.165Z" }, + { url = "https://files.pythonhosted.org/packages/5e/7d/6caf27734c42b65837e7461ed0dbbd6b6fc835060c9714ec59d673bb383a/numpy-2.5.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:cc4f247a47bbf070bfd70be53ccdcf47b800af563535e7bbe172322197c30e21", size = 18411841, upload-time = "2026-06-21T20:57:21.638Z" }, + { url = "https://files.pythonhosted.org/packages/13/dc/26edadbd812536769a82c2e9e002234e33feb5da43061d47a044f6d309b7/numpy-2.5.0-cp314-cp314-win32.whl", hash = "sha256:5dc71423499fab3f46f7a7201155ade1669ea101f2f429d332df9e72f8161731", size = 6106361, upload-time = "2026-06-21T20:57:23.844Z" }, + { url = "https://files.pythonhosted.org/packages/f2/9e/4dd1459282229a72d92dece2ae9138e5cac94a72263a7ceb48f37434c925/numpy-2.5.0-cp314-cp314-win_amd64.whl", hash = "sha256:ebb81d9d5443e0309d6c54894c3fbed74ad7da0714352a67b6d773cd189eae73", size = 12551749, upload-time = "2026-06-21T20:57:25.945Z" }, + { url = "https://files.pythonhosted.org/packages/05/a7/6bc6384c080b86c7f6c85c5bc5b540b24f4f679cd144791d99574e90d462/numpy-2.5.0-cp314-cp314-win_arm64.whl", hash = "sha256:3b94d0d0deceebfad3e67ae5c0e5eb87371e8f7a0581cd04a779928c2450cf1e", size = 10617072, upload-time = "2026-06-21T20:57:28.175Z" }, + { url = "https://files.pythonhosted.org/packages/86/6b/4a2b71d66ada5608ae02b63f150dfad520f6940721cb7f029ad270befc0e/numpy-2.5.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:22f3d43e362d650bc39db1f17851302874a148ca95ba6981c1dfb5fa6862f35b", size = 11881067, upload-time = "2026-06-21T20:57:30.104Z" }, + { url = "https://files.pythonhosted.org/packages/dc/b2/d365eb40a20efb49d67e9feb90494ed8511282ee1f5fa16006675c65397d/numpy-2.5.0-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:243563efb4cd7528a264567e9fd206c87826457322521d06206a00bfa316c927", size = 5440290, upload-time = "2026-06-21T20:57:32.193Z" }, + { url = "https://files.pythonhosted.org/packages/fa/5e/e9c03188de5f9b767e46a8fe988bcfd3efad066a4a3fda8b9cb11a93f895/numpy-2.5.0-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:84881d825ca75249b189bbee875fcfe3238aa5c479e6100893cda566e8e86826", size = 6748371, upload-time = "2026-06-21T20:57:33.933Z" }, + { url = "https://files.pythonhosted.org/packages/fd/1d/68c186a38a5027bae2c4ddd5ea681fdaf8b4d30fb7301def6d8ad270390f/numpy-2.5.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cda12aa4779d42b8771180aba759c96f527d43446d8f380ab59e2b35e8489efd", size = 15214643, upload-time = "2026-06-21T20:57:35.677Z" }, + { url = "https://files.pythonhosted.org/packages/8c/67/73f67b7c7e20635baae9c4c3ead4ae7326a005900297a6110971abd62eb5/numpy-2.5.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1c0121101093d2bd74981b10f8837d78e794a8ff57834eb27179f49e1ba11ac6", size = 16690128, upload-time = "2026-06-21T20:57:38.159Z" }, + { url = "https://files.pythonhosted.org/packages/eb/05/d4c1fb0c46d02a27d6b2b8b319a78c90937acec8631c1641874670b31e6f/numpy-2.5.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:d371c92cfa09da00022f501ab67fafaea813d752eb30ac44336d45b1e5b0268a", size = 16577902, upload-time = "2026-06-21T20:57:40.447Z" }, + { url = "https://files.pythonhosted.org/packages/9e/1d/771c797d50fa26e4888989cccf1d50ee51f530d4e455ad2692dcb64fa711/numpy-2.5.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:9990713e9c38154c6861e7547f1e3fc7a87e75ff09bab24ef1cc81d81c2835e9", size = 18452814, upload-time = "2026-06-21T20:57:42.875Z" }, + { url = "https://files.pythonhosted.org/packages/e8/46/52fc0d2a68d7643f0f149eeea5a5d8ea2a3507056ac8afa83c9212606e8b/numpy-2.5.0-cp314-cp314t-win32.whl", hash = "sha256:edadfbd4794b1086c0d822f81863e8a68fc129d132fd0bb9e31e955d7fbbbdb7", size = 6253168, upload-time = "2026-06-21T20:57:45.101Z" }, + { url = "https://files.pythonhosted.org/packages/2a/be/6c8d1118b5f13b2881dc095d5b345de19c6638b8959c17409b6eff84c8aa/numpy-2.5.0-cp314-cp314t-win_amd64.whl", hash = "sha256:f7e5fa4382967ae6548bd2f174219afb908e294b0d5f625af01166edd5f7d9aa", size = 12736286, upload-time = "2026-06-21T20:57:46.935Z" }, + { url = "https://files.pythonhosted.org/packages/fd/6a/d3a169aaf8536cf228d56a09e04bcb713a2fe4410d4e2105b9419b5a9c89/numpy-2.5.0-cp314-cp314t-win_arm64.whl", hash = "sha256:016623417bb330d719d579daf2d6b9a01ddc52e41a9ed61a47f39fde46dcd865", size = 10686451, upload-time = "2026-06-21T20:57:49.313Z" }, +] + +[[package]] +name = "nvidia-cublas" +version = "13.1.1.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "nvidia-cuda-nvrtc", marker = "sys_platform != 'win32'" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/a7/a1/0bd24ee8c8d03adac032fd2909426a00c88f8c57961b1277ded97f91119f/nvidia_cublas-13.1.1.3-py3-none-manylinux_2_27_aarch64.whl", hash = "sha256:b7a210458267ac818974c53038fbec2e969d5c99f305ab15c72522fa9f001dd5", size = 542848918, upload-time = "2026-04-08T18:46:22.985Z" }, + { url = "https://files.pythonhosted.org/packages/3b/cd/154ca20c38269e05eff77c1464e6c1da89f50a6390b565e9d82e06bc11e1/nvidia_cublas-13.1.1.3-py3-none-manylinux_2_27_x86_64.whl", hash = "sha256:37936a16db8fe4ac1f065c2139360608a543a09275cb1a1af612e08cfa065436", size = 423138758, upload-time = "2026-04-08T18:46:58.655Z" }, +] + +[[package]] +name = "nvidia-cuda-cupti" +version = "13.0.85" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2a/2a/80353b103fc20ce05ef51e928daed4b6015db4aaa9162ed0997090fe2250/nvidia_cuda_cupti-13.0.85-py3-none-manylinux_2_25_aarch64.whl", hash = "sha256:796bd679890ee55fb14a94629b698b6db54bcfd833d391d5e94017dd9d7d3151", size = 10310827, upload-time = "2025-09-04T08:26:42.012Z" }, + { url = "https://files.pythonhosted.org/packages/33/6d/737d164b4837a9bbd202f5ae3078975f0525a55730fe871d8ed4e3b952b0/nvidia_cuda_cupti-13.0.85-py3-none-manylinux_2_25_x86_64.whl", hash = "sha256:4eb01c08e859bf924d222250d2e8f8b8ff6d3db4721288cf35d14252a4d933c8", size = 10715597, upload-time = "2025-09-04T08:26:51.312Z" }, +] + +[[package]] +name = "nvidia-cuda-nvrtc" +version = "13.0.88" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c3/68/483a78f5e8f31b08fb1bb671559968c0ca3a065ac7acabfc7cee55214fd6/nvidia_cuda_nvrtc-13.0.88-py3-none-manylinux2010_x86_64.manylinux_2_12_x86_64.whl", hash = "sha256:ad9b6d2ead2435f11cbb6868809d2adeeee302e9bb94bcf0539c7a40d80e8575", size = 90215200, upload-time = "2025-09-04T08:28:44.204Z" }, + { url = "https://files.pythonhosted.org/packages/b7/dc/6bb80850e0b7edd6588d560758f17e0550893a1feaf436807d64d2da040f/nvidia_cuda_nvrtc-13.0.88-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d27f20a0ca67a4bb34268a5e951033496c5b74870b868bacd046b1b8e0c3267b", size = 43015449, upload-time = "2025-09-04T08:28:20.239Z" }, +] + +[[package]] +name = "nvidia-cuda-runtime" +version = "13.0.96" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/87/4f/17d7b9b8e285199c58ce28e31b5c5bbaa4d8271af06a89b6405258245de2/nvidia_cuda_runtime-13.0.96-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ef9bcbe90493a2b9d810e43d249adb3d02e98dd30200d86607d8d02687c43f55", size = 2261060, upload-time = "2025-10-09T08:55:15.78Z" }, + { url = "https://files.pythonhosted.org/packages/2e/24/d1558f3b68b1d26e706813b1d10aa1d785e4698c425af8db8edc3dced472/nvidia_cuda_runtime-13.0.96-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7f82250d7782aa23b6cfe765ecc7db554bd3c2870c43f3d1821f1d18aebf0548", size = 2243632, upload-time = "2025-10-09T08:55:36.117Z" }, +] + +[[package]] +name = "nvidia-cudnn-cu13" +version = "9.20.0.48" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "nvidia-cublas", marker = "sys_platform != 'win32'" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/56/c5/83384d846b2fd17c44bd499b36c75a45ed4f095fbbb2252294e89cea5c5c/nvidia_cudnn_cu13-9.20.0.48-py3-none-manylinux_2_27_aarch64.whl", hash = "sha256:e31454ae00094b0c55319d9d15b6fa2fc50a9e1c0f5c8c80fb75258234e731e1", size = 444574296, upload-time = "2026-03-09T19:28:27.751Z" }, + { url = "https://files.pythonhosted.org/packages/6e/5e/edb9c0ae051602c3ccaffe424256463636d639e27d7f302dde9975ef9e7a/nvidia_cudnn_cu13-9.20.0.48-py3-none-manylinux_2_27_x86_64.whl", hash = "sha256:0c45dd8eeb50b603f07995b1b300c62ffe6a1980482b82b3bcf94a4ca9d49304", size = 366173588, upload-time = "2026-03-09T19:29:34.474Z" }, +] + +[[package]] +name = "nvidia-cufft" +version = "12.0.0.61" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "nvidia-nvjitlink", marker = "sys_platform != 'win32'" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/8b/ae/f417a75c0259e85c1d2f83ca4e960289a5f814ed0cea74d18c353d3e989d/nvidia_cufft-12.0.0.61-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:2708c852ef8cd89d1d2068bdbece0aa188813a0c934db3779b9b1faa8442e5f5", size = 214053554, upload-time = "2025-09-04T08:31:38.196Z" }, + { url = "https://files.pythonhosted.org/packages/a8/2f/7b57e29836ea8714f81e9898409196f47d772d5ddedddf1592eadb8ab743/nvidia_cufft-12.0.0.61-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:6c44f692dce8fd5ffd3e3df134b6cdb9c2f72d99cf40b62c32dde45eea9ddad3", size = 214085489, upload-time = "2025-09-04T08:31:56.044Z" }, +] + +[[package]] +name = "nvidia-cufile" +version = "1.15.1.6" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3f/70/4f193de89a48b71714e74602ee14d04e4019ad36a5a9f20c425776e72cd6/nvidia_cufile-1.15.1.6-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:08a3ecefae5a01c7f5117351c64f17c7c62efa5fffdbe24fc7d298da19cd0b44", size = 1223672, upload-time = "2025-09-04T08:32:22.779Z" }, + { url = "https://files.pythonhosted.org/packages/ab/73/cc4a14c9813a8a0d509417cf5f4bdaba76e924d58beb9864f5a7baceefbf/nvidia_cufile-1.15.1.6-py3-none-manylinux_2_27_aarch64.whl", hash = "sha256:bdc0deedc61f548bddf7733bdc216456c2fdb101d020e1ab4b88d232d5e2f6d1", size = 1136992, upload-time = "2025-09-04T08:32:14.119Z" }, +] + +[[package]] +name = "nvidia-curand" +version = "10.4.0.35" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1e/72/7c2ae24fb6b63a32e6ae5d241cc65263ea18d08802aaae087d9f013335a2/nvidia_curand-10.4.0.35-py3-none-manylinux_2_27_aarch64.whl", hash = "sha256:133df5a7509c3e292aaa2b477afd0194f06ce4ea24d714d616ff36439cee349a", size = 61962106, upload-time = "2025-08-04T10:21:41.128Z" }, + { url = "https://files.pythonhosted.org/packages/a5/9f/be0a41ca4a4917abf5cb9ae0daff1a6060cc5de950aec0396de9f3b52bc5/nvidia_curand-10.4.0.35-py3-none-manylinux_2_27_x86_64.whl", hash = "sha256:1aee33a5da6e1db083fe2b90082def8915f30f3248d5896bcec36a579d941bfc", size = 59544258, upload-time = "2025-08-04T10:22:03.992Z" }, +] + +[[package]] +name = "nvidia-cusolver" +version = "12.0.4.66" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "nvidia-cublas", marker = "sys_platform != 'win32'" }, + { name = "nvidia-cusparse", marker = "sys_platform != 'win32'" }, + { name = "nvidia-nvjitlink", marker = "sys_platform != 'win32'" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/c8/c3/b30c9e935fc01e3da443ec0116ed1b2a009bb867f5324d3f2d7e533e776b/nvidia_cusolver-12.0.4.66-py3-none-manylinux_2_27_aarch64.whl", hash = "sha256:02c2457eaa9e39de20f880f4bd8820e6a1cfb9f9a34f820eb12a155aa5bc92d2", size = 223467760, upload-time = "2025-09-04T08:33:04.222Z" }, + { url = "https://files.pythonhosted.org/packages/5f/67/cba3777620cdacb99102da4042883709c41c709f4b6323c10781a9c3aa34/nvidia_cusolver-12.0.4.66-py3-none-manylinux_2_27_x86_64.whl", hash = "sha256:0a759da5dea5c0ea10fd307de75cdeb59e7ea4fcb8add0924859b944babf1112", size = 200941980, upload-time = "2025-09-04T08:33:22.767Z" }, +] + +[[package]] +name = "nvidia-cusparse" +version = "12.6.3.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "nvidia-nvjitlink", marker = "sys_platform != 'win32'" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/f8/94/5c26f33738ae35276672f12615a64bd008ed5be6d1ebcb23579285d960a9/nvidia_cusparse-12.6.3.3-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:80bcc4662f23f1054ee334a15c72b8940402975e0eab63178fc7e670aa59472c", size = 162155568, upload-time = "2025-09-04T08:33:42.864Z" }, + { url = "https://files.pythonhosted.org/packages/fa/18/623c77619c31d62efd55302939756966f3ecc8d724a14dab2b75f1508850/nvidia_cusparse-12.6.3.3-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:2b3c89c88d01ee0e477cb7f82ef60a11a4bcd57b6b87c33f789350b59759360b", size = 145942937, upload-time = "2025-09-04T08:33:58.029Z" }, +] + +[[package]] +name = "nvidia-cusparselt-cu13" +version = "0.8.1" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/46/e1/cdc1797eadf82d3a9a575a19b33fdc871a97edbec42c00b5b5e914f4aff4/nvidia_cusparselt_cu13-0.8.1-py3-none-manylinux2014_aarch64.whl", hash = "sha256:4dca476c50bf4780d46cd0bfbd82e2bc10a08e4fef7950917ce8d7578d22a23f", size = 221051344, upload-time = "2025-09-05T18:49:51.289Z" }, + { url = "https://files.pythonhosted.org/packages/34/7d/2661f2fb3ac4302f3a246f5fc030213ac60c1fe0bce84f9783dbd831dbb7/nvidia_cusparselt_cu13-0.8.1-py3-none-manylinux2014_x86_64.whl", hash = "sha256:786ce87568c303fadb5afcc7102d454cd3040d75f6f8626f5db460d1871f4dd0", size = 170148586, upload-time = "2025-09-05T18:50:50.248Z" }, +] + +[[package]] +name = "nvidia-nccl-cu13" +version = "2.29.7" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/72/0d/daf50d44177ee0cbc7ff0a0c91eb5ff676c82be42f9a970bc7597f440c3a/nvidia_nccl_cu13-2.29.7-py3-none-manylinux_2_18_aarch64.whl", hash = "sha256:674a12383e3c38a1bcccae7d4f3633b37852230b6047883cb2f4c2d1b36d9bf5", size = 206014712, upload-time = "2026-03-03T05:34:20.843Z" }, + { url = "https://files.pythonhosted.org/packages/67/f4/58e4e91b6919367c7aafb8e36fce9aad1a3047e536bf7e2fd560927d3a4c/nvidia_nccl_cu13-2.29.7-py3-none-manylinux_2_18_x86_64.whl", hash = "sha256:edd81538446786ec3b73972543e53bb43bcaf0bfc8ef76cb679fcc390ffe136d", size = 205976000, upload-time = "2026-03-03T05:36:24.472Z" }, +] + +[[package]] +name = "nvidia-nvjitlink" +version = "13.0.88" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/56/7a/123e033aaff487c77107195fa5a2b8686795ca537935a24efae476c41f05/nvidia_nvjitlink-13.0.88-py3-none-manylinux2010_x86_64.manylinux_2_12_x86_64.whl", hash = "sha256:13a74f429e23b921c1109976abefacc69835f2f433ebd323d3946e11d804e47b", size = 40713933, upload-time = "2025-09-04T08:35:43.553Z" }, + { url = "https://files.pythonhosted.org/packages/ab/2c/93c5250e64df4f894f1cbb397c6fd71f79813f9fd79d7cd61de3f97b3c2d/nvidia_nvjitlink-13.0.88-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:e931536ccc7d467a98ba1d8b89ff7fa7f1fa3b13f2b0069118cd7f47bff07d0c", size = 38768748, upload-time = "2025-09-04T08:35:20.008Z" }, +] + +[[package]] +name = "nvidia-nvshmem-cu13" +version = "3.4.5" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/dc/0f/05cc9c720236dcd2db9c1ab97fff629e96821be2e63103569da0c9b72f19/nvidia_nvshmem_cu13-3.4.5-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:6dc2a197f38e5d0376ad52cd1a2a3617d3cdc150fd5966f4aee9bcebb1d68fe9", size = 60215947, upload-time = "2025-09-06T00:32:20.022Z" }, + { url = "https://files.pythonhosted.org/packages/3c/35/a9bf80a609e74e3b000fef598933235c908fcefcef9026042b8e6dfde2a9/nvidia_nvshmem_cu13-3.4.5-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:290f0a2ee94c9f3687a02502f3b9299a9f9fe826e6d0287ee18482e78d495b80", size = 60412546, upload-time = "2025-09-06T00:32:41.564Z" }, +] + +[[package]] +name = "nvidia-nvtx" +version = "13.0.85" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c2/f3/d86c845465a2723ad7e1e5c36dcd75ddb82898b3f53be47ebd429fb2fa5d/nvidia_nvtx-13.0.85-py3-none-manylinux1_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:4936d1d6780fbe68db454f5e72a42ff64d1fd6397df9f363ae786930fd5c1cd4", size = 148047, upload-time = "2025-09-04T08:29:01.761Z" }, + { url = "https://files.pythonhosted.org/packages/a8/64/3708a90d1ebe202ffdeb7185f878a3c84d15c2b2c31858da2ce0583e2def/nvidia_nvtx-13.0.85-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:cb7780edb6b14107373c835bf8b72e7a178bac7367e23da7acb108f973f157a6", size = 148878, upload-time = "2025-09-04T08:28:53.627Z" }, +] + +[[package]] +name = "openai" +version = "2.44.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "distro" }, + { name = "httpx" }, + { name = "jiter" }, + { name = "pydantic" }, + { name = "sniffio" }, + { name = "tqdm" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/49/f5/7c7cb955305cb41f7f3c5fd7e0e38bf6bbf2658468863d4b7b868a5cb8df/openai-2.44.0.tar.gz", hash = "sha256:68a5a5ffad82b8ff7d451c437529fb64f7c3b8123aaf0c021966a882d9e3947d", size = 988753, upload-time = "2026-06-24T20:56:02.293Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ae/f4/561ed79fd94876160018a5e75254cfcb9b0e62d4dded9dcb20072e86d623/openai-2.44.0-py3-none-any.whl", hash = "sha256:0a2a3ab2e29aeda368700f662ff9ba0f9df17ba4c54577a64e08b8115a3cc0ad", size = 1366216, upload-time = "2026-06-24T20:55:58.882Z" }, +] + +[[package]] +name = "packageurl-python" +version = "0.17.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f5/d6/3b5a4e3cfaef7a53869a26ceb034d1ff5e5c27c814ce77260a96d50ab7bb/packageurl_python-0.17.6.tar.gz", hash = "sha256:1252ce3a102372ca6f86eb968e16f9014c4ba511c5c37d95a7f023e2ca6e5c25", size = 50618, upload-time = "2025-11-24T15:20:17.998Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b1/2f/c7277b7615a93f51b5fbc1eacfc1b75e8103370e786fd8ce2abf6e5c04ab/packageurl_python-0.17.6-py3-none-any.whl", hash = "sha256:31a85c2717bc41dd818f3c62908685ff9eebcb68588213745b14a6ee9e7df7c9", size = 36776, upload-time = "2025-11-24T15:20:16.962Z" }, +] + +[[package]] +name = "packaging" +version = "26.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d7/f1/e7a6dd94a8d4a5626c03e4e99c87f241ba9e350cd9e6d75123f992427270/packaging-26.2.tar.gz", hash = "sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661", size = 228134, upload-time = "2026-04-24T20:15:23.917Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/df/b2/87e62e8c3e2f4b32e5fe99e0b86d576da1312593b39f47d8ceef365e95ed/packaging-26.2-py3-none-any.whl", hash = "sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e", size = 100195, upload-time = "2026-04-24T20:15:22.081Z" }, +] + +[[package]] +name = "pandas" +version = "3.0.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12'" }, + { name = "numpy", version = "2.5.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12'" }, + { name = "python-dateutil" }, + { name = "tzdata", marker = "sys_platform == 'emscripten' or sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5a/fd/e0194474c71dbfba82e744f66945c274f15b667acd5f8c117b12555fb91e/pandas-3.0.4.tar.gz", hash = "sha256:62f6062586d159663825f06e70ef49cd1572d45824cb63a9559f3ffd1d0d2a20", size = 4658146, upload-time = "2026-06-28T15:31:51.3Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d3/be/f23b2369adf0fd241820778e3d534e940cf052e6cd325fee9b508726d26e/pandas-3.0.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:87d6be6820c5c2b3c41d30f2c8387aac10e842af7d43dd9c3c22f2ce0a4c4176", size = 10409998, upload-time = "2026-06-28T15:29:45.196Z" }, + { url = "https://files.pythonhosted.org/packages/79/c0/902b30ae918f5482016f6151f7e4621b71f43200f4b20f7a7fa162c74130/pandas-3.0.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dce7eca7e5adc4cc79bc28435e6111474772c14c11f4a742ea0041e23fff7d73", size = 10041669, upload-time = "2026-06-28T15:29:49.492Z" }, + { url = "https://files.pythonhosted.org/packages/58/54/2b287f9edfcbeecfd5ae9372827738f47f84130c4be73c9069c04e29bf1a/pandas-3.0.4-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:14d274e00885373c879042dd3bd3dd27bfea6edef993f23644ed8a20468a7471", size = 10598978, upload-time = "2026-06-28T15:29:52.113Z" }, + { url = "https://files.pythonhosted.org/packages/0c/36/94e1bf5c6b3a635b7d8dc496af11840489322522a53e842477fdbcd8b08a/pandas-3.0.4-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c423500b3f0118c2d02b5a76ade4c57f3a13b9c9cecf04599bf983ba247cebaa", size = 11119683, upload-time = "2026-06-28T15:29:54.912Z" }, + { url = "https://files.pythonhosted.org/packages/1a/89/d8c41d1807a09c51170e2666c956e07d881eaaac1ecdc942d6f8662a9d1e/pandas-3.0.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:aaa9760a86a77a2586807a72f64748b312b95c37135ae9932cd65fe859507377", size = 11612249, upload-time = "2026-06-28T15:29:58.235Z" }, + { url = "https://files.pythonhosted.org/packages/64/fc/e62c97b2234c89bd541ff3cc19a019c4399ca5d0af35c6a35a6bf5b41a3a/pandas-3.0.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e9c0eb4036cbf4110af16c5593191c51c1803752c7645f8f74b3a922a1027f42", size = 12170521, upload-time = "2026-06-28T15:30:01.695Z" }, + { url = "https://files.pythonhosted.org/packages/ec/b8/f5f6caf9a6c643296a92e88922c53e9932101e00403517c45ca3704b47ab/pandas-3.0.4-cp311-cp311-win_amd64.whl", hash = "sha256:a79a6401beed48057b9101d7e722d3d0af80e570b578438da6c7de4a10cc3a29", size = 9868871, upload-time = "2026-06-28T15:30:04.754Z" }, + { url = "https://files.pythonhosted.org/packages/b8/f8/22d6f9575a918c0a5c2c57414fd4ff07765b8bce1bce34bb7b6a886c6d86/pandas-3.0.4-cp311-cp311-win_arm64.whl", hash = "sha256:dc827bff97d448ced1a8d9b4055486cadd97b6ac52c3eb3e1dd154f49d869be1", size = 9117450, upload-time = "2026-06-28T15:30:08.982Z" }, + { url = "https://files.pythonhosted.org/packages/69/7d/37fce6b1f4537218af19ab71ca2814e0794c4a1d4e412026afdc1988b5cb/pandas-3.0.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:0f22242de864ca997028520e28b5dcdd440443ad239395bdabcb6124ed009067", size = 10422311, upload-time = "2026-06-28T15:30:12.192Z" }, + { url = "https://files.pythonhosted.org/packages/1b/ce/3b280464d1c6faba9080435cd54f23c244ea79228f3508913f58753235dc/pandas-3.0.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2bef5bf689a9f0d21ca83436f74c061ba52f426a689d2f8028e2e3d9ac0a8d05", size = 10061739, upload-time = "2026-06-28T15:30:15.162Z" }, + { url = "https://files.pythonhosted.org/packages/94/50/927a39cdf93bf541b56390c32a58ae64f70f2748b8f2a88576ce8e4b6d7b/pandas-3.0.4-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b9624cceb273c8f97d16c518f0cbf362d12edbdbb4ed46712eb2def2f7ed7de1", size = 10287537, upload-time = "2026-06-28T15:30:18.181Z" }, + { url = "https://files.pythonhosted.org/packages/bd/63/6898384737b5e32dd72067843bea661661ff32325da91f978347ba563cf2/pandas-3.0.4-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a477e4b7f3d18d63b5131e7a5faea3f2f8d7153f493cb145e552ba52c904ab2e", size = 10793447, upload-time = "2026-06-28T15:30:21.038Z" }, + { url = "https://files.pythonhosted.org/packages/b3/8d/1424ca0d99ea192e84b17d1547463ed7f9cd628c9c395b770aded58a7efc/pandas-3.0.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:fa604623167246500d962d109df5c5b953955afb637f0dd14d9500ab191dbce7", size = 11309351, upload-time = "2026-06-28T15:30:23.987Z" }, + { url = "https://files.pythonhosted.org/packages/c4/f0/4f5aa9df56b378434b056afc22e0a6f4ed2b69006f61e61cd4b4397a87cd/pandas-3.0.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:833232f7a694cb841a2fd8b309ca655e24dcac2ae3e1959efed97d573499b389", size = 11859582, upload-time = "2026-06-28T15:30:27.365Z" }, + { url = "https://files.pythonhosted.org/packages/5a/b0/97c3be4b0bbe82ed31d78d32659637d1ad0f2ad50b524a0851a068734f9c/pandas-3.0.4-cp312-cp312-pyemscripten_2024_0_wasm32.whl", hash = "sha256:25d9ba5ad021e7bd50c674f528e31f15dc22e28c9dfa50bd4cdbdd3a4f5f1902", size = 7115248, upload-time = "2026-06-28T15:30:30.128Z" }, + { url = "https://files.pythonhosted.org/packages/66/93/503f381c106a9e6b4717356cc4805cc68b5af64b97f273590bf294cedd54/pandas-3.0.4-cp312-cp312-win_amd64.whl", hash = "sha256:6b6797a68ccb1391ec7b7873681b23317dd4cfbd45228aadc0b837fdff02170d", size = 9670611, upload-time = "2026-06-28T15:30:32.776Z" }, + { url = "https://files.pythonhosted.org/packages/92/7d/9d7efe0c18d059d9cf0cd0f56f55c6aa584f8c506bcd5776ae097f195eaf/pandas-3.0.4-cp312-cp312-win_arm64.whl", hash = "sha256:b3543e828bbd8d6ebe98b6a4268f57edc6bd945561fd08abfd29021bd5dc23ff", size = 8966047, upload-time = "2026-06-28T15:30:35.665Z" }, + { url = "https://files.pythonhosted.org/packages/dc/df/9febd45b3a643876260a4f53c6c1c7e30894e9e9f7d3a484b97d4ccc61fb/pandas-3.0.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ab8b23bf3ea0fe4337d115389d800896583854694b4c0b2de08e19c81f70140f", size = 10443559, upload-time = "2026-06-28T15:30:38.67Z" }, + { url = "https://files.pythonhosted.org/packages/5f/e2/081b445177716989e6320c49b45c67b0b5ea75d71a327843826e380e1875/pandas-3.0.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bcf15e8c8cbe4d1bb7b9c3f243ddb96123bbeb4585a40bad4c22dd673620a3c0", size = 10073663, upload-time = "2026-06-28T15:30:41.329Z" }, + { url = "https://files.pythonhosted.org/packages/7a/76/60d39cd44c42995cb92cc627138a429533098bb4e9f4268dfef53de24e77/pandas-3.0.4-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d7ddfd571e26846b568d6e08065002046b54ffd4e81c51a61520f3040c677431", size = 10236941, upload-time = "2026-06-28T15:30:44.034Z" }, + { url = "https://files.pythonhosted.org/packages/50/68/7abd718ed1b373e47684bb788dec0b547ed218a41a15e0b04d05b81d1779/pandas-3.0.4-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6afa70bd5a24cedf0c983d888f7d48c3ca1bc5fc095d38a3e6277e85f9bd4ab3", size = 10762008, upload-time = "2026-06-28T15:30:46.904Z" }, + { url = "https://files.pythonhosted.org/packages/fb/0c/99ee1b43b23cbeb69585aebaa08575fa1bf3e8e0c5f3bb27f5148ae7d8bb/pandas-3.0.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ba4acbe620c3888ffc561d278ba5a67f30fa9d2aba92052fbee9c951938110fc", size = 11258245, upload-time = "2026-06-28T15:30:50.438Z" }, + { url = "https://files.pythonhosted.org/packages/23/74/e6dd260c2d65fe8a5eed5b2bd7756f9393ccaefef12ea683fb05b7c15b9c/pandas-3.0.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:26451dd26dcfa2e9f5172cb9c6d8213cebfc9130fc7a1844e11e642ffa458b54", size = 11820489, upload-time = "2026-06-28T15:30:53.539Z" }, + { url = "https://files.pythonhosted.org/packages/fb/e7/8eedac9e7443651a4400d2ec8ebfb4be3be43cc3ec8ac3d5fbdbf7f0e149/pandas-3.0.4-cp313-cp313-win_amd64.whl", hash = "sha256:63468a898ba7b54280fc6db21833cf99b9b62b2b54b5d5d10b5ab813ce100fbf", size = 9650344, upload-time = "2026-06-28T15:30:56.716Z" }, + { url = "https://files.pythonhosted.org/packages/fc/36/5f00ada639c67062720dc813a72d6dcca8eb86bc55620d2bb17dcf284073/pandas-3.0.4-cp313-cp313-win_arm64.whl", hash = "sha256:5f9538b9d13b974a3a7d40c23b8d66f41114ceffe6c586f38efb8ed71d778caa", size = 8958077, upload-time = "2026-06-28T15:30:59.462Z" }, + { url = "https://files.pythonhosted.org/packages/da/9d/b70e2d6fd65f497a03922d0a0019a2b9ec7a40374fbd2f2cb6a697109806/pandas-3.0.4-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:45751e5d456788ca891167c6456fb5e373ad72aa82a949c9635b63e215940181", size = 10515604, upload-time = "2026-06-28T15:31:02.329Z" }, + { url = "https://files.pythonhosted.org/packages/ae/fc/a514a959eeb0a8ad0294747df5ff1c95bf364aa2f2c533d6c2a8c0720bf4/pandas-3.0.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:5c912d80243e4563934f34acc41cfad1a08d7af1b40597492cc6b5e6ba311404", size = 10169825, upload-time = "2026-06-28T15:31:05.34Z" }, + { url = "https://files.pythonhosted.org/packages/72/f8/11da3c5c7a39ab436bda99a1bf2ff5ab3b6addb91155b3fc5d068e733940/pandas-3.0.4-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ccdf354cddecbf0d763ab5a21d0d698440154c5ed6f2c43643c5f528e5c184a7", size = 10384438, upload-time = "2026-06-28T15:31:07.949Z" }, + { url = "https://files.pythonhosted.org/packages/3e/64/01d6352e2f108045e628680f1dd0a11276489beeae580c2c9d8a74df390b/pandas-3.0.4-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cadb8f48ada5de3feaa735577af15f0874cd5498d6875cf17989d97d4bc2e926", size = 10795673, upload-time = "2026-06-28T15:31:11.331Z" }, + { url = "https://files.pythonhosted.org/packages/47/1f/c4319dc17cc88b7a90780ecaad15a484ab8ddee32466093a7ff6fcf8fdb1/pandas-3.0.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:bf867a8fe99499762626adbda73759b0378add0d13a58044ee668ba2d5df92f9", size = 11394840, upload-time = "2026-06-28T15:31:14.223Z" }, + { url = "https://files.pythonhosted.org/packages/ab/c4/5660f3f5bebfee4bcdee8c13212806f326ba9d1dbdf7f408c7766f279faa/pandas-3.0.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:58a0b88e5f6c46974ba110c2cef6b8714aaea57f9f26d55ab5361de662b28165", size = 11877357, upload-time = "2026-06-28T15:31:17.205Z" }, + { url = "https://files.pythonhosted.org/packages/c4/92/a16e08eebab6183817757adf6783f644e2061fa14e5905ced79d362cbf36/pandas-3.0.4-cp314-cp314-win_amd64.whl", hash = "sha256:2a32675e6e7641effa300e58040609107f6e976bb0783b0264556358df64db58", size = 9806280, upload-time = "2026-06-28T15:31:20.496Z" }, + { url = "https://files.pythonhosted.org/packages/6a/ef/7d0810b2ba48fd3b015f82e5f907b2b757f40727d86481a2bea22123e454/pandas-3.0.4-cp314-cp314-win_arm64.whl", hash = "sha256:337be3b93ca7e0db3ec25edc769ebb74a8702427edeb345ee6ebe3e3080c6350", size = 9125456, upload-time = "2026-06-28T15:31:23.426Z" }, + { url = "https://files.pythonhosted.org/packages/78/e6/32800039b35eaa4eeb2da0182dd13d2cc205ce21e13e860c0e855f9f64e8/pandas-3.0.4-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:ca9c1332eb5b69027fa1a73125e5b35fae26aea8c64a716a1924261070b0b859", size = 10938203, upload-time = "2026-06-28T15:31:26.903Z" }, + { url = "https://files.pythonhosted.org/packages/67/16/eff8bc63f22c8e881d31fe25a09542eea3bf8142ccf595974fc76f28a373/pandas-3.0.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a1ae9e815bb61e0a85227aec3db22ba5502a4192df4918c115a772960e6ba606", size = 10586746, upload-time = "2026-06-28T15:31:29.836Z" }, + { url = "https://files.pythonhosted.org/packages/0b/03/6b413ed392ce8d7e90af963123bc62ccb6dd8d889ecf8951b7d1c1dddd86/pandas-3.0.4-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6f482730bc2ec12b53c6205190deb195275495b4871bc1a2036beb91a7c97aee", size = 10240823, upload-time = "2026-06-28T15:31:32.879Z" }, + { url = "https://files.pythonhosted.org/packages/67/26/7992ed1748beb166a68d667e6651a03309f7e08a88a0520a7a381e06e21e/pandas-3.0.4-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5065f02eb94b947ff2610bba2b0c1a74fd67ca10fde0686b12adfc36e61d11d3", size = 10658793, upload-time = "2026-06-28T15:31:36.404Z" }, + { url = "https://files.pythonhosted.org/packages/5d/16/c92b5ea088632476b831200c54de4740531a6777c8f650ab3c3cec5e7bf5/pandas-3.0.4-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:9b1a5e49e5fa13d002e1b237af4ab57f91f535cc6f6ca9225a366b2ce6241d99", size = 11274714, upload-time = "2026-06-28T15:31:39.871Z" }, + { url = "https://files.pythonhosted.org/packages/9c/0c/149cfc617640575a28c878f2d26f20899f4ef206b08a7338a83eb592f297/pandas-3.0.4-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:f660473c1e7a7ea7155214f89047b83ac0db6ebe7fab4d5a463f881307162d8c", size = 11729898, upload-time = "2026-06-28T15:31:42.95Z" }, + { url = "https://files.pythonhosted.org/packages/fb/4a/5f1e5b5784ecd4eab4ad52b2025f3e828c289d49c063eac64b400619bb07/pandas-3.0.4-cp314-cp314t-win_amd64.whl", hash = "sha256:453c9e65d0ea8f1ff00d0d5dd2a2612df9ead3ac1baaf55b81e18a01a7a56846", size = 10201594, upload-time = "2026-06-28T15:31:45.917Z" }, + { url = "https://files.pythonhosted.org/packages/05/f3/40a59a8e1abf01b13be5102ece560dc30bb7e85ed06b3e78442c445cb028/pandas-3.0.4-cp314-cp314t-win_arm64.whl", hash = "sha256:02a8c70e5a304947a802551b8ddb38fe83d9c528395a361609fddcccb7cf8003", size = 9387615, upload-time = "2026-06-28T15:31:48.694Z" }, +] + +[[package]] +name = "pathspec" +version = "1.1.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5a/82/42f767fc1c1143d6fd36efb827202a2d997a375e160a71eb2888a925aac1/pathspec-1.1.1.tar.gz", hash = "sha256:17db5ecd524104a120e173814c90367a96a98d07c45b2e10c2f3919fff91bf5a", size = 135180, upload-time = "2026-04-27T01:46:08.907Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f1/d9/7fb5aa316bc299258e68c73ba3bddbc499654a07f151cba08f6153988714/pathspec-1.1.1-py3-none-any.whl", hash = "sha256:a00ce642f577bf7f473932318056212bc4f8bfdf53128c78bbd5af0b9b20b189", size = 57328, upload-time = "2026-04-27T01:46:07.06Z" }, +] + +[[package]] +name = "pillow" +version = "12.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/8c/21/c2bcdd5906101a30244eaffc1b6e6ce71a31bd0742a01eb89e660ebfac2d/pillow-12.2.0.tar.gz", hash = "sha256:a830b1a40919539d07806aa58e1b114df53ddd43213d9c8b75847eee6c0182b5", size = 46987819, upload-time = "2026-04-01T14:46:17.687Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/68/e1/748f5663efe6edcfc4e74b2b93edfb9b8b99b67f21a854c3ae416500a2d9/pillow-12.2.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:8be29e59487a79f173507c30ddf57e733a357f67881430449bb32614075a40ab", size = 5354347, upload-time = "2026-04-01T14:42:44.255Z" }, + { url = "https://files.pythonhosted.org/packages/47/a1/d5ff69e747374c33a3b53b9f98cca7889fce1fd03d79cdc4e1bccc6c5a87/pillow-12.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:71cde9a1e1551df7d34a25462fc60325e8a11a82cc2e2f54578e5e9a1e153d65", size = 4695873, upload-time = "2026-04-01T14:42:46.452Z" }, + { url = "https://files.pythonhosted.org/packages/df/21/e3fbdf54408a973c7f7f89a23b2cb97a7ef30c61ab4142af31eee6aebc88/pillow-12.2.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f490f9368b6fc026f021db16d7ec2fbf7d89e2edb42e8ec09d2c60505f5729c7", size = 6280168, upload-time = "2026-04-01T14:42:49.228Z" }, + { url = "https://files.pythonhosted.org/packages/d3/f1/00b7278c7dd52b17ad4329153748f87b6756ec195ff786c2bdf12518337d/pillow-12.2.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8bd7903a5f2a4545f6fd5935c90058b89d30045568985a71c79f5fd6edf9b91e", size = 8088188, upload-time = "2026-04-01T14:42:51.735Z" }, + { url = "https://files.pythonhosted.org/packages/ad/cf/220a5994ef1b10e70e85748b75649d77d506499352be135a4989c957b701/pillow-12.2.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3997232e10d2920a68d25191392e3a4487d8183039e1c74c2297f00ed1c50705", size = 6394401, upload-time = "2026-04-01T14:42:54.343Z" }, + { url = "https://files.pythonhosted.org/packages/e9/bd/e51a61b1054f09437acfbc2ff9106c30d1eb76bc1453d428399946781253/pillow-12.2.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e74473c875d78b8e9d5da2a70f7099549f9eb37ded4e2f6a463e60125bccd176", size = 7079655, upload-time = "2026-04-01T14:42:56.954Z" }, + { url = "https://files.pythonhosted.org/packages/6b/3d/45132c57d5fb4b5744567c3817026480ac7fc3ce5d4c47902bc0e7f6f853/pillow-12.2.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:56a3f9c60a13133a98ecff6197af34d7824de9b7b38c3654861a725c970c197b", size = 6503105, upload-time = "2026-04-01T14:42:59.847Z" }, + { url = "https://files.pythonhosted.org/packages/7d/2e/9df2fc1e82097b1df3dce58dc43286aa01068e918c07574711fcc53e6fb4/pillow-12.2.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:90e6f81de50ad6b534cab6e5aef77ff6e37722b2f5d908686f4a5c9eba17a909", size = 7203402, upload-time = "2026-04-01T14:43:02.664Z" }, + { url = "https://files.pythonhosted.org/packages/bd/2e/2941e42858ebb67e50ae741473de81c2984e6eff7b397017623c676e2e8d/pillow-12.2.0-cp311-cp311-win32.whl", hash = "sha256:8c984051042858021a54926eb597d6ee3012393ce9c181814115df4c60b9a808", size = 6378149, upload-time = "2026-04-01T14:43:05.274Z" }, + { url = "https://files.pythonhosted.org/packages/69/42/836b6f3cd7f3e5fa10a1f1a5420447c17966044c8fbf589cc0452d5502db/pillow-12.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:6e6b2a0c538fc200b38ff9eb6628228b77908c319a005815f2dde585a0664b60", size = 7082626, upload-time = "2026-04-01T14:43:08.557Z" }, + { url = "https://files.pythonhosted.org/packages/c2/88/549194b5d6f1f494b485e493edc6693c0a16f4ada488e5bd974ed1f42fad/pillow-12.2.0-cp311-cp311-win_arm64.whl", hash = "sha256:9a8a34cc89c67a65ea7437ce257cea81a9dad65b29805f3ecee8c8fe8ff25ffe", size = 2463531, upload-time = "2026-04-01T14:43:10.743Z" }, + { url = "https://files.pythonhosted.org/packages/58/be/7482c8a5ebebbc6470b3eb791812fff7d5e0216c2be3827b30b8bb6603ed/pillow-12.2.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2d192a155bbcec180f8564f693e6fd9bccff5a7af9b32e2e4bf8c9c69dbad6b5", size = 5308279, upload-time = "2026-04-01T14:43:13.246Z" }, + { url = "https://files.pythonhosted.org/packages/d8/95/0a351b9289c2b5cbde0bacd4a83ebc44023e835490a727b2a3bd60ddc0f4/pillow-12.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f3f40b3c5a968281fd507d519e444c35f0ff171237f4fdde090dd60699458421", size = 4695490, upload-time = "2026-04-01T14:43:15.584Z" }, + { url = "https://files.pythonhosted.org/packages/de/af/4e8e6869cbed569d43c416fad3dc4ecb944cb5d9492defaed89ddd6fe871/pillow-12.2.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:03e7e372d5240cc23e9f07deca4d775c0817bffc641b01e9c3af208dbd300987", size = 6284462, upload-time = "2026-04-01T14:43:18.268Z" }, + { url = "https://files.pythonhosted.org/packages/e9/9e/c05e19657fd57841e476be1ab46c4d501bffbadbafdc31a6d665f8b737b6/pillow-12.2.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b86024e52a1b269467a802258c25521e6d742349d760728092e1bc2d135b4d76", size = 8094744, upload-time = "2026-04-01T14:43:20.716Z" }, + { url = "https://files.pythonhosted.org/packages/2b/54/1789c455ed10176066b6e7e6da1b01e50e36f94ba584dc68d9eebfe9156d/pillow-12.2.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7371b48c4fa448d20d2714c9a1f775a81155050d383333e0a6c15b1123dda005", size = 6398371, upload-time = "2026-04-01T14:43:23.443Z" }, + { url = "https://files.pythonhosted.org/packages/43/e3/fdc657359e919462369869f1c9f0e973f353f9a9ee295a39b1fea8ee1a77/pillow-12.2.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:62f5409336adb0663b7caa0da5c7d9e7bdbaae9ce761d34669420c2a801b2780", size = 7087215, upload-time = "2026-04-01T14:43:26.758Z" }, + { url = "https://files.pythonhosted.org/packages/8b/f8/2f6825e441d5b1959d2ca5adec984210f1ec086435b0ed5f52c19b3b8a6e/pillow-12.2.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:01afa7cf67f74f09523699b4e88c73fb55c13346d212a59a2db1f86b0a63e8c5", size = 6509783, upload-time = "2026-04-01T14:43:29.56Z" }, + { url = "https://files.pythonhosted.org/packages/67/f9/029a27095ad20f854f9dba026b3ea6428548316e057e6fc3545409e86651/pillow-12.2.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fc3d34d4a8fbec3e88a79b92e5465e0f9b842b628675850d860b8bd300b159f5", size = 7212112, upload-time = "2026-04-01T14:43:32.091Z" }, + { url = "https://files.pythonhosted.org/packages/be/42/025cfe05d1be22dbfdb4f264fe9de1ccda83f66e4fc3aac94748e784af04/pillow-12.2.0-cp312-cp312-win32.whl", hash = "sha256:58f62cc0f00fd29e64b29f4fd923ffdb3859c9f9e6105bfc37ba1d08994e8940", size = 6378489, upload-time = "2026-04-01T14:43:34.601Z" }, + { url = "https://files.pythonhosted.org/packages/5d/7b/25a221d2c761c6a8ae21bfa3874988ff2583e19cf8a27bf2fee358df7942/pillow-12.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:7f84204dee22a783350679a0333981df803dac21a0190d706a50475e361c93f5", size = 7084129, upload-time = "2026-04-01T14:43:37.213Z" }, + { url = "https://files.pythonhosted.org/packages/10/e1/542a474affab20fd4a0f1836cb234e8493519da6b76899e30bcc5d990b8b/pillow-12.2.0-cp312-cp312-win_arm64.whl", hash = "sha256:af73337013e0b3b46f175e79492d96845b16126ddf79c438d7ea7ff27783a414", size = 2463612, upload-time = "2026-04-01T14:43:39.421Z" }, + { url = "https://files.pythonhosted.org/packages/4a/01/53d10cf0dbad820a8db274d259a37ba50b88b24768ddccec07355382d5ad/pillow-12.2.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:8297651f5b5679c19968abefd6bb84d95fe30ef712eb1b2d9b2d31ca61267f4c", size = 4100837, upload-time = "2026-04-01T14:43:41.506Z" }, + { url = "https://files.pythonhosted.org/packages/0f/98/f3a6657ecb698c937f6c76ee564882945f29b79bad496abcba0e84659ec5/pillow-12.2.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:50d8520da2a6ce0af445fa6d648c4273c3eeefbc32d7ce049f22e8b5c3daecc2", size = 4176528, upload-time = "2026-04-01T14:43:43.773Z" }, + { url = "https://files.pythonhosted.org/packages/69/bc/8986948f05e3ea490b8442ea1c1d4d990b24a7e43d8a51b2c7d8b1dced36/pillow-12.2.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:766cef22385fa1091258ad7e6216792b156dc16d8d3fa607e7545b2b72061f1c", size = 3640401, upload-time = "2026-04-01T14:43:45.87Z" }, + { url = "https://files.pythonhosted.org/packages/34/46/6c717baadcd62bc8ed51d238d521ab651eaa74838291bda1f86fe1f864c9/pillow-12.2.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5d2fd0fa6b5d9d1de415060363433f28da8b1526c1c129020435e186794b3795", size = 5308094, upload-time = "2026-04-01T14:43:48.438Z" }, + { url = "https://files.pythonhosted.org/packages/71/43/905a14a8b17fdb1ccb58d282454490662d2cb89a6bfec26af6d3520da5ec/pillow-12.2.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:56b25336f502b6ed02e889f4ece894a72612fe885889a6e8c4c80239ff6e5f5f", size = 4695402, upload-time = "2026-04-01T14:43:51.292Z" }, + { url = "https://files.pythonhosted.org/packages/73/dd/42107efcb777b16fa0393317eac58f5b5cf30e8392e266e76e51cff28c3d/pillow-12.2.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f1c943e96e85df3d3478f7b691f229887e143f81fedab9b20205349ab04d73ed", size = 6280005, upload-time = "2026-04-01T14:43:54.242Z" }, + { url = "https://files.pythonhosted.org/packages/a8/68/b93e09e5e8549019e61acf49f65b1a8530765a7f812c77a7461bca7e4494/pillow-12.2.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:03f6fab9219220f041c74aeaa2939ff0062bd5c364ba9ce037197f4c6d498cd9", size = 8090669, upload-time = "2026-04-01T14:43:57.335Z" }, + { url = "https://files.pythonhosted.org/packages/4b/6e/3ccb54ce8ec4ddd1accd2d89004308b7b0b21c4ac3d20fa70af4760a4330/pillow-12.2.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5cdfebd752ec52bf5bb4e35d9c64b40826bc5b40a13df7c3cda20a2c03a0f5ed", size = 6395194, upload-time = "2026-04-01T14:43:59.864Z" }, + { url = "https://files.pythonhosted.org/packages/67/ee/21d4e8536afd1a328f01b359b4d3997b291ffd35a237c877b331c1c3b71c/pillow-12.2.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:eedf4b74eda2b5a4b2b2fb4c006d6295df3bf29e459e198c90ea48e130dc75c3", size = 7082423, upload-time = "2026-04-01T14:44:02.74Z" }, + { url = "https://files.pythonhosted.org/packages/78/5f/e9f86ab0146464e8c133fe85df987ed9e77e08b29d8d35f9f9f4d6f917ba/pillow-12.2.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:00a2865911330191c0b818c59103b58a5e697cae67042366970a6b6f1b20b7f9", size = 6505667, upload-time = "2026-04-01T14:44:05.381Z" }, + { url = "https://files.pythonhosted.org/packages/ed/1e/409007f56a2fdce61584fd3acbc2bbc259857d555196cedcadc68c015c82/pillow-12.2.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1e1757442ed87f4912397c6d35a0db6a7b52592156014706f17658ff58bbf795", size = 7208580, upload-time = "2026-04-01T14:44:08.39Z" }, + { url = "https://files.pythonhosted.org/packages/23/c4/7349421080b12fb35414607b8871e9534546c128a11965fd4a7002ccfbee/pillow-12.2.0-cp313-cp313-win32.whl", hash = "sha256:144748b3af2d1b358d41286056d0003f47cb339b8c43a9ea42f5fea4d8c66b6e", size = 6375896, upload-time = "2026-04-01T14:44:11.197Z" }, + { url = "https://files.pythonhosted.org/packages/3f/82/8a3739a5e470b3c6cbb1d21d315800d8e16bff503d1f16b03a4ec3212786/pillow-12.2.0-cp313-cp313-win_amd64.whl", hash = "sha256:390ede346628ccc626e5730107cde16c42d3836b89662a115a921f28440e6a3b", size = 7081266, upload-time = "2026-04-01T14:44:13.947Z" }, + { url = "https://files.pythonhosted.org/packages/c3/25/f968f618a062574294592f668218f8af564830ccebdd1fa6200f598e65c5/pillow-12.2.0-cp313-cp313-win_arm64.whl", hash = "sha256:8023abc91fba39036dbce14a7d6535632f99c0b857807cbbbf21ecc9f4717f06", size = 2463508, upload-time = "2026-04-01T14:44:16.312Z" }, + { url = "https://files.pythonhosted.org/packages/4d/a4/b342930964e3cb4dce5038ae34b0eab4653334995336cd486c5a8c25a00c/pillow-12.2.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:042db20a421b9bafecc4b84a8b6e444686bd9d836c7fd24542db3e7df7baad9b", size = 5309927, upload-time = "2026-04-01T14:44:18.89Z" }, + { url = "https://files.pythonhosted.org/packages/9f/de/23198e0a65a9cf06123f5435a5d95cea62a635697f8f03d134d3f3a96151/pillow-12.2.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:dd025009355c926a84a612fecf58bb315a3f6814b17ead51a8e48d3823d9087f", size = 4698624, upload-time = "2026-04-01T14:44:21.115Z" }, + { url = "https://files.pythonhosted.org/packages/01/a6/1265e977f17d93ea37aa28aa81bad4fa597933879fac2520d24e021c8da3/pillow-12.2.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:88ddbc66737e277852913bd1e07c150cc7bb124539f94c4e2df5344494e0a612", size = 6321252, upload-time = "2026-04-01T14:44:23.663Z" }, + { url = "https://files.pythonhosted.org/packages/3c/83/5982eb4a285967baa70340320be9f88e57665a387e3a53a7f0db8231a0cd/pillow-12.2.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d362d1878f00c142b7e1a16e6e5e780f02be8195123f164edf7eddd911eefe7c", size = 8126550, upload-time = "2026-04-01T14:44:26.772Z" }, + { url = "https://files.pythonhosted.org/packages/4e/48/6ffc514adce69f6050d0753b1a18fd920fce8cac87620d5a31231b04bfc5/pillow-12.2.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2c727a6d53cb0018aadd8018c2b938376af27914a68a492f59dfcaca650d5eea", size = 6433114, upload-time = "2026-04-01T14:44:29.615Z" }, + { url = "https://files.pythonhosted.org/packages/36/a3/f9a77144231fb8d40ee27107b4463e205fa4677e2ca2548e14da5cf18dce/pillow-12.2.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:efd8c21c98c5cc60653bcb311bef2ce0401642b7ce9d09e03a7da87c878289d4", size = 7115667, upload-time = "2026-04-01T14:44:32.773Z" }, + { url = "https://files.pythonhosted.org/packages/c1/fc/ac4ee3041e7d5a565e1c4fd72a113f03b6394cc72ab7089d27608f8aaccb/pillow-12.2.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9f08483a632889536b8139663db60f6724bfcb443c96f1b18855860d7d5c0fd4", size = 6538966, upload-time = "2026-04-01T14:44:35.252Z" }, + { url = "https://files.pythonhosted.org/packages/c0/a8/27fb307055087f3668f6d0a8ccb636e7431d56ed0750e07a60547b1e083e/pillow-12.2.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:dac8d77255a37e81a2efcbd1fc05f1c15ee82200e6c240d7e127e25e365c39ea", size = 7238241, upload-time = "2026-04-01T14:44:37.875Z" }, + { url = "https://files.pythonhosted.org/packages/ad/4b/926ab182c07fccae9fcb120043464e1ff1564775ec8864f21a0ebce6ac25/pillow-12.2.0-cp313-cp313t-win32.whl", hash = "sha256:ee3120ae9dff32f121610bb08e4313be87e03efeadfc6c0d18f89127e24d0c24", size = 6379592, upload-time = "2026-04-01T14:44:40.336Z" }, + { url = "https://files.pythonhosted.org/packages/c2/c4/f9e476451a098181b30050cc4c9a3556b64c02cf6497ea421ac047e89e4b/pillow-12.2.0-cp313-cp313t-win_amd64.whl", hash = "sha256:325ca0528c6788d2a6c3d40e3568639398137346c3d6e66bb61db96b96511c98", size = 7085542, upload-time = "2026-04-01T14:44:43.251Z" }, + { url = "https://files.pythonhosted.org/packages/00/a4/285f12aeacbe2d6dc36c407dfbbe9e96d4a80b0fb710a337f6d2ad978c75/pillow-12.2.0-cp313-cp313t-win_arm64.whl", hash = "sha256:2e5a76d03a6c6dcef67edabda7a52494afa4035021a79c8558e14af25313d453", size = 2465765, upload-time = "2026-04-01T14:44:45.996Z" }, + { url = "https://files.pythonhosted.org/packages/bf/98/4595daa2365416a86cb0d495248a393dfc84e96d62ad080c8546256cb9c0/pillow-12.2.0-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:3adc9215e8be0448ed6e814966ecf3d9952f0ea40eb14e89a102b87f450660d8", size = 4100848, upload-time = "2026-04-01T14:44:48.48Z" }, + { url = "https://files.pythonhosted.org/packages/0b/79/40184d464cf89f6663e18dfcf7ca21aae2491fff1a16127681bf1fa9b8cf/pillow-12.2.0-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:6a9adfc6d24b10f89588096364cc726174118c62130c817c2837c60cf08a392b", size = 4176515, upload-time = "2026-04-01T14:44:51.353Z" }, + { url = "https://files.pythonhosted.org/packages/b0/63/703f86fd4c422a9cf722833670f4f71418fb116b2853ff7da722ea43f184/pillow-12.2.0-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:6a6e67ea2e6feda684ed370f9a1c52e7a243631c025ba42149a2cc5934dec295", size = 3640159, upload-time = "2026-04-01T14:44:53.588Z" }, + { url = "https://files.pythonhosted.org/packages/71/e0/fb22f797187d0be2270f83500aab851536101b254bfa1eae10795709d283/pillow-12.2.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:2bb4a8d594eacdfc59d9e5ad972aa8afdd48d584ffd5f13a937a664c3e7db0ed", size = 5312185, upload-time = "2026-04-01T14:44:56.039Z" }, + { url = "https://files.pythonhosted.org/packages/ba/8c/1a9e46228571de18f8e28f16fabdfc20212a5d019f3e3303452b3f0a580d/pillow-12.2.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:80b2da48193b2f33ed0c32c38140f9d3186583ce7d516526d462645fd98660ae", size = 4695386, upload-time = "2026-04-01T14:44:58.663Z" }, + { url = "https://files.pythonhosted.org/packages/70/62/98f6b7f0c88b9addd0e87c217ded307b36be024d4ff8869a812b241d1345/pillow-12.2.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:22db17c68434de69d8ecfc2fe821569195c0c373b25cccb9cbdacf2c6e53c601", size = 6280384, upload-time = "2026-04-01T14:45:01.5Z" }, + { url = "https://files.pythonhosted.org/packages/5e/03/688747d2e91cfbe0e64f316cd2e8005698f76ada3130d0194664174fa5de/pillow-12.2.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7b14cc0106cd9aecda615dd6903840a058b4700fcb817687d0ee4fc8b6e389be", size = 8091599, upload-time = "2026-04-01T14:45:04.5Z" }, + { url = "https://files.pythonhosted.org/packages/f6/35/577e22b936fcdd66537329b33af0b4ccfefaeabd8aec04b266528cddb33c/pillow-12.2.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8cbeb542b2ebc6fcdacabf8aca8c1a97c9b3ad3927d46b8723f9d4f033288a0f", size = 6396021, upload-time = "2026-04-01T14:45:07.117Z" }, + { url = "https://files.pythonhosted.org/packages/11/8d/d2532ad2a603ca2b93ad9f5135732124e57811d0168155852f37fbce2458/pillow-12.2.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4bfd07bc812fbd20395212969e41931001fd59eb55a60658b0e5710872e95286", size = 7083360, upload-time = "2026-04-01T14:45:09.763Z" }, + { url = "https://files.pythonhosted.org/packages/5e/26/d325f9f56c7e039034897e7380e9cc202b1e368bfd04d4cbe6a441f02885/pillow-12.2.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:9aba9a17b623ef750a4d11b742cbafffeb48a869821252b30ee21b5e91392c50", size = 6507628, upload-time = "2026-04-01T14:45:12.378Z" }, + { url = "https://files.pythonhosted.org/packages/5f/f7/769d5632ffb0988f1c5e7660b3e731e30f7f8ec4318e94d0a5d674eb65a4/pillow-12.2.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:deede7c263feb25dba4e82ea23058a235dcc2fe1f6021025dc71f2b618e26104", size = 7209321, upload-time = "2026-04-01T14:45:15.122Z" }, + { url = "https://files.pythonhosted.org/packages/6a/7a/c253e3c645cd47f1aceea6a8bacdba9991bf45bb7dfe927f7c893e89c93c/pillow-12.2.0-cp314-cp314-win32.whl", hash = "sha256:632ff19b2778e43162304d50da0181ce24ac5bb8180122cbe1bf4673428328c7", size = 6479723, upload-time = "2026-04-01T14:45:17.797Z" }, + { url = "https://files.pythonhosted.org/packages/cd/8b/601e6566b957ca50e28725cb6c355c59c2c8609751efbecd980db44e0349/pillow-12.2.0-cp314-cp314-win_amd64.whl", hash = "sha256:4e6c62e9d237e9b65fac06857d511e90d8461a32adcc1b9065ea0c0fa3a28150", size = 7217400, upload-time = "2026-04-01T14:45:20.529Z" }, + { url = "https://files.pythonhosted.org/packages/d6/94/220e46c73065c3e2951bb91c11a1fb636c8c9ad427ac3ce7d7f3359b9b2f/pillow-12.2.0-cp314-cp314-win_arm64.whl", hash = "sha256:b1c1fbd8a5a1af3412a0810d060a78b5136ec0836c8a4ef9aa11807f2a22f4e1", size = 2554835, upload-time = "2026-04-01T14:45:23.162Z" }, + { url = "https://files.pythonhosted.org/packages/b6/ab/1b426a3974cb0e7da5c29ccff4807871d48110933a57207b5a676cccc155/pillow-12.2.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:57850958fe9c751670e49b2cecf6294acc99e562531f4bd317fa5ddee2068463", size = 5314225, upload-time = "2026-04-01T14:45:25.637Z" }, + { url = "https://files.pythonhosted.org/packages/19/1e/dce46f371be2438eecfee2a1960ee2a243bbe5e961890146d2dee1ff0f12/pillow-12.2.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:d5d38f1411c0ed9f97bcb49b7bd59b6b7c314e0e27420e34d99d844b9ce3b6f3", size = 4698541, upload-time = "2026-04-01T14:45:28.355Z" }, + { url = "https://files.pythonhosted.org/packages/55/c3/7fbecf70adb3a0c33b77a300dc52e424dc22ad8cdc06557a2e49523b703d/pillow-12.2.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5c0a9f29ca8e79f09de89293f82fc9b0270bb4af1d58bc98f540cc4aedf03166", size = 6322251, upload-time = "2026-04-01T14:45:30.924Z" }, + { url = "https://files.pythonhosted.org/packages/1c/3c/7fbc17cfb7e4fe0ef1642e0abc17fc6c94c9f7a16be41498e12e2ba60408/pillow-12.2.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1610dd6c61621ae1cf811bef44d77e149ce3f7b95afe66a4512f8c59f25d9ebe", size = 8127807, upload-time = "2026-04-01T14:45:33.908Z" }, + { url = "https://files.pythonhosted.org/packages/ff/c3/a8ae14d6defd2e448493ff512fae903b1e9bd40b72efb6ec55ce0048c8ce/pillow-12.2.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0a34329707af4f73cf1782a36cd2289c0368880654a2c11f027bcee9052d35dd", size = 6433935, upload-time = "2026-04-01T14:45:36.623Z" }, + { url = "https://files.pythonhosted.org/packages/6e/32/2880fb3a074847ac159d8f902cb43278a61e85f681661e7419e6596803ed/pillow-12.2.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8e9c4f5b3c546fa3458a29ab22646c1c6c787ea8f5ef51300e5a60300736905e", size = 7116720, upload-time = "2026-04-01T14:45:39.258Z" }, + { url = "https://files.pythonhosted.org/packages/46/87/495cc9c30e0129501643f24d320076f4cc54f718341df18cc70ec94c44e1/pillow-12.2.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:fb043ee2f06b41473269765c2feae53fc2e2fbf96e5e22ca94fb5ad677856f06", size = 6540498, upload-time = "2026-04-01T14:45:41.879Z" }, + { url = "https://files.pythonhosted.org/packages/18/53/773f5edca692009d883a72211b60fdaf8871cbef075eaa9d577f0a2f989e/pillow-12.2.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:f278f034eb75b4e8a13a54a876cc4a5ab39173d2cdd93a638e1b467fc545ac43", size = 7239413, upload-time = "2026-04-01T14:45:44.705Z" }, + { url = "https://files.pythonhosted.org/packages/c9/e4/4b64a97d71b2a83158134abbb2f5bd3f8a2ea691361282f010998f339ec7/pillow-12.2.0-cp314-cp314t-win32.whl", hash = "sha256:6bb77b2dcb06b20f9f4b4a8454caa581cd4dd0643a08bacf821216a16d9c8354", size = 6482084, upload-time = "2026-04-01T14:45:47.568Z" }, + { url = "https://files.pythonhosted.org/packages/ba/13/306d275efd3a3453f72114b7431c877d10b1154014c1ebbedd067770d629/pillow-12.2.0-cp314-cp314t-win_amd64.whl", hash = "sha256:6562ace0d3fb5f20ed7290f1f929cae41b25ae29528f2af1722966a0a02e2aa1", size = 7225152, upload-time = "2026-04-01T14:45:50.032Z" }, + { url = "https://files.pythonhosted.org/packages/ff/6e/cf826fae916b8658848d7b9f38d88da6396895c676e8086fc0988073aaf8/pillow-12.2.0-cp314-cp314t-win_arm64.whl", hash = "sha256:aa88ccfe4e32d362816319ed727a004423aab09c5cea43c01a4b435643fa34eb", size = 2556579, upload-time = "2026-04-01T14:45:52.529Z" }, + { url = "https://files.pythonhosted.org/packages/4e/b7/2437044fb910f499610356d1352e3423753c98e34f915252aafecc64889f/pillow-12.2.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0538bd5e05efec03ae613fd89c4ce0368ecd2ba239cc25b9f9be7ed426b0af1f", size = 5273969, upload-time = "2026-04-01T14:45:55.538Z" }, + { url = "https://files.pythonhosted.org/packages/f6/f4/8316e31de11b780f4ac08ef3654a75555e624a98db1056ecb2122d008d5a/pillow-12.2.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:394167b21da716608eac917c60aa9b969421b5dcbbe02ae7f013e7b85811c69d", size = 4659674, upload-time = "2026-04-01T14:45:58.093Z" }, + { url = "https://files.pythonhosted.org/packages/d4/37/664fca7201f8bb2aa1d20e2c3d5564a62e6ae5111741966c8319ca802361/pillow-12.2.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5d04bfa02cc2d23b497d1e90a0f927070043f6cbf303e738300532379a4b4e0f", size = 5288479, upload-time = "2026-04-01T14:46:01.141Z" }, + { url = "https://files.pythonhosted.org/packages/49/62/5b0ed78fce87346be7a5cfcfaaad91f6a1f98c26f86bdbafa2066c647ef6/pillow-12.2.0-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0c838a5125cee37e68edec915651521191cef1e6aa336b855f495766e77a366e", size = 7032230, upload-time = "2026-04-01T14:46:03.874Z" }, + { url = "https://files.pythonhosted.org/packages/c3/28/ec0fc38107fc32536908034e990c47914c57cd7c5a3ece4d8d8f7ffd7e27/pillow-12.2.0-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4a6c9fa44005fa37a91ebfc95d081e8079757d2e904b27103f4f5fa6f0bf78c0", size = 5355404, upload-time = "2026-04-01T14:46:06.33Z" }, + { url = "https://files.pythonhosted.org/packages/5e/8b/51b0eddcfa2180d60e41f06bd6d0a62202b20b59c68f5a132e615b75aecf/pillow-12.2.0-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:25373b66e0dd5905ed63fa3cae13c82fbddf3079f2c8bf15c6fb6a35586324c1", size = 6002215, upload-time = "2026-04-01T14:46:08.83Z" }, + { url = "https://files.pythonhosted.org/packages/bc/60/5382c03e1970de634027cee8e1b7d39776b778b81812aaf45b694dfe9e28/pillow-12.2.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:bfa9c230d2fe991bed5318a5f119bd6780cda2915cca595393649fc118ab895e", size = 7080946, upload-time = "2026-04-01T14:46:11.734Z" }, +] + +[[package]] +name = "pip" +version = "26.1.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/01/91/47e7d486260f618783899587af63ccf7980fb60245c3e63dd4571c6b57ad/pip-26.1.2.tar.gz", hash = "sha256:f49cd134c61cf2fd75e0ce2676db03e4054504a5a4986d00f8299ae632dc4605", size = 1840799, upload-time = "2026-05-31T17:33:58.56Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5d/95/6b5cb3461ea5673ba0995989746db58eb18b91b54dbf331e72f569540946/pip-26.1.2-py3-none-any.whl", hash = "sha256:382ff9f685ee3bc25864f820aa50505825f10f5458ffff07e30a6d96e5715cab", size = 1813144, upload-time = "2026-05-31T17:33:56.772Z" }, +] + +[[package]] +name = "pip-api" +version = "0.0.34" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pip" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b9/f1/ee85f8c7e82bccf90a3c7aad22863cc6e20057860a1361083cd2adacb92e/pip_api-0.0.34.tar.gz", hash = "sha256:9b75e958f14c5a2614bae415f2adf7eeb54d50a2cfbe7e24fd4826471bac3625", size = 123017, upload-time = "2024-07-09T20:32:30.641Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/91/f7/ebf5003e1065fd00b4cbef53bf0a65c3d3e1b599b676d5383ccb7a8b88ba/pip_api-0.0.34-py3-none-any.whl", hash = "sha256:8b2d7d7c37f2447373aa2cf8b1f60a2f2b27a84e1e9e0294a3f6ef10eb3ba6bb", size = 120369, upload-time = "2024-07-09T20:32:29.099Z" }, +] + +[[package]] +name = "pip-audit" +version = "2.10.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cachecontrol", extra = ["filecache"] }, + { name = "cyclonedx-python-lib" }, + { name = "packaging" }, + { name = "pip-api" }, + { name = "pip-requirements-parser" }, + { name = "platformdirs" }, + { name = "requests" }, + { name = "rich" }, + { name = "tomli" }, + { name = "tomli-w" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/66/a4/f21d5f0a0edabcbce31560b73c7c5a6f72ae87af4236fd1069c8f59a353d/pip_audit-2.10.1.tar.gz", hash = "sha256:1eb4565d19ebe5d48996f4b770b4d2b32887e12cb12cfa637f1a064011b55ffc", size = 54275, upload-time = "2026-06-10T22:17:01.744Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a3/a7/b0c504148114047bd1bc9d97447453c6850ca176bb2f3c0038835994e8b7/pip_audit-2.10.1-py3-none-any.whl", hash = "sha256:99ef3f600a317c1945f1e89e227ef26e1c2d618429b8bd3fa6f4f7c440c4611a", size = 62023, upload-time = "2026-06-10T22:17:00.309Z" }, +] + +[[package]] +name = "pip-requirements-parser" +version = "32.0.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "packaging" }, + { name = "pyparsing" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5e/2a/63b574101850e7f7b306ddbdb02cb294380d37948140eecd468fae392b54/pip-requirements-parser-32.0.1.tar.gz", hash = "sha256:b4fa3a7a0be38243123cf9d1f3518da10c51bdb165a2b2985566247f9155a7d3", size = 209359, upload-time = "2022-12-21T15:25:22.732Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/54/d0/d04f1d1e064ac901439699ee097f58688caadea42498ec9c4b4ad2ef84ab/pip_requirements_parser-32.0.1-py3-none-any.whl", hash = "sha256:4659bc2a667783e7a15d190f6fccf8b2486685b6dba4c19c3876314769c57526", size = 35648, upload-time = "2022-12-21T15:25:21.046Z" }, +] + +[[package]] +name = "platformdirs" +version = "4.10.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d7/47/e4501f49c178ae1d9f4a75073fda4204f52647993f075a9db4d14930e0c5/platformdirs-4.10.0.tar.gz", hash = "sha256:31e761a6a0ca04faf7353ea759bdba55652be214725111e5aac52dfa29d4bef7", size = 31224, upload-time = "2026-05-28T03:32:53.587Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/81/e6/cd9575ac904136b3cbf7aa7ee819ef86eedb7274e46f230e94ea4342e729/platformdirs-4.10.0-py3-none-any.whl", hash = "sha256:fb516cdb12eb0d857d0cd85a7c57cea4d060bee4578d6cf5a14dfdf8cbf8784a", size = 22743, upload-time = "2026-05-28T03:32:52.175Z" }, +] + +[[package]] +name = "pluggy" +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" }, +] + +[[package]] +name = "py-serializable" +version = "2.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "defusedxml" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/73/21/d250cfca8ff30c2e5a7447bc13861541126ce9bd4426cd5d0c9f08b5547d/py_serializable-2.1.0.tar.gz", hash = "sha256:9d5db56154a867a9b897c0163b33a793c804c80cee984116d02d49e4578fc103", size = 52368, upload-time = "2025-07-21T09:56:48.07Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9b/bf/7595e817906a29453ba4d99394e781b6fabe55d21f3c15d240f85dd06bb1/py_serializable-2.1.0-py3-none-any.whl", hash = "sha256:b56d5d686b5a03ba4f4db5e769dc32336e142fc3bd4d68a8c25579ebb0a67304", size = 23045, upload-time = "2025-07-21T09:56:46.848Z" }, +] + +[[package]] +name = "pycparser" +version = "3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1b/7d/92392ff7815c21062bea51aa7b87d45576f649f16458d78b7cf94b9ab2e6/pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29", size = 103492, upload-time = "2026-01-21T14:26:51.89Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992", size = 48172, upload-time = "2026-01-21T14:26:50.693Z" }, +] + +[[package]] +name = "pydantic" +version = "2.13.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "annotated-types" }, + { name = "pydantic-core" }, + { name = "typing-extensions" }, + { name = "typing-inspection" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/18/a5/b60d21ac674192f8ab0ba4e9fd860690f9b4a6e51ca5df118733b487d8d6/pydantic-2.13.4.tar.gz", hash = "sha256:c40756b57adaa8b1efeeced5c196f3f3b7c435f90e84ea7f443901bec8099ef6", size = 844775, upload-time = "2026-05-06T13:43:05.343Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fd/7b/122376b1fd3c62c1ed9dc80c931ace4844b3c55407b6fb2d199377c9736f/pydantic-2.13.4-py3-none-any.whl", hash = "sha256:45a282cde31d808236fd7ea9d919b128653c8b38b393d1c4ab335c62924d9aba", size = 472262, upload-time = "2026-05-06T13:43:02.641Z" }, +] + +[[package]] +name = "pydantic-core" +version = "2.46.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9d/56/921726b776ace8d8f5db44c4ef961006580d91dc52b803c489fafd1aa249/pydantic_core-2.46.4.tar.gz", hash = "sha256:62f875393d7f270851f20523dd2e29f082bcc82292d66db2b64ea71f64b6e1c1", size = 471464, upload-time = "2026-05-06T13:37:06.98Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5c/fa/6d7708d2cfc1a832acb6aeb0cd16e801902df8a0f583bb3b4b527fde022e/pydantic_core-2.46.4-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:0e96592440881c74a213e5ad528e2b24d3d4f940de2766bed9010ab1d9e51594", size = 2111872, upload-time = "2026-05-06T13:40:27.596Z" }, + { url = "https://files.pythonhosted.org/packages/ae/6f/aa064a3e74b5745afbdf250594f38e7ead05e2d651bcb35994b9417a0d4d/pydantic_core-2.46.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e0d65b8c354be7fb5f720c3caa8bc940bc2d20ce749c8e06135f07f8ed95dd7c", size = 1948255, upload-time = "2026-05-06T13:39:12.574Z" }, + { url = "https://files.pythonhosted.org/packages/43/3a/41114a9f7569b84b4d84e7a018c57c56347dac30c0d4a872946ec4e36c46/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bfb192b3f4b9e8a89b6277b6ce787564f62cfd272055f6e685726b111dc7826", size = 1972827, upload-time = "2026-05-06T13:38:19.841Z" }, + { url = "https://files.pythonhosted.org/packages/ef/25/1ab42e8048fe551934d9884e8d64daa7e990ad386f310a15981aeb6a5b08/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9037063db01f09b09e237c282b6792bd4da634b5402c4e7f0c61effed7701a04", size = 2041051, upload-time = "2026-05-06T13:38:10.447Z" }, + { url = "https://files.pythonhosted.org/packages/94/c2/1a934597ddf08da410385b3b7aae91956a5a76c635effef456074fad7e88/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fc010ab034c8c7452522748bf937df58020d256ccae0874463d1f4d01758af8e", size = 2221314, upload-time = "2026-05-06T13:40:13.089Z" }, + { url = "https://files.pythonhosted.org/packages/02/6d/9e8ad178c9c4df27ad3c8f25d1fe2a7ab0d2ba0559fad4aee5d3d1f16771/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c5dac79fa1614d1e06ca695109c6105923bd9c7d1d6c918d4e637b7e6b32fd3", size = 2285146, upload-time = "2026-05-06T13:38:59.224Z" }, + { url = "https://files.pythonhosted.org/packages/80/50/540cd3aeefc041beb111125c4bff779831a2111fc6b15a9138cda277d32c/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f9fa868638bf362d3d138ea55829cefb3d5f4b0d7f142234382a15e2485dbec4", size = 2089685, upload-time = "2026-05-06T13:38:17.762Z" }, + { url = "https://files.pythonhosted.org/packages/6b/a4/b440ad35f05f6a38f89fa0f149accb3f0e02be94ca5e15f3c449a61b4bc9/pydantic_core-2.46.4-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:17299feefe090f2caa5b8e37222bb5f663e4935a8bfa6931d4102e5df1a9f398", size = 2115420, upload-time = "2026-05-06T13:37:58.195Z" }, + { url = "https://files.pythonhosted.org/packages/99/61/de4f55db8dfd57bfdfa9a12ec90fe1b57c4f41062f7ca86f08586b3e0ac0/pydantic_core-2.46.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4c63ebc82684aa89d9a3bcbd13d515b3be44250dc68dd3bd81526c1cb31286c3", size = 2165122, upload-time = "2026-05-06T13:37:01.167Z" }, + { url = "https://files.pythonhosted.org/packages/f7/52/7c529d7bdb2d1068bd52f51fe32572c8301f9a4febf1948f10639f1436f5/pydantic_core-2.46.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:aaa2a54443eff1950ba5ddc6b6ccda0d9c84a364276a62f969bdf2a390650848", size = 2182573, upload-time = "2026-05-06T13:38:45.04Z" }, + { url = "https://files.pythonhosted.org/packages/37/b3/7c40325848ba78247f2812dcf9c7274e38cd801820ca6dd9fe63bcfb0eb4/pydantic_core-2.46.4-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:18e5ceec2ab67e6d5f1a9085e5a24c9c4e2ac4545730bfe668680bca05e555f3", size = 2317139, upload-time = "2026-05-06T13:37:15.539Z" }, + { url = "https://files.pythonhosted.org/packages/d9/37/f913f81a657c865b75da6c0dbed79876073c2a43b5bd9edbe8da785e4d49/pydantic_core-2.46.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a0f62d0a58f4e7da165457e995725421e0064f2255d8eccebc49f41bbc23b109", size = 2360433, upload-time = "2026-05-06T13:37:30.099Z" }, + { url = "https://files.pythonhosted.org/packages/c4/67/6acaa1be2567f9256b056d8477158cac7240813956ce86e49deae8e173b4/pydantic_core-2.46.4-cp311-cp311-win32.whl", hash = "sha256:041bde0a48fd37cf71cab1c9d56d3e8625a3793fef1f7dd232b3ff37e978ecda", size = 1985513, upload-time = "2026-05-06T13:38:15.669Z" }, + { url = "https://files.pythonhosted.org/packages/aa/e6/c505f83dfeda9a2e5c995cfd872949e4d05e12f7feb3dca72f633daefa94/pydantic_core-2.46.4-cp311-cp311-win_amd64.whl", hash = "sha256:6f2eeda33a839975441c86a4119e1383c50b47faf0cbb5176985565c6bb02c33", size = 2071114, upload-time = "2026-05-06T13:40:35.416Z" }, + { url = "https://files.pythonhosted.org/packages/0f/da/7a263a96d965d9d0df5e8de8a475f33495451117035b09acb110288c381f/pydantic_core-2.46.4-cp311-cp311-win_arm64.whl", hash = "sha256:14f4c5d6db102bd796a627bbb3a17b4cf4574b9ae861d8b7c9a9661c6dd3362d", size = 2044298, upload-time = "2026-05-06T13:38:29.754Z" }, + { url = "https://files.pythonhosted.org/packages/ce/8c/af022f0af448d7747c5154288d46b5f2bc5f17366eaa0e23e9aa04d59f3b/pydantic_core-2.46.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:3245406455a5d98187ec35530fd772b1d799b26667980872c8d4614991e2c4a2", size = 2106158, upload-time = "2026-05-06T13:38:57.215Z" }, + { url = "https://files.pythonhosted.org/packages/19/95/6195171e385007300f0f5574592e467c568becce2d937a0b6804f218bc49/pydantic_core-2.46.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:962ccbab7b642487b1d8b7df90ef677e03134cf1fd8880bf698649b22a69371f", size = 1951724, upload-time = "2026-05-06T13:37:02.697Z" }, + { url = "https://files.pythonhosted.org/packages/8e/bc/f47d1ff9cbb1620e1b5b697eef06010035735f07820180e74178226b27b3/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8233f2947cf85404441fd7e0085f53b10c93e0ee78611099b5c7237e36aacbf7", size = 1975742, upload-time = "2026-05-06T13:37:09.448Z" }, + { url = "https://files.pythonhosted.org/packages/5b/11/9b9a5b0306345664a2da6410877af6e8082481b5884b3ddd78d47c6013ce/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3a233125ac121aa3ffba9a2b59edfc4a985a76092dc8279586ab4b71390875e7", size = 2052418, upload-time = "2026-05-06T13:37:38.234Z" }, + { url = "https://files.pythonhosted.org/packages/f1/b7/a65fec226f5d78fc39f4a13c4cc0c768c22b113438f60c14adc9d2865038/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b712b53160b79a5850310b912a5ef8e57e56947c8ad690c227f5c9d7e561712", size = 2232274, upload-time = "2026-05-06T13:38:27.753Z" }, + { url = "https://files.pythonhosted.org/packages/68/f0/92039db98b907ef49269a8271f67db9cb78ae2fc68062ef7e4e77adb5f61/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9401557acd873c3a7f3eb9383edef8ac4968f9510e340f4808d427e75667e7b4", size = 2309940, upload-time = "2026-05-06T13:38:05.353Z" }, + { url = "https://files.pythonhosted.org/packages/5f/97/2aab507d3d00ca626e8e57c1eac6a79e4e5fbcc63eb99733ff55d1717f65/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:926c9541b14b12b1681dca8a0b75feb510b06c6341b70a8e500c2fdcff837cce", size = 2094516, upload-time = "2026-05-06T13:39:10.577Z" }, + { url = "https://files.pythonhosted.org/packages/22/37/a8aca44d40d737dde2bc05b3c6c07dff0de07ce6f82e9f3167aeaf4d5dea/pydantic_core-2.46.4-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:56cb4851bcaf3d117eddcef4fe66afd750a50274b0da8e22be256d10e5611987", size = 2136854, upload-time = "2026-05-06T13:40:22.59Z" }, + { url = "https://files.pythonhosted.org/packages/24/99/fcef1b79238c06a8cbec70819ac722ba76e02bc8ada9b0fd66eba40da01b/pydantic_core-2.46.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c68fcd102d71ea85c5b2dfac3f4f8476eff42a9e078fd5faefff6d145063536b", size = 2180306, upload-time = "2026-05-06T13:40:10.666Z" }, + { url = "https://files.pythonhosted.org/packages/ae/6c/fc44000918855b42779d007ae63b0532794739027b2f417321cddbc44f6a/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b2f69dec1725e79a012d920df1707de5caf7ed5e08f3be4435e25803efc47458", size = 2190044, upload-time = "2026-05-06T13:40:43.231Z" }, + { url = "https://files.pythonhosted.org/packages/6b/65/d9cadc9f1920d7a127ad2edba16c1db7916e59719285cd6c94600b0080ba/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:8d0820e8192167f80d88d64038e609c31452eeca865b4e1d9950a27a4609b00b", size = 2329133, upload-time = "2026-05-06T13:39:57.365Z" }, + { url = "https://files.pythonhosted.org/packages/d0/cf/c873d91679f3a30bcf5e7ac280ce5573483e72295307685120d0d5ad3416/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fbdb89b3e1c94a30cc5edfce477c6e6a5dc4d8f84665b455c27582f211a1c72c", size = 2374464, upload-time = "2026-05-06T13:38:06.976Z" }, + { url = "https://files.pythonhosted.org/packages/47/bd/6f2fc8188f31bf10590f1e98e7b306336161fac930a8c514cd7bd828c7dc/pydantic_core-2.46.4-cp312-cp312-win32.whl", hash = "sha256:9aa768456404a8bf48a4406685ac2bec8e72b62c69313734fa3b73cf33b3a894", size = 1974823, upload-time = "2026-05-06T13:40:47.985Z" }, + { url = "https://files.pythonhosted.org/packages/40/8c/985c1d41ea1107c2534abd9870e4ed5c8e7669b5c308297835c001e7a1c4/pydantic_core-2.46.4-cp312-cp312-win_amd64.whl", hash = "sha256:e9c26f834c65f5752f3f06cb08cb86a913ceb7274d0db6e267808a708b46bc89", size = 2072919, upload-time = "2026-05-06T13:39:21.153Z" }, + { url = "https://files.pythonhosted.org/packages/c4/ba/f463d006e0c47373ca7ec5e1a261c59dc01ef4d62b2657af925fb0deee3a/pydantic_core-2.46.4-cp312-cp312-win_arm64.whl", hash = "sha256:4fc73cb559bdb54b1134a706a2802a4cddd27a0633f5abb7e53056268751ac6a", size = 2027604, upload-time = "2026-05-06T13:39:03.753Z" }, + { url = "https://files.pythonhosted.org/packages/51/a2/5d30b469c5267a17b39dec53208222f76a8d351dfac4af661888c5aee77d/pydantic_core-2.46.4-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:5d5902252db0d3cedf8d4a1bc68f70eeb430f7e4c7104c8c476753519b423008", size = 2106306, upload-time = "2026-05-06T13:37:48.029Z" }, + { url = "https://files.pythonhosted.org/packages/c1/81/4fa520eaffa8bd7d1525e644cd6d39e7d60b1592bc5b516693c7340b50f1/pydantic_core-2.46.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:c94f0688e7b8d0a67abf40e57a7eaaecd17cc9586706a31b76c031f63df052b4", size = 1951906, upload-time = "2026-05-06T13:37:17.012Z" }, + { url = "https://files.pythonhosted.org/packages/03/d5/fd02da45b659668b05923b17ba3a0100a0a3d5541e3bd8fcc4ecb711309e/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f027324c56cd5406ca49c124b0db10e56c69064fec039acc571c29020cc87c76", size = 1976802, upload-time = "2026-05-06T13:37:35.113Z" }, + { url = "https://files.pythonhosted.org/packages/21/f2/95727e1368be3d3ed485eaab7adbd7dda408f33f7a36e8b48e0144002b91/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e739fee756ba1010f8bcccb534252e85a35fe45ae92c295a06059ce58b74ccd3", size = 2052446, upload-time = "2026-05-06T13:37:12.313Z" }, + { url = "https://files.pythonhosted.org/packages/9c/86/5d99feea3f77c7234b8718075b23db11532773c1a0dbd9b9490215dc2eeb/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9d56801be94b86a9da183e5f3766e6310752b99ff647e38b09a9500d88e46e76", size = 2232757, upload-time = "2026-05-06T13:39:01.149Z" }, + { url = "https://files.pythonhosted.org/packages/d2/3a/508ac615935ef7588cf6d9e9b91309fdc2da751af865e02a9098de88258c/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2412e734dcb48da14d4e4006b82b46b74f2518b8a26ee7e58c6844a6cd6d03c4", size = 2309275, upload-time = "2026-05-06T13:37:41.406Z" }, + { url = "https://files.pythonhosted.org/packages/07/f8/41db9de19d7987d6b04715a02b3b40aea467000275d9d758ffaa31af7d50/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9551187363ffc0de2a00b2e47c25aeaeb1020b69b668762966df15fc5659dd5a", size = 2094467, upload-time = "2026-05-06T13:39:18.847Z" }, + { url = "https://files.pythonhosted.org/packages/2c/e2/f35033184cb11d0052daf4416e8e10a502ea2ac006fc4f459aee872727d1/pydantic_core-2.46.4-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:0186750b482eefa11d7f435892b09c5c606193ef3375bcf94aa00ae6bfb66262", size = 2134417, upload-time = "2026-05-06T13:40:17.944Z" }, + { url = "https://files.pythonhosted.org/packages/7e/7b/6ceeb1cc90e193862f444ebe373d8fdf613f0a82572dde03fb10734c6c71/pydantic_core-2.46.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5855698a4856556d86e8e6cd8434bc3ac0314ee8e12089ae0e143f64c6256e4e", size = 2179782, upload-time = "2026-05-06T13:40:32.618Z" }, + { url = "https://files.pythonhosted.org/packages/5a/f2/c8d7773ede6af08036423a00ae0ceffce266c3c52a096c435d68c896083f/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:cbaf13819775b7f769bf4a1f066cb6df7a28d4480081a589828ef190226881cd", size = 2188782, upload-time = "2026-05-06T13:36:51.018Z" }, + { url = "https://files.pythonhosted.org/packages/59/31/0c864784e31f09f05cdd87606f08923b9c9e7f6e51dd27f20f62f975ce9f/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:633147d34cf4550417f12e2b1a0383973bdf5cdfde212cb09e9a581cf10820be", size = 2328334, upload-time = "2026-05-06T13:40:37.764Z" }, + { url = "https://files.pythonhosted.org/packages/c2/eb/4f6c8a41efa30baa755590f4141abf3a8c370fab610915733e74134a7270/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:82cf5301172168103724d49a1444d3378cb20cdee30b116a1bd6031236298a5d", size = 2372986, upload-time = "2026-05-06T13:39:34.152Z" }, + { url = "https://files.pythonhosted.org/packages/5b/24/b375a480d53113860c299764bfe9f349a3dc9108b3adc0d7f0d786492ebf/pydantic_core-2.46.4-cp313-cp313-win32.whl", hash = "sha256:9fa8ae11da9e2b3126c6426f147e0fba88d96d65921799bb30c6abd1cb2c97fb", size = 1973693, upload-time = "2026-05-06T13:37:55.072Z" }, + { url = "https://files.pythonhosted.org/packages/7e/e8/cff247591966f2d22ec8c003cd7587e27b7ba7b81ab2fb888e3ab75dc285/pydantic_core-2.46.4-cp313-cp313-win_amd64.whl", hash = "sha256:6b3ace8194b0e5204818c92802dcdca7fc6d88aabbb799d7c795540d9cd6d292", size = 2071819, upload-time = "2026-05-06T13:38:49.139Z" }, + { url = "https://files.pythonhosted.org/packages/c6/1a/f4aee670d5670e9e148e0c82c7db98d780be566c6e6a97ee8035528ca0b3/pydantic_core-2.46.4-cp313-cp313-win_arm64.whl", hash = "sha256:184c081504d17f1c1066e430e117142b2c77d9448a97f7b65c6ac9fd9aee238d", size = 2027411, upload-time = "2026-05-06T13:40:45.796Z" }, + { url = "https://files.pythonhosted.org/packages/8d/74/228a26ddad29c6672b805d9fd78e8d251cd04004fa7eed0e622096cd0250/pydantic_core-2.46.4-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:428e04521a40150c85216fc8b85e8d39fece235a9cf5e383761238c7fa9b96fb", size = 2102079, upload-time = "2026-05-06T13:38:41.019Z" }, + { url = "https://files.pythonhosted.org/packages/ad/1f/8970b150a4b4365623ae00fc88603491f763c627311ae8031e3111356d6e/pydantic_core-2.46.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:23ace664830ee0bfe014a0c7bc248b1f7f25ed7ad103852c317624a1083af462", size = 1952179, upload-time = "2026-05-06T13:36:59.812Z" }, + { url = "https://files.pythonhosted.org/packages/95/30/5211a831ae054928054b2f79731661087a2bc5c01e825c672b3a4a8f1b3e/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce5c1d2a8b27468f433ca974829c44060b8097eedc39933e3c206a90ee49c4a9", size = 1978926, upload-time = "2026-05-06T13:37:39.933Z" }, + { url = "https://files.pythonhosted.org/packages/57/e9/689668733b1eb67adeef047db3c2e8788fcf65a7fd9c9e2b46b7744fe245/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7283d57845ecf5a163403eb0702dfc220cc4fbdd18919cb5ccea4f95ee1cdab4", size = 2046785, upload-time = "2026-05-06T13:38:01.995Z" }, + { url = "https://files.pythonhosted.org/packages/60/d9/6715260422ff50a2109878fd24d948a6c3446bb2664f34ee78cd972b3acd/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8daafc69c93ee8a0204506a3b6b30f586ef54028f52aeeeb5c4cfc5184fd5914", size = 2228733, upload-time = "2026-05-06T13:40:50.371Z" }, + { url = "https://files.pythonhosted.org/packages/18/ae/fdb2f64316afca925640f8e70bb1a564b0ec2721c1389e25b8eb4bf9a299/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd2213145bcc2ba85884d0ac63d222fece9209678f77b9b4d76f054c561adb28", size = 2307534, upload-time = "2026-05-06T13:37:21.531Z" }, + { url = "https://files.pythonhosted.org/packages/89/1d/8eff589b45bb8190a9d12c49cfad0f176a5cbd1534908a6b5125e2886239/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a5f930472650a82629163023e630d160863fce524c616f4e5186e5de9d9a49b", size = 2099732, upload-time = "2026-05-06T13:39:31.942Z" }, + { url = "https://files.pythonhosted.org/packages/06/d5/ee5a3366637fee41dee51a1fc91562dcf12ddbc68fda34e6b253da2324bb/pydantic_core-2.46.4-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:c1b3f518abeca3aa13c712fd202306e145abf59a18b094a6bafb2d2bbf59192c", size = 2129627, upload-time = "2026-05-06T13:37:25.033Z" }, + { url = "https://files.pythonhosted.org/packages/94/33/2414be571d2c6a6c4d08be21f9292b6d3fdb08949a97b6dfe985017821db/pydantic_core-2.46.4-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1a7dd0b3ee80d90150e3495a3a13ac34dbcbfd4f012996a6a1d8900e91b5c0fb", size = 2179141, upload-time = "2026-05-06T13:37:14.046Z" }, + { url = "https://files.pythonhosted.org/packages/7b/79/7daa95be995be0eecc4cf75064cb33f9bbbfe3fe0158caf2f0d4a996a5c7/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:3fb702cd90b0446a3a1c5e470bfa0dd23c0233b676a9099ddcc964fa6ca13898", size = 2184325, upload-time = "2026-05-06T13:36:53.615Z" }, + { url = "https://files.pythonhosted.org/packages/9f/cb/d0a382f5c0de8a222dc61c65348e0ce831b1f68e0a018450d31c2cace3a5/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:b8458003118a712e66286df6a707db01c52c0f52f7db8e4a38f0da1d3b94fc4e", size = 2323990, upload-time = "2026-05-06T13:40:29.971Z" }, + { url = "https://files.pythonhosted.org/packages/05/db/d9ba624cc4a5aced1598e88c04fdbd8310c8a69b9d38b9a3d39ce3a61ed7/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:372429a130e469c9cd698925ce5fc50940b7a1336b0d82038e63d5bbc4edc519", size = 2369978, upload-time = "2026-05-06T13:37:23.027Z" }, + { url = "https://files.pythonhosted.org/packages/f2/20/d15df15ba918c423461905802bfd2981c3af0bfa0e40d05e13edbfa48bc3/pydantic_core-2.46.4-cp314-cp314-win32.whl", hash = "sha256:85bb3611ff1802f3ee7fdd7dbff26b56f343fb432d57a4728fdd49b6ef35e2f4", size = 1966354, upload-time = "2026-05-06T13:38:03.499Z" }, + { url = "https://files.pythonhosted.org/packages/fc/b6/6b8de4c0a7d7ab3004c439c80c5c1e0a3e8d78bbae19379b01960383d9e5/pydantic_core-2.46.4-cp314-cp314-win_amd64.whl", hash = "sha256:811ff8e9c313ab425368bcbb36e5c4ebd7108c2bbf4e4089cfbb0b01eff63fac", size = 2072238, upload-time = "2026-05-06T13:39:40.807Z" }, + { url = "https://files.pythonhosted.org/packages/32/36/51eb763beec1f4cf59b1db243a7dcc39cbb41230f050a09b9d69faaf0a48/pydantic_core-2.46.4-cp314-cp314-win_arm64.whl", hash = "sha256:bfec22eab3c8cc2ceec0248aec886624116dc079afa027ecc8ad4a7e62010f8a", size = 2018251, upload-time = "2026-05-06T13:37:26.72Z" }, + { url = "https://files.pythonhosted.org/packages/e8/91/855af51d625b23aa987116a19e231d2aaef9c4a415273ddc189b79a45fee/pydantic_core-2.46.4-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:af8244b2bef6aaad6d92cda81372de7f8c8d36c9f0c3ea36e827c60e7d9467a0", size = 2099593, upload-time = "2026-05-06T13:39:47.682Z" }, + { url = "https://files.pythonhosted.org/packages/fb/1b/8784a54c65edb5f49f0a14d6977cf1b209bba85a4c77445b255c2de58ab3/pydantic_core-2.46.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5a4330cdbc57162e4b3aa303f588ba752257694c9c9be3e7ebb11b4aca659b5d", size = 1935226, upload-time = "2026-05-06T13:40:40.428Z" }, + { url = "https://files.pythonhosted.org/packages/e8/e7/1955d28d1afc56dd4b3ad7cc0cf39df1b9852964cf16e5d13912756d6d6b/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:29c61fc04a3d840155ff08e475a04809278972fe6aef51e2720554e96367e34b", size = 1974605, upload-time = "2026-05-06T13:37:32.029Z" }, + { url = "https://files.pythonhosted.org/packages/93/e2/3fedbf0ba7a22850e6e9fd78117f1c0f10f950182344d8a6c535d468fdd8/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c50f2528cf200c5eed56faf3f4e22fcd5f38c157a8b78576e6ba3168ec35f000", size = 2030777, upload-time = "2026-05-06T13:38:55.239Z" }, + { url = "https://files.pythonhosted.org/packages/f8/61/46be275fcaaba0b4f5b9669dd852267ce1ff616592dccf7a7845588df091/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0cbe8b01f948de4286c74cdd6c667aceb38f5c1e26f0693b3983d9d74887c65e", size = 2236641, upload-time = "2026-05-06T13:37:08.096Z" }, + { url = "https://files.pythonhosted.org/packages/60/db/12e93e46a8bac9988be3c016860f83293daea8c716c029c9ace279036f2f/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:617d7e2ca7dcb8c5cf6bcb8c59b8832c94b36196bbf1cbd1bfb56ed341905edd", size = 2286404, upload-time = "2026-05-06T13:40:20.221Z" }, + { url = "https://files.pythonhosted.org/packages/e2/4a/4d8b19008f38d31c53b8219cfedc2e3d5de5fe99d90076b7e767de29274f/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7027560ee92211647d0d34e3f7cd6f50da56399d26a9c8ad0da286d3869a53f3", size = 2109219, upload-time = "2026-05-06T13:38:12.153Z" }, + { url = "https://files.pythonhosted.org/packages/88/70/3cbc40978fefb7bb09c6708d40d4ad1a5d70fd7213c3d17f971de868ec1f/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:f99626688942fb746e545232e7726926f3be91b5975f8b55327665fafda991c7", size = 2110594, upload-time = "2026-05-06T13:40:02.971Z" }, + { url = "https://files.pythonhosted.org/packages/9d/20/b8d36736216e29491125531685b2f9e61aa5b4b2599893f8268551da3338/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fc3e9034a63de20e15e8ade85358bc6efc614008cab72898b4b4952bea0509ff", size = 2159542, upload-time = "2026-05-06T13:39:27.506Z" }, + { url = "https://files.pythonhosted.org/packages/1d/a2/367df868eb584dacf6bf82a389272406d7178e301c4ac82545ab98bc2dd9/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:97e7cf2be5c77b7d1a9713a05605d49460d02c6078d38d8bef3cbe323c548424", size = 2168146, upload-time = "2026-05-06T13:38:31.93Z" }, + { url = "https://files.pythonhosted.org/packages/c1/b8/4460f77f7e201893f649a29ab355dddd3beee8a97bcb1a320db414f9a06e/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:3bf92c5d0e00fefaab325a4d27828fe6b6e2a21848686b5b60d2d9eeb09d76c6", size = 2306309, upload-time = "2026-05-06T13:37:44.717Z" }, + { url = "https://files.pythonhosted.org/packages/64/c4/be2639293acd87dc8ddbcec41a73cee9b2ebf996fe6d892a1a74e88ad3f7/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:3ecbc122d18468d06ca279dc26a8c2e2d5acb10943bb35e36ae92096dc3b5565", size = 2369736, upload-time = "2026-05-06T13:37:05.645Z" }, + { url = "https://files.pythonhosted.org/packages/30/a6/9f9f380dbb301f67023bf8f707aaa75daadf84f7152d95c410fd7e81d994/pydantic_core-2.46.4-cp314-cp314t-win32.whl", hash = "sha256:e846ae7835bf0703ae43f534ab79a867146dadd59dc9ca5c8b53d5c8f7c9ef02", size = 1955575, upload-time = "2026-05-06T13:38:51.116Z" }, + { url = "https://files.pythonhosted.org/packages/40/1f/f1eb9eb350e795d1af8586289746f5c5677d16043040d63710e22abc43c9/pydantic_core-2.46.4-cp314-cp314t-win_amd64.whl", hash = "sha256:2108ba5c1c1eca18030634489dc544844144ee36357f2f9f780b93e7ddbb44b5", size = 2051624, upload-time = "2026-05-06T13:38:21.672Z" }, + { url = "https://files.pythonhosted.org/packages/f6/d2/42dd53d0a85c27606f316d3aa5d2869c4e8470a5ed6dec30e4a1abe19192/pydantic_core-2.46.4-cp314-cp314t-win_arm64.whl", hash = "sha256:4fcbe087dbc2068af7eda3aa87634eba216dbda64d1ae73c8684b621d33f6596", size = 2017325, upload-time = "2026-05-06T13:40:52.723Z" }, + { url = "https://files.pythonhosted.org/packages/ee/a4/73995fd4ebbb46ba0ee51e6fa049b8f02c40daebb762208feda8a6b7894d/pydantic_core-2.46.4-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:14d4edf427bdcf950a8a02d7cb44a08614388dd6e1bdcbf4f67504fa7887da9c", size = 2111589, upload-time = "2026-05-06T13:37:10.817Z" }, + { url = "https://files.pythonhosted.org/packages/fb/7f/f37d3a5e8bfcc2e403f5c57a730f2d815693fb42119e8ea48b3789335af1/pydantic_core-2.46.4-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:0ce40cd7b21210e99342afafbd4d0f76d784eb5b1d60f3bdc566be4983c6c73b", size = 1944552, upload-time = "2026-05-06T13:36:56.717Z" }, + { url = "https://files.pythonhosted.org/packages/15/3c/d7eb777b3ff43e8433a4efb39a17aa8fd98a4ee8561a24a67ef5db07b2d6/pydantic_core-2.46.4-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:90884113d8b48f760e9587002789ddd741e76ab9f89518cd1e43b1f1a52ec44b", size = 1982984, upload-time = "2026-05-06T13:39:06.207Z" }, + { url = "https://files.pythonhosted.org/packages/63/87/70b9f40170a81afd55ca26c9b2acb25c20d64bcfbf888fafecb3ba077d4c/pydantic_core-2.46.4-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:66ce7632c22d837c95301830e111ad0128a32b8207533b60896a96c4915192ea", size = 2138417, upload-time = "2026-05-06T13:39:45.476Z" }, + { url = "https://files.pythonhosted.org/packages/9d/1d/8987ad40f65ae1432753072f214fb5c74fe47ffbd0698bb9cbbb585664f8/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:1d8ba486450b14f3b1d63bc521d410ec7565e52f887b9fb671791886436a42f7", size = 2095527, upload-time = "2026-05-06T13:39:52.283Z" }, + { url = "https://files.pythonhosted.org/packages/64/d3/84c282a7eee1d3ac4c0377546ef5a1ea436ce26840d9ac3b7ed54a377507/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:3009f12e4e90b7f88b4f9adb1b0c4a3d58fe7820f3238c190047209d148026df", size = 1936024, upload-time = "2026-05-06T13:40:15.671Z" }, + { url = "https://files.pythonhosted.org/packages/d7/ca/eac61596cdeb4d7e174d3dc0bd8a6238f14f75f97a24e7b7db4c7e7340a0/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad785e92e6dc634c21555edc8bd6b64957ab844541bcb96a1366c202951ae526", size = 1990696, upload-time = "2026-05-06T13:38:34.717Z" }, + { url = "https://files.pythonhosted.org/packages/fa/c3/7c8b240552251faf6b3a957db200fcfbbcec36763c050428b601e0c9b83b/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00c603d540afdd6b80eb39f078f33ebd46211f02f33e34a32d9f053bba711de0", size = 2147590, upload-time = "2026-05-06T13:39:29.883Z" }, + { url = "https://files.pythonhosted.org/packages/11/cb/428de0385b6c8d44b716feba566abfacfbd23ee3c4439faa789a1456242f/pydantic_core-2.46.4-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:0c563b08bca408dc7f65f700633d8442fffb2421fc47b8101377e9fd65051ff0", size = 2112782, upload-time = "2026-05-06T13:37:04.016Z" }, + { url = "https://files.pythonhosted.org/packages/0b/b5/6a17bdadd0fc1f170adfd05a20d37c832f52b117b4d9131da1f41bb097ce/pydantic_core-2.46.4-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:db06ffe51636ffe9ca531fe9023dd64bdd794be8754cb5df57c5498ae5b518a7", size = 1952146, upload-time = "2026-05-06T13:39:43.092Z" }, + { url = "https://files.pythonhosted.org/packages/2a/dc/03734d80e362cd43ef65428e9de77c730ce7f2f11c60d2b1e1b39f0fbf99/pydantic_core-2.46.4-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:133878133d271ade3d41d1bfb2a45ec38dbdbda40bc065921c6b04e4630127e2", size = 2134492, upload-time = "2026-05-06T13:36:58.124Z" }, + { url = "https://files.pythonhosted.org/packages/de/df/5e5ffc085ed07cc22d298134d3d911c63e91f6a0eb91fe646750a3209910/pydantic_core-2.46.4-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9bc519fbf2b7578398853d815009ae5e4d4603d12f4e3f91da8c06852d3da3e9", size = 2156604, upload-time = "2026-05-06T13:37:49.88Z" }, + { url = "https://files.pythonhosted.org/packages/81/44/6e112a4253e56f5705467cbab7ab5e91ee7398ba3d56d358635958893d3e/pydantic_core-2.46.4-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:c7a7bd4e39e8e4c12c39cd480356842b6a8a06e41b23a55a5e3e191718838ddf", size = 2183828, upload-time = "2026-05-06T13:37:43.053Z" }, + { url = "https://files.pythonhosted.org/packages/ac/ad/5565071e937d8e752842ac241463944c9eb14c87e2d269f2658a5bd05e98/pydantic_core-2.46.4-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:d396ec2b979760aaf3218e76c24e65bd0aca24983298653b3a9d7a45f9e47b30", size = 2310000, upload-time = "2026-05-06T13:37:56.694Z" }, + { url = "https://files.pythonhosted.org/packages/4f/c3/66883a5cec183e7fba4d024b4cbbe61851a63750ef606b0afecc46d1f2bf/pydantic_core-2.46.4-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:86e1a4418c6cd97d60c95c71164158eaf7324fae7b0923264016baa993eba6fc", size = 2361286, upload-time = "2026-05-06T13:40:05.667Z" }, + { url = "https://files.pythonhosted.org/packages/4b/2d/69abac8f838090bbecd5df894befb2c2619e7996a98ddb949db9f3b93225/pydantic_core-2.46.4-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:d51026d73fcfd93610abc7b27789c26b313920fcfb20e27462d74a7f8b06e983", size = 2193071, upload-time = "2026-05-06T13:38:08.682Z" }, +] + +[[package]] +name = "pydantic-settings" +version = "2.14.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pydantic" }, + { name = "python-dotenv" }, + { name = "typing-inspection" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5c/b5/8f48e906c3e0205276e8bd8cb7512217a87b2685304d64be27cad5b3019f/pydantic_settings-2.14.2.tar.gz", hash = "sha256:c19dd64b19097f1de80184f0cc7b0272a13ae6e170cbf240a3e27e381ed14a5f", size = 237700, upload-time = "2026-06-19T13:44:56.324Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/77/c1/6e422f34e569cf8e18df68d1939c81c099d2b61e4f7d9621c8a77560799c/pydantic_settings-2.14.2-py3-none-any.whl", hash = "sha256:a20c97b37910b6550d5ea50fbcc2d4187defe58cd57070b73863d069419c9440", size = 61715, upload-time = "2026-06-19T13:44:55.02Z" }, +] + +[[package]] +name = "pydot" +version = "4.0.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pyparsing" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/50/35/b17cb89ff865484c6a20ef46bf9d95a5f07328292578de0b295f4a6beec2/pydot-4.0.1.tar.gz", hash = "sha256:c2148f681c4a33e08bf0e26a9e5f8e4099a82e0e2a068098f32ce86577364ad5", size = 162594, upload-time = "2025-06-17T20:09:56.454Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/32/a7125fb28c4261a627f999d5fb4afff25b523800faed2c30979949d6facd/pydot-4.0.1-py3-none-any.whl", hash = "sha256:869c0efadd2708c0be1f916eb669f3d664ca684bc57ffb7ecc08e70d5e93fee6", size = 37087, upload-time = "2025-06-17T20:09:55.25Z" }, +] + +[[package]] +name = "pygments" +version = "2.20.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991, upload-time = "2026-03-29T13:29:33.898Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" }, +] + +[[package]] +name = "pyjwt" +version = "2.13.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/3b/81/58d0ac84e1ef3a3843791d6954d94c0b33d526c75eeb1efbce9d0a4c4077/pyjwt-2.13.0.tar.gz", hash = "sha256:41571c89ca91598c79e8ef18a2d07367d4810fbbd6f637794879baf1b7703423", size = 107515, upload-time = "2026-05-21T19:54:36.618Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a3/5e/ecf12fdb62546d64385c158514e9b2b671f7832108ef2ecd2020ce0af2d1/pyjwt-2.13.0-py3-none-any.whl", hash = "sha256:66adcc2aff09b3f1bbd95fc1e1577df8ac8723c978552fd43304c8a290ac5728", size = 31274, upload-time = "2026-05-21T19:54:35.362Z" }, +] + +[package.optional-dependencies] +crypto = [ + { name = "cryptography" }, +] + +[[package]] +name = "pyparsing" +version = "3.3.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f3/91/9c6ee907786a473bf81c5f53cf703ba0957b23ab84c264080fb5a450416f/pyparsing-3.3.2.tar.gz", hash = "sha256:c777f4d763f140633dcb6d8a3eda953bf7a214dc4eff598413c070bcdc117cbc", size = 6851574, upload-time = "2026-01-21T03:57:59.36Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl", hash = "sha256:850ba148bd908d7e2411587e247a1e4f0327839c40e2e5e6d05a007ecc69911d", size = 122781, upload-time = "2026-01-21T03:57:55.912Z" }, +] + +[[package]] +name = "pyproject-hooks" +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" }, +] + +[[package]] +name = "pytest" +version = "9.1.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "iniconfig" }, + { name = "packaging" }, + { name = "pluggy" }, + { name = "pygments" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e4/47/b9efed96c114afcfa3c9d3fe98a76a1d14c74a9e266d397cf6eb64be5e01/pytest-9.1.1.tar.gz", hash = "sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313", size = 1636369, upload-time = "2026-06-19T10:58:32.857Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/24/25/1de2678b631f5a49215c6c96fff41ba892b0a34df68d6d80292b1b48aa7f/pytest-9.1.1-py3-none-any.whl", hash = "sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c", size = 386536, upload-time = "2026-06-19T10:58:31.347Z" }, +] + +[[package]] +name = "pytest-asyncio" +version = "1.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pytest" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/43/7c/d36d04db312ecf4298932ef77e6e4a9e8ad017906e24e34f0b0c361a2473/pytest_asyncio-1.4.0.tar.gz", hash = "sha256:c6c0d2259945122819f171a32ecea2c349ead889ee28176caaf492143424be42", size = 58514, upload-time = "2026-05-26T09:56:04.083Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/03/e2/08a497ef684b88559c9cc5f4ad53a37e7b99e727094a86d6ea32536d5d3c/pytest_asyncio-1.4.0-py3-none-any.whl", hash = "sha256:933ca923a23075a87fb7070c0ec272a6848489824d887c85c812670932835aa1", size = 16930, upload-time = "2026-05-26T09:56:02.576Z" }, +] + +[[package]] +name = "pytest-mock" +version = "3.15.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pytest" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/68/14/eb014d26be205d38ad5ad20d9a80f7d201472e08167f0bb4361e251084a9/pytest_mock-3.15.1.tar.gz", hash = "sha256:1849a238f6f396da19762269de72cb1814ab44416fa73a8686deac10b0d87a0f", size = 34036, upload-time = "2025-09-16T16:37:27.081Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5a/cc/06253936f4a7fa2e0f48dfe6d851d9c56df896a9ab09ac019d70b760619c/pytest_mock-3.15.1-py3-none-any.whl", hash = "sha256:0a25e2eb88fe5168d535041d09a4529a188176ae608a6d249ee65abc0949630d", size = 10095, upload-time = "2025-09-16T16:37:25.734Z" }, +] + +[[package]] +name = "python-dateutil" +version = "2.9.0.post0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432, upload-time = "2024-03-01T18:36:20.211Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" }, +] + +[[package]] +name = "python-dotenv" +version = "1.2.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/82/ed/0301aeeac3e5353ef3d94b6ec08bbcabd04a72018415dcb29e588514bba8/python_dotenv-1.2.2.tar.gz", hash = "sha256:2c371a91fbd7ba082c2c1dc1f8bf89ca22564a087c2c287cd9b662adde799cf3", size = 50135, upload-time = "2026-03-01T16:00:26.196Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0b/d7/1959b9648791274998a9c3526f6d0ec8fd2233e4d4acce81bbae76b44b2a/python_dotenv-1.2.2-py3-none-any.whl", hash = "sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a", size = 22101, upload-time = "2026-03-01T16:00:25.09Z" }, +] + +[[package]] +name = "python-multipart" +version = "0.0.32" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5b/42/55c32bb9b12693c092ad250a0e82edb5b31ddeda6eb772de5f308b3804ad/python_multipart-0.0.32.tar.gz", hash = "sha256:be54b7f3fa167bb83e4fcd936b887b708f4e57fe75911c02aebf53efaf8d938e", size = 46881, upload-time = "2026-06-04T16:18:58.647Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e1/04/e8135ebd1ad02c56ec633277529b2602ff99ff634be76cdba5744cf554fd/python_multipart-0.0.32-py3-none-any.whl", hash = "sha256:ff6d3f776f16878c894e52e107296ffc890e913c611b1a4ec6c44e2821fe2e23", size = 30042, upload-time = "2026-06-04T16:18:57.319Z" }, +] + +[[package]] +name = "pytokens" +version = "0.4.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b6/34/b4e015b99031667a7b960f888889c5bd34ef585c85e1cb56a594b92836ac/pytokens-0.4.1.tar.gz", hash = "sha256:292052fe80923aae2260c073f822ceba21f3872ced9a68bb7953b348e561179a", size = 23015, upload-time = "2026-01-30T01:03:45.924Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3d/92/790ebe03f07b57e53b10884c329b9a1a308648fc083a6d4a39a10a28c8fc/pytokens-0.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d70e77c55ae8380c91c0c18dea05951482e263982911fc7410b1ffd1dadd3440", size = 160864, upload-time = "2026-01-30T01:02:57.882Z" }, + { url = "https://files.pythonhosted.org/packages/13/25/a4f555281d975bfdd1eba731450e2fe3a95870274da73fb12c40aeae7625/pytokens-0.4.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4a58d057208cb9075c144950d789511220b07636dd2e4708d5645d24de666bdc", size = 248565, upload-time = "2026-01-30T01:02:59.912Z" }, + { url = "https://files.pythonhosted.org/packages/17/50/bc0394b4ad5b1601be22fa43652173d47e4c9efbf0044c62e9a59b747c56/pytokens-0.4.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b49750419d300e2b5a3813cf229d4e5a4c728dae470bcc89867a9ad6f25a722d", size = 260824, upload-time = "2026-01-30T01:03:01.471Z" }, + { url = "https://files.pythonhosted.org/packages/4e/54/3e04f9d92a4be4fc6c80016bc396b923d2a6933ae94b5f557c939c460ee0/pytokens-0.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d9907d61f15bf7261d7e775bd5d7ee4d2930e04424bab1972591918497623a16", size = 264075, upload-time = "2026-01-30T01:03:04.143Z" }, + { url = "https://files.pythonhosted.org/packages/d1/1b/44b0326cb5470a4375f37988aea5d61b5cc52407143303015ebee94abfd6/pytokens-0.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:ee44d0f85b803321710f9239f335aafe16553b39106384cef8e6de40cb4ef2f6", size = 103323, upload-time = "2026-01-30T01:03:05.412Z" }, + { url = "https://files.pythonhosted.org/packages/41/5d/e44573011401fb82e9d51e97f1290ceb377800fb4eed650b96f4753b499c/pytokens-0.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:140709331e846b728475786df8aeb27d24f48cbcf7bcd449f8de75cae7a45083", size = 160663, upload-time = "2026-01-30T01:03:06.473Z" }, + { url = "https://files.pythonhosted.org/packages/f0/e6/5bbc3019f8e6f21d09c41f8b8654536117e5e211a85d89212d59cbdab381/pytokens-0.4.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6d6c4268598f762bc8e91f5dbf2ab2f61f7b95bdc07953b602db879b3c8c18e1", size = 255626, upload-time = "2026-01-30T01:03:08.177Z" }, + { url = "https://files.pythonhosted.org/packages/bf/3c/2d5297d82286f6f3d92770289fd439956b201c0a4fc7e72efb9b2293758e/pytokens-0.4.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:24afde1f53d95348b5a0eb19488661147285ca4dd7ed752bbc3e1c6242a304d1", size = 269779, upload-time = "2026-01-30T01:03:09.756Z" }, + { url = "https://files.pythonhosted.org/packages/20/01/7436e9ad693cebda0551203e0bf28f7669976c60ad07d6402098208476de/pytokens-0.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5ad948d085ed6c16413eb5fec6b3e02fa00dc29a2534f088d3302c47eb59adf9", size = 268076, upload-time = "2026-01-30T01:03:10.957Z" }, + { url = "https://files.pythonhosted.org/packages/2e/df/533c82a3c752ba13ae7ef238b7f8cdd272cf1475f03c63ac6cf3fcfb00b6/pytokens-0.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:3f901fe783e06e48e8cbdc82d631fca8f118333798193e026a50ce1b3757ea68", size = 103552, upload-time = "2026-01-30T01:03:12.066Z" }, + { url = "https://files.pythonhosted.org/packages/cb/dc/08b1a080372afda3cceb4f3c0a7ba2bde9d6a5241f1edb02a22a019ee147/pytokens-0.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8bdb9d0ce90cbf99c525e75a2fa415144fd570a1ba987380190e8b786bc6ef9b", size = 160720, upload-time = "2026-01-30T01:03:13.843Z" }, + { url = "https://files.pythonhosted.org/packages/64/0c/41ea22205da480837a700e395507e6a24425151dfb7ead73343d6e2d7ffe/pytokens-0.4.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5502408cab1cb18e128570f8d598981c68a50d0cbd7c61312a90507cd3a1276f", size = 254204, upload-time = "2026-01-30T01:03:14.886Z" }, + { url = "https://files.pythonhosted.org/packages/e0/d2/afe5c7f8607018beb99971489dbb846508f1b8f351fcefc225fcf4b2adc0/pytokens-0.4.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:29d1d8fb1030af4d231789959f21821ab6325e463f0503a61d204343c9b355d1", size = 268423, upload-time = "2026-01-30T01:03:15.936Z" }, + { url = "https://files.pythonhosted.org/packages/68/d4/00ffdbd370410c04e9591da9220a68dc1693ef7499173eb3e30d06e05ed1/pytokens-0.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:970b08dd6b86058b6dc07efe9e98414f5102974716232d10f32ff39701e841c4", size = 266859, upload-time = "2026-01-30T01:03:17.458Z" }, + { url = "https://files.pythonhosted.org/packages/a7/c9/c3161313b4ca0c601eeefabd3d3b576edaa9afdefd32da97210700e47652/pytokens-0.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:9bd7d7f544d362576be74f9d5901a22f317efc20046efe2034dced238cbbfe78", size = 103520, upload-time = "2026-01-30T01:03:18.652Z" }, + { url = "https://files.pythonhosted.org/packages/8f/a7/b470f672e6fc5fee0a01d9e75005a0e617e162381974213a945fcd274843/pytokens-0.4.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:4a14d5f5fc78ce85e426aa159489e2d5961acf0e47575e08f35584009178e321", size = 160821, upload-time = "2026-01-30T01:03:19.684Z" }, + { url = "https://files.pythonhosted.org/packages/80/98/e83a36fe8d170c911f864bfded690d2542bfcfacb9c649d11a9e6eb9dc41/pytokens-0.4.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:97f50fd18543be72da51dd505e2ed20d2228c74e0464e4262e4899797803d7fa", size = 254263, upload-time = "2026-01-30T01:03:20.834Z" }, + { url = "https://files.pythonhosted.org/packages/0f/95/70d7041273890f9f97a24234c00b746e8da86df462620194cef1d411ddeb/pytokens-0.4.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dc74c035f9bfca0255c1af77ddd2d6ae8419012805453e4b0e7513e17904545d", size = 268071, upload-time = "2026-01-30T01:03:21.888Z" }, + { url = "https://files.pythonhosted.org/packages/da/79/76e6d09ae19c99404656d7db9c35dfd20f2086f3eb6ecb496b5b31163bad/pytokens-0.4.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:f66a6bbe741bd431f6d741e617e0f39ec7257ca1f89089593479347cc4d13324", size = 271716, upload-time = "2026-01-30T01:03:23.633Z" }, + { url = "https://files.pythonhosted.org/packages/79/37/482e55fa1602e0a7ff012661d8c946bafdc05e480ea5a32f4f7e336d4aa9/pytokens-0.4.1-cp314-cp314-win_amd64.whl", hash = "sha256:b35d7e5ad269804f6697727702da3c517bb8a5228afa450ab0fa787732055fc9", size = 104539, upload-time = "2026-01-30T01:03:24.788Z" }, + { url = "https://files.pythonhosted.org/packages/30/e8/20e7db907c23f3d63b0be3b8a4fd1927f6da2395f5bcc7f72242bb963dfe/pytokens-0.4.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:8fcb9ba3709ff77e77f1c7022ff11d13553f3c30299a9fe246a166903e9091eb", size = 168474, upload-time = "2026-01-30T01:03:26.428Z" }, + { url = "https://files.pythonhosted.org/packages/d6/81/88a95ee9fafdd8f5f3452107748fd04c24930d500b9aba9738f3ade642cc/pytokens-0.4.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:79fc6b8699564e1f9b521582c35435f1bd32dd06822322ec44afdeba666d8cb3", size = 290473, upload-time = "2026-01-30T01:03:27.415Z" }, + { url = "https://files.pythonhosted.org/packages/cf/35/3aa899645e29b6375b4aed9f8d21df219e7c958c4c186b465e42ee0a06bf/pytokens-0.4.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d31b97b3de0f61571a124a00ffe9a81fb9939146c122c11060725bd5aea79975", size = 303485, upload-time = "2026-01-30T01:03:28.558Z" }, + { url = "https://files.pythonhosted.org/packages/52/a0/07907b6ff512674d9b201859f7d212298c44933633c946703a20c25e9d81/pytokens-0.4.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:967cf6e3fd4adf7de8fc73cd3043754ae79c36475c1c11d514fc72cf5490094a", size = 306698, upload-time = "2026-01-30T01:03:29.653Z" }, + { url = "https://files.pythonhosted.org/packages/39/2a/cbbf9250020a4a8dd53ba83a46c097b69e5eb49dd14e708f496f548c6612/pytokens-0.4.1-cp314-cp314t-win_amd64.whl", hash = "sha256:584c80c24b078eec1e227079d56dc22ff755e0ba8654d8383b2c549107528918", size = 116287, upload-time = "2026-01-30T01:03:30.912Z" }, + { url = "https://files.pythonhosted.org/packages/c6/78/397db326746f0a342855b81216ae1f0a32965deccfd7c830a2dbc66d2483/pytokens-0.4.1-py3-none-any.whl", hash = "sha256:26cef14744a8385f35d0e095dc8b3a7583f6c953c2e3d269c7f82484bf5ad2de", size = 13729, upload-time = "2026-01-30T01:03:45.029Z" }, +] + +[[package]] +name = "pywin32" +version = "312" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1f/f5/10a6e845a00fc5e7afd0a988b744f403d4d57162a28d160a093c4d9322f0/pywin32-312-cp311-cp311-win32.whl", hash = "sha256:17948aeadbdb091f0ced6ef0841620794e68327b94ee415571c1203594b7215c", size = 6362659, upload-time = "2026-06-04T07:49:21.349Z" }, + { url = "https://files.pythonhosted.org/packages/35/c4/dcd2d62b5944b6d5db53413a5899016ccd57ffcb7278f3f81655d25d2027/pywin32-312-cp311-cp311-win_amd64.whl", hash = "sha256:d11417d84412f859b722fad0841b3614459ed0047f7542d8362e77884f6b6e8a", size = 6928825, upload-time = "2026-06-04T07:49:23.934Z" }, + { url = "https://files.pythonhosted.org/packages/b7/56/3cbb433fe4501cdba2eb9040f56a4e1a8243faa4186b25295564d1a7a79d/pywin32-312-cp311-cp311-win_arm64.whl", hash = "sha256:b2200a054ca6d6625c4842fc56a4976a4b47f96b73dbe5538c3f813a80359f47", size = 6721875, upload-time = "2026-06-04T07:49:26.416Z" }, + { url = "https://files.pythonhosted.org/packages/83/ff/32aa7d2ed0ab12b323aaa64f9b75e6ad4f8fd09f9ccfc28c79414d46838d/pywin32-312-cp312-cp312-win32.whl", hash = "sha256:dab4f65ac9c4e48400a2a0530c46c3c579cd5905ecd11b80692373915269208b", size = 6371877, upload-time = "2026-06-04T07:49:28.836Z" }, + { url = "https://files.pythonhosted.org/packages/03/d9/77040d3b43df3f3be32ea289433d660d2727f5ba327bc73be835127d9d60/pywin32-312-cp312-cp312-win_amd64.whl", hash = "sha256:b457f6d628a47e8a7346ce22acb7e1a46a4a78b52e1d17e1af56871bd19a93bc", size = 6914841, upload-time = "2026-06-04T07:49:31.85Z" }, + { url = "https://files.pythonhosted.org/packages/e3/cc/7b1ec671775756020a0ee7f4feeaf3c568f0ab86bd3900088cf986937a92/pywin32-312-cp312-cp312-win_arm64.whl", hash = "sha256:6017c58e12f6809fbb0555b75df144c2922a9ffd18e4b9b5afa863b6c1a9d950", size = 6727901, upload-time = "2026-06-04T07:49:34.244Z" }, + { url = "https://files.pythonhosted.org/packages/2d/41/12fbfd7f36ed2146d8bc9de96c2741296bf0d490b98508496cff322e274c/pywin32-312-cp313-cp313-win32.whl", hash = "sha256:7a27df850933d16a8eabfbaeb73d52b273e2da667f80d70b01a89d1f6828d02c", size = 6370184, upload-time = "2026-06-04T07:49:36.253Z" }, + { url = "https://files.pythonhosted.org/packages/ba/db/36a78e3403099d31d9746d13fdcde5accc43c1155f375a34d15983a479a7/pywin32-312-cp313-cp313-win_amd64.whl", hash = "sha256:c53e878d15a1c44788082bfe712a905433473aa38f86375b7cf8b45e3acbaaf9", size = 6914298, upload-time = "2026-06-04T07:49:38.876Z" }, + { url = "https://files.pythonhosted.org/packages/84/37/c1697194092b76de9ed47ca124323f02c57ffc8a45c06f88a3d5acaf01eb/pywin32-312-cp313-cp313-win_arm64.whl", hash = "sha256:59aba5d5940842075343a5ddc6b11f1cdf0d1567fe745290359dfbcc7c2eb831", size = 6727640, upload-time = "2026-06-04T07:49:41.083Z" }, + { url = "https://files.pythonhosted.org/packages/fc/2b/1f3cded5822fd49c02f40544cbb5f58c7cfd6b1694869fd476cb6170ee97/pywin32-312-cp314-cp314-win32.whl", hash = "sha256:a77a90fbb6881238d2ca9c6fd797b25817f3768fe78d214a90137ff055a75f5b", size = 6468928, upload-time = "2026-06-04T07:49:43.188Z" }, + { url = "https://files.pythonhosted.org/packages/21/82/3bf86d2e2808902013132e1ce905a7da0da53790f3836c64bf44d55e24f3/pywin32-312-cp314-cp314-win_amd64.whl", hash = "sha256:a4dd3a848290ef724347b19f301045831d8e802fa4464f491b98b1e0a081432e", size = 7024157, upload-time = "2026-06-04T07:49:45.34Z" }, + { url = "https://files.pythonhosted.org/packages/a4/0e/73f6d6800b4f27655abd9e9f6aaeaefcddb2b946e4674efa2bab184a7f7b/pywin32-312-cp314-cp314-win_arm64.whl", hash = "sha256:9fce94568364e0155e6dfb781ac5d95903be8baf28670632beab1b523f300daa", size = 6839598, upload-time = "2026-06-04T07:49:47.613Z" }, + { url = "https://files.pythonhosted.org/packages/eb/61/caa39686032d2ebdd04ff0ab5cbe163126c0066d98e00c9018646e42393b/pywin32-312-cp315-cp315-win32.whl", hash = "sha256:5c1fbe4a937a73ae9297384a3da38518cbc694c68ad8a809b2e19acd350f03ed", size = 6471159, upload-time = "2026-06-04T07:49:50.035Z" }, + { url = "https://files.pythonhosted.org/packages/0f/cd/7e1de64a4a6f69c04214169657ccab0d93a670ea50e35eb8f489d7378249/pywin32-312-cp315-cp315-win_amd64.whl", hash = "sha256:c2f03a0f73f804a13c2735b99392b0cd426bb4f2c4d0178e5ac966a0f21618d5", size = 7025293, upload-time = "2026-06-04T07:49:54.857Z" }, + { url = "https://files.pythonhosted.org/packages/23/ed/4532e9388e65fa16b46776ef47ad631a64eda1631884488af707666350ed/pywin32-312-cp315-cp315-win_arm64.whl", hash = "sha256:a8597d28f267b39074aef51fa593530082b39cbe5a074226096857b1fed2dfb9", size = 6840337, upload-time = "2026-06-04T07:49:57.531Z" }, +] + +[[package]] +name = "pywin32-ctypes" +version = "0.2.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/85/9f/01a1a99704853cb63f253eea009390c88e7131c67e66a0a02099a8c917cb/pywin32-ctypes-0.2.3.tar.gz", hash = "sha256:d162dc04946d704503b2edc4d55f3dba5c1d539ead017afa00142c38b9885755", size = 29471, upload-time = "2024-08-14T10:15:34.626Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/de/3d/8161f7711c017e01ac9f008dfddd9410dff3674334c233bde66e7ba65bbf/pywin32_ctypes-0.2.3-py3-none-any.whl", hash = "sha256:8a1513379d709975552d202d942d9837758905c8d01eb82b8bcc30918929e7b8", size = 30756, upload-time = "2024-08-14T10:15:33.187Z" }, +] + +[[package]] +name = "pyyaml" +version = "6.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/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]] +name = "readme-renderer" +version = "45.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "docutils" }, + { name = "nh3" }, + { name = "pygments" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/02/51/d3a6ea424652c60f05600d8c2e01a55c913755e7cdad64afabbd1aa16f44/readme_renderer-45.0.tar.gz", hash = "sha256:030a8fac74904f8fba11ad1bb6964e3f76e896dc7e5e71f16af190c9056696d1", size = 36172, upload-time = "2026-06-09T21:05:17.37Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/97/1b/295bf2fa3e740131778065e5ffa2c481f0e7210182d408e9a2c244ff5b0c/readme_renderer-45.0-py3-none-any.whl", hash = "sha256:3385ed220117104a2bceb4a9dac8c5fdf6d1f96890d7ea2a9c7174fd5c84091f", size = 14134, upload-time = "2026-06-09T21:05:15.85Z" }, +] + +[[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'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/22/f5/df4e9027acead3ecc63e50fe1e36aca1523e1719559c499951bb4b53188f/referencing-0.37.0.tar.gz", hash = "sha256:44aefc3142c5b842538163acb373e24cce6632bd54bdb01b21ad5863489f50d8", size = 78036, upload-time = "2025-10-13T15:30:48.871Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2c/58/ca301544e1fa93ed4f80d724bf5b194f6e4b945841c5bfd555878eea9fcb/referencing-0.37.0-py3-none-any.whl", hash = "sha256:381329a9f99628c9069361716891d34ad94af76e461dcb0335825aecc7692231", size = 26766, upload-time = "2025-10-13T15:30:47.625Z" }, +] + +[[package]] +name = "regex" +version = "2026.6.28" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f1/05/e4f219230e11e774a6c9987d2ab0d0c6b8573e13a17e143d0015bee710ef/regex-2026.6.28.tar.gz", hash = "sha256:3cb4b6c5cb3060cc31efdc1fbb27c25fb9b29044afd87e40601a1c4d9db54342", size = 416101, upload-time = "2026-06-28T19:56:55.302Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/72/db/9051b36294bdbabaa9c7db57db0fbcdfbd17f7a106c539bb423d0323faea/regex-2026.6.28-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a71b51dd08b9b62f055fafab3dee8af8bd2ec81b373a44caef18d6c5ca28f43a", size = 489481, upload-time = "2026-06-28T19:53:36.684Z" }, + { url = "https://files.pythonhosted.org/packages/35/3f/24097a3c3ff30f9a639888900faaecabcf5f54a5bc9c851c297e11b349ef/regex-2026.6.28-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9c26a47770d30a0f85c01e261d2a3ebc342c4af6fd666dbd8c1fe4cbf3adf726", size = 291292, upload-time = "2026-06-28T19:53:38.39Z" }, + { url = "https://files.pythonhosted.org/packages/5e/cc/e0d762a189cfb4e8926d16e691720690d139a977b38fdb80230c259332ab/regex-2026.6.28-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e5efbc1af38f97e300d43028e5a92e752d924bcfb7f465d8669d5d5a6e78c233", size = 289232, upload-time = "2026-06-28T19:53:40.181Z" }, + { url = "https://files.pythonhosted.org/packages/4b/c8/ca0ac7f09cc88ca61e0c61c53f7db29334f660ffba5d0b52378e7c44723c/regex-2026.6.28-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f1758df6fdd8c800620a5638958720e8a635e1da49a2f09df2dd63e94a24ec4a", size = 792332, upload-time = "2026-06-28T19:53:41.782Z" }, + { url = "https://files.pythonhosted.org/packages/8e/92/04ae94cbe0dd1f478b2aef6c46f995bb6946d3e338d4b28605478b66a2b7/regex-2026.6.28-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ad73ecf20c1ef5c975639f8bf845a9370fcf7dada7edc1e3b0bca20e2f8202f6", size = 861743, upload-time = "2026-06-28T19:53:43.261Z" }, + { url = "https://files.pythonhosted.org/packages/4c/ec/024d7638c807679ff8a0e6081d01d66c7762339af1cac71e45911587ff9a/regex-2026.6.28-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4d80c798b0eec6ea3d45f8816a1e8886c5664615d347d89e8c075b576a1b5a5d", size = 906481, upload-time = "2026-06-28T19:53:44.948Z" }, + { url = "https://files.pythonhosted.org/packages/cd/fd/93bfe5af45f0be4fa8983945455c0e6924e1aeb879cde227958869c1e71c/regex-2026.6.28-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a361feeaf1b6ba1df060f2ff5c5947092edf537a35ce78e76387ac56d3e0f4a4", size = 799867, upload-time = "2026-06-28T19:53:46.997Z" }, + { url = "https://files.pythonhosted.org/packages/ee/fd/e5d965d41f2398c8ce0f37a4652f03bb297fd009bb796d390134225dda12/regex-2026.6.28-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:8b92366d9c8bba9642989534073662abdd9b41faf7603a7ae71597833f3b88f0", size = 773632, upload-time = "2026-06-28T19:53:48.892Z" }, + { url = "https://files.pythonhosted.org/packages/eb/d9/ff39afaec92b9ee2dba0302a4783976005091681069808938c31cf8df3b6/regex-2026.6.28-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:11251768cc23f097dd61b18f67966e70f74da822784d17e12a444eb6b29d4288", size = 781669, upload-time = "2026-06-28T19:53:50.693Z" }, + { url = "https://files.pythonhosted.org/packages/45/4e/e2fd4bb8228e10c24af2d7ff867182372190e498eab9fd29cbe54c403c95/regex-2026.6.28-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:ad5c67786145ec28a71a267d9f9d92bdc8d70d65541eea852c253f520a01f918", size = 854497, upload-time = "2026-06-28T19:53:52.323Z" }, + { url = "https://files.pythonhosted.org/packages/72/7c/f0340384a973082979064156d05f3d2cc1dced7371efcd7a1b45726a1a8a/regex-2026.6.28-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:f1da438e739765c3e85175ede05816cbede3caaacb1e0680568bda6119bfdfca", size = 763335, upload-time = "2026-06-28T19:53:54.024Z" }, + { url = "https://files.pythonhosted.org/packages/e1/32/90ce0d0898e205506cc22b9c81cfb16b722e06ca5f50fad51c053c2a727b/regex-2026.6.28-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:d98b639046e51c5de64d9f77351532105e99ca271cb6f7640e1f903d6ab63032", size = 844615, upload-time = "2026-06-28T19:53:56.216Z" }, + { url = "https://files.pythonhosted.org/packages/6a/ef/55abb149599dce1ade687170557129524011eeb3d92afe02429cea7754a2/regex-2026.6.28-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1e164ace4dbab5c6ad4a4ac7c41a2638fe226d0c770a86f2eb041f594bac6ee7", size = 789193, upload-time = "2026-06-28T19:53:57.791Z" }, + { url = "https://files.pythonhosted.org/packages/f8/ea/cf7f6f6f152e52fdad978b913bf24c14df647eca0f81ef31f3aee0be8982/regex-2026.6.28-cp311-cp311-win32.whl", hash = "sha256:3169a3159e4d99d9ae85ff0ed90ef3b8906cc3152653b6078b842ace6c8f72c3", size = 266731, upload-time = "2026-06-28T19:53:59.938Z" }, + { url = "https://files.pythonhosted.org/packages/c6/cf/a48d8e8d406b22481cad146f48fa0dfca3c5f402b91f26d8e5a0fe4f513d/regex-2026.6.28-cp311-cp311-win_amd64.whl", hash = "sha256:5977295b0a74e8241df8a4b3b27b12412a831f6fa32ee8b755039592cd768c3d", size = 277918, upload-time = "2026-06-28T19:54:01.502Z" }, + { url = "https://files.pythonhosted.org/packages/89/b2/a222392207db7ed86281a732a99f7cf7f2bb35d332799e892b8510be000e/regex-2026.6.28-cp311-cp311-win_arm64.whl", hash = "sha256:f5fbaef40c3e9282ccee4b075f5600a0d858aa0c34147732f1baa69c8188a95d", size = 276876, upload-time = "2026-06-28T19:54:03.411Z" }, + { url = "https://files.pythonhosted.org/packages/da/21/44aa415873032056c43eac21c67285deb2cf66cddb2a964c3cdc8f803efc/regex-2026.6.28-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:81cc5793ad33a10444445e8d29d3c73e752c8fb2e120772d70fcb6d41df40fe1", size = 490480, upload-time = "2026-06-28T19:54:05.392Z" }, + { url = "https://files.pythonhosted.org/packages/8b/5f/30d4116093c2128099f78b6990dfc1698fdbf3ee528f1e1c647378034c79/regex-2026.6.28-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:e18225243250a1f7d7e5e5d883f3b96465cd79031acf5c6db902b7025f2125d9", size = 292137, upload-time = "2026-06-28T19:54:07.088Z" }, + { url = "https://files.pythonhosted.org/packages/cb/0e/ca20a0e0de49837e6337603a91ab77556aa27033ac5b975615d98698cfb3/regex-2026.6.28-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ecd1638b1c2db1f2d01c182a4b0d3e2e88b0e99910320a745c1727ee3638ddab", size = 289623, upload-time = "2026-06-28T19:54:08.762Z" }, + { url = "https://files.pythonhosted.org/packages/50/11/c013422a7e2c59946df8ac93e792a4922c98287f2a2181341603c78a5d98/regex-2026.6.28-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4303ebe16b74eeb3fe2715745023266fea92fd44a23f3e7bb2fb48c7a7bbc195", size = 796756, upload-time = "2026-06-28T19:54:10.616Z" }, + { url = "https://files.pythonhosted.org/packages/b0/95/1309645a0e1ee6fb91d954501da57a0b33d50ad2a9acb313702851a7054e/regex-2026.6.28-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:56b856b70b96c381d837f609eee442a1bd320cd2159f5c294b679552fb1a7eaf", size = 865465, upload-time = "2026-06-28T19:54:12.742Z" }, + { url = "https://files.pythonhosted.org/packages/20/06/491802db47c6f5e2904ffa2518ad3ac27fe6bbf5a66d73210a95cc080d47/regex-2026.6.28-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f74675ab76ab1d005ffba4dee308e53e89efc22be6e9f9fae5b539a3f81bdff2", size = 912350, upload-time = "2026-06-28T19:54:14.508Z" }, + { url = "https://files.pythonhosted.org/packages/5e/60/3ba57840bcc7e2367090360de0c15a5ba6ad22be89314251105f2e943f43/regex-2026.6.28-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:90581684565a93f7258af1e5d3f41ef20d7d7c61f2a428183a342bcb65485e38", size = 801261, upload-time = "2026-06-28T19:54:16.432Z" }, + { url = "https://files.pythonhosted.org/packages/eb/27/af1eb74e9a78c782b3e450b611a595e44906da8a5107e1227f4a7fd0480b/regex-2026.6.28-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:28f9e6c28f9b90f6f784595a33240a57e181e61b6ee3dc259b25c61e356d1aa3", size = 777072, upload-time = "2026-06-28T19:54:18.128Z" }, + { url = "https://files.pythonhosted.org/packages/20/18/fdd4c883a39e3ed00d669062af1135809bfd3281bf528150849fbd68825b/regex-2026.6.28-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:378a71d861fc7c8806b04ac5b133d53c0e774f92f5d9663a539872d3fa2b0417", size = 785119, upload-time = "2026-06-28T19:54:20.314Z" }, + { url = "https://files.pythonhosted.org/packages/1c/79/0aabe34b8482dcadf64355f70f96e22eba5ec6c1efb33563f89654f4061c/regex-2026.6.28-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:4cc199874ecd6267a49b111052250825bfe19b5101b23b2ba80f54efa3e0994e", size = 860118, upload-time = "2026-06-28T19:54:22.368Z" }, + { url = "https://files.pythonhosted.org/packages/a8/2c/c973323306a27c9db7d160e9584eb7e0ece2a96224ccb0d39060558b31f9/regex-2026.6.28-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:b916a10431494ef4b4d62c6c89cab6426af7873125b8cd6c15811bf5fc58eec8", size = 765786, upload-time = "2026-06-28T19:54:24.265Z" }, + { url = "https://files.pythonhosted.org/packages/e3/df/9ca3e378e352242a4cb45573a5e9162c3ee791507702a23966fa559e36b5/regex-2026.6.28-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:2e27727fba075f1e4409416d2f537d4c30fc11f012ea507f7bd74d3e19ecb57a", size = 852120, upload-time = "2026-06-28T19:54:25.972Z" }, + { url = "https://files.pythonhosted.org/packages/a2/3e/3e31e255c4971f53cbce6306b5e3c76cbd3735a54f419bb3b2f194e9f68c/regex-2026.6.28-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:700fc6a7844bb2c4149292ac79d1df8841a00acd4d45cd32c1ebc7bcc1fd0da8", size = 789503, upload-time = "2026-06-28T19:54:27.678Z" }, + { url = "https://files.pythonhosted.org/packages/72/01/d36561c21c3033d7eeb31d51b491916817de7861acefccc5fc9db8a5037c/regex-2026.6.28-cp312-cp312-win32.whl", hash = "sha256:03376d60b6a11aecb88a79fa2be06b40faa01c6693bc31ef69435cd4818b9463", size = 267109, upload-time = "2026-06-28T19:54:29.316Z" }, + { url = "https://files.pythonhosted.org/packages/a0/59/bbbb0591f38b18c65977cd65ce64749eba1c1996c99ac04e900fc30c0dcb/regex-2026.6.28-cp312-cp312-win_amd64.whl", hash = "sha256:fbd2ded482bf99e6651992bbfcde460272724d4bbc49ef3d6b46d9312867ec84", size = 277711, upload-time = "2026-06-28T19:54:31.143Z" }, + { url = "https://files.pythonhosted.org/packages/86/06/be4f6b337d773ae5739a1bc238f97c16926e72017243735853c030f4c628/regex-2026.6.28-cp312-cp312-win_arm64.whl", hash = "sha256:37294d3d7ddb64c7e89184b2894e0f8f0a19c514bc59513d71fe692c3a8d5fc6", size = 277022, upload-time = "2026-06-28T19:54:32.97Z" }, + { url = "https://files.pythonhosted.org/packages/b6/53/d5c1b3cc0b5a0c985563ad6fac93d73ff2b300cb84342d89f044625d6bc7/regex-2026.6.28-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:b295a83426e0e44e9e60fde99789e181bd26788a1890ae7fe2a24c69bb6246ca", size = 490329, upload-time = "2026-06-28T19:54:35.775Z" }, + { url = "https://files.pythonhosted.org/packages/8d/9f/0c3503e819e91ca0e7a901a8e989ebf840ac7c7aea20b1fc7f31b6759f77/regex-2026.6.28-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0c31665c0deb5c111557a1cac8c27bd5629e2f9e7fd5058900a03576c33b601c", size = 292039, upload-time = "2026-06-28T19:54:37.977Z" }, + { url = "https://files.pythonhosted.org/packages/bb/7f/cd004e13fcad23b3794a82307dfd222e6365eb7f598bd3caab148a830bff/regex-2026.6.28-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6bf295f2c59de77d1ea7de053607ae4dc9ceb3d57bbb6c7ec51ef4acc4ccff94", size = 289488, upload-time = "2026-06-28T19:54:39.545Z" }, + { url = "https://files.pythonhosted.org/packages/73/4c/293fb34586fbcdc47eac436069e9c11f71fae5dadfd4889b475d7d2e5f7a/regex-2026.6.28-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:17c077586770f67e05bbffeba07fbee6b2b22244f4d4caf8d94e59d574befe04", size = 796772, upload-time = "2026-06-28T19:54:41.347Z" }, + { url = "https://files.pythonhosted.org/packages/92/fa/c0cd1a90b7d12d9dc155cfc8bdea8df9720988ea5b07e8fa1eccbd0ab2dd/regex-2026.6.28-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:0e6cb5a61486f9062397d2e189573b39d38ecfaed698fd9fb6e2756a8ebb8762", size = 865467, upload-time = "2026-06-28T19:54:43.485Z" }, + { url = "https://files.pythonhosted.org/packages/4e/db/0b479973046d005a1eaea299d5d536aeecb9488a16d9cbb8286338102e2d/regex-2026.6.28-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e86e91a2664f44c3a4e363a7d78fb17c27d5046882e30ea5a877f5e89b28d2ba", size = 912345, upload-time = "2026-06-28T19:54:46.091Z" }, + { url = "https://files.pythonhosted.org/packages/5b/5b/d65adfbd02f32212431bca1f06d1e2eb763a20b12978b454bafaf23dacb7/regex-2026.6.28-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4dfd1331c49233998d84fc5f1f4436cf7a435a7655f6cf0f490229bb5c7254e5", size = 801291, upload-time = "2026-06-28T19:54:48.3Z" }, + { url = "https://files.pythonhosted.org/packages/fc/09/2103686defaf9a0a31c1663782359d5b45f42524c64cca681f5481e44a5e/regex-2026.6.28-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cadea12805a1bce0b091c302b814207be26fb60a9c0e7f9ad2f9e21790a429fe", size = 777106, upload-time = "2026-06-28T19:54:50.326Z" }, + { url = "https://files.pythonhosted.org/packages/85/5a/b57593c0aa23ed269ec332fbcf07852abcb6b746e811d9464e0d09b4e25f/regex-2026.6.28-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5f2c1682b67ad5d2376498f2a5a2a8f782fa2e4a06d0465b5e357799806e8a20", size = 785175, upload-time = "2026-06-28T19:54:52.172Z" }, + { url = "https://files.pythonhosted.org/packages/79/59/c36e756ad29bf14d7b6c6d7138952476b21f6160286cedb98ac13481c993/regex-2026.6.28-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:64e142eb55e84868087da1375d7c36ff97d55010951849f515322a91d5fef1b4", size = 860186, upload-time = "2026-06-28T19:54:54.11Z" }, + { url = "https://files.pythonhosted.org/packages/61/66/49808aea0da9649c300139360708fb91b7144be1f962fcebf96755fde948/regex-2026.6.28-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:abb4daabe7be63273787a62dfd6164dadf8f7a63fbec3d2730e5e5e7126d858c", size = 765754, upload-time = "2026-06-28T19:54:56.04Z" }, + { url = "https://files.pythonhosted.org/packages/be/c5/52bbd436cf2200decdf48825fa38363eaaeebb77011ea9928a1ef9e0b9f2/regex-2026.6.28-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:ec2b2ad00ab8c16a2798cc8db80c53c4d5b8b3a2441f6cbaef06625f5ca25854", size = 852085, upload-time = "2026-06-28T19:54:57.988Z" }, + { url = "https://files.pythonhosted.org/packages/f9/c3/0390b66e3019497143fe768b3ba567b64d8b24f3812d09506deb86f4a0f0/regex-2026.6.28-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:bfc9677982c914d9085b8e1c3b3ae6e88f139fb56531c2416d6c8f338093c22b", size = 789600, upload-time = "2026-06-28T19:54:59.977Z" }, + { url = "https://files.pythonhosted.org/packages/88/fd/ab5b03653a244975069fed93d73f4f5f7484c03a84cedb238292510d7182/regex-2026.6.28-cp313-cp313-win32.whl", hash = "sha256:bf54bc693fc4e0530e666ba5ec4bcba14dbe8f66b7cfc15c27317d1a6e40b9a5", size = 267088, upload-time = "2026-06-28T19:55:02.159Z" }, + { url = "https://files.pythonhosted.org/packages/68/55/21022f7d3143210ae8d4ff905c45306237b657375cc0b97883f49db3d423/regex-2026.6.28-cp313-cp313-win_amd64.whl", hash = "sha256:e128feaf65bf3d9eb91bec92322a8f7e4835e9c798f3e9ea4b69f4def85620e3", size = 277680, upload-time = "2026-06-28T19:55:04.185Z" }, + { url = "https://files.pythonhosted.org/packages/b6/99/7f664804f1aef924542b0b233996b78b3e4d0a52d9951358aac99f129f51/regex-2026.6.28-cp313-cp313-win_arm64.whl", hash = "sha256:695873e0ea8d3815ea9e92e2c68faf039cc450e2c0a62a31afe2049eb11be767", size = 277017, upload-time = "2026-06-28T19:55:06.29Z" }, + { url = "https://files.pythonhosted.org/packages/cb/e1/9eb83518e159d719fd681c4932dc2aaff855ce72451e1d05d69466f25a96/regex-2026.6.28-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:189dbf9fc4252d9f1352bf4bd1bef885edb6cc4b7341df202a65f821aaa3891c", size = 494195, upload-time = "2026-06-28T19:55:08.292Z" }, + { url = "https://files.pythonhosted.org/packages/fd/e2/e259c5f2f7be269d0e2fb54275c1fa6a13fb47019f389c3f3ae457447825/regex-2026.6.28-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:9277a4c6503390aa39cb4483b87ec0384faee0850a23b5cea33d008b5d8d83f1", size = 293976, upload-time = "2026-06-28T19:55:10.014Z" }, + { url = "https://files.pythonhosted.org/packages/8d/4e/9bdf444014d22b045d0c82ca114fac7e07a597b5b5331b7c4ce6328426e2/regex-2026.6.28-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:17eddca4e8ea9af0b5739314776cdf0172a49731ab61f2e1ea66e066ddd46c97", size = 292340, upload-time = "2026-06-28T19:55:11.88Z" }, + { url = "https://files.pythonhosted.org/packages/fd/3a/f49b11e59cbfe187ace0053a460bd72a0169b8cd52e7db9421a074ce7a43/regex-2026.6.28-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e4466b8641e00c697aab5a73150150d2b2ea96b131c595691f42031abafd9f4d", size = 811704, upload-time = "2026-06-28T19:55:13.612Z" }, + { url = "https://files.pythonhosted.org/packages/2f/fb/ad04c39e149bf8b6cf357df5fff78341733ec366780a00c803a36735818c/regex-2026.6.28-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9cfcd4b0bdcf768c498415c170d1ed2a25a99bf0b65fa253bbd02f68ceba6475", size = 871157, upload-time = "2026-06-28T19:55:15.797Z" }, + { url = "https://files.pythonhosted.org/packages/7f/64/0e5ba31c11eb8ef7aac19a690c1211fc9aa9990caf09565785ebb0081b9a/regex-2026.6.28-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:80c7adf1ef647f6b1e8aa2ca280e517174cd08bdf7a2e412cdfb68bd6a0917cb", size = 917287, upload-time = "2026-06-28T19:55:18.692Z" }, + { url = "https://files.pythonhosted.org/packages/11/75/6b78df2b858c2fcbbc4858fdc3f2975cf2703be374b2842db7d2c32591a7/regex-2026.6.28-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a043f5770e82283a22aed4cefef1a4e0f9dd8fd7184cb6ce0ad2e579e2134a9e", size = 816333, upload-time = "2026-06-28T19:55:20.973Z" }, + { url = "https://files.pythonhosted.org/packages/b4/01/ecfe665a3694d5eda9f3ec686c856438ada0943947b6005e90556a1e2cdf/regex-2026.6.28-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3bd630a8dba06b55254ea5ee862194edab52ec783100d2ef1cd15a9c512fee27", size = 785518, upload-time = "2026-06-28T19:55:23.003Z" }, + { url = "https://files.pythonhosted.org/packages/b4/0a/88f9cd88ff1e82881605c4ffd62d77ee67d051232cfe6f8e9a64b86cf0e8/regex-2026.6.28-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b77207e3cee13086f1906a6a2a12b41244c577e8ad9370d4b35ae1d548d354f3", size = 801371, upload-time = "2026-06-28T19:55:24.888Z" }, + { url = "https://files.pythonhosted.org/packages/a8/97/601483732f93275482ceb9fed57813dfed7c47d3a019db6ec4a3bb6e23e0/regex-2026.6.28-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:6de82c268e5d101ee9e3ffd869924aa9a371e3a21e752cf4fa17b6ce50d219f7", size = 866517, upload-time = "2026-06-28T19:55:27.232Z" }, + { url = "https://files.pythonhosted.org/packages/81/ed/385c2a0351b994a693453c1d1a6e9af9eb35db3c9460d76b5078acd70c62/regex-2026.6.28-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:b15859e3908544fb99cf47341dcf0bfd089147d258c4c4d8a29e5b087f8085cb", size = 772834, upload-time = "2026-06-28T19:55:29.154Z" }, + { url = "https://files.pythonhosted.org/packages/06/bc/bbf4a5b3b29770d7f307d3c28b5b1bca0105b0cb424be0a4eb1339bc92cf/regex-2026.6.28-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:c91487a917edd48a1ea646fdf60d7936d304f0e686fa7ea8326e47efca51d816", size = 856606, upload-time = "2026-06-28T19:55:32.186Z" }, + { url = "https://files.pythonhosted.org/packages/28/26/51d74fff82f682819979249f8d700267108ba5dc4eb284b0e11b9c85e4b3/regex-2026.6.28-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:c4ac65f3e3a99fd8f3a4a74e7a6610acd1ce9dfe9b8a03d346a4922380d68aeb", size = 803475, upload-time = "2026-06-28T19:55:34.328Z" }, + { url = "https://files.pythonhosted.org/packages/7c/3e/6be10cefdc813533fe604dbf5d3c77d2638e7ee658b2749ebadc113b6b2e/regex-2026.6.28-cp313-cp313t-win32.whl", hash = "sha256:3f6316f258bc7e6c9c2acbe9954947bbd397a81be3742a637a555f1855d6618d", size = 269126, upload-time = "2026-06-28T19:55:36.565Z" }, + { url = "https://files.pythonhosted.org/packages/3c/3c/32cda905ea1a6eeeb798291c294d8ec66ee0efe0cdba28b061e248b1d396/regex-2026.6.28-cp313-cp313t-win_amd64.whl", hash = "sha256:1484bdd6fba28422df9b5ebb04055b2e1b680e8e4f08490bb21ff0f3cc50d0ab", size = 279961, upload-time = "2026-06-28T19:55:38.456Z" }, + { url = "https://files.pythonhosted.org/packages/ea/b9/69f4e5cd6fbe0bb420cb2dbae441ca118f2495bdda522a74da75aa9829e7/regex-2026.6.28-cp313-cp313t-win_arm64.whl", hash = "sha256:3f15020f0b69cafe57baa067ff65b29acef68ff6b1670a53bef1ca11d708e02d", size = 279266, upload-time = "2026-06-28T19:55:40.62Z" }, + { url = "https://files.pythonhosted.org/packages/3b/fb/fad3b810a5bb1e09b9e5d6913fc6ba88cab738fdf283196827a3c59a4c10/regex-2026.6.28-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:f7c032b0c8a73739ff8ff1aaf30c281fa19c17bf7f1543256c8507390db7807c", size = 490407, upload-time = "2026-06-28T19:55:42.724Z" }, + { url = "https://files.pythonhosted.org/packages/d6/52/b8c79d12276d93e90e707e939b396034c04980caf1235312ef790f8e11fc/regex-2026.6.28-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:f6710f512c57b84f127a23d0f59560a03b64136eff419ae1be5ab557577fe5e3", size = 291988, upload-time = "2026-06-28T19:55:44.549Z" }, + { url = "https://files.pythonhosted.org/packages/23/d2/6a911f18279daa8d7bb8b20d771ddb6ef31fabd35f5921f9d3ba21640e80/regex-2026.6.28-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c0013958f427bd82509a186b9ff206d66cb8d60a81fc797a4c717afd18c5b0ba", size = 289704, upload-time = "2026-06-28T19:55:46.365Z" }, + { url = "https://files.pythonhosted.org/packages/fd/22/ad1955c47c669291a05804d53d7071cc0732dfdf166857be38003cedc2d1/regex-2026.6.28-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:94f06cdcd6421f8e194ad312ea608020381250df9b8a57661c1b57e9e5273878", size = 797017, upload-time = "2026-06-28T19:55:48.166Z" }, + { url = "https://files.pythonhosted.org/packages/e5/67/a83159ff8703ab4d0c2cf99e76ebf289b7b4a501623241d09f88f3614f80/regex-2026.6.28-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ec9689392f7494ff4e3f8e7e8522f9158f11023f337eaaf04a64542fc45bbf26", size = 866112, upload-time = "2026-06-28T19:55:51.047Z" }, + { url = "https://files.pythonhosted.org/packages/b9/09/7bff2d6dbbd77421b3274aa51db1c887381cbc5b6eda93598c3e882ea345/regex-2026.6.28-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:aa084684e6d2078bf6139e374d1fc2af5ddc1ac7122759a2db716d68169f6fd0", size = 911554, upload-time = "2026-06-28T19:55:53.707Z" }, + { url = "https://files.pythonhosted.org/packages/29/44/ae59c3826e7ba492e56795cdf74ea2a7b5b7c5ea116afb79ee4956a5dff1/regex-2026.6.28-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:40455e6840dc4e96a6fe50f4cedc957de2752c954d91e789812be55d49be199a", size = 800665, upload-time = "2026-06-28T19:55:55.875Z" }, + { url = "https://files.pythonhosted.org/packages/d6/19/6fd033d2ab00f35d445aaeaf3307c1e721424dcbfd48f6f65c857cb939cf/regex-2026.6.28-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:530b5c223b9ca5dd8370ac502e080aee0e4ded32be987c6564b425fb5523d581", size = 777243, upload-time = "2026-06-28T19:55:57.909Z" }, + { url = "https://files.pythonhosted.org/packages/4e/9d/99730f26df4938049ab1e652ca75e967b4c6739444e18d9707bfdb8af20c/regex-2026.6.28-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:8e0ed273ecd1a89be84466c1749bfe58609cc2a32b5d5e05006c4625ba96411b", size = 785784, upload-time = "2026-06-28T19:56:00.072Z" }, + { url = "https://files.pythonhosted.org/packages/48/49/105cd57162f5fc5c04cc917a1388a060cf8427e5c14353cd9044660fbf4d/regex-2026.6.28-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:0ab0d5344311fc8e8667078942056c3b9c9b4a4b1cc99f2eb8a5af54554f4acc", size = 860914, upload-time = "2026-06-28T19:56:02.017Z" }, + { url = "https://files.pythonhosted.org/packages/a2/a5/788245a95b69018f58bff2f4fd27d007cacaea088cdb390979743f1b2571/regex-2026.6.28-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:eacb79625323d9f7e7925366b917f492b8356fad58f5dc4fa12ff8c21d8f4ca9", size = 765915, upload-time = "2026-06-28T19:56:05.021Z" }, + { url = "https://files.pythonhosted.org/packages/ca/01/292065a39a004b05e67a337b18213670a7cb919d6856ac2d7df7f1a10dbb/regex-2026.6.28-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:20f4d87702702aa1d572721e146f301660c50eef6fd6cb596e48a22b0ace17db", size = 851404, upload-time = "2026-06-28T19:56:07.251Z" }, + { url = "https://files.pythonhosted.org/packages/98/9e/a93d865db0e13483ae1a01d81e2ce16d4a7fe2f9b9fe4aac4cc08590b136/regex-2026.6.28-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:1e693940a3b9e6d6e4dc2a54ecaa74b74934f77af1ef95f518a74261ef7cc1bc", size = 789373, upload-time = "2026-06-28T19:56:09.894Z" }, + { url = "https://files.pythonhosted.org/packages/82/0c/38b1685ad4017d78efbc8fa7dbbf96d8113b53750c8aa2d3609defd46605/regex-2026.6.28-cp314-cp314-win32.whl", hash = "sha256:234a51e20ebc18ab83b2c0600cf28f2e884560a0e00f743878f0b7d8e7c4cf03", size = 272496, upload-time = "2026-06-28T19:56:11.83Z" }, + { url = "https://files.pythonhosted.org/packages/55/50/e19f261ff9ba9b50722a529e09b1743ecf65eb348be99d0fd2cd7fcede1c/regex-2026.6.28-cp314-cp314-win_amd64.whl", hash = "sha256:7b15c437bc4604f03ceb3f8d37eae2f8930e320e1bc556b259848c639d9eec1a", size = 280754, upload-time = "2026-06-28T19:56:13.758Z" }, + { url = "https://files.pythonhosted.org/packages/36/b8/c9e68f3a9e33be73f20990b2c065b144ff2d0aa242608a950d8c4f3b56e8/regex-2026.6.28-cp314-cp314-win_arm64.whl", hash = "sha256:c6e6f790d01380a74ad564f216c533b86504afb61bf66f2b2e11e7f1a3e287a7", size = 280979, upload-time = "2026-06-28T19:56:15.928Z" }, + { url = "https://files.pythonhosted.org/packages/03/e6/21c425a37880c650d007c4171c6a80325446d830d85f5fbf335e7205b1e7/regex-2026.6.28-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:3527a72adcbe9e3600f1553b497d397c1a371d227580d41d96c3c5964109b65c", size = 494282, upload-time = "2026-06-28T19:56:18.049Z" }, + { url = "https://files.pythonhosted.org/packages/07/50/6647a7ccf5ffff995ba955a0b7d766440f4e58ce1666549c8ee998f2b972/regex-2026.6.28-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:a644f6408692812f5ead82519eed680e08d5d546fddbd9f7d9514e3c73899aa5", size = 293977, upload-time = "2026-06-28T19:56:20.145Z" }, + { url = "https://files.pythonhosted.org/packages/8c/dc/a3e141a4eaf125e50f63105570c01fa477c06ac5259dcfa95e9b90760e84/regex-2026.6.28-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:8e2fae6bb883648346f84db270dc9aafc29d8e895f62b88a75ccc83b09519820", size = 292432, upload-time = "2026-06-28T19:56:22.345Z" }, + { url = "https://files.pythonhosted.org/packages/35/ee/2ac1a6b9f167f8ff69f5a789938cc103b60cff41b24a6990daced8b88e34/regex-2026.6.28-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:debe623e09cee97ef9404575e936c610aac9bb08358c5099aaef14644a6871f2", size = 811877, upload-time = "2026-06-28T19:56:25.056Z" }, + { url = "https://files.pythonhosted.org/packages/df/7b/9a5505ee92180bcae300b1018b9ff3d3c19962436e66f2505f255e9fde35/regex-2026.6.28-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:cc579c91fb4605773483a8d940b136bcc5b854fff44fa14a1572a038f46563f1", size = 871212, upload-time = "2026-06-28T19:56:27.352Z" }, + { url = "https://files.pythonhosted.org/packages/24/4d/d61a702a9f9d1bd29b22cbef1aed6d477baa961232a7eb4d91b7775b0b3e/regex-2026.6.28-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e7c42be203d84ecf7d487ff23f8a61ef0eb0534fa0fc317a2fce8c065d20618f", size = 917507, upload-time = "2026-06-28T19:56:29.762Z" }, + { url = "https://files.pythonhosted.org/packages/d4/60/1308066f5966b65fbb6905b99ba37e9f1cd753dd0ac08485f8257334ee92/regex-2026.6.28-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e8184b4e2fdaf9cdfe77e38f15a4d9dc149168c9c29eb0ea17c5481d3bb80546", size = 816389, upload-time = "2026-06-28T19:56:32.043Z" }, + { url = "https://files.pythonhosted.org/packages/bd/5c/57ce2cb8d714ee0b7f11c7ee4cfe2af66df2b90f147feadcb538609a3a02/regex-2026.6.28-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:697f103104f5872d64078d8eeac59979960be8ee76115a2d3f31096312e2a400", size = 785890, upload-time = "2026-06-28T19:56:34.492Z" }, + { url = "https://files.pythonhosted.org/packages/ff/fd/1d5350d3a8a327bff0fccacb911732baf7b5b6f5529c0e3fa602a23e7dad/regex-2026.6.28-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:714d2b1aa29beef0ddfcdc72ad0771c05326551a8bb0680b0ddf74bfaad87387", size = 801451, upload-time = "2026-06-28T19:56:36.749Z" }, + { url = "https://files.pythonhosted.org/packages/f3/79/3c9e4f8a0306e030ad5a43bbbc01625fb28d58a813bc52d42fd1cc63fb2e/regex-2026.6.28-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:0f09f62e450cc2f113018cc8412aeea3a120a04e1ca7e801a0d441583f9a3b06", size = 866504, upload-time = "2026-06-28T19:56:38.994Z" }, + { url = "https://files.pythonhosted.org/packages/65/12/f747de475b54f4709efb24dd0fbc8467c64cec91f5db0d047b079646ee78/regex-2026.6.28-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:731ea12d5aeb2577eaef2393d6428b995f76eb35f68a89e03e15a97719d1de19", size = 773047, upload-time = "2026-06-28T19:56:41.061Z" }, + { url = "https://files.pythonhosted.org/packages/58/3c/f02f860e0500c1b2d61a79dec7e214b37fb9656281dcddc92397edf96678/regex-2026.6.28-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:51e952c8783eabd4706d0f63922f219bcfc1bef9b8cb35941c0d1a0396578858", size = 856665, upload-time = "2026-06-28T19:56:43.466Z" }, + { url = "https://files.pythonhosted.org/packages/4d/6c/28b3fa222513484be9dee26b7222bda109056c43ea28aa2314262ca48816/regex-2026.6.28-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:43248fe4c0ab8fbb223588a0795b11268940072c97bba30ea8f9b49d8cdfde34", size = 803573, upload-time = "2026-06-28T19:56:45.791Z" }, + { url = "https://files.pythonhosted.org/packages/fa/f0/8f86cf1a1fd85c5ab0c503c9fe4607ad4ad48978b2d8b435d94465e134c7/regex-2026.6.28-cp314-cp314t-win32.whl", hash = "sha256:fc1eddc25ad23c0f1344ab280d961ac595ead48292d7c779497975942373f493", size = 274515, upload-time = "2026-06-28T19:56:47.948Z" }, + { url = "https://files.pythonhosted.org/packages/0f/de/f8613c03b36786ddef2c930d28f9bcae861fcd541cc9203a870956cf1e83/regex-2026.6.28-cp314-cp314t-win_amd64.whl", hash = "sha256:ede8d8e53b6dde0a50f7eca902f0af76d87ab02a55aba7542da68ae3e5dfe83d", size = 283650, upload-time = "2026-06-28T19:56:50.614Z" }, + { url = "https://files.pythonhosted.org/packages/4d/f3/f5ec86839bbabe33b6dee649b62ff9a445d43de6b0ad780cf6b83c56f61e/regex-2026.6.28-cp314-cp314t-win_arm64.whl", hash = "sha256:4da6f6a72f8700b97a1a765e837fb7d5750bfd9f13acea7bae498f573e3a70a8", size = 283338, upload-time = "2026-06-28T19:56:52.879Z" }, +] + +[[package]] +name = "requests" +version = "2.34.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "charset-normalizer" }, + { name = "idna" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ac/c3/e2a2b89f2d3e2179abd6d00ebd70bff6273f37fb3e0cc209f48b39d00cbf/requests-2.34.2.tar.gz", hash = "sha256:f288924cae4e29463698d6d60bc6a4da69c89185ad1e0bcc4104f584e960b9ed", size = 142856, upload-time = "2026-05-14T19:25:27.735Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a0/f4/c67b0b3f1b9245e8d266f0f112c500d50e5b4e83cb6f3b71b6528104182a/requests-2.34.2-py3-none-any.whl", hash = "sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0", size = 73075, upload-time = "2026-05-14T19:25:26.443Z" }, +] + +[[package]] +name = "requests-toolbelt" +version = "1.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "requests" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f3/61/d7545dafb7ac2230c70d38d31cbfe4cc64f7144dc41f6e4e4b78ecd9f5bb/requests-toolbelt-1.0.0.tar.gz", hash = "sha256:7681a0a3d047012b5bdc0ee37d7f8f07ebe76ab08caeccfc3921ce23c88d5bc6", size = 206888, upload-time = "2023-05-01T04:11:33.229Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3f/51/d4db610ef29373b879047326cbf6fa98b6c1969d6f6dc423279de2b1be2c/requests_toolbelt-1.0.0-py2.py3-none-any.whl", hash = "sha256:cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06", size = 54481, upload-time = "2023-05-01T04:11:28.427Z" }, +] + +[[package]] +name = "rfc3986" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/85/40/1520d68bfa07ab5a6f065a186815fb6610c86fe957bc065754e47f7b0840/rfc3986-2.0.0.tar.gz", hash = "sha256:97aacf9dbd4bfd829baad6e6309fa6573aaf1be3f6fa735c8ab05e46cecb261c", size = 49026, upload-time = "2022-01-10T00:52:30.832Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ff/9a/9afaade874b2fa6c752c36f1548f718b5b83af81ed9b76628329dab81c1b/rfc3986-2.0.0-py2.py3-none-any.whl", hash = "sha256:50b1502b60e289cb37883f3dfd34532b8873c7de9f49bb546641ce9cbd256ebd", size = 31326, upload-time = "2022-01-10T00:52:29.594Z" }, +] + +[[package]] +name = "rich" +version = "15.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markdown-it-py" }, + { name = "pygments" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c0/8f/0722ca900cc807c13a6a0c696dacf35430f72e0ec571c4275d2371fca3e9/rich-15.0.0.tar.gz", hash = "sha256:edd07a4824c6b40189fb7ac9bc4c52536e9780fbbfbddf6f1e2502c31b068c36", size = 230680, upload-time = "2026-04-12T08:24:00.75Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl", hash = "sha256:33bd4ef74232fb73fe9279a257718407f169c09b78a87ad3d296f548e27de0bb", size = 310654, upload-time = "2026-04-12T08:24:02.83Z" }, +] + +[[package]] +name = "rpds-py" +version = "2026.5.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/2e/43/25a8dcd3feedd735039a8f0b5b7e3b118232b5eae288c4fd9ab200d41094/rpds_py-2026.5.1.tar.gz", hash = "sha256:07b24fea40541e28570e5b795a4a38fbdcd12550c06bd0748005ecc8116ca256", size = 64459, upload-time = "2026-05-28T12:02:13.232Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4f/a0/acf8b6fc20bfdcd3a45bd3f57680fb198e157b7e997b9123b10763798bd2/rpds_py-2026.5.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:3397a5ed7174dc2786bb214030232fc36fe8e5584fec43a9952cc542b1a12036", size = 355609, upload-time = "2026-05-28T11:58:50.78Z" }, + { url = "https://files.pythonhosted.org/packages/b6/95/f8203fd997484b1690a6869cd0e503b6c3c6be55b0ecc36d1a491fe742f0/rpds_py-2026.5.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:99ab6ba7bfa2cb0f96a04e3652355bf04e3f51aceb1e943b8541dab7ba4828cc", size = 348460, upload-time = "2026-05-28T11:58:52.374Z" }, + { url = "https://files.pythonhosted.org/packages/33/8c/b47326ad2f0be545a5e5c1a55937a12afaea7d392ba2837bb9680f57e6c9/rpds_py-2026.5.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d0efbe45632665e53e3db8fe1e5692db58fc5cb9bab4459d570b83efefe11164", size = 381031, upload-time = "2026-05-28T11:58:53.775Z" }, + { url = "https://files.pythonhosted.org/packages/22/0b/e83bbd97ffac6f6389b605cd4e1c8ac5761dc7e977769c9255d8c5adb7bd/rpds_py-2026.5.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:01d17b29c0c23d82b1f4751147ec49cf451f1fc2554eb9ef5f957e55d2656ead", size = 387121, upload-time = "2026-05-28T11:58:55.243Z" }, + { url = "https://files.pythonhosted.org/packages/fd/0e/d285d1bc8864245919c61e1ca82263e4a66d337759c3a4cef72766ff9afc/rpds_py-2026.5.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7559f72b94ae52659086c595dfa017cde03155f7832071d30959049052cb3ece", size = 501026, upload-time = "2026-05-28T11:58:56.788Z" }, + { url = "https://files.pythonhosted.org/packages/86/06/ccb2109a1e543437b5e43816f2b43b9554cc6783145528a4e3711e05c011/rpds_py-2026.5.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9e25b7088f9ccbfc0dfcaa52bf969300ca229e10ecf758974ebcbb080a4b37bb", size = 391865, upload-time = "2026-05-28T11:58:58.298Z" }, + { url = "https://files.pythonhosted.org/packages/3d/33/237173db1cfef10105b3839a24de00eb8d2a523711add4632447cdf0aedd/rpds_py-2026.5.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:613fc4ee9eaef26dc5840666214dd6fbcebcf32f46e76f4abc473059f4e13dda", size = 378012, upload-time = "2026-05-28T11:58:59.589Z" }, + { url = "https://files.pythonhosted.org/packages/97/64/1eae54e34d5161f9969295e80bd6b62a55f2b6ac5f2a5b60d02c2140e758/rpds_py-2026.5.1-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:85264a90ff4c05c1568dd65f5921c837614b67c60358fb4c17df3b7f2e90690a", size = 391111, upload-time = "2026-05-28T11:59:01.104Z" }, + { url = "https://files.pythonhosted.org/packages/d8/34/5bb334a5a0f65d77869217c4654f34c78a7d11b93938a3c076a2edeafc52/rpds_py-2026.5.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fe71bca7d547acb17027c7fd1624ff8aae623499c498d3e7011182c4de5c25e0", size = 409225, upload-time = "2026-05-28T11:59:02.433Z" }, + { url = "https://files.pythonhosted.org/packages/16/0f/007ec21283b5b040b4ec3bd95e0402591e22bfa7d5c93dfe01c465c2d2d7/rpds_py-2026.5.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a05fa4f41f37ec97c9c260441a940450a192f78d774d2b097eee1379f1e1246a", size = 556487, upload-time = "2026-05-28T11:59:04.012Z" }, + { url = "https://files.pythonhosted.org/packages/ff/10/5437c94508169b6b22d8418fef7a66e9ffb5f3b9e9c94460f2eedafe06ff/rpds_py-2026.5.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:df1d2a1996755b24b9ecee92cb4d36c28f86f464a6a173349c26bab41e94b8c2", size = 620798, upload-time = "2026-05-28T11:59:05.485Z" }, + { url = "https://files.pythonhosted.org/packages/e0/d5/9937dce4d6bda74157b954e7d1460db05a22f5929dccfeeba1ed27a93df0/rpds_py-2026.5.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:8895840ac4809e5f60c88fd07617cd71326e73d6e5a8aa783c5c0f7c24985de2", size = 584053, upload-time = "2026-05-28T11:59:06.837Z" }, + { url = "https://files.pythonhosted.org/packages/6c/31/750617dd0ae1752471bf43f9e41d263398fae7cde7849d23b8574a70e617/rpds_py-2026.5.1-cp311-cp311-win32.whl", hash = "sha256:3684a59b158a7683aaeb8e25352e9a9dd2122cec78f2d8530266e4f91b4c7b3f", size = 214390, upload-time = "2026-05-28T11:59:08.402Z" }, + { url = "https://files.pythonhosted.org/packages/3c/bb/3dcab0e1d9516303f2eb672a5d6f62eca5a69e2886301e9c8c54b520c39b/rpds_py-2026.5.1-cp311-cp311-win_amd64.whl", hash = "sha256:7bd530e6a530bb3ea892f194fafa455f3516ac25ecf7143fd33c09be62b0470a", size = 231097, upload-time = "2026-05-28T11:59:09.786Z" }, + { url = "https://files.pythonhosted.org/packages/49/d6/c6bbf5cb1cf12b9732df8074b57f6ef8341ba884c95d40632ae8bddb44e4/rpds_py-2026.5.1-cp311-cp311-win_arm64.whl", hash = "sha256:0a5ae4dbe43c1076983b72616496919872ae7bbe7a1e21cc48336bc3154d130b", size = 226361, upload-time = "2026-05-28T11:59:11.079Z" }, + { url = "https://files.pythonhosted.org/packages/d4/e7/a78582dc57caa592dcc7d4fb69b61390561e908eb3d2f5df5928a8e354c0/rpds_py-2026.5.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:3abe24a66e57adcfa645d718063a5fa5103ecc71ddbf26d78af8f9368018ff1d", size = 353040, upload-time = "2026-05-28T11:59:12.531Z" }, + { url = "https://files.pythonhosted.org/packages/a3/43/35e3f136343aef451e545ce8c38d36c2f93c0ed88703db8b64ba2b205c68/rpds_py-2026.5.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:58b1d94308ddf0b1982f61f2eb54bf92997c9ece8a8093ef014250f4a517906c", size = 345775, upload-time = "2026-05-28T11:59:13.827Z" }, + { url = "https://files.pythonhosted.org/packages/20/e1/0f2160c5982d3157734d5cb3ed63d8b2d583a73c9864f77b666449f32cf8/rpds_py-2026.5.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0fa92420128dadce7f54bd73ba1825a273e9268fe9e35dbf7e6362890efa4e08", size = 376329, upload-time = "2026-05-28T11:59:15.271Z" }, + { url = "https://files.pythonhosted.org/packages/d0/11/ee0ba42aff83bf4effdbc576673c6be64c5e173978c3f6d537e94482f77d/rpds_py-2026.5.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ca653c6546386227cd9800d1bef6a348099acf8db4250341da6d90f663d6dfcb", size = 383539, upload-time = "2026-05-28T11:59:16.665Z" }, + { url = "https://files.pythonhosted.org/packages/11/df/d94aa6a499d4ac40afe2d7620f2c597fd3c0f182e854ad7cf3f596a81cb6/rpds_py-2026.5.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:66c93681c4729e4e3ecba31b8179fae083ff3118841672835140338b4b9867c1", size = 494674, upload-time = "2026-05-28T11:59:17.991Z" }, + { url = "https://files.pythonhosted.org/packages/1f/75/33d30f43bb2f458de11979486a591b1bf6e5651765ed1704c6197c2dc773/rpds_py-2026.5.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:40ff257542e04796880e011e15cd4dc21c2599975df2aaa8f2c8495ca574e1a5", size = 389268, upload-time = "2026-05-28T11:59:19.434Z" }, + { url = "https://files.pythonhosted.org/packages/f4/1e/2c9096fc19d5fd084b0184ca2b651e659aa0a37e6fdbecf6ece47f147fe1/rpds_py-2026.5.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b6825cc329b290e93c5f6a9be2393118a763f6ccf6abd83704e0c102ca583644", size = 376280, upload-time = "2026-05-28T11:59:21Z" }, + { url = "https://files.pythonhosted.org/packages/b9/e5/61ec9f8be8211ea7f48448195549e4aaf02004083475493b0e137702ecb2/rpds_py-2026.5.1-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:de42116e69cb53b911cc34aee5ab98f36c597b822545045d49e938818b99e5e4", size = 387233, upload-time = "2026-05-28T11:59:22.454Z" }, + { url = "https://files.pythonhosted.org/packages/0d/ca/bcec1005c4f4a234f92a29078631fee49206c7265ccae966f18fd332e80e/rpds_py-2026.5.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c0f920015df2a504bebaba6d4c31ccf3fcf942f92655c086da30b671aad19aa6", size = 405009, upload-time = "2026-05-28T11:59:23.845Z" }, + { url = "https://files.pythonhosted.org/packages/72/e6/4d5718c5cf26c522dc7c9999e238da1e77380b81d0c5d1df11e271ddfeb1/rpds_py-2026.5.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0408a24e44feb919423dc6d9da677cb5cddb894d2ca9e763967d156d9c60fab4", size = 553113, upload-time = "2026-05-28T11:59:25.184Z" }, + { url = "https://files.pythonhosted.org/packages/d4/25/2ee807bdb3e1f0b7eddf7782acd5665a8b5205a331a7d7244a52c4812fd9/rpds_py-2026.5.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:cea68bcd53467561ae2f96a6bdad1544299ba97b5b0ddcd5ac3d376e5c781c24", size = 618838, upload-time = "2026-05-28T11:59:26.749Z" }, + { url = "https://files.pythonhosted.org/packages/6a/c1/7d4c26f167f8c41501cc073d30ee22082b16ce358cf5b00ec97cbc7804ea/rpds_py-2026.5.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:4be8b1d2a705cc37d08256004e1d07de143fa0075c8e85a3df020b776f62b732", size = 582436, upload-time = "2026-05-28T11:59:28.11Z" }, + { url = "https://files.pythonhosted.org/packages/04/1d/9d12b0a337bab46f4769f8857f4007e3b2d639e14f9a44a0efe157696e64/rpds_py-2026.5.1-cp312-cp312-win32.whl", hash = "sha256:6736718bd4fc49cbcb538ba30516fdbef161522acefb739657d48b97bd864fed", size = 212734, upload-time = "2026-05-28T11:59:29.689Z" }, + { url = "https://files.pythonhosted.org/packages/c5/93/e4116f2de7f56bc7406a76033dc501811ddeb22b7f056b92d632871ebb0c/rpds_py-2026.5.1-cp312-cp312-win_amd64.whl", hash = "sha256:0a7d1eec967df0e9b22614a5e177622e0c89611d03727fa0cb48e45028907870", size = 229045, upload-time = "2026-05-28T11:59:31.033Z" }, + { url = "https://files.pythonhosted.org/packages/cb/53/6c3419d85eb2ec5938a37627c585b42d76a63bb731d6e42ed4b079ebf486/rpds_py-2026.5.1-cp312-cp312-win_arm64.whl", hash = "sha256:1841d067089e117142d79b98aa0df2f08b52f2ecc1819dd2700636c0db74a473", size = 223967, upload-time = "2026-05-28T11:59:32.318Z" }, + { url = "https://files.pythonhosted.org/packages/6c/32/14c961ad295f490eb0849ada8b79683e93a59b9de3afdd983eaf55fa6867/rpds_py-2026.5.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:efef4ac29c6ff495531eb17ee705b62841ecaa291b7c7077e848ea03e237164d", size = 352787, upload-time = "2026-05-28T11:59:33.655Z" }, + { url = "https://files.pythonhosted.org/packages/ca/bb/d1b85117967c11191441a7274ae616c65d93901d082c588f89a50a8da5ae/rpds_py-2026.5.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:c39f5b67a8a2e67179ada2a954227d670fe65fa9098457f698f56ddf248709b3", size = 345179, upload-time = "2026-05-28T11:59:35Z" }, + { url = "https://files.pythonhosted.org/packages/7c/46/d84105f062e626a1b233f863907288a4708c2d833b8b4c6fb2764bc080c0/rpds_py-2026.5.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b5c30f3f04eef4fbd362226a6f31d7c8895ca4fbb6e0b790f6890a98d8da8559", size = 376173, upload-time = "2026-05-28T11:59:36.43Z" }, + { url = "https://files.pythonhosted.org/packages/e2/ae/469d7959ce5b1201e1de135dc735b86db3b35dd0d1734f6a44246d5f061c/rpds_py-2026.5.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:277f6c82f0580848796c7ecc8a7173aa3bfb928e4ff831261c2f60a81dc270db", size = 383162, upload-time = "2026-05-28T11:59:37.995Z" }, + { url = "https://files.pythonhosted.org/packages/dc/a2/57853d31a1116a561aa072794602ad3f6341e18d70a8523f1bd5b9fc1e5a/rpds_py-2026.5.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:63c2c4c213f1a4e3f3de28ecab029dbdee976324e729c0d7a55211be72576b02", size = 495093, upload-time = "2026-05-28T11:59:39.453Z" }, + { url = "https://files.pythonhosted.org/packages/99/63/3a8eabcad9314b7daf5c65f451d2c33d989235cd8a5762186cf2c3f5a4f8/rpds_py-2026.5.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3350ec808fb538fe71a1f94dfaa0e29c598dfad805ce49f0caec5ae3183c652b", size = 389829, upload-time = "2026-05-28T11:59:40.896Z" }, + { url = "https://files.pythonhosted.org/packages/4b/25/05678d97fc25e2622df14dc530fb82023174ecfff6733991ed0d78f167bd/rpds_py-2026.5.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1b964e3ab599e718dc46c018d104b1ebc007cbc6567d827c94a687fca56d77e", size = 374786, upload-time = "2026-05-28T11:59:42.626Z" }, + { url = "https://files.pythonhosted.org/packages/88/d1/8c90b6431e80a3b91b284a5c7c8c0c4f9c006444d90477a740d6e0f9c694/rpds_py-2026.5.1-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:19cb09fab7b7fc96b2a6e28f2e34b72a3705ff27b37edb77455316e5d3f3dc9b", size = 386920, upload-time = "2026-05-28T11:59:44.124Z" }, + { url = "https://files.pythonhosted.org/packages/ff/99/4638f672ab356682d633ee0da9255f5b67ce6efd0b85eb94ad3e255e65a5/rpds_py-2026.5.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:abe76bcdba31e576cb83eeb8797aa0d882b738fef6dc65d0601fc753806a5b46", size = 405059, upload-time = "2026-05-28T11:59:47.177Z" }, + { url = "https://files.pythonhosted.org/packages/66/3f/3546524b6eb4cc2e1f363a3d638fa52f6c24faae3500c25fb488b02f1740/rpds_py-2026.5.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:8bff7073db3899158fff55ebf57b113a67030af26f80a18978f9f0aa60250ddf", size = 553030, upload-time = "2026-05-28T11:59:48.603Z" }, + { url = "https://files.pythonhosted.org/packages/c6/c3/7b3388c796fcf471bd17194242d4dc1a7608567c0fa422bcc1c5e79f9c1e/rpds_py-2026.5.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:8ba264fa49be666cd9cc56bf34ec7002fb3d27a4aee5bcb4d43d0d18feb1bb6f", size = 618975, upload-time = "2026-05-28T11:59:50.314Z" }, + { url = "https://files.pythonhosted.org/packages/61/1e/a3cb07f2795075d1d88efddae2f541359fde5f08c81ee114c29c2949c90a/rpds_py-2026.5.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4860b603ddda0475a8885499b3729e90229d480105b42651962a5397d995fa89", size = 581178, upload-time = "2026-05-28T11:59:51.673Z" }, + { url = "https://files.pythonhosted.org/packages/a1/74/e758c03a5ef46f04c37f2651a2893db846d569ba8a7bca469d4b58939bcd/rpds_py-2026.5.1-cp313-cp313-win32.whl", hash = "sha256:7944270ae71383f6e2657dd7d5ce4eeb4ac2d0059a6738f0510583d462ab4842", size = 212481, upload-time = "2026-05-28T11:59:53.148Z" }, + { url = "https://files.pythonhosted.org/packages/70/ec/a2aca432db9c7359b40fa393eeeaa0d166c2f70175be956e75fa24197c44/rpds_py-2026.5.1-cp313-cp313-win_amd64.whl", hash = "sha256:88647f43a73c4e01be19b04ceef0c8d3a1958153604d13c773becd8016f2a0cf", size = 228519, upload-time = "2026-05-28T11:59:54.505Z" }, + { url = "https://files.pythonhosted.org/packages/29/60/a73bfdd45b096574556acf303bbd9fa9eed36ca8a818b514e2a5d5fe2b9d/rpds_py-2026.5.1-cp313-cp313-win_arm64.whl", hash = "sha256:453895624ecf7db7063b1004e44037522bbaef9ff6a945e59bc71662d7a03abd", size = 223446, upload-time = "2026-05-28T11:59:56.081Z" }, + { url = "https://files.pythonhosted.org/packages/18/e2/408105fd611823f00882aea810f3989a30d26b1bab8b6beb20f98c724e0e/rpds_py-2026.5.1-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:b4e4bc98639ec915f512fde3aa7a95e0041d95d9c3cc86eea841fa63cb1e8600", size = 355287, upload-time = "2026-05-28T11:59:57.448Z" }, + { url = "https://files.pythonhosted.org/packages/8d/58/5c4a43436843c90d0f6d19f82c200c80e3843ca9fa07b237623327f6d384/rpds_py-2026.5.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:cacedb7a6e167680acba45ad5716e89067d225dc80da0d7040cae8c81d4572fa", size = 347033, upload-time = "2026-05-28T11:59:58.881Z" }, + { url = "https://files.pythonhosted.org/packages/fb/c2/1a71acdacaf4e259b10278fb87b039ded3cf80041bcd89dd8a3ea702ded6/rpds_py-2026.5.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68700371c5d7ae1412862ddfa719090925c93ecf351c566d66f09d04b136ea00", size = 376891, upload-time = "2026-05-28T12:00:00.516Z" }, + { url = "https://files.pythonhosted.org/packages/c2/c8/535f3d9b65addd8e28aa87b83c6e526799c3717a88273db8ea795beeef7a/rpds_py-2026.5.1-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:296c799becfa849c779c8725494fe9ed94959ed886787df4364b058465bad7f0", size = 385646, upload-time = "2026-05-28T12:00:02.394Z" }, + { url = "https://files.pythonhosted.org/packages/1c/91/dc033f313345c354ade914dbe73cdb90b615a4409ea02430d5356794f3d8/rpds_py-2026.5.1-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d3858b908218ee108d0bbfb2095ccc237648053c9bf98affad7cb079acaf1d97", size = 498830, upload-time = "2026-05-28T12:00:04.189Z" }, + { url = "https://files.pythonhosted.org/packages/27/fc/90fcbea459dbb8ddc18a2e0fd1de9412b48bc84ffff2db771cf714bacfd6/rpds_py-2026.5.1-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4fb8d2e7cb2f850b169806d61d1b991738acec96500a75c30f49caf064ce7cef", size = 392830, upload-time = "2026-05-28T12:00:05.797Z" }, + { url = "https://files.pythonhosted.org/packages/b2/1d/46cd11a228c9750684a798d98f878be6f614aa762438da7378f035e79e35/rpds_py-2026.5.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:27b74c10ed6a8f190f4287f53bcfea348b92a84a9c9f70d30183d1e6172d580d", size = 379613, upload-time = "2026-05-28T12:00:07.433Z" }, + { url = "https://files.pythonhosted.org/packages/24/4a/d9b0c6af3a1de03eb93741bbe8be2bdce84d8fda8224f3005451d86df389/rpds_py-2026.5.1-cp313-cp313t-manylinux_2_31_riscv64.whl", hash = "sha256:b9a6528956191c48c52294a592dbd4a8386d7048bdb25c0efcb6b966466c6d83", size = 388183, upload-time = "2026-05-28T12:00:09.227Z" }, + { url = "https://files.pythonhosted.org/packages/c5/b4/db7aaabdda6d020afc87d981bcc2f57a434c7dec60ecfc2ab3dd50b20351/rpds_py-2026.5.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:af03e34e860047bc7a352b842856fcf78798fbb81132cc98bd2f907ab4eb9cd2", size = 408578, upload-time = "2026-05-28T12:00:10.779Z" }, + { url = "https://files.pythonhosted.org/packages/08/d6/070f6a41cbb343e2ac4171859bf3f3623e0ab002f72619d6d505313ec2de/rpds_py-2026.5.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:fea6e836d10abbe191d557d33bd58bd5987725fe63aa1eefe557d230209855bd", size = 553573, upload-time = "2026-05-28T12:00:12.443Z" }, + { url = "https://files.pythonhosted.org/packages/75/ab/1a71ea3589c4345dac0a0518f0e6a031cb42689277851b683c46d27463a5/rpds_py-2026.5.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:fc0c0f878ea770a0a8a462456c5ad36fc9fe6358e6b76fdadc7f17575e0b8bf1", size = 620861, upload-time = "2026-05-28T12:00:14.09Z" }, + { url = "https://files.pythonhosted.org/packages/8a/22/9bf80a56069c0c443fcfefac639a86a744550a2898817a6dfd3e26654924/rpds_py-2026.5.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:e0b360f316d966b048b085857630b3cc51f3db2f07b06f440eac8f695374d1e3", size = 585633, upload-time = "2026-05-28T12:00:15.66Z" }, + { url = "https://files.pythonhosted.org/packages/da/68/3b2c0a75c9e04125696f84ebdbbf304acf5a40b58ba4481cdb98a922c3ba/rpds_py-2026.5.1-cp313-cp313t-win32.whl", hash = "sha256:a2999883eedf72fdfb7520b92c7d4ec2572a71ff40239377aa604cc529eecafc", size = 210074, upload-time = "2026-05-28T12:00:17.291Z" }, + { url = "https://files.pythonhosted.org/packages/e7/8b/609157d5a25d37d4f29f92840ba531f416907c34ae5c5739dd21fc2bef98/rpds_py-2026.5.1-cp313-cp313t-win_amd64.whl", hash = "sha256:e07be2a9d7122bd6e82dea89814ef8dc893feb1aae97fec1630f3263bbb30e55", size = 228635, upload-time = "2026-05-28T12:00:18.73Z" }, + { url = "https://files.pythonhosted.org/packages/d4/6f/19c1918a4b590d8de87e712e4abe4b3875771eff60216fb6153cf6665c68/rpds_py-2026.5.1-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:1f2c391c3059798093b65df23aca2cac150460ae9c630d99dec83d703d9485b9", size = 349756, upload-time = "2026-05-28T12:00:20.217Z" }, + { url = "https://files.pythonhosted.org/packages/e5/60/a06fe7da34eca79dacbf958a2ba0c6eea85bc2b29de20080bf40f72f66fa/rpds_py-2026.5.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:413b424f7c4ee65ab5e5be91f5731be0f8b41a1ee2b12dfe810d716312e95a78", size = 343831, upload-time = "2026-05-28T12:00:21.711Z" }, + { url = "https://files.pythonhosted.org/packages/bf/ec/b2333b97b90e2a6ef6ca8ad386ee284968e74bcfe113b3f1a8d9036429a9/rpds_py-2026.5.1-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2c595a1d9255dce0599e13130d1440ab2506654f2b50294226ee06402f8fef63", size = 375127, upload-time = "2026-05-28T12:00:23.326Z" }, + { url = "https://files.pythonhosted.org/packages/14/7f/e00aae54067f2b488c4637961d5f58204d470795fc791085fa3f15060d2e/rpds_py-2026.5.1-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1c27c5f6102eac8c03e7595a00827a53b271ba40a53b59ff8709170e0855ea4a", size = 379034, upload-time = "2026-05-28T12:00:24.89Z" }, + { url = "https://files.pythonhosted.org/packages/be/cc/423999bbb8ae8dc93c77fc1d5e984ade5eb89d237d3bb884ccfa72ae2890/rpds_py-2026.5.1-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6c7fcf61d44cacecaf3aea542b0e053db77972a4573e7ceda16fb2b399161195", size = 490823, upload-time = "2026-05-28T12:00:26.676Z" }, + { url = "https://files.pythonhosted.org/packages/0f/aa/c671bf660f12e68d3c52ff86c7066ed1372df5a0f4f2ff584e419b8207e7/rpds_py-2026.5.1-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2c817a189d4ee14290420e5ff051e4dd6baa13f3edf84685071dee07a6d538ee", size = 388144, upload-time = "2026-05-28T12:00:28.577Z" }, + { url = "https://files.pythonhosted.org/packages/19/c8/d63bb75b68afe77b229e3021c6031bcaf01da5db5b0e69d0d10f9ba679a7/rpds_py-2026.5.1-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21846aac0ed2e0589f38c12dc44e77bb64e494b771eadbcf169cba00566ba7ba", size = 371959, upload-time = "2026-05-28T12:00:30.304Z" }, + { url = "https://files.pythonhosted.org/packages/82/35/c51122014d8274ff37dc606d60049c3db7d83da02b5b282511e5a906a9a6/rpds_py-2026.5.1-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:b317c87a13f769a4e787819bd508aaa5d69aa09b0880de9af6d3a8a54571cdec", size = 383558, upload-time = "2026-05-28T12:00:31.764Z" }, + { url = "https://files.pythonhosted.org/packages/e3/f9/2790cb99c136a5363acdeacf5c27c56f3de0d4118a1f48fca83404c99c89/rpds_py-2026.5.1-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ce87129d9f2c14fa6c4a8601fb80eb4488c80d38a20cd13758ef11123e14995d", size = 402789, upload-time = "2026-05-28T12:00:33.247Z" }, + { url = "https://files.pythonhosted.org/packages/e5/1b/e4fb584f8c75d35c38150ff6a332cda949e6f97acba1f4fd123b14ab56fe/rpds_py-2026.5.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:9cdddb6c1207d284d94fd1530adf57fbd797fe7c4b8704ba85f49414f2557e7d", size = 551405, upload-time = "2026-05-28T12:00:34.819Z" }, + { url = "https://files.pythonhosted.org/packages/d8/f7/a6731b4216cb3793ea1af5391da240f5683dacc0d13e034fe5fc3503f240/rpds_py-2026.5.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:4e237e139f94d3c036fd28eb9f564c99055476ff4ff05cd42be55ce349b5aa02", size = 616975, upload-time = "2026-05-28T12:00:36.268Z" }, + { url = "https://files.pythonhosted.org/packages/2c/ea/2e051a81d95d8e63f4b35a1c463a87e8766bc3d083c067c5dfb6bf220747/rpds_py-2026.5.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ed0954b524873214369184a9c82b0eaa45a3fbb9a798cd95b17e0d98499e7ea0", size = 578701, upload-time = "2026-05-28T12:00:37.82Z" }, + { url = "https://files.pythonhosted.org/packages/65/56/b5f6fdb2083e32bca8a8993d89e70db114b4756c9e2c38421328126689d2/rpds_py-2026.5.1-cp314-cp314-win32.whl", hash = "sha256:2d88621d6a7d4dfa633d21abe90f280bb205274e16b1d1e61c6ad4640b2453b7", size = 209806, upload-time = "2026-05-28T12:00:39.492Z" }, + { url = "https://files.pythonhosted.org/packages/fb/80/65a5aa96c155e611d1ed844e4e1f57f3e36b021f396d9f8585d756e6b90d/rpds_py-2026.5.1-cp314-cp314-win_amd64.whl", hash = "sha256:cef8ac28d26f4dda3533060c20fbf80a325458fa9fd23ea72a73cdfa8e978838", size = 225985, upload-time = "2026-05-28T12:00:40.94Z" }, + { url = "https://files.pythonhosted.org/packages/27/7c/ad185212e87b05f196daef92bc5f3caf07298eb47c295b5585c3dd3093ac/rpds_py-2026.5.1-cp314-cp314-win_arm64.whl", hash = "sha256:eaaea962c68cdc68d4a533ba985ab8e9484277910bbfaa2ab3ef7732667bfed8", size = 221219, upload-time = "2026-05-28T12:00:43.15Z" }, + { url = "https://files.pythonhosted.org/packages/23/58/e14ae18759020334646b031e708ab4158d653a938822bfb7b95ef2e93aa3/rpds_py-2026.5.1-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:21942f52dbbd5f8758bf021213d28bd45c39e873e65e2407faf5f1846f5761ad", size = 352148, upload-time = "2026-05-28T12:00:44.638Z" }, + { url = "https://files.pythonhosted.org/packages/31/9b/5f4a1e2f960bca3ac5d052b139dd31eed97b259f9d909173821760d542e8/rpds_py-2026.5.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:f414556f6e3958300ff941e40c9f97e3dc9774ddd1b3434c475d73dd354bbed3", size = 345196, upload-time = "2026-05-28T12:00:46.14Z" }, + { url = "https://files.pythonhosted.org/packages/1a/71/1d9574d6a2fa20ab60eaa55c7467f5aa20cbc770f341a05f09c0876f59e2/rpds_py-2026.5.1-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ef1013a8625c74043210190b246f5b1551e09757c1f356c6e4160ef96c5bc081", size = 374981, upload-time = "2026-05-28T12:00:47.531Z" }, + { url = "https://files.pythonhosted.org/packages/0c/9a/37e99f4915a80aa71670263c1267f7ae0af95f53a3f61e6c3bdc016d4515/rpds_py-2026.5.1-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:cc68e231a77a5f0d774ae278a1f8e55c0456501820847c1e4efb3829f3441df6", size = 379961, upload-time = "2026-05-28T12:00:49.216Z" }, + { url = "https://files.pythonhosted.org/packages/a8/ff/6e73f74b89d2e0715e0fc86b7dde893f9a61ae2f9b256ff3bdfe41ac4e94/rpds_py-2026.5.1-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9baffb505aff33acc69b422a19f77806680f3c8632227d79f48de8a810d1c2c5", size = 495965, upload-time = "2026-05-28T12:00:51.111Z" }, + { url = "https://files.pythonhosted.org/packages/ea/e0/425faba25f59d74d4638b267f7c7a80e8649d2ef4db10a19b0c4a71e6e6f/rpds_py-2026.5.1-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b8d2f912928d426e8cfa396f7f3f8d29a59e6689c86dcca3c420730c1096322b", size = 389526, upload-time = "2026-05-28T12:00:52.77Z" }, + { url = "https://files.pythonhosted.org/packages/c6/76/7a41960e3fddae47fab43a28684d5da981401dffd88253de0944148654cb/rpds_py-2026.5.1-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90f628283be835db980c941767d41c9a27b5239e54ba0a9c1335247e82406964", size = 376190, upload-time = "2026-05-28T12:00:54.215Z" }, + { url = "https://files.pythonhosted.org/packages/27/60/5f38dc70824fc6951b51d35377e577a3a3a4c81a6769cc5a2de25ebe0ad1/rpds_py-2026.5.1-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:1ebb2f0ab7e16132995a72de805170e0203df0c3dd22e1ef1cd1fdd90bd7a131", size = 383921, upload-time = "2026-05-28T12:00:55.673Z" }, + { url = "https://files.pythonhosted.org/packages/60/1a/d60a38caa1505f4b9483c3fbbde12c94e1079154f4f401a6da96f7e77621/rpds_py-2026.5.1-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f3df3d16ded76f1f8c9cdebd0e1ea55fdf4c23b812de189814da7cf229c22a81", size = 404766, upload-time = "2026-05-28T12:00:57.518Z" }, + { url = "https://files.pythonhosted.org/packages/87/ff/602fd3f174d6425f0bce05ad0dfbec0e96b38d0f7d08a79af5aa20083885/rpds_py-2026.5.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:9af8905b8f854990e40d5206aa5ac58d9b0fe0b7f351ff2bb086c20f6c8c6a47", size = 551343, upload-time = "2026-05-28T12:00:58.978Z" }, + { url = "https://files.pythonhosted.org/packages/b8/c1/1be13327acdbead3eca1fde03b6a34dbb011f1e864e217f0d32cc1779a7f/rpds_py-2026.5.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:036a36a87fb1cd3b214d11c4b3c4f7d2ddad933625dca1c900b56a057c07740a", size = 618502, upload-time = "2026-05-28T12:01:00.656Z" }, + { url = "https://files.pythonhosted.org/packages/f3/d7/afb49b49d7f2be8b7ba1a9f0977fa5168003437b93086726f066544e8351/rpds_py-2026.5.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:62ae3853454fe9ef283a03c96c2d835d39e84b14643a9d62c82ef0fb87d702ca", size = 581916, upload-time = "2026-05-28T12:01:02.22Z" }, + { url = "https://files.pythonhosted.org/packages/25/d1/dbef8c1f8a10f07beb62b5f054e20099fd9924b3ec001b8f0b6ac7813a85/rpds_py-2026.5.1-cp314-cp314t-win32.whl", hash = "sha256:6c3d771a46ec18b12af06ce36243a9a80b07a5d0515236332d90863ca8bb326a", size = 207855, upload-time = "2026-05-28T12:01:03.821Z" }, + { url = "https://files.pythonhosted.org/packages/2a/72/bfa4e61ab8e7dc1c8adf397e05e6cbdd4239357bd72b248d3de662f23915/rpds_py-2026.5.1-cp314-cp314t-win_amd64.whl", hash = "sha256:c93c629be4636cf54337bd5f06c104d55e42ced54d681f6fe21ae510a65116f6", size = 225422, upload-time = "2026-05-28T12:01:05.194Z" }, + { url = "https://files.pythonhosted.org/packages/27/3a/7b5da92b640f67b6717ccafc83cdd06bfa7ff2395c3685c68922bb54d703/rpds_py-2026.5.1-cp315-cp315-macosx_10_12_x86_64.whl", hash = "sha256:3574b55c604b8f75dacb007136508bbc0db406e626301778096a133327e7f2fb", size = 349576, upload-time = "2026-05-28T12:01:06.722Z" }, + { url = "https://files.pythonhosted.org/packages/d7/8a/2aafd7ad355a1bd48ca76e2262b74b15e6432b5a1efe150efd4d779cd55d/rpds_py-2026.5.1-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:94068eb3ae6d43f5a786b7db96a406a34e6d5c24489feef32fd6e8946ea7b291", size = 343640, upload-time = "2026-05-28T12:01:08.441Z" }, + { url = "https://files.pythonhosted.org/packages/f7/7d/6c9523c1abbe840a1b7fba3c516d48e1d3487cc80fea4366c4071cf56784/rpds_py-2026.5.1-cp315-cp315-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3a5b10e8ce894825f380a8f1b6444cf73c294dfea62afbb2d13e3a9e630cec1", size = 375322, upload-time = "2026-05-28T12:01:09.934Z" }, + { url = "https://files.pythonhosted.org/packages/5a/5d/0b7b03fb1dc509321f01de3149784ab773e34c8573022029af8076afcb9c/rpds_py-2026.5.1-cp315-cp315-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fc09f82e63d4bcd58149572f857a431bae851dc747e313c3b5bdf7abb907fda8", size = 379066, upload-time = "2026-05-28T12:01:11.48Z" }, + { url = "https://files.pythonhosted.org/packages/d7/e2/8ef6012999ebf1cb1c22f876d9ce5e63d960fd4631d2af3202d3f480aa25/rpds_py-2026.5.1-cp315-cp315-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e10464d17df3b582745c25cec695cb9558bca2cb6ddb631aee1787fc72c767b2", size = 494586, upload-time = "2026-05-28T12:01:13.051Z" }, + { url = "https://files.pythonhosted.org/packages/80/af/1eeb029bec67582c226b7809172207cd005073af4ebd906e65ff494f4983/rpds_py-2026.5.1-cp315-cp315-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ba05adbf15d994c38ec0b7ab32e858e5110c21e9009a00a86545fd220f84e038", size = 388415, upload-time = "2026-05-28T12:01:14.631Z" }, + { url = "https://files.pythonhosted.org/packages/18/23/ffbe10711c4d766c1cab0557d6906c074f795814863c67b351355d29354a/rpds_py-2026.5.1-cp315-cp315-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77c004fdc7b891967106f78ddfd7b076bfe6813c6139c6fff6aed3bcaa960b26", size = 372427, upload-time = "2026-05-28T12:01:16.153Z" }, + { url = "https://files.pythonhosted.org/packages/bd/3a/30ba4a6ad457e5b070c18d742a33fb77d8d922b565cc881f8a5313d63bfe/rpds_py-2026.5.1-cp315-cp315-manylinux_2_31_riscv64.whl", hash = "sha256:83bcf894486c9d78dd290d3c0124ff6dd8875d3025e2090a8ec49fcc37c55fdd", size = 383615, upload-time = "2026-05-28T12:01:17.809Z" }, + { url = "https://files.pythonhosted.org/packages/d3/69/62e242b53ce39c0814bd24e1a6e6eba6c92be716277745f317f9540a2e7b/rpds_py-2026.5.1-cp315-cp315-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c3df104083952a0e0c6f10de33e440eabe98fb6317d23e1a58c68f6df08d01b9", size = 402786, upload-time = "2026-05-28T12:01:19.419Z" }, + { url = "https://files.pythonhosted.org/packages/38/c1/a770b9c186928a1ed0f7e6d7ae50e7f3950ed23e3f9e366dbc8e38cb55de/rpds_py-2026.5.1-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:980450826cf22e133c57e0835070bdd0dd3f73b9b708c3ce223def2cb9469e14", size = 551583, upload-time = "2026-05-28T12:01:21.013Z" }, + { url = "https://files.pythonhosted.org/packages/21/7c/68e8579b95375b70d2a963103c42e705856cdb98569258bd807f4423891c/rpds_py-2026.5.1-cp315-cp315-musllinux_1_2_i686.whl", hash = "sha256:205dde846f24332ab0c1188699a043b8d165b79bb84529ce272c45048ff6be01", size = 616941, upload-time = "2026-05-28T12:01:22.548Z" }, + { url = "https://files.pythonhosted.org/packages/70/a1/a6135aed5730ff03ab957182259987ac11e55fb392a28dc6f0592048a280/rpds_py-2026.5.1-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:3966b82dd563176396df030f3dd52a6e54cb69b718e95e78bd555ed3d1e0185d", size = 578349, upload-time = "2026-05-28T12:01:24.118Z" }, + { url = "https://files.pythonhosted.org/packages/09/6e/f24201a76a84e6c49d0bdfdfcb735210e21701e9b21c5bfc0ba497dd62f6/rpds_py-2026.5.1-cp315-cp315-win32.whl", hash = "sha256:7818f8d0a415be74d2be3590b0a1c1f463a642f4d0217e7d10602dceef5b79aa", size = 209922, upload-time = "2026-05-28T12:01:25.522Z" }, + { url = "https://files.pythonhosted.org/packages/9e/e4/966bc240bb0485fc265278f6de44d05834bf0b3618886e0b22e33d54c49a/rpds_py-2026.5.1-cp315-cp315-win_amd64.whl", hash = "sha256:b3cc20c0d800af78fd0fac68086e28c1856cec51ea528bb81ea851aa40d39325", size = 226003, upload-time = "2026-05-28T12:01:27.062Z" }, + { url = "https://files.pythonhosted.org/packages/5c/5c/a15a59269cd5e74472734516c73795c15eccfc841b3d4b0228c3f53f19d0/rpds_py-2026.5.1-cp315-cp315-win_arm64.whl", hash = "sha256:3609e9939a8a76cd904cf98a3f1f13b5dc7e150adeaee89e0ea09652ea213e16", size = 221245, upload-time = "2026-05-28T12:01:28.51Z" }, + { url = "https://files.pythonhosted.org/packages/e0/22/135ce03804e179a71ceb13be095deda4a279bc88f7a6b8fa161c5ad44e12/rpds_py-2026.5.1-cp315-cp315t-macosx_10_12_x86_64.whl", hash = "sha256:5d333a7127d4b307601ac37792bee01bb95c867cbfacf21b6375b804d6bbd723", size = 352015, upload-time = "2026-05-28T12:01:30.214Z" }, + { url = "https://files.pythonhosted.org/packages/3b/5f/f1f6d2652eb9d848f6eb369d8db83a2da6249bb49ad2c2a48f45d54538d3/rpds_py-2026.5.1-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:b5f077b44a4f7808520f66dae234988d867deb9aed9be5da057ce9ba831b2a41", size = 345016, upload-time = "2026-05-28T12:01:31.656Z" }, + { url = "https://files.pythonhosted.org/packages/88/66/b74182775691ea2290c99e52ac8d5db844e56fbec90ce421f107658c8314/rpds_py-2026.5.1-cp315-cp315t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:55d8f9b7b78c9538fc9e04e82ec0e888ff0c3cffcfad152c77e57cd09351a98a", size = 374775, upload-time = "2026-05-28T12:01:33.136Z" }, + { url = "https://files.pythonhosted.org/packages/ff/8f/15e5a61d9f0a43902d36561d4f07cae6ae9f4716be825159fd72717f33af/rpds_py-2026.5.1-cp315-cp315t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e3a8ae58895ac107ed934a6bf51e5846f95c53b9b940c2c6d310838fd5846358", size = 380270, upload-time = "2026-05-28T12:01:34.574Z" }, + { url = "https://files.pythonhosted.org/packages/02/c3/f859b12763a80540cdf2af0f15b19904cf756a71d7bdd3f82ff3e5b1bbf9/rpds_py-2026.5.1-cp315-cp315t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0957cf3c2b8632ec7aaebffebea8005b353cc2a237b6e2ae3c2cac0820704cfb", size = 495285, upload-time = "2026-05-28T12:01:36.127Z" }, + { url = "https://files.pythonhosted.org/packages/1c/c7/ff27c2ac8411d30b03b1829fd88cae8dad1a4d0da48dd25e57c4038042e6/rpds_py-2026.5.1-cp315-cp315t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c396c1304de421050b3681ea70f371874b54d41b0151e96109758144c231e30b", size = 389581, upload-time = "2026-05-28T12:01:37.635Z" }, + { url = "https://files.pythonhosted.org/packages/6e/67/fe92ee32a6cc05c77228a2f8b1762e7124f386ec20ff83d0757b762d58d0/rpds_py-2026.5.1-cp315-cp315t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aad1bff7f666b9598e573815affd666aac6a13a585dde336f843e33350c7fadc", size = 376041, upload-time = "2026-05-28T12:01:39.307Z" }, + { url = "https://files.pythonhosted.org/packages/f8/91/b4d6685c27aba55bd82f25b278be8237038117d05f9659a6213ad3408130/rpds_py-2026.5.1-cp315-cp315t-manylinux_2_31_riscv64.whl", hash = "sha256:656a042550878f12d45752452d47094b7cfe5ad1e9d7b87b5a22ad3ae5ff8015", size = 383946, upload-time = "2026-05-28T12:01:41.043Z" }, + { url = "https://files.pythonhosted.org/packages/bd/79/2c1d832a53c8e0f8e98fc970ec257b950fecd4f62be2ab7182b500a0cbc8/rpds_py-2026.5.1-cp315-cp315t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:73c4bd4f70294737b5206a3e8e30ccadbf8a60301831c8ea23eec5dbeea1ecfa", size = 405526, upload-time = "2026-05-28T12:01:43.032Z" }, + { url = "https://files.pythonhosted.org/packages/78/c4/c98117b03c6a8581ab2c2dfccfe9a5ad82bd8128a3c28b46a6ad2d97c393/rpds_py-2026.5.1-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:43bca78665423cabae77146f2fe7ce55272b6c8d55d82cca83effd42c7e13972", size = 551165, upload-time = "2026-05-28T12:01:44.648Z" }, + { url = "https://files.pythonhosted.org/packages/3b/c1/bc479ca069200af730881b1bd525e3114b2b391a351509fcb1b772f28086/rpds_py-2026.5.1-cp315-cp315t-musllinux_1_2_i686.whl", hash = "sha256:42d0f20e85e549c870749d0e247f0c10d318a45b7e9676d575d2dcb04a1b2e66", size = 618778, upload-time = "2026-05-28T12:01:46.337Z" }, + { url = "https://files.pythonhosted.org/packages/77/65/38ab2f90df44c2febfb63cc10ced40763d9b4bc94d173e734528663fe7f5/rpds_py-2026.5.1-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:b1be5c35683684d5331b93600c210e8367c254683d8a6df6bd21bd2da3a334fb", size = 581839, upload-time = "2026-05-28T12:01:48.109Z" }, + { url = "https://files.pythonhosted.org/packages/15/2d/ce1f605fe036aadd460e5822e578c6c7ec3a860936cca37d6e0f299daa77/rpds_py-2026.5.1-cp315-cp315t-win32.whl", hash = "sha256:75808f6c38ce7749bb68cc2770161aae5045e6c6f6781a9782e74b93304399df", size = 207866, upload-time = "2026-05-28T12:01:49.648Z" }, + { url = "https://files.pythonhosted.org/packages/79/cb/966040123eb102371559746908ef2c9471f4d43e17ec9a645a2258dab64b/rpds_py-2026.5.1-cp315-cp315t-win_amd64.whl", hash = "sha256:90bd6630002a1c7f09e7843dd79f0d24f3d2897cc25a753480917865d14f15b3", size = 225441, upload-time = "2026-05-28T12:01:51.408Z" }, + { url = "https://files.pythonhosted.org/packages/42/56/3fe0fb34820ff667be791b3a3c22b85e8bcba54e9c832f47438c191fa7be/rpds_py-2026.5.1-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:edf2765d84e42447f112ad877af8fe1db0089aaec5b28e88d6eab45e7fe99cea", size = 357151, upload-time = "2026-05-28T12:01:53.43Z" }, + { url = "https://files.pythonhosted.org/packages/8b/f2/3eb9ccdb9f143b8c9b003978898cb497f942a324c077401e6b8834238e63/rpds_py-2026.5.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:ad3773236e95f7f33991eb125224b7da66f206504d032a253a02da7e134519fb", size = 350195, upload-time = "2026-05-28T12:01:54.901Z" }, + { url = "https://files.pythonhosted.org/packages/a7/24/dbda232bc4f3ed732120692ab0d2c8402cb020516556d8bee622dcef2413/rpds_py-2026.5.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a04df86b3f0fade39ec8fd0e0aab089b1da9fbd2b48df778a57ef96f5e7d38df", size = 381850, upload-time = "2026-05-28T12:01:56.601Z" }, + { url = "https://files.pythonhosted.org/packages/40/30/32e769839a358f78810c234f160f2cc21d1e4e47e1c0e0e0d535be5a0219/rpds_py-2026.5.1-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6142dbd80c4df62a5d899f0d616d417f84e0bc8d32526c8e5589019d75d028a7", size = 387899, upload-time = "2026-05-28T12:01:58.212Z" }, + { url = "https://files.pythonhosted.org/packages/ab/86/ec84d243aadb3b34b71dd26a010d0930b2d284ff5fc9a69fec53810ee6fd/rpds_py-2026.5.1-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0b35217adefe87f2fe4db7e9766cabe84744bfe9616d9667be18988928c7f2dc", size = 501618, upload-time = "2026-05-28T12:01:59.888Z" }, + { url = "https://files.pythonhosted.org/packages/74/25/b60e52686bbff777a64f9e4f4d3dd57980dc846913777177a2c92e4937aa/rpds_py-2026.5.1-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b95d5e11fc712b752081183a55a244c03cd00570489edd7014d8899f8ceb8162", size = 394003, upload-time = "2026-05-28T12:02:01.482Z" }, + { url = "https://files.pythonhosted.org/packages/9b/c7/b3a6a588cc2219510ef3f42e207483a93950bedd1e3a0fd4015c95cff9e5/rpds_py-2026.5.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:141c9498daf2ace9eda35d2b0e376f9ea8b058d84f2aef4f96fccfd449a2f251", size = 379778, upload-time = "2026-05-28T12:02:03.197Z" }, + { url = "https://files.pythonhosted.org/packages/31/00/c7dba3fc8a3da8cb3f6db1eb3386be4d79c2e97c6890d20eb9ac66ae8c43/rpds_py-2026.5.1-pp311-pypy311_pp73-manylinux_2_31_riscv64.whl", hash = "sha256:6f249f8b860a200ad35193af961183ebe9132710484e6f6ce0cf89fd83c63a9a", size = 392359, upload-time = "2026-05-28T12:02:04.817Z" }, + { url = "https://files.pythonhosted.org/packages/93/dd/472ba494c70753f93745992c99855bee0636daf74e6984e5e003f150316f/rpds_py-2026.5.1-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e4abbf391a70be864920858bf360f4fb380577c9a0f732438a1996726e2c195b", size = 412820, upload-time = "2026-05-28T12:02:06.401Z" }, + { url = "https://files.pythonhosted.org/packages/1d/6f/93831a3bfe789542ed0c1d0d74b78b440f055d6dc3ea4640eba2d95e6e23/rpds_py-2026.5.1-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:c74005a7bb87752acf351c93897ec63ad77a07a0da7ecad9c050e32e7286ba34", size = 557243, upload-time = "2026-05-28T12:02:08.013Z" }, + { url = "https://files.pythonhosted.org/packages/1f/ff/0b3d604614ffc77522c6b288fdbce68957eb583da1002aa65ba38ac0ee40/rpds_py-2026.5.1-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:8213afbe8a3a906fb9acb2014423fe3359ee783d0bf90995f70623a3217bfa6c", size = 623541, upload-time = "2026-05-28T12:02:09.661Z" }, + { url = "https://files.pythonhosted.org/packages/ea/ea/e7b0251441da9adfeaebcf29601d10f2a1455fcf0772fae9e7e19032bd96/rpds_py-2026.5.1-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:8c43a8a973270fd173bf48cdf80bbe66312421cba68d40845034f174f2389049", size = 586326, upload-time = "2026-05-28T12:02:11.47Z" }, +] + +[[package]] +name = "ruff" +version = "0.15.20" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/43/dc/35b341fc554ba02f217fc10da57d1a75168cfbcf75b0ef2202176d4c4f2d/ruff-0.15.20.tar.gz", hash = "sha256:1416eb04349192646b54de98f146c4f59afe37d0decfc02c3cbbf396f3a28566", size = 4755489, upload-time = "2026-06-25T17:20:37.578Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/94/d9/2d5014f0253ba541d2061d9fa7193f48e941c8b21bb88a7ff9bbe0bd0596/ruff-0.15.20-py3-none-linux_armv6l.whl", hash = "sha256:00e188c53e499c3c1637f73c91dcf2fb56d576cab76ce1be50a27c4e80e37078", size = 10839665, upload-time = "2026-06-25T17:19:44.702Z" }, + { url = "https://files.pythonhosted.org/packages/c6/d3/ac1798ba64f670698867fcfc591d50e7e421bef137db564858f619a30fcf/ruff-0.15.20-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:9ebd1fd9b9c95fc0bd7b2761aebec1f030013d2e193a2901b224af68fe47251b", size = 11208649, upload-time = "2026-06-25T17:19:48.787Z" }, + { url = "https://files.pythonhosted.org/packages/47/47/d3ac899991202095dfcf3d5176be4272642be3cf981a2f1a30f72a2afb95/ruff-0.15.20-py3-none-macosx_11_0_arm64.whl", hash = "sha256:c5b16cdd67ca108185cd36dce98c576350c03b1660a751de725fb049193a0632", size = 10622638, upload-time = "2026-06-25T17:19:51.354Z" }, + { url = "https://files.pythonhosted.org/packages/33/13/4e043fe30aa94d4ff5213a9881fc296d12960f5971b234a5263fdc225312/ruff-0.15.20-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3413bb3c3d2ca6a8208f1f4809cd2dca3c6de6d0b491c0e70847672bde6e6efd", size = 10984227, upload-time = "2026-06-25T17:19:54.044Z" }, + { url = "https://files.pythonhosted.org/packages/76/e6/92e7bf40388bc5800073b96564f56264f7e48bfd1a498f5ced6ae6d5a769/ruff-0.15.20-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bd7ec42b3bb3da066488db093308a69c4ac5ee6d2af333a86ba6e2eb2e7dd44b", size = 10622882, upload-time = "2026-06-25T17:19:57.037Z" }, + { url = "https://files.pythonhosted.org/packages/13/7a/43460be3f24495a3aa46d4b16873e2c4941b3b5f0b00cf88c03b7b94b339/ruff-0.15.20-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e1a36ad0eb77fba9aabfb69ede54de6f376d04ac18ebea022847046d340a8267", size = 11474808, upload-time = "2026-06-25T17:20:00.357Z" }, + { url = "https://files.pythonhosted.org/packages/27/a0/f37077884873221c6b33b4ab49eb18f9f88e54a16a25a5bca59bef46dd66/ruff-0.15.20-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b6df3b1e4610432f0386dba04d853b5f08cbbc903410c6fcc02f620f05aff53c", size = 12293094, upload-time = "2026-06-25T17:20:03.446Z" }, + { url = "https://files.pythonhosted.org/packages/a6/74/165545b60256a9704c21ac0ec4a0d07933b320812f9584836c9f4aca4292/ruff-0.15.20-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e89f198a1ea6ef0d727c1cf16088bc91a6cb0ab947dedc966715691647186eae", size = 11526176, upload-time = "2026-06-25T17:20:06.301Z" }, + { url = "https://files.pythonhosted.org/packages/86/b1/a976a136d40ade83ce743578399865f57001003a409acadc0ecbb3051082/ruff-0.15.20-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:309809086c2acb67624950a3c8133e80f32d0d3e27106c0cd60ff26657c9f24b", size = 11520767, upload-time = "2026-06-25T17:20:09.191Z" }, + { url = "https://files.pythonhosted.org/packages/19/0f/f032696cb01c9b54c0263fa393474d7758f1cdc021a01b04e3cbc2500999/ruff-0.15.20-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:2d2374caa2f2c2f9e2b7da0a50802cfb8b79f55a9b5e49379f564544fbf56487", size = 11500132, upload-time = "2026-06-25T17:20:13.602Z" }, + { url = "https://files.pythonhosted.org/packages/4b/f4/51b1a14bc69e8c224b15dab9cce8e99b425e0455d462caa2b3c9be2b6a8e/ruff-0.15.20-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:a1ed17b65293e0c2f22fc387bc13198a5de94bf4429589b0ff6946b0feaf21a3", size = 10943828, upload-time = "2026-06-25T17:20:16.635Z" }, + { url = "https://files.pythonhosted.org/packages/71/4b/fe267640783cd02bf6c5cc290b1df1051be2ec294c678b5c15fe19e52343/ruff-0.15.20-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:f701305e66b38ea6c91882490eb73459796808e4c6362a1b765255e0cdcd4053", size = 10645418, upload-time = "2026-06-25T17:20:19.4Z" }, + { url = "https://files.pythonhosted.org/packages/b0/c0/a65aa4ec2f5e87a1df32dc3ec1fede434fe3dfd5cbcf3b503cafc676ab54/ruff-0.15.20-py3-none-musllinux_1_2_i686.whl", hash = "sha256:5b9c0c367ad8e5d0d5b5b8537864c469a0a0e55417aadfbeca41fa61333be9f4", size = 11211770, upload-time = "2026-06-25T17:20:22.033Z" }, + { url = "https://files.pythonhosted.org/packages/5a/a4/0caa331d954ae2723d729d351c989cb4ca8b6077d5c6c2cb6de75e98c041/ruff-0.15.20-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:01cc00dd58f0df339d0e902219dd53990ea99996a0344e5d9cc8d45d5307e460", size = 11618698, upload-time = "2026-06-25T17:20:25.259Z" }, + { url = "https://files.pythonhosted.org/packages/10/9b/5f14927848d2fd4aa891fd88d883788c5a7baba561c7874732364045708c/ruff-0.15.20-py3-none-win32.whl", hash = "sha256:ed65ef510e43a137207e0f01cfcf998aeddb1aeeda5c9d35023e910284d7cf21", size = 10857322, upload-time = "2026-06-25T17:20:28.612Z" }, + { url = "https://files.pythonhosted.org/packages/fa/f0/fe47c501f9dea92a26d788ff98bb5d92ed4cb4c88792c5c88af6b697dc8e/ruff-0.15.20-py3-none-win_amd64.whl", hash = "sha256:a525c81c70fb0380344dd1d8745d8cc1c890b7fc94a58d5a07bd8eb9557b8415", size = 11993274, upload-time = "2026-06-25T17:20:31.871Z" }, + { url = "https://files.pythonhosted.org/packages/d7/2b/9555445e1201d92b3195f45cdb153a0b68f24e0a4273f6e3d5ab46e212bb/ruff-0.15.20-py3-none-win_arm64.whl", hash = "sha256:2f5b2a6d614e8700388806a14996c40fab2c47b819ef57d790a34878858ed9ca", size = 11343498, upload-time = "2026-06-25T17:20:35.03Z" }, +] + +[[package]] +name = "safetensors" +version = "0.8.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/45/06/f955dbbb1859e3bd23c8ac6141af5106e7ad5fedec4a3a6e3d60f94b7001/safetensors-0.8.0.tar.gz", hash = "sha256:fabaf3e0f18a6618d9b36560682562157f77c2b71fcffc7b432be2baed9d753d", size = 325846, upload-time = "2026-06-09T07:52:25.563Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/39/a0/f718cda65b05407d228f97602cf60dca269c979867aa5beb25410de26cd3/safetensors-0.8.0-cp310-abi3-macosx_10_12_x86_64.whl", hash = "sha256:c554f85858e05226d3c2828e32395e677434685d6d94594a41643361c5e837f0", size = 473568, upload-time = "2026-06-09T07:52:18.829Z" }, + { url = "https://files.pythonhosted.org/packages/f5/b1/fa7c600e7dceae12e9606c7578cbc9ff1e1ed55844883ee5c92205e86226/safetensors-0.8.0-cp310-abi3-macosx_11_0_arm64.whl", hash = "sha256:c80201d22cbf405b80647a60ada77bba06c8fba2da2743ba1e89cdcc39a81f25", size = 484562, upload-time = "2026-06-09T07:52:17.518Z" }, + { url = "https://files.pythonhosted.org/packages/09/7d/65a7de0af421317bb36a067241e4235fff194eed60b961ed6d3f59a3fc60/safetensors-0.8.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7a46e5ff292c356d6991e60942ba7f79817682d3a2cef0702136448cb9c4d235", size = 502844, upload-time = "2026-06-09T07:52:07.624Z" }, + { url = "https://files.pythonhosted.org/packages/91/4f/3175c9d75634e0e0dda0082794193521035edd7c70a6f212bf33ca06ddf4/safetensors-0.8.0-cp310-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4124502b78f03534117c848f87a39b8f31e577b15eff423bf8bfb95f2a8c30d0", size = 511823, upload-time = "2026-06-09T07:52:09.565Z" }, + { url = "https://files.pythonhosted.org/packages/20/87/846c289e7aa2299eff406335717cf43ce8777194ece8aad75772e0411615/safetensors-0.8.0-cp310-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7bc0a787ba8a35be368ee3574edfa2b1ad389eebd0a72e482ae275490e3f6c98", size = 633461, upload-time = "2026-06-09T07:52:11.128Z" }, + { url = "https://files.pythonhosted.org/packages/76/22/8d64d9df2c45d5ded401df889d0ad90882804ca172d79ec4f0df8f727fe0/safetensors-0.8.0-cp310-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:040070828e36dc8e122178bbbd5830ff9e97920affb84cbe0f46442497bed358", size = 545148, upload-time = "2026-06-09T07:52:13.603Z" }, + { url = "https://files.pythonhosted.org/packages/28/50/f203ff3a3ddfe19308efc83c5a3a29ed02bf786732ec35e68bf9162f3365/safetensors-0.8.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd6f3f93c9a0a7cc2788ee63fb763353d4bd2e89b0751bc78fcf7dda00bea774", size = 516040, upload-time = "2026-06-09T07:52:16.29Z" }, + { url = "https://files.pythonhosted.org/packages/46/fb/cdaed17ceb2948784fd9c36b6fd3e951b608547cea81a48e8ee6f8cfdfcb/safetensors-0.8.0-cp310-abi3-manylinux_2_31_riscv64.whl", hash = "sha256:fcdd41ec4628fee5799f807c73c353629130fbd942aa23d83c623dd6c9d52d78", size = 513832, upload-time = "2026-06-09T07:52:12.37Z" }, + { url = "https://files.pythonhosted.org/packages/0d/49/1e15de264dcc3b77943d2d0c56a95809956883b1c2d6d585c792523f180b/safetensors-0.8.0-cp310-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8e9f537aa183a38ace122d27303dcd986b26bd2a7591f9181d7f0c396f4677ca", size = 559930, upload-time = "2026-06-09T07:52:14.743Z" }, + { url = "https://files.pythonhosted.org/packages/2a/43/bf38443278eab4b1be1fce2931e2b012ad9cb7df52ada751d0aab8f7659a/safetensors-0.8.0-cp310-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:87eec7ffed2b809f05a398a8becb7d013f19f7837cd15d9748580d6cf30dbaf4", size = 678670, upload-time = "2026-06-09T07:52:20.032Z" }, + { url = "https://files.pythonhosted.org/packages/72/e3/68cd3fa5b48488e84add63e04cb12f3bc28ae4638c06d4508c6e88823d0e/safetensors-0.8.0-cp310-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:4a95ae2b05d7726d751da4ebf626a2ca782b706e101bd894c95bc2450b1cffcc", size = 786679, upload-time = "2026-06-09T07:52:21.322Z" }, + { url = "https://files.pythonhosted.org/packages/29/4b/1c19c509d56e01f4fbb3d0a2e597450f6cc04d1d56cf52defb0a62dfd715/safetensors-0.8.0-cp310-abi3-musllinux_1_2_i686.whl", hash = "sha256:3ae091f16662658bdc019a4ff6cb4c085bb7d725eb5978b183ffd265863b6d2d", size = 765683, upload-time = "2026-06-09T07:52:22.594Z" }, + { url = "https://files.pythonhosted.org/packages/27/43/41c1621732edd934d868a00d1b891584c892a7b62a9aab82ea5a0a5623ee/safetensors-0.8.0-cp310-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:8e080062fcde23be189565e1c3305d16751a218ecf9412c8601e64204eb6f846", size = 722361, upload-time = "2026-06-09T07:52:23.924Z" }, + { url = "https://files.pythonhosted.org/packages/8e/3f/73ccf82579412b4a71c4ca673f10b5f1f888d7cf5af7fe24f27d30307be4/safetensors-0.8.0-cp310-abi3-win32.whl", hash = "sha256:2ddf52eac562eda224f99acfa7889d02968c1fd59a5b011ae7d8137c37e9c02d", size = 342401, upload-time = "2026-06-09T07:52:28.895Z" }, + { url = "https://files.pythonhosted.org/packages/1b/6d/3fba214c1e5e0f69991677ec3bc17023f0421776975e1de0c682dca475e2/safetensors-0.8.0-cp310-abi3-win_amd64.whl", hash = "sha256:096ec1a98435df7beb08853bb5aa9081a84f23d0adc67ed1a0a10550f608373f", size = 355540, upload-time = "2026-06-09T07:52:27.832Z" }, + { url = "https://files.pythonhosted.org/packages/8d/fc/7eedc3510d97878876e32774eebbeb61c43f148a96e915c84229a3e967aa/safetensors-0.8.0-cp310-abi3-win_arm64.whl", hash = "sha256:f7838e5135a406ad3e02efdcb8cf2e5397d368b0154537c4fec682dbc544d452", size = 340500, upload-time = "2026-06-09T07:52:26.745Z" }, +] + +[[package]] +name = "scikit-learn" +version = "1.9.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "joblib" }, + { name = "narwhals" }, + { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12'" }, + { name = "numpy", version = "2.5.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12'" }, + { name = "scipy", version = "1.17.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12'" }, + { name = "scipy", version = "1.18.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12'" }, + { name = "threadpoolctl" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/fa/6f/37092bdb25f712817231799fc5674d8e704066a8a70c1d2d40517e18b4ab/scikit_learn-1.9.0.tar.gz", hash = "sha256:8833266989d3a5110178a9fae30783675460724d0e1efb13b14901d2c660c557", size = 7750767, upload-time = "2026-06-02T11:54:32.706Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f5/be/e844fd9586e66540a15b71924d17a6cbc1bb749e81ddd0a796bcdba4c055/scikit_learn-1.9.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9db6f4d34e68c8899e4cab27fdf8eafe6ed21f2ba52ceb25ea250cd237f8e47b", size = 8789686, upload-time = "2026-06-02T11:53:05.439Z" }, + { url = "https://files.pythonhosted.org/packages/42/e2/ff880f62677a17d035817d543cb0fc8727d01eccbee81c5f7fc733a9d856/scikit_learn-1.9.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:f401448645a3e7bc115aa3c094097865155b34bff1cba8101857d9104e99074c", size = 8256782, upload-time = "2026-06-02T11:53:08.904Z" }, + { url = "https://files.pythonhosted.org/packages/25/64/eb40435e1a508ab1b4e284ce43ae80f6a162e5be5e38ed5a6fab467a9ea4/scikit_learn-1.9.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fd3a8ef0c758555a3b23c03adaa858af32f7736785ded50ad5991f59c4ed03fa", size = 8992419, upload-time = "2026-06-02T11:53:11.551Z" }, + { url = "https://files.pythonhosted.org/packages/8d/da/4810a28e473185429e45a57eebcc91fc991b33d889cc0676063e671db03d/scikit_learn-1.9.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f7e254636164090da847715a27f8e5478feb98c40a9e0ee90cbd277de9e5ceb8", size = 9281411, upload-time = "2026-06-02T11:53:15.063Z" }, + { url = "https://files.pythonhosted.org/packages/3b/67/be3d369f40d8178ba3bd86635d132e08cb5329b023e4669d9426d84bc007/scikit_learn-1.9.0-cp311-cp311-win_amd64.whl", hash = "sha256:5dc1818c77575d149e25fce9ef82dd7b7263ae372f03494158668ad632a69759", size = 8272736, upload-time = "2026-06-02T11:53:18.108Z" }, + { url = "https://files.pythonhosted.org/packages/37/79/a733f02dc2118da7e77a134b34f39f40201a353311b011d20859d2db3556/scikit_learn-1.9.0-cp311-cp311-win_arm64.whl", hash = "sha256:366652351f092b219c248f1e72821e841960a63d8f358f1dcfd54dc1cbdbbc28", size = 7919564, upload-time = "2026-06-02T11:53:21.2Z" }, + { url = "https://files.pythonhosted.org/packages/ac/20/75f915ff375d6249e6550ac740fdbbd66159a068fd3af1400ff62036b07a/scikit_learn-1.9.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2bd41b0d201bc81575531b96b713d3eb5e5f50fb0b82101ff0f92294fdc236ac", size = 8741122, upload-time = "2026-06-02T11:53:24.08Z" }, + { url = "https://files.pythonhosted.org/packages/cc/d5/2b5148f2279196775e1db2aeb85d14b70ac80e7e32b3b28e7ebeafb0901d/scikit_learn-1.9.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:5be45aa4a42a68a533913a6ed736cf309de2226411c79ef8d609a5456f1939b1", size = 8261512, upload-time = "2026-06-02T11:53:27.183Z" }, + { url = "https://files.pythonhosted.org/packages/a0/ee/5adbc77656b71f9456a2f5a7a9fdb4bcf9207a6b962889f1c2f9323afa4e/scikit_learn-1.9.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5e50ed4da51974e86e940690e9a3d82e729b62b5a49f7c9bac534d515d39d86f", size = 8837603, upload-time = "2026-06-02T11:53:30.328Z" }, + { url = "https://files.pythonhosted.org/packages/6c/c2/63fdda36c56437eeb44aaf9493c8bcd62ce230ab1598924fc626ffbfa943/scikit_learn-1.9.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:056c92bb67ad4c28463c2f2653d9701449201e7e7a9e94e321be0f71c4fef2b8", size = 9132097, upload-time = "2026-06-02T11:53:33.456Z" }, + { url = "https://files.pythonhosted.org/packages/83/a4/c8e67227c680e2259c8864ae72ff48b06e16a6f51253a22167aa02a8aa4e/scikit_learn-1.9.0-cp312-cp312-win_amd64.whl", hash = "sha256:4306775fad04cc4b472a1b15af1ae9cede1540fbfcc17fbce3767cd8dc7ae283", size = 8211173, upload-time = "2026-06-02T11:53:36.602Z" }, + { url = "https://files.pythonhosted.org/packages/cf/fd/3c0863792e98e67e9184aa4029288a175935eb65443afcd30d4f143450cf/scikit_learn-1.9.0-cp312-cp312-win_arm64.whl", hash = "sha256:26e22435f63bcdcf396b574273f29f13dd531f5ea035801f5be10ba1540a4e60", size = 7867451, upload-time = "2026-06-02T11:53:39.075Z" }, + { url = "https://files.pythonhosted.org/packages/3c/01/cf3310626b6d48d3e9be69a1223f9180360b5e6edb045f50fade723ce494/scikit_learn-1.9.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:80746d63bd4b6eaca54d36fe5feaf4d28bb38dc6f9470f81c7cad7c40155f119", size = 8705188, upload-time = "2026-06-02T11:53:41.964Z" }, + { url = "https://files.pythonhosted.org/packages/3e/04/5acd7ae280c5f93b6ac5ef6cdec14eef4c8d1cd91d85b3292989c94d96b1/scikit_learn-1.9.0-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:5b934c45c252844a91d69fda3a34cff5e7307e1db10d77cb10a3980312c74713", size = 8228299, upload-time = "2026-06-02T11:53:44.817Z" }, + { url = "https://files.pythonhosted.org/packages/0c/39/ffe829a5b8ecb40a518724a997794657fdc354ada5e8fe8e64d998c0bac9/scikit_learn-1.9.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:38c3dcb9a1ffb85505ec53d54c7b4aea0cff70050425a7760c2af661ac85df05", size = 8789690, upload-time = "2026-06-02T11:53:47.461Z" }, + { url = "https://files.pythonhosted.org/packages/1f/88/8dab5de10c638c083772a6be83a3d8106ced492f74a928c8693638e5bb50/scikit_learn-1.9.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:da76d09304a4706db7cc1e3ebaa3b6b98a67365cc11d2996c4f1e58ba47df714", size = 9087723, upload-time = "2026-06-02T11:53:50.702Z" }, + { url = "https://files.pythonhosted.org/packages/20/3f/7917ca72464038f6240ec70c29f94862d08a34a74291ae4d4ec5eb8186a0/scikit_learn-1.9.0-cp313-cp313-win_amd64.whl", hash = "sha256:5808d98f15c6bf6d9d96d2348c1997392a5888ce7097e664105f930c4bca1277", size = 8184330, upload-time = "2026-06-02T11:53:53.396Z" }, + { url = "https://files.pythonhosted.org/packages/78/c7/15739eb2f61fda3c54639e9942414e5a19ad8a8d1f5a3266afad7cb7df80/scikit_learn-1.9.0-cp313-cp313-win_arm64.whl", hash = "sha256:d77f54c017633791bc0225a43e2f8d03745fdcfe4880268fcc4df15f505dec2e", size = 7840653, upload-time = "2026-06-02T11:53:56.035Z" }, + { url = "https://files.pythonhosted.org/packages/f4/7d/c9a35cf59b20a86fec24d306f1547b78dec194b08d367ce2a3e4854169d9/scikit_learn-1.9.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:9656acd4e93f74e0b66c8a36c88830a99252dfa900044d36bc2212ae89a47162", size = 8713289, upload-time = "2026-06-02T11:53:58.788Z" }, + { url = "https://files.pythonhosted.org/packages/3c/a7/552a7821597c632b907f7bfe8f36f9f572777af8ef8a48353041cf8e091a/scikit_learn-1.9.0-cp314-cp314-macosx_12_0_arm64.whl", hash = "sha256:24360002ae845e7866522b0a5bbf690802e7bc388cac8663502e78aa98598aa2", size = 8245141, upload-time = "2026-06-02T11:54:01.694Z" }, + { url = "https://files.pythonhosted.org/packages/7d/79/f4a0c4fe9711154cddabf913471153af79056382ddc612cfe5ee0ff4b72e/scikit_learn-1.9.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5162ad10a418c8a282dde04c9aa06965de3e9a65f33c1440c0ae69bb1a09d913", size = 8847671, upload-time = "2026-06-02T11:54:04.448Z" }, + { url = "https://files.pythonhosted.org/packages/f0/af/4d72d9e475ac83719160c662619e4bf7b95c19507cd582e7d0167a3c3dae/scikit_learn-1.9.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1fea2cc5677ab49d6f5bade978c866da44957b712d92e9635e8b4f723013c3cb", size = 9118104, upload-time = "2026-06-02T11:54:07.205Z" }, + { url = "https://files.pythonhosted.org/packages/a2/d5/6a58eea2cb9abbb9b3f2bb8b2cfb3243d1152d69f442d256c7af71304769/scikit_learn-1.9.0-cp314-cp314-win_amd64.whl", hash = "sha256:64fa347efc1c839c487433e40c5144d38c336e8a2b59c81aa8660373945c2673", size = 8290674, upload-time = "2026-06-02T11:54:10.087Z" }, + { url = "https://files.pythonhosted.org/packages/65/5b/d4c879cf358f1187141cf90ced473f087183489090244f50c124a2ee478b/scikit_learn-1.9.0-cp314-cp314-win_arm64.whl", hash = "sha256:1b944b6db288f6b926e3650026ddafb988929de95d11fc2cc5fa117773c9ba42", size = 7978807, upload-time = "2026-06-02T11:54:12.769Z" }, + { url = "https://files.pythonhosted.org/packages/8a/43/bfae3121ec67ae09150d453c442c7c1cc166e9aefe056e6ab3b7728a5cfc/scikit_learn-1.9.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:4ccacf04ca5f4b492158a5f28afe0ace43f81b2571e4b9a66d34848b46128949", size = 9031941, upload-time = "2026-06-02T11:54:15.436Z" }, + { url = "https://files.pythonhosted.org/packages/75/b0/20a4546eb17f3b25d3c66df15810411c14ed5065bcfab50b53c96fb627b2/scikit_learn-1.9.0-cp314-cp314t-macosx_12_0_arm64.whl", hash = "sha256:ee1a8db2c18c08e34c7412d4b10be1cac214cd4ea7dc9715a6a327eb49a37c96", size = 8613528, upload-time = "2026-06-02T11:54:18.842Z" }, + { url = "https://files.pythonhosted.org/packages/18/3c/e440e039bb82cd19004edaaad00acbde0fb9b461083c3ecf37941c557312/scikit_learn-1.9.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:147e9329ef0e39f75d4cffa02b2aa48d827832684926cd5210d9a2cb5c57246b", size = 8855050, upload-time = "2026-06-02T11:54:21.699Z" }, + { url = "https://files.pythonhosted.org/packages/43/26/b341b8dab5998da6270a3a42c2152c578501354d36f944b5856757035ef8/scikit_learn-1.9.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5bad8f8b9950321b54c965fdcbac6c6c55e79e16646b49977bcf3668d3870a1a", size = 9097190, upload-time = "2026-06-02T11:54:24.454Z" }, + { url = "https://files.pythonhosted.org/packages/fb/de/b650b4d69b84468cfa2e28a3ff7b8103743029e6446ce1a97fe060ef688c/scikit_learn-1.9.0-cp314-cp314t-win_amd64.whl", hash = "sha256:78fc56eafd4edb9575d2d8950d1dd152061abb573341a1cb7e099fc40f6c6666", size = 8963204, upload-time = "2026-06-02T11:54:27.428Z" }, + { url = "https://files.pythonhosted.org/packages/ee/f3/ff83d76d7418112e5a61326443cdda87be3545dd8d6599c95b2481a4419e/scikit_learn-1.9.0-cp314-cp314t-win_arm64.whl", hash = "sha256:051075bda8b7aab87b1906ab3d4740a1e1224a19d7b3781a576736edc94e76aa", size = 8222661, upload-time = "2026-06-02T11:54:30.192Z" }, +] + +[[package]] +name = "scipy" +version = "1.17.1" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.12' and sys_platform == 'win32'", + "python_full_version < '3.12' and sys_platform != 'win32'", +] +dependencies = [ + { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7a/97/5a3609c4f8d58b039179648e62dd220f89864f56f7357f5d4f45c29eb2cc/scipy-1.17.1.tar.gz", hash = "sha256:95d8e012d8cb8816c226aef832200b1d45109ed4464303e997c5b13122b297c0", size = 30573822, upload-time = "2026-02-23T00:26:24.851Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/df/75/b4ce781849931fef6fd529afa6b63711d5a733065722d0c3e2724af9e40a/scipy-1.17.1-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:1f95b894f13729334fb990162e911c9e5dc1ab390c58aa6cbecb389c5b5e28ec", size = 31613675, upload-time = "2026-02-23T00:16:00.13Z" }, + { url = "https://files.pythonhosted.org/packages/f7/58/bccc2861b305abdd1b8663d6130c0b3d7cc22e8d86663edbc8401bfd40d4/scipy-1.17.1-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:e18f12c6b0bc5a592ed23d3f7b891f68fd7f8241d69b7883769eb5d5dfb52696", size = 28162057, upload-time = "2026-02-23T00:16:09.456Z" }, + { url = "https://files.pythonhosted.org/packages/6d/ee/18146b7757ed4976276b9c9819108adbc73c5aad636e5353e20746b73069/scipy-1.17.1-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:a3472cfbca0a54177d0faa68f697d8ba4c80bbdc19908c3465556d9f7efce9ee", size = 20334032, upload-time = "2026-02-23T00:16:17.358Z" }, + { url = "https://files.pythonhosted.org/packages/ec/e6/cef1cf3557f0c54954198554a10016b6a03b2ec9e22a4e1df734936bd99c/scipy-1.17.1-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:766e0dc5a616d026a3a1cffa379af959671729083882f50307e18175797b3dfd", size = 22709533, upload-time = "2026-02-23T00:16:25.791Z" }, + { url = "https://files.pythonhosted.org/packages/4d/60/8804678875fc59362b0fb759ab3ecce1f09c10a735680318ac30da8cd76b/scipy-1.17.1-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:744b2bf3640d907b79f3fd7874efe432d1cf171ee721243e350f55234b4cec4c", size = 33062057, upload-time = "2026-02-23T00:16:36.931Z" }, + { url = "https://files.pythonhosted.org/packages/09/7d/af933f0f6e0767995b4e2d705a0665e454d1c19402aa7e895de3951ebb04/scipy-1.17.1-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:43af8d1f3bea642559019edfe64e9b11192a8978efbd1539d7bc2aaa23d92de4", size = 35349300, upload-time = "2026-02-23T00:16:49.108Z" }, + { url = "https://files.pythonhosted.org/packages/b4/3d/7ccbbdcbb54c8fdc20d3b6930137c782a163fa626f0aef920349873421ba/scipy-1.17.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:cd96a1898c0a47be4520327e01f874acfd61fb48a9420f8aa9f6483412ffa444", size = 35127333, upload-time = "2026-02-23T00:17:01.293Z" }, + { url = "https://files.pythonhosted.org/packages/e8/19/f926cb11c42b15ba08e3a71e376d816ac08614f769b4f47e06c3580c836a/scipy-1.17.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4eb6c25dd62ee8d5edf68a8e1c171dd71c292fdae95d8aeb3dd7d7de4c364082", size = 37741314, upload-time = "2026-02-23T00:17:12.576Z" }, + { url = "https://files.pythonhosted.org/packages/95/da/0d1df507cf574b3f224ccc3d45244c9a1d732c81dcb26b1e8a766ae271a8/scipy-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:d30e57c72013c2a4fe441c2fcb8e77b14e152ad48b5464858e07e2ad9fbfceff", size = 36607512, upload-time = "2026-02-23T00:17:23.424Z" }, + { url = "https://files.pythonhosted.org/packages/68/7f/bdd79ceaad24b671543ffe0ef61ed8e659440eb683b66f033454dcee90eb/scipy-1.17.1-cp311-cp311-win_arm64.whl", hash = "sha256:9ecb4efb1cd6e8c4afea0daa91a87fbddbce1b99d2895d151596716c0b2e859d", size = 24599248, upload-time = "2026-02-23T00:17:34.561Z" }, + { url = "https://files.pythonhosted.org/packages/35/48/b992b488d6f299dbe3f11a20b24d3dda3d46f1a635ede1c46b5b17a7b163/scipy-1.17.1-cp312-cp312-macosx_10_14_x86_64.whl", hash = "sha256:35c3a56d2ef83efc372eaec584314bd0ef2e2f0d2adb21c55e6ad5b344c0dcb8", size = 31610954, upload-time = "2026-02-23T00:17:49.855Z" }, + { url = "https://files.pythonhosted.org/packages/b2/02/cf107b01494c19dc100f1d0b7ac3cc08666e96ba2d64db7626066cee895e/scipy-1.17.1-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:fcb310ddb270a06114bb64bbe53c94926b943f5b7f0842194d585c65eb4edd76", size = 28172662, upload-time = "2026-02-23T00:18:01.64Z" }, + { url = "https://files.pythonhosted.org/packages/cf/a9/599c28631bad314d219cf9ffd40e985b24d603fc8a2f4ccc5ae8419a535b/scipy-1.17.1-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:cc90d2e9c7e5c7f1a482c9875007c095c3194b1cfedca3c2f3291cdc2bc7c086", size = 20344366, upload-time = "2026-02-23T00:18:12.015Z" }, + { url = "https://files.pythonhosted.org/packages/35/f5/906eda513271c8deb5af284e5ef0206d17a96239af79f9fa0aebfe0e36b4/scipy-1.17.1-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:c80be5ede8f3f8eded4eff73cc99a25c388ce98e555b17d31da05287015ffa5b", size = 22704017, upload-time = "2026-02-23T00:18:21.502Z" }, + { url = "https://files.pythonhosted.org/packages/da/34/16f10e3042d2f1d6b66e0428308ab52224b6a23049cb2f5c1756f713815f/scipy-1.17.1-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e19ebea31758fac5893a2ac360fedd00116cbb7628e650842a6691ba7ca28a21", size = 32927842, upload-time = "2026-02-23T00:18:35.367Z" }, + { url = "https://files.pythonhosted.org/packages/01/8e/1e35281b8ab6d5d72ebe9911edcdffa3f36b04ed9d51dec6dd140396e220/scipy-1.17.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:02ae3b274fde71c5e92ac4d54bc06c42d80e399fec704383dcd99b301df37458", size = 35235890, upload-time = "2026-02-23T00:18:49.188Z" }, + { url = "https://files.pythonhosted.org/packages/c5/5c/9d7f4c88bea6e0d5a4f1bc0506a53a00e9fcb198de372bfe4d3652cef482/scipy-1.17.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8a604bae87c6195d8b1045eddece0514d041604b14f2727bbc2b3020172045eb", size = 35003557, upload-time = "2026-02-23T00:18:54.74Z" }, + { url = "https://files.pythonhosted.org/packages/65/94/7698add8f276dbab7a9de9fb6b0e02fc13ee61d51c7c3f85ac28b65e1239/scipy-1.17.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f590cd684941912d10becc07325a3eeb77886fe981415660d9265c4c418d0bea", size = 37625856, upload-time = "2026-02-23T00:19:00.307Z" }, + { url = "https://files.pythonhosted.org/packages/a2/84/dc08d77fbf3d87d3ee27f6a0c6dcce1de5829a64f2eae85a0ecc1f0daa73/scipy-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:41b71f4a3a4cab9d366cd9065b288efc4d4f3c0b37a91a8e0947fb5bd7f31d87", size = 36549682, upload-time = "2026-02-23T00:19:07.67Z" }, + { url = "https://files.pythonhosted.org/packages/bc/98/fe9ae9ffb3b54b62559f52dedaebe204b408db8109a8c66fdd04869e6424/scipy-1.17.1-cp312-cp312-win_arm64.whl", hash = "sha256:f4115102802df98b2b0db3cce5cb9b92572633a1197c77b7553e5203f284a5b3", size = 24547340, upload-time = "2026-02-23T00:19:12.024Z" }, + { url = "https://files.pythonhosted.org/packages/76/27/07ee1b57b65e92645f219b37148a7e7928b82e2b5dbeccecb4dff7c64f0b/scipy-1.17.1-cp313-cp313-macosx_10_14_x86_64.whl", hash = "sha256:5e3c5c011904115f88a39308379c17f91546f77c1667cea98739fe0fccea804c", size = 31590199, upload-time = "2026-02-23T00:19:17.192Z" }, + { url = "https://files.pythonhosted.org/packages/ec/ae/db19f8ab842e9b724bf5dbb7db29302a91f1e55bc4d04b1025d6d605a2c5/scipy-1.17.1-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:6fac755ca3d2c3edcb22f479fceaa241704111414831ddd3bc6056e18516892f", size = 28154001, upload-time = "2026-02-23T00:19:22.241Z" }, + { url = "https://files.pythonhosted.org/packages/5b/58/3ce96251560107b381cbd6e8413c483bbb1228a6b919fa8652b0d4090e7f/scipy-1.17.1-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:7ff200bf9d24f2e4d5dc6ee8c3ac64d739d3a89e2326ba68aaf6c4a2b838fd7d", size = 20325719, upload-time = "2026-02-23T00:19:26.329Z" }, + { url = "https://files.pythonhosted.org/packages/b2/83/15087d945e0e4d48ce2377498abf5ad171ae013232ae31d06f336e64c999/scipy-1.17.1-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:4b400bdc6f79fa02a4d86640310dde87a21fba0c979efff5248908c6f15fad1b", size = 22683595, upload-time = "2026-02-23T00:19:30.304Z" }, + { url = "https://files.pythonhosted.org/packages/b4/e0/e58fbde4a1a594c8be8114eb4aac1a55bcd6587047efc18a61eb1f5c0d30/scipy-1.17.1-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2b64ca7d4aee0102a97f3ba22124052b4bd2152522355073580bf4845e2550b6", size = 32896429, upload-time = "2026-02-23T00:19:35.536Z" }, + { url = "https://files.pythonhosted.org/packages/f5/5f/f17563f28ff03c7b6799c50d01d5d856a1d55f2676f537ca8d28c7f627cd/scipy-1.17.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:581b2264fc0aa555f3f435a5944da7504ea3a065d7029ad60e7c3d1ae09c5464", size = 35203952, upload-time = "2026-02-23T00:19:42.259Z" }, + { url = "https://files.pythonhosted.org/packages/8d/a5/9afd17de24f657fdfe4df9a3f1ea049b39aef7c06000c13db1530d81ccca/scipy-1.17.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:beeda3d4ae615106d7094f7e7cef6218392e4465cc95d25f900bebabfded0950", size = 34979063, upload-time = "2026-02-23T00:19:47.547Z" }, + { url = "https://files.pythonhosted.org/packages/8b/13/88b1d2384b424bf7c924f2038c1c409f8d88bb2a8d49d097861dd64a57b2/scipy-1.17.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6609bc224e9568f65064cfa72edc0f24ee6655b47575954ec6339534b2798369", size = 37598449, upload-time = "2026-02-23T00:19:53.238Z" }, + { url = "https://files.pythonhosted.org/packages/35/e5/d6d0e51fc888f692a35134336866341c08655d92614f492c6860dc45bb2c/scipy-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:37425bc9175607b0268f493d79a292c39f9d001a357bebb6b88fdfaff13f6448", size = 36510943, upload-time = "2026-02-23T00:20:50.89Z" }, + { url = "https://files.pythonhosted.org/packages/2a/fd/3be73c564e2a01e690e19cc618811540ba5354c67c8680dce3281123fb79/scipy-1.17.1-cp313-cp313-win_arm64.whl", hash = "sha256:5cf36e801231b6a2059bf354720274b7558746f3b1a4efb43fcf557ccd484a87", size = 24545621, upload-time = "2026-02-23T00:20:55.871Z" }, + { url = "https://files.pythonhosted.org/packages/6f/6b/17787db8b8114933a66f9dcc479a8272e4b4da75fe03b0c282f7b0ade8cd/scipy-1.17.1-cp313-cp313t-macosx_10_14_x86_64.whl", hash = "sha256:d59c30000a16d8edc7e64152e30220bfbd724c9bbb08368c054e24c651314f0a", size = 31936708, upload-time = "2026-02-23T00:19:58.694Z" }, + { url = "https://files.pythonhosted.org/packages/38/2e/524405c2b6392765ab1e2b722a41d5da33dc5c7b7278184a8ad29b6cb206/scipy-1.17.1-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:010f4333c96c9bb1a4516269e33cb5917b08ef2166d5556ca2fd9f082a9e6ea0", size = 28570135, upload-time = "2026-02-23T00:20:03.934Z" }, + { url = "https://files.pythonhosted.org/packages/fd/c3/5bd7199f4ea8556c0c8e39f04ccb014ac37d1468e6cfa6a95c6b3562b76e/scipy-1.17.1-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:2ceb2d3e01c5f1d83c4189737a42d9cb2fc38a6eeed225e7515eef71ad301dce", size = 20741977, upload-time = "2026-02-23T00:20:07.935Z" }, + { url = "https://files.pythonhosted.org/packages/d9/b8/8ccd9b766ad14c78386599708eb745f6b44f08400a5fd0ade7cf89b6fc93/scipy-1.17.1-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:844e165636711ef41f80b4103ed234181646b98a53c8f05da12ca5ca289134f6", size = 23029601, upload-time = "2026-02-23T00:20:12.161Z" }, + { url = "https://files.pythonhosted.org/packages/6d/a0/3cb6f4d2fb3e17428ad2880333cac878909ad1a89f678527b5328b93c1d4/scipy-1.17.1-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:158dd96d2207e21c966063e1635b1063cd7787b627b6f07305315dd73d9c679e", size = 33019667, upload-time = "2026-02-23T00:20:17.208Z" }, + { url = "https://files.pythonhosted.org/packages/f3/c3/2d834a5ac7bf3a0c806ad1508efc02dda3c8c61472a56132d7894c312dea/scipy-1.17.1-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:74cbb80d93260fe2ffa334efa24cb8f2f0f622a9b9febf8b483c0b865bfb3475", size = 35264159, upload-time = "2026-02-23T00:20:23.087Z" }, + { url = "https://files.pythonhosted.org/packages/4d/77/d3ed4becfdbd217c52062fafe35a72388d1bd82c2d0ba5ca19d6fcc93e11/scipy-1.17.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:dbc12c9f3d185f5c737d801da555fb74b3dcfa1a50b66a1a93e09190f41fab50", size = 35102771, upload-time = "2026-02-23T00:20:28.636Z" }, + { url = "https://files.pythonhosted.org/packages/bd/12/d19da97efde68ca1ee5538bb261d5d2c062f0c055575128f11a2730e3ac1/scipy-1.17.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:94055a11dfebe37c656e70317e1996dc197e1a15bbcc351bcdd4610e128fe1ca", size = 37665910, upload-time = "2026-02-23T00:20:34.743Z" }, + { url = "https://files.pythonhosted.org/packages/06/1c/1172a88d507a4baaf72c5a09bb6c018fe2ae0ab622e5830b703a46cc9e44/scipy-1.17.1-cp313-cp313t-win_amd64.whl", hash = "sha256:e30bdeaa5deed6bc27b4cc490823cd0347d7dae09119b8803ae576ea0ce52e4c", size = 36562980, upload-time = "2026-02-23T00:20:40.575Z" }, + { url = "https://files.pythonhosted.org/packages/70/b0/eb757336e5a76dfa7911f63252e3b7d1de00935d7705cf772db5b45ec238/scipy-1.17.1-cp313-cp313t-win_arm64.whl", hash = "sha256:a720477885a9d2411f94a93d16f9d89bad0f28ca23c3f8daa521e2dcc3f44d49", size = 24856543, upload-time = "2026-02-23T00:20:45.313Z" }, + { url = "https://files.pythonhosted.org/packages/cf/83/333afb452af6f0fd70414dc04f898647ee1423979ce02efa75c3b0f2c28e/scipy-1.17.1-cp314-cp314-macosx_10_14_x86_64.whl", hash = "sha256:a48a72c77a310327f6a3a920092fa2b8fd03d7deaa60f093038f22d98e096717", size = 31584510, upload-time = "2026-02-23T00:21:01.015Z" }, + { url = "https://files.pythonhosted.org/packages/ed/a6/d05a85fd51daeb2e4ea71d102f15b34fedca8e931af02594193ae4fd25f7/scipy-1.17.1-cp314-cp314-macosx_12_0_arm64.whl", hash = "sha256:45abad819184f07240d8a696117a7aacd39787af9e0b719d00285549ed19a1e9", size = 28170131, upload-time = "2026-02-23T00:21:05.888Z" }, + { url = "https://files.pythonhosted.org/packages/db/7b/8624a203326675d7746a254083a187398090a179335b2e4a20e2ddc46e83/scipy-1.17.1-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:3fd1fcdab3ea951b610dc4cef356d416d5802991e7e32b5254828d342f7b7e0b", size = 20342032, upload-time = "2026-02-23T00:21:09.904Z" }, + { url = "https://files.pythonhosted.org/packages/c9/35/2c342897c00775d688d8ff3987aced3426858fd89d5a0e26e020b660b301/scipy-1.17.1-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:7bdf2da170b67fdf10bca777614b1c7d96ae3ca5794fd9587dce41eb2966e866", size = 22678766, upload-time = "2026-02-23T00:21:14.313Z" }, + { url = "https://files.pythonhosted.org/packages/ef/f2/7cdb8eb308a1a6ae1e19f945913c82c23c0c442a462a46480ce487fdc0ac/scipy-1.17.1-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:adb2642e060a6549c343603a3851ba76ef0b74cc8c079a9a58121c7ec9fe2350", size = 32957007, upload-time = "2026-02-23T00:21:19.663Z" }, + { url = "https://files.pythonhosted.org/packages/0b/2e/7eea398450457ecb54e18e9d10110993fa65561c4f3add5e8eccd2b9cd41/scipy-1.17.1-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:eee2cfda04c00a857206a4330f0c5e3e56535494e30ca445eb19ec624ae75118", size = 35221333, upload-time = "2026-02-23T00:21:25.278Z" }, + { url = "https://files.pythonhosted.org/packages/d9/77/5b8509d03b77f093a0d52e606d3c4f79e8b06d1d38c441dacb1e26cacf46/scipy-1.17.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:d2650c1fb97e184d12d8ba010493ee7b322864f7d3d00d3f9bb97d9c21de4068", size = 35042066, upload-time = "2026-02-23T00:21:31.358Z" }, + { url = "https://files.pythonhosted.org/packages/f9/df/18f80fb99df40b4070328d5ae5c596f2f00fffb50167e31439e932f29e7d/scipy-1.17.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:08b900519463543aa604a06bec02461558a6e1cef8fdbb8098f77a48a83c8118", size = 37612763, upload-time = "2026-02-23T00:21:37.247Z" }, + { url = "https://files.pythonhosted.org/packages/4b/39/f0e8ea762a764a9dc52aa7dabcfad51a354819de1f0d4652b6a1122424d6/scipy-1.17.1-cp314-cp314-win_amd64.whl", hash = "sha256:3877ac408e14da24a6196de0ddcace62092bfc12a83823e92e49e40747e52c19", size = 37290984, upload-time = "2026-02-23T00:22:35.023Z" }, + { url = "https://files.pythonhosted.org/packages/7c/56/fe201e3b0f93d1a8bcf75d3379affd228a63d7e2d80ab45467a74b494947/scipy-1.17.1-cp314-cp314-win_arm64.whl", hash = "sha256:f8885db0bc2bffa59d5c1b72fad7a6a92d3e80e7257f967dd81abb553a90d293", size = 25192877, upload-time = "2026-02-23T00:22:39.798Z" }, + { url = "https://files.pythonhosted.org/packages/96/ad/f8c414e121f82e02d76f310f16db9899c4fcde36710329502a6b2a3c0392/scipy-1.17.1-cp314-cp314t-macosx_10_14_x86_64.whl", hash = "sha256:1cc682cea2ae55524432f3cdff9e9a3be743d52a7443d0cba9017c23c87ae2f6", size = 31949750, upload-time = "2026-02-23T00:21:42.289Z" }, + { url = "https://files.pythonhosted.org/packages/7c/b0/c741e8865d61b67c81e255f4f0a832846c064e426636cd7de84e74d209be/scipy-1.17.1-cp314-cp314t-macosx_12_0_arm64.whl", hash = "sha256:2040ad4d1795a0ae89bfc7e8429677f365d45aa9fd5e4587cf1ea737f927b4a1", size = 28585858, upload-time = "2026-02-23T00:21:47.706Z" }, + { url = "https://files.pythonhosted.org/packages/ed/1b/3985219c6177866628fa7c2595bfd23f193ceebbe472c98a08824b9466ff/scipy-1.17.1-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:131f5aaea57602008f9822e2115029b55d4b5f7c070287699fe45c661d051e39", size = 20757723, upload-time = "2026-02-23T00:21:52.039Z" }, + { url = "https://files.pythonhosted.org/packages/c0/19/2a04aa25050d656d6f7b9e7b685cc83d6957fb101665bfd9369ca6534563/scipy-1.17.1-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:9cdc1a2fcfd5c52cfb3045feb399f7b3ce822abdde3a193a6b9a60b3cb5854ca", size = 23043098, upload-time = "2026-02-23T00:21:56.185Z" }, + { url = "https://files.pythonhosted.org/packages/86/f1/3383beb9b5d0dbddd030335bf8a8b32d4317185efe495374f134d8be6cce/scipy-1.17.1-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6e3dcd57ab780c741fde8dc68619de988b966db759a3c3152e8e9142c26295ad", size = 33030397, upload-time = "2026-02-23T00:22:01.404Z" }, + { url = "https://files.pythonhosted.org/packages/41/68/8f21e8a65a5a03f25a79165ec9d2b28c00e66dc80546cf5eb803aeeff35b/scipy-1.17.1-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a9956e4d4f4a301ebf6cde39850333a6b6110799d470dbbb1e25326ac447f52a", size = 35281163, upload-time = "2026-02-23T00:22:07.024Z" }, + { url = "https://files.pythonhosted.org/packages/84/8d/c8a5e19479554007a5632ed7529e665c315ae7492b4f946b0deb39870e39/scipy-1.17.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:a4328d245944d09fd639771de275701ccadf5f781ba0ff092ad141e017eccda4", size = 35116291, upload-time = "2026-02-23T00:22:12.585Z" }, + { url = "https://files.pythonhosted.org/packages/52/52/e57eceff0e342a1f50e274264ed47497b59e6a4e3118808ee58ddda7b74a/scipy-1.17.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:a77cbd07b940d326d39a1d1b37817e2ee4d79cb30e7338f3d0cddffae70fcaa2", size = 37682317, upload-time = "2026-02-23T00:22:18.513Z" }, + { url = "https://files.pythonhosted.org/packages/11/2f/b29eafe4a3fbc3d6de9662b36e028d5f039e72d345e05c250e121a230dd4/scipy-1.17.1-cp314-cp314t-win_amd64.whl", hash = "sha256:eb092099205ef62cd1782b006658db09e2fed75bffcae7cc0d44052d8aa0f484", size = 37345327, upload-time = "2026-02-23T00:22:24.442Z" }, + { url = "https://files.pythonhosted.org/packages/07/39/338d9219c4e87f3e708f18857ecd24d22a0c3094752393319553096b98af/scipy-1.17.1-cp314-cp314t-win_arm64.whl", hash = "sha256:200e1050faffacc162be6a486a984a0497866ec54149a01270adc8a59b7c7d21", size = 25489165, upload-time = "2026-02-23T00:22:29.563Z" }, +] + +[[package]] +name = "scipy" +version = "1.18.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.14' and sys_platform == 'win32'", + "python_full_version >= '3.14' and sys_platform != 'win32'", + "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'win32'", + "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform != 'win32'", +] +dependencies = [ + { name = "numpy", version = "2.5.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a7/25/c2700dfaf6442b4effaa91af24ebce5dc9d31bb4a69706313aae70d72cd0/scipy-1.18.0.tar.gz", hash = "sha256:67b2ad2ad54c72ca6d04975a9b2df8c3638c34ddd5b28738e94fc2b57929d378", size = 30774447, upload-time = "2026-06-19T15:01:43.456Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6a/19/ca10ead60b0acc80b2b833c2c4a4f2ff753d0f58b811f70d911c7e94a25c/scipy-1.18.0-cp312-cp312-macosx_10_15_x86_64.whl", hash = "sha256:7bd21faaf5a1a3b2eff922d02db5f191b99a6518db9078a8fb23169f6d22259a", size = 31056519, upload-time = "2026-06-19T14:59:45.203Z" }, + { url = "https://files.pythonhosted.org/packages/96/72/1e6442a00cd2924d361aa1b642ab6373ec35c6fabf311a760be9f76e0f13/scipy-1.18.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:265915e79107de9f946b855e50d7470d5893ec3f54b342e1aa6201cbdcd8bb6b", size = 28681889, upload-time = "2026-06-19T14:59:48.103Z" }, + { url = "https://files.pythonhosted.org/packages/9b/2d/11dd93d21e147a73ba22bd75c0b9208d3a2e0ec76d53170ce7d9029b1015/scipy-1.18.0-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:9ab7b758be6940954a713ee466e2043e9f6e2ed965c1fce5c91039f4be3d90a9", size = 20423580, upload-time = "2026-06-19T14:59:50.665Z" }, + { url = "https://files.pythonhosted.org/packages/9c/01/93552f75e0d2a7dd115a45e59209c51e8d514daff02fc887d2623be06fe1/scipy-1.18.0-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:97b6cddaaee0a779ef6b5ca83c9604b27cc16b2b8fc22c142652df8793319fb8", size = 23054441, upload-time = "2026-06-19T14:59:53.564Z" }, + { url = "https://files.pythonhosted.org/packages/3c/23/21f5e703643d66f21faa6b4c73195bfcad70c55efcb4f1ab327cd7c4101a/scipy-1.18.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:52a96e21517c7292375c0e27dd796a811f03fcea5fd4d108fdfea8145dcf17ab", size = 33968720, upload-time = "2026-06-19T14:59:56.415Z" }, + { url = "https://files.pythonhosted.org/packages/dd/aa/1b939f6c67ed68635bb538e6752d3dacc02f66535182e939a89581a44e9c/scipy-1.18.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1f55797419e16e7f30cf88ffb3113ce0467f00cfe3f70d5c281730b21769bfc2", size = 35287115, upload-time = "2026-06-19T14:59:59.411Z" }, + { url = "https://files.pythonhosted.org/packages/b6/ff/eec46be7e9234208f801062b53e1983085eddebd693f6c9bfb03b459830d/scipy-1.18.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ad033410e2e0672ffdc1042110cef20e1c46f8fd0616cee1d44d8d58fad8fc11", size = 35577989, upload-time = "2026-06-19T15:00:02.235Z" }, + { url = "https://files.pythonhosted.org/packages/84/ca/210d4759c7210bb7d269437421959b39a33434e2776b60c5cb8a763bb30a/scipy-1.18.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:4a55985d54c769c872e64b7f4c8a81cc30ef700cc04296abbbf3705439c126de", size = 37421717, upload-time = "2026-06-19T15:00:05.102Z" }, + { url = "https://files.pythonhosted.org/packages/2b/54/9a9edb45345bd6744da5ddfb6628e5d5185920494c6a67ec45b6381004cb/scipy-1.18.0-cp312-cp312-win_amd64.whl", hash = "sha256:71ccc8faa2dd16ac310233203474a8b5cb67f10dedd54a3116d34943f4b19132", size = 36597428, upload-time = "2026-06-19T15:00:08.112Z" }, + { url = "https://files.pythonhosted.org/packages/99/0e/33f32a2a58987e26aec0f7df252cbbad1e90ae77bdbc76f40dd4ed0cf0ea/scipy-1.18.0-cp312-cp312-win_arm64.whl", hash = "sha256:d88363fd9d8fbd3511bd273f1a49efb2a540773ddf92a91d57498ce7dd7f3e76", size = 24351481, upload-time = "2026-06-19T15:00:11.103Z" }, + { url = "https://files.pythonhosted.org/packages/05/52/9c0136c2de7ae0779b7b366447766cec6d9f0702c56bb8ffeb04c8fd3af4/scipy-1.18.0-cp313-cp313-macosx_10_15_x86_64.whl", hash = "sha256:09143f676d157d9f546d663504ef9c1becb819824f1afc018814176411942446", size = 31036107, upload-time = "2026-06-19T15:00:14.03Z" }, + { url = "https://files.pythonhosted.org/packages/02/73/0291a64843270f4efb86cdcf2ee0f2048631b65ec6b405398b2b4dbf11bf/scipy-1.18.0-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:5efe260f69417b97ddae455bfb5a95e8359f7f66ad7fa9522a60feb66f169520", size = 28663303, upload-time = "2026-06-19T15:00:16.819Z" }, + { url = "https://files.pythonhosted.org/packages/d3/0f/10ffa0b697a572f4e0d48b92a88895d366422f019f723e7e14a84c050dac/scipy-1.18.0-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:68363b7eaacd8b5dd426df56d782cc156468ac79a127a1b87ca597d6e2e82197", size = 20404960, upload-time = "2026-06-19T15:00:19.635Z" }, + { url = "https://files.pythonhosted.org/packages/7e/d2/e896cea21ba8edd6c81d4c55b1ffcc717e79698dcbebf9641b4cfb4c6622/scipy-1.18.0-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:c5557d8be5da8e41353fcd4d21491fdbab83b062fc579e94dc09a7c8ab4f669b", size = 23034074, upload-time = "2026-06-19T15:00:22.107Z" }, + { url = "https://files.pythonhosted.org/packages/ea/b2/e83ea34279a52c03374477c74006256ec78df65fc877baa4617d6de1d202/scipy-1.18.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0d13bca67c096d89fb95ced0d8921807300fce0275643aef9533cc63a0773468", size = 33942038, upload-time = "2026-06-19T15:00:24.964Z" }, + { url = "https://files.pythonhosted.org/packages/f6/af/e8fe5fb136f51e2b01678b92cb4106d10d8cd68ec147ead2e7cb0ac75398/scipy-1.18.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a46f9273dbd0eb1cefba61c9b8648b4dfe3cbc14a080176f9a73e44b8336dc7f", size = 35266390, upload-time = "2026-06-19T15:00:28.059Z" }, + { url = "https://files.pythonhosted.org/packages/3a/49/2c5cbb907b56695fc67517811d1db234dfd83381a84814ec220aded2794d/scipy-1.18.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5aba46108853ddfc77906b6557aac839d2b52e900c1d72a1180adaaab58d265f", size = 35551324, upload-time = "2026-06-19T15:00:31.014Z" }, + { url = "https://files.pythonhosted.org/packages/bb/73/eda39f7a2d306ff0ffc574afd13c0bbb6d10a603d9a413998ee269487a80/scipy-1.18.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b6f758e35f12757b5d95c00bc6de2438e229c2664b7a92e96f205959d9f2dfa4", size = 37404785, upload-time = "2026-06-19T15:00:34.072Z" }, + { url = "https://files.pythonhosted.org/packages/b7/d2/ae881ee28d014f38e0ccbfd974a06a919ba9af34f1f74bf42b5301891d63/scipy-1.18.0-cp313-cp313-win_amd64.whl", hash = "sha256:1afac4a847207c7ff8efd321734a50b06d0280b3b2a2c0fc2f413101747ad7c7", size = 36554943, upload-time = "2026-06-19T15:00:36.903Z" }, + { url = "https://files.pythonhosted.org/packages/70/3a/21154e2d54eb3639c6bf4dbae2e531c68356bfe95990daa30df33b30d556/scipy-1.18.0-cp313-cp313-win_arm64.whl", hash = "sha256:c5dbddf60e58c2312316d097271a8e73d40eaf2eabfa4d95ed7d3695bbf2ce7b", size = 24350911, upload-time = "2026-06-19T15:00:40.062Z" }, + { url = "https://files.pythonhosted.org/packages/78/b5/915a19b3de2f7430062b509653563db1633ddbb6f021b06731521115d4e2/scipy-1.18.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:4c256ee70c0d1a8a2ace807e199ccd4e3f57037433842abb3fb36bc17eaa9578", size = 31036253, upload-time = "2026-06-19T15:00:43.216Z" }, + { url = "https://files.pythonhosted.org/packages/d7/88/b72def7262e150d16be13fca37a96481138d624e700340bc3362a7588929/scipy-1.18.0-cp314-cp314-macosx_12_0_arm64.whl", hash = "sha256:2ef3abc54a4ffc53765374b0d5728532dfdd2585ed23f6b11c206a1f0b1b9af8", size = 28673758, upload-time = "2026-06-19T15:00:46.663Z" }, + { url = "https://files.pythonhosted.org/packages/91/02/2e636a61a525632c373cf6a9c24442a3ffb79e364d38e98b32042964ac32/scipy-1.18.0-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:f2a6af57bd9e4a75d70e4117e78a1bbee84f79ae3fbb6d0111005d6ebcc4cb8d", size = 20415514, upload-time = "2026-06-19T15:00:49.399Z" }, + { url = "https://files.pythonhosted.org/packages/c9/b6/2135974442f6aba159d9d39d774a1c8cb19947016725d69fecc685df45bf/scipy-1.18.0-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:3f1ac564d3bf6c03d861d2cd87a1bea0da2887136f7fb1bf519c05a8971452d6", size = 23034398, upload-time = "2026-06-19T15:00:51.941Z" }, + { url = "https://files.pythonhosted.org/packages/f6/e6/ba89ec5abf6ee9257c0d1ec985573f3ae32742c24bc03e016388a40b1b15/scipy-1.18.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:40395a5fcd1abee49a5c7aaa98c29db393eedc835138560a588c47ec16156690", size = 33998032, upload-time = "2026-06-19T15:00:54.838Z" }, + { url = "https://files.pythonhosted.org/packages/7f/c4/bc41eb19b0fd0db868f4132920879019318d80cc522ad8f2bca4611af808/scipy-1.18.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8ca01e8ae69f1b18e9a58d91afead31be3cef0dd905a10249dac559ee15460a0", size = 35283333, upload-time = "2026-06-19T15:00:58.152Z" }, + { url = "https://files.pythonhosted.org/packages/53/a4/cbdeef6eb3830a8462a9d4ada814de5fc984345cc9ecf17cbec51a036f1e/scipy-1.18.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7a7f3b01647384dbc3a711e8c6778e0aabbe93959249fef5c7393396bcac0867", size = 35610216, upload-time = "2026-06-19T15:01:01.155Z" }, + { url = "https://files.pythonhosted.org/packages/80/4d/b2b82502b65f661d1b789c1665dcdf315d5f12194e06fc0b37946294ebae/scipy-1.18.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:6aa94e78ec192a30063a5e72e561c28af769dc311190b24fe91774eff1969709", size = 37418960, upload-time = "2026-06-19T15:01:04.155Z" }, + { url = "https://files.pythonhosted.org/packages/93/3e/902d836831474b0ab5a37d16404f7bc5fafd9efba632890e271ba952635f/scipy-1.18.0-cp314-cp314-win_amd64.whl", hash = "sha256:2d8bbdc6c817f5b4006a54d799d4f5bab6f910193cbb9a1ff310833d4d270f61", size = 37288845, upload-time = "2026-06-19T15:01:07.822Z" }, + { url = "https://files.pythonhosted.org/packages/b6/43/8d73b337a3bdb14daa0314f0434210747c02d79d729ce1777574a817dcf6/scipy-1.18.0-cp314-cp314-win_arm64.whl", hash = "sha256:18e9575f1569b2c54174e6159d32942e03731177f63dce7975f0a0c88d102f5b", size = 24988971, upload-time = "2026-06-19T15:01:11.076Z" }, + { url = "https://files.pythonhosted.org/packages/b4/b4/f11918b0508a2787031a0499a03fbe3546f3bb5ca05d01038c45b278c09a/scipy-1.18.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:f351e0dd702687d12a402b867a1b4146a256923e1c38317cbc472f6372b94707", size = 31399325, upload-time = "2026-06-19T15:01:13.723Z" }, + { url = "https://files.pythonhosted.org/packages/7b/d1/1f287b57c0ff0ee5185dff3946d92c8017d39b0e431f0ae79a3ff1859512/scipy-1.18.0-cp314-cp314t-macosx_12_0_arm64.whl", hash = "sha256:7c7a51b33ce387193c97f228320cf8e87361daa1bba750638677729598b3e677", size = 29092110, upload-time = "2026-06-19T15:01:16.908Z" }, + { url = "https://files.pythonhosted.org/packages/ff/1a/7b74eb6c392fdcb27d414c0e7558a6d0231eb3b6d73571f479bb81ea8794/scipy-1.18.0-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:84031d7b052a54fae2f8632e0ec802073d385476eb9a63079bce6e23ef9283d4", size = 20833811, upload-time = "2026-06-19T15:01:20.488Z" }, + { url = "https://files.pythonhosted.org/packages/7c/ad/f3941716320a7b9cb4d68734a903b45fe16eff5fb7da7e16f2e619304979/scipy-1.18.0-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:56abf29a7c067dde59be8b9a22d606a4ea1b2f2a4b756d9d903c62818f5dacce", size = 23396644, upload-time = "2026-06-19T15:01:23.364Z" }, + { url = "https://files.pythonhosted.org/packages/22/22/1446b62ffe07f9719b7d9b1b6a4e05a772833ae8f441fe4c22c34c9b250f/scipy-1.18.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1ad44305cfa24b1ba5803cbbebf033590ccbac1aa5d612d727b785325ab408b0", size = 34079318, upload-time = "2026-06-19T15:01:26.002Z" }, + { url = "https://files.pythonhosted.org/packages/56/3b/b87da667098bb470fa30c7011b0ba351ee976dd395c78798c66e941665a3/scipy-1.18.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:945c1761b93f38d7f99ae81ae80c63e621471608c7eeead563f6df025585cd58", size = 35324320, upload-time = "2026-06-19T15:01:28.881Z" }, + { url = "https://files.pythonhosted.org/packages/f8/a1/c7932f91909759b0267f75fdea34e91309f96b895757534b76a90b6b4344/scipy-1.18.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:1a4441f15d620578772a49e5ab48c0ee1f7a0220e387110283062729136b2553", size = 35699541, upload-time = "2026-06-19T15:01:31.968Z" }, + { url = "https://files.pythonhosted.org/packages/f7/86/5185061a1fcc41d18c5dc2463969b3a3964b31d9ac67b2fb05d4c7ff7670/scipy-1.18.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:9aac6192fac56bf2ca534389d24623f07b39ff83317d58287285e7fbd622ff76", size = 37472480, upload-time = "2026-06-19T15:01:35.136Z" }, + { url = "https://files.pythonhosted.org/packages/31/8e/f04c68e39919a010d34f2ee1367fd705b0a25a02f609d755f0bfbc0a15fc/scipy-1.18.0-cp314-cp314t-win_amd64.whl", hash = "sha256:e40baea28ae7f5475c779741e2d90b1247c78531207b49c7030e698ff81cee3f", size = 37365390, upload-time = "2026-06-19T15:01:38.091Z" }, + { url = "https://files.pythonhosted.org/packages/d5/19/969dc072906c84dd0a3b05dcf57ea750936087d7873549e408b35cfc3f97/scipy-1.18.0-cp314-cp314t-win_arm64.whl", hash = "sha256:368e0a705903c466aa5f08eefb39e6b1b6b2d659e7352a31fd9e2438365be0f8", size = 25279661, upload-time = "2026-06-19T15:01:40.817Z" }, +] + +[[package]] +name = "seaborn" +version = "0.13.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "matplotlib" }, + { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12'" }, + { name = "numpy", version = "2.5.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12'" }, + { name = "pandas" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/86/59/a451d7420a77ab0b98f7affa3a1d78a313d2f7281a57afb1a34bae8ab412/seaborn-0.13.2.tar.gz", hash = "sha256:93e60a40988f4d65e9f4885df477e2fdaff6b73a9ded434c1ab356dd57eefff7", size = 1457696, upload-time = "2024-01-25T13:21:52.551Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/83/11/00d3c3dfc25ad54e731d91449895a79e4bf2384dc3ac01809010ba88f6d5/seaborn-0.13.2-py3-none-any.whl", hash = "sha256:636f8336facf092165e27924f223d3c62ca560b1f2bb5dff7ab7fad265361987", size = 294914, upload-time = "2024-01-25T13:21:49.598Z" }, +] + +[[package]] +name = "secretstorage" +version = "3.5.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cryptography", marker = "sys_platform != 'win32'" }, + { name = "jeepney", marker = "sys_platform != 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/1c/03/e834bcd866f2f8a49a85eaff47340affa3bfa391ee9912a952a1faa68c7b/secretstorage-3.5.0.tar.gz", hash = "sha256:f04b8e4689cbce351744d5537bf6b1329c6fc68f91fa666f60a380edddcd11be", size = 19884, upload-time = "2025-11-23T19:02:53.191Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/46/f5af3402b579fd5e11573ce652019a67074317e18c1935cc0b4ba9b35552/secretstorage-3.5.0-py3-none-any.whl", hash = "sha256:0ce65888c0725fcb2c5bc0fdb8e5438eece02c523557ea40ce0703c266248137", size = 15554, upload-time = "2025-11-23T19:02:51.545Z" }, +] + +[[package]] +name = "sentence-transformers" +version = "5.6.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "huggingface-hub" }, + { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12'" }, + { name = "numpy", version = "2.5.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12'" }, + { name = "scikit-learn" }, + { name = "scipy", version = "1.17.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12'" }, + { name = "scipy", version = "1.18.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12'" }, + { name = "torch" }, + { name = "tqdm" }, + { name = "transformers" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f9/56/d2cb00765a6b15c994a7fccf20f9032f16e8193ca49147cb5155166ad744/sentence_transformers-5.6.0.tar.gz", hash = "sha256:0e7164d051e416c1853ade7c274ff52af3f9da0f4be7f0b83d734c27699e1057", size = 453194, upload-time = "2026-06-16T14:01:56.42Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/76/c1/dc1582b79e9a2eb0cddf9559cd9bcdff084f541d6fe881fdd9d98630dba7/sentence_transformers-5.6.0-py3-none-any.whl", hash = "sha256:d2075b5e687a1611005e20ab04a6846994d51adfcf39610aed066af3c0c0b81f", size = 596411, upload-time = "2026-06-16T14:01:55.103Z" }, +] + +[[package]] +name = "setuptools" +version = "81.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0d/1c/73e719955c59b8e424d015ab450f51c0af856ae46ea2da83eba51cc88de1/setuptools-81.0.0.tar.gz", hash = "sha256:487b53915f52501f0a79ccfd0c02c165ffe06631443a886740b91af4b7a5845a", size = 1198299, upload-time = "2026-02-06T21:10:39.601Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e1/e3/c164c88b2e5ce7b24d667b9bd83589cf4f3520d97cad01534cd3c4f55fdb/setuptools-81.0.0-py3-none-any.whl", hash = "sha256:fdd925d5c5d9f62e4b74b30d6dd7828ce236fd6ed998a08d81de62ce5a6310d6", size = 1062021, upload-time = "2026-02-06T21:10:37.175Z" }, +] + +[[package]] +name = "shellingham" +version = "1.5.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/58/15/8b3609fd3830ef7b27b655beb4b4e9c62313a4e8da8c676e142cc210d58e/shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de", size = 10310, upload-time = "2023-10-24T04:13:40.426Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", size = 9755, upload-time = "2023-10-24T04:13:38.866Z" }, +] + +[[package]] +name = "six" +version = "1.17.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" }, +] + +[[package]] +name = "smith" +version = "0.2.0.dev0" +source = { editable = "." } +dependencies = [ + { name = "httpx" }, + { name = "jinja2" }, + { name = "matplotlib" }, + { name = "mcp", extra = ["cli"] }, + { name = "networkx" }, + { name = "nltk" }, + { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12'" }, + { name = "numpy", version = "2.5.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12'" }, + { name = "openai" }, + { name = "pandas" }, + { name = "pydantic" }, + { name = "pydot" }, + { name = "python-dotenv" }, + { name = "pyyaml" }, + { name = "requests" }, + { name = "rich" }, + { name = "scikit-learn" }, + { name = "seaborn" }, + { name = "sentence-transformers" }, + { name = "tenacity" }, + { name = "termcolor" }, + { name = "tqdm" }, + { name = "typer" }, +] + +[package.optional-dependencies] +dev = [ + { name = "black" }, + { name = "build" }, + { name = "pip-audit" }, + { name = "pytest" }, + { name = "pytest-asyncio" }, + { name = "pytest-mock" }, + { name = "ruff" }, + { name = "twine" }, +] + +[package.metadata] +requires-dist = [ + { name = "black", marker = "extra == 'dev'", specifier = "==26.5.1" }, + { name = "build", marker = "extra == 'dev'", specifier = ">=1.2.0" }, + { name = "httpx", specifier = ">=0.24.0" }, + { name = "jinja2", specifier = ">=3.1.0" }, + { name = "matplotlib", specifier = ">=3.7.0" }, + { name = "mcp", extras = ["cli"], specifier = ">=1.0.0" }, + { name = "networkx", specifier = ">=3.0" }, + { name = "nltk", specifier = ">=3.8.0" }, + { name = "numpy", specifier = ">=1.24.0" }, + { name = "openai", specifier = ">=1.0.0" }, + { name = "pandas", specifier = ">=2.0.0" }, + { name = "pip-audit", marker = "extra == 'dev'", specifier = ">=2.7.0" }, + { name = "pydantic", specifier = ">=2.0.0" }, + { name = "pydot", specifier = ">=1.4.0" }, + { name = "pytest", marker = "extra == 'dev'", specifier = ">=7.4.0" }, + { name = "pytest-asyncio", marker = "extra == 'dev'", specifier = ">=0.21.0" }, + { name = "pytest-mock", marker = "extra == 'dev'", specifier = ">=3.11.0" }, + { name = "python-dotenv", specifier = ">=1.0.0" }, + { name = "pyyaml", specifier = ">=6.0" }, + { name = "requests", specifier = ">=2.28.0" }, + { name = "rich", specifier = ">=13.0.0" }, + { name = "ruff", marker = "extra == 'dev'", specifier = "==0.15.20" }, + { name = "scikit-learn", specifier = ">=1.3.0" }, + { name = "seaborn", specifier = ">=0.12.0" }, + { name = "sentence-transformers", specifier = ">=2.2.0" }, + { name = "tenacity", specifier = ">=8.2.0" }, + { name = "termcolor", specifier = ">=2.0.0" }, + { name = "tqdm", specifier = ">=4.65.0" }, + { name = "twine", marker = "extra == 'dev'", specifier = ">=5.0.0" }, + { name = "typer", specifier = ">=0.9.0" }, +] +provides-extras = ["dev"] + +[[package]] +name = "sniffio" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372, upload-time = "2024-02-25T23:20:04.057Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235, upload-time = "2024-02-25T23:20:01.196Z" }, +] + +[[package]] +name = "sortedcontainers" +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" }, +] + +[[package]] +name = "sse-starlette" +version = "3.4.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "starlette" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d2/1b/bc9e3e7a72dcdad7dc7888758f5d00f56f8909ed5cfdff822bd72bb4c520/sse_starlette-3.4.5.tar.gz", hash = "sha256:83072538bc211a2f68b7b0422226c4af3e9b62e106e07034664b832ca019842a", size = 35249, upload-time = "2026-06-20T17:36:58.322Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/78/75/c88d3f5dafd59c791da1ce27650d30bf5b70cbf1cbf01cd00e5f9e360915/sse_starlette-3.4.5-py3-none-any.whl", hash = "sha256:e71bad53323f65573c3864a6c3bd0c1eb6e5f092b2e48082b0c35927d19ca296", size = 16518, upload-time = "2026-06-20T17:36:56.729Z" }, +] + +[[package]] +name = "starlette" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/eb/e3/7c1dc7381d9f8ab7d854328ebfa884e62cb3f3d8549ddfd37c7814f42afa/starlette-1.3.1.tar.gz", hash = "sha256:05d0213193f2fbaae60e2ecb593b4add4262ad4e46536b54abe36f11a71724e0", size = 2703240, upload-time = "2026-06-12T09:23:11.602Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ec/bb/2799cc2ede3ed41131f8975621e7213dfc7ef4acbbaadfa440f32500c370/starlette-1.3.1-py3-none-any.whl", hash = "sha256:c7372aae11c3c3f26a42df7bd626cec2f47d03483d261d369516a615a53714c6", size = 73632, upload-time = "2026-06-12T09:23:10.017Z" }, +] + +[[package]] +name = "sympy" +version = "1.14.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mpmath" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/83/d3/803453b36afefb7c2bb238361cd4ae6125a569b4db67cd9e79846ba2d68c/sympy-1.14.0.tar.gz", hash = "sha256:d3d3fe8df1e5a0b42f0e7bdf50541697dbe7d23746e894990c030e2b05e72517", size = 7793921, upload-time = "2025-04-27T18:05:01.611Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a2/09/77d55d46fd61b4a135c444fc97158ef34a095e5681d0a6c10b75bf356191/sympy-1.14.0-py3-none-any.whl", hash = "sha256:e091cc3e99d2141a0ba2847328f5479b05d94a6635cb96148ccb3f34671bd8f5", size = 6299353, upload-time = "2025-04-27T18:04:59.103Z" }, +] + +[[package]] +name = "tenacity" +version = "9.1.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/47/c6/ee486fd809e357697ee8a44d3d69222b344920433d3b6666ccd9b374630c/tenacity-9.1.4.tar.gz", hash = "sha256:adb31d4c263f2bd041081ab33b498309a57c77f9acf2db65aadf0898179cf93a", size = 49413, upload-time = "2026-02-07T10:45:33.841Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d7/c1/eb8f9debc45d3b7918a32ab756658a0904732f75e555402972246b0b8e71/tenacity-9.1.4-py3-none-any.whl", hash = "sha256:6095a360c919085f28c6527de529e76a06ad89b23659fa881ae0649b867a9d55", size = 28926, upload-time = "2026-02-07T10:45:32.24Z" }, +] + +[[package]] +name = "termcolor" +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" }, +] + +[[package]] +name = "threadpoolctl" +version = "3.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b7/4d/08c89e34946fce2aec4fbb45c9016efd5f4d7f24af8e5d93296e935631d8/threadpoolctl-3.6.0.tar.gz", hash = "sha256:8ab8b4aa3491d812b623328249fab5302a68d2d71745c8a4c719a2fcaba9f44e", size = 21274, upload-time = "2025-03-13T13:49:23.031Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/32/d5/f9a850d79b0851d1d4ef6456097579a9005b31fea68726a4ae5f2d82ddd9/threadpoolctl-3.6.0-py3-none-any.whl", hash = "sha256:43a0b8fd5a2928500110039e43a5eed8480b918967083ea48dc3ab9f13c4a7fb", size = 18638, upload-time = "2025-03-13T13:49:21.846Z" }, +] + +[[package]] +name = "tokenizers" +version = "0.22.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "huggingface-hub" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/73/6f/f80cfef4a312e1fb34baf7d85c72d4411afde10978d4657f8cdd811d3ccc/tokenizers-0.22.2.tar.gz", hash = "sha256:473b83b915e547aa366d1eee11806deaf419e17be16310ac0a14077f1e28f917", size = 372115, upload-time = "2026-01-05T10:45:15.988Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/92/97/5dbfabf04c7e348e655e907ed27913e03db0923abb5dfdd120d7b25630e1/tokenizers-0.22.2-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:544dd704ae7238755d790de45ba8da072e9af3eea688f698b137915ae959281c", size = 3100275, upload-time = "2026-01-05T10:41:02.158Z" }, + { url = "https://files.pythonhosted.org/packages/2e/47/174dca0502ef88b28f1c9e06b73ce33500eedfac7a7692108aec220464e7/tokenizers-0.22.2-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:1e418a55456beedca4621dbab65a318981467a2b188e982a23e117f115ce5001", size = 2981472, upload-time = "2026-01-05T10:41:00.276Z" }, + { url = "https://files.pythonhosted.org/packages/d6/84/7990e799f1309a8b87af6b948f31edaa12a3ed22d11b352eaf4f4b2e5753/tokenizers-0.22.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2249487018adec45d6e3554c71d46eb39fa8ea67156c640f7513eb26f318cec7", size = 3290736, upload-time = "2026-01-05T10:40:32.165Z" }, + { url = "https://files.pythonhosted.org/packages/78/59/09d0d9ba94dcd5f4f1368d4858d24546b4bdc0231c2354aa31d6199f0399/tokenizers-0.22.2-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:25b85325d0815e86e0bac263506dd114578953b7b53d7de09a6485e4a160a7dd", size = 3168835, upload-time = "2026-01-05T10:40:38.847Z" }, + { url = "https://files.pythonhosted.org/packages/47/50/b3ebb4243e7160bda8d34b731e54dd8ab8b133e50775872e7a434e524c28/tokenizers-0.22.2-cp39-abi3-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bfb88f22a209ff7b40a576d5324bf8286b519d7358663db21d6246fb17eea2d5", size = 3521673, upload-time = "2026-01-05T10:40:56.614Z" }, + { url = "https://files.pythonhosted.org/packages/e0/fa/89f4cb9e08df770b57adb96f8cbb7e22695a4cb6c2bd5f0c4f0ebcf33b66/tokenizers-0.22.2-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1c774b1276f71e1ef716e5486f21e76333464f47bece56bbd554485982a9e03e", size = 3724818, upload-time = "2026-01-05T10:40:44.507Z" }, + { url = "https://files.pythonhosted.org/packages/64/04/ca2363f0bfbe3b3d36e95bf67e56a4c88c8e3362b658e616d1ac185d47f2/tokenizers-0.22.2-cp39-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:df6c4265b289083bf710dff49bc51ef252f9d5be33a45ee2bed151114a56207b", size = 3379195, upload-time = "2026-01-05T10:40:51.139Z" }, + { url = "https://files.pythonhosted.org/packages/2e/76/932be4b50ef6ccedf9d3c6639b056a967a86258c6d9200643f01269211ca/tokenizers-0.22.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:369cc9fc8cc10cb24143873a0d95438bb8ee257bb80c71989e3ee290e8d72c67", size = 3274982, upload-time = "2026-01-05T10:40:58.331Z" }, + { url = "https://files.pythonhosted.org/packages/1d/28/5f9f5a4cc211b69e89420980e483831bcc29dade307955cc9dc858a40f01/tokenizers-0.22.2-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:29c30b83d8dcd061078b05ae0cb94d3c710555fbb44861139f9f83dcca3dc3e4", size = 9478245, upload-time = "2026-01-05T10:41:04.053Z" }, + { url = "https://files.pythonhosted.org/packages/6c/fb/66e2da4704d6aadebf8cb39f1d6d1957df667ab24cff2326b77cda0dcb85/tokenizers-0.22.2-cp39-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:37ae80a28c1d3265bb1f22464c856bd23c02a05bb211e56d0c5301a435be6c1a", size = 9560069, upload-time = "2026-01-05T10:45:10.673Z" }, + { url = "https://files.pythonhosted.org/packages/16/04/fed398b05caa87ce9b1a1bb5166645e38196081b225059a6edaff6440fac/tokenizers-0.22.2-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:791135ee325f2336f498590eb2f11dc5c295232f288e75c99a36c5dbce63088a", size = 9899263, upload-time = "2026-01-05T10:45:12.559Z" }, + { url = "https://files.pythonhosted.org/packages/05/a1/d62dfe7376beaaf1394917e0f8e93ee5f67fea8fcf4107501db35996586b/tokenizers-0.22.2-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:38337540fbbddff8e999d59970f3c6f35a82de10053206a7562f1ea02d046fa5", size = 10033429, upload-time = "2026-01-05T10:45:14.333Z" }, + { url = "https://files.pythonhosted.org/packages/fd/18/a545c4ea42af3df6effd7d13d250ba77a0a86fb20393143bbb9a92e434d4/tokenizers-0.22.2-cp39-abi3-win32.whl", hash = "sha256:a6bf3f88c554a2b653af81f3204491c818ae2ac6fbc09e76ef4773351292bc92", size = 2502363, upload-time = "2026-01-05T10:45:20.593Z" }, + { url = "https://files.pythonhosted.org/packages/65/71/0670843133a43d43070abeb1949abfdef12a86d490bea9cd9e18e37c5ff7/tokenizers-0.22.2-cp39-abi3-win_amd64.whl", hash = "sha256:c9ea31edff2968b44a88f97d784c2f16dc0729b8b143ed004699ebca91f05c48", size = 2747786, upload-time = "2026-01-05T10:45:18.411Z" }, + { url = "https://files.pythonhosted.org/packages/72/f4/0de46cfa12cdcbcd464cc59fde36912af405696f687e53a091fb432f694c/tokenizers-0.22.2-cp39-abi3-win_arm64.whl", hash = "sha256:9ce725d22864a1e965217204946f830c37876eee3b2ba6fc6255e8e903d5fcbc", size = 2612133, upload-time = "2026-01-05T10:45:17.232Z" }, +] + +[[package]] +name = "tomli" +version = "2.4.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/22/de/48c59722572767841493b26183a0d1cc411d54fd759c5607c4590b6563a6/tomli-2.4.1.tar.gz", hash = "sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f", size = 17543, upload-time = "2026-03-25T20:22:03.828Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/11/db3d5885d8528263d8adc260bb2d28ebf1270b96e98f0e0268d32b8d9900/tomli-2.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f8f0fc26ec2cc2b965b7a3b87cd19c5c6b8c5e5f436b984e85f486d652285c30", size = 154704, upload-time = "2026-03-25T20:21:10.473Z" }, + { url = "https://files.pythonhosted.org/packages/6d/f7/675db52c7e46064a9aa928885a9b20f4124ecb9bc2e1ce74c9106648d202/tomli-2.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4ab97e64ccda8756376892c53a72bd1f964e519c77236368527f758fbc36a53a", size = 149454, upload-time = "2026-03-25T20:21:12.036Z" }, + { url = "https://files.pythonhosted.org/packages/61/71/81c50943cf953efa35bce7646caab3cf457a7d8c030b27cfb40d7235f9ee/tomli-2.4.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:96481a5786729fd470164b47cdb3e0e58062a496f455ee41b4403be77cb5a076", size = 237561, upload-time = "2026-03-25T20:21:13.098Z" }, + { url = "https://files.pythonhosted.org/packages/48/c1/f41d9cb618acccca7df82aaf682f9b49013c9397212cb9f53219e3abac37/tomli-2.4.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a881ab208c0baf688221f8cecc5401bd291d67e38a1ac884d6736cbcd8247e9", size = 243824, upload-time = "2026-03-25T20:21:14.569Z" }, + { url = "https://files.pythonhosted.org/packages/22/e4/5a816ecdd1f8ca51fb756ef684b90f2780afc52fc67f987e3c61d800a46d/tomli-2.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:47149d5bd38761ac8be13a84864bf0b7b70bc051806bc3669ab1cbc56216b23c", size = 242227, upload-time = "2026-03-25T20:21:15.712Z" }, + { url = "https://files.pythonhosted.org/packages/6b/49/2b2a0ef529aa6eec245d25f0c703e020a73955ad7edf73e7f54ddc608aa5/tomli-2.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ec9bfaf3ad2df51ace80688143a6a4ebc09a248f6ff781a9945e51937008fcbc", size = 247859, upload-time = "2026-03-25T20:21:17.001Z" }, + { url = "https://files.pythonhosted.org/packages/83/bd/6c1a630eaca337e1e78c5903104f831bda934c426f9231429396ce3c3467/tomli-2.4.1-cp311-cp311-win32.whl", hash = "sha256:ff2983983d34813c1aeb0fa89091e76c3a22889ee83ab27c5eeb45100560c049", size = 97204, upload-time = "2026-03-25T20:21:18.079Z" }, + { url = "https://files.pythonhosted.org/packages/42/59/71461df1a885647e10b6bb7802d0b8e66480c61f3f43079e0dcd315b3954/tomli-2.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:5ee18d9ebdb417e384b58fe414e8d6af9f4e7a0ae761519fb50f721de398dd4e", size = 108084, upload-time = "2026-03-25T20:21:18.978Z" }, + { url = "https://files.pythonhosted.org/packages/b8/83/dceca96142499c069475b790e7913b1044c1a4337e700751f48ed723f883/tomli-2.4.1-cp311-cp311-win_arm64.whl", hash = "sha256:c2541745709bad0264b7d4705ad453b76ccd191e64aa6f0fc66b69a293a45ece", size = 95285, upload-time = "2026-03-25T20:21:20.309Z" }, + { url = "https://files.pythonhosted.org/packages/c1/ba/42f134a3fe2b370f555f44b1d72feebb94debcab01676bf918d0cb70e9aa/tomli-2.4.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c742f741d58a28940ce01d58f0ab2ea3ced8b12402f162f4d534dfe18ba1cd6a", size = 155924, upload-time = "2026-03-25T20:21:21.626Z" }, + { url = "https://files.pythonhosted.org/packages/dc/c7/62d7a17c26487ade21c5422b646110f2162f1fcc95980ef7f63e73c68f14/tomli-2.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7f86fd587c4ed9dd76f318225e7d9b29cfc5a9d43de44e5754db8d1128487085", size = 150018, upload-time = "2026-03-25T20:21:23.002Z" }, + { url = "https://files.pythonhosted.org/packages/5c/05/79d13d7c15f13bdef410bdd49a6485b1c37d28968314eabee452c22a7fda/tomli-2.4.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ff18e6a727ee0ab0388507b89d1bc6a22b138d1e2fa56d1ad494586d61d2eae9", size = 244948, upload-time = "2026-03-25T20:21:24.04Z" }, + { url = "https://files.pythonhosted.org/packages/10/90/d62ce007a1c80d0b2c93e02cab211224756240884751b94ca72df8a875ca/tomli-2.4.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:136443dbd7e1dee43c68ac2694fde36b2849865fa258d39bf822c10e8068eac5", size = 253341, upload-time = "2026-03-25T20:21:25.177Z" }, + { url = "https://files.pythonhosted.org/packages/1a/7e/caf6496d60152ad4ed09282c1885cca4eea150bfd007da84aea07bcc0a3e/tomli-2.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5e262d41726bc187e69af7825504c933b6794dc3fbd5945e41a79bb14c31f585", size = 248159, upload-time = "2026-03-25T20:21:26.364Z" }, + { url = "https://files.pythonhosted.org/packages/99/e7/c6f69c3120de34bbd882c6fba7975f3d7a746e9218e56ab46a1bc4b42552/tomli-2.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5cb41aa38891e073ee49d55fbc7839cfdb2bc0e600add13874d048c94aadddd1", size = 253290, upload-time = "2026-03-25T20:21:27.46Z" }, + { url = "https://files.pythonhosted.org/packages/d6/2f/4a3c322f22c5c66c4b836ec58211641a4067364f5dcdd7b974b4c5da300c/tomli-2.4.1-cp312-cp312-win32.whl", hash = "sha256:da25dc3563bff5965356133435b757a795a17b17d01dbc0f42fb32447ddfd917", size = 98141, upload-time = "2026-03-25T20:21:28.492Z" }, + { url = "https://files.pythonhosted.org/packages/24/22/4daacd05391b92c55759d55eaee21e1dfaea86ce5c571f10083360adf534/tomli-2.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:52c8ef851d9a240f11a88c003eacb03c31fc1c9c4ec64a99a0f922b93874fda9", size = 108847, upload-time = "2026-03-25T20:21:29.386Z" }, + { url = "https://files.pythonhosted.org/packages/68/fd/70e768887666ddd9e9f5d85129e84910f2db2796f9096aa02b721a53098d/tomli-2.4.1-cp312-cp312-win_arm64.whl", hash = "sha256:f758f1b9299d059cc3f6546ae2af89670cb1c4d48ea29c3cacc4fe7de3058257", size = 95088, upload-time = "2026-03-25T20:21:30.677Z" }, + { url = "https://files.pythonhosted.org/packages/07/06/b823a7e818c756d9a7123ba2cda7d07bc2dd32835648d1a7b7b7a05d848d/tomli-2.4.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:36d2bd2ad5fb9eaddba5226aa02c8ec3fa4f192631e347b3ed28186d43be6b54", size = 155866, upload-time = "2026-03-25T20:21:31.65Z" }, + { url = "https://files.pythonhosted.org/packages/14/6f/12645cf7f08e1a20c7eb8c297c6f11d31c1b50f316a7e7e1e1de6e2e7b7e/tomli-2.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:eb0dc4e38e6a1fd579e5d50369aa2e10acfc9cace504579b2faabb478e76941a", size = 149887, upload-time = "2026-03-25T20:21:33.028Z" }, + { url = "https://files.pythonhosted.org/packages/5c/e0/90637574e5e7212c09099c67ad349b04ec4d6020324539297b634a0192b0/tomli-2.4.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c7f2c7f2b9ca6bdeef8f0fa897f8e05085923eb091721675170254cbc5b02897", size = 243704, upload-time = "2026-03-25T20:21:34.51Z" }, + { url = "https://files.pythonhosted.org/packages/10/8f/d3ddb16c5a4befdf31a23307f72828686ab2096f068eaf56631e136c1fdd/tomli-2.4.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f3c6818a1a86dd6dca7ddcaaf76947d5ba31aecc28cb1b67009a5877c9a64f3f", size = 251628, upload-time = "2026-03-25T20:21:36.012Z" }, + { url = "https://files.pythonhosted.org/packages/e3/f1/dbeeb9116715abee2485bf0a12d07a8f31af94d71608c171c45f64c0469d/tomli-2.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d312ef37c91508b0ab2cee7da26ec0b3ed2f03ce12bd87a588d771ae15dcf82d", size = 247180, upload-time = "2026-03-25T20:21:37.136Z" }, + { url = "https://files.pythonhosted.org/packages/d3/74/16336ffd19ed4da28a70959f92f506233bd7cfc2332b20bdb01591e8b1d1/tomli-2.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:51529d40e3ca50046d7606fa99ce3956a617f9b36380da3b7f0dd3dd28e68cb5", size = 251674, upload-time = "2026-03-25T20:21:38.298Z" }, + { url = "https://files.pythonhosted.org/packages/16/f9/229fa3434c590ddf6c0aa9af64d3af4b752540686cace29e6281e3458469/tomli-2.4.1-cp313-cp313-win32.whl", hash = "sha256:2190f2e9dd7508d2a90ded5ed369255980a1bcdd58e52f7fe24b8162bf9fedbd", size = 97976, upload-time = "2026-03-25T20:21:39.316Z" }, + { url = "https://files.pythonhosted.org/packages/6a/1e/71dfd96bcc1c775420cb8befe7a9d35f2e5b1309798f009dca17b7708c1e/tomli-2.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:8d65a2fbf9d2f8352685bc1364177ee3923d6baf5e7f43ea4959d7d8bc326a36", size = 108755, upload-time = "2026-03-25T20:21:40.248Z" }, + { url = "https://files.pythonhosted.org/packages/83/7a/d34f422a021d62420b78f5c538e5b102f62bea616d1d75a13f0a88acb04a/tomli-2.4.1-cp313-cp313-win_arm64.whl", hash = "sha256:4b605484e43cdc43f0954ddae319fb75f04cc10dd80d830540060ee7cd0243cd", size = 95265, upload-time = "2026-03-25T20:21:41.219Z" }, + { url = "https://files.pythonhosted.org/packages/3c/fb/9a5c8d27dbab540869f7c1f8eb0abb3244189ce780ba9cd73f3770662072/tomli-2.4.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:fd0409a3653af6c147209d267a0e4243f0ae46b011aa978b1080359fddc9b6cf", size = 155726, upload-time = "2026-03-25T20:21:42.23Z" }, + { url = "https://files.pythonhosted.org/packages/62/05/d2f816630cc771ad836af54f5001f47a6f611d2d39535364f148b6a92d6b/tomli-2.4.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:a120733b01c45e9a0c34aeef92bf0cf1d56cfe81ed9d47d562f9ed591a9828ac", size = 149859, upload-time = "2026-03-25T20:21:43.386Z" }, + { url = "https://files.pythonhosted.org/packages/ce/48/66341bdb858ad9bd0ceab5a86f90eddab127cf8b046418009f2125630ecb/tomli-2.4.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:559db847dc486944896521f68d8190be1c9e719fced785720d2216fe7022b662", size = 244713, upload-time = "2026-03-25T20:21:44.474Z" }, + { url = "https://files.pythonhosted.org/packages/df/6d/c5fad00d82b3c7a3ab6189bd4b10e60466f22cfe8a08a9394185c8a8111c/tomli-2.4.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:01f520d4f53ef97964a240a035ec2a869fe1a37dde002b57ebc4417a27ccd853", size = 252084, upload-time = "2026-03-25T20:21:45.62Z" }, + { url = "https://files.pythonhosted.org/packages/00/71/3a69e86f3eafe8c7a59d008d245888051005bd657760e96d5fbfb0b740c2/tomli-2.4.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7f94b27a62cfad8496c8d2513e1a222dd446f095fca8987fceef261225538a15", size = 247973, upload-time = "2026-03-25T20:21:46.937Z" }, + { url = "https://files.pythonhosted.org/packages/67/50/361e986652847fec4bd5e4a0208752fbe64689c603c7ae5ea7cb16b1c0ca/tomli-2.4.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ede3e6487c5ef5d28634ba3f31f989030ad6af71edfb0055cbbd14189ff240ba", size = 256223, upload-time = "2026-03-25T20:21:48.467Z" }, + { url = "https://files.pythonhosted.org/packages/8c/9a/b4173689a9203472e5467217e0154b00e260621caa227b6fa01feab16998/tomli-2.4.1-cp314-cp314-win32.whl", hash = "sha256:3d48a93ee1c9b79c04bb38772ee1b64dcf18ff43085896ea460ca8dec96f35f6", size = 98973, upload-time = "2026-03-25T20:21:49.526Z" }, + { url = "https://files.pythonhosted.org/packages/14/58/640ac93bf230cd27d002462c9af0d837779f8773bc03dee06b5835208214/tomli-2.4.1-cp314-cp314-win_amd64.whl", hash = "sha256:88dceee75c2c63af144e456745e10101eb67361050196b0b6af5d717254dddf7", size = 109082, upload-time = "2026-03-25T20:21:50.506Z" }, + { url = "https://files.pythonhosted.org/packages/d5/2f/702d5e05b227401c1068f0d386d79a589bb12bf64c3d2c72ce0631e3bc49/tomli-2.4.1-cp314-cp314-win_arm64.whl", hash = "sha256:b8c198f8c1805dc42708689ed6864951fd2494f924149d3e4bce7710f8eb5232", size = 96490, upload-time = "2026-03-25T20:21:51.474Z" }, + { url = "https://files.pythonhosted.org/packages/45/4b/b877b05c8ba62927d9865dd980e34a755de541eb65fffba52b4cc495d4d2/tomli-2.4.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:d4d8fe59808a54658fcc0160ecfb1b30f9089906c50b23bcb4c69eddc19ec2b4", size = 164263, upload-time = "2026-03-25T20:21:52.543Z" }, + { url = "https://files.pythonhosted.org/packages/24/79/6ab420d37a270b89f7195dec5448f79400d9e9c1826df982f3f8e97b24fd/tomli-2.4.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7008df2e7655c495dd12d2a4ad038ff878d4ca4b81fccaf82b714e07eae4402c", size = 160736, upload-time = "2026-03-25T20:21:53.674Z" }, + { url = "https://files.pythonhosted.org/packages/02/e0/3630057d8eb170310785723ed5adcdfb7d50cb7e6455f85ba8a3deed642b/tomli-2.4.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1d8591993e228b0c930c4bb0db464bdad97b3289fb981255d6c9a41aedc84b2d", size = 270717, upload-time = "2026-03-25T20:21:55.129Z" }, + { url = "https://files.pythonhosted.org/packages/7a/b4/1613716072e544d1a7891f548d8f9ec6ce2faf42ca65acae01d76ea06bb0/tomli-2.4.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:734e20b57ba95624ecf1841e72b53f6e186355e216e5412de414e3c51e5e3c41", size = 278461, upload-time = "2026-03-25T20:21:56.228Z" }, + { url = "https://files.pythonhosted.org/packages/05/38/30f541baf6a3f6df77b3df16b01ba319221389e2da59427e221ef417ac0c/tomli-2.4.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8a650c2dbafa08d42e51ba0b62740dae4ecb9338eefa093aa5c78ceb546fcd5c", size = 274855, upload-time = "2026-03-25T20:21:57.653Z" }, + { url = "https://files.pythonhosted.org/packages/77/a3/ec9dd4fd2c38e98de34223b995a3b34813e6bdadf86c75314c928350ed14/tomli-2.4.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:504aa796fe0569bb43171066009ead363de03675276d2d121ac1a4572397870f", size = 283144, upload-time = "2026-03-25T20:21:59.089Z" }, + { url = "https://files.pythonhosted.org/packages/ef/be/605a6261cac79fba2ec0c9827e986e00323a1945700969b8ee0b30d85453/tomli-2.4.1-cp314-cp314t-win32.whl", hash = "sha256:b1d22e6e9387bf4739fbe23bfa80e93f6b0373a7f1b96c6227c32bef95a4d7a8", size = 108683, upload-time = "2026-03-25T20:22:00.214Z" }, + { url = "https://files.pythonhosted.org/packages/12/64/da524626d3b9cc40c168a13da8335fe1c51be12c0a63685cc6db7308daae/tomli-2.4.1-cp314-cp314t-win_amd64.whl", hash = "sha256:2c1c351919aca02858f740c6d33adea0c5deea37f9ecca1cc1ef9e884a619d26", size = 121196, upload-time = "2026-03-25T20:22:01.169Z" }, + { url = "https://files.pythonhosted.org/packages/5a/cd/e80b62269fc78fc36c9af5a6b89c835baa8af28ff5ad28c7028d60860320/tomli-2.4.1-cp314-cp314t-win_arm64.whl", hash = "sha256:eab21f45c7f66c13f2a9e0e1535309cee140182a9cdae1e041d02e47291e8396", size = 100393, upload-time = "2026-03-25T20:22:02.137Z" }, + { url = "https://files.pythonhosted.org/packages/7b/61/cceae43728b7de99d9b847560c262873a1f6c98202171fd5ed62640b494b/tomli-2.4.1-py3-none-any.whl", hash = "sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe", size = 14583, upload-time = "2026-03-25T20:22:03.012Z" }, +] + +[[package]] +name = "tomli-w" +version = "1.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/19/75/241269d1da26b624c0d5e110e8149093c759b7a286138f4efd61a60e75fe/tomli_w-1.2.0.tar.gz", hash = "sha256:2dd14fac5a47c27be9cd4c976af5a12d87fb1f0b4512f81d69cce3b35ae25021", size = 7184, upload-time = "2025-01-15T12:07:24.262Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c7/18/c86eb8e0202e32dd3df50d43d7ff9854f8e0603945ff398974c1d91ac1ef/tomli_w-1.2.0-py3-none-any.whl", hash = "sha256:188306098d013b691fcadc011abd66727d3c414c571bb01b1a174ba8c983cf90", size = 6675, upload-time = "2025-01-15T12:07:22.074Z" }, +] + +[[package]] +name = "torch" +version = "2.12.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cuda-bindings", marker = "sys_platform == 'linux'" }, + { name = "cuda-toolkit", extra = ["cudart", "cufft", "cufile", "cupti", "curand", "cusolver", "cusparse", "nvjitlink", "nvrtc", "nvtx"], marker = "sys_platform == 'linux'" }, + { name = "filelock" }, + { name = "fsspec" }, + { name = "jinja2" }, + { name = "networkx" }, + { name = "nvidia-cublas", marker = "sys_platform == 'linux'" }, + { name = "nvidia-cudnn-cu13", marker = "sys_platform == 'linux'" }, + { name = "nvidia-cusparselt-cu13", marker = "sys_platform == 'linux'" }, + { name = "nvidia-nccl-cu13", marker = "sys_platform == 'linux'" }, + { name = "nvidia-nvshmem-cu13", marker = "sys_platform == 'linux'" }, + { name = "setuptools" }, + { name = "sympy" }, + { name = "triton", marker = "sys_platform == 'linux'" }, + { name = "typing-extensions" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/59/38/7028d3be540f1dcdf41660a2b01d0c51d2cb73915fe370d84e4d277a6d47/torch-2.12.1-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:ef81f503912effea2ce3d9b12a2e3a6ed488943e91271c90c7a829f60baf6aa2", size = 87975425, upload-time = "2026-06-17T21:08:34.094Z" }, + { url = "https://files.pythonhosted.org/packages/5a/e3/750b3e3548635ceac03ba255daa26dbc7ed66ca3484dc4b4d955ab7f4501/torch-2.12.1-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:107df6888624bdea41508f9aeb6149d9333c737a5530ceecb56c904e811369ae", size = 426379894, upload-time = "2026-06-17T21:06:55.077Z" }, + { url = "https://files.pythonhosted.org/packages/dc/ca/ed24783da629ff3e640ba3f70a7639e9045d3d88b93ee6bc47b8a28a1f2c/torch-2.12.1-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:6e29e7e74d05bda7d955c75e99459f878ebd970ef851b4057edbd3b34a5eb4a3", size = 532169264, upload-time = "2026-06-17T21:08:17.65Z" }, + { url = "https://files.pythonhosted.org/packages/46/61/c63f0158446f3a98ea672b004d761b848911eba567ea4a624c7db5aadc04/torch-2.12.1-cp311-cp311-win_amd64.whl", hash = "sha256:a513506cfda3c1c78dabeb6574c1597538c0254b3d39af174dde35d8177f4ce3", size = 122953086, upload-time = "2026-06-17T21:08:27.69Z" }, + { url = "https://files.pythonhosted.org/packages/f0/54/efb7ebca77970012b0cc21687a55d70eb2ba514b2c2b8e18d9fb1222f3be/torch-2.12.1-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:d2dd0f2c5f7ccbddaf34cade0deaf476808368f902b9cdb7f36a2ab42301bc0e", size = 87991951, upload-time = "2026-06-17T21:07:49.309Z" }, + { url = "https://files.pythonhosted.org/packages/1e/00/4210d76ca7424981f04033ebe7e48816ab83287a62538747a58825db770c/torch-2.12.1-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:2de4e19b88a481482c6c75291f2d6a52eda3ce51f311b29aa9b68499c830c07c", size = 426382721, upload-time = "2026-06-17T21:06:41.842Z" }, + { url = "https://files.pythonhosted.org/packages/76/1f/bc9f5a5aa569307076365f25afcebacb22e9c754b1bcfbaaa146627c7fda/torch-2.12.1-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:649e4ced014ba646f76f8cb9c9726735a6323eb321b7919f942790a923f90921", size = 532261322, upload-time = "2026-06-17T21:06:06.673Z" }, + { url = "https://files.pythonhosted.org/packages/9e/49/c549461daa008159d006a76a991fbc2f26fa8bac27a4030c858463dcb20f/torch-2.12.1-cp312-cp312-win_amd64.whl", hash = "sha256:e86550597877fb272ddc52db2f85b82cb601ea7bd932576a0340152cae2200b3", size = 122988095, upload-time = "2026-06-17T21:07:44.9Z" }, + { url = "https://files.pythonhosted.org/packages/ff/4a/0300261818e1560d72cc160ac826005507e8b7ca0a35788b591436d05b4a/torch-2.12.1-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:c75e93173c700bccd6bfcc4a9d19ce242ab6dacd1f1781483027a16239b9e650", size = 87992358, upload-time = "2026-06-17T21:07:40.299Z" }, + { url = "https://files.pythonhosted.org/packages/30/a7/874a5ca05e8f159211dca7921060f7057acc1adb26431e119fd150623efc/torch-2.12.1-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:fcb61ccd20784b62bdd78ec84238a5cfb383b4994902e03bac95505ab360884c", size = 426386134, upload-time = "2026-06-17T21:07:31.481Z" }, + { url = "https://files.pythonhosted.org/packages/e1/75/20bb8fe9c1ad6538cce8cd0391b51927ae5af0b17ed1eab44b8824465dc1/torch-2.12.1-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:f4afc8083dff08719edbea346644476e3cec0cf40ebe256be0ee5d5b7c7e8c0d", size = 532268019, upload-time = "2026-06-17T21:05:37.925Z" }, + { url = "https://files.pythonhosted.org/packages/d1/fa/824ddb662af55b2eabc0dbb7b57c7c0b1bcd93693754a2b8509ec4d16490/torch-2.12.1-cp313-cp313-win_amd64.whl", hash = "sha256:f92609e3b3ce72f25e2eb780d043ced2480c1a86c47c852604fc7a9108648386", size = 122987777, upload-time = "2026-06-17T21:07:09.49Z" }, + { url = "https://files.pythonhosted.org/packages/63/b7/1b49fe7086ea36839cc80abc43174c43d0ab6f676c0891c871c162f44fe3/torch-2.12.1-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:e9b6f7d2dd66ea87a3ae620069d31335d594c06effb1a383bdd21cfe61e44ece", size = 88010025, upload-time = "2026-06-17T21:07:03.934Z" }, + { url = "https://files.pythonhosted.org/packages/d7/06/5b44063a6545036dcc680d2d303b137d9176cfb2cc1e1863e3ef94abeb52/torch-2.12.1-cp314-cp314-manylinux_2_28_aarch64.whl", hash = "sha256:7973ccd3d2cd35c74449213f7bded199bec6c6247e705cbeda7407af79703d91", size = 426392891, upload-time = "2026-06-17T21:05:52.261Z" }, + { url = "https://files.pythonhosted.org/packages/f8/dd/c9ce9a4b0eb3c5bb92d9ea56766e2c22559f0b45171149188494edcce80f/torch-2.12.1-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:c64ac4aac16be5e296dcd912305605804b203333c690bf98c55bc09494ee92ad", size = 532272494, upload-time = "2026-06-17T21:06:22.72Z" }, + { url = "https://files.pythonhosted.org/packages/21/7c/f3a601fc1b1f663ff269bfe553654e638651939aa6563e8daa7167c33098/torch-2.12.1-cp314-cp314-win_amd64.whl", hash = "sha256:f6dc4caf7eb4adb38a2d9f536b51db56310fdd1254e69a2d96767e1367c892b3", size = 122987254, upload-time = "2026-06-17T21:06:33.199Z" }, + { url = "https://files.pythonhosted.org/packages/e6/8c/b8087556cf81ddd808dbeb34afb8396d7ae7a1694ab489f08b1a0004e7d0/torch-2.12.1-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:2afbb2bdaa8a95040e733f05492ddf133c3967c9b7ce0abd218d704b6cab437d", size = 88303173, upload-time = "2026-06-17T21:05:06.603Z" }, + { url = "https://files.pythonhosted.org/packages/4a/07/fe09d1699fbed2afa10ebc692ff2b99d113f2605b6748cea633989e2789a/torch-2.12.1-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:97eba061fcb042fed191400b15568990073d67eaacaa6ee9b7ca01dd8b790fe9", size = 426404009, upload-time = "2026-06-17T21:04:57.557Z" }, + { url = "https://files.pythonhosted.org/packages/2e/f7/0ce4f6c1962c60ded7270e0a9eb560fb615c92b89d332cf9e3dff36d5ecc/torch-2.12.1-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:3867b861391701012adb2df93360efb88494dca245a185e3bb7624495cfe3f33", size = 532184292, upload-time = "2026-06-17T21:05:17.526Z" }, + { url = "https://files.pythonhosted.org/packages/70/db/e384c12aba30320ca92aaaf557456cbcb26f04b4df307728bb8f019f5000/torch-2.12.1-cp314-cp314t-win_amd64.whl", hash = "sha256:dd15595f8fc764cffde8c6361a3beb6ef69a028c851b1b3e70e077f615980d4e", size = 123231142, upload-time = "2026-06-17T21:05:27.061Z" }, +] + +[[package]] +name = "tqdm" +version = "4.68.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/87/d7/0535a28b1f5f24f6612fb3ff1e89fb1a8d160fee0f976e0aa6803862134b/tqdm-4.68.3.tar.gz", hash = "sha256:00dfa48452b6b6cfae3dd9885636c23d3422d1ec97c66d96818cbd5e0821d482", size = 170596, upload-time = "2026-06-17T07:36:52.105Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d8/8e/bb97bb0c71802080bfc8952937d174e49cfc50de5c951dd47b2496f0dcdb/tqdm-4.68.3-py3-none-any.whl", hash = "sha256:39832cc2def2789a6f29df83f172db7416cea70052c0907a57801c5f2fdccb03", size = 78337, upload-time = "2026-06-17T07:36:50.132Z" }, +] + +[[package]] +name = "transformers" +version = "5.12.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "huggingface-hub" }, + { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12'" }, + { name = "numpy", version = "2.5.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12'" }, + { name = "packaging" }, + { name = "pyyaml" }, + { name = "regex" }, + { name = "safetensors" }, + { name = "tokenizers" }, + { name = "tqdm" }, + { name = "typer" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/aa/7c/8240f612819718100a9346dc28dea6a11370c3ca9c8c6eabadd3dea4ef29/transformers-5.12.1.tar.gz", hash = "sha256:679ee731c8225347889ad4fb3b2c926a62e9da3b7d284e9d12c791da7272466b", size = 8924054, upload-time = "2026-06-15T17:27:50.604Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/df/56/bbd60dd8668055803bf8ba55a81f9b8a8b31497f620109a9671d26a2076d/transformers-5.12.1-py3-none-any.whl", hash = "sha256:2a5e109d2021265df7098ffbb738295acaf5ad256f12cbc586db2ea4dcbb1a8a", size = 11150587, upload-time = "2026-06-15T17:27:46.679Z" }, +] + +[[package]] +name = "triton" +version = "3.7.1" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7b/f9/19d842d06a08559534fa1eaab6ca551b1bcf40f06620bddec1babaa2772d/triton-3.7.1-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d4a0e1cd4c4a76370ed74a8432a53cea28716827d19e40ffc732233e35ceb3f6", size = 184664887, upload-time = "2026-06-17T20:03:42.913Z" }, + { url = "https://files.pythonhosted.org/packages/cd/5e/fce69606f7f240297f163e25539906732b199530d486ce67ae319877e821/triton-3.7.1-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6744957e9fd610a29680ec2346057d0c86948ed3812468670719f391e94b44a5", size = 197701306, upload-time = "2026-06-17T19:53:13.673Z" }, + { url = "https://files.pythonhosted.org/packages/94/fa/f856e24deb462d5f18bd4b5a746957862ab9b6ee5834bda60605ec348366/triton-3.7.1-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9497f2e696ee368862a181a90b2dcc03ca978cc4f602abd67c7d81022a6988e1", size = 184692359, upload-time = "2026-06-17T20:03:48.288Z" }, + { url = "https://files.pythonhosted.org/packages/c4/6f/fb96d15db6f36d6eae4cafb998c2e0353bf59d7c4ea1662d7497f269134a/triton-3.7.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7e40869937a68206ec70d7f25bb7ec6433cb083f9135e1f36dbd318dc449a728", size = 197719725, upload-time = "2026-06-17T19:53:20.419Z" }, + { url = "https://files.pythonhosted.org/packages/00/42/c5089d4d9327fcd1e862c599cc2927f39418f84dd11a84cb2ccff9d4787a/triton-3.7.1-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cdbfc09d9ec58bc5e68321525653220de7515c199e7a8097a97c85e62b52cd0a", size = 184694629, upload-time = "2026-06-17T20:03:53.444Z" }, + { url = "https://files.pythonhosted.org/packages/07/42/2c3ac59253ae8892b6f307875263dd23dc875cdf732d3aea40d6d41fb7cb/triton-3.7.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:58c0e131da05134a2a4788ccbcc0c1105cf0f54c8e98f19e34cd465396dc15eb", size = 197729241, upload-time = "2026-06-17T19:53:27.801Z" }, + { url = "https://files.pythonhosted.org/packages/40/71/e01aa7ad573883ed9456f130226babdec70b005e098c4d6226a6238e761b/triton-3.7.1-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fe4ea396a06171f1f1f58cbd39c70b09294398f7dd7c620939bab54ad6f934fa", size = 184705764, upload-time = "2026-06-17T20:03:59.064Z" }, + { url = "https://files.pythonhosted.org/packages/a4/09/5683146fda6a2b569deb78ccfd8fbfea8bfe55f726b081c0a6bb18dd6f28/triton-3.7.1-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2020153b08280415ec0da6607834e79166442147e78e144df06b508c75b186d2", size = 197729537, upload-time = "2026-06-17T19:53:35.516Z" }, + { url = "https://files.pythonhosted.org/packages/e9/f8/448220c3092019f9fdfab39ec47985968181d67da34b44f6a7f6280a5cbb/triton-3.7.1-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c58e4c61f0c73b5dba3b5d19b4a7093c32f90dc18b2a7f121a7c16ccd31107b7", size = 184814760, upload-time = "2026-06-17T20:04:04.984Z" }, + { url = "https://files.pythonhosted.org/packages/f0/ac/229b7d4589d2e5937310e72c6d46e89599d16a4a12b479ffa1499fee8eb8/triton-3.7.1-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:10ba85fa2cca4a2fbdeb36bf1cb082f2c252bda55bf9fccd74f65ec5bc647e68", size = 197824404, upload-time = "2026-06-17T19:53:42.772Z" }, +] + +[[package]] +name = "twine" +version = "6.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "id" }, + { name = "keyring", marker = "platform_machine != 'ppc64le' and platform_machine != 's390x'" }, + { name = "packaging" }, + { name = "readme-renderer" }, + { name = "requests" }, + { name = "requests-toolbelt" }, + { name = "rfc3986" }, + { name = "rich" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e0/a8/949edebe3a82774c1ec34f637f5dd82d1cf22c25e963b7d63771083bbee5/twine-6.2.0.tar.gz", hash = "sha256:e5ed0d2fd70c9959770dce51c8f39c8945c574e18173a7b81802dab51b4b75cf", size = 172262, upload-time = "2025-09-04T15:43:17.255Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3a/7a/882d99539b19b1490cac5d77c67338d126e4122c8276bf640e411650c830/twine-6.2.0-py3-none-any.whl", hash = "sha256:418ebf08ccda9a8caaebe414433b0ba5e25eb5e4a927667122fbe8f829f985d8", size = 42727, upload-time = "2025-09-04T15:43:15.994Z" }, +] + +[[package]] +name = "typer" +version = "0.25.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "annotated-doc" }, + { name = "click" }, + { name = "rich" }, + { name = "shellingham" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e4/51/9aed62104cea109b820bbd6c14245af756112017d309da813ef107d42e7e/typer-0.25.1.tar.gz", hash = "sha256:9616eb8853a09ffeabab1698952f33c6f29ffdbceb4eaeecf571880e8d7664cc", size = 122276, upload-time = "2026-04-30T19:32:16.964Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3f/f9/2b3ff4e56e5fa7debfaf9eb135d0da96f3e9a1d5b27222223c7296336e5f/typer-0.25.1-py3-none-any.whl", hash = "sha256:75caa44ed46a03fb2dab8808753ffacdbfea88495e74c85a28c5eefcf5f39c89", size = 58409, upload-time = "2026-04-30T19:32:18.271Z" }, +] + +[[package]] +name = "typing-extensions" +version = "4.15.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" }, +] + +[[package]] +name = "typing-inspection" +version = "0.4.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/55/e3/70399cb7dd41c10ac53367ae42139cf4b1ca5f36bb3dc6c9d33acdb43655/typing_inspection-0.4.2.tar.gz", hash = "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464", size = 75949, upload-time = "2025-10-01T02:14:41.687Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7", size = 14611, upload-time = "2025-10-01T02:14:40.154Z" }, +] + +[[package]] +name = "tzdata" +version = "2026.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ba/19/1b9b0e29f30c6d35cb345486df41110984ea67ae69dddbc0e8a100999493/tzdata-2026.2.tar.gz", hash = "sha256:9173fde7d80d9018e02a662e168e5a2d04f87c41ea174b139fbef642eda62d10", size = 198254, upload-time = "2026-04-24T15:22:08.651Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ce/e4/dccd7f47c4b64213ac01ef921a1337ee6e30e8c6466046018326977efd95/tzdata-2026.2-py2.py3-none-any.whl", hash = "sha256:bbe9af844f658da81a5f95019480da3a89415801f6cc966806612cc7169bffe7", size = 349321, upload-time = "2026-04-24T15:22:05.876Z" }, +] + +[[package]] +name = "urllib3" +version = "2.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/53/0c/06f8b233b8fd13b9e5ee11424ef85419ba0d8ba0b3138bf360be2ff56953/urllib3-2.7.0.tar.gz", hash = "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c", size = 433602, upload-time = "2026-05-07T16:13:18.596Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7f/3e/5db95bcf282c52709639744ca2a8b149baccf648e39c8cc87553df9eae0c/urllib3-2.7.0-py3-none-any.whl", hash = "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897", size = 131087, upload-time = "2026-05-07T16:13:17.151Z" }, +] + +[[package]] +name = "uvicorn" +version = "0.49.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "h11" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c4/1f/fa18009dea8469069cca78a4e877a008ab78f08b064bfc9ab891579077ff/uvicorn-0.49.0.tar.gz", hash = "sha256:ebf4271aa580d9de97f93192d4595176df6e91f9aae919ca73e4fc07df1e66a3", size = 91284, upload-time = "2026-06-03T22:01:30.448Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/88/fa/e1388bbcf24ef3274f45c0c1c7b501fd14971037c1b6ee23610553307497/uvicorn-0.49.0-py3-none-any.whl", hash = "sha256:ba3d14c3ee7e41c6c654c46c9eb489d33213cdd30aa1696eab1374337c13f68f", size = 71376, upload-time = "2026-06-03T22:01:29.037Z" }, +] + +[[package]] +name = "zipp" +version = "4.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b9/d8/eab98a517c14134c0b2eb4e2387bc5f457334293ec5d2dd3857ec2966802/zipp-4.1.0.tar.gz", hash = "sha256:4cb57381f544315db7688e976e922a2b18cdb513d21cc194eb42232ba2a3e602", size = 26214, upload-time = "2026-05-18T20:08:57.967Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3a/13/547360d81e6d88d58492968ffda9f9542854f11310ee556fef14260cc886/zipp-4.1.0-py3-none-any.whl", hash = "sha256:25ad4e16390cd314347dd8f1de67a2ac538ae658ed4ab9db16029c07c188e97f", size = 10238, upload-time = "2026-05-18T20:08:57.045Z" }, +]