Coverage for tests/unit/misc/test_sequence.py: 100%
73 statements
« prev ^ index » next coverage.py v7.6.1, created at 2025-04-04 03:33 -0600
« prev ^ index » next coverage.py v7.6.1, created at 2025-04-04 03:33 -0600
1import pytest
3from muutils.misc.sequence import (
4 list_split,
5 list_join,
6 flatten,
7 apply_mapping_chain,
8 apply_mapping,
9)
11# Test data
12simple_mapping = {1: "one", 2: "two", 3: "three"}
13chain_mapping = {1: ["one", "uno"], 2: ["two", "dos"], 3: ["three", "tres"]}
16def test_list_split():
17 # with integers
18 assert list_split([1, 2, 3, 2, 4], 2) == [
19 [1],
20 [3],
21 [4],
22 ], "List should be split correctly"
23 assert list_split([1, 2, 2, 2, 4], 2) == [
24 [1],
25 [],
26 [],
27 [4],
28 ], "Empty sublists should be created for consecutive delimiters"
29 assert list_split([], 2) == [
30 []
31 ], "Empty list should return a list with one empty sublist"
33 # with strings
34 assert list_split(["a", "b", "c", "b", "d"], "b") == [
35 ["a"],
36 ["c"],
37 ["d"],
38 ], "List should be split correctly"
39 assert list_split(["a", "b", "b", "b", "d"], "b") == [
40 ["a"],
41 [],
42 [],
43 ["d"],
44 ], "Empty sublists should be created for consecutive delimiters"
45 assert list_split([], "b") == [
46 []
47 ], "Empty list should return a list with one empty sublist"
49 # mixed types
50 assert list_split([1, "b", 3, "b", 4], "b") == [
51 [1],
52 [3],
53 [4],
54 ], "List should be split correctly"
55 assert list_split([1, "b", "b", "b", 4], "b") == [
56 [1],
57 [],
58 [],
59 [4],
60 ], "Empty sublists should be created for consecutive delimiters"
61 assert list_split([], "b") == [
62 []
63 ], "Empty list should return a list with one empty sublist"
65 assert list_split([1, 2, 3, 0, 4, 5, 0, 6], 0) == [[1, 2, 3], [4, 5], [6]]
66 assert list_split([0, 1, 2, 3], 0) == [[], [1, 2, 3]]
67 assert list_split([1, 2, 3], 0) == [[1, 2, 3]]
68 assert list_split([], 0) == [[]]
71def test_list_join():
72 # with integers
73 assert list_join([1, 2, 3], lambda: 0) == [
74 1,
75 0,
76 2,
77 0,
78 3,
79 ], "Items should be joined correctly with factory-produced values"
80 assert list_join([1], lambda: 0) == [1], "Single item list should remain unchanged"
81 assert list_join([], lambda: 0) == [], "Empty list should remain unchanged"
83 # with strings
84 assert list_join(["a", "b", "c"], lambda: "x") == [
85 "a",
86 "x",
87 "b",
88 "x",
89 "c",
90 ], "Items should be joined correctly with factory-produced values"
91 assert list_join(["a"], lambda: "x") == [
92 "a"
93 ], "Single item list should remain unchanged"
94 assert list_join([], lambda: "x") == [], "Empty list should remain unchanged"
96 # mixed types
97 assert list_join([1, "b", 3], lambda: "x") == [
98 1,
99 "x",
100 "b",
101 "x",
102 3,
103 ], "Items should be joined correctly with factory-produced values"
104 assert list_join([1], lambda: "x") == [
105 1
106 ], "Single item list should remain unchanged"
107 assert list_join([], lambda: "x") == [], "Empty list should remain unchanged"
110# Testing the flatten function
111def test_flatten_full_flattening():
112 assert list(flatten([1, [2, [3, 4]], 5])) == [1, 2, 3, 4, 5]
113 assert list(flatten([1, [2, [3, [4, [5]]]]])) == [1, 2, 3, 4, 5]
114 assert list(flatten([])) == []
117def test_flatten_partial_flattening():
118 assert list(flatten([1, [2, [3, 4]], 5], levels_to_flatten=1)) == [1, 2, [3, 4], 5]
119 assert list(flatten([1, [2, [3, [4, [5]]]]], levels_to_flatten=2)) == [
120 1,
121 2,
122 3,
123 [4, [5]],
124 ]
127def test_flatten_with_non_iterables():
128 assert list(flatten([1, 2, 3])) == [1, 2, 3]
129 assert list(flatten([1, "abc", 2, [3, 4], 5])) == [1, "abc", 2, 3, 4, 5]
132def test_apply_mapping_basic():
133 assert apply_mapping(simple_mapping, [1, 2, 3]) == ["one", "two", "three"]
136def test_apply_mapping_missing_skip():
137 assert apply_mapping(simple_mapping, [1, 4, 2], when_missing="skip") == [
138 "one",
139 "two",
140 ]
143def test_apply_mapping_missing_include():
144 assert apply_mapping(simple_mapping, [1, 4, 2], when_missing="include") == [
145 "one",
146 4,
147 "two",
148 ]
151def test_apply_mapping_missing_except():
152 with pytest.raises(KeyError):
153 apply_mapping(simple_mapping, [1, 4, 2], when_missing="except")
156def test_apply_mapping_invalid_when_missing():
157 with pytest.raises(ValueError):
158 apply_mapping(simple_mapping, [1, 2, 3, 4], when_missing="invalid") # type: ignore[arg-type]
161def test_apply_mapping_empty_input():
162 assert apply_mapping(simple_mapping, []) == []
165def test_apply_mapping_empty_mapping():
166 assert apply_mapping({}, [1, 2, 3], when_missing="include") == [1, 2, 3]
169def test_apply_mapping_chain_basic():
170 assert apply_mapping_chain(chain_mapping, [1, 2, 3]) == [
171 "one",
172 "uno",
173 "two",
174 "dos",
175 "three",
176 "tres",
177 ]
180def test_apply_mapping_chain_missing_skip():
181 assert apply_mapping_chain(chain_mapping, [1, 4, 2], when_missing="skip") == [
182 "one",
183 "uno",
184 "two",
185 "dos",
186 ]
189def test_apply_mapping_chain_missing_include():
190 assert apply_mapping_chain(chain_mapping, [1, 4, 2], when_missing="include") == [
191 "one",
192 "uno",
193 4,
194 "two",
195 "dos",
196 ]
199def test_apply_mapping_chain_missing_except():
200 with pytest.raises(KeyError):
201 apply_mapping_chain(chain_mapping, [1, 4, 2], when_missing="except")
204def test_apply_mapping_chain_invalid_when_missing():
205 with pytest.raises(ValueError):
206 apply_mapping_chain(chain_mapping, [1, 2, 3, 4], when_missing="invalid") # type: ignore[arg-type]
209def test_apply_mapping_chain_empty_input():
210 assert apply_mapping_chain(chain_mapping, []) == []
213def test_apply_mapping_chain_empty_mapping():
214 assert apply_mapping_chain({}, [1, 2, 3], when_missing="include") == [1, 2, 3]
217def test_apply_mapping_chain_empty_values():
218 empty_chain_mapping = {1: [], 2: ["two"], 3: []}
219 assert apply_mapping_chain(empty_chain_mapping, [1, 2, 3]) == ["two"]