| # 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 <module> |
| 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 <module> |
| 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 <module> |
| 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) |