├── cfcrawler
├── py.typed
├── __init__.py
├── user_agent.py
├── types.py
├── tls.py
└── client.py
├── tests
├── __init__.py
├── test_ciphers.py
├── test_rotation.py
└── test_detect.py
├── docs
├── modules.md
└── index.md
├── .pre-commit-config.yaml
├── codecov.yaml
├── Makefile
├── tox.ini
├── .github
└── workflows
│ ├── main.yml
│ └── on-release-main.yml
├── pyproject.toml
├── LICENSE
├── mkdocs.yml
├── .gitignore
├── CONTRIBUTING.rst
├── README.md
├── uv.lock
└── poetry.lock
/cfcrawler/py.typed:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/modules.md:
--------------------------------------------------------------------------------
1 | ::: cfcrawler
2 |
--------------------------------------------------------------------------------
/cfcrawler/__init__.py:
--------------------------------------------------------------------------------
1 | from cfcrawler.client import AsyncClient
2 |
3 | __all__ = [
4 | "AsyncClient",
5 | ]
6 |
--------------------------------------------------------------------------------
/.pre-commit-config.yaml:
--------------------------------------------------------------------------------
1 | repos:
2 | - repo: https://github.com/psf/black
3 | rev: "22.8.0"
4 | hooks:
5 | - id: black
6 |
--------------------------------------------------------------------------------
/codecov.yaml:
--------------------------------------------------------------------------------
1 | coverage:
2 | range: 70..100
3 | round: down
4 | precision: 1
5 | status:
6 | project:
7 | default:
8 | target: 90%
9 | threshold: 0.5%
10 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | .PHONY: install
2 | install: ## Install the uv environment and install the pre-commit hooks
3 | @echo "🚀 Creating virtual environment using uv"
4 | @uv sync
5 |
6 | .PHONY: test
7 | test: ## Test the code with pytest
8 | @echo "🚀 Testing code: Running pytest"
9 | @uv run pytest
10 |
11 | .PHONY: check
12 | check: ## check the code with flake8
13 | @echo "🚀 Checking code with ruff and pyright"
14 | @uv run ruff check .
15 | @uv run pyright
--------------------------------------------------------------------------------
/tests/test_ciphers.py:
--------------------------------------------------------------------------------
1 | import ssl
2 |
3 | import pytest
4 |
5 | from cfcrawler.tls import get_cipher_suite
6 | from cfcrawler.types import Browser
7 |
8 |
9 | def test_valid_ciphers():
10 | for browser in Browser:
11 | cipher_suite = get_cipher_suite(browser)
12 | try:
13 | context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
14 | context.set_ciphers(cipher_suite)
15 | except ssl.SSLError:
16 | pytest.fail(f"Cipher {cipher_suite} is not supported for {browser}")
17 |
--------------------------------------------------------------------------------
/docs/index.md:
--------------------------------------------------------------------------------
1 | # cfcrawler
2 |
3 | [](https://img.shields.io/github/v/release/ManiMozaffar/cfcrawler)
4 | [](https://github.com/ManiMozaffar/cfcrawler/actions/workflows/main.yml?query=branch%3Amain)
5 | [](https://img.shields.io/github/commit-activity/m/ManiMozaffar/cfcrawler)
6 | [](https://img.shields.io/github/license/ManiMozaffar/cfcrawler)
7 |
8 | Cloudflare scraper and cralwer written in Async
9 |
--------------------------------------------------------------------------------
/tox.ini:
--------------------------------------------------------------------------------
1 | [tox]
2 | skipsdist = true
3 | envlist = py39, py310, py311
4 |
5 | [gh-actions]
6 | python =
7 | 3.9: py39
8 | 3.10: py310
9 | 3.11: py311
10 |
11 | [testenv:py39]
12 | passenv = PYTHON_VERSION
13 | allowlist_externals = uv,pytest,pyright
14 | commands =
15 | uv python pin 3.9
16 | uv run pytest
17 |
18 | [testenv:py310]
19 | passenv = PYTHON_VERSION
20 | allowlist_externals = uv,pytest,pyright
21 | commands =
22 | uv python pin 3.10
23 | uv run pytest
24 |
25 | [testenv:py311]
26 | passenv = PYTHON_VERSION
27 | allowlist_externals = uv,pytest,pyright
28 | commands =
29 | uv python pin 3.11
30 | uv run pytest
31 |
32 | [testenv:py312]
33 | passenv = PYTHON_VERSION
34 | allowlist_externals = uv,pytest,pyright
35 | commands =
36 | uv python pin 3.12
37 | uv run pytest
38 |
--------------------------------------------------------------------------------
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | name: Main
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 | pull_request:
8 | types: [opened, synchronize, reopened, ready_for_review]
9 |
10 | jobs:
11 | run-quality-assurance:
12 | runs-on: ubuntu-latest
13 | strategy:
14 | matrix:
15 | python-version: ["3.12", "3.11", "3.10", "3.9"]
16 | fail-fast: false
17 | steps:
18 | - name: Check out
19 | uses: actions/checkout@v3
20 |
21 | - name: Set up python
22 | uses: actions/setup-python@v4
23 | with:
24 | python-version: ${{ matrix.python-version }}
25 |
26 | - uses: yezz123/setup-uv@v4
27 |
28 | - name: Install dependencies
29 | run: make install
30 |
31 | - name: Run test
32 | run: make test
33 |
34 | - name: Run checks
35 | run: make check
36 |
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = "cfcrawler"
3 | version = "0.1.0"
4 | description = "Cloudflare scraper and cralwer written in Async"
5 | readme = "README.md"
6 | requires-python = ">=3.9"
7 | authors = [{ name = "Mani Mozaffar", email = "mani.mozaffar@gmail.com" }]
8 | dependencies = ["httpx>=0.20", "typing-extensions>=4.12.2"]
9 |
10 | [tool.uv]
11 | dev-dependencies = [
12 | "pytest>=8.3.2",
13 | "ruff>=0.6.3",
14 | "pyright==1.1.353",
15 | "fake-useragent>=1.5.1",
16 | "pytest-asyncio<0.24",
17 | "tox>=4.18.0",
18 | "tox-gh-actions>=3.2.0",
19 | "tox-uv>=1.11.2",
20 | ]
21 |
22 |
23 | [project.optional-dependencies]
24 | ua = ["fake-useragent>=1.5.1"]
25 |
26 | [tool.pyright]
27 | typeCheckingMode = "standard"
28 |
29 | [tool.pytest.ini_options]
30 | addopts = "--tb=short --show-capture stdout"
31 |
32 | [tool.setuptools.package-data]
33 | "aioclock" = ["py.typed"]
34 |
--------------------------------------------------------------------------------
/.github/workflows/on-release-main.yml:
--------------------------------------------------------------------------------
1 | name: release-main
2 |
3 | on:
4 | release:
5 | types: [published]
6 | branches: [main]
7 |
8 | jobs:
9 | publish:
10 | runs-on: ubuntu-latest
11 | steps:
12 | - name: Check out
13 | uses: actions/checkout@v3
14 |
15 | - name: Export tag
16 | id: vars
17 | run: echo tag=${GITHUB_REF#refs/*/} >> $GITHUB_OUTPUT
18 |
19 | - name: Set up python
20 | uses: actions/setup-python@v4
21 | with:
22 | python-version: ${{ matrix.python-version }}
23 |
24 | - name: Install the latest version of rye
25 | uses: eifinger/setup-rye@v4
26 |
27 | - name: Build and publish
28 | run: |
29 | rye sync
30 | rye build
31 | rye publish --token $PYPI_TOKEN --yes
32 | env:
33 | PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }}
34 | RELEASE_VERSION: ${{ steps.vars.outputs.tag }}
35 |
--------------------------------------------------------------------------------
/tests/test_rotation.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 | from cfcrawler.client import AsyncClient
4 | from cfcrawler.types import Browser
5 |
6 |
7 | @pytest.mark.asyncio
8 | async def test_factory_works():
9 | ua_pool = ["Mozilla/5.0", "Mozilla/6.0"]
10 | client = AsyncClient(
11 | browser=Browser.CHROME, user_agent_factory=lambda: ua_pool.pop()
12 | )
13 | assert client.headers["User-Agent"] == "Mozilla/6.0"
14 | client.rotate_useragent()
15 | assert client.headers["User-Agent"] == "Mozilla/5.0"
16 |
17 |
18 | @pytest.mark.asyncio
19 | async def test_rotate_works_with_fake_lib():
20 | # This test is a bit flaky, but it's good enough for now.
21 | client = AsyncClient(browser=Browser.CHROME, use_fake_useragent_library=True)
22 | user_agents: set[str] = set()
23 | for _ in range(10):
24 | user_agent_one = client.headers["User-Agent"]
25 | client.rotate_useragent()
26 | user_agents.add(user_agent_one)
27 |
28 | assert len(user_agents) > 1 # might have repeated user agents
29 |
--------------------------------------------------------------------------------
/tests/test_detect.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from httpx import AsyncClient as DetectedClient
3 |
4 | from cfcrawler.client import AsyncClient
5 | from cfcrawler.types import Browser
6 |
7 |
8 | @pytest.mark.asyncio
9 | async def test_patched_async_client():
10 | client = AsyncClient(browser=Browser.CHROME)
11 | resp = await client.get("https://www.futbin.com/")
12 | assert resp.status_code == 200
13 | assert "__cf_bm" in resp.cookies.keys()
14 |
15 | client = AsyncClient(browser=Browser.FIREFOX)
16 | resp = await client.get("https://www.futbin.com/")
17 | assert resp.status_code == 200
18 | assert "__cf_bm" in resp.cookies.keys()
19 |
20 | client = AsyncClient(browser=Browser.FIREFOX, use_fake_useragent_library=True)
21 | resp = await client.get("https://www.futbin.com/")
22 | assert resp.status_code == 200
23 | assert "__cf_bm" in resp.cookies.keys()
24 |
25 |
26 | @pytest.mark.asyncio
27 | async def test_of_assumption_tht_target_is_still_protected():
28 | client = DetectedClient()
29 | resp = await client.get("https://www.futbin.com/")
30 | assert resp.status_code != 200
31 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023, Mani Mozaffar
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 |
23 |
--------------------------------------------------------------------------------
/mkdocs.yml:
--------------------------------------------------------------------------------
1 | site_name: cfcrawler
2 | repo_url: https://github.com/ManiMozaffar/cfcrawler
3 | site_url: https://ManiMozaffar.github.io/cfcrawler
4 | site_description: Cloudflare scraper and cralwer written in Async
5 | site_author: Mani Mozaffar
6 | edit_uri: edit/main/docs/
7 | repo_name: ManiMozaffar/cfcrawler
8 | copyright: Maintained by Florian.
9 |
10 | nav:
11 | - Home: index.md
12 | - Modules: modules.md
13 | plugins:
14 | - search
15 | - mkdocstrings:
16 | handlers:
17 | python:
18 | setup_commands:
19 | - import sys
20 | - sys.path.append('../')
21 | theme:
22 | name: material
23 | feature:
24 | tabs: true
25 | palette:
26 | - media: "(prefers-color-scheme: light)"
27 | scheme: default
28 | primary: white
29 | accent: deep orange
30 | toggle:
31 | icon: material/brightness-7
32 | name: Switch to dark mode
33 | - media: "(prefers-color-scheme: dark)"
34 | scheme: slate
35 | primary: black
36 | accent: deep orange
37 | toggle:
38 | icon: material/brightness-4
39 | name: Switch to light mode
40 | icon:
41 | repo: fontawesome/brands/github
42 |
43 | extra:
44 | social:
45 | - icon: fontawesome/brands/github
46 | link: https://github.com/ManiMozaffar/cfcrawler
47 | - icon: fontawesome/brands/python
48 | link: https://pypi.org/project/cfcrawler
49 |
50 | markdown_extensions:
51 | - toc:
52 | permalink: true
53 | - pymdownx.arithmatex:
54 | generic: true
55 |
--------------------------------------------------------------------------------
/cfcrawler/user_agent.py:
--------------------------------------------------------------------------------
1 | from functools import lru_cache
2 |
3 | from typing_extensions import assert_never
4 |
5 | from cfcrawler.types import Browser
6 |
7 |
8 | @lru_cache
9 | def get_operating_systems() -> list[str]:
10 | operating_systems = [
11 | "Windows NT 10.0; Win64; x64",
12 | "Windows NT 10.0; WOW64",
13 | "Windows NT 6.1; Win64; x64",
14 | "Macintosh; Intel Mac OS X 12.4",
15 | "Macintosh; Intel Mac OS X 10.15",
16 | "X11; Ubuntu; Linux x86_64",
17 | "X11; Fedora; Linux x86_64",
18 | ]
19 | return operating_systems
20 |
21 |
22 | def get_all_chrome_ua() -> list[str]:
23 | operating_systems = get_operating_systems()
24 | chrome_versions = [
25 | "115.0.5790.102",
26 | "114.0.5735.198",
27 | "113.0.5672.126",
28 | "112.0.5615.137",
29 | "111.0.5563.110",
30 | ]
31 | return [
32 | f"Mozilla/5.0 ({os}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/{version} Safari/537.36"
33 | for os in operating_systems
34 | for version in chrome_versions
35 | ]
36 |
37 |
38 | def get_all_fireox_ua() -> list[str]:
39 | operating_systems = get_operating_systems()
40 | firefox_versions = ["115.0", "114.0", "113.0", "112.0", "111.0", "110.0", "109.0"]
41 | return [
42 | f"Mozilla/5.0 ({os}) Gecko/20100101 Firefox/{version}"
43 | for os in operating_systems
44 | for version in firefox_versions
45 | ]
46 |
47 |
48 | def get_all_ua_for_specific_browser(browser: Browser) -> list[str]:
49 | if browser == Browser.CHROME:
50 | return get_all_chrome_ua()
51 | elif browser == Browser.FIREFOX:
52 | return get_all_fireox_ua()
53 | else:
54 | assert_never(browser)
55 |
--------------------------------------------------------------------------------
/cfcrawler/types.py:
--------------------------------------------------------------------------------
1 | from enum import Enum, auto
2 |
3 | from typing_extensions import DefaultDict
4 |
5 |
6 | class StrEnum(str, Enum):
7 | """
8 | Enum where members are also (and must be) strings
9 | """
10 |
11 | def __new__(cls, *values):
12 | "values must already be of type `str`"
13 | if len(values) > 3:
14 | raise TypeError("too many arguments for str(): %r" % (values,))
15 | if len(values) == 1:
16 | # it must be a string
17 | if not isinstance(values[0], str):
18 | raise TypeError("%r is not a string" % (values[0],))
19 | if len(values) >= 2:
20 | # check that encoding argument is a string
21 | if not isinstance(values[1], str): # type: ignore
22 | raise TypeError("encoding must be a string, not %r" % (values[1],)) # type: ignore
23 | if len(values) == 3:
24 | # check that errors argument is a string
25 | if not isinstance(values[2], str):
26 | raise TypeError("errors must be a string, not %r" % (values[2]))
27 | value = str(*values)
28 | member = str.__new__(cls, value)
29 | member._value_ = value
30 | return member
31 |
32 | def _generate_next_value_(name, start, count, last_values): # type: ignore
33 | """
34 | Return the lower-cased version of the member name.
35 | """
36 | return name.lower()
37 |
38 |
39 | class ChallengeStatus(StrEnum):
40 | PASSED = auto() # dummy value representing a successful attempt
41 | H_CAPTCHA_V1 = auto()
42 | H_CAPTCHA_V2 = auto()
43 | RECAPTCHA = auto()
44 | IUAM_V1 = auto()
45 | IUAM_V2 = auto()
46 | FIREWALL_BLOCKED = auto()
47 |
48 | UNKNOWN = auto()
49 |
50 |
51 | class CaptchaTypes(StrEnum):
52 | RE_CAPTCHA = auto()
53 | H_CAPTCHA = auto()
54 |
55 |
56 | class ChallengeForm(DefaultDict):
57 | form: str
58 | challengeUUID: str
59 |
60 |
61 | class CaptchaResult(DefaultDict):
62 | url: str
63 | data: dict
64 |
65 |
66 | class Browser(StrEnum):
67 | CHROME = auto()
68 | FIREFOX = auto()
69 |
--------------------------------------------------------------------------------
/cfcrawler/tls.py:
--------------------------------------------------------------------------------
1 | import ssl
2 | import typing
3 | from functools import lru_cache
4 |
5 | import typing_extensions as te
6 | from httpcore import AsyncConnectionPool, AsyncHTTPProxy, AsyncSOCKSProxy
7 |
8 | from cfcrawler.types import Browser
9 |
10 |
11 | def mimic_tls_fingerprint_from_browser(
12 | pool: typing.Union[AsyncConnectionPool, AsyncHTTPProxy, AsyncSOCKSProxy],
13 | browser: Browser,
14 | ecdh_curve: typing.Optional[str] = None,
15 | cipher_suite: typing.Optional[str] = None,
16 | ):
17 | if pool._ssl_context is None:
18 | pool._ssl_context = ssl.create_default_context()
19 |
20 | ecdh_curve = ecdh_curve or "secp384r1"
21 | cipher_suite = cipher_suite or get_cipher_suite(browser)
22 | pool._ssl_context.set_ecdh_curve(ecdh_curve)
23 | pool._ssl_context.set_ciphers(cipher_suite)
24 | pool._ssl_context.check_hostname = False
25 |
26 | pool._ssl_context.minimum_version = ssl.TLSVersion.TLSv1_2
27 | pool._ssl_context.maximum_version = ssl.TLSVersion.TLSv1_3
28 | pool._ssl_context = pool._ssl_context
29 |
30 |
31 | @lru_cache
32 | def get_cipher_suite(browser: Browser) -> str:
33 | if browser == Browser.CHROME:
34 | cipher_suites = [
35 | "TLS_AES_128_GCM_SHA256",
36 | "TLS_CHACHA20_POLY1305_SHA256",
37 | "TLS_AES_256_GCM_SHA384",
38 | "ECDHE-ECDSA-AES128-GCM-SHA256",
39 | "ECDHE-RSA-AES128-GCM-SHA256",
40 | "ECDHE-ECDSA-CHACHA20-POLY1305",
41 | "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
42 | "ECDHE-RSA-CHACHA20-POLY1305",
43 | "ECDHE-RSA-AES256-GCM-SHA384",
44 | "ECDHE-ECDSA-AES256-SHA",
45 | "ECDHE-ECDSA-AES128-SHA",
46 | "ECDHE-RSA-AES128-SHA",
47 | "ECDHE-RSA-AES256-SHA",
48 | "AES128-GCM-SHA256",
49 | "AES256-GCM-SHA384",
50 | "AES128-SHA",
51 | "AES256-SHA",
52 | ]
53 | elif browser == Browser.FIREFOX:
54 | cipher_suites = [
55 | "TLS_AES_128_GCM_SHA256",
56 | "TLS_CHACHA20_POLY1305_SHA256",
57 | "TLS_AES_256_GCM_SHA384",
58 | "ECDHE-ECDSA-AES128-GCM-SHA256",
59 | "ECDHE-RSA-AES128-GCM-SHA256",
60 | "ECDHE-ECDSA-CHACHA20-POLY1305",
61 | "ECDHE-RSA-CHACHA20-POLY1305",
62 | "ECDHE-ECDSA-AES256-GCM-SHA384",
63 | "ECDHE-RSA-AES256-GCM-SHA384",
64 | "ECDHE-ECDSA-AES256-SHA",
65 | "ECDHE-ECDSA-AES128-SHA",
66 | "ECDHE-RSA-AES128-SHA",
67 | "ECDHE-RSA-AES256-SHA",
68 | "AES128-GCM-SHA256",
69 | "AES256-GCM-SHA384",
70 | "AES128-SHA",
71 | "AES256-SHA",
72 | ]
73 | else:
74 | te.assert_never(browser)
75 | return ":".join(cipher_suites)
76 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | docs/source
2 |
3 | # From https://raw.githubusercontent.com/github/gitignore/main/Python.gitignore
4 |
5 | # Byte-compiled / optimized / DLL files
6 | __pycache__/
7 | *.py[cod]
8 | *$py.class
9 |
10 | # C extensions
11 | *.so
12 |
13 | # Distribution / packaging
14 | .python-version
15 | .DS_Store
16 | .Python
17 | build/
18 | develop-eggs/
19 | dist/
20 | downloads/
21 | eggs/
22 | .eggs/
23 | lib/
24 | lib64/
25 | parts/
26 | sdist/
27 | var/
28 | wheels/
29 | share/python-wheels/
30 | *.egg-info/
31 | .installed.cfg
32 | *.egg
33 | MANIFEST
34 |
35 | # PyInstaller
36 | # Usually these files are written by a python script from a template
37 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
38 | *.manifest
39 | *.spec
40 |
41 | # Installer logs
42 | pip-log.txt
43 | pip-delete-this-directory.txt
44 |
45 | # Unit test / coverage reports
46 | htmlcov/
47 | .tox/
48 | .nox/
49 | .coverage
50 | .coverage.*
51 | .cache
52 | nosetests.xml
53 | coverage.xml
54 | *.cover
55 | *.py,cover
56 | .hypothesis/
57 | .pytest_cache/
58 | cover/
59 |
60 | # Translations
61 | *.mo
62 | *.pot
63 |
64 | # Django stuff:
65 | *.log
66 | local_settings.py
67 | db.sqlite3
68 | db.sqlite3-journal
69 |
70 | # Flask stuff:
71 | instance/
72 | .webassets-cache
73 |
74 | # Scrapy stuff:
75 | .scrapy
76 |
77 | # Sphinx documentation
78 | docs/_build/
79 |
80 | # PyBuilder
81 | .pybuilder/
82 | target/
83 |
84 | # Jupyter Notebook
85 | .ipynb_checkpoints
86 |
87 | # IPython
88 | profile_default/
89 | ipython_config.py
90 |
91 | # pyenv
92 | # For a library or package, you might want to ignore these files since the code is
93 | # intended to run in multiple environments; otherwise, check them in:
94 | # .python-version
95 |
96 | # pipenv
97 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
98 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
99 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
100 | # install all needed dependencies.
101 | #Pipfile.lock
102 |
103 | # poetry
104 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
105 | # This is especially recommended for binary packages to ensure reproducibility, and is more
106 | # commonly ignored for libraries.
107 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
108 | #poetry.lock
109 |
110 | # pdm
111 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
112 | #pdm.lock
113 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
114 | # in version control.
115 | # https://pdm.fming.dev/#use-with-ide
116 | .pdm.toml
117 |
118 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
119 | __pypackages__/
120 |
121 | # Celery stuff
122 | celerybeat-schedule
123 | celerybeat.pid
124 |
125 | # SageMath parsed files
126 | *.sage.py
127 |
128 | # Environments
129 | .env
130 | .venv
131 | env/
132 | venv/
133 | ENV/
134 | env.bak/
135 | venv.bak/
136 |
137 | # Spyder project settings
138 | .spyderproject
139 | .spyproject
140 |
141 | # Rope project settings
142 | .ropeproject
143 |
144 | # mkdocs documentation
145 | /site
146 |
147 | # mypy
148 | .mypy_cache/
149 | .dmypy.json
150 | dmypy.json
151 |
152 | # Pyre type checker
153 | .pyre/
154 |
155 | # pytype static type analyzer
156 | .pytype/
157 |
158 | # Cython debug symbols
159 | cython_debug/
160 |
161 | # Vscode config files
162 | .vscode/
163 |
164 | # PyCharm
165 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
166 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
167 | # and can be added to the global gitignore or merged into this file. For a more nuclear
168 | # option (not recommended) you can uncomment the following to ignore the entire idea folder.
169 | #.idea/
170 |
--------------------------------------------------------------------------------
/CONTRIBUTING.rst:
--------------------------------------------------------------------------------
1 | ============
2 | Contributing
3 | ============
4 |
5 | Contributions are welcome, and they are greatly appreciated! Every little bit
6 | helps, and credit will always be given.
7 |
8 | You can contribute in many ways:
9 |
10 | Types of Contributions
11 | ----------------------
12 |
13 | Report Bugs
14 | ~~~~~~~~~~~
15 |
16 | Report bugs at https://github.com/ManiMozaffar/cfcrawler/issues
17 |
18 | If you are reporting a bug, please include:
19 |
20 | * Your operating system name and version.
21 | * Any details about your local setup that might be helpful in troubleshooting.
22 | * Detailed steps to reproduce the bug.
23 |
24 | Fix Bugs
25 | ~~~~~~~~
26 |
27 | Look through the GitHub issues for bugs. Anything tagged with "bug"
28 | and "help wanted" is open to whoever wants to implement a fix for it.
29 |
30 | Implement Features
31 | ~~~~~~~~~~~~~~~~~~
32 |
33 | Look through the GitHub issues for features. Anything tagged with "enhancement"
34 | and "help wanted" is open to whoever wants to implement it.
35 |
36 | Write Documentation
37 | ~~~~~~~~~~~~~~~~~~~
38 |
39 | Cookiecutter PyPackage could always use more documentation, whether as part of
40 | the official docs, in docstrings, or even on the web in blog posts, articles,
41 | and such.
42 |
43 | Submit Feedback
44 | ~~~~~~~~~~~~~~~
45 |
46 | The best way to send feedback is to file an issue at
47 | https://github.com/ManiMozaffar/cfcrawler/issues.
48 |
49 | If you are proposing a new feature:
50 |
51 | * Explain in detail how it would work.
52 | * Keep the scope as narrow as possible, to make it easier to implement.
53 | * Remember that this is a volunteer-driven project, and that contributions
54 | are welcome :)
55 |
56 | Get Started!
57 | ------------
58 |
59 | Ready to contribute? Here's how to set up `cfcrawler` for local
60 | development. Please note this documentation assumes you already have
61 | `poetry` and `Git` installed and ready to go.
62 |
63 | | 1. Fork the `cfcrawler` repo on GitHub.
64 |
65 | | 2. Clone your fork locally:
66 |
67 | .. code-block:: bash
68 |
69 | cd
70 | git clone git@github.com:YOUR_NAME/cfcrawler.git
71 |
72 |
73 | | 3. Now we need to install the environment. Navigate into the directory
74 |
75 | .. code-block:: bash
76 |
77 | cd cfcrawler
78 |
79 | If you are using ``pyenv``, select a version to use locally. (See installed versions with ``pyenv versions``)
80 |
81 | .. code-block:: bash
82 |
83 | pyenv local
84 |
85 | Then, install and activate the environment with:
86 |
87 | .. code-block:: bash
88 |
89 | poetry install
90 | poetry shell
91 |
92 | | 4. Install pre-commit to run linters/formatters at commit time:
93 |
94 | .. code-block:: bash
95 |
96 | poetry run pre-commit install
97 |
98 | | 5. Create a branch for local development:
99 |
100 | .. code-block:: bash
101 |
102 | git checkout -b name-of-your-bugfix-or-feature
103 |
104 | Now you can make your changes locally.
105 |
106 |
107 | | 6. Don't forget to add test cases for your added functionality to the ``tests`` directory.
108 |
109 | | 7. When you're done making changes, check that your changes pass the formatting tests.
110 |
111 | .. code-block:: bash
112 |
113 | make check
114 |
115 | | 8. Now, validate that all unit tests are passing:
116 |
117 | .. code-block:: bash
118 |
119 | make test
120 |
121 | | 9. Before raising a pull request you should also run tox. This will run the
122 | tests across different versions of Python:
123 |
124 | .. code-block:: bash
125 |
126 | tox
127 |
128 | This requires you to have multiple versions of python installed.
129 | This step is also triggered in the CI/CD pipeline, so you could also choose to skip this
130 | step locally.
131 |
132 | | 10. Commit your changes and push your branch to GitHub:
133 |
134 | .. code-block:: bash
135 |
136 | git add .
137 | git commit -m "Your detailed description of your changes."
138 | git push origin name-of-your-bugfix-or-feature
139 |
140 | | 11. Submit a pull request through the GitHub website.
141 |
142 | Pull Request Guidelines
143 | ---------------------------
144 |
145 | Before you submit a pull request, check that it meets these guidelines:
146 |
147 | 1. The pull request should include tests.
148 |
149 | 2. If the pull request adds functionality, the docs should be updated. Put your
150 | new functionality into a function with a docstring, and add the feature to
151 | the list in README.rst.
152 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # cfcrawler
2 |
3 | [](https://img.shields.io/github/v/release/ManiMozaffar/cfcrawler)
4 | [](https://github.com/ManiMozaffar/cfcrawler/actions/workflows/main.yml?query=branch%3Amain)
5 | [](https://codecov.io/gh/ManiMozaffar/cfcrawler)
6 | [](https://img.shields.io/github/commit-activity/m/ManiMozaffar/cfcrawler)
7 | [](https://img.shields.io/github/license/ManiMozaffar/cfcrawler)
8 |
9 | Cloudflare scraper and cralwer written in Async, In-place library for HTTPX. Crawl website that has cloudflare enabled, easier than ever!
10 |
11 | This library is a HTTP client designed to crawl websites protected by Cloudflare, even when their bot detection system is active. If you're already using httpx, you can switch to this library easily since it's a drop-in replacement. Just change the import, and you're good to go.
12 |
13 | - **Github repository**:
14 |
15 | ## Installation
16 |
17 | To install base package, you can do:
18 |
19 | ```bash
20 | pip install cfcrawler
21 | ```
22 |
23 | To install `fake-useragent` backend support to rotate user agents, you can do:
24 |
25 | ```bash
26 | pip install "cfcrawler[ua]"
27 | ```
28 |
29 | ## Getting started
30 |
31 | To use library, simply replace your aiohttp client with ours! It's completely in-place :)
32 |
33 | ```python
34 | from cfcrawler import AsyncClient
35 |
36 | async def get(url):
37 | client = AsyncClient()
38 | await client.get(url)
39 |
40 | ```
41 |
42 | By default, we're using one random user agent, which is still undetected in tests.
43 | To rotate user agent, you need to explicitly call `rotate_useragent` method.
44 | By default, we have a pool of few user agents, But you can also install extra optional dependencies to have a big pool of user agents to rotate between them.
45 |
46 | ```python
47 | from cfcrawler import AsyncClient
48 |
49 | client = AsyncClient(use_fake_useragent_library=True) # one random user agent is selected
50 | # do something
51 | client.rotate_useragent() # user agent is rotated
52 | # do something
53 | client.rotate_useragent() # user agent is rotated again
54 | # do something
55 | ```
56 |
57 | You can also specify which browser you want to use
58 |
59 | ```python
60 | from cfcrawler.types import Browser
61 | from cfcrawler import AsyncClient
62 |
63 | AsyncClient(browser=Browser.CHROME)
64 | ```
65 |
66 | If you wish to have your own user agent pool, you can pass the factory callable to the client
67 |
68 | ```python
69 | from cfcrawler import AsyncClient
70 |
71 | def my_useragent_factory():
72 | return "My User Agent" # your implementation
73 |
74 | client = AsyncClient(user_agent_factory=my_useragent_factory)
75 | ```
76 |
77 | You can also use asyncer to syncify the implementation
78 |
79 | ```python
80 | from cfcrawler import AsyncClient
81 | from asyncer import syncify
82 |
83 | def get(url):
84 | client = AsyncClient()
85 | syncify(client.get)(url)
86 | ```
87 |
88 | ## How this library works
89 |
90 | ### The Problem
91 |
92 | Websites using Cloudflare often rely on a bot detection mechanism that works by checking your TLS Fingerprint. So, what's a TLS Fingerprint? When you connect to a website that uses HTTPS, the first thing that happens is the exchange of a "Client Hello" message. This message tells the server some basic info about your client, like the TLS version you support and a list of cipher suites, and etc.
93 |
94 | ### What's a Cipher Suite?
95 |
96 | A cipher suite is a set of cryptographic algorithms that the client and server use to establish a secure connection. Each browser or client has its own specific list of cipher suites, and their order is unique. For instance, Chrome has its own list, Firefox has another, and Python's requests library has a completely different one.
97 |
98 | ### The Detection
99 |
100 | Cloudflare figures out if you're not a real browser by comparing your TLS Fingerprint—which is a combination of the TLS version and cipher suite order—with your user-agent. If there's a mismatch, like if your user-agent says you're Chrome but your cipher suites suggest you're a Python script, Cloudflare knows you're not a browser and blocks the request.
101 |
102 | ### How My Library Helps
103 |
104 | This library handles that problem by aligning your TLS Fingerprint with your user-agent, making it harder for Cloudflare to detect that you're not a real browser. The best part? It's just 10 lines of code! In source code, checkout `cfcrawler/tls.py` to see how it works.
105 |
106 | ## Coming Next
107 |
108 | 1. CF JS Challenge solver
109 | 2. Captcha solver integration (2Captcha and etc)
110 |
--------------------------------------------------------------------------------
/cfcrawler/client.py:
--------------------------------------------------------------------------------
1 | import random
2 | import typing
3 | from functools import lru_cache
4 |
5 | from httpx import AsyncHTTPTransport, _types
6 | from httpx._client import AsyncClient as _AsyncClient
7 | from httpx._config import (
8 | DEFAULT_LIMITS,
9 | DEFAULT_MAX_REDIRECTS,
10 | DEFAULT_TIMEOUT_CONFIG,
11 | Limits,
12 | )
13 | from httpx._transports.base import AsyncBaseTransport
14 | from typing_extensions import assert_never
15 |
16 | from cfcrawler.tls import mimic_tls_fingerprint_from_browser
17 | from cfcrawler.types import Browser
18 | from cfcrawler.user_agent import get_all_ua_for_specific_browser
19 |
20 |
21 | @lru_cache
22 | def get_fake_ua_factory(browser: Browser):
23 | try:
24 | from fake_useragent import UserAgent
25 | except ImportError:
26 | raise ImportError(
27 | "You need to install fake-useragent library to use this feature."
28 | "Please run `pip install cfcrawler[ua]`"
29 | )
30 |
31 | if browser == Browser.CHROME:
32 | browsers = ["chrome"]
33 | elif browser == Browser.FIREFOX:
34 | browsers = ["firefox"]
35 | else:
36 | assert_never(browser)
37 |
38 | ua = UserAgent(browsers=browsers)
39 | return ua
40 |
41 |
42 | class AsyncClient(_AsyncClient):
43 | def __init__(
44 | self,
45 | *,
46 | browser: typing.Optional[Browser] = None,
47 | default_user_agent: typing.Optional[str] = None,
48 | cipher_suite: typing.Optional[str] = None,
49 | ecdh_curve: typing.Optional[str] = None,
50 | user_agent_factory: typing.Optional[typing.Callable[[], str]] = None,
51 | use_fake_useragent_library: bool = False,
52 | transport: typing.Optional[AsyncHTTPTransport] = None,
53 | auth: typing.Optional[_types.AuthTypes] = None,
54 | params: typing.Optional[_types.QueryParamTypes] = None,
55 | headers: typing.Optional[_types.HeaderTypes] = None,
56 | cookies: typing.Optional[_types.CookieTypes] = None,
57 | verify: _types.VerifyTypes = False,
58 | cert: typing.Optional[_types.CertTypes] = None,
59 | http1: bool = True,
60 | http2: bool = False,
61 | proxies: typing.Optional[_types.ProxiesTypes] = None,
62 | mounts: typing.Optional[typing.Mapping[str, AsyncBaseTransport]] = None,
63 | timeout: _types.TimeoutTypes = DEFAULT_TIMEOUT_CONFIG,
64 | follow_redirects: bool = False,
65 | limits: Limits = DEFAULT_LIMITS,
66 | max_redirects: int = DEFAULT_MAX_REDIRECTS,
67 | event_hooks: typing.Optional[
68 | typing.Mapping[str, typing.List[typing.Callable[..., typing.Any]]]
69 | ] = None,
70 | base_url: _types.URLTypes = "",
71 | app: typing.Optional[typing.Callable[..., typing.Any]] = None,
72 | trust_env: bool = True,
73 | default_encoding: typing.Union[str, typing.Callable[[bytes], str]] = "utf-8",
74 | ):
75 | self.browser: Browser = browser or random.choice(
76 | [Browser.CHROME, Browser.FIREFOX]
77 | )
78 | self.user_agent_factory = user_agent_factory
79 | self.use_fake_useragent_library = use_fake_useragent_library
80 | self.default_user_agent = default_user_agent
81 | self._custom_transport = transport or AsyncHTTPTransport()
82 | self.ecdh_curve = ecdh_curve
83 | self.cipher_suite = cipher_suite
84 |
85 | super().__init__(
86 | auth=auth,
87 | params=params,
88 | headers=headers or {},
89 | cookies=cookies,
90 | timeout=timeout,
91 | follow_redirects=follow_redirects,
92 | max_redirects=max_redirects,
93 | event_hooks=event_hooks,
94 | base_url=base_url,
95 | verify=verify,
96 | cert=cert,
97 | http2=http2,
98 | transport=self._custom_transport,
99 | app=app,
100 | http1=http1,
101 | proxies=proxies,
102 | limits=limits,
103 | trust_env=trust_env,
104 | default_encoding=default_encoding,
105 | mounts=mounts,
106 | )
107 | self.rotate_useragent()
108 |
109 | def rotate_useragent(self):
110 | self.headers.update({"User-Agent": self.get_random_user_agent()})
111 | mimic_tls_fingerprint_from_browser(
112 | pool=self._custom_transport._pool,
113 | browser=self.browser,
114 | ecdh_curve=self.ecdh_curve,
115 | cipher_suite=self.cipher_suite,
116 | )
117 |
118 | def get_random_user_agent(self) -> str:
119 | if self.default_user_agent:
120 | return self.default_user_agent
121 | elif self.user_agent_factory:
122 | return self.user_agent_factory()
123 | elif self.use_fake_useragent_library:
124 | ua = get_fake_ua_factory(self.browser)
125 | return typing.cast(str, ua.random)
126 | else:
127 | return random.choice(get_all_ua_for_specific_browser(self.browser))
128 |
--------------------------------------------------------------------------------
/uv.lock:
--------------------------------------------------------------------------------
1 | version = 1
2 | requires-python = ">=3.9"
3 |
4 | [[package]]
5 | name = "anyio"
6 | version = "4.4.0"
7 | source = { registry = "https://pypi.org/simple" }
8 | dependencies = [
9 | { name = "exceptiongroup", marker = "python_full_version < '3.11'" },
10 | { name = "idna" },
11 | { name = "sniffio" },
12 | { name = "typing-extensions", marker = "python_full_version < '3.11'" },
13 | ]
14 | sdist = { url = "https://files.pythonhosted.org/packages/e6/e3/c4c8d473d6780ef1853d630d581f70d655b4f8d7553c6997958c283039a2/anyio-4.4.0.tar.gz", hash = "sha256:5aadc6a1bbb7cdb0bede386cac5e2940f5e2ff3aa20277e991cf028e0585ce94", size = 163930 }
15 | wheels = [
16 | { url = "https://files.pythonhosted.org/packages/7b/a2/10639a79341f6c019dedc95bd48a4928eed9f1d1197f4c04f546fc7ae0ff/anyio-4.4.0-py3-none-any.whl", hash = "sha256:c1b2d8f46a8a812513012e1107cb0e68c17159a7a594208005a57dc776e1bdc7", size = 86780 },
17 | ]
18 |
19 | [[package]]
20 | name = "cachetools"
21 | version = "5.5.0"
22 | source = { registry = "https://pypi.org/simple" }
23 | sdist = { url = "https://files.pythonhosted.org/packages/c3/38/a0f315319737ecf45b4319a8cd1f3a908e29d9277b46942263292115eee7/cachetools-5.5.0.tar.gz", hash = "sha256:2cc24fb4cbe39633fb7badd9db9ca6295d766d9c2995f245725a46715d050f2a", size = 27661 }
24 | wheels = [
25 | { url = "https://files.pythonhosted.org/packages/a4/07/14f8ad37f2d12a5ce41206c21820d8cb6561b728e51fad4530dff0552a67/cachetools-5.5.0-py3-none-any.whl", hash = "sha256:02134e8439cdc2ffb62023ce1debca2944c3f289d66bb17ead3ab3dede74b292", size = 9524 },
26 | ]
27 |
28 | [[package]]
29 | name = "certifi"
30 | version = "2024.8.30"
31 | source = { registry = "https://pypi.org/simple" }
32 | sdist = { url = "https://files.pythonhosted.org/packages/b0/ee/9b19140fe824b367c04c5e1b369942dd754c4c5462d5674002f75c4dedc1/certifi-2024.8.30.tar.gz", hash = "sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9", size = 168507 }
33 | wheels = [
34 | { url = "https://files.pythonhosted.org/packages/12/90/3c9ff0512038035f59d279fddeb79f5f1eccd8859f06d6163c58798b9487/certifi-2024.8.30-py3-none-any.whl", hash = "sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8", size = 167321 },
35 | ]
36 |
37 | [[package]]
38 | name = "cfcrawler"
39 | version = "0.1.0"
40 | source = { virtual = "." }
41 | dependencies = [
42 | { name = "httpx" },
43 | { name = "typing-extensions" },
44 | ]
45 |
46 | [package.optional-dependencies]
47 | ua = [
48 | { name = "fake-useragent" },
49 | ]
50 |
51 | [package.dev-dependencies]
52 | dev = [
53 | { name = "fake-useragent" },
54 | { name = "pyright" },
55 | { name = "pytest" },
56 | { name = "pytest-asyncio" },
57 | { name = "ruff" },
58 | { name = "tox" },
59 | { name = "tox-gh-actions" },
60 | { name = "tox-uv" },
61 | ]
62 |
63 | [package.metadata]
64 | requires-dist = [
65 | { name = "fake-useragent", marker = "extra == 'ua'", specifier = ">=1.5.1" },
66 | { name = "httpx", specifier = ">=0.20" },
67 | { name = "typing-extensions", specifier = ">=4.12.2" },
68 | ]
69 |
70 | [package.metadata.requires-dev]
71 | dev = [
72 | { name = "fake-useragent", specifier = ">=1.5.1" },
73 | { name = "pyright", specifier = "==1.1.353" },
74 | { name = "pytest", specifier = ">=8.3.2" },
75 | { name = "pytest-asyncio", specifier = "<0.24" },
76 | { name = "ruff", specifier = ">=0.6.3" },
77 | { name = "tox", specifier = ">=4.18.0" },
78 | { name = "tox-gh-actions", specifier = ">=3.2.0" },
79 | { name = "tox-uv", specifier = ">=1.11.2" },
80 | ]
81 |
82 | [[package]]
83 | name = "chardet"
84 | version = "5.2.0"
85 | source = { registry = "https://pypi.org/simple" }
86 | sdist = { url = "https://files.pythonhosted.org/packages/f3/0d/f7b6ab21ec75897ed80c17d79b15951a719226b9fababf1e40ea74d69079/chardet-5.2.0.tar.gz", hash = "sha256:1b3b6ff479a8c414bc3fa2c0852995695c4a026dcd6d0633b2dd092ca39c1cf7", size = 2069618 }
87 | wheels = [
88 | { url = "https://files.pythonhosted.org/packages/38/6f/f5fbc992a329ee4e0f288c1fe0e2ad9485ed064cac731ed2fe47dcc38cbf/chardet-5.2.0-py3-none-any.whl", hash = "sha256:e1cf59446890a00105fe7b7912492ea04b6e6f06d4b742b2c788469e34c82970", size = 199385 },
89 | ]
90 |
91 | [[package]]
92 | name = "colorama"
93 | version = "0.4.6"
94 | source = { registry = "https://pypi.org/simple" }
95 | sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697 }
96 | wheels = [
97 | { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 },
98 | ]
99 |
100 | [[package]]
101 | name = "distlib"
102 | version = "0.3.8"
103 | source = { registry = "https://pypi.org/simple" }
104 | sdist = { url = "https://files.pythonhosted.org/packages/c4/91/e2df406fb4efacdf46871c25cde65d3c6ee5e173b7e5a4547a47bae91920/distlib-0.3.8.tar.gz", hash = "sha256:1530ea13e350031b6312d8580ddb6b27a104275a31106523b8f123787f494f64", size = 609931 }
105 | wheels = [
106 | { url = "https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl", hash = "sha256:034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784", size = 468850 },
107 | ]
108 |
109 | [[package]]
110 | name = "exceptiongroup"
111 | version = "1.2.2"
112 | source = { registry = "https://pypi.org/simple" }
113 | sdist = { url = "https://files.pythonhosted.org/packages/09/35/2495c4ac46b980e4ca1f6ad6db102322ef3ad2410b79fdde159a4b0f3b92/exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc", size = 28883 }
114 | wheels = [
115 | { url = "https://files.pythonhosted.org/packages/02/cc/b7e31358aac6ed1ef2bb790a9746ac2c69bcb3c8588b41616914eb106eaf/exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b", size = 16453 },
116 | ]
117 |
118 | [[package]]
119 | name = "fake-useragent"
120 | version = "1.5.1"
121 | source = { registry = "https://pypi.org/simple" }
122 | dependencies = [
123 | { name = "importlib-resources", marker = "python_full_version < '3.10'" },
124 | ]
125 | sdist = { url = "https://files.pythonhosted.org/packages/24/a1/1f662631ab153975fa8dbf09296324ecbaf53370dce922054e8de6b57370/fake-useragent-1.5.1.tar.gz", hash = "sha256:6387269f5a2196b5ba7ed8935852f75486845a1c95c50e72460e6a8e762f5c49", size = 22631 }
126 | wheels = [
127 | { url = "https://files.pythonhosted.org/packages/e4/99/60d8cf1b26938c2e0a57e232f7f15641dfcd6f8deda454d73e4145910ff6/fake_useragent-1.5.1-py3-none-any.whl", hash = "sha256:57415096557c8a4e23b62a375c21c55af5fd4ba30549227f562d2c4f5b60e3b3", size = 17190 },
128 | ]
129 |
130 | [[package]]
131 | name = "filelock"
132 | version = "3.15.4"
133 | source = { registry = "https://pypi.org/simple" }
134 | sdist = { url = "https://files.pythonhosted.org/packages/08/dd/49e06f09b6645156550fb9aee9cc1e59aba7efbc972d665a1bd6ae0435d4/filelock-3.15.4.tar.gz", hash = "sha256:2207938cbc1844345cb01a5a95524dae30f0ce089eba5b00378295a17e3e90cb", size = 18007 }
135 | wheels = [
136 | { url = "https://files.pythonhosted.org/packages/ae/f0/48285f0262fe47103a4a45972ed2f9b93e4c80b8fd609fa98da78b2a5706/filelock-3.15.4-py3-none-any.whl", hash = "sha256:6ca1fffae96225dab4c6eaf1c4f4f28cd2568d3ec2a44e15a08520504de468e7", size = 16159 },
137 | ]
138 |
139 | [[package]]
140 | name = "h11"
141 | version = "0.14.0"
142 | source = { registry = "https://pypi.org/simple" }
143 | sdist = { url = "https://files.pythonhosted.org/packages/f5/38/3af3d3633a34a3316095b39c8e8fb4853a28a536e55d347bd8d8e9a14b03/h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d", size = 100418 }
144 | wheels = [
145 | { url = "https://files.pythonhosted.org/packages/95/04/ff642e65ad6b90db43e668d70ffb6736436c7ce41fcc549f4e9472234127/h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761", size = 58259 },
146 | ]
147 |
148 | [[package]]
149 | name = "httpcore"
150 | version = "1.0.5"
151 | source = { registry = "https://pypi.org/simple" }
152 | dependencies = [
153 | { name = "certifi" },
154 | { name = "h11" },
155 | ]
156 | sdist = { url = "https://files.pythonhosted.org/packages/17/b0/5e8b8674f8d203335a62fdfcfa0d11ebe09e23613c3391033cbba35f7926/httpcore-1.0.5.tar.gz", hash = "sha256:34a38e2f9291467ee3b44e89dd52615370e152954ba21721378a87b2960f7a61", size = 83234 }
157 | wheels = [
158 | { url = "https://files.pythonhosted.org/packages/78/d4/e5d7e4f2174f8a4d63c8897d79eb8fe2503f7ecc03282fee1fa2719c2704/httpcore-1.0.5-py3-none-any.whl", hash = "sha256:421f18bac248b25d310f3cacd198d55b8e6125c107797b609ff9b7a6ba7991b5", size = 77926 },
159 | ]
160 |
161 | [[package]]
162 | name = "httpx"
163 | version = "0.27.2"
164 | source = { registry = "https://pypi.org/simple" }
165 | dependencies = [
166 | { name = "anyio" },
167 | { name = "certifi" },
168 | { name = "httpcore" },
169 | { name = "idna" },
170 | { name = "sniffio" },
171 | ]
172 | sdist = { url = "https://files.pythonhosted.org/packages/78/82/08f8c936781f67d9e6b9eeb8a0c8b4e406136ea4c3d1f89a5db71d42e0e6/httpx-0.27.2.tar.gz", hash = "sha256:f7c2be1d2f3c3c3160d441802406b206c2b76f5947b11115e6df10c6c65e66c2", size = 144189 }
173 | wheels = [
174 | { url = "https://files.pythonhosted.org/packages/56/95/9377bcb415797e44274b51d46e3249eba641711cf3348050f76ee7b15ffc/httpx-0.27.2-py3-none-any.whl", hash = "sha256:7bb2708e112d8fdd7829cd4243970f0c223274051cb35ee80c03301ee29a3df0", size = 76395 },
175 | ]
176 |
177 | [[package]]
178 | name = "idna"
179 | version = "3.8"
180 | source = { registry = "https://pypi.org/simple" }
181 | sdist = { url = "https://files.pythonhosted.org/packages/e8/ac/e349c5e6d4543326c6883ee9491e3921e0d07b55fdf3cce184b40d63e72a/idna-3.8.tar.gz", hash = "sha256:d838c2c0ed6fced7693d5e8ab8e734d5f8fda53a039c0164afb0b82e771e3603", size = 189467 }
182 | wheels = [
183 | { url = "https://files.pythonhosted.org/packages/22/7e/d71db821f177828df9dea8c42ac46473366f191be53080e552e628aad991/idna-3.8-py3-none-any.whl", hash = "sha256:050b4e5baadcd44d760cedbd2b8e639f2ff89bbc7a5730fcc662954303377aac", size = 66894 },
184 | ]
185 |
186 | [[package]]
187 | name = "importlib-resources"
188 | version = "6.4.4"
189 | source = { registry = "https://pypi.org/simple" }
190 | dependencies = [
191 | { name = "zipp", marker = "python_full_version < '3.10'" },
192 | ]
193 | sdist = { url = "https://files.pythonhosted.org/packages/0e/6a/3ac38d1458685a04fafa299dce821713a4f65e5ec30466bec07113f2f891/importlib_resources-6.4.4.tar.gz", hash = "sha256:20600c8b7361938dc0bb2d5ec0297802e575df486f5a544fa414da65e13721f7", size = 42721 }
194 | wheels = [
195 | { url = "https://files.pythonhosted.org/packages/db/2a/728c8ae66011600fac5731a7db030d23c42f1321fd9547654f0c3b2b32d7/importlib_resources-6.4.4-py3-none-any.whl", hash = "sha256:dda242603d1c9cd836c3368b1174ed74cb4049ecd209e7a1a0104620c18c5c11", size = 35608 },
196 | ]
197 |
198 | [[package]]
199 | name = "iniconfig"
200 | version = "2.0.0"
201 | source = { registry = "https://pypi.org/simple" }
202 | sdist = { url = "https://files.pythonhosted.org/packages/d7/4b/cbd8e699e64a6f16ca3a8220661b5f83792b3017d0f79807cb8708d33913/iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3", size = 4646 }
203 | wheels = [
204 | { url = "https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374", size = 5892 },
205 | ]
206 |
207 | [[package]]
208 | name = "nodeenv"
209 | version = "1.9.1"
210 | source = { registry = "https://pypi.org/simple" }
211 | sdist = { url = "https://files.pythonhosted.org/packages/43/16/fc88b08840de0e0a72a2f9d8c6bae36be573e475a6326ae854bcc549fc45/nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f", size = 47437 }
212 | wheels = [
213 | { url = "https://files.pythonhosted.org/packages/d2/1d/1b658dbd2b9fa9c4c9f32accbfc0205d532c8c6194dc0f2a4c0428e7128a/nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9", size = 22314 },
214 | ]
215 |
216 | [[package]]
217 | name = "packaging"
218 | version = "24.1"
219 | source = { registry = "https://pypi.org/simple" }
220 | sdist = { url = "https://files.pythonhosted.org/packages/51/65/50db4dda066951078f0a96cf12f4b9ada6e4b811516bf0262c0f4f7064d4/packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002", size = 148788 }
221 | wheels = [
222 | { url = "https://files.pythonhosted.org/packages/08/aa/cc0199a5f0ad350994d660967a8efb233fe0416e4639146c089643407ce6/packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124", size = 53985 },
223 | ]
224 |
225 | [[package]]
226 | name = "platformdirs"
227 | version = "4.2.2"
228 | source = { registry = "https://pypi.org/simple" }
229 | sdist = { url = "https://files.pythonhosted.org/packages/f5/52/0763d1d976d5c262df53ddda8d8d4719eedf9594d046f117c25a27261a19/platformdirs-4.2.2.tar.gz", hash = "sha256:38b7b51f512eed9e84a22788b4bce1de17c0adb134d6becb09836e37d8654cd3", size = 20916 }
230 | wheels = [
231 | { url = "https://files.pythonhosted.org/packages/68/13/2aa1f0e1364feb2c9ef45302f387ac0bd81484e9c9a4c5688a322fbdfd08/platformdirs-4.2.2-py3-none-any.whl", hash = "sha256:2d7a1657e36a80ea911db832a8a6ece5ee53d8de21edd5cc5879af6530b1bfee", size = 18146 },
232 | ]
233 |
234 | [[package]]
235 | name = "pluggy"
236 | version = "1.5.0"
237 | source = { registry = "https://pypi.org/simple" }
238 | sdist = { url = "https://files.pythonhosted.org/packages/96/2d/02d4312c973c6050a18b314a5ad0b3210edb65a906f868e31c111dede4a6/pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1", size = 67955 }
239 | wheels = [
240 | { url = "https://files.pythonhosted.org/packages/88/5f/e351af9a41f866ac3f1fac4ca0613908d9a41741cfcf2228f4ad853b697d/pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669", size = 20556 },
241 | ]
242 |
243 | [[package]]
244 | name = "pyproject-api"
245 | version = "1.7.1"
246 | source = { registry = "https://pypi.org/simple" }
247 | dependencies = [
248 | { name = "packaging" },
249 | { name = "tomli", marker = "python_full_version < '3.11'" },
250 | ]
251 | sdist = { url = "https://files.pythonhosted.org/packages/41/43/5581b42a96c5ee7bf2b22d3b08b34c8a54dfe6591d8b9a4314c890bd4a0d/pyproject_api-1.7.1.tar.gz", hash = "sha256:7ebc6cd10710f89f4cf2a2731710a98abce37ebff19427116ff2174c9236a827", size = 22271 }
252 | wheels = [
253 | { url = "https://files.pythonhosted.org/packages/de/88/c1451b66664ae596bae93928ff372f4da89c2c7250132ecb76cc99256c93/pyproject_api-1.7.1-py3-none-any.whl", hash = "sha256:2dc1654062c2b27733d8fd4cdda672b22fe8741ef1dde8e3a998a9547b071eeb", size = 13172 },
254 | ]
255 |
256 | [[package]]
257 | name = "pyright"
258 | version = "1.1.353"
259 | source = { registry = "https://pypi.org/simple" }
260 | dependencies = [
261 | { name = "nodeenv" },
262 | ]
263 | sdist = { url = "https://files.pythonhosted.org/packages/30/89/2e537d2e109404d888bead0334168cf9985b8a9d196056c292a87dc0df90/pyright-1.1.353.tar.gz", hash = "sha256:24343bbc2a4f997563f966b6244a2e863473f1d85af6d24abcb366fcbb4abca9", size = 17490 }
264 | wheels = [
265 | { url = "https://files.pythonhosted.org/packages/75/86/e2f88eb68126ad3fdee5f575a6aaf2c87524bfa1be009200cddd4cb5fc11/pyright-1.1.353-py3-none-any.whl", hash = "sha256:8d7e6719d0be4fd9f4a37f010237c6a74d91ec1e7c81de634c2f3f9965f8ab43", size = 18224 },
266 | ]
267 |
268 | [[package]]
269 | name = "pytest"
270 | version = "8.3.2"
271 | source = { registry = "https://pypi.org/simple" }
272 | dependencies = [
273 | { name = "colorama", marker = "sys_platform == 'win32'" },
274 | { name = "exceptiongroup", marker = "python_full_version < '3.11'" },
275 | { name = "iniconfig" },
276 | { name = "packaging" },
277 | { name = "pluggy" },
278 | { name = "tomli", marker = "python_full_version < '3.11'" },
279 | ]
280 | sdist = { url = "https://files.pythonhosted.org/packages/b4/8c/9862305bdcd6020bc7b45b1b5e7397a6caf1a33d3025b9a003b39075ffb2/pytest-8.3.2.tar.gz", hash = "sha256:c132345d12ce551242c87269de812483f5bcc87cdbb4722e48487ba194f9fdce", size = 1439314 }
281 | wheels = [
282 | { url = "https://files.pythonhosted.org/packages/0f/f9/cf155cf32ca7d6fa3601bc4c5dd19086af4b320b706919d48a4c79081cf9/pytest-8.3.2-py3-none-any.whl", hash = "sha256:4ba08f9ae7dcf84ded419494d229b48d0903ea6407b030eaec46df5e6a73bba5", size = 341802 },
283 | ]
284 |
285 | [[package]]
286 | name = "pytest-asyncio"
287 | version = "0.23.8"
288 | source = { registry = "https://pypi.org/simple" }
289 | dependencies = [
290 | { name = "pytest" },
291 | ]
292 | sdist = { url = "https://files.pythonhosted.org/packages/de/b4/0b378b7bf26a8ae161c3890c0b48a91a04106c5713ce81b4b080ea2f4f18/pytest_asyncio-0.23.8.tar.gz", hash = "sha256:759b10b33a6dc61cce40a8bd5205e302978bbbcc00e279a8b61d9a6a3c82e4d3", size = 46920 }
293 | wheels = [
294 | { url = "https://files.pythonhosted.org/packages/ee/82/62e2d63639ecb0fbe8a7ee59ef0bc69a4669ec50f6d3459f74ad4e4189a2/pytest_asyncio-0.23.8-py3-none-any.whl", hash = "sha256:50265d892689a5faefb84df80819d1ecef566eb3549cf915dfb33569359d1ce2", size = 17663 },
295 | ]
296 |
297 | [[package]]
298 | name = "ruff"
299 | version = "0.6.3"
300 | source = { registry = "https://pypi.org/simple" }
301 | sdist = { url = "https://files.pythonhosted.org/packages/5d/f9/0b32e5d1c6f957df49398cd882a011e9488fcbca0d6acfeeea50ccd37a4d/ruff-0.6.3.tar.gz", hash = "sha256:183b99e9edd1ef63be34a3b51fee0a9f4ab95add123dbf89a71f7b1f0c991983", size = 2463514 }
302 | wheels = [
303 | { url = "https://files.pythonhosted.org/packages/72/68/1da6a1e39a03a229ea57c511691d6225072759cc7764206c3f0989521194/ruff-0.6.3-py3-none-linux_armv6l.whl", hash = "sha256:97f58fda4e309382ad30ede7f30e2791d70dd29ea17f41970119f55bdb7a45c3", size = 9696928 },
304 | { url = "https://files.pythonhosted.org/packages/6e/59/3b8b1d3a4271c6eb6ceecd3cef19a6d881639a0f18ad651563d6f619aaae/ruff-0.6.3-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:3b061e49b5cf3a297b4d1c27ac5587954ccb4ff601160d3d6b2f70b1622194dc", size = 9448462 },
305 | { url = "https://files.pythonhosted.org/packages/35/4f/b942ecb8bbebe53aa9b33e9b96df88acd50b70adaaed3070f1d92131a1cb/ruff-0.6.3-py3-none-macosx_11_0_arm64.whl", hash = "sha256:34e2824a13bb8c668c71c1760a6ac7d795ccbd8d38ff4a0d8471fdb15de910b1", size = 9176190 },
306 | { url = "https://files.pythonhosted.org/packages/a0/20/b0bcb29d4ee437f3567b73b6905c034e2e94d29b9b826c66daecc1cf6388/ruff-0.6.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bddfbb8d63c460f4b4128b6a506e7052bad4d6f3ff607ebbb41b0aa19c2770d1", size = 10108892 },
307 | { url = "https://files.pythonhosted.org/packages/9c/e3/211bc759f424e8823a9937e0f678695ca02113c621dfde1fa756f9f26f6d/ruff-0.6.3-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ced3eeb44df75353e08ab3b6a9e113b5f3f996bea48d4f7c027bc528ba87b672", size = 9476471 },
308 | { url = "https://files.pythonhosted.org/packages/b2/a3/2ec35a2d7a554364864206f0e46812b92a074ad8a014b923d821ead532aa/ruff-0.6.3-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:47021dff5445d549be954eb275156dfd7c37222acc1e8014311badcb9b4ec8c1", size = 10294802 },
309 | { url = "https://files.pythonhosted.org/packages/03/8b/56ef687b3489c88886dea48c78fb4969b6b65f18007d0ac450070edd1f58/ruff-0.6.3-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:7d7bd20dc07cebd68cc8bc7b3f5ada6d637f42d947c85264f94b0d1cd9d87384", size = 11022372 },
310 | { url = "https://files.pythonhosted.org/packages/a5/21/327d147feb442adb88975e81e2263102789eba9ad2afa102c661912a482f/ruff-0.6.3-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:500f166d03fc6d0e61c8e40a3ff853fa8a43d938f5d14c183c612df1b0d6c58a", size = 10596596 },
311 | { url = "https://files.pythonhosted.org/packages/6c/86/ff386de63729da3e08c8099c57f577a00ec9f3eea711b23ac07cf3588dc5/ruff-0.6.3-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:42844ff678f9b976366b262fa2d1d1a3fe76f6e145bd92c84e27d172e3c34500", size = 11572830 },
312 | { url = "https://files.pythonhosted.org/packages/38/5d/b33284c108e3f315ddd09b70296fd76bd28ecf8965a520bc93f3bbd8ac40/ruff-0.6.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70452a10eb2d66549de8e75f89ae82462159855e983ddff91bc0bce6511d0470", size = 10262577 },
313 | { url = "https://files.pythonhosted.org/packages/29/99/9cdfad0d7f460e66567236eddc691473791afd9aff93a0dfcdef0462a6c7/ruff-0.6.3-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:65a533235ed55f767d1fc62193a21cbf9e3329cf26d427b800fdeacfb77d296f", size = 10098751 },
314 | { url = "https://files.pythonhosted.org/packages/a8/9f/f801a1619f5549e552f1f722f1db57eb39e7e1d83d482133142781d450de/ruff-0.6.3-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:d2e2c23cef30dc3cbe9cc5d04f2899e7f5e478c40d2e0a633513ad081f7361b5", size = 9563859 },
315 | { url = "https://files.pythonhosted.org/packages/0b/4d/fb2424faf04ffdb960ae2b3a1d991c5183dd981003de727d2d5cc38abc98/ruff-0.6.3-py3-none-musllinux_1_2_i686.whl", hash = "sha256:d8a136aa7d228975a6aee3dd8bea9b28e2b43e9444aa678fb62aeb1956ff2351", size = 9914291 },
316 | { url = "https://files.pythonhosted.org/packages/2e/dd/94fddf002a8f6152e8ebfbb51d3f93febc415c1fe694345623c31ce8b33b/ruff-0.6.3-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:f92fe93bc72e262b7b3f2bba9879897e2d58a989b4714ba6a5a7273e842ad2f8", size = 10331549 },
317 | { url = "https://files.pythonhosted.org/packages/b4/73/ca9c2f9237a430ca423b6dca83b77e9a428afeb7aec80596e86c369123fe/ruff-0.6.3-py3-none-win32.whl", hash = "sha256:7a62d3b5b0d7f9143d94893f8ba43aa5a5c51a0ffc4a401aa97a81ed76930521", size = 7962163 },
318 | { url = "https://files.pythonhosted.org/packages/55/ce/061c605b1dfb52748d59bc0c7a8507546c178801156415773d18febfd71d/ruff-0.6.3-py3-none-win_amd64.whl", hash = "sha256:746af39356fee2b89aada06c7376e1aa274a23493d7016059c3a72e3b296befb", size = 8800901 },
319 | { url = "https://files.pythonhosted.org/packages/63/28/ae4ffe7d3b6134ca6d31ebef07447ef70097c4a9e8fbbc519b374c5c1559/ruff-0.6.3-py3-none-win_arm64.whl", hash = "sha256:14a9528a8b70ccc7a847637c29e56fd1f9183a9db743bbc5b8e0c4ad60592a82", size = 8229171 },
320 | ]
321 |
322 | [[package]]
323 | name = "sniffio"
324 | version = "1.3.1"
325 | source = { registry = "https://pypi.org/simple" }
326 | sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372 }
327 | wheels = [
328 | { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235 },
329 | ]
330 |
331 | [[package]]
332 | name = "tomli"
333 | version = "2.0.1"
334 | source = { registry = "https://pypi.org/simple" }
335 | sdist = { url = "https://files.pythonhosted.org/packages/c0/3f/d7af728f075fb08564c5949a9c95e44352e23dee646869fa104a3b2060a3/tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f", size = 15164 }
336 | wheels = [
337 | { url = "https://files.pythonhosted.org/packages/97/75/10a9ebee3fd790d20926a90a2547f0bf78f371b2f13aa822c759680ca7b9/tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc", size = 12757 },
338 | ]
339 |
340 | [[package]]
341 | name = "tox"
342 | version = "4.18.0"
343 | source = { registry = "https://pypi.org/simple" }
344 | dependencies = [
345 | { name = "cachetools" },
346 | { name = "chardet" },
347 | { name = "colorama" },
348 | { name = "filelock" },
349 | { name = "packaging" },
350 | { name = "platformdirs" },
351 | { name = "pluggy" },
352 | { name = "pyproject-api" },
353 | { name = "tomli", marker = "python_full_version < '3.11'" },
354 | { name = "virtualenv" },
355 | ]
356 | sdist = { url = "https://files.pythonhosted.org/packages/38/d6/e3713386deb7df92ef383693544eccb18260ce4325fabcf5aac6594c1d95/tox-4.18.0.tar.gz", hash = "sha256:5dfa1cab9f146becd6e351333a82f9e0ade374451630ba65ee54584624c27b58", size = 180782 }
357 | wheels = [
358 | { url = "https://files.pythonhosted.org/packages/a2/40/37c670a35bea970cb4e8c19a756ec75a3362b792041003aa075a29123ccc/tox-4.18.0-py3-none-any.whl", hash = "sha256:0a457400cf70615dc0627eb70d293e80cd95d8ce174bb40ac011011f0c03a249", size = 156735 },
359 | ]
360 |
361 | [[package]]
362 | name = "tox-gh-actions"
363 | version = "3.2.0"
364 | source = { registry = "https://pypi.org/simple" }
365 | dependencies = [
366 | { name = "tox" },
367 | ]
368 | sdist = { url = "https://files.pythonhosted.org/packages/5b/a1/3e7b3185031f905ddfc0c65dfd85949dae612a4387cbacb286b9f2931314/tox-gh-actions-3.2.0.tar.gz", hash = "sha256:ac6fa3b8da51bc90dd77985fd55f09e746c6558c55910c0a93d643045a2b0ccc", size = 18834 }
369 | wheels = [
370 | { url = "https://files.pythonhosted.org/packages/b9/7a/d59f4eb08d156787af19fb44371586fd8b25580a1837ce92ae203a847c49/tox_gh_actions-3.2.0-py2.py3-none-any.whl", hash = "sha256:821b66a4751a788fa3e9617bd796d696507b08c6e1d929ee4faefba06b73b694", size = 9951 },
371 | ]
372 |
373 | [[package]]
374 | name = "tox-uv"
375 | version = "1.11.2"
376 | source = { registry = "https://pypi.org/simple" }
377 | dependencies = [
378 | { name = "packaging" },
379 | { name = "tox" },
380 | { name = "typing-extensions", marker = "python_full_version < '3.10'" },
381 | { name = "uv" },
382 | ]
383 | sdist = { url = "https://files.pythonhosted.org/packages/fa/cf/7062095ae8c5e6a25d7153b9b1c4a16e52df61859160b3db66a60f055d1e/tox_uv-1.11.2.tar.gz", hash = "sha256:a7aded5c3fb69f055b523357988c1055bb573e91bfd7ecfb9b5233ebcab5d10b", size = 13628 }
384 | wheels = [
385 | { url = "https://files.pythonhosted.org/packages/6a/50/5b9f2d9d10bfdfb1f748bbcdb6eae5a5da6d2a7adbef9a4df34aceac6eca/tox_uv-1.11.2-py3-none-any.whl", hash = "sha256:7f8f1737b3277e1cddcb5b89fcc5931d04923562c940ae60f29e140908566df2", size = 11265 },
386 | ]
387 |
388 | [[package]]
389 | name = "typing-extensions"
390 | version = "4.12.2"
391 | source = { registry = "https://pypi.org/simple" }
392 | sdist = { url = "https://files.pythonhosted.org/packages/df/db/f35a00659bc03fec321ba8bce9420de607a1d37f8342eee1863174c69557/typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8", size = 85321 }
393 | wheels = [
394 | { url = "https://files.pythonhosted.org/packages/26/9f/ad63fc0248c5379346306f8668cda6e2e2e9c95e01216d2b8ffd9ff037d0/typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", size = 37438 },
395 | ]
396 |
397 | [[package]]
398 | name = "uv"
399 | version = "0.4.1"
400 | source = { registry = "https://pypi.org/simple" }
401 | sdist = { url = "https://files.pythonhosted.org/packages/54/11/71895ccc7a75ab750ce6223b762c654a146a3d42ee1b67d512a4a6a1d894/uv-0.4.1.tar.gz", hash = "sha256:7eaeeda1ee71671981274fbacac3258e8f878a6de254e6c38d4d8f0e7055aa2a", size = 1827976 }
402 | wheels = [
403 | { url = "https://files.pythonhosted.org/packages/be/73/7913f1a8432404506c351c03df6603df464e0acaba371be6300bf974f37d/uv-0.4.1-py3-none-linux_armv6l.whl", hash = "sha256:596b820cf452cb4a43df886043d9b881f894efbeb076184c29f5b50222164926", size = 10810783 },
404 | { url = "https://files.pythonhosted.org/packages/11/20/46c14f63da6ae489c854ab200bdd54ed0f02eb98db6df584ae12f77b4d26/uv-0.4.1-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:0e1c65e266bbac763d63b7d80542b12d6cf841f2db56a069ef9583e6ef1d9fab", size = 11197667 },
405 | { url = "https://files.pythonhosted.org/packages/46/ad/90e0d7a448b4c92846589c8bb92813ac45d2b123a2b9d4cab4167e805f9f/uv-0.4.1-py3-none-macosx_11_0_arm64.whl", hash = "sha256:fcdc6503100e86fecf6a727d3149e54581e8e9ad6c10e814fc5d22c1e80fab8d", size = 10342437 },
406 | { url = "https://files.pythonhosted.org/packages/b4/19/6f61a7893e76f030e6cfe8737bfb11929728b0db239598eb62932d49ca55/uv-0.4.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:cf17b70464b4e632cb3f3193206a231d94be98e520a254515f28abcb4110c738", size = 10679663 },
407 | { url = "https://files.pythonhosted.org/packages/47/33/ce37f56ae2e095f00038896903b958f1f08ab519efd5d18b03de5c0df010/uv-0.4.1-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ad566cd468f98ae33ea475c1bf47ec6ea6dd3be0b6b9065c4a23def54b837919", size = 10620060 },
408 | { url = "https://files.pythonhosted.org/packages/1a/8b/297fbc99fc3ea966ae3bf019dd42f5e841c69ad4c5d58c69f258a2dd5f89/uv-0.4.1-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0f0daa94e6d95b9ebd62420aa576a6a5792e03716763f27fa3430a57606de122", size = 11221220 },
409 | { url = "https://files.pythonhosted.org/packages/27/32/2f979550abe98c44613781e35c5f58b6f4927dd6f9e53251558b07d48446/uv-0.4.1-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:d6eb1d759a6a23d6b9d8ccb900a49814bdeeee32dbcd41bd0ed312373b8b2beb", size = 12036648 },
410 | { url = "https://files.pythonhosted.org/packages/aa/38/78956ac0dced46814470bfbe64381851843d9cf34f4fb5d95e3efbfb60e8/uv-0.4.1-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6068ad80a23011ef508351ddc377172d98cebfdd0e9c88d06d5b13c67d2053c3", size = 11837645 },
411 | { url = "https://files.pythonhosted.org/packages/12/d9/1ad882c99ecba897da74a4b59cc8fe02c5894f94e6c3d7d585e58458b4d5/uv-0.4.1-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d09a1888dc9580c29c8deeeaf8a991e051c1b73650e897df606ef06b8622f544", size = 14913692 },
412 | { url = "https://files.pythonhosted.org/packages/86/b6/2a5b326d1ff3461043a1fa287452e4749394a9791e12a47fd3d695d1d147/uv-0.4.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:132fa34c5813b4a2970d3ab74b700a02eb59d14bdea322a7037be1c0bd2b81c7", size = 11576290 },
413 | { url = "https://files.pythonhosted.org/packages/82/66/e441b3dc11ae5ba17e315851d348d01e24e84f3e4710db9dae1b5cb52b5d/uv-0.4.1-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:6af4e8a605aefabee333e110c93a198e1fb304f054bee822912952bf546a4896", size = 10789941 },
414 | { url = "https://files.pythonhosted.org/packages/8c/32/c3cd8773b37d8d1f20a4cc4cdc074e117c5ad5a68fe17a65d1a464f95f04/uv-0.4.1-py3-none-musllinux_1_1_armv7l.whl", hash = "sha256:bc11b55a15255deea1541dfe81455df52ad74483539a20b6515db753ec721f52", size = 10626425 },
415 | { url = "https://files.pythonhosted.org/packages/e5/c7/63defaf7be4e0acc2bd17cca1a114b514b1b49fea4395aa1ff17a9649a99/uv-0.4.1-py3-none-musllinux_1_1_i686.whl", hash = "sha256:1a253ed3d03a4a9a3d4c54feb55f3cda93d75a4038b6d9665c9b5c05e51ea594", size = 11041755 },
416 | { url = "https://files.pythonhosted.org/packages/87/99/1b661dc25b3018cdd755d7179f242034da493583023bc82728a780f71a65/uv-0.4.1-py3-none-musllinux_1_1_ppc64le.whl", hash = "sha256:7c129dc549be0a36bc0ce9540ebc981755af5a7c07076cce6564a2f10d193220", size = 12788989 },
417 | { url = "https://files.pythonhosted.org/packages/b7/f2/ac58abcd46f7235cef60df079772cf08e400adb9f43aa2e7b63181dfe34c/uv-0.4.1-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:f81f89a2c0cce1480816f5172edc39c3a80ff668404a72c3d6b7a7cdd90cd5ac", size = 11704625 },
418 | { url = "https://files.pythonhosted.org/packages/cc/21/8b25e5767eee405bc29c16c13fa347247e714226ca098a9b60e4c8252423/uv-0.4.1-py3-none-win32.whl", hash = "sha256:35992e42c1d52cbdc3db10af147818f5a440be1a2be3dfe042dfae7f0a05d71a", size = 11004831 },
419 | { url = "https://files.pythonhosted.org/packages/c7/b0/bb3ec0a1064a0548c9343c18cfcc58c76de86ba7c2fd312b9591ae6a342c/uv-0.4.1-py3-none-win_amd64.whl", hash = "sha256:3a26d911b72848062af1d0525dda85d538c57002c10c5965d591bdc774e701a2", size = 12317848 },
420 | ]
421 |
422 | [[package]]
423 | name = "virtualenv"
424 | version = "20.26.3"
425 | source = { registry = "https://pypi.org/simple" }
426 | dependencies = [
427 | { name = "distlib" },
428 | { name = "filelock" },
429 | { name = "platformdirs" },
430 | ]
431 | sdist = { url = "https://files.pythonhosted.org/packages/68/60/db9f95e6ad456f1872486769c55628c7901fb4de5a72c2f7bdd912abf0c1/virtualenv-20.26.3.tar.gz", hash = "sha256:4c43a2a236279d9ea36a0d76f98d84bd6ca94ac4e0f4a3b9d46d05e10fea542a", size = 9057588 }
432 | wheels = [
433 | { url = "https://files.pythonhosted.org/packages/07/4d/410156100224c5e2f0011d435e477b57aed9576fc7fe137abcf14ec16e11/virtualenv-20.26.3-py3-none-any.whl", hash = "sha256:8cc4a31139e796e9a7de2cd5cf2489de1217193116a8fd42328f1bd65f434589", size = 5684792 },
434 | ]
435 |
436 | [[package]]
437 | name = "zipp"
438 | version = "3.20.1"
439 | source = { registry = "https://pypi.org/simple" }
440 | sdist = { url = "https://files.pythonhosted.org/packages/d3/8b/1239a3ef43a0d0ebdca623fb6413bc7702c321400c5fdd574f0b7aa0fbb4/zipp-3.20.1.tar.gz", hash = "sha256:c22b14cc4763c5a5b04134207736c107db42e9d3ef2d9779d465f5f1bcba572b", size = 23848 }
441 | wheels = [
442 | { url = "https://files.pythonhosted.org/packages/07/9e/c96f7a4cd0bf5625bb409b7e61e99b1130dc63a98cb8b24aeabae62d43e8/zipp-3.20.1-py3-none-any.whl", hash = "sha256:9960cd8967c8f85a56f920d5d507274e74f9ff813a0ab8889a5b5be2daf44064", size = 8988 },
443 | ]
444 |
--------------------------------------------------------------------------------
/poetry.lock:
--------------------------------------------------------------------------------
1 | # This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand.
2 |
3 | [[package]]
4 | name = "anyio"
5 | version = "4.1.0"
6 | description = "High level compatibility layer for multiple asynchronous event loop implementations"
7 | optional = false
8 | python-versions = ">=3.8"
9 | files = [
10 | {file = "anyio-4.1.0-py3-none-any.whl", hash = "sha256:56a415fbc462291813a94528a779597226619c8e78af7de0507333f700011e5f"},
11 | {file = "anyio-4.1.0.tar.gz", hash = "sha256:5a0bec7085176715be77df87fc66d6c9d70626bd752fcc85f57cdbee5b3760da"},
12 | ]
13 |
14 | [package.dependencies]
15 | exceptiongroup = {version = ">=1.0.2", markers = "python_version < \"3.11\""}
16 | idna = ">=2.8"
17 | sniffio = ">=1.1"
18 |
19 | [package.extras]
20 | doc = ["Sphinx (>=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"]
21 | test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"]
22 | trio = ["trio (>=0.23)"]
23 |
24 | [[package]]
25 | name = "babel"
26 | version = "2.13.1"
27 | description = "Internationalization utilities"
28 | optional = false
29 | python-versions = ">=3.7"
30 | files = [
31 | {file = "Babel-2.13.1-py3-none-any.whl", hash = "sha256:7077a4984b02b6727ac10f1f7294484f737443d7e2e66c5e4380e41a3ae0b4ed"},
32 | {file = "Babel-2.13.1.tar.gz", hash = "sha256:33e0952d7dd6374af8dbf6768cc4ddf3ccfefc244f9986d4074704f2fbd18900"},
33 | ]
34 |
35 | [package.dependencies]
36 | setuptools = {version = "*", markers = "python_version >= \"3.12\""}
37 |
38 | [package.extras]
39 | dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"]
40 |
41 | [[package]]
42 | name = "cachetools"
43 | version = "5.3.2"
44 | description = "Extensible memoizing collections and decorators"
45 | optional = false
46 | python-versions = ">=3.7"
47 | files = [
48 | {file = "cachetools-5.3.2-py3-none-any.whl", hash = "sha256:861f35a13a451f94e301ce2bec7cac63e881232ccce7ed67fab9b5df4d3beaa1"},
49 | {file = "cachetools-5.3.2.tar.gz", hash = "sha256:086ee420196f7b2ab9ca2db2520aca326318b68fe5ba8bc4d49cca91add450f2"},
50 | ]
51 |
52 | [[package]]
53 | name = "certifi"
54 | version = "2023.11.17"
55 | description = "Python package for providing Mozilla's CA Bundle."
56 | optional = false
57 | python-versions = ">=3.6"
58 | files = [
59 | {file = "certifi-2023.11.17-py3-none-any.whl", hash = "sha256:e036ab49d5b79556f99cfc2d9320b34cfbe5be05c5871b51de9329f0603b0474"},
60 | {file = "certifi-2023.11.17.tar.gz", hash = "sha256:9b469f3a900bf28dc19b8cfbf8019bf47f7fdd1a65a1d4ffb98fc14166beb4d1"},
61 | ]
62 |
63 | [[package]]
64 | name = "cfgv"
65 | version = "3.4.0"
66 | description = "Validate configuration and produce human readable error messages."
67 | optional = false
68 | python-versions = ">=3.8"
69 | files = [
70 | {file = "cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9"},
71 | {file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"},
72 | ]
73 |
74 | [[package]]
75 | name = "chardet"
76 | version = "5.2.0"
77 | description = "Universal encoding detector for Python 3"
78 | optional = false
79 | python-versions = ">=3.7"
80 | files = [
81 | {file = "chardet-5.2.0-py3-none-any.whl", hash = "sha256:e1cf59446890a00105fe7b7912492ea04b6e6f06d4b742b2c788469e34c82970"},
82 | {file = "chardet-5.2.0.tar.gz", hash = "sha256:1b3b6ff479a8c414bc3fa2c0852995695c4a026dcd6d0633b2dd092ca39c1cf7"},
83 | ]
84 |
85 | [[package]]
86 | name = "charset-normalizer"
87 | version = "3.3.2"
88 | description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
89 | optional = false
90 | python-versions = ">=3.7.0"
91 | files = [
92 | {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"},
93 | {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"},
94 | {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"},
95 | {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"},
96 | {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"},
97 | {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"},
98 | {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"},
99 | {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"},
100 | {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"},
101 | {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"},
102 | {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"},
103 | {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"},
104 | {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"},
105 | {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"},
106 | {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"},
107 | {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"},
108 | {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"},
109 | {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"},
110 | {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"},
111 | {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"},
112 | {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"},
113 | {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"},
114 | {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"},
115 | {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"},
116 | {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"},
117 | {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"},
118 | {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"},
119 | {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"},
120 | {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"},
121 | {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"},
122 | {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"},
123 | {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"},
124 | {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"},
125 | {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"},
126 | {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"},
127 | {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"},
128 | {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"},
129 | {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"},
130 | {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"},
131 | {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"},
132 | {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"},
133 | {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"},
134 | {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"},
135 | {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"},
136 | {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"},
137 | {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"},
138 | {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"},
139 | {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"},
140 | {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"},
141 | {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"},
142 | {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"},
143 | {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"},
144 | {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"},
145 | {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"},
146 | {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"},
147 | {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"},
148 | {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"},
149 | {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"},
150 | {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"},
151 | {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"},
152 | {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"},
153 | {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"},
154 | {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"},
155 | {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"},
156 | {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"},
157 | {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"},
158 | {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"},
159 | {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"},
160 | {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"},
161 | {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"},
162 | {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"},
163 | {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"},
164 | {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"},
165 | {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"},
166 | {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"},
167 | {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"},
168 | {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"},
169 | {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"},
170 | {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"},
171 | {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"},
172 | {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"},
173 | {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"},
174 | {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"},
175 | {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"},
176 | {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"},
177 | {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"},
178 | {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"},
179 | {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"},
180 | {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"},
181 | {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"},
182 | ]
183 |
184 | [[package]]
185 | name = "click"
186 | version = "8.1.7"
187 | description = "Composable command line interface toolkit"
188 | optional = false
189 | python-versions = ">=3.7"
190 | files = [
191 | {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"},
192 | {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"},
193 | ]
194 |
195 | [package.dependencies]
196 | colorama = {version = "*", markers = "platform_system == \"Windows\""}
197 |
198 | [[package]]
199 | name = "colorama"
200 | version = "0.4.6"
201 | description = "Cross-platform colored terminal text."
202 | optional = false
203 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
204 | files = [
205 | {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
206 | {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
207 | ]
208 |
209 | [[package]]
210 | name = "coverage"
211 | version = "7.3.2"
212 | description = "Code coverage measurement for Python"
213 | optional = false
214 | python-versions = ">=3.8"
215 | files = [
216 | {file = "coverage-7.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d872145f3a3231a5f20fd48500274d7df222e291d90baa2026cc5152b7ce86bf"},
217 | {file = "coverage-7.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:310b3bb9c91ea66d59c53fa4989f57d2436e08f18fb2f421a1b0b6b8cc7fffda"},
218 | {file = "coverage-7.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f47d39359e2c3779c5331fc740cf4bce6d9d680a7b4b4ead97056a0ae07cb49a"},
219 | {file = "coverage-7.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aa72dbaf2c2068404b9870d93436e6d23addd8bbe9295f49cbca83f6e278179c"},
220 | {file = "coverage-7.3.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:beaa5c1b4777f03fc63dfd2a6bd820f73f036bfb10e925fce067b00a340d0f3f"},
221 | {file = "coverage-7.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:dbc1b46b92186cc8074fee9d9fbb97a9dd06c6cbbef391c2f59d80eabdf0faa6"},
222 | {file = "coverage-7.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:315a989e861031334d7bee1f9113c8770472db2ac484e5b8c3173428360a9148"},
223 | {file = "coverage-7.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d1bc430677773397f64a5c88cb522ea43175ff16f8bfcc89d467d974cb2274f9"},
224 | {file = "coverage-7.3.2-cp310-cp310-win32.whl", hash = "sha256:a889ae02f43aa45032afe364c8ae84ad3c54828c2faa44f3bfcafecb5c96b02f"},
225 | {file = "coverage-7.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:c0ba320de3fb8c6ec16e0be17ee1d3d69adcda99406c43c0409cb5c41788a611"},
226 | {file = "coverage-7.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ac8c802fa29843a72d32ec56d0ca792ad15a302b28ca6203389afe21f8fa062c"},
227 | {file = "coverage-7.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:89a937174104339e3a3ffcf9f446c00e3a806c28b1841c63edb2b369310fd074"},
228 | {file = "coverage-7.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e267e9e2b574a176ddb983399dec325a80dbe161f1a32715c780b5d14b5f583a"},
229 | {file = "coverage-7.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2443cbda35df0d35dcfb9bf8f3c02c57c1d6111169e3c85fc1fcc05e0c9f39a3"},
230 | {file = "coverage-7.3.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4175e10cc8dda0265653e8714b3174430b07c1dca8957f4966cbd6c2b1b8065a"},
231 | {file = "coverage-7.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0cbf38419fb1a347aaf63481c00f0bdc86889d9fbf3f25109cf96c26b403fda1"},
232 | {file = "coverage-7.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:5c913b556a116b8d5f6ef834038ba983834d887d82187c8f73dec21049abd65c"},
233 | {file = "coverage-7.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1981f785239e4e39e6444c63a98da3a1db8e971cb9ceb50a945ba6296b43f312"},
234 | {file = "coverage-7.3.2-cp311-cp311-win32.whl", hash = "sha256:43668cabd5ca8258f5954f27a3aaf78757e6acf13c17604d89648ecc0cc66640"},
235 | {file = "coverage-7.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10c39c0452bf6e694511c901426d6b5ac005acc0f78ff265dbe36bf81f808a2"},
236 | {file = "coverage-7.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:4cbae1051ab791debecc4a5dcc4a1ff45fc27b91b9aee165c8a27514dd160836"},
237 | {file = "coverage-7.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:12d15ab5833a997716d76f2ac1e4b4d536814fc213c85ca72756c19e5a6b3d63"},
238 | {file = "coverage-7.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c7bba973ebee5e56fe9251300c00f1579652587a9f4a5ed8404b15a0471f216"},
239 | {file = "coverage-7.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fe494faa90ce6381770746077243231e0b83ff3f17069d748f645617cefe19d4"},
240 | {file = "coverage-7.3.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6e9589bd04d0461a417562649522575d8752904d35c12907d8c9dfeba588faf"},
241 | {file = "coverage-7.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d51ac2a26f71da1b57f2dc81d0e108b6ab177e7d30e774db90675467c847bbdf"},
242 | {file = "coverage-7.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:99b89d9f76070237975b315b3d5f4d6956ae354a4c92ac2388a5695516e47c84"},
243 | {file = "coverage-7.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fa28e909776dc69efb6ed975a63691bc8172b64ff357e663a1bb06ff3c9b589a"},
244 | {file = "coverage-7.3.2-cp312-cp312-win32.whl", hash = "sha256:289fe43bf45a575e3ab10b26d7b6f2ddb9ee2dba447499f5401cfb5ecb8196bb"},
245 | {file = "coverage-7.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:7dbc3ed60e8659bc59b6b304b43ff9c3ed858da2839c78b804973f613d3e92ed"},
246 | {file = "coverage-7.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f94b734214ea6a36fe16e96a70d941af80ff3bfd716c141300d95ebc85339738"},
247 | {file = "coverage-7.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:af3d828d2c1cbae52d34bdbb22fcd94d1ce715d95f1a012354a75e5913f1bda2"},
248 | {file = "coverage-7.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:630b13e3036e13c7adc480ca42fa7afc2a5d938081d28e20903cf7fd687872e2"},
249 | {file = "coverage-7.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c9eacf273e885b02a0273bb3a2170f30e2d53a6d53b72dbe02d6701b5296101c"},
250 | {file = "coverage-7.3.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d8f17966e861ff97305e0801134e69db33b143bbfb36436efb9cfff6ec7b2fd9"},
251 | {file = "coverage-7.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b4275802d16882cf9c8b3d057a0839acb07ee9379fa2749eca54efbce1535b82"},
252 | {file = "coverage-7.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:72c0cfa5250f483181e677ebc97133ea1ab3eb68645e494775deb6a7f6f83901"},
253 | {file = "coverage-7.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:cb536f0dcd14149425996821a168f6e269d7dcd2c273a8bff8201e79f5104e76"},
254 | {file = "coverage-7.3.2-cp38-cp38-win32.whl", hash = "sha256:307adb8bd3abe389a471e649038a71b4eb13bfd6b7dd9a129fa856f5c695cf92"},
255 | {file = "coverage-7.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:88ed2c30a49ea81ea3b7f172e0269c182a44c236eb394718f976239892c0a27a"},
256 | {file = "coverage-7.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b631c92dfe601adf8f5ebc7fc13ced6bb6e9609b19d9a8cd59fa47c4186ad1ce"},
257 | {file = "coverage-7.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d3d9df4051c4a7d13036524b66ecf7a7537d14c18a384043f30a303b146164e9"},
258 | {file = "coverage-7.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f7363d3b6a1119ef05015959ca24a9afc0ea8a02c687fe7e2d557705375c01f"},
259 | {file = "coverage-7.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2f11cc3c967a09d3695d2a6f03fb3e6236622b93be7a4b5dc09166a861be6d25"},
260 | {file = "coverage-7.3.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:149de1d2401ae4655c436a3dced6dd153f4c3309f599c3d4bd97ab172eaf02d9"},
261 | {file = "coverage-7.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:3a4006916aa6fee7cd38db3bfc95aa9c54ebb4ffbfc47c677c8bba949ceba0a6"},
262 | {file = "coverage-7.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9028a3871280110d6e1aa2df1afd5ef003bab5fb1ef421d6dc748ae1c8ef2ebc"},
263 | {file = "coverage-7.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9f805d62aec8eb92bab5b61c0f07329275b6f41c97d80e847b03eb894f38d083"},
264 | {file = "coverage-7.3.2-cp39-cp39-win32.whl", hash = "sha256:d1c88ec1a7ff4ebca0219f5b1ef863451d828cccf889c173e1253aa84b1e07ce"},
265 | {file = "coverage-7.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b4767da59464bb593c07afceaddea61b154136300881844768037fd5e859353f"},
266 | {file = "coverage-7.3.2-pp38.pp39.pp310-none-any.whl", hash = "sha256:ae97af89f0fbf373400970c0a21eef5aa941ffeed90aee43650b81f7d7f47637"},
267 | {file = "coverage-7.3.2.tar.gz", hash = "sha256:be32ad29341b0170e795ca590e1c07e81fc061cb5b10c74ce7203491484404ef"},
268 | ]
269 |
270 | [package.dependencies]
271 | tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""}
272 |
273 | [package.extras]
274 | toml = ["tomli"]
275 |
276 | [[package]]
277 | name = "distlib"
278 | version = "0.3.7"
279 | description = "Distribution utilities"
280 | optional = false
281 | python-versions = "*"
282 | files = [
283 | {file = "distlib-0.3.7-py2.py3-none-any.whl", hash = "sha256:2e24928bc811348f0feb63014e97aaae3037f2cf48712d51ae61df7fd6075057"},
284 | {file = "distlib-0.3.7.tar.gz", hash = "sha256:9dafe54b34a028eafd95039d5e5d4851a13734540f1331060d31c9916e7147a8"},
285 | ]
286 |
287 | [[package]]
288 | name = "exceptiongroup"
289 | version = "1.2.0"
290 | description = "Backport of PEP 654 (exception groups)"
291 | optional = false
292 | python-versions = ">=3.7"
293 | files = [
294 | {file = "exceptiongroup-1.2.0-py3-none-any.whl", hash = "sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14"},
295 | {file = "exceptiongroup-1.2.0.tar.gz", hash = "sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68"},
296 | ]
297 |
298 | [package.extras]
299 | test = ["pytest (>=6)"]
300 |
301 | [[package]]
302 | name = "fake-useragent"
303 | version = "1.4.0"
304 | description = "Up-to-date simple useragent faker with real world database"
305 | optional = false
306 | python-versions = "*"
307 | files = [
308 | {file = "fake-useragent-1.4.0.tar.gz", hash = "sha256:5426e4015d8ccc5bb25f64d3dfcfd3915eba30ffebd31b86b60dc7a4c5d65528"},
309 | {file = "fake_useragent-1.4.0-py3-none-any.whl", hash = "sha256:9acce439ee2c6cf9c3772fa6c200f62dc8d56605063327a4d8c5d0e47f414b85"},
310 | ]
311 |
312 | [package.dependencies]
313 | importlib-resources = {version = ">=5.0", markers = "python_version < \"3.10\""}
314 |
315 | [[package]]
316 | name = "filelock"
317 | version = "3.13.1"
318 | description = "A platform independent file lock."
319 | optional = false
320 | python-versions = ">=3.8"
321 | files = [
322 | {file = "filelock-3.13.1-py3-none-any.whl", hash = "sha256:57dbda9b35157b05fb3e58ee91448612eb674172fab98ee235ccb0b5bee19a1c"},
323 | {file = "filelock-3.13.1.tar.gz", hash = "sha256:521f5f56c50f8426f5e03ad3b281b490a87ef15bc6c526f168290f0c7148d44e"},
324 | ]
325 |
326 | [package.extras]
327 | docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.24)"]
328 | testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)"]
329 | typing = ["typing-extensions (>=4.8)"]
330 |
331 | [[package]]
332 | name = "ghp-import"
333 | version = "2.1.0"
334 | description = "Copy your docs directly to the gh-pages branch."
335 | optional = false
336 | python-versions = "*"
337 | files = [
338 | {file = "ghp-import-2.1.0.tar.gz", hash = "sha256:9c535c4c61193c2df8871222567d7fd7e5014d835f97dc7b7439069e2413d343"},
339 | {file = "ghp_import-2.1.0-py3-none-any.whl", hash = "sha256:8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619"},
340 | ]
341 |
342 | [package.dependencies]
343 | python-dateutil = ">=2.8.1"
344 |
345 | [package.extras]
346 | dev = ["flake8", "markdown", "twine", "wheel"]
347 |
348 | [[package]]
349 | name = "griffe"
350 | version = "0.38.0"
351 | description = "Signatures for entire Python programs. Extract the structure, the frame, the skeleton of your project, to generate API documentation or find breaking changes in your API."
352 | optional = false
353 | python-versions = ">=3.8"
354 | files = [
355 | {file = "griffe-0.38.0-py3-none-any.whl", hash = "sha256:6a5bc457320e8e199006aa5fbb03e162f5e21abe31aa6221f7a5c37ea0724c71"},
356 | {file = "griffe-0.38.0.tar.gz", hash = "sha256:9b97487b583042b543d1e28196caee638ecd766c8c4c98135071806cb5333ac2"},
357 | ]
358 |
359 | [package.dependencies]
360 | colorama = ">=0.4"
361 |
362 | [[package]]
363 | name = "h11"
364 | version = "0.14.0"
365 | description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1"
366 | optional = false
367 | python-versions = ">=3.7"
368 | files = [
369 | {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"},
370 | {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"},
371 | ]
372 |
373 | [[package]]
374 | name = "httpcore"
375 | version = "1.0.2"
376 | description = "A minimal low-level HTTP client."
377 | optional = false
378 | python-versions = ">=3.8"
379 | files = [
380 | {file = "httpcore-1.0.2-py3-none-any.whl", hash = "sha256:096cc05bca73b8e459a1fc3dcf585148f63e534eae4339559c9b8a8d6399acc7"},
381 | {file = "httpcore-1.0.2.tar.gz", hash = "sha256:9fc092e4799b26174648e54b74ed5f683132a464e95643b226e00c2ed2fa6535"},
382 | ]
383 |
384 | [package.dependencies]
385 | certifi = "*"
386 | h11 = ">=0.13,<0.15"
387 |
388 | [package.extras]
389 | asyncio = ["anyio (>=4.0,<5.0)"]
390 | http2 = ["h2 (>=3,<5)"]
391 | socks = ["socksio (==1.*)"]
392 | trio = ["trio (>=0.22.0,<0.23.0)"]
393 |
394 | [[package]]
395 | name = "httpx"
396 | version = "0.25.2"
397 | description = "The next generation HTTP client."
398 | optional = false
399 | python-versions = ">=3.8"
400 | files = [
401 | {file = "httpx-0.25.2-py3-none-any.whl", hash = "sha256:a05d3d052d9b2dfce0e3896636467f8a5342fb2b902c819428e1ac65413ca118"},
402 | {file = "httpx-0.25.2.tar.gz", hash = "sha256:8b8fcaa0c8ea7b05edd69a094e63a2094c4efcb48129fb757361bc423c0ad9e8"},
403 | ]
404 |
405 | [package.dependencies]
406 | anyio = "*"
407 | certifi = "*"
408 | httpcore = "==1.*"
409 | idna = "*"
410 | sniffio = "*"
411 |
412 | [package.extras]
413 | brotli = ["brotli", "brotlicffi"]
414 | cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"]
415 | http2 = ["h2 (>=3,<5)"]
416 | socks = ["socksio (==1.*)"]
417 |
418 | [[package]]
419 | name = "identify"
420 | version = "2.5.32"
421 | description = "File identification library for Python"
422 | optional = false
423 | python-versions = ">=3.8"
424 | files = [
425 | {file = "identify-2.5.32-py2.py3-none-any.whl", hash = "sha256:0b7656ef6cba81664b783352c73f8c24b39cf82f926f78f4550eda928e5e0545"},
426 | {file = "identify-2.5.32.tar.gz", hash = "sha256:5d9979348ec1a21c768ae07e0a652924538e8bce67313a73cb0f681cf08ba407"},
427 | ]
428 |
429 | [package.extras]
430 | license = ["ukkonen"]
431 |
432 | [[package]]
433 | name = "idna"
434 | version = "3.6"
435 | description = "Internationalized Domain Names in Applications (IDNA)"
436 | optional = false
437 | python-versions = ">=3.5"
438 | files = [
439 | {file = "idna-3.6-py3-none-any.whl", hash = "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f"},
440 | {file = "idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca"},
441 | ]
442 |
443 | [[package]]
444 | name = "importlib-metadata"
445 | version = "6.9.0"
446 | description = "Read metadata from Python packages"
447 | optional = false
448 | python-versions = ">=3.8"
449 | files = [
450 | {file = "importlib_metadata-6.9.0-py3-none-any.whl", hash = "sha256:1c8dc6839ddc9771412596926f24cb5a553bbd40624ee2c7e55e531542bed3b8"},
451 | {file = "importlib_metadata-6.9.0.tar.gz", hash = "sha256:e8acb523c335a91822674e149b46c0399ec4d328c4d1f6e49c273da5ff0201b9"},
452 | ]
453 |
454 | [package.dependencies]
455 | zipp = ">=0.5"
456 |
457 | [package.extras]
458 | docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"]
459 | perf = ["ipython"]
460 | testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)", "pytest-ruff"]
461 |
462 | [[package]]
463 | name = "importlib-resources"
464 | version = "6.1.1"
465 | description = "Read resources from Python packages"
466 | optional = false
467 | python-versions = ">=3.8"
468 | files = [
469 | {file = "importlib_resources-6.1.1-py3-none-any.whl", hash = "sha256:e8bf90d8213b486f428c9c39714b920041cb02c184686a3dee24905aaa8105d6"},
470 | {file = "importlib_resources-6.1.1.tar.gz", hash = "sha256:3893a00122eafde6894c59914446a512f728a0c1a45f9bb9b63721b6bacf0b4a"},
471 | ]
472 |
473 | [package.dependencies]
474 | zipp = {version = ">=3.1.0", markers = "python_version < \"3.10\""}
475 |
476 | [package.extras]
477 | docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"]
478 | testing = ["pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-ruff", "zipp (>=3.17)"]
479 |
480 | [[package]]
481 | name = "iniconfig"
482 | version = "2.0.0"
483 | description = "brain-dead simple config-ini parsing"
484 | optional = false
485 | python-versions = ">=3.7"
486 | files = [
487 | {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"},
488 | {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"},
489 | ]
490 |
491 | [[package]]
492 | name = "jinja2"
493 | version = "3.1.2"
494 | description = "A very fast and expressive template engine."
495 | optional = false
496 | python-versions = ">=3.7"
497 | files = [
498 | {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"},
499 | {file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"},
500 | ]
501 |
502 | [package.dependencies]
503 | MarkupSafe = ">=2.0"
504 |
505 | [package.extras]
506 | i18n = ["Babel (>=2.7)"]
507 |
508 | [[package]]
509 | name = "markdown"
510 | version = "3.5.1"
511 | description = "Python implementation of John Gruber's Markdown."
512 | optional = false
513 | python-versions = ">=3.8"
514 | files = [
515 | {file = "Markdown-3.5.1-py3-none-any.whl", hash = "sha256:5874b47d4ee3f0b14d764324d2c94c03ea66bee56f2d929da9f2508d65e722dc"},
516 | {file = "Markdown-3.5.1.tar.gz", hash = "sha256:b65d7beb248dc22f2e8a31fb706d93798093c308dc1aba295aedeb9d41a813bd"},
517 | ]
518 |
519 | [package.dependencies]
520 | importlib-metadata = {version = ">=4.4", markers = "python_version < \"3.10\""}
521 |
522 | [package.extras]
523 | docs = ["mdx-gh-links (>=0.2)", "mkdocs (>=1.5)", "mkdocs-gen-files", "mkdocs-literate-nav", "mkdocs-nature (>=0.6)", "mkdocs-section-index", "mkdocstrings[python]"]
524 | testing = ["coverage", "pyyaml"]
525 |
526 | [[package]]
527 | name = "markupsafe"
528 | version = "2.1.3"
529 | description = "Safely add untrusted strings to HTML/XML markup."
530 | optional = false
531 | python-versions = ">=3.7"
532 | files = [
533 | {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cd0f502fe016460680cd20aaa5a76d241d6f35a1c3350c474bac1273803893fa"},
534 | {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57"},
535 | {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f"},
536 | {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:65c1a9bcdadc6c28eecee2c119465aebff8f7a584dd719facdd9e825ec61ab52"},
537 | {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00"},
538 | {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6"},
539 | {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779"},
540 | {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c9c804664ebe8f83a211cace637506669e7890fec1b4195b505c214e50dd4eb7"},
541 | {file = "MarkupSafe-2.1.3-cp310-cp310-win32.whl", hash = "sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431"},
542 | {file = "MarkupSafe-2.1.3-cp310-cp310-win_amd64.whl", hash = "sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559"},
543 | {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c"},
544 | {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575"},
545 | {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b076b6226fb84157e3f7c971a47ff3a679d837cf338547532ab866c57930dbee"},
546 | {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bfce63a9e7834b12b87c64d6b155fdd9b3b96191b6bd334bf37db7ff1fe457f2"},
547 | {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:338ae27d6b8745585f87218a3f23f1512dbf52c26c28e322dbe54bcede54ccb9"},
548 | {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc"},
549 | {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9"},
550 | {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"},
551 | {file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"},
552 | {file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"},
553 | {file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"},
554 | {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"},
555 | {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"},
556 | {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca379055a47383d02a5400cb0d110cef0a776fc644cda797db0c5696cfd7e18e"},
557 | {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b7ff0f54cb4ff66dd38bebd335a38e2c22c41a8ee45aa608efc890ac3e3931bc"},
558 | {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c011a4149cfbcf9f03994ec2edffcb8b1dc2d2aede7ca243746df97a5d41ce48"},
559 | {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:56d9f2ecac662ca1611d183feb03a3fa4406469dafe241673d521dd5ae92a155"},
560 | {file = "MarkupSafe-2.1.3-cp37-cp37m-win32.whl", hash = "sha256:8758846a7e80910096950b67071243da3e5a20ed2546e6392603c096778d48e0"},
561 | {file = "MarkupSafe-2.1.3-cp37-cp37m-win_amd64.whl", hash = "sha256:787003c0ddb00500e49a10f2844fac87aa6ce977b90b0feaaf9de23c22508b24"},
562 | {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4"},
563 | {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0"},
564 | {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee"},
565 | {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c41976a29d078bb235fea9b2ecd3da465df42a562910f9022f1a03107bd02be"},
566 | {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d080e0a5eb2529460b30190fcfcc4199bd7f827663f858a226a81bc27beaa97e"},
567 | {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:69c0f17e9f5a7afdf2cc9fb2d1ce6aabdb3bafb7f38017c0b77862bcec2bbad8"},
568 | {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:504b320cd4b7eff6f968eddf81127112db685e81f7e36e75f9f84f0df46041c3"},
569 | {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:42de32b22b6b804f42c5d98be4f7e5e977ecdd9ee9b660fda1a3edf03b11792d"},
570 | {file = "MarkupSafe-2.1.3-cp38-cp38-win32.whl", hash = "sha256:ceb01949af7121f9fc39f7d27f91be8546f3fb112c608bc4029aef0bab86a2a5"},
571 | {file = "MarkupSafe-2.1.3-cp38-cp38-win_amd64.whl", hash = "sha256:1b40069d487e7edb2676d3fbdb2b0829ffa2cd63a2ec26c4938b2d34391b4ecc"},
572 | {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8023faf4e01efadfa183e863fefde0046de576c6f14659e8782065bcece22198"},
573 | {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6b2b56950d93e41f33b4223ead100ea0fe11f8e6ee5f641eb753ce4b77a7042b"},
574 | {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9dcdfd0eaf283af041973bff14a2e143b8bd64e069f4c383416ecd79a81aab58"},
575 | {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05fb21170423db021895e1ea1e1f3ab3adb85d1c2333cbc2310f2a26bc77272e"},
576 | {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:282c2cb35b5b673bbcadb33a585408104df04f14b2d9b01d4c345a3b92861c2c"},
577 | {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ab4a0df41e7c16a1392727727e7998a467472d0ad65f3ad5e6e765015df08636"},
578 | {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7ef3cb2ebbf91e330e3bb937efada0edd9003683db6b57bb108c4001f37a02ea"},
579 | {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e"},
580 | {file = "MarkupSafe-2.1.3-cp39-cp39-win32.whl", hash = "sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2"},
581 | {file = "MarkupSafe-2.1.3-cp39-cp39-win_amd64.whl", hash = "sha256:3fd4abcb888d15a94f32b75d8fd18ee162ca0c064f35b11134be77050296d6ba"},
582 | {file = "MarkupSafe-2.1.3.tar.gz", hash = "sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad"},
583 | ]
584 |
585 | [[package]]
586 | name = "mergedeep"
587 | version = "1.3.4"
588 | description = "A deep merge function for 🐍."
589 | optional = false
590 | python-versions = ">=3.6"
591 | files = [
592 | {file = "mergedeep-1.3.4-py3-none-any.whl", hash = "sha256:70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307"},
593 | {file = "mergedeep-1.3.4.tar.gz", hash = "sha256:0096d52e9dad9939c3d975a774666af186eda617e6ca84df4c94dec30004f2a8"},
594 | ]
595 |
596 | [[package]]
597 | name = "mkdocs"
598 | version = "1.5.3"
599 | description = "Project documentation with Markdown."
600 | optional = false
601 | python-versions = ">=3.7"
602 | files = [
603 | {file = "mkdocs-1.5.3-py3-none-any.whl", hash = "sha256:3b3a78e736b31158d64dbb2f8ba29bd46a379d0c6e324c2246c3bc3d2189cfc1"},
604 | {file = "mkdocs-1.5.3.tar.gz", hash = "sha256:eb7c99214dcb945313ba30426c2451b735992c73c2e10838f76d09e39ff4d0e2"},
605 | ]
606 |
607 | [package.dependencies]
608 | click = ">=7.0"
609 | colorama = {version = ">=0.4", markers = "platform_system == \"Windows\""}
610 | ghp-import = ">=1.0"
611 | importlib-metadata = {version = ">=4.3", markers = "python_version < \"3.10\""}
612 | jinja2 = ">=2.11.1"
613 | markdown = ">=3.2.1"
614 | markupsafe = ">=2.0.1"
615 | mergedeep = ">=1.3.4"
616 | packaging = ">=20.5"
617 | pathspec = ">=0.11.1"
618 | platformdirs = ">=2.2.0"
619 | pyyaml = ">=5.1"
620 | pyyaml-env-tag = ">=0.1"
621 | watchdog = ">=2.0"
622 |
623 | [package.extras]
624 | i18n = ["babel (>=2.9.0)"]
625 | min-versions = ["babel (==2.9.0)", "click (==7.0)", "colorama (==0.4)", "ghp-import (==1.0)", "importlib-metadata (==4.3)", "jinja2 (==2.11.1)", "markdown (==3.2.1)", "markupsafe (==2.0.1)", "mergedeep (==1.3.4)", "packaging (==20.5)", "pathspec (==0.11.1)", "platformdirs (==2.2.0)", "pyyaml (==5.1)", "pyyaml-env-tag (==0.1)", "typing-extensions (==3.10)", "watchdog (==2.0)"]
626 |
627 | [[package]]
628 | name = "mkdocs-autorefs"
629 | version = "0.5.0"
630 | description = "Automatically link across pages in MkDocs."
631 | optional = false
632 | python-versions = ">=3.8"
633 | files = [
634 | {file = "mkdocs_autorefs-0.5.0-py3-none-any.whl", hash = "sha256:7930fcb8ac1249f10e683967aeaddc0af49d90702af111a5e390e8b20b3d97ff"},
635 | {file = "mkdocs_autorefs-0.5.0.tar.gz", hash = "sha256:9a5054a94c08d28855cfab967ada10ed5be76e2bfad642302a610b252c3274c0"},
636 | ]
637 |
638 | [package.dependencies]
639 | Markdown = ">=3.3"
640 | mkdocs = ">=1.1"
641 |
642 | [[package]]
643 | name = "mkdocs-material"
644 | version = "9.4.14"
645 | description = "Documentation that simply works"
646 | optional = false
647 | python-versions = ">=3.8"
648 | files = [
649 | {file = "mkdocs_material-9.4.14-py3-none-any.whl", hash = "sha256:dbc78a4fea97b74319a6aa9a2f0be575a6028be6958f813ba367188f7b8428f6"},
650 | {file = "mkdocs_material-9.4.14.tar.gz", hash = "sha256:a511d3ff48fa8718b033e7e37d17abd9cc1de0fdf0244a625ca2ae2387e2416d"},
651 | ]
652 |
653 | [package.dependencies]
654 | babel = ">=2.10,<3.0"
655 | colorama = ">=0.4,<1.0"
656 | jinja2 = ">=3.0,<4.0"
657 | markdown = ">=3.2,<4.0"
658 | mkdocs = ">=1.5.3,<2.0"
659 | mkdocs-material-extensions = ">=1.3,<2.0"
660 | paginate = ">=0.5,<1.0"
661 | pygments = ">=2.16,<3.0"
662 | pymdown-extensions = ">=10.2,<11.0"
663 | regex = ">=2022.4"
664 | requests = ">=2.26,<3.0"
665 |
666 | [package.extras]
667 | git = ["mkdocs-git-committers-plugin-2 (>=1.1,<2.0)", "mkdocs-git-revision-date-localized-plugin (>=1.2,<2.0)"]
668 | imaging = ["cairosvg (>=2.6,<3.0)", "pillow (>=9.4,<10.0)"]
669 | recommended = ["mkdocs-minify-plugin (>=0.7,<1.0)", "mkdocs-redirects (>=1.2,<2.0)", "mkdocs-rss-plugin (>=1.6,<2.0)"]
670 |
671 | [[package]]
672 | name = "mkdocs-material-extensions"
673 | version = "1.3.1"
674 | description = "Extension pack for Python Markdown and MkDocs Material."
675 | optional = false
676 | python-versions = ">=3.8"
677 | files = [
678 | {file = "mkdocs_material_extensions-1.3.1-py3-none-any.whl", hash = "sha256:adff8b62700b25cb77b53358dad940f3ef973dd6db797907c49e3c2ef3ab4e31"},
679 | {file = "mkdocs_material_extensions-1.3.1.tar.gz", hash = "sha256:10c9511cea88f568257f960358a467d12b970e1f7b2c0e5fb2bb48cab1928443"},
680 | ]
681 |
682 | [[package]]
683 | name = "mkdocstrings"
684 | version = "0.23.0"
685 | description = "Automatic documentation from sources, for MkDocs."
686 | optional = false
687 | python-versions = ">=3.8"
688 | files = [
689 | {file = "mkdocstrings-0.23.0-py3-none-any.whl", hash = "sha256:051fa4014dfcd9ed90254ae91de2dbb4f24e166347dae7be9a997fe16316c65e"},
690 | {file = "mkdocstrings-0.23.0.tar.gz", hash = "sha256:d9c6a37ffbe7c14a7a54ef1258c70b8d394e6a33a1c80832bce40b9567138d1c"},
691 | ]
692 |
693 | [package.dependencies]
694 | importlib-metadata = {version = ">=4.6", markers = "python_version < \"3.10\""}
695 | Jinja2 = ">=2.11.1"
696 | Markdown = ">=3.3"
697 | MarkupSafe = ">=1.1"
698 | mkdocs = ">=1.2"
699 | mkdocs-autorefs = ">=0.3.1"
700 | mkdocstrings-python = {version = ">=0.5.2", optional = true, markers = "extra == \"python\""}
701 | pymdown-extensions = ">=6.3"
702 | typing-extensions = {version = ">=4.1", markers = "python_version < \"3.10\""}
703 |
704 | [package.extras]
705 | crystal = ["mkdocstrings-crystal (>=0.3.4)"]
706 | python = ["mkdocstrings-python (>=0.5.2)"]
707 | python-legacy = ["mkdocstrings-python-legacy (>=0.2.1)"]
708 |
709 | [[package]]
710 | name = "mkdocstrings-python"
711 | version = "1.7.5"
712 | description = "A Python handler for mkdocstrings."
713 | optional = false
714 | python-versions = ">=3.8"
715 | files = [
716 | {file = "mkdocstrings_python-1.7.5-py3-none-any.whl", hash = "sha256:5f6246026353f0c0785135db70c3fe9a5d9318990fc7ceb11d62097b8ffdd704"},
717 | {file = "mkdocstrings_python-1.7.5.tar.gz", hash = "sha256:c7d143728257dbf1aa550446555a554b760dcd40a763f077189d298502b800be"},
718 | ]
719 |
720 | [package.dependencies]
721 | griffe = ">=0.37"
722 | mkdocstrings = ">=0.20"
723 |
724 | [[package]]
725 | name = "mypy"
726 | version = "1.7.1"
727 | description = "Optional static typing for Python"
728 | optional = false
729 | python-versions = ">=3.8"
730 | files = [
731 | {file = "mypy-1.7.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:12cce78e329838d70a204293e7b29af9faa3ab14899aec397798a4b41be7f340"},
732 | {file = "mypy-1.7.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1484b8fa2c10adf4474f016e09d7a159602f3239075c7bf9f1627f5acf40ad49"},
733 | {file = "mypy-1.7.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:31902408f4bf54108bbfb2e35369877c01c95adc6192958684473658c322c8a5"},
734 | {file = "mypy-1.7.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f2c2521a8e4d6d769e3234350ba7b65ff5d527137cdcde13ff4d99114b0c8e7d"},
735 | {file = "mypy-1.7.1-cp310-cp310-win_amd64.whl", hash = "sha256:fcd2572dd4519e8a6642b733cd3a8cfc1ef94bafd0c1ceed9c94fe736cb65b6a"},
736 | {file = "mypy-1.7.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4b901927f16224d0d143b925ce9a4e6b3a758010673eeded9b748f250cf4e8f7"},
737 | {file = "mypy-1.7.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2f7f6985d05a4e3ce8255396df363046c28bea790e40617654e91ed580ca7c51"},
738 | {file = "mypy-1.7.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:944bdc21ebd620eafefc090cdf83158393ec2b1391578359776c00de00e8907a"},
739 | {file = "mypy-1.7.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9c7ac372232c928fff0645d85f273a726970c014749b924ce5710d7d89763a28"},
740 | {file = "mypy-1.7.1-cp311-cp311-win_amd64.whl", hash = "sha256:f6efc9bd72258f89a3816e3a98c09d36f079c223aa345c659622f056b760ab42"},
741 | {file = "mypy-1.7.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:6dbdec441c60699288adf051f51a5d512b0d818526d1dcfff5a41f8cd8b4aaf1"},
742 | {file = "mypy-1.7.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4fc3d14ee80cd22367caaaf6e014494415bf440980a3045bf5045b525680ac33"},
743 | {file = "mypy-1.7.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c6e4464ed5f01dc44dc9821caf67b60a4e5c3b04278286a85c067010653a0eb"},
744 | {file = "mypy-1.7.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:d9b338c19fa2412f76e17525c1b4f2c687a55b156320acb588df79f2e6fa9fea"},
745 | {file = "mypy-1.7.1-cp312-cp312-win_amd64.whl", hash = "sha256:204e0d6de5fd2317394a4eff62065614c4892d5a4d1a7ee55b765d7a3d9e3f82"},
746 | {file = "mypy-1.7.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:84860e06ba363d9c0eeabd45ac0fde4b903ad7aa4f93cd8b648385a888e23200"},
747 | {file = "mypy-1.7.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8c5091ebd294f7628eb25ea554852a52058ac81472c921150e3a61cdd68f75a7"},
748 | {file = "mypy-1.7.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40716d1f821b89838589e5b3106ebbc23636ffdef5abc31f7cd0266db936067e"},
749 | {file = "mypy-1.7.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5cf3f0c5ac72139797953bd50bc6c95ac13075e62dbfcc923571180bebb662e9"},
750 | {file = "mypy-1.7.1-cp38-cp38-win_amd64.whl", hash = "sha256:78e25b2fd6cbb55ddfb8058417df193f0129cad5f4ee75d1502248e588d9e0d7"},
751 | {file = "mypy-1.7.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:75c4d2a6effd015786c87774e04331b6da863fc3fc4e8adfc3b40aa55ab516fe"},
752 | {file = "mypy-1.7.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2643d145af5292ee956aa0a83c2ce1038a3bdb26e033dadeb2f7066fb0c9abce"},
753 | {file = "mypy-1.7.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75aa828610b67462ffe3057d4d8a4112105ed211596b750b53cbfe182f44777a"},
754 | {file = "mypy-1.7.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ee5d62d28b854eb61889cde4e1dbc10fbaa5560cb39780c3995f6737f7e82120"},
755 | {file = "mypy-1.7.1-cp39-cp39-win_amd64.whl", hash = "sha256:72cf32ce7dd3562373f78bd751f73c96cfb441de147cc2448a92c1a308bd0ca6"},
756 | {file = "mypy-1.7.1-py3-none-any.whl", hash = "sha256:f7c5d642db47376a0cc130f0de6d055056e010debdaf0707cd2b0fc7e7ef30ea"},
757 | {file = "mypy-1.7.1.tar.gz", hash = "sha256:fcb6d9afb1b6208b4c712af0dafdc650f518836065df0d4fb1d800f5d6773db2"},
758 | ]
759 |
760 | [package.dependencies]
761 | mypy-extensions = ">=1.0.0"
762 | tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
763 | typing-extensions = ">=4.1.0"
764 |
765 | [package.extras]
766 | dmypy = ["psutil (>=4.0)"]
767 | install-types = ["pip"]
768 | mypyc = ["setuptools (>=50)"]
769 | reports = ["lxml"]
770 |
771 | [[package]]
772 | name = "mypy-extensions"
773 | version = "1.0.0"
774 | description = "Type system extensions for programs checked with the mypy type checker."
775 | optional = false
776 | python-versions = ">=3.5"
777 | files = [
778 | {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"},
779 | {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"},
780 | ]
781 |
782 | [[package]]
783 | name = "nodeenv"
784 | version = "1.8.0"
785 | description = "Node.js virtual environment builder"
786 | optional = false
787 | python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*"
788 | files = [
789 | {file = "nodeenv-1.8.0-py2.py3-none-any.whl", hash = "sha256:df865724bb3c3adc86b3876fa209771517b0cfe596beff01a92700e0e8be4cec"},
790 | {file = "nodeenv-1.8.0.tar.gz", hash = "sha256:d51e0c37e64fbf47d017feac3145cdbb58836d7eee8c6f6d3b6880c5456227d2"},
791 | ]
792 |
793 | [package.dependencies]
794 | setuptools = "*"
795 |
796 | [[package]]
797 | name = "packaging"
798 | version = "23.2"
799 | description = "Core utilities for Python packages"
800 | optional = false
801 | python-versions = ">=3.7"
802 | files = [
803 | {file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"},
804 | {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"},
805 | ]
806 |
807 | [[package]]
808 | name = "paginate"
809 | version = "0.5.6"
810 | description = "Divides large result sets into pages for easier browsing"
811 | optional = false
812 | python-versions = "*"
813 | files = [
814 | {file = "paginate-0.5.6.tar.gz", hash = "sha256:5e6007b6a9398177a7e1648d04fdd9f8c9766a1a945bceac82f1929e8c78af2d"},
815 | ]
816 |
817 | [[package]]
818 | name = "pathspec"
819 | version = "0.11.2"
820 | description = "Utility library for gitignore style pattern matching of file paths."
821 | optional = false
822 | python-versions = ">=3.7"
823 | files = [
824 | {file = "pathspec-0.11.2-py3-none-any.whl", hash = "sha256:1d6ed233af05e679efb96b1851550ea95bbb64b7c490b0f5aa52996c11e92a20"},
825 | {file = "pathspec-0.11.2.tar.gz", hash = "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3"},
826 | ]
827 |
828 | [[package]]
829 | name = "platformdirs"
830 | version = "4.0.0"
831 | description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
832 | optional = false
833 | python-versions = ">=3.7"
834 | files = [
835 | {file = "platformdirs-4.0.0-py3-none-any.whl", hash = "sha256:118c954d7e949b35437270383a3f2531e99dd93cf7ce4dc8340d3356d30f173b"},
836 | {file = "platformdirs-4.0.0.tar.gz", hash = "sha256:cb633b2bcf10c51af60beb0ab06d2f1d69064b43abf4c185ca6b28865f3f9731"},
837 | ]
838 |
839 | [package.extras]
840 | docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.1)", "sphinx-autodoc-typehints (>=1.24)"]
841 | test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)"]
842 |
843 | [[package]]
844 | name = "pluggy"
845 | version = "1.3.0"
846 | description = "plugin and hook calling mechanisms for python"
847 | optional = false
848 | python-versions = ">=3.8"
849 | files = [
850 | {file = "pluggy-1.3.0-py3-none-any.whl", hash = "sha256:d89c696a773f8bd377d18e5ecda92b7a3793cbe66c87060a6fb58c7b6e1061f7"},
851 | {file = "pluggy-1.3.0.tar.gz", hash = "sha256:cf61ae8f126ac6f7c451172cf30e3e43d3ca77615509771b3a984a0730651e12"},
852 | ]
853 |
854 | [package.extras]
855 | dev = ["pre-commit", "tox"]
856 | testing = ["pytest", "pytest-benchmark"]
857 |
858 | [[package]]
859 | name = "pre-commit"
860 | version = "3.5.0"
861 | description = "A framework for managing and maintaining multi-language pre-commit hooks."
862 | optional = false
863 | python-versions = ">=3.8"
864 | files = [
865 | {file = "pre_commit-3.5.0-py2.py3-none-any.whl", hash = "sha256:841dc9aef25daba9a0238cd27984041fa0467b4199fc4852e27950664919f660"},
866 | {file = "pre_commit-3.5.0.tar.gz", hash = "sha256:5804465c675b659b0862f07907f96295d490822a450c4c40e747d0b1c6ebcb32"},
867 | ]
868 |
869 | [package.dependencies]
870 | cfgv = ">=2.0.0"
871 | identify = ">=1.0.0"
872 | nodeenv = ">=0.11.1"
873 | pyyaml = ">=5.1"
874 | virtualenv = ">=20.10.0"
875 |
876 | [[package]]
877 | name = "pygments"
878 | version = "2.17.2"
879 | description = "Pygments is a syntax highlighting package written in Python."
880 | optional = false
881 | python-versions = ">=3.7"
882 | files = [
883 | {file = "pygments-2.17.2-py3-none-any.whl", hash = "sha256:b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c"},
884 | {file = "pygments-2.17.2.tar.gz", hash = "sha256:da46cec9fd2de5be3a8a784f434e4c4ab670b4ff54d605c4c2717e9d49c4c367"},
885 | ]
886 |
887 | [package.extras]
888 | plugins = ["importlib-metadata"]
889 | windows-terminal = ["colorama (>=0.4.6)"]
890 |
891 | [[package]]
892 | name = "pymdown-extensions"
893 | version = "10.5"
894 | description = "Extension pack for Python Markdown."
895 | optional = false
896 | python-versions = ">=3.8"
897 | files = [
898 | {file = "pymdown_extensions-10.5-py3-none-any.whl", hash = "sha256:1f0ca8bb5beff091315f793ee17683bc1390731f6ac4c5eb01e27464b80fe879"},
899 | {file = "pymdown_extensions-10.5.tar.gz", hash = "sha256:1b60f1e462adbec5a1ed79dac91f666c9c0d241fa294de1989f29d20096cfd0b"},
900 | ]
901 |
902 | [package.dependencies]
903 | markdown = ">=3.5"
904 | pyyaml = "*"
905 |
906 | [package.extras]
907 | extra = ["pygments (>=2.12)"]
908 |
909 | [[package]]
910 | name = "pyproject-api"
911 | version = "1.6.1"
912 | description = "API to interact with the python pyproject.toml based projects"
913 | optional = false
914 | python-versions = ">=3.8"
915 | files = [
916 | {file = "pyproject_api-1.6.1-py3-none-any.whl", hash = "sha256:4c0116d60476b0786c88692cf4e325a9814965e2469c5998b830bba16b183675"},
917 | {file = "pyproject_api-1.6.1.tar.gz", hash = "sha256:1817dc018adc0d1ff9ca1ed8c60e1623d5aaca40814b953af14a9cf9a5cae538"},
918 | ]
919 |
920 | [package.dependencies]
921 | packaging = ">=23.1"
922 | tomli = {version = ">=2.0.1", markers = "python_version < \"3.11\""}
923 |
924 | [package.extras]
925 | docs = ["furo (>=2023.8.19)", "sphinx (<7.2)", "sphinx-autodoc-typehints (>=1.24)"]
926 | testing = ["covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)", "setuptools (>=68.1.2)", "wheel (>=0.41.2)"]
927 |
928 | [[package]]
929 | name = "pytest"
930 | version = "7.4.3"
931 | description = "pytest: simple powerful testing with Python"
932 | optional = false
933 | python-versions = ">=3.7"
934 | files = [
935 | {file = "pytest-7.4.3-py3-none-any.whl", hash = "sha256:0d009c083ea859a71b76adf7c1d502e4bc170b80a8ef002da5806527b9591fac"},
936 | {file = "pytest-7.4.3.tar.gz", hash = "sha256:d989d136982de4e3b29dabcc838ad581c64e8ed52c11fbe86ddebd9da0818cd5"},
937 | ]
938 |
939 | [package.dependencies]
940 | colorama = {version = "*", markers = "sys_platform == \"win32\""}
941 | exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""}
942 | iniconfig = "*"
943 | packaging = "*"
944 | pluggy = ">=0.12,<2.0"
945 | tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""}
946 |
947 | [package.extras]
948 | testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"]
949 |
950 | [[package]]
951 | name = "pytest-asyncio"
952 | version = "0.21.1"
953 | description = "Pytest support for asyncio"
954 | optional = false
955 | python-versions = ">=3.7"
956 | files = [
957 | {file = "pytest-asyncio-0.21.1.tar.gz", hash = "sha256:40a7eae6dded22c7b604986855ea48400ab15b069ae38116e8c01238e9eeb64d"},
958 | {file = "pytest_asyncio-0.21.1-py3-none-any.whl", hash = "sha256:8666c1c8ac02631d7c51ba282e0c69a8a452b211ffedf2599099845da5c5c37b"},
959 | ]
960 |
961 | [package.dependencies]
962 | pytest = ">=7.0.0"
963 |
964 | [package.extras]
965 | docs = ["sphinx (>=5.3)", "sphinx-rtd-theme (>=1.0)"]
966 | testing = ["coverage (>=6.2)", "flaky (>=3.5.0)", "hypothesis (>=5.7.1)", "mypy (>=0.931)", "pytest-trio (>=0.7.0)"]
967 |
968 | [[package]]
969 | name = "pytest-cov"
970 | version = "4.1.0"
971 | description = "Pytest plugin for measuring coverage."
972 | optional = false
973 | python-versions = ">=3.7"
974 | files = [
975 | {file = "pytest-cov-4.1.0.tar.gz", hash = "sha256:3904b13dfbfec47f003b8e77fd5b589cd11904a21ddf1ab38a64f204d6a10ef6"},
976 | {file = "pytest_cov-4.1.0-py3-none-any.whl", hash = "sha256:6ba70b9e97e69fcc3fb45bfeab2d0a138fb65c4d0d6a41ef33983ad114be8c3a"},
977 | ]
978 |
979 | [package.dependencies]
980 | coverage = {version = ">=5.2.1", extras = ["toml"]}
981 | pytest = ">=4.6"
982 |
983 | [package.extras]
984 | testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtualenv"]
985 |
986 | [[package]]
987 | name = "python-dateutil"
988 | version = "2.8.2"
989 | description = "Extensions to the standard Python datetime module"
990 | optional = false
991 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
992 | files = [
993 | {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"},
994 | {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"},
995 | ]
996 |
997 | [package.dependencies]
998 | six = ">=1.5"
999 |
1000 | [[package]]
1001 | name = "pyyaml"
1002 | version = "6.0.1"
1003 | description = "YAML parser and emitter for Python"
1004 | optional = false
1005 | python-versions = ">=3.6"
1006 | files = [
1007 | {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"},
1008 | {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"},
1009 | {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"},
1010 | {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"},
1011 | {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"},
1012 | {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"},
1013 | {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"},
1014 | {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"},
1015 | {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"},
1016 | {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"},
1017 | {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"},
1018 | {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"},
1019 | {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"},
1020 | {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"},
1021 | {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"},
1022 | {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"},
1023 | {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"},
1024 | {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"},
1025 | {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"},
1026 | {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"},
1027 | {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"},
1028 | {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"},
1029 | {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"},
1030 | {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"},
1031 | {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"},
1032 | {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"},
1033 | {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"},
1034 | {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"},
1035 | {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"},
1036 | {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"},
1037 | {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"},
1038 | {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"},
1039 | {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"},
1040 | {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"},
1041 | {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"},
1042 | {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"},
1043 | {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"},
1044 | {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"},
1045 | {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"},
1046 | {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"},
1047 | ]
1048 |
1049 | [[package]]
1050 | name = "pyyaml-env-tag"
1051 | version = "0.1"
1052 | description = "A custom YAML tag for referencing environment variables in YAML files. "
1053 | optional = false
1054 | python-versions = ">=3.6"
1055 | files = [
1056 | {file = "pyyaml_env_tag-0.1-py3-none-any.whl", hash = "sha256:af31106dec8a4d68c60207c1886031cbf839b68aa7abccdb19868200532c2069"},
1057 | {file = "pyyaml_env_tag-0.1.tar.gz", hash = "sha256:70092675bda14fdec33b31ba77e7543de9ddc88f2e5b99160396572d11525bdb"},
1058 | ]
1059 |
1060 | [package.dependencies]
1061 | pyyaml = "*"
1062 |
1063 | [[package]]
1064 | name = "regex"
1065 | version = "2023.10.3"
1066 | description = "Alternative regular expression module, to replace re."
1067 | optional = false
1068 | python-versions = ">=3.7"
1069 | files = [
1070 | {file = "regex-2023.10.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4c34d4f73ea738223a094d8e0ffd6d2c1a1b4c175da34d6b0de3d8d69bee6bcc"},
1071 | {file = "regex-2023.10.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a8f4e49fc3ce020f65411432183e6775f24e02dff617281094ba6ab079ef0915"},
1072 | {file = "regex-2023.10.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4cd1bccf99d3ef1ab6ba835308ad85be040e6a11b0977ef7ea8c8005f01a3c29"},
1073 | {file = "regex-2023.10.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:81dce2ddc9f6e8f543d94b05d56e70d03a0774d32f6cca53e978dc01e4fc75b8"},
1074 | {file = "regex-2023.10.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c6b4d23c04831e3ab61717a707a5d763b300213db49ca680edf8bf13ab5d91b"},
1075 | {file = "regex-2023.10.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c15ad0aee158a15e17e0495e1e18741573d04eb6da06d8b84af726cfc1ed02ee"},
1076 | {file = "regex-2023.10.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6239d4e2e0b52c8bd38c51b760cd870069f0bdf99700a62cd509d7a031749a55"},
1077 | {file = "regex-2023.10.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:4a8bf76e3182797c6b1afa5b822d1d5802ff30284abe4599e1247be4fd6b03be"},
1078 | {file = "regex-2023.10.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d9c727bbcf0065cbb20f39d2b4f932f8fa1631c3e01fcedc979bd4f51fe051c5"},
1079 | {file = "regex-2023.10.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:3ccf2716add72f80714b9a63899b67fa711b654be3fcdd34fa391d2d274ce767"},
1080 | {file = "regex-2023.10.3-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:107ac60d1bfdc3edb53be75e2a52aff7481b92817cfdddd9b4519ccf0e54a6ff"},
1081 | {file = "regex-2023.10.3-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:00ba3c9818e33f1fa974693fb55d24cdc8ebafcb2e4207680669d8f8d7cca79a"},
1082 | {file = "regex-2023.10.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f0a47efb1dbef13af9c9a54a94a0b814902e547b7f21acb29434504d18f36e3a"},
1083 | {file = "regex-2023.10.3-cp310-cp310-win32.whl", hash = "sha256:36362386b813fa6c9146da6149a001b7bd063dabc4d49522a1f7aa65b725c7ec"},
1084 | {file = "regex-2023.10.3-cp310-cp310-win_amd64.whl", hash = "sha256:c65a3b5330b54103e7d21cac3f6bf3900d46f6d50138d73343d9e5b2900b2353"},
1085 | {file = "regex-2023.10.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:90a79bce019c442604662d17bf69df99090e24cdc6ad95b18b6725c2988a490e"},
1086 | {file = "regex-2023.10.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c7964c2183c3e6cce3f497e3a9f49d182e969f2dc3aeeadfa18945ff7bdd7051"},
1087 | {file = "regex-2023.10.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ef80829117a8061f974b2fda8ec799717242353bff55f8a29411794d635d964"},
1088 | {file = "regex-2023.10.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5addc9d0209a9afca5fc070f93b726bf7003bd63a427f65ef797a931782e7edc"},
1089 | {file = "regex-2023.10.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c148bec483cc4b421562b4bcedb8e28a3b84fcc8f0aa4418e10898f3c2c0eb9b"},
1090 | {file = "regex-2023.10.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d1f21af4c1539051049796a0f50aa342f9a27cde57318f2fc41ed50b0dbc4ac"},
1091 | {file = "regex-2023.10.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0b9ac09853b2a3e0d0082104036579809679e7715671cfbf89d83c1cb2a30f58"},
1092 | {file = "regex-2023.10.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ebedc192abbc7fd13c5ee800e83a6df252bec691eb2c4bedc9f8b2e2903f5e2a"},
1093 | {file = "regex-2023.10.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:d8a993c0a0ffd5f2d3bda23d0cd75e7086736f8f8268de8a82fbc4bd0ac6791e"},
1094 | {file = "regex-2023.10.3-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:be6b7b8d42d3090b6c80793524fa66c57ad7ee3fe9722b258aec6d0672543fd0"},
1095 | {file = "regex-2023.10.3-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4023e2efc35a30e66e938de5aef42b520c20e7eda7bb5fb12c35e5d09a4c43f6"},
1096 | {file = "regex-2023.10.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0d47840dc05e0ba04fe2e26f15126de7c755496d5a8aae4a08bda4dd8d646c54"},
1097 | {file = "regex-2023.10.3-cp311-cp311-win32.whl", hash = "sha256:9145f092b5d1977ec8c0ab46e7b3381b2fd069957b9862a43bd383e5c01d18c2"},
1098 | {file = "regex-2023.10.3-cp311-cp311-win_amd64.whl", hash = "sha256:b6104f9a46bd8743e4f738afef69b153c4b8b592d35ae46db07fc28ae3d5fb7c"},
1099 | {file = "regex-2023.10.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:bff507ae210371d4b1fe316d03433ac099f184d570a1a611e541923f78f05037"},
1100 | {file = "regex-2023.10.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:be5e22bbb67924dea15039c3282fa4cc6cdfbe0cbbd1c0515f9223186fc2ec5f"},
1101 | {file = "regex-2023.10.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4a992f702c9be9c72fa46f01ca6e18d131906a7180950958f766c2aa294d4b41"},
1102 | {file = "regex-2023.10.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7434a61b158be563c1362d9071358f8ab91b8d928728cd2882af060481244c9e"},
1103 | {file = "regex-2023.10.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c2169b2dcabf4e608416f7f9468737583ce5f0a6e8677c4efbf795ce81109d7c"},
1104 | {file = "regex-2023.10.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9e908ef5889cda4de038892b9accc36d33d72fb3e12c747e2799a0e806ec841"},
1105 | {file = "regex-2023.10.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:12bd4bc2c632742c7ce20db48e0d99afdc05e03f0b4c1af90542e05b809a03d9"},
1106 | {file = "regex-2023.10.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:bc72c231f5449d86d6c7d9cc7cd819b6eb30134bb770b8cfdc0765e48ef9c420"},
1107 | {file = "regex-2023.10.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bce8814b076f0ce5766dc87d5a056b0e9437b8e0cd351b9a6c4e1134a7dfbda9"},
1108 | {file = "regex-2023.10.3-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:ba7cd6dc4d585ea544c1412019921570ebd8a597fabf475acc4528210d7c4a6f"},
1109 | {file = "regex-2023.10.3-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b0c7d2f698e83f15228ba41c135501cfe7d5740181d5903e250e47f617eb4292"},
1110 | {file = "regex-2023.10.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5a8f91c64f390ecee09ff793319f30a0f32492e99f5dc1c72bc361f23ccd0a9a"},
1111 | {file = "regex-2023.10.3-cp312-cp312-win32.whl", hash = "sha256:ad08a69728ff3c79866d729b095872afe1e0557251da4abb2c5faff15a91d19a"},
1112 | {file = "regex-2023.10.3-cp312-cp312-win_amd64.whl", hash = "sha256:39cdf8d141d6d44e8d5a12a8569d5a227f645c87df4f92179bd06e2e2705e76b"},
1113 | {file = "regex-2023.10.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:4a3ee019a9befe84fa3e917a2dd378807e423d013377a884c1970a3c2792d293"},
1114 | {file = "regex-2023.10.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76066d7ff61ba6bf3cb5efe2428fc82aac91802844c022d849a1f0f53820502d"},
1115 | {file = "regex-2023.10.3-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bfe50b61bab1b1ec260fa7cd91106fa9fece57e6beba05630afe27c71259c59b"},
1116 | {file = "regex-2023.10.3-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fd88f373cb71e6b59b7fa597e47e518282455c2734fd4306a05ca219a1991b0"},
1117 | {file = "regex-2023.10.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b3ab05a182c7937fb374f7e946f04fb23a0c0699c0450e9fb02ef567412d2fa3"},
1118 | {file = "regex-2023.10.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dac37cf08fcf2094159922edc7a2784cfcc5c70f8354469f79ed085f0328ebdf"},
1119 | {file = "regex-2023.10.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e54ddd0bb8fb626aa1f9ba7b36629564544954fff9669b15da3610c22b9a0991"},
1120 | {file = "regex-2023.10.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:3367007ad1951fde612bf65b0dffc8fd681a4ab98ac86957d16491400d661302"},
1121 | {file = "regex-2023.10.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:16f8740eb6dbacc7113e3097b0a36065a02e37b47c936b551805d40340fb9971"},
1122 | {file = "regex-2023.10.3-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:f4f2ca6df64cbdd27f27b34f35adb640b5d2d77264228554e68deda54456eb11"},
1123 | {file = "regex-2023.10.3-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:39807cbcbe406efca2a233884e169d056c35aa7e9f343d4e78665246a332f597"},
1124 | {file = "regex-2023.10.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:7eece6fbd3eae4a92d7c748ae825cbc1ee41a89bb1c3db05b5578ed3cfcfd7cb"},
1125 | {file = "regex-2023.10.3-cp37-cp37m-win32.whl", hash = "sha256:ce615c92d90df8373d9e13acddd154152645c0dc060871abf6bd43809673d20a"},
1126 | {file = "regex-2023.10.3-cp37-cp37m-win_amd64.whl", hash = "sha256:0f649fa32fe734c4abdfd4edbb8381c74abf5f34bc0b3271ce687b23729299ed"},
1127 | {file = "regex-2023.10.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9b98b7681a9437262947f41c7fac567c7e1f6eddd94b0483596d320092004533"},
1128 | {file = "regex-2023.10.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:91dc1d531f80c862441d7b66c4505cd6ea9d312f01fb2f4654f40c6fdf5cc37a"},
1129 | {file = "regex-2023.10.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82fcc1f1cc3ff1ab8a57ba619b149b907072e750815c5ba63e7aa2e1163384a4"},
1130 | {file = "regex-2023.10.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7979b834ec7a33aafae34a90aad9f914c41fd6eaa8474e66953f3f6f7cbd4368"},
1131 | {file = "regex-2023.10.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ef71561f82a89af6cfcbee47f0fabfdb6e63788a9258e913955d89fdd96902ab"},
1132 | {file = "regex-2023.10.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd829712de97753367153ed84f2de752b86cd1f7a88b55a3a775eb52eafe8a94"},
1133 | {file = "regex-2023.10.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:00e871d83a45eee2f8688d7e6849609c2ca2a04a6d48fba3dff4deef35d14f07"},
1134 | {file = "regex-2023.10.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:706e7b739fdd17cb89e1fbf712d9dc21311fc2333f6d435eac2d4ee81985098c"},
1135 | {file = "regex-2023.10.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:cc3f1c053b73f20c7ad88b0d1d23be7e7b3901229ce89f5000a8399746a6e039"},
1136 | {file = "regex-2023.10.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:6f85739e80d13644b981a88f529d79c5bdf646b460ba190bffcaf6d57b2a9863"},
1137 | {file = "regex-2023.10.3-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:741ba2f511cc9626b7561a440f87d658aabb3d6b744a86a3c025f866b4d19e7f"},
1138 | {file = "regex-2023.10.3-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:e77c90ab5997e85901da85131fd36acd0ed2221368199b65f0d11bca44549711"},
1139 | {file = "regex-2023.10.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:979c24cbefaf2420c4e377ecd1f165ea08cc3d1fbb44bdc51bccbbf7c66a2cb4"},
1140 | {file = "regex-2023.10.3-cp38-cp38-win32.whl", hash = "sha256:58837f9d221744d4c92d2cf7201c6acd19623b50c643b56992cbd2b745485d3d"},
1141 | {file = "regex-2023.10.3-cp38-cp38-win_amd64.whl", hash = "sha256:c55853684fe08d4897c37dfc5faeff70607a5f1806c8be148f1695be4a63414b"},
1142 | {file = "regex-2023.10.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2c54e23836650bdf2c18222c87f6f840d4943944146ca479858404fedeb9f9af"},
1143 | {file = "regex-2023.10.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:69c0771ca5653c7d4b65203cbfc5e66db9375f1078689459fe196fe08b7b4930"},
1144 | {file = "regex-2023.10.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ac965a998e1388e6ff2e9781f499ad1eaa41e962a40d11c7823c9952c77123e"},
1145 | {file = "regex-2023.10.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1c0e8fae5b27caa34177bdfa5a960c46ff2f78ee2d45c6db15ae3f64ecadde14"},
1146 | {file = "regex-2023.10.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6c56c3d47da04f921b73ff9415fbaa939f684d47293f071aa9cbb13c94afc17d"},
1147 | {file = "regex-2023.10.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ef1e014eed78ab650bef9a6a9cbe50b052c0aebe553fb2881e0453717573f52"},
1148 | {file = "regex-2023.10.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d29338556a59423d9ff7b6eb0cb89ead2b0875e08fe522f3e068b955c3e7b59b"},
1149 | {file = "regex-2023.10.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:9c6d0ced3c06d0f183b73d3c5920727268d2201aa0fe6d55c60d68c792ff3588"},
1150 | {file = "regex-2023.10.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:994645a46c6a740ee8ce8df7911d4aee458d9b1bc5639bc968226763d07f00fa"},
1151 | {file = "regex-2023.10.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:66e2fe786ef28da2b28e222c89502b2af984858091675044d93cb50e6f46d7af"},
1152 | {file = "regex-2023.10.3-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:11175910f62b2b8c055f2b089e0fedd694fe2be3941b3e2633653bc51064c528"},
1153 | {file = "regex-2023.10.3-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:06e9abc0e4c9ab4779c74ad99c3fc10d3967d03114449acc2c2762ad4472b8ca"},
1154 | {file = "regex-2023.10.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:fb02e4257376ae25c6dd95a5aec377f9b18c09be6ebdefa7ad209b9137b73d48"},
1155 | {file = "regex-2023.10.3-cp39-cp39-win32.whl", hash = "sha256:3b2c3502603fab52d7619b882c25a6850b766ebd1b18de3df23b2f939360e1bd"},
1156 | {file = "regex-2023.10.3-cp39-cp39-win_amd64.whl", hash = "sha256:adbccd17dcaff65704c856bd29951c58a1bd4b2b0f8ad6b826dbd543fe740988"},
1157 | {file = "regex-2023.10.3.tar.gz", hash = "sha256:3fef4f844d2290ee0ba57addcec17eec9e3df73f10a2748485dfd6a3a188cc0f"},
1158 | ]
1159 |
1160 | [[package]]
1161 | name = "requests"
1162 | version = "2.31.0"
1163 | description = "Python HTTP for Humans."
1164 | optional = false
1165 | python-versions = ">=3.7"
1166 | files = [
1167 | {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"},
1168 | {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"},
1169 | ]
1170 |
1171 | [package.dependencies]
1172 | certifi = ">=2017.4.17"
1173 | charset-normalizer = ">=2,<4"
1174 | idna = ">=2.5,<4"
1175 | urllib3 = ">=1.21.1,<3"
1176 |
1177 | [package.extras]
1178 | socks = ["PySocks (>=1.5.6,!=1.5.7)"]
1179 | use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
1180 |
1181 | [[package]]
1182 | name = "setuptools"
1183 | version = "69.0.2"
1184 | description = "Easily download, build, install, upgrade, and uninstall Python packages"
1185 | optional = false
1186 | python-versions = ">=3.8"
1187 | files = [
1188 | {file = "setuptools-69.0.2-py3-none-any.whl", hash = "sha256:1e8fdff6797d3865f37397be788a4e3cba233608e9b509382a2777d25ebde7f2"},
1189 | {file = "setuptools-69.0.2.tar.gz", hash = "sha256:735896e78a4742605974de002ac60562d286fa8051a7e2299445e8e8fbb01aa6"},
1190 | ]
1191 |
1192 | [package.extras]
1193 | docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"]
1194 | testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
1195 | testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.1)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"]
1196 |
1197 | [[package]]
1198 | name = "six"
1199 | version = "1.16.0"
1200 | description = "Python 2 and 3 compatibility utilities"
1201 | optional = false
1202 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
1203 | files = [
1204 | {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
1205 | {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
1206 | ]
1207 |
1208 | [[package]]
1209 | name = "sniffio"
1210 | version = "1.3.0"
1211 | description = "Sniff out which async library your code is running under"
1212 | optional = false
1213 | python-versions = ">=3.7"
1214 | files = [
1215 | {file = "sniffio-1.3.0-py3-none-any.whl", hash = "sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384"},
1216 | {file = "sniffio-1.3.0.tar.gz", hash = "sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101"},
1217 | ]
1218 |
1219 | [[package]]
1220 | name = "tomli"
1221 | version = "2.0.1"
1222 | description = "A lil' TOML parser"
1223 | optional = false
1224 | python-versions = ">=3.7"
1225 | files = [
1226 | {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
1227 | {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
1228 | ]
1229 |
1230 | [[package]]
1231 | name = "tox"
1232 | version = "4.11.4"
1233 | description = "tox is a generic virtualenv management and test command line tool"
1234 | optional = false
1235 | python-versions = ">=3.8"
1236 | files = [
1237 | {file = "tox-4.11.4-py3-none-any.whl", hash = "sha256:2adb83d68f27116812b69aa36676a8d6a52249cb0d173649de0e7d0c2e3e7229"},
1238 | {file = "tox-4.11.4.tar.gz", hash = "sha256:73a7240778fabf305aeb05ab8ea26e575e042ab5a18d71d0ed13e343a51d6ce1"},
1239 | ]
1240 |
1241 | [package.dependencies]
1242 | cachetools = ">=5.3.1"
1243 | chardet = ">=5.2"
1244 | colorama = ">=0.4.6"
1245 | filelock = ">=3.12.3"
1246 | packaging = ">=23.1"
1247 | platformdirs = ">=3.10"
1248 | pluggy = ">=1.3"
1249 | pyproject-api = ">=1.6.1"
1250 | tomli = {version = ">=2.0.1", markers = "python_version < \"3.11\""}
1251 | virtualenv = ">=20.24.3"
1252 |
1253 | [package.extras]
1254 | docs = ["furo (>=2023.8.19)", "sphinx (>=7.2.4)", "sphinx-argparse-cli (>=1.11.1)", "sphinx-autodoc-typehints (>=1.24)", "sphinx-copybutton (>=0.5.2)", "sphinx-inline-tabs (>=2023.4.21)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"]
1255 | testing = ["build[virtualenv] (>=0.10)", "covdefaults (>=2.3)", "detect-test-pollution (>=1.1.1)", "devpi-process (>=1)", "diff-cover (>=7.7)", "distlib (>=0.3.7)", "flaky (>=3.7)", "hatch-vcs (>=0.3)", "hatchling (>=1.18)", "psutil (>=5.9.5)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)", "pytest-xdist (>=3.3.1)", "re-assert (>=1.1)", "time-machine (>=2.12)", "wheel (>=0.41.2)"]
1256 |
1257 | [[package]]
1258 | name = "typing-extensions"
1259 | version = "4.8.0"
1260 | description = "Backported and Experimental Type Hints for Python 3.8+"
1261 | optional = false
1262 | python-versions = ">=3.8"
1263 | files = [
1264 | {file = "typing_extensions-4.8.0-py3-none-any.whl", hash = "sha256:8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0"},
1265 | {file = "typing_extensions-4.8.0.tar.gz", hash = "sha256:df8e4339e9cb77357558cbdbceca33c303714cf861d1eef15e1070055ae8b7ef"},
1266 | ]
1267 |
1268 | [[package]]
1269 | name = "urllib3"
1270 | version = "2.1.0"
1271 | description = "HTTP library with thread-safe connection pooling, file post, and more."
1272 | optional = false
1273 | python-versions = ">=3.8"
1274 | files = [
1275 | {file = "urllib3-2.1.0-py3-none-any.whl", hash = "sha256:55901e917a5896a349ff771be919f8bd99aff50b79fe58fec595eb37bbc56bb3"},
1276 | {file = "urllib3-2.1.0.tar.gz", hash = "sha256:df7aa8afb0148fa78488e7899b2c59b5f4ffcfa82e6c54ccb9dd37c1d7b52d54"},
1277 | ]
1278 |
1279 | [package.extras]
1280 | brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"]
1281 | socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"]
1282 | zstd = ["zstandard (>=0.18.0)"]
1283 |
1284 | [[package]]
1285 | name = "virtualenv"
1286 | version = "20.25.0"
1287 | description = "Virtual Python Environment builder"
1288 | optional = false
1289 | python-versions = ">=3.7"
1290 | files = [
1291 | {file = "virtualenv-20.25.0-py3-none-any.whl", hash = "sha256:4238949c5ffe6876362d9c0180fc6c3a824a7b12b80604eeb8085f2ed7460de3"},
1292 | {file = "virtualenv-20.25.0.tar.gz", hash = "sha256:bf51c0d9c7dd63ea8e44086fa1e4fb1093a31e963b86959257378aef020e1f1b"},
1293 | ]
1294 |
1295 | [package.dependencies]
1296 | distlib = ">=0.3.7,<1"
1297 | filelock = ">=3.12.2,<4"
1298 | platformdirs = ">=3.9.1,<5"
1299 |
1300 | [package.extras]
1301 | docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"]
1302 | test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8)", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10)"]
1303 |
1304 | [[package]]
1305 | name = "watchdog"
1306 | version = "3.0.0"
1307 | description = "Filesystem events monitoring"
1308 | optional = false
1309 | python-versions = ">=3.7"
1310 | files = [
1311 | {file = "watchdog-3.0.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:336adfc6f5cc4e037d52db31194f7581ff744b67382eb6021c868322e32eef41"},
1312 | {file = "watchdog-3.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a70a8dcde91be523c35b2bf96196edc5730edb347e374c7de7cd20c43ed95397"},
1313 | {file = "watchdog-3.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:adfdeab2da79ea2f76f87eb42a3ab1966a5313e5a69a0213a3cc06ef692b0e96"},
1314 | {file = "watchdog-3.0.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2b57a1e730af3156d13b7fdddfc23dea6487fceca29fc75c5a868beed29177ae"},
1315 | {file = "watchdog-3.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7ade88d0d778b1b222adebcc0927428f883db07017618a5e684fd03b83342bd9"},
1316 | {file = "watchdog-3.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7e447d172af52ad204d19982739aa2346245cc5ba6f579d16dac4bfec226d2e7"},
1317 | {file = "watchdog-3.0.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:9fac43a7466eb73e64a9940ac9ed6369baa39b3bf221ae23493a9ec4d0022674"},
1318 | {file = "watchdog-3.0.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:8ae9cda41fa114e28faf86cb137d751a17ffd0316d1c34ccf2235e8a84365c7f"},
1319 | {file = "watchdog-3.0.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:25f70b4aa53bd743729c7475d7ec41093a580528b100e9a8c5b5efe8899592fc"},
1320 | {file = "watchdog-3.0.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4f94069eb16657d2c6faada4624c39464f65c05606af50bb7902e036e3219be3"},
1321 | {file = "watchdog-3.0.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7c5f84b5194c24dd573fa6472685b2a27cc5a17fe5f7b6fd40345378ca6812e3"},
1322 | {file = "watchdog-3.0.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3aa7f6a12e831ddfe78cdd4f8996af9cf334fd6346531b16cec61c3b3c0d8da0"},
1323 | {file = "watchdog-3.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:233b5817932685d39a7896b1090353fc8efc1ef99c9c054e46c8002561252fb8"},
1324 | {file = "watchdog-3.0.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:13bbbb462ee42ec3c5723e1205be8ced776f05b100e4737518c67c8325cf6100"},
1325 | {file = "watchdog-3.0.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:8f3ceecd20d71067c7fd4c9e832d4e22584318983cabc013dbf3f70ea95de346"},
1326 | {file = "watchdog-3.0.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:c9d8c8ec7efb887333cf71e328e39cffbf771d8f8f95d308ea4125bf5f90ba64"},
1327 | {file = "watchdog-3.0.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:0e06ab8858a76e1219e68c7573dfeba9dd1c0219476c5a44d5333b01d7e1743a"},
1328 | {file = "watchdog-3.0.0-py3-none-manylinux2014_armv7l.whl", hash = "sha256:d00e6be486affb5781468457b21a6cbe848c33ef43f9ea4a73b4882e5f188a44"},
1329 | {file = "watchdog-3.0.0-py3-none-manylinux2014_i686.whl", hash = "sha256:c07253088265c363d1ddf4b3cdb808d59a0468ecd017770ed716991620b8f77a"},
1330 | {file = "watchdog-3.0.0-py3-none-manylinux2014_ppc64.whl", hash = "sha256:5113334cf8cf0ac8cd45e1f8309a603291b614191c9add34d33075727a967709"},
1331 | {file = "watchdog-3.0.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:51f90f73b4697bac9c9a78394c3acbbd331ccd3655c11be1a15ae6fe289a8c83"},
1332 | {file = "watchdog-3.0.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:ba07e92756c97e3aca0912b5cbc4e5ad802f4557212788e72a72a47ff376950d"},
1333 | {file = "watchdog-3.0.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:d429c2430c93b7903914e4db9a966c7f2b068dd2ebdd2fa9b9ce094c7d459f33"},
1334 | {file = "watchdog-3.0.0-py3-none-win32.whl", hash = "sha256:3ed7c71a9dccfe838c2f0b6314ed0d9b22e77d268c67e015450a29036a81f60f"},
1335 | {file = "watchdog-3.0.0-py3-none-win_amd64.whl", hash = "sha256:4c9956d27be0bb08fc5f30d9d0179a855436e655f046d288e2bcc11adfae893c"},
1336 | {file = "watchdog-3.0.0-py3-none-win_ia64.whl", hash = "sha256:5d9f3a10e02d7371cd929b5d8f11e87d4bad890212ed3901f9b4d68767bee759"},
1337 | {file = "watchdog-3.0.0.tar.gz", hash = "sha256:4d98a320595da7a7c5a18fc48cb633c2e73cda78f93cac2ef42d42bf609a33f9"},
1338 | ]
1339 |
1340 | [package.extras]
1341 | watchmedo = ["PyYAML (>=3.10)"]
1342 |
1343 | [[package]]
1344 | name = "zipp"
1345 | version = "3.17.0"
1346 | description = "Backport of pathlib-compatible object wrapper for zip files"
1347 | optional = false
1348 | python-versions = ">=3.8"
1349 | files = [
1350 | {file = "zipp-3.17.0-py3-none-any.whl", hash = "sha256:0e923e726174922dce09c53c59ad483ff7bbb8e572e00c7f7c46b88556409f31"},
1351 | {file = "zipp-3.17.0.tar.gz", hash = "sha256:84e64a1c28cf7e91ed2078bb8cc8c259cb19b76942096c8d7b84947690cabaf0"},
1352 | ]
1353 |
1354 | [package.extras]
1355 | docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"]
1356 | testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy (>=0.9.1)", "pytest-ruff"]
1357 |
1358 | [metadata]
1359 | lock-version = "2.0"
1360 | python-versions = ">=3.9,<4.0"
1361 | content-hash = "92e63fc167852d3bb7e7d3823d6c0a8282f3e623e38fda412824d545104c9e4a"
1362 |
--------------------------------------------------------------------------------