fix: preserve function node middleware type inference - #1558
Open
Lpk124 wants to merge 2 commits into
Open
Conversation
Retry, Timeout, MaxCalls, and Lock subclassed the bare Middleware generic, which mypy resolved as Middleware[Never, Never] under invariant ParamSpec generics. Combining any two in a single middleware= list caused _P to collapse to Never, producing a (*Never, **Never) mismatch against the decorated function's real signature. Two changes together fix this: 1. Parameterize the four classes as Middleware[Any, Any] so the list element type unifies to Middleware[Any, Any] instead of Never. 2. In the function_node overload for func=None (the parametrized- decorator form), use Iterable[Middleware[Any, Any]] instead of Iterable[Middleware[_P, _TOutput]] so _P is not constrained by the middleware list and is instead inferred from the decorated function. Adds two regression tests combining multiple prebuilt middleware in one list, and a docs/scripts example that CI mypy-checks. Fixes RailtownAI#1538 Signed-off-by: Christian-Sidak <61099993+Christian-Sidak@users.noreply.github.com>
Carry middleware signature constraints separately from runtime generic slots so slot-agnostic middleware defers inference while verifier signatures remain checked. Add positive and negative mypy coverage for empty, reusable, mixed, async, and direct function node forms.
4 tasks
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
Fixes #1538.
Retry,Timeout,MaxCalls, andLockcan wrap any node signature, so this keeps theirMiddleware[Any, Any]parameterization from #1541. The decorator-factory overload still needs to defer inference until it receives the decorated function without losing the signature checks from verifier and custom middleware.This patch carries that signature constraint separately from the middleware's runtime parameter and return slots. The prebuilt middleware uses an unconstrained carrier; signature-aware middleware keeps its parameter and output constraints.
function_node(...)returns a private overloaded callable protocol, which preserves the exact sync or async function signature.The regression fixture covers empty factories, reusable prebuilt lists, mixed verifier lists, async functions, direct calls, and deliberately invalid verifier signatures.
docs_validation.shnow uses--warn-unused-ignores, so widening the factory back toAnymakes the negative cases fail CI.Type of change
Checklist
ruff check .andruff format --check .)Notes
The first commit is Christian-Sidak's work from #1541 with the original authorship preserved. The follow-up commit replaces the factory-wide
Anyannotation with the constraint carrier and adds the static coverage.Local checks:
docs/scriptsdocs/scripts/function_node_typing.pygit diff --check