diff --git a/mypy.ini b/mypy.ini index 9c34fcc0..7bcb927e 100644 --- a/mypy.ini +++ b/mypy.ini @@ -3,11 +3,14 @@ pretty = True show_error_context = True show_column_numbers = True show_error_end = True -warn_redundant_casts = True -warn_unused_ignores = True + check_untyped_defs = True + +# see https://mypy.readthedocs.io/en/stable/error_code_list2.html +warn_redundant_casts = True strict_equality = True -enable_error_code = possibly-undefined +warn_unused_ignores = True +enable_error_code = deprecated,redundant-expr,possibly-undefined,truthy-bool,truthy-iterable,ignore-without-code,unused-awaitable # todo ok, maybe it wasn't such a good idea.. # mainly because then tox picks it up and running against the user config, not the repository config diff --git a/src/my/arbtt.py b/src/my/arbtt.py index 5d4bf8ec..737780aa 100644 --- a/src/my/arbtt.py +++ b/src/my/arbtt.py @@ -87,7 +87,7 @@ def entries() -> Iterable[Entry]: from subprocess import PIPE, Popen - import ijson.backends.yajl2_cffi as ijson # type: ignore + import ijson.backends.yajl2_cffi as ijson # type: ignore[import-untyped] for cmd in cmds: with Popen(cmd, stdout=PIPE) as p: out = p.stdout; assert out is not None diff --git a/src/my/calendar/holidays.py b/src/my/calendar/holidays.py index 522672e4..2fa5ba15 100644 --- a/src/my/calendar/holidays.py +++ b/src/my/calendar/holidays.py @@ -15,7 +15,7 @@ @lru_cache(1) def _calendar(): - from workalendar.registry import registry # type: ignore + from workalendar.registry import registry # type: ignore[import-not-found] # todo switch to using time.tz.main once _get_tz stabilizes? from ..time.tz import via_location as LTZ diff --git a/src/my/core/__main__.py b/src/my/core/__main__.py index 7e2d8f94..545f3f75 100644 --- a/src/my/core/__main__.py +++ b/src/my/core/__main__.py @@ -304,8 +304,7 @@ def modules_check(*, verbose: bool, list_all: bool, quick: bool, for_modules: li try: kwargs = {} - # todo hmm why wouldn't they be callable?? - if callable(stats) and 'quick' in inspect.signature(stats).parameters: + if 'quick' in inspect.signature(stats).parameters: kwargs['quick'] = quick with quick_context: res = stats(**kwargs) diff --git a/src/my/core/_deprecated/dataset.py b/src/my/core/_deprecated/dataset.py index 9cca2fda..d7a427f9 100644 --- a/src/my/core/_deprecated/dataset.py +++ b/src/my/core/_deprecated/dataset.py @@ -3,7 +3,7 @@ def connect_readonly(db: PathIsh): - import dataset # type: ignore + import dataset # type: ignore[import-not-found] # see https://github.com/pudo/dataset/issues/136#issuecomment-128693122 # todo not sure if mode=ro has any benefit, but it doesn't work on read-only filesystems diff --git a/src/my/core/denylist.py b/src/my/core/denylist.py index c92f9a05..b0ea8530 100644 --- a/src/my/core/denylist.py +++ b/src/my/core/denylist.py @@ -135,7 +135,8 @@ def _deny_cli_remember( items: Iterator[T], mem: dict[str, T], ) -> Iterator[str]: - keyf = self._deny_cli_key_func or _default_key_func + # user can override _deny_cli_key_func, so it's not always None, hence the ignore + keyf = self._deny_cli_key_func or _default_key_func # type: ignore[redundant-expr] # i.e., convert each item to a string, and map str -> item for item in items: key = keyf(item) diff --git a/src/my/core/discovery_pure.py b/src/my/core/discovery_pure.py index 18a19c48..23d5b85c 100644 --- a/src/my/core/discovery_pure.py +++ b/src/my/core/discovery_pure.py @@ -119,8 +119,6 @@ def _extract_requirements(a: ast.Module) -> Requires: for c in elts: if isinstance(c, ast.Constant): deps.append(c.value) - elif isinstance(c, ast.Str): - deps.append(c.s) else: raise RuntimeError(f"Expecting string constants only in {REQUIRES} declaration") return tuple(deps) diff --git a/src/my/core/influxdb.py b/src/my/core/influxdb.py index 78a439a4..50c957e3 100644 --- a/src/my/core/influxdb.py +++ b/src/my/core/influxdb.py @@ -34,7 +34,7 @@ def fill(it: Iterable[Any], *, measurement: str, reset: bool = RESET_DEFAULT, dt db = config.db - from influxdb import InfluxDBClient # type: ignore + from influxdb import InfluxDBClient # type: ignore[import-not-found] client = InfluxDBClient() # todo maybe create if not exists? diff --git a/src/my/core/mime.py b/src/my/core/mime.py index 8235960f..615160c5 100644 --- a/src/my/core/mime.py +++ b/src/my/core/mime.py @@ -14,7 +14,7 @@ @functools.lru_cache(1) def _magic(): - import magic # type: ignore + import magic # type: ignore[import-not-found] # TODO also has uncompess=True? could be useful return magic.Magic(mime=True) diff --git a/src/my/core/utils/itertools.py b/src/my/core/utils/itertools.py index 42b2b771..06faf3c1 100644 --- a/src/my/core/utils/itertools.py +++ b/src/my/core/utils/itertools.py @@ -72,7 +72,7 @@ def make_dict( uniques = ensure_unique(with_keys, key=lambda p: p[0]) res: dict[K, V] = {} for k, i in uniques: - res[k] = i if value is None else value(i) + res[k] = i if value is None else value(i) # type: ignore[redundant-expr] return res diff --git a/src/my/demo.py b/src/my/demo.py index fa80b2a0..34424989 100644 --- a/src/my/demo.py +++ b/src/my/demo.py @@ -32,7 +32,7 @@ def external_module(self): return import_dir(rpath) - import my.config.repos.external as m # type: ignore + import my.config.repos.external as m # type: ignore[import-not-found] return m diff --git a/src/my/emfit/__init__.py b/src/my/emfit/__init__.py index 0d50b063..1031d12d 100644 --- a/src/my/emfit/__init__.py +++ b/src/my/emfit/__init__.py @@ -193,7 +193,7 @@ class emfit: # TODO remove/deprecate it? I think used by timeline def get_datas() -> list[Emfit]: # todo ugh. run lint properly - return sorted(datas(), key=lambda e: e.start) # type: ignore + return sorted(datas(), key=lambda e: e.start) # type: ignore[arg-type] # TODO move away old entries if there is a diff?? diff --git a/src/my/jawbone/__init__.py b/src/my/jawbone/__init__.py index 463d7352..653a6ab9 100644 --- a/src/my/jawbone/__init__.py +++ b/src/my/jawbone/__init__.py @@ -182,7 +182,7 @@ def plot_one(sleep: SleepEntry, fig, axes, xlims=None, *, showtext=True): print(f"{sleep.xid} span: {span}") # pip install imageio - from imageio import imread # type: ignore + from imageio import imread # type: ignore[import-not-found] img = imread(sleep.graph) # all of them are 300x300 images apparently diff --git a/src/my/jawbone/plots.py b/src/my/jawbone/plots.py index 59684125..ede23d0a 100755 --- a/src/my/jawbone/plots.py +++ b/src/my/jawbone/plots.py @@ -5,7 +5,7 @@ from pathlib import Path from typing import Any, NamedTuple -import matplotlib.pylab as pylab # type: ignore +import matplotlib.pylab as pylab # type: ignore[import-not-found] # sleep = [] # with open('2017.csv', 'r') as fo: @@ -13,7 +13,7 @@ # for line in islice(reader, 0, 10): # sleep # print(line) -import matplotlib.pyplot as plt # type: ignore +import matplotlib.pyplot as plt # type: ignore[import-not-found] from numpy import genfromtxt pylab.rcParams['figure.figsize'] = (32.0, 24.0) @@ -93,7 +93,7 @@ def iter_useful(data_file: str): p / "2017.csv", ] -from kython import concat, parse_date # type: ignore +from kython import concat, parse_date # type: ignore[import-not-found] useful = concat(*(list(iter_useful(str(f))) for f in files)) @@ -107,7 +107,7 @@ def iter_useful(data_file: str): # TODO filter outliers? # TODO don't need this anymore? it's gonna be in dashboards package -from kython.plotting import plot_timestamped # type: ignore +from kython.plotting import plot_timestamped # type: ignore[import-not-found] for attr, lims, mavg, fig in [ ('light', (0, 400), 5, None), diff --git a/src/my/location/google.py b/src/my/location/google.py index 750c847f..1454b76b 100644 --- a/src/my/location/google.py +++ b/src/my/location/google.py @@ -18,8 +18,7 @@ from subprocess import PIPE, Popen from typing import IO, NamedTuple, Optional -# pip3 install geopy -import geopy # type: ignore +import geopy # type: ignore[import-not-found] from my.core import Stats, make_logger, stat, warnings from my.core.cachew import cache_dir, mcachew @@ -50,10 +49,10 @@ def _iter_via_ijson(fo) -> Iterable[TsLatLon]: # todo extract to common? try: # pip3 install ijson cffi - import ijson.backends.yajl2_cffi as ijson # type: ignore + import ijson.backends.yajl2_cffi as ijson # type: ignore[import-untyped] except: warnings.medium("Falling back to default ijson because 'cffi' backend isn't found. It's up to 2x faster, you might want to check it out") - import ijson # type: ignore + import ijson # type: ignore[import-untyped] for d in ijson.items(fo, 'locations.item'): yield ( diff --git a/src/my/photos/main.py b/src/my/photos/main.py index f98cb15b..e447d8e4 100644 --- a/src/my/photos/main.py +++ b/src/my/photos/main.py @@ -17,7 +17,7 @@ from pathlib import Path from typing import NamedTuple, Optional -from geopy.geocoders import Nominatim # type: ignore +from geopy.geocoders import Nominatim # type: ignore[import-not-found] from my.core import LazyLogger from my.core.cachew import cache_dir, mcachew diff --git a/src/my/rtm.py b/src/my/rtm.py index 217c9692..716d4505 100644 --- a/src/my/rtm.py +++ b/src/my/rtm.py @@ -1,6 +1,7 @@ """ [[https://rememberthemilk.com][Remember The Milk]] tasks and notes """ +from __future__ import annotations REQUIRES = [ 'icalendar', @@ -11,8 +12,9 @@ from datetime import datetime from functools import cached_property -import icalendar # type: ignore -from icalendar.cal import Todo # type: ignore +# no mypy annotations... https://github.com/collective/icalendar/issues/395 +import icalendar # type: ignore[import-not-found] +from icalendar.cal import Todo # type: ignore[import-not-found] from more_itertools import bucket from my.core import get_files, make_logger @@ -53,9 +55,9 @@ def uid(self) -> str: def title(self) -> str: return str(self.todo['SUMMARY']) - def get_status(self) -> str: + def get_status(self) -> str | None: if 'STATUS' not in self.todo: - return None # type: ignore + return None # TODO 'COMPLETED'? return str(self.todo['STATUS']) diff --git a/src/my/tests/tz.py b/src/my/tests/tz.py index 92d8f3ba..70cc76eb 100644 --- a/src/my/tests/tz.py +++ b/src/my/tests/tz.py @@ -104,4 +104,4 @@ def test_policies() -> None: assert getzone(tz_main.localize(aware, policy='convert')) == 'Europe/Rome' with pytest.raises(RuntimeError): - assert tz_main.localize(aware, policy='throw') + tz_main.localize(aware, policy='throw') diff --git a/src/my/time/tz/via_location.py b/src/my/time/tz/via_location.py index 1b2275b4..93c43d72 100644 --- a/src/my/time/tz/via_location.py +++ b/src/my/time/tz/via_location.py @@ -93,7 +93,7 @@ def _timezone_finder(*, fast: bool) -> Any: # less precise, but faster from timezonefinder import TimezoneFinderL as Finder else: - from timezonefinder import TimezoneFinder as Finder # type: ignore + from timezonefinder import TimezoneFinder as Finder # type: ignore[assignment] return Finder(in_memory=True) diff --git a/tests_misc/takeout.py b/tests_misc/takeout.py index 47d405be..11041b3b 100644 --- a/tests_misc/takeout.py +++ b/tests_misc/takeout.py @@ -13,7 +13,7 @@ def test_location_perf() -> None: # 2.80 s for 10 iterations and 10K points # TODO try switching to jq and see how it goes? not sure.. - print(ilen(islice(LT.iter_locations(), 0, 10000))) # type: ignore + print(ilen(islice(LT.iter_locations(), 0, 10000))) # type: ignore[attr-defined] # in theory should support any HTML takeout file?