1import doctest 2import unittest 3 4 5doctests = """ 6########### Tests mostly copied from test_listcomps.py ############ 7 8Test simple loop with conditional 9 10 >>> sum({i*i for i in range(100) if i&1 == 1}) 11 166650 12 13Test simple case 14 15 >>> {2*y + x + 1 for x in (0,) for y in (1,)} 16 {3} 17 18Test 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 23Test 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 28Test 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 37Not 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 44Make 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 53Verify 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 66Make 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 73Same 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 79Generators 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 88Make 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 95Return 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 101Same 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 107Another 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 114And 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 121We 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 154def load_tests(loader, tests, pattern): 155 tests.addTest(doctest.DocTestSuite()) 156 return tests 157 158 159if __name__ == "__main__": 160 unittest.main() 161