1# mode: run
2# tag: all_language_levels
3
4cimport cython
5
6
7class Iter(object):
8    def __init__(self, it=()):
9        self.it = iter(it)
10    def __iter__(self):
11        return self
12    def __next__(self):
13        return next(self.it)
14    next = __next__
15
16
17class Map(object):
18    def __init__(self, mapping={}):
19        self.mapping = mapping
20    def __iter__(self):
21        return iter(self.mapping)
22    def keys(self):
23        return self.mapping.keys()
24    def __getitem__(self, key):
25        return self.mapping[key]
26
27
28#### tuples
29
30
31@cython.test_fail_if_path_exists(
32    "//TupleNode//TupleNode",
33    "//MergedSequenceNode",
34)
35def unpack_tuple_literal():
36    """
37    >>> unpack_tuple_literal()
38    (1, 2, 4, 5)
39    """
40    return (*(1, 2, *(4, 5)),)
41
42
43def unpack_tuple_literal_mult():
44    """
45    >>> unpack_tuple_literal_mult()
46    (1, 2, 4, 5, 4, 5, 1, 2, 4, 5, 4, 5, 1, 2, 4, 5, 4, 5)
47    """
48    return (*((1, 2, *((4, 5) * 2)) * 3),)
49
50
51@cython.test_fail_if_path_exists(
52    "//TupleNode//TupleNode",
53    "//MergedSequenceNode",
54)
55def unpack_tuple_literal_empty():
56    """
57    >>> unpack_tuple_literal_empty()
58    ()
59    """
60    return (*(*(), *()), *(), *(*(*(),),))
61
62
63def unpack_tuple_simple(it):
64    """
65    >>> unpack_tuple_simple([])
66    ()
67    >>> unpack_tuple_simple(set())
68    ()
69    >>> unpack_tuple_simple(Iter())
70    ()
71
72    >>> unpack_tuple_simple([1])
73    (1,)
74
75    >>> unpack_tuple_simple([2, 1])
76    (2, 1)
77    >>> unpack_tuple_simple((2, 1))
78    (2, 1)
79    >>> sorted(unpack_tuple_simple(set([2, 1])))
80    [1, 2]
81    >>> unpack_tuple_simple(Iter([2, 1]))
82    (2, 1)
83    """
84    return (*it,)
85
86
87def unpack_tuple_from_iterable(it):
88    """
89    >>> unpack_tuple_from_iterable([1, 2, 3])
90    (1, 2, 1, 2, 3, 1, 1, 2, 3, 1, 2, 3, 1, 2, 3, 2, 1, 1, 2, 3)
91    >>> unpack_tuple_from_iterable((1, 2, 3))
92    (1, 2, 1, 2, 3, 1, 1, 2, 3, 1, 2, 3, 1, 2, 3, 2, 1, 1, 2, 3)
93    >>> sorted(unpack_tuple_from_iterable(set([1, 2, 3])))
94    [1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3]
95
96    >>> unpack_tuple_from_iterable([1, 2])
97    (1, 2, 1, 2, 1, 1, 2, 1, 2, 1, 2, 2, 1, 1, 2)
98    >>> sorted(unpack_tuple_from_iterable(set([1, 2])))
99    [1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2]
100    >>> unpack_tuple_from_iterable(Iter([1, 2]))
101    (1, 2, 1, 2, 1, 2, 1)
102
103    >>> unpack_tuple_from_iterable([3])
104    (1, 2, 3, 1, 3, 3, 3, 2, 1, 3)
105    >>> unpack_tuple_from_iterable(set([3]))
106    (1, 2, 3, 1, 3, 3, 3, 2, 1, 3)
107    >>> unpack_tuple_from_iterable(Iter([3]))
108    (1, 2, 3, 1, 2, 1)
109
110    >>> unpack_tuple_from_iterable([])
111    (1, 2, 1, 2, 1)
112    >>> unpack_tuple_from_iterable(set([]))
113    (1, 2, 1, 2, 1)
114    >>> unpack_tuple_from_iterable([])
115    (1, 2, 1, 2, 1)
116    >>> unpack_tuple_from_iterable(Iter([1, 2, 3]))
117    (1, 2, 1, 2, 3, 1, 2, 1)
118    """
119    return (1, 2, *it, 1, *(*it, *it), *it, 2, 1, *it)
120
121
122def unpack_tuple_keep_originals(a, b, c):
123    """
124    >>> a = b = [1, 2]
125    >>> c = [3, 4]
126    >>> unpack_tuple_keep_originals(a, b, c)
127    (1, 2, 1, 2, 2, 3, 4)
128    >>> a
129    [1, 2]
130    >>> b
131    [1, 2]
132    >>> c
133    [3, 4]
134
135    >>> a = b = (1, 2)
136    >>> c = (3, 4)
137    >>> unpack_tuple_keep_originals(a, b, c)
138    (1, 2, 1, 2, 2, 3, 4)
139    >>> a
140    (1, 2)
141    >>> b
142    (1, 2)
143    >>> c
144    (3, 4)
145    """
146    return (*a, *b, 2, *c)
147
148
149def unpack_tuple_in_string_formatting(a, *args):
150    """
151    >>> print(unpack_tuple_in_string_formatting(1, 2))
152    1 2
153    >>> print(unpack_tuple_in_string_formatting(1, 'x'))
154    1 'x'
155    >>> unpack_tuple_in_string_formatting(1)  # doctest: +ELLIPSIS
156    Traceback (most recent call last):
157    TypeError: ...format...
158    >>> unpack_tuple_in_string_formatting(1, 2, 3)  # doctest: +ELLIPSIS
159    Traceback (most recent call last):
160    TypeError: ...format...
161    """
162    return "%s %r" % (a, *args)
163
164
165#### lists
166
167
168@cython.test_fail_if_path_exists(
169    "//ListNode//ListNode",
170    "//MergedSequenceNode",
171)
172def unpack_list_literal():
173    """
174    >>> unpack_list_literal()
175    [1, 2, 4, 5]
176    """
177    return [*[1, 2, *[4, 5]]]
178
179
180def unpack_list_literal_mult():
181    """
182    >>> unpack_list_literal_mult()
183    [1, 2, 4, 5, 4, 5, 1, 2, 4, 5, 4, 5, 1, 2, 4, 5, 4, 5]
184    """
185    return [*([1, 2, *([4, 5] * 2)] * 3)]
186
187
188@cython.test_fail_if_path_exists(
189    "//ListNode//ListNode",
190    "//MergedSequenceNode",
191)
192def unpack_list_literal_empty():
193    """
194    >>> unpack_list_literal_empty()
195    []
196    """
197    return [*[*[], *[]], *[], *[*[*[]]]]
198
199
200def unpack_list_simple(it):
201    """
202    >>> unpack_list_simple([])
203    []
204    >>> unpack_list_simple(set())
205    []
206    >>> unpack_list_simple(Iter())
207    []
208
209    >>> unpack_list_simple([1])
210    [1]
211
212    >>> unpack_list_simple([2, 1])
213    [2, 1]
214    >>> unpack_list_simple((2, 1))
215    [2, 1]
216    >>> sorted(unpack_list_simple(set([2, 1])))
217    [1, 2]
218    >>> unpack_list_simple(Iter([2, 1]))
219    [2, 1]
220    """
221    return [*it]
222
223
224def unpack_list_from_iterable(it):
225    """
226    >>> unpack_list_from_iterable([1, 2, 3])
227    [1, 2, 1, 2, 3, 1, 1, 2, 3, 1, 2, 3, 1, 2, 3, 2, 1, 1, 2, 3]
228    >>> unpack_list_from_iterable((1, 2, 3))
229    [1, 2, 1, 2, 3, 1, 1, 2, 3, 1, 2, 3, 1, 2, 3, 2, 1, 1, 2, 3]
230    >>> sorted(unpack_list_from_iterable(set([1, 2, 3])))
231    [1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3]
232
233    >>> unpack_list_from_iterable([1, 2])
234    [1, 2, 1, 2, 1, 1, 2, 1, 2, 1, 2, 2, 1, 1, 2]
235    >>> sorted(unpack_list_from_iterable(set([1, 2])))
236    [1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2]
237    >>> unpack_list_from_iterable(Iter([1, 2]))
238    [1, 2, 1, 2, 1, 2, 1]
239
240    >>> unpack_list_from_iterable([3])
241    [1, 2, 3, 1, 3, 3, 3, 2, 1, 3]
242    >>> unpack_list_from_iterable(set([3]))
243    [1, 2, 3, 1, 3, 3, 3, 2, 1, 3]
244    >>> unpack_list_from_iterable(Iter([3]))
245    [1, 2, 3, 1, 2, 1]
246
247    >>> unpack_list_from_iterable([])
248    [1, 2, 1, 2, 1]
249    >>> unpack_list_from_iterable(set([]))
250    [1, 2, 1, 2, 1]
251    >>> unpack_list_from_iterable([])
252    [1, 2, 1, 2, 1]
253    >>> unpack_list_from_iterable(Iter([1, 2, 3]))
254    [1, 2, 1, 2, 3, 1, 2, 1]
255    """
256    return [1, 2, *it, 1, *[*it, *it], *it, 2, 1, *it]
257
258
259def unpack_list_keep_originals(a, b, c):
260    """
261    >>> a = b = [1, 2]
262    >>> c = [3, 4]
263    >>> unpack_list_keep_originals(a, b, c)
264    [1, 2, 1, 2, 2, 3, 4]
265    >>> a
266    [1, 2]
267    >>> b
268    [1, 2]
269    >>> c
270    [3, 4]
271    """
272    return [*a, *b, 2, *c]
273
274
275###### sets
276
277
278@cython.test_fail_if_path_exists(
279    "//SetNode//SetNode",
280    "//MergedSequenceNode",
281)
282def unpack_set_literal():
283    """
284    >>> s = unpack_set_literal()
285    >>> s == set([1, 2, 4, 5]) or s
286    True
287    """
288    return {*{1, 2, *{4, 5}}}
289
290
291def unpack_set_simple(it):
292    """
293    >>> s = unpack_set_simple([])
294    >>> s == set([]) or s
295    True
296
297    >>> s = unpack_set_simple(set())
298    >>> s == set([]) or s
299    True
300
301    >>> s = unpack_set_simple(Iter())
302    >>> s == set([]) or s
303    True
304
305    >>> s = unpack_set_simple([1])
306    >>> s == set([1]) or s
307    True
308
309    >>> s = unpack_set_simple([2, 1])
310    >>> s == set([1, 2]) or s
311    True
312
313    >>> s = unpack_set_simple((2, 1))
314    >>> s == set([1, 2]) or s
315    True
316
317    >>> s = unpack_set_simple(set([2, 1]))
318    >>> s == set([1, 2]) or s
319    True
320
321    >>> s = unpack_set_simple(Iter([2, 1]))
322    >>> s == set([1, 2]) or s
323    True
324    """
325    return {*it}
326
327
328def unpack_set_from_iterable(it):
329    """
330    >>> s = unpack_set_from_iterable([1, 2, 3])
331    >>> s == set([1, 2, 3]) or s
332    True
333
334    >>> s = unpack_set_from_iterable([1, 2])
335    >>> s == set([1, 2]) or s
336    True
337
338    >>> s = unpack_set_from_iterable(set([1, 2]))
339    >>> s == set([1, 2]) or s
340    True
341
342    >>> s = unpack_set_from_iterable(Iter([1, 2]))
343    >>> s == set([1, 2]) or s
344    True
345
346    >>> s = unpack_set_from_iterable([3])
347    >>> s == set([1, 2, 3]) or s
348    True
349
350    >>> s = unpack_set_from_iterable(set([3]))
351    >>> s == set([1, 2, 3]) or s
352    True
353
354    >>> s = unpack_set_from_iterable(Iter([3]))
355    >>> s == set([1, 2, 3]) or s
356    True
357
358    >>> s = unpack_set_from_iterable([])
359    >>> s == set([1, 2]) or s
360    True
361
362    >>> s = unpack_set_from_iterable(set([]))
363    >>> s == set([1, 2]) or s
364    True
365
366    >>> s = unpack_set_from_iterable([])
367    >>> s == set([1, 2]) or s
368    True
369
370    >>> s = unpack_set_from_iterable((1, 2, 3))
371    >>> s == set([1, 2, 3]) or s
372    True
373
374    >>> s = unpack_set_from_iterable(set([1, 2, 3]))
375    >>> s == set([1, 2, 3]) or s
376    True
377
378    >>> s = unpack_set_from_iterable(Iter([1, 2, 3]))
379    >>> s == set([1, 2, 3]) or s
380    True
381    """
382    return {1, 2, *it, 1, *{*it, *it}, *it, 2, 1, *it, *it}
383
384
385def unpack_set_keep_originals(a, b, c):
386    """
387    >>> a = b = set([1, 2])
388    >>> c = set([3, 4])
389    >>> s = unpack_set_keep_originals(a, b, c)
390    >>> s == set([1, 2, 3, 4]) or s
391    True
392    >>> a == set([1, 2]) or a
393    True
394    >>> b == set([1, 2]) or b
395    True
396    >>> c == set([3, 4]) or c
397    True
398    """
399    return {*a, *b, 2, *c}
400
401
402#### dicts
403
404
405@cython.test_fail_if_path_exists(
406    "//DictNode//DictNode",
407    "//MergedDictNode",
408)
409def unpack_dict_literal():
410    """
411    >>> d = unpack_dict_literal()
412    >>> d == dict(a=1, b=2, c=4, d=5) or d
413    True
414    """
415    return {**{'a': 1, 'b': 2, **{'c': 4, 'd': 5}}}
416
417
418@cython.test_fail_if_path_exists(
419    "//DictNode//DictNode",
420    "//MergedDictNode",
421)
422def unpack_dict_literal_empty():
423    """
424    >>> unpack_dict_literal_empty()
425    {}
426    """
427    return {**{**{}, **{}}, **{}, **{**{**{}}}}
428
429
430def unpack_dict_simple(it):
431    """
432    >>> d = unpack_dict_simple({})
433    >>> d == {} or d
434    True
435
436    >>> d = unpack_dict_simple([])
437    >>> d == {} or d
438    True
439
440    >>> d = unpack_dict_simple(set())
441    >>> d == {} or d
442    True
443
444    >>> d = unpack_dict_simple(Iter())
445    >>> d == {} or d
446    True
447
448    >>> d = unpack_dict_simple(Map())
449    >>> d == {} or d
450    True
451
452    >>> d = unpack_dict_simple(dict(a=1))
453    >>> d == dict(a=1) or d
454    True
455
456    >>> d = unpack_dict_simple(dict(a=1, b=2))
457    >>> d == dict(a=1, b=2) or d
458    True
459
460    >>> d = unpack_dict_simple(Map(dict(a=1, b=2)))
461    >>> d == dict(a=1, b=2) or d
462    True
463    """
464    return {**it}
465
466
467def unpack_dict_from_iterable(it):
468    """
469    >>> d = unpack_dict_from_iterable(dict(a=1, b=2, c=3))
470    >>> d == dict(a=1, b=2, c=3) or d
471    True
472
473    >>> d = unpack_dict_from_iterable(dict(a=1, b=2))
474    >>> d == dict(a=1, b=2) or d
475    True
476
477    >>> d = unpack_dict_from_iterable(Map(dict(a=1, b=2)))
478    >>> d == dict(a=1, b=2) or d
479    True
480
481    >>> d = unpack_dict_from_iterable(dict(a=3))
482    >>> d == dict(a=3, b=5) or d
483    True
484
485    >>> d = unpack_dict_from_iterable(Map(dict(a=3)))
486    >>> d == dict(a=3, b=5) or d
487    True
488
489    >>> d = unpack_dict_from_iterable({})
490    >>> d == dict(a=4, b=5) or d
491    True
492
493    >>> d = unpack_dict_from_iterable(Map())
494    >>> d == dict(a=4, b=5) or d
495    True
496
497    >>> d = unpack_dict_from_iterable(Iter())
498    Traceback (most recent call last):
499    TypeError: 'Iter' object is not a mapping
500
501    >>> d = unpack_dict_from_iterable([])
502    Traceback (most recent call last):
503    TypeError: 'list' object is not a mapping
504
505    >>> d = unpack_dict_from_iterable(dict(b=2, c=3))
506    >>> d == dict(a=4, b=2, c=3) or d
507    True
508
509    >>> d = unpack_dict_from_iterable(Map(dict(b=2, c=3)))
510    >>> d == dict(a=4, b=2, c=3) or d
511    True
512
513    >>> d = unpack_dict_from_iterable(dict(a=2, c=3))
514    >>> d == dict(a=2, b=5, c=3) or d
515    True
516
517    >>> d = unpack_dict_from_iterable(Map(dict(a=2, c=3)))
518    >>> d == dict(a=2, b=5, c=3) or d
519    True
520    """
521    return {'a': 2, 'b': 3, **it, 'a': 1, **{**it, **it}, **it, 'a': 4, 'b': 5, **it, **it}
522
523
524def unpack_dict_keep_originals(a, b, c):
525    """
526    >>> a = b = {1: 2}
527    >>> c = {2: 3, 4: 5}
528    >>> d = unpack_dict_keep_originals(a, b, c)
529    >>> d == {1: 2, 2: 3, 4: 5} or d
530    True
531    >>> a
532    {1: 2}
533    >>> b
534    {1: 2}
535    >>> c == {2: 3, 4: 5} or c
536    True
537    """
538    return {**a, **b, 2: 4, **c}
539