Coverage for src/extratools_core/testtools.py: 99%
70 statements
« prev ^ index » next coverage.py v7.8.1, created at 2025-06-19 04:20 -0700
« prev ^ index » next coverage.py v7.8.1, created at 2025-06-19 04:20 -0700
1from collections.abc import Callable, Mapping, MutableMapping
2from typing import Any
5def expect_exception(error_cls: type[Exception], f: Callable[[], Any]) -> None:
6 try:
7 f()
8 except error_cls:
9 return
11 raise AssertionError
14def is_proper_mapping[KT, VT](
15 cls: type[Mapping[KT, VT]] | Callable[[], Mapping[KT, VT]],
16 *,
17 key_cls: type[KT] | Callable[[], KT],
18 value_cls: type[VT] | Callable[[], VT],
19) -> None:
20 m: Mapping[KT, VT] = cls()
22 assert isinstance(m, Mapping)
24 assert len(m) >= 0
26 assert list(zip(m.keys(), m.values(), strict=True)) == list(m.items())
28 key: KT
29 value: VT
30 for key, value in m.items():
31 assert key in m
32 assert m[key] == value
33 assert m.get(key) == value
35 key = key_cls()
36 value = value_cls()
38 assert key not in m
39 expect_exception(KeyError, lambda: m[key])
40 assert m.get(key) is None
41 assert m.get(key, value) == value
44def is_proper_mutable_mapping[KT, VT](
45 cls: type[MutableMapping[KT, VT]] | Callable[[], MutableMapping[KT, VT]],
46 *,
47 key_cls: type[KT] | Callable[[], KT],
48 value_cls: type[VT] | Callable[[], VT],
49) -> None:
50 m: MutableMapping[KT, VT] = cls()
52 assert isinstance(m, MutableMapping)
54 assert len(m) >= 0
56 m.clear()
57 assert len(m) == 0
59 assert list(m.keys()) == []
60 assert list(m.values()) == []
61 assert list(m.items()) == []
63 key: KT = key_cls()
64 value: VT = value_cls()
65 assert key not in m
67 m[key] = value
68 assert key in m
69 assert len(m) == 1
70 assert m[key] == value
71 assert m.get(key) == value
73 assert list(m.keys()) == [key]
74 assert list(m.values()) == [value]
75 assert list(m.items()) == [(key, value)]
77 # No duplication
78 m[key] = value
79 assert len(m) == 1
81 del m[key]
82 assert key not in m
83 assert len(m) == 0
84 expect_exception(KeyError, lambda: m[key])
85 assert m.get(key) is None
86 assert m.get(key, value) == value
88 assert m.setdefault(key, value) == value
89 assert key in m
90 assert len(m) == 1
91 assert m[key] == value
93 assert m.pop(key) == value
94 assert key not in m
95 assert len(m) == 0
96 # `pop`` is special here that it would raise `KeyError` if `default` is not specified.
97 expect_exception(KeyError, lambda: m.pop(key))
98 assert m.pop(key, None) is None
99 assert m.pop(key, value) == value
101 m.update([(key, value)])
102 assert len(m) == 1
104 assert list(zip(m.keys(), m.values(), strict=True)) == list(m.items())
106 for key, value in m.items():
107 assert key in m
108 assert m[key] == value
109 assert m.get(key) == value
111 m.clear()
112 assert len(m) == 0