Coverage for src/extratools_core/testtools.py: 99%

70 statements  

« prev     ^ index     » next       coverage.py v7.8.1, created at 2025-05-27 20:51 -0700

1from collections.abc import Callable, Mapping, MutableMapping 

2from typing import Any 

3 

4 

5def expect_exception(error_cls: type[Exception], f: Callable[[], Any]) -> None: 

6 try: 

7 f() 

8 except error_cls: 

9 return 

10 

11 raise AssertionError 

12 

13 

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() 

21 

22 assert isinstance(m, Mapping) 

23 

24 assert len(m) >= 0 

25 

26 assert list(zip(m.keys(), m.values(), strict=True)) == list(m.items()) 

27 

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 

34 

35 key = key_cls() 

36 value = value_cls() 

37 

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 

42 

43 

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() 

51 

52 assert isinstance(m, MutableMapping) 

53 

54 assert len(m) >= 0 

55 

56 m.clear() 

57 assert len(m) == 0 

58 

59 assert list(m.keys()) == [] 

60 assert list(m.values()) == [] 

61 assert list(m.items()) == [] 

62 

63 key: KT = key_cls() 

64 value: VT = value_cls() 

65 assert key not in m 

66 

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 

72 

73 assert list(m.keys()) == [key] 

74 assert list(m.values()) == [value] 

75 assert list(m.items()) == [(key, value)] 

76 

77 # No duplication 

78 m[key] = value 

79 assert len(m) == 1 

80 

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 

87 

88 assert m.setdefault(key, value) == value 

89 assert key in m 

90 assert len(m) == 1 

91 assert m[key] == value 

92 

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 

100 

101 m.update([(key, value)]) 

102 assert len(m) == 1 

103 

104 assert list(zip(m.keys(), m.values(), strict=True)) == list(m.items()) 

105 

106 for key, value in m.items(): 

107 assert key in m 

108 assert m[key] == value 

109 assert m.get(key) == value 

110 

111 m.clear() 

112 assert len(m) == 0