1import doctest 2import unittest 3 4 5doctests = """ 6########### Tests borrowed from or inspired by test_genexps.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 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 18Test 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 23Test 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 32Not 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 39Make 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 48Verify 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 63Make 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 70Same 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 76Generators 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 85Make 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 92Return 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 98Same 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 104Another 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 111And 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 118We 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 151def load_tests(loader, tests, pattern): 152 tests.addTest(doctest.DocTestSuite()) 153 return tests 154 155 156if __name__ == "__main__": 157 unittest.main() 158