├── .editorconfig
├── .github
└── workflows
│ ├── close-inactive-issues.yaml
│ ├── main.yaml
│ └── secret-scanning.yaml
├── .gitignore
├── LICENSE
├── Makefile
├── README.md
├── assets
├── alpr.gif
├── alpr_draw_predictions.png
├── alpr_result.webp
├── detector.gif
└── test_image.png
├── docs
├── contributing.md
├── custom_models.md
├── index.md
├── quick_start.md
└── reference.md
├── fast_alpr
├── __init__.py
├── alpr.py
├── base.py
├── default_detector.py
└── default_ocr.py
├── mkdocs.yml
├── poetry.lock
├── poetry.toml
├── pyproject.toml
└── test
├── __init__.py
└── test_alpr.py
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig helps maintain consistent coding styles for multiple developers working on the same
2 | # project across various editors and IDEs. The EditorConfig project consists of a file format for
3 | # defining coding styles and a collection of text editor plugins that enable editors to read the
4 | # file format and adhere to defined styles. EditorConfig files are easily readable and they work
5 | # nicely with version control systems. https://editorconfig.org/
6 |
7 | # top-most EditorConfig file
8 | root = true
9 |
10 | # Unix-style newlines with a newline ending every file
11 | [*]
12 | end_of_line = lf
13 | insert_final_newline = true
14 | charset = utf-8
15 | trim_trailing_whitespace = true
16 | indent_style = space
17 |
18 | # 4 space indentation
19 | [*.py]
20 | indent_size = 4
21 |
--------------------------------------------------------------------------------
/.github/workflows/close-inactive-issues.yaml:
--------------------------------------------------------------------------------
1 | name: Close inactive issues
2 |
3 | on:
4 | schedule:
5 | - cron: "30 1 * * *" # Runs daily at 1:30 AM UTC
6 |
7 | jobs:
8 | close-issues:
9 | runs-on: ubuntu-latest
10 | permissions:
11 | issues: write
12 | pull-requests: write
13 | steps:
14 | - uses: actions/stale@v5
15 | with:
16 | days-before-issue-stale: 90 # The number of days old an issue can be before marking it stale
17 | days-before-issue-close: 14 # The number of days to wait to close an issue after it being marked stale
18 | stale-issue-label: "stale"
19 | stale-issue-message: "This issue is stale because it has been open for 90 days with no activity."
20 | close-issue-message: "This issue was closed because it has been inactive for 14 days since being marked as stale."
21 | days-before-pr-stale: -1 # Disables stale behavior for PRs
22 | days-before-pr-close: -1 # Disables closing behavior for PRs
23 | repo-token: ${{ secrets.GITHUB_TOKEN }}
24 |
--------------------------------------------------------------------------------
/.github/workflows/main.yaml:
--------------------------------------------------------------------------------
1 | name: Test and Deploy
2 | on:
3 | push:
4 | branches:
5 | - master
6 | tags:
7 | - 'v*'
8 | pull_request:
9 | branches:
10 | - '**'
11 | jobs:
12 | test:
13 | name: Test
14 | strategy:
15 | fail-fast: false
16 | matrix:
17 | python-version: [ '3.10', '3.11', '3.12' ]
18 | os: [ ubuntu-latest ]
19 | runs-on: ${{ matrix.os }}
20 | steps:
21 | - uses: actions/checkout@v3
22 |
23 | - name: Install poetry
24 | run: pipx install poetry
25 |
26 | - uses: actions/setup-python@v4
27 | with:
28 | python-version: ${{ matrix.python-version }}
29 | cache: 'poetry'
30 |
31 | - name: Install dependencies
32 | run: poetry install --all-extras
33 |
34 | - name: Check format
35 | run: make check_format
36 |
37 | - name: Run Linters
38 | run: make lint
39 |
40 | - name: Run tests
41 | run: make test
42 |
43 | build-and-publish-pypi:
44 | name: Build and Publish to PyPI
45 | needs:
46 | - test
47 | if: "startsWith(github.ref, 'refs/tags/v')"
48 | runs-on: ubuntu-latest
49 | environment:
50 | name: pypi
51 | url: https://pypi.org/p/fast-alpr
52 | permissions:
53 | id-token: write
54 | steps:
55 | - uses: actions/checkout@v3
56 |
57 | - name: Install poetry
58 | run: pipx install poetry
59 |
60 | - name: Setup Python
61 | uses: actions/setup-python@v4
62 | with:
63 | python-version: '3.10'
64 |
65 | - name: Build a binary wheel
66 | run: poetry build
67 |
68 | - name: Publish distribution 📦 to PyPI
69 | uses: pypa/gh-action-pypi-publish@release/v1
70 |
71 | github-release:
72 | name: Create GitHub release
73 | needs:
74 | - build-and-publish-pypi
75 | runs-on: ubuntu-latest
76 |
77 | permissions:
78 | contents: write
79 |
80 | steps:
81 | - uses: actions/checkout@v3
82 |
83 | - name: Check package version matches tag
84 | id: check-version
85 | uses: samuelcolvin/check-python-version@v4.1
86 | with:
87 | version_file_path: 'pyproject.toml'
88 |
89 | - name: Create GitHub Release
90 | env:
91 | GITHUB_TOKEN: ${{ github.token }}
92 | tag: ${{ github.ref_name }}
93 | run: |
94 | gh release create "$tag" \
95 | --repo="$GITHUB_REPOSITORY" \
96 | --title="${GITHUB_REPOSITORY#*/} ${tag#v}" \
97 | --generate-notes
98 |
99 | update_docs:
100 | name: Update documentation
101 | needs:
102 | - github-release
103 | runs-on: ubuntu-latest
104 |
105 | steps:
106 | - uses: actions/checkout@v3
107 | with:
108 | fetch-depth: 0
109 |
110 | - name: Install Poetry using pipx
111 | run: pipx install poetry
112 |
113 | - uses: actions/setup-python@v4
114 | with:
115 | python-version: '3.10'
116 | cache: 'poetry'
117 |
118 | - name: Configure Git user
119 | run: |
120 | git config --local user.email "github-actions[bot]@users.noreply.github.com"
121 | git config --local user.name "github-actions[bot]"
122 |
123 | - name: Retrieve version
124 | id: check-version
125 | uses: samuelcolvin/check-python-version@v4.1
126 | with:
127 | version_file_path: 'pyproject.toml'
128 | skip_env_check: true
129 |
130 | - name: Deploy Documentation
131 | run: |
132 | poetry run mike deploy \
133 | --update-aliases \
134 | --push \
135 | --branch docs-site \
136 | ${{ steps.check-version.outputs.VERSION_MAJOR_MINOR }} latest
137 |
--------------------------------------------------------------------------------
/.github/workflows/secret-scanning.yaml:
--------------------------------------------------------------------------------
1 | on:
2 | push:
3 | branches:
4 | - master
5 | pull_request:
6 | branches:
7 | - '**'
8 |
9 | name: Secret Leaks
10 | jobs:
11 | trufflehog:
12 | runs-on: ubuntu-latest
13 | steps:
14 | - name: Checkout code
15 | uses: actions/checkout@v4
16 | with:
17 | fetch-depth: 0
18 | - name: Secret Scanning
19 | uses: trufflesecurity/trufflehog@main
20 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | build/
12 | develop-eggs/
13 | dist/
14 | downloads/
15 | eggs/
16 | .eggs/
17 | lib/
18 | lib64/
19 | parts/
20 | sdist/
21 | var/
22 | wheels/
23 | share/python-wheels/
24 | *.egg-info/
25 | .installed.cfg
26 | *.egg
27 | MANIFEST
28 |
29 | # PyInstaller
30 | # Usually these files are written by a python script from a template
31 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
32 | *.manifest
33 | *.spec
34 |
35 | # Installer logs
36 | pip-log.txt
37 | pip-delete-this-directory.txt
38 |
39 | # Unit test / coverage reports
40 | htmlcov/
41 | .tox/
42 | .nox/
43 | .coverage
44 | .coverage.*
45 | .cache
46 | nosetests.xml
47 | coverage.xml
48 | *.cover
49 | *.py,cover
50 | .hypothesis/
51 | .pytest_cache/
52 | cover/
53 |
54 | # Translations
55 | *.mo
56 | *.pot
57 |
58 | # Django stuff:
59 | *.log
60 | local_settings.py
61 | db.sqlite3
62 | db.sqlite3-journal
63 |
64 | # Flask stuff:
65 | instance/
66 | .webassets-cache
67 |
68 | # Scrapy stuff:
69 | .scrapy
70 |
71 | # Sphinx documentation
72 | docs/_build/
73 |
74 | # PyBuilder
75 | .pybuilder/
76 | target/
77 |
78 | # Jupyter Notebook
79 | .ipynb_checkpoints
80 |
81 | # IPython
82 | profile_default/
83 | ipython_config.py
84 |
85 | # pyenv
86 | # For a library or package, you might want to ignore these files since the code is
87 | # intended to run in multiple environments; otherwise, check them in:
88 | # .python-version
89 |
90 | # pipenv
91 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
93 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
94 | # install all needed dependencies.
95 | #Pipfile.lock
96 |
97 | # poetry
98 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
99 | # This is especially recommended for binary packages to ensure reproducibility, and is more
100 | # commonly ignored for libraries.
101 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
102 | #poetry.lock
103 |
104 | # pdm
105 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
106 | #pdm.lock
107 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
108 | # in version control.
109 | # https://pdm.fming.dev/#use-with-ide
110 | .pdm.toml
111 |
112 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
113 | __pypackages__/
114 |
115 | # Celery stuff
116 | celerybeat-schedule
117 | celerybeat.pid
118 |
119 | # SageMath parsed files
120 | *.sage.py
121 |
122 | # Environments
123 | .env
124 | .venv
125 | env/
126 | venv/
127 | ENV/
128 | env.bak/
129 | venv.bak/
130 |
131 | # Spyder project settings
132 | .spyderproject
133 | .spyproject
134 |
135 | # Rope project settings
136 | .ropeproject
137 |
138 | # mkdocs documentation
139 | /site
140 |
141 | # mypy
142 | .mypy_cache/
143 | .dmypy.json
144 | dmypy.json
145 |
146 | # Pyre type checker
147 | .pyre/
148 |
149 | # pytype static type analyzer
150 | .pytype/
151 |
152 | # Cython debug symbols
153 | cython_debug/
154 |
155 | # pyenv
156 | .python-version
157 |
158 | # CUDA DNN
159 | cudnn64_7.dll
160 |
161 | # Train folder
162 | train_val_set/
163 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 ankandrew
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 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | # Directories
2 | SRC_PATHS := fast_alpr/ test/
3 |
4 | # Tasks
5 | .PHONY: help
6 | help:
7 | @echo "Available targets:"
8 | @echo " help : Show this help message"
9 | @echo " format : Format code using Ruff format"
10 | @echo " check_format : Check code formatting with Ruff format"
11 | @echo " ruff : Run Ruff linter"
12 | @echo " pylint : Run Pylint linter"
13 | @echo " mypy : Run MyPy static type checker"
14 | @echo " lint : Run linters (Ruff, Pylint and Mypy)"
15 | @echo " test : Run tests using pytest"
16 | @echo " checks : Check format, lint, and test"
17 | @echo " clean : Clean up caches and build artifacts"
18 |
19 | .PHONY: format
20 | format:
21 | @echo "==> Sorting imports..."
22 | @# Currently, the Ruff formatter does not sort imports, see https://docs.astral.sh/ruff/formatter/#sorting-imports
23 | @poetry run ruff check --select I --fix $(SRC_PATHS)
24 | @echo "=====> Formatting code..."
25 | @poetry run ruff format $(SRC_PATHS)
26 |
27 | .PHONY: check_format
28 | check_format:
29 | @echo "=====> Checking format..."
30 | @poetry run ruff format --check --diff $(SRC_PATHS)
31 | @echo "=====> Checking imports are sorted..."
32 | @poetry run ruff check --select I --exit-non-zero-on-fix $(SRC_PATHS)
33 |
34 | .PHONY: ruff
35 | ruff:
36 | @echo "=====> Running Ruff..."
37 | @poetry run ruff check $(SRC_PATHS)
38 |
39 | .PHONY: pylint
40 | pylint:
41 | @echo "=====> Running Pylint..."
42 | @poetry run pylint $(SRC_PATHS)
43 |
44 | .PHONY: mypy
45 | mypy:
46 | @echo "=====> Running Mypy..."
47 | @poetry run mypy $(SRC_PATHS)
48 |
49 | .PHONY: lint
50 | lint: ruff pylint mypy
51 |
52 | .PHONY: test
53 | test:
54 | @echo "=====> Running tests..."
55 | @poetry run pytest test/
56 |
57 | .PHONY: clean
58 | clean:
59 | @echo "=====> Cleaning caches..."
60 | @poetry run ruff clean
61 | @rm -rf .cache .pytest_cache .mypy_cache build dist *.egg-info
62 |
63 | checks: format lint test
64 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # FastALPR
2 |
3 | [](https://github.com/ankandrew/fast-alpr/actions)
4 | [](https://github.com/astral-sh/ruff)
5 | [](https://github.com/pylint-dev/pylint)
6 | [](http://mypy-lang.org/)
7 | [](https://onnx.ai/)
8 | [](https://huggingface.co/spaces/ankandrew/fast-alpr)
9 | [](https://ankandrew.github.io/fast-alpr/)
10 | [](https://www.python.org/)
11 | [](https://github.com/ankandrew/fast-alpr/releases)
12 | [](./LICENSE)
13 |
14 | [](https://youtu.be/-TPJot7-HTs?t=652)
15 |
16 | **FastALPR** is a high-performance, customizable Automatic License Plate Recognition (ALPR) system. We offer fast and
17 | efficient ONNX models by default, but you can easily swap in your own models if needed.
18 |
19 | For Optical Character Recognition (**OCR**), we use [fast-plate-ocr](https://github.com/ankandrew/fast-plate-ocr) by
20 | default, and for **license plate detection**, we
21 | use [open-image-models](https://github.com/ankandrew/open-image-models). However, you can integrate any OCR or detection
22 | model of your choice.
23 |
24 | ## 📋 Table of Contents
25 |
26 | * [✨ Features](#-features)
27 | * [📦 Installation](#-installation)
28 | * [🚀 Quick Start](#-quick-start)
29 | * [🛠️ Customization and Flexibility](#-customization-and-flexibility)
30 | * [📖 Documentation](#-documentation)
31 | * [🤝 Contributing](#-contributing)
32 | * [🙏 Acknowledgements](#-acknowledgements)
33 | * [📫 Contact](#-contact)
34 |
35 | ## ✨ Features
36 |
37 | - **High Accuracy**: Uses advanced models for precise license plate detection and OCR.
38 | - **Customizable**: Easily switch out detection and OCR models.
39 | - **Easy to Use**: Quick setup with a simple API.
40 | - **Out-of-the-Box Models**: Includes ready-to-use detection and OCR models
41 | - **Fast Performance**: Optimized with ONNX Runtime for speed.
42 |
43 | ## 📦 Installation
44 |
45 | ```bash
46 | pip install fast-alpr
47 | ```
48 |
49 | ## 🚀 Quick Start
50 |
51 | > [!TIP]
52 | > Try `fast-plate-ocr` pre-trained models in [Hugging Spaces](https://huggingface.co/spaces/ankandrew/fast-alpr).
53 |
54 | Here's how to get started with FastALPR:
55 |
56 | ```python
57 | from fast_alpr import ALPR
58 |
59 | # You can also initialize the ALPR with custom plate detection and OCR models.
60 | alpr = ALPR(
61 | detector_model="yolo-v9-t-384-license-plate-end2end",
62 | ocr_model="global-plates-mobile-vit-v2-model",
63 | )
64 |
65 | # The "assets/test_image.png" can be found in repo root dit
66 | alpr_results = alpr.predict("assets/test_image.png")
67 | print(alpr_results)
68 | ```
69 |
70 | Output:
71 |
72 |
73 |
74 | You can also draw the predictions directly on the image:
75 |
76 | ```python
77 | import cv2
78 |
79 | from fast_alpr import ALPR
80 |
81 | # Initialize the ALPR
82 | alpr = ALPR(
83 | detector_model="yolo-v9-t-384-license-plate-end2end",
84 | ocr_model="global-plates-mobile-vit-v2-model",
85 | )
86 |
87 | # Load the image
88 | image_path = "assets/test_image.png"
89 | frame = cv2.imread(image_path)
90 |
91 | # Draw predictions on the image
92 | annotated_frame = alpr.draw_predictions(frame)
93 |
94 | # Display the result
95 | cv2.imshow("ALPR Result", annotated_frame)
96 | cv2.waitKey(0)
97 | cv2.destroyAllWindows()
98 | ```
99 |
100 | Output:
101 |
102 |
103 |
104 | ## 🛠️ Customization and Flexibility
105 |
106 | FastALPR is designed to be flexible. You can customize the detector and OCR models according to your requirements.
107 | You can very easily integrate with **Tesseract** OCR to leverage its capabilities:
108 |
109 | ```python
110 | import re
111 | from statistics import mean
112 |
113 | import numpy as np
114 | import pytesseract
115 |
116 | from fast_alpr.alpr import ALPR, BaseOCR, OcrResult
117 |
118 |
119 | class PytesseractOCR(BaseOCR):
120 | def __init__(self) -> None:
121 | """
122 | Init PytesseractOCR.
123 | """
124 |
125 | def predict(self, cropped_plate: np.ndarray) -> OcrResult | None:
126 | if cropped_plate is None:
127 | return None
128 | # You can change 'eng' to the appropriate language code as needed
129 | data = pytesseract.image_to_data(
130 | cropped_plate,
131 | lang="eng",
132 | config="--oem 3 --psm 6",
133 | output_type=pytesseract.Output.DICT,
134 | )
135 | plate_text = " ".join(data["text"]).strip()
136 | plate_text = re.sub(r"[^A-Za-z0-9]", "", plate_text)
137 | avg_confidence = mean(conf for conf in data["conf"] if conf > 0) / 100.0
138 | return OcrResult(text=plate_text, confidence=avg_confidence)
139 |
140 |
141 | alpr = ALPR(detector_model="yolo-v9-t-384-license-plate-end2end", ocr=PytesseractOCR())
142 |
143 | alpr_results = alpr.predict("assets/test_image.png")
144 | print(alpr_results)
145 | ```
146 |
147 | > [!TIP]
148 | > See the [docs](https://ankandrew.github.io/fast-alpr/) for more examples!
149 |
150 | ## 📖 Documentation
151 |
152 | Comprehensive documentation is available [here](https://ankandrew.github.io/fast-alpr/), including detailed API
153 | references and additional examples.
154 |
155 | ## 🤝 Contributing
156 |
157 | Contributions to the repo are greatly appreciated. Whether it's bug fixes, feature enhancements, or new models,
158 | your contributions are warmly welcomed.
159 |
160 | To start contributing or to begin development, you can follow these steps:
161 |
162 | 1. Clone repo
163 | ```shell
164 | git clone https://github.com/ankandrew/fast-alpr.git
165 | ```
166 | 2. Install all dependencies using [Poetry](https://python-poetry.org/docs/#installation):
167 | ```shell
168 | poetry install --all-extras
169 | ```
170 | 3. To ensure your changes pass linting and tests before submitting a PR:
171 | ```shell
172 | make checks
173 | ```
174 |
175 | ## 🙏 Acknowledgements
176 |
177 | - [fast-plate-ocr](https://github.com/ankandrew/fast-plate-ocr) for default **OCR** models.
178 | - [open-image-models](https://github.com/ankandrew/open-image-models) for default plate **detection** models.
179 |
180 | ## 📫 Contact
181 |
182 | For questions or suggestions, feel free to open an issue.
183 |
--------------------------------------------------------------------------------
/assets/alpr.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ankandrew/fast-alpr/8ffc0a799ada0938069da38c519ec7962828dd2b/assets/alpr.gif
--------------------------------------------------------------------------------
/assets/alpr_draw_predictions.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ankandrew/fast-alpr/8ffc0a799ada0938069da38c519ec7962828dd2b/assets/alpr_draw_predictions.png
--------------------------------------------------------------------------------
/assets/alpr_result.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ankandrew/fast-alpr/8ffc0a799ada0938069da38c519ec7962828dd2b/assets/alpr_result.webp
--------------------------------------------------------------------------------
/assets/detector.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ankandrew/fast-alpr/8ffc0a799ada0938069da38c519ec7962828dd2b/assets/detector.gif
--------------------------------------------------------------------------------
/assets/test_image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ankandrew/fast-alpr/8ffc0a799ada0938069da38c519ec7962828dd2b/assets/test_image.png
--------------------------------------------------------------------------------
/docs/contributing.md:
--------------------------------------------------------------------------------
1 | Contributions to the repo are greatly appreciated. Whether it's bug fixes, feature enhancements, or new models,
2 | your contributions are warmly welcomed.
3 |
4 | To start contributing or to begin development, you can follow these steps:
5 |
6 | 1. Clone repo
7 | ```shell
8 | git clone https://github.com/ankandrew/fast-alpr.git
9 | ```
10 | 2. Install all dependencies using [Poetry](https://python-poetry.org/docs/#installation):
11 | ```shell
12 | poetry install --all-extras
13 | ```
14 | 3. To ensure your changes pass linting and tests before submitting a PR:
15 | ```shell
16 | make checks
17 | ```
18 |
--------------------------------------------------------------------------------
/docs/custom_models.md:
--------------------------------------------------------------------------------
1 | ## 🛠️ Customization and Flexibility
2 |
3 | FastALPR is designed to be flexible. You can customize the detector and OCR models according to your requirements.
4 |
5 | ### Using Tesseract OCR
6 |
7 | You can very easily integrate with **Tesseract** OCR to leverage its capabilities:
8 |
9 | ```python title="tesseract_ocr.py"
10 | import re
11 | from statistics import mean
12 |
13 | import numpy as np
14 | import pytesseract
15 |
16 | from fast_alpr.alpr import ALPR, BaseOCR, OcrResult
17 |
18 |
19 | class PytesseractOCR(BaseOCR):
20 | def __init__(self) -> None:
21 | """
22 | Init PytesseractOCR.
23 | """
24 |
25 | def predict(self, cropped_plate: np.ndarray) -> OcrResult | None:
26 | if cropped_plate is None:
27 | return None
28 | # You can change 'eng' to the appropriate language code as needed
29 | data = pytesseract.image_to_data(
30 | cropped_plate,
31 | lang="eng",
32 | config="--oem 3 --psm 6",
33 | output_type=pytesseract.Output.DICT,
34 | )
35 | plate_text = " ".join(data["text"]).strip()
36 | plate_text = re.sub(r"[^A-Za-z0-9]", "", plate_text)
37 | avg_confidence = mean(conf for conf in data["conf"] if conf > 0) / 100.0
38 | return OcrResult(text=plate_text, confidence=avg_confidence)
39 |
40 |
41 | alpr = ALPR(detector_model="yolo-v9-t-384-license-plate-end2end", ocr=PytesseractOCR())
42 |
43 | alpr_results = alpr.predict("assets/test_image.png")
44 | print(alpr_results)
45 | ```
46 |
47 | ???+ tip
48 |
49 | You can implement this with any OCR you want! For example, [EasyOCR](https://github.com/JaidedAI/EasyOCR).
50 |
--------------------------------------------------------------------------------
/docs/index.md:
--------------------------------------------------------------------------------
1 | # FastALPR
2 |
3 | [](https://youtu.be/-TPJot7-HTs?t=652)
4 |
5 | ## Intro
6 |
7 | **FastALPR** is a high-performance, customizable Automatic License Plate Recognition (ALPR) system. We offer fast and
8 | efficient ONNX models by default, but you can easily swap in your own models if needed.
9 |
10 | For Optical Character Recognition (**OCR**), we use [fast-plate-ocr](https://github.com/ankandrew/fast-plate-ocr) by
11 | default, and for **license plate detection**, we
12 | use [open-image-models](https://github.com/ankandrew/open-image-models). However, you can integrate any OCR or detection
13 | model of your choice.
14 |
15 | ## Features
16 |
17 | - **🔍 High Accuracy**: Uses advanced models for precise license plate detection and OCR.
18 | - **🔧 Customizable**: Easily switch out detection and OCR models.
19 | - **🚀 Easy to Use**: Quick setup with a simple API.
20 | - **📦 Out-of-the-Box Models**: Includes ready-to-use detection and OCR models
21 | - **⚡ Fast Performance**: Optimized with ONNX Runtime for speed.
22 |
23 | ## Installation
24 |
25 | To install **FastALPR**, simply do:
26 |
27 | ```shell
28 | pip install fast-alpr
29 | ```
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/docs/quick_start.md:
--------------------------------------------------------------------------------
1 | ## 🚀 Quick Start
2 |
3 | Here's how to get started with FastALPR:
4 |
5 | ### Predictions
6 |
7 | ```python
8 | from fast_alpr import ALPR
9 |
10 | # You can also initialize the ALPR with custom plate detection and OCR models.
11 | alpr = ALPR(
12 | detector_model="yolo-v9-t-384-license-plate-end2end",
13 | ocr_model="global-plates-mobile-vit-v2-model",
14 | )
15 |
16 | # The "assets/test_image.png" can be found in repo root dit
17 | # You can also pass a NumPy array containing cropped plate image
18 | alpr_results = alpr.predict("assets/test_image.png")
19 | print(alpr_results)
20 | ```
21 |
22 | ???+ note
23 |
24 | See [reference](reference.md) for the available models.
25 |
26 | Output:
27 |
28 |
29 |
30 | ### Draw Results
31 |
32 | You can also **draw** the predictions directly on the image:
33 |
34 | ```python
35 | import cv2
36 |
37 | from fast_alpr import ALPR
38 |
39 | # Initialize the ALPR
40 | alpr = ALPR(
41 | detector_model="yolo-v9-t-384-license-plate-end2end",
42 | ocr_model="global-plates-mobile-vit-v2-model",
43 | )
44 |
45 | # Load the image
46 | image_path = "assets/test_image.png"
47 | frame = cv2.imread(image_path)
48 |
49 | # Draw predictions on the image
50 | annotated_frame = alpr.draw_predictions(frame)
51 |
52 | # Display the result
53 | cv2.imshow("ALPR Result", annotated_frame)
54 | cv2.waitKey(0)
55 | cv2.destroyAllWindows()
56 | ```
57 |
58 | Output:
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/docs/reference.md:
--------------------------------------------------------------------------------
1 | ## Available Models
2 |
3 | See available detection models in [open-image-models](https://ankandrew.github.io/open-image-models/0.1.0/reference/#open_image_models.detection.core.hub.PlateDetectorModel)
4 | and OCR models in [fast-plate-ocr](https://ankandrew.github.io/fast-plate-ocr/latest/reference/#fast_plate_ocr.inference.onnx_inference.ONNXPlateRecognizer).
5 |
6 | ## FastALPR
7 |
8 | ::: fast_alpr
9 |
--------------------------------------------------------------------------------
/fast_alpr/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | FastALPR package.
3 | """
4 |
5 | from fast_alpr.alpr import ALPR, ALPRResult
6 | from fast_alpr.base import BaseDetector, BaseOCR, DetectionResult, OcrResult
7 |
8 | __all__ = ["ALPR", "ALPRResult", "BaseDetector", "BaseOCR", "DetectionResult", "OcrResult"]
9 |
--------------------------------------------------------------------------------
/fast_alpr/alpr.py:
--------------------------------------------------------------------------------
1 | """
2 | ALPR module.
3 | """
4 |
5 | import os
6 | import statistics
7 | from collections.abc import Sequence
8 | from dataclasses import dataclass
9 | from typing import Literal
10 |
11 | import cv2
12 | import numpy as np
13 | import onnxruntime as ort
14 | from fast_plate_ocr.inference.hub import OcrModel
15 | from open_image_models.detection.core.hub import PlateDetectorModel
16 |
17 | from fast_alpr.base import BaseDetector, BaseOCR, DetectionResult, OcrResult
18 | from fast_alpr.default_detector import DefaultDetector
19 | from fast_alpr.default_ocr import DefaultOCR
20 |
21 | # pylint: disable=too-many-arguments, too-many-locals
22 | # ruff: noqa: PLR0913
23 |
24 |
25 | @dataclass(frozen=True)
26 | class ALPRResult:
27 | """
28 | Dataclass to hold the results of detection and OCR for a license plate.
29 | """
30 |
31 | detection: DetectionResult
32 | ocr: OcrResult | None
33 |
34 |
35 | class ALPR:
36 | """
37 | Automatic License Plate Recognition (ALPR) system class.
38 |
39 | This class combines a detector and an OCR model to recognize license plates in images.
40 | """
41 |
42 | def __init__(
43 | self,
44 | detector: BaseDetector | None = None,
45 | ocr: BaseOCR | None = None,
46 | detector_model: PlateDetectorModel = "yolo-v9-t-384-license-plate-end2end",
47 | detector_conf_thresh: float = 0.4,
48 | detector_providers: Sequence[str | tuple[str, dict]] | None = None,
49 | detector_sess_options: ort.SessionOptions = None,
50 | ocr_model: OcrModel | None = "global-plates-mobile-vit-v2-model",
51 | ocr_device: Literal["cuda", "cpu", "auto"] = "auto",
52 | ocr_providers: Sequence[str | tuple[str, dict]] | None = None,
53 | ocr_sess_options: ort.SessionOptions | None = None,
54 | ocr_model_path: str | os.PathLike | None = None,
55 | ocr_config_path: str | os.PathLike | None = None,
56 | ocr_force_download: bool = False,
57 | ) -> None:
58 | """
59 | Initialize the ALPR system.
60 |
61 | Parameters:
62 | detector: An instance of BaseDetector. If None, the DefaultDetector is used.
63 | ocr: An instance of BaseOCR. If None, the DefaultOCR is used.
64 | detector_model: The name of the detector model or a PlateDetectorModel enum instance.
65 | Defaults to "yolo-v9-t-384-license-plate-end2end".
66 | detector_conf_thresh: Confidence threshold for the detector.
67 | detector_providers: Execution providers for the detector.
68 | detector_sess_options: Session options for the detector.
69 | ocr_model: The name of the OCR model from the model hub. This can be none and
70 | `ocr_model_path` and `ocr_config_path` parameters are expected to pass them to
71 | `fast-plate-ocr` library.
72 | ocr_device: The device to run the OCR model on ("cuda", "cpu", or "auto").
73 | ocr_providers: Execution providers for the OCR. If None, the default providers are used.
74 | ocr_sess_options: Session options for the OCR. If None, default session options are
75 | used.
76 | ocr_model_path: Custom model path for the OCR. If None, the model is downloaded from the
77 | hub or cache.
78 | ocr_config_path: Custom config path for the OCR. If None, the default configuration is
79 | used.
80 | ocr_force_download: Whether to force download the OCR model.
81 | """
82 | # Initialize the detector
83 | self.detector = detector or DefaultDetector(
84 | model_name=detector_model,
85 | conf_thresh=detector_conf_thresh,
86 | providers=detector_providers,
87 | sess_options=detector_sess_options,
88 | )
89 |
90 | # Initialize the OCR
91 | self.ocr = ocr or DefaultOCR(
92 | hub_ocr_model=ocr_model,
93 | device=ocr_device,
94 | providers=ocr_providers,
95 | sess_options=ocr_sess_options,
96 | model_path=ocr_model_path,
97 | config_path=ocr_config_path,
98 | force_download=ocr_force_download,
99 | )
100 |
101 | def predict(self, frame: np.ndarray | str) -> list[ALPRResult]:
102 | """
103 | Returns all recognized license plates from a frame.
104 |
105 | Parameters:
106 | frame: Unprocessed frame (Colors in order: BGR) or image path.
107 |
108 | Returns:
109 | A list of ALPRResult objects containing detection and OCR results.
110 | """
111 | if isinstance(frame, str):
112 | img_path = frame
113 | frame = cv2.imread(img_path)
114 | if frame is None:
115 | raise ValueError(f"Failed to load image from path: {img_path}")
116 |
117 | plate_detections = self.detector.predict(frame)
118 | alpr_results = []
119 | for detection in plate_detections:
120 | bbox = detection.bounding_box
121 | x1, y1 = max(bbox.x1, 0), max(bbox.y1, 0)
122 | x2, y2 = min(bbox.x2, frame.shape[1]), min(bbox.y2, frame.shape[0])
123 | cropped_plate = frame[y1:y2, x1:x2]
124 | ocr_result = self.ocr.predict(cropped_plate)
125 | alpr_result = ALPRResult(detection=detection, ocr=ocr_result)
126 | alpr_results.append(alpr_result)
127 | return alpr_results
128 |
129 | def draw_predictions(self, frame: np.ndarray | str) -> np.ndarray:
130 | """
131 | Draws detections and OCR results on the frame.
132 |
133 | Parameters:
134 | frame: The original frame or image path.
135 |
136 | Returns:
137 | The frame with detections and OCR results drawn.
138 | """
139 | # If frame is a string, assume it's an image path and load it
140 | if isinstance(frame, str):
141 | img_path = frame
142 | frame = cv2.imread(img_path)
143 | if frame is None:
144 | raise ValueError(f"Failed to load image from path: {img_path}")
145 |
146 | # Get ALPR results
147 | alpr_results = self.predict(frame)
148 |
149 | for result in alpr_results:
150 | detection = result.detection
151 | ocr_result = result.ocr
152 | bbox = detection.bounding_box
153 | x1, y1, x2, y2 = bbox.x1, bbox.y1, bbox.x2, bbox.y2
154 | # Draw the bounding box
155 | cv2.rectangle(frame, (x1, y1), (x2, y2), (36, 255, 12), 2)
156 | if ocr_result is None or not ocr_result.text or not ocr_result.confidence:
157 | continue
158 | # Remove padding symbols if any
159 | plate_text = ocr_result.text
160 | confidence: float = (
161 | statistics.mean(ocr_result.confidence)
162 | if isinstance(ocr_result.confidence, list)
163 | else ocr_result.confidence
164 | )
165 | display_text = f"{plate_text} {confidence * 100:.2f}%"
166 | font_scale = 1.25
167 | # Draw black background for better readability
168 | cv2.putText(
169 | img=frame,
170 | text=display_text,
171 | org=(x1, y1 - 10),
172 | fontFace=cv2.FONT_HERSHEY_SIMPLEX,
173 | fontScale=font_scale,
174 | color=(0, 0, 0),
175 | thickness=6,
176 | lineType=cv2.LINE_AA,
177 | )
178 | # Draw white text
179 | cv2.putText(
180 | img=frame,
181 | text=display_text,
182 | org=(x1, y1 - 10),
183 | fontFace=cv2.FONT_HERSHEY_SIMPLEX,
184 | fontScale=font_scale,
185 | color=(255, 255, 255),
186 | thickness=2,
187 | lineType=cv2.LINE_AA,
188 | )
189 | return frame
190 |
--------------------------------------------------------------------------------
/fast_alpr/base.py:
--------------------------------------------------------------------------------
1 | """
2 | Base module.
3 | """
4 |
5 | from abc import ABC, abstractmethod
6 | from dataclasses import dataclass
7 |
8 | import numpy as np
9 |
10 |
11 | @dataclass(frozen=True)
12 | class BoundingBox:
13 | x1: int
14 | y1: int
15 | x2: int
16 | y2: int
17 |
18 |
19 | @dataclass(frozen=True)
20 | class DetectionResult:
21 | label: str
22 | confidence: float
23 | bounding_box: BoundingBox
24 |
25 |
26 | @dataclass(frozen=True)
27 | class OcrResult:
28 | text: str
29 | confidence: float | list[float]
30 |
31 |
32 | class BaseDetector(ABC):
33 | @abstractmethod
34 | def predict(self, frame: np.ndarray) -> list[DetectionResult]:
35 | """Perform detection on the input frame and return a list of detections."""
36 |
37 |
38 | class BaseOCR(ABC):
39 | @abstractmethod
40 | def predict(self, cropped_plate: np.ndarray) -> OcrResult | None:
41 | """Perform OCR on the cropped plate image and return the recognized text and character
42 | probabilities."""
43 |
--------------------------------------------------------------------------------
/fast_alpr/default_detector.py:
--------------------------------------------------------------------------------
1 | """
2 | Default Detector module.
3 | """
4 |
5 | from collections.abc import Sequence
6 |
7 | import numpy as np
8 | import onnxruntime as ort
9 | from open_image_models import LicensePlateDetector
10 | from open_image_models.detection.core.hub import PlateDetectorModel
11 |
12 | from fast_alpr.base import BaseDetector, BoundingBox, DetectionResult
13 |
14 |
15 | class DefaultDetector(BaseDetector):
16 | """
17 | Default detector class for license plate detection using ONNX models.
18 |
19 | This class utilizes the `LicensePlateDetector` from the `open_image_models` package
20 | to perform detection on input frames.
21 | """
22 |
23 | def __init__(
24 | self,
25 | model_name: PlateDetectorModel = "yolo-v9-t-384-license-plate-end2end",
26 | conf_thresh: float = 0.4,
27 | providers: Sequence[str | tuple[str, dict]] | None = None,
28 | sess_options: ort.SessionOptions = None,
29 | ) -> None:
30 | """
31 | Initialize the DefaultDetector with the specified parameters. Uses `open-image-models`'s
32 | `LicensePlateDetector`.
33 |
34 | Parameters:
35 | model_name: The name of the detector model. See `PlateDetectorModel` for the available
36 | models.
37 | conf_thresh: Confidence threshold for the detector. Defaults to 0.25.
38 | providers: The execution providers to use in ONNX Runtime. If None, the default
39 | providers are used.
40 | sess_options: Custom session options for ONNX Runtime. If None, default session options
41 | are used.
42 | """
43 | self.detector = LicensePlateDetector(
44 | detection_model=model_name,
45 | conf_thresh=conf_thresh,
46 | providers=providers,
47 | sess_options=sess_options,
48 | )
49 |
50 | def predict(self, frame: np.ndarray) -> list[DetectionResult]:
51 | """
52 | Perform detection on the input frame and return a list of detections.
53 |
54 | Parameters:
55 | frame: The input image/frame in which to detect license plates.
56 |
57 | Returns:
58 | A list of detection results, each containing the label,
59 | confidence, and bounding box of a detected license plate.
60 | """
61 | detections = self.detector.predict(frame)
62 | detection_results = [
63 | DetectionResult(
64 | label=detection.label,
65 | confidence=detection.confidence,
66 | bounding_box=BoundingBox(
67 | x1=detection.bounding_box.x1,
68 | y1=detection.bounding_box.y1,
69 | x2=detection.bounding_box.x2,
70 | y2=detection.bounding_box.y2,
71 | ),
72 | )
73 | for detection in detections
74 | ]
75 | return detection_results
76 |
--------------------------------------------------------------------------------
/fast_alpr/default_ocr.py:
--------------------------------------------------------------------------------
1 | """
2 | Default OCR module.
3 | """
4 |
5 | import os
6 | from collections.abc import Sequence
7 | from typing import Literal
8 |
9 | import cv2
10 | import numpy as np
11 | import onnxruntime as ort
12 | from fast_plate_ocr import ONNXPlateRecognizer
13 | from fast_plate_ocr.inference.hub import OcrModel
14 |
15 | from fast_alpr.base import BaseOCR, OcrResult
16 |
17 |
18 | class DefaultOCR(BaseOCR):
19 | """
20 | Default OCR class for license plate recognition using ONNX models.
21 |
22 | This class utilizes the `ONNXPlateRecognizer` from the `fast-plate-ocr` package
23 | to perform OCR on cropped license plate images.
24 | """
25 |
26 | def __init__(
27 | self,
28 | hub_ocr_model: OcrModel | None = None,
29 | device: Literal["cuda", "cpu", "auto"] = "auto",
30 | providers: Sequence[str | tuple[str, dict]] | None = None,
31 | sess_options: ort.SessionOptions | None = None,
32 | model_path: str | os.PathLike | None = None,
33 | config_path: str | os.PathLike | None = None,
34 | force_download: bool = False,
35 | ) -> None:
36 | """
37 | Initialize the DefaultOCR with the specified parameters. Uses `fast-plate-ocr`'s
38 | `ONNXPlateRecognizer`
39 |
40 | Parameters:
41 | hub_ocr_model: The name of the OCR model from the model hub.
42 | device: The device to run the model on. Options are "cuda", "cpu", or "auto". Defaults
43 | to "auto".
44 | providers: The execution providers to use in ONNX Runtime. If None, the default
45 | providers are used.
46 | sess_options: Custom session options for ONNX Runtime. If None, default session options
47 | are used.
48 | model_path: Path to a custom OCR model file. If None, the model is downloaded from the
49 | hub or cache.
50 | config_path: Path to a custom configuration file. If None, the default configuration is
51 | used.
52 | force_download: If True, forces the download of the model and overwrites any existing
53 | files.
54 | """
55 | self.ocr_model = ONNXPlateRecognizer(
56 | hub_ocr_model=hub_ocr_model,
57 | device=device,
58 | providers=providers,
59 | sess_options=sess_options,
60 | model_path=model_path,
61 | config_path=config_path,
62 | force_download=force_download,
63 | )
64 |
65 | def predict(self, cropped_plate: np.ndarray) -> OcrResult | None:
66 | """
67 | Perform OCR on a cropped license plate image.
68 |
69 | Parameters:
70 | cropped_plate: The cropped image of the license plate in BGR format.
71 |
72 | Returns:
73 | OcrResult: An object containing the recognized text and per-character confidence.
74 | """
75 | if cropped_plate is None:
76 | return None
77 | gray_plate = cv2.cvtColor(cropped_plate, cv2.COLOR_BGR2GRAY)
78 | plate_text, probabilities = self.ocr_model.run(gray_plate, return_confidence=True)
79 | if not isinstance(plate_text, list):
80 | raise TypeError(f"Expected plate_text to be a list, got {type(plate_text).__name__}")
81 | if not isinstance(probabilities, np.ndarray):
82 | raise TypeError(
83 | f"Expected probabilities to be a numpy ndarray, got {type(probabilities).__name__}"
84 | )
85 | # fast_plate_ocr uses '_' padding symbol
86 | plate_text = plate_text.pop().replace("_", "")
87 | return OcrResult(text=plate_text, confidence=float(np.mean(probabilities)))
88 |
--------------------------------------------------------------------------------
/mkdocs.yml:
--------------------------------------------------------------------------------
1 | site_name: FastALPR
2 | site_author: ankandrew
3 | site_description: Fast ALPR.
4 | repo_url: https://github.com/ankandrew/fast-alpr
5 | theme:
6 | name: material
7 | features:
8 | - navigation.instant
9 | - navigation.instant.progress
10 | - search.suggest
11 | - navigation.sections
12 | - navigation.expand
13 | - search.highlight
14 | - content.code.copy
15 | - content.code.select
16 | palette:
17 | - scheme: default
18 | toggle:
19 | icon: material/lightbulb-outline
20 | name: Switch to dark mode
21 | - scheme: slate
22 | toggle:
23 | icon: material/lightbulb
24 | name: Switch to light mode
25 | nav:
26 | - Introduction: index.md
27 | - Quick Start: quick_start.md
28 | - Custom Models: custom_models.md
29 | - Contributing: contributing.md
30 | - Reference: reference.md
31 | plugins:
32 | - search
33 | - mike:
34 | alias_type: symlink
35 | canonical_version: latest
36 | - mkdocstrings:
37 | handlers:
38 | python:
39 | paths: [ fast_alpr ]
40 | options:
41 | members_order: source
42 | separate_signature: true
43 | filters: [ "!^_" ]
44 | docstring_options:
45 | ignore_init_summary: true
46 | show_signature: true
47 | show_source: true
48 | heading_level: 2
49 | show_root_full_path: false
50 | merge_init_into_class: true
51 | show_signature_annotations: true
52 | signature_crossrefs: true
53 | extra:
54 | version:
55 | provider: mike
56 | generator: false
57 | markdown_extensions:
58 | - admonition
59 | - pymdownx.highlight:
60 | anchor_linenums: true
61 | line_spans: __span
62 | pygments_lang_class: true
63 | - pymdownx.inlinehilite
64 | - pymdownx.snippets
65 | - pymdownx.details
66 | - pymdownx.superfences
67 | - toc:
68 | permalink: true
69 | title: Page contents
70 |
--------------------------------------------------------------------------------
/poetry.lock:
--------------------------------------------------------------------------------
1 | # This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand.
2 |
3 | [[package]]
4 | name = "astroid"
5 | version = "3.1.0"
6 | description = "An abstract syntax tree for Python with inference support."
7 | optional = false
8 | python-versions = ">=3.8.0"
9 | files = [
10 | {file = "astroid-3.1.0-py3-none-any.whl", hash = "sha256:951798f922990137ac090c53af473db7ab4e70c770e6d7fae0cec59f74411819"},
11 | {file = "astroid-3.1.0.tar.gz", hash = "sha256:ac248253bfa4bd924a0de213707e7ebeeb3138abeb48d798784ead1e56d419d4"},
12 | ]
13 |
14 | [package.dependencies]
15 | typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.11\""}
16 |
17 | [[package]]
18 | name = "babel"
19 | version = "2.16.0"
20 | description = "Internationalization utilities"
21 | optional = true
22 | python-versions = ">=3.8"
23 | files = [
24 | {file = "babel-2.16.0-py3-none-any.whl", hash = "sha256:368b5b98b37c06b7daf6696391c3240c938b37767d4584413e8438c5c435fa8b"},
25 | {file = "babel-2.16.0.tar.gz", hash = "sha256:d1f3554ca26605fe173f3de0c65f750f5a42f924499bf134de6423582298e316"},
26 | ]
27 |
28 | [package.extras]
29 | dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"]
30 |
31 | [[package]]
32 | name = "certifi"
33 | version = "2024.8.30"
34 | description = "Python package for providing Mozilla's CA Bundle."
35 | optional = true
36 | python-versions = ">=3.6"
37 | files = [
38 | {file = "certifi-2024.8.30-py3-none-any.whl", hash = "sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8"},
39 | {file = "certifi-2024.8.30.tar.gz", hash = "sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9"},
40 | ]
41 |
42 | [[package]]
43 | name = "charset-normalizer"
44 | version = "3.4.0"
45 | description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
46 | optional = true
47 | python-versions = ">=3.7.0"
48 | files = [
49 | {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:4f9fc98dad6c2eaa32fc3af1417d95b5e3d08aff968df0cd320066def971f9a6"},
50 | {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0de7b687289d3c1b3e8660d0741874abe7888100efe14bd0f9fd7141bcbda92b"},
51 | {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5ed2e36c3e9b4f21dd9422f6893dec0abf2cca553af509b10cd630f878d3eb99"},
52 | {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40d3ff7fc90b98c637bda91c89d51264a3dcf210cade3a2c6f838c7268d7a4ca"},
53 | {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1110e22af8ca26b90bd6364fe4c763329b0ebf1ee213ba32b68c73de5752323d"},
54 | {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:86f4e8cca779080f66ff4f191a685ced73d2f72d50216f7112185dc02b90b9b7"},
55 | {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f683ddc7eedd742e2889d2bfb96d69573fde1d92fcb811979cdb7165bb9c7d3"},
56 | {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:27623ba66c183eca01bf9ff833875b459cad267aeeb044477fedac35e19ba907"},
57 | {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f606a1881d2663630ea5b8ce2efe2111740df4b687bd78b34a8131baa007f79b"},
58 | {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:0b309d1747110feb25d7ed6b01afdec269c647d382c857ef4663bbe6ad95a912"},
59 | {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:136815f06a3ae311fae551c3df1f998a1ebd01ddd424aa5603a4336997629e95"},
60 | {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:14215b71a762336254351b00ec720a8e85cada43b987da5a042e4ce3e82bd68e"},
61 | {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:79983512b108e4a164b9c8d34de3992f76d48cadc9554c9e60b43f308988aabe"},
62 | {file = "charset_normalizer-3.4.0-cp310-cp310-win32.whl", hash = "sha256:c94057af19bc953643a33581844649a7fdab902624d2eb739738a30e2b3e60fc"},
63 | {file = "charset_normalizer-3.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:55f56e2ebd4e3bc50442fbc0888c9d8c94e4e06a933804e2af3e89e2f9c1c749"},
64 | {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0d99dd8ff461990f12d6e42c7347fd9ab2532fb70e9621ba520f9e8637161d7c"},
65 | {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c57516e58fd17d03ebe67e181a4e4e2ccab1168f8c2976c6a334d4f819fe5944"},
66 | {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6dba5d19c4dfab08e58d5b36304b3f92f3bd5d42c1a3fa37b5ba5cdf6dfcbcee"},
67 | {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf4475b82be41b07cc5e5ff94810e6a01f276e37c2d55571e3fe175e467a1a1c"},
68 | {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce031db0408e487fd2775d745ce30a7cd2923667cf3b69d48d219f1d8f5ddeb6"},
69 | {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ff4e7cdfdb1ab5698e675ca622e72d58a6fa2a8aa58195de0c0061288e6e3ea"},
70 | {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3710a9751938947e6327ea9f3ea6332a09bf0ba0c09cae9cb1f250bd1f1549bc"},
71 | {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82357d85de703176b5587dbe6ade8ff67f9f69a41c0733cf2425378b49954de5"},
72 | {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:47334db71978b23ebcf3c0f9f5ee98b8d65992b65c9c4f2d34c2eaf5bcaf0594"},
73 | {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8ce7fd6767a1cc5a92a639b391891bf1c268b03ec7e021c7d6d902285259685c"},
74 | {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f1a2f519ae173b5b6a2c9d5fa3116ce16e48b3462c8b96dfdded11055e3d6365"},
75 | {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:63bc5c4ae26e4bc6be6469943b8253c0fd4e4186c43ad46e713ea61a0ba49129"},
76 | {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bcb4f8ea87d03bc51ad04add8ceaf9b0f085ac045ab4d74e73bbc2dc033f0236"},
77 | {file = "charset_normalizer-3.4.0-cp311-cp311-win32.whl", hash = "sha256:9ae4ef0b3f6b41bad6366fb0ea4fc1d7ed051528e113a60fa2a65a9abb5b1d99"},
78 | {file = "charset_normalizer-3.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:cee4373f4d3ad28f1ab6290684d8e2ebdb9e7a1b74fdc39e4c211995f77bec27"},
79 | {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0713f3adb9d03d49d365b70b84775d0a0d18e4ab08d12bc46baa6132ba78aaf6"},
80 | {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:de7376c29d95d6719048c194a9cf1a1b0393fbe8488a22008610b0361d834ecf"},
81 | {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4a51b48f42d9358460b78725283f04bddaf44a9358197b889657deba38f329db"},
82 | {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b295729485b06c1a0683af02a9e42d2caa9db04a373dc38a6a58cdd1e8abddf1"},
83 | {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ee803480535c44e7f5ad00788526da7d85525cfefaf8acf8ab9a310000be4b03"},
84 | {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d59d125ffbd6d552765510e3f31ed75ebac2c7470c7274195b9161a32350284"},
85 | {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8cda06946eac330cbe6598f77bb54e690b4ca93f593dee1568ad22b04f347c15"},
86 | {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07afec21bbbbf8a5cc3651aa96b980afe2526e7f048fdfb7f1014d84acc8b6d8"},
87 | {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6b40e8d38afe634559e398cc32b1472f376a4099c75fe6299ae607e404c033b2"},
88 | {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b8dcd239c743aa2f9c22ce674a145e0a25cb1566c495928440a181ca1ccf6719"},
89 | {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:84450ba661fb96e9fd67629b93d2941c871ca86fc38d835d19d4225ff946a631"},
90 | {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:44aeb140295a2f0659e113b31cfe92c9061622cadbc9e2a2f7b8ef6b1e29ef4b"},
91 | {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1db4e7fefefd0f548d73e2e2e041f9df5c59e178b4c72fbac4cc6f535cfb1565"},
92 | {file = "charset_normalizer-3.4.0-cp312-cp312-win32.whl", hash = "sha256:5726cf76c982532c1863fb64d8c6dd0e4c90b6ece9feb06c9f202417a31f7dd7"},
93 | {file = "charset_normalizer-3.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:b197e7094f232959f8f20541ead1d9862ac5ebea1d58e9849c1bf979255dfac9"},
94 | {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:dd4eda173a9fcccb5f2e2bd2a9f423d180194b1bf17cf59e3269899235b2a114"},
95 | {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e9e3c4c9e1ed40ea53acf11e2a386383c3304212c965773704e4603d589343ed"},
96 | {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:92a7e36b000bf022ef3dbb9c46bfe2d52c047d5e3f3343f43204263c5addc250"},
97 | {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54b6a92d009cbe2fb11054ba694bc9e284dad30a26757b1e372a1fdddaf21920"},
98 | {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ffd9493de4c922f2a38c2bf62b831dcec90ac673ed1ca182fe11b4d8e9f2a64"},
99 | {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:35c404d74c2926d0287fbd63ed5d27eb911eb9e4a3bb2c6d294f3cfd4a9e0c23"},
100 | {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4796efc4faf6b53a18e3d46343535caed491776a22af773f366534056c4e1fbc"},
101 | {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e7fdd52961feb4c96507aa649550ec2a0d527c086d284749b2f582f2d40a2e0d"},
102 | {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:92db3c28b5b2a273346bebb24857fda45601aef6ae1c011c0a997106581e8a88"},
103 | {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ab973df98fc99ab39080bfb0eb3a925181454d7c3ac8a1e695fddfae696d9e90"},
104 | {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4b67fdab07fdd3c10bb21edab3cbfe8cf5696f453afce75d815d9d7223fbe88b"},
105 | {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:aa41e526a5d4a9dfcfbab0716c7e8a1b215abd3f3df5a45cf18a12721d31cb5d"},
106 | {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ffc519621dce0c767e96b9c53f09c5d215578e10b02c285809f76509a3931482"},
107 | {file = "charset_normalizer-3.4.0-cp313-cp313-win32.whl", hash = "sha256:f19c1585933c82098c2a520f8ec1227f20e339e33aca8fa6f956f6691b784e67"},
108 | {file = "charset_normalizer-3.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:707b82d19e65c9bd28b81dde95249b07bf9f5b90ebe1ef17d9b57473f8a64b7b"},
109 | {file = "charset_normalizer-3.4.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:dbe03226baf438ac4fda9e2d0715022fd579cb641c4cf639fa40d53b2fe6f3e2"},
110 | {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd9a8bd8900e65504a305bf8ae6fa9fbc66de94178c420791d0293702fce2df7"},
111 | {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8831399554b92b72af5932cdbbd4ddc55c55f631bb13ff8fe4e6536a06c5c51"},
112 | {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a14969b8691f7998e74663b77b4c36c0337cb1df552da83d5c9004a93afdb574"},
113 | {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dcaf7c1524c0542ee2fc82cc8ec337f7a9f7edee2532421ab200d2b920fc97cf"},
114 | {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:425c5f215d0eecee9a56cdb703203dda90423247421bf0d67125add85d0c4455"},
115 | {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:d5b054862739d276e09928de37c79ddeec42a6e1bfc55863be96a36ba22926f6"},
116 | {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:f3e73a4255342d4eb26ef6df01e3962e73aa29baa3124a8e824c5d3364a65748"},
117 | {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:2f6c34da58ea9c1a9515621f4d9ac379871a8f21168ba1b5e09d74250de5ad62"},
118 | {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:f09cb5a7bbe1ecae6e87901a2eb23e0256bb524a79ccc53eb0b7629fbe7677c4"},
119 | {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:0099d79bdfcf5c1f0c2c72f91516702ebf8b0b8ddd8905f97a8aecf49712c621"},
120 | {file = "charset_normalizer-3.4.0-cp37-cp37m-win32.whl", hash = "sha256:9c98230f5042f4945f957d006edccc2af1e03ed5e37ce7c373f00a5a4daa6149"},
121 | {file = "charset_normalizer-3.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:62f60aebecfc7f4b82e3f639a7d1433a20ec32824db2199a11ad4f5e146ef5ee"},
122 | {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:af73657b7a68211996527dbfeffbb0864e043d270580c5aef06dc4b659a4b578"},
123 | {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cab5d0b79d987c67f3b9e9c53f54a61360422a5a0bc075f43cab5621d530c3b6"},
124 | {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9289fd5dddcf57bab41d044f1756550f9e7cf0c8e373b8cdf0ce8773dc4bd417"},
125 | {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b493a043635eb376e50eedf7818f2f322eabbaa974e948bd8bdd29eb7ef2a51"},
126 | {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fa2566ca27d67c86569e8c85297aaf413ffab85a8960500f12ea34ff98e4c41"},
127 | {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8e538f46104c815be19c975572d74afb53f29650ea2025bbfaef359d2de2f7f"},
128 | {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fd30dc99682dc2c603c2b315bded2799019cea829f8bf57dc6b61efde6611c8"},
129 | {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2006769bd1640bdf4d5641c69a3d63b71b81445473cac5ded39740a226fa88ab"},
130 | {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:dc15e99b2d8a656f8e666854404f1ba54765871104e50c8e9813af8a7db07f12"},
131 | {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:ab2e5bef076f5a235c3774b4f4028a680432cded7cad37bba0fd90d64b187d19"},
132 | {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:4ec9dd88a5b71abfc74e9df5ebe7921c35cbb3b641181a531ca65cdb5e8e4dea"},
133 | {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:43193c5cda5d612f247172016c4bb71251c784d7a4d9314677186a838ad34858"},
134 | {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:aa693779a8b50cd97570e5a0f343538a8dbd3e496fa5dcb87e29406ad0299654"},
135 | {file = "charset_normalizer-3.4.0-cp38-cp38-win32.whl", hash = "sha256:7706f5850360ac01d80c89bcef1640683cc12ed87f42579dab6c5d3ed6888613"},
136 | {file = "charset_normalizer-3.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:c3e446d253bd88f6377260d07c895816ebf33ffffd56c1c792b13bff9c3e1ade"},
137 | {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:980b4f289d1d90ca5efcf07958d3eb38ed9c0b7676bf2831a54d4f66f9c27dfa"},
138 | {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f28f891ccd15c514a0981f3b9db9aa23d62fe1a99997512b0491d2ed323d229a"},
139 | {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8aacce6e2e1edcb6ac625fb0f8c3a9570ccc7bfba1f63419b3769ccf6a00ed0"},
140 | {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd7af3717683bea4c87acd8c0d3d5b44d56120b26fd3f8a692bdd2d5260c620a"},
141 | {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5ff2ed8194587faf56555927b3aa10e6fb69d931e33953943bc4f837dfee2242"},
142 | {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e91f541a85298cf35433bf66f3fab2a4a2cff05c127eeca4af174f6d497f0d4b"},
143 | {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:309a7de0a0ff3040acaebb35ec45d18db4b28232f21998851cfa709eeff49d62"},
144 | {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:285e96d9d53422efc0d7a17c60e59f37fbf3dfa942073f666db4ac71e8d726d0"},
145 | {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:5d447056e2ca60382d460a604b6302d8db69476fd2015c81e7c35417cfabe4cd"},
146 | {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:20587d20f557fe189b7947d8e7ec5afa110ccf72a3128d61a2a387c3313f46be"},
147 | {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:130272c698667a982a5d0e626851ceff662565379baf0ff2cc58067b81d4f11d"},
148 | {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:ab22fbd9765e6954bc0bcff24c25ff71dcbfdb185fcdaca49e81bac68fe724d3"},
149 | {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7782afc9b6b42200f7362858f9e73b1f8316afb276d316336c0ec3bd73312742"},
150 | {file = "charset_normalizer-3.4.0-cp39-cp39-win32.whl", hash = "sha256:2de62e8801ddfff069cd5c504ce3bc9672b23266597d4e4f50eda28846c322f2"},
151 | {file = "charset_normalizer-3.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:95c3c157765b031331dd4db3c775e58deaee050a3042fcad72cbc4189d7c8dca"},
152 | {file = "charset_normalizer-3.4.0-py3-none-any.whl", hash = "sha256:fe9f97feb71aa9896b81973a7bbada8c49501dc73e58a10fcef6663af95e5079"},
153 | {file = "charset_normalizer-3.4.0.tar.gz", hash = "sha256:223217c3d4f82c3ac5e29032b3f1c2eb0fb591b72161f86d93f5719079dae93e"},
154 | ]
155 |
156 | [[package]]
157 | name = "click"
158 | version = "8.1.7"
159 | description = "Composable command line interface toolkit"
160 | optional = true
161 | python-versions = ">=3.7"
162 | files = [
163 | {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"},
164 | {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"},
165 | ]
166 |
167 | [package.dependencies]
168 | colorama = {version = "*", markers = "platform_system == \"Windows\""}
169 |
170 | [[package]]
171 | name = "colorama"
172 | version = "0.4.6"
173 | description = "Cross-platform colored terminal text."
174 | optional = false
175 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
176 | files = [
177 | {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
178 | {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
179 | ]
180 |
181 | [[package]]
182 | name = "coloredlogs"
183 | version = "15.0.1"
184 | description = "Colored terminal output for Python's logging module"
185 | optional = false
186 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
187 | files = [
188 | {file = "coloredlogs-15.0.1-py2.py3-none-any.whl", hash = "sha256:612ee75c546f53e92e70049c9dbfcc18c935a2b9a53b66085ce9ef6a6e5c0934"},
189 | {file = "coloredlogs-15.0.1.tar.gz", hash = "sha256:7c991aa71a4577af2f82600d8f8f3a89f936baeaf9b50a9c197da014e5bf16b0"},
190 | ]
191 |
192 | [package.dependencies]
193 | humanfriendly = ">=9.1"
194 |
195 | [package.extras]
196 | cron = ["capturer (>=2.4)"]
197 |
198 | [[package]]
199 | name = "dill"
200 | version = "0.3.8"
201 | description = "serialize all of Python"
202 | optional = false
203 | python-versions = ">=3.8"
204 | files = [
205 | {file = "dill-0.3.8-py3-none-any.whl", hash = "sha256:c36ca9ffb54365bdd2f8eb3eff7d2a21237f8452b57ace88b1ac615b7e815bd7"},
206 | {file = "dill-0.3.8.tar.gz", hash = "sha256:3ebe3c479ad625c4553aca177444d89b486b1d84982eeacded644afc0cf797ca"},
207 | ]
208 |
209 | [package.extras]
210 | graph = ["objgraph (>=1.7.2)"]
211 | profile = ["gprof2dot (>=2022.7.29)"]
212 |
213 | [[package]]
214 | name = "exceptiongroup"
215 | version = "1.2.0"
216 | description = "Backport of PEP 654 (exception groups)"
217 | optional = false
218 | python-versions = ">=3.7"
219 | files = [
220 | {file = "exceptiongroup-1.2.0-py3-none-any.whl", hash = "sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14"},
221 | {file = "exceptiongroup-1.2.0.tar.gz", hash = "sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68"},
222 | ]
223 |
224 | [package.extras]
225 | test = ["pytest (>=6)"]
226 |
227 | [[package]]
228 | name = "fast-plate-ocr"
229 | version = "0.3.0"
230 | description = "Fast & Lightweight OCR for vehicle license plates."
231 | optional = false
232 | python-versions = "<4.0,>=3.10"
233 | files = [
234 | {file = "fast_plate_ocr-0.3.0-py3-none-any.whl", hash = "sha256:9dcc2ddbb51a6261fedcf5e8c5af9a8907f4a2fa6242dbe4658a491876e89a4b"},
235 | {file = "fast_plate_ocr-0.3.0.tar.gz", hash = "sha256:141f6fcefdd43fa688b8252f7e30d45e5aec2d38716e896b9562307fcbb923e8"},
236 | ]
237 |
238 | [package.dependencies]
239 | numpy = ">=1.20"
240 | onnxruntime = {version = ">=1.19.2", markers = "sys_platform == \"darwin\" or platform_machine == \"armv7l\" or platform_machine == \"aarch64\""}
241 | onnxruntime-gpu = {version = ">=1.19.2", markers = "sys_platform != \"darwin\" and (platform_machine != \"armv7l\" and platform_machine != \"aarch64\") and (platform_system == \"Linux\" or platform_system == \"Windows\")"}
242 | opencv-python = "*"
243 | pyyaml = ">=5.1"
244 | rich = "*"
245 | tqdm = "*"
246 |
247 | [package.extras]
248 | docs = ["mike", "mkdocs-material", "mkdocstrings[python]"]
249 | train = ["albumentations", "click", "keras (>=3.1.1)", "matplotlib", "onnxsim (>0.4.10)", "pandas", "pydantic (>=2.0.0,<3.0.0)", "tensorboard", "tensorflow", "tf2onnx", "torch"]
250 |
251 | [[package]]
252 | name = "flatbuffers"
253 | version = "24.3.25"
254 | description = "The FlatBuffers serialization format for Python"
255 | optional = false
256 | python-versions = "*"
257 | files = [
258 | {file = "flatbuffers-24.3.25-py2.py3-none-any.whl", hash = "sha256:8dbdec58f935f3765e4f7f3cf635ac3a77f83568138d6a2311f524ec96364812"},
259 | {file = "flatbuffers-24.3.25.tar.gz", hash = "sha256:de2ec5b203f21441716617f38443e0a8ebf3d25bf0d9c0bb0ce68fa00ad546a4"},
260 | ]
261 |
262 | [[package]]
263 | name = "ghp-import"
264 | version = "2.1.0"
265 | description = "Copy your docs directly to the gh-pages branch."
266 | optional = true
267 | python-versions = "*"
268 | files = [
269 | {file = "ghp-import-2.1.0.tar.gz", hash = "sha256:9c535c4c61193c2df8871222567d7fd7e5014d835f97dc7b7439069e2413d343"},
270 | {file = "ghp_import-2.1.0-py3-none-any.whl", hash = "sha256:8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619"},
271 | ]
272 |
273 | [package.dependencies]
274 | python-dateutil = ">=2.8.1"
275 |
276 | [package.extras]
277 | dev = ["flake8", "markdown", "twine", "wheel"]
278 |
279 | [[package]]
280 | name = "griffe"
281 | version = "1.5.1"
282 | 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."
283 | optional = true
284 | python-versions = ">=3.9"
285 | files = [
286 | {file = "griffe-1.5.1-py3-none-any.whl", hash = "sha256:ad6a7980f8c424c9102160aafa3bcdf799df0e75f7829d75af9ee5aef656f860"},
287 | {file = "griffe-1.5.1.tar.gz", hash = "sha256:72964f93e08c553257706d6cd2c42d1c172213feb48b2be386f243380b405d4b"},
288 | ]
289 |
290 | [package.dependencies]
291 | colorama = ">=0.4"
292 |
293 | [[package]]
294 | name = "humanfriendly"
295 | version = "10.0"
296 | description = "Human friendly output for text interfaces using Python"
297 | optional = false
298 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
299 | files = [
300 | {file = "humanfriendly-10.0-py2.py3-none-any.whl", hash = "sha256:1697e1a8a8f550fd43c2865cd84542fc175a61dcb779b6fee18cf6b6ccba1477"},
301 | {file = "humanfriendly-10.0.tar.gz", hash = "sha256:6b0b831ce8f15f7300721aa49829fc4e83921a9a301cc7f606be6686a2288ddc"},
302 | ]
303 |
304 | [package.dependencies]
305 | pyreadline3 = {version = "*", markers = "sys_platform == \"win32\" and python_version >= \"3.8\""}
306 |
307 | [[package]]
308 | name = "idna"
309 | version = "3.10"
310 | description = "Internationalized Domain Names in Applications (IDNA)"
311 | optional = true
312 | python-versions = ">=3.6"
313 | files = [
314 | {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"},
315 | {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"},
316 | ]
317 |
318 | [package.extras]
319 | all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"]
320 |
321 | [[package]]
322 | name = "importlib-metadata"
323 | version = "8.5.0"
324 | description = "Read metadata from Python packages"
325 | optional = true
326 | python-versions = ">=3.8"
327 | files = [
328 | {file = "importlib_metadata-8.5.0-py3-none-any.whl", hash = "sha256:45e54197d28b7a7f1559e60b95e7c567032b602131fbd588f1497f47880aa68b"},
329 | {file = "importlib_metadata-8.5.0.tar.gz", hash = "sha256:71522656f0abace1d072b9e5481a48f07c138e00f079c38c8f883823f9c26bd7"},
330 | ]
331 |
332 | [package.dependencies]
333 | zipp = ">=3.20"
334 |
335 | [package.extras]
336 | check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)"]
337 | cover = ["pytest-cov"]
338 | doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
339 | enabler = ["pytest-enabler (>=2.2)"]
340 | perf = ["ipython"]
341 | test = ["flufl.flake8", "importlib-resources (>=1.3)", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-perf (>=0.9.2)"]
342 | type = ["pytest-mypy"]
343 |
344 | [[package]]
345 | name = "importlib-resources"
346 | version = "6.4.5"
347 | description = "Read resources from Python packages"
348 | optional = true
349 | python-versions = ">=3.8"
350 | files = [
351 | {file = "importlib_resources-6.4.5-py3-none-any.whl", hash = "sha256:ac29d5f956f01d5e4bb63102a5a19957f1b9175e45649977264a1416783bb717"},
352 | {file = "importlib_resources-6.4.5.tar.gz", hash = "sha256:980862a1d16c9e147a59603677fa2aa5fd82b87f223b6cb870695bcfce830065"},
353 | ]
354 |
355 | [package.extras]
356 | check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)"]
357 | cover = ["pytest-cov"]
358 | doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
359 | enabler = ["pytest-enabler (>=2.2)"]
360 | test = ["jaraco.test (>=5.4)", "pytest (>=6,!=8.1.*)", "zipp (>=3.17)"]
361 | type = ["pytest-mypy"]
362 |
363 | [[package]]
364 | name = "iniconfig"
365 | version = "2.0.0"
366 | description = "brain-dead simple config-ini parsing"
367 | optional = false
368 | python-versions = ">=3.7"
369 | files = [
370 | {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"},
371 | {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"},
372 | ]
373 |
374 | [[package]]
375 | name = "isort"
376 | version = "5.13.2"
377 | description = "A Python utility / library to sort Python imports."
378 | optional = false
379 | python-versions = ">=3.8.0"
380 | files = [
381 | {file = "isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"},
382 | {file = "isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109"},
383 | ]
384 |
385 | [package.extras]
386 | colors = ["colorama (>=0.4.6)"]
387 |
388 | [[package]]
389 | name = "jinja2"
390 | version = "3.1.4"
391 | description = "A very fast and expressive template engine."
392 | optional = true
393 | python-versions = ">=3.7"
394 | files = [
395 | {file = "jinja2-3.1.4-py3-none-any.whl", hash = "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d"},
396 | {file = "jinja2-3.1.4.tar.gz", hash = "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369"},
397 | ]
398 |
399 | [package.dependencies]
400 | MarkupSafe = ">=2.0"
401 |
402 | [package.extras]
403 | i18n = ["Babel (>=2.7)"]
404 |
405 | [[package]]
406 | name = "markdown"
407 | version = "3.7"
408 | description = "Python implementation of John Gruber's Markdown."
409 | optional = true
410 | python-versions = ">=3.8"
411 | files = [
412 | {file = "Markdown-3.7-py3-none-any.whl", hash = "sha256:7eb6df5690b81a1d7942992c97fad2938e956e79df20cbc6186e9c3a77b1c803"},
413 | {file = "markdown-3.7.tar.gz", hash = "sha256:2ae2471477cfd02dbbf038d5d9bc226d40def84b4fe2986e49b59b6b472bbed2"},
414 | ]
415 |
416 | [package.extras]
417 | docs = ["mdx-gh-links (>=0.2)", "mkdocs (>=1.5)", "mkdocs-gen-files", "mkdocs-literate-nav", "mkdocs-nature (>=0.6)", "mkdocs-section-index", "mkdocstrings[python]"]
418 | testing = ["coverage", "pyyaml"]
419 |
420 | [[package]]
421 | name = "markdown-it-py"
422 | version = "3.0.0"
423 | description = "Python port of markdown-it. Markdown parsing, done right!"
424 | optional = false
425 | python-versions = ">=3.8"
426 | files = [
427 | {file = "markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb"},
428 | {file = "markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1"},
429 | ]
430 |
431 | [package.dependencies]
432 | mdurl = ">=0.1,<1.0"
433 |
434 | [package.extras]
435 | benchmarking = ["psutil", "pytest", "pytest-benchmark"]
436 | code-style = ["pre-commit (>=3.0,<4.0)"]
437 | compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "mistletoe (>=1.0,<2.0)", "mistune (>=2.0,<3.0)", "panflute (>=2.3,<3.0)"]
438 | linkify = ["linkify-it-py (>=1,<3)"]
439 | plugins = ["mdit-py-plugins"]
440 | profiling = ["gprof2dot"]
441 | rtd = ["jupyter_sphinx", "mdit-py-plugins", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"]
442 | testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"]
443 |
444 | [[package]]
445 | name = "markupsafe"
446 | version = "3.0.2"
447 | description = "Safely add untrusted strings to HTML/XML markup."
448 | optional = true
449 | python-versions = ">=3.9"
450 | files = [
451 | {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8"},
452 | {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158"},
453 | {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38a9ef736c01fccdd6600705b09dc574584b89bea478200c5fbf112a6b0d5579"},
454 | {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbcb445fa71794da8f178f0f6d66789a28d7319071af7a496d4d507ed566270d"},
455 | {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57cb5a3cf367aeb1d316576250f65edec5bb3be939e9247ae594b4bcbc317dfb"},
456 | {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3809ede931876f5b2ec92eef964286840ed3540dadf803dd570c3b7e13141a3b"},
457 | {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e07c3764494e3776c602c1e78e298937c3315ccc9043ead7e685b7f2b8d47b3c"},
458 | {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b424c77b206d63d500bcb69fa55ed8d0e6a3774056bdc4839fc9298a7edca171"},
459 | {file = "MarkupSafe-3.0.2-cp310-cp310-win32.whl", hash = "sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50"},
460 | {file = "MarkupSafe-3.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:6af100e168aa82a50e186c82875a5893c5597a0c1ccdb0d8b40240b1f28b969a"},
461 | {file = "MarkupSafe-3.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d"},
462 | {file = "MarkupSafe-3.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93"},
463 | {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832"},
464 | {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84"},
465 | {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca"},
466 | {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798"},
467 | {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e"},
468 | {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4"},
469 | {file = "MarkupSafe-3.0.2-cp311-cp311-win32.whl", hash = "sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d"},
470 | {file = "MarkupSafe-3.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b"},
471 | {file = "MarkupSafe-3.0.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf"},
472 | {file = "MarkupSafe-3.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225"},
473 | {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028"},
474 | {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8"},
475 | {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c"},
476 | {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557"},
477 | {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22"},
478 | {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48"},
479 | {file = "MarkupSafe-3.0.2-cp312-cp312-win32.whl", hash = "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30"},
480 | {file = "MarkupSafe-3.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87"},
481 | {file = "MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd"},
482 | {file = "MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430"},
483 | {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094"},
484 | {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396"},
485 | {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79"},
486 | {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a"},
487 | {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca"},
488 | {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c"},
489 | {file = "MarkupSafe-3.0.2-cp313-cp313-win32.whl", hash = "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1"},
490 | {file = "MarkupSafe-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f"},
491 | {file = "MarkupSafe-3.0.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c"},
492 | {file = "MarkupSafe-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb"},
493 | {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c"},
494 | {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d"},
495 | {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe"},
496 | {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5"},
497 | {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a"},
498 | {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9"},
499 | {file = "MarkupSafe-3.0.2-cp313-cp313t-win32.whl", hash = "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6"},
500 | {file = "MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f"},
501 | {file = "MarkupSafe-3.0.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:eaa0a10b7f72326f1372a713e73c3f739b524b3af41feb43e4921cb529f5929a"},
502 | {file = "MarkupSafe-3.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:48032821bbdf20f5799ff537c7ac3d1fba0ba032cfc06194faffa8cda8b560ff"},
503 | {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a9d3f5f0901fdec14d8d2f66ef7d035f2157240a433441719ac9a3fba440b13"},
504 | {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88b49a3b9ff31e19998750c38e030fc7bb937398b1f78cfa599aaef92d693144"},
505 | {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cfad01eed2c2e0c01fd0ecd2ef42c492f7f93902e39a42fc9ee1692961443a29"},
506 | {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1225beacc926f536dc82e45f8a4d68502949dc67eea90eab715dea3a21c1b5f0"},
507 | {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:3169b1eefae027567d1ce6ee7cae382c57fe26e82775f460f0b2778beaad66c0"},
508 | {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:eb7972a85c54febfb25b5c4b4f3af4dcc731994c7da0d8a0b4a6eb0640e1d178"},
509 | {file = "MarkupSafe-3.0.2-cp39-cp39-win32.whl", hash = "sha256:8c4e8c3ce11e1f92f6536ff07154f9d49677ebaaafc32db9db4620bc11ed480f"},
510 | {file = "MarkupSafe-3.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:6e296a513ca3d94054c2c881cc913116e90fd030ad1c656b3869762b754f5f8a"},
511 | {file = "markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0"},
512 | ]
513 |
514 | [[package]]
515 | name = "mccabe"
516 | version = "0.7.0"
517 | description = "McCabe checker, plugin for flake8"
518 | optional = false
519 | python-versions = ">=3.6"
520 | files = [
521 | {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"},
522 | {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"},
523 | ]
524 |
525 | [[package]]
526 | name = "mdurl"
527 | version = "0.1.2"
528 | description = "Markdown URL utilities"
529 | optional = false
530 | python-versions = ">=3.7"
531 | files = [
532 | {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"},
533 | {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"},
534 | ]
535 |
536 | [[package]]
537 | name = "mergedeep"
538 | version = "1.3.4"
539 | description = "A deep merge function for 🐍."
540 | optional = true
541 | python-versions = ">=3.6"
542 | files = [
543 | {file = "mergedeep-1.3.4-py3-none-any.whl", hash = "sha256:70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307"},
544 | {file = "mergedeep-1.3.4.tar.gz", hash = "sha256:0096d52e9dad9939c3d975a774666af186eda617e6ca84df4c94dec30004f2a8"},
545 | ]
546 |
547 | [[package]]
548 | name = "mike"
549 | version = "2.1.3"
550 | description = "Manage multiple versions of your MkDocs-powered documentation"
551 | optional = true
552 | python-versions = "*"
553 | files = [
554 | {file = "mike-2.1.3-py3-none-any.whl", hash = "sha256:d90c64077e84f06272437b464735130d380703a76a5738b152932884c60c062a"},
555 | {file = "mike-2.1.3.tar.gz", hash = "sha256:abd79b8ea483fb0275b7972825d3082e5ae67a41820f8d8a0dc7a3f49944e810"},
556 | ]
557 |
558 | [package.dependencies]
559 | importlib-metadata = "*"
560 | importlib-resources = "*"
561 | jinja2 = ">=2.7"
562 | mkdocs = ">=1.0"
563 | pyparsing = ">=3.0"
564 | pyyaml = ">=5.1"
565 | pyyaml-env-tag = "*"
566 | verspec = "*"
567 |
568 | [package.extras]
569 | dev = ["coverage", "flake8 (>=3.0)", "flake8-quotes", "shtab"]
570 | test = ["coverage", "flake8 (>=3.0)", "flake8-quotes", "shtab"]
571 |
572 | [[package]]
573 | name = "mkdocs"
574 | version = "1.6.1"
575 | description = "Project documentation with Markdown."
576 | optional = true
577 | python-versions = ">=3.8"
578 | files = [
579 | {file = "mkdocs-1.6.1-py3-none-any.whl", hash = "sha256:db91759624d1647f3f34aa0c3f327dd2601beae39a366d6e064c03468d35c20e"},
580 | {file = "mkdocs-1.6.1.tar.gz", hash = "sha256:7b432f01d928c084353ab39c57282f29f92136665bdd6abf7c1ec8d822ef86f2"},
581 | ]
582 |
583 | [package.dependencies]
584 | click = ">=7.0"
585 | colorama = {version = ">=0.4", markers = "platform_system == \"Windows\""}
586 | ghp-import = ">=1.0"
587 | jinja2 = ">=2.11.1"
588 | markdown = ">=3.3.6"
589 | markupsafe = ">=2.0.1"
590 | mergedeep = ">=1.3.4"
591 | mkdocs-get-deps = ">=0.2.0"
592 | packaging = ">=20.5"
593 | pathspec = ">=0.11.1"
594 | pyyaml = ">=5.1"
595 | pyyaml-env-tag = ">=0.1"
596 | watchdog = ">=2.0"
597 |
598 | [package.extras]
599 | i18n = ["babel (>=2.9.0)"]
600 | min-versions = ["babel (==2.9.0)", "click (==7.0)", "colorama (==0.4)", "ghp-import (==1.0)", "importlib-metadata (==4.4)", "jinja2 (==2.11.1)", "markdown (==3.3.6)", "markupsafe (==2.0.1)", "mergedeep (==1.3.4)", "mkdocs-get-deps (==0.2.0)", "packaging (==20.5)", "pathspec (==0.11.1)", "pyyaml (==5.1)", "pyyaml-env-tag (==0.1)", "watchdog (==2.0)"]
601 |
602 | [[package]]
603 | name = "mkdocs-autorefs"
604 | version = "1.2.0"
605 | description = "Automatically link across pages in MkDocs."
606 | optional = true
607 | python-versions = ">=3.8"
608 | files = [
609 | {file = "mkdocs_autorefs-1.2.0-py3-none-any.whl", hash = "sha256:d588754ae89bd0ced0c70c06f58566a4ee43471eeeee5202427da7de9ef85a2f"},
610 | {file = "mkdocs_autorefs-1.2.0.tar.gz", hash = "sha256:a86b93abff653521bda71cf3fc5596342b7a23982093915cb74273f67522190f"},
611 | ]
612 |
613 | [package.dependencies]
614 | Markdown = ">=3.3"
615 | markupsafe = ">=2.0.1"
616 | mkdocs = ">=1.1"
617 |
618 | [[package]]
619 | name = "mkdocs-get-deps"
620 | version = "0.2.0"
621 | description = "MkDocs extension that lists all dependencies according to a mkdocs.yml file"
622 | optional = true
623 | python-versions = ">=3.8"
624 | files = [
625 | {file = "mkdocs_get_deps-0.2.0-py3-none-any.whl", hash = "sha256:2bf11d0b133e77a0dd036abeeb06dec8775e46efa526dc70667d8863eefc6134"},
626 | {file = "mkdocs_get_deps-0.2.0.tar.gz", hash = "sha256:162b3d129c7fad9b19abfdcb9c1458a651628e4b1dea628ac68790fb3061c60c"},
627 | ]
628 |
629 | [package.dependencies]
630 | mergedeep = ">=1.3.4"
631 | platformdirs = ">=2.2.0"
632 | pyyaml = ">=5.1"
633 |
634 | [[package]]
635 | name = "mkdocs-material"
636 | version = "9.5.43"
637 | description = "Documentation that simply works"
638 | optional = true
639 | python-versions = ">=3.8"
640 | files = [
641 | {file = "mkdocs_material-9.5.43-py3-none-any.whl", hash = "sha256:4aae0664c456fd12837a3192e0225c17960ba8bf55d7f0a7daef7e4b0b914a34"},
642 | {file = "mkdocs_material-9.5.43.tar.gz", hash = "sha256:83be7ff30b65a1e4930dfa4ab911e75780a3afc9583d162692e434581cb46979"},
643 | ]
644 |
645 | [package.dependencies]
646 | babel = ">=2.10,<3.0"
647 | colorama = ">=0.4,<1.0"
648 | jinja2 = ">=3.0,<4.0"
649 | markdown = ">=3.2,<4.0"
650 | mkdocs = ">=1.6,<2.0"
651 | mkdocs-material-extensions = ">=1.3,<2.0"
652 | paginate = ">=0.5,<1.0"
653 | pygments = ">=2.16,<3.0"
654 | pymdown-extensions = ">=10.2,<11.0"
655 | regex = ">=2022.4"
656 | requests = ">=2.26,<3.0"
657 |
658 | [package.extras]
659 | git = ["mkdocs-git-committers-plugin-2 (>=1.1,<2.0)", "mkdocs-git-revision-date-localized-plugin (>=1.2.4,<2.0)"]
660 | imaging = ["cairosvg (>=2.6,<3.0)", "pillow (>=10.2,<11.0)"]
661 | recommended = ["mkdocs-minify-plugin (>=0.7,<1.0)", "mkdocs-redirects (>=1.2,<2.0)", "mkdocs-rss-plugin (>=1.6,<2.0)"]
662 |
663 | [[package]]
664 | name = "mkdocs-material-extensions"
665 | version = "1.3.1"
666 | description = "Extension pack for Python Markdown and MkDocs Material."
667 | optional = true
668 | python-versions = ">=3.8"
669 | files = [
670 | {file = "mkdocs_material_extensions-1.3.1-py3-none-any.whl", hash = "sha256:adff8b62700b25cb77b53358dad940f3ef973dd6db797907c49e3c2ef3ab4e31"},
671 | {file = "mkdocs_material_extensions-1.3.1.tar.gz", hash = "sha256:10c9511cea88f568257f960358a467d12b970e1f7b2c0e5fb2bb48cab1928443"},
672 | ]
673 |
674 | [[package]]
675 | name = "mkdocstrings"
676 | version = "0.26.2"
677 | description = "Automatic documentation from sources, for MkDocs."
678 | optional = true
679 | python-versions = ">=3.9"
680 | files = [
681 | {file = "mkdocstrings-0.26.2-py3-none-any.whl", hash = "sha256:1248f3228464f3b8d1a15bd91249ce1701fe3104ac517a5f167a0e01ca850ba5"},
682 | {file = "mkdocstrings-0.26.2.tar.gz", hash = "sha256:34a8b50f1e6cfd29546c6c09fbe02154adfb0b361bb758834bf56aa284ba876e"},
683 | ]
684 |
685 | [package.dependencies]
686 | click = ">=7.0"
687 | Jinja2 = ">=2.11.1"
688 | Markdown = ">=3.6"
689 | MarkupSafe = ">=1.1"
690 | mkdocs = ">=1.4"
691 | mkdocs-autorefs = ">=1.2"
692 | mkdocstrings-python = {version = ">=0.5.2", optional = true, markers = "extra == \"python\""}
693 | platformdirs = ">=2.2"
694 | pymdown-extensions = ">=6.3"
695 |
696 | [package.extras]
697 | crystal = ["mkdocstrings-crystal (>=0.3.4)"]
698 | python = ["mkdocstrings-python (>=0.5.2)"]
699 | python-legacy = ["mkdocstrings-python-legacy (>=0.2.1)"]
700 |
701 | [[package]]
702 | name = "mkdocstrings-python"
703 | version = "1.12.2"
704 | description = "A Python handler for mkdocstrings."
705 | optional = true
706 | python-versions = ">=3.9"
707 | files = [
708 | {file = "mkdocstrings_python-1.12.2-py3-none-any.whl", hash = "sha256:7f7d40d6db3cb1f5d19dbcd80e3efe4d0ba32b073272c0c0de9de2e604eda62a"},
709 | {file = "mkdocstrings_python-1.12.2.tar.gz", hash = "sha256:7a1760941c0b52a2cd87b960a9e21112ffe52e7df9d0b9583d04d47ed2e186f3"},
710 | ]
711 |
712 | [package.dependencies]
713 | griffe = ">=0.49"
714 | mkdocs-autorefs = ">=1.2"
715 | mkdocstrings = ">=0.26"
716 |
717 | [[package]]
718 | name = "mpmath"
719 | version = "1.3.0"
720 | description = "Python library for arbitrary-precision floating-point arithmetic"
721 | optional = false
722 | python-versions = "*"
723 | files = [
724 | {file = "mpmath-1.3.0-py3-none-any.whl", hash = "sha256:a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c"},
725 | {file = "mpmath-1.3.0.tar.gz", hash = "sha256:7a28eb2a9774d00c7bc92411c19a89209d5da7c4c9a9e227be8330a23a25b91f"},
726 | ]
727 |
728 | [package.extras]
729 | develop = ["codecov", "pycodestyle", "pytest (>=4.6)", "pytest-cov", "wheel"]
730 | docs = ["sphinx"]
731 | gmpy = ["gmpy2 (>=2.1.0a4)"]
732 | tests = ["pytest (>=4.6)"]
733 |
734 | [[package]]
735 | name = "mypy"
736 | version = "1.9.0"
737 | description = "Optional static typing for Python"
738 | optional = false
739 | python-versions = ">=3.8"
740 | files = [
741 | {file = "mypy-1.9.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f8a67616990062232ee4c3952f41c779afac41405806042a8126fe96e098419f"},
742 | {file = "mypy-1.9.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d357423fa57a489e8c47b7c85dfb96698caba13d66e086b412298a1a0ea3b0ed"},
743 | {file = "mypy-1.9.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49c87c15aed320de9b438ae7b00c1ac91cd393c1b854c2ce538e2a72d55df150"},
744 | {file = "mypy-1.9.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:48533cdd345c3c2e5ef48ba3b0d3880b257b423e7995dada04248725c6f77374"},
745 | {file = "mypy-1.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:4d3dbd346cfec7cb98e6cbb6e0f3c23618af826316188d587d1c1bc34f0ede03"},
746 | {file = "mypy-1.9.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:653265f9a2784db65bfca694d1edd23093ce49740b2244cde583aeb134c008f3"},
747 | {file = "mypy-1.9.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3a3c007ff3ee90f69cf0a15cbcdf0995749569b86b6d2f327af01fd1b8aee9dc"},
748 | {file = "mypy-1.9.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2418488264eb41f69cc64a69a745fad4a8f86649af4b1041a4c64ee61fc61129"},
749 | {file = "mypy-1.9.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:68edad3dc7d70f2f17ae4c6c1b9471a56138ca22722487eebacfd1eb5321d612"},
750 | {file = "mypy-1.9.0-cp311-cp311-win_amd64.whl", hash = "sha256:85ca5fcc24f0b4aeedc1d02f93707bccc04733f21d41c88334c5482219b1ccb3"},
751 | {file = "mypy-1.9.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aceb1db093b04db5cd390821464504111b8ec3e351eb85afd1433490163d60cd"},
752 | {file = "mypy-1.9.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0235391f1c6f6ce487b23b9dbd1327b4ec33bb93934aa986efe8a9563d9349e6"},
753 | {file = "mypy-1.9.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d4d5ddc13421ba3e2e082a6c2d74c2ddb3979c39b582dacd53dd5d9431237185"},
754 | {file = "mypy-1.9.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:190da1ee69b427d7efa8aa0d5e5ccd67a4fb04038c380237a0d96829cb157913"},
755 | {file = "mypy-1.9.0-cp312-cp312-win_amd64.whl", hash = "sha256:fe28657de3bfec596bbeef01cb219833ad9d38dd5393fc649f4b366840baefe6"},
756 | {file = "mypy-1.9.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e54396d70be04b34f31d2edf3362c1edd023246c82f1730bbf8768c28db5361b"},
757 | {file = "mypy-1.9.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5e6061f44f2313b94f920e91b204ec600982961e07a17e0f6cd83371cb23f5c2"},
758 | {file = "mypy-1.9.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:81a10926e5473c5fc3da8abb04119a1f5811a236dc3a38d92015cb1e6ba4cb9e"},
759 | {file = "mypy-1.9.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b685154e22e4e9199fc95f298661deea28aaede5ae16ccc8cbb1045e716b3e04"},
760 | {file = "mypy-1.9.0-cp38-cp38-win_amd64.whl", hash = "sha256:5d741d3fc7c4da608764073089e5f58ef6352bedc223ff58f2f038c2c4698a89"},
761 | {file = "mypy-1.9.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:587ce887f75dd9700252a3abbc9c97bbe165a4a630597845c61279cf32dfbf02"},
762 | {file = "mypy-1.9.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f88566144752999351725ac623471661c9d1cd8caa0134ff98cceeea181789f4"},
763 | {file = "mypy-1.9.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:61758fabd58ce4b0720ae1e2fea5cfd4431591d6d590b197775329264f86311d"},
764 | {file = "mypy-1.9.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e49499be624dead83927e70c756970a0bc8240e9f769389cdf5714b0784ca6bf"},
765 | {file = "mypy-1.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:571741dc4194b4f82d344b15e8837e8c5fcc462d66d076748142327626a1b6e9"},
766 | {file = "mypy-1.9.0-py3-none-any.whl", hash = "sha256:a260627a570559181a9ea5de61ac6297aa5af202f06fd7ab093ce74e7181e43e"},
767 | {file = "mypy-1.9.0.tar.gz", hash = "sha256:3cc5da0127e6a478cddd906068496a97a7618a21ce9b54bde5bf7e539c7af974"},
768 | ]
769 |
770 | [package.dependencies]
771 | mypy-extensions = ">=1.0.0"
772 | tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
773 | typing-extensions = ">=4.1.0"
774 |
775 | [package.extras]
776 | dmypy = ["psutil (>=4.0)"]
777 | install-types = ["pip"]
778 | mypyc = ["setuptools (>=50)"]
779 | reports = ["lxml"]
780 |
781 | [[package]]
782 | name = "mypy-extensions"
783 | version = "1.0.0"
784 | description = "Type system extensions for programs checked with the mypy type checker."
785 | optional = false
786 | python-versions = ">=3.5"
787 | files = [
788 | {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"},
789 | {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"},
790 | ]
791 |
792 | [[package]]
793 | name = "numpy"
794 | version = "1.26.4"
795 | description = "Fundamental package for array computing in Python"
796 | optional = false
797 | python-versions = ">=3.9"
798 | files = [
799 | {file = "numpy-1.26.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9ff0f4f29c51e2803569d7a51c2304de5554655a60c5d776e35b4a41413830d0"},
800 | {file = "numpy-1.26.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2e4ee3380d6de9c9ec04745830fd9e2eccb3e6cf790d39d7b98ffd19b0dd754a"},
801 | {file = "numpy-1.26.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d209d8969599b27ad20994c8e41936ee0964e6da07478d6c35016bc386b66ad4"},
802 | {file = "numpy-1.26.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ffa75af20b44f8dba823498024771d5ac50620e6915abac414251bd971b4529f"},
803 | {file = "numpy-1.26.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:62b8e4b1e28009ef2846b4c7852046736bab361f7aeadeb6a5b89ebec3c7055a"},
804 | {file = "numpy-1.26.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a4abb4f9001ad2858e7ac189089c42178fcce737e4169dc61321660f1a96c7d2"},
805 | {file = "numpy-1.26.4-cp310-cp310-win32.whl", hash = "sha256:bfe25acf8b437eb2a8b2d49d443800a5f18508cd811fea3181723922a8a82b07"},
806 | {file = "numpy-1.26.4-cp310-cp310-win_amd64.whl", hash = "sha256:b97fe8060236edf3662adfc2c633f56a08ae30560c56310562cb4f95500022d5"},
807 | {file = "numpy-1.26.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4c66707fabe114439db9068ee468c26bbdf909cac0fb58686a42a24de1760c71"},
808 | {file = "numpy-1.26.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:edd8b5fe47dab091176d21bb6de568acdd906d1887a4584a15a9a96a1dca06ef"},
809 | {file = "numpy-1.26.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ab55401287bfec946ced39700c053796e7cc0e3acbef09993a9ad2adba6ca6e"},
810 | {file = "numpy-1.26.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:666dbfb6ec68962c033a450943ded891bed2d54e6755e35e5835d63f4f6931d5"},
811 | {file = "numpy-1.26.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:96ff0b2ad353d8f990b63294c8986f1ec3cb19d749234014f4e7eb0112ceba5a"},
812 | {file = "numpy-1.26.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:60dedbb91afcbfdc9bc0b1f3f402804070deed7392c23eb7a7f07fa857868e8a"},
813 | {file = "numpy-1.26.4-cp311-cp311-win32.whl", hash = "sha256:1af303d6b2210eb850fcf03064d364652b7120803a0b872f5211f5234b399f20"},
814 | {file = "numpy-1.26.4-cp311-cp311-win_amd64.whl", hash = "sha256:cd25bcecc4974d09257ffcd1f098ee778f7834c3ad767fe5db785be9a4aa9cb2"},
815 | {file = "numpy-1.26.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b3ce300f3644fb06443ee2222c2201dd3a89ea6040541412b8fa189341847218"},
816 | {file = "numpy-1.26.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:03a8c78d01d9781b28a6989f6fa1bb2c4f2d51201cf99d3dd875df6fbd96b23b"},
817 | {file = "numpy-1.26.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9fad7dcb1aac3c7f0584a5a8133e3a43eeb2fe127f47e3632d43d677c66c102b"},
818 | {file = "numpy-1.26.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:675d61ffbfa78604709862923189bad94014bef562cc35cf61d3a07bba02a7ed"},
819 | {file = "numpy-1.26.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ab47dbe5cc8210f55aa58e4805fe224dac469cde56b9f731a4c098b91917159a"},
820 | {file = "numpy-1.26.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:1dda2e7b4ec9dd512f84935c5f126c8bd8b9f2fc001e9f54af255e8c5f16b0e0"},
821 | {file = "numpy-1.26.4-cp312-cp312-win32.whl", hash = "sha256:50193e430acfc1346175fcbdaa28ffec49947a06918b7b92130744e81e640110"},
822 | {file = "numpy-1.26.4-cp312-cp312-win_amd64.whl", hash = "sha256:08beddf13648eb95f8d867350f6a018a4be2e5ad54c8d8caed89ebca558b2818"},
823 | {file = "numpy-1.26.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7349ab0fa0c429c82442a27a9673fc802ffdb7c7775fad780226cb234965e53c"},
824 | {file = "numpy-1.26.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:52b8b60467cd7dd1e9ed082188b4e6bb35aa5cdd01777621a1658910745b90be"},
825 | {file = "numpy-1.26.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d5241e0a80d808d70546c697135da2c613f30e28251ff8307eb72ba696945764"},
826 | {file = "numpy-1.26.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f870204a840a60da0b12273ef34f7051e98c3b5961b61b0c2c1be6dfd64fbcd3"},
827 | {file = "numpy-1.26.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:679b0076f67ecc0138fd2ede3a8fd196dddc2ad3254069bcb9faf9a79b1cebcd"},
828 | {file = "numpy-1.26.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:47711010ad8555514b434df65f7d7b076bb8261df1ca9bb78f53d3b2db02e95c"},
829 | {file = "numpy-1.26.4-cp39-cp39-win32.whl", hash = "sha256:a354325ee03388678242a4d7ebcd08b5c727033fcff3b2f536aea978e15ee9e6"},
830 | {file = "numpy-1.26.4-cp39-cp39-win_amd64.whl", hash = "sha256:3373d5d70a5fe74a2c1bb6d2cfd9609ecf686d47a2d7b1d37a8f3b6bf6003aea"},
831 | {file = "numpy-1.26.4-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:afedb719a9dcfc7eaf2287b839d8198e06dcd4cb5d276a3df279231138e83d30"},
832 | {file = "numpy-1.26.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95a7476c59002f2f6c590b9b7b998306fba6a5aa646b1e22ddfeaf8f78c3a29c"},
833 | {file = "numpy-1.26.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7e50d0a0cc3189f9cb0aeb3a6a6af18c16f59f004b866cd2be1c14b36134a4a0"},
834 | {file = "numpy-1.26.4.tar.gz", hash = "sha256:2a02aba9ed12e4ac4eb3ea9421c420301a0c6460d9830d74a9df87efa4912010"},
835 | ]
836 |
837 | [[package]]
838 | name = "onnxruntime"
839 | version = "1.19.2"
840 | description = "ONNX Runtime is a runtime accelerator for Machine Learning models"
841 | optional = false
842 | python-versions = "*"
843 | files = [
844 | {file = "onnxruntime-1.19.2-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:84fa57369c06cadd3c2a538ae2a26d76d583e7c34bdecd5769d71ca5c0fc750e"},
845 | {file = "onnxruntime-1.19.2-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bdc471a66df0c1cdef774accef69e9f2ca168c851ab5e4f2f3341512c7ef4666"},
846 | {file = "onnxruntime-1.19.2-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e3a4ce906105d99ebbe817f536d50a91ed8a4d1592553f49b3c23c4be2560ae6"},
847 | {file = "onnxruntime-1.19.2-cp310-cp310-win32.whl", hash = "sha256:4b3d723cc154c8ddeb9f6d0a8c0d6243774c6b5930847cc83170bfe4678fafb3"},
848 | {file = "onnxruntime-1.19.2-cp310-cp310-win_amd64.whl", hash = "sha256:17ed7382d2c58d4b7354fb2b301ff30b9bf308a1c7eac9546449cd122d21cae5"},
849 | {file = "onnxruntime-1.19.2-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:d863e8acdc7232d705d49e41087e10b274c42f09e259016a46f32c34e06dc4fd"},
850 | {file = "onnxruntime-1.19.2-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c1dfe4f660a71b31caa81fc298a25f9612815215a47b286236e61d540350d7b6"},
851 | {file = "onnxruntime-1.19.2-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a36511dc07c5c964b916697e42e366fa43c48cdb3d3503578d78cef30417cb84"},
852 | {file = "onnxruntime-1.19.2-cp311-cp311-win32.whl", hash = "sha256:50cbb8dc69d6befad4746a69760e5b00cc3ff0a59c6c3fb27f8afa20e2cab7e7"},
853 | {file = "onnxruntime-1.19.2-cp311-cp311-win_amd64.whl", hash = "sha256:1c3e5d415b78337fa0b1b75291e9ea9fb2a4c1f148eb5811e7212fed02cfffa8"},
854 | {file = "onnxruntime-1.19.2-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:68e7051bef9cfefcbb858d2d2646536829894d72a4130c24019219442b1dd2ed"},
855 | {file = "onnxruntime-1.19.2-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d2d366fbcc205ce68a8a3bde2185fd15c604d9645888703785b61ef174265168"},
856 | {file = "onnxruntime-1.19.2-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:477b93df4db467e9cbf34051662a4b27c18e131fa1836e05974eae0d6e4cf29b"},
857 | {file = "onnxruntime-1.19.2-cp312-cp312-win32.whl", hash = "sha256:9a174073dc5608fad05f7cf7f320b52e8035e73d80b0a23c80f840e5a97c0147"},
858 | {file = "onnxruntime-1.19.2-cp312-cp312-win_amd64.whl", hash = "sha256:190103273ea4507638ffc31d66a980594b237874b65379e273125150eb044857"},
859 | {file = "onnxruntime-1.19.2-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:636bc1d4cc051d40bc52e1f9da87fbb9c57d9d47164695dfb1c41646ea51ea66"},
860 | {file = "onnxruntime-1.19.2-cp38-cp38-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5bd8b875757ea941cbcfe01582970cc299893d1b65bd56731e326a8333f638a3"},
861 | {file = "onnxruntime-1.19.2-cp38-cp38-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b2046fc9560f97947bbc1acbe4c6d48585ef0f12742744307d3364b131ac5778"},
862 | {file = "onnxruntime-1.19.2-cp38-cp38-win32.whl", hash = "sha256:31c12840b1cde4ac1f7d27d540c44e13e34f2345cf3642762d2a3333621abb6a"},
863 | {file = "onnxruntime-1.19.2-cp38-cp38-win_amd64.whl", hash = "sha256:016229660adea180e9a32ce218b95f8f84860a200f0f13b50070d7d90e92956c"},
864 | {file = "onnxruntime-1.19.2-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:006c8d326835c017a9e9f74c9c77ebb570a71174a1e89fe078b29a557d9c3848"},
865 | {file = "onnxruntime-1.19.2-cp39-cp39-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:df2a94179a42d530b936f154615b54748239c2908ee44f0d722cb4df10670f68"},
866 | {file = "onnxruntime-1.19.2-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fae4b4de45894b9ce7ae418c5484cbf0341db6813effec01bb2216091c52f7fb"},
867 | {file = "onnxruntime-1.19.2-cp39-cp39-win32.whl", hash = "sha256:dc5430f473e8706fff837ae01323be9dcfddd3ea471c900a91fa7c9b807ec5d3"},
868 | {file = "onnxruntime-1.19.2-cp39-cp39-win_amd64.whl", hash = "sha256:38475e29a95c5f6c62c2c603d69fc7d4c6ccbf4df602bd567b86ae1138881c49"},
869 | ]
870 |
871 | [package.dependencies]
872 | coloredlogs = "*"
873 | flatbuffers = "*"
874 | numpy = ">=1.21.6"
875 | packaging = "*"
876 | protobuf = "*"
877 | sympy = "*"
878 |
879 | [[package]]
880 | name = "onnxruntime-gpu"
881 | version = "1.19.2"
882 | description = "ONNX Runtime is a runtime accelerator for Machine Learning models"
883 | optional = false
884 | python-versions = "*"
885 | files = [
886 | {file = "onnxruntime_gpu-1.19.2-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a49740e079e7c5215830d30cde3df792e903df007aa0b0fd7aa797937061b27a"},
887 | {file = "onnxruntime_gpu-1.19.2-cp310-cp310-win_amd64.whl", hash = "sha256:b895920bb5e4241299f68874e0becdc2635ea0142939c11e7ff5ae5b28993613"},
888 | {file = "onnxruntime_gpu-1.19.2-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:562fc7c755393eaad9751e56149339dd201ffbfdb3ef5f43ff21d0619ba9045f"},
889 | {file = "onnxruntime_gpu-1.19.2-cp311-cp311-win_amd64.whl", hash = "sha256:522f7495918176cb8c1a3c78bde7152d984f7096acc786c73a27643af8af87c9"},
890 | {file = "onnxruntime_gpu-1.19.2-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:554a02a3fac0119707eb87327908afd21c4e6f0fa5bf9a034398f098adc316c5"},
891 | {file = "onnxruntime_gpu-1.19.2-cp312-cp312-win_amd64.whl", hash = "sha256:e7c6165a405027e3c0f11d189ae7013b5d66919b3381f9bfb3405c0c0cf07968"},
892 | {file = "onnxruntime_gpu-1.19.2-cp38-cp38-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b4a8562e1e6f1912870c60bfaf8233c82b86e5b93ae39f211b650ac0f2015430"},
893 | {file = "onnxruntime_gpu-1.19.2-cp38-cp38-win_amd64.whl", hash = "sha256:55505c99e18688a7c68fdc811ed6e7a315aa36f543b33920c77d03a627d2c3f5"},
894 | {file = "onnxruntime_gpu-1.19.2-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c9e369f01f55ea726ae5d28f18236426e52e97c433f0b7682054e61c478a06c9"},
895 | {file = "onnxruntime_gpu-1.19.2-cp39-cp39-win_amd64.whl", hash = "sha256:c8b8128174b0470537e9f4983aeecc002a435d13914970c2af2f41d244ef2781"},
896 | ]
897 |
898 | [package.dependencies]
899 | coloredlogs = "*"
900 | flatbuffers = "*"
901 | numpy = ">=1.21.6"
902 | packaging = "*"
903 | protobuf = "*"
904 | sympy = "*"
905 |
906 | [[package]]
907 | name = "open-image-models"
908 | version = "0.2.0"
909 | description = "Pre-trained image models using ONNX for fast, out-of-the-box inference."
910 | optional = false
911 | python-versions = "<4.0,>=3.10"
912 | files = [
913 | {file = "open_image_models-0.2.0-py3-none-any.whl", hash = "sha256:a4b5c89409dbe373cc2d0f6db7312ec7c9e61caa0c9fbed400d7b8179c8b6eab"},
914 | {file = "open_image_models-0.2.0.tar.gz", hash = "sha256:b77ec208fb45e5b74ac3de7b7b4258fa985009168e5222b0cc5dd1aa79bd0c2e"},
915 | ]
916 |
917 | [package.dependencies]
918 | numpy = ">=1.20"
919 | onnxruntime = {version = ">=1.19.2", markers = "sys_platform == \"darwin\" or platform_machine == \"armv7l\" or platform_machine == \"aarch64\""}
920 | onnxruntime-gpu = {version = ">=1.19.2", markers = "sys_platform != \"darwin\" and (platform_machine != \"armv7l\" and platform_machine != \"aarch64\") and (platform_system == \"Linux\" or platform_system == \"Windows\")"}
921 | opencv-python = "*"
922 | rich = "*"
923 | tqdm = "*"
924 |
925 | [package.extras]
926 | docs = ["mike", "mkdocs-material", "mkdocstrings[python]"]
927 |
928 | [[package]]
929 | name = "opencv-python"
930 | version = "4.9.0.80"
931 | description = "Wrapper package for OpenCV python bindings."
932 | optional = false
933 | python-versions = ">=3.6"
934 | files = [
935 | {file = "opencv-python-4.9.0.80.tar.gz", hash = "sha256:1a9f0e6267de3a1a1db0c54213d022c7c8b5b9ca4b580e80bdc58516c922c9e1"},
936 | {file = "opencv_python-4.9.0.80-cp37-abi3-macosx_10_16_x86_64.whl", hash = "sha256:7e5f7aa4486651a6ebfa8ed4b594b65bd2d2f41beeb4241a3e4b1b85acbbbadb"},
937 | {file = "opencv_python-4.9.0.80-cp37-abi3-macosx_11_0_arm64.whl", hash = "sha256:71dfb9555ccccdd77305fc3dcca5897fbf0cf28b297c51ee55e079c065d812a3"},
938 | {file = "opencv_python-4.9.0.80-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b34a52e9da36dda8c151c6394aed602e4b17fa041df0b9f5b93ae10b0fcca2a"},
939 | {file = "opencv_python-4.9.0.80-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4088cab82b66a3b37ffc452976b14a3c599269c247895ae9ceb4066d8188a57"},
940 | {file = "opencv_python-4.9.0.80-cp37-abi3-win32.whl", hash = "sha256:dcf000c36dd1651118a2462257e3a9e76db789a78432e1f303c7bac54f63ef6c"},
941 | {file = "opencv_python-4.9.0.80-cp37-abi3-win_amd64.whl", hash = "sha256:3f16f08e02b2a2da44259c7cc712e779eff1dd8b55fdb0323e8cab09548086c0"},
942 | ]
943 |
944 | [package.dependencies]
945 | numpy = [
946 | {version = ">=1.21.4", markers = "python_version >= \"3.10\" and platform_system == \"Darwin\" and python_version < \"3.11\""},
947 | {version = ">=1.21.2", markers = "platform_system != \"Darwin\" and python_version >= \"3.10\" and python_version < \"3.11\""},
948 | {version = ">=1.26.0", markers = "python_version >= \"3.12\""},
949 | {version = ">=1.23.5", markers = "python_version >= \"3.11\" and python_version < \"3.12\""},
950 | ]
951 |
952 | [[package]]
953 | name = "packaging"
954 | version = "24.0"
955 | description = "Core utilities for Python packages"
956 | optional = false
957 | python-versions = ">=3.7"
958 | files = [
959 | {file = "packaging-24.0-py3-none-any.whl", hash = "sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5"},
960 | {file = "packaging-24.0.tar.gz", hash = "sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9"},
961 | ]
962 |
963 | [[package]]
964 | name = "paginate"
965 | version = "0.5.7"
966 | description = "Divides large result sets into pages for easier browsing"
967 | optional = true
968 | python-versions = "*"
969 | files = [
970 | {file = "paginate-0.5.7-py2.py3-none-any.whl", hash = "sha256:b885e2af73abcf01d9559fd5216b57ef722f8c42affbb63942377668e35c7591"},
971 | {file = "paginate-0.5.7.tar.gz", hash = "sha256:22bd083ab41e1a8b4f3690544afb2c60c25e5c9a63a30fa2f483f6c60c8e5945"},
972 | ]
973 |
974 | [package.extras]
975 | dev = ["pytest", "tox"]
976 | lint = ["black"]
977 |
978 | [[package]]
979 | name = "pathspec"
980 | version = "0.12.1"
981 | description = "Utility library for gitignore style pattern matching of file paths."
982 | optional = true
983 | python-versions = ">=3.8"
984 | files = [
985 | {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"},
986 | {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"},
987 | ]
988 |
989 | [[package]]
990 | name = "platformdirs"
991 | version = "4.2.0"
992 | description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
993 | optional = false
994 | python-versions = ">=3.8"
995 | files = [
996 | {file = "platformdirs-4.2.0-py3-none-any.whl", hash = "sha256:0614df2a2f37e1a662acbd8e2b25b92ccf8632929bc6d43467e17fe89c75e068"},
997 | {file = "platformdirs-4.2.0.tar.gz", hash = "sha256:ef0cc731df711022c174543cb70a9b5bd22e5a9337c8624ef2c2ceb8ddad8768"},
998 | ]
999 |
1000 | [package.extras]
1001 | docs = ["furo (>=2023.9.10)", "proselint (>=0.13)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"]
1002 | test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)"]
1003 |
1004 | [[package]]
1005 | name = "pluggy"
1006 | version = "1.4.0"
1007 | description = "plugin and hook calling mechanisms for python"
1008 | optional = false
1009 | python-versions = ">=3.8"
1010 | files = [
1011 | {file = "pluggy-1.4.0-py3-none-any.whl", hash = "sha256:7db9f7b503d67d1c5b95f59773ebb58a8c1c288129a88665838012cfb07b8981"},
1012 | {file = "pluggy-1.4.0.tar.gz", hash = "sha256:8c85c2876142a764e5b7548e7d9a0e0ddb46f5185161049a79b7e974454223be"},
1013 | ]
1014 |
1015 | [package.extras]
1016 | dev = ["pre-commit", "tox"]
1017 | testing = ["pytest", "pytest-benchmark"]
1018 |
1019 | [[package]]
1020 | name = "protobuf"
1021 | version = "3.20.3"
1022 | description = "Protocol Buffers"
1023 | optional = false
1024 | python-versions = ">=3.7"
1025 | files = [
1026 | {file = "protobuf-3.20.3-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:f4bd856d702e5b0d96a00ec6b307b0f51c1982c2bf9c0052cf9019e9a544ba99"},
1027 | {file = "protobuf-3.20.3-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:9aae4406ea63d825636cc11ffb34ad3379335803216ee3a856787bcf5ccc751e"},
1028 | {file = "protobuf-3.20.3-cp310-cp310-win32.whl", hash = "sha256:28545383d61f55b57cf4df63eebd9827754fd2dc25f80c5253f9184235db242c"},
1029 | {file = "protobuf-3.20.3-cp310-cp310-win_amd64.whl", hash = "sha256:67a3598f0a2dcbc58d02dd1928544e7d88f764b47d4a286202913f0b2801c2e7"},
1030 | {file = "protobuf-3.20.3-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:899dc660cd599d7352d6f10d83c95df430a38b410c1b66b407a6b29265d66469"},
1031 | {file = "protobuf-3.20.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:e64857f395505ebf3d2569935506ae0dfc4a15cb80dc25261176c784662cdcc4"},
1032 | {file = "protobuf-3.20.3-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:d9e4432ff660d67d775c66ac42a67cf2453c27cb4d738fc22cb53b5d84c135d4"},
1033 | {file = "protobuf-3.20.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:74480f79a023f90dc6e18febbf7b8bac7508420f2006fabd512013c0c238f454"},
1034 | {file = "protobuf-3.20.3-cp37-cp37m-win32.whl", hash = "sha256:b6cc7ba72a8850621bfec987cb72623e703b7fe2b9127a161ce61e61558ad905"},
1035 | {file = "protobuf-3.20.3-cp37-cp37m-win_amd64.whl", hash = "sha256:8c0c984a1b8fef4086329ff8dd19ac77576b384079247c770f29cc8ce3afa06c"},
1036 | {file = "protobuf-3.20.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:de78575669dddf6099a8a0f46a27e82a1783c557ccc38ee620ed8cc96d3be7d7"},
1037 | {file = "protobuf-3.20.3-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:f4c42102bc82a51108e449cbb32b19b180022941c727bac0cfd50170341f16ee"},
1038 | {file = "protobuf-3.20.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:44246bab5dd4b7fbd3c0c80b6f16686808fab0e4aca819ade6e8d294a29c7050"},
1039 | {file = "protobuf-3.20.3-cp38-cp38-win32.whl", hash = "sha256:c02ce36ec760252242a33967d51c289fd0e1c0e6e5cc9397e2279177716add86"},
1040 | {file = "protobuf-3.20.3-cp38-cp38-win_amd64.whl", hash = "sha256:447d43819997825d4e71bf5769d869b968ce96848b6479397e29fc24c4a5dfe9"},
1041 | {file = "protobuf-3.20.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:398a9e0c3eaceb34ec1aee71894ca3299605fa8e761544934378bbc6c97de23b"},
1042 | {file = "protobuf-3.20.3-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:bf01b5720be110540be4286e791db73f84a2b721072a3711efff6c324cdf074b"},
1043 | {file = "protobuf-3.20.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:daa564862dd0d39c00f8086f88700fdbe8bc717e993a21e90711acfed02f2402"},
1044 | {file = "protobuf-3.20.3-cp39-cp39-win32.whl", hash = "sha256:819559cafa1a373b7096a482b504ae8a857c89593cf3a25af743ac9ecbd23480"},
1045 | {file = "protobuf-3.20.3-cp39-cp39-win_amd64.whl", hash = "sha256:03038ac1cfbc41aa21f6afcbcd357281d7521b4157926f30ebecc8d4ea59dcb7"},
1046 | {file = "protobuf-3.20.3-py2.py3-none-any.whl", hash = "sha256:a7ca6d488aa8ff7f329d4c545b2dbad8ac31464f1d8b1c87ad1346717731e4db"},
1047 | {file = "protobuf-3.20.3.tar.gz", hash = "sha256:2e3427429c9cffebf259491be0af70189607f365c2f41c7c3764af6f337105f2"},
1048 | ]
1049 |
1050 | [[package]]
1051 | name = "pygments"
1052 | version = "2.17.2"
1053 | description = "Pygments is a syntax highlighting package written in Python."
1054 | optional = false
1055 | python-versions = ">=3.7"
1056 | files = [
1057 | {file = "pygments-2.17.2-py3-none-any.whl", hash = "sha256:b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c"},
1058 | {file = "pygments-2.17.2.tar.gz", hash = "sha256:da46cec9fd2de5be3a8a784f434e4c4ab670b4ff54d605c4c2717e9d49c4c367"},
1059 | ]
1060 |
1061 | [package.extras]
1062 | plugins = ["importlib-metadata"]
1063 | windows-terminal = ["colorama (>=0.4.6)"]
1064 |
1065 | [[package]]
1066 | name = "pylint"
1067 | version = "3.1.0"
1068 | description = "python code static checker"
1069 | optional = false
1070 | python-versions = ">=3.8.0"
1071 | files = [
1072 | {file = "pylint-3.1.0-py3-none-any.whl", hash = "sha256:507a5b60953874766d8a366e8e8c7af63e058b26345cfcb5f91f89d987fd6b74"},
1073 | {file = "pylint-3.1.0.tar.gz", hash = "sha256:6a69beb4a6f63debebaab0a3477ecd0f559aa726af4954fc948c51f7a2549e23"},
1074 | ]
1075 |
1076 | [package.dependencies]
1077 | astroid = ">=3.1.0,<=3.2.0-dev0"
1078 | colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""}
1079 | dill = [
1080 | {version = ">=0.2", markers = "python_version < \"3.11\""},
1081 | {version = ">=0.3.7", markers = "python_version >= \"3.12\""},
1082 | {version = ">=0.3.6", markers = "python_version >= \"3.11\" and python_version < \"3.12\""},
1083 | ]
1084 | isort = ">=4.2.5,<5.13.0 || >5.13.0,<6"
1085 | mccabe = ">=0.6,<0.8"
1086 | platformdirs = ">=2.2.0"
1087 | tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
1088 | tomlkit = ">=0.10.1"
1089 |
1090 | [package.extras]
1091 | spelling = ["pyenchant (>=3.2,<4.0)"]
1092 | testutils = ["gitpython (>3)"]
1093 |
1094 | [[package]]
1095 | name = "pymdown-extensions"
1096 | version = "10.12"
1097 | description = "Extension pack for Python Markdown."
1098 | optional = true
1099 | python-versions = ">=3.8"
1100 | files = [
1101 | {file = "pymdown_extensions-10.12-py3-none-any.whl", hash = "sha256:49f81412242d3527b8b4967b990df395c89563043bc51a3d2d7d500e52123b77"},
1102 | {file = "pymdown_extensions-10.12.tar.gz", hash = "sha256:b0ee1e0b2bef1071a47891ab17003bfe5bf824a398e13f49f8ed653b699369a7"},
1103 | ]
1104 |
1105 | [package.dependencies]
1106 | markdown = ">=3.6"
1107 | pyyaml = "*"
1108 |
1109 | [package.extras]
1110 | extra = ["pygments (>=2.12)"]
1111 |
1112 | [[package]]
1113 | name = "pyparsing"
1114 | version = "3.2.0"
1115 | description = "pyparsing module - Classes and methods to define and execute parsing grammars"
1116 | optional = true
1117 | python-versions = ">=3.9"
1118 | files = [
1119 | {file = "pyparsing-3.2.0-py3-none-any.whl", hash = "sha256:93d9577b88da0bbea8cc8334ee8b918ed014968fd2ec383e868fb8afb1ccef84"},
1120 | {file = "pyparsing-3.2.0.tar.gz", hash = "sha256:cbf74e27246d595d9a74b186b810f6fbb86726dbf3b9532efb343f6d7294fe9c"},
1121 | ]
1122 |
1123 | [package.extras]
1124 | diagrams = ["jinja2", "railroad-diagrams"]
1125 |
1126 | [[package]]
1127 | name = "pyreadline3"
1128 | version = "3.4.1"
1129 | description = "A python implementation of GNU readline."
1130 | optional = false
1131 | python-versions = "*"
1132 | files = [
1133 | {file = "pyreadline3-3.4.1-py3-none-any.whl", hash = "sha256:b0efb6516fd4fb07b45949053826a62fa4cb353db5be2bbb4a7aa1fdd1e345fb"},
1134 | {file = "pyreadline3-3.4.1.tar.gz", hash = "sha256:6f3d1f7b8a31ba32b73917cefc1f28cc660562f39aea8646d30bd6eff21f7bae"},
1135 | ]
1136 |
1137 | [[package]]
1138 | name = "pytest"
1139 | version = "8.1.1"
1140 | description = "pytest: simple powerful testing with Python"
1141 | optional = false
1142 | python-versions = ">=3.8"
1143 | files = [
1144 | {file = "pytest-8.1.1-py3-none-any.whl", hash = "sha256:2a8386cfc11fa9d2c50ee7b2a57e7d898ef90470a7a34c4b949ff59662bb78b7"},
1145 | {file = "pytest-8.1.1.tar.gz", hash = "sha256:ac978141a75948948817d360297b7aae0fcb9d6ff6bc9ec6d514b85d5a65c044"},
1146 | ]
1147 |
1148 | [package.dependencies]
1149 | colorama = {version = "*", markers = "sys_platform == \"win32\""}
1150 | exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""}
1151 | iniconfig = "*"
1152 | packaging = "*"
1153 | pluggy = ">=1.4,<2.0"
1154 | tomli = {version = ">=1", markers = "python_version < \"3.11\""}
1155 |
1156 | [package.extras]
1157 | testing = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"]
1158 |
1159 | [[package]]
1160 | name = "python-dateutil"
1161 | version = "2.9.0.post0"
1162 | description = "Extensions to the standard Python datetime module"
1163 | optional = true
1164 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
1165 | files = [
1166 | {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"},
1167 | {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"},
1168 | ]
1169 |
1170 | [package.dependencies]
1171 | six = ">=1.5"
1172 |
1173 | [[package]]
1174 | name = "pyyaml"
1175 | version = "6.0.1"
1176 | description = "YAML parser and emitter for Python"
1177 | optional = false
1178 | python-versions = ">=3.6"
1179 | files = [
1180 | {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"},
1181 | {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"},
1182 | {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"},
1183 | {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"},
1184 | {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"},
1185 | {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"},
1186 | {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"},
1187 | {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"},
1188 | {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"},
1189 | {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"},
1190 | {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"},
1191 | {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"},
1192 | {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"},
1193 | {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"},
1194 | {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"},
1195 | {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"},
1196 | {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"},
1197 | {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"},
1198 | {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"},
1199 | {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"},
1200 | {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"},
1201 | {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"},
1202 | {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"},
1203 | {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"},
1204 | {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"},
1205 | {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"},
1206 | {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"},
1207 | {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"},
1208 | {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"},
1209 | {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"},
1210 | {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"},
1211 | {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"},
1212 | {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"},
1213 | {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"},
1214 | {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"},
1215 | {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"},
1216 | {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"},
1217 | {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"},
1218 | {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"},
1219 | {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"},
1220 | {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"},
1221 | {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"},
1222 | {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"},
1223 | {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"},
1224 | {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"},
1225 | {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"},
1226 | {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"},
1227 | {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"},
1228 | {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"},
1229 | {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"},
1230 | {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"},
1231 | ]
1232 |
1233 | [[package]]
1234 | name = "pyyaml-env-tag"
1235 | version = "0.1"
1236 | description = "A custom YAML tag for referencing environment variables in YAML files. "
1237 | optional = true
1238 | python-versions = ">=3.6"
1239 | files = [
1240 | {file = "pyyaml_env_tag-0.1-py3-none-any.whl", hash = "sha256:af31106dec8a4d68c60207c1886031cbf839b68aa7abccdb19868200532c2069"},
1241 | {file = "pyyaml_env_tag-0.1.tar.gz", hash = "sha256:70092675bda14fdec33b31ba77e7543de9ddc88f2e5b99160396572d11525bdb"},
1242 | ]
1243 |
1244 | [package.dependencies]
1245 | pyyaml = "*"
1246 |
1247 | [[package]]
1248 | name = "regex"
1249 | version = "2024.9.11"
1250 | description = "Alternative regular expression module, to replace re."
1251 | optional = true
1252 | python-versions = ">=3.8"
1253 | files = [
1254 | {file = "regex-2024.9.11-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:1494fa8725c285a81d01dc8c06b55287a1ee5e0e382d8413adc0a9197aac6408"},
1255 | {file = "regex-2024.9.11-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0e12c481ad92d129c78f13a2a3662317e46ee7ef96c94fd332e1c29131875b7d"},
1256 | {file = "regex-2024.9.11-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:16e13a7929791ac1216afde26f712802e3df7bf0360b32e4914dca3ab8baeea5"},
1257 | {file = "regex-2024.9.11-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:46989629904bad940bbec2106528140a218b4a36bb3042d8406980be1941429c"},
1258 | {file = "regex-2024.9.11-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a906ed5e47a0ce5f04b2c981af1c9acf9e8696066900bf03b9d7879a6f679fc8"},
1259 | {file = "regex-2024.9.11-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e9a091b0550b3b0207784a7d6d0f1a00d1d1c8a11699c1a4d93db3fbefc3ad35"},
1260 | {file = "regex-2024.9.11-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ddcd9a179c0a6fa8add279a4444015acddcd7f232a49071ae57fa6e278f1f71"},
1261 | {file = "regex-2024.9.11-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6b41e1adc61fa347662b09398e31ad446afadff932a24807d3ceb955ed865cc8"},
1262 | {file = "regex-2024.9.11-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ced479f601cd2f8ca1fd7b23925a7e0ad512a56d6e9476f79b8f381d9d37090a"},
1263 | {file = "regex-2024.9.11-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:635a1d96665f84b292e401c3d62775851aedc31d4f8784117b3c68c4fcd4118d"},
1264 | {file = "regex-2024.9.11-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:c0256beda696edcf7d97ef16b2a33a8e5a875affd6fa6567b54f7c577b30a137"},
1265 | {file = "regex-2024.9.11-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:3ce4f1185db3fbde8ed8aa223fc9620f276c58de8b0d4f8cc86fd1360829edb6"},
1266 | {file = "regex-2024.9.11-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:09d77559e80dcc9d24570da3745ab859a9cf91953062e4ab126ba9d5993688ca"},
1267 | {file = "regex-2024.9.11-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7a22ccefd4db3f12b526eccb129390942fe874a3a9fdbdd24cf55773a1faab1a"},
1268 | {file = "regex-2024.9.11-cp310-cp310-win32.whl", hash = "sha256:f745ec09bc1b0bd15cfc73df6fa4f726dcc26bb16c23a03f9e3367d357eeedd0"},
1269 | {file = "regex-2024.9.11-cp310-cp310-win_amd64.whl", hash = "sha256:01c2acb51f8a7d6494c8c5eafe3d8e06d76563d8a8a4643b37e9b2dd8a2ff623"},
1270 | {file = "regex-2024.9.11-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2cce2449e5927a0bf084d346da6cd5eb016b2beca10d0013ab50e3c226ffc0df"},
1271 | {file = "regex-2024.9.11-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3b37fa423beefa44919e009745ccbf353d8c981516e807995b2bd11c2c77d268"},
1272 | {file = "regex-2024.9.11-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:64ce2799bd75039b480cc0360907c4fb2f50022f030bf9e7a8705b636e408fad"},
1273 | {file = "regex-2024.9.11-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a4cc92bb6db56ab0c1cbd17294e14f5e9224f0cc6521167ef388332604e92679"},
1274 | {file = "regex-2024.9.11-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d05ac6fa06959c4172eccd99a222e1fbf17b5670c4d596cb1e5cde99600674c4"},
1275 | {file = "regex-2024.9.11-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:040562757795eeea356394a7fb13076ad4f99d3c62ab0f8bdfb21f99a1f85664"},
1276 | {file = "regex-2024.9.11-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6113c008a7780792efc80f9dfe10ba0cd043cbf8dc9a76ef757850f51b4edc50"},
1277 | {file = "regex-2024.9.11-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8e5fb5f77c8745a60105403a774fe2c1759b71d3e7b4ca237a5e67ad066c7199"},
1278 | {file = "regex-2024.9.11-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:54d9ff35d4515debf14bc27f1e3b38bfc453eff3220f5bce159642fa762fe5d4"},
1279 | {file = "regex-2024.9.11-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:df5cbb1fbc74a8305b6065d4ade43b993be03dbe0f8b30032cced0d7740994bd"},
1280 | {file = "regex-2024.9.11-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:7fb89ee5d106e4a7a51bce305ac4efb981536301895f7bdcf93ec92ae0d91c7f"},
1281 | {file = "regex-2024.9.11-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:a738b937d512b30bf75995c0159c0ddf9eec0775c9d72ac0202076c72f24aa96"},
1282 | {file = "regex-2024.9.11-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e28f9faeb14b6f23ac55bfbbfd3643f5c7c18ede093977f1df249f73fd22c7b1"},
1283 | {file = "regex-2024.9.11-cp311-cp311-win32.whl", hash = "sha256:18e707ce6c92d7282dfce370cd205098384b8ee21544e7cb29b8aab955b66fa9"},
1284 | {file = "regex-2024.9.11-cp311-cp311-win_amd64.whl", hash = "sha256:313ea15e5ff2a8cbbad96ccef6be638393041b0a7863183c2d31e0c6116688cf"},
1285 | {file = "regex-2024.9.11-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:b0d0a6c64fcc4ef9c69bd5b3b3626cc3776520a1637d8abaa62b9edc147a58f7"},
1286 | {file = "regex-2024.9.11-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:49b0e06786ea663f933f3710a51e9385ce0cba0ea56b67107fd841a55d56a231"},
1287 | {file = "regex-2024.9.11-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5b513b6997a0b2f10e4fd3a1313568e373926e8c252bd76c960f96fd039cd28d"},
1288 | {file = "regex-2024.9.11-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee439691d8c23e76f9802c42a95cfeebf9d47cf4ffd06f18489122dbb0a7ad64"},
1289 | {file = "regex-2024.9.11-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a8f877c89719d759e52783f7fe6e1c67121076b87b40542966c02de5503ace42"},
1290 | {file = "regex-2024.9.11-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:23b30c62d0f16827f2ae9f2bb87619bc4fba2044911e2e6c2eb1af0161cdb766"},
1291 | {file = "regex-2024.9.11-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85ab7824093d8f10d44330fe1e6493f756f252d145323dd17ab6b48733ff6c0a"},
1292 | {file = "regex-2024.9.11-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8dee5b4810a89447151999428fe096977346cf2f29f4d5e29609d2e19e0199c9"},
1293 | {file = "regex-2024.9.11-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:98eeee2f2e63edae2181c886d7911ce502e1292794f4c5ee71e60e23e8d26b5d"},
1294 | {file = "regex-2024.9.11-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:57fdd2e0b2694ce6fc2e5ccf189789c3e2962916fb38779d3e3521ff8fe7a822"},
1295 | {file = "regex-2024.9.11-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:d552c78411f60b1fdaafd117a1fca2f02e562e309223b9d44b7de8be451ec5e0"},
1296 | {file = "regex-2024.9.11-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:a0b2b80321c2ed3fcf0385ec9e51a12253c50f146fddb2abbb10f033fe3d049a"},
1297 | {file = "regex-2024.9.11-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:18406efb2f5a0e57e3a5881cd9354c1512d3bb4f5c45d96d110a66114d84d23a"},
1298 | {file = "regex-2024.9.11-cp312-cp312-win32.whl", hash = "sha256:e464b467f1588e2c42d26814231edecbcfe77f5ac414d92cbf4e7b55b2c2a776"},
1299 | {file = "regex-2024.9.11-cp312-cp312-win_amd64.whl", hash = "sha256:9e8719792ca63c6b8340380352c24dcb8cd7ec49dae36e963742a275dfae6009"},
1300 | {file = "regex-2024.9.11-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:c157bb447303070f256e084668b702073db99bbb61d44f85d811025fcf38f784"},
1301 | {file = "regex-2024.9.11-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4db21ece84dfeefc5d8a3863f101995de646c6cb0536952c321a2650aa202c36"},
1302 | {file = "regex-2024.9.11-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:220e92a30b426daf23bb67a7962900ed4613589bab80382be09b48896d211e92"},
1303 | {file = "regex-2024.9.11-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eb1ae19e64c14c7ec1995f40bd932448713d3c73509e82d8cd7744dc00e29e86"},
1304 | {file = "regex-2024.9.11-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f47cd43a5bfa48f86925fe26fbdd0a488ff15b62468abb5d2a1e092a4fb10e85"},
1305 | {file = "regex-2024.9.11-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9d4a76b96f398697fe01117093613166e6aa8195d63f1b4ec3f21ab637632963"},
1306 | {file = "regex-2024.9.11-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ea51dcc0835eea2ea31d66456210a4e01a076d820e9039b04ae8d17ac11dee6"},
1307 | {file = "regex-2024.9.11-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b7aaa315101c6567a9a45d2839322c51c8d6e81f67683d529512f5bcfb99c802"},
1308 | {file = "regex-2024.9.11-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c57d08ad67aba97af57a7263c2d9006d5c404d721c5f7542f077f109ec2a4a29"},
1309 | {file = "regex-2024.9.11-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:f8404bf61298bb6f8224bb9176c1424548ee1181130818fcd2cbffddc768bed8"},
1310 | {file = "regex-2024.9.11-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:dd4490a33eb909ef5078ab20f5f000087afa2a4daa27b4c072ccb3cb3050ad84"},
1311 | {file = "regex-2024.9.11-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:eee9130eaad130649fd73e5cd92f60e55708952260ede70da64de420cdcad554"},
1312 | {file = "regex-2024.9.11-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6a2644a93da36c784e546de579ec1806bfd2763ef47babc1b03d765fe560c9f8"},
1313 | {file = "regex-2024.9.11-cp313-cp313-win32.whl", hash = "sha256:e997fd30430c57138adc06bba4c7c2968fb13d101e57dd5bb9355bf8ce3fa7e8"},
1314 | {file = "regex-2024.9.11-cp313-cp313-win_amd64.whl", hash = "sha256:042c55879cfeb21a8adacc84ea347721d3d83a159da6acdf1116859e2427c43f"},
1315 | {file = "regex-2024.9.11-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:35f4a6f96aa6cb3f2f7247027b07b15a374f0d5b912c0001418d1d55024d5cb4"},
1316 | {file = "regex-2024.9.11-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:55b96e7ce3a69a8449a66984c268062fbaa0d8ae437b285428e12797baefce7e"},
1317 | {file = "regex-2024.9.11-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:cb130fccd1a37ed894824b8c046321540263013da72745d755f2d35114b81a60"},
1318 | {file = "regex-2024.9.11-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:323c1f04be6b2968944d730e5c2091c8c89767903ecaa135203eec4565ed2b2b"},
1319 | {file = "regex-2024.9.11-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:be1c8ed48c4c4065ecb19d882a0ce1afe0745dfad8ce48c49586b90a55f02366"},
1320 | {file = "regex-2024.9.11-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b5b029322e6e7b94fff16cd120ab35a253236a5f99a79fb04fda7ae71ca20ae8"},
1321 | {file = "regex-2024.9.11-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6fff13ef6b5f29221d6904aa816c34701462956aa72a77f1f151a8ec4f56aeb"},
1322 | {file = "regex-2024.9.11-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:587d4af3979376652010e400accc30404e6c16b7df574048ab1f581af82065e4"},
1323 | {file = "regex-2024.9.11-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:079400a8269544b955ffa9e31f186f01d96829110a3bf79dc338e9910f794fca"},
1324 | {file = "regex-2024.9.11-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:f9268774428ec173654985ce55fc6caf4c6d11ade0f6f914d48ef4719eb05ebb"},
1325 | {file = "regex-2024.9.11-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:23f9985c8784e544d53fc2930fc1ac1a7319f5d5332d228437acc9f418f2f168"},
1326 | {file = "regex-2024.9.11-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:ae2941333154baff9838e88aa71c1d84f4438189ecc6021a12c7573728b5838e"},
1327 | {file = "regex-2024.9.11-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:e93f1c331ca8e86fe877a48ad64e77882c0c4da0097f2212873a69bbfea95d0c"},
1328 | {file = "regex-2024.9.11-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:846bc79ee753acf93aef4184c040d709940c9d001029ceb7b7a52747b80ed2dd"},
1329 | {file = "regex-2024.9.11-cp38-cp38-win32.whl", hash = "sha256:c94bb0a9f1db10a1d16c00880bdebd5f9faf267273b8f5bd1878126e0fbde771"},
1330 | {file = "regex-2024.9.11-cp38-cp38-win_amd64.whl", hash = "sha256:2b08fce89fbd45664d3df6ad93e554b6c16933ffa9d55cb7e01182baaf971508"},
1331 | {file = "regex-2024.9.11-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:07f45f287469039ffc2c53caf6803cd506eb5f5f637f1d4acb37a738f71dd066"},
1332 | {file = "regex-2024.9.11-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4838e24ee015101d9f901988001038f7f0d90dc0c3b115541a1365fb439add62"},
1333 | {file = "regex-2024.9.11-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6edd623bae6a737f10ce853ea076f56f507fd7726bee96a41ee3d68d347e4d16"},
1334 | {file = "regex-2024.9.11-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c69ada171c2d0e97a4b5aa78fbb835e0ffbb6b13fc5da968c09811346564f0d3"},
1335 | {file = "regex-2024.9.11-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:02087ea0a03b4af1ed6ebab2c54d7118127fee8d71b26398e8e4b05b78963199"},
1336 | {file = "regex-2024.9.11-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:69dee6a020693d12a3cf892aba4808fe168d2a4cef368eb9bf74f5398bfd4ee8"},
1337 | {file = "regex-2024.9.11-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:297f54910247508e6e5cae669f2bc308985c60540a4edd1c77203ef19bfa63ca"},
1338 | {file = "regex-2024.9.11-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ecea58b43a67b1b79805f1a0255730edaf5191ecef84dbc4cc85eb30bc8b63b9"},
1339 | {file = "regex-2024.9.11-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:eab4bb380f15e189d1313195b062a6aa908f5bd687a0ceccd47c8211e9cf0d4a"},
1340 | {file = "regex-2024.9.11-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:0cbff728659ce4bbf4c30b2a1be040faafaa9eca6ecde40aaff86f7889f4ab39"},
1341 | {file = "regex-2024.9.11-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:54c4a097b8bc5bb0dfc83ae498061d53ad7b5762e00f4adaa23bee22b012e6ba"},
1342 | {file = "regex-2024.9.11-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:73d6d2f64f4d894c96626a75578b0bf7d9e56dcda8c3d037a2118fdfe9b1c664"},
1343 | {file = "regex-2024.9.11-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:e53b5fbab5d675aec9f0c501274c467c0f9a5d23696cfc94247e1fb56501ed89"},
1344 | {file = "regex-2024.9.11-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:0ffbcf9221e04502fc35e54d1ce9567541979c3fdfb93d2c554f0ca583a19b35"},
1345 | {file = "regex-2024.9.11-cp39-cp39-win32.whl", hash = "sha256:e4c22e1ac1f1ec1e09f72e6c44d8f2244173db7eb9629cc3a346a8d7ccc31142"},
1346 | {file = "regex-2024.9.11-cp39-cp39-win_amd64.whl", hash = "sha256:faa3c142464efec496967359ca99696c896c591c56c53506bac1ad465f66e919"},
1347 | {file = "regex-2024.9.11.tar.gz", hash = "sha256:6c188c307e8433bcb63dc1915022deb553b4203a70722fc542c363bf120a01fd"},
1348 | ]
1349 |
1350 | [[package]]
1351 | name = "requests"
1352 | version = "2.32.3"
1353 | description = "Python HTTP for Humans."
1354 | optional = true
1355 | python-versions = ">=3.8"
1356 | files = [
1357 | {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"},
1358 | {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"},
1359 | ]
1360 |
1361 | [package.dependencies]
1362 | certifi = ">=2017.4.17"
1363 | charset-normalizer = ">=2,<4"
1364 | idna = ">=2.5,<4"
1365 | urllib3 = ">=1.21.1,<3"
1366 |
1367 | [package.extras]
1368 | socks = ["PySocks (>=1.5.6,!=1.5.7)"]
1369 | use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
1370 |
1371 | [[package]]
1372 | name = "rich"
1373 | version = "13.7.1"
1374 | description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal"
1375 | optional = false
1376 | python-versions = ">=3.7.0"
1377 | files = [
1378 | {file = "rich-13.7.1-py3-none-any.whl", hash = "sha256:4edbae314f59eb482f54e9e30bf00d33350aaa94f4bfcd4e9e3110e64d0d7222"},
1379 | {file = "rich-13.7.1.tar.gz", hash = "sha256:9be308cb1fe2f1f57d67ce99e95af38a1e2bc71ad9813b0e247cf7ffbcc3a432"},
1380 | ]
1381 |
1382 | [package.dependencies]
1383 | markdown-it-py = ">=2.2.0"
1384 | pygments = ">=2.13.0,<3.0.0"
1385 |
1386 | [package.extras]
1387 | jupyter = ["ipywidgets (>=7.5.1,<9)"]
1388 |
1389 | [[package]]
1390 | name = "ruff"
1391 | version = "0.7.2"
1392 | description = "An extremely fast Python linter and code formatter, written in Rust."
1393 | optional = false
1394 | python-versions = ">=3.7"
1395 | files = [
1396 | {file = "ruff-0.7.2-py3-none-linux_armv6l.whl", hash = "sha256:b73f873b5f52092e63ed540adefc3c36f1f803790ecf2590e1df8bf0a9f72cb8"},
1397 | {file = "ruff-0.7.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:5b813ef26db1015953daf476202585512afd6a6862a02cde63f3bafb53d0b2d4"},
1398 | {file = "ruff-0.7.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:853277dbd9675810c6826dad7a428d52a11760744508340e66bf46f8be9701d9"},
1399 | {file = "ruff-0.7.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:21aae53ab1490a52bf4e3bf520c10ce120987b047c494cacf4edad0ba0888da2"},
1400 | {file = "ruff-0.7.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ccc7e0fc6e0cb3168443eeadb6445285abaae75142ee22b2b72c27d790ab60ba"},
1401 | {file = "ruff-0.7.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fd77877a4e43b3a98e5ef4715ba3862105e299af0c48942cc6d51ba3d97dc859"},
1402 | {file = "ruff-0.7.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:e00163fb897d35523c70d71a46fbaa43bf7bf9af0f4534c53ea5b96b2e03397b"},
1403 | {file = "ruff-0.7.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f3c54b538633482dc342e9b634d91168fe8cc56b30a4b4f99287f4e339103e88"},
1404 | {file = "ruff-0.7.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7b792468e9804a204be221b14257566669d1db5c00d6bb335996e5cd7004ba80"},
1405 | {file = "ruff-0.7.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dba53ed84ac19ae4bfb4ea4bf0172550a2285fa27fbb13e3746f04c80f7fa088"},
1406 | {file = "ruff-0.7.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:b19fafe261bf741bca2764c14cbb4ee1819b67adb63ebc2db6401dcd652e3748"},
1407 | {file = "ruff-0.7.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:28bd8220f4d8f79d590db9e2f6a0674f75ddbc3847277dd44ac1f8d30684b828"},
1408 | {file = "ruff-0.7.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:9fd67094e77efbea932e62b5d2483006154794040abb3a5072e659096415ae1e"},
1409 | {file = "ruff-0.7.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:576305393998b7bd6c46018f8104ea3a9cb3fa7908c21d8580e3274a3b04b691"},
1410 | {file = "ruff-0.7.2-py3-none-win32.whl", hash = "sha256:fa993cfc9f0ff11187e82de874dfc3611df80852540331bc85c75809c93253a8"},
1411 | {file = "ruff-0.7.2-py3-none-win_amd64.whl", hash = "sha256:dd8800cbe0254e06b8fec585e97554047fb82c894973f7ff18558eee33d1cb88"},
1412 | {file = "ruff-0.7.2-py3-none-win_arm64.whl", hash = "sha256:bb8368cd45bba3f57bb29cbb8d64b4a33f8415d0149d2655c5c8539452ce7760"},
1413 | {file = "ruff-0.7.2.tar.gz", hash = "sha256:2b14e77293380e475b4e3a7a368e14549288ed2931fce259a6f99978669e844f"},
1414 | ]
1415 |
1416 | [[package]]
1417 | name = "six"
1418 | version = "1.16.0"
1419 | description = "Python 2 and 3 compatibility utilities"
1420 | optional = true
1421 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
1422 | files = [
1423 | {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
1424 | {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
1425 | ]
1426 |
1427 | [[package]]
1428 | name = "sympy"
1429 | version = "1.12"
1430 | description = "Computer algebra system (CAS) in Python"
1431 | optional = false
1432 | python-versions = ">=3.8"
1433 | files = [
1434 | {file = "sympy-1.12-py3-none-any.whl", hash = "sha256:c3588cd4295d0c0f603d0f2ae780587e64e2efeedb3521e46b9bb1d08d184fa5"},
1435 | {file = "sympy-1.12.tar.gz", hash = "sha256:ebf595c8dac3e0fdc4152c51878b498396ec7f30e7a914d6071e674d49420fb8"},
1436 | ]
1437 |
1438 | [package.dependencies]
1439 | mpmath = ">=0.19"
1440 |
1441 | [[package]]
1442 | name = "tomli"
1443 | version = "2.0.1"
1444 | description = "A lil' TOML parser"
1445 | optional = false
1446 | python-versions = ">=3.7"
1447 | files = [
1448 | {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
1449 | {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
1450 | ]
1451 |
1452 | [[package]]
1453 | name = "tomlkit"
1454 | version = "0.12.4"
1455 | description = "Style preserving TOML library"
1456 | optional = false
1457 | python-versions = ">=3.7"
1458 | files = [
1459 | {file = "tomlkit-0.12.4-py3-none-any.whl", hash = "sha256:5cd82d48a3dd89dee1f9d64420aa20ae65cfbd00668d6f094d7578a78efbb77b"},
1460 | {file = "tomlkit-0.12.4.tar.gz", hash = "sha256:7ca1cfc12232806517a8515047ba66a19369e71edf2439d0f5824f91032b6cc3"},
1461 | ]
1462 |
1463 | [[package]]
1464 | name = "tqdm"
1465 | version = "4.66.2"
1466 | description = "Fast, Extensible Progress Meter"
1467 | optional = false
1468 | python-versions = ">=3.7"
1469 | files = [
1470 | {file = "tqdm-4.66.2-py3-none-any.whl", hash = "sha256:1ee4f8a893eb9bef51c6e35730cebf234d5d0b6bd112b0271e10ed7c24a02bd9"},
1471 | {file = "tqdm-4.66.2.tar.gz", hash = "sha256:6cd52cdf0fef0e0f543299cfc96fec90d7b8a7e88745f411ec33eb44d5ed3531"},
1472 | ]
1473 |
1474 | [package.dependencies]
1475 | colorama = {version = "*", markers = "platform_system == \"Windows\""}
1476 |
1477 | [package.extras]
1478 | dev = ["pytest (>=6)", "pytest-cov", "pytest-timeout", "pytest-xdist"]
1479 | notebook = ["ipywidgets (>=6)"]
1480 | slack = ["slack-sdk"]
1481 | telegram = ["requests"]
1482 |
1483 | [[package]]
1484 | name = "types-pyyaml"
1485 | version = "6.0.12.20240311"
1486 | description = "Typing stubs for PyYAML"
1487 | optional = false
1488 | python-versions = ">=3.8"
1489 | files = [
1490 | {file = "types-PyYAML-6.0.12.20240311.tar.gz", hash = "sha256:a9e0f0f88dc835739b0c1ca51ee90d04ca2a897a71af79de9aec5f38cb0a5342"},
1491 | {file = "types_PyYAML-6.0.12.20240311-py3-none-any.whl", hash = "sha256:b845b06a1c7e54b8e5b4c683043de0d9caf205e7434b3edc678ff2411979b8f6"},
1492 | ]
1493 |
1494 | [[package]]
1495 | name = "typing-extensions"
1496 | version = "4.11.0"
1497 | description = "Backported and Experimental Type Hints for Python 3.8+"
1498 | optional = false
1499 | python-versions = ">=3.8"
1500 | files = [
1501 | {file = "typing_extensions-4.11.0-py3-none-any.whl", hash = "sha256:c1f94d72897edaf4ce775bb7558d5b79d8126906a14ea5ed1635921406c0387a"},
1502 | {file = "typing_extensions-4.11.0.tar.gz", hash = "sha256:83f085bd5ca59c80295fc2a82ab5dac679cbe02b9f33f7d83af68e241bea51b0"},
1503 | ]
1504 |
1505 | [[package]]
1506 | name = "urllib3"
1507 | version = "2.2.3"
1508 | description = "HTTP library with thread-safe connection pooling, file post, and more."
1509 | optional = true
1510 | python-versions = ">=3.8"
1511 | files = [
1512 | {file = "urllib3-2.2.3-py3-none-any.whl", hash = "sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac"},
1513 | {file = "urllib3-2.2.3.tar.gz", hash = "sha256:e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9"},
1514 | ]
1515 |
1516 | [package.extras]
1517 | brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"]
1518 | h2 = ["h2 (>=4,<5)"]
1519 | socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"]
1520 | zstd = ["zstandard (>=0.18.0)"]
1521 |
1522 | [[package]]
1523 | name = "verspec"
1524 | version = "0.1.0"
1525 | description = "Flexible version handling"
1526 | optional = true
1527 | python-versions = "*"
1528 | files = [
1529 | {file = "verspec-0.1.0-py3-none-any.whl", hash = "sha256:741877d5633cc9464c45a469ae2a31e801e6dbbaa85b9675d481cda100f11c31"},
1530 | {file = "verspec-0.1.0.tar.gz", hash = "sha256:c4504ca697b2056cdb4bfa7121461f5a0e81809255b41c03dda4ba823637c01e"},
1531 | ]
1532 |
1533 | [package.extras]
1534 | test = ["coverage", "flake8 (>=3.7)", "mypy", "pretend", "pytest"]
1535 |
1536 | [[package]]
1537 | name = "watchdog"
1538 | version = "6.0.0"
1539 | description = "Filesystem events monitoring"
1540 | optional = true
1541 | python-versions = ">=3.9"
1542 | files = [
1543 | {file = "watchdog-6.0.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d1cdb490583ebd691c012b3d6dae011000fe42edb7a82ece80965b42abd61f26"},
1544 | {file = "watchdog-6.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bc64ab3bdb6a04d69d4023b29422170b74681784ffb9463ed4870cf2f3e66112"},
1545 | {file = "watchdog-6.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c897ac1b55c5a1461e16dae288d22bb2e412ba9807df8397a635d88f671d36c3"},
1546 | {file = "watchdog-6.0.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6eb11feb5a0d452ee41f824e271ca311a09e250441c262ca2fd7ebcf2461a06c"},
1547 | {file = "watchdog-6.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ef810fbf7b781a5a593894e4f439773830bdecb885e6880d957d5b9382a960d2"},
1548 | {file = "watchdog-6.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:afd0fe1b2270917c5e23c2a65ce50c2a4abb63daafb0d419fde368e272a76b7c"},
1549 | {file = "watchdog-6.0.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:bdd4e6f14b8b18c334febb9c4425a878a2ac20efd1e0b231978e7b150f92a948"},
1550 | {file = "watchdog-6.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c7c15dda13c4eb00d6fb6fc508b3c0ed88b9d5d374056b239c4ad1611125c860"},
1551 | {file = "watchdog-6.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6f10cb2d5902447c7d0da897e2c6768bca89174d0c6e1e30abec5421af97a5b0"},
1552 | {file = "watchdog-6.0.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:490ab2ef84f11129844c23fb14ecf30ef3d8a6abafd3754a6f75ca1e6654136c"},
1553 | {file = "watchdog-6.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:76aae96b00ae814b181bb25b1b98076d5fc84e8a53cd8885a318b42b6d3a5134"},
1554 | {file = "watchdog-6.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a175f755fc2279e0b7312c0035d52e27211a5bc39719dd529625b1930917345b"},
1555 | {file = "watchdog-6.0.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e6f0e77c9417e7cd62af82529b10563db3423625c5fce018430b249bf977f9e8"},
1556 | {file = "watchdog-6.0.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:90c8e78f3b94014f7aaae121e6b909674df5b46ec24d6bebc45c44c56729af2a"},
1557 | {file = "watchdog-6.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e7631a77ffb1f7d2eefa4445ebbee491c720a5661ddf6df3498ebecae5ed375c"},
1558 | {file = "watchdog-6.0.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:c7ac31a19f4545dd92fc25d200694098f42c9a8e391bc00bdd362c5736dbf881"},
1559 | {file = "watchdog-6.0.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:9513f27a1a582d9808cf21a07dae516f0fab1cf2d7683a742c498b93eedabb11"},
1560 | {file = "watchdog-6.0.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7a0e56874cfbc4b9b05c60c8a1926fedf56324bb08cfbc188969777940aef3aa"},
1561 | {file = "watchdog-6.0.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:e6439e374fc012255b4ec786ae3c4bc838cd7309a540e5fe0952d03687d8804e"},
1562 | {file = "watchdog-6.0.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:7607498efa04a3542ae3e05e64da8202e58159aa1fa4acddf7678d34a35d4f13"},
1563 | {file = "watchdog-6.0.0-py3-none-manylinux2014_armv7l.whl", hash = "sha256:9041567ee8953024c83343288ccc458fd0a2d811d6a0fd68c4c22609e3490379"},
1564 | {file = "watchdog-6.0.0-py3-none-manylinux2014_i686.whl", hash = "sha256:82dc3e3143c7e38ec49d61af98d6558288c415eac98486a5c581726e0737c00e"},
1565 | {file = "watchdog-6.0.0-py3-none-manylinux2014_ppc64.whl", hash = "sha256:212ac9b8bf1161dc91bd09c048048a95ca3a4c4f5e5d4a7d1b1a7d5752a7f96f"},
1566 | {file = "watchdog-6.0.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:e3df4cbb9a450c6d49318f6d14f4bbc80d763fa587ba46ec86f99f9e6876bb26"},
1567 | {file = "watchdog-6.0.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:2cce7cfc2008eb51feb6aab51251fd79b85d9894e98ba847408f662b3395ca3c"},
1568 | {file = "watchdog-6.0.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:20ffe5b202af80ab4266dcd3e91aae72bf2da48c0d33bdb15c66658e685e94e2"},
1569 | {file = "watchdog-6.0.0-py3-none-win32.whl", hash = "sha256:07df1fdd701c5d4c8e55ef6cf55b8f0120fe1aef7ef39a1c6fc6bc2e606d517a"},
1570 | {file = "watchdog-6.0.0-py3-none-win_amd64.whl", hash = "sha256:cbafb470cf848d93b5d013e2ecb245d4aa1c8fd0504e863ccefa32445359d680"},
1571 | {file = "watchdog-6.0.0-py3-none-win_ia64.whl", hash = "sha256:a1914259fa9e1454315171103c6a30961236f508b9b623eae470268bbcc6a22f"},
1572 | {file = "watchdog-6.0.0.tar.gz", hash = "sha256:9ddf7c82fda3ae8e24decda1338ede66e1c99883db93711d8fb941eaa2d8c282"},
1573 | ]
1574 |
1575 | [package.extras]
1576 | watchmedo = ["PyYAML (>=3.10)"]
1577 |
1578 | [[package]]
1579 | name = "zipp"
1580 | version = "3.20.2"
1581 | description = "Backport of pathlib-compatible object wrapper for zip files"
1582 | optional = true
1583 | python-versions = ">=3.8"
1584 | files = [
1585 | {file = "zipp-3.20.2-py3-none-any.whl", hash = "sha256:a817ac80d6cf4b23bf7f2828b7cabf326f15a001bea8b1f9b49631780ba28350"},
1586 | {file = "zipp-3.20.2.tar.gz", hash = "sha256:bc9eb26f4506fda01b81bcde0ca78103b6e62f991b381fec825435c836edbc29"},
1587 | ]
1588 |
1589 | [package.extras]
1590 | check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)"]
1591 | cover = ["pytest-cov"]
1592 | doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
1593 | enabler = ["pytest-enabler (>=2.2)"]
1594 | test = ["big-O", "importlib-resources", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-ignore-flaky"]
1595 | type = ["pytest-mypy"]
1596 |
1597 | [extras]
1598 | docs = ["mike", "mkdocs-material", "mkdocstrings"]
1599 |
1600 | [metadata]
1601 | lock-version = "2.0"
1602 | python-versions = ">=3.10,<4.0"
1603 | content-hash = "995f846b9ab37153d6595f080f2eea936ab3e1a2093becb0929f602c2abb12a5"
1604 |
--------------------------------------------------------------------------------
/poetry.toml:
--------------------------------------------------------------------------------
1 | [virtualenvs]
2 | in-project = true
3 | prefer-active-python = true
4 |
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [tool.poetry]
2 | name = "fast-alpr"
3 | version = "0.1.2"
4 | description = "Fast Automatic License Plate Recognition."
5 | authors = ["ankandrew <61120139+ankandrew@users.noreply.github.com>"]
6 | readme = "README.md"
7 | license = "MIT"
8 | keywords = [
9 | "image-processing",
10 | "computer-vision",
11 | "deep-learning",
12 | "object-detection",
13 | "plate-detection",
14 | "license-plate-ocr",
15 | "onnx",
16 | ]
17 | classifiers = [
18 | "Typing :: Typed",
19 | "Intended Audience :: Developers",
20 | "Intended Audience :: Education",
21 | "Intended Audience :: Science/Research",
22 | "Operating System :: OS Independent",
23 | "Topic :: Software Development",
24 | "Topic :: Scientific/Engineering",
25 | "Topic :: Software Development :: Libraries",
26 | "Topic :: Software Development :: Build Tools",
27 | "Topic :: Scientific/Engineering :: Artificial Intelligence",
28 | "Topic :: Software Development :: Libraries :: Python Modules",
29 | ]
30 |
31 | [tool.poetry.dependencies]
32 | python = ">=3.10,<4.0"
33 | opencv-python = "^4.9.0.80"
34 | fast-plate-ocr = "^0.3.0"
35 | open-image-models = "^0.2.0"
36 |
37 | # Optional packages for creating the docs
38 | mkdocs-material = { version = "*", optional = true }
39 | mkdocstrings = { version = "*", extras = ["python"], optional = true }
40 | mike = { version = "*", optional = true }
41 |
42 | [tool.poetry.extras]
43 | docs = ["mkdocs-material", "mkdocstrings", "mike"]
44 |
45 | [tool.poetry.group.test.dependencies]
46 | pytest = "*"
47 |
48 | [tool.poetry.group.dev.dependencies]
49 | mypy = "*"
50 | ruff = "*"
51 | pylint = "*"
52 | types-pyyaml = "*"
53 |
54 | [tool.ruff]
55 | line-length = 100
56 | target-version = "py310"
57 |
58 | [tool.ruff.lint]
59 | select = [
60 | # pycodestyle
61 | "E",
62 | "W",
63 | # Pyflakes
64 | "F",
65 | # pep8-naming
66 | "N",
67 | # pyupgrade
68 | "UP",
69 | # flake8-bugbear
70 | "B",
71 | # flake8-simplify
72 | "SIM",
73 | # flake8-unused-arguments
74 | "ARG",
75 | # Pylint
76 | "PL",
77 | # Perflint
78 | "PERF",
79 | # Ruff-specific rules
80 | "RUF",
81 | # pandas-vet
82 | "PD",
83 | ]
84 | ignore = ["N812", "PLR2004", "PD011"]
85 | fixable = ["ALL"]
86 | unfixable = []
87 |
88 | [tool.ruff.lint.pylint]
89 | max-args = 8
90 |
91 | [tool.ruff.format]
92 | line-ending = "lf"
93 |
94 | [tool.mypy]
95 | disable_error_code = "import-untyped"
96 |
97 | [tool.pylint.typecheck]
98 | generated-members = ["cv2.*"]
99 | signature-mutators = [
100 | "click.decorators.option",
101 | "click.decorators.argument",
102 | "click.decorators.version_option",
103 | "click.decorators.help_option",
104 | "click.decorators.pass_context",
105 | "click.decorators.confirmation_option"
106 | ]
107 |
108 | [tool.pylint.format]
109 | max-line-length = 100
110 |
111 | [tool.pylint."messages control"]
112 | disable = ["missing-class-docstring", "missing-function-docstring"]
113 |
114 | [tool.pylint.design]
115 | max-args = 8
116 | min-public-methods = 1
117 |
118 | [tool.pylint.basic]
119 | no-docstring-rgx = "^__|^test_"
120 |
121 | [build-system]
122 | requires = ["poetry-core"]
123 | build-backend = "poetry.core.masonry.api"
124 |
--------------------------------------------------------------------------------
/test/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ankandrew/fast-alpr/8ffc0a799ada0938069da38c519ec7962828dd2b/test/__init__.py
--------------------------------------------------------------------------------
/test/test_alpr.py:
--------------------------------------------------------------------------------
1 | """
2 | Test ALPR end-to-end.
3 | """
4 |
5 | from pathlib import Path
6 |
7 | import cv2
8 | import pytest
9 |
10 | from fast_alpr.alpr import ALPR
11 |
12 | ASSETS_DIR = Path(__file__).resolve().parent.parent / "assets"
13 |
14 |
15 | @pytest.mark.parametrize(
16 | "img_path, expected_plates", [(ASSETS_DIR / "test_image.png", {"5AU5341"})]
17 | )
18 | def test_default_alpr(img_path: Path, expected_plates: set[str]) -> None:
19 | im = cv2.imread(str(img_path))
20 | alpr = ALPR(
21 | detector_model="yolo-v9-t-384-license-plate-end2end",
22 | ocr_model="global-plates-mobile-vit-v2-model",
23 | )
24 | actual_result = alpr.predict(im)
25 | actual_plates = {x.ocr.text for x in actual_result if x.ocr is not None}
26 | assert actual_plates == expected_plates
27 |
28 | for res in actual_result:
29 | bbox = res.detection.bounding_box
30 | height, width = im.shape[:2]
31 | x1, y1 = max(bbox.x1, 0), max(bbox.y1, 0)
32 | x2, y2 = min(bbox.x2, width), min(bbox.y2, height)
33 |
34 | assert 0 <= x1 < width, f"x1 coordinate {x1} out of bounds (0, {width})"
35 | assert 0 <= x2 <= width, f"x2 coordinate {x2} out of bounds (0, {width})"
36 | assert 0 <= y1 < height, f"y1 coordinate {y1} out of bounds (0, {height})"
37 | assert 0 <= y2 <= height, f"y2 coordinate {y2} out of bounds (0, {height})"
38 | assert x1 < x2, f"x1 ({x1}) should be less than x2 ({x2})"
39 | assert y1 < y2, f"y1 ({y1}) should be less than y2 ({y2})"
40 |
41 | if res.ocr is not None:
42 | conf = res.ocr.confidence
43 | if isinstance(conf, list):
44 | assert all(0.0 <= x <= 1.0 for x in conf)
45 | elif isinstance(conf, float):
46 | assert 0.0 <= conf <= 1.0
47 | else:
48 | raise TypeError(f"Unexpected type for confidence: {type(conf).__name__}")
49 |
--------------------------------------------------------------------------------