pax_global_header00006660000000000000000000000064151737164730014530gustar00rootroot0000000000000052 comment=f84fc183d1148e0a82e314c55b0f8e56b32c50ba python-openapi-openapi-schema-validator-9480dee/000077500000000000000000000000001517371647300220005ustar00rootroot00000000000000python-openapi-openapi-schema-validator-9480dee/.github/000077500000000000000000000000001517371647300233405ustar00rootroot00000000000000python-openapi-openapi-schema-validator-9480dee/.github/FUNDING.yml000066400000000000000000000000201517371647300251450ustar00rootroot00000000000000github: [p1c2u] python-openapi-openapi-schema-validator-9480dee/.github/dependabot.yml000066400000000000000000000003151517371647300261670ustar00rootroot00000000000000version: 2 updates: - package-ecosystem: "pip" directory: "/" schedule: interval: "weekly" - package-ecosystem: "github-actions" directory: "/" schedule: interval: "weekly" python-openapi-openapi-schema-validator-9480dee/.github/workflows/000077500000000000000000000000001517371647300253755ustar00rootroot00000000000000python-openapi-openapi-schema-validator-9480dee/.github/workflows/docs-build.yml000066400000000000000000000027441517371647300301540ustar00rootroot00000000000000name: CI / Docs on: push: pull_request: types: [opened, synchronize] jobs: docs_build: name: "Build" runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - name: Set up Python 3.12 uses: actions/setup-python@v6 with: python-version: "3.12" - name: Get full Python version id: full-python-version run: echo ::set-output name=version::$(python -c "import sys; print('-'.join(str(v) for v in sys.version_info))") - name: Set up poetry uses: Gr1N/setup-poetry@v9 with: poetry-version: "2.1.1" - name: Configure poetry run: poetry config virtualenvs.in-project true - name: Set up cache uses: actions/cache@v5 id: cache with: path: .venv key: venv-${{ steps.full-python-version.outputs.version }}-${{ hashFiles('**/poetry.lock') }} - name: Ensure cache is healthy if: steps.cache.outputs.cache-hit == 'true' run: timeout 10s poetry run pip --version || rm -rf .venv - name: Install dependencies run: poetry install --with docs - name: Build documentation run: | poetry run python -m sphinx -T -b html -d docs/_build/doctrees -D language=en docs docs/_build/html -n -W - uses: actions/upload-artifact@v7 name: Upload docs as artifact with: name: docs-html path: './docs/_build/html' if-no-files-found: error python-openapi-openapi-schema-validator-9480dee/.github/workflows/python-publish.yml000066400000000000000000000014541517371647300311110ustar00rootroot00000000000000# This workflow will upload a Python Package using Twine when a release is created # For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries name: Publish python packages on: workflow_dispatch: release: types: - published jobs: publish: runs-on: ubuntu-latest permissions: id-token: write steps: - uses: actions/checkout@v6 - name: Set up Python uses: actions/setup-python@v6 with: python-version: '3.x' - name: Set up poetry uses: Gr1N/setup-poetry@v9 - name: Build run: poetry build - name: Publish uses: pypa/gh-action-pypi-publish@release/v1 with: packages-dir: dist/ python-openapi-openapi-schema-validator-9480dee/.github/workflows/python-tests.yml000066400000000000000000000101221517371647300305750ustar00rootroot00000000000000# This workflow will install Python dependencies, run tests and lint with a variety of Python versions # For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions name: CI / Tests on: push: pull_request: types: [opened, synchronize] jobs: tests: name: "py${{ matrix.python-version }}" runs-on: ubuntu-latest strategy: matrix: python-version: ['3.10', '3.11', '3.12', '3.13', '3.14'] fail-fast: false steps: - uses: actions/checkout@v6 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v6 with: python-version: ${{ matrix.python-version }} - name: Get full Python version id: full-python-version run: echo ::set-output name=version::$(python -c "import sys; print('-'.join(str(v) for v in sys.version_info))") - name: Set up poetry uses: Gr1N/setup-poetry@v9 - name: Configure poetry run: poetry config virtualenvs.in-project true - name: Set up cache uses: actions/cache@v5 id: cache with: path: .venv key: venv-${{ steps.full-python-version.outputs.version }}-${{ hashFiles('**/poetry.lock') }} - name: Ensure cache is healthy if: steps.cache.outputs.cache-hit == 'true' run: timeout 10s poetry run pip --version || rm -rf .venv - name: Install dependencies run: poetry install --all-extras - name: Test env: PYTEST_ADDOPTS: "--color=yes" run: poetry run pytest - name: Static type check run: poetry run mypy - name: Check dependencies run: poetry run deptry . - name: Upload coverage uses: codecov/codecov-action@v6 tests_no_extras: name: "py3.14 no extras" runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - name: Set up Python 3.14 uses: actions/setup-python@v6 with: python-version: "3.14" - name: Get full Python version id: full-python-version run: echo ::set-output name=version::$(python -c "import sys; print('-'.join(str(v) for v in sys.version_info))") - name: Set up poetry uses: Gr1N/setup-poetry@v9 - name: Configure poetry run: poetry config virtualenvs.in-project true - name: Set up cache uses: actions/cache@v5 id: cache with: path: .venv key: venv-no-extras-${{ steps.full-python-version.outputs.version }}-${{ hashFiles('**/poetry.lock') }} - name: Ensure cache is healthy if: steps.cache.outputs.cache-hit == 'true' run: timeout 10s poetry run pip --version || rm -rf .venv - name: Install dependencies run: poetry install - name: Test fallback regex behavior env: PYTEST_ADDOPTS: "--color=yes" run: poetry run pytest tests/integration/test_validators.py -k pattern static_checks: name: "Static checks" runs-on: ubuntu-latest steps: - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" uses: actions/checkout@v6 - name: "Setup Python" uses: actions/setup-python@v6 with: python-version: "3.10" - name: Get full Python version id: full-python-version run: echo ::set-output name=version::$(python -c "import sys; print('-'.join(str(v) for v in sys.version_info))") - name: Set up poetry uses: Gr1N/setup-poetry@v9 - name: Configure poetry run: poetry config virtualenvs.in-project true - name: Set up cache uses: actions/cache@v5 id: cache with: path: .venv key: venv-${{ steps.full-python-version.outputs.version }}-${{ hashFiles('**/poetry.lock') }} - name: Ensure cache is healthy if: steps.cache.outputs.cache-hit == 'true' run: timeout 10s poetry run pip --version || rm -rf .venv - name: Install dependencies run: poetry install - name: Run static checks run: poetry run pre-commit run -a python-openapi-openapi-schema-validator-9480dee/.gitignore000066400000000000000000000035111517371647300237700ustar00rootroot00000000000000# Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] *$py.class # C extensions *.so # Distribution / packaging .Python build/ develop-eggs/ dist/ downloads/ eggs/ .eggs/ lib/ lib64/ parts/ sdist/ var/ wheels/ 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 # Installer logs pip-log.txt pip-delete-this-directory.txt # Unit test / coverage reports htmlcov/ .tox/ .nox/ .coverage .coverage.* .cache nosetests.xml coverage.xml *.cover *.py,cover .hypothesis/ .pytest_cache/ reports/ # Translations *.mo *.pot # Django stuff: *.log local_settings.py db.sqlite3 db.sqlite3-journal # Flask stuff: instance/ .webassets-cache # Scrapy stuff: .scrapy # Sphinx documentation docs/_build/ # PyBuilder 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 # asdf versions .tool-versions .default-python-packages # mypy .mypy_cache/ .dmypy.json dmypy.json # Pyre type checker .pyre/ python-openapi-openapi-schema-validator-9480dee/.pre-commit-config.yaml000066400000000000000000000015421517371647300262630ustar00rootroot00000000000000--- default_stages: [pre-commit, pre-push] default_language_version: # force all unspecified python hooks to run python3 python: python3 minimum_pre_commit_version: "1.20.0" repos: - repo: meta hooks: - id: check-hooks-apply - repo: https://github.com/asottile/pyupgrade rev: v2.38.4 hooks: - id: pyupgrade args: ["--py36-plus"] - repo: local hooks: - id: flynt name: Convert to f-strings with flynt entry: flynt language: python additional_dependencies: ['flynt==0.76'] - id: black name: black entry: black language: system require_serial: true types: [python] - id: isort name: isort entry: isort args: ['--filter-files'] language: system require_serial: true types: [python] python-openapi-openapi-schema-validator-9480dee/.readthedocs.yaml000066400000000000000000000006141517371647300252300ustar00rootroot00000000000000version: 2 sphinx: configuration: docs/conf.py formats: all build: os: ubuntu-24.04 tools: python: "3.10" jobs: post_create_environment: - pip install "poetry==2.1.1" - poetry config virtualenvs.create false post_install: - poetry install --with docs --no-interaction --no-ansi - python -m pip install --no-cache-dir "sphinx-immaterial>=0.11,<0.14" python-openapi-openapi-schema-validator-9480dee/.travis.yml000066400000000000000000000006341517371647300241140ustar00rootroot00000000000000language: python sudo: false matrix: include: - python: 3.10 - python: 3.11 - python: 3.12 - python: nightly - python: pypy3 allow_failures: - python: nightly before_install: - curl -sL https://raw.githubusercontent.com/python-poetry/poetry/master/install-poetry.py | python - -y - export PATH=$PATH:$HOME/.local/bin install: - poetry install script: - poetry run pytest after_success: - codecov python-openapi-openapi-schema-validator-9480dee/AGENTS.md000066400000000000000000000140421517371647300233040ustar00rootroot00000000000000# AGENTS.md Agent guide for `openapi-schema-validator`. Use this as the default operating playbook when making changes. ## Project Snapshot - Language: Python. - Build backend and packaging: Poetry (`poetry-core`). - Runtime package: `openapi_schema_validator/`. - Tests: `pytest` in `tests/unit` and `tests/integration`. - Type checking: `mypy` with `strict = true`. - Formatting and imports: `black` and `isort`. - Extra static analysis: `deptry`. - Supported Python versions: 3.10, 3.11, 3.12, 3.13, 3.14. ## Source Layout - `openapi_schema_validator/__init__.py`: public exports + package metadata. - `openapi_schema_validator/validators.py`: validator class setup for OAS 3.0/3.1/3.2. - `openapi_schema_validator/_keywords.py`: custom keyword handlers and ValidationError generation. - `openapi_schema_validator/_format.py`: format checker functions and registrations. - `openapi_schema_validator/_types.py`: custom type checker setup. - `openapi_schema_validator/shortcuts.py`: top-level `validate` helper. - `tests/unit/`: focused unit tests. - `tests/integration/`: validator behavior integration coverage. - `docs/`: Sphinx source files. ## Environment Setup 1. Install Poetry. 2. Recommended one-time config: - `poetry config virtualenvs.in-project true` 3. Install dependencies: - `poetry install` 4. Include docs toolchain when needed: - `poetry install --with docs` ## Build, Lint, and Test Commands Run commands from repository root. ### Install / bootstrap - `poetry install` - `poetry install --all-extras` (matches CI tests job) ### Test suite - Full suite: `poetry run pytest` - Unit only: `poetry run pytest tests/unit` - Integration only: `poetry run pytest tests/integration` ### Running a single test (important) - Single file: `poetry run pytest tests/unit/test_shortcut.py` - Single test function: - `poetry run pytest tests/unit/test_shortcut.py::test_validate_does_not_mutate_schema` - Single test class: - `poetry run pytest tests/integration/test_validators.py::TestOAS31ValidatorValidate` - Pattern selection: `poetry run pytest -k nullable` ### Type checks - `poetry run mypy` ### Lint / formatting / static checks - Full pre-commit run: `poetry run pre-commit run -a` - Staged files pre-commit run: `poetry run pre-commit run` - Format explicitly: `poetry run black .` - Sort imports explicitly: `poetry run isort .` - Convert to f-strings where safe: `poetry run flynt .` - Dependency hygiene: `poetry run deptry .` ### Build package / docs - Build distributions: `poetry build` - Build docs (CI-equivalent command): - `poetry run python -m sphinx -T -b html -d docs/_build/doctrees -D language=en docs docs/_build/html -n -W` ## Pytest Behavior Notes - Default `pytest` options are defined in `pyproject.toml`. - Normal runs are verbose and include local variable display on failures. - Reports are generated in `reports/junit.xml` and `reports/coverage.xml`. - Coverage is collected for `openapi_schema_validator` by default. - Test commands usually update files under `reports/`. ## Code Style Rules (Repository-Specific) ### Formatting - Black line length is 79; keep new code Black-compatible. - Prefer clear, wrapped multi-line literals for schemas and parametrized test data. - Follow existing wrapping style for function signatures and long calls. ### Imports - Isort is configured with `profile = "black"`, `line_length = 79`, and `force_single_line = true`. - Import one symbol per line in `from ... import ...` blocks. - Keep import grouping conventional: stdlib, third-party, local package. - Prefer absolute imports from `openapi_schema_validator`. ### Types - Keep all new functions fully type-annotated (mypy strict mode). - Use `Mapping[str, Any]` for schema-like readonly mappings. - Use `Iterator[ValidationError]` for keyword handler generators. - Use `Any` and `cast(...)` only when necessary for interop with jsonschema internals. ### Naming conventions - Functions and variables: `snake_case`. - Classes: `PascalCase`. - Constants: `UPPER_SNAKE_CASE` (e.g., validator maps). - Tests: `test_*` functions; group with `Test*` classes when useful. - Preserve OpenAPI field spellings exactly (`readOnly`, `writeOnly`, `nullable`, etc.). ### Error handling and validation behavior - Validation failures should raise or yield `jsonschema.exceptions.ValidationError`. - Prefer narrow exception handling (`FormatError`, etc.) instead of broad catches. - If broad catches are required for ref-resolution boundaries, convert to explicit `ValidationError` messages. - Keep error text stable and human-readable; tests assert message content. - Preserve `None` return behavior for successful `.validate(...)` paths. ### Behavioral constraints to preserve - Do not mutate incoming schema objects in helper APIs. - Maintain compatibility for OAS 3.0, OAS 3.1, and OAS 3.2 validators. - Keep existing read/write behavior around `readOnly` and `writeOnly`. - Keep format and type checker semantics aligned with current tests. ## Testing Expectations for Changes - For small edits, run the most targeted pytest selection first. - Before handoff when feasible, run: - `poetry run pytest` - `poetry run mypy` - `poetry run pre-commit run -a` - If you changed dependencies/import graph, also run `poetry run deptry .`. ## CI Parity Checklist - CI tests run on Python 3.10-3.14. - CI static checks run via `pre-commit`. - CI docs job builds Sphinx docs with warnings treated as errors. - Keep local validation aligned with `.github/workflows/`. ## Cursor / Copilot Instructions Status - `.cursor/rules/` was not found. - `.cursorrules` was not found. - `.github/copilot-instructions.md` was not found. - If any of these appear later, treat them as higher-priority instructions and update this guide. ## Practical Workflow for Agents 1. Read `pyproject.toml` and the nearest related module/tests before editing. 2. Make minimal, focused changes that match existing patterns. 3. Add or update tests in the closest relevant test module. 4. Run a single-test command first, then broader checks. 5. Keep `openapi_schema_validator/__init__.py` exports synchronized if public API changes. python-openapi-openapi-schema-validator-9480dee/CONTRIBUTING.rst000066400000000000000000000002251517371647300244400ustar00rootroot00000000000000Please read the `Contributing `__ guidelines in the documentation site. python-openapi-openapi-schema-validator-9480dee/LICENSE000066400000000000000000000027451517371647300230150ustar00rootroot00000000000000BSD 3-Clause License Copyright (c) 2020, A All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. python-openapi-openapi-schema-validator-9480dee/MANIFEST.in000066400000000000000000000001311517371647300235310ustar00rootroot00000000000000include LICENSE include README.rst include requirements.txt include requirements_dev.txt python-openapi-openapi-schema-validator-9480dee/Makefile000066400000000000000000000014221517371647300234370ustar00rootroot00000000000000.EXPORT_ALL_VARIABLES: PROJECT_NAME=openapi-schema-validator PACKAGE_NAME=$(subst -,_,${PROJECT_NAME}) VERSION=`git describe --abbrev=0` PYTHONDONTWRITEBYTECODE=1 params: @echo "Project name: ${PROJECT_NAME}" @echo "Package name: ${PACKAGE_NAME}" @echo "Version: ${VERSION}" dist-build: @poetry build dist-cleanup: @rm -rf build dist ${PACKAGE_NAME}.egg-info dist-upload: @poetry publish test-python: @pytest test-cache-cleanup: @rm -rf .pytest_cache reports-cleanup: @rm -rf reports test-cleanup: test-cache-cleanup reports-cleanup docs-html: sphinx-build -b html docs docs/_build docs-cleanup: @rm -rf docs/_build cleanup: dist-cleanup test-cleanup release/patch: @bump2version patch release/minor: @bump2version minor release/major: @bump2version major python-openapi-openapi-schema-validator-9480dee/README.rst000066400000000000000000000212531517371647300234720ustar00rootroot00000000000000************************ openapi-schema-validator ************************ .. image:: https://img.shields.io/pypi/v/openapi-schema-validator.svg :target: https://pypi.org/project/openapi-schema-validator/ .. image:: https://github.com/python-openapi/openapi-schema-validator/actions/workflows/python-tests.yml/badge.svg :target: https://github.com/python-openapi/openapi-schema-validator/actions .. image:: https://img.shields.io/codecov/c/github/python-openapi/openapi-schema-validator/master.svg?style=flat :target: https://codecov.io/github/python-openapi/openapi-schema-validator?branch=master .. image:: https://img.shields.io/pypi/pyversions/openapi-schema-validator.svg :target: https://pypi.org/project/openapi-schema-validator/ .. image:: https://img.shields.io/pypi/format/openapi-schema-validator.svg :target: https://pypi.org/project/openapi-schema-validator/ .. image:: https://img.shields.io/pypi/status/openapi-schema-validator.svg :target: https://pypi.org/project/openapi-schema-validator/ About ##### openapi-schema-validator is a Python library that validates schemas against: * `OpenAPI Schema Specification v3.0 `__ which is an extended subset of the `JSON Schema Specification Wright Draft 00 `__. * `OpenAPI Schema Specification v3.1 `__ which is an extended superset of the `JSON Schema Specification Draft 2020-12 `__. * `OpenAPI Schema Specification v3.2 `__ using the published OAS 3.2 JSON Schema dialect resources. Documentation ############# Check documentation to see more details about the features. All documentation is in the "docs" directory and online at `openapi-schema-validator.readthedocs.io `__ Installation ############ Recommended way (via pip): .. code-block:: console pip install openapi-schema-validator Alternatively you can download the code and install from the repository: .. code-block:: console pip install "git+https://github.com/python-openapi/openapi-schema-validator.git" Usage ##### ``validate`` call signature is: .. code-block:: python validate( instance, schema, cls=OAS32Validator, allow_remote_references=False, check_schema=True, enforce_properties_required=False, **kwargs, ) The first argument is always the value you want to validate. The second argument is always the OpenAPI schema object. The ``cls`` keyword argument is optional and defaults to ``OAS32Validator``. Use ``cls`` when you need a specific validator version/behavior. .. code-block:: python from openapi_schema_validator import OAS30Validator from openapi_schema_validator import OAS31Validator from openapi_schema_validator import validate # OpenAPI 3.0 behavior validate(instance, schema, cls=OAS30Validator) # OpenAPI 3.1 behavior validate(instance, schema, cls=OAS31Validator) # OpenAPI 3.2 behavior (default) validate(instance, schema) Common forwarded keyword arguments include ``registry`` (reference context) and ``format_checker`` (format validation behavior). By default, ``validate`` uses a local-only empty registry to avoid implicit remote ``$ref`` retrieval. To resolve external references, pass an explicit ``registry``. Set ``allow_remote_references=True`` only if you explicitly accept jsonschema's default remote retrieval behavior. ``check_schema`` defaults to ``True`` and validates the schema before validating an instance. For trusted pre-validated schemas in hot paths, set ``check_schema=False`` to skip schema checking. When ``enforce_properties_required=True`` is passed, all properties declared in the schema's ``properties`` object are strictly required to be present in the instance (except those marked as ``writeOnly`` or ``readOnly`` where appropriate), regardless of the schema's ``required`` array. This is useful for response or contract testing to ensure no documented fields are missing. The ``validate`` helper keeps an internal compiled-validator cache. You can control cache size using the ``OPENAPI_SCHEMA_VALIDATOR_COMPILED_VALIDATOR_CACHE_MAX_SIZE`` environment variable (default: ``128``). The value is loaded once at first use and reused for the lifetime of the process. To validate an OpenAPI schema: .. code-block:: python from openapi_schema_validator import validate # A sample schema schema = { "type": "object", "required": [ "name" ], "properties": { "name": { "type": "string" }, "age": { "type": ["integer", "null"], "format": "int32", "minimum": 0, }, "birth-date": { "type": "string", "format": "date", }, "address": { "type": 'array', "prefixItems": [ { "type": "number" }, { "type": "string" }, { "enum": ["Street", "Avenue", "Boulevard"] }, { "enum": ["NW", "NE", "SW", "SE"] } ], "items": False, } }, "additionalProperties": False, } # If no exception is raised by validate(), the instance is valid. validate({"name": "John", "age": 23, "address": [1600, "Pennsylvania", "Avenue"]}, schema) validate({"name": "John", "city": "London"}, schema) Expected failure output: .. code-block:: text Traceback (most recent call last): ... ValidationError: Additional properties are not allowed ('city' was unexpected) By default, the latest OpenAPI schema syntax is expected. Default dialect resolution -------------------------- The OpenAPI 3.1 and 3.2 base dialect URIs are registered for ``jsonschema.validators.validator_for`` resolution. Schemas declaring ``"$schema"`` as either ``"https://spec.openapis.org/oas/3.1/dialect/base"`` or ``"https://spec.openapis.org/oas/3.2/dialect/2025-09-17"`` resolve directly to ``OAS31Validator`` and ``OAS32Validator`` without unresolved-metaschema fallback warnings. .. code-block:: python from jsonschema.validators import validator_for from openapi_schema_validator import OAS31Validator from openapi_schema_validator import OAS32Validator schema = { "$schema": "https://spec.openapis.org/oas/3.1/dialect/base", "type": "object", } schema32 = { "$schema": "https://spec.openapis.org/oas/3.2/dialect/2025-09-17", "type": "object", } assert validator_for(schema) is OAS31Validator assert validator_for(schema32) is OAS32Validator Binary Data Semantics ===================== The handling of binary-like payloads differs between OpenAPI versions. OpenAPI 3.0 ----------- OpenAPI 3.0 keeps historical ``format: binary`` / ``format: byte`` usage on ``type: string``. **OAS30Validator (default - compatibility behavior)** - ``type: string`` accepts ``str`` - ``type: string, format: binary`` accepts Python ``bytes`` and strings - useful when validating Python-native runtime data **OAS30StrictValidator** - ``type: string`` accepts ``str`` only - ``type: string, format: binary`` uses strict format validation - use when you want strict, spec-oriented behavior for 3.0 schemas OpenAPI 3.1+ ------------ OpenAPI 3.1+ follows JSON Schema semantics for string typing in this library. - ``type: string`` accepts ``str`` only (not ``bytes``) - ``format: binary`` and ``format: byte`` are not treated as built-in formats - for base64-in-JSON, model with ``contentEncoding: base64`` (optionally ``contentMediaType``) - for raw binary payloads, model via media type (for example ``application/octet-stream``) rather than schema string formats Regex Behavior ============== By default, ``pattern`` handling follows host Python regex behavior. For ECMAScript-oriented regex validation and matching (via ``regress``), install the optional extra: .. code-block:: console pip install "openapi-schema-validator[ecma-regex]" For more details read about `Validation `__. Related projects ################ * `openapi-core `__ Python library that adds client-side and server-side support for the OpenAPI. * `openapi-spec-validator `__ Python library that validates OpenAPI Specs against the OpenAPI 2.0 (aka Swagger) and OpenAPI 3.0 specification python-openapi-openapi-schema-validator-9480dee/SECURITY.md000066400000000000000000000023631517371647300235750ustar00rootroot00000000000000# Security Policy ## Reporting a Vulnerability If you believe you have found a security vulnerability in the repository, please report it to us as described below. **Please do not report security vulnerabilities through public GitHub issues.** Instead, please report them directly to the repository maintainers or use GitHub's private vulnerability reporting flow (``Security Advisories``) to report security issues privately: https://docs.github.com/en/code-security/how-tos/report-and-fix-vulnerabilities/report-a-vulnerability/privately-reporting-a-security-vulnerability Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) * Full paths of source file(s) related to the manifestation of the issue * The location of the affected source code (tag/branch/commit or direct URL) * Any special configuration required to reproduce the issue * Step-by-step instructions to reproduce the issue * Proof-of-concept or exploit code (if possible) * Impact of the issue, including how an attacker might exploit the issue * This information will help us triage your report more quickly. python-openapi-openapi-schema-validator-9480dee/benchmarks/000077500000000000000000000000001517371647300241155ustar00rootroot00000000000000python-openapi-openapi-schema-validator-9480dee/benchmarks/__init__.py000066400000000000000000000000001517371647300262140ustar00rootroot00000000000000python-openapi-openapi-schema-validator-9480dee/benchmarks/cases.py000066400000000000000000000141741517371647300255740ustar00rootroot00000000000000from dataclasses import dataclass from typing import Any from referencing import Registry from referencing import Resource from referencing.jsonschema import DRAFT202012 from openapi_schema_validator import OAS30Validator from openapi_schema_validator import OAS31Validator from openapi_schema_validator import OAS32Validator from openapi_schema_validator import oas30_format_checker from openapi_schema_validator import oas31_format_checker from openapi_schema_validator import oas32_format_checker @dataclass(frozen=True) class BenchmarkCase: name: str validator_class: Any schema: dict[str, Any] instance: Any validator_kwargs: dict[str, Any] def build_cases() -> list[BenchmarkCase]: name_schema = Resource.from_contents( { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "string", } ) age_schema = DRAFT202012.create_resource( { "type": "integer", "format": "int32", "minimum": 0, "maximum": 120, } ) registry = Registry().with_resources( [ ("urn:name-schema", name_schema), ("urn:age-schema", age_schema), ] ) return [ BenchmarkCase( name="oas32_simple_object", validator_class=OAS32Validator, schema={ "type": "object", "required": ["name"], "properties": { "name": {"type": "string"}, "enabled": {"type": "boolean"}, }, "additionalProperties": False, }, instance={"name": "svc", "enabled": True}, validator_kwargs={"format_checker": oas32_format_checker}, ), BenchmarkCase( name="oas31_prefix_items", validator_class=OAS31Validator, schema={ "type": "array", "prefixItems": [ {"type": "number"}, {"type": "string"}, {"enum": ["Street", "Avenue", "Boulevard"]}, {"enum": ["NW", "NE", "SW", "SE"]}, ], "items": False, }, instance=[1600, "Pennsylvania", "Avenue", "NW"], validator_kwargs={"format_checker": oas31_format_checker}, ), BenchmarkCase( name="oas30_nullable", validator_class=OAS30Validator, schema={"type": "string", "nullable": True}, instance=None, validator_kwargs={"format_checker": oas30_format_checker}, ), BenchmarkCase( name="oas30_discriminator", validator_class=OAS30Validator, schema={ "$ref": "#/components/schemas/Route", "components": { "schemas": { "MountainHiking": { "type": "object", "properties": { "discipline": { "type": "string", "enum": [ "mountain_hiking", "MountainHiking", ], }, "length": {"type": "integer"}, }, "required": ["discipline", "length"], }, "AlpineClimbing": { "type": "object", "properties": { "discipline": { "type": "string", "enum": ["alpine_climbing"], }, "height": {"type": "integer"}, }, "required": ["discipline", "height"], }, "Route": { "oneOf": [ { "$ref": ( "#/components/schemas/" "MountainHiking" ) }, { "$ref": ( "#/components/schemas/" "AlpineClimbing" ) }, ], "discriminator": { "propertyName": "discipline", "mapping": { "mountain_hiking": ( "#/components/schemas/" "MountainHiking" ), "alpine_climbing": ( "#/components/schemas/" "AlpineClimbing" ), }, }, }, } }, }, instance={"discipline": "mountain_hiking", "length": 10}, validator_kwargs={"format_checker": oas30_format_checker}, ), BenchmarkCase( name="oas32_registry_refs", validator_class=OAS32Validator, schema={ "type": "object", "required": ["name"], "properties": { "name": {"$ref": "urn:name-schema"}, "age": {"$ref": "urn:age-schema"}, }, "additionalProperties": False, }, instance={"name": "John", "age": 23}, validator_kwargs={ "format_checker": oas32_format_checker, "registry": registry, }, ), ] python-openapi-openapi-schema-validator-9480dee/benchmarks/compare.py000066400000000000000000000113251517371647300261170ustar00rootroot00000000000000from __future__ import annotations import argparse import json from pathlib import Path from typing import Any LOWER_IS_BETTER_METRICS = { "compile_ms", "first_validate_ms", "compiled_peak_memory_kib", } HIGHER_IS_BETTER_METRICS = { "compiled_validations_per_second", "helper_validations_per_second", "helper_trusted_validations_per_second", } ALL_METRICS = [ "compile_ms", "first_validate_ms", "compiled_validations_per_second", "helper_validations_per_second", "helper_trusted_validations_per_second", "compiled_peak_memory_kib", ] def _parse_args() -> argparse.Namespace: parser = argparse.ArgumentParser( description="Compare two benchmark JSON reports.", ) parser.add_argument( "--baseline", type=Path, required=True, help="Path to baseline benchmark JSON.", ) parser.add_argument( "--candidate", type=Path, required=True, help="Path to candidate benchmark JSON.", ) parser.add_argument( "--regression-threshold", type=float, default=0.0, help=( "Percent threshold for regressions. " "Example: 5 means fail only when regression exceeds 5%%." ), ) parser.add_argument( "--fail-on-regression", action="store_true", help="Exit with status 1 if regressions exceed threshold.", ) return parser.parse_args() def _load_report(path: Path) -> dict[str, Any]: return json.loads(path.read_text(encoding="utf-8")) def _cases_by_name(report: dict[str, Any]) -> dict[str, dict[str, Any]]: return {case["name"]: case for case in report["cases"]} def _percent_change(baseline_value: float, candidate_value: float) -> float: if baseline_value == 0: if candidate_value == 0: return 0.0 return float("inf") return ((candidate_value - baseline_value) / baseline_value) * 100.0 def _is_regression(metric: str, percent_change: float) -> bool: if metric in LOWER_IS_BETTER_METRICS: return percent_change > 0 return percent_change < 0 def _format_status(is_regression: bool, percent_change: float) -> str: if abs(percent_change) < 1e-12: return "no change (0.00%)" direction = "regression" if is_regression else "improvement" sign = "+" if percent_change >= 0 else "" return f"{direction} ({sign}{percent_change:.2f}%)" def _compare_reports( baseline: dict[str, Any], candidate: dict[str, Any], regression_threshold: float, ) -> tuple[list[str], list[str]]: baseline_cases = _cases_by_name(baseline) candidate_cases = _cases_by_name(candidate) report_lines: list[str] = [] regressions: list[str] = [] for case_name in sorted(baseline_cases): if case_name not in candidate_cases: regressions.append( f"Missing case in candidate report: {case_name}" ) continue report_lines.append(f"Case: {case_name}") baseline_case = baseline_cases[case_name] candidate_case = candidate_cases[case_name] for metric in ALL_METRICS: baseline_value = float(baseline_case[metric]) candidate_value = float(candidate_case[metric]) change = _percent_change(baseline_value, candidate_value) regression = _is_regression(metric, change) status = _format_status(regression, change) report_lines.append( " " f"{metric}: baseline={baseline_value:.6f} " f"candidate={candidate_value:.6f} -> {status}" ) if regression and abs(change) > regression_threshold: regressions.append( f"{case_name} {metric} regressed by {abs(change):.2f}%" ) extra_candidate_cases = set(candidate_cases).difference(baseline_cases) for case_name in sorted(extra_candidate_cases): report_lines.append(f"Case present only in candidate: {case_name}") return report_lines, regressions def main() -> int: args = _parse_args() baseline = _load_report(args.baseline) candidate = _load_report(args.candidate) report_lines, regressions = _compare_reports( baseline, candidate, args.regression_threshold, ) print( f"Comparing candidate {args.candidate} " f"against baseline {args.baseline}" ) print("") print("\n".join(report_lines)) if regressions: print("") print("Regressions above threshold:") for regression in regressions: print(f"- {regression}") if args.fail_on_regression: return 1 return 0 if __name__ == "__main__": raise SystemExit(main()) python-openapi-openapi-schema-validator-9480dee/benchmarks/run.py000066400000000000000000000140431517371647300252750ustar00rootroot00000000000000from __future__ import annotations import argparse import gc import json import platform import statistics import time import tracemalloc from datetime import datetime from datetime import timezone from pathlib import Path from typing import Any from benchmarks.cases import BenchmarkCase from benchmarks.cases import build_cases from openapi_schema_validator.shortcuts import clear_validate_cache from openapi_schema_validator.shortcuts import validate def _measure_compile_time_ms( case: BenchmarkCase, rounds: int, ) -> float: samples: list[float] = [] for _ in range(rounds): start_ns = time.perf_counter_ns() case.validator_class( case.schema, **case.validator_kwargs, ) elapsed_ms = (time.perf_counter_ns() - start_ns) / 1_000_000 samples.append(elapsed_ms) return statistics.median(samples) def _measure_first_validate_ms(case: BenchmarkCase) -> float: validator = case.validator_class(case.schema, **case.validator_kwargs) start_ns = time.perf_counter_ns() validator.validate(case.instance) return (time.perf_counter_ns() - start_ns) / 1_000_000 def _measure_compiled_validate_per_second( case: BenchmarkCase, iterations: int, warmup: int, ) -> float: validator = case.validator_class(case.schema, **case.validator_kwargs) for _ in range(warmup): validator.validate(case.instance) start_ns = time.perf_counter_ns() for _ in range(iterations): validator.validate(case.instance) elapsed = (time.perf_counter_ns() - start_ns) / 1_000_000_000 return iterations / elapsed def _measure_helper_validate_per_second( case: BenchmarkCase, iterations: int, warmup: int, *, check_schema: bool, ) -> float: clear_validate_cache() for _ in range(warmup): validate( case.instance, case.schema, cls=case.validator_class, check_schema=check_schema, **case.validator_kwargs, ) start_ns = time.perf_counter_ns() for _ in range(iterations): validate( case.instance, case.schema, cls=case.validator_class, check_schema=check_schema, **case.validator_kwargs, ) elapsed = (time.perf_counter_ns() - start_ns) / 1_000_000_000 return iterations / elapsed def _measure_peak_memory_kib( case: BenchmarkCase, iterations: int, ) -> float: validator = case.validator_class(case.schema, **case.validator_kwargs) tracemalloc.start() for _ in range(iterations): validator.validate(case.instance) _, peak = tracemalloc.get_traced_memory() tracemalloc.stop() return peak / 1024 def _measure_case( case: BenchmarkCase, iterations: int, warmup: int, compile_rounds: int, ) -> dict[str, Any]: gc_enabled = gc.isenabled() gc.disable() try: return { "name": case.name, "validator_class": case.validator_class.__name__, "compile_ms": _measure_compile_time_ms(case, compile_rounds), "first_validate_ms": _measure_first_validate_ms(case), "compiled_validations_per_second": ( _measure_compiled_validate_per_second( case, iterations, warmup, ) ), "helper_validations_per_second": ( _measure_helper_validate_per_second( case, iterations, warmup, check_schema=True, ) ), "helper_trusted_validations_per_second": ( _measure_helper_validate_per_second( case, iterations, warmup, check_schema=False, ) ), "compiled_peak_memory_kib": _measure_peak_memory_kib( case, max(iterations, 100), ), } finally: if gc_enabled: gc.enable() def _build_report( cases: list[BenchmarkCase], iterations: int, warmup: int, compile_rounds: int, ) -> dict[str, Any]: results = [ _measure_case( case, iterations=iterations, warmup=warmup, compile_rounds=compile_rounds, ) for case in cases ] return { "timestamp_utc": datetime.now(timezone.utc).isoformat(), "python_version": platform.python_version(), "platform": platform.platform(), "benchmark_parameters": { "iterations": iterations, "warmup": warmup, "compile_rounds": compile_rounds, }, "cases": results, } def _parse_args() -> argparse.Namespace: parser = argparse.ArgumentParser( description="Run validation performance benchmarks.", ) parser.add_argument( "--iterations", type=int, default=1000, help="Measured validation iterations per case.", ) parser.add_argument( "--warmup", type=int, default=100, help="Warmup iterations per case.", ) parser.add_argument( "--compile-rounds", type=int, default=50, help="Schema compile measurements per case.", ) parser.add_argument( "--output", type=Path, default=Path("reports/benchmarks/python-baseline.json"), help="Path to write JSON benchmark report.", ) return parser.parse_args() def main() -> int: args = _parse_args() cases = build_cases() report = _build_report( cases, iterations=args.iterations, warmup=args.warmup, compile_rounds=args.compile_rounds, ) output_path = args.output output_path.parent.mkdir(parents=True, exist_ok=True) output_path.write_text(json.dumps(report, indent=2), encoding="utf-8") print(f"Saved benchmark report to {output_path}") return 0 if __name__ == "__main__": raise SystemExit(main()) python-openapi-openapi-schema-validator-9480dee/docs/000077500000000000000000000000001517371647300227305ustar00rootroot00000000000000python-openapi-openapi-schema-validator-9480dee/docs/conf.py000066400000000000000000000040171517371647300242310ustar00rootroot00000000000000import re import sys from pathlib import Path ROOT_DIR = Path(__file__).resolve().parents[1] sys.path.insert(0, str(ROOT_DIR)) def _read_project_version() -> str: pyproject_path = ROOT_DIR / "pyproject.toml" pyproject_content = pyproject_path.read_text(encoding="utf-8") match = re.search( r"\[tool\.poetry\][\s\S]*?^version\s*=\s*\"([^\"]+)\"", pyproject_content, re.MULTILINE, ) if match is None: return "unknown" return match.group(1) project = "openapi-schema-validator" copyright = "2023, Artur Maciag" author = "Artur Maciag" release = _read_project_version() extensions = [ "sphinx.ext.autodoc", "sphinx.ext.doctest", "sphinx.ext.intersphinx", "sphinx.ext.coverage", "sphinx.ext.viewcode", "sphinx_immaterial", ] templates_path = ["_templates"] exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] html_theme = "sphinx_immaterial" html_static_path = [] html_title = "openapi-schema-validator" html_theme_options = { "analytics": { "provider": "google", "property": "G-11RDPBZ7EJ", }, "repo_url": "https://github.com/python-openapi/openapi-schema-validator/", "repo_name": "openapi-schema-validator", "icon": { "repo": "fontawesome/brands/github-alt", "edit": "material/file-edit-outline", }, "palette": [ { "media": "(prefers-color-scheme: dark)", "scheme": "slate", "primary": "lime", "accent": "amber", "scheme": "slate", "toggle": { "icon": "material/toggle-switch", "name": "Switch to light mode", }, }, { "media": "(prefers-color-scheme: light)", "scheme": "default", "primary": "lime", "accent": "amber", "toggle": { "icon": "material/toggle-switch-off-outline", "name": "Switch to dark mode", }, }, ], "globaltoc_collapse": False, } python-openapi-openapi-schema-validator-9480dee/docs/contributing.rst000066400000000000000000000060041517371647300261710ustar00rootroot00000000000000Contributing ============ Firstly, thank you all for taking the time to contribute. The following section describes how you can contribute to the openapi-schema-validator project on GitHub. Reporting bugs -------------- Before you report ^^^^^^^^^^^^^^^^^ * Check whether your issue does not already exist in the `Issue tracker `__. * Make sure it is not a support request or question better suited for `Discussion board `__. How to submit a report ^^^^^^^^^^^^^^^^^^^^^^ * Include clear title. * Describe your runtime environment with exact versions you use. * Describe the exact steps which reproduce the problem, including minimal code snippets. * Describe the behavior you observed after following the steps, pasting console outputs. * Describe expected behavior to see and why, including links to documentations. Code contribution ----------------- Prerequisites ^^^^^^^^^^^^^ Install `Poetry `__ by following the `official installation instructions `__. Optionally (but recommended), configure Poetry to create a virtual environment in a folder named ``.venv`` within the root directory of the project: .. code-block:: console poetry config virtualenvs.in-project true Setup ^^^^^ To create a development environment and install the runtime and development dependencies, run: .. code-block:: console poetry install Then enter the virtual environment created by Poetry: .. code-block:: console poetry shell Static checks ^^^^^^^^^^^^^ The project uses static checks using fantastic `pre-commit `__. Every change is checked on CI and if it does not pass the tests it cannot be accepted. If you want to check locally then run following command to install pre-commit. To turn on pre-commit checks for commit operations in git, enter: .. code-block:: console pre-commit install To run all checks on your staged files, enter: .. code-block:: console pre-commit run To run all checks on all files, enter: .. code-block:: console pre-commit run --all-files Pre-commit check results are also attached to your PR through integration with GitHub Actions. Performance benchmark ^^^^^^^^^^^^^^^^^^^^^ The ``validate`` shortcut uses an internal compiled-validator cache. You can adjust cache capacity with the ``OPENAPI_SCHEMA_VALIDATOR_COMPILED_VALIDATOR_CACHE_MAX_SIZE`` environment variable (default: ``128``). To collect a local benchmark report for validation performance, run: .. code-block:: console poetry run python benchmarks/run.py --output reports/benchmarks/current.json To compare two benchmark reports and optionally fail on regressions, run: .. code-block:: console poetry run python benchmarks/compare.py \ --baseline reports/benchmarks/baseline.json \ --candidate reports/benchmarks/current.json \ --regression-threshold 5 \ --fail-on-regression python-openapi-openapi-schema-validator-9480dee/docs/format.rst000066400000000000000000000006261517371647300247560ustar00rootroot00000000000000Format check ============ You can check format for predefined OAS primitive types .. code-block:: python from openapi_schema_validator import oas31_format_checker validate({"name": "John", "birth-date": "-12"}, schema, format_checker=oas31_format_checker) Traceback (most recent call last): ... ValidationError: '-12' is not a 'date' For OpenAPI 3.2, use ``oas32_format_checker``. python-openapi-openapi-schema-validator-9480dee/docs/index.rst000066400000000000000000000066221517371647300245770ustar00rootroot00000000000000openapi-schema-validator ======================== .. toctree:: :hidden: :maxdepth: 2 validation format references contributing Openapi-schema-validator is a Python library that validates schema against: * `OpenAPI Schema Specification v3.0 `__ which is an extended subset of the `JSON Schema Specification Wright Draft 00 `__. * `OpenAPI Schema Specification v3.1 `__ which is an extended superset of the `JSON Schema Specification Draft 2020-12 `__. * `OpenAPI Schema Specification v3.2 `__ using the published OAS 3.2 JSON Schema dialect resources. Installation ------------ .. md-tab-set:: .. md-tab-item:: Pip + PyPI (recommended) .. code-block:: console pip install openapi-schema-validator .. md-tab-item:: Pip + the source .. code-block:: console pip install -e git+https://github.com/python-openapi/openapi-schema-validator.git#egg=openapi_schema_validator Usage ----- .. code-block:: python from openapi_schema_validator import validate # A sample schema schema = { "type": "object", "required": [ "name" ], "properties": { "name": { "type": "string" }, "age": { "type": ["integer", "null"], "format": "int32", "minimum": 0, }, "birth-date": { "type": "string", "format": "date", }, "address": { "type": 'array', "prefixItems": [ { "type": "number" }, { "type": "string" }, { "enum": ["Street", "Avenue", "Boulevard"] }, { "enum": ["NW", "NE", "SW", "SE"] } ], "items": False, } }, "additionalProperties": False, } # If no exception is raised by validate(), the instance is valid. validate({"name": "John", "age": 23, "address": [1600, "Pennsylvania", "Avenue"]}, schema) validate({"name": "John", "city": "London"}, schema) Traceback (most recent call last): ... ValidationError: Additional properties are not allowed ('city' was unexpected) Read more about the :doc:`validation`. Configuration ------------- Environment variables: * ``OPENAPI_SCHEMA_VALIDATOR_COMPILED_VALIDATOR_CACHE_MAX_SIZE`` Maximum number of compiled validators kept by the ``validate`` shortcut cache. Default: ``128``. Loaded once at first use. See :doc:`validation` for runtime behavior details. Related projects ---------------- * `openapi-core `__ Python library that adds client-side and server-side support for the OpenAPI v3.0 and OpenAPI v3.1 specification. * `openapi-spec-validator `__ Python library that validates OpenAPI Specs against the OpenAPI 2.0 (aka Swagger), OpenAPI 3.0 and OpenAPI 3.1 specification. The validator aims to check for full compliance with the Specification. License ------- The project is under the terms of BSD 3-Clause License. python-openapi-openapi-schema-validator-9480dee/docs/make.bat000066400000000000000000000014331517371647300243360ustar00rootroot00000000000000@ECHO OFF pushd %~dp0 REM Command file for Sphinx documentation if "%SPHINXBUILD%" == "" ( set SPHINXBUILD=sphinx-build ) set SOURCEDIR=. set BUILDDIR=_build if "%1" == "" goto help %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.http://sphinx-doc.org/ exit /b 1 ) %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% goto end :help %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% :end popd python-openapi-openapi-schema-validator-9480dee/docs/references.rst000066400000000000000000000043021517371647300256020ustar00rootroot00000000000000References ========== You can resolve JSON Schema references by passing registry. The ``validate(instance, schema, ...)`` shortcut resolves local references (``#/...``) against the provided ``schema`` mapping. By default, the shortcut uses a local-only empty registry and does not implicitly retrieve remote references. If needed, ``allow_remote_references=True`` enables jsonschema's default remote retrieval behavior. .. code-block:: python from openapi_schema_validator import validate from referencing import Registry, Resource from referencing.jsonschema import DRAFT202012 # A schema with reference schema = { "type" : "object", "required": [ "name" ], "properties": { "name": { "$ref": "urn:name-schema" }, "age": { "$ref": "urn:age-schema" }, "birth-date": { "$ref": "urn:birth-date-schema" } }, "additionalProperties": False, } # Referenced schemas # In-schema identifier name_schema = Resource.from_contents({ "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "string", }) # Explicit identifier age_schema = DRAFT202012.create_resource({ "type": "integer", "format": "int32", "minimum": 0, "maximum": 120, }) # Default identifier birth_date_schema = Resource.from_contents({ "type": "string", "format": "date", }, default_specification=DRAFT202012) registry = Registry().with_resources( [ ("urn:name-schema", name_schema), ("urn:age-schema", age_schema), ("urn:birth-date-schema", birth_date_schema), ], ) # If no exception is raised by validate(), the instance is valid. validate({"name": "John", "age": 23}, schema, registry=registry) # raises error validate({"birth-date": "yesterday", "age": -1}, schema, registry=registry) Traceback (most recent call last): ... ValidationError: 'name' is a required property For more information about resolving references see `JSON (Schema) Referencing `__ python-openapi-openapi-schema-validator-9480dee/docs/validation.rst000066400000000000000000000250201517371647300256130ustar00rootroot00000000000000Schema validation ================= The simplest way to validate an instance under OAS schema is to use the ``validate`` function. Validate -------- ``validate`` call signature is: .. code-block:: python validate( instance, schema, cls=OAS32Validator, allow_remote_references=False, check_schema=True, enforce_properties_required=False, **kwargs, ) The first argument is always the value you want to validate. The second argument is always the OpenAPI schema object. The ``cls`` keyword argument is optional and defaults to ``OAS32Validator``. Use ``cls`` when you need a specific validator version/behavior. The ``allow_remote_references`` keyword argument is optional and defaults to ``False``. The ``check_schema`` keyword argument is optional and defaults to ``True``. Common forwarded keyword arguments include: - ``registry`` for explicit external reference resolution context - ``format_checker`` to control format validation behavior By default, ``validate`` uses a local-only empty registry to avoid implicit remote ``$ref`` retrieval. Set ``allow_remote_references=True`` only if you explicitly accept jsonschema's default remote retrieval behavior. For trusted pre-validated schemas in hot paths, set ``check_schema=False`` to skip schema checking. When ``enforce_properties_required=True`` is passed, all properties declared in the schema's ``properties`` object are strictly required to be present in the instance (except those marked as ``writeOnly`` or ``readOnly`` where appropriate), regardless of the schema's ``required`` array. This is useful for response or contract testing to ensure no documented fields are missing. The shortcut keeps an internal compiled-validator cache. Use ``OPENAPI_SCHEMA_VALIDATOR_COMPILED_VALIDATOR_CACHE_MAX_SIZE`` to control cache capacity (default: ``128``). The setting is read once at first use and then cached for the process lifetime. To validate an OpenAPI schema: .. code-block:: python from openapi_schema_validator import validate # A sample schema schema = { "type": "object", "required": [ "name" ], "properties": { "name": { "type": "string" }, "age": { "type": ["integer", "null"], "format": "int32", "minimum": 0, }, "birth-date": { "type": "string", "format": "date", }, "address": { "type": 'array', "prefixItems": [ { "type": "number" }, { "type": "string" }, { "enum": ["Street", "Avenue", "Boulevard"] }, { "enum": ["NW", "NE", "SW", "SE"] } ], "items": False, } }, "additionalProperties": False, } # If no exception is raised by validate(), the instance is valid. validate({"name": "John", "age": 23, "address": [1600, "Pennsylvania", "Avenue"]}, schema) validate({"name": "John", "city": "London"}, schema) Traceback (most recent call last): ... ValidationError: Additional properties are not allowed ('city' was unexpected) By default, the latest OpenAPI schema syntax is expected. Common pitfalls --------------- - argument order matters: call ``validate(instance, schema)``, not ``validate(schema, instance)`` - ``validate`` does not load files from a path; load your OpenAPI document first and pass the parsed schema mapping - ``validate`` treats the provided ``schema`` as the reference root; local references like ``#/components/...`` must exist within that mapping - when a schema uses external references (for example ``urn:...``), provide reference context via ``registry=...`` as shown in :doc:`references` - for schema fragments containing local references (for example, ``paths/.../responses/.../schema``), use a validator built from the full schema root and then validate the fragment via ``validator.evolve(...)`` Validators ---------- if you want to disambiguate the expected schema version, import and use ``OAS31Validator``: .. code-block:: python from openapi_schema_validator import OAS31Validator validate({"name": "John", "age": 23}, schema, cls=OAS31Validator) For OpenAPI 3.2, use ``OAS32Validator``. In order to validate OpenAPI 3.0 schema, import and use ``OAS30Validator`` instead of ``OAS31Validator``. .. code-block:: python from openapi_schema_validator import OAS30Validator # A sample schema schema = { "type": "object", "required": [ "name" ], "properties": { "name": { "type": "string" }, "age": { "type": "integer", "format": "int32", "minimum": 0, "nullable": True, }, "birth-date": { "type": "string", "format": "date", } }, "additionalProperties": False, } validate({"name": "John", "age": None}, schema, cls=OAS30Validator) Default dialect resolution -------------------------- The OpenAPI 3.1 and 3.2 base dialect URIs are registered for ``jsonschema.validators.validator_for`` resolution. If your schema declares ``"$schema": "https://spec.openapis.org/oas/3.1/dialect/base"`` or ``"$schema": "https://spec.openapis.org/oas/3.2/dialect/2025-09-17"``, ``validator_for`` resolves directly to ``OAS31Validator`` or ``OAS32Validator`` without unresolved-metaschema fallback warnings. .. code-block:: python from jsonschema.validators import validator_for from openapi_schema_validator import OAS31Validator from openapi_schema_validator import OAS32Validator schema = { "$schema": "https://spec.openapis.org/oas/3.1/dialect/base", "type": "object", } schema32 = { "$schema": "https://spec.openapis.org/oas/3.2/dialect/2025-09-17", "type": "object", } assert validator_for(schema) is OAS31Validator assert validator_for(schema32) is OAS32Validator Schema errors vs instance errors -------------------------------- The high-level ``validate(...)`` helper checks schema validity before instance validation by default (``check_schema=True``), following ``jsonschema.validate(...)`` behavior. Malformed schema values (for example an invalid regex in ``pattern``) raise ``SchemaError``. When ``check_schema=False``, schema checking is skipped and malformed schemas may instead fail during validation with lower-level errors. If you instantiate a validator class directly and call ``.validate(...)``, schema checking is not performed automatically, matching ``jsonschema`` validator-class behavior. For malformed regex patterns this may raise a lower-level regex error (default mode) or ``ValidationError`` from the validator (ECMAScript mode). Use ``.check_schema(schema)`` first when you need deterministic schema-validation errors with direct validator usage. Read/write context ------------------ OpenAPI 3.0 schema comes with ``readOnly`` and ``writeOnly`` keywords. In order to validate read/write context in OpenAPI 3.0 schema, import and use ``OAS30ReadValidator`` or ``OAS30WriteValidator``. .. code-block:: python from openapi_schema_validator import OAS30WriteValidator # A sample schema schema = { "type": "object", "required": [ "name" ], "properties": { "name": { "type": "string" }, "age": { "type": "integer", "format": "int32", "minimum": 0, "readOnly": True, }, "birth-date": { "type": "string", "format": "date", } }, "additionalProperties": False, } validate({"name": "John", "age": 23}, schema, cls=OAS30WriteValidator) Traceback (most recent call last): ... ValidationError: Tried to write read-only property with 23 Binary Data Semantics --------------------- The handling of binary-like payloads differs between OpenAPI versions. OpenAPI 3.0 ~~~~~~~~~~~ OpenAPI 3.0 keeps historical ``format: binary`` / ``format: byte`` usage on ``type: string``. **OAS30Validator (default - compatibility behavior)** - ``type: string`` accepts ``str`` - ``type: string, format: binary`` accepts Python ``bytes`` and strings - useful when validating Python-native runtime data **OAS30StrictValidator** - ``type: string`` accepts ``str`` only - ``type: string, format: binary`` uses strict format validation - use when you want strict, spec-oriented behavior for 3.0 schemas OpenAPI 3.1+ ~~~~~~~~~~~~ OpenAPI 3.1+ follows JSON Schema semantics for string typing in this library. - ``type: string`` accepts ``str`` only (not ``bytes``) - ``format: binary`` and ``format: byte`` are not treated as built-in formats - for base64-in-JSON, model with ``contentEncoding: base64`` (optionally ``contentMediaType``) - for raw binary payloads, model via media type (for example ``application/octet-stream``) rather than schema string formats Quick Reference ~~~~~~~~~~~~~~~ .. list-table:: :header-rows: 1 :widths: 28 24 24 24 * - Context - ``"text"`` (str) - ``b"text"`` (bytes) - Notes * - OAS 3.0 + ``OAS30Validator`` - Pass - Pass for ``format: binary`` - Compatibility behavior for Python runtime payloads * - OAS 3.0 + ``OAS30StrictValidator`` - Pass - Fail - Strict 3.0 validation mode * - OAS 3.1 + ``OAS31Validator`` - Pass - Fail - Use ``contentEncoding``/``contentMediaType`` and media types * - OAS 3.2 + ``OAS32Validator`` - Pass - Fail - Same semantics as OAS 3.1 Regex Behavior -------------- Pattern validation follows one of two modes: - default installation: follows host Python regex behavior - ``ecma-regex`` extra installed: uses ``regress`` for ECMAScript-oriented regex validation and matching Install optional ECMAScript regex support with: .. code-block:: console pip install "openapi-schema-validator[ecma-regex]" Example usage: .. code-block:: python from openapi_schema_validator import OAS30StrictValidator from openapi_schema_validator import OAS30Validator # Pragmatic (default) - accepts bytes for binary format validator = OAS30Validator({"type": "string", "format": "binary"}) validator.validate(b"binary data") # passes # Strict - follows spec precisely validator = OAS30StrictValidator({"type": "string", "format": "binary"}) validator.validate(b"binary data") # raises ValidationError python-openapi-openapi-schema-validator-9480dee/openapi_schema_validator/000077500000000000000000000000001517371647300270205ustar00rootroot00000000000000python-openapi-openapi-schema-validator-9480dee/openapi_schema_validator/__init__.py000066400000000000000000000026011517371647300311300ustar00rootroot00000000000000from openapi_schema_validator._dialects import OAS31_BASE_DIALECT_ID from openapi_schema_validator._dialects import OAS32_BASE_DIALECT_ID from openapi_schema_validator._format import oas30_format_checker from openapi_schema_validator._format import oas30_strict_format_checker from openapi_schema_validator._format import oas31_format_checker from openapi_schema_validator._format import oas32_format_checker from openapi_schema_validator.shortcuts import validate from openapi_schema_validator.validators import OAS30ReadValidator from openapi_schema_validator.validators import OAS30StrictValidator from openapi_schema_validator.validators import OAS30Validator from openapi_schema_validator.validators import OAS30WriteValidator from openapi_schema_validator.validators import OAS31Validator from openapi_schema_validator.validators import OAS32Validator __author__ = "Artur Maciag" __email__ = "maciag.artur@gmail.com" __version__ = "0.9.0" __url__ = "https://github.com/python-openapi/openapi-schema-validator" __license__ = "3-clause BSD License" __all__ = [ "validate", "OAS30ReadValidator", "OAS30StrictValidator", "OAS30WriteValidator", "OAS30Validator", "oas30_format_checker", "oas30_strict_format_checker", "OAS31Validator", "oas31_format_checker", "OAS32Validator", "oas32_format_checker", "OAS31_BASE_DIALECT_ID", "OAS32_BASE_DIALECT_ID", ] python-openapi-openapi-schema-validator-9480dee/openapi_schema_validator/_caches.py000066400000000000000000000061271517371647300307650ustar00rootroot00000000000000from collections import OrderedDict from dataclasses import dataclass from threading import RLock from typing import Any from typing import Hashable from typing import Mapping from jsonschema.protocols import Validator from openapi_schema_validator.settings import get_settings @dataclass class CachedValidator: validator: Any schema_checked: bool class ValidatorCache: def __init__(self) -> None: self._cache: OrderedDict[Hashable, CachedValidator] = OrderedDict() self._lock = RLock() def _freeze_value(self, value: Any) -> Hashable: if isinstance(value, dict): return tuple( sorted( (str(key), self._freeze_value(item)) for key, item in value.items() ) ) if isinstance(value, list): return tuple(self._freeze_value(item) for item in value) if isinstance(value, tuple): return tuple(self._freeze_value(item) for item in value) if isinstance(value, set): return tuple( sorted( (self._freeze_value(item) for item in value), key=repr, ) ) if isinstance(value, (str, bytes, int, float, bool, type(None))): return value return ("id", id(value)) def _schema_fingerprint(self, schema: Mapping[str, Any]) -> Hashable: return self._freeze_value(dict(schema)) def build_key( self, schema: Mapping[str, Any], cls: type[Validator], args: tuple[Any, ...], kwargs: Mapping[str, Any], allow_remote_references: bool, ) -> Hashable: return ( cls, allow_remote_references, self._schema_fingerprint(schema), self._freeze_value(args), self._freeze_value(dict(kwargs)), ) def get(self, key: Hashable) -> CachedValidator | None: with self._lock: return self._cache.get(key) def set( self, key: Hashable, *, validator: Any, schema_checked: bool, ) -> CachedValidator: cached = CachedValidator( validator=validator, schema_checked=schema_checked, ) with self._lock: self._cache[key] = cached self._cache.move_to_end(key) self._prune_if_needed() return cached def mark_schema_checked(self, key: Hashable) -> None: with self._lock: cached = self._cache.get(key) if cached is None: return cached.schema_checked = True self._cache.move_to_end(key) def touch(self, key: Hashable) -> None: with self._lock: if key in self._cache: self._cache.move_to_end(key) def clear(self) -> None: with self._lock: self._cache.clear() def _prune_if_needed(self) -> None: max_size = get_settings().compiled_validator_cache_max_size while len(self._cache) > max_size: self._cache.popitem(last=False) python-openapi-openapi-schema-validator-9480dee/openapi_schema_validator/_dialects.py000066400000000000000000000023721517371647300313250ustar00rootroot00000000000000from typing import Any from jsonschema.validators import validates from openapi_schema_validator._specifications import ( REGISTRY as OPENAPI_SPECIFICATIONS, ) __all__ = [ "OAS31_BASE_DIALECT_ID", "OAS31_BASE_DIALECT_METASCHEMA", "OAS32_BASE_DIALECT_ID", "OAS32_BASE_DIALECT_METASCHEMA", "register_openapi_dialect", ] OAS31_BASE_DIALECT_ID = "https://spec.openapis.org/oas/3.1/dialect/base" OAS31_BASE_DIALECT_METASCHEMA = OPENAPI_SPECIFICATIONS.contents( OAS31_BASE_DIALECT_ID, ) OAS32_BASE_DIALECT_ID = "https://spec.openapis.org/oas/3.2/dialect/2025-09-17" OAS32_BASE_DIALECT_METASCHEMA = OPENAPI_SPECIFICATIONS.contents( OAS32_BASE_DIALECT_ID, ) _REGISTERED_VALIDATORS: dict[tuple[str, str], Any] = {} def register_openapi_dialect( *, validator: Any, dialect_id: str, version_name: str, metaschema: Any, ) -> Any: key = (dialect_id, version_name) registered_validator = _REGISTERED_VALIDATORS.get(key) if registered_validator is validator: return validator if registered_validator is not None: return registered_validator validator.META_SCHEMA = metaschema validator = validates(version_name)(validator) _REGISTERED_VALIDATORS[key] = validator return validator python-openapi-openapi-schema-validator-9480dee/openapi_schema_validator/_format.py000066400000000000000000000100011517371647300310110ustar00rootroot00000000000000import binascii from base64 import b64decode from base64 import b64encode from numbers import Number from jsonschema._format import FormatChecker from openapi_schema_validator._regex import is_valid_regex def is_int32(instance: object) -> bool: # bool inherits from int, so ensure bools aren't reported as ints if isinstance(instance, bool): return True if not isinstance(instance, int): return True return ~(1 << 31) < instance < 1 << 31 def is_int64(instance: object) -> bool: # bool inherits from int, so ensure bools aren't reported as ints if isinstance(instance, bool): return True if not isinstance(instance, int): return True return ~(1 << 63) < instance < 1 << 63 def is_float(instance: object) -> bool: # bool inherits from int if isinstance(instance, int): return True if not isinstance(instance, Number): return True return isinstance(instance, float) def is_double(instance: object) -> bool: # bool inherits from int if isinstance(instance, int): return True if not isinstance(instance, Number): return True # float has double precision in Python # It's double in CPython and Jython return isinstance(instance, float) def is_binary_strict(instance: object) -> bool: # Strict: only accepts base64-encoded strings, not raw bytes if isinstance(instance, bytes): return False if isinstance(instance, str): try: b64decode(instance) return True except Exception: return False return True def is_binary_pragmatic(instance: object) -> bool: # Pragmatic: accepts bytes (common in Python) or base64-encoded strings if isinstance(instance, (str, bytes)): return True return True def is_byte(instance: object) -> bool: if not isinstance(instance, (str, bytes)): return True if isinstance(instance, str): instance = instance.encode("ascii", errors="strict") try: b64decode(instance, validate=True) except (binascii.Error, ValueError): return False return True def is_password(instance: object) -> bool: # A hint to UIs to obscure input return True def is_regex(instance: object) -> bool: if not isinstance(instance, str): return True return is_valid_regex(instance) oas30_format_checker = FormatChecker() oas30_format_checker.checks("int32")(is_int32) oas30_format_checker.checks("int64")(is_int64) oas30_format_checker.checks("float")(is_float) oas30_format_checker.checks("double")(is_double) oas30_format_checker.checks("binary")(is_binary_pragmatic) oas30_format_checker.checks("byte", (binascii.Error, TypeError))(is_byte) oas30_format_checker.checks("password")(is_password) oas30_format_checker.checks("regex")(is_regex) oas30_strict_format_checker = FormatChecker() oas30_strict_format_checker.checks("int32")(is_int32) oas30_strict_format_checker.checks("int64")(is_int64) oas30_strict_format_checker.checks("float")(is_float) oas30_strict_format_checker.checks("double")(is_double) oas30_strict_format_checker.checks("binary")(is_binary_strict) oas30_strict_format_checker.checks("byte", (binascii.Error, TypeError))( is_byte ) oas30_strict_format_checker.checks("password")(is_password) oas30_strict_format_checker.checks("regex")(is_regex) oas31_format_checker = FormatChecker() oas31_format_checker.checks("int32")(is_int32) oas31_format_checker.checks("int64")(is_int64) oas31_format_checker.checks("float")(is_float) oas31_format_checker.checks("double")(is_double) oas31_format_checker.checks("password")(is_password) oas31_format_checker.checks("regex")(is_regex) # OAS 3.2 uses the same format checks as OAS 3.1 oas32_format_checker = FormatChecker() oas32_format_checker.checks("int32")(is_int32) oas32_format_checker.checks("int64")(is_int64) oas32_format_checker.checks("float")(is_float) oas32_format_checker.checks("double")(is_double) oas32_format_checker.checks("password")(is_password) oas32_format_checker.checks("regex")(is_regex) python-openapi-openapi-schema-validator-9480dee/openapi_schema_validator/_keywords.py000066400000000000000000000232451517371647300314060ustar00rootroot00000000000000from typing import Any from typing import Iterator from typing import Mapping from typing import cast from jsonschema._keywords import allOf as _allOf from jsonschema._keywords import anyOf as _anyOf from jsonschema._keywords import oneOf as _oneOf from jsonschema._keywords import pattern as _pattern from jsonschema._utils import extras_msg from jsonschema._utils import find_additional_properties from jsonschema.exceptions import FormatError from jsonschema.exceptions import ValidationError from jsonschema.exceptions import _WrappedReferencingError from openapi_schema_validator._regex import ECMARegexSyntaxError from openapi_schema_validator._regex import has_ecma_regex from openapi_schema_validator._regex import search as regex_search def handle_discriminator( validator: Any, _: Any, instance: Any, schema: Mapping[str, Any] ) -> Iterator[ValidationError]: """ Handle presence of discriminator in anyOf, oneOf and allOf. The behaviour is the same in all 3 cases because at most 1 schema will match. """ discriminator = schema["discriminator"] prop_name = discriminator["propertyName"] if not validator.is_type(instance, "object"): yield ValidationError( f"{instance!r} is not of type 'object'", context=[] ) return prop_value = instance.get(prop_name) if not prop_value: # instance is missing $propertyName yield ValidationError( f"{instance!r} does not contain discriminating property {prop_name!r}", context=[], ) return # Use explicit mapping if available, otherwise try implicit value ref = ( discriminator.get("mapping", {}).get(prop_value) or f"#/components/schemas/{prop_value}" ) if not isinstance(ref, str): # this is a schema error yield ValidationError( f"{instance!r} mapped value for {prop_value!r} should be a string, was {ref!r}", context=[], ) return try: validator._validate_reference(ref=ref, instance=instance) except _WrappedReferencingError: yield ValidationError( f"{instance!r} reference {ref!r} could not be resolved", context=[], ) return yield from validator.descend(instance, {"$ref": ref}) def anyOf( validator: Any, anyOf: list[Mapping[str, Any]], instance: Any, schema: Mapping[str, Any], ) -> Iterator[ValidationError]: if "discriminator" not in schema: yield from cast( Iterator[ValidationError], _anyOf(validator, anyOf, instance, schema), ) else: yield from handle_discriminator(validator, anyOf, instance, schema) def oneOf( validator: Any, oneOf: list[Mapping[str, Any]], instance: Any, schema: Mapping[str, Any], ) -> Iterator[ValidationError]: if "discriminator" not in schema: yield from cast( Iterator[ValidationError], _oneOf(validator, oneOf, instance, schema), ) else: yield from handle_discriminator(validator, oneOf, instance, schema) def allOf( validator: Any, allOf: list[Mapping[str, Any]], instance: Any, schema: Mapping[str, Any], ) -> Iterator[ValidationError]: if "discriminator" not in schema: yield from cast( Iterator[ValidationError], _allOf(validator, allOf, instance, schema), ) else: yield from handle_discriminator(validator, allOf, instance, schema) def type( validator: Any, data_type: str, instance: Any, schema: Mapping[str, Any], ) -> Iterator[ValidationError]: """Default type validator - allows Python bytes for binary format for pragmatic reasons.""" if instance is None: # nullable implementation based on OAS 3.0.3 # * nullable is only meaningful if its value is true # * nullable: true is only meaningful in combination with a type # assertion specified in the same Schema Object. # * nullable: true operates within a single Schema Object if schema.get("nullable") is True: return yield ValidationError("None for not nullable") # Pragmatic: allow bytes for binary format (common in Python use cases) if ( data_type == "string" and schema.get("format") == "binary" and isinstance(instance, bytes) ): return if not validator.is_type(instance, data_type): data_repr = repr(data_type) yield ValidationError(f"{instance!r} is not of type {data_repr}") def strict_type( validator: Any, data_type: str, instance: Any, schema: Any, ) -> Any: """ Strict type validator - follows OAS spec precisely. Does NOT allow Python bytes for binary format. """ if instance is None: if schema.get("nullable") is True: return yield ValidationError("None for not nullable") if not validator.is_type(instance, data_type): data_repr = repr(data_type) yield ValidationError(f"{instance!r} is not of type {data_repr}") def pattern( validator: Any, patrn: str, instance: Any, schema: Mapping[str, Any], ) -> Iterator[ValidationError]: if not has_ecma_regex(): yield from cast( Iterator[ValidationError], _pattern(validator, patrn, instance, schema), ) return if not validator.is_type(instance, "string"): return try: matches = regex_search(patrn, instance) except ECMARegexSyntaxError as exc: yield ValidationError( f"{patrn!r} is not a valid regular expression ({exc})" ) return if not matches: yield ValidationError(f"{instance!r} does not match {patrn!r}") def format( validator: Any, format: str, instance: Any, schema: Mapping[str, Any], ) -> Iterator[ValidationError]: if instance is None: return if validator.format_checker is not None: try: validator.format_checker.check(instance, format) except FormatError as error: yield ValidationError(str(error), cause=error.cause) def items( validator: Any, items: Mapping[str, Any], instance: Any, schema: Mapping[str, Any], ) -> Iterator[ValidationError]: if not validator.is_type(instance, "array"): return for index, item in enumerate(instance): yield from validator.descend(item, items, path=index) def required( validator: Any, required: list[str], instance: Any, schema: Mapping[str, Any], ) -> Iterator[ValidationError]: if not validator.is_type(instance, "object"): return for property in required: if property not in instance: prop_schema = schema.get("properties", {}).get(property) if prop_schema: read_only = prop_schema.get("readOnly", False) write_only = prop_schema.get("writeOnly", False) if ( getattr(validator, "write", True) and read_only or getattr(validator, "read", True) and write_only ): continue yield ValidationError(f"{property!r} is a required property") def read_required( validator: Any, required: list[str], instance: Any, schema: Mapping[str, Any], ) -> Iterator[ValidationError]: if not validator.is_type(instance, "object"): return for property in required: if property not in instance: prop_schema = schema.get("properties", {}).get(property) if prop_schema: write_only = prop_schema.get("writeOnly", False) if getattr(validator, "read", True) and write_only: continue yield ValidationError(f"{property!r} is a required property") def write_required( validator: Any, required: list[str], instance: Any, schema: Mapping[str, Any], ) -> Iterator[ValidationError]: if not validator.is_type(instance, "object"): return for property in required: if property not in instance: prop_schema = schema.get("properties", {}).get(property) if prop_schema: read_only = prop_schema.get("readOnly", False) if read_only: continue yield ValidationError(f"{property!r} is a required property") def additionalProperties( validator: Any, aP: Any, instance: Any, schema: Mapping[str, Any], ) -> Iterator[ValidationError]: if not validator.is_type(instance, "object"): return extras = set(find_additional_properties(instance, schema)) if not extras: return if validator.is_type(aP, "object"): for extra in extras: for error in validator.descend(instance[extra], aP, path=extra): yield error elif validator.is_type(aP, "boolean"): if not aP: error = "Additional properties are not allowed (%s %s unexpected)" yield ValidationError(error % extras_msg(extras)) def write_readOnly( validator: Any, ro: bool, instance: Any, schema: Mapping[str, Any], ) -> Iterator[ValidationError]: if not ro: return yield ValidationError(f"Tried to write read-only property with {instance}") def read_writeOnly( validator: Any, wo: bool, instance: Any, schema: Mapping[str, Any], ) -> Iterator[ValidationError]: if not wo: return yield ValidationError(f"Tried to read write-only property with {instance}") def not_implemented( validator: Any, value: Any, instance: Any, schema: Mapping[str, Any], ) -> Iterator[ValidationError]: yield from () python-openapi-openapi-schema-validator-9480dee/openapi_schema_validator/_regex.py000066400000000000000000000017361517371647300306520ustar00rootroot00000000000000import re from typing import Any _REGEX_CLASS: Any = None _REGRESS_ERROR: type[Exception] = Exception try: from regress import Regex as _REGEX_CLASS from regress import RegressError as _REGRESS_ERROR except ImportError: # pragma: no cover - optional dependency pass class ECMARegexSyntaxError(ValueError): pass def has_ecma_regex() -> bool: return _REGEX_CLASS is not None def is_valid_regex(pattern: str) -> bool: if _REGEX_CLASS is None: try: re.compile(pattern) except re.error: return False return True try: _REGEX_CLASS(pattern) except _REGRESS_ERROR: return False return True def search(pattern: str, instance: str) -> bool: if _REGEX_CLASS is None: return re.search(pattern, instance) is not None try: return _REGEX_CLASS(pattern).find(instance) is not None except _REGRESS_ERROR as exc: raise ECMARegexSyntaxError(str(exc)) from exc python-openapi-openapi-schema-validator-9480dee/openapi_schema_validator/_specifications.py000066400000000000000000000017301517371647300325350ustar00rootroot00000000000000import json from importlib.resources import files from typing import Any from typing import Iterator from jsonschema_specifications import REGISTRY as JSONSCHEMA_REGISTRY from referencing import Resource __all__ = ["REGISTRY"] def _iter_schema_files() -> Iterator[Any]: schema_root = files(__package__).joinpath("schemas") stack = [schema_root] while stack: current = stack.pop() for child in current.iterdir(): if child.name.startswith("."): continue if child.is_dir(): stack.append(child) continue yield child def _load_schemas() -> Iterator[Resource]: for path in _iter_schema_files(): contents = json.loads(path.read_text(encoding="utf-8")) yield Resource.from_contents(contents) #: A `referencing.Registry` containing all official jsonschema resources #: plus openapi resources. REGISTRY = (_load_schemas() @ JSONSCHEMA_REGISTRY).crawl() python-openapi-openapi-schema-validator-9480dee/openapi_schema_validator/_types.py000066400000000000000000000015071517371647300307000ustar00rootroot00000000000000from typing import Any from typing import cast from jsonschema._types import TypeChecker from jsonschema._types import draft202012_type_checker from jsonschema._types import is_array from jsonschema._types import is_bool from jsonschema._types import is_integer from jsonschema._types import is_number from jsonschema._types import is_object def is_string(checker: Any, instance: Any) -> bool: # Both strict and pragmatic: only accepts str for plain string type return isinstance(instance, str) oas30_type_checker = TypeChecker( cast( Any, { "string": is_string, "number": is_number, "integer": is_integer, "boolean": is_bool, "array": is_array, "object": is_object, }, ), ) oas31_type_checker = draft202012_type_checker python-openapi-openapi-schema-validator-9480dee/openapi_schema_validator/py.typed000066400000000000000000000000001517371647300305050ustar00rootroot00000000000000python-openapi-openapi-schema-validator-9480dee/openapi_schema_validator/schemas/000077500000000000000000000000001517371647300304435ustar00rootroot00000000000000python-openapi-openapi-schema-validator-9480dee/openapi_schema_validator/schemas/oas3.1/000077500000000000000000000000001517371647300314475ustar00rootroot00000000000000metaschema.json000066400000000000000000000020311517371647300343660ustar00rootroot00000000000000python-openapi-openapi-schema-validator-9480dee/openapi_schema_validator/schemas/oas3.1{ "$id": "https://spec.openapis.org/oas/3.1/dialect/base", "$schema": "https://json-schema.org/draft/2020-12/schema", "title": "OpenAPI 3.1 Schema Object Dialect", "description": "A JSON Schema dialect describing schemas found in OpenAPI documents", "$vocabulary": { "https://json-schema.org/draft/2020-12/vocab/core": true, "https://json-schema.org/draft/2020-12/vocab/applicator": true, "https://json-schema.org/draft/2020-12/vocab/unevaluated": true, "https://json-schema.org/draft/2020-12/vocab/validation": true, "https://json-schema.org/draft/2020-12/vocab/meta-data": true, "https://json-schema.org/draft/2020-12/vocab/format-annotation": true, "https://json-schema.org/draft/2020-12/vocab/content": true, "https://spec.openapis.org/oas/3.1/vocab/base": false }, "$dynamicAnchor": "meta", "allOf": [ { "$ref": "https://json-schema.org/draft/2020-12/schema" }, { "$ref": "https://spec.openapis.org/oas/3.1/meta/base" } ] } vocabularies/000077500000000000000000000000001517371647300340475ustar00rootroot00000000000000python-openapi-openapi-schema-validator-9480dee/openapi_schema_validator/schemas/oas3.1base000066400000000000000000000045011517371647300347040ustar00rootroot00000000000000python-openapi-openapi-schema-validator-9480dee/openapi_schema_validator/schemas/oas3.1/vocabularies{ "$id": "https://spec.openapis.org/oas/3.1/meta/base", "$schema": "https://json-schema.org/draft/2020-12/schema", "title": "OAS Base vocabulary", "description": "A JSON Schema Vocabulary used in the OpenAPI Schema Dialect", "$vocabulary": { "https://spec.openapis.org/oas/3.1/vocab/base": true }, "$dynamicAnchor": "meta", "type": ["object", "boolean"], "properties": { "example": true, "discriminator": { "$ref": "#/$defs/discriminator" }, "externalDocs": { "$ref": "#/$defs/external-docs" }, "xml": { "$ref": "#/$defs/xml" } }, "$defs": { "extensible": { "patternProperties": { "^x-": true } }, "discriminator": { "$ref": "#/$defs/extensible", "type": "object", "properties": { "propertyName": { "type": "string" }, "mapping": { "type": "object", "additionalProperties": { "type": "string" } } }, "required": ["propertyName"], "unevaluatedProperties": false }, "external-docs": { "$ref": "#/$defs/extensible", "type": "object", "properties": { "url": { "type": "string", "format": "uri-reference" }, "description": { "type": "string" } }, "required": ["url"], "unevaluatedProperties": false }, "xml": { "$ref": "#/$defs/extensible", "type": "object", "properties": { "name": { "type": "string" }, "namespace": { "type": "string", "format": "uri" }, "prefix": { "type": "string" }, "attribute": { "type": "boolean" }, "wrapped": { "type": "boolean" } }, "unevaluatedProperties": false } } } python-openapi-openapi-schema-validator-9480dee/openapi_schema_validator/schemas/oas3.2/000077500000000000000000000000001517371647300314505ustar00rootroot00000000000000python-openapi-openapi-schema-validator-9480dee/openapi_schema_validator/schemas/oas3.2/dialect/000077500000000000000000000000001517371647300330555ustar00rootroot000000000000002025-09-17.json000066400000000000000000000021231517371647300347320ustar00rootroot00000000000000python-openapi-openapi-schema-validator-9480dee/openapi_schema_validator/schemas/oas3.2/dialect{ "$id": "https://spec.openapis.org/oas/3.2/dialect/2025-09-17", "$schema": "https://json-schema.org/draft/2020-12/schema", "title": "OpenAPI 3.2 Schema Object Dialect", "description": "A JSON Schema dialect describing schemas found in OpenAPI v3.2.x Descriptions", "$dynamicAnchor": "meta", "$vocabulary": { "https://json-schema.org/draft/2020-12/vocab/applicator": true, "https://json-schema.org/draft/2020-12/vocab/content": true, "https://json-schema.org/draft/2020-12/vocab/core": true, "https://json-schema.org/draft/2020-12/vocab/format-annotation": true, "https://json-schema.org/draft/2020-12/vocab/meta-data": true, "https://json-schema.org/draft/2020-12/vocab/unevaluated": true, "https://json-schema.org/draft/2020-12/vocab/validation": true, "https://spec.openapis.org/oas/3.2/vocab/base": false }, "allOf": [ { "$ref": "https://json-schema.org/draft/2020-12/schema" }, { "$ref": "https://spec.openapis.org/oas/3.2/meta/2025-09-17" } ] } python-openapi-openapi-schema-validator-9480dee/openapi_schema_validator/schemas/oas3.2/meta/000077500000000000000000000000001517371647300323765ustar00rootroot000000000000002025-09-17.json000066400000000000000000000061771517371647300342700ustar00rootroot00000000000000python-openapi-openapi-schema-validator-9480dee/openapi_schema_validator/schemas/oas3.2/meta{ "$id": "https://spec.openapis.org/oas/3.2/meta/2025-09-17", "$schema": "https://json-schema.org/draft/2020-12/schema", "title": "OAS Base Vocabulary", "description": "A JSON Schema Vocabulary used in the OpenAPI JSON Schema Dialect", "$dynamicAnchor": "meta", "$vocabulary": { "https://spec.openapis.org/oas/3.2/vocab/base": true }, "type": [ "object", "boolean" ], "properties": { "discriminator": { "$ref": "#/$defs/discriminator" }, "example": { "deprecated": true }, "externalDocs": { "$ref": "#/$defs/external-docs" }, "xml": { "$ref": "#/$defs/xml" } }, "$defs": { "discriminator": { "$ref": "#/$defs/extensible", "properties": { "mapping": { "additionalProperties": { "type": "string" }, "type": "object" }, "defaultMapping": { "type": "string" }, "propertyName": { "type": "string" } }, "type": "object", "unevaluatedProperties": false }, "extensible": { "patternProperties": { "^x-": true } }, "external-docs": { "$ref": "#/$defs/extensible", "properties": { "description": { "type": "string" }, "url": { "format": "uri-reference", "type": "string" } }, "required": [ "url" ], "type": "object", "unevaluatedProperties": false }, "xml": { "$ref": "#/$defs/extensible", "properties": { "nodeType": { "type": "string", "enum": [ "element", "attribute", "text", "cdata", "none" ] }, "name": { "type": "string" }, "namespace": { "format": "iri", "type": "string" }, "prefix": { "type": "string" }, "attribute": { "type": "boolean", "deprecated": true }, "wrapped": { "type": "boolean", "deprecated": true } }, "type": "object", "dependentSchemas": { "nodeType": { "properties": { "attribute": false, "wrapped": false } } }, "unevaluatedProperties": false } } } python-openapi-openapi-schema-validator-9480dee/openapi_schema_validator/settings.py000066400000000000000000000011111517371647300312240ustar00rootroot00000000000000from functools import lru_cache from pydantic import Field from pydantic_settings import BaseSettings from pydantic_settings import SettingsConfigDict class OpenAPISchemaValidatorSettings(BaseSettings): model_config = SettingsConfigDict( env_prefix="OPENAPI_SCHEMA_VALIDATOR_", extra="ignore", ) compiled_validator_cache_max_size: int = Field(default=128, ge=0) @lru_cache(maxsize=1) def get_settings() -> OpenAPISchemaValidatorSettings: return OpenAPISchemaValidatorSettings() def reset_settings_cache() -> None: get_settings.cache_clear() python-openapi-openapi-schema-validator-9480dee/openapi_schema_validator/shortcuts.py000066400000000000000000000110411517371647300314250ustar00rootroot00000000000000from __future__ import annotations from typing import Any from typing import Mapping from typing import cast from jsonschema.exceptions import best_match from jsonschema.protocols import Validator from referencing import Registry from openapi_schema_validator._caches import ValidatorCache from openapi_schema_validator._dialects import OAS31_BASE_DIALECT_ID from openapi_schema_validator._dialects import OAS32_BASE_DIALECT_ID from openapi_schema_validator.validators import OAS32Validator from openapi_schema_validator.validators import ( build_enforce_properties_required_validator, ) from openapi_schema_validator.validators import check_openapi_schema _LOCAL_ONLY_REGISTRY = Registry() _VALIDATOR_CACHE = ValidatorCache() def _check_schema( cls: type[Validator], schema: dict[str, Any], ) -> None: meta_schema = getattr(cls, "META_SCHEMA", None) # jsonschema's default check_schema path does not accept a custom # registry, so for OAS dialects we use the package registry # explicitly to keep metaschema resolution local and deterministic. if isinstance(meta_schema, dict) and meta_schema.get("$id") in ( OAS31_BASE_DIALECT_ID, OAS32_BASE_DIALECT_ID, ): check_openapi_schema(cls, schema) else: cls.check_schema(schema) def validate( instance: Any, schema: Mapping[str, Any], cls: type[Validator] = OAS32Validator, *args: Any, allow_remote_references: bool = False, check_schema: bool = True, enforce_properties_required: bool = False, **kwargs: Any, ) -> None: """ Validate an instance against a given schema using the specified validator class. Unlike direct ``Validator(schema).validate(instance)`` usage, this helper checks schema validity first. Invalid schemas therefore raise ``SchemaError`` before any instance validation occurs. Args: instance: Value to validate against ``schema``. schema: OpenAPI schema mapping used for validation. Local references (``#/...``) are resolved against this mapping. cls: Validator class to use. Defaults to ``OAS32Validator``. *args: Positional arguments forwarded to ``cls`` constructor. allow_remote_references: If ``True`` and no explicit ``registry`` is provided, allow jsonschema's default remote reference retrieval behavior. check_schema: If ``True`` (default), validate the provided schema before validating ``instance``. If ``False``, skip schema validation and run instance validation directly. enforce_properties_required: If ``True``, all properties declared in the schema's ``properties`` object are strictly required to be present in the instance (except those marked as ``writeOnly`` or ``readOnly`` where appropriate), regardless of the schema's ``required`` array. Defaults to ``False``. **kwargs: Keyword arguments forwarded to ``cls`` constructor (for example ``registry`` and ``format_checker``). If omitted, a local-only empty ``Registry`` is used to avoid implicit remote reference retrieval. Raises: jsonschema.exceptions.SchemaError: If ``schema`` is invalid. jsonschema.exceptions.ValidationError: If ``instance`` is invalid. """ if enforce_properties_required: cls = build_enforce_properties_required_validator(cls) # type: ignore[arg-type] schema_dict = cast(dict[str, Any], schema) validator_kwargs = kwargs.copy() if not allow_remote_references: validator_kwargs.setdefault("registry", _LOCAL_ONLY_REGISTRY) key = _VALIDATOR_CACHE.build_key( schema=schema_dict, cls=cls, args=args, kwargs=validator_kwargs, allow_remote_references=allow_remote_references, ) cached = _VALIDATOR_CACHE.get(key) if cached is None: if check_schema: _check_schema(cls, schema_dict) validator = cls(schema_dict, *args, **validator_kwargs) cached = _VALIDATOR_CACHE.set( key, validator=validator, schema_checked=check_schema, ) elif check_schema and not cached.schema_checked: _check_schema(cls, schema_dict) _VALIDATOR_CACHE.mark_schema_checked(key) else: _VALIDATOR_CACHE.touch(key) error = best_match( cached.validator.evolve(schema=schema_dict).iter_errors(instance) ) if error is not None: raise error def clear_validate_cache() -> None: _VALIDATOR_CACHE.clear() python-openapi-openapi-schema-validator-9480dee/openapi_schema_validator/validators.py000066400000000000000000000200221517371647300315360ustar00rootroot00000000000000from functools import lru_cache from typing import Any from typing import Iterator from typing import Mapping from typing import cast from jsonschema import _keywords from jsonschema import _legacy_keywords from jsonschema.exceptions import SchemaError from jsonschema.exceptions import ValidationError from jsonschema.protocols import Validator from jsonschema.validators import Draft202012Validator from jsonschema.validators import create from jsonschema.validators import extend from jsonschema.validators import validator_for from openapi_schema_validator import _format as oas_format from openapi_schema_validator import _keywords as oas_keywords from openapi_schema_validator import _types as oas_types from openapi_schema_validator._dialects import OAS31_BASE_DIALECT_ID from openapi_schema_validator._dialects import OAS31_BASE_DIALECT_METASCHEMA from openapi_schema_validator._dialects import OAS32_BASE_DIALECT_ID from openapi_schema_validator._dialects import OAS32_BASE_DIALECT_METASCHEMA from openapi_schema_validator._dialects import register_openapi_dialect from openapi_schema_validator._specifications import ( REGISTRY as OPENAPI_SPECIFICATIONS, ) from openapi_schema_validator._types import oas31_type_checker _CHECK_SCHEMA_UNSET = object() def check_openapi_schema( cls: Any, schema: Any, format_checker: Any = _CHECK_SCHEMA_UNSET, ) -> None: if format_checker is _CHECK_SCHEMA_UNSET: format_checker = cls.FORMAT_CHECKER validator_class = validator_for(cls.META_SCHEMA, default=cls) validator_for_metaschema = validator_class( cls.META_SCHEMA, format_checker=format_checker, registry=OPENAPI_SPECIFICATIONS, ) for error in validator_for_metaschema.iter_errors(schema): raise SchemaError.create_from(error) def _oas30_id_of(schema: Any) -> str: if isinstance(schema, dict): return schema.get("id", "") # type: ignore[no-any-return] return "" OAS30_VALIDATORS = cast( Any, { "multipleOf": _keywords.multipleOf, # exclusiveMaximum supported inside maximum_draft3_draft4 "maximum": _legacy_keywords.maximum_draft3_draft4, # exclusiveMinimum supported inside minimum_draft3_draft4 "minimum": _legacy_keywords.minimum_draft3_draft4, "maxLength": _keywords.maxLength, "minLength": _keywords.minLength, "pattern": oas_keywords.pattern, "maxItems": _keywords.maxItems, "minItems": _keywords.minItems, "uniqueItems": _keywords.uniqueItems, "maxProperties": _keywords.maxProperties, "minProperties": _keywords.minProperties, "enum": _keywords.enum, # adjusted to OAS "type": oas_keywords.type, "allOf": oas_keywords.allOf, "oneOf": oas_keywords.oneOf, "anyOf": oas_keywords.anyOf, "not": _keywords.not_, "items": oas_keywords.items, "properties": _keywords.properties, "required": oas_keywords.required, "additionalProperties": oas_keywords.additionalProperties, # TODO: adjust description "format": oas_keywords.format, # TODO: adjust default "$ref": _keywords.ref, # fixed OAS fields "discriminator": oas_keywords.not_implemented, "readOnly": oas_keywords.not_implemented, "writeOnly": oas_keywords.not_implemented, "xml": oas_keywords.not_implemented, "externalDocs": oas_keywords.not_implemented, "example": oas_keywords.not_implemented, "deprecated": oas_keywords.not_implemented, }, ) def _build_oas30_validator() -> Any: return create( meta_schema=OPENAPI_SPECIFICATIONS.contents( "http://json-schema.org/draft-04/schema#", ), validators=OAS30_VALIDATORS, type_checker=oas_types.oas30_type_checker, format_checker=oas_format.oas30_format_checker, # NOTE: version causes conflict with global jsonschema validator # See https://github.com/python-openapi/openapi-schema-validator/pull/12 # version="oas30", id_of=_oas30_id_of, ) def _build_oas31_validator() -> Any: validator = extend( Draft202012Validator, { # adjusted to OAS "pattern": oas_keywords.pattern, "description": oas_keywords.not_implemented, # fixed OAS fields # discriminator is annotation-only in OAS 3.1+ "discriminator": oas_keywords.not_implemented, "xml": oas_keywords.not_implemented, "externalDocs": oas_keywords.not_implemented, "example": oas_keywords.not_implemented, }, type_checker=oas31_type_checker, format_checker=oas_format.oas31_format_checker, ) return register_openapi_dialect( validator=validator, dialect_id=OAS31_BASE_DIALECT_ID, version_name="oas31", metaschema=OAS31_BASE_DIALECT_METASCHEMA, ) def _build_oas32_validator() -> Any: validator = extend( OAS31Validator, {}, format_checker=oas_format.oas32_format_checker, ) return register_openapi_dialect( validator=validator, dialect_id=OAS32_BASE_DIALECT_ID, version_name="oas32", metaschema=OAS32_BASE_DIALECT_METASCHEMA, ) OAS30Validator = _build_oas30_validator() OAS30StrictValidator = extend( OAS30Validator, validators={ "type": oas_keywords.strict_type, }, type_checker=oas_types.oas30_type_checker, format_checker=oas_format.oas30_strict_format_checker, # NOTE: version causes conflict with global jsonschema validator # See https://github.com/python-openapi/openapi-schema-validator/pull/12 # version="oas30-strict", ) OAS30ReadValidator = extend( OAS30Validator, validators={ "required": oas_keywords.read_required, "writeOnly": oas_keywords.read_writeOnly, }, ) OAS30WriteValidator = extend( OAS30Validator, validators={ "required": oas_keywords.write_required, "readOnly": oas_keywords.write_readOnly, }, ) OAS31Validator = _build_oas31_validator() OAS32Validator = _build_oas32_validator() # These validator classes are generated via jsonschema create/extend, so there # is no simpler hook to inject registry-aware schema checking while preserving # each class's FORMAT_CHECKER. Override check_schema on each class to keep # OpenAPI metaschema resolution local and to apply optional ecma-regex # behavior consistently across OAS 3.0/3.1/3.2. OAS30Validator.check_schema = classmethod(check_openapi_schema) OAS31Validator.check_schema = classmethod(check_openapi_schema) OAS32Validator.check_schema = classmethod(check_openapi_schema) @lru_cache(maxsize=None) def build_enforce_properties_required_validator( validator_class: Any, ) -> type[Validator]: properties_validator = validator_class.VALIDATORS.get("properties") required_validator = validator_class.VALIDATORS.get("required") def enforce_properties( validator: Any, properties: Any, instance: Any, schema: Mapping[str, Any], ) -> Iterator[Any]: if properties_validator is not None: yield from properties_validator( validator, properties, instance, schema ) if not validator.is_type(instance, "object"): return if required_validator is not None: schema_required = ( schema.get("required", []) if isinstance(schema, dict) else [] ) missing_props = [ p for p in properties.keys() if p not in schema_required ] if missing_props: yield from required_validator( validator, missing_props, instance, schema ) extended_validator = extend( validator_class, validators={"properties": enforce_properties}, ) if hasattr(validator_class, "check_schema"): extended_validator.check_schema = classmethod( validator_class.check_schema.__func__ ) return cast(type[Validator], extended_validator) python-openapi-openapi-schema-validator-9480dee/poetry.lock000066400000000000000000006144351517371647300242110ustar00rootroot00000000000000# This file is automatically @generated by Poetry 2.2.1 and should not be changed by hand. [[package]] name = "alabaster" version = "0.7.16" description = "A light, configurable Sphinx theme" optional = false python-versions = ">=3.9" groups = ["docs"] files = [ {file = "alabaster-0.7.16-py3-none-any.whl", hash = "sha256:b46733c07dce03ae4e150330b975c75737fa60f0a7c591b6c8bf4928a28e2c92"}, {file = "alabaster-0.7.16.tar.gz", hash = "sha256:75a8b99c28a5dad50dd7f8ccdd447a121ddb3892da9e53d1ca5cca3106d58d65"}, ] [[package]] name = "annotated-types" version = "0.7.0" description = "Reusable constraint types to use with typing.Annotated" optional = false python-versions = ">=3.8" groups = ["main", "docs"] files = [ {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, ] [[package]] name = "appdirs" version = "1.4.4" description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." optional = false python-versions = "*" groups = ["docs"] files = [ {file = "appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"}, {file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"}, ] [[package]] name = "attrs" version = "25.4.0" description = "Classes Without Boilerplate" optional = false python-versions = ">=3.9" groups = ["main"] files = [ {file = "attrs-25.4.0-py3-none-any.whl", hash = "sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373"}, {file = "attrs-25.4.0.tar.gz", hash = "sha256:16d5969b87f0859ef33a48b35d55ac1be6e42ae49d5e853b597db70c35c57e11"}, ] [[package]] name = "babel" version = "2.18.0" description = "Internationalization utilities" optional = false python-versions = ">=3.8" groups = ["docs"] files = [ {file = "babel-2.18.0-py3-none-any.whl", hash = "sha256:e2b422b277c2b9a9630c1d7903c2a00d0830c409c59ac8cae9081c92f1aeba35"}, {file = "babel-2.18.0.tar.gz", hash = "sha256:b80b99a14bd085fcacfa15c9165f651fbb3406e66cc603abf11c5750937c992d"}, ] [package.extras] dev = ["backports.zoneinfo ; python_version < \"3.9\"", "freezegun (>=1.0,<2.0)", "jinja2 (>=3.0)", "pytest (>=6.0)", "pytest-cov", "pytz", "setuptools", "tzdata ; sys_platform == \"win32\""] [[package]] name = "black" version = "26.3.1" description = "The uncompromising code formatter." optional = false python-versions = ">=3.10" groups = ["dev"] files = [ {file = "black-26.3.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:86a8b5035fce64f5dcd1b794cf8ec4d31fe458cf6ce3986a30deb434df82a1d2"}, {file = "black-26.3.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5602bdb96d52d2d0672f24f6ffe5218795736dd34807fd0fd55ccd6bf206168b"}, {file = "black-26.3.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6c54a4a82e291a1fee5137371ab488866b7c86a3305af4026bdd4dc78642e1ac"}, {file = "black-26.3.1-cp310-cp310-win_amd64.whl", hash = "sha256:6e131579c243c98f35bce64a7e08e87fb2d610544754675d4a0e73a070a5aa3a"}, {file = "black-26.3.1-cp310-cp310-win_arm64.whl", hash = "sha256:5ed0ca58586c8d9a487352a96b15272b7fa55d139fc8496b519e78023a8dab0a"}, {file = "black-26.3.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:28ef38aee69e4b12fda8dba75e21f9b4f979b490c8ac0baa7cb505369ac9e1ff"}, {file = "black-26.3.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bf9bf162ed91a26f1adba8efda0b573bc6924ec1408a52cc6f82cb73ec2b142c"}, {file = "black-26.3.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:474c27574d6d7037c1bc875a81d9be0a9a4f9ee95e62800dab3cfaadbf75acd5"}, {file = "black-26.3.1-cp311-cp311-win_amd64.whl", hash = "sha256:5e9d0d86df21f2e1677cc4bd090cd0e446278bcbbe49bf3659c308c3e402843e"}, {file = "black-26.3.1-cp311-cp311-win_arm64.whl", hash = "sha256:9a5e9f45e5d5e1c5b5c29b3bd4265dcc90e8b92cf4534520896ed77f791f4da5"}, {file = "black-26.3.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b5e6f89631eb88a7302d416594a32faeee9fb8fb848290da9d0a5f2903519fc1"}, {file = "black-26.3.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:41cd2012d35b47d589cb8a16faf8a32ef7a336f56356babd9fcf70939ad1897f"}, {file = "black-26.3.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0f76ff19ec5297dd8e66eb64deda23631e642c9393ab592826fd4bdc97a4bce7"}, {file = "black-26.3.1-cp312-cp312-win_amd64.whl", hash = "sha256:ddb113db38838eb9f043623ba274cfaf7d51d5b0c22ecb30afe58b1bb8322983"}, {file = "black-26.3.1-cp312-cp312-win_arm64.whl", hash = "sha256:dfdd51fc3e64ea4f35873d1b3fb25326773d55d2329ff8449139ebaad7357efb"}, {file = "black-26.3.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:855822d90f884905362f602880ed8b5df1b7e3ee7d0db2502d4388a954cc8c54"}, {file = "black-26.3.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8a33d657f3276328ce00e4d37fe70361e1ec7614da5d7b6e78de5426cb56332f"}, {file = "black-26.3.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f1cd08e99d2f9317292a311dfe578fd2a24b15dbce97792f9c4d752275c1fa56"}, {file = "black-26.3.1-cp313-cp313-win_amd64.whl", hash = "sha256:c7e72339f841b5a237ff14f7d3880ddd0fc7f98a1199e8c4327f9a4f478c1839"}, {file = "black-26.3.1-cp313-cp313-win_arm64.whl", hash = "sha256:afc622538b430aa4c8c853f7f63bc582b3b8030fd8c80b70fb5fa5b834e575c2"}, {file = "black-26.3.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:2d6bfaf7fd0993b420bed691f20f9492d53ce9a2bcccea4b797d34e947318a78"}, {file = "black-26.3.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:f89f2ab047c76a9c03f78d0d66ca519e389519902fa27e7a91117ef7611c0568"}, {file = "black-26.3.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b07fc0dab849d24a80a29cfab8d8a19187d1c4685d8a5e6385a5ce323c1f015f"}, {file = "black-26.3.1-cp314-cp314-win_amd64.whl", hash = "sha256:0126ae5b7c09957da2bdbd91a9ba1207453feada9e9fe51992848658c6c8e01c"}, {file = "black-26.3.1-cp314-cp314-win_arm64.whl", hash = "sha256:92c0ec1f2cc149551a2b7b47efc32c866406b6891b0ee4625e95967c8f4acfb1"}, {file = "black-26.3.1-py3-none-any.whl", hash = "sha256:2bd5aa94fc267d38bb21a70d7410a89f1a1d318841855f698746f8e7f51acd1b"}, {file = "black-26.3.1.tar.gz", hash = "sha256:2c50f5063a9641c7eed7795014ba37b0f5fa227f3d408b968936e24bc0566b07"}, ] [package.dependencies] click = ">=8.0.0" mypy-extensions = ">=0.4.3" packaging = ">=22.0" pathspec = ">=1.0.0" platformdirs = ">=2" pytokens = ">=0.4.0,<0.5.0" tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} typing-extensions = {version = ">=4.0.1", markers = "python_version < \"3.11\""} [package.extras] colorama = ["colorama (>=0.4.3)"] d = ["aiohttp (>=3.10)"] jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] uvloop = ["uvloop (>=0.15.2) ; sys_platform != \"win32\"", "winloop (>=0.5.0) ; sys_platform == \"win32\""] [[package]] name = "certifi" version = "2026.1.4" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.7" groups = ["dev", "docs"] files = [ {file = "certifi-2026.1.4-py3-none-any.whl", hash = "sha256:9943707519e4add1115f44c2bc244f782c0249876bf51b6599fee1ffbedd685c"}, {file = "certifi-2026.1.4.tar.gz", hash = "sha256:ac726dd470482006e014ad384921ed6438c457018f4b3d204aea4281258b2120"}, ] [[package]] name = "cfgv" version = "3.5.0" description = "Validate configuration and produce human readable error messages." optional = false python-versions = ">=3.10" groups = ["dev"] files = [ {file = "cfgv-3.5.0-py2.py3-none-any.whl", hash = "sha256:a8dc6b26ad22ff227d2634a65cb388215ce6cc96bbcc5cfde7641ae87e8dacc0"}, {file = "cfgv-3.5.0.tar.gz", hash = "sha256:d5b1034354820651caa73ede66a6294d6e95c1b00acc5e9b098e917404669132"}, ] [[package]] name = "charset-normalizer" version = "3.4.4" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." optional = false python-versions = ">=3.7" groups = ["dev", "docs"] files = [ {file = "charset_normalizer-3.4.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e824f1492727fa856dd6eda4f7cee25f8518a12f3c4a56a74e8095695089cf6d"}, {file = "charset_normalizer-3.4.4-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4bd5d4137d500351a30687c2d3971758aac9a19208fc110ccb9d7188fbe709e8"}, {file = "charset_normalizer-3.4.4-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:027f6de494925c0ab2a55eab46ae5129951638a49a34d87f4c3eda90f696b4ad"}, {file = "charset_normalizer-3.4.4-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f820802628d2694cb7e56db99213f930856014862f3fd943d290ea8438d07ca8"}, {file = "charset_normalizer-3.4.4-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:798d75d81754988d2565bff1b97ba5a44411867c0cf32b77a7e8f8d84796b10d"}, {file = "charset_normalizer-3.4.4-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9d1bb833febdff5c8927f922386db610b49db6e0d4f4ee29601d71e7c2694313"}, {file = "charset_normalizer-3.4.4-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:9cd98cdc06614a2f768d2b7286d66805f94c48cde050acdbbb7db2600ab3197e"}, {file = "charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:077fbb858e903c73f6c9db43374fd213b0b6a778106bc7032446a8e8b5b38b93"}, {file = "charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:244bfb999c71b35de57821b8ea746b24e863398194a4014e4c76adc2bbdfeff0"}, {file = "charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:64b55f9dce520635f018f907ff1b0df1fdc31f2795a922fb49dd14fbcdf48c84"}, {file = "charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:faa3a41b2b66b6e50f84ae4a68c64fcd0c44355741c6374813a800cd6695db9e"}, {file = "charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:6515f3182dbe4ea06ced2d9e8666d97b46ef4c75e326b79bb624110f122551db"}, {file = "charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:cc00f04ed596e9dc0da42ed17ac5e596c6ccba999ba6bd92b0e0aef2f170f2d6"}, {file = "charset_normalizer-3.4.4-cp310-cp310-win32.whl", hash = "sha256:f34be2938726fc13801220747472850852fe6b1ea75869a048d6f896838c896f"}, {file = "charset_normalizer-3.4.4-cp310-cp310-win_amd64.whl", hash = "sha256:a61900df84c667873b292c3de315a786dd8dac506704dea57bc957bd31e22c7d"}, {file = "charset_normalizer-3.4.4-cp310-cp310-win_arm64.whl", hash = "sha256:cead0978fc57397645f12578bfd2d5ea9138ea0fac82b2f63f7f7c6877986a69"}, {file = "charset_normalizer-3.4.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6e1fcf0720908f200cd21aa4e6750a48ff6ce4afe7ff5a79a90d5ed8a08296f8"}, {file = "charset_normalizer-3.4.4-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5f819d5fe9234f9f82d75bdfa9aef3a3d72c4d24a6e57aeaebba32a704553aa0"}, {file = "charset_normalizer-3.4.4-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:a59cb51917aa591b1c4e6a43c132f0cdc3c76dbad6155df4e28ee626cc77a0a3"}, {file = "charset_normalizer-3.4.4-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8ef3c867360f88ac904fd3f5e1f902f13307af9052646963ee08ff4f131adafc"}, {file = "charset_normalizer-3.4.4-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d9e45d7faa48ee908174d8fe84854479ef838fc6a705c9315372eacbc2f02897"}, {file = "charset_normalizer-3.4.4-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:840c25fb618a231545cbab0564a799f101b63b9901f2569faecd6b222ac72381"}, {file = "charset_normalizer-3.4.4-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ca5862d5b3928c4940729dacc329aa9102900382fea192fc5e52eb69d6093815"}, {file = "charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d9c7f57c3d666a53421049053eaacdd14bbd0a528e2186fcb2e672effd053bb0"}, {file = "charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:277e970e750505ed74c832b4bf75dac7476262ee2a013f5574dd49075879e161"}, {file = "charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:31fd66405eaf47bb62e8cd575dc621c56c668f27d46a61d975a249930dd5e2a4"}, {file = "charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:0d3d8f15c07f86e9ff82319b3d9ef6f4bf907608f53fe9d92b28ea9ae3d1fd89"}, {file = "charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:9f7fcd74d410a36883701fafa2482a6af2ff5ba96b9a620e9e0721e28ead5569"}, {file = "charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ebf3e58c7ec8a8bed6d66a75d7fb37b55e5015b03ceae72a8e7c74495551e224"}, {file = "charset_normalizer-3.4.4-cp311-cp311-win32.whl", hash = "sha256:eecbc200c7fd5ddb9a7f16c7decb07b566c29fa2161a16cf67b8d068bd21690a"}, {file = "charset_normalizer-3.4.4-cp311-cp311-win_amd64.whl", hash = "sha256:5ae497466c7901d54b639cf42d5b8c1b6a4fead55215500d2f486d34db48d016"}, {file = "charset_normalizer-3.4.4-cp311-cp311-win_arm64.whl", hash = "sha256:65e2befcd84bc6f37095f5961e68a6f077bf44946771354a28ad434c2cce0ae1"}, {file = "charset_normalizer-3.4.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0a98e6759f854bd25a58a73fa88833fba3b7c491169f86ce1180c948ab3fd394"}, {file = "charset_normalizer-3.4.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b5b290ccc2a263e8d185130284f8501e3e36c5e02750fc6b6bdeb2e9e96f1e25"}, {file = "charset_normalizer-3.4.4-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:74bb723680f9f7a6234dcf67aea57e708ec1fbdf5699fb91dfd6f511b0a320ef"}, {file = "charset_normalizer-3.4.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f1e34719c6ed0b92f418c7c780480b26b5d9c50349e9a9af7d76bf757530350d"}, {file = "charset_normalizer-3.4.4-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2437418e20515acec67d86e12bf70056a33abdacb5cb1655042f6538d6b085a8"}, {file = "charset_normalizer-3.4.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:11d694519d7f29d6cd09f6ac70028dba10f92f6cdd059096db198c283794ac86"}, {file = "charset_normalizer-3.4.4-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ac1c4a689edcc530fc9d9aa11f5774b9e2f33f9a0c6a57864e90908f5208d30a"}, {file = "charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:21d142cc6c0ec30d2efee5068ca36c128a30b0f2c53c1c07bd78cb6bc1d3be5f"}, {file = "charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:5dbe56a36425d26d6cfb40ce79c314a2e4dd6211d51d6d2191c00bed34f354cc"}, {file = "charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:5bfbb1b9acf3334612667b61bd3002196fe2a1eb4dd74d247e0f2a4d50ec9bbf"}, {file = "charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:d055ec1e26e441f6187acf818b73564e6e6282709e9bcb5b63f5b23068356a15"}, {file = "charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:af2d8c67d8e573d6de5bc30cdb27e9b95e49115cd9baad5ddbd1a6207aaa82a9"}, {file = "charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:780236ac706e66881f3b7f2f32dfe90507a09e67d1d454c762cf642e6e1586e0"}, {file = "charset_normalizer-3.4.4-cp312-cp312-win32.whl", hash = "sha256:5833d2c39d8896e4e19b689ffc198f08ea58116bee26dea51e362ecc7cd3ed26"}, {file = "charset_normalizer-3.4.4-cp312-cp312-win_amd64.whl", hash = "sha256:a79cfe37875f822425b89a82333404539ae63dbdddf97f84dcbc3d339aae9525"}, {file = "charset_normalizer-3.4.4-cp312-cp312-win_arm64.whl", hash = "sha256:376bec83a63b8021bb5c8ea75e21c4ccb86e7e45ca4eb81146091b56599b80c3"}, {file = "charset_normalizer-3.4.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:e1f185f86a6f3403aa2420e815904c67b2f9ebc443f045edd0de921108345794"}, {file = "charset_normalizer-3.4.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b39f987ae8ccdf0d2642338faf2abb1862340facc796048b604ef14919e55ed"}, {file = "charset_normalizer-3.4.4-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3162d5d8ce1bb98dd51af660f2121c55d0fa541b46dff7bb9b9f86ea1d87de72"}, {file = "charset_normalizer-3.4.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:81d5eb2a312700f4ecaa977a8235b634ce853200e828fbadf3a9c50bab278328"}, {file = "charset_normalizer-3.4.4-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5bd2293095d766545ec1a8f612559f6b40abc0eb18bb2f5d1171872d34036ede"}, {file = "charset_normalizer-3.4.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a8a8b89589086a25749f471e6a900d3f662d1d3b6e2e59dcecf787b1cc3a1894"}, {file = "charset_normalizer-3.4.4-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc7637e2f80d8530ee4a78e878bce464f70087ce73cf7c1caf142416923b98f1"}, {file = "charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f8bf04158c6b607d747e93949aa60618b61312fe647a6369f88ce2ff16043490"}, {file = "charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:554af85e960429cf30784dd47447d5125aaa3b99a6f0683589dbd27e2f45da44"}, {file = "charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:74018750915ee7ad843a774364e13a3db91682f26142baddf775342c3f5b1133"}, {file = "charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:c0463276121fdee9c49b98908b3a89c39be45d86d1dbaa22957e38f6321d4ce3"}, {file = "charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:362d61fd13843997c1c446760ef36f240cf81d3ebf74ac62652aebaf7838561e"}, {file = "charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9a26f18905b8dd5d685d6d07b0cdf98a79f3c7a918906af7cc143ea2e164c8bc"}, {file = "charset_normalizer-3.4.4-cp313-cp313-win32.whl", hash = "sha256:9b35f4c90079ff2e2edc5b26c0c77925e5d2d255c42c74fdb70fb49b172726ac"}, {file = "charset_normalizer-3.4.4-cp313-cp313-win_amd64.whl", hash = "sha256:b435cba5f4f750aa6c0a0d92c541fb79f69a387c91e61f1795227e4ed9cece14"}, {file = "charset_normalizer-3.4.4-cp313-cp313-win_arm64.whl", hash = "sha256:542d2cee80be6f80247095cc36c418f7bddd14f4a6de45af91dfad36d817bba2"}, {file = "charset_normalizer-3.4.4-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:da3326d9e65ef63a817ecbcc0df6e94463713b754fe293eaa03da99befb9a5bd"}, {file = "charset_normalizer-3.4.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8af65f14dc14a79b924524b1e7fffe304517b2bff5a58bf64f30b98bbc5079eb"}, {file = "charset_normalizer-3.4.4-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:74664978bb272435107de04e36db5a9735e78232b85b77d45cfb38f758efd33e"}, {file = "charset_normalizer-3.4.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:752944c7ffbfdd10c074dc58ec2d5a8a4cd9493b314d367c14d24c17684ddd14"}, {file = "charset_normalizer-3.4.4-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d1f13550535ad8cff21b8d757a3257963e951d96e20ec82ab44bc64aeb62a191"}, {file = "charset_normalizer-3.4.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ecaae4149d99b1c9e7b88bb03e3221956f68fd6d50be2ef061b2381b61d20838"}, {file = "charset_normalizer-3.4.4-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cb6254dc36b47a990e59e1068afacdcd02958bdcce30bb50cc1700a8b9d624a6"}, {file = "charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c8ae8a0f02f57a6e61203a31428fa1d677cbe50c93622b4149d5c0f319c1d19e"}, {file = "charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:47cc91b2f4dd2833fddaedd2893006b0106129d4b94fdb6af1f4ce5a9965577c"}, {file = "charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:82004af6c302b5d3ab2cfc4cc5f29db16123b1a8417f2e25f9066f91d4411090"}, {file = "charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:2b7d8f6c26245217bd2ad053761201e9f9680f8ce52f0fcd8d0755aeae5b2152"}, {file = "charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:799a7a5e4fb2d5898c60b640fd4981d6a25f1c11790935a44ce38c54e985f828"}, {file = "charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:99ae2cffebb06e6c22bdc25801d7b30f503cc87dbd283479e7b606f70aff57ec"}, {file = "charset_normalizer-3.4.4-cp314-cp314-win32.whl", hash = "sha256:f9d332f8c2a2fcbffe1378594431458ddbef721c1769d78e2cbc06280d8155f9"}, {file = "charset_normalizer-3.4.4-cp314-cp314-win_amd64.whl", hash = "sha256:8a6562c3700cce886c5be75ade4a5db4214fda19fede41d9792d100288d8f94c"}, {file = "charset_normalizer-3.4.4-cp314-cp314-win_arm64.whl", hash = "sha256:de00632ca48df9daf77a2c65a484531649261ec9f25489917f09e455cb09ddb2"}, {file = "charset_normalizer-3.4.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ce8a0633f41a967713a59c4139d29110c07e826d131a316b50ce11b1d79b4f84"}, {file = "charset_normalizer-3.4.4-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:eaabd426fe94daf8fd157c32e571c85cb12e66692f15516a83a03264b08d06c3"}, {file = "charset_normalizer-3.4.4-cp38-cp38-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c4ef880e27901b6cc782f1b95f82da9313c0eb95c3af699103088fa0ac3ce9ac"}, {file = "charset_normalizer-3.4.4-cp38-cp38-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2aaba3b0819274cc41757a1da876f810a3e4d7b6eb25699253a4effef9e8e4af"}, {file = "charset_normalizer-3.4.4-cp38-cp38-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:778d2e08eda00f4256d7f672ca9fef386071c9202f5e4607920b86d7803387f2"}, {file = "charset_normalizer-3.4.4-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f155a433c2ec037d4e8df17d18922c3a0d9b3232a396690f17175d2946f0218d"}, {file = "charset_normalizer-3.4.4-cp38-cp38-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a8bf8d0f749c5757af2142fe7903a9df1d2e8aa3841559b2bad34b08d0e2bcf3"}, {file = "charset_normalizer-3.4.4-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:194f08cbb32dc406d6e1aea671a68be0823673db2832b38405deba2fb0d88f63"}, {file = "charset_normalizer-3.4.4-cp38-cp38-musllinux_1_2_armv7l.whl", hash = "sha256:6aee717dcfead04c6eb1ce3bd29ac1e22663cdea57f943c87d1eab9a025438d7"}, {file = "charset_normalizer-3.4.4-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:cd4b7ca9984e5e7985c12bc60a6f173f3c958eae74f3ef6624bb6b26e2abbae4"}, {file = "charset_normalizer-3.4.4-cp38-cp38-musllinux_1_2_riscv64.whl", hash = "sha256:b7cf1017d601aa35e6bb650b6ad28652c9cd78ee6caff19f3c28d03e1c80acbf"}, {file = "charset_normalizer-3.4.4-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:e912091979546adf63357d7e2ccff9b44f026c075aeaf25a52d0e95ad2281074"}, {file = "charset_normalizer-3.4.4-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:5cb4d72eea50c8868f5288b7f7f33ed276118325c1dfd3957089f6b519e1382a"}, {file = "charset_normalizer-3.4.4-cp38-cp38-win32.whl", hash = "sha256:837c2ce8c5a65a2035be9b3569c684358dfbf109fd3b6969630a87535495ceaa"}, {file = "charset_normalizer-3.4.4-cp38-cp38-win_amd64.whl", hash = "sha256:44c2a8734b333e0578090c4cd6b16f275e07aa6614ca8715e6c038e865e70576"}, {file = "charset_normalizer-3.4.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:a9768c477b9d7bd54bc0c86dbaebdec6f03306675526c9927c0e8a04e8f94af9"}, {file = "charset_normalizer-3.4.4-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1bee1e43c28aa63cb16e5c14e582580546b08e535299b8b6158a7c9c768a1f3d"}, {file = "charset_normalizer-3.4.4-cp39-cp39-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:fd44c878ea55ba351104cb93cc85e74916eb8fa440ca7903e57575e97394f608"}, {file = "charset_normalizer-3.4.4-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:0f04b14ffe5fdc8c4933862d8306109a2c51e0704acfa35d51598eb45a1e89fc"}, {file = "charset_normalizer-3.4.4-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:cd09d08005f958f370f539f186d10aec3377d55b9eeb0d796025d4886119d76e"}, {file = "charset_normalizer-3.4.4-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4fe7859a4e3e8457458e2ff592f15ccb02f3da787fcd31e0183879c3ad4692a1"}, {file = "charset_normalizer-3.4.4-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fa09f53c465e532f4d3db095e0c55b615f010ad81803d383195b6b5ca6cbf5f3"}, {file = "charset_normalizer-3.4.4-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:7fa17817dc5625de8a027cb8b26d9fefa3ea28c8253929b8d6649e705d2835b6"}, {file = "charset_normalizer-3.4.4-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:5947809c8a2417be3267efc979c47d76a079758166f7d43ef5ae8e9f92751f88"}, {file = "charset_normalizer-3.4.4-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:4902828217069c3c5c71094537a8e623f5d097858ac6ca8252f7b4d10b7560f1"}, {file = "charset_normalizer-3.4.4-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:7c308f7e26e4363d79df40ca5b2be1c6ba9f02bdbccfed5abddb7859a6ce72cf"}, {file = "charset_normalizer-3.4.4-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:2c9d3c380143a1fedbff95a312aa798578371eb29da42106a29019368a475318"}, {file = "charset_normalizer-3.4.4-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:cb01158d8b88ee68f15949894ccc6712278243d95f344770fa7593fa2d94410c"}, {file = "charset_normalizer-3.4.4-cp39-cp39-win32.whl", hash = "sha256:2677acec1a2f8ef614c6888b5b4ae4060cc184174a938ed4e8ef690e15d3e505"}, {file = "charset_normalizer-3.4.4-cp39-cp39-win_amd64.whl", hash = "sha256:f8e160feb2aed042cd657a72acc0b481212ed28b1b9a95c0cee1621b524e1966"}, {file = "charset_normalizer-3.4.4-cp39-cp39-win_arm64.whl", hash = "sha256:b5d84d37db046c5ca74ee7bb47dd6cbc13f80665fdde3e8040bdd3fb015ecb50"}, {file = "charset_normalizer-3.4.4-py3-none-any.whl", hash = "sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f"}, {file = "charset_normalizer-3.4.4.tar.gz", hash = "sha256:94537985111c35f28720e43603b8e7b43a6ecfb2ce1d3058bbe955b73404e21a"}, ] [[package]] name = "cli-ui" version = "0.19.0" description = "Build Nice User Interfaces In The Terminal" optional = false python-versions = "<4.0,>=3.9" groups = ["dev"] files = [ {file = "cli_ui-0.19.0-py3-none-any.whl", hash = "sha256:1cf1b93328f7377730db29507e10bcb29ccc1427ceef45714b522d1f2055e7cd"}, {file = "cli_ui-0.19.0.tar.gz", hash = "sha256:59cdab0c6a2a6703c61b31cb75a1943076888907f015fffe15c5a8eb41a933aa"}, ] [package.dependencies] colorama = ">=0.4.1,<0.5.0" tabulate = ">=0.9.0,<0.10.0" unidecode = ">=1.3.6,<2.0.0" [[package]] name = "click" version = "8.3.1" description = "Composable command line interface toolkit" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ {file = "click-8.3.1-py3-none-any.whl", hash = "sha256:981153a64e25f12d547d3426c367a4857371575ee7ad18df2a6183ab0545b2a6"}, {file = "click-8.3.1.tar.gz", hash = "sha256:12ff4785d337a1bb490bb7e9c2b1ee5da3112e94a8622f26a6c77f5d2fc6842a"}, ] [package.dependencies] colorama = {version = "*", markers = "platform_system == \"Windows\""} [[package]] name = "colorama" version = "0.4.6" description = "Cross-platform colored terminal text." optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" groups = ["dev", "docs"] files = [ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] markers = {docs = "sys_platform == \"win32\""} [[package]] name = "coverage" version = "7.13.4" description = "Code coverage measurement for Python" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ {file = "coverage-7.13.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0fc31c787a84f8cd6027eba44010517020e0d18487064cd3d8968941856d1415"}, {file = "coverage-7.13.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a32ebc02a1805adf637fc8dec324b5cdacd2e493515424f70ee33799573d661b"}, {file = "coverage-7.13.4-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:e24f9156097ff9dc286f2f913df3a7f63c0e333dcafa3c196f2c18b4175ca09a"}, {file = "coverage-7.13.4-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:8041b6c5bfdc03257666e9881d33b1abc88daccaf73f7b6340fb7946655cd10f"}, {file = "coverage-7.13.4-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2a09cfa6a5862bc2fc6ca7c3def5b2926194a56b8ab78ffcf617d28911123012"}, {file = "coverage-7.13.4-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:296f8b0af861d3970c2a4d8c91d48eb4dd4771bcef9baedec6a9b515d7de3def"}, {file = "coverage-7.13.4-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e101609bcbbfb04605ea1027b10dc3735c094d12d40826a60f897b98b1c30256"}, {file = "coverage-7.13.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:aa3feb8db2e87ff5e6d00d7e1480ae241876286691265657b500886c98f38bda"}, {file = "coverage-7.13.4-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:4fc7fa81bbaf5a02801b65346c8b3e657f1d93763e58c0abdf7c992addd81a92"}, {file = "coverage-7.13.4-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:33901f604424145c6e9c2398684b92e176c0b12df77d52db81c20abd48c3794c"}, {file = "coverage-7.13.4-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:bb28c0f2cf2782508a40cec377935829d5fcc3ad9a3681375af4e84eb34b6b58"}, {file = "coverage-7.13.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:9d107aff57a83222ddbd8d9ee705ede2af2cc926608b57abed8ef96b50b7e8f9"}, {file = "coverage-7.13.4-cp310-cp310-win32.whl", hash = "sha256:a6f94a7d00eb18f1b6d403c91a88fd58cfc92d4b16080dfdb774afc8294469bf"}, {file = "coverage-7.13.4-cp310-cp310-win_amd64.whl", hash = "sha256:2cb0f1e000ebc419632bbe04366a8990b6e32c4e0b51543a6484ffe15eaeda95"}, {file = "coverage-7.13.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d490ba50c3f35dd7c17953c68f3270e7ccd1c6642e2d2afe2d8e720b98f5a053"}, {file = "coverage-7.13.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:19bc3c88078789f8ef36acb014d7241961dbf883fd2533d18cb1e7a5b4e28b11"}, {file = "coverage-7.13.4-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3998e5a32e62fdf410c0dbd3115df86297995d6e3429af80b8798aad894ca7aa"}, {file = "coverage-7.13.4-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:8e264226ec98e01a8e1054314af91ee6cde0eacac4f465cc93b03dbe0bce2fd7"}, {file = "coverage-7.13.4-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a3aa4e7b9e416774b21797365b358a6e827ffadaaca81b69ee02946852449f00"}, {file = "coverage-7.13.4-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:71ca20079dd8f27fcf808817e281e90220475cd75115162218d0e27549f95fef"}, {file = "coverage-7.13.4-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e2f25215f1a359ab17320b47bcdaca3e6e6356652e8256f2441e4ef972052903"}, {file = "coverage-7.13.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d65b2d373032411e86960604dc4edac91fdfb5dca539461cf2cbe78327d1e64f"}, {file = "coverage-7.13.4-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:94eb63f9b363180aff17de3e7c8760c3ba94664ea2695c52f10111244d16a299"}, {file = "coverage-7.13.4-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:e856bf6616714c3a9fbc270ab54103f4e685ba236fa98c054e8f87f266c93505"}, {file = "coverage-7.13.4-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:65dfcbe305c3dfe658492df2d85259e0d79ead4177f9ae724b6fb245198f55d6"}, {file = "coverage-7.13.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b507778ae8a4c915436ed5c2e05b4a6cecfa70f734e19c22a005152a11c7b6a9"}, {file = "coverage-7.13.4-cp311-cp311-win32.whl", hash = "sha256:784fc3cf8be001197b652d51d3fd259b1e2262888693a4636e18879f613a62a9"}, {file = "coverage-7.13.4-cp311-cp311-win_amd64.whl", hash = "sha256:2421d591f8ca05b308cf0092807308b2facbefe54af7c02ac22548b88b95c98f"}, {file = "coverage-7.13.4-cp311-cp311-win_arm64.whl", hash = "sha256:79e73a76b854d9c6088fe5d8b2ebe745f8681c55f7397c3c0a016192d681045f"}, {file = "coverage-7.13.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:02231499b08dabbe2b96612993e5fc34217cdae907a51b906ac7fca8027a4459"}, {file = "coverage-7.13.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40aa8808140e55dc022b15d8aa7f651b6b3d68b365ea0398f1441e0b04d859c3"}, {file = "coverage-7.13.4-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:5b856a8ccf749480024ff3bd7310adaef57bf31fd17e1bfc404b7940b6986634"}, {file = "coverage-7.13.4-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:2c048ea43875fbf8b45d476ad79f179809c590ec7b79e2035c662e7afa3192e3"}, {file = "coverage-7.13.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b7b38448866e83176e28086674fe7368ab8590e4610fb662b44e345b86d63ffa"}, {file = "coverage-7.13.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:de6defc1c9badbf8b9e67ae90fd00519186d6ab64e5cc5f3d21359c2a9b2c1d3"}, {file = "coverage-7.13.4-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:7eda778067ad7ffccd23ecffce537dface96212576a07924cbf0d8799d2ded5a"}, {file = "coverage-7.13.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e87f6c587c3f34356c3759f0420693e35e7eb0e2e41e4c011cb6ec6ecbbf1db7"}, {file = "coverage-7.13.4-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:8248977c2e33aecb2ced42fef99f2d319e9904a36e55a8a68b69207fb7e43edc"}, {file = "coverage-7.13.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:25381386e80ae727608e662474db537d4df1ecd42379b5ba33c84633a2b36d47"}, {file = "coverage-7.13.4-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:ee756f00726693e5ba94d6df2bdfd64d4852d23b09bb0bc700e3b30e6f333985"}, {file = "coverage-7.13.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fdfc1e28e7c7cdce44985b3043bc13bbd9c747520f94a4d7164af8260b3d91f0"}, {file = "coverage-7.13.4-cp312-cp312-win32.whl", hash = "sha256:01d4cbc3c283a17fc1e42d614a119f7f438eabb593391283adca8dc86eff1246"}, {file = "coverage-7.13.4-cp312-cp312-win_amd64.whl", hash = "sha256:9401ebc7ef522f01d01d45532c68c5ac40fb27113019b6b7d8b208f6e9baa126"}, {file = "coverage-7.13.4-cp312-cp312-win_arm64.whl", hash = "sha256:b1ec7b6b6e93255f952e27ab58fbc68dcc468844b16ecbee881aeb29b6ab4d8d"}, {file = "coverage-7.13.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b66a2da594b6068b48b2692f043f35d4d3693fb639d5ea8b39533c2ad9ac3ab9"}, {file = "coverage-7.13.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3599eb3992d814d23b35c536c28df1a882caa950f8f507cef23d1cbf334995ac"}, {file = "coverage-7.13.4-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:93550784d9281e374fb5a12bf1324cc8a963fd63b2d2f223503ef0fd4aa339ea"}, {file = "coverage-7.13.4-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b720ce6a88a2755f7c697c23268ddc47a571b88052e6b155224347389fdf6a3b"}, {file = "coverage-7.13.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7b322db1284a2ed3aa28ffd8ebe3db91c929b7a333c0820abec3d838ef5b3525"}, {file = "coverage-7.13.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f4594c67d8a7c89cf922d9df0438c7c7bb022ad506eddb0fdb2863359ff78242"}, {file = "coverage-7.13.4-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:53d133df809c743eb8bce33b24bcababb371f4441340578cd406e084d94a6148"}, {file = "coverage-7.13.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:76451d1978b95ba6507a039090ba076105c87cc76fc3efd5d35d72093964d49a"}, {file = "coverage-7.13.4-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:7f57b33491e281e962021de110b451ab8a24182589be17e12a22c79047935e23"}, {file = "coverage-7.13.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:1731dc33dc276dafc410a885cbf5992f1ff171393e48a21453b78727d090de80"}, {file = "coverage-7.13.4-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:bd60d4fe2f6fa7dff9223ca1bbc9f05d2b6697bc5961072e5d3b952d46e1b1ea"}, {file = "coverage-7.13.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9181a3ccead280b828fae232df12b16652702b49d41e99d657f46cc7b1f6ec7a"}, {file = "coverage-7.13.4-cp313-cp313-win32.whl", hash = "sha256:f53d492307962561ac7de4cd1de3e363589b000ab69617c6156a16ba7237998d"}, {file = "coverage-7.13.4-cp313-cp313-win_amd64.whl", hash = "sha256:e6f70dec1cc557e52df5306d051ef56003f74d56e9c4dd7ddb07e07ef32a84dd"}, {file = "coverage-7.13.4-cp313-cp313-win_arm64.whl", hash = "sha256:fb07dc5da7e849e2ad31a5d74e9bece81f30ecf5a42909d0a695f8bd1874d6af"}, {file = "coverage-7.13.4-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:40d74da8e6c4b9ac18b15331c4b5ebc35a17069410cad462ad4f40dcd2d50c0d"}, {file = "coverage-7.13.4-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:4223b4230a376138939a9173f1bdd6521994f2aff8047fae100d6d94d50c5a12"}, {file = "coverage-7.13.4-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:1d4be36a5114c499f9f1f9195e95ebf979460dbe2d88e6816ea202010ba1c34b"}, {file = "coverage-7.13.4-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:200dea7d1e8095cc6e98cdabe3fd1d21ab17d3cee6dab00cadbb2fe35d9c15b9"}, {file = "coverage-7.13.4-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b8eb931ee8e6d8243e253e5ed7336deea6904369d2fd8ae6e43f68abbf167092"}, {file = "coverage-7.13.4-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:75eab1ebe4f2f64d9509b984f9314d4aa788540368218b858dad56dc8f3e5eb9"}, {file = "coverage-7.13.4-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c35eb28c1d085eb7d8c9b3296567a1bebe03ce72962e932431b9a61f28facf26"}, {file = "coverage-7.13.4-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:eb88b316ec33760714a4720feb2816a3a59180fd58c1985012054fa7aebee4c2"}, {file = "coverage-7.13.4-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:7d41eead3cc673cbd38a4417deb7fd0b4ca26954ff7dc6078e33f6ff97bed940"}, {file = "coverage-7.13.4-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:fb26a934946a6afe0e326aebe0730cdff393a8bc0bbb65a2f41e30feddca399c"}, {file = "coverage-7.13.4-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:dae88bc0fc77edaa65c14be099bd57ee140cf507e6bfdeea7938457ab387efb0"}, {file = "coverage-7.13.4-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:845f352911777a8e722bfce168958214951e07e47e5d5d9744109fa5fe77f79b"}, {file = "coverage-7.13.4-cp313-cp313t-win32.whl", hash = "sha256:2fa8d5f8de70688a28240de9e139fa16b153cc3cbb01c5f16d88d6505ebdadf9"}, {file = "coverage-7.13.4-cp313-cp313t-win_amd64.whl", hash = "sha256:9351229c8c8407645840edcc277f4a2d44814d1bc34a2128c11c2a031d45a5dd"}, {file = "coverage-7.13.4-cp313-cp313t-win_arm64.whl", hash = "sha256:30b8d0512f2dc8c8747557e8fb459d6176a2c9e5731e2b74d311c03b78451997"}, {file = "coverage-7.13.4-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:300deaee342f90696ed186e3a00c71b5b3d27bffe9e827677954f4ee56969601"}, {file = "coverage-7.13.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:29e3220258d682b6226a9b0925bc563ed9a1ebcff3cad30f043eceea7eaf2689"}, {file = "coverage-7.13.4-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:391ee8f19bef69210978363ca930f7328081c6a0152f1166c91f0b5fdd2a773c"}, {file = "coverage-7.13.4-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:0dd7ab8278f0d58a0128ba2fca25824321f05d059c1441800e934ff2efa52129"}, {file = "coverage-7.13.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:78cdf0d578b15148b009ccf18c686aa4f719d887e76e6b40c38ffb61d264a552"}, {file = "coverage-7.13.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:48685fee12c2eb3b27c62f2658e7ea21e9c3239cba5a8a242801a0a3f6a8c62a"}, {file = "coverage-7.13.4-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:4e83efc079eb39480e6346a15a1bcb3e9b04759c5202d157e1dd4303cd619356"}, {file = "coverage-7.13.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ecae9737b72408d6a950f7e525f30aca12d4bd8dd95e37342e5beb3a2a8c4f71"}, {file = "coverage-7.13.4-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:ae4578f8528569d3cf303fef2ea569c7f4c4059a38c8667ccef15c6e1f118aa5"}, {file = "coverage-7.13.4-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:6fdef321fdfbb30a197efa02d48fcd9981f0d8ad2ae8903ac318adc653f5df98"}, {file = "coverage-7.13.4-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:2b0f6ccf3dbe577170bebfce1318707d0e8c3650003cb4b3a9dd744575daa8b5"}, {file = "coverage-7.13.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:75fcd519f2a5765db3f0e391eb3b7d150cce1a771bf4c9f861aeab86c767a3c0"}, {file = "coverage-7.13.4-cp314-cp314-win32.whl", hash = "sha256:8e798c266c378da2bd819b0677df41ab46d78065fb2a399558f3f6cae78b2fbb"}, {file = "coverage-7.13.4-cp314-cp314-win_amd64.whl", hash = "sha256:245e37f664d89861cf2329c9afa2c1fe9e6d4e1a09d872c947e70718aeeac505"}, {file = "coverage-7.13.4-cp314-cp314-win_arm64.whl", hash = "sha256:ad27098a189e5838900ce4c2a99f2fe42a0bf0c2093c17c69b45a71579e8d4a2"}, {file = "coverage-7.13.4-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:85480adfb35ffc32d40918aad81b89c69c9cc5661a9b8a81476d3e645321a056"}, {file = "coverage-7.13.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:79be69cf7f3bf9b0deeeb062eab7ac7f36cd4cc4c4dd694bd28921ba4d8596cc"}, {file = "coverage-7.13.4-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:caa421e2684e382c5d8973ac55e4f36bed6821a9bad5c953494de960c74595c9"}, {file = "coverage-7.13.4-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:14375934243ee05f56c45393fe2ce81fe5cc503c07cee2bdf1725fb8bef3ffaf"}, {file = "coverage-7.13.4-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:25a41c3104d08edb094d9db0d905ca54d0cd41c928bb6be3c4c799a54753af55"}, {file = "coverage-7.13.4-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6f01afcff62bf9a08fb32b2c1d6e924236c0383c02c790732b6537269e466a72"}, {file = "coverage-7.13.4-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:eb9078108fbf0bcdde37c3f4779303673c2fa1fe8f7956e68d447d0dd426d38a"}, {file = "coverage-7.13.4-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:0e086334e8537ddd17e5f16a344777c1ab8194986ec533711cbe6c41cde841b6"}, {file = "coverage-7.13.4-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:725d985c5ab621268b2edb8e50dfe57633dc69bda071abc470fed55a14935fd3"}, {file = "coverage-7.13.4-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:3c06f0f1337c667b971ca2f975523347e63ec5e500b9aa5882d91931cd3ef750"}, {file = "coverage-7.13.4-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:590c0ed4bf8e85f745e6b805b2e1c457b2e33d5255dd9729743165253bc9ad39"}, {file = "coverage-7.13.4-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:eb30bf180de3f632cd043322dad5751390e5385108b2807368997d1a92a509d0"}, {file = "coverage-7.13.4-cp314-cp314t-win32.whl", hash = "sha256:c4240e7eded42d131a2d2c4dec70374b781b043ddc79a9de4d55ca71f8e98aea"}, {file = "coverage-7.13.4-cp314-cp314t-win_amd64.whl", hash = "sha256:4c7d3cc01e7350f2f0f6f7036caaf5673fb56b6998889ccfe9e1c1fe75a9c932"}, {file = "coverage-7.13.4-cp314-cp314t-win_arm64.whl", hash = "sha256:23e3f687cf945070d1c90f85db66d11e3025665d8dafa831301a0e0038f3db9b"}, {file = "coverage-7.13.4-py3-none-any.whl", hash = "sha256:1af1641e57cf7ba1bd67d677c9abdbcd6cc2ab7da3bca7fa1e2b7e50e65f2ad0"}, {file = "coverage-7.13.4.tar.gz", hash = "sha256:e5c8f6ed1e61a8b2dcdf31eb0b9bbf0130750ca79c1c49eb898e2ad86f5ccc91"}, ] [package.dependencies] tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""} [package.extras] toml = ["tomli ; python_full_version <= \"3.11.0a6\""] [[package]] name = "deptry" version = "0.25.1" description = "A command line utility to check for unused, missing and transitive dependencies in a Python project." optional = false python-versions = ">=3.10" groups = ["dev"] files = [ {file = "deptry-0.25.1-cp310-abi3-macosx_10_12_x86_64.whl", hash = "sha256:a4dd1148db24a1ddacfa8b840836c6019c2f864fcb7579dd089fd217606338c8"}, {file = "deptry-0.25.1-cp310-abi3-macosx_11_0_arm64.whl", hash = "sha256:c67c666d916ef12013c0772e40d78be0f21577a495d8d99ec5fcb18c332d393d"}, {file = "deptry-0.25.1-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:58d39279828dbf4efc1abb40bf50a71b21499c36759bed5a8d8a3c0e3149b091"}, {file = "deptry-0.25.1-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14bfcc28b4326ed8c6abb30691b19077d4ef8613cfba6c37ef5b1f471775bf6f"}, {file = "deptry-0.25.1-cp310-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:555f5f9a487899ec9bf301eecba1745e14d212c4b354f4d3a5fd691e907366d3"}, {file = "deptry-0.25.1-cp310-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:18d21b3545ab2bfec53f3f45c6f5f201d55f713323327f8d12674505469ae6b7"}, {file = "deptry-0.25.1-cp310-abi3-win_amd64.whl", hash = "sha256:b59a560cb7dffb21832a98bb80d33d614cfb5630ea36ce21833eabf4eae3df99"}, {file = "deptry-0.25.1-cp310-abi3-win_arm64.whl", hash = "sha256:6efffd8116fb9d2c45a251382ce4ce1c38dbb17179f581ec9231ed5390f7fc12"}, {file = "deptry-0.25.1-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:30d64d4df1c08bc69de56cb0b4ec1f4cd9fa2e42582347d5b1eb25fd0e401745"}, {file = "deptry-0.25.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:87bcd90f99a98bb059c7580bc315c3f87d97fe2db725530030bc974176834735"}, {file = "deptry-0.25.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:80f31eb5c520651b102568dd91f738222b250a3e44c9e95d4941322109b8d40a"}, {file = "deptry-0.25.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:df88952a2bab7517ef23cb304b979199b28449e5d9db2e9ba9bc27a286ac852b"}, {file = "deptry-0.25.1-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:e6f7b8fa72932e51e86799b10dcd29381b2132dc799c790dca3b28ab08dffb28"}, {file = "deptry-0.25.1-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:e3fa3321078e11cd1ac3f10ce3ff0547731c53f9253b87c757a8749c76fe8fa9"}, {file = "deptry-0.25.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:03c032c32492fde434736954fbcaff09c02bf207b0f793b77e9040300e34b344"}, {file = "deptry-0.25.1.tar.gz", hash = "sha256:45c8cd982c85cd4faae573ddff6920de7eec735336db6973f26a765ae7950f7d"}, ] [package.dependencies] click = ">=8.0.0,<9" colorama = {version = ">=0.4.6", markers = "sys_platform == \"win32\""} packaging = ">=23.2" requirements-parser = ">=0.11.0,<1" tomli = {version = ">=2.0.1", markers = "python_full_version < \"3.15.0\""} [[package]] name = "distlib" version = "0.4.0" description = "Distribution utilities" optional = false python-versions = "*" groups = ["dev"] files = [ {file = "distlib-0.4.0-py2.py3-none-any.whl", hash = "sha256:9659f7d87e46584a30b5780e43ac7a2143098441670ff0a49d5f9034c54a6c16"}, {file = "distlib-0.4.0.tar.gz", hash = "sha256:feec40075be03a04501a973d81f633735b4b69f98b05450592310c0f401a4e0d"}, ] [[package]] name = "docopt" version = "0.6.2" description = "Pythonic argument parser, that will make you smile" optional = false python-versions = "*" groups = ["dev"] files = [ {file = "docopt-0.6.2.tar.gz", hash = "sha256:49b3a825280bd66b3aa83585ef59c4a8c82f2c8a522dbe754a8bc8d08c85c491"}, ] [[package]] name = "docutils" version = "0.21.2" description = "Docutils -- Python Documentation Utilities" optional = false python-versions = ">=3.9" groups = ["docs"] files = [ {file = "docutils-0.21.2-py3-none-any.whl", hash = "sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2"}, {file = "docutils-0.21.2.tar.gz", hash = "sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f"}, ] [[package]] name = "exceptiongroup" version = "1.3.1" description = "Backport of PEP 654 (exception groups)" optional = false python-versions = ">=3.7" groups = ["dev"] markers = "python_version < \"3.11\"" files = [ {file = "exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598"}, {file = "exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219"}, ] [package.dependencies] typing-extensions = {version = ">=4.6.0", markers = "python_version < \"3.13\""} [package.extras] test = ["pytest (>=6)"] [[package]] name = "filelock" version = "3.24.3" description = "A platform independent file lock." optional = false python-versions = ">=3.10" groups = ["dev"] files = [ {file = "filelock-3.24.3-py3-none-any.whl", hash = "sha256:426e9a4660391f7f8a810d71b0555bce9008b0a1cc342ab1f6947d37639e002d"}, {file = "filelock-3.24.3.tar.gz", hash = "sha256:011a5644dc937c22699943ebbfc46e969cdde3e171470a6e40b9533e5a72affa"}, ] [[package]] name = "flake8" version = "7.3.0" description = "the modular source code checker: pep8 pyflakes and co" optional = false python-versions = ">=3.9" groups = ["dev"] files = [ {file = "flake8-7.3.0-py2.py3-none-any.whl", hash = "sha256:b9696257b9ce8beb888cdbe31cf885c90d31928fe202be0889a7cdafad32f01e"}, {file = "flake8-7.3.0.tar.gz", hash = "sha256:fe044858146b9fc69b551a4b490d69cf960fcb78ad1edcb84e7fbb1b4a8e3872"}, ] [package.dependencies] mccabe = ">=0.7.0,<0.8.0" pycodestyle = ">=2.14.0,<2.15.0" pyflakes = ">=3.4.0,<3.5.0" [[package]] name = "flynt" version = "1.0.6" description = "CLI tool to convert a python project's %-formatted strings to f-strings." optional = false python-versions = ">=3.9" groups = ["dev"] files = [ {file = "flynt-1.0.6-py3-none-any.whl", hash = "sha256:4e837c9597036b634a347855a89acf1483c4f8b73daa82c49372b10b6e1d1778"}, {file = "flynt-1.0.6.tar.gz", hash = "sha256:471b7ff00756678e2912d4261dcbcd8fc1395129b66bf6977f88a3b3ad220c90"}, ] [package.dependencies] tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} [package.extras] dev = ["build", "pre-commit", "pytest", "pytest-cov", "ruff", "twine"] [[package]] name = "identify" version = "2.6.16" description = "File identification library for Python" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ {file = "identify-2.6.16-py2.py3-none-any.whl", hash = "sha256:391ee4d77741d994189522896270b787aed8670389bfd60f326d677d64a6dfb0"}, {file = "identify-2.6.16.tar.gz", hash = "sha256:846857203b5511bbe94d5a352a48ef2359532bc8f6727b5544077a0dcfb24980"}, ] [package.extras] license = ["ukkonen"] [[package]] name = "idna" version = "3.11" description = "Internationalized Domain Names in Applications (IDNA)" optional = false python-versions = ">=3.8" groups = ["dev", "docs"] files = [ {file = "idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea"}, {file = "idna-3.11.tar.gz", hash = "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902"}, ] [package.extras] all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] [[package]] name = "imagesize" version = "1.4.1" description = "Getting image size from png/jpeg/jpeg2000/gif file" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" groups = ["docs"] files = [ {file = "imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b"}, {file = "imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a"}, ] [[package]] name = "iniconfig" version = "2.3.0" description = "brain-dead simple config-ini parsing" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ {file = "iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12"}, {file = "iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730"}, ] [[package]] name = "isort" version = "8.0.1" description = "A Python utility / library to sort Python imports." optional = false python-versions = ">=3.10.0" groups = ["dev"] files = [ {file = "isort-8.0.1-py3-none-any.whl", hash = "sha256:28b89bc70f751b559aeca209e6120393d43fbe2490de0559662be7a9787e3d75"}, {file = "isort-8.0.1.tar.gz", hash = "sha256:171ac4ff559cdc060bcfff550bc8404a486fee0caab245679c2abe7cb253c78d"}, ] [package.extras] colors = ["colorama"] [[package]] name = "jinja2" version = "3.1.6" description = "A very fast and expressive template engine." optional = false python-versions = ">=3.7" groups = ["docs"] files = [ {file = "jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67"}, {file = "jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d"}, ] [package.dependencies] MarkupSafe = ">=2.0" [package.extras] i18n = ["Babel (>=2.7)"] [[package]] name = "jsonschema" version = "4.26.0" description = "An implementation of JSON Schema validation for Python" optional = false python-versions = ">=3.10" groups = ["main"] files = [ {file = "jsonschema-4.26.0-py3-none-any.whl", hash = "sha256:d489f15263b8d200f8387e64b4c3a75f06629559fb73deb8fdfb525f2dab50ce"}, {file = "jsonschema-4.26.0.tar.gz", hash = "sha256:0c26707e2efad8aa1bfc5b7ce170f3fccc2e4918ff85989ba9ffa9facb2be326"}, ] [package.dependencies] attrs = ">=22.2.0" jsonschema-specifications = ">=2023.03.6" referencing = ">=0.28.4" rpds-py = ">=0.25.0" [package.extras] format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "rfc3987-syntax (>=1.1.0)", "uri-template", "webcolors (>=24.6.0)"] [[package]] name = "jsonschema-specifications" version = "2025.9.1" description = "The JSON Schema meta-schemas and vocabularies, exposed as a Registry" optional = false python-versions = ">=3.9" groups = ["main"] files = [ {file = "jsonschema_specifications-2025.9.1-py3-none-any.whl", hash = "sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe"}, {file = "jsonschema_specifications-2025.9.1.tar.gz", hash = "sha256:b540987f239e745613c7a9176f3edb72b832a4ac465cf02712288397832b5e8d"}, ] [package.dependencies] referencing = ">=0.31.0" [[package]] name = "librt" version = "0.8.1" description = "Mypyc runtime library" optional = false python-versions = ">=3.9" groups = ["dev"] markers = "platform_python_implementation != \"PyPy\"" files = [ {file = "librt-0.8.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:81fd938344fecb9373ba1b155968c8a329491d2ce38e7ddb76f30ffb938f12dc"}, {file = "librt-0.8.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5db05697c82b3a2ec53f6e72b2ed373132b0c2e05135f0696784e97d7f5d48e7"}, {file = "librt-0.8.1-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:d56bc4011975f7460bea7b33e1ff425d2f1adf419935ff6707273c77f8a4ada6"}, {file = "librt-0.8.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5cdc0f588ff4b663ea96c26d2a230c525c6fc62b28314edaaaca8ed5af931ad0"}, {file = "librt-0.8.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:97c2b54ff6717a7a563b72627990bec60d8029df17df423f0ed37d56a17a176b"}, {file = "librt-0.8.1-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:8f1125e6bbf2f1657d9a2f3ccc4a2c9b0c8b176965bb565dd4d86be67eddb4b6"}, {file = "librt-0.8.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:8f4bb453f408137d7581be309b2fbc6868a80e7ef60c88e689078ee3a296ae71"}, {file = "librt-0.8.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:c336d61d2fe74a3195edc1646d53ff1cddd3a9600b09fa6ab75e5514ba4862a7"}, {file = "librt-0.8.1-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:eb5656019db7c4deacf0c1a55a898c5bb8f989be904597fcb5232a2f4828fa05"}, {file = "librt-0.8.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c25d9e338d5bed46c1632f851babf3d13c78f49a225462017cf5e11e845c5891"}, {file = "librt-0.8.1-cp310-cp310-win32.whl", hash = "sha256:aaab0e307e344cb28d800957ef3ec16605146ef0e59e059a60a176d19543d1b7"}, {file = "librt-0.8.1-cp310-cp310-win_amd64.whl", hash = "sha256:56e04c14b696300d47b3bc5f1d10a00e86ae978886d0cee14e5714fafb5df5d2"}, {file = "librt-0.8.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:681dc2451d6d846794a828c16c22dc452d924e9f700a485b7ecb887a30aad1fd"}, {file = "librt-0.8.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a3b4350b13cc0e6f5bec8fa7caf29a8fb8cdc051a3bae45cfbfd7ce64f009965"}, {file = "librt-0.8.1-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:ac1e7817fd0ed3d14fd7c5df91daed84c48e4c2a11ee99c0547f9f62fdae13da"}, {file = "librt-0.8.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:747328be0c5b7075cde86a0e09d7a9196029800ba75a1689332348e998fb85c0"}, {file = "librt-0.8.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f0af2bd2bc204fa27f3d6711d0f360e6b8c684a035206257a81673ab924aa11e"}, {file = "librt-0.8.1-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d480de377f5b687b6b1bc0c0407426da556e2a757633cc7e4d2e1a057aa688f3"}, {file = "librt-0.8.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d0ee06b5b5291f609ddb37b9750985b27bc567791bc87c76a569b3feed8481ac"}, {file = "librt-0.8.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:9e2c6f77b9ad48ce5603b83b7da9ee3e36b3ab425353f695cba13200c5d96596"}, {file = "librt-0.8.1-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:439352ba9373f11cb8e1933da194dcc6206daf779ff8df0ed69c5e39113e6a99"}, {file = "librt-0.8.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:82210adabbc331dbb65d7868b105185464ef13f56f7f76688565ad79f648b0fe"}, {file = "librt-0.8.1-cp311-cp311-win32.whl", hash = "sha256:52c224e14614b750c0a6d97368e16804a98c684657c7518752c356834fff83bb"}, {file = "librt-0.8.1-cp311-cp311-win_amd64.whl", hash = "sha256:c00e5c884f528c9932d278d5c9cbbea38a6b81eb62c02e06ae53751a83a4d52b"}, {file = "librt-0.8.1-cp311-cp311-win_arm64.whl", hash = "sha256:f7cdf7f26c2286ffb02e46d7bac56c94655540b26347673bea15fa52a6af17e9"}, {file = "librt-0.8.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a28f2612ab566b17f3698b0da021ff9960610301607c9a5e8eaca62f5e1c350a"}, {file = "librt-0.8.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:60a78b694c9aee2a0f1aaeaa7d101cf713e92e8423a941d2897f4fa37908dab9"}, {file = "librt-0.8.1-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:758509ea3f1eba2a57558e7e98f4659d0ea7670bff49673b0dde18a3c7e6c0eb"}, {file = "librt-0.8.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:039b9f2c506bd0ab0f8725aa5ba339c6f0cd19d3b514b50d134789809c24285d"}, {file = "librt-0.8.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5bb54f1205a3a6ab41a6fd71dfcdcbd278670d3a90ca502a30d9da583105b6f7"}, {file = "librt-0.8.1-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:05bd41cdee35b0c59c259f870f6da532a2c5ca57db95b5f23689fcb5c9e42440"}, {file = "librt-0.8.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:adfab487facf03f0d0857b8710cf82d0704a309d8ffc33b03d9302b4c64e91a9"}, {file = "librt-0.8.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:153188fe98a72f206042be10a2c6026139852805215ed9539186312d50a8e972"}, {file = "librt-0.8.1-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:dd3c41254ee98604b08bd5b3af5bf0a89740d4ee0711de95b65166bf44091921"}, {file = "librt-0.8.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e0d138c7ae532908cbb342162b2611dbd4d90c941cd25ab82084aaf71d2c0bd0"}, {file = "librt-0.8.1-cp312-cp312-win32.whl", hash = "sha256:43353b943613c5d9c49a25aaffdba46f888ec354e71e3529a00cca3f04d66a7a"}, {file = "librt-0.8.1-cp312-cp312-win_amd64.whl", hash = "sha256:ff8baf1f8d3f4b6b7257fcb75a501f2a5499d0dda57645baa09d4d0d34b19444"}, {file = "librt-0.8.1-cp312-cp312-win_arm64.whl", hash = "sha256:0f2ae3725904f7377e11cc37722d5d401e8b3d5851fb9273d7f4fe04f6b3d37d"}, {file = "librt-0.8.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7e6bad1cd94f6764e1e21950542f818a09316645337fd5ab9a7acc45d99a8f35"}, {file = "librt-0.8.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cf450f498c30af55551ba4f66b9123b7185362ec8b625a773b3d39aa1a717583"}, {file = "librt-0.8.1-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:eca45e982fa074090057132e30585a7e8674e9e885d402eae85633e9f449ce6c"}, {file = "librt-0.8.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0c3811485fccfda840861905b8c70bba5ec094e02825598bb9d4ca3936857a04"}, {file = "librt-0.8.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5e4af413908f77294605e28cfd98063f54b2c790561383971d2f52d113d9c363"}, {file = "librt-0.8.1-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:5212a5bd7fae98dae95710032902edcd2ec4dc994e883294f75c857b83f9aba0"}, {file = "librt-0.8.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e692aa2d1d604e6ca12d35e51fdc36f4cda6345e28e36374579f7ef3611b3012"}, {file = "librt-0.8.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:4be2a5c926b9770c9e08e717f05737a269b9d0ebc5d2f0060f0fe3fe9ce47acb"}, {file = "librt-0.8.1-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:fd1a720332ea335ceb544cf0a03f81df92abd4bb887679fd1e460976b0e6214b"}, {file = "librt-0.8.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:93c2af9e01e0ef80d95ae3c720be101227edae5f2fe7e3dc63d8857fadfc5a1d"}, {file = "librt-0.8.1-cp313-cp313-win32.whl", hash = "sha256:086a32dbb71336627e78cc1d6ee305a68d038ef7d4c39aaff41ae8c9aa46e91a"}, {file = "librt-0.8.1-cp313-cp313-win_amd64.whl", hash = "sha256:e11769a1dbda4da7b00a76cfffa67aa47cfa66921d2724539eee4b9ede780b79"}, {file = "librt-0.8.1-cp313-cp313-win_arm64.whl", hash = "sha256:924817ab3141aca17893386ee13261f1d100d1ef410d70afe4389f2359fea4f0"}, {file = "librt-0.8.1-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:6cfa7fe54fd4d1f47130017351a959fe5804bda7a0bc7e07a2cdbc3fdd28d34f"}, {file = "librt-0.8.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:228c2409c079f8c11fb2e5d7b277077f694cb93443eb760e00b3b83cb8b3176c"}, {file = "librt-0.8.1-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:7aae78ab5e3206181780e56912d1b9bb9f90a7249ce12f0e8bf531d0462dd0fc"}, {file = "librt-0.8.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:172d57ec04346b047ca6af181e1ea4858086c80bdf455f61994c4aa6fc3f866c"}, {file = "librt-0.8.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6b1977c4ea97ce5eb7755a78fae68d87e4102e4aaf54985e8b56806849cc06a3"}, {file = "librt-0.8.1-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:10c42e1f6fd06733ef65ae7bebce2872bcafd8d6e6b0a08fe0a05a23b044fb14"}, {file = "librt-0.8.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:4c8dfa264b9193c4ee19113c985c95f876fae5e51f731494fc4e0cf594990ba7"}, {file = "librt-0.8.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:01170b6729a438f0dedc4a26ed342e3dc4f02d1000b4b19f980e1877f0c297e6"}, {file = "librt-0.8.1-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:7b02679a0d783bdae30d443025b94465d8c3dc512f32f5b5031f93f57ac32071"}, {file = "librt-0.8.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:190b109bb69592a3401fe1ffdea41a2e73370ace2ffdc4a0e8e2b39cdea81b78"}, {file = "librt-0.8.1-cp314-cp314-win32.whl", hash = "sha256:e70a57ecf89a0f64c24e37f38d3fe217a58169d2fe6ed6d70554964042474023"}, {file = "librt-0.8.1-cp314-cp314-win_amd64.whl", hash = "sha256:7e2f3edca35664499fbb36e4770650c4bd4a08abc1f4458eab9df4ec56389730"}, {file = "librt-0.8.1-cp314-cp314-win_arm64.whl", hash = "sha256:0d2f82168e55ddefd27c01c654ce52379c0750ddc31ee86b4b266bcf4d65f2a3"}, {file = "librt-0.8.1-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:2c74a2da57a094bd48d03fa5d196da83d2815678385d2978657499063709abe1"}, {file = "librt-0.8.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a355d99c4c0d8e5b770313b8b247411ed40949ca44e33e46a4789b9293a907ee"}, {file = "librt-0.8.1-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:2eb345e8b33fb748227409c9f1233d4df354d6e54091f0e8fc53acdb2ffedeb7"}, {file = "librt-0.8.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9be2f15e53ce4e83cc08adc29b26fb5978db62ef2a366fbdf716c8a6c8901040"}, {file = "librt-0.8.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:785ae29c1f5c6e7c2cde2c7c0e148147f4503da3abc5d44d482068da5322fd9e"}, {file = "librt-0.8.1-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:1d3a7da44baf692f0c6aeb5b2a09c5e6fc7a703bca9ffa337ddd2e2da53f7732"}, {file = "librt-0.8.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5fc48998000cbc39ec0d5311312dda93ecf92b39aaf184c5e817d5d440b29624"}, {file = "librt-0.8.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:e96baa6820280077a78244b2e06e416480ed859bbd8e5d641cf5742919d8beb4"}, {file = "librt-0.8.1-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:31362dbfe297b23590530007062c32c6f6176f6099646bb2c95ab1b00a57c382"}, {file = "librt-0.8.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:cc3656283d11540ab0ea01978378e73e10002145117055e03722417aeab30994"}, {file = "librt-0.8.1-cp314-cp314t-win32.whl", hash = "sha256:738f08021b3142c2918c03692608baed43bc51144c29e35807682f8070ee2a3a"}, {file = "librt-0.8.1-cp314-cp314t-win_amd64.whl", hash = "sha256:89815a22daf9c51884fb5dbe4f1ef65ee6a146e0b6a8df05f753e2e4a9359bf4"}, {file = "librt-0.8.1-cp314-cp314t-win_arm64.whl", hash = "sha256:bf512a71a23504ed08103a13c941f763db13fb11177beb3d9244c98c29fb4a61"}, {file = "librt-0.8.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3dff3d3ca8db20e783b1bc7de49c0a2ab0b8387f31236d6a026597d07fcd68ac"}, {file = "librt-0.8.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:08eec3a1fc435f0d09c87b6bf1ec798986a3544f446b864e4099633a56fcd9ed"}, {file = "librt-0.8.1-cp39-cp39-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:e3f0a41487fd5fad7e760b9e8a90e251e27c2816fbc2cff36a22a0e6bcbbd9dd"}, {file = "librt-0.8.1-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bacdb58d9939d95cc557b4dbaa86527c9db2ac1ed76a18bc8d26f6dc8647d851"}, {file = "librt-0.8.1-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b6d7ab1f01aa753188605b09a51faa44a3327400b00b8cce424c71910fc0a128"}, {file = "librt-0.8.1-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:4998009e7cb9e896569f4be7004f09d0ed70d386fa99d42b6d363f6d200501ac"}, {file = "librt-0.8.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2cc68eeeef5e906839c7bb0815748b5b0a974ec27125beefc0f942715785b551"}, {file = "librt-0.8.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:0bf69d79a23f4f40b8673a947a234baeeb133b5078b483b7297c5916539cf5d5"}, {file = "librt-0.8.1-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:22b46eabd76c1986ee7d231b0765ad387d7673bbd996aa0d0d054b38ac65d8f6"}, {file = "librt-0.8.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:237796479f4d0637d6b9cbcb926ff424a97735e68ade6facf402df4ec93375ed"}, {file = "librt-0.8.1-cp39-cp39-win32.whl", hash = "sha256:4beb04b8c66c6ae62f8c1e0b2f097c1ebad9295c929a8d5286c05eae7c2fc7dc"}, {file = "librt-0.8.1-cp39-cp39-win_amd64.whl", hash = "sha256:64548cde61b692dc0dc379f4b5f59a2f582c2ebe7890d09c1ae3b9e66fa015b7"}, {file = "librt-0.8.1.tar.gz", hash = "sha256:be46a14693955b3bd96014ccbdb8339ee8c9346fbe11c1b78901b55125f14c73"}, ] [[package]] name = "markupsafe" version = "3.0.3" description = "Safely add untrusted strings to HTML/XML markup." optional = false python-versions = ">=3.9" groups = ["docs"] files = [ {file = "markupsafe-3.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2f981d352f04553a7171b8e44369f2af4055f888dfb147d55e42d29e29e74559"}, {file = "markupsafe-3.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e1c1493fb6e50ab01d20a22826e57520f1284df32f2d8601fdd90b6304601419"}, {file = "markupsafe-3.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1ba88449deb3de88bd40044603fafffb7bc2b055d626a330323a9ed736661695"}, {file = "markupsafe-3.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f42d0984e947b8adf7dd6dde396e720934d12c506ce84eea8476409563607591"}, {file = "markupsafe-3.0.3-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c0c0b3ade1c0b13b936d7970b1d37a57acde9199dc2aecc4c336773e1d86049c"}, {file = "markupsafe-3.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:0303439a41979d9e74d18ff5e2dd8c43ed6c6001fd40e5bf2e43f7bd9bbc523f"}, {file = "markupsafe-3.0.3-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:d2ee202e79d8ed691ceebae8e0486bd9a2cd4794cec4824e1c99b6f5009502f6"}, {file = "markupsafe-3.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:177b5253b2834fe3678cb4a5f0059808258584c559193998be2601324fdeafb1"}, {file = "markupsafe-3.0.3-cp310-cp310-win32.whl", hash = "sha256:2a15a08b17dd94c53a1da0438822d70ebcd13f8c3a95abe3a9ef9f11a94830aa"}, {file = "markupsafe-3.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:c4ffb7ebf07cfe8931028e3e4c85f0357459a3f9f9490886198848f4fa002ec8"}, {file = "markupsafe-3.0.3-cp310-cp310-win_arm64.whl", hash = "sha256:e2103a929dfa2fcaf9bb4e7c091983a49c9ac3b19c9061b6d5427dd7d14d81a1"}, {file = "markupsafe-3.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1cc7ea17a6824959616c525620e387f6dd30fec8cb44f649e31712db02123dad"}, {file = "markupsafe-3.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4bd4cd07944443f5a265608cc6aab442e4f74dff8088b0dfc8238647b8f6ae9a"}, {file = "markupsafe-3.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b5420a1d9450023228968e7e6a9ce57f65d148ab56d2313fcd589eee96a7a50"}, {file = "markupsafe-3.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0bf2a864d67e76e5c9a34dc26ec616a66b9888e25e7b9460e1c76d3293bd9dbf"}, {file = "markupsafe-3.0.3-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc51efed119bc9cfdf792cdeaa4d67e8f6fcccab66ed4bfdd6bde3e59bfcbb2f"}, {file = "markupsafe-3.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:068f375c472b3e7acbe2d5318dea141359e6900156b5b2ba06a30b169086b91a"}, {file = "markupsafe-3.0.3-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:7be7b61bb172e1ed687f1754f8e7484f1c8019780f6f6b0786e76bb01c2ae115"}, {file = "markupsafe-3.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a"}, {file = "markupsafe-3.0.3-cp311-cp311-win32.whl", hash = "sha256:0db14f5dafddbb6d9208827849fad01f1a2609380add406671a26386cdf15a19"}, {file = "markupsafe-3.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:de8a88e63464af587c950061a5e6a67d3632e36df62b986892331d4620a35c01"}, {file = "markupsafe-3.0.3-cp311-cp311-win_arm64.whl", hash = "sha256:3b562dd9e9ea93f13d53989d23a7e775fdfd1066c33494ff43f5418bc8c58a5c"}, {file = "markupsafe-3.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d53197da72cc091b024dd97249dfc7794d6a56530370992a5e1a08983ad9230e"}, {file = "markupsafe-3.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1872df69a4de6aead3491198eaf13810b565bdbeec3ae2dc8780f14458ec73ce"}, {file = "markupsafe-3.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3a7e8ae81ae39e62a41ec302f972ba6ae23a5c5396c8e60113e9066ef893da0d"}, {file = "markupsafe-3.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d6dd0be5b5b189d31db7cda48b91d7e0a9795f31430b7f271219ab30f1d3ac9d"}, {file = "markupsafe-3.0.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:94c6f0bb423f739146aec64595853541634bde58b2135f27f61c1ffd1cd4d16a"}, {file = "markupsafe-3.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:be8813b57049a7dc738189df53d69395eba14fb99345e0a5994914a3864c8a4b"}, {file = "markupsafe-3.0.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:83891d0e9fb81a825d9a6d61e3f07550ca70a076484292a70fde82c4b807286f"}, {file = "markupsafe-3.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:77f0643abe7495da77fb436f50f8dab76dbc6e5fd25d39589a0f1fe6548bfa2b"}, {file = "markupsafe-3.0.3-cp312-cp312-win32.whl", hash = "sha256:d88b440e37a16e651bda4c7c2b930eb586fd15ca7406cb39e211fcff3bf3017d"}, {file = "markupsafe-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:26a5784ded40c9e318cfc2bdb30fe164bdb8665ded9cd64d500a34fb42067b1c"}, {file = "markupsafe-3.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:35add3b638a5d900e807944a078b51922212fb3dedb01633a8defc4b01a3c85f"}, {file = "markupsafe-3.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e1cf1972137e83c5d4c136c43ced9ac51d0e124706ee1c8aa8532c1287fa8795"}, {file = "markupsafe-3.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219"}, {file = "markupsafe-3.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6"}, {file = "markupsafe-3.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676"}, {file = "markupsafe-3.0.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:509fa21c6deb7a7a273d629cf5ec029bc209d1a51178615ddf718f5918992ab9"}, {file = "markupsafe-3.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4afe79fb3de0b7097d81da19090f4df4f8d3a2b3adaa8764138aac2e44f3af1"}, {file = "markupsafe-3.0.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:795e7751525cae078558e679d646ae45574b47ed6e7771863fcc079a6171a0fc"}, {file = "markupsafe-3.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8485f406a96febb5140bfeca44a73e3ce5116b2501ac54fe953e488fb1d03b12"}, {file = "markupsafe-3.0.3-cp313-cp313-win32.whl", hash = "sha256:bdd37121970bfd8be76c5fb069c7751683bdf373db1ed6c010162b2a130248ed"}, {file = "markupsafe-3.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5"}, {file = "markupsafe-3.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:7e68f88e5b8799aa49c85cd116c932a1ac15caaa3f5db09087854d218359e485"}, {file = "markupsafe-3.0.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:218551f6df4868a8d527e3062d0fb968682fe92054e89978594c28e642c43a73"}, {file = "markupsafe-3.0.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3524b778fe5cfb3452a09d31e7b5adefeea8c5be1d43c4f810ba09f2ceb29d37"}, {file = "markupsafe-3.0.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4e885a3d1efa2eadc93c894a21770e4bc67899e3543680313b09f139e149ab19"}, {file = "markupsafe-3.0.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8709b08f4a89aa7586de0aadc8da56180242ee0ada3999749b183aa23df95025"}, {file = "markupsafe-3.0.3-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b8512a91625c9b3da6f127803b166b629725e68af71f8184ae7e7d54686a56d6"}, {file = "markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9b79b7a16f7fedff2495d684f2b59b0457c3b493778c9eed31111be64d58279f"}, {file = "markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:12c63dfb4a98206f045aa9563db46507995f7ef6d83b2f68eda65c307c6829eb"}, {file = "markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8f71bc33915be5186016f675cd83a1e08523649b0e33efdb898db577ef5bb009"}, {file = "markupsafe-3.0.3-cp313-cp313t-win32.whl", hash = "sha256:69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354"}, {file = "markupsafe-3.0.3-cp313-cp313t-win_amd64.whl", hash = "sha256:1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218"}, {file = "markupsafe-3.0.3-cp313-cp313t-win_arm64.whl", hash = "sha256:ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287"}, {file = "markupsafe-3.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:eaa9599de571d72e2daf60164784109f19978b327a3910d3e9de8c97b5b70cfe"}, {file = "markupsafe-3.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026"}, {file = "markupsafe-3.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f34c41761022dd093b4b6896d4810782ffbabe30f2d443ff5f083e0cbbb8c737"}, {file = "markupsafe-3.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:457a69a9577064c05a97c41f4e65148652db078a3a509039e64d3467b9e7ef97"}, {file = "markupsafe-3.0.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e8afc3f2ccfa24215f8cb28dcf43f0113ac3c37c2f0f0806d8c70e4228c5cf4d"}, {file = "markupsafe-3.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ec15a59cf5af7be74194f7ab02d0f59a62bdcf1a537677ce67a2537c9b87fcda"}, {file = "markupsafe-3.0.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:0eb9ff8191e8498cca014656ae6b8d61f39da5f95b488805da4bb029cccbfbaf"}, {file = "markupsafe-3.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2713baf880df847f2bece4230d4d094280f4e67b1e813eec43b4c0e144a34ffe"}, {file = "markupsafe-3.0.3-cp314-cp314-win32.whl", hash = "sha256:729586769a26dbceff69f7a7dbbf59ab6572b99d94576a5592625d5b411576b9"}, {file = "markupsafe-3.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:bdc919ead48f234740ad807933cdf545180bfbe9342c2bb451556db2ed958581"}, {file = "markupsafe-3.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:5a7d5dc5140555cf21a6fefbdbf8723f06fcd2f63ef108f2854de715e4422cb4"}, {file = "markupsafe-3.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:1353ef0c1b138e1907ae78e2f6c63ff67501122006b0f9abad68fda5f4ffc6ab"}, {file = "markupsafe-3.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1085e7fbddd3be5f89cc898938f42c0b3c711fdcb37d75221de2666af647c175"}, {file = "markupsafe-3.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1b52b4fb9df4eb9ae465f8d0c228a00624de2334f216f178a995ccdcf82c4634"}, {file = "markupsafe-3.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50"}, {file = "markupsafe-3.0.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f190daf01f13c72eac4efd5c430a8de82489d9cff23c364c3ea822545032993e"}, {file = "markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e56b7d45a839a697b5eb268c82a71bd8c7f6c94d6fd50c3d577fa39a9f1409f5"}, {file = "markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:f3e98bb3798ead92273dc0e5fd0f31ade220f59a266ffd8a4f6065e0a3ce0523"}, {file = "markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5678211cb9333a6468fb8d8be0305520aa073f50d17f089b5b4b477ea6e67fdc"}, {file = "markupsafe-3.0.3-cp314-cp314t-win32.whl", hash = "sha256:915c04ba3851909ce68ccc2b8e2cd691618c4dc4c4232fb7982bca3f41fd8c3d"}, {file = "markupsafe-3.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4faffd047e07c38848ce017e8725090413cd80cbc23d86e55c587bf979e579c9"}, {file = "markupsafe-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa"}, {file = "markupsafe-3.0.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:15d939a21d546304880945ca1ecb8a039db6b4dc49b2c5a400387cdae6a62e26"}, {file = "markupsafe-3.0.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f71a396b3bf33ecaa1626c255855702aca4d3d9fea5e051b41ac59a9c1c41edc"}, {file = "markupsafe-3.0.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0f4b68347f8c5eab4a13419215bdfd7f8c9b19f2b25520968adfad23eb0ce60c"}, {file = "markupsafe-3.0.3-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e8fc20152abba6b83724d7ff268c249fa196d8259ff481f3b1476383f8f24e42"}, {file = "markupsafe-3.0.3-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:949b8d66bc381ee8b007cd945914c721d9aba8e27f71959d750a46f7c282b20b"}, {file = "markupsafe-3.0.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:3537e01efc9d4dccdf77221fb1cb3b8e1a38d5428920e0657ce299b20324d758"}, {file = "markupsafe-3.0.3-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:591ae9f2a647529ca990bc681daebdd52c8791ff06c2bfa05b65163e28102ef2"}, {file = "markupsafe-3.0.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a320721ab5a1aba0a233739394eb907f8c8da5c98c9181d1161e77a0c8e36f2d"}, {file = "markupsafe-3.0.3-cp39-cp39-win32.whl", hash = "sha256:df2449253ef108a379b8b5d6b43f4b1a8e81a061d6537becd5582fba5f9196d7"}, {file = "markupsafe-3.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:7c3fb7d25180895632e5d3148dbdc29ea38ccb7fd210aa27acbd1201a1902c6e"}, {file = "markupsafe-3.0.3-cp39-cp39-win_arm64.whl", hash = "sha256:38664109c14ffc9e7437e86b4dceb442b0096dfe3541d7864d9cbe1da4cf36c8"}, {file = "markupsafe-3.0.3.tar.gz", hash = "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698"}, ] [[package]] name = "mccabe" version = "0.7.0" description = "McCabe checker, plugin for flake8" optional = false python-versions = ">=3.6" groups = ["dev"] files = [ {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, ] [[package]] name = "mypy" version = "1.19.1" description = "Optional static typing for Python" optional = false python-versions = ">=3.9" groups = ["dev"] files = [ {file = "mypy-1.19.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5f05aa3d375b385734388e844bc01733bd33c644ab48e9684faa54e5389775ec"}, {file = "mypy-1.19.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:022ea7279374af1a5d78dfcab853fe6a536eebfda4b59deab53cd21f6cd9f00b"}, {file = "mypy-1.19.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee4c11e460685c3e0c64a4c5de82ae143622410950d6be863303a1c4ba0e36d6"}, {file = "mypy-1.19.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:de759aafbae8763283b2ee5869c7255391fbc4de3ff171f8f030b5ec48381b74"}, {file = "mypy-1.19.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ab43590f9cd5108f41aacf9fca31841142c786827a74ab7cc8a2eacb634e09a1"}, {file = "mypy-1.19.1-cp310-cp310-win_amd64.whl", hash = "sha256:2899753e2f61e571b3971747e302d5f420c3fd09650e1951e99f823bc3089dac"}, {file = "mypy-1.19.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d8dfc6ab58ca7dda47d9237349157500468e404b17213d44fc1cb77bce532288"}, {file = "mypy-1.19.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e3f276d8493c3c97930e354b2595a44a21348b320d859fb4a2b9f66da9ed27ab"}, {file = "mypy-1.19.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2abb24cf3f17864770d18d673c85235ba52456b36a06b6afc1e07c1fdcd3d0e6"}, {file = "mypy-1.19.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a009ffa5a621762d0c926a078c2d639104becab69e79538a494bcccb62cc0331"}, {file = "mypy-1.19.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f7cee03c9a2e2ee26ec07479f38ea9c884e301d42c6d43a19d20fb014e3ba925"}, {file = "mypy-1.19.1-cp311-cp311-win_amd64.whl", hash = "sha256:4b84a7a18f41e167f7995200a1d07a4a6810e89d29859df936f1c3923d263042"}, {file = "mypy-1.19.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a8174a03289288c1f6c46d55cef02379b478bfbc8e358e02047487cad44c6ca1"}, {file = "mypy-1.19.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ffcebe56eb09ff0c0885e750036a095e23793ba6c2e894e7e63f6d89ad51f22e"}, {file = "mypy-1.19.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b64d987153888790bcdb03a6473d321820597ab8dd9243b27a92153c4fa50fd2"}, {file = "mypy-1.19.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c35d298c2c4bba75feb2195655dfea8124d855dfd7343bf8b8c055421eaf0cf8"}, {file = "mypy-1.19.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:34c81968774648ab5ac09c29a375fdede03ba253f8f8287847bd480782f73a6a"}, {file = "mypy-1.19.1-cp312-cp312-win_amd64.whl", hash = "sha256:b10e7c2cd7870ba4ad9b2d8a6102eb5ffc1f16ca35e3de6bfa390c1113029d13"}, {file = "mypy-1.19.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e3157c7594ff2ef1634ee058aafc56a82db665c9438fd41b390f3bde1ab12250"}, {file = "mypy-1.19.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bdb12f69bcc02700c2b47e070238f42cb87f18c0bc1fc4cdb4fb2bc5fd7a3b8b"}, {file = "mypy-1.19.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f859fb09d9583a985be9a493d5cfc5515b56b08f7447759a0c5deaf68d80506e"}, {file = "mypy-1.19.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c9a6538e0415310aad77cb94004ca6482330fece18036b5f360b62c45814c4ef"}, {file = "mypy-1.19.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:da4869fc5e7f62a88f3fe0b5c919d1d9f7ea3cef92d3689de2823fd27e40aa75"}, {file = "mypy-1.19.1-cp313-cp313-win_amd64.whl", hash = "sha256:016f2246209095e8eda7538944daa1d60e1e8134d98983b9fc1e92c1fc0cb8dd"}, {file = "mypy-1.19.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:06e6170bd5836770e8104c8fdd58e5e725cfeb309f0a6c681a811f557e97eac1"}, {file = "mypy-1.19.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:804bd67b8054a85447c8954215a906d6eff9cabeabe493fb6334b24f4bfff718"}, {file = "mypy-1.19.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:21761006a7f497cb0d4de3d8ef4ca70532256688b0523eee02baf9eec895e27b"}, {file = "mypy-1.19.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:28902ee51f12e0f19e1e16fbe2f8f06b6637f482c459dd393efddd0ec7f82045"}, {file = "mypy-1.19.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:481daf36a4c443332e2ae9c137dfee878fcea781a2e3f895d54bd3002a900957"}, {file = "mypy-1.19.1-cp314-cp314-win_amd64.whl", hash = "sha256:8bb5c6f6d043655e055be9b542aa5f3bdd30e4f3589163e85f93f3640060509f"}, {file = "mypy-1.19.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7bcfc336a03a1aaa26dfce9fff3e287a3ba99872a157561cbfcebe67c13308e3"}, {file = "mypy-1.19.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b7951a701c07ea584c4fe327834b92a30825514c868b1f69c30445093fdd9d5a"}, {file = "mypy-1.19.1-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b13cfdd6c87fc3efb69ea4ec18ef79c74c3f98b4e5498ca9b85ab3b2c2329a67"}, {file = "mypy-1.19.1-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4f28f99c824ecebcdaa2e55d82953e38ff60ee5ec938476796636b86afa3956e"}, {file = "mypy-1.19.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c608937067d2fc5a4dd1a5ce92fd9e1398691b8c5d012d66e1ddd430e9244376"}, {file = "mypy-1.19.1-cp39-cp39-win_amd64.whl", hash = "sha256:409088884802d511ee52ca067707b90c883426bd95514e8cfda8281dc2effe24"}, {file = "mypy-1.19.1-py3-none-any.whl", hash = "sha256:f1235f5ea01b7db5468d53ece6aaddf1ad0b88d9e7462b86ef96fe04995d7247"}, {file = "mypy-1.19.1.tar.gz", hash = "sha256:19d88bb05303fe63f71dd2c6270daca27cb9401c4ca8255fe50d1d920e0eb9ba"}, ] [package.dependencies] librt = {version = ">=0.6.2", markers = "platform_python_implementation != \"PyPy\""} mypy_extensions = ">=1.0.0" pathspec = ">=0.9.0" tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} typing_extensions = ">=4.6.0" [package.extras] dmypy = ["psutil (>=4.0)"] faster-cache = ["orjson"] install-types = ["pip"] mypyc = ["setuptools (>=50)"] reports = ["lxml"] [[package]] name = "mypy-extensions" version = "1.1.0" description = "Type system extensions for programs checked with the mypy type checker." optional = false python-versions = ">=3.8" groups = ["dev"] files = [ {file = "mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505"}, {file = "mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558"}, ] [[package]] name = "nodeenv" version = "1.10.0" description = "Node.js virtual environment builder" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" groups = ["dev"] files = [ {file = "nodeenv-1.10.0-py2.py3-none-any.whl", hash = "sha256:5bb13e3eed2923615535339b3c620e76779af4cb4c6a90deccc9e36b274d3827"}, {file = "nodeenv-1.10.0.tar.gz", hash = "sha256:996c191ad80897d076bdfba80a41994c2b47c68e224c542b48feba42ba00f8bb"}, ] [[package]] name = "packaging" version = "26.0" description = "Core utilities for Python packages" optional = false python-versions = ">=3.8" groups = ["dev", "docs"] files = [ {file = "packaging-26.0-py3-none-any.whl", hash = "sha256:b36f1fef9334a5588b4166f8bcd26a14e521f2b55e6b9de3aaa80d3ff7a37529"}, {file = "packaging-26.0.tar.gz", hash = "sha256:00243ae351a257117b6a241061796684b084ed1c516a08c48a3f7e147a9d80b4"}, ] [[package]] name = "pathspec" version = "1.0.4" description = "Utility library for gitignore style pattern matching of file paths." optional = false python-versions = ">=3.9" groups = ["dev"] files = [ {file = "pathspec-1.0.4-py3-none-any.whl", hash = "sha256:fb6ae2fd4e7c921a165808a552060e722767cfa526f99ca5156ed2ce45a5c723"}, {file = "pathspec-1.0.4.tar.gz", hash = "sha256:0210e2ae8a21a9137c0d470578cb0e595af87edaa6ebf12ff176f14a02e0e645"}, ] [package.extras] hyperscan = ["hyperscan (>=0.7)"] optional = ["typing-extensions (>=4)"] re2 = ["google-re2 (>=1.1)"] tests = ["pytest (>=9)", "typing-extensions (>=4.15)"] [[package]] name = "platformdirs" version = "4.9.2" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." optional = false python-versions = ">=3.10" groups = ["dev"] files = [ {file = "platformdirs-4.9.2-py3-none-any.whl", hash = "sha256:9170634f126f8efdae22fb58ae8a0eaa86f38365bc57897a6c4f781d1f5875bd"}, {file = "platformdirs-4.9.2.tar.gz", hash = "sha256:9a33809944b9db043ad67ca0db94b14bf452cc6aeaac46a88ea55b26e2e9d291"}, ] [[package]] name = "pluggy" version = "1.6.0" description = "plugin and hook calling mechanisms for python" optional = false python-versions = ">=3.9" groups = ["dev"] files = [ {file = "pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746"}, {file = "pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3"}, ] [package.extras] dev = ["pre-commit", "tox"] testing = ["coverage", "pytest", "pytest-benchmark"] [[package]] name = "pre-commit" version = "4.5.1" description = "A framework for managing and maintaining multi-language pre-commit hooks." optional = false python-versions = ">=3.10" groups = ["dev"] files = [ {file = "pre_commit-4.5.1-py2.py3-none-any.whl", hash = "sha256:3b3afd891e97337708c1674210f8eba659b52a38ea5f822ff142d10786221f77"}, {file = "pre_commit-4.5.1.tar.gz", hash = "sha256:eb545fcff725875197837263e977ea257a402056661f09dae08e4b149b030a61"}, ] [package.dependencies] cfgv = ">=2.0.0" identify = ">=1.0.0" nodeenv = ">=0.11.1" pyyaml = ">=5.1" virtualenv = ">=20.10.0" [[package]] name = "pycodestyle" version = "2.14.0" description = "Python style guide checker" optional = false python-versions = ">=3.9" groups = ["dev"] files = [ {file = "pycodestyle-2.14.0-py2.py3-none-any.whl", hash = "sha256:dd6bf7cb4ee77f8e016f9c8e74a35ddd9f67e1d5fd4184d86c3b98e07099f42d"}, {file = "pycodestyle-2.14.0.tar.gz", hash = "sha256:c4b5b517d278089ff9d0abdec919cd97262a3367449ea1c8b49b91529167b783"}, ] [[package]] name = "pydantic" version = "2.12.5" description = "Data validation using Python type hints" optional = false python-versions = ">=3.9" groups = ["main", "docs"] files = [ {file = "pydantic-2.12.5-py3-none-any.whl", hash = "sha256:e561593fccf61e8a20fc46dfc2dfe075b8be7d0188df33f221ad1f0139180f9d"}, {file = "pydantic-2.12.5.tar.gz", hash = "sha256:4d351024c75c0f085a9febbb665ce8c0c6ec5d30e903bdb6394b7ede26aebb49"}, ] [package.dependencies] annotated-types = ">=0.6.0" pydantic-core = "2.41.5" typing-extensions = ">=4.14.1" typing-inspection = ">=0.4.2" [package.extras] email = ["email-validator (>=2.0.0)"] timezone = ["tzdata ; python_version >= \"3.9\" and platform_system == \"Windows\""] [[package]] name = "pydantic-core" version = "2.41.5" description = "Core functionality for Pydantic validation and serialization" optional = false python-versions = ">=3.9" groups = ["main", "docs"] files = [ {file = "pydantic_core-2.41.5-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:77b63866ca88d804225eaa4af3e664c5faf3568cea95360d21f4725ab6e07146"}, {file = "pydantic_core-2.41.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:dfa8a0c812ac681395907e71e1274819dec685fec28273a28905df579ef137e2"}, {file = "pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5921a4d3ca3aee735d9fd163808f5e8dd6c6972101e4adbda9a4667908849b97"}, {file = "pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e25c479382d26a2a41b7ebea1043564a937db462816ea07afa8a44c0866d52f9"}, {file = "pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f547144f2966e1e16ae626d8ce72b4cfa0caedc7fa28052001c94fb2fcaa1c52"}, {file = "pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6f52298fbd394f9ed112d56f3d11aabd0d5bd27beb3084cc3d8ad069483b8941"}, {file = "pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:100baa204bb412b74fe285fb0f3a385256dad1d1879f0a5cb1499ed2e83d132a"}, {file = "pydantic_core-2.41.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:05a2c8852530ad2812cb7914dc61a1125dc4e06252ee98e5638a12da6cc6fb6c"}, {file = "pydantic_core-2.41.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:29452c56df2ed968d18d7e21f4ab0ac55e71dc59524872f6fc57dcf4a3249ed2"}, {file = "pydantic_core-2.41.5-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:d5160812ea7a8a2ffbe233d8da666880cad0cbaf5d4de74ae15c313213d62556"}, {file = "pydantic_core-2.41.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:df3959765b553b9440adfd3c795617c352154e497a4eaf3752555cfb5da8fc49"}, {file = "pydantic_core-2.41.5-cp310-cp310-win32.whl", hash = "sha256:1f8d33a7f4d5a7889e60dc39856d76d09333d8a6ed0f5f1190635cbec70ec4ba"}, {file = "pydantic_core-2.41.5-cp310-cp310-win_amd64.whl", hash = "sha256:62de39db01b8d593e45871af2af9e497295db8d73b085f6bfd0b18c83c70a8f9"}, {file = "pydantic_core-2.41.5-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:a3a52f6156e73e7ccb0f8cced536adccb7042be67cb45f9562e12b319c119da6"}, {file = "pydantic_core-2.41.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7f3bf998340c6d4b0c9a2f02d6a400e51f123b59565d74dc60d252ce888c260b"}, {file = "pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:378bec5c66998815d224c9ca994f1e14c0c21cb95d2f52b6021cc0b2a58f2a5a"}, {file = "pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e7b576130c69225432866fe2f4a469a85a54ade141d96fd396dffcf607b558f8"}, {file = "pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6cb58b9c66f7e4179a2d5e0f849c48eff5c1fca560994d6eb6543abf955a149e"}, {file = "pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:88942d3a3dff3afc8288c21e565e476fc278902ae4d6d134f1eeda118cc830b1"}, {file = "pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f31d95a179f8d64d90f6831d71fa93290893a33148d890ba15de25642c5d075b"}, {file = "pydantic_core-2.41.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c1df3d34aced70add6f867a8cf413e299177e0c22660cc767218373d0779487b"}, {file = "pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:4009935984bd36bd2c774e13f9a09563ce8de4abaa7226f5108262fa3e637284"}, {file = "pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:34a64bc3441dc1213096a20fe27e8e128bd3ff89921706e83c0b1ac971276594"}, {file = "pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c9e19dd6e28fdcaa5a1de679aec4141f691023916427ef9bae8584f9c2fb3b0e"}, {file = "pydantic_core-2.41.5-cp311-cp311-win32.whl", hash = "sha256:2c010c6ded393148374c0f6f0bf89d206bf3217f201faa0635dcd56bd1520f6b"}, {file = "pydantic_core-2.41.5-cp311-cp311-win_amd64.whl", hash = "sha256:76ee27c6e9c7f16f47db7a94157112a2f3a00e958bc626e2f4ee8bec5c328fbe"}, {file = "pydantic_core-2.41.5-cp311-cp311-win_arm64.whl", hash = "sha256:4bc36bbc0b7584de96561184ad7f012478987882ebf9f9c389b23f432ea3d90f"}, {file = "pydantic_core-2.41.5-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:f41a7489d32336dbf2199c8c0a215390a751c5b014c2c1c5366e817202e9cdf7"}, {file = "pydantic_core-2.41.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:070259a8818988b9a84a449a2a7337c7f430a22acc0859c6b110aa7212a6d9c0"}, {file = "pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e96cea19e34778f8d59fe40775a7a574d95816eb150850a85a7a4c8f4b94ac69"}, {file = "pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ed2e99c456e3fadd05c991f8f437ef902e00eedf34320ba2b0842bd1c3ca3a75"}, {file = "pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:65840751b72fbfd82c3c640cff9284545342a4f1eb1586ad0636955b261b0b05"}, {file = "pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e536c98a7626a98feb2d3eaf75944ef6f3dbee447e1f841eae16f2f0a72d8ddc"}, {file = "pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eceb81a8d74f9267ef4081e246ffd6d129da5d87e37a77c9bde550cb04870c1c"}, {file = "pydantic_core-2.41.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d38548150c39b74aeeb0ce8ee1d8e82696f4a4e16ddc6de7b1d8823f7de4b9b5"}, {file = "pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c23e27686783f60290e36827f9c626e63154b82b116d7fe9adba1fda36da706c"}, {file = "pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:482c982f814460eabe1d3bb0adfdc583387bd4691ef00b90575ca0d2b6fe2294"}, {file = "pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:bfea2a5f0b4d8d43adf9d7b8bf019fb46fdd10a2e5cde477fbcb9d1fa08c68e1"}, {file = "pydantic_core-2.41.5-cp312-cp312-win32.whl", hash = "sha256:b74557b16e390ec12dca509bce9264c3bbd128f8a2c376eaa68003d7f327276d"}, {file = "pydantic_core-2.41.5-cp312-cp312-win_amd64.whl", hash = "sha256:1962293292865bca8e54702b08a4f26da73adc83dd1fcf26fbc875b35d81c815"}, {file = "pydantic_core-2.41.5-cp312-cp312-win_arm64.whl", hash = "sha256:1746d4a3d9a794cacae06a5eaaccb4b8643a131d45fbc9af23e353dc0a5ba5c3"}, {file = "pydantic_core-2.41.5-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:941103c9be18ac8daf7b7adca8228f8ed6bb7a1849020f643b3a14d15b1924d9"}, {file = "pydantic_core-2.41.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:112e305c3314f40c93998e567879e887a3160bb8689ef3d2c04b6cc62c33ac34"}, {file = "pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cbaad15cb0c90aa221d43c00e77bb33c93e8d36e0bf74760cd00e732d10a6a0"}, {file = "pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:03ca43e12fab6023fc79d28ca6b39b05f794ad08ec2feccc59a339b02f2b3d33"}, {file = "pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dc799088c08fa04e43144b164feb0c13f9a0bc40503f8df3e9fde58a3c0c101e"}, {file = "pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:97aeba56665b4c3235a0e52b2c2f5ae9cd071b8a8310ad27bddb3f7fb30e9aa2"}, {file = "pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:406bf18d345822d6c21366031003612b9c77b3e29ffdb0f612367352aab7d586"}, {file = "pydantic_core-2.41.5-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b93590ae81f7010dbe380cdeab6f515902ebcbefe0b9327cc4804d74e93ae69d"}, {file = "pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:01a3d0ab748ee531f4ea6c3e48ad9dac84ddba4b0d82291f87248f2f9de8d740"}, {file = "pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:6561e94ba9dacc9c61bce40e2d6bdc3bfaa0259d3ff36ace3b1e6901936d2e3e"}, {file = "pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:915c3d10f81bec3a74fbd4faebe8391013ba61e5a1a8d48c4455b923bdda7858"}, {file = "pydantic_core-2.41.5-cp313-cp313-win32.whl", hash = "sha256:650ae77860b45cfa6e2cdafc42618ceafab3a2d9a3811fcfbd3bbf8ac3c40d36"}, {file = "pydantic_core-2.41.5-cp313-cp313-win_amd64.whl", hash = "sha256:79ec52ec461e99e13791ec6508c722742ad745571f234ea6255bed38c6480f11"}, {file = "pydantic_core-2.41.5-cp313-cp313-win_arm64.whl", hash = "sha256:3f84d5c1b4ab906093bdc1ff10484838aca54ef08de4afa9de0f5f14d69639cd"}, {file = "pydantic_core-2.41.5-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:3f37a19d7ebcdd20b96485056ba9e8b304e27d9904d233d7b1015db320e51f0a"}, {file = "pydantic_core-2.41.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1d1d9764366c73f996edd17abb6d9d7649a7eb690006ab6adbda117717099b14"}, {file = "pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25e1c2af0fce638d5f1988b686f3b3ea8cd7de5f244ca147c777769e798a9cd1"}, {file = "pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:506d766a8727beef16b7adaeb8ee6217c64fc813646b424d0804d67c16eddb66"}, {file = "pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4819fa52133c9aa3c387b3328f25c1facc356491e6135b459f1de698ff64d869"}, {file = "pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2b761d210c9ea91feda40d25b4efe82a1707da2ef62901466a42492c028553a2"}, {file = "pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22f0fb8c1c583a3b6f24df2470833b40207e907b90c928cc8d3594b76f874375"}, {file = "pydantic_core-2.41.5-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2782c870e99878c634505236d81e5443092fba820f0373997ff75f90f68cd553"}, {file = "pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:0177272f88ab8312479336e1d777f6b124537d47f2123f89cb37e0accea97f90"}, {file = "pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:63510af5e38f8955b8ee5687740d6ebf7c2a0886d15a6d65c32814613681bc07"}, {file = "pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:e56ba91f47764cc14f1daacd723e3e82d1a89d783f0f5afe9c364b8bb491ccdb"}, {file = "pydantic_core-2.41.5-cp314-cp314-win32.whl", hash = "sha256:aec5cf2fd867b4ff45b9959f8b20ea3993fc93e63c7363fe6851424c8a7e7c23"}, {file = "pydantic_core-2.41.5-cp314-cp314-win_amd64.whl", hash = "sha256:8e7c86f27c585ef37c35e56a96363ab8de4e549a95512445b85c96d3e2f7c1bf"}, {file = "pydantic_core-2.41.5-cp314-cp314-win_arm64.whl", hash = "sha256:e672ba74fbc2dc8eea59fb6d4aed6845e6905fc2a8afe93175d94a83ba2a01a0"}, {file = "pydantic_core-2.41.5-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:8566def80554c3faa0e65ac30ab0932b9e3a5cd7f8323764303d468e5c37595a"}, {file = "pydantic_core-2.41.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:b80aa5095cd3109962a298ce14110ae16b8c1aece8b72f9dafe81cf597ad80b3"}, {file = "pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3006c3dd9ba34b0c094c544c6006cc79e87d8612999f1a5d43b769b89181f23c"}, {file = "pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:72f6c8b11857a856bcfa48c86f5368439f74453563f951e473514579d44aa612"}, {file = "pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5cb1b2f9742240e4bb26b652a5aeb840aa4b417c7748b6f8387927bc6e45e40d"}, {file = "pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bd3d54f38609ff308209bd43acea66061494157703364ae40c951f83ba99a1a9"}, {file = "pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ff4321e56e879ee8d2a879501c8e469414d948f4aba74a2d4593184eb326660"}, {file = "pydantic_core-2.41.5-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d0d2568a8c11bf8225044aa94409e21da0cb09dcdafe9ecd10250b2baad531a9"}, {file = "pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:a39455728aabd58ceabb03c90e12f71fd30fa69615760a075b9fec596456ccc3"}, {file = "pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:239edca560d05757817c13dc17c50766136d21f7cd0fac50295499ae24f90fdf"}, {file = "pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:2a5e06546e19f24c6a96a129142a75cee553cc018ffee48a460059b1185f4470"}, {file = "pydantic_core-2.41.5-cp314-cp314t-win32.whl", hash = "sha256:b4ececa40ac28afa90871c2cc2b9ffd2ff0bf749380fbdf57d165fd23da353aa"}, {file = "pydantic_core-2.41.5-cp314-cp314t-win_amd64.whl", hash = "sha256:80aa89cad80b32a912a65332f64a4450ed00966111b6615ca6816153d3585a8c"}, {file = "pydantic_core-2.41.5-cp314-cp314t-win_arm64.whl", hash = "sha256:35b44f37a3199f771c3eaa53051bc8a70cd7b54f333531c59e29fd4db5d15008"}, {file = "pydantic_core-2.41.5-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:8bfeaf8735be79f225f3fefab7f941c712aaca36f1128c9d7e2352ee1aa87bdf"}, {file = "pydantic_core-2.41.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:346285d28e4c8017da95144c7f3acd42740d637ff41946af5ce6e5e420502dd5"}, {file = "pydantic_core-2.41.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a75dafbf87d6276ddc5b2bf6fae5254e3d0876b626eb24969a574fff9149ee5d"}, {file = "pydantic_core-2.41.5-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7b93a4d08587e2b7e7882de461e82b6ed76d9026ce91ca7915e740ecc7855f60"}, {file = "pydantic_core-2.41.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e8465ab91a4bd96d36dde3263f06caa6a8a6019e4113f24dc753d79a8b3a3f82"}, {file = "pydantic_core-2.41.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:299e0a22e7ae2b85c1a57f104538b2656e8ab1873511fd718a1c1c6f149b77b5"}, {file = "pydantic_core-2.41.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:707625ef0983fcfb461acfaf14de2067c5942c6bb0f3b4c99158bed6fedd3cf3"}, {file = "pydantic_core-2.41.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f41eb9797986d6ebac5e8edff36d5cef9de40def462311b3eb3eeded1431e425"}, {file = "pydantic_core-2.41.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0384e2e1021894b1ff5a786dbf94771e2986ebe2869533874d7e43bc79c6f504"}, {file = "pydantic_core-2.41.5-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:f0cd744688278965817fd0839c4a4116add48d23890d468bc436f78beb28abf5"}, {file = "pydantic_core-2.41.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:753e230374206729bf0a807954bcc6c150d3743928a73faffee51ac6557a03c3"}, {file = "pydantic_core-2.41.5-cp39-cp39-win32.whl", hash = "sha256:873e0d5b4fb9b89ef7c2d2a963ea7d02879d9da0da8d9d4933dee8ee86a8b460"}, {file = "pydantic_core-2.41.5-cp39-cp39-win_amd64.whl", hash = "sha256:e4f4a984405e91527a0d62649ee21138f8e3d0ef103be488c1dc11a80d7f184b"}, {file = "pydantic_core-2.41.5-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:b96d5f26b05d03cc60f11a7761a5ded1741da411e7fe0909e27a5e6a0cb7b034"}, {file = "pydantic_core-2.41.5-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:634e8609e89ceecea15e2d61bc9ac3718caaaa71963717bf3c8f38bfde64242c"}, {file = "pydantic_core-2.41.5-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:93e8740d7503eb008aa2df04d3b9735f845d43ae845e6dcd2be0b55a2da43cd2"}, {file = "pydantic_core-2.41.5-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f15489ba13d61f670dcc96772e733aad1a6f9c429cc27574c6cdaed82d0146ad"}, {file = "pydantic_core-2.41.5-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:7da7087d756b19037bc2c06edc6c170eeef3c3bafcb8f532ff17d64dc427adfd"}, {file = "pydantic_core-2.41.5-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:aabf5777b5c8ca26f7824cb4a120a740c9588ed58df9b2d196ce92fba42ff8dc"}, {file = "pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c007fe8a43d43b3969e8469004e9845944f1a80e6acd47c150856bb87f230c56"}, {file = "pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:76d0819de158cd855d1cbb8fcafdf6f5cf1eb8e470abe056d5d161106e38062b"}, {file = "pydantic_core-2.41.5-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b5819cd790dbf0c5eb9f82c73c16b39a65dd6dd4d1439dcdea7816ec9adddab8"}, {file = "pydantic_core-2.41.5-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:5a4e67afbc95fa5c34cf27d9089bca7fcab4e51e57278d710320a70b956d1b9a"}, {file = "pydantic_core-2.41.5-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ece5c59f0ce7d001e017643d8d24da587ea1f74f6993467d85ae8a5ef9d4f42b"}, {file = "pydantic_core-2.41.5-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:16f80f7abe3351f8ea6858914ddc8c77e02578544a0ebc15b4c2e1a0e813b0b2"}, {file = "pydantic_core-2.41.5-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:33cb885e759a705b426baada1fe68cbb0a2e68e34c5d0d0289a364cf01709093"}, {file = "pydantic_core-2.41.5-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:c8d8b4eb992936023be7dee581270af5c6e0697a8559895f527f5b7105ecd36a"}, {file = "pydantic_core-2.41.5-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:242a206cd0318f95cd21bdacff3fcc3aab23e79bba5cac3db5a841c9ef9c6963"}, {file = "pydantic_core-2.41.5-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:d3a978c4f57a597908b7e697229d996d77a6d3c94901e9edee593adada95ce1a"}, {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b2379fa7ed44ddecb5bfe4e48577d752db9fc10be00a6b7446e9663ba143de26"}, {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:266fb4cbf5e3cbd0b53669a6d1b039c45e3ce651fd5442eff4d07c2cc8d66808"}, {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58133647260ea01e4d0500089a8c4f07bd7aa6ce109682b1426394988d8aaacc"}, {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:287dad91cfb551c363dc62899a80e9e14da1f0e2b6ebde82c806612ca2a13ef1"}, {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:03b77d184b9eb40240ae9fd676ca364ce1085f203e1b1256f8ab9984dca80a84"}, {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:a668ce24de96165bb239160b3d854943128f4334822900534f2fe947930e5770"}, {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f14f8f046c14563f8eb3f45f499cc658ab8d10072961e07225e507adb700e93f"}, {file = "pydantic_core-2.41.5-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:56121965f7a4dc965bff783d70b907ddf3d57f6eba29b6d2e5dabfaf07799c51"}, {file = "pydantic_core-2.41.5.tar.gz", hash = "sha256:08daa51ea16ad373ffd5e7606252cc32f07bc72b28284b6bc9c6df804816476e"}, ] [package.dependencies] typing-extensions = ">=4.14.1" [[package]] name = "pydantic-extra-types" version = "2.11.0" description = "Extra Pydantic types." optional = false python-versions = ">=3.9" groups = ["docs"] files = [ {file = "pydantic_extra_types-2.11.0-py3-none-any.whl", hash = "sha256:84b864d250a0fc62535b7ec591e36f2c5b4d1325fa0017eb8cda9aeb63b374a6"}, {file = "pydantic_extra_types-2.11.0.tar.gz", hash = "sha256:4e9991959d045b75feb775683437a97991d02c138e00b59176571db9ce634f0e"}, ] [package.dependencies] pydantic = ">=2.5.2" typing-extensions = "*" [package.extras] all = ["cron-converter (>=1.2.2)", "pendulum (>=3.0.0,<4.0.0)", "phonenumbers (>=8,<10)", "pycountry (>=23)", "pymongo (>=4.0.0,<5.0.0)", "python-ulid (>=1,<2) ; python_version < \"3.9\"", "python-ulid (>=1,<4) ; python_version >= \"3.9\"", "pytz (>=2024.1)", "semver (>=3.0.2)", "semver (>=3.0.2,<3.1.0)", "tzdata (>=2024.1)"] cron = ["cron-converter (>=1.2.2)"] pendulum = ["pendulum (>=3.0.0,<4.0.0)"] phonenumbers = ["phonenumbers (>=8,<10)"] pycountry = ["pycountry (>=23)"] python-ulid = ["python-ulid (>=1,<2) ; python_version < \"3.9\"", "python-ulid (>=1,<4) ; python_version >= \"3.9\""] semver = ["semver (>=3.0.2)"] [[package]] name = "pydantic-settings" version = "2.13.1" description = "Settings management using Pydantic" optional = false python-versions = ">=3.10" groups = ["main"] files = [ {file = "pydantic_settings-2.13.1-py3-none-any.whl", hash = "sha256:d56fd801823dbeae7f0975e1f8c8e25c258eb75d278ea7abb5d9cebb01b56237"}, {file = "pydantic_settings-2.13.1.tar.gz", hash = "sha256:b4c11847b15237fb0171e1462bf540e294affb9b86db4d9aa5c01730bdbe4025"}, ] [package.dependencies] pydantic = ">=2.7.0" python-dotenv = ">=0.21.0" typing-inspection = ">=0.4.0" [package.extras] aws-secrets-manager = ["boto3 (>=1.35.0)", "boto3-stubs[secretsmanager]"] azure-key-vault = ["azure-identity (>=1.16.0)", "azure-keyvault-secrets (>=4.8.0)"] gcp-secret-manager = ["google-cloud-secret-manager (>=2.23.1)"] toml = ["tomli (>=2.0.1)"] yaml = ["pyyaml (>=6.0.1)"] [[package]] name = "pyflakes" version = "3.4.0" description = "passive checker of Python programs" optional = false python-versions = ">=3.9" groups = ["dev"] files = [ {file = "pyflakes-3.4.0-py2.py3-none-any.whl", hash = "sha256:f742a7dbd0d9cb9ea41e9a24a918996e8170c799fa528688d40dd582c8265f4f"}, {file = "pyflakes-3.4.0.tar.gz", hash = "sha256:b24f96fafb7d2ab0ec5075b7350b3d2d2218eab42003821c06344973d3ea2f58"}, ] [[package]] name = "pygments" version = "2.20.0" description = "Pygments is a syntax highlighting package written in Python." optional = false python-versions = ">=3.9" groups = ["dev", "docs"] files = [ {file = "pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176"}, {file = "pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f"}, ] [package.extras] windows-terminal = ["colorama (>=0.4.6)"] [[package]] name = "pytest" version = "9.0.3" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ {file = "pytest-9.0.3-py3-none-any.whl", hash = "sha256:2c5efc453d45394fdd706ade797c0a81091eccd1d6e4bccfcd476e2b8e0ab5d9"}, {file = "pytest-9.0.3.tar.gz", hash = "sha256:b86ada508af81d19edeb213c681b1d48246c1a91d304c6c81a427674c17eb91c"}, ] [package.dependencies] colorama = {version = ">=0.4", markers = "sys_platform == \"win32\""} exceptiongroup = {version = ">=1", markers = "python_version < \"3.11\""} iniconfig = ">=1.0.1" packaging = ">=22" pluggy = ">=1.5,<2" pygments = ">=2.7.2" tomli = {version = ">=1", markers = "python_version < \"3.11\""} [package.extras] dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "requests", "setuptools", "xmlschema"] [[package]] name = "pytest-cov" version = "7.1.0" description = "Pytest plugin for measuring coverage." optional = false python-versions = ">=3.9" groups = ["dev"] files = [ {file = "pytest_cov-7.1.0-py3-none-any.whl", hash = "sha256:a0461110b7865f9a271aa1b51e516c9a95de9d696734a2f71e3e78f46e1d4678"}, {file = "pytest_cov-7.1.0.tar.gz", hash = "sha256:30674f2b5f6351aa09702a9c8c364f6a01c27aae0c1366ae8016160d1efc56b2"}, ] [package.dependencies] coverage = {version = ">=7.10.6", extras = ["toml"]} pluggy = ">=1.2" pytest = ">=7" [package.extras] testing = ["process-tests", "pytest-xdist", "virtualenv"] [[package]] name = "pytest-flake8" version = "1.3.0" description = "pytest plugin to check FLAKE8 requirements" optional = false python-versions = ">=3.9" groups = ["dev"] files = [ {file = "pytest_flake8-1.3.0-py3-none-any.whl", hash = "sha256:de10517c59fce25c0a7abb2a2b2a9d0b0ceb59ff0add7fa8e654d613bb25e218"}, {file = "pytest_flake8-1.3.0.tar.gz", hash = "sha256:88fb35562ce32d915c6ba41ef0d5e1cfcdd8ff884a32b7d46aa99fc77a3d1fe6"}, ] [package.dependencies] flake8 = ">=4.0" pytest = ">=7.0" [package.extras] check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\""] cover = ["pytest-cov"] doc = ["furo", "jaraco.packaging (>=9.3)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] enabler = ["pytest-enabler (>=2.2)"] test = ["pytest (>=6,!=8.1.*)"] type = ["pytest-mypy"] [[package]] name = "python-dotenv" version = "1.2.2" description = "Read key-value pairs from a .env file and set them as environment variables" optional = false python-versions = ">=3.10" groups = ["main"] files = [ {file = "python_dotenv-1.2.2-py3-none-any.whl", hash = "sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a"}, {file = "python_dotenv-1.2.2.tar.gz", hash = "sha256:2c371a91fbd7ba082c2c1dc1f8bf89ca22564a087c2c287cd9b662adde799cf3"}, ] [package.extras] cli = ["click (>=5.0)"] [[package]] name = "pytokens" version = "0.4.1" description = "A Fast, spec compliant Python 3.14+ tokenizer that runs on older Pythons." optional = false python-versions = ">=3.8" groups = ["dev"] files = [ {file = "pytokens-0.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2a44ed93ea23415c54f3face3b65ef2b844d96aeb3455b8a69b3df6beab6acc5"}, {file = "pytokens-0.4.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:add8bf86b71a5d9fb5b89f023a80b791e04fba57960aa790cc6125f7f1d39dfe"}, {file = "pytokens-0.4.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:670d286910b531c7b7e3c0b453fd8156f250adb140146d234a82219459b9640c"}, {file = "pytokens-0.4.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:4e691d7f5186bd2842c14813f79f8884bb03f5995f0575272009982c5ac6c0f7"}, {file = "pytokens-0.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:27b83ad28825978742beef057bfe406ad6ed524b2d28c252c5de7b4a6dd48fa2"}, {file = "pytokens-0.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d70e77c55ae8380c91c0c18dea05951482e263982911fc7410b1ffd1dadd3440"}, {file = "pytokens-0.4.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4a58d057208cb9075c144950d789511220b07636dd2e4708d5645d24de666bdc"}, {file = "pytokens-0.4.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b49750419d300e2b5a3813cf229d4e5a4c728dae470bcc89867a9ad6f25a722d"}, {file = "pytokens-0.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d9907d61f15bf7261d7e775bd5d7ee4d2930e04424bab1972591918497623a16"}, {file = "pytokens-0.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:ee44d0f85b803321710f9239f335aafe16553b39106384cef8e6de40cb4ef2f6"}, {file = "pytokens-0.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:140709331e846b728475786df8aeb27d24f48cbcf7bcd449f8de75cae7a45083"}, {file = "pytokens-0.4.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6d6c4268598f762bc8e91f5dbf2ab2f61f7b95bdc07953b602db879b3c8c18e1"}, {file = "pytokens-0.4.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:24afde1f53d95348b5a0eb19488661147285ca4dd7ed752bbc3e1c6242a304d1"}, {file = "pytokens-0.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5ad948d085ed6c16413eb5fec6b3e02fa00dc29a2534f088d3302c47eb59adf9"}, {file = "pytokens-0.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:3f901fe783e06e48e8cbdc82d631fca8f118333798193e026a50ce1b3757ea68"}, {file = "pytokens-0.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8bdb9d0ce90cbf99c525e75a2fa415144fd570a1ba987380190e8b786bc6ef9b"}, {file = "pytokens-0.4.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5502408cab1cb18e128570f8d598981c68a50d0cbd7c61312a90507cd3a1276f"}, {file = "pytokens-0.4.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:29d1d8fb1030af4d231789959f21821ab6325e463f0503a61d204343c9b355d1"}, {file = "pytokens-0.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:970b08dd6b86058b6dc07efe9e98414f5102974716232d10f32ff39701e841c4"}, {file = "pytokens-0.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:9bd7d7f544d362576be74f9d5901a22f317efc20046efe2034dced238cbbfe78"}, {file = "pytokens-0.4.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:4a14d5f5fc78ce85e426aa159489e2d5961acf0e47575e08f35584009178e321"}, {file = "pytokens-0.4.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:97f50fd18543be72da51dd505e2ed20d2228c74e0464e4262e4899797803d7fa"}, {file = "pytokens-0.4.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dc74c035f9bfca0255c1af77ddd2d6ae8419012805453e4b0e7513e17904545d"}, {file = "pytokens-0.4.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:f66a6bbe741bd431f6d741e617e0f39ec7257ca1f89089593479347cc4d13324"}, {file = "pytokens-0.4.1-cp314-cp314-win_amd64.whl", hash = "sha256:b35d7e5ad269804f6697727702da3c517bb8a5228afa450ab0fa787732055fc9"}, {file = "pytokens-0.4.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:8fcb9ba3709ff77e77f1c7022ff11d13553f3c30299a9fe246a166903e9091eb"}, {file = "pytokens-0.4.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:79fc6b8699564e1f9b521582c35435f1bd32dd06822322ec44afdeba666d8cb3"}, {file = "pytokens-0.4.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d31b97b3de0f61571a124a00ffe9a81fb9939146c122c11060725bd5aea79975"}, {file = "pytokens-0.4.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:967cf6e3fd4adf7de8fc73cd3043754ae79c36475c1c11d514fc72cf5490094a"}, {file = "pytokens-0.4.1-cp314-cp314t-win_amd64.whl", hash = "sha256:584c80c24b078eec1e227079d56dc22ff755e0ba8654d8383b2c549107528918"}, {file = "pytokens-0.4.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:da5baeaf7116dced9c6bb76dc31ba04a2dc3695f3d9f74741d7910122b456edc"}, {file = "pytokens-0.4.1-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:11edda0942da80ff58c4408407616a310adecae1ddd22eef8c692fe266fa5009"}, {file = "pytokens-0.4.1-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0fc71786e629cef478cbf29d7ea1923299181d0699dbe7c3c0f4a583811d9fc1"}, {file = "pytokens-0.4.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:dcafc12c30dbaf1e2af0490978352e0c4041a7cde31f4f81435c2a5e8b9cabb6"}, {file = "pytokens-0.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:42f144f3aafa5d92bad964d471a581651e28b24434d184871bd02e3a0d956037"}, {file = "pytokens-0.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:34bcc734bd2f2d5fe3b34e7b3c0116bfb2397f2d9666139988e7a3eb5f7400e3"}, {file = "pytokens-0.4.1-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:941d4343bf27b605e9213b26bfa1c4bf197c9c599a9627eb7305b0defcfe40c1"}, {file = "pytokens-0.4.1-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3ad72b851e781478366288743198101e5eb34a414f1d5627cdd585ca3b25f1db"}, {file = "pytokens-0.4.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:682fa37ff4d8e95f7df6fe6fe6a431e8ed8e788023c6bcc0f0880a12eab80ad1"}, {file = "pytokens-0.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:30f51edd9bb7f85c748979384165601d028b84f7bd13fe14d3e065304093916a"}, {file = "pytokens-0.4.1-py3-none-any.whl", hash = "sha256:26cef14744a8385f35d0e095dc8b3a7583f6c953c2e3d269c7f82484bf5ad2de"}, {file = "pytokens-0.4.1.tar.gz", hash = "sha256:292052fe80923aae2260c073f822ceba21f3872ced9a68bb7953b348e561179a"}, ] [package.extras] dev = ["black", "build", "mypy", "pytest", "pytest-cov", "setuptools", "tox", "twine", "wheel"] [[package]] name = "pyyaml" version = "6.0.3" description = "YAML parser and emitter for Python" optional = false python-versions = ">=3.8" groups = ["dev"] files = [ {file = "PyYAML-6.0.3-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:c2514fceb77bc5e7a2f7adfaa1feb2fb311607c9cb518dbc378688ec73d8292f"}, {file = "PyYAML-6.0.3-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9c57bb8c96f6d1808c030b1687b9b5fb476abaa47f0db9c0101f5e9f394e97f4"}, {file = "PyYAML-6.0.3-cp38-cp38-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:efd7b85f94a6f21e4932043973a7ba2613b059c4a000551892ac9f1d11f5baf3"}, {file = "PyYAML-6.0.3-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:22ba7cfcad58ef3ecddc7ed1db3409af68d023b7f940da23c6c2a1890976eda6"}, {file = "PyYAML-6.0.3-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:6344df0d5755a2c9a276d4473ae6b90647e216ab4757f8426893b5dd2ac3f369"}, {file = "PyYAML-6.0.3-cp38-cp38-win32.whl", hash = "sha256:3ff07ec89bae51176c0549bc4c63aa6202991da2d9a6129d7aef7f1407d3f295"}, {file = "PyYAML-6.0.3-cp38-cp38-win_amd64.whl", hash = "sha256:5cf4e27da7e3fbed4d6c3d8e797387aaad68102272f8f9752883bc32d61cb87b"}, {file = "pyyaml-6.0.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b"}, {file = "pyyaml-6.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02ea2dfa234451bbb8772601d7b8e426c2bfa197136796224e50e35a78777956"}, {file = "pyyaml-6.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b30236e45cf30d2b8e7b3e85881719e98507abed1011bf463a8fa23e9c3e98a8"}, {file = "pyyaml-6.0.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:66291b10affd76d76f54fad28e22e51719ef9ba22b29e1d7d03d6777a9174198"}, {file = "pyyaml-6.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9c7708761fccb9397fe64bbc0395abcae8c4bf7b0eac081e12b809bf47700d0b"}, {file = "pyyaml-6.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:418cf3f2111bc80e0933b2cd8cd04f286338bb88bdc7bc8e6dd775ebde60b5e0"}, {file = "pyyaml-6.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5e0b74767e5f8c593e8c9b5912019159ed0533c70051e9cce3e8b6aa699fcd69"}, {file = "pyyaml-6.0.3-cp310-cp310-win32.whl", hash = "sha256:28c8d926f98f432f88adc23edf2e6d4921ac26fb084b028c733d01868d19007e"}, {file = "pyyaml-6.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:bdb2c67c6c1390b63c6ff89f210c8fd09d9a1217a465701eac7316313c915e4c"}, {file = "pyyaml-6.0.3-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:44edc647873928551a01e7a563d7452ccdebee747728c1080d881d68af7b997e"}, {file = "pyyaml-6.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:652cb6edd41e718550aad172851962662ff2681490a8a711af6a4d288dd96824"}, {file = "pyyaml-6.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:10892704fc220243f5305762e276552a0395f7beb4dbf9b14ec8fd43b57f126c"}, {file = "pyyaml-6.0.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:850774a7879607d3a6f50d36d04f00ee69e7fc816450e5f7e58d7f17f1ae5c00"}, {file = "pyyaml-6.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b8bb0864c5a28024fac8a632c443c87c5aa6f215c0b126c449ae1a150412f31d"}, {file = "pyyaml-6.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1d37d57ad971609cf3c53ba6a7e365e40660e3be0e5175fa9f2365a379d6095a"}, {file = "pyyaml-6.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:37503bfbfc9d2c40b344d06b2199cf0e96e97957ab1c1b546fd4f87e53e5d3e4"}, {file = "pyyaml-6.0.3-cp311-cp311-win32.whl", hash = "sha256:8098f252adfa6c80ab48096053f512f2321f0b998f98150cea9bd23d83e1467b"}, {file = "pyyaml-6.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:9f3bfb4965eb874431221a3ff3fdcddc7e74e3b07799e0e84ca4a0f867d449bf"}, {file = "pyyaml-6.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7f047e29dcae44602496db43be01ad42fc6f1cc0d8cd6c83d342306c32270196"}, {file = "pyyaml-6.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0"}, {file = "pyyaml-6.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28"}, {file = "pyyaml-6.0.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5fdec68f91a0c6739b380c83b951e2c72ac0197ace422360e6d5a959d8d97b2c"}, {file = "pyyaml-6.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc"}, {file = "pyyaml-6.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8dc52c23056b9ddd46818a57b78404882310fb473d63f17b07d5c40421e47f8e"}, {file = "pyyaml-6.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:41715c910c881bc081f1e8872880d3c650acf13dfa8214bad49ed4cede7c34ea"}, {file = "pyyaml-6.0.3-cp312-cp312-win32.whl", hash = "sha256:96b533f0e99f6579b3d4d4995707cf36df9100d67e0c8303a0c55b27b5f99bc5"}, {file = "pyyaml-6.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:5fcd34e47f6e0b794d17de1b4ff496c00986e1c83f7ab2fb8fcfe9616ff7477b"}, {file = "pyyaml-6.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:64386e5e707d03a7e172c0701abfb7e10f0fb753ee1d773128192742712a98fd"}, {file = "pyyaml-6.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8"}, {file = "pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1"}, {file = "pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c"}, {file = "pyyaml-6.0.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5"}, {file = "pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6"}, {file = "pyyaml-6.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6"}, {file = "pyyaml-6.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be"}, {file = "pyyaml-6.0.3-cp313-cp313-win32.whl", hash = "sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26"}, {file = "pyyaml-6.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c"}, {file = "pyyaml-6.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb"}, {file = "pyyaml-6.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac"}, {file = "pyyaml-6.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310"}, {file = "pyyaml-6.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7"}, {file = "pyyaml-6.0.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788"}, {file = "pyyaml-6.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5"}, {file = "pyyaml-6.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764"}, {file = "pyyaml-6.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35"}, {file = "pyyaml-6.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac"}, {file = "pyyaml-6.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3"}, {file = "pyyaml-6.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3"}, {file = "pyyaml-6.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba"}, {file = "pyyaml-6.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c"}, {file = "pyyaml-6.0.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702"}, {file = "pyyaml-6.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c"}, {file = "pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065"}, {file = "pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65"}, {file = "pyyaml-6.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9"}, {file = "pyyaml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b"}, {file = "pyyaml-6.0.3-cp39-cp39-macosx_10_13_x86_64.whl", hash = "sha256:b865addae83924361678b652338317d1bd7e79b1f4596f96b96c77a5a34b34da"}, {file = "pyyaml-6.0.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c3355370a2c156cffb25e876646f149d5d68f5e0a3ce86a5084dd0b64a994917"}, {file = "pyyaml-6.0.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3c5677e12444c15717b902a5798264fa7909e41153cdf9ef7ad571b704a63dd9"}, {file = "pyyaml-6.0.3-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5ed875a24292240029e4483f9d4a4b8a1ae08843b9c54f43fcc11e404532a8a5"}, {file = "pyyaml-6.0.3-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0150219816b6a1fa26fb4699fb7daa9caf09eb1999f3b70fb6e786805e80375a"}, {file = "pyyaml-6.0.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:fa160448684b4e94d80416c0fa4aac48967a969efe22931448d853ada8baf926"}, {file = "pyyaml-6.0.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:27c0abcb4a5dac13684a37f76e701e054692a9b2d3064b70f5e4eb54810553d7"}, {file = "pyyaml-6.0.3-cp39-cp39-win32.whl", hash = "sha256:1ebe39cb5fc479422b83de611d14e2c0d3bb2a18bbcb01f229ab3cfbd8fee7a0"}, {file = "pyyaml-6.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:2e71d11abed7344e42a8849600193d15b6def118602c4c176f748e4583246007"}, {file = "pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f"}, ] [[package]] name = "referencing" version = "0.37.0" description = "JSON Referencing + Python" optional = false python-versions = ">=3.10" groups = ["main"] files = [ {file = "referencing-0.37.0-py3-none-any.whl", hash = "sha256:381329a9f99628c9069361716891d34ad94af76e461dcb0335825aecc7692231"}, {file = "referencing-0.37.0.tar.gz", hash = "sha256:44aefc3142c5b842538163acb373e24cce6632bd54bdb01b21ad5863489f50d8"}, ] [package.dependencies] attrs = ">=22.2.0" rpds-py = ">=0.7.0" typing-extensions = {version = ">=4.4.0", markers = "python_version < \"3.13\""} [[package]] name = "regress" version = "2025.10.1" description = "Python bindings to Rust's regress ECMA regular expressions library" optional = true python-versions = ">=3.10" groups = ["main"] markers = "extra == \"ecma-regex\"" files = [ {file = "regress-2025.10.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:590abc9fa10255dcf84b4469f08cad9787001c38600080a033cd7a71f51cae02"}, {file = "regress-2025.10.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:dc9046f25971e9d6dc3b57028de8991d0d7c346efcb0c15acbfecbfb8e4c1813"}, {file = "regress-2025.10.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:81733f0e7f583d181bc9fc187b3d766489bcf7e0c85eff26f1e067c942e4e45a"}, {file = "regress-2025.10.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3d48ae257483ff7da43c15b8071b132a1e75e4be2242a44e2587b8492afae32e"}, {file = "regress-2025.10.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:30e70b966015beef7e9287feaf37ed9606744ceaa88be24b10824f5b4c354498"}, {file = "regress-2025.10.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6c1c968ee4dca933e0cd6cea51d9c6494c3d82650ce826e7a5d007c9de720da2"}, {file = "regress-2025.10.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:212fe8c4f823730d1578d0fe8b5edf21b393074b90a8ec704d6d6c1c96ffe7dc"}, {file = "regress-2025.10.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cb23c4ab28e75e35f033e4e392f01f6a9344a961e2f4ded56af5520b5841fe8d"}, {file = "regress-2025.10.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:fdcd839a87fae1e47bf376248589ebcb2e58d3a0fad66837d69856ae99ef3c93"}, {file = "regress-2025.10.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:1809ac971207bb2e098a46e08c2f241a259ac3bda48228f295a3c2cba49c6c0e"}, {file = "regress-2025.10.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:cbf1371ae2cfe1a2d6e1bb21f73a557138bc45347021f1701f196b484789639a"}, {file = "regress-2025.10.1-cp310-cp310-win32.whl", hash = "sha256:8a9c00ede347a5a431e36d4fcf75e2ec9094feac2f6170f2ffbd5e32f7f7a4b4"}, {file = "regress-2025.10.1-cp310-cp310-win_amd64.whl", hash = "sha256:cba77808a756f1f117916c0afb0e79f01be1cb46ee51c77780e8afc59ddac76b"}, {file = "regress-2025.10.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:02da99e41c6a97f6d2146d326541b4035ed2139c92b2f56ca7e464ceb84fe24f"}, {file = "regress-2025.10.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5d961e81b169fce4f6c0e35f52bbfca9e20abf9674dd391c75708f0665ef4f6f"}, {file = "regress-2025.10.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c34b13e7785554997e18725b896d404ba992cee5b691768476f14b48de0c393a"}, {file = "regress-2025.10.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:15efcb8d568e712919cb56b78fffe08a09d5ed1844b43cccc3235c2da90d0e59"}, {file = "regress-2025.10.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5a2ddb0d1c0821b70dd50daa773c5f3fbb2155398c57809a2f54447958c9569f"}, {file = "regress-2025.10.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:70c78c6cf679da47fbde85b75407fdfb4642477315ee94d6cdd62a0606941b83"}, {file = "regress-2025.10.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:707e2846e784ecef666a6892753cf5d8441e4cf02bcc7fa10fd21527429815fc"}, {file = "regress-2025.10.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5c147e4d3799022bac9fc49fd042a51b7f746c41ed231fa6b496720dab0d2f9d"}, {file = "regress-2025.10.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:148f15530807a63e24ca2dea3795546723d84c0b3a8e4152a24b58318f841b3c"}, {file = "regress-2025.10.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:9670d957d156fa90e5582c4337ca1757b643859780896c8d853b015cd01456dc"}, {file = "regress-2025.10.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:af290cfb3b7d4b14319a88feab4e86f54a2c43bd8189be5a0dcd8f847f832847"}, {file = "regress-2025.10.1-cp311-cp311-win32.whl", hash = "sha256:7343ef7eae795e1449308d6d05131195f5af31ab1b2b6b405ff9370b64c1e7e1"}, {file = "regress-2025.10.1-cp311-cp311-win_amd64.whl", hash = "sha256:8f42578d920fc878fe19ed8e2fbe38edd212c451bb2fc5e0084716d5acd26c4c"}, {file = "regress-2025.10.1-cp311-cp311-win_arm64.whl", hash = "sha256:a6f0320f53e8fd8722211c0620fcd9bfecc0db05bf0d59385ee301f86b815671"}, {file = "regress-2025.10.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:45695cd7ddc6a919863f243a09a9e737257f958c0d2af0e71e349c9d0f3048ad"}, {file = "regress-2025.10.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:63503a8f601a10e5d9d72ea6efb415a2838a4766736775322578ce5fe18cb233"}, {file = "regress-2025.10.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28941c80252119ef051ad67195fa8d155a0c8dc9ecb801786d94eeea6738e4c3"}, {file = "regress-2025.10.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6d26daee7d46905c8d4232f44c39ea788f10d39c166735177f603783b4ace4e8"}, {file = "regress-2025.10.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f0599f9cb12722300b6d4fcd6bd9b2be5bf233bc567c3ca503d8e392de23798a"}, {file = "regress-2025.10.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:46b92e1ec6092e6e989e4ad5f52f0a358e88355f70cf4dba9abce84f3cd513cf"}, {file = "regress-2025.10.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ac0e197c7f1b5ffca42341518b6a03e2ea3cdd66516af9278492d2d2bfc9ce2"}, {file = "regress-2025.10.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:05e6c68021dff89fee7bcdab25e0819cff4c7f0761dc41f0fb609b0e9ebb6272"}, {file = "regress-2025.10.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:39600db4e404155168d6f75c3dbb2ae03ef3e288b4a57c7a6562a1144bf07682"}, {file = "regress-2025.10.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:d48e91d14a366570685f76adaf9d108e3abc5522572e7e1d0d78c3cc3ebf0833"}, {file = "regress-2025.10.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ce4e38ada2a39159d8a2523084e2b5ed94b3f7f7b196ba6b99c2d6c4ff634a87"}, {file = "regress-2025.10.1-cp312-cp312-win32.whl", hash = "sha256:c35c8cd42900d9195e5bf48d701dda28c204854fba7cc27d18f309745f57b8b5"}, {file = "regress-2025.10.1-cp312-cp312-win_amd64.whl", hash = "sha256:089b6c5f0965962e8046493e5a1222a24e88d6f235fa8fe2424ec869e6ff613c"}, {file = "regress-2025.10.1-cp312-cp312-win_arm64.whl", hash = "sha256:469b03b1deffb6d20ea4f95aa44ef0e0e5a9b47d56f709276b06a96338b570a0"}, {file = "regress-2025.10.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:9100da34f69e18ad6d545f5d74f8ee729e42ce200a73752dd6d94f8a373d0e71"}, {file = "regress-2025.10.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9e25096697b034848d8fc7910cdb38b7abc2bd2d7ade8767893359918ed4efd0"}, {file = "regress-2025.10.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c4c40a8c9f3e0119d2384a52b55dcc770461e1ead6ae7b41314999223116a15"}, {file = "regress-2025.10.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:25d8518285aa3ce67ddbede90a1a9ca6a5d23a1b8275dd5a9722af0c64b37b2a"}, {file = "regress-2025.10.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8051fac3696730bb84d7675c62c7073792a0e105233d4f8e1055f2cab9b04fce"}, {file = "regress-2025.10.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8e337ce3b150ca0ff599b1150b995ff6a2e32b5940e17ac3f30a29133960709e"}, {file = "regress-2025.10.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:290a15652c3fafe387db02061d4ed9a100804ed5a162d069b5a0ac28b5df162a"}, {file = "regress-2025.10.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b4bc2008b59e5124c1672d7fd9f203e5d4a4ff88ebaf4666e3281141e2d8db20"}, {file = "regress-2025.10.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:56ef2f8ef9a102a7d42cbbc2f3c0c5e1b186bd8eaa78d564da566b0bf20653dc"}, {file = "regress-2025.10.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:0680ac0b0a0058acb55b64aa56956732cf56b0baa84ea95e3fa124ab16da58aa"}, {file = "regress-2025.10.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:47c03bfd853651241fc11436fb14ef7c9b312bb9a9c2828aa5c93943e945f1ef"}, {file = "regress-2025.10.1-cp313-cp313-win32.whl", hash = "sha256:3d12e6a834ed5f6d9dc7e86ea8fd77d37bb13900129930151d87c3261c3a799e"}, {file = "regress-2025.10.1-cp313-cp313-win_amd64.whl", hash = "sha256:ee3b7325ea849097d674020c72b2e6deb8f1018f085a7ecbd22831cd217b7f80"}, {file = "regress-2025.10.1-cp313-cp313-win_arm64.whl", hash = "sha256:e5f35e04fe6382c236d60c98b3f0a4a22dea75398b99c9c9bf3fb9d386cd7ebb"}, {file = "regress-2025.10.1-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:0ee12c4e1c4e6e3609f41dd58065bc241945e912772f7320238d6544f0745950"}, {file = "regress-2025.10.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:389c2278848cbfed81753a04ce8ea6c037271179cb9ef4decac7d3c65ae3330b"}, {file = "regress-2025.10.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf743b00cac20f8e8d271f275df7bc192ebb4faa7aee8fe98484df338786dec6"}, {file = "regress-2025.10.1-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5541da1f581377bc20d2f77e017453aa8f2c2f4bfe7679dee00e139ec700abe8"}, {file = "regress-2025.10.1-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a67216efa72bb27db170f637d67eb9acdc167da5d617163b057803de7aed1e6d"}, {file = "regress-2025.10.1-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fb61e653a325aea4681cf7b96ba9bbabc1aeb3f3d8fe877a07800024907398b9"}, {file = "regress-2025.10.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e2a0a7da1d42fdff8068ab976a66beea572621514a130b37592489ae134a0e27"}, {file = "regress-2025.10.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:337ef62f785dc6e05c4a09be7a902980cf4d4f15346f4eca9eaf02745485440c"}, {file = "regress-2025.10.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:aaf5d102e05b109dde13363e705969b3ffdbbfeb880270187eed0871e75f0c8f"}, {file = "regress-2025.10.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:adf331c8938e0d8705fc5d05d08fab09c11cb4bcdf8a64fa21902972c4cd38f4"}, {file = "regress-2025.10.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:287f86b5c0bf3bc9c0abd45bf6745ba9c6a5624c3132b07631bac4403b45143f"}, {file = "regress-2025.10.1-cp313-cp313t-win32.whl", hash = "sha256:877e05e7c570ee1e077e8b587cca8a318b7675f3c94c6c4e25d0d145abf7c0b6"}, {file = "regress-2025.10.1-cp313-cp313t-win_amd64.whl", hash = "sha256:97307f87b128389d8b3f385c8e431fc318263281d1a1c0394606bc813aea05fc"}, {file = "regress-2025.10.1-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:56123dbe783a2bab04d1a1850605c483d40f36196bc52d249aa245d06f866f78"}, {file = "regress-2025.10.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:8405a31f0a1475e1c9aa20c4d6e1465ef2f7259581c018a2e273083494ca9a61"}, {file = "regress-2025.10.1-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:12430b2c7263a7b359d30dd0f2b179426d489df30da78cd21023376eb2fe2682"}, {file = "regress-2025.10.1-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c7ecba827aff7f951db40be777c32608a1b16bbeb7f02fcc97a2e9fc6702641f"}, {file = "regress-2025.10.1-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:293be370961c6887efb82e466a15523ff24a702d444f44917ce318b222ffd229"}, {file = "regress-2025.10.1-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:783b9c50760aab988e4d60dcb7c54eba3fe730d80f9a877f1dc52d14263f86b1"}, {file = "regress-2025.10.1-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0ed3b4d0df960aeccb685f8de5001c19f426f1ab09fde715e5abdbf9c59b26a"}, {file = "regress-2025.10.1-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:08e99c44e4c3860352400af96b25a4ebb673c16d53c6367153631ec77d5130b8"}, {file = "regress-2025.10.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:6b52096ecbf39f50756e51efa9286f47c598572f6b8bb2119f855de817f38b8e"}, {file = "regress-2025.10.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:b99a73cfbdc5d99681aeb3aeaa2d88369023c96648cc785433d6a92c8d3a8394"}, {file = "regress-2025.10.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:05d02b4d7179b85acf28d7329a488901d6baef5f5b337dcd52f53ea0ff980bc3"}, {file = "regress-2025.10.1-cp314-cp314-win32.whl", hash = "sha256:e7cc153fabb47b6f8dfc2903186934e07aa57ee1debe9b3569ac4779b43708ae"}, {file = "regress-2025.10.1-cp314-cp314-win_amd64.whl", hash = "sha256:102c4627f026db8d361ab61155e0f1093176555d60ddb1cc4c9b6f5bbe255c1f"}, {file = "regress-2025.10.1-cp314-cp314-win_arm64.whl", hash = "sha256:e5c441a6017a5a29bb38c573892d882485cc26937cb1ee12da8593723bf6c041"}, {file = "regress-2025.10.1-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:77d63b338c2a4e56b4f05632d3fd94061ad47ee2b272b158b9c2e09545a4c6bb"}, {file = "regress-2025.10.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:722c408a3bc92b4904005e68244c28fa6df943290df8d670faf349414c86aabb"}, {file = "regress-2025.10.1-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3afe24e6474f5dbc448f865641c29bcbed4eb3b87ac9eb0e6755c4eff4f7111"}, {file = "regress-2025.10.1-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9fdbbea49bf2fe65f7272b0316e1343aff1ccbb85b58fab325778c416d648ed9"}, {file = "regress-2025.10.1-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6d451a88292c5a93f57cf754c71b3aa8b570ed159f9fd481554948c467e6105d"}, {file = "regress-2025.10.1-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a97649f21c875b7e95e10a59f0f487a518735f51a7aec7fc95fb2c3d9a3914d5"}, {file = "regress-2025.10.1-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a542e38c8bb95f618674a5d2d248f1010547d7ff2e46a6cf4fa4b851459ba440"}, {file = "regress-2025.10.1-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:933561ea90b2ac9a826e956a994b8a66635cd96467374281da992ceea8b0de4c"}, {file = "regress-2025.10.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:b6b5aa9f9408fdf260c73071282a28d29efbb4c30a4b95ab29863bea31987621"}, {file = "regress-2025.10.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:afee501f000666afe18531132edcaf0dc0178dd591cccf5b9596563e7456c118"}, {file = "regress-2025.10.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:4d0bf23a6d996655ed88c822bb0123cc2e92a1df95079ce7408552c35ec05d47"}, {file = "regress-2025.10.1-cp314-cp314t-win32.whl", hash = "sha256:adaa80c97927d623ff72b920bcc637568f124eabe84559c7927a91253ff55d5e"}, {file = "regress-2025.10.1-cp314-cp314t-win_amd64.whl", hash = "sha256:6553c8ba57fa92ab3e9ef5c811d6214c80131bba06496bd5920e6e5a3d53ca8e"}, {file = "regress-2025.10.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b5254f758206ba45776aefbd3c4223898890209b4dd3a743f2dc5cd1ebc5e9fd"}, {file = "regress-2025.10.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:966dcad04fe1821c7af9bf6dd33bbeca5c2649b7a3c5b2af57700e6d93335fd4"}, {file = "regress-2025.10.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d725e10a99ff65b0ad83b8c20f05645d9c67dbc809e2bf3b1db230d3e15081b"}, {file = "regress-2025.10.1-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3605ef64ab64658856ce8d6fda730dfb62c01002e2283bd6400df8e912d1b56a"}, {file = "regress-2025.10.1-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:daece9f2fbaaadd23ef2cb31ffbaecd74f946938ff9b70d22c891c66d1435ad2"}, {file = "regress-2025.10.1-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1460d95d39d956ba0fab8a7b614b7ee5486473b1b210f65d6a3043dc08462f38"}, {file = "regress-2025.10.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac04243bf4ba86196b2491bdacd9450b339b3e5e97192aab82234baac1f0a74f"}, {file = "regress-2025.10.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c3962e4b980bfb844518beb1a3afce069674377ba99189fe339918fe7e7cbb7a"}, {file = "regress-2025.10.1-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:f418c11a6bae820fad1334e0569336e2e7848cf4b81e503bfb038daf0e57ec12"}, {file = "regress-2025.10.1-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:19b875513ebecc2b37a125d5794ce91fb4c203b06cb187e15d13b2a761df4621"}, {file = "regress-2025.10.1-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:415dd30885dfdb57f281f7c284e4495e85a90aa66965e3f10cb1bd862f40c2e4"}, {file = "regress-2025.10.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:faa057895de8e41301f9367b286bb3fd0cd80bc8523c8c80866fe746a33d13b6"}, {file = "regress-2025.10.1-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:de16665fcc008db88729f52bab92e36d0c0534bcb3f334ff6d2c7574b16a3d6d"}, {file = "regress-2025.10.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:1624855927d72bb0f8281785fc110eb89702078abe1c42e2e6cbe872ec374277"}, {file = "regress-2025.10.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d0f63f4c3f2e701c832e54434ee10bd0bd2c850b0ae4029829d2dd0c9a340d83"}, {file = "regress-2025.10.1-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ccfc11e2b632a21d82a56b52a70fc002b990fcf4f6b30661724732776bea6f1d"}, {file = "regress-2025.10.1-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:be96403b244e3d6925e225b4da5fbc4f5dd6f06b07f751f00047aa48fd2c7fe3"}, {file = "regress-2025.10.1-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:15a7c2777e8eeb153fe87327871669c3bd1aab4fe20c1fccf448616bc298350d"}, {file = "regress-2025.10.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:905c4e364526f89b33db8e69468b15d9c294a56af4d533f2700e0e1a363fbae7"}, {file = "regress-2025.10.1-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0d1f3c465f415521ca259209dd2587c9a35785b35e98d62d4a7fba3c2bf1cfc8"}, {file = "regress-2025.10.1-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:701d1e4f2b30abfb39b27759a52e68cab8b76484b3d9b51b2d7f368807613f77"}, {file = "regress-2025.10.1-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:189899161133e7c56e733a3fc939642611585c5599626352ee0849cd34d7f436"}, {file = "regress-2025.10.1-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:4c559282471f4f0c9bf7b588985c4bec16de0a85e1a3e017dca39640e15118ce"}, {file = "regress-2025.10.1.tar.gz", hash = "sha256:dcc0a8af0cdbc3d6e0d4725f113335d0a5ffbba86ae3ca18d2b5b352c5f2c8ed"}, ] [[package]] name = "requests" version = "2.33.0" description = "Python HTTP for Humans." optional = false python-versions = ">=3.10" groups = ["dev", "docs"] files = [ {file = "requests-2.33.0-py3-none-any.whl", hash = "sha256:3324635456fa185245e24865e810cecec7b4caf933d7eb133dcde67d48cee69b"}, {file = "requests-2.33.0.tar.gz", hash = "sha256:c7ebc5e8b0f21837386ad0e1c8fe8b829fa5f544d8df3b2253bff14ef29d7652"}, ] [package.dependencies] certifi = ">=2023.5.7" charset_normalizer = ">=2,<4" idna = ">=2.5,<4" urllib3 = ">=1.26,<3" [package.extras] socks = ["PySocks (>=1.5.6,!=1.5.7)"] test = ["PySocks (>=1.5.6,!=1.5.7)", "pytest (>=3)", "pytest-cov", "pytest-httpbin (==2.1.0)", "pytest-mock", "pytest-xdist"] use-chardet-on-py3 = ["chardet (>=3.0.2,<8)"] [[package]] name = "requirements-parser" version = "0.13.0" description = "This is a small Python module for parsing Pip requirement files." optional = false python-versions = "<4.0,>=3.8" groups = ["dev"] files = [ {file = "requirements_parser-0.13.0-py3-none-any.whl", hash = "sha256:2b3173faecf19ec5501971b7222d38f04cb45bb9d87d0ad629ca71e2e62ded14"}, {file = "requirements_parser-0.13.0.tar.gz", hash = "sha256:0843119ca2cb2331de4eb31b10d70462e39ace698fd660a915c247d2301a4418"}, ] [package.dependencies] packaging = ">=23.2" [[package]] name = "rfc3339-validator" version = "0.1.4" description = "A pure python RFC3339 validator" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" groups = ["main"] files = [ {file = "rfc3339_validator-0.1.4-py2.py3-none-any.whl", hash = "sha256:24f6ec1eda14ef823da9e36ec7113124b39c04d50a4d3d3a3c2859577e7791fa"}, {file = "rfc3339_validator-0.1.4.tar.gz", hash = "sha256:138a2abdf93304ad60530167e51d2dfb9549521a836871b88d7f4695d0022f6b"}, ] [package.dependencies] six = "*" [[package]] name = "rpds-py" version = "0.30.0" description = "Python bindings to Rust's persistent data structures (rpds)" optional = false python-versions = ">=3.10" groups = ["main"] files = [ {file = "rpds_py-0.30.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:679ae98e00c0e8d68a7fda324e16b90fd5260945b45d3b824c892cec9eea3288"}, {file = "rpds_py-0.30.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4cc2206b76b4f576934f0ed374b10d7ca5f457858b157ca52064bdfc26b9fc00"}, {file = "rpds_py-0.30.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:389a2d49eded1896c3d48b0136ead37c48e221b391c052fba3f4055c367f60a6"}, {file = "rpds_py-0.30.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:32c8528634e1bf7121f3de08fa85b138f4e0dc47657866630611b03967f041d7"}, {file = "rpds_py-0.30.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f207f69853edd6f6700b86efb84999651baf3789e78a466431df1331608e5324"}, {file = "rpds_py-0.30.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:67b02ec25ba7a9e8fa74c63b6ca44cf5707f2fbfadae3ee8e7494297d56aa9df"}, {file = "rpds_py-0.30.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c0e95f6819a19965ff420f65578bacb0b00f251fefe2c8b23347c37174271f3"}, {file = "rpds_py-0.30.0-cp310-cp310-manylinux_2_31_riscv64.whl", hash = "sha256:a452763cc5198f2f98898eb98f7569649fe5da666c2dc6b5ddb10fde5a574221"}, {file = "rpds_py-0.30.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e0b65193a413ccc930671c55153a03ee57cecb49e6227204b04fae512eb657a7"}, {file = "rpds_py-0.30.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:858738e9c32147f78b3ac24dc0edb6610000e56dc0f700fd5f651d0a0f0eb9ff"}, {file = "rpds_py-0.30.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:da279aa314f00acbb803da1e76fa18666778e8a8f83484fba94526da5de2cba7"}, {file = "rpds_py-0.30.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7c64d38fb49b6cdeda16ab49e35fe0da2e1e9b34bc38bd78386530f218b37139"}, {file = "rpds_py-0.30.0-cp310-cp310-win32.whl", hash = "sha256:6de2a32a1665b93233cde140ff8b3467bdb9e2af2b91079f0333a0974d12d464"}, {file = "rpds_py-0.30.0-cp310-cp310-win_amd64.whl", hash = "sha256:1726859cd0de969f88dc8673bdd954185b9104e05806be64bcd87badbe313169"}, {file = "rpds_py-0.30.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:a2bffea6a4ca9f01b3f8e548302470306689684e61602aa3d141e34da06cf425"}, {file = "rpds_py-0.30.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dc4f992dfe1e2bc3ebc7444f6c7051b4bc13cd8e33e43511e8ffd13bf407010d"}, {file = "rpds_py-0.30.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:422c3cb9856d80b09d30d2eb255d0754b23e090034e1deb4083f8004bd0761e4"}, {file = "rpds_py-0.30.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:07ae8a593e1c3c6b82ca3292efbe73c30b61332fd612e05abee07c79359f292f"}, {file = "rpds_py-0.30.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:12f90dd7557b6bd57f40abe7747e81e0c0b119bef015ea7726e69fe550e394a4"}, {file = "rpds_py-0.30.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:99b47d6ad9a6da00bec6aabe5a6279ecd3c06a329d4aa4771034a21e335c3a97"}, {file = "rpds_py-0.30.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:33f559f3104504506a44bb666b93a33f5d33133765b0c216a5bf2f1e1503af89"}, {file = "rpds_py-0.30.0-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:946fe926af6e44f3697abbc305ea168c2c31d3e3ef1058cf68f379bf0335a78d"}, {file = "rpds_py-0.30.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:495aeca4b93d465efde585977365187149e75383ad2684f81519f504f5c13038"}, {file = "rpds_py-0.30.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d9a0ca5da0386dee0655b4ccdf46119df60e0f10da268d04fe7cc87886872ba7"}, {file = "rpds_py-0.30.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8d6d1cc13664ec13c1b84241204ff3b12f9bb82464b8ad6e7a5d3486975c2eed"}, {file = "rpds_py-0.30.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3896fa1be39912cf0757753826bc8bdc8ca331a28a7c4ae46b7a21280b06bb85"}, {file = "rpds_py-0.30.0-cp311-cp311-win32.whl", hash = "sha256:55f66022632205940f1827effeff17c4fa7ae1953d2b74a8581baaefb7d16f8c"}, {file = "rpds_py-0.30.0-cp311-cp311-win_amd64.whl", hash = "sha256:a51033ff701fca756439d641c0ad09a41d9242fa69121c7d8769604a0a629825"}, {file = "rpds_py-0.30.0-cp311-cp311-win_arm64.whl", hash = "sha256:47b0ef6231c58f506ef0b74d44e330405caa8428e770fec25329ed2cb971a229"}, {file = "rpds_py-0.30.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a161f20d9a43006833cd7068375a94d035714d73a172b681d8881820600abfad"}, {file = "rpds_py-0.30.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6abc8880d9d036ecaafe709079969f56e876fcf107f7a8e9920ba6d5a3878d05"}, {file = "rpds_py-0.30.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca28829ae5f5d569bb62a79512c842a03a12576375d5ece7d2cadf8abe96ec28"}, {file = "rpds_py-0.30.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a1010ed9524c73b94d15919ca4d41d8780980e1765babf85f9a2f90d247153dd"}, {file = "rpds_py-0.30.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f8d1736cfb49381ba528cd5baa46f82fdc65c06e843dab24dd70b63d09121b3f"}, {file = "rpds_py-0.30.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d948b135c4693daff7bc2dcfc4ec57237a29bd37e60c2fabf5aff2bbacf3e2f1"}, {file = "rpds_py-0.30.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47f236970bccb2233267d89173d3ad2703cd36a0e2a6e92d0560d333871a3d23"}, {file = "rpds_py-0.30.0-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:2e6ecb5a5bcacf59c3f912155044479af1d0b6681280048b338b28e364aca1f6"}, {file = "rpds_py-0.30.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a8fa71a2e078c527c3e9dc9fc5a98c9db40bcc8a92b4e8858e36d329f8684b51"}, {file = "rpds_py-0.30.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:73c67f2db7bc334e518d097c6d1e6fed021bbc9b7d678d6cc433478365d1d5f5"}, {file = "rpds_py-0.30.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:5ba103fb455be00f3b1c2076c9d4264bfcb037c976167a6047ed82f23153f02e"}, {file = "rpds_py-0.30.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7cee9c752c0364588353e627da8a7e808a66873672bcb5f52890c33fd965b394"}, {file = "rpds_py-0.30.0-cp312-cp312-win32.whl", hash = "sha256:1ab5b83dbcf55acc8b08fc62b796ef672c457b17dbd7820a11d6c52c06839bdf"}, {file = "rpds_py-0.30.0-cp312-cp312-win_amd64.whl", hash = "sha256:a090322ca841abd453d43456ac34db46e8b05fd9b3b4ac0c78bcde8b089f959b"}, {file = "rpds_py-0.30.0-cp312-cp312-win_arm64.whl", hash = "sha256:669b1805bd639dd2989b281be2cfd951c6121b65e729d9b843e9639ef1fd555e"}, {file = "rpds_py-0.30.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:f83424d738204d9770830d35290ff3273fbb02b41f919870479fab14b9d303b2"}, {file = "rpds_py-0.30.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e7536cd91353c5273434b4e003cbda89034d67e7710eab8761fd918ec6c69cf8"}, {file = "rpds_py-0.30.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2771c6c15973347f50fece41fc447c054b7ac2ae0502388ce3b6738cd366e3d4"}, {file = "rpds_py-0.30.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0a59119fc6e3f460315fe9d08149f8102aa322299deaa5cab5b40092345c2136"}, {file = "rpds_py-0.30.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:76fec018282b4ead0364022e3c54b60bf368b9d926877957a8624b58419169b7"}, {file = "rpds_py-0.30.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:692bef75a5525db97318e8cd061542b5a79812d711ea03dbc1f6f8dbb0c5f0d2"}, {file = "rpds_py-0.30.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9027da1ce107104c50c81383cae773ef5c24d296dd11c99e2629dbd7967a20c6"}, {file = "rpds_py-0.30.0-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:9cf69cdda1f5968a30a359aba2f7f9aa648a9ce4b580d6826437f2b291cfc86e"}, {file = "rpds_py-0.30.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a4796a717bf12b9da9d3ad002519a86063dcac8988b030e405704ef7d74d2d9d"}, {file = "rpds_py-0.30.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5d4c2aa7c50ad4728a094ebd5eb46c452e9cb7edbfdb18f9e1221f597a73e1e7"}, {file = "rpds_py-0.30.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ba81a9203d07805435eb06f536d95a266c21e5b2dfbf6517748ca40c98d19e31"}, {file = "rpds_py-0.30.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:945dccface01af02675628334f7cf49c2af4c1c904748efc5cf7bbdf0b579f95"}, {file = "rpds_py-0.30.0-cp313-cp313-win32.whl", hash = "sha256:b40fb160a2db369a194cb27943582b38f79fc4887291417685f3ad693c5a1d5d"}, {file = "rpds_py-0.30.0-cp313-cp313-win_amd64.whl", hash = "sha256:806f36b1b605e2d6a72716f321f20036b9489d29c51c91f4dd29a3e3afb73b15"}, {file = "rpds_py-0.30.0-cp313-cp313-win_arm64.whl", hash = "sha256:d96c2086587c7c30d44f31f42eae4eac89b60dabbac18c7669be3700f13c3ce1"}, {file = "rpds_py-0.30.0-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:eb0b93f2e5c2189ee831ee43f156ed34e2a89a78a66b98cadad955972548be5a"}, {file = "rpds_py-0.30.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:922e10f31f303c7c920da8981051ff6d8c1a56207dbdf330d9047f6d30b70e5e"}, {file = "rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cdc62c8286ba9bf7f47befdcea13ea0e26bf294bda99758fd90535cbaf408000"}, {file = "rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:47f9a91efc418b54fb8190a6b4aa7813a23fb79c51f4bb84e418f5476c38b8db"}, {file = "rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1f3587eb9b17f3789ad50824084fa6f81921bbf9a795826570bda82cb3ed91f2"}, {file = "rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:39c02563fc592411c2c61d26b6c5fe1e51eaa44a75aa2c8735ca88b0d9599daa"}, {file = "rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51a1234d8febafdfd33a42d97da7a43f5dcb120c1060e352a3fbc0c6d36e2083"}, {file = "rpds_py-0.30.0-cp313-cp313t-manylinux_2_31_riscv64.whl", hash = "sha256:eb2c4071ab598733724c08221091e8d80e89064cd472819285a9ab0f24bcedb9"}, {file = "rpds_py-0.30.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6bdfdb946967d816e6adf9a3d8201bfad269c67efe6cefd7093ef959683c8de0"}, {file = "rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:c77afbd5f5250bf27bf516c7c4a016813eb2d3e116139aed0096940c5982da94"}, {file = "rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:61046904275472a76c8c90c9ccee9013d70a6d0f73eecefd38c1ae7c39045a08"}, {file = "rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4c5f36a861bc4b7da6516dbdf302c55313afa09b81931e8280361a4f6c9a2d27"}, {file = "rpds_py-0.30.0-cp313-cp313t-win32.whl", hash = "sha256:3d4a69de7a3e50ffc214ae16d79d8fbb0922972da0356dcf4d0fdca2878559c6"}, {file = "rpds_py-0.30.0-cp313-cp313t-win_amd64.whl", hash = "sha256:f14fc5df50a716f7ece6a80b6c78bb35ea2ca47c499e422aa4463455dd96d56d"}, {file = "rpds_py-0.30.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:68f19c879420aa08f61203801423f6cd5ac5f0ac4ac82a2368a9fcd6a9a075e0"}, {file = "rpds_py-0.30.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ec7c4490c672c1a0389d319b3a9cfcd098dcdc4783991553c332a15acf7249be"}, {file = "rpds_py-0.30.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f251c812357a3fed308d684a5079ddfb9d933860fc6de89f2b7ab00da481e65f"}, {file = "rpds_py-0.30.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac98b175585ecf4c0348fd7b29c3864bda53b805c773cbf7bfdaffc8070c976f"}, {file = "rpds_py-0.30.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3e62880792319dbeb7eb866547f2e35973289e7d5696c6e295476448f5b63c87"}, {file = "rpds_py-0.30.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4e7fc54e0900ab35d041b0601431b0a0eb495f0851a0639b6ef90f7741b39a18"}, {file = "rpds_py-0.30.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47e77dc9822d3ad616c3d5759ea5631a75e5809d5a28707744ef79d7a1bcfcad"}, {file = "rpds_py-0.30.0-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:b4dc1a6ff022ff85ecafef7979a2c6eb423430e05f1165d6688234e62ba99a07"}, {file = "rpds_py-0.30.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4559c972db3a360808309e06a74628b95eaccbf961c335c8fe0d590cf587456f"}, {file = "rpds_py-0.30.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:0ed177ed9bded28f8deb6ab40c183cd1192aa0de40c12f38be4d59cd33cb5c65"}, {file = "rpds_py-0.30.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:ad1fa8db769b76ea911cb4e10f049d80bf518c104f15b3edb2371cc65375c46f"}, {file = "rpds_py-0.30.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:46e83c697b1f1c72b50e5ee5adb4353eef7406fb3f2043d64c33f20ad1c2fc53"}, {file = "rpds_py-0.30.0-cp314-cp314-win32.whl", hash = "sha256:ee454b2a007d57363c2dfd5b6ca4a5d7e2c518938f8ed3b706e37e5d470801ed"}, {file = "rpds_py-0.30.0-cp314-cp314-win_amd64.whl", hash = "sha256:95f0802447ac2d10bcc69f6dc28fe95fdf17940367b21d34e34c737870758950"}, {file = "rpds_py-0.30.0-cp314-cp314-win_arm64.whl", hash = "sha256:613aa4771c99f03346e54c3f038e4cc574ac09a3ddfb0e8878487335e96dead6"}, {file = "rpds_py-0.30.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:7e6ecfcb62edfd632e56983964e6884851786443739dbfe3582947e87274f7cb"}, {file = "rpds_py-0.30.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a1d0bc22a7cdc173fedebb73ef81e07faef93692b8c1ad3733b67e31e1b6e1b8"}, {file = "rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d08f00679177226c4cb8c5265012eea897c8ca3b93f429e546600c971bcbae7"}, {file = "rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5965af57d5848192c13534f90f9dd16464f3c37aaf166cc1da1cae1fd5a34898"}, {file = "rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9a4e86e34e9ab6b667c27f3211ca48f73dba7cd3d90f8d5b11be56e5dbc3fb4e"}, {file = "rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e5d3e6b26f2c785d65cc25ef1e5267ccbe1b069c5c21b8cc724efee290554419"}, {file = "rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:626a7433c34566535b6e56a1b39a7b17ba961e97ce3b80ec62e6f1312c025551"}, {file = "rpds_py-0.30.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:acd7eb3f4471577b9b5a41baf02a978e8bdeb08b4b355273994f8b87032000a8"}, {file = "rpds_py-0.30.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fe5fa731a1fa8a0a56b0977413f8cacac1768dad38d16b3a296712709476fbd5"}, {file = "rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:74a3243a411126362712ee1524dfc90c650a503502f135d54d1b352bd01f2404"}, {file = "rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:3e8eeb0544f2eb0d2581774be4c3410356eba189529a6b3e36bbbf9696175856"}, {file = "rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:dbd936cde57abfee19ab3213cf9c26be06d60750e60a8e4dd85d1ab12c8b1f40"}, {file = "rpds_py-0.30.0-cp314-cp314t-win32.whl", hash = "sha256:dc824125c72246d924f7f796b4f63c1e9dc810c7d9e2355864b3c3a73d59ade0"}, {file = "rpds_py-0.30.0-cp314-cp314t-win_amd64.whl", hash = "sha256:27f4b0e92de5bfbc6f86e43959e6edd1425c33b5e69aab0984a72047f2bcf1e3"}, {file = "rpds_py-0.30.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:c2262bdba0ad4fc6fb5545660673925c2d2a5d9e2e0fb603aad545427be0fc58"}, {file = "rpds_py-0.30.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:ee6af14263f25eedc3bb918a3c04245106a42dfd4f5c2285ea6f997b1fc3f89a"}, {file = "rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3adbb8179ce342d235c31ab8ec511e66c73faa27a47e076ccc92421add53e2bb"}, {file = "rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:250fa00e9543ac9b97ac258bd37367ff5256666122c2d0f2bc97577c60a1818c"}, {file = "rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9854cf4f488b3d57b9aaeb105f06d78e5529d3145b1e4a41750167e8c213c6d3"}, {file = "rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:993914b8e560023bc0a8bf742c5f303551992dcb85e247b1e5c7f4a7d145bda5"}, {file = "rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58edca431fb9b29950807e301826586e5bbf24163677732429770a697ffe6738"}, {file = "rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_31_riscv64.whl", hash = "sha256:dea5b552272a944763b34394d04577cf0f9bd013207bc32323b5a89a53cf9c2f"}, {file = "rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ba3af48635eb83d03f6c9735dfb21785303e73d22ad03d489e88adae6eab8877"}, {file = "rpds_py-0.30.0-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:dff13836529b921e22f15cb099751209a60009731a68519630a24d61f0b1b30a"}, {file = "rpds_py-0.30.0-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:1b151685b23929ab7beec71080a8889d4d6d9fa9a983d213f07121205d48e2c4"}, {file = "rpds_py-0.30.0-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:ac37f9f516c51e5753f27dfdef11a88330f04de2d564be3991384b2f3535d02e"}, {file = "rpds_py-0.30.0.tar.gz", hash = "sha256:dd8ff7cf90014af0c0f787eea34794ebf6415242ee1d6fa91eaba725cc441e84"}, ] [[package]] name = "schema" version = "0.7.8" description = "Simple data validation library" optional = false python-versions = "*" groups = ["dev"] files = [ {file = "schema-0.7.8-py2.py3-none-any.whl", hash = "sha256:00bd977fadc7d9521bf289850cd8a8aa5f4948f575476b8daaa5c1b57af2dce1"}, {file = "schema-0.7.8.tar.gz", hash = "sha256:e86cc08edd6fe6e2522648f4e47e3a31920a76e82cce8937535422e310862ab5"}, ] [[package]] name = "six" version = "1.17.0" description = "Python 2 and 3 compatibility utilities" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" groups = ["main"] files = [ {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"}, {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, ] [[package]] name = "snowballstemmer" version = "3.0.1" description = "This package provides 32 stemmers for 30 languages generated from Snowball algorithms." optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*" groups = ["docs"] files = [ {file = "snowballstemmer-3.0.1-py3-none-any.whl", hash = "sha256:6cd7b3897da8d6c9ffb968a6781fa6532dce9c3618a4b127d920dab764a19064"}, {file = "snowballstemmer-3.0.1.tar.gz", hash = "sha256:6d5eeeec8e9f84d4d56b847692bacf79bc2c8e90c7f80ca4444ff8b6f2e52895"}, ] [[package]] name = "sphinx" version = "8.1.3" description = "Python documentation generator" optional = false python-versions = ">=3.10" groups = ["docs"] files = [ {file = "sphinx-8.1.3-py3-none-any.whl", hash = "sha256:09719015511837b76bf6e03e42eb7595ac8c2e41eeb9c29c5b755c6b677992a2"}, {file = "sphinx-8.1.3.tar.gz", hash = "sha256:43c1911eecb0d3e161ad78611bc905d1ad0e523e4ddc202a58a821773dc4c927"}, ] [package.dependencies] alabaster = ">=0.7.14" babel = ">=2.13" colorama = {version = ">=0.4.6", markers = "sys_platform == \"win32\""} docutils = ">=0.20,<0.22" imagesize = ">=1.3" Jinja2 = ">=3.1" packaging = ">=23.0" Pygments = ">=2.17" requests = ">=2.30.0" snowballstemmer = ">=2.2" sphinxcontrib-applehelp = ">=1.0.7" sphinxcontrib-devhelp = ">=1.0.6" sphinxcontrib-htmlhelp = ">=2.0.6" sphinxcontrib-jsmath = ">=1.0.1" sphinxcontrib-qthelp = ">=1.0.6" sphinxcontrib-serializinghtml = ">=1.1.9" tomli = {version = ">=2", markers = "python_version < \"3.11\""} [package.extras] docs = ["sphinxcontrib-websupport"] lint = ["flake8 (>=6.0)", "mypy (==1.11.1)", "pyright (==1.1.384)", "pytest (>=6.0)", "ruff (==0.6.9)", "sphinx-lint (>=0.9)", "tomli (>=2)", "types-Pillow (==10.2.0.20240822)", "types-Pygments (==2.18.0.20240506)", "types-colorama (==0.4.15.20240311)", "types-defusedxml (==0.7.0.20240218)", "types-docutils (==0.21.0.20241005)", "types-requests (==2.32.0.20240914)", "types-urllib3 (==1.26.25.14)"] test = ["cython (>=3.0)", "defusedxml (>=0.7.1)", "pytest (>=8.0)", "setuptools (>=70.0)", "typing_extensions (>=4.9)"] [[package]] name = "sphinx-immaterial" version = "0.13.9" description = "Adaptation of mkdocs-material theme for the Sphinx documentation system" optional = false python-versions = ">=3.10" groups = ["docs"] files = [ {file = "sphinx_immaterial-0.13.9-py3-none-any.whl", hash = "sha256:5ea92d2ddc6befcd0fedbd3e6766ea4746e94d9a8a5cc0ab092a946e1fde4254"}, ] [package.dependencies] appdirs = "*" markupsafe = "*" pydantic = ">=2.4" pydantic-extra-types = "*" requests = "*" sphinx = ">=6" typing-extensions = "*" [package.extras] black = ["black"] clang-format = ["clang-format"] cpp = ["libclang"] json = ["pyyaml"] jsonschema-validation = ["jsonschema"] keys = ["pymdown-extensions"] [[package]] name = "sphinxcontrib-applehelp" version = "2.0.0" description = "sphinxcontrib-applehelp is a Sphinx extension which outputs Apple help books" optional = false python-versions = ">=3.9" groups = ["docs"] files = [ {file = "sphinxcontrib_applehelp-2.0.0-py3-none-any.whl", hash = "sha256:4cd3f0ec4ac5dd9c17ec65e9ab272c9b867ea77425228e68ecf08d6b28ddbdb5"}, {file = "sphinxcontrib_applehelp-2.0.0.tar.gz", hash = "sha256:2f29ef331735ce958efa4734873f084941970894c6090408b079c61b2e1c06d1"}, ] [package.extras] lint = ["mypy", "ruff (==0.5.5)", "types-docutils"] standalone = ["Sphinx (>=5)"] test = ["pytest"] [[package]] name = "sphinxcontrib-devhelp" version = "2.0.0" description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp documents" optional = false python-versions = ">=3.9" groups = ["docs"] files = [ {file = "sphinxcontrib_devhelp-2.0.0-py3-none-any.whl", hash = "sha256:aefb8b83854e4b0998877524d1029fd3e6879210422ee3780459e28a1f03a8a2"}, {file = "sphinxcontrib_devhelp-2.0.0.tar.gz", hash = "sha256:411f5d96d445d1d73bb5d52133377b4248ec79db5c793ce7dbe59e074b4dd1ad"}, ] [package.extras] lint = ["mypy", "ruff (==0.5.5)", "types-docutils"] standalone = ["Sphinx (>=5)"] test = ["pytest"] [[package]] name = "sphinxcontrib-htmlhelp" version = "2.1.0" description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" optional = false python-versions = ">=3.9" groups = ["docs"] files = [ {file = "sphinxcontrib_htmlhelp-2.1.0-py3-none-any.whl", hash = "sha256:166759820b47002d22914d64a075ce08f4c46818e17cfc9470a9786b759b19f8"}, {file = "sphinxcontrib_htmlhelp-2.1.0.tar.gz", hash = "sha256:c9e2916ace8aad64cc13a0d233ee22317f2b9025b9cf3295249fa985cc7082e9"}, ] [package.extras] lint = ["mypy", "ruff (==0.5.5)", "types-docutils"] standalone = ["Sphinx (>=5)"] test = ["html5lib", "pytest"] [[package]] name = "sphinxcontrib-jsmath" version = "1.0.1" description = "A sphinx extension which renders display math in HTML via JavaScript" optional = false python-versions = ">=3.5" groups = ["docs"] files = [ {file = "sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8"}, {file = "sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178"}, ] [package.extras] test = ["flake8", "mypy", "pytest"] [[package]] name = "sphinxcontrib-qthelp" version = "2.0.0" description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp documents" optional = false python-versions = ">=3.9" groups = ["docs"] files = [ {file = "sphinxcontrib_qthelp-2.0.0-py3-none-any.whl", hash = "sha256:b18a828cdba941ccd6ee8445dbe72ffa3ef8cbe7505d8cd1fa0d42d3f2d5f3eb"}, {file = "sphinxcontrib_qthelp-2.0.0.tar.gz", hash = "sha256:4fe7d0ac8fc171045be623aba3e2a8f613f8682731f9153bb2e40ece16b9bbab"}, ] [package.extras] lint = ["mypy", "ruff (==0.5.5)", "types-docutils"] standalone = ["Sphinx (>=5)"] test = ["defusedxml (>=0.7.1)", "pytest"] [[package]] name = "sphinxcontrib-serializinghtml" version = "2.0.0" description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)" optional = false python-versions = ">=3.9" groups = ["docs"] files = [ {file = "sphinxcontrib_serializinghtml-2.0.0-py3-none-any.whl", hash = "sha256:6e2cb0eef194e10c27ec0023bfeb25badbbb5868244cf5bc5bdc04e4464bf331"}, {file = "sphinxcontrib_serializinghtml-2.0.0.tar.gz", hash = "sha256:e9d912827f872c029017a53f0ef2180b327c3f7fd23c87229f7a8e8b70031d4d"}, ] [package.extras] lint = ["mypy", "ruff (==0.5.5)", "types-docutils"] standalone = ["Sphinx (>=5)"] test = ["pytest"] [[package]] name = "tabulate" version = "0.9.0" description = "Pretty-print tabular data" optional = false python-versions = ">=3.7" groups = ["dev"] files = [ {file = "tabulate-0.9.0-py3-none-any.whl", hash = "sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f"}, {file = "tabulate-0.9.0.tar.gz", hash = "sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c"}, ] [package.extras] widechars = ["wcwidth"] [[package]] name = "tbump" version = "6.11.0" description = "Bump software releases" optional = false python-versions = ">=3.7,<4.0" groups = ["dev"] files = [ {file = "tbump-6.11.0-py3-none-any.whl", hash = "sha256:6b181fe6f3ae84ce0b9af8cc2009a8bca41ded34e73f623a7413b9684f1b4526"}, {file = "tbump-6.11.0.tar.gz", hash = "sha256:385e710eedf0a8a6ff959cf1e9f3cfd17c873617132fc0ec5f629af0c355c870"}, ] [package.dependencies] cli-ui = ">=0.10.3" docopt = ">=0.6.2,<0.7.0" schema = ">=0.7.1,<0.8.0" tomlkit = ">=0.11,<0.12" [[package]] name = "tomli" version = "2.4.0" description = "A lil' TOML parser" optional = false python-versions = ">=3.8" groups = ["dev", "docs"] files = [ {file = "tomli-2.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b5ef256a3fd497d4973c11bf142e9ed78b150d36f5773f1ca6088c230ffc5867"}, {file = "tomli-2.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5572e41282d5268eb09a697c89a7bee84fae66511f87533a6f88bd2f7b652da9"}, {file = "tomli-2.4.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:551e321c6ba03b55676970b47cb1b73f14a0a4dce6a3e1a9458fd6d921d72e95"}, {file = "tomli-2.4.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5e3f639a7a8f10069d0e15408c0b96a2a828cfdec6fca05296ebcdcc28ca7c76"}, {file = "tomli-2.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1b168f2731796b045128c45982d3a4874057626da0e2ef1fdd722848b741361d"}, {file = "tomli-2.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:133e93646ec4300d651839d382d63edff11d8978be23da4cc106f5a18b7d0576"}, {file = "tomli-2.4.0-cp311-cp311-win32.whl", hash = "sha256:b6c78bdf37764092d369722d9946cb65b8767bfa4110f902a1b2542d8d173c8a"}, {file = "tomli-2.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:d3d1654e11d724760cdb37a3d7691f0be9db5fbdaef59c9f532aabf87006dbaa"}, {file = "tomli-2.4.0-cp311-cp311-win_arm64.whl", hash = "sha256:cae9c19ed12d4e8f3ebf46d1a75090e4c0dc16271c5bce1c833ac168f08fb614"}, {file = "tomli-2.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:920b1de295e72887bafa3ad9f7a792f811847d57ea6b1215154030cf131f16b1"}, {file = "tomli-2.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7d6d9a4aee98fac3eab4952ad1d73aee87359452d1c086b5ceb43ed02ddb16b8"}, {file = "tomli-2.4.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:36b9d05b51e65b254ea6c2585b59d2c4cb91c8a3d91d0ed0f17591a29aaea54a"}, {file = "tomli-2.4.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1c8a885b370751837c029ef9bc014f27d80840e48bac415f3412e6593bbc18c1"}, {file = "tomli-2.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8768715ffc41f0008abe25d808c20c3d990f42b6e2e58305d5da280ae7d1fa3b"}, {file = "tomli-2.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7b438885858efd5be02a9a133caf5812b8776ee0c969fea02c45e8e3f296ba51"}, {file = "tomli-2.4.0-cp312-cp312-win32.whl", hash = "sha256:0408e3de5ec77cc7f81960c362543cbbd91ef883e3138e81b729fc3eea5b9729"}, {file = "tomli-2.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:685306e2cc7da35be4ee914fd34ab801a6acacb061b6a7abca922aaf9ad368da"}, {file = "tomli-2.4.0-cp312-cp312-win_arm64.whl", hash = "sha256:5aa48d7c2356055feef06a43611fc401a07337d5b006be13a30f6c58f869e3c3"}, {file = "tomli-2.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:84d081fbc252d1b6a982e1870660e7330fb8f90f676f6e78b052ad4e64714bf0"}, {file = "tomli-2.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9a08144fa4cba33db5255f9b74f0b89888622109bd2776148f2597447f92a94e"}, {file = "tomli-2.4.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c73add4bb52a206fd0c0723432db123c0c75c280cbd67174dd9d2db228ebb1b4"}, {file = "tomli-2.4.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1fb2945cbe303b1419e2706e711b7113da57b7db31ee378d08712d678a34e51e"}, {file = "tomli-2.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bbb1b10aa643d973366dc2cb1ad94f99c1726a02343d43cbc011edbfac579e7c"}, {file = "tomli-2.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4cbcb367d44a1f0c2be408758b43e1ffb5308abe0ea222897d6bfc8e8281ef2f"}, {file = "tomli-2.4.0-cp313-cp313-win32.whl", hash = "sha256:7d49c66a7d5e56ac959cb6fc583aff0651094ec071ba9ad43df785abc2320d86"}, {file = "tomli-2.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:3cf226acb51d8f1c394c1b310e0e0e61fecdd7adcb78d01e294ac297dd2e7f87"}, {file = "tomli-2.4.0-cp313-cp313-win_arm64.whl", hash = "sha256:d20b797a5c1ad80c516e41bc1fb0443ddb5006e9aaa7bda2d71978346aeb9132"}, {file = "tomli-2.4.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:26ab906a1eb794cd4e103691daa23d95c6919cc2fa9160000ac02370cc9dd3f6"}, {file = "tomli-2.4.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:20cedb4ee43278bc4f2fee6cb50daec836959aadaf948db5172e776dd3d993fc"}, {file = "tomli-2.4.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:39b0b5d1b6dd03684b3fb276407ebed7090bbec989fa55838c98560c01113b66"}, {file = "tomli-2.4.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a26d7ff68dfdb9f87a016ecfd1e1c2bacbe3108f4e0f8bcd2228ef9a766c787d"}, {file = "tomli-2.4.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:20ffd184fb1df76a66e34bd1b36b4a4641bd2b82954befa32fe8163e79f1a702"}, {file = "tomli-2.4.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:75c2f8bbddf170e8effc98f5e9084a8751f8174ea6ccf4fca5398436e0320bc8"}, {file = "tomli-2.4.0-cp314-cp314-win32.whl", hash = "sha256:31d556d079d72db7c584c0627ff3a24c5d3fb4f730221d3444f3efb1b2514776"}, {file = "tomli-2.4.0-cp314-cp314-win_amd64.whl", hash = "sha256:43e685b9b2341681907759cf3a04e14d7104b3580f808cfde1dfdb60ada85475"}, {file = "tomli-2.4.0-cp314-cp314-win_arm64.whl", hash = "sha256:3d895d56bd3f82ddd6faaff993c275efc2ff38e52322ea264122d72729dca2b2"}, {file = "tomli-2.4.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:5b5807f3999fb66776dbce568cc9a828544244a8eb84b84b9bafc080c99597b9"}, {file = "tomli-2.4.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c084ad935abe686bd9c898e62a02a19abfc9760b5a79bc29644463eaf2840cb0"}, {file = "tomli-2.4.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0f2e3955efea4d1cfbcb87bc321e00dc08d2bcb737fd1d5e398af111d86db5df"}, {file = "tomli-2.4.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0e0fe8a0b8312acf3a88077a0802565cb09ee34107813bba1c7cd591fa6cfc8d"}, {file = "tomli-2.4.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:413540dce94673591859c4c6f794dfeaa845e98bf35d72ed59636f869ef9f86f"}, {file = "tomli-2.4.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:0dc56fef0e2c1c470aeac5b6ca8cc7b640bb93e92d9803ddaf9ea03e198f5b0b"}, {file = "tomli-2.4.0-cp314-cp314t-win32.whl", hash = "sha256:d878f2a6707cc9d53a1be1414bbb419e629c3d6e67f69230217bb663e76b5087"}, {file = "tomli-2.4.0-cp314-cp314t-win_amd64.whl", hash = "sha256:2add28aacc7425117ff6364fe9e06a183bb0251b03f986df0e78e974047571fd"}, {file = "tomli-2.4.0-cp314-cp314t-win_arm64.whl", hash = "sha256:2b1e3b80e1d5e52e40e9b924ec43d81570f0e7d09d11081b797bc4692765a3d4"}, {file = "tomli-2.4.0-py3-none-any.whl", hash = "sha256:1f776e7d669ebceb01dee46484485f43a4048746235e683bcdffacdf1fb4785a"}, {file = "tomli-2.4.0.tar.gz", hash = "sha256:aa89c3f6c277dd275d8e243ad24f3b5e701491a860d5121f2cdd399fbb31fc9c"}, ] markers = {dev = "python_version < \"3.15\"", docs = "python_version < \"3.11\""} [[package]] name = "tomlkit" version = "0.11.8" description = "Style preserving TOML library" optional = false python-versions = ">=3.7" groups = ["dev"] files = [ {file = "tomlkit-0.11.8-py3-none-any.whl", hash = "sha256:8c726c4c202bdb148667835f68d68780b9a003a9ec34167b6c673b38eff2a171"}, {file = "tomlkit-0.11.8.tar.gz", hash = "sha256:9330fc7faa1db67b541b28e62018c17d20be733177d290a13b24c62d1614e0c3"}, ] [[package]] name = "typing-extensions" version = "4.15.0" description = "Backported and Experimental Type Hints for Python 3.9+" optional = false python-versions = ">=3.9" groups = ["main", "dev", "docs"] files = [ {file = "typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548"}, {file = "typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466"}, ] [[package]] name = "typing-inspection" version = "0.4.2" description = "Runtime typing introspection tools" optional = false python-versions = ">=3.9" groups = ["main", "docs"] files = [ {file = "typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7"}, {file = "typing_inspection-0.4.2.tar.gz", hash = "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464"}, ] [package.dependencies] typing-extensions = ">=4.12.0" [[package]] name = "unidecode" version = "1.4.0" description = "ASCII transliterations of Unicode text" optional = false python-versions = ">=3.7" groups = ["dev"] files = [ {file = "Unidecode-1.4.0-py3-none-any.whl", hash = "sha256:c3c7606c27503ad8d501270406e345ddb480a7b5f38827eafe4fa82a137f0021"}, {file = "Unidecode-1.4.0.tar.gz", hash = "sha256:ce35985008338b676573023acc382d62c264f307c8f7963733405add37ea2b23"}, ] [[package]] name = "urllib3" version = "2.6.3" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = ">=3.9" groups = ["dev", "docs"] files = [ {file = "urllib3-2.6.3-py3-none-any.whl", hash = "sha256:bf272323e553dfb2e87d9bfd225ca7b0f467b919d7bbd355436d3fd37cb0acd4"}, {file = "urllib3-2.6.3.tar.gz", hash = "sha256:1b62b6884944a57dbe321509ab94fd4d3b307075e0c2eae991ac71ee15ad38ed"}, ] [package.extras] brotli = ["brotli (>=1.2.0) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=1.2.0.0) ; platform_python_implementation != \"CPython\""] h2 = ["h2 (>=4,<5)"] socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] zstd = ["backports-zstd (>=1.0.0) ; python_version < \"3.14\""] [[package]] name = "virtualenv" version = "20.38.0" description = "Virtual Python Environment builder" optional = false python-versions = ">=3.8" groups = ["dev"] files = [ {file = "virtualenv-20.38.0-py3-none-any.whl", hash = "sha256:d6e78e5889de3a4742df2d3d44e779366325a90cf356f15621fddace82431794"}, {file = "virtualenv-20.38.0.tar.gz", hash = "sha256:94f39b1abaea5185bf7ea5a46702b56f1d0c9aa2f41a6c2b8b0af4ddc74c10a7"}, ] [package.dependencies] distlib = ">=0.3.7,<1" filelock = {version = ">=3.24.2,<4", markers = "python_version >= \"3.10\""} platformdirs = ">=3.9.1,<5" typing-extensions = {version = ">=4.13.2", markers = "python_version < \"3.11\""} [package.extras] docs = ["furo (>=2023.7.26)", "pre-commit-uv (>=4.1.4)", "proselint (>=0.13)", "sphinx (>=7.1.2,!=7.3)", "sphinx-argparse (>=0.4)", "sphinx-autodoc-typehints (>=3.6.2)", "sphinx-copybutton (>=0.5.2)", "sphinx-inline-tabs (>=2025.12.21.14)", "sphinxcontrib-mermaid (>=2)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"] test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8) ; platform_python_implementation == \"PyPy\" or platform_python_implementation == \"GraalVM\" or platform_python_implementation == \"CPython\" and sys_platform == \"win32\" and python_version >= \"3.13\"", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "pytest-xdist (>=3.5)", "setuptools (>=68)", "time-machine (>=2.10) ; platform_python_implementation == \"CPython\""] [extras] docs = [] ecma-regex = ["regress"] [metadata] lock-version = "2.1" python-versions = "^3.10.0" content-hash = "96cf4e09bdcae07474f44bd3de949b358cf8bb865f49ba4d34f3d1233c618652" python-openapi-openapi-schema-validator-9480dee/pyproject.toml000066400000000000000000000057431517371647300247250ustar00rootroot00000000000000[build-system] requires = ["poetry-core>=1.0.0"] build-backend = "poetry.core.masonry.api" [tool.coverage.run] branch = true source =["openapi_schema_validator"] [tool.coverage.xml] output = "reports/coverage.xml" [tool.deptry.per_rule_ignores] DEP002 = ["rfc3339-validator"] [tool.mypy] files = "openapi_schema_validator" strict = true [[tool.mypy.overrides]] module = "jsonschema.*" ignore_missing_imports = true [[tool.mypy.overrides]] module = "jsonschema_specifications" ignore_missing_imports = true [[tool.mypy.overrides]] module = "rfc3339_validator" ignore_missing_imports = true [[tool.mypy.overrides]] module = "regress" ignore_missing_imports = true [tool.tbump] github_url = "https://github.com/python-openapi/openapi-schema-validator" [tool.tbump.version] current = "0.9.0" regex = ''' (?P\d+) \. (?P\d+) \. (?P\d+) ''' [tool.tbump.git] message_template = "Version {new_version}" tag_template = "{new_version}" [[tool.tbump.file]] src = "openapi_schema_validator/__init__.py" [[tool.tbump.file]] src = "pyproject.toml" [tool.poetry] name = "openapi-schema-validator" version = "0.9.0" description = "OpenAPI schema validation for Python" authors = ["Artur Maciag "] license = "BSD-3-Clause" readme = "README.rst" repository = "https://github.com/python-openapi/openapi-schema-validator" keywords = ["openapi", "swagger", "schema"] classifiers = [ "Development Status :: 4 - Beta", "Intended Audience :: Developers", "Topic :: Software Development :: Libraries :: Python Modules", "Operating System :: OS Independent", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3.14", "Topic :: Software Development :: Libraries", "Typing :: Typed", ] include = [ {path = "tests", format = "sdist"}, ] [tool.poetry.dependencies] python = "^3.10.0" jsonschema = "^4.19.1" rfc3339-validator = "*" # requred by jsonschema for date-time checker jsonschema-specifications = ">=2024.10.1" referencing = "^0.37.0" regress = {version = ">=2025.10.1", optional = true} pydantic = "^2.0.0" pydantic-settings = "^2.0.0" [tool.poetry.extras] docs = ["sphinx", "sphinx-immaterial"] ecma-regex = ["regress"] [tool.poetry.group.dev.dependencies] black = ">=24.4,<27.0" isort = ">=5.13.2,<9.0.0" pre-commit = "*" pytest = "^9" pytest-flake8 = "*" pytest-cov = "*" mypy = "^1.14" flynt = "^1.0" deptry = ">=0.16.2,<0.26.0" tbump = "^6.11.0" [tool.poetry.group.docs.dependencies] sphinx = ">=5.3,<9.0" sphinx-immaterial = ">=0.11,<0.14" [tool.pytest.ini_options] addopts = """ --capture=no --verbose --color=yes --showlocals --junitxml=reports/junit.xml --cov=openapi_schema_validator --cov-report=term-missing --cov-report=xml """ [tool.black] line-length = 79 [tool.isort] profile = "black" line_length = 79 force_single_line = true python-openapi-openapi-schema-validator-9480dee/tests/000077500000000000000000000000001517371647300231425ustar00rootroot00000000000000python-openapi-openapi-schema-validator-9480dee/tests/integration/000077500000000000000000000000001517371647300254655ustar00rootroot00000000000000python-openapi-openapi-schema-validator-9480dee/tests/integration/test_validators.py000066400000000000000000001334301517371647300312520ustar00rootroot00000000000000import re import warnings from base64 import b64encode from typing import Any from typing import cast from unittest.mock import patch import pytest from jsonschema import SchemaError from jsonschema import ValidationError from jsonschema.exceptions import ( _WrappedReferencingError as WrappedReferencingError, ) from jsonschema.validators import Draft202012Validator from jsonschema.validators import extend from jsonschema.validators import validator_for from referencing import Registry from referencing import Resource from referencing.exceptions import InvalidAnchor from referencing.exceptions import NoSuchAnchor from referencing.exceptions import PointerToNowhere from referencing.jsonschema import DRAFT202012 from openapi_schema_validator import OAS30ReadValidator from openapi_schema_validator import OAS30StrictValidator from openapi_schema_validator import OAS30Validator from openapi_schema_validator import OAS30WriteValidator from openapi_schema_validator import OAS31Validator from openapi_schema_validator import OAS32Validator from openapi_schema_validator import oas30_format_checker from openapi_schema_validator import oas30_strict_format_checker from openapi_schema_validator import oas31_format_checker from openapi_schema_validator import oas32_format_checker from openapi_schema_validator import validate from openapi_schema_validator._dialects import OAS31_BASE_DIALECT_ID from openapi_schema_validator._dialects import OAS31_BASE_DIALECT_METASCHEMA from openapi_schema_validator._dialects import OAS32_BASE_DIALECT_ID from openapi_schema_validator._dialects import OAS32_BASE_DIALECT_METASCHEMA from openapi_schema_validator._dialects import register_openapi_dialect from openapi_schema_validator._regex import has_ecma_regex class TestOAS30ValidatorFormatChecker: @pytest.fixture def format_checker(self): return OAS30Validator.FORMAT_CHECKER def test_required_checkers(self, format_checker): required_formats_set = { "int32", "int64", "float", "double", "byte", "binary", "date", "date-time", "password", } assert required_formats_set.issubset( set(format_checker.checkers.keys()) ) class BaseTestOASValidatorValidate: @pytest.mark.parametrize( "format,value", [ ("int32", "test"), ("int32", True), ("int32", 3.12), ("int32", ["test"]), ("int64", "test"), ("int64", True), ("int64", 3.12), ("int64", ["test"]), ("float", "test"), ("float", 3), ("float", True), ("float", ["test"]), ("double", "test"), ("double", 3), ("double", True), ("double", ["test"]), ("password", 3.12), ("password", True), ("password", 3), ("password", ["test"]), ], ) def test_formats_ignored( self, format, value, validator_class, format_checker ): schema = {"format": format} validator = validator_class(schema, format_checker=format_checker) result = validator.validate(value) assert result is None @pytest.mark.parametrize("format", ["float", "double"]) @pytest.mark.parametrize("value", [3, 3.14, 1.0]) def test_number_float_and_double_valid( self, format, value, validator_class, format_checker ): schema = {"type": "number", "format": format} validator = validator_class(schema, format_checker=format_checker) result = validator.validate(value) assert result is None @pytest.mark.parametrize("value", ["test"]) def test_string(self, validator_class, value): schema = {"type": "string"} validator = validator_class(schema) result = validator.validate(value) assert result is None @pytest.mark.parametrize("value", [True, 3, 3.12, None]) def test_string_invalid(self, validator_class, value): schema = {"type": "string"} validator = validator_class(schema) with pytest.raises(ValidationError): validator.validate(value) def test_invalid_pattern_raises_expected_error(self, validator_class): schema = {"type": "string", "pattern": "["} validator = validator_class(schema) if has_ecma_regex(): with pytest.raises( ValidationError, match="is not a valid regular expression", ): validator.validate("foo") else: with pytest.raises(re.error): validator.validate("foo") def test_invalid_pattern_rejected_by_validate_helper( self, validator_class ): schema = {"type": "string", "pattern": "["} with pytest.raises(SchemaError, match="is not a 'regex'"): validate("foo", schema, cls=validator_class) @pytest.mark.skipif( not has_ecma_regex(), reason="requires optional ecma-regex extra" ) def test_z_escape_behaves_as_ecma_literal_escape(self, validator_class): schema = {"type": "string", "pattern": r"^foo\z"} validator = validator_class(schema) with pytest.raises(ValidationError, match="does not match"): validator.validate("foo") result = validator.validate("fooz") assert result is None result = validate("fooz", schema, cls=validator_class) assert result is None @pytest.mark.skipif( not has_ecma_regex(), reason="requires optional ecma-regex extra" ) def test_escaped_z_pattern_is_allowed_with_ecma_regex( self, validator_class ): schema = {"type": "string", "pattern": r"^foo\\z$"} validator = validator_class(schema) result = validator.validate(r"foo\z") assert result is None def test_referencing(self, validator_class): name_schema = Resource.from_contents( { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "string", } ) age_schema = DRAFT202012.create_resource( { "type": "integer", "format": "int32", "minimum": 0, "maximum": 120, } ) birth_date_schema = Resource.from_contents( { "type": "string", "format": "date", }, default_specification=DRAFT202012, ) registry = Registry().with_resources( [ ("urn:name-schema", name_schema), ("urn:age-schema", age_schema), ("urn:birth-date-schema", birth_date_schema), ], ) schema = { "type": "object", "required": ["name"], "properties": { "name": {"$ref": "urn:name-schema"}, "age": {"$ref": "urn:age-schema"}, "birth-date": {"$ref": "urn:birth-date-schema"}, }, "additionalProperties": False, } validator = validator_class(schema, registry=registry) result = validator.validate({"name": "John", "age": 23}) assert result is None class TestOAS30ValidatorValidate(BaseTestOASValidatorValidate): @pytest.fixture def validator_class(self): return OAS30Validator @pytest.fixture def format_checker(self): return oas30_format_checker @pytest.mark.parametrize( "format,value", [ ("binary", True), ("binary", 3), ("binary", 3.12), ("binary", ["test"]), ("byte", True), ("byte", 3), ("byte", 3.12), ("byte", ["test"]), ], ) def test_oas30_formats_ignored( self, format, value, validator_class, format_checker ): schema = {"format": format} validator = validator_class(schema, format_checker=format_checker) result = validator.validate(value) assert result is None @pytest.mark.parametrize("value", [b"test"]) def test_string_disallow_binary(self, validator_class, value): schema = {"type": "string"} validator = validator_class(schema) with pytest.raises(ValidationError): validator.validate(value) @pytest.mark.parametrize("value", [b"test"]) def test_string_binary_valid(self, validator_class, format_checker, value): schema = {"type": "string", "format": "binary"} validator = validator_class(schema, format_checker=format_checker) result = validator.validate(value) assert result is None @pytest.mark.parametrize("value", [True, 3, 3.12, None]) def test_string_binary_invalid( self, validator_class, format_checker, value ): schema = {"type": "string", "format": "binary"} validator = validator_class(schema, format_checker=format_checker) with pytest.raises(ValidationError): validator.validate(value) @pytest.mark.parametrize( "schema_type", [ "boolean", "array", "integer", "number", "string", ], ) def test_null(self, validator_class, schema_type): schema = {"type": schema_type} validator = validator_class(schema) value = None with pytest.raises(ValidationError): validator.validate(value) @pytest.mark.parametrize("is_nullable", [True, False]) def test_nullable_untyped(self, validator_class, is_nullable): schema = {"nullable": is_nullable} validator = validator_class(schema) value = None result = validator.validate(value) assert result is None @pytest.mark.parametrize( "schema_type", [ "boolean", "array", "integer", "number", "string", ], ) def test_nullable(self, validator_class, schema_type): schema = {"type": schema_type, "nullable": True} validator = validator_class(schema) value = None result = validator.validate(value) assert result is None def test_nullable_enum_without_none(self, validator_class): schema = {"type": "integer", "nullable": True, "enum": [1, 2, 3]} validator = validator_class(schema) value = None with pytest.raises(ValidationError): validator.validate(value) def test_nullable_enum_with_none(self, validator_class): schema = {"type": "integer", "nullable": True, "enum": [1, 2, 3, None]} validator = validator_class(schema) value = None result = validator.validate(value) assert result is None @pytest.mark.parametrize( "value", [ b64encode(b"string").decode(), b64encode(b"\x00\x01\x02").decode(), "", "AQ==", "SGVsbG8=", ], ) def test_string_format_byte_valid(self, validator_class, value): schema = {"type": "string", "format": "byte"} validator = validator_class( schema, format_checker=oas30_format_checker ) result = validator.validate(value) assert result is None @pytest.mark.parametrize( "value", [ "string", "SGVsbG8", "SGVsbG8===", "SGVsbG8$", "SGVsbG8 ", "SGVsbG8\n", "SGVsbG8_", "SGVsbG8-", ], ) def test_string_format_byte_invalid(self, validator_class, value): schema = {"type": "string", "format": "byte"} validator = validator_class( schema, format_checker=oas30_format_checker ) with pytest.raises(ValidationError, match="is not a 'byte'"): validator.validate(value) def test_allof_required(self, validator_class): schema = { "allOf": [ { "type": "object", "properties": {"some_prop": {"type": "string"}}, }, {"type": "object", "required": ["some_prop"]}, ] } validator = validator_class( schema, format_checker=oas30_format_checker ) with pytest.raises( ValidationError, match="'some_prop' is a required property" ): validator.validate({"another_prop": "bla"}) def test_required(self, validator_class): schema = { "type": "object", "properties": {"some_prop": {"type": "string"}}, "required": ["some_prop"], } validator = validator_class( schema, format_checker=oas30_format_checker ) with pytest.raises( ValidationError, match="'some_prop' is a required property" ): validator.validate({"another_prop": "bla"}) assert validator.validate({"some_prop": "hello"}) is None def test_oneof_required(self, validator_class): instance = { "n3IwfId": "string", } schema = { "type": "object", "properties": { "n3IwfId": {"type": "string"}, "wagfId": {"type": "string"}, }, "oneOf": [ {"required": ["n3IwfId"]}, {"required": ["wagfId"]}, ], } validator = validator_class( schema, format_checker=oas30_format_checker ) result = validator.validate(instance) assert result is None @pytest.mark.parametrize( "mapping_ref", [ "#/components/schemas/Missing", "#missing-anchor", "#bad/frag", ], ) def test_discriminator_handles_unresolvable_reference_kinds( self, mapping_ref ): schema = { "oneOf": [{"$ref": "#/components/schemas/MountainHiking"}], "discriminator": { "propertyName": "discipline", "mapping": {"mountain_hiking": mapping_ref}, }, "components": { "schemas": { "MountainHiking": { "type": "object", "properties": { "discipline": {"type": "string"}, "length": {"type": "integer"}, }, "required": ["discipline", "length"], }, }, }, } validator = OAS30Validator( schema, format_checker=oas30_format_checker, ) with pytest.raises( ValidationError, match=f"reference '{mapping_ref}' could not be resolved", ): validator.validate( { "discipline": "mountain_hiking", "length": 10, } ) @pytest.mark.parametrize( "mapping_ref, expected_cause", [ ("#/components/schemas/Missing", PointerToNowhere), ("#missing-anchor", NoSuchAnchor), ("#bad/frag", InvalidAnchor), ], ) def test_discriminator_unresolvable_reference_causes( self, mapping_ref, expected_cause ): schema = { "oneOf": [{"$ref": "#/components/schemas/MountainHiking"}], "discriminator": { "propertyName": "discipline", "mapping": {"mountain_hiking": mapping_ref}, }, "components": { "schemas": { "MountainHiking": { "type": "object", "properties": { "discipline": {"type": "string"}, "length": {"type": "integer"}, }, "required": ["discipline", "length"], }, }, }, } validator = OAS30Validator( schema, format_checker=oas30_format_checker, ) with pytest.raises(WrappedReferencingError) as exc_info: cast(Any, validator)._validate_reference( ref=mapping_ref, instance={"discipline": "mountain_hiking", "length": 10}, ) assert isinstance(exc_info.value.__cause__, expected_cause) @pytest.mark.parametrize( "schema_type", [ "oneOf", "anyOf", "allOf", ], ) def test_oneof_discriminator(self, validator_class, schema_type): # We define a few components schemas components = { "MountainHiking": { "type": "object", "properties": { "discipline": { "type": "string", # we allow both the explicitly matched mountain_hiking discipline # and the implicitly matched MoutainHiking discipline "enum": ["mountain_hiking", "MountainHiking"], }, "length": { "type": "integer", }, }, "required": ["discipline", "length"], }, "AlpineClimbing": { "type": "object", "properties": { "discipline": { "type": "string", "enum": ["alpine_climbing"], }, "height": { "type": "integer", }, }, "required": ["discipline", "height"], }, "Route": { # defined later }, } components["Route"][schema_type] = [ {"$ref": "#/components/schemas/MountainHiking"}, {"$ref": "#/components/schemas/AlpineClimbing"}, ] # Add the components in a minimalis schema schema = { "$ref": "#/components/schemas/Route", "components": {"schemas": components}, } if schema_type != "allOf": # use jsonschema validator when no discriminator is defined validator = validator_class( schema, format_checker=oas30_format_checker ) with pytest.raises( ValidationError, match="is not valid under any of the given schemas", ): validator.validate( {"something": "matching_none_of_the_schemas"} ) assert False if schema_type == "anyOf": # use jsonschema validator when no discriminator is defined validator = validator_class( schema, format_checker=oas30_format_checker ) with pytest.raises( ValidationError, match="is not valid under any of the given schemas", ): validator.validate( {"something": "matching_none_of_the_schemas"} ) assert False discriminator = { "propertyName": "discipline", "mapping": { "mountain_hiking": "#/components/schemas/MountainHiking", "alpine_climbing": "#/components/schemas/AlpineClimbing", }, } schema["components"]["schemas"]["Route"][ "discriminator" ] = discriminator # Optional: check we return useful result when the schema is wrong validator = validator_class( schema, format_checker=oas30_format_checker ) with pytest.raises( ValidationError, match="is not of type 'object'", ): validator.validate("not-an-object") with pytest.raises( ValidationError, match="does not contain discriminating property" ): validator.validate({"something": "missing"}) assert False # Check we get a non-generic, somehow usable, error message when a discriminated schema is failing with pytest.raises( ValidationError, match="'bad_string' is not of type 'integer'" ): validator.validate( {"discipline": "mountain_hiking", "length": "bad_string"} ) assert False # Check explicit MountainHiking resolution validator.validate({"discipline": "mountain_hiking", "length": 10}) # Check implicit MountainHiking resolution validator.validate({"discipline": "MountainHiking", "length": 10}) # Check non resolvable implicit schema with pytest.raises( ValidationError, match="reference '#/components/schemas/other' could not be resolved", ): result = validator.validate({"discipline": "other"}) assert False @pytest.mark.parametrize("is_nullable", [True, False]) def test_nullable_ref(self, validator_class, is_nullable): """ Tests that a field that points to a schema reference is null checked based on the $ref schema rather than on this schema :param is_nullable: if the schema is marked as nullable. If not, validate an exception is raised on None """ schema = { "$ref": "#/$defs/Pet", "$defs": { "NullableText": {"type": "string", "nullable": is_nullable}, "Pet": { "properties": { "testfield": {"$ref": "#/$defs/NullableText"}, }, }, }, } validator = validator_class( schema, format_checker=oas30_format_checker, ) result = validator.validate({"testfield": "John"}) assert result is None if is_nullable: result = validator.validate({"testfield": None}) assert result is None else: with pytest.raises( ValidationError, match="None for not nullable", ): validator.validate({"testfield": None}) assert False @pytest.mark.parametrize( "schema_type, not_nullable_regex", [ ("oneOf", "None is not valid under any of the given schemas"), ("anyOf", "None is not valid under any of the given schemas"), ("allOf", "None for not nullable"), ], ) @pytest.mark.parametrize("is_nullable", [True, False]) def test_nullable_schema_combos( self, validator_class, is_nullable, schema_type, not_nullable_regex ): """ This test ensures that nullablilty semantics are correct for oneOf, anyOf and allOf Specifically, nullable should checked on the children schemas :param is_nullable: if the schema is marked as nullable. If not, validate an exception is raised on None :param schema_type: the schema type to validate :param not_nullable_regex: the expected raised exception if fields are marked as not nullable """ schema = { "$ref": "#/$defs/Pet", "$defs": { "NullableText": { "type": "string", "nullable": ( False if schema_type == "oneOf" else is_nullable ), }, "NullableEnum": { "type": "string", "nullable": is_nullable, "enum": ["John", "Alice", None], }, "Pet": { "properties": { "testfield": { schema_type: [ {"$ref": "#/$defs/NullableText"}, {"$ref": "#/$defs/NullableEnum"}, ] } }, }, }, } validator = validator_class( schema, format_checker=oas30_format_checker, ) if is_nullable: result = validator.validate({"testfield": None}) assert result is None else: with pytest.raises(ValidationError, match=not_nullable_regex): validator.validate({"testfield": None}) assert False class TestOAS30ReadWriteValidatorValidate: def test_read_only(self): schema = { "type": "object", "properties": {"some_prop": {"type": "string", "readOnly": True}}, } validator = OAS30WriteValidator( schema, format_checker=oas30_format_checker, ) with pytest.raises( ValidationError, match="Tried to write read-only property with hello", ): validator.validate({"some_prop": "hello"}) validator = OAS30ReadValidator( schema, format_checker=oas30_format_checker, ) assert validator.validate({"some_prop": "hello"}) is None validator = OAS30Validator( schema, format_checker=oas30_format_checker, ) assert validator.validate({"some_prop": "hello"}) is None def test_write_only(self): schema = { "type": "object", "properties": {"some_prop": {"type": "string", "writeOnly": True}}, } validator = OAS30ReadValidator( schema, format_checker=oas30_format_checker, ) with pytest.raises( ValidationError, match="Tried to read write-only property with hello", ): validator.validate({"some_prop": "hello"}) validator = OAS30WriteValidator( schema, format_checker=oas30_format_checker, ) assert validator.validate({"some_prop": "hello"}) is None validator = OAS30Validator( schema, format_checker=oas30_format_checker, ) assert validator.validate({"some_prop": "hello"}) is None def test_required_read_only(self): schema = { "type": "object", "properties": {"some_prop": {"type": "string", "readOnly": True}}, "required": ["some_prop"], } validator = OAS30ReadValidator( schema, format_checker=oas30_format_checker, ) with pytest.raises( ValidationError, match="'some_prop' is a required property" ): validator.validate({"another_prop": "hello"}) validator = OAS30WriteValidator( schema, format_checker=oas30_format_checker, ) assert validator.validate({"another_prop": "hello"}) is None def test_required_write_only(self): schema = { "type": "object", "properties": {"some_prop": {"type": "string", "writeOnly": True}}, "required": ["some_prop"], } validator = OAS30WriteValidator( schema, format_checker=oas30_format_checker, ) with pytest.raises( ValidationError, match="'some_prop' is a required property" ): validator.validate({"another_prop": "hello"}) validator = OAS30ReadValidator( schema, format_checker=oas30_format_checker, ) assert validator.validate({"another_prop": "hello"}) is None def test_read_only_false(self): schema = { "type": "object", "properties": {"some_prop": {"type": "string", "readOnly": False}}, } validator = OAS30WriteValidator( schema, format_checker=oas30_format_checker, ) assert validator.validate({"some_prop": "hello"}) is None def test_write_only_false(self): schema = { "type": "object", "properties": { "some_prop": {"type": "string", "writeOnly": False} }, } validator = OAS30ReadValidator( schema, format_checker=oas30_format_checker, ) assert validator.validate({"some_prop": "hello"}) is None class TestOAS31ValidatorFormatChecker: @pytest.fixture def format_checker(self): return OAS31Validator.FORMAT_CHECKER def test_required_checkers(self, format_checker): required_formats_set = { # standard formats "int32", "int64", "float", "double", "password", } assert required_formats_set.issubset( set(format_checker.checkers.keys()) ) class TestOAS31ValidatorValidate(BaseTestOASValidatorValidate): @pytest.fixture def validator_class(self): return OAS31Validator @pytest.fixture def format_checker(self): return oas31_format_checker @pytest.mark.parametrize("value", [b"test"]) def test_string_disallow_binary(self, validator_class, value): schema = {"type": "string"} validator = validator_class(schema) with pytest.raises(ValidationError): validator.validate(value) @pytest.mark.parametrize("value", [b"test"]) def test_string_binary_rejects_bytes( self, validator_class, format_checker, value ): schema = {"type": "string", "format": "binary"} validator = validator_class(schema, format_checker=format_checker) with pytest.raises(ValidationError): validator.validate(value) @pytest.mark.parametrize("value", [True, 3, 3.12, None]) def test_string_binary_invalid( self, validator_class, format_checker, value ): schema = {"type": "string", "format": "binary"} validator = validator_class(schema, format_checker=format_checker) with pytest.raises(ValidationError): validator.validate(value) @pytest.mark.parametrize( "schema_type", [ "boolean", "array", "integer", "number", "string", ], ) def test_null(self, validator_class, schema_type): schema = {"type": schema_type} validator = validator_class(schema) value = None with pytest.raises(ValidationError): validator.validate(value) @pytest.mark.parametrize( "schema_type", [ "boolean", "array", "integer", "number", "string", ], ) def test_nullable(self, validator_class, schema_type): schema = {"type": [schema_type, "null"]} validator = validator_class(schema) value = None result = validator.validate(value) assert result is None def test_schema_validation(self, validator_class, format_checker): schema = { "type": "object", "required": ["name"], "properties": { "name": {"type": "string"}, "age": { "type": "integer", "format": "int32", "minimum": 0, "nullable": True, }, "birth-date": { "type": "string", "format": "date", }, }, "additionalProperties": False, } validator = validator_class( schema, format_checker=format_checker, ) result = validator.validate({"name": "John", "age": 23}) assert result is None with pytest.raises(ValidationError) as excinfo: validator.validate({"name": "John", "city": "London"}) error = "Additional properties are not allowed ('city' was unexpected)" assert error in str(excinfo.value) with pytest.raises(ValidationError) as excinfo: validator.validate({"name": "John", "birth-date": "-12"}) error = "'-12' is not a 'date'" assert error in str(excinfo.value) def test_schema_ref(self, validator_class, format_checker): schema = { "$ref": "#/$defs/Pet", "$defs": { "Pet": { "required": ["id", "name"], "properties": { "id": {"type": "integer", "format": "int64"}, "name": {"type": "string"}, "tag": {"type": "string"}, }, } }, } validator = validator_class( schema, format_checker=format_checker, ) result = validator.validate({"id": 1, "name": "John"}) assert result is None with pytest.raises(ValidationError) as excinfo: validator.validate({"name": "John"}) error = "'id' is a required property" assert error in str(excinfo.value) @pytest.mark.parametrize( "value", [ [1600, "Pennsylvania", "Avenue", "NW"], [1600, "Pennsylvania", "Avenue"], ], ) def test_array_prefixitems(self, validator_class, format_checker, value): schema = { "type": "array", "prefixItems": [ {"type": "number"}, {"type": "string"}, {"enum": ["Street", "Avenue", "Boulevard"]}, {"enum": ["NW", "NE", "SW", "SE"]}, ], "items": False, } validator = validator_class( schema, format_checker=format_checker, ) result = validator.validate(value) assert result is None @pytest.mark.parametrize( "value", [ [1600, "Pennsylvania", "Avenue", "NW", "Washington"], ], ) def test_array_prefixitems_invalid(self, validator_class, value): schema = { "type": "array", "prefixItems": [ {"type": "number"}, {"type": "string"}, {"enum": ["Street", "Avenue", "Boulevard"]}, {"enum": ["NW", "NE", "SW", "SE"]}, ], "items": False, } validator = validator_class( schema, format_checker=oas31_format_checker, ) with pytest.raises(ValidationError) as excinfo: validator.validate(value) errors = [ # jsonschema < 4.20.0 "Expected at most 4 items, but found 5", # jsonschema >= 4.20.0 "Expected at most 4 items but found 1 extra", ] assert any(error in str(excinfo.value) for error in errors) def test_discriminator_is_annotation_only(self, validator_class): schema = { "components": { "schemas": { "A": { "type": "object", "properties": {"kind": {"type": "string"}}, "required": ["kind"], }, "B": { "type": "object", "properties": { "kind": {"type": "string"}, "other": {"type": "string"}, }, "required": ["kind"], }, } }, "oneOf": [ {"$ref": "#/components/schemas/A"}, {"$ref": "#/components/schemas/B"}, ], "discriminator": {"propertyName": "kind"}, } validator = validator_class(schema) # A payload valid for both schemas A and B instance = {"kind": "B"} # oneOf fails because it matches BOTH A and B, discriminator does not restrict it with pytest.raises(ValidationError): validator.validate(instance) @pytest.mark.parametrize( "mapping_ref", [ "#/components/schemas/Missing", "#missing-anchor", "#bad/frag", ], ) def test_discriminator_unresolvable_reference_ignored( self, validator_class, mapping_ref ): schema = { "oneOf": [{"$ref": "#/components/schemas/MountainHiking"}], "discriminator": { "propertyName": "discipline", "mapping": {"mountain_hiking": mapping_ref}, }, "components": { "schemas": { "MountainHiking": { "type": "object", "properties": { "discipline": {"type": "string"}, "length": {"type": "integer"}, }, "required": ["discipline", "length"], }, }, }, } validator = validator_class(schema) # It should not raise any referencing errors because discriminator mapping is annotation-only validator.validate( {"discipline": "mountain_hiking", "length": 10}, ) class TestOAS32ValidatorValidate(TestOAS31ValidatorValidate): """OAS 3.2 uses the OAS 3.2 published dialect resources.""" @pytest.fixture def validator_class(self): return OAS32Validator @pytest.fixture def format_checker(self): return oas32_format_checker def test_validator_is_distinct_from_oas31(self): assert OAS32Validator is not OAS31Validator def test_format_checker_is_distinct_from_oas31(self): assert oas32_format_checker is not oas31_format_checker def test_validator_shares_oas31_behavior(self): assert OAS32Validator.VALIDATORS == OAS31Validator.VALIDATORS def test_validator_has_oas32_dialect_metaschema(self): assert OAS32Validator.META_SCHEMA["$id"] == OAS32_BASE_DIALECT_ID def test_format_validation_int32(self, validator_class): schema = {"type": "integer", "format": "int32"} validator = validator_class( schema, format_checker=oas32_format_checker ) result = validator.validate(42) assert result is None with pytest.raises(ValidationError): validator.validate(9999999999) def test_format_validation_date(self, validator_class): schema = {"type": "string", "format": "date"} validator = validator_class( schema, format_checker=oas32_format_checker ) result = validator.validate("2024-01-15") assert result is None with pytest.raises(ValidationError): validator.validate("not-a-date") def test_schema_with_allof(self, validator_class): schema = { "allOf": [ {"type": "object", "properties": {"id": {"type": "integer"}}}, {"type": "object", "properties": {"name": {"type": "string"}}}, ] } validator = validator_class(schema) result = validator.validate({"id": 1, "name": "test"}) assert result is None with pytest.raises(ValidationError): validator.validate({"id": "not-an-integer"}) def test_check_schema_accepts_oas32_discriminator_default_mapping(self): schema = { "type": "object", "discriminator": { "propertyName": "kind", "defaultMapping": "#/components/schemas/Pet", }, } OAS32Validator.check_schema(schema) def test_oas31_check_schema_rejects_discriminator_default_mapping(self): schema = { "type": "object", "discriminator": { "propertyName": "kind", "defaultMapping": "#/components/schemas/Pet", }, } with pytest.raises(SchemaError): OAS31Validator.check_schema(schema) def test_oas32_check_schema_does_not_fetch_remote_metaschemas(self): schema = { "type": "object", "discriminator": { "propertyName": "kind", "defaultMapping": "#/components/schemas/Pet", }, } with patch("urllib.request.urlopen") as urlopen: OAS32Validator.check_schema(schema) urlopen.assert_not_called() class TestOAS30StrictValidator: """ Tests for OAS30StrictValidator which follows OAS spec strictly: - type: string only accepts str (not bytes) - format: binary also only accepts str (no special bytes handling) """ def test_strict_string_rejects_bytes(self): """Strict validator rejects bytes for plain string type.""" schema = {"type": "string"} validator = OAS30StrictValidator(schema) with pytest.raises(ValidationError): validator.validate(b"test") def test_strict_string_accepts_str(self): """Strict validator accepts str for string type.""" schema = {"type": "string"} validator = OAS30StrictValidator(schema) result = validator.validate("test") assert result is None def test_strict_binary_format_rejects_bytes(self): """Strict validator rejects bytes even with binary format.""" schema = {"type": "string", "format": "binary"} validator = OAS30StrictValidator( schema, format_checker=oas30_format_checker ) with pytest.raises(ValidationError): validator.validate(b"test") def test_strict_binary_format_rejects_str(self): """ Strict validator with binary format rejects strings. Binary format is for bytes in OAS, not plain strings. """ schema = {"type": "string", "format": "binary"} validator = OAS30StrictValidator( schema, format_checker=oas30_strict_format_checker ) # Binary format expects actual binary data (bytes in Python) # Plain strings fail format validation because they are not valid base64 # Note: "test" is actually valid base64, so use "not base64" which is not with pytest.raises(ValidationError, match="is not a 'binary'"): validator.validate("not base64") class TestValidatorForDiscovery: def test_oas31_base_dialect_resolves_to_oas31_validator(self): schema = {"$schema": OAS31_BASE_DIALECT_ID} validator_class = validator_for(schema) assert validator_class is OAS31Validator def test_oas31_base_dialect_discovery_has_no_deprecation_warning(self): schema = {"$schema": OAS31_BASE_DIALECT_ID} with warnings.catch_warnings(record=True) as caught: warnings.simplefilter("always") validator_for(schema) assert not any( issubclass(warning.category, DeprecationWarning) for warning in caught ) def test_oas32_base_dialect_resolves_to_oas32_validator(self): schema = {"$schema": OAS32_BASE_DIALECT_ID} validator_class = validator_for(schema) assert validator_class is OAS32Validator def test_oas32_base_dialect_discovery_has_no_deprecation_warning(self): schema = {"$schema": OAS32_BASE_DIALECT_ID} with warnings.catch_warnings(record=True) as caught: warnings.simplefilter("always") validator_for(schema) assert not any( issubclass(warning.category, DeprecationWarning) for warning in caught ) def test_oas31_base_dialect_keeps_oas_keyword_behavior(self): schema = { "$schema": OAS31_BASE_DIALECT_ID, "type": "object", "required": ["kind"], "properties": {"kind": {"type": "string"}}, "discriminator": {"propertyName": "kind"}, "xml": {"name": "Pet"}, "example": {"kind": "cat"}, } validator_class = validator_for(schema) validator = validator_class( schema, format_checker=oas31_format_checker ) result = validator.validate({"kind": "cat"}) assert result is None def test_draft_2020_12_discovery_is_unchanged(self): schema = {"$schema": "https://json-schema.org/draft/2020-12/schema"} validator_class = validator_for(schema) assert validator_class is Draft202012Validator def test_openapi_dialect_registration_is_idempotent(self): register_openapi_dialect( validator=OAS31Validator, dialect_id=OAS31_BASE_DIALECT_ID, version_name="oas31", metaschema=OAS31_BASE_DIALECT_METASCHEMA, ) register_openapi_dialect( validator=OAS31Validator, dialect_id=OAS31_BASE_DIALECT_ID, version_name="oas31", metaschema=OAS31_BASE_DIALECT_METASCHEMA, ) validator_class = validator_for({"$schema": OAS31_BASE_DIALECT_ID}) assert validator_class is OAS31Validator def test_openapi_dialect_registration_does_not_replace_validator(self): another_oas31_validator = extend(OAS31Validator, {}) registered_validator = register_openapi_dialect( validator=another_oas31_validator, dialect_id=OAS31_BASE_DIALECT_ID, version_name="oas31", metaschema=OAS31_BASE_DIALECT_METASCHEMA, ) assert registered_validator is OAS31Validator assert ( validator_for({"$schema": OAS31_BASE_DIALECT_ID}) is OAS31Validator ) def test_openapi_oas32_dialect_registration_is_idempotent(self): register_openapi_dialect( validator=OAS32Validator, dialect_id=OAS32_BASE_DIALECT_ID, version_name="oas32", metaschema=OAS32_BASE_DIALECT_METASCHEMA, ) register_openapi_dialect( validator=OAS32Validator, dialect_id=OAS32_BASE_DIALECT_ID, version_name="oas32", metaschema=OAS32_BASE_DIALECT_METASCHEMA, ) validator_class = validator_for({"$schema": OAS32_BASE_DIALECT_ID}) assert validator_class is OAS32Validator python-openapi-openapi-schema-validator-9480dee/tests/unit/000077500000000000000000000000001517371647300241215ustar00rootroot00000000000000python-openapi-openapi-schema-validator-9480dee/tests/unit/test_settings.py000066400000000000000000000013341517371647300273730ustar00rootroot00000000000000from openapi_schema_validator.settings import get_settings from openapi_schema_validator.settings import reset_settings_cache def test_compiled_validator_cache_size_env_is_cached(monkeypatch): monkeypatch.setenv( "OPENAPI_SCHEMA_VALIDATOR_COMPILED_VALIDATOR_CACHE_MAX_SIZE", "11", ) reset_settings_cache() first = get_settings() assert first.compiled_validator_cache_max_size == 11 monkeypatch.setenv( "OPENAPI_SCHEMA_VALIDATOR_COMPILED_VALIDATOR_CACHE_MAX_SIZE", "3", ) second = get_settings() assert second.compiled_validator_cache_max_size == 11 reset_settings_cache() third = get_settings() assert third.compiled_validator_cache_max_size == 3 python-openapi-openapi-schema-validator-9480dee/tests/unit/test_shortcut.py000066400000000000000000000256511517371647300274160ustar00rootroot00000000000000import inspect import re from unittest.mock import patch import pytest from jsonschema.exceptions import SchemaError from jsonschema.exceptions import ValidationError from referencing import Registry from referencing import Resource from openapi_schema_validator import OAS32Validator from openapi_schema_validator import validate from openapi_schema_validator._regex import has_ecma_regex from openapi_schema_validator.settings import reset_settings_cache from openapi_schema_validator.shortcuts import clear_validate_cache from openapi_schema_validator.validators import OAS30ReadValidator from openapi_schema_validator.validators import OAS30Validator from openapi_schema_validator.validators import OAS30WriteValidator from openapi_schema_validator.validators import OAS31Validator from openapi_schema_validator.validators import OAS32Validator @pytest.fixture(scope="function") def schema(): return { "type": "object", "properties": { "email": {"type": "string"}, "enabled": { "type": "boolean", }, }, "example": {"enabled": False, "email": "foo@bar.com"}, } @pytest.fixture(autouse=True) def clear_validate_cache_fixture(): reset_settings_cache() clear_validate_cache() yield clear_validate_cache() reset_settings_cache() def test_validate_does_not_add_nullable_to_schema(schema): """ Verify that calling validate does not add the 'nullable' key to the schema """ validate({"email": "foo@bar.com"}, schema) assert "nullable" not in schema["properties"]["email"].keys() def test_validate_does_not_mutate_schema(schema): """ Verify that calling validate does not mutate the schema """ original_schema = schema.copy() validate({"email": "foo@bar.com"}, schema) assert schema == original_schema def test_validate_does_not_fetch_remote_metaschemas(schema): with patch("urllib.request.urlopen") as urlopen: validate({"email": "foo@bar.com"}, schema) urlopen.assert_not_called() def test_validate_defaults_to_oas32_validator(): signature = inspect.signature(validate) assert signature.parameters["cls"].default is OAS32Validator def test_oas32_validate_does_not_fetch_remote_metaschemas(schema): with patch("urllib.request.urlopen") as urlopen: validate({"email": "foo@bar.com"}, schema, cls=OAS32Validator) urlopen.assert_not_called() def test_validate_blocks_implicit_remote_http_references_by_default(): schema = {"$ref": "http://example.com/remote-schema.json"} with patch("urllib.request.urlopen") as urlopen: with pytest.raises(Exception, match="Unresolvable"): validate({}, schema) urlopen.assert_not_called() def test_validate_blocks_implicit_file_references_by_default(): schema = {"$ref": "file:///etc/hosts"} with patch("urllib.request.urlopen") as urlopen: with pytest.raises(Exception, match="Unresolvable"): validate({}, schema) urlopen.assert_not_called() def test_validate_local_references_still_work_by_default(): schema = {"$defs": {"Value": {"type": "integer"}}, "$ref": "#/$defs/Value"} with patch("urllib.request.urlopen") as urlopen: result = validate(1, schema) assert result is None urlopen.assert_not_called() def test_validate_honors_explicit_registry(): schema = { "type": "object", "properties": {"name": {"$ref": "urn:name-schema"}}, } name_schema = Resource.from_contents( { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "string", } ) registry = Registry().with_resources( [("urn:name-schema", name_schema)], ) result = validate({"name": "John"}, schema, registry=registry) assert result is None def test_validate_can_allow_implicit_remote_references(): schema = {"$ref": "http://example.com/remote-schema.json"} with patch("urllib.request.urlopen") as urlopen: with pytest.raises(Exception): validate({}, schema, allow_remote_references=True) assert urlopen.called def test_validate_skip_schema_check(): schema = {"type": "string", "pattern": "["} with pytest.raises(SchemaError, match="is not a 'regex'"): validate("foo", schema) if has_ecma_regex(): with pytest.raises( ValidationError, match="is not a valid regular expression" ): validate("foo", schema, check_schema=False) else: with pytest.raises(re.error): validate("foo", schema, check_schema=False) def test_validate_cache_avoids_rechecking_schema(schema): with patch( "openapi_schema_validator.shortcuts.check_openapi_schema" ) as check_schema_mock: validate({"email": "foo@bar.com"}, schema, cls=OAS32Validator) validate({"email": "foo@bar.com"}, schema, cls=OAS32Validator) check_schema_mock.assert_called_once() def test_validate_cache_promotes_unchecked_validator(schema): with patch( "openapi_schema_validator.shortcuts.check_openapi_schema" ) as check_schema_mock: validate( {"email": "foo@bar.com"}, schema, cls=OAS32Validator, check_schema=False, ) validate({"email": "foo@bar.com"}, schema, cls=OAS32Validator) validate({"email": "foo@bar.com"}, schema, cls=OAS32Validator) check_schema_mock.assert_called_once() def test_validate_cache_max_size_from_env(monkeypatch): schema_a = {"type": "string"} schema_b = {"type": "integer"} monkeypatch.setenv( "OPENAPI_SCHEMA_VALIDATOR_COMPILED_VALIDATOR_CACHE_MAX_SIZE", "1", ) reset_settings_cache() with patch( "openapi_schema_validator.shortcuts.check_openapi_schema" ) as check_schema_mock: validate("foo", schema_a, cls=OAS32Validator) validate(1, schema_b, cls=OAS32Validator) validate("foo", schema_a, cls=OAS32Validator) assert check_schema_mock.call_count == 3 @pytest.mark.parametrize( "schema, cls, instance, enforce, expected_error", [ ( { "type": "object", "properties": { "id": {"type": "string"}, "nickname": {"type": "string"}, }, "required": ["id"], }, OAS30Validator, {"id": "42"}, False, None, ), ( { "type": "object", "properties": { "id": {"type": "string"}, "nickname": {"type": "string"}, }, "required": ["id"], }, OAS30Validator, {"id": "42"}, True, "'nickname' is a required property", ), ( { "type": "object", "properties": { "id": {"type": "string", "readOnly": True}, "password": {"type": "string", "writeOnly": True}, "normal": {"type": "string"}, }, }, OAS30ReadValidator, {"id": "123"}, True, "'normal' is a required property", ), ( { "type": "object", "properties": { "id": {"type": "string", "readOnly": True}, "password": {"type": "string", "writeOnly": True}, "normal": {"type": "string"}, }, }, OAS30ReadValidator, {"normal": "abc"}, True, "'id' is a required property", ), ( { "type": "object", "properties": { "id": {"type": "string", "readOnly": True}, "password": {"type": "string", "writeOnly": True}, "normal": {"type": "string"}, }, }, OAS30ReadValidator, {"id": "123", "normal": "abc"}, True, None, ), ( { "type": "object", "properties": { "id": {"type": "string", "readOnly": True}, "password": {"type": "string", "writeOnly": True}, "normal": {"type": "string"}, }, }, OAS30WriteValidator, {"normal": "abc"}, True, "'password' is a required property", ), ( { "type": "object", "properties": { "id": {"type": "string", "readOnly": True}, "password": {"type": "string", "writeOnly": True}, "normal": {"type": "string"}, }, }, OAS30WriteValidator, {"password": "secret"}, True, "'normal' is a required property", ), ( { "type": "object", "properties": { "id": {"type": "string", "readOnly": True}, "password": {"type": "string", "writeOnly": True}, "normal": {"type": "string"}, }, }, OAS30WriteValidator, {"password": "secret", "normal": "abc"}, True, None, ), ( { "type": "object", "properties": { "foo": True, }, }, OAS31Validator, {}, False, None, ), ( { "type": "object", "properties": { "foo": True, }, }, OAS31Validator, {}, True, "'foo' is a required property", ), ( { "type": "object", "properties": { "foo": {"type": "string"}, }, }, OAS32Validator, {}, False, None, ), ( { "type": "object", "properties": { "foo": {"type": "string"}, }, }, OAS32Validator, {}, True, "'foo' is a required property", ), ], ) def test_enforce_properties_required( schema, cls, instance, enforce, expected_error ): if expected_error: with pytest.raises(ValidationError) as exc: validate( instance, schema, cls=cls, enforce_properties_required=enforce, ) assert expected_error in str(exc.value) else: validate( instance, schema, cls=cls, enforce_properties_required=enforce )