1 import doctest
2 import unittest
3
4
5 doctests = """
6 ########### Tests mostly copied from test_listcomps.py ############
7
8 Test simple loop with conditional
9
10 >>> sum({i*i for i in range(100) if i&1 == 1})
11 166650
12
13 Test simple case
14
15 >>> {2*y + x + 1 for x in (0,) for y in (1,)}
16 {3}
17
18 Test simple nesting
19
20 >>> list(sorted({(i,j) for i in range(3) for j in range(4)}))
21 [(0, 0), (0, 1), (0, 2), (0, 3), (1, 0), (1, 1), (1, 2), (1, 3), (2, 0), (2, 1), (2, 2), (2, 3)]
22
23 Test nesting with the inner expression dependent on the outer
24
25 >>> list(sorted({(i,j) for i in range(4) for j in range(i)}))
26 [(1, 0), (2, 0), (2, 1), (3, 0), (3, 1), (3, 2)]
27
28 Test the idiom for temporary variable assignment in comprehensions.
29
30 >>> sorted({j*j for i in range(4) for j in [i+1]})
31 [1, 4, 9, 16]
32 >>> sorted({j*k for i in range(4) for j in [i+1] for k in [j+1]})
33 [2, 6, 12, 20]
34 >>> sorted({j*k for i in range(4) for j, k in [(i+1, i+2)]})
35 [2, 6, 12, 20]
36
37 Not assignment
38
39 >>> sorted({i*i for i in [*range(4)]})
40 [0, 1, 4, 9]
41 >>> sorted({i*i for i in (*range(4),)})
42 [0, 1, 4, 9]
43
44 Make sure the induction variable is not exposed
45
46 >>> i = 20
47 >>> sum({i*i for i in range(100)})
48 328350
49
50 >>> i
51 20
52
53 Verify that syntax error's are raised for setcomps used as lvalues
54
55 >>> {y for y in (1,2)} = 10 # doctest: +IGNORE_EXCEPTION_DETAIL
56 Traceback (most recent call last):
57 ...
58 SyntaxError: ...
59
60 >>> {y for y in (1,2)} += 10 # doctest: +IGNORE_EXCEPTION_DETAIL
61 Traceback (most recent call last):
62 ...
63 SyntaxError: ...
64
65
66 Make a nested set comprehension that acts like set(range())
67
68 >>> def srange(n):
69 ... return {i for i in range(n)}
70 >>> list(sorted(srange(10)))
71 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
72
73 Same again, only as a lambda expression instead of a function definition
74
75 >>> lrange = lambda n: {i for i in range(n)}
76 >>> list(sorted(lrange(10)))
77 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
78
79 Generators can call other generators:
80
81 >>> def grange(n):
82 ... for x in {i for i in range(n)}:
83 ... yield x
84 >>> list(sorted(grange(5)))
85 [0, 1, 2, 3, 4]
86
87
88 Make sure that None is a valid return value
89
90 >>> {None for i in range(10)}
91 {None}
92
93 ########### Tests for various scoping corner cases ############
94
95 Return lambdas that use the iteration variable as a default argument
96
97 >>> items = {(lambda i=i: i) for i in range(5)}
98 >>> {x() for x in items} == set(range(5))
99 True
100
101 Same again, only this time as a closure variable
102
103 >>> items = {(lambda: i) for i in range(5)}
104 >>> {x() for x in items}
105 {4}
106
107 Another way to test that the iteration variable is local to the list comp
108
109 >>> items = {(lambda: i) for i in range(5)}
110 >>> i = 20
111 >>> {x() for x in items}
112 {4}
113
114 And confirm that a closure can jump over the list comp scope
115
116 >>> items = {(lambda: y) for i in range(5)}
117 >>> y = 2
118 >>> {x() for x in items}
119 {2}
120
121 We also repeat each of the above scoping tests inside a function
122
123 >>> def test_func():
124 ... items = {(lambda i=i: i) for i in range(5)}
125 ... return {x() for x in items}
126 >>> test_func() == set(range(5))
127 True
128
129 >>> def test_func():
130 ... items = {(lambda: i) for i in range(5)}
131 ... return {x() for x in items}
132 >>> test_func()
133 {4}
134
135 >>> def test_func():
136 ... items = {(lambda: i) for i in range(5)}
137 ... i = 20
138 ... return {x() for x in items}
139 >>> test_func()
140 {4}
141
142 >>> def test_func():
143 ... items = {(lambda: y) for i in range(5)}
144 ... y = 2
145 ... return {x() for x in items}
146 >>> test_func()
147 {2}
148
149 """
150
151
152 __test__ = {'doctests' : doctests}
153
154 def load_tests(loader, tests, pattern):
155 tests.addTest(doctest.DocTestSuite())
156 return tests
157
158
159 if __name__ == "__main__":
160 unittest.main()