├── tests ├── __init__.py ├── test_generate_readme.py └── test_mypy_clean_slate.py ├── scripts ├── __init__.py └── add_help_to_readme.py ├── mypy_clean_slate ├── __init__.py └── main.py ├── setup.cfg ├── .gitignore ├── .github ├── dependabot.yml └── workflows │ ├── dependabot.yml │ ├── release.yml │ └── test.yml ├── .pre-commit-config.yaml ├── LICENSE ├── Makefile ├── pyproject.toml ├── README.md └── uv.lock /tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /scripts/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /mypy_clean_slate/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | __version__ = "0.4.0" 4 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [flake8] 2 | eradicate-aggressive = False 3 | max-line-length = 89 4 | extend-ignore = 5 | D1, # don't enforce docstrings, but check if they exist. 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | .DS_Store 3 | dist/ 4 | build/ 5 | *.egg-info/ 6 | .python-version 7 | .coverage 8 | .uv 9 | requirements.txt 10 | requirements-dev.txt 11 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | # GitHub Actions 9 | - package-ecosystem: "github-actions" 10 | directory: "/" 11 | schedule: 12 | interval: "daily" 13 | commit-message: 14 | prefix: ⬆ 15 | # Python 16 | - package-ecosystem: "pip" 17 | directory: "/" 18 | schedule: 19 | interval: "daily" 20 | commit-message: 21 | prefix: ⬆ 22 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/pre-commit/pre-commit-hooks 3 | rev: v4.5.0 4 | hooks: 5 | - id: check-added-large-files 6 | - id: check-ast 7 | - id: check-case-conflict 8 | - id: check-docstring-first 9 | - id: check-executables-have-shebangs 10 | - id: check-merge-conflict 11 | - id: check-toml 12 | - id: check-vcs-permalinks 13 | - id: check-yaml 14 | - id: debug-statements 15 | - id: destroyed-symlinks 16 | - id: detect-private-key 17 | - id: end-of-file-fixer 18 | - id: fix-byte-order-marker 19 | - id: fix-encoding-pragma 20 | args: ["--remove"] 21 | - id: forbid-new-submodules 22 | - id: mixed-line-ending 23 | - id: trailing-whitespace 24 | -------------------------------------------------------------------------------- /.github/workflows/dependabot.yml: -------------------------------------------------------------------------------- 1 | name: Dependabot auto-approve 2 | on: pull_request_target 3 | 4 | permissions: 5 | contents: write 6 | pull-requests: write 7 | 8 | jobs: 9 | dependabot: 10 | runs-on: ubuntu-latest 11 | if: ${{ github.actor == 'dependabot[bot]' }} 12 | steps: 13 | - name: Dependabot metadata 14 | id: metadata 15 | uses: dependabot/fetch-metadata@v2.4.0 16 | with: 17 | github-token: "${{ secrets.GITHUB_TOKEN }}" 18 | - name: Enable auto-merge for Dependabot PRs 19 | if: ${{steps.metadata.outputs.update-type == 'version-update:semver-patch' || steps.metadata.outputs.update-type == 'version-update:semver-minor'}} 20 | run: gh pr merge --auto --merge "$PR_URL" 21 | env: 22 | PR_URL: ${{github.event.pull_request.html_url}} 23 | GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} 24 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | tags: 6 | - '*' 7 | 8 | jobs: 9 | release: 10 | 11 | environment: 12 | name: pypi 13 | url: https://pypi.org/project/${{ github.event.repository.name }} 14 | 15 | runs-on: ubuntu-latest 16 | permissions: 17 | contents: write 18 | id-token: write 19 | 20 | steps: 21 | - uses: actions/checkout@v4 22 | 23 | - name: Install uv 24 | uses: astral-sh/setup-uv@v4 25 | with: 26 | version: "latest" 27 | 28 | - name: Set up Python 29 | run: uv python install 3.12 30 | 31 | - name: Install dependencies 32 | run: uv sync 33 | 34 | - name: Build package 35 | run: uv build 36 | 37 | - name: Publish to PyPI 38 | uses: pypa/gh-action-pypi-publish@release/v1 39 | 40 | - name: Create GitHub Release 41 | uses: softprops/action-gh-release@v2 42 | with: 43 | files: dist/* 44 | generate_release_notes: true 45 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 geo7 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 | -------------------------------------------------------------------------------- /tests/test_generate_readme.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import pathlib 4 | import sys 5 | 6 | import pytest 7 | 8 | from scripts import add_help_to_readme 9 | 10 | 11 | @pytest.mark.skipif( 12 | # This test isn't critical to any application logic, and is caught by 13 | # testing on other versions in CI. Change here is that argparse from >3.9 14 | # uses 'options' rather than 'optional arguments'. As long as it generates 15 | # something correctly on _a_ python version I'm fine. 16 | sys.version_info < (3, 13), 17 | reason="Changes in argparse output.", 18 | ) 19 | def test_readme_cli_help() -> None: 20 | """Test the README has up to date help output.""" 21 | 22 | # For some reason I was getting some whitespace differences when generating 23 | # in different places, not sure why this was (the content was the same 24 | # otherwise) so am just comparing without \n or ' ' 25 | def strp(s: str) -> str: 26 | return s.replace("\n", "").replace(" ", "") 27 | 28 | updated = strp(add_help_to_readme.update_readme_cli_help()) 29 | existing = strp(pathlib.Path("README.md").read_text()) 30 | assert updated == existing 31 | -------------------------------------------------------------------------------- /scripts/add_help_to_readme.py: -------------------------------------------------------------------------------- 1 | """ 2 | Add --help output from cli to README usage section. 3 | 4 | Little script to make it easier to keep the README Usage section up to date with 5 | the parsers help output. 6 | """ 7 | 8 | from io import StringIO 9 | from pathlib import Path 10 | 11 | from mypy_clean_slate.main import create_parser 12 | 13 | 14 | def cli_help_text() -> str: 15 | """Get --help from argparse parser.""" 16 | parser = create_parser() 17 | cli_help = StringIO() 18 | parser.print_help(file=cli_help) 19 | return cli_help.getvalue() 20 | 21 | 22 | def update_readme_cli_help() -> str: 23 | """Generate README with updated cli --help.""" 24 | result = cli_help_text() 25 | readme = Path("./README.md").read_text() 26 | split_string = "[comment]: # (CLI help split)\n" 27 | splits = readme.split(split_string) 28 | return splits[0] + split_string + "\n```\n" + result + "\n```\n\n" + split_string + splits[2] 29 | 30 | 31 | def main() -> int: 32 | updated_readme = update_readme_cli_help() 33 | with open("README.md", "w") as f: 34 | f.write(updated_readme) 35 | return 0 36 | 37 | 38 | if __name__ == "__main__": 39 | raise SystemExit(main()) 40 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: [push] 3 | 4 | jobs: 5 | linting: 6 | runs-on: ubuntu-latest 7 | steps: 8 | - name: Check out repository 9 | uses: actions/checkout@v4 10 | - name: Set up python "3.13" 11 | uses: actions/setup-python@v6 12 | with: 13 | python-version: "3.13" 14 | - name: Set up uv 15 | uses: astral-sh/setup-uv@v4 16 | - name: Install dependencies 17 | run: uv sync --all-extras 18 | - name: ruff format 19 | run: uv run ruff format . --check 20 | - name: ruff check 21 | run: uv run ruff check . 22 | 23 | test: 24 | needs: linting 25 | strategy: 26 | fail-fast: true 27 | matrix: 28 | os: [ "ubuntu-latest" ] 29 | python-version: [ "3.9", "3.10", "3.11", "3.12", "3.13" ] 30 | runs-on: ${{ matrix.os }} 31 | steps: 32 | - name: Check out repository 33 | uses: actions/checkout@v4 34 | - name: Set up python ${{ matrix.python-version }} 35 | uses: actions/setup-python@v6 36 | with: 37 | python-version: ${{ matrix.python-version }} 38 | - name: Set up uv 39 | uses: astral-sh/setup-uv@v4 40 | - name: Install dependencies 41 | run: uv sync --all-extras 42 | - name: Install library 43 | run: uv pip install -e . 44 | - name: Pytest ${{ matrix.python-version }} 45 | run: uv run pytest 46 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: clean requirements 2 | .PHONY: git-stats git-log cloc clean-git 3 | .PHONY: deploy 4 | .PHONY: test 5 | .PHONY: requirements 6 | .PHONY: help 7 | 8 | CLOC := cloc 9 | 10 | ######### 11 | # UTILS # 12 | ######### 13 | 14 | help: 15 | @awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf "\033[36m%-15s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST) | sort 16 | 17 | clean: 18 | @find . -path './.venv' -prune -o -type f -name "*.pyc" -delete 19 | @find . -path './.venv' -prune -o -type d -name "__pycache__" -exec rm -rf {} + 20 | @find . -path './.venv' -prune -o -type d -name ".pytest_cache" -exec rm -rf {} + 21 | @find . -path './.venv' -prune -o -type d -name ".mypy_cache" -exec rm -rf {} + 22 | @find . -path './.venv' -prune -o -type d -name ".ipynb_checkpoints" -exec rm -rf {} + 23 | 24 | cloc: 25 | @echo "Code statistics using cloc:" 26 | $(CLOC) --exclude-dir=venv . 27 | 28 | readme: 29 | uv run python -m scripts.add_help_to_readme 30 | 31 | ######## 32 | # LINT # 33 | ######## 34 | 35 | pre-commit-run: 36 | uv run pre-commit run --all-files 37 | 38 | mypy: 39 | uv run mypy --strict . 40 | 41 | lint: mypy 42 | uv run ruff check . 43 | uv run ruff format . --check 44 | @$(MAKE) --no-print-directory clean 45 | 46 | format: pre-commit-run 47 | uv run ruff format . 48 | uv run ruff check . --fix 49 | @$(MAKE) --no-print-directory clean 50 | 51 | ######## 52 | # UV # 53 | ######## 54 | 55 | uv.lock: 56 | uv lock --check || uv lock 57 | 58 | install: uv.lock 59 | uv sync --all-extras 60 | @$(MAKE) --no-print-directory clean 61 | 62 | ########## 63 | # PYTEST # 64 | ########## 65 | 66 | test: ## run tests 67 | uv run pytest -vv --cov=mypy_clean_slate --cov-report=html 68 | uv run coverage html 69 | @$(MAKE) --no-print-directory clean 70 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "mypy_clean_slate" 3 | version = "0.4.0" 4 | description = "CLI tool for providing a clean slate for mypy usage within a project." 5 | authors = [{ name = "George Lenton", email = "georgelenton@gmail.com" }] 6 | license = { text = "MIT" } 7 | readme = "README.md" 8 | requires-python = ">=3.9" 9 | keywords = ["mypy", "typing", "typehint", "type-hint"] 10 | dependencies = [ 11 | "mypy>=0.910,<2.0", 12 | ] 13 | 14 | [project.urls] 15 | Homepage = "https://github.com/geo7/mypy_clean_slate" 16 | 17 | [project.scripts] 18 | mypy_clean_slate = "mypy_clean_slate.main:main" 19 | 20 | [project.optional-dependencies] 21 | dev = [ 22 | "pytest>=8.0.0,<9.0.0", 23 | "pre-commit>=4.0.0", 24 | "ipython>=8.18.1", 25 | "ipdb>=0.13.9,<0.14.0", 26 | "ruff>=0.0.265", 27 | "pytest-cov>=5.0.0", 28 | "pdbpp>=0.10.3,<0.12.0", 29 | ] 30 | 31 | 32 | [build-system] 33 | requires = ["hatchling"] 34 | build-backend = "hatchling.build" 35 | 36 | [tool.ruff] 37 | line-length = 100 38 | 39 | [tool.ruff.lint] 40 | select = ["ALL"] 41 | ignore = [ 42 | "ANN204", # Missing return type annotation for special method `__attrs_post_init__` 43 | "ANN206", # Missing return type annotation for classmethod `get_all_human_readable` 44 | "D100", # Missing docstring in public module 45 | "D101", # Missing docstring in public class 46 | "D102", # Missing docstring in public method 47 | "D103", # Missing docstring in public function 48 | "D104", # Missing docstring in public package 49 | "D105", # Missing docstring in magic method 50 | "D107", # Missing docstring in `__init__` 51 | "D203", # Conflicts with formatter 52 | "D211", # no-blank-line-before-class 53 | "D212", # multi-line-summary-first-line 54 | "D401", # First line of docstring should be in imperative mood. 55 | "FIX002", # Line contains TODO, consider resolving the issue 56 | "COM812", # missing-trailing-comma 57 | "ISC001", # single-line-implicit-string-concatenation 58 | "PD901", # `df` is a bad variable name. 59 | "PLR0913", # Too many arguments to function call (6 > 5) 60 | "PLW1510", # `subprocess.run` without explicit `check` argument 61 | "PTH123", # `open()` should be replaced by `Path.open()` 62 | "PTH201", # [*] Do not pass the current directory explicitly to `Path` 63 | "RUF010", # [*] Use explicit conversion flag 64 | "S311", # Standard pseudo-random generators are not suitable for cryptographic purposes 65 | "S603", # `subprocess` call: check for execution of untrusted input 66 | "T100", # Trace found: `breakpoint` used 67 | "T201", # `print` found 68 | ] 69 | fixable = ["ALL"] 70 | unfixable = [] 71 | 72 | [tool.ruff.lint.per-file-ignores] 73 | "__init__.py" = ["F401"] 74 | "scratch/*" = ["ALL"] 75 | "tests/*" = [ 76 | "ANN001", # Missing type annotation for function argument `tmpdir` 77 | "ANN201", # Missing return type annotation for public function `test_get_file_types` 78 | "D100", # Missing docstring in public module 79 | "D101", # Missing docstring in public class 80 | "D102", # Missing docstring in public method 81 | "S101", # Use of `assert` detected 82 | ] 83 | 84 | [tool.ruff.lint.isort] 85 | section-order = ["future", "standard-library", "third-party", "first-party", "local-folder"] 86 | case-sensitive = true 87 | combine-as-imports = true 88 | -------------------------------------------------------------------------------- /tests/test_mypy_clean_slate.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import pathlib 4 | import textwrap 5 | 6 | from mypy_clean_slate import __version__, main 7 | 8 | 9 | def test_version() -> None: 10 | # Ensure toml version is in sync with package version. 11 | with open("pyproject.toml") as f: 12 | pyproject_version = [line for line in f if line.startswith("version = ")] 13 | assert len(pyproject_version) == 1 14 | assert pyproject_version[0].strip().split(" = ")[-1].replace('"', "") == __version__ 15 | 16 | 17 | def test_mypy_clean_slate_usage(tmp_path: pathlib.Path) -> None: 18 | # atm this is a pretty broad usage test - just checks that things are, pretty much, 19 | # working as expected. 20 | py_file_before_fix = textwrap.dedent( 21 | """ 22 | from __future__ import annotations 23 | 24 | 25 | def add(*, arg_1, arg_2): 26 | return arg_1 + arg_2 27 | 28 | 29 | add(arg_1=1, arg_2="s") # inline comment. 30 | 31 | 32 | def useless_sub(*, arg_1: float, arg_2: Sequence): 33 | return add(arg_1=arg_1, arg_2="what") - arg_2 34 | 35 | 36 | useless_sub(arg_1=3, arg_2=4) 37 | useless_sub(arg_1=3, arg_2="4") 38 | """, 39 | ).strip() 40 | 41 | py_file_after_fix = textwrap.dedent( 42 | """ 43 | from __future__ import annotations 44 | 45 | 46 | def add(*, arg_1, arg_2): # type: ignore[no-untyped-def] 47 | return arg_1 + arg_2 48 | 49 | 50 | add(arg_1=1, arg_2="s") # type: ignore[no-untyped-call] # inline comment. 51 | 52 | 53 | def useless_sub(*, arg_1: float, arg_2: Sequence): # type: ignore[name-defined, no-untyped-def] 54 | return add(arg_1=arg_1, arg_2="what") - arg_2 # type: ignore[no-untyped-call] 55 | 56 | 57 | useless_sub(arg_1=3, arg_2=4) 58 | useless_sub(arg_1=3, arg_2="4") 59 | """.strip(), 60 | ) 61 | 62 | python_file = pathlib.Path(tmp_path, "file_to_check.py") 63 | python_file.write_text(py_file_before_fix, encoding="utf8") 64 | 65 | # there's probably a much nicer way to write these tests. 66 | report_output = pathlib.Path(tmp_path, "testing_report_output.txt") 67 | report_output.write_text( 68 | main.generate_mypy_error_report(path_to_code=python_file, mypy_flags=[""]), 69 | encoding="utf8", 70 | ) 71 | 72 | main.add_type_ignores(report_output=report_output) 73 | assert python_file.read_text(encoding="utf8").strip() == py_file_after_fix 74 | 75 | 76 | def test_no_duplicate_codes_added(tmp_path: pathlib.Path) -> None: 77 | """Ensure duplicate ignore messages aren't applied.""" 78 | py_file_before_fix = textwrap.dedent( 79 | """ 80 | from __future__ import annotations 81 | 82 | object().foo, object().bar 83 | """, 84 | ).strip() 85 | 86 | py_file_after_fix = textwrap.dedent( 87 | """ 88 | from __future__ import annotations 89 | 90 | object().foo, object().bar # type: ignore[attr-defined] 91 | """, 92 | ).strip() 93 | 94 | python_file = pathlib.Path(tmp_path, "file_to_check.py") 95 | python_file.write_text(py_file_before_fix, encoding="utf8") 96 | 97 | report_output = pathlib.Path(tmp_path, "testing_report_output.txt") 98 | report_output.write_text( 99 | main.generate_mypy_error_report(path_to_code=python_file, mypy_flags=[""]), 100 | encoding="utf8", 101 | ) 102 | 103 | main.add_type_ignores(report_output=report_output) 104 | assert python_file.read_text(encoding="utf8").strip() == py_file_after_fix 105 | 106 | 107 | def test_custom_mypy_flags(tmp_path: pathlib.Path) -> None: 108 | """Ensure custom mypy flags are respected.""" 109 | py_file_before_fix = textwrap.dedent( 110 | """ 111 | def f(x): 112 | return x ** 2 113 | 114 | def main() -> int: 115 | y = f(12) 116 | return 0 117 | 118 | if __name__ == '__main__': 119 | raise SystemExit(main()) 120 | """, 121 | ).strip() 122 | 123 | py_file_after_fix = textwrap.dedent( 124 | """ 125 | def f(x): 126 | return x ** 2 127 | 128 | def main() -> int: 129 | y = f(12) # type: ignore[no-untyped-call] 130 | return 0 131 | 132 | if __name__ == '__main__': 133 | raise SystemExit(main()) 134 | """, 135 | ).strip() 136 | 137 | python_file = pathlib.Path(tmp_path, "file_to_check.py") 138 | python_file.write_text(py_file_before_fix, encoding="utf8") 139 | 140 | # there's probably a much nicer way to write these tests. 141 | report_output = pathlib.Path(tmp_path, "testing_report_output.txt") 142 | report_output.write_text( 143 | main.generate_mypy_error_report( 144 | path_to_code=python_file, 145 | mypy_flags=["--disallow-untyped-calls"], 146 | ), 147 | encoding="utf8", 148 | ) 149 | 150 | main.add_type_ignores(report_output=report_output) 151 | assert python_file.read_text(encoding="utf8").strip() == py_file_after_fix 152 | 153 | 154 | def test_remove_used_ignores(tmp_path: pathlib.Path) -> None: 155 | """Ensure unused ignores raised as errors are removed.""" 156 | py_file_before_fix = textwrap.dedent( 157 | """ 158 | def f(x : float) -> float: 159 | return x ** 2 160 | 161 | def main() -> int: 162 | y = f(12) # type: ignore[no-untyped-call] 163 | return 0 164 | 165 | if __name__ == '__main__': 166 | raise SystemExit(main()) 167 | """, 168 | ).strip() 169 | 170 | py_file_after_fix = textwrap.dedent( 171 | """ 172 | def f(x : float) -> float: 173 | return x ** 2 174 | 175 | def main() -> int: 176 | y = f(12) 177 | return 0 178 | 179 | if __name__ == '__main__': 180 | raise SystemExit(main()) 181 | """, 182 | ).strip() 183 | 184 | python_file = pathlib.Path(tmp_path, "file_to_check.py") 185 | python_file.write_text(py_file_before_fix, encoding="utf8") 186 | 187 | # there's probably a much nicer way to write these tests. 188 | report_output = pathlib.Path(tmp_path, "testing_report_output.txt") 189 | report_output.write_text( 190 | main.generate_mypy_error_report( 191 | path_to_code=python_file, 192 | mypy_flags=[""], 193 | ), 194 | encoding="utf8", 195 | ) 196 | main.remove_unused_ignores(report_output=report_output) 197 | main.add_type_ignores(report_output=report_output) 198 | assert python_file.read_text(encoding="utf8").strip() == py_file_after_fix 199 | 200 | 201 | def test_hash_in_string_literal() -> None: 202 | """Ensure that '#' in a string literal is not treated as a comment.""" 203 | line = 'my_string = "hello #world"' 204 | code, comment = main.extract_code_comment(line=line) 205 | assert code == line 206 | assert comment == "" 207 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Mypy Clean Slate 2 | 3 | 4 | 5 | [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff) 6 | [![PyPI Latest Release](https://img.shields.io/pypi/v/mypy-clean-slate.svg)](https://pypi.org/project/mypy-clean-slate/) 7 | [![License](https://img.shields.io/pypi/l/mypy-clean-slate.svg)](https://github.com/geo7/mypy_clean_slate/blob/main/LICENSE) 8 | [![image](https://img.shields.io/pypi/pyversions/mypy-clean-slate.svg)](https://pypi.python.org/pypi/mypy-clean-slate) 9 | [![Actions status](https://github.com/geo7/mypy_clean_slate/workflows/CI/badge.svg)](https://github.com/geo7/mypy_clean_slate/actions) 10 | 11 | > _**Note:** This project was initially created to address a specific need with 12 | > some projects I was working on. While it may still be useful to others, It's 13 | > not something I'd typically use. I'd typically opt for ignoring rules / files 14 | > within pyproject.toml first._ 15 | 16 | CLI tool for providing a clean slate for mypy usage within a project 17 | 18 | ## Motivation 19 | 20 | It can be difficult to get a large project to the point where `mypy --strict` 21 | can be run on it. Rather than incrementally increasing the severity of mypy, 22 | either overall or per module, `mypy_clean_slate` enables one to ignore all 23 | previous errors so that `mypy --strict` (or similar) can be used almost 24 | immediately. This enables all code written from that point on to be checked with 25 | `mypy --strict` (or whichever flags are preferred), gradually removing the 26 | `type: ignore` comments from that point onwards. 27 | 28 | Often running `mypy_clean_slate` will cover all errors cleanly in a single pass, 29 | but there are cases when not all error output is generated first time, and it 30 | can be necessary to run a couple of times, checking the diffs. Example of this 31 | scenario is given. 32 | 33 | By default `mypy_clean_slate` works by parsing the output of `mypy --strict` and 34 | adding the relevant `type: ignore[code]` to each line, though custom flags can 35 | be passed to mypy instead. Only errors from the report are considered, notes are 36 | not handled. Meaning something such as `error: Function is missing a type 37 | annotation [no-untyped-def]` will have `# type: ignore[no-untyped-def]` 38 | appended to the end of the line, whereas `note: (Skipping most remaining errors 39 | due to unresolved imports or missing stubs; fix these first)` will be ignored. 40 | Errors relating to unused ignores (which might occur if code changes after 41 | adding the initial ignore) can also be handled. 42 | 43 | # Installation 44 | 45 | ```bash 46 | pip install mypy-clean-slate 47 | ``` 48 | 49 | # Usage 50 | 51 | [comment]: # (CLI help split) 52 | 53 | ``` 54 | usage: mypy_clean_slate [options] 55 | 56 | CLI tool for providing a clean slate for mypy usage within a project. 57 | 58 | Default expectation is to want to get a project into a state that it 59 | will pass mypy when run with `--strict`, if this isn't the case custom 60 | flags can be passed to mypy via the `--mypy_flags` argument. 61 | 62 | options: 63 | -h, --help show this help message and exit 64 | -r, --generate_mypy_error_report 65 | Generate 'mypy_error_report.txt' in the cwd. 66 | -p, --path_to_code PATH_TO_CODE 67 | Where code is that needs report generating for it. 68 | -a, --add_type_ignore 69 | Add "# type: ignore[]" to suppress all raised mypy errors. 70 | --remove_unused Remove unused instances of "# type: ignore[]" if raised as an error by mypy. 71 | -o, --mypy_report_output MYPY_REPORT_OUTPUT 72 | File to save report output to (default is mypy_error_report.txt) 73 | --mypy_flags MYPY_FLAGS 74 | Custom flags to pass to mypy (provide them as a single string, default is to use --strict) 75 | 76 | ``` 77 | 78 | [comment]: # (CLI help split) 79 | 80 | See `./tests/test_mypy_clean_slate.py` for some examples with before/after. 81 | 82 | 83 | 84 | # Examples 85 | 86 | ## Simple example 87 | 88 | Given a project with only: 89 | 90 | ```txt 91 | ➜ simple_example git:(master) ✗ tree 92 | . 93 | `-- simple.py 94 | 95 | 0 directories, 1 file 96 | ``` 97 | 98 | Containing: 99 | 100 | ```python 101 | # simple.py 102 | def f(x): 103 | return x + 1 104 | ``` 105 | 106 | The report can be generated, and `simple.py` updated, using `mypy_clean_slate -ra`, resulting in: 107 | 108 | 109 | ```python 110 | def f(x): # type: ignore[no-untyped-def] 111 | return x + 1 112 | ``` 113 | 114 | And `mypy --strict` will now pass. 115 | 116 | ## Project example, using `pingouin` 117 | 118 | Project `pingouin` is located at: https://github.com/raphaelvallat/pingouin, and 119 | commit `ea8b5605a1776aaa0e89dd5c0e3df4320950fb38` is used for this example. 120 | `mypy_clean_slate` needs to be run a couple of times here. 121 | 122 | First, generate report and apply `type: ignore[]` 123 | 124 | ```sh 125 | mypy_clean_slate -ra 126 | ``` 127 | 128 | Looking at a subset of `git diff`: 129 | 130 | ```diff 131 | 132 | (venv) ➜ pingouin git:(master) ✗ git diff | grep 'type' | head 133 | +import sphinx_bootstrap_theme # type: ignore[import] 134 | +from outdated import warn_if_outdated # type: ignore[import] 135 | +import numpy as np # type: ignore[import] 136 | +from scipy.integrate import quad # type: ignore[import] 137 | + from scipy.special import gamma, betaln, hyp2f1 # type: ignore[import] 138 | + from mpmath import hyp3f2 # type: ignore[import] 139 | + from scipy.stats import binom # type: ignore[import] 140 | +import numpy as np # type: ignore[import] 141 | +from scipy.stats import norm # type: ignore[import] 142 | +import numpy as np # type: ignore[import] 143 | ``` 144 | 145 | Changes are added and committed with message `'mypy_clean_slate first pass'` (commit message used makes no functional difference), and the report re-generated: 146 | 147 | ```bash 148 | mypy_clean_slate -r 149 | ``` 150 | 151 | Which reports `Found 1107 errors in 39 files (checked 42 source files)`. So, re-running `mypy_clean_slate` 152 | 153 | ```bash 154 | mypy_clean_slate -a 155 | ``` 156 | 157 | And looking again at the diff: 158 | 159 | ```diff 160 | 161 | (venv) ➜ pingouin git:(master) ✗ gd | grep 'type' | head 162 | +latex_elements = { # type: ignore[var-annotated] 163 | +def setup(app): # type: ignore[no-untyped-def] 164 | @@ -27,4 +27,4 @@ from outdated import warn_if_outdated # type: ignore[import] 165 | +set_default_options() # type: ignore[no-untyped-call] 166 | +def _format_bf(bf, precision=3, trim='0'): # type: ignore[no-untyped-def] 167 | if type(bf) == str: 168 | +def bayesfactor_ttest(t, nx, ny=None, paired=False, tail='two-sided', r=.707): # type: ignore[no-untyped-def] 169 | + def fun(g, t, n, r, df): # type: ignore[no-untyped-def] 170 | +def bayesfactor_pearson(r, n, tail='two-sided', method='ly', kappa=1.): # type: ignore[no-untyped-def] 171 | + def fun(g, r, n): # type: ignore[no-untyped-def] 172 | ``` 173 | 174 | Committing these with `'mypy_clean_slate second pass'`, and re-running `mypy_clean_slate -r` outputs the following: 175 | 176 | ```txt 177 | (venv) ➜ pingouin git:(master) ✗ cat mypy_error_report.txt 178 | Success: no issues found in 42 source files 179 | ``` 180 | 181 | Can now rebase / amend commits as necessary, but could now update CI/pre-commit or whatever to use `mypy --strict` (or a subset of its flags) going forwards. 182 | 183 | 184 | # Handling of existing comments and `pylint` 185 | 186 | Lines which contain existing comments such as: 187 | 188 | ```python 189 | def ThisFunction(something): # pylint: disable=invalid-name 190 | return f"this is {something}" 191 | ``` 192 | 193 | Will be updated to: 194 | 195 | ```python 196 | def ThisFunction(something): # type: ignore[no-untyped-def] # pylint: disable=invalid-name 197 | return f"this is {something}" 198 | ``` 199 | 200 | As the `type:` comment needs to precede pylints. 201 | 202 | # Issues 203 | 204 | ## Generating report 205 | 206 | The report generation is pretty straightforward, `mypy . --strict --show-error-codes`, so might not be worth having as part of this script. The user can generate the report to a text file and just pass the path to that as an argument. 207 | 208 | ## Handling `-> None` 209 | 210 | Report output for functions which don't return is pretty consistent, so these could be automated if considered worth it. 211 | 212 | ## Integration with other tooling 213 | 214 | I've tried to consider `pylint` comments, but no doubt there are many other arguments for different tools which aren't taken into consideration. 215 | -------------------------------------------------------------------------------- /mypy_clean_slate/main.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import argparse 4 | import io 5 | import itertools 6 | import logging 7 | import pathlib 8 | import re 9 | import shlex 10 | import subprocess 11 | import sys 12 | import textwrap 13 | import tokenize 14 | import warnings 15 | from typing import TYPE_CHECKING, TypeVar 16 | 17 | if TYPE_CHECKING: 18 | from collections.abc import Sequence 19 | 20 | 21 | T = TypeVar("T") 22 | # contains (file_path, line_number, error_code); file to update, line within that file to 23 | # append `type: ignore[]` 24 | FileUpdate = tuple[str, int, str] 25 | 26 | log = logging.getLogger(__name__) 27 | 28 | 29 | DEFAULT_REPORT_FILE = "mypy_error_report.txt" 30 | 31 | 32 | def raise_if_none(*, value: T | None) -> T: 33 | if value is None: 34 | msg = "None value" 35 | raise RuntimeError(msg) 36 | return value 37 | 38 | 39 | def generate_mypy_error_report( 40 | *, 41 | path_to_code: pathlib.Path, 42 | mypy_flags: list[str], 43 | ) -> str: 44 | """Run mypy and generate report with errors.""" 45 | no_arguments_passed = (len(mypy_flags) == 0) or ((len(mypy_flags) == 1) and mypy_flags[0] == "") 46 | 47 | if no_arguments_passed: 48 | # If no flags are passed we just assume we want to get things ready to 49 | # use with --strict going forwards. 50 | mypy_command = [ 51 | "mypy", 52 | f"{str(path_to_code)}", 53 | # Want error codes output from mypy to re-add in ignores. 54 | "--show-error-codes", 55 | # pretty output will format reports in an unexpected way for parsing. 56 | "--no-pretty", 57 | "--strict", # Default is to assume we want to aim for --strict. 58 | ] 59 | else: 60 | mypy_command = [ 61 | "mypy", 62 | f"{str(path_to_code)}", 63 | # Leaving --show-error-codes and --no-pretty as the error codes are 64 | # necessary to enable parsing the report output and writing back to 65 | # the files. --no-pretty is needed as, if there's a config setting 66 | # to use pretty the report output is altered and not parsed 67 | # properly. 68 | "--show-error-codes", 69 | "--no-pretty", 70 | *mypy_flags, 71 | ] 72 | 73 | print(f"Generating mypy report using: {' '.join(mypy_command)}") 74 | 75 | # Mypy is likely to return '1' here (otherwise pointless using this script) 76 | mypy_process = subprocess.run( 77 | mypy_command, 78 | capture_output=True, 79 | ) 80 | # don't think there's any need to check stderr 81 | return mypy_process.stdout.decode() 82 | 83 | 84 | def exit_if_no_errors( 85 | *, 86 | report: Sequence[str], 87 | ) -> None: 88 | # A report with no errors will contain this substring, so if this substring 89 | # exists there's nothing to be done. 90 | success_check = "Success: no issues found in" 91 | if any(report_line.startswith(success_check) for report_line in report): 92 | msg = ( 93 | "Generated mypy report contains line starting with: " 94 | f"{success_check}, so there's probably nothing that needs to be done. " 95 | "Full report: \n" 96 | f"{report}" 97 | ) 98 | raise SystemExit(msg) 99 | 100 | 101 | # --- Add ` # type: ignore[]` to lines which throw errors. 102 | 103 | 104 | def extract_code_comment(*, line: str) -> tuple[str, str]: 105 | """ 106 | Break line into code,comment if necessary. 107 | 108 | When there are lines containing ignores for tooling such as pylint the mypy ignore should be 109 | placed before the pylint disable. Therefore it's necessary to split lines into code,comment. 110 | """ 111 | # if '#' isn't in line then there's definitely no trailing code comment. 112 | if "#" not in line: 113 | return line, "" 114 | 115 | # generate_tokens wants a "callable returning a single line of input" 116 | reader = io.StringIO(line).readline 117 | 118 | # TODO(geo7): Handle multiline statements properly. 119 | # https://github.com/geo7/mypy_clean_slate/issues/114 120 | try: 121 | comment_tokens = [t for t in tokenize.generate_tokens(reader) if t.type == tokenize.COMMENT] 122 | except tokenize.TokenError as er: 123 | warnings.warn(f"TokenError encountered: {er} for line {line}.", UserWarning, stacklevel=2) 124 | return line, "" 125 | 126 | # Line doesn't contain a comment 127 | if len(comment_tokens) == 0: 128 | return line, "" 129 | # If there's an inline comment then only expect a single one. 130 | if len(comment_tokens) > 1: 131 | msg = f"Expected there to be a single comment token, have {len(comment_tokens)}" 132 | raise ValueError( 133 | msg, 134 | ) 135 | 136 | comment_token = comment_tokens[0] 137 | python_code = line[0 : comment_token.start[1]] 138 | python_comment = line[comment_token.start[1] :] 139 | return python_code, python_comment 140 | 141 | 142 | def read_mypy_error_report( 143 | *, 144 | path_to_error_report: pathlib.Path, 145 | ) -> list[str]: 146 | error_report_lines = path_to_error_report.read_text().split("\n") 147 | # eg: "Found 1 error in 1 file (checked 5 source files)", have no use for this. 148 | summary_regex = re.compile(r"^Found [0-9]+ errors? in [0-9]+") 149 | error_report_lines_no_summary = [ 150 | line for line in error_report_lines if summary_regex.match(line) is None 151 | ] 152 | # typically a '' at the end of the report - any lines which are just '' (or ' ') are 153 | # of no use though. 154 | error_report_lines_filtered = [line for line in error_report_lines_no_summary if line.strip()] 155 | # return list sorted by file path (file path is at the start of all lines in error report). 156 | return sorted(error_report_lines_filtered) 157 | 158 | 159 | def update_files(*, file_updates: list[FileUpdate]) -> None: 160 | # update each line with `# type: ignore[]` 161 | for pth_and_line_num, grp in itertools.groupby( 162 | file_updates, 163 | key=lambda x: (x[0], x[1]), 164 | ): 165 | file_path, line_number = pth_and_line_num 166 | error_codes = ", ".join(x[2] for x in grp) 167 | file_lines = pathlib.Path(file_path).read_text(encoding="utf8").split("\n") 168 | 169 | python_code, python_comment = extract_code_comment(line=file_lines[line_number]) 170 | # In some cases it's possible for there to be multiple spaces added 171 | # before '# type: ...' whereas we'd like to ensure only two spaces are 172 | # added. 173 | python_code = python_code.rstrip() 174 | mypy_ignore = f"# type: ignore[{error_codes}]" 175 | 176 | if python_comment: 177 | line_update = f"{python_code} {mypy_ignore} {python_comment}" 178 | else: 179 | line_update = f"{python_code} {mypy_ignore}" 180 | 181 | # check to see if the line contains a trailing comment already - it it does then this line 182 | # needs to be handled separately. 183 | file_lines[line_number] = line_update.rstrip(" ") 184 | new_text = "\n".join(file_lines) 185 | with open(file_path, "w", encoding="utf8") as file: 186 | file.write(new_text) 187 | 188 | 189 | def line_contains_error(*, error_message: str) -> bool: 190 | """Ensure that the line contains an error message to extract.""" 191 | return bool(re.match(r".*error.*\[.*\]$", error_message)) 192 | 193 | 194 | def line_is_unused_ignore(*, error_message: str) -> bool: 195 | """ 196 | Return true if line relates to an unused ignore. 197 | 198 | These are treated differently to other messages, in this case the current 199 | type: ignore needs to be removed rather than adding one. 200 | """ 201 | return bool(re.match('.*unused.ignore.*|Unused "type: ignore" comment', error_message)) 202 | 203 | 204 | def extract_file_line_number_and_error_code( 205 | *, 206 | error_report_lines: list[str], 207 | ) -> list[FileUpdate]: 208 | file_updates: list[FileUpdate] = [] 209 | for error_line in error_report_lines: 210 | if (not line_contains_error(error_message=error_line)) or line_is_unused_ignore( 211 | error_message=error_line, 212 | ): 213 | continue 214 | 215 | # Call to untyped function "main" in typed context [no-untyped-call]' 216 | file_path, line_number, *_ = error_line.split(":") 217 | # mypy will report the first line as '1' rather than '0'. 218 | line_num = int(line_number) - 1 219 | if error_message := re.match(r"^.*\[(.*)\]$", error_line): 220 | file_updates.append((file_path, line_num, error_message.group(1))) 221 | else: 222 | # haven't seen anything else yet, though there might be other error types which need to 223 | # be handled. 224 | msg = f"Unexpected line format: {error_line}" 225 | raise RuntimeError(msg) 226 | 227 | # Ensure that the returned updates are unique. For example we might have 228 | # file_updates as something like [('f.py', 0, 'attr-defined'), ('f.py', 0, 229 | # 'attr-defined')] given code such as object().foo, object().bar - leading 230 | # to igore[attr-defined, attr-defined] instead of ignore[attr-defined] 231 | return sorted(set(file_updates), key=lambda x: (x[0], x[1], x[2])) 232 | 233 | 234 | def add_type_ignores( 235 | *, 236 | report_output: pathlib.Path, 237 | ) -> None: 238 | """Add `# type: ignore` to all lines which fail on given mypy command.""" 239 | error_report_lines = read_mypy_error_report(path_to_error_report=report_output) 240 | exit_if_no_errors(report=error_report_lines) 241 | # process all lines in report. 242 | file_updates = extract_file_line_number_and_error_code( 243 | error_report_lines=error_report_lines, 244 | ) 245 | update_files(file_updates=file_updates) 246 | 247 | 248 | def remove_unused_ignores(*, report_output: pathlib.Path) -> None: 249 | """Remove ignores which are no longer needed, based on report output.""" 250 | report_lines = report_output.read_text().split("\n") 251 | ignores_lines: list[FileUpdate] = sorted( 252 | [ 253 | (line.split(":", 2)[0], int(line.split(":", 2)[1]), line.split(":", 2)[2]) 254 | for line in report_lines 255 | if 'error: Unused "type: ignore" comment' in line 256 | ], 257 | key=lambda x: (x[0], x[1]), 258 | ) 259 | 260 | for file_path, grp in itertools.groupby(ignores_lines, key=lambda x: x[0]): 261 | _grp = sorted(grp) 262 | file_lines = pathlib.Path(file_path).read_text().split("\n") 263 | for _, line_n, _ in _grp: 264 | _line_n = int(line_n) - 1 # Decrease by 1 as mypy indexes from 1 not zero 265 | regexp = r"#\s*type:\s*ignore(?:\[[^\]]*\])?" 266 | file_lines[_line_n] = re.sub(regexp, "", file_lines[_line_n]).rstrip() 267 | 268 | # Write updated file out. 269 | with open(file_path, "w", encoding="utf8") as file: 270 | file.write("\n".join(file_lines)) 271 | 272 | 273 | # --- Call functions above. 274 | def create_parser() -> argparse.ArgumentParser: 275 | parser = argparse.ArgumentParser( 276 | description=textwrap.dedent( 277 | """ 278 | CLI tool for providing a clean slate for mypy usage within a project. 279 | 280 | Default expectation is to want to get a project into a state that it 281 | will pass mypy when run with `--strict`, if this isn't the case custom 282 | flags can be passed to mypy via the `--mypy_flags` argument. 283 | """, 284 | ).strip(), 285 | formatter_class=argparse.RawDescriptionHelpFormatter, 286 | # Hard-coding this as the usage is dynamic otherwise, based on where the 287 | # parser is defined. I'm using print_help() to generate the output of 288 | # --help into the README so need this to be consistent. Otherwise, 289 | # creating the parser from within mod.py will put mod.py into the usage 290 | # rather than the script entry point for the CLI. 291 | usage="mypy_clean_slate [options]", 292 | ) 293 | parser.add_argument( 294 | "-r", 295 | "--generate_mypy_error_report", 296 | help=("Generate 'mypy_error_report.txt' in the cwd."), 297 | action="store_true", 298 | ) 299 | 300 | parser.add_argument( 301 | "-p", 302 | "--path_to_code", 303 | help=("Where code is that needs report generating for it."), 304 | default=pathlib.Path("."), 305 | ) 306 | 307 | parser.add_argument( 308 | "-a", 309 | "--add_type_ignore", 310 | help=('Add "# type: ignore[]" to suppress all raised mypy errors.'), 311 | action="store_true", 312 | ) 313 | 314 | parser.add_argument( 315 | "--remove_unused", 316 | help=( 317 | 'Remove unused instances of "# type: ignore[]" ' 318 | "if raised as an error by mypy." 319 | ), 320 | action="store_true", 321 | default=False, 322 | ) 323 | 324 | parser.add_argument( 325 | "-o", 326 | "--mypy_report_output", 327 | help=f"File to save report output to (default is {DEFAULT_REPORT_FILE})", 328 | ) 329 | 330 | parser.add_argument( 331 | "--mypy_flags", 332 | type=str, 333 | default="", 334 | help=( 335 | "Custom flags to pass to mypy (provide them as a single string, " 336 | "default is to use --strict)" 337 | ), 338 | ) 339 | 340 | return parser 341 | 342 | 343 | def main() -> int: 344 | logging.basicConfig(level=logging.DEBUG) 345 | parser = create_parser() 346 | args = parser.parse_args() 347 | 348 | if args.mypy_report_output is None: 349 | report_output = pathlib.Path(DEFAULT_REPORT_FILE) 350 | else: 351 | report_output = pathlib.Path(args.mypy_report_output) 352 | 353 | if args.generate_mypy_error_report: 354 | report = generate_mypy_error_report( 355 | path_to_code=args.path_to_code, 356 | mypy_flags=shlex.split(args.mypy_flags), 357 | ) 358 | report_output.write_text(report, encoding="utf8") 359 | 360 | if args.remove_unused: 361 | remove_unused_ignores(report_output=report_output) 362 | 363 | if args.add_type_ignore: 364 | add_type_ignores(report_output=report_output) 365 | 366 | return 0 367 | 368 | 369 | if __name__ == "__main__": 370 | sys.exit(main()) 371 | -------------------------------------------------------------------------------- /uv.lock: -------------------------------------------------------------------------------- 1 | version = 1 2 | revision = 2 3 | requires-python = ">=3.9" 4 | resolution-markers = [ 5 | "python_full_version >= '3.12'", 6 | "python_full_version == '3.11.*'", 7 | "python_full_version == '3.10.*'", 8 | "python_full_version < '3.10'", 9 | ] 10 | 11 | [[package]] 12 | name = "asttokens" 13 | version = "3.0.0" 14 | source = { registry = "https://pypi.org/simple" } 15 | sdist = { url = "https://files.pythonhosted.org/packages/4a/e7/82da0a03e7ba5141f05cce0d302e6eed121ae055e0456ca228bf693984bc/asttokens-3.0.0.tar.gz", hash = "sha256:0dcd8baa8d62b0c1d118b399b2ddba3c4aff271d0d7a9e0d4c1681c79035bbc7", size = 61978, upload-time = "2024-11-30T04:30:14.439Z" } 16 | wheels = [ 17 | { url = "https://files.pythonhosted.org/packages/25/8a/c46dcc25341b5bce5472c718902eb3d38600a903b14fa6aeecef3f21a46f/asttokens-3.0.0-py3-none-any.whl", hash = "sha256:e3078351a059199dd5138cb1c706e6430c05eff2ff136af5eb4790f9d28932e2", size = 26918, upload-time = "2024-11-30T04:30:10.946Z" }, 18 | ] 19 | 20 | [[package]] 21 | name = "cfgv" 22 | version = "3.4.0" 23 | source = { registry = "https://pypi.org/simple" } 24 | sdist = { url = "https://files.pythonhosted.org/packages/11/74/539e56497d9bd1d484fd863dd69cbbfa653cd2aa27abfe35653494d85e94/cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560", size = 7114, upload-time = "2023-08-12T20:38:17.776Z" } 25 | wheels = [ 26 | { url = "https://files.pythonhosted.org/packages/c5/55/51844dd50c4fc7a33b653bfaba4c2456f06955289ca770a5dbd5fd267374/cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9", size = 7249, upload-time = "2023-08-12T20:38:16.269Z" }, 27 | ] 28 | 29 | [[package]] 30 | name = "colorama" 31 | version = "0.4.6" 32 | source = { registry = "https://pypi.org/simple" } 33 | sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } 34 | wheels = [ 35 | { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, 36 | ] 37 | 38 | [[package]] 39 | name = "coverage" 40 | version = "7.9.2" 41 | source = { registry = "https://pypi.org/simple" } 42 | sdist = { url = "https://files.pythonhosted.org/packages/04/b7/c0465ca253df10a9e8dae0692a4ae6e9726d245390aaef92360e1d6d3832/coverage-7.9.2.tar.gz", hash = "sha256:997024fa51e3290264ffd7492ec97d0690293ccd2b45a6cd7d82d945a4a80c8b", size = 813556, upload-time = "2025-07-03T10:54:15.101Z" } 43 | wheels = [ 44 | { url = "https://files.pythonhosted.org/packages/a1/0d/5c2114fd776c207bd55068ae8dc1bef63ecd1b767b3389984a8e58f2b926/coverage-7.9.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:66283a192a14a3854b2e7f3418d7db05cdf411012ab7ff5db98ff3b181e1f912", size = 212039, upload-time = "2025-07-03T10:52:38.955Z" }, 45 | { url = "https://files.pythonhosted.org/packages/cf/ad/dc51f40492dc2d5fcd31bb44577bc0cc8920757d6bc5d3e4293146524ef9/coverage-7.9.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4e01d138540ef34fcf35c1aa24d06c3de2a4cffa349e29a10056544f35cca15f", size = 212428, upload-time = "2025-07-03T10:52:41.36Z" }, 46 | { url = "https://files.pythonhosted.org/packages/a2/a3/55cb3ff1b36f00df04439c3993d8529193cdf165a2467bf1402539070f16/coverage-7.9.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f22627c1fe2745ee98d3ab87679ca73a97e75ca75eb5faee48660d060875465f", size = 241534, upload-time = "2025-07-03T10:52:42.956Z" }, 47 | { url = "https://files.pythonhosted.org/packages/eb/c9/a8410b91b6be4f6e9c2e9f0dce93749b6b40b751d7065b4410bf89cb654b/coverage-7.9.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4b1c2d8363247b46bd51f393f86c94096e64a1cf6906803fa8d5a9d03784bdbf", size = 239408, upload-time = "2025-07-03T10:52:44.199Z" }, 48 | { url = "https://files.pythonhosted.org/packages/ff/c4/6f3e56d467c612b9070ae71d5d3b114c0b899b5788e1ca3c93068ccb7018/coverage-7.9.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c10c882b114faf82dbd33e876d0cbd5e1d1ebc0d2a74ceef642c6152f3f4d547", size = 240552, upload-time = "2025-07-03T10:52:45.477Z" }, 49 | { url = "https://files.pythonhosted.org/packages/fd/20/04eda789d15af1ce79bce5cc5fd64057c3a0ac08fd0576377a3096c24663/coverage-7.9.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:de3c0378bdf7066c3988d66cd5232d161e933b87103b014ab1b0b4676098fa45", size = 240464, upload-time = "2025-07-03T10:52:46.809Z" }, 50 | { url = "https://files.pythonhosted.org/packages/a9/5a/217b32c94cc1a0b90f253514815332d08ec0812194a1ce9cca97dda1cd20/coverage-7.9.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:1e2f097eae0e5991e7623958a24ced3282676c93c013dde41399ff63e230fcf2", size = 239134, upload-time = "2025-07-03T10:52:48.149Z" }, 51 | { url = "https://files.pythonhosted.org/packages/34/73/1d019c48f413465eb5d3b6898b6279e87141c80049f7dbf73fd020138549/coverage-7.9.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:28dc1f67e83a14e7079b6cea4d314bc8b24d1aed42d3582ff89c0295f09b181e", size = 239405, upload-time = "2025-07-03T10:52:49.687Z" }, 52 | { url = "https://files.pythonhosted.org/packages/49/6c/a2beca7aa2595dad0c0d3f350382c381c92400efe5261e2631f734a0e3fe/coverage-7.9.2-cp310-cp310-win32.whl", hash = "sha256:bf7d773da6af9e10dbddacbf4e5cab13d06d0ed93561d44dae0188a42c65be7e", size = 214519, upload-time = "2025-07-03T10:52:51.036Z" }, 53 | { url = "https://files.pythonhosted.org/packages/fc/c8/91e5e4a21f9a51e2c7cdd86e587ae01a4fcff06fc3fa8cde4d6f7cf68df4/coverage-7.9.2-cp310-cp310-win_amd64.whl", hash = "sha256:0c0378ba787681ab1897f7c89b415bd56b0b2d9a47e5a3d8dc0ea55aac118d6c", size = 215400, upload-time = "2025-07-03T10:52:52.313Z" }, 54 | { url = "https://files.pythonhosted.org/packages/39/40/916786453bcfafa4c788abee4ccd6f592b5b5eca0cd61a32a4e5a7ef6e02/coverage-7.9.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a7a56a2964a9687b6aba5b5ced6971af308ef6f79a91043c05dd4ee3ebc3e9ba", size = 212152, upload-time = "2025-07-03T10:52:53.562Z" }, 55 | { url = "https://files.pythonhosted.org/packages/9f/66/cc13bae303284b546a030762957322bbbff1ee6b6cb8dc70a40f8a78512f/coverage-7.9.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:123d589f32c11d9be7fe2e66d823a236fe759b0096f5db3fb1b75b2fa414a4fa", size = 212540, upload-time = "2025-07-03T10:52:55.196Z" }, 56 | { url = "https://files.pythonhosted.org/packages/0f/3c/d56a764b2e5a3d43257c36af4a62c379df44636817bb5f89265de4bf8bd7/coverage-7.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:333b2e0ca576a7dbd66e85ab402e35c03b0b22f525eed82681c4b866e2e2653a", size = 245097, upload-time = "2025-07-03T10:52:56.509Z" }, 57 | { url = "https://files.pythonhosted.org/packages/b1/46/bd064ea8b3c94eb4ca5d90e34d15b806cba091ffb2b8e89a0d7066c45791/coverage-7.9.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:326802760da234baf9f2f85a39e4a4b5861b94f6c8d95251f699e4f73b1835dc", size = 242812, upload-time = "2025-07-03T10:52:57.842Z" }, 58 | { url = "https://files.pythonhosted.org/packages/43/02/d91992c2b29bc7afb729463bc918ebe5f361be7f1daae93375a5759d1e28/coverage-7.9.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:19e7be4cfec248df38ce40968c95d3952fbffd57b400d4b9bb580f28179556d2", size = 244617, upload-time = "2025-07-03T10:52:59.239Z" }, 59 | { url = "https://files.pythonhosted.org/packages/b7/4f/8fadff6bf56595a16d2d6e33415841b0163ac660873ed9a4e9046194f779/coverage-7.9.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0b4a4cb73b9f2b891c1788711408ef9707666501ba23684387277ededab1097c", size = 244263, upload-time = "2025-07-03T10:53:00.601Z" }, 60 | { url = "https://files.pythonhosted.org/packages/9b/d2/e0be7446a2bba11739edb9f9ba4eff30b30d8257370e237418eb44a14d11/coverage-7.9.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:2c8937fa16c8c9fbbd9f118588756e7bcdc7e16a470766a9aef912dd3f117dbd", size = 242314, upload-time = "2025-07-03T10:53:01.932Z" }, 61 | { url = "https://files.pythonhosted.org/packages/9d/7d/dcbac9345000121b8b57a3094c2dfcf1ccc52d8a14a40c1d4bc89f936f80/coverage-7.9.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:42da2280c4d30c57a9b578bafd1d4494fa6c056d4c419d9689e66d775539be74", size = 242904, upload-time = "2025-07-03T10:53:03.478Z" }, 62 | { url = "https://files.pythonhosted.org/packages/41/58/11e8db0a0c0510cf31bbbdc8caf5d74a358b696302a45948d7c768dfd1cf/coverage-7.9.2-cp311-cp311-win32.whl", hash = "sha256:14fa8d3da147f5fdf9d298cacc18791818f3f1a9f542c8958b80c228320e90c6", size = 214553, upload-time = "2025-07-03T10:53:05.174Z" }, 63 | { url = "https://files.pythonhosted.org/packages/3a/7d/751794ec8907a15e257136e48dc1021b1f671220ecccfd6c4eaf30802714/coverage-7.9.2-cp311-cp311-win_amd64.whl", hash = "sha256:549cab4892fc82004f9739963163fd3aac7a7b0df430669b75b86d293d2df2a7", size = 215441, upload-time = "2025-07-03T10:53:06.472Z" }, 64 | { url = "https://files.pythonhosted.org/packages/62/5b/34abcedf7b946c1c9e15b44f326cb5b0da852885312b30e916f674913428/coverage-7.9.2-cp311-cp311-win_arm64.whl", hash = "sha256:c2667a2b913e307f06aa4e5677f01a9746cd08e4b35e14ebcde6420a9ebb4c62", size = 213873, upload-time = "2025-07-03T10:53:07.699Z" }, 65 | { url = "https://files.pythonhosted.org/packages/53/d7/7deefc6fd4f0f1d4c58051f4004e366afc9e7ab60217ac393f247a1de70a/coverage-7.9.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ae9eb07f1cfacd9cfe8eaee6f4ff4b8a289a668c39c165cd0c8548484920ffc0", size = 212344, upload-time = "2025-07-03T10:53:09.3Z" }, 66 | { url = "https://files.pythonhosted.org/packages/95/0c/ee03c95d32be4d519e6a02e601267769ce2e9a91fc8faa1b540e3626c680/coverage-7.9.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9ce85551f9a1119f02adc46d3014b5ee3f765deac166acf20dbb851ceb79b6f3", size = 212580, upload-time = "2025-07-03T10:53:11.52Z" }, 67 | { url = "https://files.pythonhosted.org/packages/8b/9f/826fa4b544b27620086211b87a52ca67592622e1f3af9e0a62c87aea153a/coverage-7.9.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8f6389ac977c5fb322e0e38885fbbf901743f79d47f50db706e7644dcdcb6e1", size = 246383, upload-time = "2025-07-03T10:53:13.134Z" }, 68 | { url = "https://files.pythonhosted.org/packages/7f/b3/4477aafe2a546427b58b9c540665feff874f4db651f4d3cb21b308b3a6d2/coverage-7.9.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ff0d9eae8cdfcd58fe7893b88993723583a6ce4dfbfd9f29e001922544f95615", size = 243400, upload-time = "2025-07-03T10:53:14.614Z" }, 69 | { url = "https://files.pythonhosted.org/packages/f8/c2/efffa43778490c226d9d434827702f2dfbc8041d79101a795f11cbb2cf1e/coverage-7.9.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fae939811e14e53ed8a9818dad51d434a41ee09df9305663735f2e2d2d7d959b", size = 245591, upload-time = "2025-07-03T10:53:15.872Z" }, 70 | { url = "https://files.pythonhosted.org/packages/c6/e7/a59888e882c9a5f0192d8627a30ae57910d5d449c80229b55e7643c078c4/coverage-7.9.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:31991156251ec202c798501e0a42bbdf2169dcb0f137b1f5c0f4267f3fc68ef9", size = 245402, upload-time = "2025-07-03T10:53:17.124Z" }, 71 | { url = "https://files.pythonhosted.org/packages/92/a5/72fcd653ae3d214927edc100ce67440ed8a0a1e3576b8d5e6d066ed239db/coverage-7.9.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:d0d67963f9cbfc7c7f96d4ac74ed60ecbebd2ea6eeb51887af0f8dce205e545f", size = 243583, upload-time = "2025-07-03T10:53:18.781Z" }, 72 | { url = "https://files.pythonhosted.org/packages/5c/f5/84e70e4df28f4a131d580d7d510aa1ffd95037293da66fd20d446090a13b/coverage-7.9.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:49b752a2858b10580969ec6af6f090a9a440a64a301ac1528d7ca5f7ed497f4d", size = 244815, upload-time = "2025-07-03T10:53:20.168Z" }, 73 | { url = "https://files.pythonhosted.org/packages/39/e7/d73d7cbdbd09fdcf4642655ae843ad403d9cbda55d725721965f3580a314/coverage-7.9.2-cp312-cp312-win32.whl", hash = "sha256:88d7598b8ee130f32f8a43198ee02edd16d7f77692fa056cb779616bbea1b355", size = 214719, upload-time = "2025-07-03T10:53:21.521Z" }, 74 | { url = "https://files.pythonhosted.org/packages/9f/d6/7486dcc3474e2e6ad26a2af2db7e7c162ccd889c4c68fa14ea8ec189c9e9/coverage-7.9.2-cp312-cp312-win_amd64.whl", hash = "sha256:9dfb070f830739ee49d7c83e4941cc767e503e4394fdecb3b54bfdac1d7662c0", size = 215509, upload-time = "2025-07-03T10:53:22.853Z" }, 75 | { url = "https://files.pythonhosted.org/packages/b7/34/0439f1ae2593b0346164d907cdf96a529b40b7721a45fdcf8b03c95fcd90/coverage-7.9.2-cp312-cp312-win_arm64.whl", hash = "sha256:4e2c058aef613e79df00e86b6d42a641c877211384ce5bd07585ed7ba71ab31b", size = 213910, upload-time = "2025-07-03T10:53:24.472Z" }, 76 | { url = "https://files.pythonhosted.org/packages/94/9d/7a8edf7acbcaa5e5c489a646226bed9591ee1c5e6a84733c0140e9ce1ae1/coverage-7.9.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:985abe7f242e0d7bba228ab01070fde1d6c8fa12f142e43debe9ed1dde686038", size = 212367, upload-time = "2025-07-03T10:53:25.811Z" }, 77 | { url = "https://files.pythonhosted.org/packages/e8/9e/5cd6f130150712301f7e40fb5865c1bc27b97689ec57297e568d972eec3c/coverage-7.9.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:82c3939264a76d44fde7f213924021ed31f55ef28111a19649fec90c0f109e6d", size = 212632, upload-time = "2025-07-03T10:53:27.075Z" }, 78 | { url = "https://files.pythonhosted.org/packages/a8/de/6287a2c2036f9fd991c61cefa8c64e57390e30c894ad3aa52fac4c1e14a8/coverage-7.9.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ae5d563e970dbe04382f736ec214ef48103d1b875967c89d83c6e3f21706d5b3", size = 245793, upload-time = "2025-07-03T10:53:28.408Z" }, 79 | { url = "https://files.pythonhosted.org/packages/06/cc/9b5a9961d8160e3cb0b558c71f8051fe08aa2dd4b502ee937225da564ed1/coverage-7.9.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bdd612e59baed2a93c8843c9a7cb902260f181370f1d772f4842987535071d14", size = 243006, upload-time = "2025-07-03T10:53:29.754Z" }, 80 | { url = "https://files.pythonhosted.org/packages/49/d9/4616b787d9f597d6443f5588619c1c9f659e1f5fc9eebf63699eb6d34b78/coverage-7.9.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:256ea87cb2a1ed992bcdfc349d8042dcea1b80436f4ddf6e246d6bee4b5d73b6", size = 244990, upload-time = "2025-07-03T10:53:31.098Z" }, 81 | { url = "https://files.pythonhosted.org/packages/48/83/801cdc10f137b2d02b005a761661649ffa60eb173dcdaeb77f571e4dc192/coverage-7.9.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f44ae036b63c8ea432f610534a2668b0c3aee810e7037ab9d8ff6883de480f5b", size = 245157, upload-time = "2025-07-03T10:53:32.717Z" }, 82 | { url = "https://files.pythonhosted.org/packages/c8/a4/41911ed7e9d3ceb0ffb019e7635468df7499f5cc3edca5f7dfc078e9c5ec/coverage-7.9.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:82d76ad87c932935417a19b10cfe7abb15fd3f923cfe47dbdaa74ef4e503752d", size = 243128, upload-time = "2025-07-03T10:53:34.009Z" }, 83 | { url = "https://files.pythonhosted.org/packages/10/41/344543b71d31ac9cb00a664d5d0c9ef134a0fe87cb7d8430003b20fa0b7d/coverage-7.9.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:619317bb86de4193debc712b9e59d5cffd91dc1d178627ab2a77b9870deb2868", size = 244511, upload-time = "2025-07-03T10:53:35.434Z" }, 84 | { url = "https://files.pythonhosted.org/packages/d5/81/3b68c77e4812105e2a060f6946ba9e6f898ddcdc0d2bfc8b4b152a9ae522/coverage-7.9.2-cp313-cp313-win32.whl", hash = "sha256:0a07757de9feb1dfafd16ab651e0f628fd7ce551604d1bf23e47e1ddca93f08a", size = 214765, upload-time = "2025-07-03T10:53:36.787Z" }, 85 | { url = "https://files.pythonhosted.org/packages/06/a2/7fac400f6a346bb1a4004eb2a76fbff0e242cd48926a2ce37a22a6a1d917/coverage-7.9.2-cp313-cp313-win_amd64.whl", hash = "sha256:115db3d1f4d3f35f5bb021e270edd85011934ff97c8797216b62f461dd69374b", size = 215536, upload-time = "2025-07-03T10:53:38.188Z" }, 86 | { url = "https://files.pythonhosted.org/packages/08/47/2c6c215452b4f90d87017e61ea0fd9e0486bb734cb515e3de56e2c32075f/coverage-7.9.2-cp313-cp313-win_arm64.whl", hash = "sha256:48f82f889c80af8b2a7bb6e158d95a3fbec6a3453a1004d04e4f3b5945a02694", size = 213943, upload-time = "2025-07-03T10:53:39.492Z" }, 87 | { url = "https://files.pythonhosted.org/packages/a3/46/e211e942b22d6af5e0f323faa8a9bc7c447a1cf1923b64c47523f36ed488/coverage-7.9.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:55a28954545f9d2f96870b40f6c3386a59ba8ed50caf2d949676dac3ecab99f5", size = 213088, upload-time = "2025-07-03T10:53:40.874Z" }, 88 | { url = "https://files.pythonhosted.org/packages/d2/2f/762551f97e124442eccd907bf8b0de54348635b8866a73567eb4e6417acf/coverage-7.9.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:cdef6504637731a63c133bb2e6f0f0214e2748495ec15fe42d1e219d1b133f0b", size = 213298, upload-time = "2025-07-03T10:53:42.218Z" }, 89 | { url = "https://files.pythonhosted.org/packages/7a/b7/76d2d132b7baf7360ed69be0bcab968f151fa31abe6d067f0384439d9edb/coverage-7.9.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bcd5ebe66c7a97273d5d2ddd4ad0ed2e706b39630ed4b53e713d360626c3dbb3", size = 256541, upload-time = "2025-07-03T10:53:43.823Z" }, 90 | { url = "https://files.pythonhosted.org/packages/a0/17/392b219837d7ad47d8e5974ce5f8dc3deb9f99a53b3bd4d123602f960c81/coverage-7.9.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9303aed20872d7a3c9cb39c5d2b9bdbe44e3a9a1aecb52920f7e7495410dfab8", size = 252761, upload-time = "2025-07-03T10:53:45.19Z" }, 91 | { url = "https://files.pythonhosted.org/packages/d5/77/4256d3577fe1b0daa8d3836a1ebe68eaa07dd2cbaf20cf5ab1115d6949d4/coverage-7.9.2-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc18ea9e417a04d1920a9a76fe9ebd2f43ca505b81994598482f938d5c315f46", size = 254917, upload-time = "2025-07-03T10:53:46.931Z" }, 92 | { url = "https://files.pythonhosted.org/packages/53/99/fc1a008eef1805e1ddb123cf17af864743354479ea5129a8f838c433cc2c/coverage-7.9.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6406cff19880aaaadc932152242523e892faff224da29e241ce2fca329866584", size = 256147, upload-time = "2025-07-03T10:53:48.289Z" }, 93 | { url = "https://files.pythonhosted.org/packages/92/c0/f63bf667e18b7f88c2bdb3160870e277c4874ced87e21426128d70aa741f/coverage-7.9.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:2d0d4f6ecdf37fcc19c88fec3e2277d5dee740fb51ffdd69b9579b8c31e4232e", size = 254261, upload-time = "2025-07-03T10:53:49.99Z" }, 94 | { url = "https://files.pythonhosted.org/packages/8c/32/37dd1c42ce3016ff8ec9e4b607650d2e34845c0585d3518b2a93b4830c1a/coverage-7.9.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:c33624f50cf8de418ab2b4d6ca9eda96dc45b2c4231336bac91454520e8d1fac", size = 255099, upload-time = "2025-07-03T10:53:51.354Z" }, 95 | { url = "https://files.pythonhosted.org/packages/da/2e/af6b86f7c95441ce82f035b3affe1cd147f727bbd92f563be35e2d585683/coverage-7.9.2-cp313-cp313t-win32.whl", hash = "sha256:1df6b76e737c6a92210eebcb2390af59a141f9e9430210595251fbaf02d46926", size = 215440, upload-time = "2025-07-03T10:53:52.808Z" }, 96 | { url = "https://files.pythonhosted.org/packages/4d/bb/8a785d91b308867f6b2e36e41c569b367c00b70c17f54b13ac29bcd2d8c8/coverage-7.9.2-cp313-cp313t-win_amd64.whl", hash = "sha256:f5fd54310b92741ebe00d9c0d1d7b2b27463952c022da6d47c175d246a98d1bd", size = 216537, upload-time = "2025-07-03T10:53:54.273Z" }, 97 | { url = "https://files.pythonhosted.org/packages/1d/a0/a6bffb5e0f41a47279fd45a8f3155bf193f77990ae1c30f9c224b61cacb0/coverage-7.9.2-cp313-cp313t-win_arm64.whl", hash = "sha256:c48c2375287108c887ee87d13b4070a381c6537d30e8487b24ec721bf2a781cb", size = 214398, upload-time = "2025-07-03T10:53:56.715Z" }, 98 | { url = "https://files.pythonhosted.org/packages/62/ab/b4b06662ccaa00ca7bbee967b7035a33a58b41efb92d8c89a6c523a2ccd5/coverage-7.9.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ddc39510ac922a5c4c27849b739f875d3e1d9e590d1e7b64c98dadf037a16cce", size = 212037, upload-time = "2025-07-03T10:53:58.055Z" }, 99 | { url = "https://files.pythonhosted.org/packages/bb/5e/04619995657acc898d15bfad42b510344b3a74d4d5bc34f2e279d46c781c/coverage-7.9.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a535c0c7364acd55229749c2b3e5eebf141865de3a8f697076a3291985f02d30", size = 212412, upload-time = "2025-07-03T10:53:59.451Z" }, 100 | { url = "https://files.pythonhosted.org/packages/14/e7/1465710224dc6d31c534e7714cbd907210622a044adc81c810e72eea873f/coverage-7.9.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df0f9ef28e0f20c767ccdccfc5ae5f83a6f4a2fbdfbcbcc8487a8a78771168c8", size = 241164, upload-time = "2025-07-03T10:54:00.852Z" }, 101 | { url = "https://files.pythonhosted.org/packages/ab/f2/44c6fbd2794afeb9ab6c0a14d3c088ab1dae3dff3df2624609981237bbb4/coverage-7.9.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2f3da12e0ccbcb348969221d29441ac714bbddc4d74e13923d3d5a7a0bebef7a", size = 239032, upload-time = "2025-07-03T10:54:02.25Z" }, 102 | { url = "https://files.pythonhosted.org/packages/6a/d2/7a79845429c0aa2e6788bc45c26a2e3052fa91082c9ea1dea56fb531952c/coverage-7.9.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0a17eaf46f56ae0f870f14a3cbc2e4632fe3771eab7f687eda1ee59b73d09fe4", size = 240148, upload-time = "2025-07-03T10:54:03.618Z" }, 103 | { url = "https://files.pythonhosted.org/packages/9c/7d/2731d1b4c9c672d82d30d218224dfc62939cf3800bc8aba0258fefb191f5/coverage-7.9.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:669135a9d25df55d1ed56a11bf555f37c922cf08d80799d4f65d77d7d6123fcf", size = 239875, upload-time = "2025-07-03T10:54:05.022Z" }, 104 | { url = "https://files.pythonhosted.org/packages/1b/83/685958715429a9da09cf172c15750ca5c795dd7259466f2645403696557b/coverage-7.9.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:9d3a700304d01a627df9db4322dc082a0ce1e8fc74ac238e2af39ced4c083193", size = 238127, upload-time = "2025-07-03T10:54:06.366Z" }, 105 | { url = "https://files.pythonhosted.org/packages/34/ff/161a4313308b3783126790adfae1970adbe4886fda8788792e435249910a/coverage-7.9.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:71ae8b53855644a0b1579d4041304ddc9995c7b21c8a1f16753c4d8903b4dfed", size = 239064, upload-time = "2025-07-03T10:54:07.878Z" }, 106 | { url = "https://files.pythonhosted.org/packages/17/14/fe33f41b2e80811021de059621f44c01ebe4d6b08bdb82d54a514488e933/coverage-7.9.2-cp39-cp39-win32.whl", hash = "sha256:dd7a57b33b5cf27acb491e890720af45db05589a80c1ffc798462a765be6d4d7", size = 214522, upload-time = "2025-07-03T10:54:09.331Z" }, 107 | { url = "https://files.pythonhosted.org/packages/6e/30/63d850ec31b5c6f6a7b4e853016375b846258300320eda29376e2786ceeb/coverage-7.9.2-cp39-cp39-win_amd64.whl", hash = "sha256:f65bb452e579d5540c8b37ec105dd54d8b9307b07bcaa186818c104ffda22441", size = 215419, upload-time = "2025-07-03T10:54:10.681Z" }, 108 | { url = "https://files.pythonhosted.org/packages/d7/85/f8bbefac27d286386961c25515431482a425967e23d3698b75a250872924/coverage-7.9.2-pp39.pp310.pp311-none-any.whl", hash = "sha256:8a1166db2fb62473285bcb092f586e081e92656c7dfa8e9f62b4d39d7e6b5050", size = 204013, upload-time = "2025-07-03T10:54:12.084Z" }, 109 | { url = "https://files.pythonhosted.org/packages/3c/38/bbe2e63902847cf79036ecc75550d0698af31c91c7575352eb25190d0fb3/coverage-7.9.2-py3-none-any.whl", hash = "sha256:e425cd5b00f6fc0ed7cdbd766c70be8baab4b7839e4d4fe5fac48581dd968ea4", size = 204005, upload-time = "2025-07-03T10:54:13.491Z" }, 110 | ] 111 | 112 | [package.optional-dependencies] 113 | toml = [ 114 | { name = "tomli", marker = "python_full_version <= '3.11'" }, 115 | ] 116 | 117 | [[package]] 118 | name = "decorator" 119 | version = "5.2.1" 120 | source = { registry = "https://pypi.org/simple" } 121 | sdist = { url = "https://files.pythonhosted.org/packages/43/fa/6d96a0978d19e17b68d634497769987b16c8f4cd0a7a05048bec693caa6b/decorator-5.2.1.tar.gz", hash = "sha256:65f266143752f734b0a7cc83c46f4618af75b8c5911b00ccb61d0ac9b6da0360", size = 56711, upload-time = "2025-02-24T04:41:34.073Z" } 122 | wheels = [ 123 | { url = "https://files.pythonhosted.org/packages/4e/8c/f3147f5c4b73e7550fe5f9352eaa956ae838d5c51eb58e7a25b9f3e2643b/decorator-5.2.1-py3-none-any.whl", hash = "sha256:d316bb415a2d9e2d2b3abcc4084c6502fc09240e292cd76a76afc106a1c8e04a", size = 9190, upload-time = "2025-02-24T04:41:32.565Z" }, 124 | ] 125 | 126 | [[package]] 127 | name = "distlib" 128 | version = "0.3.9" 129 | source = { registry = "https://pypi.org/simple" } 130 | sdist = { url = "https://files.pythonhosted.org/packages/0d/dd/1bec4c5ddb504ca60fc29472f3d27e8d4da1257a854e1d96742f15c1d02d/distlib-0.3.9.tar.gz", hash = "sha256:a60f20dea646b8a33f3e7772f74dc0b2d0772d2837ee1342a00645c81edf9403", size = 613923, upload-time = "2024-10-09T18:35:47.551Z" } 131 | wheels = [ 132 | { url = "https://files.pythonhosted.org/packages/91/a1/cf2472db20f7ce4a6be1253a81cfdf85ad9c7885ffbed7047fb72c24cf87/distlib-0.3.9-py2.py3-none-any.whl", hash = "sha256:47f8c22fd27c27e25a65601af709b38e4f0a45ea4fc2e710f65755fa8caaaf87", size = 468973, upload-time = "2024-10-09T18:35:44.272Z" }, 133 | ] 134 | 135 | [[package]] 136 | name = "exceptiongroup" 137 | version = "1.3.0" 138 | source = { registry = "https://pypi.org/simple" } 139 | dependencies = [ 140 | { name = "typing-extensions", marker = "python_full_version < '3.11'" }, 141 | ] 142 | sdist = { url = "https://files.pythonhosted.org/packages/0b/9f/a65090624ecf468cdca03533906e7c69ed7588582240cfe7cc9e770b50eb/exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88", size = 29749, upload-time = "2025-05-10T17:42:51.123Z" } 143 | wheels = [ 144 | { url = "https://files.pythonhosted.org/packages/36/f4/c6e662dade71f56cd2f3735141b265c3c79293c109549c1e6933b0651ffc/exceptiongroup-1.3.0-py3-none-any.whl", hash = "sha256:4d111e6e0c13d0644cad6ddaa7ed0261a0b36971f6d23e7ec9b4b9097da78a10", size = 16674, upload-time = "2025-05-10T17:42:49.33Z" }, 145 | ] 146 | 147 | [[package]] 148 | name = "executing" 149 | version = "2.2.0" 150 | source = { registry = "https://pypi.org/simple" } 151 | sdist = { url = "https://files.pythonhosted.org/packages/91/50/a9d80c47ff289c611ff12e63f7c5d13942c65d68125160cefd768c73e6e4/executing-2.2.0.tar.gz", hash = "sha256:5d108c028108fe2551d1a7b2e8b713341e2cb4fc0aa7dcf966fa4327a5226755", size = 978693, upload-time = "2025-01-22T15:41:29.403Z" } 152 | wheels = [ 153 | { url = "https://files.pythonhosted.org/packages/7b/8f/c4d9bafc34ad7ad5d8dc16dd1347ee0e507a52c3adb6bfa8887e1c6a26ba/executing-2.2.0-py2.py3-none-any.whl", hash = "sha256:11387150cad388d62750327a53d3339fad4888b39a6fe233c3afbb54ecffd3aa", size = 26702, upload-time = "2025-01-22T15:41:25.929Z" }, 154 | ] 155 | 156 | [[package]] 157 | name = "fancycompleter" 158 | version = "0.11.1" 159 | source = { registry = "https://pypi.org/simple" } 160 | dependencies = [ 161 | { name = "pyreadline3", marker = "python_full_version < '3.13' and sys_platform == 'win32'" }, 162 | { name = "pyrepl", marker = "python_full_version < '3.13'" }, 163 | ] 164 | sdist = { url = "https://files.pythonhosted.org/packages/4e/4c/d11187dee93eff89d082afda79b63c79320ae1347e49485a38f05ad359d0/fancycompleter-0.11.1.tar.gz", hash = "sha256:5b4ad65d76b32b1259251516d0f1cb2d82832b1ff8506697a707284780757f69", size = 341776, upload-time = "2025-05-26T12:59:11.045Z" } 165 | wheels = [ 166 | { url = "https://files.pythonhosted.org/packages/30/c3/6f0e3896f193528bbd2b4d2122d4be8108a37efab0b8475855556a8c4afa/fancycompleter-0.11.1-py3-none-any.whl", hash = "sha256:44243d7fab37087208ca5acacf8f74c0aa4d733d04d593857873af7513cdf8a6", size = 11207, upload-time = "2025-05-26T12:59:09.857Z" }, 167 | ] 168 | 169 | [[package]] 170 | name = "filelock" 171 | version = "3.18.0" 172 | source = { registry = "https://pypi.org/simple" } 173 | sdist = { url = "https://files.pythonhosted.org/packages/0a/10/c23352565a6544bdc5353e0b15fc1c563352101f30e24bf500207a54df9a/filelock-3.18.0.tar.gz", hash = "sha256:adbc88eabb99d2fec8c9c1b229b171f18afa655400173ddc653d5d01501fb9f2", size = 18075, upload-time = "2025-03-14T07:11:40.47Z" } 174 | wheels = [ 175 | { url = "https://files.pythonhosted.org/packages/4d/36/2a115987e2d8c300a974597416d9de88f2444426de9571f4b59b2cca3acc/filelock-3.18.0-py3-none-any.whl", hash = "sha256:c401f4f8377c4464e6db25fff06205fd89bdd83b65eb0488ed1b160f780e21de", size = 16215, upload-time = "2025-03-14T07:11:39.145Z" }, 176 | ] 177 | 178 | [[package]] 179 | name = "identify" 180 | version = "2.6.12" 181 | source = { registry = "https://pypi.org/simple" } 182 | sdist = { url = "https://files.pythonhosted.org/packages/a2/88/d193a27416618628a5eea64e3223acd800b40749a96ffb322a9b55a49ed1/identify-2.6.12.tar.gz", hash = "sha256:d8de45749f1efb108badef65ee8386f0f7bb19a7f26185f74de6367bffbaf0e6", size = 99254, upload-time = "2025-05-23T20:37:53.3Z" } 183 | wheels = [ 184 | { url = "https://files.pythonhosted.org/packages/7a/cd/18f8da995b658420625f7ef13f037be53ae04ec5ad33f9b718240dcfd48c/identify-2.6.12-py2.py3-none-any.whl", hash = "sha256:ad9672d5a72e0d2ff7c5c8809b62dfa60458626352fb0eb7b55e69bdc45334a2", size = 99145, upload-time = "2025-05-23T20:37:51.495Z" }, 185 | ] 186 | 187 | [[package]] 188 | name = "iniconfig" 189 | version = "2.1.0" 190 | source = { registry = "https://pypi.org/simple" } 191 | sdist = { url = "https://files.pythonhosted.org/packages/f2/97/ebf4da567aa6827c909642694d71c9fcf53e5b504f2d96afea02718862f3/iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7", size = 4793, upload-time = "2025-03-19T20:09:59.721Z" } 192 | wheels = [ 193 | { url = "https://files.pythonhosted.org/packages/2c/e1/e6716421ea10d38022b952c159d5161ca1193197fb744506875fbb87ea7b/iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760", size = 6050, upload-time = "2025-03-19T20:10:01.071Z" }, 194 | ] 195 | 196 | [[package]] 197 | name = "ipdb" 198 | version = "0.13.13" 199 | source = { registry = "https://pypi.org/simple" } 200 | dependencies = [ 201 | { name = "decorator" }, 202 | { name = "ipython", version = "8.18.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, 203 | { name = "ipython", version = "8.37.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, 204 | { name = "ipython", version = "9.4.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, 205 | { name = "tomli", marker = "python_full_version < '3.11'" }, 206 | ] 207 | sdist = { url = "https://files.pythonhosted.org/packages/3d/1b/7e07e7b752017f7693a0f4d41c13e5ca29ce8cbcfdcc1fd6c4ad8c0a27a0/ipdb-0.13.13.tar.gz", hash = "sha256:e3ac6018ef05126d442af680aad863006ec19d02290561ac88b8b1c0b0cfc726", size = 17042, upload-time = "2023-03-09T15:40:57.487Z" } 208 | wheels = [ 209 | { url = "https://files.pythonhosted.org/packages/0c/4c/b075da0092003d9a55cf2ecc1cae9384a1ca4f650d51b00fc59875fe76f6/ipdb-0.13.13-py3-none-any.whl", hash = "sha256:45529994741c4ab6d2388bfa5d7b725c2cf7fe9deffabdb8a6113aa5ed449ed4", size = 12130, upload-time = "2023-03-09T15:40:55.021Z" }, 210 | ] 211 | 212 | [[package]] 213 | name = "ipython" 214 | version = "8.18.1" 215 | source = { registry = "https://pypi.org/simple" } 216 | resolution-markers = [ 217 | "python_full_version < '3.10'", 218 | ] 219 | dependencies = [ 220 | { name = "colorama", marker = "python_full_version < '3.10' and sys_platform == 'win32'" }, 221 | { name = "decorator", marker = "python_full_version < '3.10'" }, 222 | { name = "exceptiongroup", marker = "python_full_version < '3.10'" }, 223 | { name = "jedi", marker = "python_full_version < '3.10'" }, 224 | { name = "matplotlib-inline", marker = "python_full_version < '3.10'" }, 225 | { name = "pexpect", marker = "python_full_version < '3.10' and sys_platform != 'win32'" }, 226 | { name = "prompt-toolkit", marker = "python_full_version < '3.10'" }, 227 | { name = "pygments", marker = "python_full_version < '3.10'" }, 228 | { name = "stack-data", marker = "python_full_version < '3.10'" }, 229 | { name = "traitlets", marker = "python_full_version < '3.10'" }, 230 | { name = "typing-extensions", marker = "python_full_version < '3.10'" }, 231 | ] 232 | sdist = { url = "https://files.pythonhosted.org/packages/b1/b9/3ba6c45a6df813c09a48bac313c22ff83efa26cbb55011218d925a46e2ad/ipython-8.18.1.tar.gz", hash = "sha256:ca6f079bb33457c66e233e4580ebfc4128855b4cf6370dddd73842a9563e8a27", size = 5486330, upload-time = "2023-11-27T09:58:34.596Z" } 233 | wheels = [ 234 | { url = "https://files.pythonhosted.org/packages/47/6b/d9fdcdef2eb6a23f391251fde8781c38d42acd82abe84d054cb74f7863b0/ipython-8.18.1-py3-none-any.whl", hash = "sha256:e8267419d72d81955ec1177f8a29aaa90ac80ad647499201119e2f05e99aa397", size = 808161, upload-time = "2023-11-27T09:58:30.538Z" }, 235 | ] 236 | 237 | [[package]] 238 | name = "ipython" 239 | version = "8.37.0" 240 | source = { registry = "https://pypi.org/simple" } 241 | resolution-markers = [ 242 | "python_full_version == '3.10.*'", 243 | ] 244 | dependencies = [ 245 | { name = "colorama", marker = "python_full_version == '3.10.*' and sys_platform == 'win32'" }, 246 | { name = "decorator", marker = "python_full_version == '3.10.*'" }, 247 | { name = "exceptiongroup", marker = "python_full_version == '3.10.*'" }, 248 | { name = "jedi", marker = "python_full_version == '3.10.*'" }, 249 | { name = "matplotlib-inline", marker = "python_full_version == '3.10.*'" }, 250 | { name = "pexpect", marker = "python_full_version == '3.10.*' and sys_platform != 'emscripten' and sys_platform != 'win32'" }, 251 | { name = "prompt-toolkit", marker = "python_full_version == '3.10.*'" }, 252 | { name = "pygments", marker = "python_full_version == '3.10.*'" }, 253 | { name = "stack-data", marker = "python_full_version == '3.10.*'" }, 254 | { name = "traitlets", marker = "python_full_version == '3.10.*'" }, 255 | { name = "typing-extensions", marker = "python_full_version == '3.10.*'" }, 256 | ] 257 | sdist = { url = "https://files.pythonhosted.org/packages/85/31/10ac88f3357fc276dc8a64e8880c82e80e7459326ae1d0a211b40abf6665/ipython-8.37.0.tar.gz", hash = "sha256:ca815841e1a41a1e6b73a0b08f3038af9b2252564d01fc405356d34033012216", size = 5606088, upload-time = "2025-05-31T16:39:09.613Z" } 258 | wheels = [ 259 | { url = "https://files.pythonhosted.org/packages/91/d0/274fbf7b0b12643cbbc001ce13e6a5b1607ac4929d1b11c72460152c9fc3/ipython-8.37.0-py3-none-any.whl", hash = "sha256:ed87326596b878932dbcb171e3e698845434d8c61b8d8cd474bf663041a9dcf2", size = 831864, upload-time = "2025-05-31T16:39:06.38Z" }, 260 | ] 261 | 262 | [[package]] 263 | name = "ipython" 264 | version = "9.4.0" 265 | source = { registry = "https://pypi.org/simple" } 266 | resolution-markers = [ 267 | "python_full_version >= '3.12'", 268 | "python_full_version == '3.11.*'", 269 | ] 270 | dependencies = [ 271 | { name = "colorama", marker = "python_full_version >= '3.11' and sys_platform == 'win32'" }, 272 | { name = "decorator", marker = "python_full_version >= '3.11'" }, 273 | { name = "ipython-pygments-lexers", marker = "python_full_version >= '3.11'" }, 274 | { name = "jedi", marker = "python_full_version >= '3.11'" }, 275 | { name = "matplotlib-inline", marker = "python_full_version >= '3.11'" }, 276 | { name = "pexpect", marker = "python_full_version >= '3.11' and sys_platform != 'emscripten' and sys_platform != 'win32'" }, 277 | { name = "prompt-toolkit", marker = "python_full_version >= '3.11'" }, 278 | { name = "pygments", marker = "python_full_version >= '3.11'" }, 279 | { name = "stack-data", marker = "python_full_version >= '3.11'" }, 280 | { name = "traitlets", marker = "python_full_version >= '3.11'" }, 281 | { name = "typing-extensions", marker = "python_full_version == '3.11.*'" }, 282 | ] 283 | sdist = { url = "https://files.pythonhosted.org/packages/54/80/406f9e3bde1c1fd9bf5a0be9d090f8ae623e401b7670d8f6fdf2ab679891/ipython-9.4.0.tar.gz", hash = "sha256:c033c6d4e7914c3d9768aabe76bbe87ba1dc66a92a05db6bfa1125d81f2ee270", size = 4385338, upload-time = "2025-07-01T11:11:30.606Z" } 284 | wheels = [ 285 | { url = "https://files.pythonhosted.org/packages/63/f8/0031ee2b906a15a33d6bfc12dd09c3dfa966b3cb5b284ecfb7549e6ac3c4/ipython-9.4.0-py3-none-any.whl", hash = "sha256:25850f025a446d9b359e8d296ba175a36aedd32e83ca9b5060430fe16801f066", size = 611021, upload-time = "2025-07-01T11:11:27.85Z" }, 286 | ] 287 | 288 | [[package]] 289 | name = "ipython-pygments-lexers" 290 | version = "1.1.1" 291 | source = { registry = "https://pypi.org/simple" } 292 | dependencies = [ 293 | { name = "pygments", marker = "python_full_version >= '3.11'" }, 294 | ] 295 | sdist = { url = "https://files.pythonhosted.org/packages/ef/4c/5dd1d8af08107f88c7f741ead7a40854b8ac24ddf9ae850afbcf698aa552/ipython_pygments_lexers-1.1.1.tar.gz", hash = "sha256:09c0138009e56b6854f9535736f4171d855c8c08a563a0dcd8022f78355c7e81", size = 8393, upload-time = "2025-01-17T11:24:34.505Z" } 296 | wheels = [ 297 | { url = "https://files.pythonhosted.org/packages/d9/33/1f075bf72b0b747cb3288d011319aaf64083cf2efef8354174e3ed4540e2/ipython_pygments_lexers-1.1.1-py3-none-any.whl", hash = "sha256:a9462224a505ade19a605f71f8fa63c2048833ce50abc86768a0d81d876dc81c", size = 8074, upload-time = "2025-01-17T11:24:33.271Z" }, 298 | ] 299 | 300 | [[package]] 301 | name = "jedi" 302 | version = "0.19.2" 303 | source = { registry = "https://pypi.org/simple" } 304 | dependencies = [ 305 | { name = "parso" }, 306 | ] 307 | sdist = { url = "https://files.pythonhosted.org/packages/72/3a/79a912fbd4d8dd6fbb02bf69afd3bb72cf0c729bb3063c6f4498603db17a/jedi-0.19.2.tar.gz", hash = "sha256:4770dc3de41bde3966b02eb84fbcf557fb33cce26ad23da12c742fb50ecb11f0", size = 1231287, upload-time = "2024-11-11T01:41:42.873Z" } 308 | wheels = [ 309 | { url = "https://files.pythonhosted.org/packages/c0/5a/9cac0c82afec3d09ccd97c8b6502d48f165f9124db81b4bcb90b4af974ee/jedi-0.19.2-py2.py3-none-any.whl", hash = "sha256:a8ef22bde8490f57fe5c7681a3c83cb58874daf72b4784de3cce5b6ef6edb5b9", size = 1572278, upload-time = "2024-11-11T01:41:40.175Z" }, 310 | ] 311 | 312 | [[package]] 313 | name = "matplotlib-inline" 314 | version = "0.1.7" 315 | source = { registry = "https://pypi.org/simple" } 316 | dependencies = [ 317 | { name = "traitlets" }, 318 | ] 319 | sdist = { url = "https://files.pythonhosted.org/packages/99/5b/a36a337438a14116b16480db471ad061c36c3694df7c2084a0da7ba538b7/matplotlib_inline-0.1.7.tar.gz", hash = "sha256:8423b23ec666be3d16e16b60bdd8ac4e86e840ebd1dd11a30b9f117f2fa0ab90", size = 8159, upload-time = "2024-04-15T13:44:44.803Z" } 320 | wheels = [ 321 | { url = "https://files.pythonhosted.org/packages/8f/8e/9ad090d3553c280a8060fbf6e24dc1c0c29704ee7d1c372f0c174aa59285/matplotlib_inline-0.1.7-py3-none-any.whl", hash = "sha256:df192d39a4ff8f21b1895d72e6a13f5fcc5099f00fa84384e0ea28c2cc0653ca", size = 9899, upload-time = "2024-04-15T13:44:43.265Z" }, 322 | ] 323 | 324 | [[package]] 325 | name = "mypy" 326 | version = "1.16.1" 327 | source = { registry = "https://pypi.org/simple" } 328 | dependencies = [ 329 | { name = "mypy-extensions" }, 330 | { name = "pathspec" }, 331 | { name = "tomli", marker = "python_full_version < '3.11'" }, 332 | { name = "typing-extensions" }, 333 | ] 334 | sdist = { url = "https://files.pythonhosted.org/packages/81/69/92c7fa98112e4d9eb075a239caa4ef4649ad7d441545ccffbd5e34607cbb/mypy-1.16.1.tar.gz", hash = "sha256:6bd00a0a2094841c5e47e7374bb42b83d64c527a502e3334e1173a0c24437bab", size = 3324747, upload-time = "2025-06-16T16:51:35.145Z" } 335 | wheels = [ 336 | { url = "https://files.pythonhosted.org/packages/8e/12/2bf23a80fcef5edb75de9a1e295d778e0f46ea89eb8b115818b663eff42b/mypy-1.16.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b4f0fed1022a63c6fec38f28b7fc77fca47fd490445c69d0a66266c59dd0b88a", size = 10958644, upload-time = "2025-06-16T16:51:11.649Z" }, 337 | { url = "https://files.pythonhosted.org/packages/08/50/bfe47b3b278eacf348291742fd5e6613bbc4b3434b72ce9361896417cfe5/mypy-1.16.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:86042bbf9f5a05ea000d3203cf87aa9d0ccf9a01f73f71c58979eb9249f46d72", size = 10087033, upload-time = "2025-06-16T16:35:30.089Z" }, 338 | { url = "https://files.pythonhosted.org/packages/21/de/40307c12fe25675a0776aaa2cdd2879cf30d99eec91b898de00228dc3ab5/mypy-1.16.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ea7469ee5902c95542bea7ee545f7006508c65c8c54b06dc2c92676ce526f3ea", size = 11875645, upload-time = "2025-06-16T16:35:48.49Z" }, 339 | { url = "https://files.pythonhosted.org/packages/a6/d8/85bdb59e4a98b7a31495bd8f1a4445d8ffc86cde4ab1f8c11d247c11aedc/mypy-1.16.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:352025753ef6a83cb9e7f2427319bb7875d1fdda8439d1e23de12ab164179574", size = 12616986, upload-time = "2025-06-16T16:48:39.526Z" }, 340 | { url = "https://files.pythonhosted.org/packages/0e/d0/bb25731158fa8f8ee9e068d3e94fcceb4971fedf1424248496292512afe9/mypy-1.16.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ff9fa5b16e4c1364eb89a4d16bcda9987f05d39604e1e6c35378a2987c1aac2d", size = 12878632, upload-time = "2025-06-16T16:36:08.195Z" }, 341 | { url = "https://files.pythonhosted.org/packages/2d/11/822a9beb7a2b825c0cb06132ca0a5183f8327a5e23ef89717c9474ba0bc6/mypy-1.16.1-cp310-cp310-win_amd64.whl", hash = "sha256:1256688e284632382f8f3b9e2123df7d279f603c561f099758e66dd6ed4e8bd6", size = 9484391, upload-time = "2025-06-16T16:37:56.151Z" }, 342 | { url = "https://files.pythonhosted.org/packages/9a/61/ec1245aa1c325cb7a6c0f8570a2eee3bfc40fa90d19b1267f8e50b5c8645/mypy-1.16.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:472e4e4c100062488ec643f6162dd0d5208e33e2f34544e1fc931372e806c0cc", size = 10890557, upload-time = "2025-06-16T16:37:21.421Z" }, 343 | { url = "https://files.pythonhosted.org/packages/6b/bb/6eccc0ba0aa0c7a87df24e73f0ad34170514abd8162eb0c75fd7128171fb/mypy-1.16.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ea16e2a7d2714277e349e24d19a782a663a34ed60864006e8585db08f8ad1782", size = 10012921, upload-time = "2025-06-16T16:51:28.659Z" }, 344 | { url = "https://files.pythonhosted.org/packages/5f/80/b337a12e2006715f99f529e732c5f6a8c143bb58c92bb142d5ab380963a5/mypy-1.16.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:08e850ea22adc4d8a4014651575567b0318ede51e8e9fe7a68f25391af699507", size = 11802887, upload-time = "2025-06-16T16:50:53.627Z" }, 345 | { url = "https://files.pythonhosted.org/packages/d9/59/f7af072d09793d581a745a25737c7c0a945760036b16aeb620f658a017af/mypy-1.16.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:22d76a63a42619bfb90122889b903519149879ddbf2ba4251834727944c8baca", size = 12531658, upload-time = "2025-06-16T16:33:55.002Z" }, 346 | { url = "https://files.pythonhosted.org/packages/82/c4/607672f2d6c0254b94a646cfc45ad589dd71b04aa1f3d642b840f7cce06c/mypy-1.16.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:2c7ce0662b6b9dc8f4ed86eb7a5d505ee3298c04b40ec13b30e572c0e5ae17c4", size = 12732486, upload-time = "2025-06-16T16:37:03.301Z" }, 347 | { url = "https://files.pythonhosted.org/packages/b6/5e/136555ec1d80df877a707cebf9081bd3a9f397dedc1ab9750518d87489ec/mypy-1.16.1-cp311-cp311-win_amd64.whl", hash = "sha256:211287e98e05352a2e1d4e8759c5490925a7c784ddc84207f4714822f8cf99b6", size = 9479482, upload-time = "2025-06-16T16:47:37.48Z" }, 348 | { url = "https://files.pythonhosted.org/packages/b4/d6/39482e5fcc724c15bf6280ff5806548c7185e0c090712a3736ed4d07e8b7/mypy-1.16.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:af4792433f09575d9eeca5c63d7d90ca4aeceda9d8355e136f80f8967639183d", size = 11066493, upload-time = "2025-06-16T16:47:01.683Z" }, 349 | { url = "https://files.pythonhosted.org/packages/e6/e5/26c347890efc6b757f4d5bb83f4a0cf5958b8cf49c938ac99b8b72b420a6/mypy-1.16.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:66df38405fd8466ce3517eda1f6640611a0b8e70895e2a9462d1d4323c5eb4b9", size = 10081687, upload-time = "2025-06-16T16:48:19.367Z" }, 350 | { url = "https://files.pythonhosted.org/packages/44/c7/b5cb264c97b86914487d6a24bd8688c0172e37ec0f43e93b9691cae9468b/mypy-1.16.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:44e7acddb3c48bd2713994d098729494117803616e116032af192871aed80b79", size = 11839723, upload-time = "2025-06-16T16:49:20.912Z" }, 351 | { url = "https://files.pythonhosted.org/packages/15/f8/491997a9b8a554204f834ed4816bda813aefda31cf873bb099deee3c9a99/mypy-1.16.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0ab5eca37b50188163fa7c1b73c685ac66c4e9bdee4a85c9adac0e91d8895e15", size = 12722980, upload-time = "2025-06-16T16:37:40.929Z" }, 352 | { url = "https://files.pythonhosted.org/packages/df/f0/2bd41e174b5fd93bc9de9a28e4fb673113633b8a7f3a607fa4a73595e468/mypy-1.16.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:dedb6229b2c9086247e21a83c309754b9058b438704ad2f6807f0d8227f6ebdd", size = 12903328, upload-time = "2025-06-16T16:34:35.099Z" }, 353 | { url = "https://files.pythonhosted.org/packages/61/81/5572108a7bec2c46b8aff7e9b524f371fe6ab5efb534d38d6b37b5490da8/mypy-1.16.1-cp312-cp312-win_amd64.whl", hash = "sha256:1f0435cf920e287ff68af3d10a118a73f212deb2ce087619eb4e648116d1fe9b", size = 9562321, upload-time = "2025-06-16T16:48:58.823Z" }, 354 | { url = "https://files.pythonhosted.org/packages/28/e3/96964af4a75a949e67df4b95318fe2b7427ac8189bbc3ef28f92a1c5bc56/mypy-1.16.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ddc91eb318c8751c69ddb200a5937f1232ee8efb4e64e9f4bc475a33719de438", size = 11063480, upload-time = "2025-06-16T16:47:56.205Z" }, 355 | { url = "https://files.pythonhosted.org/packages/f5/4d/cd1a42b8e5be278fab7010fb289d9307a63e07153f0ae1510a3d7b703193/mypy-1.16.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:87ff2c13d58bdc4bbe7dc0dedfe622c0f04e2cb2a492269f3b418df2de05c536", size = 10090538, upload-time = "2025-06-16T16:46:43.92Z" }, 356 | { url = "https://files.pythonhosted.org/packages/c9/4f/c3c6b4b66374b5f68bab07c8cabd63a049ff69796b844bc759a0ca99bb2a/mypy-1.16.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0a7cfb0fe29fe5a9841b7c8ee6dffb52382c45acdf68f032145b75620acfbd6f", size = 11836839, upload-time = "2025-06-16T16:36:28.039Z" }, 357 | { url = "https://files.pythonhosted.org/packages/b4/7e/81ca3b074021ad9775e5cb97ebe0089c0f13684b066a750b7dc208438403/mypy-1.16.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:051e1677689c9d9578b9c7f4d206d763f9bbd95723cd1416fad50db49d52f359", size = 12715634, upload-time = "2025-06-16T16:50:34.441Z" }, 358 | { url = "https://files.pythonhosted.org/packages/e9/95/bdd40c8be346fa4c70edb4081d727a54d0a05382d84966869738cfa8a497/mypy-1.16.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d5d2309511cc56c021b4b4e462907c2b12f669b2dbeb68300110ec27723971be", size = 12895584, upload-time = "2025-06-16T16:34:54.857Z" }, 359 | { url = "https://files.pythonhosted.org/packages/5a/fd/d486a0827a1c597b3b48b1bdef47228a6e9ee8102ab8c28f944cb83b65dc/mypy-1.16.1-cp313-cp313-win_amd64.whl", hash = "sha256:4f58ac32771341e38a853c5d0ec0dfe27e18e27da9cdb8bbc882d2249c71a3ee", size = 9573886, upload-time = "2025-06-16T16:36:43.589Z" }, 360 | { url = "https://files.pythonhosted.org/packages/49/5e/ed1e6a7344005df11dfd58b0fdd59ce939a0ba9f7ed37754bf20670b74db/mypy-1.16.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7fc688329af6a287567f45cc1cefb9db662defeb14625213a5b7da6e692e2069", size = 10959511, upload-time = "2025-06-16T16:47:21.945Z" }, 361 | { url = "https://files.pythonhosted.org/packages/30/88/a7cbc2541e91fe04f43d9e4577264b260fecedb9bccb64ffb1a34b7e6c22/mypy-1.16.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5e198ab3f55924c03ead626ff424cad1732d0d391478dfbf7bb97b34602395da", size = 10075555, upload-time = "2025-06-16T16:50:14.084Z" }, 362 | { url = "https://files.pythonhosted.org/packages/93/f7/c62b1e31a32fbd1546cca5e0a2e5f181be5761265ad1f2e94f2a306fa906/mypy-1.16.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:09aa4f91ada245f0a45dbc47e548fd94e0dd5a8433e0114917dc3b526912a30c", size = 11874169, upload-time = "2025-06-16T16:49:42.276Z" }, 363 | { url = "https://files.pythonhosted.org/packages/c8/15/db580a28034657fb6cb87af2f8996435a5b19d429ea4dcd6e1c73d418e60/mypy-1.16.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:13c7cd5b1cb2909aa318a90fd1b7e31f17c50b242953e7dd58345b2a814f6383", size = 12610060, upload-time = "2025-06-16T16:34:15.215Z" }, 364 | { url = "https://files.pythonhosted.org/packages/ec/78/c17f48f6843048fa92d1489d3095e99324f2a8c420f831a04ccc454e2e51/mypy-1.16.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:58e07fb958bc5d752a280da0e890c538f1515b79a65757bbdc54252ba82e0b40", size = 12875199, upload-time = "2025-06-16T16:35:14.448Z" }, 365 | { url = "https://files.pythonhosted.org/packages/bc/d6/ed42167d0a42680381653fd251d877382351e1bd2c6dd8a818764be3beb1/mypy-1.16.1-cp39-cp39-win_amd64.whl", hash = "sha256:f895078594d918f93337a505f8add9bd654d1a24962b4c6ed9390e12531eb31b", size = 9487033, upload-time = "2025-06-16T16:49:57.907Z" }, 366 | { url = "https://files.pythonhosted.org/packages/cf/d3/53e684e78e07c1a2bf7105715e5edd09ce951fc3f47cf9ed095ec1b7a037/mypy-1.16.1-py3-none-any.whl", hash = "sha256:5fc2ac4027d0ef28d6ba69a0343737a23c4d1b83672bf38d1fe237bdc0643b37", size = 2265923, upload-time = "2025-06-16T16:48:02.366Z" }, 367 | ] 368 | 369 | [[package]] 370 | name = "mypy-clean-slate" 371 | version = "0.4.0" 372 | source = { editable = "." } 373 | dependencies = [ 374 | { name = "mypy" }, 375 | ] 376 | 377 | [package.optional-dependencies] 378 | dev = [ 379 | { name = "ipdb" }, 380 | { name = "ipython", version = "8.18.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, 381 | { name = "ipython", version = "8.37.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, 382 | { name = "ipython", version = "9.4.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, 383 | { name = "pdbpp" }, 384 | { name = "pre-commit" }, 385 | { name = "pytest" }, 386 | { name = "pytest-cov" }, 387 | { name = "ruff" }, 388 | ] 389 | 390 | [package.metadata] 391 | requires-dist = [ 392 | { name = "ipdb", marker = "extra == 'dev'", specifier = ">=0.13.9,<0.14.0" }, 393 | { name = "ipython", marker = "extra == 'dev'", specifier = ">=8.18.1" }, 394 | { name = "mypy", specifier = ">=0.910,<2.0" }, 395 | { name = "pdbpp", marker = "extra == 'dev'", specifier = ">=0.10.3,<0.12.0" }, 396 | { name = "pre-commit", marker = "extra == 'dev'", specifier = ">=4.0.0" }, 397 | { name = "pytest", marker = "extra == 'dev'", specifier = ">=8.0.0,<9.0.0" }, 398 | { name = "pytest-cov", marker = "extra == 'dev'", specifier = ">=5.0.0" }, 399 | { name = "ruff", marker = "extra == 'dev'", specifier = ">=0.0.265" }, 400 | ] 401 | provides-extras = ["dev"] 402 | 403 | [[package]] 404 | name = "mypy-extensions" 405 | version = "1.1.0" 406 | source = { registry = "https://pypi.org/simple" } 407 | sdist = { url = "https://files.pythonhosted.org/packages/a2/6e/371856a3fb9d31ca8dac321cda606860fa4548858c0cc45d9d1d4ca2628b/mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558", size = 6343, upload-time = "2025-04-22T14:54:24.164Z" } 408 | wheels = [ 409 | { url = "https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", size = 4963, upload-time = "2025-04-22T14:54:22.983Z" }, 410 | ] 411 | 412 | [[package]] 413 | name = "nodeenv" 414 | version = "1.9.1" 415 | source = { registry = "https://pypi.org/simple" } 416 | sdist = { url = "https://files.pythonhosted.org/packages/43/16/fc88b08840de0e0a72a2f9d8c6bae36be573e475a6326ae854bcc549fc45/nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f", size = 47437, upload-time = "2024-06-04T18:44:11.171Z" } 417 | wheels = [ 418 | { url = "https://files.pythonhosted.org/packages/d2/1d/1b658dbd2b9fa9c4c9f32accbfc0205d532c8c6194dc0f2a4c0428e7128a/nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9", size = 22314, upload-time = "2024-06-04T18:44:08.352Z" }, 419 | ] 420 | 421 | [[package]] 422 | name = "packaging" 423 | version = "25.0" 424 | source = { registry = "https://pypi.org/simple" } 425 | sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727, upload-time = "2025-04-19T11:48:59.673Z" } 426 | wheels = [ 427 | { url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" }, 428 | ] 429 | 430 | [[package]] 431 | name = "parso" 432 | version = "0.8.4" 433 | source = { registry = "https://pypi.org/simple" } 434 | sdist = { url = "https://files.pythonhosted.org/packages/66/94/68e2e17afaa9169cf6412ab0f28623903be73d1b32e208d9e8e541bb086d/parso-0.8.4.tar.gz", hash = "sha256:eb3a7b58240fb99099a345571deecc0f9540ea5f4dd2fe14c2a99d6b281ab92d", size = 400609, upload-time = "2024-04-05T09:43:55.897Z" } 435 | wheels = [ 436 | { url = "https://files.pythonhosted.org/packages/c6/ac/dac4a63f978e4dcb3c6d3a78c4d8e0192a113d288502a1216950c41b1027/parso-0.8.4-py2.py3-none-any.whl", hash = "sha256:a418670a20291dacd2dddc80c377c5c3791378ee1e8d12bffc35420643d43f18", size = 103650, upload-time = "2024-04-05T09:43:53.299Z" }, 437 | ] 438 | 439 | [[package]] 440 | name = "pathspec" 441 | version = "0.12.1" 442 | source = { registry = "https://pypi.org/simple" } 443 | sdist = { url = "https://files.pythonhosted.org/packages/ca/bc/f35b8446f4531a7cb215605d100cd88b7ac6f44ab3fc94870c120ab3adbf/pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712", size = 51043, upload-time = "2023-12-10T22:30:45Z" } 444 | wheels = [ 445 | { url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191, upload-time = "2023-12-10T22:30:43.14Z" }, 446 | ] 447 | 448 | [[package]] 449 | name = "pdbpp" 450 | version = "0.11.6" 451 | source = { registry = "https://pypi.org/simple" } 452 | dependencies = [ 453 | { name = "fancycompleter" }, 454 | { name = "pygments" }, 455 | ] 456 | sdist = { url = "https://files.pythonhosted.org/packages/27/ef/e6ae1a1e1d2cbe0fbf04f22b21d7d58e8e13d24dfcc3b6a4dea18a3ed1e0/pdbpp-0.11.6.tar.gz", hash = "sha256:36a73c5bcf0c3c35034be4cf99e6106e3ee0c8f5e0faafc2cf9be5f1481eb4b7", size = 78178, upload-time = "2025-04-16T10:20:07.008Z" } 457 | wheels = [ 458 | { url = "https://files.pythonhosted.org/packages/c5/e1/77fa5c45fcd95a80b0d793b604c19b71c9fa8d5b27d403eced79f3842828/pdbpp-0.11.6-py3-none-any.whl", hash = "sha256:8e024d36bd2f35a3b19d8732524c696b8b4aef633250d28547198e746cd81ccb", size = 33334, upload-time = "2025-04-16T10:20:05.529Z" }, 459 | ] 460 | 461 | [[package]] 462 | name = "pexpect" 463 | version = "4.9.0" 464 | source = { registry = "https://pypi.org/simple" } 465 | dependencies = [ 466 | { name = "ptyprocess" }, 467 | ] 468 | sdist = { url = "https://files.pythonhosted.org/packages/42/92/cc564bf6381ff43ce1f4d06852fc19a2f11d180f23dc32d9588bee2f149d/pexpect-4.9.0.tar.gz", hash = "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f", size = 166450, upload-time = "2023-11-25T09:07:26.339Z" } 469 | wheels = [ 470 | { url = "https://files.pythonhosted.org/packages/9e/c3/059298687310d527a58bb01f3b1965787ee3b40dce76752eda8b44e9a2c5/pexpect-4.9.0-py2.py3-none-any.whl", hash = "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523", size = 63772, upload-time = "2023-11-25T06:56:14.81Z" }, 471 | ] 472 | 473 | [[package]] 474 | name = "platformdirs" 475 | version = "4.3.8" 476 | source = { registry = "https://pypi.org/simple" } 477 | sdist = { url = "https://files.pythonhosted.org/packages/fe/8b/3c73abc9c759ecd3f1f7ceff6685840859e8070c4d947c93fae71f6a0bf2/platformdirs-4.3.8.tar.gz", hash = "sha256:3d512d96e16bcb959a814c9f348431070822a6496326a4be0911c40b5a74c2bc", size = 21362, upload-time = "2025-05-07T22:47:42.121Z" } 478 | wheels = [ 479 | { url = "https://files.pythonhosted.org/packages/fe/39/979e8e21520d4e47a0bbe349e2713c0aac6f3d853d0e5b34d76206c439aa/platformdirs-4.3.8-py3-none-any.whl", hash = "sha256:ff7059bb7eb1179e2685604f4aaf157cfd9535242bd23742eadc3c13542139b4", size = 18567, upload-time = "2025-05-07T22:47:40.376Z" }, 480 | ] 481 | 482 | [[package]] 483 | name = "pluggy" 484 | version = "1.6.0" 485 | source = { registry = "https://pypi.org/simple" } 486 | sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" } 487 | wheels = [ 488 | { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" }, 489 | ] 490 | 491 | [[package]] 492 | name = "pre-commit" 493 | version = "4.2.0" 494 | source = { registry = "https://pypi.org/simple" } 495 | dependencies = [ 496 | { name = "cfgv" }, 497 | { name = "identify" }, 498 | { name = "nodeenv" }, 499 | { name = "pyyaml" }, 500 | { name = "virtualenv" }, 501 | ] 502 | sdist = { url = "https://files.pythonhosted.org/packages/08/39/679ca9b26c7bb2999ff122d50faa301e49af82ca9c066ec061cfbc0c6784/pre_commit-4.2.0.tar.gz", hash = "sha256:601283b9757afd87d40c4c4a9b2b5de9637a8ea02eaff7adc2d0fb4e04841146", size = 193424, upload-time = "2025-03-18T21:35:20.987Z" } 503 | wheels = [ 504 | { url = "https://files.pythonhosted.org/packages/88/74/a88bf1b1efeae488a0c0b7bdf71429c313722d1fc0f377537fbe554e6180/pre_commit-4.2.0-py2.py3-none-any.whl", hash = "sha256:a009ca7205f1eb497d10b845e52c838a98b6cdd2102a6c8e4540e94ee75c58bd", size = 220707, upload-time = "2025-03-18T21:35:19.343Z" }, 505 | ] 506 | 507 | [[package]] 508 | name = "prompt-toolkit" 509 | version = "3.0.51" 510 | source = { registry = "https://pypi.org/simple" } 511 | dependencies = [ 512 | { name = "wcwidth" }, 513 | ] 514 | sdist = { url = "https://files.pythonhosted.org/packages/bb/6e/9d084c929dfe9e3bfe0c6a47e31f78a25c54627d64a66e884a8bf5474f1c/prompt_toolkit-3.0.51.tar.gz", hash = "sha256:931a162e3b27fc90c86f1b48bb1fb2c528c2761475e57c9c06de13311c7b54ed", size = 428940, upload-time = "2025-04-15T09:18:47.731Z" } 515 | wheels = [ 516 | { url = "https://files.pythonhosted.org/packages/ce/4f/5249960887b1fbe561d9ff265496d170b55a735b76724f10ef19f9e40716/prompt_toolkit-3.0.51-py3-none-any.whl", hash = "sha256:52742911fde84e2d423e2f9a4cf1de7d7ac4e51958f648d9540e0fb8db077b07", size = 387810, upload-time = "2025-04-15T09:18:44.753Z" }, 517 | ] 518 | 519 | [[package]] 520 | name = "ptyprocess" 521 | version = "0.7.0" 522 | source = { registry = "https://pypi.org/simple" } 523 | sdist = { url = "https://files.pythonhosted.org/packages/20/e5/16ff212c1e452235a90aeb09066144d0c5a6a8c0834397e03f5224495c4e/ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220", size = 70762, upload-time = "2020-12-28T15:15:30.155Z" } 524 | wheels = [ 525 | { url = "https://files.pythonhosted.org/packages/22/a6/858897256d0deac81a172289110f31629fc4cee19b6f01283303e18c8db3/ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35", size = 13993, upload-time = "2020-12-28T15:15:28.35Z" }, 526 | ] 527 | 528 | [[package]] 529 | name = "pure-eval" 530 | version = "0.2.3" 531 | source = { registry = "https://pypi.org/simple" } 532 | sdist = { url = "https://files.pythonhosted.org/packages/cd/05/0a34433a064256a578f1783a10da6df098ceaa4a57bbeaa96a6c0352786b/pure_eval-0.2.3.tar.gz", hash = "sha256:5f4e983f40564c576c7c8635ae88db5956bb2229d7e9237d03b3c0b0190eaf42", size = 19752, upload-time = "2024-07-21T12:58:21.801Z" } 533 | wheels = [ 534 | { url = "https://files.pythonhosted.org/packages/8e/37/efad0257dc6e593a18957422533ff0f87ede7c9c6ea010a2177d738fb82f/pure_eval-0.2.3-py3-none-any.whl", hash = "sha256:1db8e35b67b3d218d818ae653e27f06c3aa420901fa7b081ca98cbedc874e0d0", size = 11842, upload-time = "2024-07-21T12:58:20.04Z" }, 535 | ] 536 | 537 | [[package]] 538 | name = "pygments" 539 | version = "2.19.2" 540 | source = { registry = "https://pypi.org/simple" } 541 | sdist = { url = "https://files.pythonhosted.org/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631, upload-time = "2025-06-21T13:39:12.283Z" } 542 | wheels = [ 543 | { url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" }, 544 | ] 545 | 546 | [[package]] 547 | name = "pyreadline3" 548 | version = "3.5.4" 549 | source = { registry = "https://pypi.org/simple" } 550 | sdist = { url = "https://files.pythonhosted.org/packages/0f/49/4cea918a08f02817aabae639e3d0ac046fef9f9180518a3ad394e22da148/pyreadline3-3.5.4.tar.gz", hash = "sha256:8d57d53039a1c75adba8e50dd3d992b28143480816187ea5efbd5c78e6c885b7", size = 99839, upload-time = "2024-09-19T02:40:10.062Z" } 551 | wheels = [ 552 | { url = "https://files.pythonhosted.org/packages/5a/dc/491b7661614ab97483abf2056be1deee4dc2490ecbf7bff9ab5cdbac86e1/pyreadline3-3.5.4-py3-none-any.whl", hash = "sha256:eaf8e6cc3c49bcccf145fc6067ba8643d1df34d604a1ec0eccbf7a18e6d3fae6", size = 83178, upload-time = "2024-09-19T02:40:08.598Z" }, 553 | ] 554 | 555 | [[package]] 556 | name = "pyrepl" 557 | version = "0.11.3.post1" 558 | source = { registry = "https://pypi.org/simple" } 559 | sdist = { url = "https://files.pythonhosted.org/packages/92/78/65b9a4a4b15f7f5aae84c3edb9d3adc1acb2acc38eb9d5404cd5cf980927/pyrepl-0.11.3.post1.tar.gz", hash = "sha256:0ca7568c8be919b69f99644d29d31738a5b1a87750d06dd36564bcfad278d402", size = 50954, upload-time = "2025-04-13T12:21:51.403Z" } 560 | wheels = [ 561 | { url = "https://files.pythonhosted.org/packages/2d/45/02a5e2da58a32ff407b14d38690c1d2f8705bd6909320817b444070dcbb0/pyrepl-0.11.3.post1-py3-none-any.whl", hash = "sha256:59fcd67588892731dc6e7aff106c380d303d54324ff028827804a2b056223d92", size = 55613, upload-time = "2025-04-13T12:21:49.464Z" }, 562 | ] 563 | 564 | [[package]] 565 | name = "pytest" 566 | version = "8.4.1" 567 | source = { registry = "https://pypi.org/simple" } 568 | dependencies = [ 569 | { name = "colorama", marker = "sys_platform == 'win32'" }, 570 | { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, 571 | { name = "iniconfig" }, 572 | { name = "packaging" }, 573 | { name = "pluggy" }, 574 | { name = "pygments" }, 575 | { name = "tomli", marker = "python_full_version < '3.11'" }, 576 | ] 577 | sdist = { url = "https://files.pythonhosted.org/packages/08/ba/45911d754e8eba3d5a841a5ce61a65a685ff1798421ac054f85aa8747dfb/pytest-8.4.1.tar.gz", hash = "sha256:7c67fd69174877359ed9371ec3af8a3d2b04741818c51e5e99cc1742251fa93c", size = 1517714, upload-time = "2025-06-18T05:48:06.109Z" } 578 | wheels = [ 579 | { url = "https://files.pythonhosted.org/packages/29/16/c8a903f4c4dffe7a12843191437d7cd8e32751d5de349d45d3fe69544e87/pytest-8.4.1-py3-none-any.whl", hash = "sha256:539c70ba6fcead8e78eebbf1115e8b589e7565830d7d006a8723f19ac8a0afb7", size = 365474, upload-time = "2025-06-18T05:48:03.955Z" }, 580 | ] 581 | 582 | [[package]] 583 | name = "pytest-cov" 584 | version = "6.2.1" 585 | source = { registry = "https://pypi.org/simple" } 586 | dependencies = [ 587 | { name = "coverage", extra = ["toml"] }, 588 | { name = "pluggy" }, 589 | { name = "pytest" }, 590 | ] 591 | sdist = { url = "https://files.pythonhosted.org/packages/18/99/668cade231f434aaa59bbfbf49469068d2ddd945000621d3d165d2e7dd7b/pytest_cov-6.2.1.tar.gz", hash = "sha256:25cc6cc0a5358204b8108ecedc51a9b57b34cc6b8c967cc2c01a4e00d8a67da2", size = 69432, upload-time = "2025-06-12T10:47:47.684Z" } 592 | wheels = [ 593 | { url = "https://files.pythonhosted.org/packages/bc/16/4ea354101abb1287856baa4af2732be351c7bee728065aed451b678153fd/pytest_cov-6.2.1-py3-none-any.whl", hash = "sha256:f5bc4c23f42f1cdd23c70b1dab1bbaef4fc505ba950d53e0081d0730dd7e86d5", size = 24644, upload-time = "2025-06-12T10:47:45.932Z" }, 594 | ] 595 | 596 | [[package]] 597 | name = "pyyaml" 598 | version = "6.0.2" 599 | source = { registry = "https://pypi.org/simple" } 600 | sdist = { url = "https://files.pythonhosted.org/packages/54/ed/79a089b6be93607fa5cdaedf301d7dfb23af5f25c398d5ead2525b063e17/pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e", size = 130631, upload-time = "2024-08-06T20:33:50.674Z" } 601 | wheels = [ 602 | { url = "https://files.pythonhosted.org/packages/9b/95/a3fac87cb7158e231b5a6012e438c647e1a87f09f8e0d123acec8ab8bf71/PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086", size = 184199, upload-time = "2024-08-06T20:31:40.178Z" }, 603 | { url = "https://files.pythonhosted.org/packages/c7/7a/68bd47624dab8fd4afbfd3c48e3b79efe09098ae941de5b58abcbadff5cb/PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf", size = 171758, upload-time = "2024-08-06T20:31:42.173Z" }, 604 | { url = "https://files.pythonhosted.org/packages/49/ee/14c54df452143b9ee9f0f29074d7ca5516a36edb0b4cc40c3f280131656f/PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237", size = 718463, upload-time = "2024-08-06T20:31:44.263Z" }, 605 | { url = "https://files.pythonhosted.org/packages/4d/61/de363a97476e766574650d742205be468921a7b532aa2499fcd886b62530/PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b", size = 719280, upload-time = "2024-08-06T20:31:50.199Z" }, 606 | { url = "https://files.pythonhosted.org/packages/6b/4e/1523cb902fd98355e2e9ea5e5eb237cbc5f3ad5f3075fa65087aa0ecb669/PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed", size = 751239, upload-time = "2024-08-06T20:31:52.292Z" }, 607 | { url = "https://files.pythonhosted.org/packages/b7/33/5504b3a9a4464893c32f118a9cc045190a91637b119a9c881da1cf6b7a72/PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180", size = 695802, upload-time = "2024-08-06T20:31:53.836Z" }, 608 | { url = "https://files.pythonhosted.org/packages/5c/20/8347dcabd41ef3a3cdc4f7b7a2aff3d06598c8779faa189cdbf878b626a4/PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68", size = 720527, upload-time = "2024-08-06T20:31:55.565Z" }, 609 | { url = "https://files.pythonhosted.org/packages/be/aa/5afe99233fb360d0ff37377145a949ae258aaab831bde4792b32650a4378/PyYAML-6.0.2-cp310-cp310-win32.whl", hash = "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99", size = 144052, upload-time = "2024-08-06T20:31:56.914Z" }, 610 | { url = "https://files.pythonhosted.org/packages/b5/84/0fa4b06f6d6c958d207620fc60005e241ecedceee58931bb20138e1e5776/PyYAML-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e", size = 161774, upload-time = "2024-08-06T20:31:58.304Z" }, 611 | { url = "https://files.pythonhosted.org/packages/f8/aa/7af4e81f7acba21a4c6be026da38fd2b872ca46226673c89a758ebdc4fd2/PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774", size = 184612, upload-time = "2024-08-06T20:32:03.408Z" }, 612 | { url = "https://files.pythonhosted.org/packages/8b/62/b9faa998fd185f65c1371643678e4d58254add437edb764a08c5a98fb986/PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee", size = 172040, upload-time = "2024-08-06T20:32:04.926Z" }, 613 | { url = "https://files.pythonhosted.org/packages/ad/0c/c804f5f922a9a6563bab712d8dcc70251e8af811fce4524d57c2c0fd49a4/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c", size = 736829, upload-time = "2024-08-06T20:32:06.459Z" }, 614 | { url = "https://files.pythonhosted.org/packages/51/16/6af8d6a6b210c8e54f1406a6b9481febf9c64a3109c541567e35a49aa2e7/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317", size = 764167, upload-time = "2024-08-06T20:32:08.338Z" }, 615 | { url = "https://files.pythonhosted.org/packages/75/e4/2c27590dfc9992f73aabbeb9241ae20220bd9452df27483b6e56d3975cc5/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85", size = 762952, upload-time = "2024-08-06T20:32:14.124Z" }, 616 | { url = "https://files.pythonhosted.org/packages/9b/97/ecc1abf4a823f5ac61941a9c00fe501b02ac3ab0e373c3857f7d4b83e2b6/PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4", size = 735301, upload-time = "2024-08-06T20:32:16.17Z" }, 617 | { url = "https://files.pythonhosted.org/packages/45/73/0f49dacd6e82c9430e46f4a027baa4ca205e8b0a9dce1397f44edc23559d/PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e", size = 756638, upload-time = "2024-08-06T20:32:18.555Z" }, 618 | { url = "https://files.pythonhosted.org/packages/22/5f/956f0f9fc65223a58fbc14459bf34b4cc48dec52e00535c79b8db361aabd/PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5", size = 143850, upload-time = "2024-08-06T20:32:19.889Z" }, 619 | { url = "https://files.pythonhosted.org/packages/ed/23/8da0bbe2ab9dcdd11f4f4557ccaf95c10b9811b13ecced089d43ce59c3c8/PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44", size = 161980, upload-time = "2024-08-06T20:32:21.273Z" }, 620 | { url = "https://files.pythonhosted.org/packages/86/0c/c581167fc46d6d6d7ddcfb8c843a4de25bdd27e4466938109ca68492292c/PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab", size = 183873, upload-time = "2024-08-06T20:32:25.131Z" }, 621 | { url = "https://files.pythonhosted.org/packages/a8/0c/38374f5bb272c051e2a69281d71cba6fdb983413e6758b84482905e29a5d/PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725", size = 173302, upload-time = "2024-08-06T20:32:26.511Z" }, 622 | { url = "https://files.pythonhosted.org/packages/c3/93/9916574aa8c00aa06bbac729972eb1071d002b8e158bd0e83a3b9a20a1f7/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5", size = 739154, upload-time = "2024-08-06T20:32:28.363Z" }, 623 | { url = "https://files.pythonhosted.org/packages/95/0f/b8938f1cbd09739c6da569d172531567dbcc9789e0029aa070856f123984/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425", size = 766223, upload-time = "2024-08-06T20:32:30.058Z" }, 624 | { url = "https://files.pythonhosted.org/packages/b9/2b/614b4752f2e127db5cc206abc23a8c19678e92b23c3db30fc86ab731d3bd/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476", size = 767542, upload-time = "2024-08-06T20:32:31.881Z" }, 625 | { url = "https://files.pythonhosted.org/packages/d4/00/dd137d5bcc7efea1836d6264f049359861cf548469d18da90cd8216cf05f/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48", size = 731164, upload-time = "2024-08-06T20:32:37.083Z" }, 626 | { url = "https://files.pythonhosted.org/packages/c9/1f/4f998c900485e5c0ef43838363ba4a9723ac0ad73a9dc42068b12aaba4e4/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b", size = 756611, upload-time = "2024-08-06T20:32:38.898Z" }, 627 | { url = "https://files.pythonhosted.org/packages/df/d1/f5a275fdb252768b7a11ec63585bc38d0e87c9e05668a139fea92b80634c/PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4", size = 140591, upload-time = "2024-08-06T20:32:40.241Z" }, 628 | { url = "https://files.pythonhosted.org/packages/0c/e8/4f648c598b17c3d06e8753d7d13d57542b30d56e6c2dedf9c331ae56312e/PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8", size = 156338, upload-time = "2024-08-06T20:32:41.93Z" }, 629 | { url = "https://files.pythonhosted.org/packages/ef/e3/3af305b830494fa85d95f6d95ef7fa73f2ee1cc8ef5b495c7c3269fb835f/PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba", size = 181309, upload-time = "2024-08-06T20:32:43.4Z" }, 630 | { url = "https://files.pythonhosted.org/packages/45/9f/3b1c20a0b7a3200524eb0076cc027a970d320bd3a6592873c85c92a08731/PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1", size = 171679, upload-time = "2024-08-06T20:32:44.801Z" }, 631 | { url = "https://files.pythonhosted.org/packages/7c/9a/337322f27005c33bcb656c655fa78325b730324c78620e8328ae28b64d0c/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133", size = 733428, upload-time = "2024-08-06T20:32:46.432Z" }, 632 | { url = "https://files.pythonhosted.org/packages/a3/69/864fbe19e6c18ea3cc196cbe5d392175b4cf3d5d0ac1403ec3f2d237ebb5/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484", size = 763361, upload-time = "2024-08-06T20:32:51.188Z" }, 633 | { url = "https://files.pythonhosted.org/packages/04/24/b7721e4845c2f162d26f50521b825fb061bc0a5afcf9a386840f23ea19fa/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5", size = 759523, upload-time = "2024-08-06T20:32:53.019Z" }, 634 | { url = "https://files.pythonhosted.org/packages/2b/b2/e3234f59ba06559c6ff63c4e10baea10e5e7df868092bf9ab40e5b9c56b6/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc", size = 726660, upload-time = "2024-08-06T20:32:54.708Z" }, 635 | { url = "https://files.pythonhosted.org/packages/fe/0f/25911a9f080464c59fab9027482f822b86bf0608957a5fcc6eaac85aa515/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652", size = 751597, upload-time = "2024-08-06T20:32:56.985Z" }, 636 | { url = "https://files.pythonhosted.org/packages/14/0d/e2c3b43bbce3cf6bd97c840b46088a3031085179e596d4929729d8d68270/PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183", size = 140527, upload-time = "2024-08-06T20:33:03.001Z" }, 637 | { url = "https://files.pythonhosted.org/packages/fa/de/02b54f42487e3d3c6efb3f89428677074ca7bf43aae402517bc7cca949f3/PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", size = 156446, upload-time = "2024-08-06T20:33:04.33Z" }, 638 | { url = "https://files.pythonhosted.org/packages/65/d8/b7a1db13636d7fb7d4ff431593c510c8b8fca920ade06ca8ef20015493c5/PyYAML-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d", size = 184777, upload-time = "2024-08-06T20:33:25.896Z" }, 639 | { url = "https://files.pythonhosted.org/packages/0a/02/6ec546cd45143fdf9840b2c6be8d875116a64076218b61d68e12548e5839/PyYAML-6.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f", size = 172318, upload-time = "2024-08-06T20:33:27.212Z" }, 640 | { url = "https://files.pythonhosted.org/packages/0e/9a/8cc68be846c972bda34f6c2a93abb644fb2476f4dcc924d52175786932c9/PyYAML-6.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290", size = 720891, upload-time = "2024-08-06T20:33:28.974Z" }, 641 | { url = "https://files.pythonhosted.org/packages/e9/6c/6e1b7f40181bc4805e2e07f4abc10a88ce4648e7e95ff1abe4ae4014a9b2/PyYAML-6.0.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12", size = 722614, upload-time = "2024-08-06T20:33:34.157Z" }, 642 | { url = "https://files.pythonhosted.org/packages/3d/32/e7bd8535d22ea2874cef6a81021ba019474ace0d13a4819c2a4bce79bd6a/PyYAML-6.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19", size = 737360, upload-time = "2024-08-06T20:33:35.84Z" }, 643 | { url = "https://files.pythonhosted.org/packages/d7/12/7322c1e30b9be969670b672573d45479edef72c9a0deac3bb2868f5d7469/PyYAML-6.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e", size = 699006, upload-time = "2024-08-06T20:33:37.501Z" }, 644 | { url = "https://files.pythonhosted.org/packages/82/72/04fcad41ca56491995076630c3ec1e834be241664c0c09a64c9a2589b507/PyYAML-6.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725", size = 723577, upload-time = "2024-08-06T20:33:39.389Z" }, 645 | { url = "https://files.pythonhosted.org/packages/ed/5e/46168b1f2757f1fcd442bc3029cd8767d88a98c9c05770d8b420948743bb/PyYAML-6.0.2-cp39-cp39-win32.whl", hash = "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631", size = 144593, upload-time = "2024-08-06T20:33:46.63Z" }, 646 | { url = "https://files.pythonhosted.org/packages/19/87/5124b1c1f2412bb95c59ec481eaf936cd32f0fe2a7b16b97b81c4c017a6a/PyYAML-6.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8", size = 162312, upload-time = "2024-08-06T20:33:49.073Z" }, 647 | ] 648 | 649 | [[package]] 650 | name = "ruff" 651 | version = "0.12.2" 652 | source = { registry = "https://pypi.org/simple" } 653 | sdist = { url = "https://files.pythonhosted.org/packages/6c/3d/d9a195676f25d00dbfcf3cf95fdd4c685c497fcfa7e862a44ac5e4e96480/ruff-0.12.2.tar.gz", hash = "sha256:d7b4f55cd6f325cb7621244f19c873c565a08aff5a4ba9c69aa7355f3f7afd3e", size = 4432239, upload-time = "2025-07-03T16:40:19.566Z" } 654 | wheels = [ 655 | { url = "https://files.pythonhosted.org/packages/74/b6/2098d0126d2d3318fd5bec3ad40d06c25d377d95749f7a0c5af17129b3b1/ruff-0.12.2-py3-none-linux_armv6l.whl", hash = "sha256:093ea2b221df1d2b8e7ad92fc6ffdca40a2cb10d8564477a987b44fd4008a7be", size = 10369761, upload-time = "2025-07-03T16:39:38.847Z" }, 656 | { url = "https://files.pythonhosted.org/packages/b1/4b/5da0142033dbe155dc598cfb99262d8ee2449d76920ea92c4eeb9547c208/ruff-0.12.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:09e4cf27cc10f96b1708100fa851e0daf21767e9709e1649175355280e0d950e", size = 11155659, upload-time = "2025-07-03T16:39:42.294Z" }, 657 | { url = "https://files.pythonhosted.org/packages/3e/21/967b82550a503d7c5c5c127d11c935344b35e8c521f52915fc858fb3e473/ruff-0.12.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:8ae64755b22f4ff85e9c52d1f82644abd0b6b6b6deedceb74bd71f35c24044cc", size = 10537769, upload-time = "2025-07-03T16:39:44.75Z" }, 658 | { url = "https://files.pythonhosted.org/packages/33/91/00cff7102e2ec71a4890fb7ba1803f2cdb122d82787c7d7cf8041fe8cbc1/ruff-0.12.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3eb3a6b2db4d6e2c77e682f0b988d4d61aff06860158fdb413118ca133d57922", size = 10717602, upload-time = "2025-07-03T16:39:47.652Z" }, 659 | { url = "https://files.pythonhosted.org/packages/9b/eb/928814daec4e1ba9115858adcda44a637fb9010618721937491e4e2283b8/ruff-0.12.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:73448de992d05517170fc37169cbca857dfeaeaa8c2b9be494d7bcb0d36c8f4b", size = 10198772, upload-time = "2025-07-03T16:39:49.641Z" }, 660 | { url = "https://files.pythonhosted.org/packages/50/fa/f15089bc20c40f4f72334f9145dde55ab2b680e51afb3b55422effbf2fb6/ruff-0.12.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3b8b94317cbc2ae4a2771af641739f933934b03555e51515e6e021c64441532d", size = 11845173, upload-time = "2025-07-03T16:39:52.069Z" }, 661 | { url = "https://files.pythonhosted.org/packages/43/9f/1f6f98f39f2b9302acc161a4a2187b1e3a97634fe918a8e731e591841cf4/ruff-0.12.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:45fc42c3bf1d30d2008023a0a9a0cfb06bf9835b147f11fe0679f21ae86d34b1", size = 12553002, upload-time = "2025-07-03T16:39:54.551Z" }, 662 | { url = "https://files.pythonhosted.org/packages/d8/70/08991ac46e38ddd231c8f4fd05ef189b1b94be8883e8c0c146a025c20a19/ruff-0.12.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce48f675c394c37e958bf229fb5c1e843e20945a6d962cf3ea20b7a107dcd9f4", size = 12171330, upload-time = "2025-07-03T16:39:57.55Z" }, 663 | { url = "https://files.pythonhosted.org/packages/88/a9/5a55266fec474acfd0a1c73285f19dd22461d95a538f29bba02edd07a5d9/ruff-0.12.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:793d8859445ea47591272021a81391350205a4af65a9392401f418a95dfb75c9", size = 11774717, upload-time = "2025-07-03T16:39:59.78Z" }, 664 | { url = "https://files.pythonhosted.org/packages/87/e5/0c270e458fc73c46c0d0f7cf970bb14786e5fdb88c87b5e423a4bd65232b/ruff-0.12.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6932323db80484dda89153da3d8e58164d01d6da86857c79f1961934354992da", size = 11646659, upload-time = "2025-07-03T16:40:01.934Z" }, 665 | { url = "https://files.pythonhosted.org/packages/b7/b6/45ab96070c9752af37f0be364d849ed70e9ccede07675b0ec4e3ef76b63b/ruff-0.12.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:6aa7e623a3a11538108f61e859ebf016c4f14a7e6e4eba1980190cacb57714ce", size = 10604012, upload-time = "2025-07-03T16:40:04.363Z" }, 666 | { url = "https://files.pythonhosted.org/packages/86/91/26a6e6a424eb147cc7627eebae095cfa0b4b337a7c1c413c447c9ebb72fd/ruff-0.12.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:2a4a20aeed74671b2def096bdf2eac610c7d8ffcbf4fb0e627c06947a1d7078d", size = 10176799, upload-time = "2025-07-03T16:40:06.514Z" }, 667 | { url = "https://files.pythonhosted.org/packages/f5/0c/9f344583465a61c8918a7cda604226e77b2c548daf8ef7c2bfccf2b37200/ruff-0.12.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:71a4c550195612f486c9d1f2b045a600aeba851b298c667807ae933478fcef04", size = 11241507, upload-time = "2025-07-03T16:40:08.708Z" }, 668 | { url = "https://files.pythonhosted.org/packages/1c/b7/99c34ded8fb5f86c0280278fa89a0066c3760edc326e935ce0b1550d315d/ruff-0.12.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:4987b8f4ceadf597c927beee65a5eaf994c6e2b631df963f86d8ad1bdea99342", size = 11717609, upload-time = "2025-07-03T16:40:10.836Z" }, 669 | { url = "https://files.pythonhosted.org/packages/51/de/8589fa724590faa057e5a6d171e7f2f6cffe3287406ef40e49c682c07d89/ruff-0.12.2-py3-none-win32.whl", hash = "sha256:369ffb69b70cd55b6c3fc453b9492d98aed98062db9fec828cdfd069555f5f1a", size = 10523823, upload-time = "2025-07-03T16:40:13.203Z" }, 670 | { url = "https://files.pythonhosted.org/packages/94/47/8abf129102ae4c90cba0c2199a1a9b0fa896f6f806238d6f8c14448cc748/ruff-0.12.2-py3-none-win_amd64.whl", hash = "sha256:dca8a3b6d6dc9810ed8f328d406516bf4d660c00caeaef36eb831cf4871b0639", size = 11629831, upload-time = "2025-07-03T16:40:15.478Z" }, 671 | { url = "https://files.pythonhosted.org/packages/e2/1f/72d2946e3cc7456bb837e88000eb3437e55f80db339c840c04015a11115d/ruff-0.12.2-py3-none-win_arm64.whl", hash = "sha256:48d6c6bfb4761df68bc05ae630e24f506755e702d4fb08f08460be778c7ccb12", size = 10735334, upload-time = "2025-07-03T16:40:17.677Z" }, 672 | ] 673 | 674 | [[package]] 675 | name = "stack-data" 676 | version = "0.6.3" 677 | source = { registry = "https://pypi.org/simple" } 678 | dependencies = [ 679 | { name = "asttokens" }, 680 | { name = "executing" }, 681 | { name = "pure-eval" }, 682 | ] 683 | sdist = { url = "https://files.pythonhosted.org/packages/28/e3/55dcc2cfbc3ca9c29519eb6884dd1415ecb53b0e934862d3559ddcb7e20b/stack_data-0.6.3.tar.gz", hash = "sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9", size = 44707, upload-time = "2023-09-30T13:58:05.479Z" } 684 | wheels = [ 685 | { url = "https://files.pythonhosted.org/packages/f1/7b/ce1eafaf1a76852e2ec9b22edecf1daa58175c090266e9f6c64afcd81d91/stack_data-0.6.3-py3-none-any.whl", hash = "sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695", size = 24521, upload-time = "2023-09-30T13:58:03.53Z" }, 686 | ] 687 | 688 | [[package]] 689 | name = "tomli" 690 | version = "2.2.1" 691 | source = { registry = "https://pypi.org/simple" } 692 | sdist = { url = "https://files.pythonhosted.org/packages/18/87/302344fed471e44a87289cf4967697d07e532f2421fdaf868a303cbae4ff/tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff", size = 17175, upload-time = "2024-11-27T22:38:36.873Z" } 693 | wheels = [ 694 | { url = "https://files.pythonhosted.org/packages/43/ca/75707e6efa2b37c77dadb324ae7d9571cb424e61ea73fad7c56c2d14527f/tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249", size = 131077, upload-time = "2024-11-27T22:37:54.956Z" }, 695 | { url = "https://files.pythonhosted.org/packages/c7/16/51ae563a8615d472fdbffc43a3f3d46588c264ac4f024f63f01283becfbb/tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6", size = 123429, upload-time = "2024-11-27T22:37:56.698Z" }, 696 | { url = "https://files.pythonhosted.org/packages/f1/dd/4f6cd1e7b160041db83c694abc78e100473c15d54620083dbd5aae7b990e/tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a", size = 226067, upload-time = "2024-11-27T22:37:57.63Z" }, 697 | { url = "https://files.pythonhosted.org/packages/a9/6b/c54ede5dc70d648cc6361eaf429304b02f2871a345bbdd51e993d6cdf550/tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee", size = 236030, upload-time = "2024-11-27T22:37:59.344Z" }, 698 | { url = "https://files.pythonhosted.org/packages/1f/47/999514fa49cfaf7a92c805a86c3c43f4215621855d151b61c602abb38091/tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e", size = 240898, upload-time = "2024-11-27T22:38:00.429Z" }, 699 | { url = "https://files.pythonhosted.org/packages/73/41/0a01279a7ae09ee1573b423318e7934674ce06eb33f50936655071d81a24/tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4", size = 229894, upload-time = "2024-11-27T22:38:02.094Z" }, 700 | { url = "https://files.pythonhosted.org/packages/55/18/5d8bc5b0a0362311ce4d18830a5d28943667599a60d20118074ea1b01bb7/tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106", size = 245319, upload-time = "2024-11-27T22:38:03.206Z" }, 701 | { url = "https://files.pythonhosted.org/packages/92/a3/7ade0576d17f3cdf5ff44d61390d4b3febb8a9fc2b480c75c47ea048c646/tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8", size = 238273, upload-time = "2024-11-27T22:38:04.217Z" }, 702 | { url = "https://files.pythonhosted.org/packages/72/6f/fa64ef058ac1446a1e51110c375339b3ec6be245af9d14c87c4a6412dd32/tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff", size = 98310, upload-time = "2024-11-27T22:38:05.908Z" }, 703 | { url = "https://files.pythonhosted.org/packages/6a/1c/4a2dcde4a51b81be3530565e92eda625d94dafb46dbeb15069df4caffc34/tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b", size = 108309, upload-time = "2024-11-27T22:38:06.812Z" }, 704 | { url = "https://files.pythonhosted.org/packages/52/e1/f8af4c2fcde17500422858155aeb0d7e93477a0d59a98e56cbfe75070fd0/tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea", size = 132762, upload-time = "2024-11-27T22:38:07.731Z" }, 705 | { url = "https://files.pythonhosted.org/packages/03/b8/152c68bb84fc00396b83e7bbddd5ec0bd3dd409db4195e2a9b3e398ad2e3/tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8", size = 123453, upload-time = "2024-11-27T22:38:09.384Z" }, 706 | { url = "https://files.pythonhosted.org/packages/c8/d6/fc9267af9166f79ac528ff7e8c55c8181ded34eb4b0e93daa767b8841573/tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192", size = 233486, upload-time = "2024-11-27T22:38:10.329Z" }, 707 | { url = "https://files.pythonhosted.org/packages/5c/51/51c3f2884d7bab89af25f678447ea7d297b53b5a3b5730a7cb2ef6069f07/tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222", size = 242349, upload-time = "2024-11-27T22:38:11.443Z" }, 708 | { url = "https://files.pythonhosted.org/packages/ab/df/bfa89627d13a5cc22402e441e8a931ef2108403db390ff3345c05253935e/tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77", size = 252159, upload-time = "2024-11-27T22:38:13.099Z" }, 709 | { url = "https://files.pythonhosted.org/packages/9e/6e/fa2b916dced65763a5168c6ccb91066f7639bdc88b48adda990db10c8c0b/tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6", size = 237243, upload-time = "2024-11-27T22:38:14.766Z" }, 710 | { url = "https://files.pythonhosted.org/packages/b4/04/885d3b1f650e1153cbb93a6a9782c58a972b94ea4483ae4ac5cedd5e4a09/tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd", size = 259645, upload-time = "2024-11-27T22:38:15.843Z" }, 711 | { url = "https://files.pythonhosted.org/packages/9c/de/6b432d66e986e501586da298e28ebeefd3edc2c780f3ad73d22566034239/tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e", size = 244584, upload-time = "2024-11-27T22:38:17.645Z" }, 712 | { url = "https://files.pythonhosted.org/packages/1c/9a/47c0449b98e6e7d1be6cbac02f93dd79003234ddc4aaab6ba07a9a7482e2/tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98", size = 98875, upload-time = "2024-11-27T22:38:19.159Z" }, 713 | { url = "https://files.pythonhosted.org/packages/ef/60/9b9638f081c6f1261e2688bd487625cd1e660d0a85bd469e91d8db969734/tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4", size = 109418, upload-time = "2024-11-27T22:38:20.064Z" }, 714 | { url = "https://files.pythonhosted.org/packages/04/90/2ee5f2e0362cb8a0b6499dc44f4d7d48f8fff06d28ba46e6f1eaa61a1388/tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7", size = 132708, upload-time = "2024-11-27T22:38:21.659Z" }, 715 | { url = "https://files.pythonhosted.org/packages/c0/ec/46b4108816de6b385141f082ba99e315501ccd0a2ea23db4a100dd3990ea/tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c", size = 123582, upload-time = "2024-11-27T22:38:22.693Z" }, 716 | { url = "https://files.pythonhosted.org/packages/a0/bd/b470466d0137b37b68d24556c38a0cc819e8febe392d5b199dcd7f578365/tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13", size = 232543, upload-time = "2024-11-27T22:38:24.367Z" }, 717 | { url = "https://files.pythonhosted.org/packages/d9/e5/82e80ff3b751373f7cead2815bcbe2d51c895b3c990686741a8e56ec42ab/tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281", size = 241691, upload-time = "2024-11-27T22:38:26.081Z" }, 718 | { url = "https://files.pythonhosted.org/packages/05/7e/2a110bc2713557d6a1bfb06af23dd01e7dde52b6ee7dadc589868f9abfac/tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272", size = 251170, upload-time = "2024-11-27T22:38:27.921Z" }, 719 | { url = "https://files.pythonhosted.org/packages/64/7b/22d713946efe00e0adbcdfd6d1aa119ae03fd0b60ebed51ebb3fa9f5a2e5/tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140", size = 236530, upload-time = "2024-11-27T22:38:29.591Z" }, 720 | { url = "https://files.pythonhosted.org/packages/38/31/3a76f67da4b0cf37b742ca76beaf819dca0ebef26d78fc794a576e08accf/tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2", size = 258666, upload-time = "2024-11-27T22:38:30.639Z" }, 721 | { url = "https://files.pythonhosted.org/packages/07/10/5af1293da642aded87e8a988753945d0cf7e00a9452d3911dd3bb354c9e2/tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744", size = 243954, upload-time = "2024-11-27T22:38:31.702Z" }, 722 | { url = "https://files.pythonhosted.org/packages/5b/b9/1ed31d167be802da0fc95020d04cd27b7d7065cc6fbefdd2f9186f60d7bd/tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec", size = 98724, upload-time = "2024-11-27T22:38:32.837Z" }, 723 | { url = "https://files.pythonhosted.org/packages/c7/32/b0963458706accd9afcfeb867c0f9175a741bf7b19cd424230714d722198/tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69", size = 109383, upload-time = "2024-11-27T22:38:34.455Z" }, 724 | { url = "https://files.pythonhosted.org/packages/6e/c2/61d3e0f47e2b74ef40a68b9e6ad5984f6241a942f7cd3bbfbdbd03861ea9/tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc", size = 14257, upload-time = "2024-11-27T22:38:35.385Z" }, 725 | ] 726 | 727 | [[package]] 728 | name = "traitlets" 729 | version = "5.14.3" 730 | source = { registry = "https://pypi.org/simple" } 731 | sdist = { url = "https://files.pythonhosted.org/packages/eb/79/72064e6a701c2183016abbbfedaba506d81e30e232a68c9f0d6f6fcd1574/traitlets-5.14.3.tar.gz", hash = "sha256:9ed0579d3502c94b4b3732ac120375cda96f923114522847de4b3bb98b96b6b7", size = 161621, upload-time = "2024-04-19T11:11:49.746Z" } 732 | wheels = [ 733 | { url = "https://files.pythonhosted.org/packages/00/c0/8f5d070730d7836adc9c9b6408dec68c6ced86b304a9b26a14df072a6e8c/traitlets-5.14.3-py3-none-any.whl", hash = "sha256:b74e89e397b1ed28cc831db7aea759ba6640cb3de13090ca145426688ff1ac4f", size = 85359, upload-time = "2024-04-19T11:11:46.763Z" }, 734 | ] 735 | 736 | [[package]] 737 | name = "typing-extensions" 738 | version = "4.14.1" 739 | source = { registry = "https://pypi.org/simple" } 740 | sdist = { url = "https://files.pythonhosted.org/packages/98/5a/da40306b885cc8c09109dc2e1abd358d5684b1425678151cdaed4731c822/typing_extensions-4.14.1.tar.gz", hash = "sha256:38b39f4aeeab64884ce9f74c94263ef78f3c22467c8724005483154c26648d36", size = 107673, upload-time = "2025-07-04T13:28:34.16Z" } 741 | wheels = [ 742 | { url = "https://files.pythonhosted.org/packages/b5/00/d631e67a838026495268c2f6884f3711a15a9a2a96cd244fdaea53b823fb/typing_extensions-4.14.1-py3-none-any.whl", hash = "sha256:d1e1e3b58374dc93031d6eda2420a48ea44a36c2b4766a4fdeb3710755731d76", size = 43906, upload-time = "2025-07-04T13:28:32.743Z" }, 743 | ] 744 | 745 | [[package]] 746 | name = "virtualenv" 747 | version = "20.31.2" 748 | source = { registry = "https://pypi.org/simple" } 749 | dependencies = [ 750 | { name = "distlib" }, 751 | { name = "filelock" }, 752 | { name = "platformdirs" }, 753 | ] 754 | sdist = { url = "https://files.pythonhosted.org/packages/56/2c/444f465fb2c65f40c3a104fd0c495184c4f2336d65baf398e3c75d72ea94/virtualenv-20.31.2.tar.gz", hash = "sha256:e10c0a9d02835e592521be48b332b6caee6887f332c111aa79a09b9e79efc2af", size = 6076316, upload-time = "2025-05-08T17:58:23.811Z" } 755 | wheels = [ 756 | { url = "https://files.pythonhosted.org/packages/f3/40/b1c265d4b2b62b58576588510fc4d1fe60a86319c8de99fd8e9fec617d2c/virtualenv-20.31.2-py3-none-any.whl", hash = "sha256:36efd0d9650ee985f0cad72065001e66d49a6f24eb44d98980f630686243cf11", size = 6057982, upload-time = "2025-05-08T17:58:21.15Z" }, 757 | ] 758 | 759 | [[package]] 760 | name = "wcwidth" 761 | version = "0.2.13" 762 | source = { registry = "https://pypi.org/simple" } 763 | sdist = { url = "https://files.pythonhosted.org/packages/6c/63/53559446a878410fc5a5974feb13d31d78d752eb18aeba59c7fef1af7598/wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5", size = 101301, upload-time = "2024-01-06T02:10:57.829Z" } 764 | wheels = [ 765 | { url = "https://files.pythonhosted.org/packages/fd/84/fd2ba7aafacbad3c4201d395674fc6348826569da3c0937e75505ead3528/wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859", size = 34166, upload-time = "2024-01-06T02:10:55.763Z" }, 766 | ] 767 | --------------------------------------------------------------------------------