Skip to content

Regression: unittest.IsolatedAsyncioTestCase in 3.11 is too picky about what it will run with the event loop #101486

@zware

Description

@zware

In previous versions, _callMaybeAsync(self, func, /, *args, **kwargs) would run result = func(*args, **kwargs) and then run the result with the event loop if inspect.isawaitable(result) returned True. In 3.11 inspect.iscoroutinefunction(func) is checked ahead of time instead, resulting in a warning about a coroutine not being awaited after trying to run func(*args, **kwargs) synchronously. This prevents using anything other than an async def-defined coroutine for test methods or cleanup functions1, the latter of which may not be defined in local code. This can be worked around by wrapping any known awaitable in a dummy async def _wrapper(aw): return await aw, but that's rather inconvenient and not a pleasant UX.

I have a "fix" for this that I don't consider to be viable that I'll nevertheless attach as a draft PR for discussion. It gives the behavior I would prefer to see in unittest and passes all existing tests, but relies on an ugly hack in asyncio to defeat the non-reentrancy of contextvars.Context.run. Ideally, either Context.run would allow recursive calls (by not running the entrance and exit routines if the context is already entered?), or would expose the underlying ctx_entered flag to allow LBYL when calling Context.run. I don't have a great understanding of contextvars, so I'm not sure how any of these options might break things or if there's a better option that's obvious to someone who knows what's going on here :)

Linked PRs

Footnotes

  1. which when initially added explicitly supported exotic awaitables, see https://github.com/python/cpython/blob/76efcb40930d1584e8706f015d0e5475fb16acb5/Lib/unittest/async_case.py#L53-L58

Metadata

Metadata

Assignees

No one assigned

    Labels

    3.11only security fixes3.12only security fixesstdlibPython modules in the Lib dirtopic-asynciotype-bugAn unexpected behavior, bug, or error

    Projects

    Status

    Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions