# Test cases for "range" objects, "for" and "while" loops (compile and run) [case testFor] from typing import List, Tuple def count(n: int) -> None: for i in range(n): print(i) def count_between(n: int, k: int) -> None: for i in range(n, k): print(i) print('n=', n) def count_down(n: int, k: int) -> None: for i in range(n, k, -1): print(i) def count_double(n: int, k: int) -> None: for i in range(n, k, 2): print(i) def list_iter(l: List[int]) -> None: for i in l: print(i) def tuple_iter(l: Tuple[int, ...]) -> None: for i in l: print(i) def str_iter(l: str) -> None: for i in l: print(i) def list_rev_iter(l: List[int]) -> None: for i in reversed(l): print(i) def list_rev_iter_lol(l: List[int]) -> None: for i in reversed(l): print(i) if i == 3: while l: l.pop() def count_down_short() -> None: for i in range(10, 0, -1): print(i) [file driver.py] from native import ( count, list_iter, list_rev_iter, list_rev_iter_lol, count_between, count_down, count_double, count_down_short, tuple_iter, str_iter, ) count(5) list_iter(list(reversed(range(5)))) list_rev_iter(list(reversed(range(5)))) count_between(11, 15) count_between(10**20, 10**20+3) count_down(20, 10) count_double(10, 15) count_down_short() print('==') list_rev_iter_lol(list(reversed(range(5)))) tuple_iter((1, 2, 3)) str_iter("abc") [out] 0 1 2 3 4 4 3 2 1 0 0 1 2 3 4 11 12 13 14 n= 11 100000000000000000000 100000000000000000001 100000000000000000002 n= 100000000000000000000 20 19 18 17 16 15 14 13 12 11 10 12 14 10 9 8 7 6 5 4 3 2 1 == 0 1 2 3 1 2 3 a b c [case testLoopElse] from typing import Iterator def run_for_range(n: int) -> None: for i in range(n): if i == 3: break print(i) else: print(n+1) def run_for_list(n: int) -> None: for i in list(range(n)): if i == 3: break print(i) else: print(n+1) def run_for_iter(n: int) -> None: def identity(x: Iterator[int]) -> Iterator[int]: return x for i in identity(range(n)): if i == 3: break print(i) else: print(n+1) def count(n: int) -> int: i = 1 while i <= n: i = i + 1 if i == 5: break else: i *= -1 return i def nested_while() -> int: while True: while False: pass else: break else: return -1 return 0 def nested_for() -> int: for x in range(1000): for y in [1,2,3]: pass else: break else: return -1 return 0 [file driver.py] from native import run_for_range, run_for_list, run_for_iter, count, nested_while, nested_for assert nested_while() == 0 assert nested_for() == 0 assert count(0) == -1 assert count(1) == -2 assert count(5) == 5 assert count(6) == 5 run_for_range(3) run_for_range(5) print('==') run_for_list(3) run_for_list(5) print('==') run_for_iter(3) run_for_iter(5) [out] 0 1 2 4 0 1 2 == 0 1 2 4 0 1 2 == 0 1 2 4 0 1 2 [case testNestedLoopSameIdx] from typing import List, Generator def nested_enumerate() -> None: l1 = [0,1,2] l2 = [0,1,2] outer_seen = [] outer = 0 for i, j in enumerate(l1): assert i == outer outer_seen.append(i) inner = 0 for i, k in enumerate(l2): assert i == inner inner += 1 outer += 1 assert outer_seen == l1 def nested_range() -> None: outer = 0 outer_seen = [] for i in range(3): assert i == outer outer_seen.append(i) inner = 0 for i in range(3): assert i == inner inner += 1 outer += 1 assert outer_seen == [0,1,2] def nested_list() -> None: l1 = [0,1,2] l2 = [0,1,2] outer_seen = [] outer = 0 for i in l1: assert i == outer outer_seen.append(i) inner = 0 for i in l2: assert i == inner inner += 1 outer += 1 assert outer_seen == l1 def nested_yield() -> Generator: for i in range(3): for i in range(3): yield i yield i [file driver.py] from native import nested_enumerate, nested_range, nested_list, nested_yield nested_enumerate() nested_range() nested_list() gen = nested_yield() for k in range(12): assert next(gen) == k % 4 [out] [case testForIterable] from typing import Iterable, Dict, Any, Tuple def iterate_over_any(a: Any) -> None: for element in a: print(element) def iterate_over_iterable(iterable: Iterable[T]) -> None: for element in iterable: print(element) def iterate_and_delete(d: Dict[int, int]) -> None: for key in d: d.pop(key) def sum_over_values(d: Dict[int, int]) -> int: s = 0 for key in d: s = s + d[key] return s def sum_over_even_values(d: Dict[int, int]) -> int: s = 0 for key in d: if d[key] % 2: continue s = s + d[key] return s def sum_over_two_values(d: Dict[int, int]) -> int: s = 0 i = 0 for key in d: if i == 2: break s = s + d[key] i = i + 1 return s def iterate_over_tuple(iterable: Tuple[int, int, int]) -> None: for element in iterable: print(element) [file driver.py] from native import iterate_over_any, iterate_over_iterable, iterate_and_delete, sum_over_values, sum_over_even_values, sum_over_two_values, iterate_over_tuple import traceback def broken_generator(n): num = 0 while num < n: yield num num += 1 raise Exception('Exception Manually Raised') d = {1:1, 2:2, 3:3, 4:4, 5:5} print(sum_over_values(d)) print(sum_over_even_values(d)) print(sum_over_two_values(d)) try: iterate_over_any(5) except TypeError: traceback.print_exc() try: iterate_over_iterable(broken_generator(5)) except Exception: traceback.print_exc() try: iterate_and_delete(d) except RuntimeError: traceback.print_exc() iterate_over_tuple((1, 2, 3)) [out] Traceback (most recent call last): File "driver.py", line 16, in iterate_over_any(5) File "native.py", line 3, in iterate_over_any for element in a: TypeError: 'int' object is not iterable Traceback (most recent call last): File "driver.py", line 20, in iterate_over_iterable(broken_generator(5)) File "native.py", line 7, in iterate_over_iterable for element in iterable: File "driver.py", line 8, in broken_generator raise Exception('Exception Manually Raised') Exception: Exception Manually Raised Traceback (most recent call last): File "driver.py", line 24, in iterate_and_delete(d) File "native.py", line 11, in iterate_and_delete for key in d: RuntimeError: dictionary changed size during iteration 15 6 3 0 1 2 3 4 1 2 3 [case testContinueFor] def f() -> None: for n in range(5): continue [file driver.py] from native import f f() [case testMultipleVarsWithLoops] # Test comprehensions and for loops with multiple index variables l = [(1, 2, 'a'), (3, 4, 'b'), (5, 6, 'c')] l2 = [str(a*100+b)+' '+c for a, b, c in l] l3 = [] for a, b, c in l: l3.append(str(a*1000+b)+' '+c) [file driver.py] from native import l, l2, l3 for a in l2 + l3: print(a) [out] 102 a 304 b 506 c 1002 a 3004 b 5006 c [case testForZipAndEnumerate] from typing import Iterable, List, Any def f(a: Iterable[int], b: List[int]) -> List[Any]: res = [] for (x, y), z in zip(enumerate(a), b): res.append((x, y, z)) return res def g(a: Iterable[int], b: Iterable[str]) -> List[Any]: res = [] for x, (y, z) in enumerate(zip(a, b)): res.append((x, y, z)) return res [file driver.py] from native import f, g assert f([6, 7], [8, 9]) == [(0, 6, 8), (1, 7, 9)] assert g([6, 7], ['a', 'b']) == [(0, 6, 'a'), (1, 7, 'b')] assert f([6, 7], [8]) == [(0, 6, 8)] assert f([6], [8, 9]) == [(0, 6, 8)] [case testIterTypeTrickiness] # Test inferring the type of a for loop body doesn't cause us grief # Extracted from somethings that broke in mypy from typing import Optional # really I only care that this one build def foo(x: object) -> None: if isinstance(x, dict): for a in x: pass def bar(x: Optional[str]) -> None: vars = ( ("a", 'lol'), ("b", 'asdf'), ("lol", x), ("an int", 10), ) for name, value in vars: pass [file driver.py] from native import bar bar(None) [case testRangeObject] from typing import Any def f(x: range) -> int: sum = 0 for i in x: sum += i return sum def test_range_object() -> None: r1 = range(4, 12, 2) tmp_list = [x for x in r1] assert tmp_list == [4, 6, 8, 10] assert f(r1) == 28 r2: Any = range(10) assert f(r2) == 45 r3: Any = 'x' try: f(r3) except TypeError as e: assert "range object expected; got str" in str(e) try: ff: Any = f ff(r3) except TypeError as e: assert "range object expected; got str" in str(e) try: r4 = range(4, 12, 0) except ValueError as e: assert "range() arg 3 must not be zero" in str(e)