diff --git a/src/hypercorn/asyncio/run.py b/src/hypercorn/asyncio/run.py index 09fec25..f5ef496 100644 --- a/src/hypercorn/asyncio/run.py +++ b/src/hypercorn/asyncio/run.py @@ -228,9 +228,17 @@ def _run( shutdown_trigger: Callable[..., Awaitable[None]] | None = None, loop_factory: Callable[[], asyncio.AbstractEventLoop] | None = None, ) -> None: + async def wrapped( + shutdown_trigger: Callable[..., Awaitable[None]] | None = None, + ) -> None: + # Python 3.14 may eager-start the Runner task. Yield so + # wait_for, timeout, and TaskGroup see a current_task(). + await asyncio.sleep(0) + await main(shutdown_trigger=shutdown_trigger) + with Runner(debug=debug, loop_factory=loop_factory) as runner: runner.get_loop().set_exception_handler(_exception_handler) - runner.run(main(shutdown_trigger=shutdown_trigger)) + runner.run(wrapped(shutdown_trigger=shutdown_trigger)) def _exception_handler(loop: asyncio.AbstractEventLoop, context: dict) -> None: diff --git a/tests/asyncio/test_run.py b/tests/asyncio/test_run.py new file mode 100644 index 0000000..86000c9 --- /dev/null +++ b/tests/asyncio/test_run.py @@ -0,0 +1,18 @@ +from __future__ import annotations + +import asyncio + +from hypercorn.asyncio.run import _run + + +def test_run_establishes_current_task() -> None: + seen: dict[str, object] = {} + + async def main(shutdown_trigger: object = None) -> None: + seen["task"] = asyncio.current_task() + await asyncio.wait_for(asyncio.sleep(0), timeout=1) + seen["wait_for_ok"] = True + + _run(main) + assert seen["task"] is not None + assert seen["wait_for_ok"] is True