From dc5b953a3396c8048e287f2a79b0d5122cf39214 Mon Sep 17 00:00:00 2001 From: Carlos Chinchilla Corbacho <188046461+cchinchilla-dev@users.noreply.github.com> Date: Fri, 20 Feb 2026 20:00:45 +0100 Subject: [PATCH 1/3] feat(client): expose close() and async context manager support on abstract Client --- src/a2a/client/client.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/a2a/client/client.py b/src/a2a/client/client.py index cad49173d..785018d04 100644 --- a/src/a2a/client/client.py +++ b/src/a2a/client/client.py @@ -3,8 +3,11 @@ from abc import ABC, abstractmethod from collections.abc import AsyncIterator, Callable, Coroutine +from types import TracebackType from typing import Any +from typing_extensions import Self + import httpx from a2a.client.middleware import ClientCallContext, ClientCallInterceptor @@ -106,6 +109,19 @@ def __init__( self._consumers = consumers self._middleware = middleware + async def __aenter__(self) -> Self: + """Enters the async context manager.""" + return self + + async def __aexit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> None: + """Exits the async context manager and closes the client.""" + await self.close() + @abstractmethod async def send_message( self, @@ -217,3 +233,7 @@ async def consume( return for c in self._consumers: await c(event, card) + + @abstractmethod + async def close(self) -> None: + """Closes the client and releases any underlying resources.""" \ No newline at end of file From e29ec70b995ccf49b15693337ffefabbe22c0ac8 Mon Sep 17 00:00:00 2001 From: Carlos Chinchilla Corbacho <188046461+cchinchilla-dev@users.noreply.github.com> Date: Fri, 20 Feb 2026 20:06:49 +0100 Subject: [PATCH 2/3] feat(client): expose close() and async context manager support on abstract Client (lint) --- src/a2a/client/client.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/a2a/client/client.py b/src/a2a/client/client.py index 785018d04..b698a7699 100644 --- a/src/a2a/client/client.py +++ b/src/a2a/client/client.py @@ -6,10 +6,10 @@ from types import TracebackType from typing import Any -from typing_extensions import Self - import httpx +from typing_extensions import Self + from a2a.client.middleware import ClientCallContext, ClientCallInterceptor from a2a.client.optionals import Channel from a2a.types.a2a_pb2 import ( @@ -236,4 +236,4 @@ async def consume( @abstractmethod async def close(self) -> None: - """Closes the client and releases any underlying resources.""" \ No newline at end of file + """Closes the client and releases any underlying resources.""" From 9b4d19d3303a00208dfcc5dc6822d830433cfa56 Mon Sep 17 00:00:00 2001 From: Carlos Chinchilla Corbacho <188046461+cchinchilla-dev@users.noreply.github.com> Date: Tue, 24 Feb 2026 22:39:57 +0100 Subject: [PATCH 3/3] feat(client): remove __aenter__ and __aexit__ from BaseClient --- src/a2a/client/base_client.py | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/src/a2a/client/base_client.py b/src/a2a/client/base_client.py index 657e78aca..eadfdb625 100644 --- a/src/a2a/client/base_client.py +++ b/src/a2a/client/base_client.py @@ -1,9 +1,6 @@ from collections.abc import AsyncGenerator, AsyncIterator, Callable -from types import TracebackType from typing import Any -from typing_extensions import Self - from a2a.client.client import ( Client, ClientCallContext, @@ -48,19 +45,6 @@ def __init__( self._config = config self._transport = transport - async def __aenter__(self) -> Self: - """Enters the async context manager, returning the client itself.""" - return self - - async def __aexit__( - self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: TracebackType | None, - ) -> None: - """Exits the async context manager, ensuring close() is called.""" - await self.close() - async def send_message( self, request: Message,