-
-
Notifications
You must be signed in to change notification settings - Fork 16
Expand file tree
/
Copy pathtest_async.py
More file actions
119 lines (90 loc) · 3.01 KB
/
test_async.py
File metadata and controls
119 lines (90 loc) · 3.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import asyncio
import contextlib
import gc
import platform
import sys
import traceback
import types
import weakref
import pytest
import outcome
from outcome import AlreadyUsedError, Error, Value
pytestmark = pytest.mark.asyncio
async def test_acapture():
async def add(x, y):
await asyncio.sleep(0)
return x + y
v = await outcome.acapture(add, 3, y=4)
assert v == Value(7)
async def raise_ValueError(x):
await asyncio.sleep(0)
raise ValueError(x)
e = await outcome.acapture(raise_ValueError, 9)
assert type(e.error) is ValueError
assert e.error.args == (9,)
async def test_asend():
async def my_agen_func():
assert (yield 1) == "value"
with pytest.raises(KeyError):
yield 2
yield 3
my_agen = my_agen_func().__aiter__()
v = Value("value")
e = Error(KeyError())
assert (await my_agen.asend(None)) == 1
assert (await v.asend(my_agen)) == 2
with pytest.raises(AlreadyUsedError):
await v.asend(my_agen)
assert (await e.asend(my_agen)) == 3
with pytest.raises(AlreadyUsedError):
await e.asend(my_agen)
with pytest.raises(StopAsyncIteration):
await my_agen.asend(None)
async def test_traceback_frame_removal():
async def raise_ValueError(x):
raise ValueError(x)
e = await outcome.acapture(raise_ValueError, 'abc')
with pytest.raises(ValueError) as exc_info:
e.unwrap()
frames = traceback.extract_tb(exc_info.value.__traceback__)
functions = [function for _, _, function, _ in frames]
assert functions[-2:] == ['unwrap', 'raise_ValueError']
@types.coroutine
def async_yield(v):
return (yield v)
async def test_unwrap_leaves_a_refcycle():
class MyException(Exception):
pass
async def network_operation():
return (await async_yield("network operation")).unwrap()
async def coro_fn():
try:
await network_operation()
except MyException as e:
wr_e = weakref.ref(e)
del e
if platform.python_implementation() == "PyPy":
gc.collect()
assert isinstance(wr_e(), MyException)
with contextlib.closing(coro_fn()) as coro:
assert coro.send(None) == "network operation"
with pytest.raises(StopIteration):
coro.send(outcome.Error(MyException()))
async def test_unwrap_and_destroy_does_not_leave_a_refcycle():
class MyException(Exception):
pass
async def network_operation():
return (await async_yield("network operation")).unwrap_and_destroy()
async def coro_fn():
try:
await network_operation()
except MyException as e:
wr_e = weakref.ref(e)
del e
if platform.python_implementation() == "PyPy":
gc.collect()
assert wr_e() is None
with contextlib.closing(coro_fn()) as coro:
assert coro.send(None) == "network operation"
with pytest.raises(StopIteration):
coro.send(outcome.Error(MyException()))