Fix @noreentry decorator breaking static type-checking of decorated methods — Closes #183#184
Merged
conradbzura merged 1 commit intowool-labs:masterfrom Apr 23, 2026
Conversation
Without a type annotation, static type-checkers inferred the return type of noreentry as NoReentryBoundMethod. Methods decorated with @noreentry — including WorkerPool.__aenter__ and WorkerProxy.__aenter__ — were therefore reported as not matching the AsyncContextManager protocol, producing spurious errors on every async with call site. Typing noreentry as Callable[P, R] -> Callable[P, R] preserves the wrapped callable's signature so the checker continues to see the original async method.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Annotate
noreentrywith a pass-through generic signature so Pyright/Pylance preserve the wrapped callable's type through the decorator. Previously the decorator returned an un-annotatedNoReentryBoundMethodinstance, so type-checkers inferred decorated attributes as the descriptor type and flaggedasync with WorkerPool(): ...andasync with WorkerProxy(...): ...as not satisfying theAsyncContextManagerprotocol. The descriptor's__get__already returns the correct async wrapper at runtime — the fix is purely a type-hint change with no behavioral impact.Closes #183
Proposed changes
wool/src/wool/utilities/noreentry.pyType
noreentryasCallable[P, R] -> Callable[P, R]using aParamSpecandTypeVar. TheNoReentryBoundMethod(fn)return is suppressed with# type: ignore[return-value]since the descriptor is invoked through__get__at access time and produces a callable matching the declared signature. No runtime logic changes.Test cases
No new tests. The change is a pure type annotation — runtime behavior, including the single-use guard semantics, is unchanged and already covered by the existing
noreentrysuite. The regression is observable only to static type-checkers.