gh-125862: Context decorator support for generators and async functions#136212
gh-125862: Context decorator support for generators and async functions#136212agronholm wants to merge 24 commits intopython:mainfrom
Conversation
|
Ack. WASI tests are failing because I used asyncio. Gotta work around that. |
|
@ambv I recall that back in July in Prague you said you'd take a look at this PR, yes? Would now be a good time? |
|
This PR is stale because it has been open for 30 days with no activity. |
…zy import inspect
ContextDecorator's generator wrapper now uses ``return (yield from gen)`` so a wrapped generator's StopIteration value is not lost. Tests: drop the unused run_test() helper, normalize quote style, and add exception-path and early-close coverage for the new generator and async generator wrappers so closing()/aclosing() behavior is exercised.
Add versionchanged notes to ContextDecorator and AsyncContextDecorator describing the new behavior when decorating generator, coroutine, and async generator functions, and call out that asend()/athrow() are not forwarded through the async generator wrapper. Reword the AsyncContextDecorator intro now that synchronous callables are accepted.
|
I'm testing this out. It is technically a behavior change so I want to understand if this is strictly a buggy behavior fix that nothing would've relied on, or something we'll need a backward compatibility with the prior behavior story for. |
|
okay, I analyzed things. First, a datapoint, we've been using a monkeypatch style equivalent to this PR on our contextlib decorators internally at work across O(NNNN) uses for ~6 months without issue. among other uses that don't use that fixed variant, some re-invent their own correct versions and could be cleaned up, and a few have been silently buggy. The contextlib behavior before this PR is that the context manager exits before any line of the decorated body runs. Not semantically something code can usefully depend on. There is nothing to deprecate because the decorator was effectively a no-op on these function kinds. There are open issues for |
State the primary use (coroutine and async generator functions) up front and move the synchronous-input behavior into a note that points users at ContextDecorator when the calling convention change is not wanted.
The early-stop tests asserted ordering with comments that named closing() and aclosing() as the reason; restate as the invariant being tested so the comments stay correct if the implementation changes.
The sync generator wrapper uses ``yield from`` so .send() and .throw() reach the wrapped generator; lock that in. The async generator wrapper re-yields with ``async for`` so asend()/athrow() do not reach the wrapped generator; pin that documented behavior so a future change that starts forwarding will fail and prompt a doc update.
contextlib.ContextDecoratorsupport for generators and async functions #125862