diff options
author | Damien George <damien@micropython.org> | 2024-01-19 10:07:51 +1100 |
---|---|---|
committer | Damien George <damien@micropython.org> | 2024-01-22 12:03:21 +1100 |
commit | 2ecbad4e91192c88f831d8690dbad31ddba72135 (patch) | |
tree | 05700d7e5ba462c58b92885e72911c0d8e4465e8 /tests/extmod/asyncio_gather_finished_early.py | |
parent | 51fbec2780b9c095c7eabdabab043c30dbb99d1d (diff) | |
download | micropython-2ecbad4e91192c88f831d8690dbad31ddba72135.tar.gz micropython-2ecbad4e91192c88f831d8690dbad31ddba72135.zip |
extmod/asyncio: Support gather of tasks that finish early.
Adds support to asyncio.gather() for the case that one or more (or all)
sub-tasks finish and/or raise an exception before the gather starts.
Signed-off-by: Damien George <damien@micropython.org>
Diffstat (limited to 'tests/extmod/asyncio_gather_finished_early.py')
-rw-r--r-- | tests/extmod/asyncio_gather_finished_early.py | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/tests/extmod/asyncio_gather_finished_early.py b/tests/extmod/asyncio_gather_finished_early.py new file mode 100644 index 0000000000..030e79e357 --- /dev/null +++ b/tests/extmod/asyncio_gather_finished_early.py @@ -0,0 +1,65 @@ +# Test asyncio.gather() when a task is already finished before the gather starts. + +try: + import asyncio +except ImportError: + print("SKIP") + raise SystemExit + + +# CPython and MicroPython differ in when they signal (and print) that a task raised an +# uncaught exception. So define an empty custom_handler() to suppress this output. +def custom_handler(loop, context): + pass + + +async def task_that_finishes_early(id, event, fail): + print("task_that_finishes_early", id) + event.set() + if fail: + raise ValueError("intentional exception", id) + + +async def task_that_runs(): + for i in range(5): + print("task_that_runs", i) + await asyncio.sleep(0) + + +async def main(start_task_that_runs, task_fail, return_exceptions): + print("== start", start_task_that_runs, task_fail, return_exceptions) + + # Set exception handler to suppress exception output. + loop = asyncio.get_event_loop() + loop.set_exception_handler(custom_handler) + + # Create tasks. + event_a = asyncio.Event() + event_b = asyncio.Event() + tasks = [] + if start_task_that_runs: + tasks.append(asyncio.create_task(task_that_runs())) + tasks.append(asyncio.create_task(task_that_finishes_early("a", event_a, task_fail))) + tasks.append(asyncio.create_task(task_that_finishes_early("b", event_b, task_fail))) + + # Make sure task_that_finishes_early() are both done, before calling gather(). + await event_a.wait() + await event_b.wait() + + # Gather the tasks. + try: + result = "complete", await asyncio.gather(*tasks, return_exceptions=return_exceptions) + except Exception as er: + result = "exception", er, start_task_that_runs and tasks[0].done() + + # Wait for the final task to finish (if it was started). + if start_task_that_runs: + await tasks[0] + + # Print results. + print(result) + + +# Run the test in the 8 different combinations of its arguments. +for i in range(8): + asyncio.run(main(bool(i & 4), bool(i & 2), bool(i & 1))) |