diff --git a/.flake8 b/.flake8 deleted file mode 100644 index ae4540b..0000000 --- a/.flake8 +++ /dev/null @@ -1,5 +0,0 @@ -[flake8] -max-line-length = 100 -max-complexity = 18 -select = B,C,D,E,F,W,T4,B9 -ignore = W503 diff --git a/.github/workflows/ruff.yml b/.github/workflows/ruff.yml new file mode 100644 index 0000000..757cae6 --- /dev/null +++ b/.github/workflows/ruff.yml @@ -0,0 +1,8 @@ +name: Ruff +on: [ push, pull_request ] +jobs: + ruff: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: chartboost/ruff-action@v1 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index baf8d56..a76c1aa 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -3,23 +3,9 @@ repos: rev: v2.2.0 hooks: - id: seed-isort-config - - repo: https://github.com/pycqa/isort - rev: 5.13.2 + - repo: https://github.com/astral-sh/ruff-pre-commit + # Ruff version. + rev: v0.2.0 hooks: - - id: isort - - repo: https://github.com/ambv/black - rev: 24.1.1 - hooks: - - id: black - language_version: python3.11 - - repo: https://github.com/PyCQA/flake8 - rev: 7.0.0 - hooks: - - id: flake8 - additional_dependencies: - [flake8-docstrings, flake8-builtins, flake8-rst-docstrings] - - repo: https://github.com/asottile/pyupgrade - rev: v3.15.0 - hooks: - - id: pyupgrade - args: ["--py36-plus", "--py37-plus", "--py38-plus", "--py39-plus"] + - id: ruff + - id: ruff-format diff --git a/docs/source/__init__.py b/docs/source/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/docs/source/conf.py b/docs/source/conf.py index 9019357..c2a4bc3 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -15,9 +15,9 @@ import os import sys -sys.path.insert(0, os.path.abspath("../..")) +sys.path.insert(0, os.path.abspath("../..")) # noqa: PTH100 # This import needs to be *after* setting the sys path -import mokkari # noqa #E402 +import mokkari # E402 # -- Project information ----------------------------------------------------- diff --git a/mokkari/__init__.py b/mokkari/__init__.py index 42537e8..017061e 100644 --- a/mokkari/__init__.py +++ b/mokkari/__init__.py @@ -3,16 +3,15 @@ # Keep this at beginning of file to prevent circular import with session __version__ = "3.0.0" -from typing import Optional from mokkari import exceptions, session, sqlite_cache def api( - username: Optional[str] = None, - passwd: Optional[str] = None, + username: str | None = None, + passwd: str | None = None, cache: sqlite_cache.SqliteCache = None, - user_agent: Optional[str] = None, + user_agent: str | None = None, ) -> session.Session: """Entry function the sets login credentials for metron.cloud. diff --git a/mokkari/exceptions.py b/mokkari/exceptions.py index 62a39cd..6c3738f 100644 --- a/mokkari/exceptions.py +++ b/mokkari/exceptions.py @@ -12,22 +12,22 @@ class ApiError(Exception): """Class for any api errors.""" - def __init__(self, *args, **kwargs): + def __init__(self: "ApiError", *args: tuple[any], **kwargs: dict[str, any]) -> None: """Initialize an ApiError.""" Exception.__init__(self, *args, **kwargs) -class AuthenticationError(ApiError): +class AuthenticationError(Exception): """Class for any authentication errors.""" - def __init__(self, *args, **kwargs): + def __init__(self: "AuthenticationError", *args: tuple[any], **kwargs: dict[str, any]) -> None: """Initialize an AuthenticationError.""" Exception.__init__(self, *args, **kwargs) -class CacheError(ApiError): +class CacheError(Exception): """Class for any database cache errors.""" - def __init__(self, *args, **kwargs): + def __init__(self: "CacheError", *args: tuple[any], **kwargs: dict[str, any]) -> None: """Initialize an CacheError.""" Exception.__init__(self, *args, **kwargs) diff --git a/mokkari/schemas/character.py b/mokkari/schemas/character.py index 092624f..8ffdb4e 100644 --- a/mokkari/schemas/character.py +++ b/mokkari/schemas/character.py @@ -1,3 +1,4 @@ +# ruff: noqa: RUF012 """ Character module. diff --git a/mokkari/schemas/issue.py b/mokkari/schemas/issue.py index 22e51ed..a41c39b 100644 --- a/mokkari/schemas/issue.py +++ b/mokkari/schemas/issue.py @@ -1,3 +1,4 @@ +# ruff: noqa: RUF012 """ Issue module. diff --git a/mokkari/schemas/series.py b/mokkari/schemas/series.py index be25454..bb98f78 100644 --- a/mokkari/schemas/series.py +++ b/mokkari/schemas/series.py @@ -1,3 +1,4 @@ +# ruff: noqa: RUF012 """ Series module. diff --git a/mokkari/schemas/team.py b/mokkari/schemas/team.py index 2c25d19..7c2afb5 100644 --- a/mokkari/schemas/team.py +++ b/mokkari/schemas/team.py @@ -1,3 +1,4 @@ +# ruff: noqa: RUF012 """ Team module. diff --git a/mokkari/session.py b/mokkari/session.py index 5302a6e..5e356ff 100644 --- a/mokkari/session.py +++ b/mokkari/session.py @@ -8,7 +8,7 @@ import platform from collections import OrderedDict -from typing import Any, Optional, Union +from typing import Any from urllib.parse import urlencode import requests @@ -45,26 +45,26 @@ class Session: """ def __init__( - self, + self: "Session", username: str, passwd: str, - cache: Optional[sqlite_cache.SqliteCache] = None, - user_agent: Optional[str] = None, + cache: sqlite_cache.SqliteCache | None = None, + user_agent: str | None = None, ) -> None: """Initialize a new Session.""" self.username = username self.passwd = passwd self.header = { "User-Agent": f"{f'{user_agent} ' if user_agent is not None else ''}" - + f"Mokkari/{__version__} ({platform.system()}; {platform.release()})" + f"Mokkari/{__version__} ({platform.system()}; {platform.release()})" } self.api_url = "https://metron.cloud/api/{}/" self.cache = cache def _call( - self, - endpoint: list[Union[str, int]], - params: Optional[dict[str, Union[str, int]]] = None, + self: "Session", + endpoint: list[str | int], + params: dict[str, str | int] | None = None, ) -> dict[str, Any]: """ Make request for api endpoints. @@ -97,7 +97,7 @@ def _call( return data - def creator(self, _id: int) -> Creator: + def creator(self: "Session", _id: int) -> Creator: """ Request data for a creator based on its ``_id``. @@ -119,7 +119,7 @@ def creator(self, _id: int) -> Creator: return result def creators_list( - self, params: Optional[dict[str, Union[str, int]]] = None + self: "Session", params: dict[str, str | int] | None = None ) -> list[BaseResource]: """ Request a list of creators. @@ -138,7 +138,7 @@ def creators_list( raise exceptions.ApiError(error) from error return result - def character(self, _id: int) -> Character: + def character(self: "Session", _id: int) -> Character: """ Request data for a character based on its ``_id``. @@ -160,7 +160,7 @@ def character(self, _id: int) -> Character: return result def characters_list( - self, params: Optional[dict[str, Union[str, int]]] = None + self: "Session", params: dict[str, str | int] | None = None ) -> list[BaseResource]: """ Request a list of characters. @@ -179,7 +179,7 @@ def characters_list( raise exceptions.ApiError(error) from error return result - def character_issues_list(self, _id: int) -> list[BaseIssue]: + def character_issues_list(self: "Session", _id: int) -> list[BaseIssue]: """ Request a list of issues that a character appears in. @@ -199,7 +199,7 @@ def character_issues_list(self, _id: int) -> list[BaseIssue]: raise exceptions.ApiError(err) from err return result - def publisher(self, _id: int) -> Publisher: + def publisher(self: "Session", _id: int) -> Publisher: """ Request data for a publisher based on its ``_id``. @@ -221,7 +221,7 @@ def publisher(self, _id: int) -> Publisher: return result def publishers_list( - self, params: Optional[dict[str, Union[str, int]]] = None + self: "Session", params: dict[str, str | int] | None = None ) -> list[BaseResource]: """ Request a list of publishers. @@ -240,7 +240,7 @@ def publishers_list( raise exceptions.ApiError(err) from err return result - def team(self, _id: int) -> Team: + def team(self: "Session", _id: int) -> Team: """ Request data for a team based on its ``_id``. @@ -261,7 +261,9 @@ def team(self, _id: int) -> Team: raise exceptions.ApiError(error) from error return result - def teams_list(self, params: Optional[dict[str, Union[str, int]]] = None) -> list[BaseResource]: + def teams_list( + self: "Session", params: dict[str, str | int] | None = None + ) -> list[BaseResource]: """ Request a list of teams. @@ -279,7 +281,7 @@ def teams_list(self, params: Optional[dict[str, Union[str, int]]] = None) -> lis raise exceptions.ApiError(err) from err return result - def team_issues_list(self, _id: int) -> list[BaseIssue]: + def team_issues_list(self: "Session", _id: int) -> list[BaseIssue]: """ Request a list of issues that a team appears in. @@ -299,7 +301,7 @@ def team_issues_list(self, _id: int) -> list[BaseIssue]: raise exceptions.ApiError(err) from err return result - def arc(self, _id: int) -> Arc: + def arc(self: "Session", _id: int) -> Arc: """ Request data for a story arc based on its ``_id``. @@ -320,7 +322,9 @@ def arc(self, _id: int) -> Arc: raise exceptions.ApiError(err) from err return result - def arcs_list(self, params: Optional[dict[str, Union[str, int]]] = None) -> list[BaseResource]: + def arcs_list( + self: "Session", params: dict[str, str | int] | None = None + ) -> list[BaseResource]: """ Request a list of story arcs. @@ -338,7 +342,7 @@ def arcs_list(self, params: Optional[dict[str, Union[str, int]]] = None) -> list raise exceptions.ApiError(err) from err return result - def arc_issues_list(self, _id: int) -> list[BaseIssue]: + def arc_issues_list(self: "Session", _id: int) -> list[BaseIssue]: """ Request a list of issues for a story arc. @@ -356,7 +360,7 @@ def arc_issues_list(self, _id: int) -> list[BaseIssue]: raise exceptions.ApiError(err) from err return result - def series(self, _id: int) -> Series: + def series(self: "Session", _id: int) -> Series: """ Request data for a series based on its ``_id``. @@ -377,7 +381,9 @@ def series(self, _id: int) -> Series: raise exceptions.ApiError(err) from err return result - def series_list(self, params: Optional[dict[str, Union[str, int]]] = None) -> list[BaseSeries]: + def series_list( + self: "Session", params: dict[str, str | int] | None = None + ) -> list[BaseSeries]: """ Request a list of series. @@ -396,7 +402,7 @@ def series_list(self, params: Optional[dict[str, Union[str, int]]] = None) -> li return result def series_type_list( - self, params: Optional[dict[str, Union[str, int]]] = None + self: "Session", params: dict[str, str | int] | None = None ) -> list[GenericItem]: """ Request a list of series types. @@ -419,7 +425,7 @@ def series_type_list( raise exceptions.ApiError(err) from err return result - def issue(self, _id: int) -> Issue: + def issue(self: "Session", _id: int) -> Issue: """ Request data for an issue based on it's ``_id``. @@ -440,7 +446,7 @@ def issue(self, _id: int) -> Issue: raise exceptions.ApiError(error) from error return result - def issues_list(self, params: Optional[dict[str, Union[str, int]]] = None) -> list[BaseIssue]: + def issues_list(self: "Session", params: dict[str, str | int] | None = None) -> list[BaseIssue]: """ Request a list of issues. @@ -458,7 +464,7 @@ def issues_list(self, params: Optional[dict[str, Union[str, int]]] = None) -> li raise exceptions.ApiError(err) from err return result - def role_list(self, params: Optional[dict[str, Union[str, int]]] = None) -> list[GenericItem]: + def role_list(self: "Session", params: dict[str, str | int] | None = None) -> list[GenericItem]: """ Request a list of creator roles. @@ -477,7 +483,7 @@ def role_list(self, params: Optional[dict[str, Union[str, int]]] = None) -> list raise exceptions.ApiError(err) from err return result - def universe(self, _id: int) -> Universe: + def universe(self: "Session", _id: int) -> Universe: """ Request data for a universe based on its ``_id``. @@ -499,7 +505,7 @@ def universe(self, _id: int) -> Universe: return result def universes_list( - self, params: Optional[dict[str, Union[str, int]]] = None + self: "Session", params: dict[str, str | int] | None = None ) -> list[BaseResource]: """ Request a list of universes. @@ -519,9 +525,9 @@ def universes_list( return result def _get_results( - self, - endpoint: list[Union[str, int]], - params: Optional[dict[str, Union[str, int]]] = None, + self: "Session", + endpoint: list[str | int], + params: dict[str, str | int] | None = None, ) -> dict[str, Any]: if params is None: params = {} @@ -531,7 +537,7 @@ def _get_results( result = self._retrieve_all_results(result) return result - def _retrieve_all_results(self, data: dict[str, Any]) -> dict[str, Any]: + def _retrieve_all_results(self: "Session", data: dict[str, Any]) -> dict[str, Any]: has_next_page = True next_page = data["next"] @@ -558,7 +564,7 @@ def _retrieve_all_results(self, data: dict[str, Any]) -> dict[str, Any]: @sleep_and_retry @limits(calls=25, period=ONE_MINUTE) - def _request_data(self, url: str, params: Optional[dict[str, Union[str, int]]] = None) -> Any: + def _request_data(self: "Session", url: str, params: dict[str, str | int] | None = None) -> Any: # noqa: ANN401 if params is None: params = {} @@ -574,11 +580,11 @@ def _request_data(self, url: str, params: Optional[dict[str, Union[str, int]]] = headers=self.header, ).json() except requests.exceptions.ConnectionError as e: - raise exceptions.ApiError(f"Connection error: {repr(e)}") from e + raise exceptions.ApiError(f"Connection error: {e!r}") from e return response - def _get_results_from_cache(self, key: str) -> Optional[Any]: + def _get_results_from_cache(self: "Session", key: str) -> Any | None: # noqa: ANN401 cached_response = None if self.cache: @@ -586,16 +592,16 @@ def _get_results_from_cache(self, key: str) -> Optional[Any]: cached_response = self.cache.get(key) except AttributeError as e: raise exceptions.CacheError( - f"Cache object passed in is missing attribute: {repr(e)}" + f"Cache object passed in is missing attribute: {e!r}" ) from e return cached_response - def _save_results_to_cache(self, key: str, data: str) -> None: + def _save_results_to_cache(self: "Session", key: str, data: str) -> None: if self.cache: try: self.cache.store(key, data) except AttributeError as e: raise exceptions.CacheError( - f"Cache object passed in is missing attribute: {repr(e)}" + f"Cache object passed in is missing attribute: {e!r}" ) from e diff --git a/mokkari/sqlite_cache.py b/mokkari/sqlite_cache.py index e444e0e..acef7df 100644 --- a/mokkari/sqlite_cache.py +++ b/mokkari/sqlite_cache.py @@ -8,8 +8,8 @@ import json import sqlite3 -from datetime import datetime, timedelta -from typing import Any, Optional +from datetime import datetime, timedelta, timezone +from typing import Any class SqliteCache: @@ -22,7 +22,9 @@ class SqliteCache: before they expire. """ - def __init__(self, db_name: str = "mokkari_cache.db", expire: Optional[int] = None) -> None: + def __init__( + self: "SqliteCache", db_name: str = "mokkari_cache.db", expire: int | None = None + ) -> None: """Initialize a new SqliteCache.""" self.expire = expire self.con = sqlite3.connect(db_name) @@ -30,7 +32,7 @@ def __init__(self, db_name: str = "mokkari_cache.db", expire: Optional[int] = No self.cur.execute("CREATE TABLE IF NOT EXISTS responses (key, json, expire)") self.cleanup() - def get(self, key: str) -> Optional[Any]: + def get(self: "SqliteCache", key: str) -> Any | None: # noqa: ANN401 """ Retrieve data from the cache database. @@ -40,7 +42,7 @@ def get(self, key: str) -> Optional[Any]: self.cur.execute("SELECT json FROM responses WHERE key = ?", (key,)) return json.loads(result[0]) if (result := self.cur.fetchone()) else None - def store(self, key: str, value: str) -> None: + def store(self: "SqliteCache", key: str, value: str) -> None: """ Save data to the cache database. @@ -54,19 +56,20 @@ def store(self, key: str, value: str) -> None: ) self.con.commit() - def cleanup(self) -> None: + def cleanup(self: "SqliteCache") -> None: """Remove any expired data from the cache database.""" if not self.expire: return self.cur.execute( "DELETE FROM responses WHERE expire < ?;", - (datetime.now().strftime("%Y-%m-%d"),), + (datetime.now(tz=timezone.utc).strftime("%Y-%m-%d"),), ) self.con.commit() - def _determine_expire_str(self) -> str: - if self.expire: - dt = datetime.now() + timedelta(days=self.expire) - else: - dt = datetime.now() + def _determine_expire_str(self: "SqliteCache") -> str: + dt = ( + datetime.now(tz=timezone.utc) + timedelta(days=self.expire) + if self.expire + else datetime.now(tz=timezone.utc) + ) return dt.strftime("%Y-%m-%d") diff --git a/poetry.lock b/poetry.lock index 67c7edd..389ab4e 100644 --- a/poetry.lock +++ b/poetry.lock @@ -47,52 +47,6 @@ files = [ [package.extras] dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"] -[[package]] -name = "black" -version = "23.12.1" -description = "The uncompromising code formatter." -optional = false -python-versions = ">=3.8" -files = [ - {file = "black-23.12.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e0aaf6041986767a5e0ce663c7a2f0e9eaf21e6ff87a5f95cbf3675bfd4c41d2"}, - {file = "black-23.12.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c88b3711d12905b74206227109272673edce0cb29f27e1385f33b0163c414bba"}, - {file = "black-23.12.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a920b569dc6b3472513ba6ddea21f440d4b4c699494d2e972a1753cdc25df7b0"}, - {file = "black-23.12.1-cp310-cp310-win_amd64.whl", hash = "sha256:3fa4be75ef2a6b96ea8d92b1587dd8cb3a35c7e3d51f0738ced0781c3aa3a5a3"}, - {file = "black-23.12.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8d4df77958a622f9b5a4c96edb4b8c0034f8434032ab11077ec6c56ae9f384ba"}, - {file = "black-23.12.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:602cfb1196dc692424c70b6507593a2b29aac0547c1be9a1d1365f0d964c353b"}, - {file = "black-23.12.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c4352800f14be5b4864016882cdba10755bd50805c95f728011bcb47a4afd59"}, - {file = "black-23.12.1-cp311-cp311-win_amd64.whl", hash = "sha256:0808494f2b2df923ffc5723ed3c7b096bd76341f6213989759287611e9837d50"}, - {file = "black-23.12.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:25e57fd232a6d6ff3f4478a6fd0580838e47c93c83eaf1ccc92d4faf27112c4e"}, - {file = "black-23.12.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2d9e13db441c509a3763a7a3d9a49ccc1b4e974a47be4e08ade2a228876500ec"}, - {file = "black-23.12.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d1bd9c210f8b109b1762ec9fd36592fdd528485aadb3f5849b2740ef17e674e"}, - {file = "black-23.12.1-cp312-cp312-win_amd64.whl", hash = "sha256:ae76c22bde5cbb6bfd211ec343ded2163bba7883c7bc77f6b756a1049436fbb9"}, - {file = "black-23.12.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1fa88a0f74e50e4487477bc0bb900c6781dbddfdfa32691e780bf854c3b4a47f"}, - {file = "black-23.12.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a4d6a9668e45ad99d2f8ec70d5c8c04ef4f32f648ef39048d010b0689832ec6d"}, - {file = "black-23.12.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b18fb2ae6c4bb63eebe5be6bd869ba2f14fd0259bda7d18a46b764d8fb86298a"}, - {file = "black-23.12.1-cp38-cp38-win_amd64.whl", hash = "sha256:c04b6d9d20e9c13f43eee8ea87d44156b8505ca8a3c878773f68b4e4812a421e"}, - {file = "black-23.12.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3e1b38b3135fd4c025c28c55ddfc236b05af657828a8a6abe5deec419a0b7055"}, - {file = "black-23.12.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4f0031eaa7b921db76decd73636ef3a12c942ed367d8c3841a0739412b260a54"}, - {file = "black-23.12.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:97e56155c6b737854e60a9ab1c598ff2533d57e7506d97af5481141671abf3ea"}, - {file = "black-23.12.1-cp39-cp39-win_amd64.whl", hash = "sha256:dd15245c8b68fe2b6bd0f32c1556509d11bb33aec9b5d0866dd8e2ed3dba09c2"}, - {file = "black-23.12.1-py3-none-any.whl", hash = "sha256:78baad24af0f033958cad29731e27363183e140962595def56423e626f4bee3e"}, - {file = "black-23.12.1.tar.gz", hash = "sha256:4ce3ef14ebe8d9509188014d96af1c456a910d5b5cbf434a09fef7e024b3d0d5"}, -] - -[package.dependencies] -click = ">=8.0.0" -mypy-extensions = ">=0.4.3" -packaging = ">=22.0" -pathspec = ">=0.9.0" -platformdirs = ">=2" -tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} -typing-extensions = {version = ">=4.0.1", markers = "python_version < \"3.11\""} - -[package.extras] -colorama = ["colorama (>=0.4.3)"] -d = ["aiohttp (>=3.7.4)", "aiohttp (>=3.7.4,!=3.9.0)"] -jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] -uvloop = ["uvloop (>=0.15.2)"] - [[package]] name = "cachetools" version = "5.3.2" @@ -236,20 +190,6 @@ files = [ {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, ] -[[package]] -name = "click" -version = "8.1.7" -description = "Composable command line interface toolkit" -optional = false -python-versions = ">=3.7" -files = [ - {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, - {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} - [[package]] name = "colorama" version = "0.4.6" @@ -394,73 +334,6 @@ docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1 testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)"] typing = ["typing-extensions (>=4.8)"] -[[package]] -name = "flake8" -version = "6.1.0" -description = "the modular source code checker: pep8 pyflakes and co" -optional = false -python-versions = ">=3.8.1" -files = [ - {file = "flake8-6.1.0-py2.py3-none-any.whl", hash = "sha256:ffdfce58ea94c6580c77888a86506937f9a1a227dfcd15f245d694ae20a6b6e5"}, - {file = "flake8-6.1.0.tar.gz", hash = "sha256:d5b3857f07c030bdb5bf41c7f53799571d75c4491748a3adcd47de929e34cd23"}, -] - -[package.dependencies] -mccabe = ">=0.7.0,<0.8.0" -pycodestyle = ">=2.11.0,<2.12.0" -pyflakes = ">=3.1.0,<3.2.0" - -[[package]] -name = "flake8-builtins" -version = "2.2.0" -description = "Check for python builtins being used as variables or parameters" -optional = false -python-versions = ">=3.8" -files = [ - {file = "flake8_builtins-2.2.0-py3-none-any.whl", hash = "sha256:7ee5766d9c60e5d579dfda84e65c6d0e6c26005f6f59cb9bf722462d7987a807"}, - {file = "flake8_builtins-2.2.0.tar.gz", hash = "sha256:392d5af3a0720c5a863aa93dc47f48c879081345a143fe9f20d995fe9ff5686a"}, -] - -[package.dependencies] -flake8 = "*" - -[package.extras] -test = ["pytest"] - -[[package]] -name = "flake8-docstrings" -version = "1.7.0" -description = "Extension for flake8 which uses pydocstyle to check docstrings" -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-rst-docstrings" -version = "0.3.0" -description = "Python docstring reStructuredText (RST) validator for flake8" -optional = false -python-versions = ">=3.7" -files = [ - {file = "flake8-rst-docstrings-0.3.0.tar.gz", hash = "sha256:d1ce22b4bd37b73cd86b8d980e946ef198cfcc18ed82fedb674ceaa2f8d1afa4"}, - {file = "flake8_rst_docstrings-0.3.0-py3-none-any.whl", hash = "sha256:f8c3c6892ff402292651c31983a38da082480ad3ba253743de52989bdc84ca1c"}, -] - -[package.dependencies] -flake8 = ">=3" -pygments = "*" -restructuredtext-lint = "*" - -[package.extras] -develop = ["build", "twine"] - [[package]] name = "identify" version = "2.5.33" @@ -508,20 +381,6 @@ files = [ {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, ] -[[package]] -name = "isort" -version = "5.13.2" -description = "A Python utility / library to sort Python imports." -optional = false -python-versions = ">=3.8.0" -files = [ - {file = "isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"}, - {file = "isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109"}, -] - -[package.extras] -colors = ["colorama (>=0.4.6)"] - [[package]] name = "jinja2" version = "3.1.3" @@ -608,28 +467,6 @@ files = [ {file = "MarkupSafe-2.1.4.tar.gz", hash = "sha256:3aae9af4cac263007fd6309c64c6ab4506dd2b79382d9d19a1994f9240b8db4f"}, ] -[[package]] -name = "mccabe" -version = "0.7.0" -description = "McCabe checker, plugin for flake8" -optional = false -python-versions = ">=3.6" -files = [ - {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, - {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, -] - -[[package]] -name = "mypy-extensions" -version = "1.0.0" -description = "Type system extensions for programs checked with the mypy type checker." -optional = false -python-versions = ">=3.5" -files = [ - {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, - {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, -] - [[package]] name = "nodeenv" version = "1.8.0" @@ -655,17 +492,6 @@ files = [ {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, ] -[[package]] -name = "pathspec" -version = "0.12.1" -description = "Utility library for gitignore style pattern matching of file paths." -optional = false -python-versions = ">=3.8" -files = [ - {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, - {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, -] - [[package]] name = "platformdirs" version = "4.1.0" @@ -728,17 +554,6 @@ nodeenv = ">=0.11.1" pyyaml = ">=5.1" virtualenv = ">=20.10.0" -[[package]] -name = "pycodestyle" -version = "2.11.1" -description = "Python style guide checker" -optional = false -python-versions = ">=3.8" -files = [ - {file = "pycodestyle-2.11.1-py2.py3-none-any.whl", hash = "sha256:44fe31000b2d866f2e41841b18528a505fbd7fef9017b04eff4e2648a0fadc67"}, - {file = "pycodestyle-2.11.1.tar.gz", hash = "sha256:41ba0e7afc9752dfb53ced5489e89f8186be00e599e712660695b7a75ff2663f"}, -] - [[package]] name = "pydantic" version = "2.5.3" @@ -875,34 +690,6 @@ files = [ [package.dependencies] typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" -[[package]] -name = "pydocstyle" -version = "6.3.0" -description = "Python docstring style checker" -optional = false -python-versions = ">=3.6" -files = [ - {file = "pydocstyle-6.3.0-py3-none-any.whl", hash = "sha256:118762d452a49d6b05e194ef344a55822987a462831ade91ec5c06fd2169d019"}, - {file = "pydocstyle-6.3.0.tar.gz", hash = "sha256:7ce43f0c0ac87b07494eb9c0b462c0b73e6ff276807f204d6b53edc72b7e44e1"}, -] - -[package.dependencies] -snowballstemmer = ">=2.2.0" - -[package.extras] -toml = ["tomli (>=1.2.3)"] - -[[package]] -name = "pyflakes" -version = "3.1.0" -description = "passive checker of Python programs" -optional = false -python-versions = ">=3.8" -files = [ - {file = "pyflakes-3.1.0-py2.py3-none-any.whl", hash = "sha256:4132f6d49cb4dae6819e5379898f2b8cce3c5f23994194c24b77d5da2e36f774"}, - {file = "pyflakes-3.1.0.tar.gz", hash = "sha256:a0aae034c444db0071aa077972ba4768d40c830d9539fd45bf4cd3f8f6992efc"}, -] - [[package]] name = "pygments" version = "2.17.2" @@ -997,20 +784,6 @@ psutil = ["psutil (>=3.0)"] setproctitle = ["setproctitle"] testing = ["filelock"] -[[package]] -name = "pyupgrade" -version = "3.15.0" -description = "A tool to automatically upgrade syntax for newer versions." -optional = false -python-versions = ">=3.8.1" -files = [ - {file = "pyupgrade-3.15.0-py2.py3-none-any.whl", hash = "sha256:8dc8ebfaed43566e2c65994162795017c7db11f531558a74bc8aa077907bc305"}, - {file = "pyupgrade-3.15.0.tar.gz", hash = "sha256:a7fde381060d7c224f55aef7a30fae5ac93bbc428367d27e70a603bc2acd4f00"}, -] - -[package.dependencies] -tokenize-rt = ">=5.2.0" - [[package]] name = "pyyaml" version = "6.0.1" @@ -1121,18 +894,31 @@ fixture = ["fixtures"] test = ["fixtures", "mock", "purl", "pytest", "requests-futures", "sphinx", "testtools"] [[package]] -name = "restructuredtext-lint" -version = "1.4.0" -description = "reStructuredText linter" +name = "ruff" +version = "0.2.0" +description = "An extremely fast Python linter and code formatter, written in Rust." optional = false -python-versions = "*" +python-versions = ">=3.7" files = [ - {file = "restructuredtext_lint-1.4.0.tar.gz", hash = "sha256:1b235c0c922341ab6c530390892eb9e92f90b9b75046063e047cacfb0f050c45"}, + {file = "ruff-0.2.0-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:638ea3294f800d18bae84a492cb5a245c8d29c90d19a91d8e338937a4c27fca0"}, + {file = "ruff-0.2.0-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:3ff35433fcf4dff6d610738712152df6b7d92351a1bde8e00bd405b08b3d5759"}, + {file = "ruff-0.2.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf9faafbdcf4f53917019f2c230766da437d4fd5caecd12ddb68bb6a17d74399"}, + {file = "ruff-0.2.0-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8153a3e4128ed770871c47545f1ae7b055023e0c222ff72a759f5a341ee06483"}, + {file = "ruff-0.2.0-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e8a75a98ae989a27090e9c51f763990ad5bbc92d20626d54e9701c7fe597f399"}, + {file = "ruff-0.2.0-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:87057dd2fdde297130ff99553be8549ca38a2965871462a97394c22ed2dfc19d"}, + {file = "ruff-0.2.0-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6d232f99d3ab00094ebaf88e0fb7a8ccacaa54cc7fa3b8993d9627a11e6aed7a"}, + {file = "ruff-0.2.0-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d3c641f95f435fc6754b05591774a17df41648f0daf3de0d75ad3d9f099ab92"}, + {file = "ruff-0.2.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3826fb34c144ef1e171b323ed6ae9146ab76d109960addca730756dc19dc7b22"}, + {file = "ruff-0.2.0-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:eceab7d85d09321b4de18b62d38710cf296cb49e98979960a59c6b9307c18cfe"}, + {file = "ruff-0.2.0-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:30ad74687e1f4a9ff8e513b20b82ccadb6bd796fe5697f1e417189c5cde6be3e"}, + {file = "ruff-0.2.0-py3-none-musllinux_1_2_i686.whl", hash = "sha256:a7e3818698f8460bd0f8d4322bbe99db8327e9bc2c93c789d3159f5b335f47da"}, + {file = "ruff-0.2.0-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:edf23041242c48b0d8295214783ef543847ef29e8226d9f69bf96592dba82a83"}, + {file = "ruff-0.2.0-py3-none-win32.whl", hash = "sha256:e155147199c2714ff52385b760fe242bb99ea64b240a9ffbd6a5918eb1268843"}, + {file = "ruff-0.2.0-py3-none-win_amd64.whl", hash = "sha256:ba918e01cdd21e81b07555564f40d307b0caafa9a7a65742e98ff244f5035c59"}, + {file = "ruff-0.2.0-py3-none-win_arm64.whl", hash = "sha256:3fbaff1ba9564a2c5943f8f38bc221f04bac687cc7485e45237579fee7ccda79"}, + {file = "ruff-0.2.0.tar.gz", hash = "sha256:63856b91837606c673537d2889989733d7dffde553828d3b0f0bacfa6def54be"}, ] -[package.dependencies] -docutils = ">=0.11,<1.0" - [[package]] name = "seed-isort-config" version = "2.2.0" @@ -1361,17 +1147,6 @@ lint = ["docutils-stubs", "flake8", "mypy"] standalone = ["Sphinx (>=5)"] test = ["pytest"] -[[package]] -name = "tokenize-rt" -version = "5.2.0" -description = "A wrapper around the stdlib `tokenize` which roundtrips." -optional = false -python-versions = ">=3.8" -files = [ - {file = "tokenize_rt-5.2.0-py2.py3-none-any.whl", hash = "sha256:b79d41a65cfec71285433511b50271b05da3584a1da144a0752e9c621a285289"}, - {file = "tokenize_rt-5.2.0.tar.gz", hash = "sha256:9fe80f8a5c1edad2d3ede0f37481cc0cc1538a2f442c9c2f9e4feacd2792d054"}, -] - [[package]] name = "tomli" version = "2.0.1" @@ -1460,4 +1235,4 @@ test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess [metadata] lock-version = "2.0" python-versions = "^3.10" -content-hash = "7e1e331b3701d973569ce02d1e29cdf1294d80c88d53e0c94bf981baf9b09e88" +content-hash = "c27dc739eb52469a0a3afa03f56e8d7ca3bf56e9277145f600101ea88a0f7304" diff --git a/pyproject.toml b/pyproject.toml index 4d7f4a2..4a0c0f4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -39,18 +39,12 @@ pydantic = "^2.5.3" [tool.poetry.group.dev.dependencies] pytest = "^7.4.2" pytest-cov = "^4.1.0" -flake8 = "^6.1.0" pytest-xdist = "^3.3.1" requests-mock = "^1.9.3" -black = "^23.9.1" pre-commit = "^3.5.0" -isort = "^5.9.3" seed-isort-config = "^2.2.0" tox = "^4.11.3" -flake8-docstrings = "^1.6.0" -flake8-builtins = "^2.1.0" -flake8-rst-docstrings = "^0.3.0" -pyupgrade = "^3.15.0" +ruff = "^0.2.0" [tool.poetry.group.docs] optional = true @@ -63,10 +57,6 @@ sphinxcontrib-napoleon = "^0.7" requires = ["poetry-core>=1.1.0"] build-backend = "poetry.core.masonry.api" -[tool.black] -line-length = 100 -target-version = ['py310'] - [tool.isort] profile = "black" multi_line_output = 3 @@ -75,6 +65,68 @@ default_section = "THIRDPARTY" known_first_party = [] known_third_party = ["pydantic", "pytest", "ratelimit", "requests", "requests_mock", "urllib3"] +[tool.ruff] +fix = true +line-length = 100 +show-fixes = true +target-version = "py310" +lint.ignore = ["A001", "A003", "COM812", "COM819", "E501", "ISC001", "Q000", "Q001", "Q002", "Q003", "W191"] +lint.select = [ + "A", + "ANN", + "ARG", + "B", + "BLE", + "C40", + "COM", + "DTZ", + "E", + "ERA", + "F", + "G", + "I", + "ICN", + "INP", + "ISC", + "N", + "NPY", + "PD", + "PGH", + "PIE", + "PLC", + "PLE", + "PLW", + "PT", + "PTH", + "PYI", + "Q", + "RET", + "RSE", + "RUF", + "S", + "SIM", + "SLF", + "T10", + "T20", + "TCH", + "TID", + "UP", + "W", + "YTT" +] + +[tool.ruff.lint.flake8-annotations] +allow-star-arg-any = true + +[tool.ruff.lint.flake8-tidy-imports] +ban-relative-imports = "all" + +[tool.ruff.lint.isort] +combine-as-imports = true + +[tool.ruff.lint.per-file-ignores] +"tests/test_*.py" = ["ERA001", "S101", "SLF001"] + [tool.poetry.urls] "Homepage" = "https://github.com/Metron-Project/mokkari" "Bug Tracker" = "https://github.com/Metron-Project/mokkari/issues" diff --git a/tests/test_cache.py b/tests/test_cache.py index 07ccd00..3124b1a 100644 --- a/tests/test_cache.py +++ b/tests/test_cache.py @@ -13,7 +13,7 @@ class NoGet: """The NoGet object fakes storing data from the sqlite cache.""" - def store(self, key, value) -> None: + def store(self: "NoGet", key: any, value: any) -> None: # noqa: ARG002 """Save no data.""" # This method should store key value pair return @@ -22,9 +22,9 @@ def store(self, key, value) -> None: class NoStore: """The NoStore object fakes getting data from the sqlite cache.""" - def get(self, key) -> None: + def get(self: "NoStore", key: any) -> None: # noqa: ARG002 """Retrieve no data.""" - return None + return def test_no_get(dummy_username: str, dummy_password: str) -> None: diff --git a/tests/test_init.py b/tests/test_init.py index f4a48e5..348ff45 100644 --- a/tests/test_init.py +++ b/tests/test_init.py @@ -1,3 +1,4 @@ +# ruff: noqa: S106 """ Test Init module. @@ -23,7 +24,7 @@ def test_api() -> None: m = None try: m = api(username="Something", passwd="Else") - except Exception as exc: - print(f"mokkari.api() raised {exc} unexpectedly!") + except Exception as exc: # noqa: BLE001 + print(f"mokkari.api() raised {exc} unexpectedly!") # noqa: T201 assert m.__class__.__name__ == session.Session.__name__ diff --git a/tests/test_issues.py b/tests/test_issues.py index 5922ce7..8b7aeb2 100644 --- a/tests/test_issues.py +++ b/tests/test_issues.py @@ -5,7 +5,7 @@ """ import json -from datetime import date, datetime, timedelta, timezone +from datetime import date from decimal import Decimal import pytest diff --git a/tests/test_universes.py b/tests/test_universes.py index 014a5af..29fdf23 100644 --- a/tests/test_universes.py +++ b/tests/test_universes.py @@ -15,13 +15,13 @@ def test_known_universe(talker: Session) -> None: """Test for a known universe object.""" - DCeased = talker.universe(83) - assert isinstance(DCeased, Universe) - assert DCeased.name == "DCeased" - assert DCeased.designation == "Earth 55" - assert DCeased.publisher.name == "DC Comics" - assert DCeased.publisher.id == 2 - assert DCeased.resource_url.__str__() == "https://metron.cloud/universe/dceased/" + dceased = talker.universe(83) + assert isinstance(dceased, Universe) + assert dceased.name == "DCeased" + assert dceased.designation == "Earth 55" + assert dceased.publisher.name == "DC Comics" + assert dceased.publisher.id == 2 + assert dceased.resource_url.__str__() == "https://metron.cloud/universe/dceased/" def test_universe_list(talker: Session) -> None: diff --git a/tox.ini b/tox.ini index 1f72d8c..24365bf 100644 --- a/tox.ini +++ b/tox.ini @@ -5,5 +5,4 @@ envlist = py310, py311, py312 [testenv] allowlist_externals = poetry commands = - ; poetry install -v poetry run pytest tests/