Skip to content

Fix grpc aio handler typing#15497

Open
XiaXia009 wants to merge 7 commits intopython:mainfrom
XiaXia009:fix-grpc-aio-handler
Open

Fix grpc aio handler typing#15497
XiaXia009 wants to merge 7 commits intopython:mainfrom
XiaXia009:fix-grpc-aio-handler

Conversation

@XiaXia009
Copy link

Hi there, this is my first contribution to typeshed.
This PR is related to #15495

Fix typing for aio ServerInterceptor continuation.

grpc.aio.ServerInterceptor.intercept_service should return
grpc.aio.RpcMethodHandler instead of grpc.RpcMethodHandler.

The current stub references the synchronous handler type, which is
incorrect for the aio API.

This PR updates:

  • the return type of the continuation callable
  • the return type of intercept_service
  • the tests to cover aio handler callables

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@XiaXia009 XiaXia009 marked this pull request as draft March 9, 2026 17:45
@XiaXia009 XiaXia009 marked this pull request as ready for review March 9, 2026 18:24
@github-actions
Copy link
Contributor

github-actions bot commented Mar 9, 2026

According to mypy_primer, this change has no effect on the checked open source code. 🤖🎉

@XiaXia009
Copy link
Author

Sorry for the multiple commits. Some of the CI errors were not reproducible in my local environment, so I had to rely on GitHub Actions to verify the fixes.🥹

Copy link
Collaborator

@srittau srittau left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Some notes below.

Comment on lines +37 to +43
aio_handler = cast(grpc.aio.RpcMethodHandler[bytes, bytes], object())
aio_handler.unary_unary = cast(Callable[[bytes, grpc.aio.ServicerContext[bytes, bytes]], Awaitable[bytes]], None)
aio_handler.unary_stream = cast(Callable[[bytes, grpc.aio.ServicerContext[bytes, bytes]], AsyncIterator[bytes]], None)
aio_handler.stream_unary = cast(Callable[[AsyncIterator[bytes], grpc.aio.ServicerContext[bytes, bytes]], Awaitable[bytes]], None)
aio_handler.stream_stream = cast(
Callable[[AsyncIterator[bytes], grpc.aio.ServicerContext[bytes, bytes]], AsyncIterator[bytes]], None
)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

About tests: We only use tests for complex annotations. In this case, the tests basically replicate the type annotations, so we don't need them.

Comment on lines +373 to +374
@type_check_only
class RpcMethodHandler(Generic[_TRequest, _TResponse]):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apart from marking non-existing runtime types with @type_check_only, we also prefix them with an underscore to make it very obvious that something is "wrong" with this type to users. I would also like to add some explanation for why this type is here, and add Async to the name to clearly distinguish it from the "regular" RpcMethodHandler:

Suggested change
@type_check_only
class RpcMethodHandler(Generic[_TRequest, _TResponse]):
# Async version of gprc.RpcMethodHandler. As opposed to the former, this type
# does not exist at runtime.
@type_check_only
class _AsyncRpcMethodHandler(Generic[_TRequest, _TResponse]):

@srittau srittau linked an issue Mar 20, 2026 that may be closed by this pull request
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

grpc.aio.ServerInterceptor is incompatible with async RPC methods

2 participants