Add type hints for internal members of the test cases so type checkers can ensure the code properly constrains to these types and accounts for scenarios where the values are `None`. In most cases, the type checker is allowed to assume the inferred type upon assignment. An example is any test case that creates a `Chip` as part of its `setUp` method. Many of these tests subsequently set the reference to `None` in `tearDown` to free up resources to be collected by the GC. If the member was "properly" typed to be `Optional`, all references in the unit tests would need to be guarded by an assert or a cast or ignored by the type checker. This is noisy and doesn't add value since for the life of the test it should always be a valid reference. Instead, allow `tearDown` to violate the inferred type and inform the type checker to ignore the assignment via directive. If the tests are ever changed to set the member to something other than the inferred type outside of `tearDown`, explicit type hints and proper checks should be added. Signed-off-by: Vincent Fazio <vfazio@xxxxxxxxxxx> --- bindings/python/tests/tests_chip.py | 6 +++--- bindings/python/tests/tests_chip_info.py | 6 +++--- bindings/python/tests/tests_edge_event.py | 5 +++-- bindings/python/tests/tests_info_event.py | 11 ++++++----- bindings/python/tests/tests_line_info.py | 4 ++-- 5 files changed, 17 insertions(+), 15 deletions(-) diff --git a/bindings/python/tests/tests_chip.py b/bindings/python/tests/tests_chip.py index 9c8f875..218f238 100644 --- a/bindings/python/tests/tests_chip.py +++ b/bindings/python/tests/tests_chip.py @@ -75,7 +75,7 @@ class ChipProperties(TestCase): def tearDown(self) -> None: self.chip.close() - self.sim = None + self.sim = None # type: ignore[assignment] def test_get_chip_path(self) -> None: self.assertEqual(self.sim.dev_path, self.chip.path) @@ -200,7 +200,7 @@ class StringRepresentation(TestCase): def tearDown(self) -> None: self.chip.close() - self.sim = None + self.sim = None # type: ignore[assignment] def test_repr(self) -> None: self.assertEqual(repr(self.chip), 'gpiod.Chip("{}")'.format(self.sim.dev_path)) @@ -224,7 +224,7 @@ class StringRepresentationClosed(TestCase): self.chip = gpiod.Chip(self.sim.dev_path) def tearDown(self) -> None: - self.sim = None + self.sim = None # type: ignore[assignment] def test_repr_closed(self) -> None: self.chip.close() diff --git a/bindings/python/tests/tests_chip_info.py b/bindings/python/tests/tests_chip_info.py index acb0da9..aabfbee 100644 --- a/bindings/python/tests/tests_chip_info.py +++ b/bindings/python/tests/tests_chip_info.py @@ -15,10 +15,10 @@ class ChipInfoProperties(TestCase): self.info = self.chip.get_info() def tearDown(self) -> None: - self.info = None + self.info = None # type: ignore[assignment] self.chip.close() - self.chip = None - self.sim = None + self.chip = None # type: ignore[assignment] + self.sim = None # type: ignore[assignment] def test_chip_info_name(self) -> None: self.assertEqual(self.info.name, self.sim.name) diff --git a/bindings/python/tests/tests_edge_event.py b/bindings/python/tests/tests_edge_event.py index f80d6a5..d7766ec 100644 --- a/bindings/python/tests/tests_edge_event.py +++ b/bindings/python/tests/tests_edge_event.py @@ -5,6 +5,7 @@ import time from datetime import timedelta from functools import partial from threading import Thread +from typing import Optional from unittest import TestCase import gpiod @@ -54,13 +55,13 @@ class EdgeEventInvalidConfig(TestCase): class WaitingForEdgeEvents(TestCase): def setUp(self) -> None: self.sim = gpiosim.Chip(num_lines=8) - self.thread = None + self.thread: Optional[Thread] = None def tearDown(self) -> None: if self.thread: self.thread.join() del self.thread - self.sim = None + self.sim = None # type: ignore[assignment] def trigger_falling_and_rising_edge(self, offset: int) -> None: time.sleep(0.05) diff --git a/bindings/python/tests/tests_info_event.py b/bindings/python/tests/tests_info_event.py index 7e12b8e..1005647 100644 --- a/bindings/python/tests/tests_info_event.py +++ b/bindings/python/tests/tests_info_event.py @@ -7,6 +7,7 @@ import threading import time from dataclasses import FrozenInstanceError from functools import partial +from typing import Optional from unittest import TestCase import gpiod @@ -51,7 +52,7 @@ class WatchingInfoEventWorks(TestCase): def setUp(self) -> None: self.sim = gpiosim.Chip(num_lines=8, line_names={4: "foobar"}) self.chip = gpiod.Chip(self.sim.dev_path) - self.thread = None + self.thread: Optional[threading.Thread] = None def tearDown(self) -> None: if self.thread: @@ -59,8 +60,8 @@ class WatchingInfoEventWorks(TestCase): self.thread = None self.chip.close() - self.chip = None - self.sim = None + self.chip = None # type: ignore[assignment] + self.sim = None # type: ignore[assignment] def test_watch_line_info_returns_line_info(self) -> None: info = self.chip.watch_line_info(7) @@ -138,8 +139,8 @@ class UnwatchingLineInfo(TestCase): def tearDown(self) -> None: self.chip.close() - self.chip = None - self.sim = None + self.chip = None # type: ignore[assignment] + self.sim = None # type: ignore[assignment] def test_unwatch_line_info(self) -> None: self.chip.watch_line_info(0) diff --git a/bindings/python/tests/tests_line_info.py b/bindings/python/tests/tests_line_info.py index 9828349..7bc244d 100644 --- a/bindings/python/tests/tests_line_info.py +++ b/bindings/python/tests/tests_line_info.py @@ -22,8 +22,8 @@ class GetLineInfo(TestCase): def tearDown(self) -> None: self.chip.close() - self.chip = None - self.sim = None + self.chip = None # type: ignore[assignment] + self.sim = None # type: ignore[assignment] def test_get_line_info_by_offset(self) -> None: self.chip.get_line_info(0) -- 2.34.1