| |
| [case testCallTrivialFunction] |
| def f(x: int) -> int: |
| return x |
| [file driver.py] |
| from native import f |
| print(f(3)) |
| print(f(-157)) |
| print(f(10**20)) |
| print(f(-10**20)) |
| [out] |
| 3 |
| -157 |
| 100000000000000000000 |
| -100000000000000000000 |
| |
| [case testInc] |
| def inc(x: int) -> int: |
| return x + 1 |
| [file driver.py] |
| from native import inc |
| print(inc(3)) |
| print(inc(-5)) |
| print(inc(10**20)) |
| [out] |
| 4 |
| -4 |
| 100000000000000000001 |
| |
| [case testCount] |
| def count(n: int) -> int: |
| i = 1 |
| while i <= n: |
| i = i + 1 |
| return i |
| [file driver.py] |
| from native import count |
| print(count(0)) |
| print(count(1)) |
| print(count(5)) |
| [out] |
| 1 |
| 2 |
| 6 |
| |
| [case testFor] |
| from typing import List |
| 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) |
| 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 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 |
| ) |
| 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)))) |
| [out] |
| 0 |
| 1 |
| 2 |
| 3 |
| 4 |
| 4 |
| 3 |
| 2 |
| 1 |
| 0 |
| 0 |
| 1 |
| 2 |
| 3 |
| 4 |
| 11 |
| 12 |
| 13 |
| 14 |
| 100000000000000000000 |
| 100000000000000000001 |
| 100000000000000000002 |
| 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 |
| |
| [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 testAsync] |
| import asyncio |
| |
| async def h() -> int: |
| return 1 |
| |
| async def g() -> int: |
| await asyncio.sleep(0.01) |
| return await h() |
| |
| async def f() -> int: |
| return await g() |
| |
| loop = asyncio.get_event_loop() |
| result = loop.run_until_complete(f()) |
| assert result == 1 |
| |
| [typing fixtures/typing-full.pyi] |
| |
| [file driver.py] |
| from native import f |
| import asyncio |
| loop = asyncio.get_event_loop() |
| result = loop.run_until_complete(f()) |
| assert result == 1 |
| |
| [case testRecursiveFibonacci] |
| def fib(n: int) -> int: |
| if n <= 1: |
| return 1 |
| else: |
| return fib(n - 1) + fib(n - 2) |
| return 0 # TODO: This should be unnecessary |
| [file driver.py] |
| from native import fib |
| print(fib(0)) |
| print(fib(1)) |
| print(fib(2)) |
| print(fib(6)) |
| [out] |
| 1 |
| 1 |
| 2 |
| 13 |
| |
| [case testListPlusEquals] |
| from typing import Any |
| def append(x: Any) -> None: |
| x += [1] |
| |
| [file driver.py] |
| from native import append |
| x = [] |
| append(x) |
| assert x == [1] |
| |
| [case testListSum] |
| from typing import List |
| def sum(a: List[int], l: int) -> int: |
| sum = 0 |
| i = 0 |
| while i < l: |
| sum = sum + a[i] |
| i = i + 1 |
| return sum |
| [file driver.py] |
| from native import sum |
| print(sum([], 0)) |
| print(sum([3], 1)) |
| print(sum([5, 6, -4], 3)) |
| print(sum([2**128 + 5, -2**127 - 8], 2)) |
| [out] |
| 0 |
| 3 |
| 7 |
| 170141183460469231731687303715884105725 |
| |
| [case testListSet] |
| from typing import List |
| def copy(a: List[int], b: List[int], l: int) -> int: |
| i = 0 |
| while i < l: |
| a[i] = b[i] |
| i = i + 1 |
| return 0 |
| [file driver.py] |
| from native import copy |
| a = [0, ''] |
| copy(a, [-1, 5], 2) |
| print(1, a) |
| copy(a, [2**128 + 5, -2**127 - 8], 2) |
| print(2, a) |
| [out] |
| 1 [-1, 5] |
| 2 [340282366920938463463374607431768211461, -170141183460469231731687303715884105736] |
| |
| [case testSieve] |
| from typing import List |
| |
| def primes(n: int) -> List[int]: |
| a = [1] * (n + 1) |
| a[0] = 0 |
| a[1] = 0 |
| i = 0 |
| while i < n: |
| if a[i] == 1: |
| j = i * i |
| while j < n: |
| a[j] = 0 |
| j = j + i |
| i = i + 1 |
| return a |
| [file driver.py] |
| from native import primes |
| print(primes(3)) |
| print(primes(13)) |
| [out] |
| \[0, 0, 1, 1] |
| \[0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1] |
| |
| |
| [case testListPrims] |
| from typing import List |
| def append(x: List[int], n: int) -> None: |
| x.append(n) |
| def pop_last(x: List[int]) -> int: |
| return x.pop() |
| def pop(x: List[int], i: int) -> int: |
| return x.pop(i) |
| def count(x: List[int], i: int) -> int: |
| return x.count(i) |
| [file driver.py] |
| from native import append, pop_last, pop, count |
| l = [1, 2] |
| append(l, 10) |
| assert l == [1, 2, 10] |
| append(l, 3) |
| append(l, 4) |
| append(l, 5) |
| assert l == [1, 2, 10, 3, 4, 5] |
| pop_last(l) |
| pop_last(l) |
| assert l == [1, 2, 10, 3] |
| pop(l, 2) |
| assert l == [1, 2, 3] |
| pop(l, -2) |
| assert l == [1, 3] |
| assert count(l, 1) == 1 |
| assert count(l, 2) == 0 |
| |
| [case testTrue] |
| def f() -> bool: |
| return True |
| [file driver.py] |
| from native import f |
| print(f()) |
| [out] |
| True |
| |
| [case testBoolIf] |
| def f(x: bool) -> bool: |
| if x: |
| return False |
| else: |
| return True |
| [file driver.py] |
| from native import f |
| print(f(True)) |
| print(f(False)) |
| [out] |
| False |
| True |
| |
| [case testTuple] |
| from typing import List, Optional, Tuple |
| from typing import Tuple |
| def f(x: Tuple[int, int]) -> Tuple[int,int]: |
| return x |
| |
| def lurr(x: List[Optional[Tuple[int, str]]]) -> object: |
| return x[0] |
| |
| def asdf(x: Tuple[int, str]) -> None: |
| pass |
| |
| [file driver.py] |
| from testutil import assertRaises |
| from native import f, lurr, asdf |
| |
| assert f((1,2)) == (1, 2) |
| assert lurr([(1, '2')]) == (1, '2') |
| |
| with assertRaises(TypeError): |
| print(lurr([(1, 2)])) |
| |
| with assertRaises(TypeError): |
| asdf((1, 2)) |
| |
| [case testEmptyTupleFunctionWithTupleType] |
| from typing import Tuple |
| def f() -> Tuple[()]: |
| return () |
| [file driver.py] |
| from native import f |
| assert f() == () |
| |
| [case testEmptyTupleFunctionWithAnyType] |
| from typing import Any |
| def f() -> Any: |
| return () |
| [file driver.py] |
| from native import f |
| assert f() == () |
| |
| [case testTupleGet] |
| from typing import Tuple |
| def f(x: Tuple[Tuple[int, bool], int]) -> int: |
| return x[0][0] |
| [file driver.py] |
| from native import f |
| print(f(((1,True),2))) |
| [out] |
| 1 |
| |
| [case testTupleGetBoxedInt] |
| from typing import Tuple |
| def f(x: Tuple[Tuple[int, bool], int]) -> int: |
| return x[0][0] |
| [file driver.py] |
| from native import f |
| big_number = pow(2, 80) |
| print(f(((big_number,True),2))) |
| [out] |
| 1208925819614629174706176 |
| |
| [case testNewTuple] |
| def f() -> int: |
| x = (False, 1) |
| return x[1] |
| [file driver.py] |
| from native import f |
| print(f()) |
| [out] |
| 1 |
| |
| [case testNewTupleBoxedInt] |
| def f(y: int) -> int: |
| x = (False, y) |
| return x[1] |
| [file driver.py] |
| from native import f |
| big_number = pow(2, 80) |
| print(f(big_number)) |
| [out] |
| 1208925819614629174706176 |
| |
| [case testSequenceTuple] |
| from typing import List |
| def f(x: List[int]) -> int: |
| return tuple(x)[1] |
| [file driver.py] |
| from native import f |
| print(f([1,2,3,4])) |
| [out] |
| 2 |
| |
| [case testSequenceTupleLen] |
| from typing import List |
| def f(x: List[int]) -> int: |
| return len(tuple(x)) |
| [file driver.py] |
| from native import f |
| print(f([1,2,3,4])) |
| [out] |
| 4 |
| |
| [case testSequenceTupleArg] |
| from typing import Tuple |
| def f(x: Tuple[int, ...]) -> int: |
| return x[1] |
| [file driver.py] |
| from native import f |
| print(f((1,2,3,4))) |
| [out] |
| 2 |
| |
| [case testMaybeUninitVar] |
| class C: |
| def __init__(self, x: int) -> None: |
| self.x = x |
| |
| def f(b: bool) -> None: |
| u = C(1) |
| while b: |
| v = C(2) |
| if v is not u: |
| break |
| print(v.x) |
| [file driver.py] |
| from native import f |
| f(True) |
| [out] |
| 2 |
| |
| [case testUninitBoom] |
| def f(a: bool, b: bool) -> None: |
| if a: |
| x = 'lol' |
| if b: |
| print(x) |
| |
| def g() -> None: |
| try: |
| [0][1] |
| y = 1 |
| except Exception: |
| pass |
| print(y) |
| |
| [file driver.py] |
| from native import f, g |
| from testutil import assertRaises |
| |
| f(True, True) |
| f(False, False) |
| with assertRaises(NameError): |
| f(False, True) |
| with assertRaises(NameError): |
| g() |
| [out] |
| lol |
| |
| [case testFunctionCallWithDefaultArgs] |
| from typing import Tuple, List, Optional, Callable, Any |
| def f(x: int, y: int = 3, s: str = "test", z: object = 5) -> Tuple[int, str]: |
| def inner() -> int: |
| return x + y |
| return inner(), s |
| def g() -> None: |
| assert f(2) == (5, "test") |
| assert f(s = "123", x = -2) == (1, "123") |
| def h(a: Optional[object] = None, b: Optional[str] = None) -> Tuple[object, Optional[str]]: |
| return (a, b) |
| |
| def same(x: object = object()) -> object: |
| return x |
| |
| a_lambda: Callable[..., Any] = lambda n=20: n |
| |
| def nested_funcs(n: int) -> List[Callable[..., Any]]: |
| ls: List[Callable[..., Any]] = [] |
| for i in range(n): |
| def f(i: int = i) -> int: |
| return i |
| ls.append(f) |
| return ls |
| |
| |
| [file driver.py] |
| from native import f, g, h, same, nested_funcs, a_lambda |
| g() |
| assert f(2) == (5, "test") |
| assert f(s = "123", x = -2) == (1, "123") |
| assert h() == (None, None) |
| assert h(10) == (10, None) |
| assert h(b='a') == (None, 'a') |
| assert h(10, 'a') == (10, 'a') |
| assert same() == same() |
| |
| assert [f() for f in nested_funcs(10)] == list(range(10)) |
| |
| assert a_lambda(10) == 10 |
| assert a_lambda() == 20 |
| |
| [case testMethodCallWithDefaultArgs] |
| from typing import Tuple, List |
| class A: |
| def f(self, x: int, y: int = 3, s: str = "test") -> Tuple[int, str]: |
| def inner() -> int: |
| return x + y |
| return inner(), s |
| def g() -> None: |
| a = A() |
| assert a.f(2) == (5, "test") |
| assert a.f(s = "123", x = -2) == (1, "123") |
| [file driver.py] |
| from native import A, g |
| g() |
| a = A() |
| assert a.f(2) == (5, "test") |
| assert a.f(s = "123", x = -2) == (1, "123") |
| |
| [case testMethodCallOrdering] |
| class A: |
| def __init__(self, s: str) -> None: |
| print(s) |
| def f(self, x: 'A', y: 'A') -> None: |
| pass |
| |
| def g() -> None: |
| A('A!').f(A('hello'), A('world')) |
| [file driver.py] |
| from native import g |
| g() |
| [out] |
| A! |
| hello |
| world |
| |
| [case testImports] |
| import testmodule |
| |
| def f(x: int) -> int: |
| return testmodule.factorial(5) |
| def g(x: int) -> int: |
| from welp import foo |
| return foo(x) |
| [file testmodule.py] |
| def factorial(x: int) -> int: |
| if x == 0: |
| return 1 |
| else: |
| return x * factorial(x-1) |
| [file welp.py] |
| def foo(x: int) -> int: |
| return x |
| [file driver.py] |
| from native import f, g |
| print(f(5)) |
| print(g(5)) |
| [out] |
| 120 |
| 5 |
| |
| [case testBuiltins] |
| y = 10 |
| def f(x: int) -> None: |
| print(5) |
| d = globals() |
| assert d['y'] == 10 |
| d['y'] = 20 |
| assert y == 20 |
| [file driver.py] |
| from native import f |
| f(5) |
| [out] |
| 5 |
| |
| [case testImportMissing] |
| # The unchecked module is configured by the test harness to not be |
| # picked up by mypy, so we can test that we do that right thing when |
| # calling library modules without stubs. |
| import unchecked # type: ignore |
| import unchecked as lol # type: ignore |
| assert unchecked.x == 10 |
| assert lol.x == 10 |
| [file unchecked.py] |
| x = 10 |
| |
| [file driver.py] |
| import native |
| |
| [case testOptional] |
| from typing import Optional |
| |
| class A: pass |
| |
| def f(x: Optional[A]) -> Optional[A]: |
| return x |
| |
| def g(x: Optional[A]) -> int: |
| if x is None: |
| return 1 |
| if x is not None: |
| return 2 |
| return 3 |
| |
| def h(x: Optional[int], y: Optional[bool]) -> None: |
| pass |
| |
| [file driver.py] |
| from native import f, g, A |
| a = A() |
| assert f(None) is None |
| assert f(a) is a |
| assert g(None) == 1 |
| assert g(a) == 2 |
| |
| [case testFromImport] |
| from testmodule import g |
| |
| def f(x: int) -> int: |
| return g(x) |
| [file testmodule.py] |
| def g(x: int) -> int: |
| return x + 1 |
| [file driver.py] |
| from native import f |
| assert f(1) == 2 |
| |
| [case testStr] |
| def f() -> str: |
| return 'some string' |
| def g() -> str: |
| return 'some\a \v \t \x7f " \n \0string 🐍' |
| def tostr(x: int) -> str: |
| return str(x) |
| def concat(x: str, y: str) -> str: |
| return x + y |
| def eq(x: str) -> int: |
| if x == 'foo': |
| return 0 |
| elif x != 'bar': |
| return 1 |
| return 2 |
| |
| [file driver.py] |
| from native import f, g, tostr, concat, eq |
| assert f() == 'some string' |
| assert g() == 'some\a \v \t \x7f " \n \0string 🐍' |
| assert tostr(57) == '57' |
| assert concat('foo', 'bar') == 'foobar' |
| assert eq('foo') == 0 |
| assert eq('zar') == 1 |
| assert eq('bar') == 2 |
| |
| [case testFstring] |
| |
| var = 'mypyc' |
| |
| num = 20 |
| |
| f1 = f'Hello {var}, this is a test' |
| |
| f2 = f'Hello {var!r}' |
| |
| f3 = f'Hello {var!a}' |
| |
| f4 = f'Hello {var!s}' |
| |
| f5 = f'Hello {var:>20}' |
| |
| f6 = f'Hello {var!r:>20}' |
| |
| f7 = f'Hello {var:>{num}}' |
| |
| f8 = f'Hello {var!r:>{num}}' |
| |
| f9 = f'Hello {var}, hello again {var}' |
| |
| [file driver.py] |
| from native import f1, f2, f3, f4, f5, f6, f7, f8, f9 |
| assert f1 == "Hello mypyc, this is a test" |
| assert f2 == "Hello 'mypyc'" |
| assert f3 == "Hello 'mypyc'" |
| assert f4 == "Hello mypyc" |
| assert f5 == "Hello mypyc" |
| assert f6 == "Hello 'mypyc'" |
| assert f7 == "Hello mypyc" |
| assert f8 == "Hello 'mypyc'" |
| assert f9 == "Hello mypyc, hello again mypyc" |
| |
| [out] |
| |
| [case testSets] |
| from typing import Set, List |
| def instantiateLiteral() -> Set[int]: |
| return {1, 2, 3, 5, 8} |
| |
| def fromIterator() -> List[Set[int]]: |
| x = set([1, 3, 5]) |
| y = set((1, 3, 5)) |
| z = set({1: '1', 3: '3', 5: '5'}) |
| return [x, y, z] |
| |
| def addIncrementing(s : Set[int]) -> None: |
| for a in [1, 2, 3]: |
| if a not in s: |
| s.add(a) |
| return |
| |
| def replaceWith1(s : Set[int]) -> None: |
| s.clear() |
| s.add(1) |
| |
| def remove1(s : Set[int]) -> None: |
| s.remove(1) |
| |
| def discard1(s: Set[int]) -> None: |
| s.discard(1) |
| |
| def pop(s : Set[int]) -> int: |
| return s.pop() |
| |
| def update(s: Set[int], x: List[int]) -> None: |
| s.update(x) |
| |
| [file driver.py] |
| from native import instantiateLiteral |
| from testutil import assertRaises |
| |
| val = instantiateLiteral() |
| assert 1 in val |
| assert 2 in val |
| assert 3 in val |
| assert 5 in val |
| assert 8 in val |
| assert len(val) == 5 |
| assert val == {1, 2, 3, 5, 8} |
| s = 0 |
| for i in val: |
| s += i |
| assert s == 19 |
| |
| from native import fromIterator |
| sets = fromIterator() |
| for s in sets: |
| assert s == {1, 3, 5} |
| |
| from native import addIncrementing |
| s = set() |
| addIncrementing(s) |
| assert s == {1} |
| addIncrementing(s) |
| assert s == {1, 2} |
| addIncrementing(s) |
| assert s == {1, 2, 3} |
| |
| from native import replaceWith1 |
| s = {3, 7, 12} |
| replaceWith1(s) |
| assert s == {1} |
| |
| from native import remove1 |
| import traceback |
| s = {1, 4, 6} |
| remove1(s) |
| assert s == {4, 6} |
| with assertRaises(KeyError, '1'): |
| remove1(s) |
| |
| from native import discard1 |
| s = {1, 4, 6} |
| discard1(s) |
| assert s == {4, 6} |
| discard1(s) |
| assert s == {4, 6} |
| |
| from native import pop |
| s = {1, 2, 3} |
| x = pop(s) |
| assert len(s) == 2 |
| assert x in [1, 2, 3] |
| y = pop(s) |
| assert len(s) == 1 |
| assert y in [1, 2, 3] |
| assert x != y |
| z = pop(s) |
| assert len(s) == 0 |
| assert z in [1, 2, 3] |
| assert x != z |
| assert y != z |
| with assertRaises(KeyError, 'pop from an empty set'): |
| pop(s) |
| |
| from native import update |
| s = {1, 2, 3} |
| update(s, [5, 4, 3]) |
| assert s == {1, 2, 3, 4, 5} |
| |
| [case testDictStuff] |
| from typing import Dict, Any |
| from defaultdictwrap import make_dict |
| |
| def f(x: int) -> int: |
| dict1 = {} # type: Dict[int, int] |
| dict1[1] = 1 |
| dict2 = {} # type: Dict[int, int] |
| dict2[x] = 2 |
| dict1.update(dict2) |
| |
| l = [(5, 2)] # type: Any |
| dict1.update(l) |
| d2 = {6: 4} # type: Any |
| dict1.update(d2) |
| |
| return dict1[1] |
| |
| def g() -> int: |
| d = make_dict() |
| d['a'] = 10 |
| d['a'] += 10 |
| d['b'] += 10 |
| l = [('c', 2)] # type: Any |
| d.update(l) |
| d2 = {'d': 4} # type: Any |
| d.update(d2) |
| return d['a'] + d['b'] |
| |
| def h() -> None: |
| d = {} # type: Dict[Any, Any] |
| d[{}] |
| |
| def update_dict(x: Dict[Any, Any], y: Any): |
| x.update(y) |
| |
| def make_dict1(x: Any) -> Dict[Any, Any]: |
| return dict(x) |
| |
| def make_dict2(x: Dict[Any, Any]) -> Dict[Any, Any]: |
| return dict(x) |
| |
| def u(x: int) -> int: |
| d = {} # type: Dict[str, int] |
| d.update(x=x) |
| return d['x'] |
| |
| [file defaultdictwrap.py] |
| from typing import Dict |
| from collections import defaultdict # type: ignore |
| def make_dict() -> Dict[str, int]: |
| return defaultdict(int) |
| |
| [file driver.py] |
| from native import f, g, h, u, make_dict1, make_dict2, update_dict |
| assert f(1) == 2 |
| assert f(2) == 1 |
| assert g() == 30 |
| # Make sure we get a TypeError from indexing with unhashable and not KeyError |
| try: |
| h() |
| except TypeError: |
| pass |
| else: |
| assert False |
| d = {'a': 1, 'b': 2} |
| assert make_dict1(d) == d |
| assert make_dict1(d.items()) == d |
| assert make_dict2(d) == d |
| # object.__dict__ is a "mappingproxy" and not a dict |
| assert make_dict1(object.__dict__) == dict(object.__dict__) |
| d = {} |
| update_dict(d, object.__dict__) |
| assert d == dict(object.__dict__) |
| |
| assert u(10) == 10 |
| |
| [case testPyMethodCall] |
| from typing import List |
| def f(x: List[int]) -> int: |
| return x.pop() |
| def g(x: List[int], y: List[int]) -> None: |
| x.extend(y) |
| [file driver.py] |
| from native import f, g |
| l = [1, 2] |
| assert f(l) == 2 |
| g(l, [10]) |
| assert l == [1, 10] |
| assert f(l) == 10 |
| assert f(l) == 1 |
| g(l, [11, 12]) |
| assert l == [11, 12] |
| |
| [case testMethodCallWithKeywordArgs] |
| from typing import Tuple |
| import testmodule |
| class A: |
| def echo(self, a: int, b: int, c: int) -> Tuple[int, int, int]: |
| return a, b, c |
| def test_native_method_call_with_kwargs() -> None: |
| a = A() |
| assert a.echo(1, c=3, b=2) == (1, 2, 3) |
| assert a.echo(c = 3, a = 1, b = 2) == (1, 2, 3) |
| def test_module_method_call_with_kwargs() -> None: |
| a = testmodule.A() |
| assert a.echo(1, c=3, b=2) == (1, 2, 3) |
| assert a.echo(c = 3, a = 1, b = 2) == (1, 2, 3) |
| [file testmodule.py] |
| from typing import Tuple |
| class A: |
| def echo(self, a: int, b: int, c: int) -> Tuple[int, int, int]: |
| return a, b, c |
| [file driver.py] |
| import native |
| native.test_native_method_call_with_kwargs() |
| native.test_module_method_call_with_kwargs() |
| |
| [case testException] |
| from typing import List |
| def f(x: List[int]) -> None: |
| g(x) |
| |
| def g(x: List[int]) -> bool: |
| x[5] = 2 |
| return True |
| |
| def r1() -> None: |
| q1() |
| |
| def q1() -> None: |
| raise Exception("test") |
| |
| def r2() -> None: |
| q2() |
| |
| def q2() -> None: |
| raise Exception |
| |
| class A: |
| def __init__(self) -> None: |
| raise Exception |
| |
| def hey() -> None: |
| A() |
| |
| [file driver.py] |
| from native import f, r1, r2, hey |
| import traceback |
| try: |
| f([]) |
| except IndexError: |
| traceback.print_exc() |
| try: |
| r1() |
| except Exception: |
| traceback.print_exc() |
| try: |
| r2() |
| except Exception: |
| traceback.print_exc() |
| try: |
| hey() |
| except Exception: |
| traceback.print_exc() |
| [out] |
| Traceback (most recent call last): |
| File "driver.py", line 4, in <module> |
| f([]) |
| File "native.py", line 3, in f |
| g(x) |
| File "native.py", line 6, in g |
| x[5] = 2 |
| IndexError: list assignment index out of range |
| Traceback (most recent call last): |
| File "driver.py", line 8, in <module> |
| r1() |
| File "native.py", line 10, in r1 |
| q1() |
| File "native.py", line 13, in q1 |
| raise Exception("test") |
| Exception: test |
| Traceback (most recent call last): |
| File "driver.py", line 12, in <module> |
| r2() |
| File "native.py", line 16, in r2 |
| q2() |
| File "native.py", line 19, in q2 |
| raise Exception |
| Exception |
| Traceback (most recent call last): |
| File "driver.py", line 16, in <module> |
| hey() |
| File "native.py", line 26, in hey |
| A() |
| File "native.py", line 23, in __init__ |
| raise Exception |
| Exception |
| |
| [case testTryExcept] |
| from typing import Any, Iterator |
| import wrapsys |
| def g(b: bool) -> None: |
| try: |
| if b: |
| x = [0] |
| x[1] |
| else: |
| raise Exception('hi') |
| except: |
| print("caught!") |
| |
| def r(x: int) -> None: |
| if x == 0: |
| [0][1] |
| elif x == 1: |
| raise Exception('hi') |
| elif x == 2: |
| {1: 1}[0] |
| elif x == 3: |
| a = object() # type: Any |
| a.lol |
| |
| def f(b: bool) -> None: |
| try: |
| r(int(b)) |
| except AttributeError: |
| print('no') |
| except: |
| print(str(wrapsys.exc_info()[1])) |
| print(str(wrapsys.exc_info()[1])) |
| |
| def h() -> None: |
| while True: |
| try: |
| raise Exception('gonna break') |
| except: |
| print(str(wrapsys.exc_info()[1])) |
| break |
| print(str(wrapsys.exc_info()[1])) |
| |
| def i() -> None: |
| try: |
| r(0) |
| except: |
| print(type(wrapsys.exc_info()[1])) |
| raise |
| |
| def j(n: int) -> None: |
| try: |
| r(n) |
| except (IndexError, KeyError): |
| print("lookup!") |
| except AttributeError as e: |
| print("attr! --", e) |
| |
| def k() -> None: |
| try: |
| r(1) |
| except: |
| r(0) |
| |
| def l() -> None: |
| try: |
| r(0) |
| except IndexError: |
| try: |
| r(2) |
| except KeyError as e: |
| print("key! --", e) |
| |
| def m(x: object) -> int: |
| try: |
| st = id(x) |
| except Exception: |
| return -1 |
| return st + 1 |
| |
| def iter_exception() -> Iterator[str]: |
| try: |
| r(0) |
| except KeyError as e: |
| yield 'lol' |
| |
| [file wrapsys.py] |
| # This is a gross hack around some limitations of the test system/mypyc. |
| from typing import Any |
| import sys |
| def exc_info() -> Any: |
| return sys.exc_info() # type: ignore |
| |
| [file driver.py] |
| import sys, traceback |
| from native import g, f, h, i, j, k, l, m, iter_exception |
| from testutil import assertRaises |
| print("== i ==") |
| try: |
| i() |
| except: |
| traceback.print_exc(file=sys.stdout) |
| |
| print("== k ==") |
| try: |
| k() |
| except: |
| traceback.print_exc(file=sys.stdout) |
| |
| print("== g ==") |
| g(True) |
| g(False) |
| |
| print("== f ==") |
| f(True) |
| f(False) |
| |
| print("== h ==") |
| h() |
| |
| print("== j ==") |
| j(0) |
| j(2) |
| j(3) |
| try: |
| j(1) |
| except: |
| print("out!") |
| |
| print("== l ==") |
| l() |
| |
| m('lol') |
| |
| with assertRaises(IndexError): |
| list(iter_exception()) |
| |
| [out] |
| == i == |
| <class 'IndexError'> |
| Traceback (most recent call last): |
| File "driver.py", line 6, in <module> |
| i() |
| File "native.py", line 44, in i |
| r(0) |
| File "native.py", line 15, in r |
| [0][1] |
| IndexError: list index out of range |
| == k == |
| Traceback (most recent call last): |
| File "native.py", line 59, in k |
| r(1) |
| File "native.py", line 17, in r |
| raise Exception('hi') |
| Exception: hi |
| |
| During handling of the above exception, another exception occurred: |
| |
| Traceback (most recent call last): |
| File "driver.py", line 12, in <module> |
| k() |
| File "native.py", line 61, in k |
| r(0) |
| File "native.py", line 15, in r |
| [0][1] |
| IndexError: list index out of range |
| == g == |
| caught! |
| caught! |
| == f == |
| hi |
| None |
| list index out of range |
| None |
| == h == |
| gonna break |
| None |
| == j == |
| lookup! |
| lookup! |
| attr! -- 'object' object has no attribute 'lol' |
| out! |
| == l == |
| key! -- 0 |
| |
| [case testTryFinally] |
| from typing import Any |
| import wrapsys |
| |
| def a(b1: bool, b2: int) -> None: |
| try: |
| if b1: |
| raise Exception('hi') |
| finally: |
| print('finally:', str(wrapsys.exc_info()[1])) |
| if b2 == 2: |
| return |
| if b2 == 1: |
| raise Exception('again!') |
| |
| def b(b1: int, b2: int) -> str: |
| try: |
| if b1 == 1: |
| raise Exception('hi') |
| elif b1 == 2: |
| [0][1] |
| elif b1 == 3: |
| return 'try' |
| except IndexError: |
| print('except') |
| finally: |
| print('finally:', str(wrapsys.exc_info()[1])) |
| if b2 == 2: |
| return 'finally' |
| if b2 == 1: |
| raise Exception('again!') |
| return 'outer' |
| |
| def c() -> str: |
| try: |
| try: |
| return 'wee' |
| finally: |
| print("out a") |
| finally: |
| print("out b") |
| |
| |
| [file wrapsys.py] |
| # This is a gross hack around some limitations of the test system/mypyc. |
| from typing import Any |
| import sys |
| def exc_info() -> Any: |
| return sys.exc_info() # type: ignore |
| |
| [file driver.py] |
| import traceback |
| import sys |
| from native import a, b, c |
| |
| def run(f): |
| try: |
| x = f() |
| if x: |
| print("returned:", x) |
| except Exception as e: |
| print("caught:", type(e).__name__ + ": " + str(e)) |
| |
| print("== a ==") |
| for i in range(3): |
| for b1 in [False, True]: |
| run(lambda: a(b1, i)) |
| |
| print("== b ==") |
| for i in range(4): |
| for j in range(3): |
| run(lambda: b(i, j)) |
| |
| print("== b ==") |
| print(c()) |
| |
| [out] |
| == a == |
| finally: None |
| finally: hi |
| caught: Exception: hi |
| finally: None |
| caught: Exception: again! |
| finally: hi |
| caught: Exception: again! |
| finally: None |
| finally: hi |
| == b == |
| finally: None |
| returned: outer |
| finally: None |
| caught: Exception: again! |
| finally: None |
| returned: finally |
| finally: hi |
| caught: Exception: hi |
| finally: hi |
| caught: Exception: again! |
| finally: hi |
| returned: finally |
| except |
| finally: None |
| returned: outer |
| except |
| finally: None |
| caught: Exception: again! |
| except |
| finally: None |
| returned: finally |
| finally: None |
| returned: try |
| finally: None |
| caught: Exception: again! |
| finally: None |
| returned: finally |
| == b == |
| out a |
| out b |
| wee |
| |
| [case testCustomException] |
| from typing import List |
| |
| class ListOutOfBounds(IndexError): |
| pass |
| |
| class UserListWarning(UserWarning): |
| pass |
| |
| def f(l: List[int], k: int) -> int: |
| try: |
| return l[k] |
| except IndexError: |
| raise ListOutOfBounds("Ruh-roh from f!") |
| |
| def g(l: List[int], k: int) -> int: |
| try: |
| return f([1,2,3], 3) |
| except ListOutOfBounds: |
| raise ListOutOfBounds("Ruh-roh from g!") |
| |
| def k(l: List[int], k: int) -> int: |
| try: |
| return g([1,2,3], 3) |
| except IndexError: |
| raise UserListWarning("Ruh-roh from k!") |
| |
| def h() -> int: |
| try: |
| return k([1,2,3], 3) |
| except UserWarning: |
| return -1 |
| |
| [file driver.py] |
| from native import h |
| assert h() == -1 |
| |
| [case testWith] |
| from typing import Any |
| class Thing: |
| def __init__(self, x: str) -> None: |
| self.x = x |
| def __enter__(self) -> str: |
| print('enter!', self.x) |
| if self.x == 'crash': |
| raise Exception('ohno') |
| return self.x |
| def __exit__(self, x: Any, y: Any, z: Any) -> None: |
| print('exit!', self.x, y) |
| |
| def foo(i: int) -> int: |
| with Thing('a') as x: |
| print("yooo?", x) |
| if i == 0: |
| return 10 |
| elif i == 1: |
| raise Exception('exception!') |
| return -1 |
| |
| def bar() -> None: |
| with Thing('a') as x, Thing('b') as y: |
| print("yooo?", x, y) |
| |
| def baz() -> None: |
| with Thing('a') as x, Thing('crash') as y: |
| print("yooo?", x, y) |
| |
| [file driver.py] |
| from native import foo, bar, baz |
| assert foo(0) == 10 |
| print('== foo ==') |
| try: |
| foo(1) |
| except Exception: |
| print('caught') |
| assert foo(2) == -1 |
| |
| print('== bar ==') |
| bar() |
| |
| print('== baz ==') |
| try: |
| baz() |
| except Exception: |
| print('caught') |
| |
| [out] |
| enter! a |
| yooo? a |
| exit! a None |
| == foo == |
| enter! a |
| yooo? a |
| exit! a exception! |
| caught |
| enter! a |
| yooo? a |
| exit! a None |
| == bar == |
| enter! a |
| enter! b |
| yooo? a b |
| exit! b None |
| exit! a None |
| == baz == |
| enter! a |
| enter! crash |
| exit! a ohno |
| caught |
| |
| [case testGenericEquality] |
| def eq(a: object, b: object) -> bool: |
| if a == b: |
| return True |
| else: |
| return False |
| def ne(a: object, b: object) -> bool: |
| if a != b: |
| return True |
| else: |
| return False |
| def f(o: object) -> bool: |
| if [1, 2] == o: |
| return True |
| else: |
| return False |
| [file driver.py] |
| from native import eq, ne, f |
| assert eq('xz', 'x' + 'z') |
| assert not eq('x', 'y') |
| assert not ne('xz', 'x' + 'z') |
| assert ne('x', 'y') |
| assert f([1, 2]) |
| assert not f([2, 2]) |
| assert not f(1) |
| |
| [case testGenericBinaryOps] |
| from typing import Any |
| def add(x: Any, y: Any) -> Any: |
| return x + y |
| def subtract(x: Any, y: Any) -> Any: |
| return x - y |
| def multiply(x: Any, y: Any) -> Any: |
| return x * y |
| def floor_div(x: Any, y: Any) -> Any: |
| return x // y |
| def true_div(x: Any, y: Any) -> Any: |
| return x / y |
| def remainder(x: Any, y: Any) -> Any: |
| return x % y |
| def power(x: Any, y: Any) -> Any: |
| return x ** y |
| def lshift(x: Any, y: Any) -> Any: |
| return x << y |
| def rshift(x: Any, y: Any) -> Any: |
| return x >> y |
| def num_and(x: Any, y: Any) -> Any: |
| return x & y |
| def num_xor(x: Any, y: Any) -> Any: |
| return x ^ y |
| def num_or(x: Any, y: Any) -> Any: |
| return x | y |
| def lt(x: Any, y: Any) -> Any: |
| if x < y: |
| return True |
| else: |
| return False |
| def le(x: Any, y: Any) -> Any: |
| if x <= y: |
| return True |
| else: |
| return False |
| def gt(x: Any, y: Any) -> Any: |
| if x > y: |
| return True |
| else: |
| return False |
| def ge(x: Any, y: Any) -> Any: |
| if x >= y: |
| return True |
| else: |
| return False |
| def contains(x: Any, y: Any) -> Any: |
| if x in y: |
| return True |
| else: |
| return False |
| def identity(x: Any, y: Any) -> Any: |
| if x is y: |
| return True |
| else: |
| return False |
| def disidentity(x: Any, y: Any) -> Any: |
| if x is not y: |
| return True |
| else: |
| return False |
| def not_eq_cond(a: Any, b: Any) -> bool: |
| if not (a == b): |
| return True |
| else: |
| return False |
| def eq2(a: Any, b: Any) -> bool: |
| return a == b |
| def slice1(x: Any) -> Any: |
| return x[:] |
| def slice2(x: Any, y: Any) -> Any: |
| return x[y:] |
| def slice3(x: Any, y: Any) -> Any: |
| return x[:y] |
| def slice4(x: Any, y: Any, z: Any) -> Any: |
| return x[y:z] |
| def slice5(x: Any, y: Any, z: Any, zz: Any) -> Any: |
| return x[y:z:zz] |
| [file driver.py] |
| from native import * |
| assert add(5, 6) == 11 |
| assert add('x', 'y') == 'xy' |
| assert subtract(8, 3) == 5 |
| assert multiply(8, 3) == 24 |
| assert floor_div(8, 3) == 2 |
| assert true_div(7, 2) == 3.5 |
| assert remainder(11, 4) == 3 |
| assert remainder('%.3d', 5) == '005' |
| assert remainder('%d-%s', (5, 'xy')) == '5-xy' |
| assert power(3, 4) == 81 |
| assert lshift(5, 3) == 40 |
| assert rshift(41, 3) == 5 |
| assert num_and(99, 56) == 32 |
| assert num_xor(99, 56) == 91 |
| assert num_or(99, 56) == 123 |
| assert lt('a', 'b') |
| assert not lt('a', 'a') |
| assert not lt('b', 'a') |
| assert not gt('a', 'b') |
| assert not gt('a', 'a') |
| assert gt('b', 'a') |
| assert le('a', 'b') |
| assert le('a', 'a') |
| assert not le('b', 'a') |
| assert not ge('a', 'b') |
| assert ge('a', 'a') |
| assert ge('b', 'a') |
| assert contains('x', 'axb') |
| assert not contains('X', 'axb') |
| assert contains('x', {'x', 'y'}) |
| a = [1, 3, 5] |
| assert slice1(a) == a |
| assert slice1(a) is not a |
| assert slice2(a, 1) == [3, 5] |
| assert slice3(a, -1) == [1, 3] |
| assert slice4(a, 1, -1) == [3] |
| assert slice5(a, 2, 0, -1) == [5, 3] |
| o1, o2 = object(), object() |
| assert identity(o1, o1) |
| assert not identity(o1, o2) |
| assert not disidentity(o1, o1) |
| assert disidentity(o1, o2) |
| assert eq2('xz', 'x' + 'z') |
| assert not eq2('x', 'y') |
| assert not not_eq_cond('xz', 'x' + 'z') |
| assert not_eq_cond('x', 'y') |
| |
| [case testGenericMiscOps] |
| from typing import Any |
| def neg(x: Any) -> Any: |
| return -x |
| def pos(x: Any) -> Any: |
| return +x |
| def invert(x: Any) -> Any: |
| return ~x |
| def get_item(o: Any, k: Any) -> Any: |
| return o[k] |
| def set_item(o: Any, k: Any, v: Any) -> Any: |
| o[k] = v |
| [file driver.py] |
| from native import * |
| assert neg(6) == -6 |
| assert pos(6) == 6 |
| assert invert(6) == -7 |
| d = {'x': 5} |
| assert get_item(d, 'x') == 5 |
| set_item(d, 'y', 6) |
| assert d['y'] == 6 |
| |
| [case testIntMathOps] |
| # This tests integer math things that are either easier to test in Python than |
| # in our C tests or are tested here because (for annoying reasons) we don't run |
| # the C unit tests in our 32-bit CI. |
| def multiply(x: int, y: int) -> int: |
| return x * y |
| |
| # these stringify their outputs because that will catch if exceptions are mishandled |
| def floor_div(x: int, y: int) -> str: |
| return str(x // y) |
| def remainder(x: int, y: int) -> str: |
| return str(x % y) |
| |
| [file driver.py] |
| from native import multiply, floor_div, remainder |
| |
| def test_multiply(x, y): |
| assert multiply(x, y) == x * y |
| def test_floor_div(x, y): |
| assert floor_div(x, y) == str(x // y) |
| def test_remainder(x, y): |
| assert remainder(x, y) == str(x % y) |
| |
| test_multiply(10**6, 10**6) |
| test_multiply(2**15, 2**15-1) |
| test_multiply(2**14, 2**14) |
| |
| test_multiply(10**12, 10**12) |
| test_multiply(2**30, 2**30-1) |
| test_multiply(2**29, 2**29) |
| |
| test_floor_div(-2**62, -1) |
| test_floor_div(-2**30, -1) |
| try: |
| floor_div(10, 0) |
| except ZeroDivisionError: |
| pass |
| else: |
| assert False, "Expected ZeroDivisionError" |
| |
| test_remainder(-2**62, -1) |
| test_remainder(-2**30, -1) |
| try: |
| remainder(10, 0) |
| except ZeroDivisionError: |
| pass |
| else: |
| assert False, "Expected ZeroDivisionError" |
| |
| [case testSubclassAttributeAccess] |
| from mypy_extensions import trait |
| |
| class A: |
| v = 0 |
| |
| class B(A): |
| v = 1 |
| |
| class C(B): |
| v = 2 |
| |
| [file driver.py] |
| from native import A, B, C |
| |
| a = A() |
| b = B() |
| c = C() |
| |
| [case testAnyAttributeAndMethodAccess] |
| from typing import Any, List |
| class C: |
| a: int |
| def m(self, x: int, a: List[int]) -> int: |
| return self.a + x + a[0] |
| def get_a(x: Any) -> Any: |
| return x.a |
| def set_a(x: Any, y: Any) -> None: |
| x.a = y |
| def call_m(x: Any) -> Any: |
| return x.m(1, [3]) |
| [file driver.py] |
| from native import C, get_a, set_a, call_m |
| class D: |
| def m(self, x, a): |
| return self.a + x + a[0] |
| |
| c = C() |
| c.a = 6 |
| d = D() |
| d.a = 2 |
| assert get_a(c) == 6 |
| assert get_a(d) == 2 |
| assert call_m(c) == 10 |
| assert call_m(d) == 6 |
| set_a(c, 5) |
| assert c.a == 5 |
| set_a(d, 4) |
| assert d.a == 4 |
| try: |
| get_a(object()) |
| except AttributeError: |
| pass |
| else: |
| assert False |
| try: |
| call_m(object()) |
| except AttributeError: |
| pass |
| else: |
| assert False |
| try: |
| set_a(object(), 5) |
| except AttributeError: |
| pass |
| else: |
| assert False |
| |
| [case testAnyCall] |
| from typing import Any |
| def call(f: Any) -> Any: |
| return f(1, 'x') |
| [file driver.py] |
| from native import call |
| def f(x, y): |
| return (x, y) |
| def g(x): pass |
| |
| assert call(f) == (1, 'x') |
| for bad in g, 1: |
| try: |
| call(bad) |
| except TypeError: |
| pass |
| else: |
| assert False, bad |
| |
| [case testFloat] |
| def assign_and_return_float_sum() -> float: |
| f1 = 1.0 |
| f2 = 2.0 |
| f3 = 3.0 |
| return f1 * f2 + f3 |
| |
| def from_int(i: int) -> float: |
| return float(i) |
| |
| def to_int(x: float) -> int: |
| return int(x) |
| |
| def get_complex() -> complex: |
| return 5.0j + 3.0 |
| |
| [file driver.py] |
| from native import assign_and_return_float_sum, from_int, to_int, get_complex |
| sum = 0.0 |
| for i in range(10): |
| sum += assign_and_return_float_sum() |
| assert sum == 50.0 |
| |
| assert str(from_int(10)) == '10.0' |
| assert str(to_int(3.14)) == '3' |
| assert str(to_int(3)) == '3' |
| assert get_complex() == 3+5j |
| |
| [case testBytes] |
| def f(x: bytes) -> bytes: |
| return x |
| |
| def concat(a: bytes, b: bytes) -> bytes: |
| return a + b |
| |
| def eq(a: bytes, b: bytes) -> bool: |
| return a == b |
| |
| def neq(a: bytes, b: bytes) -> bool: |
| return a != b |
| |
| def join() -> bytes: |
| seq = (b'1', b'"', b'\xf0') |
| return b'\x07'.join(seq) |
| [file driver.py] |
| from native import f, concat, eq, neq, join |
| assert f(b'123') == b'123' |
| assert f(b'\x07 \x0b " \t \x7f \xf0') == b'\x07 \x0b " \t \x7f \xf0' |
| assert concat(b'123', b'456') == b'123456' |
| assert eq(b'123', b'123') |
| assert not eq(b'123', b'1234') |
| assert neq(b'123', b'1234') |
| assert join() == b'1\x07"\x07\xf0' |
| |
| [case testBigIntLiteral] |
| def big_int() -> None: |
| a_62_bit = 4611686018427387902 |
| max_62_bit = 4611686018427387903 |
| b_63_bit = 4611686018427387904 |
| c_63_bit = 9223372036854775806 |
| max_63_bit = 9223372036854775807 |
| d_64_bit = 9223372036854775808 |
| max_32_bit = 2147483647 |
| max_31_bit = 1073741823 |
| print(a_62_bit) |
| print(max_62_bit) |
| print(b_63_bit) |
| print(c_63_bit) |
| print(max_63_bit) |
| print(d_64_bit) |
| print(max_32_bit) |
| print(max_31_bit) |
| [file driver.py] |
| from native import big_int |
| big_int() |
| [out] |
| 4611686018427387902 |
| 4611686018427387903 |
| 4611686018427387904 |
| 9223372036854775806 |
| 9223372036854775807 |
| 9223372036854775808 |
| 2147483647 |
| 1073741823 |
| |
| [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 testNeg] |
| def neg(x: int) -> int: |
| return -x |
| [file driver.py] |
| from native import neg |
| assert neg(5) == -5 |
| assert neg(-5) == 5 |
| assert neg(1073741823) == -1073741823 |
| assert neg(-1073741823) == 1073741823 |
| assert neg(1073741824) == -1073741824 |
| assert neg(-1073741824) == 1073741824 |
| assert neg(2147483647) == -2147483647 |
| assert neg(-2147483647) == 2147483647 |
| assert neg(2147483648) == -2147483648 |
| assert neg(-2147483648) == 2147483648 |
| assert neg(4611686018427387904) == -4611686018427387904 |
| assert neg(-4611686018427387904) == 4611686018427387904 |
| assert neg(9223372036854775807) == -9223372036854775807 |
| assert neg(-9223372036854775807) == 9223372036854775807 |
| assert neg(9223372036854775808) == -9223372036854775808 |
| assert neg(-9223372036854775808) == 9223372036854775808 |
| |
| [case testContinueFor] |
| def f() -> None: |
| for n in range(5): |
| continue |
| [file driver.py] |
| from native import f |
| f() |
| |
| [case testDisplays] |
| from typing import List, Set, Tuple, Sequence, Dict, Any |
| |
| def listDisplay(x: List[int], y: List[int]) -> List[int]: |
| return [1, 2, *x, *y, 3] |
| |
| def setDisplay(x: Set[int], y: Set[int]) -> Set[int]: |
| return {1, 2, *x, *y, 3} |
| |
| def tupleDisplay(x: Sequence[str], y: Sequence[str]) -> Tuple[str, ...]: |
| return ('1', '2', *x, *y, '3') |
| |
| def dictDisplay(x: str, y1: Dict[str, int], y2: Dict[str, int]) -> Dict[str, int]: |
| return {x: 2, **y1, 'z': 3, **y2} |
| |
| [file driver.py] |
| from native import listDisplay, setDisplay, tupleDisplay, dictDisplay |
| assert listDisplay([4], [5, 6]) == [1, 2, 4, 5, 6, 3] |
| assert setDisplay({4}, {5}) == {1, 2, 3, 4, 5} |
| assert tupleDisplay(['4', '5'], ['6']) == ('1', '2', '4', '5', '6', '3') |
| assert dictDisplay('x', {'y1': 1}, {'y2': 2, 'z': 5}) == {'x': 2, 'y1': 1, 'y2': 2, 'z': 5} |
| |
| [case testCallableTypes] |
| from typing import Callable |
| def absolute_value(x: int) -> int: |
| return x if x > 0 else -x |
| |
| def call_native_function(x: int) -> int: |
| return absolute_value(x) |
| |
| def call_python_function(x: int) -> int: |
| return int(x) |
| |
| def return_float() -> float: |
| return 5.0 |
| |
| def return_callable_type() -> Callable[[], float]: |
| return return_float |
| |
| def call_callable_type() -> float: |
| f = return_callable_type() |
| return f() |
| |
| def return_passed_in_callable_type(f: Callable[[], float]) -> Callable[[], float]: |
| return f |
| |
| def call_passed_in_callable_type(f: Callable[[], float]) -> float: |
| return f() |
| |
| [file driver.py] |
| from native import call_native_function, call_python_function, return_float, return_callable_type, call_callable_type, return_passed_in_callable_type, call_passed_in_callable_type |
| a = call_native_function(1) |
| b = call_python_function(1) |
| c = return_callable_type() |
| d = call_callable_type() |
| e = return_passed_in_callable_type(return_float) |
| f = call_passed_in_callable_type(return_float) |
| assert a == 1 |
| assert b == 1 |
| assert c() == 5.0 |
| assert d == 5.0 |
| assert e() == 5.0 |
| assert f == 5.0 |
| |
| [case testKeywordArgs] |
| from typing import Tuple |
| import testmodule |
| |
| def g(a: int, b: int, c: int) -> Tuple[int, int, int]: |
| return a, b, c |
| |
| def test_call_native_function_with_keyword_args() -> None: |
| assert g(1, c = 3, b = 2) == (1, 2, 3) |
| assert g(c = 3, a = 1, b = 2) == (1, 2, 3) |
| |
| def test_call_module_function_with_keyword_args() -> None: |
| assert testmodule.g(1, c = 3, b = 2) == (1, 2, 3) |
| assert testmodule.g(c = 3, a = 1, b = 2) == (1, 2, 3) |
| |
| def test_call_python_function_with_keyword_args() -> None: |
| assert int("11", base=2) == 3 |
| |
| def test_call_lambda_function_with_keyword_args() -> None: |
| g = testmodule.get_lambda_function() |
| assert g(1, c = 3, b = 2) == (1, 2, 3) |
| assert g(c = 3, a = 1, b = 2) == (1, 2, 3) |
| |
| [file testmodule.py] |
| from typing import Tuple |
| |
| def g(a: int, b: int, c: int) -> Tuple[int, int, int]: |
| return a, b, c |
| |
| def get_lambda_function(): |
| return (lambda a, b, c: (a, b, c)) |
| |
| [file driver.py] |
| import native |
| native.test_call_native_function_with_keyword_args() |
| native.test_call_module_function_with_keyword_args() |
| native.test_call_python_function_with_keyword_args() |
| native.test_call_lambda_function_with_keyword_args() |
| |
| [case testStarArgs] |
| from typing import Tuple |
| |
| def g(a: int, b: int, c: int) -> Tuple[int, int, int]: |
| return a, b, c |
| |
| def test_star_args() -> None: |
| assert g(*[1, 2, 3]) == (1, 2, 3) |
| assert g(*(1, 2, 3)) == (1, 2, 3) |
| assert g(*(1,), *[2, 3]) == (1, 2, 3) |
| assert g(*(), *(1,), *(), *(2,), *(3,), *()) == (1, 2, 3) |
| assert g(*range(3)) == (0, 1, 2) |
| |
| [file driver.py] |
| import native |
| native.test_star_args() |
| |
| [case testStar2Args] |
| from typing import Tuple |
| |
| def g(a: int, b: int, c: int) -> Tuple[int, int, int]: |
| return a, b, c |
| |
| def test_star2_args() -> None: |
| assert g(**{'a': 1, 'b': 2, 'c': 3}) == (1, 2, 3) |
| assert g(**{'c': 3, 'a': 1, 'b': 2}) == (1, 2, 3) |
| assert g(b=2, **{'a': 1, 'c': 3}) == (1, 2, 3) |
| |
| def test_star2_args_bad(v: dict) -> bool: |
| return g(a=1, b=2, **v) == (1, 2, 3) |
| [file driver.py] |
| import native |
| native.test_star2_args() |
| |
| # this should raise TypeError due to duplicate kwarg, but currently it doesn't |
| assert native.test_star2_args_bad({'b': 2, 'c': 3}) |
| |
| [case testStarAndStar2Args] |
| from typing import Tuple |
| def g(a: int, b: int, c: int) -> Tuple[int, int, int]: |
| return a, b, c |
| |
| class C: |
| def g(self, a: int, b: int, c: int) -> Tuple[int, int, int]: |
| return a, b, c |
| |
| def test_star_and_star2_args() -> None: |
| assert g(1, *(2,), **{'c': 3}) == (1, 2, 3) |
| assert g(*[1], **{'b': 2, 'c': 3}) == (1, 2, 3) |
| c = C() |
| assert c.g(1, *(2,), **{'c': 3}) == (1, 2, 3) |
| assert c.g(*[1], **{'b': 2, 'c': 3}) == (1, 2, 3) |
| |
| [file driver.py] |
| import native |
| native.test_star_and_star2_args() |
| |
| [case testAllTheArgCombinations] |
| from typing import Tuple |
| def g(a: int, b: int, c: int, d: int = -1) -> Tuple[int, int, int, int]: |
| return a, b, c, d |
| |
| class C: |
| def g(self, a: int, b: int, c: int, d: int = -1) -> Tuple[int, int, int, int]: |
| return a, b, c, d |
| |
| def test_all_the_arg_combinations() -> None: |
| assert g(1, *(2,), **{'c': 3}) == (1, 2, 3, -1) |
| assert g(*[1], **{'b': 2, 'c': 3, 'd': 4}) == (1, 2, 3, 4) |
| c = C() |
| assert c.g(1, *(2,), **{'c': 3}) == (1, 2, 3, -1) |
| assert c.g(*[1], **{'b': 2, 'c': 3, 'd': 4}) == (1, 2, 3, 4) |
| |
| [file driver.py] |
| import native |
| native.test_all_the_arg_combinations() |
| |
| [case testArbitraryLvalues] |
| from typing import List, Dict, Any |
| |
| class O(object): |
| def __init__(self) -> None: |
| self.x = 1 |
| |
| def increment_attr(a: Any) -> Any: |
| a.x += 1 |
| return a |
| |
| def increment_attr_o(o: O) -> O: |
| o.x += 1 |
| return o |
| |
| def increment_all_indices(l: List[int]) -> List[int]: |
| for i in range(len(l)): |
| l[i] += 1 |
| return l |
| |
| def increment_all_keys(d: Dict[str, int]) -> Dict[str, int]: |
| for k in d: |
| d[k] += 1 |
| return d |
| |
| [file driver.py] |
| from native import O, increment_attr, increment_attr_o, increment_all_indices, increment_all_keys |
| |
| class P(object): |
| def __init__(self) -> None: |
| self.x = 0 |
| |
| assert increment_attr(P()).x == 1 |
| assert increment_attr_o(O()).x == 2 |
| assert increment_all_indices([1, 2, 3]) == [2, 3, 4] |
| assert increment_all_keys({'a':1, 'b':2, 'c':3}) == {'a':2, 'b':3, 'c':4} |
| |
| [case testNestedFunctions] |
| from typing import Callable |
| |
| def outer() -> Callable[[], object]: |
| def inner() -> object: |
| return None |
| return inner |
| |
| def first() -> Callable[[], Callable[[], str]]: |
| def second() -> Callable[[], str]: |
| def third() -> str: |
| return 'third: nested function' |
| return third |
| return second |
| |
| def f1() -> int: |
| x = 1 |
| def f2() -> int: |
| y = 2 |
| def f3() -> int: |
| z = 3 |
| return y |
| return f3() |
| return f2() |
| |
| def outer_func() -> int: |
| def inner_func() -> int: |
| return x |
| x = 1 |
| return inner_func() |
| |
| def mutual_recursion(start : int) -> int: |
| def f1(k : int) -> int: |
| if k <= 0: |
| return 0 |
| k -= 1 |
| return f2(k) |
| |
| def f2(k : int) -> int: |
| if k <= 0: |
| return 0 |
| k -= 1 |
| return f1(k) |
| return f1(start) |
| |
| def topLayer() -> int: |
| def middleLayer() -> int: |
| def bottomLayer() -> int: |
| return x |
| |
| return bottomLayer() |
| |
| x = 1 |
| return middleLayer() |
| |
| def nest1() -> str: |
| def nest2() -> str: |
| def nest3() -> str: |
| def mut1(val: int) -> str: |
| if val <= 0: |
| return "bottomed" |
| val -= 1 |
| return mut2(val) |
| def mut2(val: int) -> str: |
| if val <= 0: |
| return "bottomed" |
| val -= 1 |
| return mut1(val) |
| return mut1(start) |
| return nest3() |
| start = 3 |
| return nest2() |
| |
| def uno(num: float) -> Callable[[str], str]: |
| def dos(s: str) -> str: |
| return s + '!' |
| return dos |
| |
| def eins(num: float) -> str: |
| def zwei(s: str) -> str: |
| return s + '?' |
| a = zwei('eins') |
| b = zwei('zwei') |
| return a |
| |
| def call_other_inner_func(a: int) -> int: |
| def foo() -> int: |
| return a + 1 |
| |
| def bar() -> int: |
| return foo() |
| |
| def baz(n: int) -> int: |
| if n == 0: |
| return 0 |
| return n + baz(n - 1) |
| |
| return bar() + baz(a) |
| |
| def inner() -> str: |
| return 'inner: normal function' |
| |
| def second() -> str: |
| return 'second: normal function' |
| |
| def third() -> str: |
| return 'third: normal function' |
| |
| [file driver.py] |
| from native import (outer, inner, first, uno, eins, call_other_inner_func, |
| second, third, f1, outer_func, mutual_recursion, topLayer, nest1) |
| |
| assert outer()() == None |
| assert inner() == 'inner: normal function' |
| assert first()()() == 'third: nested function' |
| assert uno(5.0)('uno') == 'uno!' |
| assert eins(4.0) == 'eins?' |
| assert call_other_inner_func(5) == 21 |
| assert second() == 'second: normal function' |
| assert third() == 'third: normal function' |
| assert f1() == 2 |
| assert outer_func() == 1 |
| assert mutual_recursion(5) == 0 |
| assert topLayer() == 1 |
| assert nest1() == "bottomed" |
| |
| [case testOverloads] |
| from typing import overload, Union, Tuple |
| |
| @overload |
| def foo(x: int) -> int: ... |
| |
| @overload |
| def foo(x: str) -> str: ... |
| |
| def foo(x: Union[int, str]) -> Union[int, str]: |
| return x |
| |
| class A: |
| @overload |
| def foo(self, x: int) -> int: ... |
| |
| @overload |
| def foo(self, x: str) -> str: ... |
| |
| def foo(self, x: Union[int, str]) -> Union[int, str]: |
| return x |
| |
| def call1() -> Tuple[int, str]: |
| return (foo(10), foo('10')) |
| def call2() -> Tuple[int, str]: |
| x = A() |
| return (x.foo(10), x.foo('10')) |
| |
| [file driver.py] |
| from native import * |
| assert call1() == (10, '10') |
| assert call2() == (10, '10') |
| |
| [case testControlFlowExprs] |
| from typing import Tuple |
| def foo() -> object: |
| print('foo') |
| return 'foo' |
| def bar() -> object: |
| print('bar') |
| return 'bar' |
| def t(x: int) -> int: |
| print(x) |
| return x |
| |
| def f(b: bool) -> Tuple[object, object, object]: |
| x = foo() if b else bar() |
| y = b or foo() |
| z = b and foo() |
| return (x, y, z) |
| def g() -> Tuple[object, object]: |
| return (foo() or bar(), foo() and bar()) |
| |
| def nand(p: bool, q: bool) -> bool: |
| if not (p and q): |
| return True |
| return False |
| |
| def chained(x: int, y: int, z: int) -> bool: |
| return t(x) < t(y) > t(z) |
| |
| def chained2(x: int, y: int, z: int, w: int) -> bool: |
| return t(x) < t(y) < t(z) < t(w) |
| [file driver.py] |
| from native import f, g, nand, chained, chained2 |
| assert f(True) == ('foo', True, 'foo') |
| print() |
| assert f(False) == ('bar', 'foo', False) |
| print() |
| assert g() == ('foo', 'bar') |
| |
| assert nand(True, True) == False |
| assert nand(True, False) == True |
| assert nand(False, True) == True |
| assert nand(False, False) == True |
| |
| print() |
| assert chained(10, 20, 15) == True |
| print() |
| assert chained(10, 20, 30) == False |
| print() |
| assert chained(21, 20, 30) == False |
| print() |
| assert chained2(1, 2, 3, 4) == True |
| print() |
| assert chained2(1, 0, 3, 4) == False |
| print() |
| assert chained2(1, 2, 0, 4) == False |
| [out] |
| foo |
| foo |
| |
| bar |
| foo |
| |
| foo |
| foo |
| bar |
| |
| 10 |
| 20 |
| 15 |
| |
| 10 |
| 20 |
| 30 |
| |
| 21 |
| 20 |
| |
| 1 |
| 2 |
| 3 |
| 4 |
| |
| 1 |
| 0 |
| |
| 1 |
| 2 |
| 0 |
| |
| [case testMultipleAssignment] |
| from typing import Tuple, List, Any |
| |
| def from_tuple(t: Tuple[int, str]) -> List[Any]: |
| x, y = t |
| return [y, x] |
| |
| def from_list(l: List[int]) -> List[int]: |
| x, y = l |
| return [y, x] |
| |
| def from_any(o: Any) -> List[Any]: |
| x, y = o |
| return [y, x] |
| [file driver.py] |
| from native import from_tuple, from_list, from_any |
| |
| assert from_tuple((1, 'x')) == ['x', 1] |
| assert from_list([3, 4]) == [4, 3] |
| assert from_any('xy') == ['y', 'x'] |
| |
| [case testUnboxTuple] |
| from typing import List, Tuple |
| |
| def f(x: List[Tuple[int, int]]) -> int: |
| a, b = x[0] |
| return a + b |
| [file driver.py] |
| from native import f |
| assert f([(5, 6)]) == 11 |
| |
| [case testUnpack] |
| from typing import List |
| |
| a, *b = [1, 2, 3, 4, 5] |
| |
| *c, d = [1, 2, 3, 4, 5] |
| |
| e, *f = [1,2] |
| |
| j, *k, l = [1, 2, 3] |
| |
| m, *n, o = [1, 2, 3, 4, 5, 6] |
| |
| p, q, r, *s, t = [1,2,3,4,5,6,7,8,9,10] |
| |
| tup = (1,2,3) |
| y, *z = tup |
| |
| def unpack1(l : List[int]) -> None: |
| *v1, v2, v3 = l |
| |
| def unpack2(l : List[int]) -> None: |
| v1, *v2, v3 = l |
| |
| def unpack3(l : List[int]) -> None: |
| v1, v2, *v3 = l |
| |
| [file driver.py] |
| from native import a, b, c, d, e, f, j, k, l, m, n, o, p, q, r, s, t, y, z |
| from native import unpack1, unpack2, unpack3 |
| from testutil import assertRaises |
| |
| assert a == 1 |
| assert b == [2,3,4,5] |
| assert c == [1,2,3,4] |
| assert d == 5 |
| assert e == 1 |
| assert f == [2] |
| assert j == 1 |
| assert k == [2] |
| assert l == 3 |
| assert m == 1 |
| assert n == [2,3,4,5] |
| assert o == 6 |
| assert p == 1 |
| assert q == 2 |
| assert r == 3 |
| assert s == [4,5,6,7,8,9] |
| assert t == 10 |
| assert y == 1 |
| assert z == [2,3] |
| |
| with assertRaises(ValueError, "not enough values to unpack"): |
| unpack1([1]) |
| |
| with assertRaises(ValueError, "not enough values to unpack"): |
| unpack2([1]) |
| |
| with assertRaises(ValueError, "not enough values to unpack"): |
| unpack3([1]) |
| |
| [out] |
| |
| [case testModuleTopLevel] |
| x = 1 |
| print(x) |
| |
| def f() -> None: |
| print(x + 1) |
| |
| def g() -> None: |
| global x |
| x = 77 |
| |
| [file driver.py] |
| import native |
| native.f() |
| native.x = 5 |
| native.f() |
| native.g() |
| print(native.x) |
| |
| [out] |
| 1 |
| 2 |
| 6 |
| 77 |
| |
| [case testExceptionAtModuleTopLevel] |
| from typing import Any |
| |
| def f(x: int) -> None: pass |
| |
| y: Any = '' |
| f(y) |
| |
| [file driver.py] |
| import traceback |
| try: |
| import native |
| except TypeError: |
| traceback.print_exc() |
| else: |
| assert False |
| |
| [out] |
| Traceback (most recent call last): |
| File "driver.py", line 3, in <module> |
| import native |
| File "native.py", line 6, in <module> |
| f(y) |
| TypeError: int object expected; got str |
| |
| [case testComprehensions] |
| # A list comprehension |
| l = [str(x) + " " + str(y) + " " + str(x*y) for x in range(10) |
| if x != 6 if x != 5 for y in range(x) if y*x != 8] |
| |
| # Test short-circuiting as well |
| def pred(x: int) -> bool: |
| if x > 6: |
| raise Exception() |
| return x > 3 |
| # If we fail to short-circuit, pred(x) will be called with x=7 |
| # eventually and will raise an exception. |
| l2 = [x for x in range(10) if x <= 6 if pred(x)] |
| |
| # A dictionary comprehension |
| d = {k: k*k for k in range(10) if k != 5 if k != 6} |
| |
| # A set comprehension |
| s = {str(x) + " " + str(y) + " " + str(x*y) for x in range(10) |
| if x != 6 if x != 5 for y in range(x) if y*x != 8} |
| |
| [file driver.py] |
| from native import l, l2, d, s |
| for a in l: |
| print(a) |
| print(tuple(l2)) |
| for k in sorted(d): |
| print(k, d[k]) |
| for a in sorted(s): |
| print(a) |
| [out] |
| 1 0 0 |
| 2 0 0 |
| 2 1 2 |
| 3 0 0 |
| 3 1 3 |
| 3 2 6 |
| 4 0 0 |
| 4 1 4 |
| 4 3 12 |
| 7 0 0 |
| 7 1 7 |
| 7 2 14 |
| 7 3 21 |
| 7 4 28 |
| 7 5 35 |
| 7 6 42 |
| 8 0 0 |
| 8 2 16 |
| 8 3 24 |
| 8 4 32 |
| 8 5 40 |
| 8 6 48 |
| 8 7 56 |
| 9 0 0 |
| 9 1 9 |
| 9 2 18 |
| 9 3 27 |
| 9 4 36 |
| 9 5 45 |
| 9 6 54 |
| 9 7 63 |
| 9 8 72 |
| (4, 5, 6) |
| 0 0 |
| 1 1 |
| 2 4 |
| 3 9 |
| 4 16 |
| 7 49 |
| 8 64 |
| 9 81 |
| 1 0 0 |
| 2 0 0 |
| 2 1 2 |
| 3 0 0 |
| 3 1 3 |
| 3 2 6 |
| 4 0 0 |
| 4 1 4 |
| 4 3 12 |
| 7 0 0 |
| 7 1 7 |
| 7 2 14 |
| 7 3 21 |
| 7 4 28 |
| 7 5 35 |
| 7 6 42 |
| 8 0 0 |
| 8 2 16 |
| 8 3 24 |
| 8 4 32 |
| 8 5 40 |
| 8 6 48 |
| 8 7 56 |
| 9 0 0 |
| 9 1 9 |
| 9 2 18 |
| 9 3 27 |
| 9 4 36 |
| 9 5 45 |
| 9 6 54 |
| 9 7 63 |
| 9 8 72 |
| |
| [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 testDel] |
| from typing import List |
| from testutil import assertRaises |
| |
| def printDict(dict) -> None: |
| l = list(dict.keys()) # type: List[str] |
| l.sort() |
| for key in l: |
| print(key, dict[key]) |
| print("#########") |
| |
| def delList() -> None: |
| l = [1, 2, 3] |
| print(tuple(l)) |
| del l[1] |
| print(tuple(l)) |
| |
| def delDict() -> None: |
| d = {"one":1, "two":2} |
| printDict(d) |
| del d["one"] |
| printDict(d) |
| |
| def delListMultiple() -> None: |
| l = [1, 2, 3, 4, 5, 6, 7] |
| print(tuple(l)) |
| del l[1], l[2], l[3] |
| print(tuple(l)) |
| |
| def delDictMultiple() -> None: |
| d = {"one":1, "two":2, "three":3, "four":4} |
| printDict(d) |
| del d["two"], d["four"] |
| printDict(d) |
| |
| class Dummy(): |
| def __init__(self, x: int, y: int) -> None: |
| self.x = x |
| self.y = y |
| |
| def delAttribute() -> None: |
| dummy = Dummy(1, 2) |
| del dummy.x |
| with assertRaises(AttributeError): |
| dummy.x |
| |
| def delAttributeMultiple() -> None: |
| dummy = Dummy(1, 2) |
| del dummy.x, dummy.y |
| with assertRaises(AttributeError): |
| dummy.x |
| with assertRaises(AttributeError): |
| dummy.y |
| |
| def delLocal(b: bool) -> int: |
| dummy = 10 |
| if b: |
| del dummy |
| return dummy |
| |
| def delLocalLoop() -> None: |
| # Try deleting a local in a loop to make sure the control flow analysis works |
| dummy = 1 |
| for i in range(10): |
| print(dummy) |
| dummy *= 2 |
| if i == 4: |
| del dummy |
| |
| global_var = 10 |
| del global_var |
| |
| [file driver.py] |
| from native import ( |
| delList, delDict, delListMultiple, delDictMultiple, delAttribute, |
| delAttributeMultiple, delLocal, delLocalLoop, |
| ) |
| import native |
| from testutil import assertRaises |
| |
| delList() |
| delDict() |
| delListMultiple() |
| delDictMultiple() |
| delAttribute() |
| delAttributeMultiple() |
| with assertRaises(AttributeError): |
| native.global_var |
| with assertRaises(NameError, "local variable 'dummy' referenced before assignment"): |
| delLocal(True) |
| assert delLocal(False) == 10 |
| with assertRaises(NameError, "local variable 'dummy' referenced before assignment"): |
| delLocalLoop() |
| [out] |
| (1, 2, 3) |
| (1, 3) |
| one 1 |
| two 2 |
| ######### |
| two 2 |
| ######### |
| (1, 2, 3, 4, 5, 6, 7) |
| (1, 3, 5, 7) |
| four 4 |
| one 1 |
| three 3 |
| two 2 |
| ######### |
| one 1 |
| three 3 |
| ######### |
| 1 |
| 2 |
| 4 |
| 8 |
| 16 |
| |
| [case testProperty] |
| from typing import Callable |
| from mypy_extensions import trait |
| class Temperature: |
| @property |
| def celsius(self) -> float: |
| return 5.0 * (self.farenheit - 32.0) / 9.0 |
| |
| def __init__(self, farenheit: float) -> None: |
| self.farenheit = farenheit |
| |
| def print_temp(self) -> None: |
| print("F:", self.farenheit, "C:", self.celsius) |
| |
| @property |
| def rankine(self) -> float: |
| raise NotImplementedError |
| |
| class Access: |
| @property |
| def number_of_accesses(self) -> int: |
| self._count += 1 |
| return self._count |
| def __init__(self) -> None: |
| self._count = 0 |
| |
| from typing import Callable |
| class BaseProperty: |
| @property |
| def doc(self) -> str: |
| return "Represents a sequence of values. Updates itself by next, which is a new value." |
| |
| @property |
| def value(self) -> object: |
| return self._incrementer |
| |
| @property |
| def bad_value(self) -> object: |
| return self._incrementer |
| |
| @property |
| def next(self) -> BaseProperty: |
| return BaseProperty(self._incrementer + 1) |
| |
| def __init__(self, value: int) -> None: |
| self._incrementer = value |
| |
| class DerivedProperty(BaseProperty): |
| @property |
| def value(self) -> int: |
| return self._incrementer |
| |
| @property |
| def bad_value(self) -> object: |
| return self._incrementer |
| |
| def __init__(self, incr_func: Callable[[int], int], value: int) -> None: |
| BaseProperty.__init__(self, value) |
| self._incr_func = incr_func |
| |
| @property |
| def next(self) -> DerivedProperty: |
| return DerivedProperty(self._incr_func, self._incr_func(self.value)) |
| |
| class AgainProperty(DerivedProperty): |
| @property |
| def next(self) -> AgainProperty: |
| return AgainProperty(self._incr_func, self._incr_func(self._incr_func(self.value))) |
| |
| @property |
| def bad_value(self) -> int: |
| return self._incrementer |
| |
| def print_first_n(n: int, thing: BaseProperty) -> None: |
| vals = [] |
| cur_thing = thing |
| for _ in range(n): |
| vals.append(cur_thing.value) |
| cur_thing = cur_thing.next |
| print ('', vals) |
| |
| @trait |
| class Trait: |
| @property |
| def value(self) -> int: |
| return 3 |
| |
| class Printer(Trait): |
| def print_value(self) -> None: |
| print(self.value) |
| |
| [file driver.py] |
| from native import Temperature, Access |
| import traceback |
| x = Temperature(32.0) |
| try: |
| print (x.rankine) |
| except NotImplementedError as e: |
| traceback.print_exc() |
| print (x.celsius) |
| x.print_temp() |
| |
| y = Temperature(212.0) |
| print (y.celsius) |
| y.print_temp() |
| |
| z = Access() |
| print (z.number_of_accesses) |
| print (z.number_of_accesses) |
| print (z.number_of_accesses) |
| print (z.number_of_accesses) |
| |
| from native import BaseProperty, DerivedProperty, AgainProperty, print_first_n |
| a = BaseProperty(7) |
| b = DerivedProperty((lambda x: x // 2 if (x % 2 == 0) else 3 * x + 1), 7) |
| c = AgainProperty((lambda x: x // 2 if (x % 2 == 0) else 3 * x + 1), 7) |
| |
| def py_print_first_n(n: int, thing: BaseProperty) -> None: |
| vals = [] |
| cur_thing = thing |
| for _ in range(n): |
| vals.append(cur_thing.value) |
| cur_thing = cur_thing.next |
| print ('', vals) |
| |
| py_print_first_n(20, a) |
| py_print_first_n(20, b) |
| py_print_first_n(20, c) |
| |
| print(a.next.next.next.bad_value) |
| print(b.next.next.next.bad_value) |
| print(c.next.next.next.bad_value) |
| |
| print_first_n(20, a) |
| print_first_n(20, b) |
| print_first_n(20, c) |
| |
| print (a.doc) |
| print (b.doc) |
| print (c.doc) |
| |
| from native import Printer |
| Printer().print_value() |
| print (Printer().value) |
| [out] |
| Traceback (most recent call last): |
| File "driver.py", line 5, in <module> |
| print (x.rankine) |
| File "native.py", line 16, in rankine |
| raise NotImplementedError |
| NotImplementedError |
| 0.0 |
| F: 32.0 C: 0.0 |
| 100.0 |
| F: 212.0 C: 100.0 |
| 1 |
| 2 |
| 3 |
| 4 |
| [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26] |
| [7, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1, 4, 2, 1] |
| [7, 11, 17, 26, 40, 10, 16, 4, 1, 2, 4, 1, 2, 4, 1, 2, 4, 1, 2, 4] |
| 10 |
| 34 |
| 26 |
| [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26] |
| [7, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1, 4, 2, 1] |
| [7, 11, 17, 26, 40, 10, 16, 4, 1, 2, 4, 1, 2, 4, 1, 2, 4, 1, 2, 4] |
| Represents a sequence of values. Updates itself by next, which is a new value. |
| Represents a sequence of values. Updates itself by next, which is a new value. |
| Represents a sequence of values. Updates itself by next, which is a new value. |
| 3 |
| 3 |
| |
| [case testPropertySetters] |
| |
| from mypy_extensions import trait |
| |
| class Foo(): |
| def __init__(self) -> None: |
| self.attr = "unmodified" |
| |
| class A: |
| def __init__(self) -> None: |
| self._x = 0 |
| self._foo = Foo() |
| |
| @property |
| def x(self) -> int: |
| return self._x |
| |
| @x.setter |
| def x(self, val : int) -> None: |
| self._x = val |
| |
| @property |
| def foo(self) -> Foo: |
| return self._foo |
| |
| @foo.setter |
| def foo(self, val : Foo) -> None: |
| self._foo = val |
| |
| # Overrides base property setters and getters |
| class B(A): |
| def __init__(self) -> None: |
| self._x = 10 |
| |
| @property |
| def x(self) -> int: |
| return self._x + 1 |
| |
| @x.setter |
| def x(self, val : int) -> None: |
| self._x = val + 1 |
| |
| #Inerits base property setters and getters |
| class C(A): |
| def __init__(self) -> None: |
| A.__init__(self) |
| |
| @trait |
| class D(): |
| def __init__(self) -> None: |
| self._x = 0 |
| |
| @property |
| def x(self) -> int: |
| return self._x |
| |
| @x.setter |
| def x(self, val : int) -> None: |
| self._x = val |
| |
| #Inherits trait property setters and getters |
| class E(D): |
| def __init__(self) -> None: |
| D.__init__(self) |
| |
| #Overrides trait property setters and getters |
| class F(D): |
| def __init__(self) -> None: |
| self._x = 10 |
| |
| @property |
| def x(self) -> int: |
| return self._x + 10 |
| |
| @x.setter |
| def x(self, val : int) -> None: |
| self._x = val + 10 |
| |
| # # Property setter and getter are subtypes of base property setters and getters |
| # # class G(A): |
| # # def __init__(self) -> None: |
| # # A.__init__(self) |
| |
| # # @property |
| # # def y(self) -> int: |
| # # return self._y |
| |
| # # @y.setter |
| # # def y(self, val : object) -> None: |
| # # self._y = val |
| |
| [file other.py] |
| # Run in both interpreted and compiled mode |
| |
| from native import A, B, C, D, E, F |
| |
| a = A() |
| assert a.x == 0 |
| assert a._x == 0 |
| a.x = 1 |
| assert a.x == 1 |
| assert a._x == 1 |
| a._x = 0 |
| assert a.x == 0 |
| assert a._x == 0 |
| b = B() |
| assert b.x == 11 |
| assert b._x == 10 |
| b.x = 11 |
| assert b.x == 13 |
| b._x = 11 |
| assert b.x == 12 |
| c = C() |
| assert c.x == 0 |
| c.x = 1000 |
| assert c.x == 1000 |
| e = E() |
| assert e.x == 0 |
| e.x = 1000 |
| assert e.x == 1000 |
| f = F() |
| assert f.x == 20 |
| f.x = 30 |
| assert f.x == 50 |
| |
| [file driver.py] |
| # Run the tests in both interpreted and compiled mode |
| import other |
| import other_interpreted |
| |
| [out] |
| |
| [case testDunders] |
| from typing import Any |
| class Item: |
| def __init__(self, value: str) -> None: |
| self.value = value |
| |
| def __hash__(self) -> int: |
| return hash(self.value) |
| |
| def __eq__(self, rhs: object) -> bool: |
| return isinstance(rhs, Item) and self.value == rhs.value |
| |
| def __lt__(self, x: 'Item') -> bool: |
| return self.value < x.value |
| |
| class Subclass1(Item): |
| def __bool__(self) -> bool: |
| return bool(self.value) |
| |
| class NonBoxedThing: |
| def __getitem__(self, index: Item) -> Item: |
| return Item("2 * " + index.value + " + 1") |
| |
| class BoxedThing: |
| def __getitem__(self, index: int) -> int: |
| return 2 * index + 1 |
| |
| class Subclass2(BoxedThing): |
| pass |
| |
| def index_into(x : Any, y : Any) -> Any: |
| return x[y] |
| |
| def internal_index_into() -> None: |
| x = BoxedThing() |
| print (x[3]) |
| y = NonBoxedThing() |
| z = Item("3") |
| print(y[z].value) |
| |
| def is_truthy(x: Item) -> bool: |
| return True if x else False |
| |
| [file driver.py] |
| from native import * |
| x = BoxedThing() |
| y = 3 |
| print(x[y], index_into(x, y)) |
| |
| x = Subclass2() |
| y = 3 |
| print(x[y], index_into(x, y)) |
| |
| z = NonBoxedThing() |
| w = Item("3") |
| print(z[w].value, index_into(z, w).value) |
| |
| i1 = Item('lolol') |
| i2 = Item('lol' + 'ol') |
| i3 = Item('xyzzy') |
| assert hash(i1) == hash(i2) |
| |
| assert i1 == i2 |
| assert not i1 != i2 |
| assert not i1 == i3 |
| assert i1 != i3 |
| assert i2 < i3 |
| assert not i1 < i2 |
| assert i1 == Subclass1('lolol') |
| |
| assert is_truthy(Item('')) |
| assert is_truthy(Item('a')) |
| assert not is_truthy(Subclass1('')) |
| assert is_truthy(Subclass1('a')) |
| |
| internal_index_into() |
| [out] |
| 7 7 |
| 7 7 |
| 2 * 3 + 1 2 * 3 + 1 |
| 7 |
| 2 * 3 + 1 |
| |
| [case testDummyTypes] |
| from typing import Tuple, List, Dict, NamedTuple |
| from typing_extensions import Literal, TypedDict, NewType |
| |
| class A: |
| pass |
| |
| T = List[A] |
| U = List[Tuple[int, str]] |
| Z = List[List[int]] |
| D = Dict[int, List[int]] |
| N = NewType('N', int) |
| G = Tuple[int, str] |
| def foo(x: N) -> int: |
| return x |
| foo(N(10)) |
| z = N(10) |
| Lol = NamedTuple('Lol', (('a', int), ('b', T))) |
| x = Lol(1, []) |
| def take_lol(x: Lol) -> int: |
| return x.a |
| |
| TD = TypedDict('TD', {'a': int}) |
| def take_typed_dict(x: TD) -> int: |
| return x['a'] |
| |
| def take_literal(x: Literal[1, 2, 3]) -> None: |
| print(x) |
| |
| [file driver.py] |
| import sys |
| from native import * |
| |
| if sys.version_info[:3] > (3, 5, 2): |
| assert "%s %s %s %s" % (T, U, Z, D) == "typing.List[native.A] typing.List[typing.Tuple[int, str]] typing.List[typing.List[int]] typing.Dict[int, typing.List[int]]" |
| print(x) |
| print(z) |
| print(take_lol(x)) |
| print(take_typed_dict({'a': 20})) |
| try: |
| take_typed_dict(None) |
| except Exception as e: |
| print(type(e).__name__) |
| |
| |
| take_literal(1) |
| # We check that the type is the real underlying type |
| try: |
| take_literal(None) |
| except Exception as e: |
| print(type(e).__name__) |
| # ... but not that it is a valid literal value |
| take_literal(10) |
| [out] |
| Lol(a=1, b=[]) |
| 10 |
| 1 |
| 20 |
| TypeError |
| 1 |
| TypeError |
| 10 |
| |
| [case testTupleAttr] |
| from typing import Tuple |
| class C: |
| b: Tuple[Tuple[Tuple[int, int], int], int, str, object] |
| c: Tuple[()] |
| def f() -> None: |
| c = C() |
| c.b = (((1, 2), 2), 1, 'hi', 'hi2') |
| print(c.b) |
| |
| def g() -> None: |
| try: |
| h() |
| except Exception: |
| print('caught the exception') |
| |
| def h() -> Tuple[Tuple[Tuple[int, int], int], int, str, object]: |
| raise Exception('Intentional exception') |
| [file driver.py] |
| from native import f, g, C |
| f() |
| g() |
| assert not hasattr(C(), 'c') |
| [out] |
| (((1, 2), 2), 1, 'hi', 'hi2') |
| caught the exception |
| |
| [case testUnion] |
| from typing import Union |
| |
| class A: |
| def __init__(self, x: int) -> None: |
| self.x = x |
| def f(self, y: int) -> int: |
| return y + self.x |
| |
| class B: |
| def __init__(self, x: object) -> None: |
| self.x = x |
| def f(self, y: object) -> object: |
| return y |
| |
| def f(x: Union[A, str]) -> object: |
| if isinstance(x, A): |
| return x.x |
| else: |
| return x + 'x' |
| |
| def g(x: int) -> Union[A, int]: |
| if x == 0: |
| return A(1) |
| else: |
| return x + 1 |
| |
| def get(x: Union[A, B]) -> object: |
| return x.x |
| |
| def call(x: Union[A, B]) -> object: |
| return x.f(5) |
| |
| [file driver.py] |
| from native import A, B, f, g, get, call |
| assert f('a') == 'ax' |
| assert f(A(4)) == 4 |
| assert isinstance(g(0), A) |
| assert g(2) == 3 |
| assert get(A(5)) == 5 |
| assert get(B('x')) == 'x' |
| assert call(A(4)) == 9 |
| assert call(B('x')) == 5 |
| try: |
| f(1) |
| except TypeError: |
| pass |
| else: |
| assert False |
| |
| [case testYield] |
| from typing import Generator, Iterable, Union, Tuple |
| |
| def yield_three_times() -> Iterable[int]: |
| yield 1 |
| yield 2 |
| yield 3 |
| |
| def yield_twice_and_return() -> Generator[int, None, int]: |
| yield 1 |
| yield 2 |
| return 4 |
| |
| def yield_while_loop() -> Generator[int, None, int]: |
| i = 0 |
| while i < 5: |
| if i == 3: |
| return i |
| yield i |
| i += 1 |
| return -1 |
| |
| def yield_for_loop() -> Iterable[int]: |
| l = [i for i in range(3)] |
| for i in l: |
| yield i |
| |
| d = {k: None for k in range(3)} |
| for k in d: |
| yield k |
| |
| for i in range(3): |
| yield i |
| |
| for i in range(three()): |
| yield i |
| |
| def yield_with_except() -> Generator[int, None, None]: |
| yield 10 |
| try: |
| return |
| except: |
| print('Caught exception inside generator function') |
| |
| def complex_yield(a: int, b: str, c: float) -> Generator[Union[str, int], None, float]: |
| x = 2 |
| while x < a: |
| if x % 2 == 0: |
| dummy_var = 1 |
| yield str(x) + ' ' + b |
| dummy_var = 1 |
| else: |
| dummy_var = 1 |
| yield x |
| dummy_var = 1 |
| x += 1 |
| return c |
| |
| def yield_with_default(x: bool = False) -> Iterable[int]: |
| if x: |
| yield 0 |
| |
| def three() -> int: |
| return 3 |
| |
| class A(object): |
| def __init__(self, x: int) -> None: |
| self.x = x |
| |
| def generator(self) -> Iterable[int]: |
| yield self.x |
| |
| def return_tuple() -> Generator[int, None, Tuple[int, int]]: |
| yield 0 |
| return 1, 2 |
| |
| [file driver.py] |
| from native import yield_three_times, yield_twice_and_return, yield_while_loop, yield_for_loop, yield_with_except, complex_yield, yield_with_default, A, return_tuple |
| from testutil import run_generator |
| |
| assert run_generator(yield_three_times()) == ((1, 2, 3), None) |
| assert run_generator(yield_twice_and_return()) == ((1, 2), 4) |
| assert run_generator(yield_while_loop()) == ((0, 1, 2), 3) |
| assert run_generator(yield_for_loop()) == (tuple(4 * [i for i in range(3)]), None) |
| assert run_generator(yield_with_except()) == ((10,), None) |
| assert run_generator(complex_yield(5, 'foo', 1.0)) == (('2 foo', 3, '4 foo'), 1.0) |
| assert run_generator(yield_with_default()) == ((), None) |
| assert run_generator(A(0).generator()) == ((0,), None) |
| assert run_generator(return_tuple()) == ((0,), (1, 2)) |
| |
| for i in yield_twice_and_return(): |
| print(i) |
| |
| for i in yield_while_loop(): |
| print(i) |
| |
| [out] |
| 1 |
| 2 |
| 0 |
| 1 |
| 2 |
| |
| [case testYieldTryFinallyWith] |
| from typing import Generator, Any |
| |
| class Thing: |
| def __init__(self, x: str) -> None: |
| self.x = x |
| def __enter__(self) -> str: |
| print('enter!', self.x) |
| if self.x == 'crash': |
| raise Exception('ohno') |
| return self.x |
| def __exit__(self, x: Any, y: Any, z: Any) -> None: |
| print('exit!', self.x, y) |
| |
| def yield_try_finally() -> Generator[int, None, str]: |
| try: |
| yield 1 |
| yield 2 |
| return 'lol' |
| except Exception: |
| raise |
| finally: |
| print('goodbye!') |
| |
| def yield_with(i: int) -> Generator[int, None, int]: |
| with Thing('a') as x: |
| yield 1 |
| print("yooo?", x) |
| if i == 0: |
| yield 2 |
| return 10 |
| elif i == 1: |
| raise Exception('exception!') |
| return -1 |
| |
| [file driver.py] |
| from native import yield_try_finally, yield_with |
| from testutil import run_generator |
| |
| print(run_generator(yield_try_finally(), p=True)) |
| print(run_generator(yield_with(0), p=True)) |
| print(run_generator(yield_with(1), p=True)) |
| [out] |
| 1 |
| 2 |
| goodbye! |
| ((1, 2), 'lol') |
| enter! a |
| 1 |
| yooo? a |
| 2 |
| exit! a None |
| ((1, 2), 10) |
| enter! a |
| 1 |
| yooo? a |
| exit! a exception! |
| ((1,), 'exception!') |
| |
| [case testYieldNested] |
| from typing import Callable, Generator |
| |
| def normal(a: int, b: float) -> Callable: |
| def generator(x: int, y: str) -> Generator: |
| yield a |
| yield b |
| yield x |
| yield y |
| return generator |
| |
| def generator(a: int) -> Generator: |
| def normal(x: int) -> int: |
| return a + x |
| for i in range(3): |
| yield normal(i) |
| |
| def triple() -> Callable: |
| def generator() -> Generator: |
| x = 0 |
| def inner() -> int: |
| x += 1 |
| return x |
| while x < 3: |
| yield inner() |
| return generator |
| |
| def another_triple() -> Callable: |
| def generator() -> Generator: |
| x = 0 |
| def inner_generator() -> Generator: |
| x += 1 |
| yield x |
| yield next(inner_generator()) |
| return generator |
| |
| def outer() -> Generator: |
| def recursive(n: int) -> Generator: |
| if n < 10: |
| for i in range(n): |
| yield i |
| return |
| for i in recursive(5): |
| yield i |
| return recursive(10) |
| |
| [file driver.py] |
| from native import normal, generator, triple, another_triple, outer |
| from testutil import run_generator |
| |
| assert run_generator(normal(1, 2.0)(3, '4.00')) == ((1, 2.0, 3, '4.00'), None) |
| assert run_generator(generator(1)) == ((1, 2, 3), None) |
| assert run_generator(triple()()) == ((1, 2, 3), None) |
| assert run_generator(another_triple()()) == ((1,), None) |
| assert run_generator(outer()) == ((0, 1, 2, 3, 4), None) |
| |
| [case testYieldThrow] |
| from typing import Generator, Iterable, Any |
| from traceback import print_tb |
| from contextlib import contextmanager |
| import wrapsys |
| |
| def generator() -> Iterable[int]: |
| try: |
| yield 1 |
| yield 2 |
| yield 3 |
| except Exception as e: |
| print_tb(wrapsys.exc_info()[2]) |
| s = str(e) |
| if s: |
| print('caught exception with value ' + s) |
| else: |
| print('caught exception without value') |
| return 0 |
| |
| def no_except() -> Iterable[int]: |
| yield 1 |
| yield 2 |
| |
| def raise_something() -> Iterable[int]: |
| yield 1 |
| yield 2 |
| raise Exception('failure') |
| |
| def wrapper(x: Any) -> Any: |
| return (yield from x) |
| |
| def foo() -> Generator[int, None, None]: |
| try: |
| yield 1 |
| except Exception as e: |
| print(str(e)) |
| finally: |
| print('goodbye') |
| |
| ctx_manager = contextmanager(foo) |
| |
| [file wrapsys.py] |
| # This is a gross hack around some limitations of the test system/mypyc. |
| from typing import Any |
| import sys |
| def exc_info() -> Any: |
| return sys.exc_info() # type: ignore |
| |
| [file driver.py] |
| import sys |
| from typing import Generator, Tuple, TypeVar, Sequence |
| from native import generator, ctx_manager, wrapper, no_except, raise_something |
| |
| T = TypeVar('T') |
| U = TypeVar('U') |
| |
| def run_generator_and_throw(gen: Generator[T, None, U], |
| num_times: int, |
| value: object = None, |
| traceback: object = None) -> Tuple[Sequence[T], U]: |
| res = [] |
| try: |
| for i in range(num_times): |
| res.append(next(gen)) |
| if value is not None and traceback is not None: |
| gen.throw(Exception, value, traceback) |
| elif value is not None: |
| gen.throw(Exception, value) |
| else: |
| gen.throw(Exception) |
| except StopIteration as e: |
| return (tuple(res), e.value) |
| except Exception as e: |
| return (tuple(res), str(e)) |
| |
| assert run_generator_and_throw(generator(), 0, 'hello') == ((), 'hello') |
| assert run_generator_and_throw(generator(), 3) == ((1, 2, 3), 0) |
| assert run_generator_and_throw(generator(), 2, 'some string') == ((1, 2), 0) |
| try: |
| raise Exception |
| except Exception as e: |
| tb = sys.exc_info()[2] |
| assert run_generator_and_throw(generator(), 1, 'some other string', tb) == ((1,), 0) |
| |
| assert run_generator_and_throw(wrapper(generator()), 0, 'hello') == ((), 'hello') |
| assert run_generator_and_throw(wrapper(generator()), 3) == ((1, 2, 3), 0) |
| assert run_generator_and_throw(wrapper(generator()), 2, 'some string') == ((1, 2), 0) |
| # Make sure we aren't leaking exc_info |
| assert sys.exc_info()[0] is None |
| |
| assert run_generator_and_throw(wrapper([1, 2, 3]), 3, 'lol') == ((1, 2, 3), 'lol') |
| assert run_generator_and_throw(wrapper(no_except()), 2, 'lol') == ((1, 2), 'lol') |
| |
| assert run_generator_and_throw(wrapper(raise_something()), 3) == ((1, 2), 'failure') |
| |
| with ctx_manager() as c: |
| raise Exception('exception') |
| |
| [out] |
| File "native.py", line 10, in generator |
| yield 3 |
| File "native.py", line 9, in generator |
| yield 2 |
| File "native.py", line 8, in generator |
| yield 1 |
| File "driver.py", line 31, in <module> |
| raise Exception |
| File "native.py", line 10, in generator |
| yield 3 |
| File "native.py", line 30, in wrapper |
| return (yield from x) |
| File "native.py", line 9, in generator |
| yield 2 |
| File "native.py", line 30, in wrapper |
| return (yield from x) |
| caught exception without value |
| caught exception with value some string |
| caught exception with value some other string |
| caught exception without value |
| caught exception with value some string |
| exception |
| goodbye |
| |
| [case testYieldSend] |
| from typing import Generator |
| |
| def basic() -> Generator[int, int, int]: |
| x = yield 1 |
| y = yield (x + 1) |
| return y |
| |
| def use_from() -> Generator[int, int, int]: |
| return (yield from basic()) |
| |
| [file driver.py] |
| from native import basic, use_from |
| from testutil import run_generator |
| |
| assert run_generator(basic(), [5, 50]) == ((1, 6), 50) |
| assert run_generator(use_from(), [5, 50]) == ((1, 6), 50) |
| |
| [case testYieldFrom] |
| from typing import Generator, Iterator, List |
| |
| def basic() -> Iterator[int]: |
| yield from [1, 2, 3] |
| |
| def call_next() -> int: |
| x = [] # type: List[int] |
| return next(iter(x)) |
| |
| def inner(b: bool) -> Generator[int, None, int]: |
| if b: |
| yield from [1, 2, 3] |
| return 10 |
| |
| def with_return(b: bool) -> Generator[int, None, int]: |
| x = yield from inner(b) |
| for a in [1, 2]: |
| pass |
| return x |
| |
| [file driver.py] |
| from native import basic, call_next, with_return |
| from testutil import run_generator, assertRaises |
| |
| assert run_generator(basic()) == ((1, 2, 3), None) |
| |
| with assertRaises(StopIteration): |
| call_next() |
| |
| assert run_generator(with_return(True)) == ((1, 2, 3), 10) |
| assert run_generator(with_return(False)) == ((), 10) |
| |
| [case testDecorators1] |
| from typing import Generator, Callable, Iterator |
| from contextlib import contextmanager |
| |
| def a(f: Callable[[], None]) -> Callable[[], None]: |
| def g() -> None: |
| print('Entering') |
| f() |
| print('Exited') |
| return g |
| |
| def b(f: Callable[[], None]) -> Callable[[], None]: |
| def g() -> None: |
| print('***') |
| f() |
| print('***') |
| return g |
| |
| @contextmanager |
| def foo() -> Iterator[int]: |
| try: |
| print('started') |
| yield 0 |
| finally: |
| print('finished') |
| |
| @contextmanager |
| def catch() -> Iterator[None]: |
| try: |
| print('started') |
| yield |
| except IndexError: |
| print('index') |
| raise |
| except Exception: |
| print('lol') |
| |
| def thing() -> None: |
| c() |
| |
| @a |
| @b |
| def c() -> None: |
| @a |
| @b |
| def d() -> None: |
| print('d') |
| print('c') |
| d() |
| |
| def hm() -> None: |
| x = [1] |
| with catch(): |
| x[2] |
| |
| [file driver.py] |
| from native import foo, c, thing, hm |
| |
| with foo() as f: |
| print('hello') |
| |
| c() |
| thing() |
| print('==') |
| try: |
| hm() |
| except IndexError: |
| pass |
| else: |
| assert False |
| |
| [out] |
| started |
| hello |
| finished |
| Entering |
| *** |
| c |
| Entering |
| *** |
| d |
| *** |
| Exited |
| *** |
| Exited |
| Entering |
| *** |
| c |
| Entering |
| *** |
| d |
| *** |
| Exited |
| *** |
| Exited |
| == |
| started |
| index |
| |
| [case testDecoratorsMethods] |
| from typing import Any, Callable, Iterator |
| from contextlib import contextmanager |
| |
| def a(f: Callable[[Any], None]) -> Callable[[Any], None]: |
| def g(a: Any) -> None: |
| print('Entering') |
| f(a) |
| print('Exited') |
| return g |
| |
| class A: |
| @a |
| def foo(self) -> None: |
| print('foo') |
| |
| @contextmanager |
| def generator(self) -> Iterator[int]: |
| try: |
| print('contextmanager: entering') |
| yield 0 |
| finally: |
| print('contextmanager: exited') |
| |
| def inside() -> None: |
| with A().generator() as g: |
| print('hello!') |
| |
| with A().generator() as g: |
| print('hello!') |
| |
| def lol() -> None: |
| with A().generator() as g: |
| raise Exception |
| |
| [file driver.py] |
| from native import A, lol |
| |
| A.foo(A()) |
| A().foo() |
| with A().generator() as g: |
| print('hello!') |
| try: |
| lol() |
| except: |
| pass |
| else: |
| assert False |
| |
| [out] |
| contextmanager: entering |
| hello! |
| contextmanager: exited |
| Entering |
| foo |
| Exited |
| Entering |
| foo |
| Exited |
| contextmanager: entering |
| hello! |
| contextmanager: exited |
| contextmanager: entering |
| contextmanager: exited |
| |
| [case testAnyAll] |
| from typing import Iterable |
| |
| def call_any_nested(l: Iterable[Iterable[int]], val: int = 0) -> int: |
| res = any(i == val for l2 in l for i in l2) |
| return 0 if res else 1 |
| |
| def call_any(l: Iterable[int], val: int = 0) -> int: |
| res = any(i == val for i in l) |
| return 0 if res else 1 |
| |
| def call_all(l: Iterable[int], val: int = 0) -> int: |
| res = all(i == val for i in l) |
| return 0 if res else 1 |
| |
| [file driver.py] |
| from native import call_any, call_all, call_any_nested |
| |
| zeros = [0, 0, 0] |
| ones = [1, 1, 1] |
| mixed_001 = [0, 0, 1] |
| mixed_010 = [0, 1, 0] |
| mixed_100 = [1, 0, 0] |
| mixed_011 = [0, 1, 1] |
| mixed_101 = [1, 0, 1] |
| mixed_110 = [1, 1, 0] |
| |
| assert call_any([]) == 1 |
| assert call_any(zeros) == 0 |
| assert call_any(ones) == 1 |
| assert call_any(mixed_001) == 0 |
| assert call_any(mixed_010) == 0 |
| assert call_any(mixed_100) == 0 |
| assert call_any(mixed_011) == 0 |
| assert call_any(mixed_101) == 0 |
| assert call_any(mixed_110) == 0 |
| |
| assert call_all([]) == 0 |
| assert call_all(zeros) == 0 |
| assert call_all(ones) == 1 |
| assert call_all(mixed_001) == 1 |
| assert call_all(mixed_010) == 1 |
| assert call_all(mixed_100) == 1 |
| assert call_all(mixed_011) == 1 |
| assert call_all(mixed_101) == 1 |
| assert call_all(mixed_110) == 1 |
| |
| assert call_any_nested([[1, 1, 1], [1, 1], []]) == 1 |
| assert call_any_nested([[1, 1, 1], [0, 1], []]) == 0 |
| |
| [case testNextGenerator] |
| from typing import Iterable |
| |
| def f(x: int) -> int: |
| print(x) |
| return x |
| |
| def call_next_loud(l: Iterable[int], val: int) -> int: |
| return next(i for i in l if f(i) == val) |
| |
| def call_next_default(l: Iterable[int], val: int) -> int: |
| return next((i*2 for i in l if i == val), -1) |
| |
| def call_next_default_list(l: Iterable[int], val: int) -> int: |
| return next((i*2 for i in l if i == val), -1) |
| [file driver.py] |
| from native import call_next_loud, call_next_default, call_next_default_list |
| from testutil import assertRaises |
| |
| assert call_next_default([0, 1, 2], 0) == 0 |
| assert call_next_default([0, 1, 2], 1) == 2 |
| assert call_next_default([0, 1, 2], 2) == 4 |
| assert call_next_default([0, 1, 2], 3) == -1 |
| assert call_next_default([], 0) == -1 |
| assert call_next_default_list([0, 1, 2], 0) == 0 |
| assert call_next_default_list([0, 1, 2], 1) == 2 |
| assert call_next_default_list([0, 1, 2], 2) == 4 |
| assert call_next_default_list([0, 1, 2], 3) == -1 |
| assert call_next_default_list([], 0) == -1 |
| |
| assert call_next_loud([0, 1, 2], 0) == 0 |
| assert call_next_loud([0, 1, 2], 1) == 1 |
| assert call_next_loud([0, 1, 2], 2) == 2 |
| with assertRaises(StopIteration): |
| call_next_loud([42], 3) |
| with assertRaises(StopIteration): |
| call_next_loud([], 3) |
| |
| [out] |
| 0 |
| 0 |
| 1 |
| 0 |
| 1 |
| 2 |
| 42 |
| |
| [case testGeneratorSuper] |
| from typing import Iterator, Callable, Any |
| |
| class A(): |
| def testA(self) -> int: |
| return 2 |
| |
| class B(A): |
| def testB(self) -> Iterator[int]: |
| x = super().testA() |
| while True: |
| yield x |
| |
| def testAsserts(): |
| b = B() |
| b_gen = b.testB() |
| assert next(b_gen) == 2 |
| |
| [file driver.py] |
| from native import testAsserts |
| |
| testAsserts() |
| |
| [case testAssignModule] |
| import a |
| assert a.x == 20 |
| a.x = 10 |
| [file a.py] |
| x = 20 |
| [file driver.py] |
| import native |
| |
| [case testNoneStuff] |
| from typing import Optional |
| class A: |
| x: int |
| |
| def lol(x: A) -> None: |
| setattr(x, 'x', 5) |
| |
| def none() -> None: |
| return |
| |
| def arg(x: Optional[A]) -> bool: |
| return x is None |
| |
| |
| [file driver.py] |
| import native |
| native.lol(native.A()) |
| |
| # Catch refcounting failures |
| for i in range(10000): |
| native.none() |
| native.arg(None) |
| |
| [case testBorrowRefs] |
| def make_garbage(arg: object) -> None: |
| b = True |
| while b: |
| arg = None |
| b = False |
| |
| [file driver.py] |
| from native import make_garbage |
| import sys |
| |
| def test(): |
| x = object() |
| r0 = sys.getrefcount(x) |
| make_garbage(x) |
| r1 = sys.getrefcount(x) |
| assert r0 == r1 |
| |
| test() |
| |
| [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 testFinalStaticRunFail] |
| if False: |
| from typing import Final |
| |
| if bool(): |
| x: 'Final' = [1] |
| |
| def f() -> int: |
| return x[0] |
| |
| [file driver.py] |
| from native import f |
| try: |
| print(f()) |
| except ValueError as e: |
| print(e.args[0]) |
| [out] |
| value for final name "x" was not set |
| |
| [case testFinalStaticRunListTupleInt] |
| if False: |
| from typing import Final |
| |
| x: 'Final' = [1] |
| y: 'Final' = (1, 2) |
| z: 'Final' = 1 + 1 |
| |
| def f() -> int: |
| return x[0] |
| def g() -> int: |
| return y[0] |
| def h() -> int: |
| return z - 1 |
| |
| [file driver.py] |
| from native import f, g, h, x, y, z |
| print(f()) |
| print(x[0]) |
| print(g()) |
| print(y) |
| print(h()) |
| print(z) |
| [out] |
| 1 |
| 1 |
| 1 |
| (1, 2) |
| 1 |
| 2 |
| |
| [case testUnannotatedFunction] |
| def g(x: int) -> int: |
| return x * 2 |
| |
| def f(x): |
| return g(x) |
| [file driver.py] |
| from native import f |
| assert f(3) == 6 |
| |
| [case testCheckVersion] |
| import sys |
| |
| # We lie about the version we are running in tests if it is 3.5, so |
| # that hits a crash case. |
| if sys.version_info[:2] == (3, 8): |
| def version() -> int: |
| return 8 |
| elif sys.version_info[:2] == (3, 7): |
| def version() -> int: |
| return 7 |
| elif sys.version_info[:2] == (3, 6): |
| def version() -> int: |
| return 6 |
| else: |
| raise Exception("we don't support this version yet!") |
| |
| |
| [file driver.py] |
| import sys |
| version = sys.version_info[:2] |
| |
| try: |
| import native |
| assert version != (3, 5), "3.5 should fail!" |
| assert native.version() == sys.version_info[1] |
| except RuntimeError: |
| assert version == (3, 5), "only 3.5 should fail!" |
| |
| [case testNameClashIssues] |
| class A: |
| def foo(self) -> object: |
| yield |
| class B: |
| def foo(self) -> object: |
| yield |
| |
| class C: |
| def foo(self) -> None: |
| def bar(self) -> None: |
| pass |
| class D: |
| def foo(self) -> None: |
| def bar(self) -> None: |
| pass |
| |
| class E: |
| default: int |
| switch: int |
| |
| [file driver.py] |
| # really I only care it builds |
| |
| [case testTupleUnionFail] |
| # Test that order is irrelevant to unions |
| |
| from typing import Optional, Tuple |
| |
| class A: |
| pass |
| |
| def lol() -> A: |
| return A() |
| |
| def foo(x: bool, y: bool) -> Tuple[Optional[A], bool]: |
| z = lol() |
| |
| return None if y else z, x |
| |
| [file driver.py] |
| # really I only care it builds |
| |
| [case testDictFree] |
| # Test that we garbage collect stuff with __dict__ right! |
| from typing import Optional, Any, Dict, Generic, List |
| from base import Base |
| |
| class A(Base): |
| z: Any |
| |
| def make_garbage(x: List[str]) -> None: |
| a = A() |
| b = A() |
| a.x = b |
| b.x = a |
| a.y = [1,2,3,4,5] |
| |
| [file base.py] |
| class Base: |
| x = None # type: object |
| y = None # type: object |
| |
| [file driver.py] |
| from native import make_garbage |
| import gc |
| |
| def test(): |
| gc.collect(2) |
| x = len(gc.get_objects()) |
| make_garbage([1,2,3,4]) |
| gc.collect(2) |
| y = len(gc.get_objects()) |
| assert x == y |
| |
| test() |
| |
| [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 testComplicatedArgs] |
| from typing import Tuple, Dict |
| |
| def kwonly1(x: int = 0, *, y: int) -> Tuple[int, int]: |
| return x, y |
| |
| def kwonly2(*, x: int = 0, y: int) -> Tuple[int, int]: |
| return x, y |
| |
| def kwonly3(a: int, b: int = 0, *, y: int, x: int = 1) -> Tuple[int, int, int, int]: |
| return a, b, x, y |
| |
| def kwonly4(*, x: int, y: int) -> Tuple[int, int]: |
| return x, y |
| |
| def varargs1(*args: int) -> Tuple[int, ...]: |
| return args |
| |
| def varargs2(*args: int, **kwargs: int) -> Tuple[Tuple[int, ...], Dict[str, int]]: |
| return args, kwargs |
| |
| def varargs3(**kwargs: int) -> Dict[str, int]: |
| return kwargs |
| |
| def varargs4(a: int, b: int = 0, |
| *args: int, y: int, x: int = 1, |
| **kwargs: int) -> Tuple[Tuple[int, ...], Dict[str, int]]: |
| return (a, b, *args), {'x': x, 'y': y, **kwargs} |
| |
| class A: |
| def f(self, x: int) -> Tuple[int, ...]: |
| return (x,) |
| def g(self, x: int) -> Tuple[Tuple[int, ...], Dict[str, int]]: |
| return (x,), {} |
| |
| class B(A): |
| def f(self, *args: int) -> Tuple[int, ...]: |
| return args |
| def g(self, *args: int, **kwargs: int) -> Tuple[Tuple[int, ...], Dict[str, int]]: |
| return args, kwargs |
| |
| [file other.py] |
| # This file is imported in both compiled and interpreted mode in order to |
| # test both native calls and calls via the C API. |
| |
| from native import ( |
| kwonly1, kwonly2, kwonly3, kwonly4, |
| varargs1, varargs2, varargs3, varargs4, |
| A, B |
| ) |
| |
| # kwonly arg tests |
| assert kwonly1(10, y=20) == (10, 20) |
| assert kwonly1(y=20) == (0, 20) |
| |
| assert kwonly2(x=10, y=20) == (10, 20) |
| assert kwonly2(y=20) == (0, 20) |
| |
| assert kwonly3(10, y=20) == (10, 0, 1, 20) |
| assert kwonly3(a=10, y=20) == (10, 0, 1, 20) |
| assert kwonly3(10, 30, y=20) == (10, 30, 1, 20) |
| assert kwonly3(10, b=30, y=20) == (10, 30, 1, 20) |
| assert kwonly3(a=10, b=30, y=20) == (10, 30, 1, 20) |
| |
| assert kwonly3(10, x=40, y=20) == (10, 0, 40, 20) |
| assert kwonly3(a=10, x=40, y=20) == (10, 0, 40, 20) |
| assert kwonly3(10, 30, x=40, y=20) == (10, 30, 40, 20) |
| assert kwonly3(10, b=30, x=40, y=20) == (10, 30, 40, 20) |
| assert kwonly3(a=10, b=30, x=40, y=20) == (10, 30, 40, 20) |
| |
| assert kwonly4(x=1, y=2) == (1, 2) |
| assert kwonly4(y=2, x=1) == (1, 2) |
| |
| # varargs tests |
| assert varargs1() == () |
| assert varargs1(1, 2, 3) == (1, 2, 3) |
| assert varargs2(1, 2, 3) == ((1, 2, 3), {}) |
| assert varargs2(1, 2, 3, x=4) == ((1, 2, 3), {'x': 4}) |
| assert varargs2(x=4) == ((), {'x': 4}) |
| assert varargs3() == {} |
| assert varargs3(x=4) == {'x': 4} |
| assert varargs3(x=4, y=5) == {'x': 4, 'y': 5} |
| |
| assert varargs4(-1, y=2) == ((-1, 0), {'x': 1, 'y': 2}) |
| assert varargs4(-1, 2, y=2) == ((-1, 2), {'x': 1, 'y': 2}) |
| assert varargs4(-1, 2, 3, y=2) == ((-1, 2, 3), {'x': 1, 'y': 2}) |
| assert varargs4(-1, 2, 3, x=10, y=2) == ((-1, 2, 3), {'x': 10, 'y': 2}) |
| assert varargs4(-1, x=10, y=2) == ((-1, 0), {'x': 10, 'y': 2}) |
| assert varargs4(-1, y=2, z=20) == ((-1, 0), {'x': 1, 'y': 2, 'z': 20}) |
| assert varargs4(-1, 2, y=2, z=20) == ((-1, 2), {'x': 1, 'y': 2, 'z': 20}) |
| assert varargs4(-1, 2, 3, y=2, z=20) == ((-1, 2, 3), {'x': 1, 'y': 2, 'z': 20}) |
| assert varargs4(-1, 2, 3, x=10, y=2, z=20) == ((-1, 2, 3), {'x': 10, 'y': 2, 'z': 20}) |
| assert varargs4(-1, x=10, y=2, z=20) == ((-1, 0), {'x': 10, 'y': 2, 'z': 20}) |
| |
| x = B() # type: A |
| assert x.f(1) == (1,) |
| assert x.g(1) == ((1,), {}) |
| # This one is really funny! When we make native calls we lose |
| # track of which arguments are positional or keyword, so the glue |
| # calls them all positional unless they are keyword only... |
| # It would be possible to fix this by dynamically tracking which |
| # arguments were passed by keyword (for example, by passing a bitmask |
| # to functions indicating this), but paying a speed, size, and complexity |
| # cost for something so deeply marginal seems like a bad choice. |
| # assert x.g(x=1) == ((), {'x': 1}) |
| |
| [file driver.py] |
| from testutil import assertRaises |
| from native import ( |
| kwonly1, kwonly2, kwonly3, kwonly4, |
| varargs1, varargs2, varargs3, varargs4, |
| ) |
| |
| # Run the non-exceptional tests in both interpreted and compiled mode |
| import other |
| import other_interpreted |
| |
| |
| # And the tests for errors at the interfaces in interpreted only |
| with assertRaises(TypeError, "missing required keyword-only argument 'y'"): |
| kwonly1() |
| with assertRaises(TypeError, "takes at most 1 positional argument (2 given)"): |
| kwonly1(10, 20) |
| |
| with assertRaises(TypeError, "missing required keyword-only argument 'y'"): |
| kwonly2() |
| with assertRaises(TypeError, "takes no positional arguments"): |
| kwonly2(10, 20) |
| |
| with assertRaises(TypeError, "missing required argument 'a'"): |
| kwonly3(b=30, x=40, y=20) |
| with assertRaises(TypeError, "missing required keyword-only argument 'y'"): |
| kwonly3(10) |
| |
| with assertRaises(TypeError, "missing required keyword-only argument 'y'"): |
| kwonly4(x=1) |
| with assertRaises(TypeError, "missing required keyword-only argument 'x'"): |
| kwonly4(y=1) |
| with assertRaises(TypeError, "missing required keyword-only argument 'x'"): |
| kwonly4() |
| |
| with assertRaises(TypeError, "'x' is an invalid keyword argument for varargs1()"): |
| varargs1(x=10) |
| with assertRaises(TypeError, "'x' is an invalid keyword argument for varargs1()"): |
| varargs1(1, x=10) |
| with assertRaises(TypeError, "varargs3() takes no positional arguments"): |
| varargs3(10) |
| with assertRaises(TypeError, "varargs3() takes no positional arguments"): |
| varargs3(10, x=10) |
| |
| with assertRaises(TypeError, "varargs4() missing required argument 'a' (pos 1)"): |
| varargs4() |
| with assertRaises(TypeError, "varargs4() missing required keyword-only argument 'y'"): |
| varargs4(1, 2) |
| with assertRaises(TypeError, "varargs4() missing required keyword-only argument 'y'"): |
| varargs4(1, 2, x=1) |
| with assertRaises(TypeError, "varargs4() missing required keyword-only argument 'y'"): |
| varargs4(1, 2, 3) |
| with assertRaises(TypeError, "varargs4() missing required argument 'a' (pos 1)"): |
| varargs4(y=20) |
| |
| [case testTypeErrorMessages] |
| from typing import Tuple |
| class A: |
| pass |
| class B: |
| pass |
| |
| def f(x: B) -> None: |
| pass |
| def g(x: Tuple[int, A]) -> None: |
| pass |
| [file driver.py] |
| from testutil import assertRaises |
| from native import A, f, g |
| |
| class Busted: |
| pass |
| Busted.__module__ = None |
| |
| with assertRaises(TypeError, "int"): |
| f(0) |
| with assertRaises(TypeError, "native.A"): |
| f(A()) |
| with assertRaises(TypeError, "tuple[None, native.A]"): |
| f((None, A())) |
| with assertRaises(TypeError, "tuple[tuple[int, str], native.A]"): |
| f(((1, "ha"), A())) |
| with assertRaises(TypeError, "tuple[<50 items>]"): |
| f(tuple(range(50))) |
| |
| with assertRaises(TypeError, "errored formatting real type!"): |
| f(Busted()) |
| |
| with assertRaises(TypeError, "tuple[int, native.A] object expected; got tuple[int, int]"): |
| g((20, 30)) |
| |
| [case testComprehensionShadowBinder] |
| def foo(x: object) -> object: |
| if isinstance(x, list): |
| return tuple(x for x in x), x |
| return None |
| |
| [file driver.py] |
| from native import foo |
| |
| assert foo(None) == None |
| assert foo([1, 2, 3]) == ((1, 2, 3), [1, 2, 3]) |
| |
| [case testReexport] |
| # Test that we properly handle accessing values that have been reexported |
| import a |
| def f(x: int) -> int: |
| return a.g(x) + a.foo + a.b.foo |
| |
| whatever = a.A() |
| |
| [file a.py] |
| from b import g as g, A as A, foo as foo |
| import b |
| |
| [file b.py] |
| def g(x: int) -> int: |
| return x + 1 |
| |
| class A: |
| pass |
| |
| foo = 20 |
| |
| [file driver.py] |
| from native import f, whatever |
| import b |
| |
| assert f(20) == 61 |
| assert isinstance(whatever, b.A) |