Skip to content

Commit d529a96

Browse files
authored
Make typing strict on tests (#93)
1 parent 55abd65 commit d529a96

File tree

6 files changed

+106
-95
lines changed

6 files changed

+106
-95
lines changed

tests/test_api.py

+25-20
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import inspect
66
import unittest
7+
from typing import Callable, TypeVar, cast
78

89
import pandas as pd
910
import rdflib
@@ -14,37 +15,41 @@
1415

1516
SKIP = {"__init__"}
1617

18+
X = TypeVar("X")
1719

18-
def _df_equal(a: pd.DataFrame, b: pd.DataFrame, msg=None) -> bool:
19-
return a.values.tolist() == b.values.tolist()
2020

21+
def _df_equal(a: pd.DataFrame, b: pd.DataFrame, msg: str | None = None) -> bool:
22+
return bool(a.values.tolist() == b.values.tolist())
2123

22-
def _rdf_equal(a: rdflib.Graph, b: rdflib.Graph, msg=None) -> bool:
24+
25+
def _rdf_equal(a: rdflib.Graph, b: rdflib.Graph, msg: str | None = None) -> bool:
2326
return {tuple(t) for t in a} == {tuple(t) for t in b}
2427

2528

26-
def _etree_equal(a: etree.ElementTree, b: etree.ElementTree, msg=None) -> bool:
27-
return etree.tostring(a) == etree.tostring(b)
29+
def _etree_equal(a: etree.ElementTree, b: etree.ElementTree, msg: str | None = None) -> bool:
30+
return cast(str, etree.tostring(a)) == cast(str, etree.tostring(b))
2831

2932

3033
class TestExposed(unittest.TestCase):
3134
"""Test API exposure."""
3235

3336
def setUp(self) -> None:
3437
"""Set up the test case."""
35-
self.addTypeEqualityFunc(pd.DataFrame, _df_equal)
36-
self.addTypeEqualityFunc(rdflib.Graph, _rdf_equal)
37-
self.addTypeEqualityFunc(type(etree.ElementTree()), _etree_equal)
38+
self.addTypeEqualityFunc(pd.DataFrame, _df_equal) # type:ignore[arg-type]
39+
self.addTypeEqualityFunc(rdflib.Graph, _rdf_equal) # type:ignore[arg-type]
40+
self.addTypeEqualityFunc(type(etree.ElementTree()), _etree_equal) # type:ignore[arg-type]
3841

39-
def assert_io(self, obj, ext: str, dump, load):
42+
def assert_io(
43+
self, obj: X, extension: str, dump: Callable[..., None], load: Callable[..., X]
44+
) -> None:
4045
"""Test an object can be dumped and loaded.
4146
4247
:param obj: The object to dump
43-
:param ext: The extension to use
48+
:param extension: The extension to use
4449
:param dump: The dump function
4550
:param load: The load function
4651
"""
47-
name = f"test.{ext}"
52+
name = f"test.{extension}"
4853
path = pystow.join("test", name=name)
4954
if path.is_file():
5055
path.unlink()
@@ -54,7 +59,7 @@ def assert_io(self, obj, ext: str, dump, load):
5459
self.assertTrue(path.is_file())
5560
self.assertEqual(obj, load("test", name=name))
5661

57-
def test_exposed(self):
62+
def test_exposed(self) -> None:
5863
"""Test that all module-level functions also have a counterpart in the top-level API."""
5964
for name, func in Module.__dict__.items():
6065
if not inspect.isfunction(func) or name in SKIP:
@@ -75,24 +80,24 @@ def test_exposed(self):
7580
msg=f"`pystow.api.{name}` should be imported in `pystow.__init__`.",
7681
)
7782

78-
def test_io(self):
83+
def test_io(self) -> None:
7984
"""Test IO functions."""
8085
obj = ["a", "b", "c"]
8186
for ext, dump, load in [
8287
("json", pystow.dump_json, pystow.load_json),
8388
("pkl", pystow.dump_pickle, pystow.load_pickle),
8489
]:
8590
with self.subTest(ext=ext):
86-
self.assert_io(obj, ext=ext, dump=dump, load=load)
91+
self.assert_io(obj, extension=ext, dump=dump, load=load) # type:ignore
8792

88-
def test_pd_io(self):
93+
def test_pd_io(self) -> None:
8994
"""Test pandas IO."""
9095
columns = list("abc")
9196
data = [(1, 2, 3), (4, 5, 6)]
9297
df = pd.DataFrame(data, columns=columns)
93-
self.assert_io(df, ext="tsv", load=pystow.load_df, dump=pystow.dump_df)
98+
self.assert_io(df, extension="tsv", load=pystow.load_df, dump=pystow.dump_df)
9499

95-
def test_rdf_io(self):
100+
def test_rdf_io(self) -> None:
96101
"""Test RDFlib IO."""
97102
graph = rdflib.Graph()
98103
graph.add(
@@ -103,12 +108,12 @@ def test_rdf_io(self):
103108
)
104109
)
105110
self.assertEqual(1, len(graph))
106-
self.assert_io(graph, ext="ttl", dump=pystow.dump_rdf, load=pystow.load_rdf)
111+
self.assert_io(graph, extension="ttl", dump=pystow.dump_rdf, load=pystow.load_rdf)
107112

