From 80025f97f2ef8321711669d02d3ae428d4d90362 Mon Sep 17 00:00:00 2001 From: Leandro Lucarella Date: Wed, 4 Sep 2024 18:28:07 +0200 Subject: [PATCH 1/2] Improve the typing of the example in `BaseApiClient` The `mypy-protobuf` plugin generates a `XxxAsyncStub` class for each service, which have proper type information to be used with async. This still needs some hacks (type ignore) to make it work, but it's better than using the normal stubs and having to cast on each call. Signed-off-by: Leandro Lucarella --- src/frequenz/client/base/client.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/frequenz/client/base/client.py b/src/frequenz/client/base/client.py index ad47839..3e5176a 100644 --- a/src/frequenz/client/base/client.py +++ b/src/frequenz/client/base/client.py @@ -42,7 +42,9 @@ class BaseApiClient(abc.ABC, Generic[StubT]): from frequenz.client.base.streaming import GrpcStreamBroadcaster from frequenz.channels import Receiver - # These classes are normally generated by protoc + # These classes are normally generated by protoc, please use mypy-protobuf to + # get proper type checking and the XxxAsyncStub class (only for typing) + # generated. class ExampleRequest: int_value: int str_value: str @@ -51,6 +53,9 @@ class ExampleResponse: float_value: float class ExampleStub: + ... + + class ExampleAsyncStub: async def example_method( self, request: ExampleRequest # pylint: disable=unused-argument @@ -65,10 +70,14 @@ class ExampleResponseWrapper: def __init__(self, response: ExampleResponse): self.transformed_value = f"{response.float_value:.2f}" - class MyApiClient(BaseApiClient[ExampleStub]): + class MyApiClient(BaseApiClient[ExampleAsyncStub]): def __init__(self, server_url: str, *, connect: bool = True): super().__init__( - server_url, ExampleStub, connect=connect + server_url, + # We need to type ignore here because the generated normal and + # async stubs are not type-compatible with each other. + ExampleStub, # type: ignore[arg-type] + connect=connect ) self._broadcaster = GrpcStreamBroadcaster( "stream", From 19b5e8796b626c34acba5045361399ea20459c5b Mon Sep 17 00:00:00 2001 From: Leandro Lucarella Date: Wed, 4 Sep 2024 18:34:50 +0200 Subject: [PATCH 2/2] Add `channel_defaults` to the `BaseApiClient` example Signed-off-by: Leandro Lucarella --- src/frequenz/client/base/client.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/frequenz/client/base/client.py b/src/frequenz/client/base/client.py index 3e5176a..99f6596 100644 --- a/src/frequenz/client/base/client.py +++ b/src/frequenz/client/base/client.py @@ -70,14 +70,24 @@ class ExampleResponseWrapper: def __init__(self, response: ExampleResponse): self.transformed_value = f"{response.float_value:.2f}" + # Change defaults as needed + DEFAULT_CHANNEL_OPTIONS = ChannelOptions() + class MyApiClient(BaseApiClient[ExampleAsyncStub]): - def __init__(self, server_url: str, *, connect: bool = True): + def __init__( + self, + server_url: str, + *, + connect: bool = True, + channel_defaults: ChannelOptions = DEFAULT_CHANNEL_OPTIONS, + ) -> None: super().__init__( server_url, # We need to type ignore here because the generated normal and # async stubs are not type-compatible with each other. ExampleStub, # type: ignore[arg-type] - connect=connect + connect=connect, + channel_defaults=channel_defaults, ) self._broadcaster = GrpcStreamBroadcaster( "stream",