From aab91d7c5610b42562ad7573abdfc7f3cc177304 Mon Sep 17 00:00:00 2001 From: "shai.ungar" Date: Fri, 12 Jul 2024 14:12:33 +0300 Subject: [PATCH 1/2] fix tests --- .flake8 | 5 --- .pre-commit-config.yaml | 63 ++++++++++++++-------------------- LICENSE | 2 +- examples/test_api.py | 1 + pylintrc | 14 -------- pyproject.toml | 66 ++++++++++++++++++++++++++++++++++-- pyseventeentrack/__init__.py | 1 + pyseventeentrack/client.py | 5 +-- pyseventeentrack/errors.py | 6 ---- pyseventeentrack/package.py | 7 ++-- pyseventeentrack/profile.py | 5 +-- pyseventeentrack/track.py | 1 + requirements_test.txt | 5 +-- script/run-in-env.sh | 30 ++++++++++++++++ tests/common.py | 11 ++++++ tests/test_client.py | 3 +- tests/test_profile.py | 3 -- 17 files changed, 148 insertions(+), 80 deletions(-) delete mode 100644 .flake8 delete mode 100644 pylintrc create mode 100755 script/run-in-env.sh diff --git a/.flake8 b/.flake8 deleted file mode 100644 index cdb952c..0000000 --- a/.flake8 +++ /dev/null @@ -1,5 +0,0 @@ -[flake8] -ignore = E203, E266, E501, F811, W503 -max-line-length = 80 -max-complexity = 18 -select = B,C,E,F,W,T4,B9 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 34c2a1e..c533e4f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,5 +1,14 @@ --- repos: + - repo: https://github.com/astral-sh/ruff-pre-commit + # Ruff version. + rev: v0.5.1 + hooks: + # Run the linter. + - id: ruff + args: [ --fix ] + # Run the formatter. + - id: ruff-format - repo: https://github.com/PyCQA/bandit rev: 1.6.2 hooks: @@ -9,15 +18,6 @@ repos: - --format=custom - --configfile=.bandit.yaml files: ^pyseventeentrack/.+\.py$ - - repo: https://github.com/python/black - rev: 22.3.0 - hooks: - - id: black - args: - - --safe - - --quiet - language_version: python3 - files: ^((pyseventeentrack|tests)/.+)?[^/]+\.py$ - repo: https://github.com/codespell-project/codespell rev: v1.16.0 hooks: @@ -26,26 +26,6 @@ repos: - --skip="./.*,*.json" - --quiet-level=4 exclude_types: [json] - - repo: https://gitlab.com/pycqa/flake8 - rev: 3.7.9 - hooks: - - id: flake8 - additional_dependencies: - - flake8-docstrings==1.5.0 - - pydocstyle==5.0.1 - files: ^pyseventeentrack/.+\.py$ - - repo: https://github.com/pre-commit/mirrors-isort - rev: v4.3.21 - hooks: - - id: isort - additional_dependencies: - - toml - files: ^(pyseventeentrack|tests)/.+\.py$ - - repo: https://github.com/pre-commit/mirrors-mypy - rev: v0.790 - hooks: - - id: mypy - files: ^pyseventeentrack/.+\.py$ - repo: https://github.com/pre-commit/pre-commit-hooks rev: v2.4.0 hooks: @@ -54,13 +34,20 @@ repos: args: - --branch=dev - --branch=master - - repo: https://github.com/PyCQA/pydocstyle - rev: 5.0.2 + - repo: local hooks: - - id: pydocstyle - files: ^((pyseventeentrack|tests)/.+)?[^/]+\.py$ - - repo: https://github.com/gruntwork-io/pre-commit - rev: v0.1.12 - hooks: - - id: shellcheck - files: ^script/.+ + # Run mypy through our wrapper script in order to get the possible + # pyenv and/or virtualenv activated; it may not have been e.g. if + # committing from a GUI tool that was not launched from an activated + # shell. + - id: mypy + name: mypy + entry: script/run-in-env.sh mypy + language: script + types_or: [ python, pyi ] + require_serial: true + - id: pylint + name: pylint + entry: script/run-in-env.sh pylint -j 0 + language: script + types_or: [ python, pyi ] diff --git a/LICENSE b/LICENSE index 3d241d8..3aa338d 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2018 Aaron Bach +Copyright (c) 2018 Shai Ungar Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/examples/test_api.py b/examples/test_api.py index 4c0e7f0..c874d4f 100644 --- a/examples/test_api.py +++ b/examples/test_api.py @@ -1,4 +1,5 @@ """Run an example script to quickly test a 17track.net account.""" + import asyncio import logging diff --git a/pylintrc b/pylintrc deleted file mode 100644 index 841fa42..0000000 --- a/pylintrc +++ /dev/null @@ -1,14 +0,0 @@ -[MESSAGES CONTROL] -# Reasons disabled: -# bad-continuation - Invalid attack on black -# unnecessary-pass - This can hurt readability -disable= - bad-continuation, - unnecessary-pass - -[REPORTS] -reports=no - -[FORMAT] -expected-line-ending-format=LF - diff --git a/pyproject.toml b/pyproject.toml index c440cad..d47655c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -43,8 +43,70 @@ python = "^3.9.0" pytz = ">=2021.1" [tool.poetry.dev-dependencies] -aresponses = "^2.0.0" +aresponses = "^3.0.0" pre-commit = "^2.0.1" -pytest = "^7.0.0" +pytest = "^8.0.0" pytest-aiohttp = "^1.0.0" pytest-cov = "^3.0.0" + +# Exclude a variety of commonly ignored directories. +exclude = [ + ".bzr", + ".direnv", + ".eggs", + ".git", + ".git-rewrite", + ".hg", + ".ipynb_checkpoints", + ".mypy_cache", + ".nox", + ".pants.d", + ".pyenv", + ".pytest_cache", + ".pytype", + ".ruff_cache", + ".svn", + ".tox", + ".venv", + ".vscode", + "__pypackages__", + "_build", + "buck-out", + "build", + "dist", + "node_modules", + "site-packages", + "venv", +] + +# Same as Black. +line-length = 88 +indent-width = 4 + +# Assume Python 3.8 +target-version = "py38" + +[tool.ruff.lint] +# Enable Pyflakes (`F`) and a subset of the pycodestyle (`E`) codes by default. +select = ["E4", "E7", "E9", "F"] +ignore = [] + +# Allow fix for all enabled rules (when `--fix`) is provided. +fixable = ["ALL"] +unfixable = [] + +# Allow unused variables when underscore-prefixed. +dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$" + +[tool.ruff.format] +# Like Black, use double quotes for strings. +quote-style = "double" + +# Like Black, indent with spaces, rather than tabs. +indent-style = "space" + +# Like Black, respect magic trailing commas. +skip-magic-trailing-comma = false + +# Like Black, automatically detect the appropriate line ending. +line-ending = "auto" diff --git a/pyseventeentrack/__init__.py b/pyseventeentrack/__init__.py index 2b6825d..e7c2516 100644 --- a/pyseventeentrack/__init__.py +++ b/pyseventeentrack/__init__.py @@ -1,2 +1,3 @@ """Define module-level imports.""" + from .client import Client # noqa diff --git a/pyseventeentrack/client.py b/pyseventeentrack/client.py index 5e88b84..b011740 100644 --- a/pyseventeentrack/client.py +++ b/pyseventeentrack/client.py @@ -1,4 +1,5 @@ """Define a 17track.net client.""" + from typing import Optional from aiohttp import ClientSession, ClientTimeout @@ -23,7 +24,7 @@ def __init__(self, *, session: Optional[ClientSession] = None) -> None: # This is disabled until a workaround can be found: # self.track = Track(self._request) - async def _request( + async def _request( # pylint: disable=too-many-arguments self, method: str, url: str, @@ -50,7 +51,7 @@ async def _request( data: dict = await resp.json(content_type=None) return data except ClientError as err: - raise RequestError(f"Error requesting data from {url}: {err}") + raise RequestError(f"Error requesting data from {url}: {err}") from err finally: if not use_running_session: await session.close() diff --git a/pyseventeentrack/errors.py b/pyseventeentrack/errors.py index b43ff93..1150110 100644 --- a/pyseventeentrack/errors.py +++ b/pyseventeentrack/errors.py @@ -4,16 +4,10 @@ class SeventeenTrackError(Exception): """Define a base error.""" - pass - class InvalidTrackingNumberError(SeventeenTrackError): """Define an error for an invalid tracking number.""" - pass - class RequestError(SeventeenTrackError): """Define an error for HTTP request errors.""" - - pass diff --git a/pyseventeentrack/package.py b/pyseventeentrack/package.py index ba6acdb..404037b 100644 --- a/pyseventeentrack/package.py +++ b/pyseventeentrack/package.py @@ -1,4 +1,5 @@ """Define a simple structure for a package.""" + from datetime import datetime from typing import Dict, Optional @@ -255,10 +256,8 @@ } -@attr.s( - frozen=True -) # pylint: disable=too-few-public-methods,too-many-instance-attributes -class Package: +@attr.s(frozen=True) +class Package: # pylint: disable=too-few-public-methods,too-many-instance-attributes """Define a package object.""" tracking_number: str = attr.ib() diff --git a/pyseventeentrack/profile.py b/pyseventeentrack/profile.py index b117dcd..01a047d 100644 --- a/pyseventeentrack/profile.py +++ b/pyseventeentrack/profile.py @@ -1,4 +1,5 @@ """Define interaction with a user profile.""" + import json import logging from typing import Callable, Coroutine, List, Optional, Union @@ -141,10 +142,10 @@ async def add_package( new_package = next( p for p in packages if p.tracking_number == tracking_number ) - except StopIteration: + except StopIteration as err: raise InvalidTrackingNumberError( f"Recently added package not found by tracking number: {tracking_number}" - ) + ) from err _LOGGER.debug("Found internal ID of recently added package: %s", new_package.id) diff --git a/pyseventeentrack/track.py b/pyseventeentrack/track.py index 965a0a1..8795ec6 100644 --- a/pyseventeentrack/track.py +++ b/pyseventeentrack/track.py @@ -1,4 +1,5 @@ """Define interaction with an individual package.""" + from typing import Callable, Coroutine, List from .errors import InvalidTrackingNumberError diff --git a/requirements_test.txt b/requirements_test.txt index 07e9c2b..c7196f6 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -1,6 +1,7 @@ aiohttp>=3.8.0 -aresponses==1.1.2 +aresponses==3.0.0 pytest-aiohttp==0.3.0 pytest-cov==2.8.1 -pytest==6.2.5 +pytest==8.2.2 pytz>=2021.1 +pre-commit diff --git a/script/run-in-env.sh b/script/run-in-env.sh new file mode 100755 index 0000000..1c7f76c --- /dev/null +++ b/script/run-in-env.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env sh +set -eu + +# Used in venv activate script. +# Would be an error if undefined. +OSTYPE="${OSTYPE-}" + +# Activate pyenv and virtualenv if present, then run the specified command + +# pyenv, pyenv-virtualenv +if [ -s .python-version ]; then + PYENV_VERSION=$(head -n 1 .python-version) + export PYENV_VERSION +fi + +if [ -n "${VIRTUAL_ENV-}" ] && [ -f "${VIRTUAL_ENV}/bin/activate" ]; then + . "${VIRTUAL_ENV}/bin/activate" +else + # other common virtualenvs + my_path=$(git rev-parse --show-toplevel) + + for venv in venv .venv .; do + if [ -f "${my_path}/${venv}/bin/activate" ]; then + . "${my_path}/${venv}/bin/activate" + break + fi + done +fi + +exec "$@" diff --git a/tests/common.py b/tests/common.py index abb3063..7e60a9a 100644 --- a/tests/common.py +++ b/tests/common.py @@ -1,10 +1,21 @@ """Define common test utilities.""" + import os +import pytest +from aresponses import ResponsesMockServer # type: ignore + TEST_EMAIL = "user@email.com" TEST_PASSWORD = "password" +@pytest.fixture(autouse=True) +async def aresponses(loop): + """replace aresponses""" + async with ResponsesMockServer(loop=loop) as server: + yield server + + def load_fixture(filename): """Load a fixture.""" path = os.path.join(os.path.dirname(__file__), "fixtures", filename) diff --git a/tests/test_client.py b/tests/test_client.py index f667845..bf1da84 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -1,4 +1,5 @@ """Define tests for the client object.""" + import aiohttp import pytest @@ -16,4 +17,4 @@ async def test_bad_request(aresponses): with pytest.raises(RequestError): async with aiohttp.ClientSession() as session: client = Client(session=session) - await client._request("get", "https://random.domain/no/good") + await client._request("get", "https://random.domain/no/good") # pylint: disable=protected-access diff --git a/tests/test_profile.py b/tests/test_profile.py index 26ba4bf..29da1c0 100644 --- a/tests/test_profile.py +++ b/tests/test_profile.py @@ -1,13 +1,10 @@ """Define tests for the client object.""" -from datetime import datetime import aiohttp import pytest -from pytz import UTC, timezone from pyseventeentrack import Client from pyseventeentrack.errors import InvalidTrackingNumberError, RequestError - from .common import TEST_EMAIL, TEST_PASSWORD, load_fixture From 4bcc33c487eb391277e5a85b39a1d4b4f5dab49e Mon Sep 17 00:00:00 2001 From: "shai.ungar" Date: Fri, 12 Jul 2024 14:19:29 +0300 Subject: [PATCH 2/2] update requirements_test.txt --- requirements_test.txt | 41 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/requirements_test.txt b/requirements_test.txt index c7196f6..fdae1e7 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -1,7 +1,40 @@ -aiohttp>=3.8.0 +aiohttp==3.9.5 +aioresponses==0.7.6 +aiosignal==1.3.1 aresponses==3.0.0 +astroid==3.2.3 +attrs==23.2.0 +cfgv==3.4.0 +coverage==7.5.4 +dill==0.3.8 +distlib==0.3.8 +filelock==3.15.4 +frozenlist==1.4.1 +identify==2.6.0 +idna==3.7 +iniconfig==2.0.0 +isort==5.13.2 +mccabe==0.7.0 +multidict==6.0.5 +mypy==1.10.1 +mypy-extensions==1.0.0 +nodeenv==1.9.1 +packaging==24.1 +platformdirs==4.2.2 +pluggy==1.5.0 +pre-commit==3.7.1 +py==1.11.0 +pylint==3.2.5 +pytest==8.2.2 pytest-aiohttp==0.3.0 +pytest-asyncio==0.23.7 pytest-cov==2.8.1 -pytest==8.2.2 -pytz>=2021.1 -pre-commit +pytz==2024.1 +PyYAML==6.0.1 +ruff==0.5.1 +toml==0.10.2 +tomlkit==0.13.0 +types-pytz==2024.1.0.20240417 +typing_extensions==4.12.2 +virtualenv==20.26.3 +yarl==1.9.4