diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..aea4a7b --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,56 @@ +name: Publish + +# Tag push (v*) publishes to PyPI. Manual run publishes to TestPyPI. +on: + push: + tags: ["v*"] + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v7 + - uses: astral-sh/setup-uv@v10.3.2 + - run: uv build + - name: Check tag matches package version + if: github.ref_type == 'tag' + run: test -f "dist/pse_sdk-${GITHUB_REF_NAME#v}.tar.gz" + - uses: actions/upload-artifact@v7 + with: + name: dist + path: dist/ + + testpypi: + if: github.event_name == 'workflow_dispatch' + needs: build + runs-on: ubuntu-latest + environment: + name: testpypi + url: https://test.pypi.org/project/pse-sdk/ + permissions: + id-token: write + steps: + - uses: actions/download-artifact@v8 + with: + name: dist + path: dist/ + - uses: pypa/gh-action-pypi-publish@release/v1 + with: + repository-url: https://test.pypi.org/legacy/ + + pypi: + if: github.ref_type == 'tag' + needs: build + runs-on: ubuntu-latest + environment: + name: pypi + url: https://pypi.org/project/pse-sdk/ + permissions: + id-token: write + steps: + - uses: actions/download-artifact@v8 + with: + name: dist + path: dist/ + - uses: pypa/gh-action-pypi-publish@release/v1 diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..48adad1 --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,44 @@ +name: Tests + +on: + push: + branches: [main, develop] + pull_request: + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v7 + - uses: astral-sh/setup-uv@v10.3.2 + - run: uv run --locked ruff check src/ scripts/ tests/ + - run: uv run --locked ruff format --check src/ scripts/ tests/ + - run: uv run --locked scripts/gen_docs.py --check + + test: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"] + steps: + - uses: actions/checkout@v7 + - uses: astral-sh/setup-uv@v10.3.2 + with: + python-version: ${{ matrix.python-version }} + # manual_test.py calls the live API on import + - run: uv run --locked pytest --ignore=tests/manual_test.py + + test-lowest: + # Oldest dependency versions pyproject.toml allows. pandas 1.5 predates + # numpy 2 and breaks against it, so numpy is held below 2. + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v7 + - uses: astral-sh/setup-uv@v10.3.2 + with: + python-version: "3.10" + - run: echo "numpy<2" > constraints.txt + - run: uv venv + - run: uv pip install --resolution lowest-direct -e . --group dev -c constraints.txt + - run: .venv/bin/python -m pytest --ignore=tests/manual_test.py diff --git a/.python-version b/.python-version new file mode 100644 index 0000000..24ee5b1 --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.13 diff --git a/CHANGELOG.md b/CHANGELOG.md index cb33378..24761f4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,59 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [2.0.0] - 2026-10-27 + +### Added +- `PSEClient.fetch(endpoint, start, end, columns=None, format="dict")`: + query any of the 90 PSE API endpoints for a date range, fetched in + 30-day chunks. Replaces the `get_*` methods +- Published on PyPI as `pse-sdk`: `pip install pse-sdk`, or + `pip install "pse-sdk[pandas]"` for DataFrame output +- `PSEClient.endpoints()`: names of all endpoints +- `PSEClient.columns(endpoint)`: data columns of an endpoint, in API order + (meta columns left out). Both read the bundled registry, no HTTP request. +- `fetch()` checks column names against the registry before any request. + Unknown columns raise `ValueError` naming each one with a hint (close + match, or other endpoints that have it) instead of an HTTP 400. `columns` + that is not a list or tuple of strings raises `TypeError` (#25) +- `fetch()` supports the six `ogr-*-head` endpoints, filtered on `period` + (#37) + +### Changed +- License is now MIT (was proprietary) +- README and package description state the SDK is unofficial and not + affiliated with PSE S.A. +- Unknown endpoint errors suggest the closest endpoint name (#25) +- `HTTPError` from the API includes the API's error message, e.g. + `Invalid field to be returned requested: cen_cots` +- `docs/endpoints.md` is generated from the endpoint registry + (`scripts/gen_docs.py`) and lists the data columns of all 90 endpoints, + including the previously missing `wmb` and `his-gen-pal-sire`, plus the + date and key columns of each. The Description column is dropped. +- `fetch()` column and date-filter notes moved from `docs/endpoints.md` and + the README to the new `docs/usage.md` +- Development uses uv: dev dependencies in a uv dependency group, + `uv.lock` and `.python-version` committed +- Package version is read from `pse_sdk.__version__` (hatch dynamic + version) +- GitHub Actions: `tests.yml` runs ruff, `gen_docs.py --check` and tests on + Python 3.10–3.14; `publish.yml` publishes to PyPI on `v*` tag push + (TestPyPI on manual run) + +### Removed +- **Breaking:** all 32 `get_*` methods of `PSEClient` (`get_cen`, `get_csdac`, + `get_kb`, `get_sk_cost`, `get_demand`, ...) and the internal `make_endpoint` + helper. Use `fetch()` with the endpoint and column instead: + `get_cen(s, e)` → `fetch("price-cost", s, e, columns=["cen_cost"])`. + `fetch()` also returns the `*_utc` meta columns. + +### Fixed +- First page request of `fetch()` now retried on 5xx errors, like later + pages (#32) +- Non-string endpoint (e.g. a list or dict) raises `ValueError` naming its + type, e.g. `Endpoint must be a str, got list.`, instead of + `TypeError: unhashable type` (#56) + ## [1.5.1] - 2026-10-20 ### Added @@ -67,11 +120,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - `PSEClient` class for interacting with the PSE public REST API -- `OutputFormat` enum for controlling response format (JSON, CSV, XML) +- `OutputFormat` type (`Literal["dict", "dataframe"]`) for controlling response + format: list of dicts or pandas DataFrame - `HTTPClient` for managing HTTP requests with pagination support - Coverage of the `price-cost` PSE API endpoint - Date normalization and validation utilities -- Configurable `base_url` and `page_size` parameters +- Configurable HTTP `timeout` parameter - Optional pandas integration via `pip install pse-sdk[pandas]` - Unit tests for PSEClient and HTTPClient diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 88d2dca..97daef0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -9,12 +9,10 @@ cd pse-python-sdk ``` -2. **Set up a virtual environment** and install dev dependencies: +2. **Install [uv](https://docs.astral.sh/uv/getting-started/installation/)** and sync the environment (creates `.venv` with the package and dev dependencies, pinned by `uv.lock`): ```bash - python -m venv .venv - source .venv/bin/activate # Windows: .venv\Scripts\activate - pip install -e ".[dev]" + uv sync ``` 3. **Checkout `develop`** — all feature work starts here: @@ -43,21 +41,59 @@ Short-lived branches for specific work: ## Development Workflow -Run these from the project root with your venv activated: +Run these from the project root: ```bash # Run tests -pytest +uv run pytest # Lint -ruff check src/ +uv run ruff check src/ scripts/ tests/ # Format -ruff format src/ +uv run ruff format src/ scripts/ tests/ ``` Fix any lint/test failures before opening a PR. +## Endpoint Registry + +`src/pse_sdk/_registry.py` is generated from the PSE OpenAPI spec (`https://api.raporty.pse.pl/api/openapi`) — don't edit it by hand. + +```bash +# Regenerate from the live spec +uv run scripts/gen_registry.py + +# Check that the committed registry is up to date +uv run scripts/gen_registry.py --check +``` + +## Endpoint Docs + +`docs/endpoints.md` is generated from the registry — don't edit it by hand. Regenerate it after any registry change. + +```bash +# Regenerate +uv run scripts/gen_docs.py + +# Check that the committed docs are up to date +uv run scripts/gen_docs.py --check +``` + +## Dependencies + +Dev dependencies live in the `dev` dependency group in `pyproject.toml`; exact versions are pinned in `uv.lock`. + +```bash +# Add a dev dependency +uv add --dev + +# Upgrade a single locked package +uv lock --upgrade-package +``` + +Commit `uv.lock` together with any `pyproject.toml` dependency change. + ## Commit Convention Use [Conventional Commits](https://www.conventionalcommits.org/): diff --git a/LICENSE.md b/LICENSE.md index ab9f3c4..142caa8 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,23 +1,21 @@ -Copyright (C) 2026 FranekGit - All Rights Reserved. - -IMPORTANT NOTICE: PLEASE READ CAREFULLY BEFORE USING THE SOFTWARE. - -1. PROPRIETARY AND CONFIDENTIAL INFORMATION - -The contents of this project, including its source code, are proprietary and confidential. Unauthorized copying, transferring, or reproduction of any part of this project, through any medium, is strictly prohibited. - -2. LICENSE GRANT - -The receipt or possession of the source code and/or any parts thereof does not convey or imply any right to use them for any purpose other than the specific purpose for which they were provided to you. - -3. DISCLAIMER OF WARRANTIES - -The software is provided "AS IS," without warranty of any kind, express or implied, including, but not limited to, the warranties of merchantability, fitness for a particular purpose, and non-infringement. - -4. LIMITATION OF LIABILITY - -In no event shall Sourceduty, its authors, or copyright holders be liable for any claim, damages, or other liability, whether in an action of contract, tort, or otherwise, arising from, out of, or in connection with the Software or the use or other dealings in the Software. - -5. COPYRIGHT NOTICE - -You are required to include the above copyright notice and this permission notice in all copies or substantial portions of the Software. \ No newline at end of file +MIT License + +Copyright (c) 2026 FranekGit + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 6b85647..0cfb509 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,23 @@

- PSE Logo + PSE Logo

# pse-python-sdk -![Version](https://img.shields.io/badge/version-v1.5.1-blue) +![Version](https://img.shields.io/badge/version-v2.0.0-blue) Python SDK for the PSE (Polskie Sieci Elektroenergetyczne) public reporting API. > API reference: https://api.raporty.pse.pl/app/home +> **Disclaimer:** not affiliated with PSE S.A. + + ## Installation ```bash -pip install git+https://github.com/FranekGit/pse-python-sdk.git +pip install pse-sdk ``` ## Quick Start @@ -24,29 +27,22 @@ from pse_sdk import PSEClient client = PSEClient() -# Returns list[dict] -records = client.get_cen(start="2024-01-01", end="2024-01-31") - -# Returns pd.DataFrame (requires pandas) -df = client.get_cen(start="2024-01-01", end="2024-01-31", format="dataframe") +# list[dict] with all columns +rows = client.fetch("price-cost", start="2025-10-01", end="2025-10-31") + +# pd.DataFrame (requires pandas) with selected columns +df = client.fetch( + "price-cost", + start="2025-10-01", + end="2025-10-31", + columns=["cen_cost", "ckoeb_cost"], + format="dataframe", +) ``` -## Date Formats - -| Format | Example | -|--------------|--------------| -| `YYYY-MM-DD` | `2024-01-01` | -| `YYYY/MM/DD` | `2024/01/01` | -| `YYYYMMDD` | `20240101` | - -## Output Formats - -| Format | Return Type | -|---------------|----------------| -| `"dict"` | `list[dict]` | -| `"dataframe"` | `pd.DataFrame` | - -## Endpoints - -See [docs/endpoints.md](docs/endpoints.md) for available endpoints. +## Documentation +- [docs/usage.md](https://github.com/FranekGit/pse-python-sdk/blob/main/docs/usage.md): finding endpoints, date ranges, columns and + output formats +- [docs/endpoints.md](https://github.com/FranekGit/pse-python-sdk/blob/main/docs/endpoints.md): all endpoints, their columns and + types diff --git a/docs/endpoints.md b/docs/endpoints.md index 1b61467..e6e528f 100644 --- a/docs/endpoints.md +++ b/docs/endpoints.md @@ -1,137 +1,880 @@ + # Endpoints -All endpoints share the same signature: - -```python -(start: str, end: str, format: OutputFormat = "dict") -``` +> API reference: `https://api.raporty.pse.pl/api/openapi` -## Common Response Columns +See [usage.md](usage.md) for how `fetch()` uses these columns. -Every endpoint returns these columns plus endpoint-specific columns: +## Data columns -- `dtime` — timestamp -- `period` — period identifier -- `business_date` — business date -- `publication_ts` — publication timestamp +In API order. Meta columns are left out. -## Endpoints Coverage +| Endpoint | Column | Type | +|---|---|---| +| `afrr-status` | `event_time` | string | +| `afrr-status` | `event_time_utc` | string | +| `afrr-status` | `afrr_status` | integer | +| `afrr-status` | `reason_code` | integer | +| `afrr-status` | `reason` | string | +| `cmbp-tp` | `onmb` | string | +| `cmbp-tp` | `fcr_g` | number | +| `cmbp-tp` | `fcr_d` | number | +| `cmbp-tp` | `afrr_g` | number | +| `cmbp-tp` | `afrr_d` | number | +| `cmbp-tp` | `mfrrd_g` | number | +| `cmbp-tp` | `mfrrd_d` | number | +| `cmbp-tp` | `rr_d` | number | +| `cmbp-tp` | `rr_g` | number | +| `cmbu-tu` | `fcr_g` | number | +| `cmbu-tu` | `fcr_d` | number | +| `cmbu-tu` | `afrr_g` | number | +| `cmbu-tu` | `afrr_d` | number | +| `cmbu-tu` | `mfrrd_g` | number | +| `cmbu-tu` | `mfrrd_d` | number | +| `codn` | `period_from_date` | string | +| `codn` | `period_to_date` | string | +| `codn` | `price` | number | +| `cor` | `cor_cost` | number | +| `cor` | `cor_fcst` | number | +| `cor-q-1` | `period_from_date` | string | +| `cor-q-1` | `period_to_date` | string | +| `cor-q-1` | `cor_excl` | number | +| `cor-q-1` | `cor_inc` | number | +| `cordmax` | `cordmax_fcst` | number | +| `cordmax` | `cordmax_cost` | number | +| `crb-rozl` | `cen_cost` | number | +| `crb-rozl` | `ckoeb_cost` | number | +| `crb-rozl` | `ceb_pp_cost` | number | +| `crb-rozl` | `ceb_sr_cost` | number | +| `crb-rozl` | `ceb_sr_afrrg_cost` | number | +| `crb-rozl` | `ceb_sr_afrrd_cost` | number | +| `csdac-pln` | `csdac_pln` | number | +| `csire-kpi1` | `row_no` | string | +| `csire-kpi1` | `eic_code` | string | +| `csire-kpi1` | `tax_id` | string | +| `csire-kpi1` | `name` | string | +| `csire-kpi1` | `date_1d` | string | +| `csire-kpi1` | `completeness_1d` | number | +| `csire-kpi1` | `date_from_5d` | string | +| `csire-kpi1` | `date_to_5d` | string | +| `csire-kpi1` | `completeness_5d` | number | +| `csire-kpi1` | `date_from_1m` | string | +| `csire-kpi1` | `date_to_1m` | string | +| `csire-kpi1` | `completeness_1m` | number | +| `csire-kpi1` | `date_from_6m` | string | +| `csire-kpi1` | `date_to_6m` | string | +| `csire-kpi1` | `completeness_6m` | number | +| `csire-kpi2` | `row_no` | string | +| `csire-kpi2` | `eic_code` | string | +| `csire-kpi2` | `tax_id` | string | +| `csire-kpi2` | `name` | string | +| `csire-kpi2` | `date_from_1m` | string | +| `csire-kpi2` | `date_to_1m` | string | +| `csire-kpi2` | `completeness_1m` | number | +| `csire-kpi2` | `date_from_6m` | string | +| `csire-kpi2` | `date_to_6m` | string | +| `csire-kpi2` | `completeness_6m` | number | +| `csire-kpi3` | `row_no` | string | +| `csire-kpi3` | `eic_code` | string | +| `csire-kpi3` | `tax_id` | string | +| `csire-kpi3` | `name` | string | +| `csire-kpi3` | `date_from_1m` | string | +| `csire-kpi3` | `date_to_1m` | string | +| `csire-kpi3` | `completeness_1m` | number | +| `csire-kpi3` | `date_from_6m` | string | +| `csire-kpi3` | `date_to_6m` | string | +| `csire-kpi3` | `completeness_6m` | number | +| `csire-kpi4` | `row_no` | string | +| `csire-kpi4` | `eic_code` | string | +| `csire-kpi4` | `tax_id` | string | +| `csire-kpi4` | `name` | string | +| `csire-kpi4` | `date_1d` | string | +| `csire-kpi4` | `completeness_1d` | number | +| `csire-kpi4` | `date_from_5d` | string | +| `csire-kpi4` | `date_to_5d` | string | +| `csire-kpi4` | `completeness_5d` | number | +| `csire-kpi4` | `date_from_1m` | string | +| `csire-kpi4` | `date_to_1m` | string | +| `csire-kpi4` | `completeness_1m` | number | +| `csire-kpi4` | `date_from_6m` | string | +| `csire-kpi4` | `date_to_6m` | string | +| `csire-kpi4` | `completeness_6m` | number | +| `csire-kpi5` | `row_no` | string | +| `csire-kpi5` | `eic_code` | string | +| `csire-kpi5` | `tax_id` | string | +| `csire-kpi5` | `name` | string | +| `csire-kpi5` | `date_1d` | string | +| `csire-kpi5` | `timeliness_1d` | number | +| `csire-kpi5` | `date_from_5d` | string | +| `csire-kpi5` | `date_to_5d` | string | +| `csire-kpi5` | `timeliness_5d` | number | +| `csire-kpi5` | `date_from_1m` | string | +| `csire-kpi5` | `date_to_1m` | string | +| `csire-kpi5` | `timeliness_1m` | number | +| `csire-kpi5` | `date_from_6m` | string | +| `csire-kpi5` | `date_to_6m` | string | +| `csire-kpi5` | `timeliness_6m` | number | +| `csire-kpi6` | `row_no` | string | +| `csire-kpi6` | `eic_code` | string | +| `csire-kpi6` | `tax_id` | string | +| `csire-kpi6` | `name` | string | +| `csire-kpi6` | `date_from_1m` | string | +| `csire-kpi6` | `date_to_1m` | string | +| `csire-kpi6` | `timeliness_1m` | number | +| `csire-kpi6` | `date_from_6m` | string | +| `csire-kpi6` | `date_to_6m` | string | +| `csire-kpi6` | `timeliness_6m` | number | +| `csire-kpi7` | `row_no` | string | +| `csire-kpi7` | `eic_code` | string | +| `csire-kpi7` | `tax_id` | string | +| `csire-kpi7` | `name` | string | +| `csire-kpi7` | `date_from_1m` | string | +| `csire-kpi7` | `date_to_1m` | string | +| `csire-kpi7` | `timeliness_1m` | number | +| `csire-kpi7` | `date_from_6m` | string | +| `csire-kpi7` | `date_to_6m` | string | +| `csire-kpi7` | `timeliness_6m` | number | +| `csire-kpi8` | `row_no` | string | +| `csire-kpi8` | `eic_code` | string | +| `csire-kpi8` | `tax_id` | string | +| `csire-kpi8` | `name` | string | +| `csire-kpi8` | `date_1d` | string | +| `csire-kpi8` | `timeliness_1d` | number | +| `csire-kpi8` | `date_from_5d` | string | +| `csire-kpi8` | `date_to_5d` | string | +| `csire-kpi8` | `timeliness_5d` | number | +| `csire-kpi8` | `date_from_1m` | string | +| `csire-kpi8` | `date_to_1m` | string | +| `csire-kpi8` | `timeliness_1m` | number | +| `csire-kpi8` | `date_from_6m` | string | +| `csire-kpi8` | `date_to_6m` | string | +| `csire-kpi8` | `timeliness_6m` | number | +| `csire-kpi9` | `row_no` | string | +| `csire-kpi9` | `eic_code` | string | +| `csire-kpi9` | `tax_id` | string | +| `csire-kpi9` | `name` | string | +| `csire-kpi9` | `date_1d` | string | +| `csire-kpi9` | `correctness_1d` | number | +| `csire-kpi9` | `date_from_5d` | string | +| `csire-kpi9` | `date_to_5d` | string | +| `csire-kpi9` | `correctness_5d` | number | +| `csire-kpi9` | `date_from_1m` | string | +| `csire-kpi9` | `date_to_1m` | string | +| `csire-kpi9` | `correctness_1m` | number | +| `csire-kpi9` | `date_from_6m` | string | +| `csire-kpi9` | `date_to_6m` | string | +| `csire-kpi9` | `correctness_6m` | number | +| `csire-kpi10` | `row_no` | string | +| `csire-kpi10` | `eic_code` | string | +| `csire-kpi10` | `tax_id` | string | +| `csire-kpi10` | `name` | string | +| `csire-kpi10` | `date_from_1m` | string | +| `csire-kpi10` | `date_to_1m` | string | +| `csire-kpi10` | `timeliness_1m` | number | +| `csire-kpi10` | `date_from_6m` | string | +| `csire-kpi10` | `date_to_6m` | string | +| `csire-kpi10` | `timeliness_6m` | number | +| `eb-rozl` | `eb_d_pp` | number | +| `eb-rozl` | `eb_w_pp` | number | +| `eb-rozl` | `eb_afrrg` | number | +| `eb-rozl` | `eb_afrrd` | number | +| `en-rozl` | `en_d` | number | +| `en-rozl` | `en_w` | number | +| `en-rozl` | `balance` | number | +| `energy-prices` | `cor_cost` | number | +| `energy-prices` | `ceb_pp_cost` | number | +| `energy-prices` | `ceb_sr_cost` | number | +| `energy-prices` | `cen_cost` | number | +| `energy-prices` | `csdac_pln` | number | +| `energy-prices` | `sk_cost` | number | +| `energy-prices` | `balance` | number | +| `energy-prices` | `balance_power` | number | +| `energy-prices` | `sk_cost_power` | number | +| `gen-jw` | `resource_code` | string | +| `gen-jw` | `power_plant` | string | +| `gen-jw` | `operating_mode` | string | +| `gen-jw` | `operating_mode_eng` | string | +| `gen-jw` | `value` | number | +| `his-bil-mocy` | `peak` | string | +| `his-bil-mocy` | `peak_hour` | string | +| `his-bil-mocy` | `demand` | number | +| `his-bil-mocy` | `swm` | number | +| `his-bil-mocy` | `pos_jg` | number | +| `his-bil-mocy` | `pos_prb` | number | +| `his-bil-mocy` | `pos_sum` | number | +| `his-bil-mocy` | `rk_jg` | number | +| `his-bil-mocy` | `rk_prb` | number | +| `his-bil-mocy` | `rs_jg` | number | +| `his-bil-mocy` | `rs_prb` | number | +| `his-bil-mocy` | `rb_jg` | number | +| `his-bil-mocy` | `rb_prb` | number | +| `his-bil-mocy` | `ra_jg` | number | +| `his-bil-mocy` | `ra_prb` | number | +| `his-bil-mocy` | `we_jg` | number | +| `his-bil-mocy` | `we_prb` | number | +| `his-bil-mocy` | `ciep_jg` | number | +| `his-bil-mocy` | `ciep_prb` | number | +| `his-bil-mocy` | `inw_jg` | number | +| `his-bil-mocy` | `inw_prb` | number | +| `his-bil-mocy` | `pdysp_jg` | number | +| `his-bil-mocy` | `pdysp_prb` | number | +| `his-bil-mocy` | `sub` | number | +| `his-bil-mocy` | `sub_jg` | number | +| `his-bil-mocy` | `sub_prb` | number | +| `his-bil-mocy` | `rez` | number | +| `his-bil-mocy` | `rez_jg` | number | +| `his-bil-mocy` | `rez_jgw` | number | +| `his-bil-mocy` | `rez_jgw_wir` | number | +| `his-bil-mocy` | `rez_jgw_zim` | number | +| `his-bil-mocy` | `rez_jgm` | number | +| `his-bil-mocy` | `rez_jgz` | number | +| `his-bil-mocy` | `rez_jga` | number | +| `his-bil-mocy` | `rez_prb` | number | +| `his-bil-mocy` | `obc_sum` | number | +| `his-bil-mocy` | `obc_jg` | number | +| `his-bil-mocy` | `obc_prb` | number | +| `his-bil-mocy` | `ub_sum` | number | +| `his-bil-mocy` | `pdysp_sum` | number | +| `his-gen-pal` | `date` | string | +| `his-gen-pal` | `alias_entsoe` | string | +| `his-gen-pal` | `value` | string | +| `his-gen-pal-sire` | `date` | string | +| `his-gen-pal-sire` | `alias_entsoe` | string | +| `his-gen-pal-sire` | `value` | string | +| `his-gen-pal-sire` | `alias_sire` | string | +| `his-wlk-cal` | `demand` | number | +| `his-wlk-cal` | `swm_p` | number | +| `his-wlk-cal` | `swm_np` | number | +| `his-wlk-cal` | `jg` | number | +| `his-wlk-cal` | `jgo` | string | +| `his-wlk-cal` | `jgw1` | number | +| `his-wlk-cal` | `jgw2` | number | +| `his-wlk-cal` | `jgm1` | number | +| `his-wlk-cal` | `jgm2` | number | +| `his-wlk-cal` | `jgz1` | number | +| `his-wlk-cal` | `jgz2` | number | +| `his-wlk-cal` | `jgz3` | number | +| `his-wlk-cal` | `jga` | number | +| `his-wlk-cal` | `jnwrb` | number | +| `his-wlk-cal` | `jgm` | number | +| `his-wlk-cal` | `wi` | number | +| `his-wlk-cal` | `pv` | number | +| `it-oeb-rbb` | `iteration_no` | integer | +| `it-oeb-rbb` | `time_iteration_from_ts` | string | +| `it-oeb-rbb` | `time_iteration_from_ts_utc` | string | +| `it-oeb-rbb` | `time_iteration_to_ts` | string | +| `it-oeb-rbb` | `time_iteration_to_ts_utc` | string | +| `it-oeb-rbb` | `last_doc_dtime` | string | +| `it-oeb-rbb` | `last_doc_dtime_utc` | string | +| `it-oeb-rbb` | `time_period_from_dtime` | string | +| `it-oeb-rbb` | `time_period_from_dtime_utc` | string | +| `it-oeb-rbb` | `time_period_to_dtime` | string | +| `it-oeb-rbb` | `time_period_to_dtime_utc` | string | +| `it-oeb-rbn` | `iteration_no` | integer | +| `it-oeb-rbn` | `iteration_type` | string | +| `it-oeb-rbn` | `time_iteration_from_ts` | string | +| `it-oeb-rbn` | `time_iteration_from_ts_utc` | string | +| `it-oeb-rbn` | `time_iteration_to_ts` | string | +| `it-oeb-rbn` | `time_iteration_to_ts_utc` | string | +| `it-oeb-rbn` | `last_doc_dtime` | string | +| `it-oeb-rbn` | `last_doc_dtime_utc` | string | +| `it-omb-rbb` | `iteration_no` | integer | +| `it-omb-rbb` | `time_iteration_from_ts` | string | +| `it-omb-rbb` | `time_iteration_from_ts_utc` | string | +| `it-omb-rbb` | `time_iteration_to_ts` | string | +| `it-omb-rbb` | `time_iteration_to_ts_utc` | string | +| `it-omb-rbb` | `last_doc_dtime` | string | +| `it-omb-rbb` | `last_doc_dtime_utc` | string | +| `it-omb-rbb` | `time_period_from_dtime` | string | +| `it-omb-rbb` | `time_period_from_dtime_utc` | string | +| `it-omb-rbb` | `time_period_to_dtime` | string | +| `it-omb-rbb` | `time_period_to_dtime_utc` | string | +| `it-omb-rbn` | `iteration_no` | integer | +| `it-omb-rbn` | `iteration_type` | string | +| `it-omb-rbn` | `time_iteration_from_ts` | string | +| `it-omb-rbn` | `time_iteration_from_ts_utc` | string | +| `it-omb-rbn` | `time_iteration_to_ts` | string | +| `it-omb-rbn` | `time_iteration_to_ts_utc` | string | +| `it-omb-rbn` | `last_doc_dtime` | string | +| `it-omb-rbn` | `last_doc_dtime_utc` | string | +| `it-opmb-rmb` | `iteration_no` | integer | +| `it-opmb-rmb` | `iteration_type` | string | +| `it-opmb-rmb` | `time_iteration_from_ts` | string | +| `it-opmb-rmb` | `time_iteration_from_ts_utc` | string | +| `it-opmb-rmb` | `time_iteration_to_ts` | string | +| `it-opmb-rmb` | `time_iteration_to_ts_utc` | string | +| `it-opmb-rmb` | `last_doc_dtime` | string | +| `it-opmb-rmb` | `last_doc_dtime_utc` | string | +| `it-ot-rbn` | `iteration_no` | integer | +| `it-ot-rbn` | `iteration_type` | string | +| `it-ot-rbn` | `time_iteration_from_ts` | string | +| `it-ot-rbn` | `time_iteration_from_ts_utc` | string | +| `it-ot-rbn` | `time_iteration_to_ts` | string | +| `it-ot-rbn` | `time_iteration_to_ts_utc` | string | +| `it-ot-rbn` | `last_doc_dtime` | string | +| `it-ot-rbn` | `last_doc_dtime_utc` | string | +| `it-pp-rbb` | `iteration_no` | integer | +| `it-pp-rbb` | `time_iteration_from_ts` | string | +| `it-pp-rbb` | `time_iteration_from_ts_utc` | string | +| `it-pp-rbb` | `time_iteration_to_ts` | string | +| `it-pp-rbb` | `time_iteration_to_ts_utc` | string | +| `it-pp-rbb` | `last_doc_dtime` | string | +| `it-pp-rbb` | `last_doc_dtime_utc` | string | +| `it-pp-rbb` | `time_period_from_dtime` | string | +| `it-pp-rbb` | `time_period_from_dtime_utc` | string | +| `it-pp-rbb` | `time_period_to_dtime` | string | +| `it-pp-rbb` | `time_period_to_dtime_utc` | string | +| `it-pp-rbn` | `iteration_no` | integer | +| `it-pp-rbn` | `iteration_type` | string | +| `it-pp-rbn` | `time_iteration_from_ts` | string | +| `it-pp-rbn` | `time_iteration_from_ts_utc` | string | +| `it-pp-rbn` | `time_iteration_to_ts` | string | +| `it-pp-rbn` | `time_iteration_to_ts_utc` | string | +| `it-pp-rbn` | `last_doc_dtime` | string | +| `it-pp-rbn` | `last_doc_dtime_utc` | string | +| `it-use-rbb` | `iteration_no` | integer | +| `it-use-rbb` | `time_iteration_from_ts` | string | +| `it-use-rbb` | `time_iteration_from_ts_utc` | string | +| `it-use-rbb` | `time_iteration_to_ts` | string | +| `it-use-rbb` | `time_iteration_to_ts_utc` | string | +| `it-use-rbb` | `last_doc_dtime` | string | +| `it-use-rbb` | `last_doc_dtime_utc` | string | +| `it-use-rbb` | `time_period_from_dtime` | string | +| `it-use-rbb` | `time_period_from_dtime_utc` | string | +| `it-use-rbb` | `time_period_to_dtime` | string | +| `it-use-rbb` | `time_period_to_dtime_utc` | string | +| `it-use-rbb` | `volume` | number | +| `it-use-rbn` | `iteration_no` | integer | +| `it-use-rbn` | `iteration_type` | string | +| `it-use-rbn` | `time_iteration_from_ts` | string | +| `it-use-rbn` | `time_iteration_from_ts_utc` | string | +| `it-use-rbn` | `time_iteration_to_ts` | string | +| `it-use-rbn` | `time_iteration_to_ts_utc` | string | +| `it-use-rbn` | `last_doc_dtime` | string | +| `it-use-rbn` | `last_doc_dtime_utc` | string | +| `kmb-kro-rozl` | `kmb` | number | +| `kmb-kro-rozl` | `kro` | number | +| `krb-rozl` | `kcz` | number | +| `krb-rozl` | `kb` | number | +| `krb-rozl` | `ko` | number | +| `kse-load` | `load_actual` | number | +| `kse-load` | `load_fcst` | number | +| `lolp` | `ojnz_id` | string | +| `lolp` | `b0` | number | +| `lolp` | `b1` | number | +| `lolp` | `b2` | number | +| `lolp` | `b3` | number | +| `lolp` | `b4` | number | +| `lolp` | `b5` | number | +| `lolp` | `b6` | number | +| `lolp` | `b7` | number | +| `lolp` | `b8` | number | +| `lolp` | `b9` | number | +| `lolp` | `p0` | number | +| `lolp` | `p1` | number | +| `lolp` | `p2` | number | +| `lolp` | `p3` | number | +| `lolp` | `p4` | number | +| `lolp` | `p5` | number | +| `lolp` | `p6` | number | +| `lolp` | `p7` | number | +| `lolp` | `p8` | number | +| `lolp` | `p9` | number | +| `mbp-tp` | `onmbp` | string | +| `mbp-tp` | `fcr_g` | number | +| `mbp-tp` | `fcr_d` | number | +| `mbp-tp` | `afrr_g` | number | +| `mbp-tp` | `afrr_d` | number | +| `mbp-tp` | `mfrrd_g` | number | +| `mbp-tp` | `mfrrd_d` | number | +| `mbp-tp` | `rr_g` | number | +| `mbp-tp` | `rr_d` | number | +| `mbu-tu` | `fcr_g` | number | +| `mbu-tu` | `fcr_d` | number | +| `mbu-tu` | `afrr_g` | number | +| `mbu-tu` | `afrr_d` | number | +| `mbu-tu` | `mfrrd_g` | number | +| `mbu-tu` | `mfrrd_d` | number | +| `oeb-bpkdbo` | `ofp` | number | +| `oeb-bpkdbo` | `ofc` | number | +| `oeb-bpkdbo` | `cdo` | number | +| `oeb-bpkdbo` | `activ_direction` | string | +| `oeb-bpkdbo` | `sort` | integer | +| `ogr-b` | `node` | string | +| `ogr-b` | `resource_name` | string | +| `ogr-b` | `resource_code` | string | +| `ogr-b` | `direction` | string | +| `ogr-b` | `pol_min_power_of_unit` | number | +| `ogr-b` | `pol_min_power_of_unit_plant` | integer | +| `ogr-b` | `pol_max_power_of_unit_plant` | number | +| `ogr-b` | `pol_max_power_of_unit` | integer | +| `ogr-b` | `from_dtime` | string | +| `ogr-b` | `from_dtime_utc` | string | +| `ogr-b` | `to_dtime` | string | +| `ogr-b` | `to_dtime_utc` | string | +| `ogr-b` | `time_conditions` | string | +| `ogr-b` | `limiting_element` | string | +| `ogr-b` | `add_cond` | string | +| `ogr-b` | `year` | number | +| `ogr-b` | `month` | number | +| `ogr-b` | `is_active` | boolean | +| `ogr-b` | `valid_from_ts_utc` | string | +| `ogr-b` | `valid_to_ts_utc` | string | +| `ogr-b` | `version` | string | +| `ogr-b-head` | `title` | string | +| `ogr-b-head` | `remarks` | string | +| `ogr-b-head` | `version` | string | +| `ogr-b-head` | `is_active` | boolean | +| `ogr-d1` | `node` | string | +| `ogr-d1` | `resource_name` | string | +| `ogr-d1` | `resource_code` | string | +| `ogr-d1` | `direction` | string | +| `ogr-d1` | `pol_min_power_of_unit` | number | +| `ogr-d1` | `pol_min_power_of_unit_plant` | integer | +| `ogr-d1` | `pol_max_power_of_unit_plant` | number | +| `ogr-d1` | `pol_max_power_of_unit` | integer | +| `ogr-d1` | `from_dtime` | string | +| `ogr-d1` | `from_dtime_utc` | string | +| `ogr-d1` | `to_dtime` | string | +| `ogr-d1` | `to_dtime_utc` | string | +| `ogr-d1` | `time_conditions` | string | +| `ogr-d1` | `limiting_element` | string | +| `ogr-d1` | `add_cond` | string | +| `ogr-d1-head` | `title` | string | +| `ogr-d1-head` | `remarks` | string | +| `ogr-d2` | `node` | string | +| `ogr-d2` | `resource_name` | string | +| `ogr-d2` | `resource_code` | string | +| `ogr-d2` | `direction` | string | +| `ogr-d2` | `pol_min_power_of_unit` | number | +| `ogr-d2` | `pol_min_power_of_unit_plant` | integer | +| `ogr-d2` | `pol_max_power_of_unit_plant` | number | +| `ogr-d2` | `pol_max_power_of_unit` | integer | +| `ogr-d2` | `from_dtime` | string | +| `ogr-d2` | `from_dtime_utc` | string | +| `ogr-d2` | `to_dtime` | string | +| `ogr-d2` | `to_dtime_utc` | string | +| `ogr-d2` | `time_conditions` | string | +| `ogr-d2` | `limiting_element` | string | +| `ogr-d2` | `add_cond` | string | +| `ogr-d2-head` | `title` | string | +| `ogr-d2-head` | `remarks` | string | +| `ogr-d39` | `node` | string | +| `ogr-d39` | `resource_name` | string | +| `ogr-d39` | `resource_code` | string | +| `ogr-d39` | `direction` | string | +| `ogr-d39` | `pol_min_power_of_unit` | number | +| `ogr-d39` | `pol_min_power_of_unit_plant` | integer | +| `ogr-d39` | `pol_max_power_of_unit_plant` | number | +| `ogr-d39` | `pol_max_power_of_unit` | integer | +| `ogr-d39` | `from_dtime` | string | +| `ogr-d39` | `from_dtime_utc` | string | +| `ogr-d39` | `to_dtime` | string | +| `ogr-d39` | `to_dtime_utc` | string | +| `ogr-d39` | `time_conditions` | string | +| `ogr-d39` | `limiting_element` | string | +| `ogr-d39` | `add_cond` | string | +| `ogr-d39-head` | `title` | string | +| `ogr-d39-head` | `from_period` | string | +| `ogr-d39-head` | `to_period` | string | +| `ogr-d39-head` | `remarks` | string | +| `ogr-m` | `node` | string | +| `ogr-m` | `resource_name` | string | +| `ogr-m` | `resource_code` | string | +| `ogr-m` | `direction` | string | +| `ogr-m` | `pol_min_power_of_unit` | number | +| `ogr-m` | `pol_min_power_of_unit_plant` | integer | +| `ogr-m` | `pol_max_power_of_unit_plant` | number | +| `ogr-m` | `pol_max_power_of_unit` | integer | +| `ogr-m` | `from_dtime` | string | +| `ogr-m` | `from_dtime_utc` | string | +| `ogr-m` | `to_dtime` | string | +| `ogr-m` | `to_dtime_utc` | string | +| `ogr-m` | `time_conditions` | string | +| `ogr-m` | `limiting_element` | string | +| `ogr-m` | `add_cond` | string | +| `ogr-m-head` | `title` | string | +| `ogr-m-head` | `from_period` | string | +| `ogr-m-head` | `to_period` | string | +| `ogr-m-head` | `remarks` | string | +| `ogr-oper` | `node` | string | +| `ogr-oper` | `resource_name` | string | +| `ogr-oper` | `resource_code` | string | +| `ogr-oper` | `direction` | string | +| `ogr-oper` | `pol_min_power_of_unit` | number | +| `ogr-oper` | `pol_min_power_of_unit_plant` | integer | +| `ogr-oper` | `pol_max_power_of_unit_plant` | number | +| `ogr-oper` | `pol_max_power_of_unit` | integer | +| `ogr-oper` | `from_dtime` | string | +| `ogr-oper` | `from_dtime_utc` | string | +| `ogr-oper` | `to_dtime` | string | +| `ogr-oper` | `to_dtime_utc` | string | +| `ogr-oper` | `time_conditions` | string | +| `ogr-oper` | `limiting_element` | string | +| `ogr-oper` | `add_cond` | string | +| `ogr-oper-head` | `title` | string | +| `ogr-oper-head` | `remarks` | string | +| `ogr-r` | `node` | string | +| `ogr-r` | `resource_name` | string | +| `ogr-r` | `resource_code` | string | +| `ogr-r` | `direction` | string | +| `ogr-r` | `pol_min_power_of_unit` | number | +| `ogr-r` | `pol_min_power_of_unit_plant` | integer | +| `ogr-r` | `pol_max_power_of_unit_plant` | number | +| `ogr-r` | `pol_max_power_of_unit` | integer | +| `ogr-r` | `from_dtime` | string | +| `ogr-r` | `from_dtime_utc` | string | +| `ogr-r` | `to_dtime` | string | +| `ogr-r` | `to_dtime_utc` | string | +| `ogr-r` | `time_conditions` | string | +| `ogr-r` | `limiting_element` | string | +| `ogr-r` | `add_cond` | string | +| `ogr-r` | `year` | number | +| `ogr-r` | `month` | number | +| `ogr-r-head` | `title` | string | +| `ogr-r-head` | `from_period` | string | +| `ogr-r-head` | `to_period` | string | +| `ogr-r-head` | `remarks` | string | +| `ogr-rmb` | `id` | integer | +| `ogr-rmb` | `node` | string | +| `ogr-rmb` | `from_dtime` | string | +| `ogr-rmb` | `from_dtime_utc` | string | +| `ogr-rmb` | `to_dtime` | string | +| `ogr-rmb` | `to_dtime_utc` | string | +| `ogr-rmb` | `unit_name` | string | +| `ogr-rmb` | `direction` | string | +| `ogr-rmb` | `sminp` | integer | +| `ogr-rmb` | `smaxp` | integer | +| `ogr-rmb` | `smaxp_sminp` | integer | +| `pdgobpkd` | `kse_pow_dem` | number | +| `pdgobpkd` | `capacity_jgw_jgm_jgz_jga` | number | +| `pdgobpkd` | `capacity_jgw_zak_1` | number | +| `pdgobpkd` | `capacity_jgw_zak_2` | number | +| `pdgobpkd` | `capacity_jgm_zak_1` | number | +| `pdgobpkd` | `capacity_jgm_zak_2` | number | +| `pdgobpkd` | `capacity_jgz_zak_1` | number | +| `pdgobpkd` | `capacity_jgz_zak_2` | number | +| `pdgobpkd` | `capacity_jgz_zak_3` | number | +| `pdgobpkd` | `capacity_jga` | number | +| `pdgobpkd` | `capacity_jgo` | number | +| `pdgobpkd` | `gen_jgw_jgm_jgz_jga` | number | +| `pdgobpkd` | `gen_jgw_zak_1` | number | +| `pdgobpkd` | `gen_jgw_zak_2` | number | +| `pdgobpkd` | `gen_jgm_zak_1` | number | +| `pdgobpkd` | `gen_jgm_zak_2` | number | +| `pdgobpkd` | `gen_jgz_zak_1` | number | +| `pdgobpkd` | `gen_jgz_zak_2` | number | +| `pdgobpkd` | `gen_jgz_zak_3` | number | +| `pdgobpkd` | `gen_jga` | number | +| `pdgobpkd` | `gen_jgo` | number | +| `pdgobpkd` | `gen_not_activ_part` | number | +| `pdgobpkd` | `ogr_mwe` | number | +| `pdgobpkd` | `tot_jgm_char_pow` | number | +| `pdgobpkd` | `gen_wi` | number | +| `pdgobpkd` | `gen_fv` | number | +| `pdgobpkd` | `dom_balance_exchange_non_par` | number | +| `pdgobpkd` | `dom_balance_exchange_par` | number | +| `pdgobpkd` | `rez_over_demand` | number | +| `pdgobpkd` | `rez_under` | number | +| `pdgopkd` | `kse_pow_dem` | number | +| `pdgopkd` | `capacity_jgw_jgm_jgz_jga` | number | +| `pdgopkd` | `capacity_jgw_zak_1` | number | +| `pdgopkd` | `capacity_jgw_zak_2` | number | +| `pdgopkd` | `capacity_jgm_zak_1` | number | +| `pdgopkd` | `capacity_jgm_zak_2` | number | +| `pdgopkd` | `capacity_jgz_zak_1` | number | +| `pdgopkd` | `capacity_jgz_zak_2` | number | +| `pdgopkd` | `capacity_jgz_zak_3` | number | +| `pdgopkd` | `capacity_jga` | number | +| `pdgopkd` | `capacity_jgo` | number | +| `pdgopkd` | `gen_jgw_jgm_jgz_jga` | number | +| `pdgopkd` | `gen_jgw_zak_1` | number | +| `pdgopkd` | `gen_jgw_zak_2` | number | +| `pdgopkd` | `gen_jgm_zak_1` | number | +| `pdgopkd` | `gen_jgm_zak_2` | number | +| `pdgopkd` | `gen_jgz_zak_1` | number | +| `pdgopkd` | `gen_jgz_zak_2` | number | +| `pdgopkd` | `gen_jgz_zak_3` | number | +| `pdgopkd` | `gen_jga` | number | +| `pdgopkd` | `gen_jgo` | number | +| `pdgopkd` | `gen_not_activ_part` | number | +| `pdgopkd` | `ogr_mwe` | number | +| `pdgopkd` | `tot_jgm_char_pow` | number | +| `pdgopkd` | `gen_wi` | number | +| `pdgopkd` | `gen_fv` | number | +| `pdgopkd` | `dom_balance_exchange_non_par` | number | +| `pdgopkd` | `dom_balance_exchange_par` | number | +| `pdgopkd` | `rez_over_demand` | number | +| `pdgopkd` | `rez_under` | number | +| `pdgsz` | `usage_fcst` | integer | +| `pdgsz` | `total_power_demand` | number | +| `pdgsz` | `is_active` | boolean | +| `pdgsz` | `valid_from_ts` | string | +| `pdgsz` | `valid_to_ts` | string | +| `pdwkseub` | `power_plant` | string | +| `pdwkseub` | `resource_code` | string | +| `pdwkseub` | `non_us_cap` | number | +| `pdwkseub` | `grid_lim` | number | +| `pdwkseub` | `available_capacity` | number | +| `pk5l-wp` | `plan_dtime` | string | +| `pk5l-wp` | `plan_dtime_utc` | string | +| `pk5l-wp` | `grid_demand_fcst` | number | +| `pk5l-wp` | `req_pow_res` | number | +| `pk5l-wp` | `surplus_cap_avail_tso` | number | +| `pk5l-wp` | `gen_surplus_avail_tso_above` | number | +| `pk5l-wp` | `avail_cap_gen_units_stor_prov` | number | +| `pk5l-wp` | `avail_cap_gen_units_stor_prov_tso` | number | +| `pk5l-wp` | `fcst_gen_unit_stor_prov` | number | +| `pk5l-wp` | `fcst_gen_unit_stor_non_prov` | number | +| `pk5l-wp` | `fcst_wi_tot_gen` | number | +| `pk5l-wp` | `fcst_pv_tot_gen` | number | +| `pk5l-wp` | `planned_exchange` | number | +| `pk5l-wp` | `fcst_unav_energy` | number | +| `pk5l-wp` | `planned_restr_mwe_avail_shutdown` | number | +| `pk5l-wp` | `sum_unav_oper_cond` | number | +| `pk5l-wp` | `pred_gen_res_not_cov` | number | +| `pk5l-wp` | `cap_market_obligation` | number | +| `poeb-rbb` | `ofcg` | number | +| `poeb-rbb` | `ofcd` | number | +| `poeb-rbb` | `ofp` | number | +| `poeb-rbn` | `ofcg` | number | +| `poeb-rbn` | `ofcd` | number | +| `poeb-rbn` | `ofp` | number | +| `pomb-rbn` | `reserve_type` | string | +| `pomb-rbn` | `pofmin` | number | +| `pomb-rbn` | `pofmax` | number | +| `pomb-rbn` | `plofmin` | number | +| `pomb-rbn` | `plofmax` | number | +| `pomb-rbn` | `ofc` | number | +| `popmb-rmb` | `onmbp` | string | +| `popmb-rmb` | `reserve_type` | string | +| `popmb-rmb` | `pom` | number | +| `popmb-rmb` | `com` | number | +| `popmb-rmb` | `comrr` | number | +| `poze-redoze` | `pv_red_balance` | number | +| `poze-redoze` | `wi_red_balance` | number | +| `poze-redoze` | `pv_red_network` | number | +| `poze-redoze` | `wi_red_network` | number | +| `price-cost` | `cen_cost` | number | +| `price-cost` | `ckoeb_cost` | number | +| `price-cost` | `ceb_sr_cost` | number | +| `price-cost` | `cor_pp_cost` | number | +| `price-cost` | `imb_energy` | number | +| `price-cost` | `contracting` | string | +| `price-fcst` | `cen_fcst` | number | +| `price-fcst` | `ckoeb_fcst` | number | +| `price-fcst` | `ceb_sr_fcst` | number | +| `price-fcst` | `cor_fcst` | number | +| `price-fcst` | `imb_energy` | number | +| `price-fcst` | `contracting` | string | +| `przeplywy-mocy` | `section_code` | string | +| `przeplywy-mocy` | `value` | number | +| `pwm-dost-op` | `pl_cz` | number | +| `pwm-dost-op` | `cz_pl` | number | +| `pwm-dost-op` | `pl_sk` | number | +| `pwm-dost-op` | `sk_pl` | number | +| `pwm-dost-op` | `pl_de` | number | +| `pwm-dost-op` | `de_pl` | number | +| `pwm-dost-op` | `pl_se` | number | +| `pwm-dost-op` | `se_pl` | number | +| `pwm-dost-op` | `pl_ua` | number | +| `pwm-dost-op` | `ua_pl` | number | +| `pwm-dost-op` | `pl_lt` | number | +| `pwm-dost-op` | `lt_pl` | number | +| `pwm-dost-op` | `saldo` | number | +| `pwm-igcc-in` | `energy_afrr_exp` | number | +| `pwm-igcc-in` | `energy_afrr_imp` | number | +| `pwm-igcc-in` | `afrr_exp_pln` | number | +| `pwm-igcc-in` | `afrr_imp_pln` | number | +| `pwm-igcc-in` | `afrr_exp_eur` | number | +| `pwm-igcc-in` | `afrr_imp_eur` | number | +| `pwm-rdb` | `pl_cz` | number | +| `pwm-rdb` | `cz_pl` | number | +| `pwm-rdb` | `pl_sk` | number | +| `pwm-rdb` | `sk_pl` | number | +| `pwm-rdb` | `pl_de` | number | +| `pwm-rdb` | `de_pl` | number | +| `pwm-rdb` | `pl_se` | number | +| `pwm-rdb` | `se_pl` | number | +| `pwm-rdb` | `pl_ua` | number | +| `pwm-rdb` | `ua_pl` | number | +| `pwm-rdb` | `pl_lt` | number | +| `pwm-rdb` | `lt_pl` | number | +| `pwm-rdn` | `pl_cz` | number | +| `pwm-rdn` | `cz_pl` | number | +| `pwm-rdn` | `pl_sk` | number | +| `pwm-rdn` | `sk_pl` | number | +| `pwm-rdn` | `pl_de` | number | +| `pwm-rdn` | `de_pl` | number | +| `pwm-rdn` | `pl_se` | number | +| `pwm-rdn` | `se_pl` | number | +| `pwm-rdn` | `pl_ua_dob` | number | +| `pwm-rdn` | `ua_dob_pl` | number | +| `pwm-rdn` | `pl_ua` | number | +| `pwm-rdn` | `ua_pl` | number | +| `pwm-rdn` | `pl_lt` | number | +| `pwm-rdn` | `lt_pl` | number | +| `pwm-rdn-rdb` | `pl_cz` | number | +| `pwm-rdn-rdb` | `cz_pl` | number | +| `pwm-rdn-rdb` | `pl_sk` | number | +| `pwm-rdn-rdb` | `sk_pl` | number | +| `pwm-rdn-rdb` | `pl_de` | number | +| `pwm-rdn-rdb` | `de_pl` | number | +| `pwm-rdn-rdb` | `pl_se` | number | +| `pwm-rdn-rdb` | `se_pl` | number | +| `pwm-rdn-rdb` | `pl_ua_dob` | number | +| `pwm-rdn-rdb` | `ua_dob_pl` | number | +| `pwm-rdn-rdb` | `pl_ua` | number | +| `pwm-rdn-rdb` | `ua_pl` | number | +| `pwm-rdn-rdb` | `pl_lt` | number | +| `pwm-rdn-rdb` | `lt_pl` | number | +| `rcco2` | `rcco2_pln` | number | +| `rcco2` | `rcco2_eur` | number | +| `rce-pln` | `rce_pln` | number | +| `ro-prog` | `ro_fcst` | number | +| `ro-rozl` | `ro_cost` | number | +| `sk` | `sk_d1_fcst` | number | +| `sk` | `sk_d_fcst` | number | +| `sk` | `sk_cost` | number | +| `specwezlow` | `regional_dispatch_center` | string | +| `specwezlow` | `dso_branch` | string | +| `specwezlow` | `station_name` | string | +| `specwezlow` | `switching_station_code` | string | +| `specwezlow` | `switching_station_voltage` | string | +| `specwezlow` | `busbar_code` | string | +| `specwezlow` | `busbar_name` | string | +| `unav-pk5l` | `power_plant` | string | +| `unav-pk5l` | `type` | string | +| `unav-pk5l` | `state` | string | +| `unav-pk5l` | `unit_code` | string | +| `unav-pk5l` | `reason` | string | +| `unav-pk5l` | `start_dtime` | string | +| `unav-pk5l` | `start_dtime_utc` | string | +| `unav-pk5l` | `end_dtime` | string | +| `unav-pk5l` | `end_dtime_utc` | string | +| `unav-pk5l` | `direction` | string | +| `unav-pk5l` | `mrid_zas` | string | +| `unav-pk5l` | `snd_dtime` | string | +| `unav-pk5l` | `snd_dtime_utc` | string | +| `use-sprz-rbb` | `sprz_volume` | number | +| `use-sprz-rbn` | `day_ahead_tr_vol` | number | +| `wmb` | `fcrg` | integer | +| `wmb` | `fcrd` | integer | +| `wmb` | `frrg` | integer | +| `wmb` | `frrd` | integer | +| `wmb` | `afrrg` | integer | +| `wmb` | `afrrd` | integer | +| `wmb` | `rrg` | integer | +| `wmb` | `rrd` | integer | +| `wsp-wrm` | `az` | number | +| `wsp-wrm` | `afw` | number | +| `wsp-wrm` | `apv` | number | +| `wsp-wrm` | `ws` | number | +| `wsp-wrm` | `wmb_max` | number | +| `wsp-wrm` | `ojnz_id` | string | +| `zeb-rozl` | `zebpp` | number | +| `zeb-rozl` | `pzeb_afrrg_cost` | number | +| `zeb-rozl` | `pzeb_afrrd_cost` | number | +| `zmb` | `zmb_fcrg` | number | +| `zmb` | `zmb_fcrd` | number | +| `zmb` | `zmb_frrg` | number | +| `zmb` | `zmb_frrd` | number | +| `zmb` | `zmb_afrrg` | number | +| `zmb` | `zmb_afrrd` | number | +| `zmb` | `zmb_rrg` | number | +| `zmb` | `zmb_rrd` | number | -> API reference: `https://api.raporty.pse.pl/api/openapi` +## Date and key columns -| Endpoint | Description | Column | Method | Status | -|---|---|---|---|---| -| `price-cost` | CEN price | `cen_cost` | `get_cen()` | ![stable](https://img.shields.io/badge/stable-brightgreen) | -| `price-cost` | CKOEB price | `ckoeb_cost` | `get_ckoeb()` | ![stable](https://img.shields.io/badge/stable-brightgreen) | -| `price-cost` | CEBśr price | `ceb_sr_cost` | `get_ceb_sr()` | ![stable](https://img.shields.io/badge/stable-brightgreen) | -| `price-cost` | Operating reserve price (COR) | `cor_pp_cost` | `get_cor_pp()` | ![stable](https://img.shields.io/badge/stable-brightgreen) | -| `price-cost` | Imbalance energy | `imb_energy` | `get_imb_energy()` | ![stable](https://img.shields.io/badge/stable-brightgreen) | -| `price-cost` | KSE contracting status (`short` if < 0, else `long`) | `contracting` | `get_contracting()` | ![stable](https://img.shields.io/badge/stable-brightgreen) | -| `csdac-pln` | SDAC price (PLN) | `csdac_pln` | `get_csdac()` | ![stable](https://img.shields.io/badge/stable-brightgreen) | -| `his-wlk-cal` | KSE power demand | `demand` | `get_demand()` | ![stable](https://img.shields.io/badge/stable-brightgreen) | -| `his-wlk-cal` | National cross-border exchange balance (parallel) | `swm_p` | `get_swm_p()` | ![stable](https://img.shields.io/badge/stable-brightgreen) | -| `his-wlk-cal` | National cross-border exchange balance (non-parallel) | `swm_np` | `get_swm_np()` | ![stable](https://img.shields.io/badge/stable-brightgreen) | -| `his-wlk-cal` | Total generation of scheduling units in KSE (JGw, JGm, JGz, JGa) | `jg` | `get_jg()` | ![stable](https://img.shields.io/badge/stable-brightgreen) | -| `his-wlk-cal` | Total generation of generating scheduling units JGw (ZAK=1) | `jgw1` | `get_jgw1()` | ![stable](https://img.shields.io/badge/stable-brightgreen) | -| `his-wlk-cal` | Total generation of generating scheduling units JGw (ZAK=2) | `jgw2` | `get_jgw2()` | ![stable](https://img.shields.io/badge/stable-brightgreen) | -| `his-wlk-cal` | Total generation of energy storage scheduling units JGm (ZAK=1) | `jgm1` | `get_jgm1()` | ![stable](https://img.shields.io/badge/stable-brightgreen) | -| `his-wlk-cal` | Total generation of energy storage scheduling units JGm (ZAK=2) | `jgm2` | `get_jgm2()` | ![stable](https://img.shields.io/badge/stable-brightgreen) | -| `his-wlk-cal` | Total generation of wind and PV scheduling units JGz (ZAK=1) | `jgz1` | `get_jgz1()` | ![stable](https://img.shields.io/badge/stable-brightgreen) | -| `his-wlk-cal` | Total generation of wind and PV scheduling units JGz (ZAK=2) | `jgz2` | `get_jgz2()` | ![stable](https://img.shields.io/badge/stable-brightgreen) | -| `his-wlk-cal` | Total generation of wind and PV scheduling units JGz (ZAK=3) | `jgz3` | `get_jgz3()` | ![stable](https://img.shields.io/badge/stable-brightgreen) | -| `his-wlk-cal` | Total generation of aggregator scheduling units (JGa) | `jga` | `get_jga()` | ![stable](https://img.shields.io/badge/stable-brightgreen) | -| `his-wlk-cal` | Total consumption of receiving scheduling units (JGo) | `jgo` | `get_jgo()` | ![stable](https://img.shields.io/badge/stable-brightgreen) | -| `his-wlk-cal` | Total generation of units not actively participating in balancing market | `jnwrb` | `get_jnwrb()` | ![stable](https://img.shields.io/badge/stable-brightgreen) | -| `his-wlk-cal` | Total JGm charging power | `jgm` | `get_jgm()` | ![stable](https://img.shields.io/badge/stable-brightgreen) | -| `his-wlk-cal` | Total wind generation | `wi` | `get_wi()` | ![stable](https://img.shields.io/badge/stable-brightgreen) | -| `his-wlk-cal` | Total photovoltaic generation | `pv` | `get_pv()` | ![stable](https://img.shields.io/badge/stable-brightgreen) | -| `kmb-kro-rozl` | Balancing capacity cost (KMB) | `kmb` | `get_kmb()` | ![stable](https://img.shields.io/badge/stable-brightgreen) | -| `kmb-kro-rozl` | Operating reserve cost (KRO) | `kro` | `get_kro()` | ![stable](https://img.shields.io/badge/stable-brightgreen) | -| `krb-rozl` | KB cost | `kb` | `get_kb()` | ![stable](https://img.shields.io/badge/stable-brightgreen) | -| `krb-rozl` | KO cost | `ko` | `get_ko()` | ![stable](https://img.shields.io/badge/stable-brightgreen) | -| `krb-rozl` | KCZ cost | `kcz` | `get_kcz()` | ![stable](https://img.shields.io/badge/stable-brightgreen) | -| `sk` | Forecasted KSE contracting status determined on day d-1 | `sk_d1_fcst` | `get_sk_d1_fcst()` | ![stable](https://img.shields.io/badge/stable-brightgreen) | -| `sk` | Forecasted KSE contracting status determined on day d | `sk_d_fcst` | `get_sk_d_fcst()` | ![stable](https://img.shields.io/badge/stable-brightgreen) | -| `sk` | KSE contracting status | `sk_cost` | `get_sk_cost()` | ![stable](https://img.shields.io/badge/stable-brightgreen) | -| `afrr-status` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `cmbp-tp` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `cmbu-tu` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `codn` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `cor` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `cor-q-1` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `cordmax` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `crb-rozl` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `csire-kpi1` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `csire-kpi2` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `csire-kpi3` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `csire-kpi4` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `csire-kpi5` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `csire-kpi6` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `csire-kpi7` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `csire-kpi8` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `csire-kpi9` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `csire-kpi10` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `eb-rozl` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `en-rozl` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `energy-prices` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `gen-jw` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `his-bil-mocy` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `his-gen-pal` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `it-oeb-rbb` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `it-oeb-rbn` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `it-omb-rbb` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `it-omb-rbn` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `it-opmb-rmb` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `it-ot-rbn` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `it-pp-rbb` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `it-pp-rbn` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `it-use-rbb` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `it-use-rbn` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `kse-load` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `lolp` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `mbp-tp` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `mbu-tu` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `oeb-bpkdbo` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `ogr-b` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `ogr-b-head` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `ogr-d1` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `ogr-d1-head` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `ogr-d2` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `ogr-d2-head` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `ogr-d39` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `ogr-d39-head` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `ogr-m` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `ogr-m-head` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `ogr-oper` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `ogr-oper-head` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `ogr-r` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `ogr-r-head` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `ogr-rmb` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `pdgobpkd` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `pdgopkd` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `pdgsz` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `pdwkseub` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `pk5l-wp` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `poeb-rbb` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `poeb-rbn` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `pomb-rbn` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `popmb-rmb` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `poze-redoze` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `price-fcst` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `przeplywy-mocy` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `pwm-dost-op` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `pwm-igcc-in` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `pwm-rdb` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `pwm-rdn` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `pwm-rdn-rdb` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `rcco2` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `rce-pln` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `ro-prog` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `ro-rozl` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `specwezlow` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `unav-pk5l` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `use-sprz-rbb` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `use-sprz-rbn` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `wsp-wrm` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `zeb-rozl` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | -| `zmb` | | | | ![planned](https://img.shields.io/badge/planned-yellow) | +| Endpoint | Date column | Key columns | +|---|---|---| +| `afrr-status` | `business_date` | `event_time_utc`, `afrr_status`, `reason_code` | +| `cmbp-tp` | `business_date` | `dtime_utc` | +| `cmbu-tu` | `business_date` | `dtime_utc` | +| `codn` | `business_date` | `business_date`, `period_from_date`, `period_to_date` | +| `cor` | `business_date` | `dtime_utc` | +| `cor-q-1` | `business_date` | `business_date`, `period_to_date`, `period_from_date` | +| `cordmax` | `business_date` | `business_date`, `cordmax_fcst`, `cordmax_cost` | +| `crb-rozl` | `business_date` | `dtime_utc` | +| `csdac-pln` | `business_date` | `dtime_utc` | +| `csire-kpi1` | `business_date` | `business_date`, `row_no` | +| `csire-kpi2` | `business_date` | `business_date`, `row_no` | +| `csire-kpi3` | `business_date` | `business_date`, `row_no` | +| `csire-kpi4` | `business_date` | `business_date`, `row_no` | +| `csire-kpi5` | `business_date` | `business_date`, `row_no` | +| `csire-kpi6` | `business_date` | `business_date`, `row_no` | +| `csire-kpi7` | `business_date` | `business_date`, `row_no` | +| `csire-kpi8` | `business_date` | `business_date`, `row_no` | +| `csire-kpi9` | `business_date` | `business_date`, `row_no` | +| `csire-kpi10` | `business_date` | `business_date`, `row_no` | +| `eb-rozl` | `business_date` | `dtime_utc` | +| `en-rozl` | `business_date` | `dtime_utc` | +| `energy-prices` | `business_date` | `dtime_utc` | +| `gen-jw` | `business_date` | `dtime_utc`, `resource_code`, `operating_mode` | +| `his-bil-mocy` | `business_date` | `business_date`, `peak_hour`, `peak` | +| `his-gen-pal` | `business_date` | `business_date`, `dtime_utc`, `alias_entsoe` | +| `his-gen-pal-sire` | `business_date` | `business_date`, `dtime_utc`, `alias_sire`, `alias_entsoe` | +| `his-wlk-cal` | `business_date` | `dtime_utc` | +| `it-oeb-rbb` | `business_date` | `business_date`, `iteration_no` | +| `it-oeb-rbn` | `business_date` | `business_date`, `iteration_no` | +| `it-omb-rbb` | `business_date` | `business_date`, `iteration_no` | +| `it-omb-rbn` | `business_date` | `business_date`, `iteration_no` | +| `it-opmb-rmb` | `business_date` | `business_date`, `iteration_no` | +| `it-ot-rbn` | `business_date` | `business_date`, `iteration_no` | +| `it-pp-rbb` | `business_date` | `business_date`, `iteration_no` | +| `it-pp-rbn` | `business_date` | `business_date`, `iteration_no` | +| `it-use-rbb` | `business_date` | `business_date`, `iteration_no` | +| `it-use-rbn` | `business_date` | `business_date`, `iteration_no` | +| `kmb-kro-rozl` | `business_date` | `dtime_utc` | +| `krb-rozl` | `business_date` | `dtime_utc` | +| `kse-load` | `business_date` | `dtime_utc` | +| `lolp` | `business_date` | `business_date`, `dtime_utc` | +| `mbp-tp` | `business_date` | `dtime_utc` | +| `mbu-tu` | `business_date` | `dtime_utc` | +| `oeb-bpkdbo` | `business_date` | `dtime_utc`, `activ_direction`, `ofp`, `ofc`, `cdo` | +| `ogr-b` | `business_date` | `node`, `business_date`, `to_dtime_utc`, `from_dtime_utc`, `period` | +| `ogr-b-head` | `business_date` | `business_date` | +| `ogr-d1` | `business_date` | `node`, `business_date`, `to_dtime`, `from_dtime` | +| `ogr-d1-head` | `period` | `period` | +| `ogr-d2` | `business_date` | `node`, `business_date`, `to_dtime`, `from_dtime` | +| `ogr-d2-head` | `period` | `period` | +| `ogr-d39` | `business_date` | `node`, `business_date`, `to_dtime`, `from_dtime` | +| `ogr-d39-head` | `period` | `period` | +| `ogr-m` | `business_date` | `node`, `business_date`, `to_dtime`, `from_dtime` | +| `ogr-m-head` | `period` | `period` | +| `ogr-oper` | `business_date` | `node`, `business_date`, `to_dtime`, `from_dtime` | +| `ogr-oper-head` | `period` | `period` | +| `ogr-r` | `business_date` | `node`, `business_date`, `to_dtime`, `from_dtime`, `period` | +| `ogr-r-head` | `period` | `period` | +| `ogr-rmb` | `business_date` | `from_dtime`, `node` | +| `pdgobpkd` | `business_date` | `dtime_utc`, `business_date` | +| `pdgopkd` | `business_date` | `dtime_utc`, `business_date` | +| `pdgsz` | `business_date` | `dtime_utc`, `valid_from_ts`, `valid_to_ts` | +| `pdwkseub` | `business_date` | `dtime_utc`, `resource_code` | +| `pk5l-wp` | `business_date` | `plan_dtime_utc` | +| `poeb-rbb` | `business_date` | `business_date`, `dtime_utc`, `ofcg`, `ofcd`, `ofp` | +| `poeb-rbn` | `business_date` | `business_date`, `dtime_utc`, `ofcg`, `ofcd`, `ofp` | +| `pomb-rbn` | `business_date` | `dtime_utc`, `pofmin`, `pofmax`, `plofmin`, `plofmax`, `ofc`, `reserve_type` | +| `popmb-rmb` | `business_date` | `dtime_utc`, `pom`, `com`, `comrr`, `reserve_type` | +| `poze-redoze` | `business_date` | `business_date`, `period` | +| `price-cost` | `business_date` | `dtime_utc` | +| `price-fcst` | `business_date` | `dtime_utc` | +| `przeplywy-mocy` | `business_date` | `dtime_utc`, `section_code` | +| `pwm-dost-op` | `business_date` | `business_date`, `dtime_utc` | +| `pwm-igcc-in` | `business_date` | `business_date`, `dtime_utc` | +| `pwm-rdb` | `business_date` | `business_date`, `dtime_utc` | +| `pwm-rdn` | `business_date` | `business_date`, `dtime_utc` | +| `pwm-rdn-rdb` | `business_date` | `business_date`, `dtime_utc` | +| `rcco2` | `business_date` | `business_date`, `rcco2_pln` | +| `rce-pln` | `business_date` | `dtime_utc` | +| `ro-prog` | `business_date` | `dtime_utc` | +| `ro-rozl` | `business_date` | `dtime_utc` | +| `sk` | `business_date` | `dtime_utc` | +| `specwezlow` | `business_date` | `business_date`, `regional_dispatch_center` | +| `unav-pk5l` | `business_date` | `power_plant`, `unit_code`, `start_dtime_utc`, `end_dtime_utc` | +| `use-sprz-rbb` | `business_date` | `dtime_utc` | +| `use-sprz-rbn` | `business_date` | `dtime_utc` | +| `wmb` | `business_date` | `dtime_utc` | +| `wsp-wrm` | `business_date` | `dtime_utc` | +| `zeb-rozl` | `business_date` | `dtime` | +| `zmb` | `business_date` | `dtime_utc` | diff --git a/docs/pse-api-endpoints-map.pdf b/docs/pse-api-endpoints-map.pdf deleted file mode 100644 index 502ecf3..0000000 Binary files a/docs/pse-api-endpoints-map.pdf and /dev/null differ diff --git a/docs/usage.md b/docs/usage.md new file mode 100644 index 0000000..38b5a48 --- /dev/null +++ b/docs/usage.md @@ -0,0 +1,62 @@ +# Usage + +How to find an endpoint, fetch a date range, pick columns and choose an +output format. All endpoints and their columns are listed in +[endpoints.md](endpoints.md). + +## Find an endpoint + +```python +from pse_sdk import PSEClient + +client = PSEClient() + +client.endpoints() # ["afrr-status", "cmbp-tp", ...] +client.columns("price-cost") # ["cen_cost", "ckoeb_cost", ...] +``` + +## Fetch a date range + +```python +rows = client.fetch("price-cost", "2025-10-01", "2025-10-31") +``` + +`start` and `end` are inclusive and accept these formats: + +| Format | Example | +|--------------|--------------| +| `YYYY-MM-DD` | `2025-10-01` | +| `YYYY/MM/DD` | `2025/10/01` | +| `YYYYMMDD` | `20251001` | + +## Pick columns + +`columns=None` (the default) returns all columns. Pass a list to get only +some of them: + +```python +rows = client.fetch("price-cost", "2025-10-01", "2025-10-01", columns=["cen_cost"]) +rows[0] +``` + +```python +{ + "dtime": "2025-10-01 00:15:00", + "period": "00:00 - 00:15", + "cen_cost": 449.02, + "dtime_utc": "2025-09-30 22:15:00", + "period_utc": "22:00 - 22:15", + "business_date": "2025-10-01", + "publication_ts": "2026-06-16 12:11:18.607", + "publication_ts_utc": "2026-06-16 10:11:18.607", +} +``` + +## Choose an output format + +| `format` | Returns | +|---------------------|----------------| +| `"dict"` (default) | `list[dict]` | +| `"dataframe"` | `pd.DataFrame` | + +`"dataframe"` requires pandas \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index fb01526..da01a7c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,31 +1,59 @@ [build-system] -requires = ["hatchling"] +requires = ["hatchling>=1.27"] build-backend = "hatchling.build" [project] name = "pse-sdk" -version = "1.5.1" -description = "Python SDK for the PSE (Polskie Sieci Elektroenergetyczne) public REST API" +dynamic = ["version"] +description = "Unofficial Python SDK for the PSE (Polskie Sieci Elektroenergetyczne) public REST API" readme = "README.md" +license = "MIT" +license-files = ["LICENSE.md"] +authors = [{ name = "FranekGit" }] requires-python = ">=3.10" +keywords = ["pse", "energy", "electricity", "poland"] +classifiers = [ + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", + "Typing :: Typed", +] dependencies = [ "requests>=2.28", ] [project.optional-dependencies] pandas = ["pandas>=1.5"] + +[project.urls] +Homepage = "https://github.com/FranekGit/pse-python-sdk" +Documentation = "https://github.com/FranekGit/pse-python-sdk/blob/main/docs/usage.md" +Changelog = "https://github.com/FranekGit/pse-python-sdk/blob/main/CHANGELOG.md" +Issues = "https://github.com/FranekGit/pse-python-sdk/issues" + +[dependency-groups] dev = [ - "pytest", - "responses", - "ruff", + "pytest>=8", + "responses>=0.25", + "ruff>=0.15", "pandas>=1.5", ] +[tool.hatch.version] +path = "src/pse_sdk/__init__.py" + [tool.hatch.build.targets.wheel] packages = ["src/pse_sdk"] [tool.pytest.ini_options] testpaths = ["tests"] +pythonpath = ["scripts"] [tool.ruff] -src = ["src"] +src = ["src", "scripts"] +extend-exclude = ["src/pse_sdk/_registry.py"] + +[tool.ruff.lint.per-file-ignores] +"tests/**" = ["S102"] diff --git a/scripts/gen_docs.py b/scripts/gen_docs.py new file mode 100644 index 0000000..eb15d3d --- /dev/null +++ b/scripts/gen_docs.py @@ -0,0 +1,95 @@ +from __future__ import annotations + +import argparse +import re +import sys +from pathlib import Path + +from pse_sdk._endpoint_spec import EndpointSpec +from pse_sdk._query import data_columns +from pse_sdk._registry import REGISTRY + +OUTPUT = Path(__file__).resolve().parents[1] / "docs" / "endpoints.md" + +HEADER = """\ + +# Endpoints + +> API reference: `https://api.raporty.pse.pl/api/openapi` + +See [usage.md](usage.md) for how `fetch()` uses these columns. + +## Data columns + +In API order. Meta columns are left out. + +| Endpoint | Column | Type | +|---|---|---| +""" + +KEYS_HEADER = """ +## Date and key columns + +| Endpoint | Date column | Key columns | +|---|---|---| +""" + + +def natural_key(name: str) -> list[str | int]: + """Sort key that orders digit runs numerically (``kpi2`` before ``kpi10``).""" + return [int(part) if part.isdigit() else part for part in re.split(r"(\d+)", name)] + + +def _code(names: tuple[str, ...]) -> str: + """Join *names* as inline code, or ``-`` if empty.""" + return ", ".join(f"`{name}`" for name in names) or "-" + + +def render(registry: dict[str, EndpointSpec]) -> str: + """Render the data and key columns tables for *registry*.""" + data_rows = [] + key_rows = [] + for name in sorted(registry, key=natural_key): + spec = registry[name] + for column in data_columns(spec): + data_rows.append(f"| `{name}` | `{column}` | {spec.columns[column]} |\n") + key_rows.append(f"| `{name}` | `{spec.date_column}` | {_code(spec.keys)} |\n") + return HEADER + "".join(data_rows) + KEYS_HEADER + "".join(key_rows) + + +def _check(source: str) -> int: + """Return 1 if the committed docs differ from *source*, else 0.""" + current = OUTPUT.read_text(encoding="utf-8") if OUTPUT.exists() else None + if current != source: + print( + f"{OUTPUT.name} is out of date. Run: uv run scripts/gen_docs.py", + file=sys.stderr, + ) + return 1 + print(f"{OUTPUT.name} is up to date.") + return 0 + + +def main(argv: list[str] | None = None) -> int: + parser = argparse.ArgumentParser( + description="Generate docs/endpoints.md from the endpoint registry." + ) + parser.add_argument( + "--check", + action="store_true", + help="exit 1 if the committed docs are out of date", + ) + args = parser.parse_args(argv) + + source = render(REGISTRY) + + if args.check: + return _check(source) + + OUTPUT.write_text(source, encoding="utf-8", newline="\n") + print(f"Wrote {len(REGISTRY)} endpoints to {OUTPUT}") + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/scripts/gen_registry.py b/scripts/gen_registry.py new file mode 100644 index 0000000..15bea13 --- /dev/null +++ b/scripts/gen_registry.py @@ -0,0 +1,179 @@ +"""Generate ``src/pse_sdk/_registry.py`` from the PSE OpenAPI spec. + +Usage:: + + uv run scripts/gen_registry.py # regenerate + uv run scripts/gen_registry.py --check # exit 1 if out of date + uv run scripts/gen_registry.py --spec openapi.json # use a local spec file +""" + +from __future__ import annotations + +import argparse +import json +import string +import subprocess +import sys +import urllib.request +from pathlib import Path + +SPEC_URL = "https://api.raporty.pse.pl/api/openapi" +OUTPUT = Path(__file__).resolve().parents[1] / "src" / "pse_sdk" / "_registry.py" + +META_COLUMNS = ( + "dtime", + "dtime_utc", + "period", + "period_utc", + "business_date", + "publication_ts", + "publication_ts_utc", +) + +TEMPLATE = string.Template("""\ +# Generated by scripts/gen_registry.py from $url +# (spec version $version). Do not edit by hand. +from typing import Literal + +from pse_sdk._endpoint_spec import EndpointSpec + +Endpoint = Literal[$names] + +REGISTRY: dict[Endpoint, EndpointSpec] = {$entries} +""") + + +def load_spec(source: str) -> dict: + """Load the OpenAPI spec from a URL or a local file path.""" + if source.startswith(("http://", "https://")): + with urllib.request.urlopen(source, timeout=60) as resp: + return json.load(resp) + return json.loads(Path(source).read_text(encoding="utf-8")) + + +def parse_keys(paths: dict) -> dict[str, tuple[str, ...]]: + """Extract primary key columns from the by-key paths. + + ``/gen-jw/dtime_utc/{dtime_utc}/resource_code/{resource_code}`` + → ``{"gen-jw": ("dtime_utc", "resource_code")}`` + """ + keys: dict[str, tuple[str, ...]] = {} + for path in paths: + if "{" not in path: + continue + name, *parts = path.strip("/").split("/") + keys[name] = tuple(parts[::2]) + return keys + + +def date_column(name: str, columns: dict, keys: tuple[str, ...]) -> str: + """Return the column *name* is range-filtered on. + + ``business_date`` where present. Otherwise a lone ``period`` key: header + tables (``ogr-*-head``) hold one plan per date, so the key is the date. + + Raises: + ValueError: If neither applies. + """ + if "business_date" in columns: + return "business_date" + if keys == ("period",): + return "period" + raise ValueError(f"{name}: no date column (no business_date, keys={keys})") + + +def build_registry(spec: dict) -> dict[str, dict]: + """Build a registry entry for every endpoint in *spec*, sorted by name. + + Raises: + ValueError: If an endpoint has no date column. + """ + all_keys = parse_keys(spec["paths"]) + registry: dict[str, dict] = {} + for name, schema in sorted(spec["components"]["schemas"].items()): + columns = {col: prop["type"] for col, prop in schema["properties"].items()} + keys = all_keys.get(name, ()) + registry[name] = { + "columns": columns, + "date_column": date_column(name, columns, keys), + "meta_columns": tuple(c for c in META_COLUMNS if c in columns), + "keys": keys, + } + return registry + + +def render(registry: dict[str, dict], spec_version: str) -> str: + """Render *registry* as the source code of ``_registry.py``. + + Values are written with ``repr`` and laid out by ``ruff format``; trailing + commas keep one endpoint per line. + """ + names = "".join(f"{name!r}," for name in registry) + entries = "".join( + f"{name!r}: EndpointSpec({_kwargs(entry)})," for name, entry in registry.items() + ) + source = TEMPLATE.substitute( + url=SPEC_URL, version=spec_version, names=names, entries=entries + ) + return _ruff_format(source) + + +def _kwargs(entry: dict) -> str: + return ", ".join(f"{field}={value!r}" for field, value in entry.items()) + + +def _ruff_format(source: str) -> str: + """Format *source* with the ruff pinned in ``uv.lock``, ignoring config.""" + result = subprocess.run( + [sys.executable, "-m", "ruff", "format", "--isolated", "-"], + input=source, + capture_output=True, + encoding="utf-8", + check=True, + ) + return result.stdout + + +def _check(source: str) -> int: + """Return 1 if the committed registry differs from *source*, else 0.""" + current = OUTPUT.read_text(encoding="utf-8") if OUTPUT.exists() else None + if current != source: + print( + f"{OUTPUT.name} is out of date. Run: uv run scripts/gen_registry.py", + file=sys.stderr, + ) + return 1 + print(f"{OUTPUT.name} is up to date.") + return 0 + + +def main(argv: list[str] | None = None) -> int: + parser = argparse.ArgumentParser( + description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter + ) + parser.add_argument( + "--spec", + default=SPEC_URL, + help="spec URL or local file path (default: %(default)s)", + ) + parser.add_argument( + "--check", + action="store_true", + help="exit 1 if the committed registry is out of date", + ) + args = parser.parse_args(argv) + + spec = load_spec(args.spec) + registry = build_registry(spec) + source = render(registry, spec["info"]["version"]) + + if args.check: + return _check(source) + + OUTPUT.write_text(source, encoding="utf-8", newline="\n") + print(f"Wrote {len(registry)} endpoints to {OUTPUT}") + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/src/pse_sdk/__init__.py b/src/pse_sdk/__init__.py index 2bbea15..093c317 100644 --- a/src/pse_sdk/__init__.py +++ b/src/pse_sdk/__init__.py @@ -1,7 +1,5 @@ -"""PSE SDK — easy access to PSE public API.""" - from pse_sdk._client import PSEClient from pse_sdk._format import OutputFormat -__version__ = "1.5.1" -__all__ = ["PSEClient", "OutputFormat"] +__version__ = "2.0.0" +__all__ = ["OutputFormat", "PSEClient"] diff --git a/src/pse_sdk/_client.py b/src/pse_sdk/_client.py index ca86574..bf63e70 100644 --- a/src/pse_sdk/_client.py +++ b/src/pse_sdk/_client.py @@ -1,11 +1,15 @@ from __future__ import annotations -from pse_sdk._endpoints import make_endpoint +from pse_sdk._dates import normalize_date_range, split_date_range +from pse_sdk._format import OutputFormat, convert, validate_format from pse_sdk._http import HTTPClient +from pse_sdk._query import build_select, data_columns, date_clauses, get_spec +from pse_sdk._registry import REGISTRY, Endpoint +from pse_sdk._validate import validate_columns class PSEClient: - """Client for the PSE (Polskie Sieci Elektoenergetyczne) reporting API. + """Client for the PSE (Polskie Sieci Elektroenergetyczne) reporting API. Args: timeout: HTTP timeout in seconds. @@ -14,8 +18,16 @@ class PSEClient: from pse_sdk import PSEClient pse = PSEClient() - records = pse.get_cen("2024-01-01", "2024-01-31") - df = pse.get_price_cost("2024-01-01", "2024-01-31", format="dataframe") + pse.endpoints() # ["afrr-status", "cmbp-tp", ...] + pse.columns("price-cost") # ["cen_cost", "ckoeb_cost", ...] + records = pse.fetch("price-cost", "2024-01-01", "2024-01-31") + df = pse.fetch( + "price-cost", + "2024-01-01", + "2024-01-31", + columns=["cen_cost", "ckoeb_cost"], + format="dataframe", + ) """ _BASE_URL = "https://api.raporty.pse.pl/api" @@ -28,106 +40,66 @@ def __init__(self, timeout: int = 30) -> None: timeout=timeout, ) - # price-cost - self.get_cen = make_endpoint( - client=self.client, path="price-cost", columns=["cen_cost"] - ) - self.get_ckoeb = make_endpoint( - client=self.client, path="price-cost", columns=["ckoeb_cost"] - ) - self.get_ceb_sr = make_endpoint( - client=self.client, path="price-cost", columns=["ceb_sr_cost"] - ) - self.get_cor_pp = make_endpoint( - client=self.client, path="price-cost", columns=["cor_pp_cost"] - ) - self.get_imb_energy = make_endpoint( - client=self.client, path="price-cost", columns=["imb_energy"] - ) - self.get_contracting = make_endpoint( - client=self.client, path="price-cost", columns=["contracting"] - ) + @staticmethod + def endpoints() -> list[Endpoint]: + """Return the names of all endpoints, sorted alphabetically.""" + return list(REGISTRY) - # csdac-pln - self.get_csdac = make_endpoint( - client=self.client, path="csdac-pln", columns=["csdac_pln"] - ) + @staticmethod + def columns(endpoint: Endpoint) -> list[str]: + """Return the data columns of *endpoint* in API order. - # krb-rozl - self.get_kb = make_endpoint(client=self.client, path="krb-rozl", columns=["kb"]) - self.get_ko = make_endpoint(client=self.client, path="krb-rozl", columns=["ko"]) - self.get_kcz = make_endpoint( - client=self.client, path="krb-rozl", columns=["kcz"] - ) + These are the names accepted by ``fetch(columns=...)``. Meta columns + (``dtime``, ``period``, ``business_date``, ``publication_ts`` and their + ``*_utc`` variants) are left out; ``fetch()`` always returns them. - # kmb-kro-rozl - self.get_kmb = make_endpoint( - client=self.client, path="kmb-kro-rozl", columns=["kmb"] - ) - self.get_kro = make_endpoint( - client=self.client, path="kmb-kro-rozl", columns=["kro"] - ) + Raises: + ValueError: If *endpoint* is unknown. + """ + return data_columns(get_spec(endpoint)) - # sk - self.get_sk_d1_fcst = make_endpoint( - client=self.client, path="sk", columns=["sk_d1_fcst"] - ) - self.get_sk_d_fcst = make_endpoint( - client=self.client, path="sk", columns=["sk_d_fcst"] - ) - self.get_sk_cost = make_endpoint( - client=self.client, path="sk", columns=["sk_cost"] - ) + def fetch( + self, + endpoint: Endpoint, + start: str, + end: str, + *, + columns: list[str] | None = None, + format: OutputFormat = "dict", + ): + """Query *endpoint* for a date range. - # his-wlk-cal - self.get_demand = make_endpoint( - client=self.client, path="his-wlk-cal", columns=["demand"] - ) - self.get_swm_p = make_endpoint( - client=self.client, path="his-wlk-cal", columns=["swm_p"] - ) - self.get_swm_np = make_endpoint( - client=self.client, path="his-wlk-cal", columns=["swm_np"] - ) - self.get_jg = make_endpoint( - client=self.client, path="his-wlk-cal", columns=["jg"] - ) - self.get_jgw1 = make_endpoint( - client=self.client, path="his-wlk-cal", columns=["jgw1"] - ) - self.get_jgw2 = make_endpoint( - client=self.client, path="his-wlk-cal", columns=["jgw2"] - ) - self.get_jgm1 = make_endpoint( - client=self.client, path="his-wlk-cal", columns=["jgm1"] - ) - self.get_jgm2 = make_endpoint( - client=self.client, path="his-wlk-cal", columns=["jgm2"] - ) - self.get_jgz1 = make_endpoint( - client=self.client, path="his-wlk-cal", columns=["jgz1"] - ) - self.get_jgz2 = make_endpoint( - client=self.client, path="his-wlk-cal", columns=["jgz2"] - ) - self.get_jgz3 = make_endpoint( - client=self.client, path="his-wlk-cal", columns=["jgz3"] - ) - self.get_jga = make_endpoint( - client=self.client, path="his-wlk-cal", columns=["jga"] - ) - self.get_jgo = make_endpoint( - client=self.client, path="his-wlk-cal", columns=["jgo"] - ) - self.get_jnwrb = make_endpoint( - client=self.client, path="his-wlk-cal", columns=["jnwrb"] - ) - self.get_jgm = make_endpoint( - client=self.client, path="his-wlk-cal", columns=["jgm"] - ) - self.get_wi = make_endpoint( - client=self.client, path="his-wlk-cal", columns=["wi"] - ) - self.get_pv = make_endpoint( - client=self.client, path="his-wlk-cal", columns=["pv"] - ) + The range is fetched in 30-day chunks. + + Args: + endpoint: Endpoint name, e.g. ``"price-cost"``. + start: Begin of range (``YYYY-MM-DD``, ``YYYY/MM/DD``, or ``YYYYMMDD``). + end: End of range (``YYYY-MM-DD``, ``YYYY/MM/DD``, or ``YYYYMMDD``). + columns: Data columns to return. The endpoint's meta and key + columns are always included. ``None`` (default) returns all + columns. + format: Output format — ``"dict"`` (default) or ``"dataframe"``. + + Raises: + TypeError: If *start* or *end* is not a string, or *columns* is + not a list of strings. + ValueError: If *endpoint* or a column is unknown, *format* is not + supported, a date string cannot be parsed, or *start* is after + *end*. + """ + spec = get_spec(endpoint) + validate_format(format) + validate_columns(endpoint, columns) + start_str, end_str = normalize_date_range(start, end) + select = build_select(spec, columns) + + records: list[dict] = [] + for chunk_start, chunk_end in split_date_range(start_str, end_str): + filter_expr = " and ".join( + date_clauses(spec.date_column, chunk_start, chunk_end) + ) + records.extend( + self.client.fetch_all(endpoint, select=select, filter_expr=filter_expr) + ) + + return convert(records, format) diff --git a/src/pse_sdk/_endpoint_spec.py b/src/pse_sdk/_endpoint_spec.py new file mode 100644 index 0000000..1b2889b --- /dev/null +++ b/src/pse_sdk/_endpoint_spec.py @@ -0,0 +1,16 @@ +from __future__ import annotations + +from dataclasses import dataclass +from typing import Literal + +ColumnType = Literal["string", "number", "integer", "boolean"] + + +@dataclass(frozen=True) +class EndpointSpec: + """Schema of one PSE API endpoint.""" + + columns: dict[str, ColumnType] # all columns in API order -> JSON type + date_column: str # column for date-range filtering + meta_columns: tuple[str, ...] # dtime/period/business_date/publication_ts (+ _utc) + keys: tuple[str, ...] # primary key columns diff --git a/src/pse_sdk/_endpoints.py b/src/pse_sdk/_endpoints.py deleted file mode 100644 index c77d735..0000000 --- a/src/pse_sdk/_endpoints.py +++ /dev/null @@ -1,40 +0,0 @@ -from __future__ import annotations - -from pse_sdk._dates import normalize_date_range, split_date_range -from pse_sdk._format import OutputFormat, convert -from pse_sdk._http import HTTPClient - -COMMON_COLUMNS = ["dtime", "period", "business_date", "publication_ts"] - - -def make_endpoint(client: HTTPClient, path: str, columns: list[str] | None = None): - """Create a callable that fetches and formats endpoint data.""" - select = list(COMMON_COLUMNS) + columns if columns else None - - def fetch(start: str, end: str, format: OutputFormat = "dict") -> list[dict]: - """Query PSE data for a date range. - - Args: - start: Begin of range (``YYYY-MM-DD``, ``YYYY/MM/DD``, or ``YYYYMMDD``). - end: End of range (``YYYY-MM-DD``, ``YYYY/MM/DD``, or ``YYYYMMDD``). - format: Output format — ``"dict"`` (default) or ``"dataframe"``. - - Raises: - TypeError: If *start* or *end* is not a string. - ValueError: If a date string cannot be parsed, or *start* is - after *end*. - """ - start_str, end_str = normalize_date_range(start, end) - - records: list[dict] = [] - for chunk_start, chunk_end in split_date_range(start_str, end_str): - filter_expr = ( - f"business_date ge '{chunk_start}' and business_date le '{chunk_end}'" - ) - records.extend( - client.fetch_all(path, select=select, filter_expr=filter_expr) - ) - - return convert(records, format) - - return fetch diff --git a/src/pse_sdk/_http.py b/src/pse_sdk/_http.py index 2f0dfff..576f828 100644 --- a/src/pse_sdk/_http.py +++ b/src/pse_sdk/_http.py @@ -51,30 +51,7 @@ def fetch( if after: params.append("$after=" + quote(after)) - resp = self.session.get(url, params="&".join(params), timeout=self.timeout) - resp.raise_for_status() - return resp.json() - - def _request_with_retry(self, url: str) -> dict: - """GET *url* with retries on transient server errors.""" - for attempt in range(self._MAX_RETRIES + 1): - resp = self.session.get(url, timeout=self.timeout) - if ( - resp.status_code not in self._RETRY_STATUSES - or attempt == self._MAX_RETRIES - ): - resp.raise_for_status() - return resp.json() - delay = self._BACKOFF_BASE * (2**attempt) - logger.warning( - "HTTP %s from %s, retrying in %ss (%d/%d)", - resp.status_code, - url, - delay, - attempt + 1, - self._MAX_RETRIES, - ) - time.sleep(delay) + return self._request_with_retry(url, params="&".join(params)) def fetch_all( self, @@ -99,3 +76,43 @@ def fetch_all( records.extend(data.get("value", [])) return records + + def _request_with_retry(self, url: str, params: str | None = None) -> dict: + """GET *url* with retries on transient server errors.""" + for attempt in range(self._MAX_RETRIES + 1): + resp = self.session.get(url, params=params, timeout=self.timeout) + if ( + resp.status_code not in self._RETRY_STATUSES + or attempt == self._MAX_RETRIES + ): + self._raise_for_status(resp) + return resp.json() + delay = self._BACKOFF_BASE * (2**attempt) + logger.warning( + "HTTP %s from %s, retrying in %ss (%d/%d)", + resp.status_code, + resp.url, + delay, + attempt + 1, + self._MAX_RETRIES, + ) + time.sleep(delay) + + @staticmethod + def _raise_for_status(resp: requests.Response) -> None: + """Like ``resp.raise_for_status()``, plus the API error message if any.""" + try: + resp.raise_for_status() + except requests.HTTPError as e: + message = HTTPClient._error_message(resp) + if message is None: + raise + raise requests.HTTPError(f"{e}: {message}", response=resp) from None + + @staticmethod + def _error_message(resp: requests.Response) -> str | None: + """Return the PSE API ``error.message`` from *resp*, or ``None``.""" + try: + return resp.json()["error"]["message"] + except (ValueError, KeyError, TypeError): # non-JSON or unexpected shape + return None diff --git a/src/pse_sdk/_query.py b/src/pse_sdk/_query.py new file mode 100644 index 0000000..efff26a --- /dev/null +++ b/src/pse_sdk/_query.py @@ -0,0 +1,36 @@ +from __future__ import annotations + +from pse_sdk._endpoint_spec import EndpointSpec +from pse_sdk._registry import REGISTRY +from pse_sdk._validate import validate_endpoint + + +def get_spec(endpoint: str) -> EndpointSpec: + """Return the registry entry for *endpoint*. + + Raises: + ValueError: If *endpoint* is not in the registry. + """ + validate_endpoint(endpoint) + return REGISTRY[endpoint] + + +def data_columns(spec: EndpointSpec) -> list[str]: + """Return the non-meta columns of *spec* in API order.""" + return [c for c in spec.columns if c not in spec.meta_columns] + + +def build_select(spec: EndpointSpec, columns: list[str] | None) -> list[str] | None: + """Return the ``$select`` columns for *columns* of *spec*. + + ``None`` selects all columns. Otherwise the meta and key columns are + prepended so every row stays identifiable; duplicates are dropped. + """ + if columns is None: + return None + return list(dict.fromkeys([*spec.meta_columns, *spec.keys, *columns])) + + +def date_clauses(column: str, start: str, end: str) -> list[str]: + """Return ``$filter`` clauses limiting *column* to ``[start, end]``.""" + return [f"{column} ge '{start}'", f"{column} le '{end}'"] diff --git a/src/pse_sdk/_registry.py b/src/pse_sdk/_registry.py new file mode 100644 index 0000000..73cd988 --- /dev/null +++ b/src/pse_sdk/_registry.py @@ -0,0 +1,2301 @@ +# Generated by scripts/gen_registry.py from https://api.raporty.pse.pl/api/openapi +# (spec version 2.1.5). Do not edit by hand. +from typing import Literal + +from pse_sdk._endpoint_spec import EndpointSpec + +Endpoint = Literal[ + "afrr-status", + "cmbp-tp", + "cmbu-tu", + "codn", + "cor", + "cor-q-1", + "cordmax", + "crb-rozl", + "csdac-pln", + "csire-kpi1", + "csire-kpi10", + "csire-kpi2", + "csire-kpi3", + "csire-kpi4", + "csire-kpi5", + "csire-kpi6", + "csire-kpi7", + "csire-kpi8", + "csire-kpi9", + "eb-rozl", + "en-rozl", + "energy-prices", + "gen-jw", + "his-bil-mocy", + "his-gen-pal", + "his-gen-pal-sire", + "his-wlk-cal", + "it-oeb-rbb", + "it-oeb-rbn", + "it-omb-rbb", + "it-omb-rbn", + "it-opmb-rmb", + "it-ot-rbn", + "it-pp-rbb", + "it-pp-rbn", + "it-use-rbb", + "it-use-rbn", + "kmb-kro-rozl", + "krb-rozl", + "kse-load", + "lolp", + "mbp-tp", + "mbu-tu", + "oeb-bpkdbo", + "ogr-b", + "ogr-b-head", + "ogr-d1", + "ogr-d1-head", + "ogr-d2", + "ogr-d2-head", + "ogr-d39", + "ogr-d39-head", + "ogr-m", + "ogr-m-head", + "ogr-oper", + "ogr-oper-head", + "ogr-r", + "ogr-r-head", + "ogr-rmb", + "pdgobpkd", + "pdgopkd", + "pdgsz", + "pdwkseub", + "pk5l-wp", + "poeb-rbb", + "poeb-rbn", + "pomb-rbn", + "popmb-rmb", + "poze-redoze", + "price-cost", + "price-fcst", + "przeplywy-mocy", + "pwm-dost-op", + "pwm-igcc-in", + "pwm-rdb", + "pwm-rdn", + "pwm-rdn-rdb", + "rcco2", + "rce-pln", + "ro-prog", + "ro-rozl", + "sk", + "specwezlow", + "unav-pk5l", + "use-sprz-rbb", + "use-sprz-rbn", + "wmb", + "wsp-wrm", + "zeb-rozl", + "zmb", +] + +REGISTRY: dict[Endpoint, EndpointSpec] = { + "afrr-status": EndpointSpec( + columns={ + "event_time": "string", + "event_time_utc": "string", + "afrr_status": "integer", + "reason_code": "integer", + "reason": "string", + "business_date": "string", + "publication_ts": "string", + "publication_ts_utc": "string", + }, + date_column="business_date", + meta_columns=("business_date", "publication_ts", "publication_ts_utc"), + keys=("event_time_utc", "afrr_status", "reason_code"), + ), + "cmbp-tp": EndpointSpec( + columns={ + "dtime": "string", + "dtime_utc": "string", + "onmb": "string", + "fcr_g": "number", + "fcr_d": "number", + "afrr_g": "number", + "afrr_d": "number", + "mfrrd_g": "number", + "mfrrd_d": "number", + "rr_d": "number", + "rr_g": "number", + "business_date": "string", + "publication_ts": "string", + "publication_ts_utc": "string", + }, + date_column="business_date", + meta_columns=( + "dtime", + "dtime_utc", + "business_date", + "publication_ts", + "publication_ts_utc", + ), + keys=("dtime_utc",), + ), + "cmbu-tu": EndpointSpec( + columns={ + "dtime": "string", + "dtime_utc": "string", + "period": "string", + "period_utc": "string", + "fcr_g": "number", + "fcr_d": "number", + "afrr_g": "number", + "afrr_d": "number", + "mfrrd_g": "number", + "mfrrd_d": "number", + "business_date": "string", + "publication_ts": "string", + "publication_ts_utc": "string", + }, + date_column="business_date", + meta_columns=( + "dtime", + "dtime_utc", + "period", + "period_utc", + "business_date", + "publication_ts", + "publication_ts_utc", + ), + keys=("dtime_utc",), + ), + "codn": EndpointSpec( + columns={ + "period_from_date": "string", + "period_to_date": "string", + "price": "number", + "business_date": "string", + "publication_ts_utc": "string", + "publication_ts": "string", + }, + date_column="business_date", + meta_columns=("business_date", "publication_ts", "publication_ts_utc"), + keys=("business_date", "period_from_date", "period_to_date"), + ), + "cor": EndpointSpec( + columns={ + "dtime_utc": "string", + "dtime": "string", + "period": "string", + "period_utc": "string", + "cor_cost": "number", + "cor_fcst": "number", + "business_date": "string", + "publication_ts": "string", + "publication_ts_utc": "string", + }, + date_column="business_date", + meta_columns=( + "dtime", + "dtime_utc", + "period", + "period_utc", + "business_date", + "publication_ts", + "publication_ts_utc", + ), + keys=("dtime_utc",), + ), + "cor-q-1": EndpointSpec( + columns={ + "period_from_date": "string", + "period_to_date": "string", + "cor_excl": "number", + "cor_inc": "number", + "business_date": "string", + "publication_ts_utc": "string", + "publication_ts": "string", + }, + date_column="business_date", + meta_columns=("business_date", "publication_ts", "publication_ts_utc"), + keys=("business_date", "period_to_date", "period_from_date"), + ), + "cordmax": EndpointSpec( + columns={ + "cordmax_fcst": "number", + "cordmax_cost": "number", + "business_date": "string", + "publication_ts": "string", + "publication_ts_utc": "string", + }, + date_column="business_date", + meta_columns=("business_date", "publication_ts", "publication_ts_utc"), + keys=("business_date", "cordmax_fcst", "cordmax_cost"), + ), + "crb-rozl": EndpointSpec( + columns={ + "period": "string", + "period_utc": "string", + "dtime": "string", + "dtime_utc": "string", + "cen_cost": "number", + "ckoeb_cost": "number", + "ceb_pp_cost": "number", + "ceb_sr_cost": "number", + "ceb_sr_afrrg_cost": "number", + "ceb_sr_afrrd_cost": "number", + "business_date": "string", + "publication_ts": "string", + "publication_ts_utc": "string", + }, + date_column="business_date", + meta_columns=( + "dtime", + "dtime_utc", + "period", + "period_utc", + "business_date", + "publication_ts", + "publication_ts_utc", + ), + keys=("dtime_utc",), + ), + "csdac-pln": EndpointSpec( + columns={ + "period": "string", + "period_utc": "string", + "dtime": "string", + "dtime_utc": "string", + "csdac_pln": "number", + "business_date": "string", + "publication_ts": "string", + "publication_ts_utc": "string", + }, + date_column="business_date", + meta_columns=( + "dtime", + "dtime_utc", + "period", + "period_utc", + "business_date", + "publication_ts", + "publication_ts_utc", + ), + keys=("dtime_utc",), + ), + "csire-kpi1": EndpointSpec( + columns={ + "row_no": "string", + "eic_code": "string", + "tax_id": "string", + "name": "string", + "date_1d": "string", + "completeness_1d": "number", + "date_from_5d": "string", + "date_to_5d": "string", + "completeness_5d": "number", + "date_from_1m": "string", + "date_to_1m": "string", + "completeness_1m": "number", + "date_from_6m": "string", + "date_to_6m": "string", + "completeness_6m": "number", + "business_date": "string", + "publication_ts": "string", + "publication_ts_utc": "string", + }, + date_column="business_date", + meta_columns=("business_date", "publication_ts", "publication_ts_utc"), + keys=("business_date", "row_no"), + ), + "csire-kpi10": EndpointSpec( + columns={ + "row_no": "string", + "eic_code": "string", + "tax_id": "string", + "name": "string", + "date_from_1m": "string", + "date_to_1m": "string", + "timeliness_1m": "number", + "date_from_6m": "string", + "date_to_6m": "string", + "timeliness_6m": "number", + "business_date": "string", + "publication_ts": "string", + "publication_ts_utc": "string", + }, + date_column="business_date", + meta_columns=("business_date", "publication_ts", "publication_ts_utc"), + keys=("business_date", "row_no"), + ), + "csire-kpi2": EndpointSpec( + columns={ + "row_no": "string", + "eic_code": "string", + "tax_id": "string", + "name": "string", + "date_from_1m": "string", + "date_to_1m": "string", + "completeness_1m": "number", + "date_from_6m": "string", + "date_to_6m": "string", + "completeness_6m": "number", + "business_date": "string", + "publication_ts": "string", + "publication_ts_utc": "string", + }, + date_column="business_date", + meta_columns=("business_date", "publication_ts", "publication_ts_utc"), + keys=("business_date", "row_no"), + ), + "csire-kpi3": EndpointSpec( + columns={ + "row_no": "string", + "eic_code": "string", + "tax_id": "string", + "name": "string", + "date_from_1m": "string", + "date_to_1m": "string", + "completeness_1m": "number", + "date_from_6m": "string", + "date_to_6m": "string", + "completeness_6m": "number", + "business_date": "string", + "publication_ts": "string", + "publication_ts_utc": "string", + }, + date_column="business_date", + meta_columns=("business_date", "publication_ts", "publication_ts_utc"), + keys=("business_date", "row_no"), + ), + "csire-kpi4": EndpointSpec( + columns={ + "row_no": "string", + "eic_code": "string", + "tax_id": "string", + "name": "string", + "date_1d": "string", + "completeness_1d": "number", + "date_from_5d": "string", + "date_to_5d": "string", + "completeness_5d": "number", + "date_from_1m": "string", + "date_to_1m": "string", + "completeness_1m": "number", + "date_from_6m": "string", + "date_to_6m": "string", + "completeness_6m": "number", + "business_date": "string", + "publication_ts": "string", + "publication_ts_utc": "string", + }, + date_column="business_date", + meta_columns=("business_date", "publication_ts", "publication_ts_utc"), + keys=("business_date", "row_no"), + ), + "csire-kpi5": EndpointSpec( + columns={ + "row_no": "string", + "eic_code": "string", + "tax_id": "string", + "name": "string", + "date_1d": "string", + "timeliness_1d": "number", + "date_from_5d": "string", + "date_to_5d": "string", + "timeliness_5d": "number", + "date_from_1m": "string", + "date_to_1m": "string", + "timeliness_1m": "number", + "date_from_6m": "string", + "date_to_6m": "string", + "timeliness_6m": "number", + "business_date": "string", + "publication_ts": "string", + "publication_ts_utc": "string", + }, + date_column="business_date", + meta_columns=("business_date", "publication_ts", "publication_ts_utc"), + keys=("business_date", "row_no"), + ), + "csire-kpi6": EndpointSpec( + columns={ + "row_no": "string", + "eic_code": "string", + "tax_id": "string", + "name": "string", + "date_from_1m": "string", + "date_to_1m": "string", + "timeliness_1m": "number", + "date_from_6m": "string", + "date_to_6m": "string", + "timeliness_6m": "number", + "business_date": "string", + "publication_ts": "string", + "publication_ts_utc": "string", + }, + date_column="business_date", + meta_columns=("business_date", "publication_ts", "publication_ts_utc"), + keys=("business_date", "row_no"), + ), + "csire-kpi7": EndpointSpec( + columns={ + "row_no": "string", + "eic_code": "string", + "tax_id": "string", + "name": "string", + "date_from_1m": "string", + "date_to_1m": "string", + "timeliness_1m": "number", + "date_from_6m": "string", + "date_to_6m": "string", + "timeliness_6m": "number", + "business_date": "string", + "publication_ts": "string", + "publication_ts_utc": "string", + }, + date_column="business_date", + meta_columns=("business_date", "publication_ts", "publication_ts_utc"), + keys=("business_date", "row_no"), + ), + "csire-kpi8": EndpointSpec( + columns={ + "row_no": "string", + "eic_code": "string", + "tax_id": "string", + "name": "string", + "date_1d": "string", + "timeliness_1d": "number", + "date_from_5d": "string", + "date_to_5d": "string", + "timeliness_5d": "number", + "date_from_1m": "string", + "date_to_1m": "string", + "timeliness_1m": "number", + "date_from_6m": "string", + "date_to_6m": "string", + "timeliness_6m": "number", + "business_date": "string", + "publication_ts": "string", + "publication_ts_utc": "string", + }, + date_column="business_date", + meta_columns=("business_date", "publication_ts", "publication_ts_utc"), + keys=("business_date", "row_no"), + ), + "csire-kpi9": EndpointSpec( + columns={ + "row_no": "string", + "eic_code": "string", + "tax_id": "string", + "name": "string", + "date_1d": "string", + "correctness_1d": "number", + "date_from_5d": "string", + "date_to_5d": "string", + "correctness_5d": "number", + "date_from_1m": "string", + "date_to_1m": "string", + "correctness_1m": "number", + "date_from_6m": "string", + "date_to_6m": "string", + "correctness_6m": "number", + "business_date": "string", + "publication_ts": "string", + "publication_ts_utc": "string", + }, + date_column="business_date", + meta_columns=("business_date", "publication_ts", "publication_ts_utc"), + keys=("business_date", "row_no"), + ), + "eb-rozl": EndpointSpec( + columns={ + "dtime": "string", + "dtime_utc": "string", + "period": "string", + "period_utc": "string", + "eb_d_pp": "number", + "eb_w_pp": "number", + "eb_afrrg": "number", + "eb_afrrd": "number", + "business_date": "string", + "publication_ts": "string", + "publication_ts_utc": "string", + }, + date_column="business_date", + meta_columns=( + "dtime", + "dtime_utc", + "period", + "period_utc", + "business_date", + "publication_ts", + "publication_ts_utc", + ), + keys=("dtime_utc",), + ), + "en-rozl": EndpointSpec( + columns={ + "period": "string", + "period_utc": "string", + "dtime": "string", + "dtime_utc": "string", + "en_d": "number", + "en_w": "number", + "balance": "number", + "business_date": "string", + "publication_ts": "string", + "publication_ts_utc": "string", + }, + date_column="business_date", + meta_columns=( + "dtime", + "dtime_utc", + "period", + "period_utc", + "business_date", + "publication_ts", + "publication_ts_utc", + ), + keys=("dtime_utc",), + ), + "energy-prices": EndpointSpec( + columns={ + "dtime_utc": "string", + "dtime": "string", + "period": "string", + "period_utc": "string", + "cor_cost": "number", + "ceb_pp_cost": "number", + "ceb_sr_cost": "number", + "cen_cost": "number", + "csdac_pln": "number", + "sk_cost": "number", + "balance": "number", + "balance_power": "number", + "sk_cost_power": "number", + "business_date": "string", + "publication_ts": "string", + "publication_ts_utc": "string", + }, + date_column="business_date", + meta_columns=( + "dtime", + "dtime_utc", + "period", + "period_utc", + "business_date", + "publication_ts", + "publication_ts_utc", + ), + keys=("dtime_utc",), + ), + "gen-jw": EndpointSpec( + columns={ + "dtime_utc": "string", + "dtime": "string", + "resource_code": "string", + "power_plant": "string", + "operating_mode": "string", + "operating_mode_eng": "string", + "period": "string", + "period_utc": "string", + "value": "number", + "business_date": "string", + "publication_ts_utc": "string", + "publication_ts": "string", + }, + date_column="business_date", + meta_columns=( + "dtime", + "dtime_utc", + "period", + "period_utc", + "business_date", + "publication_ts", + "publication_ts_utc", + ), + keys=("dtime_utc", "resource_code", "operating_mode"), + ), + "his-bil-mocy": EndpointSpec( + columns={ + "peak": "string", + "peak_hour": "string", + "demand": "number", + "swm": "number", + "pos_jg": "number", + "pos_prb": "number", + "pos_sum": "number", + "rk_jg": "number", + "rk_prb": "number", + "rs_jg": "number", + "rs_prb": "number", + "rb_jg": "number", + "rb_prb": "number", + "ra_jg": "number", + "ra_prb": "number", + "we_jg": "number", + "we_prb": "number", + "ciep_jg": "number", + "ciep_prb": "number", + "inw_jg": "number", + "inw_prb": "number", + "pdysp_jg": "number", + "pdysp_prb": "number", + "sub": "number", + "sub_jg": "number", + "sub_prb": "number", + "rez": "number", + "rez_jg": "number", + "rez_jgw": "number", + "rez_jgw_wir": "number", + "rez_jgw_zim": "number", + "rez_jgm": "number", + "rez_jgz": "number", + "rez_jga": "number", + "rez_prb": "number", + "obc_sum": "number", + "obc_jg": "number", + "obc_prb": "number", + "ub_sum": "number", + "pdysp_sum": "number", + "business_date": "string", + "publication_ts_utc": "string", + "publication_ts": "string", + }, + date_column="business_date", + meta_columns=("business_date", "publication_ts", "publication_ts_utc"), + keys=("business_date", "peak_hour", "peak"), + ), + "his-gen-pal": EndpointSpec( + columns={ + "dtime": "string", + "dtime_utc": "string", + "period_utc": "string", + "period": "string", + "date": "string", + "alias_entsoe": "string", + "value": "string", + "publication_ts": "string", + "publication_ts_utc": "string", + "business_date": "string", + }, + date_column="business_date", + meta_columns=( + "dtime", + "dtime_utc", + "period", + "period_utc", + "business_date", + "publication_ts", + "publication_ts_utc", + ), + keys=("business_date", "dtime_utc", "alias_entsoe"), + ), + "his-gen-pal-sire": EndpointSpec( + columns={ + "dtime": "string", + "dtime_utc": "string", + "period_utc": "string", + "period": "string", + "date": "string", + "alias_entsoe": "string", + "value": "string", + "publication_ts": "string", + "publication_ts_utc": "string", + "business_date": "string", + "alias_sire": "string", + }, + date_column="business_date", + meta_columns=( + "dtime", + "dtime_utc", + "period", + "period_utc", + "business_date", + "publication_ts", + "publication_ts_utc", + ), + keys=("business_date", "dtime_utc", "alias_sire", "alias_entsoe"), + ), + "his-wlk-cal": EndpointSpec( + columns={ + "dtime": "string", + "dtime_utc": "string", + "period": "string", + "period_utc": "string", + "demand": "number", + "swm_p": "number", + "swm_np": "number", + "jg": "number", + "jgo": "string", + "jgw1": "number", + "jgw2": "number", + "jgm1": "number", + "jgm2": "number", + "jgz1": "number", + "jgz2": "number", + "jgz3": "number", + "jga": "number", + "jnwrb": "number", + "jgm": "number", + "wi": "number", + "pv": "number", + "business_date": "string", + "publication_ts": "string", + "publication_ts_utc": "string", + }, + date_column="business_date", + meta_columns=( + "dtime", + "dtime_utc", + "period", + "period_utc", + "business_date", + "publication_ts", + "publication_ts_utc", + ), + keys=("dtime_utc",), + ), + "it-oeb-rbb": EndpointSpec( + columns={ + "iteration_no": "integer", + "time_iteration_from_ts": "string", + "time_iteration_from_ts_utc": "string", + "time_iteration_to_ts": "string", + "time_iteration_to_ts_utc": "string", + "last_doc_dtime": "string", + "last_doc_dtime_utc": "string", + "time_period_from_dtime": "string", + "time_period_from_dtime_utc": "string", + "time_period_to_dtime": "string", + "time_period_to_dtime_utc": "string", + "business_date": "string", + "publication_ts": "string", + "publication_ts_utc": "string", + }, + date_column="business_date", + meta_columns=("business_date", "publication_ts", "publication_ts_utc"), + keys=("business_date", "iteration_no"), + ), + "it-oeb-rbn": EndpointSpec( + columns={ + "iteration_no": "integer", + "iteration_type": "string", + "time_iteration_from_ts": "string", + "time_iteration_from_ts_utc": "string", + "time_iteration_to_ts": "string", + "time_iteration_to_ts_utc": "string", + "last_doc_dtime": "string", + "last_doc_dtime_utc": "string", + "business_date": "string", + "publication_ts_utc": "string", + "publication_ts": "string", + }, + date_column="business_date", + meta_columns=("business_date", "publication_ts", "publication_ts_utc"), + keys=("business_date", "iteration_no"), + ), + "it-omb-rbb": EndpointSpec( + columns={ + "iteration_no": "integer", + "time_iteration_from_ts": "string", + "time_iteration_from_ts_utc": "string", + "time_iteration_to_ts": "string", + "time_iteration_to_ts_utc": "string", + "last_doc_dtime": "string", + "last_doc_dtime_utc": "string", + "time_period_from_dtime": "string", + "time_period_from_dtime_utc": "string", + "time_period_to_dtime": "string", + "time_period_to_dtime_utc": "string", + "business_date": "string", + "publication_ts": "string", + "publication_ts_utc": "string", + }, + date_column="business_date", + meta_columns=("business_date", "publication_ts", "publication_ts_utc"), + keys=("business_date", "iteration_no"), + ), + "it-omb-rbn": EndpointSpec( + columns={ + "iteration_no": "integer", + "iteration_type": "string", + "time_iteration_from_ts": "string", + "time_iteration_from_ts_utc": "string", + "time_iteration_to_ts": "string", + "time_iteration_to_ts_utc": "string", + "last_doc_dtime": "string", + "last_doc_dtime_utc": "string", + "business_date": "string", + "publication_ts_utc": "string", + "publication_ts": "string", + }, + date_column="business_date", + meta_columns=("business_date", "publication_ts", "publication_ts_utc"), + keys=("business_date", "iteration_no"), + ), + "it-opmb-rmb": EndpointSpec( + columns={ + "iteration_no": "integer", + "iteration_type": "string", + "time_iteration_from_ts": "string", + "time_iteration_from_ts_utc": "string", + "time_iteration_to_ts": "string", + "time_iteration_to_ts_utc": "string", + "last_doc_dtime": "string", + "last_doc_dtime_utc": "string", + "business_date": "string", + "publication_ts_utc": "string", + "publication_ts": "string", + }, + date_column="business_date", + meta_columns=("business_date", "publication_ts", "publication_ts_utc"), + keys=("business_date", "iteration_no"), + ), + "it-ot-rbn": EndpointSpec( + columns={ + "iteration_no": "integer", + "iteration_type": "string", + "time_iteration_from_ts": "string", + "time_iteration_from_ts_utc": "string", + "time_iteration_to_ts": "string", + "time_iteration_to_ts_utc": "string", + "last_doc_dtime": "string", + "last_doc_dtime_utc": "string", + "business_date": "string", + "publication_ts_utc": "string", + "publication_ts": "string", + }, + date_column="business_date", + meta_columns=("business_date", "publication_ts", "publication_ts_utc"), + keys=("business_date", "iteration_no"), + ), + "it-pp-rbb": EndpointSpec( + columns={ + "iteration_no": "integer", + "time_iteration_from_ts": "string", + "time_iteration_from_ts_utc": "string", + "time_iteration_to_ts": "string", + "time_iteration_to_ts_utc": "string", + "last_doc_dtime": "string", + "last_doc_dtime_utc": "string", + "time_period_from_dtime": "string", + "time_period_from_dtime_utc": "string", + "time_period_to_dtime": "string", + "time_period_to_dtime_utc": "string", + "business_date": "string", + "publication_ts": "string", + "publication_ts_utc": "string", + }, + date_column="business_date", + meta_columns=("business_date", "publication_ts", "publication_ts_utc"), + keys=("business_date", "iteration_no"), + ), + "it-pp-rbn": EndpointSpec( + columns={ + "iteration_no": "integer", + "iteration_type": "string", + "time_iteration_from_ts": "string", + "time_iteration_from_ts_utc": "string", + "time_iteration_to_ts": "string", + "time_iteration_to_ts_utc": "string", + "last_doc_dtime": "string", + "last_doc_dtime_utc": "string", + "business_date": "string", + "publication_ts_utc": "string", + "publication_ts": "string", + }, + date_column="business_date", + meta_columns=("business_date", "publication_ts", "publication_ts_utc"), + keys=("business_date", "iteration_no"), + ), + "it-use-rbb": EndpointSpec( + columns={ + "iteration_no": "integer", + "time_iteration_from_ts": "string", + "time_iteration_from_ts_utc": "string", + "time_iteration_to_ts": "string", + "time_iteration_to_ts_utc": "string", + "last_doc_dtime": "string", + "last_doc_dtime_utc": "string", + "time_period_from_dtime": "string", + "time_period_from_dtime_utc": "string", + "time_period_to_dtime": "string", + "time_period_to_dtime_utc": "string", + "volume": "number", + "business_date": "string", + "publication_ts": "string", + "publication_ts_utc": "string", + }, + date_column="business_date", + meta_columns=("business_date", "publication_ts", "publication_ts_utc"), + keys=("business_date", "iteration_no"), + ), + "it-use-rbn": EndpointSpec( + columns={ + "iteration_no": "integer", + "iteration_type": "string", + "time_iteration_from_ts": "string", + "time_iteration_from_ts_utc": "string", + "time_iteration_to_ts": "string", + "time_iteration_to_ts_utc": "string", + "last_doc_dtime": "string", + "last_doc_dtime_utc": "string", + "business_date": "string", + "publication_ts_utc": "string", + "publication_ts": "string", + }, + date_column="business_date", + meta_columns=("business_date", "publication_ts", "publication_ts_utc"), + keys=("business_date", "iteration_no"), + ), + "kmb-kro-rozl": EndpointSpec( + columns={ + "period": "string", + "period_utc": "string", + "dtime": "string", + "dtime_utc": "string", + "kmb": "number", + "kro": "number", + "business_date": "string", + "publication_ts": "string", + "publication_ts_utc": "string", + }, + date_column="business_date", + meta_columns=( + "dtime", + "dtime_utc", + "period", + "period_utc", + "business_date", + "publication_ts", + "publication_ts_utc", + ), + keys=("dtime_utc",), + ), + "krb-rozl": EndpointSpec( + columns={ + "period": "string", + "period_utc": "string", + "dtime": "string", + "dtime_utc": "string", + "kcz": "number", + "kb": "number", + "ko": "number", + "business_date": "string", + "publication_ts": "string", + "publication_ts_utc": "string", + }, + date_column="business_date", + meta_columns=( + "dtime", + "dtime_utc", + "period", + "period_utc", + "business_date", + "publication_ts", + "publication_ts_utc", + ), + keys=("dtime_utc",), + ), + "kse-load": EndpointSpec( + columns={ + "dtime": "string", + "dtime_utc": "string", + "period": "string", + "period_utc": "string", + "load_actual": "number", + "load_fcst": "number", + "publication_ts": "string", + "publication_ts_utc": "string", + "business_date": "string", + }, + date_column="business_date", + meta_columns=( + "dtime", + "dtime_utc", + "period", + "period_utc", + "business_date", + "publication_ts", + "publication_ts_utc", + ), + keys=("dtime_utc",), + ), + "lolp": EndpointSpec( + columns={ + "period": "string", + "period_utc": "string", + "dtime": "string", + "dtime_utc": "string", + "ojnz_id": "string", + "b0": "number", + "b1": "number", + "b2": "number", + "b3": "number", + "b4": "number", + "b5": "number", + "b6": "number", + "b7": "number", + "b8": "number", + "b9": "number", + "p0": "number", + "p1": "number", + "p2": "number", + "p3": "number", + "p4": "number", + "p5": "number", + "p6": "number", + "p7": "number", + "p8": "number", + "p9": "number", + "business_date": "string", + "publication_ts_utc": "string", + "publication_ts": "string", + }, + date_column="business_date", + meta_columns=( + "dtime", + "dtime_utc", + "period", + "period_utc", + "business_date", + "publication_ts", + "publication_ts_utc", + ), + keys=("business_date", "dtime_utc"), + ), + "mbp-tp": EndpointSpec( + columns={ + "dtime": "string", + "dtime_utc": "string", + "onmbp": "string", + "fcr_g": "number", + "fcr_d": "number", + "afrr_g": "number", + "afrr_d": "number", + "mfrrd_g": "number", + "mfrrd_d": "number", + "rr_g": "number", + "rr_d": "number", + "business_date": "string", + "publication_ts": "string", + "publication_ts_utc": "string", + }, + date_column="business_date", + meta_columns=( + "dtime", + "dtime_utc", + "business_date", + "publication_ts", + "publication_ts_utc", + ), + keys=("dtime_utc",), + ), + "mbu-tu": EndpointSpec( + columns={ + "dtime": "string", + "dtime_utc": "string", + "period": "string", + "period_utc": "string", + "fcr_g": "number", + "fcr_d": "number", + "afrr_g": "number", + "afrr_d": "number", + "mfrrd_g": "number", + "mfrrd_d": "number", + "publication_ts": "string", + "publication_ts_utc": "string", + "business_date": "string", + }, + date_column="business_date", + meta_columns=( + "dtime", + "dtime_utc", + "period", + "period_utc", + "business_date", + "publication_ts", + "publication_ts_utc", + ), + keys=("dtime_utc",), + ), + "oeb-bpkdbo": EndpointSpec( + columns={ + "dtime": "string", + "dtime_utc": "string", + "period": "string", + "period_utc": "string", + "ofp": "number", + "ofc": "number", + "cdo": "number", + "activ_direction": "string", + "sort": "integer", + "business_date": "string", + "publication_ts_utc": "string", + "publication_ts": "string", + }, + date_column="business_date", + meta_columns=( + "dtime", + "dtime_utc", + "period", + "period_utc", + "business_date", + "publication_ts", + "publication_ts_utc", + ), + keys=("dtime_utc", "activ_direction", "ofp", "ofc", "cdo"), + ), + "ogr-b": EndpointSpec( + columns={ + "node": "string", + "resource_name": "string", + "resource_code": "string", + "direction": "string", + "pol_min_power_of_unit": "number", + "pol_min_power_of_unit_plant": "integer", + "pol_max_power_of_unit_plant": "number", + "pol_max_power_of_unit": "integer", + "from_dtime": "string", + "from_dtime_utc": "string", + "to_dtime": "string", + "to_dtime_utc": "string", + "time_conditions": "string", + "limiting_element": "string", + "add_cond": "string", + "business_date": "string", + "publication_ts": "string", + "publication_ts_utc": "string", + "year": "number", + "month": "number", + "period": "string", + "is_active": "boolean", + "valid_from_ts_utc": "string", + "valid_to_ts_utc": "string", + "version": "string", + }, + date_column="business_date", + meta_columns=( + "period", + "business_date", + "publication_ts", + "publication_ts_utc", + ), + keys=("node", "business_date", "to_dtime_utc", "from_dtime_utc", "period"), + ), + "ogr-b-head": EndpointSpec( + columns={ + "title": "string", + "business_date": "string", + "remarks": "string", + "version": "string", + "is_active": "boolean", + }, + date_column="business_date", + meta_columns=("business_date",), + keys=("business_date",), + ), + "ogr-d1": EndpointSpec( + columns={ + "node": "string", + "resource_name": "string", + "resource_code": "string", + "direction": "string", + "pol_min_power_of_unit": "number", + "pol_min_power_of_unit_plant": "integer", + "pol_max_power_of_unit_plant": "number", + "pol_max_power_of_unit": "integer", + "from_dtime": "string", + "from_dtime_utc": "string", + "to_dtime": "string", + "to_dtime_utc": "string", + "time_conditions": "string", + "limiting_element": "string", + "add_cond": "string", + "business_date": "string", + "publication_ts": "string", + "publication_ts_utc": "string", + }, + date_column="business_date", + meta_columns=("business_date", "publication_ts", "publication_ts_utc"), + keys=("node", "business_date", "to_dtime", "from_dtime"), + ), + "ogr-d1-head": EndpointSpec( + columns={"title": "string", "period": "string", "remarks": "string"}, + date_column="period", + meta_columns=("period",), + keys=("period",), + ), + "ogr-d2": EndpointSpec( + columns={ + "node": "string", + "resource_name": "string", + "resource_code": "string", + "direction": "string", + "pol_min_power_of_unit": "number", + "pol_min_power_of_unit_plant": "integer", + "pol_max_power_of_unit_plant": "number", + "pol_max_power_of_unit": "integer", + "from_dtime": "string", + "from_dtime_utc": "string", + "to_dtime": "string", + "to_dtime_utc": "string", + "time_conditions": "string", + "limiting_element": "string", + "add_cond": "string", + "business_date": "string", + "publication_ts": "string", + "publication_ts_utc": "string", + }, + date_column="business_date", + meta_columns=("business_date", "publication_ts", "publication_ts_utc"), + keys=("node", "business_date", "to_dtime", "from_dtime"), + ), + "ogr-d2-head": EndpointSpec( + columns={"title": "string", "period": "string", "remarks": "string"}, + date_column="period", + meta_columns=("period",), + keys=("period",), + ), + "ogr-d39": EndpointSpec( + columns={ + "node": "string", + "resource_name": "string", + "resource_code": "string", + "direction": "string", + "pol_min_power_of_unit": "number", + "pol_min_power_of_unit_plant": "integer", + "pol_max_power_of_unit_plant": "number", + "pol_max_power_of_unit": "integer", + "from_dtime": "string", + "from_dtime_utc": "string", + "to_dtime": "string", + "to_dtime_utc": "string", + "time_conditions": "string", + "limiting_element": "string", + "add_cond": "string", + "business_date": "string", + "publication_ts": "string", + "publication_ts_utc": "string", + }, + date_column="business_date", + meta_columns=("business_date", "publication_ts", "publication_ts_utc"), + keys=("node", "business_date", "to_dtime", "from_dtime"), + ), + "ogr-d39-head": EndpointSpec( + columns={ + "title": "string", + "period": "string", + "from_period": "string", + "to_period": "string", + "remarks": "string", + }, + date_column="period", + meta_columns=("period",), + keys=("period",), + ), + "ogr-m": EndpointSpec( + columns={ + "node": "string", + "resource_name": "string", + "resource_code": "string", + "direction": "string", + "pol_min_power_of_unit": "number", + "pol_min_power_of_unit_plant": "integer", + "pol_max_power_of_unit_plant": "number", + "pol_max_power_of_unit": "integer", + "from_dtime": "string", + "from_dtime_utc": "string", + "to_dtime": "string", + "to_dtime_utc": "string", + "time_conditions": "string", + "limiting_element": "string", + "add_cond": "string", + "business_date": "string", + "publication_ts": "string", + "publication_ts_utc": "string", + }, + date_column="business_date", + meta_columns=("business_date", "publication_ts", "publication_ts_utc"), + keys=("node", "business_date", "to_dtime", "from_dtime"), + ), + "ogr-m-head": EndpointSpec( + columns={ + "title": "string", + "period": "string", + "from_period": "string", + "to_period": "string", + "remarks": "string", + }, + date_column="period", + meta_columns=("period",), + keys=("period",), + ), + "ogr-oper": EndpointSpec( + columns={ + "node": "string", + "resource_name": "string", + "resource_code": "string", + "direction": "string", + "pol_min_power_of_unit": "number", + "pol_min_power_of_unit_plant": "integer", + "pol_max_power_of_unit_plant": "number", + "pol_max_power_of_unit": "integer", + "from_dtime": "string", + "from_dtime_utc": "string", + "to_dtime": "string", + "to_dtime_utc": "string", + "time_conditions": "string", + "limiting_element": "string", + "add_cond": "string", + "business_date": "string", + "publication_ts": "string", + "publication_ts_utc": "string", + }, + date_column="business_date", + meta_columns=("business_date", "publication_ts", "publication_ts_utc"), + keys=("node", "business_date", "to_dtime", "from_dtime"), + ), + "ogr-oper-head": EndpointSpec( + columns={"title": "string", "period": "string", "remarks": "string"}, + date_column="period", + meta_columns=("period",), + keys=("period",), + ), + "ogr-r": EndpointSpec( + columns={ + "node": "string", + "resource_name": "string", + "resource_code": "string", + "direction": "string", + "pol_min_power_of_unit": "number", + "pol_min_power_of_unit_plant": "integer", + "pol_max_power_of_unit_plant": "number", + "pol_max_power_of_unit": "integer", + "from_dtime": "string", + "from_dtime_utc": "string", + "to_dtime": "string", + "to_dtime_utc": "string", + "time_conditions": "string", + "limiting_element": "string", + "add_cond": "string", + "business_date": "string", + "publication_ts": "string", + "publication_ts_utc": "string", + "year": "number", + "month": "number", + "period": "string", + }, + date_column="business_date", + meta_columns=( + "period", + "business_date", + "publication_ts", + "publication_ts_utc", + ), + keys=("node", "business_date", "to_dtime", "from_dtime", "period"), + ), + "ogr-r-head": EndpointSpec( + columns={ + "title": "string", + "period": "string", + "from_period": "string", + "to_period": "string", + "remarks": "string", + }, + date_column="period", + meta_columns=("period",), + keys=("period",), + ), + "ogr-rmb": EndpointSpec( + columns={ + "id": "integer", + "node": "string", + "from_dtime": "string", + "from_dtime_utc": "string", + "to_dtime": "string", + "to_dtime_utc": "string", + "unit_name": "string", + "direction": "string", + "sminp": "integer", + "smaxp": "integer", + "smaxp_sminp": "integer", + "business_date": "string", + "publication_ts": "string", + "publication_ts_utc": "string", + }, + date_column="business_date", + meta_columns=("business_date", "publication_ts", "publication_ts_utc"), + keys=("from_dtime", "node"), + ), + "pdgobpkd": EndpointSpec( + columns={ + "dtime_utc": "string", + "dtime": "string", + "period": "string", + "period_utc": "string", + "kse_pow_dem": "number", + "capacity_jgw_jgm_jgz_jga": "number", + "capacity_jgw_zak_1": "number", + "capacity_jgw_zak_2": "number", + "capacity_jgm_zak_1": "number", + "capacity_jgm_zak_2": "number", + "capacity_jgz_zak_1": "number", + "capacity_jgz_zak_2": "number", + "capacity_jgz_zak_3": "number", + "capacity_jga": "number", + "capacity_jgo": "number", + "gen_jgw_jgm_jgz_jga": "number", + "gen_jgw_zak_1": "number", + "gen_jgw_zak_2": "number", + "gen_jgm_zak_1": "number", + "gen_jgm_zak_2": "number", + "gen_jgz_zak_1": "number", + "gen_jgz_zak_2": "number", + "gen_jgz_zak_3": "number", + "gen_jga": "number", + "gen_jgo": "number", + "gen_not_activ_part": "number", + "ogr_mwe": "number", + "tot_jgm_char_pow": "number", + "gen_wi": "number", + "gen_fv": "number", + "dom_balance_exchange_non_par": "number", + "dom_balance_exchange_par": "number", + "rez_over_demand": "number", + "rez_under": "number", + "business_date": "string", + "publication_ts_utc": "string", + "publication_ts": "string", + }, + date_column="business_date", + meta_columns=( + "dtime", + "dtime_utc", + "period", + "period_utc", + "business_date", + "publication_ts", + "publication_ts_utc", + ), + keys=("dtime_utc", "business_date"), + ), + "pdgopkd": EndpointSpec( + columns={ + "dtime_utc": "string", + "dtime": "string", + "period": "string", + "period_utc": "string", + "kse_pow_dem": "number", + "capacity_jgw_jgm_jgz_jga": "number", + "capacity_jgw_zak_1": "number", + "capacity_jgw_zak_2": "number", + "capacity_jgm_zak_1": "number", + "capacity_jgm_zak_2": "number", + "capacity_jgz_zak_1": "number", + "capacity_jgz_zak_2": "number", + "capacity_jgz_zak_3": "number", + "capacity_jga": "number", + "capacity_jgo": "number", + "gen_jgw_jgm_jgz_jga": "number", + "gen_jgw_zak_1": "number", + "gen_jgw_zak_2": "number", + "gen_jgm_zak_1": "number", + "gen_jgm_zak_2": "number", + "gen_jgz_zak_1": "number", + "gen_jgz_zak_2": "number", + "gen_jgz_zak_3": "number", + "gen_jga": "number", + "gen_jgo": "number", + "gen_not_activ_part": "number", + "ogr_mwe": "number", + "tot_jgm_char_pow": "number", + "gen_wi": "number", + "gen_fv": "number", + "dom_balance_exchange_non_par": "number", + "dom_balance_exchange_par": "number", + "rez_over_demand": "number", + "rez_under": "number", + "business_date": "string", + "publication_ts_utc": "string", + "publication_ts": "string", + }, + date_column="business_date", + meta_columns=( + "dtime", + "dtime_utc", + "period", + "period_utc", + "business_date", + "publication_ts", + "publication_ts_utc", + ), + keys=("dtime_utc", "business_date"), + ), + "pdgsz": EndpointSpec( + columns={ + "dtime": "string", + "usage_fcst": "integer", + "total_power_demand": "number", + "dtime_utc": "string", + "business_date": "string", + "publication_ts": "string", + "publication_ts_utc": "string", + "is_active": "boolean", + "valid_from_ts": "string", + "valid_to_ts": "string", + }, + date_column="business_date", + meta_columns=( + "dtime", + "dtime_utc", + "business_date", + "publication_ts", + "publication_ts_utc", + ), + keys=("dtime_utc", "valid_from_ts", "valid_to_ts"), + ), + "pdwkseub": EndpointSpec( + columns={ + "dtime": "string", + "dtime_utc": "string", + "period": "string", + "period_utc": "string", + "power_plant": "string", + "resource_code": "string", + "non_us_cap": "number", + "grid_lim": "number", + "available_capacity": "number", + "publication_ts": "string", + "publication_ts_utc": "string", + "business_date": "string", + }, + date_column="business_date", + meta_columns=( + "dtime", + "dtime_utc", + "period", + "period_utc", + "business_date", + "publication_ts", + "publication_ts_utc", + ), + keys=("dtime_utc", "resource_code"), + ), + "pk5l-wp": EndpointSpec( + columns={ + "period": "string", + "plan_dtime": "string", + "plan_dtime_utc": "string", + "grid_demand_fcst": "number", + "req_pow_res": "number", + "surplus_cap_avail_tso": "number", + "gen_surplus_avail_tso_above": "number", + "avail_cap_gen_units_stor_prov": "number", + "avail_cap_gen_units_stor_prov_tso": "number", + "fcst_gen_unit_stor_prov": "number", + "fcst_gen_unit_stor_non_prov": "number", + "fcst_wi_tot_gen": "number", + "fcst_pv_tot_gen": "number", + "planned_exchange": "number", + "fcst_unav_energy": "number", + "planned_restr_mwe_avail_shutdown": "number", + "sum_unav_oper_cond": "number", + "pred_gen_res_not_cov": "number", + "cap_market_obligation": "number", + "business_date": "string", + "publication_ts_utc": "string", + "publication_ts": "string", + }, + date_column="business_date", + meta_columns=( + "period", + "business_date", + "publication_ts", + "publication_ts_utc", + ), + keys=("plan_dtime_utc",), + ), + "poeb-rbb": EndpointSpec( + columns={ + "dtime_utc": "string", + "dtime": "string", + "period": "string", + "period_utc": "string", + "ofcg": "number", + "ofcd": "number", + "ofp": "number", + "business_date": "string", + "publication_ts_utc": "string", + "publication_ts": "string", + }, + date_column="business_date", + meta_columns=( + "dtime", + "dtime_utc", + "period", + "period_utc", + "business_date", + "publication_ts", + "publication_ts_utc", + ), + keys=("business_date", "dtime_utc", "ofcg", "ofcd", "ofp"), + ), + "poeb-rbn": EndpointSpec( + columns={ + "dtime_utc": "string", + "dtime": "string", + "period": "string", + "period_utc": "string", + "ofcg": "number", + "ofcd": "number", + "ofp": "number", + "business_date": "string", + "publication_ts_utc": "string", + "publication_ts": "string", + }, + date_column="business_date", + meta_columns=( + "dtime", + "dtime_utc", + "period", + "period_utc", + "business_date", + "publication_ts", + "publication_ts_utc", + ), + keys=("business_date", "dtime_utc", "ofcg", "ofcd", "ofp"), + ), + "pomb-rbn": EndpointSpec( + columns={ + "dtime": "string", + "dtime_utc": "string", + "period": "string", + "period_utc": "string", + "reserve_type": "string", + "pofmin": "number", + "pofmax": "number", + "plofmin": "number", + "plofmax": "number", + "ofc": "number", + "business_date": "string", + "publication_ts": "string", + "publication_ts_utc": "string", + }, + date_column="business_date", + meta_columns=( + "dtime", + "dtime_utc", + "period", + "period_utc", + "business_date", + "publication_ts", + "publication_ts_utc", + ), + keys=( + "dtime_utc", + "pofmin", + "pofmax", + "plofmin", + "plofmax", + "ofc", + "reserve_type", + ), + ), + "popmb-rmb": EndpointSpec( + columns={ + "dtime": "string", + "dtime_utc": "string", + "onmbp": "string", + "reserve_type": "string", + "pom": "number", + "com": "number", + "comrr": "number", + "business_date": "string", + "publication_ts": "string", + "publication_ts_utc": "string", + }, + date_column="business_date", + meta_columns=( + "dtime", + "dtime_utc", + "business_date", + "publication_ts", + "publication_ts_utc", + ), + keys=("dtime_utc", "pom", "com", "comrr", "reserve_type"), + ), + "poze-redoze": EndpointSpec( + columns={ + "dtime": "string", + "dtime_utc": "string", + "period": "string", + "period_utc": "string", + "pv_red_balance": "number", + "wi_red_balance": "number", + "pv_red_network": "number", + "wi_red_network": "number", + "business_date": "string", + "publication_ts": "string", + "publication_ts_utc": "string", + }, + date_column="business_date", + meta_columns=( + "dtime", + "dtime_utc", + "period", + "period_utc", + "business_date", + "publication_ts", + "publication_ts_utc", + ), + keys=("business_date", "period"), + ), + "price-cost": EndpointSpec( + columns={ + "cen_cost": "number", + "ckoeb_cost": "number", + "ceb_sr_cost": "number", + "cor_pp_cost": "number", + "imb_energy": "number", + "contracting": "string", + "dtime": "string", + "dtime_utc": "string", + "period": "string", + "period_utc": "string", + "publication_ts": "string", + "publication_ts_utc": "string", + "business_date": "string", + }, + date_column="business_date", + meta_columns=( + "dtime", + "dtime_utc", + "period", + "period_utc", + "business_date", + "publication_ts", + "publication_ts_utc", + ), + keys=("dtime_utc",), + ), + "price-fcst": EndpointSpec( + columns={ + "cen_fcst": "number", + "ckoeb_fcst": "number", + "ceb_sr_fcst": "number", + "cor_fcst": "number", + "imb_energy": "number", + "contracting": "string", + "dtime": "string", + "dtime_utc": "string", + "period": "string", + "period_utc": "string", + "publication_ts": "string", + "publication_ts_utc": "string", + "business_date": "string", + }, + date_column="business_date", + meta_columns=( + "dtime", + "dtime_utc", + "period", + "period_utc", + "business_date", + "publication_ts", + "publication_ts_utc", + ), + keys=("dtime_utc",), + ), + "przeplywy-mocy": EndpointSpec( + columns={ + "section_code": "string", + "dtime": "string", + "dtime_utc": "string", + "period": "string", + "period_utc": "string", + "value": "number", + "business_date": "string", + "publication_ts": "string", + "publication_ts_utc": "string", + }, + date_column="business_date", + meta_columns=( + "dtime", + "dtime_utc", + "period", + "period_utc", + "business_date", + "publication_ts", + "publication_ts_utc", + ), + keys=("dtime_utc", "section_code"), + ), + "pwm-dost-op": EndpointSpec( + columns={ + "dtime": "string", + "dtime_utc": "string", + "period": "string", + "period_utc": "string", + "pl_cz": "number", + "cz_pl": "number", + "pl_sk": "number", + "sk_pl": "number", + "pl_de": "number", + "de_pl": "number", + "pl_se": "number", + "se_pl": "number", + "pl_ua": "number", + "ua_pl": "number", + "pl_lt": "number", + "lt_pl": "number", + "saldo": "number", + "business_date": "string", + "publication_ts": "string", + "publication_ts_utc": "string", + }, + date_column="business_date", + meta_columns=( + "dtime", + "dtime_utc", + "period", + "period_utc", + "business_date", + "publication_ts", + "publication_ts_utc", + ), + keys=("business_date", "dtime_utc"), + ), + "pwm-igcc-in": EndpointSpec( + columns={ + "dtime": "string", + "dtime_utc": "string", + "period": "string", + "period_utc": "string", + "energy_afrr_exp": "number", + "energy_afrr_imp": "number", + "afrr_exp_pln": "number", + "afrr_imp_pln": "number", + "afrr_exp_eur": "number", + "afrr_imp_eur": "number", + "business_date": "string", + "publication_ts": "string", + "publication_ts_utc": "string", + }, + date_column="business_date", + meta_columns=( + "dtime", + "dtime_utc", + "period", + "period_utc", + "business_date", + "publication_ts", + "publication_ts_utc", + ), + keys=("business_date", "dtime_utc"), + ), + "pwm-rdb": EndpointSpec( + columns={ + "dtime": "string", + "dtime_utc": "string", + "period": "string", + "period_utc": "string", + "pl_cz": "number", + "cz_pl": "number", + "pl_sk": "number", + "sk_pl": "number", + "pl_de": "number", + "de_pl": "number", + "pl_se": "number", + "se_pl": "number", + "pl_ua": "number", + "ua_pl": "number", + "pl_lt": "number", + "lt_pl": "number", + "business_date": "string", + "publication_ts": "string", + "publication_ts_utc": "string", + }, + date_column="business_date", + meta_columns=( + "dtime", + "dtime_utc", + "period", + "period_utc", + "business_date", + "publication_ts", + "publication_ts_utc", + ), + keys=("business_date", "dtime_utc"), + ), + "pwm-rdn": EndpointSpec( + columns={ + "dtime": "string", + "dtime_utc": "string", + "period": "string", + "period_utc": "string", + "pl_cz": "number", + "cz_pl": "number", + "pl_sk": "number", + "sk_pl": "number", + "pl_de": "number", + "de_pl": "number", + "pl_se": "number", + "se_pl": "number", + "pl_ua_dob": "number", + "ua_dob_pl": "number", + "pl_ua": "number", + "ua_pl": "number", + "pl_lt": "number", + "lt_pl": "number", + "business_date": "string", + "publication_ts": "string", + "publication_ts_utc": "string", + }, + date_column="business_date", + meta_columns=( + "dtime", + "dtime_utc", + "period", + "period_utc", + "business_date", + "publication_ts", + "publication_ts_utc", + ), + keys=("business_date", "dtime_utc"), + ), + "pwm-rdn-rdb": EndpointSpec( + columns={ + "dtime": "string", + "dtime_utc": "string", + "period": "string", + "period_utc": "string", + "pl_cz": "number", + "cz_pl": "number", + "pl_sk": "number", + "sk_pl": "number", + "pl_de": "number", + "de_pl": "number", + "pl_se": "number", + "se_pl": "number", + "pl_ua_dob": "number", + "ua_dob_pl": "number", + "pl_ua": "number", + "ua_pl": "number", + "pl_lt": "number", + "lt_pl": "number", + "business_date": "string", + "publication_ts": "string", + "publication_ts_utc": "string", + }, + date_column="business_date", + meta_columns=( + "dtime", + "dtime_utc", + "period", + "period_utc", + "business_date", + "publication_ts", + "publication_ts_utc", + ), + keys=("business_date", "dtime_utc"), + ), + "rcco2": EndpointSpec( + columns={ + "rcco2_pln": "number", + "rcco2_eur": "number", + "publication_ts": "string", + "publication_ts_utc": "string", + "business_date": "string", + }, + date_column="business_date", + meta_columns=("business_date", "publication_ts", "publication_ts_utc"), + keys=("business_date", "rcco2_pln"), + ), + "rce-pln": EndpointSpec( + columns={ + "dtime": "string", + "dtime_utc": "string", + "period": "string", + "period_utc": "string", + "rce_pln": "number", + "business_date": "string", + "publication_ts": "string", + "publication_ts_utc": "string", + }, + date_column="business_date", + meta_columns=( + "dtime", + "dtime_utc", + "period", + "period_utc", + "business_date", + "publication_ts", + "publication_ts_utc", + ), + keys=("dtime_utc",), + ), + "ro-prog": EndpointSpec( + columns={ + "period": "string", + "period_utc": "string", + "dtime": "string", + "dtime_utc": "string", + "ro_fcst": "number", + "business_date": "string", + "publication_ts": "string", + "publication_ts_utc": "string", + }, + date_column="business_date", + meta_columns=( + "dtime", + "dtime_utc", + "period", + "period_utc", + "business_date", + "publication_ts", + "publication_ts_utc", + ), + keys=("dtime_utc",), + ), + "ro-rozl": EndpointSpec( + columns={ + "period": "string", + "period_utc": "string", + "dtime": "string", + "dtime_utc": "string", + "ro_cost": "number", + "business_date": "string", + "publication_ts": "string", + "publication_ts_utc": "string", + }, + date_column="business_date", + meta_columns=( + "dtime", + "dtime_utc", + "period", + "period_utc", + "business_date", + "publication_ts", + "publication_ts_utc", + ), + keys=("dtime_utc",), + ), + "sk": EndpointSpec( + columns={ + "dtime_utc": "string", + "dtime": "string", + "period": "string", + "period_utc": "string", + "sk_d1_fcst": "number", + "sk_d_fcst": "number", + "sk_cost": "number", + "business_date": "string", + "publication_ts": "string", + "publication_ts_utc": "string", + }, + date_column="business_date", + meta_columns=( + "dtime", + "dtime_utc", + "period", + "period_utc", + "business_date", + "publication_ts", + "publication_ts_utc", + ), + keys=("dtime_utc",), + ), + "specwezlow": EndpointSpec( + columns={ + "regional_dispatch_center": "string", + "dso_branch": "string", + "station_name": "string", + "switching_station_code": "string", + "switching_station_voltage": "string", + "busbar_code": "string", + "busbar_name": "string", + "business_date": "string", + "publication_ts_utc": "string", + "publication_ts": "string", + }, + date_column="business_date", + meta_columns=("business_date", "publication_ts", "publication_ts_utc"), + keys=("business_date", "regional_dispatch_center"), + ), + "unav-pk5l": EndpointSpec( + columns={ + "power_plant": "string", + "type": "string", + "state": "string", + "unit_code": "string", + "reason": "string", + "start_dtime": "string", + "start_dtime_utc": "string", + "end_dtime": "string", + "end_dtime_utc": "string", + "direction": "string", + "mrid_zas": "string", + "snd_dtime": "string", + "snd_dtime_utc": "string", + "business_date": "string", + "publication_ts": "string", + "publication_ts_utc": "string", + }, + date_column="business_date", + meta_columns=("business_date", "publication_ts", "publication_ts_utc"), + keys=("power_plant", "unit_code", "start_dtime_utc", "end_dtime_utc"), + ), + "use-sprz-rbb": EndpointSpec( + columns={ + "dtime": "string", + "dtime_utc": "string", + "sprz_volume": "number", + "business_date": "string", + "publication_ts": "string", + "publication_ts_utc": "string", + }, + date_column="business_date", + meta_columns=( + "dtime", + "dtime_utc", + "business_date", + "publication_ts", + "publication_ts_utc", + ), + keys=("dtime_utc",), + ), + "use-sprz-rbn": EndpointSpec( + columns={ + "dtime": "string", + "dtime_utc": "string", + "day_ahead_tr_vol": "number", + "business_date": "string", + "publication_ts": "string", + "publication_ts_utc": "string", + }, + date_column="business_date", + meta_columns=( + "dtime", + "dtime_utc", + "business_date", + "publication_ts", + "publication_ts_utc", + ), + keys=("dtime_utc",), + ), + "wmb": EndpointSpec( + columns={ + "dtime": "string", + "dtime_utc": "string", + "period": "string", + "period_utc": "string", + "fcrg": "integer", + "fcrd": "integer", + "frrg": "integer", + "frrd": "integer", + "afrrg": "integer", + "afrrd": "integer", + "rrg": "integer", + "rrd": "integer", + "publication_ts": "string", + "publication_ts_utc": "string", + "business_date": "string", + }, + date_column="business_date", + meta_columns=( + "dtime", + "dtime_utc", + "period", + "period_utc", + "business_date", + "publication_ts", + "publication_ts_utc", + ), + keys=("dtime_utc",), + ), + "wsp-wrm": EndpointSpec( + columns={ + "dtime": "string", + "dtime_utc": "string", + "period": "string", + "period_utc": "string", + "az": "number", + "afw": "number", + "apv": "number", + "ws": "number", + "wmb_max": "number", + "business_date": "string", + "publication_ts": "string", + "publication_ts_utc": "string", + "ojnz_id": "string", + }, + date_column="business_date", + meta_columns=( + "dtime", + "dtime_utc", + "period", + "period_utc", + "business_date", + "publication_ts", + "publication_ts_utc", + ), + keys=("dtime_utc",), + ), + "zeb-rozl": EndpointSpec( + columns={ + "dtime": "string", + "dtime_utc": "string", + "period": "string", + "period_utc": "string", + "zebpp": "number", + "pzeb_afrrg_cost": "number", + "pzeb_afrrd_cost": "number", + "business_date": "string", + "publication_ts": "string", + "publication_ts_utc": "string", + }, + date_column="business_date", + meta_columns=( + "dtime", + "dtime_utc", + "period", + "period_utc", + "business_date", + "publication_ts", + "publication_ts_utc", + ), + keys=("dtime",), + ), + "zmb": EndpointSpec( + columns={ + "dtime": "string", + "dtime_utc": "string", + "period": "string", + "period_utc": "string", + "zmb_fcrg": "number", + "zmb_fcrd": "number", + "zmb_frrg": "number", + "zmb_frrd": "number", + "zmb_afrrg": "number", + "zmb_afrrd": "number", + "zmb_rrg": "number", + "zmb_rrd": "number", + "publication_ts": "string", + "publication_ts_utc": "string", + "business_date": "string", + }, + date_column="business_date", + meta_columns=( + "dtime", + "dtime_utc", + "period", + "period_utc", + "business_date", + "publication_ts", + "publication_ts_utc", + ), + keys=("dtime_utc",), + ), +} diff --git a/src/pse_sdk/_validate.py b/src/pse_sdk/_validate.py new file mode 100644 index 0000000..be03618 --- /dev/null +++ b/src/pse_sdk/_validate.py @@ -0,0 +1,94 @@ +from __future__ import annotations + +import difflib +from collections.abc import Iterable + +from pse_sdk._registry import REGISTRY + + +def suggest(name: str, choices: Iterable[str]) -> str | None: + """Return the closest match to *name* in *choices*, or ``None``. + + *name* is lowercased first, so case is ignored (registry names are all + lowercase). A non-string *name* has no match. + """ + if not isinstance(name, str): + return None + matches = difflib.get_close_matches(name.lower(), choices, n=1) + return matches[0] if matches else None + + +def validate_endpoint(endpoint: str) -> None: + """Raise ``ValueError`` if *endpoint* is not in the registry. + + A non-string *endpoint* is unknown; the message names its type. + """ + if isinstance(endpoint, str): + if endpoint in REGISTRY: + return + match = suggest(endpoint, REGISTRY) + hint = f"Did you mean {match!r}?" if match else "See PSEClient.endpoints()." + else: + hint = f"Endpoint must be a str, got {type(endpoint).__name__}." + raise ValueError(f"Unknown endpoint {endpoint!r}. {hint}") + + +def validate_columns(endpoint: str, columns: list[str] | None) -> None: + """Raise if any of *columns* is not a column of *endpoint*. + + Meta columns count, so requesting them explicitly is fine. ``None`` + (all columns) always passes. *endpoint* must already be validated. + + Raises: + TypeError: If *columns* is not a list or tuple, or holds a non-string. + ValueError: If a column is unknown. The message names every unknown + column with a hint. + """ + if columns is None: + return + _check_types(columns) + known = REGISTRY[endpoint].columns + unknown = list(dict.fromkeys(c for c in columns if c not in known)) + if unknown: + raise ValueError(_unknown_columns_message(endpoint, unknown)) + + +def _check_types(columns: list[str]) -> None: + """Raise ``TypeError`` unless *columns* is a list or tuple of strings.""" + if not isinstance(columns, (list, tuple)): + raise TypeError( + f"columns must be a list of column names, got {type(columns).__name__}" + ) + for column in columns: + if not isinstance(column, str): + raise TypeError(f"column names must be str, got {type(column).__name__}") + + +def _unknown_columns_message(endpoint: str, unknown: list[str]) -> str: + hints = [_column_hint(endpoint, column) for column in unknown] + items = ", ".join( + f"{column!r} ({hint})" if hint else repr(column) + for column, hint in zip(unknown, hints) + ) + noun = "column" if len(unknown) == 1 else "columns" + message = f"Unknown {noun} for endpoint {endpoint!r}: {items}." + if None in hints: + message += f" See PSEClient.columns({endpoint!r})." + return message + + +def _column_hint(endpoint: str, column: str) -> str | None: + """Return a hint for unknown *column* of *endpoint*, or ``None``. + + Other endpoints with the exact column (as a data column) win over a close + match in *endpoint*. + """ + elsewhere = [ + name + for name, spec in REGISTRY.items() + if column in spec.columns and column not in spec.meta_columns + ] + if elsewhere: + return f"found in: {', '.join(elsewhere)}" + match = suggest(column, REGISTRY[endpoint].columns) + return f"did you mean {match!r}?" if match else None diff --git a/tests/conftest.py b/tests/conftest.py index ecbb9ad..5f721e5 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,12 +1,9 @@ -from unittest.mock import MagicMock, patch +from unittest.mock import patch import pytest @pytest.fixture() -def mock_client(): - with ( - patch("pse_sdk._client.HTTPClient") as mock_http, - patch("pse_sdk._client.make_endpoint", return_value=MagicMock()) as mock_make, - ): - yield mock_http, mock_make +def mock_http(): + with patch("pse_sdk._client.HTTPClient") as mock_http: + yield mock_http diff --git a/tests/manual_test.py b/tests/manual_test.py index d8410b3..b93b01b 100644 --- a/tests/manual_test.py +++ b/tests/manual_test.py @@ -2,6 +2,12 @@ client = PSEClient() -resp = client.get_demand(start="2026-01-01", end="2026-01-02", format="dataframe") +resp = client.fetch( + "his-wlk-cal", + start="2026-01-01", + end="2026-01-02", + columns=["demand", "pv"], + format="dataframe", +) print(resp) diff --git a/tests/test_client.py b/tests/test_client.py index 25dac25..2c56d7d 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -1,44 +1,12 @@ -from pse_sdk._client import PSEClient +import pandas as pd +import pytest -EXPECTED_ENDPOINTS = [ - ("get_cen", "price-cost", ["cen_cost"]), - ("get_ckoeb", "price-cost", ["ckoeb_cost"]), - ("get_ceb_sr", "price-cost", ["ceb_sr_cost"]), - ("get_cor_pp", "price-cost", ["cor_pp_cost"]), - ("get_imb_energy", "price-cost", ["imb_energy"]), - ("get_contracting", "price-cost", ["contracting"]), - ("get_csdac", "csdac-pln", ["csdac_pln"]), - ("get_kb", "krb-rozl", ["kb"]), - ("get_ko", "krb-rozl", ["ko"]), - ("get_kcz", "krb-rozl", ["kcz"]), - ("get_kmb", "kmb-kro-rozl", ["kmb"]), - ("get_kro", "kmb-kro-rozl", ["kro"]), - ("get_sk_d1_fcst", "sk", ["sk_d1_fcst"]), - ("get_sk_d_fcst", "sk", ["sk_d_fcst"]), - ("get_sk_cost", "sk", ["sk_cost"]), - ("get_demand", "his-wlk-cal", ["demand"]), - ("get_swm_p", "his-wlk-cal", ["swm_p"]), - ("get_swm_np", "his-wlk-cal", ["swm_np"]), - ("get_jg", "his-wlk-cal", ["jg"]), - ("get_jgw1", "his-wlk-cal", ["jgw1"]), - ("get_jgw2", "his-wlk-cal", ["jgw2"]), - ("get_jgm1", "his-wlk-cal", ["jgm1"]), - ("get_jgm2", "his-wlk-cal", ["jgm2"]), - ("get_jgz1", "his-wlk-cal", ["jgz1"]), - ("get_jgz2", "his-wlk-cal", ["jgz2"]), - ("get_jgz3", "his-wlk-cal", ["jgz3"]), - ("get_jga", "his-wlk-cal", ["jga"]), - ("get_jgo", "his-wlk-cal", ["jgo"]), - ("get_jnwrb", "his-wlk-cal", ["jnwrb"]), - ("get_jgm", "his-wlk-cal", ["jgm"]), - ("get_wi", "his-wlk-cal", ["wi"]), - ("get_pv", "his-wlk-cal", ["pv"]), -] +from pse_sdk._client import PSEClient +from pse_sdk._registry import REGISTRY class TestPSEClient: - def test_default_timeout(self, mock_client): - mock_http, mock_make = mock_client + def test_default_timeout(self, mock_http): PSEClient() mock_http.assert_called_once_with( base_url="https://api.raporty.pse.pl/api", @@ -46,8 +14,7 @@ def test_default_timeout(self, mock_client): timeout=30, ) - def test_custom_timeout(self, mock_client): - mock_http, mock_make = mock_client + def test_custom_timeout(self, mock_http): PSEClient(timeout=60) mock_http.assert_called_once_with( base_url="https://api.raporty.pse.pl/api", @@ -55,24 +22,151 @@ def test_custom_timeout(self, mock_client): timeout=60, ) - def test_all_endpoints_created(self, mock_client): - pse = PSEClient() - for name, _, _ in EXPECTED_ENDPOINTS: - assert callable(getattr(pse, name)) - def test_make_endpoint_call_count(self, mock_client): - _, mock_make = mock_client - PSEClient() - assert mock_make.call_count == len(EXPECTED_ENDPOINTS) +class TestEndpoints: + def test_all_registry_endpoints_sorted(self): + assert PSEClient.endpoints() == sorted(REGISTRY) - def test_endpoint_paths(self, mock_client): - _, mock_make = mock_client - PSEClient() - paths = [call.kwargs["path"] for call in mock_make.call_args_list] - assert paths == [path for _, path, _ in EXPECTED_ENDPOINTS] + def test_callable_on_instance(self, mock_http): + assert PSEClient().endpoints() == PSEClient.endpoints() - def test_endpoint_columns(self, mock_client): - _, mock_make = mock_client - PSEClient() - columns = [call.kwargs["columns"] for call in mock_make.call_args_list] - assert columns == [cols for _, _, cols in EXPECTED_ENDPOINTS] + def test_returns_new_list(self): + PSEClient.endpoints().clear() + assert PSEClient.endpoints() + + +class TestColumns: + def test_data_columns_in_api_order(self): + assert PSEClient.columns("price-cost") == [ + "cen_cost", + "ckoeb_cost", + "ceb_sr_cost", + "cor_pp_cost", + "imb_energy", + "contracting", + ] + + def test_key_columns_included(self): + assert {"resource_code", "operating_mode"} <= set(PSEClient.columns("gen-jw")) + + def test_callable_on_instance(self, mock_http): + assert PSEClient().columns("price-cost") == PSEClient.columns("price-cost") + + def test_unknown_endpoint_raises(self): + with pytest.raises(ValueError, match="Unknown endpoint 'nope'"): + PSEClient.columns("nope") + + def test_unknown_endpoint_suggests(self): + with pytest.raises(ValueError, match="Did you mean 'price-cost'"): + PSEClient.columns("price-cots") + + @pytest.mark.parametrize("endpoint", [["price-cost"], {"price-cost": 1}]) + def test_non_str_endpoint_raises(self, endpoint): + with pytest.raises(ValueError, match="Endpoint must be a str"): + PSEClient.columns(endpoint) + + @pytest.mark.parametrize("name", REGISTRY) + def test_registry_columns_no_meta(self, name): + columns = PSEClient.columns(name) + assert columns + assert not set(columns) & set(REGISTRY[name].meta_columns) + + +@pytest.fixture() +def pse(mock_http): + client = PSEClient() + client.client.fetch_all.return_value = [] + return client + + +class TestFetch: + def test_select_meta_keys_and_columns(self, pse): + pse.fetch( + "price-cost", "2024-01-01", "2024-01-15", columns=["cen_cost", "ckoeb_cost"] + ) + assert pse.client.fetch_all.call_count == 1 + assert pse.client.fetch_all.call_args.args == ("price-cost",) + assert pse.client.fetch_all.call_args.kwargs["select"] == [ + *REGISTRY["price-cost"].meta_columns, + "cen_cost", + "ckoeb_cost", + ] + + def test_select_includes_keys(self, pse): + pse.fetch("gen-jw", "2024-01-01", "2024-01-15", columns=[]) + select = pse.client.fetch_all.call_args.kwargs["select"] + assert {"resource_code", "operating_mode"} <= set(select) + + def test_columns_none_selects_all(self, pse): + pse.fetch("price-cost", "2024-01-01", "2024-01-15") + assert pse.client.fetch_all.call_args.kwargs["select"] is None + + def test_filter_on_date_column(self, pse): + pse.fetch("price-cost", "2024-01-01", "2024-01-30") + filter_expr = pse.client.fetch_all.call_args.kwargs["filter_expr"] + assert ( + filter_expr + == "business_date ge '2024-01-01' and business_date le '2024-01-30'" + ) + + def test_long_range_chunked(self, pse): + pse.fetch("price-cost", "2024-01-01", "2024-02-29") + filters = [c.kwargs["filter_expr"] for c in pse.client.fetch_all.call_args_list] + assert filters == [ + "business_date ge '2024-01-01' and business_date le '2024-01-30'", + "business_date ge '2024-01-31' and business_date le '2024-02-29'", + ] + + def test_chunked_results_combined(self, pse): + pse.client.fetch_all.side_effect = [[{"a": 1}], [{"a": 2}]] + result = pse.fetch("price-cost", "2024-01-01", "2024-02-29") + assert result == [{"a": 1}, {"a": 2}] + + def test_dataframe_format(self, pse): + pse.client.fetch_all.side_effect = [[{"a": 1}], [{"a": 2}]] + result = pse.fetch("price-cost", "2024-01-01", "2024-02-29", format="dataframe") + assert isinstance(result, pd.DataFrame) + assert len(result) == 2 + + def test_invalid_format_raises_before_request(self, pse): + with pytest.raises(ValueError, match="format must be"): + pse.fetch("price-cost", "2024-01-01", "2024-01-30", format="df") + pse.client.fetch_all.assert_not_called() + + def test_head_endpoint_filters_on_period(self, pse): + pse.fetch("ogr-d1-head", "2024-01-01", "2024-01-30") + filter_expr = pse.client.fetch_all.call_args.kwargs["filter_expr"] + assert filter_expr == "period ge '2024-01-01' and period le '2024-01-30'" + + def test_unknown_endpoint_raises_before_request(self, pse): + with pytest.raises(ValueError, match="Unknown endpoint 'nope'"): + pse.fetch("nope", "2024-01-01", "2024-01-30") + pse.client.fetch_all.assert_not_called() + + def test_unknown_endpoint_suggests(self, pse): + with pytest.raises(ValueError, match="Did you mean 'price-cost'"): + pse.fetch("price-cots", "2024-01-01", "2024-01-30") + + @pytest.mark.parametrize("endpoint", [["price-cost"], {"price-cost": 1}]) + def test_non_str_endpoint_raises_before_request(self, pse, endpoint): + with pytest.raises(ValueError, match="Endpoint must be a str"): + pse.fetch(endpoint, "2024-01-01", "2024-01-30") + pse.client.fetch_all.assert_not_called() + + def test_unknown_column_raises_before_request(self, pse): + with pytest.raises( + ValueError, + match="Unknown column for endpoint 'price-cost': 'cen_cots'.*'cen_cost'", + ): + pse.fetch("price-cost", "2024-01-01", "2024-01-30", columns=["cen_cots"]) + pse.client.fetch_all.assert_not_called() + + def test_str_columns_raises_before_request(self, pse): + with pytest.raises(TypeError, match="columns must be a list"): + pse.fetch("price-cost", "2024-01-01", "2024-01-30", columns="cen_cost") + pse.client.fetch_all.assert_not_called() + + def test_invalid_date_range_raises_before_request(self, pse): + with pytest.raises(ValueError, match="must not be after"): + pse.fetch("price-cost", "2024-02-01", "2024-01-01") + pse.client.fetch_all.assert_not_called() diff --git a/tests/test_date.py b/tests/test_date.py index 16f4c92..f098c5c 100644 --- a/tests/test_date.py +++ b/tests/test_date.py @@ -31,10 +31,16 @@ def test_impossible_date(self): class TestNormalizeDateRange: def test_equal_dates_pass(self): - assert normalize_date_range("2024-01-01", "2024-01-01") == ("2024-01-01", "2024-01-01") + assert normalize_date_range("2024-01-01", "2024-01-01") == ( + "2024-01-01", + "2024-01-01", + ) def test_start_before_end_pass(self): - assert normalize_date_range("2024-01-01", "2024-01-31") == ("2024-01-01", "2024-01-31") + assert normalize_date_range("2024-01-01", "2024-01-31") == ( + "2024-01-01", + "2024-01-31", + ) def test_start_after_end_raises(self): with pytest.raises(ValueError, match="must not be after"): diff --git a/tests/test_docs.py b/tests/test_docs.py new file mode 100644 index 0000000..e941e56 --- /dev/null +++ b/tests/test_docs.py @@ -0,0 +1,85 @@ +from gen_docs import HEADER, KEYS_HEADER, OUTPUT, natural_key, render +from pse_sdk._endpoint_spec import EndpointSpec +from pse_sdk._registry import REGISTRY + +SPEC = { + "price-cost": EndpointSpec( + columns={ + "cen_cost": "number", + "contracting": "string", + "dtime": "string", + "business_date": "string", + }, + date_column="business_date", + meta_columns=("dtime", "business_date"), + keys=("dtime",), + ), + "csire-kpi10": EndpointSpec( + columns={"kpi": "number"}, date_column="business_date", meta_columns=(), keys=() + ), + "csire-kpi2": EndpointSpec( + columns={"kpi": "number"}, date_column="business_date", meta_columns=(), keys=() + ), +} + + +def _rows(source: str) -> list[str]: + return source.removeprefix(HEADER).split(KEYS_HEADER)[0].splitlines() + + +def _key_rows(source: str) -> list[str]: + return source.split(KEYS_HEADER)[1].splitlines() + + +class TestNaturalKey: + def test_digits_compared_numerically(self): + names = ["csire-kpi10", "csire-kpi2", "csire-kpi1"] + assert sorted(names, key=natural_key) == [ + "csire-kpi1", + "csire-kpi2", + "csire-kpi10", + ] + + def test_otherwise_alphabetical(self): + names = ["ogr-d1-head", "ogr-b", "ogr-d1", "cor-q-1", "cor"] + assert sorted(names, key=natural_key) == sorted(names) + + +class TestRender: + def test_header(self): + assert render(SPEC).startswith(HEADER) + + def test_endpoints_natural_order(self): + endpoints = [row.split("`")[1] for row in _rows(render(SPEC))] + assert list(dict.fromkeys(endpoints)) == [ + "csire-kpi2", + "csire-kpi10", + "price-cost", + ] + + def test_data_columns_only_in_api_order(self): + rows = _rows(render({"price-cost": SPEC["price-cost"]})) + assert rows == [ + "| `price-cost` | `cen_cost` | number |", + "| `price-cost` | `contracting` | string |", + ] + + def test_key_rows(self): + assert _key_rows(render(SPEC)) == [ + "| `csire-kpi2` | `business_date` | - |", + "| `csire-kpi10` | `business_date` | - |", + "| `price-cost` | `business_date` | `dtime` |", + ] + + +class TestCommittedDocs: + def test_up_to_date(self): + assert OUTPUT.read_text(encoding="utf-8") == render(REGISTRY) + + def test_all_endpoints_listed(self): + endpoints = {row.split("`")[1] for row in _rows(render(REGISTRY))} + assert endpoints == set(REGISTRY) + + def test_all_endpoints_in_key_table(self): + endpoints = [row.split("`")[1] for row in _key_rows(render(REGISTRY))] + assert sorted(endpoints) == sorted(REGISTRY) diff --git a/tests/test_endpoints.py b/tests/test_endpoints.py deleted file mode 100644 index 8cfb638..0000000 --- a/tests/test_endpoints.py +++ /dev/null @@ -1,99 +0,0 @@ -from unittest.mock import MagicMock - -import pandas as pd -import pytest - -from pse_sdk._endpoints import COMMON_COLUMNS, make_endpoint - - -class TestMakeEndpoint: - def test_returns_callable(self): - client = MagicMock() - result = make_endpoint(client, "price-cost") - assert callable(result) - - def test_select_with_columns(self): - client = MagicMock() - client.fetch_all.return_value = [] - fn = make_endpoint(client, "price-cost", columns=["cen_cost"]) - fn("2024-01-01", "2024-01-30") - call_kwargs = client.fetch_all.call_args - assert call_kwargs.kwargs["select"] == COMMON_COLUMNS + ["cen_cost"] - - def test_select_none_without_columns(self): - client = MagicMock() - client.fetch_all.return_value = [] - fn = make_endpoint(client, "price-cost") - fn("2024-01-01", "2024-01-30") - call_kwargs = client.fetch_all.call_args - assert call_kwargs.kwargs["select"] is None - - def test_common_columns_not_mutated(self): - original = list(COMMON_COLUMNS) - client = MagicMock() - make_endpoint(client, "price-cost", columns=["extra"]) - assert COMMON_COLUMNS == original - - -class TestEndpointFetch: - def test_filter_expr_built_correctly(self): - client = MagicMock() - client.fetch_all.return_value = [] - fn = make_endpoint(client, "price-cost", columns=["cen_cost"]) - fn("2024-01-01", "2024-01-30") - filter_expr = client.fetch_all.call_args.kwargs["filter_expr"] - assert filter_expr == "business_date ge '2024-01-01' and business_date le '2024-01-30'" - - def test_dict_format_returns_list(self): - client = MagicMock() - client.fetch_all.return_value = [{"a": 1}] - fn = make_endpoint(client, "price-cost") - result = fn("2024-01-01", "2024-01-30", format="dict") - assert isinstance(result, list) - - def test_dataframe_format_returns_df(self): - client = MagicMock() - client.fetch_all.return_value = [{"a": 1}] - fn = make_endpoint(client, "price-cost") - result = fn("2024-01-01", "2024-01-30", format="dataframe") - assert isinstance(result, pd.DataFrame) - - def test_invalid_dates_propagate(self): - client = MagicMock() - fn = make_endpoint(client, "price-cost") - with pytest.raises(ValueError): - fn("2024-02-01", "2024-01-01") - - -class TestChunkedFetch: - def test_short_range_single_call(self): - client = MagicMock() - client.fetch_all.return_value = [{"a": 1}] - fn = make_endpoint(client, "price-cost", columns=["cen_cost"]) - fn("2024-01-01", "2024-01-15") - assert client.fetch_all.call_count == 1 - - def test_long_range_multiple_calls(self): - client = MagicMock() - client.fetch_all.return_value = [] - fn = make_endpoint(client, "price-cost", columns=["cen_cost"]) - fn("2024-01-01", "2024-02-29") - assert client.fetch_all.call_count == 2 - filters = [c.kwargs["filter_expr"] for c in client.fetch_all.call_args_list] - assert filters[0] == "business_date ge '2024-01-01' and business_date le '2024-01-30'" - assert filters[1] == "business_date ge '2024-01-31' and business_date le '2024-02-29'" - - def test_chunked_results_combined(self): - client = MagicMock() - client.fetch_all.side_effect = [[{"a": 1}], [{"a": 2}]] - fn = make_endpoint(client, "price-cost") - result = fn("2024-01-01", "2024-02-29") - assert result == [{"a": 1}, {"a": 2}] - - def test_chunked_results_combined_dataframe(self): - client = MagicMock() - client.fetch_all.side_effect = [[{"a": 1}], [{"a": 2}]] - fn = make_endpoint(client, "price-cost") - result = fn("2024-01-01", "2024-02-29", format="dataframe") - assert isinstance(result, pd.DataFrame) - assert len(result) == 2 diff --git a/tests/test_http.py b/tests/test_http.py index 8b6eb41..c075443 100644 --- a/tests/test_http.py +++ b/tests/test_http.py @@ -63,6 +63,42 @@ def test_http_error_raises(self): c = HTTPClient(BASE_URL, 10, 5) with pytest.raises(requests.exceptions.HTTPError): c.fetch("data") + assert len(responses.calls) == 1 + + @responses.activate + def test_http_error_includes_api_message(self): + responses.get( + f"{BASE_URL}/data", + status=400, + json={ + "error": { + "code": "BadRequest", + "message": "Invalid field to be returned requested: x", + "status": 400, + } + }, + ) + c = HTTPClient(BASE_URL, 10, 5) + with pytest.raises(requests.exceptions.HTTPError) as exc: + c.fetch("data") + assert str(exc.value) == ( + f"400 Client Error: Bad Request for url: {BASE_URL}/data: " + "Invalid field to be returned requested: x" + ) + assert exc.value.response.status_code == 400 + + @responses.activate + @pytest.mark.parametrize( + "body", [{"body": "Bad Request"}, {"json": {"detail": "x"}}] + ) + def test_http_error_without_api_message_unchanged(self, body): + responses.get(f"{BASE_URL}/data", status=400, **body) + c = HTTPClient(BASE_URL, 10, 5) + with pytest.raises(requests.exceptions.HTTPError) as exc: + c.fetch("data") + assert ( + str(exc.value) == f"400 Client Error: Bad Request for url: {BASE_URL}/data" + ) class TestFetchAll: @@ -179,3 +215,57 @@ def test_retry_on_other_server_errors(self, mock_sleep, status): c = HTTPClient(BASE_URL, 10, 5) result = c.fetch_all("data") assert result == [{"a": 1}, {"a": 2}] + + @responses.activate + @patch("pse_sdk._http.time.sleep") + def test_first_page_retry_on_503_then_success(self, mock_sleep): + responses.get(f"{BASE_URL}/data", status=503) + responses.get(f"{BASE_URL}/data", json={"value": [{"a": 1}]}) + + c = HTTPClient(BASE_URL, 10, 5) + result = c.fetch_all("data") + assert result == [{"a": 1}] + mock_sleep.assert_called_once_with(1) + + @responses.activate + @patch("pse_sdk._http.time.sleep") + def test_first_page_retry_exhaustion_raises(self, mock_sleep): + for _ in range(4): + responses.get(f"{BASE_URL}/data", status=500) + + c = HTTPClient(BASE_URL, 10, 5) + with pytest.raises(requests.exceptions.HTTPError): + c.fetch_all("data") + assert mock_sleep.call_count == 3 + + @responses.activate + @patch("pse_sdk._http.time.sleep") + def test_retry_exhaustion_includes_api_message(self, mock_sleep): + for _ in range(4): + responses.get( + f"{BASE_URL}/data", + status=500, + json={"error": {"message": "DatabaseOperationFailed"}}, + ) + + c = HTTPClient(BASE_URL, 10, 5) + with pytest.raises( + requests.exceptions.HTTPError, + match=r"^500 Server Error.*: DatabaseOperationFailed$", + ): + c.fetch_all("data") + assert mock_sleep.call_count == 3 + + @responses.activate + @patch("pse_sdk._http.time.sleep") + def test_first_page_retry_keeps_query_params(self, mock_sleep): + responses.get(f"{BASE_URL}/data", status=503) + responses.get(f"{BASE_URL}/data", json={"value": []}) + + c = HTTPClient(BASE_URL, 25, 5) + c.fetch_all("data", select=["a", "b"], filter_expr="x eq 1") + assert len(responses.calls) == 2 + params = parse_qs(urlparse(responses.calls[1].request.url).query) + assert params["$first"] == ["25"] + assert params["$select"] == ["a,b"] + assert params["$filter"] == ["x eq 1"] diff --git a/tests/test_query.py b/tests/test_query.py new file mode 100644 index 0000000..531dcfa --- /dev/null +++ b/tests/test_query.py @@ -0,0 +1,81 @@ +import pytest + +from pse_sdk._endpoint_spec import EndpointSpec +from pse_sdk._query import build_select, data_columns, date_clauses, get_spec +from pse_sdk._registry import REGISTRY + +SPEC = EndpointSpec( + columns={ + "node": "string", + "value": "number", + "other": "number", + "dtime": "string", + "dtime_utc": "string", + "business_date": "string", + }, + date_column="business_date", + meta_columns=("dtime", "dtime_utc", "business_date"), + keys=("dtime_utc", "node"), +) + + +class TestGetSpec: + def test_known_endpoint(self): + assert get_spec("price-cost") is REGISTRY["price-cost"] + + def test_unknown_endpoint_raises(self): + with pytest.raises(ValueError, match="Unknown endpoint 'nope'"): + get_spec("nope") + + +class TestDataColumns: + def test_meta_dropped_api_order_kept(self): + assert data_columns(SPEC) == ["node", "value", "other"] + + +class TestBuildSelect: + def test_none_selects_all(self): + assert build_select(SPEC, None) is None + + def test_meta_then_keys_then_columns(self): + assert build_select(SPEC, ["value", "other"]) == [ + "dtime", + "dtime_utc", + "business_date", + "node", + "value", + "other", + ] + + def test_duplicates_dropped(self): + assert build_select(SPEC, ["node", "business_date", "value", "value"]) == [ + "dtime", + "dtime_utc", + "business_date", + "node", + "value", + ] + + def test_empty_columns_selects_meta_and_keys(self): + assert build_select(SPEC, []) == ["dtime", "dtime_utc", "business_date", "node"] + + def test_unknown_column_passed_through(self): + assert build_select(SPEC, ["typo"])[-1] == "typo" + + def test_columns_not_mutated(self): + columns = ["value"] + build_select(SPEC, columns) + assert columns == ["value"] + + +@pytest.mark.parametrize("name", REGISTRY) +def test_registry_select_only_existing_columns(name): + spec = REGISTRY[name] + assert set(build_select(spec, [])) <= set(spec.columns) + + +def test_date_clauses(): + assert date_clauses("business_date", "2024-01-01", "2024-01-30") == [ + "business_date ge '2024-01-01'", + "business_date le '2024-01-30'", + ] diff --git a/tests/test_registry.py b/tests/test_registry.py new file mode 100644 index 0000000..fcf509f --- /dev/null +++ b/tests/test_registry.py @@ -0,0 +1,182 @@ +import typing + +import pytest + +from gen_registry import build_registry, date_column, parse_keys, render +from pse_sdk._registry import REGISTRY, Endpoint + + +def _props(**types): + return {col: {"type": type_, "format": ""} for col, type_ in types.items()} + + +SPEC = { + "info": {"version": "1.0"}, + "paths": { + "/price-cost": {}, + "/price-cost/dtime_utc/{dtime_utc}": {}, + "/unav-pk5l": {}, + "/unav-pk5l/unit_code/{unit_code}/start_dtime_utc/{start_dtime_utc}": {}, + "/ogr-d1-head": {}, + "/ogr-d1-head/period/{period}": {}, + }, + "components": { + "schemas": { + "price-cost": { + "type": "object", + "properties": _props( + cen_cost="number", + contracting="string", + publication_ts="string", + business_date="string", + dtime_utc="string", + dtime="string", + ), + }, + "unav-pk5l": { + "type": "object", + "properties": _props( + unit_code="string", + start_dtime_utc="string", + business_date="string", + ), + }, + "ogr-d1-head": { + "type": "object", + "properties": _props(title="string", period="string"), + }, + } + }, +} + + +class TestParseKeys: + def test_single_key(self): + assert parse_keys(SPEC["paths"])["price-cost"] == ("dtime_utc",) + + def test_composite_key(self): + keys = parse_keys(SPEC["paths"]) + assert keys["unav-pk5l"] == ("unit_code", "start_dtime_utc") + + def test_collection_paths_ignored(self): + assert set(parse_keys(SPEC["paths"])) == { + "price-cost", + "unav-pk5l", + "ogr-d1-head", + } + + +class TestBuildRegistry: + def test_endpoints_sorted(self): + assert list(build_registry(SPEC)) == ["ogr-d1-head", "price-cost", "unav-pk5l"] + + def test_columns_keep_spec_order_and_types(self): + columns = build_registry(SPEC)["price-cost"]["columns"] + assert list(columns) == [ + "cen_cost", + "contracting", + "publication_ts", + "business_date", + "dtime_utc", + "dtime", + ] + assert columns["cen_cost"] == "number" + assert columns["contracting"] == "string" + + def test_date_column_business_date(self): + assert build_registry(SPEC)["price-cost"]["date_column"] == "business_date" + + def test_date_column_period_key(self): + assert build_registry(SPEC)["ogr-d1-head"]["date_column"] == "period" + + def test_business_date_wins_over_period_key(self): + columns = {"period": "string", "business_date": "string"} + assert date_column("x", columns, ("period",)) == "business_date" + + def test_unclassifiable_endpoint_raises(self): + with pytest.raises(ValueError, match="rcco2: no date column"): + date_column("rcco2", {"period": "string"}, ("dtime_utc",)) + + def test_meta_columns_fixed_order(self): + assert build_registry(SPEC)["price-cost"]["meta_columns"] == ( + "dtime", + "dtime_utc", + "business_date", + "publication_ts", + ) + + def test_utc_data_columns_not_meta(self): + meta = build_registry(SPEC)["unav-pk5l"]["meta_columns"] + assert meta == ("business_date",) + + def test_keys(self): + assert build_registry(SPEC)["unav-pk5l"]["keys"] == ( + "unit_code", + "start_dtime_utc", + ) + + +class TestRender: + def test_round_trip(self): + registry = build_registry(SPEC) + namespace: dict = {} + exec(render(registry, "1.0"), namespace) + spec_cls = namespace["EndpointSpec"] + assert namespace["REGISTRY"] == { + name: spec_cls(**entry) for name, entry in registry.items() + } + + def test_endpoint_literal(self): + namespace: dict = {} + exec(render(build_registry(SPEC), "1.0"), namespace) + assert typing.get_args(namespace["Endpoint"]) == ( + "ogr-d1-head", + "price-cost", + "unav-pk5l", + ) + + def test_header_has_spec_version(self): + assert "(spec version 1.0)" in render(build_registry(SPEC), "1.0") + + +class TestCommittedRegistry: + def test_endpoint_literal_matches_registry(self): + assert typing.get_args(Endpoint) == tuple(REGISTRY) + + def test_price_cost(self): + spec = REGISTRY["price-cost"] + assert spec.columns["cen_cost"] == "number" + assert spec.date_column == "business_date" + assert spec.keys == ("dtime_utc",) + + def test_rcco2_has_no_dtime(self): + assert "dtime" not in REGISTRY["rcco2"].meta_columns + + @pytest.mark.parametrize( + "name", + [ + "ogr-oper-head", + "ogr-d1-head", + "ogr-d2-head", + "ogr-d39-head", + "ogr-m-head", + "ogr-r-head", + ], + ) + def test_head_endpoints_filter_on_period(self, name): + assert REGISTRY[name].date_column == "period" + + +@pytest.mark.parametrize("name", REGISTRY) +class TestRegistryInvariants: + def test_meta_columns_are_columns(self, name): + spec = REGISTRY[name] + assert set(spec.meta_columns) <= set(spec.columns) + + def test_keys_are_columns(self, name): + spec = REGISTRY[name] + assert set(spec.keys) <= set(spec.columns) + + def test_date_column_is_column(self, name): + spec = REGISTRY[name] + assert spec.date_column in spec.columns diff --git a/tests/test_validate.py b/tests/test_validate.py new file mode 100644 index 0000000..616c609 --- /dev/null +++ b/tests/test_validate.py @@ -0,0 +1,125 @@ +import pytest + +from pse_sdk._registry import REGISTRY +from pse_sdk._validate import suggest, validate_columns, validate_endpoint + + +def error(func, *args) -> str: + with pytest.raises(ValueError) as exc: + func(*args) + return str(exc.value) + + +class TestSuggest: + def test_typo(self): + assert suggest("price-cots", REGISTRY) == "price-cost" + + def test_ignores_case(self): + assert suggest("CEN_COST", REGISTRY["price-cost"].columns) == "cen_cost" + + def test_no_match(self): + assert suggest("xyz", REGISTRY) is None + + +class TestValidateEndpoint: + def test_known(self): + validate_endpoint("price-cost") + + def test_typo_suggests(self): + assert error(validate_endpoint, "price-cots") == ( + "Unknown endpoint 'price-cots'. Did you mean 'price-cost'?" + ) + + def test_no_match_points_to_endpoints(self): + assert error(validate_endpoint, "xyz") == ( + "Unknown endpoint 'xyz'. See PSEClient.endpoints()." + ) + + @pytest.mark.parametrize( + ("endpoint", "type_name"), + [ + (None, "NoneType"), + (5, "int"), + (["price-cost"], "list"), + ({"price-cost": 1}, "dict"), + ], + ) + def test_non_str(self, endpoint, type_name): + assert error(validate_endpoint, endpoint) == ( + f"Unknown endpoint {endpoint!r}. Endpoint must be a str, got {type_name}." + ) + + +class TestValidateColumns: + def test_none_passes(self): + validate_columns("price-cost", None) + + def test_empty_passes(self): + validate_columns("price-cost", []) + + def test_data_columns_pass(self): + validate_columns("price-cost", ["cen_cost", "ckoeb_cost"]) + + def test_meta_column_passes(self): + validate_columns("price-cost", ["dtime_utc"]) + + def test_tuple_passes(self): + validate_columns("price-cost", ("cen_cost",)) + + def test_typo_suggests(self): + assert error(validate_columns, "price-cost", ["cen_cots"]) == ( + "Unknown column for endpoint 'price-cost': " + "'cen_cots' (did you mean 'cen_cost'?)." + ) + + def test_typo_ignores_case(self): + assert error(validate_columns, "price-cost", ["CEN_COST"]).endswith( + "(did you mean 'cen_cost'?)." + ) + + def test_column_of_other_endpoints(self): + assert error(validate_columns, "kse-load", ["cen_cost"]) == ( + "Unknown column for endpoint 'kse-load': " + "'cen_cost' (found in: crb-rozl, energy-prices, price-cost)." + ) + + def test_no_match_points_to_columns(self): + assert error(validate_columns, "price-cost", ["foo"]) == ( + "Unknown column for endpoint 'price-cost': 'foo'. " + "See PSEClient.columns('price-cost')." + ) + + def test_all_unknown_named_once(self): + assert error( + validate_columns, "price-cost", ["cen_cots", "foo", "cen_cost", "foo"] + ) == ( + "Unknown columns for endpoint 'price-cost': " + "'cen_cots' (did you mean 'cen_cost'?), 'foo'. " + "See PSEClient.columns('price-cost')." + ) + + def test_all_unknown_hinted(self): + assert error(validate_columns, "price-cost", ["cen_cots", "ckoeb_cots"]) == ( + "Unknown columns for endpoint 'price-cost': " + "'cen_cots' (did you mean 'cen_cost'?), " + "'ckoeb_cots' (did you mean 'ckoeb_cost'?)." + ) + + def test_meta_column_missing_on_endpoint(self): + message = error(validate_columns, "rcco2", ["dtime"]) + assert message.startswith("Unknown column for endpoint 'rcco2': 'dtime'") + assert "found in" not in message + + @pytest.mark.parametrize("columns", ["cen_cost", {"cen_cost"}, iter(["cen_cost"])]) + def test_not_list_raises(self, columns): + with pytest.raises(TypeError, match="columns must be a list of column names"): + validate_columns("price-cost", columns) + + def test_non_str_column_raises(self): + with pytest.raises(TypeError, match="column names must be str, got int"): + validate_columns("price-cost", ["cen_cost", 1]) + + +@pytest.mark.parametrize("name", sorted(REGISTRY)) +def test_registry_own_columns_pass(name): + validate_columns(name, list(REGISTRY[name].columns)) diff --git a/uv.lock b/uv.lock new file mode 100644 index 0000000..40e0b50 --- /dev/null +++ b/uv.lock @@ -0,0 +1,931 @@ +version = 1 +revision = 3 +requires-python = ">=3.10" +resolution-markers = [ + "python_full_version >= '3.14' and sys_platform == 'win32'", + "python_full_version >= '3.14' and sys_platform == 'emscripten'", + "python_full_version >= '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", + "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'win32'", + "python_full_version == '3.11.*' and sys_platform == 'win32'", + "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'emscripten'", + "python_full_version == '3.11.*' and sys_platform == 'emscripten'", + "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", + "python_full_version == '3.11.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", + "python_full_version < '3.11'", +] + +[[package]] +name = "certifi" +version = "2026.10.19" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a6/bd/1436c50cc46699de0230fbaacc1d1de7bfec413176099949e9d5112e88f2/certifi-2026.10.19.tar.gz", hash = "sha256:035c1e85572b141bf1c3a3eff0e33a8eb74917522f2559075ff8d2fea780a1ae", size = 137598, upload-time = "2026-10-20T02:24:16.604Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c4/51/29046e48f693c54e5b7412216d447a1d8362c9653148d98c02cdf65fa733/certifi-2026.10.19-py3-none-any.whl", hash = "sha256:42d35340cc5b9ba78e818ddbff0c5b1c2b779de448a340fd1b989f5fa8670e1b", size = 136464, upload-time = "2026-10-20T02:24:15.072Z" }, +] + +[[package]] +name = "charset-normalizer" +version = "3.5.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/33/1c/f41d4e74c28ab327ff3acd36053f7ea506c55872d7a90b0fa71aa3ab0c89/charset_normalizer-3.5.2.tar.gz", hash = "sha256:39de2a259fc954455c57274dc94c79d5842774e1247a016aff30bc0efed0f4ef", size = 172659, upload-time = "2026-09-30T04:39:23.398Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/98/77/46e87bcfc45d25ab4db7cfc9bb544bfa3ffd302289ed31ae93f5433eb899/charset_normalizer-3.5.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:195c26fb65950f8fce54e26349852b7bdd7c5f120aeefbcc440b8a20faaed4a3", size = 373348, upload-time = "2026-09-30T04:34:42.843Z" }, + { url = "https://files.pythonhosted.org/packages/52/fc/e518013affcc43c9f919c3ba41bffe9b4ee4aceb0a6462a6243efcca5f2d/charset_normalizer-3.5.2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9373ad13ef0d2c0fb761e04e55bfdee5a08b52cef2c882c8fbe9935b1517152e", size = 260860, upload-time = "2026-09-30T04:34:44.817Z" }, + { url = "https://files.pythonhosted.org/packages/d5/ad/2a895c945ee61988dfd9ccee64f0b78dc09f29c9b34d1dd545246d78e0ad/charset_normalizer-3.5.2-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:ddf19c062bea7a0cc80f519243d2c01dd091be0cf952a0750d4ad576709559f5", size = 246491, upload-time = "2026-09-30T04:34:46.227Z" }, + { url = "https://files.pythonhosted.org/packages/c9/05/5d958bc8ea503e26be25ada5430fd409cfb45dc22ff33f9f96e649613c99/charset_normalizer-3.5.2-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:3d14b50de6bf4d0edf857a9386836846f982b8f524e188e2e68b96d702bcf4aa", size = 290875, upload-time = "2026-09-30T04:34:47.691Z" }, + { url = "https://files.pythonhosted.org/packages/55/e2/06bad57dfdb49cad92c0ba85b6b4fa5827a67df37897287cfef0553843c2/charset_normalizer-3.5.2-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:28a15fdad492a99b6eccfaaed66ef3f74050680545ea61ec8b2f4c538f1f1320", size = 286987, upload-time = "2026-09-30T04:34:49.356Z" }, + { url = "https://files.pythonhosted.org/packages/c4/9f/9f52d2886d52645987d603425482c63c5045a3005db1354a7097e5ed1ae9/charset_normalizer-3.5.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8a893cc101149f80a653f82062ebc95b34525a2614382e1da5458fe7c6997249", size = 271105, upload-time = "2026-09-30T04:34:50.957Z" }, + { url = "https://files.pythonhosted.org/packages/4a/41/e05e19578b7b87e7db2c3ecb884bd09d065274ab41e1f535542e8bae9b06/charset_normalizer-3.5.2-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:619799369eeef6366ed3e8755a5670f4f2f0fb6b30a0fd7264dc0fdc2357058e", size = 269833, upload-time = "2026-09-30T04:34:52.623Z" }, + { url = "https://files.pythonhosted.org/packages/c2/cd/fc7152414561ff78f9c61a4a627025f65fd244abaefc99ac4e75c6169b33/charset_normalizer-3.5.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:447441e76ec720b15e64418d32e092297340387053047c7c694f579efb0ee1d9", size = 263048, upload-time = "2026-09-30T04:34:54.013Z" }, + { url = "https://files.pythonhosted.org/packages/71/71/fb379e399b1013962716a059d551e03bd80b3e02f05d81246886af6c0958/charset_normalizer-3.5.2-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:62588a277bfb59def052abd940703fa35107152bf479781a878617d60faf8fb5", size = 249237, upload-time = "2026-09-30T04:34:55.373Z" }, + { url = "https://files.pythonhosted.org/packages/33/4f/aeadccd6d20882909eb2597ec40eccc05d505e2262f14dc76d7620700657/charset_normalizer-3.5.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:44bd4fbb29dfbeba60e7d2bd000c59e4b21ddb3cc53912b14048d37092706d7c", size = 290756, upload-time = "2026-09-30T04:34:56.867Z" }, + { url = "https://files.pythonhosted.org/packages/b9/7b/e8a92613236b257d3b75d532496eb21f68ad8231d7d56df94497e460112e/charset_normalizer-3.5.2-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:30fcd120b732aa79317f08dee04d7de0847822e4cf7ee0e9f445bb958832252c", size = 269026, upload-time = "2026-09-30T04:34:58.278Z" }, + { url = "https://files.pythonhosted.org/packages/ff/ac/21d5c6b972285c5f095ff78afdc99f3539e3985dfcf7ff1cfbe9e772f529/charset_normalizer-3.5.2-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:50e3adfb96fc189eb27b1cf62d3b598b89b4bb0420d93a3d3e42e137409011be", size = 287601, upload-time = "2026-09-30T04:34:59.703Z" }, + { url = "https://files.pythonhosted.org/packages/59/72/263491ec1494a194b16fcbff88a0220f2af633738c79e92b4d7189226322/charset_normalizer-3.5.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b736353c0a625bbd5fcec108576e2385db3496f4f771f785ff32e108d3c3bc45", size = 272660, upload-time = "2026-09-30T04:35:01.26Z" }, + { url = "https://files.pythonhosted.org/packages/38/7a/81f1186c57e406233969ae96b5fd0c907254ab8b6e47da8ae24cd20fb9d7/charset_normalizer-3.5.2-cp310-cp310-win32.whl", hash = "sha256:f5833ad231be5eb6553de524a70f48d71b2c8563101750531e0b80184e175cd4", size = 187301, upload-time = "2026-09-30T04:35:02.659Z" }, + { url = "https://files.pythonhosted.org/packages/ae/ab/fb8b5178fdf7bf68efa61cbe892286bc9f73846f26147d4725fb89388475/charset_normalizer-3.5.2-cp310-cp310-win_amd64.whl", hash = "sha256:1461ac396c4fdb983a675f20aa555624f0ee18ac83d832b9244ffff3d8055275", size = 215446, upload-time = "2026-09-30T04:35:04.011Z" }, + { url = "https://files.pythonhosted.org/packages/36/40/e270b74e0d3f583d78d902960845a149e80eb7c737ee5613ccc6efc7264b/charset_normalizer-3.5.2-cp310-cp310-win_arm64.whl", hash = "sha256:c6708715abcf3c73b99508253e961a9967f02fe536532834149574eda6de0d1c", size = 203389, upload-time = "2026-09-30T04:35:05.577Z" }, + { url = "https://files.pythonhosted.org/packages/22/67/6a0b94a7960d5e1b5eacd2fb529f3fccc47db4644f7f0a7cfdcfc3be578a/charset_normalizer-3.5.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:3d21b8b13c7592db2ac5e544a6d83187b995257472b0c9e8351b6d507ae37ed6", size = 370642, upload-time = "2026-09-30T04:35:06.91Z" }, + { url = "https://files.pythonhosted.org/packages/fb/94/01009e13b94041599004edf32e56e382c24e570f60f79bab8efe45cfe1eb/charset_normalizer-3.5.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d760fe2a4d7c3b226cb9026d6a842868d52a7901bd98420e1baf14e80da85cf5", size = 259280, upload-time = "2026-09-30T04:35:08.448Z" }, + { url = "https://files.pythonhosted.org/packages/66/85/3b5358f60a13210f0b67d3755c168ef758701b021e655d88d4da28554467/charset_normalizer-3.5.2-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c9790464842f85f437dbbb54417eda1e0e6bfc52dd8d22d6fd1c994b73b2dc74", size = 245335, upload-time = "2026-09-30T04:35:10.104Z" }, + { url = "https://files.pythonhosted.org/packages/74/75/77c1c479b09ecd751d1e767b251ea5c14d4d50ff757bf404afab2692f600/charset_normalizer-3.5.2-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4685902cf26edf013ed7a3da0f426ebba7a00ebb9541386d835afbf002c11cab", size = 291707, upload-time = "2026-09-30T04:35:11.575Z" }, + { url = "https://files.pythonhosted.org/packages/0b/0d/363f78cacb70f58f15f4b083961bbd9d292f335d3f5c66fc4f1cfe69cb90/charset_normalizer-3.5.2-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4495c5002a7b28557e7e222e77e0b661183e432b7d6d2e788101e3f240e05b8c", size = 286747, upload-time = "2026-09-30T04:35:13.022Z" }, + { url = "https://files.pythonhosted.org/packages/e4/ed/cf505d3011ffceb12c2067a7a5d3cfe92b875d4d44bb0ff0d69375e2c184/charset_normalizer-3.5.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:211d5a3eb6af8f513b8d4ca19a8c1b7accab1b5f0d3175f9826b03c1a920dc1f", size = 269972, upload-time = "2026-09-30T04:35:14.606Z" }, + { url = "https://files.pythonhosted.org/packages/15/d8/f0a93a431d170e7ca681d4f6650fee3de934d18560e474e7267eb4b0f987/charset_normalizer-3.5.2-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ef4fcbf3327382cd4c9f540babd61248208af7b93eec4de397b4d5f58a09e288", size = 269339, upload-time = "2026-09-30T04:35:16.087Z" }, + { url = "https://files.pythonhosted.org/packages/86/bd/9b2bd1c5b7af02462c9752d33994834ff972a96b4c483eefde9e594488e2/charset_normalizer-3.5.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:bd16aabe4a02a297c23417aa17ac6299dbd8c49f673bcd645b4929b11f5a4400", size = 261683, upload-time = "2026-09-30T04:35:17.488Z" }, + { url = "https://files.pythonhosted.org/packages/76/a5/cac540ab0fd61f3fec88ad3dbb64509e71424593d73cfdfff5ab3e4db279/charset_normalizer-3.5.2-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:fb9e68df06293761f9fe66ade60a9bc6d0f5e42b8acf2939a9158af86ab0e5bd", size = 248143, upload-time = "2026-09-30T04:35:18.849Z" }, + { url = "https://files.pythonhosted.org/packages/71/7a/ff467301deef2089fad87f72df9e000a26a78fec7acbb18e1999371b8369/charset_normalizer-3.5.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:59f63901b0031c3136cf64704dcb21de0bbae62ce2c9529bc39d27665463de37", size = 292358, upload-time = "2026-09-30T04:35:20.326Z" }, + { url = "https://files.pythonhosted.org/packages/ad/77/22d7e785d1e210afc2e2f58600dd1799d17a35665faf84383f002826c5f8/charset_normalizer-3.5.2-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:304d5463e65a35d7bb0850550e0780395395f6fcf452f04db7d5ca7cecc425ac", size = 268766, upload-time = "2026-09-30T04:35:21.72Z" }, + { url = "https://files.pythonhosted.org/packages/ae/91/e8e946267f1c2d9e2bd651726e2fbd2addf02c4d36cea5069e32ca9d7bb5/charset_normalizer-3.5.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:9cf9b1a857e25c4baceeb3624e92a56df3668f398c4acba74e174d81fb4d1d3a", size = 287432, upload-time = "2026-09-30T04:35:23.273Z" }, + { url = "https://files.pythonhosted.org/packages/4e/88/7561d8a88d555e7df6623abe7c0070b4baf47549b9408783a2ae0a1a6cf7/charset_normalizer-3.5.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:114e4d0c92d618409ed82a99e22b5c5e768fe995f2973f78265f4524f49d4640", size = 272470, upload-time = "2026-09-30T04:35:24.655Z" }, + { url = "https://files.pythonhosted.org/packages/35/7e/578c702301ec036f01455f30744a08d2b42f6ab35b9b2d4bf8cae0ef2a80/charset_normalizer-3.5.2-cp311-cp311-win32.whl", hash = "sha256:2625388c6c754520c37abaf3b41eb34d1cc4a373f457898f08606c8e362b891d", size = 186688, upload-time = "2026-09-30T04:35:26.225Z" }, + { url = "https://files.pythonhosted.org/packages/e8/fc/fdf8cf52ff21cd5bf158f20978991cf985325842f74283eb6df26c8a39d8/charset_normalizer-3.5.2-cp311-cp311-win_amd64.whl", hash = "sha256:87e50a3e7cb90af586b6c5faf23e302a970415ac73bd7bd90a515a04b427ef96", size = 214932, upload-time = "2026-09-30T04:35:27.796Z" }, + { url = "https://files.pythonhosted.org/packages/97/66/3e45a506d8110b632541faf9a9470185aa9878f1ed44020f31346c1c5e5b/charset_normalizer-3.5.2-cp311-cp311-win_arm64.whl", hash = "sha256:254eb48b9fa5ee9898a3c445825a1f340fe53712a098904b39b0bddba8ea3cb1", size = 202828, upload-time = "2026-09-30T04:35:29.259Z" }, + { url = "https://files.pythonhosted.org/packages/e7/c8/693809898870237d82785a03f3b2b58fe4c9f14669f84a7d4e623c92a59e/charset_normalizer-3.5.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:ed2a239c0ea213acc1908150a3037257083c7c083128f1a4cec2ec4b97dca491", size = 367780, upload-time = "2026-09-30T04:35:30.888Z" }, + { url = "https://files.pythonhosted.org/packages/c9/87/2fea8c13dc24b3ca9c6f803a5b2dfdeae73eb4f9e12c7885ed908ff0433c/charset_normalizer-3.5.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b91363207bd9dc966a691e959bb47f64b30f7ac4b072be9968b366982f7db77c", size = 246730, upload-time = "2026-09-30T04:35:32.286Z" }, + { url = "https://files.pythonhosted.org/packages/a8/9e/09efac30b937722f46d3110ba30b875b24b2e3a266ed746cc4e376a94d80/charset_normalizer-3.5.2-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:38a873987f3be698494da8b2e3085e29da02da7b633dce73e79c699a113d7bf0", size = 237707, upload-time = "2026-09-30T04:35:33.709Z" }, + { url = "https://files.pythonhosted.org/packages/9e/18/70d76670b13686237863a379928d60bd10e021f17d243ab3d7014c4a5f4e/charset_normalizer-3.5.2-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:355ad8011081dec5412240c087a9a0c9d4d5039f3ed11a3f13e18c2b29b56c51", size = 273050, upload-time = "2026-09-30T04:35:35.138Z" }, + { url = "https://files.pythonhosted.org/packages/54/e2/77a8b09d5adc013ed07b95b01b8b8fa5441c4e810e83ee7e4aae2fa4d91a/charset_normalizer-3.5.2-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ee21e28f0430bd6dc9086c6e525d5e818a44a5ad19720c8a0ef766792f3eb5e5", size = 270345, upload-time = "2026-09-30T04:35:36.502Z" }, + { url = "https://files.pythonhosted.org/packages/7f/c5/38806a25ab5e65fc178f39affeda20858efafede2fce1ffc2556cfc9fe73/charset_normalizer-3.5.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3d31298449090ab8d47b7b1b2a555ff73cac7ed438a08b7ac160980c7ebed649", size = 257601, upload-time = "2026-09-30T04:35:37.919Z" }, + { url = "https://files.pythonhosted.org/packages/ae/8d/213565184708fdb263ae55e2c04ee1ff748129dd65d48ed0e3502da9c85a/charset_normalizer-3.5.2-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:5cde776b7cc66e4f6c99612cea4aa7269aa65863f7a15841b2c264f103822f4e", size = 252222, upload-time = "2026-09-30T04:35:39.544Z" }, + { url = "https://files.pythonhosted.org/packages/7e/24/76d2cefc25472531e4c5c7dfff68865eb1c39b78482f0fdc15b46f047830/charset_normalizer-3.5.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ae4f5fea5b8b8ccff88238cc8569303e5ee95efae67fa62922a311397a71f346", size = 248482, upload-time = "2026-09-30T04:35:41.088Z" }, + { url = "https://files.pythonhosted.org/packages/7d/dc/65a801b66ab4c197e22c433ab25e7ac24324ac6f45a2269aca42cce309bf/charset_normalizer-3.5.2-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:f7d486c83842422badd511868fd8a9a20e9407ace71564b6af47ce7e60a336c1", size = 241206, upload-time = "2026-09-30T04:35:42.59Z" }, + { url = "https://files.pythonhosted.org/packages/a7/95/ca9b5eabde673002c6f1e7ada1b223916fe18f6d661da7aabd4d643718f1/charset_normalizer-3.5.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:11a4d68a6ecda3292cb1e50239e111543ba5d709bb62a6b4ea1afcfa729d8875", size = 273190, upload-time = "2026-09-30T04:35:44.347Z" }, + { url = "https://files.pythonhosted.org/packages/2d/8b/803b4d2a3f6e1740f63f1e87b04d14b42f3d4fdfe6ed7d4db2d34102b14f/charset_normalizer-3.5.2-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:d6734d2ef8a50fbf8445c139477da401f50d62a0606bf00e20ec6d87773fefb1", size = 253527, upload-time = "2026-09-30T04:35:45.915Z" }, + { url = "https://files.pythonhosted.org/packages/a9/55/93c0e5dbd085ae0471346026abbe7e0db9ea2d6fea74e51f0b5a46f233a7/charset_normalizer-3.5.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:a815775b6c38d4e0ff7bcffbeba67feded90202bb6a226b8dd35f1c855217413", size = 271285, upload-time = "2026-09-30T04:35:47.49Z" }, + { url = "https://files.pythonhosted.org/packages/95/69/0dbd0e0b9b16cfa816cdfcb3e2e3854a1f680dc07fb1245ea125e7448060/charset_normalizer-3.5.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:23851fb4e1b85ed3f6c2a27b777cdfe2e19fb5b38429a8faf38c7542b7665869", size = 260010, upload-time = "2026-09-30T04:35:48.996Z" }, + { url = "https://files.pythonhosted.org/packages/58/9d/e7b88e7b1bf403590c3b573277b5e1e488c68c7a6fbacca310a2c324e90c/charset_normalizer-3.5.2-cp312-cp312-win32.whl", hash = "sha256:db19d07e2e0129e974a0e65d0064fc222a446cd5122c2fd4184d2af9fc734a9e", size = 184125, upload-time = "2026-09-30T04:35:50.777Z" }, + { url = "https://files.pythonhosted.org/packages/eb/e6/e6e083884cbcfd49c64865af05027fe7011be7b2d9179524f099a1b611f3/charset_normalizer-3.5.2-cp312-cp312-win_amd64.whl", hash = "sha256:780fbe7cab297b81dad9fb8dc5eb003c0468ffb0d9e5f65068c53a34661a96bc", size = 207486, upload-time = "2026-09-30T04:35:52.194Z" }, + { url = "https://files.pythonhosted.org/packages/c4/e3/017aea0911ada7405a825c7d937eb3a13009664e2f5b38e8c4bbf2abf894/charset_normalizer-3.5.2-cp312-cp312-win_arm64.whl", hash = "sha256:e2af3aad578aa6bd1384bcf4750fc285e5a9de53f40b7d41e5a0bf748edeb2b3", size = 196734, upload-time = "2026-09-30T04:35:53.636Z" }, + { url = "https://files.pythonhosted.org/packages/c5/34/68292d68512768591aaff07c59bb53ee31341c87759433a859c4641a50c2/charset_normalizer-3.5.2-cp313-cp313-android_24_arm64_v8a.whl", hash = "sha256:ed905975ab14056a2e5eb1c376cb2e1ebc5396baf84163939c518556fccde9f5", size = 225946, upload-time = "2026-09-30T04:35:55.313Z" }, + { url = "https://files.pythonhosted.org/packages/e3/80/bee0b01b90ccd5322ae1d0abb33fab1bd95b7c2eadaf02aeccf22e04ee83/charset_normalizer-3.5.2-cp313-cp313-android_24_x86_64.whl", hash = "sha256:a66c3bc5ab1f0ff2164fc9965ddd611ff0802173f4b9d24554c563f6ab7e1d6e", size = 238619, upload-time = "2026-09-30T04:35:56.863Z" }, + { url = "https://files.pythonhosted.org/packages/78/6e/60ce52a85a7fd631ae8482ae6d74521014ca2f255892679484dc04d7ef56/charset_normalizer-3.5.2-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:d2374b62878abb00cd8309b32af6c0b715cd02dec0ca74ef12e5069bdc64144a", size = 206701, upload-time = "2026-09-30T04:35:58.639Z" }, + { url = "https://files.pythonhosted.org/packages/36/8c/71aafad23f971afc84c2b295bc0c560739ce1dac558aad9fec22e39f3639/charset_normalizer-3.5.2-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:d376bbd28b3a8999db1a103b3b388aee6f1ddeb3e51bc2172993efdcd86e064d", size = 210506, upload-time = "2026-09-30T04:36:00.147Z" }, + { url = "https://files.pythonhosted.org/packages/91/da/3c5a7798c046df7d2d68ad653cf5b6c5a8bfee225055a843c6f2f42aac1a/charset_normalizer-3.5.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:6045373d5a89a5ec71afde535db987ca28e76dfa276c2d4c818265b375d4b055", size = 366626, upload-time = "2026-09-30T04:36:01.77Z" }, + { url = "https://files.pythonhosted.org/packages/e1/16/710ac3de2ee354e2bd1a9c94efe45a2d27b5c6ad39b2d6a905be2c094b6c/charset_normalizer-3.5.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:849df64e889b2e17230d58410a03dba311a65b163508fd33679b2b737d4b7858", size = 244624, upload-time = "2026-09-30T04:36:03.389Z" }, + { url = "https://files.pythonhosted.org/packages/d6/39/45c7439f5b63d24f7d5b2a1d760f34af7628782d7144b4cc8ded45c2d4bc/charset_normalizer-3.5.2-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:15c44f7edfd477b06f517a5cc317fc1707edb9de2c865f43d4b6513907473234", size = 235731, upload-time = "2026-09-30T04:36:04.987Z" }, + { url = "https://files.pythonhosted.org/packages/4d/34/38f3154785ce92e9f56eb226f4d35bdfae6b008480dd055f58837a89c810/charset_normalizer-3.5.2-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a89012d6d5476ee112d20d998570ed58df2260a852afb1758809cd6900411d21", size = 270352, upload-time = "2026-09-30T04:36:06.412Z" }, + { url = "https://files.pythonhosted.org/packages/04/f3/859f74e7babc977705026b30593b3be04049632a522fb7000f83c033d747/charset_normalizer-3.5.2-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0c951d5e6dd9c2ff60609476752bee49da4206adde960ebc247766937f72e718", size = 267393, upload-time = "2026-09-30T04:36:07.865Z" }, + { url = "https://files.pythonhosted.org/packages/4b/85/41d27f234b82e47c167a5f6c0f62501dc0c640585ff4aba79e08a390336a/charset_normalizer-3.5.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7218e8f32b0956cfcd048fd42d9d5779809745ca1d86113ca56f66e7ae1549c4", size = 254660, upload-time = "2026-09-30T04:36:09.248Z" }, + { url = "https://files.pythonhosted.org/packages/58/ca/5d1a997587febe5b26d8daffe363b5c1a091cece19828eec6502fd09c5ef/charset_normalizer-3.5.2-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a19a731138fc27d5682277d3b9df22855cea1239bce7fcec5f78f42ef2d1f3c3", size = 249996, upload-time = "2026-09-30T04:36:10.73Z" }, + { url = "https://files.pythonhosted.org/packages/b3/1f/d1e78246f7ed60c8c8d606b4ac27f66ce49cc3e95f24893ccbeba9f77302/charset_normalizer-3.5.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:62603db9a7caa0802eaa28c1c46fecd7b3a263a774069c24c3c28c302448721c", size = 247028, upload-time = "2026-09-30T04:36:12.294Z" }, + { url = "https://files.pythonhosted.org/packages/8e/37/eba316edd4f0c4d3a5d945924c4eeeae59abac4056aa815d8a4268f863a2/charset_normalizer-3.5.2-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:b6856554c4f44d79fc2307d5768854310a8f0096e501c75637542c82292b0429", size = 240562, upload-time = "2026-09-30T04:36:13.887Z" }, + { url = "https://files.pythonhosted.org/packages/c8/8e/aaa037d40ca9ef045977f1a661048b1aa33f223adfce3452fe9be9f79d14/charset_normalizer-3.5.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:1bc0baf5ef96b6ede57d47f4b8fe4d9d84019c3bfcbeb20a41edc6a6ee341f1f", size = 271699, upload-time = "2026-09-30T04:36:15.41Z" }, + { url = "https://files.pythonhosted.org/packages/26/19/1c1c9f75974adf523b87f34b8a2adc5a435cd65916812bcbd0dfa45f9a29/charset_normalizer-3.5.2-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:56bc200a365efb37383b7852e4cc5898d3b2da5987289b543956cf8cad71018a", size = 252030, upload-time = "2026-09-30T04:36:16.839Z" }, + { url = "https://files.pythonhosted.org/packages/bc/90/0660ef18e18df0a4d2a1a0edff7dfbba42d4e50ef2425557a5bb7051f77b/charset_normalizer-3.5.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:2c9ad19a6cfcd5ea5c0d41161d22f9df1dcc277e9bef2751391334546a314c00", size = 268565, upload-time = "2026-09-30T04:36:18.468Z" }, + { url = "https://files.pythonhosted.org/packages/79/ba/57adc269824e8658f1a0f97a9e514c247445a9632b3419b97e0ba37f16dc/charset_normalizer-3.5.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e243bd13217235fc7290c621941c3f5cc8b66e4872495be821d7436ba2fb838d", size = 257627, upload-time = "2026-09-30T04:36:19.938Z" }, + { url = "https://files.pythonhosted.org/packages/9a/85/33abd4315c052d3d4f54c92b1ee49bfbc0dc7115a981e462a793b6d2ab87/charset_normalizer-3.5.2-cp313-cp313-pyemscripten_2025_0_wasm32.whl", hash = "sha256:a090bb2c68df85450502e3e20d665e3a5af9c65a84d6508ed477badd49166fd3", size = 143407, upload-time = "2026-09-30T04:36:21.376Z" }, + { url = "https://files.pythonhosted.org/packages/4f/de/6435e18d1aaa5d910b896d551411c96af1f42a0c56c29afc2016c61ccc2e/charset_normalizer-3.5.2-cp313-cp313-win32.whl", hash = "sha256:2b7b3bbfb4fe8ef40600792d762fbaa9057559f9d3fad209525b7a22b99e91fd", size = 183207, upload-time = "2026-09-30T04:36:22.776Z" }, + { url = "https://files.pythonhosted.org/packages/9c/76/b8ec57f4e9ee3253541abf95e4a462c0175fe8032dcd070f1f2421240942/charset_normalizer-3.5.2-cp313-cp313-win_amd64.whl", hash = "sha256:78456a747de8dc58360ffa581f30a002baf5aa28cb262536545e91f113ed7639", size = 206489, upload-time = "2026-09-30T04:36:24.306Z" }, + { url = "https://files.pythonhosted.org/packages/3e/60/c647c6ae47480221e875ea5d743ff94946f7416e3c69415ab772928e8d32/charset_normalizer-3.5.2-cp313-cp313-win_arm64.whl", hash = "sha256:11912e4bb14baae7c5d8791aa55ba0a3a03ec6729073307b0f57270abaa713d3", size = 195501, upload-time = "2026-09-30T04:36:25.846Z" }, + { url = "https://files.pythonhosted.org/packages/58/ca/7aa91362a2f77ac8e9e28a9b902a74f7d0e11a851ef0d27a74308da8cd90/charset_normalizer-3.5.2-cp314-cp314-android_24_arm64_v8a.whl", hash = "sha256:1afb975bd5d68d5ce9f6b6d44fdf2f7e34b895a35e95708a7a91b20a3b51d187", size = 226010, upload-time = "2026-09-30T04:36:27.669Z" }, + { url = "https://files.pythonhosted.org/packages/a8/cf/ac8878d0322cf88a1aad4c7b147db32ca0bd806eb0060957b2e31486dbe6/charset_normalizer-3.5.2-cp314-cp314-android_24_x86_64.whl", hash = "sha256:bbbfc8e28816f19d7c0f1816664980c0a9875d01b27cdf8eedddb639d9e108ad", size = 239266, upload-time = "2026-09-30T04:36:29.434Z" }, + { url = "https://files.pythonhosted.org/packages/c9/6d/9a08d7e0b29b7208e2c6c01dc56c8e0520e7c7beadbbfb024b58fd69c8a5/charset_normalizer-3.5.2-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:7967d08cf06dee78443b874f98c98036f624f3a4e73e11f9f64f5be4d25393cf", size = 206783, upload-time = "2026-09-30T04:36:30.872Z" }, + { url = "https://files.pythonhosted.org/packages/82/44/b0aa350280e6ff5a5492d17cf10460dd39d5ee848f872f7ba2df10607f60/charset_normalizer-3.5.2-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:4c2b5031f63e331e3839b40aed2dd6f191e9c07edbde303e7876846ea1946995", size = 210449, upload-time = "2026-09-30T04:36:32.625Z" }, + { url = "https://files.pythonhosted.org/packages/7c/8a/40db9aa9f5907bb0e6f8b6d64064bf8852fb33d4b813ff9414911df7647c/charset_normalizer-3.5.2-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:fcff63213e8e6e47770541a4607175404f47cbb3ebea7b6058cc82d524a0e424", size = 367815, upload-time = "2026-09-30T04:36:34.197Z" }, + { url = "https://files.pythonhosted.org/packages/7f/72/9c5e7707b57c8ddfa9ddf7b0b1d009d7fbab9e9e887d5b721060f37e307d/charset_normalizer-3.5.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8d86d6fc60743dc916eb79e2eb1ec4818e21e427731543af40a3021851174a13", size = 247095, upload-time = "2026-09-30T04:36:35.803Z" }, + { url = "https://files.pythonhosted.org/packages/83/09/71e453691e927de4ddf792770cfaab3f49d494e222f66ea5e404bbd5e39c/charset_normalizer-3.5.2-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:7a881931aa470808df94a8c380eed2bbbc76cd9dc622310f99665658c821eb6d", size = 233942, upload-time = "2026-09-30T04:36:37.407Z" }, + { url = "https://files.pythonhosted.org/packages/9f/86/85c84e4da8b27dd409577d9437926ff581c5f9d3c66038dc68c1a526de51/charset_normalizer-3.5.2-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8024d00c3faf3fc0c16e07a69f4405e8eac7cc0ab15f65fe6cf43827c4cf72b4", size = 273762, upload-time = "2026-09-30T04:36:38.904Z" }, + { url = "https://files.pythonhosted.org/packages/92/08/564955a4b5f2ccb410ab480bbe8c6a18063ff27f2d35458731c4a5335df9/charset_normalizer-3.5.2-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4d48f2d08b9de5864e2c8744d4461b862fb149a18274abc8b698c45975573438", size = 269514, upload-time = "2026-09-30T04:36:40.469Z" }, + { url = "https://files.pythonhosted.org/packages/18/24/bad3ac4271589df29cf5ce2f5ae490518a5739358052bd0d61209e6fea54/charset_normalizer-3.5.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:34276fd796040bf0993ab33a369aa572e6979c7aab225a88893667ad8eac8f7a", size = 255056, upload-time = "2026-09-30T04:36:42.02Z" }, + { url = "https://files.pythonhosted.org/packages/d6/3e/350d89ad49916b86554d6f5f2d03ec1152148f87e5ff735106c6a03b1a36/charset_normalizer-3.5.2-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0521c5665880b33d603717defa76c094048900010897909952397feb3039da56", size = 251311, upload-time = "2026-09-30T04:36:43.577Z" }, + { url = "https://files.pythonhosted.org/packages/56/5b/4970a2d154df502e133402906dd04e3ae7cada7b3011283c88d0479a2585/charset_normalizer-3.5.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:eff0ac9dbe711a4aee69bf04a83896aa9b85f19641264053a9f6d48573abb7dd", size = 250190, upload-time = "2026-09-30T04:36:45.185Z" }, + { url = "https://files.pythonhosted.org/packages/88/8c/f1a91bddc8fb47c2889e29ea7ea49a194eb0d9868675d786806519c00d76/charset_normalizer-3.5.2-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:1503bccbeb36d5527790c3930327704c39af22de3112f1b1666a9f3ce15ee204", size = 237098, upload-time = "2026-09-30T04:36:46.689Z" }, + { url = "https://files.pythonhosted.org/packages/24/0e/bb5dace3cc7e79068425386a6589c19b5a2ab5fefc2a46abea6919683332/charset_normalizer-3.5.2-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:52aa6992700996af31f375de0c6bacd402b0097fe40b53c426b9f51a90ebabc7", size = 274228, upload-time = "2026-09-30T04:36:48.31Z" }, + { url = "https://files.pythonhosted.org/packages/9d/79/b849ad523017ea9f5a45581bbebed91439e0cf42fd2860a6f64e358eb5a6/charset_normalizer-3.5.2-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:e09a3942ecbdee5cce73ea9d42da82b81b72ac1bf031ce069b93b5adf4eac8cd", size = 252401, upload-time = "2026-09-30T04:36:50.091Z" }, + { url = "https://files.pythonhosted.org/packages/89/8c/75469d690cf47200bce8f6cad7655724fc23148e147abfc5ce78b5f65863/charset_normalizer-3.5.2-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:c7c9ab723cde841fefb34efbad91e87f00a674b1fe1cd0784fde742bf2c154dc", size = 271846, upload-time = "2026-09-30T04:36:51.719Z" }, + { url = "https://files.pythonhosted.org/packages/26/cd/6d52d3c7437cdcf2e310ce9f28f282e733d4ef60ed19105d1819c356255f/charset_normalizer-3.5.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ddc7dacc8ece3a182e7f15cb862d1fd616b46d076cb1ae9dd232b2c38b655874", size = 258151, upload-time = "2026-09-30T04:36:53.234Z" }, + { url = "https://files.pythonhosted.org/packages/f7/4c/070b38bdb5f49a70199fce923ec0726a49536a63ab262abbfcaaf351110b/charset_normalizer-3.5.2-cp314-cp314-pyemscripten_2026_0_wasm32.whl", hash = "sha256:ee43c17b173d46a3212baa6ead3ae258eeabdae48c263a01ccf0218c366dd655", size = 143570, upload-time = "2026-09-30T04:36:54.816Z" }, + { url = "https://files.pythonhosted.org/packages/81/84/9ebfc8ed6c8c4fcd8e726ff6bf220cc8deb3966e31dce9be8dd8aa017e64/charset_normalizer-3.5.2-cp314-cp314-win32.whl", hash = "sha256:4f87960d57feabfb618e4e0af6e7371645fa26a277860739d6e5d6e0012c92f0", size = 186412, upload-time = "2026-09-30T04:36:56.643Z" }, + { url = "https://files.pythonhosted.org/packages/d1/78/5ed86f743d4bc350db307e7636419a0a5ee1d91806d30c7f667bd5c80dae/charset_normalizer-3.5.2-cp314-cp314-win_amd64.whl", hash = "sha256:e4e81e09c1578b8df602e3db08b0b3ea0a6947ad612f52bf8dc5ea8d47691f0c", size = 210965, upload-time = "2026-09-30T04:36:58.205Z" }, + { url = "https://files.pythonhosted.org/packages/53/94/a3a7698e9b1a395e1eb99ccd9a324be9347973bff4e72db2a06496d7cd27/charset_normalizer-3.5.2-cp314-cp314-win_arm64.whl", hash = "sha256:80d02b6f04e92601a081dd97b23d3128033098bff5d35d392ddcc0476ea11253", size = 200406, upload-time = "2026-09-30T04:36:59.764Z" }, + { url = "https://files.pythonhosted.org/packages/c1/48/c5dd00d5ef7791f02666de250a5bb6071e29b7e133cf4b835800b6d3bc27/charset_normalizer-3.5.2-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:dca9ab98072a5a54ebacebdc45f53e645336b320c667410b061be1ca588ae709", size = 396871, upload-time = "2026-09-30T04:37:01.543Z" }, + { url = "https://files.pythonhosted.org/packages/12/c8/8379554b42e8368161d898476686947a0fdbd3e8865170d7909dcabfdee8/charset_normalizer-3.5.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f0aa869112ef88429ae17820d99c3dd9504c9e9c671d3c246f3d7442cb051084", size = 249711, upload-time = "2026-09-30T04:37:03.111Z" }, + { url = "https://files.pythonhosted.org/packages/4a/eb/2ddb1035d17320caa9f41682935123a9a250277b261c3efc86b2d2a21343/charset_normalizer-3.5.2-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c0afc6800ba57ccc350374c5bd6150419915d95ce93cdbab2d783d75eaf30ecb", size = 231146, upload-time = "2026-09-30T04:37:04.721Z" }, + { url = "https://files.pythonhosted.org/packages/4a/24/2ecb4bde104322cd7859d6594fcfa74649f8d90b3221c9feecbef149875b/charset_normalizer-3.5.2-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7dcd882da75ef9adf94903b1e3b9419e8aa8fb4c7396822b834b9ef7fb96954f", size = 271552, upload-time = "2026-09-30T04:37:06.295Z" }, + { url = "https://files.pythonhosted.org/packages/3f/98/9d5f6ebc3aee9fef5d30b4aff11fb2ab7a1222b4064f8ef2c7c87cde217a/charset_normalizer-3.5.2-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2e06a3a98f916dd41d27f3105e02e7a40181c98c94b9158733d03a6f80506c09", size = 269810, upload-time = "2026-09-30T04:37:07.905Z" }, + { url = "https://files.pythonhosted.org/packages/09/e1/a3b06a10461b1b7628853c934c644e03bc28e42767116afb52f19a56519b/charset_normalizer-3.5.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6bd128f206a7752ae1f2ab6c61bf8a24ba28913a10df8b14c2637b973ff97a80", size = 259845, upload-time = "2026-09-30T04:37:09.554Z" }, + { url = "https://files.pythonhosted.org/packages/fd/d3/6f561f74a296cf27d61775a1dc665ad13f3bff6a798810ca05907f37a7c4/charset_normalizer-3.5.2-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c8f3d67aeaf55f017982b73683f0e7342ba2f6635a78f69ce89ebb26aa411e5c", size = 252825, upload-time = "2026-09-30T04:37:11.274Z" }, + { url = "https://files.pythonhosted.org/packages/26/9f/69e13ca3b18f43e0eafcd34c04a45b732ae22a43b54a5fc9e119103356eb/charset_normalizer-3.5.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:fe9753dfee015c570d73df76f899f18444d41388bffcde097deba51c4fadbb9f", size = 252659, upload-time = "2026-09-30T04:37:12.941Z" }, + { url = "https://files.pythonhosted.org/packages/73/a9/ace29806a0dae18939919c76ba526472d83214afa101105fabff2cf30625/charset_normalizer-3.5.2-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:92888bb3187c5ba50500b00b3b310c9f2c651709d28036077680cb5255450a03", size = 238819, upload-time = "2026-09-30T04:37:14.659Z" }, + { url = "https://files.pythonhosted.org/packages/f8/c1/6116d52a2e3311ec80f21f5fb5e17b27405f10b9608af8f6e69516841a1b/charset_normalizer-3.5.2-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:d008d90a7f2471519aef0c90dfbe73b3e6e4d5e66ac48e19154c17e89e98b604", size = 272973, upload-time = "2026-09-30T04:37:16.346Z" }, + { url = "https://files.pythonhosted.org/packages/19/aa/9955c7e93bba10a9c7e8f7a5031b7ced66f3a1883a55c00712b8d5850ff3/charset_normalizer-3.5.2-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:31f3930700408d211f13378ccbe1c40845d8da54bd0681fac3a9b5aae81c7aa8", size = 253692, upload-time = "2026-09-30T04:37:18.212Z" }, + { url = "https://files.pythonhosted.org/packages/bb/33/2a6ae7fdc1b10cb581cef91addd8cdfc5f40d50abb5702309369d5834579/charset_normalizer-3.5.2-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:2a925889534b3748302dae5dead07cc13480de1dac3aea80a941b729b471ef93", size = 268757, upload-time = "2026-09-30T04:37:19.877Z" }, + { url = "https://files.pythonhosted.org/packages/a2/22/80992720a0282cd39bba1db35868e6b9c22f41281160143a836544bc1d8a/charset_normalizer-3.5.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:f5ec61164adcec446f8969a3358ec3f9b26bbda3b9213e5586d219afa8df2915", size = 262220, upload-time = "2026-09-30T04:37:21.583Z" }, + { url = "https://files.pythonhosted.org/packages/92/9f/181fd07e1bffea1d95cd80c84ac537354f50699c22cfc4d3c02b6fc16208/charset_normalizer-3.5.2-cp314-cp314t-win32.whl", hash = "sha256:598a11a2c7ebaa5334bf698bf29568c9c390abac6a154d8170fedecd1cea38c5", size = 197797, upload-time = "2026-09-30T04:37:23.235Z" }, + { url = "https://files.pythonhosted.org/packages/49/1c/25d8415ec1c4f2f41f1680435e4c87cfb378ff2f677d950946f2a45d0632/charset_normalizer-3.5.2-cp314-cp314t-win_amd64.whl", hash = "sha256:7fdde2c9fd9e3eca40631e024664cf2584272cc8f96308cbe5fdfc930f51d8bc", size = 222765, upload-time = "2026-09-30T04:37:24.891Z" }, + { url = "https://files.pythonhosted.org/packages/3e/b4/46b48f013dadfc0d0d33b375438e31bdf5a989dc68389c6bf627054d4df9/charset_normalizer-3.5.2-cp314-cp314t-win_arm64.whl", hash = "sha256:d1befeed746d247c81127bb14de9dc3d30edb6e5976d34f83f86ed262b1d9105", size = 210985, upload-time = "2026-09-30T04:37:26.634Z" }, + { url = "https://files.pythonhosted.org/packages/ca/e9/34e597dee616d0b8ee4b34d29399e85c2204ade174157a48505d42baa4ff/charset_normalizer-3.5.2-cp315-cp315-macosx_10_15_universal2.whl", hash = "sha256:87475fabc8d9996fd9c27debb395e642e8c838d78a00b6e932227a0e06b81e26", size = 367676, upload-time = "2026-09-30T04:37:28.329Z" }, + { url = "https://files.pythonhosted.org/packages/60/9f/a5d1c91c0263745e2cd344c5a4415d787c575501ab1d449f1148ac6b495d/charset_normalizer-3.5.2-cp315-cp315-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9409a8bf35cf78353942504b24a57de3d75b708997a1e4bd8db71ac8633ce364", size = 248414, upload-time = "2026-09-30T04:37:30.167Z" }, + { url = "https://files.pythonhosted.org/packages/26/79/e697f77464748a3ee3cf490c83d592459400d4898380d66c38366b03080c/charset_normalizer-3.5.2-cp315-cp315-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:498dc3188ca05a68231ac3fdbfc7f57eb67e1343c30e0fea17f8218c1599b253", size = 244775, upload-time = "2026-09-30T04:37:31.964Z" }, + { url = "https://files.pythonhosted.org/packages/ca/87/3d42a42e18ea066e2513936fd678a00696e77878b5ae04528976abdbcb83/charset_normalizer-3.5.2-cp315-cp315-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e242bb1c5e76e97dfa9e7f209a71e93a01d7f19ffdd5cfbb2e2d55b4f08f8ab0", size = 273877, upload-time = "2026-09-30T04:37:33.661Z" }, + { url = "https://files.pythonhosted.org/packages/c3/76/8a28136f3938ba9836f84280ce0c4d61ed1cf15a036b2034900c62634162/charset_normalizer-3.5.2-cp315-cp315-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:def79fa35ef0cef8d2accec024f4fdc7ead3012ff02f5215c783f39f03ef8cfc", size = 269455, upload-time = "2026-09-30T04:37:35.573Z" }, + { url = "https://files.pythonhosted.org/packages/a0/a1/4fbf5d0f0f1b2a080474c1cf9a2f12c4c6531bb0e8ba591055e846d2b4e9/charset_normalizer-3.5.2-cp315-cp315-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3df041de8887954562c9b261cba85ca0e9ded74048daf125f45edcfaa4832229", size = 257336, upload-time = "2026-09-30T04:37:37.397Z" }, + { url = "https://files.pythonhosted.org/packages/ba/a2/8b50aa320adb880ad579518e6f718f24944804b42a88b83d267d5d444125/charset_normalizer-3.5.2-cp315-cp315-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:04851f73ae72b8413dddadb16a49dfee95263553741fd42d546f7d66907e6be5", size = 257584, upload-time = "2026-09-30T04:37:39.522Z" }, + { url = "https://files.pythonhosted.org/packages/a5/57/50e3fed84e175f40349bd0da7a4fce94c87f0378f52d74f511d89e0bdc20/charset_normalizer-3.5.2-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:183b88127acdb4fabe59d951ab424faf1af7b63cdbb5f776186c1ea2ffcaed98", size = 251854, upload-time = "2026-09-30T04:37:41.23Z" }, + { url = "https://files.pythonhosted.org/packages/d6/54/f7fbb3493c9f49091213b9c2d6dd65800696f1ce1a3f196a4205f50417b1/charset_normalizer-3.5.2-cp315-cp315-musllinux_1_2_armv7l.whl", hash = "sha256:16fa0eccf81304b79c5cd87f9271c3b85dd9dd99245e4422ae9c0dd45e0f99d3", size = 248767, upload-time = "2026-09-30T04:37:42.883Z" }, + { url = "https://files.pythonhosted.org/packages/d9/37/b3a6385acc5a1e45b39ae9c90bfb9cf838a09b9dd37ef2740ab4c6b4a2eb/charset_normalizer-3.5.2-cp315-cp315-musllinux_1_2_ppc64le.whl", hash = "sha256:7441d755b7ab94f8d4eb3e43ec05482d760842fd263d003a99102d742cd835e2", size = 274479, upload-time = "2026-09-30T04:37:44.658Z" }, + { url = "https://files.pythonhosted.org/packages/89/44/809913e2cfd279e635a9294fdbbfb1b1dc62a8189d473d561f649fce98d8/charset_normalizer-3.5.2-cp315-cp315-musllinux_1_2_riscv64.whl", hash = "sha256:ca403d7e4798f525fdfc78e258820419cbbd0f0ecbab9de7840e3c017cf6b8cf", size = 258310, upload-time = "2026-09-30T04:37:46.529Z" }, + { url = "https://files.pythonhosted.org/packages/af/a2/f28400ab13359d91bd39179df8e149376b9bf36588e739a3a4f9de2b84b2/charset_normalizer-3.5.2-cp315-cp315-musllinux_1_2_s390x.whl", hash = "sha256:df29a0a7107f7011e77f4eebdddec4c7331e24d787a0b21a46d63bdf7445da95", size = 271100, upload-time = "2026-09-30T04:37:48.399Z" }, + { url = "https://files.pythonhosted.org/packages/e9/89/9bab37955edf0adb3b66f8a3a6617d9f2f487e0d56f295a6a286cb640aa6/charset_normalizer-3.5.2-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:f3c96f633825733f735c5a9cf21d21a257d8e1edf0b1cee0a064b9c424ca0f7d", size = 259936, upload-time = "2026-09-30T04:37:50.023Z" }, + { url = "https://files.pythonhosted.org/packages/23/b5/4459e08d45a679f903d50fea08bc52cfa728cca4d7bd02c757b5e5abda2e/charset_normalizer-3.5.2-cp315-cp315-win32.whl", hash = "sha256:281cb91036248400f4cc957495cccd44c275c2e0c5854f7e45ac5cf7dc193847", size = 186301, upload-time = "2026-09-30T04:37:51.722Z" }, + { url = "https://files.pythonhosted.org/packages/98/e8/55d5fd3935b4bce6da4fe0df61898e8c82653e317e677bd58aceb9c60f13/charset_normalizer-3.5.2-cp315-cp315-win_amd64.whl", hash = "sha256:89b53f3cda69831909888e0494f4fa0bcd3537e3e138dabeb620bd6ad946bae8", size = 210858, upload-time = "2026-09-30T04:37:53.427Z" }, + { url = "https://files.pythonhosted.org/packages/a9/5b/974423c2fd8e524c7a7f64318c1e02240ef954912fa2b4d70344107b9c68/charset_normalizer-3.5.2-cp315-cp315-win_arm64.whl", hash = "sha256:6be488a102b8cf28d0391d8c4ba7748938ae28b78ad901f8585520fca33ead1a", size = 200309, upload-time = "2026-09-30T04:37:55.015Z" }, + { url = "https://files.pythonhosted.org/packages/ee/f9/00ee0195db1013d8f7c416fd770fbeb560bb46eb2e36b054d05cb56f6cfa/charset_normalizer-3.5.2-cp315-cp315t-macosx_10_15_universal2.whl", hash = "sha256:915563965d418f986e7e145accc592eae9e1a1be3566ff98a05d7a9ec42a76e1", size = 395343, upload-time = "2026-09-30T04:37:56.743Z" }, + { url = "https://files.pythonhosted.org/packages/04/3a/c00b50e94c964cf934c7899cd47c97952fc11dad71cc5884b3c61795b09b/charset_normalizer-3.5.2-cp315-cp315t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:65cd72beeeca9d3aaea1201e5923859f308f952f9c71de93f06063c79f0f7a3b", size = 250114, upload-time = "2026-09-30T04:37:58.607Z" }, + { url = "https://files.pythonhosted.org/packages/50/27/d102dc880bbcffd0479ab64dfc1fb96777a854355a55e2bda72a71efadcb/charset_normalizer-3.5.2-cp315-cp315t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:b7fd005a73d9e657273b7a10dc71a9e03c8fb9ee6999798d6918ce095b81ac7f", size = 239997, upload-time = "2026-09-30T04:38:00.511Z" }, + { url = "https://files.pythonhosted.org/packages/a5/4a/bf7ef45794dd293fab5f98a9309817977fbb845b9998f171b8cc5d8437a3/charset_normalizer-3.5.2-cp315-cp315t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e54da4baf05720032d527874d40b65fa4d7e5c6c6a43d0c3adbeffcaf275a2b3", size = 272313, upload-time = "2026-09-30T04:38:02.509Z" }, + { url = "https://files.pythonhosted.org/packages/e8/ee/008a2837737991474c5754bb3191010007663860979701990982a502cbaf/charset_normalizer-3.5.2-cp315-cp315t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:124fbf1a8ff966d87ae05bb8bd45a71f966055ed8bba320d0c7cf450bc5f4d0e", size = 269986, upload-time = "2026-09-30T04:38:04.435Z" }, + { url = "https://files.pythonhosted.org/packages/93/ad/bd74a283940dc910c5b14f8e4f80a248082bc9c0fcbe1f54530cb6d9cc5e/charset_normalizer-3.5.2-cp315-cp315t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:28b4f0d66fb834ff90f28209ac7bce77868c45d8c93e26f906709d9b7c2e1af9", size = 260202, upload-time = "2026-09-30T04:38:06.549Z" }, + { url = "https://files.pythonhosted.org/packages/8a/7b/ed341c66f69f688723501fac752be3d63c7159ca0d0d4174fc611e5710bb/charset_normalizer-3.5.2-cp315-cp315t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:58ca3755ee7ff7f59b57789ec9833c9de9ea275405cdd240eda1f193112e398a", size = 259083, upload-time = "2026-09-30T04:38:08.311Z" }, + { url = "https://files.pythonhosted.org/packages/cc/9d/e41588b777965e5031a43128a1e96173ebb35ac75fc53ec3b517e7c21cd4/charset_normalizer-3.5.2-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:443eae2bf318abeaf6f15d785138f71fd6de770e99a92158b8b814265e079115", size = 253081, upload-time = "2026-09-30T04:38:10.402Z" }, + { url = "https://files.pythonhosted.org/packages/81/35/b761eb6d8c1eb218b9b42b9b4d5ac902afdc399fb6dac6f9a9aac7bda589/charset_normalizer-3.5.2-cp315-cp315t-musllinux_1_2_armv7l.whl", hash = "sha256:58f361dcbab699cf8f42db3f47c8e7fd1036f138c23a5d08de9fde5f425a730c", size = 248712, upload-time = "2026-09-30T04:38:12.317Z" }, + { url = "https://files.pythonhosted.org/packages/4d/2c/147169a041b747759f37405c0a97157e8e92de967968373101ff14915cba/charset_normalizer-3.5.2-cp315-cp315t-musllinux_1_2_ppc64le.whl", hash = "sha256:1b4cbc7c3491ccb4aa17fcd8165649d01cf39f76de1696da8631b5f71b85401d", size = 274176, upload-time = "2026-09-30T04:38:14.138Z" }, + { url = "https://files.pythonhosted.org/packages/f0/2d/0ff8db0d373ba8538db686db11cd7e8912031490b9e4f383b41912e8d594/charset_normalizer-3.5.2-cp315-cp315t-musllinux_1_2_riscv64.whl", hash = "sha256:ba0b1d2620edf869789c3879223f52bf2afc5d31b3cb47cc57b3a12c05e2aa9d", size = 259413, upload-time = "2026-09-30T04:38:15.841Z" }, + { url = "https://files.pythonhosted.org/packages/8a/8e/b4a085fb47c9d3a7e43576a4784fdd8fe23f907514a972de8086edaf7a48/charset_normalizer-3.5.2-cp315-cp315t-musllinux_1_2_s390x.whl", hash = "sha256:5e2b6b57e9733d39f0c9fd3185efa6b8e29652c4cd8fe94180272cf6ed9a78c4", size = 269434, upload-time = "2026-09-30T04:38:17.626Z" }, + { url = "https://files.pythonhosted.org/packages/83/1c/d8d8d7322a7c3eecdf3237a4a419cf41d2eaad8e006ce7dfdd9d4c8fa2eb/charset_normalizer-3.5.2-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:51cf45226a9b588d0d2b4880c62d686934b63ab0bd79ca23ab0e9762eb27441b", size = 262716, upload-time = "2026-09-30T04:38:19.214Z" }, + { url = "https://files.pythonhosted.org/packages/a0/16/0e4c6ba9b44e97a2da150e52d331e8f9c968b21b358fbffa6c856cebcd89/charset_normalizer-3.5.2-cp315-cp315t-win32.whl", hash = "sha256:5fb29fb8cd1a46c27a1bf9613ad5ec2599310d46b4025d9556404a6b6a292800", size = 197159, upload-time = "2026-09-30T04:38:21.037Z" }, + { url = "https://files.pythonhosted.org/packages/be/33/e90bc2b1374f7f36ef106f56620de5a783907e19ca857efe2277e31cac3e/charset_normalizer-3.5.2-cp315-cp315t-win_amd64.whl", hash = "sha256:a192e2c40070d92c3ccf777e3a5c4ff515573cd2bb7ed0c537fdadbbec5bbf21", size = 221322, upload-time = "2026-09-30T04:38:22.886Z" }, + { url = "https://files.pythonhosted.org/packages/66/89/dfa6dcb08c200b7830ab56439e8c1890f2971d51aafbb3937894a2e7fcfc/charset_normalizer-3.5.2-cp315-cp315t-win_arm64.whl", hash = "sha256:749e97e1b32313717a565abbe321bc2190bc8b35f1a67e4cdbc7c56c8d8ffe58", size = 209192, upload-time = "2026-09-30T04:38:24.648Z" }, + { url = "https://files.pythonhosted.org/packages/8c/ab/176fbfd5b64939c55d652366aa5b9ef1d767af207a3aa6ebeb0d226c484d/charset_normalizer-3.5.2-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:4275811936e2f06feff5e598fb42a1b7ae852da8e39605211892b56b81a34efd", size = 331815, upload-time = "2026-09-30T04:38:26.216Z" }, + { url = "https://files.pythonhosted.org/packages/7e/84/371eac6b30bdbcbf2d632a1a01809103459216fcaae61b8b8d922c1bfb8a/charset_normalizer-3.5.2-cp37-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:1c50fe28bbc2ced33386f298650d91218076c05420e6cbd790b913adc41659e7", size = 253276, upload-time = "2026-09-30T04:38:28.032Z" }, + { url = "https://files.pythonhosted.org/packages/43/6f/c4fbae58febff71709c51bc7e18fdfa55341dc382704740f9f0cbf03817b/charset_normalizer-3.5.2-cp37-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d19fbd981a488e22cd04883659ca6b08f50b5974f9fd7c95655ef6a043e5893f", size = 241239, upload-time = "2026-09-30T04:38:29.732Z" }, + { url = "https://files.pythonhosted.org/packages/61/71/458c3f42164a07d0c5210798e9e704b39e540a6793b05aba67f3a35243a9/charset_normalizer-3.5.2-cp37-abi3-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:0fed1d06615f022ee3b13caf5e8b180cfea32bb2c5aded8a9d44277afc040f93", size = 231121, upload-time = "2026-09-30T04:38:31.462Z" }, + { url = "https://files.pythonhosted.org/packages/09/54/ab9e89367076f6331bb6c65c4bf14a5361fa5191cb6561bf534f18504e1b/charset_normalizer-3.5.2-cp37-abi3-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:838dcc90063569a0448120554591a1d6c4a4ffe11babf048908793154ab86ade", size = 260350, upload-time = "2026-09-30T04:38:33.239Z" }, + { url = "https://files.pythonhosted.org/packages/7c/c1/061431ecc688d9d76602502cb57cc01e691e682c18f1beb45f9673b5bbd2/charset_normalizer-3.5.2-cp37-abi3-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2ce45c6627b22c47e390bc91a41c3d13032192e699fa0bea96e9671b373d69b0", size = 255430, upload-time = "2026-09-30T04:38:34.865Z" }, + { url = "https://files.pythonhosted.org/packages/8d/1f/20c8949f0676f7ab811abdeb7f4d7f1cbc6e61ff20bef08b44edeb092bc8/charset_normalizer-3.5.2-cp37-abi3-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0774bf9bf620249fee3e0b8b9fd3065de213be30f3aa94ce2494b3b638949e26", size = 250612, upload-time = "2026-09-30T04:38:36.649Z" }, + { url = "https://files.pythonhosted.org/packages/2b/9e/46f2fa4c431fc98c4ae76a8cb5bdca54e0341e3cfc3fcfd8e82740250818/charset_normalizer-3.5.2-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:1db38f4c5496827c1a501846d64d14c3b80c7e6714e406cd7dc36a9899fa1011", size = 242083, upload-time = "2026-09-30T04:38:38.26Z" }, + { url = "https://files.pythonhosted.org/packages/bd/39/559be29a0c0f086e0bba6922babd38916cc5e0b58ced4de13ee01ea05508/charset_normalizer-3.5.2-cp37-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:304d8e4d493af723536393eee0c689eb7813f4a474c8b479dee63f1fdd98f621", size = 232738, upload-time = "2026-09-30T04:38:39.81Z" }, + { url = "https://files.pythonhosted.org/packages/ff/6c/387b0e4f756a282831c1d9fc6aeb6c51ca4507ca202767c8de15ce9b12e2/charset_normalizer-3.5.2-cp37-abi3-musllinux_1_2_ppc64le.whl", hash = "sha256:9b7f416ff0978e2f2249330527f0ad6fa02f4932e6199692d3b52da2048c19e4", size = 260703, upload-time = "2026-09-30T04:38:41.346Z" }, + { url = "https://files.pythonhosted.org/packages/96/92/1fdf015f09ef449f50d3ac4b67c90887c9c318b727daa95cc4f866e6521d/charset_normalizer-3.5.2-cp37-abi3-musllinux_1_2_riscv64.whl", hash = "sha256:01077390b03f7988f11d700a2194e69b119741a86b1a638b1db88891e3eced8e", size = 247622, upload-time = "2026-09-30T04:38:42.937Z" }, + { url = "https://files.pythonhosted.org/packages/dc/3c/8e7b8a5671ad5d433669fb2a76f1a0164df2d9b1718b0206bc2a16d840cc/charset_normalizer-3.5.2-cp37-abi3-musllinux_1_2_s390x.whl", hash = "sha256:7e841fb9010836c992c9f12fcbd43a831de93a5f726fc1ccd8ca1d0268c5014c", size = 257500, upload-time = "2026-09-30T04:38:44.604Z" }, + { url = "https://files.pythonhosted.org/packages/b4/f0/45b579df5cabc1d5d53ea1cc35e8437d3ca768c0acccc7041517cb6fbb32/charset_normalizer-3.5.2-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:9cae88599c7219005d879f98e5ed53341e9a122af585e1091200358a3003d2a0", size = 255100, upload-time = "2026-09-30T04:38:46.289Z" }, + { url = "https://files.pythonhosted.org/packages/31/68/fdec18a343f5fb3f310588dd478b09ac4799e0b187dbade3a8cd776f03ef/charset_normalizer-3.5.2-cp37-abi3-win32.whl", hash = "sha256:01b0c0d2262a9e28e8484a278c7e1b5d650e3ac8cf2683d2967e25899f208bdf", size = 174499, upload-time = "2026-09-30T04:38:47.999Z" }, + { url = "https://files.pythonhosted.org/packages/9d/8a/b618149cc5207943a0242068d7a27897f56a62947b5a039085f2a22029f8/charset_normalizer-3.5.2-cp37-abi3-win_amd64.whl", hash = "sha256:9f56f72050826f63dcee7a7f55b0a77168cb3bfc553fd405e7f8f9ece75a4036", size = 200092, upload-time = "2026-09-30T04:38:49.707Z" }, + { url = "https://files.pythonhosted.org/packages/03/cf/4c66866fa9e2b1c78e3c911516d1de497a677b7ac60f1eceda74ce777ca3/charset_normalizer-3.5.2-cp37-abi3-win_arm64.whl", hash = "sha256:40ab6bffa02ae10a0581e6c198be7d2d8ca5c2a0c64e4ed3465d766df457573e", size = 294363, upload-time = "2026-09-30T04:38:51.312Z" }, + { url = "https://files.pythonhosted.org/packages/fc/ad/d07d7862a62ffa6d79d68074d14823243dd235a77c45262acbf6adeb28bf/charset_normalizer-3.5.2-py3-none-any.whl", hash = "sha256:b6b751274acb69d77b3323d6b7dbaa3c7fdfc1eb829b7eb61d262f32e1af9685", size = 68872, upload-time = "2026-09-30T04:39:21.828Z" }, +] + +[[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 = "exceptiongroup" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598", size = 16740, upload-time = "2025-11-21T23:01:53.443Z" }, +] + +[[package]] +name = "idna" +version = "3.20" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f5/08/8eea9d4b8302028f3abb2c0813953f7aec26d33b7a8960ed760e65ff29fa/idna-3.20.tar.gz", hash = "sha256:a7db850025b95ded1eae8a46181a1a6c56c92c96f0e2b005d9ff8dc0210cab44", size = 216463, upload-time = "2026-09-17T14:11:04.752Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/58/a2/bb081bab032533a855d44de1d56f8e8426114ff1ba5d1f07a438a0a654f8/idna-3.20-py3-none-any.whl", hash = "sha256:ab7ae7122974553370f0bdb919e1a960b2cd1bc1ef0276416d896db81c14582c", size = 69583, upload-time = "2026-09-17T14:11:03.168Z" }, +] + +[[package]] +name = "iniconfig" +version = "2.3.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/01/e1/2069291243c926a2ff1cd706c7f3eeb9b62144bf60f77c9fb9ff2fb26bd3/iniconfig-2.3.1.tar.gz", hash = "sha256:67f4b9c50da0dedf52af349e7749a80a9057a5031199791b906c3bb3ae878960", size = 21209, upload-time = "2026-10-06T22:48:38.076Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/56/43/4ca9e49d27a1fcf6bece6f6aec0ea46bb9112489b93d4b688fb415457bdb/iniconfig-2.3.1-py3-none-any.whl", hash = "sha256:9121e2c1fdb355232495be3194c8dfe87ccc2d5dee45947b78e68f499790d7a7", size = 7552, upload-time = "2026-10-06T22:48:36.959Z" }, +] + +[[package]] +name = "numpy" +version = "2.2.6" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.11'", +] +sdist = { url = "https://files.pythonhosted.org/packages/76/21/7d2a95e4bba9dc13d043ee156a356c0a8f0c6309dff6b21b4d71a073b8a8/numpy-2.2.6.tar.gz", hash = "sha256:e29554e2bef54a90aa5cc07da6ce955accb83f21ab5de01a62c8478897b264fd", size = 20276440, upload-time = "2025-05-17T22:38:04.611Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9a/3e/ed6db5be21ce87955c0cbd3009f2803f59fa08df21b5df06862e2d8e2bdd/numpy-2.2.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b412caa66f72040e6d268491a59f2c43bf03eb6c96dd8f0307829feb7fa2b6fb", size = 21165245, upload-time = "2025-05-17T21:27:58.555Z" }, + { url = "https://files.pythonhosted.org/packages/22/c2/4b9221495b2a132cc9d2eb862e21d42a009f5a60e45fc44b00118c174bff/numpy-2.2.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8e41fd67c52b86603a91c1a505ebaef50b3314de0213461c7a6e99c9a3beff90", size = 14360048, upload-time = "2025-05-17T21:28:21.406Z" }, + { url = "https://files.pythonhosted.org/packages/fd/77/dc2fcfc66943c6410e2bf598062f5959372735ffda175b39906d54f02349/numpy-2.2.6-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:37e990a01ae6ec7fe7fa1c26c55ecb672dd98b19c3d0e1d1f326fa13cb38d163", size = 5340542, upload-time = "2025-05-17T21:28:30.931Z" }, + { url = "https://files.pythonhosted.org/packages/7a/4f/1cb5fdc353a5f5cc7feb692db9b8ec2c3d6405453f982435efc52561df58/numpy-2.2.6-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:5a6429d4be8ca66d889b7cf70f536a397dc45ba6faeb5f8c5427935d9592e9cf", size = 6878301, upload-time = "2025-05-17T21:28:41.613Z" }, + { url = "https://files.pythonhosted.org/packages/eb/17/96a3acd228cec142fcb8723bd3cc39c2a474f7dcf0a5d16731980bcafa95/numpy-2.2.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:efd28d4e9cd7d7a8d39074a4d44c63eda73401580c5c76acda2ce969e0a38e83", size = 14297320, upload-time = "2025-05-17T21:29:02.78Z" }, + { url = "https://files.pythonhosted.org/packages/b4/63/3de6a34ad7ad6646ac7d2f55ebc6ad439dbbf9c4370017c50cf403fb19b5/numpy-2.2.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc7b73d02efb0e18c000e9ad8b83480dfcd5dfd11065997ed4c6747470ae8915", size = 16801050, upload-time = "2025-05-17T21:29:27.675Z" }, + { url = "https://files.pythonhosted.org/packages/07/b6/89d837eddef52b3d0cec5c6ba0456c1bf1b9ef6a6672fc2b7873c3ec4e2e/numpy-2.2.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:74d4531beb257d2c3f4b261bfb0fc09e0f9ebb8842d82a7b4209415896adc680", size = 15807034, upload-time = "2025-05-17T21:29:51.102Z" }, + { url = "https://files.pythonhosted.org/packages/01/c8/dc6ae86e3c61cfec1f178e5c9f7858584049b6093f843bca541f94120920/numpy-2.2.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8fc377d995680230e83241d8a96def29f204b5782f371c532579b4f20607a289", size = 18614185, upload-time = "2025-05-17T21:30:18.703Z" }, + { url = "https://files.pythonhosted.org/packages/5b/c5/0064b1b7e7c89137b471ccec1fd2282fceaae0ab3a9550f2568782d80357/numpy-2.2.6-cp310-cp310-win32.whl", hash = "sha256:b093dd74e50a8cba3e873868d9e93a85b78e0daf2e98c6797566ad8044e8363d", size = 6527149, upload-time = "2025-05-17T21:30:29.788Z" }, + { url = "https://files.pythonhosted.org/packages/a3/dd/4b822569d6b96c39d1215dbae0582fd99954dcbcf0c1a13c61783feaca3f/numpy-2.2.6-cp310-cp310-win_amd64.whl", hash = "sha256:f0fd6321b839904e15c46e0d257fdd101dd7f530fe03fd6359c1ea63738703f3", size = 12904620, upload-time = "2025-05-17T21:30:48.994Z" }, + { url = "https://files.pythonhosted.org/packages/da/a8/4f83e2aa666a9fbf56d6118faaaf5f1974d456b1823fda0a176eff722839/numpy-2.2.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f9f1adb22318e121c5c69a09142811a201ef17ab257a1e66ca3025065b7f53ae", size = 21176963, upload-time = "2025-05-17T21:31:19.36Z" }, + { url = "https://files.pythonhosted.org/packages/b3/2b/64e1affc7972decb74c9e29e5649fac940514910960ba25cd9af4488b66c/numpy-2.2.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c820a93b0255bc360f53eca31a0e676fd1101f673dda8da93454a12e23fc5f7a", size = 14406743, upload-time = "2025-05-17T21:31:41.087Z" }, + { url = "https://files.pythonhosted.org/packages/4a/9f/0121e375000b5e50ffdd8b25bf78d8e1a5aa4cca3f185d41265198c7b834/numpy-2.2.6-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:3d70692235e759f260c3d837193090014aebdf026dfd167834bcba43e30c2a42", size = 5352616, upload-time = "2025-05-17T21:31:50.072Z" }, + { url = "https://files.pythonhosted.org/packages/31/0d/b48c405c91693635fbe2dcd7bc84a33a602add5f63286e024d3b6741411c/numpy-2.2.6-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:481b49095335f8eed42e39e8041327c05b0f6f4780488f61286ed3c01368d491", size = 6889579, upload-time = "2025-05-17T21:32:01.712Z" }, + { url = "https://files.pythonhosted.org/packages/52/b8/7f0554d49b565d0171eab6e99001846882000883998e7b7d9f0d98b1f934/numpy-2.2.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b64d8d4d17135e00c8e346e0a738deb17e754230d7e0810ac5012750bbd85a5a", size = 14312005, upload-time = "2025-05-17T21:32:23.332Z" }, + { url = "https://files.pythonhosted.org/packages/b3/dd/2238b898e51bd6d389b7389ffb20d7f4c10066d80351187ec8e303a5a475/numpy-2.2.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba10f8411898fc418a521833e014a77d3ca01c15b0c6cdcce6a0d2897e6dbbdf", size = 16821570, upload-time = "2025-05-17T21:32:47.991Z" }, + { url = "https://files.pythonhosted.org/packages/83/6c/44d0325722cf644f191042bf47eedad61c1e6df2432ed65cbe28509d404e/numpy-2.2.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:bd48227a919f1bafbdda0583705e547892342c26fb127219d60a5c36882609d1", size = 15818548, upload-time = "2025-05-17T21:33:11.728Z" }, + { url = "https://files.pythonhosted.org/packages/ae/9d/81e8216030ce66be25279098789b665d49ff19eef08bfa8cb96d4957f422/numpy-2.2.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9551a499bf125c1d4f9e250377c1ee2eddd02e01eac6644c080162c0c51778ab", size = 18620521, upload-time = "2025-05-17T21:33:39.139Z" }, + { url = "https://files.pythonhosted.org/packages/6a/fd/e19617b9530b031db51b0926eed5345ce8ddc669bb3bc0044b23e275ebe8/numpy-2.2.6-cp311-cp311-win32.whl", hash = "sha256:0678000bb9ac1475cd454c6b8c799206af8107e310843532b04d49649c717a47", size = 6525866, upload-time = "2025-05-17T21:33:50.273Z" }, + { url = "https://files.pythonhosted.org/packages/31/0a/f354fb7176b81747d870f7991dc763e157a934c717b67b58456bc63da3df/numpy-2.2.6-cp311-cp311-win_amd64.whl", hash = "sha256:e8213002e427c69c45a52bbd94163084025f533a55a59d6f9c5b820774ef3303", size = 12907455, upload-time = "2025-05-17T21:34:09.135Z" }, + { url = "https://files.pythonhosted.org/packages/82/5d/c00588b6cf18e1da539b45d3598d3557084990dcc4331960c15ee776ee41/numpy-2.2.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:41c5a21f4a04fa86436124d388f6ed60a9343a6f767fced1a8a71c3fbca038ff", size = 20875348, upload-time = "2025-05-17T21:34:39.648Z" }, + { url = "https://files.pythonhosted.org/packages/66/ee/560deadcdde6c2f90200450d5938f63a34b37e27ebff162810f716f6a230/numpy-2.2.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:de749064336d37e340f640b05f24e9e3dd678c57318c7289d222a8a2f543e90c", size = 14119362, upload-time = "2025-05-17T21:35:01.241Z" }, + { url = "https://files.pythonhosted.org/packages/3c/65/4baa99f1c53b30adf0acd9a5519078871ddde8d2339dc5a7fde80d9d87da/numpy-2.2.6-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:894b3a42502226a1cac872f840030665f33326fc3dac8e57c607905773cdcde3", size = 5084103, upload-time = "2025-05-17T21:35:10.622Z" }, + { url = "https://files.pythonhosted.org/packages/cc/89/e5a34c071a0570cc40c9a54eb472d113eea6d002e9ae12bb3a8407fb912e/numpy-2.2.6-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:71594f7c51a18e728451bb50cc60a3ce4e6538822731b2933209a1f3614e9282", size = 6625382, upload-time = "2025-05-17T21:35:21.414Z" }, + { url = "https://files.pythonhosted.org/packages/f8/35/8c80729f1ff76b3921d5c9487c7ac3de9b2a103b1cd05e905b3090513510/numpy-2.2.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f2618db89be1b4e05f7a1a847a9c1c0abd63e63a1607d892dd54668dd92faf87", size = 14018462, upload-time = "2025-05-17T21:35:42.174Z" }, + { url = "https://files.pythonhosted.org/packages/8c/3d/1e1db36cfd41f895d266b103df00ca5b3cbe965184df824dec5c08c6b803/numpy-2.2.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd83c01228a688733f1ded5201c678f0c53ecc1006ffbc404db9f7a899ac6249", size = 16527618, upload-time = "2025-05-17T21:36:06.711Z" }, + { url = "https://files.pythonhosted.org/packages/61/c6/03ed30992602c85aa3cd95b9070a514f8b3c33e31124694438d88809ae36/numpy-2.2.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:37c0ca431f82cd5fa716eca9506aefcabc247fb27ba69c5062a6d3ade8cf8f49", size = 15505511, upload-time = "2025-05-17T21:36:29.965Z" }, + { url = "https://files.pythonhosted.org/packages/b7/25/5761d832a81df431e260719ec45de696414266613c9ee268394dd5ad8236/numpy-2.2.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fe27749d33bb772c80dcd84ae7e8df2adc920ae8297400dabec45f0dedb3f6de", size = 18313783, upload-time = "2025-05-17T21:36:56.883Z" }, + { url = "https://files.pythonhosted.org/packages/57/0a/72d5a3527c5ebffcd47bde9162c39fae1f90138c961e5296491ce778e682/numpy-2.2.6-cp312-cp312-win32.whl", hash = "sha256:4eeaae00d789f66c7a25ac5f34b71a7035bb474e679f410e5e1a94deb24cf2d4", size = 6246506, upload-time = "2025-05-17T21:37:07.368Z" }, + { url = "https://files.pythonhosted.org/packages/36/fa/8c9210162ca1b88529ab76b41ba02d433fd54fecaf6feb70ef9f124683f1/numpy-2.2.6-cp312-cp312-win_amd64.whl", hash = "sha256:c1f9540be57940698ed329904db803cf7a402f3fc200bfe599334c9bd84a40b2", size = 12614190, upload-time = "2025-05-17T21:37:26.213Z" }, + { url = "https://files.pythonhosted.org/packages/f9/5c/6657823f4f594f72b5471f1db1ab12e26e890bb2e41897522d134d2a3e81/numpy-2.2.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0811bb762109d9708cca4d0b13c4f67146e3c3b7cf8d34018c722adb2d957c84", size = 20867828, upload-time = "2025-05-17T21:37:56.699Z" }, + { url = "https://files.pythonhosted.org/packages/dc/9e/14520dc3dadf3c803473bd07e9b2bd1b69bc583cb2497b47000fed2fa92f/numpy-2.2.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:287cc3162b6f01463ccd86be154f284d0893d2b3ed7292439ea97eafa8170e0b", size = 14143006, upload-time = "2025-05-17T21:38:18.291Z" }, + { url = "https://files.pythonhosted.org/packages/4f/06/7e96c57d90bebdce9918412087fc22ca9851cceaf5567a45c1f404480e9e/numpy-2.2.6-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:f1372f041402e37e5e633e586f62aa53de2eac8d98cbfb822806ce4bbefcb74d", size = 5076765, upload-time = "2025-05-17T21:38:27.319Z" }, + { url = "https://files.pythonhosted.org/packages/73/ed/63d920c23b4289fdac96ddbdd6132e9427790977d5457cd132f18e76eae0/numpy-2.2.6-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:55a4d33fa519660d69614a9fad433be87e5252f4b03850642f88993f7b2ca566", size = 6617736, upload-time = "2025-05-17T21:38:38.141Z" }, + { url = "https://files.pythonhosted.org/packages/85/c5/e19c8f99d83fd377ec8c7e0cf627a8049746da54afc24ef0a0cb73d5dfb5/numpy-2.2.6-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f92729c95468a2f4f15e9bb94c432a9229d0d50de67304399627a943201baa2f", size = 14010719, upload-time = "2025-05-17T21:38:58.433Z" }, + { url = "https://files.pythonhosted.org/packages/19/49/4df9123aafa7b539317bf6d342cb6d227e49f7a35b99c287a6109b13dd93/numpy-2.2.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1bc23a79bfabc5d056d106f9befb8d50c31ced2fbc70eedb8155aec74a45798f", size = 16526072, upload-time = "2025-05-17T21:39:22.638Z" }, + { url = "https://files.pythonhosted.org/packages/b2/6c/04b5f47f4f32f7c2b0e7260442a8cbcf8168b0e1a41ff1495da42f42a14f/numpy-2.2.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e3143e4451880bed956e706a3220b4e5cf6172ef05fcc397f6f36a550b1dd868", size = 15503213, upload-time = "2025-05-17T21:39:45.865Z" }, + { url = "https://files.pythonhosted.org/packages/17/0a/5cd92e352c1307640d5b6fec1b2ffb06cd0dabe7d7b8227f97933d378422/numpy-2.2.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b4f13750ce79751586ae2eb824ba7e1e8dba64784086c98cdbbcc6a42112ce0d", size = 18316632, upload-time = "2025-05-17T21:40:13.331Z" }, + { url = "https://files.pythonhosted.org/packages/f0/3b/5cba2b1d88760ef86596ad0f3d484b1cbff7c115ae2429678465057c5155/numpy-2.2.6-cp313-cp313-win32.whl", hash = "sha256:5beb72339d9d4fa36522fc63802f469b13cdbe4fdab4a288f0c441b74272ebfd", size = 6244532, upload-time = "2025-05-17T21:43:46.099Z" }, + { url = "https://files.pythonhosted.org/packages/cb/3b/d58c12eafcb298d4e6d0d40216866ab15f59e55d148a5658bb3132311fcf/numpy-2.2.6-cp313-cp313-win_amd64.whl", hash = "sha256:b0544343a702fa80c95ad5d3d608ea3599dd54d4632df855e4c8d24eb6ecfa1c", size = 12610885, upload-time = "2025-05-17T21:44:05.145Z" }, + { url = "https://files.pythonhosted.org/packages/6b/9e/4bf918b818e516322db999ac25d00c75788ddfd2d2ade4fa66f1f38097e1/numpy-2.2.6-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0bca768cd85ae743b2affdc762d617eddf3bcf8724435498a1e80132d04879e6", size = 20963467, upload-time = "2025-05-17T21:40:44Z" }, + { url = "https://files.pythonhosted.org/packages/61/66/d2de6b291507517ff2e438e13ff7b1e2cdbdb7cb40b3ed475377aece69f9/numpy-2.2.6-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:fc0c5673685c508a142ca65209b4e79ed6740a4ed6b2267dbba90f34b0b3cfda", size = 14225144, upload-time = "2025-05-17T21:41:05.695Z" }, + { url = "https://files.pythonhosted.org/packages/e4/25/480387655407ead912e28ba3a820bc69af9adf13bcbe40b299d454ec011f/numpy-2.2.6-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:5bd4fc3ac8926b3819797a7c0e2631eb889b4118a9898c84f585a54d475b7e40", size = 5200217, upload-time = "2025-05-17T21:41:15.903Z" }, + { url = "https://files.pythonhosted.org/packages/aa/4a/6e313b5108f53dcbf3aca0c0f3e9c92f4c10ce57a0a721851f9785872895/numpy-2.2.6-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:fee4236c876c4e8369388054d02d0e9bb84821feb1a64dd59e137e6511a551f8", size = 6712014, upload-time = "2025-05-17T21:41:27.321Z" }, + { url = "https://files.pythonhosted.org/packages/b7/30/172c2d5c4be71fdf476e9de553443cf8e25feddbe185e0bd88b096915bcc/numpy-2.2.6-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e1dda9c7e08dc141e0247a5b8f49cf05984955246a327d4c48bda16821947b2f", size = 14077935, upload-time = "2025-05-17T21:41:49.738Z" }, + { url = "https://files.pythonhosted.org/packages/12/fb/9e743f8d4e4d3c710902cf87af3512082ae3d43b945d5d16563f26ec251d/numpy-2.2.6-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f447e6acb680fd307f40d3da4852208af94afdfab89cf850986c3ca00562f4fa", size = 16600122, upload-time = "2025-05-17T21:42:14.046Z" }, + { url = "https://files.pythonhosted.org/packages/12/75/ee20da0e58d3a66f204f38916757e01e33a9737d0b22373b3eb5a27358f9/numpy-2.2.6-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:389d771b1623ec92636b0786bc4ae56abafad4a4c513d36a55dce14bd9ce8571", size = 15586143, upload-time = "2025-05-17T21:42:37.464Z" }, + { url = "https://files.pythonhosted.org/packages/76/95/bef5b37f29fc5e739947e9ce5179ad402875633308504a52d188302319c8/numpy-2.2.6-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8e9ace4a37db23421249ed236fdcdd457d671e25146786dfc96835cd951aa7c1", size = 18385260, upload-time = "2025-05-17T21:43:05.189Z" }, + { url = "https://files.pythonhosted.org/packages/09/04/f2f83279d287407cf36a7a8053a5abe7be3622a4363337338f2585e4afda/numpy-2.2.6-cp313-cp313t-win32.whl", hash = "sha256:038613e9fb8c72b0a41f025a7e4c3f0b7a1b5d768ece4796b674c8f3fe13efff", size = 6377225, upload-time = "2025-05-17T21:43:16.254Z" }, + { url = "https://files.pythonhosted.org/packages/67/0e/35082d13c09c02c011cf21570543d202ad929d961c02a147493cb0c2bdf5/numpy-2.2.6-cp313-cp313t-win_amd64.whl", hash = "sha256:6031dd6dfecc0cf9f668681a37648373bddd6421fff6c66ec1624eed0180ee06", size = 12771374, upload-time = "2025-05-17T21:43:35.479Z" }, + { url = "https://files.pythonhosted.org/packages/9e/3b/d94a75f4dbf1ef5d321523ecac21ef23a3cd2ac8b78ae2aac40873590229/numpy-2.2.6-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0b605b275d7bd0c640cad4e5d30fa701a8d59302e127e5f79138ad62762c3e3d", size = 21040391, upload-time = "2025-05-17T21:44:35.948Z" }, + { url = "https://files.pythonhosted.org/packages/17/f4/09b2fa1b58f0fb4f7c7963a1649c64c4d315752240377ed74d9cd878f7b5/numpy-2.2.6-pp310-pypy310_pp73-macosx_14_0_x86_64.whl", hash = "sha256:7befc596a7dc9da8a337f79802ee8adb30a552a94f792b9c9d18c840055907db", size = 6786754, upload-time = "2025-05-17T21:44:47.446Z" }, + { url = "https://files.pythonhosted.org/packages/af/30/feba75f143bdc868a1cc3f44ccfa6c4b9ec522b36458e738cd00f67b573f/numpy-2.2.6-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce47521a4754c8f4593837384bd3424880629f718d87c5d44f8ed763edd63543", size = 16643476, upload-time = "2025-05-17T21:45:11.871Z" }, + { url = "https://files.pythonhosted.org/packages/37/48/ac2a9584402fb6c0cd5b5d1a91dcf176b15760130dd386bbafdbfe3640bf/numpy-2.2.6-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:d042d24c90c41b54fd506da306759e06e568864df8ec17ccc17e9e884634fd00", size = 12812666, upload-time = "2025-05-17T21:45:31.426Z" }, +] + +[[package]] +name = "numpy" +version = "2.4.6" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version == '3.11.*' and sys_platform == 'win32'", + "python_full_version == '3.11.*' and sys_platform == 'emscripten'", + "python_full_version == '3.11.*' and sys_platform != 'emscripten' 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.4" +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 == 'emscripten'", + "python_full_version >= '3.14' and sys_platform != 'emscripten' 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 == 'emscripten'", + "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", +] +sdist = { url = "https://files.pythonhosted.org/packages/95/b0/c7453d0b6e2073c3264468b106ee1563750cecc910965e67357e3698c83e/numpy-2.5.4.tar.gz", hash = "sha256:9a94cf751c9ad8ebaa835bcd3d40dacf8534ad086b88c38029b65123c7999d2a", size = 20866315, upload-time = "2026-10-10T20:05:31.422Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d0/97/ba2074e92b7befea137e77ea8471e768bbd87c339b7e8c9f5a931949f977/numpy-2.5.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c6342f54c67093cae5c0227eb0eb772fdb79f2a2c37a6eb278b9909ee06aa356", size = 17001609, upload-time = "2026-10-10T20:02:40.843Z" }, + { url = "https://files.pythonhosted.org/packages/ff/a9/bac826765e971d8e16e2064e9ac7525fd69b40ac17c905033a7f5442023f/numpy-2.5.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b11e8fda06a7d69f15ebf542660b74466c2e51094800c1fb794f47ad4faeef17", size = 12015718, upload-time = "2026-10-10T20:02:43.45Z" }, + { url = "https://files.pythonhosted.org/packages/31/2f/5ea3570fcb8ccd0882bea99436a513b2c85dad8f774a2057849130a8fb99/numpy-2.5.4-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:9cb18a327b49c5c337f972b03682f6a49855525faaf3c0d3e9c96cd0fd8880a8", size = 5451717, upload-time = "2026-10-10T20:02:46.169Z" }, + { url = "https://files.pythonhosted.org/packages/34/f2/b4fc1bafca03868220b5eaf729d2f21ebd7d7b151c0f9e144fe212bbca35/numpy-2.5.4-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:aec3fc4b32ff82421274f5d205c559c51c840c8df66a78efd7f3612dd005a26a", size = 6789926, upload-time = "2026-10-10T20:02:48.139Z" }, + { url = "https://files.pythonhosted.org/packages/dc/96/8319e2457ae4333c62c815c7006b869a4f60985c1e01024c2f8c6c040fe5/numpy-2.5.4-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fe4d21ab149f15e4e6043dfb0de87e6e5f34ac176cde83060e9802981fca2ac2", size = 15695312, upload-time = "2026-10-10T20:02:50.115Z" }, + { url = "https://files.pythonhosted.org/packages/43/a3/c799c62e19c337e6d3770b08e475887fb30ce8477d3c09efca6b2f0228a6/numpy-2.5.4-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fbde6962867ee75b48b0ee29b2b9372ec5d617799dbaf38e82dc0596f2f7738a", size = 16727283, upload-time = "2026-10-10T20:02:53.186Z" }, + { url = "https://files.pythonhosted.org/packages/39/6b/3604e53fb00314d0dc1b94ec9125a1484f649c0a17480b1f0f0c7a9d6250/numpy-2.5.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:381a7a3d2e65e64c0ec302795ab9dc12bb1e73f150904699c153716177eebdaf", size = 17047890, upload-time = "2026-10-10T20:02:56.038Z" }, + { url = "https://files.pythonhosted.org/packages/4a/7a/e8b58a5289a0d464c52885de47c35a935cdd70c03a4c3ab94a5126416dd0/numpy-2.5.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b89d0aaae2fe498c648f4c4795c084db535af5bd98ef942b2a3681fb74ce8645", size = 18485839, upload-time = "2026-10-10T20:02:59.018Z" }, + { url = "https://files.pythonhosted.org/packages/6f/c9/47094f597015009f310b8c900def59065ef1ff5a6fe7b51fc65ec58ec2c6/numpy-2.5.4-cp312-cp312-win32.whl", hash = "sha256:9968ab7e49b93ac6e1c3b2239732183152c9150f16308d30b66a372cffe3483c", size = 6138936, upload-time = "2026-10-10T20:03:01.626Z" }, + { url = "https://files.pythonhosted.org/packages/12/33/fefe62073dc8acfd0f2b9ed7c003af2f50aa61555e113e6db02b8f79f145/numpy-2.5.4-cp312-cp312-win_amd64.whl", hash = "sha256:a7b1b6353e36a7e50de2973a38d705c88ee93adcf120673cee7f45a4a3fa223a", size = 12573091, upload-time = "2026-10-10T20:03:04.349Z" }, + { url = "https://files.pythonhosted.org/packages/1a/07/161270b0c2eec56e4c905f6d6d22e1b836887b2cb189d3f5820aa588e9dd/numpy-2.5.4-cp312-cp312-win_arm64.whl", hash = "sha256:aa1cce2ff3f8d953de38b76bf44602caeb69f101430208f64a10067f7cb4b1d3", size = 10521630, upload-time = "2026-10-10T20:03:06.767Z" }, + { url = "https://files.pythonhosted.org/packages/67/14/1c3ee0118a8fce08565a5d8482631608426a33af10a01077fada5dc7c119/numpy-2.5.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:2377da2dd3ba2c1200956acbab2a358c83b8e1f8531191672d1cd6ad83250d53", size = 16997729, upload-time = "2026-10-10T20:03:09.291Z" }, + { url = "https://files.pythonhosted.org/packages/83/8c/b0ea9477fb1f0d4484bbc5cba21678cc9969704d8d7f3f158d1db35f8e14/numpy-2.5.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7415db95818b39ec475a5eea54d9e3b6bc83e3912158e46da3438cdce399804d", size = 12009826, upload-time = "2026-10-10T20:03:11.946Z" }, + { url = "https://files.pythonhosted.org/packages/e2/84/6a3d75b3ba3dfe84ac0053450753d1e6d250a8bf80f66474cc46d1fb643f/numpy-2.5.4-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:6d6a71b9d9a97c03633aa12565ef2825ffa036cc1d99cfd50dacf0f128af4fe2", size = 5445803, upload-time = "2026-10-10T20:03:14.329Z" }, + { url = "https://files.pythonhosted.org/packages/61/18/bb993f267ca20b376e07092a16793a5b31ed3138751e9ba480011a14d742/numpy-2.5.4-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:d8200f16437b289a5bb927c6e184eccc3e8389bc0070fea4cd5b9e13c1757959", size = 6786220, upload-time = "2026-10-10T20:03:16.602Z" }, + { url = "https://files.pythonhosted.org/packages/db/b6/135bb0953b61dc21c6cafa14b424ae666944e4899cf140e00c2b322a1a45/numpy-2.5.4-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1c2e71b04c6cad90026e544501bbe0ab9290fa8a4d845e7e8c0d124fb429c988", size = 15689178, upload-time = "2026-10-10T20:03:18.721Z" }, + { url = "https://files.pythonhosted.org/packages/da/24/3bd070f3269dc609d8f26b2643f62ef91bb415841c0b294805aaf7fe06da/numpy-2.5.4-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6ffa07666f8da0eef81d149934a626d0d95fbd6838432a33e66245423a9062c0", size = 16718044, upload-time = "2026-10-10T20:03:21.386Z" }, + { url = "https://files.pythonhosted.org/packages/c7/8e/9d15bd356b0a019c965312b1a3c6a727cac4cae5bc40045fbc12ce4cff9c/numpy-2.5.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2fa3328f784fc8277fc48026f6cad516f5c561c5d8e2e39b3c9e0c8f23223b34", size = 17048364, upload-time = "2026-10-10T20:03:24.468Z" }, + { url = "https://files.pythonhosted.org/packages/dc/fe/9d5b560db964f15871885f2250795d15945f8699e17ef90c0c2ff4c875b2/numpy-2.5.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b86966fbe4ad7de710422175572bcdc75fdedadfb54bc6fab7deabccddd7780b", size = 18474904, upload-time = "2026-10-10T20:03:27.895Z" }, + { url = "https://files.pythonhosted.org/packages/e9/98/d27552990f1bd611ef3e7466adadc78312ea2df63b83aad47fdc3d3ca8df/numpy-2.5.4-cp313-cp313-win32.whl", hash = "sha256:5258bc06526964be5face2fc6f756857a3f24f21ec3e72ca131337a75b165d6c", size = 6134537, upload-time = "2026-10-10T20:03:30.511Z" }, + { url = "https://files.pythonhosted.org/packages/90/8c/140a40398a66b4471211be1affdb6ed24c486d581bd28d07b7f2fcb69540/numpy-2.5.4-cp313-cp313-win_amd64.whl", hash = "sha256:8b4d2fd2d34e5f8c9235ee787de5631a37a28402b15cb80814df973d2be54129", size = 12566113, upload-time = "2026-10-10T20:03:32.612Z" }, + { url = "https://files.pythonhosted.org/packages/34/52/01d205e5e8ccb27b2b0b141e801f22b830198c979111b0fa44771438d9a9/numpy-2.5.4-cp313-cp313-win_arm64.whl", hash = "sha256:bc39ac66a7a9a3fbd6134fda43136b60ffde99c8f4501e64e0d2b24da137babf", size = 10519523, upload-time = "2026-10-10T20:03:35.163Z" }, + { url = "https://files.pythonhosted.org/packages/99/ba/005cb5edd580d2f84d7ca3206b92dc17d4388e56e6f87ffe8f2762f83139/numpy-2.5.4-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:c668b2f0d651605b58892644b0e302c7157f7159544227758c896982ef384b18", size = 17005499, upload-time = "2026-10-10T20:03:37.961Z" }, + { url = "https://files.pythonhosted.org/packages/f3/49/fee7587c33ee35f7977f9051d7f2023d4e7246d62710c80f20c2361ea232/numpy-2.5.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ffa6ce09a1c6a08e9667dd9c97aa0b14184e8d18f2a14b78b2a2328c9147f076", size = 12019666, upload-time = "2026-10-10T20:03:40.606Z" }, + { url = "https://files.pythonhosted.org/packages/d5/b2/c6ce165acffceb15a82c07b9cc77d391f86b3f379ba62911908ae5d34b91/numpy-2.5.4-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:956555e0603a4d38019ae6925711cb9dc43195c076a928accf7ea5d50bddfe53", size = 5455617, upload-time = "2026-10-10T20:03:43.138Z" }, + { url = "https://files.pythonhosted.org/packages/77/7f/dd85ce260a669a89be06842cf355d7353a33e6cfbc590fb8ebb947d88dc9/numpy-2.5.4-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:2c2c4afffdeb7920e445028dd71eb932cac3e704792e964bc2a232426d4f1255", size = 6791932, upload-time = "2026-10-10T20:03:44.874Z" }, + { url = "https://files.pythonhosted.org/packages/63/d6/34b0a2b0741386a63025a65a2c09caaaaaad6d0ca95b66cd65c30dd7fcb5/numpy-2.5.4-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4054173604cd8658796053f1f3bc0befb68ec1c0762c57fdad61e199256a8617", size = 15710899, upload-time = "2026-10-10T20:03:46.839Z" }, + { url = "https://files.pythonhosted.org/packages/16/d5/928078d2b28f26829b138b4a6c3980045022fb409f570657a224ae60ef4e/numpy-2.5.4-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d549420b8858885cea8838a727842249218b9c1da24dd517e25c9c7a948310a3", size = 16721710, upload-time = "2026-10-10T20:03:49.489Z" }, + { url = "https://files.pythonhosted.org/packages/f9/cf/673fd1b8f4cd78eb6320e87ec4c90ac19c095644259e3749853a405c70f4/numpy-2.5.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:823874a507a84af050493b622affde94b6f7c3a0dc22cb2801381bc03b871c00", size = 17066182, upload-time = "2026-10-10T20:03:52.25Z" }, + { url = "https://files.pythonhosted.org/packages/f3/92/a77b5061b1b3e2643928c37976d79ee173e1b171ed158b7a3c61056b41bc/numpy-2.5.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:4e263278bfb5ee6409db8aedbc4cc32973b1b82bc1e8d3c668551d04d83a7e37", size = 18480315, upload-time = "2026-10-10T20:03:55.39Z" }, + { url = "https://files.pythonhosted.org/packages/bb/1d/1486ef3d3fb2279fd93c4c43c1bbbf1ca389a19816696684409f71babaab/numpy-2.5.4-cp314-cp314-win32.whl", hash = "sha256:cfd73180400042a7c532d30c5e287bdd03c59ff9ee1b4c0316af0539e29dfe23", size = 6185739, upload-time = "2026-10-10T20:03:58.186Z" }, + { url = "https://files.pythonhosted.org/packages/52/9a/e1e512ebc948d5b9dd33b08736760f0ebbed2848fd4eda1f553088a6dcee/numpy-2.5.4-cp314-cp314-win_amd64.whl", hash = "sha256:2ca144f15135b6212a5c47b1e2aeca6e412f102f95a2d5d88d8aec77eb255de3", size = 12703552, upload-time = "2026-10-10T20:04:00.28Z" }, + { url = "https://files.pythonhosted.org/packages/2c/05/de709a982d7bbcd688a3fad71f002e9ff80c2db39e03ee726609b610f1d1/numpy-2.5.4-cp314-cp314-win_arm64.whl", hash = "sha256:468397ba3c64427474706e5c9123fe266395496714dc684294eac75cd4930d1e", size = 10803901, upload-time = "2026-10-10T20:04:02.659Z" }, + { url = "https://files.pythonhosted.org/packages/13/34/083570ada3bb2a30fbe5d77c8c6fef9141144a15d33e6f793a67e9749ab8/numpy-2.5.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1ef3aa6d7e29bb13677323114280b05acc57607fa2300e66432d665d5418a162", size = 12138695, upload-time = "2026-10-10T20:04:05.012Z" }, + { url = "https://files.pythonhosted.org/packages/94/06/1f9c24db48eef0c2d1207e3b11fffb0478e39dfd8c1e1be7476936885eed/numpy-2.5.4-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:98b053943e5a0474ec0da309d2cb9d3f18ea57f8a2067c2ab7b5f763d1068380", size = 5574615, upload-time = "2026-10-10T20:04:07.316Z" }, + { url = "https://files.pythonhosted.org/packages/da/0f/593fba2e1560e949123bc7d2fc48b5893d56e58cd4bd5a273d2fbf60b220/numpy-2.5.4-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:b64a85f40e154983960a4167d4c1d57a50c7f109b3d3264a3a984154e90a8454", size = 6889383, upload-time = "2026-10-10T20:04:09.918Z" }, + { url = "https://files.pythonhosted.org/packages/eb/9f/b799dfdce4e05e80ed4bc815c71ff343a11533b2c0ffc221cae8538cda63/numpy-2.5.4-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a813ed7719bf45463c51779e6a98d0385fe905e48447526938a4b8337333d551", size = 15753763, upload-time = "2026-10-10T20:04:12.278Z" }, + { url = "https://files.pythonhosted.org/packages/34/88/16c5f12f86f5ad2817c4d103205131fc6c8acb3d1878af05a1a4f23ec859/numpy-2.5.4-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c9b80cdf5cedba0e90d93fa5f9a333c4d65bd545cd669b71bb97ce2b703c9d73", size = 16757212, upload-time = "2026-10-10T20:04:14.799Z" }, + { url = "https://files.pythonhosted.org/packages/ff/4f/a1fe40e18a898e6a5089f4f0d891f0a493eb0574d5b34458f0fbe5aa3e5c/numpy-2.5.4-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:2199ed071f460487c8db2c0e5c0b564494190edb4772fe80f9aad88b2604def5", size = 17116471, upload-time = "2026-10-10T20:04:17.58Z" }, + { url = "https://files.pythonhosted.org/packages/aa/46/e923a11c78e65c1722e7aaad817c06bd591324174b9d28ce5d31eee4d432/numpy-2.5.4-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:64f9c9878c1938476365e11ccfb6b770f3b9e5f045ccddc514235041e6959365", size = 18524063, upload-time = "2026-10-10T20:04:20.365Z" }, + { url = "https://files.pythonhosted.org/packages/5a/fa/84ab064514440c1f64a1b21088f2c82756defdd05e07c75ab233899565b2/numpy-2.5.4-cp314-cp314t-win32.whl", hash = "sha256:64d1c8ac28a4077cf987e0a71a7a0ef7e2df70722f07f0baa42dbb7eb6938647", size = 6340926, upload-time = "2026-10-10T20:04:22.865Z" }, + { url = "https://files.pythonhosted.org/packages/7e/7e/6cd886876f435b10685db9b9f7eeb70356f99e052116f4e5f11c5792c714/numpy-2.5.4-cp314-cp314t-win_amd64.whl", hash = "sha256:067374eb538c34c745436365cf7b0112595c1d326f21ce4ff340f61230239fbb", size = 12901584, upload-time = "2026-10-10T20:04:24.99Z" }, + { url = "https://files.pythonhosted.org/packages/38/1b/3c1684f6a06f7307f2335fca6e486cb162847fb97e91d65f8eb5cabad213/numpy-2.5.4-cp314-cp314t-win_arm64.whl", hash = "sha256:e94aef2c639da4a960ad0db8e06471208d8589974953d78b61d345b4eb99e394", size = 10891152, upload-time = "2026-10-10T20:04:27.52Z" }, + { url = "https://files.pythonhosted.org/packages/08/f4/3224deff3af2bef6bc0b175369698d8cb348f3d91d9bb0286cd5c9eae9e0/numpy-2.5.4-cp315-cp315-macosx_10_15_x86_64.whl", hash = "sha256:8dddfbee2e68d26d0d7d7d9cb247b1fd4409241cce32d815a11d97ec2cfde179", size = 17003231, upload-time = "2026-10-10T20:04:30.021Z" }, + { url = "https://files.pythonhosted.org/packages/be/75/fee0b8c6d94b44b2fdfae74f6a4ad5a138739589a8aebaec28ce4e713ed5/numpy-2.5.4-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:81e3420b27048b65eb14c3acf0c174a8cb0e023277716110347d2dcb26026dad", size = 12018300, upload-time = "2026-10-10T20:04:32.519Z" }, + { url = "https://files.pythonhosted.org/packages/47/c0/d0b335a499a04b65f532c3f034346ef390f81299060f928492dabc1e0272/numpy-2.5.4-cp315-cp315-macosx_14_0_arm64.whl", hash = "sha256:0b4724a19de67bea8cfc4970798efa78bcbbe2ac2613cfac16721a42d44de2a5", size = 5454250, upload-time = "2026-10-10T20:04:34.943Z" }, + { url = "https://files.pythonhosted.org/packages/5a/0e/461b3783c03d668052e6a21b01b673db6ffcb7831fd32d9aa5368c1cd426/numpy-2.5.4-cp315-cp315-macosx_14_0_x86_64.whl", hash = "sha256:2132418bf8dd124a427ca9e6a1daf9ee1a87185344c95119ceae868b99466da1", size = 6789644, upload-time = "2026-10-10T20:04:37.258Z" }, + { url = "https://files.pythonhosted.org/packages/b3/02/5dad269b02166965a7b4ca14adaddd75dbee0de42435bfecf561b84ba5a6/numpy-2.5.4-cp315-cp315-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:325518d4245b9e331387702aa58c2ce1dc4cdcbb41dfb4ccd5dcbc7e08db1266", size = 15704353, upload-time = "2026-10-10T20:04:39.616Z" }, + { url = "https://files.pythonhosted.org/packages/93/3a/01360c8036822ed9f7aa32189a77d1476567ec1e8e1383522389e4faac45/numpy-2.5.4-cp315-cp315-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:56733449d2544178beaa4545cee357370440cf056c197f9c7bfb19dbfdd0e86d", size = 16718648, upload-time = "2026-10-10T20:04:42.383Z" }, + { url = "https://files.pythonhosted.org/packages/7d/5c/b863a2c093c4d6f21a597fcaf24ead0835c09ab16a8312d5a5a8868af683/numpy-2.5.4-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:5ec3753760c1a6d8bb91200666e545c3a9728e6269dfb5d6ce02340996698aa3", size = 17059053, upload-time = "2026-10-10T20:04:44.976Z" }, + { url = "https://files.pythonhosted.org/packages/0a/60/ced4f57f9a1258a0af74f17cb0b0c2700b5c67cd6678823c803b263e4df3/numpy-2.5.4-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:b1185012870173de7ae33d370bd45b1cf5baee747ea4b97036b65f4e93016877", size = 18477406, upload-time = "2026-10-10T20:04:47.863Z" }, + { url = "https://files.pythonhosted.org/packages/f9/bd/0ef22dafaafcc7d4bb3ca26b8d2afbd55dedad8eaba99a8c864e1997456f/numpy-2.5.4-cp315-cp315-win32.whl", hash = "sha256:298eca75243f2cbbfdb460560b9fb2a1792a33cf2ab4286efd43d92e8d3df508", size = 6185133, upload-time = "2026-10-10T20:04:50.467Z" }, + { url = "https://files.pythonhosted.org/packages/50/bc/d2651b155ecc608a77e6f4d15495c11f14f19bb98f8bf0c5b0d38f86dda1/numpy-2.5.4-cp315-cp315-win_amd64.whl", hash = "sha256:332f3378fe077dd850e677ec01bdcc4f22368fb5d50ef10b2c79230b1bf5a592", size = 12703085, upload-time = "2026-10-10T20:04:52.63Z" }, + { url = "https://files.pythonhosted.org/packages/dc/d2/45e404f8abb26fb9eda12b94012936873e827b1be76f2ee7890be128312e/numpy-2.5.4-cp315-cp315-win_arm64.whl", hash = "sha256:d4cccbbc78717966f764cd3af4fb70276fa01fc7a2688af11c78901fa5c04f05", size = 10801451, upload-time = "2026-10-10T20:04:55.677Z" }, + { url = "https://files.pythonhosted.org/packages/c6/c3/2ae14e09cfdb67dc187a342e15308a21c15bf4d2071f8079e6aee5fe56dc/numpy-2.5.4-cp315-cp315t-macosx_10_15_x86_64.whl", hash = "sha256:950ea81d57ef070665581b6e1b5f6a029306423cd1739c5b95fe78aa30db6b9d", size = 17097121, upload-time = "2026-10-10T20:04:58.403Z" }, + { url = "https://files.pythonhosted.org/packages/f5/cf/305ae624ef8a039414317224abe9ec9c2fe7ea3c2e1cf204d43ff6b2ffb9/numpy-2.5.4-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:c05ede731b03fb1b7591faca9389ade3267d2bddf1ad8882bb3f2cc5e101694f", size = 12135439, upload-time = "2026-10-10T20:05:01.65Z" }, + { url = "https://files.pythonhosted.org/packages/a9/a8/f75c63813aef95827bb2c0d13b12803016853056e8792c280058cdbfe783/numpy-2.5.4-cp315-cp315t-macosx_14_0_arm64.whl", hash = "sha256:5fbf7141bbfd63aea22f435c9062a032b9ea0082fe9845dad7f021d3f1234e71", size = 5571451, upload-time = "2026-10-10T20:05:04.135Z" }, + { url = "https://files.pythonhosted.org/packages/6f/0f/f17763f983868b5c49b4101ebd7e00760bd1769478a6bb6a8de6e085bbac/numpy-2.5.4-cp315-cp315t-macosx_14_0_x86_64.whl", hash = "sha256:3573cd22564692a5b899ec344e5d5b9cc4576f2985b96f22af3564ed54f2710f", size = 6883356, upload-time = "2026-10-10T20:05:06.249Z" }, + { url = "https://files.pythonhosted.org/packages/67/a7/8af04c5a79e047996cfa38854dcfbececdd0343a7c933a46fdd03ef6f5da/numpy-2.5.4-cp315-cp315t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6c109eac9cd439193678f69d70733c1108487546ca8eafc107b510ae10c1aecd", size = 15750991, upload-time = "2026-10-10T20:05:08.376Z" }, + { url = "https://files.pythonhosted.org/packages/57/7a/648254290d0c504faa8f2d07aa206660c728802c781a6f3fc68ab7cb5d71/numpy-2.5.4-cp315-cp315t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:80d6ef6e8620eb2c2b4c4caad50b5935d6db3cde2d51581b55dcc79e14016d1d", size = 16757675, upload-time = "2026-10-10T20:05:11.393Z" }, + { url = "https://files.pythonhosted.org/packages/b8/fe/4a8c3cdb0c70400cfe4c5bec42d3099a5673802a95064614b33e07b82aa1/numpy-2.5.4-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:77045a4b175bbf5316ec08003880804336c78f92281a1b72222b274ea85ec5ac", size = 17113846, upload-time = "2026-10-10T20:05:14.49Z" }, + { url = "https://files.pythonhosted.org/packages/1b/7e/619692bb67778702c0e9eb2d468568a7573f4e269386ea61aed01ee4e557/numpy-2.5.4-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:0f02a46e49cfb6c73bdb7aea1c0d3461dbae9aba613542b65f657cd3d17b9fab", size = 18522915, upload-time = "2026-10-10T20:05:17.33Z" }, + { url = "https://files.pythonhosted.org/packages/b7/b5/4da41c328788f575838f97a098fe8ca691ebc6f6fd73ad4a262ee40b184d/numpy-2.5.4-cp315-cp315t-win32.whl", hash = "sha256:ad62a416ddcf863bf44bba76fbf6b53366ab0692e294f51cae4b5fbe0d246788", size = 6335804, upload-time = "2026-10-10T20:05:19.921Z" }, + { url = "https://files.pythonhosted.org/packages/98/94/6482ddfa3d312490cb9358f375bf2ad56427dbea8769187158e94d653753/numpy-2.5.4-cp315-cp315t-win_amd64.whl", hash = "sha256:38f47be9f74ab870d2633b5456ae519c43758a8d1fd05342f0ce4ecc034396ee", size = 12890095, upload-time = "2026-10-10T20:05:21.875Z" }, + { url = "https://files.pythonhosted.org/packages/48/7f/c2d1b436b6e7cfebac140c2579a298344b85f2991a2ce5c3615cefb29400/numpy-2.5.4-cp315-cp315t-win_arm64.whl", hash = "sha256:7a14a461d9340f1b46b8648578aed9cdb8b3b018a8fac6c1dde2c9192a01a87f", size = 10883718, upload-time = "2026-10-10T20:05:28.547Z" }, +] + +[[package]] +name = "packaging" +version = "26.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7d/fa/3944b40b07da9ce895c0e6303a5ab7d53da063554f534556b134a54d6093/packaging-26.3.tar.gz", hash = "sha256:94edc256424af38762eb31306eed28beb9f0efc50a8837492c9d6fd6004aed79", size = 313412, upload-time = "2026-08-04T18:15:28.737Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/63/34/ba1c580383c9eada3711951fef0795c80b829a078d72188184bcab9dd527/packaging-26.3-py3-none-any.whl", hash = "sha256:d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c", size = 129956, upload-time = "2026-08-04T18:15:27.159Z" }, +] + +[[package]] +name = "pandas" +version = "2.3.3" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.11'", +] +dependencies = [ + { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "python-dateutil", marker = "python_full_version < '3.11'" }, + { name = "pytz", marker = "python_full_version < '3.11'" }, + { name = "tzdata", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/33/01/d40b85317f86cf08d853a4f495195c73815fdf205eef3993821720274518/pandas-2.3.3.tar.gz", hash = "sha256:e05e1af93b977f7eafa636d043f9f94c7ee3ac81af99c13508215942e64c993b", size = 4495223, upload-time = "2025-09-29T23:34:51.853Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3d/f7/f425a00df4fcc22b292c6895c6831c0c8ae1d9fac1e024d16f98a9ce8749/pandas-2.3.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:376c6446ae31770764215a6c937f72d917f214b43560603cd60da6408f183b6c", size = 11555763, upload-time = "2025-09-29T23:16:53.287Z" }, + { url = "https://files.pythonhosted.org/packages/13/4f/66d99628ff8ce7857aca52fed8f0066ce209f96be2fede6cef9f84e8d04f/pandas-2.3.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e19d192383eab2f4ceb30b412b22ea30690c9e618f78870357ae1d682912015a", size = 10801217, upload-time = "2025-09-29T23:17:04.522Z" }, + { url = "https://files.pythonhosted.org/packages/1d/03/3fc4a529a7710f890a239cc496fc6d50ad4a0995657dccc1d64695adb9f4/pandas-2.3.3-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5caf26f64126b6c7aec964f74266f435afef1c1b13da3b0636c7518a1fa3e2b1", size = 12148791, upload-time = "2025-09-29T23:17:18.444Z" }, + { url = "https://files.pythonhosted.org/packages/40/a8/4dac1f8f8235e5d25b9955d02ff6f29396191d4e665d71122c3722ca83c5/pandas-2.3.3-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dd7478f1463441ae4ca7308a70e90b33470fa593429f9d4c578dd00d1fa78838", size = 12769373, upload-time = "2025-09-29T23:17:35.846Z" }, + { url = "https://files.pythonhosted.org/packages/df/91/82cc5169b6b25440a7fc0ef3a694582418d875c8e3ebf796a6d6470aa578/pandas-2.3.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4793891684806ae50d1288c9bae9330293ab4e083ccd1c5e383c34549c6e4250", size = 13200444, upload-time = "2025-09-29T23:17:49.341Z" }, + { url = "https://files.pythonhosted.org/packages/10/ae/89b3283800ab58f7af2952704078555fa60c807fff764395bb57ea0b0dbd/pandas-2.3.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:28083c648d9a99a5dd035ec125d42439c6c1c525098c58af0fc38dd1a7a1b3d4", size = 13858459, upload-time = "2025-09-29T23:18:03.722Z" }, + { url = "https://files.pythonhosted.org/packages/85/72/530900610650f54a35a19476eca5104f38555afccda1aa11a92ee14cb21d/pandas-2.3.3-cp310-cp310-win_amd64.whl", hash = "sha256:503cf027cf9940d2ceaa1a93cfb5f8c8c7e6e90720a2850378f0b3f3b1e06826", size = 11346086, upload-time = "2025-09-29T23:18:18.505Z" }, + { url = "https://files.pythonhosted.org/packages/c1/fa/7ac648108144a095b4fb6aa3de1954689f7af60a14cf25583f4960ecb878/pandas-2.3.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:602b8615ebcc4a0c1751e71840428ddebeb142ec02c786e8ad6b1ce3c8dec523", size = 11578790, upload-time = "2025-09-29T23:18:30.065Z" }, + { url = "https://files.pythonhosted.org/packages/9b/35/74442388c6cf008882d4d4bdfc4109be87e9b8b7ccd097ad1e7f006e2e95/pandas-2.3.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8fe25fc7b623b0ef6b5009149627e34d2a4657e880948ec3c840e9402e5c1b45", size = 10833831, upload-time = "2025-09-29T23:38:56.071Z" }, + { url = "https://files.pythonhosted.org/packages/fe/e4/de154cbfeee13383ad58d23017da99390b91d73f8c11856f2095e813201b/pandas-2.3.3-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b468d3dad6ff947df92dcb32ede5b7bd41a9b3cceef0a30ed925f6d01fb8fa66", size = 12199267, upload-time = "2025-09-29T23:18:41.627Z" }, + { url = "https://files.pythonhosted.org/packages/bf/c9/63f8d545568d9ab91476b1818b4741f521646cbdd151c6efebf40d6de6f7/pandas-2.3.3-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b98560e98cb334799c0b07ca7967ac361a47326e9b4e5a7dfb5ab2b1c9d35a1b", size = 12789281, upload-time = "2025-09-29T23:18:56.834Z" }, + { url = "https://files.pythonhosted.org/packages/f2/00/a5ac8c7a0e67fd1a6059e40aa08fa1c52cc00709077d2300e210c3ce0322/pandas-2.3.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1d37b5848ba49824e5c30bedb9c830ab9b7751fd049bc7914533e01c65f79791", size = 13240453, upload-time = "2025-09-29T23:19:09.247Z" }, + { url = "https://files.pythonhosted.org/packages/27/4d/5c23a5bc7bd209231618dd9e606ce076272c9bc4f12023a70e03a86b4067/pandas-2.3.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:db4301b2d1f926ae677a751eb2bd0e8c5f5319c9cb3f88b0becbbb0b07b34151", size = 13890361, upload-time = "2025-09-29T23:19:25.342Z" }, + { url = "https://files.pythonhosted.org/packages/8e/59/712db1d7040520de7a4965df15b774348980e6df45c129b8c64d0dbe74ef/pandas-2.3.3-cp311-cp311-win_amd64.whl", hash = "sha256:f086f6fe114e19d92014a1966f43a3e62285109afe874f067f5abbdcbb10e59c", size = 11348702, upload-time = "2025-09-29T23:19:38.296Z" }, + { url = "https://files.pythonhosted.org/packages/9c/fb/231d89e8637c808b997d172b18e9d4a4bc7bf31296196c260526055d1ea0/pandas-2.3.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6d21f6d74eb1725c2efaa71a2bfc661a0689579b58e9c0ca58a739ff0b002b53", size = 11597846, upload-time = "2025-09-29T23:19:48.856Z" }, + { url = "https://files.pythonhosted.org/packages/5c/bd/bf8064d9cfa214294356c2d6702b716d3cf3bb24be59287a6a21e24cae6b/pandas-2.3.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3fd2f887589c7aa868e02632612ba39acb0b8948faf5cc58f0850e165bd46f35", size = 10729618, upload-time = "2025-09-29T23:39:08.659Z" }, + { url = "https://files.pythonhosted.org/packages/57/56/cf2dbe1a3f5271370669475ead12ce77c61726ffd19a35546e31aa8edf4e/pandas-2.3.3-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ecaf1e12bdc03c86ad4a7ea848d66c685cb6851d807a26aa245ca3d2017a1908", size = 11737212, upload-time = "2025-09-29T23:19:59.765Z" }, + { url = "https://files.pythonhosted.org/packages/e5/63/cd7d615331b328e287d8233ba9fdf191a9c2d11b6af0c7a59cfcec23de68/pandas-2.3.3-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b3d11d2fda7eb164ef27ffc14b4fcab16a80e1ce67e9f57e19ec0afaf715ba89", size = 12362693, upload-time = "2025-09-29T23:20:14.098Z" }, + { url = "https://files.pythonhosted.org/packages/a6/de/8b1895b107277d52f2b42d3a6806e69cfef0d5cf1d0ba343470b9d8e0a04/pandas-2.3.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a68e15f780eddf2b07d242e17a04aa187a7ee12b40b930bfdd78070556550e98", size = 12771002, upload-time = "2025-09-29T23:20:26.76Z" }, + { url = "https://files.pythonhosted.org/packages/87/21/84072af3187a677c5893b170ba2c8fbe450a6ff911234916da889b698220/pandas-2.3.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:371a4ab48e950033bcf52b6527eccb564f52dc826c02afd9a1bc0ab731bba084", size = 13450971, upload-time = "2025-09-29T23:20:41.344Z" }, + { url = "https://files.pythonhosted.org/packages/86/41/585a168330ff063014880a80d744219dbf1dd7a1c706e75ab3425a987384/pandas-2.3.3-cp312-cp312-win_amd64.whl", hash = "sha256:a16dcec078a01eeef8ee61bf64074b4e524a2a3f4b3be9326420cabe59c4778b", size = 10992722, upload-time = "2025-09-29T23:20:54.139Z" }, + { url = "https://files.pythonhosted.org/packages/cd/4b/18b035ee18f97c1040d94debd8f2e737000ad70ccc8f5513f4eefad75f4b/pandas-2.3.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:56851a737e3470de7fa88e6131f41281ed440d29a9268dcbf0002da5ac366713", size = 11544671, upload-time = "2025-09-29T23:21:05.024Z" }, + { url = "https://files.pythonhosted.org/packages/31/94/72fac03573102779920099bcac1c3b05975c2cb5f01eac609faf34bed1ca/pandas-2.3.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bdcd9d1167f4885211e401b3036c0c8d9e274eee67ea8d0758a256d60704cfe8", size = 10680807, upload-time = "2025-09-29T23:21:15.979Z" }, + { url = "https://files.pythonhosted.org/packages/16/87/9472cf4a487d848476865321de18cc8c920b8cab98453ab79dbbc98db63a/pandas-2.3.3-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e32e7cc9af0f1cc15548288a51a3b681cc2a219faa838e995f7dc53dbab1062d", size = 11709872, upload-time = "2025-09-29T23:21:27.165Z" }, + { url = "https://files.pythonhosted.org/packages/15/07/284f757f63f8a8d69ed4472bfd85122bd086e637bf4ed09de572d575a693/pandas-2.3.3-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:318d77e0e42a628c04dc56bcef4b40de67918f7041c2b061af1da41dcff670ac", size = 12306371, upload-time = "2025-09-29T23:21:40.532Z" }, + { url = "https://files.pythonhosted.org/packages/33/81/a3afc88fca4aa925804a27d2676d22dcd2031c2ebe08aabd0ae55b9ff282/pandas-2.3.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4e0a175408804d566144e170d0476b15d78458795bb18f1304fb94160cabf40c", size = 12765333, upload-time = "2025-09-29T23:21:55.77Z" }, + { url = "https://files.pythonhosted.org/packages/8d/0f/b4d4ae743a83742f1153464cf1a8ecfafc3ac59722a0b5c8602310cb7158/pandas-2.3.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:93c2d9ab0fc11822b5eece72ec9587e172f63cff87c00b062f6e37448ced4493", size = 13418120, upload-time = "2025-09-29T23:22:10.109Z" }, + { url = "https://files.pythonhosted.org/packages/4f/c7/e54682c96a895d0c808453269e0b5928a07a127a15704fedb643e9b0a4c8/pandas-2.3.3-cp313-cp313-win_amd64.whl", hash = "sha256:f8bfc0e12dc78f777f323f55c58649591b2cd0c43534e8355c51d3fede5f4dee", size = 10993991, upload-time = "2025-09-29T23:25:04.889Z" }, + { url = "https://files.pythonhosted.org/packages/f9/ca/3f8d4f49740799189e1395812f3bf23b5e8fc7c190827d55a610da72ce55/pandas-2.3.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:75ea25f9529fdec2d2e93a42c523962261e567d250b0013b16210e1d40d7c2e5", size = 12048227, upload-time = "2025-09-29T23:22:24.343Z" }, + { url = "https://files.pythonhosted.org/packages/0e/5a/f43efec3e8c0cc92c4663ccad372dbdff72b60bdb56b2749f04aa1d07d7e/pandas-2.3.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:74ecdf1d301e812db96a465a525952f4dde225fdb6d8e5a521d47e1f42041e21", size = 11411056, upload-time = "2025-09-29T23:22:37.762Z" }, + { url = "https://files.pythonhosted.org/packages/46/b1/85331edfc591208c9d1a63a06baa67b21d332e63b7a591a5ba42a10bb507/pandas-2.3.3-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6435cb949cb34ec11cc9860246ccb2fdc9ecd742c12d3304989017d53f039a78", size = 11645189, upload-time = "2025-09-29T23:22:51.688Z" }, + { url = "https://files.pythonhosted.org/packages/44/23/78d645adc35d94d1ac4f2a3c4112ab6f5b8999f4898b8cdf01252f8df4a9/pandas-2.3.3-cp313-cp313t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:900f47d8f20860de523a1ac881c4c36d65efcb2eb850e6948140fa781736e110", size = 12121912, upload-time = "2025-09-29T23:23:05.042Z" }, + { url = "https://files.pythonhosted.org/packages/53/da/d10013df5e6aaef6b425aa0c32e1fc1f3e431e4bcabd420517dceadce354/pandas-2.3.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a45c765238e2ed7d7c608fc5bc4a6f88b642f2f01e70c0c23d2224dd21829d86", size = 12712160, upload-time = "2025-09-29T23:23:28.57Z" }, + { url = "https://files.pythonhosted.org/packages/bd/17/e756653095a083d8a37cbd816cb87148debcfcd920129b25f99dd8d04271/pandas-2.3.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:c4fc4c21971a1a9f4bdb4c73978c7f7256caa3e62b323f70d6cb80db583350bc", size = 13199233, upload-time = "2025-09-29T23:24:24.876Z" }, + { url = "https://files.pythonhosted.org/packages/04/fd/74903979833db8390b73b3a8a7d30d146d710bd32703724dd9083950386f/pandas-2.3.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:ee15f284898e7b246df8087fc82b87b01686f98ee67d85a17b7ab44143a3a9a0", size = 11540635, upload-time = "2025-09-29T23:25:52.486Z" }, + { url = "https://files.pythonhosted.org/packages/21/00/266d6b357ad5e6d3ad55093a7e8efc7dd245f5a842b584db9f30b0f0a287/pandas-2.3.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1611aedd912e1ff81ff41c745822980c49ce4a7907537be8692c8dbc31924593", size = 10759079, upload-time = "2025-09-29T23:26:33.204Z" }, + { url = "https://files.pythonhosted.org/packages/ca/05/d01ef80a7a3a12b2f8bbf16daba1e17c98a2f039cbc8e2f77a2c5a63d382/pandas-2.3.3-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6d2cefc361461662ac48810cb14365a365ce864afe85ef1f447ff5a1e99ea81c", size = 11814049, upload-time = "2025-09-29T23:27:15.384Z" }, + { url = "https://files.pythonhosted.org/packages/15/b2/0e62f78c0c5ba7e3d2c5945a82456f4fac76c480940f805e0b97fcbc2f65/pandas-2.3.3-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ee67acbbf05014ea6c763beb097e03cd629961c8a632075eeb34247120abcb4b", size = 12332638, upload-time = "2025-09-29T23:27:51.625Z" }, + { url = "https://files.pythonhosted.org/packages/c5/33/dd70400631b62b9b29c3c93d2feee1d0964dc2bae2e5ad7a6c73a7f25325/pandas-2.3.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c46467899aaa4da076d5abc11084634e2d197e9460643dd455ac3db5856b24d6", size = 12886834, upload-time = "2025-09-29T23:28:21.289Z" }, + { url = "https://files.pythonhosted.org/packages/d3/18/b5d48f55821228d0d2692b34fd5034bb185e854bdb592e9c640f6290e012/pandas-2.3.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:6253c72c6a1d990a410bc7de641d34053364ef8bcd3126f7e7450125887dffe3", size = 13409925, upload-time = "2025-09-29T23:28:58.261Z" }, + { url = "https://files.pythonhosted.org/packages/a6/3d/124ac75fcd0ecc09b8fdccb0246ef65e35b012030defb0e0eba2cbbbe948/pandas-2.3.3-cp314-cp314-win_amd64.whl", hash = "sha256:1b07204a219b3b7350abaae088f451860223a52cfb8a6c53358e7948735158e5", size = 11109071, upload-time = "2025-09-29T23:32:27.484Z" }, + { url = "https://files.pythonhosted.org/packages/89/9c/0e21c895c38a157e0faa1fb64587a9226d6dd46452cac4532d80c3c4a244/pandas-2.3.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:2462b1a365b6109d275250baaae7b760fd25c726aaca0054649286bcfbb3e8ec", size = 12048504, upload-time = "2025-09-29T23:29:31.47Z" }, + { url = "https://files.pythonhosted.org/packages/d7/82/b69a1c95df796858777b68fbe6a81d37443a33319761d7c652ce77797475/pandas-2.3.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:0242fe9a49aa8b4d78a4fa03acb397a58833ef6199e9aa40a95f027bb3a1b6e7", size = 11410702, upload-time = "2025-09-29T23:29:54.591Z" }, + { url = "https://files.pythonhosted.org/packages/f9/88/702bde3ba0a94b8c73a0181e05144b10f13f29ebfc2150c3a79062a8195d/pandas-2.3.3-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a21d830e78df0a515db2b3d2f5570610f5e6bd2e27749770e8bb7b524b89b450", size = 11634535, upload-time = "2025-09-29T23:30:21.003Z" }, + { url = "https://files.pythonhosted.org/packages/a4/1e/1bac1a839d12e6a82ec6cb40cda2edde64a2013a66963293696bbf31fbbb/pandas-2.3.3-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2e3ebdb170b5ef78f19bfb71b0dc5dc58775032361fa188e814959b74d726dd5", size = 12121582, upload-time = "2025-09-29T23:30:43.391Z" }, + { url = "https://files.pythonhosted.org/packages/44/91/483de934193e12a3b1d6ae7c8645d083ff88dec75f46e827562f1e4b4da6/pandas-2.3.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:d051c0e065b94b7a3cea50eb1ec32e912cd96dba41647eb24104b6c6c14c5788", size = 12699963, upload-time = "2025-09-29T23:31:10.009Z" }, + { url = "https://files.pythonhosted.org/packages/70/44/5191d2e4026f86a2a109053e194d3ba7a31a2d10a9c2348368c63ed4e85a/pandas-2.3.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:3869faf4bd07b3b66a9f462417d0ca3a9df29a9f6abd5d0d0dbab15dac7abe87", size = 13202175, upload-time = "2025-09-29T23:31:59.173Z" }, +] + +[[package]] +name = "pandas" +version = "3.0.6" +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 == 'emscripten'", + "python_full_version >= '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", + "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'win32'", + "python_full_version == '3.11.*' and sys_platform == 'win32'", + "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform == 'emscripten'", + "python_full_version == '3.11.*' and sys_platform == 'emscripten'", + "python_full_version >= '3.12' and python_full_version < '3.14' and sys_platform != 'emscripten' and sys_platform != 'win32'", + "python_full_version == '3.11.*' and sys_platform != 'emscripten' and sys_platform != 'win32'", +] +dependencies = [ + { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.11.*'" }, + { name = "numpy", version = "2.5.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12'" }, + { name = "python-dateutil", marker = "python_full_version >= '3.11'" }, + { name = "tzdata", marker = "(python_full_version >= '3.11' and sys_platform == 'emscripten') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e2/17/d7b106e05bfa642e8694451e7d3d759c6a241c5386a5d962e4f66c047e06/pandas-3.0.6.tar.gz", hash = "sha256:66b07ef7315a31bfe1089cd3d71a7de781c9dca986762d0b4fe7c0ef17465d10", size = 4667686, upload-time = "2026-09-17T23:23:18.345Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7d/48/88e8d250d28efa8163294f6809a71683c7ee67f63ac7c33021c0503b3547/pandas-3.0.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:085e3786ae6b2e82b406266bce36690f72b9dc1421903ba9296b2981a9fcf586", size = 10391798, upload-time = "2026-09-17T23:20:20.96Z" }, + { url = "https://files.pythonhosted.org/packages/55/a6/39db5d41f3eb5d7846626312cb30e0cea48e988fc47a3725698bc931ad3c/pandas-3.0.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d7564d86a94c2eb8ab290b07f63ddaae5c032fa53897c29a2ff2197d43aee8af", size = 10023718, upload-time = "2026-09-17T23:20:25.094Z" }, + { url = "https://files.pythonhosted.org/packages/54/b7/707e966129f77ee8a39d41a41bbd989b790b3fef581c6e26b821315cba6b/pandas-3.0.6-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1e7c0afdcaf6661d795fcefc2f647ddd1136f62cdc153fba177c685d97a87808", size = 10612800, upload-time = "2026-09-17T23:20:27.99Z" }, + { url = "https://files.pythonhosted.org/packages/63/be/dfb6cc9329d0bbe76dadda8a1113d026bb996ec76c509221368dc68349f4/pandas-3.0.6-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:47121f9571503f724c9b93e297ab6254ac99c77adf5e9ed085ea419fd585c258", size = 11108900, upload-time = "2026-09-17T23:20:30.65Z" }, + { url = "https://files.pythonhosted.org/packages/1a/6f/3d58f15bbe972f3d7bfa13ee06d731785a76fe8d232c92b2655a8de14127/pandas-3.0.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:994a79608263fe1c14cc48ffa7300e2b834b7d1cb406ffe96a08828cb0cdd79b", size = 11630226, upload-time = "2026-09-17T23:20:33.582Z" }, + { url = "https://files.pythonhosted.org/packages/58/54/9b494de4a3dd92fc6eb19187db1b21afb50fdc21962f32ea1aca9f270cb2/pandas-3.0.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a3a22e07fe75347eaacc75b0e85297947af4fba6b4aae23916bd8b6828d0bba3", size = 12146942, upload-time = "2026-09-17T23:20:36.792Z" }, + { url = "https://files.pythonhosted.org/packages/d3/dc/d2df02854aec5d47659acfb2be352eecc691845b2f86e99c84f1010a8671/pandas-3.0.6-cp311-cp311-win_amd64.whl", hash = "sha256:2e5fa32ff162dfdbc280157d664f44d23049ae414725af9676df339c501d82cd", size = 9859246, upload-time = "2026-09-17T23:20:43.976Z" }, + { url = "https://files.pythonhosted.org/packages/79/1e/2a30df0d7dede5c195300a1820b0bc21cea3aa24e4c8b6c4431565ecc79a/pandas-3.0.6-cp311-cp311-win_arm64.whl", hash = "sha256:5e75072773c1b2f7cb63faa3a6f562aede11f3976f68ed34cb538bc091a28171", size = 9106923, upload-time = "2026-09-17T23:20:46.611Z" }, + { url = "https://files.pythonhosted.org/packages/77/4c/597d588c055d4373cff19cbbc32d4dd046c7be8fadee957585b5ba9e5b24/pandas-3.0.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7dac2d65e9087e8e7b5a45fe15c4920911a221df061ab629943ce016489145c7", size = 10397411, upload-time = "2026-09-17T23:20:49.465Z" }, + { url = "https://files.pythonhosted.org/packages/18/8f/48907c7c707b61a8e5018c32e1a3f70623209bfb59020a2f6196159d3aa7/pandas-3.0.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9dab635a549e58a053c7b0fa054dc0bd7be22f0ed9a720f4a85d5fb993276172", size = 10051279, upload-time = "2026-09-17T23:20:52.409Z" }, + { url = "https://files.pythonhosted.org/packages/67/fa/613d867c3d9554a61bafdec6f79565c8a3e73235feb52cc4a72ad2e0fa6a/pandas-3.0.6-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e3dccb584123b399c07562ac4d62543e90ede49ddf8ce3c13ffc64cbe828c281", size = 10303429, upload-time = "2026-09-17T23:20:55.597Z" }, + { url = "https://files.pythonhosted.org/packages/cb/67/0c0f18e38d7f2d2af8c24b3315bc4046e73bbdd4a5540405506671ad0c0d/pandas-3.0.6-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0704044b676496b8350e023b09f174a26772456c974a2b11c36bebb558c9490d", size = 10788193, upload-time = "2026-09-17T23:20:58.617Z" }, + { url = "https://files.pythonhosted.org/packages/39/53/1b57f3162501fe36687e4870e1b918a6458ca7386b173af75663ace95857/pandas-3.0.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e7c1905ef02c3d6d43d9dbd5b6ccb4da4870a0b0c821bbc103fbdb6f3ad2707b", size = 11323501, upload-time = "2026-09-17T23:21:01.911Z" }, + { url = "https://files.pythonhosted.org/packages/f2/d2/b1182e8d39100369d7f13f4a125a3fb6b096fef112c46d0566c25781ff68/pandas-3.0.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:569e114072b24fc4970c12e2b4bab252671668a40b324318903380cab0254c0c", size = 11838173, upload-time = "2026-09-17T23:21:04.85Z" }, + { url = "https://files.pythonhosted.org/packages/c7/33/5b717af24d2f27995e51e0875a269dddd373045216e34cf62e3aa764eaa1/pandas-3.0.6-cp312-cp312-pyemscripten_2024_0_wasm32.whl", hash = "sha256:2a8fc94be2ee5f1d86f97aacd8cc566f81680b6498e76f3007421bb5d98151bf", size = 7118499, upload-time = "2026-09-17T23:21:07.661Z" }, + { url = "https://files.pythonhosted.org/packages/bd/2a/14b3b17cd75cef4a1ee1af4234eb41cc1afe4103b98c2d80e8916abfd42b/pandas-3.0.6-cp312-cp312-win_amd64.whl", hash = "sha256:3ef908d28590b3f42d7070e7ad8f9b34b442b260b7f3c1afb57e0040c58cdb1b", size = 9661439, upload-time = "2026-09-17T23:21:10.959Z" }, + { url = "https://files.pythonhosted.org/packages/3b/11/3d580a604a1e35d69f6676847bd12db7d14344bc677b717f4413e79c5d0d/pandas-3.0.6-cp312-cp312-win_arm64.whl", hash = "sha256:f4e7c52eb108d752e7592268108fd3e98efd76d83a3125cdd06c621c2e44359b", size = 8959806, upload-time = "2026-09-17T23:21:13.851Z" }, + { url = "https://files.pythonhosted.org/packages/8e/1c/143605a1f6443ad50ebda78a31e5a3a10147fec2590e931584aaa5ff0a09/pandas-3.0.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:9ae8073aed8e21d1a7fe263dcdc6840743549722a6738198a0a46000fa9476f2", size = 10418900, upload-time = "2026-09-17T23:21:16.594Z" }, + { url = "https://files.pythonhosted.org/packages/ea/ca/87f8548f73d452aab35e4a90f8b39ae303295e0f2ef0b4055c44d6b3f1be/pandas-3.0.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:60d81f9e1799b36f3739e7fff44d1fbb2e8fd5a271b3863e03de9715fccda0fa", size = 10064785, upload-time = "2026-09-17T23:21:19.677Z" }, + { url = "https://files.pythonhosted.org/packages/43/1a/d951442e5607c6e3b2462eff8f420797d428aa74b87c6ecfe4f48553626e/pandas-3.0.6-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:097090508a1dd335013d39106fc10b20f4fd4a171638e47b77d55798ed9dab6c", size = 10245290, upload-time = "2026-09-17T23:21:22.797Z" }, + { url = "https://files.pythonhosted.org/packages/50/fa/96d50e1e6cd0b08b5e2b7c838f65ae644940f75a124063380b5ef73b6866/pandas-3.0.6-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1e92d9fa834c7d877130027cddc0cad8dcff97c1f6cca26bd6310f847228b658", size = 10757657, upload-time = "2026-09-17T23:21:25.673Z" }, + { url = "https://files.pythonhosted.org/packages/7b/12/f82d13a2cb703e1a8acee7e01fdc2b898d9cd0c00f07d1dfce63af43e350/pandas-3.0.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b27c8d890e4aa2171437ae2a39de1d215e674158e4865c4023a8b31c932513b2", size = 11249114, upload-time = "2026-09-17T23:21:28.898Z" }, + { url = "https://files.pythonhosted.org/packages/1a/ce/8aef2e561a2f2c8b38c913c67373c65ba6748174e763d27c80271b24bd17/pandas-3.0.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f8029ec0f1f89e4f985929ce1f6626dabf3140d61a4e9c1215afdab34eaf9a5d", size = 11820511, upload-time = "2026-09-17T23:21:32.11Z" }, + { url = "https://files.pythonhosted.org/packages/c0/bd/63cb67e6903ef6d9c2871916dbcbc09d254da0fe8b870cf62e16b21945f2/pandas-3.0.6-cp313-cp313-win_amd64.whl", hash = "sha256:f3ce8a6968045481e91a3990e797e348ce13db45ee164a7095bbc824e26c09dd", size = 9638092, upload-time = "2026-09-17T23:21:34.883Z" }, + { url = "https://files.pythonhosted.org/packages/75/2e/e7b35b712edb068d382ddc8b2bea8a04974100515ba2daa22b478b265842/pandas-3.0.6-cp313-cp313-win_arm64.whl", hash = "sha256:cc39303913e2ea129915670de5d1c9fbd647f543bb72e5543bac8baa94e9e42f", size = 8952032, upload-time = "2026-09-17T23:21:37.729Z" }, + { url = "https://files.pythonhosted.org/packages/75/55/1a8875395b05ccd572cbca0b9255dcd2db6e6508e632a558c1a6884b39ad/pandas-3.0.6-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:ee913a91669056c1de1a6b733fbfeab711de9e54e3bee2dfa5fe79d9457247d1", size = 10492213, upload-time = "2026-09-17T23:21:40.746Z" }, + { url = "https://files.pythonhosted.org/packages/35/61/47ae13476995cc8a40cd609e93e7cf11f273d8692925c2903cb6d38aa0d1/pandas-3.0.6-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ff51a4459ed036e93d1eb1bb5e6e7b28685d3cb6b7c12b91c05b31024e234729", size = 10156618, upload-time = "2026-09-17T23:21:44.142Z" }, + { url = "https://files.pythonhosted.org/packages/bc/f2/cc5f2adb8d6e86a85d9fb5128f8cf205a61189336f70d1f7faf0d1b53ec9/pandas-3.0.6-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:654aae059295dbba6ecd2328ca12712a2cf1676214c8699f1c29213f7ccf9c34", size = 10375479, upload-time = "2026-09-17T23:21:47.159Z" }, + { url = "https://files.pythonhosted.org/packages/ca/ba/ffdcb19be4ff6bfe7d969e7cef2c567c633df5a3a1cc1053394ad053bca8/pandas-3.0.6-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:62f51d7f651c8054c5e82a69265c98082e795d1442df7ca6edc3a545d61214b1", size = 10783244, upload-time = "2026-09-17T23:21:50.367Z" }, + { url = "https://files.pythonhosted.org/packages/77/5b/e150075b2c6eb69fae896f2d9239bc6ed07db97735971d53d66de6553460/pandas-3.0.6-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:22172a92e7ee678ec0140c7af4fc9366b55413834a1cd86af78b3caa0b0574de", size = 11382223, upload-time = "2026-09-17T23:21:53.355Z" }, + { url = "https://files.pythonhosted.org/packages/d6/8a/b441c587dc7355bf6e1f68a91b4f76a6c29740f0c23be3acc5d4ebbeea6d/pandas-3.0.6-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:583be68728a31d0d750d5b8d9e00f02b153df0d4655f858bde93cb84cfc4227c", size = 11854881, upload-time = "2026-09-17T23:21:56.342Z" }, + { url = "https://files.pythonhosted.org/packages/b7/e9/f43410fada510b43fec09993c08f552086c3d247d3ee801a678f3cb10ea5/pandas-3.0.6-cp314-cp314-win_amd64.whl", hash = "sha256:77ccbe5057aece6fc172b9b77f19c04335af6882bc2e10c8f3ee4e6bfb3da553", size = 9791672, upload-time = "2026-09-17T23:21:59.332Z" }, + { url = "https://files.pythonhosted.org/packages/8b/9e/db14c059c21f9baa1907d436f8bf30e0c76c6288225c5e8b79a08ba8b2c5/pandas-3.0.6-cp314-cp314-win_arm64.whl", hash = "sha256:fb625f426b375bcc96e3a04c5d5d266cd7be6ae5d6866e0e703382ab5164068c", size = 9121246, upload-time = "2026-09-17T23:22:02.123Z" }, + { url = "https://files.pythonhosted.org/packages/67/ba/bad0f8dac020ab38a8637fddab01a57a82da7a496a6e6f19590aad53ab62/pandas-3.0.6-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:9e492cd4bdba6778de4fe0df7f4590c012161ebcf9902dce01b01dc683105514", size = 10920612, upload-time = "2026-09-17T23:22:05.404Z" }, + { url = "https://files.pythonhosted.org/packages/c4/a9/b500982e9aac6d52a58da4ad3f11e14168a315b06906b3f397c427878065/pandas-3.0.6-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:d7dcd21238cbb4828ff148481ba01cac8946dc5121457b5aeba28636f8f99a60", size = 10570213, upload-time = "2026-09-17T23:22:08.44Z" }, + { url = "https://files.pythonhosted.org/packages/4b/fa/e6ecd0073c98be8f840ac3125b955272835d7d9fd69f5944383b164deb5e/pandas-3.0.6-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6ff482fa91fa2bafd92e8fe66ce3645c851824310f295c1f0a2f96e928fc4541", size = 10252356, upload-time = "2026-09-17T23:22:11.302Z" }, + { url = "https://files.pythonhosted.org/packages/04/f5/001e230a7a7803590d9275a1a3f7e1bb605e3a495cfe5e8d3a532090621b/pandas-3.0.6-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:db7ec631f26223beee8e5c9e0b8f23c24d8197bbd1d982421d4e3188bea51965", size = 10655952, upload-time = "2026-09-17T23:22:14.283Z" }, + { url = "https://files.pythonhosted.org/packages/ca/ab/bab587148a3852c96aae26c4b5f9e04ce2221801ad94e166b4fbf969ede0/pandas-3.0.6-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:bd75ed0c840f709fc2ae26ddd9534ac77ca1a48ac0cce521a74acaa85f3340a7", size = 11274177, upload-time = "2026-09-17T23:22:17.352Z" }, + { url = "https://files.pythonhosted.org/packages/f3/32/74b48d87df2b80892d713c149abfe36d5db4de41b4eccb042a2bc07dafc1/pandas-3.0.6-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ef738d71d1059245b6bb03e312be06d8b3821326a83486c1ad03b9aba3710e44", size = 11719041, upload-time = "2026-09-17T23:22:20.227Z" }, + { url = "https://files.pythonhosted.org/packages/f6/c6/d64b72d64d7eb0fad9fe424d34138e45dee70ddbea1360dcd0adf30e28f6/pandas-3.0.6-cp314-cp314t-win_amd64.whl", hash = "sha256:429d9df32731ab01383ed98f2baa7a60368090d1a94fc06019a12062510e8630", size = 10191388, upload-time = "2026-09-17T23:22:23.524Z" }, + { url = "https://files.pythonhosted.org/packages/7a/30/5e5b2ccabeca73ae2b03fc82bca3eabb7466cf43737f05ac08d591665d47/pandas-3.0.6-cp314-cp314t-win_arm64.whl", hash = "sha256:a4dbd4dc65cbe645b92b8785d0f96dd7311010dc6606cf620e51b07b8788a12a", size = 9387796, upload-time = "2026-09-17T23:22:26.64Z" }, + { url = "https://files.pythonhosted.org/packages/b6/77/47c5fb0be8bdd00116814c2c40d9ec42dbeb943865ef95130fe58a898226/pandas-3.0.6-cp315-cp315-macosx_10_15_x86_64.whl", hash = "sha256:50c44cbf5820b6b91a5f74aae04972472aefadd3cd9fbd1010409d85528bd570", size = 10483960, upload-time = "2026-09-17T23:22:30.071Z" }, + { url = "https://files.pythonhosted.org/packages/09/08/a310cb2fefe6d2b4623ab2150da818d93d4e73e33b58e4d163bb74243c5a/pandas-3.0.6-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:eb6900de08ac85f93ac4948aa6b80842eba555875337b8359035ac9c43e92d34", size = 10149432, upload-time = "2026-09-17T23:22:32.818Z" }, + { url = "https://files.pythonhosted.org/packages/54/36/6af478ec3a26d7754555cd62c3101c589c0931b1d85398e4fa5403910a1c/pandas-3.0.6-cp315-cp315-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4e25e2e1adee99ddfada6f7206a79ae8e9c8a8861b0e3eaaba165006d3eef18e", size = 10360981, upload-time = "2026-09-17T23:22:35.621Z" }, + { url = "https://files.pythonhosted.org/packages/43/20/5ece0e9cb79a6473216620db6a90546f578001c2bd857b77c444b27acad1/pandas-3.0.6-cp315-cp315-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4ff44b2cb51cbd691c91f92c4ea6c71e34003f239ebd67c2e857dc898466b49c", size = 10776585, upload-time = "2026-09-17T23:22:38.427Z" }, + { url = "https://files.pythonhosted.org/packages/2f/b6/cd3038f31ade5e8d2b4e1c9549d4b31e4d598469562f47142b2ad9171c0a/pandas-3.0.6-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:5edd0a7abb0986ecce1ac81f56d99b6763f86aa6946dceb6c661224f90af5a19", size = 11385249, upload-time = "2026-09-17T23:22:41.18Z" }, + { url = "https://files.pythonhosted.org/packages/0a/87/05bb3003737f80375d7311774916a24d161e2e591abe8c672aed7813defc/pandas-3.0.6-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:1bcb3e9ed29e74a7439cedff9e2aefd3ea65de84d7de9ccb6c194192541bd60e", size = 11848595, upload-time = "2026-09-17T23:22:44.207Z" }, + { url = "https://files.pythonhosted.org/packages/c0/30/1c0d46acf236d19ef975e9cdd5d1e0dd54924b03f0ed8287096ad4a18152/pandas-3.0.6-cp315-cp315-win_amd64.whl", hash = "sha256:253e12cb9081b0afbac607920f6142975966bc315135e09de275fdbaa415d2de", size = 9783810, upload-time = "2026-09-17T23:22:47.097Z" }, + { url = "https://files.pythonhosted.org/packages/87/03/df3304a9c2833c4810e7f1c887b04105b24731f9deef8b5d5d04522a375b/pandas-3.0.6-cp315-cp315-win_arm64.whl", hash = "sha256:97274c9adf6255bb48c620cd6959805efa7f09ea2167f0e0ae006a448cd2fca7", size = 9116820, upload-time = "2026-09-17T23:22:50.149Z" }, + { url = "https://files.pythonhosted.org/packages/47/25/d5f6cce5efa17c38e4f752a875b4a26d66cfadd529cb8c81672f0376d6a6/pandas-3.0.6-cp315-cp315t-macosx_10_15_x86_64.whl", hash = "sha256:265f562fdd1079f69f3de96dd425c3405224038c0af4f920c54bd240ee2c4640", size = 10894614, upload-time = "2026-09-17T23:22:53.223Z" }, + { url = "https://files.pythonhosted.org/packages/ea/8b/e1876bfdc1df06bafc022d33202b5663bd86c81df2a6140aacafd0344669/pandas-3.0.6-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:c6e4aae3e9bea26c6c9a20d88d96c86ec4a99b4db5fd516bcb4e829ab2c0ee36", size = 10546973, upload-time = "2026-09-17T23:22:56.155Z" }, + { url = "https://files.pythonhosted.org/packages/e9/27/e0a27a5a5c27f7db66657b44def9e93121fd0ad4f0808355b9898fcbf204/pandas-3.0.6-cp315-cp315t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a77a1a44e4d88f1c6a2a64d3eb12efec8420875722e14279800b173a7c7c2804", size = 10239717, upload-time = "2026-09-17T23:22:59.603Z" }, + { url = "https://files.pythonhosted.org/packages/d5/4f/4eadb7d86a921c1e8bc70916cfe601ed667c4169118d17d69958611c21f8/pandas-3.0.6-cp315-cp315t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:86fa853a12e0b70927e2b1ee00d56d2224ec9cbb4b9d58348b5ad52d2f21150e", size = 10641275, upload-time = "2026-09-17T23:23:02.81Z" }, + { url = "https://files.pythonhosted.org/packages/c7/d1/eba72e9d905e84e79aefeefdcc6bc1abe15d9077973566643f4211636966/pandas-3.0.6-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:c826e9babb7790142c399f58599d8de679bea059d7b39c5b6efa2096fac37266", size = 11262919, upload-time = "2026-09-17T23:23:06.038Z" }, + { url = "https://files.pythonhosted.org/packages/9d/8a/1c5bd2642b450e374b6191189f47c49538fe41f82348a66de6f647e6ab59/pandas-3.0.6-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:8fe77b408d82e2615674dfed62533b95e18a03610573877422aada4f625d4947", size = 11709148, upload-time = "2026-09-17T23:23:09.082Z" }, + { url = "https://files.pythonhosted.org/packages/73/3d/1b142bd0d0f1326a5d98c91c955b923cd1e06b5eecb428cd9d8817fa01c0/pandas-3.0.6-cp315-cp315t-win_amd64.whl", hash = "sha256:83e91d15738d7783c050197cef2f2cf82fc6353dae9865aa87ed1fa16aa4d55a", size = 10161518, upload-time = "2026-09-17T23:23:12.365Z" }, + { url = "https://files.pythonhosted.org/packages/0b/a3/6419c14da2adc1f09a6a183b8f91d7494d325b287f4ca984ac04f663638a/pandas-3.0.6-cp315-cp315t-win_arm64.whl", hash = "sha256:963ca21199097a84c7827c4678b04e30833084fbf8ef44fde3fa7180a29f8fa0", size = 9364529, upload-time = "2026-09-17T23:23:15.274Z" }, +] + +[[package]] +name = "pluggy" +version = "1.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/bf/db/7fc19e6f2dc92a966727031389fc2e08b558f0f25eb7403c1119ad4713cd/pluggy-1.7.0.tar.gz", hash = "sha256:d1eaa46ebb595891b860ab086b4d09c8588af65ebd4361b8e8f4bb8920b90ba8", size = 123304, upload-time = "2026-10-15T09:50:58.343Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/40/9e/2b38731e0fc536806f16490e1a12d7f0dc2a1235aa8cc07bcc75416a7daa/pluggy-1.7.0-py3-none-any.whl", hash = "sha256:7dd7b0d8832ba3cb632c306926ded123429211b83641b35dc5c41ad2d34f9bec", size = 27082, upload-time = "2026-10-15T09:50:56.808Z" }, +] + +[[package]] +name = "pse-sdk" +source = { editable = "." } +dependencies = [ + { name = "requests" }, +] + +[package.optional-dependencies] +pandas = [ + { name = "pandas", version = "2.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "pandas", version = "3.0.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, +] + +[package.dev-dependencies] +dev = [ + { name = "pandas", version = "2.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "pandas", version = "3.0.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "pytest" }, + { name = "responses" }, + { name = "ruff" }, +] + +[package.metadata] +requires-dist = [ + { name = "pandas", marker = "extra == 'pandas'", specifier = ">=1.5" }, + { name = "requests", specifier = ">=2.28" }, +] +provides-extras = ["pandas"] + +[package.metadata.requires-dev] +dev = [ + { name = "pandas", specifier = ">=1.5" }, + { name = "pytest", specifier = ">=8" }, + { name = "responses", specifier = ">=0.25" }, + { name = "ruff", specifier = ">=0.15" }, +] + +[[package]] +name = "pygments" +version = "2.21.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/49/2e/ced460408999b33da6b31b0021b0f37d329e202d4169aeb164493778f25b/pygments-2.21.0.tar.gz", hash = "sha256:610ca751c9bc2492b38eb9a38a7fbc93edbbb2d7182edaf34e66ae493dee5c8c", size = 5005329, upload-time = "2026-08-17T08:02:48.824Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/71/46/17f022dd3e953bf20a04a028a21ec746d942f8d2af30fa0f124fa0e6a684/pygments-2.21.0-py3-none-any.whl", hash = "sha256:2363c69b61c4a97c838da3b130dcd6468f4848992b21a82f2a63ec34377137d9", size = 1250147, upload-time = "2026-08-17T08:02:44.912Z" }, +] + +[[package]] +name = "pytest" +version = "9.1.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, + { name = "iniconfig" }, + { name = "packaging" }, + { name = "pluggy" }, + { name = "pygments" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, +] +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 = "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 = "pytz" +version = "2026.5" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/14/21/d83d6ef28c4c912c4bb4d1dcf591f7b8c6bde87b9c66f9f454677314e16d/pytz-2026.5.tar.gz", hash = "sha256:fa23724b9c486543b9ff54a327ee7569ac83ade54bb9afd0fc18676620401c86", size = 318572, upload-time = "2026-10-04T02:37:58.719Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4f/ef/c66110d46fb800dda0bf33164182dfadabe26a90e4476844d502a23dca8e/pytz-2026.5-py2.py3-none-any.whl", hash = "sha256:e658af3757f9e26a9d25dd2aff38335acd92bc9104f890a894b2c1ba28311b03", size = 506342, upload-time = "2026-10-04T02:37:56.814Z" }, +] + +[[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/f4/a0/39350dd17dd6d6c6507025c0e53aef67a9293a6d37d3511f23ea510d5800/pyyaml-6.0.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b", size = 184227, upload-time = "2025-09-25T21:31:46.04Z" }, + { url = "https://files.pythonhosted.org/packages/05/14/52d505b5c59ce73244f59c7a50ecf47093ce4765f116cdb98286a71eeca2/pyyaml-6.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02ea2dfa234451bbb8772601d7b8e426c2bfa197136796224e50e35a78777956", size = 174019, upload-time = "2025-09-25T21:31:47.706Z" }, + { url = "https://files.pythonhosted.org/packages/43/f7/0e6a5ae5599c838c696adb4e6330a59f463265bfa1e116cfd1fbb0abaaae/pyyaml-6.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b30236e45cf30d2b8e7b3e85881719e98507abed1011bf463a8fa23e9c3e98a8", size = 740646, upload-time = "2025-09-25T21:31:49.21Z" }, + { url = "https://files.pythonhosted.org/packages/2f/3a/61b9db1d28f00f8fd0ae760459a5c4bf1b941baf714e207b6eb0657d2578/pyyaml-6.0.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:66291b10affd76d76f54fad28e22e51719ef9ba22b29e1d7d03d6777a9174198", size = 840793, upload-time = "2025-09-25T21:31:50.735Z" }, + { url = "https://files.pythonhosted.org/packages/7a/1e/7acc4f0e74c4b3d9531e24739e0ab832a5edf40e64fbae1a9c01941cabd7/pyyaml-6.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9c7708761fccb9397fe64bbc0395abcae8c4bf7b0eac081e12b809bf47700d0b", size = 770293, upload-time = "2025-09-25T21:31:51.828Z" }, + { url = "https://files.pythonhosted.org/packages/8b/ef/abd085f06853af0cd59fa5f913d61a8eab65d7639ff2a658d18a25d6a89d/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:418cf3f2111bc80e0933b2cd8cd04f286338bb88bdc7bc8e6dd775ebde60b5e0", size = 732872, upload-time = "2025-09-25T21:31:53.282Z" }, + { url = "https://files.pythonhosted.org/packages/1f/15/2bc9c8faf6450a8b3c9fc5448ed869c599c0a74ba2669772b1f3a0040180/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5e0b74767e5f8c593e8c9b5912019159ed0533c70051e9cce3e8b6aa699fcd69", size = 758828, upload-time = "2025-09-25T21:31:54.807Z" }, + { url = "https://files.pythonhosted.org/packages/a3/00/531e92e88c00f4333ce359e50c19b8d1de9fe8d581b1534e35ccfbc5f393/pyyaml-6.0.3-cp310-cp310-win32.whl", hash = "sha256:28c8d926f98f432f88adc23edf2e6d4921ac26fb084b028c733d01868d19007e", size = 142415, upload-time = "2025-09-25T21:31:55.885Z" }, + { url = "https://files.pythonhosted.org/packages/2a/fa/926c003379b19fca39dd4634818b00dec6c62d87faf628d1394e137354d4/pyyaml-6.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:bdb2c67c6c1390b63c6ff89f210c8fd09d9a1217a465701eac7316313c915e4c", size = 158561, upload-time = "2025-09-25T21:31:57.406Z" }, + { 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 = "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 = "responses" +version = "0.26.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pyyaml" }, + { name = "requests" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9f/47/f216a33221db8eff328987661cf18371afee89c62a62b434b963d6b509c9/responses-0.26.3.tar.gz", hash = "sha256:b0c11ca8131b8b227b8d5108e6ed39772222bd5aab030ed430e8f99057c4c409", size = 86335, upload-time = "2026-08-26T19:17:24.373Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6d/86/ca7958de70cb0752350575e98229368a3a2f746a2942034b3364e17312bb/responses-0.26.3-py3-none-any.whl", hash = "sha256:74474f799334ac4f37d93b6437ecc3bb1bb5c77a8d31780a338643be2dce0af8", size = 36289, upload-time = "2026-08-26T19:17:23.176Z" }, +] + +[[package]] +name = "ruff" +version = "0.17.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f9/e7/e6d5749983b020e6cb1055abec0a6f361a8e94f0184cdcf56d4760995f02/ruff-0.17.1.tar.gz", hash = "sha256:5bb796c5112e9fb9527f2ef2faa0a130d6312d19de92bcfaddd70dbb2d41020f", size = 5323349, upload-time = "2026-10-15T15:23:18.64Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2e/78/90c46ca6250709f7c37e397b60d06061adee8d0f7d13959ed6a8e49b14fd/ruff-0.17.1-py3-none-linux_armv6l.whl", hash = "sha256:1796c41eafec66f4635125dd1e074a7aa27b8d20c187d484360acf11d247fc4a", size = 10147528, upload-time = "2026-10-15T15:22:33.667Z" }, + { url = "https://files.pythonhosted.org/packages/aa/d2/a2e28bc35b083ae51fa07dfba5280a667c8b01ecaee7802fc8849dcd5c46/ruff-0.17.1-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:8eadb09a788010be29c895418bdfa513e4e1c65e64b94e5b19e4cd381f6cc7fb", size = 10225974, upload-time = "2026-10-15T15:22:36.328Z" }, + { url = "https://files.pythonhosted.org/packages/8e/71/7a9029a81c8206ee01a98f6cfeeb56e6c095af86857581a37045c46d7e94/ruff-0.17.1-py3-none-macosx_11_0_arm64.whl", hash = "sha256:29b454f18ca3eeaf37fbf140841dcf27d36109e29dee9aae8acecb68c26c6f74", size = 9270361, upload-time = "2026-10-15T15:22:38.651Z" }, + { url = "https://files.pythonhosted.org/packages/c0/8c/e075e9c917cb0575297880c96768304e881240171c870cbd8d9b7b54bec2/ruff-0.17.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:872e03dd231744d6c5ec5c8af6be52b71323fc6ee096e4c8b34d9f844ee3b978", size = 9938300, upload-time = "2026-10-15T15:22:41.284Z" }, + { url = "https://files.pythonhosted.org/packages/87/27/0b4bb926a49de2383f161272b4d863571a4c7ecdbf595a6bc58813a13367/ruff-0.17.1-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4c0d6cb5f8fbac77eec9af49f4fc0eaf856b05545e372b0694d24b4e76b1c640", size = 9948464, upload-time = "2026-10-15T15:22:43.681Z" }, + { url = "https://files.pythonhosted.org/packages/14/27/518d57e0e02aecb8ea4acac6b57b51a53173d25fa734952bfdd7d531e88e/ruff-0.17.1-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:78beced4a3c94dfedbee4b999b95b6a27b35820fdc0afbacc6d37a8da26c1cd1", size = 10638639, upload-time = "2026-10-15T15:22:46.081Z" }, + { url = "https://files.pythonhosted.org/packages/01/82/d89a4e498ade59e6cee52d67f8da569019372212b87468c1fdeae884601c/ruff-0.17.1-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7feefc63921202894f0e158b0e32f45a5950d70a7fb693ccb9264816c25b1c05", size = 11337238, upload-time = "2026-10-15T15:22:48.894Z" }, + { url = "https://files.pythonhosted.org/packages/a2/7c/3b0fdef9352656317c977086fe1d802902406e4f2a0d8578da90c0e6d1c5/ruff-0.17.1-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:684154861a819bf1f433669d2a0ce9c3e54677c65b8ebb866cc2a7ec86345785", size = 10896327, upload-time = "2026-10-15T15:22:51.45Z" }, + { url = "https://files.pythonhosted.org/packages/62/86/5566290219708ce2928f3a29c4f843a1185b341ec6111c4631a33c5ceced/ruff-0.17.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a6ef98e51de8ef38082f90653ceeb84944bd7673783eea13e1647c5b9b064189", size = 10350811, upload-time = "2026-10-15T15:22:54.401Z" }, + { url = "https://files.pythonhosted.org/packages/ad/d2/ca8462dabb3c413990d49703ba306c30c862195a75448d080fa8fcce9775/ruff-0.17.1-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:8f9aa5b5bd5fa1937803ea609c8f153b8de39bf3e0e149897ae34b0c5b52f467", size = 10569994, upload-time = "2026-10-15T15:22:57.142Z" }, + { url = "https://files.pythonhosted.org/packages/e3/ad/dd1864c1f1db17c8cfb297ce70b352388e6977620f66f7182c52855407df/ruff-0.17.1-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:80e53b0e5faa3c5667f035daaa032893ae42b7cfe708c886d39ed131e54688ab", size = 10059672, upload-time = "2026-10-15T15:23:00.084Z" }, + { url = "https://files.pythonhosted.org/packages/65/45/3f56cf1d2168c2165cdd5ac6f9668aee66a4cfdd4caf2b2cc5ccb2b1d568/ruff-0.17.1-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:056c5d5fa0ac790051ae165d7035c7bf956d02de2db557f2e9b31d877a505fca", size = 9947803, upload-time = "2026-10-15T15:23:03.132Z" }, + { url = "https://files.pythonhosted.org/packages/aa/4b/5457cb2be4c1d1ea5e919558131a0f197a4a454a0530d9e30820e8206e4c/ruff-0.17.1-py3-none-musllinux_1_2_i686.whl", hash = "sha256:bd8f5a55b10f371642eacd0e8665a42a8b97da15c9a7187c79e697b77b5e0ce4", size = 10351807, upload-time = "2026-10-15T15:23:05.628Z" }, + { url = "https://files.pythonhosted.org/packages/49/fb/db15b4f8fa24a1e36b99e1401f42ef6df16ee299a48670d5d262b771e7d7/ruff-0.17.1-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:ce05e6f3973611d9550a600e04bb531061e368baba31610eb57c1509a8f21a0a", size = 10765716, upload-time = "2026-10-15T15:23:08.092Z" }, + { url = "https://files.pythonhosted.org/packages/0a/e8/1e186578076aff7a80735f625005fde678412ab609cd323ed182eb7d6b87/ruff-0.17.1-py3-none-win32.whl", hash = "sha256:1de0030a8aa78c65c5fecb84b2e5c390ac684c0452875a02afc7c083d49a496a", size = 9895093, upload-time = "2026-10-15T15:23:10.582Z" }, + { url = "https://files.pythonhosted.org/packages/6a/2e/da3d9589bae8e8b58f3a48bd5bc0b980232fb14a83bf02c3be7660f87c1b/ruff-0.17.1-py3-none-win_amd64.whl", hash = "sha256:5df76f16580fab58d0f6c98a3ac254a4abceb7b2489b8b678335869cff77b3d7", size = 10097955, upload-time = "2026-10-15T15:23:13.309Z" }, + { url = "https://files.pythonhosted.org/packages/df/c9/0f2a4dea06a5e12c1191ee3d96b1e1233797d0d5e18f97a2b909a95a9836/ruff-0.17.1-py3-none-win_arm64.whl", hash = "sha256:42400b9a6ff8515ff27796f07f92e0195be011c86e81e381606f58ea5502fef4", size = 9853542, upload-time = "2026-10-15T15:23:16.05Z" }, +] + +[[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 = "tomli" +version = "2.5.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b0/78/9ad63712633ed3ab5cc1a648d863d7e7da371e9425e209555a0fe711b695/tomli-2.5.0.tar.gz", hash = "sha256:264507556cd8b8c8e7c6ee037cdf443a463f03f4c958e57195e3d369711b8ff6", size = 17662, upload-time = "2026-10-07T12:23:37.892Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/22/a6/ab99b60ee52acd949684febabc3005d0045d0f66bebd9cdebd67372d26dd/tomli-2.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c4dc1c1781f2f716de763d1e9a7b34c6a894e167e291c7c5d16c72f7a9538545", size = 163901, upload-time = "2026-10-07T12:22:15.601Z" }, + { url = "https://files.pythonhosted.org/packages/bc/00/ee01b7ed4579180fff07142d290257f25ba786f23f3ec6005f620933c2f5/tomli-2.5.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:eff8babca5a7999bc137acbc7482a8b7e17ffca5075ab41f5d770ab408c7bfef", size = 163756, upload-time = "2026-10-07T12:22:16.957Z" }, + { url = "https://files.pythonhosted.org/packages/72/c2/4efebf65372f6583185f79799312109dddb61102d47e5c33dcfd1a297aca/tomli-2.5.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:86665cee9c4835b7a7f1e8ec2c719b5258d4dc782887aded5a8ae7352a96843b", size = 268038, upload-time = "2026-10-07T12:22:18.135Z" }, + { url = "https://files.pythonhosted.org/packages/53/07/5850468e925d898abb36038666f9c333a94d2a223e802a8ba5b6d319d23f/tomli-2.5.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d7e369fd63331746182360977b1892bfc215476a30d61612d732425311639f56", size = 276422, upload-time = "2026-10-07T12:22:19.567Z" }, + { url = "https://files.pythonhosted.org/packages/b4/87/f293984cdcf83c054196d4fd3dad44fc68ae55b4b8c44bc76cef360c3150/tomli-2.5.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7ad1ea345759240d6463efa0ed1c704402752e49aa21476620738d74d72d8aa1", size = 272616, upload-time = "2026-10-07T12:22:20.794Z" }, + { url = "https://files.pythonhosted.org/packages/ce/ce/db582886b3c1219d3fec93ebd669332482e5aee7a91e0f7838d84f2d1759/tomli-2.5.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:96243987194634bd411066ce40c952e108f86af04db533ecd8ac3ff2a85b1885", size = 276593, upload-time = "2026-10-07T12:22:22.12Z" }, + { url = "https://files.pythonhosted.org/packages/bf/72/7619b87dea4261fc27dd7b54c4461c129c1f7d9bb7ba3aec89c797a431b8/tomli-2.5.0-cp311-cp311-win32.whl", hash = "sha256:610b27d99f28ec5f191c7064a48f3ddb179a1fe6ca73d571483ae859f57b605e", size = 101830, upload-time = "2026-10-07T12:22:23.651Z" }, + { url = "https://files.pythonhosted.org/packages/1e/74/220106da34502304b6751a2a9b8a9fbca6c3fd47e737a2e2e3da7c61c9db/tomli-2.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:c804ae44fe7b4bab5da295e4f980a1ff04670bca9d23fe0a4e887e08ebd741a8", size = 112742, upload-time = "2026-10-07T12:22:24.972Z" }, + { url = "https://files.pythonhosted.org/packages/27/99/7d9c8b41837a7773613e169504147375c157a290167aa59ad74a085f521f/tomli-2.5.0-cp311-cp311-win_arm64.whl", hash = "sha256:cfac177ebd6236003846ea339981f71457cb6eb748f23381eb257e45092e3980", size = 109332, upload-time = "2026-10-07T12:22:26.117Z" }, + { url = "https://files.pythonhosted.org/packages/52/ed/7baa86f87493646a594de388c7c1c40a39dd0461f7e9c0359cbeefc91fe8/tomli-2.5.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:1f4a40d03fb9f63424f0979855bdeaf44dd7696b8d59501822c10ed30ba532df", size = 164854, upload-time = "2026-10-07T12:22:27.444Z" }, + { url = "https://files.pythonhosted.org/packages/a5/b1/44c0341f2224397855723c7a8a39f718ea6fcbcc3dacc66e5aeca0f334e3/tomli-2.5.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9ebf8d19b17bd0daeb7b7dec81a946a439b753942fd0210d6e96c532249eea6b", size = 164074, upload-time = "2026-10-07T12:22:28.679Z" }, + { url = "https://files.pythonhosted.org/packages/23/04/e2d5b7d3fba47adedb23de616c16d428ea076c79a3d8e1d95d649ffe197e/tomli-2.5.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bf0b5e8e0f68ebb494356e577c06c139161efd8d3b9050f93b39b7c26cc54ff0", size = 274274, upload-time = "2026-10-07T12:22:29.804Z" }, + { url = "https://files.pythonhosted.org/packages/43/90/6090e706ff27a6f89f4a40578e3324b95c3cd8c4150868aabf33a8f414c3/tomli-2.5.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6cf74416bdc94ae458b14e37286c1073081850ac8459a00d0c5efef5d44294c6", size = 286435, upload-time = "2026-10-07T12:22:31.297Z" }, + { url = "https://files.pythonhosted.org/packages/0a/9e/a2c40768df16c408f22430afb0a73e9d7e5f79c950884954649d1146b74d/tomli-2.5.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:61ea1ebe1e55a34ea8199cc8dbff398d35027b82271c8ac4802fd3a1fd5b1bcc", size = 278119, upload-time = "2026-10-07T12:22:32.601Z" }, + { url = "https://files.pythonhosted.org/packages/12/25/3c0cb485b98e9cfac495629b1c93c87ccf0b72fbe9d2689fd8fe62c6d5a3/tomli-2.5.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ed53f7e89bb04f6d9e8e7799112360b0c4d5cbff067de0814c98c37c39b920f7", size = 286177, upload-time = "2026-10-07T12:22:33.745Z" }, + { url = "https://files.pythonhosted.org/packages/77/8b/0144c65f0e37e51c18d04ae15c21b19431c165002d0131fe9aa8b0b8b1e8/tomli-2.5.0-cp312-cp312-win32.whl", hash = "sha256:e7ad033e27a516a233bea839cdb77b80146facb3b4f40bf02cd0cac165cdd5c2", size = 102760, upload-time = "2026-10-07T12:22:34.887Z" }, + { url = "https://files.pythonhosted.org/packages/de/32/5d6d8f42fc9a05fce69354e00ff256484192f5f2fc9a2165718fa0de61ec/tomli-2.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:bd05de8c1698f8413dd7d869492693a0bf2211543b787ac78cd5e7536af1a6d7", size = 112722, upload-time = "2026-10-07T12:22:36.162Z" }, + { url = "https://files.pythonhosted.org/packages/30/65/df18032218db0fb9b769fb23c8039a051f15c811993995ea04c350273a32/tomli-2.5.0-cp312-cp312-win_arm64.whl", hash = "sha256:069435bd5480429b98c5e5afb02ab21c219b6f0064680671c6dc0d46817346ea", size = 109534, upload-time = "2026-10-07T12:22:37.296Z" }, + { url = "https://files.pythonhosted.org/packages/42/e5/51736d70da209350969e15aca5c5ab6e2ce1ea87a0a892a6c13aec172a86/tomli-2.5.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:943276cf269e0071948d9ff697159c1735e623c1151d88abb09b74659ef0cbea", size = 163328, upload-time = "2026-10-07T12:22:38.373Z" }, + { url = "https://files.pythonhosted.org/packages/ec/55/086f80dab4ab497602644274e6dea7ec5dd0b4e262e443a8ad3bb7edee2d/tomli-2.5.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:463b16086865b97facd8d0b3fb4cb7c544e3f58d2a69dc3113d6db9653fdb043", size = 162246, upload-time = "2026-10-07T12:22:39.673Z" }, + { url = "https://files.pythonhosted.org/packages/aa/eb/3ecc94459f3635c92321f4e7bde571323fdb2267c50e19e3188a281eae3b/tomli-2.5.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1245a6638fc4bb0a60af38a7d45413db34a13842027c77597c712c998c62fdf0", size = 272655, upload-time = "2026-10-07T12:22:41.08Z" }, + { url = "https://files.pythonhosted.org/packages/c0/d7/494fd1f0c37a621f1ad9975c2efadb523e8101f144ed6edb2e7fe64738f2/tomli-2.5.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5d8bac3d603c97e6854424e5b2b5b741bdbde387e09f162fb0446812b4a8362b", size = 283595, upload-time = "2026-10-07T12:22:42.222Z" }, + { url = "https://files.pythonhosted.org/packages/70/51/bb8d62b1317e6640866f6949b2d5855e5300f2c99d46de1cd245570bba65/tomli-2.5.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:21e4cae4114aba25aa0d4f85cdf486d290fb35c0954d7bba536248da64d43066", size = 276253, upload-time = "2026-10-07T12:22:43.625Z" }, + { url = "https://files.pythonhosted.org/packages/66/f4/f46bd7f0763cd47de2db697dca9257c6a4adfd1a93b018cc75c8190ed5a8/tomli-2.5.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:bbaefc84548d754be821bba7c4141c4787dda182f9e77f2f87b71213529efa7b", size = 283582, upload-time = "2026-10-07T12:22:44.983Z" }, + { url = "https://files.pythonhosted.org/packages/ac/03/70f2bcb2923a6db37818d917e124270a7f4cfd38ea576f5aa753a91c0ef5/tomli-2.5.0-cp313-cp313-win32.whl", hash = "sha256:abdbf6313b8d9efe157edeb7ab6eae4de064b1300ad31abf73755154b30abe68", size = 102628, upload-time = "2026-10-07T12:22:46.508Z" }, + { url = "https://files.pythonhosted.org/packages/dc/98/d52024bb5b0ff68b4f0d276d867f634c84a67319a7e9f6b7708a37742333/tomli-2.5.0-cp313-cp313-win_amd64.whl", hash = "sha256:fd4dc129784e0c5335bd4e61dfcc4487499a013419e655cf2da1d091b7e0efdc", size = 113301, upload-time = "2026-10-07T12:22:47.647Z" }, + { url = "https://files.pythonhosted.org/packages/6f/f2/540db3a70572a8c23a28aba3e9c358ce0ffffbafc990905c1343aa265b31/tomli-2.5.0-cp313-cp313-win_arm64.whl", hash = "sha256:69491c143d2fe063046e0301e62a810bed338fa4d1ce0fd870c27dc1e09b0d84", size = 109744, upload-time = "2026-10-07T12:22:48.925Z" }, + { url = "https://files.pythonhosted.org/packages/e4/49/caf6b307766eb9567664a8707e9d6be5fcc0e8903f18781c6677a60d80c7/tomli-2.5.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:d3182ee2d887e507bd67319a0a61105d1dd33facc111329559a233b772c1a105", size = 162899, upload-time = "2026-10-07T12:22:50.088Z" }, + { url = "https://files.pythonhosted.org/packages/d3/c8/68cfce773a2733a49c74f99d627fb461bd990756860099eac25617889585/tomli-2.5.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:521345fd1f19d45b8df87657aaa38b6f2ca3800059fadf428e7ebf479a383646", size = 162080, upload-time = "2026-10-07T12:22:51.558Z" }, + { url = "https://files.pythonhosted.org/packages/7e/b2/e5bb8651fdad593f670501a7d718b1a7f73f064d44dea15e04c04dfef45d/tomli-2.5.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6e95c7614e705bfe2b04b27aa124adec59752d15813df37e2156747cab3a006b", size = 273380, upload-time = "2026-10-07T12:22:52.918Z" }, + { url = "https://files.pythonhosted.org/packages/8d/d2/9e2d7f8b1dfe0e2b34c245986ebd55c4c553ea4ce6c47c443b332673253f/tomli-2.5.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7ac2027d37c3afbdf4bdd377f2676f6f1d2122a5be1f1137b49dced590b37e75", size = 283228, upload-time = "2026-10-07T12:22:54.173Z" }, + { url = "https://files.pythonhosted.org/packages/ba/df/ec7b876b7b1a2718bd74a3743c076fff565b04029ba33e8f61fac262739f/tomli-2.5.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c414be4ed9d3cac80c42e348fa5a956117d1a48227f48026e31f59cb4a7671eb", size = 277189, upload-time = "2026-10-07T12:22:55.342Z" }, + { url = "https://files.pythonhosted.org/packages/7d/7b/e192d9eed0b9cb80da799f4d77052297fb9a2c3cc9b19f571f56ea88add6/tomli-2.5.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:9b03d7dc168353b4132965bde20feceabaa470e570c6f59660dfae59b1f9eeb3", size = 283632, upload-time = "2026-10-07T12:22:56.735Z" }, + { url = "https://files.pythonhosted.org/packages/84/50/ff94454e75461d75623e47401ed323d65c10aab8fe9033242c20cd2fdf32/tomli-2.5.0-cp314-cp314-win32.whl", hash = "sha256:6f041843c4d3a37245c0c056fd955b186bf8b1fb85690cbe40b81230891dc34b", size = 103535, upload-time = "2026-10-07T12:22:58.084Z" }, + { url = "https://files.pythonhosted.org/packages/54/0b/bdacf05f963bd6026ebf6eeb0beda847d1d60e03e440725c64a4e08a0afd/tomli-2.5.0-cp314-cp314-win_amd64.whl", hash = "sha256:f4b653094e18f9031102d3a1da5c729c8f222d85225b18037dac621695e46e1a", size = 114621, upload-time = "2026-10-07T12:22:59.2Z" }, + { url = "https://files.pythonhosted.org/packages/61/99/53f438fa6ae4f9d4ed0ddde3e7242b3bdc34b48c8f9948b72b9e9b127676/tomli-2.5.0-cp314-cp314-win_arm64.whl", hash = "sha256:3f89d10c1ff6a38d992c27fc8a4816af71a909e08a40ec66934240b1e74347c3", size = 111572, upload-time = "2026-10-07T12:23:00.479Z" }, + { url = "https://files.pythonhosted.org/packages/b9/20/1f88f19427d380a40e90a770e087489eaafe4aeee070ae88ed2bbec00acd/tomli-2.5.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:e9e15b4a6c7dd6b85b5fbab29488a73f1f70de516942308daa266bf0e0aeb0d4", size = 171814, upload-time = "2026-10-07T12:23:01.914Z" }, + { url = "https://files.pythonhosted.org/packages/d0/56/cbe5079c9f9a54b9b3e27fc82f08f3cb36edee75561679f53d2380c801d6/tomli-2.5.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:e12bbcd32897272fb05929110362ae9ff4c1b9bb26bd9e971e71dcd3275b4c3d", size = 171324, upload-time = "2026-10-07T12:23:03.18Z" }, + { url = "https://files.pythonhosted.org/packages/2b/30/1d53fd3b0f1cb3ba542e345ec32c26aefdddc4e829e4f3429af8a4f27782/tomli-2.5.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:20aa36de8f2cf87237143bc1fa1aae8d6612c09118f4da21c6a684db5dd1f6f9", size = 297441, upload-time = "2026-10-07T12:23:04.345Z" }, + { url = "https://files.pythonhosted.org/packages/66/d9/0800acb6a111686f764c1b91ef15cc42a20a66a46013bb42220f1d2c61c1/tomli-2.5.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:22185fad8a1e622f064e78008018a0dd3323550dcb479cb7a1d296888d74024f", size = 307476, upload-time = "2026-10-07T12:23:05.671Z" }, + { url = "https://files.pythonhosted.org/packages/e8/63/30a8f3cd51b5bec37f04744bad0b0dc6160df84aad4f27b0e9283d66f221/tomli-2.5.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:984012f71908165449a951de2050d52f276bfe3aa5d5f570f63ddad814370374", size = 296113, upload-time = "2026-10-07T12:23:07.202Z" }, + { url = "https://files.pythonhosted.org/packages/ab/18/0b9ffc597e69c5a1e20a7823cb60d54b39a9f54e91edcb8574f022186758/tomli-2.5.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:f79203b3965b4000e91808aaa7c040206093f2b8bf86f455982f2274c9ccf442", size = 307725, upload-time = "2026-10-07T12:23:08.508Z" }, + { url = "https://files.pythonhosted.org/packages/ab/c7/18f8baae0b5607a60e8e19b4a7fedee43a8ff6458e3896dcbbadeeac9c22/tomli-2.5.0-cp314-cp314t-win32.whl", hash = "sha256:91294a9fb94a75542f6e46e4a2ae709bd8d9b51134098cae5cf3bea5478b6d03", size = 108546, upload-time = "2026-10-07T12:23:09.956Z" }, + { url = "https://files.pythonhosted.org/packages/72/34/4cca9739254130627bde87500b3f2b512154fe2f278efa7e2a5e10ad4bcb/tomli-2.5.0-cp314-cp314t-win_amd64.whl", hash = "sha256:f15e3e0b835a6d68b10c86bf80a3149780498d6911c93c3ffd1861d19f9200f1", size = 117814, upload-time = "2026-10-07T12:23:11.486Z" }, + { url = "https://files.pythonhosted.org/packages/7d/fb/afa530d47dd80a78fce43beac6bc6e00f84558eafcffbc6f37b21e80d056/tomli-2.5.0-cp314-cp314t-win_arm64.whl", hash = "sha256:6664b7ae7af7294256c53960a6103077f4914cec8ff98479c352f622c6f6b2f0", size = 115188, upload-time = "2026-10-07T12:23:12.728Z" }, + { url = "https://files.pythonhosted.org/packages/66/98/316fdc00f8c0939e6fe50461dd343c162d3ad51d1286eb25b7db54361d50/tomli-2.5.0-cp315-cp315-macosx_10_15_x86_64.whl", hash = "sha256:a525685c2f97da40762b8695eb7aa0af4c8344ca1905c73e4e29cb04d34607dc", size = 162775, upload-time = "2026-10-07T12:23:13.941Z" }, + { url = "https://files.pythonhosted.org/packages/c5/22/7b10fa5bb01c9539f53f69b619361b19350acc73657772ea7ac70ba309a8/tomli-2.5.0-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:9dbb18c1cfb2f6517942fc9314437f66aa06d94436ffb1f06102ef3572f35276", size = 161406, upload-time = "2026-10-07T12:23:15.215Z" }, + { url = "https://files.pythonhosted.org/packages/9c/e7/1a069d86dfd20f1f84f71c63faed9f83c1d890bc06c27d82dc7d888fb573/tomli-2.5.0-cp315-cp315-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:752e8b1aa6a4367ef8bf6a1a1e005540f7ed055ba36d7193796812ca5404eb52", size = 273855, upload-time = "2026-10-07T12:23:16.471Z" }, + { url = "https://files.pythonhosted.org/packages/ae/83/d1ef43d1687d092ab9c235455c76e6e709483b346b056f086095c7c263a5/tomli-2.5.0-cp315-cp315-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c47300f9bf791808f77d82747691c4bb09cb14bdf3060cca99b42cdc4361d5a7", size = 284910, upload-time = "2026-10-07T12:23:18.166Z" }, + { url = "https://files.pythonhosted.org/packages/cc/05/f4d9cf7de61822ece0c3873f30d291e324911c71a378b8bfe5ced13fd9f5/tomli-2.5.0-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:19b0dd8749f4ea2f112c5fcfb3c5248390c899d7e2e173f1d91abee1fa0ff391", size = 277723, upload-time = "2026-10-07T12:23:19.355Z" }, + { url = "https://files.pythonhosted.org/packages/42/28/78262493141fa543151cf005760c3cb01d09fc28a11f993c05109902cb8c/tomli-2.5.0-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:57b1c3b01fab802e2899bc3d168dca320e14165e2fd9fd584760fb4ca5826859", size = 285115, upload-time = "2026-10-07T12:23:20.698Z" }, + { url = "https://files.pythonhosted.org/packages/1a/b9/e1dab9a30bcb677b5cc5cee810609cfd64f24306a3055767dd3fda00b1e0/tomli-2.5.0-cp315-cp315-win32.whl", hash = "sha256:667e521b37a6c5ccaa044202c235b530f90177ffe2cd4a64ecc213c7dd535feb", size = 103475, upload-time = "2026-10-07T12:23:21.941Z" }, + { url = "https://files.pythonhosted.org/packages/4c/bd/31a3790c11d6ea95fcf5e6022ac0f8d0543c9b61120b730fc481bd43d3b4/tomli-2.5.0-cp315-cp315-win_amd64.whl", hash = "sha256:d747252933c8a65ef6bd8da0fbb7ce28a90eb6119d8cd00772cd528aa07b68d5", size = 114589, upload-time = "2026-10-07T12:23:23.098Z" }, + { url = "https://files.pythonhosted.org/packages/47/a2/4f6310fa699364f0e3af7ee3af88dddd9af066d33e716a0265bbe2b3ea84/tomli-2.5.0-cp315-cp315-win_arm64.whl", hash = "sha256:75dbcde8751b0a960aa3de173aa5e894d590755c6d7758b7e774c06f1dc3cbdd", size = 111493, upload-time = "2026-10-07T12:23:24.233Z" }, + { url = "https://files.pythonhosted.org/packages/68/14/00853f0b396d8971107ae1921bb5b322fdee1650d2f16bf06c20adb532e5/tomli-2.5.0-cp315-cp315t-macosx_10_15_x86_64.whl", hash = "sha256:2419c2a189551987b59d80e63ec355671283336f41c6b9b89462df679c7d0c57", size = 171380, upload-time = "2026-10-07T12:23:25.512Z" }, + { url = "https://files.pythonhosted.org/packages/89/ad/fa6949321dadee46b27363974fb197b94c911c3b0f7a5fd26d7dc18fc2a0/tomli-2.5.0-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:0dc598040da8d42cf20f0be588ed7004f46db12a0ac6c32e03a59dccedaaadcd", size = 170553, upload-time = "2026-10-07T12:23:26.855Z" }, + { url = "https://files.pythonhosted.org/packages/53/aa/3056c919eb3e084df3752b2cf5f865dcc04af0b27dba2f66d7b28af4633a/tomli-2.5.0-cp315-cp315t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:49096930c8d886c9bbdab62d2d0d17ce823ddeea522309a190b36245d5b49e01", size = 294428, upload-time = "2026-10-07T12:23:28.132Z" }, + { url = "https://files.pythonhosted.org/packages/96/b2/faeeb5d8769ea3832021d73e892c8391eae7b4b4f8b55a789127bd8b18a9/tomli-2.5.0-cp315-cp315t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b8ade5023067f99fe72b88accd30d0ea05a158e9e32a11f124e731ea9695313f", size = 304909, upload-time = "2026-10-07T12:23:29.381Z" }, + { url = "https://files.pythonhosted.org/packages/f6/52/f094c09e73fb654b621716d019acb5d29bdfd1be01df80c281d552bda48d/tomli-2.5.0-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:b69564772b5c8f22ea5f498dff08cfa825045b4d4c4400529000bdf818aa3b2a", size = 293220, upload-time = "2026-10-07T12:23:30.608Z" }, + { url = "https://files.pythonhosted.org/packages/86/f5/0c30541078ca4b505ce3bd76ed931facbfec524dd018535d691d1af0a6d2/tomli-2.5.0-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:8ff3a2ca028c7eee0c777f9a092038d0a594a9fa04e215f929a22c329e2cb142", size = 305705, upload-time = "2026-10-07T12:23:32.181Z" }, + { url = "https://files.pythonhosted.org/packages/05/74/590e7d19d6a118fc5cc5704ff358e21d95b8573f6b9443b1519f29ca8825/tomli-2.5.0-cp315-cp315t-win32.whl", hash = "sha256:62fc1bc8eb03e3a9cadfca713d65614ed8e09d974a283295ffe3a831976b4dc5", size = 108432, upload-time = "2026-10-07T12:23:33.496Z" }, + { url = "https://files.pythonhosted.org/packages/1c/b8/63a75cfb27a17c38550e44025d3a6e7be64516fd8608a3b75703bf37d81b/tomli-2.5.0-cp315-cp315t-win_amd64.whl", hash = "sha256:f3fcbc57b1791fa6cbe5d8434179d51de12be1a4811469529f47f6e7487a2571", size = 117281, upload-time = "2026-10-07T12:23:34.648Z" }, + { url = "https://files.pythonhosted.org/packages/72/01/e8c1debb2173973372934c68fc8e46170ab60ef23ed4592dff4dec6e8993/tomli-2.5.0-cp315-cp315t-win_arm64.whl", hash = "sha256:d2ba24db8a9376921b5e87b4762b9adb0f3f1deaea68f2b8b0bb2c11efb9c3e7", size = 115069, upload-time = "2026-10-07T12:23:35.77Z" }, + { url = "https://files.pythonhosted.org/packages/60/3f/3e3f8fd0919249b0200c80fbc4f9a1e70be19f9883da71dfb7f8b9ab8aca/tomli-2.5.0-py3-none-any.whl", hash = "sha256:32a7b79ac57a2e83670ce329ccf675798bc5a2094783a63676866b70503f2e2b", size = 14765, upload-time = "2026-10-07T12:23:36.875Z" }, +] + +[[package]] +name = "typing-extensions" +version = "4.16.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f6/cc/6253133b5bb138fc3306cebfbda2c520f545d36b5be2c7255cc528bb45d6/typing_extensions-4.16.0.tar.gz", hash = "sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5", size = 113555, upload-time = "2026-07-02T08:40:05.92Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/49/d3/b8441a820a491ddfc024b0b0cf0393375b75ea13866d9c66727e54c2fc80/typing_extensions-4.16.0-py3-none-any.whl", hash = "sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8", size = 45571, upload-time = "2026-07-02T08:40:04.659Z" }, +] + +[[package]] +name = "tzdata" +version = "2026.5" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d9/68/f1b440335057bfce71b6e50a9d09445aa2ecbd08359a337976627b8409e7/tzdata-2026.5.tar.gz", hash = "sha256:8cc73c0a0bfca7dbfa59235d60b2eff82231dee33f53d206db1acd9173cfc0a7", size = 200404, upload-time = "2026-10-03T09:23:14.143Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/94/21/1e5995a1c920cce14e4bffae20c665ec10e7ed03ab25e006cd741092b718/tzdata-2026.5-py2.py3-none-any.whl", hash = "sha256:b683bd1b6659ddcd810ff02ad09ba821d4bf1065072805063eb35c49617905ac", size = 347996, upload-time = "2026-10-03T09:23:12.535Z" }, +] + +[[package]] +name = "urllib3" +version = "2.8.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e3/05/b17359e1cefb4f909b5e40b1b90a496d987258916dbbf88e842c729f510e/urllib3-2.8.0.tar.gz", hash = "sha256:63bf2ead4c879426ebf22ef2a781eeb4aa3b4ae798a0435506f8687fd5bb9b63", size = 458972, upload-time = "2026-09-15T19:29:36.253Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/92/9d/c4e665119135114480843e7ab388fa94d8480650450e6f8e26b70d323a4c/urllib3-2.8.0-py3-none-any.whl", hash = "sha256:0cf3cae568d36aa9576b28dfb35f11328f1cb974ca7647d9475ebb86c75ac6e3", size = 135717, upload-time = "2026-09-15T19:29:34.577Z" }, +]