@@ -396,6 +396,75 @@ async def trio_task():
396
396
assert fut .cancelled ()
397
397
398
398
399
+ @pytest .mark .trio
400
+ async def test_trio_as_fut_throws_after_cancelled ():
401
+ """If a trio_as_future() future is cancelled, any exception
402
+ thrown by the Trio task as it unwinds is ignored. (This is
403
+ somewhat infelicitous, but the asyncio Future API doesn't allow
404
+ a future to go from cancelled to some other outcome.)
405
+ """
406
+
407
+ async def trio_task ():
408
+ try :
409
+ await trio .sleep_forever ()
410
+ finally :
411
+ raise ValueError ("hi" )
412
+
413
+ async with trio_asyncio .open_loop () as loop :
414
+ fut = loop .trio_as_future (trio_task )
415
+ await trio .testing .wait_all_tasks_blocked ()
416
+ fut .cancel ()
417
+ with pytest .raises (asyncio .CancelledError ):
418
+ await fut
419
+
420
+
421
+ @pytest .mark .trio
422
+ async def test_run_trio_task_errors (monkeypatch ):
423
+ async with trio_asyncio .open_loop () as loop :
424
+ # Test never getting to start the task
425
+ handle = loop .run_trio_task (trio .sleep_forever )
426
+ handle .cancel ()
427
+
428
+ # Test cancelling the task
429
+ handle = loop .run_trio_task (trio .sleep_forever )
430
+ await trio .testing .wait_all_tasks_blocked ()
431
+ handle .cancel ()
432
+
433
+ # Helper for the rest of this test, which covers cases where
434
+ # the Trio task raises an exception
435
+ async def raise_in_aio_loop (exc ):
436
+ async def raise_it ():
437
+ raise exc
438
+
439
+ async with trio_asyncio .open_loop () as loop :
440
+ loop .run_trio_task (raise_it )
441
+
442
+ # We temporarily modify the default exception handler to collect
443
+ # the exceptions instead of logging or raising them
444
+
445
+ exceptions = []
446
+
447
+ def collect_exceptions (loop , context ):
448
+ if context .get ("exception" ):
449
+ exceptions .append (context ["exception" ])
450
+ else :
451
+ exceptions .append (RuntimeError (context .get ("message" ) or "unknown" ))
452
+
453
+ monkeypatch .setattr (
454
+ trio_asyncio .TrioEventLoop , "default_exception_handler" , collect_exceptions
455
+ )
456
+ expected = [
457
+ ValueError ("hi" ), ValueError ("lo" ), KeyError (), IndexError ()
458
+ ]
459
+ await raise_in_aio_loop (expected [0 ])
460
+ with pytest .raises (SystemExit ):
461
+ await raise_in_aio_loop (SystemExit (0 ))
462
+ with pytest .raises (SystemExit ):
463
+ await raise_in_aio_loop (trio .MultiError ([expected [1 ], SystemExit ()]))
464
+ await raise_in_aio_loop (trio .MultiError (expected [2 :]))
465
+ assert exceptions == expected
466
+
467
+
399
468
@pytest .mark .trio
400
469
@pytest .mark .skipif (sys .version_info < (3 , 7 ), reason = "needs asyncio contextvars" )
401
470
async def test_contextvars ():
0 commit comments