From b6542235ced2fde556d9435470964496c6854cd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Corentin=20S=C3=A9chet?= Date: Wed, 30 Mar 2022 02:19:02 +0200 Subject: [PATCH] lint: switch mypy to strict --- .flake8 | 4 ++-- frontools/__init__.py | 1 + frontools/cache.py | 27 +++++++++++++++++---------- frontools/cli.py | 2 +- frontools/config.py | 13 +++++++------ frontools/sources.py | 7 ++++--- frontools/utils.py | 8 ++++---- noxfile.py | 22 +++++++++++----------- pyproject.toml | 6 ++++++ tests/__init__.py | 1 + 10 files changed, 54 insertions(+), 37 deletions(-) create mode 100644 tests/__init__.py diff --git a/.flake8 b/.flake8 index ba11b9c..ea4e97d 100644 --- a/.flake8 +++ b/.flake8 @@ -1,9 +1,9 @@ [flake8] -filename= marshpy tests ignore = # Line too long E501 -include = marshpy,test + # at least two spaces before inline comment + E261 max-complexity = 10 per-file-ignores = # Imported but unused diff --git a/frontools/__init__.py b/frontools/__init__.py index d83129b..2295de0 100644 --- a/frontools/__init__.py +++ b/frontools/__init__.py @@ -2,3 +2,4 @@ from .config import Config, SiteConfig from .utils import report_progress +from asyncio import gather diff --git a/frontools/cache.py b/frontools/cache.py index dc3ce1e..2956404 100644 --- a/frontools/cache.py +++ b/frontools/cache.py @@ -2,8 +2,7 @@ from abc import ABC, abstractmethod from pathlib import Path from pickle import dumps, loads -from typing import Awaitable, Callable, Generic, TypeVar, Union -from urllib.parse import urlparse +from typing import Awaitable, Callable, Generic, TypeVar, Union, cast from xdg import xdg_cache_home @@ -16,7 +15,9 @@ class Cache(Generic[ResourceType], ABC): """Base class for caches""" @abstractmethod - async def get(self, key: str, fallback: CacheFallback) -> ResourceType: + async def get( + self, key: str, fallback: CacheFallback[ResourceType] + ) -> ResourceType: """Get an item in the cache, call fallback if it's not present""" @abstractmethod @@ -24,7 +25,9 @@ class Cache(Generic[ResourceType], ABC): """Set a resource in the cache""" @staticmethod - async def _get_fallback_value(key: str, fallback: CacheFallback[ResourceType]) -> ResourceType: + async def _get_fallback_value( + key: str, fallback: CacheFallback[ResourceType] + ) -> ResourceType: if callable(fallback): result = await fallback(key) else: @@ -33,10 +36,12 @@ class Cache(Generic[ResourceType], ABC): return result -class NullCache(Cache): +class NullCache(Cache[ResourceType]): """Disabled cache""" - async def get(self, key: str, fallback: CacheFallback) -> ResourceType: + async def get( + self, key: str, fallback: CacheFallback[ResourceType] + ) -> ResourceType: return await self._get_fallback_value(key, fallback) def set(self, key: str, resource: ResourceType) -> None: @@ -46,10 +51,12 @@ class NullCache(Cache): class FileCache(Cache[ResourceType]): """Cache on the local filesystem""" - def __init__(self, name): + def __init__(self, name: str) -> None: self._name = name - async def get(self, key: str, fallback: CacheFallback) -> ResourceType: + async def get( + self, key: str, fallback: CacheFallback[ResourceType] + ) -> ResourceType: """Get an item in the cache, call fallback if it's not present""" cache_file_path = self._get_cache_file_path(key) if not cache_file_path.is_file(): @@ -104,9 +111,9 @@ class ObjectCache(FileCache[ResourceType]): return dumps(resource) def _deserialize(self, data: bytes) -> ResourceType: - return loads(data) + return cast(ResourceType, loads(data)) def _get_key_slug(url: str) -> str: """Return an unique slug usable as a path name for a given url.""" - return url.replace('_', '___').replace('/', '__').replace(':', '_') + return url.replace("_", "___").replace("/", "__").replace(":", "_") diff --git a/frontools/cli.py b/frontools/cli.py index d486ed2..5d2f80b 100644 --- a/frontools/cli.py +++ b/frontools/cli.py @@ -52,7 +52,7 @@ async def main( @argument("right_source", type=str) @pass_context @_async_command -async def css_diff_cli(ctx: ClickContext, right_source) -> None: +async def css_diff_cli(ctx: ClickContext, right_source: str) -> None: """Diff CSS""" config: Config = ctx.obj for _, site in config.sites: diff --git a/frontools/config.py b/frontools/config.py index 0edf8f9..807010e 100644 --- a/frontools/config.py +++ b/frontools/config.py @@ -87,7 +87,8 @@ class Config: return self._sites.items() @property - def config_cache(self) -> Cache: + def config_cache(self) -> Cache[object]: + """Get the cache for configuration""" return self.get_object_cache("config") def add_site_url(self, name: str, url: str) -> None: @@ -97,17 +98,17 @@ class Config: self._sites[name].urls.append(url) - def get_data_cache(self, name: str): + def get_data_cache(self, name: str) -> Cache[bytes]: """Get a data cache with the given identifier""" if self._use_cache: return DataCache(name) return NullCache() - def get_object_cache(self, name: str): + def get_object_cache(self, name: str) -> Cache[object]: """Get an object cache with the given identifier""" if self._use_cache: - return ObjectCache(name) + return ObjectCache[object](name) return NullCache() @@ -116,7 +117,7 @@ class Config: name: str, mappings: list[tuple[str, str]], next_source_name: Optional[str] = None, - ): + ) -> None: """Add a source overriding given patterns""" assert name not in self._sources if next_source_name is None: @@ -131,7 +132,7 @@ class Config: raise Exception(f"No source configured matching {name}") return self._sources[name] - def _add_source(self, name: str, source: Source): + def _add_source(self, name: str, source: Source) -> None: if name in self._sources: raise Exception(f"Source {name} already configured") self._sources[name] = source diff --git a/frontools/sources.py b/frontools/sources.py index 274b32c..6699548 100644 --- a/frontools/sources.py +++ b/frontools/sources.py @@ -1,10 +1,11 @@ """Source for remote files""" -from aiohttp import ClientSession from abc import ABC, abstractmethod from re import Pattern from re import compile as re_compile -from frontools.cache import DataCache +from aiohttp import ClientSession + +from frontools.cache import Cache class Source(ABC): @@ -18,7 +19,7 @@ class Source(ABC): class CachedSource(Source): """Source loading urls from the internet.""" - def __init__(self, cache: DataCache) -> None: + def __init__(self, cache: Cache[bytes]) -> None: self._cache = cache async def get_url(self, url: str) -> bytes: diff --git a/frontools/utils.py b/frontools/utils.py index 8038277..90de5f3 100644 --- a/frontools/utils.py +++ b/frontools/utils.py @@ -4,7 +4,7 @@ from datetime import datetime from os.path import expandvars from pathlib import Path from re import compile as re_compile -from typing import Awaitable +from typing import Awaitable, cast from click import progressbar from xdg import xdg_config_home @@ -43,14 +43,14 @@ async def report_progress(label: str, task_list: TaskListType) -> None: with progressbar( length=len(task_list), label=label, - item_show_func=lambda it: it, + item_show_func=lambda it: cast(str, it), ) as progress: - async def worker(): + async def worker() -> None: try: while True: item_name, task = next(iterator) - progress.update(1, current_item=item_name) + progress.update(1, current_item=item_name) # type: ignore await task except StopIteration: pass diff --git a/noxfile.py b/noxfile.py index 628a011..97e8af6 100644 --- a/noxfile.py +++ b/noxfile.py @@ -14,49 +14,49 @@ VENV_DIR = Path(".venv") @nox.session(python=["3.9", "3.10"], reuse_venv=True) -def tests(session: Session): +def tests(session: Session) -> None: """Run unit tests.""" session.install("-e", ".", *PYTEST_PACKAGES) session.run("pytest") @nox.session(reuse_venv=True) -def black(session: Session): +def black(session: Session) -> None: """Check black formatting.""" session.install("black") session.run("black", "--check", *LINT_PATHS) @nox.session(reuse_venv=True) -def flake8(session: Session): +def flake8(session: Session) -> None: """Run flake8""" session.install("flake8") - session.run("flake8") + session.run("flake8", "frontools", "tests") @nox.session(reuse_venv=True) -def isort(session: Session): +def isort(session: Session) -> None: """Check imports sorting""" session.install("isort") session.run("isort", "--check", *LINT_PATHS) @nox.session(reuse_venv=True) -def mypy(session: Session): +def mypy(session: Session) -> None: """Run Mypy""" - session.install("mypy", "types-click") - session.run("mypy", *LINT_PATHS) + session.install("mypy", "types-click", "-e", ".") + session.run("mypy", "--install-types", *LINT_PATHS) @nox.session(reuse_venv=True) -def pylint(session: Session): +def pylint(session: Session) -> None: """Run pylint""" session.install("pylint", "-e", ".", *PYTEST_PACKAGES) session.run("pylint", "--rcfile=pyproject.toml", *LINT_PATHS) @nox.session(python=False) -def lint(session: Session): +def lint(session: Session) -> None: """Run all lint tasks""" session.notify("black") session.notify("flake8") @@ -66,7 +66,7 @@ def lint(session: Session): @nox.session(python=False) -def checks(session: Session): +def checks(session: Session) -> None: """Run all checks""" session.notify("lint") session.notify("tests") diff --git a/pyproject.toml b/pyproject.toml index b068e6d..c868641 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -52,6 +52,9 @@ junit_family = "legacy" addopts = "--cov=frontools --cov-report html" testpaths = "tests" +[tool.mypy] +strict=true + [[tool.mypy.overrides]] module = [ 'pytest', @@ -65,6 +68,9 @@ ignore_missing_imports = true [tool.isort] profile = "black" +[tool.pylint.reports] +msg-template="{path}:{line}: [{msg_id}({symbol}), {obj}] {msg}" + [tool.pylint.messages_control] disable = [ "invalid-name", diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..6f9e2e3 --- /dev/null +++ b/tests/__init__.py @@ -0,0 +1 @@ +"""Frontools unit tests packages"""