From e9cbae463871b09c967db16a458b4bc86d2fe9cc Mon Sep 17 00:00:00 2001 From: Klaas Schoute Date: Fri, 24 Feb 2023 02:48:30 +0100 Subject: [PATCH] General refactor/restructure of project (#282) --- .flake8 | 4 - .github/dependabot.yml | 5 - .github/workflows/linting.yaml | 227 +++++--- .github/workflows/release.yaml | 35 +- .github/workflows/requirements.txt | 2 - .github/workflows/tests.yaml | 62 +-- .github/workflows/typing.yaml | 39 +- .gitignore | 3 + .pre-commit-config.yaml | 49 +- examples/__init__.py | 1 + test_output.py => examples/garages.py | 11 +- examples/parking.py | 35 ++ examples/ruff.toml | 6 + odp_amsterdam/const.py | 1 + odp_amsterdam/models.py | 27 +- odp_amsterdam/odp_amsterdam.py | 67 ++- poetry.lock | 711 +++++--------------------- pyproject.toml | 101 ++-- tests/__init__.py | 7 +- tests/ruff.toml | 12 + tests/test_amsterdam.py | 25 +- tests/test_models.py | 35 +- 22 files changed, 510 insertions(+), 955 deletions(-) delete mode 100644 .flake8 delete mode 100644 .github/workflows/requirements.txt create mode 100644 examples/__init__.py rename test_output.py => examples/garages.py (72%) create mode 100644 examples/parking.py create mode 100644 examples/ruff.toml create mode 100644 tests/ruff.toml diff --git a/.flake8 b/.flake8 deleted file mode 100644 index 9e3158a..0000000 --- a/.flake8 +++ /dev/null @@ -1,4 +0,0 @@ -[flake8] -max-line-length = 88 -ignore = D202,W503 -per-file-ignores = tests/*:DAR,S101 diff --git a/.github/dependabot.yml b/.github/dependabot.yml index f20c199..1438cb1 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -6,11 +6,6 @@ updates: schedule: interval: daily time: "02:00" - - package-ecosystem: pip - directory: "/.github/workflows" - schedule: - interval: daily - time: "02:00" - package-ecosystem: "github-actions" directory: "/" schedule: diff --git a/.github/workflows/linting.yaml b/.github/workflows/linting.yaml index 18d7c3b..264bf56 100644 --- a/.github/workflows/linting.yaml +++ b/.github/workflows/linting.yaml @@ -7,97 +7,170 @@ on: pull_request: workflow_dispatch: +env: + DEFAULT_PYTHON: "3.9" + jobs: - precommit: - name: ${{ matrix.name }} + codespell: + name: codespell + runs-on: ubuntu-latest + steps: + - name: โคต๏ธ Check out code from GitHub + uses: actions/checkout@v3 + - name: ๐Ÿ— Set up Poetry + run: pipx install poetry + - name: ๐Ÿ— Set up Python ${{ env.DEFAULT_PYTHON }} + id: python + uses: actions/setup-python@v4 + with: + python-version: ${{ env.DEFAULT_PYTHON }} + cache: 'poetry' + - name: ๐Ÿ— Install workflow dependencies + run: | + poetry config virtualenvs.create true + poetry config virtualenvs.in-project true + - name: ๐Ÿ— Install Python dependencies + run: poetry install --no-interaction + - name: ๐Ÿš€ Check code for common misspellings + run: poetry run pre-commit run codespell --all-files + + ruff: + name: Ruff + runs-on: ubuntu-latest + steps: + - name: โคต๏ธ Check out code from GitHub + uses: actions/checkout@v3 + - name: ๐Ÿ— Set up Poetry + run: pipx install poetry + - name: ๐Ÿ— Set up Python ${{ env.DEFAULT_PYTHON }} + id: python + uses: actions/setup-python@v4 + with: + python-version: ${{ env.DEFAULT_PYTHON }} + cache: 'poetry' + - name: ๐Ÿ— Install workflow dependencies + run: | + poetry config virtualenvs.create true + poetry config virtualenvs.in-project true + - name: ๐Ÿ— Install Python dependencies + run: poetry install --no-interaction + - name: ๐Ÿš€ Run Ruff + run: poetry run ruff . + + black: + name: black + runs-on: ubuntu-latest + steps: + - name: โคต๏ธ Check out code from GitHub + uses: actions/checkout@v3 + - name: ๐Ÿ— Set up Poetry + run: pipx install poetry + - name: ๐Ÿ— Set up Python ${{ env.DEFAULT_PYTHON }} + id: python + uses: actions/setup-python@v4 + with: + python-version: ${{ env.DEFAULT_PYTHON }} + cache: 'poetry' + - name: ๐Ÿ— Install workflow dependencies + run: | + poetry config virtualenvs.create true + poetry config virtualenvs.in-project true + - name: ๐Ÿ— Install Python dependencies + run: poetry install --no-interaction + - name: ๐Ÿš€ Run black on docs + run: poetry run blacken-docs + + pre-commit-hooks: + name: pre-commit-hooks runs-on: ubuntu-latest - if: ${{ github.actor != 'dependabot[bot]' }} - strategy: - matrix: - include: - - id: bandit - name: Check with bandit - - id: black - name: Check code style - - id: blacken-docs - name: Check code style in documentation - - id: check-ast - name: Check Python AST - - id: check-case-conflict - name: Check for case conflicts - - id: check-docstring-first - name: Check docstring is first - - id: check-executables-have-shebangs - name: Check that executables have shebangs - - id: check-json - name: Check JSON files - - id: check-merge-conflict - name: Check for merge conflicts - - id: check-symlinks - name: Check for broken symlinks - - id: check-toml - name: Check TOML files - - id: check-yaml - name: Check YAML files - - id: codespell - name: Check code for common misspellings - - id: debug-statements - name: Debug Statements and imports (Python) - - id: detect-private-key - name: Detect Private Keys - - id: end-of-file-fixer - name: Check End of Files - - id: fix-byte-order-marker - name: Check UTF-8 byte order marker - - id: flake8 - name: Enforcing style guide with flake8 - - id: isort - name: Check imports are sorted - - id: poetry - name: Check pyproject file - - id: pylint - name: Check with pylint - - id: pyupgrade - name: Check for upgradable syntax - - id: trailing-whitespace - name: Trim Trailing Whitespace - - id: vulture - name: Check for unused Python code - - id: yamllint - name: Check YAML style steps: - name: โคต๏ธ Check out code from GitHub uses: actions/checkout@v3 - - name: ๐Ÿ— Set up Python 3.9 + - name: ๐Ÿ— Set up Poetry + run: pipx install poetry + - name: ๐Ÿ— Set up Python ${{ env.DEFAULT_PYTHON }} id: python uses: actions/setup-python@v4 with: - python-version: 3.9 - - name: ๐Ÿ— Get pip cache dir - id: pip-cache + python-version: ${{ env.DEFAULT_PYTHON }} + cache: 'poetry' + - name: ๐Ÿ— Install workflow dependencies run: | - echo "dir=$(pip cache dir)" >> $GITHUB_OUTPUT - - name: โคต๏ธ Restore cached Python PIP packages - uses: actions/cache@v3 + poetry config virtualenvs.create true + poetry config virtualenvs.in-project true + - name: ๐Ÿ— Install Python dependencies + run: poetry install --no-interaction + - name: ๐Ÿš€ Check Python AST + run: poetry run pre-commit run check-ast --all-files + - name: ๐Ÿš€ Check for case conflicts + run: poetry run pre-commit run check-case-conflict --all-files + - name: ๐Ÿš€ Check docstring is first + run: poetry run pre-commit run check-docstring-first --all-files + - name: ๐Ÿš€ Check that executables have shebangs + run: poetry run pre-commit run check-executables-have-shebangs --all-files + - name: ๐Ÿš€ Check JSON files + run: poetry run pre-commit run check-json --all-files + - name: ๐Ÿš€ Check for merge conflicts + run: poetry run pre-commit run check-merge-conflict --all-files + - name: ๐Ÿš€ Check for broken symlinks + run: poetry run pre-commit run check-symlinks --all-files + - name: ๐Ÿš€ Check TOML files + run: poetry run pre-commit run check-toml --all-files + - name: ๐Ÿš€ Check XML files + run: poetry run pre-commit run check-xml --all-files + - name: ๐Ÿš€ Check YAML files + run: poetry run pre-commit run check-yaml --all-files + - name: ๐Ÿš€ Check YAML files + run: poetry run pre-commit run check-yaml --all-files + - name: ๐Ÿš€ Detect Private Keys + run: poetry run pre-commit run detect-private-key --all-files + - name: ๐Ÿš€ Check End of Files + run: poetry run pre-commit run end-of-file-fixer --all-files + - name: ๐Ÿš€ Trim Trailing Whitespace + run: poetry run pre-commit run trailing-whitespace --all-files + + pylint: + name: pylint + runs-on: ubuntu-latest + steps: + - name: โคต๏ธ Check out code from GitHub + uses: actions/checkout@v3 + - name: ๐Ÿ— Set up Poetry + run: pipx install poetry + - name: ๐Ÿ— Set up Python ${{ env.DEFAULT_PYTHON }} + id: python + uses: actions/setup-python@v4 with: - path: ${{ steps.pip-cache.outputs.dir }} - key: pip-${{ runner.os }}-v2-${{ steps.python.outputs.python-version }}-${{ hashFiles('.github/workflows/requirements.txt') }} - restore-keys: | - pip-${{ runner.os }}-v2-${{ steps.python.outputs.python-version }}- + python-version: ${{ env.DEFAULT_PYTHON }} + cache: 'poetry' - name: ๐Ÿ— Install workflow dependencies run: | - pip install -r .github/workflows/requirements.txt poetry config virtualenvs.create true poetry config virtualenvs.in-project true - - name: โคต๏ธ Restore cached Python virtual environment - id: cached-poetry-dependencies - uses: actions/cache@v3 + - name: ๐Ÿ— Install Python dependencies + run: poetry install --no-interaction + - name: ๐Ÿš€ Run pylint + run: poetry run pre-commit run pylint --all-files + + yamllint: + name: yamllint + runs-on: ubuntu-latest + steps: + - name: โคต๏ธ Check out code from GitHub + uses: actions/checkout@v3 + - name: ๐Ÿ— Set up Poetry + run: pipx install poetry + - name: ๐Ÿ— Set up Python ${{ env.DEFAULT_PYTHON }} + id: python + uses: actions/setup-python@v4 with: - path: .venv - key: >- - venv-${{ runner.os }}-v2-${{ steps.python.outputs.python-version }}-${{ hashFiles('poetry.lock') }} - venv-${{ runner.os }}-v2-${{ steps.python.outputs.python-version }}- + python-version: ${{ env.DEFAULT_PYTHON }} + cache: 'poetry' + - name: ๐Ÿ— Install workflow dependencies + run: | + poetry config virtualenvs.create true + poetry config virtualenvs.in-project true - name: ๐Ÿ— Install Python dependencies run: poetry install --no-interaction - - name: ๐Ÿš€ Run pre-commit for ${{ matrix.id }} - run: poetry run pre-commit run ${{ matrix.id }} --all-files + - name: ๐Ÿš€ Run yamllint + run: poetry run yamllint . diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index f1d4d41..e9c57bf 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -4,44 +4,31 @@ name: Release # yamllint disable-line rule:truthy on: release: - types: [published] + types: + - published + +env: + DEFAULT_PYTHON: "3.9" jobs: release: - name: ๐Ÿš€ Releasing to PyPi + name: Releasing to PyPi runs-on: ubuntu-latest steps: - name: โคต๏ธ Check out code from GitHub uses: actions/checkout@v3 - - name: ๐Ÿ— Set up Python 3.9 + - name: ๐Ÿ— Set up Poetry + run: pipx install poetry + - name: ๐Ÿ— Set up Python ${{ env.DEFAULT_PYTHON }} id: python uses: actions/setup-python@v4 with: - python-version: 3.9 - - name: ๐Ÿ— Get pip cache dir - id: pip-cache - run: | - echo "dir=$(pip cache dir)" >> $GITHUB_OUTPUT - - name: โคต๏ธ Restore cached Python PIP packages - uses: actions/cache@v3 - with: - path: ${{ steps.pip-cache.outputs.dir }} - key: pip-${{ runner.os }}-v2-${{ steps.python.outputs.python-version }}-${{ hashFiles('.github/workflows/requirements.txt') }} - restore-keys: | - pip-${{ runner.os }}-v2-${{ steps.python.outputs.python-version }}- + python-version: ${{ env.DEFAULT_PYTHON }} + cache: 'poetry' - name: ๐Ÿ— Install workflow dependencies run: | - pip install -r .github/workflows/requirements.txt poetry config virtualenvs.create true poetry config virtualenvs.in-project true - - name: โคต๏ธ Restore cached Python virtual environment - id: cached-poetry-dependencies - uses: actions/cache@v3 - with: - path: .venv - key: >- - venv-${{ runner.os }}-v2-${{ steps.python.outputs.python-version }}-${{ hashFiles('poetry.lock') }} - venv-${{ runner.os }}-v2-${{ steps.python.outputs.python-version }}- - name: ๐Ÿ— Install dependencies run: poetry install --no-interaction - name: ๐Ÿ— Set package version diff --git a/.github/workflows/requirements.txt b/.github/workflows/requirements.txt deleted file mode 100644 index 6de83e2..0000000 --- a/.github/workflows/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -pip==23.0 -poetry==1.3.2 diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 3980ef9..0da8bdc 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -7,47 +7,32 @@ on: pull_request: workflow_dispatch: +env: + DEFAULT_PYTHON: "3.9" + jobs: pytest: - name: Python ${{ matrix.python }} on ${{ matrix.os }} - runs-on: ${{ matrix.os }}-latest + name: Python ${{ matrix.python }} + runs-on: ubuntu-latest strategy: fail-fast: false matrix: - os: [ubuntu, macos] python: ["3.9", "3.10", "3.11"] steps: - name: โคต๏ธ Check out code from GitHub uses: actions/checkout@v3 + - name: ๐Ÿ— Set up Poetry + run: pipx install poetry - name: ๐Ÿ— Set up Python ${{ matrix.python }} id: python uses: actions/setup-python@v4 with: python-version: ${{ matrix.python }} - - name: ๐Ÿ— Get pip cache dir - id: pip-cache - run: | - echo "dir=$(pip cache dir)" >> $GITHUB_OUTPUT - - name: โคต๏ธ Restore cached Python PIP packages - uses: actions/cache@v3 - with: - path: ${{ steps.pip-cache.outputs.dir }} - key: pip-${{ runner.os }}-v2-${{ steps.python.outputs.python-version }}-${{ hashFiles('.github/workflows/requirements.txt') }} - restore-keys: | - pip-${{ runner.os }}-v2-${{ steps.python.outputs.python-version }}- + cache: 'poetry' - name: ๐Ÿ— Install workflow dependencies run: | - pip install -r .github/workflows/requirements.txt poetry config virtualenvs.create true poetry config virtualenvs.in-project true - - name: โคต๏ธ Restore cached Python virtual environment - id: cached-poetry-dependencies - uses: actions/cache@v3 - with: - path: .venv - key: venv-${{ runner.os }}-v2-${{ steps.python.outputs.python-version }}-${{ hashFiles('poetry.lock') }} - restore-keys: | - venv-${{ runner.os }}-v2-${{ steps.python.outputs.python-version }}- - name: ๐Ÿ— Install dependencies run: poetry install --no-interaction - name: ๐Ÿš€ Run pytest @@ -55,7 +40,7 @@ jobs: - name: โฌ†๏ธ Upload coverage artifact uses: actions/upload-artifact@v3 with: - name: coverage-${{ matrix.python }}-${{ matrix.os }} + name: coverage-${{ matrix.python }} path: .coverage coverage: @@ -64,37 +49,22 @@ jobs: steps: - name: โคต๏ธ Check out code from GitHub uses: actions/checkout@v3 + with: + fetch-depth: 0 - name: โฌ‡๏ธ Download coverage data uses: actions/download-artifact@v3 - - name: ๐Ÿ— Set up Python 3.9 + - name: ๐Ÿ— Set up Poetry + run: pipx install poetry + - name: ๐Ÿ— Set up Python ${{ env.DEFAULT_PYTHON }} id: python uses: actions/setup-python@v4 with: - python-version: 3.9 - - name: ๐Ÿ— Get pip cache dir - id: pip-cache - run: | - echo "dir=$(pip cache dir)" >> $GITHUB_OUTPUT - - name: โคต๏ธ Restore cached Python PIP packages - uses: actions/cache@v3 - with: - path: ${{ steps.pip-cache.outputs.dir }} - key: pip-${{ runner.os }}-v2-${{ steps.python.outputs.python-version }}-${{ hashFiles('.github/workflows/requirements.txt') }} - restore-keys: | - pip-${{ runner.os }}-v2-${{ steps.python.outputs.python-version }}- + python-version: ${{ env.DEFAULT_PYTHON }} + cache: 'poetry' - name: ๐Ÿ— Install workflow dependencies run: | - pip install -r .github/workflows/requirements.txt poetry config virtualenvs.create true poetry config virtualenvs.in-project true - - name: โคต๏ธ Restore cached Python virtual environment - id: cached-poetry-dependencies - uses: actions/cache@v3 - with: - path: .venv - key: >- - venv-${{ runner.os }}-v2-${{ steps.python.outputs.python-version }}-${{ hashFiles('poetry.lock') }} - venv-${{ runner.os }}-v2-${{ steps.python.outputs.python-version }}- - name: ๐Ÿ— Install dependencies run: poetry install --no-interaction - name: ๐Ÿš€ Process coverage results diff --git a/.github/workflows/typing.yaml b/.github/workflows/typing.yaml index ac03ff8..c23d1dc 100644 --- a/.github/workflows/typing.yaml +++ b/.github/workflows/typing.yaml @@ -7,48 +7,29 @@ on: pull_request: workflow_dispatch: +env: + DEFAULT_PYTHON: "3.9" + jobs: mypy: - name: mypy on Python ${{ matrix.python }} + name: mypy runs-on: ubuntu-latest - if: ${{ github.actor != 'dependabot[bot]' }} - strategy: - fail-fast: false - matrix: - python: ["3.9", "3.10", "3.11"] steps: - name: โคต๏ธ Check out code from GitHub uses: actions/checkout@v3 - - name: ๐Ÿ— Set up Python ${{ matrix.python }} + - name: ๐Ÿ— Set up Poetry + run: pipx install poetry + - name: ๐Ÿ— Set up Python ${{ env.DEFAULT_PYTHON }} id: python uses: actions/setup-python@v4 with: - python-version: ${{ matrix.python }} - - name: ๐Ÿ— Get pip cache dir - id: pip-cache - run: | - echo "dir=$(pip cache dir)" >> $GITHUB_OUTPUT - - name: โคต๏ธ Restore cached Python PIP packages - uses: actions/cache@v3 - with: - path: ${{ steps.pip-cache.outputs.dir }} - key: pip-${{ runner.os }}-v2-${{ steps.python.outputs.python-version }}-${{ hashFiles('.github/workflows/requirements.txt') }} - restore-keys: | - pip-${{ runner.os }}-v2-${{ steps.python.outputs.python-version }}- + python-version: ${{ env.DEFAULT_PYTHON }} + cache: 'poetry' - name: ๐Ÿ— Install workflow dependencies run: | - pip install -r .github/workflows/requirements.txt poetry config virtualenvs.create true poetry config virtualenvs.in-project true - - name: โคต๏ธ Restore cached Python virtual environment - id: cached-poetry-dependencies - uses: actions/cache@v3 - with: - path: .venv - key: venv-${{ runner.os }}-v2-${{ steps.python.outputs.python-version }}-${{ hashFiles('poetry.lock') }} - restore-keys: | - venv-${{ runner.os }}-v2-${{ steps.python.outputs.python-version }}- - name: ๐Ÿ— Install dependencies run: poetry install --no-interaction - name: ๐Ÿš€ Run mypy - run: poetry run mypy odp_amsterdam tests + run: poetry run mypy examples odp_amsterdam tests diff --git a/.gitignore b/.gitignore index 715b2e8..e0859fb 100644 --- a/.gitignore +++ b/.gitignore @@ -120,6 +120,9 @@ venv.bak/ # Visual Studio Code .vscode +# ruff +.ruff_cache + # Pyre type checker .pyre/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index af417f3..b6bd5fb 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,13 +2,13 @@ repos: - repo: local hooks: - - id: bandit - name: ๐ŸŽฐ Checking using bandit + - id: ruff + name: ๐Ÿถ Ruff language: system types: [python] - entry: poetry run bandit - files: ^odp_amsterdam/ + entry: poetry run ruff --fix require_serial: true + stages: [commit, push, manual] - id: black name: โ˜•๏ธ Format using black language: system @@ -61,6 +61,11 @@ repos: language: system types: [toml] entry: poetry run check-toml + - id: check-xml + name: โœ… Check XML files + entry: check-xml + language: system + types: [xml] - id: check-yaml name: โœ… Check YAML files language: system @@ -73,11 +78,6 @@ repos: exclude: ^poetry\.lock$ entry: poetry run codespell args: [--ignore-words=.codespell-ignore] - - id: debug-statements - name: ๐Ÿชต Debug Statements and imports (Python) - language: system - types: [python] - entry: poetry run debug-statement-hook - id: detect-private-key name: ๐Ÿ•ต๏ธ Detect Private Keys language: system @@ -89,22 +89,6 @@ repos: types: [text] entry: poetry run end-of-file-fixer stages: [commit, push, manual] - - id: fix-byte-order-marker - name: ๐Ÿš Fix UTF-8 byte order marker - language: system - types: [text] - entry: poetry run fix-byte-order-marker - - id: flake8 - name: ๐Ÿ‘” Enforcing style guide with flake8 - language: system - types: [python] - entry: poetry run flake8 - require_serial: true - - id: isort - name: ๐Ÿ”€ Sort all imports with isort - language: system - types: [python] - entry: poetry run isort - id: mypy name: ๐Ÿ†Ž Static type checking using mypy language: system @@ -135,27 +119,14 @@ repos: types: [python] entry: poetry run pytest pass_filenames: false - - id: pyupgrade - name: ๐Ÿ†™ Checking for upgradable syntax with pyupgrade - language: system - types: [python] - entry: poetry run pyupgrade - args: [--py39-plus, --keep-runtime-typing] - id: trailing-whitespace name: โœ„ Trim Trailing Whitespace language: system types: [text] entry: poetry run trailing-whitespace-fixer stages: [commit, push, manual] - - id: vulture - name: ๐Ÿ” Find unused Python code with Vulture - language: system - types: [python] - entry: poetry run vulture - pass_filenames: false - require_serial: true - id: yamllint - name: ๐ŸŽ— Check YAML files with yamllint + name: ๐ŸŽ— Check YAML files with yamllint language: system types: [yaml] entry: poetry run yamllint diff --git a/examples/__init__.py b/examples/__init__.py new file mode 100644 index 0000000..9fee590 --- /dev/null +++ b/examples/__init__.py @@ -0,0 +1 @@ +"""Examples for this library.""" diff --git a/test_output.py b/examples/garages.py similarity index 72% rename from test_output.py rename to examples/garages.py index 7a30db8..2a68d13 100644 --- a/test_output.py +++ b/examples/garages.py @@ -11,12 +11,11 @@ async def main() -> None: async with ODPAmsterdam() as client: count: int - garages: list[Garage] = await client.all_garages() - locations = await client.locations(limit=10, parking_type="E6a") - garage = await client.garage(garage_id="99b77fc5-a237-4ba0-abe4-b9a3886aa471") + garages = await client.all_garages() + garage: Garage = await client.garage( + garage_id="99b77fc5-a237-4ba0-abe4-b9a3886aa471", + ) - print(locations) - print() print(garage) print() @@ -31,7 +30,7 @@ async def main() -> None: num_values = len(set(unique_values)) print("__________________________") - print(f"Total locations found: {count}") + print(f"Total garages found: {count}") print(f"Unique ID values: {num_values}") diff --git a/examples/parking.py b/examples/parking.py new file mode 100644 index 0000000..6f1ce7b --- /dev/null +++ b/examples/parking.py @@ -0,0 +1,35 @@ +# pylint: disable=W0621 +"""Asynchronous Python client providing Open Data information of Amsterdam.""" + +import asyncio + +from odp_amsterdam import ODPAmsterdam + + +async def main() -> None: + """Show example on using the ODP Amsterdam API client.""" + async with ODPAmsterdam() as client: + count: int + + locations = await client.locations( + limit=10, + parking_type="E6a", + ) + + for index, item in enumerate(locations, 1): + count = index + print(item) + + # # Count unique id's in disabled_parkings + unique_values: list[str] = [] + for location in locations: + unique_values.append(location.spot_id) + num_values = len(set(unique_values)) + + print("__________________________") + print(f"Total locations found: {count}") + print(f"Unique ID values: {num_values}") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/examples/ruff.toml b/examples/ruff.toml new file mode 100644 index 0000000..2eb42d9 --- /dev/null +++ b/examples/ruff.toml @@ -0,0 +1,6 @@ +# This extend our general Ruff rules specifically for the examples +extend = "../pyproject.toml" + +extend-ignore = [ + "T201", # Allow the use of print() in examples +] diff --git a/odp_amsterdam/const.py b/odp_amsterdam/const.py index f5857a5..4510f02 100644 --- a/odp_amsterdam/const.py +++ b/odp_amsterdam/const.py @@ -20,6 +20,7 @@ " P21", " P22", " P23", + " P24", ] FILTER_UNKNOWN: list[str] = [ diff --git a/odp_amsterdam/models.py b/odp_amsterdam/models.py index 13901db..2330f0d 100644 --- a/odp_amsterdam/models.py +++ b/odp_amsterdam/models.py @@ -22,13 +22,14 @@ class ParkingSpot: coordinates: list[float] @classmethod - def from_json(cls, data: dict[str, Any]) -> ParkingSpot: + def from_json(cls: type[ParkingSpot], data: dict[str, Any]) -> ParkingSpot: """Return ParkingSpot object from a dictionary. Args: data: The JSON data from the API. - Returns: + Returns + ------- An ParkingSpot object. """ attr = data["properties"] @@ -60,13 +61,14 @@ class Garage: latitude: float @classmethod - def from_json(cls, data: dict[str, Any]) -> Garage: + def from_json(cls: type[Garage], data: dict[str, Any]) -> Garage: """Return Garage object from a dictionary. Args: data: The JSON data from the API. - Returns: + Returns + ------- An Garage object. """ latitude, longitude = split_coordinates(str(data["geometry"]["coordinates"])) @@ -84,7 +86,8 @@ def from_json(cls, data: dict[str, Any]) -> Garage: if attr["LongCapacity"] == "" else int(attr["LongCapacity"]), availability_pct=calculate_pct( - attr.get("FreeSpaceShort"), attr.get("ShortCapacity") + attr.get("FreeSpaceShort"), + attr.get("ShortCapacity"), ), longitude=longitude, latitude=latitude, @@ -97,10 +100,10 @@ def split_coordinates(data: str) -> tuple[float, float]: Args: data: The data to be split. - Returns: + Returns + ------- The coordinates. """ - longitude, latitude = data.split(", ") longitude = longitude.replace("[", "") latitude = latitude.replace("]", "") @@ -114,7 +117,8 @@ def calculate_pct(current: int, total: int) -> float | None: current: The current amount of free parking spots. total: The total amount of parking spots. - Returns: + Returns + ------- The percentage of free parking spots. """ try: @@ -129,10 +133,10 @@ def correct_name(name: str) -> str: Args: name: The name of the parking garage. - Returns: + Returns + ------- The corrected name. """ - for value in FILTER_NAMES: # Remove parts from name string. name = name.replace(value, "") @@ -149,7 +153,8 @@ def filter_unknown(data: str) -> str | None: Args: data: The data to be filtered. - Returns: + Returns + ------- The filtered data. """ if data in FILTER_UNKNOWN: diff --git a/odp_amsterdam/odp_amsterdam.py b/odp_amsterdam/odp_amsterdam.py index 40b94d0..5c86036 100644 --- a/odp_amsterdam/odp_amsterdam.py +++ b/odp_amsterdam/odp_amsterdam.py @@ -8,9 +8,9 @@ from importlib import metadata from typing import Any -import aiohttp import async_timeout -from aiohttp import hdrs +from aiohttp import ClientError, ClientSession +from aiohttp.hdrs import METH_GET from yarl import URL from .const import FILTER_OUT @@ -27,7 +27,7 @@ class ODPAmsterdam: """Main class for handling data fetchting from Open Data Platform of Amsterdam.""" request_timeout: float = 15.0 - session: aiohttp.client.ClientSession | None = None + session: ClientSession | None = None _close_session: bool = False @@ -35,7 +35,7 @@ async def _request( self, uri: str, *, - method: str = hdrs.METH_GET, + method: str = METH_GET, params: dict[str, Any] | None = None, ) -> Any: """Handle a request to the Open Data Platform API of Amsterdam. @@ -45,11 +45,13 @@ async def _request( method: HTTP method to use, for example, 'GET' params: Extra options to improve or limit the response. - Returns: + Returns + ------- A Python dictionary (text) with the response from the Open Data Platform API of Amsterdam. - Raises: + Raises + ------ ODPAmsterdamConnectionError: An error occurred while communicating with the Open Data Platform API of Amsterdam. ODPAmsterdamError: Received an unexpected response from @@ -57,7 +59,7 @@ async def _request( """ version = metadata.version(__package__) url = URL.build(scheme="https", host="api.data.amsterdam.nl", path="/").join( - URL(uri) + URL(uri), ) headers = { @@ -66,7 +68,7 @@ async def _request( } if self.session is None: - self.session = aiohttp.ClientSession() + self.session = ClientSession() self._close_session = True try: @@ -80,27 +82,32 @@ async def _request( ) response.raise_for_status() except asyncio.TimeoutError as exception: + msg = "Timeout occurred while connecting to the Open Data Platform API." raise ODPAmsterdamConnectionError( - "Timeout occurred while connecting to the Open Data Platform API.", + msg, ) from exception - except (aiohttp.ClientError, socket.gaierror) as exception: + except (ClientError, socket.gaierror) as exception: + msg = "Error occurred while communicating with the Open Data Platform API." raise ODPAmsterdamConnectionError( - "Error occurred while communicating with the Open Data Platform API." + msg, ) from exception types = ["application/json", "text/plain", "application/geo+json"] content_type = response.headers.get("Content-Type", "") if not any(item in content_type for item in types): text = await response.text() + msg = "Unexpected content type response from the Open Data Platform API" raise ODPAmsterdamError( - "Unexpected content type response from the Open Data Platform API", + msg, {"Content-Type": content_type, "response": text}, ) return json.loads(await response.text()) async def locations( - self, limit: int = 10, parking_type: str = "" + self, + limit: int = 10, + parking_type: str = "", ) -> list[ParkingSpot]: """Get all the parking locations. @@ -108,7 +115,8 @@ async def locations( limit: The number of results to return. parking_type: The selected parking type number. - Returns: + Returns + ------- A list of ParkingSpot objects. """ results: list[ParkingSpot] = [] @@ -124,10 +132,12 @@ async def locations( async def all_garages(self) -> list[Garage]: """Get all the garages. - Returns: + Returns + ------- A list of Garage objects. - Raises: + Raises + ------ ODPAmsterdamError: If the data is not valid. """ results: list[Garage] = [] @@ -138,7 +148,8 @@ async def all_garages(self) -> list[Garage]: if not any(x in item["properties"]["Name"] for x in FILTER_OUT): results.append(Garage.from_json(item)) except KeyError as exception: - raise ODPAmsterdamError(f"Got wrong data: {item}") from exception + msg = f"Got wrong data from the API: {item}" + raise ODPAmsterdamError(msg) from exception return results async def garage(self, garage_id: str) -> Garage: @@ -147,20 +158,20 @@ async def garage(self, garage_id: str) -> Garage: Args: garage_id: The ID of the garage. - Returns: + Returns + ------- A garage object. - Raises: + Raises + ------ ODPAmsterdamResultsError: When no results are found. """ data = await self._request("dcatd/datasets/9ORkef6T-aU29g/purls/1") - try: - result = [item for item in data["features"] if item["Id"] in garage_id] - return Garage.from_json(result[0]) - except IndexError as exception: - raise ODPAmsterdamResultsError( - f"No garage was found with id ({garage_id})" - ) from exception + for item in data["features"]: + if item["Id"] == garage_id: + return Garage.from_json(item) + msg = f"No garage was found with id - {garage_id}" + raise ODPAmsterdamResultsError(msg) async def close(self) -> None: """Close open client session.""" @@ -170,7 +181,8 @@ async def close(self) -> None: async def __aenter__(self) -> ODPAmsterdam: """Async enter. - Returns: + Returns + ------- The Open Data Platform Amsterdam object. """ return self @@ -179,6 +191,7 @@ async def __aexit__(self, *_exc_info: str) -> None: """Async exit. Args: + ---- _exc_info: Exec type. """ await self.close() diff --git a/poetry.lock b/poetry.lock index 648ab43..34ca8bc 100644 --- a/poetry.lock +++ b/poetry.lock @@ -140,18 +140,6 @@ files = [ aiohttp = ">=3.1.0,<4.0.0" pytest-asyncio = "*" -[[package]] -name = "astor" -version = "0.8.1" -description = "Read/rewrite/write Python ASTs" -category = "dev" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" -files = [ - {file = "astor-0.8.1-py2.py3-none-any.whl", hash = "sha256:070a54e890cefb5b3739d19f30f5a5ec840ffc9c50ffa7d23cc9fc1a38ebbfc5"}, - {file = "astor-0.8.1.tar.gz", hash = "sha256:6a6effda93f4e1ce9f618779b2dd1d9d84f1e32812c23a29b3fff6fd7f63fa5e"}, -] - [[package]] name = "astroid" version = "2.14.2" @@ -202,29 +190,6 @@ docs = ["furo", "sphinx", "sphinx-notfound-page", "zope.interface"] tests = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "zope.interface"] tests-no-zope = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins"] -[[package]] -name = "bandit" -version = "1.7.4" -description = "Security oriented static analyser for python code." -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "bandit-1.7.4-py3-none-any.whl", hash = "sha256:412d3f259dab4077d0e7f0c11f50f650cc7d10db905d98f6520a95a18049658a"}, - {file = "bandit-1.7.4.tar.gz", hash = "sha256:2d63a8c573417bae338962d4b9b06fbc6080f74ecd955a092849e1e65c717bd2"}, -] - -[package.dependencies] -colorama = {version = ">=0.3.9", markers = "platform_system == \"Windows\""} -GitPython = ">=1.0.1" -PyYAML = ">=5.3.1" -stevedore = ">=1.20.0" - -[package.extras] -test = ["beautifulsoup4 (>=4.8.0)", "coverage (>=4.5.4)", "fixtures (>=3.0.0)", "flake8 (>=4.0.0)", "pylint (==1.9.4)", "stestr (>=2.5.0)", "testscenarios (>=0.5.0)", "testtools (>=2.3.0)", "toml"] -toml = ["toml"] -yaml = ["PyYAML"] - [[package]] name = "black" version = "22.12.0" @@ -276,18 +241,6 @@ files = [ [package.dependencies] black = ">=22.1.0" -[[package]] -name = "certifi" -version = "2022.12.7" -description = "Python package for providing Mozilla's CA Bundle." -category = "dev" -optional = false -python-versions = ">=3.6" -files = [ - {file = "certifi-2022.12.7-py3-none-any.whl", hash = "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18"}, - {file = "certifi-2022.12.7.tar.gz", hash = "sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3"}, -] - [[package]] name = "cfgv" version = "3.3.1" @@ -360,83 +313,87 @@ files = [ ] [[package]] -name = "coverage" -version = "6.5.0" -description = "Code coverage measurement for Python" +name = "covdefaults" +version = "2.2.2" +description = "A coverage plugin to provide sensible default settings" category = "dev" 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"}, + {file = "covdefaults-2.2.2-py2.py3-none-any.whl", hash = "sha256:10c193cbf290675961a09166d7cdea8a783655e04009f5493d50685fe6ec82f3"}, + {file = "covdefaults-2.2.2.tar.gz", hash = "sha256:e543862ee0347769b47b27fa586d690e6b91587a3dcaaf8552fcfb1fac03d061"}, ] [package.dependencies] -tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""} - -[package.extras] -toml = ["tomli"] +coverage = ">=6.0.2" [[package]] -name = "darglint" -version = "1.8.1" -description = "A utility for ensuring Google-style docstrings stay up to date with the source code." +name = "coverage" +version = "7.2.0" +description = "Code coverage measurement for Python" category = "dev" optional = false -python-versions = ">=3.6,<4.0" +python-versions = ">=3.7" files = [ - {file = "darglint-1.8.1-py3-none-any.whl", hash = "sha256:5ae11c259c17b0701618a20c3da343a3eb98b3bc4b5a83d31cdd94f5ebdced8d"}, - {file = "darglint-1.8.1.tar.gz", hash = "sha256:080d5106df149b199822e7ee7deb9c012b49891538f14a11be681044f0bb20da"}, + {file = "coverage-7.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:90e7a4cbbb7b1916937d380beb1315b12957b8e895d7d9fb032e2038ac367525"}, + {file = "coverage-7.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:34d7211be69b215ad92298a962b2cd5a4ef4b17c7871d85e15d3d1b6dc8d8c96"}, + {file = "coverage-7.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:971b49dbf713044c3e5f6451b39f65615d4d1c1d9a19948fa0f41b0245a98765"}, + {file = "coverage-7.2.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f0557289260125a6c453ad5673ba79e5b6841d9a20c9e101f758bfbedf928a77"}, + {file = "coverage-7.2.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:049806ae2df69468c130f04f0fab4212c46b34ba5590296281423bb1ae379df2"}, + {file = "coverage-7.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:875b03d92ac939fbfa8ae74a35b2c468fc4f070f613d5b1692f9980099a3a210"}, + {file = "coverage-7.2.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:c160e34e388277f10c50dc2c7b5e78abe6d07357d9fe7fcb2f3c156713fd647e"}, + {file = "coverage-7.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:32e6a730fd18b2556716039ab93278ccebbefa1af81e6aa0c8dba888cf659e6e"}, + {file = "coverage-7.2.0-cp310-cp310-win32.whl", hash = "sha256:f3ff4205aff999164834792a3949f82435bc7c7655c849226d5836c3242d7451"}, + {file = "coverage-7.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:93db11da6e728587e943dff8ae1b739002311f035831b6ecdb15e308224a4247"}, + {file = "coverage-7.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cd38140b56538855d3d5722c6d1b752b35237e7ea3f360047ce57f3fade82d98"}, + {file = "coverage-7.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9dbb21561b0e04acabe62d2c274f02df0d715e8769485353ddf3cf84727e31ce"}, + {file = "coverage-7.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:171dd3aa71a49274a7e4fc26f5bc167bfae5a4421a668bc074e21a0522a0af4b"}, + {file = "coverage-7.2.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4655ecd813f4ba44857af3e9cffd133ab409774e9d2a7d8fdaf4fdfd2941b789"}, + {file = "coverage-7.2.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1856a8c4aa77eb7ca0d42c996d0ca395ecafae658c1432b9da4528c429f2575c"}, + {file = "coverage-7.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bd67df6b48db18c10790635060858e2ea4109601e84a1e9bfdd92e898dc7dc79"}, + {file = "coverage-7.2.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:2d7daf3da9c7e0ed742b3e6b4de6cc464552e787b8a6449d16517b31bbdaddf5"}, + {file = "coverage-7.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:bf9e02bc3dee792b9d145af30db8686f328e781bd212fdef499db5e9e4dd8377"}, + {file = "coverage-7.2.0-cp311-cp311-win32.whl", hash = "sha256:3713a8ec18781fda408f0e853bf8c85963e2d3327c99a82a22e5c91baffcb934"}, + {file = "coverage-7.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:88ae5929f0ef668b582fd7cad09b5e7277f50f912183cf969b36e82a1c26e49a"}, + {file = "coverage-7.2.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5e29a64e9586194ea271048bc80c83cdd4587830110d1e07b109e6ff435e5dbc"}, + {file = "coverage-7.2.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d5302eb84c61e758c9d68b8a2f93a398b272073a046d07da83d77b0edc8d76b"}, + {file = "coverage-7.2.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2c9fffbc39dc4a6277e1525cab06c161d11ee3995bbc97543dc74fcec33e045b"}, + {file = "coverage-7.2.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a6ceeab5fca62bca072eba6865a12d881f281c74231d2990f8a398226e1a5d96"}, + {file = "coverage-7.2.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:28563a35ef4a82b5bc5160a01853ce62b9fceee00760e583ffc8acf9e3413753"}, + {file = "coverage-7.2.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:bfa065307667f1c6e1f4c3e13f415b0925e34e56441f5fda2c84110a4a1d8bda"}, + {file = "coverage-7.2.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:7f992b32286c86c38f07a8b5c3fc88384199e82434040a729ec06b067ee0d52c"}, + {file = "coverage-7.2.0-cp37-cp37m-win32.whl", hash = "sha256:2c15bd09fd5009f3a79c8b3682b52973df29761030b692043f9834fc780947c4"}, + {file = "coverage-7.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:f332d61fbff353e2ef0f3130a166f499c3fad3a196e7f7ae72076d41a6bfb259"}, + {file = "coverage-7.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:577a8bc40c01ad88bb9ab1b3a1814f2f860ff5c5099827da2a3cafc5522dadea"}, + {file = "coverage-7.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9240a0335365c29c968131bdf624bb25a8a653a9c0d8c5dbfcabf80b59c1973c"}, + {file = "coverage-7.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:358d3bce1468f298b19a3e35183bdb13c06cdda029643537a0cc37e55e74e8f1"}, + {file = "coverage-7.2.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:932048364ff9c39030c6ba360c31bf4500036d4e15c02a2afc5a76e7623140d4"}, + {file = "coverage-7.2.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7efa21611ffc91156e6f053997285c6fe88cfef3fb7533692d0692d2cb30c846"}, + {file = "coverage-7.2.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:465ea431c3b78a87e32d7d9ea6d081a1003c43a442982375cf2c247a19971961"}, + {file = "coverage-7.2.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:0f03c229f1453b936916f68a47b3dfb5e84e7ad48e160488168a5e35115320c8"}, + {file = "coverage-7.2.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:40785553d68c61e61100262b73f665024fd2bb3c6f0f8e2cd5b13e10e4df027b"}, + {file = "coverage-7.2.0-cp38-cp38-win32.whl", hash = "sha256:b09dd7bef59448c66e6b490cc3f3c25c14bc85d4e3c193b81a6204be8dd355de"}, + {file = "coverage-7.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:dc4f9a89c82faf6254d646180b2e3aa4daf5ff75bdb2c296b9f6a6cf547e26a7"}, + {file = "coverage-7.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c243b25051440386179591a8d5a5caff4484f92c980fb6e061b9559da7cc3f64"}, + {file = "coverage-7.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4b8fd32f85b256fc096deeb4872aeb8137474da0c0351236f93cbedc359353d6"}, + {file = "coverage-7.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7f2a7df523791e6a63b40360afa6792a11869651307031160dc10802df9a252"}, + {file = "coverage-7.2.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:da32526326e8da0effb452dc32a21ffad282c485a85a02aeff2393156f69c1c3"}, + {file = "coverage-7.2.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c1153a6156715db9d6ae8283480ae67fb67452aa693a56d7dae9ffe8f7a80da"}, + {file = "coverage-7.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:74cd60fa00f46f28bd40048d6ca26bd58e9bee61d2b0eb4ec18cea13493c003f"}, + {file = "coverage-7.2.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:59a427f8a005aa7254074719441acb25ac2c2f60c1f1026d43f846d4254c1c2f"}, + {file = "coverage-7.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c3c4beddee01c8125a75cde3b71be273995e2e9ec08fbc260dd206b46bb99969"}, + {file = "coverage-7.2.0-cp39-cp39-win32.whl", hash = "sha256:08e3dd256b8d3e07bb230896c8c96ec6c5dffbe5a133ba21f8be82b275b900e8"}, + {file = "coverage-7.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:ad12c74c6ce53a027f5a5ecbac9be20758a41c85425c1bbab7078441794b04ee"}, + {file = "coverage-7.2.0-pp37.pp38.pp39-none-any.whl", hash = "sha256:ffa637a2d5883298449a5434b699b22ef98dd8e2ef8a1d9e60fa9cfe79813411"}, + {file = "coverage-7.2.0.tar.gz", hash = "sha256:9cc9c41aa5af16d845b53287051340c363dd03b7ef408e45eec3af52be77810d"}, ] +[package.dependencies] +tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""} + +[package.extras] +toml = ["tomli"] + [[package]] name = "dill" version = "0.3.6" @@ -464,38 +421,6 @@ files = [ {file = "distlib-0.3.6.tar.gz", hash = "sha256:14bad2d9b04d3a36127ac97f30b12a19268f211063d8f8ee4f47108896e11b46"}, ] -[[package]] -name = "dparse" -version = "0.6.2" -description = "A parser for Python dependency files" -category = "dev" -optional = false -python-versions = ">=3.5" -files = [ - {file = "dparse-0.6.2-py3-none-any.whl", hash = "sha256:8097076f1dd26c377f30d4745e6ec18fef42f3bf493933b842ac5bafad8c345f"}, - {file = "dparse-0.6.2.tar.gz", hash = "sha256:d45255bda21f998bc7ddf2afd5e62505ba6134756ba2d42a84c56b0826614dfe"}, -] - -[package.dependencies] -packaging = "*" -toml = "*" - -[package.extras] -conda = ["pyyaml"] -pipenv = ["pipenv"] - -[[package]] -name = "eradicate" -version = "2.1.0" -description = "Removes commented-out code." -category = "dev" -optional = false -python-versions = "*" -files = [ - {file = "eradicate-2.1.0-py3-none-any.whl", hash = "sha256:8bfaca181db9227dc88bdbce4d051a9627604c2243e7d85324f6d6ce0fd08bb2"}, - {file = "eradicate-2.1.0.tar.gz", hash = "sha256:aac7384ab25b1bf21c4c012de9b4bf8398945a14c98c911545b2ea50ab558014"}, -] - [[package]] name = "exceptiongroup" version = "1.0.4" @@ -527,172 +452,6 @@ files = [ docs = ["furo (>=2022.6.21)", "sphinx (>=5.1.1)", "sphinx-autodoc-typehints (>=1.19.1)"] testing = ["covdefaults (>=2.2)", "coverage (>=6.4.2)", "pytest (>=7.1.2)", "pytest-cov (>=3)", "pytest-timeout (>=2.1)"] -[[package]] -name = "flake8" -version = "4.0.1" -description = "the modular source code checker: pep8 pyflakes and co" -category = "dev" -optional = false -python-versions = ">=3.6" -files = [ - {file = "flake8-4.0.1-py2.py3-none-any.whl", hash = "sha256:479b1304f72536a55948cb40a32dce8bb0ffe3501e26eaf292c7e60eb5e0428d"}, - {file = "flake8-4.0.1.tar.gz", hash = "sha256:806e034dda44114815e23c16ef92f95c91e4c71100ff52813adf7132a6ad870d"}, -] - -[package.dependencies] -mccabe = ">=0.6.0,<0.7.0" -pycodestyle = ">=2.8.0,<2.9.0" -pyflakes = ">=2.4.0,<2.5.0" - -[[package]] -name = "flake8-bandit" -version = "3.0.0" -description = "Automated security testing with bandit and flake8." -category = "dev" -optional = false -python-versions = ">=3.6" -files = [ - {file = "flake8_bandit-3.0.0-py2.py3-none-any.whl", hash = "sha256:61b617f4f7cdaa0e2b1e6bf7b68afb2b619a227bb3e3ae00dd36c213bd17900a"}, - {file = "flake8_bandit-3.0.0.tar.gz", hash = "sha256:54d19427e6a8d50322a7b02e1841c0a7c22d856975f3459803320e0e18e2d6a1"}, -] - -[package.dependencies] -bandit = ">=1.7.3" -flake8 = "*" -flake8-polyfill = "*" -pycodestyle = "*" - -[[package]] -name = "flake8-bugbear" -version = "22.12.6" -description = "A plugin for flake8 finding likely bugs and design problems in your program. Contains warnings that don't belong in pyflakes and pycodestyle." -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "flake8-bugbear-22.12.6.tar.gz", hash = "sha256:4cdb2c06e229971104443ae293e75e64c6107798229202fbe4f4091427a30ac0"}, - {file = "flake8_bugbear-22.12.6-py3-none-any.whl", hash = "sha256:b69a510634f8a9c298dfda2b18a8036455e6b19ecac4fe582e4d7a0abfa50a30"}, -] - -[package.dependencies] -attrs = ">=19.2.0" -flake8 = ">=3.0.0" - -[package.extras] -dev = ["coverage", "hypothesis", "hypothesmith (>=0.2)", "pre-commit", "tox"] - -[[package]] -name = "flake8-builtins" -version = "2.1.0" -description = "Check for python builtins being used as variables or parameters." -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "flake8-builtins-2.1.0.tar.gz", hash = "sha256:12ff1ee96dd4e1f3141141ee6c45a5c7d3b3c440d0949e9b8d345c42b39c51d4"}, - {file = "flake8_builtins-2.1.0-py3-none-any.whl", hash = "sha256:469e8f03d6d0edf4b1e62b6d5a97dce4598592c8a13ec8f0952e7a185eba50a1"}, -] - -[package.dependencies] -flake8 = "*" - -[package.extras] -test = ["pytest"] - -[[package]] -name = "flake8-comprehensions" -version = "3.10.1" -description = "A flake8 plugin to help you write better list/set/dict comprehensions." -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "flake8-comprehensions-3.10.1.tar.gz", hash = "sha256:412052ac4a947f36b891143430fef4859705af11b2572fbb689f90d372cf26ab"}, - {file = "flake8_comprehensions-3.10.1-py3-none-any.whl", hash = "sha256:d763de3c74bc18a79c039a7ec732e0a1985b0c79309ceb51e56401ad0a2cd44e"}, -] - -[package.dependencies] -flake8 = ">=3.0,<3.2.0 || >3.2.0" - -[[package]] -name = "flake8-docstrings" -version = "1.7.0" -description = "Extension for flake8 which uses pydocstyle to check docstrings" -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "flake8_docstrings-1.7.0-py2.py3-none-any.whl", hash = "sha256:51f2344026da083fc084166a9353f5082b01f72901df422f74b4d953ae88ac75"}, - {file = "flake8_docstrings-1.7.0.tar.gz", hash = "sha256:4c8cc748dc16e6869728699e5d0d685da9a10b0ea718e090b1ba088e67a941af"}, -] - -[package.dependencies] -flake8 = ">=3" -pydocstyle = ">=2.1" - -[[package]] -name = "flake8-eradicate" -version = "1.4.0" -description = "Flake8 plugin to find commented out code" -category = "dev" -optional = false -python-versions = ">=3.7,<4.0" -files = [ - {file = "flake8-eradicate-1.4.0.tar.gz", hash = "sha256:3088cfd6717d1c9c6c3ac45ef2e5f5b6c7267f7504d5a74b781500e95cb9c7e1"}, - {file = "flake8_eradicate-1.4.0-py3-none-any.whl", hash = "sha256:e3bbd0871be358e908053c1ab728903c114f062ba596b4d40c852fd18f473d56"}, -] - -[package.dependencies] -attrs = "*" -eradicate = ">=2.0,<3.0" -flake8 = ">=3.5,<6" - -[[package]] -name = "flake8-markdown" -version = "0.3.0" -description = "Lints Python code blocks in Markdown files using flake8" -category = "dev" -optional = false -python-versions = ">=3.6,<4.0" -files = [ - {file = "flake8-markdown-0.3.0.tar.gz", hash = "sha256:5b54f143c9568da11a9d74ce5e580e96685fe758a14933f140c6d7006041fafd"}, - {file = "flake8_markdown-0.3.0-py3-none-any.whl", hash = "sha256:122705b8b26b1523c5a225a728743393d254394e142680e4af17f930cdd87386"}, -] - -[package.dependencies] -flake8 = ">=3.0,<5.0" - -[[package]] -name = "flake8-polyfill" -version = "1.0.2" -description = "Polyfill package for Flake8 plugins" -category = "dev" -optional = false -python-versions = "*" -files = [ - {file = "flake8-polyfill-1.0.2.tar.gz", hash = "sha256:e44b087597f6da52ec6393a709e7108b2905317d0c0b744cdca6208e670d8eda"}, - {file = "flake8_polyfill-1.0.2-py2.py3-none-any.whl", hash = "sha256:12be6a34ee3ab795b19ca73505e7b55826d5f6ad7230d31b18e106400169b9e9"}, -] - -[package.dependencies] -flake8 = "*" - -[[package]] -name = "flake8-simplify" -version = "0.19.3" -description = "flake8 plugin which checks for code that can be simplified" -category = "dev" -optional = false -python-versions = ">=3.6.1" -files = [ - {file = "flake8_simplify-0.19.3-py3-none-any.whl", hash = "sha256:1057320e9312d75849541fee822900d27bcad05b2405edc84713affee635629e"}, - {file = "flake8_simplify-0.19.3.tar.gz", hash = "sha256:2fb083bf5142a98d9c9554755cf2f56f8926eb4a33eae30c0809041b1546879e"}, -] - -[package.dependencies] -astor = ">=0.1" -flake8 = ">=3.7" - [[package]] name = "frozenlist" version = "1.3.3" @@ -777,36 +536,6 @@ files = [ {file = "frozenlist-1.3.3.tar.gz", hash = "sha256:58bcc55721e8a90b88332d6cd441261ebb22342e238296bb330968952fbb3a6a"}, ] -[[package]] -name = "gitdb" -version = "4.0.10" -description = "Git Object Database" -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "gitdb-4.0.10-py3-none-any.whl", hash = "sha256:c286cf298426064079ed96a9e4a9d39e7f3e9bf15ba60701e95f5492f28415c7"}, - {file = "gitdb-4.0.10.tar.gz", hash = "sha256:6eb990b69df4e15bad899ea868dc46572c3f75339735663b81de79b06f17eb9a"}, -] - -[package.dependencies] -smmap = ">=3.0.1,<6" - -[[package]] -name = "gitpython" -version = "3.1.30" -description = "GitPython is a python library used to interact with Git repositories" -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "GitPython-3.1.30-py3-none-any.whl", hash = "sha256:cd455b0000615c60e286208ba540271af9fe531fa6a87cc590a7298785ab2882"}, - {file = "GitPython-3.1.30.tar.gz", hash = "sha256:769c2d83e13f5d938b7688479da374c4e3d49f71549aaf462b646db9602ea6f8"}, -] - -[package.dependencies] -gitdb = ">=4.0.1,<5" - [[package]] name = "identify" version = "2.5.9" @@ -976,42 +705,38 @@ files = [ [[package]] name = "mypy" -version = "0.991" +version = "1.0.1" description = "Optional static typing for Python" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-0.991-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7d17e0a9707d0772f4a7b878f04b4fd11f6f5bcb9b3813975a9b13c9332153ab"}, - {file = "mypy-0.991-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0714258640194d75677e86c786e80ccf294972cc76885d3ebbb560f11db0003d"}, - {file = "mypy-0.991-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0c8f3be99e8a8bd403caa8c03be619544bc2c77a7093685dcf308c6b109426c6"}, - {file = "mypy-0.991-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc9ec663ed6c8f15f4ae9d3c04c989b744436c16d26580eaa760ae9dd5d662eb"}, - {file = "mypy-0.991-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4307270436fd7694b41f913eb09210faff27ea4979ecbcd849e57d2da2f65305"}, - {file = "mypy-0.991-cp310-cp310-win_amd64.whl", hash = "sha256:901c2c269c616e6cb0998b33d4adbb4a6af0ac4ce5cd078afd7bc95830e62c1c"}, - {file = "mypy-0.991-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:d13674f3fb73805ba0c45eb6c0c3053d218aa1f7abead6e446d474529aafc372"}, - {file = "mypy-0.991-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1c8cd4fb70e8584ca1ed5805cbc7c017a3d1a29fb450621089ffed3e99d1857f"}, - {file = "mypy-0.991-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:209ee89fbb0deed518605edddd234af80506aec932ad28d73c08f1400ef80a33"}, - {file = "mypy-0.991-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37bd02ebf9d10e05b00d71302d2c2e6ca333e6c2a8584a98c00e038db8121f05"}, - {file = "mypy-0.991-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:26efb2fcc6b67e4d5a55561f39176821d2adf88f2745ddc72751b7890f3194ad"}, - {file = "mypy-0.991-cp311-cp311-win_amd64.whl", hash = "sha256:3a700330b567114b673cf8ee7388e949f843b356a73b5ab22dd7cff4742a5297"}, - {file = "mypy-0.991-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:1f7d1a520373e2272b10796c3ff721ea1a0712288cafaa95931e66aa15798813"}, - {file = "mypy-0.991-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:641411733b127c3e0dab94c45af15fea99e4468f99ac88b39efb1ad677da5711"}, - {file = "mypy-0.991-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:3d80e36b7d7a9259b740be6d8d906221789b0d836201af4234093cae89ced0cd"}, - {file = "mypy-0.991-cp37-cp37m-win_amd64.whl", hash = "sha256:e62ebaad93be3ad1a828a11e90f0e76f15449371ffeecca4a0a0b9adc99abcef"}, - {file = "mypy-0.991-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:b86ce2c1866a748c0f6faca5232059f881cda6dda2a893b9a8373353cfe3715a"}, - {file = "mypy-0.991-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ac6e503823143464538efda0e8e356d871557ef60ccd38f8824a4257acc18d93"}, - {file = "mypy-0.991-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:0cca5adf694af539aeaa6ac633a7afe9bbd760df9d31be55ab780b77ab5ae8bf"}, - {file = "mypy-0.991-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a12c56bf73cdab116df96e4ff39610b92a348cc99a1307e1da3c3768bbb5b135"}, - {file = "mypy-0.991-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:652b651d42f155033a1967739788c436491b577b6a44e4c39fb340d0ee7f0d70"}, - {file = "mypy-0.991-cp38-cp38-win_amd64.whl", hash = "sha256:4175593dc25d9da12f7de8de873a33f9b2b8bdb4e827a7cae952e5b1a342e243"}, - {file = "mypy-0.991-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:98e781cd35c0acf33eb0295e8b9c55cdbef64fcb35f6d3aa2186f289bed6e80d"}, - {file = "mypy-0.991-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6d7464bac72a85cb3491c7e92b5b62f3dcccb8af26826257760a552a5e244aa5"}, - {file = "mypy-0.991-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c9166b3f81a10cdf9b49f2d594b21b31adadb3d5e9db9b834866c3258b695be3"}, - {file = "mypy-0.991-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8472f736a5bfb159a5e36740847808f6f5b659960115ff29c7cecec1741c648"}, - {file = "mypy-0.991-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5e80e758243b97b618cdf22004beb09e8a2de1af481382e4d84bc52152d1c476"}, - {file = "mypy-0.991-cp39-cp39-win_amd64.whl", hash = "sha256:74e259b5c19f70d35fcc1ad3d56499065c601dfe94ff67ae48b85596b9ec1461"}, - {file = "mypy-0.991-py3-none-any.whl", hash = "sha256:de32edc9b0a7e67c2775e574cb061a537660e51210fbf6006b0b36ea695ae9bb"}, - {file = "mypy-0.991.tar.gz", hash = "sha256:3c0165ba8f354a6d9881809ef29f1a9318a236a6d81c690094c5df32107bde06"}, + {file = "mypy-1.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:71a808334d3f41ef011faa5a5cd8153606df5fc0b56de5b2e89566c8093a0c9a"}, + {file = "mypy-1.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:920169f0184215eef19294fa86ea49ffd4635dedfdea2b57e45cb4ee85d5ccaf"}, + {file = "mypy-1.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:27a0f74a298769d9fdc8498fcb4f2beb86f0564bcdb1a37b58cbbe78e55cf8c0"}, + {file = "mypy-1.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:65b122a993d9c81ea0bfde7689b3365318a88bde952e4dfa1b3a8b4ac05d168b"}, + {file = "mypy-1.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:5deb252fd42a77add936b463033a59b8e48eb2eaec2976d76b6878d031933fe4"}, + {file = "mypy-1.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2013226d17f20468f34feddd6aae4635a55f79626549099354ce641bc7d40262"}, + {file = "mypy-1.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:48525aec92b47baed9b3380371ab8ab6e63a5aab317347dfe9e55e02aaad22e8"}, + {file = "mypy-1.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c96b8a0c019fe29040d520d9257d8c8f122a7343a8307bf8d6d4a43f5c5bfcc8"}, + {file = "mypy-1.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:448de661536d270ce04f2d7dddaa49b2fdba6e3bd8a83212164d4174ff43aa65"}, + {file = "mypy-1.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:d42a98e76070a365a1d1c220fcac8aa4ada12ae0db679cb4d910fabefc88b994"}, + {file = "mypy-1.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:e64f48c6176e243ad015e995de05af7f22bbe370dbb5b32bd6988438ec873919"}, + {file = "mypy-1.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5fdd63e4f50e3538617887e9aee91855368d9fc1dea30da743837b0df7373bc4"}, + {file = "mypy-1.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:dbeb24514c4acbc78d205f85dd0e800f34062efcc1f4a4857c57e4b4b8712bff"}, + {file = "mypy-1.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:a2948c40a7dd46c1c33765718936669dc1f628f134013b02ff5ac6c7ef6942bf"}, + {file = "mypy-1.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5bc8d6bd3b274dd3846597855d96d38d947aedba18776aa998a8d46fabdaed76"}, + {file = "mypy-1.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:17455cda53eeee0a4adb6371a21dd3dbf465897de82843751cf822605d152c8c"}, + {file = "mypy-1.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e831662208055b006eef68392a768ff83596035ffd6d846786578ba1714ba8f6"}, + {file = "mypy-1.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e60d0b09f62ae97a94605c3f73fd952395286cf3e3b9e7b97f60b01ddfbbda88"}, + {file = "mypy-1.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:0af4f0e20706aadf4e6f8f8dc5ab739089146b83fd53cb4a7e0e850ef3de0bb6"}, + {file = "mypy-1.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:24189f23dc66f83b839bd1cce2dfc356020dfc9a8bae03978477b15be61b062e"}, + {file = "mypy-1.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:93a85495fb13dc484251b4c1fd7a5ac370cd0d812bbfc3b39c1bafefe95275d5"}, + {file = "mypy-1.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f546ac34093c6ce33f6278f7c88f0f147a4849386d3bf3ae193702f4fe31407"}, + {file = "mypy-1.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c6c2ccb7af7154673c591189c3687b013122c5a891bb5651eca3db8e6c6c55bd"}, + {file = "mypy-1.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:15b5a824b58c7c822c51bc66308e759243c32631896743f030daf449fe3677f3"}, + {file = "mypy-1.0.1-py3-none-any.whl", hash = "sha256:eda5c8b9949ed411ff752b9a01adda31afe7eae1e53e946dbdf9db23865e66c4"}, + {file = "mypy-1.0.1.tar.gz", hash = "sha256:28cea5a6392bb43d266782983b5a4216c25544cd7d80be681a155ddcdafd152d"}, ] [package.dependencies] @@ -1079,18 +804,6 @@ files = [ {file = "pathspec-0.10.2.tar.gz", hash = "sha256:8f6bf73e5758fd365ef5d58ce09ac7c27d2833a8d7da51712eac6e27e35141b0"}, ] -[[package]] -name = "pbr" -version = "5.11.0" -description = "Python Build Reasonableness" -category = "dev" -optional = false -python-versions = ">=2.6" -files = [ - {file = "pbr-5.11.0-py2.py3-none-any.whl", hash = "sha256:db2317ff07c84c4c63648c9064a79fe9d9f5c7ce85a9099d4b6258b3db83225a"}, - {file = "pbr-5.11.0.tar.gz", hash = "sha256:b97bc6695b2aff02144133c2e7399d5885223d42b7912ffaec2ca3898e673bfe"}, -] - [[package]] name = "platformdirs" version = "2.5.4" @@ -1125,14 +838,14 @@ testing = ["pytest", "pytest-benchmark"] [[package]] name = "pre-commit" -version = "2.21.0" +version = "3.1.0" description = "A framework for managing and maintaining multi-language pre-commit hooks." category = "dev" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "pre_commit-2.21.0-py2.py3-none-any.whl", hash = "sha256:e2f91727039fc39a92f58a588a25b87f936de6567eed4f0e673e0507edc75bad"}, - {file = "pre_commit-2.21.0.tar.gz", hash = "sha256:31ef31af7e474a8d8995027fefdfcf509b5c913ff31f2015b4ec4beb26a6f658"}, + {file = "pre_commit-3.1.0-py2.py3-none-any.whl", hash = "sha256:7001dfcd174540658822b1fd3630ceadf4f41375a5d1844b5c3b3830f227348c"}, + {file = "pre_commit-3.1.0.tar.gz", hash = "sha256:61bd9f1b96d3d1e763f2a9a0f8522aed341646800642ff6803c73fac5781f5b7"}, ] [package.dependencies] @@ -1158,48 +871,6 @@ files = [ "ruamel.yaml" = ">=0.15" tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} -[[package]] -name = "pycodestyle" -version = "2.8.0" -description = "Python style guide checker" -category = "dev" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -files = [ - {file = "pycodestyle-2.8.0-py2.py3-none-any.whl", hash = "sha256:720f8b39dde8b293825e7ff02c475f3077124006db4f440dcbc9a20b76548a20"}, - {file = "pycodestyle-2.8.0.tar.gz", hash = "sha256:eddd5847ef438ea1c7870ca7eb78a9d47ce0cdb4851a5523949f2601d0cbbe7f"}, -] - -[[package]] -name = "pydocstyle" -version = "6.1.1" -description = "Python docstring style checker" -category = "dev" -optional = false -python-versions = ">=3.6" -files = [ - {file = "pydocstyle-6.1.1-py3-none-any.whl", hash = "sha256:6987826d6775056839940041beef5c08cc7e3d71d63149b48e36727f70144dc4"}, - {file = "pydocstyle-6.1.1.tar.gz", hash = "sha256:1d41b7c459ba0ee6c345f2eb9ae827cab14a7533a88c5c6f7e94923f72df92dc"}, -] - -[package.dependencies] -snowballstemmer = "*" - -[package.extras] -toml = ["toml"] - -[[package]] -name = "pyflakes" -version = "2.4.0" -description = "passive checker of Python programs" -category = "dev" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -files = [ - {file = "pyflakes-2.4.0-py2.py3-none-any.whl", hash = "sha256:3bb3a3f256f4b7968c9c788781e4ff07dce46bdf12339dcda61053375426ee2e"}, - {file = "pyflakes-2.4.0.tar.gz", hash = "sha256:05a85c2872edf37a4ed30b0cce2f6093e1d0581f8c19d7393122da7e25b2b24c"}, -] - [[package]] name = "pylint" version = "2.16.2" @@ -1307,21 +978,6 @@ pytest = ">=4.6" [package.extras] testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtualenv"] -[[package]] -name = "pyupgrade" -version = "3.3.1" -description = "A tool to automatically upgrade syntax for newer versions." -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "pyupgrade-3.3.1-py2.py3-none-any.whl", hash = "sha256:3b93641963df022d605c78aeae4b5956a5296ea24701eafaef9c487527b77e60"}, - {file = "pyupgrade-3.3.1.tar.gz", hash = "sha256:f88bce38b0ba92c2a9a5063c8629e456e8d919b67d2d42c7ecab82ff196f9813"}, -] - -[package.dependencies] -tokenize-rt = ">=3.2.0" - [[package]] name = "pyyaml" version = "6.0" @@ -1372,28 +1028,6 @@ files = [ {file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"}, ] -[[package]] -name = "requests" -version = "2.28.1" -description = "Python HTTP for Humans." -category = "dev" -optional = false -python-versions = ">=3.7, <4" -files = [ - {file = "requests-2.28.1-py3-none-any.whl", hash = "sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349"}, - {file = "requests-2.28.1.tar.gz", hash = "sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983"}, -] - -[package.dependencies] -certifi = ">=2017.4.17" -charset-normalizer = ">=2,<3" -idna = ">=2.5,<4" -urllib3 = ">=1.21.1,<1.27" - -[package.extras] -socks = ["PySocks (>=1.5.6,!=1.5.7)"] -use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] - [[package]] name = "ruamel-yaml" version = "0.17.21" @@ -1429,7 +1063,6 @@ files = [ {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-win_amd64.whl", hash = "sha256:d000f258cf42fec2b1bbf2863c61d7b8918d31ffee905da62dede869254d3b8a"}, {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:045e0626baf1c52e5527bd5db361bc83180faaba2ff586e763d3d5982a876a9e"}, {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-macosx_12_6_arm64.whl", hash = "sha256:721bc4ba4525f53f6a611ec0967bdcee61b31df5a56801281027a3a6d1c2daf5"}, - {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:41d0f1fa4c6830176eef5b276af04c89320ea616655d01327d5ce65e50575c94"}, {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:4b3a93bb9bc662fc1f99c5c3ea8e623d8b23ad22f861eb6fce9377ac07ad6072"}, {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-macosx_12_0_arm64.whl", hash = "sha256:a234a20ae07e8469da311e182e70ef6b199d0fbeb6c6cc2901204dd87fb867e8"}, {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:15910ef4f3e537eea7fe45f8a5d19997479940d9196f357152a09031c5be59f3"}, @@ -1458,29 +1091,32 @@ files = [ ] [[package]] -name = "safety" -version = "2.3.5" -description = "Checks installed dependencies for known vulnerabilities and licenses." +name = "ruff" +version = "0.0.247" +description = "An extremely fast Python linter, written in Rust." category = "dev" optional = false -python-versions = "*" +python-versions = ">=3.7" files = [ - {file = "safety-2.3.5-py3-none-any.whl", hash = "sha256:2227fcac1b22b53c1615af78872b48348661691450aa25d6704a5504dbd1f7e2"}, - {file = "safety-2.3.5.tar.gz", hash = "sha256:a60c11f8952f412cbb165d70cb1f673a3b43a2ba9a93ce11f97e6a4de834aa3a"}, + {file = "ruff-0.0.247-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:0151face9ef0e09c0d09166eae5f6df9d61ed7b1686086092d56164b790d1adf"}, + {file = "ruff-0.0.247-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:0abffda0039dc0eec18d624a48a725c414587c816194d1c9889eceba82e87ad0"}, + {file = "ruff-0.0.247-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e34ce0a12a9c7ac25fcfd8a9a25ade778f4e54df37f7ce58c406c36f9d5a1e3"}, + {file = "ruff-0.0.247-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c31adc9f08e1652acb6c1b6d494a3e52895e341398b5dcaffe3325688f70de87"}, + {file = "ruff-0.0.247-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ebc3b3077a880ea8af9f17c5614f606d6c1a15db6823501f4b8d3daf51f78782"}, + {file = "ruff-0.0.247-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:403f67452655923d0775c6c3854750e77c9c97eb875ea979ad515d3c75a45cff"}, + {file = "ruff-0.0.247-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:53dd6124c6b822c27ee23965ce9d8c5fbc76a97ecc209daef0bbfbe8f905cb18"}, + {file = "ruff-0.0.247-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f1483c7435db4926da3793a89f6bbb68dedf2990aeddef01407d8c47953403e0"}, + {file = "ruff-0.0.247-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ce619be01206ab71054c9f492a803cc81be678222379c69a0d60aa66c30e4a2"}, + {file = "ruff-0.0.247-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:172c0a8fb295259d9e12e43c39cf3bd006ae85eae89b8e9ca6ece7252241b603"}, + {file = "ruff-0.0.247-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:0cda3a13e67adaf5198c69847a2f04011434bdfbfdca05ac32c101991dd56162"}, + {file = "ruff-0.0.247-py3-none-musllinux_1_2_i686.whl", hash = "sha256:4481b5b6103dffc09156f2fea79a9a9282a72c0109ca4ab74828ae1089ec8c7e"}, + {file = "ruff-0.0.247-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:8c835b703cebb0f23d59ec3d83ff498c5290fae51f98df548aacbb9ff85cc93c"}, + {file = "ruff-0.0.247-py3-none-win32.whl", hash = "sha256:3695f5fd2f4ad44030799a6021b2626442e8d92e432d646aadeefd4a1fceab12"}, + {file = "ruff-0.0.247-py3-none-win_amd64.whl", hash = "sha256:3e22f08bc403d3b4f32488ea52cd69fc3cb343b2c99431fd969cda1c83f4bc2f"}, + {file = "ruff-0.0.247-py3-none-win_arm64.whl", hash = "sha256:737b7fd25d2523b7c526830a3670364a953cb6c6bbf9912c78cba06bbf0ca125"}, + {file = "ruff-0.0.247.tar.gz", hash = "sha256:cce9566cea1cb348bb2dec99f810d846d112627fa52bf3a554773ce4737a061b"}, ] -[package.dependencies] -Click = ">=8.0.2" -dparse = ">=0.6.2" -packaging = ">=21.0,<22.0" -requests = "*" -"ruamel.yaml" = ">=0.17.21" -setuptools = ">=19.3" - -[package.extras] -github = ["jinja2 (>=3.1.0)", "pygithub (>=1.43.3)"] -gitlab = ["python-gitlab (>=1.3.0)"] - [[package]] name = "setuptools" version = "65.6.3" @@ -1498,69 +1134,6 @@ docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-g testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8 (<5)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] -[[package]] -name = "smmap" -version = "5.0.0" -description = "A pure Python implementation of a sliding window memory map manager" -category = "dev" -optional = false -python-versions = ">=3.6" -files = [ - {file = "smmap-5.0.0-py3-none-any.whl", hash = "sha256:2aba19d6a040e78d8b09de5c57e96207b09ed71d8e55ce0959eeee6c8e190d94"}, - {file = "smmap-5.0.0.tar.gz", hash = "sha256:c840e62059cd3be204b0c9c9f74be2c09d5648eddd4580d9314c3ecde0b30936"}, -] - -[[package]] -name = "snowballstemmer" -version = "2.2.0" -description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms." -category = "dev" -optional = false -python-versions = "*" -files = [ - {file = "snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a"}, - {file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"}, -] - -[[package]] -name = "stevedore" -version = "4.1.1" -description = "Manage dynamic plugins for Python applications" -category = "dev" -optional = false -python-versions = ">=3.8" -files = [ - {file = "stevedore-4.1.1-py3-none-any.whl", hash = "sha256:aa6436565c069b2946fe4ebff07f5041e0c8bf18c7376dd29edf80cf7d524e4e"}, - {file = "stevedore-4.1.1.tar.gz", hash = "sha256:7f8aeb6e3f90f96832c301bff21a7eb5eefbe894c88c506483d355565d88cc1a"}, -] - -[package.dependencies] -pbr = ">=2.0.0,<2.1.0 || >2.1.0" - -[[package]] -name = "tokenize-rt" -version = "5.0.0" -description = "A wrapper around the stdlib `tokenize` which roundtrips." -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "tokenize_rt-5.0.0-py2.py3-none-any.whl", hash = "sha256:c67772c662c6b3dc65edf66808577968fb10badfc2042e3027196bed4daf9e5a"}, - {file = "tokenize_rt-5.0.0.tar.gz", hash = "sha256:3160bc0c3e8491312d0485171dea861fc160a240f5f5766b72a1165408d10740"}, -] - -[[package]] -name = "toml" -version = "0.10.2" -description = "Python Library for Tom's Obvious, Minimal Language" -category = "dev" -optional = false -python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" -files = [ - {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, - {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, -] - [[package]] name = "tomli" version = "2.0.1" @@ -1585,18 +1158,6 @@ files = [ {file = "tomlkit-0.11.6.tar.gz", hash = "sha256:71b952e5721688937fb02cf9d354dbcf0785066149d2855e44531ebdd2b65d73"}, ] -[[package]] -name = "types-cachetools" -version = "5.3.0.2" -description = "Typing stubs for cachetools" -category = "dev" -optional = false -python-versions = "*" -files = [ - {file = "types-cachetools-5.3.0.2.tar.gz", hash = "sha256:bd4be85c086d002ba215c1c1c888d78bdafdcbc6a6d6813cd43b0b327ff4aa58"}, - {file = "types_cachetools-5.3.0.2-py3-none-any.whl", hash = "sha256:2a59e253d2c4321e93333837f3c2c992c33c2efc96b7249042701eb909e2ba3d"}, -] - [[package]] name = "typing-extensions" version = "4.4.0" @@ -1609,23 +1170,6 @@ files = [ {file = "typing_extensions-4.4.0.tar.gz", hash = "sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa"}, ] -[[package]] -name = "urllib3" -version = "1.26.13" -description = "HTTP library with thread-safe connection pooling, file post, and more." -category = "dev" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" -files = [ - {file = "urllib3-1.26.13-py2.py3-none-any.whl", hash = "sha256:47cc05d99aaa09c9e72ed5809b60e7ba354e64b59c9c173ac3018642d8bb41fc"}, - {file = "urllib3-1.26.13.tar.gz", hash = "sha256:c083dd0dce68dbfbe1129d5271cb90f9447dea7d52097c6e0126120c521ddea8"}, -] - -[package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] -secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] -socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] - [[package]] name = "virtualenv" version = "20.17.0" @@ -1647,21 +1191,6 @@ platformdirs = ">=2.4,<3" docs = ["proselint (>=0.13)", "sphinx (>=5.3)", "sphinx-argparse (>=0.3.2)", "sphinx-rtd-theme (>=1)", "towncrier (>=22.8)"] testing = ["coverage (>=6.2)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=21.3)", "pytest (>=7.0.1)", "pytest-env (>=0.6.2)", "pytest-freezegun (>=0.4.2)", "pytest-mock (>=3.6.1)", "pytest-randomly (>=3.10.3)", "pytest-timeout (>=2.1)"] -[[package]] -name = "vulture" -version = "2.7" -description = "Find dead code" -category = "dev" -optional = false -python-versions = ">=3.6" -files = [ - {file = "vulture-2.7-py2.py3-none-any.whl", hash = "sha256:bccc51064ed76db15a6b58277cea8885936af047f53d2655fb5de575e93d0bca"}, - {file = "vulture-2.7.tar.gz", hash = "sha256:67fb80a014ed9fdb599dd44bb96cb54311032a104106fc2e706ef7a6dad88032"}, -] - -[package.dependencies] -toml = "*" - [[package]] name = "wrapt" version = "1.14.1" @@ -1844,4 +1373,4 @@ multidict = ">=4.0" [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "4531b18a0c7f1f72e835881769b70b7d2c5fef73cf5199de659d0413b41924ba" +content-hash = "d1fff89626ba90f5caae0738f4886e5dd969aa8138307cc814d7078301b310fb" diff --git a/pyproject.toml b/pyproject.toml index 6e66d85..594418d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -30,40 +30,26 @@ aiohttp = ">=3.0.0" python = "^3.9" yarl = ">=1.6.0" +[tool.poetry.urls] +"Bug Tracker" = "https://github.com/klaasnicolaas/python-odp-amsterdam/issues" +Changelog = "https://github.com/klaasnicolaas/python-odp-amsterdam/releases" + [tool.poetry.group.dev.dependencies] +ruff = "^0.0.247" aresponses = "^2.1.6" -bandit = "^1.7.4" -black = "^22.10" -blacken-docs = "^1.12.1" +black = "^22.12" +blacken-docs = "^1.13.0" codespell = "^2.2.2" -coverage = {version = "^6.5", extras = ["toml"]} -darglint = "^1.8.1" -flake8 = "^4.0.1" -flake8-bandit = "^3.0.0" -flake8-bugbear = "^22.10.27" -flake8-builtins = "^2.0.1" -flake8-comprehensions = "^3.10.1" -flake8-docstrings = "^1.5.0" -flake8-eradicate = "^1.4.0" -flake8-markdown = "^0.3.0" -flake8-simplify = "^0.19.3" -isort = "^5.10.1" -mypy = "^0.991" -pre-commit = "^2.20.0" +coverage = {version = "^7.1", extras = ["toml"]} +mypy = "^1.0" +pre-commit = "^3.0.4" pre-commit-hooks = "^4.4.0" -pylint = "^2.15.6" -pytest = "^7.2.0" -pytest-asyncio = "^0.20.2" +pylint = "^2.16.1" +pytest = "^7.2.1" +pytest-asyncio = "^0.20.3" pytest-cov = "^4.0.0" -pyupgrade = "^3.2.2" -safety = "^2.3.2" -vulture = "^2.6" -yamllint = "^1.28.0" -types-cachetools = "^5.2.1" - -[tool.poetry.urls] -"Bug Tracker" = "https://github.com/klaasnicolaas/python-odp-amsterdam/issues" -Changelog = "https://github.com/klaasnicolaas/python-odp-amsterdam/releases" +yamllint = "^1.29.0" +covdefaults = "^2.2.2" [tool.black] target-version = ['py39'] @@ -71,27 +57,16 @@ target-version = ['py39'] [tool.coverage.paths] source = ["odp_amsterdam"] -[tool.coverage.report] -show_missing = true -exclude_lines = ["pragma: no cover", "if TYPE_CHECKING:"] - [tool.coverage.run] -branch = true +plugins = ["covdefaults"] source = ["odp_amsterdam"] -[tool.isort] -profile = "black" -multi_line_output = 3 - [tool.mypy] # Specify the target platform details in config, so your developers are # free to run mypy on Windows, Linux, or macOS and get consistent # results. platform = "linux" -python_version = 3.9 - -# flake8-mypy expects the two following for sensible formatting -show_column_numbers = true +python_version = "3.9" # show error messages from unrelated files follow_imports = "normal" @@ -106,7 +81,7 @@ disallow_incomplete_defs = true disallow_subclassing_any = true disallow_untyped_calls = true disallow_untyped_defs = true -disallow_untyped_decorators = false # thanks backoff :( +disallow_untyped_decorators = true no_implicit_optional = true no_implicit_reexport = true strict_optional = true @@ -117,8 +92,13 @@ warn_return_any = true warn_unused_configs = true warn_unused_ignores = true -# No incremental mode -cache_dir = "/dev/null" +[tool.pylint.MASTER] +extension-pkg-whitelist = [ + "pydantic" +] +ignore= [ + "tests" +] [tool.pylint.BASIC] good-names = [ @@ -134,9 +114,11 @@ good-names = [ "T", ] +[tool.pylint.DESIGN] +max-attributes=15 + [tool.pylint."MESSAGES CONTROL"] disable= [ - "too-few-public-methods", "duplicate-code", "format", "unsubscriptable-object", @@ -148,17 +130,30 @@ ignore-imports = true [tool.pylint.FORMAT] max-line-length=88 -[tool.pylint.DESIGN] -max-attributes=20 - [tool.pytest.ini_options] addopts = "--cov" asyncio_mode = "auto" -[tool.vulture] -min_confidence = 80 -paths = ["odp_amsterdam"] -verbose = true +[tool.ruff] +select = ["ALL"] +ignore = [ + "ANN101", # Self... explanatory + "ANN401", # Opinioated warning on disallowing dynamically typed expressions + "D203", # Conflicts with other rules + "D213", # Conflicts with other rules + "D417", # False positives in some occasions + "PLR2004", # Just annoying, not really useful +] + +[tool.ruff.flake8-pytest-style] +mark-parentheses = false +fixture-parentheses = false + +[tool.ruff.isort] +known-first-party = ["gridnet"] + +[tool.ruff.mccabe] +max-complexity = 25 [build-system] requires = ["poetry-core>=1.0.0"] diff --git a/tests/__init__.py b/tests/__init__.py index 36a665f..c641d26 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1,9 +1,8 @@ """Asynchronous Python client providing Open Data information of Amsterdam.""" -import os +from pathlib import Path def load_fixtures(filename: str) -> str: """Load a fixture.""" - path = os.path.join(os.path.dirname(__file__), "fixtures", filename) - with open(path, encoding="utf-8") as fptr: - return fptr.read() + path = Path(__file__).parent / "fixtures" / filename + return path.read_text() diff --git a/tests/ruff.toml b/tests/ruff.toml new file mode 100644 index 0000000..b346c56 --- /dev/null +++ b/tests/ruff.toml @@ -0,0 +1,12 @@ +# This extend our general Ruff rules specifically for tests +extend = "../pyproject.toml" + +extend-select = [ + "PT", # Use @pytest.fixture without parentheses +] + +extend-ignore = [ + "S101", # Use of assert detected. As these are tests... + "SLF001", # Tests will access private/protected members... + "TCH002", # pytest doesn't like this one... +] diff --git a/tests/test_amsterdam.py b/tests/test_amsterdam.py index f4b13ba..f9c184f 100644 --- a/tests/test_amsterdam.py +++ b/tests/test_amsterdam.py @@ -3,17 +3,15 @@ import asyncio from unittest.mock import patch -import aiohttp import pytest +from aiohttp import ClientError, ClientResponse, ClientSession from aresponses import Response, ResponsesMockServer - from odp_amsterdam import ODPAmsterdam from odp_amsterdam.exceptions import ODPAmsterdamConnectionError, ODPAmsterdamError from . import load_fixtures -@pytest.mark.asyncio async def test_json_request(aresponses: ResponsesMockServer) -> None: """Test JSON response is handled correctly.""" aresponses.add( @@ -26,14 +24,13 @@ async def test_json_request(aresponses: ResponsesMockServer) -> None: text=load_fixtures("garages.json"), ), ) - async with aiohttp.ClientSession() as session: + async with ClientSession() as session: client = ODPAmsterdam(session=session) response = await client._request("test") assert response is not None await client.close() -@pytest.mark.asyncio async def test_internal_session(aresponses: ResponsesMockServer) -> None: """Test internal session is handled correctly.""" aresponses.add( @@ -50,19 +47,19 @@ async def test_internal_session(aresponses: ResponsesMockServer) -> None: await client._request("test") -@pytest.mark.asyncio async def test_timeout(aresponses: ResponsesMockServer) -> None: """Test request timeout from the Open Data Platform API of Amsterdam.""" # Faking a timeout by sleeping - async def response_handler(_: aiohttp.ClientResponse) -> Response: + async def response_handler(_: ClientResponse) -> Response: await asyncio.sleep(0.2) return aresponses.Response( - body="Goodmorning!", text=load_fixtures("garages.json") + body="Goodmorning!", + text=load_fixtures("garages.json"), ) aresponses.add("api.data.amsterdam.nl", "/test", "GET", response_handler) - async with aiohttp.ClientSession() as session: + async with ClientSession() as session: client = ODPAmsterdam( session=session, request_timeout=0.1, @@ -71,7 +68,6 @@ async def response_handler(_: aiohttp.ClientResponse) -> Response: assert await client._request("test") -@pytest.mark.asyncio async def test_content_type(aresponses: ResponsesMockServer) -> None: """Test request content type error from Open Data Platform API of Amsterdam.""" aresponses.add( @@ -84,18 +80,19 @@ async def test_content_type(aresponses: ResponsesMockServer) -> None: ), ) - async with aiohttp.ClientSession() as session: + async with ClientSession() as session: client = ODPAmsterdam(session=session) with pytest.raises(ODPAmsterdamError): assert await client._request("test") -@pytest.mark.asyncio async def test_client_error() -> None: """Test request client error from the Open Data Platform API of Amsterdam.""" - async with aiohttp.ClientSession() as session: + async with ClientSession() as session: client = ODPAmsterdam(session=session) with patch.object( - session, "request", side_effect=aiohttp.ClientError + session, + "request", + side_effect=ClientError, ), pytest.raises(ODPAmsterdamConnectionError): assert await client._request("test") diff --git a/tests/test_models.py b/tests/test_models.py index e7a9b4c..6df2871 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -1,8 +1,7 @@ """Test the models.""" -import aiohttp import pytest +from aiohttp import ClientSession from aresponses import ResponsesMockServer - from odp_amsterdam import ( Garage, ODPAmsterdam, @@ -14,7 +13,6 @@ from . import load_fixtures -@pytest.mark.asyncio async def test_all_garages(aresponses: ResponsesMockServer) -> None: """Test all garage function.""" aresponses.add( @@ -27,18 +25,12 @@ async def test_all_garages(aresponses: ResponsesMockServer) -> None: text=load_fixtures("garages.json"), ), ) - async with aiohttp.ClientSession() as session: + async with ClientSession() as session: client = ODPAmsterdam(session=session) garages: list[Garage] = await client.all_garages() assert garages is not None - for item in garages: - assert isinstance(item, Garage) - assert item.garage_id is not None - assert item.garage_name is not None - assert item.state is not None -@pytest.mark.asyncio async def test_single_garage(aresponses: ResponsesMockServer) -> None: """Test a single garage model.""" aresponses.add( @@ -51,7 +43,7 @@ async def test_single_garage(aresponses: ResponsesMockServer) -> None: text=load_fixtures("garages.json"), ), ) - async with aiohttp.ClientSession() as session: + async with ClientSession() as session: client = ODPAmsterdam(session=session) garage: Garage = await client.garage("A557D1AD-5D39-915B-8B54-A4AAFA2C1CFC") assert garage.garage_name == "P02 Olympisch Stadion" @@ -63,7 +55,6 @@ async def test_single_garage(aresponses: ResponsesMockServer) -> None: assert garage.availability_pct == 61.3 -@pytest.mark.asyncio async def test_parking_locations_model(aresponses: ResponsesMockServer) -> None: """Test the parking locations model.""" aresponses.add( @@ -76,19 +67,20 @@ async def test_parking_locations_model(aresponses: ResponsesMockServer) -> None: text=load_fixtures("parking.json"), ), ) - async with aiohttp.ClientSession() as session: + async with ClientSession() as session: client = ODPAmsterdam(session=session) locations: list[ParkingSpot] = await client.locations() assert locations is not None for item in locations: assert isinstance(item, ParkingSpot) - assert item.spot_id is not None and isinstance(item.spot_id, str) + assert item.spot_id is not None + assert isinstance(item.spot_id, str) assert isinstance(item.spot_type, str) assert isinstance(item.street, str) or item.street is None - assert item.coordinates is not None and isinstance(item.coordinates, list) + assert item.coordinates is not None + assert isinstance(item.coordinates, list) -@pytest.mark.asyncio async def test_wrong_garage_model(aresponses: ResponsesMockServer) -> None: """Test a wrong garage model.""" aresponses.add( @@ -101,14 +93,12 @@ async def test_wrong_garage_model(aresponses: ResponsesMockServer) -> None: text=load_fixtures("wrong_garages.json"), ), ) - async with aiohttp.ClientSession() as session: + async with ClientSession() as session: client = ODPAmsterdam(session=session) with pytest.raises(ODPAmsterdamError): - garages: list[Garage] = await client.all_garages() - assert garages is not None + await client.all_garages() -@pytest.mark.asyncio async def test_no_garage_found(aresponses: ResponsesMockServer) -> None: """Test a wrong garage model.""" aresponses.add( @@ -121,8 +111,7 @@ async def test_no_garage_found(aresponses: ResponsesMockServer) -> None: text=load_fixtures("garages.json"), ), ) - async with aiohttp.ClientSession() as session: + async with ClientSession() as session: client = ODPAmsterdam(session=session) with pytest.raises(ODPAmsterdamResultsError): - garage = await client.garage(garage_id="test") - assert garage is None + await client.garage(garage_id="test")