diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 6ebf4395..8c48b285 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,5 +1,9 @@ # Frequenz Dispatch Client Library Release Notes +## New Features + +* Update BaseApiClient to get the http2 keepalive feature. + ## Bug Fixes * Fix crash by adding the missing YEARLY frequency. diff --git a/pyproject.toml b/pyproject.toml index e4a7a5c0..82f35d7a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -38,9 +38,9 @@ requires-python = ">= 3.11, < 4" dependencies = [ "typing-extensions >= 4.6.1, < 5", "frequenz-api-dispatch >= 0.15.1, < 0.16", - "frequenz-client-base >= 0.6.0, < 0.7.0", + "frequenz-client-base >= 0.7.0, < 0.8.0", "frequenz-client-common >= 0.1.0, < 0.3.0", - "grpcio >= 1.64.1, < 2", + "grpcio >= 1.66.1, < 2", ] dynamic = ["version"] @@ -151,6 +151,8 @@ disable = [ # pylint's unsubscriptable check is buggy and is not needed because # it is a type-check, for which we already have mypy. "unsubscriptable-object", + # Checked by mypy + "no-member", # Checked by flake8 "redefined-outer-name", "unused-import", diff --git a/src/frequenz/client/dispatch/__main__.py b/src/frequenz/client/dispatch/__main__.py index 92671e65..8b69526c 100644 --- a/src/frequenz/client/dispatch/__main__.py +++ b/src/frequenz/client/dispatch/__main__.py @@ -459,9 +459,9 @@ async def display_help() -> None: # Add recurrence options to the create command -create.params += recurrence_options # pylint: disable=no-member +create.params += recurrence_options # Add recurrence options to the update command -update.params += recurrence_options # pylint: disable=no-member +update.params += recurrence_options def main() -> None: diff --git a/src/frequenz/client/dispatch/_client.py b/src/frequenz/client/dispatch/_client.py index e2db9499..7126786c 100644 --- a/src/frequenz/client/dispatch/_client.py +++ b/src/frequenz/client/dispatch/_client.py @@ -2,6 +2,8 @@ # Copyright © 2024 Frequenz Energy-as-a-Service GmbH """Dispatch API client for Python.""" +from __future__ import annotations + from datetime import datetime, timedelta from importlib.resources import files from pathlib import Path @@ -33,6 +35,7 @@ from frequenz.client.base.channel import ChannelOptions, SslOptions from frequenz.client.base.client import BaseApiClient from frequenz.client.base.conversion import to_timestamp +from frequenz.client.base.exception import ClientNotConnected from frequenz.client.base.retry import LinearBackoff from frequenz.client.base.streaming import GrpcStreamBroadcaster @@ -49,7 +52,7 @@ DEFAULT_DISPATCH_PORT = 50051 -class Client(BaseApiClient[dispatch_pb2_grpc.MicrogridDispatchServiceStub]): +class Client(BaseApiClient): """Dispatch API client.""" streams: dict[ @@ -73,7 +76,6 @@ def __init__( """ super().__init__( server_url, - dispatch_pb2_grpc.MicrogridDispatchServiceStub, connect=connect, channel_defaults=ChannelOptions( port=DEFAULT_DISPATCH_PORT, @@ -88,6 +90,20 @@ def __init__( ), ) self._metadata = (("key", key),) + self._setup_stub() + + def _setup_stub(self) -> None: + self._stub = cast( + dispatch_pb2_grpc.MicrogridDispatchServiceAsyncStub, + dispatch_pb2_grpc.MicrogridDispatchServiceStub(self.channel), + ) + + @property + def stub(self) -> dispatch_pb2_grpc.MicrogridDispatchServiceAsyncStub: + """The stub for the service.""" + if self._channel is None: + raise ClientNotConnected(server_url=self.server_url, operation="stub") + return self._stub # pylint: disable=too-many-arguments, too-many-locals async def list( diff --git a/src/frequenz/client/dispatch/test/client.py b/src/frequenz/client/dispatch/test/client.py index 8c755aaa..ba12a074 100644 --- a/src/frequenz/client/dispatch/test/client.py +++ b/src/frequenz/client/dispatch/test/client.py @@ -34,6 +34,9 @@ def stub(self) -> FakeService: # type: ignore """ return self._stuba + def _setup_stub(self) -> None: + """Empty body because no setup needed.""" + def dispatches(self, microgrid_id: int) -> list[Dispatch]: """List of dispatches.