Browse Source

adapt internal type hints for mypy's strict mode

Fabian Peter Hammerle 6 months ago
parent
commit
a0190b0478
7 changed files with 47 additions and 27 deletions
  1. 1 1
      .github/workflows/python.yml
  2. 5 4
      ical2vdir/__init__.py
  3. 26 13
      tests/cli_test.py
  4. 3 1
      tests/datetime_test.py
  5. 3 1
      tests/event_test.py
  6. 4 2
      tests/prop_test.py
  7. 5 5
      tests/vdir_test.py

+ 1 - 1
.github/workflows/python.yml

@@ -60,7 +60,7 @@ jobs:
     # > tests/resources/__init__.py:1:0: F0010: error while code parsing: Unable to load file tests/resources/__init__.py:
     # > [Errno 2] No such file or directory: 'tests/resources/__init__.py' (parse-error)
     - run: pipenv run pylint --disable=parse-error tests/*
-    - run: pipenv run mypy "$(cat *.egg-info/top_level.txt)" tests
+    - run: pipenv run mypy --strict "$(cat *.egg-info/top_level.txt)" tests
     # >=2.1.0 to support GITHUB_TOKEN
     # COVERALLS_REPO_TOKEN required manual configuration of secret
     # https://github.com/TheKevJames/coveralls-python/commit/f597109b62fadaf900af79d4f08a7debee5229e2

+ 5 - 4
ical2vdir/__init__.py

@@ -22,6 +22,7 @@ import os
 import pathlib
 import sys
 import tempfile
+import typing
 
 import icalendar
 
@@ -30,7 +31,7 @@ _LOGGER = logging.getLogger(__name__)
 _VDIR_EVENT_FILE_EXTENSION = ".ics"
 
 
-def _event_prop_equal(prop_a, prop_b) -> bool:
+def _event_prop_equal(prop_a: typing.Any, prop_b: typing.Any) -> bool:
     if isinstance(prop_a, list):
         return len(prop_a) == len(prop_b) and all(
             _event_prop_equal(*pair) for pair in zip(prop_a, prop_b)
@@ -46,7 +47,7 @@ def _event_prop_equal(prop_a, prop_b) -> bool:
     if isinstance(prop_a, (icalendar.prop.vDDDTypes, icalendar.prop.vCategory)):
         # pylint: disable=unidiomatic-typecheck
         return type(prop_a) == type(prop_b) and vars(prop_a) == vars(prop_b)
-    return prop_a == prop_b and prop_a.params == prop_b.params
+    return typing.cast(bool, prop_a == prop_b and prop_a.params == prop_b.params)
 
 
 def _events_equal(event_a: icalendar.cal.Event, event_b: icalendar.cal.Event) -> bool:
@@ -90,7 +91,7 @@ def _event_vdir_filename(event: icalendar.cal.Event) -> str:
     return output_filename + _VDIR_EVENT_FILE_EXTENSION
 
 
-def _write_event(event: icalendar.cal.Event, path: pathlib.Path):
+def _write_event(event: icalendar.cal.Event, path: pathlib.Path) -> None:
     # > Creating and modifying items or metadata files should happen atomically.
     # https://vdirsyncer.readthedocs.io/en/stable/vdir.html#writing-to-vdirs
     temp_fd, temp_path = tempfile.mkstemp(
@@ -127,7 +128,7 @@ def _sync_event(
     return output_path
 
 
-def _main():
+def _main() -> None:
     # https://docs.python.org/3/library/logging.html#levels
     logging.basicConfig(
         format="%(message)s",

+ 26 - 13
tests/cli_test.py

@@ -21,6 +21,7 @@ import pathlib
 import subprocess
 import unittest.mock
 
+import _pytest.logging
 import icalendar
 
 import ical2vdir
@@ -28,13 +29,15 @@ import ical2vdir
 # pylint: disable=protected-access
 
 
-def test_entrypoint_help():
+def test_entrypoint_help() -> None:
     subprocess.run(["ical2vdir", "--help"], check=True, stdout=subprocess.PIPE)
 
 
 def test__main_create_all(
-    caplog, tmp_path: pathlib.Path, google_calendar_file: io.BufferedReader
-):
+    caplog: _pytest.logging.LogCaptureFixture,
+    tmp_path: pathlib.Path,
+    google_calendar_file: io.BufferedReader,
+) -> None:
     with unittest.mock.patch("sys.stdin", google_calendar_file):
         with unittest.mock.patch("sys.argv", ["", "--output-dir", str(tmp_path)]):
             with caplog.at_level(logging.INFO):
@@ -58,8 +61,10 @@ def test__main_create_all(
 
 
 def test__main_create_some(
-    caplog, tmp_path: pathlib.Path, google_calendar_file: io.BufferedReader
-):
+    caplog: _pytest.logging.LogCaptureFixture,
+    tmp_path: pathlib.Path,
+    google_calendar_file: io.BufferedReader,
+) -> None:
     with unittest.mock.patch("sys.stdin", google_calendar_file):
         with unittest.mock.patch("sys.argv", ["", "--output-dir", str(tmp_path)]):
             ical2vdir._main()
@@ -77,8 +82,10 @@ def test__main_create_some(
 
 
 def test__main_update(
-    caplog, tmp_path: pathlib.Path, google_calendar_file: io.BufferedReader
-):
+    caplog: _pytest.logging.LogCaptureFixture,
+    tmp_path: pathlib.Path,
+    google_calendar_file: io.BufferedReader,
+) -> None:
     with unittest.mock.patch("sys.stdin", google_calendar_file):
         with unittest.mock.patch("sys.argv", ["", "--output-dir", str(tmp_path)]):
             ical2vdir._main()
@@ -107,8 +114,10 @@ def test__main_update(
 
 
 def test__main_update_silent(
-    caplog, tmp_path: pathlib.Path, google_calendar_file: io.BufferedReader
-):
+    caplog: _pytest.logging.LogCaptureFixture,
+    tmp_path: pathlib.Path,
+    google_calendar_file: io.BufferedReader,
+) -> None:
     with unittest.mock.patch("sys.stdin", google_calendar_file):
         with unittest.mock.patch(
             "sys.argv", ["", "--output-dir", str(tmp_path), "--silent"]
@@ -130,8 +139,10 @@ def test__main_update_silent(
 
 
 def test__main_update_verbose(
-    caplog, tmp_path: pathlib.Path, google_calendar_file: io.BufferedReader
-):
+    caplog: _pytest.logging.LogCaptureFixture,
+    tmp_path: pathlib.Path,
+    google_calendar_file: io.BufferedReader,
+) -> None:
     with unittest.mock.patch("sys.stdin", google_calendar_file):
         with unittest.mock.patch(
             "sys.argv", ["", "--output-dir", str(tmp_path), "--verbose"]
@@ -165,8 +176,10 @@ def test__main_update_verbose(
 
 
 def test__main_delete(
-    caplog, tmp_path: pathlib.Path, google_calendar_file: io.BufferedReader
-):
+    caplog: _pytest.logging.LogCaptureFixture,
+    tmp_path: pathlib.Path,
+    google_calendar_file: io.BufferedReader,
+) -> None:
     tmp_path.joinpath("will-be-deleted.ics").touch()
     with unittest.mock.patch("sys.stdin", google_calendar_file):
         with unittest.mock.patch(

+ 3 - 1
tests/datetime_test.py

@@ -34,6 +34,8 @@ _CEST = datetime.timezone(datetime.timedelta(hours=+2))
         ),
     ],
 )
-def test__datetime_basic_isoformat(dt_obj, expected_str):
+def test__datetime_basic_isoformat(
+    dt_obj: datetime.datetime, expected_str: str
+) -> None:
     # pylint: disable=protected-access
     assert ical2vdir._datetime_basic_isoformat(dt_obj) == expected_str

+ 3 - 1
tests/event_test.py

@@ -144,7 +144,9 @@ END:VEVENT
         ]
     ),
 )
-def test__events_equal(event_a_ical, event_b_ical, expected_result):
+def test__events_equal(
+    event_a_ical: str, event_b_ical: str, expected_result: bool
+) -> None:
     event_a = icalendar.cal.Event.from_ical(event_a_ical)
     event_b = icalendar.cal.Event.from_ical(event_b_ical)
     # pylint: disable=protected-access

+ 4 - 2
tests/prop_test.py

@@ -26,7 +26,7 @@ from ical2vdir import _event_prop_equal
 _CEST = datetime.timezone(datetime.timedelta(hours=+2))
 
 
-def _parametrize(obj: typing.Any, params: dict) -> typing.Any:
+def _parametrize(obj: typing.Any, params: typing.Dict[str, str]) -> typing.Any:
     for key, value in params.items():
         obj.params.__setitem__(key, value)
     return obj
@@ -203,5 +203,7 @@ def _parametrize(obj: typing.Any, params: dict) -> typing.Any:
         ),
     ],
 )
-def test__event_prop_equal(prop_a, prop_b, expected_result):
+def test__event_prop_equal(
+    prop_a: object, prop_b: object, expected_result: bool
+) -> None:
     assert _event_prop_equal(prop_a, prop_b) == expected_result

+ 5 - 5
tests/vdir_test.py

@@ -53,7 +53,7 @@ END:VEVENT
 # tmp_path fixture: https://github.com/pytest-dev/pytest/blob/5.4.3/src/_pytest/tmpdir.py#L191
 
 
-def test__write_event_cleanup(tmp_path: pathlib.Path):
+def test__write_event_cleanup(tmp_path: pathlib.Path) -> None:
     event = icalendar.cal.Event.from_ical(_SINGLE_EVENT_ICAL)
     with unittest.mock.patch("os.unlink") as unlink_mock:
         with pytest.raises(IsADirectoryError):
@@ -91,13 +91,13 @@ END:VEVENT
         ),
     ],
 )
-def test__event_vdir_filename(event_ical, expected_filename):
+def test__event_vdir_filename(event_ical: bytes, expected_filename: str) -> None:
     event = icalendar.cal.Event.from_ical(event_ical)
     assert ical2vdir._event_vdir_filename(event) == expected_filename
 
 
 @pytest.mark.parametrize("event_ical", [_SINGLE_EVENT_ICAL])
-def test__sync_event_create(tmp_path: pathlib.Path, event_ical):
+def test__sync_event_create(tmp_path: pathlib.Path, event_ical: bytes) -> None:
     event = icalendar.cal.Event.from_ical(event_ical)
     ical2vdir._sync_event(event, tmp_path)
     (ics_path,) = tmp_path.iterdir()
@@ -106,7 +106,7 @@ def test__sync_event_create(tmp_path: pathlib.Path, event_ical):
 
 
 @pytest.mark.parametrize("event_ical", [_SINGLE_EVENT_ICAL])
-def test__sync_event_update(tmp_path: pathlib.Path, event_ical):
+def test__sync_event_update(tmp_path: pathlib.Path, event_ical: bytes) -> None:
     event = icalendar.cal.Event.from_ical(event_ical)
     ical2vdir._sync_event(event, tmp_path)
     event["SUMMARY"] += " suffix"
@@ -119,7 +119,7 @@ def test__sync_event_update(tmp_path: pathlib.Path, event_ical):
 
 
 @pytest.mark.parametrize("event_ical", [_SINGLE_EVENT_ICAL])
-def test__sync_event_unchanged(tmp_path: pathlib.Path, event_ical):
+def test__sync_event_unchanged(tmp_path: pathlib.Path, event_ical: bytes) -> None:
     event = icalendar.cal.Event.from_ical(event_ical)
     ical2vdir._sync_event(event, tmp_path)
     (ics_path,) = tmp_path.iterdir()