# Test cases for functions and calls (compile and run) [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 testRecursiveFibonacci] def fib(n: int) -> int: if n <= 1: return 1 else: return fib(n - 1) + fib(n - 2) [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 testNestedFunctions] from typing import Callable, List def a() -> Callable[[], object]: def inner() -> object: return None return inner def b() -> Callable[[], Callable[[], str]]: def first() -> Callable[[], str]: def second() -> str: return 'b.first.second: nested function' return second return first def c(num: float) -> Callable[[str], str]: def inner(s: str) -> str: return s + '!' return inner def d(num: float) -> str: def inner(s: str) -> str: return s + '?' a = inner('one') b = inner('two') return a def e() -> int: return 0 def f() -> int: def inner() -> int: return e() return inner() def g() -> Callable[[], Callable[[], int]]: def inner() -> Callable[[], int]: return e return inner def h(num: int) -> int: def inner() -> int: return num return inner() def i() -> int: num = 3 def inner() -> int: return num return inner() def j(num: int) -> int: x = 1 y = 2 def inner() -> int: nonlocal x x = 3 return num + x + y return inner() def k() -> int: num = 3 def inner() -> int: nonlocal num num = 5 return num return inner() + num def l() -> int: num = 3 def inner() -> int: num = 5 return num return inner() + num def m() -> Callable[[], int]: num = 1 def inner() -> int: num += 1 return num num += 1 return inner def n() -> int: x = 1 def add_one() -> None: x += 1 def add_two() -> None: x += 2 add_one() add_two() return x def triple(a: int) -> Callable[[], Callable[[int], int]]: x = 1 def outer() -> Callable[[int], int]: nonlocal x x += 1 x += a a += 1 def inner(b: int) -> int: x += b return x return inner return outer def if_else(flag: int) -> str: def dummy_funtion() -> str: return 'if_else.dummy_function' if flag < 0: def inner() -> str: return 'if_else.inner: first definition' elif flag > 0: def inner() -> str: return 'if_else.inner: second definition' else: def inner() -> str: return 'if_else.inner: third definition' return inner() def for_loop() -> int: def dummy_funtion() -> str: return 'for_loop.dummy_function' for i in range(5): def inner(i: int) -> int: return i if i == 3: return inner(i) return 0 def while_loop() -> int: def dummy_funtion() -> str: return 'while_loop.dummy_function' i = 0 while i < 5: def inner(i: int) -> int: return i if i == 3: return inner(i) i += 1 return 0 def free_vars(foo: int, bar: int) -> int: x = 1 y = 2 def g(): # type: ignore # missing type annotation for testing nonlocal y y = 3 nonlocal bar bar += y z = 3 g() return bar def lambdas(x: int, y: int) -> int: s = lambda a, b: a + b + x + y return s(1, 2) def outer() -> str: return 'outer: normal function' def inner() -> str: return 'inner: normal function' class A: def __init__(self, x: int) -> None: self.x = x def outer(self, num: int) -> int: y = 5 def inner() -> int: return self.x + y + num return inner() def o() -> int: a = [0, 0] b = 0 def b_incr() -> List[int]: b += 10 return a c = 0 def c_incr() -> int: c += 1 return c # x = 1, y = 1 x = y = c_incr() # a = [2, 2], b = 20 b_incr()[0] = b_incr()[1] = c_incr() # Should return 26. return x + y + a[0] + a[1] + b global_upvar = 20 toplevel_lambda = lambda x: 10 + global_upvar + x [file driver.py] from native import ( a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, triple, if_else, for_loop, while_loop, free_vars, lambdas, outer, inner, A, toplevel_lambda ) assert a()() == None assert b()()() == 'b.first.second: nested function' assert c(5.0)('c') == 'c!' assert d(4.0) == 'one?' assert e() == 0 assert f() == 0 assert g()()() == 0 assert h(3) == 3 assert i() == 3 assert j(3) == 8 assert k() == 10 assert l() == 8 assert m()() == 3 assert n() == 4 assert o() == 26 triple_outer = triple(2) triple_inner = triple_outer() assert triple_inner(4) == 8 assert triple_inner(4) == 12 assert triple_outer()(4) == 20 assert if_else(-1) == 'if_else.inner: first definition' assert if_else(1) == 'if_else.inner: second definition' assert if_else(0) == 'if_else.inner: third definition' assert for_loop() == 3 assert while_loop() == 3 assert free_vars(1, 2) == 5 assert lambdas(3, 4) == 10 assert outer() == 'outer: normal function' assert inner() == 'inner: normal function' assert A(3).outer(4) == 12 assert toplevel_lambda(5) == 35 [case testNestedFunctions2] 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 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 def bool_default(x: bool = False, y: bool = True) -> str: return str(x) + '-' + str(y) [file driver.py] from native import f, g, h, same, nested_funcs, a_lambda, bool_default 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 assert bool_default() == 'False-True' assert bool_default(True) == 'True-True' assert bool_default(True, False) == 'True-False' [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 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 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 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 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 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, TypeVar from contextlib import contextmanager T = TypeVar('T') def dec(f: T) -> T: return f 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') class Lol: @staticmethod def foo() -> None: Lol.bar() Lol.baz() @staticmethod @dec def bar() -> None: pass @classmethod @dec def baz(cls) -> None: pass 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 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 testUnannotatedModuleLevelInitFunction] # Ensure that adding an implicit `-> None` annotation only applies to `__init__` # _methods_ specifically (not module-level `__init__` functions). def __init__(): return 42 [file driver.py] from native import __init__ assert __init__() == 42 [case testDifferentArgCountsFromInterpreted] # Test various signatures from interpreted code. def noargs() -> int: return 5 def onearg(x: int) -> int: return x + 1 def twoargs(x: int, y: str) -> int: return x + len(y) def one_or_two(x: int, y: str = 'a') -> int: return x + len(y) [file driver.py] from native import noargs, onearg, twoargs, one_or_two from testutil import assertRaises assert noargs() == 5 t = () assert noargs(*t) == 5 d = {} assert noargs(**d) == 5 assert noargs(*t, **d) == 5 assert onearg(12) == 13 assert onearg(x=8) == 9 t = (1,) assert onearg(*t) == 2 d = {'x': 5} assert onearg(**d) == 6 # Test a bogus call to twoargs before any correct calls are made with assertRaises(TypeError, "twoargs() missing required argument 'x' (pos 1)"): twoargs() assert twoargs(5, 'foo') == 8 assert twoargs(4, y='foo') == 7 assert twoargs(y='foo', x=7) == 10 t = (1, 'xy') assert twoargs(*t) == 3 d = {'y': 'xy'} assert twoargs(2, **d) == 4 assert one_or_two(5) == 6 assert one_or_two(x=3) == 4 assert one_or_two(6, 'xy') == 8 assert one_or_two(7, y='xy') == 9 assert one_or_two(y='xy', x=2) == 4 assert one_or_two(*t) == 3 d = {'x': 5} assert one_or_two(**d) == 6 assert one_or_two(y='xx', **d) == 7 d = {'y': 'abc'} assert one_or_two(1, **d) == 4 with assertRaises(TypeError, 'noargs() takes at most 0 arguments (1 given)'): noargs(1) with assertRaises(TypeError, 'noargs() takes at most 0 keyword arguments (1 given)'): noargs(x=1) with assertRaises(TypeError, "onearg() missing required argument 'x' (pos 1)"): onearg() with assertRaises(TypeError, 'onearg() takes at most 1 argument (2 given)'): onearg(1, 2) with assertRaises(TypeError, "onearg() missing required argument 'x' (pos 1)"): onearg(y=1) with assertRaises(TypeError, "onearg() takes at most 1 argument (2 given)"): onearg(1, y=1) with assertRaises(TypeError, "twoargs() missing required argument 'x' (pos 1)"): twoargs() with assertRaises(TypeError, "twoargs() missing required argument 'y' (pos 2)"): twoargs(1) with assertRaises(TypeError, 'twoargs() takes at most 2 arguments (3 given)'): twoargs(1, 'x', 2) with assertRaises(TypeError, 'twoargs() takes at most 2 arguments (3 given)'): twoargs(1, 'x', y=2) with assertRaises(TypeError, "one_or_two() missing required argument 'x' (pos 1)"): one_or_two() with assertRaises(TypeError, 'one_or_two() takes at most 2 arguments (3 given)'): one_or_two(1, 'x', 2) with assertRaises(TypeError, 'one_or_two() takes at most 2 arguments (3 given)'): one_or_two(1, 'x', y=2) [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 varargs1(1, *[2, 3, 4], 5, *[6, 7, 8], 9) == (1, 2, 3, 4, 5, 6, 7, 8, 9) 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 testDecoratorName] def dec(f): return f @dec def foo(): pass def test_decorator_name(): assert foo.__name__ == "foo" [case testLambdaArgToOverloaded] from lib import sub def test_str_overload() -> None: assert sub('x', lambda m: m) == 'x' def test_bytes_overload() -> None: assert sub(b'x', lambda m: m) == b'x' [file lib.py] from typing import overload, Callable, TypeVar, Generic T = TypeVar("T") class Match(Generic[T]): def __init__(self, x: T) -> None: self.x = x def group(self, n: int) -> T: return self.x @overload def sub(s: str, f: Callable[[str], str]) -> str: ... @overload def sub(s: bytes, f: Callable[[bytes], bytes]) -> bytes: ... def sub(s, f): return f(s) [case testContextManagerSpecialCase] from typing import Generator, Callable, Iterator from contextlib import contextmanager @contextmanager def f() -> Iterator[None]: yield def g() -> None: a = [''] with f(): a.pop() g() [case testUnpackKwargsCompiled] from typing_extensions import Unpack, TypedDict class Person(TypedDict): name: str age: int def foo(**kwargs: Unpack[Person]) -> None: print(kwargs["name"]) # This is not really supported yet, just test that we behave reasonably. foo(name='Jennifer', age=38) [out] Jennifer