From 853cb172ff67a2b99c7871885ccc5afa8ceaddc8 Mon Sep 17 00:00:00 2001 From: Blake Williams Date: Wed, 27 Dec 2023 16:10:46 +1100 Subject: [PATCH 01/18] Import raw stubs from grpc-stubs package --- stubs/grpc/METADATA.toml | 6 + stubs/grpc/grpc/__init__.pyi | 791 ++++++++++++++++++ stubs/grpc/grpc/aio/__init__.pyi | 457 ++++++++++ stubs/grpc/grpc/aio/py.typed | 1 + stubs/grpc_channelz/METADATA.toml | 6 + .../grpc_channelz/grpc_channelz/__init__.pyi | 3 + .../grpc_channelz/v1/__init__.pyi | 3 + .../grpc_channelz/v1/_servicer.pyi | 32 + .../grpc_channelz/v1/channelz.pyi | 4 + stubs/grpc_health/METADATA.toml | 6 + stubs/grpc_health/grpc_health/__init__.pyi | 3 + stubs/grpc_health/grpc_health/v1/__init__.pyi | 3 + stubs/grpc_health/grpc_health/v1/health.pyi | 43 + stubs/grpc_reflection/METADATA.toml | 6 + .../grpc_reflection/__init__.pyi | 3 + .../grpc_reflection/v1alpha/__init__.pyi | 3 + .../grpc_reflection/v1alpha/reflection.pyi | 27 + stubs/grpc_status/METADATA.toml | 6 + stubs/grpc_status/grpc_status/__init__.pyi | 3 + stubs/grpc_status/grpc_status/rpc_status.pyi | 17 + 20 files changed, 1423 insertions(+) create mode 100644 stubs/grpc/METADATA.toml create mode 100644 stubs/grpc/grpc/__init__.pyi create mode 100644 stubs/grpc/grpc/aio/__init__.pyi create mode 100644 stubs/grpc/grpc/aio/py.typed create mode 100644 stubs/grpc_channelz/METADATA.toml create mode 100644 stubs/grpc_channelz/grpc_channelz/__init__.pyi create mode 100644 stubs/grpc_channelz/grpc_channelz/v1/__init__.pyi create mode 100644 stubs/grpc_channelz/grpc_channelz/v1/_servicer.pyi create mode 100644 stubs/grpc_channelz/grpc_channelz/v1/channelz.pyi create mode 100644 stubs/grpc_health/METADATA.toml create mode 100644 stubs/grpc_health/grpc_health/__init__.pyi create mode 100644 stubs/grpc_health/grpc_health/v1/__init__.pyi create mode 100644 stubs/grpc_health/grpc_health/v1/health.pyi create mode 100644 stubs/grpc_reflection/METADATA.toml create mode 100644 stubs/grpc_reflection/grpc_reflection/__init__.pyi create mode 100644 stubs/grpc_reflection/grpc_reflection/v1alpha/__init__.pyi create mode 100644 stubs/grpc_reflection/grpc_reflection/v1alpha/reflection.pyi create mode 100644 stubs/grpc_status/METADATA.toml create mode 100644 stubs/grpc_status/grpc_status/__init__.pyi create mode 100644 stubs/grpc_status/grpc_status/rpc_status.pyi diff --git a/stubs/grpc/METADATA.toml b/stubs/grpc/METADATA.toml new file mode 100644 index 000000000000..b81a42967303 --- /dev/null +++ b/stubs/grpc/METADATA.toml @@ -0,0 +1,6 @@ +version = "1.*" +upstream_repository = "https://github.com/grpc/grpc" +partial_stub = true + +[tool.stubtest] +ignore_missing_stub = true diff --git a/stubs/grpc/grpc/__init__.pyi b/stubs/grpc/grpc/__init__.pyi new file mode 100644 index 000000000000..13b2ba7a3e8d --- /dev/null +++ b/stubs/grpc/grpc/__init__.pyi @@ -0,0 +1,791 @@ +import enum +import threading +import typing +from concurrent import futures +from types import ModuleType, TracebackType + +__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 typing.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. +class _PartialStubMustCastOrIgnore: + pass + + +# 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? +_OptionKeyValue = typing.Tuple[str, typing.Any] +_Options = typing.Sequence[_OptionKeyValue] + + +class Compression(enum.IntEnum): + NoCompression = ... + Deflate = ... + Gzip = ... + + +@enum.unique +class LocalConnectionType(enum.Enum): + UDS = ... + LOCAL_TCP = ... + + +# XXX: not documented, needs more investigation. +# Some evidence: +# - https://github.com/grpc/grpc/blob/0e1984effd7e977ef18f1ad7fde7d10a2a153e1d/src/python/grpcio_tests/tests/unit/_metadata_test.py#L71 +# - https://github.com/grpc/grpc/blob/0e1984effd7e977ef18f1ad7fde7d10a2a153e1d/src/python/grpcio_tests/tests/unit/_metadata_test.py#L58 +# - https://github.com/grpc/grpc/blob/0e1984effd7e977ef18f1ad7fde7d10a2a153e1d/src/python/grpcio_tests/tests/unit/_invocation_defects_test.py#L66 +Metadata = typing.Tuple[ + typing.Tuple[str, typing.Union[str, bytes]], + ..., +] + + +"""Create Client""" + +def insecure_channel( + target: str, + options: typing.Optional[_Options] = None, + compression: typing.Optional[Compression] = None, +) -> Channel: + ... + + +def secure_channel( + target: str, + credentials: ChannelCredentials, + options: typing.Optional[_Options] = None, + compression: typing.Optional[Compression] = None, +) -> Channel: + ... + + +Interceptor = typing.Union[ + UnaryUnaryClientInterceptor, + UnaryStreamClientInterceptor, + StreamUnaryClientInterceptor, + StreamStreamClientInterceptor, +] + +def intercept_channel(channel: Channel, *interceptors: Interceptor) -> Channel: + ... + + +"""Create Client Credentials""" + +def ssl_channel_credentials( + root_certificates: typing.Optional[bytes] = None, + private_key: typing.Optional[bytes] = None, + certificate_chain: typing.Optional[bytes] = None, +) -> ChannelCredentials: + ... + +def local_channel_credentials( + local_connect_type: LocalConnectionType = LocalConnectionType.LOCAL_TCP, +) -> ChannelCredentials: + ... + +def metadata_call_credentials( + metadata_plugin: AuthMetadataPlugin, + name: typing.Optional[str] = None, +) -> CallCredentials: + ... + +def access_token_call_credentials(access_token: str) -> CallCredentials: + ... + +def alts_channel_credentials( + service_accounts: typing.Optional[typing.Sequence[str]] = None, +) -> ChannelCredentials: ... + +def compute_engine_channel_credentials() -> ChannelCredentials: ... + +def xds_channel_credentials( + fallback_credentials: typing.Optional[ChannelCredentials] = None, +) -> ChannelCredentials: ... + +# GRPC docs say there should be at least two: +def composite_call_credentials( + creds1: CallCredentials, + creds2: CallCredentials, + *rest: CallCredentials, +) -> CallCredentials: + ... + +# Compose a ChannelCredentials and one or more CallCredentials objects. +def composite_channel_credentials( + channel_credentials: ChannelCredentials, + call_credentials: CallCredentials, + *rest: CallCredentials, +) -> ChannelCredentials: + ... + + +"""Create Server""" + +def server( + thread_pool: futures.ThreadPoolExecutor, + handlers: typing.Optional[typing.List[GenericRpcHandler]] = None, + interceptors: typing.Optional[typing.List[ServerInterceptor]] = None, + options: typing.Optional[_Options] = None, + maximum_concurrent_rpcs: typing.Optional[int] = None, + compression: typing.Optional[Compression] = None, + xds: bool = False, +) -> Server: + ... + + +"""Create Server Credentials""" + +CertificateChainPair = typing.Tuple[bytes, bytes] + +def ssl_server_credentials( + private_key_certificate_chain_pairs: typing.List[CertificateChainPair], + root_certificates: typing.Optional[bytes] = None, + require_client_auth: bool = False, +) -> ServerCredentials: + ... + + +def local_server_credentials( + local_connect_type: LocalConnectionType = LocalConnectionType.LOCAL_TCP, +) -> ServerCredentials: + ... + + +def ssl_server_certificate_configuration( + private_key_certificate_chain_pairs: typing.List[CertificateChainPair], + root_certificates: typing.Optional[bytes] = None, +) -> ServerCertificateConfiguration: + ... + + +def dynamic_ssl_server_credentials( + initial_certificate_configuration: ServerCertificateConfiguration, + certificate_configuration_fetcher: typing.Callable[[], ServerCertificateConfiguration], + require_client_authentication: bool = False, +) -> ServerCredentials: + ... + +def alts_server_credentials() -> ServerCredentials: ... + +def insecure_server_credentials() -> ServerCredentials: ... + +def xds_server_credentials( + fallback_credentials: ServerCredentials, +) -> ServerCredentials: ... + +"""RPC Method Handlers""" + +# XXX: This is probably what appears in the add_FooServicer_to_server function +# in the _pb2_grpc files that get generated, which points to the FooServicer +# handler functions that get generated, which look like this: +# +# def FloobDoob(self, request, context): +# return response +# +Behaviour = typing.Callable + +# XXX: These are probably the SerializeToTring/FromString pb2 methods, but +# this needs further investigation +RequestDeserializer = typing.Callable +ResponseSerializer = typing.Callable + + +def unary_unary_rpc_method_handler( + behavior: Behaviour, + request_deserializer: typing.Optional[RequestDeserializer] = None, + response_serializer: typing.Optional[ResponseSerializer] = None, +) -> RpcMethodHandler: + ... + +def unary_stream_rpc_method_handler( + behavior: Behaviour, + request_deserializer: typing.Optional[RequestDeserializer] = None, + response_serializer: typing.Optional[ResponseSerializer] = None, +) -> RpcMethodHandler: + ... + +def stream_unary_rpc_method_handler( + behavior: Behaviour, + request_deserializer: typing.Optional[RequestDeserializer] = None, + response_serializer: typing.Optional[ResponseSerializer] = None, +) -> RpcMethodHandler: + ... + +def stream_stream_rpc_method_handler( + behavior: Behaviour, + request_deserializer: typing.Optional[RequestDeserializer] = None, + response_serializer: typing.Optional[ResponseSerializer] = None, +) -> RpcMethodHandler: + ... + +def method_handlers_generic_handler( + service: str, + method_handlers: typing.Dict[str, RpcMethodHandler], +) -> GenericRpcHandler: + ... + + +"""Channel Ready Future""" + +def channel_ready_future(channel: Channel) -> Future: + ... + + +"""Channel Connectivity""" + +class ChannelConnectivity(enum.Enum): + IDLE = ... + CONNECTING = ... + READY = ... + TRANSIENT_FAILURE = ... + SHUTDOWN = ... + + + +"""gRPC Status Code""" + +class Status: + code: StatusCode + + # XXX: misnamed property, does not align with status.proto, where it is called 'message': + details: str + + trailing_metadata: Metadata + + +# https://grpc.github.io/grpc/core/md_doc_statuscodes.html +class StatusCode(enum.Enum): + OK = ... + CANCELLED = ... + UNKNOWN = ... + INVALID_ARGUMENT = ... + DEADLINE_EXCEEDED = ... + NOT_FOUND = ... + ALREADY_EXISTS = ... + PERMISSION_DENIED = ... + RESOURCE_EXHAUSTED = ... + FAILED_PRECONDITION = ... + ABORTED = ... + OUT_OF_RANGE = ... + UNIMPLEMENTED = ... + INTERNAL = ... + UNAVAILABLE = ... + DATA_LOSS = ... + UNAUTHENTICATED = ... + + +"""Channel Object""" + +# XXX: These are probably the SerializeToTring/FromString pb2 methods, but +# this needs further investigation +RequestSerializer = typing.Callable +ResponseDeserializer = typing.Callable + + +class Channel: + def close(self) -> None: ... + + def stream_stream( + self, + method: str, + request_serializer: typing.Optional[RequestSerializer], + response_deserializer: typing.Optional[ResponseDeserializer], + ) -> StreamStreamMultiCallable: + ... + + def stream_unary( + self, + method: str, + request_serializer: typing.Optional[RequestSerializer], + response_deserializer: typing.Optional[ResponseDeserializer], + ) -> StreamUnaryMultiCallable: + ... + + def subscribe( + self, + callback: typing.Callable[[ChannelConnectivity], None], + try_to_connect: bool = False, + ) -> None: + ... + + def unary_stream( + self, + method: str, + request_serializer: typing.Optional[RequestSerializer], + response_deserializer: typing.Optional[ResponseDeserializer], + ) -> UnaryStreamMultiCallable: + ... + + def unary_unary( + self, + method: str, + request_serializer: typing.Optional[RequestSerializer], + response_deserializer: typing.Optional[ResponseDeserializer], + ) -> UnaryUnaryMultiCallable: + ... + + def unsubscribe( + self, + callback: typing.Callable[[ChannelConnectivity], None], + ) -> None: + ... + + def __enter__(self) -> Channel: + ... + + def __exit__(self, + exc_type: typing.Optional[typing.Type[BaseException]], + exc_val: typing.Optional[BaseException], + exc_tb: typing.Optional[TracebackType], + ) -> typing.Optional[bool]: + ... + + +"""Server Object""" + +class Server: + def add_generic_rpc_handlers( + self, + generic_rpc_handlers: typing.Iterable[GenericRpcHandler], + ) -> None: + ... + + # Returns an integer port on which server will accept RPC requests. + def add_insecure_port(self, address: str) -> int: + ... + + # Returns an integer port on which server will accept RPC requests. + def add_secure_port(self, address: str, server_credentials: ServerCredentials) -> int: + ... + + def start(self) -> None: + ... + + # Grace period is in seconds. + def stop(self, grace: typing.Optional[float] = None) -> threading.Event: + ... + + # Block current thread until the server stops. Returns a bool + # indicates if the operation times out. Timeout is in seconds. + def wait_for_termination(self, timeout: typing.Optional[float] = None) -> bool: + ... + + +"""Authentication & Authorization Objects""" + +class ChannelCredentials: + """This class has no supported interface""" + + +class CallCredentials: + """This class has no supported interface""" + + +class AuthMetadataContext: + service_url: str + method_name: str + + +class AuthMetadataPluginCallback: + def __call__(self, metadata: Metadata, error: typing.Optional[Exception]) -> None: + ... + + +class AuthMetadataPlugin: + def __call__(self, context: AuthMetadataContext, callback: AuthMetadataPluginCallback) -> None: + ... + + +class ServerCredentials: + """This class has no supported interface""" + + +class ServerCertificateConfiguration: + """This class has no supported interface""" + + +"""gRPC Exceptions""" + +class _Metadatum: + key: str + value: bytes + + +# FIXME: There is scant documentation about what is actually available in this type. +# The properties here are the properties observed in the wild, and may be inaccurate. +# A better source to confirm their presence needs to be found at some point. +class RpcError(Exception): + def code(self) -> StatusCode: ... + + # misnamed property, does not align with status.proto, where it is called 'message': + def details(self) -> typing.Optional[str]: ... + + # XXX: This has a slightly different return type to all the other metadata: + def trailing_metadata(self) -> typing.Tuple[_Metadatum, ...]: ... + + +"""Shared Context""" + +class RpcContext: + def add_callback(self, callback: typing.Callable[[], None]) -> bool: ... + def cancel(self): ... + def is_active(self) -> bool: ... + def time_remaining(self) -> float: ... + + +"""Client-Side Context""" + +class Call(RpcContext): + def code(self) -> StatusCode: ... + + # misnamed property, does not align with status.proto, where it is called 'message': + def details(self) -> str: ... + + def initial_metadata(self) -> Metadata: ... + def trailing_metadata(self) -> Metadata: ... + + +"""Client-Side Interceptor""" + +class ClientCallDetails: + method: str + timeout: typing.Optional[float] + metadata: typing.Optional[Metadata] + credentials: typing.Optional[CallCredentials] + + # "This is an EXPERIMENTAL argument. An optional flag t enable wait for ready mechanism." + wait_for_ready: typing.Optional[bool] + + compression: typing.Optional[Compression] + + +TRequest = typing.TypeVar("TRequest") +TResponse = typing.TypeVar("TResponse") + +# An object that is both a Call for the RPC and a Future. In the event of +# RPC completion, the return Call-Future’s result value will be the +# response message of the RPC. Should the event terminate with non-OK +# status, the returned Call-Future’s exception value will be an RpcError. +# +class CallFuture(Call, Future[TResponse], typing.Generic[TResponse]): + pass + + +class UnaryUnaryClientInterceptor(typing.Generic[TRequest, TResponse]): + def intercept_unary_unary( + self, + + # FIXME: decode these cryptic runes to confirm the typing mystery of + # this callable's signature that was left for us by past civilisations: + # + # continuation – A function that proceeds with the invocation by + # executing the next interceptor in chain or invoking the actual RPC + # on the underlying Channel. It is the interceptor’s responsibility + # to call it if it decides to move the RPC forward. The interceptor + # can use response_future = continuation(client_call_details, + # request) to continue with the RPC. continuation returns an object + # that is both a Call for the RPC and a Future. In the event of RPC + # completion, the return Call-Future’s result value will be the + # response message of the RPC. Should the event terminate with non-OK + # status, the returned Call-Future’s exception value will be an + # RpcError. + # + continuation: typing.Callable[[ClientCallDetails, TRequest], CallFuture[TResponse]], + + client_call_details: ClientCallDetails, + + request: TRequest, + + ) -> CallFuture[TResponse]: + ... + + +class CallIterator(typing.Generic[TResponse], Call): + def __iter__(self) -> typing.Iterator[TResponse]: ... + + +class UnaryStreamClientInterceptor(typing.Generic[TRequest, TResponse]): + def intercept_unary_stream( + self, + continuation: typing.Callable[[ClientCallDetails, TRequest], CallIterator[TResponse]], + client_call_details: ClientCallDetails, + request: TRequest, + ) -> CallIterator[TResponse]: + ... + + +class StreamUnaryClientInterceptor(typing.Generic[TRequest, TResponse]): + def intercept_stream_unary( + self, + continuation: typing.Callable[[ClientCallDetails, TRequest], CallFuture[TResponse]], + client_call_details: ClientCallDetails, + request_iterator: typing.Iterator[TRequest], + ) -> CallFuture[TResponse]: + ... + + +class StreamStreamClientInterceptor(typing.Generic[TRequest, TResponse]): + def intercept_stream_stream( + self, + continuation: typing.Callable[[ClientCallDetails, TRequest], CallIterator[TResponse]], + client_call_details: ClientCallDetails, + request_iterator: typing.Iterator[TRequest], + ) -> CallIterator[TResponse]: + ... + + +"""Service-Side Context""" + +class ServicerContext(RpcContext): + + # misnamed parameter 'details', does not align with status.proto, where it is called 'message': + def abort(self, code: StatusCode, details: str) -> typing.NoReturn: ... + def abort_with_status(self, status: Status) -> typing.NoReturn: ... + + # FIXME: The docs say "A map of strings to an iterable of bytes for each auth property". + # Does that mean 'bytes' (which is iterable), or 'typing.Iterable[bytes]'? + def auth_context(self) -> typing.Mapping[str, bytes]: + ... + + def disable_next_message_compression(self) -> None: ... + + def invocation_metadata(self) -> Metadata: ... + + def peer(self) -> str: ... + def peer_identities(self) -> typing.Optional[typing.Iterable[bytes]]: ... + def peer_identity_key(self) -> typing.Optional[str]: ... + def send_initial_metadata(self, initial_metadata: Metadata) -> None: ... + def set_code(self, code: StatusCode) -> None: ... + def set_compression(self, compression: Compression) -> None: ... + def set_trailing_metadata(self, trailing_metadata: Metadata) -> None: ... + + # misnamed function 'details', does not align with status.proto, where it is called 'message': + def set_details(self, details: str) -> None: ... + + def trailing_metadata(self) -> Metadata: ... + + +"""Service-Side Handler""" + +class RpcMethodHandler(typing.Generic[TRequest, TResponse]): + request_streaming: bool + response_streaming: bool + + # XXX: not clear from docs whether this is optional or not + request_deserializer: typing.Optional[RequestDeserializer] + + # XXX: not clear from docs whether this is optional or not + response_serializer: typing.Optional[ResponseSerializer] + + unary_unary: typing.Optional[typing.Callable[[TRequest, ServicerContext], TResponse]] + + unary_stream: typing.Optional[typing.Callable[[TRequest, ServicerContext], typing.Iterator[TResponse]]] + + stream_unary: typing.Optional[typing.Callable[[typing.Iterator[TRequest], ServicerContext], TResponse]] + + stream_stream: typing.Optional[typing.Callable[[typing.Iterator[TRequest], ServicerContext], typing.Iterator[TResponse]]] + + +class HandlerCallDetails: + method: str + invocation_metadata: Metadata + + +class GenericRpcHandler(typing.Generic[TRequest, TResponse]): + def service(self, handler_call_details: HandlerCallDetails) -> typing.Optional[RpcMethodHandler[TRequest, TResponse]]: + ... + +class ServiceRpcHandler(GenericRpcHandler[TRequest, TResponse], typing.Generic[TRequest, TResponse]): + def service_name(self) -> str: ... + + +"""Service-Side Interceptor""" + +class ServerInterceptor(typing.Generic[TRequest, TResponse]): + def intercept_service( + self, + continuation: typing.Callable[ + [HandlerCallDetails], + typing.Optional[RpcMethodHandler[TRequest, TResponse]] + ], + handler_call_details: HandlerCallDetails, + ) -> typing.Optional[RpcMethodHandler[TRequest, TResponse]]: + ... + + +"""Multi-Callable Interfaces""" + +class UnaryUnaryMultiCallable(typing.Generic[TRequest, TResponse]): + def __call__( + self, + request: TRequest, + timeout: typing.Optional[float] = None, + metadata: typing.Optional[Metadata] = None, + credentials: typing.Optional[CallCredentials] = None, + + # FIXME: optional bool seems weird, but that's what the docs suggest + wait_for_ready: typing.Optional[bool] = None, + + compression: typing.Optional[Compression] = None, + ) -> TResponse: + ... + + def future( + self, + request: TRequest, + timeout: typing.Optional[float] = None, + metadata: typing.Optional[Metadata] = None, + credentials: typing.Optional[CallCredentials] = None, + + # FIXME: optional bool seems weird, but that's what the docs suggest + wait_for_ready: typing.Optional[bool] = None, + + compression: typing.Optional[Compression] = None, + ) -> CallFuture[TResponse]: + ... + + def with_call( + self, + request: TRequest, + timeout: typing.Optional[float] = None, + metadata: typing.Optional[Metadata] = None, + credentials: typing.Optional[CallCredentials] = None, + + # FIXME: optional bool seems weird, but that's what the docs suggest + wait_for_ready: typing.Optional[bool] = None, + + compression: typing.Optional[Compression] = None, + + # FIXME: Return value is documented as "The response value for the RPC and a Call value for the RPC"; + # this is slightly unclear so this return type is a best-effort guess. + ) -> typing.Tuple[TResponse, Call]: + ... + + +class UnaryStreamMultiCallable(typing.Generic[TRequest, TResponse]): + def __call__( + self, + request: TRequest, + timeout: typing.Optional[float] = None, + metadata: typing.Optional[Metadata] = None, + credentials: typing.Optional[CallCredentials] = None, + + # FIXME: optional bool seems weird, but that's what the docs suggest + wait_for_ready: typing.Optional[bool] = None, + + compression: typing.Optional[Compression] = None, + + ) -> CallIterator[TResponse]: + ... + + +class StreamUnaryMultiCallable(typing.Generic[TRequest, TResponse]): + def __call__( + self, + request_iterator: typing.Iterator[TRequest], + timeout: typing.Optional[float] = None, + metadata: typing.Optional[Metadata] = None, + credentials: typing.Optional[CallCredentials] = None, + + # FIXME: optional bool seems weird, but that's what the docs suggest + wait_for_ready: typing.Optional[bool] = None, + + compression: typing.Optional[Compression] = None, + ) -> TResponse: + ... + + def future( + self, + request_iterator: typing.Iterator[TRequest], + timeout: typing.Optional[float] = None, + metadata: typing.Optional[Metadata] = None, + credentials: typing.Optional[CallCredentials] = None, + + # FIXME: optional bool seems weird, but that's what the docs suggest + wait_for_ready: typing.Optional[bool] = None, + + compression: typing.Optional[Compression] = None, + ) -> CallFuture[TResponse]: + ... + + def with_call( + self, + request_iterator: typing.Iterator[TRequest], + timeout: typing.Optional[float] = None, + metadata: typing.Optional[Metadata] = None, + credentials: typing.Optional[CallCredentials] = None, + + # FIXME: optional bool seems weird, but that's what the docs suggest + wait_for_ready: typing.Optional[bool] = None, + + compression: typing.Optional[Compression] = None, + + # FIXME: Return value is documented as "The response value for the RPC and a Call value for the RPC"; + # this is slightly unclear so this return type is a best-effort guess. + ) -> typing.Tuple[TResponse, Call]: + ... + + +class StreamStreamMultiCallable(typing.Generic[TRequest, TResponse]): + def __call__( + self, + request_iterator: typing.Iterator[TRequest], + timeout: typing.Optional[float] = None, + metadata: typing.Optional[Metadata] = None, + credentials: typing.Optional[CallCredentials] = None, + + # FIXME: optional bool seems weird, but that's what the docs suggest + wait_for_ready: typing.Optional[bool] = None, + + compression: typing.Optional[Compression] = None, + + ) -> CallIterator[TResponse]: + ... + + +"""Future Interfaces""" + + +class FutureTimeoutError(Exception): + pass + + +class FutureCancelledError(Exception): + pass + + +TFutureValue = typing.TypeVar("TFutureValue") + +class Future(typing.Generic[TFutureValue]): + def add_done_callback(self, fn: typing.Callable[[Future[TFutureValue]], None]) -> None: + ... + + def cancel(self) -> bool: ... + def cancelled(self) -> bool: ... + def done(self) -> bool: ... + def exception(self) -> typing.Optional[Exception]: ... + def result(self, timeout: typing.Optional[float] = None) -> TFutureValue: ... + def running(self) -> bool: ... + + # FIXME: unsure of the exact return type here. Is it a traceback.StackSummary? + def traceback(self, timeout: typing.Optional[float] = None) -> typing.Any: ... + + +"""Runtime Protobuf Parsing""" + +def protos(protobuf_path: str) -> ModuleType: + ... + +def services(protobuf_path: str) -> ModuleType: + ... + +def protos_and_services(protobuf_path: str) -> typing.Tuple[ModuleType, ModuleType]: + ... + diff --git a/stubs/grpc/grpc/aio/__init__.pyi b/stubs/grpc/grpc/aio/__init__.pyi new file mode 100644 index 000000000000..9ac28efeebdc --- /dev/null +++ b/stubs/grpc/grpc/aio/__init__.pyi @@ -0,0 +1,457 @@ +import asyncio +import typing +from concurrent import futures +from types import TracebackType +from grpc import ( + _Options, + _PartialStubMustCastOrIgnore, + RpcError, + Compression, + GenericRpcHandler, + ServerCredentials, + StatusCode, + ChannelCredentials, + CallCredentials, + ChannelConnectivity, + HandlerCallDetails, + RpcMethodHandler, +) + +"""Exceptions""" +class BaseError(Exception): ... +class UsageError(BaseError): ... +class AbortError(BaseError): ... +class InternalError(BaseError): ... + +class AioRpcError(RpcError): + def __init__( + self, + code: StatusCode, + initial_metadata: Metadata, + trailing_metadata: Metadata, + details: typing.Optional[str], + debug_error_string: typing.Optional[str], + ) -> None: + ... + + # FIXME: confirm if these are present in the parent type. The remaining + # methods already exist. + def debug_error_string(self) -> str: ... + def initial_metadata(self) -> Metadata: ... + + +"""Create Client""" + +ClientInterceptor = _PartialStubMustCastOrIgnore + +def insecure_channel( + target: str, + options: typing.Optional[_Options] = None, + compression: typing.Optional[Compression] = None, + interceptors: typing.Optional[typing.Sequence[ClientInterceptor]] = None, +) -> Channel: ... +def secure_channel( + target: str, + credentials: ChannelCredentials, + options: typing.Optional[_Options] = None, + compression: typing.Optional[Compression] = None, + interceptors: typing.Optional[typing.Sequence[ClientInterceptor]] = None, +) -> Channel: ... + + +"""Create Server""" + +def server( + migration_thread_pool: typing.Optional[futures.Executor] = None, + handlers: typing.Optional[typing.Sequence[GenericRpcHandler]] = None, + interceptors: typing.Optional[typing.Sequence[ServerInterceptor]] = None, + options: typing.Optional[_Options] = None, + maximum_concurrent_rpcs: typing.Optional[int] = None, + compression: typing.Optional[Compression] = None, +) -> 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 = typing.Callable[[typing.Any], bytes] +ResponseDeserializer = typing.Callable[[bytes], typing.Any] + +class Channel: + async def close(self, grace: typing.Optional[float]) -> None: ... + + def get_state(self, try_to_connect: bool = False) -> ChannelConnectivity: ... + + async def wait_for_state_change(self, last_observed_state: ChannelConnectivity) -> None: ... + + def stream_stream( + self, + method: str, + request_serializer: typing.Optional[RequestSerializer], + response_deserializer: typing.Optional[ResponseDeserializer], + ) -> StreamStreamMultiCallable: ... + + def stream_unary( + self, + method: str, + request_serializer: typing.Optional[RequestSerializer], + response_deserializer: typing.Optional[ResponseDeserializer], + ) -> StreamUnaryMultiCallable: ... + + def unary_stream( + self, + method: str, + request_serializer: typing.Optional[RequestSerializer], + response_deserializer: typing.Optional[ResponseDeserializer], + ) -> UnaryStreamMultiCallable: ... + + def unary_unary( + self, + method: str, + request_serializer: typing.Optional[RequestSerializer], + response_deserializer: typing.Optional[ResponseDeserializer], + ) -> UnaryUnaryMultiCallable: ... + + async def __aenter__(self) -> Channel: ... + + async def __aexit__( + self, + exc_type: typing.Optional[typing.Type[BaseException]], + exc_val: typing.Optional[BaseException], + exc_tb: typing.Optional[TracebackType], + ) -> typing.Optional[bool]: ... + + async def channel_ready(self) -> None: ... + +"""Server Object""" + +class Server: + def add_generic_rpc_handlers( + self, + generic_rpc_handlers: typing.Iterable[GenericRpcHandler], + ) -> None: ... + + # Returns an integer port on which server will accept RPC requests. + def add_insecure_port(self, address: str) -> int: ... + + # Returns an integer port on which server will accept RPC requests. + def add_secure_port( + self, address: str, server_credentials: ServerCredentials + ) -> int: ... + + async def start(self) -> None: ... + + # Grace period is in seconds. + async def stop(self, grace: typing.Optional[float] = None) -> None: ... + + # Returns a bool indicates if the operation times out. Timeout is in seconds. + async def wait_for_termination( + self, timeout: typing.Optional[float] = None + ) -> bool: ... + +"""Client-Side Context""" + +DoneCallbackType = typing.Callable[[typing.Any], None] +EOFType = object + +class RpcContext: + def cancelled(self) -> bool: ... + def done(self) -> bool: ... + def time_remaining(self) -> typing.Optional[float]: ... + def cancel(self) -> bool: ... + def add_done_callback(self, callback: DoneCallbackType) -> None: ... + +class Call(RpcContext): + async def initial_metadata(self) -> Metadata: ... + async def trailing_metadata(self) -> Metadata: ... + async def code(self) -> StatusCode: ... + async def details(self) -> str: ... + async def wait_for_connection(self) -> None: ... + +class UnaryUnaryCall(typing.Generic[TRequest, TResponse], Call): + def __await__(self) -> typing.Generator[None, None, TResponse]: ... + +class UnaryStreamCall(typing.Generic[TRequest, TResponse], Call): + def __aiter__(self) -> typing.AsyncIterator[TResponse]: ... + async def read(self) -> typing.Union[EOFType, TResponse]: ... + +class StreamUnaryCall(typing.Generic[TRequest, TResponse], Call): + async def write(self, request: TRequest) -> None: ... + async def done_writing(self) -> None: ... + def __await__(self) -> typing.Generator[None, None, TResponse]: ... + +class StreamStreamCall(typing.Generic[TRequest, TResponse], Call): + def __aiter__(self) -> typing.AsyncIterator[TResponse]: ... + async def read(self) -> typing.Union[EOFType, TResponse]: ... + async def write(self, request: TRequest) -> None: ... + async def done_writing(self) -> None: ... + +TRequest = typing.TypeVar("TRequest") +TResponse = typing.TypeVar("TResponse") + +"""Service-Side Context""" + +class DoneCallback(typing.Generic[TRequest, TResponse]): + def __call__( + self, + ctx: ServicerContext[TRequest, TResponse], + ) -> None: + ... + +class ServicerContext(typing.Generic[TRequest, TResponse]): + async def abort( + self, + code: StatusCode, + details: str = "", + trailing_metadata: MetadataType = tuple(), + ) -> typing.NoReturn: ... + + async def read(self) -> TRequest: ... + async def write(self, message: TResponse) -> None: ... + async def send_initial_metadata(self, initial_metadata: MetadataType) -> None: ... + + def add_done_callback(self, callback: DoneCallback[TRequest, TResponse]) -> None: ... + def set_trailing_metadata(self, trailing_metadata: MetadataType) -> None: ... + def invocation_metadata(self) -> typing.Optional[Metadata]: ... + def set_code(self, code: StatusCode) -> None: ... + def set_details(self, details: str) -> None: ... + def set_compression(self, compression: Compression) -> None: ... + def disable_next_message_compression(self) -> None: ... + def peer(self) -> str: ... + def peer_identities(self) -> typing.Optional[typing.Iterable[bytes]]: ... + def peer_identity_key(self) -> typing.Optional[str]: ... + def auth_context(self) -> typing.Mapping[str, typing.Iterable[bytes]]: ... + def time_remaining(self) -> float: ... + def trailing_metadata(self) -> Metadata: ... + def code(self) -> StatusCode: ... + def details(self) -> str: ... + def cancelled(self) -> bool: ... + def done(self) -> bool: ... + + +"""Client-Side Interceptor""" + +class ClientCallDetails: + def __init__( + self, + method: str, + timeout: typing.Optional[float], + metadata: typing.Optional[Metadata], + credentials: typing.Optional[CallCredentials], + wait_for_ready: typing.Optional[bool], + ) -> None: + ... + + method: str + timeout: typing.Optional[float] + metadata: typing.Optional[Metadata] + credentials: typing.Optional[CallCredentials] + + # "This is an EXPERIMENTAL argument. An optional flag t enable wait for ready mechanism." + wait_for_ready: typing.Optional[bool] + + # As at 1.53.0, this is not supported in aio: + # compression: typing.Optional[Compression] + + +class InterceptedCall(typing.Generic[TRequest, TResponse]): + def __init__(self, interceptors_task: asyncio.Task) -> None: ... + def __del__(self): ... + + def cancel(self) -> bool: ... + def cancelled(self) -> bool: ... + def done(self) -> bool: ... + def add_done_callback(self, callback: DoneCallback[TRequest, TResponse]) -> None: ... + def time_remaining(self) -> typing.Optional[float]: ... + async def initial_metadata(self) -> typing.Optional[Metadata]: ... + async def trailing_metadata(self) -> typing.Optional[Metadata]: ... + async def code(self) -> StatusCode: ... + async def details(self) -> str: ... + async def debug_error_string(self) -> typing.Optional[str]: ... + async def wait_for_connection(self) -> None: ... + + +class InterceptedUnaryUnaryCall(InterceptedCall[TRequest, TResponse], typing.Generic[TRequest, TResponse]): + def __await__(self): ... + + def __init__( + self, + interceptors: typing.Sequence[UnaryUnaryClientInterceptor], + request: TRequest, + timeout: typing.Optional[float], + metadata: Metadata, + credentials: typing.Optional[CallCredentials], + wait_for_ready: typing.Optional[bool], + channel: Channel, + method: bytes, + request_serializer: RequestSerializer, + response_deserializer: ResponseDeserializer, + loop: asyncio.AbstractEventLoop, + ) -> None: + ... + + # pylint: disable=too-many-arguments + async def _invoke( + self, + interceptors: typing.Sequence[UnaryUnaryClientInterceptor], + method: bytes, + timeout: typing.Optional[float], + metadata: typing.Optional[Metadata], + credentials: typing.Optional[CallCredentials], + wait_for_ready: typing.Optional[bool], + request: TRequest, + request_serializer: RequestSerializer, + response_deserializer: ResponseDeserializer, + ) -> UnaryUnaryCall: + ... + + def time_remaining(self) -> typing.Optional[float]: ... + + +class UnaryUnaryClientInterceptor(typing.Generic[TRequest, TResponse]): + async def intercept_unary_unary( + self, + # XXX: See equivalent function in grpc types for notes about continuation: + continuation: typing.Callable[[ClientCallDetails, TRequest], UnaryUnaryCall[TRequest, TResponse]], + client_call_details: ClientCallDetails, + request: TRequest, + ) -> TResponse: + ... + + +class UnaryStreamClientInterceptor(typing.Generic[TRequest, TResponse]): + async def intercept_unary_stream( + self, + continuation: typing.Callable[[ClientCallDetails, TRequest], UnaryStreamCall[TRequest, TResponse]], + client_call_details: ClientCallDetails, + request: TRequest, + ) -> typing.Union[ + typing.AsyncIterable[TResponse], + UnaryStreamCall[TRequest, TResponse], + ]: + ... + + +class StreamUnaryClientInterceptor(typing.Generic[TRequest, TResponse]): + async def intercept_stream_unary( + self, + continuation: typing.Callable[[ClientCallDetails, TRequest], StreamUnaryCall[TRequest, TResponse]], + client_call_details: ClientCallDetails, + request_iterator: typing.Union[typing.AsyncIterable[TRequest], typing.Iterable[TRequest]], + ) -> typing.Union[ + typing.AsyncIterable[TResponse], + UnaryStreamCall[TRequest, TResponse], + ]: + ... + + +class StreamStreamClientInterceptor(typing.Generic[TRequest, TResponse]): + async def intercept_stream_stream( + self, + continuation: typing.Callable[[ClientCallDetails, TRequest], StreamStreamCall[TRequest, TResponse]], + client_call_details: ClientCallDetails, + request_iterator: typing.Union[typing.AsyncIterable[TRequest], typing.Iterable[TRequest]], + ) -> typing.Union[ + typing.AsyncIterable[TResponse], + StreamStreamCall[TRequest, TResponse], + ]: + ... + + +"""Server-Side Interceptor""" + +class ServerInterceptor(typing.Generic[TRequest, TResponse]): + async def intercept_service( + self, + continuation: typing.Callable[ + [HandlerCallDetails], + typing.Awaitable[RpcMethodHandler[TRequest, TResponse]], + ], + handler_call_details: HandlerCallDetails, + ) -> RpcMethodHandler[TRequest, TResponse]: + ... + + +"""Multi-Callable Interfaces""" + +class UnaryUnaryMultiCallable(typing.Generic[TRequest, TResponse]): + def __call__( + self, + request: TRequest, + timeout: typing.Optional[float] = None, + metadata: typing.Optional[MetadataType] = None, + credentials: typing.Optional[CallCredentials] = None, + # FIXME: optional bool seems weird, but that's what the docs suggest + wait_for_ready: typing.Optional[bool] = None, + compression: typing.Optional[Compression] = None, + ) -> UnaryUnaryCall[TRequest, TResponse]: ... + +class UnaryStreamMultiCallable(typing.Generic[TRequest, TResponse]): + def __call__( + self, + request: TRequest, + timeout: typing.Optional[float] = None, + metadata: typing.Optional[MetadataType] = None, + credentials: typing.Optional[CallCredentials] = None, + # FIXME: optional bool seems weird, but that's what the docs suggest + wait_for_ready: typing.Optional[bool] = None, + compression: typing.Optional[Compression] = None, + ) -> UnaryStreamCall[TRequest, TResponse]: ... + +class StreamUnaryMultiCallable(typing.Generic[TRequest, TResponse]): + def __call__( + self, + request_iterator: typing.Optional[ + typing.Union[typing.AsyncIterator[TRequest], typing.Iterator[TRequest]] + ], + timeout: typing.Optional[float] = None, + metadata: typing.Optional[MetadataType] = None, + credentials: typing.Optional[CallCredentials] = None, + # FIXME: optional bool seems weird, but that's what the docs suggest + wait_for_ready: typing.Optional[bool] = None, + compression: typing.Optional[Compression] = None, + ) -> StreamUnaryCall[TRequest, TResponse]: ... + +class StreamStreamMultiCallable(typing.Generic[TRequest, TResponse]): + def __call__( + self, + request_iterator: typing.Optional[ + typing.Union[typing.AsyncIterator[TRequest], typing.Iterator[TRequest]] + ], + timeout: typing.Optional[float] = None, + metadata: typing.Optional[MetadataType] = None, + credentials: typing.Optional[CallCredentials] = None, + # FIXME: optional bool seems weird, but that's what the docs suggest + wait_for_ready: typing.Optional[bool] = None, + compression: typing.Optional[Compression] = None, + ) -> StreamStreamCall[TRequest, TResponse]: ... + + +"""Metadata""" + +MetadataKey = str +MetadataValue = typing.Union[str, bytes] +MetadatumType = typing.Tuple[MetadataKey, MetadataValue] +MetadataType = typing.Union[Metadata, typing.Sequence[MetadatumType]] + +class Metadata(typing.Mapping): + def __init__(self, *args: typing.Tuple[MetadataKey, MetadataValue]) -> None: ... + @classmethod + def from_tuple( + cls, raw_metadata: typing.Tuple[MetadataKey, MetadataValue] + ) -> Metadata: ... + def add(self, key: MetadataKey, value: MetadataValue) -> None: ... + def __len__(self) -> int: ... + def __getitem__(self, key: MetadataKey) -> MetadataValue: ... + def __setitem__(self, key: MetadataKey, value: MetadataValue) -> None: ... + def __delitem__(self, key: MetadataKey) -> None: ... + def delete_all(self, key: MetadataKey) -> None: ... + def __iter__(self) -> typing.Iterator[typing.Tuple[MetadataKey, MetadataValue]]: ... + def get_all(self, key: MetadataKey) -> typing.List[MetadataValue]: ... + def set_all(self, key: MetadataKey, values: typing.List[MetadataValue]) -> None: ... + def __contains__(self, key: object) -> bool: ... + def __eq__(self, other: typing.Any) -> bool: ... + def __add__(self, other: typing.Any) -> Metadata: ... + def __repr__(self) -> str: ... diff --git a/stubs/grpc/grpc/aio/py.typed b/stubs/grpc/grpc/aio/py.typed new file mode 100644 index 000000000000..b648ac923333 --- /dev/null +++ b/stubs/grpc/grpc/aio/py.typed @@ -0,0 +1 @@ +partial diff --git a/stubs/grpc_channelz/METADATA.toml b/stubs/grpc_channelz/METADATA.toml new file mode 100644 index 000000000000..b81a42967303 --- /dev/null +++ b/stubs/grpc_channelz/METADATA.toml @@ -0,0 +1,6 @@ +version = "1.*" +upstream_repository = "https://github.com/grpc/grpc" +partial_stub = true + +[tool.stubtest] +ignore_missing_stub = true diff --git a/stubs/grpc_channelz/grpc_channelz/__init__.pyi b/stubs/grpc_channelz/grpc_channelz/__init__.pyi new file mode 100644 index 000000000000..e4579106bab4 --- /dev/null +++ b/stubs/grpc_channelz/grpc_channelz/__init__.pyi @@ -0,0 +1,3 @@ +import typing + +def __getattr__(name) -> typing.Any: ... diff --git a/stubs/grpc_channelz/grpc_channelz/v1/__init__.pyi b/stubs/grpc_channelz/grpc_channelz/v1/__init__.pyi new file mode 100644 index 000000000000..e4579106bab4 --- /dev/null +++ b/stubs/grpc_channelz/grpc_channelz/v1/__init__.pyi @@ -0,0 +1,3 @@ +import typing + +def __getattr__(name) -> typing.Any: ... diff --git a/stubs/grpc_channelz/grpc_channelz/v1/_servicer.pyi b/stubs/grpc_channelz/grpc_channelz/v1/_servicer.pyi new file mode 100644 index 000000000000..702b304d8d09 --- /dev/null +++ b/stubs/grpc_channelz/grpc_channelz/v1/_servicer.pyi @@ -0,0 +1,32 @@ +from grpc import ServicerContext +import grpc_channelz.v1.channelz_pb2 as _channelz_pb2 +import grpc_channelz.v1.channelz_pb2_grpc as _channelz_pb2_grpc + +class ChannelzServicer(_channelz_pb2_grpc.ChannelzServicer): + @staticmethod + def GetTopChannels(request: _channelz_pb2.GetTopChannelsRequest, context: ServicerContext) -> _channelz_pb2.GetTopChannelsResponse: + ... + + @staticmethod + def GetServers(request: _channelz_pb2.GetServersRequest, context: ServicerContext) -> _channelz_pb2.GetServersResponse: + ... + + @staticmethod + def GetServer(request: _channelz_pb2.GetServerRequest, context: ServicerContext) -> _channelz_pb2.GetServerResponse: + ... + + @staticmethod + def GetServerSockets(request: _channelz_pb2.GetServerSocketsRequest, context: ServicerContext) -> _channelz_pb2.GetServerSocketsResponse: + ... + + @staticmethod + def GetChannel(request: _channelz_pb2.GetChannelRequest, context: ServicerContext) -> _channelz_pb2.GetChannelResponse: + ... + + @staticmethod + def GetSubchannel(request: _channelz_pb2.GetSubchannelRequest, context: ServicerContext) -> _channelz_pb2.GetSubchannelResponse: + ... + + @staticmethod + def GetSocket(request: _channelz_pb2.GetSocketRequest, context: ServicerContext) -> _channelz_pb2.GetSocketResponse: + ... diff --git a/stubs/grpc_channelz/grpc_channelz/v1/channelz.pyi b/stubs/grpc_channelz/grpc_channelz/v1/channelz.pyi new file mode 100644 index 000000000000..a6635710c829 --- /dev/null +++ b/stubs/grpc_channelz/grpc_channelz/v1/channelz.pyi @@ -0,0 +1,4 @@ +from grpc import Server + +def add_channelz_servicer(server: Server) -> None: + ... diff --git a/stubs/grpc_health/METADATA.toml b/stubs/grpc_health/METADATA.toml new file mode 100644 index 000000000000..b81a42967303 --- /dev/null +++ b/stubs/grpc_health/METADATA.toml @@ -0,0 +1,6 @@ +version = "1.*" +upstream_repository = "https://github.com/grpc/grpc" +partial_stub = true + +[tool.stubtest] +ignore_missing_stub = true diff --git a/stubs/grpc_health/grpc_health/__init__.pyi b/stubs/grpc_health/grpc_health/__init__.pyi new file mode 100644 index 000000000000..e4579106bab4 --- /dev/null +++ b/stubs/grpc_health/grpc_health/__init__.pyi @@ -0,0 +1,3 @@ +import typing + +def __getattr__(name) -> typing.Any: ... diff --git a/stubs/grpc_health/grpc_health/v1/__init__.pyi b/stubs/grpc_health/grpc_health/v1/__init__.pyi new file mode 100644 index 000000000000..e4579106bab4 --- /dev/null +++ b/stubs/grpc_health/grpc_health/v1/__init__.pyi @@ -0,0 +1,3 @@ +import typing + +def __getattr__(name) -> typing.Any: ... diff --git a/stubs/grpc_health/grpc_health/v1/health.pyi b/stubs/grpc_health/grpc_health/v1/health.pyi new file mode 100644 index 000000000000..f7552f08cc22 --- /dev/null +++ b/stubs/grpc_health/grpc_health/v1/health.pyi @@ -0,0 +1,43 @@ +from concurrent import futures +from grpc import ServicerContext +from grpc_health.v1 import health_pb2 as _health_pb2 +from grpc_health.v1 import health_pb2_grpc as _health_pb2_grpc +from typing import Callable, Optional + +SERVICE_NAME: str +OVERALL_HEALTH: str + +class _Watcher: + def __init__(self) -> None: + ... + + def __iter__(self) -> _Watcher: + ... + + def next(self) -> _health_pb2.HealthCheckResponse: + ... + + def __next__(self) -> _health_pb2.HealthCheckResponse: + ... + + def add(self, response: _health_pb2.HealthCheckResponse) -> None: + ... + + def close(self) -> None: + ... + +class HealthServicer(_health_pb2_grpc.HealthServicer): + def __init__(self, experimental_non_blocking: bool = ..., experimental_thread_pool: Optional[futures.ThreadPoolExecutor] = ...) -> None: + ... + + def Check(self, request: _health_pb2.HealthCheckRequest, context: ServicerContext) -> _health_pb2.HealthCheckResponse: + ... + + def Watch(self, request: _health_pb2.HealthCheckRequest, context: ServicerContext, send_response_callback: Optional[Callable] = ...) -> _health_pb2.HealthCheckResponse: + ... + + def set(self, service: str, status: _health_pb2.HealthCheckResponse.ServingStatus) -> None: + ... + + def enter_graceful_shutdown(self) -> None: + ... diff --git a/stubs/grpc_reflection/METADATA.toml b/stubs/grpc_reflection/METADATA.toml new file mode 100644 index 000000000000..b81a42967303 --- /dev/null +++ b/stubs/grpc_reflection/METADATA.toml @@ -0,0 +1,6 @@ +version = "1.*" +upstream_repository = "https://github.com/grpc/grpc" +partial_stub = true + +[tool.stubtest] +ignore_missing_stub = true diff --git a/stubs/grpc_reflection/grpc_reflection/__init__.pyi b/stubs/grpc_reflection/grpc_reflection/__init__.pyi new file mode 100644 index 000000000000..e4579106bab4 --- /dev/null +++ b/stubs/grpc_reflection/grpc_reflection/__init__.pyi @@ -0,0 +1,3 @@ +import typing + +def __getattr__(name) -> typing.Any: ... diff --git a/stubs/grpc_reflection/grpc_reflection/v1alpha/__init__.pyi b/stubs/grpc_reflection/grpc_reflection/v1alpha/__init__.pyi new file mode 100644 index 000000000000..e4579106bab4 --- /dev/null +++ b/stubs/grpc_reflection/grpc_reflection/v1alpha/__init__.pyi @@ -0,0 +1,3 @@ +import typing + +def __getattr__(name) -> typing.Any: ... diff --git a/stubs/grpc_reflection/grpc_reflection/v1alpha/reflection.pyi b/stubs/grpc_reflection/grpc_reflection/v1alpha/reflection.pyi new file mode 100644 index 000000000000..3ac378c90b84 --- /dev/null +++ b/stubs/grpc_reflection/grpc_reflection/v1alpha/reflection.pyi @@ -0,0 +1,27 @@ +import typing + +import grpc +from grpc import aio +from google.protobuf import descriptor_pool +from grpc_reflection.v1alpha import reflection_pb2 as _reflection_pb2 +from grpc_reflection.v1alpha._base import BaseReflectionServicer + +SERVICE_NAME: str + +AnyServer = typing.Union[grpc.Server, aio.Server] +AnyServicerContext = typing.Union[grpc.ServicerContext, aio.ServicerContext] + +class ReflectionServicer(BaseReflectionServicer): + def ServerReflectionInfo( + self, + request_iterator: typing.Iterable[_reflection_pb2.ServerReflectionRequest], + context: AnyServicerContext, + ) -> None: + ... + +def enable_server_reflection( + service_names: typing.Iterable[str], + server: AnyServer, + pool: typing.Optional[descriptor_pool.DescriptorPool] = ..., +) -> None: + ... diff --git a/stubs/grpc_status/METADATA.toml b/stubs/grpc_status/METADATA.toml new file mode 100644 index 000000000000..b81a42967303 --- /dev/null +++ b/stubs/grpc_status/METADATA.toml @@ -0,0 +1,6 @@ +version = "1.*" +upstream_repository = "https://github.com/grpc/grpc" +partial_stub = true + +[tool.stubtest] +ignore_missing_stub = true diff --git a/stubs/grpc_status/grpc_status/__init__.pyi b/stubs/grpc_status/grpc_status/__init__.pyi new file mode 100644 index 000000000000..e4579106bab4 --- /dev/null +++ b/stubs/grpc_status/grpc_status/__init__.pyi @@ -0,0 +1,3 @@ +import typing + +def __getattr__(name) -> typing.Any: ... diff --git a/stubs/grpc_status/grpc_status/rpc_status.pyi b/stubs/grpc_status/grpc_status/rpc_status.pyi new file mode 100644 index 000000000000..8cdc1ee816a0 --- /dev/null +++ b/stubs/grpc_status/grpc_status/rpc_status.pyi @@ -0,0 +1,17 @@ +import grpc +import typing + + +# XXX: don't yet know how to add a stub for google.rpc.status_pb2.Status +# without affecting other stuff; may need to make a stub-only package for +# google.rpc as well. + + +# Returns a google.rpc.status.Status message corresponding to a given grpc.Call. +def from_call(call: grpc.Call) -> typing.Any: + ... + + +# Convert a google.rpc.status.Status message to grpc.Status. +def to_status(status: typing.Any) -> grpc.Status: + ... From b3dd7ca1cc3871c578ea33967c783bdf49f64570 Mon Sep 17 00:00:00 2001 From: Blake Williams Date: Wed, 27 Dec 2023 16:26:16 +1100 Subject: [PATCH 02/18] Format grpc stubs --- stubs/grpc/grpc/__init__.pyi | 374 ++++-------------- stubs/grpc/grpc/aio/__init__.pyi | 139 ++----- .../grpc_channelz/v1/_servicer.pyi | 35 +- .../grpc_channelz/v1/channelz.pyi | 3 +- stubs/grpc_health/grpc_health/v1/health.pyi | 52 +-- .../grpc_reflection/v1alpha/reflection.pyi | 16 +- stubs/grpc_status/grpc_status/rpc_status.pyi | 10 +- 7 files changed, 155 insertions(+), 474 deletions(-) diff --git a/stubs/grpc/grpc/__init__.pyi b/stubs/grpc/grpc/__init__.pyi index 13b2ba7a3e8d..efd4cabd4319 100644 --- a/stubs/grpc/grpc/__init__.pyi +++ b/stubs/grpc/grpc/__init__.pyi @@ -13,68 +13,48 @@ __version__: str # 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. class _PartialStubMustCastOrIgnore: - pass - + ... # 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? -_OptionKeyValue = typing.Tuple[str, typing.Any] +_OptionKeyValue = tuple[str, typing.Any] _Options = typing.Sequence[_OptionKeyValue] - class Compression(enum.IntEnum): NoCompression = ... Deflate = ... Gzip = ... - @enum.unique class LocalConnectionType(enum.Enum): UDS = ... LOCAL_TCP = ... - # XXX: not documented, needs more investigation. # Some evidence: # - https://github.com/grpc/grpc/blob/0e1984effd7e977ef18f1ad7fde7d10a2a153e1d/src/python/grpcio_tests/tests/unit/_metadata_test.py#L71 # - https://github.com/grpc/grpc/blob/0e1984effd7e977ef18f1ad7fde7d10a2a153e1d/src/python/grpcio_tests/tests/unit/_metadata_test.py#L58 # - https://github.com/grpc/grpc/blob/0e1984effd7e977ef18f1ad7fde7d10a2a153e1d/src/python/grpcio_tests/tests/unit/_invocation_defects_test.py#L66 -Metadata = typing.Tuple[ - typing.Tuple[str, typing.Union[str, bytes]], - ..., -] - +Metadata = tuple[tuple[str, typing.Union[str, bytes]], ...] """Create Client""" def insecure_channel( - target: str, - options: typing.Optional[_Options] = None, - compression: typing.Optional[Compression] = None, -) -> Channel: - ... - - + target: str, options: typing.Optional[_Options] = None, compression: typing.Optional[Compression] = None +) -> Channel: ... def secure_channel( target: str, credentials: ChannelCredentials, options: typing.Optional[_Options] = None, compression: typing.Optional[Compression] = None, -) -> Channel: - ... - +) -> Channel: ... Interceptor = typing.Union[ - UnaryUnaryClientInterceptor, - UnaryStreamClientInterceptor, - StreamUnaryClientInterceptor, - StreamStreamClientInterceptor, + UnaryUnaryClientInterceptor, UnaryStreamClientInterceptor, StreamUnaryClientInterceptor, StreamStreamClientInterceptor ] -def intercept_channel(channel: Channel, *interceptors: Interceptor) -> Channel: - ... - +def intercept_channel(channel: Channel, *interceptors: Interceptor) -> Channel: ... """Create Client Credentials""" @@ -82,103 +62,55 @@ def ssl_channel_credentials( root_certificates: typing.Optional[bytes] = None, private_key: typing.Optional[bytes] = None, certificate_chain: typing.Optional[bytes] = None, -) -> ChannelCredentials: - ... - -def local_channel_credentials( - local_connect_type: LocalConnectionType = LocalConnectionType.LOCAL_TCP, -) -> ChannelCredentials: - ... - -def metadata_call_credentials( - metadata_plugin: AuthMetadataPlugin, - name: typing.Optional[str] = None, -) -> CallCredentials: - ... - -def access_token_call_credentials(access_token: str) -> CallCredentials: - ... - -def alts_channel_credentials( - service_accounts: typing.Optional[typing.Sequence[str]] = None, ) -> ChannelCredentials: ... - +def local_channel_credentials(local_connect_type: LocalConnectionType = LocalConnectionType.LOCAL_TCP) -> ChannelCredentials: ... +def metadata_call_credentials(metadata_plugin: AuthMetadataPlugin, name: typing.Optional[str] = None) -> CallCredentials: ... +def access_token_call_credentials(access_token: str) -> CallCredentials: ... +def alts_channel_credentials(service_accounts: typing.Optional[typing.Sequence[str]] = None) -> ChannelCredentials: ... def compute_engine_channel_credentials() -> ChannelCredentials: ... - -def xds_channel_credentials( - fallback_credentials: typing.Optional[ChannelCredentials] = None, -) -> ChannelCredentials: ... +def xds_channel_credentials(fallback_credentials: typing.Optional[ChannelCredentials] = None) -> ChannelCredentials: ... # GRPC docs say there should be at least two: -def composite_call_credentials( - creds1: CallCredentials, - creds2: CallCredentials, - *rest: CallCredentials, -) -> CallCredentials: - ... +def composite_call_credentials(creds1: CallCredentials, creds2: CallCredentials, *rest: CallCredentials) -> CallCredentials: ... # Compose a ChannelCredentials and one or more CallCredentials objects. def composite_channel_credentials( - channel_credentials: ChannelCredentials, - call_credentials: CallCredentials, - *rest: CallCredentials, -) -> ChannelCredentials: - ... - + channel_credentials: ChannelCredentials, call_credentials: CallCredentials, *rest: CallCredentials +) -> ChannelCredentials: ... """Create Server""" def server( thread_pool: futures.ThreadPoolExecutor, - handlers: typing.Optional[typing.List[GenericRpcHandler]] = None, - interceptors: typing.Optional[typing.List[ServerInterceptor]] = None, + handlers: typing.Optional[list[GenericRpcHandler]] = None, + interceptors: typing.Optional[list[ServerInterceptor]] = None, options: typing.Optional[_Options] = None, maximum_concurrent_rpcs: typing.Optional[int] = None, compression: typing.Optional[Compression] = None, xds: bool = False, -) -> Server: - ... - +) -> Server: ... """Create Server Credentials""" -CertificateChainPair = typing.Tuple[bytes, bytes] +CertificateChainPair = tuple[bytes, bytes] def ssl_server_credentials( - private_key_certificate_chain_pairs: typing.List[CertificateChainPair], + private_key_certificate_chain_pairs: list[CertificateChainPair], root_certificates: typing.Optional[bytes] = None, require_client_auth: bool = False, -) -> ServerCredentials: - ... - - -def local_server_credentials( - local_connect_type: LocalConnectionType = LocalConnectionType.LOCAL_TCP, -) -> ServerCredentials: - ... - - +) -> ServerCredentials: ... +def local_server_credentials(local_connect_type: LocalConnectionType = LocalConnectionType.LOCAL_TCP) -> ServerCredentials: ... def ssl_server_certificate_configuration( - private_key_certificate_chain_pairs: typing.List[CertificateChainPair], - root_certificates: typing.Optional[bytes] = None, -) -> ServerCertificateConfiguration: - ... - - + private_key_certificate_chain_pairs: list[CertificateChainPair], root_certificates: typing.Optional[bytes] = None +) -> ServerCertificateConfiguration: ... def dynamic_ssl_server_credentials( initial_certificate_configuration: ServerCertificateConfiguration, certificate_configuration_fetcher: typing.Callable[[], ServerCertificateConfiguration], require_client_authentication: bool = False, -) -> ServerCredentials: - ... - +) -> ServerCredentials: ... def alts_server_credentials() -> ServerCredentials: ... - def insecure_server_credentials() -> ServerCredentials: ... - -def xds_server_credentials( - fallback_credentials: ServerCredentials, -) -> ServerCredentials: ... +def xds_server_credentials(fallback_credentials: ServerCredentials) -> ServerCredentials: ... """RPC Method Handlers""" @@ -196,47 +128,31 @@ Behaviour = typing.Callable RequestDeserializer = typing.Callable ResponseSerializer = typing.Callable - def unary_unary_rpc_method_handler( behavior: Behaviour, request_deserializer: typing.Optional[RequestDeserializer] = None, response_serializer: typing.Optional[ResponseSerializer] = None, -) -> RpcMethodHandler: - ... - +) -> RpcMethodHandler: ... def unary_stream_rpc_method_handler( behavior: Behaviour, request_deserializer: typing.Optional[RequestDeserializer] = None, response_serializer: typing.Optional[ResponseSerializer] = None, -) -> RpcMethodHandler: - ... - +) -> RpcMethodHandler: ... def stream_unary_rpc_method_handler( behavior: Behaviour, request_deserializer: typing.Optional[RequestDeserializer] = None, response_serializer: typing.Optional[ResponseSerializer] = None, -) -> RpcMethodHandler: - ... - +) -> RpcMethodHandler: ... def stream_stream_rpc_method_handler( behavior: Behaviour, request_deserializer: typing.Optional[RequestDeserializer] = None, response_serializer: typing.Optional[ResponseSerializer] = None, -) -> RpcMethodHandler: - ... - -def method_handlers_generic_handler( - service: str, - method_handlers: typing.Dict[str, RpcMethodHandler], -) -> GenericRpcHandler: - ... - +) -> RpcMethodHandler: ... +def method_handlers_generic_handler(service: str, method_handlers: dict[str, RpcMethodHandler]) -> GenericRpcHandler: ... """Channel Ready Future""" -def channel_ready_future(channel: Channel) -> Future: - ... - +def channel_ready_future(channel: Channel) -> Future: ... """Channel Connectivity""" @@ -247,8 +163,6 @@ class ChannelConnectivity(enum.Enum): TRANSIENT_FAILURE = ... SHUTDOWN = ... - - """gRPC Status Code""" class Status: @@ -259,7 +173,6 @@ class Status: trailing_metadata: Metadata - # https://grpc.github.io/grpc/core/md_doc_statuscodes.html class StatusCode(enum.Enum): OK = ... @@ -280,7 +193,6 @@ class StatusCode(enum.Enum): DATA_LOSS = ... UNAUTHENTICATED = ... - """Channel Object""" # XXX: These are probably the SerializeToTring/FromString pb2 methods, but @@ -288,136 +200,91 @@ class StatusCode(enum.Enum): RequestSerializer = typing.Callable ResponseDeserializer = typing.Callable - class Channel: def close(self) -> None: ... - def stream_stream( self, method: str, request_serializer: typing.Optional[RequestSerializer], response_deserializer: typing.Optional[ResponseDeserializer], - ) -> StreamStreamMultiCallable: - ... - + ) -> StreamStreamMultiCallable: ... def stream_unary( self, method: str, request_serializer: typing.Optional[RequestSerializer], response_deserializer: typing.Optional[ResponseDeserializer], - ) -> StreamUnaryMultiCallable: - ... - - def subscribe( - self, - callback: typing.Callable[[ChannelConnectivity], None], - try_to_connect: bool = False, - ) -> None: - ... - + ) -> StreamUnaryMultiCallable: ... + def subscribe(self, callback: typing.Callable[[ChannelConnectivity], None], try_to_connect: bool = False) -> None: ... def unary_stream( self, method: str, request_serializer: typing.Optional[RequestSerializer], response_deserializer: typing.Optional[ResponseDeserializer], - ) -> UnaryStreamMultiCallable: - ... - + ) -> UnaryStreamMultiCallable: ... def unary_unary( self, method: str, request_serializer: typing.Optional[RequestSerializer], response_deserializer: typing.Optional[ResponseDeserializer], - ) -> UnaryUnaryMultiCallable: - ... - - def unsubscribe( + ) -> UnaryUnaryMultiCallable: ... + def unsubscribe(self, callback: typing.Callable[[ChannelConnectivity], None]) -> None: ... + def __enter__(self) -> Channel: ... + def __exit__( self, - callback: typing.Callable[[ChannelConnectivity], None], - ) -> None: - ... - - def __enter__(self) -> Channel: - ... - - def __exit__(self, - exc_type: typing.Optional[typing.Type[BaseException]], + exc_type: typing.Optional[type[BaseException]], exc_val: typing.Optional[BaseException], exc_tb: typing.Optional[TracebackType], - ) -> typing.Optional[bool]: - ... - + ) -> typing.Optional[bool]: ... """Server Object""" class Server: - def add_generic_rpc_handlers( - self, - generic_rpc_handlers: typing.Iterable[GenericRpcHandler], - ) -> None: - ... + def add_generic_rpc_handlers(self, generic_rpc_handlers: typing.Iterable[GenericRpcHandler]) -> None: ... # Returns an integer port on which server will accept RPC requests. - def add_insecure_port(self, address: str) -> int: - ... + def add_insecure_port(self, address: str) -> int: ... # Returns an integer port on which server will accept RPC requests. - def add_secure_port(self, address: str, server_credentials: ServerCredentials) -> int: - ... - - def start(self) -> None: - ... + def add_secure_port(self, address: str, server_credentials: ServerCredentials) -> int: ... + def start(self) -> None: ... # Grace period is in seconds. - def stop(self, grace: typing.Optional[float] = None) -> threading.Event: - ... + def stop(self, grace: typing.Optional[float] = None) -> threading.Event: ... # Block current thread until the server stops. Returns a bool # indicates if the operation times out. Timeout is in seconds. - def wait_for_termination(self, timeout: typing.Optional[float] = None) -> bool: - ... - + def wait_for_termination(self, timeout: typing.Optional[float] = None) -> bool: ... """Authentication & Authorization Objects""" class ChannelCredentials: """This class has no supported interface""" - class CallCredentials: """This class has no supported interface""" - class AuthMetadataContext: service_url: str method_name: str - class AuthMetadataPluginCallback: - def __call__(self, metadata: Metadata, error: typing.Optional[Exception]) -> None: - ... - + def __call__(self, metadata: Metadata, error: typing.Optional[Exception]) -> None: ... class AuthMetadataPlugin: - def __call__(self, context: AuthMetadataContext, callback: AuthMetadataPluginCallback) -> None: - ... - + def __call__(self, context: AuthMetadataContext, callback: AuthMetadataPluginCallback) -> None: ... class ServerCredentials: """This class has no supported interface""" - class ServerCertificateConfiguration: """This class has no supported interface""" - """gRPC Exceptions""" class _Metadatum: key: str value: bytes - # FIXME: There is scant documentation about what is actually available in this type. # The properties here are the properties observed in the wild, and may be inaccurate. # A better source to confirm their presence needs to be found at some point. @@ -428,8 +295,7 @@ class RpcError(Exception): def details(self) -> typing.Optional[str]: ... # XXX: This has a slightly different return type to all the other metadata: - def trailing_metadata(self) -> typing.Tuple[_Metadatum, ...]: ... - + def trailing_metadata(self) -> tuple[_Metadatum, ...]: ... """Shared Context""" @@ -439,7 +305,6 @@ class RpcContext: def is_active(self) -> bool: ... def time_remaining(self) -> float: ... - """Client-Side Context""" class Call(RpcContext): @@ -447,11 +312,9 @@ class Call(RpcContext): # misnamed property, does not align with status.proto, where it is called 'message': def details(self) -> str: ... - def initial_metadata(self) -> Metadata: ... def trailing_metadata(self) -> Metadata: ... - """Client-Side Interceptor""" class ClientCallDetails: @@ -465,7 +328,6 @@ class ClientCallDetails: compression: typing.Optional[Compression] - TRequest = typing.TypeVar("TRequest") TResponse = typing.TypeVar("TResponse") @@ -475,13 +337,11 @@ TResponse = typing.TypeVar("TResponse") # status, the returned Call-Future’s exception value will be an RpcError. # class CallFuture(Call, Future[TResponse], typing.Generic[TResponse]): - pass - + ... class UnaryUnaryClientInterceptor(typing.Generic[TRequest, TResponse]): def intercept_unary_unary( self, - # FIXME: decode these cryptic runes to confirm the typing mystery of # this callable's signature that was left for us by past civilisations: # @@ -498,28 +358,20 @@ class UnaryUnaryClientInterceptor(typing.Generic[TRequest, TResponse]): # RpcError. # continuation: typing.Callable[[ClientCallDetails, TRequest], CallFuture[TResponse]], - client_call_details: ClientCallDetails, - request: TRequest, - - ) -> CallFuture[TResponse]: - ... - + ) -> CallFuture[TResponse]: ... class CallIterator(typing.Generic[TResponse], Call): def __iter__(self) -> typing.Iterator[TResponse]: ... - class UnaryStreamClientInterceptor(typing.Generic[TRequest, TResponse]): def intercept_unary_stream( self, continuation: typing.Callable[[ClientCallDetails, TRequest], CallIterator[TResponse]], client_call_details: ClientCallDetails, request: TRequest, - ) -> CallIterator[TResponse]: - ... - + ) -> CallIterator[TResponse]: ... class StreamUnaryClientInterceptor(typing.Generic[TRequest, TResponse]): def intercept_stream_unary( @@ -527,9 +379,7 @@ class StreamUnaryClientInterceptor(typing.Generic[TRequest, TResponse]): continuation: typing.Callable[[ClientCallDetails, TRequest], CallFuture[TResponse]], client_call_details: ClientCallDetails, request_iterator: typing.Iterator[TRequest], - ) -> CallFuture[TResponse]: - ... - + ) -> CallFuture[TResponse]: ... class StreamStreamClientInterceptor(typing.Generic[TRequest, TResponse]): def intercept_stream_stream( @@ -537,27 +387,20 @@ class StreamStreamClientInterceptor(typing.Generic[TRequest, TResponse]): continuation: typing.Callable[[ClientCallDetails, TRequest], CallIterator[TResponse]], client_call_details: ClientCallDetails, request_iterator: typing.Iterator[TRequest], - ) -> CallIterator[TResponse]: - ... - + ) -> CallIterator[TResponse]: ... """Service-Side Context""" class ServicerContext(RpcContext): - # misnamed parameter 'details', does not align with status.proto, where it is called 'message': def abort(self, code: StatusCode, details: str) -> typing.NoReturn: ... def abort_with_status(self, status: Status) -> typing.NoReturn: ... # FIXME: The docs say "A map of strings to an iterable of bytes for each auth property". # Does that mean 'bytes' (which is iterable), or 'typing.Iterable[bytes]'? - def auth_context(self) -> typing.Mapping[str, bytes]: - ... - + def auth_context(self) -> typing.Mapping[str, bytes]: ... def disable_next_message_compression(self) -> None: ... - def invocation_metadata(self) -> Metadata: ... - def peer(self) -> str: ... def peer_identities(self) -> typing.Optional[typing.Iterable[bytes]]: ... def peer_identity_key(self) -> typing.Optional[str]: ... @@ -568,10 +411,8 @@ class ServicerContext(RpcContext): # misnamed function 'details', does not align with status.proto, where it is called 'message': def set_details(self, details: str) -> None: ... - def trailing_metadata(self) -> Metadata: ... - """Service-Side Handler""" class RpcMethodHandler(typing.Generic[TRequest, TResponse]): @@ -592,33 +433,24 @@ class RpcMethodHandler(typing.Generic[TRequest, TResponse]): stream_stream: typing.Optional[typing.Callable[[typing.Iterator[TRequest], ServicerContext], typing.Iterator[TResponse]]] - class HandlerCallDetails: method: str invocation_metadata: Metadata - class GenericRpcHandler(typing.Generic[TRequest, TResponse]): - def service(self, handler_call_details: HandlerCallDetails) -> typing.Optional[RpcMethodHandler[TRequest, TResponse]]: - ... + def service(self, handler_call_details: HandlerCallDetails) -> typing.Optional[RpcMethodHandler[TRequest, TResponse]]: ... class ServiceRpcHandler(GenericRpcHandler[TRequest, TResponse], typing.Generic[TRequest, TResponse]): def service_name(self) -> str: ... - """Service-Side Interceptor""" class ServerInterceptor(typing.Generic[TRequest, TResponse]): def intercept_service( self, - continuation: typing.Callable[ - [HandlerCallDetails], - typing.Optional[RpcMethodHandler[TRequest, TResponse]] - ], + continuation: typing.Callable[[HandlerCallDetails], typing.Optional[RpcMethodHandler[TRequest, TResponse]]], handler_call_details: HandlerCallDetails, - ) -> typing.Optional[RpcMethodHandler[TRequest, TResponse]]: - ... - + ) -> typing.Optional[RpcMethodHandler[TRequest, TResponse]]: ... """Multi-Callable Interfaces""" @@ -629,45 +461,32 @@ class UnaryUnaryMultiCallable(typing.Generic[TRequest, TResponse]): timeout: typing.Optional[float] = None, metadata: typing.Optional[Metadata] = None, credentials: typing.Optional[CallCredentials] = None, - # FIXME: optional bool seems weird, but that's what the docs suggest wait_for_ready: typing.Optional[bool] = None, - compression: typing.Optional[Compression] = None, - ) -> TResponse: - ... - + ) -> TResponse: ... def future( self, request: TRequest, timeout: typing.Optional[float] = None, metadata: typing.Optional[Metadata] = None, credentials: typing.Optional[CallCredentials] = None, - # FIXME: optional bool seems weird, but that's what the docs suggest wait_for_ready: typing.Optional[bool] = None, - compression: typing.Optional[Compression] = None, - ) -> CallFuture[TResponse]: - ... - + ) -> CallFuture[TResponse]: ... def with_call( self, request: TRequest, timeout: typing.Optional[float] = None, metadata: typing.Optional[Metadata] = None, credentials: typing.Optional[CallCredentials] = None, - # FIXME: optional bool seems weird, but that's what the docs suggest wait_for_ready: typing.Optional[bool] = None, - compression: typing.Optional[Compression] = None, - - # FIXME: Return value is documented as "The response value for the RPC and a Call value for the RPC"; - # this is slightly unclear so this return type is a best-effort guess. - ) -> typing.Tuple[TResponse, Call]: - ... - + # FIXME: Return value is documented as "The response value for the RPC and a Call value for the RPC"; + # this is slightly unclear so this return type is a best-effort guess. + ) -> tuple[TResponse, Call]: ... class UnaryStreamMultiCallable(typing.Generic[TRequest, TResponse]): def __call__( @@ -676,15 +495,10 @@ class UnaryStreamMultiCallable(typing.Generic[TRequest, TResponse]): timeout: typing.Optional[float] = None, metadata: typing.Optional[Metadata] = None, credentials: typing.Optional[CallCredentials] = None, - # FIXME: optional bool seems weird, but that's what the docs suggest wait_for_ready: typing.Optional[bool] = None, - compression: typing.Optional[Compression] = None, - - ) -> CallIterator[TResponse]: - ... - + ) -> CallIterator[TResponse]: ... class StreamUnaryMultiCallable(typing.Generic[TRequest, TResponse]): def __call__( @@ -693,45 +507,32 @@ class StreamUnaryMultiCallable(typing.Generic[TRequest, TResponse]): timeout: typing.Optional[float] = None, metadata: typing.Optional[Metadata] = None, credentials: typing.Optional[CallCredentials] = None, - # FIXME: optional bool seems weird, but that's what the docs suggest wait_for_ready: typing.Optional[bool] = None, - compression: typing.Optional[Compression] = None, - ) -> TResponse: - ... - + ) -> TResponse: ... def future( self, request_iterator: typing.Iterator[TRequest], timeout: typing.Optional[float] = None, metadata: typing.Optional[Metadata] = None, credentials: typing.Optional[CallCredentials] = None, - # FIXME: optional bool seems weird, but that's what the docs suggest wait_for_ready: typing.Optional[bool] = None, - compression: typing.Optional[Compression] = None, - ) -> CallFuture[TResponse]: - ... - + ) -> CallFuture[TResponse]: ... def with_call( self, request_iterator: typing.Iterator[TRequest], timeout: typing.Optional[float] = None, metadata: typing.Optional[Metadata] = None, credentials: typing.Optional[CallCredentials] = None, - # FIXME: optional bool seems weird, but that's what the docs suggest wait_for_ready: typing.Optional[bool] = None, - compression: typing.Optional[Compression] = None, - - # FIXME: Return value is documented as "The response value for the RPC and a Call value for the RPC"; - # this is slightly unclear so this return type is a best-effort guess. - ) -> typing.Tuple[TResponse, Call]: - ... - + # FIXME: Return value is documented as "The response value for the RPC and a Call value for the RPC"; + # this is slightly unclear so this return type is a best-effort guess. + ) -> tuple[TResponse, Call]: ... class StreamStreamMultiCallable(typing.Generic[TRequest, TResponse]): def __call__( @@ -740,33 +541,23 @@ class StreamStreamMultiCallable(typing.Generic[TRequest, TResponse]): timeout: typing.Optional[float] = None, metadata: typing.Optional[Metadata] = None, credentials: typing.Optional[CallCredentials] = None, - # FIXME: optional bool seems weird, but that's what the docs suggest wait_for_ready: typing.Optional[bool] = None, - compression: typing.Optional[Compression] = None, - - ) -> CallIterator[TResponse]: - ... - + ) -> CallIterator[TResponse]: ... """Future Interfaces""" - class FutureTimeoutError(Exception): - pass - + ... class FutureCancelledError(Exception): - pass - + ... TFutureValue = typing.TypeVar("TFutureValue") class Future(typing.Generic[TFutureValue]): - def add_done_callback(self, fn: typing.Callable[[Future[TFutureValue]], None]) -> None: - ... - + def add_done_callback(self, fn: typing.Callable[[Future[TFutureValue]], None]) -> None: ... def cancel(self) -> bool: ... def cancelled(self) -> bool: ... def done(self) -> bool: ... @@ -777,15 +568,8 @@ class Future(typing.Generic[TFutureValue]): # FIXME: unsure of the exact return type here. Is it a traceback.StackSummary? def traceback(self, timeout: typing.Optional[float] = None) -> typing.Any: ... - """Runtime Protobuf Parsing""" -def protos(protobuf_path: str) -> ModuleType: - ... - -def services(protobuf_path: str) -> ModuleType: - ... - -def protos_and_services(protobuf_path: str) -> typing.Tuple[ModuleType, ModuleType]: - ... - +def protos(protobuf_path: str) -> ModuleType: ... +def services(protobuf_path: str) -> ModuleType: ... +def protos_and_services(protobuf_path: str) -> tuple[ModuleType, ModuleType]: ... diff --git a/stubs/grpc/grpc/aio/__init__.pyi b/stubs/grpc/grpc/aio/__init__.pyi index 9ac28efeebdc..44b185eeda79 100644 --- a/stubs/grpc/grpc/aio/__init__.pyi +++ b/stubs/grpc/grpc/aio/__init__.pyi @@ -2,22 +2,24 @@ import asyncio import typing from concurrent import futures from types import TracebackType + from grpc import ( - _Options, - _PartialStubMustCastOrIgnore, - RpcError, - Compression, - GenericRpcHandler, - ServerCredentials, - StatusCode, - ChannelCredentials, CallCredentials, ChannelConnectivity, + ChannelCredentials, + Compression, + GenericRpcHandler, HandlerCallDetails, + RpcError, RpcMethodHandler, + ServerCredentials, + StatusCode, + _Options, + _PartialStubMustCastOrIgnore, ) """Exceptions""" + class BaseError(Exception): ... class UsageError(BaseError): ... class AbortError(BaseError): ... @@ -31,15 +33,13 @@ class AioRpcError(RpcError): trailing_metadata: Metadata, details: typing.Optional[str], debug_error_string: typing.Optional[str], - ) -> None: - ... + ) -> None: ... # FIXME: confirm if these are present in the parent type. The remaining # methods already exist. def debug_error_string(self) -> str: ... def initial_metadata(self) -> Metadata: ... - """Create Client""" ClientInterceptor = _PartialStubMustCastOrIgnore @@ -58,7 +58,6 @@ def secure_channel( interceptors: typing.Optional[typing.Sequence[ClientInterceptor]] = None, ) -> Channel: ... - """Create Server""" def server( @@ -70,7 +69,6 @@ def server( compression: typing.Optional[Compression] = None, ) -> Server: ... - """Channel Object""" # XXX: The docs suggest these type signatures for aio, but not for non-async, @@ -81,75 +79,58 @@ ResponseDeserializer = typing.Callable[[bytes], typing.Any] class Channel: async def close(self, grace: typing.Optional[float]) -> None: ... - def get_state(self, try_to_connect: bool = False) -> ChannelConnectivity: ... - async def wait_for_state_change(self, last_observed_state: ChannelConnectivity) -> None: ... - def stream_stream( self, method: str, request_serializer: typing.Optional[RequestSerializer], response_deserializer: typing.Optional[ResponseDeserializer], ) -> StreamStreamMultiCallable: ... - def stream_unary( self, method: str, request_serializer: typing.Optional[RequestSerializer], response_deserializer: typing.Optional[ResponseDeserializer], ) -> StreamUnaryMultiCallable: ... - def unary_stream( self, method: str, request_serializer: typing.Optional[RequestSerializer], response_deserializer: typing.Optional[ResponseDeserializer], ) -> UnaryStreamMultiCallable: ... - def unary_unary( self, method: str, request_serializer: typing.Optional[RequestSerializer], response_deserializer: typing.Optional[ResponseDeserializer], ) -> UnaryUnaryMultiCallable: ... - async def __aenter__(self) -> Channel: ... - async def __aexit__( self, - exc_type: typing.Optional[typing.Type[BaseException]], + exc_type: typing.Optional[type[BaseException]], exc_val: typing.Optional[BaseException], exc_tb: typing.Optional[TracebackType], ) -> typing.Optional[bool]: ... - async def channel_ready(self) -> None: ... """Server Object""" class Server: - def add_generic_rpc_handlers( - self, - generic_rpc_handlers: typing.Iterable[GenericRpcHandler], - ) -> None: ... + def add_generic_rpc_handlers(self, generic_rpc_handlers: typing.Iterable[GenericRpcHandler]) -> None: ... # Returns an integer port on which server will accept RPC requests. def add_insecure_port(self, address: str) -> int: ... # Returns an integer port on which server will accept RPC requests. - def add_secure_port( - self, address: str, server_credentials: ServerCredentials - ) -> int: ... - + def add_secure_port(self, address: str, server_credentials: ServerCredentials) -> int: ... async def start(self) -> None: ... # Grace period is in seconds. async def stop(self, grace: typing.Optional[float] = None) -> None: ... # Returns a bool indicates if the operation times out. Timeout is in seconds. - async def wait_for_termination( - self, timeout: typing.Optional[float] = None - ) -> bool: ... + async def wait_for_termination(self, timeout: typing.Optional[float] = None) -> bool: ... """Client-Side Context""" @@ -194,24 +175,13 @@ TResponse = typing.TypeVar("TResponse") """Service-Side Context""" class DoneCallback(typing.Generic[TRequest, TResponse]): - def __call__( - self, - ctx: ServicerContext[TRequest, TResponse], - ) -> None: - ... + def __call__(self, ctx: ServicerContext[TRequest, TResponse]) -> None: ... class ServicerContext(typing.Generic[TRequest, TResponse]): - async def abort( - self, - code: StatusCode, - details: str = "", - trailing_metadata: MetadataType = tuple(), - ) -> typing.NoReturn: ... - + async def abort(self, code: StatusCode, details: str = "", trailing_metadata: MetadataType = tuple()) -> typing.NoReturn: ... async def read(self) -> TRequest: ... async def write(self, message: TResponse) -> None: ... async def send_initial_metadata(self, initial_metadata: MetadataType) -> None: ... - def add_done_callback(self, callback: DoneCallback[TRequest, TResponse]) -> None: ... def set_trailing_metadata(self, trailing_metadata: MetadataType) -> None: ... def invocation_metadata(self) -> typing.Optional[Metadata]: ... @@ -230,7 +200,6 @@ class ServicerContext(typing.Generic[TRequest, TResponse]): def cancelled(self) -> bool: ... def done(self) -> bool: ... - """Client-Side Interceptor""" class ClientCallDetails: @@ -241,8 +210,7 @@ class ClientCallDetails: metadata: typing.Optional[Metadata], credentials: typing.Optional[CallCredentials], wait_for_ready: typing.Optional[bool], - ) -> None: - ... + ) -> None: ... method: str timeout: typing.Optional[float] @@ -255,11 +223,9 @@ class ClientCallDetails: # As at 1.53.0, this is not supported in aio: # compression: typing.Optional[Compression] - class InterceptedCall(typing.Generic[TRequest, TResponse]): def __init__(self, interceptors_task: asyncio.Task) -> None: ... def __del__(self): ... - def cancel(self) -> bool: ... def cancelled(self) -> bool: ... def done(self) -> bool: ... @@ -272,10 +238,8 @@ class InterceptedCall(typing.Generic[TRequest, TResponse]): async def debug_error_string(self) -> typing.Optional[str]: ... async def wait_for_connection(self) -> None: ... - class InterceptedUnaryUnaryCall(InterceptedCall[TRequest, TResponse], typing.Generic[TRequest, TResponse]): def __await__(self): ... - def __init__( self, interceptors: typing.Sequence[UnaryUnaryClientInterceptor], @@ -289,8 +253,7 @@ class InterceptedUnaryUnaryCall(InterceptedCall[TRequest, TResponse], typing.Gen request_serializer: RequestSerializer, response_deserializer: ResponseDeserializer, loop: asyncio.AbstractEventLoop, - ) -> None: - ... + ) -> None: ... # pylint: disable=too-many-arguments async def _invoke( @@ -304,12 +267,9 @@ class InterceptedUnaryUnaryCall(InterceptedCall[TRequest, TResponse], typing.Gen request: TRequest, request_serializer: RequestSerializer, response_deserializer: ResponseDeserializer, - ) -> UnaryUnaryCall: - ... - + ) -> UnaryUnaryCall: ... def time_remaining(self) -> typing.Optional[float]: ... - class UnaryUnaryClientInterceptor(typing.Generic[TRequest, TResponse]): async def intercept_unary_unary( self, @@ -317,9 +277,7 @@ class UnaryUnaryClientInterceptor(typing.Generic[TRequest, TResponse]): continuation: typing.Callable[[ClientCallDetails, TRequest], UnaryUnaryCall[TRequest, TResponse]], client_call_details: ClientCallDetails, request: TRequest, - ) -> TResponse: - ... - + ) -> TResponse: ... class UnaryStreamClientInterceptor(typing.Generic[TRequest, TResponse]): async def intercept_unary_stream( @@ -327,12 +285,7 @@ class UnaryStreamClientInterceptor(typing.Generic[TRequest, TResponse]): continuation: typing.Callable[[ClientCallDetails, TRequest], UnaryStreamCall[TRequest, TResponse]], client_call_details: ClientCallDetails, request: TRequest, - ) -> typing.Union[ - typing.AsyncIterable[TResponse], - UnaryStreamCall[TRequest, TResponse], - ]: - ... - + ) -> typing.Union[typing.AsyncIterable[TResponse], UnaryStreamCall[TRequest, TResponse]]: ... class StreamUnaryClientInterceptor(typing.Generic[TRequest, TResponse]): async def intercept_stream_unary( @@ -340,12 +293,7 @@ class StreamUnaryClientInterceptor(typing.Generic[TRequest, TResponse]): continuation: typing.Callable[[ClientCallDetails, TRequest], StreamUnaryCall[TRequest, TResponse]], client_call_details: ClientCallDetails, request_iterator: typing.Union[typing.AsyncIterable[TRequest], typing.Iterable[TRequest]], - ) -> typing.Union[ - typing.AsyncIterable[TResponse], - UnaryStreamCall[TRequest, TResponse], - ]: - ... - + ) -> typing.Union[typing.AsyncIterable[TResponse], UnaryStreamCall[TRequest, TResponse]]: ... class StreamStreamClientInterceptor(typing.Generic[TRequest, TResponse]): async def intercept_stream_stream( @@ -353,26 +301,16 @@ class StreamStreamClientInterceptor(typing.Generic[TRequest, TResponse]): continuation: typing.Callable[[ClientCallDetails, TRequest], StreamStreamCall[TRequest, TResponse]], client_call_details: ClientCallDetails, request_iterator: typing.Union[typing.AsyncIterable[TRequest], typing.Iterable[TRequest]], - ) -> typing.Union[ - typing.AsyncIterable[TResponse], - StreamStreamCall[TRequest, TResponse], - ]: - ... - + ) -> typing.Union[typing.AsyncIterable[TResponse], StreamStreamCall[TRequest, TResponse]]: ... """Server-Side Interceptor""" class ServerInterceptor(typing.Generic[TRequest, TResponse]): async def intercept_service( self, - continuation: typing.Callable[ - [HandlerCallDetails], - typing.Awaitable[RpcMethodHandler[TRequest, TResponse]], - ], + continuation: typing.Callable[[HandlerCallDetails], typing.Awaitable[RpcMethodHandler[TRequest, TResponse]]], handler_call_details: HandlerCallDetails, - ) -> RpcMethodHandler[TRequest, TResponse]: - ... - + ) -> RpcMethodHandler[TRequest, TResponse]: ... """Multi-Callable Interfaces""" @@ -403,9 +341,7 @@ class UnaryStreamMultiCallable(typing.Generic[TRequest, TResponse]): class StreamUnaryMultiCallable(typing.Generic[TRequest, TResponse]): def __call__( self, - request_iterator: typing.Optional[ - typing.Union[typing.AsyncIterator[TRequest], typing.Iterator[TRequest]] - ], + request_iterator: typing.Optional[typing.Union[typing.AsyncIterator[TRequest], typing.Iterator[TRequest]]], timeout: typing.Optional[float] = None, metadata: typing.Optional[MetadataType] = None, credentials: typing.Optional[CallCredentials] = None, @@ -417,9 +353,7 @@ class StreamUnaryMultiCallable(typing.Generic[TRequest, TResponse]): class StreamStreamMultiCallable(typing.Generic[TRequest, TResponse]): def __call__( self, - request_iterator: typing.Optional[ - typing.Union[typing.AsyncIterator[TRequest], typing.Iterator[TRequest]] - ], + request_iterator: typing.Optional[typing.Union[typing.AsyncIterator[TRequest], typing.Iterator[TRequest]]], timeout: typing.Optional[float] = None, metadata: typing.Optional[MetadataType] = None, credentials: typing.Optional[CallCredentials] = None, @@ -428,30 +362,27 @@ class StreamStreamMultiCallable(typing.Generic[TRequest, TResponse]): compression: typing.Optional[Compression] = None, ) -> StreamStreamCall[TRequest, TResponse]: ... - """Metadata""" MetadataKey = str MetadataValue = typing.Union[str, bytes] -MetadatumType = typing.Tuple[MetadataKey, MetadataValue] +MetadatumType = tuple[MetadataKey, MetadataValue] MetadataType = typing.Union[Metadata, typing.Sequence[MetadatumType]] class Metadata(typing.Mapping): - def __init__(self, *args: typing.Tuple[MetadataKey, MetadataValue]) -> None: ... + def __init__(self, *args: tuple[MetadataKey, MetadataValue]) -> None: ... @classmethod - def from_tuple( - cls, raw_metadata: typing.Tuple[MetadataKey, MetadataValue] - ) -> Metadata: ... + def from_tuple(cls, raw_metadata: tuple[MetadataKey, MetadataValue]) -> Metadata: ... def add(self, key: MetadataKey, value: MetadataValue) -> None: ... def __len__(self) -> int: ... def __getitem__(self, key: MetadataKey) -> MetadataValue: ... def __setitem__(self, key: MetadataKey, value: MetadataValue) -> None: ... def __delitem__(self, key: MetadataKey) -> None: ... def delete_all(self, key: MetadataKey) -> None: ... - def __iter__(self) -> typing.Iterator[typing.Tuple[MetadataKey, MetadataValue]]: ... - def get_all(self, key: MetadataKey) -> typing.List[MetadataValue]: ... - def set_all(self, key: MetadataKey, values: typing.List[MetadataValue]) -> None: ... + def __iter__(self) -> typing.Iterator[tuple[MetadataKey, MetadataValue]]: ... + def get_all(self, key: MetadataKey) -> list[MetadataValue]: ... + def set_all(self, key: MetadataKey, values: list[MetadataValue]) -> None: ... def __contains__(self, key: object) -> bool: ... - def __eq__(self, other: typing.Any) -> bool: ... + def __eq__(self, other: object) -> bool: ... def __add__(self, other: typing.Any) -> Metadata: ... def __repr__(self) -> str: ... diff --git a/stubs/grpc_channelz/grpc_channelz/v1/_servicer.pyi b/stubs/grpc_channelz/grpc_channelz/v1/_servicer.pyi index 702b304d8d09..f8b7ba089b47 100644 --- a/stubs/grpc_channelz/grpc_channelz/v1/_servicer.pyi +++ b/stubs/grpc_channelz/grpc_channelz/v1/_servicer.pyi @@ -1,32 +1,25 @@ -from grpc import ServicerContext import grpc_channelz.v1.channelz_pb2 as _channelz_pb2 import grpc_channelz.v1.channelz_pb2_grpc as _channelz_pb2_grpc +from grpc import ServicerContext class ChannelzServicer(_channelz_pb2_grpc.ChannelzServicer): @staticmethod - def GetTopChannels(request: _channelz_pb2.GetTopChannelsRequest, context: ServicerContext) -> _channelz_pb2.GetTopChannelsResponse: - ... - + def GetTopChannels( + request: _channelz_pb2.GetTopChannelsRequest, context: ServicerContext + ) -> _channelz_pb2.GetTopChannelsResponse: ... @staticmethod - def GetServers(request: _channelz_pb2.GetServersRequest, context: ServicerContext) -> _channelz_pb2.GetServersResponse: - ... - + def GetServers(request: _channelz_pb2.GetServersRequest, context: ServicerContext) -> _channelz_pb2.GetServersResponse: ... @staticmethod - def GetServer(request: _channelz_pb2.GetServerRequest, context: ServicerContext) -> _channelz_pb2.GetServerResponse: - ... - + def GetServer(request: _channelz_pb2.GetServerRequest, context: ServicerContext) -> _channelz_pb2.GetServerResponse: ... @staticmethod - def GetServerSockets(request: _channelz_pb2.GetServerSocketsRequest, context: ServicerContext) -> _channelz_pb2.GetServerSocketsResponse: - ... - + def GetServerSockets( + request: _channelz_pb2.GetServerSocketsRequest, context: ServicerContext + ) -> _channelz_pb2.GetServerSocketsResponse: ... @staticmethod - def GetChannel(request: _channelz_pb2.GetChannelRequest, context: ServicerContext) -> _channelz_pb2.GetChannelResponse: - ... - + def GetChannel(request: _channelz_pb2.GetChannelRequest, context: ServicerContext) -> _channelz_pb2.GetChannelResponse: ... @staticmethod - def GetSubchannel(request: _channelz_pb2.GetSubchannelRequest, context: ServicerContext) -> _channelz_pb2.GetSubchannelResponse: - ... - + def GetSubchannel( + request: _channelz_pb2.GetSubchannelRequest, context: ServicerContext + ) -> _channelz_pb2.GetSubchannelResponse: ... @staticmethod - def GetSocket(request: _channelz_pb2.GetSocketRequest, context: ServicerContext) -> _channelz_pb2.GetSocketResponse: - ... + def GetSocket(request: _channelz_pb2.GetSocketRequest, context: ServicerContext) -> _channelz_pb2.GetSocketResponse: ... diff --git a/stubs/grpc_channelz/grpc_channelz/v1/channelz.pyi b/stubs/grpc_channelz/grpc_channelz/v1/channelz.pyi index a6635710c829..f5aa790e028d 100644 --- a/stubs/grpc_channelz/grpc_channelz/v1/channelz.pyi +++ b/stubs/grpc_channelz/grpc_channelz/v1/channelz.pyi @@ -1,4 +1,3 @@ from grpc import Server -def add_channelz_servicer(server: Server) -> None: - ... +def add_channelz_servicer(server: Server) -> None: ... diff --git a/stubs/grpc_health/grpc_health/v1/health.pyi b/stubs/grpc_health/grpc_health/v1/health.pyi index f7552f08cc22..41b0ea7c5f0e 100644 --- a/stubs/grpc_health/grpc_health/v1/health.pyi +++ b/stubs/grpc_health/grpc_health/v1/health.pyi @@ -1,43 +1,27 @@ from concurrent import futures -from grpc import ServicerContext -from grpc_health.v1 import health_pb2 as _health_pb2 -from grpc_health.v1 import health_pb2_grpc as _health_pb2_grpc from typing import Callable, Optional +from grpc import ServicerContext +from grpc_health.v1 import health_pb2 as _health_pb2, health_pb2_grpc as _health_pb2_grpc + SERVICE_NAME: str OVERALL_HEALTH: str class _Watcher: - def __init__(self) -> None: - ... - - def __iter__(self) -> _Watcher: - ... - - def next(self) -> _health_pb2.HealthCheckResponse: - ... - - def __next__(self) -> _health_pb2.HealthCheckResponse: - ... - - def add(self, response: _health_pb2.HealthCheckResponse) -> None: - ... - - def close(self) -> None: - ... + def __init__(self) -> None: ... + def __iter__(self) -> _Watcher: ... + def next(self) -> _health_pb2.HealthCheckResponse: ... + def __next__(self) -> _health_pb2.HealthCheckResponse: ... + def add(self, response: _health_pb2.HealthCheckResponse) -> None: ... + def close(self) -> None: ... class HealthServicer(_health_pb2_grpc.HealthServicer): - def __init__(self, experimental_non_blocking: bool = ..., experimental_thread_pool: Optional[futures.ThreadPoolExecutor] = ...) -> None: - ... - - def Check(self, request: _health_pb2.HealthCheckRequest, context: ServicerContext) -> _health_pb2.HealthCheckResponse: - ... - - def Watch(self, request: _health_pb2.HealthCheckRequest, context: ServicerContext, send_response_callback: Optional[Callable] = ...) -> _health_pb2.HealthCheckResponse: - ... - - def set(self, service: str, status: _health_pb2.HealthCheckResponse.ServingStatus) -> None: - ... - - def enter_graceful_shutdown(self) -> None: - ... + def __init__( + self, experimental_non_blocking: bool = ..., experimental_thread_pool: Optional[futures.ThreadPoolExecutor] = ... + ) -> None: ... + def Check(self, request: _health_pb2.HealthCheckRequest, context: ServicerContext) -> _health_pb2.HealthCheckResponse: ... + def Watch( + self, request: _health_pb2.HealthCheckRequest, context: ServicerContext, send_response_callback: Optional[Callable] = ... + ) -> _health_pb2.HealthCheckResponse: ... + def set(self, service: str, status: _health_pb2.HealthCheckResponse.ServingStatus) -> None: ... + def enter_graceful_shutdown(self) -> None: ... diff --git a/stubs/grpc_reflection/grpc_reflection/v1alpha/reflection.pyi b/stubs/grpc_reflection/grpc_reflection/v1alpha/reflection.pyi index 3ac378c90b84..eb3496a146e6 100644 --- a/stubs/grpc_reflection/grpc_reflection/v1alpha/reflection.pyi +++ b/stubs/grpc_reflection/grpc_reflection/v1alpha/reflection.pyi @@ -1,8 +1,8 @@ import typing import grpc -from grpc import aio from google.protobuf import descriptor_pool +from grpc import aio from grpc_reflection.v1alpha import reflection_pb2 as _reflection_pb2 from grpc_reflection.v1alpha._base import BaseReflectionServicer @@ -13,15 +13,9 @@ AnyServicerContext = typing.Union[grpc.ServicerContext, aio.ServicerContext] class ReflectionServicer(BaseReflectionServicer): def ServerReflectionInfo( - self, - request_iterator: typing.Iterable[_reflection_pb2.ServerReflectionRequest], - context: AnyServicerContext, - ) -> None: - ... + self, request_iterator: typing.Iterable[_reflection_pb2.ServerReflectionRequest], context: AnyServicerContext + ) -> None: ... def enable_server_reflection( - service_names: typing.Iterable[str], - server: AnyServer, - pool: typing.Optional[descriptor_pool.DescriptorPool] = ..., -) -> None: - ... + service_names: typing.Iterable[str], server: AnyServer, pool: typing.Optional[descriptor_pool.DescriptorPool] = ... +) -> None: ... diff --git a/stubs/grpc_status/grpc_status/rpc_status.pyi b/stubs/grpc_status/grpc_status/rpc_status.pyi index 8cdc1ee816a0..0726d4f8bab5 100644 --- a/stubs/grpc_status/grpc_status/rpc_status.pyi +++ b/stubs/grpc_status/grpc_status/rpc_status.pyi @@ -1,17 +1,13 @@ -import grpc import typing +import grpc # XXX: don't yet know how to add a stub for google.rpc.status_pb2.Status # without affecting other stuff; may need to make a stub-only package for # google.rpc as well. - # Returns a google.rpc.status.Status message corresponding to a given grpc.Call. -def from_call(call: grpc.Call) -> typing.Any: - ... - +def from_call(call: grpc.Call) -> typing.Any: ... # Convert a google.rpc.status.Status message to grpc.Status. -def to_status(status: typing.Any) -> grpc.Status: - ... +def to_status(status: typing.Any) -> grpc.Status: ... From 775a418f50bfca2adf19caa9b400cab783027ae3 Mon Sep 17 00:00:00 2001 From: Blake Williams Date: Wed, 27 Dec 2023 16:48:41 +1100 Subject: [PATCH 03/18] Fix ruff lints --- stubs/grpc/grpc/__init__.pyi | 223 ++++++++---------- stubs/grpc/grpc/aio/__init__.pyi | 173 +++++++------- stubs/grpc_health/grpc_health/v1/health.pyi | 6 +- .../grpc_reflection/v1alpha/reflection.pyi | 6 +- 4 files changed, 183 insertions(+), 225 deletions(-) diff --git a/stubs/grpc/grpc/__init__.pyi b/stubs/grpc/grpc/__init__.pyi index efd4cabd4319..caa4063bcb06 100644 --- a/stubs/grpc/grpc/__init__.pyi +++ b/stubs/grpc/grpc/__init__.pyi @@ -12,8 +12,7 @@ __version__: str # The alternative is typing.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. -class _PartialStubMustCastOrIgnore: - ... +class _PartialStubMustCastOrIgnore: ... # 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 @@ -36,39 +35,32 @@ class LocalConnectionType(enum.Enum): # - https://github.com/grpc/grpc/blob/0e1984effd7e977ef18f1ad7fde7d10a2a153e1d/src/python/grpcio_tests/tests/unit/_metadata_test.py#L71 # - https://github.com/grpc/grpc/blob/0e1984effd7e977ef18f1ad7fde7d10a2a153e1d/src/python/grpcio_tests/tests/unit/_metadata_test.py#L58 # - https://github.com/grpc/grpc/blob/0e1984effd7e977ef18f1ad7fde7d10a2a153e1d/src/python/grpcio_tests/tests/unit/_invocation_defects_test.py#L66 -Metadata = tuple[tuple[str, typing.Union[str, bytes]], ...] +Metadata = tuple[tuple[str, str | bytes], ...] """Create Client""" -def insecure_channel( - target: str, options: typing.Optional[_Options] = None, compression: typing.Optional[Compression] = None -) -> Channel: ... +def insecure_channel(target: str, options: _Options | None = None, compression: Compression | None = None) -> Channel: ... def secure_channel( - target: str, - credentials: ChannelCredentials, - options: typing.Optional[_Options] = None, - compression: typing.Optional[Compression] = None, + target: str, credentials: ChannelCredentials, options: _Options | None = None, compression: Compression | None = None ) -> Channel: ... -Interceptor = typing.Union[ - UnaryUnaryClientInterceptor, UnaryStreamClientInterceptor, StreamUnaryClientInterceptor, StreamStreamClientInterceptor -] +Interceptor = ( + UnaryUnaryClientInterceptor | UnaryStreamClientInterceptor | StreamUnaryClientInterceptor | StreamStreamClientInterceptor +) def intercept_channel(channel: Channel, *interceptors: Interceptor) -> Channel: ... """Create Client Credentials""" def ssl_channel_credentials( - root_certificates: typing.Optional[bytes] = None, - private_key: typing.Optional[bytes] = None, - certificate_chain: typing.Optional[bytes] = None, + root_certificates: bytes | None = None, private_key: bytes | None = None, certificate_chain: bytes | None = None ) -> ChannelCredentials: ... def local_channel_credentials(local_connect_type: LocalConnectionType = LocalConnectionType.LOCAL_TCP) -> ChannelCredentials: ... -def metadata_call_credentials(metadata_plugin: AuthMetadataPlugin, name: typing.Optional[str] = None) -> CallCredentials: ... +def metadata_call_credentials(metadata_plugin: AuthMetadataPlugin, name: str | None = None) -> CallCredentials: ... def access_token_call_credentials(access_token: str) -> CallCredentials: ... -def alts_channel_credentials(service_accounts: typing.Optional[typing.Sequence[str]] = None) -> ChannelCredentials: ... +def alts_channel_credentials(service_accounts: typing.Sequence[str] | None = None) -> ChannelCredentials: ... def compute_engine_channel_credentials() -> ChannelCredentials: ... -def xds_channel_credentials(fallback_credentials: typing.Optional[ChannelCredentials] = None) -> ChannelCredentials: ... +def xds_channel_credentials(fallback_credentials: ChannelCredentials | None = None) -> ChannelCredentials: ... # GRPC docs say there should be at least two: def composite_call_credentials(creds1: CallCredentials, creds2: CallCredentials, *rest: CallCredentials) -> CallCredentials: ... @@ -82,11 +74,11 @@ def composite_channel_credentials( def server( thread_pool: futures.ThreadPoolExecutor, - handlers: typing.Optional[list[GenericRpcHandler]] = None, - interceptors: typing.Optional[list[ServerInterceptor]] = None, - options: typing.Optional[_Options] = None, - maximum_concurrent_rpcs: typing.Optional[int] = None, - compression: typing.Optional[Compression] = None, + handlers: list[GenericRpcHandler] | None = None, + interceptors: list[ServerInterceptor] | None = None, + options: _Options | None = None, + maximum_concurrent_rpcs: int | None = None, + compression: Compression | None = None, xds: bool = False, ) -> Server: ... @@ -96,12 +88,12 @@ CertificateChainPair = tuple[bytes, bytes] def ssl_server_credentials( private_key_certificate_chain_pairs: list[CertificateChainPair], - root_certificates: typing.Optional[bytes] = None, + root_certificates: bytes | None = None, require_client_auth: bool = False, ) -> ServerCredentials: ... def local_server_credentials(local_connect_type: LocalConnectionType = LocalConnectionType.LOCAL_TCP) -> ServerCredentials: ... def ssl_server_certificate_configuration( - private_key_certificate_chain_pairs: list[CertificateChainPair], root_certificates: typing.Optional[bytes] = None + private_key_certificate_chain_pairs: list[CertificateChainPair], root_certificates: bytes | None = None ) -> ServerCertificateConfiguration: ... def dynamic_ssl_server_credentials( initial_certificate_configuration: ServerCertificateConfiguration, @@ -130,23 +122,23 @@ ResponseSerializer = typing.Callable def unary_unary_rpc_method_handler( behavior: Behaviour, - request_deserializer: typing.Optional[RequestDeserializer] = None, - response_serializer: typing.Optional[ResponseSerializer] = None, + request_deserializer: RequestDeserializer | None = None, + response_serializer: ResponseSerializer | None = None, ) -> RpcMethodHandler: ... def unary_stream_rpc_method_handler( behavior: Behaviour, - request_deserializer: typing.Optional[RequestDeserializer] = None, - response_serializer: typing.Optional[ResponseSerializer] = None, + request_deserializer: RequestDeserializer | None = None, + response_serializer: ResponseSerializer | None = None, ) -> RpcMethodHandler: ... def stream_unary_rpc_method_handler( behavior: Behaviour, - request_deserializer: typing.Optional[RequestDeserializer] = None, - response_serializer: typing.Optional[ResponseSerializer] = None, + request_deserializer: RequestDeserializer | None = None, + response_serializer: ResponseSerializer | None = None, ) -> RpcMethodHandler: ... def stream_stream_rpc_method_handler( behavior: Behaviour, - request_deserializer: typing.Optional[RequestDeserializer] = None, - response_serializer: typing.Optional[ResponseSerializer] = None, + request_deserializer: RequestDeserializer | None = None, + response_serializer: ResponseSerializer | None = None, ) -> RpcMethodHandler: ... def method_handlers_generic_handler(service: str, method_handlers: dict[str, RpcMethodHandler]) -> GenericRpcHandler: ... @@ -203,38 +195,23 @@ ResponseDeserializer = typing.Callable class Channel: def close(self) -> None: ... def stream_stream( - self, - method: str, - request_serializer: typing.Optional[RequestSerializer], - response_deserializer: typing.Optional[ResponseDeserializer], + self, method: str, request_serializer: RequestSerializer | None, response_deserializer: ResponseDeserializer | None ) -> StreamStreamMultiCallable: ... def stream_unary( - self, - method: str, - request_serializer: typing.Optional[RequestSerializer], - response_deserializer: typing.Optional[ResponseDeserializer], + self, method: str, request_serializer: RequestSerializer | None, response_deserializer: ResponseDeserializer | None ) -> StreamUnaryMultiCallable: ... def subscribe(self, callback: typing.Callable[[ChannelConnectivity], None], try_to_connect: bool = False) -> None: ... def unary_stream( - self, - method: str, - request_serializer: typing.Optional[RequestSerializer], - response_deserializer: typing.Optional[ResponseDeserializer], + self, method: str, request_serializer: RequestSerializer | None, response_deserializer: ResponseDeserializer | None ) -> UnaryStreamMultiCallable: ... def unary_unary( - self, - method: str, - request_serializer: typing.Optional[RequestSerializer], - response_deserializer: typing.Optional[ResponseDeserializer], + self, method: str, request_serializer: RequestSerializer | None, response_deserializer: ResponseDeserializer | None ) -> UnaryUnaryMultiCallable: ... def unsubscribe(self, callback: typing.Callable[[ChannelConnectivity], None]) -> None: ... def __enter__(self) -> Channel: ... def __exit__( - self, - exc_type: typing.Optional[type[BaseException]], - exc_val: typing.Optional[BaseException], - exc_tb: typing.Optional[TracebackType], - ) -> typing.Optional[bool]: ... + self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + ) -> bool | None: ... """Server Object""" @@ -249,11 +226,11 @@ class Server: def start(self) -> None: ... # Grace period is in seconds. - def stop(self, grace: typing.Optional[float] = None) -> threading.Event: ... + def stop(self, grace: float | None = None) -> threading.Event: ... # Block current thread until the server stops. Returns a bool # indicates if the operation times out. Timeout is in seconds. - def wait_for_termination(self, timeout: typing.Optional[float] = None) -> bool: ... + def wait_for_termination(self, timeout: float | None = None) -> bool: ... """Authentication & Authorization Objects""" @@ -268,7 +245,7 @@ class AuthMetadataContext: method_name: str class AuthMetadataPluginCallback: - def __call__(self, metadata: Metadata, error: typing.Optional[Exception]) -> None: ... + def __call__(self, metadata: Metadata, error: Exception | None) -> None: ... class AuthMetadataPlugin: def __call__(self, context: AuthMetadataContext, callback: AuthMetadataPluginCallback) -> None: ... @@ -292,7 +269,7 @@ class RpcError(Exception): def code(self) -> StatusCode: ... # misnamed property, does not align with status.proto, where it is called 'message': - def details(self) -> typing.Optional[str]: ... + def details(self) -> str | None: ... # XXX: This has a slightly different return type to all the other metadata: def trailing_metadata(self) -> tuple[_Metadatum, ...]: ... @@ -319,14 +296,14 @@ class Call(RpcContext): class ClientCallDetails: method: str - timeout: typing.Optional[float] - metadata: typing.Optional[Metadata] - credentials: typing.Optional[CallCredentials] + timeout: float | None + metadata: Metadata | None + credentials: CallCredentials | None # "This is an EXPERIMENTAL argument. An optional flag t enable wait for ready mechanism." - wait_for_ready: typing.Optional[bool] + wait_for_ready: bool | None - compression: typing.Optional[Compression] + compression: Compression | None TRequest = typing.TypeVar("TRequest") TResponse = typing.TypeVar("TResponse") @@ -336,8 +313,7 @@ TResponse = typing.TypeVar("TResponse") # response message of the RPC. Should the event terminate with non-OK # status, the returned Call-Future’s exception value will be an RpcError. # -class CallFuture(Call, Future[TResponse], typing.Generic[TResponse]): - ... +class CallFuture(Call, Future[TResponse], typing.Generic[TResponse]): ... class UnaryUnaryClientInterceptor(typing.Generic[TRequest, TResponse]): def intercept_unary_unary( @@ -402,8 +378,8 @@ class ServicerContext(RpcContext): def disable_next_message_compression(self) -> None: ... def invocation_metadata(self) -> Metadata: ... def peer(self) -> str: ... - def peer_identities(self) -> typing.Optional[typing.Iterable[bytes]]: ... - def peer_identity_key(self) -> typing.Optional[str]: ... + def peer_identities(self) -> typing.Iterable[bytes] | None: ... + def peer_identity_key(self) -> str | None: ... def send_initial_metadata(self, initial_metadata: Metadata) -> None: ... def set_code(self, code: StatusCode) -> None: ... def set_compression(self, compression: Compression) -> None: ... @@ -420,25 +396,25 @@ class RpcMethodHandler(typing.Generic[TRequest, TResponse]): response_streaming: bool # XXX: not clear from docs whether this is optional or not - request_deserializer: typing.Optional[RequestDeserializer] + request_deserializer: RequestDeserializer | None # XXX: not clear from docs whether this is optional or not - response_serializer: typing.Optional[ResponseSerializer] + response_serializer: ResponseSerializer | None - unary_unary: typing.Optional[typing.Callable[[TRequest, ServicerContext], TResponse]] + unary_unary: typing.Callable[[TRequest, ServicerContext], TResponse] | None - unary_stream: typing.Optional[typing.Callable[[TRequest, ServicerContext], typing.Iterator[TResponse]]] + unary_stream: typing.Callable[[TRequest, ServicerContext], typing.Iterator[TResponse]] | None - stream_unary: typing.Optional[typing.Callable[[typing.Iterator[TRequest], ServicerContext], TResponse]] + stream_unary: typing.Callable[[typing.Iterator[TRequest], ServicerContext], TResponse] | None - stream_stream: typing.Optional[typing.Callable[[typing.Iterator[TRequest], ServicerContext], typing.Iterator[TResponse]]] + stream_stream: typing.Callable[[typing.Iterator[TRequest], ServicerContext], typing.Iterator[TResponse]] | None class HandlerCallDetails: method: str invocation_metadata: Metadata class GenericRpcHandler(typing.Generic[TRequest, TResponse]): - def service(self, handler_call_details: HandlerCallDetails) -> typing.Optional[RpcMethodHandler[TRequest, TResponse]]: ... + def service(self, handler_call_details: HandlerCallDetails) -> RpcMethodHandler[TRequest, TResponse] | None: ... class ServiceRpcHandler(GenericRpcHandler[TRequest, TResponse], typing.Generic[TRequest, TResponse]): def service_name(self) -> str: ... @@ -448,9 +424,9 @@ class ServiceRpcHandler(GenericRpcHandler[TRequest, TResponse], typing.Generic[T class ServerInterceptor(typing.Generic[TRequest, TResponse]): def intercept_service( self, - continuation: typing.Callable[[HandlerCallDetails], typing.Optional[RpcMethodHandler[TRequest, TResponse]]], + continuation: typing.Callable[[HandlerCallDetails], RpcMethodHandler[TRequest, TResponse] | None], handler_call_details: HandlerCallDetails, - ) -> typing.Optional[RpcMethodHandler[TRequest, TResponse]]: ... + ) -> RpcMethodHandler[TRequest, TResponse] | None: ... """Multi-Callable Interfaces""" @@ -458,32 +434,32 @@ class UnaryUnaryMultiCallable(typing.Generic[TRequest, TResponse]): def __call__( self, request: TRequest, - timeout: typing.Optional[float] = None, - metadata: typing.Optional[Metadata] = None, - credentials: typing.Optional[CallCredentials] = None, + timeout: float | None = None, + metadata: Metadata | None = None, + credentials: CallCredentials | None = None, # FIXME: optional bool seems weird, but that's what the docs suggest - wait_for_ready: typing.Optional[bool] = None, - compression: typing.Optional[Compression] = None, + wait_for_ready: bool | None = None, + compression: Compression | None = None, ) -> TResponse: ... def future( self, request: TRequest, - timeout: typing.Optional[float] = None, - metadata: typing.Optional[Metadata] = None, - credentials: typing.Optional[CallCredentials] = None, + timeout: float | None = None, + metadata: Metadata | None = None, + credentials: CallCredentials | None = None, # FIXME: optional bool seems weird, but that's what the docs suggest - wait_for_ready: typing.Optional[bool] = None, - compression: typing.Optional[Compression] = None, + wait_for_ready: bool | None = None, + compression: Compression | None = None, ) -> CallFuture[TResponse]: ... def with_call( self, request: TRequest, - timeout: typing.Optional[float] = None, - metadata: typing.Optional[Metadata] = None, - credentials: typing.Optional[CallCredentials] = None, + timeout: float | None = None, + metadata: Metadata | None = None, + credentials: CallCredentials | None = None, # FIXME: optional bool seems weird, but that's what the docs suggest - wait_for_ready: typing.Optional[bool] = None, - compression: typing.Optional[Compression] = None, + wait_for_ready: bool | None = None, + compression: Compression | None = None, # FIXME: Return value is documented as "The response value for the RPC and a Call value for the RPC"; # this is slightly unclear so this return type is a best-effort guess. ) -> tuple[TResponse, Call]: ... @@ -492,44 +468,44 @@ class UnaryStreamMultiCallable(typing.Generic[TRequest, TResponse]): def __call__( self, request: TRequest, - timeout: typing.Optional[float] = None, - metadata: typing.Optional[Metadata] = None, - credentials: typing.Optional[CallCredentials] = None, + timeout: float | None = None, + metadata: Metadata | None = None, + credentials: CallCredentials | None = None, # FIXME: optional bool seems weird, but that's what the docs suggest - wait_for_ready: typing.Optional[bool] = None, - compression: typing.Optional[Compression] = None, + wait_for_ready: bool | None = None, + compression: Compression | None = None, ) -> CallIterator[TResponse]: ... class StreamUnaryMultiCallable(typing.Generic[TRequest, TResponse]): def __call__( self, request_iterator: typing.Iterator[TRequest], - timeout: typing.Optional[float] = None, - metadata: typing.Optional[Metadata] = None, - credentials: typing.Optional[CallCredentials] = None, + timeout: float | None = None, + metadata: Metadata | None = None, + credentials: CallCredentials | None = None, # FIXME: optional bool seems weird, but that's what the docs suggest - wait_for_ready: typing.Optional[bool] = None, - compression: typing.Optional[Compression] = None, + wait_for_ready: bool | None = None, + compression: Compression | None = None, ) -> TResponse: ... def future( self, request_iterator: typing.Iterator[TRequest], - timeout: typing.Optional[float] = None, - metadata: typing.Optional[Metadata] = None, - credentials: typing.Optional[CallCredentials] = None, + timeout: float | None = None, + metadata: Metadata | None = None, + credentials: CallCredentials | None = None, # FIXME: optional bool seems weird, but that's what the docs suggest - wait_for_ready: typing.Optional[bool] = None, - compression: typing.Optional[Compression] = None, + wait_for_ready: bool | None = None, + compression: Compression | None = None, ) -> CallFuture[TResponse]: ... def with_call( self, request_iterator: typing.Iterator[TRequest], - timeout: typing.Optional[float] = None, - metadata: typing.Optional[Metadata] = None, - credentials: typing.Optional[CallCredentials] = None, + timeout: float | None = None, + metadata: Metadata | None = None, + credentials: CallCredentials | None = None, # FIXME: optional bool seems weird, but that's what the docs suggest - wait_for_ready: typing.Optional[bool] = None, - compression: typing.Optional[Compression] = None, + wait_for_ready: bool | None = None, + compression: Compression | None = None, # FIXME: Return value is documented as "The response value for the RPC and a Call value for the RPC"; # this is slightly unclear so this return type is a best-effort guess. ) -> tuple[TResponse, Call]: ... @@ -538,21 +514,18 @@ class StreamStreamMultiCallable(typing.Generic[TRequest, TResponse]): def __call__( self, request_iterator: typing.Iterator[TRequest], - timeout: typing.Optional[float] = None, - metadata: typing.Optional[Metadata] = None, - credentials: typing.Optional[CallCredentials] = None, + timeout: float | None = None, + metadata: Metadata | None = None, + credentials: CallCredentials | None = None, # FIXME: optional bool seems weird, but that's what the docs suggest - wait_for_ready: typing.Optional[bool] = None, - compression: typing.Optional[Compression] = None, + wait_for_ready: bool | None = None, + compression: Compression | None = None, ) -> CallIterator[TResponse]: ... """Future Interfaces""" -class FutureTimeoutError(Exception): - ... - -class FutureCancelledError(Exception): - ... +class FutureTimeoutError(Exception): ... +class FutureCancelledError(Exception): ... TFutureValue = typing.TypeVar("TFutureValue") @@ -561,12 +534,12 @@ class Future(typing.Generic[TFutureValue]): def cancel(self) -> bool: ... def cancelled(self) -> bool: ... def done(self) -> bool: ... - def exception(self) -> typing.Optional[Exception]: ... - def result(self, timeout: typing.Optional[float] = None) -> TFutureValue: ... + def exception(self) -> Exception | None: ... + def result(self, timeout: float | None = None) -> TFutureValue: ... def running(self) -> bool: ... # FIXME: unsure of the exact return type here. Is it a traceback.StackSummary? - def traceback(self, timeout: typing.Optional[float] = None) -> typing.Any: ... + def traceback(self, timeout: float | None = None) -> typing.Any: ... """Runtime Protobuf Parsing""" diff --git a/stubs/grpc/grpc/aio/__init__.pyi b/stubs/grpc/grpc/aio/__init__.pyi index 44b185eeda79..e1db8cfd0f3b 100644 --- a/stubs/grpc/grpc/aio/__init__.pyi +++ b/stubs/grpc/grpc/aio/__init__.pyi @@ -31,8 +31,8 @@ class AioRpcError(RpcError): code: StatusCode, initial_metadata: Metadata, trailing_metadata: Metadata, - details: typing.Optional[str], - debug_error_string: typing.Optional[str], + details: str | None, + debug_error_string: str | None, ) -> None: ... # FIXME: confirm if these are present in the parent type. The remaining @@ -46,27 +46,27 @@ ClientInterceptor = _PartialStubMustCastOrIgnore def insecure_channel( target: str, - options: typing.Optional[_Options] = None, - compression: typing.Optional[Compression] = None, - interceptors: typing.Optional[typing.Sequence[ClientInterceptor]] = None, + options: _Options | None = None, + compression: Compression | None = None, + interceptors: typing.Sequence[ClientInterceptor] | None = None, ) -> Channel: ... def secure_channel( target: str, credentials: ChannelCredentials, - options: typing.Optional[_Options] = None, - compression: typing.Optional[Compression] = None, - interceptors: typing.Optional[typing.Sequence[ClientInterceptor]] = None, + options: _Options | None = None, + compression: Compression | None = None, + interceptors: typing.Sequence[ClientInterceptor] | None = None, ) -> Channel: ... """Create Server""" def server( - migration_thread_pool: typing.Optional[futures.Executor] = None, - handlers: typing.Optional[typing.Sequence[GenericRpcHandler]] = None, - interceptors: typing.Optional[typing.Sequence[ServerInterceptor]] = None, - options: typing.Optional[_Options] = None, - maximum_concurrent_rpcs: typing.Optional[int] = None, - compression: typing.Optional[Compression] = None, + migration_thread_pool: futures.Executor | None = None, + handlers: typing.Sequence[GenericRpcHandler] | None = None, + interceptors: typing.Sequence[ServerInterceptor] | None = None, + options: _Options | None = None, + maximum_concurrent_rpcs: int | None = None, + compression: Compression | None = None, ) -> Server: ... """Channel Object""" @@ -78,40 +78,25 @@ RequestSerializer = typing.Callable[[typing.Any], bytes] ResponseDeserializer = typing.Callable[[bytes], typing.Any] class Channel: - async def close(self, grace: typing.Optional[float]) -> None: ... + async def close(self, grace: float | None) -> None: ... def get_state(self, try_to_connect: bool = False) -> ChannelConnectivity: ... async def wait_for_state_change(self, last_observed_state: ChannelConnectivity) -> None: ... def stream_stream( - self, - method: str, - request_serializer: typing.Optional[RequestSerializer], - response_deserializer: typing.Optional[ResponseDeserializer], + self, method: str, request_serializer: RequestSerializer | None, response_deserializer: ResponseDeserializer | None ) -> StreamStreamMultiCallable: ... def stream_unary( - self, - method: str, - request_serializer: typing.Optional[RequestSerializer], - response_deserializer: typing.Optional[ResponseDeserializer], + self, method: str, request_serializer: RequestSerializer | None, response_deserializer: ResponseDeserializer | None ) -> StreamUnaryMultiCallable: ... def unary_stream( - self, - method: str, - request_serializer: typing.Optional[RequestSerializer], - response_deserializer: typing.Optional[ResponseDeserializer], + self, method: str, request_serializer: RequestSerializer | None, response_deserializer: ResponseDeserializer | None ) -> UnaryStreamMultiCallable: ... def unary_unary( - self, - method: str, - request_serializer: typing.Optional[RequestSerializer], - response_deserializer: typing.Optional[ResponseDeserializer], + self, method: str, request_serializer: RequestSerializer | None, response_deserializer: ResponseDeserializer | None ) -> UnaryUnaryMultiCallable: ... async def __aenter__(self) -> Channel: ... async def __aexit__( - self, - exc_type: typing.Optional[type[BaseException]], - exc_val: typing.Optional[BaseException], - exc_tb: typing.Optional[TracebackType], - ) -> typing.Optional[bool]: ... + self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None + ) -> bool | None: ... async def channel_ready(self) -> None: ... """Server Object""" @@ -127,10 +112,10 @@ class Server: async def start(self) -> None: ... # Grace period is in seconds. - async def stop(self, grace: typing.Optional[float] = None) -> None: ... + async def stop(self, grace: float | None = None) -> None: ... # Returns a bool indicates if the operation times out. Timeout is in seconds. - async def wait_for_termination(self, timeout: typing.Optional[float] = None) -> bool: ... + async def wait_for_termination(self, timeout: float | None = None) -> bool: ... """Client-Side Context""" @@ -140,7 +125,7 @@ EOFType = object class RpcContext: def cancelled(self) -> bool: ... def done(self) -> bool: ... - def time_remaining(self) -> typing.Optional[float]: ... + def time_remaining(self) -> float | None: ... def cancel(self) -> bool: ... def add_done_callback(self, callback: DoneCallbackType) -> None: ... @@ -156,7 +141,7 @@ class UnaryUnaryCall(typing.Generic[TRequest, TResponse], Call): class UnaryStreamCall(typing.Generic[TRequest, TResponse], Call): def __aiter__(self) -> typing.AsyncIterator[TResponse]: ... - async def read(self) -> typing.Union[EOFType, TResponse]: ... + async def read(self) -> EOFType | TResponse: ... class StreamUnaryCall(typing.Generic[TRequest, TResponse], Call): async def write(self, request: TRequest) -> None: ... @@ -165,7 +150,7 @@ class StreamUnaryCall(typing.Generic[TRequest, TResponse], Call): class StreamStreamCall(typing.Generic[TRequest, TResponse], Call): def __aiter__(self) -> typing.AsyncIterator[TResponse]: ... - async def read(self) -> typing.Union[EOFType, TResponse]: ... + async def read(self) -> EOFType | TResponse: ... async def write(self, request: TRequest) -> None: ... async def done_writing(self) -> None: ... @@ -184,14 +169,14 @@ class ServicerContext(typing.Generic[TRequest, TResponse]): async def send_initial_metadata(self, initial_metadata: MetadataType) -> None: ... def add_done_callback(self, callback: DoneCallback[TRequest, TResponse]) -> None: ... def set_trailing_metadata(self, trailing_metadata: MetadataType) -> None: ... - def invocation_metadata(self) -> typing.Optional[Metadata]: ... + def invocation_metadata(self) -> Metadata | None: ... def set_code(self, code: StatusCode) -> None: ... def set_details(self, details: str) -> None: ... def set_compression(self, compression: Compression) -> None: ... def disable_next_message_compression(self) -> None: ... def peer(self) -> str: ... - def peer_identities(self) -> typing.Optional[typing.Iterable[bytes]]: ... - def peer_identity_key(self) -> typing.Optional[str]: ... + def peer_identities(self) -> typing.Iterable[bytes] | None: ... + def peer_identity_key(self) -> str | None: ... def auth_context(self) -> typing.Mapping[str, typing.Iterable[bytes]]: ... def time_remaining(self) -> float: ... def trailing_metadata(self) -> Metadata: ... @@ -206,22 +191,22 @@ class ClientCallDetails: def __init__( self, method: str, - timeout: typing.Optional[float], - metadata: typing.Optional[Metadata], - credentials: typing.Optional[CallCredentials], - wait_for_ready: typing.Optional[bool], + timeout: float | None, + metadata: Metadata | None, + credentials: CallCredentials | None, + wait_for_ready: bool | None, ) -> None: ... method: str - timeout: typing.Optional[float] - metadata: typing.Optional[Metadata] - credentials: typing.Optional[CallCredentials] + timeout: float | None + metadata: Metadata | None + credentials: CallCredentials | None # "This is an EXPERIMENTAL argument. An optional flag t enable wait for ready mechanism." - wait_for_ready: typing.Optional[bool] + wait_for_ready: bool | None # As at 1.53.0, this is not supported in aio: - # compression: typing.Optional[Compression] + # compression: Compression | None class InterceptedCall(typing.Generic[TRequest, TResponse]): def __init__(self, interceptors_task: asyncio.Task) -> None: ... @@ -230,12 +215,12 @@ class InterceptedCall(typing.Generic[TRequest, TResponse]): def cancelled(self) -> bool: ... def done(self) -> bool: ... def add_done_callback(self, callback: DoneCallback[TRequest, TResponse]) -> None: ... - def time_remaining(self) -> typing.Optional[float]: ... - async def initial_metadata(self) -> typing.Optional[Metadata]: ... - async def trailing_metadata(self) -> typing.Optional[Metadata]: ... + def time_remaining(self) -> float | None: ... + async def initial_metadata(self) -> Metadata | None: ... + async def trailing_metadata(self) -> Metadata | None: ... async def code(self) -> StatusCode: ... async def details(self) -> str: ... - async def debug_error_string(self) -> typing.Optional[str]: ... + async def debug_error_string(self) -> str | None: ... async def wait_for_connection(self) -> None: ... class InterceptedUnaryUnaryCall(InterceptedCall[TRequest, TResponse], typing.Generic[TRequest, TResponse]): @@ -244,10 +229,10 @@ class InterceptedUnaryUnaryCall(InterceptedCall[TRequest, TResponse], typing.Gen self, interceptors: typing.Sequence[UnaryUnaryClientInterceptor], request: TRequest, - timeout: typing.Optional[float], + timeout: float | None, metadata: Metadata, - credentials: typing.Optional[CallCredentials], - wait_for_ready: typing.Optional[bool], + credentials: CallCredentials | None, + wait_for_ready: bool | None, channel: Channel, method: bytes, request_serializer: RequestSerializer, @@ -260,15 +245,15 @@ class InterceptedUnaryUnaryCall(InterceptedCall[TRequest, TResponse], typing.Gen self, interceptors: typing.Sequence[UnaryUnaryClientInterceptor], method: bytes, - timeout: typing.Optional[float], - metadata: typing.Optional[Metadata], - credentials: typing.Optional[CallCredentials], - wait_for_ready: typing.Optional[bool], + timeout: float | None, + metadata: Metadata | None, + credentials: CallCredentials | None, + wait_for_ready: bool | None, request: TRequest, request_serializer: RequestSerializer, response_deserializer: ResponseDeserializer, ) -> UnaryUnaryCall: ... - def time_remaining(self) -> typing.Optional[float]: ... + def time_remaining(self) -> float | None: ... class UnaryUnaryClientInterceptor(typing.Generic[TRequest, TResponse]): async def intercept_unary_unary( @@ -285,23 +270,23 @@ class UnaryStreamClientInterceptor(typing.Generic[TRequest, TResponse]): continuation: typing.Callable[[ClientCallDetails, TRequest], UnaryStreamCall[TRequest, TResponse]], client_call_details: ClientCallDetails, request: TRequest, - ) -> typing.Union[typing.AsyncIterable[TResponse], UnaryStreamCall[TRequest, TResponse]]: ... + ) -> typing.AsyncIterable[TResponse] | UnaryStreamCall[TRequest, TResponse]: ... class StreamUnaryClientInterceptor(typing.Generic[TRequest, TResponse]): async def intercept_stream_unary( self, continuation: typing.Callable[[ClientCallDetails, TRequest], StreamUnaryCall[TRequest, TResponse]], client_call_details: ClientCallDetails, - request_iterator: typing.Union[typing.AsyncIterable[TRequest], typing.Iterable[TRequest]], - ) -> typing.Union[typing.AsyncIterable[TResponse], UnaryStreamCall[TRequest, TResponse]]: ... + request_iterator: typing.AsyncIterable[TRequest] | typing.Iterable[TRequest], + ) -> typing.AsyncIterable[TResponse] | UnaryStreamCall[TRequest, TResponse]: ... class StreamStreamClientInterceptor(typing.Generic[TRequest, TResponse]): async def intercept_stream_stream( self, continuation: typing.Callable[[ClientCallDetails, TRequest], StreamStreamCall[TRequest, TResponse]], client_call_details: ClientCallDetails, - request_iterator: typing.Union[typing.AsyncIterable[TRequest], typing.Iterable[TRequest]], - ) -> typing.Union[typing.AsyncIterable[TResponse], StreamStreamCall[TRequest, TResponse]]: ... + request_iterator: typing.AsyncIterable[TRequest] | typing.Iterable[TRequest], + ) -> typing.AsyncIterable[TResponse] | StreamStreamCall[TRequest, TResponse]: ... """Server-Side Interceptor""" @@ -318,56 +303,56 @@ class UnaryUnaryMultiCallable(typing.Generic[TRequest, TResponse]): def __call__( self, request: TRequest, - timeout: typing.Optional[float] = None, - metadata: typing.Optional[MetadataType] = None, - credentials: typing.Optional[CallCredentials] = None, + timeout: float | None = None, + metadata: MetadataType | None = None, + credentials: CallCredentials | None = None, # FIXME: optional bool seems weird, but that's what the docs suggest - wait_for_ready: typing.Optional[bool] = None, - compression: typing.Optional[Compression] = None, + wait_for_ready: bool | None = None, + compression: Compression | None = None, ) -> UnaryUnaryCall[TRequest, TResponse]: ... class UnaryStreamMultiCallable(typing.Generic[TRequest, TResponse]): def __call__( self, request: TRequest, - timeout: typing.Optional[float] = None, - metadata: typing.Optional[MetadataType] = None, - credentials: typing.Optional[CallCredentials] = None, + timeout: float | None = None, + metadata: MetadataType | None = None, + credentials: CallCredentials | None = None, # FIXME: optional bool seems weird, but that's what the docs suggest - wait_for_ready: typing.Optional[bool] = None, - compression: typing.Optional[Compression] = None, + wait_for_ready: bool | None = None, + compression: Compression | None = None, ) -> UnaryStreamCall[TRequest, TResponse]: ... class StreamUnaryMultiCallable(typing.Generic[TRequest, TResponse]): def __call__( self, - request_iterator: typing.Optional[typing.Union[typing.AsyncIterator[TRequest], typing.Iterator[TRequest]]], - timeout: typing.Optional[float] = None, - metadata: typing.Optional[MetadataType] = None, - credentials: typing.Optional[CallCredentials] = None, + request_iterator: typing.AsyncIterator[TRequest] | typing.Iterator[TRequest] | None, + timeout: float | None = None, + metadata: MetadataType | None = None, + credentials: CallCredentials | None = None, # FIXME: optional bool seems weird, but that's what the docs suggest - wait_for_ready: typing.Optional[bool] = None, - compression: typing.Optional[Compression] = None, + wait_for_ready: bool | None = None, + compression: Compression | None = None, ) -> StreamUnaryCall[TRequest, TResponse]: ... class StreamStreamMultiCallable(typing.Generic[TRequest, TResponse]): def __call__( self, - request_iterator: typing.Optional[typing.Union[typing.AsyncIterator[TRequest], typing.Iterator[TRequest]]], - timeout: typing.Optional[float] = None, - metadata: typing.Optional[MetadataType] = None, - credentials: typing.Optional[CallCredentials] = None, + request_iterator: typing.AsyncIterator[TRequest] | typing.Iterator[TRequest] | None, + timeout: float | None = None, + metadata: MetadataType | None = None, + credentials: CallCredentials | None = None, # FIXME: optional bool seems weird, but that's what the docs suggest - wait_for_ready: typing.Optional[bool] = None, - compression: typing.Optional[Compression] = None, + wait_for_ready: bool | None = None, + compression: Compression | None = None, ) -> StreamStreamCall[TRequest, TResponse]: ... """Metadata""" MetadataKey = str -MetadataValue = typing.Union[str, bytes] +MetadataValue = str | bytes MetadatumType = tuple[MetadataKey, MetadataValue] -MetadataType = typing.Union[Metadata, typing.Sequence[MetadatumType]] +MetadataType = Metadata | typing.Sequence[MetadatumType] class Metadata(typing.Mapping): def __init__(self, *args: tuple[MetadataKey, MetadataValue]) -> None: ... diff --git a/stubs/grpc_health/grpc_health/v1/health.pyi b/stubs/grpc_health/grpc_health/v1/health.pyi index 41b0ea7c5f0e..747999e65044 100644 --- a/stubs/grpc_health/grpc_health/v1/health.pyi +++ b/stubs/grpc_health/grpc_health/v1/health.pyi @@ -1,5 +1,5 @@ from concurrent import futures -from typing import Callable, Optional +from typing import Callable from grpc import ServicerContext from grpc_health.v1 import health_pb2 as _health_pb2, health_pb2_grpc as _health_pb2_grpc @@ -17,11 +17,11 @@ class _Watcher: class HealthServicer(_health_pb2_grpc.HealthServicer): def __init__( - self, experimental_non_blocking: bool = ..., experimental_thread_pool: Optional[futures.ThreadPoolExecutor] = ... + self, experimental_non_blocking: bool = ..., experimental_thread_pool: futures.ThreadPoolExecutor | None = ... ) -> None: ... def Check(self, request: _health_pb2.HealthCheckRequest, context: ServicerContext) -> _health_pb2.HealthCheckResponse: ... def Watch( - self, request: _health_pb2.HealthCheckRequest, context: ServicerContext, send_response_callback: Optional[Callable] = ... + self, request: _health_pb2.HealthCheckRequest, context: ServicerContext, send_response_callback: Callable | None = ... ) -> _health_pb2.HealthCheckResponse: ... def set(self, service: str, status: _health_pb2.HealthCheckResponse.ServingStatus) -> None: ... def enter_graceful_shutdown(self) -> None: ... diff --git a/stubs/grpc_reflection/grpc_reflection/v1alpha/reflection.pyi b/stubs/grpc_reflection/grpc_reflection/v1alpha/reflection.pyi index eb3496a146e6..0d46bcd4c496 100644 --- a/stubs/grpc_reflection/grpc_reflection/v1alpha/reflection.pyi +++ b/stubs/grpc_reflection/grpc_reflection/v1alpha/reflection.pyi @@ -8,8 +8,8 @@ from grpc_reflection.v1alpha._base import BaseReflectionServicer SERVICE_NAME: str -AnyServer = typing.Union[grpc.Server, aio.Server] -AnyServicerContext = typing.Union[grpc.ServicerContext, aio.ServicerContext] +AnyServer = grpc.Server | aio.Server +AnyServicerContext = grpc.ServicerContext | aio.ServicerContext class ReflectionServicer(BaseReflectionServicer): def ServerReflectionInfo( @@ -17,5 +17,5 @@ class ReflectionServicer(BaseReflectionServicer): ) -> None: ... def enable_server_reflection( - service_names: typing.Iterable[str], server: AnyServer, pool: typing.Optional[descriptor_pool.DescriptorPool] = ... + service_names: typing.Iterable[str], server: AnyServer, pool: descriptor_pool.DescriptorPool | None = ... ) -> None: ... From 241b0e1d4bfa46d5b5b9aba99828c8e17726b1de Mon Sep 17 00:00:00 2001 From: Blake Williams Date: Wed, 27 Dec 2023 18:43:21 +1100 Subject: [PATCH 04/18] Migrate tests from grpc-stubs --- stubs/grpc/@tests/test_cases/check_aio.py | 16 +++++++ .../test_cases/check_aio_multi_callable.py | 37 +++++++++++++++ stubs/grpc/@tests/test_cases/check_grpc.py | 45 +++++++++++++++++++ .../test_cases/check_handler_inheritance.py | 33 ++++++++++++++ .../@tests/test_cases/check_multi_callable.py | 35 +++++++++++++++ .../test_cases/check_server_interceptor.py | 22 +++++++++ stubs/grpc/grpc/aio/__init__.pyi | 18 ++++---- stubs/grpc/grpc/aio/py.typed | 1 - stubs/grpc_channelz/METADATA.toml | 3 ++ .../grpc_channelz/grpc_channelz/__init__.pyi | 4 +- .../grpc_channelz/v1/__init__.pyi | 4 +- stubs/grpc_health/METADATA.toml | 3 ++ .../@tests/test_cases/check_reflection.py | 9 ++++ .../@tests/test_cases/check_reflection_aio.py | 9 ++++ stubs/grpc_reflection/METADATA.toml | 4 ++ .../grpc_reflection/__init__.pyi | 4 +- .../grpc_reflection/v1alpha/__init__.pyi | 4 +- .../grpc_reflection/v1alpha/_base.pyi | 5 +++ .../grpc_reflection/v1alpha/reflection.pyi | 6 ++- .../v1alpha/reflection_pb2.pyi | 3 ++ .../@tests/test_cases/check_status.py | 8 ++++ stubs/grpc_status/METADATA.toml | 1 + stubs/grpc_status/grpc_status/__init__.pyi | 4 +- 23 files changed, 256 insertions(+), 22 deletions(-) create mode 100644 stubs/grpc/@tests/test_cases/check_aio.py create mode 100644 stubs/grpc/@tests/test_cases/check_aio_multi_callable.py create mode 100644 stubs/grpc/@tests/test_cases/check_grpc.py create mode 100644 stubs/grpc/@tests/test_cases/check_handler_inheritance.py create mode 100644 stubs/grpc/@tests/test_cases/check_multi_callable.py create mode 100644 stubs/grpc/@tests/test_cases/check_server_interceptor.py delete mode 100644 stubs/grpc/grpc/aio/py.typed create mode 100644 stubs/grpc_reflection/@tests/test_cases/check_reflection.py create mode 100644 stubs/grpc_reflection/@tests/test_cases/check_reflection_aio.py create mode 100644 stubs/grpc_reflection/grpc_reflection/v1alpha/_base.pyi create mode 100644 stubs/grpc_reflection/grpc_reflection/v1alpha/reflection_pb2.pyi create mode 100644 stubs/grpc_status/@tests/test_cases/check_status.py diff --git a/stubs/grpc/@tests/test_cases/check_aio.py b/stubs/grpc/@tests/test_cases/check_aio.py new file mode 100644 index 000000000000..5963cb757572 --- /dev/null +++ b/stubs/grpc/@tests/test_cases/check_aio.py @@ -0,0 +1,16 @@ +from __future__ import annotations + +import typing +from typing_extensions import assert_type + +import grpc.aio + +assert_type(grpc.aio.Channel(), grpc.aio.Channel) +assert_type(grpc.aio.Server(), grpc.aio.Server) + +# Interceptor casts +client_interceptors = [typing.cast(grpc.aio.ClientInterceptor, "interceptor")] +grpc.aio.insecure_channel("target", interceptors=client_interceptors) + +server_interceptors = [typing.cast(grpc.aio.ServerInterceptor[typing.Any, typing.Any], "interceptor")] +grpc.aio.server(interceptors=server_interceptors) diff --git a/stubs/grpc/@tests/test_cases/check_aio_multi_callable.py b/stubs/grpc/@tests/test_cases/check_aio_multi_callable.py new file mode 100644 index 000000000000..87062bf136b0 --- /dev/null +++ b/stubs/grpc/@tests/test_cases/check_aio_multi_callable.py @@ -0,0 +1,37 @@ +from __future__ import annotations + +import typing +from typing_extensions import assert_type + +import grpc.aio + + +class DummyRequest: + pass + + +class DummyReply: + pass + + +class DummyServiceStub(typing.Protocol): + UnaryUnary: grpc.aio.UnaryUnaryMultiCallable[DummyRequest, DummyReply] + UnaryStream: grpc.aio.UnaryStreamMultiCallable[DummyRequest, DummyReply] + StreamUnary: grpc.aio.StreamUnaryMultiCallable[DummyRequest, DummyReply] + StreamStream: grpc.aio.StreamStreamMultiCallable[DummyRequest, DummyReply] + + +stub: DummyServiceStub = typing.cast(typing.Any, None) +req = DummyRequest() + + +async def async_context() -> None: + assert_type(await stub.UnaryUnary(req), DummyReply) + + async for resp in stub.UnaryStream(req): + assert_type(resp, DummyReply) + + assert_type(await stub.StreamUnary(iter([req])), DummyReply) + + async for resp in stub.StreamStream(iter([req])): + assert_type(resp, DummyReply) diff --git a/stubs/grpc/@tests/test_cases/check_grpc.py b/stubs/grpc/@tests/test_cases/check_grpc.py new file mode 100644 index 000000000000..c4c70b92f340 --- /dev/null +++ b/stubs/grpc/@tests/test_cases/check_grpc.py @@ -0,0 +1,45 @@ +from __future__ import annotations + +import typing +from typing_extensions import assert_type + +import grpc + +assert_type(grpc.Channel(), grpc.Channel) +assert_type(grpc.Server(), grpc.Server) + +# Channel options: +assert_type(grpc.insecure_channel("target", ()), grpc.Channel) +assert_type(grpc.insecure_channel("target", (("a", "b"),)), grpc.Channel) +assert_type(grpc.insecure_channel("target", (("a", "b"), ("c", "d"))), grpc.Channel) + +# Local channel credentials: +creds = grpc.local_channel_credentials(grpc.LocalConnectionType.LOCAL_TCP) +assert_type(creds, grpc.ChannelCredentials) + +# Other credential types: +assert_type(grpc.alts_channel_credentials(), grpc.ChannelCredentials) +assert_type(grpc.alts_server_credentials(), grpc.ServerCredentials) +assert_type(grpc.compute_engine_channel_credentials(), grpc.ChannelCredentials) +assert_type(grpc.insecure_server_credentials(), grpc.ServerCredentials) + +# XDS credentials: +assert_type( + grpc.xds_channel_credentials(grpc.local_channel_credentials(grpc.LocalConnectionType.LOCAL_TCP)), grpc.ChannelCredentials +) +assert_type(grpc.xds_server_credentials(grpc.insecure_server_credentials()), grpc.ServerCredentials) + +# Channel options supports list: +assert_type(grpc.insecure_channel("target", []), grpc.Channel) +assert_type(grpc.insecure_channel("target", [("a", "b")]), grpc.Channel) +assert_type(grpc.insecure_channel("target", [("a", "b"), ("c", "d")]), grpc.Channel) + +# Client call details optionals: +call_details = grpc.ClientCallDetails() +assert_type(call_details.method, str) +assert_type(call_details.timeout, typing.Optional[float]) + +# Call iterator +call_iter: grpc.CallIterator[str] = typing.cast(typing.Any, None) +for call in call_iter: + assert_type(call, str) diff --git a/stubs/grpc/@tests/test_cases/check_handler_inheritance.py b/stubs/grpc/@tests/test_cases/check_handler_inheritance.py new file mode 100644 index 000000000000..60ce09d90f23 --- /dev/null +++ b/stubs/grpc/@tests/test_cases/check_handler_inheritance.py @@ -0,0 +1,33 @@ +from __future__ import annotations + +import typing +from typing_extensions import assert_type + +import grpc + + +class Request: + pass + + +class Response: + pass + + +def unary_unary_call(rq: Request, ctx: grpc.ServicerContext) -> Response: + assert_type(rq, Request) + return Response() + + +class ServiceHandler(grpc.ServiceRpcHandler[Request, Response]): + def service(self, handler_call_details: grpc.HandlerCallDetails) -> typing.Optional[grpc.RpcMethodHandler[Request, Response]]: + rpc = grpc.RpcMethodHandler[Request, Response]() + rpc.unary_unary = unary_unary_call + return rpc + + +h = ServiceHandler() +ctx = grpc.ServicerContext() +svc = h.service(grpc.HandlerCallDetails()) +if svc is not None and svc.unary_unary is not None: + svc.unary_unary(Request(), ctx) diff --git a/stubs/grpc/@tests/test_cases/check_multi_callable.py b/stubs/grpc/@tests/test_cases/check_multi_callable.py new file mode 100644 index 000000000000..b3a74e05bfbc --- /dev/null +++ b/stubs/grpc/@tests/test_cases/check_multi_callable.py @@ -0,0 +1,35 @@ +from __future__ import annotations + +import typing +from typing_extensions import assert_type + +import grpc + + +class DummyRequest: + pass + + +class DummyReply: + pass + + +class DummyServiceStub(typing.Protocol): + UnaryUnary: grpc.UnaryUnaryMultiCallable[DummyRequest, DummyReply] + UnaryStream: grpc.UnaryStreamMultiCallable[DummyRequest, DummyReply] + StreamUnary: grpc.StreamUnaryMultiCallable[DummyRequest, DummyReply] + StreamStream: grpc.StreamStreamMultiCallable[DummyRequest, DummyReply] + + +stub: DummyServiceStub = typing.cast(typing.Any, None) +req = DummyRequest() + +assert_type(stub.UnaryUnary(req), DummyReply) + +for resp in stub.UnaryStream(req): + assert_type(resp, DummyReply) + +assert_type(stub.StreamUnary(iter([req])), DummyReply) + +for resp in stub.StreamStream(iter([req])): + assert_type(resp, DummyReply) diff --git a/stubs/grpc/@tests/test_cases/check_server_interceptor.py b/stubs/grpc/@tests/test_cases/check_server_interceptor.py new file mode 100644 index 000000000000..f83da1c1b7c5 --- /dev/null +++ b/stubs/grpc/@tests/test_cases/check_server_interceptor.py @@ -0,0 +1,22 @@ +from __future__ import annotations + +import typing + +import grpc + + +class Request: + pass + + +class Response: + pass + + +class NoopInterceptor(grpc.ServerInterceptor[Request, Response]): + def intercept_service( + self, + continuation: typing.Callable[[grpc.HandlerCallDetails], grpc.RpcMethodHandler[Request, Response] | None], + handler_call_details: grpc.HandlerCallDetails, + ) -> typing.Optional[grpc.RpcMethodHandler[Request, Response]]: + return continuation(handler_call_details) diff --git a/stubs/grpc/grpc/aio/__init__.pyi b/stubs/grpc/grpc/aio/__init__.pyi index e1db8cfd0f3b..d3f5148af87e 100644 --- a/stubs/grpc/grpc/aio/__init__.pyi +++ b/stubs/grpc/grpc/aio/__init__.pyi @@ -61,12 +61,12 @@ def secure_channel( """Create Server""" def server( - migration_thread_pool: futures.Executor | None = None, - handlers: typing.Sequence[GenericRpcHandler] | None = None, - interceptors: typing.Sequence[ServerInterceptor] | None = None, - options: _Options | None = None, - maximum_concurrent_rpcs: int | None = None, - compression: Compression | None = None, + migration_thread_pool: futures.Executor | None = ..., + handlers: typing.Sequence[GenericRpcHandler[typing.Any, typing.Any]] | None = ..., + interceptors: typing.Sequence[ServerInterceptor[typing.Any, typing.Any]] | None = ..., + options: _Options | None = ..., + maximum_concurrent_rpcs: int | None = ..., + compression: Compression | None = ..., ) -> Server: ... """Channel Object""" @@ -227,7 +227,7 @@ class InterceptedUnaryUnaryCall(InterceptedCall[TRequest, TResponse], typing.Gen def __await__(self): ... def __init__( self, - interceptors: typing.Sequence[UnaryUnaryClientInterceptor], + interceptors: typing.Sequence[UnaryUnaryClientInterceptor[TRequest, TResponse]], request: TRequest, timeout: float | None, metadata: Metadata, @@ -243,7 +243,7 @@ class InterceptedUnaryUnaryCall(InterceptedCall[TRequest, TResponse], typing.Gen # pylint: disable=too-many-arguments async def _invoke( self, - interceptors: typing.Sequence[UnaryUnaryClientInterceptor], + interceptors: typing.Sequence[UnaryUnaryClientInterceptor[TRequest, TResponse]], method: bytes, timeout: float | None, metadata: Metadata | None, @@ -252,7 +252,7 @@ class InterceptedUnaryUnaryCall(InterceptedCall[TRequest, TResponse], typing.Gen request: TRequest, request_serializer: RequestSerializer, response_deserializer: ResponseDeserializer, - ) -> UnaryUnaryCall: ... + ) -> UnaryUnaryCall[TRequest, TResponse]: ... def time_remaining(self) -> float | None: ... class UnaryUnaryClientInterceptor(typing.Generic[TRequest, TResponse]): diff --git a/stubs/grpc/grpc/aio/py.typed b/stubs/grpc/grpc/aio/py.typed deleted file mode 100644 index b648ac923333..000000000000 --- a/stubs/grpc/grpc/aio/py.typed +++ /dev/null @@ -1 +0,0 @@ -partial diff --git a/stubs/grpc_channelz/METADATA.toml b/stubs/grpc_channelz/METADATA.toml index b81a42967303..c7934b2b5446 100644 --- a/stubs/grpc_channelz/METADATA.toml +++ b/stubs/grpc_channelz/METADATA.toml @@ -1,6 +1,9 @@ version = "1.*" upstream_repository = "https://github.com/grpc/grpc" partial_stub = true +requires = [ + "types-grpc", +] [tool.stubtest] ignore_missing_stub = true diff --git a/stubs/grpc_channelz/grpc_channelz/__init__.pyi b/stubs/grpc_channelz/grpc_channelz/__init__.pyi index e4579106bab4..0f6820f054ea 100644 --- a/stubs/grpc_channelz/grpc_channelz/__init__.pyi +++ b/stubs/grpc_channelz/grpc_channelz/__init__.pyi @@ -1,3 +1,3 @@ -import typing +from _typeshed import Incomplete -def __getattr__(name) -> typing.Any: ... +def __getattr__(name: str) -> Incomplete: ... diff --git a/stubs/grpc_channelz/grpc_channelz/v1/__init__.pyi b/stubs/grpc_channelz/grpc_channelz/v1/__init__.pyi index e4579106bab4..0f6820f054ea 100644 --- a/stubs/grpc_channelz/grpc_channelz/v1/__init__.pyi +++ b/stubs/grpc_channelz/grpc_channelz/v1/__init__.pyi @@ -1,3 +1,3 @@ -import typing +from _typeshed import Incomplete -def __getattr__(name) -> typing.Any: ... +def __getattr__(name: str) -> Incomplete: ... diff --git a/stubs/grpc_health/METADATA.toml b/stubs/grpc_health/METADATA.toml index b81a42967303..c7934b2b5446 100644 --- a/stubs/grpc_health/METADATA.toml +++ b/stubs/grpc_health/METADATA.toml @@ -1,6 +1,9 @@ version = "1.*" upstream_repository = "https://github.com/grpc/grpc" partial_stub = true +requires = [ + "types-grpc", +] [tool.stubtest] ignore_missing_stub = true diff --git a/stubs/grpc_reflection/@tests/test_cases/check_reflection.py b/stubs/grpc_reflection/@tests/test_cases/check_reflection.py new file mode 100644 index 000000000000..fb31fb8dfea7 --- /dev/null +++ b/stubs/grpc_reflection/@tests/test_cases/check_reflection.py @@ -0,0 +1,9 @@ +from __future__ import annotations + +import typing + +import grpc +from grpc_reflection.v1alpha.reflection import enable_server_reflection + +server = typing.cast(grpc.Server, None) +enable_server_reflection(["foo"], server, None) diff --git a/stubs/grpc_reflection/@tests/test_cases/check_reflection_aio.py b/stubs/grpc_reflection/@tests/test_cases/check_reflection_aio.py new file mode 100644 index 000000000000..6ed8130645fb --- /dev/null +++ b/stubs/grpc_reflection/@tests/test_cases/check_reflection_aio.py @@ -0,0 +1,9 @@ +from __future__ import annotations + +import typing + +import grpc.aio +from grpc_reflection.v1alpha.reflection import enable_server_reflection + +server = typing.cast(grpc.aio.Server, None) +enable_server_reflection(["foo"], server, None) diff --git a/stubs/grpc_reflection/METADATA.toml b/stubs/grpc_reflection/METADATA.toml index b81a42967303..5fc3efa942c2 100644 --- a/stubs/grpc_reflection/METADATA.toml +++ b/stubs/grpc_reflection/METADATA.toml @@ -1,6 +1,10 @@ version = "1.*" upstream_repository = "https://github.com/grpc/grpc" partial_stub = true +requires = [ + "types-grpc", + "types-protobuf", +] [tool.stubtest] ignore_missing_stub = true diff --git a/stubs/grpc_reflection/grpc_reflection/__init__.pyi b/stubs/grpc_reflection/grpc_reflection/__init__.pyi index e4579106bab4..0f6820f054ea 100644 --- a/stubs/grpc_reflection/grpc_reflection/__init__.pyi +++ b/stubs/grpc_reflection/grpc_reflection/__init__.pyi @@ -1,3 +1,3 @@ -import typing +from _typeshed import Incomplete -def __getattr__(name) -> typing.Any: ... +def __getattr__(name: str) -> Incomplete: ... diff --git a/stubs/grpc_reflection/grpc_reflection/v1alpha/__init__.pyi b/stubs/grpc_reflection/grpc_reflection/v1alpha/__init__.pyi index e4579106bab4..0f6820f054ea 100644 --- a/stubs/grpc_reflection/grpc_reflection/v1alpha/__init__.pyi +++ b/stubs/grpc_reflection/grpc_reflection/v1alpha/__init__.pyi @@ -1,3 +1,3 @@ -import typing +from _typeshed import Incomplete -def __getattr__(name) -> typing.Any: ... +def __getattr__(name: str) -> Incomplete: ... diff --git a/stubs/grpc_reflection/grpc_reflection/v1alpha/_base.pyi b/stubs/grpc_reflection/grpc_reflection/v1alpha/_base.pyi new file mode 100644 index 000000000000..ab31ad3f712e --- /dev/null +++ b/stubs/grpc_reflection/grpc_reflection/v1alpha/_base.pyi @@ -0,0 +1,5 @@ +from _typeshed import Incomplete + +def __getattr__(name: str) -> Incomplete: ... + +class BaseReflectionServicer: ... diff --git a/stubs/grpc_reflection/grpc_reflection/v1alpha/reflection.pyi b/stubs/grpc_reflection/grpc_reflection/v1alpha/reflection.pyi index 0d46bcd4c496..49d2a7e6b410 100644 --- a/stubs/grpc_reflection/grpc_reflection/v1alpha/reflection.pyi +++ b/stubs/grpc_reflection/grpc_reflection/v1alpha/reflection.pyi @@ -1,4 +1,6 @@ import typing +import typing_extensions +from _typeshed import Incomplete import grpc from google.protobuf import descriptor_pool @@ -8,8 +10,8 @@ from grpc_reflection.v1alpha._base import BaseReflectionServicer SERVICE_NAME: str -AnyServer = grpc.Server | aio.Server -AnyServicerContext = grpc.ServicerContext | aio.ServicerContext +AnyServer: typing_extensions.TypeAlias = grpc.Server | aio.Server +AnyServicerContext: typing_extensions.TypeAlias = grpc.ServicerContext | aio.ServicerContext[Incomplete, Incomplete] class ReflectionServicer(BaseReflectionServicer): def ServerReflectionInfo( diff --git a/stubs/grpc_reflection/grpc_reflection/v1alpha/reflection_pb2.pyi b/stubs/grpc_reflection/grpc_reflection/v1alpha/reflection_pb2.pyi new file mode 100644 index 000000000000..0f6820f054ea --- /dev/null +++ b/stubs/grpc_reflection/grpc_reflection/v1alpha/reflection_pb2.pyi @@ -0,0 +1,3 @@ +from _typeshed import Incomplete + +def __getattr__(name: str) -> Incomplete: ... diff --git a/stubs/grpc_status/@tests/test_cases/check_status.py b/stubs/grpc_status/@tests/test_cases/check_status.py new file mode 100644 index 000000000000..b9e1776b68cf --- /dev/null +++ b/stubs/grpc_status/@tests/test_cases/check_status.py @@ -0,0 +1,8 @@ +from __future__ import annotations + +from grpc import Status +from grpc_status import to_status + +# XXX: to_status actually expects a "google.rpc.status.Status", +# but the stubs for that aren't present yet. +status: Status = to_status(None) diff --git a/stubs/grpc_status/METADATA.toml b/stubs/grpc_status/METADATA.toml index b81a42967303..26a1fab02c88 100644 --- a/stubs/grpc_status/METADATA.toml +++ b/stubs/grpc_status/METADATA.toml @@ -1,6 +1,7 @@ version = "1.*" upstream_repository = "https://github.com/grpc/grpc" partial_stub = true +requires = ["types-grpc"] [tool.stubtest] ignore_missing_stub = true diff --git a/stubs/grpc_status/grpc_status/__init__.pyi b/stubs/grpc_status/grpc_status/__init__.pyi index e4579106bab4..0f6820f054ea 100644 --- a/stubs/grpc_status/grpc_status/__init__.pyi +++ b/stubs/grpc_status/grpc_status/__init__.pyi @@ -1,3 +1,3 @@ -import typing +from _typeshed import Incomplete -def __getattr__(name) -> typing.Any: ... +def __getattr__(name: str) -> Incomplete: ... From 5eadd4fd2dbdb2f0b3db5aa304e7d66d9b72d468 Mon Sep 17 00:00:00 2001 From: Blake Williams Date: Wed, 27 Dec 2023 18:50:34 +1100 Subject: [PATCH 05/18] Convert docstrings to comments --- stubs/grpc/grpc/__init__.pyi | 58 ++++++++++++++++---------------- stubs/grpc/grpc/aio/__init__.pyi | 22 ++++++------ 2 files changed, 40 insertions(+), 40 deletions(-) diff --git a/stubs/grpc/grpc/__init__.pyi b/stubs/grpc/grpc/__init__.pyi index caa4063bcb06..84b3cdefe5f5 100644 --- a/stubs/grpc/grpc/__init__.pyi +++ b/stubs/grpc/grpc/__init__.pyi @@ -37,7 +37,7 @@ class LocalConnectionType(enum.Enum): # - https://github.com/grpc/grpc/blob/0e1984effd7e977ef18f1ad7fde7d10a2a153e1d/src/python/grpcio_tests/tests/unit/_invocation_defects_test.py#L66 Metadata = tuple[tuple[str, str | bytes], ...] -"""Create Client""" +# Create Client: def insecure_channel(target: str, options: _Options | None = None, compression: Compression | None = None) -> Channel: ... def secure_channel( @@ -50,7 +50,7 @@ Interceptor = ( def intercept_channel(channel: Channel, *interceptors: Interceptor) -> Channel: ... -"""Create Client Credentials""" +# Create Client Credentials: def ssl_channel_credentials( root_certificates: bytes | None = None, private_key: bytes | None = None, certificate_chain: bytes | None = None @@ -70,7 +70,7 @@ def composite_channel_credentials( channel_credentials: ChannelCredentials, call_credentials: CallCredentials, *rest: CallCredentials ) -> ChannelCredentials: ... -"""Create Server""" +# Create Server: def server( thread_pool: futures.ThreadPoolExecutor, @@ -82,7 +82,7 @@ def server( xds: bool = False, ) -> Server: ... -"""Create Server Credentials""" +# Create Server Credentials: CertificateChainPair = tuple[bytes, bytes] @@ -104,7 +104,7 @@ def alts_server_credentials() -> ServerCredentials: ... def insecure_server_credentials() -> ServerCredentials: ... def xds_server_credentials(fallback_credentials: ServerCredentials) -> ServerCredentials: ... -"""RPC Method Handlers""" +# RPC Method Handlers: # XXX: This is probably what appears in the add_FooServicer_to_server function # in the _pb2_grpc files that get generated, which points to the FooServicer @@ -142,11 +142,11 @@ def stream_stream_rpc_method_handler( ) -> RpcMethodHandler: ... def method_handlers_generic_handler(service: str, method_handlers: dict[str, RpcMethodHandler]) -> GenericRpcHandler: ... -"""Channel Ready Future""" +# Channel Ready Future: def channel_ready_future(channel: Channel) -> Future: ... -"""Channel Connectivity""" +# Channel Connectivity: class ChannelConnectivity(enum.Enum): IDLE = ... @@ -155,7 +155,7 @@ class ChannelConnectivity(enum.Enum): TRANSIENT_FAILURE = ... SHUTDOWN = ... -"""gRPC Status Code""" +# gRPC Status Code: class Status: code: StatusCode @@ -185,7 +185,7 @@ class StatusCode(enum.Enum): DATA_LOSS = ... UNAUTHENTICATED = ... -"""Channel Object""" +# Channel Object: # XXX: These are probably the SerializeToTring/FromString pb2 methods, but # this needs further investigation @@ -213,7 +213,7 @@ class Channel: self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None ) -> bool | None: ... -"""Server Object""" +# Server Object: class Server: def add_generic_rpc_handlers(self, generic_rpc_handlers: typing.Iterable[GenericRpcHandler]) -> None: ... @@ -232,13 +232,13 @@ class Server: # indicates if the operation times out. Timeout is in seconds. def wait_for_termination(self, timeout: float | None = None) -> bool: ... -"""Authentication & Authorization Objects""" +# Authentication & Authorization Objects: -class ChannelCredentials: - """This class has no supported interface""" +# This class has no supported interface +class ChannelCredentials: ... -class CallCredentials: - """This class has no supported interface""" +# This class has no supported interface +class CallCredentials: ... class AuthMetadataContext: service_url: str @@ -250,13 +250,13 @@ class AuthMetadataPluginCallback: class AuthMetadataPlugin: def __call__(self, context: AuthMetadataContext, callback: AuthMetadataPluginCallback) -> None: ... -class ServerCredentials: - """This class has no supported interface""" +# This class has no supported interface +class ServerCredentials: ... -class ServerCertificateConfiguration: - """This class has no supported interface""" +# This class has no supported interface +class ServerCertificateConfiguration: ... -"""gRPC Exceptions""" +# gRPC Exceptions: class _Metadatum: key: str @@ -274,7 +274,7 @@ class RpcError(Exception): # XXX: This has a slightly different return type to all the other metadata: def trailing_metadata(self) -> tuple[_Metadatum, ...]: ... -"""Shared Context""" +# Shared Context: class RpcContext: def add_callback(self, callback: typing.Callable[[], None]) -> bool: ... @@ -282,7 +282,7 @@ class RpcContext: def is_active(self) -> bool: ... def time_remaining(self) -> float: ... -"""Client-Side Context""" +# Client-Side Context: class Call(RpcContext): def code(self) -> StatusCode: ... @@ -292,7 +292,7 @@ class Call(RpcContext): def initial_metadata(self) -> Metadata: ... def trailing_metadata(self) -> Metadata: ... -"""Client-Side Interceptor""" +# Client-Side Interceptor: class ClientCallDetails: method: str @@ -365,7 +365,7 @@ class StreamStreamClientInterceptor(typing.Generic[TRequest, TResponse]): request_iterator: typing.Iterator[TRequest], ) -> CallIterator[TResponse]: ... -"""Service-Side Context""" +# Service-Side Context: class ServicerContext(RpcContext): # misnamed parameter 'details', does not align with status.proto, where it is called 'message': @@ -389,7 +389,7 @@ class ServicerContext(RpcContext): def set_details(self, details: str) -> None: ... def trailing_metadata(self) -> Metadata: ... -"""Service-Side Handler""" +# Service-Side Handler: class RpcMethodHandler(typing.Generic[TRequest, TResponse]): request_streaming: bool @@ -419,7 +419,7 @@ class GenericRpcHandler(typing.Generic[TRequest, TResponse]): class ServiceRpcHandler(GenericRpcHandler[TRequest, TResponse], typing.Generic[TRequest, TResponse]): def service_name(self) -> str: ... -"""Service-Side Interceptor""" +# Service-Side Interceptor: class ServerInterceptor(typing.Generic[TRequest, TResponse]): def intercept_service( @@ -428,7 +428,7 @@ class ServerInterceptor(typing.Generic[TRequest, TResponse]): handler_call_details: HandlerCallDetails, ) -> RpcMethodHandler[TRequest, TResponse] | None: ... -"""Multi-Callable Interfaces""" +# Multi-Callable Interfaces: class UnaryUnaryMultiCallable(typing.Generic[TRequest, TResponse]): def __call__( @@ -522,7 +522,7 @@ class StreamStreamMultiCallable(typing.Generic[TRequest, TResponse]): compression: Compression | None = None, ) -> CallIterator[TResponse]: ... -"""Future Interfaces""" +# Future Interfaces: class FutureTimeoutError(Exception): ... class FutureCancelledError(Exception): ... @@ -541,7 +541,7 @@ class Future(typing.Generic[TFutureValue]): # FIXME: unsure of the exact return type here. Is it a traceback.StackSummary? def traceback(self, timeout: float | None = None) -> typing.Any: ... -"""Runtime Protobuf Parsing""" +# Runtime Protobuf Parsing: def protos(protobuf_path: str) -> ModuleType: ... def services(protobuf_path: str) -> ModuleType: ... diff --git a/stubs/grpc/grpc/aio/__init__.pyi b/stubs/grpc/grpc/aio/__init__.pyi index d3f5148af87e..5764d0de7f41 100644 --- a/stubs/grpc/grpc/aio/__init__.pyi +++ b/stubs/grpc/grpc/aio/__init__.pyi @@ -18,7 +18,7 @@ from grpc import ( _PartialStubMustCastOrIgnore, ) -"""Exceptions""" +# Exceptions: class BaseError(Exception): ... class UsageError(BaseError): ... @@ -40,7 +40,7 @@ class AioRpcError(RpcError): def debug_error_string(self) -> str: ... def initial_metadata(self) -> Metadata: ... -"""Create Client""" +# Create Client: ClientInterceptor = _PartialStubMustCastOrIgnore @@ -58,7 +58,7 @@ def secure_channel( interceptors: typing.Sequence[ClientInterceptor] | None = None, ) -> Channel: ... -"""Create Server""" +# Create Server: def server( migration_thread_pool: futures.Executor | None = ..., @@ -69,7 +69,7 @@ def server( compression: Compression | None = ..., ) -> Server: ... -"""Channel Object""" +# Channel Object: # XXX: The docs suggest these type signatures for aio, but not for non-async, # and it's unclear why; @@ -99,7 +99,7 @@ class Channel: ) -> bool | None: ... async def channel_ready(self) -> None: ... -"""Server Object""" +# Server Object: class Server: def add_generic_rpc_handlers(self, generic_rpc_handlers: typing.Iterable[GenericRpcHandler]) -> None: ... @@ -117,7 +117,7 @@ class Server: # Returns a bool indicates if the operation times out. Timeout is in seconds. async def wait_for_termination(self, timeout: float | None = None) -> bool: ... -"""Client-Side Context""" +# Client-Side Context: DoneCallbackType = typing.Callable[[typing.Any], None] EOFType = object @@ -157,7 +157,7 @@ class StreamStreamCall(typing.Generic[TRequest, TResponse], Call): TRequest = typing.TypeVar("TRequest") TResponse = typing.TypeVar("TResponse") -"""Service-Side Context""" +# Service-Side Context: class DoneCallback(typing.Generic[TRequest, TResponse]): def __call__(self, ctx: ServicerContext[TRequest, TResponse]) -> None: ... @@ -185,7 +185,7 @@ class ServicerContext(typing.Generic[TRequest, TResponse]): def cancelled(self) -> bool: ... def done(self) -> bool: ... -"""Client-Side Interceptor""" +# Client-Side Interceptor: class ClientCallDetails: def __init__( @@ -288,7 +288,7 @@ class StreamStreamClientInterceptor(typing.Generic[TRequest, TResponse]): request_iterator: typing.AsyncIterable[TRequest] | typing.Iterable[TRequest], ) -> typing.AsyncIterable[TResponse] | StreamStreamCall[TRequest, TResponse]: ... -"""Server-Side Interceptor""" +# Server-Side Interceptor: class ServerInterceptor(typing.Generic[TRequest, TResponse]): async def intercept_service( @@ -297,7 +297,7 @@ class ServerInterceptor(typing.Generic[TRequest, TResponse]): handler_call_details: HandlerCallDetails, ) -> RpcMethodHandler[TRequest, TResponse]: ... -"""Multi-Callable Interfaces""" +# Multi-Callable Interfaces: class UnaryUnaryMultiCallable(typing.Generic[TRequest, TResponse]): def __call__( @@ -347,7 +347,7 @@ class StreamStreamMultiCallable(typing.Generic[TRequest, TResponse]): compression: Compression | None = None, ) -> StreamStreamCall[TRequest, TResponse]: ... -"""Metadata""" +# Metadata: MetadataKey = str MetadataValue = str | bytes From 1c09ab48a479125af821b7bedcadfd56596917da Mon Sep 17 00:00:00 2001 From: Blake Williams Date: Wed, 27 Dec 2023 19:29:30 +1100 Subject: [PATCH 06/18] Default argument warnings, missing generics --- .../test_cases/check_handler_inheritance.py | 3 +- .../test_cases/check_server_interceptor.py | 2 +- stubs/grpc/grpc/__init__.pyi | 158 +++++++++--------- stubs/grpc/grpc/aio/__init__.pyi | 64 +++---- 4 files changed, 116 insertions(+), 111 deletions(-) diff --git a/stubs/grpc/@tests/test_cases/check_handler_inheritance.py b/stubs/grpc/@tests/test_cases/check_handler_inheritance.py index 60ce09d90f23..c0a88443c5ea 100644 --- a/stubs/grpc/@tests/test_cases/check_handler_inheritance.py +++ b/stubs/grpc/@tests/test_cases/check_handler_inheritance.py @@ -1,6 +1,5 @@ from __future__ import annotations -import typing from typing_extensions import assert_type import grpc @@ -20,7 +19,7 @@ def unary_unary_call(rq: Request, ctx: grpc.ServicerContext) -> Response: class ServiceHandler(grpc.ServiceRpcHandler[Request, Response]): - def service(self, handler_call_details: grpc.HandlerCallDetails) -> typing.Optional[grpc.RpcMethodHandler[Request, Response]]: + def service(self, handler_call_details: grpc.HandlerCallDetails) -> grpc.RpcMethodHandler[Request, Response] | None: rpc = grpc.RpcMethodHandler[Request, Response]() rpc.unary_unary = unary_unary_call return rpc diff --git a/stubs/grpc/@tests/test_cases/check_server_interceptor.py b/stubs/grpc/@tests/test_cases/check_server_interceptor.py index f83da1c1b7c5..6c469caf469c 100644 --- a/stubs/grpc/@tests/test_cases/check_server_interceptor.py +++ b/stubs/grpc/@tests/test_cases/check_server_interceptor.py @@ -18,5 +18,5 @@ def intercept_service( self, continuation: typing.Callable[[grpc.HandlerCallDetails], grpc.RpcMethodHandler[Request, Response] | None], handler_call_details: grpc.HandlerCallDetails, - ) -> typing.Optional[grpc.RpcMethodHandler[Request, Response]]: + ) -> grpc.RpcMethodHandler[Request, Response] | None: return continuation(handler_call_details) diff --git a/stubs/grpc/grpc/__init__.pyi b/stubs/grpc/grpc/__init__.pyi index 84b3cdefe5f5..4c0a68f23539 100644 --- a/stubs/grpc/grpc/__init__.pyi +++ b/stubs/grpc/grpc/__init__.pyi @@ -3,6 +3,7 @@ import threading import typing from concurrent import futures from types import ModuleType, TracebackType +from typing_extensions import TypeAlias __version__: str @@ -17,8 +18,8 @@ class _PartialStubMustCastOrIgnore: ... # 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? -_OptionKeyValue = tuple[str, typing.Any] -_Options = typing.Sequence[_OptionKeyValue] +_OptionKeyValue: TypeAlias = tuple[str, typing.Any] +_Options: TypeAlias = typing.Sequence[_OptionKeyValue] class Compression(enum.IntEnum): NoCompression = ... @@ -37,15 +38,21 @@ class LocalConnectionType(enum.Enum): # - https://github.com/grpc/grpc/blob/0e1984effd7e977ef18f1ad7fde7d10a2a153e1d/src/python/grpcio_tests/tests/unit/_invocation_defects_test.py#L66 Metadata = tuple[tuple[str, str | bytes], ...] +TRequest = typing.TypeVar("TRequest") +TResponse = typing.TypeVar("TResponse") + # Create Client: -def insecure_channel(target: str, options: _Options | None = None, compression: Compression | None = None) -> Channel: ... +def insecure_channel(target: str, options: _Options | None = ..., compression: Compression | None = ...) -> Channel: ... def secure_channel( - target: str, credentials: ChannelCredentials, options: _Options | None = None, compression: Compression | None = None + target: str, credentials: ChannelCredentials, options: _Options | None = ..., compression: Compression | None = ... ) -> Channel: ... Interceptor = ( - UnaryUnaryClientInterceptor | UnaryStreamClientInterceptor | StreamUnaryClientInterceptor | StreamStreamClientInterceptor + UnaryUnaryClientInterceptor[TRequest, TResponse] + | UnaryStreamClientInterceptor[TRequest, TResponse] + | StreamUnaryClientInterceptor[TRequest, TResponse] + | StreamStreamClientInterceptor[TRequest, TResponse] ) def intercept_channel(channel: Channel, *interceptors: Interceptor) -> Channel: ... @@ -53,14 +60,14 @@ def intercept_channel(channel: Channel, *interceptors: Interceptor) -> Channel: # Create Client Credentials: def ssl_channel_credentials( - root_certificates: bytes | None = None, private_key: bytes | None = None, certificate_chain: bytes | None = None + root_certificates: bytes | None = ..., private_key: bytes | None = ..., certificate_chain: bytes | None = ... ) -> ChannelCredentials: ... -def local_channel_credentials(local_connect_type: LocalConnectionType = LocalConnectionType.LOCAL_TCP) -> ChannelCredentials: ... -def metadata_call_credentials(metadata_plugin: AuthMetadataPlugin, name: str | None = None) -> CallCredentials: ... +def local_channel_credentials(local_connect_type: LocalConnectionType = ...) -> ChannelCredentials: ... +def metadata_call_credentials(metadata_plugin: AuthMetadataPlugin, name: str | None = ...) -> CallCredentials: ... def access_token_call_credentials(access_token: str) -> CallCredentials: ... -def alts_channel_credentials(service_accounts: typing.Sequence[str] | None = None) -> ChannelCredentials: ... +def alts_channel_credentials(service_accounts: typing.Sequence[str] | None = ...) -> ChannelCredentials: ... def compute_engine_channel_credentials() -> ChannelCredentials: ... -def xds_channel_credentials(fallback_credentials: ChannelCredentials | None = None) -> ChannelCredentials: ... +def xds_channel_credentials(fallback_credentials: ChannelCredentials | None = ...) -> ChannelCredentials: ... # GRPC docs say there should be at least two: def composite_call_credentials(creds1: CallCredentials, creds2: CallCredentials, *rest: CallCredentials) -> CallCredentials: ... @@ -74,12 +81,12 @@ def composite_channel_credentials( def server( thread_pool: futures.ThreadPoolExecutor, - handlers: list[GenericRpcHandler] | None = None, - interceptors: list[ServerInterceptor] | None = None, - options: _Options | None = None, - maximum_concurrent_rpcs: int | None = None, - compression: Compression | None = None, - xds: bool = False, + handlers: list[GenericRpcHandler] | None = ..., + interceptors: list[ServerInterceptor] | None = ..., + options: _Options | None = ..., + maximum_concurrent_rpcs: int | None = ..., + compression: Compression | None = ..., + xds: bool = ..., ) -> Server: ... # Create Server Credentials: @@ -88,17 +95,17 @@ CertificateChainPair = tuple[bytes, bytes] def ssl_server_credentials( private_key_certificate_chain_pairs: list[CertificateChainPair], - root_certificates: bytes | None = None, - require_client_auth: bool = False, + root_certificates: bytes | None = ..., + require_client_auth: bool = ..., ) -> ServerCredentials: ... -def local_server_credentials(local_connect_type: LocalConnectionType = LocalConnectionType.LOCAL_TCP) -> ServerCredentials: ... +def local_server_credentials(local_connect_type: LocalConnectionType = ...) -> ServerCredentials: ... def ssl_server_certificate_configuration( - private_key_certificate_chain_pairs: list[CertificateChainPair], root_certificates: bytes | None = None + private_key_certificate_chain_pairs: list[CertificateChainPair], root_certificates: bytes | None = ... ) -> ServerCertificateConfiguration: ... def dynamic_ssl_server_credentials( initial_certificate_configuration: ServerCertificateConfiguration, certificate_configuration_fetcher: typing.Callable[[], ServerCertificateConfiguration], - require_client_authentication: bool = False, + require_client_authentication: bool = ..., ) -> ServerCredentials: ... def alts_server_credentials() -> ServerCredentials: ... def insecure_server_credentials() -> ServerCredentials: ... @@ -122,23 +129,23 @@ ResponseSerializer = typing.Callable def unary_unary_rpc_method_handler( behavior: Behaviour, - request_deserializer: RequestDeserializer | None = None, - response_serializer: ResponseSerializer | None = None, + request_deserializer: RequestDeserializer | None = ..., + response_serializer: ResponseSerializer | None = ..., ) -> RpcMethodHandler: ... def unary_stream_rpc_method_handler( behavior: Behaviour, - request_deserializer: RequestDeserializer | None = None, - response_serializer: ResponseSerializer | None = None, + request_deserializer: RequestDeserializer | None = ..., + response_serializer: ResponseSerializer | None = ..., ) -> RpcMethodHandler: ... def stream_unary_rpc_method_handler( behavior: Behaviour, - request_deserializer: RequestDeserializer | None = None, - response_serializer: ResponseSerializer | None = None, + request_deserializer: RequestDeserializer | None = ..., + response_serializer: ResponseSerializer | None = ..., ) -> RpcMethodHandler: ... def stream_stream_rpc_method_handler( behavior: Behaviour, - request_deserializer: RequestDeserializer | None = None, - response_serializer: ResponseSerializer | None = None, + request_deserializer: RequestDeserializer | None = ..., + response_serializer: ResponseSerializer | None = ..., ) -> RpcMethodHandler: ... def method_handlers_generic_handler(service: str, method_handlers: dict[str, RpcMethodHandler]) -> GenericRpcHandler: ... @@ -200,7 +207,7 @@ class Channel: def stream_unary( self, method: str, request_serializer: RequestSerializer | None, response_deserializer: ResponseDeserializer | None ) -> StreamUnaryMultiCallable: ... - def subscribe(self, callback: typing.Callable[[ChannelConnectivity], None], try_to_connect: bool = False) -> None: ... + def subscribe(self, callback: typing.Callable[[ChannelConnectivity], None], try_to_connect: bool = ...) -> None: ... def unary_stream( self, method: str, request_serializer: RequestSerializer | None, response_deserializer: ResponseDeserializer | None ) -> UnaryStreamMultiCallable: ... @@ -226,11 +233,11 @@ class Server: def start(self) -> None: ... # Grace period is in seconds. - def stop(self, grace: float | None = None) -> threading.Event: ... + def stop(self, grace: float | None = ...) -> threading.Event: ... # Block current thread until the server stops. Returns a bool # indicates if the operation times out. Timeout is in seconds. - def wait_for_termination(self, timeout: float | None = None) -> bool: ... + def wait_for_termination(self, timeout: float | None = ...) -> bool: ... # Authentication & Authorization Objects: @@ -305,9 +312,6 @@ class ClientCallDetails: compression: Compression | None -TRequest = typing.TypeVar("TRequest") -TResponse = typing.TypeVar("TResponse") - # An object that is both a Call for the RPC and a Future. In the event of # RPC completion, the return Call-Future’s result value will be the # response message of the RPC. Should the event terminate with non-OK @@ -434,32 +438,32 @@ class UnaryUnaryMultiCallable(typing.Generic[TRequest, TResponse]): def __call__( self, request: TRequest, - timeout: float | None = None, - metadata: Metadata | None = None, - credentials: CallCredentials | None = None, + timeout: float | None = ..., + metadata: Metadata | None = ..., + credentials: CallCredentials | None = ..., # FIXME: optional bool seems weird, but that's what the docs suggest - wait_for_ready: bool | None = None, - compression: Compression | None = None, + wait_for_ready: bool | None = ..., + compression: Compression | None = ..., ) -> TResponse: ... def future( self, request: TRequest, - timeout: float | None = None, - metadata: Metadata | None = None, - credentials: CallCredentials | None = None, + timeout: float | None = ..., + metadata: Metadata | None = ..., + credentials: CallCredentials | None = ..., # FIXME: optional bool seems weird, but that's what the docs suggest - wait_for_ready: bool | None = None, - compression: Compression | None = None, + wait_for_ready: bool | None = ..., + compression: Compression | None = ..., ) -> CallFuture[TResponse]: ... def with_call( self, request: TRequest, - timeout: float | None = None, - metadata: Metadata | None = None, - credentials: CallCredentials | None = None, + timeout: float | None = ..., + metadata: Metadata | None = ..., + credentials: CallCredentials | None = ..., # FIXME: optional bool seems weird, but that's what the docs suggest - wait_for_ready: bool | None = None, - compression: Compression | None = None, + wait_for_ready: bool | None = ..., + compression: Compression | None = ..., # FIXME: Return value is documented as "The response value for the RPC and a Call value for the RPC"; # this is slightly unclear so this return type is a best-effort guess. ) -> tuple[TResponse, Call]: ... @@ -468,44 +472,44 @@ class UnaryStreamMultiCallable(typing.Generic[TRequest, TResponse]): def __call__( self, request: TRequest, - timeout: float | None = None, - metadata: Metadata | None = None, - credentials: CallCredentials | None = None, + timeout: float | None = ..., + metadata: Metadata | None = ..., + credentials: CallCredentials | None = ..., # FIXME: optional bool seems weird, but that's what the docs suggest - wait_for_ready: bool | None = None, - compression: Compression | None = None, + wait_for_ready: bool | None = ..., + compression: Compression | None = ..., ) -> CallIterator[TResponse]: ... class StreamUnaryMultiCallable(typing.Generic[TRequest, TResponse]): def __call__( self, request_iterator: typing.Iterator[TRequest], - timeout: float | None = None, - metadata: Metadata | None = None, - credentials: CallCredentials | None = None, + timeout: float | None = ..., + metadata: Metadata | None = ..., + credentials: CallCredentials | None = ..., # FIXME: optional bool seems weird, but that's what the docs suggest - wait_for_ready: bool | None = None, - compression: Compression | None = None, + wait_for_ready: bool | None = ..., + compression: Compression | None = ..., ) -> TResponse: ... def future( self, request_iterator: typing.Iterator[TRequest], - timeout: float | None = None, - metadata: Metadata | None = None, - credentials: CallCredentials | None = None, + timeout: float | None = ..., + metadata: Metadata | None = ..., + credentials: CallCredentials | None = ..., # FIXME: optional bool seems weird, but that's what the docs suggest - wait_for_ready: bool | None = None, - compression: Compression | None = None, + wait_for_ready: bool | None = ..., + compression: Compression | None = ..., ) -> CallFuture[TResponse]: ... def with_call( self, request_iterator: typing.Iterator[TRequest], - timeout: float | None = None, - metadata: Metadata | None = None, - credentials: CallCredentials | None = None, + timeout: float | None = ..., + metadata: Metadata | None = ..., + credentials: CallCredentials | None = ..., # FIXME: optional bool seems weird, but that's what the docs suggest - wait_for_ready: bool | None = None, - compression: Compression | None = None, + wait_for_ready: bool | None = ..., + compression: Compression | None = ..., # FIXME: Return value is documented as "The response value for the RPC and a Call value for the RPC"; # this is slightly unclear so this return type is a best-effort guess. ) -> tuple[TResponse, Call]: ... @@ -514,12 +518,12 @@ class StreamStreamMultiCallable(typing.Generic[TRequest, TResponse]): def __call__( self, request_iterator: typing.Iterator[TRequest], - timeout: float | None = None, - metadata: Metadata | None = None, - credentials: CallCredentials | None = None, + timeout: float | None = ..., + metadata: Metadata | None = ..., + credentials: CallCredentials | None = ..., # FIXME: optional bool seems weird, but that's what the docs suggest - wait_for_ready: bool | None = None, - compression: Compression | None = None, + wait_for_ready: bool | None = ..., + compression: Compression | None = ..., ) -> CallIterator[TResponse]: ... # Future Interfaces: @@ -535,11 +539,11 @@ class Future(typing.Generic[TFutureValue]): def cancelled(self) -> bool: ... def done(self) -> bool: ... def exception(self) -> Exception | None: ... - def result(self, timeout: float | None = None) -> TFutureValue: ... + def result(self, timeout: float | None = ...) -> TFutureValue: ... def running(self) -> bool: ... # FIXME: unsure of the exact return type here. Is it a traceback.StackSummary? - def traceback(self, timeout: float | None = None) -> typing.Any: ... + def traceback(self, timeout: float | None = ...) -> typing.Any: ... # Runtime Protobuf Parsing: diff --git a/stubs/grpc/grpc/aio/__init__.pyi b/stubs/grpc/grpc/aio/__init__.pyi index 5764d0de7f41..8fa03366f50f 100644 --- a/stubs/grpc/grpc/aio/__init__.pyi +++ b/stubs/grpc/grpc/aio/__init__.pyi @@ -46,16 +46,16 @@ ClientInterceptor = _PartialStubMustCastOrIgnore def insecure_channel( target: str, - options: _Options | None = None, - compression: Compression | None = None, - interceptors: typing.Sequence[ClientInterceptor] | None = None, + options: _Options | None = ..., + compression: Compression | None = ..., + interceptors: typing.Sequence[ClientInterceptor] | None = ..., ) -> Channel: ... def secure_channel( target: str, credentials: ChannelCredentials, - options: _Options | None = None, - compression: Compression | None = None, - interceptors: typing.Sequence[ClientInterceptor] | None = None, + options: _Options | None = ..., + compression: Compression | None = ..., + interceptors: typing.Sequence[ClientInterceptor] | None = ..., ) -> Channel: ... # Create Server: @@ -79,7 +79,7 @@ ResponseDeserializer = typing.Callable[[bytes], typing.Any] class Channel: async def close(self, grace: float | None) -> None: ... - def get_state(self, try_to_connect: bool = False) -> ChannelConnectivity: ... + def get_state(self, try_to_connect: bool = ...) -> ChannelConnectivity: ... async def wait_for_state_change(self, last_observed_state: ChannelConnectivity) -> None: ... def stream_stream( self, method: str, request_serializer: RequestSerializer | None, response_deserializer: ResponseDeserializer | None @@ -102,7 +102,9 @@ class Channel: # Server Object: class Server: - def add_generic_rpc_handlers(self, generic_rpc_handlers: typing.Iterable[GenericRpcHandler]) -> None: ... + def add_generic_rpc_handlers( + self, generic_rpc_handlers: typing.Iterable[GenericRpcHandler[typing.Any, typing.Any]] + ) -> None: ... # Returns an integer port on which server will accept RPC requests. def add_insecure_port(self, address: str) -> int: ... @@ -112,10 +114,10 @@ class Server: async def start(self) -> None: ... # Grace period is in seconds. - async def stop(self, grace: float | None = None) -> None: ... + async def stop(self, grace: float | None = ...) -> None: ... # Returns a bool indicates if the operation times out. Timeout is in seconds. - async def wait_for_termination(self, timeout: float | None = None) -> bool: ... + async def wait_for_termination(self, timeout: float | None = ...) -> bool: ... # Client-Side Context: @@ -163,7 +165,7 @@ class DoneCallback(typing.Generic[TRequest, TResponse]): def __call__(self, ctx: ServicerContext[TRequest, TResponse]) -> None: ... class ServicerContext(typing.Generic[TRequest, TResponse]): - async def abort(self, code: StatusCode, details: str = "", trailing_metadata: MetadataType = tuple()) -> typing.NoReturn: ... + async def abort(self, code: StatusCode, details: str = ..., trailing_metadata: MetadataType = ...) -> typing.NoReturn: ... async def read(self) -> TRequest: ... async def write(self, message: TResponse) -> None: ... async def send_initial_metadata(self, initial_metadata: MetadataType) -> None: ... @@ -303,48 +305,48 @@ class UnaryUnaryMultiCallable(typing.Generic[TRequest, TResponse]): def __call__( self, request: TRequest, - timeout: float | None = None, - metadata: MetadataType | None = None, - credentials: CallCredentials | None = None, + timeout: float | None = ..., + metadata: MetadataType | None = ..., + credentials: CallCredentials | None = ..., # FIXME: optional bool seems weird, but that's what the docs suggest - wait_for_ready: bool | None = None, - compression: Compression | None = None, + wait_for_ready: bool | None = ..., + compression: Compression | None = ..., ) -> UnaryUnaryCall[TRequest, TResponse]: ... class UnaryStreamMultiCallable(typing.Generic[TRequest, TResponse]): def __call__( self, request: TRequest, - timeout: float | None = None, - metadata: MetadataType | None = None, - credentials: CallCredentials | None = None, + timeout: float | None = ..., + metadata: MetadataType | None = ..., + credentials: CallCredentials | None = ..., # FIXME: optional bool seems weird, but that's what the docs suggest - wait_for_ready: bool | None = None, - compression: Compression | None = None, + wait_for_ready: bool | None = ..., + compression: Compression | None = ..., ) -> UnaryStreamCall[TRequest, TResponse]: ... class StreamUnaryMultiCallable(typing.Generic[TRequest, TResponse]): def __call__( self, request_iterator: typing.AsyncIterator[TRequest] | typing.Iterator[TRequest] | None, - timeout: float | None = None, - metadata: MetadataType | None = None, - credentials: CallCredentials | None = None, + timeout: float | None = ..., + metadata: MetadataType | None = ..., + credentials: CallCredentials | None = ..., # FIXME: optional bool seems weird, but that's what the docs suggest - wait_for_ready: bool | None = None, - compression: Compression | None = None, + wait_for_ready: bool | None = ..., + compression: Compression | None = ..., ) -> StreamUnaryCall[TRequest, TResponse]: ... class StreamStreamMultiCallable(typing.Generic[TRequest, TResponse]): def __call__( self, request_iterator: typing.AsyncIterator[TRequest] | typing.Iterator[TRequest] | None, - timeout: float | None = None, - metadata: MetadataType | None = None, - credentials: CallCredentials | None = None, + timeout: float | None = ..., + metadata: MetadataType | None = ..., + credentials: CallCredentials | None = ..., # FIXME: optional bool seems weird, but that's what the docs suggest - wait_for_ready: bool | None = None, - compression: Compression | None = None, + wait_for_ready: bool | None = ..., + compression: Compression | None = ..., ) -> StreamStreamCall[TRequest, TResponse]: ... # Metadata: From 505d234c750eedbf88f9ee486f095ac3a83c9212 Mon Sep 17 00:00:00 2001 From: Blake Williams Date: Wed, 27 Dec 2023 19:45:29 +1100 Subject: [PATCH 07/18] Add TypeAlias --- stubs/grpc/grpc/__init__.pyi | 16 ++++++++-------- stubs/grpc/grpc/aio/__init__.pyi | 27 ++++++++++++++------------- 2 files changed, 22 insertions(+), 21 deletions(-) diff --git a/stubs/grpc/grpc/__init__.pyi b/stubs/grpc/grpc/__init__.pyi index 4c0a68f23539..be9f597257ab 100644 --- a/stubs/grpc/grpc/__init__.pyi +++ b/stubs/grpc/grpc/__init__.pyi @@ -36,7 +36,7 @@ class LocalConnectionType(enum.Enum): # - https://github.com/grpc/grpc/blob/0e1984effd7e977ef18f1ad7fde7d10a2a153e1d/src/python/grpcio_tests/tests/unit/_metadata_test.py#L71 # - https://github.com/grpc/grpc/blob/0e1984effd7e977ef18f1ad7fde7d10a2a153e1d/src/python/grpcio_tests/tests/unit/_metadata_test.py#L58 # - https://github.com/grpc/grpc/blob/0e1984effd7e977ef18f1ad7fde7d10a2a153e1d/src/python/grpcio_tests/tests/unit/_invocation_defects_test.py#L66 -Metadata = tuple[tuple[str, str | bytes], ...] +Metadata: TypeAlias = tuple[tuple[str, str | bytes], ...] TRequest = typing.TypeVar("TRequest") TResponse = typing.TypeVar("TResponse") @@ -91,7 +91,7 @@ def server( # Create Server Credentials: -CertificateChainPair = tuple[bytes, bytes] +CertificateChainPair: TypeAlias = tuple[bytes, bytes] def ssl_server_credentials( private_key_certificate_chain_pairs: list[CertificateChainPair], @@ -120,12 +120,12 @@ def xds_server_credentials(fallback_credentials: ServerCredentials) -> ServerCre # def FloobDoob(self, request, context): # return response # -Behaviour = typing.Callable +Behaviour: TypeAlias = typing.Callable # XXX: These are probably the SerializeToTring/FromString pb2 methods, but # this needs further investigation -RequestDeserializer = typing.Callable -ResponseSerializer = typing.Callable +RequestDeserialize: TypeAlias = typing.Callable +ResponseSerialize: TypeAlias = typing.Callable def unary_unary_rpc_method_handler( behavior: Behaviour, @@ -196,8 +196,8 @@ class StatusCode(enum.Enum): # XXX: These are probably the SerializeToTring/FromString pb2 methods, but # this needs further investigation -RequestSerializer = typing.Callable -ResponseDeserializer = typing.Callable +RequestSerializer: TypeAlias = typing.Callable +ResponseDeserializer: TypeAlias = typing.Callable class Channel: def close(self) -> None: ... @@ -342,7 +342,7 @@ class UnaryUnaryClientInterceptor(typing.Generic[TRequest, TResponse]): request: TRequest, ) -> CallFuture[TResponse]: ... -class CallIterator(typing.Generic[TResponse], Call): +class CallIterator(Call, typing.Generic[TResponse]): def __iter__(self) -> typing.Iterator[TResponse]: ... class UnaryStreamClientInterceptor(typing.Generic[TRequest, TResponse]): diff --git a/stubs/grpc/grpc/aio/__init__.pyi b/stubs/grpc/grpc/aio/__init__.pyi index 8fa03366f50f..44b2d2292385 100644 --- a/stubs/grpc/grpc/aio/__init__.pyi +++ b/stubs/grpc/grpc/aio/__init__.pyi @@ -2,6 +2,7 @@ import asyncio import typing from concurrent import futures from types import TracebackType +from typing_extensions import TypeAlias from grpc import ( CallCredentials, @@ -42,7 +43,7 @@ class AioRpcError(RpcError): # Create Client: -ClientInterceptor = _PartialStubMustCastOrIgnore +ClientInterceptor: TypeAlias = _PartialStubMustCastOrIgnore def insecure_channel( target: str, @@ -74,8 +75,8 @@ def server( # 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 = typing.Callable[[typing.Any], bytes] -ResponseDeserializer = typing.Callable[[bytes], typing.Any] +RequestSerializer: TypeAlias = typing.Callable[[typing.Any], bytes] +ResponseDeserializer: TypeAlias = typing.Callable[[bytes], typing.Any] class Channel: async def close(self, grace: float | None) -> None: ... @@ -121,8 +122,8 @@ class Server: # Client-Side Context: -DoneCallbackType = typing.Callable[[typing.Any], None] -EOFType = object +DoneCallbackType: TypeAlias = typing.Callable[[typing.Any], None] +EOFType: TypeAlias = object class RpcContext: def cancelled(self) -> bool: ... @@ -138,19 +139,19 @@ class Call(RpcContext): async def details(self) -> str: ... async def wait_for_connection(self) -> None: ... -class UnaryUnaryCall(typing.Generic[TRequest, TResponse], Call): +class UnaryUnaryCall(Call, typing.Generic[TRequest, TResponse]): def __await__(self) -> typing.Generator[None, None, TResponse]: ... -class UnaryStreamCall(typing.Generic[TRequest, TResponse], Call): +class UnaryStreamCall(Call, typing.Generic[TRequest, TResponse]): def __aiter__(self) -> typing.AsyncIterator[TResponse]: ... async def read(self) -> EOFType | TResponse: ... -class StreamUnaryCall(typing.Generic[TRequest, TResponse], Call): +class StreamUnaryCall(Call, typing.Generic[TRequest, TResponse]): async def write(self, request: TRequest) -> None: ... async def done_writing(self) -> None: ... def __await__(self) -> typing.Generator[None, None, TResponse]: ... -class StreamStreamCall(typing.Generic[TRequest, TResponse], Call): +class StreamStreamCall(Call, typing.Generic[TRequest, TResponse]): def __aiter__(self) -> typing.AsyncIterator[TResponse]: ... async def read(self) -> EOFType | TResponse: ... async def write(self, request: TRequest) -> None: ... @@ -351,10 +352,10 @@ class StreamStreamMultiCallable(typing.Generic[TRequest, TResponse]): # Metadata: -MetadataKey = str -MetadataValue = str | bytes -MetadatumType = tuple[MetadataKey, MetadataValue] -MetadataType = Metadata | typing.Sequence[MetadatumType] +MetadataKey: TypeAlias = str +MetadataValue: TypeAlias = str | bytes +MetadatumType: TypeAlias = tuple[MetadataKey, MetadataValue] +MetadataType: TypeAlias = Metadata | typing.Sequence[MetadatumType] class Metadata(typing.Mapping): def __init__(self, *args: tuple[MetadataKey, MetadataValue]) -> None: ... From 7a7cf619365a6b1e4ac014932afe12bf9a15ce48 Mon Sep 17 00:00:00 2001 From: Blake Williams Date: Wed, 27 Dec 2023 20:06:30 +1100 Subject: [PATCH 08/18] Update typing.Callable to collections.abc.Callable --- stubs/grpc/grpc/__init__.pyi | 55 +++++++++++++++++--------------- stubs/grpc/grpc/aio/__init__.pyi | 17 +++++----- 2 files changed, 39 insertions(+), 33 deletions(-) diff --git a/stubs/grpc/grpc/__init__.pyi b/stubs/grpc/grpc/__init__.pyi index be9f597257ab..84caa896c4c3 100644 --- a/stubs/grpc/grpc/__init__.pyi +++ b/stubs/grpc/grpc/__init__.pyi @@ -1,6 +1,7 @@ import enum import threading import typing +from collections.abc import Callable from concurrent import futures from types import ModuleType, TracebackType from typing_extensions import TypeAlias @@ -41,6 +42,20 @@ Metadata: TypeAlias = tuple[tuple[str, str | bytes], ...] TRequest = typing.TypeVar("TRequest") TResponse = typing.TypeVar("TResponse") +# XXX: These are probably the SerializeToTring/FromString pb2 methods, but +# this needs further investigation +class RequestSerializer(typing.Protocol): + def __call__(self, *args: typing.Any, **kwargs: typing.Any): ... + +class RequestDeserializer(typing.Protocol): + def __call__(self, *args: typing.Any, **kwargs: typing.Any): ... + +class ResponseSerializer(typing.Protocol): + def __call__(self, *args: typing.Any, **kwargs: typing.Any): ... + +class ResponseDeserializer(typing.Protocol): + def __call__(self, *args: typing.Any, **kwargs: typing.Any): ... + # Create Client: def insecure_channel(target: str, options: _Options | None = ..., compression: Compression | None = ...) -> Channel: ... @@ -104,7 +119,7 @@ def ssl_server_certificate_configuration( ) -> ServerCertificateConfiguration: ... def dynamic_ssl_server_credentials( initial_certificate_configuration: ServerCertificateConfiguration, - certificate_configuration_fetcher: typing.Callable[[], ServerCertificateConfiguration], + certificate_configuration_fetcher: Callable[[], ServerCertificateConfiguration], require_client_authentication: bool = ..., ) -> ServerCredentials: ... def alts_server_credentials() -> ServerCredentials: ... @@ -120,12 +135,7 @@ def xds_server_credentials(fallback_credentials: ServerCredentials) -> ServerCre # def FloobDoob(self, request, context): # return response # -Behaviour: TypeAlias = typing.Callable - -# XXX: These are probably the SerializeToTring/FromString pb2 methods, but -# this needs further investigation -RequestDeserialize: TypeAlias = typing.Callable -ResponseSerialize: TypeAlias = typing.Callable +Behaviour: TypeAlias = Callable def unary_unary_rpc_method_handler( behavior: Behaviour, @@ -194,11 +204,6 @@ class StatusCode(enum.Enum): # Channel Object: -# XXX: These are probably the SerializeToTring/FromString pb2 methods, but -# this needs further investigation -RequestSerializer: TypeAlias = typing.Callable -ResponseDeserializer: TypeAlias = typing.Callable - class Channel: def close(self) -> None: ... def stream_stream( @@ -207,14 +212,14 @@ class Channel: def stream_unary( self, method: str, request_serializer: RequestSerializer | None, response_deserializer: ResponseDeserializer | None ) -> StreamUnaryMultiCallable: ... - def subscribe(self, callback: typing.Callable[[ChannelConnectivity], None], try_to_connect: bool = ...) -> None: ... + def subscribe(self, callback: Callable[[ChannelConnectivity], None], try_to_connect: bool = ...) -> None: ... def unary_stream( self, method: str, request_serializer: RequestSerializer | None, response_deserializer: ResponseDeserializer | None ) -> UnaryStreamMultiCallable: ... def unary_unary( self, method: str, request_serializer: RequestSerializer | None, response_deserializer: ResponseDeserializer | None ) -> UnaryUnaryMultiCallable: ... - def unsubscribe(self, callback: typing.Callable[[ChannelConnectivity], None]) -> None: ... + def unsubscribe(self, callback: Callable[[ChannelConnectivity], None]) -> None: ... def __enter__(self) -> Channel: ... def __exit__( self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None @@ -284,7 +289,7 @@ class RpcError(Exception): # Shared Context: class RpcContext: - def add_callback(self, callback: typing.Callable[[], None]) -> bool: ... + def add_callback(self, callback: Callable[[], None]) -> bool: ... def cancel(self): ... def is_active(self) -> bool: ... def time_remaining(self) -> float: ... @@ -337,7 +342,7 @@ class UnaryUnaryClientInterceptor(typing.Generic[TRequest, TResponse]): # status, the returned Call-Future’s exception value will be an # RpcError. # - continuation: typing.Callable[[ClientCallDetails, TRequest], CallFuture[TResponse]], + continuation: Callable[[ClientCallDetails, TRequest], CallFuture[TResponse]], client_call_details: ClientCallDetails, request: TRequest, ) -> CallFuture[TResponse]: ... @@ -348,7 +353,7 @@ class CallIterator(Call, typing.Generic[TResponse]): class UnaryStreamClientInterceptor(typing.Generic[TRequest, TResponse]): def intercept_unary_stream( self, - continuation: typing.Callable[[ClientCallDetails, TRequest], CallIterator[TResponse]], + continuation: Callable[[ClientCallDetails, TRequest], CallIterator[TResponse]], client_call_details: ClientCallDetails, request: TRequest, ) -> CallIterator[TResponse]: ... @@ -356,7 +361,7 @@ class UnaryStreamClientInterceptor(typing.Generic[TRequest, TResponse]): class StreamUnaryClientInterceptor(typing.Generic[TRequest, TResponse]): def intercept_stream_unary( self, - continuation: typing.Callable[[ClientCallDetails, TRequest], CallFuture[TResponse]], + continuation: Callable[[ClientCallDetails, TRequest], CallFuture[TResponse]], client_call_details: ClientCallDetails, request_iterator: typing.Iterator[TRequest], ) -> CallFuture[TResponse]: ... @@ -364,7 +369,7 @@ class StreamUnaryClientInterceptor(typing.Generic[TRequest, TResponse]): class StreamStreamClientInterceptor(typing.Generic[TRequest, TResponse]): def intercept_stream_stream( self, - continuation: typing.Callable[[ClientCallDetails, TRequest], CallIterator[TResponse]], + continuation: Callable[[ClientCallDetails, TRequest], CallIterator[TResponse]], client_call_details: ClientCallDetails, request_iterator: typing.Iterator[TRequest], ) -> CallIterator[TResponse]: ... @@ -405,13 +410,13 @@ class RpcMethodHandler(typing.Generic[TRequest, TResponse]): # XXX: not clear from docs whether this is optional or not response_serializer: ResponseSerializer | None - unary_unary: typing.Callable[[TRequest, ServicerContext], TResponse] | None + unary_unary: Callable[[TRequest, ServicerContext], TResponse] | None - unary_stream: typing.Callable[[TRequest, ServicerContext], typing.Iterator[TResponse]] | None + unary_stream: Callable[[TRequest, ServicerContext], typing.Iterator[TResponse]] | None - stream_unary: typing.Callable[[typing.Iterator[TRequest], ServicerContext], TResponse] | None + stream_unary: Callable[[typing.Iterator[TRequest], ServicerContext], TResponse] | None - stream_stream: typing.Callable[[typing.Iterator[TRequest], ServicerContext], typing.Iterator[TResponse]] | None + stream_stream: Callable[[typing.Iterator[TRequest], ServicerContext], typing.Iterator[TResponse]] | None class HandlerCallDetails: method: str @@ -428,7 +433,7 @@ class ServiceRpcHandler(GenericRpcHandler[TRequest, TResponse], typing.Generic[T class ServerInterceptor(typing.Generic[TRequest, TResponse]): def intercept_service( self, - continuation: typing.Callable[[HandlerCallDetails], RpcMethodHandler[TRequest, TResponse] | None], + continuation: Callable[[HandlerCallDetails], RpcMethodHandler[TRequest, TResponse] | None], handler_call_details: HandlerCallDetails, ) -> RpcMethodHandler[TRequest, TResponse] | None: ... @@ -534,7 +539,7 @@ class FutureCancelledError(Exception): ... TFutureValue = typing.TypeVar("TFutureValue") class Future(typing.Generic[TFutureValue]): - def add_done_callback(self, fn: typing.Callable[[Future[TFutureValue]], None]) -> None: ... + def add_done_callback(self, fn: Callable[[Future[TFutureValue]], None]) -> None: ... def cancel(self) -> bool: ... def cancelled(self) -> bool: ... def done(self) -> bool: ... diff --git a/stubs/grpc/grpc/aio/__init__.pyi b/stubs/grpc/grpc/aio/__init__.pyi index 44b2d2292385..343ee7870ccf 100644 --- a/stubs/grpc/grpc/aio/__init__.pyi +++ b/stubs/grpc/grpc/aio/__init__.pyi @@ -1,5 +1,6 @@ import asyncio import typing +from collections.abc import Callable from concurrent import futures from types import TracebackType from typing_extensions import TypeAlias @@ -75,8 +76,8 @@ def server( # 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 = typing.Callable[[typing.Any], bytes] -ResponseDeserializer: TypeAlias = typing.Callable[[bytes], typing.Any] +RequestSerializer: TypeAlias = Callable[[typing.Any], bytes] +ResponseDeserializer: TypeAlias = Callable[[bytes], typing.Any] class Channel: async def close(self, grace: float | None) -> None: ... @@ -122,7 +123,7 @@ class Server: # Client-Side Context: -DoneCallbackType: TypeAlias = typing.Callable[[typing.Any], None] +DoneCallbackType: TypeAlias = Callable[[typing.Any], None] EOFType: TypeAlias = object class RpcContext: @@ -262,7 +263,7 @@ class UnaryUnaryClientInterceptor(typing.Generic[TRequest, TResponse]): async def intercept_unary_unary( self, # XXX: See equivalent function in grpc types for notes about continuation: - continuation: typing.Callable[[ClientCallDetails, TRequest], UnaryUnaryCall[TRequest, TResponse]], + continuation: Callable[[ClientCallDetails, TRequest], UnaryUnaryCall[TRequest, TResponse]], client_call_details: ClientCallDetails, request: TRequest, ) -> TResponse: ... @@ -270,7 +271,7 @@ class UnaryUnaryClientInterceptor(typing.Generic[TRequest, TResponse]): class UnaryStreamClientInterceptor(typing.Generic[TRequest, TResponse]): async def intercept_unary_stream( self, - continuation: typing.Callable[[ClientCallDetails, TRequest], UnaryStreamCall[TRequest, TResponse]], + continuation: Callable[[ClientCallDetails, TRequest], UnaryStreamCall[TRequest, TResponse]], client_call_details: ClientCallDetails, request: TRequest, ) -> typing.AsyncIterable[TResponse] | UnaryStreamCall[TRequest, TResponse]: ... @@ -278,7 +279,7 @@ class UnaryStreamClientInterceptor(typing.Generic[TRequest, TResponse]): class StreamUnaryClientInterceptor(typing.Generic[TRequest, TResponse]): async def intercept_stream_unary( self, - continuation: typing.Callable[[ClientCallDetails, TRequest], StreamUnaryCall[TRequest, TResponse]], + continuation: Callable[[ClientCallDetails, TRequest], StreamUnaryCall[TRequest, TResponse]], client_call_details: ClientCallDetails, request_iterator: typing.AsyncIterable[TRequest] | typing.Iterable[TRequest], ) -> typing.AsyncIterable[TResponse] | UnaryStreamCall[TRequest, TResponse]: ... @@ -286,7 +287,7 @@ class StreamUnaryClientInterceptor(typing.Generic[TRequest, TResponse]): class StreamStreamClientInterceptor(typing.Generic[TRequest, TResponse]): async def intercept_stream_stream( self, - continuation: typing.Callable[[ClientCallDetails, TRequest], StreamStreamCall[TRequest, TResponse]], + continuation: Callable[[ClientCallDetails, TRequest], StreamStreamCall[TRequest, TResponse]], client_call_details: ClientCallDetails, request_iterator: typing.AsyncIterable[TRequest] | typing.Iterable[TRequest], ) -> typing.AsyncIterable[TResponse] | StreamStreamCall[TRequest, TResponse]: ... @@ -296,7 +297,7 @@ class StreamStreamClientInterceptor(typing.Generic[TRequest, TResponse]): class ServerInterceptor(typing.Generic[TRequest, TResponse]): async def intercept_service( self, - continuation: typing.Callable[[HandlerCallDetails], typing.Awaitable[RpcMethodHandler[TRequest, TResponse]]], + continuation: Callable[[HandlerCallDetails], typing.Awaitable[RpcMethodHandler[TRequest, TResponse]]], handler_call_details: HandlerCallDetails, ) -> RpcMethodHandler[TRequest, TResponse]: ... From 0a228f86f22168d508581f93533c989c220497fc Mon Sep 17 00:00:00 2001 From: Blake Williams Date: Wed, 27 Dec 2023 20:48:35 +1100 Subject: [PATCH 09/18] Update more typings to collections.abcs --- stubs/grpc/grpc/__init__.pyi | 82 ++++++++++++++++---------------- stubs/grpc/grpc/aio/__init__.pyi | 59 +++++++++++------------ 2 files changed, 69 insertions(+), 72 deletions(-) diff --git a/stubs/grpc/grpc/__init__.pyi b/stubs/grpc/grpc/__init__.pyi index 84caa896c4c3..d7986fdb329a 100644 --- a/stubs/grpc/grpc/__init__.pyi +++ b/stubs/grpc/grpc/__init__.pyi @@ -1,10 +1,10 @@ import enum import threading import typing -from collections.abc import Callable +from collections.abc import Callable, Iterable, Iterator, Mapping, Sequence from concurrent import futures from types import ModuleType, TracebackType -from typing_extensions import TypeAlias +from typing_extensions import Self, TypeAlias __version__: str @@ -20,7 +20,7 @@ class _PartialStubMustCastOrIgnore: ... # 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? _OptionKeyValue: TypeAlias = tuple[str, typing.Any] -_Options: TypeAlias = typing.Sequence[_OptionKeyValue] +_Options: TypeAlias = Sequence[_OptionKeyValue] class Compression(enum.IntEnum): NoCompression = ... @@ -56,6 +56,25 @@ class ResponseSerializer(typing.Protocol): class ResponseDeserializer(typing.Protocol): def __call__(self, *args: typing.Any, **kwargs: typing.Any): ... +# Future Interfaces: + +class FutureTimeoutError(Exception): ... +class FutureCancelledError(Exception): ... + +TFutureValue = typing.TypeVar("TFutureValue") + +class Future(typing.Generic[TFutureValue]): + def add_done_callback(self, fn: Callable[[Future[TFutureValue]], None]) -> None: ... + def cancel(self) -> bool: ... + def cancelled(self) -> bool: ... + def done(self) -> bool: ... + def exception(self) -> Exception | None: ... + def result(self, timeout: float | None = ...) -> TFutureValue: ... + def running(self) -> bool: ... + + # FIXME: unsure of the exact return type here. Is it a traceback.StackSummary? + def traceback(self, timeout: float | None = ...) -> typing.Any: ... + # Create Client: def insecure_channel(target: str, options: _Options | None = ..., compression: Compression | None = ...) -> Channel: ... @@ -63,7 +82,7 @@ def secure_channel( target: str, credentials: ChannelCredentials, options: _Options | None = ..., compression: Compression | None = ... ) -> Channel: ... -Interceptor = ( +Interceptor: TypeAlias = ( UnaryUnaryClientInterceptor[TRequest, TResponse] | UnaryStreamClientInterceptor[TRequest, TResponse] | StreamUnaryClientInterceptor[TRequest, TResponse] @@ -80,7 +99,7 @@ def ssl_channel_credentials( def local_channel_credentials(local_connect_type: LocalConnectionType = ...) -> ChannelCredentials: ... def metadata_call_credentials(metadata_plugin: AuthMetadataPlugin, name: str | None = ...) -> CallCredentials: ... def access_token_call_credentials(access_token: str) -> CallCredentials: ... -def alts_channel_credentials(service_accounts: typing.Sequence[str] | None = ...) -> ChannelCredentials: ... +def alts_channel_credentials(service_accounts: Sequence[str] | None = ...) -> ChannelCredentials: ... def compute_engine_channel_credentials() -> ChannelCredentials: ... def xds_channel_credentials(fallback_credentials: ChannelCredentials | None = ...) -> ChannelCredentials: ... @@ -220,7 +239,7 @@ class Channel: self, method: str, request_serializer: RequestSerializer | None, response_deserializer: ResponseDeserializer | None ) -> UnaryUnaryMultiCallable: ... def unsubscribe(self, callback: Callable[[ChannelConnectivity], None]) -> None: ... - def __enter__(self) -> Channel: ... + def __enter__(self) -> Self: ... def __exit__( self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None ) -> bool | None: ... @@ -228,7 +247,7 @@ class Channel: # Server Object: class Server: - def add_generic_rpc_handlers(self, generic_rpc_handlers: typing.Iterable[GenericRpcHandler]) -> None: ... + def add_generic_rpc_handlers(self, generic_rpc_handlers: Iterable[GenericRpcHandler]) -> None: ... # Returns an integer port on which server will accept RPC requests. def add_insecure_port(self, address: str) -> int: ... @@ -322,7 +341,7 @@ class ClientCallDetails: # response message of the RPC. Should the event terminate with non-OK # status, the returned Call-Future’s exception value will be an RpcError. # -class CallFuture(Call, Future[TResponse], typing.Generic[TResponse]): ... +class CallFuture(Call, Future[TResponse]): ... class UnaryUnaryClientInterceptor(typing.Generic[TRequest, TResponse]): def intercept_unary_unary( @@ -348,7 +367,7 @@ class UnaryUnaryClientInterceptor(typing.Generic[TRequest, TResponse]): ) -> CallFuture[TResponse]: ... class CallIterator(Call, typing.Generic[TResponse]): - def __iter__(self) -> typing.Iterator[TResponse]: ... + def __iter__(self) -> Iterator[TResponse]: ... class UnaryStreamClientInterceptor(typing.Generic[TRequest, TResponse]): def intercept_unary_stream( @@ -363,7 +382,7 @@ class StreamUnaryClientInterceptor(typing.Generic[TRequest, TResponse]): self, continuation: Callable[[ClientCallDetails, TRequest], CallFuture[TResponse]], client_call_details: ClientCallDetails, - request_iterator: typing.Iterator[TRequest], + request_iterator: Iterator[TRequest], ) -> CallFuture[TResponse]: ... class StreamStreamClientInterceptor(typing.Generic[TRequest, TResponse]): @@ -371,7 +390,7 @@ class StreamStreamClientInterceptor(typing.Generic[TRequest, TResponse]): self, continuation: Callable[[ClientCallDetails, TRequest], CallIterator[TResponse]], client_call_details: ClientCallDetails, - request_iterator: typing.Iterator[TRequest], + request_iterator: Iterator[TRequest], ) -> CallIterator[TResponse]: ... # Service-Side Context: @@ -382,12 +401,12 @@ class ServicerContext(RpcContext): def abort_with_status(self, status: Status) -> typing.NoReturn: ... # FIXME: The docs say "A map of strings to an iterable of bytes for each auth property". - # Does that mean 'bytes' (which is iterable), or 'typing.Iterable[bytes]'? - def auth_context(self) -> typing.Mapping[str, bytes]: ... + # Does that mean 'bytes' (which is iterable), or 'Iterable[bytes]'? + def auth_context(self) -> Mapping[str, bytes]: ... def disable_next_message_compression(self) -> None: ... def invocation_metadata(self) -> Metadata: ... def peer(self) -> str: ... - def peer_identities(self) -> typing.Iterable[bytes] | None: ... + def peer_identities(self) -> Iterable[bytes] | None: ... def peer_identity_key(self) -> str | None: ... def send_initial_metadata(self, initial_metadata: Metadata) -> None: ... def set_code(self, code: StatusCode) -> None: ... @@ -412,11 +431,11 @@ class RpcMethodHandler(typing.Generic[TRequest, TResponse]): unary_unary: Callable[[TRequest, ServicerContext], TResponse] | None - unary_stream: Callable[[TRequest, ServicerContext], typing.Iterator[TResponse]] | None + unary_stream: Callable[[TRequest, ServicerContext], Iterator[TResponse]] | None - stream_unary: Callable[[typing.Iterator[TRequest], ServicerContext], TResponse] | None + stream_unary: Callable[[Iterator[TRequest], ServicerContext], TResponse] | None - stream_stream: Callable[[typing.Iterator[TRequest], ServicerContext], typing.Iterator[TResponse]] | None + stream_stream: Callable[[Iterator[TRequest], ServicerContext], Iterator[TResponse]] | None class HandlerCallDetails: method: str @@ -425,7 +444,7 @@ class HandlerCallDetails: class GenericRpcHandler(typing.Generic[TRequest, TResponse]): def service(self, handler_call_details: HandlerCallDetails) -> RpcMethodHandler[TRequest, TResponse] | None: ... -class ServiceRpcHandler(GenericRpcHandler[TRequest, TResponse], typing.Generic[TRequest, TResponse]): +class ServiceRpcHandler(GenericRpcHandler[TRequest, TResponse]): def service_name(self) -> str: ... # Service-Side Interceptor: @@ -488,7 +507,7 @@ class UnaryStreamMultiCallable(typing.Generic[TRequest, TResponse]): class StreamUnaryMultiCallable(typing.Generic[TRequest, TResponse]): def __call__( self, - request_iterator: typing.Iterator[TRequest], + request_iterator: Iterator[TRequest], timeout: float | None = ..., metadata: Metadata | None = ..., credentials: CallCredentials | None = ..., @@ -498,7 +517,7 @@ class StreamUnaryMultiCallable(typing.Generic[TRequest, TResponse]): ) -> TResponse: ... def future( self, - request_iterator: typing.Iterator[TRequest], + request_iterator: Iterator[TRequest], timeout: float | None = ..., metadata: Metadata | None = ..., credentials: CallCredentials | None = ..., @@ -508,7 +527,7 @@ class StreamUnaryMultiCallable(typing.Generic[TRequest, TResponse]): ) -> CallFuture[TResponse]: ... def with_call( self, - request_iterator: typing.Iterator[TRequest], + request_iterator: Iterator[TRequest], timeout: float | None = ..., metadata: Metadata | None = ..., credentials: CallCredentials | None = ..., @@ -522,7 +541,7 @@ class StreamUnaryMultiCallable(typing.Generic[TRequest, TResponse]): class StreamStreamMultiCallable(typing.Generic[TRequest, TResponse]): def __call__( self, - request_iterator: typing.Iterator[TRequest], + request_iterator: Iterator[TRequest], timeout: float | None = ..., metadata: Metadata | None = ..., credentials: CallCredentials | None = ..., @@ -531,25 +550,6 @@ class StreamStreamMultiCallable(typing.Generic[TRequest, TResponse]): compression: Compression | None = ..., ) -> CallIterator[TResponse]: ... -# Future Interfaces: - -class FutureTimeoutError(Exception): ... -class FutureCancelledError(Exception): ... - -TFutureValue = typing.TypeVar("TFutureValue") - -class Future(typing.Generic[TFutureValue]): - def add_done_callback(self, fn: Callable[[Future[TFutureValue]], None]) -> None: ... - def cancel(self) -> bool: ... - def cancelled(self) -> bool: ... - def done(self) -> bool: ... - def exception(self) -> Exception | None: ... - def result(self, timeout: float | None = ...) -> TFutureValue: ... - def running(self) -> bool: ... - - # FIXME: unsure of the exact return type here. Is it a traceback.StackSummary? - def traceback(self, timeout: float | None = ...) -> typing.Any: ... - # Runtime Protobuf Parsing: def protos(protobuf_path: str) -> ModuleType: ... diff --git a/stubs/grpc/grpc/aio/__init__.pyi b/stubs/grpc/grpc/aio/__init__.pyi index 343ee7870ccf..4b59b352e0e2 100644 --- a/stubs/grpc/grpc/aio/__init__.pyi +++ b/stubs/grpc/grpc/aio/__init__.pyi @@ -1,9 +1,9 @@ import asyncio import typing -from collections.abc import Callable +from collections.abc import AsyncIterable, AsyncIterator, Awaitable, Callable, Generator, Iterable, Iterator, Mapping, Sequence from concurrent import futures from types import TracebackType -from typing_extensions import TypeAlias +from typing_extensions import Self, TypeAlias from grpc import ( CallCredentials, @@ -50,22 +50,22 @@ def insecure_channel( target: str, options: _Options | None = ..., compression: Compression | None = ..., - interceptors: typing.Sequence[ClientInterceptor] | None = ..., + interceptors: Sequence[ClientInterceptor] | None = ..., ) -> Channel: ... def secure_channel( target: str, credentials: ChannelCredentials, options: _Options | None = ..., compression: Compression | None = ..., - interceptors: typing.Sequence[ClientInterceptor] | None = ..., + interceptors: Sequence[ClientInterceptor] | None = ..., ) -> Channel: ... # Create Server: def server( migration_thread_pool: futures.Executor | None = ..., - handlers: typing.Sequence[GenericRpcHandler[typing.Any, typing.Any]] | None = ..., - interceptors: typing.Sequence[ServerInterceptor[typing.Any, typing.Any]] | None = ..., + handlers: Sequence[GenericRpcHandler[typing.Any, typing.Any]] | None = ..., + interceptors: Sequence[ServerInterceptor[typing.Any, typing.Any]] | None = ..., options: _Options | None = ..., maximum_concurrent_rpcs: int | None = ..., compression: Compression | None = ..., @@ -95,7 +95,7 @@ class Channel: def unary_unary( self, method: str, request_serializer: RequestSerializer | None, response_deserializer: ResponseDeserializer | None ) -> UnaryUnaryMultiCallable: ... - async def __aenter__(self) -> Channel: ... + async def __aenter__(self) -> Self: ... async def __aexit__( self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None ) -> bool | None: ... @@ -104,9 +104,7 @@ class Channel: # Server Object: class Server: - def add_generic_rpc_handlers( - self, generic_rpc_handlers: typing.Iterable[GenericRpcHandler[typing.Any, typing.Any]] - ) -> None: ... + def add_generic_rpc_handlers(self, generic_rpc_handlers: Iterable[GenericRpcHandler[typing.Any, typing.Any]]) -> None: ... # Returns an integer port on which server will accept RPC requests. def add_insecure_port(self, address: str) -> int: ... @@ -141,19 +139,19 @@ class Call(RpcContext): async def wait_for_connection(self) -> None: ... class UnaryUnaryCall(Call, typing.Generic[TRequest, TResponse]): - def __await__(self) -> typing.Generator[None, None, TResponse]: ... + def __await__(self) -> Generator[None, None, TResponse]: ... class UnaryStreamCall(Call, typing.Generic[TRequest, TResponse]): - def __aiter__(self) -> typing.AsyncIterator[TResponse]: ... + def __aiter__(self) -> AsyncIterator[TResponse]: ... async def read(self) -> EOFType | TResponse: ... class StreamUnaryCall(Call, typing.Generic[TRequest, TResponse]): async def write(self, request: TRequest) -> None: ... async def done_writing(self) -> None: ... - def __await__(self) -> typing.Generator[None, None, TResponse]: ... + def __await__(self) -> Generator[None, None, TResponse]: ... class StreamStreamCall(Call, typing.Generic[TRequest, TResponse]): - def __aiter__(self) -> typing.AsyncIterator[TResponse]: ... + def __aiter__(self) -> AsyncIterator[TResponse]: ... async def read(self) -> EOFType | TResponse: ... async def write(self, request: TRequest) -> None: ... async def done_writing(self) -> None: ... @@ -179,9 +177,9 @@ class ServicerContext(typing.Generic[TRequest, TResponse]): def set_compression(self, compression: Compression) -> None: ... def disable_next_message_compression(self) -> None: ... def peer(self) -> str: ... - def peer_identities(self) -> typing.Iterable[bytes] | None: ... + def peer_identities(self) -> Iterable[bytes] | None: ... def peer_identity_key(self) -> str | None: ... - def auth_context(self) -> typing.Mapping[str, typing.Iterable[bytes]]: ... + def auth_context(self) -> Mapping[str, Iterable[bytes]]: ... def time_remaining(self) -> float: ... def trailing_metadata(self) -> Metadata: ... def code(self) -> StatusCode: ... @@ -227,11 +225,11 @@ class InterceptedCall(typing.Generic[TRequest, TResponse]): async def debug_error_string(self) -> str | None: ... async def wait_for_connection(self) -> None: ... -class InterceptedUnaryUnaryCall(InterceptedCall[TRequest, TResponse], typing.Generic[TRequest, TResponse]): +class InterceptedUnaryUnaryCall(InterceptedCall[TRequest, TResponse]): def __await__(self): ... def __init__( self, - interceptors: typing.Sequence[UnaryUnaryClientInterceptor[TRequest, TResponse]], + interceptors: Sequence[UnaryUnaryClientInterceptor[TRequest, TResponse]], request: TRequest, timeout: float | None, metadata: Metadata, @@ -247,7 +245,7 @@ class InterceptedUnaryUnaryCall(InterceptedCall[TRequest, TResponse], typing.Gen # pylint: disable=too-many-arguments async def _invoke( self, - interceptors: typing.Sequence[UnaryUnaryClientInterceptor[TRequest, TResponse]], + interceptors: Sequence[UnaryUnaryClientInterceptor[TRequest, TResponse]], method: bytes, timeout: float | None, metadata: Metadata | None, @@ -274,30 +272,30 @@ class UnaryStreamClientInterceptor(typing.Generic[TRequest, TResponse]): continuation: Callable[[ClientCallDetails, TRequest], UnaryStreamCall[TRequest, TResponse]], client_call_details: ClientCallDetails, request: TRequest, - ) -> typing.AsyncIterable[TResponse] | UnaryStreamCall[TRequest, TResponse]: ... + ) -> AsyncIterable[TResponse] | UnaryStreamCall[TRequest, TResponse]: ... class StreamUnaryClientInterceptor(typing.Generic[TRequest, TResponse]): async def intercept_stream_unary( self, continuation: Callable[[ClientCallDetails, TRequest], StreamUnaryCall[TRequest, TResponse]], client_call_details: ClientCallDetails, - request_iterator: typing.AsyncIterable[TRequest] | typing.Iterable[TRequest], - ) -> typing.AsyncIterable[TResponse] | UnaryStreamCall[TRequest, TResponse]: ... + request_iterator: AsyncIterable[TRequest] | Iterable[TRequest], + ) -> AsyncIterable[TResponse] | UnaryStreamCall[TRequest, TResponse]: ... class StreamStreamClientInterceptor(typing.Generic[TRequest, TResponse]): async def intercept_stream_stream( self, continuation: Callable[[ClientCallDetails, TRequest], StreamStreamCall[TRequest, TResponse]], client_call_details: ClientCallDetails, - request_iterator: typing.AsyncIterable[TRequest] | typing.Iterable[TRequest], - ) -> typing.AsyncIterable[TResponse] | StreamStreamCall[TRequest, TResponse]: ... + request_iterator: AsyncIterable[TRequest] | Iterable[TRequest], + ) -> AsyncIterable[TResponse] | StreamStreamCall[TRequest, TResponse]: ... # Server-Side Interceptor: class ServerInterceptor(typing.Generic[TRequest, TResponse]): async def intercept_service( self, - continuation: Callable[[HandlerCallDetails], typing.Awaitable[RpcMethodHandler[TRequest, TResponse]]], + continuation: Callable[[HandlerCallDetails], Awaitable[RpcMethodHandler[TRequest, TResponse]]], handler_call_details: HandlerCallDetails, ) -> RpcMethodHandler[TRequest, TResponse]: ... @@ -330,7 +328,7 @@ class UnaryStreamMultiCallable(typing.Generic[TRequest, TResponse]): class StreamUnaryMultiCallable(typing.Generic[TRequest, TResponse]): def __call__( self, - request_iterator: typing.AsyncIterator[TRequest] | typing.Iterator[TRequest] | None, + request_iterator: AsyncIterator[TRequest] | Iterator[TRequest] | None, timeout: float | None = ..., metadata: MetadataType | None = ..., credentials: CallCredentials | None = ..., @@ -342,7 +340,7 @@ class StreamUnaryMultiCallable(typing.Generic[TRequest, TResponse]): class StreamStreamMultiCallable(typing.Generic[TRequest, TResponse]): def __call__( self, - request_iterator: typing.AsyncIterator[TRequest] | typing.Iterator[TRequest] | None, + request_iterator: AsyncIterator[TRequest] | Iterator[TRequest] | None, timeout: float | None = ..., metadata: MetadataType | None = ..., credentials: CallCredentials | None = ..., @@ -356,9 +354,9 @@ class StreamStreamMultiCallable(typing.Generic[TRequest, TResponse]): MetadataKey: TypeAlias = str MetadataValue: TypeAlias = str | bytes MetadatumType: TypeAlias = tuple[MetadataKey, MetadataValue] -MetadataType: TypeAlias = Metadata | typing.Sequence[MetadatumType] +MetadataType: TypeAlias = Metadata | Sequence[MetadatumType] -class Metadata(typing.Mapping): +class Metadata(Mapping): def __init__(self, *args: tuple[MetadataKey, MetadataValue]) -> None: ... @classmethod def from_tuple(cls, raw_metadata: tuple[MetadataKey, MetadataValue]) -> Metadata: ... @@ -368,10 +366,9 @@ class Metadata(typing.Mapping): def __setitem__(self, key: MetadataKey, value: MetadataValue) -> None: ... def __delitem__(self, key: MetadataKey) -> None: ... def delete_all(self, key: MetadataKey) -> None: ... - def __iter__(self) -> typing.Iterator[tuple[MetadataKey, MetadataValue]]: ... + def __iter__(self) -> Iterator[tuple[MetadataKey, MetadataValue]]: ... def get_all(self, key: MetadataKey) -> list[MetadataValue]: ... def set_all(self, key: MetadataKey, values: list[MetadataValue]) -> None: ... def __contains__(self, key: object) -> bool: ... def __eq__(self, other: object) -> bool: ... def __add__(self, other: typing.Any) -> Metadata: ... - def __repr__(self) -> str: ... From 1e31e622962fb31fa11a49f415902a7f673b0395 Mon Sep 17 00:00:00 2001 From: Blake Williams Date: Wed, 27 Dec 2023 20:50:16 +1100 Subject: [PATCH 10/18] Add underscore to typevars --- stubs/grpc/grpc/__init__.pyi | 120 +++++++++++++++---------------- stubs/grpc/grpc/aio/__init__.pyi | 120 +++++++++++++++---------------- 2 files changed, 120 insertions(+), 120 deletions(-) diff --git a/stubs/grpc/grpc/__init__.pyi b/stubs/grpc/grpc/__init__.pyi index d7986fdb329a..94b6797e0ffe 100644 --- a/stubs/grpc/grpc/__init__.pyi +++ b/stubs/grpc/grpc/__init__.pyi @@ -39,8 +39,8 @@ class LocalConnectionType(enum.Enum): # - https://github.com/grpc/grpc/blob/0e1984effd7e977ef18f1ad7fde7d10a2a153e1d/src/python/grpcio_tests/tests/unit/_invocation_defects_test.py#L66 Metadata: TypeAlias = tuple[tuple[str, str | bytes], ...] -TRequest = typing.TypeVar("TRequest") -TResponse = typing.TypeVar("TResponse") +_TRequest = typing.TypeVar("_TRequest") +_TResponse = typing.TypeVar("_TResponse") # XXX: These are probably the SerializeToTring/FromString pb2 methods, but # this needs further investigation @@ -61,15 +61,15 @@ class ResponseDeserializer(typing.Protocol): class FutureTimeoutError(Exception): ... class FutureCancelledError(Exception): ... -TFutureValue = typing.TypeVar("TFutureValue") +_TFutureValue = typing.TypeVar("_TFutureValue") -class Future(typing.Generic[TFutureValue]): - def add_done_callback(self, fn: Callable[[Future[TFutureValue]], None]) -> None: ... +class Future(typing.Generic[_TFutureValue]): + def add_done_callback(self, fn: Callable[[Future[_TFutureValue]], None]) -> None: ... def cancel(self) -> bool: ... def cancelled(self) -> bool: ... def done(self) -> bool: ... def exception(self) -> Exception | None: ... - def result(self, timeout: float | None = ...) -> TFutureValue: ... + def result(self, timeout: float | None = ...) -> _TFutureValue: ... def running(self) -> bool: ... # FIXME: unsure of the exact return type here. Is it a traceback.StackSummary? @@ -83,10 +83,10 @@ def secure_channel( ) -> Channel: ... Interceptor: TypeAlias = ( - UnaryUnaryClientInterceptor[TRequest, TResponse] - | UnaryStreamClientInterceptor[TRequest, TResponse] - | StreamUnaryClientInterceptor[TRequest, TResponse] - | StreamStreamClientInterceptor[TRequest, TResponse] + UnaryUnaryClientInterceptor[_TRequest, _TResponse] + | UnaryStreamClientInterceptor[_TRequest, _TResponse] + | StreamUnaryClientInterceptor[_TRequest, _TResponse] + | StreamStreamClientInterceptor[_TRequest, _TResponse] ) def intercept_channel(channel: Channel, *interceptors: Interceptor) -> Channel: ... @@ -341,9 +341,9 @@ class ClientCallDetails: # response message of the RPC. Should the event terminate with non-OK # status, the returned Call-Future’s exception value will be an RpcError. # -class CallFuture(Call, Future[TResponse]): ... +class CallFuture(Call, Future[_TResponse]): ... -class UnaryUnaryClientInterceptor(typing.Generic[TRequest, TResponse]): +class UnaryUnaryClientInterceptor(typing.Generic[_TRequest, _TResponse]): def intercept_unary_unary( self, # FIXME: decode these cryptic runes to confirm the typing mystery of @@ -361,37 +361,37 @@ class UnaryUnaryClientInterceptor(typing.Generic[TRequest, TResponse]): # status, the returned Call-Future’s exception value will be an # RpcError. # - continuation: Callable[[ClientCallDetails, TRequest], CallFuture[TResponse]], + continuation: Callable[[ClientCallDetails, _TRequest], CallFuture[_TResponse]], client_call_details: ClientCallDetails, - request: TRequest, - ) -> CallFuture[TResponse]: ... + request: _TRequest, + ) -> CallFuture[_TResponse]: ... -class CallIterator(Call, typing.Generic[TResponse]): - def __iter__(self) -> Iterator[TResponse]: ... +class CallIterator(Call, typing.Generic[_TResponse]): + def __iter__(self) -> Iterator[_TResponse]: ... -class UnaryStreamClientInterceptor(typing.Generic[TRequest, TResponse]): +class UnaryStreamClientInterceptor(typing.Generic[_TRequest, _TResponse]): def intercept_unary_stream( self, - continuation: Callable[[ClientCallDetails, TRequest], CallIterator[TResponse]], + continuation: Callable[[ClientCallDetails, _TRequest], CallIterator[_TResponse]], client_call_details: ClientCallDetails, - request: TRequest, - ) -> CallIterator[TResponse]: ... + request: _TRequest, + ) -> CallIterator[_TResponse]: ... -class StreamUnaryClientInterceptor(typing.Generic[TRequest, TResponse]): +class StreamUnaryClientInterceptor(typing.Generic[_TRequest, _TResponse]): def intercept_stream_unary( self, - continuation: Callable[[ClientCallDetails, TRequest], CallFuture[TResponse]], + continuation: Callable[[ClientCallDetails, _TRequest], CallFuture[_TResponse]], client_call_details: ClientCallDetails, - request_iterator: Iterator[TRequest], - ) -> CallFuture[TResponse]: ... + request_iterator: Iterator[_TRequest], + ) -> CallFuture[_TResponse]: ... -class StreamStreamClientInterceptor(typing.Generic[TRequest, TResponse]): +class StreamStreamClientInterceptor(typing.Generic[_TRequest, _TResponse]): def intercept_stream_stream( self, - continuation: Callable[[ClientCallDetails, TRequest], CallIterator[TResponse]], + continuation: Callable[[ClientCallDetails, _TRequest], CallIterator[_TResponse]], client_call_details: ClientCallDetails, - request_iterator: Iterator[TRequest], - ) -> CallIterator[TResponse]: ... + request_iterator: Iterator[_TRequest], + ) -> CallIterator[_TResponse]: ... # Service-Side Context: @@ -419,7 +419,7 @@ class ServicerContext(RpcContext): # Service-Side Handler: -class RpcMethodHandler(typing.Generic[TRequest, TResponse]): +class RpcMethodHandler(typing.Generic[_TRequest, _TResponse]): request_streaming: bool response_streaming: bool @@ -429,59 +429,59 @@ class RpcMethodHandler(typing.Generic[TRequest, TResponse]): # XXX: not clear from docs whether this is optional or not response_serializer: ResponseSerializer | None - unary_unary: Callable[[TRequest, ServicerContext], TResponse] | None + unary_unary: Callable[[_TRequest, ServicerContext], _TResponse] | None - unary_stream: Callable[[TRequest, ServicerContext], Iterator[TResponse]] | None + unary_stream: Callable[[_TRequest, ServicerContext], Iterator[_TResponse]] | None - stream_unary: Callable[[Iterator[TRequest], ServicerContext], TResponse] | None + stream_unary: Callable[[Iterator[_TRequest], ServicerContext], _TResponse] | None - stream_stream: Callable[[Iterator[TRequest], ServicerContext], Iterator[TResponse]] | None + stream_stream: Callable[[Iterator[_TRequest], ServicerContext], Iterator[_TResponse]] | None class HandlerCallDetails: method: str invocation_metadata: Metadata -class GenericRpcHandler(typing.Generic[TRequest, TResponse]): - def service(self, handler_call_details: HandlerCallDetails) -> RpcMethodHandler[TRequest, TResponse] | None: ... +class GenericRpcHandler(typing.Generic[_TRequest, _TResponse]): + def service(self, handler_call_details: HandlerCallDetails) -> RpcMethodHandler[_TRequest, _TResponse] | None: ... -class ServiceRpcHandler(GenericRpcHandler[TRequest, TResponse]): +class ServiceRpcHandler(GenericRpcHandler[_TRequest, _TResponse]): def service_name(self) -> str: ... # Service-Side Interceptor: -class ServerInterceptor(typing.Generic[TRequest, TResponse]): +class ServerInterceptor(typing.Generic[_TRequest, _TResponse]): def intercept_service( self, - continuation: Callable[[HandlerCallDetails], RpcMethodHandler[TRequest, TResponse] | None], + continuation: Callable[[HandlerCallDetails], RpcMethodHandler[_TRequest, _TResponse] | None], handler_call_details: HandlerCallDetails, - ) -> RpcMethodHandler[TRequest, TResponse] | None: ... + ) -> RpcMethodHandler[_TRequest, _TResponse] | None: ... # Multi-Callable Interfaces: -class UnaryUnaryMultiCallable(typing.Generic[TRequest, TResponse]): +class UnaryUnaryMultiCallable(typing.Generic[_TRequest, _TResponse]): def __call__( self, - request: TRequest, + request: _TRequest, timeout: float | None = ..., metadata: Metadata | None = ..., credentials: CallCredentials | None = ..., # FIXME: optional bool seems weird, but that's what the docs suggest wait_for_ready: bool | None = ..., compression: Compression | None = ..., - ) -> TResponse: ... + ) -> _TResponse: ... def future( self, - request: TRequest, + request: _TRequest, timeout: float | None = ..., metadata: Metadata | None = ..., credentials: CallCredentials | None = ..., # FIXME: optional bool seems weird, but that's what the docs suggest wait_for_ready: bool | None = ..., compression: Compression | None = ..., - ) -> CallFuture[TResponse]: ... + ) -> CallFuture[_TResponse]: ... def with_call( self, - request: TRequest, + request: _TRequest, timeout: float | None = ..., metadata: Metadata | None = ..., credentials: CallCredentials | None = ..., @@ -490,44 +490,44 @@ class UnaryUnaryMultiCallable(typing.Generic[TRequest, TResponse]): compression: Compression | None = ..., # FIXME: Return value is documented as "The response value for the RPC and a Call value for the RPC"; # this is slightly unclear so this return type is a best-effort guess. - ) -> tuple[TResponse, Call]: ... + ) -> tuple[_TResponse, Call]: ... -class UnaryStreamMultiCallable(typing.Generic[TRequest, TResponse]): +class UnaryStreamMultiCallable(typing.Generic[_TRequest, _TResponse]): def __call__( self, - request: TRequest, + request: _TRequest, timeout: float | None = ..., metadata: Metadata | None = ..., credentials: CallCredentials | None = ..., # FIXME: optional bool seems weird, but that's what the docs suggest wait_for_ready: bool | None = ..., compression: Compression | None = ..., - ) -> CallIterator[TResponse]: ... + ) -> CallIterator[_TResponse]: ... -class StreamUnaryMultiCallable(typing.Generic[TRequest, TResponse]): +class StreamUnaryMultiCallable(typing.Generic[_TRequest, _TResponse]): def __call__( self, - request_iterator: Iterator[TRequest], + request_iterator: Iterator[_TRequest], timeout: float | None = ..., metadata: Metadata | None = ..., credentials: CallCredentials | None = ..., # FIXME: optional bool seems weird, but that's what the docs suggest wait_for_ready: bool | None = ..., compression: Compression | None = ..., - ) -> TResponse: ... + ) -> _TResponse: ... def future( self, - request_iterator: Iterator[TRequest], + request_iterator: Iterator[_TRequest], timeout: float | None = ..., metadata: Metadata | None = ..., credentials: CallCredentials | None = ..., # FIXME: optional bool seems weird, but that's what the docs suggest wait_for_ready: bool | None = ..., compression: Compression | None = ..., - ) -> CallFuture[TResponse]: ... + ) -> CallFuture[_TResponse]: ... def with_call( self, - request_iterator: Iterator[TRequest], + request_iterator: Iterator[_TRequest], timeout: float | None = ..., metadata: Metadata | None = ..., credentials: CallCredentials | None = ..., @@ -536,19 +536,19 @@ class StreamUnaryMultiCallable(typing.Generic[TRequest, TResponse]): compression: Compression | None = ..., # FIXME: Return value is documented as "The response value for the RPC and a Call value for the RPC"; # this is slightly unclear so this return type is a best-effort guess. - ) -> tuple[TResponse, Call]: ... + ) -> tuple[_TResponse, Call]: ... -class StreamStreamMultiCallable(typing.Generic[TRequest, TResponse]): +class StreamStreamMultiCallable(typing.Generic[_TRequest, _TResponse]): def __call__( self, - request_iterator: Iterator[TRequest], + request_iterator: Iterator[_TRequest], timeout: float | None = ..., metadata: Metadata | None = ..., credentials: CallCredentials | None = ..., # FIXME: optional bool seems weird, but that's what the docs suggest wait_for_ready: bool | None = ..., compression: Compression | None = ..., - ) -> CallIterator[TResponse]: ... + ) -> CallIterator[_TResponse]: ... # Runtime Protobuf Parsing: diff --git a/stubs/grpc/grpc/aio/__init__.pyi b/stubs/grpc/grpc/aio/__init__.pyi index 4b59b352e0e2..3789ba89d433 100644 --- a/stubs/grpc/grpc/aio/__init__.pyi +++ b/stubs/grpc/grpc/aio/__init__.pyi @@ -20,6 +20,9 @@ from grpc import ( _PartialStubMustCastOrIgnore, ) +_TRequest = typing.TypeVar("_TRequest") +_TResponse = typing.TypeVar("_TResponse") + # Exceptions: class BaseError(Exception): ... @@ -138,38 +141,35 @@ class Call(RpcContext): async def details(self) -> str: ... async def wait_for_connection(self) -> None: ... -class UnaryUnaryCall(Call, typing.Generic[TRequest, TResponse]): - def __await__(self) -> Generator[None, None, TResponse]: ... +class UnaryUnaryCall(Call, typing.Generic[_TRequest, _TResponse]): + def __await__(self) -> Generator[None, None, _TResponse]: ... -class UnaryStreamCall(Call, typing.Generic[TRequest, TResponse]): - def __aiter__(self) -> AsyncIterator[TResponse]: ... - async def read(self) -> EOFType | TResponse: ... +class UnaryStreamCall(Call, typing.Generic[_TRequest, _TResponse]): + def __aiter__(self) -> AsyncIterator[_TResponse]: ... + async def read(self) -> EOFType | _TResponse: ... -class StreamUnaryCall(Call, typing.Generic[TRequest, TResponse]): - async def write(self, request: TRequest) -> None: ... +class StreamUnaryCall(Call, typing.Generic[_TRequest, _TResponse]): + async def write(self, request: _TRequest) -> None: ... async def done_writing(self) -> None: ... - def __await__(self) -> Generator[None, None, TResponse]: ... + def __await__(self) -> Generator[None, None, _TResponse]: ... -class StreamStreamCall(Call, typing.Generic[TRequest, TResponse]): - def __aiter__(self) -> AsyncIterator[TResponse]: ... - async def read(self) -> EOFType | TResponse: ... - async def write(self, request: TRequest) -> None: ... +class StreamStreamCall(Call, typing.Generic[_TRequest, _TResponse]): + def __aiter__(self) -> AsyncIterator[_TResponse]: ... + async def read(self) -> EOFType | _TResponse: ... + async def write(self, request: _TRequest) -> None: ... async def done_writing(self) -> None: ... -TRequest = typing.TypeVar("TRequest") -TResponse = typing.TypeVar("TResponse") - # Service-Side Context: -class DoneCallback(typing.Generic[TRequest, TResponse]): - def __call__(self, ctx: ServicerContext[TRequest, TResponse]) -> None: ... +class DoneCallback(typing.Generic[_TRequest, _TResponse]): + def __call__(self, ctx: ServicerContext[_TRequest, _TResponse]) -> None: ... -class ServicerContext(typing.Generic[TRequest, TResponse]): +class ServicerContext(typing.Generic[_TRequest, _TResponse]): async def abort(self, code: StatusCode, details: str = ..., trailing_metadata: MetadataType = ...) -> typing.NoReturn: ... - async def read(self) -> TRequest: ... - async def write(self, message: TResponse) -> None: ... + async def read(self) -> _TRequest: ... + async def write(self, message: _TResponse) -> None: ... async def send_initial_metadata(self, initial_metadata: MetadataType) -> None: ... - def add_done_callback(self, callback: DoneCallback[TRequest, TResponse]) -> None: ... + def add_done_callback(self, callback: DoneCallback[_TRequest, _TResponse]) -> None: ... def set_trailing_metadata(self, trailing_metadata: MetadataType) -> None: ... def invocation_metadata(self) -> Metadata | None: ... def set_code(self, code: StatusCode) -> None: ... @@ -210,13 +210,13 @@ class ClientCallDetails: # As at 1.53.0, this is not supported in aio: # compression: Compression | None -class InterceptedCall(typing.Generic[TRequest, TResponse]): +class InterceptedCall(typing.Generic[_TRequest, _TResponse]): def __init__(self, interceptors_task: asyncio.Task) -> None: ... def __del__(self): ... def cancel(self) -> bool: ... def cancelled(self) -> bool: ... def done(self) -> bool: ... - def add_done_callback(self, callback: DoneCallback[TRequest, TResponse]) -> None: ... + def add_done_callback(self, callback: DoneCallback[_TRequest, _TResponse]) -> None: ... def time_remaining(self) -> float | None: ... async def initial_metadata(self) -> Metadata | None: ... async def trailing_metadata(self) -> Metadata | None: ... @@ -225,12 +225,12 @@ class InterceptedCall(typing.Generic[TRequest, TResponse]): async def debug_error_string(self) -> str | None: ... async def wait_for_connection(self) -> None: ... -class InterceptedUnaryUnaryCall(InterceptedCall[TRequest, TResponse]): +class InterceptedUnaryUnaryCall(InterceptedCall[_TRequest, _TResponse]): def __await__(self): ... def __init__( self, - interceptors: Sequence[UnaryUnaryClientInterceptor[TRequest, TResponse]], - request: TRequest, + interceptors: Sequence[UnaryUnaryClientInterceptor[_TRequest, _TResponse]], + request: _TRequest, timeout: float | None, metadata: Metadata, credentials: CallCredentials | None, @@ -245,109 +245,109 @@ class InterceptedUnaryUnaryCall(InterceptedCall[TRequest, TResponse]): # pylint: disable=too-many-arguments async def _invoke( self, - interceptors: Sequence[UnaryUnaryClientInterceptor[TRequest, TResponse]], + interceptors: Sequence[UnaryUnaryClientInterceptor[_TRequest, _TResponse]], method: bytes, timeout: float | None, metadata: Metadata | None, credentials: CallCredentials | None, wait_for_ready: bool | None, - request: TRequest, + request: _TRequest, request_serializer: RequestSerializer, response_deserializer: ResponseDeserializer, - ) -> UnaryUnaryCall[TRequest, TResponse]: ... + ) -> UnaryUnaryCall[_TRequest, _TResponse]: ... def time_remaining(self) -> float | None: ... -class UnaryUnaryClientInterceptor(typing.Generic[TRequest, TResponse]): +class UnaryUnaryClientInterceptor(typing.Generic[_TRequest, _TResponse]): async def intercept_unary_unary( self, # XXX: See equivalent function in grpc types for notes about continuation: - continuation: Callable[[ClientCallDetails, TRequest], UnaryUnaryCall[TRequest, TResponse]], + continuation: Callable[[ClientCallDetails, _TRequest], UnaryUnaryCall[_TRequest, _TResponse]], client_call_details: ClientCallDetails, - request: TRequest, - ) -> TResponse: ... + request: _TRequest, + ) -> _TResponse: ... -class UnaryStreamClientInterceptor(typing.Generic[TRequest, TResponse]): +class UnaryStreamClientInterceptor(typing.Generic[_TRequest, _TResponse]): async def intercept_unary_stream( self, - continuation: Callable[[ClientCallDetails, TRequest], UnaryStreamCall[TRequest, TResponse]], + continuation: Callable[[ClientCallDetails, _TRequest], UnaryStreamCall[_TRequest, _TResponse]], client_call_details: ClientCallDetails, - request: TRequest, - ) -> AsyncIterable[TResponse] | UnaryStreamCall[TRequest, TResponse]: ... + request: _TRequest, + ) -> AsyncIterable[_TResponse] | UnaryStreamCall[_TRequest, _TResponse]: ... -class StreamUnaryClientInterceptor(typing.Generic[TRequest, TResponse]): +class StreamUnaryClientInterceptor(typing.Generic[_TRequest, _TResponse]): async def intercept_stream_unary( self, - continuation: Callable[[ClientCallDetails, TRequest], StreamUnaryCall[TRequest, TResponse]], + continuation: Callable[[ClientCallDetails, _TRequest], StreamUnaryCall[_TRequest, _TResponse]], client_call_details: ClientCallDetails, - request_iterator: AsyncIterable[TRequest] | Iterable[TRequest], - ) -> AsyncIterable[TResponse] | UnaryStreamCall[TRequest, TResponse]: ... + request_iterator: AsyncIterable[_TRequest] | Iterable[_TRequest], + ) -> AsyncIterable[_TResponse] | UnaryStreamCall[_TRequest, _TResponse]: ... -class StreamStreamClientInterceptor(typing.Generic[TRequest, TResponse]): +class StreamStreamClientInterceptor(typing.Generic[_TRequest, _TResponse]): async def intercept_stream_stream( self, - continuation: Callable[[ClientCallDetails, TRequest], StreamStreamCall[TRequest, TResponse]], + continuation: Callable[[ClientCallDetails, _TRequest], StreamStreamCall[_TRequest, _TResponse]], client_call_details: ClientCallDetails, - request_iterator: AsyncIterable[TRequest] | Iterable[TRequest], - ) -> AsyncIterable[TResponse] | StreamStreamCall[TRequest, TResponse]: ... + request_iterator: AsyncIterable[_TRequest] | Iterable[_TRequest], + ) -> AsyncIterable[_TResponse] | StreamStreamCall[_TRequest, _TResponse]: ... # Server-Side Interceptor: -class ServerInterceptor(typing.Generic[TRequest, TResponse]): +class ServerInterceptor(typing.Generic[_TRequest, _TResponse]): async def intercept_service( self, - continuation: Callable[[HandlerCallDetails], Awaitable[RpcMethodHandler[TRequest, TResponse]]], + continuation: Callable[[HandlerCallDetails], Awaitable[RpcMethodHandler[_TRequest, _TResponse]]], handler_call_details: HandlerCallDetails, - ) -> RpcMethodHandler[TRequest, TResponse]: ... + ) -> RpcMethodHandler[_TRequest, _TResponse]: ... # Multi-Callable Interfaces: -class UnaryUnaryMultiCallable(typing.Generic[TRequest, TResponse]): +class UnaryUnaryMultiCallable(typing.Generic[_TRequest, _TResponse]): def __call__( self, - request: TRequest, + request: _TRequest, timeout: float | None = ..., metadata: MetadataType | None = ..., credentials: CallCredentials | None = ..., # FIXME: optional bool seems weird, but that's what the docs suggest wait_for_ready: bool | None = ..., compression: Compression | None = ..., - ) -> UnaryUnaryCall[TRequest, TResponse]: ... + ) -> UnaryUnaryCall[_TRequest, _TResponse]: ... -class UnaryStreamMultiCallable(typing.Generic[TRequest, TResponse]): +class UnaryStreamMultiCallable(typing.Generic[_TRequest, _TResponse]): def __call__( self, - request: TRequest, + request: _TRequest, timeout: float | None = ..., metadata: MetadataType | None = ..., credentials: CallCredentials | None = ..., # FIXME: optional bool seems weird, but that's what the docs suggest wait_for_ready: bool | None = ..., compression: Compression | None = ..., - ) -> UnaryStreamCall[TRequest, TResponse]: ... + ) -> UnaryStreamCall[_TRequest, _TResponse]: ... -class StreamUnaryMultiCallable(typing.Generic[TRequest, TResponse]): +class StreamUnaryMultiCallable(typing.Generic[_TRequest, _TResponse]): def __call__( self, - request_iterator: AsyncIterator[TRequest] | Iterator[TRequest] | None, + request_iterator: AsyncIterator[_TRequest] | Iterator[_TRequest] | None, timeout: float | None = ..., metadata: MetadataType | None = ..., credentials: CallCredentials | None = ..., # FIXME: optional bool seems weird, but that's what the docs suggest wait_for_ready: bool | None = ..., compression: Compression | None = ..., - ) -> StreamUnaryCall[TRequest, TResponse]: ... + ) -> StreamUnaryCall[_TRequest, _TResponse]: ... -class StreamStreamMultiCallable(typing.Generic[TRequest, TResponse]): +class StreamStreamMultiCallable(typing.Generic[_TRequest, _TResponse]): def __call__( self, - request_iterator: AsyncIterator[TRequest] | Iterator[TRequest] | None, + request_iterator: AsyncIterator[_TRequest] | Iterator[_TRequest] | None, timeout: float | None = ..., metadata: MetadataType | None = ..., credentials: CallCredentials | None = ..., # FIXME: optional bool seems weird, but that's what the docs suggest wait_for_ready: bool | None = ..., compression: Compression | None = ..., - ) -> StreamStreamCall[TRequest, TResponse]: ... + ) -> StreamStreamCall[_TRequest, _TResponse]: ... # Metadata: From 18b3d7dc487b402e6c605d99da03e89c1ba3e6f3 Mon Sep 17 00:00:00 2001 From: Blake Williams Date: Wed, 27 Dec 2023 22:31:46 +1100 Subject: [PATCH 11/18] Silence remaining typing failures --- stubs/grpc/@tests/test_cases/check_aio.py | 12 ++++++ stubs/grpc/@tests/test_cases/check_grpc.py | 4 ++ stubs/grpc/grpc/__init__.pyi | 43 ++++++++++++---------- stubs/grpc/grpc/aio/__init__.pyi | 19 +++++----- 4 files changed, 49 insertions(+), 29 deletions(-) diff --git a/stubs/grpc/@tests/test_cases/check_aio.py b/stubs/grpc/@tests/test_cases/check_aio.py index 5963cb757572..96bc89309b15 100644 --- a/stubs/grpc/@tests/test_cases/check_aio.py +++ b/stubs/grpc/@tests/test_cases/check_aio.py @@ -14,3 +14,15 @@ server_interceptors = [typing.cast(grpc.aio.ServerInterceptor[typing.Any, typing.Any], "interceptor")] grpc.aio.server(interceptors=server_interceptors) + + +# Metadata +async def metadata() -> None: + metadata = await typing.cast(grpc.aio.Call, None).initial_metadata() + assert_type(metadata["foo"], grpc.aio.MetadataValue) + for k in metadata: + assert_type(k, str) + + for k, v in metadata.items(): + assert_type(k, str) + assert_type(v, grpc.aio.MetadataValue) diff --git a/stubs/grpc/@tests/test_cases/check_grpc.py b/stubs/grpc/@tests/test_cases/check_grpc.py index c4c70b92f340..beeaaac6d831 100644 --- a/stubs/grpc/@tests/test_cases/check_grpc.py +++ b/stubs/grpc/@tests/test_cases/check_grpc.py @@ -29,6 +29,10 @@ ) assert_type(grpc.xds_server_credentials(grpc.insecure_server_credentials()), grpc.ServerCredentials) +# Channel ready future +channel = grpc.insecure_channel("target", ()) +assert_type(grpc.channel_ready_future(channel).result(), None) + # Channel options supports list: assert_type(grpc.insecure_channel("target", []), grpc.Channel) assert_type(grpc.insecure_channel("target", [("a", "b")]), grpc.Channel) diff --git a/stubs/grpc/grpc/__init__.pyi b/stubs/grpc/grpc/__init__.pyi index 94b6797e0ffe..d4d0afa9e219 100644 --- a/stubs/grpc/grpc/__init__.pyi +++ b/stubs/grpc/grpc/__init__.pyi @@ -45,16 +45,16 @@ _TResponse = typing.TypeVar("_TResponse") # XXX: These are probably the SerializeToTring/FromString pb2 methods, but # this needs further investigation class RequestSerializer(typing.Protocol): - def __call__(self, *args: typing.Any, **kwargs: typing.Any): ... + def __call__(self, *args: typing.Any, **kwargs: typing.Any) -> typing.Any: ... class RequestDeserializer(typing.Protocol): - def __call__(self, *args: typing.Any, **kwargs: typing.Any): ... + def __call__(self, *args: typing.Any, **kwargs: typing.Any) -> typing.Any: ... class ResponseSerializer(typing.Protocol): - def __call__(self, *args: typing.Any, **kwargs: typing.Any): ... + def __call__(self, *args: typing.Any, **kwargs: typing.Any) -> typing.Any: ... class ResponseDeserializer(typing.Protocol): - def __call__(self, *args: typing.Any, **kwargs: typing.Any): ... + def __call__(self, *args: typing.Any, **kwargs: typing.Any) -> typing.Any: ... # Future Interfaces: @@ -89,7 +89,7 @@ Interceptor: TypeAlias = ( | StreamStreamClientInterceptor[_TRequest, _TResponse] ) -def intercept_channel(channel: Channel, *interceptors: Interceptor) -> Channel: ... +def intercept_channel(channel: Channel, *interceptors: Interceptor[_TRequest, _TResponse]) -> Channel: ... # Create Client Credentials: @@ -115,8 +115,8 @@ def composite_channel_credentials( def server( thread_pool: futures.ThreadPoolExecutor, - handlers: list[GenericRpcHandler] | None = ..., - interceptors: list[ServerInterceptor] | None = ..., + handlers: list[GenericRpcHandler[typing.Any, typing.Any]] | None = ..., + interceptors: list[ServerInterceptor[typing.Any, typing.Any]] | None = ..., options: _Options | None = ..., maximum_concurrent_rpcs: int | None = ..., compression: Compression | None = ..., @@ -154,33 +154,36 @@ def xds_server_credentials(fallback_credentials: ServerCredentials) -> ServerCre # def FloobDoob(self, request, context): # return response # -Behaviour: TypeAlias = Callable +class Behaviour(typing.Protocol): + def __call__(self, *args: typing.Any, **kwargs: typing.Any) -> typing.Any: ... def unary_unary_rpc_method_handler( behavior: Behaviour, request_deserializer: RequestDeserializer | None = ..., response_serializer: ResponseSerializer | None = ..., -) -> RpcMethodHandler: ... +) -> RpcMethodHandler[typing.Any, typing.Any]: ... def unary_stream_rpc_method_handler( behavior: Behaviour, request_deserializer: RequestDeserializer | None = ..., response_serializer: ResponseSerializer | None = ..., -) -> RpcMethodHandler: ... +) -> RpcMethodHandler[typing.Any, typing.Any]: ... def stream_unary_rpc_method_handler( behavior: Behaviour, request_deserializer: RequestDeserializer | None = ..., response_serializer: ResponseSerializer | None = ..., -) -> RpcMethodHandler: ... +) -> RpcMethodHandler[typing.Any, typing.Any]: ... def stream_stream_rpc_method_handler( behavior: Behaviour, request_deserializer: RequestDeserializer | None = ..., response_serializer: ResponseSerializer | None = ..., -) -> RpcMethodHandler: ... -def method_handlers_generic_handler(service: str, method_handlers: dict[str, RpcMethodHandler]) -> GenericRpcHandler: ... +) -> RpcMethodHandler[typing.Any, typing.Any]: ... +def method_handlers_generic_handler( + service: str, method_handlers: dict[str, RpcMethodHandler[typing.Any, typing.Any]] +) -> GenericRpcHandler[typing.Any, typing.Any]: ... # Channel Ready Future: -def channel_ready_future(channel: Channel) -> Future: ... +def channel_ready_future(channel: Channel) -> Future[None]: ... # Channel Connectivity: @@ -227,17 +230,17 @@ class Channel: def close(self) -> None: ... def stream_stream( self, method: str, request_serializer: RequestSerializer | None, response_deserializer: ResponseDeserializer | None - ) -> StreamStreamMultiCallable: ... + ) -> StreamStreamMultiCallable[typing.Any, typing.Any]: ... def stream_unary( self, method: str, request_serializer: RequestSerializer | None, response_deserializer: ResponseDeserializer | None - ) -> StreamUnaryMultiCallable: ... + ) -> StreamUnaryMultiCallable[typing.Any, typing.Any]: ... def subscribe(self, callback: Callable[[ChannelConnectivity], None], try_to_connect: bool = ...) -> None: ... def unary_stream( self, method: str, request_serializer: RequestSerializer | None, response_deserializer: ResponseDeserializer | None - ) -> UnaryStreamMultiCallable: ... + ) -> UnaryStreamMultiCallable[typing.Any, typing.Any]: ... def unary_unary( self, method: str, request_serializer: RequestSerializer | None, response_deserializer: ResponseDeserializer | None - ) -> UnaryUnaryMultiCallable: ... + ) -> UnaryUnaryMultiCallable[typing.Any, typing.Any]: ... def unsubscribe(self, callback: Callable[[ChannelConnectivity], None]) -> None: ... def __enter__(self) -> Self: ... def __exit__( @@ -247,7 +250,7 @@ class Channel: # Server Object: class Server: - def add_generic_rpc_handlers(self, generic_rpc_handlers: Iterable[GenericRpcHandler]) -> None: ... + def add_generic_rpc_handlers(self, generic_rpc_handlers: Iterable[GenericRpcHandler[typing.Any, typing.Any]]) -> None: ... # Returns an integer port on which server will accept RPC requests. def add_insecure_port(self, address: str) -> int: ... @@ -309,7 +312,7 @@ class RpcError(Exception): class RpcContext: def add_callback(self, callback: Callable[[], None]) -> bool: ... - def cancel(self): ... + def cancel(self) -> bool: ... def is_active(self) -> bool: ... def time_remaining(self) -> float: ... diff --git a/stubs/grpc/grpc/aio/__init__.pyi b/stubs/grpc/grpc/aio/__init__.pyi index 3789ba89d433..f8e49b885bf9 100644 --- a/stubs/grpc/grpc/aio/__init__.pyi +++ b/stubs/grpc/grpc/aio/__init__.pyi @@ -1,5 +1,6 @@ import asyncio import typing +from _typeshed import Incomplete from collections.abc import AsyncIterable, AsyncIterator, Awaitable, Callable, Generator, Iterable, Iterator, Mapping, Sequence from concurrent import futures from types import TracebackType @@ -88,16 +89,16 @@ class Channel: async def wait_for_state_change(self, last_observed_state: ChannelConnectivity) -> None: ... def stream_stream( self, method: str, request_serializer: RequestSerializer | None, response_deserializer: ResponseDeserializer | None - ) -> StreamStreamMultiCallable: ... + ) -> StreamStreamMultiCallable[typing.Any, typing.Any]: ... def stream_unary( self, method: str, request_serializer: RequestSerializer | None, response_deserializer: ResponseDeserializer | None - ) -> StreamUnaryMultiCallable: ... + ) -> StreamUnaryMultiCallable[typing.Any, typing.Any]: ... def unary_stream( self, method: str, request_serializer: RequestSerializer | None, response_deserializer: ResponseDeserializer | None - ) -> UnaryStreamMultiCallable: ... + ) -> UnaryStreamMultiCallable[typing.Any, typing.Any]: ... def unary_unary( self, method: str, request_serializer: RequestSerializer | None, response_deserializer: ResponseDeserializer | None - ) -> UnaryUnaryMultiCallable: ... + ) -> UnaryUnaryMultiCallable[typing.Any, typing.Any]: ... async def __aenter__(self) -> Self: ... async def __aexit__( self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None @@ -211,8 +212,8 @@ class ClientCallDetails: # compression: Compression | None class InterceptedCall(typing.Generic[_TRequest, _TResponse]): - def __init__(self, interceptors_task: asyncio.Task) -> None: ... - def __del__(self): ... + def __init__(self, interceptors_task: asyncio.Task[typing.Any]) -> None: ... + def __del__(self) -> None: ... def cancel(self) -> bool: ... def cancelled(self) -> bool: ... def done(self) -> bool: ... @@ -226,7 +227,7 @@ class InterceptedCall(typing.Generic[_TRequest, _TResponse]): async def wait_for_connection(self) -> None: ... class InterceptedUnaryUnaryCall(InterceptedCall[_TRequest, _TResponse]): - def __await__(self): ... + def __await__(self) -> Incomplete: ... def __init__( self, interceptors: Sequence[UnaryUnaryClientInterceptor[_TRequest, _TResponse]], @@ -356,7 +357,7 @@ MetadataValue: TypeAlias = str | bytes MetadatumType: TypeAlias = tuple[MetadataKey, MetadataValue] MetadataType: TypeAlias = Metadata | Sequence[MetadatumType] -class Metadata(Mapping): +class Metadata(Mapping[MetadataKey, MetadataValue]): def __init__(self, *args: tuple[MetadataKey, MetadataValue]) -> None: ... @classmethod def from_tuple(cls, raw_metadata: tuple[MetadataKey, MetadataValue]) -> Metadata: ... @@ -366,7 +367,7 @@ class Metadata(Mapping): def __setitem__(self, key: MetadataKey, value: MetadataValue) -> None: ... def __delitem__(self, key: MetadataKey) -> None: ... def delete_all(self, key: MetadataKey) -> None: ... - def __iter__(self) -> Iterator[tuple[MetadataKey, MetadataValue]]: ... + def __iter__(self) -> Iterator[MetadataKey]: ... def get_all(self, key: MetadataKey) -> list[MetadataValue]: ... def set_all(self, key: MetadataKey, values: list[MetadataValue]) -> None: ... def __contains__(self, key: object) -> bool: ... From 15811e666365e8303e92f56c2ad155d72614981f Mon Sep 17 00:00:00 2001 From: Blake Williams Date: Wed, 27 Dec 2023 22:44:16 +1100 Subject: [PATCH 12/18] Paper over cracks in supplemental packages --- .../grpc_channelz/v1/channelz_pb2.pyi | 16 ++++++++++++++++ .../grpc_channelz/v1/channelz_pb2_grpc.pyi | 3 +++ stubs/grpc_health/grpc_health/__init__.pyi | 4 ++-- stubs/grpc_health/grpc_health/v1/__init__.pyi | 4 ++-- stubs/grpc_health/grpc_health/v1/health.pyi | 11 +++++++++-- stubs/grpc_health/grpc_health/v1/health_pb2.pyi | 3 +++ .../grpc_health/v1/health_pb2_grpc.pyi | 6 ++++++ .../grpc_reflection/v1alpha/_base.pyi | 1 + .../grpc_reflection/v1alpha/reflection.pyi | 6 +++--- 9 files changed, 45 insertions(+), 9 deletions(-) create mode 100644 stubs/grpc_channelz/grpc_channelz/v1/channelz_pb2.pyi create mode 100644 stubs/grpc_channelz/grpc_channelz/v1/channelz_pb2_grpc.pyi create mode 100644 stubs/grpc_health/grpc_health/v1/health_pb2.pyi create mode 100644 stubs/grpc_health/grpc_health/v1/health_pb2_grpc.pyi diff --git a/stubs/grpc_channelz/grpc_channelz/v1/channelz_pb2.pyi b/stubs/grpc_channelz/grpc_channelz/v1/channelz_pb2.pyi new file mode 100644 index 000000000000..fdc2ff0ee872 --- /dev/null +++ b/stubs/grpc_channelz/grpc_channelz/v1/channelz_pb2.pyi @@ -0,0 +1,16 @@ +from _typeshed import Incomplete + +GetTopChannelsRequest = Incomplete +GetTopChannelsResponse = Incomplete +GetServersRequest = Incomplete +GetServersResponse = Incomplete +GetServerRequest = Incomplete +GetServerResponse = Incomplete +GetServerSocketsRequest = Incomplete +GetServerSocketsResponse = Incomplete +GetChannelRequest = Incomplete +GetChannelResponse = Incomplete +GetSubchannelRequest = Incomplete +GetSubchannelResponse = Incomplete +GetSocketRequest = Incomplete +GetSocketResponse = Incomplete diff --git a/stubs/grpc_channelz/grpc_channelz/v1/channelz_pb2_grpc.pyi b/stubs/grpc_channelz/grpc_channelz/v1/channelz_pb2_grpc.pyi new file mode 100644 index 000000000000..0b9716abcf75 --- /dev/null +++ b/stubs/grpc_channelz/grpc_channelz/v1/channelz_pb2_grpc.pyi @@ -0,0 +1,3 @@ +from _typeshed import Incomplete + +ChannelzServicer = Incomplete diff --git a/stubs/grpc_health/grpc_health/__init__.pyi b/stubs/grpc_health/grpc_health/__init__.pyi index e4579106bab4..0f6820f054ea 100644 --- a/stubs/grpc_health/grpc_health/__init__.pyi +++ b/stubs/grpc_health/grpc_health/__init__.pyi @@ -1,3 +1,3 @@ -import typing +from _typeshed import Incomplete -def __getattr__(name) -> typing.Any: ... +def __getattr__(name: str) -> Incomplete: ... diff --git a/stubs/grpc_health/grpc_health/v1/__init__.pyi b/stubs/grpc_health/grpc_health/v1/__init__.pyi index e4579106bab4..0f6820f054ea 100644 --- a/stubs/grpc_health/grpc_health/v1/__init__.pyi +++ b/stubs/grpc_health/grpc_health/v1/__init__.pyi @@ -1,3 +1,3 @@ -import typing +from _typeshed import Incomplete -def __getattr__(name) -> typing.Any: ... +def __getattr__(name: str) -> Incomplete: ... diff --git a/stubs/grpc_health/grpc_health/v1/health.pyi b/stubs/grpc_health/grpc_health/v1/health.pyi index 747999e65044..43e740f34618 100644 --- a/stubs/grpc_health/grpc_health/v1/health.pyi +++ b/stubs/grpc_health/grpc_health/v1/health.pyi @@ -1,5 +1,5 @@ +import typing from concurrent import futures -from typing import Callable from grpc import ServicerContext from grpc_health.v1 import health_pb2 as _health_pb2, health_pb2_grpc as _health_pb2_grpc @@ -15,13 +15,20 @@ class _Watcher: def add(self, response: _health_pb2.HealthCheckResponse) -> None: ... def close(self) -> None: ... +# FIXME: This needs further investigation +class SendResponseCallback(typing.Protocol): + def __call__(self, *args: typing.Any, **kwargs: typing.Any) -> typing.Any: ... + class HealthServicer(_health_pb2_grpc.HealthServicer): def __init__( self, experimental_non_blocking: bool = ..., experimental_thread_pool: futures.ThreadPoolExecutor | None = ... ) -> None: ... def Check(self, request: _health_pb2.HealthCheckRequest, context: ServicerContext) -> _health_pb2.HealthCheckResponse: ... def Watch( - self, request: _health_pb2.HealthCheckRequest, context: ServicerContext, send_response_callback: Callable | None = ... + self, + request: _health_pb2.HealthCheckRequest, + context: ServicerContext, + send_response_callback: SendResponseCallback | None = ..., ) -> _health_pb2.HealthCheckResponse: ... def set(self, service: str, status: _health_pb2.HealthCheckResponse.ServingStatus) -> None: ... def enter_graceful_shutdown(self) -> None: ... diff --git a/stubs/grpc_health/grpc_health/v1/health_pb2.pyi b/stubs/grpc_health/grpc_health/v1/health_pb2.pyi new file mode 100644 index 000000000000..0f6820f054ea --- /dev/null +++ b/stubs/grpc_health/grpc_health/v1/health_pb2.pyi @@ -0,0 +1,3 @@ +from _typeshed import Incomplete + +def __getattr__(name: str) -> Incomplete: ... diff --git a/stubs/grpc_health/grpc_health/v1/health_pb2_grpc.pyi b/stubs/grpc_health/grpc_health/v1/health_pb2_grpc.pyi new file mode 100644 index 000000000000..8a29ae2fab5b --- /dev/null +++ b/stubs/grpc_health/grpc_health/v1/health_pb2_grpc.pyi @@ -0,0 +1,6 @@ +from _typeshed import Incomplete + +def __getattr__(name: str) -> Incomplete: ... + +# FIXME: Incomplete +class HealthServicer: ... diff --git a/stubs/grpc_reflection/grpc_reflection/v1alpha/_base.pyi b/stubs/grpc_reflection/grpc_reflection/v1alpha/_base.pyi index ab31ad3f712e..00704b5062ef 100644 --- a/stubs/grpc_reflection/grpc_reflection/v1alpha/_base.pyi +++ b/stubs/grpc_reflection/grpc_reflection/v1alpha/_base.pyi @@ -2,4 +2,5 @@ from _typeshed import Incomplete def __getattr__(name: str) -> Incomplete: ... +# FIXME: Incomplete class BaseReflectionServicer: ... diff --git a/stubs/grpc_reflection/grpc_reflection/v1alpha/reflection.pyi b/stubs/grpc_reflection/grpc_reflection/v1alpha/reflection.pyi index 49d2a7e6b410..146318de8ae4 100644 --- a/stubs/grpc_reflection/grpc_reflection/v1alpha/reflection.pyi +++ b/stubs/grpc_reflection/grpc_reflection/v1alpha/reflection.pyi @@ -1,6 +1,6 @@ -import typing import typing_extensions from _typeshed import Incomplete +from collections.abc import Iterable import grpc from google.protobuf import descriptor_pool @@ -15,9 +15,9 @@ AnyServicerContext: typing_extensions.TypeAlias = grpc.ServicerContext | aio.Ser class ReflectionServicer(BaseReflectionServicer): def ServerReflectionInfo( - self, request_iterator: typing.Iterable[_reflection_pb2.ServerReflectionRequest], context: AnyServicerContext + self, request_iterator: Iterable[_reflection_pb2.ServerReflectionRequest], context: AnyServicerContext ) -> None: ... def enable_server_reflection( - service_names: typing.Iterable[str], server: AnyServer, pool: descriptor_pool.DescriptorPool | None = ... + service_names: Iterable[str], server: AnyServer, pool: descriptor_pool.DescriptorPool | None = ... ) -> None: ... From 59fb63071804457dc1cb7119c8e3420dc6111660 Mon Sep 17 00:00:00 2001 From: Blake Williams Date: Wed, 27 Dec 2023 23:25:45 +1100 Subject: [PATCH 13/18] Add ABC and ABCMeta to classes that declare it in the grpcio source --- .../grpc/@tests/test_cases/check_register.py | 14 ++++++ stubs/grpc/grpc/__init__.pyi | 49 ++++++++++--------- 2 files changed, 39 insertions(+), 24 deletions(-) create mode 100644 stubs/grpc/@tests/test_cases/check_register.py diff --git a/stubs/grpc/@tests/test_cases/check_register.py b/stubs/grpc/@tests/test_cases/check_register.py new file mode 100644 index 000000000000..4bf4eda7f02a --- /dev/null +++ b/stubs/grpc/@tests/test_cases/check_register.py @@ -0,0 +1,14 @@ +from __future__ import annotations + +import typing + +import grpc + + +@grpc.Call.register +class CallProxy: + def __init__(self, target: grpc.Call) -> None: + self._target = target + + def __getattr__(self, name: str) -> typing.Any: + return getattr(self._target, name) diff --git a/stubs/grpc/grpc/__init__.pyi b/stubs/grpc/grpc/__init__.pyi index d4d0afa9e219..742c843494ad 100644 --- a/stubs/grpc/grpc/__init__.pyi +++ b/stubs/grpc/grpc/__init__.pyi @@ -1,3 +1,4 @@ +import abc import enum import threading import typing @@ -63,7 +64,7 @@ class FutureCancelledError(Exception): ... _TFutureValue = typing.TypeVar("_TFutureValue") -class Future(typing.Generic[_TFutureValue]): +class Future(abc.ABC, typing.Generic[_TFutureValue]): def add_done_callback(self, fn: Callable[[Future[_TFutureValue]], None]) -> None: ... def cancel(self) -> bool: ... def cancelled(self) -> bool: ... @@ -196,7 +197,7 @@ class ChannelConnectivity(enum.Enum): # gRPC Status Code: -class Status: +class Status(abc.ABC): code: StatusCode # XXX: misnamed property, does not align with status.proto, where it is called 'message': @@ -226,7 +227,7 @@ class StatusCode(enum.Enum): # Channel Object: -class Channel: +class Channel(abc.ABC): def close(self) -> None: ... def stream_stream( self, method: str, request_serializer: RequestSerializer | None, response_deserializer: ResponseDeserializer | None @@ -249,7 +250,7 @@ class Channel: # Server Object: -class Server: +class Server(abc.ABC): def add_generic_rpc_handlers(self, generic_rpc_handlers: Iterable[GenericRpcHandler[typing.Any, typing.Any]]) -> None: ... # Returns an integer port on which server will accept RPC requests. @@ -274,14 +275,14 @@ class ChannelCredentials: ... # This class has no supported interface class CallCredentials: ... -class AuthMetadataContext: +class AuthMetadataContext(abc.ABC): service_url: str method_name: str -class AuthMetadataPluginCallback: +class AuthMetadataPluginCallback(abc.ABC): def __call__(self, metadata: Metadata, error: Exception | None) -> None: ... -class AuthMetadataPlugin: +class AuthMetadataPlugin(abc.ABC): def __call__(self, context: AuthMetadataContext, callback: AuthMetadataPluginCallback) -> None: ... # This class has no supported interface @@ -310,7 +311,7 @@ class RpcError(Exception): # Shared Context: -class RpcContext: +class RpcContext(abc.ABC): def add_callback(self, callback: Callable[[], None]) -> bool: ... def cancel(self) -> bool: ... def is_active(self) -> bool: ... @@ -318,7 +319,7 @@ class RpcContext: # Client-Side Context: -class Call(RpcContext): +class Call(RpcContext, metaclass=abc.ABCMeta): def code(self) -> StatusCode: ... # misnamed property, does not align with status.proto, where it is called 'message': @@ -328,7 +329,7 @@ class Call(RpcContext): # Client-Side Interceptor: -class ClientCallDetails: +class ClientCallDetails(abc.ABC): method: str timeout: float | None metadata: Metadata | None @@ -346,7 +347,7 @@ class ClientCallDetails: # class CallFuture(Call, Future[_TResponse]): ... -class UnaryUnaryClientInterceptor(typing.Generic[_TRequest, _TResponse]): +class UnaryUnaryClientInterceptor(abc.ABC, typing.Generic[_TRequest, _TResponse]): def intercept_unary_unary( self, # FIXME: decode these cryptic runes to confirm the typing mystery of @@ -372,7 +373,7 @@ class UnaryUnaryClientInterceptor(typing.Generic[_TRequest, _TResponse]): class CallIterator(Call, typing.Generic[_TResponse]): def __iter__(self) -> Iterator[_TResponse]: ... -class UnaryStreamClientInterceptor(typing.Generic[_TRequest, _TResponse]): +class UnaryStreamClientInterceptor(abc.ABC, typing.Generic[_TRequest, _TResponse]): def intercept_unary_stream( self, continuation: Callable[[ClientCallDetails, _TRequest], CallIterator[_TResponse]], @@ -380,7 +381,7 @@ class UnaryStreamClientInterceptor(typing.Generic[_TRequest, _TResponse]): request: _TRequest, ) -> CallIterator[_TResponse]: ... -class StreamUnaryClientInterceptor(typing.Generic[_TRequest, _TResponse]): +class StreamUnaryClientInterceptor(abc.ABC, typing.Generic[_TRequest, _TResponse]): def intercept_stream_unary( self, continuation: Callable[[ClientCallDetails, _TRequest], CallFuture[_TResponse]], @@ -388,7 +389,7 @@ class StreamUnaryClientInterceptor(typing.Generic[_TRequest, _TResponse]): request_iterator: Iterator[_TRequest], ) -> CallFuture[_TResponse]: ... -class StreamStreamClientInterceptor(typing.Generic[_TRequest, _TResponse]): +class StreamStreamClientInterceptor(abc.ABC, typing.Generic[_TRequest, _TResponse]): def intercept_stream_stream( self, continuation: Callable[[ClientCallDetails, _TRequest], CallIterator[_TResponse]], @@ -398,7 +399,7 @@ class StreamStreamClientInterceptor(typing.Generic[_TRequest, _TResponse]): # Service-Side Context: -class ServicerContext(RpcContext): +class ServicerContext(RpcContext, metaclass=abc.ABCMeta): # misnamed parameter 'details', does not align with status.proto, where it is called 'message': def abort(self, code: StatusCode, details: str) -> typing.NoReturn: ... def abort_with_status(self, status: Status) -> typing.NoReturn: ... @@ -422,7 +423,7 @@ class ServicerContext(RpcContext): # Service-Side Handler: -class RpcMethodHandler(typing.Generic[_TRequest, _TResponse]): +class RpcMethodHandler(abc.ABC, typing.Generic[_TRequest, _TResponse]): request_streaming: bool response_streaming: bool @@ -440,19 +441,19 @@ class RpcMethodHandler(typing.Generic[_TRequest, _TResponse]): stream_stream: Callable[[Iterator[_TRequest], ServicerContext], Iterator[_TResponse]] | None -class HandlerCallDetails: +class HandlerCallDetails(abc.ABC): method: str invocation_metadata: Metadata -class GenericRpcHandler(typing.Generic[_TRequest, _TResponse]): +class GenericRpcHandler(abc.ABC, typing.Generic[_TRequest, _TResponse]): def service(self, handler_call_details: HandlerCallDetails) -> RpcMethodHandler[_TRequest, _TResponse] | None: ... -class ServiceRpcHandler(GenericRpcHandler[_TRequest, _TResponse]): +class ServiceRpcHandler(GenericRpcHandler[_TRequest, _TResponse], metaclass=abc.ABCMeta): def service_name(self) -> str: ... # Service-Side Interceptor: -class ServerInterceptor(typing.Generic[_TRequest, _TResponse]): +class ServerInterceptor(abc.ABC, typing.Generic[_TRequest, _TResponse]): def intercept_service( self, continuation: Callable[[HandlerCallDetails], RpcMethodHandler[_TRequest, _TResponse] | None], @@ -461,7 +462,7 @@ class ServerInterceptor(typing.Generic[_TRequest, _TResponse]): # Multi-Callable Interfaces: -class UnaryUnaryMultiCallable(typing.Generic[_TRequest, _TResponse]): +class UnaryUnaryMultiCallable(abc.ABC, typing.Generic[_TRequest, _TResponse]): def __call__( self, request: _TRequest, @@ -495,7 +496,7 @@ class UnaryUnaryMultiCallable(typing.Generic[_TRequest, _TResponse]): # this is slightly unclear so this return type is a best-effort guess. ) -> tuple[_TResponse, Call]: ... -class UnaryStreamMultiCallable(typing.Generic[_TRequest, _TResponse]): +class UnaryStreamMultiCallable(abc.ABC, typing.Generic[_TRequest, _TResponse]): def __call__( self, request: _TRequest, @@ -507,7 +508,7 @@ class UnaryStreamMultiCallable(typing.Generic[_TRequest, _TResponse]): compression: Compression | None = ..., ) -> CallIterator[_TResponse]: ... -class StreamUnaryMultiCallable(typing.Generic[_TRequest, _TResponse]): +class StreamUnaryMultiCallable(abc.ABC, typing.Generic[_TRequest, _TResponse]): def __call__( self, request_iterator: Iterator[_TRequest], @@ -541,7 +542,7 @@ class StreamUnaryMultiCallable(typing.Generic[_TRequest, _TResponse]): # this is slightly unclear so this return type is a best-effort guess. ) -> tuple[_TResponse, Call]: ... -class StreamStreamMultiCallable(typing.Generic[_TRequest, _TResponse]): +class StreamStreamMultiCallable(abc.ABC, typing.Generic[_TRequest, _TResponse]): def __call__( self, request_iterator: Iterator[_TRequest], From 0ac8415074eb3e2c7bf1ec54b2cfff8783ce9b8a Mon Sep 17 00:00:00 2001 From: Blake Williams Date: Thu, 28 Dec 2023 13:30:05 +1100 Subject: [PATCH 14/18] Add check for alternate aio import --- stubs/grpc/@tests/test_cases/check_aio_via_grpc.py | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 stubs/grpc/@tests/test_cases/check_aio_via_grpc.py diff --git a/stubs/grpc/@tests/test_cases/check_aio_via_grpc.py b/stubs/grpc/@tests/test_cases/check_aio_via_grpc.py new file mode 100644 index 000000000000..a13d1551edf2 --- /dev/null +++ b/stubs/grpc/@tests/test_cases/check_aio_via_grpc.py @@ -0,0 +1,9 @@ +from __future__ import annotations + +from typing_extensions import assert_type + +# Both import methods work, see the comment in grpc/__init__.py. +from grpc import aio + +assert_type(aio.Channel(), aio.Channel) +assert_type(aio.Server(), aio.Server) From 82d02fb3257d1333271a0b2f7ad766c21c9f24cd Mon Sep 17 00:00:00 2001 From: Blake Williams Date: Thu, 28 Dec 2023 22:41:29 +1100 Subject: [PATCH 15/18] Move grpc stubs into grpcio folder --- stubs/grpc/METADATA.toml | 6 ------ stubs/grpc_channelz/METADATA.toml | 9 --------- stubs/grpc_health/METADATA.toml | 9 --------- stubs/grpc_status/METADATA.toml | 7 ------- stubs/{grpc => grpcio}/@tests/test_cases/check_aio.py | 0 .../@tests/test_cases/check_aio_multi_callable.py | 0 .../@tests/test_cases/check_aio_via_grpc.py | 0 stubs/{grpc => grpcio}/@tests/test_cases/check_grpc.py | 0 .../@tests/test_cases/check_handler_inheritance.py | 0 .../@tests/test_cases/check_multi_callable.py | 0 .../@tests/test_cases/check_reflection.py | 0 .../@tests/test_cases/check_reflection_aio.py | 0 .../{grpc => grpcio}/@tests/test_cases/check_register.py | 0 .../@tests/test_cases/check_server_interceptor.py | 0 .../@tests/test_cases/check_status.py | 0 stubs/{grpc_reflection => grpcio}/METADATA.toml | 1 - stubs/{grpc => grpcio}/grpc/__init__.pyi | 0 stubs/{grpc => grpcio}/grpc/aio/__init__.pyi | 0 .../{grpc_channelz => grpcio}/grpc_channelz/__init__.pyi | 0 .../grpc_channelz/v1/__init__.pyi | 0 .../grpc_channelz/v1/_servicer.pyi | 0 .../grpc_channelz/v1/channelz.pyi | 0 .../grpc_channelz/v1/channelz_pb2.pyi | 0 .../grpc_channelz/v1/channelz_pb2_grpc.pyi | 0 stubs/{grpc_health => grpcio}/grpc_health/__init__.pyi | 0 .../{grpc_health => grpcio}/grpc_health/v1/__init__.pyi | 0 stubs/{grpc_health => grpcio}/grpc_health/v1/health.pyi | 0 .../grpc_health/v1/health_pb2.pyi | 0 .../grpc_health/v1/health_pb2_grpc.pyi | 0 .../grpc_reflection/__init__.pyi | 0 .../grpc_reflection/v1alpha/__init__.pyi | 0 .../grpc_reflection/v1alpha/_base.pyi | 0 .../grpc_reflection/v1alpha/reflection.pyi | 0 .../grpc_reflection/v1alpha/reflection_pb2.pyi | 0 stubs/{grpc_status => grpcio}/grpc_status/__init__.pyi | 0 stubs/{grpc_status => grpcio}/grpc_status/rpc_status.pyi | 0 36 files changed, 32 deletions(-) delete mode 100644 stubs/grpc/METADATA.toml delete mode 100644 stubs/grpc_channelz/METADATA.toml delete mode 100644 stubs/grpc_health/METADATA.toml delete mode 100644 stubs/grpc_status/METADATA.toml rename stubs/{grpc => grpcio}/@tests/test_cases/check_aio.py (100%) rename stubs/{grpc => grpcio}/@tests/test_cases/check_aio_multi_callable.py (100%) rename stubs/{grpc => grpcio}/@tests/test_cases/check_aio_via_grpc.py (100%) rename stubs/{grpc => grpcio}/@tests/test_cases/check_grpc.py (100%) rename stubs/{grpc => grpcio}/@tests/test_cases/check_handler_inheritance.py (100%) rename stubs/{grpc => grpcio}/@tests/test_cases/check_multi_callable.py (100%) rename stubs/{grpc_reflection => grpcio}/@tests/test_cases/check_reflection.py (100%) rename stubs/{grpc_reflection => grpcio}/@tests/test_cases/check_reflection_aio.py (100%) rename stubs/{grpc => grpcio}/@tests/test_cases/check_register.py (100%) rename stubs/{grpc => grpcio}/@tests/test_cases/check_server_interceptor.py (100%) rename stubs/{grpc_status => grpcio}/@tests/test_cases/check_status.py (100%) rename stubs/{grpc_reflection => grpcio}/METADATA.toml (90%) rename stubs/{grpc => grpcio}/grpc/__init__.pyi (100%) rename stubs/{grpc => grpcio}/grpc/aio/__init__.pyi (100%) rename stubs/{grpc_channelz => grpcio}/grpc_channelz/__init__.pyi (100%) rename stubs/{grpc_channelz => grpcio}/grpc_channelz/v1/__init__.pyi (100%) rename stubs/{grpc_channelz => grpcio}/grpc_channelz/v1/_servicer.pyi (100%) rename stubs/{grpc_channelz => grpcio}/grpc_channelz/v1/channelz.pyi (100%) rename stubs/{grpc_channelz => grpcio}/grpc_channelz/v1/channelz_pb2.pyi (100%) rename stubs/{grpc_channelz => grpcio}/grpc_channelz/v1/channelz_pb2_grpc.pyi (100%) rename stubs/{grpc_health => grpcio}/grpc_health/__init__.pyi (100%) rename stubs/{grpc_health => grpcio}/grpc_health/v1/__init__.pyi (100%) rename stubs/{grpc_health => grpcio}/grpc_health/v1/health.pyi (100%) rename stubs/{grpc_health => grpcio}/grpc_health/v1/health_pb2.pyi (100%) rename stubs/{grpc_health => grpcio}/grpc_health/v1/health_pb2_grpc.pyi (100%) rename stubs/{grpc_reflection => grpcio}/grpc_reflection/__init__.pyi (100%) rename stubs/{grpc_reflection => grpcio}/grpc_reflection/v1alpha/__init__.pyi (100%) rename stubs/{grpc_reflection => grpcio}/grpc_reflection/v1alpha/_base.pyi (100%) rename stubs/{grpc_reflection => grpcio}/grpc_reflection/v1alpha/reflection.pyi (100%) rename stubs/{grpc_reflection => grpcio}/grpc_reflection/v1alpha/reflection_pb2.pyi (100%) rename stubs/{grpc_status => grpcio}/grpc_status/__init__.pyi (100%) rename stubs/{grpc_status => grpcio}/grpc_status/rpc_status.pyi (100%) diff --git a/stubs/grpc/METADATA.toml b/stubs/grpc/METADATA.toml deleted file mode 100644 index b81a42967303..000000000000 --- a/stubs/grpc/METADATA.toml +++ /dev/null @@ -1,6 +0,0 @@ -version = "1.*" -upstream_repository = "https://github.com/grpc/grpc" -partial_stub = true - -[tool.stubtest] -ignore_missing_stub = true diff --git a/stubs/grpc_channelz/METADATA.toml b/stubs/grpc_channelz/METADATA.toml deleted file mode 100644 index c7934b2b5446..000000000000 --- a/stubs/grpc_channelz/METADATA.toml +++ /dev/null @@ -1,9 +0,0 @@ -version = "1.*" -upstream_repository = "https://github.com/grpc/grpc" -partial_stub = true -requires = [ - "types-grpc", -] - -[tool.stubtest] -ignore_missing_stub = true diff --git a/stubs/grpc_health/METADATA.toml b/stubs/grpc_health/METADATA.toml deleted file mode 100644 index c7934b2b5446..000000000000 --- a/stubs/grpc_health/METADATA.toml +++ /dev/null @@ -1,9 +0,0 @@ -version = "1.*" -upstream_repository = "https://github.com/grpc/grpc" -partial_stub = true -requires = [ - "types-grpc", -] - -[tool.stubtest] -ignore_missing_stub = true diff --git a/stubs/grpc_status/METADATA.toml b/stubs/grpc_status/METADATA.toml deleted file mode 100644 index 26a1fab02c88..000000000000 --- a/stubs/grpc_status/METADATA.toml +++ /dev/null @@ -1,7 +0,0 @@ -version = "1.*" -upstream_repository = "https://github.com/grpc/grpc" -partial_stub = true -requires = ["types-grpc"] - -[tool.stubtest] -ignore_missing_stub = true diff --git a/stubs/grpc/@tests/test_cases/check_aio.py b/stubs/grpcio/@tests/test_cases/check_aio.py similarity index 100% rename from stubs/grpc/@tests/test_cases/check_aio.py rename to stubs/grpcio/@tests/test_cases/check_aio.py diff --git a/stubs/grpc/@tests/test_cases/check_aio_multi_callable.py b/stubs/grpcio/@tests/test_cases/check_aio_multi_callable.py similarity index 100% rename from stubs/grpc/@tests/test_cases/check_aio_multi_callable.py rename to stubs/grpcio/@tests/test_cases/check_aio_multi_callable.py diff --git a/stubs/grpc/@tests/test_cases/check_aio_via_grpc.py b/stubs/grpcio/@tests/test_cases/check_aio_via_grpc.py similarity index 100% rename from stubs/grpc/@tests/test_cases/check_aio_via_grpc.py rename to stubs/grpcio/@tests/test_cases/check_aio_via_grpc.py diff --git a/stubs/grpc/@tests/test_cases/check_grpc.py b/stubs/grpcio/@tests/test_cases/check_grpc.py similarity index 100% rename from stubs/grpc/@tests/test_cases/check_grpc.py rename to stubs/grpcio/@tests/test_cases/check_grpc.py diff --git a/stubs/grpc/@tests/test_cases/check_handler_inheritance.py b/stubs/grpcio/@tests/test_cases/check_handler_inheritance.py similarity index 100% rename from stubs/grpc/@tests/test_cases/check_handler_inheritance.py rename to stubs/grpcio/@tests/test_cases/check_handler_inheritance.py diff --git a/stubs/grpc/@tests/test_cases/check_multi_callable.py b/stubs/grpcio/@tests/test_cases/check_multi_callable.py similarity index 100% rename from stubs/grpc/@tests/test_cases/check_multi_callable.py rename to stubs/grpcio/@tests/test_cases/check_multi_callable.py diff --git a/stubs/grpc_reflection/@tests/test_cases/check_reflection.py b/stubs/grpcio/@tests/test_cases/check_reflection.py similarity index 100% rename from stubs/grpc_reflection/@tests/test_cases/check_reflection.py rename to stubs/grpcio/@tests/test_cases/check_reflection.py diff --git a/stubs/grpc_reflection/@tests/test_cases/check_reflection_aio.py b/stubs/grpcio/@tests/test_cases/check_reflection_aio.py similarity index 100% rename from stubs/grpc_reflection/@tests/test_cases/check_reflection_aio.py rename to stubs/grpcio/@tests/test_cases/check_reflection_aio.py diff --git a/stubs/grpc/@tests/test_cases/check_register.py b/stubs/grpcio/@tests/test_cases/check_register.py similarity index 100% rename from stubs/grpc/@tests/test_cases/check_register.py rename to stubs/grpcio/@tests/test_cases/check_register.py diff --git a/stubs/grpc/@tests/test_cases/check_server_interceptor.py b/stubs/grpcio/@tests/test_cases/check_server_interceptor.py similarity index 100% rename from stubs/grpc/@tests/test_cases/check_server_interceptor.py rename to stubs/grpcio/@tests/test_cases/check_server_interceptor.py diff --git a/stubs/grpc_status/@tests/test_cases/check_status.py b/stubs/grpcio/@tests/test_cases/check_status.py similarity index 100% rename from stubs/grpc_status/@tests/test_cases/check_status.py rename to stubs/grpcio/@tests/test_cases/check_status.py diff --git a/stubs/grpc_reflection/METADATA.toml b/stubs/grpcio/METADATA.toml similarity index 90% rename from stubs/grpc_reflection/METADATA.toml rename to stubs/grpcio/METADATA.toml index 5fc3efa942c2..885a12a1ef9a 100644 --- a/stubs/grpc_reflection/METADATA.toml +++ b/stubs/grpcio/METADATA.toml @@ -2,7 +2,6 @@ version = "1.*" upstream_repository = "https://github.com/grpc/grpc" partial_stub = true requires = [ - "types-grpc", "types-protobuf", ] diff --git a/stubs/grpc/grpc/__init__.pyi b/stubs/grpcio/grpc/__init__.pyi similarity index 100% rename from stubs/grpc/grpc/__init__.pyi rename to stubs/grpcio/grpc/__init__.pyi diff --git a/stubs/grpc/grpc/aio/__init__.pyi b/stubs/grpcio/grpc/aio/__init__.pyi similarity index 100% rename from stubs/grpc/grpc/aio/__init__.pyi rename to stubs/grpcio/grpc/aio/__init__.pyi diff --git a/stubs/grpc_channelz/grpc_channelz/__init__.pyi b/stubs/grpcio/grpc_channelz/__init__.pyi similarity index 100% rename from stubs/grpc_channelz/grpc_channelz/__init__.pyi rename to stubs/grpcio/grpc_channelz/__init__.pyi diff --git a/stubs/grpc_channelz/grpc_channelz/v1/__init__.pyi b/stubs/grpcio/grpc_channelz/v1/__init__.pyi similarity index 100% rename from stubs/grpc_channelz/grpc_channelz/v1/__init__.pyi rename to stubs/grpcio/grpc_channelz/v1/__init__.pyi diff --git a/stubs/grpc_channelz/grpc_channelz/v1/_servicer.pyi b/stubs/grpcio/grpc_channelz/v1/_servicer.pyi similarity index 100% rename from stubs/grpc_channelz/grpc_channelz/v1/_servicer.pyi rename to stubs/grpcio/grpc_channelz/v1/_servicer.pyi diff --git a/stubs/grpc_channelz/grpc_channelz/v1/channelz.pyi b/stubs/grpcio/grpc_channelz/v1/channelz.pyi similarity index 100% rename from stubs/grpc_channelz/grpc_channelz/v1/channelz.pyi rename to stubs/grpcio/grpc_channelz/v1/channelz.pyi diff --git a/stubs/grpc_channelz/grpc_channelz/v1/channelz_pb2.pyi b/stubs/grpcio/grpc_channelz/v1/channelz_pb2.pyi similarity index 100% rename from stubs/grpc_channelz/grpc_channelz/v1/channelz_pb2.pyi rename to stubs/grpcio/grpc_channelz/v1/channelz_pb2.pyi diff --git a/stubs/grpc_channelz/grpc_channelz/v1/channelz_pb2_grpc.pyi b/stubs/grpcio/grpc_channelz/v1/channelz_pb2_grpc.pyi similarity index 100% rename from stubs/grpc_channelz/grpc_channelz/v1/channelz_pb2_grpc.pyi rename to stubs/grpcio/grpc_channelz/v1/channelz_pb2_grpc.pyi diff --git a/stubs/grpc_health/grpc_health/__init__.pyi b/stubs/grpcio/grpc_health/__init__.pyi similarity index 100% rename from stubs/grpc_health/grpc_health/__init__.pyi rename to stubs/grpcio/grpc_health/__init__.pyi diff --git a/stubs/grpc_health/grpc_health/v1/__init__.pyi b/stubs/grpcio/grpc_health/v1/__init__.pyi similarity index 100% rename from stubs/grpc_health/grpc_health/v1/__init__.pyi rename to stubs/grpcio/grpc_health/v1/__init__.pyi diff --git a/stubs/grpc_health/grpc_health/v1/health.pyi b/stubs/grpcio/grpc_health/v1/health.pyi similarity index 100% rename from stubs/grpc_health/grpc_health/v1/health.pyi rename to stubs/grpcio/grpc_health/v1/health.pyi diff --git a/stubs/grpc_health/grpc_health/v1/health_pb2.pyi b/stubs/grpcio/grpc_health/v1/health_pb2.pyi similarity index 100% rename from stubs/grpc_health/grpc_health/v1/health_pb2.pyi rename to stubs/grpcio/grpc_health/v1/health_pb2.pyi diff --git a/stubs/grpc_health/grpc_health/v1/health_pb2_grpc.pyi b/stubs/grpcio/grpc_health/v1/health_pb2_grpc.pyi similarity index 100% rename from stubs/grpc_health/grpc_health/v1/health_pb2_grpc.pyi rename to stubs/grpcio/grpc_health/v1/health_pb2_grpc.pyi diff --git a/stubs/grpc_reflection/grpc_reflection/__init__.pyi b/stubs/grpcio/grpc_reflection/__init__.pyi similarity index 100% rename from stubs/grpc_reflection/grpc_reflection/__init__.pyi rename to stubs/grpcio/grpc_reflection/__init__.pyi diff --git a/stubs/grpc_reflection/grpc_reflection/v1alpha/__init__.pyi b/stubs/grpcio/grpc_reflection/v1alpha/__init__.pyi similarity index 100% rename from stubs/grpc_reflection/grpc_reflection/v1alpha/__init__.pyi rename to stubs/grpcio/grpc_reflection/v1alpha/__init__.pyi diff --git a/stubs/grpc_reflection/grpc_reflection/v1alpha/_base.pyi b/stubs/grpcio/grpc_reflection/v1alpha/_base.pyi similarity index 100% rename from stubs/grpc_reflection/grpc_reflection/v1alpha/_base.pyi rename to stubs/grpcio/grpc_reflection/v1alpha/_base.pyi diff --git a/stubs/grpc_reflection/grpc_reflection/v1alpha/reflection.pyi b/stubs/grpcio/grpc_reflection/v1alpha/reflection.pyi similarity index 100% rename from stubs/grpc_reflection/grpc_reflection/v1alpha/reflection.pyi rename to stubs/grpcio/grpc_reflection/v1alpha/reflection.pyi diff --git a/stubs/grpc_reflection/grpc_reflection/v1alpha/reflection_pb2.pyi b/stubs/grpcio/grpc_reflection/v1alpha/reflection_pb2.pyi similarity index 100% rename from stubs/grpc_reflection/grpc_reflection/v1alpha/reflection_pb2.pyi rename to stubs/grpcio/grpc_reflection/v1alpha/reflection_pb2.pyi diff --git a/stubs/grpc_status/grpc_status/__init__.pyi b/stubs/grpcio/grpc_status/__init__.pyi similarity index 100% rename from stubs/grpc_status/grpc_status/__init__.pyi rename to stubs/grpcio/grpc_status/__init__.pyi diff --git a/stubs/grpc_status/grpc_status/rpc_status.pyi b/stubs/grpcio/grpc_status/rpc_status.pyi similarity index 100% rename from stubs/grpc_status/grpc_status/rpc_status.pyi rename to stubs/grpcio/grpc_status/rpc_status.pyi From 9993e8ddccf39e2a798722bcd7a909e0318d2c68 Mon Sep 17 00:00:00 2001 From: Blake Williams Date: Thu, 28 Dec 2023 22:46:36 +1100 Subject: [PATCH 16/18] Add abstractmethod decorator to grpc.Call --- stubs/grpcio/grpc/__init__.pyi | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/stubs/grpcio/grpc/__init__.pyi b/stubs/grpcio/grpc/__init__.pyi index 742c843494ad..4a4b0ff1f9ad 100644 --- a/stubs/grpcio/grpc/__init__.pyi +++ b/stubs/grpcio/grpc/__init__.pyi @@ -320,11 +320,17 @@ class RpcContext(abc.ABC): # Client-Side Context: class Call(RpcContext, metaclass=abc.ABCMeta): + @abc.abstractmethod def code(self) -> StatusCode: ... # misnamed property, does not align with status.proto, where it is called 'message': + @abc.abstractmethod def details(self) -> str: ... + + @abc.abstractmethod def initial_metadata(self) -> Metadata: ... + + @abc.abstractmethod def trailing_metadata(self) -> Metadata: ... # Client-Side Interceptor: From be407203286ec3ff8a45480c85269176222f3bd3 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 28 Dec 2023 11:47:17 +0000 Subject: [PATCH 17/18] [pre-commit.ci] auto fixes from pre-commit.com hooks --- stubs/grpcio/grpc/__init__.pyi | 2 -- 1 file changed, 2 deletions(-) diff --git a/stubs/grpcio/grpc/__init__.pyi b/stubs/grpcio/grpc/__init__.pyi index 4a4b0ff1f9ad..0eaa0779928e 100644 --- a/stubs/grpcio/grpc/__init__.pyi +++ b/stubs/grpcio/grpc/__init__.pyi @@ -326,10 +326,8 @@ class Call(RpcContext, metaclass=abc.ABCMeta): # misnamed property, does not align with status.proto, where it is called 'message': @abc.abstractmethod def details(self) -> str: ... - @abc.abstractmethod def initial_metadata(self) -> Metadata: ... - @abc.abstractmethod def trailing_metadata(self) -> Metadata: ... From 5b3e6986b0b26bb56b82274b36442f3cd5342bab Mon Sep 17 00:00:00 2001 From: Blake Williams Date: Thu, 28 Dec 2023 23:26:56 +1100 Subject: [PATCH 18/18] Fix a bunch of stubtest issues --- stubs/grpcio/@tests/test_cases/check_grpc.py | 5 +- .../test_cases/check_handler_inheritance.py | 6 +- stubs/grpcio/grpc/__init__.pyi | 147 +++++++++++++----- stubs/grpcio/grpc/aio/__init__.pyi | 78 +++++++--- 4 files changed, 170 insertions(+), 66 deletions(-) diff --git a/stubs/grpcio/@tests/test_cases/check_grpc.py b/stubs/grpcio/@tests/test_cases/check_grpc.py index beeaaac6d831..b453077097f2 100644 --- a/stubs/grpcio/@tests/test_cases/check_grpc.py +++ b/stubs/grpcio/@tests/test_cases/check_grpc.py @@ -5,9 +5,6 @@ import grpc -assert_type(grpc.Channel(), grpc.Channel) -assert_type(grpc.Server(), grpc.Server) - # Channel options: assert_type(grpc.insecure_channel("target", ()), grpc.Channel) assert_type(grpc.insecure_channel("target", (("a", "b"),)), grpc.Channel) @@ -20,7 +17,7 @@ # Other credential types: assert_type(grpc.alts_channel_credentials(), grpc.ChannelCredentials) assert_type(grpc.alts_server_credentials(), grpc.ServerCredentials) -assert_type(grpc.compute_engine_channel_credentials(), grpc.ChannelCredentials) +assert_type(grpc.compute_engine_channel_credentials(typing.cast(typing.Any, None)), grpc.ChannelCredentials) assert_type(grpc.insecure_server_credentials(), grpc.ServerCredentials) # XDS credentials: diff --git a/stubs/grpcio/@tests/test_cases/check_handler_inheritance.py b/stubs/grpcio/@tests/test_cases/check_handler_inheritance.py index c0a88443c5ea..617e8e67adfc 100644 --- a/stubs/grpcio/@tests/test_cases/check_handler_inheritance.py +++ b/stubs/grpcio/@tests/test_cases/check_handler_inheritance.py @@ -1,5 +1,6 @@ from __future__ import annotations +import typing from typing_extensions import assert_type import grpc @@ -19,6 +20,9 @@ def unary_unary_call(rq: Request, ctx: grpc.ServicerContext) -> Response: class ServiceHandler(grpc.ServiceRpcHandler[Request, Response]): + def service_name(self) -> str: + return "hello" + def service(self, handler_call_details: grpc.HandlerCallDetails) -> grpc.RpcMethodHandler[Request, Response] | None: rpc = grpc.RpcMethodHandler[Request, Response]() rpc.unary_unary = unary_unary_call @@ -26,7 +30,7 @@ def service(self, handler_call_details: grpc.HandlerCallDetails) -> grpc.RpcMeth h = ServiceHandler() -ctx = grpc.ServicerContext() +ctx = typing.cast(grpc.ServicerContext, None) svc = h.service(grpc.HandlerCallDetails()) if svc is not None and svc.unary_unary is not None: svc.unary_unary(Request(), ctx) diff --git a/stubs/grpcio/grpc/__init__.pyi b/stubs/grpcio/grpc/__init__.pyi index 0eaa0779928e..e852ac61232c 100644 --- a/stubs/grpcio/grpc/__init__.pyi +++ b/stubs/grpcio/grpc/__init__.pyi @@ -2,6 +2,7 @@ import abc import enum import threading import typing +from _typeshed import Incomplete from collections.abc import Callable, Iterable, Iterator, Mapping, Sequence from concurrent import futures from types import ModuleType, TracebackType @@ -24,14 +25,14 @@ _OptionKeyValue: TypeAlias = tuple[str, typing.Any] _Options: TypeAlias = Sequence[_OptionKeyValue] class Compression(enum.IntEnum): - NoCompression = ... - Deflate = ... - Gzip = ... + NoCompression = 0 + Deflate = 1 + Gzip = 2 @enum.unique class LocalConnectionType(enum.Enum): - UDS = ... - LOCAL_TCP = ... + UDS = 0 + LOCAL_TCP = 1 # XXX: not documented, needs more investigation. # Some evidence: @@ -65,15 +66,23 @@ class FutureCancelledError(Exception): ... _TFutureValue = typing.TypeVar("_TFutureValue") class Future(abc.ABC, typing.Generic[_TFutureValue]): + @abc.abstractmethod def add_done_callback(self, fn: Callable[[Future[_TFutureValue]], None]) -> None: ... + @abc.abstractmethod def cancel(self) -> bool: ... + @abc.abstractmethod def cancelled(self) -> bool: ... + @abc.abstractmethod def done(self) -> bool: ... - def exception(self) -> Exception | None: ... + @abc.abstractmethod + def exception(self, timeout: float | None = ...) -> Exception | None: ... + @abc.abstractmethod def result(self, timeout: float | None = ...) -> _TFutureValue: ... + @abc.abstractmethod def running(self) -> bool: ... # FIXME: unsure of the exact return type here. Is it a traceback.StackSummary? + @abc.abstractmethod def traceback(self, timeout: float | None = ...) -> typing.Any: ... # Create Client: @@ -101,7 +110,7 @@ def local_channel_credentials(local_connect_type: LocalConnectionType = ...) -> def metadata_call_credentials(metadata_plugin: AuthMetadataPlugin, name: str | None = ...) -> CallCredentials: ... def access_token_call_credentials(access_token: str) -> CallCredentials: ... def alts_channel_credentials(service_accounts: Sequence[str] | None = ...) -> ChannelCredentials: ... -def compute_engine_channel_credentials() -> ChannelCredentials: ... +def compute_engine_channel_credentials(call_credentials: CallCredentials) -> ChannelCredentials: ... def xds_channel_credentials(fallback_credentials: ChannelCredentials | None = ...) -> ChannelCredentials: ... # GRPC docs say there should be at least two: @@ -189,11 +198,11 @@ def channel_ready_future(channel: Channel) -> Future[None]: ... # Channel Connectivity: class ChannelConnectivity(enum.Enum): - IDLE = ... - CONNECTING = ... - READY = ... - TRANSIENT_FAILURE = ... - SHUTDOWN = ... + IDLE = (0, "idle") + CONNECTING = (1, "connecting") + READY = (2, "ready") + TRANSIENT_FAILURE = (3, "transient failure") + SHUTDOWN = (4, "shutdown") # gRPC Status Code: @@ -207,41 +216,60 @@ class Status(abc.ABC): # https://grpc.github.io/grpc/core/md_doc_statuscodes.html class StatusCode(enum.Enum): - OK = ... - CANCELLED = ... - UNKNOWN = ... - INVALID_ARGUMENT = ... - DEADLINE_EXCEEDED = ... - NOT_FOUND = ... - ALREADY_EXISTS = ... - PERMISSION_DENIED = ... - RESOURCE_EXHAUSTED = ... - FAILED_PRECONDITION = ... - ABORTED = ... - OUT_OF_RANGE = ... - UNIMPLEMENTED = ... - INTERNAL = ... - UNAVAILABLE = ... - DATA_LOSS = ... - UNAUTHENTICATED = ... + OK = (0, "ok") + CANCELLED = (1, "cancelled") + UNKNOWN = (2, "unknown") + INVALID_ARGUMENT = (3, "invalid argument") + DEADLINE_EXCEEDED = (4, "deadline exceeded") + NOT_FOUND = (5, "not found") + ALREADY_EXISTS = (6, "already exists") + PERMISSION_DENIED = (7, "permission denied") + RESOURCE_EXHAUSTED = (8, "resource exhausted") + FAILED_PRECONDITION = (9, "failed precondition") + ABORTED = (10, "aborted") + OUT_OF_RANGE = (11, "out of range") + UNIMPLEMENTED = (12, "unimplemented") + INTERNAL = (13, "internal") + UNAVAILABLE = (14, "unavailable") + DATA_LOSS = (15, "data loss") + UNAUTHENTICATED = (16, "unauthenticated") # Channel Object: class Channel(abc.ABC): + @abc.abstractmethod def close(self) -> None: ... + @abc.abstractmethod def stream_stream( - self, method: str, request_serializer: RequestSerializer | None, response_deserializer: ResponseDeserializer | None + self, + method: str, + request_serializer: RequestSerializer | None = ..., + response_deserializer: ResponseDeserializer | None = ..., ) -> StreamStreamMultiCallable[typing.Any, typing.Any]: ... + @abc.abstractmethod def stream_unary( - self, method: str, request_serializer: RequestSerializer | None, response_deserializer: ResponseDeserializer | None + self, + method: str, + request_serializer: RequestSerializer | None = ..., + response_deserializer: ResponseDeserializer | None = ..., ) -> StreamUnaryMultiCallable[typing.Any, typing.Any]: ... + @abc.abstractmethod def subscribe(self, callback: Callable[[ChannelConnectivity], None], try_to_connect: bool = ...) -> None: ... + @abc.abstractmethod def unary_stream( - self, method: str, request_serializer: RequestSerializer | None, response_deserializer: ResponseDeserializer | None + self, + method: str, + request_serializer: RequestSerializer | None = ..., + response_deserializer: ResponseDeserializer | None = ..., ) -> UnaryStreamMultiCallable[typing.Any, typing.Any]: ... + @abc.abstractmethod def unary_unary( - self, method: str, request_serializer: RequestSerializer | None, response_deserializer: ResponseDeserializer | None + self, + method: str, + request_serializer: RequestSerializer | None = ..., + response_deserializer: ResponseDeserializer | None = ..., ) -> UnaryUnaryMultiCallable[typing.Any, typing.Any]: ... + @abc.abstractmethod def unsubscribe(self, callback: Callable[[ChannelConnectivity], None]) -> None: ... def __enter__(self) -> Self: ... def __exit__( @@ -251,17 +279,22 @@ class Channel(abc.ABC): # Server Object: class Server(abc.ABC): + @abc.abstractmethod def add_generic_rpc_handlers(self, generic_rpc_handlers: Iterable[GenericRpcHandler[typing.Any, typing.Any]]) -> None: ... # Returns an integer port on which server will accept RPC requests. + @abc.abstractmethod def add_insecure_port(self, address: str) -> int: ... # Returns an integer port on which server will accept RPC requests. + @abc.abstractmethod def add_secure_port(self, address: str, server_credentials: ServerCredentials) -> int: ... + @abc.abstractmethod def start(self) -> None: ... # Grace period is in seconds. - def stop(self, grace: float | None = ...) -> threading.Event: ... + @abc.abstractmethod + def stop(self, grace: float | None) -> threading.Event: ... # Block current thread until the server stops. Returns a bool # indicates if the operation times out. Timeout is in seconds. @@ -270,10 +303,12 @@ class Server(abc.ABC): # Authentication & Authorization Objects: # This class has no supported interface -class ChannelCredentials: ... +class ChannelCredentials: + def __init__(self, credentials: Incomplete) -> None: ... # This class has no supported interface -class CallCredentials: ... +class CallCredentials: + def __init__(self, credentials: Incomplete) -> None: ... class AuthMetadataContext(abc.ABC): service_url: str @@ -286,10 +321,12 @@ class AuthMetadataPlugin(abc.ABC): def __call__(self, context: AuthMetadataContext, callback: AuthMetadataPluginCallback) -> None: ... # This class has no supported interface -class ServerCredentials: ... +class ServerCredentials: + def __init__(self, credentials: Incomplete) -> None: ... # This class has no supported interface -class ServerCertificateConfiguration: ... +class ServerCertificateConfiguration: + def __init__(self, certificate_configuration: Incomplete) -> None: ... # gRPC Exceptions: @@ -312,9 +349,13 @@ class RpcError(Exception): # Shared Context: class RpcContext(abc.ABC): + @abc.abstractmethod def add_callback(self, callback: Callable[[], None]) -> bool: ... + @abc.abstractmethod def cancel(self) -> bool: ... + @abc.abstractmethod def is_active(self) -> bool: ... + @abc.abstractmethod def time_remaining(self) -> float: ... # Client-Side Context: @@ -349,9 +390,10 @@ class ClientCallDetails(abc.ABC): # response message of the RPC. Should the event terminate with non-OK # status, the returned Call-Future’s exception value will be an RpcError. # -class CallFuture(Call, Future[_TResponse]): ... +class CallFuture(Call, Future[_TResponse], metaclass=abc.ABCMeta): ... class UnaryUnaryClientInterceptor(abc.ABC, typing.Generic[_TRequest, _TResponse]): + @abc.abstractmethod def intercept_unary_unary( self, # FIXME: decode these cryptic runes to confirm the typing mystery of @@ -374,10 +416,11 @@ class UnaryUnaryClientInterceptor(abc.ABC, typing.Generic[_TRequest, _TResponse] request: _TRequest, ) -> CallFuture[_TResponse]: ... -class CallIterator(Call, typing.Generic[_TResponse]): +class CallIterator(Call, typing.Generic[_TResponse], metaclass=abc.ABCMeta): def __iter__(self) -> Iterator[_TResponse]: ... class UnaryStreamClientInterceptor(abc.ABC, typing.Generic[_TRequest, _TResponse]): + @abc.abstractmethod def intercept_unary_stream( self, continuation: Callable[[ClientCallDetails, _TRequest], CallIterator[_TResponse]], @@ -386,6 +429,7 @@ class UnaryStreamClientInterceptor(abc.ABC, typing.Generic[_TRequest, _TResponse ) -> CallIterator[_TResponse]: ... class StreamUnaryClientInterceptor(abc.ABC, typing.Generic[_TRequest, _TResponse]): + @abc.abstractmethod def intercept_stream_unary( self, continuation: Callable[[ClientCallDetails, _TRequest], CallFuture[_TResponse]], @@ -394,6 +438,7 @@ class StreamUnaryClientInterceptor(abc.ABC, typing.Generic[_TRequest, _TResponse ) -> CallFuture[_TResponse]: ... class StreamStreamClientInterceptor(abc.ABC, typing.Generic[_TRequest, _TResponse]): + @abc.abstractmethod def intercept_stream_stream( self, continuation: Callable[[ClientCallDetails, _TRequest], CallIterator[_TResponse]], @@ -405,23 +450,34 @@ class StreamStreamClientInterceptor(abc.ABC, typing.Generic[_TRequest, _TRespons class ServicerContext(RpcContext, metaclass=abc.ABCMeta): # misnamed parameter 'details', does not align with status.proto, where it is called 'message': + @abc.abstractmethod def abort(self, code: StatusCode, details: str) -> typing.NoReturn: ... + @abc.abstractmethod def abort_with_status(self, status: Status) -> typing.NoReturn: ... # FIXME: The docs say "A map of strings to an iterable of bytes for each auth property". # Does that mean 'bytes' (which is iterable), or 'Iterable[bytes]'? + @abc.abstractmethod def auth_context(self) -> Mapping[str, bytes]: ... def disable_next_message_compression(self) -> None: ... + @abc.abstractmethod def invocation_metadata(self) -> Metadata: ... + @abc.abstractmethod def peer(self) -> str: ... + @abc.abstractmethod def peer_identities(self) -> Iterable[bytes] | None: ... + @abc.abstractmethod def peer_identity_key(self) -> str | None: ... + @abc.abstractmethod def send_initial_metadata(self, initial_metadata: Metadata) -> None: ... + @abc.abstractmethod def set_code(self, code: StatusCode) -> None: ... def set_compression(self, compression: Compression) -> None: ... + @abc.abstractmethod def set_trailing_metadata(self, trailing_metadata: Metadata) -> None: ... # misnamed function 'details', does not align with status.proto, where it is called 'message': + @abc.abstractmethod def set_details(self, details: str) -> None: ... def trailing_metadata(self) -> Metadata: ... @@ -450,14 +506,17 @@ class HandlerCallDetails(abc.ABC): invocation_metadata: Metadata class GenericRpcHandler(abc.ABC, typing.Generic[_TRequest, _TResponse]): + @abc.abstractmethod def service(self, handler_call_details: HandlerCallDetails) -> RpcMethodHandler[_TRequest, _TResponse] | None: ... class ServiceRpcHandler(GenericRpcHandler[_TRequest, _TResponse], metaclass=abc.ABCMeta): + @abc.abstractmethod def service_name(self) -> str: ... # Service-Side Interceptor: class ServerInterceptor(abc.ABC, typing.Generic[_TRequest, _TResponse]): + @abc.abstractmethod def intercept_service( self, continuation: Callable[[HandlerCallDetails], RpcMethodHandler[_TRequest, _TResponse] | None], @@ -467,6 +526,7 @@ class ServerInterceptor(abc.ABC, typing.Generic[_TRequest, _TResponse]): # Multi-Callable Interfaces: class UnaryUnaryMultiCallable(abc.ABC, typing.Generic[_TRequest, _TResponse]): + @abc.abstractmethod def __call__( self, request: _TRequest, @@ -477,6 +537,7 @@ class UnaryUnaryMultiCallable(abc.ABC, typing.Generic[_TRequest, _TResponse]): wait_for_ready: bool | None = ..., compression: Compression | None = ..., ) -> _TResponse: ... + @abc.abstractmethod def future( self, request: _TRequest, @@ -487,6 +548,7 @@ class UnaryUnaryMultiCallable(abc.ABC, typing.Generic[_TRequest, _TResponse]): wait_for_ready: bool | None = ..., compression: Compression | None = ..., ) -> CallFuture[_TResponse]: ... + @abc.abstractmethod def with_call( self, request: _TRequest, @@ -501,6 +563,7 @@ class UnaryUnaryMultiCallable(abc.ABC, typing.Generic[_TRequest, _TResponse]): ) -> tuple[_TResponse, Call]: ... class UnaryStreamMultiCallable(abc.ABC, typing.Generic[_TRequest, _TResponse]): + @abc.abstractmethod def __call__( self, request: _TRequest, @@ -513,6 +576,7 @@ class UnaryStreamMultiCallable(abc.ABC, typing.Generic[_TRequest, _TResponse]): ) -> CallIterator[_TResponse]: ... class StreamUnaryMultiCallable(abc.ABC, typing.Generic[_TRequest, _TResponse]): + @abc.abstractmethod def __call__( self, request_iterator: Iterator[_TRequest], @@ -523,6 +587,7 @@ class StreamUnaryMultiCallable(abc.ABC, typing.Generic[_TRequest, _TResponse]): wait_for_ready: bool | None = ..., compression: Compression | None = ..., ) -> _TResponse: ... + @abc.abstractmethod def future( self, request_iterator: Iterator[_TRequest], @@ -533,6 +598,7 @@ class StreamUnaryMultiCallable(abc.ABC, typing.Generic[_TRequest, _TResponse]): wait_for_ready: bool | None = ..., compression: Compression | None = ..., ) -> CallFuture[_TResponse]: ... + @abc.abstractmethod def with_call( self, request_iterator: Iterator[_TRequest], @@ -547,6 +613,7 @@ class StreamUnaryMultiCallable(abc.ABC, typing.Generic[_TRequest, _TResponse]): ) -> tuple[_TResponse, Call]: ... class StreamStreamMultiCallable(abc.ABC, typing.Generic[_TRequest, _TResponse]): + @abc.abstractmethod def __call__( self, request_iterator: Iterator[_TRequest], diff --git a/stubs/grpcio/grpc/aio/__init__.pyi b/stubs/grpcio/grpc/aio/__init__.pyi index f8e49b885bf9..9447018f1756 100644 --- a/stubs/grpcio/grpc/aio/__init__.pyi +++ b/stubs/grpcio/grpc/aio/__init__.pyi @@ -1,3 +1,4 @@ +import abc import asyncio import typing from _typeshed import Incomplete @@ -18,7 +19,6 @@ from grpc import ( ServerCredentials, StatusCode, _Options, - _PartialStubMustCastOrIgnore, ) _TRequest = typing.TypeVar("_TRequest") @@ -37,8 +37,8 @@ class AioRpcError(RpcError): code: StatusCode, initial_metadata: Metadata, trailing_metadata: Metadata, - details: str | None, - debug_error_string: str | None, + details: str | None = ..., + debug_error_string: str | None = ..., ) -> None: ... # FIXME: confirm if these are present in the parent type. The remaining @@ -48,7 +48,7 @@ class AioRpcError(RpcError): # Create Client: -ClientInterceptor: TypeAlias = _PartialStubMustCastOrIgnore +class ClientInterceptor(metaclass=abc.ABCMeta): ... def insecure_channel( target: str, @@ -83,26 +83,48 @@ def server( RequestSerializer: TypeAlias = Callable[[typing.Any], bytes] ResponseDeserializer: TypeAlias = Callable[[bytes], typing.Any] -class Channel: - async def close(self, grace: float | None) -> None: ... +class Channel(abc.ABC): + @abc.abstractmethod + async def close(self, grace: float | None = ...) -> None: ... + @abc.abstractmethod def get_state(self, try_to_connect: bool = ...) -> ChannelConnectivity: ... + @abc.abstractmethod async def wait_for_state_change(self, last_observed_state: ChannelConnectivity) -> None: ... + @abc.abstractmethod def stream_stream( - self, method: str, request_serializer: RequestSerializer | None, response_deserializer: ResponseDeserializer | None + self, + method: str, + request_serializer: RequestSerializer | None = ..., + response_deserializer: ResponseDeserializer | None = ..., ) -> StreamStreamMultiCallable[typing.Any, typing.Any]: ... + @abc.abstractmethod def stream_unary( - self, method: str, request_serializer: RequestSerializer | None, response_deserializer: ResponseDeserializer | None + self, + method: str, + request_serializer: RequestSerializer | None = ..., + response_deserializer: ResponseDeserializer | None = ..., ) -> StreamUnaryMultiCallable[typing.Any, typing.Any]: ... + @abc.abstractmethod def unary_stream( - self, method: str, request_serializer: RequestSerializer | None, response_deserializer: ResponseDeserializer | None + self, + method: str, + request_serializer: RequestSerializer | None = ..., + response_deserializer: ResponseDeserializer | None = ..., ) -> UnaryStreamMultiCallable[typing.Any, typing.Any]: ... + @abc.abstractmethod def unary_unary( - self, method: str, request_serializer: RequestSerializer | None, response_deserializer: ResponseDeserializer | None + self, + method: str, + request_serializer: RequestSerializer | None = ..., + response_deserializer: ResponseDeserializer | None = ..., ) -> UnaryUnaryMultiCallable[typing.Any, typing.Any]: ... + @abc.abstractmethod async def __aenter__(self) -> Self: ... + @abc.abstractmethod async def __aexit__( self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None ) -> bool | None: ... + @abc.abstractmethod async def channel_ready(self) -> None: ... # Server Object: @@ -128,33 +150,43 @@ class Server: DoneCallbackType: TypeAlias = Callable[[typing.Any], None] EOFType: TypeAlias = object -class RpcContext: +class RpcContext(metaclass=abc.ABCMeta): + @abc.abstractmethod def cancelled(self) -> bool: ... + @abc.abstractmethod def done(self) -> bool: ... + @abc.abstractmethod def time_remaining(self) -> float | None: ... + @abc.abstractmethod def cancel(self) -> bool: ... + @abc.abstractmethod def add_done_callback(self, callback: DoneCallbackType) -> None: ... -class Call(RpcContext): +class Call(RpcContext, metaclass=abc.ABCMeta): + @abc.abstractmethod async def initial_metadata(self) -> Metadata: ... + @abc.abstractmethod async def trailing_metadata(self) -> Metadata: ... + @abc.abstractmethod async def code(self) -> StatusCode: ... + @abc.abstractmethod async def details(self) -> str: ... + @abc.abstractmethod async def wait_for_connection(self) -> None: ... -class UnaryUnaryCall(Call, typing.Generic[_TRequest, _TResponse]): +class UnaryUnaryCall(Call, typing.Generic[_TRequest, _TResponse], metaclass=abc.ABCMeta): def __await__(self) -> Generator[None, None, _TResponse]: ... -class UnaryStreamCall(Call, typing.Generic[_TRequest, _TResponse]): +class UnaryStreamCall(Call, typing.Generic[_TRequest, _TResponse], metaclass=abc.ABCMeta): def __aiter__(self) -> AsyncIterator[_TResponse]: ... async def read(self) -> EOFType | _TResponse: ... -class StreamUnaryCall(Call, typing.Generic[_TRequest, _TResponse]): +class StreamUnaryCall(Call, typing.Generic[_TRequest, _TResponse], metaclass=abc.ABCMeta): async def write(self, request: _TRequest) -> None: ... async def done_writing(self) -> None: ... def __await__(self) -> Generator[None, None, _TResponse]: ... -class StreamStreamCall(Call, typing.Generic[_TRequest, _TResponse]): +class StreamStreamCall(Call, typing.Generic[_TRequest, _TResponse], metaclass=abc.ABCMeta): def __aiter__(self) -> AsyncIterator[_TResponse]: ... async def read(self) -> EOFType | _TResponse: ... async def write(self, request: _TRequest) -> None: ... @@ -190,7 +222,7 @@ class ServicerContext(typing.Generic[_TRequest, _TResponse]): # Client-Side Interceptor: -class ClientCallDetails: +class ClientCallDetails(abc.ABC): def __init__( self, method: str, @@ -259,6 +291,7 @@ class InterceptedUnaryUnaryCall(InterceptedCall[_TRequest, _TResponse]): def time_remaining(self) -> float | None: ... class UnaryUnaryClientInterceptor(typing.Generic[_TRequest, _TResponse]): + @abc.abstractmethod async def intercept_unary_unary( self, # XXX: See equivalent function in grpc types for notes about continuation: @@ -268,6 +301,7 @@ class UnaryUnaryClientInterceptor(typing.Generic[_TRequest, _TResponse]): ) -> _TResponse: ... class UnaryStreamClientInterceptor(typing.Generic[_TRequest, _TResponse]): + @abc.abstractmethod async def intercept_unary_stream( self, continuation: Callable[[ClientCallDetails, _TRequest], UnaryStreamCall[_TRequest, _TResponse]], @@ -276,6 +310,7 @@ class UnaryStreamClientInterceptor(typing.Generic[_TRequest, _TResponse]): ) -> AsyncIterable[_TResponse] | UnaryStreamCall[_TRequest, _TResponse]: ... class StreamUnaryClientInterceptor(typing.Generic[_TRequest, _TResponse]): + @abc.abstractmethod async def intercept_stream_unary( self, continuation: Callable[[ClientCallDetails, _TRequest], StreamUnaryCall[_TRequest, _TResponse]], @@ -284,6 +319,7 @@ class StreamUnaryClientInterceptor(typing.Generic[_TRequest, _TResponse]): ) -> AsyncIterable[_TResponse] | UnaryStreamCall[_TRequest, _TResponse]: ... class StreamStreamClientInterceptor(typing.Generic[_TRequest, _TResponse]): + @abc.abstractmethod async def intercept_stream_stream( self, continuation: Callable[[ClientCallDetails, _TRequest], StreamStreamCall[_TRequest, _TResponse]], @@ -302,7 +338,7 @@ class ServerInterceptor(typing.Generic[_TRequest, _TResponse]): # Multi-Callable Interfaces: -class UnaryUnaryMultiCallable(typing.Generic[_TRequest, _TResponse]): +class UnaryUnaryMultiCallable(typing.Generic[_TRequest, _TResponse], metaclass=abc.ABCMeta): def __call__( self, request: _TRequest, @@ -314,7 +350,7 @@ class UnaryUnaryMultiCallable(typing.Generic[_TRequest, _TResponse]): compression: Compression | None = ..., ) -> UnaryUnaryCall[_TRequest, _TResponse]: ... -class UnaryStreamMultiCallable(typing.Generic[_TRequest, _TResponse]): +class UnaryStreamMultiCallable(typing.Generic[_TRequest, _TResponse], metaclass=abc.ABCMeta): def __call__( self, request: _TRequest, @@ -326,7 +362,7 @@ class UnaryStreamMultiCallable(typing.Generic[_TRequest, _TResponse]): compression: Compression | None = ..., ) -> UnaryStreamCall[_TRequest, _TResponse]: ... -class StreamUnaryMultiCallable(typing.Generic[_TRequest, _TResponse]): +class StreamUnaryMultiCallable(typing.Generic[_TRequest, _TResponse], metaclass=abc.ABCMeta): def __call__( self, request_iterator: AsyncIterator[_TRequest] | Iterator[_TRequest] | None, @@ -338,7 +374,7 @@ class StreamUnaryMultiCallable(typing.Generic[_TRequest, _TResponse]): compression: Compression | None = ..., ) -> StreamUnaryCall[_TRequest, _TResponse]: ... -class StreamStreamMultiCallable(typing.Generic[_TRequest, _TResponse]): +class StreamStreamMultiCallable(typing.Generic[_TRequest, _TResponse], metaclass=abc.ABCMeta): def __call__( self, request_iterator: AsyncIterator[_TRequest] | Iterator[_TRequest] | None,