1# -*- coding: utf-8 -*-
2
3import math
4from operator import itemgetter
5
6import pydash as _
7
8from . import fixtures
9from .fixtures import parametrize
10
11
12@parametrize('case,expected', [
13    ((['a', 'b', 'c', 'd', 'e'], [0], [2], [4]), ['a', 'c', 'e']),
14    ((['moe', 'larry', 'curly'], 0, 2), ['moe', 'curly']),
15    (({'a': 1, 'b': 2, 'c': 3}, 'a', 'b'), [1, 2])
16])
17def test_at(case, expected):
18    assert _.at(*case) == expected
19
20
21@parametrize('case,expected', [
22    (([4.3, 6.1, 6.4], lambda num: int(math.floor(num))), {4: 1, 6: 2}),
23    (([{'one': 1}, {'one': 1}, {'two': 2}, {'one': 1}], {'one': 1}),
24     {True: 3, False: 1}),
25    (([{'one': 1}, {'one': 1}, {'two': 2}, {'one': 1}], 'one'),
26     {1: 3, None: 1}),
27    (({1: 0, 2: 0, 4: 3},), {0: 2, 3: 1})
28])
29def test_count_by(case, expected):
30    assert _.count_by(*case) == expected
31
32
33@parametrize('case,expected', [
34    (([True, 1, None, 'yes'], bool), False),
35    (([True, 1, None, 'yes'],), False),
36    (([{'name': 'moe', 'age': 40},
37       {'name': 'larry', 'age': 50}],
38      'age'),
39     True),
40    (([{'name': 'moe', 'age': 40},
41       {'name': 'larry', 'age': 50}],
42      {'age': 50}),
43     False)
44])
45def test_every(case, expected):
46    assert _.every(*case) == expected
47
48
49@parametrize('case,expected', [
50    (([0, True, False, None, 1, 2, 3],), [True, 1, 2, 3]),
51    (([1, 2, 3, 4, 5, 6], lambda num: num % 2 == 0), [2, 4, 6]),
52    (([{'name': 'barney', 'age': 36, 'blocked': False},
53       {'name': 'fred', 'age': 40, 'blocked': True}],
54      'blocked'),
55     [{'name': 'fred', 'age': 40, 'blocked': True}]),
56    (([{'name': 'barney', 'age': 36, 'blocked': False},
57       {'name': 'fred', 'age': 40, 'blocked': True}],
58      {'age': 36}),
59     [{'name': 'barney', 'age': 36, 'blocked': False}]),
60    (([{'name': 'moe', 'age': 40}, {'name': 'larry', 'age': 50}], {'age': 40}),
61     [{'name': 'moe', 'age': 40}])
62])
63def test_filter_(case, expected):
64    assert _.filter_(*case) == expected
65
66
67@parametrize('case,expected', [
68    (([{'name': 'barney', 'age': 36, 'blocked': False},
69       {'name': 'fred', 'age': 40, 'blocked': True},
70       {'name': 'pebbles', 'age': 1, 'blocked': False}],
71      lambda c: c['age'] < 40),
72     {'name': 'barney', 'age': 36, 'blocked': False}),
73    (([{'name': 'barney', 'age': 36, 'blocked': False},
74       {'name': 'fred', 'age': 40, 'blocked': True},
75       {'name': 'pebbles', 'age': 1, 'blocked': False}],
76      {'age': 1}),
77     {'name': 'pebbles', 'age': 1, 'blocked': False}),
78    (([{'name': 'barney', 'age': 36, 'blocked': False},
79       {'name': 'fred', 'age': 40, 'blocked': True},
80       {'name': 'pebbles', 'age': 1, 'blocked': False}],
81      'blocked'),
82     {'name': 'fred', 'age': 40, 'blocked': True}),
83    (([{'name': 'barney', 'age': 36, 'blocked': False},
84       {'name': 'fred', 'age': 40, 'blocked': True},
85       {'name': 'pebbles', 'age': 1, 'blocked': False}],),
86     {'name': 'barney', 'age': 36, 'blocked': False}),
87    (({'abc': 1, 'xyz': 2, 'c': 3}.keys(),
88      lambda x: 'y' in x),
89     'xyz'),
90    (({'abc': 1, 'xyz': 2, 'c': 3}.values(),
91      lambda x: x < 2),
92     1),
93])
94def test_find(case, expected):
95    assert _.find(*case) == expected
96
97
98@parametrize('case,expected', [
99    (([1, 2, 3, 4], lambda num: num % 2 == 1), 3),
100    (({'abc': 1, 'xyz': 2, 'c': 3}.keys(),
101      lambda x: 'y' in x),
102     'xyz'),
103    (({'abc': 1, 'xyz': 2, 'c': 3}.values(),
104      lambda x: x < 2),
105     1),
106])
107def test_find_last(case, expected):
108    assert _.find_last(*case) == expected
109
110
111@parametrize('case,expected', [
112    (([1, 2, 3], None), [1, 2, 3]),
113    (([[1], [2], [3]], None), [1, 2, 3]),
114    (([[[1]], [[2]], [[3]]], None), [[1], [2], [3]]),
115    (([1, 2, 3], lambda x: [x - 1]), [0, 1, 2]),
116    (([1, 2, 3], lambda x: [[x], [x]]), [[1], [1], [2], [2], [3], [3]]),
117])
118def test_flat_map(case, expected):
119    assert _.flat_map(*case) == expected
120
121
122@parametrize('case,expected', [
123    (([1, 2, 3], None), [1, 2, 3]),
124    (([[1], [2], [3]], None), [1, 2, 3]),
125    (([[[1]], [[2]], [[3]]], None), [1, 2, 3]),
126    (([1, 2, 3], lambda x: [x - 1]), [0, 1, 2]),
127    (([1, 2, 3], lambda x: [[x], [x]]), [1, 1, 2, 2, 3, 3]),
128])
129def test_flat_map_deep(case, expected):
130    assert _.flat_map_deep(*case) == expected
131
132
133@parametrize('case,expected', [
134    (([1, 2, 3], None), [1, 2, 3]),
135    (([[1], [2], [3]], None), [1, 2, 3]),
136    (([[[1]], [[2]], [[3]]], None), [[1], [2], [3]]),
137    (([[[1]], [[2]], [[3]]], None, 1), [[1], [2], [3]]),
138    (([[[1]], [[2]], [[3]]], None, 2), [1, 2, 3]),
139])
140def test_flat_map_depth(case, expected):
141    assert _.flat_map_depth(*case) == expected
142
143
144@parametrize('case,expected', [
145    (([1, 2, 3], fixtures.noop), [1, 2, 3]),
146    (([1, 2, 3], lambda value: value < 2), [1, 2, 3]),
147    (({'one': 1, 'two': 2, 'three': 3}, fixtures.noop),
148     {'one': 1, 'two': 2, 'three': 3}),
149])
150def test_for_each(case, expected):
151    assert _.for_each(*case) == expected
152
153
154@parametrize('case,expected', [
155    (([1, 2, 3], fixtures.noop), [1, 2, 3]),
156    (([1, 2, 3], lambda value: value < 2), [1, 2, 3]),
157    (({'one': 1, 'two': 2, 'three': 3}, fixtures.noop),
158     {'one': 1, 'two': 2, 'three': 3}),
159])
160def test_for_each_right(case, expected):
161    assert _.for_each_right(*case) == expected
162
163
164@parametrize('case,expected', [
165    (([4.2, 6.1, 6.4],
166      lambda num: int(math.floor(num))),
167     {4: [4.2], 6: [6.1, 6.4]}),
168])
169def test_group_by(case, expected):
170    assert _.group_by(*case) == expected
171
172
173@parametrize('case,expected', [
174    (([1, 2, 3], 1), True),
175    (([1, 2, 3], 1, 2), False),
176    (({'name': 'fred', 'age': 40}, 'fred'), True),
177    (('pebbles', 'eb'), True)
178])
179def test_includes(case, expected):
180    assert _.includes(*case) == expected
181
182
183@parametrize('case,expected', [
184    (([{'a': {'b': 2}}, {'a': {'c': 3}}], 'a.items'),
185     [{'b': 2}.items(), {'c': 3}.items()]),
186    (([{'a': {'b': {'c': 2}}}, {'a': {'b': {'c': 3}}}], 'a.b.items'),
187     [{'c': 2}.items(), {'c': 3}.items()]),
188])
189def test_invoke_map(case, expected):
190    assert _.invoke_map(*case) == expected
191
192
193@parametrize('case,expected', [
194    (([{'dir': 'left', 'code': 97}, {'dir': 'right', 'code': 100}], 'dir'),
195     {'left': {'dir': 'left', 'code': 97},
196      'right': {'dir': 'right', 'code': 100}}),
197])
198def test_key_by(case, expected):
199    assert _.key_by(*case) == expected
200
201
202@parametrize('case,expected,sort_results', [
203    (([1, 2, 3],), [1, 2, 3], False),
204    (([1.1, 2.1, 3.1], int), [1, 2, 3], False),
205    (([1, 2, 3], lambda num: num * 3), [3, 6, 9], False),
206    (([[1], [2, 3], [4, 5, 6]], len), [1, 2, 3], False),
207    (({'one': 1, 'two': 2, 'three': 3}, lambda num: num * 3),
208     [3, 6, 9],
209     True),
210    (([{'name': 'moe', 'age': 40},
211       {'name': 'larry', 'age': 50}],
212      'name'),
213     ['moe', 'larry'],
214     False),
215    (([{'level1': {'level2': {'level3': {'value': 1}}}},
216       {'level1': {'level2': {'level3': {'value': 2}}}},
217       {'level1': {'level2': {'level3': {'value': 3}}}},
218       {'level1': {'level2': {'level3': {'value': 4}}}},
219       {'level1': {'level2': {}}},
220       {}],
221      'level1.level2.level3.value'),
222     [1, 2, 3, 4, None, None],
223     False),
224    (([[0, 1], [2, 3], [4, 5]], 1), [1, 3, 5], False),
225    (([{'a': 1, 'b': 2, 'c': -1},
226       {'a': 3, 'b': 4, 'c': -1},
227       {'a': 5, 'b': 6, 'c': -1}],
228      itemgetter('a', 'b')),
229     [(1, 2), (3, 4), (5, 6)],
230     False)
231])
232def test_map_(case, expected, sort_results):
233    actual = _.map_(*case)
234
235    if sort_results:
236        actual = sorted(actual)
237
238    assert actual == expected
239
240
241@parametrize('case,expected', [
242    (([{'a': 1, 'b': 2, 'c': 3},
243       {'a': 1, 'b': 2, 'c': 4},
244       {'a': 1, 'b': 2, 'c': 5},
245       {'a': 1, 'b': 1, 'c': 6},
246       {'a': 1, 'b': 1, 'c': 7},
247       {'a': 2, 'b': 2, 'c': 8},
248       {'a': 2, 'b': 2, 'c': 9},
249       {'a': 2, 'b': 2, 'c': 10},
250       {'a': 3, 'b': 1, 'c': 11}],
251      'a'),
252     {1: [{'a': 1, 'b': 2, 'c': 3},
253          {'a': 1, 'b': 2, 'c': 4},
254          {'a': 1, 'b': 2, 'c': 5},
255          {'a': 1, 'b': 1, 'c': 6},
256          {'a': 1, 'b': 1, 'c': 7}],
257      2: [{'a': 2, 'b': 2, 'c': 8},
258          {'a': 2, 'b': 2, 'c': 9},
259          {'a': 2, 'b': 2, 'c': 10}],
260      3: [{'a': 3, 'b': 1, 'c': 11}]}),
261    (([{'a': 1, 'b': 2, 'c': 3},
262       {'a': 1, 'b': 2, 'c': 4},
263       {'a': 1, 'b': 2, 'c': 5},
264       {'a': 1, 'b': 1, 'c': 6},
265       {'a': 1, 'b': 1, 'c': 7},
266       {'a': 2, 'b': 2, 'c': 8},
267       {'a': 2, 'b': 2, 'c': 9},
268       {'a': 2, 'b': 2, 'c': 10},
269       {'a': 3, 'b': 1, 'c': 11}],
270      'a', 'b'),
271     {1: {2: [{'a': 1, 'b': 2, 'c': 3},
272              {'a': 1, 'b': 2, 'c': 4},
273              {'a': 1, 'b': 2, 'c': 5}],
274          1: [{'a': 1, 'b': 1, 'c': 6},
275              {'a': 1, 'b': 1, 'c': 7}]},
276      2: {2: [{'a': 2, 'b': 2, 'c': 8},
277              {'a': 2, 'b': 2, 'c': 9},
278              {'a': 2, 'b': 2, 'c': 10}]},
279      3: {1: [{'a': 3, 'b': 1, 'c': 11}]}}),
280    (([{'a': 1, 'b': 2, 'c': 3},
281       {'a': 1, 'b': 2, 'c': 4},
282       {'a': 1, 'b': 2, 'c': 5},
283       {'a': 1, 'b': 1, 'c': 6},
284       {'a': 1, 'b': 1, 'c': 7},
285       {'a': 2, 'b': 2, 'c': 8},
286       {'a': 2, 'b': 2, 'c': 9},
287       {'a': 2, 'b': 2, 'c': 10},
288       {'a': 3, 'b': 1, 'c': 11}],),
289     [{'a': 1, 'b': 2, 'c': 3},
290      {'a': 1, 'b': 2, 'c': 4},
291      {'a': 1, 'b': 2, 'c': 5},
292      {'a': 1, 'b': 1, 'c': 6},
293      {'a': 1, 'b': 1, 'c': 7},
294      {'a': 2, 'b': 2, 'c': 8},
295      {'a': 2, 'b': 2, 'c': 9},
296      {'a': 2, 'b': 2, 'c': 10},
297      {'a': 3, 'b': 1, 'c': 11}]),
298])
299def test_nest(case, expected):
300    assert _.nest(*case) == expected
301
302
303@parametrize('case,expected', [
304    (([{'user': 'barney', 'age': 36},
305       {'user': 'fred', 'age': 40},
306       {'user': 'barney', 'age': 26},
307       {'user': 'fred', 'age': 30}],
308      []),
309     [{'user': 'barney', 'age': 36},
310      {'user': 'fred', 'age': 40},
311      {'user': 'barney', 'age': 26},
312      {'user': 'fred', 'age': 30}]),
313    (([{'user': 'barney', 'age': 36},
314       {'user': 'fred', 'age': 40},
315       {'user': 'barney', 'age': 26},
316       {'user': 'fred', 'age': 30}],
317      ['user', 'age']),
318     [{'user': 'barney', 'age': 26},
319      {'user': 'barney', 'age': 36},
320      {'user': 'fred', 'age': 30},
321      {'user': 'fred', 'age': 40}]),
322    (([{'user': 'barney', 'age': 36},
323       {'user': 'fred', 'age': 40},
324       {'user': 'barney', 'age': 26},
325       {'user': 'fred', 'age': 30}],
326      ['-user', 'age']),
327     [{'user': 'fred', 'age': 30},
328      {'user': 'fred', 'age': 40},
329      {'user': 'barney', 'age': 26},
330      {'user': 'barney', 'age': 36}]),
331    (([{'user': 'barney', 'age': 36},
332       {'user': 'fred', 'age': 40},
333       {'user': 'barney', 'age': 26},
334       {'user': 'fred', 'age': 30}],
335      ['user', '-age']),
336     [{'user': 'barney', 'age': 36},
337      {'user': 'barney', 'age': 26},
338      {'user': 'fred', 'age': 40},
339      {'user': 'fred', 'age': 30}]),
340    (([{'user': 'barney', 'age': 36},
341       {'user': 'fred', 'age': 40},
342       {'user': 'barney', 'age': 26},
343       {'user': 'fred', 'age': 30}],
344      ['-user', '-age']),
345     [{'user': 'fred', 'age': 40},
346      {'user': 'fred', 'age': 30},
347      {'user': 'barney', 'age': 36},
348      {'user': 'barney', 'age': 26}]),
349    (({1: {'user': 'barney', 'age': 36},
350       2: {'user': 'fred', 'age': 40},
351       3: {'user': 'barney', 'age': 26},
352       4: {'user': 'fred', 'age': 30}},
353      ['user', 'age']),
354     [{'user': 'barney', 'age': 26},
355      {'user': 'barney', 'age': 36},
356      {'user': 'fred', 'age': 30},
357      {'user': 'fred', 'age': 40}]),
358    (([{'user': 'barney', 'age': 36},
359       {'user': 'fred', 'age': 40},
360       {'user': 'barney', 'age': 26},
361       {'user': 'fred', 'age': 30}],
362      [],
363      True),
364     [{'user': 'barney', 'age': 36},
365      {'user': 'fred', 'age': 40},
366      {'user': 'barney', 'age': 26},
367      {'user': 'fred', 'age': 30}]),
368    (([{'user': 'barney', 'age': 36},
369       {'user': 'fred', 'age': 40},
370       {'user': 'barney', 'age': 26},
371       {'user': 'fred', 'age': 30}],
372      ['user', 'age'],
373      True),
374     list(reversed([{'user': 'barney', 'age': 26},
375                    {'user': 'barney', 'age': 36},
376                    {'user': 'fred', 'age': 30},
377                    {'user': 'fred', 'age': 40}]))),
378    (([{'user': 'barney', 'age': 36},
379       {'user': 'fred', 'age': 40},
380       {'user': 'barney', 'age': 26},
381       {'user': 'fred', 'age': 30}],
382      ['-user', 'age'],
383      True),
384     list(reversed([{'user': 'fred', 'age': 30},
385                    {'user': 'fred', 'age': 40},
386                    {'user': 'barney', 'age': 26},
387                    {'user': 'barney', 'age': 36}]))),
388    (([{'user': 'barney', 'age': 36},
389       {'user': 'fred', 'age': 40},
390       {'user': 'barney', 'age': 26},
391       {'user': 'fred', 'age': 30}],
392      ['user', '-age'],
393      True),
394     list(reversed([{'user': 'barney', 'age': 36},
395                    {'user': 'barney', 'age': 26},
396                    {'user': 'fred', 'age': 40},
397                    {'user': 'fred', 'age': 30}]))),
398    (([{'user': 'barney', 'age': 36},
399       {'user': 'fred', 'age': 40},
400       {'user': 'barney', 'age': 26},
401       {'user': 'fred', 'age': 30}],
402      ['-user', '-age'],
403      True),
404     list(reversed([{'user': 'fred', 'age': 40},
405                    {'user': 'fred', 'age': 30},
406                    {'user': 'barney', 'age': 36},
407                    {'user': 'barney', 'age': 26}]))),
408    (({1: {'user': 'barney', 'age': 36},
409       2: {'user': 'fred', 'age': 40},
410       3: {'user': 'barney', 'age': 26},
411       4: {'user': 'fred', 'age': 30}},
412      ['user', 'age'],
413      True),
414     list(reversed([{'user': 'barney', 'age': 26},
415                    {'user': 'barney', 'age': 36},
416                    {'user': 'fred', 'age': 30},
417                    {'user': 'fred', 'age': 40}]))),
418    (([{'user': 'barney', 'age': 36},
419       {'user': 'fred', 'age': 40},
420       {'user': 'barney', 'age': 26},
421       {'user': 'fred', 'age': 30}],
422      ['user', 'age'],
423      [False, True],
424      True),
425     list(reversed([{'user': 'fred', 'age': 30},
426                    {'user': 'fred', 'age': 40},
427                    {'user': 'barney', 'age': 26},
428                    {'user': 'barney', 'age': 36}]))),
429    (([{'user': 'barney', 'age': 36},
430       {'user': 'fred', 'age': 40},
431       {'user': 'barney', 'age': 26},
432       {'user': 'fred', 'age': 30}],
433      ['user', 'age'],
434      [False],
435      True),
436     list(reversed([{'user': 'fred', 'age': 30},
437                    {'user': 'fred', 'age': 40},
438                    {'user': 'barney', 'age': 26},
439                    {'user': 'barney', 'age': 36}]))),
440])
441def test_order_by(case, expected):
442    assert _.order_by(*case) == expected
443
444
445@parametrize('case,expected', [
446    (([1, 2, 3], lambda item: item % 2), [[1, 3], [2]]),
447    (([1.2, 2.3, 3.4], lambda item: math.floor(item) % 2),
448     [[1.2, 3.4], [2.3]]),
449    (([{'name': 'barney', 'age': 36},
450       {'name': 'fred', 'age': 40, 'blocked': True},
451       {'name': 'pebbles', 'age': 1}],
452      {'age': 1}),
453     [[{'name': 'pebbles', 'age': 1}],
454      [{'name': 'barney', 'age': 36},
455       {'name': 'fred', 'age': 40, 'blocked': True}]]),
456    (([{'name': 'barney', 'age': 36},
457       {'name': 'fred', 'age': 40, 'blocked': True},
458       {'name': 'pebbles', 'age': 1}],
459      'blocked'),
460     [[{'name': 'fred', 'age': 40, 'blocked': True}],
461      [{'name': 'barney', 'age': 36},
462       {'name': 'pebbles', 'age': 1}]]),
463])
464def test_partition(case, expected):
465    assert _.partition(*case) == expected
466
467
468@parametrize('case,expected', [
469    (([{'name': 'moe', 'age': 40}, {'name': 'larry', 'age': 50}],
470      'name'),
471     ['moe', 'larry']),
472    (([{'level1': {'level2': {'level3': {'value': 1}}}},
473       {'level1': {'level2': {'level3': {'value': 2}}}},
474       {'level1': {'level2': {'level3': {'value': 3}}}},
475       {'level1': {'level2': {'level3': {'value': 4}}}},
476       {'level1': {'level2': {}}},
477        {}],
478      'level1.level2.level3.value'),
479     [1, 2, 3, 4, None, None])
480])
481def test_pluck(case, expected):
482    assert _.pluck(*case) == expected
483
484
485@parametrize('case,expected', [
486    (([1, 2, 3], None), 1),
487    (([1, 2, 3], fixtures.reduce_iteratee0), 6),
488    (({'a': 1, 'b': 2, 'c': 3}, fixtures.reduce_iteratee1, {}),
489     {'a': 3, 'b': 6, 'c': 9})
490])
491def test_reduce_(case, expected):
492    assert _.reduce_(*case) == expected
493
494
495@parametrize('case,exception', [
496    (([],), TypeError)
497])
498def test_reduce_raise(case, exception):
499    raised = False
500
501    try:
502        _.reduce_(*case)
503    except exception:
504        raised = True
505
506    assert raised
507
508
509@parametrize('case,expected', [
510    (([1, 2, 3], None), 3),
511    (([1, 2, 3], fixtures.reduce_iteratee0), 6),
512    (([[0, 1], [2, 3], [4, 5]], fixtures.reduce_right_iteratee0),
513     [4, 5, 2, 3, 0, 1]),
514    (({'a': 1, 'b': 2, 'c': 3}, fixtures.reduce_iteratee1, {}),
515     {'a': 3, 'b': 6, 'c': 9})
516])
517def test_reduce_right(case, expected):
518    assert _.reduce_right(*case) == expected
519
520
521@parametrize('case,exception', [
522    (([],), TypeError)
523])
524def test_reduce_right_exception(case, exception):
525    raised = False
526
527    try:
528        _.reduce_right(*case)
529    except exception:
530        raised = True
531
532    assert raised
533
534
535@parametrize('case,expected', [
536    (([1, 2, 3], None), [1, 1]),
537    (([1, 2, 3], fixtures.reduce_iteratee0), [3, 6]),
538    (([1, 2, 3, 4, 5], fixtures.reduce_iteratee0, 0), [1, 3, 6, 10, 15])
539])
540def test_reductions(case, expected):
541    assert _.reductions(*case) == expected
542
543
544@parametrize('case,expected', [
545    (([1, 2, 3], None), [3, 3]),
546    (([1, 2, 3], fixtures.reduce_iteratee0), [5, 6]),
547    (([[0, 1], [2, 3], [4, 5]], fixtures.reduce_right_iteratee0),
548     [[4, 5, 2, 3], [4, 5, 2, 3, 0, 1]]),
549])
550def test_reductions_right(case, expected):
551    assert _.reductions_right(*case) == expected
552
553
554@parametrize('case,expected', [
555    (([0, True, False, None, 1, 2, 3],), [0, False, None]),
556    (([1, 2, 3, 4, 5, 6], lambda num: num % 2 == 0), [1, 3, 5]),
557    (([{'name': 'barney', 'age': 36, 'blocked': False},
558       {'name': 'fred', 'age': 40, 'blocked': True}],
559      'blocked'),
560     [{'name': 'barney', 'age': 36, 'blocked': False}]),
561    (([{'name': 'barney', 'age': 36, 'blocked': False},
562       {'name': 'fred', 'age': 40, 'blocked': True}],
563      {'age': 36}),
564     [{'name': 'fred', 'age': 40, 'blocked': True}]),
565])
566def test_reject(case, expected):
567    assert _.reject(*case) == expected
568
569
570@parametrize('case', [
571    [1, 2, 3, 4, 5, 6],
572])
573def test_sample(case):
574    assert _.sample(case) in case
575
576
577@parametrize('case', [
578    ([1, 2, 3, 4, 5, 6], 2),
579    ([1, 2, 3, 4, 5, 6], 3),
580    ([1, 2, 3, 4, 5, 6], 4),
581])
582def test_sample_size(case):
583    collection, n = case
584    sample_n = _.sample_size(*case)
585
586    assert isinstance(sample_n, list)
587    assert len(sample_n) == min(n, len(collection))
588    assert set(sample_n).issubset(collection)
589
590
591@parametrize('case', [
592    [1, 2, 3, 4, 5, 6],
593    {'one': 1, 'two': 2, 'three': 3}
594])
595def test_shuffle(case):
596    shuffled = _.shuffle(case)
597
598    assert len(shuffled) == len(case)
599
600    if isinstance(case, dict):
601        assert set(shuffled) == set(case.values())
602    else:
603        assert set(shuffled) == set(case)
604
605
606@parametrize('case', [
607    [1, 2, 3, 4, 5],
608    {'1': 1, '2': 2, '3': 3}
609])
610def test_size(case):
611    assert _.size(case) == len(case)
612
613
614@parametrize('case,expected', [
615    (([None, 0, 'yes', False], bool), True),
616    (([None, 0, 'yes', False],), True),
617    (([{'name': 'apple', 'organic': False, 'type': 'fruit'},
618       {'name': 'carrot', 'organic': True, 'type': 'vegetable'}],
619      'organic'),
620     True),
621    (([{'name': 'apple', 'organic': False, 'type': 'fruit'},
622       {'name': 'carrot', 'organic': True, 'type': 'vegetable'}],
623      {'type': 'meat'}),
624     False)
625])
626def test_some(case, expected):
627    assert _.some(*case) == expected
628
629
630@parametrize('case,expected', [
631    (([1, 2, 3], lambda x: math.sin(x)), [3, 1, 2]),
632    (([{'name': 'barney', 'age': 36},
633       {'name': 'fred', 'age': 40},
634       {'name': 'barney', 'age': 26},
635       {'name': 'fred', 'age': 30}],
636      'age'),
637     [{'name': 'barney', 'age': 26},
638      {'name': 'fred', 'age': 30},
639      {'name': 'barney', 'age': 36},
640      {'name': 'fred', 'age': 40}]),
641    (({'a': 1, 'b': 2, 'c': 3}, lambda x: math.sin(x)), [3, 1, 2]),
642    (([1, 2, 3], lambda x: math.sin(x), True), [2, 1, 3]),
643    (([{'name': 'barney', 'age': 36},
644       {'name': 'fred', 'age': 40},
645       {'name': 'barney', 'age': 26},
646       {'name': 'fred', 'age': 30}],
647      'age',
648      True),
649     [{'name': 'fred', 'age': 40},
650      {'name': 'barney', 'age': 36},
651      {'name': 'fred', 'age': 30},
652      {'name': 'barney', 'age': 26}]),
653    (({'a': 1, 'b': 2, 'c': 3}, lambda x: math.sin(x), True), [2, 1, 3]),
654])
655def test_sort_by(case, expected):
656    assert _.sort_by(*case) == expected
657
658
659@parametrize('case,expected', [
660    (('cat',), ['c', 'a', 't']),
661    ((b'cat',), ['c', 'a', 't']),
662    ((u'cat',), [u'c', u'a', u't']),
663    (('cat', False), ['cat']),
664    ((b'cat', False), [b'cat']),
665    ((u'cat', False), [u'cat']),
666    (({'a': 1, 'b': 2, 'c': 3},), [1, 2, 3])
667])
668def test_to_list(case, expected):
669    assert set(_.to_list(*case)) == set(expected)
670