108-
def test_xml_io(self):
113+
def test_xml_io(self) -> None:
109114
"""Test XML I/O."""
110115
root = etree.Element("root")
111116
root.set("interesting", "somewhat")
112117
etree.SubElement(root, "test")
113118
my_tree = etree.ElementTree(root)
114-
self.assert_io(my_tree, ext="xml", dump=pystow.dump_xml, load=pystow.load_xml)
119+
self.assert_io(my_tree, extension="xml", dump=pystow.dump_xml, load=pystow.load_xml)

tests/test_caching.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,14 @@ def tearDown(self) -> None:
2525
"""Tear down the test case's temporary directory."""
2626
self.tmpdir.cleanup()
2727

28-
def test_cache_exception(self):
28+
def test_cache_exception(self) -> None:
2929
"""Test that exceptions aren't swallowed."""
3030
path = self.directory.joinpath("test.pkl")
3131

3232
self.assertFalse(path.is_file())
3333

3434
@CachedPickle(path=path)
35-
def _f1():
35+
def _f1() -> None:
3636
raise NotImplementedError
3737

3838
self.assertFalse(path.is_file(), msg="function has not been called")
@@ -45,7 +45,7 @@ def _f1():
4545
msg="file should not have been created if an exception was thrown by the function",
4646
)
4747

48-
def test_cache_pickle(self):
48+
def test_cache_pickle(self) -> None:
4949
"""Test caching a pickle."""
5050
path = self.directory.joinpath("test.pkl")
5151
self.assertFalse(
@@ -56,7 +56,7 @@ def test_cache_pickle(self):
5656
raise_flag = True
5757

5858
@CachedPickle(path=path)
59-
def _f1():
59+
def _f1() -> int:
6060
if raise_flag:
6161
raise ValueError
6262
return EXPECTED
@@ -87,7 +87,7 @@ def _f1():
8787
_f1()
8888

8989
@CachedPickle(path=path, force=True)
90-
def _f2():
90+
def _f2() -> int:
9191
return EXPECTED_2
9292

9393
self.assertEqual(EXPECTED_2, _f2()) # overwrites the file

tests/test_config.py

+13-6
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44

55
import tempfile
66
import unittest
7+
from configparser import ConfigParser
78
from pathlib import Path
9+
from typing import ClassVar
810

911
import pystow
1012
from pystow.config_api import CONFIG_HOME_ENVVAR, _get_cfp
@@ -14,6 +16,11 @@
1416
class TestConfig(unittest.TestCase):
1517
"""Test configuration."""
1618

19+
test_section: ClassVar[str]
20+
test_option: ClassVar[str]
21+
test_value: ClassVar[str]
22+
cfp: ClassVar[ConfigParser]
23+
1724
@classmethod
1825
def setUpClass(cls) -> None:
1926
"""Set up the class for testing."""
@@ -28,7 +35,7 @@ def setUpClass(cls) -> None:
2835
value=cls.test_value,
2936
)
3037

31-
def test_env_cast(self):
38+
def test_env_cast(self) -> None:
3239
"""Test casting works properly when getting from the environment."""
3340
with mock_envvar("TEST_VAR", "1234"):
3441
self.assertEqual("1234", pystow.get_config("test", "var"))
@@ -39,7 +46,7 @@ def test_env_cast(self):
3946
with self.assertRaises(TypeError):
4047
pystow.get_config("test", "var", dtype=object)
4148

42-
def test_get_config(self):
49+
def test_get_config(self) -> None:
4350
"""Test lookup not existing."""
4451
self.assertIsNone(pystow.get_config(self.test_section, "key"))
4552
self.assertEqual("1234", pystow.get_config(self.test_section, "key", default="1234"))
@@ -94,17 +101,17 @@ def test_get_config(self):
94101
True, pystow.get_config(self.test_section, self.test_option, passthrough=1, dtype=bool)
95102
)
96103

97-
def test_subsection(self):
104+
def test_subsection(self) -> None:
98105
"""Test subsections."""
99106
with tempfile.TemporaryDirectory() as directory, mock_envvar(CONFIG_HOME_ENVVAR, directory):
100-
directory = Path(directory)
101-
path = directory.joinpath("test.ini")
107+
directory_ = Path(directory)
108+
path = directory_.joinpath("test.ini")
102109
self.assertFalse(path.is_file(), msg="file should not already exist")
103110

104111
self.assertIsNone(pystow.get_config("test:subtest", "key"))
105112
self.assertFalse(path.is_file(), msg="getting config should not create a file")
106113

107114
pystow.write_config("test:subtest", "key", "value")
108-
self.assertTrue(path.is_file(), msg=f"{list(directory.iterdir())}")
115+
self.assertTrue(path.is_file(), msg=f"{list(directory_.iterdir())}")
109116

110117
self.assertEqual("value", pystow.get_config("test:subtest", "key"))

0 commit comments

Comments
 (0)