You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[grpcio] Type async handler factories and mixed aio interceptor chains - #16580
Builds on @wolfgang-aura's work in #16461, extending it to handler factories and registration while accounting for synchronous handlers in aio interceptor chains.
An aio server can run both synchronous and asynchronous handlers. Its interceptor continuation returns the original handler without adapting its behavior, so the return type must allow both. Synchronous handlers are dispatched through a thread pool.
This PR:
Adds async overloads for all four RPC handler factories, including streaming handlers that use context.write().
Preserves handler types through generic handler registration, with synchronous defaults for existing users.
Accepts both handler types in aio generic and registered method handlers.
Types aio interceptor continuations and return values as synchronous or asynchronous handlers.
Adds regression cases for factory inference, custom generic handlers, mixed registration, and an interceptor that checks the handler before awaiting it.
The private, type-check-only _AsyncRpcMethodHandler follows the naming guidance from the review of #15497.
Support async factories, generic and registered handlers, and mixed
sync/async interceptor continuations while retaining sync defaults.
Builds on the async handler helper introduced by wolfgang-aura in
python#16461, with a mixed-handler continuation contract.
Prefer synchronous signatures when a response serializer is supplied.
Keep callbacks with insufficient type information gradual instead of
inferring an incorrect synchronous or asynchronous handler type.
Cover all four factories, keyword serializers, raw callbacks, and
partially annotated async behaviors in regression tests.
Apply the gradual overload to optional response serializers in all four
factories so Any-typed synchronous callbacks remain registrable.
Cover optional codecs and keyword serializers without contextual handler
types, and preserve precise inference for explicitly typed aio callbacks.
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
Factory overloads can erase synchronous handler types or misclassify asynchronous callbacks as synchronous.
No open issues 🎉
2 previously missed issues
In code that hasn't changed since last review
Serializer overload misclassifies asynchronous callbacks as synchronous
stubs/grpcio/grpc/__init__.pyi:166
A non-None serializer does not always distinguish synchronous from asynchronous callbacks. Calling this factory with the test's partial_async_unary and a Callable[[object], bytes] serializer matches this first synchronous overload: the callback accepts the synchronous context through Any, and _TResponse can accommodate its coroutine return. The result is classified as RpcMethodHandler, incorrectly allowing synchronous-server registration. The positional and keyword-only overloads have this problem; stream_unary_rpc_method_handler also has it when both callback inputs are typed Any. Handle awaitable-returning ambiguity before these synchronous overloads, retaining an unknown handler type where necessary without regressing Any-returning synchronous callbacks. Add regression cases using a serializer that accepts object.
Any fallback misclassifies synchronous callbacks without codecs
stubs/grpcio/grpc/__init__.pyi:173
The Any fallback also matches unambiguously synchronous callbacks. For example, a callback annotated (bytes, grpc.ServicerContext) -> bytes, passed without codecs, now returns Any instead of retaining the RpcMethodHandler interface. This disables checks on subsequent handler use. The corresponding overloads in all four factories have the same problem, including when the serializer is optional. Restrict these ambiguity overloads to callbacks accepting both context types, for example by using ServicerContext | aio.ServicerContext[_TRequest, _TResponse] for their context parameter, so synchronous-only callbacks reach the typed fallback. Add regression assertions for fully annotated synchronous callbacks without codecs.
Limit gradual inference to callbacks that accept both sync and aio inputs.
Keep typed synchronous handlers precise without codecs, and avoid treating
coroutines as synchronous responses when serializers accept object.
Remove serializer-specific overloads and cover both review regressions.
Diff from mypy_primer, showing the effect of this PR on open source code:
sphinx (https://github.com/sphinx-doc/sphinx)
- sphinx/builders/_epub_base.py:34:1: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports
This branch has not been deployed
No deployments
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
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.
Fixes #15495.
Closes #16461.
Builds on @wolfgang-aura's work in #16461, extending it to handler factories and registration while accounting for synchronous handlers in aio interceptor chains.
An aio server can run both synchronous and asynchronous handlers. Its interceptor continuation returns the original handler without adapting its behavior, so the return type must allow both. Synchronous handlers are dispatched through a thread pool.
This PR:
context.write().The private, type-check-only
_AsyncRpcMethodHandlerfollows the naming guidance from the review of #15497.Runtime references: