From b960f682fb35e207a47398a34083940aba583624 Mon Sep 17 00:00:00 2001 From: Pankaj Kumar Bind Date: Tue, 12 Aug 2025 20:08:54 +0530 Subject: [PATCH 1/4] feat: Add validation for transport types in ClientFactory --- src/a2a/client/client_factory.py | 10 +++++++++- tests/client/test_client_factory.py | 16 ++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/a2a/client/client_factory.py b/src/a2a/client/client_factory.py index c568331f..5bb97c07 100644 --- a/src/a2a/client/client_factory.py +++ b/src/a2a/client/client_factory.py @@ -91,7 +91,7 @@ def _register_defaults( if GrpcTransport is None: raise ImportError( 'To use GrpcClient, its dependencies must be installed. ' - 'You can install them with \'pip install "a2a-sdk[grpc]"\'' + 'You can install them with \'pip install "a2a-sdk[grpc]"\'', ) self.register( TransportProtocol.grpc, @@ -124,6 +124,14 @@ def create( If there is no valid matching of the client configuration with the server configuration, a `ValueError` is raised. """ + valid_transports = {member.value for member in TransportProtocol} + for transport in self._config.supported_transports: + if transport not in valid_transports: + raise ValueError( + f"Unsupported transport type in ClientConfig: '{transport}'. " + f'Valid types are: {", ".join(sorted(valid_transports))}', + ) + server_preferred = card.preferred_transport or TransportProtocol.jsonrpc server_set = {server_preferred: card.url} if card.additional_interfaces: diff --git a/tests/client/test_client_factory.py b/tests/client/test_client_factory.py index d615bbff..1085a05b 100644 --- a/tests/client/test_client_factory.py +++ b/tests/client/test_client_factory.py @@ -103,3 +103,19 @@ def test_client_factory_no_compatible_transport(base_agent_card: AgentCard): factory = ClientFactory(config) with pytest.raises(ValueError, match='no compatible transports found'): factory.create(base_agent_card) + + +def test_client_factory_invalid_transport_in_config(base_agent_card: AgentCard): + """Verify that the factory raises an error for an unknown transport type.""" + config = ClientConfig( + httpx_client=httpx.AsyncClient(), + supported_transports=[ + TransportProtocol.jsonrpc, + 'invalid-transport-protocol', + ], + ) + factory = ClientFactory(config) + with pytest.raises( + ValueError, match='Unsupported transport type in ClientConfig' + ): + factory.create(base_agent_card) From 16b40a42f6c63e2df1692367759fa2976e3d7607 Mon Sep 17 00:00:00 2001 From: Pankaj Kumar Bind <73558583+pankaj-bind@users.noreply.github.com> Date: Tue, 12 Aug 2025 20:16:59 +0530 Subject: [PATCH 2/4] Update src/a2a/client/client_factory.py Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- src/a2a/client/client_factory.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/a2a/client/client_factory.py b/src/a2a/client/client_factory.py index 5bb97c07..947d5688 100644 --- a/src/a2a/client/client_factory.py +++ b/src/a2a/client/client_factory.py @@ -125,12 +125,16 @@ def create( server configuration, a `ValueError` is raised. """ valid_transports = {member.value for member in TransportProtocol} - for transport in self._config.supported_transports: - if transport not in valid_transports: - raise ValueError( - f"Unsupported transport type in ClientConfig: '{transport}'. " - f'Valid types are: {", ".join(sorted(valid_transports))}', - ) + configured_transports = set(self._config.supported_transports) + + invalid_transports = configured_transports.difference(valid_transports) + if invalid_transports: + invalid_str = ", ".join(sorted(f"'{t}'" for t in invalid_transports)) + valid_str = ", ".join(sorted(valid_transports)) + raise ValueError( + f"Unsupported transport type(s) in ClientConfig: {invalid_str}. " + f"Valid types are: {valid_str}" + ) server_preferred = card.preferred_transport or TransportProtocol.jsonrpc server_set = {server_preferred: card.url} From 86e3f97b770be91f558979641950ac17584c0767 Mon Sep 17 00:00:00 2001 From: Pankaj Kumar Bind <73558583+pankaj-bind@users.noreply.github.com> Date: Tue, 12 Aug 2025 20:21:35 +0530 Subject: [PATCH 3/4] Update test_client_factory.py --- tests/client/test_client_factory.py | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/tests/client/test_client_factory.py b/tests/client/test_client_factory.py index 1085a05b..2f1ab9b8 100644 --- a/tests/client/test_client_factory.py +++ b/tests/client/test_client_factory.py @@ -105,17 +105,31 @@ def test_client_factory_no_compatible_transport(base_agent_card: AgentCard): factory.create(base_agent_card) -def test_client_factory_invalid_transport_in_config(base_agent_card: AgentCard): - """Verify that the factory raises an error for an unknown transport type.""" +@pytest.mark.parametrize( + ('invalid_transports', 'expected_match'), + [ + ( + ['invalid-transport'], + "Unsupported transport type\\(s\\) in ClientConfig: 'invalid-transport'", + ), + ( + ['invalid-1', 'another-bad-one'], + "Unsupported transport type\\(s\\) in ClientConfig: 'another-bad-one', 'invalid-1'", + ), + ], +) +def test_client_factory_invalid_transport_in_config( + base_agent_card: AgentCard, invalid_transports, expected_match +): + """Verify that the factory raises an error for unknown transport types.""" config = ClientConfig( httpx_client=httpx.AsyncClient(), supported_transports=[ TransportProtocol.jsonrpc, - 'invalid-transport-protocol', + *invalid_transports, ], ) factory = ClientFactory(config) - with pytest.raises( - ValueError, match='Unsupported transport type in ClientConfig' - ): + with pytest.raises(ValueError, match=expected_match): factory.create(base_agent_card) + From dce5b16903c121813195c8a8cadcb91941443675 Mon Sep 17 00:00:00 2001 From: Pankaj Kumar Bind Date: Tue, 12 Aug 2025 20:56:39 +0530 Subject: [PATCH 4/4] fix lint issue --- src/a2a/client/client_factory.py | 10 ++++++---- tests/client/test_client_factory.py | 1 - 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/a2a/client/client_factory.py b/src/a2a/client/client_factory.py index 947d5688..57926a8a 100644 --- a/src/a2a/client/client_factory.py +++ b/src/a2a/client/client_factory.py @@ -129,11 +129,13 @@ def create( invalid_transports = configured_transports.difference(valid_transports) if invalid_transports: - invalid_str = ", ".join(sorted(f"'{t}'" for t in invalid_transports)) - valid_str = ", ".join(sorted(valid_transports)) + invalid_str = ', '.join( + sorted(f"'{t}'" for t in invalid_transports) + ) + valid_str = ', '.join(sorted(valid_transports)) raise ValueError( - f"Unsupported transport type(s) in ClientConfig: {invalid_str}. " - f"Valid types are: {valid_str}" + f'Unsupported transport type(s) in ClientConfig: {invalid_str}. ' + f'Valid types are: {valid_str}' ) server_preferred = card.preferred_transport or TransportProtocol.jsonrpc diff --git a/tests/client/test_client_factory.py b/tests/client/test_client_factory.py index 2f1ab9b8..a1f88214 100644 --- a/tests/client/test_client_factory.py +++ b/tests/client/test_client_factory.py @@ -132,4 +132,3 @@ def test_client_factory_invalid_transport_in_config( factory = ClientFactory(config) with pytest.raises(ValueError, match=expected_match): factory.create(base_agent_card) -