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