Improve grpcio serializer/deserializer types (#14093)

This commit is contained in:
Robin McCorkell
2025-06-02 12:04:54 +01:00
committed by GitHub
parent 798f332afa
commit 33fb34fa74
2 changed files with 48 additions and 74 deletions
+30 -53
View File
@@ -11,18 +11,11 @@ from . import aio as aio
__version__: str
# This class encodes an uninhabited type, requiring use of explicit casts or ignores
# in order to satisfy type checkers. This allows grpc-stubs to add proper stubs
# later, allowing those overrides to be removed.
# The alternative is Any, but a future replacement of Any with a proper type
# would result in type errors where previously the type checker was happy, which
# we want to avoid. Forcing the user to use overrides provides forwards-compatibility.
@type_check_only
class _PartialStubMustCastOrIgnore: ...
_T = TypeVar("_T")
# XXX: Early attempts to tame this used literals for all the keys (gRPC is
# a bit segfaulty and doesn't adequately validate the option keys), but that
# didn't quite work out. Maybe it's something we can come back to?
# didn't quite work out. Maybe it's something we can come back to
_OptionKeyValue: TypeAlias = tuple[str, Any]
_Options: TypeAlias = Sequence[_OptionKeyValue]
@@ -45,24 +38,8 @@ _Metadata: TypeAlias = tuple[tuple[str, str | bytes], ...]
_TRequest = TypeVar("_TRequest")
_TResponse = TypeVar("_TResponse")
# XXX: These are probably the SerializeToTring/FromString pb2 methods, but
# this needs further investigation
@type_check_only
class _RequestSerializer(Protocol):
def __call__(self, *args: Any, **kwargs: Any) -> Any: ...
@type_check_only
class _RequestDeserializer(Protocol):
def __call__(self, *args: Any, **kwargs: Any) -> Any: ...
@type_check_only
class _ResponseSerializer(Protocol):
def __call__(self, *args: Any, **kwargs: Any) -> Any: ...
@type_check_only
class _ResponseDeserializer(Protocol):
def __call__(self, *args: Any, **kwargs: Any) -> Any: ...
_Serializer: TypeAlias = Callable[[_T], bytes]
_Deserializer: TypeAlias = Callable[[bytes], _T]
# Future Interfaces:
@@ -176,24 +153,24 @@ class _Behaviour(Protocol):
def unary_unary_rpc_method_handler(
behavior: _Behaviour,
request_deserializer: _RequestDeserializer | None = None,
response_serializer: _ResponseSerializer | None = None,
) -> RpcMethodHandler[Any, Any]: ...
request_deserializer: _Deserializer[_TRequest] | None = None,
response_serializer: _Serializer[_TResponse] | None = None,
) -> RpcMethodHandler[_TRequest, _TResponse]: ...
def unary_stream_rpc_method_handler(
behavior: _Behaviour,
request_deserializer: _RequestDeserializer | None = None,
response_serializer: _ResponseSerializer | None = None,
) -> RpcMethodHandler[Any, Any]: ...
request_deserializer: _Deserializer[_TRequest] | None = None,
response_serializer: _Serializer[_TResponse] | None = None,
) -> RpcMethodHandler[_TRequest, _TResponse]: ...
def stream_unary_rpc_method_handler(
behavior: _Behaviour,
request_deserializer: _RequestDeserializer | None = None,
response_serializer: _ResponseSerializer | None = None,
) -> RpcMethodHandler[Any, Any]: ...
request_deserializer: _Deserializer[_TRequest] | None = None,
response_serializer: _Serializer[_TResponse] | None = None,
) -> RpcMethodHandler[_TRequest, _TResponse]: ...
def stream_stream_rpc_method_handler(
behavior: _Behaviour,
request_deserializer: _RequestDeserializer | None = None,
response_serializer: _ResponseSerializer | None = None,
) -> RpcMethodHandler[Any, Any]: ...
request_deserializer: _Deserializer[_TRequest] | None = None,
response_serializer: _Serializer[_TResponse] | None = None,
) -> RpcMethodHandler[_TRequest, _TResponse]: ...
def method_handlers_generic_handler(
service: str, method_handlers: dict[str, RpcMethodHandler[Any, Any]]
) -> GenericRpcHandler[Any, Any]: ...
@@ -250,32 +227,32 @@ class Channel(abc.ABC):
def stream_stream(
self,
method: str,
request_serializer: _RequestSerializer | None = None,
response_deserializer: _ResponseDeserializer | None = None,
) -> StreamStreamMultiCallable[Any, Any]: ...
request_serializer: _Serializer[_TRequest] | None = None,
response_deserializer: _Deserializer[_TResponse] | None = None,
) -> StreamStreamMultiCallable[_TRequest, _TResponse]: ...
@abc.abstractmethod
def stream_unary(
self,
method: str,
request_serializer: _RequestSerializer | None = None,
response_deserializer: _ResponseDeserializer | None = None,
) -> StreamUnaryMultiCallable[Any, Any]: ...
request_serializer: _Serializer[_TRequest] | None = None,
response_deserializer: _Deserializer[_TResponse] | None = None,
) -> StreamUnaryMultiCallable[_TRequest, _TResponse]: ...
@abc.abstractmethod
def subscribe(self, callback: Callable[[ChannelConnectivity], None], try_to_connect: bool = False) -> None: ...
@abc.abstractmethod
def unary_stream(
self,
method: str,
request_serializer: _RequestSerializer | None = None,
response_deserializer: _ResponseDeserializer | None = None,
) -> UnaryStreamMultiCallable[Any, Any]: ...
request_serializer: _Serializer[_TRequest] | None = None,
response_deserializer: _Deserializer[_TResponse] | None = None,
) -> UnaryStreamMultiCallable[_TRequest, _TResponse]: ...
@abc.abstractmethod
def unary_unary(
self,
method: str,
request_serializer: _RequestSerializer | None = None,
response_deserializer: _ResponseDeserializer | None = None,
) -> UnaryUnaryMultiCallable[Any, Any]: ...
request_serializer: _Serializer[_TRequest] | None = None,
response_deserializer: _Deserializer[_TResponse] | None = None,
) -> UnaryUnaryMultiCallable[_TRequest, _TResponse]: ...
@abc.abstractmethod
def unsubscribe(self, callback: Callable[[ChannelConnectivity], None]) -> None: ...
def __enter__(self) -> Self: ...
@@ -499,10 +476,10 @@ class RpcMethodHandler(abc.ABC, Generic[_TRequest, _TResponse]):
response_streaming: bool
# XXX: not clear from docs whether this is optional or not
request_deserializer: _RequestDeserializer | None
request_deserializer: _Deserializer[_TRequest] | None
# XXX: not clear from docs whether this is optional or not
response_serializer: _ResponseSerializer | None
response_serializer: _Serializer[_TResponse] | None
unary_unary: Callable[[_TRequest, ServicerContext], _TResponse] | None
+18 -21
View File
@@ -74,11 +74,8 @@ def server(
# Channel Object:
# XXX: The docs suggest these type signatures for aio, but not for non-async,
# and it's unclear why;
# https://grpc.github.io/grpc/python/grpc_asyncio.html#grpc.aio.Channel.stream_stream
_RequestSerializer: TypeAlias = Callable[[Any], bytes]
_ResponseDeserializer: TypeAlias = Callable[[bytes], Any]
_Serializer: TypeAlias = Callable[[_T], bytes]
_Deserializer: TypeAlias = Callable[[bytes], _T]
class Channel(abc.ABC):
@abc.abstractmethod
@@ -91,30 +88,30 @@ class Channel(abc.ABC):
def stream_stream(
self,
method: str,
request_serializer: _RequestSerializer | None = None,
response_deserializer: _ResponseDeserializer | None = None,
) -> StreamStreamMultiCallable[Any, Any]: ...
request_serializer: _Serializer[_TRequest] | None = None,
response_deserializer: _Deserializer[_TResponse] | None = None,
) -> StreamStreamMultiCallable[_TRequest, _TResponse]: ...
@abc.abstractmethod
def stream_unary(
self,
method: str,
request_serializer: _RequestSerializer | None = None,
response_deserializer: _ResponseDeserializer | None = None,
) -> StreamUnaryMultiCallable[Any, Any]: ...
request_serializer: _Serializer[_TRequest] | None = None,
response_deserializer: _Deserializer[_TResponse] | None = None,
) -> StreamUnaryMultiCallable[_TRequest, _TResponse]: ...
@abc.abstractmethod
def unary_stream(
self,
method: str,
request_serializer: _RequestSerializer | None = None,
response_deserializer: _ResponseDeserializer | None = None,
) -> UnaryStreamMultiCallable[Any, Any]: ...
request_serializer: _Serializer[_TRequest] | None = None,
response_deserializer: _Deserializer[_TResponse] | None = None,
) -> UnaryStreamMultiCallable[_TRequest, _TResponse]: ...
@abc.abstractmethod
def unary_unary(
self,
method: str,
request_serializer: _RequestSerializer | None = None,
response_deserializer: _ResponseDeserializer | None = None,
) -> UnaryUnaryMultiCallable[Any, Any]: ...
request_serializer: _Serializer[_TRequest] | None = None,
response_deserializer: _Deserializer[_TResponse] | None = None,
) -> UnaryUnaryMultiCallable[_TRequest, _TResponse]: ...
@abc.abstractmethod
async def __aenter__(self) -> Self: ...
@abc.abstractmethod
@@ -299,8 +296,8 @@ class InterceptedUnaryUnaryCall(_InterceptedCall[_TRequest, _TResponse], metacla
wait_for_ready: bool | None,
channel: Channel,
method: bytes,
request_serializer: _RequestSerializer,
response_deserializer: _ResponseDeserializer,
request_serializer: _Serializer[_TRequest],
response_deserializer: _Deserializer[_TResponse],
loop: asyncio.AbstractEventLoop,
) -> None: ...
@@ -314,8 +311,8 @@ class InterceptedUnaryUnaryCall(_InterceptedCall[_TRequest, _TResponse], metacla
credentials: CallCredentials | None,
wait_for_ready: bool | None,
request: _TRequest,
request_serializer: _RequestSerializer,
response_deserializer: _ResponseDeserializer,
request_serializer: _Serializer[_TRequest],
response_deserializer: _Deserializer[_TResponse],
) -> UnaryUnaryCall[_TRequest, _TResponse]: ...
def time_remaining(self) -> float | None: ...