Skip to content

Commit fe2946b

Browse files
committed
Add tests
1 parent 5c26a25 commit fe2946b

File tree

2 files changed

+238
-10
lines changed

2 files changed

+238
-10
lines changed

tests/snippets/async_stuff.py

+50-10
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,53 @@
1+
import asyncio_slow as asyncio
12

2-
import sys
3-
import ast
43

5-
src = """
6-
async def x():
7-
async for x in [1,2,3]:
8-
await y()
9-
"""
4+
class ContextManager:
5+
async def __aenter__(self):
6+
print("Entrada")
7+
ls.append(1)
8+
return 1
109

11-
mod = ast.parse(src)
12-
# print(mod)
13-
# print(ast.dump(mod))
10+
def __str__(self):
11+
ls.append(2)
12+
return "c'est moi!"
13+
14+
async def __aexit__(self, exc_type, exc_val, exc_tb):
15+
ls.append(3)
16+
print("Wiedersehen")
17+
18+
19+
ls = []
20+
21+
22+
async def a(s, m):
23+
async with ContextManager() as b:
24+
print(f"val = {b}")
25+
await asyncio.sleep(s)
26+
for _ in range(0, 2):
27+
ls.append(m)
28+
await asyncio.sleep(1)
29+
30+
31+
loop = asyncio.get_event_loop()
32+
loop.run_until_complete(
33+
asyncio.wait([a(0, "hello1"), a(0.5, "hello2"), a(1, "hello3"), a(1.5, "hello4")])
34+
)
35+
36+
assert ls == [
37+
1,
38+
3,
39+
"hello1",
40+
1,
41+
3,
42+
1,
43+
3,
44+
1,
45+
3,
46+
"hello2",
47+
"hello1",
48+
"hello3",
49+
"hello4",
50+
"hello2",
51+
"hello3",
52+
"hello4",
53+
]

tests/snippets/asyncio_slow.py

+188
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
# Adapted from micropython-lib
2+
3+
# The MIT License (MIT)
4+
#
5+
# Copyright (c) 2013, 2014 micropython-lib contributors
6+
#
7+
# Permission is hereby granted, free of charge, to any person obtaining a copy
8+
# of this software and associated documentation files (the "Software"), to deal
9+
# in the Software without restriction, including without limitation the rights
10+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+
# copies of the Software, and to permit persons to whom the Software is
12+
# furnished to do so, subject to the following conditions:
13+
#
14+
# The above copyright notice and this permission notice shall be included in
15+
# all copies or substantial portions of the Software.
16+
#
17+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23+
# THE SOFTWARE.
24+
25+
import time
26+
import logging
27+
import types
28+
29+
30+
log = logging.getLogger("asyncio")
31+
32+
33+
# Workaround for not being able to subclass builtin types
34+
class LoopStop(Exception):
35+
pass
36+
37+
38+
class InvalidStateError(Exception):
39+
pass
40+
41+
42+
# Object not matching any other object
43+
_sentinel = []
44+
45+
46+
class EventLoop:
47+
def __init__(self):
48+
self.q = []
49+
50+
def call_soon(self, c, *args):
51+
self.q.append((c, args))
52+
53+
def call_later(self, delay, c, *args):
54+
def _delayed(c, args, delay):
55+
yield from sleep(delay)
56+
self.call_soon(c, *args)
57+
58+
Task(_delayed(c, args, delay))
59+
60+
def run_forever(self):
61+
while self.q:
62+
f, args = self.q.pop(0)
63+
try:
64+
f(*args)
65+
except LoopStop:
66+
return
67+
# I mean, forever
68+
while True:
69+
time.sleep(1)
70+
71+
def stop(self):
72+
def _cb():
73+
raise LoopStop
74+
75+
self.call_soon(_cb)
76+
77+
def run_until_complete(self, coro):
78+
t = ensure_future(coro)
79+
t.add_done_callback(lambda a: self.stop())
80+
self.run_forever()
81+
82+
def close(self):
83+
pass
84+
85+
86+
_def_event_loop = EventLoop()
87+
88+
89+
class Future:
90+
def __init__(self, loop=_def_event_loop):
91+
self.loop = loop
92+
self.res = _sentinel
93+
self.cbs = []
94+
95+
def result(self):
96+
if self.res is _sentinel:
97+
raise InvalidStateError
98+
return self.res
99+
100+
def add_done_callback(self, fn):
101+
if self.res is _sentinel:
102+
self.cbs.append(fn)
103+
else:
104+
self.loop.call_soon(fn, self)
105+
106+
def set_result(self, val):
107+
self.res = val
108+
for f in self.cbs:
109+
f(self)
110+
111+
112+
class Task(Future):
113+
def __init__(self, coro, loop=_def_event_loop):
114+
super().__init__()
115+
self.loop = loop
116+
self.c = coro
117+
# upstream asyncio forces task to be scheduled on instantiation
118+
self.loop.call_soon(self)
119+
120+
def __call__(self):
121+
try:
122+
next(self.c)
123+
except StopIteration as e:
124+
log.debug("Coro finished: %s", self.c)
125+
self.set_result(None)
126+
else:
127+
self.loop.call_soon(self)
128+
129+
130+
def get_event_loop():
131+
return _def_event_loop
132+
133+
134+
# Decorator
135+
def coroutine(f):
136+
return f
137+
138+
139+
def ensure_future(coro):
140+
if isinstance(coro, Future):
141+
return coro
142+
elif hasattr(coro, "__await__"):
143+
return ensure_future(_wrap_awaitable(coro))
144+
return Task(coro)
145+
146+
147+
def _wrap_awaitable(awaitable):
148+
"""Helper for asyncio.ensure_future().
149+
Wraps awaitable (an object with __await__) into a coroutine
150+
that will later be wrapped in a Task by ensure_future().
151+
"""
152+
return (yield from awaitable.__await__())
153+
154+
155+
class _Wait(Future):
156+
def __init__(self, n):
157+
super().__init__()
158+
self.n = n
159+
160+
def _done(self):
161+
self.n -= 1
162+
log.debug("Wait: remaining tasks: %d", self.n)
163+
if not self.n:
164+
self.set_result(None)
165+
166+
def __call__(self):
167+
pass
168+
169+
170+
def wait(coro_list, loop=_def_event_loop):
171+
172+
w = _Wait(len(coro_list))
173+
174+
for c in coro_list:
175+
t = ensure_future(c)
176+
t.add_done_callback(lambda val: w._done())
177+
178+
return w
179+
180+
181+
@types.coroutine
182+
def sleep(secs):
183+
t = time.time()
184+
log.debug("Started sleep at: %s, targetting: %s", t, t + secs)
185+
while time.time() < t + secs:
186+
time.sleep(0.01)
187+
yield
188+
log.debug("Finished sleeping %ss", secs)

0 commit comments

Comments
 (0)