17db96d56Sopenharmony_ciimport doctest 27db96d56Sopenharmony_ciimport unittest 37db96d56Sopenharmony_ci 47db96d56Sopenharmony_ci 57db96d56Sopenharmony_cidoctests = """ 67db96d56Sopenharmony_ci########### Tests borrowed from or inspired by test_genexps.py ############ 77db96d56Sopenharmony_ci 87db96d56Sopenharmony_ciTest simple loop with conditional 97db96d56Sopenharmony_ci 107db96d56Sopenharmony_ci >>> sum([i*i for i in range(100) if i&1 == 1]) 117db96d56Sopenharmony_ci 166650 127db96d56Sopenharmony_ci 137db96d56Sopenharmony_ciTest simple nesting 147db96d56Sopenharmony_ci 157db96d56Sopenharmony_ci >>> [(i,j) for i in range(3) for j in range(4)] 167db96d56Sopenharmony_ci [(0, 0), (0, 1), (0, 2), (0, 3), (1, 0), (1, 1), (1, 2), (1, 3), (2, 0), (2, 1), (2, 2), (2, 3)] 177db96d56Sopenharmony_ci 187db96d56Sopenharmony_ciTest nesting with the inner expression dependent on the outer 197db96d56Sopenharmony_ci 207db96d56Sopenharmony_ci >>> [(i,j) for i in range(4) for j in range(i)] 217db96d56Sopenharmony_ci [(1, 0), (2, 0), (2, 1), (3, 0), (3, 1), (3, 2)] 227db96d56Sopenharmony_ci 237db96d56Sopenharmony_ciTest the idiom for temporary variable assignment in comprehensions. 247db96d56Sopenharmony_ci 257db96d56Sopenharmony_ci >>> [j*j for i in range(4) for j in [i+1]] 267db96d56Sopenharmony_ci [1, 4, 9, 16] 277db96d56Sopenharmony_ci >>> [j*k for i in range(4) for j in [i+1] for k in [j+1]] 287db96d56Sopenharmony_ci [2, 6, 12, 20] 297db96d56Sopenharmony_ci >>> [j*k for i in range(4) for j, k in [(i+1, i+2)]] 307db96d56Sopenharmony_ci [2, 6, 12, 20] 317db96d56Sopenharmony_ci 327db96d56Sopenharmony_ciNot assignment 337db96d56Sopenharmony_ci 347db96d56Sopenharmony_ci >>> [i*i for i in [*range(4)]] 357db96d56Sopenharmony_ci [0, 1, 4, 9] 367db96d56Sopenharmony_ci >>> [i*i for i in (*range(4),)] 377db96d56Sopenharmony_ci [0, 1, 4, 9] 387db96d56Sopenharmony_ci 397db96d56Sopenharmony_ciMake sure the induction variable is not exposed 407db96d56Sopenharmony_ci 417db96d56Sopenharmony_ci >>> i = 20 427db96d56Sopenharmony_ci >>> sum([i*i for i in range(100)]) 437db96d56Sopenharmony_ci 328350 447db96d56Sopenharmony_ci 457db96d56Sopenharmony_ci >>> i 467db96d56Sopenharmony_ci 20 477db96d56Sopenharmony_ci 487db96d56Sopenharmony_ciVerify that syntax error's are raised for listcomps used as lvalues 497db96d56Sopenharmony_ci 507db96d56Sopenharmony_ci >>> [y for y in (1,2)] = 10 # doctest: +IGNORE_EXCEPTION_DETAIL 517db96d56Sopenharmony_ci Traceback (most recent call last): 527db96d56Sopenharmony_ci ... 537db96d56Sopenharmony_ci SyntaxError: ... 547db96d56Sopenharmony_ci 557db96d56Sopenharmony_ci >>> [y for y in (1,2)] += 10 # doctest: +IGNORE_EXCEPTION_DETAIL 567db96d56Sopenharmony_ci Traceback (most recent call last): 577db96d56Sopenharmony_ci ... 587db96d56Sopenharmony_ci SyntaxError: ... 597db96d56Sopenharmony_ci 607db96d56Sopenharmony_ci 617db96d56Sopenharmony_ci########### Tests borrowed from or inspired by test_generators.py ############ 627db96d56Sopenharmony_ci 637db96d56Sopenharmony_ciMake a nested list comprehension that acts like range() 647db96d56Sopenharmony_ci 657db96d56Sopenharmony_ci >>> def frange(n): 667db96d56Sopenharmony_ci ... return [i for i in range(n)] 677db96d56Sopenharmony_ci >>> frange(10) 687db96d56Sopenharmony_ci [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 697db96d56Sopenharmony_ci 707db96d56Sopenharmony_ciSame again, only as a lambda expression instead of a function definition 717db96d56Sopenharmony_ci 727db96d56Sopenharmony_ci >>> lrange = lambda n: [i for i in range(n)] 737db96d56Sopenharmony_ci >>> lrange(10) 747db96d56Sopenharmony_ci [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 757db96d56Sopenharmony_ci 767db96d56Sopenharmony_ciGenerators can call other generators: 777db96d56Sopenharmony_ci 787db96d56Sopenharmony_ci >>> def grange(n): 797db96d56Sopenharmony_ci ... for x in [i for i in range(n)]: 807db96d56Sopenharmony_ci ... yield x 817db96d56Sopenharmony_ci >>> list(grange(5)) 827db96d56Sopenharmony_ci [0, 1, 2, 3, 4] 837db96d56Sopenharmony_ci 847db96d56Sopenharmony_ci 857db96d56Sopenharmony_ciMake sure that None is a valid return value 867db96d56Sopenharmony_ci 877db96d56Sopenharmony_ci >>> [None for i in range(10)] 887db96d56Sopenharmony_ci [None, None, None, None, None, None, None, None, None, None] 897db96d56Sopenharmony_ci 907db96d56Sopenharmony_ci########### Tests for various scoping corner cases ############ 917db96d56Sopenharmony_ci 927db96d56Sopenharmony_ciReturn lambdas that use the iteration variable as a default argument 937db96d56Sopenharmony_ci 947db96d56Sopenharmony_ci >>> items = [(lambda i=i: i) for i in range(5)] 957db96d56Sopenharmony_ci >>> [x() for x in items] 967db96d56Sopenharmony_ci [0, 1, 2, 3, 4] 977db96d56Sopenharmony_ci 987db96d56Sopenharmony_ciSame again, only this time as a closure variable 997db96d56Sopenharmony_ci 1007db96d56Sopenharmony_ci >>> items = [(lambda: i) for i in range(5)] 1017db96d56Sopenharmony_ci >>> [x() for x in items] 1027db96d56Sopenharmony_ci [4, 4, 4, 4, 4] 1037db96d56Sopenharmony_ci 1047db96d56Sopenharmony_ciAnother way to test that the iteration variable is local to the list comp 1057db96d56Sopenharmony_ci 1067db96d56Sopenharmony_ci >>> items = [(lambda: i) for i in range(5)] 1077db96d56Sopenharmony_ci >>> i = 20 1087db96d56Sopenharmony_ci >>> [x() for x in items] 1097db96d56Sopenharmony_ci [4, 4, 4, 4, 4] 1107db96d56Sopenharmony_ci 1117db96d56Sopenharmony_ciAnd confirm that a closure can jump over the list comp scope 1127db96d56Sopenharmony_ci 1137db96d56Sopenharmony_ci >>> items = [(lambda: y) for i in range(5)] 1147db96d56Sopenharmony_ci >>> y = 2 1157db96d56Sopenharmony_ci >>> [x() for x in items] 1167db96d56Sopenharmony_ci [2, 2, 2, 2, 2] 1177db96d56Sopenharmony_ci 1187db96d56Sopenharmony_ciWe also repeat each of the above scoping tests inside a function 1197db96d56Sopenharmony_ci 1207db96d56Sopenharmony_ci >>> def test_func(): 1217db96d56Sopenharmony_ci ... items = [(lambda i=i: i) for i in range(5)] 1227db96d56Sopenharmony_ci ... return [x() for x in items] 1237db96d56Sopenharmony_ci >>> test_func() 1247db96d56Sopenharmony_ci [0, 1, 2, 3, 4] 1257db96d56Sopenharmony_ci 1267db96d56Sopenharmony_ci >>> def test_func(): 1277db96d56Sopenharmony_ci ... items = [(lambda: i) for i in range(5)] 1287db96d56Sopenharmony_ci ... return [x() for x in items] 1297db96d56Sopenharmony_ci >>> test_func() 1307db96d56Sopenharmony_ci [4, 4, 4, 4, 4] 1317db96d56Sopenharmony_ci 1327db96d56Sopenharmony_ci >>> def test_func(): 1337db96d56Sopenharmony_ci ... items = [(lambda: i) for i in range(5)] 1347db96d56Sopenharmony_ci ... i = 20 1357db96d56Sopenharmony_ci ... return [x() for x in items] 1367db96d56Sopenharmony_ci >>> test_func() 1377db96d56Sopenharmony_ci [4, 4, 4, 4, 4] 1387db96d56Sopenharmony_ci 1397db96d56Sopenharmony_ci >>> def test_func(): 1407db96d56Sopenharmony_ci ... items = [(lambda: y) for i in range(5)] 1417db96d56Sopenharmony_ci ... y = 2 1427db96d56Sopenharmony_ci ... return [x() for x in items] 1437db96d56Sopenharmony_ci >>> test_func() 1447db96d56Sopenharmony_ci [2, 2, 2, 2, 2] 1457db96d56Sopenharmony_ci 1467db96d56Sopenharmony_ci""" 1477db96d56Sopenharmony_ci 1487db96d56Sopenharmony_ci 1497db96d56Sopenharmony_ci__test__ = {'doctests' : doctests} 1507db96d56Sopenharmony_ci 1517db96d56Sopenharmony_cidef load_tests(loader, tests, pattern): 1527db96d56Sopenharmony_ci tests.addTest(doctest.DocTestSuite()) 1537db96d56Sopenharmony_ci return tests 1547db96d56Sopenharmony_ci 1557db96d56Sopenharmony_ci 1567db96d56Sopenharmony_ciif __name__ == "__main__": 1577db96d56Sopenharmony_ci unittest.main() 158