pax_global_header00006660000000000000000000000064147124775010014522gustar00rootroot0000000000000052 comment=316d08303807e61e66dcfba107dbe6e6d6fc4db5 python-crc-7.1.0/000077500000000000000000000000001471247750100136155ustar00rootroot00000000000000python-crc-7.1.0/.github/000077500000000000000000000000001471247750100151555ustar00rootroot00000000000000python-crc-7.1.0/.github/ISSUE_TEMPLATE/000077500000000000000000000000001471247750100173405ustar00rootroot00000000000000python-crc-7.1.0/.github/ISSUE_TEMPLATE/blank.md000066400000000000000000000001461471247750100207520ustar00rootroot00000000000000--- name: πŸ“ Blank Issue about: Blank Issue title: πŸ“ labels: assignees: '' --- python-crc-7.1.0/.github/ISSUE_TEMPLATE/bug.md000066400000000000000000000034721471247750100204450ustar00rootroot00000000000000--- name: 🐞 Bug Report about: File a bug report title: 🐞 labels: bug assignees: '' --- ### Checklist In order to improve the time, how long a bugfix does take, please make sure you address as much as possible of the following checklist. - [ ] I have reproduced the issue with at least the latest released version of \. - [ ] I have added references to issues that sound similar. **Tip: Adding screenshots, outputs and logs help to improve clarity.** # Summary ## Reproducing the Issue Reproducibility: sporadic, regularly, always ### Steps to reproduce the behavior: 1. 2. 3. .... ## Expected Behaviour ## Actual Behaviour ## Root Cause (optional) ## Context ### System **Desktop:** - OS: [e.g. Linux (Fedora 35), Linux (Ubuntu 20.01), MacOs (...), Windows (...)] - Python Version [e.g. Python 3.8.0] - Package Version [e.g. 22] ### Additional Context (optional) #### Related Issues (optional) python-crc-7.1.0/.github/ISSUE_TEMPLATE/documentation.md000066400000000000000000000015501471247750100225340ustar00rootroot00000000000000--- name: πŸ“š Documentation about: Add/Improve Documentation title: πŸ“š labels: documentation assignees: '' --- # Summary # Details ## Background & Context ## References # Task(s) python-crc-7.1.0/.github/ISSUE_TEMPLATE/feature.md000066400000000000000000000016321471247750100213170ustar00rootroot00000000000000--- name: ✨ Feature about: Add/Implement Feature title: ✨ labels: feature assignees: '' --- # Summary # Details ## Background & Context ## Examples ## References # Task(s) python-crc-7.1.0/.github/ISSUE_TEMPLATE/refactoring.md000066400000000000000000000017401471247750100221670ustar00rootroot00000000000000--- name: πŸ”§ Refactoring about: Refactor title: πŸ”§ labels: refactoring assignees: '' --- # Summary # Details ## Background & Context ## Examples ## References # Task(s) python-crc-7.1.0/.github/ISSUE_TEMPLATE/security.md000066400000000000000000000021051471247750100215270ustar00rootroot00000000000000--- name: πŸ” Security Issue about: Fix Security Issue title: πŸ” labels: security assignees: '' --- # Summary | | | |------------|-----| | Class/Type | - | | Version(s) | - | | Severity | - | | CVE Number | - | # Details ### Description ### Impact ### References # Solutions # Credit python-crc-7.1.0/.github/actions/000077500000000000000000000000001471247750100166155ustar00rootroot00000000000000python-crc-7.1.0/.github/actions/python-environment/000077500000000000000000000000001471247750100225005ustar00rootroot00000000000000python-crc-7.1.0/.github/actions/python-environment/action.yml000066400000000000000000000012721471247750100245020ustar00rootroot00000000000000name: 'SPPE' description: 'Setup python and poetry environment' inputs: python-version: description: 'Python version to use' required: true default: 3.8 poetry-version: description: 'Poetry version to use' required: true default: 1.2.2 runs: using: "composite" steps: - name: Setup Python (${{ inputs.python-version}}) uses: actions/setup-python@v5.1.0 with: python-version: ${{ inputs.python-version }} - name: Setup Poetry (${{ inputs.poetry-version }}) uses: abatilo/actions-poetry@v3 with: poetry-version: ${{ inputs.poetry-version }} - name: Poetry install run: poetry install shell: bash python-crc-7.1.0/.github/dependabot.yml000066400000000000000000000007021471247750100200040ustar00rootroot00000000000000version: 2 updates: # Maintain dependencies for GitHub Actions - package-ecosystem: "github-actions" directory: "/" schedule: interval: "weekly" day: "monday" open-pull-requests-limit: 5 # Maintain dependencies for poetry - package-ecosystem: "pip" directory: "/" schedule: interval: "monthly" day: "monday" open-pull-requests-limit: 5 groups: dev: patterns: - "*"python-crc-7.1.0/.github/workflows/000077500000000000000000000000001471247750100172125ustar00rootroot00000000000000python-crc-7.1.0/.github/workflows/checks.yml000066400000000000000000000050771471247750100212060ustar00rootroot00000000000000name: Checks on: workflow_call jobs: format-job: name: "Format (Python-${{ matrix.python-version }} on ${{ matrix.os }})" runs-on: ${{ matrix.os }} strategy: fail-fast: true matrix: os: - ubuntu-latest python-version: - "3.8" steps: - name: SCM Checkout uses: actions/checkout@v4 - name: Setup Python & Poetry Environment uses: ./.github/actions/python-environment with: python-version: ${{ matrix.python-version }} - name: Run Coverage run: poetry run invoke check.format typing-job: name: "Typing (Python-${{ matrix.python-version }} on ${{ matrix.os }})" needs: [format-job] runs-on: ${{ matrix.os }} strategy: fail-fast: true matrix: os: - ubuntu-latest python-version: - "3.8" - "3.9" - "3.10" - "3.11" - "3.12" steps: - name: SCM Checkout uses: actions/checkout@v4 - name: Setup Python & Poetry Environment uses: ./.github/actions/python-environment with: python-version: ${{ matrix.python-version }} - name: Run Coverage run: poetry run invoke check.typing --files src/ linting-job: name: "Lint (Python-${{ matrix.python-version }} on ${{ matrix.os }})" needs: [format-job] runs-on: ${{ matrix.os }} strategy: fail-fast: true matrix: os: - ubuntu-latest python-version: - "3.8" steps: - name: SCM Checkout uses: actions/checkout@v4 - name: Setup Python & Poetry Environment uses: ./.github/actions/python-environment with: python-version: ${{ matrix.python-version }} - name: Run Linter run: poetry run invoke check.lint --files src/ tests-job: name: "Tests (Python-${{ matrix.python-version }} on ${{ matrix.os }})" needs: [format-job, linting-job, typing-job] runs-on: ${{ matrix.os }} strategy: fail-fast: true matrix: os: - ubuntu-latest - macos-latest - windows-latest python-version: - "3.8" - "3.9" - "3.10" - "3.11" - "3.12" steps: - name: SCM Checkout uses: actions/checkout@v4 - name: Setup Python & Poetry Environment uses: ./.github/actions/python-environment with: python-version: ${{ matrix.python-version }} - name: Run Tests run: poetry run invoke test.coverage python-crc-7.1.0/.github/workflows/ci-cd.yml000066400000000000000000000025451471247750100207220ustar00rootroot00000000000000name: CI/CD on: push: tags: - '**' jobs: check-tag-version-job: name: Check Tag Version runs-on: ubuntu-latest steps: - name: SCM Checkout uses: actions/checkout@v4 - name: Setup Python & Poetry Environment uses: ./.github/actions/python-environment - name: Check Tag Version # make sure the pushed/created tag matched the project version run: "[[ `poetry version --short` == ${{ github.ref_name }} ]]" ci-job: name: Checks needs: [ check-tag-version-job ] uses: ./.github/workflows/checks.yml cd-job: name: Continues Delivery needs: [ ci-job ] runs-on: ubuntu-latest steps: - name: SCM Checkout uses: actions/checkout@v4 - name: Setup Python & Poetry Environment uses: ./.github/actions/python-environment - name: Build Artifacts run: poetry build - name: PyPi Release env: POETRY_HTTP_BASIC_PYPI_USERNAME: "__token__" POETRY_HTTP_BASIC_PYPI_PASSWORD: "${{ secrets.PYPI_TOKEN }}" run: poetry publish - name: GitHub Release env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: > gh release create ${GITHUB_REF_NAME} --title ${GITHUB_REF_NAME} --notes-file docs/docs/changelog/changes_${GITHUB_REF_NAME}.md dist/* python-crc-7.1.0/.github/workflows/ci.yml000066400000000000000000000001521471247750100203260ustar00rootroot00000000000000name: CI on: pull_request: jobs: ci-job: name: Checks uses: ./.github/workflows/checks.yml python-crc-7.1.0/.github/workflows/gh-pages.yml000066400000000000000000000013631471247750100214330ustar00rootroot00000000000000name: Publish Documentation on: workflow_call jobs: documentation-job: runs-on: ubuntu-latest steps: - name: SCM Checkout uses: actions/checkout@v4 - name: Setup Python & Poetry Environment uses: ./.github/actions/python-environment with: python-version: "3.10" - name: Build Documentation run: | poetry run mkdocs build -c -s -d ../.html-documentation -f docs/mkdocs.yml touch .html-documentation/.nojekyll - name: Deploy uses: JamesIves/github-pages-deploy-action@v4.6.8 with: branch: gh-pages folder: .html-documentation git-config-name: Github Action git-config-email: nico.coretti@gmail.com python-crc-7.1.0/.github/workflows/pr-merge.yml000066400000000000000000000015521471247750100214560ustar00rootroot00000000000000name: PR-Merge on: push: branches: - 'master' jobs: ci-job: name: Checks uses: ./.github/workflows/checks.yml publish-coverage: name: Publish Code Coverage runs-on: ubuntu-latest steps: - name: SCM Checkout uses: actions/checkout@v4 - name: Setup Python & Poetry Environment uses: ./.github/actions/python-environment with: python-version: 3.8 - name: Collect Code Coverage run: poetry run invoke test.coverage env: COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }} - name: Publish Code Coverage env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: poetry run coveralls --service=github publish-docs: name: Publish Documentation uses: ./.github/workflows/gh-pages.yml python-crc-7.1.0/.gitignore000066400000000000000000000001731471247750100156060ustar00rootroot00000000000000.html-documentation/ .idea dist .tox venv/ __pycache__/* docs/_build/* .coverage *.egg-info/ *.pyc */__pychache__/* .envrc python-crc-7.1.0/.pre-commit-config.yaml000066400000000000000000000003031471247750100200720ustar00rootroot00000000000000default_stages: [ push ] repos: - repo: local hooks: - id: fmt name: fmt entry: echo "foo" language: system always_run: true types: [ python ] python-crc-7.1.0/LICENSE.txt000066400000000000000000000024311471247750100154400ustar00rootroot00000000000000Copyright (c) 2016, Nicola Coretti All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. python-crc-7.1.0/README.md000066400000000000000000000107741471247750100151050ustar00rootroot00000000000000

CRC

Calculate CRC checksums, verify CRC checksum, predefined CRC configurations, custom CRC configurations

Checks Master Coverage License Downloads Supported Python Versions PyPi Package

