init
This commit is contained in:
commit
38355d2442
9083 changed files with 1225834 additions and 0 deletions
|
|
@ -0,0 +1,518 @@
|
|||
# Test cases for generators and yield (compile and run)
|
||||
|
||||
[case testYield]
|
||||
from typing import Generator, Iterable, Union, Tuple, Dict
|
||||
|
||||
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 yield_dict_methods(d1: Dict[int, int],
|
||||
d2: Dict[int, int],
|
||||
d3: Dict[int, int]) -> Iterable[int]:
|
||||
for k in d1.keys():
|
||||
yield k
|
||||
for k, v in d2.items():
|
||||
yield k
|
||||
yield v
|
||||
for v in d3.values():
|
||||
yield v
|
||||
|
||||
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,
|
||||
yield_dict_methods,
|
||||
)
|
||||
from testutil import run_generator
|
||||
from collections import defaultdict
|
||||
|
||||
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))
|
||||
assert run_generator(yield_dict_methods({}, {}, {})) == ((), None)
|
||||
assert run_generator(yield_dict_methods({1: 2}, {3: 4}, {5: 6})) == ((1, 3, 4, 6), None)
|
||||
dd = defaultdict(int, {0: 1})
|
||||
assert run_generator(yield_dict_methods(dd, dd, dd)) == ((0, 0, 1, 1), None)
|
||||
|
||||
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 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 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
|
||||
|
||||
def C___foo() -> 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
|
||||
Loading…
Add table
Add a link
Reference in a new issue