@@ -59,6 +59,9 @@ typedef struct _mp_obj_task_queue_t {
5959 mp_obj_task_t * heap ;
6060} mp_obj_task_queue_t ;
6161
62+ MP_DEFINE_EXCEPTION (CancelledError , BaseException )
63+ MP_DEFINE_EXCEPTION (InvalidStateError , Exception )
64+
6265STATIC const mp_obj_type_t task_queue_type ;
6366STATIC const mp_obj_type_t task_type ;
6467
@@ -194,6 +197,85 @@ STATIC mp_obj_t task_get_coro(mp_obj_t self_in) {
194197}
195198STATIC MP_DEFINE_CONST_FUN_OBJ_1 (task_get_coro_obj , task_get_coro );
196199
200+ STATIC mp_obj_t task_set_exception (mp_obj_t self_in , const mp_obj_t arg ) {
201+ mp_raise_msg (& mp_type_RuntimeError , MP_ERROR_TEXT ("Task does not support set_exception operation" ));
202+ }
203+ STATIC MP_DEFINE_CONST_FUN_OBJ_2 (task_set_exception_obj , task_set_exception );
204+
205+ STATIC mp_obj_t task_exception (mp_obj_t self_in ) {
206+ mp_obj_task_t * self = MP_OBJ_TO_PTR (self_in );
207+
208+ if (!TASK_IS_DONE (self )) {
209+ mp_raise_msg (& mp_type_InvalidStateError , MP_ERROR_TEXT ("Exception is not set." ));
210+ return NULL ;
211+ }
212+
213+ mp_obj_t data_obj = self -> data ;
214+
215+ // If the exception is a cancelled error then we should raise it
216+ if (mp_obj_is_subclass_fast (MP_OBJ_FROM_PTR (mp_obj_get_type (data_obj )), MP_OBJ_FROM_PTR (& mp_type_CancelledError ))) {
217+ nlr_raise (data_obj );
218+ }
219+
220+ // If it's a StopIteration we should should return none
221+ if (mp_obj_is_subclass_fast (MP_OBJ_FROM_PTR (mp_obj_get_type (data_obj )), MP_OBJ_FROM_PTR (& mp_type_StopIteration ))) {
222+ return mp_const_none ;
223+ }
224+
225+ if (!mp_obj_is_exception_instance (data_obj )) {
226+ return mp_const_none ;
227+ }
228+
229+ return data_obj ;
230+ }
231+ STATIC MP_DEFINE_CONST_FUN_OBJ_1 (task_exception_obj , task_exception );
232+
233+ STATIC mp_obj_t task_set_result (mp_obj_t self_in , const mp_obj_t arg ) {
234+ mp_raise_msg (& mp_type_RuntimeError , MP_ERROR_TEXT ("Task does not support set_result operation" ));
235+ }
236+ STATIC MP_DEFINE_CONST_FUN_OBJ_2 (task_set_result_obj , task_set_result );
237+
238+ STATIC mp_obj_t task_result (mp_obj_t self_in ) {
239+ mp_obj_task_t * self = MP_OBJ_TO_PTR (self_in );
240+
241+ if (!TASK_IS_DONE (self )) {
242+ mp_raise_msg (& mp_type_InvalidStateError , MP_ERROR_TEXT ("Result is not ready." ));
243+ return NULL ;
244+ }
245+
246+ // If `exception()` returns anything we raise that
247+ mp_obj_t exception_obj = task_exception (self_in );
248+ if (exception_obj != mp_const_none ) {
249+ nlr_raise (exception_obj );
250+ }
251+
252+ mp_obj_t data_obj = self -> data ;
253+
254+ // If not StopIteration, bail early
255+ if (!mp_obj_is_subclass_fast (MP_OBJ_FROM_PTR (mp_obj_get_type (data_obj )), MP_OBJ_FROM_PTR (& mp_type_StopIteration ))) {
256+ return mp_const_none ;
257+ }
258+
259+ return mp_obj_exception_get_value (data_obj );
260+ }
261+ STATIC MP_DEFINE_CONST_FUN_OBJ_1 (task_result_obj , task_result );
262+
263+ STATIC mp_obj_t task_cancelled (mp_obj_t self_in ) {
264+ mp_obj_task_t * self = MP_OBJ_TO_PTR (self_in );
265+
266+ if (!TASK_IS_DONE (self )) {
267+ // If task isn't done it can't possibly be cancelled, and would instead
268+ // be considered "cancelling" even if a cancel was requested until it
269+ // has fully completed.
270+ return mp_obj_new_bool (false);
271+ }
272+
273+ mp_obj_t data_obj = self -> data ;
274+
275+ return mp_obj_new_bool (mp_obj_is_subclass_fast (MP_OBJ_FROM_PTR (mp_obj_get_type (data_obj )), MP_OBJ_FROM_PTR (& mp_type_CancelledError )));
276+ }
277+ STATIC MP_DEFINE_CONST_FUN_OBJ_1 (task_cancelled_obj , task_cancelled );
278+
197279STATIC mp_obj_t task_cancel (mp_obj_t self_in ) {
198280 mp_obj_task_t * self = MP_OBJ_TO_PTR (self_in );
199281 // Check if task is already finished.
@@ -271,6 +353,21 @@ STATIC void task_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
271353 } else if (attr == MP_QSTR_get_coro ) {
272354 dest [0 ] = MP_OBJ_FROM_PTR (& task_get_coro_obj );
273355 dest [1 ] = self_in ;
356+ } else if (attr == MP_QSTR_set_result ) {
357+ dest [0 ] = MP_OBJ_FROM_PTR (& task_set_result_obj );
358+ dest [1 ] = self_in ;
359+ } else if (attr == MP_QSTR_result ) {
360+ dest [0 ] = MP_OBJ_FROM_PTR (& task_result_obj );
361+ dest [1 ] = self_in ;
362+ } else if (attr == MP_QSTR_set_exception ) {
363+ dest [0 ] = MP_OBJ_FROM_PTR (& task_set_exception_obj );
364+ dest [1 ] = self_in ;
365+ } else if (attr == MP_QSTR_exception ) {
366+ dest [0 ] = MP_OBJ_FROM_PTR (& task_exception_obj );
367+ dest [1 ] = self_in ;
368+ } else if (attr == MP_QSTR_cancelled ) {
369+ dest [0 ] = MP_OBJ_FROM_PTR (& task_cancelled_obj );
370+ dest [1 ] = self_in ;
274371 }
275372 } else if (dest [1 ] != MP_OBJ_NULL ) {
276373 // Store
@@ -285,9 +382,9 @@ STATIC void task_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
285382}
286383
287384STATIC mp_obj_t task_unary_op (mp_unary_op_t op , mp_obj_t o_in ) {
288- switch (op ) {
385+ switch (op ) {
289386 case MP_UNARY_OP_HASH :
290- return MP_OBJ_NEW_SMALL_INT ((mp_uint_t ) o_in );
387+ return MP_OBJ_NEW_SMALL_INT ((mp_uint_t )o_in );
291388 default :
292389 return MP_OBJ_NULL ; // op not supported
293390 }
@@ -352,6 +449,8 @@ STATIC const mp_rom_map_elem_t mp_module_asyncio_globals_table[] = {
352449 { MP_ROM_QSTR (MP_QSTR___name__ ), MP_ROM_QSTR (MP_QSTR__asyncio ) },
353450 { MP_ROM_QSTR (MP_QSTR_TaskQueue ), MP_ROM_PTR (& task_queue_type ) },
354451 { MP_ROM_QSTR (MP_QSTR_Task ), MP_ROM_PTR (& task_type ) },
452+ { MP_ROM_QSTR (MP_QSTR_CancelledError ), MP_ROM_PTR (& mp_type_CancelledError ) },
453+ { MP_ROM_QSTR (MP_QSTR_InvalidStateError ), MP_ROM_PTR (& mp_type_InvalidStateError ) },
355454};
356455STATIC MP_DEFINE_CONST_DICT (mp_module_asyncio_globals , mp_module_asyncio_globals_table );
357456
0 commit comments