--- * Documentation: [https://nicoretti.github.io/crc](https://nicoretti.github.io/crc) * Source Code: [https://github.com/Nicoretti/crc](https://github.com/Nicoretti/crc) --- ## Available CRC Configurations For convenience various frequently used crc configurations ship with the library out of the box. | CRC8 | CRC16 | CRC32 | CRC64 | |---------------|----------|---------|-------| | CCITT | XMODEM | CRC32 | CRC64 | | AUTOSAR | GSM | AUTOSAR | | | SAEJ1850 | PROFIBUS | BZIP2 | | | SAEJ1850_ZERO | MODBUS | POSIX | | | BLUETOOTH | IBM-3740 | | | | MAXIM-DOW | KERMIT | | | If you find yourself in the position, where having a new configuration available out of the box would be desirable, feel free to create a [PR](https://github.com/Nicoretti/crc/pulls) or file an [issue](https://github.com/Nicoretti/crc/issues). ## Custom Configurations If you want to create a custom configuration, you should have the following information available: πŸ—’ Note: This library currently only supports bit widths of full bytes 8, 16, 24, 32, ... * **width** * **polynom** * **init value** * **final xor value** * **reversed input** * **reversed output** In case you only have a name of a specific crc configuration/algorithm and you are unsure what are the specific parameters of it, a look into this [crc-catalogue](http://reveng.sourceforge.net/crc-catalogue/all.htm) might help. ## Requirements * [\>= Python 3.8](https://www.python.org) ## Installation ```shell pip install crc ``` ## Examples ### Create a Calculator #### Pre defined configuration ```python from crc import Calculator, Crc8 calculator = Calculator(Crc8.CCITT) ``` #### Custom configuration ```python from crc import Calculator, Configuration config = Configuration( width=8, polynomial=0x07, init_value=0x00, final_xor_value=0x00, reverse_input=False, reverse_output=False, ) calculator = Calculator(config) ``` ### Calculate a checksum #### Standard ```python from crc import Calculator, Crc8 expected = 0xBC data = bytes([0, 1, 2, 3, 4, 5]) calculator = Calculator(Crc8.CCITT) assert expected == calculator.checksum(data) ``` #### Optimized for speed ```python from crc import Calculator, Crc8 expected = 0xBC data = bytes([0, 1, 2, 3, 4, 5]) calculator = Calculator(Crc8.CCITT, optimized=True) assert expected == calculator.checksum(data) ``` ### Verify a checksum #### Standard ```python from crc import Calculator, Crc8 expected = 0xBC data = bytes([0, 1, 2, 3, 4, 5]) calculator = Calculator(Crc8.CCITT) assert calculator.verify(data, expected) ``` #### Optimized for speed ```python from crc import Calculator, Crc8 expected = 0xBC data = bytes([0, 1, 2, 3, 4, 5]) calculator = Calculator(Crc8.CCITT, optimized=True) assert calculator.verify(data, expected) ``` ### Calculate a checksum with raw registers #### Register ```python from crc import Crc8, Register expected = 0xBC data = bytes([0, 1, 2, 3, 4, 5]) register = Register(Crc8.CCITT) register.init() register.update(data) assert expected == register.digest() ``` #### TableBasedRegister ```python from crc import Crc8, TableBasedRegister expected = 0xBC data = bytes([0, 1, 2, 3, 4, 5]) register = TableBasedRegister(Crc8.CCITT) register.init() register.update(data) assert expected == register.digest() ``` References & Resources ----------------------- * [A Painless guide to crc error detection algorithms](http://www.zlib.net/crc_v3.txt) * [CRC-Catalogue](http://reveng.sourceforge.net/crc-catalogue/all.htm) python-crc-7.1.0/docs/000077500000000000000000000000001471247750100145455ustar00rootroot00000000000000python-crc-7.1.0/docs/docs/000077500000000000000000000000001471247750100154755ustar00rootroot00000000000000python-crc-7.1.0/docs/docs/api/000077500000000000000000000000001471247750100162465ustar00rootroot00000000000000python-crc-7.1.0/docs/docs/api/abstract_register.md000066400000000000000000000000551471247750100222770ustar00rootroot00000000000000# AbstractRegister ::: crc.AbstractRegister python-crc-7.1.0/docs/docs/api/basic_register.md000066400000000000000000000000471471247750100215560ustar00rootroot00000000000000# BasicRegister ::: crc.BasicRegister python-crc-7.1.0/docs/docs/api/calculator.md000066400000000000000000000001301471247750100207130ustar00rootroot00000000000000# Calculator ::: crc options: members: - InputType ::: crc.Calculator python-crc-7.1.0/docs/docs/api/configuration.md000066400000000000000000000002411471247750100214340ustar00rootroot00000000000000# Configuration ::: crc.Configuration options: members: ["width", "polynomial", "init_value", "final_xor_value", "reverse_input", "reverse_output"] python-crc-7.1.0/docs/docs/api/crc16.md000066400000000000000000000002071471247750100175050ustar00rootroot00000000000000# Crc16 ## Available Configurations ::: crc.Crc16 options: members: ["GSM", "PROFIBUS", "IBM","MAXIM","USB","X25","DNP"] python-crc-7.1.0/docs/docs/api/crc32.md000066400000000000000000000001711471247750100175030ustar00rootroot00000000000000# Crc32 ## Available Configurations ::: crc.Crc32 options: members: ["CRC32", "AUTOSAR", "BZIP2", "POSIX"] python-crc-7.1.0/docs/docs/api/crc64.md000066400000000000000000000001341471247750100175070ustar00rootroot00000000000000# Crc64 ## Available Configurations ::: crc.Crc64 options: members: ["CRC64"] python-crc-7.1.0/docs/docs/api/crc8.md000066400000000000000000000002301471247750100174220ustar00rootroot00000000000000# Crc8 ## Available Configurations ::: crc.Crc8 options: members: ["CCITT", "AUTOSAR", "BLUETOOTH", "SAEJ1850", "MAXIM_DOW","ITU","ROHC"] python-crc-7.1.0/docs/docs/api/register.md000066400000000000000000000000351471247750100204120ustar00rootroot00000000000000# Register ::: crc.Register python-crc-7.1.0/docs/docs/api/table_based_register.md000066400000000000000000000000611471247750100227160ustar00rootroot00000000000000# TableBasedRegister ::: crc.TableBasedRegister python-crc-7.1.0/docs/docs/changelog/000077500000000000000000000000001471247750100174245ustar00rootroot00000000000000python-crc-7.1.0/docs/docs/changelog/changes_2.0.0.md000066400000000000000000000016561471247750100221030ustar00rootroot00000000000000# 2.0.0 - 2022-11-27 ## 🚨 Breaking API Changes ** Renamed ** *Classes:* * `AbstractCrcRegister` -> `AbstractRegister` * `CrcRegisterBase` -> `BasicRegister` * `CrcRegister` -> `Register` * `TableBasedCrcRegister` -> `TableBasedRegister` * `CrcCalculator` -> `Calculator` *Functions & Methods:* * `CrcCalculator.calculate_checksum` -> `Calculator.checksum` * `CrcCalculator.verify_checksum` -> `Calculator.verify` * \[public\] `argument_parser()` -> \[private\] `_argument_parser()` *Arguments:* * `CrcCalculator(configuration, table_based=False)` -> `Calculator(configuration, optimized=False)` ** Removed ** * Removed `CRC_TYPES` mapping * Removed `checksum` function/cli-entry-point ## πŸ—‘ Removed * Removed checksum subcommand from CLI * Removed `CRC_TYPES` mapping ## ✨ Added * Added typing support * Added Documentation [see here](https://nicoretti.github.io/crc) ## πŸ”§ Refactorings * Fixed various linter warnings python-crc-7.1.0/docs/docs/changelog/changes_3.0.0.md000066400000000000000000000015561471247750100221030ustar00rootroot00000000000000# 3.0.0 - 2022-12-04 ## 🚨 Breaking API Changes ** Renamed ** *Functions & Methods:* * Renamed keyword argument `expected_checksum` of method `Calculator.verify` to `expected` === "Old API" ```python def verify(self, data: bytes, expected_checksum: int ) -> bool: ... ``` === "New API" ```python def verify(self, data: Union[int, ByteString, BinaryIO, Iterable[ByteString]], expected: int ) -> bool: ... ``` ## πŸ› Fixes * Fixed return type for all inputs of ByteString types ## ✨ Added * Added support for other data types than `bytes` to `Calculator.checksum` and `Calculator.verify` (`int`, `ByteString`, `BinaryIO`, `Iterable[ByteString]`) ## πŸ“š Documentation * Renamed "Latest - Changes" to "Unreleased" * Added "API" section * Added "development" section python-crc-7.1.0/docs/docs/changelog/changes_3.0.1.md000066400000000000000000000003101471247750100220670ustar00rootroot00000000000000# 3.0.1 - 2022-12-18 ## πŸ“š Documentation * Fix code example in 3.0.0 changelog entry * Fix code example in README #59 ## πŸ”© Internal * Adjust release.workflow task * Update dev dependencies python-crc-7.1.0/docs/docs/changelog/changes_4.0.0.md000066400000000000000000000004101471247750100220700ustar00rootroot00000000000000# 4.0.0 - 2022-12-18 ## 🚨 Breaking Changes * Remove Python 3.7 support ## πŸ“š Documentation * Update repository status badge * Fix heading in 3.0.1 changelog ## πŸ”© Internal * Remove nox support * Add additional pypi metadata * Fix CI/CD checks and tasks python-crc-7.1.0/docs/docs/changelog/changes_4.1.0.md000066400000000000000000000004631471247750100221010ustar00rootroot00000000000000# 4.1.0 - 2022-12-18 ## πŸ“š Documentation * Update repository status badge in documentation * Fix minimum required version in documentation and README * Update developer documentation ## πŸ”© Internal * Remove custom python version classifiers from pyproject.toml * Add support for GitHub release notes python-crc-7.1.0/docs/docs/changelog/changes_4.2.0.md000066400000000000000000000004551471247750100221030ustar00rootroot00000000000000# 4.2.0 - 2023-04-16 ## ✨ Features * Add support for MODBUS ## πŸ“š Documentation * Add copy button support for code snippets ## πŸ”© Internal * Fix path to changelog file for GitHub release * Add python 3.11 to test matrix * Add pre-commit support * Update dev dependencies * Fix mypy warnings python-crc-7.1.0/docs/docs/changelog/changes_4.3.0.md000066400000000000000000000001541471247750100221000ustar00rootroot00000000000000# 4.3.0 - 2023-06-25 ## πŸ“š Documentation * Fix typo in license file ## πŸ”© Internal * Update lockfile python-crc-7.1.0/docs/docs/changelog/changes_5.0.0.md000066400000000000000000000047221471247750100221030ustar00rootroot00000000000000# 5.0.0 - 2023-10-08 πŸš€ This release is powered by **Gert van Dijk**, thank you for your contribution! ## 🚨 Breaking Changes * Move from a single-file/module to an β€˜src-based layout’ package. The layout of the source repository has changed from single file `crc.py` in the root into a package where `crc.py` is now a private module `_crc.py` of package `crc`. ``` src/ └── crc/ β”œβ”€β”€ _crc.py └── __init__.py ``` `__init__.py` re-exports all the public entities from the private module, so that typical imports like `from crc import Calculator` remain working as-is. The need and choice for this new layout is discussed in [Issue #110][issue-110]. * The shebang line on the main `src/crc/_crc.py` file (formerly `crc.py`) has been removed. This shouldn't affect anyone installing `crc` as package. Both the entrypoint `crc` and the package-level `__main__` remain in place. However, in case you were to obtain the `src/crc/_crc.py` file (formerly `crc.py`) and mark it as executable afterwards to run it directly, then this change may affect you. Running the `main()` function can then still be achieved by either: - `python path/to/crc.py` - `python -m crc` (if the module is on your `PYTHON_PATH`) ## ✨ Added * Add `py.typed` marker to indicate the `crc` package ships with type information. The type information was added inline since [2.0.0](changes_2.0.0.md), but the marker file was missing in the package, so type checkers did not consider the type information. This eliminates the use of `ignore_missing_imports` (mypy) or `reportMissingTypeStubs` (Pylance/Pyright) in downstream projects. ## πŸ“š Documentation * Add contributors page ## πŸ”© Internal / Development * Several improvements to type annotations: * Conform to mypy in strict mode. * Type information now follows a more modern syntax by implementing recommendations from PEPs [563][PEP 563], [585][PEP 585], [604][PEP 604] while maintaining support for Python 3.8. * Declare all instance variables on classes. * Create a Type Alias for a complex Union used repetitively. * Remove unnecessary parentheses and `start` argument in `range()`. * Remove unused imports. * Update lockfile. [issue-110]: https://github.com/Nicoretti/crc/issues/110 [PEP 563]: https://peps.python.org/pep-0563/ [PEP 585]: https://peps.python.org/pep-0585/ [PEP 604]: https://peps.python.org/pep-0604/ python-crc-7.1.0/docs/docs/changelog/changes_6.0.0.md000066400000000000000000000007041471247750100221000ustar00rootroot00000000000000# 6.0.0 - 2023-12-02 ## 🚨️ Breaking Changes * Remove Python 3.7 support * Changed SAE1850J configuration (see Bug fixes) ## 🐞 Bug Fix * Adjusted the SAE-J1850 configuration to match the specification 🚨️ For users which do rely on the previously misconfigured `SAEJ1850` settings a configuration named `SAEJ1850_ZERO` was added. ## πŸ”© Internal / Development * Add `python 3.12` to test matrix * Re-lock dev dependencies python-crc-7.1.0/docs/docs/changelog/changes_6.1.0.md000066400000000000000000000003741471247750100221040ustar00rootroot00000000000000# 6.1.0 - 2023-12-30 πŸš€ This release is powered by **Riccardo Malavolti**, thank you for your contribution! ## ✨ Features * Add support for IBM-3740 (also known as CCITT-FALSE) ## πŸ”© Internal * Update GitHub Action(s) * Re-lock dependencies python-crc-7.1.0/docs/docs/changelog/changes_6.1.1.md000066400000000000000000000002751471247750100221050ustar00rootroot00000000000000# 6.1.1 - 2024-02-10 πŸš€ This release is powered by **Ramya-Ab**, thank you for your contribution! ## πŸ“š Documentation * Fix typos in README ## πŸ”© Internal * Re-lock dependencies python-crc-7.1.0/docs/docs/changelog/changes_6.1.2.md000066400000000000000000000010461471247750100221030ustar00rootroot00000000000000# 6.1.2 - 2024-04-14 ## 🐞 Bug Fixes * Fixed unstable return values of `digest` function. For more details, see issue [#151](https://github.com/Nicoretti/crc/issues/151). !!! bug This issue specifically affected scenarios where the CRC register was manually manipulated. Standard usages of the `Calculator` class were not impacted. Furthermore, this issue primarily occurred in configurations that required reverse output. ## πŸ“š Documentation * Add overview of crc configurations ## πŸ”© Internal * Re-lock dependencies python-crc-7.1.0/docs/docs/changelog/changes_7.0.0.md000066400000000000000000000025501471247750100221020ustar00rootroot00000000000000# 7.0.0 - 2024-04-19 ## 🚨 Breaking Changes ### Update of crc configurations - **Rename:** The `Crc16.CCITT` configuration to `Crc16.XMODEM`. - **New Addition:** Introduced `Crc16.KERMIT`, which matches the official configuration for `Crc16.CCITT`. #### Decision Rationale It was intentionally decided not to reintroduce `Crc16.CCITT` with the updated configuration. While it could have been added as an alias for `Crc16.KERMIT` or a replacement, omitting `Crc16.CCITT` ensures that client code will break upon update, thereby forcing maintainers to take notice and react accordingly. #### Migration Guide Below are solutions to the two common scenarios that need to be addressed due to this change: 1. **If you previously used `Crc16.CCITT` and expected the configuration defined [here](https://reveng.sourceforge.io/crc-catalogue/all.htm#crc.cat.crc-16-kermit):** **Solution:** Replace all usages of `Crc16.CCITT` in your code with `Crc16.KERMIT`. 2. **If you depended on or wanted to use the configuration values that `Crc16.CCITT` provided so far:** **Solution:** Replace all usages of `Crc16.CCITT` in your code with `Crc16.XMODEM`. #### Related Issues - [#148](https://github.com/Nicoretti/crc/issues/148) - [#145](https://github.com/Nicoretti/crc/issues/145) ## πŸ”© Internal * Update `python-environment` action * Add classifiers to `pyproject.toml` python-crc-7.1.0/docs/docs/changelog/changes_7.1.0.md000066400000000000000000000005461471247750100221060ustar00rootroot00000000000000# 7.1.0 - 2024-11-05 πŸš€ This release is powered by **Allen-saltedfish**, thank you for your contribution! ## ✨ Features * Add support for the following Crc8 configurations: - ITU - ROHC * Add support for the following Crc16 configurations: - IBM - MAXIM - USB - X25 (X-25) - DNP ## πŸ”© Internal * Re-lock dependencies python-crc-7.1.0/docs/docs/changelog/unreleased.md000066400000000000000000000000161471247750100220720ustar00rootroot00000000000000# Unreleased python-crc-7.1.0/docs/docs/cli.md000066400000000000000000000007341471247750100165720ustar00rootroot00000000000000# CLI Tools The crc library comes with a small command line tool which can generate crc lookup tables if needed. ```console usage: crc table [-h] positional arguments: width of the crc algorithm, common width's are 8, 16, 32, 64 hex value of the polynomial used for calculating the crc table optional arguments: -h, --help show this help message and exit ``` Example Usage: ``` user@host ~$ crc table 8 0x7D ``` python-crc-7.1.0/docs/docs/contributors.md000066400000000000000000000002571471247750100205600ustar00rootroot00000000000000# Contributors Thank you to all contributors for your help in improving this project. πŸš€ * Gert van Dijk * Riccardo Malavolti * Ramya-Ab * Allen-saltedfish * Dependabot python-crc-7.1.0/docs/docs/development/000077500000000000000000000000001471247750100200175ustar00rootroot00000000000000python-crc-7.1.0/docs/docs/development/release.md000066400000000000000000000010241471247750100217560ustar00rootroot00000000000000# Release ## Create a release using the GitHub release workflow 1. Rename `unreleased.md` to `changes_{X.Y.Z}.md` 2. Update heading in `changes_{X.Y.Z}.md` to reflect the release version 3. Add the current date behind the release number ```markdown # X.Y.Z - YYYY-MM-DD ``` 4. Prepare the release ```console invoke release.prepare X.Y.Z ``` 5. Run the CI/CD pipeline to publish the release: Execute the `release.workflow` task and follow potential instructions. ``` invoke release.workflow X.Y.Z ``` python-crc-7.1.0/docs/docs/development/setup.md000066400000000000000000000020301471247750100214740ustar00rootroot00000000000000# Setup ## Requirements TL;DR * [poetry](https://python-poetry.org) * [gh](https://cli.github.com) ## 1. Install Poetry Follow the poetry [installation instructions](https://python-poetry.org/docs/#installation). ## 2. Install gh Follow the gh [installation instructions](https://cli.github.com). ## 3. Checkout the project === "GitHub CLI" ``` gh repo clone Nicoretti/crc ``` === "SSH" ``` git clone git@github.com:Nicoretti/crc.git ``` === "HTTPS" ``` git clone https://github.com/Nicoretti/crc.git ``` ## 4. Switch into the directory ``` cd crc ``` ## 5. The Poetry environment Make sure the poetry environment is setup properly and all dependencies are installed. 1. Activate the Poetry shell ``` poetry shell ``` 2. Install the project dependencies ``` poetry install ``` ## Run the `init` task In order to bootstrap the remaining parts of the workspace setup, just execute the following command: ``` invoke init ``` !!! note Follow potential instructions. python-crc-7.1.0/docs/docs/index.md000066400000000000000000000146121471247750100171320ustar00rootroot00000000000000

CRC

Calculate CRC checksums, verify CRC checksum, predefined CRC configurations, custom CRC configurations

Checks Master Coverage License Downloads Supported Python Versions PyPi Package

--- * :books: Documentation: [https://nicoretti.github.io/crc](https://nicoretti.github.io/crc) * :simple-git: Source Code: [https://github.com/Nicoretti/crc](https://github.com/Nicoretti/crc) --- ## Available CRC Configurations The library includes a variety of common CRC configurations for convenience. To explore the full range of available CRC configurations, please checkout the [configurations](configurations.md) section of the documentation. If you need a new configuration to be readily available, consider submitting a [PR](https://github.com/Nicoretti/crc/pulls) or raising an [issue](https://github.com/Nicoretti/crc/issues). ## Custom Configurations If you want to create a custom configuration, you should have the following information available: * **width** * **polynom** * **init value** * **final xor value** * **reversed input** * **reversed output** In case you only have a name of a specific crc configuration/algorithm and you are unsure what are the specific parameters of it, a look into this [:material-note-search: crc-catalogue](http://reveng.sourceforge.net/crc-catalogue/all.htm) might help. ??? note This library currently only supports bit widths of full bytes 8, 16, 24, 32, ... ## Requirements * [\>= :material-language-python: Python 3.8](https://www.python.org) ## Installation ```shell pip install crc ``` ## Examples ### Create a Calculator === "Pre defined configuration" ```python from crc import Calculator, Crc8 calculator = Calculator(Crc8.CCITT) ``` === "Custom configuration" ```python from crc import Calculator, Configuration config = Configuration( width=8, poly=0x07, init_value=0x00, final_xor_value=0x00, reverse_input=False, reverse_output=False, ) calculator = Calculator(config) ``` ### Calculate a checksum === "Standard" ```python from crc import Calculator, Crc8 expected = 0xBC data = bytes([0, 1, 2, 3, 4, 5]) calculator = Calculator(Crc8.CCITT) assert expected == calculator.checksum(data) ``` === "Optimized for speed" ```python hl_lines="5" from crc import Calculator, Crc8 expected = 0xBC data = bytes([0, 1, 2, 3, 4, 5]) calculator = Calculator(Crc8.CCITT, optimized=True) assert expected == calculator.checksum(data) ``` ### Verify a checksum === "Standard" ```python from crc import Calculator, Crc8 expected = 0xBC data = bytes([0, 1, 2, 3, 4, 5]) calculator = Calculator(Crc8.CCITT) assert calculator.verify(data, expected) ``` === "Optimized for speed" ```python hl_lines="5" from crc import Calculator, Crc8 expected = 0xBC data = bytes([0, 1, 2, 3, 4, 5]) calculator = Calculator(Crc8.CCITT, optimized=True) assert calculator.verify(data, expected) ``` ### Supported data types === "int" ```python from crc import Calculator, Crc8 expected = 0x20 data = 97 calculator = Calculator(Crc8.CCITT, optimized=True) assert calculator.checksum(data) == expected ``` === "bytes" ```python from crc import Calculator, Crc8 expected = 0xF4 data = b"123456789" calculator = Calculator(Crc8.CCITT, optimized=True) assert calculator.checksum(data) == expected ``` === "bytearray" ```python from crc import Calculator, Crc8 expected = 0xF4 data = bytearray(b"123456789") calculator = Calculator(Crc8.CCITT, optimized=True) assert calculator.checksum(data) == expected ``` === "File" ```python from crc import Calculator, Crc8 expected = 0xF4 calculator = Calculator(Crc8.CCITT, optimized=True) with open("afile.txt", "rb") as f: assert calculator.checksum(f) == expected ``` === "ByteIo" ```python import io from crc import Calculator, Crc8 expected = 0xF4 data = io.ByteIo(b"123456789") calculator = Calculator(Crc8.CCITT, optimized=True) assert calculator.checksum(data) == expected ``` === "Iterable of bytes" ```python from crc import Calculator, Crc8 expected = 0xF4 calculator = Calculator(Crc8.CCITT, optimized=True) data = (data for data in [b"12", b"34", b"56", b"78", b"9"]) assert calculator.checksum(data) == expected ``` === "Byte convertibles" ```python from crc import Calculator, Crc8 class ByteConvertible: def __init__(self, data): self._data = data def __bytes__(self): return self._data.encode("utf-8") expected = 0xF4 calculator = Calculator(Crc8.CCITT, optimized=True) data = ByteConvertible("123456789") assert calculator.checksum(bytes(data)) == expected ``` ### Calculate a checksum with raw registers === "Register" ```python from crc import Crc8, Register expected = 0xBC data = bytes([0, 1, 2, 3, 4, 5]) register = Register(Crc8.CCITT) register.init() register.update(data) assert expected == register.digest() ``` === "TableBasedRegister" ```python from crc import Crc8, TableBasedRegister expected = 0xBC data = bytes([0, 1, 2, 3, 4, 5]) register = TableBasedRegister(Crc8.CCITT) register.init() register.update(data) assert expected == register.digest() ``` References & Resources ----------------------- * [A Painless guide to crc error detection algorithms](http://www.zlib.net/crc_v3.txt) * [CRC-Catalogue](http://reveng.sourceforge.net/crc-catalogue/all.htm) python-crc-7.1.0/docs/mkdocs.yml000066400000000000000000000046671471247750100165650ustar00rootroot00000000000000site_name: CRC site_url: https://nicoretti.github.io/crc/ repo_name: nicoretti/crc repo_url: https://github.com/Nicoretti/crc nav: - "index.md" # Configurations will be gernerated on the fly, # for more details see docs/scripts/configurations.py - "configurations.md" - API: - "api/calculator.md" - "api/configuration.md" - "api/crc8.md" - "api/crc16.md" - "api/crc32.md" - "api/crc64.md" - "api/abstract_register.md" - "api/basic_register.md" - "api/register.md" - "api/table_based_register.md" - "cli.md" - Development: - "development/setup.md" - "development/release.md" - Changelog: - "changelog/unreleased.md" - "changelog/changes_7.1.0.md" - "changelog/changes_7.0.0.md" - "changelog/changes_6.1.2.md" - "changelog/changes_6.1.1.md" - "changelog/changes_6.1.0.md" - "changelog/changes_6.0.0.md" - "changelog/changes_5.0.0.md" - "changelog/changes_4.3.0.md" - "changelog/changes_4.2.0.md" - "changelog/changes_4.1.0.md" - "changelog/changes_4.0.0.md" - "changelog/changes_3.0.1.md" - "changelog/changes_3.0.0.md" - "changelog/changes_2.0.0.md" - "contributors.md" theme: name: material icon: repo: fontawesome/brands/github palette: - media: '(prefers-color-scheme: light)' scheme: default primary: lime accent: amber toggle: icon: material/toggle-switch name: Switch to light mode - media: '(prefers-color-scheme: dark)' scheme: slate primary: lime accent: amber toggle: icon: material/toggle-switch-off-outline name: Switch to dark mode features: - search.suggest - search.highlight - content.tabs.link - content.code.copy font: false copyright: > Copyright © 2022 Nicola Coretti markdown_extensions: - admonition - pymdownx.details - pymdownx.highlight: use_pygments: true - pymdownx.superfences - attr_list - pymdownx.emoji: emoji_index: !!python/name:material.extensions.emoji.twemoji emoji_generator: !!python/name:material.extensions.emoji.to_svg - pymdownx.tabbed: alternate_style: true watch: - . - "../src" plugins: - search - gen-files: scripts: - "scripts/configurations.py" - autorefs - mkdocstrings: default_handler: python handlers: python: paths: ["../src"] options: show_source: false python-crc-7.1.0/docs/scripts/000077500000000000000000000000001471247750100162345ustar00rootroot00000000000000python-crc-7.1.0/docs/scripts/configurations.py000066400000000000000000000027711471247750100216470ustar00rootroot00000000000000from inspect import cleandoc from io import StringIO import mkdocs_gen_files from crc import ( Crc8, Crc16, Crc32, Crc64, ) _TAB_META_TEMPLATE = cleandoc( """ === "{{name}}"
- *Width:* **{{width}}** - *Final Xor:* **0x{{final_xor:0{length}X}}** - *Init Value:* **0x{{init_value:0{length}X}}** - *Rev Input:* **{{reverse_input}}** - *Polynomial:* **0x{{polynomial:0{length}X}}** - *Rev Output:* **{{reverse_output}}**
""" ) def as_content_tabs(config_group): output = StringIO() print(f"## {config_group.__name__} ", file=output) group2length = {Crc8: 2, Crc16: 4, Crc32: 8, Crc64: 16} for cfg in config_group: length = group2length[type(cfg)] tab_template = _TAB_META_TEMPLATE.format(length=length) row = tab_template.format( name=cfg.name, width=cfg.value.width, polynomial=cfg.value.polynomial, init_value=cfg.value.init_value, final_xor=cfg.value.final_xor_value, reverse_input=cfg.value.reverse_input, reverse_output=cfg.value.reverse_output, ) print(row, file=output) return output.getvalue() def main(): filename = "configurations.md" with mkdocs_gen_files.open(filename, "w") as f: config_groups = (Crc8, Crc16, Crc32, Crc64) for group in config_groups: t = as_content_tabs(config_group=group) print(t, file=f) main() python-crc-7.1.0/poetry.lock000066400000000000000000003417151471247750100160240ustar00rootroot00000000000000# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand. [[package]] name = "astroid" version = "3.2.4" description = "An abstract syntax tree for Python with inference support." optional = false python-versions = ">=3.8.0" files = [ {file = "astroid-3.2.4-py3-none-any.whl", hash = "sha256:413658a61eeca6202a59231abb473f932038fbcbf1666587f66d482083413a25"}, {file = "astroid-3.2.4.tar.gz", hash = "sha256:0e14202810b30da1b735827f78f5157be2bbd4a7a59b7707ca0bfc2fb4c0063a"}, ] [package.dependencies] typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.11\""} [[package]] name = "astunparse" version = "1.6.3" description = "An AST unparser for Python" optional = false python-versions = "*" files = [ {file = "astunparse-1.6.3-py2.py3-none-any.whl", hash = "sha256:c2652417f2c8b5bb325c885ae329bdf3f86424075c4fd1a128674bc6fba4b8e8"}, {file = "astunparse-1.6.3.tar.gz", hash = "sha256:5ad93a8456f0d084c3456d059fd9a92cce667963232cbf763eac3bc5b7940872"}, ] [package.dependencies] six = ">=1.6.1,<2.0" wheel = ">=0.23.0,<1.0" [[package]] name = "autoflake" version = "2.3.1" description = "Removes unused imports and unused variables" optional = false python-versions = ">=3.8" files = [ {file = "autoflake-2.3.1-py3-none-any.whl", hash = "sha256:3ae7495db9084b7b32818b4140e6dc4fc280b712fb414f5b8fe57b0a8e85a840"}, {file = "autoflake-2.3.1.tar.gz", hash = "sha256:c98b75dc5b0a86459c4f01a1d32ac7eb4338ec4317a4469515ff1e687ecd909e"}, ] [package.dependencies] pyflakes = ">=3.0.0" tomli = {version = ">=2.0.1", markers = "python_version < \"3.11\""} [[package]] name = "babel" version = "2.16.0" description = "Internationalization utilities" optional = false python-versions = ">=3.8" files = [ {file = "babel-2.16.0-py3-none-any.whl", hash = "sha256:368b5b98b37c06b7daf6696391c3240c938b37767d4584413e8438c5c435fa8b"}, {file = "babel-2.16.0.tar.gz", hash = "sha256:d1f3554ca26605fe173f3de0c65f750f5a42f924499bf134de6423582298e316"}, ] [package.dependencies] pytz = {version = ">=2015.7", markers = "python_version < \"3.9\""} [package.extras] dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"] [[package]] name = "black" version = "24.8.0" description = "The uncompromising code formatter." optional = false python-versions = ">=3.8" files = [ {file = "black-24.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:09cdeb74d494ec023ded657f7092ba518e8cf78fa8386155e4a03fdcc44679e6"}, {file = "black-24.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:81c6742da39f33b08e791da38410f32e27d632260e599df7245cccee2064afeb"}, {file = "black-24.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:707a1ca89221bc8a1a64fb5e15ef39cd755633daa672a9db7498d1c19de66a42"}, {file = "black-24.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:d6417535d99c37cee4091a2f24eb2b6d5ec42b144d50f1f2e436d9fe1916fe1a"}, {file = "black-24.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:fb6e2c0b86bbd43dee042e48059c9ad7830abd5c94b0bc518c0eeec57c3eddc1"}, {file = "black-24.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:837fd281f1908d0076844bc2b801ad2d369c78c45cf800cad7b61686051041af"}, {file = "black-24.8.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:62e8730977f0b77998029da7971fa896ceefa2c4c4933fcd593fa599ecbf97a4"}, {file = "black-24.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:72901b4913cbac8972ad911dc4098d5753704d1f3c56e44ae8dce99eecb0e3af"}, {file = "black-24.8.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:7c046c1d1eeb7aea9335da62472481d3bbf3fd986e093cffd35f4385c94ae368"}, {file = "black-24.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:649f6d84ccbae73ab767e206772cc2d7a393a001070a4c814a546afd0d423aed"}, {file = "black-24.8.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2b59b250fdba5f9a9cd9d0ece6e6d993d91ce877d121d161e4698af3eb9c1018"}, {file = "black-24.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:6e55d30d44bed36593c3163b9bc63bf58b3b30e4611e4d88a0c3c239930ed5b2"}, {file = "black-24.8.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:505289f17ceda596658ae81b61ebbe2d9b25aa78067035184ed0a9d855d18afd"}, {file = "black-24.8.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b19c9ad992c7883ad84c9b22aaa73562a16b819c1d8db7a1a1a49fb7ec13c7d2"}, {file = "black-24.8.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1f13f7f386f86f8121d76599114bb8c17b69d962137fc70efe56137727c7047e"}, {file = "black-24.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:f490dbd59680d809ca31efdae20e634f3fae27fba3ce0ba3208333b713bc3920"}, {file = "black-24.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:eab4dd44ce80dea27dc69db40dab62d4ca96112f87996bca68cd75639aeb2e4c"}, {file = "black-24.8.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3c4285573d4897a7610054af5a890bde7c65cb466040c5f0c8b732812d7f0e5e"}, {file = "black-24.8.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9e84e33b37be070ba135176c123ae52a51f82306def9f7d063ee302ecab2cf47"}, {file = "black-24.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:73bbf84ed136e45d451a260c6b73ed674652f90a2b3211d6a35e78054563a9bb"}, {file = "black-24.8.0-py3-none-any.whl", hash = "sha256:972085c618ee94f402da1af548a4f218c754ea7e5dc70acb168bfaca4c2542ed"}, {file = "black-24.8.0.tar.gz", hash = "sha256:2500945420b6784c38b9ee885af039f5e7471ef284ab03fa35ecdde4688cd83f"}, ] [package.dependencies] click = ">=8.0.0" mypy-extensions = ">=0.4.3" packaging = ">=22.0" pathspec = ">=0.9.0" platformdirs = ">=2" tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} typing-extensions = {version = ">=4.0.1", markers = "python_version < \"3.11\""} [package.extras] colorama = ["colorama (>=0.4.3)"] d = ["aiohttp (>=3.7.4)", "aiohttp (>=3.7.4,!=3.9.0)"] jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] uvloop = ["uvloop (>=0.15.2)"] [[package]] name = "certifi" version = "2024.8.30" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" files = [ {file = "certifi-2024.8.30-py3-none-any.whl", hash = "sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8"}, {file = "certifi-2024.8.30.tar.gz", hash = "sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9"}, ] [[package]] name = "cfgv" version = "3.4.0" description = "Validate configuration and produce human readable error messages." optional = false python-versions = ">=3.8" files = [ {file = "cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9"}, {file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"}, ] [[package]] name = "charset-normalizer" version = "3.4.0" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." optional = false python-versions = ">=3.7.0" files = [ {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:4f9fc98dad6c2eaa32fc3af1417d95b5e3d08aff968df0cd320066def971f9a6"}, {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0de7b687289d3c1b3e8660d0741874abe7888100efe14bd0f9fd7141bcbda92b"}, {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5ed2e36c3e9b4f21dd9422f6893dec0abf2cca553af509b10cd630f878d3eb99"}, {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40d3ff7fc90b98c637bda91c89d51264a3dcf210cade3a2c6f838c7268d7a4ca"}, {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1110e22af8ca26b90bd6364fe4c763329b0ebf1ee213ba32b68c73de5752323d"}, {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:86f4e8cca779080f66ff4f191a685ced73d2f72d50216f7112185dc02b90b9b7"}, {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f683ddc7eedd742e2889d2bfb96d69573fde1d92fcb811979cdb7165bb9c7d3"}, {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:27623ba66c183eca01bf9ff833875b459cad267aeeb044477fedac35e19ba907"}, {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f606a1881d2663630ea5b8ce2efe2111740df4b687bd78b34a8131baa007f79b"}, {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:0b309d1747110feb25d7ed6b01afdec269c647d382c857ef4663bbe6ad95a912"}, {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:136815f06a3ae311fae551c3df1f998a1ebd01ddd424aa5603a4336997629e95"}, {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:14215b71a762336254351b00ec720a8e85cada43b987da5a042e4ce3e82bd68e"}, {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:79983512b108e4a164b9c8d34de3992f76d48cadc9554c9e60b43f308988aabe"}, {file = "charset_normalizer-3.4.0-cp310-cp310-win32.whl", hash = "sha256:c94057af19bc953643a33581844649a7fdab902624d2eb739738a30e2b3e60fc"}, {file = "charset_normalizer-3.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:55f56e2ebd4e3bc50442fbc0888c9d8c94e4e06a933804e2af3e89e2f9c1c749"}, {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0d99dd8ff461990f12d6e42c7347fd9ab2532fb70e9621ba520f9e8637161d7c"}, {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c57516e58fd17d03ebe67e181a4e4e2ccab1168f8c2976c6a334d4f819fe5944"}, {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6dba5d19c4dfab08e58d5b36304b3f92f3bd5d42c1a3fa37b5ba5cdf6dfcbcee"}, {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf4475b82be41b07cc5e5ff94810e6a01f276e37c2d55571e3fe175e467a1a1c"}, {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce031db0408e487fd2775d745ce30a7cd2923667cf3b69d48d219f1d8f5ddeb6"}, {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ff4e7cdfdb1ab5698e675ca622e72d58a6fa2a8aa58195de0c0061288e6e3ea"}, {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3710a9751938947e6327ea9f3ea6332a09bf0ba0c09cae9cb1f250bd1f1549bc"}, {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82357d85de703176b5587dbe6ade8ff67f9f69a41c0733cf2425378b49954de5"}, {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:47334db71978b23ebcf3c0f9f5ee98b8d65992b65c9c4f2d34c2eaf5bcaf0594"}, {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8ce7fd6767a1cc5a92a639b391891bf1c268b03ec7e021c7d6d902285259685c"}, {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f1a2f519ae173b5b6a2c9d5fa3116ce16e48b3462c8b96dfdded11055e3d6365"}, {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:63bc5c4ae26e4bc6be6469943b8253c0fd4e4186c43ad46e713ea61a0ba49129"}, {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bcb4f8ea87d03bc51ad04add8ceaf9b0f085ac045ab4d74e73bbc2dc033f0236"}, {file = "charset_normalizer-3.4.0-cp311-cp311-win32.whl", hash = "sha256:9ae4ef0b3f6b41bad6366fb0ea4fc1d7ed051528e113a60fa2a65a9abb5b1d99"}, {file = "charset_normalizer-3.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:cee4373f4d3ad28f1ab6290684d8e2ebdb9e7a1b74fdc39e4c211995f77bec27"}, {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0713f3adb9d03d49d365b70b84775d0a0d18e4ab08d12bc46baa6132ba78aaf6"}, {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:de7376c29d95d6719048c194a9cf1a1b0393fbe8488a22008610b0361d834ecf"}, {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4a51b48f42d9358460b78725283f04bddaf44a9358197b889657deba38f329db"}, {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b295729485b06c1a0683af02a9e42d2caa9db04a373dc38a6a58cdd1e8abddf1"}, {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ee803480535c44e7f5ad00788526da7d85525cfefaf8acf8ab9a310000be4b03"}, {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d59d125ffbd6d552765510e3f31ed75ebac2c7470c7274195b9161a32350284"}, {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8cda06946eac330cbe6598f77bb54e690b4ca93f593dee1568ad22b04f347c15"}, {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07afec21bbbbf8a5cc3651aa96b980afe2526e7f048fdfb7f1014d84acc8b6d8"}, {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6b40e8d38afe634559e398cc32b1472f376a4099c75fe6299ae607e404c033b2"}, {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b8dcd239c743aa2f9c22ce674a145e0a25cb1566c495928440a181ca1ccf6719"}, {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:84450ba661fb96e9fd67629b93d2941c871ca86fc38d835d19d4225ff946a631"}, {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:44aeb140295a2f0659e113b31cfe92c9061622cadbc9e2a2f7b8ef6b1e29ef4b"}, {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1db4e7fefefd0f548d73e2e2e041f9df5c59e178b4c72fbac4cc6f535cfb1565"}, {file = "charset_normalizer-3.4.0-cp312-cp312-win32.whl", hash = "sha256:5726cf76c982532c1863fb64d8c6dd0e4c90b6ece9feb06c9f202417a31f7dd7"}, {file = "charset_normalizer-3.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:b197e7094f232959f8f20541ead1d9862ac5ebea1d58e9849c1bf979255dfac9"}, {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:dd4eda173a9fcccb5f2e2bd2a9f423d180194b1bf17cf59e3269899235b2a114"}, {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e9e3c4c9e1ed40ea53acf11e2a386383c3304212c965773704e4603d589343ed"}, {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:92a7e36b000bf022ef3dbb9c46bfe2d52c047d5e3f3343f43204263c5addc250"}, {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54b6a92d009cbe2fb11054ba694bc9e284dad30a26757b1e372a1fdddaf21920"}, {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ffd9493de4c922f2a38c2bf62b831dcec90ac673ed1ca182fe11b4d8e9f2a64"}, {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:35c404d74c2926d0287fbd63ed5d27eb911eb9e4a3bb2c6d294f3cfd4a9e0c23"}, {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4796efc4faf6b53a18e3d46343535caed491776a22af773f366534056c4e1fbc"}, {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e7fdd52961feb4c96507aa649550ec2a0d527c086d284749b2f582f2d40a2e0d"}, {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:92db3c28b5b2a273346bebb24857fda45601aef6ae1c011c0a997106581e8a88"}, {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ab973df98fc99ab39080bfb0eb3a925181454d7c3ac8a1e695fddfae696d9e90"}, {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4b67fdab07fdd3c10bb21edab3cbfe8cf5696f453afce75d815d9d7223fbe88b"}, {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:aa41e526a5d4a9dfcfbab0716c7e8a1b215abd3f3df5a45cf18a12721d31cb5d"}, {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ffc519621dce0c767e96b9c53f09c5d215578e10b02c285809f76509a3931482"}, {file = "charset_normalizer-3.4.0-cp313-cp313-win32.whl", hash = "sha256:f19c1585933c82098c2a520f8ec1227f20e339e33aca8fa6f956f6691b784e67"}, {file = "charset_normalizer-3.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:707b82d19e65c9bd28b81dde95249b07bf9f5b90ebe1ef17d9b57473f8a64b7b"}, {file = "charset_normalizer-3.4.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:dbe03226baf438ac4fda9e2d0715022fd579cb641c4cf639fa40d53b2fe6f3e2"}, {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd9a8bd8900e65504a305bf8ae6fa9fbc66de94178c420791d0293702fce2df7"}, {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8831399554b92b72af5932cdbbd4ddc55c55f631bb13ff8fe4e6536a06c5c51"}, {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a14969b8691f7998e74663b77b4c36c0337cb1df552da83d5c9004a93afdb574"}, {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dcaf7c1524c0542ee2fc82cc8ec337f7a9f7edee2532421ab200d2b920fc97cf"}, {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:425c5f215d0eecee9a56cdb703203dda90423247421bf0d67125add85d0c4455"}, {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:d5b054862739d276e09928de37c79ddeec42a6e1bfc55863be96a36ba22926f6"}, {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:f3e73a4255342d4eb26ef6df01e3962e73aa29baa3124a8e824c5d3364a65748"}, {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:2f6c34da58ea9c1a9515621f4d9ac379871a8f21168ba1b5e09d74250de5ad62"}, {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:f09cb5a7bbe1ecae6e87901a2eb23e0256bb524a79ccc53eb0b7629fbe7677c4"}, {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:0099d79bdfcf5c1f0c2c72f91516702ebf8b0b8ddd8905f97a8aecf49712c621"}, {file = "charset_normalizer-3.4.0-cp37-cp37m-win32.whl", hash = "sha256:9c98230f5042f4945f957d006edccc2af1e03ed5e37ce7c373f00a5a4daa6149"}, {file = "charset_normalizer-3.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:62f60aebecfc7f4b82e3f639a7d1433a20ec32824db2199a11ad4f5e146ef5ee"}, {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:af73657b7a68211996527dbfeffbb0864e043d270580c5aef06dc4b659a4b578"}, {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cab5d0b79d987c67f3b9e9c53f54a61360422a5a0bc075f43cab5621d530c3b6"}, {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9289fd5dddcf57bab41d044f1756550f9e7cf0c8e373b8cdf0ce8773dc4bd417"}, {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b493a043635eb376e50eedf7818f2f322eabbaa974e948bd8bdd29eb7ef2a51"}, {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fa2566ca27d67c86569e8c85297aaf413ffab85a8960500f12ea34ff98e4c41"}, {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8e538f46104c815be19c975572d74afb53f29650ea2025bbfaef359d2de2f7f"}, {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fd30dc99682dc2c603c2b315bded2799019cea829f8bf57dc6b61efde6611c8"}, {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2006769bd1640bdf4d5641c69a3d63b71b81445473cac5ded39740a226fa88ab"}, {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:dc15e99b2d8a656f8e666854404f1ba54765871104e50c8e9813af8a7db07f12"}, {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:ab2e5bef076f5a235c3774b4f4028a680432cded7cad37bba0fd90d64b187d19"}, {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:4ec9dd88a5b71abfc74e9df5ebe7921c35cbb3b641181a531ca65cdb5e8e4dea"}, {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:43193c5cda5d612f247172016c4bb71251c784d7a4d9314677186a838ad34858"}, {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:aa693779a8b50cd97570e5a0f343538a8dbd3e496fa5dcb87e29406ad0299654"}, {file = "charset_normalizer-3.4.0-cp38-cp38-win32.whl", hash = "sha256:7706f5850360ac01d80c89bcef1640683cc12ed87f42579dab6c5d3ed6888613"}, {file = "charset_normalizer-3.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:c3e446d253bd88f6377260d07c895816ebf33ffffd56c1c792b13bff9c3e1ade"}, {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:980b4f289d1d90ca5efcf07958d3eb38ed9c0b7676bf2831a54d4f66f9c27dfa"}, {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f28f891ccd15c514a0981f3b9db9aa23d62fe1a99997512b0491d2ed323d229a"}, {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8aacce6e2e1edcb6ac625fb0f8c3a9570ccc7bfba1f63419b3769ccf6a00ed0"}, {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd7af3717683bea4c87acd8c0d3d5b44d56120b26fd3f8a692bdd2d5260c620a"}, {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5ff2ed8194587faf56555927b3aa10e6fb69d931e33953943bc4f837dfee2242"}, {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e91f541a85298cf35433bf66f3fab2a4a2cff05c127eeca4af174f6d497f0d4b"}, {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:309a7de0a0ff3040acaebb35ec45d18db4b28232f21998851cfa709eeff49d62"}, {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:285e96d9d53422efc0d7a17c60e59f37fbf3dfa942073f666db4ac71e8d726d0"}, {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:5d447056e2ca60382d460a604b6302d8db69476fd2015c81e7c35417cfabe4cd"}, {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:20587d20f557fe189b7947d8e7ec5afa110ccf72a3128d61a2a387c3313f46be"}, {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:130272c698667a982a5d0e626851ceff662565379baf0ff2cc58067b81d4f11d"}, {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:ab22fbd9765e6954bc0bcff24c25ff71dcbfdb185fcdaca49e81bac68fe724d3"}, {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7782afc9b6b42200f7362858f9e73b1f8316afb276d316336c0ec3bd73312742"}, {file = "charset_normalizer-3.4.0-cp39-cp39-win32.whl", hash = "sha256:2de62e8801ddfff069cd5c504ce3bc9672b23266597d4e4f50eda28846c322f2"}, {file = "charset_normalizer-3.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:95c3c157765b031331dd4db3c775e58deaee050a3042fcad72cbc4189d7c8dca"}, {file = "charset_normalizer-3.4.0-py3-none-any.whl", hash = "sha256:fe9f97feb71aa9896b81973a7bbada8c49501dc73e58a10fcef6663af95e5079"}, {file = "charset_normalizer-3.4.0.tar.gz", hash = "sha256:223217c3d4f82c3ac5e29032b3f1c2eb0fb591b72161f86d93f5719079dae93e"}, ] [[package]] name = "click" version = "8.1.7" description = "Composable command line interface toolkit" optional = false python-versions = ">=3.7" files = [ {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, ] [package.dependencies] colorama = {version = "*", markers = "platform_system == \"Windows\""} [[package]] name = "colorama" version = "0.4.6" description = "Cross-platform colored terminal text." optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" files = [ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] [[package]] name = "com2ann" version = "0.3.0" description = "Tool to translate type comments to annotations." optional = false python-versions = ">=3.8" files = [ {file = "com2ann-0.3.0-py3-none-any.whl", hash = "sha256:bb0994c7ea9e6f847c98b20d0cc056aa90c256937d3aede504026663d7f36bb6"}, {file = "com2ann-0.3.0.tar.gz", hash = "sha256:0da5e3900292057e5c4a5e33b21fe48817b4923437a095e6a677dff94b3d4e10"}, ] [[package]] name = "coverage" version = "6.5.0" description = "Code coverage measurement for Python" optional = false python-versions = ">=3.7" files = [ {file = "coverage-6.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ef8674b0ee8cc11e2d574e3e2998aea5df5ab242e012286824ea3c6970580e53"}, {file = "coverage-6.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:784f53ebc9f3fd0e2a3f6a78b2be1bd1f5575d7863e10c6e12504f240fd06660"}, {file = "coverage-6.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b4a5be1748d538a710f87542f22c2cad22f80545a847ad91ce45e77417293eb4"}, {file = "coverage-6.5.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:83516205e254a0cb77d2d7bb3632ee019d93d9f4005de31dca0a8c3667d5bc04"}, {file = "coverage-6.5.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:af4fffaffc4067232253715065e30c5a7ec6faac36f8fc8d6f64263b15f74db0"}, {file = "coverage-6.5.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:97117225cdd992a9c2a5515db1f66b59db634f59d0679ca1fa3fe8da32749cae"}, {file = "coverage-6.5.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a1170fa54185845505fbfa672f1c1ab175446c887cce8212c44149581cf2d466"}, {file = "coverage-6.5.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:11b990d520ea75e7ee8dcab5bc908072aaada194a794db9f6d7d5cfd19661e5a"}, {file = "coverage-6.5.0-cp310-cp310-win32.whl", hash = "sha256:5dbec3b9095749390c09ab7c89d314727f18800060d8d24e87f01fb9cfb40b32"}, {file = "coverage-6.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:59f53f1dc5b656cafb1badd0feb428c1e7bc19b867479ff72f7a9dd9b479f10e"}, {file = "coverage-6.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4a5375e28c5191ac38cca59b38edd33ef4cc914732c916f2929029b4bfb50795"}, {file = "coverage-6.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4ed2820d919351f4167e52425e096af41bfabacb1857186c1ea32ff9983ed75"}, {file = "coverage-6.5.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:33a7da4376d5977fbf0a8ed91c4dffaaa8dbf0ddbf4c8eea500a2486d8bc4d7b"}, {file = "coverage-6.5.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8fb6cf131ac4070c9c5a3e21de0f7dc5a0fbe8bc77c9456ced896c12fcdad91"}, {file = "coverage-6.5.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a6b7d95969b8845250586f269e81e5dfdd8ff828ddeb8567a4a2eaa7313460c4"}, {file = "coverage-6.5.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:1ef221513e6f68b69ee9e159506d583d31aa3567e0ae84eaad9d6ec1107dddaa"}, {file = "coverage-6.5.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cca4435eebea7962a52bdb216dec27215d0df64cf27fc1dd538415f5d2b9da6b"}, {file = "coverage-6.5.0-cp311-cp311-win32.whl", hash = "sha256:98e8a10b7a314f454d9eff4216a9a94d143a7ee65018dd12442e898ee2310578"}, {file = "coverage-6.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:bc8ef5e043a2af066fa8cbfc6e708d58017024dc4345a1f9757b329a249f041b"}, {file = "coverage-6.5.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:4433b90fae13f86fafff0b326453dd42fc9a639a0d9e4eec4d366436d1a41b6d"}, {file = "coverage-6.5.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f4f05d88d9a80ad3cac6244d36dd89a3c00abc16371769f1340101d3cb899fc3"}, {file = "coverage-6.5.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:94e2565443291bd778421856bc975d351738963071e9b8839ca1fc08b42d4bef"}, {file = "coverage-6.5.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:027018943386e7b942fa832372ebc120155fd970837489896099f5cfa2890f79"}, {file = "coverage-6.5.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:255758a1e3b61db372ec2736c8e2a1fdfaf563977eedbdf131de003ca5779b7d"}, {file = "coverage-6.5.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:851cf4ff24062c6aec510a454b2584f6e998cada52d4cb58c5e233d07172e50c"}, {file = "coverage-6.5.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:12adf310e4aafddc58afdb04d686795f33f4d7a6fa67a7a9d4ce7d6ae24d949f"}, {file = "coverage-6.5.0-cp37-cp37m-win32.whl", hash = "sha256:b5604380f3415ba69de87a289a2b56687faa4fe04dbee0754bfcae433489316b"}, {file = "coverage-6.5.0-cp37-cp37m-win_amd64.whl", hash = "sha256:4a8dbc1f0fbb2ae3de73eb0bdbb914180c7abfbf258e90b311dcd4f585d44bd2"}, {file = "coverage-6.5.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d900bb429fdfd7f511f868cedd03a6bbb142f3f9118c09b99ef8dc9bf9643c3c"}, {file = "coverage-6.5.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2198ea6fc548de52adc826f62cb18554caedfb1d26548c1b7c88d8f7faa8f6ba"}, {file = "coverage-6.5.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c4459b3de97b75e3bd6b7d4b7f0db13f17f504f3d13e2a7c623786289dd670e"}, {file = "coverage-6.5.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:20c8ac5386253717e5ccc827caad43ed66fea0efe255727b1053a8154d952398"}, {file = "coverage-6.5.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b07130585d54fe8dff3d97b93b0e20290de974dc8177c320aeaf23459219c0b"}, {file = "coverage-6.5.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:dbdb91cd8c048c2b09eb17713b0c12a54fbd587d79adcebad543bc0cd9a3410b"}, {file = "coverage-6.5.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:de3001a203182842a4630e7b8d1a2c7c07ec1b45d3084a83d5d227a3806f530f"}, {file = "coverage-6.5.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e07f4a4a9b41583d6eabec04f8b68076ab3cd44c20bd29332c6572dda36f372e"}, {file = "coverage-6.5.0-cp38-cp38-win32.whl", hash = "sha256:6d4817234349a80dbf03640cec6109cd90cba068330703fa65ddf56b60223a6d"}, {file = "coverage-6.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:7ccf362abd726b0410bf8911c31fbf97f09f8f1061f8c1cf03dfc4b6372848f6"}, {file = "coverage-6.5.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:633713d70ad6bfc49b34ead4060531658dc6dfc9b3eb7d8a716d5873377ab745"}, {file = "coverage-6.5.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:95203854f974e07af96358c0b261f1048d8e1083f2de9b1c565e1be4a3a48cfc"}, {file = "coverage-6.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9023e237f4c02ff739581ef35969c3739445fb059b060ca51771e69101efffe"}, {file = "coverage-6.5.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:265de0fa6778d07de30bcf4d9dc471c3dc4314a23a3c6603d356a3c9abc2dfcf"}, {file = "coverage-6.5.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f830ed581b45b82451a40faabb89c84e1a998124ee4212d440e9c6cf70083e5"}, {file = "coverage-6.5.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7b6be138d61e458e18d8e6ddcddd36dd96215edfe5f1168de0b1b32635839b62"}, {file = "coverage-6.5.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:42eafe6778551cf006a7c43153af1211c3aaab658d4d66fa5fcc021613d02518"}, {file = "coverage-6.5.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:723e8130d4ecc8f56e9a611e73b31219595baa3bb252d539206f7bbbab6ffc1f"}, {file = "coverage-6.5.0-cp39-cp39-win32.whl", hash = "sha256:d9ecf0829c6a62b9b573c7bb6d4dcd6ba8b6f80be9ba4fc7ed50bf4ac9aecd72"}, {file = "coverage-6.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:fc2af30ed0d5ae0b1abdb4ebdce598eafd5b35397d4d75deb341a614d333d987"}, {file = "coverage-6.5.0-pp36.pp37.pp38-none-any.whl", hash = "sha256:1431986dac3923c5945271f169f59c45b8802a114c8f548d611f2015133df77a"}, {file = "coverage-6.5.0.tar.gz", hash = "sha256:f642e90754ee3e06b0e7e51bce3379590e76b7f76b708e1a71ff043f87025c84"}, ] [package.extras] toml = ["tomli"] [[package]] name = "coveralls" version = "3.3.1" description = "Show coverage stats online via coveralls.io" optional = false python-versions = ">= 3.5" files = [ {file = "coveralls-3.3.1-py2.py3-none-any.whl", hash = "sha256:f42015f31d386b351d4226389b387ae173207058832fbf5c8ec4b40e27b16026"}, {file = "coveralls-3.3.1.tar.gz", hash = "sha256:b32a8bb5d2df585207c119d6c01567b81fba690c9c10a753bfe27a335bfc43ea"}, ] [package.dependencies] coverage = ">=4.1,<6.0.dev0 || >6.1,<6.1.1 || >6.1.1,<7.0" docopt = ">=0.6.1" requests = ">=1.0.0" [package.extras] yaml = ["PyYAML (>=3.10)"] [[package]] name = "dill" version = "0.3.9" description = "serialize all of Python" optional = false python-versions = ">=3.8" files = [ {file = "dill-0.3.9-py3-none-any.whl", hash = "sha256:468dff3b89520b474c0397703366b7b95eebe6303f108adf9b19da1f702be87a"}, {file = "dill-0.3.9.tar.gz", hash = "sha256:81aa267dddf68cbfe8029c42ca9ec6a4ab3b22371d1c450abc54422577b4512c"}, ] [package.extras] graph = ["objgraph (>=1.7.2)"] profile = ["gprof2dot (>=2022.7.29)"] [[package]] name = "distlib" version = "0.3.9" description = "Distribution utilities" optional = false python-versions = "*" files = [ {file = "distlib-0.3.9-py2.py3-none-any.whl", hash = "sha256:47f8c22fd27c27e25a65601af709b38e4f0a45ea4fc2e710f65755fa8caaaf87"}, {file = "distlib-0.3.9.tar.gz", hash = "sha256:a60f20dea646b8a33f3e7772f74dc0b2d0772d2837ee1342a00645c81edf9403"}, ] [[package]] name = "docopt" version = "0.6.2" description = "Pythonic argument parser, that will make you smile" optional = false python-versions = "*" files = [ {file = "docopt-0.6.2.tar.gz", hash = "sha256:49b3a825280bd66b3aa83585ef59c4a8c82f2c8a522dbe754a8bc8d08c85c491"}, ] [[package]] name = "exceptiongroup" version = "1.2.2" description = "Backport of PEP 654 (exception groups)" optional = false python-versions = ">=3.7" files = [ {file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"}, {file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"}, ] [package.extras] test = ["pytest (>=6)"] [[package]] name = "filelock" version = "3.16.1" description = "A platform independent file lock." optional = false python-versions = ">=3.8" files = [ {file = "filelock-3.16.1-py3-none-any.whl", hash = "sha256:2082e5703d51fbf98ea75855d9d5527e33d8ff23099bec374a134febee6946b0"}, {file = "filelock-3.16.1.tar.gz", hash = "sha256:c249fbfcd5db47e5e2d6d62198e565475ee65e4831e2561c8e313fa7eb961435"}, ] [package.extras] docs = ["furo (>=2024.8.6)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4.1)"] testing = ["covdefaults (>=2.3)", "coverage (>=7.6.1)", "diff-cover (>=9.2)", "pytest (>=8.3.3)", "pytest-asyncio (>=0.24)", "pytest-cov (>=5)", "pytest-mock (>=3.14)", "pytest-timeout (>=2.3.1)", "virtualenv (>=20.26.4)"] typing = ["typing-extensions (>=4.12.2)"] [[package]] name = "ghp-import" version = "2.1.0" description = "Copy your docs directly to the gh-pages branch." optional = false python-versions = "*" files = [ {file = "ghp-import-2.1.0.tar.gz", hash = "sha256:9c535c4c61193c2df8871222567d7fd7e5014d835f97dc7b7439069e2413d343"}, {file = "ghp_import-2.1.0-py3-none-any.whl", hash = "sha256:8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619"}, ] [package.dependencies] python-dateutil = ">=2.8.1" [package.extras] dev = ["flake8", "markdown", "twine", "wheel"] [[package]] name = "griffe" version = "1.4.0" 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." optional = false python-versions = ">=3.8" files = [ {file = "griffe-1.4.0-py3-none-any.whl", hash = "sha256:e589de8b8c137e99a46ec45f9598fc0ac5b6868ce824b24db09c02d117b89bc5"}, {file = "griffe-1.4.0.tar.gz", hash = "sha256:8fccc585896d13f1221035d32c50dec65830c87d23f9adb9b1e6f3d63574f7f5"}, ] [package.dependencies] astunparse = {version = ">=1.6", markers = "python_version < \"3.9\""} colorama = ">=0.4" [[package]] name = "identify" version = "2.6.1" description = "File identification library for Python" optional = false python-versions = ">=3.8" files = [ {file = "identify-2.6.1-py2.py3-none-any.whl", hash = "sha256:53863bcac7caf8d2ed85bd20312ea5dcfc22226800f6d6881f232d861db5a8f0"}, {file = "identify-2.6.1.tar.gz", hash = "sha256:91478c5fb7c3aac5ff7bf9b4344f803843dc586832d5f110d672b19aa1984c98"}, ] [package.extras] license = ["ukkonen"] [[package]] name = "idna" version = "3.10" description = "Internationalized Domain Names in Applications (IDNA)" optional = false python-versions = ">=3.6" files = [ {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, ] [package.extras] all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] [[package]] name = "importlib-metadata" version = "8.5.0" description = "Read metadata from Python packages" optional = false python-versions = ">=3.8" files = [ {file = "importlib_metadata-8.5.0-py3-none-any.whl", hash = "sha256:45e54197d28b7a7f1559e60b95e7c567032b602131fbd588f1497f47880aa68b"}, {file = "importlib_metadata-8.5.0.tar.gz", hash = "sha256:71522656f0abace1d072b9e5481a48f07c138e00f079c38c8f883823f9c26bd7"}, ] [package.dependencies] zipp = ">=3.20" [package.extras] check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)"] cover = ["pytest-cov"] doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] enabler = ["pytest-enabler (>=2.2)"] perf = ["ipython"] test = ["flufl.flake8", "importlib-resources (>=1.3)", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-perf (>=0.9.2)"] type = ["pytest-mypy"] [[package]] name = "iniconfig" version = "2.0.0" description = "brain-dead simple config-ini parsing" optional = false python-versions = ">=3.7" files = [ {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, ] [[package]] name = "invoke" version = "2.2.0" description = "Pythonic task execution" optional = false python-versions = ">=3.6" files = [ {file = "invoke-2.2.0-py3-none-any.whl", hash = "sha256:6ea924cc53d4f78e3d98bc436b08069a03077e6f85ad1ddaa8a116d7dad15820"}, {file = "invoke-2.2.0.tar.gz", hash = "sha256:ee6cbb101af1a859c7fe84f2a264c059020b0cb7fe3535f9424300ab568f6bd5"}, ] [[package]] name = "isort" version = "5.13.2" description = "A Python utility / library to sort Python imports." optional = false python-versions = ">=3.8.0" files = [ {file = "isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"}, {file = "isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109"}, ] [package.extras] colors = ["colorama (>=0.4.6)"] [[package]] name = "jinja2" version = "3.1.4" description = "A very fast and expressive template engine." optional = false python-versions = ">=3.7" files = [ {file = "jinja2-3.1.4-py3-none-any.whl", hash = "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d"}, {file = "jinja2-3.1.4.tar.gz", hash = "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369"}, ] [package.dependencies] MarkupSafe = ">=2.0" [package.extras] i18n = ["Babel (>=2.7)"] [[package]] name = "libcst" version = "1.1.0" description = "A concrete syntax tree with AST-like properties for Python 3.5, 3.6, 3.7, 3.8, 3.9, and 3.10 programs." optional = false python-versions = ">=3.8" files = [ {file = "libcst-1.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:63f75656fd733dc20354c46253fde3cf155613e37643c3eaf6f8818e95b7a3d1"}, {file = "libcst-1.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8ae11eb1ea55a16dc0cdc61b41b29ac347da70fec14cc4381248e141ee2fbe6c"}, {file = "libcst-1.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4bc745d0c06420fe2644c28d6ddccea9474fb68a2135904043676deb4fa1e6bc"}, {file = "libcst-1.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c1f2da45f1c45634090fd8672c15e0159fdc46853336686959b2d093b6e10fa"}, {file = "libcst-1.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:003e5e83a12eed23542c4ea20fdc8de830887cc03662432bb36f84f8c4841b81"}, {file = "libcst-1.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:3ebbb9732ae3cc4ae7a0e97890bed0a57c11d6df28790c2b9c869f7da653c7c7"}, {file = "libcst-1.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d68c34e3038d3d1d6324eb47744cbf13f2c65e1214cf49db6ff2a6603c1cd838"}, {file = "libcst-1.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9dffa1795c2804d183efb01c0f1efd20a7831db6a21a0311edf90b4100d67436"}, {file = "libcst-1.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc9b6ac36d7ec9db2f053014ea488086ca2ed9c322be104fbe2c71ca759da4bb"}, {file = "libcst-1.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78b7a38ec4c1c009ac39027d51558b52851fb9234669ba5ba62283185963a31c"}, {file = "libcst-1.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5297a16e575be8173185e936b7765c89a3ca69d4ae217a4af161814a0f9745a7"}, {file = "libcst-1.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:7ccaf53925f81118aeaadb068a911fac8abaff608817d7343da280616a5ca9c1"}, {file = "libcst-1.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:75816647736f7e09c6120bdbf408456f99b248d6272277eed9a58cf50fb8bc7d"}, {file = "libcst-1.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c8f26250f87ca849a7303ed7a4fd6b2c7ac4dec16b7d7e68ca6a476d7c9bfcdb"}, {file = "libcst-1.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d37326bd6f379c64190a28947a586b949de3a76be00176b0732c8ee87d67ebe"}, {file = "libcst-1.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e3d8cf974cfa2487b28f23f56c4bff90d550ef16505e58b0dca0493d5293784b"}, {file = "libcst-1.1.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82d1271403509b0a4ee6ff7917c2d33b5a015f44d1e208abb1da06ba93b2a378"}, {file = "libcst-1.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:bca1841693941fdd18371824bb19a9702d5784cd347cb8231317dbdc7062c5bc"}, {file = "libcst-1.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f36f592e035ef84f312a12b75989dde6a5f6767fe99146cdae6a9ee9aff40dd0"}, {file = "libcst-1.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f561c9a84eca18be92f4ad90aa9bd873111efbea995449301719a1a7805dbc5c"}, {file = "libcst-1.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:97fbc73c87e9040e148881041fd5ffa2a6ebf11f64b4ccb5b52e574b95df1a15"}, {file = "libcst-1.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:99fdc1929703fd9e7408aed2e03f58701c5280b05c8911753a8d8619f7dfdda5"}, {file = "libcst-1.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0bf69cbbab5016d938aac4d3ae70ba9ccb3f90363c588b3b97be434e6ba95403"}, {file = "libcst-1.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:fe41b33aa73635b1651f64633f429f7aa21f86d2db5748659a99d9b7b1ed2a90"}, {file = "libcst-1.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:73c086705ed34dbad16c62c9adca4249a556c1b022993d511da70ea85feaf669"}, {file = "libcst-1.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3a07ecfabbbb8b93209f952a365549e65e658831e9231649f4f4e4263cad24b1"}, {file = "libcst-1.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c653d9121d6572d8b7f8abf20f88b0a41aab77ff5a6a36e5a0ec0f19af0072e8"}, {file = "libcst-1.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f1cd308a4c2f71d5e4eec6ee693819933a03b78edb2e4cc5e3ad1afd5fb3f07"}, {file = "libcst-1.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8afb6101b8b3c86c5f9cec6b90ab4da16c3c236fe7396f88e8b93542bb341f7c"}, {file = "libcst-1.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:d22d1abfe49aa60fc61fa867e10875a9b3024ba5a801112f4d7ba42d8d53242e"}, {file = "libcst-1.1.0.tar.gz", hash = "sha256:0acbacb9a170455701845b7e940e2d7b9519db35a86768d86330a0b0deae1086"}, ] [package.dependencies] pyyaml = ">=5.2" typing-extensions = ">=3.7.4.2" typing-inspect = ">=0.4.0" [package.extras] dev = ["Sphinx (>=5.1.1)", "black (==23.9.1)", "build (>=0.10.0)", "coverage (>=4.5.4)", "fixit (==2.0.0.post1)", "flake8 (>=3.7.8,<5)", "hypothesis (>=4.36.0)", "hypothesmith (>=0.0.4)", "jinja2 (==3.1.2)", "jupyter (>=1.0.0)", "maturin (>=0.8.3,<0.16)", "nbsphinx (>=0.4.2)", "prompt-toolkit (>=2.0.9)", "pyre-check (==0.9.18)", "setuptools-rust (>=1.5.2)", "setuptools-scm (>=6.0.1)", "slotscheck (>=0.7.1)", "sphinx-rtd-theme (>=0.4.3)", "ufmt (==2.2.0)", "usort (==1.0.7)"] [[package]] name = "markdown" version = "3.7" description = "Python implementation of John Gruber's Markdown." optional = false python-versions = ">=3.8" files = [ {file = "Markdown-3.7-py3-none-any.whl", hash = "sha256:7eb6df5690b81a1d7942992c97fad2938e956e79df20cbc6186e9c3a77b1c803"}, {file = "markdown-3.7.tar.gz", hash = "sha256:2ae2471477cfd02dbbf038d5d9bc226d40def84b4fe2986e49b59b6b472bbed2"}, ] [package.dependencies] importlib-metadata = {version = ">=4.4", markers = "python_version < \"3.10\""} [package.extras] docs = ["mdx-gh-links (>=0.2)", "mkdocs (>=1.5)", "mkdocs-gen-files", "mkdocs-literate-nav", "mkdocs-nature (>=0.6)", "mkdocs-section-index", "mkdocstrings[python]"] testing = ["coverage", "pyyaml"] [[package]] name = "markupsafe" version = "2.1.5" description = "Safely add untrusted strings to HTML/XML markup." optional = false python-versions = ">=3.7" files = [ {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc"}, {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5"}, {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46"}, {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f"}, {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900"}, {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff"}, {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad"}, {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd"}, {file = "MarkupSafe-2.1.5-cp310-cp310-win32.whl", hash = "sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4"}, {file = "MarkupSafe-2.1.5-cp310-cp310-win_amd64.whl", hash = "sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5"}, {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f"}, {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2"}, {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced"}, {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5"}, {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c"}, {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f"}, {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a"}, {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f"}, {file = "MarkupSafe-2.1.5-cp311-cp311-win32.whl", hash = "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906"}, {file = "MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl", hash = "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617"}, {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1"}, {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4"}, {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee"}, {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5"}, {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b"}, {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a"}, {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f"}, {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169"}, {file = "MarkupSafe-2.1.5-cp312-cp312-win32.whl", hash = "sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad"}, {file = "MarkupSafe-2.1.5-cp312-cp312-win_amd64.whl", hash = "sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb"}, {file = "MarkupSafe-2.1.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f"}, {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf"}, {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a"}, {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52"}, {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9"}, {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df"}, {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50"}, {file = "MarkupSafe-2.1.5-cp37-cp37m-win32.whl", hash = "sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371"}, {file = "MarkupSafe-2.1.5-cp37-cp37m-win_amd64.whl", hash = "sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2"}, {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a"}, {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46"}, {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532"}, {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab"}, {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68"}, {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0"}, {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4"}, {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3"}, {file = "MarkupSafe-2.1.5-cp38-cp38-win32.whl", hash = "sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff"}, {file = "MarkupSafe-2.1.5-cp38-cp38-win_amd64.whl", hash = "sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029"}, {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf"}, {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2"}, {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8"}, {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3"}, {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465"}, {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e"}, {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea"}, {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6"}, {file = "MarkupSafe-2.1.5-cp39-cp39-win32.whl", hash = "sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf"}, {file = "MarkupSafe-2.1.5-cp39-cp39-win_amd64.whl", hash = "sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5"}, {file = "MarkupSafe-2.1.5.tar.gz", hash = "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b"}, ] [[package]] name = "mccabe" version = "0.7.0" description = "McCabe checker, plugin for flake8" optional = false python-versions = ">=3.6" files = [ {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, ] [[package]] name = "mergedeep" version = "1.3.4" description = "A deep merge function for 🐍." optional = false python-versions = ">=3.6" files = [ {file = "mergedeep-1.3.4-py3-none-any.whl", hash = "sha256:70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307"}, {file = "mergedeep-1.3.4.tar.gz", hash = "sha256:0096d52e9dad9939c3d975a774666af186eda617e6ca84df4c94dec30004f2a8"}, ] [[package]] name = "mkdocs" version = "1.6.1" description = "Project documentation with Markdown." optional = false python-versions = ">=3.8" files = [ {file = "mkdocs-1.6.1-py3-none-any.whl", hash = "sha256:db91759624d1647f3f34aa0c3f327dd2601beae39a366d6e064c03468d35c20e"}, {file = "mkdocs-1.6.1.tar.gz", hash = "sha256:7b432f01d928c084353ab39c57282f29f92136665bdd6abf7c1ec8d822ef86f2"}, ] [package.dependencies] click = ">=7.0" colorama = {version = ">=0.4", markers = "platform_system == \"Windows\""} ghp-import = ">=1.0" importlib-metadata = {version = ">=4.4", markers = "python_version < \"3.10\""} 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" [package.extras] i18n = ["babel (>=2.9.0)"] 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)"] [[package]] name = "mkdocs-autorefs" version = "1.2.0" description = "Automatically link across pages in MkDocs." optional = false python-versions = ">=3.8" files = [ {file = "mkdocs_autorefs-1.2.0-py3-none-any.whl", hash = "sha256:d588754ae89bd0ced0c70c06f58566a4ee43471eeeee5202427da7de9ef85a2f"}, {file = "mkdocs_autorefs-1.2.0.tar.gz", hash = "sha256:a86b93abff653521bda71cf3fc5596342b7a23982093915cb74273f67522190f"}, ] [package.dependencies] Markdown = ">=3.3" markupsafe = ">=2.0.1" mkdocs = ">=1.1" [[package]] name = "mkdocs-gen-files" version = "0.5.0" description = "MkDocs plugin to programmatically generate documentation pages during the build" optional = false python-versions = ">=3.7" files = [ {file = "mkdocs_gen_files-0.5.0-py3-none-any.whl", hash = "sha256:7ac060096f3f40bd19039e7277dd3050be9a453c8ac578645844d4d91d7978ea"}, {file = "mkdocs_gen_files-0.5.0.tar.gz", hash = "sha256:4c7cf256b5d67062a788f6b1d035e157fc1a9498c2399be9af5257d4ff4d19bc"}, ] [package.dependencies] mkdocs = ">=1.0.3" [[package]] name = "mkdocs-get-deps" version = "0.2.0" description = "MkDocs extension that lists all dependencies according to a mkdocs.yml file" optional = false python-versions = ">=3.8" files = [ {file = "mkdocs_get_deps-0.2.0-py3-none-any.whl", hash = "sha256:2bf11d0b133e77a0dd036abeeb06dec8775e46efa526dc70667d8863eefc6134"}, {file = "mkdocs_get_deps-0.2.0.tar.gz", hash = "sha256:162b3d129c7fad9b19abfdcb9c1458a651628e4b1dea628ac68790fb3061c60c"}, ] [package.dependencies] importlib-metadata = {version = ">=4.3", markers = "python_version < \"3.10\""} mergedeep = ">=1.3.4" platformdirs = ">=2.2.0" pyyaml = ">=5.1" [[package]] name = "mkdocs-material" version = "9.5.44" description = "Documentation that simply works" optional = false python-versions = ">=3.8" files = [ {file = "mkdocs_material-9.5.44-py3-none-any.whl", hash = "sha256:47015f9c167d58a5ff5e682da37441fc4d66a1c79334bfc08d774763cacf69ca"}, {file = "mkdocs_material-9.5.44.tar.gz", hash = "sha256:f3a6c968e524166b3f3ed1fb97d3ed3e0091183b0545cedf7156a2a6804c56c0"}, ] [package.dependencies] babel = ">=2.10,<3.0" colorama = ">=0.4,<1.0" jinja2 = ">=3.0,<4.0" markdown = ">=3.2,<4.0" mkdocs = ">=1.6,<2.0" mkdocs-material-extensions = ">=1.3,<2.0" paginate = ">=0.5,<1.0" pygments = ">=2.16,<3.0" pymdown-extensions = ">=10.2,<11.0" regex = ">=2022.4" requests = ">=2.26,<3.0" [package.extras] git = ["mkdocs-git-committers-plugin-2 (>=1.1,<2.0)", "mkdocs-git-revision-date-localized-plugin (>=1.2.4,<2.0)"] imaging = ["cairosvg (>=2.6,<3.0)", "pillow (>=10.2,<11.0)"] recommended = ["mkdocs-minify-plugin (>=0.7,<1.0)", "mkdocs-redirects (>=1.2,<2.0)", "mkdocs-rss-plugin (>=1.6,<2.0)"] [[package]] name = "mkdocs-material-extensions" version = "1.3.1" description = "Extension pack for Python Markdown and MkDocs Material." optional = false python-versions = ">=3.8" files = [ {file = "mkdocs_material_extensions-1.3.1-py3-none-any.whl", hash = "sha256:adff8b62700b25cb77b53358dad940f3ef973dd6db797907c49e3c2ef3ab4e31"}, {file = "mkdocs_material_extensions-1.3.1.tar.gz", hash = "sha256:10c9511cea88f568257f960358a467d12b970e1f7b2c0e5fb2bb48cab1928443"}, ] [[package]] name = "mkdocstrings" version = "0.26.1" description = "Automatic documentation from sources, for MkDocs." optional = false python-versions = ">=3.8" files = [ {file = "mkdocstrings-0.26.1-py3-none-any.whl", hash = "sha256:29738bfb72b4608e8e55cc50fb8a54f325dc7ebd2014e4e3881a49892d5983cf"}, {file = "mkdocstrings-0.26.1.tar.gz", hash = "sha256:bb8b8854d6713d5348ad05b069a09f3b79edbc6a0f33a34c6821141adb03fe33"}, ] [package.dependencies] click = ">=7.0" importlib-metadata = {version = ">=4.6", markers = "python_version < \"3.10\""} Jinja2 = ">=2.11.1" Markdown = ">=3.6" MarkupSafe = ">=1.1" mkdocs = ">=1.4" mkdocs-autorefs = ">=1.2" platformdirs = ">=2.2" pymdown-extensions = ">=6.3" typing-extensions = {version = ">=4.1", markers = "python_version < \"3.10\""} [package.extras] crystal = ["mkdocstrings-crystal (>=0.3.4)"] python = ["mkdocstrings-python (>=0.5.2)"] python-legacy = ["mkdocstrings-python-legacy (>=0.2.1)"] [[package]] name = "mkdocstrings-python" version = "1.11.1" description = "A Python handler for mkdocstrings." optional = false python-versions = ">=3.8" files = [ {file = "mkdocstrings_python-1.11.1-py3-none-any.whl", hash = "sha256:a21a1c05acef129a618517bb5aae3e33114f569b11588b1e7af3e9d4061a71af"}, {file = "mkdocstrings_python-1.11.1.tar.gz", hash = "sha256:8824b115c5359304ab0b5378a91f6202324a849e1da907a3485b59208b797322"}, ] [package.dependencies] griffe = ">=0.49" mkdocs-autorefs = ">=1.2" mkdocstrings = ">=0.26" [[package]] name = "mypy" version = "1.13.0" description = "Optional static typing for Python" optional = false python-versions = ">=3.8" files = [ {file = "mypy-1.13.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6607e0f1dd1fb7f0aca14d936d13fd19eba5e17e1cd2a14f808fa5f8f6d8f60a"}, {file = "mypy-1.13.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8a21be69bd26fa81b1f80a61ee7ab05b076c674d9b18fb56239d72e21d9f4c80"}, {file = "mypy-1.13.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7b2353a44d2179846a096e25691d54d59904559f4232519d420d64da6828a3a7"}, {file = "mypy-1.13.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0730d1c6a2739d4511dc4253f8274cdd140c55c32dfb0a4cf8b7a43f40abfa6f"}, {file = "mypy-1.13.0-cp310-cp310-win_amd64.whl", hash = "sha256:c5fc54dbb712ff5e5a0fca797e6e0aa25726c7e72c6a5850cfd2adbc1eb0a372"}, {file = "mypy-1.13.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:581665e6f3a8a9078f28d5502f4c334c0c8d802ef55ea0e7276a6e409bc0d82d"}, {file = "mypy-1.13.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3ddb5b9bf82e05cc9a627e84707b528e5c7caaa1c55c69e175abb15a761cec2d"}, {file = "mypy-1.13.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:20c7ee0bc0d5a9595c46f38beb04201f2620065a93755704e141fcac9f59db2b"}, {file = "mypy-1.13.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3790ded76f0b34bc9c8ba4def8f919dd6a46db0f5a6610fb994fe8efdd447f73"}, {file = "mypy-1.13.0-cp311-cp311-win_amd64.whl", hash = "sha256:51f869f4b6b538229c1d1bcc1dd7d119817206e2bc54e8e374b3dfa202defcca"}, {file = "mypy-1.13.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:5c7051a3461ae84dfb5dd15eff5094640c61c5f22257c8b766794e6dd85e72d5"}, {file = "mypy-1.13.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:39bb21c69a5d6342f4ce526e4584bc5c197fd20a60d14a8624d8743fffb9472e"}, {file = "mypy-1.13.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:164f28cb9d6367439031f4c81e84d3ccaa1e19232d9d05d37cb0bd880d3f93c2"}, {file = "mypy-1.13.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a4c1bfcdbce96ff5d96fc9b08e3831acb30dc44ab02671eca5953eadad07d6d0"}, {file = "mypy-1.13.0-cp312-cp312-win_amd64.whl", hash = "sha256:a0affb3a79a256b4183ba09811e3577c5163ed06685e4d4b46429a271ba174d2"}, {file = "mypy-1.13.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a7b44178c9760ce1a43f544e595d35ed61ac2c3de306599fa59b38a6048e1aa7"}, {file = "mypy-1.13.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5d5092efb8516d08440e36626f0153b5006d4088c1d663d88bf79625af3d1d62"}, {file = "mypy-1.13.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:de2904956dac40ced10931ac967ae63c5089bd498542194b436eb097a9f77bc8"}, {file = "mypy-1.13.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:7bfd8836970d33c2105562650656b6846149374dc8ed77d98424b40b09340ba7"}, {file = "mypy-1.13.0-cp313-cp313-win_amd64.whl", hash = "sha256:9f73dba9ec77acb86457a8fc04b5239822df0c14a082564737833d2963677dbc"}, {file = "mypy-1.13.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:100fac22ce82925f676a734af0db922ecfea991e1d7ec0ceb1e115ebe501301a"}, {file = "mypy-1.13.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7bcb0bb7f42a978bb323a7c88f1081d1b5dee77ca86f4100735a6f541299d8fb"}, {file = "mypy-1.13.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bde31fc887c213e223bbfc34328070996061b0833b0a4cfec53745ed61f3519b"}, {file = "mypy-1.13.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:07de989f89786f62b937851295ed62e51774722e5444a27cecca993fc3f9cd74"}, {file = "mypy-1.13.0-cp38-cp38-win_amd64.whl", hash = "sha256:4bde84334fbe19bad704b3f5b78c4abd35ff1026f8ba72b29de70dda0916beb6"}, {file = "mypy-1.13.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0246bcb1b5de7f08f2826451abd947bf656945209b140d16ed317f65a17dc7dc"}, {file = "mypy-1.13.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7f5b7deae912cf8b77e990b9280f170381fdfbddf61b4ef80927edd813163732"}, {file = "mypy-1.13.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7029881ec6ffb8bc233a4fa364736789582c738217b133f1b55967115288a2bc"}, {file = "mypy-1.13.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3e38b980e5681f28f033f3be86b099a247b13c491f14bb8b1e1e134d23bb599d"}, {file = "mypy-1.13.0-cp39-cp39-win_amd64.whl", hash = "sha256:a6789be98a2017c912ae6ccb77ea553bbaf13d27605d2ca20a76dfbced631b24"}, {file = "mypy-1.13.0-py3-none-any.whl", hash = "sha256:9c250883f9fd81d212e0952c92dbfcc96fc237f4b7c92f56ac81fd48460b3e5a"}, {file = "mypy-1.13.0.tar.gz", hash = "sha256:0291a61b6fbf3e6673e3405cfcc0e7650bebc7939659fdca2702958038bd835e"}, ] [package.dependencies] mypy-extensions = ">=1.0.0" tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} typing-extensions = ">=4.6.0" [package.extras] dmypy = ["psutil (>=4.0)"] faster-cache = ["orjson"] install-types = ["pip"] mypyc = ["setuptools (>=50)"] reports = ["lxml"] [[package]] name = "mypy-extensions" version = "1.0.0" description = "Type system extensions for programs checked with the mypy type checker." optional = false python-versions = ">=3.5" files = [ {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, ] [[package]] name = "nodeenv" version = "1.9.1" description = "Node.js virtual environment builder" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" files = [ {file = "nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9"}, {file = "nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f"}, ] [[package]] name = "packaging" version = "24.1" description = "Core utilities for Python packages" optional = false python-versions = ">=3.8" files = [ {file = "packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"}, {file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"}, ] [[package]] name = "paginate" version = "0.5.7" description = "Divides large result sets into pages for easier browsing" optional = false python-versions = "*" files = [ {file = "paginate-0.5.7-py2.py3-none-any.whl", hash = "sha256:b885e2af73abcf01d9559fd5216b57ef722f8c42affbb63942377668e35c7591"}, {file = "paginate-0.5.7.tar.gz", hash = "sha256:22bd083ab41e1a8b4f3690544afb2c60c25e5c9a63a30fa2f483f6c60c8e5945"}, ] [package.extras] dev = ["pytest", "tox"] lint = ["black"] [[package]] name = "pathspec" version = "0.12.1" description = "Utility library for gitignore style pattern matching of file paths." optional = false python-versions = ">=3.8" files = [ {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, ] [[package]] name = "platformdirs" version = "4.3.6" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." optional = false python-versions = ">=3.8" files = [ {file = "platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb"}, {file = "platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907"}, ] [package.extras] docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4)"] test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.2)", "pytest-cov (>=5)", "pytest-mock (>=3.14)"] type = ["mypy (>=1.11.2)"] [[package]] name = "pluggy" version = "1.5.0" description = "plugin and hook calling mechanisms for python" optional = false python-versions = ">=3.8" files = [ {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, ] [package.extras] dev = ["pre-commit", "tox"] testing = ["pytest", "pytest-benchmark"] [[package]] name = "pre-commit" version = "3.5.0" description = "A framework for managing and maintaining multi-language pre-commit hooks." optional = false python-versions = ">=3.8" files = [ {file = "pre_commit-3.5.0-py2.py3-none-any.whl", hash = "sha256:841dc9aef25daba9a0238cd27984041fa0467b4199fc4852e27950664919f660"}, {file = "pre_commit-3.5.0.tar.gz", hash = "sha256:5804465c675b659b0862f07907f96295d490822a450c4c40e747d0b1c6ebcb32"}, ] [package.dependencies] cfgv = ">=2.0.0" identify = ">=1.0.0" nodeenv = ">=0.11.1" pyyaml = ">=5.1" virtualenv = ">=20.10.0" [[package]] name = "pyflakes" version = "3.2.0" description = "passive checker of Python programs" optional = false python-versions = ">=3.8" files = [ {file = "pyflakes-3.2.0-py2.py3-none-any.whl", hash = "sha256:84b5be138a2dfbb40689ca07e2152deb896a65c3a3e24c251c5c62489568074a"}, {file = "pyflakes-3.2.0.tar.gz", hash = "sha256:1c61603ff154621fb2a9172037d84dca3500def8c8b630657d1701f026f8af3f"}, ] [[package]] name = "pygments" version = "2.18.0" description = "Pygments is a syntax highlighting package written in Python." optional = false python-versions = ">=3.8" files = [ {file = "pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a"}, {file = "pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199"}, ] [package.extras] windows-terminal = ["colorama (>=0.4.6)"] [[package]] name = "pylint" version = "3.2.7" description = "python code static checker" optional = false python-versions = ">=3.8.0" files = [ {file = "pylint-3.2.7-py3-none-any.whl", hash = "sha256:02f4aedeac91be69fb3b4bea997ce580a4ac68ce58b89eaefeaf06749df73f4b"}, {file = "pylint-3.2.7.tar.gz", hash = "sha256:1b7a721b575eaeaa7d39db076b6e7743c993ea44f57979127c517c6c572c803e"}, ] [package.dependencies] astroid = ">=3.2.4,<=3.3.0-dev0" colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} dill = [ {version = ">=0.2", markers = "python_version < \"3.11\""}, {version = ">=0.3.7", markers = "python_version >= \"3.12\""}, {version = ">=0.3.6", markers = "python_version >= \"3.11\" and python_version < \"3.12\""}, ] isort = ">=4.2.5,<5.13.0 || >5.13.0,<6" mccabe = ">=0.6,<0.8" platformdirs = ">=2.2.0" tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} tomlkit = ">=0.10.1" typing-extensions = {version = ">=3.10.0", markers = "python_version < \"3.10\""} [package.extras] spelling = ["pyenchant (>=3.2,<4.0)"] testutils = ["gitpython (>3)"] [[package]] name = "pymdown-extensions" version = "10.12" description = "Extension pack for Python Markdown." optional = false python-versions = ">=3.8" files = [ {file = "pymdown_extensions-10.12-py3-none-any.whl", hash = "sha256:49f81412242d3527b8b4967b990df395c89563043bc51a3d2d7d500e52123b77"}, {file = "pymdown_extensions-10.12.tar.gz", hash = "sha256:b0ee1e0b2bef1071a47891ab17003bfe5bf824a398e13f49f8ed653b699369a7"}, ] [package.dependencies] markdown = ">=3.6" pyyaml = "*" [package.extras] extra = ["pygments (>=2.12)"] [[package]] name = "pytest" version = "8.3.3" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.8" files = [ {file = "pytest-8.3.3-py3-none-any.whl", hash = "sha256:a6853c7375b2663155079443d2e45de913a911a11d669df02a50814944db57b2"}, {file = "pytest-8.3.3.tar.gz", hash = "sha256:70b98107bd648308a7952b06e6ca9a50bc660be218d53c257cc1fc94fda10181"}, ] [package.dependencies] colorama = {version = "*", markers = "sys_platform == \"win32\""} exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} iniconfig = "*" packaging = "*" pluggy = ">=1.5,<2" tomli = {version = ">=1", markers = "python_version < \"3.11\""} [package.extras] dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] [[package]] name = "python-dateutil" version = "2.9.0.post0" description = "Extensions to the standard Python datetime module" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" files = [ {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, ] [package.dependencies] six = ">=1.5" [[package]] name = "pytkdocs" version = "0.16.2" description = "Load Python objects documentation." optional = false python-versions = ">=3.8" files = [ {file = "pytkdocs-0.16.2-py3-none-any.whl", hash = "sha256:36450316d004f6399402d044f122f28f88ff4a069899d10de3d28ad6b4ba5799"}, {file = "pytkdocs-0.16.2.tar.gz", hash = "sha256:e75538a34932996b8803fbad4e4f6851fc0e9fd9aea86fc6602d6582c12098f3"}, ] [package.dependencies] astunparse = {version = ">=1.6", markers = "python_version < \"3.9\""} [package.extras] numpy-style = ["docstring_parser (>=0.7)"] [[package]] name = "pytz" version = "2024.2" description = "World timezone definitions, modern and historical" optional = false python-versions = "*" files = [ {file = "pytz-2024.2-py2.py3-none-any.whl", hash = "sha256:31c7c1817eb7fae7ca4b8c7ee50c72f93aa2dd863de768e1ef4245d426aa0725"}, {file = "pytz-2024.2.tar.gz", hash = "sha256:2aa355083c50a0f93fa581709deac0c9ad65cca8a9e9beac660adcbd493c798a"}, ] [[package]] name = "pyupgrade" version = "3.8.0" description = "A tool to automatically upgrade syntax for newer versions." optional = false python-versions = ">=3.8" files = [ {file = "pyupgrade-3.8.0-py2.py3-none-any.whl", hash = "sha256:08d0e6129f5e9da7e7a581bdbea689e0d49c3c93eeaf156a07ae2fd794f52660"}, {file = "pyupgrade-3.8.0.tar.gz", hash = "sha256:1facb0b8407cca468dfcc1d13717e3a85aa37b9e6e7338664ad5bfe5ef50c867"}, ] [package.dependencies] tokenize-rt = ">=3.2.0" [[package]] name = "pyyaml" version = "6.0.2" description = "YAML parser and emitter for Python" optional = false python-versions = ">=3.8" files = [ {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237"}, {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b"}, {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed"}, {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180"}, {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68"}, {file = "PyYAML-6.0.2-cp310-cp310-win32.whl", hash = "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99"}, {file = "PyYAML-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e"}, {file = "PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774"}, {file = "PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee"}, {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c"}, {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317"}, {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85"}, {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4"}, {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e"}, {file = "PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5"}, {file = "PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44"}, {file = "PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab"}, {file = "PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725"}, {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5"}, {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425"}, {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476"}, {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48"}, {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b"}, {file = "PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4"}, {file = "PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8"}, {file = "PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba"}, {file = "PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1"}, {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133"}, {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484"}, {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5"}, {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc"}, {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652"}, {file = "PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183"}, {file = "PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563"}, {file = "PyYAML-6.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a"}, {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5"}, {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d"}, {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083"}, {file = "PyYAML-6.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706"}, {file = "PyYAML-6.0.2-cp38-cp38-win32.whl", hash = "sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a"}, {file = "PyYAML-6.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff"}, {file = "PyYAML-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d"}, {file = "PyYAML-6.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f"}, {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290"}, {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12"}, {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19"}, {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e"}, {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725"}, {file = "PyYAML-6.0.2-cp39-cp39-win32.whl", hash = "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631"}, {file = "PyYAML-6.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8"}, {file = "pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e"}, ] [[package]] name = "pyyaml-env-tag" version = "0.1" description = "A custom YAML tag for referencing environment variables in YAML files. " optional = false python-versions = ">=3.6" files = [ {file = "pyyaml_env_tag-0.1-py3-none-any.whl", hash = "sha256:af31106dec8a4d68c60207c1886031cbf839b68aa7abccdb19868200532c2069"}, {file = "pyyaml_env_tag-0.1.tar.gz", hash = "sha256:70092675bda14fdec33b31ba77e7543de9ddc88f2e5b99160396572d11525bdb"}, ] [package.dependencies] pyyaml = "*" [[package]] name = "regex" version = "2024.9.11" description = "Alternative regular expression module, to replace re." optional = false python-versions = ">=3.8" files = [ {file = "regex-2024.9.11-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:1494fa8725c285a81d01dc8c06b55287a1ee5e0e382d8413adc0a9197aac6408"}, {file = "regex-2024.9.11-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0e12c481ad92d129c78f13a2a3662317e46ee7ef96c94fd332e1c29131875b7d"}, {file = "regex-2024.9.11-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:16e13a7929791ac1216afde26f712802e3df7bf0360b32e4914dca3ab8baeea5"}, {file = "regex-2024.9.11-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:46989629904bad940bbec2106528140a218b4a36bb3042d8406980be1941429c"}, {file = "regex-2024.9.11-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a906ed5e47a0ce5f04b2c981af1c9acf9e8696066900bf03b9d7879a6f679fc8"}, {file = "regex-2024.9.11-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e9a091b0550b3b0207784a7d6d0f1a00d1d1c8a11699c1a4d93db3fbefc3ad35"}, {file = "regex-2024.9.11-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ddcd9a179c0a6fa8add279a4444015acddcd7f232a49071ae57fa6e278f1f71"}, {file = "regex-2024.9.11-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6b41e1adc61fa347662b09398e31ad446afadff932a24807d3ceb955ed865cc8"}, {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"}, {file = "regex-2024.9.11-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:635a1d96665f84b292e401c3d62775851aedc31d4f8784117b3c68c4fcd4118d"}, {file = "regex-2024.9.11-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:c0256beda696edcf7d97ef16b2a33a8e5a875affd6fa6567b54f7c577b30a137"}, {file = "regex-2024.9.11-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:3ce4f1185db3fbde8ed8aa223fc9620f276c58de8b0d4f8cc86fd1360829edb6"}, {file = "regex-2024.9.11-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:09d77559e80dcc9d24570da3745ab859a9cf91953062e4ab126ba9d5993688ca"}, {file = "regex-2024.9.11-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7a22ccefd4db3f12b526eccb129390942fe874a3a9fdbdd24cf55773a1faab1a"}, {file = "regex-2024.9.11-cp310-cp310-win32.whl", hash = "sha256:f745ec09bc1b0bd15cfc73df6fa4f726dcc26bb16c23a03f9e3367d357eeedd0"}, {file = "regex-2024.9.11-cp310-cp310-win_amd64.whl", hash = "sha256:01c2acb51f8a7d6494c8c5eafe3d8e06d76563d8a8a4643b37e9b2dd8a2ff623"}, {file = "regex-2024.9.11-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2cce2449e5927a0bf084d346da6cd5eb016b2beca10d0013ab50e3c226ffc0df"}, {file = "regex-2024.9.11-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3b37fa423beefa44919e009745ccbf353d8c981516e807995b2bd11c2c77d268"}, {file = "regex-2024.9.11-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:64ce2799bd75039b480cc0360907c4fb2f50022f030bf9e7a8705b636e408fad"}, {file = "regex-2024.9.11-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a4cc92bb6db56ab0c1cbd17294e14f5e9224f0cc6521167ef388332604e92679"}, {file = "regex-2024.9.11-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d05ac6fa06959c4172eccd99a222e1fbf17b5670c4d596cb1e5cde99600674c4"}, {file = "regex-2024.9.11-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:040562757795eeea356394a7fb13076ad4f99d3c62ab0f8bdfb21f99a1f85664"}, {file = "regex-2024.9.11-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6113c008a7780792efc80f9dfe10ba0cd043cbf8dc9a76ef757850f51b4edc50"}, {file = "regex-2024.9.11-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8e5fb5f77c8745a60105403a774fe2c1759b71d3e7b4ca237a5e67ad066c7199"}, {file = "regex-2024.9.11-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:54d9ff35d4515debf14bc27f1e3b38bfc453eff3220f5bce159642fa762fe5d4"}, {file = "regex-2024.9.11-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:df5cbb1fbc74a8305b6065d4ade43b993be03dbe0f8b30032cced0d7740994bd"}, {file = "regex-2024.9.11-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:7fb89ee5d106e4a7a51bce305ac4efb981536301895f7bdcf93ec92ae0d91c7f"}, {file = "regex-2024.9.11-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:a738b937d512b30bf75995c0159c0ddf9eec0775c9d72ac0202076c72f24aa96"}, {file = "regex-2024.9.11-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e28f9faeb14b6f23ac55bfbbfd3643f5c7c18ede093977f1df249f73fd22c7b1"}, {file = "regex-2024.9.11-cp311-cp311-win32.whl", hash = "sha256:18e707ce6c92d7282dfce370cd205098384b8ee21544e7cb29b8aab955b66fa9"}, {file = "regex-2024.9.11-cp311-cp311-win_amd64.whl", hash = "sha256:313ea15e5ff2a8cbbad96ccef6be638393041b0a7863183c2d31e0c6116688cf"}, {file = "regex-2024.9.11-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:b0d0a6c64fcc4ef9c69bd5b3b3626cc3776520a1637d8abaa62b9edc147a58f7"}, {file = "regex-2024.9.11-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:49b0e06786ea663f933f3710a51e9385ce0cba0ea56b67107fd841a55d56a231"}, {file = "regex-2024.9.11-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5b513b6997a0b2f10e4fd3a1313568e373926e8c252bd76c960f96fd039cd28d"}, {file = "regex-2024.9.11-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee439691d8c23e76f9802c42a95cfeebf9d47cf4ffd06f18489122dbb0a7ad64"}, {file = "regex-2024.9.11-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a8f877c89719d759e52783f7fe6e1c67121076b87b40542966c02de5503ace42"}, {file = "regex-2024.9.11-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:23b30c62d0f16827f2ae9f2bb87619bc4fba2044911e2e6c2eb1af0161cdb766"}, {file = "regex-2024.9.11-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85ab7824093d8f10d44330fe1e6493f756f252d145323dd17ab6b48733ff6c0a"}, {file = "regex-2024.9.11-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8dee5b4810a89447151999428fe096977346cf2f29f4d5e29609d2e19e0199c9"}, {file = "regex-2024.9.11-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:98eeee2f2e63edae2181c886d7911ce502e1292794f4c5ee71e60e23e8d26b5d"}, {file = "regex-2024.9.11-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:57fdd2e0b2694ce6fc2e5ccf189789c3e2962916fb38779d3e3521ff8fe7a822"}, {file = "regex-2024.9.11-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:d552c78411f60b1fdaafd117a1fca2f02e562e309223b9d44b7de8be451ec5e0"}, {file = "regex-2024.9.11-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:a0b2b80321c2ed3fcf0385ec9e51a12253c50f146fddb2abbb10f033fe3d049a"}, {file = "regex-2024.9.11-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:18406efb2f5a0e57e3a5881cd9354c1512d3bb4f5c45d96d110a66114d84d23a"}, {file = "regex-2024.9.11-cp312-cp312-win32.whl", hash = "sha256:e464b467f1588e2c42d26814231edecbcfe77f5ac414d92cbf4e7b55b2c2a776"}, {file = "regex-2024.9.11-cp312-cp312-win_amd64.whl", hash = "sha256:9e8719792ca63c6b8340380352c24dcb8cd7ec49dae36e963742a275dfae6009"}, {file = "regex-2024.9.11-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:c157bb447303070f256e084668b702073db99bbb61d44f85d811025fcf38f784"}, {file = "regex-2024.9.11-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4db21ece84dfeefc5d8a3863f101995de646c6cb0536952c321a2650aa202c36"}, {file = "regex-2024.9.11-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:220e92a30b426daf23bb67a7962900ed4613589bab80382be09b48896d211e92"}, {file = "regex-2024.9.11-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eb1ae19e64c14c7ec1995f40bd932448713d3c73509e82d8cd7744dc00e29e86"}, {file = "regex-2024.9.11-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f47cd43a5bfa48f86925fe26fbdd0a488ff15b62468abb5d2a1e092a4fb10e85"}, {file = "regex-2024.9.11-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9d4a76b96f398697fe01117093613166e6aa8195d63f1b4ec3f21ab637632963"}, {file = "regex-2024.9.11-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ea51dcc0835eea2ea31d66456210a4e01a076d820e9039b04ae8d17ac11dee6"}, {file = "regex-2024.9.11-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b7aaa315101c6567a9a45d2839322c51c8d6e81f67683d529512f5bcfb99c802"}, {file = "regex-2024.9.11-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c57d08ad67aba97af57a7263c2d9006d5c404d721c5f7542f077f109ec2a4a29"}, {file = "regex-2024.9.11-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:f8404bf61298bb6f8224bb9176c1424548ee1181130818fcd2cbffddc768bed8"}, {file = "regex-2024.9.11-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:dd4490a33eb909ef5078ab20f5f000087afa2a4daa27b4c072ccb3cb3050ad84"}, {file = "regex-2024.9.11-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:eee9130eaad130649fd73e5cd92f60e55708952260ede70da64de420cdcad554"}, {file = "regex-2024.9.11-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6a2644a93da36c784e546de579ec1806bfd2763ef47babc1b03d765fe560c9f8"}, {file = "regex-2024.9.11-cp313-cp313-win32.whl", hash = "sha256:e997fd30430c57138adc06bba4c7c2968fb13d101e57dd5bb9355bf8ce3fa7e8"}, {file = "regex-2024.9.11-cp313-cp313-win_amd64.whl", hash = "sha256:042c55879cfeb21a8adacc84ea347721d3d83a159da6acdf1116859e2427c43f"}, {file = "regex-2024.9.11-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:35f4a6f96aa6cb3f2f7247027b07b15a374f0d5b912c0001418d1d55024d5cb4"}, {file = "regex-2024.9.11-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:55b96e7ce3a69a8449a66984c268062fbaa0d8ae437b285428e12797baefce7e"}, {file = "regex-2024.9.11-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:cb130fccd1a37ed894824b8c046321540263013da72745d755f2d35114b81a60"}, {file = "regex-2024.9.11-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:323c1f04be6b2968944d730e5c2091c8c89767903ecaa135203eec4565ed2b2b"}, {file = "regex-2024.9.11-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:be1c8ed48c4c4065ecb19d882a0ce1afe0745dfad8ce48c49586b90a55f02366"}, {file = "regex-2024.9.11-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b5b029322e6e7b94fff16cd120ab35a253236a5f99a79fb04fda7ae71ca20ae8"}, {file = "regex-2024.9.11-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6fff13ef6b5f29221d6904aa816c34701462956aa72a77f1f151a8ec4f56aeb"}, {file = "regex-2024.9.11-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:587d4af3979376652010e400accc30404e6c16b7df574048ab1f581af82065e4"}, {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"}, {file = "regex-2024.9.11-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:f9268774428ec173654985ce55fc6caf4c6d11ade0f6f914d48ef4719eb05ebb"}, {file = "regex-2024.9.11-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:23f9985c8784e544d53fc2930fc1ac1a7319f5d5332d228437acc9f418f2f168"}, {file = "regex-2024.9.11-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:ae2941333154baff9838e88aa71c1d84f4438189ecc6021a12c7573728b5838e"}, {file = "regex-2024.9.11-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:e93f1c331ca8e86fe877a48ad64e77882c0c4da0097f2212873a69bbfea95d0c"}, {file = "regex-2024.9.11-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:846bc79ee753acf93aef4184c040d709940c9d001029ceb7b7a52747b80ed2dd"}, {file = "regex-2024.9.11-cp38-cp38-win32.whl", hash = "sha256:c94bb0a9f1db10a1d16c00880bdebd5f9faf267273b8f5bd1878126e0fbde771"}, {file = "regex-2024.9.11-cp38-cp38-win_amd64.whl", hash = "sha256:2b08fce89fbd45664d3df6ad93e554b6c16933ffa9d55cb7e01182baaf971508"}, {file = "regex-2024.9.11-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:07f45f287469039ffc2c53caf6803cd506eb5f5f637f1d4acb37a738f71dd066"}, {file = "regex-2024.9.11-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4838e24ee015101d9f901988001038f7f0d90dc0c3b115541a1365fb439add62"}, {file = "regex-2024.9.11-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6edd623bae6a737f10ce853ea076f56f507fd7726bee96a41ee3d68d347e4d16"}, {file = "regex-2024.9.11-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c69ada171c2d0e97a4b5aa78fbb835e0ffbb6b13fc5da968c09811346564f0d3"}, {file = "regex-2024.9.11-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:02087ea0a03b4af1ed6ebab2c54d7118127fee8d71b26398e8e4b05b78963199"}, {file = "regex-2024.9.11-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:69dee6a020693d12a3cf892aba4808fe168d2a4cef368eb9bf74f5398bfd4ee8"}, {file = "regex-2024.9.11-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:297f54910247508e6e5cae669f2bc308985c60540a4edd1c77203ef19bfa63ca"}, {file = "regex-2024.9.11-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ecea58b43a67b1b79805f1a0255730edaf5191ecef84dbc4cc85eb30bc8b63b9"}, {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"}, {file = "regex-2024.9.11-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:0cbff728659ce4bbf4c30b2a1be040faafaa9eca6ecde40aaff86f7889f4ab39"}, {file = "regex-2024.9.11-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:54c4a097b8bc5bb0dfc83ae498061d53ad7b5762e00f4adaa23bee22b012e6ba"}, {file = "regex-2024.9.11-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:73d6d2f64f4d894c96626a75578b0bf7d9e56dcda8c3d037a2118fdfe9b1c664"}, {file = "regex-2024.9.11-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:e53b5fbab5d675aec9f0c501274c467c0f9a5d23696cfc94247e1fb56501ed89"}, {file = "regex-2024.9.11-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:0ffbcf9221e04502fc35e54d1ce9567541979c3fdfb93d2c554f0ca583a19b35"}, {file = "regex-2024.9.11-cp39-cp39-win32.whl", hash = "sha256:e4c22e1ac1f1ec1e09f72e6c44d8f2244173db7eb9629cc3a346a8d7ccc31142"}, {file = "regex-2024.9.11-cp39-cp39-win_amd64.whl", hash = "sha256:faa3c142464efec496967359ca99696c896c591c56c53506bac1ad465f66e919"}, {file = "regex-2024.9.11.tar.gz", hash = "sha256:6c188c307e8433bcb63dc1915022deb553b4203a70722fc542c363bf120a01fd"}, ] [[package]] name = "requests" version = "2.32.3" description = "Python HTTP for Humans." optional = false python-versions = ">=3.8" files = [ {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, ] [package.dependencies] certifi = ">=2017.4.17" charset-normalizer = ">=2,<4" idna = ">=2.5,<4" urllib3 = ">=1.21.1,<3" [package.extras] socks = ["PySocks (>=1.5.6,!=1.5.7)"] use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "shed" version = "2023.6.1" description = "`shed` canonicalises Python code." optional = false python-versions = ">=3.7" files = [ {file = "shed-2023.6.1-py3-none-any.whl", hash = "sha256:f57ec3c5bebdace91dd4cff975e0b76405914dd4d3d6a107aa5fe5c05ca1c6c7"}, {file = "shed-2023.6.1.tar.gz", hash = "sha256:9f884d783f48b8ad86ce8fef9e3f71056190ce1421d942cbf59c23ac08ccd380"}, ] [package.dependencies] autoflake = ">=1.4" black = ">=23.3.0" com2ann = ">=0.3.0" isort = ">=5.10.1" libcst = ">=0.4.10" pyupgrade = ">=3.0.0" [[package]] name = "six" version = "1.16.0" description = "Python 2 and 3 compatibility utilities" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" files = [ {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, ] [[package]] name = "tokenize-rt" version = "6.0.0" description = "A wrapper around the stdlib `tokenize` which roundtrips." optional = false python-versions = ">=3.8" files = [ {file = "tokenize_rt-6.0.0-py2.py3-none-any.whl", hash = "sha256:d4ff7ded2873512938b4f8cbb98c9b07118f01d30ac585a30d7a88353ca36d22"}, {file = "tokenize_rt-6.0.0.tar.gz", hash = "sha256:b9711bdfc51210211137499b5e355d3de5ec88a85d2025c520cbb921b5194367"}, ] [[package]] name = "tomli" version = "2.0.2" description = "A lil' TOML parser" optional = false python-versions = ">=3.8" files = [ {file = "tomli-2.0.2-py3-none-any.whl", hash = "sha256:2ebe24485c53d303f690b0ec092806a085f07af5a5aa1464f3931eec36caaa38"}, {file = "tomli-2.0.2.tar.gz", hash = "sha256:d46d457a85337051c36524bc5349dd91b1877838e2979ac5ced3e710ed8a60ed"}, ] [[package]] name = "tomlkit" version = "0.13.2" description = "Style preserving TOML library" optional = false python-versions = ">=3.8" files = [ {file = "tomlkit-0.13.2-py3-none-any.whl", hash = "sha256:7a974427f6e119197f670fbbbeae7bef749a6c14e793db934baefc1b5f03efde"}, {file = "tomlkit-0.13.2.tar.gz", hash = "sha256:fff5fe59a87295b278abd31bec92c15d9bc4a06885ab12bcea52c71119392e79"}, ] [[package]] name = "typing-extensions" version = "4.12.2" description = "Backported and Experimental Type Hints for Python 3.8+" optional = false python-versions = ">=3.8" files = [ {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, ] [[package]] name = "typing-inspect" version = "0.9.0" description = "Runtime inspection utilities for typing module." optional = false python-versions = "*" files = [ {file = "typing_inspect-0.9.0-py3-none-any.whl", hash = "sha256:9ee6fc59062311ef8547596ab6b955e1b8aa46242d854bfc78f4f6b0eff35f9f"}, {file = "typing_inspect-0.9.0.tar.gz", hash = "sha256:b23fc42ff6f6ef6954e4852c1fb512cdd18dbea03134f91f856a95ccc9461f78"}, ] [package.dependencies] mypy-extensions = ">=0.3.0" typing-extensions = ">=3.7.4" [[package]] name = "urllib3" version = "2.2.3" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = ">=3.8" files = [ {file = "urllib3-2.2.3-py3-none-any.whl", hash = "sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac"}, {file = "urllib3-2.2.3.tar.gz", hash = "sha256:e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9"}, ] [package.extras] brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] h2 = ["h2 (>=4,<5)"] socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] zstd = ["zstandard (>=0.18.0)"] [[package]] name = "virtualenv" version = "20.27.1" description = "Virtual Python Environment builder" optional = false python-versions = ">=3.8" files = [ {file = "virtualenv-20.27.1-py3-none-any.whl", hash = "sha256:f11f1b8a29525562925f745563bfd48b189450f61fb34c4f9cc79dd5aa32a1f4"}, {file = "virtualenv-20.27.1.tar.gz", hash = "sha256:142c6be10212543b32c6c45d3d3893dff89112cc588b7d0879ae5a1ec03a47ba"}, ] [package.dependencies] distlib = ">=0.3.7,<1" filelock = ">=3.12.2,<4" platformdirs = ">=3.9.1,<5" [package.extras] docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2,!=7.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"] test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8)", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10)"] [[package]] name = "watchdog" version = "4.0.2" description = "Filesystem events monitoring" optional = false python-versions = ">=3.8" files = [ {file = "watchdog-4.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ede7f010f2239b97cc79e6cb3c249e72962404ae3865860855d5cbe708b0fd22"}, {file = "watchdog-4.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a2cffa171445b0efa0726c561eca9a27d00a1f2b83846dbd5a4f639c4f8ca8e1"}, {file = "watchdog-4.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c50f148b31b03fbadd6d0b5980e38b558046b127dc483e5e4505fcef250f9503"}, {file = "watchdog-4.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7c7d4bf585ad501c5f6c980e7be9c4f15604c7cc150e942d82083b31a7548930"}, {file = "watchdog-4.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:914285126ad0b6eb2258bbbcb7b288d9dfd655ae88fa28945be05a7b475a800b"}, {file = "watchdog-4.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:984306dc4720da5498b16fc037b36ac443816125a3705dfde4fd90652d8028ef"}, {file = "watchdog-4.0.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:1cdcfd8142f604630deef34722d695fb455d04ab7cfe9963055df1fc69e6727a"}, {file = "watchdog-4.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d7ab624ff2f663f98cd03c8b7eedc09375a911794dfea6bf2a359fcc266bff29"}, {file = "watchdog-4.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:132937547a716027bd5714383dfc40dc66c26769f1ce8a72a859d6a48f371f3a"}, {file = "watchdog-4.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:cd67c7df93eb58f360c43802acc945fa8da70c675b6fa37a241e17ca698ca49b"}, {file = "watchdog-4.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:bcfd02377be80ef3b6bc4ce481ef3959640458d6feaae0bd43dd90a43da90a7d"}, {file = "watchdog-4.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:980b71510f59c884d684b3663d46e7a14b457c9611c481e5cef08f4dd022eed7"}, {file = "watchdog-4.0.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:aa160781cafff2719b663c8a506156e9289d111d80f3387cf3af49cedee1f040"}, {file = "watchdog-4.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f6ee8dedd255087bc7fe82adf046f0b75479b989185fb0bdf9a98b612170eac7"}, {file = "watchdog-4.0.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:0b4359067d30d5b864e09c8597b112fe0a0a59321a0f331498b013fb097406b4"}, {file = "watchdog-4.0.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:770eef5372f146997638d737c9a3c597a3b41037cfbc5c41538fc27c09c3a3f9"}, {file = "watchdog-4.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:eeea812f38536a0aa859972d50c76e37f4456474b02bd93674d1947cf1e39578"}, {file = "watchdog-4.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b2c45f6e1e57ebb4687690c05bc3a2c1fb6ab260550c4290b8abb1335e0fd08b"}, {file = "watchdog-4.0.2-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:10b6683df70d340ac3279eff0b2766813f00f35a1d37515d2c99959ada8f05fa"}, {file = "watchdog-4.0.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:f7c739888c20f99824f7aa9d31ac8a97353e22d0c0e54703a547a218f6637eb3"}, {file = "watchdog-4.0.2-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:c100d09ac72a8a08ddbf0629ddfa0b8ee41740f9051429baa8e31bb903ad7508"}, {file = "watchdog-4.0.2-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:f5315a8c8dd6dd9425b974515081fc0aadca1d1d61e078d2246509fd756141ee"}, {file = "watchdog-4.0.2-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:2d468028a77b42cc685ed694a7a550a8d1771bb05193ba7b24006b8241a571a1"}, {file = "watchdog-4.0.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:f15edcae3830ff20e55d1f4e743e92970c847bcddc8b7509bcd172aa04de506e"}, {file = "watchdog-4.0.2-py3-none-manylinux2014_aarch64.whl", hash = "sha256:936acba76d636f70db8f3c66e76aa6cb5136a936fc2a5088b9ce1c7a3508fc83"}, {file = "watchdog-4.0.2-py3-none-manylinux2014_armv7l.whl", hash = "sha256:e252f8ca942a870f38cf785aef420285431311652d871409a64e2a0a52a2174c"}, {file = "watchdog-4.0.2-py3-none-manylinux2014_i686.whl", hash = "sha256:0e83619a2d5d436a7e58a1aea957a3c1ccbf9782c43c0b4fed80580e5e4acd1a"}, {file = "watchdog-4.0.2-py3-none-manylinux2014_ppc64.whl", hash = "sha256:88456d65f207b39f1981bf772e473799fcdc10801062c36fd5ad9f9d1d463a73"}, {file = "watchdog-4.0.2-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:32be97f3b75693a93c683787a87a0dc8db98bb84701539954eef991fb35f5fbc"}, {file = "watchdog-4.0.2-py3-none-manylinux2014_s390x.whl", hash = "sha256:c82253cfc9be68e3e49282831afad2c1f6593af80c0daf1287f6a92657986757"}, {file = "watchdog-4.0.2-py3-none-manylinux2014_x86_64.whl", hash = "sha256:c0b14488bd336c5b1845cee83d3e631a1f8b4e9c5091ec539406e4a324f882d8"}, {file = "watchdog-4.0.2-py3-none-win32.whl", hash = "sha256:0d8a7e523ef03757a5aa29f591437d64d0d894635f8a50f370fe37f913ce4e19"}, {file = "watchdog-4.0.2-py3-none-win_amd64.whl", hash = "sha256:c344453ef3bf875a535b0488e3ad28e341adbd5a9ffb0f7d62cefacc8824ef2b"}, {file = "watchdog-4.0.2-py3-none-win_ia64.whl", hash = "sha256:baececaa8edff42cd16558a639a9b0ddf425f93d892e8392a56bf904f5eff22c"}, {file = "watchdog-4.0.2.tar.gz", hash = "sha256:b4dfbb6c49221be4535623ea4474a4d6ee0a9cef4a80b20c28db4d858b64e270"}, ] [package.extras] watchmedo = ["PyYAML (>=3.10)"] [[package]] name = "wheel" version = "0.44.0" description = "A built-package format for Python" optional = false python-versions = ">=3.8" files = [ {file = "wheel-0.44.0-py3-none-any.whl", hash = "sha256:2376a90c98cc337d18623527a97c31797bd02bad0033d41547043a1cbfbe448f"}, {file = "wheel-0.44.0.tar.gz", hash = "sha256:a29c3f2817e95ab89aa4660681ad547c0e9547f20e75b0562fe7723c9a2a9d49"}, ] [package.extras] test = ["pytest (>=6.0.0)", "setuptools (>=65)"] [[package]] name = "zipp" version = "3.20.2" description = "Backport of pathlib-compatible object wrapper for zip files" optional = false python-versions = ">=3.8" files = [ {file = "zipp-3.20.2-py3-none-any.whl", hash = "sha256:a817ac80d6cf4b23bf7f2828b7cabf326f15a001bea8b1f9b49631780ba28350"}, {file = "zipp-3.20.2.tar.gz", hash = "sha256:bc9eb26f4506fda01b81bcde0ca78103b6e62f991b381fec825435c836edbc29"}, ] [package.extras] check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)"] cover = ["pytest-cov"] doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] enabler = ["pytest-enabler (>=2.2)"] test = ["big-O", "importlib-resources", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-ignore-flaky"] type = ["pytest-mypy"] [metadata] lock-version = "2.0" python-versions = ">=3.8,<4.0" content-hash = "883ed8fddffad4efc5496b3397886be879fed43fd9b462762e2f568e2cb0cf99" python-crc-7.1.0/pyproject.toml000066400000000000000000000037271471247750100165420ustar00rootroot00000000000000[tool.poetry] name = "crc" version = "7.1.0" description = "Pure Python CRC library" packages = [ { include = "crc", from = "src" }, ] authors = ["Nicola Coretti "] maintainers = ["Nicola Coretti "] license = "BSD-2-Clause" readme = "README.md" classifiers = [ "License :: OSI Approved :: BSD License", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", ] keywords = ['CRC', 'CRC8', 'CRC16', 'CRC32', 'CRC64'] repository = "https://github.com/Nicoretti/crc" [tool.poetry.urls] "Homepage" = "https://nicoretti.github.io/crc/" "Documentation" = "https://nicoretti.github.io/crc/" "Source" = "https://github.com/Nicoretti/crc" "Issues" = "https://github.com/Nicoretti/crc/issues" "Changelog" = "https://nicoretti.github.io/crc/changelog/unreleased/" [tool.poetry.scripts] crc = "crc._crc:main" [tool.poetry.dependencies] python = ">=3.8,<4.0" [tool.poetry.dev-dependencies] pytest = ">=7.2.0" pylint = ">=2.12.2" black = ">=22.1.0" isort = ">=5.10.1" coveralls = ">=3.3.1" mkdocs = ">=1.4.2" mkdocs-material = ">=9.0.6" pyupgrade = ">=3.2.2" shed = ">=0.10.7" mypy = ">=0.991" invoke = ">=2" mkdocs-autorefs = ">=0.4.1" mkdocstrings = ">=0.20.0" mkdocstrings-python = ">=0.8.2" pytkdocs = ">=0.16.1" pre-commit = "^3.1.1" mkdocs-gen-files = "^0.5.0" [build-system] requires = ["poetry-core>=1.0.0"] build-backend = "poetry.core.masonry.api" [tool.coverage.run] source = [ "crc", ] [tool.pylint.master] fail-under = 9.0 [tool.pylint.format] max-line-length = 88 max-module-lines = 800 [tool.black] line-length = 88 verbose = true include = "\\.pyi?$" [tool.isort] profile = "black" force_grid_wrap = 2 skip = [".gitignore", "venv", ".nox"] [tool.mypy] strict = true show_column_numbers = true show_error_context = true python-crc-7.1.0/src/000077500000000000000000000000001471247750100144045ustar00rootroot00000000000000python-crc-7.1.0/src/crc/000077500000000000000000000000001471247750100151535ustar00rootroot00000000000000python-crc-7.1.0/src/crc/__init__.py000066400000000000000000000006651471247750100172730ustar00rootroot00000000000000from ._crc import ( AbstractRegister, BasicRegister, Calculator, Configuration, Crc8, Crc16, Crc32, Crc64, InputType, Register, TableBasedRegister, __author__, ) __all__ = [ "AbstractRegister", "BasicRegister", "Calculator", "Configuration", "Crc16", "Crc32", "Crc64", "Crc8", "InputType", "Register", "TableBasedRegister", "__author__", ] python-crc-7.1.0/src/crc/__main__.py000066400000000000000000000003201471247750100172400ustar00rootroot00000000000000"""Main entrypoint for the package, to ensure it's runnable, ie: `python -m crc`.""" from ._crc import main # pragma: no cover if __name__ == "__main__": # pragma: no cover main() # pragma: no cover python-crc-7.1.0/src/crc/_crc.py000066400000000000000000000440021471247750100164330ustar00rootroot00000000000000# Copyright (c) 2018, Nicola Coretti # All rights reserved. from __future__ import annotations import abc import argparse import enum import functools import numbers import sys from dataclasses import dataclass from typing import ( BinaryIO, Final, Iterable, Iterator, Union, ) __author__ = [ "Nicola Coretti ", "Gert van Dijk ", ] InputType = Union[ int, bytes, bytearray, memoryview, BinaryIO, Iterable[Union[bytes, bytearray, memoryview]], ] """Type alias for acceptable input types for [Calculator][crc.Calculator].""" class Byte(numbers.Number): BIT_LENGTH: Final[int] = 8 BIT_MASK: Final[int] = 0xFF _value: int def __init__(self, value: int = 0x00) -> None: self._value = value & Byte.BIT_MASK def __add__(self, other: Byte) -> Byte: if not isinstance(other, Byte): other = Byte(other) return Byte(self.value + other.value) def __radd__(self, other: Byte) -> Byte: return self + other def __iadd__(self, other: Byte) -> Byte: result = self + other self.value = result.value return self def __eq__(self, other: object) -> bool: if not isinstance(other, Byte): return False return self.value == other.value def __hash__(self) -> int: return hash(self.value) def __len__(self) -> int: return Byte.BIT_LENGTH def __getitem__(self, index: int) -> int: if index >= Byte.BIT_LENGTH or index < 0: raise IndexError return (self.value & (1 << index)) >> index def __iter__(self) -> Iterator[int]: return (self[i] for i in range(len(self))) def __int__(self) -> int: return self.value @property def value(self) -> int: return self._value & Byte.BIT_MASK @value.setter def value(self, value: int) -> None: self._value = value & Byte.BIT_MASK def reversed(self) -> Byte: value = 0 for index, bit in enumerate(reversed(self)): value += bit << index return Byte(value) class AbstractRegister(metaclass=abc.ABCMeta): """ Abstract base class / Interface a crc register needs to implement. Workflow: 1. The Crc-Register needs to be initialized. 1 time (init) 2. Data is feed into the crc register. 1..n times (update) 3. Final result is calculated. 1 time (digest) """ @abc.abstractmethod def init(self) -> None: """ Initializes the crc register. """ @abc.abstractmethod def update(self, data: bytes) -> int: """ Feeds data into the register. Args: data: which will be feed into the register. Returns: Register content after the update. """ @abc.abstractmethod def digest(self) -> int: """ Final crc checksum will be calculated. Returns: Final crc result/value (applies pending operations like final xor). """ @abc.abstractmethod def reverse(self) -> int: """ Calculates the reversed value of the crc register. Returns: The reversed value of the crc register. """ @dataclass(frozen=True) class Configuration: """ A Configuration provides all settings necessary to determine the concrete implementation of a specific crc algorithm/register. Example: Create a custom configuration ```python from crc import Configuration saej1850 = Configuration( width=8, polynomial=0x1D, init_value=0xFF, final_xor_value=0xFF, reverse_input=False, reverse_output=False ) ``` """ width: int polynomial: int init_value: int = 0 final_xor_value: int = 0 reverse_input: bool = False reverse_output: bool = False class BasicRegister(AbstractRegister): """ Implements the common crc algorithm, assuming a user of this base class will provide an overwrite for the _process_byte method. """ _topbit: int _bitmask: int _config: Configuration _register: int def __init__(self, configuration: Configuration) -> None: """ Create a new BasicRegister. Args: configuration: Used to configure the crc algorithm. """ if isinstance(configuration, enum.Enum): configuration = configuration.value self._topbit = 1 << (configuration.width - 1) self._bitmask = int(2**configuration.width - 1) self._config = configuration self._register = configuration.init_value & self._bitmask def __len__(self) -> int: """ Returns: The width of the register. """ return self._config.width // 8 def __getitem__(self, index: int) -> int: """ Gets a single byte of the register. Args: index: byte which shall be returned. Returns: The byte at the specified index. Raises: IndexError: Invalid index for this register. """ if index >= (self._config.width / 8) or index < 0: raise IndexError shift_offset = index * 8 return (self.register & (0xFF << shift_offset)) >> shift_offset def init(self) -> None: """ See `AbstractRegister.init` """ self.register = self._config.init_value def update(self, data: bytes) -> int: """ See `AbstractRegister.update` """ for byte in (Byte(b) for b in data): if self._config.reverse_input: byte = byte.reversed() self._register = self._process_byte(byte) return self.register @abc.abstractmethod def _process_byte(self, byte: Byte) -> int: """ Feed a byte into the crc register. Args: byte: the byte which shall be processed by the crc register. Returns: The value/state the crc register needs to be put in after this byte has been processed. """ def digest(self) -> int: """ See `AbstractRegister.digest` """ value = self.reverse() if self._config.reverse_output else self.register return value ^ self._config.final_xor_value def reverse(self) -> int: """ See `AbstractRegister.digest` """ index = 0 reversed_value = 0 for byte in reversed(self): reversed_value += int(Byte(byte).reversed()) << index index += 8 return reversed_value def _is_division_possible(self) -> bool: return (self.register & self._topbit) > 0 @property def register(self) -> int: return self._register & self._bitmask @register.setter def register(self, value: int) -> None: self._register = value & self._bitmask class Register(BasicRegister): """ Simple crc register, which will process one bit at the time. Note: If performance is an important issue for the crc calculation use a table based register. """ def _process_byte(self, byte: Byte) -> int: """ See BasicRegister._process_byte """ self.register ^= int(byte) << (self._config.width - 8) for _ in byte: if self._is_division_possible(): self.register = (self.register << 1) ^ self._config.polynomial else: self.register <<= 1 return self.register class TableBasedRegister(BasicRegister): """ Lookup table based crc register. Info: This register type will be much faster than a simple bit by bit based crc register like `Register`. """ def __init__(self, configuration: Configuration) -> None: """ Creates a new table based crc register. Args: configuration: used for the crc algorithm. Attention: Creating a table based register initially might take some extra time, due to the fact that some lookup tables need to be calculated/initialized. """ super().__init__(configuration) if isinstance(configuration, enum.Enum): configuration = configuration.value self._lookup_table = create_lookup_table( configuration.width, configuration.polynomial ) def _process_byte(self, byte: Byte) -> int: """ See BasicRegister._process_byte """ index = int(byte) ^ (self.register >> (self._config.width - 8)) self.register = self._lookup_table[index] ^ (self.register << 8) return self.register @functools.lru_cache def create_lookup_table(width: int, polynomial: int) -> list[int]: """ Creates a crc lookup table. Args: width: of the crc checksum. polynomial: which is used for the crc calculation. Returns: The lookup table for the specified width and polynomial. """ config = Configuration(width=width, polynomial=polynomial) crc_register = Register(config) lookup_table: list[int] = [] for index in range(256): crc_register.init() data = bytes(index.to_bytes(1, byteorder="big")) crc_register.update(data) lookup_table.append(crc_register.digest()) return lookup_table class Calculator: def __init__(self, configuration: Configuration, optimized: bool = False) -> None: """ Creates a new Calculator. Args: configuration: for the crc algorithm. optimized: whether a register optimized for speed shall be used. :warning: initializing an optimized calculator might take some extra time, calculation itself will be faster though. """ _types = { False: Register, True: TableBasedRegister, } klass = _types[optimized] self._crc_register = klass(configuration) def checksum(self, data: InputType) -> int: """ Calculates the checksum for the given data. Args: data: which will be used as input for the checksum. Returns: Checksum for the given input data. """ self._crc_register.init() for chunk in _bytes_generator(data): self._crc_register.update(chunk) return self._crc_register.digest() def verify(self, data: InputType, expected: int) -> bool: """ Verifies that the checksum for the given data is the expected one. Args: data: which will be used as input for the checksum. expected: checksum. Returns: True if the expected checksum matches the actual checksum for the given data, False otherwise. """ return self.checksum(data) == expected def _bytes_generator(data: InputType) -> Iterable[bytes]: if isinstance(data, int): yield data.to_bytes(1, "big") elif isinstance(data, bytes): yield data elif isinstance(data, (bytearray, memoryview)): yield bytes(data) elif isinstance(data, (Iterable, BinaryIO)): yield from (bytes(e) for e in data) else: raise TypeError(f"Unsupported parameter type: {type(data)}") @enum.unique class Crc8(enum.Enum): CCITT = Configuration( width=8, polynomial=0x07, init_value=0x00, final_xor_value=0x00, reverse_input=False, reverse_output=False, ) SAEJ1850 = Configuration( width=8, polynomial=0x1D, init_value=0xFF, final_xor_value=0xFF, reverse_input=False, reverse_output=False, ) SAEJ1850_ZERO = Configuration( width=8, polynomial=0x1D, init_value=0x00, final_xor_value=0x00, reverse_input=False, reverse_output=False, ) AUTOSAR = Configuration( width=8, polynomial=0x2F, init_value=0xFF, final_xor_value=0xFF, reverse_input=False, reverse_output=False, ) BLUETOOTH = Configuration( width=8, polynomial=0xA7, init_value=0x00, final_xor_value=0x00, reverse_input=True, reverse_output=True, ) MAXIM_DOW = Configuration( width=8, polynomial=0x31, init_value=0, final_xor_value=0, reverse_input=True, reverse_output=True, ) ITU = Configuration( width=8, polynomial=0x07, init_value=0x00, final_xor_value=0x55, reverse_input=False, reverse_output=False, ) ROHC = Configuration( width=8, polynomial=0x07, init_value=0xFF, final_xor_value=0x00, reverse_input=True, reverse_output=True, ) @enum.unique class Crc16(enum.Enum): XMODEM = Configuration( width=16, polynomial=0x1021, init_value=0x0000, final_xor_value=0x0000, reverse_input=False, reverse_output=False, ) GSM = Configuration( width=16, polynomial=0x1021, init_value=0x0000, final_xor_value=0xFFFF, reverse_input=False, reverse_output=False, ) PROFIBUS = Configuration( width=16, polynomial=0x1DCF, init_value=0xFFFF, final_xor_value=0xFFFF, reverse_input=False, reverse_output=False, ) MODBUS = Configuration( width=16, polynomial=0x8005, init_value=0xFFFF, final_xor_value=0x0000, reverse_input=True, reverse_output=True, ) IBM_3740 = Configuration( width=16, polynomial=0x1021, init_value=0xFFFF, final_xor_value=0x0000, reverse_input=False, reverse_output=False, ) KERMIT = Configuration( width=16, polynomial=0x1021, init_value=0x0000, final_xor_value=0x0000, reverse_input=True, reverse_output=True, ) IBM = Configuration( width=16, polynomial=0x8005, init_value=0x0000, final_xor_value=0x0000, reverse_input=True, reverse_output=True, ) MAXIM = Configuration( width=16, polynomial=0x8005, init_value=0x0000, final_xor_value=0xFFFF, reverse_input=True, reverse_output=True, ) USB = Configuration( width=16, polynomial=0x8005, init_value=0xFFFF, final_xor_value=0xFFFF, reverse_input=True, reverse_output=True, ) X25 = Configuration( width=16, polynomial=0x1021, init_value=0xFFFF, final_xor_value=0xFFFF, reverse_input=True, reverse_output=True, ) DNP = Configuration( width=16, polynomial=0x3D65, init_value=0x0000, final_xor_value=0xFFFF, reverse_input=True, reverse_output=True, ) @enum.unique class Crc32(enum.Enum): CRC32 = Configuration( width=32, polynomial=0x04C11DB7, init_value=0xFFFFFFFF, final_xor_value=0xFFFFFFFF, reverse_input=True, reverse_output=True, ) AUTOSAR = Configuration( width=32, polynomial=0xF4ACFB13, init_value=0xFFFFFFFF, final_xor_value=0xFFFFFFFF, reverse_input=True, reverse_output=True, ) BZIP2 = Configuration( width=32, polynomial=0x04C11DB7, init_value=0xFFFFFFFF, final_xor_value=0xFFFFFFFF, reverse_input=False, reverse_output=False, ) POSIX = Configuration( width=32, polynomial=0x04C11DB7, init_value=0x00000000, final_xor_value=0xFFFFFFFF, reverse_input=False, reverse_output=False, ) @enum.unique class Crc64(enum.Enum): CRC64 = Configuration( width=64, polynomial=0x42F0E1EBA9EA3693, init_value=0x0000000000000000, final_xor_value=0x0000000000000000, reverse_input=False, reverse_output=False, ) def _argument_parser() -> argparse.ArgumentParser: into_int = functools.partial(int, base=0) program = "crc" description = "A set of crc checksum related command line tools." parser = argparse.ArgumentParser( prog=program, description=description, formatter_class=argparse.ArgumentDefaultsHelpFormatter, ) subparsers = parser.add_subparsers() table_command = subparsers.add_parser( "table", help="Generates lookup tables for various crc algorithm settings" ) table_command.add_argument( "width", metavar="", type=into_int, help="width of the crc algorithm, common width's are 8, 16, 32, 64", ) table_command.add_argument( "polynomial", metavar="", type=into_int, help="hex value of the polynomial used for calculating the crc table", ) table_command.set_defaults(func=table) return parser def _generate_template(width: int) -> str: return f"0x{{:0{(width + 3) // 4}X}}" def table(args: argparse.Namespace) -> bool: if not (args.width and args.polynomial): return False columns = 8 width = args.width polynomial = args.polynomial lookup_table = create_lookup_table(width, polynomial) template = _generate_template(width) rows = (lookup_table[i : i + columns] for i in range(0, len(lookup_table), columns)) print("\n".join(" ".join(template.format(value) for value in r) for r in rows)) return True def main(argv: list[str] | None = None) -> None: parser = _argument_parser() args = parser.parse_args(argv) if "func" in args: exit_code = 0 if args.func(args) else -1 sys.exit(exit_code) else: parser.print_help() sys.exit(-1) # Although there's a __main__.py to invoke main(), let's keep this in for users who # would like to use crc as a single-file. if __name__ == "__main__": main() # pragma: no cover python-crc-7.1.0/src/crc/py.typed000066400000000000000000000000001471247750100166400ustar00rootroot00000000000000python-crc-7.1.0/tasks.py000066400000000000000000000207601471247750100153210ustar00rootroot00000000000000"""Automation tasks for the crc project""" import shutil import sys from functools import partial from inspect import cleandoc from pathlib import Path from shutil import which from typing import Iterable from invoke import ( Collection, task, ) from invoke.main import program BASEPATH = Path(__file__).parent.resolve() def _python_files( project_root: Path, path_filters: Iterable[str] = ("dist", ".eggs", "venv") ) -> Iterable[Path]: """Returns all relevant""" return _deny_filter(project_root.glob("**/*.py"), deny_list=path_filters) def _deny_filter(files: Iterable[Path], deny_list: Iterable[str]) -> Iterable[Path]: """ Adds a filter to remove unwanted paths containing python files from the iterator. args: return: """ for entry in deny_list: files = filter(lambda path: entry not in path.parts, files) return files def _cmd(*args): return " ".join(args) def _poetry(*args): return _cmd("poetry", "run", *args) def _select_files(root, files): if root != BASEPATH and files is not None: raise Exception( "Conflicting options --files --root, details: " "either specify --files or --root but not both." ) return ( list(files) if files is not None and len(files) > 0 else [f"{f}" for f in _python_files(BASEPATH)] ) def _is_command_available(command: str) -> bool: path = which(command) return path is not None and path not in ["", " "] class Console: stdout = print stderr = partial(print, file=sys.stderr) @task(aliases=["init"]) def initialize_workspace(context): """ Prepare/Initialize the workspace """ context.run("pre-commit install") if not _is_command_available("gh"): Console.stdout( cleandoc( """ ❌ Error Please install the gh command line tool, and then rerun this task. Details: https://cli.github.com/manual/installation """ ) ) sys.exit(-1) result = context.run(_cmd("gh", "auth", "status"), warn=True, pty=True) if not result.ok: Console.stdout( cleandoc( """ ❌ Error Please authenticate the gh command line tool, and then rerun this task. Details see: gh auth -h """ ) ) sys.exit(-1) Console.stdout("βœ… You are all set, happy hacking!") @task( name="format", optional=["root", "files", "fix"], iterable=["files"], help={ "root": f"default: {BASEPATH}", "fix": "default: True", "files": "default: None", }, aliases=["fmt"], ) def fmt(context, root=BASEPATH, files=None, fix=True): """Run code formatter(s)""" mode_filter = lambda v: v != "--check" if fix else lambda v: True files = _select_files(root, files) isort = _poetry(*filter(mode_filter, ["isort", "--check", "-v"]), *files) black = _poetry(*filter(mode_filter, ["black", "--check", "--color"]), *files) context.run(isort) context.run(black) @task(aliases=["ut"]) def unit_test(context, root=BASEPATH / "test" / "unit", coverage=False): """Run all unit tests""" command = ["coverage", "run", "-m", "-a"] if coverage else [] command = _poetry(*command, "pytest", f"{root}") context.run(command) @task(aliases=["it"]) def integration_test(context, root=BASEPATH / "test" / "integration", coverage=False): """Run all integration tests""" command = ["coverage", "run", "-m", "-a"] if coverage else [] command = _poetry(*command, "pytest", f"{root}") context.run(command) @task( optional=["root"], help={"root": f"default: {BASEPATH}"}, aliases=["cov"], ) def coverage(context, root=BASEPATH): """Run all tests and collect & report coverage information""" coverage_file = BASEPATH / ".coverage" coverage_file.unlink(missing_ok=True) unit_test(context, root=root / "test" / "unit", coverage=True) integration_test(context, root=root / "test" / "integration", coverage=True) report = _poetry("coverage", "report", "--fail-under=100", "--show-missing") context.run(report) @task( optional=["root", "files"], iterable=["files"], help={ "root": f"default: {BASEPATH}", "files": "default: None", }, ) def lint(context, root=BASEPATH, files=None): """Run linting""" files = _select_files(root, files) pylint = _poetry("pylint", *files) context.run(pylint) @task( optional=["root", "files"], iterable=["files"], help={ "root": f"default: {BASEPATH}", "files": "default: None", }, ) def typing(context, root=BASEPATH, files=None): """Run type check(s)""" files = _select_files(root, files) mypy = _poetry("mypy", *files) context.run(mypy) @task( optional=["root", "files"], iterable=["files"], help={ "root": f"default: {BASEPATH}", "files": "default: None", }, ) def check(context, root=BASEPATH, files=None): """Run all code format checks""" fmt(context, root, files, fix=False) @task def clean_docs(_context): """Remove all documentation build artifacts""" doc_output_folder = BASEPATH / ".html-documentation" if doc_output_folder.exists(): shutil.rmtree(doc_output_folder) @task def build_docs(context): """Build project documentation""" context.run( _poetry( "mkdocs", "build", "-c", "-s", "-d", f"{BASEPATH / '.html-documentation'}", "-f", f"{BASEPATH / 'docs' / 'mkdocs.yml'}", ) ) @task def serve_docs(context): """Serve project documentation""" context.run(_poetry("mkdocs", "serve", "-f", f"{BASEPATH / 'docs' / 'mkdocs.yml'}")) @task def release_pypi(context): """Create a PyPi release""" context.run(_cmd("poetry", "build")) context.run(_cmd("poetry", "publish")) @task(aliases=["gh"]) def release_github(context, version): """Create a GitHub release""" context.run(_cmd("poetry", "build")) context.run(_cmd("gh", "release", "create", version, "--title", version, "dist/*")) @task def release_docs(context): """Deploy documentation to GitHub pages""" context.run( _poetry( "mkdocs", "deploy", "-f", f"{BASEPATH / 'docs' / 'mkdocs.yml'}", "--remote-branch", "gh-pages", ) ) @task(aliases=["prep"]) def release_prepare(context, version): """Pre release steps""" answer = input("did you update the changelog? [y/n] ").lower() if answer not in ["yes", "y"]: Console.stdout("Aborting, re run once the changelog have been updated.") sys.exit(-1) context.run(_cmd("poetry", "version", version)) context.run(_cmd("git", "add", "pyproject.toml")) context.run(_cmd("git", "commit", "-m", f'"Prepare release {version}"')) @task def release_workflow(context, version): """Start/Trigger a GitHub action based release workflow""" context.run(_cmd("git", "tag", version)) context.run(_cmd("git", "push", "origin", version)) context.run(_cmd("gh", "workflow", "view", "ci-cd.yml", "--web")) @task def release_local(context, version): """Do a release out of the current workspace""" check(context) lint(context) typing(context) coverage(context) release_prepare(context, version) release_github(context, version) release_pypi(context) release_docs(context) test = Collection("test") test.add_task(unit_test, name="unit") test.add_task(integration_test, name="integration") test.add_task(coverage, name="coverage") checks = Collection("check") checks.add_task(lint, name="lint") checks.add_task(typing, name="typing") checks.add_task(check, name="format") docs = Collection("docs") docs.add_task(clean_docs, name="clean") docs.add_task(build_docs, name="build") docs.add_task(serve_docs, name="serve") release = Collection("release") release.add_task(release_prepare, name="prepare") release.add_task(release_workflow, name="workflow") release.add_task(release_local, name="local") release.add_task(release_pypi, name="pypi") release.add_task(release_github, name="github") release.add_task(release_docs, name="docs") namespace = Collection() namespace.add_task(initialize_workspace) namespace.add_task(fmt, name="format") namespace.add_collection(test) namespace.add_collection(checks) namespace.add_collection(docs) namespace.add_collection(release) if __name__ == "__main__": program.run() python-crc-7.1.0/test/000077500000000000000000000000001471247750100145745ustar00rootroot00000000000000python-crc-7.1.0/test/bench/000077500000000000000000000000001471247750100156535ustar00rootroot00000000000000python-crc-7.1.0/test/bench/benches.py000066400000000000000000000047521471247750100176440ustar00rootroot00000000000000import timeit import unittest class CrcRegisterBenchTest(unittest.TestCase): def test_crc_reg_vs_table_based_reg(self): reg = "\n".join( [ "import string", "from crc import Register", "from crc import Configuration, Crc8", "from collections import namedtuple", "CrcTestData = namedtuple('CrcTestData', 'data checksum')", "config = Crc8.CCITT", "crc_register = Register(config)", "test_suit = [", " CrcTestData(data='', checksum=0x00),", " CrcTestData(data=string.digits[1:], checksum=0xF4),", " CrcTestData(data=string.digits[1:][::-1], checksum=0x91),", " CrcTestData(data=string.digits, checksum=0x45),", " CrcTestData(data=string.digits[::-1], checksum=0x6E),", "]", "for test in test_suit:", " crc_register.init()", "crc_register.update(test.data.encode('utf-8'))", "assert test.checksum == crc_register.digest()", ] ) reg_times = timeit.repeat(reg, number=100) table_reg = "\n".join( [ "import string", "from crc import TableBasedRegister", "from crc import Configuration, Crc8", "from collections import namedtuple", "CrcTestData = namedtuple('CrcTestData', 'data checksum')", "config = Crc8.CCITT", "crc_register = TableBasedRegister(config)", "test_suit = [", " CrcTestData(data='', checksum=0x00),", " CrcTestData(data=string.digits[1:], checksum=0xF4),", " CrcTestData(data=string.digits[1:][::-1], checksum=0x91),", " CrcTestData(data=string.digits, checksum=0x45),", " CrcTestData(data=string.digits[::-1], checksum=0x6E),", "]", "for test in test_suit:", " crc_register.init()", "crc_register.update(test.data.encode('utf-8'))", "assert test.checksum == crc_register.digest()", ] ) table_reg_times = timeit.repeat(table_reg, number=100) self.assertTrue( all(map(lambda entry: entry[0] > entry[1], zip(reg_times, table_reg_times))) ) if __name__ == "__main__": unittest.main() python-crc-7.1.0/test/integration/000077500000000000000000000000001471247750100171175ustar00rootroot00000000000000python-crc-7.1.0/test/integration/test_cli.py000066400000000000000000000062061471247750100213030ustar00rootroot00000000000000# Copyright (c) 2021, Nicola Coretti # All rights reserved. import inspect import io import unittest from unittest.mock import ( call, patch, ) from crc._crc import main class CliTests(unittest.TestCase): def test_cli_no_arguments_provided(self): expected_exit_code = -1 argv = [] with patch("sys.exit") as exit_mock: main(argv) self.assertTrue(exit_mock.called) self.assertEqual(exit_mock.call_args, (call(expected_exit_code))) def test_table_subcommand_with_no_additional_arguments(self): expected_exit_code = -1 argv = ["table"] with patch("sys.exit") as exit_mock: main(argv) self.assertTrue(exit_mock.called) self.assertEqual(exit_mock.call_args, (call(expected_exit_code))) def test_table_generation_for_width_8_and_poly_0x1D(self): expected_output = io.StringIO( inspect.cleandoc( """ 0x00 0x1D 0x3A 0x27 0x74 0x69 0x4E 0x53 0xE8 0xF5 0xD2 0xCF 0x9C 0x81 0xA6 0xBB 0xCD 0xD0 0xF7 0xEA 0xB9 0xA4 0x83 0x9E 0x25 0x38 0x1F 0x02 0x51 0x4C 0x6B 0x76 0x87 0x9A 0xBD 0xA0 0xF3 0xEE 0xC9 0xD4 0x6F 0x72 0x55 0x48 0x1B 0x06 0x21 0x3C 0x4A 0x57 0x70 0x6D 0x3E 0x23 0x04 0x19 0xA2 0xBF 0x98 0x85 0xD6 0xCB 0xEC 0xF1 0x13 0x0E 0x29 0x34 0x67 0x7A 0x5D 0x40 0xFB 0xE6 0xC1 0xDC 0x8F 0x92 0xB5 0xA8 0xDE 0xC3 0xE4 0xF9 0xAA 0xB7 0x90 0x8D 0x36 0x2B 0x0C 0x11 0x42 0x5F 0x78 0x65 0x94 0x89 0xAE 0xB3 0xE0 0xFD 0xDA 0xC7 0x7C 0x61 0x46 0x5B 0x08 0x15 0x32 0x2F 0x59 0x44 0x63 0x7E 0x2D 0x30 0x17 0x0A 0xB1 0xAC 0x8B 0x96 0xC5 0xD8 0xFF 0xE2 0x26 0x3B 0x1C 0x01 0x52 0x4F 0x68 0x75 0xCE 0xD3 0xF4 0xE9 0xBA 0xA7 0x80 0x9D 0xEB 0xF6 0xD1 0xCC 0x9F 0x82 0xA5 0xB8 0x03 0x1E 0x39 0x24 0x77 0x6A 0x4D 0x50 0xA1 0xBC 0x9B 0x86 0xD5 0xC8 0xEF 0xF2 0x49 0x54 0x73 0x6E 0x3D 0x20 0x07 0x1A 0x6C 0x71 0x56 0x4B 0x18 0x05 0x22 0x3F 0x84 0x99 0xBE 0xA3 0xF0 0xED 0xCA 0xD7 0x35 0x28 0x0F 0x12 0x41 0x5C 0x7B 0x66 0xDD 0xC0 0xE7 0xFA 0xA9 0xB4 0x93 0x8E 0xF8 0xE5 0xC2 0xDF 0x8C 0x91 0xB6 0xAB 0x10 0x0D 0x2A 0x37 0x64 0x79 0x5E 0x43 0xB2 0xAF 0x88 0x95 0xC6 0xDB 0xFC 0xE1 0x5A 0x47 0x60 0x7D 0x2E 0x33 0x14 0x09 0x7F 0x62 0x45 0x58 0x0B 0x16 0x31 0x2C 0x97 0x8A 0xAD 0xB0 0xE3 0xFE 0xD9 0xC4 """ ) + "\n" ) expected_exit_code = 0 argv = ["table", "8", "0x1D"] with patch("sys.exit") as exit, patch( "sys.stdout", new_callable=io.StringIO ) as stdout: main(argv) stdout.seek(0) actual = stdout.read().split("\n") expected = expected_output.read().split("\n") self.assertEqual(expected, actual) self.assertEqual(exit.call_args, (call(expected_exit_code))) if __name__ == "__main__": unittest.main() python-crc-7.1.0/test/unit/000077500000000000000000000000001471247750100155535ustar00rootroot00000000000000python-crc-7.1.0/test/unit/regression/000077500000000000000000000000001471247750100177335ustar00rootroot00000000000000python-crc-7.1.0/test/unit/regression/test_unstable_digest.py000066400000000000000000000022241471247750100245200ustar00rootroot00000000000000""" This module contains regression tests regarding the issue of unstable return values from the `digest` function. The tests ensure that the `digest` function consistently returns the expected output for given inputs. For more context and a detailed discussion of the problem, refer to the GitHub issue: https://github.com/Nicoretti/crc/issues/151 """ import itertools import pytest import crc def test_original_regression(): reg = crc.Register(crc.Crc8.BLUETOOTH) reg.init() reg.update(b"Hello World!") times = 10 expected = [81 for _ in range(0, times)] actual = [reg.digest() for _ in range(0, times)] assert actual == expected @pytest.mark.parametrize( "configuration,times,expected", [ (config, 10, crc.Calculator(config).checksum(b"Hello World!")) for config in itertools.chain(crc.Crc8, crc.Crc16, crc.Crc32, crc.Crc64) ], ) def test_digest_is_stable(configuration, times, expected): expected = [expected for _ in range(times)] reg = crc.Register(configuration) reg.init() reg.update(b"Hello World!") actual = [reg.digest() for _ in range(times)] assert actual == expected python-crc-7.1.0/test/unit/test_crc.py000066400000000000000000000760561471247750100177510ustar00rootroot00000000000000# Copyright (c) 2018, Nicola Coretti # All rights reserved. import io import string import unittest from collections import namedtuple import pytest from crc._crc import ( Byte, Calculator, Configuration, Crc8, Crc16, Register, TableBasedRegister, _generate_template, create_lookup_table, ) Fixture = namedtuple("Fixture", "data checksum") class TemplateTest(unittest.TestCase): def test_generate_template(self): test_data = ( (1, "0x{:01X}"), (4, "0x{:01X}"), (7, "0x{:02X}"), (8, "0x{:02X}"), (15, "0x{:04X}"), (16, "0x{:04X}"), (31, "0x{:08X}"), (32, "0x{:08X}"), (63, "0x{:016X}"), (64, "0x{:016X}"), ) for width, expected in test_data: with self.subTest(width=width): self.assertEqual(expected, _generate_template(width)) def test_render_template(self): test_data = ( (1, 1, "0x1"), (1, 15, "0xF"), (4, 1, "0x1"), (8, 1, "0x01"), (16, 1, "0x0001"), (32, 1, "0x00000001"), (64, 1, "0x0000000000000001"), (8, 16, "0x10"), (16, 16, "0x0010"), (32, 16, "0x00000010"), (64, 16, "0x0000000000000010"), (16, 0x0840, "0x0840"), (32, 0x0840, "0x00000840"), (64, 0x0840, "0x0000000000000840"), ) for width, value, expected in test_data: with self.subTest(width=width): template = _generate_template(width) self.assertEqual(expected, template.format(value)) class ByteTest(unittest.TestCase): def test_index_operator(self): byte = Byte(129) self.assertEqual(byte[0], 1) self.assertEqual(byte[1], 0) self.assertEqual(byte[2], 0) self.assertEqual(byte[3], 0) self.assertEqual(byte[4], 0) self.assertEqual(byte[5], 0) self.assertEqual(byte[6], 0) self.assertEqual(byte[7], 1) def test_index_operator_raises_error(self): byte = Byte(129) with self.assertRaises(IndexError): byte[-1] with self.assertRaises(IndexError): byte[8] def test_conversion_to_int(self): int_value = 0x01 byte = Byte(int_value) self.assertIsInstance(int(byte), int) self.assertEqual(int(byte), int_value) def test_is_equal_operator(self): for value in range(0, 256): self.assertEqual(Byte(value) == Byte(value), True) self.assertEqual(Byte(value) == Byte(value + 1), False) def test_is_equal_operator_returns_false_for_non_byte_type(self): lhs = Byte(1) rhs = 1 self.assertFalse(lhs == rhs) def test_hash_byte(self): self.assertEqual(hash(1), hash(Byte(1))) def test_adding_two_bytes_without_overflow(self): lhs = Byte(0x02) rhs = Byte(0x10) expected_result = Byte(0x12) self.assertEqual(lhs + rhs, expected_result) def test_adding_an_integer_to_a_byte_without_overflow(self): lhs = 0xF0 rhs = Byte(0x02) expected_result = Byte(lhs + int(rhs)) self.assertEqual(lhs + rhs, expected_result) def test_adding_two_bytes_with_overflow(self): lhs = Byte(0xFA) rhs = Byte(0xFA) expected_result = Byte(0xFA + 0xFA) self.assertEqual(expected_result, lhs + rhs) def test_adding_an_integer_to_a_byte_with_overflow(self): lhs = 0xFA rhs = Byte(0xFA) expected_result = Byte(lhs + int(rhs)) self.assertEqual(lhs + rhs, expected_result) self.assertEqual(lhs + rhs, expected_result) def test_instance_based_add(self): lhs = Byte(0x00) rhs = Byte(0xFA) lhs += rhs self.assertEqual(lhs._value, rhs._value) def test_reversed(self): self.assertEqual(int(Byte(0x80).reversed()), 0x01) self.assertEqual(int(Byte(0x10).reversed()), 0x08) self.assertEqual(int(Byte(0x01).reversed()), 0x80) self.assertEqual(int(Byte(0x11).reversed()), 0x88) self.assertEqual(int(Byte(0xF0).reversed()), 0x0F) self.assertEqual(int(Byte(0x0F).reversed()), 0xF0) class ConfigurationTest(unittest.TestCase): def setUp(self): self.width = 8 self.polynom = 0x07 self.init_value = 0xFF self.final_xor_value = 0xAA self.reverse_input = True self.reverse_output = True def test_init_using_defaults(self): configuration = Configuration(self.width, self.polynom) self.assertEqual(configuration.width, self.width) self.assertEqual(configuration.polynomial, self.polynom) self.assertEqual(configuration.init_value, 0) self.assertEqual(configuration.final_xor_value, 0) self.assertEqual(configuration.reverse_input, False) self.assertEqual(configuration.reverse_output, False) def test_init(self): configuration = Configuration( self.width, self.polynom, self.init_value, self.final_xor_value, self.reverse_input, self.reverse_output, ) self.assertEqual(configuration.width, self.width) self.assertEqual(configuration.polynomial, self.polynom) self.assertEqual(configuration.init_value, self.init_value) self.assertEqual(configuration.final_xor_value, self.final_xor_value) self.assertEqual(configuration.reverse_input, self.reverse_input) self.assertEqual(configuration.reverse_output, self.reverse_output) class RegisterTest(unittest.TestCase): def setUp(self): self._register_types = [Register, TableBasedRegister] def test_crc_register_index_error(self): config = Crc8.CCITT for register_type in self._register_types: crc_register = register_type(config) with self.assertRaises(IndexError): crc_register[10] def test_crc8_ccitt(self): config = Crc8.CCITT for register_type in self._register_types: crc_register = register_type(config) test_suit = [ Fixture(data="", checksum=0x00), Fixture(data=string.digits[1:], checksum=0xF4), Fixture(data=string.digits[1:][::-1], checksum=0x91), Fixture(data=string.digits, checksum=0x45), Fixture(data=string.digits[::-1], checksum=0x6E), ] for test in test_suit: crc_register.init() crc_register.update(test.data.encode("utf-8")) self.assertEqual(test.checksum, crc_register.digest()) def test_crc8_saej1850(self): config = Crc8.SAEJ1850 for register_type in self._register_types: crc_register = register_type(config) test_suit = [ Fixture(data="", checksum=0x00), Fixture(data=string.digits[1:], checksum=0x4B), Fixture(data=string.digits[1:][::-1], checksum=0xD6), Fixture(data=string.digits, checksum=0x74), Fixture(data=string.digits[::-1], checksum=0xC7), ] for test in test_suit: crc_register.init() crc_register.update(test.data.encode("utf-8")) self.assertEqual(test.checksum, crc_register.digest()) def test_crc8_saej1850_zero(self): config = Crc8.SAEJ1850_ZERO for register_type in self._register_types: crc_register = register_type(config) test_suit = [ Fixture(data="", checksum=0x00), Fixture(data=string.digits[1:], checksum=0x37), Fixture(data=string.digits[1:][::-1], checksum=0xAA), Fixture(data=string.digits, checksum=0x8A), Fixture(data=string.digits[::-1], checksum=0x39), ] for test in test_suit: crc_register.init() crc_register.update(test.data.encode("utf-8")) self.assertEqual(test.checksum, crc_register.digest()) def test_crc8_itu(self): config = Crc8.ITU for register_type in self._register_types: crc_register = register_type(config) test_suit = [ Fixture(data="", checksum=0x55), Fixture(data=string.digits[1:], checksum=0xA1), Fixture(data=string.digits[1:][::-1], checksum=0xC4), Fixture(data=string.digits, checksum=0x10), Fixture(data=string.digits[::-1], checksum=0x3B), ] for test in test_suit: crc_register.init() crc_register.update(test.data.encode("utf-8")) self.assertEqual(test.checksum, crc_register.digest()) def test_crc8_rohc(self): config = Crc8.ROHC for register_type in self._register_types: crc_register = register_type(config) test_suit = [ Fixture(data="", checksum=0xFF), Fixture(data=string.digits[1:], checksum=0xD0), Fixture(data=string.digits[1:][::-1], checksum=0x68), Fixture(data=string.digits, checksum=0xE3), Fixture(data=string.digits[::-1], checksum=0x62), ] for test in test_suit: crc_register.init() crc_register.update(test.data.encode("utf-8")) self.assertEqual(test.checksum, crc_register.digest()) def test_crc16_ccitt(self): config = Crc16.XMODEM for register_type in self._register_types: crc_register = register_type(config) test_suit = [ Fixture(data="", checksum=0x0000), Fixture(data=string.digits[1:], checksum=0x31C3), Fixture(data=string.digits[1:][::-1], checksum=0x9CAD), Fixture(data=string.digits, checksum=0x9C58), Fixture(data=string.digits[::-1], checksum=0xD966), ] for test in test_suit: crc_register.init() crc_register.update(test.data.encode("utf-8")) self.assertEqual(test.checksum, crc_register.digest()) def test_crc16_modbus(self): config = Crc16.MODBUS for register_type in self._register_types: crc_register = register_type(config) test_suit = [ Fixture(data="", checksum=0xFFFF), Fixture(data=string.digits[1:], checksum=0x4B37), Fixture(data=string.digits[1:][::-1], checksum=0xC9D3), Fixture(data=string.digits, checksum=0x434D), Fixture(data=string.digits[::-1], checksum=0x8988), ] for test in test_suit: crc_register.init() crc_register.update(test.data.encode("utf-8")) self.assertEqual(test.checksum, crc_register.digest()) def test_cr16_ibm_3740(self): config = Crc16.IBM_3740 for register_type in self._register_types: crc_register = register_type(config) test_suit = [ Fixture(data="", checksum=0xFFFF), Fixture(data=string.digits[1:], checksum=0x29B1), Fixture(data=string.digits[1:][::-1], checksum=0x84DF), Fixture(data=string.digits, checksum=0x7D61), Fixture(data=string.digits[::-1], checksum=0x385F), ] for test in test_suit: crc_register.init() crc_register.update(test.data.encode("utf-8")) self.assertEqual(test.checksum, crc_register.digest()) def test_cr16_kermit(self): config = Crc16.KERMIT for register_type in self._register_types: crc_register = register_type(config) test_suit = [ Fixture(data="", checksum=0x0000), Fixture(data=string.digits[1:], checksum=0x2189), Fixture(data=string.digits[1:][::-1], checksum=0x349F), Fixture(data=string.digits, checksum=0x5F6E), Fixture(data=string.digits[::-1], checksum=0x5DC9), ] for test in test_suit: crc_register.init() crc_register.update(test.data.encode("utf-8")) self.assertEqual(test.checksum, crc_register.digest()) def test_cr16_ibm(self): config = Crc16.IBM for register_type in self._register_types: crc_register = register_type(config) test_suit = [ Fixture(data="", checksum=0x0000), Fixture(data=string.digits[1:], checksum=0xBB3D), Fixture(data=string.digits[1:][::-1], checksum=0x39D9), Fixture(data=string.digits, checksum=0x443D), Fixture(data=string.digits[::-1], checksum=0x8EF8), ] for test in test_suit: crc_register.init() crc_register.update(test.data.encode("utf-8")) self.assertEqual(test.checksum, crc_register.digest()) def test_cr16_maxim(self): config = Crc16.MAXIM for register_type in self._register_types: crc_register = register_type(config) test_suit = [ Fixture(data="", checksum=0xFFFF), Fixture(data=string.digits[1:], checksum=0x44C2), Fixture(data=string.digits[1:][::-1], checksum=0xC626), Fixture(data=string.digits, checksum=0xBBC2), Fixture(data=string.digits[::-1], checksum=0x7107), ] for test in test_suit: crc_register.init() crc_register.update(test.data.encode("utf-8")) self.assertEqual(test.checksum, crc_register.digest()) def test_cr16_usb(self): config = Crc16.USB for register_type in self._register_types: crc_register = register_type(config) test_suit = [ Fixture(data="", checksum=0x0000), Fixture(data=string.digits[1:], checksum=0xB4C8), Fixture(data=string.digits[1:][::-1], checksum=0x362C), Fixture(data=string.digits, checksum=0xBCB2), Fixture(data=string.digits[::-1], checksum=0x7677), ] for test in test_suit: crc_register.init() crc_register.update(test.data.encode("utf-8")) self.assertEqual(test.checksum, crc_register.digest()) def test_cr16_x25(self): config = Crc16.X25 for register_type in self._register_types: crc_register = register_type(config) test_suit = [ Fixture(data="", checksum=0x0000), Fixture(data=string.digits[1:], checksum=0x906E), Fixture(data=string.digits[1:][::-1], checksum=0x8578), Fixture(data=string.digits, checksum=0x3C16), Fixture(data=string.digits[::-1], checksum=0x3EB1), ] for test in test_suit: crc_register.init() crc_register.update(test.data.encode("utf-8")) self.assertEqual(test.checksum, crc_register.digest()) def test_cr16_dnp(self): config = Crc16.DNP for register_type in self._register_types: crc_register = register_type(config) test_suit = [ Fixture(data="", checksum=0xFFFF), Fixture(data=string.digits[1:], checksum=0xEA82), Fixture(data=string.digits[1:][::-1], checksum=0x51A6), Fixture(data=string.digits, checksum=0x6772), Fixture(data=string.digits[::-1], checksum=0x4C77), ] for test in test_suit: crc_register.init() crc_register.update(test.data.encode("utf-8")) self.assertEqual(test.checksum, crc_register.digest()) def test_crc16_with_reflected_input(self): config = Configuration(16, 0x1021, 0, 0, True, False) for register_type in self._register_types: crc_register = register_type(config) test_suit = [ Fixture(data="", checksum=0x0000), Fixture(data=string.digits[1:], checksum=0x9184), Fixture(data=string.digits[1:][::-1], checksum=0xF92C), Fixture(data=string.digits, checksum=0x76FA), Fixture(data=string.digits[::-1], checksum=0x93BA), ] for test in test_suit: crc_register.init() crc_register.update(test.data.encode("utf-8")) self.assertEqual(test.checksum, crc_register.digest()) def test_crc16_with_reflected_output(self): config = Configuration(16, 0x1021, 0, 0, False, True) for register_type in self._register_types: crc_register = register_type(config) test_suit = [ Fixture(data="", checksum=0x0000), Fixture(data=string.digits[1:], checksum=0xC38C), Fixture(data=string.digits[1:][::-1], checksum=0xB539), Fixture(data=string.digits, checksum=0x1A39), Fixture(data=string.digits[::-1], checksum=0x669B), ] for test in test_suit: crc_register.init() crc_register.update(test.data.encode("utf-8")) self.assertEqual(test.checksum, crc_register.digest()) class CalculatorTest(unittest.TestCase): def test_register_based(self): calculator = Calculator(Crc8.CCITT) test_suit = [ Fixture(data="", checksum=0x00), Fixture(data=string.digits[1:], checksum=0xF4), Fixture(data=string.digits[1:][::-1], checksum=0x91), Fixture(data=string.digits, checksum=0x45), Fixture(data=string.digits[::-1], checksum=0x6E), ] for test in test_suit: calculator.verify(test.data.encode("utf-8"), test.checksum) def test_table_based_calculator(self): calculator = Calculator(Crc8.CCITT, True) test_suit = [ Fixture(data="", checksum=0x00), Fixture(data=string.digits[1:], checksum=0xF4), Fixture(data=string.digits[1:][::-1], checksum=0x91), Fixture(data=string.digits, checksum=0x45), Fixture(data=string.digits[::-1], checksum=0x6E), ] for test in test_suit: calculator.verify(test.data.encode("utf-8"), test.checksum) @pytest.mark.parametrize( "config,data,expected", [ (Crc8.CCITT, 0, 0x00), (Crc8.CCITT, b"", 0x00), (Crc8.CCITT, bytearray(), 0x00), (Crc8.CCITT, io.BytesIO(b""), 0x00), (Crc8.CCITT, (b"", b"", b""), 0x00), (Crc8.CCITT, (b"" for i in range(0, 10)), 0x00), (Crc8.CCITT, 97, 32), (Crc8.CCITT, b"123456789", 0xF4), (Crc8.CCITT, bytearray((49, 50, 51, 52, 53, 54, 55, 56, 57)), 0xF4), (Crc8.CCITT, io.BytesIO(b"123456789"), 0xF4), (Crc8.CCITT, (b"12", b"34", b"56", b"78", b"9"), 0xF4), (Crc8.CCITT, (chunk for chunk in (b"12", b"34", b"56", b"78", b"9")), 0xF4), ], ) def test_calculator_with_different_input_types(config, data, expected): calculator = Calculator(config) assert calculator.checksum(data) == expected @pytest.mark.parametrize( "config,data,expected", [ (Crc8.CCITT, 2.00, TypeError), (Crc8.CCITT, "some string", TypeError), ], ) def test_calculator_throws_exception_for_unsupported_input_type(config, data, expected): calculator = Calculator(config) with pytest.raises(expected): calculator.checksum(data) class CreateLookupTableTest(unittest.TestCase): def test_create_crc8_lookup_table(self): # fmt: off tables = { 0x07: [ 0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15, 0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D, 0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65, 0x48, 0x4F, 0x46, 0x41, 0x54, 0x53, 0x5A, 0x5D, 0xE0, 0xE7, 0xEE, 0xE9, 0xFC, 0xFB, 0xF2, 0xF5, 0xD8, 0xDF, 0xD6, 0xD1, 0xC4, 0xC3, 0xCA, 0xCD, 0x90, 0x97, 0x9E, 0x99, 0x8C, 0x8B, 0x82, 0x85, 0xA8, 0xAF, 0xA6, 0xA1, 0xB4, 0xB3, 0xBA, 0xBD, 0xC7, 0xC0, 0xC9, 0xCE, 0xDB, 0xDC, 0xD5, 0xD2, 0xFF, 0xF8, 0xF1, 0xF6, 0xE3, 0xE4, 0xED, 0xEA, 0xB7, 0xB0, 0xB9, 0xBE, 0xAB, 0xAC, 0xA5, 0xA2, 0x8F, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9D, 0x9A, 0x27, 0x20, 0x29, 0x2E, 0x3B, 0x3C, 0x35, 0x32, 0x1F, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0D, 0x0A, 0x57, 0x50, 0x59, 0x5E, 0x4B, 0x4C, 0x45, 0x42, 0x6F, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7D, 0x7A, 0x89, 0x8E, 0x87, 0x80, 0x95, 0x92, 0x9B, 0x9C, 0xB1, 0xB6, 0xBF, 0xB8, 0xAD, 0xAA, 0xA3, 0xA4, 0xF9, 0xFE, 0xF7, 0xF0, 0xE5, 0xE2, 0xEB, 0xEC, 0xC1, 0xC6, 0xCF, 0xC8, 0xDD, 0xDA, 0xD3, 0xD4, 0x69, 0x6E, 0x67, 0x60, 0x75, 0x72, 0x7B, 0x7C, 0x51, 0x56, 0x5F, 0x58, 0x4D, 0x4A, 0x43, 0x44, 0x19, 0x1E, 0x17, 0x10, 0x05, 0x02, 0x0B, 0x0C, 0x21, 0x26, 0x2F, 0x28, 0x3D, 0x3A, 0x33, 0x34, 0x4E, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5C, 0x5B, 0x76, 0x71, 0x78, 0x7F, 0x6A, 0x6D, 0x64, 0x63, 0x3E, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2C, 0x2B, 0x06, 0x01, 0x08, 0x0F, 0x1A, 0x1D, 0x14, 0x13, 0xAE, 0xA9, 0xA0, 0xA7, 0xB2, 0xB5, 0xBC, 0xBB, 0x96, 0x91, 0x98, 0x9F, 0x8A, 0x8D, 0x84, 0x83, 0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC, 0xCB, 0xE6, 0xE1, 0xE8, 0xEF, 0xFA, 0xFD, 0xF4, 0xF3 ], 0x1D: [0x00, 0x1D, 0x3A, 0x27, 0x74, 0x69, 0x4E, 0x53, 0xE8, 0xF5, 0xD2, 0xCF, 0x9C, 0x81, 0xA6, 0xBB, 0xCD, 0xD0, 0xF7, 0xEA, 0xB9, 0xA4, 0x83, 0x9E, 0x25, 0x38, 0x1F, 0x02, 0x51, 0x4C, 0x6B, 0x76, 0x87, 0x9A, 0xBD, 0xA0, 0xF3, 0xEE, 0xC9, 0xD4, 0x6F, 0x72, 0x55, 0x48, 0x1B, 0x06, 0x21, 0x3C, 0x4A, 0x57, 0x70, 0x6D, 0x3E, 0x23, 0x04, 0x19, 0xA2, 0xBF, 0x98, 0x85, 0xD6, 0xCB, 0xEC, 0xF1, 0x13, 0x0E, 0x29, 0x34, 0x67, 0x7A, 0x5D, 0x40, 0xFB, 0xE6, 0xC1, 0xDC, 0x8F, 0x92, 0xB5, 0xA8, 0xDE, 0xC3, 0xE4, 0xF9, 0xAA, 0xB7, 0x90, 0x8D, 0x36, 0x2B, 0x0C, 0x11, 0x42, 0x5F, 0x78, 0x65, 0x94, 0x89, 0xAE, 0xB3, 0xE0, 0xFD, 0xDA, 0xC7, 0x7C, 0x61, 0x46, 0x5B, 0x08, 0x15, 0x32, 0x2F, 0x59, 0x44, 0x63, 0x7E, 0x2D, 0x30, 0x17, 0x0A, 0xB1, 0xAC, 0x8B, 0x96, 0xC5, 0xD8, 0xFF, 0xE2, 0x26, 0x3B, 0x1C, 0x01, 0x52, 0x4F, 0x68, 0x75, 0xCE, 0xD3, 0xF4, 0xE9, 0xBA, 0xA7, 0x80, 0x9D, 0xEB, 0xF6, 0xD1, 0xCC, 0x9F, 0x82, 0xA5, 0xB8, 0x03, 0x1E, 0x39, 0x24, 0x77, 0x6A, 0x4D, 0x50, 0xA1, 0xBC, 0x9B, 0x86, 0xD5, 0xC8, 0xEF, 0xF2, 0x49, 0x54, 0x73, 0x6E, 0x3D, 0x20, 0x07, 0x1A, 0x6C, 0x71, 0x56, 0x4B, 0x18, 0x05, 0x22, 0x3F, 0x84, 0x99, 0xBE, 0xA3, 0xF0, 0xED, 0xCA, 0xD7, 0x35, 0x28, 0x0F, 0x12, 0x41, 0x5C, 0x7B, 0x66, 0xDD, 0xC0, 0xE7, 0xFA, 0xA9, 0xB4, 0x93, 0x8E, 0xF8, 0xE5, 0xC2, 0xDF, 0x8C, 0x91, 0xB6, 0xAB, 0x10, 0x0D, 0x2A, 0x37, 0x64, 0x79, 0x5E, 0x43, 0xB2, 0xAF, 0x88, 0x95, 0xC6, 0xDB, 0xFC, 0xE1, 0x5A, 0x47, 0x60, 0x7D, 0x2E, 0x33, 0x14, 0x09, 0x7F, 0x62, 0x45, 0x58, 0x0B, 0x16, 0x31, 0x2C, 0x97, 0x8A, 0xAD, 0xB0, 0xE3, 0xFE, 0xD9, 0xC4] } # fmt: on for polynom, table in tables.items(): with self.subTest(polynom=polynom, table=table): self.assertEqual(table, create_lookup_table(8, polynom)) def test_create_crc16_lookup_table(self): # fmt: off tables = { 0x1021: [0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0] } # fmt: on for polynom, table in tables.items(): with self.subTest(polynom=polynom, table=table): self.assertEqual(table, create_lookup_table(16, polynom)) def test_create_crc32_lookup_table(self): # fmt: off tables = { 0x4C11DB7: [0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9, 0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005, 0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61, 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD, 0x4C11DB70, 0x48D0C6C7, 0x4593E01E, 0x4152FDA9, 0x5F15ADAC, 0x5BD4B01B, 0x569796C2, 0x52568B75, 0x6A1936C8, 0x6ED82B7F, 0x639B0DA6, 0x675A1011, 0x791D4014, 0x7DDC5DA3, 0x709F7B7A, 0x745E66CD, 0x9823B6E0, 0x9CE2AB57, 0x91A18D8E, 0x95609039, 0x8B27C03C, 0x8FE6DD8B, 0x82A5FB52, 0x8664E6E5, 0xBE2B5B58, 0xBAEA46EF, 0xB7A96036, 0xB3687D81, 0xAD2F2D84, 0xA9EE3033, 0xA4AD16EA, 0xA06C0B5D, 0xD4326D90, 0xD0F37027, 0xDDB056FE, 0xD9714B49, 0xC7361B4C, 0xC3F706FB, 0xCEB42022, 0xCA753D95, 0xF23A8028, 0xF6FB9D9F, 0xFBB8BB46, 0xFF79A6F1, 0xE13EF6F4, 0xE5FFEB43, 0xE8BCCD9A, 0xEC7DD02D, 0x34867077, 0x30476DC0, 0x3D044B19, 0x39C556AE, 0x278206AB, 0x23431B1C, 0x2E003DC5, 0x2AC12072, 0x128E9DCF, 0x164F8078, 0x1B0CA6A1, 0x1FCDBB16, 0x018AEB13, 0x054BF6A4, 0x0808D07D, 0x0CC9CDCA, 0x7897AB07, 0x7C56B6B0, 0x71159069, 0x75D48DDE, 0x6B93DDDB, 0x6F52C06C, 0x6211E6B5, 0x66D0FB02, 0x5E9F46BF, 0x5A5E5B08, 0x571D7DD1, 0x53DC6066, 0x4D9B3063, 0x495A2DD4, 0x44190B0D, 0x40D816BA, 0xACA5C697, 0xA864DB20, 0xA527FDF9, 0xA1E6E04E, 0xBFA1B04B, 0xBB60ADFC, 0xB6238B25, 0xB2E29692, 0x8AAD2B2F, 0x8E6C3698, 0x832F1041, 0x87EE0DF6, 0x99A95DF3, 0x9D684044, 0x902B669D, 0x94EA7B2A, 0xE0B41DE7, 0xE4750050, 0xE9362689, 0xEDF73B3E, 0xF3B06B3B, 0xF771768C, 0xFA325055, 0xFEF34DE2, 0xC6BCF05F, 0xC27DEDE8, 0xCF3ECB31, 0xCBFFD686, 0xD5B88683, 0xD1799B34, 0xDC3ABDED, 0xD8FBA05A, 0x690CE0EE, 0x6DCDFD59, 0x608EDB80, 0x644FC637, 0x7A089632, 0x7EC98B85, 0x738AAD5C, 0x774BB0EB, 0x4F040D56, 0x4BC510E1, 0x46863638, 0x42472B8F, 0x5C007B8A, 0x58C1663D, 0x558240E4, 0x51435D53, 0x251D3B9E, 0x21DC2629, 0x2C9F00F0, 0x285E1D47, 0x36194D42, 0x32D850F5, 0x3F9B762C, 0x3B5A6B9B, 0x0315D626, 0x07D4CB91, 0x0A97ED48, 0x0E56F0FF, 0x1011A0FA, 0x14D0BD4D, 0x19939B94, 0x1D528623, 0xF12F560E, 0xF5EE4BB9, 0xF8AD6D60, 0xFC6C70D7, 0xE22B20D2, 0xE6EA3D65, 0xEBA91BBC, 0xEF68060B, 0xD727BBB6, 0xD3E6A601, 0xDEA580D8, 0xDA649D6F, 0xC423CD6A, 0xC0E2D0DD, 0xCDA1F604, 0xC960EBB3, 0xBD3E8D7E, 0xB9FF90C9, 0xB4BCB610, 0xB07DABA7, 0xAE3AFBA2, 0xAAFBE615, 0xA7B8C0CC, 0xA379DD7B, 0x9B3660C6, 0x9FF77D71, 0x92B45BA8, 0x9675461F, 0x8832161A, 0x8CF30BAD, 0x81B02D74, 0x857130C3, 0x5D8A9099, 0x594B8D2E, 0x5408ABF7, 0x50C9B640, 0x4E8EE645, 0x4A4FFBF2, 0x470CDD2B, 0x43CDC09C, 0x7B827D21, 0x7F436096, 0x7200464F, 0x76C15BF8, 0x68860BFD, 0x6C47164A, 0x61043093, 0x65C52D24, 0x119B4BE9, 0x155A565E, 0x18197087, 0x1CD86D30, 0x029F3D35, 0x065E2082, 0x0B1D065B, 0x0FDC1BEC, 0x3793A651, 0x3352BBE6, 0x3E119D3F, 0x3AD08088, 0x2497D08D, 0x2056CD3A, 0x2D15EBE3, 0x29D4F654, 0xC5A92679, 0xC1683BCE, 0xCC2B1D17, 0xC8EA00A0, 0xD6AD50A5, 0xD26C4D12, 0xDF2F6BCB, 0xDBEE767C, 0xE3A1CBC1, 0xE760D676, 0xEA23F0AF, 0xEEE2ED18, 0xF0A5BD1D, 0xF464A0AA, 0xF9278673, 0xFDE69BC4, 0x89B8FD09, 0x8D79E0BE, 0x803AC667, 0x84FBDBD0, 0x9ABC8BD5, 0x9E7D9662, 0x933EB0BB, 0x97FFAD0C, 0xAFB010B1, 0xAB710D06, 0xA6322BDF, 0xA2F33668, 0xBCB4666D, 0xB8757BDA, 0xB5365D03, 0xB1F740B4] } # fmt: on for polynom, table in tables.items(): with self.subTest(polynom=polynom, table=table): self.assertEqual(table, create_lookup_table(32, polynom)) if __name__ == "__main__": unittest.main()