Skip to content

Commit 309dfe3

Browse files
committed
extmod/uasyncio: Add Task.done() method.
This is added because task.coro==None is no longer the way to detect if a task is finished. Providing a (CPython compatible) function for this allows the implementation to be abstracted away. Signed-off-by: Damien George <damien@micropython.org>
1 parent ca40eb0 commit 309dfe3

File tree

4 files changed

+102
-0
lines changed

4 files changed

+102
-0
lines changed

extmod/moduasyncio.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,12 @@ STATIC mp_obj_t task_make_new(const mp_obj_type_t *type, size_t n_args, size_t n
167167
return MP_OBJ_FROM_PTR(self);
168168
}
169169

170+
STATIC mp_obj_t task_done(mp_obj_t self_in) {
171+
mp_obj_task_t *self = MP_OBJ_TO_PTR(self_in);
172+
return mp_obj_new_bool(TASK_IS_DONE(self));
173+
}
174+
STATIC MP_DEFINE_CONST_FUN_OBJ_1(task_done_obj, task_done);
175+
170176
STATIC mp_obj_t task_cancel(mp_obj_t self_in) {
171177
mp_obj_task_t *self = MP_OBJ_TO_PTR(self_in);
172178
// Check if task is already finished.
@@ -242,6 +248,9 @@ STATIC void task_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
242248
if (self->waiting != mp_const_none && self->waiting != mp_const_false) {
243249
dest[0] = self->waiting;
244250
}
251+
} else if (attr == MP_QSTR_done) {
252+
dest[0] = MP_OBJ_FROM_PTR(&task_done_obj);
253+
dest[1] = self_in;
245254
} else if (attr == MP_QSTR_cancel) {
246255
dest[0] = MP_OBJ_FROM_PTR(&task_cancel_obj);
247256
dest[1] = self_in;

extmod/uasyncio/task.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,9 @@ def __next__(self):
148148
# Set calling task's data to this task that it waits on, to double-link it.
149149
core.cur_task.data = self
150150

151+
def done(self):
152+
return self.coro is self
153+
151154
def cancel(self):
152155
# Check if task is already finished.
153156
if self.coro is self:

tests/extmod/uasyncio_task_done.py

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# Test the Task.done() method
2+
3+
try:
4+
import uasyncio as asyncio
5+
except ImportError:
6+
try:
7+
import asyncio
8+
except ImportError:
9+
print("SKIP")
10+
raise SystemExit
11+
12+
13+
async def task(t, exc=None):
14+
print("task start")
15+
if t >= 0:
16+
await asyncio.sleep(t)
17+
if exc:
18+
raise exc
19+
print("task done")
20+
21+
22+
async def main():
23+
# Task that finishes immediately.
24+
print("=" * 10)
25+
t = asyncio.create_task(task(-1))
26+
print(t.done())
27+
await asyncio.sleep(0)
28+
print(t.done())
29+
await t
30+
print(t.done())
31+
32+
# Task that starts, runs and finishes.
33+
print("=" * 10)
34+
t = asyncio.create_task(task(0.01))
35+
print(t.done())
36+
await asyncio.sleep(0)
37+
print(t.done())
38+
await t
39+
print(t.done())
40+
41+
# Task that raises immediately.
42+
print("=" * 10)
43+
t = asyncio.create_task(task(-1, ValueError))
44+
print(t.done())
45+
await asyncio.sleep(0)
46+
print(t.done())
47+
try:
48+
await t
49+
except ValueError as er:
50+
print(repr(er))
51+
print(t.done())
52+
53+
# Task that raises after a delay.
54+
print("=" * 10)
55+
t = asyncio.create_task(task(0.01, ValueError))
56+
print(t.done())
57+
await asyncio.sleep(0)
58+
print(t.done())
59+
try:
60+
await t
61+
except ValueError as er:
62+
print(repr(er))
63+
print(t.done())
64+
65+
66+
asyncio.run(main())
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
==========
2+
False
3+
task start
4+
task done
5+
True
6+
True
7+
==========
8+
False
9+
task start
10+
False
11+
task done
12+
True
13+
==========
14+
False
15+
task start
16+
True
17+
ValueError()
18+
True
19+
==========
20+
False
21+
task start
22+
False
23+
ValueError()
24+
True

0 commit comments

Comments
 (0)