diff --git a/docs/library/uasyncio.rst b/docs/library/uasyncio.rst index 0f363a076e..31b38a4e05 100644 --- a/docs/library/uasyncio.rst +++ b/docs/library/uasyncio.rst @@ -74,6 +74,12 @@ Additional functions This is a coroutine. +.. function:: wait_for_ms(awaitable, timeout) + + Similar to `wait_for` but *timeout* is an integer in milliseconds. + + This is a coroutine, and a MicroPython extension. + .. function:: gather(\*awaitables, return_exceptions=False) Run all *awaitables* concurrently. Any *awaitables* that are not tasks are diff --git a/extmod/uasyncio/__init__.py b/extmod/uasyncio/__init__.py index da8b58061e..08f924cf29 100644 --- a/extmod/uasyncio/__init__.py +++ b/extmod/uasyncio/__init__.py @@ -7,6 +7,7 @@ __version__ = (3, 0, 0) _attrs = { "wait_for": "funcs", + "wait_for_ms": "funcs", "gather": "funcs", "Event": "event", "Lock": "lock", diff --git a/extmod/uasyncio/funcs.py b/extmod/uasyncio/funcs.py index 7a4bddf256..6e1305c94f 100644 --- a/extmod/uasyncio/funcs.py +++ b/extmod/uasyncio/funcs.py @@ -4,16 +4,16 @@ from . import core -async def wait_for(aw, timeout): +async def wait_for(aw, timeout, sleep=core.sleep): aw = core._promote_to_task(aw) if timeout is None: return await aw - def cancel(aw, timeout): - await core.sleep(timeout) + def cancel(aw, timeout, sleep): + await sleep(timeout) aw.cancel() - cancel_task = core.create_task(cancel(aw, timeout)) + cancel_task = core.create_task(cancel(aw, timeout, sleep)) try: ret = await aw except core.CancelledError: @@ -29,6 +29,10 @@ async def wait_for(aw, timeout): return ret +def wait_for_ms(aw, timeout): + return wait_for(aw, timeout, core.sleep_ms) + + async def gather(*aws, return_exceptions=False): ts = [core._promote_to_task(aw) for aw in aws] for i in range(len(ts)): diff --git a/tests/extmod/uasyncio_micropython.py b/tests/extmod/uasyncio_micropython.py new file mode 100644 index 0000000000..69e5fa3224 --- /dev/null +++ b/tests/extmod/uasyncio_micropython.py @@ -0,0 +1,37 @@ +# Test MicroPython extensions on CPython asyncio: +# - sleep_ms +# - wait_for_ms + +try: + import utime, uasyncio +except ImportError: + print("SKIP") + raise SystemExit + + +async def task(id, t): + print("task start", id) + await uasyncio.sleep_ms(t) + print("task end", id) + return id * 2 + + +async def main(): + # Simple sleep_ms + t0 = utime.ticks_ms() + await uasyncio.sleep_ms(1) + print(utime.ticks_diff(utime.ticks_ms(), t0) < 100) + + # When task finished before the timeout + print(await uasyncio.wait_for_ms(task(1, 5), 50)) + + # When timeout passes and task is cancelled + try: + print(await uasyncio.wait_for_ms(task(2, 50), 5)) + except uasyncio.TimeoutError: + print("timeout") + + print("finish") + + +uasyncio.run(main()) diff --git a/tests/extmod/uasyncio_micropython.py.exp b/tests/extmod/uasyncio_micropython.py.exp new file mode 100644 index 0000000000..f5be1dc75a --- /dev/null +++ b/tests/extmod/uasyncio_micropython.py.exp @@ -0,0 +1,7 @@ +True +task start 1 +task end 1 +2 +task start 2 +timeout +finish