diff --git a/.dockerignore b/.dockerignore index a1b797f..41ec0d7 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,26 +1,34 @@ +.git/ .github/ -.venv/ .vscode/ .idea/ + +.venv/ +__pycache__/ +*.py[cod] +*.egg-info/ + +.pytest_cache/ +.mypy_cache/ +.ruff_cache/ +.coverage +.coverage.* +htmlcov/ +test-results.xml + ci/ doc/ -gurobi/ -htmlcov/ local_test/ -*.egg-info/ -unit_test/ +tests/ +gurobi/ + .env -.env.local -.env.template -.gitignore -.taplo.toml +.env.* + CHANGELOG.md CONTRIBUTING.md -dev.Dockerfile -docker-compose.worker-only.yml -docker-compose.yml LICENSE run.bat run.sh run_windows.sh -test-results.xml +dev.Dockerfile diff --git a/.env.template b/.env.template index 14f4455..35bf500 100644 --- a/.env.template +++ b/.env.template @@ -1,22 +1,32 @@ -ESDL_OUTPUT_PROFILES_TYPE=POSTGRESQL +LOG_LEVEL=INFO +ESDL_OUTPUT_PROFILES_TYPE=POSTGRESQL DB_HOSTNAME=omotes_postgres DB_PORT=6432 DB_USERNAME=omotes_timeseries_rw DB_PASSWORD=somepass4 -RABBITMQ_USERNAME=celery -RABBITMQ_PASSWORD=somepass2 -RABBITMQ_HOSTNAME=localhost -RABBITMQ_PORT=5672 -RABBITMQ_VIRTUALHOST=omotes_celery +# ESDL_OUTPUT_PROFILES_TYPE=INFLUXDB +# DB_HOSTNAME=omotes_influxdb +# DB_PORT=8096 +# DB_USERNAME=root +# DB_PASSWORD=9012 -# May be grow_optimizer_default, grow_optimizer_no_heat_losses, grow_optimizer_with_pressure or grow_simulator -GROW_TASK_TYPE=grow_optimizer_default -LOG_LEVEL=INFO +MINIO_HOST=minio:9000 +MINIO_EXTERNAL_HOST=minio:9000 +MINIO_ACCESS_KEY=omotesadmin +MINIO_SECRET=password + +PREFECT_API_URL=http://localhost:4200/api +PREFECT_API_URL_FOR_WORKER=http://prefect-server:4200/api +PREFECT_WORK_POOL_NAME="docker-worker" +PREFECT_API_AUTH_STRING=admin:password -TASK_RESULT_QUEUE_NAME=omotes_task_result_events -TASK_PROGRESS_QUEUE_NAME=omotes_task_progress_events +PREFECT_FLOW_MAX_CONCURRENT_RUNS=4 -# MAX_TASKS_BEFORE_RESTART: 0 means no scheduled restarts -MAX_TASKS_BEFORE_RESTART=0 +# For deploying to prefect (will run inside local docker container or k8s pod) +# When using docker desktop you can use your local code without pushing to gitlab first: +PREFECT_USE_LOCAL_CODE_AND_IMAGE=false +PREFECT_USE_LOCAL_SDK_AND_MESIDO=false +# OPTIMIZER_WORKER_VERSION not used when PREFECT_USE_LOCAL_CODE_AND_IMAGE=true: +OPTIMIZER_WORKER_VERSION=3.0.0 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ac5d42f..16c4167 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,45 +6,41 @@ jobs: lint: name: Lint runs-on: ubuntu-latest - strategy: - matrix: - python-version: [ "3.10" ] steps: - - uses: actions/checkout@v3 - - name: setup python + - uses: actions/checkout@v4 + - name: Set up Python uses: actions/setup-python@v4 with: - python-version: ${{ matrix.python-version }} - cache: pip - - name: create and activate venv - run: | - ./ci/linux/create_venv.sh - ./ci/linux/install_dependencies.sh - - name: run lint - run: | - ./ci/linux/lint.sh + python-version: "3.10" + - name: Install uv + uses: astral-sh/setup-uv@v2 + - name: Install just + uses: taiki-e/install-action@just + - name: Install dependencies + run: just install + - name: Run linter + run: just lint + - name: Check formatting + run: just format-check test: - name: Unit Tests + name: Test runs-on: ubuntu-latest - strategy: - matrix: - python-version: [ "3.10" ] steps: - - uses: actions/checkout@v3 - - name: setup python + - uses: actions/checkout@v4 + - name: Set up Python uses: actions/setup-python@v4 with: - python-version: ${{ matrix.python-version }} - cache: pip - - name: create and activate venv - run: | - ./ci/linux/create_venv.sh - ./ci/linux/install_dependencies.sh - - name: run unit tests - run: | - ./ci/linux/test_unit.sh - - name: surface failing tests + python-version: "3.10" + - name: Install uv + uses: astral-sh/setup-uv@v2 + - name: Install just + uses: taiki-e/install-action@just + - name: Install dependencies + run: just install + - name: Run unit tests + run: just test + - name: Publish test results if: always() uses: pmeier/pytest-results-action@main with: @@ -54,22 +50,19 @@ jobs: fail-on-empty: true typecheck: - name: Typecheck + name: Type Check runs-on: ubuntu-latest - strategy: - matrix: - python-version: [ "3.10" ] steps: - - uses: actions/checkout@v3 - - name: setup python + - uses: actions/checkout@v4 + - name: Set up Python uses: actions/setup-python@v4 with: - python-version: ${{ matrix.python-version }} - cache: pip - - name: create and activate venv - run: | - ./ci/linux/create_venv.sh - ./ci/linux/install_dependencies.sh - - name: run typechecker - run: | - ./ci/linux/typecheck.sh \ No newline at end of file + python-version: "3.10" + - name: Install uv + uses: astral-sh/setup-uv@v2 + - name: Install just + uses: taiki-e/install-action@just + - name: Install dependencies + run: just install + - name: Run type checker + run: just typecheck \ No newline at end of file diff --git a/.github/workflows/publish_container_image.yml b/.github/workflows/publish_container_image.yml index d366636..8e461ad 100644 --- a/.github/workflows/publish_container_image.yml +++ b/.github/workflows/publish_container_image.yml @@ -1,28 +1,48 @@ -name: Deply to GitHub Container Registry +name: Publish Container Image +run-name: Releasing next version 🚀 + on: push: tags: - - '*' + - "*" jobs: - publish-container-image: - runs-on: ubuntu-latest - steps: - - name: Checkout sources - uses: actions/checkout@v3 - with: - fetch-depth: 0 + publish-container-image: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + steps: + - name: Checkout sources + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} - - name: Login to GitHub Container Registry - uses: docker/login-action@v1 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} + - name: Extract Docker metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: ghcr.io/project-omotes/omotes-optimizer + tags: | + type=raw,value=latest + type=raw,value=${{ github.ref_name }} - - name: Build the container image - run: | - docker build . --tag ghcr.io/project-omotes/omotes-grow-optimizer-worker:latest --tag ghcr.io/project-omotes/omotes-grow-optimizer-worker:${{ github.ref_name}} - docker push ghcr.io/project-omotes/omotes-grow-optimizer-worker:latest - docker push ghcr.io/project-omotes/omotes-grow-optimizer-worker:${{ github.ref_name}} + - name: Build and push container image + uses: docker/build-push-action@v6 + with: + context: . + file: ./Dockerfile + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/.gitignore b/.gitignore index 48f5126..efae4e6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,226 +1,48 @@ -# Byte-compiled / optimized / DLL files +# Byte-compiled / optimized files __pycache__/ *.py[cod] *$py.class -# C extensions +# Native extensions *.so -# Distribution / packaging -.Python + # Build / packaging artifacts build/ -develop-eggs/ dist/ -downloads/ -eggs/ +*.egg-info/ .eggs/ -lib/ -lib64/ -parts/ -sdist/ -var/ -wheels/ pip-wheel-metadata/ -share/python-wheels/ -*.egg-info/ -.installed.cfg *.egg -MANIFEST -# PyInstaller -# Usually these files are written by a python script from a template -# before PyInstaller builds the exe, so as to inject date/other infos into it. -*.manifest -*.spec +# Virtual environments +.venv/ +venv/ +env/ +ENV/ -# Installer logs -pip-log.txt -pip-delete-this-directory.txt +# Local environment files +.env -# Unit test / coverage reports -htmlcov/ -.tox/ -.nox/ +# Test / coverage artifacts +.pytest_cache/ .coverage .coverage.* -.cache -nosetests.xml +htmlcov/ coverage.xml -*.cover -*.py,cover -.hypothesis/ -.pytest_cache/ - -# Translations -*.mo -*.pot - -# Django stuff: -*.log -local_settings.py -db.sqlite3 -db.sqlite3-journal - -# Flask stuff: -instance/ -.webassets-cache - -# Scrapy stuff: -.scrapy - -# Sphinx documentation -doc/*/_build/ -doc/*/_static/ -doc/*/_templates/ - -# PyBuilder -target/ - -# Jupyter Notebook -.ipynb_checkpoints - -# IPython -profile_default/ -ipython_config.py - -# pyenv -.python-version - -# pipenv -# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. -# However, in case of collaboration, if having platform-specific dependencies or dependencies -# having no cross-platform support, pipenv may install dependencies that don't work, or not -# install all needed dependencies. -#Pipfile.lock - -# PEP 582; used by e.g. github.com/David-OConnor/pyflow -__pypackages__/ - -# Celery stuff -celerybeat-schedule -celerybeat.pid - -# SageMath parsed files -*.sage.py - -# Environments -.env -.venv -env/ -venv/ -ENV/ -env.bak/ -venv.bak/ - -# Spyder project settings -.spyderproject -.spyproject - -# Rope project settings -.ropeproject - -# mkdocs documentation -/site +test-results.xml +unit_test_coverage/ -# mypy +# Type checker / linter caches .mypy_cache/ -.dmypy.json -dmypy.json - -# Pyre type checker +.ruff_cache/ .pyre/ -### PyCharm+all ### -# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider -# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 - -# User-specific stuff -.idea/**/workspace.xml -.idea/**/tasks.xml -.idea/**/usage.statistics.xml -.idea/**/dictionaries -.idea/**/shelf - -# AWS User-specific -.idea/**/aws.xml - -# Generated files -.idea/**/contentModel.xml - -# Sensitive or high-churn files -.idea/**/dataSources/ -.idea/**/dataSources.ids -.idea/**/dataSources.local.xml -.idea/**/sqlDataSources.xml -.idea/**/dynamic.xml -.idea/**/uiDesigner.xml -.idea/**/dbnavigator.xml - -# Gradle -.idea/**/gradle.xml -.idea/**/libraries - -# Gradle and Maven with auto-import -# When using Gradle or Maven with auto-import, you should exclude module files, -# since they will be recreated, and may cause churn. Uncomment if using -# auto-import. -# .idea/artifacts -# .idea/compiler.xml -# .idea/jarRepositories.xml -# .idea/modules.xml -# .idea/*.iml -# .idea/modules -# *.iml -# *.ipr - -# CMake -cmake-build-*/ - -# Mongo Explorer plugin -.idea/**/mongoSettings.xml - -# File-based project format -*.iws - -# IntelliJ -out/ - -# mpeltonen/sbt-idea plugin -.idea_modules/ - -# JIRA plugin -atlassian-ide-plugin.xml - -# Cursive Clojure plugin -.idea/replstate.xml - -# SonarLint plugin -.idea/sonarlint/ - -# Crashlytics plugin (for Android Studio and IntelliJ) -com_crashlytics_export_strings.xml -crashlytics.properties -crashlytics-build.properties -fabric.properties - -# Editor-based Rest Client -.idea/httpRequests - -# Android studio 3.1+ serialized cache file -.idea/caches/build_file_checksums.ser - -### PyCharm+all Patch ### -# Ignore everything but code style settings and run configurations -# that are supposed to be shared within teams. - -.idea/* +# Editor / IDE +.idea/ -!.idea/codeStyles -!.idea/runConfigurations - -unit_test_coverage/ -test-results.xml +# Notebook checkpoints +.ipynb_checkpoints/ +# Misc local output temp/ gurobi/ -.idea/ diff --git a/.taplo.toml b/.taplo.toml deleted file mode 100644 index 66d8049..0000000 --- a/.taplo.toml +++ /dev/null @@ -1,5 +0,0 @@ -include = ["pyproject.toml"] - - -[schema] -path = "https://json.schemastore.org/pyproject.json" diff --git a/.vscode/launch.json b/.vscode/launch.json index 00aff4e..a6cab56 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -2,17 +2,43 @@ "version": "0.2.0", "configurations": [ { - "name": "Run worker.py", + "name": "prefect_deploy_flow", "type": "debugpy", "request": "launch", - "program": "${workspaceFolder}/src/grow_worker/worker.py", + "program": "${workspaceFolder}/src/omotes_optimizer_worker/prefect_deploy_flow.py", + "cwd": "${workspaceFolder}/src", "console": "integratedTerminal", + "env": { + "PYTHONPATH": "${workspaceFolder}/src" + }, + "envFile": "${workspaceFolder}/.env" + }, + { + "name": "run_optimizer_flow_function", + "type": "debugpy", + "request": "launch", + "program": "${workspaceFolder}/local_test/run_optimizer_flow_function.py", "cwd": "${workspaceFolder}", - "justMyCode": true, + "console": "integratedTerminal", "env": { "PYTHONPATH": "${workspaceFolder}/src" }, "envFile": "${workspaceFolder}/.env" + }, + { + "name": "pytest", + "type": "debugpy", + "request": "launch", + "module": "pytest", + "args": [ + "tests", + "-q" + ], + "env": { + "PYTHONPATH": "${workspaceFolder}/src" + }, + "console": "integratedTerminal", + "justMyCode": false } ] } \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 9d29e7e..c459c01 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,24 +1,23 @@ { "flake8.enabled": false, "[python]": { - "editor.formatOnSave": true, - "editor.defaultFormatter": "ms-python.black-formatter", + "editor.defaultFormatter": "charliermarsh.ruff", "editor.codeActionsOnSave": { - "source.organizeImports": "explicit" - }, + "source.fixAll.ruff": "always", + "source.organizeImports.ruff": "explicit" + } }, "python.analysis.typeCheckingMode": "basic", "python.testing.unittestArgs": [ "-v", "-s", - "./unit_test", + "./tests", "-p", "test_*.py" ], "python.testing.pytestEnabled": true, "python.testing.unittestEnabled": false, "python.testing.autoTestDiscoverOnSaveEnabled": true, - "mypy.runUsingActiveInterpreter": true, "isort.args": [ "--profile", "black" @@ -26,4 +25,18 @@ "terminal.integrated.env.windows": { "PYTHONPATH": "${workspaceFolder}/src" }, + "python.languageServer": "None", // disable Pylance (ruff/ty is used) + "ty.diagnosticMode": "workspace", + "ty.importStrategy": "fromEnvironment", + "ty.interpreter": "${workspaceFolder}/.venv/bin/python", + "ruff.organizeImports": true, + "ruff.lint.enable": true, + "[just]": { + "editor.formatOnSave": false, + "editor.defaultFormatter": null + }, + "files.associations": { + "justfile": "just", + "*.just": "just" + } } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index 149a75c..0000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,32 +0,0 @@ -# Changelog -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.0.0/), -and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - -## [Unreleased] - 2024-3-31 -### Added -- New functionality added to the project, with reference to issue-ticket (#123) -- Another new item (#1234) - -### Fixed -- bugfixes, with references to your issue-tickets (#123) -- another bugfix (#1234) - -### Changed -- Changes, for example code structure -- but also changed/updated dependencies -- Add references to tickets where applicable (#123) - -### Removed -- Files that have been removed -- Functionality that has been removed -- Add references to tickets where applicable (#123) - -## [0.0.1] - 2023-09-21 -### Added -- Kickoff of Nieuwe Warmte Nu!. -- initialized repo from template. - -### Changed -- everything. diff --git a/Dockerfile b/Dockerfile index c6652ef..688ebb9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM python:3.10-slim-bookworm +FROM python:3.11-slim-bookworm WORKDIR /app RUN apt update && \ @@ -18,13 +18,21 @@ ENV GUROBI_VERSION="$CASADI_GUROBI_VERSION" # This env var is for gurobi ENV GRB_LICENSE_FILE="/app/gurobi/gurobi.lic" - RUN mkdir -p /app/gurobi && \ wget -qO- https://packages.gurobi.com/${GUROBI_VERSION_URL_MAJOR}/gurobi${GUROBI_VERSION_URL}_linux64.tar.gz | tar xvz --strip-components=2 -C /app/gurobi -COPY requirements.txt /app/grow_worker/requirements.txt -RUN pip install -r /app/grow_worker/requirements.txt --no-cache-dir +# install uv +COPY --from=ghcr.io/astral-sh/uv:0.8.22 /uv /uvx /bin/ + +WORKDIR /src -COPY src/grow_worker /app/grow_worker/ +# install dependencies, avoid using Gurobi's embedded python +ENV UV_PYTHON=/usr/local/bin/python3.11 +RUN --mount=type=cache,target=/root/.cache/uv \ + --mount=type=bind,source=uv.lock,target=uv.lock \ + --mount=type=bind,source=pyproject.toml,target=pyproject.toml \ + uv sync --locked --no-install-project --no-dev +# enable running commands without 'uv run' +ENV PATH="/src/.venv/bin:$PATH" -CMD ["python3", "-m", "grow_worker.worker"] +COPY src . diff --git a/README.md b/README.md index dde100b..36d3e31 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,83 @@ # Optimizer worker -to test locally run: -``` -docker-compose up +Prefect flow repo for the NWN optimizer.\ +This defines the prefect flow function which is the entry function for prefect runs.\ +There is a `prefect_deploy_flow` script to create/update a prefect deployment which can be used for runs. + +## Development + +### Tools + +This project uses: + +- **uv**: Fast Python package manager and resolver. Install via [https://docs.astral.sh/uv/](https://docs.astral.sh/uv/) +- **just**: Command runner for common tasks (similar to Make). Install via [https://github.com/casey/just](https://github.com/casey/just) + +### Setup + +1. Install dependencies: + + ```bash + uv sync + ``` + +2. Copy `.env.template` to `.env` + +**Note** to use local code for sdk run `.venv/bin/pip install -e ../omotes-sdk-python/`. + +### Run/debug the prefect flow function locally + +In vscode go to the debug view and run `run_optimizer_flow_function`. This runs the function without prefect. + +### Lint/typecheck/test locally + +Run via just (also used in in github actions): + +```bash +just ci # run all CI checks (lint, format-check, typecheck, test) + +just lint # ruff checks +just format # ruff format +just format-check # verify formatting +just typecheck # ty type checking +just test # pytest ``` -The local_test service can be run multiple times. -The result exit code is printed in each `local_test` test app output. -For testing during development keep `rabbitmq` and `omotes_influxdd` running and run: +To debug test go to the debug view in vscode and run "pytest".\ +When using an editable install of the sdk, don't use the just command as `uv run ...` will remove this editable install. + +### Deploy flow to prefect + +In vscode go to the debug view and run `prefect_deploy_flow`.\ +This will create a deployment on prefect (to the prefect instance on `PREFECT_API_URL`).\ + +During development you may want to deploy local code of this repo instead of an already published image, then set `PREFECT_USE_LOCAL_CODE_AND_IMAGE=true` in `.env`. +To also use local code for the omoted-sdk-python and mesido set `PREFECT_USE_LOCAL_SDK_AND_MESIDO=true` as well. + +## Project Structure + +```text +optimizer-worker/ +├── src/ +│ └── omotes_optimizer_worker/ +│ ├── __init__.py # Package initialization +│ ├── env.py # Environment configuration helpers +│ ├── prefect_deploy_flow.py # Registers/updates Prefect deployment +│ ├── prefect_flow.py # Main Prefect flow implementation +│ └── worker_types.py # Workflow/solver mapping utilities +├── tests/ +│ ├── test_prefect_deploy_flow.py # Tests for deploy flow module behavior +│ └── test_worker_types.py # Tests for worker type mapping logic +├── local_test/ +│ ├── Delft_T.esdl # Local test input ESDL +│ ├── Delft_T feedback.esdl # Local test output/feedback ESDL +│ └── run_optimizer_flow_function.py # Run flow function locally without Prefect +├── doc/ # Project documentation assets +├── gurobi/ +│ └── gurobi.lic # Local Gurobi license file +├── Dockerfile # Runtime image for optimizer worker +├── dev.Dockerfile # Local development image (monorepo/local SDK mode) +├── justfile # Task runner commands (ci, lint, typecheck, test) +├── pyproject.toml # Dependencies and project metadata +└── README.md ``` -docker-compose up --build grow_worker local_test -``` \ No newline at end of file diff --git a/ci/linux/_load_dot_env.sh b/ci/linux/_load_dot_env.sh deleted file mode 100755 index 434c067..0000000 --- a/ci/linux/_load_dot_env.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash - -set -a -source $1 -set +a diff --git a/ci/linux/create_venv.sh b/ci/linux/create_venv.sh deleted file mode 100755 index 13ffbc9..0000000 --- a/ci/linux/create_venv.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env bash - -python3.10 -m venv ./.venv -if [[ "$OSTYPE" != "win32" && "$OSTYPE" != "msys" ]]; then - echo "Activating .venv first." - . .venv/bin/activate -fi -pip3 install pip-tools diff --git a/ci/linux/install_dependencies.sh b/ci/linux/install_dependencies.sh deleted file mode 100755 index e00b897..0000000 --- a/ci/linux/install_dependencies.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env bash - -if [[ "$OSTYPE" != "win32" && "$OSTYPE" != "msys" ]]; then - echo "Activating .venv first." - . .venv/bin/activate -fi - -pip-sync ./dev-requirements.txt ./requirements.txt diff --git a/ci/linux/lint.sh b/ci/linux/lint.sh deleted file mode 100755 index a07472f..0000000 --- a/ci/linux/lint.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env bash - -if [[ "$OSTYPE" != "win32" && "$OSTYPE" != "msys" ]]; then - echo "Activating .venv first." - . .venv/bin/activate -fi - -flake8 ./src/grow_worker ./unit_test/ diff --git a/ci/linux/test_unit.sh b/ci/linux/test_unit.sh deleted file mode 100755 index bff0c15..0000000 --- a/ci/linux/test_unit.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env bash - -if [[ "$OSTYPE" != "win32" && "$OSTYPE" != "msys" ]]; then - echo "Activating .venv first." - . .venv/bin/activate -fi - -PYTHONPATH='$PYTHONPATH:src/' pytest --junit-xml=test-results.xml unit_test/ diff --git a/ci/linux/typecheck.sh b/ci/linux/typecheck.sh deleted file mode 100755 index 70fb623..0000000 --- a/ci/linux/typecheck.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env bash - -if [[ "$OSTYPE" != "win32" && "$OSTYPE" != "msys" ]]; then - echo "Activating .venv first." - . .venv/bin/activate -fi - -python -m mypy ./src/grow_worker ./unit_test/ diff --git a/ci/linux/update_dependencies.sh b/ci/linux/update_dependencies.sh deleted file mode 100755 index fea6566..0000000 --- a/ci/linux/update_dependencies.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/env bash - -if [[ "$OSTYPE" != "win32" && "$OSTYPE" != "msys" ]]; then - echo "Activating .venv first." - . .venv/bin/activate -fi - -pip-compile --upgrade --output-file=requirements.txt pyproject.toml -pip-compile --upgrade --extra=dev -c requirements.txt --output-file=dev-requirements.txt pyproject.toml diff --git a/ci/win32/create_venv.cmd b/ci/win32/create_venv.cmd deleted file mode 100644 index 3cd00af..0000000 --- a/ci/win32/create_venv.cmd +++ /dev/null @@ -1,9 +0,0 @@ -rem Short script to initialize virtual environment using venv and pip -rem @echo off - -pushd . -cd /D "%~dp0" -py -3.10 -m venv ..\..\venv -call ..\..\venv\Scripts\activate.bat -python -m pip install pip-tools -popd diff --git a/ci/win32/install_dependencies.cmd b/ci/win32/install_dependencies.cmd deleted file mode 100644 index e76c29d..0000000 --- a/ci/win32/install_dependencies.cmd +++ /dev/null @@ -1,6 +0,0 @@ - -pushd . -cd /D "%~dp0" -cd ..\..\ -pip-sync .\dev-requirements.txt .\requirements.txt -popd \ No newline at end of file diff --git a/ci/win32/lint.cmd b/ci/win32/lint.cmd deleted file mode 100644 index 061804d..0000000 --- a/ci/win32/lint.cmd +++ /dev/null @@ -1,8 +0,0 @@ -rem Short script to run linting -rem @echo off - -pushd . -cd /D "%~dp0" -cd ..\..\ -flake8 .\src\grow_worker -popd diff --git a/ci/win32/test_unit.cmd b/ci/win32/test_unit.cmd deleted file mode 100644 index c2d51b8..0000000 --- a/ci/win32/test_unit.cmd +++ /dev/null @@ -1,9 +0,0 @@ - -pushd . -cd /D "%~dp0" - -cd ..\..\ -call .\venv\Scripts\activate -set PYTHONPATH=.\src\;%$PYTHONPATH% -pytest unit_test/ -popd \ No newline at end of file diff --git a/ci/win32/typecheck.cmd b/ci/win32/typecheck.cmd deleted file mode 100644 index cd5d30f..0000000 --- a/ci/win32/typecheck.cmd +++ /dev/null @@ -1,8 +0,0 @@ -REM script to run mypy type checker on this source tree. -pushd . -cd /D "%~dp0" -cd ..\..\ -call .\venv\Scripts\activate -set PYTHONPATH=.\src\grow_worker;%$PYTHONPATH% -python -m mypy ./src/grow_worker ./unit_test/ -popd \ No newline at end of file diff --git a/ci/win32/update_dependencies.cmd b/ci/win32/update_dependencies.cmd deleted file mode 100644 index b76748f..0000000 --- a/ci/win32/update_dependencies.cmd +++ /dev/null @@ -1,6 +0,0 @@ - -pushd . -cd /D "%~dp0" -pip-compile --output-file=..\..\requirements.txt ..\..\pyproject.toml -pip-compile --extra=dev --output-file=..\..\dev-requirements.txt -c requirements.txt ..\..\pyproject.toml -popd \ No newline at end of file diff --git a/dev-requirements.txt b/dev-requirements.txt deleted file mode 100644 index 990ec4e..0000000 --- a/dev-requirements.txt +++ /dev/null @@ -1,355 +0,0 @@ -# -# This file is autogenerated by pip-compile with Python 3.10 -# by the following command: -# -# pip-compile --constraint=requirements.txt --extra=dev --output-file=dev-requirements.txt pyproject.toml -# -aio-pika==9.4.3 - # via - # -c requirements.txt - # omotes-sdk-python -aiormq==6.8.1 - # via - # -c requirements.txt - # aio-pika -amqp==5.3.1 - # via - # -c requirements.txt - # kombu -antlr4-python3-runtime==4.13.2 - # via - # -c requirements.txt - # pymoca -attrs==26.1.0 - # via flake8-bugbear -billiard==4.2.4 - # via - # -c requirements.txt - # celery -black==24.10.0 - # via omotes-grow-worker (pyproject.toml) -build==1.2.2.post1 - # via omotes-grow-worker (pyproject.toml) -casadi-gil-comp==3.6.7 - # via - # -c requirements.txt - # mesido - # rtc-tools-gil-comp -celery==5.6.3 - # via - # -c requirements.txt - # omotes-sdk-python -certifi==2026.6.17 - # via - # -c requirements.txt - # requests -charset-normalizer==3.4.9 - # via - # -c requirements.txt - # requests -click==8.4.2 - # via - # -c requirements.txt - # black - # celery - # click-didyoumean - # click-plugins - # click-repl -click-didyoumean==0.3.1 - # via - # -c requirements.txt - # celery -click-plugins==1.1.1.2 - # via - # -c requirements.txt - # celery -click-repl==0.3.0 - # via - # -c requirements.txt - # celery -coolprop==6.6.0 - # via - # -c requirements.txt - # mesido -coverage[toml]==7.15.2 - # via pytest-cov -defusedxml==0.7.1 - # via - # -c requirements.txt - # rtc-tools-gil-comp -et-xmlfile==2.0.0 - # via - # -c requirements.txt - # openpyxl -exceptiongroup==1.3.1 - # via - # -c requirements.txt - # celery - # pytest -flake8==7.1.1 - # via - # flake8-bugbear - # flake8-docstrings - # flake8-pyproject - # flake8-quotes - # flake8-tuple - # omotes-grow-worker (pyproject.toml) -flake8-bugbear==24.10.31 - # via omotes-grow-worker (pyproject.toml) -flake8-docstrings==1.7.0 - # via omotes-grow-worker (pyproject.toml) -flake8-mock==0.4 - # via omotes-grow-worker (pyproject.toml) -flake8-pyproject==1.2.4 - # via omotes-grow-worker (pyproject.toml) -flake8-quotes==3.4.0 - # via omotes-grow-worker (pyproject.toml) -flake8-tuple==0.4.1 - # via omotes-grow-worker (pyproject.toml) -future-fstrings==1.2.0 - # via - # -c requirements.txt - # pyecore -idna==3.18 - # via - # -c requirements.txt - # requests - # yarl -influxdb==5.3.1 - # via - # -c requirements.txt - # mesido - # pyesdl -iniconfig==2.3.0 - # via pytest -isort==5.13.2 - # via omotes-grow-worker (pyproject.toml) -kombu==5.6.2 - # via - # -c requirements.txt - # celery -lxml==6.1.1 - # via - # -c requirements.txt - # pyecore -mccabe==0.7.0 - # via flake8 -mesido==0.1.20.3 - # via - # -c requirements.txt - # omotes-grow-worker (pyproject.toml) -msgpack==1.2.1 - # via - # -c requirements.txt - # influxdb -multidict==6.7.1 - # via - # -c requirements.txt - # yarl -mypy==1.13.0 - # via omotes-grow-worker (pyproject.toml) -mypy-extensions==1.1.0 - # via - # black - # mypy -numpy==1.25.2 - # via - # -c requirements.txt - # casadi-gil-comp - # pandas - # pymoca - # rtc-tools-gil-comp - # scipy -omotes-sdk-protocol==1.2.0 - # via - # -c requirements.txt - # omotes-sdk-python -omotes-sdk-python==4.3.6 - # via - # -c requirements.txt - # omotes-grow-worker (pyproject.toml) -openpyxl==3.1.2 - # via - # -c requirements.txt - # pyesdl -ordered-set==4.1.0 - # via - # -c requirements.txt - # pyecore -packaging==26.2 - # via - # -c requirements.txt - # black - # build - # kombu - # pytest - # setuptools-git-versioning -pamqp==3.3.0 - # via - # -c requirements.txt - # aiormq - # omotes-sdk-python -pandas==1.5.3 - # via - # -c requirements.txt - # mesido -pathspec==1.1.1 - # via black -platformdirs==4.10.0 - # via black -pluggy==1.6.0 - # via pytest -prompt-toolkit==3.0.52 - # via - # -c requirements.txt - # click-repl -propcache==0.5.2 - # via - # -c requirements.txt - # yarl -protobuf==5.29.6 - # via - # -c requirements.txt - # omotes-sdk-protocol -psycopg[binary]==3.3.3 - # via - # -c requirements.txt - # pyesdl -psycopg-binary==3.3.3 - # via - # -c requirements.txt - # psycopg - # pyesdl -pycodestyle==2.12.1 - # via flake8 -pydocstyle==6.3.0 - # via flake8-docstrings -pyecore==0.13.2 - # via - # -c requirements.txt - # mesido - # pyesdl -pyesdl[profiles]==26.7 - # via - # -c requirements.txt - # mesido - # omotes-sdk-python -pyflakes==3.2.0 - # via flake8 -pymoca==0.9.2 - # via - # -c requirements.txt - # mesido - # rtc-tools-channel-flow - # rtc-tools-gil-comp -pyproject-hooks==1.2.0 - # via build -pytest==8.3.5 - # via - # omotes-grow-worker (pyproject.toml) - # pytest-cov -pytest-cov==6.0.0 - # via omotes-grow-worker (pyproject.toml) -python-dateutil==2.9.0.post0 - # via - # -c requirements.txt - # celery - # influxdb - # pandas -python-dotenv==1.0.1 - # via - # -c requirements.txt - # omotes-grow-worker (pyproject.toml) -pytz==2026.2 - # via - # -c requirements.txt - # influxdb - # pandas -requests==2.34.2 - # via - # -c requirements.txt - # influxdb -restrictedpython==8.4 - # via - # -c requirements.txt - # pyecore -rtc-tools-channel-flow==1.3.1 - # via - # -c requirements.txt - # rtc-tools-gil-comp -rtc-tools-gil-comp==2.6.1 - # via - # -c requirements.txt - # mesido -scipy==1.10.1 - # via - # -c requirements.txt - # rtc-tools-gil-comp -setuptools-git-versioning==2.1.0 - # via omotes-grow-worker (pyproject.toml) -six==1.17.0 - # via - # -c requirements.txt - # flake8-tuple - # influxdb - # python-dateutil -snowballstemmer==3.1.1 - # via pydocstyle -streamcapture==1.2.7 - # via - # -c requirements.txt - # omotes-sdk-python -strenum==0.4.15 - # via - # -c requirements.txt - # mesido -tomli==2.4.1 - # via - # black - # build - # coverage - # flake8-pyproject - # mypy - # pytest - # setuptools-git-versioning -typing-extensions==4.16.0 - # via - # -c requirements.txt - # black - # exceptiongroup - # multidict - # mypy - # omotes-sdk-python - # psycopg -tzdata==2026.3 - # via - # -c requirements.txt - # kombu -tzlocal==5.4.4 - # via - # -c requirements.txt - # celery -urllib3==2.7.0 - # via - # -c requirements.txt - # requests -vine==5.1.0 - # via - # -c requirements.txt - # amqp - # celery - # kombu -wcwidth==0.8.2 - # via - # -c requirements.txt - # prompt-toolkit -wheel==0.45.1 - # via omotes-grow-worker (pyproject.toml) -yarl==1.24.2 - # via - # -c requirements.txt - # aio-pika - # aiormq - -# The following packages are considered to be unsafe in a requirements file: -# setuptools diff --git a/dev.Dockerfile b/dev.Dockerfile index c6efedc..2bc2cdb 100644 --- a/dev.Dockerfile +++ b/dev.Dockerfile @@ -1,4 +1,4 @@ -FROM python:3.10-slim-bookworm +FROM python:3.11-slim-bookworm WORKDIR /app RUN apt update && \ @@ -18,18 +18,27 @@ ENV GUROBI_VERSION="$CASADI_GUROBI_VERSION" # This env var is for gurobi ENV GRB_LICENSE_FILE="/app/gurobi/gurobi.lic" - RUN mkdir -p /app/gurobi && \ wget -qO- https://packages.gurobi.com/${GUROBI_VERSION_URL_MAJOR}/gurobi${GUROBI_VERSION_URL}_linux64.tar.gz | tar xvz --strip-components=2 -C /app/gurobi -COPY optimizer-worker/requirements.txt /app/grow_worker/requirements.txt -RUN pip install -r /app/grow_worker/requirements.txt --no-cache-dir +# install uv +COPY --from=ghcr.io/astral-sh/uv:0.8.22 /uv /uvx /bin/ + +WORKDIR /src -COPY ../omotes-sdk-protocol/python/ /omotes-sdk-protocol/python/ -COPY ../omotes-sdk-python/ /omotes-sdk-python/ -RUN pip install /omotes-sdk-python/ -RUN pip install /omotes-sdk-protocol/python/ +# install dependencies, avoid using Gurobi's embedded python +ENV UV_PYTHON=/usr/local/bin/python3.11 +RUN --mount=type=cache,target=/root/.cache/uv \ + --mount=type=bind,source=optimizer-worker/uv.lock,target=uv.lock \ + --mount=type=bind,source=optimizer-worker/pyproject.toml,target=pyproject.toml \ + uv sync --locked --no-install-project --no-dev +# enable running commands without 'uv run' +ENV PATH="/src/.venv/bin:$PATH" -COPY optimizer-worker/src/grow_worker /app/grow_worker/ +# install omotes-sdk-python and mesido from local code +COPY omotes-sdk-python/ /omotes-sdk-python/ +RUN uv pip install --python /src/.venv/bin/python /omotes-sdk-python/ +COPY mesido/ /mesido/ +RUN uv pip install --python /src/.venv/bin/python /mesido/ -CMD ["python3", "-m", "grow_worker.worker"] +COPY optimizer-worker/src . diff --git a/doc/dev_documentation/Makefile b/doc/dev_documentation/Makefile deleted file mode 100644 index d4bb2cb..0000000 --- a/doc/dev_documentation/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# Minimal makefile for Sphinx documentation -# - -# You can set these variables from the command line, and also -# from the environment for the first two. -SPHINXOPTS ?= -SPHINXBUILD ?= sphinx-build -SOURCEDIR = . -BUILDDIR = _build - -# Put it first so that "make" without argument is like "make help". -help: - @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) - -.PHONY: help Makefile - -# Catch-all target: route all unknown targets to Sphinx using the new -# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). -%: Makefile - @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/doc/dev_documentation/Tools.rst b/doc/dev_documentation/Tools.rst deleted file mode 100644 index 2f4653f..0000000 --- a/doc/dev_documentation/Tools.rst +++ /dev/null @@ -1,60 +0,0 @@ -Tools & IDE's -=================================================================== - -.. toctree:: - :maxdepth: 2 - :caption: Contents: - - -There are numerous IDE's for developing python applications, but we -will focus on two: Visual Studio Code and PyCharm - -General -------- -Python code can be writtin using any text editor. However, we've chosen the following tools to support us: - -- **Black** for code formatting -- **Flake8** for code linting -- **MyPy** for typehints/typeChecking -- **pytest** for unit testing -- - -PyCharm -------- - - - - - -VS Code -------- - -The following extensions should be installed: - -* https://marketplace.visualstudio.com/items?itemName=ms-python.python -* https://marketplace.visualstudio.com/items?itemName=ms-python.flake8 -* https://marketplace.visualstudio.com/items?itemName=ms-python.black-formatter -* https://marketplace.visualstudio.com/items?itemName=matangover.mypy - -settings.json for vscode: - -.. code-block:: JSON - - { - "python.analysis.typeCheckingMode": "basic", - "[python]": { - "editor.defaultFormatter": "ms-python.black-formatter" - }, - "python.formatting.provider": "black", - "mypy.runUsingActiveInterpreter": true, - } - - - - -Indices and tables ------------------- - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` diff --git a/doc/dev_documentation/conf.py b/doc/dev_documentation/conf.py deleted file mode 100644 index 2c567ef..0000000 --- a/doc/dev_documentation/conf.py +++ /dev/null @@ -1,57 +0,0 @@ -# Configuration file for the Sphinx documentation builder. -# -# This file only contains a selection of the most common options. For a full -# list see the documentation: -# https://www.sphinx-doc.org/en/master/usage/configuration.html - -# -- Path setup -------------------------------------------------------------- - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -# -# import os -# import sys -# sys.path.insert(0, os.path.abspath('.')) - - -# -- Project information ----------------------------------------------------- - -project = 'Nieuwe Warmte Nu! python user documentation' -copyright = '2023, NieuweWarmteNu Design Toolkit' -author = 'Sebastiaan la Fleur' - - -# -- General configuration --------------------------------------------------- - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. -extensions = [ - "sphinx.ext.autodoc", - "sphinx.ext.intersphinx", - "sphinx.ext.autosummary", - "sphinx.ext.napoleon", - "sphinx_copybutton", -] - -# Add any paths that contain templates here, relative to this directory. -templates_path = ["_templates"] - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -# This pattern also affects html_static_path and html_extra_path. -exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] - - -# -- Options for HTML output ------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -# -html_theme = "furo" - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ["_static"] diff --git a/doc/dev_documentation/index.rst b/doc/dev_documentation/index.rst deleted file mode 100644 index 77be81e..0000000 --- a/doc/dev_documentation/index.rst +++ /dev/null @@ -1,24 +0,0 @@ -.. Deltares python Developer documentation documentation master file, created by - sphinx-quickstart on Fri Apr 21 15:13:59 2023. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - -Welcome to Design Toolkit python Developer documentation's documentation! -=================================================================== - -.. toctree:: - :maxdepth: 2 - :caption: Contents: - - Tools - -This is the developer documentation for this project. This documentation provides -information on tools, configurations and howto's for developers. - - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` diff --git a/doc/dev_documentation/make.bat b/doc/dev_documentation/make.bat deleted file mode 100644 index 954237b..0000000 --- a/doc/dev_documentation/make.bat +++ /dev/null @@ -1,35 +0,0 @@ -@ECHO OFF - -pushd %~dp0 - -REM Command file for Sphinx documentation - -if "%SPHINXBUILD%" == "" ( - set SPHINXBUILD=sphinx-build -) -set SOURCEDIR=. -set BUILDDIR=_build - -%SPHINXBUILD% >NUL 2>NUL -if errorlevel 9009 ( - echo. - echo.The 'sphinx-build' command was not found. Make sure you have Sphinx - echo.installed, then set the SPHINXBUILD environment variable to point - echo.to the full path of the 'sphinx-build' executable. Alternatively you - echo.may add the Sphinx directory to PATH. - echo. - echo.If you don't have Sphinx installed, grab it from - echo.https://www.sphinx-doc.org/ - exit /b 1 -) - -if "%1" == "" goto help - -%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% -goto end - -:help -%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% - -:end -popd diff --git a/doc/user_documentation/Makefile b/doc/user_documentation/Makefile deleted file mode 100644 index d4bb2cb..0000000 --- a/doc/user_documentation/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# Minimal makefile for Sphinx documentation -# - -# You can set these variables from the command line, and also -# from the environment for the first two. -SPHINXOPTS ?= -SPHINXBUILD ?= sphinx-build -SOURCEDIR = . -BUILDDIR = _build - -# Put it first so that "make" without argument is like "make help". -help: - @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) - -.PHONY: help Makefile - -# Catch-all target: route all unknown targets to Sphinx using the new -# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). -%: Makefile - @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/doc/user_documentation/conf.py b/doc/user_documentation/conf.py deleted file mode 100644 index d31a147..0000000 --- a/doc/user_documentation/conf.py +++ /dev/null @@ -1,52 +0,0 @@ -# Configuration file for the Sphinx documentation builder. -# -# This file only contains a selection of the most common options. For a full -# list see the documentation: -# https://www.sphinx-doc.org/en/master/usage/configuration.html - -# -- Path setup -------------------------------------------------------------- - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -# -# import os -# import sys -# sys.path.insert(0, os.path.abspath('.')) - - -# -- Project information ----------------------------------------------------- - -project = 'Nieuwe Warmte Nu! python user documentation' -copyright = '2023, NieuweWarmteNu Design Toolkit' -author = 'Sebastiaan la Fleur' - - -# -- General configuration --------------------------------------------------- - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. -extensions = [ -] - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -# This pattern also affects html_static_path and html_extra_path. -exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] - - -# -- Options for HTML output ------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -# -html_theme = 'alabaster' - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] \ No newline at end of file diff --git a/doc/user_documentation/index.rst b/doc/user_documentation/index.rst deleted file mode 100644 index 097493f..0000000 --- a/doc/user_documentation/index.rst +++ /dev/null @@ -1,20 +0,0 @@ -.. Deltares python user documentation documentation master file, created by - sphinx-quickstart on Fri Apr 21 15:13:29 2023. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - -Welcome to Design Toolkit python user documentation's documentation! -============================================================== - -.. toctree:: - :maxdepth: 2 - :caption: Contents: - - - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` diff --git a/doc/user_documentation/make.bat b/doc/user_documentation/make.bat deleted file mode 100644 index 954237b..0000000 --- a/doc/user_documentation/make.bat +++ /dev/null @@ -1,35 +0,0 @@ -@ECHO OFF - -pushd %~dp0 - -REM Command file for Sphinx documentation - -if "%SPHINXBUILD%" == "" ( - set SPHINXBUILD=sphinx-build -) -set SOURCEDIR=. -set BUILDDIR=_build - -%SPHINXBUILD% >NUL 2>NUL -if errorlevel 9009 ( - echo. - echo.The 'sphinx-build' command was not found. Make sure you have Sphinx - echo.installed, then set the SPHINXBUILD environment variable to point - echo.to the full path of the 'sphinx-build' executable. Alternatively you - echo.may add the Sphinx directory to PATH. - echo. - echo.If you don't have Sphinx installed, grab it from - echo.https://www.sphinx-doc.org/ - exit /b 1 -) - -if "%1" == "" goto help - -%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% -goto end - -:help -%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% - -:end -popd diff --git a/docker-compose.worker-only.dev.yml b/docker-compose.worker-only.dev.yml deleted file mode 100644 index 676732f..0000000 --- a/docker-compose.worker-only.dev.yml +++ /dev/null @@ -1,34 +0,0 @@ -networks: - omotes: - external: true - -services: - grow_worker: - build: - context: .. - dockerfile: optimizer-worker/dev.Dockerfile - environment: - INFLUXDB_HOSTNAME: omotes_influxdb - INFLUXDB_PORT: 8096 - INFLUXDB_USERNAME: root - INFLUXDB_PASSWORD: 9012 - - RABBITMQ_HOSTNAME: rabbitmq-nwn - RABBITMQ_PORT: 5672 - RABBITMQ_USERNAME: root - RABBITMQ_PASSWORD: 5678 - RABBITMQ_VIRTUALHOST: omotes_celery - - GROW_TASK_TYPE: grow_optimizer_no_heat_losses_gurobi - LOG_LEVEL: INFO - volumes: - - "./gurobi/gurobi.lic:/app/gurobi/gurobi.lic" - networks: - - omotes - deploy: - replicas: 1 - resources: - limits: - cpus: '4' - memory: 4gb - memswap_limit: 4gb diff --git a/docker-compose.worker-only.yml b/docker-compose.worker-only.yml deleted file mode 100644 index 2c54610..0000000 --- a/docker-compose.worker-only.yml +++ /dev/null @@ -1,33 +0,0 @@ -networks: - omotes: - external: true - -services: - grow_worker: - build: - context: . - environment: - INFLUXDB_HOSTNAME: omotes_influxdb - INFLUXDB_PORT: 8096 - INFLUXDB_USERNAME: root - INFLUXDB_PASSWORD: 9012 - - RABBITMQ_HOSTNAME: rabbitmq-nwn - RABBITMQ_PORT: 5672 - RABBITMQ_USERNAME: root - RABBITMQ_PASSWORD: 5678 - RABBITMQ_VIRTUALHOST: omotes_celery - - GROW_TASK_TYPE: grow_optimizer_default - LOG_LEVEL: DEBUG - volumes: - - "./gurobi/gurobi.lic:/app/gurobi/gurobi.lic" - networks: - - omotes - deploy: - replicas: 3 - resources: - limits: - cpus: '4' - memory: 4gb - memswap_limit: 4gb diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index 21bfbdb..0000000 --- a/docker-compose.yml +++ /dev/null @@ -1,67 +0,0 @@ -networks: - omotes: - -volumes: - db-data: - broker-data: - influxdb_storage: - -services: - rabbitmq: - image: bitnami/rabbitmq:3.8.27 - ports: - - "15672:15672" - - "5673:5672" - networks: - - omotes - healthcheck: - test: [ "CMD", "curl", "-f", "http://localhost:15672" ] - interval: 10s - timeout: 10s - retries: 5 - - omotes_influxdb: - image: influxdb:1.7 - ports: - - "${INFLUXDB_PORT}:${INFLUXDB_PORT}" - - "${INFLUXDB_RPC_PORT}:${INFLUXDB_RPC_PORT}" - networks: - - omotes - environment: - - INFLUXDB_ADMIN_USER=${INFLUXDB_ADMIN_USER} - - INFLUXDB_ADMIN_PASSWORD=${INFLUXDB_ADMIN_PASSWORD} - - INFLUXDB_HTTP_BIND_ADDRESS=:${INFLUXDB_PORT} - - INFLUXDB_BIND_ADDRESS=:${INFLUXDB_RPC_PORT} - - INFLUXDB_DB=omotes_timeseries - - INFLUXDB_WRITE_USER=${INFLUXDB_WRITE_USER} - - INFLUXDB_WRITE_USER_PASSWORD=${INFLUXDB_WRITE_USER_PASSWORD} - healthcheck: - test: [ "CMD", "curl", "-f", "http://omotes_influxdb:${INFLUXDB_PORT}/ping" ] - interval: 10s - timeout: 5s - volumes: - - influxdb_storage:/var/lib/influxdb - - grow_worker: - build: - context: . - env_file: .env - networks: - - omotes - deploy: - replicas: 1 - depends_on: - rabbitmq: - condition: service_healthy - omotes_influxdb: - condition: service_healthy - - local_test: - build: - context: ./local_test - dockerfile: Dockerfile - networks: - - omotes - depends_on: - grow_worker: - condition: service_started diff --git a/justfile b/justfile new file mode 100644 index 0000000..93ed975 --- /dev/null +++ b/justfile @@ -0,0 +1,32 @@ +# CI tasks + +# Install dependencies with dev group +install: + uv sync --locked --group dev + +# Run linter checks +lint: + uv run ruff check ./src ./tests + +# Fix linting issues +format: + uv run ruff format ./src ./tests + +# Check formatting without modifying files +format-check: + uv run ruff format --check ./src ./tests + +# Run type checker +typecheck: + uv run ty check ./src ./tests + +# Run tests +test: + uv run pytest --junit-xml=test-results.xml tests/ + +# Run all checks (install, lint, format-check, typecheck, test) +ci: install lint format-check typecheck test + +# Show this help message +help: + @just --list diff --git a/local_test/Delft_T feedback.esdl b/local_test/Delft_T feedback.esdl new file mode 100644 index 0000000..e6620b4 --- /dev/null +++ b/local_test/Delft_T feedback.esdl @@ -0,0 +1,697 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/local_test/Delft_T.esdl b/local_test/Delft_T.esdl new file mode 100644 index 0000000..4fdeb81 --- /dev/null +++ b/local_test/Delft_T.esdl @@ -0,0 +1,697 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/local_test/Dockerfile b/local_test/Dockerfile deleted file mode 100644 index a635c18..0000000 --- a/local_test/Dockerfile +++ /dev/null @@ -1,11 +0,0 @@ -FROM python:3.10 - -WORKDIR /app - -COPY ./requirements.txt . - -RUN pip install -r requirements.txt - -COPY . . - -ENTRYPOINT python -u test_app.py diff --git a/local_test/requirements.txt b/local_test/requirements.txt deleted file mode 100644 index 0d07dbf..0000000 --- a/local_test/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -celery==5.3.5 -jsonpickle==3.0.2 diff --git a/local_test/run_optimizer_flow_function.py b/local_test/run_optimizer_flow_function.py new file mode 100644 index 0000000..556a7d7 --- /dev/null +++ b/local_test/run_optimizer_flow_function.py @@ -0,0 +1,21 @@ +from omotes_optimizer_worker.prefect_flow import optimizer_flow + +input_esdl_file = "./local_test/Delft_T.esdl" +# input_esdl_file = "./local_test/Delft_T feedback.esdl" + +workflow_type_name = "grow_optimizer_no_heat_losses" + +with open(input_esdl_file) as open_file: + input_esdl = open_file.read() + +optimizer_flow_result = optimizer_flow.fn( + input_esdl=input_esdl, + workflow_config={}, + workflow_type_name=workflow_type_name, +) +print("--------------ESDL messages:") +print(optimizer_flow_result.esdl_messages) +print("--------------Result") +print(f"Job is done (type: {workflow_type_name}). Output esdl length: {len(optimizer_flow_result.output_esdl)}, ") + +# print("Output ESDL:", optimizer_flow_result.output_esdl) diff --git a/local_test/test_app.py b/local_test/test_app.py deleted file mode 100644 index 9656809..0000000 --- a/local_test/test_app.py +++ /dev/null @@ -1,85 +0,0 @@ -import sys -import threading -from uuid import uuid4 -import jsonpickle -from celery import Celery - -input_esdl_no_influx = "PD94bWwgdmVyc2lvbj0nMS4wJyBlbmNvZGluZz0nVVRGLTgnPz4KPGVzZGw6RW5lcmd5U3lzdGVtIHhtbG5zOnhzaT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEtaW5zdGFuY2UiIHhtbG5zOmVzZGw9Imh0dHA6Ly93d3cudG5vLm5sL2VzZGwiIG5hbWU9IlVudGl0bGVkIEVuZXJneVN5c3RlbSB3aXRoIHJldHVybiBuZXR3b3JrIiBpZD0iN2FjMDkyMzEtY2U2MC00YzI0LTgzMzgtOWMwMzE3Njk1YmE0X3dpdGhfcmV0dXJuX25ldHdvcmsiIGRlc2NyaXB0aW9uPSIiIGVzZGxWZXJzaW9uPSJ2MjIxMCIgdmVyc2lvbj0iMTQiPgogIDxlbmVyZ3lTeXN0ZW1JbmZvcm1hdGlvbiB4c2k6dHlwZT0iZXNkbDpFbmVyZ3lTeXN0ZW1JbmZvcm1hdGlvbiIgaWQ9ImU2NDczN2Q5LWQ3NzItNDcyMy1iMDkyLWEwYjM5N2FjMDBiMyI+CiAgICA8Y2FycmllcnMgeHNpOnR5cGU9ImVzZGw6Q2FycmllcnMiIGlkPSI5ZGZmMTNiOS03N2NkLTRiOTktODc3Ny02Yjc2ODBhMTU1YjYiPgogICAgICA8Y2FycmllciB4c2k6dHlwZT0iZXNkbDpIZWF0Q29tbW9kaXR5IiBpZD0iN2IzMmUyODctZDc3NS00ODBjLWIzMTctNjRmZmRhY2YxMmM5IiBuYW1lPSJIZWF0IiBzdXBwbHlUZW1wZXJhdHVyZT0iNzAuMCIvPgogICAgICA8Y2FycmllciB4c2k6dHlwZT0iZXNkbDpIZWF0Q29tbW9kaXR5IiByZXR1cm5UZW1wZXJhdHVyZT0iNDAuMCIgaWQ9IjdiMzJlMjg3LWQ3NzUtNDgwYy1iMzE3LTY0ZmZkYWNmMTJjOV9yZXQiIG5hbWU9IkhlYXRfcmV0Ii8+CiAgICA8L2NhcnJpZXJzPgogIDwvZW5lcmd5U3lzdGVtSW5mb3JtYXRpb24+CiAgPGluc3RhbmNlIHhzaTp0eXBlPSJlc2RsOkluc3RhbmNlIiBpZD0iZjg1MmI5NDEtOTlmZS00ODdiLWEyMGQtMDFiZWZmOWU3YzQzIiBuYW1lPSJVbnRpdGxlZCBJbnN0YW5jZSI+CiAgICA8YXJlYSB4c2k6dHlwZT0iZXNkbDpBcmVhIiBpZD0iZjRhY2M3ZWYtYTM3ZC00M2I3LTg3Y2ItOGFmNWI4MmUzZmVkIiBuYW1lPSJVbnRpdGxlZCBBcmVhIj4KICAgICAgPGFzc2V0IHhzaTp0eXBlPSJlc2RsOkhlYXRpbmdEZW1hbmQiIG5hbWU9IkhlYXRpbmdEZW1hbmRfMSIgaWQ9ImMyZDc3YWJjLTE2NTYtNDcyMi04NTA4LTdjNjQ1NzRlMDRlZiIgcG93ZXI9IjEwMDAwMDAwLjAiPgogICAgICAgIDxnZW9tZXRyeSB4c2k6dHlwZT0iZXNkbDpQb2ludCIgQ1JTPSJXR1M4NCIgbGF0PSI1Mi4wNDE5ODU4ODk0NDE0NiIgbG9uPSI0LjMwODg3MjIyMjkwMDM5MTUiLz4KICAgICAgICA8cG9ydCB4c2k6dHlwZT0iZXNkbDpJblBvcnQiIGNvbm5lY3RlZFRvPSIxZGZkYzE3Mi05MzU5LTQzNWEtODE1My0wYTY1NzkzMjIyM2EiIGlkPSIyYTg3MzE5NS1mYTZiLTQyNTAtODUxOS0wNDZmMDQwZmVkYjciIGNhcnJpZXI9IjdiMzJlMjg3LWQ3NzUtNDgwYy1iMzE3LTY0ZmZkYWNmMTJjOSIgbmFtZT0iSW4iLz4KICAgICAgICA8cG9ydCB4c2k6dHlwZT0iZXNkbDpPdXRQb3J0IiBpZD0iZWY3NGVhOGMtODliNC00MmUwLWE5OGMtNDExODYwODc2YzFhIiBjb25uZWN0ZWRUbz0iMThjZTY5MDYtNTk1Yy00NWU0LWFjZjAtZTA3ZjdkNzY0OGM2IiBjYXJyaWVyPSI3YjMyZTI4Ny1kNzc1LTQ4MGMtYjMxNy02NGZmZGFjZjEyYzlfcmV0IiBuYW1lPSJPdXQiLz4KICAgICAgICA8Y29zdEluZm9ybWF0aW9uIHhzaTp0eXBlPSJlc2RsOkNvc3RJbmZvcm1hdGlvbiIgaWQ9ImQ4YTY3MjQzLTRlNGUtNDNmOC05ODAxLWZkNDU3OWMwZWRkZiI+CiAgICAgICAgICA8aW5zdGFsbGF0aW9uQ29zdHMgeHNpOnR5cGU9ImVzZGw6U2luZ2xlVmFsdWUiIHZhbHVlPSIxMDAwMDAwLjAiIGlkPSJhY2NkODRiYy1kM2VkLTQ1MjgtYTFmZi1mOTA2YzQ4OTkxYTEiPgogICAgICAgICAgICA8cHJvZmlsZVF1YW50aXR5QW5kVW5pdCB4c2k6dHlwZT0iZXNkbDpRdWFudGl0eUFuZFVuaXRUeXBlIiB1bml0PSJFVVJPIiBwaHlzaWNhbFF1YW50aXR5PSJDT1NUIiBpZD0iYWU4YjgxZmItODU3Yi00MjgwLTllOTEtOTE5ZGQxYzc2NzVlIiBkZXNjcmlwdGlvbj0iQ29zdCBpbiBFVVIiLz4KICAgICAgICAgIDwvaW5zdGFsbGF0aW9uQ29zdHM+CiAgICAgICAgPC9jb3N0SW5mb3JtYXRpb24+CiAgICAgIDwvYXNzZXQ+CiAgICAgIDxhc3NldCB4c2k6dHlwZT0iZXNkbDpIZWF0aW5nRGVtYW5kIiBuYW1lPSJIZWF0aW5nRGVtYW5kXzIiIGlkPSI5MzUyZDk4NC0wZTIxLTRhZjYtOWM1Zi05MWY5ODRhYmZjZmQiIHBvd2VyPSIxMDAwMDAwMC4wIj4KICAgICAgICA8Z2VvbWV0cnkgeHNpOnR5cGU9ImVzZGw6UG9pbnQiIENSUz0iV0dTODQiIGxhdD0iNTIuMDQwMDI1OTAzNjk1NjgiIGxvbj0iNC4zMTA2MTAyOTQzNDIwNDIiLz4KICAgICAgICA8cG9ydCB4c2k6dHlwZT0iZXNkbDpJblBvcnQiIGNvbm5lY3RlZFRvPSI1M2E1NDQ0OC1hYmRiLTQxYWItYTUzZS00OTg1NTYwNjIyMTYiIGlkPSJhNGE3YzIzZS00ZDc3LTRiYmUtYjhiNC1kZGYyZDJkNmU5N2UiIGNhcnJpZXI9IjdiMzJlMjg3LWQ3NzUtNDgwYy1iMzE3LTY0ZmZkYWNmMTJjOSIgbmFtZT0iSW4iLz4KICAgICAgICA8cG9ydCB4c2k6dHlwZT0iZXNkbDpPdXRQb3J0IiBpZD0iYmY2ZTBiNmItYmFhYy00NjhiLWE5YmEtZjgzOTdiYWJmNWQ2IiBjb25uZWN0ZWRUbz0iZDEyNmY3OWUtYzQzZS00ZDlkLWE3Y2UtOGY1OGJlNjM0Njk1IiBjYXJyaWVyPSI3YjMyZTI4Ny1kNzc1LTQ4MGMtYjMxNy02NGZmZGFjZjEyYzlfcmV0IiBuYW1lPSJPdXQiLz4KICAgICAgICA8Y29zdEluZm9ybWF0aW9uIHhzaTp0eXBlPSJlc2RsOkNvc3RJbmZvcm1hdGlvbiIgaWQ9IjdkOTVkYzU4LTAyYjAtNDljZi1hN2E3LTU2MjNmZmZiNDA3OSI+CiAgICAgICAgICA8aW5zdGFsbGF0aW9uQ29zdHMgeHNpOnR5cGU9ImVzZGw6U2luZ2xlVmFsdWUiIHZhbHVlPSIxMDAwMDAwLjAiIGlkPSJjMzNhZjYyOS02ZmM1LTRkN2MtOWFjNC01YjFlMGRiMjk1YTUiPgogICAgICAgICAgICA8cHJvZmlsZVF1YW50aXR5QW5kVW5pdCB4c2k6dHlwZT0iZXNkbDpRdWFudGl0eUFuZFVuaXRUeXBlIiB1bml0PSJFVVJPIiBwaHlzaWNhbFF1YW50aXR5PSJDT1NUIiBpZD0iODkzMDE4MjYtYWNmMy00ZmVjLWIwM2MtN2RiMjc3ZGUwMDRhIiBkZXNjcmlwdGlvbj0iQ29zdCBpbiBFVVIiLz4KICAgICAgICAgIDwvaW5zdGFsbGF0aW9uQ29zdHM+CiAgICAgICAgPC9jb3N0SW5mb3JtYXRpb24+CiAgICAgIDwvYXNzZXQ+CiAgICAgIDxhc3NldCB4c2k6dHlwZT0iZXNkbDpIZWF0aW5nRGVtYW5kIiBuYW1lPSJIZWF0aW5nRGVtYW5kXzMiIGlkPSJlMjk1YTE1NS0zZmFiLTRhYjEtOTI1ZC03YmRiNTAwOTRmNDgiIHBvd2VyPSIxMDAwMDAwMC4wIj4KICAgICAgICA8Z2VvbWV0cnkgeHNpOnR5cGU9ImVzZGw6UG9pbnQiIGxhdD0iNTIuMDM3OTY4NDg2MTM3NjEiIGxvbj0iNC4zMTI2NDYwOTA5ODQzNDUiLz4KICAgICAgICA8cG9ydCB4c2k6dHlwZT0iZXNkbDpJblBvcnQiIGNvbm5lY3RlZFRvPSIxNmIxMzM3Yy01OTcwLTRlYjQtOTBkMy1lNTJkNTE0YTEzZGYiIGlkPSI3NzAwMjJlNi0zZTcxLTRlNTEtODU0NC0wZGJhODZjNDZhNWIiIGNhcnJpZXI9IjdiMzJlMjg3LWQ3NzUtNDgwYy1iMzE3LTY0ZmZkYWNmMTJjOSIgbmFtZT0iSW4iLz4KICAgICAgICA8cG9ydCB4c2k6dHlwZT0iZXNkbDpPdXRQb3J0IiBpZD0iOWMwMjViMTktNTdkMS00M2E4LWIyZTgtZGIzZTY4NDc1NmYyIiBjb25uZWN0ZWRUbz0iNWNkMGYyZTAtZDQ1Ni00OTA5LWE4MWMtNGIzMTJiMWJlODU3IiBjYXJyaWVyPSI3YjMyZTI4Ny1kNzc1LTQ4MGMtYjMxNy02NGZmZGFjZjEyYzlfcmV0IiBuYW1lPSJPdXQiLz4KICAgICAgICA8Y29zdEluZm9ybWF0aW9uIHhzaTp0eXBlPSJlc2RsOkNvc3RJbmZvcm1hdGlvbiIgaWQ9IjNkMDdiMTcxLWY2NWItNDEzZC05MDkwLTJkMWNkNTc4YTQ4OCI+CiAgICAgICAgICA8aW5zdGFsbGF0aW9uQ29zdHMgeHNpOnR5cGU9ImVzZGw6U2luZ2xlVmFsdWUiIHZhbHVlPSIxMDAwMDAwLjAiIGlkPSJhZTFkNmNkOC0yOTkwLTRhNzctYTc0Yy02NWViOWM5M2IwODQiPgogICAgICAgICAgICA8cHJvZmlsZVF1YW50aXR5QW5kVW5pdCB4c2k6dHlwZT0iZXNkbDpRdWFudGl0eUFuZFVuaXRUeXBlIiB1bml0PSJFVVJPIiBwaHlzaWNhbFF1YW50aXR5PSJDT1NUIiBpZD0iN2ZlYjI4Y2EtYmZiOC00YzBkLWIxYjUtYWIxYjM5N2UzOTRjIiBkZXNjcmlwdGlvbj0iQ29zdCBpbiBFVVIiLz4KICAgICAgICAgIDwvaW5zdGFsbGF0aW9uQ29zdHM+CiAgICAgICAgPC9jb3N0SW5mb3JtYXRpb24+CiAgICAgIDwvYXNzZXQ+CiAgICAgIDxhc3NldCB4c2k6dHlwZT0iZXNkbDpQaXBlIiByZWxhdGVkPSJQaXBlMV9yZXQiIGRpYW1ldGVyPSJETjQ1MCIgbmFtZT0iUGlwZTEiIGxlbmd0aD0iMjQ1LjciIGlubmVyRGlhbWV0ZXI9IjAuNDQ0NCIgaWQ9IlBpcGUxIiBvdXRlckRpYW1ldGVyPSIwLjYzIj4KICAgICAgICA8Z2VvbWV0cnkgeHNpOnR5cGU9ImVzZGw6TGluZSIgQ1JTPSJXR1M4NCI+CiAgICAgICAgICA8cG9pbnQgeHNpOnR5cGU9ImVzZGw6UG9pbnQiIGxhdD0iNTIuMDQ0Njk4MDUxMTkyMTQiIGxvbj0iNC4zMTAwNTIzOTQ4NjY5NDQiLz4KICAgICAgICAgIDxwb2ludCB4c2k6dHlwZT0iZXNkbDpQb2ludCIgbGF0PSI1Mi4wNDI3NDE0ODM4ODg0OSIgbG9uPSI0LjMxMTcyMDcyODg3NDIwNyIvPgogICAgICAgIDwvZ2VvbWV0cnk+CiAgICAgICAgPHBvcnQgeHNpOnR5cGU9ImVzZGw6SW5Qb3J0IiBjb25uZWN0ZWRUbz0iNDViZmM3ZDAtZWY1OS00ZjQ5LWIzN2EtODY3YjE4ZTA0Yjg2IiBpZD0iYjQ2MmQ1NjQtYThjMC00YWUwLWE0YWYtMzY5NThmMjQ1NWVhIiBjYXJyaWVyPSI3YjMyZTI4Ny1kNzc1LTQ4MGMtYjMxNy02NGZmZGFjZjEyYzkiIG5hbWU9IkluIi8+CiAgICAgICAgPHBvcnQgeHNpOnR5cGU9ImVzZGw6T3V0UG9ydCIgaWQ9IjY2NTkwZjk2LWEzOTctNGQ2Zi05Y2ZiLWU3ZDM0MjMyY2FkNiIgY29ubmVjdGVkVG89IjUxODUyODYxLWFlZWItNDYxZi1iOGVjLTA4ZjAwMGFiYzZkZCIgY2Fycmllcj0iN2IzMmUyODctZDc3NS00ODBjLWIzMTctNjRmZmRhY2YxMmM5IiBuYW1lPSJPdXQiLz4KICAgICAgICA8bWF0ZXJpYWwgeHNpOnR5cGU9ImVzZGw6Q29tcG91bmRNYXR0ZXIiIGNvbXBvdW5kVHlwZT0iTEFZRVJFRCI+CiAgICAgICAgICA8Y29tcG9uZW50IHhzaTp0eXBlPSJlc2RsOkNvbXBvdW5kTWF0dGVyQ29tcG9uZW50IiBsYXllcldpZHRoPSIwLjAwNjMiPgogICAgICAgICAgICA8bWF0dGVyIHhzaTp0eXBlPSJlc2RsOk1hdGVyaWFsIiB0aGVybWFsQ29uZHVjdGl2aXR5PSI1Mi4xNSIgbmFtZT0ic3RlZWwiIGlkPSIzNzFjMWQ3Mi1kZTM1LTQ1NTktOWIwZS00NzE3MmU1ZDFkODMiLz4KICAgICAgICAgIDwvY29tcG9uZW50PgogICAgICAgICAgPGNvbXBvbmVudCB4c2k6dHlwZT0iZXNkbDpDb21wb3VuZE1hdHRlckNvbXBvbmVudCIgbGF5ZXJXaWR0aD0iMC4wODA1Ij4KICAgICAgICAgICAgPG1hdHRlciB4c2k6dHlwZT0iZXNkbDpNYXRlcmlhbCIgdGhlcm1hbENvbmR1Y3Rpdml0eT0iMC4wMjciIG5hbWU9IlBVUiIgaWQ9ImRmMzBiZDM3LTJmYzQtNDk5My04MjhmLTFiN2NmMWU4MjAyYyIvPgogICAgICAgICAgPC9jb21wb25lbnQ+CiAgICAgICAgICA8Y29tcG9uZW50IHhzaTp0eXBlPSJlc2RsOkNvbXBvdW5kTWF0dGVyQ29tcG9uZW50IiBsYXllcldpZHRoPSIwLjAwNiI+CiAgICAgICAgICAgIDxtYXR0ZXIgeHNpOnR5cGU9ImVzZGw6TWF0ZXJpYWwiIHRoZXJtYWxDb25kdWN0aXZpdHk9IjAuNCIgbmFtZT0iSERQRSIgaWQ9ImY1M2RlMzdiLWE3MzUtNGIwZC1iMjI2LWE2YjcyMjAyOWEwMSIvPgogICAgICAgICAgPC9jb21wb25lbnQ+CiAgICAgICAgPC9tYXRlcmlhbD4KICAgICAgICA8ZGF0YVNvdXJjZSB4c2k6dHlwZT0iZXNkbDpEYXRhU291cmNlIiBhdHRyaWJ1dGlvbj0iaHR0cHM6Ly93d3cubG9nc3Rvci5jb20vbWVkaWEvNjUwNi9wcm9kdWN0LWNhdGFsb2d1ZS11ay0yMDIwMDMucGRmIiBuYW1lPSJMb2dzdG9yIFByb2R1Y3QgQ2F0YWxvZ3VlIFZlcnNpb24gMjAyMC4wMyIvPgogICAgICAgIDxjb3N0SW5mb3JtYXRpb24geHNpOnR5cGU9ImVzZGw6Q29zdEluZm9ybWF0aW9uIiBpZD0iZWMyZDc0MGMtMmYxMy00YjcwLWExYmItNmU0YTU2MTQxNGMyIj4KICAgICAgICAgIDxpbnZlc3RtZW50Q29zdHMgeHNpOnR5cGU9ImVzZGw6U2luZ2xlVmFsdWUiIG5hbWU9IkNvbWJpbmVkIGludmVzdG1lbnQgYW5kIGluc3RhbGxhdGlvbiBjb3N0cyIgaWQ9ImE0MDE2NWU4LTg4YmQtNDliOS04MWQ5LTI5ODgxMmFjMDE3MCIgdmFsdWU9IjM0MTcuOSI+CiAgICAgICAgICAgIDxwcm9maWxlUXVhbnRpdHlBbmRVbml0IHhzaTp0eXBlPSJlc2RsOlF1YW50aXR5QW5kVW5pdFR5cGUiIGlkPSJkMGFlYmM3Ni0yMDFiLTRiMmQtODFmZS01NTI2OWZjZWZlM2IiIGRlc2NyaXB0aW9uPSJDb3N0cyBpbiBFVVIvbSIgcGVyVW5pdD0iTUVUUkUiIHBoeXNpY2FsUXVhbnRpdHk9IkNPU1QiIHVuaXQ9IkVVUk8iLz4KICAgICAgICAgIDwvaW52ZXN0bWVudENvc3RzPgogICAgICAgIDwvY29zdEluZm9ybWF0aW9uPgogICAgICA8L2Fzc2V0PgogICAgICA8YXNzZXQgeHNpOnR5cGU9ImVzZGw6UGlwZSIgcmVsYXRlZD0iUGlwZTJfcmV0IiBkaWFtZXRlcj0iRE40NTAiIG5hbWU9IlBpcGUyIiBsZW5ndGg9IjE5NS40IiBpbm5lckRpYW1ldGVyPSIwLjQ0NDQiIGlkPSJQaXBlMiIgb3V0ZXJEaWFtZXRlcj0iMC42MyI+CiAgICAgICAgPGdlb21ldHJ5IHhzaTp0eXBlPSJlc2RsOkxpbmUiIENSUz0iV0dTODQiPgogICAgICAgICAgPHBvaW50IHhzaTp0eXBlPSJlc2RsOlBvaW50IiBsYXQ9IjUyLjA0MjcxMTc4ODI3ODAxIiBsb249IjQuMzExNjI5NTMzNzY3NzAxIi8+CiAgICAgICAgICA8cG9pbnQgeHNpOnR5cGU9ImVzZGw6UG9pbnQiIGxhdD0iNTIuMDQyMDIyMTg0NjYzMjYiIGxvbj0iNC4zMDkwMDA5Njg5MzMxMDYiLz4KICAgICAgICA8L2dlb21ldHJ5PgogICAgICAgIDxwb3J0IHhzaTp0eXBlPSJlc2RsOkluUG9ydCIgY29ubmVjdGVkVG89ImMwZWFjNGRiLWY1ZGEtNDdmMy04MjAyLTg0MzhkMDAwYmQzMiIgaWQ9IjVmNjU1MjBkLTYxZWUtNGY2OC04MDAyLTI3MWY0OGYxZGFlZSIgY2Fycmllcj0iN2IzMmUyODctZDc3NS00ODBjLWIzMTctNjRmZmRhY2YxMmM5IiBuYW1lPSJJbiIvPgogICAgICAgIDxwb3J0IHhzaTp0eXBlPSJlc2RsOk91dFBvcnQiIGlkPSIxZGZkYzE3Mi05MzU5LTQzNWEtODE1My0wYTY1NzkzMjIyM2EiIGNvbm5lY3RlZFRvPSIyYTg3MzE5NS1mYTZiLTQyNTAtODUxOS0wNDZmMDQwZmVkYjciIGNhcnJpZXI9IjdiMzJlMjg3LWQ3NzUtNDgwYy1iMzE3LTY0ZmZkYWNmMTJjOSIgbmFtZT0iT3V0Ii8+CiAgICAgICAgPG1hdGVyaWFsIHhzaTp0eXBlPSJlc2RsOkNvbXBvdW5kTWF0dGVyIiBjb21wb3VuZFR5cGU9IkxBWUVSRUQiPgogICAgICAgICAgPGNvbXBvbmVudCB4c2k6dHlwZT0iZXNkbDpDb21wb3VuZE1hdHRlckNvbXBvbmVudCIgbGF5ZXJXaWR0aD0iMC4wMDYzIj4KICAgICAgICAgICAgPG1hdHRlciB4c2k6dHlwZT0iZXNkbDpNYXRlcmlhbCIgdGhlcm1hbENvbmR1Y3Rpdml0eT0iNTIuMTUiIG5hbWU9InN0ZWVsIiBpZD0iMzcxYzFkNzItZGUzNS00NTU5LTliMGUtNDcxNzJlNWQxZDgzIi8+CiAgICAgICAgICA8L2NvbXBvbmVudD4KICAgICAgICAgIDxjb21wb25lbnQgeHNpOnR5cGU9ImVzZGw6Q29tcG91bmRNYXR0ZXJDb21wb25lbnQiIGxheWVyV2lkdGg9IjAuMDgwNSI+CiAgICAgICAgICAgIDxtYXR0ZXIgeHNpOnR5cGU9ImVzZGw6TWF0ZXJpYWwiIHRoZXJtYWxDb25kdWN0aXZpdHk9IjAuMDI3IiBuYW1lPSJQVVIiIGlkPSJkZjMwYmQzNy0yZmM0LTQ5OTMtODI4Zi0xYjdjZjFlODIwMmMiLz4KICAgICAgICAgIDwvY29tcG9uZW50PgogICAgICAgICAgPGNvbXBvbmVudCB4c2k6dHlwZT0iZXNkbDpDb21wb3VuZE1hdHRlckNvbXBvbmVudCIgbGF5ZXJXaWR0aD0iMC4wMDYiPgogICAgICAgICAgICA8bWF0dGVyIHhzaTp0eXBlPSJlc2RsOk1hdGVyaWFsIiB0aGVybWFsQ29uZHVjdGl2aXR5PSIwLjQiIG5hbWU9IkhEUEUiIGlkPSJmNTNkZTM3Yi1hNzM1LTRiMGQtYjIyNi1hNmI3MjIwMjlhMDEiLz4KICAgICAgICAgIDwvY29tcG9uZW50PgogICAgICAgIDwvbWF0ZXJpYWw+CiAgICAgICAgPGRhdGFTb3VyY2UgeHNpOnR5cGU9ImVzZGw6RGF0YVNvdXJjZSIgYXR0cmlidXRpb249Imh0dHBzOi8vd3d3LmxvZ3N0b3IuY29tL21lZGlhLzY1MDYvcHJvZHVjdC1jYXRhbG9ndWUtdWstMjAyMDAzLnBkZiIgbmFtZT0iTG9nc3RvciBQcm9kdWN0IENhdGFsb2d1ZSBWZXJzaW9uIDIwMjAuMDMiLz4KICAgICAgICA8Y29zdEluZm9ybWF0aW9uIHhzaTp0eXBlPSJlc2RsOkNvc3RJbmZvcm1hdGlvbiIgaWQ9ImM4MTQwYjNiLTk5ZGMtNGVlMC1iMDM0LTEwNTBiNGZkMTk0NiI+CiAgICAgICAgICA8aW52ZXN0bWVudENvc3RzIHhzaTp0eXBlPSJlc2RsOlNpbmdsZVZhbHVlIiBuYW1lPSJDb21iaW5lZCBpbnZlc3RtZW50IGFuZCBpbnN0YWxsYXRpb24gY29zdHMiIGlkPSJhNDAxNjVlOC04OGJkLTQ5YjktODFkOS0yOTg4MTJhYzAxNzAiIHZhbHVlPSIzNDE3LjkiPgogICAgICAgICAgICA8cHJvZmlsZVF1YW50aXR5QW5kVW5pdCB4c2k6dHlwZT0iZXNkbDpRdWFudGl0eUFuZFVuaXRUeXBlIiBpZD0iZDBhZWJjNzYtMjAxYi00YjJkLTgxZmUtNTUyNjlmY2VmZTNiIiBkZXNjcmlwdGlvbj0iQ29zdHMgaW4gRVVSL20iIHBlclVuaXQ9Ik1FVFJFIiBwaHlzaWNhbFF1YW50aXR5PSJDT1NUIiB1bml0PSJFVVJPIi8+CiAgICAgICAgICA8L2ludmVzdG1lbnRDb3N0cz4KICAgICAgICA8L2Nvc3RJbmZvcm1hdGlvbj4KICAgICAgPC9hc3NldD4KICAgICAgPGFzc2V0IHhzaTp0eXBlPSJlc2RsOlBpcGUiIHJlbGF0ZWQ9IlBpcGUzX3JldCIgZGlhbWV0ZXI9IkRONDUwIiBuYW1lPSJQaXBlMyIgbGVuZ3RoPSIyNDEuNiIgaW5uZXJEaWFtZXRlcj0iMC40NDQ0IiBpZD0iUGlwZTMiIG91dGVyRGlhbWV0ZXI9IjAuNjMiPgogICAgICAgIDxnZW9tZXRyeSB4c2k6dHlwZT0iZXNkbDpMaW5lIiBDUlM9IldHUzg0Ij4KICAgICAgICAgIDxwb2ludCB4c2k6dHlwZT0iZXNkbDpQb2ludCIgbGF0PSI1Mi4wNDI3MDg0ODg3NjQ1MDQiIGxvbj0iNC4zMTE3NTgyNzk4MDA0MTYiLz4KICAgICAgICAgIDxwb2ludCB4c2k6dHlwZT0iZXNkbDpQb2ludCIgbGF0PSI1Mi4wNDA3ODQ4MzA5MzE1NiIgbG9uPSI0LjMxMzM5OTc5MTcxNzUzIi8+CiAgICAgICAgPC9nZW9tZXRyeT4KICAgICAgICA8cG9ydCB4c2k6dHlwZT0iZXNkbDpJblBvcnQiIGNvbm5lY3RlZFRvPSJjMGVhYzRkYi1mNWRhLTQ3ZjMtODIwMi04NDM4ZDAwMGJkMzIiIGlkPSI1NzhlYzQxNC0zZjExLTQzMGUtYTg5My02MGVhNzc4NDhmZjUiIGNhcnJpZXI9IjdiMzJlMjg3LWQ3NzUtNDgwYy1iMzE3LTY0ZmZkYWNmMTJjOSIgbmFtZT0iSW4iLz4KICAgICAgICA8cG9ydCB4c2k6dHlwZT0iZXNkbDpPdXRQb3J0IiBpZD0iZGMxYmM5NGYtMjZmMi00YTQ5LWEzYmYtZDA2MTRiMWYwZGYyIiBjb25uZWN0ZWRUbz0iZTBhZGY4MGEtYjZmMy00YzEyLWE0MzktZGFiNGU1NTUyMDJhIiBjYXJyaWVyPSI3YjMyZTI4Ny1kNzc1LTQ4MGMtYjMxNy02NGZmZGFjZjEyYzkiIG5hbWU9Ik91dCIvPgogICAgICAgIDxtYXRlcmlhbCB4c2k6dHlwZT0iZXNkbDpDb21wb3VuZE1hdHRlciIgY29tcG91bmRUeXBlPSJMQVlFUkVEIj4KICAgICAgICAgIDxjb21wb25lbnQgeHNpOnR5cGU9ImVzZGw6Q29tcG91bmRNYXR0ZXJDb21wb25lbnQiIGxheWVyV2lkdGg9IjAuMDA2MyI+CiAgICAgICAgICAgIDxtYXR0ZXIgeHNpOnR5cGU9ImVzZGw6TWF0ZXJpYWwiIHRoZXJtYWxDb25kdWN0aXZpdHk9IjUyLjE1IiBuYW1lPSJzdGVlbCIgaWQ9IjM3MWMxZDcyLWRlMzUtNDU1OS05YjBlLTQ3MTcyZTVkMWQ4MyIvPgogICAgICAgICAgPC9jb21wb25lbnQ+CiAgICAgICAgICA8Y29tcG9uZW50IHhzaTp0eXBlPSJlc2RsOkNvbXBvdW5kTWF0dGVyQ29tcG9uZW50IiBsYXllcldpZHRoPSIwLjA4MDUiPgogICAgICAgICAgICA8bWF0dGVyIHhzaTp0eXBlPSJlc2RsOk1hdGVyaWFsIiB0aGVybWFsQ29uZHVjdGl2aXR5PSIwLjAyNyIgbmFtZT0iUFVSIiBpZD0iZGYzMGJkMzctMmZjNC00OTkzLTgyOGYtMWI3Y2YxZTgyMDJjIi8+CiAgICAgICAgICA8L2NvbXBvbmVudD4KICAgICAgICAgIDxjb21wb25lbnQgeHNpOnR5cGU9ImVzZGw6Q29tcG91bmRNYXR0ZXJDb21wb25lbnQiIGxheWVyV2lkdGg9IjAuMDA2Ij4KICAgICAgICAgICAgPG1hdHRlciB4c2k6dHlwZT0iZXNkbDpNYXRlcmlhbCIgdGhlcm1hbENvbmR1Y3Rpdml0eT0iMC40IiBuYW1lPSJIRFBFIiBpZD0iZjUzZGUzN2ItYTczNS00YjBkLWIyMjYtYTZiNzIyMDI5YTAxIi8+CiAgICAgICAgICA8L2NvbXBvbmVudD4KICAgICAgICA8L21hdGVyaWFsPgogICAgICAgIDxkYXRhU291cmNlIHhzaTp0eXBlPSJlc2RsOkRhdGFTb3VyY2UiIGF0dHJpYnV0aW9uPSJodHRwczovL3d3dy5sb2dzdG9yLmNvbS9tZWRpYS82NTA2L3Byb2R1Y3QtY2F0YWxvZ3VlLXVrLTIwMjAwMy5wZGYiIG5hbWU9IkxvZ3N0b3IgUHJvZHVjdCBDYXRhbG9ndWUgVmVyc2lvbiAyMDIwLjAzIi8+CiAgICAgICAgPGNvc3RJbmZvcm1hdGlvbiB4c2k6dHlwZT0iZXNkbDpDb3N0SW5mb3JtYXRpb24iIGlkPSI4ODNhZmMxMy0wOThlLTQ3YjQtYWEzMC1hZTNjM2UyNWY5YjEiPgogICAgICAgICAgPGludmVzdG1lbnRDb3N0cyB4c2k6dHlwZT0iZXNkbDpTaW5nbGVWYWx1ZSIgbmFtZT0iQ29tYmluZWQgaW52ZXN0bWVudCBhbmQgaW5zdGFsbGF0aW9uIGNvc3RzIiBpZD0iYTQwMTY1ZTgtODhiZC00OWI5LTgxZDktMjk4ODEyYWMwMTcwIiB2YWx1ZT0iMzQxNy45Ij4KICAgICAgICAgICAgPHByb2ZpbGVRdWFudGl0eUFuZFVuaXQgeHNpOnR5cGU9ImVzZGw6UXVhbnRpdHlBbmRVbml0VHlwZSIgaWQ9ImQwYWViYzc2LTIwMWItNGIyZC04MWZlLTU1MjY5ZmNlZmUzYiIgZGVzY3JpcHRpb249IkNvc3RzIGluIEVVUi9tIiBwZXJVbml0PSJNRVRSRSIgcGh5c2ljYWxRdWFudGl0eT0iQ09TVCIgdW5pdD0iRVVSTyIvPgogICAgICAgICAgPC9pbnZlc3RtZW50Q29zdHM+CiAgICAgICAgPC9jb3N0SW5mb3JtYXRpb24+CiAgICAgIDwvYXNzZXQ+CiAgICAgIDxhc3NldCB4c2k6dHlwZT0iZXNkbDpQaXBlIiByZWxhdGVkPSJQaXBlNF9yZXQiIGRpYW1ldGVyPSJETjQ1MCIgbmFtZT0iUGlwZTQiIGxlbmd0aD0iMTg5LjciIGlubmVyRGlhbWV0ZXI9IjAuNDQ0NCIgaWQ9IlBpcGU0IiBvdXRlckRpYW1ldGVyPSIwLjYzIj4KICAgICAgICA8Z2VvbWV0cnkgeHNpOnR5cGU9ImVzZGw6TGluZSIgQ1JTPSJXR1M4NCI+CiAgICAgICAgICA8cG9pbnQgeHNpOnR5cGU9ImVzZGw6UG9pbnQiIGxhdD0iNTIuMDQwNzYxNzMzMzM2MjIiIGxvbj0iNC4zMTMzMjQ2ODk4NjUxMTMiLz4KICAgICAgICAgIDxwb2ludCB4c2k6dHlwZT0iZXNkbDpQb2ludCIgbGF0PSI1Mi4wNDAwNzIwOTk2MzQ4NyIgbG9uPSI0LjMxMDc4NzMyMDEzNzAyNSIvPgogICAgICAgIDwvZ2VvbWV0cnk+CiAgICAgICAgPHBvcnQgeHNpOnR5cGU9ImVzZGw6SW5Qb3J0IiBjb25uZWN0ZWRUbz0iZWQ3NWIyMTAtNmI1YS00ODhlLThhOGQtZWZlNTcwYzg0OTkwIiBpZD0iNGI5MmU0MTgtNGNhNi00NzY1LTg1YWItY2UzMGY0MTI3YmYwIiBjYXJyaWVyPSI3YjMyZTI4Ny1kNzc1LTQ4MGMtYjMxNy02NGZmZGFjZjEyYzkiIG5hbWU9IkluIi8+CiAgICAgICAgPHBvcnQgeHNpOnR5cGU9ImVzZGw6T3V0UG9ydCIgaWQ9IjUzYTU0NDQ4LWFiZGItNDFhYi1hNTNlLTQ5ODU1NjA2MjIxNiIgY29ubmVjdGVkVG89ImE0YTdjMjNlLTRkNzctNGJiZS1iOGI0LWRkZjJkMmQ2ZTk3ZSIgY2Fycmllcj0iN2IzMmUyODctZDc3NS00ODBjLWIzMTctNjRmZmRhY2YxMmM5IiBuYW1lPSJPdXQiLz4KICAgICAgICA8bWF0ZXJpYWwgeHNpOnR5cGU9ImVzZGw6Q29tcG91bmRNYXR0ZXIiIGNvbXBvdW5kVHlwZT0iTEFZRVJFRCI+CiAgICAgICAgICA8Y29tcG9uZW50IHhzaTp0eXBlPSJlc2RsOkNvbXBvdW5kTWF0dGVyQ29tcG9uZW50IiBsYXllcldpZHRoPSIwLjAwNjMiPgogICAgICAgICAgICA8bWF0dGVyIHhzaTp0eXBlPSJlc2RsOk1hdGVyaWFsIiB0aGVybWFsQ29uZHVjdGl2aXR5PSI1Mi4xNSIgbmFtZT0ic3RlZWwiIGlkPSIzNzFjMWQ3Mi1kZTM1LTQ1NTktOWIwZS00NzE3MmU1ZDFkODMiLz4KICAgICAgICAgIDwvY29tcG9uZW50PgogICAgICAgICAgPGNvbXBvbmVudCB4c2k6dHlwZT0iZXNkbDpDb21wb3VuZE1hdHRlckNvbXBvbmVudCIgbGF5ZXJXaWR0aD0iMC4wODA1Ij4KICAgICAgICAgICAgPG1hdHRlciB4c2k6dHlwZT0iZXNkbDpNYXRlcmlhbCIgdGhlcm1hbENvbmR1Y3Rpdml0eT0iMC4wMjciIG5hbWU9IlBVUiIgaWQ9ImRmMzBiZDM3LTJmYzQtNDk5My04MjhmLTFiN2NmMWU4MjAyYyIvPgogICAgICAgICAgPC9jb21wb25lbnQ+CiAgICAgICAgICA8Y29tcG9uZW50IHhzaTp0eXBlPSJlc2RsOkNvbXBvdW5kTWF0dGVyQ29tcG9uZW50IiBsYXllcldpZHRoPSIwLjAwNiI+CiAgICAgICAgICAgIDxtYXR0ZXIgeHNpOnR5cGU9ImVzZGw6TWF0ZXJpYWwiIHRoZXJtYWxDb25kdWN0aXZpdHk9IjAuNCIgbmFtZT0iSERQRSIgaWQ9ImY1M2RlMzdiLWE3MzUtNGIwZC1iMjI2LWE2YjcyMjAyOWEwMSIvPgogICAgICAgICAgPC9jb21wb25lbnQ+CiAgICAgICAgPC9tYXRlcmlhbD4KICAgICAgICA8ZGF0YVNvdXJjZSB4c2k6dHlwZT0iZXNkbDpEYXRhU291cmNlIiBhdHRyaWJ1dGlvbj0iaHR0cHM6Ly93d3cubG9nc3Rvci5jb20vbWVkaWEvNjUwNi9wcm9kdWN0LWNhdGFsb2d1ZS11ay0yMDIwMDMucGRmIiBuYW1lPSJMb2dzdG9yIFByb2R1Y3QgQ2F0YWxvZ3VlIFZlcnNpb24gMjAyMC4wMyIvPgogICAgICAgIDxjb3N0SW5mb3JtYXRpb24geHNpOnR5cGU9ImVzZGw6Q29zdEluZm9ybWF0aW9uIiBpZD0iYjFkZDA0MjctZjhjYS00NTI1LTgxOTItOGE4OTU0ZjJiZTFjIj4KICAgICAgICAgIDxpbnZlc3RtZW50Q29zdHMgeHNpOnR5cGU9ImVzZGw6U2luZ2xlVmFsdWUiIG5hbWU9IkNvbWJpbmVkIGludmVzdG1lbnQgYW5kIGluc3RhbGxhdGlvbiBjb3N0cyIgaWQ9ImE0MDE2NWU4LTg4YmQtNDliOS04MWQ5LTI5ODgxMmFjMDE3MCIgdmFsdWU9IjM0MTcuOSI+CiAgICAgICAgICAgIDxwcm9maWxlUXVhbnRpdHlBbmRVbml0IHhzaTp0eXBlPSJlc2RsOlF1YW50aXR5QW5kVW5pdFR5cGUiIGlkPSJkMGFlYmM3Ni0yMDFiLTRiMmQtODFmZS01NTI2OWZjZWZlM2IiIGRlc2NyaXB0aW9uPSJDb3N0cyBpbiBFVVIvbSIgcGVyVW5pdD0iTUVUUkUiIHBoeXNpY2FsUXVhbnRpdHk9IkNPU1QiIHVuaXQ9IkVVUk8iLz4KICAgICAgICAgIDwvaW52ZXN0bWVudENvc3RzPgogICAgICAgIDwvY29zdEluZm9ybWF0aW9uPgogICAgICA8L2Fzc2V0PgogICAgICA8YXNzZXQgeHNpOnR5cGU9ImVzZGw6UGlwZSIgcmVsYXRlZD0iUGlwZTVfcmV0IiBkaWFtZXRlcj0iRE40NTAiIG5hbWU9IlBpcGU1IiBsZW5ndGg9IjI0NC42IiBpbm5lckRpYW1ldGVyPSIwLjQ0NDQiIGlkPSJQaXBlNSIgb3V0ZXJEaWFtZXRlcj0iMC42MyI+CiAgICAgICAgPGdlb21ldHJ5IHhzaTp0eXBlPSJlc2RsOkxpbmUiIENSUz0iV0dTODQiPgogICAgICAgICAgPHBvaW50IHhzaTp0eXBlPSJlc2RsOlBvaW50IiBsYXQ9IjUyLjA0MDczODYzNTcyODk4IiBsb249IjQuMzEzNDUzNDM1ODk3ODI4Ii8+CiAgICAgICAgICA8cG9pbnQgeHNpOnR5cGU9ImVzZGw6UG9pbnQiIGxhdD0iNTIuMDM4Nzk4Mzk0MTA5MzgiIGxvbj0iNC4zMTUxMzc4NjMxNTkxODEiLz4KICAgICAgICA8L2dlb21ldHJ5PgogICAgICAgIDxwb3J0IHhzaTp0eXBlPSJlc2RsOkluUG9ydCIgY29ubmVjdGVkVG89ImVkNzViMjEwLTZiNWEtNDg4ZS04YThkLWVmZTU3MGM4NDk5MCIgaWQ9ImQxY2UxN2ZlLTU3MmQtNGFkZS1hNmUxLWEzZDNhYTBmYWI2NCIgY2Fycmllcj0iN2IzMmUyODctZDc3NS00ODBjLWIzMTctNjRmZmRhY2YxMmM5IiBuYW1lPSJJbiIvPgogICAgICAgIDxwb3J0IHhzaTp0eXBlPSJlc2RsOk91dFBvcnQiIGlkPSI4ZjFiZWE1Mi1lMzIyLTRkMzQtYWQ0My03ZDFlOTcyNDNkNjIiIGNvbm5lY3RlZFRvPSIxY2I5MjNiNS0yYTY5LTQ2ZDktODc0Yy02OGQ1NTJlZjU1NzYiIGNhcnJpZXI9IjdiMzJlMjg3LWQ3NzUtNDgwYy1iMzE3LTY0ZmZkYWNmMTJjOSIgbmFtZT0iT3V0Ii8+CiAgICAgICAgPG1hdGVyaWFsIHhzaTp0eXBlPSJlc2RsOkNvbXBvdW5kTWF0dGVyIiBjb21wb3VuZFR5cGU9IkxBWUVSRUQiPgogICAgICAgICAgPGNvbXBvbmVudCB4c2k6dHlwZT0iZXNkbDpDb21wb3VuZE1hdHRlckNvbXBvbmVudCIgbGF5ZXJXaWR0aD0iMC4wMDYzIj4KICAgICAgICAgICAgPG1hdHRlciB4c2k6dHlwZT0iZXNkbDpNYXRlcmlhbCIgdGhlcm1hbENvbmR1Y3Rpdml0eT0iNTIuMTUiIG5hbWU9InN0ZWVsIiBpZD0iMzcxYzFkNzItZGUzNS00NTU5LTliMGUtNDcxNzJlNWQxZDgzIi8+CiAgICAgICAgICA8L2NvbXBvbmVudD4KICAgICAgICAgIDxjb21wb25lbnQgeHNpOnR5cGU9ImVzZGw6Q29tcG91bmRNYXR0ZXJDb21wb25lbnQiIGxheWVyV2lkdGg9IjAuMDgwNSI+CiAgICAgICAgICAgIDxtYXR0ZXIgeHNpOnR5cGU9ImVzZGw6TWF0ZXJpYWwiIHRoZXJtYWxDb25kdWN0aXZpdHk9IjAuMDI3IiBuYW1lPSJQVVIiIGlkPSJkZjMwYmQzNy0yZmM0LTQ5OTMtODI4Zi0xYjdjZjFlODIwMmMiLz4KICAgICAgICAgIDwvY29tcG9uZW50PgogICAgICAgICAgPGNvbXBvbmVudCB4c2k6dHlwZT0iZXNkbDpDb21wb3VuZE1hdHRlckNvbXBvbmVudCIgbGF5ZXJXaWR0aD0iMC4wMDYiPgogICAgICAgICAgICA8bWF0dGVyIHhzaTp0eXBlPSJlc2RsOk1hdGVyaWFsIiB0aGVybWFsQ29uZHVjdGl2aXR5PSIwLjQiIG5hbWU9IkhEUEUiIGlkPSJmNTNkZTM3Yi1hNzM1LTRiMGQtYjIyNi1hNmI3MjIwMjlhMDEiLz4KICAgICAgICAgIDwvY29tcG9uZW50PgogICAgICAgIDwvbWF0ZXJpYWw+CiAgICAgICAgPGRhdGFTb3VyY2UgeHNpOnR5cGU9ImVzZGw6RGF0YVNvdXJjZSIgYXR0cmlidXRpb249Imh0dHBzOi8vd3d3LmxvZ3N0b3IuY29tL21lZGlhLzY1MDYvcHJvZHVjdC1jYXRhbG9ndWUtdWstMjAyMDAzLnBkZiIgbmFtZT0iTG9nc3RvciBQcm9kdWN0IENhdGFsb2d1ZSBWZXJzaW9uIDIwMjAuMDMiLz4KICAgICAgICA8Y29zdEluZm9ybWF0aW9uIHhzaTp0eXBlPSJlc2RsOkNvc3RJbmZvcm1hdGlvbiIgaWQ9ImQ5MTMyMzAxLTFmNDktNGMzMS1iMzhmLTRlNjUwYzE4YTk4NCI+CiAgICAgICAgICA8aW52ZXN0bWVudENvc3RzIHhzaTp0eXBlPSJlc2RsOlNpbmdsZVZhbHVlIiBuYW1lPSJDb21iaW5lZCBpbnZlc3RtZW50IGFuZCBpbnN0YWxsYXRpb24gY29zdHMiIGlkPSJhNDAxNjVlOC04OGJkLTQ5YjktODFkOS0yOTg4MTJhYzAxNzAiIHZhbHVlPSIzNDE3LjkiPgogICAgICAgICAgICA8cHJvZmlsZVF1YW50aXR5QW5kVW5pdCB4c2k6dHlwZT0iZXNkbDpRdWFudGl0eUFuZFVuaXRUeXBlIiBpZD0iZDBhZWJjNzYtMjAxYi00YjJkLTgxZmUtNTUyNjlmY2VmZTNiIiBkZXNjcmlwdGlvbj0iQ29zdHMgaW4gRVVSL20iIHBlclVuaXQ9Ik1FVFJFIiBwaHlzaWNhbFF1YW50aXR5PSJDT1NUIiB1bml0PSJFVVJPIi8+CiAgICAgICAgICA8L2ludmVzdG1lbnRDb3N0cz4KICAgICAgICA8L2Nvc3RJbmZvcm1hdGlvbj4KICAgICAgPC9hc3NldD4KICAgICAgPGFzc2V0IHhzaTp0eXBlPSJlc2RsOlBpcGUiIHJlbGF0ZWQ9IlBpcGU2X3JldCIgZGlhbWV0ZXI9IkRONDUwIiBuYW1lPSJQaXBlNiIgbGVuZ3RoPSIxNzYuNiIgaW5uZXJEaWFtZXRlcj0iMC40NDQ0IiBpZD0iUGlwZTYiIG91dGVyRGlhbWV0ZXI9IjAuNjMiPgogICAgICAgIDxnZW9tZXRyeSB4c2k6dHlwZT0iZXNkbDpMaW5lIiBDUlM9IldHUzg0Ij4KICAgICAgICAgIDxwb2ludCB4c2k6dHlwZT0iZXNkbDpQb2ludCIgbGF0PSI1Mi4wMzg3NTIxOTY4NTM4OSIgbG9uPSI0LjMxNTA5NDk0NzgxNDk0MiIvPgogICAgICAgICAgPHBvaW50IHhzaTp0eXBlPSJlc2RsOlBvaW50IiBsYXQ9IjUyLjAzODAxMzAzNDI3MjkyIiBsb249IjQuMzEyODA5NzA1NzM0MjU0Ii8+CiAgICAgICAgPC9nZW9tZXRyeT4KICAgICAgICA8cG9ydCB4c2k6dHlwZT0iZXNkbDpJblBvcnQiIGNvbm5lY3RlZFRvPSJhMDJlNDFhYi05OWY4LTQ2ZDMtYjJkMS1iZTQ0YWE1Yjc5MTQiIGlkPSI3ZjE2MmEzMC03ZTQxLTRkN2YtYjAxMS1mZmNmNGMxNjUxZjgiIGNhcnJpZXI9IjdiMzJlMjg3LWQ3NzUtNDgwYy1iMzE3LTY0ZmZkYWNmMTJjOSIgbmFtZT0iSW4iLz4KICAgICAgICA8cG9ydCB4c2k6dHlwZT0iZXNkbDpPdXRQb3J0IiBpZD0iMTZiMTMzN2MtNTk3MC00ZWI0LTkwZDMtZTUyZDUxNGExM2RmIiBjb25uZWN0ZWRUbz0iNzcwMDIyZTYtM2U3MS00ZTUxLTg1NDQtMGRiYTg2YzQ2YTViIiBjYXJyaWVyPSI3YjMyZTI4Ny1kNzc1LTQ4MGMtYjMxNy02NGZmZGFjZjEyYzkiIG5hbWU9Ik91dCIvPgogICAgICAgIDxtYXRlcmlhbCB4c2k6dHlwZT0iZXNkbDpDb21wb3VuZE1hdHRlciIgY29tcG91bmRUeXBlPSJMQVlFUkVEIj4KICAgICAgICAgIDxjb21wb25lbnQgeHNpOnR5cGU9ImVzZGw6Q29tcG91bmRNYXR0ZXJDb21wb25lbnQiIGxheWVyV2lkdGg9IjAuMDA2MyI+CiAgICAgICAgICAgIDxtYXR0ZXIgeHNpOnR5cGU9ImVzZGw6TWF0ZXJpYWwiIHRoZXJtYWxDb25kdWN0aXZpdHk9IjUyLjE1IiBuYW1lPSJzdGVlbCIgaWQ9IjM3MWMxZDcyLWRlMzUtNDU1OS05YjBlLTQ3MTcyZTVkMWQ4MyIvPgogICAgICAgICAgPC9jb21wb25lbnQ+CiAgICAgICAgICA8Y29tcG9uZW50IHhzaTp0eXBlPSJlc2RsOkNvbXBvdW5kTWF0dGVyQ29tcG9uZW50IiBsYXllcldpZHRoPSIwLjA4MDUiPgogICAgICAgICAgICA8bWF0dGVyIHhzaTp0eXBlPSJlc2RsOk1hdGVyaWFsIiB0aGVybWFsQ29uZHVjdGl2aXR5PSIwLjAyNyIgbmFtZT0iUFVSIiBpZD0iZGYzMGJkMzctMmZjNC00OTkzLTgyOGYtMWI3Y2YxZTgyMDJjIi8+CiAgICAgICAgICA8L2NvbXBvbmVudD4KICAgICAgICAgIDxjb21wb25lbnQgeHNpOnR5cGU9ImVzZGw6Q29tcG91bmRNYXR0ZXJDb21wb25lbnQiIGxheWVyV2lkdGg9IjAuMDA2Ij4KICAgICAgICAgICAgPG1hdHRlciB4c2k6dHlwZT0iZXNkbDpNYXRlcmlhbCIgdGhlcm1hbENvbmR1Y3Rpdml0eT0iMC40IiBuYW1lPSJIRFBFIiBpZD0iZjUzZGUzN2ItYTczNS00YjBkLWIyMjYtYTZiNzIyMDI5YTAxIi8+CiAgICAgICAgICA8L2NvbXBvbmVudD4KICAgICAgICA8L21hdGVyaWFsPgogICAgICAgIDxkYXRhU291cmNlIHhzaTp0eXBlPSJlc2RsOkRhdGFTb3VyY2UiIGF0dHJpYnV0aW9uPSJodHRwczovL3d3dy5sb2dzdG9yLmNvbS9tZWRpYS82NTA2L3Byb2R1Y3QtY2F0YWxvZ3VlLXVrLTIwMjAwMy5wZGYiIG5hbWU9IkxvZ3N0b3IgUHJvZHVjdCBDYXRhbG9ndWUgVmVyc2lvbiAyMDIwLjAzIi8+CiAgICAgICAgPGNvc3RJbmZvcm1hdGlvbiB4c2k6dHlwZT0iZXNkbDpDb3N0SW5mb3JtYXRpb24iIGlkPSI3NjJhZWVjNi1hYzVkLTRlNTQtYjMyZi0zZGE5MjliZDY3MTMiPgogICAgICAgICAgPGludmVzdG1lbnRDb3N0cyB4c2k6dHlwZT0iZXNkbDpTaW5nbGVWYWx1ZSIgbmFtZT0iQ29tYmluZWQgaW52ZXN0bWVudCBhbmQgaW5zdGFsbGF0aW9uIGNvc3RzIiBpZD0iYTQwMTY1ZTgtODhiZC00OWI5LTgxZDktMjk4ODEyYWMwMTcwIiB2YWx1ZT0iMzQxNy45Ij4KICAgICAgICAgICAgPHByb2ZpbGVRdWFudGl0eUFuZFVuaXQgeHNpOnR5cGU9ImVzZGw6UXVhbnRpdHlBbmRVbml0VHlwZSIgaWQ9ImQwYWViYzc2LTIwMWItNGIyZC04MWZlLTU1MjY5ZmNlZmUzYiIgZGVzY3JpcHRpb249IkNvc3RzIGluIEVVUi9tIiBwZXJVbml0PSJNRVRSRSIgcGh5c2ljYWxRdWFudGl0eT0iQ09TVCIgdW5pdD0iRVVSTyIvPgogICAgICAgICAgPC9pbnZlc3RtZW50Q29zdHM+CiAgICAgICAgPC9jb3N0SW5mb3JtYXRpb24+CiAgICAgIDwvYXNzZXQ+CiAgICAgIDxhc3NldCB4c2k6dHlwZT0iZXNkbDpIZWF0UHJvZHVjZXIiIHBvd2VyPSIzMDAwMDAwLjAiIG5hbWU9IkhlYXRQcm9kdWNlcl8xIiBpZD0iMzI0YjAzNzEtYjczOC00ZjU1LWE5NzgtMzMwNmVlODE2MzhjIj4KICAgICAgICA8Z2VvbWV0cnkgeHNpOnR5cGU9ImVzZGw6UG9pbnQiIGxhdD0iNTIuMDQ0NzY0MDM4NDc4MjUiIGxvbj0iNC4zMDk5NzcyOTMwMTQ1MjciLz4KICAgICAgICA8cG9ydCB4c2k6dHlwZT0iZXNkbDpPdXRQb3J0IiBpZD0iNDViZmM3ZDAtZWY1OS00ZjQ5LWIzN2EtODY3YjE4ZTA0Yjg2IiBjb25uZWN0ZWRUbz0iYjQ2MmQ1NjQtYThjMC00YWUwLWE0YWYtMzY5NThmMjQ1NWVhIiBjYXJyaWVyPSI3YjMyZTI4Ny1kNzc1LTQ4MGMtYjMxNy02NGZmZGFjZjEyYzkiIG5hbWU9Ik91dCIvPgogICAgICAgIDxwb3J0IHhzaTp0eXBlPSJlc2RsOkluUG9ydCIgY29ubmVjdGVkVG89ImUzMWUxMmMyLThmODAtNGFlZC05ZTRiLTkxODQ0NWEzMjk5NiIgaWQ9ImJhOWNhMDg0LWI3MWYtNDJhMy04ODRhLWYyZjJiM2FlNDI2NSIgY2Fycmllcj0iN2IzMmUyODctZDc3NS00ODBjLWIzMTctNjRmZmRhY2YxMmM5X3JldCIgbmFtZT0iSW4iLz4KICAgICAgICA8Y29zdEluZm9ybWF0aW9uIHhzaTp0eXBlPSJlc2RsOkNvc3RJbmZvcm1hdGlvbiIgaWQ9IjI4ZTliODUzLWU0MDctNDliMC1iZTY2LTE1NzJjMTJkYzgxMSI+CiAgICAgICAgICA8aW5zdGFsbGF0aW9uQ29zdHMgeHNpOnR5cGU9ImVzZGw6U2luZ2xlVmFsdWUiIHZhbHVlPSIzMDAwMDAuMCIgaWQ9ImNjYmE0M2E1LWM0YzgtNDgxOC1hMzM5LTc2MmIzMzg1ZjU2MiI+CiAgICAgICAgICAgIDxwcm9maWxlUXVhbnRpdHlBbmRVbml0IHhzaTp0eXBlPSJlc2RsOlF1YW50aXR5QW5kVW5pdFR5cGUiIHVuaXQ9IkVVUk8iIHBoeXNpY2FsUXVhbnRpdHk9IkNPU1QiIGlkPSI2OTI0MDMxYy0wNTQ4LTRiMzMtYTM0MS0zZDAzYzVjMmI1YTAiIGRlc2NyaXB0aW9uPSJDb3N0IGluIEVVUiIvPgogICAgICAgICAgPC9pbnN0YWxsYXRpb25Db3N0cz4KICAgICAgICAgIDxpbnZlc3RtZW50Q29zdHMgeHNpOnR5cGU9ImVzZGw6U2luZ2xlVmFsdWUiIHZhbHVlPSI5MDAwMDAuMCIgaWQ9ImI2Yzg1MjU5LTkyMTEtNDE3Zi1iOWRiLTg5ZmI0NzNmMmYxYyI+CiAgICAgICAgICAgIDxwcm9maWxlUXVhbnRpdHlBbmRVbml0IHhzaTp0eXBlPSJlc2RsOlF1YW50aXR5QW5kVW5pdFR5cGUiIGlkPSI0N2ZjYmZmMi1mMGYxLTQ4ZDktYjdjMS03ZTM0YTkwYjE1MzkiIGRlc2NyaXB0aW9uPSJDb3N0IGluIEVVUi9NVyIgcGVyVW5pdD0iV0FUVCIgcGVyTXVsdGlwbGllcj0iTUVHQSIgdW5pdD0iRVVSTyIgcGh5c2ljYWxRdWFudGl0eT0iQ09TVCIvPgogICAgICAgICAgPC9pbnZlc3RtZW50Q29zdHM+CiAgICAgICAgICA8dmFyaWFibGVPcGVyYXRpb25hbEFuZE1haW50ZW5hbmNlQ29zdHMgeHNpOnR5cGU9ImVzZGw6U2luZ2xlVmFsdWUiIHZhbHVlPSIxNS4wIiBpZD0iYjkwYzY1OWYtNGQ4Ny00NDAyLWIwNDItOTBhNzU5NGU3MDE2Ij4KICAgICAgICAgICAgPHByb2ZpbGVRdWFudGl0eUFuZFVuaXQgeHNpOnR5cGU9ImVzZGw6UXVhbnRpdHlBbmRVbml0VHlwZSIgaWQ9IjBkOTQ4NDA2LTc4NjQtNGVmZi1iYzY1LTc2NzA1MzNiZjE4YiIgZGVzY3JpcHRpb249IkNvc3QgaW4gRVVSL01XaCIgcGVyVW5pdD0iV0FUVEhPVVIiIHBlck11bHRpcGxpZXI9Ik1FR0EiIHVuaXQ9IkVVUk8iIHBoeXNpY2FsUXVhbnRpdHk9IkNPU1QiLz4KICAgICAgICAgIDwvdmFyaWFibGVPcGVyYXRpb25hbEFuZE1haW50ZW5hbmNlQ29zdHM+CiAgICAgICAgICA8bWFyZ2luYWxDb3N0cyB4c2k6dHlwZT0iZXNkbDpTaW5nbGVWYWx1ZSIgdmFsdWU9IjIuMCIgaWQ9IjgzNzdjNTE0LTc2YTItNDU5Mi04YzljLWYyZTQyOTgzNzA5OCI+CiAgICAgICAgICAgIDxwcm9maWxlUXVhbnRpdHlBbmRVbml0IHhzaTp0eXBlPSJlc2RsOlF1YW50aXR5QW5kVW5pdFR5cGUiIGlkPSI4OGU3ODM1OC0xMzQ0LTQ1YzItOGJiYy01MWRlMDY2MDAzYjEiIHBoeXNpY2FsUXVhbnRpdHk9IkNPU1QiIGRlc2NyaXB0aW9uPSJDb3N0IGluIEVVUiIgdW5pdD0iRVVSTyIvPgogICAgICAgICAgPC9tYXJnaW5hbENvc3RzPgogICAgICAgIDwvY29zdEluZm9ybWF0aW9uPgogICAgICA8L2Fzc2V0PgogICAgICA8YXNzZXQgeHNpOnR5cGU9ImVzZGw6Sm9pbnQiIG5hbWU9IkpvaW50XzEiIGlkPSJmOTZkMDJkNy0xOWQxLTRhMGItODg2OS0yZDE4MGYzOWI3ZTYiPgogICAgICAgIDxnZW9tZXRyeSB4c2k6dHlwZT0iZXNkbDpQb2ludCIgQ1JTPSJXR1M4NCIgbGF0PSI1Mi4wNDI3MjA4NjE5Mzg4NTQiIGxvbj0iNC4zMTE2OTUyNDc4ODg1NjYiLz4KICAgICAgICA8cG9ydCB4c2k6dHlwZT0iZXNkbDpJblBvcnQiIGNvbm5lY3RlZFRvPSI2NjU5MGY5Ni1hMzk3LTRkNmYtOWNmYi1lN2QzNDIzMmNhZDYgZjk2NmJhZGUtMWZhZC00NTNmLThlYzItNDA2MmVjNzBiYzdiIiBpZD0iNTE4NTI4NjEtYWVlYi00NjFmLWI4ZWMtMDhmMDAwYWJjNmRkIiBjYXJyaWVyPSI3YjMyZTI4Ny1kNzc1LTQ4MGMtYjMxNy02NGZmZGFjZjEyYzkiIG5hbWU9IkluIi8+CiAgICAgICAgPHBvcnQgeHNpOnR5cGU9ImVzZGw6T3V0UG9ydCIgaWQ9ImMwZWFjNGRiLWY1ZGEtNDdmMy04MjAyLTg0MzhkMDAwYmQzMiIgY29ubmVjdGVkVG89IjVmNjU1MjBkLTYxZWUtNGY2OC04MDAyLTI3MWY0OGYxZGFlZSA1NzhlYzQxNC0zZjExLTQzMGUtYTg5My02MGVhNzc4NDhmZjUgMmNjNzczZWUtYjU2Mi00ZTFmLWExZDEtYTI2NTZlMTA5MDdkIiBjYXJyaWVyPSI3YjMyZTI4Ny1kNzc1LTQ4MGMtYjMxNy02NGZmZGFjZjEyYzkiIG5hbWU9Ik91dCIvPgogICAgICA8L2Fzc2V0PgogICAgICA8YXNzZXQgeHNpOnR5cGU9ImVzZGw6Sm9pbnQiIG5hbWU9IkpvaW50XzIiIGlkPSJkNzRkYjliYS1iODZjLTQ4NmEtODkxMS0zZmYzNjhhZTYzYTMiPgogICAgICAgIDxnZW9tZXRyeSB4c2k6dHlwZT0iZXNkbDpQb2ludCIgQ1JTPSJXR1M4NCIgbGF0PSI1Mi4wNDA3NTY3ODM4NDk5NyIgbG9uPSI0LjMxMzM3Mjk2OTYyNzM4MSIvPgogICAgICAgIDxwb3J0IHhzaTp0eXBlPSJlc2RsOkluUG9ydCIgY29ubmVjdGVkVG89ImRjMWJjOTRmLTI2ZjItNGE0OS1hM2JmLWQwNjE0YjFmMGRmMiIgaWQ9ImUwYWRmODBhLWI2ZjMtNGMxMi1hNDM5LWRhYjRlNTU1MjAyYSIgY2Fycmllcj0iN2IzMmUyODctZDc3NS00ODBjLWIzMTctNjRmZmRhY2YxMmM5IiBuYW1lPSJJbiIvPgogICAgICAgIDxwb3J0IHhzaTp0eXBlPSJlc2RsOk91dFBvcnQiIGlkPSJlZDc1YjIxMC02YjVhLTQ4OGUtOGE4ZC1lZmU1NzBjODQ5OTAiIGNvbm5lY3RlZFRvPSI0YjkyZTQxOC00Y2E2LTQ3NjUtODVhYi1jZTMwZjQxMjdiZjAgZDFjZTE3ZmUtNTcyZC00YWRlLWE2ZTEtYTNkM2FhMGZhYjY0IiBjYXJyaWVyPSI3YjMyZTI4Ny1kNzc1LTQ4MGMtYjMxNy02NGZmZGFjZjEyYzkiIG5hbWU9Ik91dCIvPgogICAgICA8L2Fzc2V0PgogICAgICA8YXNzZXQgeHNpOnR5cGU9ImVzZGw6Sm9pbnQiIG5hbWU9IkpvaW50XzMiIGlkPSJkYTJmMTJkYy0wYjc0LTQ3MTktYmM1MC0xOGQ4NDc1MjRkYjMiPgogICAgICAgIDxnZW9tZXRyeSB4c2k6dHlwZT0iZXNkbDpQb2ludCIgQ1JTPSJXR1M4NCIgbGF0PSI1Mi4wMzg3NzAzNDU3ODEzOTQiIGxvbj0iNC4zMTUxMjcxMzQzMjMxMjEiLz4KICAgICAgICA8cG9ydCB4c2k6dHlwZT0iZXNkbDpJblBvcnQiIGNvbm5lY3RlZFRvPSI4ZjFiZWE1Mi1lMzIyLTRkMzQtYWQ0My03ZDFlOTcyNDNkNjIiIGlkPSIxY2I5MjNiNS0yYTY5LTQ2ZDktODc0Yy02OGQ1NTJlZjU1NzYiIGNhcnJpZXI9IjdiMzJlMjg3LWQ3NzUtNDgwYy1iMzE3LTY0ZmZkYWNmMTJjOSIgbmFtZT0iSW4iLz4KICAgICAgICA8cG9ydCB4c2k6dHlwZT0iZXNkbDpPdXRQb3J0IiBpZD0iYTAyZTQxYWItOTlmOC00NmQzLWIyZDEtYmU0NGFhNWI3OTE0IiBjb25uZWN0ZWRUbz0iN2YxNjJhMzAtN2U0MS00ZDdmLWIwMTEtZmZjZjRjMTY1MWY4IiBjYXJyaWVyPSI3YjMyZTI4Ny1kNzc1LTQ4MGMtYjMxNy02NGZmZGFjZjEyYzkiIG5hbWU9Ik91dCIvPgogICAgICA8L2Fzc2V0PgogICAgICA8YXNzZXQgeHNpOnR5cGU9ImVzZGw6QVRFUyIgYXF1aWZlck5ldFRvR3Jvc3M9IjEuMCIgbmFtZT0iQVRFU18wMzNjIiBhcXVpZmVyVGhpY2tuZXNzPSI0NS4wIiBtYXhEaXNjaGFyZ2VSYXRlPSIxMTYxMDAwMC4wIiB3ZWxsQ2FzaW5nU2l6ZT0iMTMuMCIgYXF1aWZlckFuaXNvdHJvcHk9IjQuMCIgYXF1aWZlclBvcm9zaXR5PSIwLjMiIGFxdWlmZXJNaWRUZW1wZXJhdHVyZT0iMTcuMCIgYXF1aWZlclRvcERlcHRoPSIzMDAuMCIgaWQ9IjAzM2MyNTk4LTVjMWEtNDhiNy05M2IxLWM3NDZiODE4MTlmZiIgd2VsbERpc3RhbmNlPSIxNTAuMCIgbWF4Q2hhcmdlUmF0ZT0iMTE2MTAwMDAuMCIgc2FsaW5pdHk9IjEwMDAwLjAiIGFxdWlmZXJQZXJtZWFiaWxpdHk9IjEwMDAwLjAiPgogICAgICAgIDxnZW9tZXRyeSB4c2k6dHlwZT0iZXNkbDpQb2ludCIgbG9uPSI0LjMxNDk0NDc0NDExMDEwOCIgbGF0PSI1Mi4wNDM5MjU5OTI3MDYxOSIvPgogICAgICAgIDxkYXRhU291cmNlIHhzaTp0eXBlPSJlc2RsOkRhdGFTb3VyY2UiIGRlc2NyaXB0aW9uPSJUaGlzIGRhdGEgd2FzIGdlbmVyYXRlZCB1c2luZyB0aGUgJ2tvc3Rlbl9wZXJfYXNzZXQueHNseCcgZmlsZSBpbiB0aGUgJ0tlbnRhbGxlbicgZGlyZWN0b3J5IG9mIFdhcm1pbmdVcCBwcm9qZWN0IDFEIiBhdHRyaWJ1dGlvbj0iIiBuYW1lPSJXYXJtaW5nVXAgZmFjdHNoZWV0OiBIVC1BVEVTIChoaWdoKSIvPgogICAgICAgIDxwb3J0IHhzaTp0eXBlPSJlc2RsOkluUG9ydCIgY29ubmVjdGVkVG89IjAxYzg4MmY3LWVjMTUtNGQzNC05ZjQzLTgxODE5NzJmMjUwMCIgaWQ9IjZiODNlNzRkLTVmZjEtNGZmYS04YmQ0LWRlMTE1NGI1NDFlMiIgY2Fycmllcj0iN2IzMmUyODctZDc3NS00ODBjLWIzMTctNjRmZmRhY2YxMmM5IiBuYW1lPSJJblBvcnQiLz4KICAgICAgICA8cG9ydCB4c2k6dHlwZT0iZXNkbDpPdXRQb3J0IiBpZD0iMTFlMzU4OWItOWEyZC00OTdlLWJjMmYtZmZmM2UzNGQ2ZWZlIiBjb25uZWN0ZWRUbz0iY2FkMTYyNTMtZjAwMS00N2YwLWFlYjAtMWU1MzJmNTIxM2U3IiBjYXJyaWVyPSI3YjMyZTI4Ny1kNzc1LTQ4MGMtYjMxNy02NGZmZGFjZjEyYzlfcmV0IiBuYW1lPSJPdXRQb3J0Ii8+CiAgICAgICAgPGNvc3RJbmZvcm1hdGlvbiB4c2k6dHlwZT0iZXNkbDpDb3N0SW5mb3JtYXRpb24iPgogICAgICAgICAgPHZhcmlhYmxlT3BlcmF0aW9uYWxDb3N0cyB4c2k6dHlwZT0iZXNkbDpTaW5nbGVWYWx1ZSIgdmFsdWU9IjYuMCIgaWQ9IjdhNzg5Yjk1LTkzYmItNDE1Yi1hYmJkLTRlY2JiNmFkNjBjOSI+CiAgICAgICAgICAgIDxwcm9maWxlUXVhbnRpdHlBbmRVbml0IHhzaTp0eXBlPSJlc2RsOlF1YW50aXR5QW5kVW5pdFR5cGUiIGlkPSJjNTIzMzRjOS1iYzVkLTQxZjQtYjkzZC0xMGU3Yjc2OWYyODEiIGRlc2NyaXB0aW9uPSJDb3N0IGluIEVVUi9NV2giIHBlclVuaXQ9IldBVFRIT1VSIiBwZXJNdWx0aXBsaWVyPSJNRUdBIiB1bml0PSJFVVJPIiBwaHlzaWNhbFF1YW50aXR5PSJDT1NUIi8+CiAgICAgICAgICA8L3ZhcmlhYmxlT3BlcmF0aW9uYWxDb3N0cz4KICAgICAgICAgIDxpbnZlc3RtZW50Q29zdHMgeHNpOnR5cGU9ImVzZGw6U2luZ2xlVmFsdWUiIHZhbHVlPSIyMzMzNTkuMCI+CiAgICAgICAgICAgIDxwcm9maWxlUXVhbnRpdHlBbmRVbml0IHhzaTp0eXBlPSJlc2RsOlF1YW50aXR5QW5kVW5pdFR5cGUiIGlkPSJhM2I1Y2RkOS0zNjRiLTQyNjItYmNlNS00NjU4YzVmMWJhYzkiIGRlc2NyaXB0aW9uPSJDb3N0IGluIEVVUi9NVyIgcGVyVW5pdD0iV0FUVCIgcGVyTXVsdGlwbGllcj0iTUVHQSIgdW5pdD0iRVVSTyIvPgogICAgICAgICAgPC9pbnZlc3RtZW50Q29zdHM+CiAgICAgICAgICA8aW5zdGFsbGF0aW9uQ29zdHMgeHNpOnR5cGU9ImVzZGw6U2luZ2xlVmFsdWUiIHZhbHVlPSIxMDAwMDAwLjAiIGlkPSIyMjUyODk3Mi0xOTIwLTQyZDgtOWUwYy0xMTVmNDE5YzMxZDEiPgogICAgICAgICAgICA8cHJvZmlsZVF1YW50aXR5QW5kVW5pdCB4c2k6dHlwZT0iZXNkbDpRdWFudGl0eUFuZFVuaXRUeXBlIiBpZD0iNjIwYTg1MjktNDNlYy00Njc0LThlZDMtMTBiZWZhZmYwNzQyIiBwaHlzaWNhbFF1YW50aXR5PSJDT1NUIiBkZXNjcmlwdGlvbj0iQ29zdCBpbiBFVVIiIHVuaXQ9IkVVUk8iLz4KICAgICAgICAgIDwvaW5zdGFsbGF0aW9uQ29zdHM+CiAgICAgICAgPC9jb3N0SW5mb3JtYXRpb24+CiAgICAgIDwvYXNzZXQ+CiAgICAgIDxhc3NldCB4c2k6dHlwZT0iZXNkbDpKb2ludCIgbmFtZT0iSm9pbnRfMV9yZXQiIGlkPSI2ZDk3NzAwYy1hM2Q3LTQxMjctYjY0Yy1mMDhlZTJlMzA4ZjkiPgogICAgICAgIDxnZW9tZXRyeSB4c2k6dHlwZT0iZXNkbDpQb2ludCIgQ1JTPSJXR1M4NCIgbGF0PSI1Mi4wNDI4MTA4NjIwMjg4NSIgbG9uPSI0LjMxMTA3NDQwMjY2NTY0OSIvPgogICAgICAgIDxwb3J0IHhzaTp0eXBlPSJlc2RsOk91dFBvcnQiIGlkPSIyOTEzZTY0NS1iMDI3LTQyOWUtYmY1ZC0yMmFjZTk2YTM5ZmEiIGNvbm5lY3RlZFRvPSJkZDUwZTYwMy1jODdjLTRjZGItODJiYi00ODZlYmVlNzcyNTUgNDJlOWY4NmItZWE5Ni00OTkyLWJmM2YtOWNiYWU4YTRhMzljIiBjYXJyaWVyPSI3YjMyZTI4Ny1kNzc1LTQ4MGMtYjMxNy02NGZmZGFjZjEyYzlfcmV0IiBuYW1lPSJyZXRfcG9ydCIvPgogICAgICAgIDxwb3J0IHhzaTp0eXBlPSJlc2RsOkluUG9ydCIgY29ubmVjdGVkVG89IjA0MzFiOGEwLWE4ZDEtNDM3NS1iMzQ4LTM3YTQ3NWFkZDQ3YSA2YjY1NWViMS0yYjY2LTQ1NWYtOTBhMy0wZGQ2ZjI4NDRmYWIgNmNjYjAwNWMtNDVkNC00MjIwLTkyODYtY2M4Zjc3YjAzZWM2IiBpZD0iNzg5MzEyNWQtZDgyZi00ZmU4LWFhZWEtNWZiNmFmZWNjNjM1IiBjYXJyaWVyPSI3YjMyZTI4Ny1kNzc1LTQ4MGMtYjMxNy02NGZmZGFjZjEyYzlfcmV0IiBuYW1lPSJyZXRfcG9ydCIvPgogICAgICA8L2Fzc2V0PgogICAgICA8YXNzZXQgeHNpOnR5cGU9ImVzZGw6Sm9pbnQiIG5hbWU9IkpvaW50XzJfcmV0IiBpZD0iZTYxNWM3N2EtYmI3NS00MTFiLTkyYzItNTQ5ZWZiZGY4ZWM4Ij4KICAgICAgICA8Z2VvbWV0cnkgeHNpOnR5cGU9ImVzZGw6UG9pbnQiIENSUz0iV0dTODQiIGxhdD0iNTIuMDQwODQ2NzgzOTM5OTciIGxvbj0iNC4zMTI3NDYyNDU1Mjk1MzYiLz4KICAgICAgICA8cG9ydCB4c2k6dHlwZT0iZXNkbDpJblBvcnQiIGNvbm5lY3RlZFRvPSJiMzE4N2VmOS1jZDBiLTRlYTgtOTBlNC1lYWIzOWZhMjI1ZTkgNGIzOTczYWItNmU0Yi00OGFmLTk0N2QtNTJjNmQzMGYyMGVhIiBpZD0iYTFiNzE5Y2ItZjczNS00YTMwLWEwZDItY2Y2OTQ1YjNhZmExIiBjYXJyaWVyPSI3YjMyZTI4Ny1kNzc1LTQ4MGMtYjMxNy02NGZmZGFjZjEyYzlfcmV0IiBuYW1lPSJyZXRfcG9ydCIvPgogICAgICAgIDxwb3J0IHhzaTp0eXBlPSJlc2RsOk91dFBvcnQiIGlkPSIyZGQ3OTYxYi00NmNlLTQwMjctODRiNi1jYzI2ODRhMDNhN2IiIGNvbm5lY3RlZFRvPSIwNjUwZDg1MC01OGE5LTQ1YjMtODMxMy1hMzE1NmEwNjE5ODgiIGNhcnJpZXI9IjdiMzJlMjg3LWQ3NzUtNDgwYy1iMzE3LTY0ZmZkYWNmMTJjOV9yZXQiIG5hbWU9InJldF9wb3J0Ii8+CiAgICAgIDwvYXNzZXQ+CiAgICAgIDxhc3NldCB4c2k6dHlwZT0iZXNkbDpKb2ludCIgbmFtZT0iSm9pbnRfM19yZXQiIGlkPSJhOTBkMTQ2Zi1lMjM0LTQ1OWMtOTc0ZS03ODY3YWZiYmIzZjAiPgogICAgICAgIDxnZW9tZXRyeSB4c2k6dHlwZT0iZXNkbDpQb2ludCIgQ1JTPSJXR1M4NCIgbGF0PSI1Mi4wMzg4NjAzNDU4NzEzOSIgbG9uPSI0LjMxNDQ5NDM0NzU3NjM0NCIvPgogICAgICAgIDxwb3J0IHhzaTp0eXBlPSJlc2RsOkluUG9ydCIgY29ubmVjdGVkVG89IjIwNDVhY2E5LTRlNTAtNDJlYy05OWRlLWZiY2ZmYTYyN2E4NiIgaWQ9ImYzNmI5NzY3LThlNjQtNDc0NC04Y2QwLTA4YWNiMmFlODczYiIgY2Fycmllcj0iN2IzMmUyODctZDc3NS00ODBjLWIzMTctNjRmZmRhY2YxMmM5X3JldCIgbmFtZT0icmV0X3BvcnQiLz4KICAgICAgICA8cG9ydCB4c2k6dHlwZT0iZXNkbDpPdXRQb3J0IiBpZD0iNTljY2RkZGMtODkzYi00MTUyLThiYzQtMDE2OGU3ZTc0YmYzIiBjb25uZWN0ZWRUbz0iMmI3YzNhY2ItNjlhNy00OTdkLWE3MmYtYjk4ZGIxODk4NDFjIiBjYXJyaWVyPSI3YjMyZTI4Ny1kNzc1LTQ4MGMtYjMxNy02NGZmZGFjZjEyYzlfcmV0IiBuYW1lPSJyZXRfcG9ydCIvPgogICAgICA8L2Fzc2V0PgogICAgICA8YXNzZXQgeHNpOnR5cGU9ImVzZGw6UGlwZSIgcmVsYXRlZD0iUGlwZTEiIGRpYW1ldGVyPSJETjQ1MCIgbmFtZT0iUGlwZTFfcmV0IiBsZW5ndGg9IjI0NS43IiBpbm5lckRpYW1ldGVyPSIwLjQ0NDQiIGlkPSJQaXBlMV9yZXQiIG91dGVyRGlhbWV0ZXI9IjAuNjMiPgogICAgICAgIDxnZW9tZXRyeSB4c2k6dHlwZT0iZXNkbDpMaW5lIj4KICAgICAgICAgIDxwb2ludCB4c2k6dHlwZT0iZXNkbDpQb2ludCIgQ1JTPSJXR1M4NCIgbGF0PSI1Mi4wNDI4MzE0ODM5Nzg0OSIgbG9uPSI0LjMxMTA5OTk0NDc3OTE4MiIvPgogICAgICAgICAgPHBvaW50IHhzaTp0eXBlPSJlc2RsOlBvaW50IiBDUlM9IldHUzg0IiBsYXQ9IjUyLjA0NDc4ODA1MTI4MjE0IiBsb249IjQuMzA5NDM3MzU1MDMzMDA2Ii8+CiAgICAgICAgPC9nZW9tZXRyeT4KICAgICAgICA8cG9ydCB4c2k6dHlwZT0iZXNkbDpJblBvcnQiIGNvbm5lY3RlZFRvPSIyOTEzZTY0NS1iMDI3LTQyOWUtYmY1ZC0yMmFjZTk2YTM5ZmEiIGlkPSJkZDUwZTYwMy1jODdjLTRjZGItODJiYi00ODZlYmVlNzcyNTUiIGNhcnJpZXI9IjdiMzJlMjg3LWQ3NzUtNDgwYy1iMzE3LTY0ZmZkYWNmMTJjOV9yZXQiIG5hbWU9IkluX3JldCIvPgogICAgICAgIDxwb3J0IHhzaTp0eXBlPSJlc2RsOk91dFBvcnQiIGlkPSJlMzFlMTJjMi04ZjgwLTRhZWQtOWU0Yi05MTg0NDVhMzI5OTYiIGNvbm5lY3RlZFRvPSJiYTljYTA4NC1iNzFmLTQyYTMtODg0YS1mMmYyYjNhZTQyNjUiIGNhcnJpZXI9IjdiMzJlMjg3LWQ3NzUtNDgwYy1iMzE3LTY0ZmZkYWNmMTJjOV9yZXQiIG5hbWU9Ik91dF9yZXQiLz4KICAgICAgICA8Y29zdEluZm9ybWF0aW9uIHhzaTp0eXBlPSJlc2RsOkNvc3RJbmZvcm1hdGlvbiIgaWQ9IjAzYzA3MjkzLWY2ZDQtNGFhNi1hMjk3LTUzMTJjNGQxYzI3ZSI+CiAgICAgICAgICA8aW52ZXN0bWVudENvc3RzIHhzaTp0eXBlPSJlc2RsOlNpbmdsZVZhbHVlIiB2YWx1ZT0iMzQxNy45IiBpZD0iOWI0NDkxNDQtZDBiZi00NWI5LTg4MjItMTVkYmExZDQxMjZkIj4KICAgICAgICAgICAgPHByb2ZpbGVRdWFudGl0eUFuZFVuaXQgeHNpOnR5cGU9ImVzZGw6UXVhbnRpdHlBbmRVbml0VHlwZSIgaWQ9IjZkYmUwOTNmLWY2ZGQtNDliNC05ZDVlLWEyY2Q1Nzg2MTFiZSIgZGVzY3JpcHRpb249IkNvc3QgaW4gRVVSL20iIHBlclVuaXQ9Ik1FVFJFIiBwaHlzaWNhbFF1YW50aXR5PSJDT1NUIiB1bml0PSJFVVJPIi8+CiAgICAgICAgICA8L2ludmVzdG1lbnRDb3N0cz4KICAgICAgICA8L2Nvc3RJbmZvcm1hdGlvbj4KICAgICAgPC9hc3NldD4KICAgICAgPGFzc2V0IHhzaTp0eXBlPSJlc2RsOlBpcGUiIHJlbGF0ZWQ9IlBpcGUyIiBkaWFtZXRlcj0iRE40NTAiIG5hbWU9IlBpcGUyX3JldCIgbGVuZ3RoPSIxOTUuNCIgaW5uZXJEaWFtZXRlcj0iMC40NDQ0IiBpZD0iUGlwZTJfcmV0IiBvdXRlckRpYW1ldGVyPSIwLjYzIj4KICAgICAgICA8Z2VvbWV0cnkgeHNpOnR5cGU9ImVzZGw6TGluZSI+CiAgICAgICAgICA8cG9pbnQgeHNpOnR5cGU9ImVzZGw6UG9pbnQiIENSUz0iV0dTODQiIGxhdD0iNTIuMDQyMTEyMTg0NzUzMjYiIGxvbj0iNC4zMDgzNzgwNDUzODY2OTEiLz4KICAgICAgICAgIDxwb2ludCB4c2k6dHlwZT0iZXNkbDpQb2ludCIgQ1JTPSJXR1M4NCIgbGF0PSI1Mi4wNDI4MDE3ODgzNjgwMSIgbG9uPSI0LjMxMTAwODY2MTY0NDYwNiIvPgogICAgICAgIDwvZ2VvbWV0cnk+CiAgICAgICAgPHBvcnQgeHNpOnR5cGU9ImVzZGw6SW5Qb3J0IiBjb25uZWN0ZWRUbz0iZWY3NGVhOGMtODliNC00MmUwLWE5OGMtNDExODYwODc2YzFhIiBpZD0iMThjZTY5MDYtNTk1Yy00NWU0LWFjZjAtZTA3ZjdkNzY0OGM2IiBjYXJyaWVyPSI3YjMyZTI4Ny1kNzc1LTQ4MGMtYjMxNy02NGZmZGFjZjEyYzlfcmV0IiBuYW1lPSJJbl9yZXQiLz4KICAgICAgICA8cG9ydCB4c2k6dHlwZT0iZXNkbDpPdXRQb3J0IiBpZD0iMDQzMWI4YTAtYThkMS00Mzc1LWIzNDgtMzdhNDc1YWRkNDdhIiBjb25uZWN0ZWRUbz0iNzg5MzEyNWQtZDgyZi00ZmU4LWFhZWEtNWZiNmFmZWNjNjM1IiBjYXJyaWVyPSI3YjMyZTI4Ny1kNzc1LTQ4MGMtYjMxNy02NGZmZGFjZjEyYzlfcmV0IiBuYW1lPSJPdXRfcmV0Ii8+CiAgICAgICAgPGNvc3RJbmZvcm1hdGlvbiB4c2k6dHlwZT0iZXNkbDpDb3N0SW5mb3JtYXRpb24iIGlkPSJiZWM4MzA3MC0yYzUxLTQ4MjUtODJmMy05MjQzNGJkM2U1OWMiPgogICAgICAgICAgPGludmVzdG1lbnRDb3N0cyB4c2k6dHlwZT0iZXNkbDpTaW5nbGVWYWx1ZSIgdmFsdWU9IjM0MTcuOSIgaWQ9IjFjMzMwMjRjLTk5YzgtNDE2OC1iMzUzLTlmMDk5YjU5ZWI2MCI+CiAgICAgICAgICAgIDxwcm9maWxlUXVhbnRpdHlBbmRVbml0IHhzaTp0eXBlPSJlc2RsOlF1YW50aXR5QW5kVW5pdFR5cGUiIGlkPSIyNmZkYjhiZi02NDEzLTQyNzItYTU2Yi1iMDg0ODIzYWM1NzQiIGRlc2NyaXB0aW9uPSJDb3N0IGluIEVVUi9tIiBwZXJVbml0PSJNRVRSRSIgcGh5c2ljYWxRdWFudGl0eT0iQ09TVCIgdW5pdD0iRVVSTyIvPgogICAgICAgICAgPC9pbnZlc3RtZW50Q29zdHM+CiAgICAgICAgPC9jb3N0SW5mb3JtYXRpb24+CiAgICAgIDwvYXNzZXQ+CiAgICAgIDxhc3NldCB4c2k6dHlwZT0iZXNkbDpQaXBlIiByZWxhdGVkPSJQaXBlMyIgZGlhbWV0ZXI9IkRONDUwIiBuYW1lPSJQaXBlM19yZXQiIGxlbmd0aD0iMjQxLjYiIGlubmVyRGlhbWV0ZXI9IjAuNDQ0NCIgaWQ9IlBpcGUzX3JldCIgb3V0ZXJEaWFtZXRlcj0iMC42MyI+CiAgICAgICAgPGdlb21ldHJ5IHhzaTp0eXBlPSJlc2RsOkxpbmUiPgogICAgICAgICAgPHBvaW50IHhzaTp0eXBlPSJlc2RsOlBvaW50IiBDUlM9IldHUzg0IiBsYXQ9IjUyLjA0MDg3NDgzMTAyMTU1NCIgbG9uPSI0LjMxMjc3MzE1MjM3MDcwNSIvPgogICAgICAgICAgPHBvaW50IHhzaTp0eXBlPSJlc2RsOlBvaW50IiBDUlM9IldHUzg0IiBsYXQ9IjUyLjA0Mjc5ODQ4ODg1NDUiIGxvbj0iNC4zMTExMzczOTc4OTQ4NDU1Ii8+CiAgICAgICAgPC9nZW9tZXRyeT4KICAgICAgICA8cG9ydCB4c2k6dHlwZT0iZXNkbDpJblBvcnQiIGNvbm5lY3RlZFRvPSIyZGQ3OTYxYi00NmNlLTQwMjctODRiNi1jYzI2ODRhMDNhN2IiIGlkPSIwNjUwZDg1MC01OGE5LTQ1YjMtODMxMy1hMzE1NmEwNjE5ODgiIGNhcnJpZXI9IjdiMzJlMjg3LWQ3NzUtNDgwYy1iMzE3LTY0ZmZkYWNmMTJjOV9yZXQiIG5hbWU9IkluX3JldCIvPgogICAgICAgIDxwb3J0IHhzaTp0eXBlPSJlc2RsOk91dFBvcnQiIGlkPSI2YjY1NWViMS0yYjY2LTQ1NWYtOTBhMy0wZGQ2ZjI4NDRmYWIiIGNvbm5lY3RlZFRvPSI3ODkzMTI1ZC1kODJmLTRmZTgtYWFlYS01ZmI2YWZlY2M2MzUiIGNhcnJpZXI9IjdiMzJlMjg3LWQ3NzUtNDgwYy1iMzE3LTY0ZmZkYWNmMTJjOV9yZXQiIG5hbWU9Ik91dF9yZXQiLz4KICAgICAgICA8Y29zdEluZm9ybWF0aW9uIHhzaTp0eXBlPSJlc2RsOkNvc3RJbmZvcm1hdGlvbiIgaWQ9IjM4ZjJmMGY3LWY4MTQtNGJhZi1hZTNhLTM2NWFmMWI4NzJkYiI+CiAgICAgICAgICA8aW52ZXN0bWVudENvc3RzIHhzaTp0eXBlPSJlc2RsOlNpbmdsZVZhbHVlIiB2YWx1ZT0iMzQxNy45IiBpZD0iNzgyMjE2NTktNzI5NC00ODMwLTgwMmMtNjdlMzgzNjRiMWYwIj4KICAgICAgICAgICAgPHByb2ZpbGVRdWFudGl0eUFuZFVuaXQgeHNpOnR5cGU9ImVzZGw6UXVhbnRpdHlBbmRVbml0VHlwZSIgaWQ9IjE5ZjYzYjYxLTQ1M2QtNDIxMy1iZGM2LTg2ZjY1NDY4ZmVjOSIgZGVzY3JpcHRpb249IkNvc3QgaW4gRVVSL20iIHBlclVuaXQ9Ik1FVFJFIiBwaHlzaWNhbFF1YW50aXR5PSJDT1NUIiB1bml0PSJFVVJPIi8+CiAgICAgICAgICA8L2ludmVzdG1lbnRDb3N0cz4KICAgICAgICA8L2Nvc3RJbmZvcm1hdGlvbj4KICAgICAgPC9hc3NldD4KICAgICAgPGFzc2V0IHhzaTp0eXBlPSJlc2RsOlBpcGUiIHJlbGF0ZWQ9IlBpcGU0IiBkaWFtZXRlcj0iRE40NTAiIG5hbWU9IlBpcGU0X3JldCIgbGVuZ3RoPSIxODkuNyIgaW5uZXJEaWFtZXRlcj0iMC40NDQ0IiBpZD0iUGlwZTRfcmV0IiBvdXRlckRpYW1ldGVyPSIwLjYzIj4KICAgICAgICA8Z2VvbWV0cnkgeHNpOnR5cGU9ImVzZGw6TGluZSI+CiAgICAgICAgICA8cG9pbnQgeHNpOnR5cGU9ImVzZGw6UG9pbnQiIENSUz0iV0dTODQiIGxhdD0iNTIuMDQwMTYyMDk5NzI0ODciIGxvbj0iNC4zMTAxNTg1MTk4MTI2ODQiLz4KICAgICAgICAgIDxwb2ludCB4c2k6dHlwZT0iZXNkbDpQb2ludCIgQ1JTPSJXR1M4NCIgbGF0PSI1Mi4wNDA4NTE3MzM0MjYyMTYiIGxvbj0iNC4zMTI2OTc5ODA3MjUwMzYiLz4KICAgICAgICA8L2dlb21ldHJ5PgogICAgICAgIDxwb3J0IHhzaTp0eXBlPSJlc2RsOkluUG9ydCIgY29ubmVjdGVkVG89ImJmNmUwYjZiLWJhYWMtNDY4Yi1hOWJhLWY4Mzk3YmFiZjVkNiIgaWQ9ImQxMjZmNzllLWM0M2UtNGQ5ZC1hN2NlLThmNThiZTYzNDY5NSIgY2Fycmllcj0iN2IzMmUyODctZDc3NS00ODBjLWIzMTctNjRmZmRhY2YxMmM5X3JldCIgbmFtZT0iSW5fcmV0Ii8+CiAgICAgICAgPHBvcnQgeHNpOnR5cGU9ImVzZGw6T3V0UG9ydCIgaWQ9ImIzMTg3ZWY5LWNkMGItNGVhOC05MGU0LWVhYjM5ZmEyMjVlOSIgY29ubmVjdGVkVG89ImExYjcxOWNiLWY3MzUtNGEzMC1hMGQyLWNmNjk0NWIzYWZhMSIgY2Fycmllcj0iN2IzMmUyODctZDc3NS00ODBjLWIzMTctNjRmZmRhY2YxMmM5X3JldCIgbmFtZT0iT3V0X3JldCIvPgogICAgICAgIDxjb3N0SW5mb3JtYXRpb24geHNpOnR5cGU9ImVzZGw6Q29zdEluZm9ybWF0aW9uIiBpZD0iMmExNTQ1NmUtZDIzZS00MDY0LThkZWUtYzA1ODhkM2IwNWRjIj4KICAgICAgICAgIDxpbnZlc3RtZW50Q29zdHMgeHNpOnR5cGU9ImVzZGw6U2luZ2xlVmFsdWUiIHZhbHVlPSIzNDE3LjkiIGlkPSIwMjk3Yjk2YS1jMzJjLTQxZjgtODY1My0wMDg1NjU5ZGJhMjkiPgogICAgICAgICAgICA8cHJvZmlsZVF1YW50aXR5QW5kVW5pdCB4c2k6dHlwZT0iZXNkbDpRdWFudGl0eUFuZFVuaXRUeXBlIiBpZD0iOTg2OWIwZDItZGZhMy00MTQ4LTg2YWItZGRkMWNiNDNiN2M3IiBkZXNjcmlwdGlvbj0iQ29zdCBpbiBFVVIvbSIgcGVyVW5pdD0iTUVUUkUiIHBoeXNpY2FsUXVhbnRpdHk9IkNPU1QiIHVuaXQ9IkVVUk8iLz4KICAgICAgICAgIDwvaW52ZXN0bWVudENvc3RzPgogICAgICAgIDwvY29zdEluZm9ybWF0aW9uPgogICAgICA8L2Fzc2V0PgogICAgICA8YXNzZXQgeHNpOnR5cGU9ImVzZGw6UGlwZSIgcmVsYXRlZD0iUGlwZTUiIGRpYW1ldGVyPSJETjQ1MCIgbmFtZT0iUGlwZTVfcmV0IiBsZW5ndGg9IjI0NC42IiBpbm5lckRpYW1ldGVyPSIwLjQ0NDQiIGlkPSJQaXBlNV9yZXQiIG91dGVyRGlhbWV0ZXI9IjAuNjMiPgogICAgICAgIDxnZW9tZXRyeSB4c2k6dHlwZT0iZXNkbDpMaW5lIj4KICAgICAgICAgIDxwb2ludCB4c2k6dHlwZT0iZXNkbDpQb2ludCIgQ1JTPSJXR1M4NCIgbGF0PSI1Mi4wMzg4ODgzOTQxOTkzNzUiIGxvbj0iNC4zMTQ1MDUxNjI4NTAxODgiLz4KICAgICAgICAgIDxwb2ludCB4c2k6dHlwZT0iZXNkbDpQb2ludCIgQ1JTPSJXR1M4NCIgbGF0PSI1Mi4wNDA4Mjg2MzU4MTg5NzYiIGxvbj0iNC4zMTI4MjY2NTY5NDg1NzkiLz4KICAgICAgICA8L2dlb21ldHJ5PgogICAgICAgIDxwb3J0IHhzaTp0eXBlPSJlc2RsOkluUG9ydCIgY29ubmVjdGVkVG89IjU5Y2NkZGRjLTg5M2ItNDE1Mi04YmM0LTAxNjhlN2U3NGJmMyIgaWQ9IjJiN2MzYWNiLTY5YTctNDk3ZC1hNzJmLWI5OGRiMTg5ODQxYyIgY2Fycmllcj0iN2IzMmUyODctZDc3NS00ODBjLWIzMTctNjRmZmRhY2YxMmM5X3JldCIgbmFtZT0iSW5fcmV0Ii8+CiAgICAgICAgPHBvcnQgeHNpOnR5cGU9ImVzZGw6T3V0UG9ydCIgaWQ9IjRiMzk3M2FiLTZlNGItNDhhZi05NDdkLTUyYzZkMzBmMjBlYSIgY29ubmVjdGVkVG89ImExYjcxOWNiLWY3MzUtNGEzMC1hMGQyLWNmNjk0NWIzYWZhMSIgY2Fycmllcj0iN2IzMmUyODctZDc3NS00ODBjLWIzMTctNjRmZmRhY2YxMmM5X3JldCIgbmFtZT0iT3V0X3JldCIvPgogICAgICAgIDxjb3N0SW5mb3JtYXRpb24geHNpOnR5cGU9ImVzZGw6Q29zdEluZm9ybWF0aW9uIiBpZD0iMzg3ZWI0NTgtNGUzZS00ZTBkLWJmMWMtMGNhMmQ3N2FhNGRkIj4KICAgICAgICAgIDxpbnZlc3RtZW50Q29zdHMgeHNpOnR5cGU9ImVzZGw6U2luZ2xlVmFsdWUiIHZhbHVlPSIzNDE3LjkiIGlkPSJiNzhhYzhhNy05ZDBlLTQ2MDMtODIxYi1mZWJmNThiNDhiYjMiPgogICAgICAgICAgICA8cHJvZmlsZVF1YW50aXR5QW5kVW5pdCB4c2k6dHlwZT0iZXNkbDpRdWFudGl0eUFuZFVuaXRUeXBlIiBpZD0iZDY1NDc4MDEtMGViNy00ZWQ0LTk1OTctMWU3OWNjMDkzNjIyIiBkZXNjcmlwdGlvbj0iQ29zdCBpbiBFVVIvbSIgcGVyVW5pdD0iTUVUUkUiIHBoeXNpY2FsUXVhbnRpdHk9IkNPU1QiIHVuaXQ9IkVVUk8iLz4KICAgICAgICAgIDwvaW52ZXN0bWVudENvc3RzPgogICAgICAgIDwvY29zdEluZm9ybWF0aW9uPgogICAgICA8L2Fzc2V0PgogICAgICA8YXNzZXQgeHNpOnR5cGU9ImVzZGw6UGlwZSIgcmVsYXRlZD0iUGlwZTYiIGRpYW1ldGVyPSJETjQ1MCIgbmFtZT0iUGlwZTZfcmV0IiBsZW5ndGg9IjE3Ni42IiBpbm5lckRpYW1ldGVyPSIwLjQ0NDQiIGlkPSJQaXBlNl9yZXQiIG91dGVyRGlhbWV0ZXI9IjAuNjMiPgogICAgICAgIDxnZW9tZXRyeSB4c2k6dHlwZT0iZXNkbDpMaW5lIj4KICAgICAgICAgIDxwb2ludCB4c2k6dHlwZT0iZXNkbDpQb2ludCIgQ1JTPSJXR1M4NCIgbGF0PSI1Mi4wMzgxMDMwMzQzNjI5MiIgbG9uPSI0LjMxMjE3NDU3NTk5NjczMiIvPgogICAgICAgICAgPHBvaW50IHhzaTp0eXBlPSJlc2RsOlBvaW50IiBDUlM9IldHUzg0IiBsYXQ9IjUyLjAzODg0MjE5Njk0Mzg5IiBsb249IjQuMzE0NDYyMTA1MTI0OTU1Ii8+CiAgICAgICAgPC9nZW9tZXRyeT4KICAgICAgICA8cG9ydCB4c2k6dHlwZT0iZXNkbDpJblBvcnQiIGNvbm5lY3RlZFRvPSI5YzAyNWIxOS01N2QxLTQzYTgtYjJlOC1kYjNlNjg0NzU2ZjIiIGlkPSI1Y2QwZjJlMC1kNDU2LTQ5MDktYTgxYy00YjMxMmIxYmU4NTciIGNhcnJpZXI9IjdiMzJlMjg3LWQ3NzUtNDgwYy1iMzE3LTY0ZmZkYWNmMTJjOV9yZXQiIG5hbWU9IkluX3JldCIvPgogICAgICAgIDxwb3J0IHhzaTp0eXBlPSJlc2RsOk91dFBvcnQiIGlkPSIyMDQ1YWNhOS00ZTUwLTQyZWMtOTlkZS1mYmNmZmE2MjdhODYiIGNvbm5lY3RlZFRvPSJmMzZiOTc2Ny04ZTY0LTQ3NDQtOGNkMC0wOGFjYjJhZTg3M2IiIGNhcnJpZXI9IjdiMzJlMjg3LWQ3NzUtNDgwYy1iMzE3LTY0ZmZkYWNmMTJjOV9yZXQiIG5hbWU9Ik91dF9yZXQiLz4KICAgICAgICA8Y29zdEluZm9ybWF0aW9uIHhzaTp0eXBlPSJlc2RsOkNvc3RJbmZvcm1hdGlvbiIgaWQ9ImNiYmI3NGJhLWJhNmYtNGYxNy1hNzhmLTNiM2MwN2NlNTMxZCI+CiAgICAgICAgICA8aW52ZXN0bWVudENvc3RzIHhzaTp0eXBlPSJlc2RsOlNpbmdsZVZhbHVlIiB2YWx1ZT0iMzQxNy45IiBpZD0iYWU1ZjRmNWYtMTMyMy00YTNiLTk4YzgtZmFjYTMyMWEwMGM3Ij4KICAgICAgICAgICAgPHByb2ZpbGVRdWFudGl0eUFuZFVuaXQgeHNpOnR5cGU9ImVzZGw6UXVhbnRpdHlBbmRVbml0VHlwZSIgaWQ9IjE4NTcwYjIwLWI4MjAtNDNkMC05NTJhLWI2ZWFmMTY2YzYzOSIgZGVzY3JpcHRpb249IkNvc3QgaW4gRVVSL20iIHBlclVuaXQ9Ik1FVFJFIiBwaHlzaWNhbFF1YW50aXR5PSJDT1NUIiB1bml0PSJFVVJPIi8+CiAgICAgICAgICA8L2ludmVzdG1lbnRDb3N0cz4KICAgICAgICA8L2Nvc3RJbmZvcm1hdGlvbj4KICAgICAgPC9hc3NldD4KICAgICAgPGFzc2V0IHhzaTp0eXBlPSJlc2RsOkhlYXRQcm9kdWNlciIgcG93ZXI9IjI1MDAwMDAuMCIgbmFtZT0iSGVhdFByb2R1Y2VyXzIiIGlkPSJkYTAwZGRmYy1jZmE0LTRmMjEtYjViZS03YzY5ZDJiZjUzYmIiPgogICAgICAgIDxnZW9tZXRyeSB4c2k6dHlwZT0iZXNkbDpQb2ludCIgbG9uPSI0LjMxMTcyNjA5MzI5MjIzNyIgQ1JTPSJXR1M4NCIgbGF0PSI1Mi4wNDQ4NzYyMTY2NDEwMyIvPgogICAgICAgIDxwb3J0IHhzaTp0eXBlPSJlc2RsOk91dFBvcnQiIGlkPSI4ODZlNTQzMC1iZWMxLTQ0ZTMtYmFiNi0yMjFjNDUxOGM4MTAiIGNvbm5lY3RlZFRvPSJiYmZlZDgzMC0wNzFkLTRkMDItYmRkZC1lNzA5MjQ3YzgzMzciIGNhcnJpZXI9IjdiMzJlMjg3LWQ3NzUtNDgwYy1iMzE3LTY0ZmZkYWNmMTJjOSIgbmFtZT0iT3V0Ii8+CiAgICAgICAgPHBvcnQgeHNpOnR5cGU9ImVzZGw6SW5Qb3J0IiBjb25uZWN0ZWRUbz0iZGY2Zjg5ZDAtNzg3Mi00ODkxLTkzNGYtZGU0MDdmNmFhMTQyIiBpZD0iYzdlZDg5MTUtZGRkMC00N2Y4LTkzZDYtMWRhYmZiNWQzMjBiIiBjYXJyaWVyPSI3YjMyZTI4Ny1kNzc1LTQ4MGMtYjMxNy02NGZmZGFjZjEyYzlfcmV0IiBuYW1lPSJJbiIvPgogICAgICAgIDxjb3N0SW5mb3JtYXRpb24geHNpOnR5cGU9ImVzZGw6Q29zdEluZm9ybWF0aW9uIiBpZD0iZDU5ZmUwYzQtNTE1Ni00ZGNmLWIyNTktNmFjNjg1NTI0MWM2Ij4KICAgICAgICAgIDx2YXJpYWJsZU9wZXJhdGlvbmFsQ29zdHMgeHNpOnR5cGU9ImVzZGw6U2luZ2xlVmFsdWUiIHZhbHVlPSI2LjAiIGlkPSI3YTc4OWI5NS05M2JiLTQxNWItYWJiZC00ZWNiYjZhZDYwYzkiPgogICAgICAgICAgICA8cHJvZmlsZVF1YW50aXR5QW5kVW5pdCB4c2k6dHlwZT0iZXNkbDpRdWFudGl0eUFuZFVuaXRUeXBlIiBpZD0iYzUyMzM0YzktYmM1ZC00MWY0LWI5M2QtMTBlN2I3NjlmMjgxIiBkZXNjcmlwdGlvbj0iQ29zdCBpbiBFVVIvTVdoIiBwZXJVbml0PSJXQVRUSE9VUiIgcGVyTXVsdGlwbGllcj0iTUVHQSIgdW5pdD0iRVVSTyIgcGh5c2ljYWxRdWFudGl0eT0iQ09TVCIvPgogICAgICAgICAgPC92YXJpYWJsZU9wZXJhdGlvbmFsQ29zdHM+CiAgICAgICAgICA8aW5zdGFsbGF0aW9uQ29zdHMgeHNpOnR5cGU9ImVzZGw6U2luZ2xlVmFsdWUiIHZhbHVlPSIxMDAwMDAuMCIgaWQ9IjJiMmY0YjkzLTMyYzctNGYyMC05NzIzLTU5MDBjYzc2ZmUyMCI+CiAgICAgICAgICAgIDxwcm9maWxlUXVhbnRpdHlBbmRVbml0IHhzaTp0eXBlPSJlc2RsOlF1YW50aXR5QW5kVW5pdFR5cGUiIGlkPSJiMDk3NWVlZi0yZTEzLTRiN2YtYjg5YS02NGE0NzE4M2U4Y2MiIHBoeXNpY2FsUXVhbnRpdHk9IkNPU1QiIGRlc2NyaXB0aW9uPSJDb3N0IGluIEVVUiIgdW5pdD0iRVVSTyIvPgogICAgICAgICAgPC9pbnN0YWxsYXRpb25Db3N0cz4KICAgICAgICAgIDxpbnZlc3RtZW50Q29zdHMgeHNpOnR5cGU9ImVzZGw6U2luZ2xlVmFsdWUiIHZhbHVlPSIxMDAwMDAuMCIgaWQ9IjM2MzNjZDA5LTlmODctNGQ4ZC1hNWY4LTA0MzFiYWI5NTc2ZCI+CiAgICAgICAgICAgIDxwcm9maWxlUXVhbnRpdHlBbmRVbml0IHhzaTp0eXBlPSJlc2RsOlF1YW50aXR5QW5kVW5pdFR5cGUiIGlkPSI4OGEwMDlmZi0wZWViLTQ4YjEtOWViMy02MGRiYTA0YjNlNzkiIGRlc2NyaXB0aW9uPSJDb3N0IGluIEVVUi9NVyIgcGVyVW5pdD0iV0FUVCIgcGVyTXVsdGlwbGllcj0iTUVHQSIgdW5pdD0iRVVSTyIgcGh5c2ljYWxRdWFudGl0eT0iQ09TVCIvPgogICAgICAgICAgPC9pbnZlc3RtZW50Q29zdHM+CiAgICAgICAgICA8bWFyZ2luYWxDb3N0cyB4c2k6dHlwZT0iZXNkbDpTaW5nbGVWYWx1ZSIgdmFsdWU9IjEuMCIgaWQ9IjNmNzNiZDI2LWI5MjMtNGUyYS04ZjhlLTQzNWM4YTc4M2Q4ZCI+CiAgICAgICAgICAgIDxwcm9maWxlUXVhbnRpdHlBbmRVbml0IHhzaTp0eXBlPSJlc2RsOlF1YW50aXR5QW5kVW5pdFR5cGUiIGlkPSJhMTA4NmE3Ny1hMmQxLTRhOWItYTZmMi1hZGYwZTQzODBlY2EiIHBoeXNpY2FsUXVhbnRpdHk9IkNPU1QiIGRlc2NyaXB0aW9uPSJDb3N0IGluIEVVUiIgdW5pdD0iRVVSTyIvPgogICAgICAgICAgPC9tYXJnaW5hbENvc3RzPgogICAgICAgIDwvY29zdEluZm9ybWF0aW9uPgogICAgICA8L2Fzc2V0PgogICAgICA8YXNzZXQgeHNpOnR5cGU9ImVzZGw6UGlwZSIgZGlhbWV0ZXI9IkRONDUwIiBuYW1lPSJQaXBlX2Y2ZTUiIGxlbmd0aD0iMjM5LjciIGlubmVyRGlhbWV0ZXI9IjAuNDQ0NCIgaWQ9ImY2ZTVhNzYwLTAxZDUtNDM0MS1iZjE1LWI4ZDMzYjdiZWE1MCIgb3V0ZXJEaWFtZXRlcj0iMC42MyI+CiAgICAgICAgPGdlb21ldHJ5IHhzaTp0eXBlPSJlc2RsOkxpbmUiIENSUz0iV0dTODQiPgogICAgICAgICAgPHBvaW50IHhzaTp0eXBlPSJlc2RsOlBvaW50IiBsb249IjQuMzExNzI2MDkzMjkyMjM3IiBsYXQ9IjUyLjA0NDg3NjIxNjY0MTAzIi8+CiAgICAgICAgICA8cG9pbnQgeHNpOnR5cGU9ImVzZGw6UG9pbnQiIGxvbj0iNC4zMTE2OTUyNDc4ODg1NjYiIGxhdD0iNTIuMDQyNzIwODYxOTM4ODU0Ii8+CiAgICAgICAgPC9nZW9tZXRyeT4KICAgICAgICA8cG9ydCB4c2k6dHlwZT0iZXNkbDpJblBvcnQiIGNvbm5lY3RlZFRvPSI4ODZlNTQzMC1iZWMxLTQ0ZTMtYmFiNi0yMjFjNDUxOGM4MTAiIGlkPSJiYmZlZDgzMC0wNzFkLTRkMDItYmRkZC1lNzA5MjQ3YzgzMzciIGNhcnJpZXI9IjdiMzJlMjg3LWQ3NzUtNDgwYy1iMzE3LTY0ZmZkYWNmMTJjOSIgbmFtZT0iSW4iLz4KICAgICAgICA8cG9ydCB4c2k6dHlwZT0iZXNkbDpPdXRQb3J0IiBpZD0iZjk2NmJhZGUtMWZhZC00NTNmLThlYzItNDA2MmVjNzBiYzdiIiBjb25uZWN0ZWRUbz0iNTE4NTI4NjEtYWVlYi00NjFmLWI4ZWMtMDhmMDAwYWJjNmRkIiBjYXJyaWVyPSI3YjMyZTI4Ny1kNzc1LTQ4MGMtYjMxNy02NGZmZGFjZjEyYzkiIG5hbWU9Ik91dCIvPgogICAgICAgIDxtYXRlcmlhbCB4c2k6dHlwZT0iZXNkbDpDb21wb3VuZE1hdHRlciIgY29tcG91bmRUeXBlPSJMQVlFUkVEIj4KICAgICAgICAgIDxjb21wb25lbnQgeHNpOnR5cGU9ImVzZGw6Q29tcG91bmRNYXR0ZXJDb21wb25lbnQiIGxheWVyV2lkdGg9IjAuMDA2MyI+CiAgICAgICAgICAgIDxtYXR0ZXIgeHNpOnR5cGU9ImVzZGw6TWF0ZXJpYWwiIHRoZXJtYWxDb25kdWN0aXZpdHk9IjUyLjE1IiBuYW1lPSJzdGVlbCIgaWQ9IjM3MWMxZDcyLWRlMzUtNDU1OS05YjBlLTQ3MTcyZTVkMWQ4MyIvPgogICAgICAgICAgPC9jb21wb25lbnQ+CiAgICAgICAgICA8Y29tcG9uZW50IHhzaTp0eXBlPSJlc2RsOkNvbXBvdW5kTWF0dGVyQ29tcG9uZW50IiBsYXllcldpZHRoPSIwLjA4MDUiPgogICAgICAgICAgICA8bWF0dGVyIHhzaTp0eXBlPSJlc2RsOk1hdGVyaWFsIiB0aGVybWFsQ29uZHVjdGl2aXR5PSIwLjAyNyIgbmFtZT0iUFVSIiBpZD0iZGYzMGJkMzctMmZjNC00OTkzLTgyOGYtMWI3Y2YxZTgyMDJjIi8+CiAgICAgICAgICA8L2NvbXBvbmVudD4KICAgICAgICAgIDxjb21wb25lbnQgeHNpOnR5cGU9ImVzZGw6Q29tcG91bmRNYXR0ZXJDb21wb25lbnQiIGxheWVyV2lkdGg9IjAuMDA2Ij4KICAgICAgICAgICAgPG1hdHRlciB4c2k6dHlwZT0iZXNkbDpNYXRlcmlhbCIgdGhlcm1hbENvbmR1Y3Rpdml0eT0iMC40IiBuYW1lPSJIRFBFIiBpZD0iZjUzZGUzN2ItYTczNS00YjBkLWIyMjYtYTZiNzIyMDI5YTAxIi8+CiAgICAgICAgICA8L2NvbXBvbmVudD4KICAgICAgICA8L21hdGVyaWFsPgogICAgICAgIDxkYXRhU291cmNlIHhzaTp0eXBlPSJlc2RsOkRhdGFTb3VyY2UiIGF0dHJpYnV0aW9uPSJodHRwczovL3d3dy5sb2dzdG9yLmNvbS9tZWRpYS82NTA2L3Byb2R1Y3QtY2F0YWxvZ3VlLXVrLTIwMjAwMy5wZGYiIG5hbWU9IkxvZ3N0b3IgUHJvZHVjdCBDYXRhbG9ndWUgVmVyc2lvbiAyMDIwLjAzIi8+CiAgICAgICAgPGNvc3RJbmZvcm1hdGlvbiB4c2k6dHlwZT0iZXNkbDpDb3N0SW5mb3JtYXRpb24iIGlkPSIyMmZiMmU4NS03YTgxLTQzNzEtYjZhYi02ZDUxMDFiOGNhNDUiPgogICAgICAgICAgPGludmVzdG1lbnRDb3N0cyB4c2k6dHlwZT0iZXNkbDpTaW5nbGVWYWx1ZSIgbmFtZT0iQ29tYmluZWQgaW52ZXN0bWVudCBhbmQgaW5zdGFsbGF0aW9uIGNvc3RzIiBpZD0iYTQwMTY1ZTgtODhiZC00OWI5LTgxZDktMjk4ODEyYWMwMTcwIiB2YWx1ZT0iMzQxNy45Ij4KICAgICAgICAgICAgPHByb2ZpbGVRdWFudGl0eUFuZFVuaXQgeHNpOnR5cGU9ImVzZGw6UXVhbnRpdHlBbmRVbml0VHlwZSIgaWQ9ImQwYWViYzc2LTIwMWItNGIyZC04MWZlLTU1MjY5ZmNlZmUzYiIgZGVzY3JpcHRpb249IkNvc3RzIGluIEVVUi9tIiBwZXJVbml0PSJNRVRSRSIgcGh5c2ljYWxRdWFudGl0eT0iQ09TVCIgdW5pdD0iRVVSTyIvPgogICAgICAgICAgPC9pbnZlc3RtZW50Q29zdHM+CiAgICAgICAgPC9jb3N0SW5mb3JtYXRpb24+CiAgICAgIDwvYXNzZXQ+CiAgICAgIDxhc3NldCB4c2k6dHlwZT0iZXNkbDpQaXBlIiBkaWFtZXRlcj0iRE40NTAiIG5hbWU9IlBpcGVfZjZlNV9yZXQiIGxlbmd0aD0iMjMzLjkiIGlubmVyRGlhbWV0ZXI9IjAuNDQ0NCIgaWQ9IjBkYjkxNTE1LTQxOGEtNGJjYi05ZDk5LTkwNDdjMWNhOGJkZiIgb3V0ZXJEaWFtZXRlcj0iMC42MyI+CiAgICAgICAgPGdlb21ldHJ5IHhzaTp0eXBlPSJlc2RsOkxpbmUiIENSUz0iV0dTODQiPgogICAgICAgICAgPHBvaW50IHhzaTp0eXBlPSJlc2RsOlBvaW50IiBsb249IjQuMzExMDc0NDAyNjY1NjQ5IiBsYXQ9IjUyLjA0MjgxMDg2MjAyODg1Ii8+CiAgICAgICAgICA8cG9pbnQgeHNpOnR5cGU9ImVzZGw6UG9pbnQiIGxvbj0iNC4zMTE3MjYwOTMyOTIyMzciIGxhdD0iNTIuMDQ0ODc2MjE2NjQxMDMiLz4KICAgICAgICA8L2dlb21ldHJ5PgogICAgICAgIDxwb3J0IHhzaTp0eXBlPSJlc2RsOkluUG9ydCIgY29ubmVjdGVkVG89IjI5MTNlNjQ1LWIwMjctNDI5ZS1iZjVkLTIyYWNlOTZhMzlmYSIgaWQ9IjQyZTlmODZiLWVhOTYtNDk5Mi1iZjNmLTljYmFlOGE0YTM5YyIgY2Fycmllcj0iN2IzMmUyODctZDc3NS00ODBjLWIzMTctNjRmZmRhY2YxMmM5X3JldCIgbmFtZT0iSW4iLz4KICAgICAgICA8cG9ydCB4c2k6dHlwZT0iZXNkbDpPdXRQb3J0IiBpZD0iZGY2Zjg5ZDAtNzg3Mi00ODkxLTkzNGYtZGU0MDdmNmFhMTQyIiBjb25uZWN0ZWRUbz0iYzdlZDg5MTUtZGRkMC00N2Y4LTkzZDYtMWRhYmZiNWQzMjBiIiBjYXJyaWVyPSI3YjMyZTI4Ny1kNzc1LTQ4MGMtYjMxNy02NGZmZGFjZjEyYzlfcmV0IiBuYW1lPSJPdXQiLz4KICAgICAgICA8bWF0ZXJpYWwgeHNpOnR5cGU9ImVzZGw6Q29tcG91bmRNYXR0ZXIiIGNvbXBvdW5kVHlwZT0iTEFZRVJFRCI+CiAgICAgICAgICA8Y29tcG9uZW50IHhzaTp0eXBlPSJlc2RsOkNvbXBvdW5kTWF0dGVyQ29tcG9uZW50IiBsYXllcldpZHRoPSIwLjAwNjMiPgogICAgICAgICAgICA8bWF0dGVyIHhzaTp0eXBlPSJlc2RsOk1hdGVyaWFsIiB0aGVybWFsQ29uZHVjdGl2aXR5PSI1Mi4xNSIgbmFtZT0ic3RlZWwiIGlkPSIzNzFjMWQ3Mi1kZTM1LTQ1NTktOWIwZS00NzE3MmU1ZDFkODMiLz4KICAgICAgICAgIDwvY29tcG9uZW50PgogICAgICAgICAgPGNvbXBvbmVudCB4c2k6dHlwZT0iZXNkbDpDb21wb3VuZE1hdHRlckNvbXBvbmVudCIgbGF5ZXJXaWR0aD0iMC4wODA1Ij4KICAgICAgICAgICAgPG1hdHRlciB4c2k6dHlwZT0iZXNkbDpNYXRlcmlhbCIgdGhlcm1hbENvbmR1Y3Rpdml0eT0iMC4wMjciIG5hbWU9IlBVUiIgaWQ9ImRmMzBiZDM3LTJmYzQtNDk5My04MjhmLTFiN2NmMWU4MjAyYyIvPgogICAgICAgICAgPC9jb21wb25lbnQ+CiAgICAgICAgICA8Y29tcG9uZW50IHhzaTp0eXBlPSJlc2RsOkNvbXBvdW5kTWF0dGVyQ29tcG9uZW50IiBsYXllcldpZHRoPSIwLjAwNiI+CiAgICAgICAgICAgIDxtYXR0ZXIgeHNpOnR5cGU9ImVzZGw6TWF0ZXJpYWwiIHRoZXJtYWxDb25kdWN0aXZpdHk9IjAuNCIgbmFtZT0iSERQRSIgaWQ9ImY1M2RlMzdiLWE3MzUtNGIwZC1iMjI2LWE2YjcyMjAyOWEwMSIvPgogICAgICAgICAgPC9jb21wb25lbnQ+CiAgICAgICAgPC9tYXRlcmlhbD4KICAgICAgICA8ZGF0YVNvdXJjZSB4c2k6dHlwZT0iZXNkbDpEYXRhU291cmNlIiBhdHRyaWJ1dGlvbj0iaHR0cHM6Ly93d3cubG9nc3Rvci5jb20vbWVkaWEvNjUwNi9wcm9kdWN0LWNhdGFsb2d1ZS11ay0yMDIwMDMucGRmIiBuYW1lPSJMb2dzdG9yIFByb2R1Y3QgQ2F0YWxvZ3VlIFZlcnNpb24gMjAyMC4wMyIvPgogICAgICAgIDxjb3N0SW5mb3JtYXRpb24geHNpOnR5cGU9ImVzZGw6Q29zdEluZm9ybWF0aW9uIiBpZD0iN2NiYzljMzItM2Q3ZC00NGUxLWFiNzMtNTk4NDU5Mjk0ZjBjIj4KICAgICAgICAgIDxpbnZlc3RtZW50Q29zdHMgeHNpOnR5cGU9ImVzZGw6U2luZ2xlVmFsdWUiIG5hbWU9IkNvbWJpbmVkIGludmVzdG1lbnQgYW5kIGluc3RhbGxhdGlvbiBjb3N0cyIgaWQ9ImE0MDE2NWU4LTg4YmQtNDliOS04MWQ5LTI5ODgxMmFjMDE3MCIgdmFsdWU9IjM0MTcuOSI+CiAgICAgICAgICAgIDxwcm9maWxlUXVhbnRpdHlBbmRVbml0IHhzaTp0eXBlPSJlc2RsOlF1YW50aXR5QW5kVW5pdFR5cGUiIGlkPSJkMGFlYmM3Ni0yMDFiLTRiMmQtODFmZS01NTI2OWZjZWZlM2IiIGRlc2NyaXB0aW9uPSJDb3N0cyBpbiBFVVIvbSIgcGVyVW5pdD0iTUVUUkUiIHBoeXNpY2FsUXVhbnRpdHk9IkNPU1QiIHVuaXQ9IkVVUk8iLz4KICAgICAgICAgIDwvaW52ZXN0bWVudENvc3RzPgogICAgICAgIDwvY29zdEluZm9ybWF0aW9uPgogICAgICA8L2Fzc2V0PgogICAgICA8YXNzZXQgeHNpOnR5cGU9ImVzZGw6UGlwZSIgZGlhbWV0ZXI9IkRONDAwIiBuYW1lPSJQaXBlX2IyYTQiIG91dGVyRGlhbWV0ZXI9IjAuNjMiIGlkPSJiMmE0MTQ5Yi1hYjVjLTQ2ZmItODA3ZS1hYjU2N2Q4NTljMmEiIGlubmVyRGlhbWV0ZXI9IjAuMzkzOCIgbGVuZ3RoPSIyNTkuNSI+CiAgICAgICAgPGdlb21ldHJ5IHhzaTp0eXBlPSJlc2RsOkxpbmUiIENSUz0iV0dTODQiPgogICAgICAgICAgPHBvaW50IHhzaTp0eXBlPSJlc2RsOlBvaW50IiBsb249IjQuMzExNjk1MjQ3ODg4NTY2IiBsYXQ9IjUyLjA0MjcyMDg2MTkzODg1NCIvPgogICAgICAgICAgPHBvaW50IHhzaTp0eXBlPSJlc2RsOlBvaW50IiBsb249IjQuMzE0OTQ0NzQ0MTEwMTA4IiBsYXQ9IjUyLjA0MzkyNTk5MjcwNjE5Ii8+CiAgICAgICAgPC9nZW9tZXRyeT4KICAgICAgICA8bWF0ZXJpYWwgeHNpOnR5cGU9ImVzZGw6Q29tcG91bmRNYXR0ZXIiIGNvbXBvdW5kVHlwZT0iTEFZRVJFRCI+CiAgICAgICAgICA8Y29tcG9uZW50IHhzaTp0eXBlPSJlc2RsOkNvbXBvdW5kTWF0dGVyQ29tcG9uZW50IiBsYXllcldpZHRoPSIwLjAwNjMiPgogICAgICAgICAgICA8bWF0dGVyIHhzaTp0eXBlPSJlc2RsOk1hdGVyaWFsIiB0aGVybWFsQ29uZHVjdGl2aXR5PSI1Mi4xNSIgaWQ9ImFlMzJkMzBiLTRlMGQtNDQ3MC1hNGYwLTRiYTdiZDI1ODA3MCIgbmFtZT0ic3RlZWwiLz4KICAgICAgICAgIDwvY29tcG9uZW50PgogICAgICAgICAgPGNvbXBvbmVudCB4c2k6dHlwZT0iZXNkbDpDb21wb3VuZE1hdHRlckNvbXBvbmVudCIgbGF5ZXJXaWR0aD0iMC4xMDUyIj4KICAgICAgICAgICAgPG1hdHRlciB4c2k6dHlwZT0iZXNkbDpNYXRlcmlhbCIgdGhlcm1hbENvbmR1Y3Rpdml0eT0iMC4wMjciIGlkPSI1ZDU5MWI1OC0yY2Y4LTRkOTQtOTFlYi1iZTc3M2UxYzI1ZWUiIG5hbWU9IlBVUiIvPgogICAgICAgICAgPC9jb21wb25lbnQ+CiAgICAgICAgICA8Y29tcG9uZW50IHhzaTp0eXBlPSJlc2RsOkNvbXBvdW5kTWF0dGVyQ29tcG9uZW50IiBsYXllcldpZHRoPSIwLjAwNjYiPgogICAgICAgICAgICA8bWF0dGVyIHhzaTp0eXBlPSJlc2RsOk1hdGVyaWFsIiB0aGVybWFsQ29uZHVjdGl2aXR5PSIwLjQiIGlkPSI4YTAyNzljYy1hZmJmLTQ2ZmItYTU5MC0zMzk2MGNlMzA2MTMiIG5hbWU9IkhEUEUiLz4KICAgICAgICAgIDwvY29tcG9uZW50PgogICAgICAgIDwvbWF0ZXJpYWw+CiAgICAgICAgPHBvcnQgeHNpOnR5cGU9ImVzZGw6SW5Qb3J0IiBjb25uZWN0ZWRUbz0iYzBlYWM0ZGItZjVkYS00N2YzLTgyMDItODQzOGQwMDBiZDMyIiBpZD0iMmNjNzczZWUtYjU2Mi00ZTFmLWExZDEtYTI2NTZlMTA5MDdkIiBjYXJyaWVyPSI3YjMyZTI4Ny1kNzc1LTQ4MGMtYjMxNy02NGZmZGFjZjEyYzkiIG5hbWU9IkluIi8+CiAgICAgICAgPHBvcnQgeHNpOnR5cGU9ImVzZGw6T3V0UG9ydCIgaWQ9IjAxYzg4MmY3LWVjMTUtNGQzNC05ZjQzLTgxODE5NzJmMjUwMCIgY29ubmVjdGVkVG89IjZiODNlNzRkLTVmZjEtNGZmYS04YmQ0LWRlMTE1NGI1NDFlMiIgY2Fycmllcj0iN2IzMmUyODctZDc3NS00ODBjLWIzMTctNjRmZmRhY2YxMmM5IiBuYW1lPSJPdXQiLz4KICAgICAgICA8ZGF0YVNvdXJjZSB4c2k6dHlwZT0iZXNkbDpEYXRhU291cmNlIiBhdHRyaWJ1dGlvbj0iaHR0cHM6Ly93d3cubG9nc3Rvci5jb20vbWVkaWEvNjUwNi9wcm9kdWN0LWNhdGFsb2d1ZS11ay0yMDIwMDMucGRmIiBuYW1lPSJMb2dzdG9yIFByb2R1Y3QgQ2F0YWxvZ3VlIFZlcnNpb24gMjAyMC4wMyIvPgogICAgICAgIDxjb3N0SW5mb3JtYXRpb24geHNpOnR5cGU9ImVzZGw6Q29zdEluZm9ybWF0aW9uIiBpZD0iZmFjYjYxMGEtMWJiYy00NTAzLThlMDItOWE3Njc1NThlY2RmIj4KICAgICAgICAgIDxpbnZlc3RtZW50Q29zdHMgeHNpOnR5cGU9ImVzZGw6U2luZ2xlVmFsdWUiIG5hbWU9IkNvbWJpbmVkIGludmVzdG1lbnQgYW5kIGluc3RhbGxhdGlvbiBjb3N0cyIgaWQ9IjU2NmQzZjI2LWY4NWEtNDhiNC1iMDZhLTVmZDYyYWM2ZmE2MSIgdmFsdWU9IjI4NDAuNiI+CiAgICAgICAgICAgIDxwcm9maWxlUXVhbnRpdHlBbmRVbml0IHhzaTp0eXBlPSJlc2RsOlF1YW50aXR5QW5kVW5pdFR5cGUiIGlkPSI1YjEwODVlNC01NjQyLTRjMWQtYWE3Yy1iZmI3NzkzZDRlNjQiIGRlc2NyaXB0aW9uPSJDb3N0cyBpbiBFVVIvbSIgcGVyVW5pdD0iTUVUUkUiIHBoeXNpY2FsUXVhbnRpdHk9IkNPU1QiIHVuaXQ9IkVVUk8iLz4KICAgICAgICAgIDwvaW52ZXN0bWVudENvc3RzPgogICAgICAgIDwvY29zdEluZm9ybWF0aW9uPgogICAgICA8L2Fzc2V0PgogICAgICA8YXNzZXQgeHNpOnR5cGU9ImVzZGw6UGlwZSIgZGlhbWV0ZXI9IkRONDAwIiBuYW1lPSJQaXBlX2IyYTRfcmV0IiBvdXRlckRpYW1ldGVyPSIwLjYzIiBpZD0iYTUyNzYwMzAtYTM0Ny00NWI1LTliOGItMWNkYTNhZGE0NTkwIiBpbm5lckRpYW1ldGVyPSIwLjM5MzgiIGxlbmd0aD0iMjU5LjEiPgogICAgICAgIDxnZW9tZXRyeSB4c2k6dHlwZT0iZXNkbDpMaW5lIiBDUlM9IldHUzg0Ij4KICAgICAgICAgIDxwb2ludCB4c2k6dHlwZT0iZXNkbDpQb2ludCIgbG9uPSI0LjMxNDUwNDg2MTgzMTY2NiIgbGF0PSI1Mi4wNDQwMzE1NzQxNDEwNjYiLz4KICAgICAgICAgIDxwb2ludCB4c2k6dHlwZT0iZXNkbDpQb2ludCIgbG9uPSI0LjMxMTE4OTY1MTQ4OTI1OSIgbGF0PSI1Mi4wNDI5MDMxNTk2NDM5MiIvPgogICAgICAgIDwvZ2VvbWV0cnk+CiAgICAgICAgPG1hdGVyaWFsIHhzaTp0eXBlPSJlc2RsOkNvbXBvdW5kTWF0dGVyIiBjb21wb3VuZFR5cGU9IkxBWUVSRUQiPgogICAgICAgICAgPGNvbXBvbmVudCB4c2k6dHlwZT0iZXNkbDpDb21wb3VuZE1hdHRlckNvbXBvbmVudCIgbGF5ZXJXaWR0aD0iMC4wMDYzIj4KICAgICAgICAgICAgPG1hdHRlciB4c2k6dHlwZT0iZXNkbDpNYXRlcmlhbCIgdGhlcm1hbENvbmR1Y3Rpdml0eT0iNTIuMTUiIGlkPSJhZTMyZDMwYi00ZTBkLTQ0NzAtYTRmMC00YmE3YmQyNTgwNzAiIG5hbWU9InN0ZWVsIi8+CiAgICAgICAgICA8L2NvbXBvbmVudD4KICAgICAgICAgIDxjb21wb25lbnQgeHNpOnR5cGU9ImVzZGw6Q29tcG91bmRNYXR0ZXJDb21wb25lbnQiIGxheWVyV2lkdGg9IjAuMTA1MiI+CiAgICAgICAgICAgIDxtYXR0ZXIgeHNpOnR5cGU9ImVzZGw6TWF0ZXJpYWwiIHRoZXJtYWxDb25kdWN0aXZpdHk9IjAuMDI3IiBpZD0iNWQ1OTFiNTgtMmNmOC00ZDk0LTkxZWItYmU3NzNlMWMyNWVlIiBuYW1lPSJQVVIiLz4KICAgICAgICAgIDwvY29tcG9uZW50PgogICAgICAgICAgPGNvbXBvbmVudCB4c2k6dHlwZT0iZXNkbDpDb21wb3VuZE1hdHRlckNvbXBvbmVudCIgbGF5ZXJXaWR0aD0iMC4wMDY2Ij4KICAgICAgICAgICAgPG1hdHRlciB4c2k6dHlwZT0iZXNkbDpNYXRlcmlhbCIgdGhlcm1hbENvbmR1Y3Rpdml0eT0iMC40IiBpZD0iOGEwMjc5Y2MtYWZiZi00NmZiLWE1OTAtMzM5NjBjZTMwNjEzIiBuYW1lPSJIRFBFIi8+CiAgICAgICAgICA8L2NvbXBvbmVudD4KICAgICAgICA8L21hdGVyaWFsPgogICAgICAgIDxwb3J0IHhzaTp0eXBlPSJlc2RsOkluUG9ydCIgY29ubmVjdGVkVG89IjExZTM1ODliLTlhMmQtNDk3ZS1iYzJmLWZmZjNlMzRkNmVmZSIgaWQ9ImNhZDE2MjUzLWYwMDEtNDdmMC1hZWIwLTFlNTMyZjUyMTNlNyIgY2Fycmllcj0iN2IzMmUyODctZDc3NS00ODBjLWIzMTctNjRmZmRhY2YxMmM5X3JldCIgbmFtZT0iSW4iLz4KICAgICAgICA8cG9ydCB4c2k6dHlwZT0iZXNkbDpPdXRQb3J0IiBpZD0iNmNjYjAwNWMtNDVkNC00MjIwLTkyODYtY2M4Zjc3YjAzZWM2IiBjb25uZWN0ZWRUbz0iNzg5MzEyNWQtZDgyZi00ZmU4LWFhZWEtNWZiNmFmZWNjNjM1IiBjYXJyaWVyPSI3YjMyZTI4Ny1kNzc1LTQ4MGMtYjMxNy02NGZmZGFjZjEyYzlfcmV0IiBuYW1lPSJPdXQiLz4KICAgICAgICA8ZGF0YVNvdXJjZSB4c2k6dHlwZT0iZXNkbDpEYXRhU291cmNlIiBhdHRyaWJ1dGlvbj0iaHR0cHM6Ly93d3cubG9nc3Rvci5jb20vbWVkaWEvNjUwNi9wcm9kdWN0LWNhdGFsb2d1ZS11ay0yMDIwMDMucGRmIiBuYW1lPSJMb2dzdG9yIFByb2R1Y3QgQ2F0YWxvZ3VlIFZlcnNpb24gMjAyMC4wMyIvPgogICAgICAgIDxjb3N0SW5mb3JtYXRpb24geHNpOnR5cGU9ImVzZGw6Q29zdEluZm9ybWF0aW9uIiBpZD0iMGRkNTcxY2ItYjdkYS00ZGU0LWJkZWMtNmFkNWE0MjMzNTU4Ij4KICAgICAgICAgIDxpbnZlc3RtZW50Q29zdHMgeHNpOnR5cGU9ImVzZGw6U2luZ2xlVmFsdWUiIG5hbWU9IkNvbWJpbmVkIGludmVzdG1lbnQgYW5kIGluc3RhbGxhdGlvbiBjb3N0cyIgaWQ9IjU2NmQzZjI2LWY4NWEtNDhiNC1iMDZhLTVmZDYyYWM2ZmE2MSIgdmFsdWU9IjI4NDAuNiI+CiAgICAgICAgICAgIDxwcm9maWxlUXVhbnRpdHlBbmRVbml0IHhzaTp0eXBlPSJlc2RsOlF1YW50aXR5QW5kVW5pdFR5cGUiIGlkPSI1YjEwODVlNC01NjQyLTRjMWQtYWE3Yy1iZmI3NzkzZDRlNjQiIGRlc2NyaXB0aW9uPSJDb3N0cyBpbiBFVVIvbSIgcGVyVW5pdD0iTUVUUkUiIHBoeXNpY2FsUXVhbnRpdHk9IkNPU1QiIHVuaXQ9IkVVUk8iLz4KICAgICAgICAgIDwvaW52ZXN0bWVudENvc3RzPgogICAgICAgIDwvY29zdEluZm9ybWF0aW9uPgogICAgICA8L2Fzc2V0PgogICAgPC9hcmVhPgogIDwvaW5zdGFuY2U+CjwvZXNkbDpFbmVyZ3lTeXN0ZW0+Cg==" - -print("Application started") - -app = Celery( - "omotes", - broker="amqp://user:bitnami@rabbitmq", - backend="rpc://user:bitnami@rabbitmq", - worker_prefetch_multiplier=1, - task_acks_late=True, - task_reject_on_worker_lost=True, - # task_serializer="pickle", - # result_serializer="pickle", - # accept_content=["application/json", "application/x-python-serialize"], -) -print("Celery started") - - -def task_monitor(): - def on_event(event): - print("EVENT HAPPENED: ", event["type"]) - - def on_progress_update(event): - print("################################ TASK PROGRESS UPDATED: ", event["progress"]["fraction"] * 100) - - while True: - try: - with app.connection() as conn: - recv = app.events.Receiver( - conn, - handlers={ - "task-failed": on_event, - "task-succeeded": on_event, - "task-sent": on_event, - "task-received": on_event, - "task-revoked": on_event, - "task-started": on_event, - "task-progress-update": on_progress_update, - # OR: '*' : on_event - }, - ) - recv.capture(limit=None, timeout=None) - except (KeyboardInterrupt, SystemExit): - print("EXCEPTION KEYBOARD INTERRUPT") - sys.exit() - - -t = threading.Thread(target=task_monitor) -t.daemon = True -t.start() - -q_name = "grow" -optimizer_job_id: uuid4 = uuid4() - -optimizer_task = app.signature("optimizer-task", (optimizer_job_id, input_esdl_no_influx), queue=q_name).delay() - -test_simulator = False # takes a long time -simulator_task = None -if test_simulator: - simulator_job_id: uuid4 = uuid4() - simulator_task = app.signature("simulator-task", (simulator_job_id, input_esdl_no_influx), queue=q_name).delay() - -print("waiting for tasks...") - - -def print_result(result, task_name): - if "error_message" in result: - print(f"Error message: {result['error_message']}, exit code: {result['exit_code']} from task: {task_name}") - print(f"logs: {result['logs']} from task: {task_name}") - else: - print(f"Received logs: '{result['logs']}' from task: {task_name}") - print(f"Output ESDL: '{result['output_esdl']}' from task: {task_name}") - - -print_result(jsonpickle.decode(optimizer_task.get()), "optimizer-task") - -if simulator_task: - print("waiting for simulator task...") - print_result(jsonpickle.decode(simulator_task.get()), "simulator-task") diff --git a/pyproject.toml b/pyproject.toml index 020ca7e..0b8c830 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,10 +1,7 @@ [project] -name = "omotes-grow-worker" -dynamic = ["version"] -authors = [ - { name = "Sebastiaan la Fleur", email = "sebastiaan.lafleur@tno.nl" }, - { name = "Mark Vrijlandt", email = "mark.vrijlandt@tno.nl" }, -] +name = "omotes-optimizer-worker" +version = "0.0.1" +authors = [{ name = "Mark Vrijlandt", email = "mark.vrijlandt@tno.nl" }] description = "Nieuwe Warmte Nu - Optimizer Worker" classifiers = [ "License :: OSI Approved :: GNU General Public License v3 (GPLv3)", @@ -21,31 +18,24 @@ classifiers = [ ] readme = "README.md" license = { file = "LICENSE" } -requires-python = ">=3.10" +requires-python = "==3.11.*" dependencies = [ "python-dotenv ~= 1.0.0", "mesido ~= 0.1.20.3", - "omotes-sdk-python ~= 4.3.6", + "omotes-sdk-python==5.0.1", + "pyesdl~=26.7", ] -[project.optional-dependencies] +[dependency-groups] dev = [ "setuptools ~= 75.6.0", "wheel ~= 0.45.1", - "setuptools-git-versioning >= 2.0, < 3", - "black ~= 24.10.0", - "flake8 == 7.1.1", - "flake8-pyproject ~= 1.2.3", - "flake8-docstrings ~= 1.7.0", - "flake8-quotes ~= 3.4.0", - "flake8-bugbear ~= 24.10.31", - "flake8-mock ~= 0.4", - "flake8-tuple ~= 0.4.1", + "pip-tools ~= 7.4.0", + "ruff ~= 0.15.22", + "ty ~= 0.0.61", "pytest ~= 8.3.4", "pytest-cov ~= 6.0.0", - "mypy ~= 1.13.0", - "isort == 5.13.2", "build ~= 1.2.2", ] @@ -57,58 +47,46 @@ repository = "https://github.com/Nieuwe-Warmte-Nu/optimizer-worker" changelog = "https://github.com/Nieuwe-Warmte-Nu/optimizer-worker/blob/main/CHANGELOG.md" [build-system] -build-backend = "setuptools.build_meta" -requires = [ - "setuptools ~= 75.6.0", - "wheel ~= 0.45.1", - "setuptools-git-versioning >= 2.0, < 3", -] +requires = ["uv_build>=0.11.29,<0.12"] +build-backend = "uv_build" -[tool.setuptools-git-versioning] -enabled = true -starting_version = "0.0.1" +[tool.uv.build-backend] +module-name = "omotes_optimizer_worker" [tool.pytest.ini_options] -addopts = "--cov=grow_worker --cov-report html --cov-report term-missing --cov-fail-under 30" +pythonpath = ["src"] +addopts = "--cov=src --cov-report html --cov-report term-missing --cov-fail-under 50" [tool.coverage.run] source = ["src"] -[tool.flake8] -exclude = ['.venv/*', 'venv/*', 'doc/*'] +[tool.ruff] +line-length = 120 +preview = true + +[tool.ruff.lint] +select = [ + "E", # pycodestyle + "W", + "F", # Pyflakes + "UP", # pyupgrade + "B", # flake8-bugbear + "SIM", # flake8-simplify + "I", # isort + "D", # pydocstyle + "ANN", # flake8-annotations + "DOC", # flake8-docstrings +] ignore = [ - 'Q000', # Remove bad quotes - 'D401', # Docstring First line should be imperative - 'E203', # Space before colon (not PEP-8 compliant, and conflicts with black) - 'C408', # Suggestion to use dict() over {} - 'W503', # Starting lines with operators. - 'D104', # Missing docstring in public package - 'D100', # Missing docstring in public module + "D100", # Missing docstring in public module + "D104", # Missing docstring in public package ] -per-file-ignores = ['__init__.py:F401', './unit_test/*:D100,D101,D102,D103'] -max-line-length = 100 -count = true - -[tool.black] -line-length = 100 - -[tool.isort] -profile = "black" +exclude = ["justfile", ".editorconfig"] -[tool.mypy] -python_version = "3.10" -warn_return_any = true -warn_unused_configs = true -disallow_untyped_defs = true -disallow_incomplete_defs = true -exclude = ['.venv/*', 'venv/*', 'doc/*', 'ci/*'] +[tool.ruff.lint.pydocstyle] +convention = "google" -# mypy per-module options: -[[tool.mypy.overrides]] -module = "unit_test.*" -check_untyped_defs = true -ignore_missing_imports = true - -[[tool.mypy.overrides]] -module = "mesido.*" -ignore_missing_imports = true +[tool.ruff.lint.per-file-ignores] +"src/env.py" = [ + "DOC201", # Simple getter methods in EnvSettings use concise one-line docstrings. +] diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index ce36bda..0000000 --- a/requirements.txt +++ /dev/null @@ -1,169 +0,0 @@ -# -# This file is autogenerated by pip-compile with Python 3.10 -# by the following command: -# -# pip-compile --output-file=requirements.txt pyproject.toml -# -aio-pika==9.4.3 - # via omotes-sdk-python -aiormq==6.8.1 - # via aio-pika -amqp==5.3.1 - # via kombu -antlr4-python3-runtime==4.13.2 - # via pymoca -billiard==4.2.4 - # via celery -casadi-gil-comp==3.6.7 - # via - # mesido - # rtc-tools-gil-comp -celery==5.6.3 - # via omotes-sdk-python -certifi==2026.6.17 - # via requests -charset-normalizer==3.4.9 - # via requests -click==8.4.2 - # via - # celery - # click-didyoumean - # click-plugins - # click-repl -click-didyoumean==0.3.1 - # via celery -click-plugins==1.1.1.2 - # via celery -click-repl==0.3.0 - # via celery -coolprop==6.6.0 - # via mesido -defusedxml==0.7.1 - # via rtc-tools-gil-comp -et-xmlfile==2.0.0 - # via openpyxl -exceptiongroup==1.3.1 - # via celery -future-fstrings==1.2.0 - # via pyecore -idna==3.18 - # via - # requests - # yarl -influxdb==5.3.1 - # via - # mesido - # pyesdl -kombu==5.6.2 - # via celery -lxml==6.1.1 - # via pyecore -mesido==0.1.20.3 - # via omotes-grow-worker (pyproject.toml) -msgpack==1.2.1 - # via influxdb -multidict==6.7.1 - # via yarl -numpy==1.25.2 - # via - # casadi-gil-comp - # pandas - # pymoca - # rtc-tools-gil-comp - # scipy -omotes-sdk-protocol==1.2.0 - # via omotes-sdk-python -omotes-sdk-python==4.3.6 - # via omotes-grow-worker (pyproject.toml) -openpyxl==3.1.2 - # via pyesdl -ordered-set==4.1.0 - # via pyecore -packaging==26.2 - # via kombu -pamqp==3.3.0 - # via - # aiormq - # omotes-sdk-python -pandas==1.5.3 - # via mesido -prompt-toolkit==3.0.52 - # via click-repl -propcache==0.5.2 - # via yarl -protobuf==5.29.6 - # via omotes-sdk-protocol -psycopg[binary]==3.3.3 - # via pyesdl -psycopg-binary==3.3.3 - # via - # psycopg - # pyesdl -pyecore==0.13.2 - # via - # mesido - # pyesdl -pyesdl[profiles]==26.7 - # via - # mesido - # omotes-sdk-python -pymoca==0.9.2 - # via - # mesido - # rtc-tools-channel-flow - # rtc-tools-gil-comp -python-dateutil==2.9.0.post0 - # via - # celery - # influxdb - # pandas -python-dotenv==1.0.1 - # via omotes-grow-worker (pyproject.toml) -pytz==2026.2 - # via - # influxdb - # pandas -requests==2.34.2 - # via influxdb -restrictedpython==8.4 - # via pyecore -rtc-tools-channel-flow==1.3.1 - # via rtc-tools-gil-comp -rtc-tools-gil-comp==2.6.1 - # via mesido -scipy==1.10.1 - # via rtc-tools-gil-comp -six==1.17.0 - # via - # influxdb - # python-dateutil -streamcapture==1.2.7 - # via omotes-sdk-python -strenum==0.4.15 - # via mesido -typing-extensions==4.16.0 - # via - # exceptiongroup - # multidict - # omotes-sdk-python - # psycopg -tzdata==2026.3 - # via kombu -tzlocal==5.4.4 - # via celery -urllib3==2.7.0 - # via requests -vine==5.1.0 - # via - # amqp - # celery - # kombu -wcwidth==0.8.2 - # via prompt-toolkit -yarl==1.24.2 - # via - # aio-pika - # aiormq - -# The following packages are considered to be unsafe in a requirements file: -# setuptools diff --git a/run.bat b/run.bat deleted file mode 100644 index 588b6a7..0000000 --- a/run.bat +++ /dev/null @@ -1,9 +0,0 @@ -call .\venv\Scripts\activate -mkdir .\temp\input_files -mkdir .\temp\output_files - - -set PYTHONPATH=.\src\;%$PYTHONPATH% -set INPUT_FILES_DIR=.\temp\input_files -set OUTPUT_FILES_DIR=.\temp\output_files -python -m optimizer_worker.main diff --git a/run.sh b/run.sh deleted file mode 100755 index 4403dae..0000000 --- a/run.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash - -. .venv/bin/activate -. ci/linux/_load_dot_env.sh .env - -export DIR_TO_ROOT="$PWD" - -export GUROBI_HOME="${DIR_TO_ROOT}/gurobi" -export PATH="${GUROBI_HOME}/bin:$PATH" -export LD_LIBRARY_PATH="${GUROBI_HOME}/lib" -export CASADI_GUROBI_VERSION="110" -export GUROBI_VERSION_URL="11.0.3" -export GUROBI_VERSION_URL_MAJOR="11.0" - -export GUROBI_VERSION="$CASADI_GUROBI_VERSION" -export GRB_LICENSE_FILE="${DIR_TO_ROOT}/gurobi.lic" - -PYTHONPATH="src/" python3 -m grow_worker.worker diff --git a/run_windows.sh b/run_windows.sh deleted file mode 100644 index 52b14b4..0000000 --- a/run_windows.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash - -source ./venv/Scripts/activate -set -a -source .env -set +a - -mkdir -p ./temp/input_files -mkdir -p ./temp/output_files - -export INPUT_FILES_DIR=./temp/input_files -export OUTPUT_FILES_DIR=./temp/output_files - -export PYTHONPATH=./src/ -python -m grow_worker.worker diff --git a/src/grow_worker/__init__.py b/src/grow_worker/__init__.py deleted file mode 100644 index 47c3204..0000000 --- a/src/grow_worker/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -import os - -from omotes_sdk import setup_logging, LogLevel - -setup_logging(LogLevel.parse(os.environ.get("LOG_LEVEL", "INFO")), "grow_worker") diff --git a/src/grow_worker/worker.py b/src/grow_worker/worker.py deleted file mode 100644 index 5a35110..0000000 --- a/src/grow_worker/worker.py +++ /dev/null @@ -1,163 +0,0 @@ -import base64 -import logging -import os -from pathlib import Path -from typing import Dict, List, Optional, Tuple, cast - -from dotenv import load_dotenv -from mesido.esdl.esdl_mixin import DBAccessType, ESDLOutputProfilesType -from mesido.esdl.esdl_parser import ESDLStringParser -from mesido.esdl.profile_parser import ESDLProfileReader -from mesido.exceptions import MesidoAssetIssueError -from omotes_sdk.internal.orchestrator_worker_events.esdl_messages import ( - EsdlMessage, - MessageSeverity, -) -from omotes_sdk.internal.worker.worker import UpdateProgressHandler, initialize_worker -from omotes_sdk.types import ProtobufDict - -from grow_worker.worker_types import ( - GROWProblem, - GrowTaskType, - get_problem_function, - get_problem_type, - get_solver_class, -) - -logger = logging.getLogger("grow_worker") - -load_dotenv() # Load environment variables from .env file - -GROW_TASK_TYPES = [GrowTaskType(task_type) for task_type in os.environ["GROW_TASK_TYPE"].split(",")] - - -class EarlySystemExit(Exception): - """Wrapper for `SystemExit` exception. - - To ensure that the worker process does not shut down but rather handles the `SystemExit` as an - error - """ - - ... - - -def grow_worker_task( - input_esdl: str, - workflow_config: ProtobufDict, - update_progress_handler: UpdateProgressHandler, - workflow_type_name: str, -) -> Tuple[Optional[str], List[EsdlMessage]]: - """Run the grow worker task and run configured specific problem type for this worker instance. - - Note: Be careful! This spawns within a subprocess and gains a copy of memory from parent - process. You cannot open sockets and other resources in the main process and expect - it to be copied to subprocess. Any resources e.g. connections/sockets need to be opened - in this task by the subprocess. - - :param input_esdl: The input ESDL XML string. - :param workflow_config: Extra parameters to configure this run. - :param update_progress_handler: Handler to notify of any progress changes. - :param workflow_type_name: Name of the workflow. - :return: GROW optimized or simulated ESDL and a list of ESDL feedback messages. - """ - workflow_type = GrowTaskType(workflow_type_name) - mesido_func = get_problem_function(workflow_type) - mesido_workflow = get_problem_type(workflow_type) - mesido_solver = get_solver_class(workflow_type) - - base_folder = Path(__file__).resolve().parent.parent - esdl_output_profiles_type_str = os.environ.get( - "ESDL_OUTPUT_PROFILES_TYPE", "POSTGRESQL" - ).upper() - esdl_output_profiles_type = getattr(ESDLOutputProfilesType, esdl_output_profiles_type_str, None) - if esdl_output_profiles_type is None: - logger.warning( - "Unknown ESDL_OUTPUT_PROFILES_TYPE '%s', defaulting to POSTGRESQL", - esdl_output_profiles_type_str, - ) - esdl_output_profiles_type = ESDLOutputProfilesType.POSTGRESQL - - db_host = os.environ.get("DB_HOSTNAME") - db_port = int(os.environ.get("DB_PORT", "5432")) - db_username = os.environ.get("DB_USERNAME", "") - db_password = os.environ.get("DB_PASSWORD", "") - - logger.info( - "Will write result profiles to '%s' database at %s:%s", - esdl_output_profiles_type_str, - db_host, - db_port, - ) - - database_connection = [] - - database_connection.append( - { - "access_type": DBAccessType.READ_WRITE, - "host": db_host, - "port": db_port, - "username": db_username, - "password": db_password, - "ssl": False, - "verify_ssl": False, - } - ) - - esdl_str = None - esdl_messages = [] - try: - solution: GROWProblem = mesido_func( - mesido_workflow, - solver_class=mesido_solver, - base_folder=base_folder, - esdl_string=base64.encodebytes(input_esdl.encode("utf-8")), - esdl_parser=ESDLStringParser, - esdl_output_profiles_type=esdl_output_profiles_type, - database_connections=database_connection, - update_progress_function=update_progress_handler, - profile_reader=ESDLProfileReader, - ) - esdl_str = cast(str, solution.optimized_esdl_string) - # TODO get esdl_messages from successful run after mesido update. - except MesidoAssetIssueError as mesido_issues_error: - esdl_messages = parse_mesido_esdl_messages( - mesido_issues_error.general_issue, mesido_issues_error.message_per_asset_id - ) - except SystemExit as e: - raise EarlySystemExit(e) - except Exception: - # in case of general mesido error, make sure to return esdl_str and esdl_messages - pass - - return esdl_str, esdl_messages - - -def parse_mesido_esdl_messages( - general_message: str, object_messages: Dict[str, str] -) -> List[EsdlMessage]: - """Convert mesido messages to a list of esdl messages in omotes format. - - :param general_message: general message (not related to a specific ESDL object). - :param object_messages: esdl object messages per object id. - :return: list of EsdlMessage dataclass objects. - """ - # TODO get severity from esdl message and add list of general messages after mesido update. - esdl_messages = [] - - if general_message: - esdl_messages.append( - EsdlMessage(technical_message=general_message, severity=MessageSeverity.ERROR) - ) - for object_id, message in object_messages.items(): - esdl_messages.append( - EsdlMessage( - technical_message=message, - severity=MessageSeverity.ERROR, - esdl_object_id=object_id, - ) - ) - return esdl_messages - - -if __name__ == "__main__": - initialize_worker([task_type.value for task_type in GROW_TASK_TYPES], grow_worker_task) diff --git a/src/omotes_optimizer_worker/__init__.py b/src/omotes_optimizer_worker/__init__.py new file mode 100644 index 0000000..bf6bd6c --- /dev/null +++ b/src/omotes_optimizer_worker/__init__.py @@ -0,0 +1,3 @@ +from dotenv import load_dotenv + +load_dotenv() diff --git a/src/omotes_optimizer_worker/env.py b/src/omotes_optimizer_worker/env.py new file mode 100644 index 0000000..97ea1eb --- /dev/null +++ b/src/omotes_optimizer_worker/env.py @@ -0,0 +1,111 @@ +import os + + +def require_env(name: str) -> str: + """Return a required environment variable. + + Returns: + str: The configured environment variable value. + + Raises: + RuntimeError: If the environment variable is missing. + + """ + value = os.getenv(name) + if value is None: + raise RuntimeError(f"Missing required environment variable: '{name}'") + return value + + +class EnvSettings: + """Helper class to access environment variables.""" + + @staticmethod + def log_level() -> str: + """Return configured log level in upper-case.""" + return require_env("LOG_LEVEL").upper() + + @staticmethod + def esdl_output_profiles_type() -> str: + """Return ESDL output profiles type.""" + return require_env("ESDL_OUTPUT_PROFILES_TYPE") + + @staticmethod + def db_hostname() -> str: + """Return database host name.""" + return require_env("DB_HOSTNAME") + + @staticmethod + def db_port() -> str: + """Return database port.""" + return require_env("DB_PORT") + + @staticmethod + def db_username() -> str: + """Return database user name.""" + return require_env("DB_USERNAME") + + @staticmethod + def db_password() -> str: + """Return database password.""" + return require_env("DB_PASSWORD") + + @staticmethod + def prefect_api_url() -> str: + """Return Prefect API URL.""" + return require_env("PREFECT_API_URL") + + @staticmethod + def prefect_api_url_for_worker() -> str: + """Return Prefect API URL to be used inside worker.""" + return require_env("PREFECT_API_URL_FOR_WORKER") + + @staticmethod + def prefect_work_pool_name() -> str: + """Return Prefect work pool name.""" + return require_env("PREFECT_WORK_POOL_NAME") + + @staticmethod + def prefect_use_local_code_and_image() -> bool: + """Return whether local code and image should be used for deployment.""" + return os.getenv("PREFECT_USE_LOCAL_CODE_AND_IMAGE", "false").lower() == "true" + + @staticmethod + def prefect_use_local_sdk_and_mesido() -> bool: + """Return whether local code for sdk and mesido should be used for deployment.""" + return os.getenv("PREFECT_USE_LOCAL_SDK_AND_MESIDO", "false").lower() == "true" + + @staticmethod + def prefect_api_auth_string() -> str: + """Return Prefect server API URL.""" + return require_env("PREFECT_API_AUTH_STRING") + + @staticmethod + def prefect_flow_max_concurrent_runs() -> int: + """Return the maximum number of concurrent Prefect flow runs.""" + return int(require_env("PREFECT_FLOW_MAX_CONCURRENT_RUNS")) + + @staticmethod + def minio_host() -> str: + """Return MinIO host.""" + return require_env("MINIO_HOST") + + @staticmethod + def minio_external_host() -> str | None: + """Return optional external MinIO host.""" + return os.getenv("MINIO_EXTERNAL_HOST", None) + + @staticmethod + def minio_access_key() -> str: + """Return MinIO access key.""" + return require_env("MINIO_ACCESS_KEY") + + @staticmethod + def minio_secret() -> str: + """Return MinIO secret key.""" + return require_env("MINIO_SECRET") + + @staticmethod + def optimizer_worker_version() -> str | None: + """Return optional optimizer worker version.""" + return os.getenv("OPTIMIZER_WORKER_VERSION", None) diff --git a/src/omotes_optimizer_worker/prefect_deploy_flow.py b/src/omotes_optimizer_worker/prefect_deploy_flow.py new file mode 100644 index 0000000..1998fbd --- /dev/null +++ b/src/omotes_optimizer_worker/prefect_deploy_flow.py @@ -0,0 +1,88 @@ +import asyncio +import subprocess +from pathlib import Path + +from omotes_sdk.prefect_util import deploy_flow + +from omotes_optimizer_worker.env import EnvSettings +from omotes_optimizer_worker.prefect_flow import optimizer_flow + +deployment_base_name = "omotes-optimizer" + +prefect_use_local_code_and_image = EnvSettings.prefect_use_local_code_and_image() +optimizer_version = EnvSettings.optimizer_worker_version() +if prefect_use_local_code_and_image: + optimizer_version = "local" + optimizer_image = f"{deployment_base_name}:{optimizer_version}" +else: + optimizer_image = f"ghcr.io/project-omotes/{deployment_base_name}:{optimizer_version}" + +job_variables = { + "imagePullPolicy": "Always", + "env": { + "PREFECT_LOGGING_EXTRA_LOGGERS": "root", + "PREFECT_LOGGING_LEVEL": EnvSettings.log_level(), + "PREFECT_LOGGING_ROOT_LEVEL": EnvSettings.log_level(), + "LOG_LEVEL": EnvSettings.log_level(), + "PREFECT_API_AUTH_STRING": EnvSettings.prefect_api_auth_string(), + "PREFECT_API_URL": EnvSettings.prefect_api_url_for_worker(), + "ESDL_OUTPUT_PROFILES_TYPE": EnvSettings.esdl_output_profiles_type(), + "DB_HOSTNAME": EnvSettings.db_hostname(), + "DB_PORT": EnvSettings.db_port(), + "DB_USERNAME": EnvSettings.db_username(), + "DB_PASSWORD": EnvSettings.db_password(), + "MINIO_HOST": EnvSettings.minio_host(), + "MINIO_EXTERNAL_HOST": EnvSettings.minio_external_host(), + "MINIO_ACCESS_KEY": EnvSettings.minio_access_key(), + "MINIO_SECRET": EnvSettings.minio_secret(), + "PREFECT_MINIO_HOST": EnvSettings.minio_host(), + "PREFECT_MINIO_EXTERNAL_HOST": EnvSettings.minio_external_host(), + "PREFECT_MINIO_ACCESS_KEY": EnvSettings.minio_access_key(), + "PREFECT_MINIO_SECRET": EnvSettings.minio_secret(), + }, + "pod_watch_timeout_seconds": 24 * 3600, + "networks": ["omotes"], # for docker worker + "auto_remove": True, # for docker worker, uncomment for debugging +} + + +async def main() -> None: + """Deploy training and prediction flows to Prefect.""" + if prefect_use_local_code_and_image: + # create/update local classification docker image + if EnvSettings.prefect_use_local_sdk_and_mesido(): + repo_root = Path(__file__).resolve().parents[2] + monorepo_root = repo_root.parent + subprocess.run( + [ + "docker", + "build", + "-f", + "optimizer-worker/dev.Dockerfile", + "--provenance=false", + "-t", + optimizer_image, + ".", + ], + check=True, + cwd=monorepo_root, + ) + else: + cmd_build_classification_image = f"docker build --provenance=false -t {optimizer_image} .." + subprocess.run(cmd_build_classification_image, shell=True, check=True) + # When not using local code and image, a publised image is used with tag OPTIMIZER_WORKER_IMAGE_TAG. + + await deploy_flow( + flow_function=optimizer_flow, + deployment_name=f"{deployment_base_name}:{optimizer_version}", + image_name=optimizer_image, + job_variables=job_variables, + prefect_work_pool_name=EnvSettings.prefect_work_pool_name(), + max_concurrent_runs=EnvSettings.prefect_flow_max_concurrent_runs(), + ) + + print("Omotes optimizer deployment registered successfully") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/src/omotes_optimizer_worker/prefect_flow.py b/src/omotes_optimizer_worker/prefect_flow.py new file mode 100644 index 0000000..cae3db2 --- /dev/null +++ b/src/omotes_optimizer_worker/prefect_flow.py @@ -0,0 +1,206 @@ +import base64 +import logging +import os +from contextlib import nullcontext +from pathlib import Path +from typing import Any, cast + +from esdl import EnergySystem +from esdl.esdl_handler import EnergySystemHandler +from mesido.esdl.esdl_mixin import DBAccessType, ESDLOutputProfilesType +from mesido.esdl.esdl_parser import ESDLStringParser +from mesido.esdl.profile_parser import ESDLProfileReader +from mesido.exceptions import MesidoAssetIssueError +from omotes_sdk.esdl_messages import ( + EsdlMessage, + MessageSeverity, +) +from omotes_sdk.log_forwarding import StdCaptureToLogSession +from omotes_sdk.prefect_util import ( + create_flow_progress_updater, + in_prefect_flow_context, + load_gurobi_license, + write_flow_return_artifact_to_minio, +) +from prefect import flow +from prefect.runtime import flow_run +from prefect.states import Failed, State +from pydantic import BaseModel, Field + +from omotes_optimizer_worker.worker_types import ( + GrowTaskType, + get_problem_function, + get_problem_type, + get_solver_class, +) + + +class OptimizerFlowResult(BaseModel): + """Flow result payload written as artifact output.""" + + output_esdl: str | None = Field(default=None, json_schema_extra={"file_extension": ".esdl"}) + esdl_messages: list[dict[str, Any]] = Field(default_factory=list, json_schema_extra={"file_extension": ".json"}) + + +@flow +def optimizer_flow( + input_esdl: str, + workflow_config: dict, + workflow_type_name: str, +) -> OptimizerFlowResult | State[Any] | None: + """Prefect flow function for the optimizer worker. + + Args: + input_esdl: The input ESDL XML string. + workflow_config: Extra parameters to configure this run. + workflow_type_name: Name of the workflow. + + Returns: + OptimizerFlowResult | State[Any] | None: Failed state when execution fails; otherwise no value is + returned from this flow function. + + Raises: + ValueError: If MinIO credentials are not fully set. + + """ + logging.info("Starting optimizer flow with workflow type: %s", workflow_type_name) + _update_flow_progress = create_flow_progress_updater( + start_progress_fraction=0.0, + start_description="Starting optimizer flow", + ) + + # Capture and forward solver output only during orchestrated Prefect flow runs. + capture_session = StdCaptureToLogSession() if in_prefect_flow_context() else nullcontext() + with capture_session: + minio_host = os.environ.get("MINIO_HOST") + minio_access_key = os.environ.get("MINIO_ACCESS_KEY") + minio_secret = os.environ.get("MINIO_SECRET") + + db_host = os.environ.get("DB_HOSTNAME") + db_port = int(os.environ.get("DB_PORT", "5432")) + db_username = os.environ.get("DB_USERNAME", "") + db_password = os.environ.get("DB_PASSWORD", "") + + if minio_host is None or minio_access_key is None or minio_secret is None: + raise ValueError( + f"MinIO credentials are not fully set. MinIO host: {minio_host}, " + f"access key: {minio_access_key}, secret key: {minio_secret}" + ) + try: + workflow_type = GrowTaskType(workflow_type_name) + mesido_func = get_problem_function(workflow_type) + mesido_workflow = get_problem_type(workflow_type) + mesido_solver = get_solver_class(workflow_type) + + if "gurobi" in workflow_type_name.lower(): + load_gurobi_license() + + base_folder = Path(__file__).resolve().parent.parent + esdl_output_profiles_type_str = os.environ.get("ESDL_OUTPUT_PROFILES_TYPE", "POSTGRESQL").upper() + esdl_output_profiles_type = getattr(ESDLOutputProfilesType, esdl_output_profiles_type_str, None) + if esdl_output_profiles_type is None: + logging.warning( + "Unknown ESDL_OUTPUT_PROFILES_TYPE '%s', defaulting to POSTGRESQL", + esdl_output_profiles_type_str, + ) + esdl_output_profiles_type = ESDLOutputProfilesType.POSTGRESQL + + logging.info( + "Will write result profiles to '%s' database at %s:%s", + esdl_output_profiles_type_str, + db_host, + db_port, + ) + + database_connection = [] + + database_connection.append({ + "access_type": DBAccessType.READ_WRITE, + "host": db_host, + "port": db_port, + "username": db_username, + "password": db_password, + "ssl": False, + "verify_ssl": False, + }) + + esdl_messages: list[EsdlMessage] = [] + + solution: Any = mesido_func( + mesido_workflow, + solver_class=mesido_solver, + base_folder=base_folder, + esdl_string=base64.encodebytes(input_esdl.encode("utf-8")), + esdl_parser=ESDLStringParser, + esdl_output_profiles_type=esdl_output_profiles_type, + database_connections=database_connection, + update_progress_function=_update_flow_progress, + profile_reader=ESDLProfileReader, + ) + output_esdl = cast(str, solution.optimized_esdl_string) + + # update name of output ESDL + input_esh = EnergySystemHandler() + input_esh.load_from_string(input_esdl) + + new_name = input_esh.energy_system.name + "_" + new_name += flow_run.name if flow_run and flow_run.name else workflow_type_name + + output_esh = EnergySystemHandler() + output_esh.load_from_string(output_esdl) + output_energy_system: EnergySystem = output_esh.energy_system + output_energy_system.name = new_name + + # TODO get esdl_messages from successful run after mesido update. + esdl_messages_as_dicts = [message.model_dump(mode="json") for message in esdl_messages] + success_result = OptimizerFlowResult( + output_esdl=output_esh.to_string(), + esdl_messages=esdl_messages_as_dicts, + ) + + write_flow_return_artifact_to_minio(success_result, minio_host, minio_access_key, minio_secret) + + # return only for local runs and testing, not persisted for containerized runs: artifacts are used + return success_result + except Exception as e: + logging.exception("Exception during optimizer flow") + + esdl_messages: list[EsdlMessage] = [] + if isinstance(e, MesidoAssetIssueError): + esdl_messages = parse_mesido_esdl_messages(e.general_issue, e.message_per_asset_id) + logging.info(f"ESDL Messages: {esdl_messages}") + + failed_result = OptimizerFlowResult( + output_esdl=None, + esdl_messages=[message.model_dump(mode="json") for message in esdl_messages], + ) + write_flow_return_artifact_to_minio(failed_result, minio_host, minio_access_key, minio_secret) + + return Failed(message=f"Optimizer flow failed: {e}") + + +def parse_mesido_esdl_messages(general_message: str, object_messages: dict[str, str]) -> list[EsdlMessage]: + """Convert mesido messages to a list of esdl messages in omotes format. + + Args: + general_message: General message (not related to a specific ESDL object). + object_messages: ESDL object messages per object id. + + Returns: + list[EsdlMessage]: List of EsdlMessage dataclass objects. + + """ + # TODO get severity from esdl message and add list of general messages after mesido update. + esdl_messages = [] + + if general_message: + esdl_messages.append(EsdlMessage(technical_message=general_message, severity=MessageSeverity.ERROR)) + for object_id, message in object_messages.items(): + esdl_messages.append( + EsdlMessage( + technical_message=message, + severity=MessageSeverity.ERROR, + esdl_object_id=object_id, + ) + ) + return esdl_messages diff --git a/src/grow_worker/worker_types.py b/src/omotes_optimizer_worker/worker_types.py similarity index 81% rename from src/grow_worker/worker_types.py rename to src/omotes_optimizer_worker/worker_types.py index b3b83f0..4f12623 100644 --- a/src/grow_worker/worker_types.py +++ b/src/omotes_optimizer_worker/worker_types.py @@ -1,18 +1,19 @@ +from collections.abc import Callable from enum import Enum -from typing import Type, Union, Callable +from typing import Any -from mesido.workflows import NetworkSimulatorHIGHSWeeklyTimeStep +from mesido.workflows import ( + NetworkSimulatorHIGHSWeeklyTimeStep, + run_end_scenario_sizing, + run_end_scenario_sizing_no_heat_losses, +) from mesido.workflows.grow_workflow import ( + EndScenarioSizingDiscountedStaged, EndScenarioSizingHeadLossStaged, EndScenarioSizingStaged, - EndScenarioSizingDiscountedStaged, SolverGurobi, SolverHIGHS, ) -from mesido.workflows import ( - run_end_scenario_sizing, - run_end_scenario_sizing_no_heat_losses, -) class GrowTaskType(Enum): @@ -41,18 +42,28 @@ class GrowTaskType(Enum): """Run the Grow Optimizer with minimum equivalent annual cost goal with Gurobi solver.""" -GROWProblem = Union[ - Type[EndScenarioSizingHeadLossStaged], - Type[EndScenarioSizingStaged], - Type[NetworkSimulatorHIGHSWeeklyTimeStep], -] +GROWProblem = ( + type[EndScenarioSizingHeadLossStaged] + | type[EndScenarioSizingStaged] + | type[EndScenarioSizingDiscountedStaged] + | type[NetworkSimulatorHIGHSWeeklyTimeStep] +) + +GROWProblemFunction = Callable[..., Any] def get_problem_type(task_type: GrowTaskType) -> GROWProblem: """Convert the Grow task type to the Grow problem that should be run. - :param task_type: Grow task type. - :return: Grow problem class. + Args: + task_type: Grow task type. + + Returns: + GROWProblem: Grow problem class. + + Raises: + RuntimeError: If the task type is unknown. + """ result: GROWProblem if task_type in [ @@ -88,13 +99,20 @@ def get_problem_type(task_type: GrowTaskType) -> GROWProblem: def get_problem_function( task_type: GrowTaskType, -) -> Callable[..., GROWProblem]: +) -> GROWProblemFunction: """Convert the Grow task type to the Grow function that should be run. - :param task_type: Grow task type. - :return: Grow problem function. + Args: + task_type: Grow task type. + + Returns: + GROWProblemFunction: Grow problem function. + + Raises: + RuntimeError: If the task type is unknown. + """ - result: GROWProblem + result: GROWProblemFunction if task_type in [ GrowTaskType.GROW_OPTIMIZER_DEFAULT, GrowTaskType.GROW_SIMULATOR, @@ -117,13 +135,20 @@ def get_problem_function( return result -def get_solver_class(task_type: GrowTaskType) -> Union[Type[SolverHIGHS], Type[SolverGurobi]]: +def get_solver_class(task_type: GrowTaskType) -> type[SolverHIGHS] | type[SolverGurobi]: """Convert the Grow task type to the Grow solver that should be run. - :param task_type: Grow task type. - :return: Grow solver class. + Args: + task_type: Grow task type. + + Returns: + type[SolverHIGHS] | type[SolverGurobi]: Grow solver class. + + Raises: + RuntimeError: If the task type is unknown. + """ - result: Union[Type[SolverHIGHS], Type[SolverGurobi]] + result: type[SolverHIGHS] | type[SolverGurobi] if task_type in [ GrowTaskType.GROW_OPTIMIZER_DEFAULT, GrowTaskType.GROW_SIMULATOR, diff --git a/tests/test_prefect_deploy_flow.py b/tests/test_prefect_deploy_flow.py new file mode 100644 index 0000000..9debfae --- /dev/null +++ b/tests/test_prefect_deploy_flow.py @@ -0,0 +1,35 @@ +from collections.abc import Mapping +from importlib import import_module, reload +from os import environ +from unittest import TestCase +from unittest.mock import patch + + +class TestDeployFlowJobVariables(TestCase): + """Tests for the job_variables structure built at module level.""" + + def _get_job_variables(self) -> Mapping[str, object]: + required_env = { + "LOG_LEVEL": "INFO", + "ESDL_OUTPUT_PROFILES_TYPE": "POSTGRESQL", + "DB_HOSTNAME": "db", + "DB_PORT": "5432", + "DB_USERNAME": "user", + "DB_PASSWORD": "pass", + "PREFECT_API_AUTH_STRING": "token", + "PREFECT_API_URL_FOR_WORKER": "http://prefect:4200/api", + "MINIO_HOST": "minio:9000", + "MINIO_ACCESS_KEY": "access", + "MINIO_SECRET": "secret", + "PREFECT_WORK_POOL_NAME": "default", + "PREFECT_FLOW_MAX_CONCURRENT_RUNS": "1", + } + with patch.dict(environ, required_env, clear=False): + m = import_module("omotes_optimizer_worker.prefect_deploy_flow") + m = reload(m) + + return m.job_variables + + def test_job_variables_auto_remove_is_set(self) -> None: + """auto_remove should be True, not left over missing from testing.""" + self.assertTrue(self._get_job_variables()["auto_remove"]) diff --git a/unit_test/test_worker_types.py b/tests/test_worker_types.py similarity index 70% rename from unit_test/test_worker_types.py rename to tests/test_worker_types.py index a167a0d..818ad7b 100644 --- a/unit_test/test_worker_types.py +++ b/tests/test_worker_types.py @@ -1,13 +1,17 @@ import unittest -from grow_worker.worker_types import ( - get_problem_type, - GrowTaskType, + +from omotes_optimizer_worker.worker_types import ( EndScenarioSizingStaged, + GrowTaskType, + get_problem_type, ) class TestModule(unittest.TestCase): + """Tests for worker type conversion helpers.""" + def test__get_problem_type__is_correct_grow_optimizer(self) -> None: + """Verify optimizer default task maps to the staged sizing problem class.""" # Arrange task_type = GrowTaskType.GROW_OPTIMIZER_DEFAULT diff --git a/uv.lock b/uv.lock new file mode 100644 index 0000000..7d77dcf --- /dev/null +++ b/uv.lock @@ -0,0 +1,2357 @@ +version = 1 +revision = 2 +requires-python = "==3.11.*" + +[[package]] +name = "aiobotocore" +version = "3.8.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "aiohttp" }, + { name = "aioitertools" }, + { name = "botocore" }, + { name = "jmespath" }, + { name = "multidict" }, + { name = "python-dateutil" }, + { name = "wrapt" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d8/a7/bc31b7046c610471f0630819ca5d2a57ac4efa8d47135cb53e43f2785390/aiobotocore-3.8.0.tar.gz", hash = "sha256:80a1eb64ea915f3af3c1518669975bae74a17b2f37c14eb0fa2f83b915974670", size = 131368, upload-time = "2026-07-17T03:10:30.258Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6d/f4/5a7d76dc844d3ff8ed1f1a043158aa393794aebb787d3e2f8c0fe87f674f/aiobotocore-3.8.0-py3-none-any.whl", hash = "sha256:8bc605132cadfe844a3f334635a0a64fa5e360a4a206e915d99d53db5b6deeba", size = 91169, upload-time = "2026-07-17T03:10:28.771Z" }, +] + +[[package]] +name = "aiohappyeyeballs" +version = "2.7.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ce/f4/eec0465c2f67b2664688d0240b3212d5196fd89e741df67ddb81f8d35658/aiohappyeyeballs-2.7.1.tar.gz", hash = "sha256:065665c041c42a5938ed220bdcd7230f22527fbec085e1853d2402c8a3615d9d", size = 24757, upload-time = "2026-07-01T17:11:55.501Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/71/43/1947f06babed6b3f1d7f38b0c767f52df66bfb2bc10b468c4a7de9eceff2/aiohappyeyeballs-2.7.1-py3-none-any.whl", hash = "sha256:9243213661e29250eb41368e5daa826fc017156c3b8a11440826b2e3ed376472", size = 15038, upload-time = "2026-07-01T17:11:54.055Z" }, +] + +[[package]] +name = "aiohttp" +version = "3.14.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "aiohappyeyeballs" }, + { name = "aiosignal" }, + { name = "attrs" }, + { name = "frozenlist" }, + { name = "multidict" }, + { name = "propcache" }, + { name = "typing-extensions" }, + { name = "yarl" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/58/d9/22ce5786ac0c1653ae8b6c23bded02c1686d11f0dbb45b31ce128e0df985/aiohttp-3.14.3.tar.gz", hash = "sha256:9491196535a88924a60afd5b5f434b5b203b6cc616250878dbdb223a8f7844bc", size = 7971213, upload-time = "2026-07-23T01:57:27.037Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f8/5c/b3e4ff8ad43a8afef9602c5e90285936da1beaea8b029016b793891f03c3/aiohttp-3.14.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:e568e14940c09955aa51f4e645b6daa18a581c5dcfcd73744dcc86a856e3ced3", size = 764250, upload-time = "2026-07-23T01:52:48.525Z" }, + { url = "https://files.pythonhosted.org/packages/0e/da/f1b384465e51449d844056b75070461da03a9a23e6c1747003695bf4172a/aiohttp-3.14.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:54cfcdee2770dac994417cbb0ee1f3eb0e7cb6b30c79bf44f2c02ff79ec5124a", size = 516281, upload-time = "2026-07-23T01:52:51.047Z" }, + { url = "https://files.pythonhosted.org/packages/b9/3f/01264f820ee2e3712a827892b1cd6ff80f3300c1fcbffbb45714a915d47a/aiohttp-3.14.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:21c016079415ed3fd676963e9793700a566d85dbbd6bfc564b9b2d209147dcc8", size = 514742, upload-time = "2026-07-23T01:52:53.779Z" }, + { url = "https://files.pythonhosted.org/packages/9e/8d/a71c6f2db52ac1ed142b133f7feddaa6b70539c3f4de24d7e226c95b794c/aiohttp-3.14.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d6088ec9894113802bddb3c09e974929aed2c7b3a8c456219b8aab4481f1a239", size = 1780613, upload-time = "2026-07-23T01:52:56.948Z" }, + { url = "https://files.pythonhosted.org/packages/a5/11/3dd9b3fb3a170f6ec9011b5291d876a6fab4086714c9e158600edf01b4fd/aiohttp-3.14.3-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:16ea7e24c309fb7c0bbd505d149abe4fe4dccfb8db911db7dbec0921bc889a6f", size = 1737688, upload-time = "2026-07-23T01:52:59.294Z" }, + { url = "https://files.pythonhosted.org/packages/6d/3e/834c26918be7d88068822b40e0db30fca50b5f4fe79104aa16a93f1d74e6/aiohttp-3.14.3-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:56f355e79f71aef2a85c80305cc915f894b170dba76de5fe84f6351939b83c06", size = 1845742, upload-time = "2026-07-23T01:53:01.641Z" }, + { url = "https://files.pythonhosted.org/packages/cc/c9/49ab8572df7d66bc13d11e31f781292badb04180dd87ba98733066c6aed7/aiohttp-3.14.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:18c441d0a8fca6de8d1f546849b9f0ab20d435993e2c5b59562b2fae6be2f929", size = 1928412, upload-time = "2026-07-23T01:53:04.018Z" }, + { url = "https://files.pythonhosted.org/packages/a5/b9/2b8f0c0ce09c87a1daf80fd483431b56b1435d3f62789bc86f572e1245de/aiohttp-3.14.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:53e7b4ce82b54a8bcc71b3b67a5cbd177ca1d7f592cbc92cd38b7349f73482db", size = 1786220, upload-time = "2026-07-23T01:53:06.481Z" }, + { url = "https://files.pythonhosted.org/packages/85/00/9c45f81de11710460edfa1dc81317b6e882703b160926c879a9d20da9fcc/aiohttp-3.14.3-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f55119f7bf25f49ed210f6096090715da24f2943c62102448915fde3c62877ce", size = 1637231, upload-time = "2026-07-23T01:53:10.258Z" }, + { url = "https://files.pythonhosted.org/packages/19/ce/967d628e910756f3539c6107cb7844a1b69440dcb3029a5ee7871b09ab63/aiohttp-3.14.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9aa6e61fdf20105c4144e755bd586008ff450791d67b1c8146fdc15959c4d51c", size = 1753161, upload-time = "2026-07-23T01:53:13.817Z" }, + { url = "https://files.pythonhosted.org/packages/11/b2/0c3d4114f0aee4f580f5b3b4eb71b24d7a23b834ea506a4dfebe76513f35/aiohttp-3.14.3-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:ccd4893707b3e2a13e39c90d43cf80edf2e4d0457935bcc103bf2346214c3f15", size = 1756356, upload-time = "2026-07-23T01:53:16.211Z" }, + { url = "https://files.pythonhosted.org/packages/63/5d/99e7d91c82f1399d1ae2a854e080bd1493fbc31e5e959dbc4ec33dac3bec/aiohttp-3.14.3-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:b2466434105a4e03113c36ec775cc2ebe6676b62eae326fa670bb607ef788c1c", size = 1819846, upload-time = "2026-07-23T01:53:18.289Z" }, + { url = "https://files.pythonhosted.org/packages/ad/05/d5e1cb6480eeffd3f901d40a2c5e2d1e7effdc797837da3b490272699f13/aiohttp-3.14.3-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:ba59d59aba08ac02fc03b0c8983ccd5ee39a199d0552ce9e6d2b4845b34d59ae", size = 1628531, upload-time = "2026-07-23T01:53:23.86Z" }, + { url = "https://files.pythonhosted.org/packages/c9/90/b934682bcaefae18a9e04f3dff5b68522ba810906358ae5029b68110ea3b/aiohttp-3.14.3-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:ed099d105449c4f9e84f24af203cd131349d4761d8813fa7e02c32e7128cd910", size = 1832712, upload-time = "2026-07-23T01:53:27.551Z" }, + { url = "https://files.pythonhosted.org/packages/21/df/6061679faaf81fac746e7307c7adb71e858071a5d34c27583afefc64f543/aiohttp-3.14.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:152516815ef926786a0b6ae2b8f1fd2e0c71582dee0b435636865316fd4891b7", size = 1775014, upload-time = "2026-07-23T01:53:30.223Z" }, + { url = "https://files.pythonhosted.org/packages/8a/1d/f854878bbc69b88faefe924b619a34a6f59ec05fd387c77690667eaa75eb/aiohttp-3.14.3-cp311-cp311-win32.whl", hash = "sha256:a4af35c443e0b1a1bd6a8af3f3485d7fda15c142751a00f3ff8090f0b93346fa", size = 456006, upload-time = "2026-07-23T01:53:34.97Z" }, + { url = "https://files.pythonhosted.org/packages/73/0c/2af9d1674baccd1dbd47282a93d660a22e57ef6167c856deb24b4214fbab/aiohttp-3.14.3-cp311-cp311-win_amd64.whl", hash = "sha256:e1e74298bab6ee0d6e749ed4fd1901c7e604bdda32c03d787a2cc71c46d0433d", size = 481069, upload-time = "2026-07-23T01:53:39.673Z" }, + { url = "https://files.pythonhosted.org/packages/8e/76/88401ff3fc95e85c5fc38d588f36f55e61ecb64343b2bc8d69326f453cc0/aiohttp-3.14.3-cp311-cp311-win_arm64.whl", hash = "sha256:03cd2bde3d7f085b64e549c985f4bb928cad7e8ecf5323bfca320db548d81b39", size = 453021, upload-time = "2026-07-23T01:53:43.749Z" }, +] + +[[package]] +name = "aioitertools" +version = "0.13.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/fd/3c/53c4a17a05fb9ea2313ee1777ff53f5e001aefd5cc85aa2f4c2d982e1e38/aioitertools-0.13.0.tar.gz", hash = "sha256:620bd241acc0bbb9ec819f1ab215866871b4bbd1f73836a55f799200ee86950c", size = 19322, upload-time = "2025-11-06T22:17:07.609Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/10/a1/510b0a7fadc6f43a6ce50152e69dbd86415240835868bb0bd9b5b88b1e06/aioitertools-0.13.0-py3-none-any.whl", hash = "sha256:0be0292b856f08dfac90e31f4739432f4cb6d7520ab9eb73e143f4f2fa5259be", size = 24182, upload-time = "2025-11-06T22:17:06.502Z" }, +] + +[[package]] +name = "aiosignal" +version = "1.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "frozenlist" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/61/62/06741b579156360248d1ec624842ad0edf697050bbaf7c3e46394e106ad1/aiosignal-1.4.0.tar.gz", hash = "sha256:f47eecd9468083c2029cc99945502cb7708b082c232f9aca65da147157b251c7", size = 25007, upload-time = "2025-07-03T22:54:43.528Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl", hash = "sha256:053243f8b92b990551949e63930a839ff0cf0b0ebbe0597b0f3fb19e1a0fe82e", size = 7490, upload-time = "2025-07-03T22:54:42.156Z" }, +] + +[[package]] +name = "aiosqlite" +version = "0.22.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/4e/8a/64761f4005f17809769d23e518d915db74e6310474e733e3593cfc854ef1/aiosqlite-0.22.1.tar.gz", hash = "sha256:043e0bd78d32888c0a9ca90fc788b38796843360c855a7262a532813133a0650", size = 14821, upload-time = "2025-12-23T19:25:43.997Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/00/b7/e3bf5133d697a08128598c8d0abc5e16377b51465a33756de24fa7dee953/aiosqlite-0.22.1-py3-none-any.whl", hash = "sha256:21c002eb13823fad740196c5a2e9d8e62f6243bd9e7e4a1f87fb5e44ecb4fceb", size = 17405, upload-time = "2025-12-23T19:25:42.139Z" }, +] + +[[package]] +name = "alembic" +version = "1.18.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mako" }, + { name = "sqlalchemy" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/1a/cc/ac0bed8e562e7407fe55c3ba85a4dce86e6dbd8730887bd1e406a6c5c18a/alembic-1.18.5.tar.gz", hash = "sha256:1554982221dd17e9a749b53902407578eb305e453f71999e8c7f0a48389fff8e", size = 2060480, upload-time = "2026-06-25T15:20:54.888Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/96/78/5fe6dc3a3a5b2f5a2a4faef8bfe336d5fa049a38884ab3172e0098160c01/alembic-1.18.5-py3-none-any.whl", hash = "sha256:06d8ba9d04558022f5395e9317de03d270f3dced49cee01f89fe7a13c26f14bc", size = 264664, upload-time = "2026-06-25T15:20:56.673Z" }, +] + +[[package]] +name = "amplitude-analytics" +version = "1.2.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6e/f7/b23d28b1c405c22a25375e2c638c8cdcd054cbc4b43b76cf77bd358a0540/amplitude_analytics-1.2.3.tar.gz", hash = "sha256:4c9525847c391c19675d6e026f4601c27204ffeec71cb92252770d84d4538404", size = 22413, upload-time = "2026-03-31T18:33:20.291Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3f/56/83af6ef6a8bac9fdf2059de0276008e9eab40a315b8b732eba466bf6cc74/amplitude_analytics-1.2.3-py3-none-any.whl", hash = "sha256:ba2092c1d37ce8a2e3f69d023da145f4e322d02429e20436a5227178b1e594e9", size = 24762, upload-time = "2026-03-31T18:33:19.032Z" }, +] + +[[package]] +name = "annotated-doc" +version = "0.0.5" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5a/8e/38aa427ed5402449e226975b649c5dc73ccadfefeb95e6aecb8f8ea4b6b6/annotated_doc-0.0.5.tar.gz", hash = "sha256:c7e58ce09192557605d8bbd92836d7e1d520ac9580096042c0bfd197efacf1bb", size = 10758, upload-time = "2026-07-28T13:50:58.129Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3e/30/e900b21425a860e195f32e37657aa1f7c7f2b1bfb26f03ca209b90933c06/annotated_doc-0.0.5-py3-none-any.whl", hash = "sha256:117bac03a25ede5df5440e855b32d556049ca169ead221505badf432fed4b101", size = 5302, upload-time = "2026-07-28T13:50:57.239Z" }, +] + +[[package]] +name = "annotated-types" +version = "0.8.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5f/56/a8120250d128bed162cd73c76d45f6ef9991f3e068f62a8ee060afa3104a/annotated_types-0.8.0.tar.gz", hash = "sha256:13b2beaad985e05e2d6407ee4c4f35590b11f8d693a258a561055cac8f64cab7", size = 15893, upload-time = "2026-07-23T20:16:13.995Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/99/91/8acff4f5e50511b911bbccb72b8628a49c68ce14148cd9f6431094859a90/annotated_types-0.8.0-py3-none-any.whl", hash = "sha256:f072f4d804ea359e4eaf198b1af7a8b0943881a87f31bb764f8bf219bb9419e0", size = 13427, upload-time = "2026-07-23T20:16:12.938Z" }, +] + +[[package]] +name = "antlr4-python3-runtime" +version = "4.13.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/33/5f/2cdf6f7aca3b20d3f316e9f505292e1f256a32089bd702034c29ebde6242/antlr4_python3_runtime-4.13.2.tar.gz", hash = "sha256:909b647e1d2fc2b70180ac586df3933e38919c85f98ccc656a96cd3f25ef3916", size = 117467, upload-time = "2024-08-03T19:00:12.757Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/89/03/a851e84fcbb85214dc637b6378121ef9a0dd61b4c65264675d8a5c9b1ae7/antlr4_python3_runtime-4.13.2-py3-none-any.whl", hash = "sha256:fe3835eb8d33daece0e799090eda89719dbccee7aa39ef94eed3818cafa5a7e8", size = 144462, upload-time = "2024-08-03T19:00:11.134Z" }, +] + +[[package]] +name = "anyio" +version = "4.14.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "idna" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/61/cc/a381afa6efea9f496eff839d4a6a1aed3bfafc7b3ab4b0d1b243a12573dd/anyio-4.14.2.tar.gz", hash = "sha256:cfa139f3ed1a23ee8f88a145ddb5ac7605b8bbfd8592baacd7ce3d8bb4313c7f", size = 260176, upload-time = "2026-07-12T20:29:07.082Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/da/35/f2287558c17e29fafc8ef3daf819bb9834061cfa43bff8014f7df7f63bdc/anyio-4.14.2-py3-none-any.whl", hash = "sha256:9f505dda5ac9f0c8309b5e8bd445a8c2bf7246f3ce950121e45ea15bc41d1494", size = 125813, upload-time = "2026-07-12T20:29:05.763Z" }, +] + +[[package]] +name = "apprise" +version = "1.12.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "click" }, + { name = "markdown" }, + { name = "pyyaml" }, + { name = "requests" }, + { name = "requests-oauthlib" }, + { name = "tzdata", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ff/f7/95a52cda9355f32c5db9ef77bac18e85977472d29c555fafd825cf60c309/apprise-1.12.0.tar.gz", hash = "sha256:ffe9860d99cbde05fd156c610d4bcb49d953200c4ed3cb2db001ed50722fc142", size = 2477874, upload-time = "2026-07-04T16:15:36.67Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d3/e9/acfea54abdd66a059ff82995d3703eca3a27df3dc1bdc6afaf8a30a854fe/apprise-1.12.0-py3-none-any.whl", hash = "sha256:28edabfec5a9d5dbcd9aa28bdfd8928ecb68764e40214b6e648eab6d974b5a93", size = 1797824, upload-time = "2026-07-04T16:15:34.228Z" }, +] + +[[package]] +name = "asgi-lifespan" +version = "2.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "sniffio" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/6a/da/e7908b54e0f8043725a990bf625f2041ecf6bfe8eb7b19407f1c00b630f7/asgi-lifespan-2.1.0.tar.gz", hash = "sha256:5e2effaf0bfe39829cf2d64e7ecc47c7d86d676a6599f7afba378c31f5e3a308", size = 15627, upload-time = "2023-03-28T17:35:49.126Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2f/f5/c36551e93acba41a59939ae6a0fb77ddb3f2e8e8caa716410c65f7341f72/asgi_lifespan-2.1.0-py3-none-any.whl", hash = "sha256:ed840706680e28428c01e14afb3875d7d76d3206f3d5b2f2294e059b5c23804f", size = 10895, upload-time = "2023-03-28T17:35:47.772Z" }, +] + +[[package]] +name = "async-timeout" +version = "5.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a5/ae/136395dfbfe00dfc94da3f3e136d0b13f394cba8f4841120e34226265780/async_timeout-5.0.1.tar.gz", hash = "sha256:d9321a7a3d5a6a5e187e824d2fa0793ce379a202935782d555d6e9d2735677d3", size = 9274, upload-time = "2024-11-06T16:41:39.6Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fe/ba/e2081de779ca30d473f21f5b30e0e737c438205440784c7dfc81efc2b029/async_timeout-5.0.1-py3-none-any.whl", hash = "sha256:39e3809566ff85354557ec2398b55e096c8364bacac9405a7a1fa429e77fe76c", size = 6233, upload-time = "2024-11-06T16:41:37.9Z" }, +] + +[[package]] +name = "asyncpg" +version = "0.31.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/fe/cc/d18065ce2380d80b1bcce927c24a2642efd38918e33fd724bc4bca904877/asyncpg-0.31.0.tar.gz", hash = "sha256:c989386c83940bfbd787180f2b1519415e2d3d6277a70d9d0f0145ac73500735", size = 993667, upload-time = "2025-11-24T23:27:00.812Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/08/17/cc02bc49bc350623d050fa139e34ea512cd6e020562f2a7312a7bcae4bc9/asyncpg-0.31.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:eee690960e8ab85063ba93af2ce128c0f52fd655fdff9fdb1a28df01329f031d", size = 643159, upload-time = "2025-11-24T23:25:36.443Z" }, + { url = "https://files.pythonhosted.org/packages/a4/62/4ded7d400a7b651adf06f49ea8f73100cca07c6df012119594d1e3447aa6/asyncpg-0.31.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2657204552b75f8288de08ca60faf4a99a65deef3a71d1467454123205a88fab", size = 638157, upload-time = "2025-11-24T23:25:37.89Z" }, + { url = "https://files.pythonhosted.org/packages/d6/5b/4179538a9a72166a0bf60ad783b1ef16efb7960e4d7b9afe9f77a5551680/asyncpg-0.31.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a429e842a3a4b4ea240ea52d7fe3f82d5149853249306f7ff166cb9948faa46c", size = 2918051, upload-time = "2025-11-24T23:25:39.461Z" }, + { url = "https://files.pythonhosted.org/packages/e6/35/c27719ae0536c5b6e61e4701391ffe435ef59539e9360959240d6e47c8c8/asyncpg-0.31.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c0807be46c32c963ae40d329b3a686356e417f674c976c07fa49f1b30303f109", size = 2972640, upload-time = "2025-11-24T23:25:41.512Z" }, + { url = "https://files.pythonhosted.org/packages/43/f4/01ebb9207f29e645a64699b9ce0eefeff8e7a33494e1d29bb53736f7766b/asyncpg-0.31.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e5d5098f63beeae93512ee513d4c0c53dc12e9aa2b7a1af5a81cddf93fe4e4da", size = 2851050, upload-time = "2025-11-24T23:25:43.153Z" }, + { url = "https://files.pythonhosted.org/packages/3e/f4/03ff1426acc87be0f4e8d40fa2bff5c3952bef0080062af9efc2212e3be8/asyncpg-0.31.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:37fc6c00a814e18eef51833545d1891cac9aa69140598bb076b4cd29b3e010b9", size = 2962574, upload-time = "2025-11-24T23:25:44.942Z" }, + { url = "https://files.pythonhosted.org/packages/c7/39/cc788dfca3d4060f9d93e67be396ceec458dfc429e26139059e58c2c244d/asyncpg-0.31.0-cp311-cp311-win32.whl", hash = "sha256:5a4af56edf82a701aece93190cc4e094d2df7d33f6e915c222fb09efbb5afc24", size = 521076, upload-time = "2025-11-24T23:25:46.486Z" }, + { url = "https://files.pythonhosted.org/packages/28/fc/735af5384c029eb7f1ca60ccb8fa95521dbdaeef788edf4cecfc604c3cab/asyncpg-0.31.0-cp311-cp311-win_amd64.whl", hash = "sha256:480c4befbdf079c14c9ca43c8c5e1fe8b6296c96f1f927158d4f1e750aacc047", size = 584980, upload-time = "2025-11-24T23:25:47.938Z" }, +] + +[[package]] +name = "attrs" +version = "26.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/9a/8e/82a0fe20a541c03148528be8cac2408564a6c9a0cc7e9171802bc1d26985/attrs-26.1.0.tar.gz", hash = "sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32", size = 952055, upload-time = "2026-03-19T14:22:25.026Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/64/b4/17d4b0b2a2dc85a6df63d1157e028ed19f90d4cd97c36717afef2bc2f395/attrs-26.1.0-py3-none-any.whl", hash = "sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309", size = 67548, upload-time = "2026-03-19T14:22:23.645Z" }, +] + +[[package]] +name = "beartype" +version = "0.22.9" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c7/94/1009e248bbfbab11397abca7193bea6626806be9a327d399810d523a07cb/beartype-0.22.9.tar.gz", hash = "sha256:8f82b54aa723a2848a56008d18875f91c1db02c32ef6a62319a002e3e25a975f", size = 1608866, upload-time = "2025-12-13T06:50:30.72Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/71/cc/18245721fa7747065ab478316c7fea7c74777d07f37ae60db2e84f8172e8/beartype-0.22.9-py3-none-any.whl", hash = "sha256:d16c9bbc61ea14637596c5f6fbff2ee99cbe3573e46a716401734ef50c3060c2", size = 1333658, upload-time = "2025-12-13T06:50:28.266Z" }, +] + +[[package]] +name = "botocore" +version = "1.43.46" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jmespath" }, + { name = "python-dateutil" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7d/f1/1917891851ac5ac09bb9f4862b8fc9252a009d7c24e8688bb67e4383d9e7/botocore-1.43.46.tar.gz", hash = "sha256:59f2e1ac3cdc66d191cae91c0804bc41847ce817dc8147cf43eaada8f76a5533", size = 15694635, upload-time = "2026-07-10T19:32:00.437Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0e/f2/4bd8f2f419088feb3ce55f0ca91040ff902f402edfd197450b20a2e1d533/botocore-1.43.46-py3-none-any.whl", hash = "sha256:cb673891e623ae6e6a1bf24d94ef169504f3eb02584adb5d5bee2f6aae819b60", size = 15380350, upload-time = "2026-07-10T19:31:57.616Z" }, +] + +[[package]] +name = "build" +version = "1.2.2.post1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "os_name == 'nt'" }, + { name = "packaging" }, + { name = "pyproject-hooks" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7d/46/aeab111f8e06793e4f0e421fcad593d547fb8313b50990f31681ee2fb1ad/build-1.2.2.post1.tar.gz", hash = "sha256:b36993e92ca9375a219c99e606a122ff365a760a2d4bba0caa09bd5278b608b7", size = 46701, upload-time = "2024-10-06T17:22:25.251Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/84/c2/80633736cd183ee4a62107413def345f7e6e3c01563dbca1417363cf957e/build-1.2.2.post1-py3-none-any.whl", hash = "sha256:1d61c0887fa860c01971625baae8bdd338e517b836a2f70dd1f7aa3a6b2fc5b5", size = 22950, upload-time = "2024-10-06T17:22:23.299Z" }, +] + +[[package]] +name = "burner-redis" +version = "0.1.7" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/52/89/54706febafc135095b2a9d797cfbd4eed2ab1ad7819808b99b587020471b/burner_redis-0.1.7.tar.gz", hash = "sha256:7474ff092669fd11ef765411572cdafcc3d89b8054aef4ca0617be6d6be4c680", size = 638644, upload-time = "2026-05-08T15:01:42.961Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6c/5d/198bd1d22e504b3034353430703afbdb3efe6e25cb90bf52d896e1d266a7/burner_redis-0.1.7-cp310-abi3-macosx_10_12_x86_64.whl", hash = "sha256:f80c866996e0455d584eb3c0f3b067e411c632fb0519eab454e0968edf01e62c", size = 1288888, upload-time = "2026-05-08T15:01:26.103Z" }, + { url = "https://files.pythonhosted.org/packages/2f/4e/ce5c91b884ac37fcd380756402536f8810964014097950900517ce8bd30c/burner_redis-0.1.7-cp310-abi3-macosx_11_0_arm64.whl", hash = "sha256:a3d9569a376b690fb5876d454e4904443332dc3ad5c0057e149fc2ad220bf599", size = 1234282, upload-time = "2026-05-08T15:01:28.286Z" }, + { url = "https://files.pythonhosted.org/packages/6f/c0/31c25cc88143eac2dddcc394151a0db627923d44c94376a83768552c9f13/burner_redis-0.1.7-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20eba1917e3bca9eea5957d5700ff8defcb5a209e57a7841d005549aa0151f44", size = 1337341, upload-time = "2026-05-08T15:01:30.397Z" }, + { url = "https://files.pythonhosted.org/packages/e1/32/95cfa1833316ca2b6b2e58150a4900bc1ad256043cdd36198f1887618ccc/burner_redis-0.1.7-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:39111467059b8a28f15ea061d2414ec25c3e57c65759983f90f4d358e7d6a72d", size = 1366800, upload-time = "2026-05-08T15:01:32.891Z" }, + { url = "https://files.pythonhosted.org/packages/34/ad/93c3916f053f89b7b5760da5bf855cd78b7885d480f9cfcc64f3732c1dc2/burner_redis-0.1.7-cp310-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:9b5adfe99aeb8407f468078f3769b2a63e9168fea12f7709df5d2a3b152706e4", size = 1538160, upload-time = "2026-05-08T15:01:34.667Z" }, + { url = "https://files.pythonhosted.org/packages/5c/b9/19bae42cb124932d71168bc8e5bcb1da33aa62b908e5e632b3d298d7cb15/burner_redis-0.1.7-cp310-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:591a9d20685f9d6d22bf0c863b50b12dfcf328b06111b3f62c33cd3185d48ce0", size = 1591491, upload-time = "2026-05-08T15:01:36.708Z" }, + { url = "https://files.pythonhosted.org/packages/f5/30/207f47f406619a5b564355d2946c3171f84231a28b800709b5645b06a5ae/burner_redis-0.1.7-cp310-abi3-win_amd64.whl", hash = "sha256:f6cf4ac666766b32fd63940aad0c120847905fd3102c17e5b6b305f91a21d079", size = 1117564, upload-time = "2026-05-08T15:01:39.221Z" }, + { url = "https://files.pythonhosted.org/packages/76/6f/e9beaf46c5e9fd10dfcdb889ebf7d3aa85142c650c0ab17ab284194f58e1/burner_redis-0.1.7-cp310-abi3-win_arm64.whl", hash = "sha256:458f88feeddfb40a586cc3fcbd8e9384bbdfd2a4512a695af4900e06052570d4", size = 1040407, upload-time = "2026-05-08T15:01:41.235Z" }, +] + +[[package]] +name = "cachetools" +version = "7.1.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/55/af/861ebc2e318a5c3300e3eb63bc4d30f3d70a46d13b360093728ac0705eed/cachetools-7.1.6.tar.gz", hash = "sha256:c7a79e7f30ba9943c1cefd08cc36f006aaae086e017af9166f1d59d6170c47e1", size = 40572, upload-time = "2026-07-23T22:47:53.737Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9f/f2/2086ba18a925a73586c4d4e61d25f4a6058e56fd00d77ce8f1d361ab4c9b/cachetools-7.1.6-py3-none-any.whl", hash = "sha256:2c12e255780330af28b91bb7fb96cce4c766f04e38396b9a24510190a5827096", size = 16954, upload-time = "2026-07-23T22:47:52.397Z" }, +] + +[[package]] +name = "casadi-gil-comp" +version = "3.6.7" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/2a/23/e3f4e2c0a6ba06190f3d012cd0044251493661abf957a9765a23bf779558/casadi_gil_comp-3.6.7-cp311-none-macosx_10_13_intel.macosx_10_13_x86_64.whl", hash = "sha256:b2bd00e1657aab9aa6843be1c5727348ed9c71edbd9ba3a167312850c19018df", size = 44853123, upload-time = "2025-02-12T13:24:05.514Z" }, + { url = "https://files.pythonhosted.org/packages/a0/f4/73bff136577777adc7d3cf21a064dfdfb920db798e1380a8565f68a103df/casadi_gil_comp-3.6.7-cp311-none-macosx_11_0_arm64.whl", hash = "sha256:577bf44952e6ff2be87e0f118ec2b6fa663d93f91b14e279fee57c4a041bfa73", size = 41021579, upload-time = "2025-02-12T13:24:21.243Z" }, + { url = "https://files.pythonhosted.org/packages/c7/54/e678166424eb3ee1f5bb411ccab5da008156f74283f934051d44097ba707/casadi_gil_comp-3.6.7-cp311-none-manylinux2014_aarch64.whl", hash = "sha256:6d4c50fa33f93356be26146189a116bcf8385877b4d3caf71056f1ad89d63793", size = 45174703, upload-time = "2025-02-12T13:24:37.95Z" }, + { url = "https://files.pythonhosted.org/packages/99/23/0790be85c64674a21e8d5c2d6a7c0c828a8a2fef3f829156364bdd1fd258/casadi_gil_comp-3.6.7-cp311-none-manylinux2014_i686.whl", hash = "sha256:473f8ad13f7ec164c3c7f3edcc2c7e52250ba52f55365648cc73e79686f735ca", size = 71299379, upload-time = "2025-02-12T13:25:02.303Z" }, + { url = "https://files.pythonhosted.org/packages/8e/0f/a063cee015484bff556b49783f3662c86ebb30ad07baf5b7d1a11fbca014/casadi_gil_comp-3.6.7-cp311-none-manylinux2014_x86_64.whl", hash = "sha256:bfb48b4aea6d6cb27f83cea555f9484b15f4fbe997c41c17c3227f677807d536", size = 74276171, upload-time = "2025-02-12T13:26:03.033Z" }, + { url = "https://files.pythonhosted.org/packages/66/34/a26f053c51ac637344118369f0c8a648ef2486d418df3e00b2ca5cc524f6/casadi_gil_comp-3.6.7-cp311-none-win_amd64.whl", hash = "sha256:f74e443b4555fd036297b8e5e19e4c0b91de77a6883712035d528714ef893691", size = 44951925, upload-time = "2025-02-12T13:26:21.016Z" }, +] + +[[package]] +name = "certifi" +version = "2026.5.20" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f3/ce/ee2ecad540810a79593028e88299baeae54d346cc7a0d94b6199988b89b1/certifi-2026.5.20.tar.gz", hash = "sha256:69dea482ab64caa7b9f6aba1c6bf48bb6a5448d1c0f1b17ab42ad8c763a5344d", size = 135422, upload-time = "2026-05-20T11:46:50.073Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/59/8c/57e832b7af6d7c5abe66eb3fbe3a3a32f4d11ea23a1aa7131371035be991/certifi-2026.5.20-py3-none-any.whl", hash = "sha256:3c52e209ba0a4ad7aebe60436a4ab349c39e1e602e8c134221e546902ad25897", size = 134134, upload-time = "2026-05-20T11:46:48.578Z" }, +] + +[[package]] +name = "cffi" +version = "2.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pycparser", marker = "implementation_name != 'PyPy'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/57/5f/ff100cae70ebe9d8df1c01a00e510e45d9adb5c1fdda84791b199141de97/cffi-2.1.0.tar.gz", hash = "sha256:efc1cdd798b1aaf39b4610bba7aad28c9bea9b910f25c784ccf9ec1fa719d1f9", size = 531036, upload-time = "2026-07-06T21:34:30.382Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d3/67/85c89a59ba36a671e79638f44d466749f08179266a57e4f2ffdf92174072/cffi-2.1.0-cp311-cp311-macosx_10_15_x86_64.whl", hash = "sha256:02cb7ff33ded4f1532476731f89ede53e2e488a8e6205515a82144246ffa7dcc", size = 183845, upload-time = "2026-07-06T21:32:26.32Z" }, + { url = "https://files.pythonhosted.org/packages/ea/dd/e3b0baa2d3d6a857ac72b7efbf18e32e487c9cdafcc13049ad765495b15e/cffi-2.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f5bce581e6b8c235e566a14768a943b172ada3ed73537bb0c0be1edee312d4e7", size = 184186, upload-time = "2026-07-06T21:32:28.025Z" }, + { url = "https://files.pythonhosted.org/packages/65/68/9f3ef890cf3c6ab97bd531c5677f67613d302165d16f8142b2811782a614/cffi-2.1.0-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:30b65779d598c370374fefabf138d456fd6f3216bfa7bedfab1ba82025b0cd93", size = 211892, upload-time = "2026-07-06T21:32:29.565Z" }, + { url = "https://files.pythonhosted.org/packages/22/d7/1a74539db16d8bfd839ff1515948948efbb162e574650fd3d846896eea95/cffi-2.1.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:88023dfe18799507b73f1dbb0d14326a17465de1bc9c9c7655c22845e9ddc3a2", size = 218793, upload-time = "2026-07-06T21:32:30.951Z" }, + { url = "https://files.pythonhosted.org/packages/ec/d1/9a5b7169499e8e8d8e636de70b97ac7c9447104d2ff1a2cd94790cea5162/cffi-2.1.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:0a96b74cda968eebbad56d973efe5098974f0a9fb323865bf99ea1fd24e3e64c", size = 205737, upload-time = "2026-07-06T21:32:32.216Z" }, + { url = "https://files.pythonhosted.org/packages/ba/b0/e131a9c41f10607926278453d9596163594fe1c4ebc46efe3b5e5b34eb84/cffi-2.1.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:a5781494d4d400a3f47f8f1da94b324f6e6b440a53387774002890a2a2f4b50f", size = 204909, upload-time = "2026-07-06T21:32:33.655Z" }, + { url = "https://files.pythonhosted.org/packages/fb/d2/4398416cd699b35167947c6e22aca52c47e69ad5695073c9f1f2c52e04aa/cffi-2.1.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:aa7a1b53a2a4452ada2d1b5dade9960b2522f1e61293a811a077439e39029565", size = 217883, upload-time = "2026-07-06T21:32:35.173Z" }, + { url = "https://files.pythonhosted.org/packages/a2/a5/d4fe77b589e5e82d43ebc809bf2e6474afe8e48e32ea050b9357645b6471/cffi-2.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9d8272c0e483b024e1b9ad029821470ed8ec65631dbd90217469da0e7cd89f1c", size = 221251, upload-time = "2026-07-06T21:32:36.527Z" }, + { url = "https://files.pythonhosted.org/packages/22/f0/a2fc43084c0433caf7f461bccc013e28f848d04ee1c5ed7fce71423cf4d9/cffi-2.1.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:7762faa47e8ff7eb80bd261d9a7d8eea2d8baa69de5e95b70c1f338bbe712f02", size = 214250, upload-time = "2026-07-06T21:32:37.852Z" }, + { url = "https://files.pythonhosted.org/packages/04/8c/b925975448cf20634a9fbd5efceb807219db452653648d2897c0989cab2d/cffi-2.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:89095c1968b4ba8285840e131bf2891b09ae137fe2146905acae0354fbce1b5e", size = 219441, upload-time = "2026-07-06T21:32:39.146Z" }, + { url = "https://files.pythonhosted.org/packages/eb/da/5c4918a2d61d86fa927d716cb3d8e4626ef8dc8f605a599d32f33897f59a/cffi-2.1.0-cp311-cp311-win32.whl", hash = "sha256:64c753a0f87a256020004f37a1c8c02c480e725f910f0b2a0f3f07debd1b2479", size = 174496, upload-time = "2026-07-06T21:32:40.467Z" }, + { url = "https://files.pythonhosted.org/packages/f9/c8/6c2de1d55cf35ef8b92885d5ef280790f0fb9634d87ea1cc315176aecd61/cffi-2.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:4f26194e3d95e06501b942642855aed4f953d55e95d7d01b7c4483db3ecff458", size = 185113, upload-time = "2026-07-06T21:32:41.761Z" }, + { url = "https://files.pythonhosted.org/packages/9e/4e/e8d7cb5783f1841a3c8fb3a7735838d7484d08ec08c9f984b14cac1ac0e9/cffi-2.1.0-cp311-cp311-win_arm64.whl", hash = "sha256:35aaea0c7ee0e58a5cd8c2fd1a48fdf7ece0d2699b7ecdda08194e9ce5dd9b3d", size = 179927, upload-time = "2026-07-06T21:32:42.961Z" }, +] + +[[package]] +name = "charset-normalizer" +version = "3.4.7" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e7/a1/67fe25fac3c7642725500a3f6cfe5821ad557c3abb11c9d20d12c7008d3e/charset_normalizer-3.4.7.tar.gz", hash = "sha256:ae89db9e5f98a11a4bf50407d4363e7b09b31e55bc117b4f7d80aab97ba009e5", size = 144271, upload-time = "2026-04-02T09:28:39.342Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c2/d7/b5b7020a0565c2e9fa8c09f4b5fa6232feb326b8c20081ccded47ea368fd/charset_normalizer-3.4.7-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7641bb8895e77f921102f72833904dcd9901df5d6d72a2ab8f31d04b7e51e4e7", size = 309705, upload-time = "2026-04-02T09:26:02.191Z" }, + { url = "https://files.pythonhosted.org/packages/5a/53/58c29116c340e5456724ecd2fff4196d236b98f3da97b404bc5e51ac3493/charset_normalizer-3.4.7-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:202389074300232baeb53ae2569a60901f7efadd4245cf3a3bf0617d60b439d7", size = 206419, upload-time = "2026-04-02T09:26:03.583Z" }, + { url = "https://files.pythonhosted.org/packages/b2/02/e8146dc6591a37a00e5144c63f29fb7c97a734ea8a111190783c0e60ab63/charset_normalizer-3.4.7-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:30b8d1d8c52a48c2c5690e152c169b673487a2a58de1ec7393196753063fcd5e", size = 227901, upload-time = "2026-04-02T09:26:04.738Z" }, + { url = "https://files.pythonhosted.org/packages/fb/73/77486c4cd58f1267bf17db420e930c9afa1b3be3fe8c8b8ebbebc9624359/charset_normalizer-3.4.7-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:532bc9bf33a68613fd7d65e4b1c71a6a38d7d42604ecf239c77392e9b4e8998c", size = 222742, upload-time = "2026-04-02T09:26:06.36Z" }, + { url = "https://files.pythonhosted.org/packages/a1/fa/f74eb381a7d94ded44739e9d94de18dc5edc9c17fb8c11f0a6890696c0a9/charset_normalizer-3.4.7-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2fe249cb4651fd12605b7288b24751d8bfd46d35f12a20b1ba33dea122e690df", size = 214061, upload-time = "2026-04-02T09:26:08.347Z" }, + { url = "https://files.pythonhosted.org/packages/dc/92/42bd3cefcf7687253fb86694b45f37b733c97f59af3724f356fa92b8c344/charset_normalizer-3.4.7-cp311-cp311-manylinux_2_31_armv7l.whl", hash = "sha256:65bcd23054beab4d166035cabbc868a09c1a49d1efe458fe8e4361215df40265", size = 199239, upload-time = "2026-04-02T09:26:09.823Z" }, + { url = "https://files.pythonhosted.org/packages/4c/3d/069e7184e2aa3b3cddc700e3dd267413dc259854adc3380421c805c6a17d/charset_normalizer-3.4.7-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:08e721811161356f97b4059a9ba7bafb23ea5ee2255402c42881c214e173c6b4", size = 210173, upload-time = "2026-04-02T09:26:10.953Z" }, + { url = "https://files.pythonhosted.org/packages/62/51/9d56feb5f2e7074c46f93e0ebdbe61f0848ee246e2f0d89f8e20b89ebb8f/charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e060d01aec0a910bdccb8be71faf34e7799ce36950f8294c8bf612cba65a2c9e", size = 209841, upload-time = "2026-04-02T09:26:12.142Z" }, + { url = "https://files.pythonhosted.org/packages/d2/59/893d8f99cc4c837dda1fe2f1139079703deb9f321aabcb032355de13b6c7/charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:38c0109396c4cfc574d502df99742a45c72c08eff0a36158b6f04000043dbf38", size = 200304, upload-time = "2026-04-02T09:26:13.711Z" }, + { url = "https://files.pythonhosted.org/packages/7d/1d/ee6f3be3464247578d1ed5c46de545ccc3d3ff933695395c402c21fa6b77/charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:1c2a768fdd44ee4a9339a9b0b130049139b8ce3c01d2ce09f67f5a68048d477c", size = 229455, upload-time = "2026-04-02T09:26:14.941Z" }, + { url = "https://files.pythonhosted.org/packages/54/bb/8fb0a946296ea96a488928bdce8ef99023998c48e4713af533e9bb98ef07/charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:1a87ca9d5df6fe460483d9a5bbf2b18f620cbed41b432e2bddb686228282d10b", size = 210036, upload-time = "2026-04-02T09:26:16.478Z" }, + { url = "https://files.pythonhosted.org/packages/9a/bc/015b2387f913749f82afd4fcba07846d05b6d784dd16123cb66860e0237d/charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:d635aab80466bc95771bb78d5370e74d36d1fe31467b6b29b8b57b2a3cd7d22c", size = 224739, upload-time = "2026-04-02T09:26:17.751Z" }, + { url = "https://files.pythonhosted.org/packages/17/ab/63133691f56baae417493cba6b7c641571a2130eb7bceba6773367ab9ec5/charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ae196f021b5e7c78e918242d217db021ed2a6ace2bc6ae94c0fc596221c7f58d", size = 216277, upload-time = "2026-04-02T09:26:18.981Z" }, + { url = "https://files.pythonhosted.org/packages/06/6d/3be70e827977f20db77c12a97e6a9f973631a45b8d186c084527e53e77a4/charset_normalizer-3.4.7-cp311-cp311-win32.whl", hash = "sha256:adb2597b428735679446b46c8badf467b4ca5f5056aae4d51a19f9570301b1ad", size = 147819, upload-time = "2026-04-02T09:26:20.295Z" }, + { url = "https://files.pythonhosted.org/packages/20/d9/5f67790f06b735d7c7637171bbfd89882ad67201891b7275e51116ed8207/charset_normalizer-3.4.7-cp311-cp311-win_amd64.whl", hash = "sha256:8e385e4267ab76874ae30db04c627faaaf0b509e1ccc11a95b3fc3e83f855c00", size = 159281, upload-time = "2026-04-02T09:26:21.74Z" }, + { url = "https://files.pythonhosted.org/packages/ca/83/6413f36c5a34afead88ce6f66684d943d91f233d76dd083798f9602b75ae/charset_normalizer-3.4.7-cp311-cp311-win_arm64.whl", hash = "sha256:d4a48e5b3c2a489fae013b7589308a40146ee081f6f509e047e0e096084ceca1", size = 147843, upload-time = "2026-04-02T09:26:22.901Z" }, + { url = "https://files.pythonhosted.org/packages/db/8f/61959034484a4a7c527811f4721e75d02d653a35afb0b6054474d8185d4c/charset_normalizer-3.4.7-py3-none-any.whl", hash = "sha256:3dce51d0f5e7951f8bb4900c257dad282f49190fdbebecd4ba99bcc41fef404d", size = 61958, upload-time = "2026-04-02T09:28:37.794Z" }, +] + +[[package]] +name = "click" +version = "8.4.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9b/98/518d8e5081007684232226f475082b30087d0f585e8457db087298259f49/click-8.4.1.tar.gz", hash = "sha256:918b5633eddf6b41c32d4f454bf0de810065c74e3f7dbf8ee5452f8be88d3e96", size = 353007, upload-time = "2026-05-22T04:08:37.769Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c7/0d/67e5b4109ea4a837e80daa87c2c696711955e40449a97e8926672534def2/click-8.4.1-py3-none-any.whl", hash = "sha256:482be17c6991b8c19c5429a1e995d9b0efdbb63172824c41f99965dc0ade8ec2", size = 116639, upload-time = "2026-05-22T04:08:35.26Z" }, +] + +[[package]] +name = "cloudpickle" +version = "3.1.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/27/fb/576f067976d320f5f0114a8d9fa1215425441bb35627b1993e5afd8111e5/cloudpickle-3.1.2.tar.gz", hash = "sha256:7fda9eb655c9c230dab534f1983763de5835249750e85fbcef43aaa30a9a2414", size = 22330, upload-time = "2025-11-03T09:25:26.604Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/88/39/799be3f2f0f38cc727ee3b4f1445fe6d5e4133064ec2e4115069418a5bb6/cloudpickle-3.1.2-py3-none-any.whl", hash = "sha256:9acb47f6afd73f60dc1df93bb801b472f05ff42fa6c84167d25cb206be1fbf4a", size = 22228, upload-time = "2025-11-03T09:25:25.534Z" }, +] + +[[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 = "coolname" +version = "5.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/fe/45/deae12f31934301a488df985880240a200119aca2e4b5ceba71d73bc5e86/coolname-5.0.0.tar.gz", hash = "sha256:594bc6c98ebc75ddd51c0ce10efbb5d2556c14eac60b5b36900dfdd5db20eecf", size = 45800, upload-time = "2026-04-23T06:04:50.824Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/97/35/cf824e535233c432048bd7455b28808776471ab5861375772b2c98ea4cbd/coolname-5.0.0-py3-none-any.whl", hash = "sha256:b86eea9670aa0620965167d1bfadfe654fabec839a5b51e8da611c4a64f86192", size = 47368, upload-time = "2026-04-23T06:04:49.374Z" }, +] + +[[package]] +name = "coolprop" +version = "6.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/13/88/35c88960cf20cf483f1e2127ad999fce4528451ad37173064cdcb3834ebf/CoolProp-6.6.0.tar.gz", hash = "sha256:cf6fad704b3ae00f4df309cfd1e2ee48d155886b569a73f2cc38a57eda463082", size = 13995226, upload-time = "2023-11-29T15:09:38.459Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/97/0d/f2bb30a984bfac131f31973dc6e03952393c418b7f82dacbdc8286e3d973/CoolProp-6.6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cfe23e785e27ac4d12e0b13708a8bdc087caee8133fa0840509efaaf1ad311ba", size = 2787489, upload-time = "2023-11-29T15:08:10.756Z" }, + { url = "https://files.pythonhosted.org/packages/ca/cf/5aa6cf66554703a9b5a2a24deceb5784b9b7a1fd6eb55220bb61b8f1183e/CoolProp-6.6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f374a948bc42babdf644f912958c79effa8ccc4f3f461a0f822715dcdf819c6b", size = 2552683, upload-time = "2023-11-29T15:08:12.468Z" }, + { url = "https://files.pythonhosted.org/packages/5f/83/5aa63e8638acad76b5cc468f9c4594f27fb969dcb10c7fd6918f40d29f37/CoolProp-6.6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3b43e70dfd9825a4de138ce76365978e24532711fb2f4781dacf2b92b96985ed", size = 7068222, upload-time = "2023-11-29T15:08:15.645Z" }, + { url = "https://files.pythonhosted.org/packages/4e/03/c1ade6e9be334bb1ce94583b3f6e4796e097a83ef3c43830ab98908600ac/CoolProp-6.6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c46edd2dad3b99402ad2bff227a53182e0aba954847cac12686e78abd37ae1d", size = 7297130, upload-time = "2023-11-29T15:08:17.513Z" }, + { url = "https://files.pythonhosted.org/packages/ec/7e/e446c7b7767b69892b9f64c06368f793ff9952915ffdbb51ab5afd814d57/CoolProp-6.6.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b83370f50f85cf80ad6c010175b99d6ed7485e647ab70ca85772fecebdcfce86", size = 7314607, upload-time = "2023-11-29T15:08:19.415Z" }, + { url = "https://files.pythonhosted.org/packages/e8/3d/89ad9faf684e6c0171d13d2a2232dfad4fa59ff51a6f3dd2fc44368454af/CoolProp-6.6.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9bf37b539640e787250075e9042590f89bf83a1859c62d1695d2269d95fe7cff", size = 7549917, upload-time = "2023-11-29T15:08:21.178Z" }, + { url = "https://files.pythonhosted.org/packages/9c/46/f97c8fc66653996d92483478ed86944ed3be569b53c28c94321e698630ff/CoolProp-6.6.0-cp311-cp311-win32.whl", hash = "sha256:7b72406779cb17b4197d8bfbb90601f60a5ebb44b8c0c5882e8353021163783a", size = 1863473, upload-time = "2023-11-29T15:08:22.846Z" }, + { url = "https://files.pythonhosted.org/packages/c5/80/97d1ac40b23e953a25b3085a4c3194975d48f76a5dddeaf41869ffd6610d/CoolProp-6.6.0-cp311-cp311-win_amd64.whl", hash = "sha256:b22c30a23603ce3df88a18a445fad14f93fd9757720f43d3b8041549e93c4b93", size = 2023020, upload-time = "2023-11-29T15:08:24.907Z" }, +] + +[[package]] +name = "coverage" +version = "7.14.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/54/fd/0ab2772530e946e1be1abd0bc09e647ec9b02e88f0867857601fefca8953/coverage-7.14.1.tar.gz", hash = "sha256:30c08f7d90415aa98b3c990385dea2939b0da55f38515e5b369b83655f8523be", size = 920132, upload-time = "2026-05-26T20:41:36.783Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7d/d7/477ad149490e6cb849f28abea1dabb9c823cea72e7500c81b4240ce619c0/coverage-7.14.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:478b5bcd63c2e1357c5c7e16c070690df7b07f676b1c114d7b93e533c664309f", size = 219848, upload-time = "2026-05-26T20:38:38.715Z" }, + { url = "https://files.pythonhosted.org/packages/91/82/a5eb47257c50601bb7b9a9d2857c67b7a3a85ad74180eb2c98bb1fbe0ce5/coverage-7.14.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a24a81f9715ee42ef59a316cc11611c98fe23920f7c81861315c9f3ff4a230f4", size = 220354, upload-time = "2026-05-26T20:38:40.232Z" }, + { url = "https://files.pythonhosted.org/packages/43/8b/78419b5391a5cb706b6544390507e469d83ffc9a8248b02c4011aceb9365/coverage-7.14.1-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:196a13319ad88d6d8ef5ab489ec4f44ddde2143c0c7d5b27786f6c3ffd56a7e1", size = 250771, upload-time = "2026-05-26T20:38:41.782Z" }, + { url = "https://files.pythonhosted.org/packages/77/63/e77aaacd491182210d639636b7a8bba23ffffa9b82aa3762da9431855fa9/coverage-7.14.1-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:3d452fd08b5c72c5167c93e6867b5c08500bd40f2a21e1e854a500550b6cc36f", size = 252683, upload-time = "2026-05-26T20:38:43.305Z" }, + { url = "https://files.pythonhosted.org/packages/65/1c/a022e3cfbec2ac241640003cb3a817e161d9c7f5aa9b49173756cdc03204/coverage-7.14.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:23bf7fa51ac02e07fc7c96849b82946da47ae862dc8f86d183b2a4864fc38129", size = 254791, upload-time = "2026-05-26T20:38:45.361Z" }, + { url = "https://files.pythonhosted.org/packages/61/d6/967e408aca4c1ceb88cb0cc677169110ae7f5995fb5eaf5fb1f5a1bb8f5d/coverage-7.14.1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:bcaa50684dcaadfa599ac48f81103c756d791cfd85c97203d2217c593d48b860", size = 256748, upload-time = "2026-05-26T20:38:46.91Z" }, + { url = "https://files.pythonhosted.org/packages/b8/be/869188f7fe28638078ec479331ace6dc5f7b40b7153eb616f47ab79404d8/coverage-7.14.1-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:4ea1c034f95c9b056e856b794630b17f9fa3d57e4800ff1e503d3be0f9c9078c", size = 250907, upload-time = "2026-05-26T20:38:48.493Z" }, + { url = "https://files.pythonhosted.org/packages/07/aa/adb7d3b4278d690e68703abcd76ab1b948242e3668d921711551b78f9ddb/coverage-7.14.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c7e057326434e441306226fbeb5d1aaf14a2637efe97ba668306635835f32ad7", size = 252483, upload-time = "2026-05-26T20:38:50.074Z" }, + { url = "https://files.pythonhosted.org/packages/43/61/331c74103c62dcb0c4b9b3a0de9a61aca016208b0a90f109592a9f9ecc28/coverage-7.14.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:59baf88468dbc8d63b1887afd92bda52e40bb1561696e5819670601403810cec", size = 250545, upload-time = "2026-05-26T20:38:51.613Z" }, + { url = "https://files.pythonhosted.org/packages/f6/b6/c5dae3c104d89be04828f61810e6b3473825482e4c288cc4ed04553e08ae/coverage-7.14.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:d34d75f892b3ab73ba11cab5442cce7b3e168fd64162b16f0e1e0d09c508edef", size = 254310, upload-time = "2026-05-26T20:38:53.503Z" }, + { url = "https://files.pythonhosted.org/packages/ad/a1/2b9d5863e3b83c01ad8199e3c597802fbb3a9dc90b058885804c20296d31/coverage-7.14.1-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:3a56abc20a472baf0304c455721bc601477440d28ecfde8a03dde79ede07e0df", size = 250266, upload-time = "2026-05-26T20:38:55.414Z" }, + { url = "https://files.pythonhosted.org/packages/7f/5e/0e511fbdb269359be26fe678a1c3fa1f2aa2a01573cc3f54268c8d6d4797/coverage-7.14.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6a3cb83d1552c0cd1b4906655b6a33fd4a8473229633a901c6b73bf86914dee9", size = 251174, upload-time = "2026-05-26T20:38:57.141Z" }, + { url = "https://files.pythonhosted.org/packages/85/10/e55307b622b3dd9671cb321824502dc10f93e72f2802b9946159a8edadeb/coverage-7.14.1-cp311-cp311-win32.whl", hash = "sha256:10274a1fbeb8ec5d72966e17bb198a3104257aca4ac09d98667c5f8aca8c8548", size = 222354, upload-time = "2026-05-26T20:38:58.727Z" }, + { url = "https://files.pythonhosted.org/packages/71/cf/107421693cfb71e4f1ca5bf70443f64d4161878068d07a3e51c7ad21d17b/coverage-7.14.1-cp311-cp311-win_amd64.whl", hash = "sha256:87ebdf787d4888e3f3f2d523eadc6e18c6d18c6d0eb173801a189641627fb37e", size = 223290, upload-time = "2026-05-26T20:39:00.413Z" }, + { url = "https://files.pythonhosted.org/packages/b8/1d/3e3644585eb29e9dafefb19555078529a4d7cce12bd21929664eea989277/coverage-7.14.1-cp311-cp311-win_arm64.whl", hash = "sha256:dd34767fa19848d35659ffc0a75314f58c7af3f1cd87ec521e8292a1238398a3", size = 221953, upload-time = "2026-05-26T20:39:02.159Z" }, + { url = "https://files.pythonhosted.org/packages/8a/3c/1a983b9a745d7f83d53f057bcc5bf79ba6a2bbc08266b3f0c7d6fe630c9b/coverage-7.14.1-py3-none-any.whl", hash = "sha256:a252f21c27e38347e60111a3266b03827422a7d5525951aceee313aa68bab1d2", size = 211815, upload-time = "2026-05-26T20:41:34.078Z" }, +] + +[package.optional-dependencies] +toml = [ + { name = "tomli", marker = "python_full_version <= '3.11'" }, +] + +[[package]] +name = "cronsim" +version = "2.7" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fb/1a/02f105147f7f2e06ed4f734ff5a6439590bb275a53dd91fc73df6312298a/cronsim-2.7-py3-none-any.whl", hash = "sha256:1e1431fa08c51dc7f72e67e571c7c7a09af26420169b607badd4ca9677ffad1e", size = 14213, upload-time = "2025-10-21T16:38:20.431Z" }, +] + +[[package]] +name = "cryptography" +version = "49.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cffi", marker = "platform_python_implementation != 'PyPy'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/1f/99/d1c90d6041656cc6ee229dc99cd67fd0cd5aec3c5f7d72fffc27cc750054/cryptography-49.0.0.tar.gz", hash = "sha256:f89660a348f4f78a92366240a61404e337586ef7f5909a2fef59ca88ef505493", size = 854345, upload-time = "2026-06-12T20:02:30.512Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9b/22/adf66990e63584a68dfb50c24f48a125c07b1699899381c8151e63ed458c/cryptography-49.0.0-cp311-abi3-macosx_11_0_arm64.whl", hash = "sha256:966fe0e9c67490071f14c0d2b1cb2dfb3023c5ce39457343931415f08382f2db", size = 4032100, upload-time = "2026-06-12T20:02:32.143Z" }, + { url = "https://files.pythonhosted.org/packages/09/41/3797cfaf69cae04a13ee78ebd83f0678d9c02b4779d21ce24445326f1a69/cryptography-49.0.0-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:36d1709f992593689b45bda411498d62c6e365f2ca00b84657d4dadd24de16db", size = 4692978, upload-time = "2026-06-12T20:01:21.305Z" }, + { url = "https://files.pythonhosted.org/packages/e6/8b/43011f7ebe515a8aa20d61f290a326cd890c2e738e16e59eaff8d9c3a412/cryptography-49.0.0-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0e959b578856a3924bc0cbb710fc12c387b9412a951389f3ca61704a9e25f325", size = 4716422, upload-time = "2026-06-12T20:01:48.566Z" }, + { url = "https://files.pythonhosted.org/packages/4a/91/01ce7303a4579e6d3a6abef01bd322848e9ea7a219adcabc5048b9033571/cryptography-49.0.0-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:53ecee2e23f7169b6117e99fc8a944e5e50f79e69758a83b52a00cb98ab2b2d2", size = 4700503, upload-time = "2026-06-12T20:02:47.091Z" }, + { url = "https://files.pythonhosted.org/packages/62/99/a2c95cf8293f07491e9e27c20cc4dcd18176d944e674679adeb1d0173fd6/cryptography-49.0.0-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:2eda353d8a27bcbcaa4cbed18994a74ab4d19a2ca897db188ea269ab9b71419b", size = 5309779, upload-time = "2026-06-12T20:02:08.987Z" }, + { url = "https://files.pythonhosted.org/packages/20/2c/0622f20ff02b2ef32558733443805dc82fd4c275be01b2d19d14676f3a1b/cryptography-49.0.0-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:2afe9051da7ae7bd5905da5a949280c7d2bb75682e188f650a9d0f2756b834c6", size = 4749683, upload-time = "2026-06-12T20:02:03.335Z" }, + { url = "https://files.pythonhosted.org/packages/a3/5b/c5246635d5fd3b64e0d45ae10e99fd32fe9676a79915ccfe5a61ba9af1a5/cryptography-49.0.0-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:0b82e28ee398a386f0807bba7884d30f25218855690f45115831bcce5d90822c", size = 4337874, upload-time = "2026-06-12T20:02:54.323Z" }, + { url = "https://files.pythonhosted.org/packages/6d/88/05563c7fe2e914e87d1a536d06fe83e66b4e1d95cb593e05aea375531da8/cryptography-49.0.0-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:ccac2bfebc306b862133e3bb71f3f6ee8bb525240089b2d952e4144b3a6d5da7", size = 4700283, upload-time = "2026-06-12T20:01:34.822Z" }, + { url = "https://files.pythonhosted.org/packages/c4/b6/d7696e4e890d6ae1469935164c9e5215c557671cb78d6e3f458ccceaa632/cryptography-49.0.0-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:d0527ce944105f257f605a827d6ebead966c752038b6e8656abb9c5edee6fc68", size = 5265844, upload-time = "2026-06-12T20:01:24.09Z" }, + { url = "https://files.pythonhosted.org/packages/a9/3c/f3ad17eecc1a57b0ba236dc01f90e783c51f4a2f35f64777cc4f47a184b2/cryptography-49.0.0-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:cbc77da8c523d5abd028635ba850a6966fcee2c82e2bf65a41d1d8afe0f98be9", size = 4749290, upload-time = "2026-06-12T20:01:30.848Z" }, + { url = "https://files.pythonhosted.org/packages/4f/01/339573cf1023163a400b0b5d16f6d507de413b9f60be6fd1b77feeaf6737/cryptography-49.0.0-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:b87e65d263b3e5d3bb92a57e2a6638e2f31110fa7aa890c7b2dbba42248d0a3f", size = 4834612, upload-time = "2026-06-12T20:01:29.246Z" }, + { url = "https://files.pythonhosted.org/packages/71/fd/577302e213a1be9468f92d1afef66fcf1ef83d516819d9992ca547f592bd/cryptography-49.0.0-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:66ec79c3904820572d7e987abdf304281f141d37ad9a489b8e97066e7b9b6459", size = 4980804, upload-time = "2026-06-12T20:01:42.853Z" }, + { url = "https://files.pythonhosted.org/packages/1f/09/f42b1d190c5ba75f72062a387f8030d1d75f6ab035788f1d9c4b01de6525/cryptography-49.0.0-cp311-abi3-win_amd64.whl", hash = "sha256:e5dfc1e64de5677cec922ffa8da89c546d0415bf6efdf081842e5d44c84e1f0e", size = 3810026, upload-time = "2026-06-12T20:02:39.262Z" }, + { url = "https://files.pythonhosted.org/packages/19/2a/5bb823f5bedcf80718cea7fbc95ec5515cca3769633c4b01a32be7f30e7c/cryptography-49.0.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:ec5e529fb80935c94fe7b729f9972b50e351a0e6b50aa294fd5cabb109fcc29a", size = 4025947, upload-time = "2026-06-12T20:01:25.745Z" }, + { url = "https://files.pythonhosted.org/packages/3d/df/40577043ca124e17012f408ddddaeb213b856336ac82ddb3bc915f39e29f/cryptography-49.0.0-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f78ff2c9ed8dc2d036b0f4d640e22522213d047c1b14e61205a7e55c80a494d4", size = 4692429, upload-time = "2026-06-12T20:01:53.628Z" }, + { url = "https://files.pythonhosted.org/packages/2c/99/2d13299eb3dd27b02dcfaafcc91d6b5cb3329f7cbd6d8f51921acd566c1a/cryptography-49.0.0-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:35b151772baff2c74cba7fa290ceaff4c3b11c0c881eb93eb5dbc05a7cfbba18", size = 4700968, upload-time = "2026-06-12T20:02:45.383Z" }, + { url = "https://files.pythonhosted.org/packages/a5/4d/9c0cd02f95e2602dd5e563da149ee0830abef3537be8b34dc56281ebe27a/cryptography-49.0.0-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:0f21641cf4b30fca7aee061ced0ec7ad7b073518088b7c9969a297c0ae796c69", size = 4697758, upload-time = "2026-06-12T20:01:41.13Z" }, + { url = "https://files.pythonhosted.org/packages/24/01/186c825898477d77e2324d5360fefe622ff1d8d1963ec0554e2cada8ec77/cryptography-49.0.0-cp39-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:9e82dcc8e56052715fb18b2429e3bca4823b1629136a2084fc45a9a5cecb9b64", size = 5298863, upload-time = "2026-06-12T20:02:24.579Z" }, + { url = "https://files.pythonhosted.org/packages/b8/7b/62cbbab75d0659865bf0273790031544a0b16c8072d258f9428dcd8190dc/cryptography-49.0.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:6f2debedf9ca60cf1d5bd466475638af5130f89965605cd818484d19987d3a21", size = 4735983, upload-time = "2026-06-12T20:01:50.14Z" }, + { url = "https://files.pythonhosted.org/packages/6c/72/3e798c064bc39e471008075d0f9bc9daf77a80879c092e4a8e170c585ed4/cryptography-49.0.0-cp39-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:8c25ceb16df5b9435f3f6a9829204985b0e0cbee3b48aacd432c7d2c850b44d9", size = 4334173, upload-time = "2026-06-12T20:01:44.743Z" }, + { url = "https://files.pythonhosted.org/packages/f0/ee/6fca21d1ac73e06f8bef71940abfd4d2f6472b4bca284d770f32bd4086f6/cryptography-49.0.0-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:28d8b15e6275f12c8a207dc309dfa957903c927d08d0cc937ee3f63f200693cc", size = 4697298, upload-time = "2026-06-12T20:02:20.918Z" }, + { url = "https://files.pythonhosted.org/packages/67/d0/a5fcd3515f0bae49a7b6d0413cc1bdccdcc1fc0047037a0d480642cdc5d6/cryptography-49.0.0-cp39-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:6fc361c34fb6aac015ce19435876635e5c6d21db31998b0920f675f131e043b8", size = 5254338, upload-time = "2026-06-12T20:02:22.737Z" }, + { url = "https://files.pythonhosted.org/packages/a0/84/84fe36f19caf857d61cb7fc9c63035a47ffabd84ea12d1d393148efa3615/cryptography-49.0.0-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:2400ef9c9e2299a25614eb1dea3db54a69b1349efd043bfac9c67630d136df36", size = 4735650, upload-time = "2026-06-12T20:02:41.389Z" }, + { url = "https://files.pythonhosted.org/packages/6c/a0/db537264e234f7273a73ec020873d6d6b39dfd8a53db78b550ca8320440e/cryptography-49.0.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:67e1d20ad9ef3a563c59ef22e7a8a0b8210bd26604369ea4a30a7c66aefe504e", size = 4834820, upload-time = "2026-06-12T20:01:51.847Z" }, + { url = "https://files.pythonhosted.org/packages/93/77/8df9eb486495979bccecd1062e2eaf435250e84437040295b57d09048b0b/cryptography-49.0.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:42b0684e0e40cf26122427802486f6d93aea593612603a94fbf260c7eb1e9c1b", size = 4967968, upload-time = "2026-06-12T20:02:12.524Z" }, + { url = "https://files.pythonhosted.org/packages/c2/e6/f60198ea8d9dfa15fff9ed4ca02ce362f6eadd9ba757dcc50634c4257b63/cryptography-49.0.0-cp39-abi3-win_amd64.whl", hash = "sha256:026ac7423e6fa66872d3bf889be5974507da3944f866f704fa200eadacd00001", size = 3785547, upload-time = "2026-06-12T20:02:26.847Z" }, + { url = "https://files.pythonhosted.org/packages/63/d3/4a83af35d65e3fad632c926fad684c193ea4398569ccb0bbbc7fe8f5dc9a/cryptography-49.0.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:fc1e275c2f1d97b1a6450b8b0ea3ebfa6e087a611c2b26cb2404d48588abab7b", size = 3993685, upload-time = "2026-06-12T20:02:14.883Z" }, + { url = "https://files.pythonhosted.org/packages/d6/a7/f9dac0ab7f80368c56993a7bf638ef9935f825c91902798481fac0898138/cryptography-49.0.0-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:c83782480a4a9da4d0feb51950131ba32e12e70813848b3343f6e18c28a66838", size = 4676239, upload-time = "2026-06-12T20:02:28.793Z" }, + { url = "https://files.pythonhosted.org/packages/d7/70/2ba3769dd0ae167e2f33dfa9592d45db6ff9a61d62ca1a5b3d1bdd09068f/cryptography-49.0.0-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:b39efa323140595abd3ecca8529d321ae50f55f3aa3ba9cc81ea56a6011953d5", size = 4715584, upload-time = "2026-06-12T20:01:27.495Z" }, + { url = "https://files.pythonhosted.org/packages/94/64/2923570ac1c0bd3a737aa366ac3abbbbde273042308b8cde95e2364a6e6a/cryptography-49.0.0-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:b47db11c2c3525083296069b98ac5221907455e989ae0c2e3008bde851921615", size = 4675885, upload-time = "2026-06-12T20:01:55.49Z" }, + { url = "https://files.pythonhosted.org/packages/ab/f8/614dc7e051418cfe53d55173c1e24c6b0085e89996fe90508c2fdf769aef/cryptography-49.0.0-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:084ef1af862eb07ec46d25f68689f2102a9fc0e05ce7b80f14f5fe51e4eef0f6", size = 4715449, upload-time = "2026-06-12T20:02:05.469Z" }, + { url = "https://files.pythonhosted.org/packages/aa/50/a9caea39ad19c431c1a3f8a31114df65b260cdfe67786b6c7e7c040c4c44/cryptography-49.0.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:be9fcb48a55f023493482827d4f459bd263cc20efde64f204b97c123201850c6", size = 3783731, upload-time = "2026-06-12T20:02:43.319Z" }, +] + +[[package]] +name = "cyclopts" +version = "4.22.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "docstring-parser" }, + { name = "rich" }, + { name = "rich-rst" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/69/98/ca72a91d5c25a2ae1baf19d27b31f12288cb9d8a3168b65b3cd54d40d277/cyclopts-4.22.2.tar.gz", hash = "sha256:0721e90e7209885e78f7637cfba255c12e89206b633e35d185305e349ba20ecd", size = 194511, upload-time = "2026-07-24T20:53:08.739Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bd/75/a11bfb5045e58b4ef69337b848985918e829fe9a90572a761d17c1a992f5/cyclopts-4.22.2-py3-none-any.whl", hash = "sha256:9c2cdf6a621886cd0af631a67437eb7d0084f33f9e8fba2d2562a1aecf75f2ff", size = 233906, upload-time = "2026-07-24T20:53:07.064Z" }, +] + +[[package]] +name = "dateparser" +version = "1.4.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "python-dateutil" }, + { name = "pytz" }, + { name = "regex" }, + { name = "tzlocal" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d3/f4/561c49bca97af561d34eed27e3e831135eb5cb88e754c1150be41820f5c6/dateparser-1.4.1.tar.gz", hash = "sha256:f265df13c0380e2e07543ba74b67c0681aaa1096981ffcd35227e1aa0cb81c7c", size = 314734, upload-time = "2026-06-15T08:45:47.659Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8b/7c/2e5dcf53909deddd0bf38cbe277ad9806be038276b1c6c436561b4d9b2e2/dateparser-1.4.1-py3-none-any.whl", hash = "sha256:f25d4e051a84be27a35bd297e3e1dc59ff78373701b89be352ba80372d22d0d0", size = 300503, upload-time = "2026-06-15T08:45:45.951Z" }, +] + +[[package]] +name = "defusedxml" +version = "0.7.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0f/d5/c66da9b79e5bdb124974bfe172b4daf3c984ebd9c2a06e2b8a4dc7331c72/defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69", size = 75520, upload-time = "2021-03-08T10:59:26.269Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/07/6c/aa3f2f849e01cb6a001cd8554a88d4c77c5c1a31c95bdf1cf9301e6d9ef4/defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61", size = 25604, upload-time = "2021-03-08T10:59:24.45Z" }, +] + +[[package]] +name = "docker" +version = "7.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pywin32", marker = "sys_platform == 'win32'" }, + { name = "requests" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/88/7f/731ff914b0255d3d065f45fd4e626d4b8c95dbcbaada049f337a6ac16410/docker-7.2.0.tar.gz", hash = "sha256:cebb93773d334f778e023a7ee352a8d6e13ab1bd3b863a4d4a59dec897df43ac", size = 118731, upload-time = "2026-07-09T14:53:46.39Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/75/23/529140fe1aab80fc6992f93a706deec709140a6397439139a054e1515c45/docker-7.2.0-py3-none-any.whl", hash = "sha256:a3f45fdeb9165e2d25d9a1d02ddf3bc70fb572cf5ebbf9b58558c22caf29b71f", size = 148775, upload-time = "2026-07-09T14:53:45.224Z" }, +] + +[[package]] +name = "docstring-parser" +version = "0.18.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e0/4d/f332313098c1de1b2d2ff91cf2674415cc7cddab2ca1b01ae29774bd5fdf/docstring_parser-0.18.0.tar.gz", hash = "sha256:292510982205c12b1248696f44959db3cdd1740237a968ea1e2e7a900eeb2015", size = 29341, upload-time = "2026-04-14T04:09:19.867Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a7/5f/ed01f9a3cdffbd5a008556fc7b2a08ddb1cc6ace7effa7340604b1d16699/docstring_parser-0.18.0-py3-none-any.whl", hash = "sha256:b3fcbed555c47d8479be0796ef7e19c2670d428d72e96da63f3a40122860374b", size = 22484, upload-time = "2026-04-14T04:09:18.638Z" }, +] + +[[package]] +name = "et-xmlfile" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d3/38/af70d7ab1ae9d4da450eeec1fa3918940a5fafb9055e934af8d6eb0c2313/et_xmlfile-2.0.0.tar.gz", hash = "sha256:dab3f4764309081ce75662649be815c4c9081e88f0837825f90fd28317d4da54", size = 17234, upload-time = "2024-10-25T17:25:40.039Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c1/8b/5fe2cc11fee489817272089c4203e679c63b570a5aaeb18d852ae3cbba6a/et_xmlfile-2.0.0-py3-none-any.whl", hash = "sha256:7a91720bc756843502c3b7504c77b8fe44217c85c537d85037f0f536151b2caa", size = 18059, upload-time = "2024-10-25T17:25:39.051Z" }, +] + +[[package]] +name = "exceptiongroup" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +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 = "fastapi" +version = "0.140.10" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "annotated-doc" }, + { name = "pydantic" }, + { name = "starlette" }, + { name = "typing-extensions" }, + { name = "typing-inspection" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/60/3a/4734b861d4471653ad4c3c86af25904bde8adabc6357e9b400f7f80451bc/fastapi-0.140.10.tar.gz", hash = "sha256:e05c183a57e1084708c34e43b5305494046c28a798b753f94ba96691f5394262", size = 423129, upload-time = "2026-07-28T14:21:30.866Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/05/bf/19aaed94c5f893555520cd539f08b4eebe6741154a3fd8b4a4216448ab95/fastapi-0.140.10-py3-none-any.whl", hash = "sha256:d545b4a3a3a0d5a1ce99d28b38568b0b228bcc47490af150f7c87691df6bc7a5", size = 131128, upload-time = "2026-07-28T14:21:29.445Z" }, +] + +[[package]] +name = "frozenlist" +version = "1.8.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/2d/f5/c831fac6cc817d26fd54c7eaccd04ef7e0288806943f7cc5bbf69f3ac1f0/frozenlist-1.8.0.tar.gz", hash = "sha256:3ede829ed8d842f6cd48fc7081d7a41001a56f1f38603f9d49bf3020d59a31ad", size = 45875, upload-time = "2025-10-06T05:38:17.865Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bc/03/077f869d540370db12165c0aa51640a873fb661d8b315d1d4d67b284d7ac/frozenlist-1.8.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:09474e9831bc2b2199fad6da3c14c7b0fbdd377cce9d3d77131be28906cb7d84", size = 86912, upload-time = "2025-10-06T05:35:45.98Z" }, + { url = "https://files.pythonhosted.org/packages/df/b5/7610b6bd13e4ae77b96ba85abea1c8cb249683217ef09ac9e0ae93f25a91/frozenlist-1.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:17c883ab0ab67200b5f964d2b9ed6b00971917d5d8a92df149dc2c9779208ee9", size = 50046, upload-time = "2025-10-06T05:35:47.009Z" }, + { url = "https://files.pythonhosted.org/packages/6e/ef/0e8f1fe32f8a53dd26bdd1f9347efe0778b0fddf62789ea683f4cc7d787d/frozenlist-1.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fa47e444b8ba08fffd1c18e8cdb9a75db1b6a27f17507522834ad13ed5922b93", size = 50119, upload-time = "2025-10-06T05:35:48.38Z" }, + { url = "https://files.pythonhosted.org/packages/11/b1/71a477adc7c36e5fb628245dfbdea2166feae310757dea848d02bd0689fd/frozenlist-1.8.0-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:2552f44204b744fba866e573be4c1f9048d6a324dfe14475103fd51613eb1d1f", size = 231067, upload-time = "2025-10-06T05:35:49.97Z" }, + { url = "https://files.pythonhosted.org/packages/45/7e/afe40eca3a2dc19b9904c0f5d7edfe82b5304cb831391edec0ac04af94c2/frozenlist-1.8.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:957e7c38f250991e48a9a73e6423db1bb9dd14e722a10f6b8bb8e16a0f55f695", size = 233160, upload-time = "2025-10-06T05:35:51.729Z" }, + { url = "https://files.pythonhosted.org/packages/a6/aa/7416eac95603ce428679d273255ffc7c998d4132cfae200103f164b108aa/frozenlist-1.8.0-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:8585e3bb2cdea02fc88ffa245069c36555557ad3609e83be0ec71f54fd4abb52", size = 228544, upload-time = "2025-10-06T05:35:53.246Z" }, + { url = "https://files.pythonhosted.org/packages/8b/3d/2a2d1f683d55ac7e3875e4263d28410063e738384d3adc294f5ff3d7105e/frozenlist-1.8.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:edee74874ce20a373d62dc28b0b18b93f645633c2943fd90ee9d898550770581", size = 243797, upload-time = "2025-10-06T05:35:54.497Z" }, + { url = "https://files.pythonhosted.org/packages/78/1e/2d5565b589e580c296d3bb54da08d206e797d941a83a6fdea42af23be79c/frozenlist-1.8.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c9a63152fe95756b85f31186bddf42e4c02c6321207fd6601a1c89ebac4fe567", size = 247923, upload-time = "2025-10-06T05:35:55.861Z" }, + { url = "https://files.pythonhosted.org/packages/aa/c3/65872fcf1d326a7f101ad4d86285c403c87be7d832b7470b77f6d2ed5ddc/frozenlist-1.8.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b6db2185db9be0a04fecf2f241c70b63b1a242e2805be291855078f2b404dd6b", size = 230886, upload-time = "2025-10-06T05:35:57.399Z" }, + { url = "https://files.pythonhosted.org/packages/a0/76/ac9ced601d62f6956f03cc794f9e04c81719509f85255abf96e2510f4265/frozenlist-1.8.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:f4be2e3d8bc8aabd566f8d5b8ba7ecc09249d74ba3c9ed52e54dc23a293f0b92", size = 245731, upload-time = "2025-10-06T05:35:58.563Z" }, + { url = "https://files.pythonhosted.org/packages/b9/49/ecccb5f2598daf0b4a1415497eba4c33c1e8ce07495eb07d2860c731b8d5/frozenlist-1.8.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:c8d1634419f39ea6f5c427ea2f90ca85126b54b50837f31497f3bf38266e853d", size = 241544, upload-time = "2025-10-06T05:35:59.719Z" }, + { url = "https://files.pythonhosted.org/packages/53/4b/ddf24113323c0bbcc54cb38c8b8916f1da7165e07b8e24a717b4a12cbf10/frozenlist-1.8.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:1a7fa382a4a223773ed64242dbe1c9c326ec09457e6b8428efb4118c685c3dfd", size = 241806, upload-time = "2025-10-06T05:36:00.959Z" }, + { url = "https://files.pythonhosted.org/packages/a7/fb/9b9a084d73c67175484ba2789a59f8eebebd0827d186a8102005ce41e1ba/frozenlist-1.8.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:11847b53d722050808926e785df837353bd4d75f1d494377e59b23594d834967", size = 229382, upload-time = "2025-10-06T05:36:02.22Z" }, + { url = "https://files.pythonhosted.org/packages/95/a3/c8fb25aac55bf5e12dae5c5aa6a98f85d436c1dc658f21c3ac73f9fa95e5/frozenlist-1.8.0-cp311-cp311-win32.whl", hash = "sha256:27c6e8077956cf73eadd514be8fb04d77fc946a7fe9f7fe167648b0b9085cc25", size = 39647, upload-time = "2025-10-06T05:36:03.409Z" }, + { url = "https://files.pythonhosted.org/packages/0a/f5/603d0d6a02cfd4c8f2a095a54672b3cf967ad688a60fb9faf04fc4887f65/frozenlist-1.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:ac913f8403b36a2c8610bbfd25b8013488533e71e62b4b4adce9c86c8cea905b", size = 44064, upload-time = "2025-10-06T05:36:04.368Z" }, + { url = "https://files.pythonhosted.org/packages/5d/16/c2c9ab44e181f043a86f9a8f84d5124b62dbcb3a02c0977ec72b9ac1d3e0/frozenlist-1.8.0-cp311-cp311-win_arm64.whl", hash = "sha256:d4d3214a0f8394edfa3e303136d0575eece0745ff2b47bd2cb2e66dd92d4351a", size = 39937, upload-time = "2025-10-06T05:36:05.669Z" }, + { url = "https://files.pythonhosted.org/packages/9a/9a/e35b4a917281c0b8419d4207f4334c8e8c5dbf4f3f5f9ada73958d937dcc/frozenlist-1.8.0-py3-none-any.whl", hash = "sha256:0c18a16eab41e82c295618a77502e17b195883241c563b00f0aa5106fc4eaa0d", size = 13409, upload-time = "2025-10-06T05:38:16.721Z" }, +] + +[[package]] +name = "fsspec" +version = "2026.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/10/a1/ae4e3e5003468d6391d2c77b6fa1cd73bd5d13511d81c642d7b28ac90ed4/fsspec-2026.6.0.tar.gz", hash = "sha256:f5bac145310fe30e16e1471bd6840b2d990d609e872251d7e674241822abf01a", size = 313646, upload-time = "2026-06-16T01:57:28.105Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e5/22/4222d7ddf3da30f363edaa98e329c2bce6c65497c9cb2810931c8b2c0fbc/fsspec-2026.6.0-py3-none-any.whl", hash = "sha256:02e0b71817df9b2169dc30a16832045764def1191b43dcff5bb85bdee212d2a1", size = 203949, upload-time = "2026-06-16T01:57:26.358Z" }, +] + +[[package]] +name = "future-fstrings" +version = "1.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5d/e2/3874574cce18a2e3608abfe5b4b5b3c9765653c464f5da18df8971cf501d/future_fstrings-1.2.0.tar.gz", hash = "sha256:6cf41cbe97c398ab5a81168ce0dbb8ad95862d3caf23c21e4430627b90844089", size = 5786, upload-time = "2019-06-16T03:04:42.651Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ab/6d/ea1d52e9038558dd37f5d30647eb9f07888c164960a5d4daa5f970c6da25/future_fstrings-1.2.0-py2.py3-none-any.whl", hash = "sha256:90e49598b553d8746c4dc7d9442e0359d038c3039d802c91c0a55505da318c63", size = 6138, upload-time = "2019-06-16T03:04:40.395Z" }, +] + +[[package]] +name = "graphviz" +version = "0.21" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f8/b3/3ac91e9be6b761a4b30d66ff165e54439dcd48b83f4e20d644867215f6ca/graphviz-0.21.tar.gz", hash = "sha256:20743e7183be82aaaa8ad6c93f8893c923bd6658a04c32ee115edb3c8a835f78", size = 200434, upload-time = "2025-06-15T09:35:05.824Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/91/4c/e0ce1ef95d4000ebc1c11801f9b944fa5910ecc15b5e351865763d8657f8/graphviz-0.21-py3-none-any.whl", hash = "sha256:54f33de9f4f911d7e84e4191749cac8cc5653f815b06738c54db9a15ab8b1e42", size = 47300, upload-time = "2025-06-15T09:35:04.433Z" }, +] + +[[package]] +name = "greenlet" +version = "3.5.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a3/74/b13368064b09053253555d3f2839cc2684d22d5aed0d2ccffbf7a6736558/greenlet-3.5.4.tar.gz", hash = "sha256:0232ae1de90a8e07867bb127d7a6ba2301e859145489f25cda8a6096dabe1d20", size = 206538, upload-time = "2026-07-22T12:47:14.468Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/61/16/71eefcf68267bbf06a9b6bff57d0b222e49432326e85d74348b67694b8d4/greenlet-3.5.4-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:e883de250e299654b1f1680f72a1a9f9ba62c9bd1bce84099c90657349a8dfbb", size = 294266, upload-time = "2026-07-22T11:37:56.142Z" }, + { url = "https://files.pythonhosted.org/packages/36/ea/a0b19adfc35d07e10acb626e9d22a3893b95f1309c42c4a20161dec16800/greenlet-3.5.4-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:32802705c2c1ff25e8237b3bdacf2594fa02be80af8a66703eb7853ea7e68686", size = 613712, upload-time = "2026-07-22T12:26:39.375Z" }, + { url = "https://files.pythonhosted.org/packages/54/76/a121978b3337407d05a1ce5f79b4aa5998a43a9d8422f9726029b90b4471/greenlet-3.5.4-cp311-cp311-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:57aa201b351f7c7c75627c60d29e4d5b97a07d37efeb62b903466fca42c097d7", size = 625582, upload-time = "2026-07-22T12:29:00.814Z" }, + { url = "https://files.pythonhosted.org/packages/d1/4a/f301f1d85c69a86b90b5d581a73e8927bba4e79450037e6e2cbca05eb4fd/greenlet-3.5.4-cp311-cp311-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:9667862a2e38ad379f11b845daeda22c8989186def44f06962c9c4c05e556da7", size = 633429, upload-time = "2026-07-22T12:43:42.073Z" }, + { url = "https://files.pythonhosted.org/packages/34/c2/080f16cf870e929e592f55767f01d6c98d2ee83bfdc36c3b892f2d0459ab/greenlet-3.5.4-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c3fe76c2cac86b4f7a1e92865ac0a54384deb05c92986287c1a7110d9bd53071", size = 624663, upload-time = "2026-07-22T11:51:08.016Z" }, + { url = "https://files.pythonhosted.org/packages/6f/2e/26884072b0eb343a4d5fee903341bfe5171b32b7f14553886e2b6349135a/greenlet-3.5.4-cp311-cp311-manylinux_2_39_riscv64.whl", hash = "sha256:ae53534b5dec0f4c2ec26f898f538dc8ea1ca3ef2927d597a9439e40a09da937", size = 428238, upload-time = "2026-07-22T12:39:49.973Z" }, + { url = "https://files.pythonhosted.org/packages/9e/bb/8f3ca88370b817369008faeceeee85970adc16c92a70a3e5fe5fea495a57/greenlet-3.5.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1e1a4a684b16c45ba324e60b32a4386a87722bcb815d2a149d2182f9b401ca72", size = 1585010, upload-time = "2026-07-22T12:25:02.539Z" }, + { url = "https://files.pythonhosted.org/packages/51/c2/45877154689709ebce9a0b83c2235e6ca0f31577889b02af308c8cc5f8fb/greenlet-3.5.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e849e6e139b9671adeac505f72fc05f4af7fd1921faef40295e214fc3b361b59", size = 1651283, upload-time = "2026-07-22T11:51:10.408Z" }, + { url = "https://files.pythonhosted.org/packages/cd/7d/8711a75cb61d85246277c07ff6e1a6504621ba473d808c11ad225ffca43f/greenlet-3.5.4-cp311-cp311-win_amd64.whl", hash = "sha256:dc418cf4c873357964d6624445ed09472e50def990c65dd4e76fc3ba8cd9cef6", size = 246434, upload-time = "2026-07-22T11:43:15.557Z" }, + { url = "https://files.pythonhosted.org/packages/00/62/e290b3bce433da8f0324ac02da0b128d683482229f1a8b789fa47818a4cd/greenlet-3.5.4-cp311-cp311-win_arm64.whl", hash = "sha256:c38c902a0986eba1f6e7ba1ab39ad5195926abde90f3fe080e08212db62176da", size = 244990, upload-time = "2026-07-22T11:39:22.626Z" }, +] + +[[package]] +name = "griffe" +version = "2.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "griffecli" }, + { name = "griffelib" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/00/44/63913c007814cab5ba9d36f25ad40dfc640c2e2931d195bd2d05f774a5d6/griffe-2.1.0.tar.gz", hash = "sha256:c58845df5a364feaabd05ee8c767b97b03e478da8aa18b9923553c812fb0d955", size = 244879, upload-time = "2026-06-19T12:05:41.262Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6b/fb/3c65d392feae6c36dc2b55a14dd8270b7b35a3171c93b71a4d2ee4abf241/griffe-2.1.0-py3-none-any.whl", hash = "sha256:2ccdab17fb9cd76f278d7b5611cfc8f68cbe846d8d48df63dff80b62ecfa6f65", size = 5140, upload-time = "2026-06-19T12:05:39.913Z" }, +] + +[[package]] +name = "griffecli" +version = "2.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama" }, + { name = "griffelib" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/8e/c6/90f85d47af96300d629b38c25b71aad9467a620cac964a39280e822efc8a/griffecli-2.1.0.tar.gz", hash = "sha256:2ff68dbee9395fdb668b10374c51683392d697b226ac60159798f4add1ee716c", size = 56913, upload-time = "2026-06-19T12:05:43.119Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/80/2f/513232ec1d5f5da182e4ce45a11427e37dd210844a9e2bca451fc9661fb3/griffecli-2.1.0-py3-none-any.whl", hash = "sha256:6e22b1423d562ddc510997b4be1fe89de59e19dcff78831c0f4bfc3b8134a718", size = 9500, upload-time = "2026-06-19T12:05:37.517Z" }, +] + +[[package]] +name = "griffelib" +version = "2.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/33/e4/8d187ea29c2e30b3a09505c567513077d6117861bde1fbd997a167f262ec/griffelib-2.1.0.tar.gz", hash = "sha256:762a186d2c6fd6794d4ea20d428d597ffb857cb56b66421651cbba15bdd5e813", size = 216234, upload-time = "2026-06-19T12:05:42.278Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e4/d3/5268aeabf2ad82658c4e2ff3a060648d0f02f3926cb53247c0e4d0dab49e/griffelib-2.1.0-py3-none-any.whl", hash = "sha256:cc7b3d2d2865ad0b909fcc38086e3f554b5ea7acbaa7bbb7ecaa3f5dfb7d9f00", size = 142560, upload-time = "2026-06-19T12:05:38.742Z" }, +] + +[[package]] +name = "h11" +version = "0.16.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/01/ee/02a2c011bdab74c6fb3c75474d40b3052059d95df7e73351460c8588d963/h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", size = 101250, upload-time = "2025-04-24T03:35:25.427Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload-time = "2025-04-24T03:35:24.344Z" }, +] + +[[package]] +name = "h2" +version = "4.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "hpack" }, + { name = "hyperframe" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/30/d4/a7d6fb3f58be99d65cbf2d3f766896217a2921d0f3ab10711c45dc1519ee/h2-4.4.0.tar.gz", hash = "sha256:46b551bdcdc7e83cf5c04d0bf93badb8a939bd2287d9fee1abb23a445b9e0580", size = 2156691, upload-time = "2026-07-23T19:14:19.442Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f6/df/5b14a118322d6097cb9bb30ec6bacad268e546a8ecfcb1f6d0de618dac2f/h2-4.4.0-py3-none-any.whl", hash = "sha256:6acffe1aeab79098d7eb0f8385c1add11f2c7a94815f6fa2b7060eeddee3d87c", size = 62368, upload-time = "2026-07-23T19:14:16.143Z" }, +] + +[[package]] +name = "hpack" +version = "4.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/26/5b/fcabf6028144a8723726318b07a32c2f3314acdff6265743cf08a344b18e/hpack-4.2.0.tar.gz", hash = "sha256:0895cfa3b5531fc65fe439c05eb65144f123bf7a394fcaa56aa423548d8e45c0", size = 51300, upload-time = "2026-06-23T18:34:46.667Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/71/b4/4a9fcfb2aef6ba44d9073ecd301443aa00b3dac95de5619f2a7de7ec8a91/hpack-4.2.0-py3-none-any.whl", hash = "sha256:858ac0b02280fa582b5080d68db0899c62a80375e0e5413a74970c5e518b6986", size = 34246, upload-time = "2026-06-23T18:34:45.472Z" }, +] + +[[package]] +name = "httpcore" +version = "1.0.9" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "h11" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/06/94/82699a10bca87a5556c9c59b5963f2d039dbd239f25bc2a63907a05a14cb/httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8", size = 85484, upload-time = "2025-04-24T22:06:22.219Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", size = 78784, upload-time = "2025-04-24T22:06:20.566Z" }, +] + +[[package]] +name = "httpx" +version = "0.28.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "certifi" }, + { name = "httpcore" }, + { name = "idna" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406, upload-time = "2024-12-06T15:37:23.222Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517, upload-time = "2024-12-06T15:37:21.509Z" }, +] + +[package.optional-dependencies] +http2 = [ + { name = "h2" }, +] + +[[package]] +name = "humanize" +version = "4.16.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0a/ea/13a1ef3c12d12662905801495283530251918b70d62d368f1d2e0272c70d/humanize-4.16.0.tar.gz", hash = "sha256:7dc2244a2f84a4bfb1d36c37bac80cd78e35cdc5c119206d87b018e1445f3a3f", size = 89515, upload-time = "2026-06-30T16:17:29.859Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b0/aa/0b7365d30fed43e7a3449aba1fe20a0a7174d9cf13e282af4e69ac825441/humanize-4.16.0-py3-none-any.whl", hash = "sha256:353eb2f34c09d098b2880eee8bef21832eae6d174f48c5762fff7e5fcb74d01d", size = 137209, upload-time = "2026-06-30T16:17:28.36Z" }, +] + +[[package]] +name = "hyperframe" +version = "6.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/02/e7/94f8232d4a74cc99514c13a9f995811485a6903d48e5d952771ef6322e30/hyperframe-6.1.0.tar.gz", hash = "sha256:f630908a00854a7adeabd6382b43923a4c4cd4b821fcb527e6ab9e15382a3b08", size = 26566, upload-time = "2025-01-22T21:41:49.302Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/48/30/47d0bf6072f7252e6521f3447ccfa40b421b6824517f82854703d0f5a98b/hyperframe-6.1.0-py3-none-any.whl", hash = "sha256:b03380493a519fce58ea5af42e4a42317bf9bd425596f7a0835ffce80f1a42e5", size = 13007, upload-time = "2025-01-22T21:41:47.295Z" }, +] + +[[package]] +name = "idna" +version = "3.18" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cd/63/9496c57188a2ee585e0f1db071d75089a11e98aa86eb99d9d7618fc1edce/idna-3.18.tar.gz", hash = "sha256:ffb385a7e039654cef1ab9ef32c6fafe283c0c0467bba1d9029738ce4a14a848", size = 196711, upload-time = "2026-06-02T14:34:07.794Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1e/5e/d4e9f1a599fb8e573b7b87160658329fbf28d19eac2718f51fc3def3aa5a/idna-3.18-py3-none-any.whl", hash = "sha256:7f952cbe720b688055e3f87de14f5c3e5fdaa8bc3928985c4077ca689de849a2", size = 65455, upload-time = "2026-06-02T14:34:06.319Z" }, +] + +[[package]] +name = "influxdb" +version = "5.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "msgpack" }, + { name = "python-dateutil" }, + { name = "pytz" }, + { name = "requests" }, + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/86/4f/a9c524576677c1694b149e09d4fd6342e4a1d9a5f409e437168a14d6d150/influxdb-5.3.1.tar.gz", hash = "sha256:46f85e7b04ee4b3dee894672be6a295c94709003a7ddea8820deec2ac4d8b27a", size = 67385, upload-time = "2020-11-11T21:23:44.167Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/01/95/3a72ea5e19df828d27af0a50092f2b24114a5f89922efb4d8a0960bf13ef/influxdb-5.3.1-py2.py3-none-any.whl", hash = "sha256:65040a1f53d1a2a4f88a677e89e3a98189a7d30cf2ab61c318aaa89733280747", size = 77906, upload-time = "2020-11-11T21:23:41.567Z" }, +] + +[[package]] +name = "iniconfig" +version = "2.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" }, +] + +[[package]] +name = "jinja2" +version = "3.1.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markupsafe" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115, upload-time = "2025-03-05T20:05:02.478Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" }, +] + +[[package]] +name = "jinja2-humanize-extension" +version = "0.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "humanize" }, + { name = "jinja2" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/74/77/0bba383819dd4e67566487c11c49479ced87e77c3285d8e7f7a3401cf882/jinja2_humanize_extension-0.4.0.tar.gz", hash = "sha256:e7d69b1c20f32815bbec722330ee8af14b1287bb1c2b0afa590dbf031cadeaa0", size = 4746, upload-time = "2023-09-01T12:52:42.781Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/26/b4/08c9d297edd5e1182506edecccbb88a92e1122a057953068cadac420ca5d/jinja2_humanize_extension-0.4.0-py3-none-any.whl", hash = "sha256:b6326e2da0f7d425338bebf58848e830421defbce785f12ae812e65128518156", size = 4769, upload-time = "2023-09-01T12:52:41.098Z" }, +] + +[[package]] +name = "jmespath" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d3/59/322338183ecda247fb5d1763a6cbe46eff7222eaeebafd9fa65d4bf5cb11/jmespath-1.1.0.tar.gz", hash = "sha256:472c87d80f36026ae83c6ddd0f1d05d4e510134ed462851fd5f754c8c3cbb88d", size = 27377, upload-time = "2026-01-22T16:35:26.279Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/14/2f/967ba146e6d58cf6a652da73885f52fc68001525b4197effc174321d70b4/jmespath-1.1.0-py3-none-any.whl", hash = "sha256:a5663118de4908c91729bea0acadca56526eb2698e83de10cd116ae0f4e97c64", size = 20419, upload-time = "2026-01-22T16:35:24.919Z" }, +] + +[[package]] +name = "jsonpatch" +version = "1.33" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jsonpointer" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/42/78/18813351fe5d63acad16aec57f94ec2b70a09e53ca98145589e185423873/jsonpatch-1.33.tar.gz", hash = "sha256:9fcd4009c41e6d12348b4a0ff2563ba56a2923a7dfee731d004e212e1ee5030c", size = 21699, upload-time = "2023-06-26T12:07:29.144Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/73/07/02e16ed01e04a374e644b575638ec7987ae846d25ad97bcc9945a3ee4b0e/jsonpatch-1.33-py2.py3-none-any.whl", hash = "sha256:0ae28c0cd062bbd8b8ecc26d7d164fbbea9652a1a3693f3b956c1eae5145dade", size = 12898, upload-time = "2023-06-16T21:01:28.466Z" }, +] + +[[package]] +name = "jsonpointer" +version = "3.1.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/18/c7/af399a2e7a67fd18d63c40c5e62d3af4e67b836a2107468b6a5ea24c4304/jsonpointer-3.1.1.tar.gz", hash = "sha256:0b801c7db33a904024f6004d526dcc53bbb8a4a0f4e32bfd10beadf60adf1900", size = 9068, upload-time = "2026-03-23T22:32:32.458Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9e/6a/a83720e953b1682d2d109d3c2dbb0bc9bf28cc1cbc205be4ef4be5da709d/jsonpointer-3.1.1-py3-none-any.whl", hash = "sha256:8ff8b95779d071ba472cf5bc913028df06031797532f08a7d5b602d8b2a488ca", size = 7659, upload-time = "2026-03-23T22:32:31.568Z" }, +] + +[[package]] +name = "jsonschema" +version = "4.26.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "jsonschema-specifications" }, + { name = "referencing" }, + { name = "rpds-py" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b3/fc/e067678238fa451312d4c62bf6e6cf5ec56375422aee02f9cb5f909b3047/jsonschema-4.26.0.tar.gz", hash = "sha256:0c26707e2efad8aa1bfc5b7ce170f3fccc2e4918ff85989ba9ffa9facb2be326", size = 366583, upload-time = "2026-01-07T13:41:07.246Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/69/90/f63fb5873511e014207a475e2bb4e8b2e570d655b00ac19a9a0ca0a385ee/jsonschema-4.26.0-py3-none-any.whl", hash = "sha256:d489f15263b8d200f8387e64b4c3a75f06629559fb73deb8fdfb525f2dab50ce", size = 90630, upload-time = "2026-01-07T13:41:05.306Z" }, +] + +[[package]] +name = "jsonschema-specifications" +version = "2025.9.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "referencing" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/19/74/a633ee74eb36c44aa6d1095e7cc5569bebf04342ee146178e2d36600708b/jsonschema_specifications-2025.9.1.tar.gz", hash = "sha256:b540987f239e745613c7a9176f3edb72b832a4ac465cf02712288397832b5e8d", size = 32855, upload-time = "2025-09-08T01:34:59.186Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl", hash = "sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe", size = 18437, upload-time = "2025-09-08T01:34:57.871Z" }, +] + +[[package]] +name = "lxml" +version = "6.1.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/05/3b/aab6728cae887456f409b4d75e8a01856e4f04bd510de38052a47768b680/lxml-6.1.1.tar.gz", hash = "sha256:ba96ae44888e0185281e937633a743ea90d5a196c6000f82565ebb0580012d40", size = 4197430, upload-time = "2026-05-18T19:19:06.424Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/62/b0/83f481780d1548750b8ce2ec824073deef2f452d9cd1a6faff8507e3d16d/lxml-6.1.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:53b7d2b7a10b1c35c0a5e21e9224accf60c1bbfba523990732e521b2b73adef2", size = 8526461, upload-time = "2026-05-18T19:17:25.862Z" }, + { url = "https://files.pythonhosted.org/packages/b9/d5/30fa0f808002c7329397bfbb24e306789c0b29f04aa5842c07b174b4216f/lxml-6.1.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ff3f333630ab480244a1bff72043e511a91eb22e7595dead8653ee5612dd8f3d", size = 4595375, upload-time = "2026-05-18T19:17:34.555Z" }, + { url = "https://files.pythonhosted.org/packages/4f/d2/edb71cf0e561581a7c5eb2626244320eb04e9f8ce6d563184fd668b45073/lxml-6.1.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:a4bbea04c97f6d78a48e3fbc1cb9116d2780b1b39e03a23f6eb9b603fd61f510", size = 4923654, upload-time = "2026-05-18T19:17:42.917Z" }, + { url = "https://files.pythonhosted.org/packages/4c/77/1bc7eeb0de4577d783fb625aa092cc9357883bba35845a3666bf1259f3dc/lxml-6.1.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:db1d75f6617a49c1c01bc7023713e0ff59ab32c9579ae62a7674c0e34f3b0b0a", size = 5067921, upload-time = "2026-05-18T19:17:49.175Z" }, + { url = "https://files.pythonhosted.org/packages/1b/3c/c0690d74bd2bc17bc03b5b0d093569ead597dd0bfa088bf99eef8c24e19c/lxml-6.1.1-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3a12689be69a28ddaa0ab99a5a1137da2afd5f8f16df7b5680b66f616d3eda1d", size = 5002456, upload-time = "2026-05-18T19:17:59.715Z" }, + { url = "https://files.pythonhosted.org/packages/66/8d/d1b3271af0c0f1e27e8472a849e4d2c65bc7766884b9ad2da9e76e145c88/lxml-6.1.1-cp311-cp311-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:18b73c339ae29b90fd2d06e58ebd555a751bde9cd6bbd36cc0281b9a2c94e9d8", size = 5202776, upload-time = "2026-05-18T19:18:08.924Z" }, + { url = "https://files.pythonhosted.org/packages/7a/45/689824ffb237fd10125ad273f32b28ff04dc6203c2822c85ff65a93df65e/lxml-6.1.1-cp311-cp311-manylinux_2_28_i686.whl", hash = "sha256:752d3bbfe874715ccd0aec7f88d7fc623c0f1fd7aa7b3238a084e017bad2a009", size = 5329945, upload-time = "2026-05-18T19:18:13.673Z" }, + { url = "https://files.pythonhosted.org/packages/5d/c0/ef73af53767e958fd87d437c170f272e2f6e6c0f854939f133a895f1e711/lxml-6.1.1-cp311-cp311-manylinux_2_31_armv7l.whl", hash = "sha256:6b1761fbf9ec984e2e9d9c589ef5f5fd684b7c19f92aadd567a26c5224958db6", size = 4659237, upload-time = "2026-05-18T19:18:18.657Z" }, + { url = "https://files.pythonhosted.org/packages/a0/5e/e1158e40397585e91cb0472374a1f63d0926a1ddeaa92f13d1a1ffe306d5/lxml-6.1.1-cp311-cp311-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d680fbcb768404c601ecb43519ecd8461f6954cb11c06a78962f666832ccfca8", size = 5265904, upload-time = "2026-05-18T19:18:24.883Z" }, + { url = "https://files.pythonhosted.org/packages/a0/16/8687e5d1400ed1c0bc41dace232ebb7553952b618ea1f2e5fb6e2cfbbe23/lxml-6.1.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:162af1091cd785f2f27e62d3547ae9bc58ec5c86dd314d67021fd02463708d83", size = 5045225, upload-time = "2026-05-18T19:17:20.073Z" }, + { url = "https://files.pythonhosted.org/packages/ca/18/d877bd1ae2e5ffdfd4836565aba350db31feb2f2656d6ce70316ed66a05e/lxml-6.1.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:e9308ff8241c532df3f3e570f9a5aeed6c853f888512ba4b75638d7c11c95ef6", size = 4712721, upload-time = "2026-05-18T19:17:40.512Z" }, + { url = "https://files.pythonhosted.org/packages/44/4d/1f44fd1d770b10dacbf6b5c6e520f4d6e0708744930f719dc04e67cab981/lxml-6.1.1-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:5f6994074ebae6ffb04447268e37dc16edc304f9859cf91acb86e0af6c1b395c", size = 5252549, upload-time = "2026-05-18T19:17:51.236Z" }, + { url = "https://files.pythonhosted.org/packages/64/5d/1d66b84f850089254c230ef6ea6b267a5a54e2e179a5d960036a05d501d7/lxml-6.1.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:80c2dfadb855da477cf73373ad29a333535dedb9b12bad02c9814c8e2b43bf08", size = 5226877, upload-time = "2026-05-18T19:18:00.875Z" }, + { url = "https://files.pythonhosted.org/packages/ad/00/84c4b5302d42a2d0184f38d538c8a197f33b52a50bd4f7bcfe990bce3036/lxml-6.1.1-cp311-cp311-win32.whl", hash = "sha256:30a89d3ac8faec007453fb541f3f46807eeec88edd5826f6e3fe001752a2c621", size = 3594072, upload-time = "2026-05-18T19:17:12.714Z" }, + { url = "https://files.pythonhosted.org/packages/61/9d/2e2f7d876349f45e0f3e29f72da311668853d59b58d473a2dea4f0160135/lxml-6.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:abbefa31eee84842140f67acef1c828e28bba8bbf0c3bc6e5492a9af88152c28", size = 4025469, upload-time = "2026-05-18T19:17:50.566Z" }, + { url = "https://files.pythonhosted.org/packages/b0/d5/570e6390e4110331e6208b2ba83d1482cc9146808ee118b22824a34c1070/lxml-6.1.1-cp311-cp311-win_arm64.whl", hash = "sha256:dcb292aa7fe485ceff7af4f92e46c5af397daec5dff64871a528f0fc47a3cc5b", size = 3667640, upload-time = "2026-05-19T19:22:48.293Z" }, + { url = "https://files.pythonhosted.org/packages/b5/32/86a3f0f724a3a402d4627937a7fc27b160e45e7012b4adf47f6e1e844511/lxml-6.1.1-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:31033dc34636ea6b7d5cc11b1ddbda78a14de858ba9d3e1ed4b69a3085bc521e", size = 3930127, upload-time = "2026-05-18T19:19:02.27Z" }, + { url = "https://files.pythonhosted.org/packages/40/44/d832e82af08723761556d004b1d04d281c09f9a8cecd7d3148548c9941a3/lxml-6.1.1-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3893c14c4b6ac5b2d54ba8cf03e99fe5104e592de491f19bd6b82756c09f8004", size = 4210769, upload-time = "2026-05-18T19:20:41.427Z" }, + { url = "https://files.pythonhosted.org/packages/6d/39/0dc5949f759ed7d951e0bb8c2f2d9d7aca1908d22352fa84a8afd2ea54af/lxml-6.1.1-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c07da4cebf6889f03ebac8d238f62318e29f495de0aa18a51ea14e61ae907e2e", size = 4318163, upload-time = "2026-05-18T19:20:44.702Z" }, + { url = "https://files.pythonhosted.org/packages/e6/fb/8ab3845fe046ba4cbf74536bcf6801a774b7caf4350de1c5d37f1f0a9e90/lxml-6.1.1-pp311-pypy311_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f6f0ce10945fab9c4c06ce14e22af9059d1a87493a9af4501a5b0b9187e21cf2", size = 4250945, upload-time = "2026-05-18T19:20:47.385Z" }, + { url = "https://files.pythonhosted.org/packages/68/1b/7553ab136894374ffae8851ec06f98f511cd8e66246e41b6be059d0a7289/lxml-6.1.1-pp311-pypy311_pp73-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f8844cd288697c6425c9beba919302241e3278871dc6519515e72b04e987abcf", size = 4401664, upload-time = "2026-05-18T19:20:50.489Z" }, + { url = "https://files.pythonhosted.org/packages/db/a4/441aee36c6f6b249823d20fd91f9be9ab89d7c5a8ae542a4a4ca6d342d56/lxml-6.1.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:ed21202aec73cda4d55d1ce57b389aadb90ffb044e6cd1080b8347efe1b1ec84", size = 3508989, upload-time = "2026-05-18T19:18:38.158Z" }, +] + +[[package]] +name = "mako" +version = "1.3.12" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markupsafe" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/00/62/791b31e69ae182791ec67f04850f2f062716bbd205483d63a215f3e062d3/mako-1.3.12.tar.gz", hash = "sha256:9f778e93289bd410bb35daadeb4fc66d95a746f0b75777b942088b7fd7af550a", size = 400219, upload-time = "2026-04-28T19:01:08.512Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bc/b1/a0ec7a5a9db730a08daef1fdfb8090435b82465abbf758a596f0ea88727e/mako-1.3.12-py3-none-any.whl", hash = "sha256:8f61569480282dbf557145ce441e4ba888be453c30989f879f0d652e39f53ea9", size = 78521, upload-time = "2026-04-28T19:01:10.393Z" }, +] + +[[package]] +name = "markdown" +version = "3.10.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/2b/f4/69fa6ed85ae003c2378ffa8f6d2e3234662abd02c10d216c0ba96081a238/markdown-3.10.2.tar.gz", hash = "sha256:994d51325d25ad8aa7ce4ebaec003febcce822c3f8c911e3b17c52f7f589f950", size = 368805, upload-time = "2026-02-09T14:57:26.942Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/de/1f/77fa3081e4f66ca3576c896ae5d31c3002ac6607f9747d2e3aa49227e464/markdown-3.10.2-py3-none-any.whl", hash = "sha256:e91464b71ae3ee7afd3017d9f358ef0baf158fd9a298db92f1d4761133824c36", size = 108180, upload-time = "2026-02-09T14:57:25.787Z" }, +] + +[[package]] +name = "markdown-it-py" +version = "4.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mdurl" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/06/ff/7841249c247aa650a76b9ee4bbaeae59370dc8bfd2f6c01f3630c35eb134/markdown_it_py-4.2.0.tar.gz", hash = "sha256:04a21681d6fbb623de53f6f364d352309d4094dd4194040a10fd51833e418d49", size = 82454, upload-time = "2026-05-07T12:08:28.36Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl", hash = "sha256:9f7ebbcd14fe59494226453aed97c1070d83f8d24b6fc3a3bcf9a38092641c4a", size = 91687, upload-time = "2026-05-07T12:08:27.182Z" }, +] + +[[package]] +name = "markupsafe" +version = "3.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7e/99/7690b6d4034fffd95959cbe0c02de8deb3098cc577c67bb6a24fe5d7caa7/markupsafe-3.0.3.tar.gz", hash = "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698", size = 80313, upload-time = "2025-09-27T18:37:40.426Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/08/db/fefacb2136439fc8dd20e797950e749aa1f4997ed584c62cfb8ef7c2be0e/markupsafe-3.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1cc7ea17a6824959616c525620e387f6dd30fec8cb44f649e31712db02123dad", size = 11631, upload-time = "2025-09-27T18:36:18.185Z" }, + { url = "https://files.pythonhosted.org/packages/e1/2e/5898933336b61975ce9dc04decbc0a7f2fee78c30353c5efba7f2d6ff27a/markupsafe-3.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4bd4cd07944443f5a265608cc6aab442e4f74dff8088b0dfc8238647b8f6ae9a", size = 12058, upload-time = "2025-09-27T18:36:19.444Z" }, + { url = "https://files.pythonhosted.org/packages/1d/09/adf2df3699d87d1d8184038df46a9c80d78c0148492323f4693df54e17bb/markupsafe-3.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b5420a1d9450023228968e7e6a9ce57f65d148ab56d2313fcd589eee96a7a50", size = 24287, upload-time = "2025-09-27T18:36:20.768Z" }, + { url = "https://files.pythonhosted.org/packages/30/ac/0273f6fcb5f42e314c6d8cd99effae6a5354604d461b8d392b5ec9530a54/markupsafe-3.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0bf2a864d67e76e5c9a34dc26ec616a66b9888e25e7b9460e1c76d3293bd9dbf", size = 22940, upload-time = "2025-09-27T18:36:22.249Z" }, + { url = "https://files.pythonhosted.org/packages/19/ae/31c1be199ef767124c042c6c3e904da327a2f7f0cd63a0337e1eca2967a8/markupsafe-3.0.3-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc51efed119bc9cfdf792cdeaa4d67e8f6fcccab66ed4bfdd6bde3e59bfcbb2f", size = 21887, upload-time = "2025-09-27T18:36:23.535Z" }, + { url = "https://files.pythonhosted.org/packages/b2/76/7edcab99d5349a4532a459e1fe64f0b0467a3365056ae550d3bcf3f79e1e/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:068f375c472b3e7acbe2d5318dea141359e6900156b5b2ba06a30b169086b91a", size = 23692, upload-time = "2025-09-27T18:36:24.823Z" }, + { url = "https://files.pythonhosted.org/packages/a4/28/6e74cdd26d7514849143d69f0bf2399f929c37dc2b31e6829fd2045b2765/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:7be7b61bb172e1ed687f1754f8e7484f1c8019780f6f6b0786e76bb01c2ae115", size = 21471, upload-time = "2025-09-27T18:36:25.95Z" }, + { url = "https://files.pythonhosted.org/packages/62/7e/a145f36a5c2945673e590850a6f8014318d5577ed7e5920a4b3448e0865d/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a", size = 22923, upload-time = "2025-09-27T18:36:27.109Z" }, + { url = "https://files.pythonhosted.org/packages/0f/62/d9c46a7f5c9adbeeeda52f5b8d802e1094e9717705a645efc71b0913a0a8/markupsafe-3.0.3-cp311-cp311-win32.whl", hash = "sha256:0db14f5dafddbb6d9208827849fad01f1a2609380add406671a26386cdf15a19", size = 14572, upload-time = "2025-09-27T18:36:28.045Z" }, + { url = "https://files.pythonhosted.org/packages/83/8a/4414c03d3f891739326e1783338e48fb49781cc915b2e0ee052aa490d586/markupsafe-3.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:de8a88e63464af587c950061a5e6a67d3632e36df62b986892331d4620a35c01", size = 15077, upload-time = "2025-09-27T18:36:29.025Z" }, + { url = "https://files.pythonhosted.org/packages/35/73/893072b42e6862f319b5207adc9ae06070f095b358655f077f69a35601f0/markupsafe-3.0.3-cp311-cp311-win_arm64.whl", hash = "sha256:3b562dd9e9ea93f13d53989d23a7e775fdfd1066c33494ff43f5418bc8c58a5c", size = 13876, upload-time = "2025-09-27T18:36:29.954Z" }, +] + +[[package]] +name = "mdurl" +version = "0.1.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" }, +] + +[[package]] +name = "mesido" +version = "0.1.20.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "casadi-gil-comp" }, + { name = "coolprop" }, + { name = "influxdb" }, + { name = "pandas" }, + { name = "pyecore" }, + { name = "pyesdl", extra = ["profiles"] }, + { name = "pymoca" }, + { name = "rtc-tools-gil-comp" }, + { name = "setuptools" }, + { name = "strenum" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/1b/ca/071cb7540708108f3f72f5f692d4df80f91d327314861873383b869761ae/mesido-0.1.20.3.tar.gz", hash = "sha256:82302e5b4a7c09cf2353facbd48a8000ee94420f5ad8461d15fe117150f83b93", size = 441829, upload-time = "2026-07-15T14:33:04.584Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/91/14/f54fe73742a29c7ac97473c964db40d2ca1fe3a5d44229dd0082a199d582/mesido-0.1.20.3-py3-none-any.whl", hash = "sha256:a2f87495cd9f32964ebf3ed3b8651261568fe33d834bc66c3b4531e39e60007d", size = 384963, upload-time = "2026-07-15T14:33:03.281Z" }, +] + +[[package]] +name = "msgpack" +version = "1.1.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/4d/f2/bfb55a6236ed8725a96b0aa3acbd0ec17588e6a2c3b62a93eb513ed8783f/msgpack-1.1.2.tar.gz", hash = "sha256:3b60763c1373dd60f398488069bcdc703cd08a711477b5d480eecc9f9626f47e", size = 173581, upload-time = "2025-10-08T09:15:56.596Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2c/97/560d11202bcd537abca693fd85d81cebe2107ba17301de42b01ac1677b69/msgpack-1.1.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2e86a607e558d22985d856948c12a3fa7b42efad264dca8a3ebbcfa2735d786c", size = 82271, upload-time = "2025-10-08T09:14:49.967Z" }, + { url = "https://files.pythonhosted.org/packages/83/04/28a41024ccbd67467380b6fb440ae916c1e4f25e2cd4c63abe6835ac566e/msgpack-1.1.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:283ae72fc89da59aa004ba147e8fc2f766647b1251500182fac0350d8af299c0", size = 84914, upload-time = "2025-10-08T09:14:50.958Z" }, + { url = "https://files.pythonhosted.org/packages/71/46/b817349db6886d79e57a966346cf0902a426375aadc1e8e7a86a75e22f19/msgpack-1.1.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:61c8aa3bd513d87c72ed0b37b53dd5c5a0f58f2ff9f26e1555d3bd7948fb7296", size = 416962, upload-time = "2025-10-08T09:14:51.997Z" }, + { url = "https://files.pythonhosted.org/packages/da/e0/6cc2e852837cd6086fe7d8406af4294e66827a60a4cf60b86575a4a65ca8/msgpack-1.1.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:454e29e186285d2ebe65be34629fa0e8605202c60fbc7c4c650ccd41870896ef", size = 426183, upload-time = "2025-10-08T09:14:53.477Z" }, + { url = "https://files.pythonhosted.org/packages/25/98/6a19f030b3d2ea906696cedd1eb251708e50a5891d0978b012cb6107234c/msgpack-1.1.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7bc8813f88417599564fafa59fd6f95be417179f76b40325b500b3c98409757c", size = 411454, upload-time = "2025-10-08T09:14:54.648Z" }, + { url = "https://files.pythonhosted.org/packages/b7/cd/9098fcb6adb32187a70b7ecaabf6339da50553351558f37600e53a4a2a23/msgpack-1.1.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bafca952dc13907bdfdedfc6a5f579bf4f292bdd506fadb38389afa3ac5b208e", size = 422341, upload-time = "2025-10-08T09:14:56.328Z" }, + { url = "https://files.pythonhosted.org/packages/e6/ae/270cecbcf36c1dc85ec086b33a51a4d7d08fc4f404bdbc15b582255d05ff/msgpack-1.1.2-cp311-cp311-win32.whl", hash = "sha256:602b6740e95ffc55bfb078172d279de3773d7b7db1f703b2f1323566b878b90e", size = 64747, upload-time = "2025-10-08T09:14:57.882Z" }, + { url = "https://files.pythonhosted.org/packages/2a/79/309d0e637f6f37e83c711f547308b91af02b72d2326ddd860b966080ef29/msgpack-1.1.2-cp311-cp311-win_amd64.whl", hash = "sha256:d198d275222dc54244bf3327eb8cbe00307d220241d9cec4d306d49a44e85f68", size = 71633, upload-time = "2025-10-08T09:14:59.177Z" }, + { url = "https://files.pythonhosted.org/packages/73/4d/7c4e2b3d9b1106cd0aa6cb56cc57c6267f59fa8bfab7d91df5adc802c847/msgpack-1.1.2-cp311-cp311-win_arm64.whl", hash = "sha256:86f8136dfa5c116365a8a651a7d7484b65b13339731dd6faebb9a0242151c406", size = 64755, upload-time = "2025-10-08T09:15:00.48Z" }, +] + +[[package]] +name = "multidict" +version = "6.7.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1a/c2/c2d94cbe6ac1753f3fc980da97b3d930efe1da3af3c9f5125354436c073d/multidict-6.7.1.tar.gz", hash = "sha256:ec6652a1bee61c53a3e5776b6049172c53b6aaba34f18c9ad04f82712bac623d", size = 102010, upload-time = "2026-01-26T02:46:45.979Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ce/f1/a90635c4f88fb913fbf4ce660b83b7445b7a02615bda034b2f8eb38fd597/multidict-6.7.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7ff981b266af91d7b4b3793ca3382e53229088d193a85dfad6f5f4c27fc73e5d", size = 76626, upload-time = "2026-01-26T02:43:26.485Z" }, + { url = "https://files.pythonhosted.org/packages/a6/9b/267e64eaf6fc637a15b35f5de31a566634a2740f97d8d094a69d34f524a4/multidict-6.7.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:844c5bca0b5444adb44a623fb0a1310c2f4cd41f402126bb269cd44c9b3f3e1e", size = 44706, upload-time = "2026-01-26T02:43:27.607Z" }, + { url = "https://files.pythonhosted.org/packages/dd/a4/d45caf2b97b035c57267791ecfaafbd59c68212004b3842830954bb4b02e/multidict-6.7.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f2a0a924d4c2e9afcd7ec64f9de35fcd96915149b2216e1cb2c10a56df483855", size = 44356, upload-time = "2026-01-26T02:43:28.661Z" }, + { url = "https://files.pythonhosted.org/packages/fd/d2/0a36c8473f0cbaeadd5db6c8b72d15bbceeec275807772bfcd059bef487d/multidict-6.7.1-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:8be1802715a8e892c784c0197c2ace276ea52702a0ede98b6310c8f255a5afb3", size = 244355, upload-time = "2026-01-26T02:43:31.165Z" }, + { url = "https://files.pythonhosted.org/packages/5d/16/8c65be997fd7dd311b7d39c7b6e71a0cb449bad093761481eccbbe4b42a2/multidict-6.7.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2e2d2ed645ea29f31c4c7ea1552fcfd7cb7ba656e1eafd4134a6620c9f5fdd9e", size = 246433, upload-time = "2026-01-26T02:43:32.581Z" }, + { url = "https://files.pythonhosted.org/packages/01/fb/4dbd7e848d2799c6a026ec88ad39cf2b8416aa167fcc903baa55ecaa045c/multidict-6.7.1-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:95922cee9a778659e91db6497596435777bd25ed116701a4c034f8e46544955a", size = 225376, upload-time = "2026-01-26T02:43:34.417Z" }, + { url = "https://files.pythonhosted.org/packages/b6/8a/4a3a6341eac3830f6053062f8fbc9a9e54407c80755b3f05bc427295c2d0/multidict-6.7.1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6b83cabdc375ffaaa15edd97eb7c0c672ad788e2687004990074d7d6c9b140c8", size = 257365, upload-time = "2026-01-26T02:43:35.741Z" }, + { url = "https://files.pythonhosted.org/packages/f7/a2/dd575a69c1aa206e12d27d0770cdf9b92434b48a9ef0cd0d1afdecaa93c4/multidict-6.7.1-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:38fb49540705369bab8484db0689d86c0a33a0a9f2c1b197f506b71b4b6c19b0", size = 254747, upload-time = "2026-01-26T02:43:36.976Z" }, + { url = "https://files.pythonhosted.org/packages/5a/56/21b27c560c13822ed93133f08aa6372c53a8e067f11fbed37b4adcdac922/multidict-6.7.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:439cbebd499f92e9aa6793016a8acaa161dfa749ae86d20960189f5398a19144", size = 246293, upload-time = "2026-01-26T02:43:38.258Z" }, + { url = "https://files.pythonhosted.org/packages/5a/a4/23466059dc3854763423d0ad6c0f3683a379d97673b1b89ec33826e46728/multidict-6.7.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6d3bc717b6fe763b8be3f2bee2701d3c8eb1b2a8ae9f60910f1b2860c82b6c49", size = 242962, upload-time = "2026-01-26T02:43:40.034Z" }, + { url = "https://files.pythonhosted.org/packages/1f/67/51dd754a3524d685958001e8fa20a0f5f90a6a856e0a9dcabff69be3dbb7/multidict-6.7.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:619e5a1ac57986dbfec9f0b301d865dddf763696435e2962f6d9cf2fdff2bb71", size = 237360, upload-time = "2026-01-26T02:43:41.752Z" }, + { url = "https://files.pythonhosted.org/packages/64/3f/036dfc8c174934d4b55d86ff4f978e558b0e585cef70cfc1ad01adc6bf18/multidict-6.7.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:0b38ebffd9be37c1170d33bc0f36f4f262e0a09bc1aac1c34c7aa51a7293f0b3", size = 245940, upload-time = "2026-01-26T02:43:43.042Z" }, + { url = "https://files.pythonhosted.org/packages/3d/20/6214d3c105928ebc353a1c644a6ef1408bc5794fcb4f170bb524a3c16311/multidict-6.7.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:10ae39c9cfe6adedcdb764f5e8411d4a92b055e35573a2eaa88d3323289ef93c", size = 253502, upload-time = "2026-01-26T02:43:44.371Z" }, + { url = "https://files.pythonhosted.org/packages/b1/e2/c653bc4ae1be70a0f836b82172d643fcf1dade042ba2676ab08ec08bff0f/multidict-6.7.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:25167cc263257660290fba06b9318d2026e3c910be240a146e1f66dd114af2b0", size = 247065, upload-time = "2026-01-26T02:43:45.745Z" }, + { url = "https://files.pythonhosted.org/packages/c8/11/a854b4154cd3bd8b1fd375e8a8ca9d73be37610c361543d56f764109509b/multidict-6.7.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:128441d052254f42989ef98b7b6a6ecb1e6f708aa962c7984235316db59f50fa", size = 241870, upload-time = "2026-01-26T02:43:47.054Z" }, + { url = "https://files.pythonhosted.org/packages/13/bf/9676c0392309b5fdae322333d22a829715b570edb9baa8016a517b55b558/multidict-6.7.1-cp311-cp311-win32.whl", hash = "sha256:d62b7f64ffde3b99d06b707a280db04fb3855b55f5a06df387236051d0668f4a", size = 41302, upload-time = "2026-01-26T02:43:48.753Z" }, + { url = "https://files.pythonhosted.org/packages/c9/68/f16a3a8ba6f7b6dc92a1f19669c0810bd2c43fc5a02da13b1cbf8e253845/multidict-6.7.1-cp311-cp311-win_amd64.whl", hash = "sha256:bdbf9f3b332abd0cdb306e7c2113818ab1e922dc84b8f8fd06ec89ed2a19ab8b", size = 45981, upload-time = "2026-01-26T02:43:49.921Z" }, + { url = "https://files.pythonhosted.org/packages/ac/ad/9dd5305253fa00cd3c7555dbef69d5bf4133debc53b87ab8d6a44d411665/multidict-6.7.1-cp311-cp311-win_arm64.whl", hash = "sha256:b8c990b037d2fff2f4e33d3f21b9b531c5745b33a49a7d6dbe7a177266af44f6", size = 43159, upload-time = "2026-01-26T02:43:51.635Z" }, + { url = "https://files.pythonhosted.org/packages/81/08/7036c080d7117f28a4af526d794aab6a84463126db031b007717c1a6676e/multidict-6.7.1-py3-none-any.whl", hash = "sha256:55d97cc6dae627efa6a6e548885712d4864b81110ac76fa4e534c03819fa4a56", size = 12319, upload-time = "2026-01-26T02:46:44.004Z" }, +] + +[[package]] +name = "numpy" +version = "1.25.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a0/41/8f53eff8e969dd8576ddfb45e7ed315407d27c7518ae49418be8ed532b07/numpy-1.25.2.tar.gz", hash = "sha256:fd608e19c8d7c55021dffd43bfe5492fab8cc105cc8986f813f8c3c048b38760", size = 10805282, upload-time = "2023-07-31T15:17:43.198Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c9/57/3cb8131a0e6d559501e088d3e685f4122e9ff9104c4b63e4dfd3a577b491/numpy-1.25.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c5462d19336db4560041517dbb7759c21d181a67cb01b36ca109b2ae37d32418", size = 20801693, upload-time = "2023-07-31T14:53:53.29Z" }, + { url = "https://files.pythonhosted.org/packages/86/a1/b8ef999c32f26a97b5f714887e21f96c12ae99a38583a0a96e65283ac0a1/numpy-1.25.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c5652ea24d33585ea39eb6a6a15dac87a1206a692719ff45d53c5282e66d4a8f", size = 14004130, upload-time = "2023-07-31T14:54:16.413Z" }, + { url = "https://files.pythonhosted.org/packages/50/67/3e966d99a07d60a21a21d7ec016e9e4c2642a86fea251ec68677daf71d4d/numpy-1.25.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d60fbae8e0019865fc4784745814cff1c421df5afee233db6d88ab4f14655a2", size = 14158219, upload-time = "2023-07-31T14:54:39.032Z" }, + { url = "https://files.pythonhosted.org/packages/32/6a/65dbc57a89078af9ff8bfcd4c0761a50172d90192eaeb1b6f56e5fbf1c3d/numpy-1.25.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:60e7f0f7f6d0eee8364b9a6304c2845b9c491ac706048c7e8cf47b83123b8dbf", size = 18209344, upload-time = "2023-07-31T14:55:08.584Z" }, + { url = "https://files.pythonhosted.org/packages/cd/fe/e900cb2ebafae04b7570081cefc65b6fdd9e202b9b353572506cea5cafdf/numpy-1.25.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:bb33d5a1cf360304754913a350edda36d5b8c5331a8237268c48f91253c3a364", size = 18072378, upload-time = "2023-07-31T14:55:39.551Z" }, + { url = "https://files.pythonhosted.org/packages/5c/e4/990c6cb09f2cd1a3f53bcc4e489dad903faa01b058b625d84bb62d2e9391/numpy-1.25.2-cp311-cp311-win32.whl", hash = "sha256:5883c06bb92f2e6c8181df7b39971a5fb436288db58b5a1c3967702d4278691d", size = 12654351, upload-time = "2023-07-31T14:56:10.623Z" }, + { url = "https://files.pythonhosted.org/packages/72/b2/02770e60c4e2f7e158d923ab0dea4e9f146a2dbf267fec6d8dc61d475689/numpy-1.25.2-cp311-cp311-win_amd64.whl", hash = "sha256:5c97325a0ba6f9d041feb9390924614b60b99209a71a69c876f71052521d42a4", size = 15546748, upload-time = "2023-07-31T14:57:13.015Z" }, +] + +[[package]] +name = "oauthlib" +version = "3.3.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0b/5f/19930f824ffeb0ad4372da4812c50edbd1434f678c90c2733e1188edfc63/oauthlib-3.3.1.tar.gz", hash = "sha256:0f0f8aa759826a193cf66c12ea1af1637f87b9b4622d46e866952bb022e538c9", size = 185918, upload-time = "2025-06-19T22:48:08.269Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/be/9c/92789c596b8df838baa98fa71844d84283302f7604ed565dafe5a6b5041a/oauthlib-3.3.1-py3-none-any.whl", hash = "sha256:88119c938d2b8fb88561af5f6ee0eec8cc8d552b7bb1f712743136eb7523b7a1", size = 160065, upload-time = "2025-06-19T22:48:06.508Z" }, +] + +[[package]] +name = "omotes-optimizer-worker" +version = "0.0.1" +source = { editable = "." } +dependencies = [ + { name = "mesido" }, + { name = "omotes-sdk-python" }, + { name = "pyesdl" }, + { name = "python-dotenv" }, +] + +[package.dev-dependencies] +dev = [ + { name = "build" }, + { name = "pip-tools" }, + { name = "pytest" }, + { name = "pytest-cov" }, + { name = "ruff" }, + { name = "setuptools" }, + { name = "ty" }, + { name = "wheel" }, +] + +[package.metadata] +requires-dist = [ + { name = "mesido", specifier = "~=0.1.20.3" }, + { name = "omotes-sdk-python", specifier = "==5.0.1" }, + { name = "pyesdl", specifier = "~=26.7" }, + { name = "python-dotenv", specifier = "~=1.0.0" }, +] + +[package.metadata.requires-dev] +dev = [ + { name = "build", specifier = "~=1.2.2" }, + { name = "pip-tools", specifier = "~=7.4.0" }, + { name = "pytest", specifier = "~=8.3.4" }, + { name = "pytest-cov", specifier = "~=6.0.0" }, + { name = "ruff", specifier = "~=0.15.22" }, + { name = "setuptools", specifier = "~=75.6.0" }, + { name = "ty", specifier = "~=0.0.61" }, + { name = "wheel", specifier = "~=0.45.1" }, +] + +[[package]] +name = "omotes-sdk-python" +version = "5.0.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "prefect" }, + { name = "s3fs" }, + { name = "streamcapture" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/fa/48/0e2dc6faf0dbe4115f3aa3205fb4252ce30e111cff2403c2daea212301c4/omotes_sdk_python-5.0.1.tar.gz", hash = "sha256:c4dd22943d1cdde29a96f0b6f416e699c56a51abd0f13ec482ff238f36d32535", size = 24840, upload-time = "2026-07-28T15:57:58.87Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/19/ea/bdb96e4371ae46171e05615c57c102faa25a946805164d2c560c0715d922/omotes_sdk_python-5.0.1-py3-none-any.whl", hash = "sha256:990affd855439fe01f50a64e1b782f410b718f5d05f2cd233018cae650ecfc4d", size = 21613, upload-time = "2026-07-28T15:57:57.696Z" }, +] + +[[package]] +name = "openpyxl" +version = "3.1.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "et-xmlfile" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/42/e8/af028681d493814ca9c2ff8106fc62a4a32e4e0ae14602c2a98fc7b741c8/openpyxl-3.1.2.tar.gz", hash = "sha256:a6f5977418eff3b2d5500d54d9db50c8277a368436f4e4f8ddb1be3422870184", size = 185977, upload-time = "2023-03-11T16:58:38.78Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6a/94/a59521de836ef0da54aaf50da6c4da8fb4072fb3053fa71f052fd9399e7a/openpyxl-3.1.2-py2.py3-none-any.whl", hash = "sha256:f91456ead12ab3c6c2e9491cf33ba6d08357d802192379bb482f1033ade496f5", size = 249985, upload-time = "2023-03-11T16:58:36.257Z" }, +] + +[[package]] +name = "opentelemetry-api" +version = "1.44.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ee/8b/aa9e2d8b8dfa7c946f7dec5d1f8f6ba8eca062f43509a06bdb5ce93d26c0/opentelemetry_api-1.44.0.tar.gz", hash = "sha256:67647e5e9566edcf421166fdf022b3537f818635daa852b289e34604dc6fb33a", size = 72406, upload-time = "2026-07-16T15:25:32.678Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ca/6f/a04e900f465ff3221ccc395522503e2d10e79fa21f2723c8e177aae1e0d1/opentelemetry_api-1.44.0-py3-none-any.whl", hash = "sha256:94b98c893a91b88657eaac1e3ba89618cdb85be6918196705354f34728b2cdef", size = 60018, upload-time = "2026-07-16T15:25:11.657Z" }, +] + +[[package]] +name = "ordered-set" +version = "4.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/4c/ca/bfac8bc689799bcca4157e0e0ced07e70ce125193fc2e166d2e685b7e2fe/ordered-set-4.1.0.tar.gz", hash = "sha256:694a8e44c87657c59292ede72891eb91d34131f6531463aab3009191c77364a8", size = 12826, upload-time = "2022-01-26T14:38:56.6Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/33/55/af02708f230eb77084a299d7b08175cff006dea4f2721074b92cdb0296c0/ordered_set-4.1.0-py3-none-any.whl", hash = "sha256:046e1132c71fcf3330438a539928932caf51ddbc582496833e23de611de14562", size = 7634, upload-time = "2022-01-26T14:38:48.677Z" }, +] + +[[package]] +name = "orjson" +version = "3.11.9" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7e/0c/964746fcafbd16f8ff53219ad9f6b412b34f345c75f384ad434ceaadb538/orjson-3.11.9.tar.gz", hash = "sha256:4fef17e1f8722c11587a6ef18e35902450221da0028e65dbaaa543619e68e48f", size = 5599163, upload-time = "2026-05-06T15:11:08.309Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1e/51/3fb9e65ae76ee97bd611869a503fa3fc0a6e81dd8b737cf3003f682df7ff/orjson-3.11.9-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:f01c4818b3fc9b0da8e096722a84318071eaa118df35f6ed2344da0e73a5444f", size = 228522, upload-time = "2026-05-06T15:09:35.362Z" }, + { url = "https://files.pythonhosted.org/packages/16/fa/9d54b07cb3f3b0bfd57841478e42d7a0ece4a9f49f9907eecf5a45461687/orjson-3.11.9-cp311-cp311-macosx_15_0_arm64.whl", hash = "sha256:3ebca4179031ee716ed076ffadc29428e900512f6fccee8614c9983157fcf19c", size = 128463, upload-time = "2026-05-06T15:09:37.063Z" }, + { url = "https://files.pythonhosted.org/packages/88/b1/6ceafc2eefd0a553e3be77ce6c49d107e772485d9568629376171c50e634/orjson-3.11.9-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48ee05097750de0ff69ed5b7bbcf0732182fd57a24043dcc2a1da780a5ead3a5", size = 132306, upload-time = "2026-05-06T15:09:38.299Z" }, + { url = "https://files.pythonhosted.org/packages/ea/76/f11311285324a40aab1e3031385c50b635a7cd0734fdaf60c7e89a696f60/orjson-3.11.9-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a6082706765a95a6680d812e1daf1c0cfe8adec7831b3ff3b625693f3b461b1c", size = 127988, upload-time = "2026-05-06T15:09:39.597Z" }, + { url = "https://files.pythonhosted.org/packages/9e/85/0ef63bcf1337f44031ce9b91b1919563f62a37527b3ea4368bb15a22e5d7/orjson-3.11.9-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:277fefe9d76ee17eb14debf399e3533d4d63b5f677a4d3719eb763536af1f4bd", size = 135188, upload-time = "2026-05-06T15:09:40.957Z" }, + { url = "https://files.pythonhosted.org/packages/05/94/b0d27090ea8a2095db3c2bd1b1c96f96f19bbb494d7fef33130e846e613d/orjson-3.11.9-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:03db380e3780fa0015ed776a90f20e8e20bb11dde13b216ce19e5718e3dfba62", size = 145937, upload-time = "2026-05-06T15:09:42.249Z" }, + { url = "https://files.pythonhosted.org/packages/09/eb/75d50c29c05b8054013e221e598820a365c8e64065312e75e202ed880709/orjson-3.11.9-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33d7d766701847dc6729846362dc27895d2f2d2251264f9d10e7cb9878194877", size = 132758, upload-time = "2026-05-06T15:09:43.945Z" }, + { url = "https://files.pythonhosted.org/packages/49/bd/360686f39348aa88827cb6fbf7dc606fd41c831a35235e1abf1db8e3a9e6/orjson-3.11.9-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:147302878da387104b66bb4a8b0227d1d487e976ce41a8501916161072ed87b1", size = 133971, upload-time = "2026-05-06T15:09:45.239Z" }, + { url = "https://files.pythonhosted.org/packages/0e/30/3178eb16f3221aeef068b6f1f1ebe05f656ea5c6dffe9f6c917329fe17a3/orjson-3.11.9-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3513550321f8c8c811a7c3297b8a630e82dc08e4c10216d07703c997776236cd", size = 141685, upload-time = "2026-05-06T15:09:46.858Z" }, + { url = "https://files.pythonhosted.org/packages/5f/f1/ff2f19ed0225f9680fafa42febca3570dd59444ebf190980738d376214c2/orjson-3.11.9-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:c5d001196b89fa9cf0a4ab79766cd835b991a166e4b621ba95089edc50c429ff", size = 415167, upload-time = "2026-05-06T15:09:48.312Z" }, + { url = "https://files.pythonhosted.org/packages/9b/61/863bddf0da6e9e586765414debd54b4e58db05f560902b6d00658cb88636/orjson-3.11.9-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:16969c9d369c98eb084889c6e4d2d39b77c7eb38ceccf8da2a9fff62ae908980", size = 147913, upload-time = "2026-05-06T15:09:49.733Z" }, + { url = "https://files.pythonhosted.org/packages/b6/8a/4081492586d75b073d60c5271a8d0f05a0955cabf1e34c8473f6fcd84235/orjson-3.11.9-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:63e0efbc991250c0b3143488fa57d95affcabbfc63c99c48d625dd37779aafe2", size = 136959, upload-time = "2026-05-06T15:09:51.311Z" }, + { url = "https://files.pythonhosted.org/packages/0d/bd/70b6ab193594d7abb875320c0a7c8335e846f28968c432c31042409c3c8d/orjson-3.11.9-cp311-cp311-win32.whl", hash = "sha256:14ed654580c1ed2bc217352ec82f91b047aef82951aa71c7f64e0dcb03c0e180", size = 131533, upload-time = "2026-05-06T15:09:52.637Z" }, + { url = "https://files.pythonhosted.org/packages/3f/17/1a1a228183d62d1b77e2c30d210f47dd4768b310ebe1607c63e3c0e3a71e/orjson-3.11.9-cp311-cp311-win_amd64.whl", hash = "sha256:57ea77fb70a448ce87d18fca050193202a3da5e54598f6501ca5476fb66cfe02", size = 127106, upload-time = "2026-05-06T15:09:54.204Z" }, + { url = "https://files.pythonhosted.org/packages/b8/95/285de5fa296d09681ee9c546cd4a8aeb773b701cf343dc125994f4d52953/orjson-3.11.9-cp311-cp311-win_arm64.whl", hash = "sha256:19b72ed11572a2ee51a67a903afbe5af504f84ed6f529c0fe44b0ab3fb5cc697", size = 126848, upload-time = "2026-05-06T15:09:55.551Z" }, +] + +[[package]] +name = "packaging" +version = "25.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727, upload-time = "2025-04-19T11:48:59.673Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" }, +] + +[[package]] +name = "pandas" +version = "1.5.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy" }, + { name = "python-dateutil" }, + { name = "pytz" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/74/ee/146cab1ff6d575b54ace8a6a5994048380dc94879b0125b25e62edcb9e52/pandas-1.5.3.tar.gz", hash = "sha256:74a3fd7e5a7ec052f183273dc7b0acd3a863edf7520f5d3a1765c04ffdb3b0b1", size = 5203060, upload-time = "2023-01-19T08:31:39.615Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e2/24/a26af514113fd5eca2d8fe41ba4f22f70dfe6afefde4a6beb6a203570935/pandas-1.5.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6973549c01ca91ec96199e940495219c887ea815b2083722821f1d7abfa2b4dc", size = 18387750, upload-time = "2023-01-19T08:29:43.119Z" }, + { url = "https://files.pythonhosted.org/packages/53/c9/d2f910dace7ef849b626980d0fd033b9cded36568949c8d560c9630ad2e0/pandas-1.5.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c39a8da13cede5adcd3be1182883aea1c925476f4e84b2807a46e2775306305d", size = 11868668, upload-time = "2023-01-19T08:29:48.733Z" }, + { url = "https://files.pythonhosted.org/packages/b0/be/1843b9aff84b98899663e7cad9f45513dfdd11d69cb5bd85c648aaf6a8d4/pandas-1.5.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f76d097d12c82a535fda9dfe5e8dd4127952b45fea9b0276cb30cca5ea313fbc", size = 10814036, upload-time = "2023-01-19T08:29:54.886Z" }, + { url = "https://files.pythonhosted.org/packages/63/8d/c2bd356b9d4baf1c5cf8d7e251fb4540e87083072c905430da48c2bb31eb/pandas-1.5.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e474390e60ed609cec869b0da796ad94f420bb057d86784191eefc62b65819ae", size = 11374218, upload-time = "2023-01-19T08:30:00.5Z" }, + { url = "https://files.pythonhosted.org/packages/56/73/3351beeb807dca69fcc3c4966bcccc51552bd01549a9b13c04ab00a43f21/pandas-1.5.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f2b952406a1588ad4cad5b3f55f520e82e902388a6d5a4a91baa8d38d23c7f6", size = 12017319, upload-time = "2023-01-19T08:30:06.097Z" }, + { url = "https://files.pythonhosted.org/packages/da/6d/1235da14daddaa6e47f74ba0c255358f0ce7a6ee05da8bf8eb49161aa6b5/pandas-1.5.3-cp311-cp311-win_amd64.whl", hash = "sha256:bc4c368f42b551bf72fac35c5128963a171b40dce866fb066540eeaf46faa003", size = 10303385, upload-time = "2023-01-19T08:30:11.148Z" }, +] + +[[package]] +name = "pathspec" +version = "1.1.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5a/82/42f767fc1c1143d6fd36efb827202a2d997a375e160a71eb2888a925aac1/pathspec-1.1.1.tar.gz", hash = "sha256:17db5ecd524104a120e173814c90367a96a98d07c45b2e10c2f3919fff91bf5a", size = 135180, upload-time = "2026-04-27T01:46:08.907Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f1/d9/7fb5aa316bc299258e68c73ba3bddbc499654a07f151cba08f6153988714/pathspec-1.1.1-py3-none-any.whl", hash = "sha256:a00ce642f577bf7f473932318056212bc4f8bfdf53128c78bbd5af0b9b20b189", size = 57328, upload-time = "2026-04-27T01:46:07.06Z" }, +] + +[[package]] +name = "pendulum" +version = "3.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "python-dateutil" }, + { name = "tzdata" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/cb/72/9a51afa0a822b09e286c4cb827ed7b00bc818dac7bd11a5f161e493a217d/pendulum-3.2.0.tar.gz", hash = "sha256:e80feda2d10fa3ff8b1526715f7d33dcb7e08494b3088f2c8a3ac92d4a4331ce", size = 86912, upload-time = "2026-01-30T11:22:24.093Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c4/27/a4be6ec12161b503dd036f8d7cc57f8626170ae31bb298038be9af0001ce/pendulum-3.2.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:5d775cc608c909ad415c8e789c84a9f120bb6a794c4215b2d8d910893cf0ec6a", size = 337923, upload-time = "2026-01-30T11:20:51.61Z" }, + { url = "https://files.pythonhosted.org/packages/59/e1/2a214e18355ec2a6ce3f683a97eecdb6050866ff3a6cf165d411450aeb1b/pendulum-3.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8de794a7f665aebc8c1ba4dd4b05ab8fe1a36ce9c0498366adf1d1edd79b2686", size = 327379, upload-time = "2026-01-30T11:20:53.085Z" }, + { url = "https://files.pythonhosted.org/packages/9d/01/7392e58ebc1d9e70b987dc8bb0c89710b47ac8125067efe7aa4c420b616f/pendulum-3.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bac7df7696e1c942e17c0556b3a7bcdd1d7aa5b24faee7620cb071e754a0622", size = 340115, upload-time = "2026-01-30T11:20:54.635Z" }, + { url = "https://files.pythonhosted.org/packages/ef/33/80de84c5ca1a3e4f7f3b75090c9b61b6dbb6d095e302ee592cebbaf0bbfb/pendulum-3.2.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:db0f6a8a04475d9cba26ce701e7d66d266fd97227f2f5f499270eba04be1c7e9", size = 373969, upload-time = "2026-01-30T11:20:56.209Z" }, + { url = "https://files.pythonhosted.org/packages/75/e4/f7b4c1818927ab394a2a0a9b7011f360a0a75839a22678833c5bc0a84183/pendulum-3.2.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c352c63c1ff05f2198409b28498d7158547a8be23e1fbd4aa2cf5402fb239b55", size = 379058, upload-time = "2026-01-30T11:20:57.618Z" }, + { url = "https://files.pythonhosted.org/packages/36/94/9947cf710620afcc68751683f2f8de88d902505e7c13c0349d7e9d362f97/pendulum-3.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de8c1ad1d1aa7d4ceae341528bab35a0f8c88a5aa63f2f5d84e16b517d1b32c2", size = 348403, upload-time = "2026-01-30T11:20:59.56Z" }, + { url = "https://files.pythonhosted.org/packages/6f/12/0e6ba0bb00fa57907af2a3fca8643bded5dba1e87072d50673776a0d6ed2/pendulum-3.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:1ba955511c12fec2252038b0c866c25c0c30b720bf74d3023710f121e42b1498", size = 517457, upload-time = "2026-01-30T11:21:01.602Z" }, + { url = "https://files.pythonhosted.org/packages/c6/fe/dae5fbfe67bd41d943def0ad8f1e7f6988aa8e527255e433cd7c494f9ad5/pendulum-3.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4115bf364a2ec6d5ddc476751ceaa4164a04f2c15589f0d29aa210ddb784b15d", size = 561103, upload-time = "2026-01-30T11:21:03.924Z" }, + { url = "https://files.pythonhosted.org/packages/ce/a0/8f646160b98abfc19152505af19bd643a4279ec2bdbe0959f16b7025fc6b/pendulum-3.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:4151a903356413fdd9549de0997b708fb95a214ed97803ffb479ffd834088378", size = 260595, upload-time = "2026-01-30T11:21:05.495Z" }, + { url = "https://files.pythonhosted.org/packages/79/01/feead7af9ded7a13f2d798fb6573e70f469113eafcd8cc8f59671584ca3e/pendulum-3.2.0-cp311-cp311-win_arm64.whl", hash = "sha256:acfdee9ddc56053cb7c8c075afbfde0857322d09e56a56195b9cd127fae87e4c", size = 255382, upload-time = "2026-01-30T11:21:06.847Z" }, + { url = "https://files.pythonhosted.org/packages/c9/0d/d5ac8468a1b40f09a62d6e91654088de432367907579dd161c0fb1bdf222/pendulum-3.2.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:9585594d32faa71efa5a78f576f1ee4f79e9c5340d7c6f0cd6c5dfe725effaaa", size = 338760, upload-time = "2026-01-30T11:22:12.225Z" }, + { url = "https://files.pythonhosted.org/packages/a0/e5/7fa8c8be6caac8e0be78fbe7668df571f44820ed779cb3736fab645fcba8/pendulum-3.2.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:26401e2de77c437e8f3b6160c08c6c5d45518d906f8f9b48fd7cb5aa0f4e2aff", size = 328333, upload-time = "2026-01-30T11:22:13.811Z" }, + { url = "https://files.pythonhosted.org/packages/ad/78/73a1031b7d1bf7986e8e655cea3f018164b3470aecfea25a4074e77dda73/pendulum-3.2.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:637e65af042f383a2764a886aa28ccc6f853bf7a142df18e41c720542934c13b", size = 340841, upload-time = "2026-01-30T11:22:15.278Z" }, + { url = "https://files.pythonhosted.org/packages/49/40/4e36e9074e92b0164c088b9ada3c02bfea386d83e24fa98b30fe9b6e61a8/pendulum-3.2.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d6e46c28f4d067233c4a4c42748f4ffa641d9289c09e0e81488beb6d4b3fab51", size = 348959, upload-time = "2026-01-30T11:22:16.718Z" }, + { url = "https://files.pythonhosted.org/packages/24/99/8bf7fcb91b526e1efe17d047faa845709b88800fff915ff848ff26054293/pendulum-3.2.0-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:71d46bcc86269f97bfd8c5f1475d55e717696a0a010b1871023605ca94624031", size = 518102, upload-time = "2026-01-30T11:22:18.2Z" }, + { url = "https://files.pythonhosted.org/packages/b8/b0/a36c468d2d0dec62ddea7c5e4177e93abb12f48ac90f09f24d0581c5189f/pendulum-3.2.0-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:5cd956d4176afc7bfe8a91bf3f771b46ff8d326f6c5bf778eb5010eb742ebba6", size = 561884, upload-time = "2026-01-30T11:22:19.671Z" }, + { url = "https://files.pythonhosted.org/packages/c5/4d/dad105261898907bf806cabca53d3878529a9fa2c0d5d7f95f2035246fc2/pendulum-3.2.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:39ef129d7b90aab49708645867abdd207b714ba7bff12dae549975b0aca09716", size = 261236, upload-time = "2026-01-30T11:22:21.059Z" }, + { url = "https://files.pythonhosted.org/packages/02/fb/d65db067a67df7252f18b0cb7420dda84078b9e8bfb375215469c14a50be/pendulum-3.2.0-py3-none-any.whl", hash = "sha256:f3a9c18a89b4d9ef39c5fa6a78722aaff8d5be2597c129a3b16b9f40a561acf3", size = 114111, upload-time = "2026-01-30T11:22:22.361Z" }, +] + +[[package]] +name = "pip" +version = "26.1.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/01/91/47e7d486260f618783899587af63ccf7980fb60245c3e63dd4571c6b57ad/pip-26.1.2.tar.gz", hash = "sha256:f49cd134c61cf2fd75e0ce2676db03e4054504a5a4986d00f8299ae632dc4605", size = 1840799, upload-time = "2026-05-31T17:33:58.56Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5d/95/6b5cb3461ea5673ba0995989746db58eb18b91b54dbf331e72f569540946/pip-26.1.2-py3-none-any.whl", hash = "sha256:382ff9f685ee3bc25864f820aa50505825f10f5458ffff07e30a6d96e5715cab", size = 1813144, upload-time = "2026-05-31T17:33:56.772Z" }, +] + +[[package]] +name = "pip-tools" +version = "7.4.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "build" }, + { name = "click" }, + { name = "pip" }, + { name = "pyproject-hooks" }, + { name = "setuptools" }, + { name = "wheel" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/1a/87/1ef453f10fb0772f43549686f924460cc0a2404b828b348f72c52cb2f5bf/pip-tools-7.4.1.tar.gz", hash = "sha256:864826f5073864450e24dbeeb85ce3920cdfb09848a3d69ebf537b521f14bcc9", size = 145417, upload-time = "2024-03-06T12:13:23.533Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0d/dc/38f4ce065e92c66f058ea7a368a9c5de4e702272b479c0992059f7693941/pip_tools-7.4.1-py3-none-any.whl", hash = "sha256:4c690e5fbae2f21e87843e89c26191f0d9454f362d8acdbd695716493ec8b3a9", size = 61235, upload-time = "2024-03-06T12:13:40.124Z" }, +] + +[[package]] +name = "pluggy" +version = "1.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" }, +] + +[[package]] +name = "prefect" +version = "3.7.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "aiosqlite" }, + { name = "alembic" }, + { name = "amplitude-analytics" }, + { name = "anyio" }, + { name = "apprise" }, + { name = "asgi-lifespan" }, + { name = "asyncpg" }, + { name = "cachetools" }, + { name = "click" }, + { name = "cloudpickle" }, + { name = "coolname" }, + { name = "cryptography" }, + { name = "cyclopts" }, + { name = "dateparser" }, + { name = "docker" }, + { name = "exceptiongroup" }, + { name = "fastapi" }, + { name = "fsspec" }, + { name = "graphviz" }, + { name = "griffe" }, + { name = "httpcore" }, + { name = "httpx", extra = ["http2"] }, + { name = "humanize" }, + { name = "jinja2" }, + { name = "jinja2-humanize-extension" }, + { name = "jsonpatch" }, + { name = "jsonschema" }, + { name = "opentelemetry-api" }, + { name = "orjson" }, + { name = "packaging" }, + { name = "pathspec" }, + { name = "pendulum" }, + { name = "pluggy" }, + { name = "prometheus-client" }, + { name = "pydantic" }, + { name = "pydantic-core" }, + { name = "pydantic-extra-types" }, + { name = "pydantic-settings" }, + { name = "pydocket" }, + { name = "python-dateutil" }, + { name = "python-slugify" }, + { name = "pytz" }, + { name = "pyyaml" }, + { name = "readchar" }, + { name = "rfc3339-validator" }, + { name = "rich" }, + { name = "ruamel-yaml" }, + { name = "ruamel-yaml-clib", marker = "platform_python_implementation == 'CPython'" }, + { name = "semver" }, + { name = "sniffio" }, + { name = "sqlalchemy", extra = ["asyncio"] }, + { name = "starlette" }, + { name = "toml" }, + { name = "typing-extensions" }, + { name = "uvicorn" }, + { name = "websockets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e7/51/4b17109cac94607e3eecc3a0ff0d21aa40e812772a3269b78d28acf2236c/prefect-3.7.3.tar.gz", hash = "sha256:fd4f03474773af9af7f135f30cd9916bb371f88e499caec799ebd1921795d028", size = 14083737, upload-time = "2026-06-01T16:29:55.017Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/92/74/3a76454e24537429b010634896b8a51d3409ad7158b84114415085184de2/prefect-3.7.3-py3-none-any.whl", hash = "sha256:4266e950eb909b3c377d54e7b477e7ca614a69cd1190fbba6b24456dc06ec9d9", size = 14963599, upload-time = "2026-06-01T16:29:51.549Z" }, +] + +[[package]] +name = "prometheus-client" +version = "0.26.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/52/73/f1334c29c2af4cd9dba6c7817e61b611bd0215e2eb5565c6064a4de18802/prometheus_client-0.26.0.tar.gz", hash = "sha256:04a91bcf94e2cf74a44a1a874d651a2e853ed354b6e822f3b7487751465d5c2b", size = 92910, upload-time = "2026-07-24T19:36:41.893Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/eb/a3/b69efbf4143b5b9859b977770bbbabcc2796b702fa69dc40271e45cd5a56/prometheus_client-0.26.0-py3-none-any.whl", hash = "sha256:fa93d06737aa02bacd05794768508bb97d2fbee28cb3bca04eaae92f0ca953d6", size = 64494, upload-time = "2026-07-24T19:36:40.854Z" }, +] + +[[package]] +name = "propcache" +version = "0.5.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ec/44/c87281c333769159c50594f22610f77398a47ccbfbbf23074e744e86f87c/propcache-0.5.2.tar.gz", hash = "sha256:01c4fc7480cd0598bb4b57022df55b9ca296da7fc5a8760bd8451a7e63a7d427", size = 50208, upload-time = "2026-05-08T21:02:12.199Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e7/f1/8a8cc1c2c7e7934ab77e0163414f736fadbc0f5e8dd9673b952355ac175b/propcache-0.5.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:74b70780220e2dd89175ca24b81b68b67c83db499ae611e7f2313cb329801c78", size = 90744, upload-time = "2026-05-08T20:59:45.799Z" }, + { url = "https://files.pythonhosted.org/packages/c2/f4/651b1225e976bd1a2ba5cfba0c29d096581c2636b437e3a9a7ab6276270a/propcache-0.5.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a4840ab0ae0216d952f4b53dc6d0b992bfc2bedbfe360bdd9b548bc184c08959", size = 52033, upload-time = "2026-05-08T20:59:47.408Z" }, + { url = "https://files.pythonhosted.org/packages/15/a8/8ede85d6aa1f79fc7dc2f8fd2c8d65920b8272c3892903c8a1affde48cfb/propcache-0.5.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c6844ba6364fb12f403928a82cfd295ab103a2b315c77c747b2dbe4a41894ea7", size = 52754, upload-time = "2026-05-08T20:59:49.202Z" }, + { url = "https://files.pythonhosted.org/packages/7d/fe/b3551b41bbc2f5b5bb088fc6920567cd43101253e68fbaa261339eb96fe1/propcache-0.5.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2293949b855ce597f2826452d17c2d545fb5622379c4ea6fdf525e9b8e8a2511", size = 57573, upload-time = "2026-05-08T20:59:50.778Z" }, + { url = "https://files.pythonhosted.org/packages/83/27/ab851ebd1b7172e3e161f5f8d39e315d54a91bea246f01f4d872d3376aef/propcache-0.5.2-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:0fd59b5af35f74da48d905dcbad55449ba13be91823cb05a9bd590bbf5b61660", size = 60645, upload-time = "2026-05-08T20:59:52.227Z" }, + { url = "https://files.pythonhosted.org/packages/95/7d/466b3d18022e9897cbda9c735c493c5bd747d7a4c6f5ea1480b4cec434b6/propcache-0.5.2-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:29f9309a2e42b0d273be006fdb4be2d6c39a47f6f57d8fb1cf9f81481df81b66", size = 61563, upload-time = "2026-05-08T20:59:53.866Z" }, + { url = "https://files.pythonhosted.org/packages/27/1b/16ab7f2cf2041da2f60d156ba64c2484eadf9168075b4ff43c3ef60045af/propcache-0.5.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5aaa2b923c1944ac8febd6609cb373540a5563e7cbcb0fd770f75dace2eb817b", size = 58888, upload-time = "2026-05-08T20:59:55.457Z" }, + { url = "https://files.pythonhosted.org/packages/0a/67/bb777ffd907633563bf35fd859c4ce97b0512c32f4633cf5d1eb7c33512b/propcache-0.5.2-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:66ea454f095ddf5b6b14f56c064c0941c4788be11e18d2464cf643bf7203ff67", size = 59253, upload-time = "2026-05-08T20:59:57.075Z" }, + { url = "https://files.pythonhosted.org/packages/b9/42/64f8d90b73fd9cdc1499b48057ff6d9cd2a98a25734c9bb62ecf07e87061/propcache-0.5.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:95f1e3f4760d404b13c9976c0229b2b49a3c8e2c62a9ce92efdd2b11ada75e3f", size = 57558, upload-time = "2026-05-08T20:59:58.602Z" }, + { url = "https://files.pythonhosted.org/packages/eb/02/dba5bc03c9041f2092ea55a449caf5dfe68352c6654511b29ba0654ddb69/propcache-0.5.2-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:85341b12b9d55bad0bded24cac341bb34289469e03a11f3f583ea1cc1db0326c", size = 55007, upload-time = "2026-05-08T20:59:59.837Z" }, + { url = "https://files.pythonhosted.org/packages/14/c0/43f649c7aa2a77a3b100d84e9dea3a483120ecb608bfe36ce49eaff517fe/propcache-0.5.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:26a4dca084132874e639895c3135dfad5eb20bae209f62d1aeb31b03e601c3c0", size = 60355, upload-time = "2026-05-08T21:00:01.144Z" }, + { url = "https://files.pythonhosted.org/packages/83/c0/435dafd27f1cb4a495381dae60e25883ccfe4020bb72818e8184c1678092/propcache-0.5.2-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:3b199b9b2b3d6a7edf3183ba8a9a137a22b97f7df525feb5ae1eccf026d2a9c6", size = 59057, upload-time = "2026-05-08T21:00:02.401Z" }, + { url = "https://files.pythonhosted.org/packages/53/ae/6e292df9135d659944e96cb3389258e4a663e5b2b5f6c217ef0ddc8d2f73/propcache-0.5.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:e59bc9e66329185b93dab73f210f1a37f81cb40f321501db8017c9aea15dba27", size = 61938, upload-time = "2026-05-08T21:00:03.638Z" }, + { url = "https://files.pythonhosted.org/packages/0b/42/314ebc50d8159055411fd6b0bda322ff510e4b1f7d2e4927940ad0f6af20/propcache-0.5.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:552ffadf6ad409844bc5919c42a0a83d88314cedddaea0e41e80a8b8fffe881f", size = 59731, upload-time = "2026-05-08T21:00:04.881Z" }, + { url = "https://files.pythonhosted.org/packages/b8/9b/2da6dee38871c3c8772fabc2758325a5c9077d6d18c597737dc04dd884cd/propcache-0.5.2-cp311-cp311-win32.whl", hash = "sha256:cd416c1de191973c52ff1a12a57446bfc7642797b282d7caf2162d7d1b8aa9a0", size = 38966, upload-time = "2026-05-08T21:00:06.511Z" }, + { url = "https://files.pythonhosted.org/packages/42/4e/f17363fb58c0afe05b067361cb6d86ed2d29de6506779a27547c4d183075/propcache-0.5.2-cp311-cp311-win_amd64.whl", hash = "sha256:44e488ef40dbb452700b2b1f8188934121f6648f52c295055662d2191959ff82", size = 42135, upload-time = "2026-05-08T21:00:08.088Z" }, + { url = "https://files.pythonhosted.org/packages/c6/eb/6af6685077d22e8b33358d3c548e3282706a0b3cd85044ffba4e5dd08e3b/propcache-0.5.2-cp311-cp311-win_arm64.whl", hash = "sha256:54adaa85a22078d1e306304a40984dc5be99d599bf3dc0a24dc98f7daeab89ab", size = 38381, upload-time = "2026-05-08T21:00:09.692Z" }, + { url = "https://files.pythonhosted.org/packages/3a/ed/1cdcab6ba3d6ab7feca11fc14f0eeea80755bb53ef4e892079f31b10a25f/propcache-0.5.2-py3-none-any.whl", hash = "sha256:be1ddfcbb376e3de5d2e2db1d58d6d67463e6b4f9f040c000de8e300295465fe", size = 14036, upload-time = "2026-05-08T21:02:10.673Z" }, +] + +[[package]] +name = "psycopg" +version = "3.3.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, + { name = "tzdata", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d3/b6/379d0a960f8f435ec78720462fd94c4863e7a31237cf81bf76d0af5883bf/psycopg-3.3.3.tar.gz", hash = "sha256:5e9a47458b3c1583326513b2556a2a9473a1001a56c9efe9e587245b43148dd9", size = 165624, upload-time = "2026-02-18T16:52:16.546Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c8/5b/181e2e3becb7672b502f0ed7f16ed7352aca7c109cfb94cf3878a9186db9/psycopg-3.3.3-py3-none-any.whl", hash = "sha256:f96525a72bcfade6584ab17e89de415ff360748c766f0106959144dcbb38c698", size = 212768, upload-time = "2026-02-18T16:46:27.365Z" }, +] + +[package.optional-dependencies] +binary = [ + { name = "psycopg-binary", marker = "implementation_name != 'pypy'" }, +] + +[[package]] +name = "psycopg-binary" +version = "3.3.3" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/be/c0/b389119dd754483d316805260f3e73cdcad97925839107cc7a296f6132b1/psycopg_binary-3.3.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a89bb9ee11177b2995d87186b1d9fa892d8ea725e85eab28c6525e4cc14ee048", size = 4609740, upload-time = "2026-02-18T16:47:51.093Z" }, + { url = "https://files.pythonhosted.org/packages/cf/e3/9976eef20f61840285174d360da4c820a311ab39d6b82fa09fbb545be825/psycopg_binary-3.3.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9f7d0cf072c6fbac3795b08c98ef9ea013f11db609659dcfc6b1f6cc31f9e181", size = 4676837, upload-time = "2026-02-18T16:47:55.523Z" }, + { url = "https://files.pythonhosted.org/packages/9f/f2/d28ba2f7404fd7f68d41e8a11df86313bd646258244cb12a8dd83b868a97/psycopg_binary-3.3.3-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:90eecd93073922f085967f3ed3a98ba8c325cbbc8c1a204e300282abd2369e13", size = 5497070, upload-time = "2026-02-18T16:47:59.929Z" }, + { url = "https://files.pythonhosted.org/packages/de/2f/6c5c54b815edeb30a281cfcea96dc93b3bb6be939aea022f00cab7aa1420/psycopg_binary-3.3.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:dac7ee2f88b4d7bb12837989ca354c38d400eeb21bce3b73dac02622f0a3c8d6", size = 5172410, upload-time = "2026-02-18T16:48:05.665Z" }, + { url = "https://files.pythonhosted.org/packages/51/75/8206c7008b57de03c1ada46bd3110cc3743f3fd9ed52031c4601401d766d/psycopg_binary-3.3.3-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b62cf8784eb6d35beaee1056d54caf94ec6ecf2b7552395e305518ab61eb8fd2", size = 6763408, upload-time = "2026-02-18T16:48:13.541Z" }, + { url = "https://files.pythonhosted.org/packages/d4/5a/ea1641a1e6c8c8b3454b0fcb43c3045133a8b703e6e824fae134088e63bd/psycopg_binary-3.3.3-cp311-cp311-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a39f34c9b18e8f6794cca17bfbcd64572ca2482318db644268049f8c738f35a6", size = 5006255, upload-time = "2026-02-18T16:48:22.176Z" }, + { url = "https://files.pythonhosted.org/packages/aa/fb/538df099bf55ae1637d52d7ccb6b9620b535a40f4c733897ac2b7bb9e14c/psycopg_binary-3.3.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:883d68d48ca9ff3cb3d10c5fdebea02c79b48eecacdddbf7cce6e7cdbdc216b8", size = 4532694, upload-time = "2026-02-18T16:48:27.338Z" }, + { url = "https://files.pythonhosted.org/packages/a1/d1/00780c0e187ea3c13dfc53bd7060654b2232cd30df562aac91a5f1c545ac/psycopg_binary-3.3.3-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:cab7bc3d288d37a80aa8c0820033250c95e40b1c2b5c57cf59827b19c2a8b69d", size = 4222833, upload-time = "2026-02-18T16:48:31.221Z" }, + { url = "https://files.pythonhosted.org/packages/7a/34/a07f1ff713c51d64dc9f19f2c32be80299a2055d5d109d5853662b922cb4/psycopg_binary-3.3.3-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:56c767007ca959ca32f796b42379fc7e1ae2ed085d29f20b05b3fc394f3715cc", size = 3952818, upload-time = "2026-02-18T16:48:35.869Z" }, + { url = "https://files.pythonhosted.org/packages/d3/67/d33f268a7759b4445f3c9b5a181039b01af8c8263c865c1be7a6444d4749/psycopg_binary-3.3.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:da2f331a01af232259a21573a01338530c6016dcfad74626c01330535bcd8628", size = 4258061, upload-time = "2026-02-18T16:48:41.365Z" }, + { url = "https://files.pythonhosted.org/packages/b4/3b/0d8d2c5e8e29ccc07d28c8af38445d9d9abcd238d590186cac82ee71fc84/psycopg_binary-3.3.3-cp311-cp311-win_amd64.whl", hash = "sha256:19f93235ece6dbfc4036b5e4f6d8b13f0b8f2b3eeb8b0bd2936d406991bcdd40", size = 3558915, upload-time = "2026-02-18T16:48:46.679Z" }, +] + +[[package]] +name = "py-key-value-aio" +version = "0.4.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "beartype" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/fb/e2/d689d922894a7ecde73b6daeaf9b13dab5aae06fe6aaaf7514722644d382/py_key_value_aio-0.4.5.tar.gz", hash = "sha256:c6563a2c6abe5da5e20f4f9e875c2a9b425a2244a54fadbf46cf140a9eea45d7", size = 107547, upload-time = "2026-05-27T16:37:08.107Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f6/95/b8ba862968712caa12a19666175334fa979e1f198b896a430adb3bacfe87/py_key_value_aio-0.4.5-py3-none-any.whl", hash = "sha256:ab862adbcb8c72547d1c57821f22cbbb71ab86509039c96f36e914e0336c8dd7", size = 170005, upload-time = "2026-05-27T16:37:06.629Z" }, +] + +[package.optional-dependencies] +memory = [ + { name = "cachetools" }, +] +redis = [ + { name = "redis" }, +] + +[[package]] +name = "pycparser" +version = "3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1b/7d/92392ff7815c21062bea51aa7b87d45576f649f16458d78b7cf94b9ab2e6/pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29", size = 103492, upload-time = "2026-01-21T14:26:51.89Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992", size = 48172, upload-time = "2026-01-21T14:26:50.693Z" }, +] + +[[package]] +name = "pydantic" +version = "2.13.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "annotated-types" }, + { name = "pydantic-core" }, + { name = "typing-extensions" }, + { name = "typing-inspection" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/18/a5/b60d21ac674192f8ab0ba4e9fd860690f9b4a6e51ca5df118733b487d8d6/pydantic-2.13.4.tar.gz", hash = "sha256:c40756b57adaa8b1efeeced5c196f3f3b7c435f90e84ea7f443901bec8099ef6", size = 844775, upload-time = "2026-05-06T13:43:05.343Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fd/7b/122376b1fd3c62c1ed9dc80c931ace4844b3c55407b6fb2d199377c9736f/pydantic-2.13.4-py3-none-any.whl", hash = "sha256:45a282cde31d808236fd7ea9d919b128653c8b38b393d1c4ab335c62924d9aba", size = 472262, upload-time = "2026-05-06T13:43:02.641Z" }, +] + +[[package]] +name = "pydantic-core" +version = "2.46.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9d/56/921726b776ace8d8f5db44c4ef961006580d91dc52b803c489fafd1aa249/pydantic_core-2.46.4.tar.gz", hash = "sha256:62f875393d7f270851f20523dd2e29f082bcc82292d66db2b64ea71f64b6e1c1", size = 471464, upload-time = "2026-05-06T13:37:06.98Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5c/fa/6d7708d2cfc1a832acb6aeb0cd16e801902df8a0f583bb3b4b527fde022e/pydantic_core-2.46.4-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:0e96592440881c74a213e5ad528e2b24d3d4f940de2766bed9010ab1d9e51594", size = 2111872, upload-time = "2026-05-06T13:40:27.596Z" }, + { url = "https://files.pythonhosted.org/packages/ae/6f/aa064a3e74b5745afbdf250594f38e7ead05e2d651bcb35994b9417a0d4d/pydantic_core-2.46.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e0d65b8c354be7fb5f720c3caa8bc940bc2d20ce749c8e06135f07f8ed95dd7c", size = 1948255, upload-time = "2026-05-06T13:39:12.574Z" }, + { url = "https://files.pythonhosted.org/packages/43/3a/41114a9f7569b84b4d84e7a018c57c56347dac30c0d4a872946ec4e36c46/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bfb192b3f4b9e8a89b6277b6ce787564f62cfd272055f6e685726b111dc7826", size = 1972827, upload-time = "2026-05-06T13:38:19.841Z" }, + { url = "https://files.pythonhosted.org/packages/ef/25/1ab42e8048fe551934d9884e8d64daa7e990ad386f310a15981aeb6a5b08/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9037063db01f09b09e237c282b6792bd4da634b5402c4e7f0c61effed7701a04", size = 2041051, upload-time = "2026-05-06T13:38:10.447Z" }, + { url = "https://files.pythonhosted.org/packages/94/c2/1a934597ddf08da410385b3b7aae91956a5a76c635effef456074fad7e88/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fc010ab034c8c7452522748bf937df58020d256ccae0874463d1f4d01758af8e", size = 2221314, upload-time = "2026-05-06T13:40:13.089Z" }, + { url = "https://files.pythonhosted.org/packages/02/6d/9e8ad178c9c4df27ad3c8f25d1fe2a7ab0d2ba0559fad4aee5d3d1f16771/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c5dac79fa1614d1e06ca695109c6105923bd9c7d1d6c918d4e637b7e6b32fd3", size = 2285146, upload-time = "2026-05-06T13:38:59.224Z" }, + { url = "https://files.pythonhosted.org/packages/80/50/540cd3aeefc041beb111125c4bff779831a2111fc6b15a9138cda277d32c/pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f9fa868638bf362d3d138ea55829cefb3d5f4b0d7f142234382a15e2485dbec4", size = 2089685, upload-time = "2026-05-06T13:38:17.762Z" }, + { url = "https://files.pythonhosted.org/packages/6b/a4/b440ad35f05f6a38f89fa0f149accb3f0e02be94ca5e15f3c449a61b4bc9/pydantic_core-2.46.4-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:17299feefe090f2caa5b8e37222bb5f663e4935a8bfa6931d4102e5df1a9f398", size = 2115420, upload-time = "2026-05-06T13:37:58.195Z" }, + { url = "https://files.pythonhosted.org/packages/99/61/de4f55db8dfd57bfdfa9a12ec90fe1b57c4f41062f7ca86f08586b3e0ac0/pydantic_core-2.46.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4c63ebc82684aa89d9a3bcbd13d515b3be44250dc68dd3bd81526c1cb31286c3", size = 2165122, upload-time = "2026-05-06T13:37:01.167Z" }, + { url = "https://files.pythonhosted.org/packages/f7/52/7c529d7bdb2d1068bd52f51fe32572c8301f9a4febf1948f10639f1436f5/pydantic_core-2.46.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:aaa2a54443eff1950ba5ddc6b6ccda0d9c84a364276a62f969bdf2a390650848", size = 2182573, upload-time = "2026-05-06T13:38:45.04Z" }, + { url = "https://files.pythonhosted.org/packages/37/b3/7c40325848ba78247f2812dcf9c7274e38cd801820ca6dd9fe63bcfb0eb4/pydantic_core-2.46.4-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:18e5ceec2ab67e6d5f1a9085e5a24c9c4e2ac4545730bfe668680bca05e555f3", size = 2317139, upload-time = "2026-05-06T13:37:15.539Z" }, + { url = "https://files.pythonhosted.org/packages/d9/37/f913f81a657c865b75da6c0dbed79876073c2a43b5bd9edbe8da785e4d49/pydantic_core-2.46.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a0f62d0a58f4e7da165457e995725421e0064f2255d8eccebc49f41bbc23b109", size = 2360433, upload-time = "2026-05-06T13:37:30.099Z" }, + { url = "https://files.pythonhosted.org/packages/c4/67/6acaa1be2567f9256b056d8477158cac7240813956ce86e49deae8e173b4/pydantic_core-2.46.4-cp311-cp311-win32.whl", hash = "sha256:041bde0a48fd37cf71cab1c9d56d3e8625a3793fef1f7dd232b3ff37e978ecda", size = 1985513, upload-time = "2026-05-06T13:38:15.669Z" }, + { url = "https://files.pythonhosted.org/packages/aa/e6/c505f83dfeda9a2e5c995cfd872949e4d05e12f7feb3dca72f633daefa94/pydantic_core-2.46.4-cp311-cp311-win_amd64.whl", hash = "sha256:6f2eeda33a839975441c86a4119e1383c50b47faf0cbb5176985565c6bb02c33", size = 2071114, upload-time = "2026-05-06T13:40:35.416Z" }, + { url = "https://files.pythonhosted.org/packages/0f/da/7a263a96d965d9d0df5e8de8a475f33495451117035b09acb110288c381f/pydantic_core-2.46.4-cp311-cp311-win_arm64.whl", hash = "sha256:14f4c5d6db102bd796a627bbb3a17b4cf4574b9ae861d8b7c9a9661c6dd3362d", size = 2044298, upload-time = "2026-05-06T13:38:29.754Z" }, + { url = "https://files.pythonhosted.org/packages/ee/a4/73995fd4ebbb46ba0ee51e6fa049b8f02c40daebb762208feda8a6b7894d/pydantic_core-2.46.4-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:14d4edf427bdcf950a8a02d7cb44a08614388dd6e1bdcbf4f67504fa7887da9c", size = 2111589, upload-time = "2026-05-06T13:37:10.817Z" }, + { url = "https://files.pythonhosted.org/packages/fb/7f/f37d3a5e8bfcc2e403f5c57a730f2d815693fb42119e8ea48b3789335af1/pydantic_core-2.46.4-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:0ce40cd7b21210e99342afafbd4d0f76d784eb5b1d60f3bdc566be4983c6c73b", size = 1944552, upload-time = "2026-05-06T13:36:56.717Z" }, + { url = "https://files.pythonhosted.org/packages/15/3c/d7eb777b3ff43e8433a4efb39a17aa8fd98a4ee8561a24a67ef5db07b2d6/pydantic_core-2.46.4-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:90884113d8b48f760e9587002789ddd741e76ab9f89518cd1e43b1f1a52ec44b", size = 1982984, upload-time = "2026-05-06T13:39:06.207Z" }, + { url = "https://files.pythonhosted.org/packages/63/87/70b9f40170a81afd55ca26c9b2acb25c20d64bcfbf888fafecb3ba077d4c/pydantic_core-2.46.4-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:66ce7632c22d837c95301830e111ad0128a32b8207533b60896a96c4915192ea", size = 2138417, upload-time = "2026-05-06T13:39:45.476Z" }, + { url = "https://files.pythonhosted.org/packages/11/cb/428de0385b6c8d44b716feba566abfacfbd23ee3c4439faa789a1456242f/pydantic_core-2.46.4-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:0c563b08bca408dc7f65f700633d8442fffb2421fc47b8101377e9fd65051ff0", size = 2112782, upload-time = "2026-05-06T13:37:04.016Z" }, + { url = "https://files.pythonhosted.org/packages/0b/b5/6a17bdadd0fc1f170adfd05a20d37c832f52b117b4d9131da1f41bb097ce/pydantic_core-2.46.4-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:db06ffe51636ffe9ca531fe9023dd64bdd794be8754cb5df57c5498ae5b518a7", size = 1952146, upload-time = "2026-05-06T13:39:43.092Z" }, + { url = "https://files.pythonhosted.org/packages/2a/dc/03734d80e362cd43ef65428e9de77c730ce7f2f11c60d2b1e1b39f0fbf99/pydantic_core-2.46.4-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:133878133d271ade3d41d1bfb2a45ec38dbdbda40bc065921c6b04e4630127e2", size = 2134492, upload-time = "2026-05-06T13:36:58.124Z" }, + { url = "https://files.pythonhosted.org/packages/de/df/5e5ffc085ed07cc22d298134d3d911c63e91f6a0eb91fe646750a3209910/pydantic_core-2.46.4-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9bc519fbf2b7578398853d815009ae5e4d4603d12f4e3f91da8c06852d3da3e9", size = 2156604, upload-time = "2026-05-06T13:37:49.88Z" }, + { url = "https://files.pythonhosted.org/packages/81/44/6e112a4253e56f5705467cbab7ab5e91ee7398ba3d56d358635958893d3e/pydantic_core-2.46.4-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:c7a7bd4e39e8e4c12c39cd480356842b6a8a06e41b23a55a5e3e191718838ddf", size = 2183828, upload-time = "2026-05-06T13:37:43.053Z" }, + { url = "https://files.pythonhosted.org/packages/ac/ad/5565071e937d8e752842ac241463944c9eb14c87e2d269f2658a5bd05e98/pydantic_core-2.46.4-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:d396ec2b979760aaf3218e76c24e65bd0aca24983298653b3a9d7a45f9e47b30", size = 2310000, upload-time = "2026-05-06T13:37:56.694Z" }, + { url = "https://files.pythonhosted.org/packages/4f/c3/66883a5cec183e7fba4d024b4cbbe61851a63750ef606b0afecc46d1f2bf/pydantic_core-2.46.4-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:86e1a4418c6cd97d60c95c71164158eaf7324fae7b0923264016baa993eba6fc", size = 2361286, upload-time = "2026-05-06T13:40:05.667Z" }, + { url = "https://files.pythonhosted.org/packages/4b/2d/69abac8f838090bbecd5df894befb2c2619e7996a98ddb949db9f3b93225/pydantic_core-2.46.4-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:d51026d73fcfd93610abc7b27789c26b313920fcfb20e27462d74a7f8b06e983", size = 2193071, upload-time = "2026-05-06T13:38:08.682Z" }, +] + +[[package]] +name = "pydantic-extra-types" +version = "2.11.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pydantic" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/66/71/dba38ee2651f84f7842206adbd2233d8bbdb59fb85e9fa14232486a8c471/pydantic_extra_types-2.11.1.tar.gz", hash = "sha256:46792d2307383859e923d8fcefa82108b1a141f8a9c0198982b3832ab5ef1049", size = 172002, upload-time = "2026-03-16T08:08:03.92Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/17/c1/3226e6d7f5a4f736f38ac11a6fbb262d701889802595cdb0f53a885ac2e0/pydantic_extra_types-2.11.1-py3-none-any.whl", hash = "sha256:1722ea2bddae5628ace25f2aa685b69978ef533123e5638cfbddb999e0100ec1", size = 79526, upload-time = "2026-03-16T08:08:02.533Z" }, +] + +[[package]] +name = "pydantic-settings" +version = "2.14.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pydantic" }, + { name = "python-dotenv" }, + { name = "typing-inspection" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5c/b5/8f48e906c3e0205276e8bd8cb7512217a87b2685304d64be27cad5b3019f/pydantic_settings-2.14.2.tar.gz", hash = "sha256:c19dd64b19097f1de80184f0cc7b0272a13ae6e170cbf240a3e27e381ed14a5f", size = 237700, upload-time = "2026-06-19T13:44:56.324Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/77/c1/6e422f34e569cf8e18df68d1939c81c099d2b61e4f7d9621c8a77560799c/pydantic_settings-2.14.2-py3-none-any.whl", hash = "sha256:a20c97b37910b6550d5ea50fbcc2d4187defe58cd57070b73863d069419c9440", size = 61715, upload-time = "2026-06-19T13:44:55.02Z" }, +] + +[[package]] +name = "pydocket" +version = "0.23.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "burner-redis" }, + { name = "cloudpickle" }, + { name = "cronsim" }, + { name = "opentelemetry-api" }, + { name = "prometheus-client" }, + { name = "py-key-value-aio", extra = ["memory", "redis"] }, + { name = "python-json-logger" }, + { name = "redis" }, + { name = "rich" }, + { name = "typer" }, + { name = "typing-extensions" }, + { name = "tzdata", marker = "sys_platform == 'win32'" }, + { name = "uncalled-for" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f8/72/f5a0960249d32a213fb26297a55f842ce8bc90bb19adbf47fefebb9c99da/pydocket-0.23.1.tar.gz", hash = "sha256:136c1cc8b7aa7c4c08ea12431e966ae75eb093bb6ce6e0ac9db3391ba3d6034b", size = 425621, upload-time = "2026-07-20T18:49:24.592Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e6/67/b57ac7cfd2c2f30d58ff2c996591880d200078fc828cbbad8da69d634c0e/pydocket-0.23.1-py3-none-any.whl", hash = "sha256:3da279978fd0d07eb96d4119e1a213de61d6b4acd1792a28bc62e67f3e7e5929", size = 129230, upload-time = "2026-07-20T18:49:23.243Z" }, +] + +[[package]] +name = "pyecore" +version = "0.13.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "future-fstrings" }, + { name = "lxml" }, + { name = "ordered-set" }, + { name = "restrictedpython" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/cf/c5/2dab673015609457e37becd8f8d39fc2fbaee2c7fbf79de33b3fbf275717/pyecore-0.13.2.tar.gz", hash = "sha256:277b43855c3072f7ae5b5520bd4d529ee80d80c036859d25a150c8440b03de9c", size = 57559, upload-time = "2023-08-14T20:02:19.607Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e1/86/a9c3a70aef9e02d97fc210d83f295118c4e5e08aae69ad29e598ffa2b1af/pyecore-0.13.2-py3-none-any.whl", hash = "sha256:858d426fe0ffc86469a7d6b220365d0ef3c8aedd745aca0561ca20a7db05199d", size = 43326, upload-time = "2023-08-14T20:02:17.677Z" }, +] + +[[package]] +name = "pyesdl" +version = "26.7" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pyecore" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b4/62/a9cb17f916eb2ee7c12b50f363a1457eccf879888ecd3ce2a0dc2904e561/pyesdl-26.7.tar.gz", hash = "sha256:7b685ab7ef57d07178178e54c20cc61962cc1c5ff901ea5efc0669f3d6c78eb8", size = 114922, upload-time = "2026-07-13T09:49:10.629Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fd/5b/1b913d6fbb904d5fdc45f5e67cdb285dc71c096070db0fe9dd9563c9a1de/pyesdl-26.7-py3-none-any.whl", hash = "sha256:30b512ee34a1ca4ffd2e58982208a75926eda67010a7e6b8a05b737cd9d0a127", size = 108848, upload-time = "2026-07-13T09:49:09.107Z" }, +] + +[package.optional-dependencies] +profiles = [ + { name = "influxdb" }, + { name = "openpyxl" }, + { name = "psycopg", extra = ["binary"] }, + { name = "psycopg-binary" }, +] + +[[package]] +name = "pygments" +version = "2.20.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991, upload-time = "2026-03-29T13:29:33.898Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" }, +] + +[[package]] +name = "pymoca" +version = "0.9.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "antlr4-python3-runtime" }, + { name = "numpy" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9e/da/2abf5d074b6e69c190aac8fd6d2f732b2fcba0b73229776a18d4cace074f/pymoca-0.9.2.tar.gz", hash = "sha256:bb0f1368e67f7bb876c3cb3a468e4d3a87a28e7624adb7483b39a22274b730e0", size = 111886, upload-time = "2025-01-28T15:44:25.037Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/24/55/ecf41c62849b27684431f096872216427d6190dec2ee8d2c2550669d7395/pymoca-0.9.2-py3-none-any.whl", hash = "sha256:13b96bd877def818fba22f43b1b3916470b573e569c7e7f1bd98a8990b9b60d3", size = 113709, upload-time = "2025-01-28T15:44:22.626Z" }, +] + +[[package]] +name = "pyproject-hooks" +version = "1.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e7/82/28175b2414effca1cdac8dc99f76d660e7a4fb0ceefa4b4ab8f5f6742925/pyproject_hooks-1.2.0.tar.gz", hash = "sha256:1e859bd5c40fae9448642dd871adf459e5e2084186e8d2c2a79a824c970da1f8", size = 19228, upload-time = "2024-09-29T09:24:13.293Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl", hash = "sha256:9e5c6bfa8dcc30091c74b0cf803c81fdd29d94f01992a7707bc97babb1141913", size = 10216, upload-time = "2024-09-29T09:24:11.978Z" }, +] + +[[package]] +name = "pytest" +version = "8.3.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "iniconfig" }, + { name = "packaging" }, + { name = "pluggy" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ae/3c/c9d525a414d506893f0cd8a8d0de7706446213181570cdbd766691164e40/pytest-8.3.5.tar.gz", hash = "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845", size = 1450891, upload-time = "2025-03-02T12:54:54.503Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/30/3d/64ad57c803f1fa1e963a7946b6e0fea4a70df53c1a7fed304586539c2bac/pytest-8.3.5-py3-none-any.whl", hash = "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820", size = 343634, upload-time = "2025-03-02T12:54:52.069Z" }, +] + +[[package]] +name = "pytest-cov" +version = "6.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "coverage", extra = ["toml"] }, + { name = "pytest" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/be/45/9b538de8cef30e17c7b45ef42f538a94889ed6a16f2387a6c89e73220651/pytest-cov-6.0.0.tar.gz", hash = "sha256:fde0b595ca248bb8e2d76f020b465f3b107c9632e6a1d1705f17834c89dcadc0", size = 66945, upload-time = "2024-10-29T20:13:35.363Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/36/3b/48e79f2cd6a61dbbd4807b4ed46cb564b4fd50a76166b1c4ea5c1d9e2371/pytest_cov-6.0.0-py3-none-any.whl", hash = "sha256:eee6f1b9e61008bd34975a4d5bab25801eb31898b032dd55addc93e96fcaaa35", size = 22949, upload-time = "2024-10-29T20:13:33.215Z" }, +] + +[[package]] +name = "python-dateutil" +version = "2.9.0.post0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432, upload-time = "2024-03-01T18:36:20.211Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" }, +] + +[[package]] +name = "python-dotenv" +version = "1.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/bc/57/e84d88dfe0aec03b7a2d4327012c1627ab5f03652216c63d49846d7a6c58/python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca", size = 39115, upload-time = "2024-01-23T06:33:00.505Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6a/3e/b68c118422ec867fa7ab88444e1274aa40681c606d59ac27de5a5588f082/python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a", size = 19863, upload-time = "2024-01-23T06:32:58.246Z" }, +] + +[[package]] +name = "python-json-logger" +version = "4.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f7/ff/3cc9165fd44106973cd7ac9facb674a65ed853494592541d339bdc9a30eb/python_json_logger-4.1.0.tar.gz", hash = "sha256:b396b9e3ed782b09ff9d6e4f1683d46c83ad0d35d2e407c09a9ebbf038f88195", size = 17573, upload-time = "2026-03-29T04:39:56.805Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/27/be/0631a861af4d1c875f096c07d34e9a63639560a717130e7a87cbc82b7e3f/python_json_logger-4.1.0-py3-none-any.whl", hash = "sha256:132994765cf75bf44554be9aa49b06ef2345d23661a96720262716438141b6b2", size = 15021, upload-time = "2026-03-29T04:39:55.266Z" }, +] + +[[package]] +name = "python-slugify" +version = "8.0.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "text-unidecode" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/87/c7/5e1547c44e31da50a460df93af11a535ace568ef89d7a811069ead340c4a/python-slugify-8.0.4.tar.gz", hash = "sha256:59202371d1d05b54a9e7720c5e038f928f45daaffe41dd10822f3907b937c856", size = 10921, upload-time = "2024-02-08T18:32:45.488Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a4/62/02da182e544a51a5c3ccf4b03ab79df279f9c60c5e82d5e8bec7ca26ac11/python_slugify-8.0.4-py2.py3-none-any.whl", hash = "sha256:276540b79961052b66b7d116620b36518847f52d5fd9e3a70164fc8c50faa6b8", size = 10051, upload-time = "2024-02-08T18:32:43.911Z" }, +] + +[[package]] +name = "pytz" +version = "2025.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f8/bf/abbd3cdfb8fbc7fb3d4d38d320f2441b1e7cbe29be4f23797b4a2b5d8aac/pytz-2025.2.tar.gz", hash = "sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3", size = 320884, upload-time = "2025-03-25T02:25:00.538Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl", hash = "sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00", size = 509225, upload-time = "2025-03-25T02:24:58.468Z" }, +] + +[[package]] +name = "pywin32" +version = "312" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1f/f5/10a6e845a00fc5e7afd0a988b744f403d4d57162a28d160a093c4d9322f0/pywin32-312-cp311-cp311-win32.whl", hash = "sha256:17948aeadbdb091f0ced6ef0841620794e68327b94ee415571c1203594b7215c", size = 6362659, upload-time = "2026-06-04T07:49:21.349Z" }, + { url = "https://files.pythonhosted.org/packages/35/c4/dcd2d62b5944b6d5db53413a5899016ccd57ffcb7278f3f81655d25d2027/pywin32-312-cp311-cp311-win_amd64.whl", hash = "sha256:d11417d84412f859b722fad0841b3614459ed0047f7542d8362e77884f6b6e8a", size = 6928825, upload-time = "2026-06-04T07:49:23.934Z" }, + { url = "https://files.pythonhosted.org/packages/b7/56/3cbb433fe4501cdba2eb9040f56a4e1a8243faa4186b25295564d1a7a79d/pywin32-312-cp311-cp311-win_arm64.whl", hash = "sha256:b2200a054ca6d6625c4842fc56a4976a4b47f96b73dbe5538c3f813a80359f47", size = 6721875, upload-time = "2026-06-04T07:49:26.416Z" }, +] + +[[package]] +name = "pyyaml" +version = "6.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6d/16/a95b6757765b7b031c9374925bb718d55e0a9ba8a1b6a12d25962ea44347/pyyaml-6.0.3-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:44edc647873928551a01e7a563d7452ccdebee747728c1080d881d68af7b997e", size = 185826, upload-time = "2025-09-25T21:31:58.655Z" }, + { url = "https://files.pythonhosted.org/packages/16/19/13de8e4377ed53079ee996e1ab0a9c33ec2faf808a4647b7b4c0d46dd239/pyyaml-6.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:652cb6edd41e718550aad172851962662ff2681490a8a711af6a4d288dd96824", size = 175577, upload-time = "2025-09-25T21:32:00.088Z" }, + { url = "https://files.pythonhosted.org/packages/0c/62/d2eb46264d4b157dae1275b573017abec435397aa59cbcdab6fc978a8af4/pyyaml-6.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:10892704fc220243f5305762e276552a0395f7beb4dbf9b14ec8fd43b57f126c", size = 775556, upload-time = "2025-09-25T21:32:01.31Z" }, + { url = "https://files.pythonhosted.org/packages/10/cb/16c3f2cf3266edd25aaa00d6c4350381c8b012ed6f5276675b9eba8d9ff4/pyyaml-6.0.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:850774a7879607d3a6f50d36d04f00ee69e7fc816450e5f7e58d7f17f1ae5c00", size = 882114, upload-time = "2025-09-25T21:32:03.376Z" }, + { url = "https://files.pythonhosted.org/packages/71/60/917329f640924b18ff085ab889a11c763e0b573da888e8404ff486657602/pyyaml-6.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b8bb0864c5a28024fac8a632c443c87c5aa6f215c0b126c449ae1a150412f31d", size = 806638, upload-time = "2025-09-25T21:32:04.553Z" }, + { url = "https://files.pythonhosted.org/packages/dd/6f/529b0f316a9fd167281a6c3826b5583e6192dba792dd55e3203d3f8e655a/pyyaml-6.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1d37d57ad971609cf3c53ba6a7e365e40660e3be0e5175fa9f2365a379d6095a", size = 767463, upload-time = "2025-09-25T21:32:06.152Z" }, + { url = "https://files.pythonhosted.org/packages/f2/6a/b627b4e0c1dd03718543519ffb2f1deea4a1e6d42fbab8021936a4d22589/pyyaml-6.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:37503bfbfc9d2c40b344d06b2199cf0e96e97957ab1c1b546fd4f87e53e5d3e4", size = 794986, upload-time = "2025-09-25T21:32:07.367Z" }, + { url = "https://files.pythonhosted.org/packages/45/91/47a6e1c42d9ee337c4839208f30d9f09caa9f720ec7582917b264defc875/pyyaml-6.0.3-cp311-cp311-win32.whl", hash = "sha256:8098f252adfa6c80ab48096053f512f2321f0b998f98150cea9bd23d83e1467b", size = 142543, upload-time = "2025-09-25T21:32:08.95Z" }, + { url = "https://files.pythonhosted.org/packages/da/e3/ea007450a105ae919a72393cb06f122f288ef60bba2dc64b26e2646fa315/pyyaml-6.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:9f3bfb4965eb874431221a3ff3fdcddc7e74e3b07799e0e84ca4a0f867d449bf", size = 158763, upload-time = "2025-09-25T21:32:09.96Z" }, +] + +[[package]] +name = "readchar" +version = "4.2.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ed/49/a10341024c45bed95d13197ec9ef0f4e2fd10b5ca6e7f8d7684d18082398/readchar-4.2.2.tar.gz", hash = "sha256:e3b270fe16fc90c50ac79107700330a133dd4c63d22939f5b03b4f24564d5dd8", size = 9762, upload-time = "2026-04-06T19:45:54.226Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3d/ca/36133653e00939922dd1416f4c56177361289172a30563fcb9552c9ccde4/readchar-4.2.2-py3-none-any.whl", hash = "sha256:92daf7e42c52b0787e6c75d01ecfb9a94f4ceff3764958b570c1dddedd47b200", size = 9401, upload-time = "2026-04-06T19:45:52.993Z" }, +] + +[[package]] +name = "redis" +version = "8.0.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "async-timeout", marker = "python_full_version < '3.11.3'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/cc/c3/928b290c2c0ca99ab96eea5b4ff8f30be8112b075301a7d3ba214a3c8c12/redis-8.0.1.tar.gz", hash = "sha256:afc5a7a2f5a084f5b1880dec548dd45be17db7e43c82a30d84f952aefb05cfb0", size = 5114170, upload-time = "2026-06-23T14:52:37.728Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fd/0a/c2345ebf1ebe70840ce3f6c6ee612f8fa749cfbd1b03069c53bf0c62aaad/redis-8.0.1-py3-none-any.whl", hash = "sha256:47daa35a058c23468d6437f17a8c76882cb316b838ef763036af99b96cedd743", size = 502406, upload-time = "2026-06-23T14:52:36.137Z" }, +] + +[[package]] +name = "referencing" +version = "0.37.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "rpds-py" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/22/f5/df4e9027acead3ecc63e50fe1e36aca1523e1719559c499951bb4b53188f/referencing-0.37.0.tar.gz", hash = "sha256:44aefc3142c5b842538163acb373e24cce6632bd54bdb01b21ad5863489f50d8", size = 78036, upload-time = "2025-10-13T15:30:48.871Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2c/58/ca301544e1fa93ed4f80d724bf5b194f6e4b945841c5bfd555878eea9fcb/referencing-0.37.0-py3-none-any.whl", hash = "sha256:381329a9f99628c9069361716891d34ad94af76e461dcb0335825aecc7692231", size = 26766, upload-time = "2025-10-13T15:30:47.625Z" }, +] + +[[package]] +name = "regex" +version = "2026.7.19" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/20/98/04b13f1ddfb63158025291c02e03eb42fbb7acb51d091d541050eb4e35e8/regex-2026.7.19.tar.gz", hash = "sha256:7e77b324909c1617cbb4c668677e2c6ae13f44d7c1de0d4f15f2e3c10f3315b5", size = 416440, upload-time = "2026-07-19T00:19:48.923Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/05/e5/cef4de2bac939280b68d32adc659478845238a8274f2f79c465063f590ad/regex-2026.7.19-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ac777001cdfc28b72477d93c8564bb7583081ea8fb45cdca3d568e0a4f87183c", size = 494012, upload-time = "2026-07-19T00:16:39.927Z" }, + { url = "https://files.pythonhosted.org/packages/ff/87/e86f51eb117457bb7803132ffe5cb6e2841e2b5bea4cc85d397f3c6e257d/regex-2026.7.19-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:59787bd5f8c70aa339084e961d2996b53fbdeab4d5393bba5c1fe1fc32e02bae", size = 295281, upload-time = "2026-07-19T00:16:41.433Z" }, + { url = "https://files.pythonhosted.org/packages/41/2e/2360c41d8080a3d9ec7e5c90fad6eab3b50192869d10e9a5609e48c8177b/regex-2026.7.19-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:90c633e7e8d6bf4e992b8b36ce69e018f834b641dd6de8cea6d78c06ffa119c5", size = 290615, upload-time = "2026-07-19T00:16:43.058Z" }, + { url = "https://files.pythonhosted.org/packages/cf/69/b65ba4344efbc771b28fe5dde84cbbb6c8f9551165952fe78def5b9dde6a/regex-2026.7.19-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:87ccab0db8d5f4fbb0272642113c1adb2ffc698c16d3a0944580222331fa7a20", size = 791804, upload-time = "2026-07-19T00:16:44.662Z" }, + { url = "https://files.pythonhosted.org/packages/81/b6/a40dfa0dc6224b36f620c00296eacc830489cbf8c2837b6750dfe6170375/regex-2026.7.19-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9e50d748a32da622f256e8d505867f5d3c43a837c6a9f0efb149655fadd1042a", size = 861723, upload-time = "2026-07-19T00:16:46.412Z" }, + { url = "https://files.pythonhosted.org/packages/e3/02/735991dee71abd83196a7962f7ed8bf5aa05720ff06e2d3ff896a85e2bbb/regex-2026.7.19-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:bf1516fe58fc104f39b2d1dbe2d5e27d0cd45c4be2e42ba6ee0cc763701ec3c7", size = 905932, upload-time = "2026-07-19T00:16:47.956Z" }, + { url = "https://files.pythonhosted.org/packages/45/6c/e7098d8b846ccdbf431d8c081b61e496526a27a28094ed09e0dce21b3f54/regex-2026.7.19-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:09f3e5287f94f17b709dc9a9e70865855feee835c861613be144218ce4ca82cc", size = 801407, upload-time = "2026-07-19T00:16:49.43Z" }, + { url = "https://files.pythonhosted.org/packages/8a/18/34b69274e2649bcc7d9b089c2b2983fb2632d8ecf667e359593be9072e79/regex-2026.7.19-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:6383cd2ed53a646c659ba1fe65727db76437fdaa069e697a0b44a51d5843d864", size = 774448, upload-time = "2026-07-19T00:16:51.352Z" }, + { url = "https://files.pythonhosted.org/packages/bb/e6/0a72247d025585fd3800b98e040b84d562a88af6303347100484849f4f01/regex-2026.7.19-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:09d3007fc76249a83cdd33de160d50e6cb77f54e09d8fa9e7148e10607ce24af", size = 783297, upload-time = "2026-07-19T00:16:53.071Z" }, + { url = "https://files.pythonhosted.org/packages/b1/aa/c4f65ae7dd02a36b323a70c4cff326e1f3442361aaebc9311100a130d54f/regex-2026.7.19-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:6f8c6e7a1cfa3dc9d0ee2de0e65e834537fa29992cc3976ffec914afc35c5dd5", size = 854736, upload-time = "2026-07-19T00:16:54.607Z" }, + { url = "https://files.pythonhosted.org/packages/62/c3/668082bcc817b9e694189b84997aeba7385b7779faa6711788679c482e35/regex-2026.7.19-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:b2ea4a3e8357be8849e833beeae757ac3c7a6b3fc055c03c808a53c91ad30d82", size = 763298, upload-time = "2026-07-19T00:16:56.289Z" }, + { url = "https://files.pythonhosted.org/packages/4b/fb/2d07ad555e7af88aa5f867fdafa47a8d945ee237c20af3ebceb46a820835/regex-2026.7.19-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:80115dd39481fd3a4b4080220799dbcacb921a844de4b827264ececacbe17c78", size = 844430, upload-time = "2026-07-19T00:16:57.933Z" }, + { url = "https://files.pythonhosted.org/packages/51/15/c82a471fe3dce56f03745635b43aa456c40dc0db089e07ef148b331507d1/regex-2026.7.19-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d6ce43a0269d68cee79a7d1ade7def53c20f8f2a047b92d7b5d5bcc73ae88327", size = 789683, upload-time = "2026-07-19T00:16:59.583Z" }, + { url = "https://files.pythonhosted.org/packages/b5/f4/7532a2c59d56f5398902c20de60f0c9a5d1cd364e42a051b48e1b210be7b/regex-2026.7.19-cp311-cp311-win32.whl", hash = "sha256:9be2a6647740dd3cca6acb24e87f03d7632cd280dbce9bbe40c26353a215a45d", size = 266778, upload-time = "2026-07-19T00:17:01.032Z" }, + { url = "https://files.pythonhosted.org/packages/83/2b/cf1bc631db154eb95520d9d5dbc2371ff77a0f014bbf7d748fed8496aa63/regex-2026.7.19-cp311-cp311-win_amd64.whl", hash = "sha256:8d3469c91dd92ee41b7c95280edbd975ef1ba9195086686623a1c6e8935ce965", size = 277983, upload-time = "2026-07-19T00:17:02.571Z" }, + { url = "https://files.pythonhosted.org/packages/8d/bd/56ceaf170e875d5a6761bf2bfd0d040f1cacc896850d5e40cb29b11bbd06/regex-2026.7.19-cp311-cp311-win_arm64.whl", hash = "sha256:36aacfb15faaff3ced55afbf35ec72f50d4aee22082c4f7fe0573a33e2fca92e", size = 276961, upload-time = "2026-07-19T00:17:04.135Z" }, +] + +[[package]] +name = "requests" +version = "2.34.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "charset-normalizer" }, + { name = "idna" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ac/c3/e2a2b89f2d3e2179abd6d00ebd70bff6273f37fb3e0cc209f48b39d00cbf/requests-2.34.2.tar.gz", hash = "sha256:f288924cae4e29463698d6d60bc6a4da69c89185ad1e0bcc4104f584e960b9ed", size = 142856, upload-time = "2026-05-14T19:25:27.735Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a0/f4/c67b0b3f1b9245e8d266f0f112c500d50e5b4e83cb6f3b71b6528104182a/requests-2.34.2-py3-none-any.whl", hash = "sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0", size = 73075, upload-time = "2026-05-14T19:25:26.443Z" }, +] + +[[package]] +name = "requests-oauthlib" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "oauthlib" }, + { name = "requests" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/42/f2/05f29bc3913aea15eb670be136045bf5c5bbf4b99ecb839da9b422bb2c85/requests-oauthlib-2.0.0.tar.gz", hash = "sha256:b3dffaebd884d8cd778494369603a9e7b58d29111bf6b41bdc2dcd87203af4e9", size = 55650, upload-time = "2024-03-22T20:32:29.939Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3b/5d/63d4ae3b9daea098d5d6f5da83984853c1bbacd5dc826764b249fe119d24/requests_oauthlib-2.0.0-py2.py3-none-any.whl", hash = "sha256:7dd8a5c40426b779b0868c404bdef9768deccf22749cde15852df527e6269b36", size = 24179, upload-time = "2024-03-22T20:32:28.055Z" }, +] + +[[package]] +name = "restrictedpython" +version = "8.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/97/04/7314639eab9edd57b5c8f6e158a558f5a5a65453c37a51fb8f9ecc1d112e/restrictedpython-8.2.tar.gz", hash = "sha256:b835c2ff87d71b76f6d8b129096cc5a1e893bf01839ab802ba47a4129f1bdfe4", size = 449323, upload-time = "2026-05-29T06:27:57.285Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/35/59/b2778bfafcc37fdfd87c02702bbfc5753c58c28c7eb82999b7b49ec6e0e7/restrictedpython-8.2-py3-none-any.whl", hash = "sha256:6ff69e2fe06674bfe88943f17f2ce8353a9bc743ee37ea7bec38ff8b4851afd1", size = 27176, upload-time = "2026-05-29T06:27:55.651Z" }, +] + +[[package]] +name = "rfc3339-validator" +version = "0.1.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/28/ea/a9387748e2d111c3c2b275ba970b735e04e15cdb1eb30693b6b5708c4dbd/rfc3339_validator-0.1.4.tar.gz", hash = "sha256:138a2abdf93304ad60530167e51d2dfb9549521a836871b88d7f4695d0022f6b", size = 5513, upload-time = "2021-05-12T16:37:54.178Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7b/44/4e421b96b67b2daff264473f7465db72fbdf36a07e05494f50300cc7b0c6/rfc3339_validator-0.1.4-py2.py3-none-any.whl", hash = "sha256:24f6ec1eda14ef823da9e36ec7113124b39c04d50a4d3d3a3c2859577e7791fa", size = 3490, upload-time = "2021-05-12T16:37:52.536Z" }, +] + +[[package]] +name = "rich" +version = "15.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markdown-it-py" }, + { name = "pygments" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c0/8f/0722ca900cc807c13a6a0c696dacf35430f72e0ec571c4275d2371fca3e9/rich-15.0.0.tar.gz", hash = "sha256:edd07a4824c6b40189fb7ac9bc4c52536e9780fbbfbddf6f1e2502c31b068c36", size = 230680, upload-time = "2026-04-12T08:24:00.75Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl", hash = "sha256:33bd4ef74232fb73fe9279a257718407f169c09b78a87ad3d296f548e27de0bb", size = 310654, upload-time = "2026-04-12T08:24:02.83Z" }, +] + +[[package]] +name = "rich-rst" +version = "2.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pygments" }, + { name = "rich" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e2/d6/d0b9fafc73b65767200da027acab1db1bdb1048f4fea5ebf659df01c700e/rich_rst-2.1.0.tar.gz", hash = "sha256:f4d117b49697f338769759fa5cacf5197da4888b347b9fda2e50aef5cd8d93bd", size = 302732, upload-time = "2026-07-05T02:59:44.308Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2a/68/1fc93dd759605b5d00fc98b50200739e41ed32bd22d6ba35ca6c3932371b/rich_rst-2.1.0-py3-none-any.whl", hash = "sha256:7ecd1343ee12c879d0e7ae74c3eb6d263b023d2929c6d114212eb1fd91057255", size = 272987, upload-time = "2026-07-05T02:59:42.792Z" }, +] + +[[package]] +name = "rpds-py" +version = "2026.6.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/aa/2a/9618a122aeb2a169a28b03889a2995fe297588964333d4a7d67bdf46e147/rpds_py-2026.6.3.tar.gz", hash = "sha256:1cebd1337c242e4ec2293e541f712b2da849b29f48f0c293684b71c0632625d4", size = 64051, upload-time = "2026-06-30T07:17:53.009Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/94/1f/a2dca5ffdbf1d475ffc4e80e4d5d720ff3a00f691795910116960ee12511/rpds_py-2026.6.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:7b689145a1485c335569bd056464f3243a29af7ed3871c7be31ad624ba239bc7", size = 342174, upload-time = "2026-06-30T07:14:54.821Z" }, + { url = "https://files.pythonhosted.org/packages/4d/dc/323d08583c0832911768663d1944f0107fcd4088704858d84b5e06d105a0/rpds_py-2026.6.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:db08f45aecde626498fb3df07bcf6d2ec040af42e859a4f5040d79c200342911", size = 345513, upload-time = "2026-06-30T07:14:56.515Z" }, + { url = "https://files.pythonhosted.org/packages/0b/2a/e31989834d18d2f26ec1d2774c5b1eb3331df4ea8ada525175294c94b48a/rpds_py-2026.6.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:acc992ab27b15f852c76755eb2ab7dce86585ddadba6fa5946e58556088845b4", size = 373783, upload-time = "2026-06-30T07:14:57.736Z" }, + { url = "https://files.pythonhosted.org/packages/87/fe/e80107ee3639585c9941c17d6a42cd65325022f656c023191fce78c324c8/rpds_py-2026.6.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7f88d653e7b3b779d71ae7454e20dcc9b6bae903f33c269db9f2be41bda3f261", size = 378316, upload-time = "2026-06-30T07:14:59.077Z" }, + { url = "https://files.pythonhosted.org/packages/22/6f/81e3adf81acfb6fa694de2a6e4e7d8863121e3e0799e0a7725e6cf5679c4/rpds_py-2026.6.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e52655eaf81e32593abedaa4bfe33170c8cfedf3365ed9be6e11e07f148f0278", size = 499423, upload-time = "2026-06-30T07:15:00.488Z" }, + { url = "https://files.pythonhosted.org/packages/2d/9a/41263969df0ce3d9af2a96d5005a288200af1989aed3354bfceb5fc0b21f/rpds_py-2026.6.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dfcc8b909769d19db55c7cc9541eb64b9b774b1057ffffb4f1048070475bb9f9", size = 386077, upload-time = "2026-06-30T07:15:01.911Z" }, + { url = "https://files.pythonhosted.org/packages/5e/19/7e98f468bd50346faff5b10e5297374b443bfdddacc8e9fbc65984539597/rpds_py-2026.6.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c1255b302953c86a486b81d330d5ee1d5bd937691ce271b6be0ef0e299eaab7", size = 371315, upload-time = "2026-06-30T07:15:03.317Z" }, + { url = "https://files.pythonhosted.org/packages/99/3c/2b973b4d371906a134b03decfea7f5d9835a2c6d263454392e15b64b5b18/rpds_py-2026.6.3-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:8d2294a31386bfa251d8c8a39472beee17db67d4f1a6eabea665d35c9a4461c3", size = 383502, upload-time = "2026-06-30T07:15:04.627Z" }, + { url = "https://files.pythonhosted.org/packages/98/2a/12e2799500af0a307bca76b63361c51f9fe479223561489c29eea1f2ee41/rpds_py-2026.6.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f8f23ead891a3b762f35ab3b04623da7056545b48aa60d59957e6789914545da", size = 402673, upload-time = "2026-06-30T07:15:05.856Z" }, + { url = "https://files.pythonhosted.org/packages/2d/e3/21e5872d165fe08be4f229e3d5ee9d90019c0bf0e5538de60dbd54009450/rpds_py-2026.6.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:421aba32367055614287a4292b6a17f1939c9452299f7a0209c117e990b646d4", size = 549964, upload-time = "2026-06-30T07:15:07.159Z" }, + { url = "https://files.pythonhosted.org/packages/1a/d0/5ee0fe36844297de8123bee27bc12078c1a7416ad9f1b8a8ca18d6b0c0ac/rpds_py-2026.6.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1e5822dfc2f0d4ab7e745eaa6d85945069329beeccef965af3f3bb26058fcab6", size = 615446, upload-time = "2026-06-30T07:15:08.531Z" }, + { url = "https://files.pythonhosted.org/packages/b1/80/1ea5873cb683f2fbe5f21b23ea1f6d179ead19f3c5b249b7eb5dca568ef2/rpds_py-2026.6.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:83e35b57523816c8613fd0776b40cd8bb9f596b37ddd2692eb4a6bb5ab2f8c93", size = 576975, upload-time = "2026-06-30T07:15:09.97Z" }, + { url = "https://files.pythonhosted.org/packages/c9/e1/90ef639217a5ddb15b7f4f61b1c33911fd044ad03c311bafdd2bcab85582/rpds_py-2026.6.3-cp311-cp311-win32.whl", hash = "sha256:de3eceba0b683bcbb1ab93da016d0270df1f9ae7be716b40214c5dafac6ea45a", size = 204453, upload-time = "2026-06-30T07:15:11.324Z" }, + { url = "https://files.pythonhosted.org/packages/f2/b7/b7a1695d7af36f521fb11e80d6d3adbd744f73b921859bd3c2a2c0dc706f/rpds_py-2026.6.3-cp311-cp311-win_amd64.whl", hash = "sha256:2c54a076ca4d370980ab57bc0e31df57bbe8d41340436a90ef8b1219a3cbb127", size = 223219, upload-time = "2026-06-30T07:15:12.476Z" }, + { url = "https://files.pythonhosted.org/packages/d7/a2/145afacf796e4506062825941176ad9445c2dcf2b3b6a1f13d3030a15e19/rpds_py-2026.6.3-cp311-cp311-win_arm64.whl", hash = "sha256:168c733a7112e071bb7a66460e667edfcff06c017a3c523f7a8a8e08d0140804", size = 219137, upload-time = "2026-06-30T07:15:13.631Z" }, + { url = "https://files.pythonhosted.org/packages/b4/9c/f0d19ac587fd0e4ab6b72cda355e9c5a6166b01ef7e064e437aef8eb9fef/rpds_py-2026.6.3-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:4cf2d36a2357e4d07bb5a4f98801265327b48256867816cfd2ceb001e9754a8f", size = 349791, upload-time = "2026-06-30T07:17:33.315Z" }, + { url = "https://files.pythonhosted.org/packages/38/c7/1d49d204c9fd2ee6c537601dc4c1ba921e03363ca576bfab94a00254ac9a/rpds_py-2026.6.3-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:30c6dc199b24a5e3e81d50da0f00858c5bbdb2617a750395687f4339c5818171", size = 352842, upload-time = "2026-06-30T07:17:34.897Z" }, + { url = "https://files.pythonhosted.org/packages/ac/e5/c0b5dc93cd0d4c06ce1f438907649514e2ea077bcd911e3154a51e96c38e/rpds_py-2026.6.3-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9891e594296ab9dada6551c8e7b387b2721f27a67eecd528412e8906247a7b90", size = 382094, upload-time = "2026-06-30T07:17:36.514Z" }, + { url = "https://files.pythonhosted.org/packages/0d/54/ec0e907b4ca8d541112db352409bd15f871c9b243e0c92c9b5a46ae96f01/rpds_py-2026.6.3-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b5c2dc92304aa48a4a60443b548bb12f12e119d4b72f314015e67b9e1be97fca", size = 388662, upload-time = "2026-06-30T07:17:38.235Z" }, + { url = "https://files.pythonhosted.org/packages/d3/f4/921c22a4fd0f1c1ac13a3996ffbf0aa67951e2c8ad0d1d9574938a2932e8/rpds_py-2026.6.3-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:127e08c0642d880cf32ca47ec2a4a77b901f7e2dd1ad9762adb13955d72ffcc9", size = 504896, upload-time = "2026-06-30T07:17:39.689Z" }, + { url = "https://files.pythonhosted.org/packages/0b/1b/a114b972cefa1ab1cdb3c7bb177cd3844a12826c507c722d3a73516dbbaf/rpds_py-2026.6.3-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8bb68f03f395eb793220b45c097bd4d8c32944393da0fad8b999efac0868fc8c", size = 391545, upload-time = "2026-06-30T07:17:41.336Z" }, + { url = "https://files.pythonhosted.org/packages/4e/98/af9b3db77d47fcbe6c8c1f36e2c2147ec70292819e99c325f871584a1c11/rpds_py-2026.6.3-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a3450b693fde92133e9f51060568a4c31fcca76d5e53bbd611e689ca446517e9", size = 380059, upload-time = "2026-06-30T07:17:42.857Z" }, + { url = "https://files.pythonhosted.org/packages/c9/ba/0efd8668b97c1d26a61566386c636a7a7a09829e474fdf807caa15a2c844/rpds_py-2026.6.3-pp311-pypy311_pp73-manylinux_2_31_riscv64.whl", hash = "sha256:5e8d07bddee435a2ff6f1920e18feff28d0bc4533e42f4bf6927fbd073312c41", size = 393235, upload-time = "2026-06-30T07:17:44.637Z" }, + { url = "https://files.pythonhosted.org/packages/62/90/8c139ee9690f73b0829f32647de6f40d826f8f443af6fa72644f96351aac/rpds_py-2026.6.3-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3a83ae6c67b7676b9878378547ca8e93ed77a580037bcbcd1d32f739e1e6089c", size = 413008, upload-time = "2026-06-30T07:17:46.225Z" }, + { url = "https://files.pythonhosted.org/packages/9c/97/0043896fdd7828ce09a1d9a8b06433714d0960fc4ff3fc4aa72b666b764e/rpds_py-2026.6.3-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:2bfd04c19ddbd6640de0b51894d764bd2758854d5b75bd102d2ef10cb9c293a9", size = 558118, upload-time = "2026-06-30T07:17:47.759Z" }, + { url = "https://files.pythonhosted.org/packages/f6/40/02355f0e134f783a8f9814c4680a1bd311d37671577a5964ea838573ff37/rpds_py-2026.6.3-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:ca6546b66be9dc4738b1b043d5ebd5488c66c578c5ff0fd0e8065313fe3afb76", size = 623138, upload-time = "2026-06-30T07:17:49.355Z" }, + { url = "https://files.pythonhosted.org/packages/10/85/48f0abdcef5cce4e034c7a5b0ceeceba0b01bf0d942824f4bb720afe2dec/rpds_py-2026.6.3-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:8e65860d238379ed982fd9ba690579b5e95af2f4840f99c772816dbe573cb826", size = 586486, upload-time = "2026-06-30T07:17:51.141Z" }, +] + +[[package]] +name = "rtc-tools-channel-flow" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pymoca" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/74/bd/a8d14a0f9f147abd590cb25e1afeb0dfc8bfd6d091c25f3e9738e0c764cc/rtc_tools_channel_flow-1.3.1.tar.gz", hash = "sha256:d7e1a025900e975386d5915fedd9d555572801e61872ee70ab82553f474d814b", size = 51304, upload-time = "2025-12-17T10:51:07.57Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/23/5c/ee6cb699992fc5884c223bb1965c6f495be297267106f3157981313c6d5d/rtc_tools_channel_flow-1.3.1-py3-none-any.whl", hash = "sha256:fc2829eb746328b511089b1cb101247cc921c1020dd5c768bb8177a033665fd0", size = 83767, upload-time = "2025-12-17T10:51:06.571Z" }, +] + +[[package]] +name = "rtc-tools-gil-comp" +version = "2.6.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "casadi-gil-comp" }, + { name = "defusedxml" }, + { name = "numpy" }, + { name = "pymoca" }, + { name = "rtc-tools-channel-flow" }, + { name = "scipy" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/f8/1c/355e93d8c7b70fe56552cca8bebb8a09ce395acdfb5480b3b80522a98405/rtc_tools_gil_comp-2.6.1-py3-none-any.whl", hash = "sha256:f973a03e89df95bb4a8f04993e9591dadb090c683079c5ce6ae7fa525d1ca6a6", size = 146102, upload-time = "2025-02-12T13:42:26.834Z" }, +] + +[[package]] +name = "ruamel-yaml" +version = "0.19.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c7/3b/ebda527b56beb90cb7652cb1c7e4f91f48649fbcd8d2eb2fb6e77cd3329b/ruamel_yaml-0.19.1.tar.gz", hash = "sha256:53eb66cd27849eff968ebf8f0bf61f46cdac2da1d1f3576dd4ccee9b25c31993", size = 142709, upload-time = "2026-01-02T16:50:31.84Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b8/0c/51f6841f1d84f404f92463fc2b1ba0da357ca1e3db6b7fbda26956c3b82a/ruamel_yaml-0.19.1-py3-none-any.whl", hash = "sha256:27592957fedf6e0b62f281e96effd28043345e0e66001f97683aa9a40c667c93", size = 118102, upload-time = "2026-01-02T16:50:29.201Z" }, +] + +[[package]] +name = "ruamel-yaml-clib" +version = "0.2.15" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ea/97/60fda20e2fb54b83a61ae14648b0817c8f5d84a3821e40bfbdae1437026a/ruamel_yaml_clib-0.2.15.tar.gz", hash = "sha256:46e4cc8c43ef6a94885f72512094e482114a8a706d3c555a34ed4b0d20200600", size = 225794, upload-time = "2025-11-16T16:12:59.761Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2c/80/8ce7b9af532aa94dd83360f01ce4716264db73de6bc8efd22c32341f6658/ruamel_yaml_clib-0.2.15-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c583229f336682b7212a43d2fa32c30e643d3076178fb9f7a6a14dde85a2d8bd", size = 147998, upload-time = "2025-11-16T16:13:13.241Z" }, + { url = "https://files.pythonhosted.org/packages/53/09/de9d3f6b6701ced5f276d082ad0f980edf08ca67114523d1b9264cd5e2e0/ruamel_yaml_clib-0.2.15-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:56ea19c157ed8c74b6be51b5fa1c3aff6e289a041575f0556f66e5fb848bb137", size = 132743, upload-time = "2025-11-16T16:13:14.265Z" }, + { url = "https://files.pythonhosted.org/packages/0e/f7/73a9b517571e214fe5c246698ff3ed232f1ef863c8ae1667486625ec688a/ruamel_yaml_clib-0.2.15-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:5fea0932358e18293407feb921d4f4457db837b67ec1837f87074667449f9401", size = 731459, upload-time = "2025-11-16T20:22:44.338Z" }, + { url = "https://files.pythonhosted.org/packages/9b/a2/0dc0013169800f1c331a6f55b1282c1f4492a6d32660a0cf7b89e6684919/ruamel_yaml_clib-0.2.15-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ef71831bd61fbdb7aa0399d5c4da06bea37107ab5c79ff884cc07f2450910262", size = 749289, upload-time = "2025-11-16T16:13:15.633Z" }, + { url = "https://files.pythonhosted.org/packages/aa/ed/3fb20a1a96b8dc645d88c4072df481fe06e0289e4d528ebbdcc044ebc8b3/ruamel_yaml_clib-0.2.15-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:617d35dc765715fa86f8c3ccdae1e4229055832c452d4ec20856136acc75053f", size = 777630, upload-time = "2025-11-16T16:13:16.898Z" }, + { url = "https://files.pythonhosted.org/packages/60/50/6842f4628bc98b7aa4733ab2378346e1441e150935ad3b9f3c3c429d9408/ruamel_yaml_clib-0.2.15-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1b45498cc81a4724a2d42273d6cfc243c0547ad7c6b87b4f774cb7bcc131c98d", size = 744368, upload-time = "2025-11-16T16:13:18.117Z" }, + { url = "https://files.pythonhosted.org/packages/d3/b0/128ae8e19a7d794c2e36130a72b3bb650ce1dd13fb7def6cf10656437dcf/ruamel_yaml_clib-0.2.15-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:def5663361f6771b18646620fca12968aae730132e104688766cf8a3b1d65922", size = 745233, upload-time = "2025-11-16T20:22:45.833Z" }, + { url = "https://files.pythonhosted.org/packages/75/05/91130633602d6ba7ce3e07f8fc865b40d2a09efd4751c740df89eed5caf9/ruamel_yaml_clib-0.2.15-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:014181cdec565c8745b7cbc4de3bf2cc8ced05183d986e6d1200168e5bb59490", size = 770963, upload-time = "2025-11-16T16:13:19.344Z" }, + { url = "https://files.pythonhosted.org/packages/fd/4b/fd4542e7f33d7d1bc64cc9ac9ba574ce8cf145569d21f5f20133336cdc8c/ruamel_yaml_clib-0.2.15-cp311-cp311-win32.whl", hash = "sha256:d290eda8f6ada19e1771b54e5706b8f9807e6bb08e873900d5ba114ced13e02c", size = 102640, upload-time = "2025-11-16T16:13:20.498Z" }, + { url = "https://files.pythonhosted.org/packages/bb/eb/00ff6032c19c7537371e3119287999570867a0eafb0154fccc80e74bf57a/ruamel_yaml_clib-0.2.15-cp311-cp311-win_amd64.whl", hash = "sha256:bdc06ad71173b915167702f55d0f3f027fc61abd975bd308a0968c02db4a4c3e", size = 121996, upload-time = "2025-11-16T16:13:21.855Z" }, +] + +[[package]] +name = "ruff" +version = "0.15.22" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/3a/06/ae069393fc66e8ff33036d4b368003833bf6e88ccf182e17e7a2f1c754fd/ruff-0.15.22.tar.gz", hash = "sha256:3f15175b1fb580126f58285a5dae6b2ea89000136d980c64499211f116b54809", size = 4785063, upload-time = "2026-07-16T15:14:13.244Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/23/18/ee54b7ae1e121be7a28ea6da4b67564ebb0530e183a54415ab7e3bcd2c4e/ruff-0.15.22-py3-none-linux_armv6l.whl", hash = "sha256:44423e73493737f5e7c5b41d475483898ff37afcdae38bc3da5085e29af1c2d8", size = 10781258, upload-time = "2026-07-16T15:13:19.452Z" }, + { url = "https://files.pythonhosted.org/packages/2f/d2/2520cb14761ddbeaf57642a76942fc36adcbdbe53b4532241995f6fc485c/ruff-0.15.22-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b82c6482946e9eda7ff2e091d25b8bad3f718684e1916d41bd56873cee05b697", size = 10999477, upload-time = "2026-07-16T15:13:23.318Z" }, + { url = "https://files.pythonhosted.org/packages/c9/10/74e53572aa758dfaa678c2a2646b5c5515d884b7ca56be4d2ce03ca4b560/ruff-0.15.22-py3-none-macosx_11_0_arm64.whl", hash = "sha256:11c1c715af53a09f714e011106bffc419751ec8232fcb5da42173284ea3fec6f", size = 10466716, upload-time = "2026-07-16T15:13:26.162Z" }, + { url = "https://files.pythonhosted.org/packages/1e/cc/44eaaf0844e028182f2d0a8f2190d0f359159aed0a9e5ab861d892f1ae2a/ruff-0.15.22-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:742a29cf29bddb7c8327895d6a10e0e6c5b38a96dd407af9b5d0857f809c0576", size = 10892644, upload-time = "2026-07-16T15:13:29.229Z" }, + { url = "https://files.pythonhosted.org/packages/9f/21/8edf559014d2b0f82beea19cfb713993ad802ccda16868769979c6090a84/ruff-0.15.22-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:72af58b951b0ae395935ae79763dc349bc0eb706319d28f7a33ad2cfb3cfc178", size = 10576719, upload-time = "2026-07-16T15:13:32.35Z" }, + { url = "https://files.pythonhosted.org/packages/bf/1e/3a13abd392a3b50b62e5938a831f9ab6e588358cacad5c18545b716d2182/ruff-0.15.22-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62d425005c1835eb24e2ee4161cb90e8db263415f4a71c8c72c33abaa6c0c224", size = 11376494, upload-time = "2026-07-16T15:13:35.958Z" }, + { url = "https://files.pythonhosted.org/packages/bf/3e/422d3d95bcf04dd78e1aeac22184d4f9a8fb2c01865d39d44618484a0317/ruff-0.15.22-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e8b9b3f8779a4f08c969defc3c8c35abffaa757e601ed5ae66d6d1db6519969a", size = 12208370, upload-time = "2026-07-16T15:13:39.185Z" }, + { url = "https://files.pythonhosted.org/packages/1e/91/5d065a0e0a02bf4813f5119ad278462eed081d2b832eb7c021ade0ec9e65/ruff-0.15.22-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1e0dd1b2e4d3d585f897a0d137cbf4eaf6223bef4e8ce34d6bb12556c5f9249e", size = 11581098, upload-time = "2026-07-16T15:13:42.132Z" }, + { url = "https://files.pythonhosted.org/packages/f6/f9/a0d4871d12fae702eb1f41b686caf05f1f8b124dc6db6f784f53d74918fa/ruff-0.15.22-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:365523eb91d9224e1bcb03b022fbf0facb8f9e23792a2c53d9d4b3924bdbdebb", size = 11399422, upload-time = "2026-07-16T15:13:45.2Z" }, + { url = "https://files.pythonhosted.org/packages/18/80/c843a5176cddbceb0b7e8dd41cf9993490796c1c469348d384f5a5c13c56/ruff-0.15.22-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:fabfd168afdf29fee5be98b831efa9683c94d7c5a3b58b9ce5a2e38444589a74", size = 11381683, upload-time = "2026-07-16T15:13:48.46Z" }, + { url = "https://files.pythonhosted.org/packages/d4/00/8485de0ae92239438a36cfc51350db9b9e85c9ebdfaea91b18e422706662/ruff-0.15.22-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:225dbf095a87f1d9f90f5fd7924d2613ee452a75a4308c63a8f50f761787aa7c", size = 10850295, upload-time = "2026-07-16T15:13:51.655Z" }, + { url = "https://files.pythonhosted.org/packages/fa/91/24977ec2ec72eaf15e4394ace2959fdff2dd1e14f03e005e838023407169/ruff-0.15.22-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:1877d63b9d24ed278744f1523fd11b85540566d54641f97c566d7d9dc5ca5296", size = 10579640, upload-time = "2026-07-16T15:13:54.79Z" }, + { url = "https://files.pythonhosted.org/packages/9c/47/9b51216951974df1f263ac19da550d34252e0ed7218c25f10c5ef9ed7517/ruff-0.15.22-py3-none-musllinux_1_2_i686.whl", hash = "sha256:a1606c510bd7215680d32efab38965f7cdec3ef69f5170a3f4791404ffdd5262", size = 11105077, upload-time = "2026-07-16T15:13:57.915Z" }, + { url = "https://files.pythonhosted.org/packages/c2/47/20e9d4a3b8016778acea5fc32bb50d35d207500a17ddb529ffa6996feef8/ruff-0.15.22-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:630479b18625f5ffc373f77603a22a9f8ac0acd7ff0501178b5db28ec71e9c64", size = 11490980, upload-time = "2026-07-16T15:14:01.032Z" }, + { url = "https://files.pythonhosted.org/packages/4d/76/3f72d8fc38c1cb77b38c56a70da9d0c17700cc1cc50f9649c9d3c8f5ba71/ruff-0.15.22-py3-none-win32.whl", hash = "sha256:e5ba0e4a13fd14abbed2a77b517a3911290c6c6c59ef67784328d1668fab76cf", size = 10789165, upload-time = "2026-07-16T15:14:04.16Z" }, + { url = "https://files.pythonhosted.org/packages/cb/46/4965251734c2b6fcdca1b1b187d20bcac3af0ee5b083b89c910bb961ce3a/ruff-0.15.22-py3-none-win_amd64.whl", hash = "sha256:9be63ba1eb936acd2d1342fb8337c356353706fce233b2a15a09a97037e6acde", size = 11938297, upload-time = "2026-07-16T15:14:07.316Z" }, + { url = "https://files.pythonhosted.org/packages/57/c9/e69b1ff4c8b69093ef08b8919ab767af0569666865b39c30a8795d88d3c6/ruff-0.15.22-py3-none-win_arm64.whl", hash = "sha256:e1168075b72158510839f250027659cdd78476f40507dd517892304c41318661", size = 11298172, upload-time = "2026-07-16T15:14:10.51Z" }, +] + +[[package]] +name = "s3fs" +version = "2026.6.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "aiobotocore" }, + { name = "aiohttp" }, + { name = "fsspec" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/99/00/6677343dc919d6c072bb04d80210afdd22c16838a8d16b3315c122dc728f/s3fs-2026.6.0.tar.gz", hash = "sha256:b28de7082d0a4f72392884bdc497e34a4a1582f675d214c7da0acf6e950a0083", size = 87358, upload-time = "2026-06-16T02:05:48.719Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a5/0b/f68a968b49876eae0f2a515387093cebb2eb9451380a96741cc20efac0d0/s3fs-2026.6.0-py3-none-any.whl", hash = "sha256:60576e31bb31193c1f643f32b4c6439548720ea6918ac702e21cd757c80b5db8", size = 32573, upload-time = "2026-06-16T02:05:47.608Z" }, +] + +[[package]] +name = "scipy" +version = "1.10.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/84/a9/2bf119f3f9cff1f376f924e39cfae18dec92a1514784046d185731301281/scipy-1.10.1.tar.gz", hash = "sha256:2cf9dfb80a7b4589ba4c40ce7588986d6d5cebc5457cad2c2880f6bc2d42f3a5", size = 42407997, upload-time = "2023-02-19T21:20:13.395Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e7/53/053cd3669be0d474deae8fe5f757bff4c4f480b8a410231e0631c068873d/scipy-1.10.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0f1564ea217e82c1bbe75ddf7285ba0709ecd503f048cb1236ae9995f64217bd", size = 35003170, upload-time = "2023-02-19T20:40:53.274Z" }, + { url = "https://files.pythonhosted.org/packages/0d/3e/d05b9de83677195886fb79844fcca19609a538db63b1790fa373155bc3cf/scipy-1.10.1-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:d925fa1c81b772882aa55bcc10bf88324dadb66ff85d548c71515f6689c6dac5", size = 28717513, upload-time = "2023-02-19T20:42:20.82Z" }, + { url = "https://files.pythonhosted.org/packages/a5/3d/b69746c50e44893da57a68457da3d7e5bb75f6a37fbace3769b70d017488/scipy-1.10.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaea0a6be54462ec027de54fca511540980d1e9eea68b2d5c1dbfe084797be35", size = 30687257, upload-time = "2023-02-19T20:43:48.139Z" }, + { url = "https://files.pythonhosted.org/packages/21/cd/fe2d4af234b80dc08c911ce63fdaee5badcdde3e9bcd9a68884580652ef0/scipy-1.10.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15a35c4242ec5f292c3dd364a7c71a61be87a3d4ddcc693372813c0b73c9af1d", size = 34124096, upload-time = "2023-02-19T20:45:27.415Z" }, + { url = "https://files.pythonhosted.org/packages/65/76/903324159e4a3566e518c558aeb21571d642f781d842d8dd0fd9c6b0645a/scipy-1.10.1-cp311-cp311-win_amd64.whl", hash = "sha256:43b8e0bcb877faf0abfb613d51026cd5cc78918e9530e375727bf0625c82788f", size = 42238704, upload-time = "2023-02-19T20:47:26.366Z" }, +] + +[[package]] +name = "semver" +version = "3.0.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/72/d1/d3159231aec234a59dd7d601e9dd9fe96f3afff15efd33c1070019b26132/semver-3.0.4.tar.gz", hash = "sha256:afc7d8c584a5ed0a11033af086e8af226a9c0b206f313e0301f8dd7b6b589602", size = 269730, upload-time = "2025-01-24T13:19:27.617Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a6/24/4d91e05817e92e3a61c8a21e08fd0f390f5301f1c448b137c57c4bc6e543/semver-3.0.4-py3-none-any.whl", hash = "sha256:9c824d87ba7f7ab4a1890799cec8596f15c1241cb473404ea1cb0c55e4b04746", size = 17912, upload-time = "2025-01-24T13:19:24.949Z" }, +] + +[[package]] +name = "setuptools" +version = "75.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/43/54/292f26c208734e9a7f067aea4a7e282c080750c4546559b58e2e45413ca0/setuptools-75.6.0.tar.gz", hash = "sha256:8199222558df7c86216af4f84c30e9b34a61d8ba19366cc914424cdbd28252f6", size = 1337429, upload-time = "2024-11-20T18:16:13.378Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/55/21/47d163f615df1d30c094f6c8bbb353619274edccf0327b185cc2493c2c33/setuptools-75.6.0-py3-none-any.whl", hash = "sha256:ce74b49e8f7110f9bf04883b730f4765b774ef3ef28f722cce7c273d253aaf7d", size = 1224032, upload-time = "2024-11-20T18:16:10.861Z" }, +] + +[[package]] +name = "shellingham" +version = "1.5.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/58/15/8b3609fd3830ef7b27b655beb4b4e9c62313a4e8da8c676e142cc210d58e/shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de", size = 10310, upload-time = "2023-10-24T04:13:40.426Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", size = 9755, upload-time = "2023-10-24T04:13:38.866Z" }, +] + +[[package]] +name = "six" +version = "1.17.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" }, +] + +[[package]] +name = "sniffio" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372, upload-time = "2024-02-25T23:20:04.057Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235, upload-time = "2024-02-25T23:20:01.196Z" }, +] + +[[package]] +name = "sqlalchemy" +version = "2.0.51" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "greenlet", marker = "platform_machine == 'AMD64' or platform_machine == 'WIN32' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'ppc64le' or platform_machine == 'win32' or platform_machine == 'x86_64'" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/02/f1/a7a892f18d4d224e6b26f706531eafccc41e37594d37d304786969ee13cb/sqlalchemy-2.0.51.tar.gz", hash = "sha256:804dccd8a4a6242c4e30ad961e540e18a588f6527202f2d6791b01845d59fdc9", size = 9912201, upload-time = "2026-06-15T15:41:20.012Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3a/69/a67c69e5f28fc9c99d6f7bd60bd50e91f2fed2423e3b30fb228fa00e51f3/sqlalchemy-2.0.51-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1aa10c0daee6705294d181daadaa793221e1a59ed55000a3fab1d42b088ce4ba", size = 2161838, upload-time = "2026-06-15T16:05:17.144Z" }, + { url = "https://files.pythonhosted.org/packages/9a/a4/c8c22b8438bddc0a030157c6ec0f6ef97b3c38effa444bdab2a27af04090/sqlalchemy-2.0.51-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a5b2ed6d828f1f09bd812861f4f59ca3bc3803f9df871f4555187f0faf018604", size = 3319402, upload-time = "2026-06-15T16:10:40.002Z" }, + { url = "https://files.pythonhosted.org/packages/90/54/44012d32fd77d991256d2ff793ba3807c51d40cb27a85b4796224f6744df/sqlalchemy-2.0.51-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:436728ce18a80f6951a1e11cc6112c2ede9faf20766f1a26195a7c441ca12dbd", size = 3319675, upload-time = "2026-06-15T16:12:25.658Z" }, + { url = "https://files.pythonhosted.org/packages/29/a5/de0592acaf5906cd7430874392d6f7e8b4a7c8437610953ee2d1501c0b44/sqlalchemy-2.0.51-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:dc261707bf5739aea8a541593f3cc1d463c2701fb05fbcbba0ce031b69a21260", size = 3270777, upload-time = "2026-06-15T16:10:42.125Z" }, + { url = "https://files.pythonhosted.org/packages/cb/14/a44c90739c780b362238e4ac3cb19dd0ca40d13e6ddc5daa112166ddab4f/sqlalchemy-2.0.51-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a6d26094615306d116dd5e4a51b0304c99dd2356fc569eed6922a80a6bd3b265", size = 3293940, upload-time = "2026-06-15T16:12:27.156Z" }, + { url = "https://files.pythonhosted.org/packages/65/eb/fbd0f206a330e66f8c602a99c37c4e731f107faed62954b41b01f16dd9d9/sqlalchemy-2.0.51-cp311-cp311-win32.whl", hash = "sha256:ca8435d13829b92f4a97362d91975154a4015db3a2634154e1754e9a915e6b86", size = 2121183, upload-time = "2026-06-15T16:13:29.905Z" }, + { url = "https://files.pythonhosted.org/packages/ad/fd/005bf80f3cf6e5c62b5dd68616280f51cd012c60840fa74781b3ed7b1623/sqlalchemy-2.0.51-cp311-cp311-win_amd64.whl", hash = "sha256:4a011ea4510683319ce4ed274b56ee05194b39b6da9d09ca7a39388f0fa84dcc", size = 2145796, upload-time = "2026-06-15T16:13:31.283Z" }, + { url = "https://files.pythonhosted.org/packages/e2/22/dbf013a12ec759e54a34a119e9e217435b3f71b2dd5c61a7ade0a25dae87/sqlalchemy-2.0.51-py3-none-any.whl", hash = "sha256:bb024d8b621d0be75f4f44ecc7c950450026e76d66dc8f791bb5331d7fed59d5", size = 1944334, upload-time = "2026-06-15T16:09:22.418Z" }, +] + +[package.optional-dependencies] +asyncio = [ + { name = "greenlet" }, +] + +[[package]] +name = "starlette" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/eb/e3/7c1dc7381d9f8ab7d854328ebfa884e62cb3f3d8549ddfd37c7814f42afa/starlette-1.3.1.tar.gz", hash = "sha256:05d0213193f2fbaae60e2ecb593b4add4262ad4e46536b54abe36f11a71724e0", size = 2703240, upload-time = "2026-06-12T09:23:11.602Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ec/bb/2799cc2ede3ed41131f8975621e7213dfc7ef4acbbaadfa440f32500c370/starlette-1.3.1-py3-none-any.whl", hash = "sha256:c7372aae11c3c3f26a42df7bd626cec2f47d03483d261d369516a615a53714c6", size = 73632, upload-time = "2026-06-12T09:23:10.017Z" }, +] + +[[package]] +name = "streamcapture" +version = "1.2.7" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "setuptools" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9e/cc/59abd0b4eb6576bbe59c5bf4e23dfbe306c804b201bfaeca6470a8ba7562/streamcapture-1.2.7.tar.gz", hash = "sha256:2eb59cd87f91c7964a670a51879c5cd8428ed5d37dfe439c9882a87c5ae9a837", size = 7990, upload-time = "2026-02-05T19:06:21.513Z" } + +[[package]] +name = "strenum" +version = "0.4.15" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/85/ad/430fb60d90e1d112a62ff57bdd1f286ec73a2a0331272febfddd21f330e1/StrEnum-0.4.15.tar.gz", hash = "sha256:878fb5ab705442070e4dd1929bb5e2249511c0bcf2b0eeacf3bcd80875c82eff", size = 23384, upload-time = "2023-06-29T22:02:58.399Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/81/69/297302c5f5f59c862faa31e6cb9a4cd74721cd1e052b38e464c5b402df8b/StrEnum-0.4.15-py3-none-any.whl", hash = "sha256:a30cda4af7cc6b5bf52c8055bc4bf4b2b6b14a93b574626da33df53cf7740659", size = 8851, upload-time = "2023-06-29T22:02:56.947Z" }, +] + +[[package]] +name = "text-unidecode" +version = "1.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ab/e2/e9a00f0ccb71718418230718b3d900e71a5d16e701a3dae079a21e9cd8f8/text-unidecode-1.3.tar.gz", hash = "sha256:bad6603bb14d279193107714b288be206cac565dfa49aa5b105294dd5c4aab93", size = 76885, upload-time = "2019-08-30T21:36:45.405Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a6/a5/c0b6468d3824fe3fde30dbb5e1f687b291608f9473681bbf7dabbf5a87d7/text_unidecode-1.3-py2.py3-none-any.whl", hash = "sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8", size = 78154, upload-time = "2019-08-30T21:37:03.543Z" }, +] + +[[package]] +name = "toml" +version = "0.10.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/be/ba/1f744cdc819428fc6b5084ec34d9b30660f6f9daaf70eead706e3203ec3c/toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f", size = 22253, upload-time = "2020-11-01T01:40:22.204Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/44/6f/7120676b6d73228c96e17f1f794d8ab046fc910d781c8d151120c3f1569e/toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b", size = 16588, upload-time = "2020-11-01T01:40:20.672Z" }, +] + +[[package]] +name = "tomli" +version = "2.4.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/22/de/48c59722572767841493b26183a0d1cc411d54fd759c5607c4590b6563a6/tomli-2.4.1.tar.gz", hash = "sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f", size = 17543, upload-time = "2026-03-25T20:22:03.828Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/11/db3d5885d8528263d8adc260bb2d28ebf1270b96e98f0e0268d32b8d9900/tomli-2.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f8f0fc26ec2cc2b965b7a3b87cd19c5c6b8c5e5f436b984e85f486d652285c30", size = 154704, upload-time = "2026-03-25T20:21:10.473Z" }, + { url = "https://files.pythonhosted.org/packages/6d/f7/675db52c7e46064a9aa928885a9b20f4124ecb9bc2e1ce74c9106648d202/tomli-2.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4ab97e64ccda8756376892c53a72bd1f964e519c77236368527f758fbc36a53a", size = 149454, upload-time = "2026-03-25T20:21:12.036Z" }, + { url = "https://files.pythonhosted.org/packages/61/71/81c50943cf953efa35bce7646caab3cf457a7d8c030b27cfb40d7235f9ee/tomli-2.4.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:96481a5786729fd470164b47cdb3e0e58062a496f455ee41b4403be77cb5a076", size = 237561, upload-time = "2026-03-25T20:21:13.098Z" }, + { url = "https://files.pythonhosted.org/packages/48/c1/f41d9cb618acccca7df82aaf682f9b49013c9397212cb9f53219e3abac37/tomli-2.4.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a881ab208c0baf688221f8cecc5401bd291d67e38a1ac884d6736cbcd8247e9", size = 243824, upload-time = "2026-03-25T20:21:14.569Z" }, + { url = "https://files.pythonhosted.org/packages/22/e4/5a816ecdd1f8ca51fb756ef684b90f2780afc52fc67f987e3c61d800a46d/tomli-2.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:47149d5bd38761ac8be13a84864bf0b7b70bc051806bc3669ab1cbc56216b23c", size = 242227, upload-time = "2026-03-25T20:21:15.712Z" }, + { url = "https://files.pythonhosted.org/packages/6b/49/2b2a0ef529aa6eec245d25f0c703e020a73955ad7edf73e7f54ddc608aa5/tomli-2.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ec9bfaf3ad2df51ace80688143a6a4ebc09a248f6ff781a9945e51937008fcbc", size = 247859, upload-time = "2026-03-25T20:21:17.001Z" }, + { url = "https://files.pythonhosted.org/packages/83/bd/6c1a630eaca337e1e78c5903104f831bda934c426f9231429396ce3c3467/tomli-2.4.1-cp311-cp311-win32.whl", hash = "sha256:ff2983983d34813c1aeb0fa89091e76c3a22889ee83ab27c5eeb45100560c049", size = 97204, upload-time = "2026-03-25T20:21:18.079Z" }, + { url = "https://files.pythonhosted.org/packages/42/59/71461df1a885647e10b6bb7802d0b8e66480c61f3f43079e0dcd315b3954/tomli-2.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:5ee18d9ebdb417e384b58fe414e8d6af9f4e7a0ae761519fb50f721de398dd4e", size = 108084, upload-time = "2026-03-25T20:21:18.978Z" }, + { url = "https://files.pythonhosted.org/packages/b8/83/dceca96142499c069475b790e7913b1044c1a4337e700751f48ed723f883/tomli-2.4.1-cp311-cp311-win_arm64.whl", hash = "sha256:c2541745709bad0264b7d4705ad453b76ccd191e64aa6f0fc66b69a293a45ece", size = 95285, upload-time = "2026-03-25T20:21:20.309Z" }, + { url = "https://files.pythonhosted.org/packages/7b/61/cceae43728b7de99d9b847560c262873a1f6c98202171fd5ed62640b494b/tomli-2.4.1-py3-none-any.whl", hash = "sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe", size = 14583, upload-time = "2026-03-25T20:22:03.012Z" }, +] + +[[package]] +name = "ty" +version = "0.0.61" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/92/63/6944925d0fe9a4bb9cc744e6c045a42bbd2ee4654c103190674577a36c3f/ty-0.0.61.tar.gz", hash = "sha256:acbf0d914cc7e2e57ccc440036af36114819e2a604a5ffb554e72e4ca7dd65a2", size = 6234957, upload-time = "2026-07-18T01:39:54.696Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/dc/cf/044f31523e2768e3e64b0ca2ec32f70b3a731d4a2caa6ea110baf26e251c/ty-0.0.61-py3-none-linux_armv6l.whl", hash = "sha256:148779b8675eac93f40ec58bd70037fe67537117f20a23272264f8f136d41336", size = 11891448, upload-time = "2026-07-18T01:39:18.449Z" }, + { url = "https://files.pythonhosted.org/packages/d2/55/558cfe76b65d91d1854bbfac336020bd42fd887caa632d845d13c0c539eb/ty-0.0.61-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:08217382b3385808ee7288501ea3214b32631b08d1fd091ece6799b0c95264c5", size = 11602442, upload-time = "2026-07-18T01:39:20.914Z" }, + { url = "https://files.pythonhosted.org/packages/27/be/78c0ae6634cd606a68e5b46b338db427a48a1800c96a749b2d2f7a702e03/ty-0.0.61-py3-none-macosx_11_0_arm64.whl", hash = "sha256:6d99c729011b47dec20e78a32ac9c8f6defd4cf62f7bb851bbccf70dde6cee50", size = 11125286, upload-time = "2026-07-18T01:39:22.893Z" }, + { url = "https://files.pythonhosted.org/packages/a4/18/a40793962f1b6337938ddb0bca7496b54e70879e23b4d2cc8dfd7e5d1af3/ty-0.0.61-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5cda607978ae271b77e51c947663218bce635c3507e256865444b10c37cdb60d", size = 11663403, upload-time = "2026-07-18T01:39:25.017Z" }, + { url = "https://files.pythonhosted.org/packages/98/c1/7879244da5b30407dc368946d36be5024380073408b079f144ffe034030e/ty-0.0.61-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0d78f160a0f9434d570cdcdbc4dafba1f6aac3c47a32f9f63995b3cb55ffe4b6", size = 11715250, upload-time = "2026-07-18T01:39:27.045Z" }, + { url = "https://files.pythonhosted.org/packages/35/c4/8a4637cd58abd37f315dd515e24c582986cb1bfdf2edc4786882f5a4f69a/ty-0.0.61-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09aeab4800b36e93e4ce918699004da642d74988cac920b7592a6a2b9be6611c", size = 12393876, upload-time = "2026-07-18T01:39:29.197Z" }, + { url = "https://files.pythonhosted.org/packages/27/4b/27e7c640b1272743503229aa17ae2167a538040c4716a2fa1777c2b34fea/ty-0.0.61-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dccc8136df44142a109953a168be17b4915c99876b047d0b6672c31dae939bdf", size = 12958187, upload-time = "2026-07-18T01:39:31.308Z" }, + { url = "https://files.pythonhosted.org/packages/3a/f5/70eaaefb6081fb0a8115cff66fbfaa20dafac8c646df2477adad95a59de2/ty-0.0.61-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:220760c2d13a887d027ee1093172c24ac35b6e634805329c93a30908ae4d3f5c", size = 12560101, upload-time = "2026-07-18T01:39:33.35Z" }, + { url = "https://files.pythonhosted.org/packages/e3/5a/17bae3b6429b5c479dc6c1e344d34e1f79efbc27531f15f3ee5b5da63745/ty-0.0.61-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:effefbb89da7128d18059529d1c2ea390fe7f1f3882690d257ca2143d49a0c34", size = 12225389, upload-time = "2026-07-18T01:39:35.436Z" }, + { url = "https://files.pythonhosted.org/packages/d2/0e/2ac380ba20d6395542c8df1d6fa4f00e2aead784c2e6aaefa1e02ed0610c/ty-0.0.61-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:ba8b28a5ef811d5bb6461e37d76110c06fd20487474865c323d3d18b08b972b2", size = 12548403, upload-time = "2026-07-18T01:39:37.556Z" }, + { url = "https://files.pythonhosted.org/packages/b0/e5/7da4b73e825e1a9808c26d68b0156e9a37aede1846191210dfffb8c64042/ty-0.0.61-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:88ecd6d9b05e8174b1860dac9bd3e188d6cef5702b0d3239fd9f94f6ac73a29d", size = 11621813, upload-time = "2026-07-18T01:39:39.919Z" }, + { url = "https://files.pythonhosted.org/packages/9b/3c/5b58015e998cd0d89b17a463b6321421457d86d987574e8dac65ddfceba3/ty-0.0.61-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:fb0cdfe4c48542ffb9a1139825dfa3d4aae49e96e966682ef7da762ab97831ff", size = 11734101, upload-time = "2026-07-18T01:39:42.097Z" }, + { url = "https://files.pythonhosted.org/packages/a6/21/294f4cc819b7b12ed659fd860e5cdfbd592d4c768c8f23596685dbc43e6b/ty-0.0.61-py3-none-musllinux_1_2_i686.whl", hash = "sha256:dff03873c0c3d0b44738f8b6d403b0756a31cf54c65136397df7624c6159b1f0", size = 11988401, upload-time = "2026-07-18T01:39:44.183Z" }, + { url = "https://files.pythonhosted.org/packages/2e/26/0f96f79fdac118521a9771e9eef3f9b3f447d647b2c77953e80a1715c7e8/ty-0.0.61-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:a9210e80e3d41c1dfc751e9e8e0980272f475031fafd0fb0f48aee233c78da03", size = 12330624, upload-time = "2026-07-18T01:39:46.662Z" }, + { url = "https://files.pythonhosted.org/packages/e3/08/1e62d1bca5c0cebdc7a34db1f4b61557aab85961cedd56953dd2c32d3e66/ty-0.0.61-py3-none-win32.whl", hash = "sha256:e3e1fe06f49a5492a922a5df2739834aa5ee978c7dd10414119dc8755cc40c9c", size = 11313991, upload-time = "2026-07-18T01:39:48.761Z" }, + { url = "https://files.pythonhosted.org/packages/26/f1/d8e33b3aeb36b73d81ae34d10e46ec4abf506d68f4e0a1491a76a593dd42/ty-0.0.61-py3-none-win_amd64.whl", hash = "sha256:25f2291169e0298fcdbba1b1fea64f8207a6c1908dddef32346fd5e3e6ac9221", size = 12311717, upload-time = "2026-07-18T01:39:50.881Z" }, + { url = "https://files.pythonhosted.org/packages/e1/14/7caec26d93a943c0e7d15eb7374644508d08cbd387d112b722b12d14e044/ty-0.0.61-py3-none-win_arm64.whl", hash = "sha256:3e496f7698bc4b5bbb1eb66d8b5799ba87596d88d36604ca359083893fa2fc49", size = 11693485, upload-time = "2026-07-18T01:39:52.73Z" }, +] + +[[package]] +name = "typer" +version = "0.27.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "annotated-doc" }, + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "rich" }, + { name = "shellingham" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/37/78/fda3361b56efc27944f24225f6ecd13d96d6fcfe37bd0eb34e2f4c63f9fc/typer-0.27.0.tar.gz", hash = "sha256:629bd12ea5d13a17148125d9a264f949eb171fb3f120f9b04d85873cab054fa5", size = 203430, upload-time = "2026-07-15T19:21:07.007Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/40/03/26a383c9e58c213199d1aad1c3d353cfc22d4444ec6d2c0bf8ad02523843/typer-0.27.0-py3-none-any.whl", hash = "sha256:6f4b27631e47f077871b7dc30e933ec0131c1390fbe0e387ea5574b5bac9ccf1", size = 122716, upload-time = "2026-07-15T19:21:05.553Z" }, +] + +[[package]] +name = "typing-extensions" +version = "4.15.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" }, +] + +[[package]] +name = "typing-inspection" +version = "0.4.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/55/e3/70399cb7dd41c10ac53367ae42139cf4b1ca5f36bb3dc6c9d33acdb43655/typing_inspection-0.4.2.tar.gz", hash = "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464", size = 75949, upload-time = "2025-10-01T02:14:41.687Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7", size = 14611, upload-time = "2025-10-01T02:14:40.154Z" }, +] + +[[package]] +name = "tzdata" +version = "2026.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ba/19/1b9b0e29f30c6d35cb345486df41110984ea67ae69dddbc0e8a100999493/tzdata-2026.2.tar.gz", hash = "sha256:9173fde7d80d9018e02a662e168e5a2d04f87c41ea174b139fbef642eda62d10", size = 198254, upload-time = "2026-04-24T15:22:08.651Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ce/e4/dccd7f47c4b64213ac01ef921a1337ee6e30e8c6466046018326977efd95/tzdata-2026.2-py2.py3-none-any.whl", hash = "sha256:bbe9af844f658da81a5f95019480da3a89415801f6cc966806612cc7169bffe7", size = 349321, upload-time = "2026-04-24T15:22:05.876Z" }, +] + +[[package]] +name = "tzlocal" +version = "5.4.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "tzdata", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/81/5b/879b2f932adfa7a053c360d50bc896c977fa6426109185f7c12ebdd0cb9d/tzlocal-5.4.4.tar.gz", hash = "sha256:8dbb8660838688a7b6ba4fed31d18dedf842afb4d47ca050d6d891c2c15f3be4", size = 31170, upload-time = "2026-06-29T08:03:40.026Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9e/a4/017a7a6cbe387d961a688ec31364ae60a5c4e22c96ae9921b79a947c855d/tzlocal-5.4.4-py3-none-any.whl", hash = "sha256:aae09f0126a8a86fa736be266eb4a471380d26a0de3bc14844e7821fee3e2a15", size = 18115, upload-time = "2026-06-29T08:03:38.666Z" }, +] + +[[package]] +name = "uncalled-for" +version = "0.3.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b5/82/345cc927f7fbdae6065e7768759932fcc827fc20b29b45dfbafa2f1f7da4/uncalled_for-0.3.2.tar.gz", hash = "sha256:89f5dbcd71e2b8f47c030b1fa302e6cce2ec795d1ac565eeb6525c5fe55cb8a2", size = 50032, upload-time = "2026-05-06T13:38:25.204Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3b/25/2c87754f3a9e692315f7b811244090e68f362979fc8886b3fbd2985a1d8c/uncalled_for-0.3.2-py3-none-any.whl", hash = "sha256:0ff60b142c7d1f8070bde9d42afaa70aedc77dcc10998c227687e9c15713418e", size = 11444, upload-time = "2026-05-06T13:38:24.025Z" }, +] + +[[package]] +name = "urllib3" +version = "2.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/53/0c/06f8b233b8fd13b9e5ee11424ef85419ba0d8ba0b3138bf360be2ff56953/urllib3-2.7.0.tar.gz", hash = "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c", size = 433602, upload-time = "2026-05-07T16:13:18.596Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7f/3e/5db95bcf282c52709639744ca2a8b149baccf648e39c8cc87553df9eae0c/urllib3-2.7.0-py3-none-any.whl", hash = "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897", size = 131087, upload-time = "2026-05-07T16:13:17.151Z" }, +] + +[[package]] +name = "uvicorn" +version = "0.51.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "h11" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a2/65/b7c6c443ccc58678c91e1e973bbe2a878591538655d6e1d47f24ba1c51f3/uvicorn-0.51.0.tar.gz", hash = "sha256:f6f4b69b657c312f516dd2d268ab9ae6f254b11e4bac504f37b2ab58b24dd0b0", size = 94412, upload-time = "2026-07-08T10:59:05.962Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/45/ec/dbb7e5a6b91f86bfb9eb7d2988a2730907b6a729875b949c7f022e8b88fa/uvicorn-0.51.0-py3-none-any.whl", hash = "sha256:5d38af6cd620f2ae3849fb44fd4879e0890aa1febe8d47eb355fb45d93fe6a5b", size = 73219, upload-time = "2026-07-08T10:59:04.44Z" }, +] + +[[package]] +name = "websockets" +version = "16.1.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/21/f7/bc3a25c5ec26ce62ce487690becc2f3710bbc7b33338f005ad390db0b986/websockets-16.1.1.tar.gz", hash = "sha256:db234eda965dcce15df96bb9709f587cd87d4d52aaf0e80e2f34ec04c7670c57", size = 182204, upload-time = "2026-07-17T22:51:05.858Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2b/03/47debfe28e9d6d354be5d777b67fd44c359b9eb299a5d103500bd7cc3e37/websockets-16.1.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:d0fcf657e9f13ff4b177960ab2200237b12994232dfb6df16f1cfe1d4339f93c", size = 179566, upload-time = "2026-07-17T22:48:49.596Z" }, + { url = "https://files.pythonhosted.org/packages/72/93/31efa1ed78c17e5cfc229fd449e3966e1b9cc15753204cd585cc8dd01f4a/websockets-16.1.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b852788aa51764e2d8e4cf5493d559326bcae5e38d16ba25ffa322b034df272a", size = 177250, upload-time = "2026-07-17T22:48:50.942Z" }, + { url = "https://files.pythonhosted.org/packages/01/4a/542378ab3972b0c1cf1df3df3eff9591cea0d30c58c3aa3c4ddbc244e787/websockets-16.1.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1427fb4cf0d72f66333e2cacc3ff5f575bf2d7008166ce991a4a470b21d51a22", size = 177528, upload-time = "2026-07-17T22:48:52.59Z" }, + { url = "https://files.pythonhosted.org/packages/33/d9/162321f63c7eed558e9e1798ed7a1e34a4f6dab51f35419e4ed7a4907979/websockets-16.1.1-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:da4ca1a9d72f9030b3146b8d7022719a9f3d478f61efe6f7dd51d243f61c51b2", size = 186859, upload-time = "2026-07-17T22:48:53.915Z" }, + { url = "https://files.pythonhosted.org/packages/de/09/87df740f7430ce564bd52402e9c9458d4d0459cc7d2ee29e530c8204851b/websockets-16.1.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:86d7f0f8bdb25d2c632b72527325e4776430fd5bc61b9118de4e2b8ddb5f5b01", size = 188095, upload-time = "2026-07-17T22:48:55.384Z" }, + { url = "https://files.pythonhosted.org/packages/d2/12/3d2703af7cc095f3c81904c92208cc1ae79affbc67376944b50ee9301f73/websockets-16.1.1-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:7dfcad78ea1492ee3a9ec765cb7f51bbc17d477107aaf6b22abf7b2558d1c5a0", size = 191385, upload-time = "2026-07-17T22:48:56.742Z" }, + { url = "https://files.pythonhosted.org/packages/1d/69/986aa0234a964a00f5149cfc46e136e96c8faad1c783474550f40d31aef4/websockets-16.1.1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:fb9a0a6dc3d1b3986cb88091b6899f0396651e0f74e2c9766ab8d6ffc3842e29", size = 188653, upload-time = "2026-07-17T22:48:58.134Z" }, + { url = "https://files.pythonhosted.org/packages/35/6b/10f9d03e3970a69ba67bd3b46b87a929b586d0300fadbfe14f57c1f85490/websockets-16.1.1-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:29dfa8114c4a620c69591c5973860f768eac29d3fd6904f37f34266cb219c512", size = 187426, upload-time = "2026-07-17T22:48:59.515Z" }, + { url = "https://files.pythonhosted.org/packages/56/db/bb3aad62bf63d8bb3f0634b2eabffcfb3677a34bd19492110ff6869cf703/websockets-16.1.1-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:6ff9417c0ada4d0f7d212f928303e5579bdf3ace4c802fa4afabb30995da58c3", size = 184882, upload-time = "2026-07-17T22:49:00.916Z" }, + { url = "https://files.pythonhosted.org/packages/6c/4c/c09a2ea9bfbeccce52fdc383e5f28af4bc8843338aabac28c81489af6120/websockets-16.1.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8fe0b50da2d84535fb4f7b4bfa951280f97ce3d558a0443b541166d609e67b57", size = 187584, upload-time = "2026-07-17T22:49:02.283Z" }, + { url = "https://files.pythonhosted.org/packages/c7/8b/31bb4eb4d9eaacf1fdd39d115772a8aeaedfc19b5dc262e57ffbc8a9d42c/websockets-16.1.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:34420aaa64440ebd51ac72ca8a45ef4626429438c9b02e633ae412ed43f925d3", size = 186174, upload-time = "2026-07-17T22:49:03.973Z" }, + { url = "https://files.pythonhosted.org/packages/2f/e4/dc02d725610a1ad49e193ef91a548194d71bdc6cdf27da83067dd1f73995/websockets-16.1.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:a6a61aff018180c9c50b7b0da33bfd29d378af3497429c95006c589a23a11648", size = 187986, upload-time = "2026-07-17T22:49:05.553Z" }, + { url = "https://files.pythonhosted.org/packages/e0/73/30ed84c8bfd14c73d4af29d5ed9323c3073b48e0b7b23b67070f4e7fd59b/websockets-16.1.1-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:04fd29a0e2fe9414a95b00e92c67ae51bf900c50c0f8a4b2dafdad621f49ea1d", size = 185565, upload-time = "2026-07-17T22:49:06.959Z" }, + { url = "https://files.pythonhosted.org/packages/7d/d3/4be8d4959f51e31b4f8fc0ece12b45bd3b6c0d15ea23b9990d9c11fc805f/websockets-16.1.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:5c31aa7e39ee3e8a358573257f1c0bb5c52430d1b637030dd9c8cc2c282926be", size = 186598, upload-time = "2026-07-17T22:49:08.293Z" }, + { url = "https://files.pythonhosted.org/packages/26/fa/abb38597a52d84ed9cfacadc7a0c6f2db282c0ab23cdf72b58a666a21227/websockets-16.1.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d14bfb217eb4701e850f1525c9d29d79c44794cdf1c299ead25f39f8c78dea81", size = 186834, upload-time = "2026-07-17T22:49:09.766Z" }, + { url = "https://files.pythonhosted.org/packages/59/80/1119ad08a228b90c4eb77fbe48df7836731a605f5f881ba701ca826a4a65/websockets-16.1.1-cp311-cp311-win32.whl", hash = "sha256:2e28e602bb13da44fbe518c1781a88e3b9d4c3d48d02c9bad83e546164336f57", size = 179940, upload-time = "2026-07-17T22:49:11.196Z" }, + { url = "https://files.pythonhosted.org/packages/71/b2/e511c1c6f64a95c2f3fc54bffda0e14eaa7e9442be605c29270f7589b918/websockets-16.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:7421fad442de870a8cbf2287d1cad7e706ece0dbfeba5e911df132cbdc1cb56a", size = 180239, upload-time = "2026-07-17T22:49:12.519Z" }, + { url = "https://files.pythonhosted.org/packages/e1/ed/71fea6e141590cafc40b14dc5943b0845606bee87bdb52a21b6a73eb4311/websockets-16.1.1-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:820fb8450edddae3812fd58cbc08e2bf22812cb248ecb5f06dbb82119a56e869", size = 177185, upload-time = "2026-07-17T22:50:56.665Z" }, + { url = "https://files.pythonhosted.org/packages/01/ec/00e7eeca200facf9266a83e4cbbf1bed0e67fba1d4d45031d3e5b3d81b5c/websockets-16.1.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:125f22dbefaf1554fea66fc83851490edb284ce4f501d37ffed2752f418332d9", size = 177459, upload-time = "2026-07-17T22:50:58.197Z" }, + { url = "https://files.pythonhosted.org/packages/75/fd/5774c4b33f7c0d8f0c51809c8b3a93456c48e3543579262cfa64eb5f522e/websockets-16.1.1-pp311-pypy311_pp73-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:30bbe120437b5648a77d3519b7024ea09530e0b5b18d3698c5a0ae536fe0cc2e", size = 178294, upload-time = "2026-07-17T22:50:59.641Z" }, + { url = "https://files.pythonhosted.org/packages/37/c3/48e2c03d2bd79bb45948841c592d24156312dd5f58cdf8f549febe652fb6/websockets-16.1.1-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b6b9dadbef0cccd9f4c4ee96b08898afa73e26803bbe0f6aeb5bb12b0074206d", size = 179190, upload-time = "2026-07-17T22:51:01.129Z" }, + { url = "https://files.pythonhosted.org/packages/2d/3f/73e511ecf2496ceac57dd4ed8388efe2bcf0769338a2dbf242c8366ae87e/websockets-16.1.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:56cd5fc4f10a9ea8aa0804bddb7b42506cf9e136046f3b4c27de8fec9e2ecba5", size = 180330, upload-time = "2026-07-17T22:51:02.603Z" }, + { url = "https://files.pythonhosted.org/packages/be/4d/2d0d67834092e354d2b0498f014a41249a89556bc406cf86f3e1557bb463/websockets-16.1.1-py3-none-any.whl", hash = "sha256:6abbd3e82c731c8e531714466acd5d87b5e88ac3243465337ba71d68e23ae7e3", size = 173814, upload-time = "2026-07-17T22:51:04.184Z" }, +] + +[[package]] +name = "wheel" +version = "0.45.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/8a/98/2d9906746cdc6a6ef809ae6338005b3f21bb568bea3165cfc6a243fdc25c/wheel-0.45.1.tar.gz", hash = "sha256:661e1abd9198507b1409a20c02106d9670b2576e916d58f520316666abca6729", size = 107545, upload-time = "2024-11-23T00:18:23.513Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0b/2c/87f3254fd8ffd29e4c02732eee68a83a1d3c346ae39bc6822dcbcb697f2b/wheel-0.45.1-py3-none-any.whl", hash = "sha256:708e7481cc80179af0e556bbf0cc00b8444c7321e2700b8d8580231d13017248", size = 72494, upload-time = "2024-11-23T00:18:21.207Z" }, +] + +[[package]] +name = "wrapt" +version = "2.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/2b/b0/c1f5a970721f06b85c0cd5142e0ff8fe067708abd779b0c4f4be7d61d09f/wrapt-2.3.0.tar.gz", hash = "sha256:681a2d0eefd721998f90642762b8e75c2159ec531b20ad5e437245ea7b06a107", size = 131509, upload-time = "2026-07-28T06:06:14.895Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/00/b8/9182e4c618a847be0baccb68e4602b070d0fa22c782cf058f4bc66b32709/wrapt-2.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5ab559e1b2551d23d54db2a0001c6d73bad022a254639561c5f6c382a9d6c2fe", size = 81427, upload-time = "2026-07-28T06:04:20.106Z" }, + { url = "https://files.pythonhosted.org/packages/84/ca/613cefd9c5977366b1587e61c0b428176d382e6d75b454084c5e58503042/wrapt-2.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bff9a671bc00709cab5a7f745c592b5671873449db0ee2a569af994f16b29a4d", size = 82360, upload-time = "2026-07-28T06:04:21.613Z" }, + { url = "https://files.pythonhosted.org/packages/71/71/4cd2151a236f44a6e2dd4ed8011838d7ba0be3d656c8bafdfc65a2ed1917/wrapt-2.3.0-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:fc648a335d7e01adb3640b25f02fd0ea05886cf04d0af7f4ee902bc7b5e466e8", size = 161700, upload-time = "2026-07-28T06:04:22.723Z" }, + { url = "https://files.pythonhosted.org/packages/49/2c/bc508fee75eb2919ed69769800b09968e4aab16897f909a23f39c81e323f/wrapt-2.3.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d0077f3d65541925fa83002f967b22ad6550d24813ac64cb905f717194128d9c", size = 162922, upload-time = "2026-07-28T06:04:24.177Z" }, + { url = "https://files.pythonhosted.org/packages/4d/e5/04f34d38e66d857dfc2fc4088d60e70c0e422467822defa49b2b4a26e17b/wrapt-2.3.0-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:9790ea25190a4e0fe4cdf4eeb868e9d75f8a024a70a5b6bf9c348a3a2b72e731", size = 156125, upload-time = "2026-07-28T06:04:25.58Z" }, + { url = "https://files.pythonhosted.org/packages/23/41/c35940ea1c423f129ebe4361db853bc80d4def6326242e1206fa15bf94f4/wrapt-2.3.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:816877aa749253149f9ecfd2635d4d948ecfa338e1a0311d187b1acb1bb8a3eb", size = 162039, upload-time = "2026-07-28T06:04:27.154Z" }, + { url = "https://files.pythonhosted.org/packages/0e/60/9bda34c3d7d182aa703fe35339ae0ed4c4dad5e5c587f93890143e1f87fb/wrapt-2.3.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:3d1c2c1b808600d2ea808e6360910a60ed5f409a4011655e10f9164ba0a414a6", size = 155110, upload-time = "2026-07-28T06:04:28.497Z" }, + { url = "https://files.pythonhosted.org/packages/e8/ba/60bfd9b1a751f4fcb2d603668fc272d651ccdd339a56acf8c40ad21a0293/wrapt-2.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:5ba1e5e08ddc46130e9682b2c249f2d1dd39bda9106ed4bd401b7519f18f41bd", size = 161089, upload-time = "2026-07-28T06:04:29.959Z" }, + { url = "https://files.pythonhosted.org/packages/0f/32/2bd358c6f4f1305c813479d1e9ba746bebdd794f4a20107ab2b3ee0cbd45/wrapt-2.3.0-cp311-cp311-win32.whl", hash = "sha256:45c9279b373d15649dfa2c2077cb3408ea1a6d3125afbdab9d6b809a66f68e14", size = 78030, upload-time = "2026-07-28T06:04:31.241Z" }, + { url = "https://files.pythonhosted.org/packages/4a/62/ecc969b13b141fef89b888c9760821cb01a86ac8fc953911592c8e1e1522/wrapt-2.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:195b1842b4122fb54e3cd3dd5b2b4aa49302a5a61da901df0481f5c97aedde84", size = 80944, upload-time = "2026-07-28T06:04:32.655Z" }, + { url = "https://files.pythonhosted.org/packages/c4/3d/9278ada8a2b3f24372b630361e84e9a7de7abc3784634860c26d1c37785a/wrapt-2.3.0-cp311-cp311-win_arm64.whl", hash = "sha256:6db604ef0c67bdb2042ecdfd7b7f037cf09733557ca42360d1018285634f7b98", size = 80074, upload-time = "2026-07-28T06:04:33.811Z" }, + { url = "https://files.pythonhosted.org/packages/00/39/3daf9f47be208606586de4568ba6713db53ebc8fd7a575aea1fe57983b69/wrapt-2.3.0-py3-none-any.whl", hash = "sha256:d8c7ed08477429752b8c44991f40ad7838b18332a160698740a6bfbc10d998a2", size = 61866, upload-time = "2026-07-28T06:06:12.9Z" }, +] + +[[package]] +name = "yarl" +version = "1.24.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "idna" }, + { name = "multidict" }, + { name = "propcache" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/31/33/ebe9e3d1f86c7a0b51094c0a146392045ca1631d2664889539dec8088a33/yarl-1.24.5.tar.gz", hash = "sha256:e81b83143bee16329c23db3c1b2d82b29892fcbcb849186d2f6e98a5abe9a57f", size = 228679, upload-time = "2026-07-20T02:07:45.435Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fe/db/3cb5df059756a45761cc3dee8fd25ec82b83a6585ea3542b969fda850f99/yarl-1.24.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2c1fe720934a16ea8e7146175cba2126f87f54912c8c5435e7f7c7a51ef808d3", size = 135043, upload-time = "2026-07-20T02:04:52.39Z" }, + { url = "https://files.pythonhosted.org/packages/44/f8/767d6bd5a03db63bc467df2fb56d6fafeae9667d74aea92cd6af399f828b/yarl-1.24.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c687ed078e145f5fd53a14854beff320e1d2ab76df03e2009c98f39a0f68f39a", size = 96942, upload-time = "2026-07-20T02:04:54.26Z" }, + { url = "https://files.pythonhosted.org/packages/ce/97/10b939c44d7b28d1dbc389cfc7012306d1ea8dba01eaef44b39fffaee52a/yarl-1.24.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:709f1efed56c4a145793c046cd4939f9959bcd818979a787b77d8e09c57a0840", size = 97046, upload-time = "2026-07-20T02:04:56.638Z" }, + { url = "https://files.pythonhosted.org/packages/5b/7a/b410dbe39b6255c55fb2a2bcee96eb844d0789235ddc381a889a90dc72d6/yarl-1.24.5-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:874019bd513008b009f58657134e5d0c5e030b3559bd0553976837adf52fe966", size = 110512, upload-time = "2026-07-20T02:04:58.955Z" }, + { url = "https://files.pythonhosted.org/packages/83/c7/da591971f78a5617e1f21f5699858ebccd836fe181a6493788ffc91ba69b/yarl-1.24.5-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:a4582acf7ef76482f6f511ebaf1946dae7f2e85ec4728b81a678c01df63bd723", size = 102454, upload-time = "2026-07-20T02:05:00.623Z" }, + { url = "https://files.pythonhosted.org/packages/c4/8e/73b0ed4de47289a78a96045d76d1cfe5e41848bf0da59ce25b2ec87ee05d/yarl-1.24.5-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2cabe6546e41dabe439999a23fcb5246e0c3b595b4315b96ef755252be90caeb", size = 117617, upload-time = "2026-07-20T02:05:02.325Z" }, + { url = "https://files.pythonhosted.org/packages/cf/14/b744747bc4f57a8d55bd744df463457524583e1e9f7538b5ace0346ab92e/yarl-1.24.5-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:17f57620f5475b3c69109376cc87e42a7af5db13c9398e4292772a706ff10780", size = 116135, upload-time = "2026-07-20T02:05:04.05Z" }, + { url = "https://files.pythonhosted.org/packages/66/ca/95aa4d0e5b7ea4f20e4d577c42d001ed9df207569fdb063cc5ed4ebb496b/yarl-1.24.5-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:570fec8fbd22b032733625f03f10b7ff023bc399213db15e72a7acaef28c2f4e", size = 111935, upload-time = "2026-07-20T02:05:05.738Z" }, + { url = "https://files.pythonhosted.org/packages/72/0d/d2ad8d6b147832d177a4e720ba1962fe686eb0913b74503b3eca094b8bba/yarl-1.24.5-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:5fede79c6f73ff2c3ef822864cb1ada23196e62756df53bc6231d351a49516a2", size = 110010, upload-time = "2026-07-20T02:05:07.471Z" }, + { url = "https://files.pythonhosted.org/packages/50/18/eb335e4120903903f4865041355ae46256a2406eb2865bc24827f4f27b61/yarl-1.24.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8ccf9aca873b767977c73df497a85dbedee4ee086ae9ae49dc461333b9b79f58", size = 110058, upload-time = "2026-07-20T02:05:09.246Z" }, + { url = "https://files.pythonhosted.org/packages/44/70/97353add32c62ad6f206d948ac5a5ee84398225e534dc6ed6433d1b335b6/yarl-1.24.5-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:ad5d8201d310b031e6cd839d9bac2d4e5a01533ce5d3d5b50b7de1ef3af1de61", size = 103308, upload-time = "2026-07-20T02:05:11.31Z" }, + { url = "https://files.pythonhosted.org/packages/68/39/5e7398d4b6f6b3c9062823ebc60802df5b272e3fe9e788f9734c6ee46c85/yarl-1.24.5-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:841f0852f48fefea3b12c9dfec00704dfa3aef5215d0e3ce564bb3d7cd8d57c6", size = 116898, upload-time = "2026-07-20T02:05:13.099Z" }, + { url = "https://files.pythonhosted.org/packages/e4/c9/09e52f2239e8b96357eccca05915382e4ba5405ebfb623b6036040d99654/yarl-1.24.5-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:9baafc71b04f8f4bb0703b21d6fc9f0c30b346c636a532ff16ec8491a5ea4b1f", size = 109400, upload-time = "2026-07-20T02:05:14.821Z" }, + { url = "https://files.pythonhosted.org/packages/4b/6a/e94133d4c2d1a14d2384310bf3e79d9cf32c9d1eae1c6f034fb80d098fa1/yarl-1.24.5-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:d897129df1a22b12aeed2c2c98df0785a2e8e6e0bde87b389491d0025c187077", size = 115934, upload-time = "2026-07-20T02:05:17.78Z" }, + { url = "https://files.pythonhosted.org/packages/4e/3c/34955ed967b976fc38edcbb6d538dee79dbda4cb7fc7f72a0907a7c78e0f/yarl-1.24.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:dd625535328fd9882374356269227670189adfcc6a2d90284f323c05862eecbd", size = 112178, upload-time = "2026-07-20T02:05:19.675Z" }, + { url = "https://files.pythonhosted.org/packages/f5/46/d7bd3a8859d47dcfaffd7127af7076032a7da278a9a02e17b5f37bfb6712/yarl-1.24.5-cp311-cp311-win_amd64.whl", hash = "sha256:f4239bbec5a3577ddb49e4b50aeb32d8e5792098262ae2f63723f916a29b1a25", size = 97544, upload-time = "2026-07-20T02:05:21.523Z" }, + { url = "https://files.pythonhosted.org/packages/01/69/c1bfd21e32c638974ea2c542a0b8c53ef1fa9eff336020f5d014f9503ff2/yarl-1.24.5-cp311-cp311-win_arm64.whl", hash = "sha256:3ac6aff147deb9c09461b2d4bbdf6256831198f5d8a23f5d37138213090b6d8a", size = 93359, upload-time = "2026-07-20T02:05:23.493Z" }, + { url = "https://files.pythonhosted.org/packages/61/02/962c1cbfc401a30c1d034dc67ff395f64b52302c6d62de556c1fca99acc0/yarl-1.24.5-py3-none-any.whl", hash = "sha256:a33700d13d9b7d84fd10947b09ff69fb9a792e519c8cb9764a3ca70baa6c23a7", size = 58612, upload-time = "2026-07-20T02:07:43.461Z" }, +]