1 import pytest

2

3 from muutils.misc.sequence import (

4 list_split,

5 list_join,

6 flatten,

7 apply_mapping_chain,

8 apply_mapping,

9)

10

11# Test data

12 simple_mapping = {1: "one", 2: "two", 3: "three"}

13 chain_mapping = {1: ["one", "uno"], 2: ["two", "dos"], 3: ["three", "tres"]}

14

15

16 def 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"

32

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"

48

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"

64

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) == [[]]

69

70

71 def 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"

82

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"

95

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"

108

109

110# Testing the flatten function

111 def 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([])) == []

115

116

117 def 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 ]

125

126

127 def 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]

130

131

132 def test_apply_mapping_basic():

133 assert apply_mapping(simple_mapping, [1, 2, 3]) == ["one", "two", "three"]

134

135

136 def test_apply_mapping_missing_skip():

137 assert apply_mapping(simple_mapping, [1, 4, 2], when_missing="skip") == [

138 "one",

139 "two",

140 ]

141

142

143 def test_apply_mapping_missing_include():

144 assert apply_mapping(simple_mapping, [1, 4, 2], when_missing="include") == [

145 "one",

146 4,

147 "two",

148 ]

149

150

151 def test_apply_mapping_missing_except():

152 with pytest.raises(KeyError):

153 apply_mapping(simple_mapping, [1, 4, 2], when_missing="except")

154

155

156 def test_apply_mapping_invalid_when_missing():

157 with pytest.raises(ValueError):

158 apply_mapping(simple_mapping, [1, 2, 3, 4], when_missing="invalid")

159

160

161 def test_apply_mapping_empty_input():

162 assert apply_mapping(simple_mapping, []) == []

163

164

165 def test_apply_mapping_empty_mapping():

166 assert apply_mapping({}, [1, 2, 3], when_missing="include") == [1, 2, 3]

167

168

169 def 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 ]

178

179

180 def 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 ]

187

188

189 def 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 ]

197

198

199 def test_apply_mapping_chain_missing_except():

200 with pytest.raises(KeyError):

201 apply_mapping_chain(chain_mapping, [1, 4, 2], when_missing="except")

202

203

204 def 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")

207

208

209 def test_apply_mapping_chain_empty_input():

210 assert apply_mapping_chain(chain_mapping, []) == []

211

212

213 def test_apply_mapping_chain_empty_mapping():

214 assert apply_mapping_chain({}, [1, 2, 3], when_missing="include") == [1, 2, 3]

215

216

217 def 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"]