├── tests ├── __init__.py └── test_immutabledict.py ├── immutabledict ├── py.typed └── __init__.py ├── .github ├── CODEOWNERS ├── FUNDING.yml ├── dependabot.yml └── workflows │ ├── doc.yml │ └── ci.yml ├── docs ├── changelog.rst ├── api │ ├── immutabledict.rst │ └── immutable_ordered_dict.rst ├── Makefile ├── index.rst └── conf.py ├── tox.ini ├── Makefile ├── SECURITY.md ├── LICENSE ├── README.md ├── .gitignore ├── pyproject.toml ├── CHANGELOG.md └── poetry.lock /tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /immutabledict/py.typed: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @corenting 2 | -------------------------------------------------------------------------------- /docs/changelog.rst: -------------------------------------------------------------------------------- 1 | .. include:: ../CHANGELOG.md 2 | :parser: myst_parser.sphinx_ 3 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | tidelift: pypi/immutabledict 2 | custom: ["https://corenting.fr/donate"] 3 | -------------------------------------------------------------------------------- /docs/api/immutabledict.rst: -------------------------------------------------------------------------------- 1 | immutabledict 2 | ============= 3 | 4 | .. autoclass:: immutabledict.immutabledict 5 | :exclude-members: items,keys,values 6 | :member-order: bysource 7 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | [tox] 2 | isolated_build = true 3 | envlist = py37,py38,py39,py310,py311,py312,py313,py314 4 | 5 | [testenv] 6 | allowlist_externals = poetry, make 7 | commands = 8 | poetry install -v 9 | make test 10 | -------------------------------------------------------------------------------- /docs/api/immutable_ordered_dict.rst: -------------------------------------------------------------------------------- 1 | ImmutableOrderedDict 2 | ====================== 3 | 4 | .. autoclass:: immutabledict.ImmutableOrderedDict 5 | :exclude-members: dict_cls 6 | :show-inheritance: 7 | :member-order: bysource 8 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | PYTHON=poetry run 2 | 3 | .PHONY: format 4 | format: 5 | $(PYTHON) ruff format immutabledict tests 6 | $(PYTHON) ruff check --fix immutabledict tests 7 | 8 | .PHONY: style 9 | style: 10 | $(PYTHON) ruff format --check immutabledict tests 11 | $(PYTHON) ruff check immutabledict tests 12 | $(PYTHON) pyright -- immutabledict tests 13 | 14 | .PHONY: test 15 | test: 16 | $(PYTHON) pytest tests --cov=immutabledict --cov-report=xml 17 | 18 | .PHONY: build-doc 19 | build-doc: 20 | $(PYTHON) sphinx-build -M html docs docs/build 21 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: pip 4 | directory: "/" 5 | schedule: 6 | interval: "weekly" 7 | groups: 8 | production-dependencies: 9 | dependency-type: "production" 10 | development-dependencies: 11 | dependency-type: "development" 12 | - package-ecosystem: "github-actions" 13 | directory: "/" 14 | schedule: 15 | interval: "weekly" 16 | groups: 17 | production-dependencies: 18 | dependency-type: "production" 19 | development-dependencies: 20 | dependency-type: "development" 21 | 22 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | immutabledict will receive security updates for the current major version and the two previous ones, for the latest minor version of each. 6 | 7 | immutabledict will receive security updates for each of 1 minor versions within 3 major versions. 8 | 9 | ## Reporting a Vulnerability 10 | 11 | If you find a security issue, please do **not** report it through GitHub issues. 12 | 13 | Instead, report it directly via email at corenting@gmail.com to coordinate disclosure and the release of fixed versions. Since immutabledict uses [Tidelift](https://tidelift.com/), they will also be notified. 14 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = . 9 | BUILDDIR = _build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | Welcome to immutabledict’s documentation! 2 | ========================================= 3 | 4 | This site covers immutabledict’s API documentation for version |release|. For more information about immutabledict, see `the Github repository `_. 5 | 6 | Usage 7 | ----- 8 | 9 | The :class:`.immutabledict` class can be used as a drop-in replacement for :class:`dict`. 10 | 11 | For replacing an :class:`collections.OrderedDict`, you can use an :class:`.ImmutableOrderedDict`. The API is the same as :class:`.immutabledict`, but it will use an :class:`collections.OrderedDict` under the hood. 12 | 13 | .. code-block:: python 14 | 15 | from immutabledict import immutabledict 16 | 17 | my_item = immutabledict({"a": "value", "b": "other_value"}) 18 | print(my_item["a"]) # Print "value" 19 | 20 | Some additional methods are provided, see the API reference. 21 | 22 | 23 | API reference 24 | ------------- 25 | 26 | .. toctree:: 27 | :maxdepth: 1 28 | 29 | /api/immutabledict 30 | /api/immutable_ordered_dict 31 | changelog 32 | 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Corentin Garcia 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.github/workflows/doc.yml: -------------------------------------------------------------------------------- 1 | name: "Documentation" 2 | 3 | on: 4 | push: 5 | branches: 6 | - "master" 7 | tags: 8 | - "v*" 9 | pull_request: 10 | branches: 11 | - "master" 12 | 13 | jobs: 14 | build: 15 | name: Build sphinx documentation 16 | runs-on: ubuntu-latest 17 | permissions: 18 | contents: write 19 | steps: 20 | - name: Checkout code 21 | uses: actions/checkout@v6 22 | - name: Install Poetry 23 | run: pipx install poetry 24 | - name: Setup Python 25 | uses: actions/setup-python@v6 26 | with: 27 | python-version: 3.13 28 | cache: "poetry" 29 | - name: Setup environment 30 | run: poetry install 31 | - name: Build HTML 32 | run: poetry run sphinx-build -M html docs docs/build 33 | - name: Upload artifacts 34 | uses: actions/upload-pages-artifact@v4 35 | with: 36 | path: docs/build/html/ 37 | deploy: 38 | name: Deploy documentation 39 | runs-on: ubuntu-latest 40 | needs: build 41 | if: startsWith(github.ref, 'refs/tags/v') 42 | permissions: 43 | pages: write # to deploy to Pages 44 | id-token: write # to verify the deployment originates from an appropriate source 45 | environment: 46 | name: github-pages 47 | url: ${{ steps.deployment.outputs.page_url }} 48 | steps: 49 | - name: Deploy to GitHub Pages 50 | id: deployment 51 | uses: actions/deploy-pages@v4 52 | -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | """sphinx configuration.""" 2 | from immutabledict import __version__ 3 | 4 | # Project info 5 | project = "immutabledict" 6 | copyright = "2023, corenting" 7 | author = "corenting" 8 | version = __version__ 9 | release = __version__ 10 | 11 | # General configuration 12 | extensions = [ 13 | "alabaster", 14 | "sphinx.ext.intersphinx", 15 | "sphinx.ext.autodoc", 16 | "myst_parser", 17 | ] 18 | 19 | templates_path = ["_templates"] 20 | exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] 21 | 22 | # Autodoc settings 23 | autodoc_default_options = { 24 | "members": True, 25 | } 26 | 27 | # intersphinx to Python 28 | intersphinx_mapping = {'python': ('https://docs.python.org/3', None)} 29 | 30 | # HTML output 31 | html_theme = "alabaster" 32 | html_sidebars = { 33 | "**": [ 34 | "about.html", 35 | "navigation.html", 36 | "relations.html", 37 | "searchbox.html", 38 | "donate.html", 39 | ] 40 | } 41 | html_theme_options = { 42 | "description": "An immutable wrapper around dictionaries", 43 | "github_user": "corenting", 44 | "github_repo": "immutabledict", 45 | "github_type": "star", 46 | "codecov_button": True, 47 | "badge_branch": "master", 48 | "sidebar_width": "300px", 49 | "donate_url": "https://corenting.fr/donate", 50 | "extra_nav_links": { 51 | "Github repository": "https://github.com/corenting/immutabledict", 52 | "PyPI page": "https://pypi.org/project/immutabledict/", 53 | }, 54 | } 55 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # immutabledict 2 | 3 | ![PyPI](https://img.shields.io/pypi/v/immutabledict) ![Conda](https://img.shields.io/conda/vn/conda-forge/immutabledict) ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/immutabledict) 4 | 5 | ![License](https://img.shields.io/pypi/l/immutabledict) ![Build](https://img.shields.io/github/actions/workflow/status/corenting/immutabledict/ci.yml?branch=master) ![Codecov](https://img.shields.io/codecov/c/github/corenting/immutabledict) ![PyPI - Downloads](https://img.shields.io/pypi/dm/immutabledict) 6 | 7 | An immutable wrapper around dictionaries. immutabledict implements the complete mapping interface and can be used as a drop-in replacement for dictionaries where immutability is desired. 8 | 9 | It's a fork of slezica's [frozendict](https://github.com/slezica/python-frozendict). This library is a pure Python, MIT-licensed alternative to the new LGPL-3.0 licensed [frozendict](https://github.com/Marco-Sulla/python-frozendict). 10 | 11 | ## Installation 12 | 13 | Official release in [on pypi](https://pypi.org/project/immutabledict/) as `immutabledict`. 14 | 15 | **Community-maintained** releases are available: 16 | - On [conda-forge](https://anaconda.org/conda-forge/immutabledict) as `immutabledict` 17 | - On [various package repositories](https://repology.org/project/python:immutabledict/versions) 18 | 19 | ## Example 20 | 21 | ```python 22 | from immutabledict import immutabledict 23 | 24 | my_item = immutabledict({"a": "value", "b": "other_value"}) 25 | print(my_item["a"]) # Print "value" 26 | ``` 27 | 28 | ## Differences with the old original frozendict package 29 | 30 | - Dropped support of EOL Python versions (older versions of the library may support older Python versions) 31 | - Fixed `collections.Mapping` deprecation warning 32 | - Typing 33 | - [PEP 584 union operators](https://www.python.org/dev/peps/pep-0584/) 34 | - Keep the same signature for `copy()` as `dict` (starting with immutabledict 3.0.0), don't accept extra keyword arguments. 35 | - Added `set`, `delete` and `discard` methods 36 | 37 | ## Donations 38 | 39 | If you wish to support this library, donations are possible [here](https://corenting.fr/donate). 40 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ 130 | 131 | # Visual Studio Code 132 | .vscode/ 133 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - "master" 7 | tags: 8 | - "v*" 9 | pull_request: 10 | branches: 11 | - "master" 12 | 13 | permissions: 14 | contents: read 15 | security-events: write 16 | 17 | jobs: 18 | ci: 19 | name: Check style and run tests 20 | strategy: 21 | fail-fast: false 22 | matrix: 23 | python-version: 24 | ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "3.14", "pypy3.9", "pypy3.10", "pypy3.11"] 25 | runs-on: ubuntu-latest 26 | steps: 27 | - name: Checkout code 28 | uses: actions/checkout@v6 29 | - name: Initialize CodeQL 30 | uses: github/codeql-action/init@v4 31 | with: 32 | languages: python 33 | - name: Install Poetry 34 | run: pipx install poetry 35 | - name: Setup Python 36 | uses: actions/setup-python@v6 37 | with: 38 | python-version: ${{ matrix.python-version }} 39 | cache: "poetry" 40 | - name: Setup environment 41 | run: poetry install 42 | - name: Style 43 | run: make style 44 | - name: Test 45 | run: make test 46 | - name: Codecov 47 | uses: codecov/codecov-action@v5 48 | with: 49 | flags: ${{ matrix.python-version }} 50 | token: ${{ secrets.CODECOV_TOKEN }} 51 | code_scanning: 52 | name: Code scanning 53 | runs-on: ubuntu-latest 54 | steps: 55 | - name: Checkout code 56 | uses: actions/checkout@v6 57 | - name: Initialize CodeQL 58 | uses: github/codeql-action/init@v4 59 | with: 60 | languages: python 61 | - name: Perform CodeQL Analysis 62 | uses: github/codeql-action/analyze@v4 63 | release: 64 | name: Release on PyPI 65 | runs-on: ubuntu-latest 66 | environment: release 67 | needs: [ci, code_scanning] 68 | if: startsWith(github.ref, 'refs/tags/v') 69 | permissions: 70 | id-token: write 71 | steps: 72 | - name: Checkout code 73 | uses: actions/checkout@v6 74 | - name: Install Poetry 75 | run: pipx install poetry 76 | - name: Setup Python 77 | uses: actions/setup-python@v6 78 | with: 79 | python-version: "3.13" 80 | cache: "poetry" 81 | - name: Setup environment 82 | run: poetry install 83 | - name: Build 84 | run: | 85 | poetry build 86 | - name: Publish package distributions to PyPI 87 | uses: pypa/gh-action-pypi-publish@release/v1 88 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "immutabledict" 3 | version = "4.2.2" 4 | description = "Immutable wrapper around dictionaries (a fork of frozendict)" 5 | license = "MIT" 6 | authors = [ 7 | { name = "Corentin Garcia", email = "corenting@gmail.com" } 8 | ] 9 | readme = "README.md" 10 | keywords = ["immutable", "dictionary"] 11 | classifiers = [ 12 | "Development Status :: 5 - Production/Stable", 13 | "Programming Language :: Python :: 3 :: Only", 14 | "Programming Language :: Python :: 3.10", 15 | "Programming Language :: Python :: 3.11", 16 | "Programming Language :: Python :: 3.12", 17 | "Programming Language :: Python :: 3.13", 18 | "Programming Language :: Python :: 3.14", 19 | "Programming Language :: Python :: 3.8", 20 | "Programming Language :: Python :: 3.9", 21 | "Programming Language :: Python :: 3", 22 | "Programming Language :: Python :: Implementation :: CPython", 23 | "Programming Language :: Python :: Implementation :: PyPy", 24 | "Topic :: Software Development :: Libraries :: Python Modules", 25 | ] 26 | requires-python = ">=3.8,<4.0" 27 | 28 | [tool.poetry] 29 | include = [ 30 | { path = "tests", format = "sdist" } 31 | ] 32 | 33 | [project.urls] 34 | homepage = "https://github.com/corenting/immutabledict" 35 | bugtracker = "https://github.com/corenting/immutabledict/issues" 36 | changelog = "https://github.com/corenting/immutabledict/blob/master/CHANGELOG.md" 37 | documentation = "https://immutabledict.corenting.fr" 38 | donation = "https://corenting.fr/donate" 39 | repository = "https://github.com/corenting/immutabledict" 40 | 41 | [tool.poetry.group.dev.dependencies] 42 | coverage = "*" 43 | myst-parser = { version = ">=3.0.1,<4", python = ">=3.9" } 44 | pyright = "*" 45 | pytest = "*" 46 | pytest-cov = "*" 47 | ruff = "*" 48 | sphinx = { version = "^7.4", python = ">=3.9" } 49 | tox = "*" 50 | 51 | [tool.ruff] 52 | line-length = 88 53 | target-version = "py38" 54 | 55 | [tool.ruff.lint] 56 | # Enable pycodestyle (E), Pyflakes (F), flake8-print (T20), ruff rules (RUF), 57 | # isort (I), pep8-naming (N), pyupgrade (UP), flake8-async (ASYNC), 58 | # flake8-bandit (S), perflint (PERF) and pydocstyle (D) 59 | select = ["E", "F", "T20", "RUF", "I", "N", "UP", "ASYNC", "S", "PERF", "D"] 60 | ignore = [ 61 | "E501", # line too long as black is used 62 | "D203", # one blank line before class 63 | "D212", # multiline summary first line 64 | "D105" # no docstrings for magic methods 65 | ] 66 | per-file-ignores = {"tests/**" = ["S101", "D"]} 67 | 68 | [tool.ruff.lint.pyupgrade] 69 | # Preserve types, even if a file imports `from __future__ import annotations`. 70 | keep-runtime-typing = true 71 | 72 | [tool.mypy] 73 | ignore_missing_imports = true 74 | disallow_untyped_defs = true 75 | 76 | [build-system] 77 | requires = ["poetry-core>=2.0.0"] 78 | build-backend = "poetry.core.masonry.api" 79 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## Version 4.2.2 4 | 5 | No code changes. 6 | 7 | - Update classifiers, Github Actions... for Python 3.14 8 | - Update metadatas for PEP 639 9 | 10 | ## Version 4.2.1 11 | 12 | - Published with attestation 13 | - Update classifiers, Github Actions... for Python 3.13 (no code changes) 14 | 15 | ## Version 4.2.0 16 | 17 | - Add `discard` method which return a new immutabledict without the item at the given key, if present. Thanks to [@matthiasdiener](https://github.com/matthiasdiener) for the [PR #307](https://github.com/corenting/immutabledict/pull/307) 18 | 19 | ## Version 4.1.0 20 | 21 | - Do not store cached hash value when pickling. Thanks to [@matthiasdiener](https://github.com/matthiasdiener) for the [PR #287](https://github.com/corenting/immutabledict/pull/287) 22 | 23 | ## Version 4.0.0 24 | 25 | - Replace `__init__` by `__new__`. Thanks to [@spacether](https://github.com/spacether) for the [PR #263](https://github.com/corenting/immutabledict/pull/263) 26 | - Add explicit items()/keys()/values() methods to speedup these methods. Thanks to [@matthiasdiener](https://github.com/matthiasdiener) for the [PR #265](https://github.com/corenting/immutabledict/pull/265) 27 | - Add set/delete/update functions. Thanks to [@matthiasdiener](https://github.com/matthiasdiener) for the [PR #271](https://github.com/corenting/immutabledict/pull/271) 28 | - Add documentation at [immutabledict.corenting.fr](https://immutabledict.corenting.fr) 29 | 30 | ## Version 3.0.0 31 | 32 | - `copy()` (**breaking change**): remove the option to pass keyword arguments (which were present as key/value pairs in the copy). Now the method doesn't take any arguments (it behaves the same as a normal `dict`). 33 | - Python versions: drop Python 3.7 support 34 | - Typing: fixes 35 | - Make the key covariant. Thanks to [@spacether](https://github.com/spacether) for the [PR #244](https://github.com/corenting/immutabledict/pull/244) 36 | - Fix key/value typing missing for ImmutableOrderedDict 37 | 38 | ## Version 2.2.5 39 | 40 | - Fix hard-coded class reference in fromkeys() resulting in always using `dict` for `fromkeys()` (instead of OrderedDict in ImmutableOrderedDict for example). Thanks to [@cthoyt](https://github.com/cthoyt) for the [PR #234](https://github.com/corenting/immutabledict/pull/234) 41 | 42 | ## Version 2.2.4 43 | 44 | - Include tests in sdist for easier packaging 45 | 46 | ## Version 2.2.3 47 | 48 | - Fix TypeError message when using `|=`. Thanks to [@ronshapiro](https://github.com/ronshapiro) for the [PR #66](https://github.com/corenting/immutabledict/pull/66) 49 | - Update docstring for ImmutableOrderedDict to indicate that is not needed anymore for Python >= 3.7 but kept for compatibility purposes 50 | - Use postponed evaluation of annotations ([PEP 563](https://peps.python.org/pep-0563/)) for the typing 51 | 52 | ## Version 2.2.2 53 | 54 | - Update classifiers, Github Actions... for Python 3.11 (no code changes) 55 | 56 | ## Version 2.2.1 57 | 58 | - Update classifiers, Github Actions... for Python 3.10 (no code changes) 59 | 60 | ## Version 2.2.0 61 | 62 | - Use `poetry-core` instead of poetry for build-system. Thanks to [@mweinelt](https://github.com/mweinelt) for reporting [the issue](https://github.com/corenting/immutabledict/issues/56). 63 | 64 | ## Version 2.1.0 65 | 66 | - Fix type annotation on keyword argument in copy(**add_or_replace). Thanks to [@techsy730](https://github.com/techsy730) for the [PR #54](https://github.com/corenting/immutabledict/pull/54). 67 | 68 | ## Version 2.0.0 69 | 70 | - Support more typing (fix [issue #47](https://github.com/corenting/immutabledict/issues/47)) 71 | - ⚠️ Remove `*args, **kwargs` from the `fromkeys()` method. 72 | 73 | ## Version 1.3.0 74 | 75 | - Add typing. Thanks to [@aecay](https://github.com/aecay) for the [PR #45](https://github.com/corenting/immutabledict/pull/45). 76 | 77 | ## Version 1.2.0 78 | 79 | - Support [PEP 584 union operators](https://www.python.org/dev/peps/pep-0584/). Thanks to [@lambdalisue](https://github.com/lambdalisue) for the [PR #34](https://github.com/corenting/immutabledict/pull/34). 80 | 81 | ## Version 1.1.0 82 | 83 | - Add Python 3.9 to supported versions, remove Python 3.5 84 | - Bump dev dependencies 85 | - Improve README 86 | 87 | ## Version 1.0.0 88 | 89 | - Initial stable release 90 | -------------------------------------------------------------------------------- /immutabledict/__init__.py: -------------------------------------------------------------------------------- 1 | """Implementation of the :class:`immutabledict` and :class:`ImmutableOrderedDict` classes.""" 2 | 3 | from __future__ import annotations 4 | 5 | from collections import OrderedDict 6 | from typing import ( 7 | Any, 8 | Dict, 9 | ItemsView, 10 | Iterable, 11 | Iterator, 12 | KeysView, 13 | Mapping, 14 | Optional, 15 | Tuple, 16 | Type, 17 | TypeVar, 18 | ValuesView, 19 | ) 20 | 21 | __version__ = "4.2.2" 22 | 23 | _K = TypeVar("_K") 24 | _V = TypeVar("_V", covariant=True) 25 | 26 | 27 | class immutabledict(Mapping[_K, _V]): # noqa: N801 28 | """ 29 | An immutable wrapper around dictionaries that implements the complete :py:class:`collections.Mapping` interface. 30 | 31 | It can be used as a drop-in replacement for dictionaries where immutability is desired. 32 | """ 33 | 34 | _dict_cls: Type[Dict[Any, Any]] = dict 35 | _dict: Dict[_K, _V] 36 | _hash: Optional[int] 37 | 38 | @classmethod 39 | def fromkeys( # noqa: D102 40 | cls, seq: Iterable[_K], value: Optional[_V] = None 41 | ) -> immutabledict[_K, _V]: 42 | return cls(cls._dict_cls.fromkeys(seq, value)) 43 | 44 | def __new__(cls, *args: Any, **kwargs: Any) -> immutabledict[_K, _V]: # noqa: D102 45 | inst = super().__new__(cls) 46 | setattr(inst, "_dict", cls._dict_cls(*args, **kwargs)) 47 | setattr(inst, "_hash", None) 48 | return inst 49 | 50 | def __reduce__(self) -> Tuple[Any, ...]: 51 | # Do not store the cached hash value when pickling 52 | # as the value might change across Python invocations. 53 | return (self.__class__, (self._dict,)) 54 | 55 | def __getitem__(self, key: _K) -> _V: 56 | return self._dict[key] 57 | 58 | def __contains__(self, key: object) -> bool: 59 | return key in self._dict 60 | 61 | def copy(self) -> immutabledict[_K, _V]: # noqa: D102 62 | return self.__class__(self) 63 | 64 | def __iter__(self) -> Iterator[_K]: 65 | return iter(self._dict) 66 | 67 | def __len__(self) -> int: 68 | return len(self._dict) 69 | 70 | def __repr__(self) -> str: 71 | return f"{self.__class__.__name__}({self._dict!r})" 72 | 73 | def __hash__(self) -> int: 74 | if self._hash is None: 75 | h = 0 76 | for key, value in self.items(): 77 | h ^= hash((key, value)) 78 | self._hash = h 79 | 80 | return self._hash 81 | 82 | def __or__(self, other: Any) -> immutabledict[_K, _V]: 83 | if not isinstance(other, (dict, self.__class__)): 84 | return NotImplemented 85 | new = dict(self) 86 | new.update(other) 87 | return self.__class__(new) 88 | 89 | def __ror__(self, other: Any) -> Dict[Any, Any]: 90 | if not isinstance(other, (dict, self.__class__)): 91 | return NotImplemented 92 | new = dict(other) 93 | new.update(self) 94 | return new 95 | 96 | def __ior__(self, other: Any) -> immutabledict[_K, _V]: 97 | raise TypeError(f"'{self.__class__.__name__}' object is not mutable") 98 | 99 | def items(self) -> ItemsView[_K, _V]: # noqa: D102 100 | return self._dict.items() 101 | 102 | def keys(self) -> KeysView[_K]: # noqa: D102 103 | return self._dict.keys() 104 | 105 | def values(self) -> ValuesView[_V]: # noqa: D102 106 | return self._dict.values() 107 | 108 | def set(self, key: _K, value: Any) -> immutabledict[_K, _V]: 109 | """ 110 | Return a new :class:`immutabledict` where the item at the given key is set to to the given value. If there is already an item at the given key it will be replaced. 111 | 112 | :param key: the key for which we want to set a value 113 | :param value: the value we want to use 114 | 115 | :return: the new :class:`immutabledict` with the key set to the given value 116 | """ 117 | new = dict(self._dict) 118 | new[key] = value 119 | return self.__class__(new) 120 | 121 | def delete(self, key: _K) -> immutabledict[_K, _V]: 122 | """ 123 | Return a new :class:`immutabledict` without the item at the given key. 124 | 125 | :param key: the key of the item you want to remove in the returned :class:`immutabledict` 126 | 127 | :raises [KeyError]: a KeyError is raised if there is no item at the given key 128 | 129 | :return: the new :class:`immutabledict` without the item at the given key 130 | """ 131 | new = dict(self._dict) 132 | del new[key] 133 | return self.__class__(new) 134 | 135 | def update(self, _dict: Dict[_K, _V]) -> immutabledict[_K, _V]: 136 | """ 137 | Similar to :meth:`dict.update` but returning an immutabledict. 138 | 139 | :return: the updated :class:`immutabledict` 140 | """ 141 | new = dict(self._dict) 142 | new.update(_dict) 143 | return self.__class__(new) 144 | 145 | def discard(self, key: _K) -> immutabledict[_K, _V]: 146 | """ 147 | Return a new :class:`immutabledict` without the item at the given key, if present. 148 | 149 | :param key: the key of the item you want to remove in the returned :class:`immutabledict` 150 | 151 | :return: the new :class:`immutabledict` without the item at the given 152 | key, or a reference to itself if the key is not present 153 | """ 154 | # Based on the pyrsistent.PMap.discard() API 155 | if key not in self: 156 | return self 157 | 158 | return self.delete(key) 159 | 160 | 161 | class ImmutableOrderedDict(immutabledict[_K, _V]): 162 | """ 163 | An immutabledict subclass that maintains key order. 164 | 165 | Same as :class:`immutabledict` but based on :class:`collections.OrderedDict`. 166 | """ 167 | 168 | dict_cls = OrderedDict 169 | -------------------------------------------------------------------------------- /tests/test_immutabledict.py: -------------------------------------------------------------------------------- 1 | import pickle 2 | import platform 3 | from io import BytesIO 4 | from typing import Any, Dict, Union 5 | 6 | import pytest 7 | 8 | from immutabledict import ImmutableOrderedDict, immutabledict 9 | 10 | 11 | class TestImmutableDict: 12 | def test_covariance(self) -> None: 13 | """Not a real unit test, but test covariance 14 | as mypy runs on the tests. 15 | """ 16 | 17 | class Base: 18 | pass 19 | 20 | class One(Base): 21 | pass 22 | 23 | class Two(Base): 24 | pass 25 | 26 | # Value test 27 | my_dict: immutabledict[str, Union[Base, One]] = immutabledict() 28 | second_dict: immutabledict[str, Two] = immutabledict({"t": Two()}) 29 | my_dict = second_dict 30 | assert my_dict == second_dict 31 | 32 | def test_new_init_methods(self) -> None: 33 | assert "__new__" in immutabledict.__dict__ 34 | assert "__init__" not in immutabledict.__dict__ 35 | 36 | def test_cannot_assign_value(self) -> None: 37 | with pytest.raises(AttributeError): 38 | immutabledict().setitem("key", "value") # type: ignore 39 | 40 | def test_from_keys(self) -> None: 41 | keys = ["a", "b", "c"] 42 | immutable_dict: immutabledict[str, Any] = immutabledict.fromkeys(keys) 43 | assert "a" in immutable_dict 44 | assert "b" in immutable_dict 45 | assert "c" in immutable_dict 46 | 47 | def test_init_and_compare(self) -> None: 48 | normal_dict = {"a": "value", "b": "other_value"} 49 | immutable_dict: immutabledict[str, str] = immutabledict(normal_dict) 50 | assert immutable_dict == normal_dict 51 | 52 | def test_get_existing(self) -> None: 53 | immutable_dict: immutabledict[str, str] = immutabledict({"a": "value"}) 54 | assert immutable_dict["a"] == "value" 55 | 56 | def test_get_not_existing(self) -> None: 57 | immutable_dict: immutabledict[str, str] = immutabledict({"a": "value"}) 58 | with pytest.raises(KeyError): 59 | immutable_dict["b"] 60 | 61 | def test_contains(self) -> None: 62 | immutable_dict: immutabledict[str, str] = immutabledict({"a": "value"}) 63 | assert "a" in immutable_dict 64 | 65 | def test_contains_not_existing(self) -> None: 66 | immutable_dict: immutabledict[str, str] = immutabledict({"a": "value"}) 67 | assert "b" not in immutable_dict 68 | 69 | def test_copy(self) -> None: 70 | original: immutabledict[str, str] = immutabledict({"a": "value"}) 71 | copy = original.copy() 72 | assert original == copy 73 | assert id(original) != id(copy) 74 | 75 | def test_iter(self) -> None: 76 | immutable_dict: immutabledict[str, str] = immutabledict( 77 | {"a": "value", "b": "other_value"} 78 | ) 79 | itered_keys = set(immutable_dict) 80 | assert immutable_dict.keys() == itered_keys 81 | 82 | def test_len(self) -> None: 83 | immutable_dict: immutabledict[str, str] = immutabledict( 84 | {"a": "value", "b": "other_value"} 85 | ) 86 | assert len(immutable_dict) == 2 87 | 88 | def test_len_empty(self) -> None: 89 | immutable_dict: immutabledict[str, str] = immutabledict({}) 90 | assert len(immutable_dict) == 0 91 | 92 | def test_repr(self) -> None: 93 | immutable_dict: immutabledict[str, str] = immutabledict( 94 | {"a": "value", "b": "other_value"} 95 | ) 96 | repr_ret = repr(immutable_dict) 97 | assert repr_ret.startswith("immutabledict") 98 | assert repr_ret.endswith(")") 99 | 100 | def test_repr_should_eval(self) -> None: 101 | immutable_dict: immutabledict[str, str] = immutabledict( 102 | {"a": "value", "b": "other_value"} 103 | ) 104 | eval_ret = eval(repr(immutable_dict)) # noqa: S307 105 | assert immutable_dict == eval_ret 106 | 107 | def test_hash(self) -> None: 108 | first_dict: immutabledict[str, str] = immutabledict( 109 | {"a": "value", "b": "other_value"} 110 | ) 111 | second_dict: immutabledict[str, str] = immutabledict( 112 | {"a": "value", "b": "other_value"} 113 | ) 114 | 115 | assert hash(first_dict) == hash(second_dict) 116 | 117 | def test_union_operator_merge(self) -> None: 118 | first_dict: immutabledict[str, str] = immutabledict({"a": "a", "b": "b"}) 119 | second_dict: immutabledict[str, str] = immutabledict({"a": "A", "c": "c"}) 120 | merged_dict = first_dict | second_dict 121 | assert isinstance(merged_dict, immutabledict) 122 | assert merged_dict == { 123 | "a": "A", 124 | "b": "b", 125 | "c": "c", 126 | } 127 | assert first_dict == {"a": "a", "b": "b"} 128 | assert second_dict == {"a": "A", "c": "c"} 129 | 130 | def test_union_operator_merge_with_dict_first(self) -> None: 131 | first_dict: Dict[str, str] = dict({"a": "a", "b": "b"}) 132 | second_dict: immutabledict[str, str] = immutabledict({"a": "A", "c": "c"}) 133 | merged_dict = first_dict | second_dict 134 | assert isinstance(merged_dict, dict) 135 | assert merged_dict == { 136 | "a": "A", 137 | "b": "b", 138 | "c": "c", 139 | } 140 | assert first_dict == {"a": "a", "b": "b"} 141 | assert second_dict == {"a": "A", "c": "c"} 142 | 143 | def test_union_operator_merge_with_dict_second(self) -> None: 144 | first_dict: immutabledict[str, str] = immutabledict({"a": "a", "b": "b"}) 145 | second_dict: Dict[str, str] = dict({"a": "A", "c": "c"}) 146 | merged_dict = first_dict | second_dict 147 | assert isinstance(merged_dict, immutabledict) 148 | assert merged_dict == { 149 | "a": "A", 150 | "b": "b", 151 | "c": "c", 152 | } 153 | assert first_dict == {"a": "a", "b": "b"} 154 | assert second_dict == {"a": "A", "c": "c"} 155 | 156 | def test_union_operator_merge_fail(self) -> None: 157 | first_dict: immutabledict[str, str] = immutabledict({"a": "a", "b": "b"}) 158 | 159 | with pytest.raises(TypeError): 160 | first_dict | 0 # type: ignore 161 | 162 | with pytest.raises(TypeError): 163 | 0 | first_dict # type: ignore 164 | 165 | def test_union_operator_update(self) -> None: 166 | first_dict: immutabledict[str, str] = immutabledict({"a": "a", "b": "b"}) 167 | second_dict: immutabledict[str, str] = immutabledict({"a": "A", "c": "c"}) 168 | 169 | with pytest.raises(TypeError): 170 | first_dict |= second_dict 171 | 172 | def test_union_operator_update_with_dict_first(self) -> None: 173 | first_dict: Dict[str, str] = dict({"a": "a", "b": "b"}) 174 | second_dict: immutabledict[str, str] = immutabledict({"a": "A", "c": "c"}) 175 | 176 | first_dict |= second_dict 177 | assert isinstance(first_dict, dict) 178 | assert first_dict == { 179 | "a": "A", 180 | "b": "b", 181 | "c": "c", 182 | } 183 | assert second_dict == {"a": "A", "c": "c"} 184 | 185 | def test_union_operator_update_with_dict_second(self) -> None: 186 | first_dict: immutabledict[str, str] = immutabledict({"a": "a", "b": "b"}) 187 | second_dict: Dict[str, str] = dict({"a": "A", "c": "c"}) 188 | 189 | with pytest.raises(TypeError): 190 | first_dict |= second_dict 191 | assert isinstance(first_dict, immutabledict) 192 | assert first_dict == {"a": "a", "b": "b"} 193 | assert second_dict == {"a": "A", "c": "c"} 194 | 195 | @pytest.mark.skipif( 196 | platform.python_implementation() == "PyPy", 197 | reason="Performance is just checked against CPython", 198 | ) 199 | @pytest.mark.parametrize( 200 | "statement", 201 | [ 202 | "for k, v in d.items(): s += 1", 203 | "for v in d.values(): s += 1", 204 | "for k in d.keys(): s += 1", 205 | ], 206 | ) 207 | def test_performance(self, statement: str) -> None: 208 | from timeit import timeit 209 | 210 | time_standard = timeit( 211 | statement, 212 | number=3, 213 | setup="s=0; d = {i:i for i in range(1000000)}", 214 | ) 215 | 216 | time_immutable = timeit( 217 | statement, 218 | globals=globals(), 219 | number=3, 220 | setup="s=0; d = immutabledict({i:i for i in range(1000000)})", 221 | ) 222 | 223 | assert time_immutable < 1.4 * time_standard 224 | 225 | def test_set_delete_update(self) -> None: 226 | d: immutabledict[str, int] = immutabledict(a=1, b=2) 227 | 228 | assert d.set("a", 10) == immutabledict(a=10, b=2) == dict(a=10, b=2) 229 | assert d.delete("a") == immutabledict(b=2) == dict(b=2) 230 | 231 | with pytest.raises(KeyError): 232 | d.delete("c") 233 | 234 | assert d.update({"a": 3}) == immutabledict(a=3, b=2) == dict(a=3, b=2) 235 | 236 | assert ( 237 | d.update({"c": 17}) == immutabledict(a=1, b=2, c=17) == dict(a=1, b=2, c=17) 238 | ) 239 | 240 | # Make sure d doesn't change 241 | assert d == immutabledict(a=1, b=2) == dict(a=1, b=2) 242 | 243 | def test_discard(self) -> None: 244 | d: immutabledict[str, int] = immutabledict(a=1, b=2) 245 | 246 | # Key present 247 | assert d.discard("a") == immutabledict(b=2) == {"b": 2} 248 | assert hash(d.discard("a")) != hash(d) 249 | 250 | # Key not present 251 | assert d.discard("c") == d == {"a": 1, "b": 2} 252 | assert hash(d.discard("c")) == hash(d) 253 | assert d.discard("c") is d 254 | 255 | def test_new_kwargs(self) -> None: 256 | immutable_dict: immutabledict[str, int] = immutabledict(a=1, b=2) 257 | assert immutable_dict == {"a": 1, "b": 2} == dict(a=1, b=2) 258 | 259 | def test_reduce(self) -> None: 260 | my_dict: immutabledict[str, int] = immutabledict(a=1, b=2) 261 | reduce_cls, reduce_args = my_dict.__reduce__() 262 | 263 | assert reduce_cls == immutabledict 264 | assert reduce_args == (my_dict._dict,) 265 | 266 | def test_pickle(self) -> None: 267 | my_dict: immutabledict[str, int] = immutabledict(a=1, b=2) 268 | bytes_io = BytesIO() 269 | pickle.dump(my_dict, bytes_io) 270 | bytes_io.seek(0) 271 | 272 | from_pickle_dict = pickle.loads(bytes_io.getvalue()) # noqa: S301 273 | 274 | assert my_dict == from_pickle_dict 275 | 276 | 277 | class TestImmutableOrderedDict: 278 | def test_ordered(self) -> None: 279 | ordered: ImmutableOrderedDict[str, str] = ImmutableOrderedDict( 280 | { 281 | "a": "1", 282 | "b": "2", 283 | "c": "3", 284 | } 285 | ) # type: ignore 286 | itered_keys = list(ordered) 287 | assert itered_keys[0] == "a" 288 | assert itered_keys[1] == "b" 289 | assert itered_keys[2] == "c" 290 | -------------------------------------------------------------------------------- /poetry.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Poetry 2.2.1 and should not be changed by hand. 2 | 3 | [[package]] 4 | name = "alabaster" 5 | version = "0.7.16" 6 | description = "A light, configurable Sphinx theme" 7 | optional = false 8 | python-versions = ">=3.9" 9 | groups = ["dev"] 10 | markers = "python_version >= \"3.9\"" 11 | files = [ 12 | {file = "alabaster-0.7.16-py3-none-any.whl", hash = "sha256:b46733c07dce03ae4e150330b975c75737fa60f0a7c591b6c8bf4928a28e2c92"}, 13 | {file = "alabaster-0.7.16.tar.gz", hash = "sha256:75a8b99c28a5dad50dd7f8ccdd447a121ddb3892da9e53d1ca5cca3106d58d65"}, 14 | ] 15 | 16 | [[package]] 17 | name = "babel" 18 | version = "2.17.0" 19 | description = "Internationalization utilities" 20 | optional = false 21 | python-versions = ">=3.8" 22 | groups = ["dev"] 23 | markers = "python_version >= \"3.9\"" 24 | files = [ 25 | {file = "babel-2.17.0-py3-none-any.whl", hash = "sha256:4d0b53093fdfb4b21c92b5213dba5a1b23885afa8383709427046b21c366e5f2"}, 26 | {file = "babel-2.17.0.tar.gz", hash = "sha256:0c54cffb19f690cdcc52a3b50bcbf71e07a808d1c80d549f2459b9d2cf0afb9d"}, 27 | ] 28 | 29 | [package.extras] 30 | 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\""] 31 | 32 | [[package]] 33 | name = "cachetools" 34 | version = "5.5.2" 35 | description = "Extensible memoizing collections and decorators" 36 | optional = false 37 | python-versions = ">=3.7" 38 | groups = ["dev"] 39 | files = [ 40 | {file = "cachetools-5.5.2-py3-none-any.whl", hash = "sha256:d26a22bcc62eb95c3beabd9f1ee5e820d3d2704fe2967cbe350e20c8ffcd3f0a"}, 41 | {file = "cachetools-5.5.2.tar.gz", hash = "sha256:1a661caa9175d26759571b2e19580f9d6393969e5dfca11fdb1f947a23e640d4"}, 42 | ] 43 | 44 | [[package]] 45 | name = "certifi" 46 | version = "2025.11.12" 47 | description = "Python package for providing Mozilla's CA Bundle." 48 | optional = false 49 | python-versions = ">=3.7" 50 | groups = ["dev"] 51 | markers = "python_version >= \"3.9\"" 52 | files = [ 53 | {file = "certifi-2025.11.12-py3-none-any.whl", hash = "sha256:97de8790030bbd5c2d96b7ec782fc2f7820ef8dba6db909ccf95449f2d062d4b"}, 54 | {file = "certifi-2025.11.12.tar.gz", hash = "sha256:d8ab5478f2ecd78af242878415affce761ca6bc54a22a27e026d7c25357c3316"}, 55 | ] 56 | 57 | [[package]] 58 | name = "chardet" 59 | version = "5.2.0" 60 | description = "Universal encoding detector for Python 3" 61 | optional = false 62 | python-versions = ">=3.7" 63 | groups = ["dev"] 64 | files = [ 65 | {file = "chardet-5.2.0-py3-none-any.whl", hash = "sha256:e1cf59446890a00105fe7b7912492ea04b6e6f06d4b742b2c788469e34c82970"}, 66 | {file = "chardet-5.2.0.tar.gz", hash = "sha256:1b3b6ff479a8c414bc3fa2c0852995695c4a026dcd6d0633b2dd092ca39c1cf7"}, 67 | ] 68 | 69 | [[package]] 70 | name = "charset-normalizer" 71 | version = "3.4.4" 72 | description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." 73 | optional = false 74 | python-versions = ">=3.7" 75 | groups = ["dev"] 76 | markers = "python_version >= \"3.9\"" 77 | files = [ 78 | {file = "charset_normalizer-3.4.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e824f1492727fa856dd6eda4f7cee25f8518a12f3c4a56a74e8095695089cf6d"}, 79 | {file = "charset_normalizer-3.4.4-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4bd5d4137d500351a30687c2d3971758aac9a19208fc110ccb9d7188fbe709e8"}, 80 | {file = "charset_normalizer-3.4.4-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:027f6de494925c0ab2a55eab46ae5129951638a49a34d87f4c3eda90f696b4ad"}, 81 | {file = "charset_normalizer-3.4.4-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f820802628d2694cb7e56db99213f930856014862f3fd943d290ea8438d07ca8"}, 82 | {file = "charset_normalizer-3.4.4-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:798d75d81754988d2565bff1b97ba5a44411867c0cf32b77a7e8f8d84796b10d"}, 83 | {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"}, 84 | {file = "charset_normalizer-3.4.4-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:9cd98cdc06614a2f768d2b7286d66805f94c48cde050acdbbb7db2600ab3197e"}, 85 | {file = "charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:077fbb858e903c73f6c9db43374fd213b0b6a778106bc7032446a8e8b5b38b93"}, 86 | {file = "charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:244bfb999c71b35de57821b8ea746b24e863398194a4014e4c76adc2bbdfeff0"}, 87 | {file = "charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:64b55f9dce520635f018f907ff1b0df1fdc31f2795a922fb49dd14fbcdf48c84"}, 88 | {file = "charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:faa3a41b2b66b6e50f84ae4a68c64fcd0c44355741c6374813a800cd6695db9e"}, 89 | {file = "charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:6515f3182dbe4ea06ced2d9e8666d97b46ef4c75e326b79bb624110f122551db"}, 90 | {file = "charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:cc00f04ed596e9dc0da42ed17ac5e596c6ccba999ba6bd92b0e0aef2f170f2d6"}, 91 | {file = "charset_normalizer-3.4.4-cp310-cp310-win32.whl", hash = "sha256:f34be2938726fc13801220747472850852fe6b1ea75869a048d6f896838c896f"}, 92 | {file = "charset_normalizer-3.4.4-cp310-cp310-win_amd64.whl", hash = "sha256:a61900df84c667873b292c3de315a786dd8dac506704dea57bc957bd31e22c7d"}, 93 | {file = "charset_normalizer-3.4.4-cp310-cp310-win_arm64.whl", hash = "sha256:cead0978fc57397645f12578bfd2d5ea9138ea0fac82b2f63f7f7c6877986a69"}, 94 | {file = "charset_normalizer-3.4.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6e1fcf0720908f200cd21aa4e6750a48ff6ce4afe7ff5a79a90d5ed8a08296f8"}, 95 | {file = "charset_normalizer-3.4.4-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5f819d5fe9234f9f82d75bdfa9aef3a3d72c4d24a6e57aeaebba32a704553aa0"}, 96 | {file = "charset_normalizer-3.4.4-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:a59cb51917aa591b1c4e6a43c132f0cdc3c76dbad6155df4e28ee626cc77a0a3"}, 97 | {file = "charset_normalizer-3.4.4-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8ef3c867360f88ac904fd3f5e1f902f13307af9052646963ee08ff4f131adafc"}, 98 | {file = "charset_normalizer-3.4.4-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d9e45d7faa48ee908174d8fe84854479ef838fc6a705c9315372eacbc2f02897"}, 99 | {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"}, 100 | {file = "charset_normalizer-3.4.4-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ca5862d5b3928c4940729dacc329aa9102900382fea192fc5e52eb69d6093815"}, 101 | {file = "charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d9c7f57c3d666a53421049053eaacdd14bbd0a528e2186fcb2e672effd053bb0"}, 102 | {file = "charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:277e970e750505ed74c832b4bf75dac7476262ee2a013f5574dd49075879e161"}, 103 | {file = "charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:31fd66405eaf47bb62e8cd575dc621c56c668f27d46a61d975a249930dd5e2a4"}, 104 | {file = "charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:0d3d8f15c07f86e9ff82319b3d9ef6f4bf907608f53fe9d92b28ea9ae3d1fd89"}, 105 | {file = "charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:9f7fcd74d410a36883701fafa2482a6af2ff5ba96b9a620e9e0721e28ead5569"}, 106 | {file = "charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ebf3e58c7ec8a8bed6d66a75d7fb37b55e5015b03ceae72a8e7c74495551e224"}, 107 | {file = "charset_normalizer-3.4.4-cp311-cp311-win32.whl", hash = "sha256:eecbc200c7fd5ddb9a7f16c7decb07b566c29fa2161a16cf67b8d068bd21690a"}, 108 | {file = "charset_normalizer-3.4.4-cp311-cp311-win_amd64.whl", hash = "sha256:5ae497466c7901d54b639cf42d5b8c1b6a4fead55215500d2f486d34db48d016"}, 109 | {file = "charset_normalizer-3.4.4-cp311-cp311-win_arm64.whl", hash = "sha256:65e2befcd84bc6f37095f5961e68a6f077bf44946771354a28ad434c2cce0ae1"}, 110 | {file = "charset_normalizer-3.4.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0a98e6759f854bd25a58a73fa88833fba3b7c491169f86ce1180c948ab3fd394"}, 111 | {file = "charset_normalizer-3.4.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b5b290ccc2a263e8d185130284f8501e3e36c5e02750fc6b6bdeb2e9e96f1e25"}, 112 | {file = "charset_normalizer-3.4.4-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:74bb723680f9f7a6234dcf67aea57e708ec1fbdf5699fb91dfd6f511b0a320ef"}, 113 | {file = "charset_normalizer-3.4.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f1e34719c6ed0b92f418c7c780480b26b5d9c50349e9a9af7d76bf757530350d"}, 114 | {file = "charset_normalizer-3.4.4-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2437418e20515acec67d86e12bf70056a33abdacb5cb1655042f6538d6b085a8"}, 115 | {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"}, 116 | {file = "charset_normalizer-3.4.4-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ac1c4a689edcc530fc9d9aa11f5774b9e2f33f9a0c6a57864e90908f5208d30a"}, 117 | {file = "charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:21d142cc6c0ec30d2efee5068ca36c128a30b0f2c53c1c07bd78cb6bc1d3be5f"}, 118 | {file = "charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:5dbe56a36425d26d6cfb40ce79c314a2e4dd6211d51d6d2191c00bed34f354cc"}, 119 | {file = "charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:5bfbb1b9acf3334612667b61bd3002196fe2a1eb4dd74d247e0f2a4d50ec9bbf"}, 120 | {file = "charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:d055ec1e26e441f6187acf818b73564e6e6282709e9bcb5b63f5b23068356a15"}, 121 | {file = "charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:af2d8c67d8e573d6de5bc30cdb27e9b95e49115cd9baad5ddbd1a6207aaa82a9"}, 122 | {file = "charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:780236ac706e66881f3b7f2f32dfe90507a09e67d1d454c762cf642e6e1586e0"}, 123 | {file = "charset_normalizer-3.4.4-cp312-cp312-win32.whl", hash = "sha256:5833d2c39d8896e4e19b689ffc198f08ea58116bee26dea51e362ecc7cd3ed26"}, 124 | {file = "charset_normalizer-3.4.4-cp312-cp312-win_amd64.whl", hash = "sha256:a79cfe37875f822425b89a82333404539ae63dbdddf97f84dcbc3d339aae9525"}, 125 | {file = "charset_normalizer-3.4.4-cp312-cp312-win_arm64.whl", hash = "sha256:376bec83a63b8021bb5c8ea75e21c4ccb86e7e45ca4eb81146091b56599b80c3"}, 126 | {file = "charset_normalizer-3.4.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:e1f185f86a6f3403aa2420e815904c67b2f9ebc443f045edd0de921108345794"}, 127 | {file = "charset_normalizer-3.4.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b39f987ae8ccdf0d2642338faf2abb1862340facc796048b604ef14919e55ed"}, 128 | {file = "charset_normalizer-3.4.4-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3162d5d8ce1bb98dd51af660f2121c55d0fa541b46dff7bb9b9f86ea1d87de72"}, 129 | {file = "charset_normalizer-3.4.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:81d5eb2a312700f4ecaa977a8235b634ce853200e828fbadf3a9c50bab278328"}, 130 | {file = "charset_normalizer-3.4.4-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5bd2293095d766545ec1a8f612559f6b40abc0eb18bb2f5d1171872d34036ede"}, 131 | {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"}, 132 | {file = "charset_normalizer-3.4.4-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc7637e2f80d8530ee4a78e878bce464f70087ce73cf7c1caf142416923b98f1"}, 133 | {file = "charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f8bf04158c6b607d747e93949aa60618b61312fe647a6369f88ce2ff16043490"}, 134 | {file = "charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:554af85e960429cf30784dd47447d5125aaa3b99a6f0683589dbd27e2f45da44"}, 135 | {file = "charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:74018750915ee7ad843a774364e13a3db91682f26142baddf775342c3f5b1133"}, 136 | {file = "charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:c0463276121fdee9c49b98908b3a89c39be45d86d1dbaa22957e38f6321d4ce3"}, 137 | {file = "charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:362d61fd13843997c1c446760ef36f240cf81d3ebf74ac62652aebaf7838561e"}, 138 | {file = "charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9a26f18905b8dd5d685d6d07b0cdf98a79f3c7a918906af7cc143ea2e164c8bc"}, 139 | {file = "charset_normalizer-3.4.4-cp313-cp313-win32.whl", hash = "sha256:9b35f4c90079ff2e2edc5b26c0c77925e5d2d255c42c74fdb70fb49b172726ac"}, 140 | {file = "charset_normalizer-3.4.4-cp313-cp313-win_amd64.whl", hash = "sha256:b435cba5f4f750aa6c0a0d92c541fb79f69a387c91e61f1795227e4ed9cece14"}, 141 | {file = "charset_normalizer-3.4.4-cp313-cp313-win_arm64.whl", hash = "sha256:542d2cee80be6f80247095cc36c418f7bddd14f4a6de45af91dfad36d817bba2"}, 142 | {file = "charset_normalizer-3.4.4-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:da3326d9e65ef63a817ecbcc0df6e94463713b754fe293eaa03da99befb9a5bd"}, 143 | {file = "charset_normalizer-3.4.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8af65f14dc14a79b924524b1e7fffe304517b2bff5a58bf64f30b98bbc5079eb"}, 144 | {file = "charset_normalizer-3.4.4-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:74664978bb272435107de04e36db5a9735e78232b85b77d45cfb38f758efd33e"}, 145 | {file = "charset_normalizer-3.4.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:752944c7ffbfdd10c074dc58ec2d5a8a4cd9493b314d367c14d24c17684ddd14"}, 146 | {file = "charset_normalizer-3.4.4-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d1f13550535ad8cff21b8d757a3257963e951d96e20ec82ab44bc64aeb62a191"}, 147 | {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"}, 148 | {file = "charset_normalizer-3.4.4-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cb6254dc36b47a990e59e1068afacdcd02958bdcce30bb50cc1700a8b9d624a6"}, 149 | {file = "charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c8ae8a0f02f57a6e61203a31428fa1d677cbe50c93622b4149d5c0f319c1d19e"}, 150 | {file = "charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:47cc91b2f4dd2833fddaedd2893006b0106129d4b94fdb6af1f4ce5a9965577c"}, 151 | {file = "charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:82004af6c302b5d3ab2cfc4cc5f29db16123b1a8417f2e25f9066f91d4411090"}, 152 | {file = "charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:2b7d8f6c26245217bd2ad053761201e9f9680f8ce52f0fcd8d0755aeae5b2152"}, 153 | {file = "charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:799a7a5e4fb2d5898c60b640fd4981d6a25f1c11790935a44ce38c54e985f828"}, 154 | {file = "charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:99ae2cffebb06e6c22bdc25801d7b30f503cc87dbd283479e7b606f70aff57ec"}, 155 | {file = "charset_normalizer-3.4.4-cp314-cp314-win32.whl", hash = "sha256:f9d332f8c2a2fcbffe1378594431458ddbef721c1769d78e2cbc06280d8155f9"}, 156 | {file = "charset_normalizer-3.4.4-cp314-cp314-win_amd64.whl", hash = "sha256:8a6562c3700cce886c5be75ade4a5db4214fda19fede41d9792d100288d8f94c"}, 157 | {file = "charset_normalizer-3.4.4-cp314-cp314-win_arm64.whl", hash = "sha256:de00632ca48df9daf77a2c65a484531649261ec9f25489917f09e455cb09ddb2"}, 158 | {file = "charset_normalizer-3.4.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ce8a0633f41a967713a59c4139d29110c07e826d131a316b50ce11b1d79b4f84"}, 159 | {file = "charset_normalizer-3.4.4-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:eaabd426fe94daf8fd157c32e571c85cb12e66692f15516a83a03264b08d06c3"}, 160 | {file = "charset_normalizer-3.4.4-cp38-cp38-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c4ef880e27901b6cc782f1b95f82da9313c0eb95c3af699103088fa0ac3ce9ac"}, 161 | {file = "charset_normalizer-3.4.4-cp38-cp38-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2aaba3b0819274cc41757a1da876f810a3e4d7b6eb25699253a4effef9e8e4af"}, 162 | {file = "charset_normalizer-3.4.4-cp38-cp38-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:778d2e08eda00f4256d7f672ca9fef386071c9202f5e4607920b86d7803387f2"}, 163 | {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"}, 164 | {file = "charset_normalizer-3.4.4-cp38-cp38-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a8bf8d0f749c5757af2142fe7903a9df1d2e8aa3841559b2bad34b08d0e2bcf3"}, 165 | {file = "charset_normalizer-3.4.4-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:194f08cbb32dc406d6e1aea671a68be0823673db2832b38405deba2fb0d88f63"}, 166 | {file = "charset_normalizer-3.4.4-cp38-cp38-musllinux_1_2_armv7l.whl", hash = "sha256:6aee717dcfead04c6eb1ce3bd29ac1e22663cdea57f943c87d1eab9a025438d7"}, 167 | {file = "charset_normalizer-3.4.4-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:cd4b7ca9984e5e7985c12bc60a6f173f3c958eae74f3ef6624bb6b26e2abbae4"}, 168 | {file = "charset_normalizer-3.4.4-cp38-cp38-musllinux_1_2_riscv64.whl", hash = "sha256:b7cf1017d601aa35e6bb650b6ad28652c9cd78ee6caff19f3c28d03e1c80acbf"}, 169 | {file = "charset_normalizer-3.4.4-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:e912091979546adf63357d7e2ccff9b44f026c075aeaf25a52d0e95ad2281074"}, 170 | {file = "charset_normalizer-3.4.4-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:5cb4d72eea50c8868f5288b7f7f33ed276118325c1dfd3957089f6b519e1382a"}, 171 | {file = "charset_normalizer-3.4.4-cp38-cp38-win32.whl", hash = "sha256:837c2ce8c5a65a2035be9b3569c684358dfbf109fd3b6969630a87535495ceaa"}, 172 | {file = "charset_normalizer-3.4.4-cp38-cp38-win_amd64.whl", hash = "sha256:44c2a8734b333e0578090c4cd6b16f275e07aa6614ca8715e6c038e865e70576"}, 173 | {file = "charset_normalizer-3.4.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:a9768c477b9d7bd54bc0c86dbaebdec6f03306675526c9927c0e8a04e8f94af9"}, 174 | {file = "charset_normalizer-3.4.4-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1bee1e43c28aa63cb16e5c14e582580546b08e535299b8b6158a7c9c768a1f3d"}, 175 | {file = "charset_normalizer-3.4.4-cp39-cp39-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:fd44c878ea55ba351104cb93cc85e74916eb8fa440ca7903e57575e97394f608"}, 176 | {file = "charset_normalizer-3.4.4-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:0f04b14ffe5fdc8c4933862d8306109a2c51e0704acfa35d51598eb45a1e89fc"}, 177 | {file = "charset_normalizer-3.4.4-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:cd09d08005f958f370f539f186d10aec3377d55b9eeb0d796025d4886119d76e"}, 178 | {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"}, 179 | {file = "charset_normalizer-3.4.4-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fa09f53c465e532f4d3db095e0c55b615f010ad81803d383195b6b5ca6cbf5f3"}, 180 | {file = "charset_normalizer-3.4.4-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:7fa17817dc5625de8a027cb8b26d9fefa3ea28c8253929b8d6649e705d2835b6"}, 181 | {file = "charset_normalizer-3.4.4-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:5947809c8a2417be3267efc979c47d76a079758166f7d43ef5ae8e9f92751f88"}, 182 | {file = "charset_normalizer-3.4.4-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:4902828217069c3c5c71094537a8e623f5d097858ac6ca8252f7b4d10b7560f1"}, 183 | {file = "charset_normalizer-3.4.4-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:7c308f7e26e4363d79df40ca5b2be1c6ba9f02bdbccfed5abddb7859a6ce72cf"}, 184 | {file = "charset_normalizer-3.4.4-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:2c9d3c380143a1fedbff95a312aa798578371eb29da42106a29019368a475318"}, 185 | {file = "charset_normalizer-3.4.4-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:cb01158d8b88ee68f15949894ccc6712278243d95f344770fa7593fa2d94410c"}, 186 | {file = "charset_normalizer-3.4.4-cp39-cp39-win32.whl", hash = "sha256:2677acec1a2f8ef614c6888b5b4ae4060cc184174a938ed4e8ef690e15d3e505"}, 187 | {file = "charset_normalizer-3.4.4-cp39-cp39-win_amd64.whl", hash = "sha256:f8e160feb2aed042cd657a72acc0b481212ed28b1b9a95c0cee1621b524e1966"}, 188 | {file = "charset_normalizer-3.4.4-cp39-cp39-win_arm64.whl", hash = "sha256:b5d84d37db046c5ca74ee7bb47dd6cbc13f80665fdde3e8040bdd3fb015ecb50"}, 189 | {file = "charset_normalizer-3.4.4-py3-none-any.whl", hash = "sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f"}, 190 | {file = "charset_normalizer-3.4.4.tar.gz", hash = "sha256:94537985111c35f28720e43603b8e7b43a6ecfb2ce1d3058bbe955b73404e21a"}, 191 | ] 192 | 193 | [[package]] 194 | name = "colorama" 195 | version = "0.4.6" 196 | description = "Cross-platform colored terminal text." 197 | optional = false 198 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" 199 | groups = ["dev"] 200 | files = [ 201 | {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, 202 | {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, 203 | ] 204 | 205 | [[package]] 206 | name = "coverage" 207 | version = "7.6.1" 208 | description = "Code coverage measurement for Python" 209 | optional = false 210 | python-versions = ">=3.8" 211 | groups = ["dev"] 212 | files = [ 213 | {file = "coverage-7.6.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b06079abebbc0e89e6163b8e8f0e16270124c154dc6e4a47b413dd538859af16"}, 214 | {file = "coverage-7.6.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cf4b19715bccd7ee27b6b120e7e9dd56037b9c0681dcc1adc9ba9db3d417fa36"}, 215 | {file = "coverage-7.6.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61c0abb4c85b095a784ef23fdd4aede7a2628478e7baba7c5e3deba61070a02"}, 216 | {file = "coverage-7.6.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fd21f6ae3f08b41004dfb433fa895d858f3f5979e7762d052b12aef444e29afc"}, 217 | {file = "coverage-7.6.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f59d57baca39b32db42b83b2a7ba6f47ad9c394ec2076b084c3f029b7afca23"}, 218 | {file = "coverage-7.6.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a1ac0ae2b8bd743b88ed0502544847c3053d7171a3cff9228af618a068ed9c34"}, 219 | {file = "coverage-7.6.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e6a08c0be454c3b3beb105c0596ebdc2371fab6bb90c0c0297f4e58fd7e1012c"}, 220 | {file = "coverage-7.6.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f5796e664fe802da4f57a168c85359a8fbf3eab5e55cd4e4569fbacecc903959"}, 221 | {file = "coverage-7.6.1-cp310-cp310-win32.whl", hash = "sha256:7bb65125fcbef8d989fa1dd0e8a060999497629ca5b0efbca209588a73356232"}, 222 | {file = "coverage-7.6.1-cp310-cp310-win_amd64.whl", hash = "sha256:3115a95daa9bdba70aea750db7b96b37259a81a709223c8448fa97727d546fe0"}, 223 | {file = "coverage-7.6.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7dea0889685db8550f839fa202744652e87c60015029ce3f60e006f8c4462c93"}, 224 | {file = "coverage-7.6.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ed37bd3c3b063412f7620464a9ac1314d33100329f39799255fb8d3027da50d3"}, 225 | {file = "coverage-7.6.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d85f5e9a5f8b73e2350097c3756ef7e785f55bd71205defa0bfdaf96c31616ff"}, 226 | {file = "coverage-7.6.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9bc572be474cafb617672c43fe989d6e48d3c83af02ce8de73fff1c6bb3c198d"}, 227 | {file = "coverage-7.6.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c0420b573964c760df9e9e86d1a9a622d0d27f417e1a949a8a66dd7bcee7bc6"}, 228 | {file = "coverage-7.6.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1f4aa8219db826ce6be7099d559f8ec311549bfc4046f7f9fe9b5cea5c581c56"}, 229 | {file = "coverage-7.6.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:fc5a77d0c516700ebad189b587de289a20a78324bc54baee03dd486f0855d234"}, 230 | {file = "coverage-7.6.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b48f312cca9621272ae49008c7f613337c53fadca647d6384cc129d2996d1133"}, 231 | {file = "coverage-7.6.1-cp311-cp311-win32.whl", hash = "sha256:1125ca0e5fd475cbbba3bb67ae20bd2c23a98fac4e32412883f9bcbaa81c314c"}, 232 | {file = "coverage-7.6.1-cp311-cp311-win_amd64.whl", hash = "sha256:8ae539519c4c040c5ffd0632784e21b2f03fc1340752af711f33e5be83a9d6c6"}, 233 | {file = "coverage-7.6.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:95cae0efeb032af8458fc27d191f85d1717b1d4e49f7cb226cf526ff28179778"}, 234 | {file = "coverage-7.6.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5621a9175cf9d0b0c84c2ef2b12e9f5f5071357c4d2ea6ca1cf01814f45d2391"}, 235 | {file = "coverage-7.6.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:260933720fdcd75340e7dbe9060655aff3af1f0c5d20f46b57f262ab6c86a5e8"}, 236 | {file = "coverage-7.6.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07e2ca0ad381b91350c0ed49d52699b625aab2b44b65e1b4e02fa9df0e92ad2d"}, 237 | {file = "coverage-7.6.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c44fee9975f04b33331cb8eb272827111efc8930cfd582e0320613263ca849ca"}, 238 | {file = "coverage-7.6.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:877abb17e6339d96bf08e7a622d05095e72b71f8afd8a9fefc82cf30ed944163"}, 239 | {file = "coverage-7.6.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3e0cadcf6733c09154b461f1ca72d5416635e5e4ec4e536192180d34ec160f8a"}, 240 | {file = "coverage-7.6.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c3c02d12f837d9683e5ab2f3d9844dc57655b92c74e286c262e0fc54213c216d"}, 241 | {file = "coverage-7.6.1-cp312-cp312-win32.whl", hash = "sha256:e05882b70b87a18d937ca6768ff33cc3f72847cbc4de4491c8e73880766718e5"}, 242 | {file = "coverage-7.6.1-cp312-cp312-win_amd64.whl", hash = "sha256:b5d7b556859dd85f3a541db6a4e0167b86e7273e1cdc973e5b175166bb634fdb"}, 243 | {file = "coverage-7.6.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a4acd025ecc06185ba2b801f2de85546e0b8ac787cf9d3b06e7e2a69f925b106"}, 244 | {file = "coverage-7.6.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a6d3adcf24b624a7b778533480e32434a39ad8fa30c315208f6d3e5542aeb6e9"}, 245 | {file = "coverage-7.6.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d0c212c49b6c10e6951362f7c6df3329f04c2b1c28499563d4035d964ab8e08c"}, 246 | {file = "coverage-7.6.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e81d7a3e58882450ec4186ca59a3f20a5d4440f25b1cff6f0902ad890e6748a"}, 247 | {file = "coverage-7.6.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78b260de9790fd81e69401c2dc8b17da47c8038176a79092a89cb2b7d945d060"}, 248 | {file = "coverage-7.6.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a78d169acd38300060b28d600344a803628c3fd585c912cacc9ea8790fe96862"}, 249 | {file = "coverage-7.6.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2c09f4ce52cb99dd7505cd0fc8e0e37c77b87f46bc9c1eb03fe3bc9991085388"}, 250 | {file = "coverage-7.6.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6878ef48d4227aace338d88c48738a4258213cd7b74fd9a3d4d7582bb1d8a155"}, 251 | {file = "coverage-7.6.1-cp313-cp313-win32.whl", hash = "sha256:44df346d5215a8c0e360307d46ffaabe0f5d3502c8a1cefd700b34baf31d411a"}, 252 | {file = "coverage-7.6.1-cp313-cp313-win_amd64.whl", hash = "sha256:8284cf8c0dd272a247bc154eb6c95548722dce90d098c17a883ed36e67cdb129"}, 253 | {file = "coverage-7.6.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:d3296782ca4eab572a1a4eca686d8bfb00226300dcefdf43faa25b5242ab8a3e"}, 254 | {file = "coverage-7.6.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:502753043567491d3ff6d08629270127e0c31d4184c4c8d98f92c26f65019962"}, 255 | {file = "coverage-7.6.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a89ecca80709d4076b95f89f308544ec8f7b4727e8a547913a35f16717856cb"}, 256 | {file = "coverage-7.6.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a318d68e92e80af8b00fa99609796fdbcdfef3629c77c6283566c6f02c6d6704"}, 257 | {file = "coverage-7.6.1-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13b0a73a0896988f053e4fbb7de6d93388e6dd292b0d87ee51d106f2c11b465b"}, 258 | {file = "coverage-7.6.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4421712dbfc5562150f7554f13dde997a2e932a6b5f352edcce948a815efee6f"}, 259 | {file = "coverage-7.6.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:166811d20dfea725e2e4baa71fffd6c968a958577848d2131f39b60043400223"}, 260 | {file = "coverage-7.6.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:225667980479a17db1048cb2bf8bfb39b8e5be8f164b8f6628b64f78a72cf9d3"}, 261 | {file = "coverage-7.6.1-cp313-cp313t-win32.whl", hash = "sha256:170d444ab405852903b7d04ea9ae9b98f98ab6d7e63e1115e82620807519797f"}, 262 | {file = "coverage-7.6.1-cp313-cp313t-win_amd64.whl", hash = "sha256:b9f222de8cded79c49bf184bdbc06630d4c58eec9459b939b4a690c82ed05657"}, 263 | {file = "coverage-7.6.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6db04803b6c7291985a761004e9060b2bca08da6d04f26a7f2294b8623a0c1a0"}, 264 | {file = "coverage-7.6.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f1adfc8ac319e1a348af294106bc6a8458a0f1633cc62a1446aebc30c5fa186a"}, 265 | {file = "coverage-7.6.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a95324a9de9650a729239daea117df21f4b9868ce32e63f8b650ebe6cef5595b"}, 266 | {file = "coverage-7.6.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b43c03669dc4618ec25270b06ecd3ee4fa94c7f9b3c14bae6571ca00ef98b0d3"}, 267 | {file = "coverage-7.6.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8929543a7192c13d177b770008bc4e8119f2e1f881d563fc6b6305d2d0ebe9de"}, 268 | {file = "coverage-7.6.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:a09ece4a69cf399510c8ab25e0950d9cf2b42f7b3cb0374f95d2e2ff594478a6"}, 269 | {file = "coverage-7.6.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:9054a0754de38d9dbd01a46621636689124d666bad1936d76c0341f7d71bf569"}, 270 | {file = "coverage-7.6.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0dbde0f4aa9a16fa4d754356a8f2e36296ff4d83994b2c9d8398aa32f222f989"}, 271 | {file = "coverage-7.6.1-cp38-cp38-win32.whl", hash = "sha256:da511e6ad4f7323ee5702e6633085fb76c2f893aaf8ce4c51a0ba4fc07580ea7"}, 272 | {file = "coverage-7.6.1-cp38-cp38-win_amd64.whl", hash = "sha256:3f1156e3e8f2872197af3840d8ad307a9dd18e615dc64d9ee41696f287c57ad8"}, 273 | {file = "coverage-7.6.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:abd5fd0db5f4dc9289408aaf34908072f805ff7792632250dcb36dc591d24255"}, 274 | {file = "coverage-7.6.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:547f45fa1a93154bd82050a7f3cddbc1a7a4dd2a9bf5cb7d06f4ae29fe94eaf8"}, 275 | {file = "coverage-7.6.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:645786266c8f18a931b65bfcefdbf6952dd0dea98feee39bd188607a9d307ed2"}, 276 | {file = "coverage-7.6.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9e0b2df163b8ed01d515807af24f63de04bebcecbd6c3bfeff88385789fdf75a"}, 277 | {file = "coverage-7.6.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:609b06f178fe8e9f89ef676532760ec0b4deea15e9969bf754b37f7c40326dbc"}, 278 | {file = "coverage-7.6.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:702855feff378050ae4f741045e19a32d57d19f3e0676d589df0575008ea5004"}, 279 | {file = "coverage-7.6.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:2bdb062ea438f22d99cba0d7829c2ef0af1d768d1e4a4f528087224c90b132cb"}, 280 | {file = "coverage-7.6.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:9c56863d44bd1c4fe2abb8a4d6f5371d197f1ac0ebdee542f07f35895fc07f36"}, 281 | {file = "coverage-7.6.1-cp39-cp39-win32.whl", hash = "sha256:6e2cd258d7d927d09493c8df1ce9174ad01b381d4729a9d8d4e38670ca24774c"}, 282 | {file = "coverage-7.6.1-cp39-cp39-win_amd64.whl", hash = "sha256:06a737c882bd26d0d6ee7269b20b12f14a8704807a01056c80bb881a4b2ce6ca"}, 283 | {file = "coverage-7.6.1-pp38.pp39.pp310-none-any.whl", hash = "sha256:e9a6e0eb86070e8ccaedfbd9d38fec54864f3125ab95419970575b42af7541df"}, 284 | {file = "coverage-7.6.1.tar.gz", hash = "sha256:953510dfb7b12ab69d20135a0662397f077c59b1e6379a768e97c59d852ee51d"}, 285 | ] 286 | 287 | [package.dependencies] 288 | tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""} 289 | 290 | [package.extras] 291 | toml = ["tomli ; python_full_version <= \"3.11.0a6\""] 292 | 293 | [[package]] 294 | name = "distlib" 295 | version = "0.4.0" 296 | description = "Distribution utilities" 297 | optional = false 298 | python-versions = "*" 299 | groups = ["dev"] 300 | files = [ 301 | {file = "distlib-0.4.0-py2.py3-none-any.whl", hash = "sha256:9659f7d87e46584a30b5780e43ac7a2143098441670ff0a49d5f9034c54a6c16"}, 302 | {file = "distlib-0.4.0.tar.gz", hash = "sha256:feec40075be03a04501a973d81f633735b4b69f98b05450592310c0f401a4e0d"}, 303 | ] 304 | 305 | [[package]] 306 | name = "docutils" 307 | version = "0.21.2" 308 | description = "Docutils -- Python Documentation Utilities" 309 | optional = false 310 | python-versions = ">=3.9" 311 | groups = ["dev"] 312 | markers = "python_version >= \"3.9\"" 313 | files = [ 314 | {file = "docutils-0.21.2-py3-none-any.whl", hash = "sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2"}, 315 | {file = "docutils-0.21.2.tar.gz", hash = "sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f"}, 316 | ] 317 | 318 | [[package]] 319 | name = "exceptiongroup" 320 | version = "1.3.1" 321 | description = "Backport of PEP 654 (exception groups)" 322 | optional = false 323 | python-versions = ">=3.7" 324 | groups = ["dev"] 325 | markers = "python_version < \"3.11\"" 326 | files = [ 327 | {file = "exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598"}, 328 | {file = "exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219"}, 329 | ] 330 | 331 | [package.dependencies] 332 | typing-extensions = {version = ">=4.6.0", markers = "python_version < \"3.13\""} 333 | 334 | [package.extras] 335 | test = ["pytest (>=6)"] 336 | 337 | [[package]] 338 | name = "filelock" 339 | version = "3.16.1" 340 | description = "A platform independent file lock." 341 | optional = false 342 | python-versions = ">=3.8" 343 | groups = ["dev"] 344 | files = [ 345 | {file = "filelock-3.16.1-py3-none-any.whl", hash = "sha256:2082e5703d51fbf98ea75855d9d5527e33d8ff23099bec374a134febee6946b0"}, 346 | {file = "filelock-3.16.1.tar.gz", hash = "sha256:c249fbfcd5db47e5e2d6d62198e565475ee65e4831e2561c8e313fa7eb961435"}, 347 | ] 348 | 349 | [package.extras] 350 | docs = ["furo (>=2024.8.6)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4.1)"] 351 | testing = ["covdefaults (>=2.3)", "coverage (>=7.6.1)", "diff-cover (>=9.2)", "pytest (>=8.3.3)", "pytest-asyncio (>=0.24)", "pytest-cov (>=5)", "pytest-mock (>=3.14)", "pytest-timeout (>=2.3.1)", "virtualenv (>=20.26.4)"] 352 | typing = ["typing-extensions (>=4.12.2) ; python_version < \"3.11\""] 353 | 354 | [[package]] 355 | name = "idna" 356 | version = "3.11" 357 | description = "Internationalized Domain Names in Applications (IDNA)" 358 | optional = false 359 | python-versions = ">=3.8" 360 | groups = ["dev"] 361 | markers = "python_version >= \"3.9\"" 362 | files = [ 363 | {file = "idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea"}, 364 | {file = "idna-3.11.tar.gz", hash = "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902"}, 365 | ] 366 | 367 | [package.extras] 368 | all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] 369 | 370 | [[package]] 371 | name = "imagesize" 372 | version = "1.4.1" 373 | description = "Getting image size from png/jpeg/jpeg2000/gif file" 374 | optional = false 375 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 376 | groups = ["dev"] 377 | markers = "python_version >= \"3.9\"" 378 | files = [ 379 | {file = "imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b"}, 380 | {file = "imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a"}, 381 | ] 382 | 383 | [[package]] 384 | name = "importlib-metadata" 385 | version = "8.7.0" 386 | description = "Read metadata from Python packages" 387 | optional = false 388 | python-versions = ">=3.9" 389 | groups = ["dev"] 390 | markers = "python_version == \"3.9\"" 391 | files = [ 392 | {file = "importlib_metadata-8.7.0-py3-none-any.whl", hash = "sha256:e5dd1551894c77868a30651cef00984d50e1002d06942a7101d34870c5f02afd"}, 393 | {file = "importlib_metadata-8.7.0.tar.gz", hash = "sha256:d13b81ad223b890aa16c5471f2ac3056cf76c5f10f82d6f9292f0b415f389000"}, 394 | ] 395 | 396 | [package.dependencies] 397 | zipp = ">=3.20" 398 | 399 | [package.extras] 400 | check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\""] 401 | cover = ["pytest-cov"] 402 | doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] 403 | enabler = ["pytest-enabler (>=2.2)"] 404 | perf = ["ipython"] 405 | test = ["flufl.flake8", "importlib_resources (>=1.3) ; python_version < \"3.9\"", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-perf (>=0.9.2)"] 406 | type = ["pytest-mypy"] 407 | 408 | [[package]] 409 | name = "iniconfig" 410 | version = "2.1.0" 411 | description = "brain-dead simple config-ini parsing" 412 | optional = false 413 | python-versions = ">=3.8" 414 | groups = ["dev"] 415 | files = [ 416 | {file = "iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760"}, 417 | {file = "iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7"}, 418 | ] 419 | 420 | [[package]] 421 | name = "jinja2" 422 | version = "3.1.6" 423 | description = "A very fast and expressive template engine." 424 | optional = false 425 | python-versions = ">=3.7" 426 | groups = ["dev"] 427 | markers = "python_version >= \"3.9\"" 428 | files = [ 429 | {file = "jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67"}, 430 | {file = "jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d"}, 431 | ] 432 | 433 | [package.dependencies] 434 | MarkupSafe = ">=2.0" 435 | 436 | [package.extras] 437 | i18n = ["Babel (>=2.7)"] 438 | 439 | [[package]] 440 | name = "markdown-it-py" 441 | version = "3.0.0" 442 | description = "Python port of markdown-it. Markdown parsing, done right!" 443 | optional = false 444 | python-versions = ">=3.8" 445 | groups = ["dev"] 446 | markers = "python_version >= \"3.9\"" 447 | files = [ 448 | {file = "markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb"}, 449 | {file = "markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1"}, 450 | ] 451 | 452 | [package.dependencies] 453 | mdurl = ">=0.1,<1.0" 454 | 455 | [package.extras] 456 | benchmarking = ["psutil", "pytest", "pytest-benchmark"] 457 | code-style = ["pre-commit (>=3.0,<4.0)"] 458 | compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "mistletoe (>=1.0,<2.0)", "mistune (>=2.0,<3.0)", "panflute (>=2.3,<3.0)"] 459 | linkify = ["linkify-it-py (>=1,<3)"] 460 | plugins = ["mdit-py-plugins"] 461 | profiling = ["gprof2dot"] 462 | rtd = ["jupyter_sphinx", "mdit-py-plugins", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"] 463 | testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] 464 | 465 | [[package]] 466 | name = "markupsafe" 467 | version = "3.0.3" 468 | description = "Safely add untrusted strings to HTML/XML markup." 469 | optional = false 470 | python-versions = ">=3.9" 471 | groups = ["dev"] 472 | markers = "python_version >= \"3.9\"" 473 | files = [ 474 | {file = "markupsafe-3.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2f981d352f04553a7171b8e44369f2af4055f888dfb147d55e42d29e29e74559"}, 475 | {file = "markupsafe-3.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e1c1493fb6e50ab01d20a22826e57520f1284df32f2d8601fdd90b6304601419"}, 476 | {file = "markupsafe-3.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1ba88449deb3de88bd40044603fafffb7bc2b055d626a330323a9ed736661695"}, 477 | {file = "markupsafe-3.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f42d0984e947b8adf7dd6dde396e720934d12c506ce84eea8476409563607591"}, 478 | {file = "markupsafe-3.0.3-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c0c0b3ade1c0b13b936d7970b1d37a57acde9199dc2aecc4c336773e1d86049c"}, 479 | {file = "markupsafe-3.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:0303439a41979d9e74d18ff5e2dd8c43ed6c6001fd40e5bf2e43f7bd9bbc523f"}, 480 | {file = "markupsafe-3.0.3-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:d2ee202e79d8ed691ceebae8e0486bd9a2cd4794cec4824e1c99b6f5009502f6"}, 481 | {file = "markupsafe-3.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:177b5253b2834fe3678cb4a5f0059808258584c559193998be2601324fdeafb1"}, 482 | {file = "markupsafe-3.0.3-cp310-cp310-win32.whl", hash = "sha256:2a15a08b17dd94c53a1da0438822d70ebcd13f8c3a95abe3a9ef9f11a94830aa"}, 483 | {file = "markupsafe-3.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:c4ffb7ebf07cfe8931028e3e4c85f0357459a3f9f9490886198848f4fa002ec8"}, 484 | {file = "markupsafe-3.0.3-cp310-cp310-win_arm64.whl", hash = "sha256:e2103a929dfa2fcaf9bb4e7c091983a49c9ac3b19c9061b6d5427dd7d14d81a1"}, 485 | {file = "markupsafe-3.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1cc7ea17a6824959616c525620e387f6dd30fec8cb44f649e31712db02123dad"}, 486 | {file = "markupsafe-3.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4bd4cd07944443f5a265608cc6aab442e4f74dff8088b0dfc8238647b8f6ae9a"}, 487 | {file = "markupsafe-3.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b5420a1d9450023228968e7e6a9ce57f65d148ab56d2313fcd589eee96a7a50"}, 488 | {file = "markupsafe-3.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0bf2a864d67e76e5c9a34dc26ec616a66b9888e25e7b9460e1c76d3293bd9dbf"}, 489 | {file = "markupsafe-3.0.3-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc51efed119bc9cfdf792cdeaa4d67e8f6fcccab66ed4bfdd6bde3e59bfcbb2f"}, 490 | {file = "markupsafe-3.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:068f375c472b3e7acbe2d5318dea141359e6900156b5b2ba06a30b169086b91a"}, 491 | {file = "markupsafe-3.0.3-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:7be7b61bb172e1ed687f1754f8e7484f1c8019780f6f6b0786e76bb01c2ae115"}, 492 | {file = "markupsafe-3.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a"}, 493 | {file = "markupsafe-3.0.3-cp311-cp311-win32.whl", hash = "sha256:0db14f5dafddbb6d9208827849fad01f1a2609380add406671a26386cdf15a19"}, 494 | {file = "markupsafe-3.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:de8a88e63464af587c950061a5e6a67d3632e36df62b986892331d4620a35c01"}, 495 | {file = "markupsafe-3.0.3-cp311-cp311-win_arm64.whl", hash = "sha256:3b562dd9e9ea93f13d53989d23a7e775fdfd1066c33494ff43f5418bc8c58a5c"}, 496 | {file = "markupsafe-3.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d53197da72cc091b024dd97249dfc7794d6a56530370992a5e1a08983ad9230e"}, 497 | {file = "markupsafe-3.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1872df69a4de6aead3491198eaf13810b565bdbeec3ae2dc8780f14458ec73ce"}, 498 | {file = "markupsafe-3.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3a7e8ae81ae39e62a41ec302f972ba6ae23a5c5396c8e60113e9066ef893da0d"}, 499 | {file = "markupsafe-3.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d6dd0be5b5b189d31db7cda48b91d7e0a9795f31430b7f271219ab30f1d3ac9d"}, 500 | {file = "markupsafe-3.0.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:94c6f0bb423f739146aec64595853541634bde58b2135f27f61c1ffd1cd4d16a"}, 501 | {file = "markupsafe-3.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:be8813b57049a7dc738189df53d69395eba14fb99345e0a5994914a3864c8a4b"}, 502 | {file = "markupsafe-3.0.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:83891d0e9fb81a825d9a6d61e3f07550ca70a076484292a70fde82c4b807286f"}, 503 | {file = "markupsafe-3.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:77f0643abe7495da77fb436f50f8dab76dbc6e5fd25d39589a0f1fe6548bfa2b"}, 504 | {file = "markupsafe-3.0.3-cp312-cp312-win32.whl", hash = "sha256:d88b440e37a16e651bda4c7c2b930eb586fd15ca7406cb39e211fcff3bf3017d"}, 505 | {file = "markupsafe-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:26a5784ded40c9e318cfc2bdb30fe164bdb8665ded9cd64d500a34fb42067b1c"}, 506 | {file = "markupsafe-3.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:35add3b638a5d900e807944a078b51922212fb3dedb01633a8defc4b01a3c85f"}, 507 | {file = "markupsafe-3.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e1cf1972137e83c5d4c136c43ced9ac51d0e124706ee1c8aa8532c1287fa8795"}, 508 | {file = "markupsafe-3.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219"}, 509 | {file = "markupsafe-3.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6"}, 510 | {file = "markupsafe-3.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676"}, 511 | {file = "markupsafe-3.0.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:509fa21c6deb7a7a273d629cf5ec029bc209d1a51178615ddf718f5918992ab9"}, 512 | {file = "markupsafe-3.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4afe79fb3de0b7097d81da19090f4df4f8d3a2b3adaa8764138aac2e44f3af1"}, 513 | {file = "markupsafe-3.0.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:795e7751525cae078558e679d646ae45574b47ed6e7771863fcc079a6171a0fc"}, 514 | {file = "markupsafe-3.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8485f406a96febb5140bfeca44a73e3ce5116b2501ac54fe953e488fb1d03b12"}, 515 | {file = "markupsafe-3.0.3-cp313-cp313-win32.whl", hash = "sha256:bdd37121970bfd8be76c5fb069c7751683bdf373db1ed6c010162b2a130248ed"}, 516 | {file = "markupsafe-3.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5"}, 517 | {file = "markupsafe-3.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:7e68f88e5b8799aa49c85cd116c932a1ac15caaa3f5db09087854d218359e485"}, 518 | {file = "markupsafe-3.0.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:218551f6df4868a8d527e3062d0fb968682fe92054e89978594c28e642c43a73"}, 519 | {file = "markupsafe-3.0.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3524b778fe5cfb3452a09d31e7b5adefeea8c5be1d43c4f810ba09f2ceb29d37"}, 520 | {file = "markupsafe-3.0.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4e885a3d1efa2eadc93c894a21770e4bc67899e3543680313b09f139e149ab19"}, 521 | {file = "markupsafe-3.0.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8709b08f4a89aa7586de0aadc8da56180242ee0ada3999749b183aa23df95025"}, 522 | {file = "markupsafe-3.0.3-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b8512a91625c9b3da6f127803b166b629725e68af71f8184ae7e7d54686a56d6"}, 523 | {file = "markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9b79b7a16f7fedff2495d684f2b59b0457c3b493778c9eed31111be64d58279f"}, 524 | {file = "markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:12c63dfb4a98206f045aa9563db46507995f7ef6d83b2f68eda65c307c6829eb"}, 525 | {file = "markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8f71bc33915be5186016f675cd83a1e08523649b0e33efdb898db577ef5bb009"}, 526 | {file = "markupsafe-3.0.3-cp313-cp313t-win32.whl", hash = "sha256:69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354"}, 527 | {file = "markupsafe-3.0.3-cp313-cp313t-win_amd64.whl", hash = "sha256:1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218"}, 528 | {file = "markupsafe-3.0.3-cp313-cp313t-win_arm64.whl", hash = "sha256:ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287"}, 529 | {file = "markupsafe-3.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:eaa9599de571d72e2daf60164784109f19978b327a3910d3e9de8c97b5b70cfe"}, 530 | {file = "markupsafe-3.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026"}, 531 | {file = "markupsafe-3.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f34c41761022dd093b4b6896d4810782ffbabe30f2d443ff5f083e0cbbb8c737"}, 532 | {file = "markupsafe-3.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:457a69a9577064c05a97c41f4e65148652db078a3a509039e64d3467b9e7ef97"}, 533 | {file = "markupsafe-3.0.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e8afc3f2ccfa24215f8cb28dcf43f0113ac3c37c2f0f0806d8c70e4228c5cf4d"}, 534 | {file = "markupsafe-3.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ec15a59cf5af7be74194f7ab02d0f59a62bdcf1a537677ce67a2537c9b87fcda"}, 535 | {file = "markupsafe-3.0.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:0eb9ff8191e8498cca014656ae6b8d61f39da5f95b488805da4bb029cccbfbaf"}, 536 | {file = "markupsafe-3.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2713baf880df847f2bece4230d4d094280f4e67b1e813eec43b4c0e144a34ffe"}, 537 | {file = "markupsafe-3.0.3-cp314-cp314-win32.whl", hash = "sha256:729586769a26dbceff69f7a7dbbf59ab6572b99d94576a5592625d5b411576b9"}, 538 | {file = "markupsafe-3.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:bdc919ead48f234740ad807933cdf545180bfbe9342c2bb451556db2ed958581"}, 539 | {file = "markupsafe-3.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:5a7d5dc5140555cf21a6fefbdbf8723f06fcd2f63ef108f2854de715e4422cb4"}, 540 | {file = "markupsafe-3.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:1353ef0c1b138e1907ae78e2f6c63ff67501122006b0f9abad68fda5f4ffc6ab"}, 541 | {file = "markupsafe-3.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1085e7fbddd3be5f89cc898938f42c0b3c711fdcb37d75221de2666af647c175"}, 542 | {file = "markupsafe-3.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1b52b4fb9df4eb9ae465f8d0c228a00624de2334f216f178a995ccdcf82c4634"}, 543 | {file = "markupsafe-3.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50"}, 544 | {file = "markupsafe-3.0.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f190daf01f13c72eac4efd5c430a8de82489d9cff23c364c3ea822545032993e"}, 545 | {file = "markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e56b7d45a839a697b5eb268c82a71bd8c7f6c94d6fd50c3d577fa39a9f1409f5"}, 546 | {file = "markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:f3e98bb3798ead92273dc0e5fd0f31ade220f59a266ffd8a4f6065e0a3ce0523"}, 547 | {file = "markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5678211cb9333a6468fb8d8be0305520aa073f50d17f089b5b4b477ea6e67fdc"}, 548 | {file = "markupsafe-3.0.3-cp314-cp314t-win32.whl", hash = "sha256:915c04ba3851909ce68ccc2b8e2cd691618c4dc4c4232fb7982bca3f41fd8c3d"}, 549 | {file = "markupsafe-3.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4faffd047e07c38848ce017e8725090413cd80cbc23d86e55c587bf979e579c9"}, 550 | {file = "markupsafe-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa"}, 551 | {file = "markupsafe-3.0.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:15d939a21d546304880945ca1ecb8a039db6b4dc49b2c5a400387cdae6a62e26"}, 552 | {file = "markupsafe-3.0.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f71a396b3bf33ecaa1626c255855702aca4d3d9fea5e051b41ac59a9c1c41edc"}, 553 | {file = "markupsafe-3.0.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0f4b68347f8c5eab4a13419215bdfd7f8c9b19f2b25520968adfad23eb0ce60c"}, 554 | {file = "markupsafe-3.0.3-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e8fc20152abba6b83724d7ff268c249fa196d8259ff481f3b1476383f8f24e42"}, 555 | {file = "markupsafe-3.0.3-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:949b8d66bc381ee8b007cd945914c721d9aba8e27f71959d750a46f7c282b20b"}, 556 | {file = "markupsafe-3.0.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:3537e01efc9d4dccdf77221fb1cb3b8e1a38d5428920e0657ce299b20324d758"}, 557 | {file = "markupsafe-3.0.3-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:591ae9f2a647529ca990bc681daebdd52c8791ff06c2bfa05b65163e28102ef2"}, 558 | {file = "markupsafe-3.0.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a320721ab5a1aba0a233739394eb907f8c8da5c98c9181d1161e77a0c8e36f2d"}, 559 | {file = "markupsafe-3.0.3-cp39-cp39-win32.whl", hash = "sha256:df2449253ef108a379b8b5d6b43f4b1a8e81a061d6537becd5582fba5f9196d7"}, 560 | {file = "markupsafe-3.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:7c3fb7d25180895632e5d3148dbdc29ea38ccb7fd210aa27acbd1201a1902c6e"}, 561 | {file = "markupsafe-3.0.3-cp39-cp39-win_arm64.whl", hash = "sha256:38664109c14ffc9e7437e86b4dceb442b0096dfe3541d7864d9cbe1da4cf36c8"}, 562 | {file = "markupsafe-3.0.3.tar.gz", hash = "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698"}, 563 | ] 564 | 565 | [[package]] 566 | name = "mdit-py-plugins" 567 | version = "0.4.2" 568 | description = "Collection of plugins for markdown-it-py" 569 | optional = false 570 | python-versions = ">=3.8" 571 | groups = ["dev"] 572 | markers = "python_version >= \"3.9\"" 573 | files = [ 574 | {file = "mdit_py_plugins-0.4.2-py3-none-any.whl", hash = "sha256:0c673c3f889399a33b95e88d2f0d111b4447bdfea7f237dab2d488f459835636"}, 575 | {file = "mdit_py_plugins-0.4.2.tar.gz", hash = "sha256:5f2cd1fdb606ddf152d37ec30e46101a60512bc0e5fa1a7002c36647b09e26b5"}, 576 | ] 577 | 578 | [package.dependencies] 579 | markdown-it-py = ">=1.0.0,<4.0.0" 580 | 581 | [package.extras] 582 | code-style = ["pre-commit"] 583 | rtd = ["myst-parser", "sphinx-book-theme"] 584 | testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] 585 | 586 | [[package]] 587 | name = "mdurl" 588 | version = "0.1.2" 589 | description = "Markdown URL utilities" 590 | optional = false 591 | python-versions = ">=3.7" 592 | groups = ["dev"] 593 | markers = "python_version >= \"3.9\"" 594 | files = [ 595 | {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, 596 | {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, 597 | ] 598 | 599 | [[package]] 600 | name = "myst-parser" 601 | version = "3.0.1" 602 | description = "An extended [CommonMark](https://spec.commonmark.org/) compliant parser," 603 | optional = false 604 | python-versions = ">=3.8" 605 | groups = ["dev"] 606 | markers = "python_version >= \"3.9\"" 607 | files = [ 608 | {file = "myst_parser-3.0.1-py3-none-any.whl", hash = "sha256:6457aaa33a5d474aca678b8ead9b3dc298e89c68e67012e73146ea6fd54babf1"}, 609 | {file = "myst_parser-3.0.1.tar.gz", hash = "sha256:88f0cb406cb363b077d176b51c476f62d60604d68a8dcdf4832e080441301a87"}, 610 | ] 611 | 612 | [package.dependencies] 613 | docutils = ">=0.18,<0.22" 614 | jinja2 = "*" 615 | markdown-it-py = ">=3.0,<4.0" 616 | mdit-py-plugins = ">=0.4,<1.0" 617 | pyyaml = "*" 618 | sphinx = ">=6,<8" 619 | 620 | [package.extras] 621 | code-style = ["pre-commit (>=3.0,<4.0)"] 622 | linkify = ["linkify-it-py (>=2.0,<3.0)"] 623 | rtd = ["ipython", "sphinx (>=7)", "sphinx-autodoc2 (>=0.5.0,<0.6.0)", "sphinx-book-theme (>=1.1,<2.0)", "sphinx-copybutton", "sphinx-design", "sphinx-pyscript", "sphinx-tippy (>=0.4.3)", "sphinx-togglebutton", "sphinxext-opengraph (>=0.9.0,<0.10.0)", "sphinxext-rediraffe (>=0.2.7,<0.3.0)"] 624 | testing = ["beautifulsoup4", "coverage[toml]", "defusedxml", "pytest (>=8,<9)", "pytest-cov", "pytest-param-files (>=0.6.0,<0.7.0)", "pytest-regressions", "sphinx-pytest"] 625 | testing-docutils = ["pygments", "pytest (>=8,<9)", "pytest-param-files (>=0.6.0,<0.7.0)"] 626 | 627 | [[package]] 628 | name = "nodeenv" 629 | version = "1.9.1" 630 | description = "Node.js virtual environment builder" 631 | optional = false 632 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" 633 | groups = ["dev"] 634 | files = [ 635 | {file = "nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9"}, 636 | {file = "nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f"}, 637 | ] 638 | 639 | [[package]] 640 | name = "packaging" 641 | version = "25.0" 642 | description = "Core utilities for Python packages" 643 | optional = false 644 | python-versions = ">=3.8" 645 | groups = ["dev"] 646 | files = [ 647 | {file = "packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484"}, 648 | {file = "packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f"}, 649 | ] 650 | 651 | [[package]] 652 | name = "platformdirs" 653 | version = "4.3.6" 654 | description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." 655 | optional = false 656 | python-versions = ">=3.8" 657 | groups = ["dev"] 658 | files = [ 659 | {file = "platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb"}, 660 | {file = "platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907"}, 661 | ] 662 | 663 | [package.extras] 664 | docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4)"] 665 | test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.2)", "pytest-cov (>=5)", "pytest-mock (>=3.14)"] 666 | type = ["mypy (>=1.11.2)"] 667 | 668 | [[package]] 669 | name = "pluggy" 670 | version = "1.5.0" 671 | description = "plugin and hook calling mechanisms for python" 672 | optional = false 673 | python-versions = ">=3.8" 674 | groups = ["dev"] 675 | files = [ 676 | {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, 677 | {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, 678 | ] 679 | 680 | [package.extras] 681 | dev = ["pre-commit", "tox"] 682 | testing = ["pytest", "pytest-benchmark"] 683 | 684 | [[package]] 685 | name = "pygments" 686 | version = "2.19.2" 687 | description = "Pygments is a syntax highlighting package written in Python." 688 | optional = false 689 | python-versions = ">=3.8" 690 | groups = ["dev"] 691 | markers = "python_version >= \"3.9\"" 692 | files = [ 693 | {file = "pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b"}, 694 | {file = "pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887"}, 695 | ] 696 | 697 | [package.extras] 698 | windows-terminal = ["colorama (>=0.4.6)"] 699 | 700 | [[package]] 701 | name = "pyproject-api" 702 | version = "1.8.0" 703 | description = "API to interact with the python pyproject.toml based projects" 704 | optional = false 705 | python-versions = ">=3.8" 706 | groups = ["dev"] 707 | files = [ 708 | {file = "pyproject_api-1.8.0-py3-none-any.whl", hash = "sha256:3d7d347a047afe796fd5d1885b1e391ba29be7169bd2f102fcd378f04273d228"}, 709 | {file = "pyproject_api-1.8.0.tar.gz", hash = "sha256:77b8049f2feb5d33eefcc21b57f1e279636277a8ac8ad6b5871037b243778496"}, 710 | ] 711 | 712 | [package.dependencies] 713 | packaging = ">=24.1" 714 | tomli = {version = ">=2.0.1", markers = "python_version < \"3.11\""} 715 | 716 | [package.extras] 717 | docs = ["furo (>=2024.8.6)", "sphinx-autodoc-typehints (>=2.4.1)"] 718 | testing = ["covdefaults (>=2.3)", "pytest (>=8.3.3)", "pytest-cov (>=5)", "pytest-mock (>=3.14)", "setuptools (>=75.1)"] 719 | 720 | [[package]] 721 | name = "pyright" 722 | version = "1.1.407" 723 | description = "Command line wrapper for pyright" 724 | optional = false 725 | python-versions = ">=3.7" 726 | groups = ["dev"] 727 | files = [ 728 | {file = "pyright-1.1.407-py3-none-any.whl", hash = "sha256:6dd419f54fcc13f03b52285796d65e639786373f433e243f8b94cf93a7444d21"}, 729 | {file = "pyright-1.1.407.tar.gz", hash = "sha256:099674dba5c10489832d4a4b2d302636152a9a42d317986c38474c76fe562262"}, 730 | ] 731 | 732 | [package.dependencies] 733 | nodeenv = ">=1.6.0" 734 | typing-extensions = ">=4.1" 735 | 736 | [package.extras] 737 | all = ["nodejs-wheel-binaries", "twine (>=3.4.1)"] 738 | dev = ["twine (>=3.4.1)"] 739 | nodejs = ["nodejs-wheel-binaries"] 740 | 741 | [[package]] 742 | name = "pytest" 743 | version = "8.3.5" 744 | description = "pytest: simple powerful testing with Python" 745 | optional = false 746 | python-versions = ">=3.8" 747 | groups = ["dev"] 748 | files = [ 749 | {file = "pytest-8.3.5-py3-none-any.whl", hash = "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820"}, 750 | {file = "pytest-8.3.5.tar.gz", hash = "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845"}, 751 | ] 752 | 753 | [package.dependencies] 754 | colorama = {version = "*", markers = "sys_platform == \"win32\""} 755 | exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} 756 | iniconfig = "*" 757 | packaging = "*" 758 | pluggy = ">=1.5,<2" 759 | tomli = {version = ">=1", markers = "python_version < \"3.11\""} 760 | 761 | [package.extras] 762 | dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] 763 | 764 | [[package]] 765 | name = "pytest-cov" 766 | version = "5.0.0" 767 | description = "Pytest plugin for measuring coverage." 768 | optional = false 769 | python-versions = ">=3.8" 770 | groups = ["dev"] 771 | files = [ 772 | {file = "pytest-cov-5.0.0.tar.gz", hash = "sha256:5837b58e9f6ebd335b0f8060eecce69b662415b16dc503883a02f45dfeb14857"}, 773 | {file = "pytest_cov-5.0.0-py3-none-any.whl", hash = "sha256:4f0764a1219df53214206bf1feea4633c3b558a2925c8b59f144f682861ce652"}, 774 | ] 775 | 776 | [package.dependencies] 777 | coverage = {version = ">=5.2.1", extras = ["toml"]} 778 | pytest = ">=4.6" 779 | 780 | [package.extras] 781 | testing = ["fields", "hunter", "process-tests", "pytest-xdist", "virtualenv"] 782 | 783 | [[package]] 784 | name = "pyyaml" 785 | version = "6.0.3" 786 | description = "YAML parser and emitter for Python" 787 | optional = false 788 | python-versions = ">=3.8" 789 | groups = ["dev"] 790 | markers = "python_version >= \"3.9\"" 791 | files = [ 792 | {file = "PyYAML-6.0.3-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:c2514fceb77bc5e7a2f7adfaa1feb2fb311607c9cb518dbc378688ec73d8292f"}, 793 | {file = "PyYAML-6.0.3-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9c57bb8c96f6d1808c030b1687b9b5fb476abaa47f0db9c0101f5e9f394e97f4"}, 794 | {file = "PyYAML-6.0.3-cp38-cp38-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:efd7b85f94a6f21e4932043973a7ba2613b059c4a000551892ac9f1d11f5baf3"}, 795 | {file = "PyYAML-6.0.3-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:22ba7cfcad58ef3ecddc7ed1db3409af68d023b7f940da23c6c2a1890976eda6"}, 796 | {file = "PyYAML-6.0.3-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:6344df0d5755a2c9a276d4473ae6b90647e216ab4757f8426893b5dd2ac3f369"}, 797 | {file = "PyYAML-6.0.3-cp38-cp38-win32.whl", hash = "sha256:3ff07ec89bae51176c0549bc4c63aa6202991da2d9a6129d7aef7f1407d3f295"}, 798 | {file = "PyYAML-6.0.3-cp38-cp38-win_amd64.whl", hash = "sha256:5cf4e27da7e3fbed4d6c3d8e797387aaad68102272f8f9752883bc32d61cb87b"}, 799 | {file = "pyyaml-6.0.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b"}, 800 | {file = "pyyaml-6.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02ea2dfa234451bbb8772601d7b8e426c2bfa197136796224e50e35a78777956"}, 801 | {file = "pyyaml-6.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b30236e45cf30d2b8e7b3e85881719e98507abed1011bf463a8fa23e9c3e98a8"}, 802 | {file = "pyyaml-6.0.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:66291b10affd76d76f54fad28e22e51719ef9ba22b29e1d7d03d6777a9174198"}, 803 | {file = "pyyaml-6.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9c7708761fccb9397fe64bbc0395abcae8c4bf7b0eac081e12b809bf47700d0b"}, 804 | {file = "pyyaml-6.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:418cf3f2111bc80e0933b2cd8cd04f286338bb88bdc7bc8e6dd775ebde60b5e0"}, 805 | {file = "pyyaml-6.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5e0b74767e5f8c593e8c9b5912019159ed0533c70051e9cce3e8b6aa699fcd69"}, 806 | {file = "pyyaml-6.0.3-cp310-cp310-win32.whl", hash = "sha256:28c8d926f98f432f88adc23edf2e6d4921ac26fb084b028c733d01868d19007e"}, 807 | {file = "pyyaml-6.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:bdb2c67c6c1390b63c6ff89f210c8fd09d9a1217a465701eac7316313c915e4c"}, 808 | {file = "pyyaml-6.0.3-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:44edc647873928551a01e7a563d7452ccdebee747728c1080d881d68af7b997e"}, 809 | {file = "pyyaml-6.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:652cb6edd41e718550aad172851962662ff2681490a8a711af6a4d288dd96824"}, 810 | {file = "pyyaml-6.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:10892704fc220243f5305762e276552a0395f7beb4dbf9b14ec8fd43b57f126c"}, 811 | {file = "pyyaml-6.0.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:850774a7879607d3a6f50d36d04f00ee69e7fc816450e5f7e58d7f17f1ae5c00"}, 812 | {file = "pyyaml-6.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b8bb0864c5a28024fac8a632c443c87c5aa6f215c0b126c449ae1a150412f31d"}, 813 | {file = "pyyaml-6.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1d37d57ad971609cf3c53ba6a7e365e40660e3be0e5175fa9f2365a379d6095a"}, 814 | {file = "pyyaml-6.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:37503bfbfc9d2c40b344d06b2199cf0e96e97957ab1c1b546fd4f87e53e5d3e4"}, 815 | {file = "pyyaml-6.0.3-cp311-cp311-win32.whl", hash = "sha256:8098f252adfa6c80ab48096053f512f2321f0b998f98150cea9bd23d83e1467b"}, 816 | {file = "pyyaml-6.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:9f3bfb4965eb874431221a3ff3fdcddc7e74e3b07799e0e84ca4a0f867d449bf"}, 817 | {file = "pyyaml-6.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7f047e29dcae44602496db43be01ad42fc6f1cc0d8cd6c83d342306c32270196"}, 818 | {file = "pyyaml-6.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0"}, 819 | {file = "pyyaml-6.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28"}, 820 | {file = "pyyaml-6.0.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5fdec68f91a0c6739b380c83b951e2c72ac0197ace422360e6d5a959d8d97b2c"}, 821 | {file = "pyyaml-6.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc"}, 822 | {file = "pyyaml-6.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8dc52c23056b9ddd46818a57b78404882310fb473d63f17b07d5c40421e47f8e"}, 823 | {file = "pyyaml-6.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:41715c910c881bc081f1e8872880d3c650acf13dfa8214bad49ed4cede7c34ea"}, 824 | {file = "pyyaml-6.0.3-cp312-cp312-win32.whl", hash = "sha256:96b533f0e99f6579b3d4d4995707cf36df9100d67e0c8303a0c55b27b5f99bc5"}, 825 | {file = "pyyaml-6.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:5fcd34e47f6e0b794d17de1b4ff496c00986e1c83f7ab2fb8fcfe9616ff7477b"}, 826 | {file = "pyyaml-6.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:64386e5e707d03a7e172c0701abfb7e10f0fb753ee1d773128192742712a98fd"}, 827 | {file = "pyyaml-6.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8"}, 828 | {file = "pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1"}, 829 | {file = "pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c"}, 830 | {file = "pyyaml-6.0.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5"}, 831 | {file = "pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6"}, 832 | {file = "pyyaml-6.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6"}, 833 | {file = "pyyaml-6.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be"}, 834 | {file = "pyyaml-6.0.3-cp313-cp313-win32.whl", hash = "sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26"}, 835 | {file = "pyyaml-6.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c"}, 836 | {file = "pyyaml-6.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb"}, 837 | {file = "pyyaml-6.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac"}, 838 | {file = "pyyaml-6.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310"}, 839 | {file = "pyyaml-6.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7"}, 840 | {file = "pyyaml-6.0.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788"}, 841 | {file = "pyyaml-6.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5"}, 842 | {file = "pyyaml-6.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764"}, 843 | {file = "pyyaml-6.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35"}, 844 | {file = "pyyaml-6.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac"}, 845 | {file = "pyyaml-6.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3"}, 846 | {file = "pyyaml-6.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3"}, 847 | {file = "pyyaml-6.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba"}, 848 | {file = "pyyaml-6.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c"}, 849 | {file = "pyyaml-6.0.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702"}, 850 | {file = "pyyaml-6.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c"}, 851 | {file = "pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065"}, 852 | {file = "pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65"}, 853 | {file = "pyyaml-6.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9"}, 854 | {file = "pyyaml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b"}, 855 | {file = "pyyaml-6.0.3-cp39-cp39-macosx_10_13_x86_64.whl", hash = "sha256:b865addae83924361678b652338317d1bd7e79b1f4596f96b96c77a5a34b34da"}, 856 | {file = "pyyaml-6.0.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c3355370a2c156cffb25e876646f149d5d68f5e0a3ce86a5084dd0b64a994917"}, 857 | {file = "pyyaml-6.0.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3c5677e12444c15717b902a5798264fa7909e41153cdf9ef7ad571b704a63dd9"}, 858 | {file = "pyyaml-6.0.3-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5ed875a24292240029e4483f9d4a4b8a1ae08843b9c54f43fcc11e404532a8a5"}, 859 | {file = "pyyaml-6.0.3-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0150219816b6a1fa26fb4699fb7daa9caf09eb1999f3b70fb6e786805e80375a"}, 860 | {file = "pyyaml-6.0.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:fa160448684b4e94d80416c0fa4aac48967a969efe22931448d853ada8baf926"}, 861 | {file = "pyyaml-6.0.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:27c0abcb4a5dac13684a37f76e701e054692a9b2d3064b70f5e4eb54810553d7"}, 862 | {file = "pyyaml-6.0.3-cp39-cp39-win32.whl", hash = "sha256:1ebe39cb5fc479422b83de611d14e2c0d3bb2a18bbcb01f229ab3cfbd8fee7a0"}, 863 | {file = "pyyaml-6.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:2e71d11abed7344e42a8849600193d15b6def118602c4c176f748e4583246007"}, 864 | {file = "pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f"}, 865 | ] 866 | 867 | [[package]] 868 | name = "requests" 869 | version = "2.32.5" 870 | description = "Python HTTP for Humans." 871 | optional = false 872 | python-versions = ">=3.9" 873 | groups = ["dev"] 874 | markers = "python_version >= \"3.9\"" 875 | files = [ 876 | {file = "requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6"}, 877 | {file = "requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf"}, 878 | ] 879 | 880 | [package.dependencies] 881 | certifi = ">=2017.4.17" 882 | charset_normalizer = ">=2,<4" 883 | idna = ">=2.5,<4" 884 | urllib3 = ">=1.21.1,<3" 885 | 886 | [package.extras] 887 | socks = ["PySocks (>=1.5.6,!=1.5.7)"] 888 | use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] 889 | 890 | [[package]] 891 | name = "ruff" 892 | version = "0.14.9" 893 | description = "An extremely fast Python linter and code formatter, written in Rust." 894 | optional = false 895 | python-versions = ">=3.7" 896 | groups = ["dev"] 897 | files = [ 898 | {file = "ruff-0.14.9-py3-none-linux_armv6l.whl", hash = "sha256:f1ec5de1ce150ca6e43691f4a9ef5c04574ad9ca35c8b3b0e18877314aba7e75"}, 899 | {file = "ruff-0.14.9-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:ed9d7417a299fc6030b4f26333bf1117ed82a61ea91238558c0268c14e00d0c2"}, 900 | {file = "ruff-0.14.9-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d5dc3473c3f0e4a1008d0ef1d75cee24a48e254c8bed3a7afdd2b4392657ed2c"}, 901 | {file = "ruff-0.14.9-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:84bf7c698fc8f3cb8278830fb6b5a47f9bcc1ed8cb4f689b9dd02698fa840697"}, 902 | {file = "ruff-0.14.9-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:aa733093d1f9d88a5d98988d8834ef5d6f9828d03743bf5e338bf980a19fce27"}, 903 | {file = "ruff-0.14.9-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6a1cfb04eda979b20c8c19550c8b5f498df64ff8da151283311ce3199e8b3648"}, 904 | {file = "ruff-0.14.9-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:1e5cb521e5ccf0008bd74d5595a4580313844a42b9103b7388eca5a12c970743"}, 905 | {file = "ruff-0.14.9-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cd429a8926be6bba4befa8cdcf3f4dd2591c413ea5066b1e99155ed245ae42bb"}, 906 | {file = "ruff-0.14.9-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ab208c1b7a492e37caeaf290b1378148f75e13c2225af5d44628b95fd7834273"}, 907 | {file = "ruff-0.14.9-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72034534e5b11e8a593f517b2f2f2b273eb68a30978c6a2d40473ad0aaa4cb4a"}, 908 | {file = "ruff-0.14.9-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:712ff04f44663f1b90a1195f51525836e3413c8a773574a7b7775554269c30ed"}, 909 | {file = "ruff-0.14.9-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:a111fee1db6f1d5d5810245295527cda1d367c5aa8f42e0fca9a78ede9b4498b"}, 910 | {file = "ruff-0.14.9-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:8769efc71558fecc25eb295ddec7d1030d41a51e9dcf127cbd63ec517f22d567"}, 911 | {file = "ruff-0.14.9-py3-none-musllinux_1_2_i686.whl", hash = "sha256:347e3bf16197e8a2de17940cd75fd6491e25c0aa7edf7d61aa03f146a1aa885a"}, 912 | {file = "ruff-0.14.9-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:7715d14e5bccf5b660f54516558aa94781d3eb0838f8e706fb60e3ff6eff03a8"}, 913 | {file = "ruff-0.14.9-py3-none-win32.whl", hash = "sha256:df0937f30aaabe83da172adaf8937003ff28172f59ca9f17883b4213783df197"}, 914 | {file = "ruff-0.14.9-py3-none-win_amd64.whl", hash = "sha256:c0b53a10e61df15a42ed711ec0bda0c582039cf6c754c49c020084c55b5b0bc2"}, 915 | {file = "ruff-0.14.9-py3-none-win_arm64.whl", hash = "sha256:8e821c366517a074046d92f0e9213ed1c13dbc5b37a7fc20b07f79b64d62cc84"}, 916 | {file = "ruff-0.14.9.tar.gz", hash = "sha256:35f85b25dd586381c0cc053f48826109384c81c00ad7ef1bd977bfcc28119d5b"}, 917 | ] 918 | 919 | [[package]] 920 | name = "snowballstemmer" 921 | version = "3.0.1" 922 | description = "This package provides 32 stemmers for 30 languages generated from Snowball algorithms." 923 | optional = false 924 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*" 925 | groups = ["dev"] 926 | markers = "python_version >= \"3.9\"" 927 | files = [ 928 | {file = "snowballstemmer-3.0.1-py3-none-any.whl", hash = "sha256:6cd7b3897da8d6c9ffb968a6781fa6532dce9c3618a4b127d920dab764a19064"}, 929 | {file = "snowballstemmer-3.0.1.tar.gz", hash = "sha256:6d5eeeec8e9f84d4d56b847692bacf79bc2c8e90c7f80ca4444ff8b6f2e52895"}, 930 | ] 931 | 932 | [[package]] 933 | name = "sphinx" 934 | version = "7.4.7" 935 | description = "Python documentation generator" 936 | optional = false 937 | python-versions = ">=3.9" 938 | groups = ["dev"] 939 | markers = "python_version >= \"3.9\"" 940 | files = [ 941 | {file = "sphinx-7.4.7-py3-none-any.whl", hash = "sha256:c2419e2135d11f1951cd994d6eb18a1835bd8fdd8429f9ca375dc1f3281bd239"}, 942 | {file = "sphinx-7.4.7.tar.gz", hash = "sha256:242f92a7ea7e6c5b406fdc2615413890ba9f699114a9c09192d7dfead2ee9cfe"}, 943 | ] 944 | 945 | [package.dependencies] 946 | alabaster = ">=0.7.14,<0.8.0" 947 | babel = ">=2.13" 948 | colorama = {version = ">=0.4.6", markers = "sys_platform == \"win32\""} 949 | docutils = ">=0.20,<0.22" 950 | imagesize = ">=1.3" 951 | importlib-metadata = {version = ">=6.0", markers = "python_version < \"3.10\""} 952 | Jinja2 = ">=3.1" 953 | packaging = ">=23.0" 954 | Pygments = ">=2.17" 955 | requests = ">=2.30.0" 956 | snowballstemmer = ">=2.2" 957 | sphinxcontrib-applehelp = "*" 958 | sphinxcontrib-devhelp = "*" 959 | sphinxcontrib-htmlhelp = ">=2.0.0" 960 | sphinxcontrib-jsmath = "*" 961 | sphinxcontrib-qthelp = "*" 962 | sphinxcontrib-serializinghtml = ">=1.1.9" 963 | tomli = {version = ">=2", markers = "python_version < \"3.11\""} 964 | 965 | [package.extras] 966 | docs = ["sphinxcontrib-websupport"] 967 | lint = ["flake8 (>=6.0)", "importlib-metadata (>=6.0)", "mypy (==1.10.1)", "pytest (>=6.0)", "ruff (==0.5.2)", "sphinx-lint (>=0.9)", "tomli (>=2)", "types-docutils (==0.21.0.20240711)", "types-requests (>=2.30.0)"] 968 | test = ["cython (>=3.0)", "defusedxml (>=0.7.1)", "pytest (>=8.0)", "setuptools (>=70.0)", "typing_extensions (>=4.9)"] 969 | 970 | [[package]] 971 | name = "sphinxcontrib-applehelp" 972 | version = "2.0.0" 973 | description = "sphinxcontrib-applehelp is a Sphinx extension which outputs Apple help books" 974 | optional = false 975 | python-versions = ">=3.9" 976 | groups = ["dev"] 977 | markers = "python_version >= \"3.9\"" 978 | files = [ 979 | {file = "sphinxcontrib_applehelp-2.0.0-py3-none-any.whl", hash = "sha256:4cd3f0ec4ac5dd9c17ec65e9ab272c9b867ea77425228e68ecf08d6b28ddbdb5"}, 980 | {file = "sphinxcontrib_applehelp-2.0.0.tar.gz", hash = "sha256:2f29ef331735ce958efa4734873f084941970894c6090408b079c61b2e1c06d1"}, 981 | ] 982 | 983 | [package.extras] 984 | lint = ["mypy", "ruff (==0.5.5)", "types-docutils"] 985 | standalone = ["Sphinx (>=5)"] 986 | test = ["pytest"] 987 | 988 | [[package]] 989 | name = "sphinxcontrib-devhelp" 990 | version = "2.0.0" 991 | description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp documents" 992 | optional = false 993 | python-versions = ">=3.9" 994 | groups = ["dev"] 995 | markers = "python_version >= \"3.9\"" 996 | files = [ 997 | {file = "sphinxcontrib_devhelp-2.0.0-py3-none-any.whl", hash = "sha256:aefb8b83854e4b0998877524d1029fd3e6879210422ee3780459e28a1f03a8a2"}, 998 | {file = "sphinxcontrib_devhelp-2.0.0.tar.gz", hash = "sha256:411f5d96d445d1d73bb5d52133377b4248ec79db5c793ce7dbe59e074b4dd1ad"}, 999 | ] 1000 | 1001 | [package.extras] 1002 | lint = ["mypy", "ruff (==0.5.5)", "types-docutils"] 1003 | standalone = ["Sphinx (>=5)"] 1004 | test = ["pytest"] 1005 | 1006 | [[package]] 1007 | name = "sphinxcontrib-htmlhelp" 1008 | version = "2.1.0" 1009 | description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" 1010 | optional = false 1011 | python-versions = ">=3.9" 1012 | groups = ["dev"] 1013 | markers = "python_version >= \"3.9\"" 1014 | files = [ 1015 | {file = "sphinxcontrib_htmlhelp-2.1.0-py3-none-any.whl", hash = "sha256:166759820b47002d22914d64a075ce08f4c46818e17cfc9470a9786b759b19f8"}, 1016 | {file = "sphinxcontrib_htmlhelp-2.1.0.tar.gz", hash = "sha256:c9e2916ace8aad64cc13a0d233ee22317f2b9025b9cf3295249fa985cc7082e9"}, 1017 | ] 1018 | 1019 | [package.extras] 1020 | lint = ["mypy", "ruff (==0.5.5)", "types-docutils"] 1021 | standalone = ["Sphinx (>=5)"] 1022 | test = ["html5lib", "pytest"] 1023 | 1024 | [[package]] 1025 | name = "sphinxcontrib-jsmath" 1026 | version = "1.0.1" 1027 | description = "A sphinx extension which renders display math in HTML via JavaScript" 1028 | optional = false 1029 | python-versions = ">=3.5" 1030 | groups = ["dev"] 1031 | markers = "python_version >= \"3.9\"" 1032 | files = [ 1033 | {file = "sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8"}, 1034 | {file = "sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178"}, 1035 | ] 1036 | 1037 | [package.extras] 1038 | test = ["flake8", "mypy", "pytest"] 1039 | 1040 | [[package]] 1041 | name = "sphinxcontrib-qthelp" 1042 | version = "2.0.0" 1043 | description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp documents" 1044 | optional = false 1045 | python-versions = ">=3.9" 1046 | groups = ["dev"] 1047 | markers = "python_version >= \"3.9\"" 1048 | files = [ 1049 | {file = "sphinxcontrib_qthelp-2.0.0-py3-none-any.whl", hash = "sha256:b18a828cdba941ccd6ee8445dbe72ffa3ef8cbe7505d8cd1fa0d42d3f2d5f3eb"}, 1050 | {file = "sphinxcontrib_qthelp-2.0.0.tar.gz", hash = "sha256:4fe7d0ac8fc171045be623aba3e2a8f613f8682731f9153bb2e40ece16b9bbab"}, 1051 | ] 1052 | 1053 | [package.extras] 1054 | lint = ["mypy", "ruff (==0.5.5)", "types-docutils"] 1055 | standalone = ["Sphinx (>=5)"] 1056 | test = ["defusedxml (>=0.7.1)", "pytest"] 1057 | 1058 | [[package]] 1059 | name = "sphinxcontrib-serializinghtml" 1060 | version = "2.0.0" 1061 | description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)" 1062 | optional = false 1063 | python-versions = ">=3.9" 1064 | groups = ["dev"] 1065 | markers = "python_version >= \"3.9\"" 1066 | files = [ 1067 | {file = "sphinxcontrib_serializinghtml-2.0.0-py3-none-any.whl", hash = "sha256:6e2cb0eef194e10c27ec0023bfeb25badbbb5868244cf5bc5bdc04e4464bf331"}, 1068 | {file = "sphinxcontrib_serializinghtml-2.0.0.tar.gz", hash = "sha256:e9d912827f872c029017a53f0ef2180b327c3f7fd23c87229f7a8e8b70031d4d"}, 1069 | ] 1070 | 1071 | [package.extras] 1072 | lint = ["mypy", "ruff (==0.5.5)", "types-docutils"] 1073 | standalone = ["Sphinx (>=5)"] 1074 | test = ["pytest"] 1075 | 1076 | [[package]] 1077 | name = "tomli" 1078 | version = "2.3.0" 1079 | description = "A lil' TOML parser" 1080 | optional = false 1081 | python-versions = ">=3.8" 1082 | groups = ["dev"] 1083 | markers = "python_full_version <= \"3.11.0a6\"" 1084 | files = [ 1085 | {file = "tomli-2.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:88bd15eb972f3664f5ed4b57c1634a97153b4bac4479dcb6a495f41921eb7f45"}, 1086 | {file = "tomli-2.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:883b1c0d6398a6a9d29b508c331fa56adbcdff647f6ace4dfca0f50e90dfd0ba"}, 1087 | {file = "tomli-2.3.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d1381caf13ab9f300e30dd8feadb3de072aeb86f1d34a8569453ff32a7dea4bf"}, 1088 | {file = "tomli-2.3.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a0e285d2649b78c0d9027570d4da3425bdb49830a6156121360b3f8511ea3441"}, 1089 | {file = "tomli-2.3.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0a154a9ae14bfcf5d8917a59b51ffd5a3ac1fd149b71b47a3a104ca4edcfa845"}, 1090 | {file = "tomli-2.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:74bf8464ff93e413514fefd2be591c3b0b23231a77f901db1eb30d6f712fc42c"}, 1091 | {file = "tomli-2.3.0-cp311-cp311-win32.whl", hash = "sha256:00b5f5d95bbfc7d12f91ad8c593a1659b6387b43f054104cda404be6bda62456"}, 1092 | {file = "tomli-2.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:4dc4ce8483a5d429ab602f111a93a6ab1ed425eae3122032db7e9acf449451be"}, 1093 | {file = "tomli-2.3.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d7d86942e56ded512a594786a5ba0a5e521d02529b3826e7761a05138341a2ac"}, 1094 | {file = "tomli-2.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:73ee0b47d4dad1c5e996e3cd33b8a76a50167ae5f96a2607cbe8cc773506ab22"}, 1095 | {file = "tomli-2.3.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:792262b94d5d0a466afb5bc63c7daa9d75520110971ee269152083270998316f"}, 1096 | {file = "tomli-2.3.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4f195fe57ecceac95a66a75ac24d9d5fbc98ef0962e09b2eddec5d39375aae52"}, 1097 | {file = "tomli-2.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e31d432427dcbf4d86958c184b9bfd1e96b5b71f8eb17e6d02531f434fd335b8"}, 1098 | {file = "tomli-2.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7b0882799624980785240ab732537fcfc372601015c00f7fc367c55308c186f6"}, 1099 | {file = "tomli-2.3.0-cp312-cp312-win32.whl", hash = "sha256:ff72b71b5d10d22ecb084d345fc26f42b5143c5533db5e2eaba7d2d335358876"}, 1100 | {file = "tomli-2.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:1cb4ed918939151a03f33d4242ccd0aa5f11b3547d0cf30f7c74a408a5b99878"}, 1101 | {file = "tomli-2.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5192f562738228945d7b13d4930baffda67b69425a7f0da96d360b0a3888136b"}, 1102 | {file = "tomli-2.3.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:be71c93a63d738597996be9528f4abe628d1adf5e6eb11607bc8fe1a510b5dae"}, 1103 | {file = "tomli-2.3.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c4665508bcbac83a31ff8ab08f424b665200c0e1e645d2bd9ab3d3e557b6185b"}, 1104 | {file = "tomli-2.3.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4021923f97266babc6ccab9f5068642a0095faa0a51a246a6a02fccbb3514eaf"}, 1105 | {file = "tomli-2.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4ea38c40145a357d513bffad0ed869f13c1773716cf71ccaa83b0fa0cc4e42f"}, 1106 | {file = "tomli-2.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ad805ea85eda330dbad64c7ea7a4556259665bdf9d2672f5dccc740eb9d3ca05"}, 1107 | {file = "tomli-2.3.0-cp313-cp313-win32.whl", hash = "sha256:97d5eec30149fd3294270e889b4234023f2c69747e555a27bd708828353ab606"}, 1108 | {file = "tomli-2.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:0c95ca56fbe89e065c6ead5b593ee64b84a26fca063b5d71a1122bf26e533999"}, 1109 | {file = "tomli-2.3.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:cebc6fe843e0733ee827a282aca4999b596241195f43b4cc371d64fc6639da9e"}, 1110 | {file = "tomli-2.3.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:4c2ef0244c75aba9355561272009d934953817c49f47d768070c3c94355c2aa3"}, 1111 | {file = "tomli-2.3.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c22a8bf253bacc0cf11f35ad9808b6cb75ada2631c2d97c971122583b129afbc"}, 1112 | {file = "tomli-2.3.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0eea8cc5c5e9f89c9b90c4896a8deefc74f518db5927d0e0e8d4a80953d774d0"}, 1113 | {file = "tomli-2.3.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:b74a0e59ec5d15127acdabd75ea17726ac4c5178ae51b85bfe39c4f8a278e879"}, 1114 | {file = "tomli-2.3.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b5870b50c9db823c595983571d1296a6ff3e1b88f734a4c8f6fc6188397de005"}, 1115 | {file = "tomli-2.3.0-cp314-cp314-win32.whl", hash = "sha256:feb0dacc61170ed7ab602d3d972a58f14ee3ee60494292d384649a3dc38ef463"}, 1116 | {file = "tomli-2.3.0-cp314-cp314-win_amd64.whl", hash = "sha256:b273fcbd7fc64dc3600c098e39136522650c49bca95df2d11cf3b626422392c8"}, 1117 | {file = "tomli-2.3.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:940d56ee0410fa17ee1f12b817b37a4d4e4dc4d27340863cc67236c74f582e77"}, 1118 | {file = "tomli-2.3.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:f85209946d1fe94416debbb88d00eb92ce9cd5266775424ff81bc959e001acaf"}, 1119 | {file = "tomli-2.3.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a56212bdcce682e56b0aaf79e869ba5d15a6163f88d5451cbde388d48b13f530"}, 1120 | {file = "tomli-2.3.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c5f3ffd1e098dfc032d4d3af5c0ac64f6d286d98bc148698356847b80fa4de1b"}, 1121 | {file = "tomli-2.3.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5e01decd096b1530d97d5d85cb4dff4af2d8347bd35686654a004f8dea20fc67"}, 1122 | {file = "tomli-2.3.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:8a35dd0e643bb2610f156cca8db95d213a90015c11fee76c946aa62b7ae7e02f"}, 1123 | {file = "tomli-2.3.0-cp314-cp314t-win32.whl", hash = "sha256:a1f7f282fe248311650081faafa5f4732bdbfef5d45fe3f2e702fbc6f2d496e0"}, 1124 | {file = "tomli-2.3.0-cp314-cp314t-win_amd64.whl", hash = "sha256:70a251f8d4ba2d9ac2542eecf008b3c8a9fc5c3f9f02c56a9d7952612be2fdba"}, 1125 | {file = "tomli-2.3.0-py3-none-any.whl", hash = "sha256:e95b1af3c5b07d9e643909b5abbec77cd9f1217e6d0bca72b0234736b9fb1f1b"}, 1126 | {file = "tomli-2.3.0.tar.gz", hash = "sha256:64be704a875d2a59753d80ee8a533c3fe183e3f06807ff7dc2232938ccb01549"}, 1127 | ] 1128 | 1129 | [[package]] 1130 | name = "tox" 1131 | version = "4.25.0" 1132 | description = "tox is a generic virtualenv management and test command line tool" 1133 | optional = false 1134 | python-versions = ">=3.8" 1135 | groups = ["dev"] 1136 | files = [ 1137 | {file = "tox-4.25.0-py3-none-any.whl", hash = "sha256:4dfdc7ba2cc6fdc6688dde1b21e7b46ff6c41795fb54586c91a3533317b5255c"}, 1138 | {file = "tox-4.25.0.tar.gz", hash = "sha256:dd67f030317b80722cf52b246ff42aafd3ed27ddf331c415612d084304cf5e52"}, 1139 | ] 1140 | 1141 | [package.dependencies] 1142 | cachetools = ">=5.5.1" 1143 | chardet = ">=5.2" 1144 | colorama = ">=0.4.6" 1145 | filelock = ">=3.16.1" 1146 | packaging = ">=24.2" 1147 | platformdirs = ">=4.3.6" 1148 | pluggy = ">=1.5" 1149 | pyproject-api = ">=1.8" 1150 | tomli = {version = ">=2.2.1", markers = "python_version < \"3.11\""} 1151 | typing-extensions = {version = ">=4.12.2", markers = "python_version < \"3.11\""} 1152 | virtualenv = ">=20.29.1" 1153 | 1154 | [package.extras] 1155 | test = ["devpi-process (>=1.0.2)", "pytest (>=8.3.4)", "pytest-mock (>=3.14)"] 1156 | 1157 | [[package]] 1158 | name = "typing-extensions" 1159 | version = "4.13.2" 1160 | description = "Backported and Experimental Type Hints for Python 3.8+" 1161 | optional = false 1162 | python-versions = ">=3.8" 1163 | groups = ["dev"] 1164 | files = [ 1165 | {file = "typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c"}, 1166 | {file = "typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef"}, 1167 | ] 1168 | 1169 | [[package]] 1170 | name = "urllib3" 1171 | version = "2.6.0" 1172 | description = "HTTP library with thread-safe connection pooling, file post, and more." 1173 | optional = false 1174 | python-versions = ">=3.9" 1175 | groups = ["dev"] 1176 | markers = "python_version >= \"3.9\"" 1177 | files = [ 1178 | {file = "urllib3-2.6.0-py3-none-any.whl", hash = "sha256:c90f7a39f716c572c4e3e58509581ebd83f9b59cced005b7db7ad2d22b0db99f"}, 1179 | {file = "urllib3-2.6.0.tar.gz", hash = "sha256:cb9bcef5a4b345d5da5d145dc3e30834f58e8018828cbc724d30b4cb7d4d49f1"}, 1180 | ] 1181 | 1182 | [package.extras] 1183 | brotli = ["brotli (>=1.2.0) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=1.2.0.0) ; platform_python_implementation != \"CPython\""] 1184 | h2 = ["h2 (>=4,<5)"] 1185 | socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] 1186 | zstd = ["backports-zstd (>=1.0.0) ; python_version < \"3.14\""] 1187 | 1188 | [[package]] 1189 | name = "virtualenv" 1190 | version = "20.35.4" 1191 | description = "Virtual Python Environment builder" 1192 | optional = false 1193 | python-versions = ">=3.8" 1194 | groups = ["dev"] 1195 | files = [ 1196 | {file = "virtualenv-20.35.4-py3-none-any.whl", hash = "sha256:c21c9cede36c9753eeade68ba7d523529f228a403463376cf821eaae2b650f1b"}, 1197 | {file = "virtualenv-20.35.4.tar.gz", hash = "sha256:643d3914d73d3eeb0c552cbb12d7e82adf0e504dbf86a3182f8771a153a1971c"}, 1198 | ] 1199 | 1200 | [package.dependencies] 1201 | distlib = ">=0.3.7,<1" 1202 | filelock = ">=3.12.2,<4" 1203 | platformdirs = ">=3.9.1,<5" 1204 | typing-extensions = {version = ">=4.13.2", markers = "python_version < \"3.11\""} 1205 | 1206 | [package.extras] 1207 | docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2,!=7.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"] 1208 | 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)", "setuptools (>=68)", "time-machine (>=2.10) ; platform_python_implementation == \"CPython\""] 1209 | 1210 | [[package]] 1211 | name = "zipp" 1212 | version = "3.23.0" 1213 | description = "Backport of pathlib-compatible object wrapper for zip files" 1214 | optional = false 1215 | python-versions = ">=3.9" 1216 | groups = ["dev"] 1217 | markers = "python_version == \"3.9\"" 1218 | files = [ 1219 | {file = "zipp-3.23.0-py3-none-any.whl", hash = "sha256:071652d6115ed432f5ce1d34c336c0adfd6a884660d1e9712a256d3d3bd4b14e"}, 1220 | {file = "zipp-3.23.0.tar.gz", hash = "sha256:a07157588a12518c9d4034df3fbbee09c814741a33ff63c05fa29d26a2404166"}, 1221 | ] 1222 | 1223 | [package.extras] 1224 | check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\""] 1225 | cover = ["pytest-cov"] 1226 | doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] 1227 | enabler = ["pytest-enabler (>=2.2)"] 1228 | test = ["big-O", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more_itertools", "pytest (>=6,!=8.1.*)", "pytest-ignore-flaky"] 1229 | type = ["pytest-mypy"] 1230 | 1231 | [metadata] 1232 | lock-version = "2.1" 1233 | python-versions = ">=3.8,<4.0" 1234 | content-hash = "1d4bedf11c77edc9c3304daea9fd0e5f2b70a534a63827174734ff4c46a4122a" 1235 | --------------------------------------------------------------------------------