-
-
Notifications
You must be signed in to change notification settings - Fork 32.4k
Description
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
-
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
Labels
Projects
Status