Skip to content

gh-125862: Context decorator support for generators and async functions#136212

Open
agronholm wants to merge 24 commits intopython:mainfrom
agronholm:fix-issue-125862
Open

gh-125862: Context decorator support for generators and async functions#136212
agronholm wants to merge 24 commits intopython:mainfrom
agronholm:fix-issue-125862

Conversation

@agronholm
Copy link
Copy Markdown
Contributor

@agronholm agronholm commented Jul 2, 2025

@agronholm
Copy link
Copy Markdown
Contributor Author

Ack. WASI tests are failing because I used asyncio. Gotta work around that.

Comment thread Lib/contextlib.py Outdated
@agronholm
Copy link
Copy Markdown
Contributor Author

@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?

@github-actions
Copy link
Copy Markdown

This PR is stale because it has been open for 30 days with no activity.

@github-actions github-actions Bot added the stale Stale PR or inactive for long period of time. label Apr 26, 2026
@gpshead gpshead self-assigned this Apr 27, 2026
gpshead added 7 commits April 27, 2026 22:39
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.
@gpshead gpshead requested a review from AA-Turner as a code owner April 27, 2026 23:41
@gpshead gpshead removed the stale Stale PR or inactive for long period of time. label Apr 27, 2026
@gpshead
Copy link
Copy Markdown
Member

gpshead commented Apr 27, 2026

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.

@gpshead
Copy link
Copy Markdown
Member

gpshead commented Apr 28, 2026

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. unittest.mock.patch already does this dispatch for coroutine functions (since 3.8). This brings ContextDecorator to parity and extends both patterns to generators and async generators.

There are open issues for unittest.mock.patch to expand to work decorating generators: gh-71528 & gh-88893.

gpshead added 3 commits April 28, 2026 04:39
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.
@gpshead gpshead enabled auto-merge (squash) April 28, 2026 05:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants