@@ -232,90 +232,6 @@ def sync_wrapper(self: Any, *args, **kwargs) -> Any:
232232 return decorator
233233
234234
235- def validate_async_generator (
236- expression : Callable [[Any ], bool ], error_message : str | None = None
237- ):
238- """Decorator that validates if a given expression evaluates to True for async generators.
239-
240- Typically used on class methods to check capabilities or configuration
241- before executing the method's logic. If the expression is False,
242- an `UnsupportedOperationError` is raised.
243-
244- Args:
245- expression: A callable that takes the instance (`self`) as its argument
246- and returns a boolean.
247- error_message: An optional custom error message for the `UnsupportedOperationError`.
248- If None, the string representation of the expression will be used.
249-
250- Examples:
251- Streaming capability validation with success case:
252- >>> import asyncio
253- >>> from a2a.utils.errors import UnsupportedOperationError
254- >>>
255- >>> class StreamingAgent:
256- ... def __init__(self, streaming_enabled: bool):
257- ... self.streaming_enabled = streaming_enabled
258- ...
259- ... @validate_async_generator(
260- ... lambda self: self.streaming_enabled,
261- ... 'Streaming is not supported by this agent',
262- ... )
263- ... async def stream_messages(self, count: int):
264- ... for i in range(count):
265- ... yield f'Message {i}'
266- >>>
267- >>> async def run_streaming_test():
268- ... # Successful streaming
269- ... agent = StreamingAgent(streaming_enabled=True)
270- ... async for msg in agent.stream_messages(2):
271- ... print(msg)
272- >>>
273- >>> asyncio.run(run_streaming_test())
274- Message 0
275- Message 1
276-
277- Error case - validation fails:
278- >>> class FeatureAgent:
279- ... def __init__(self):
280- ... self.features = {'real_time': False}
281- ...
282- ... @validate_async_generator(
283- ... lambda self: self.features.get('real_time', False),
284- ... 'Real-time feature must be enabled to stream updates',
285- ... )
286- ... async def real_time_updates(self):
287- ... yield 'This should not be yielded'
288- >>>
289- >>> async def run_error_test():
290- ... agent = FeatureAgent()
291- ... try:
292- ... async for _ in agent.real_time_updates():
293- ... pass
294- ... except UnsupportedOperationError as e:
295- ... print(e.message)
296- >>>
297- >>> asyncio.run(run_error_test())
298- Real-time feature must be enabled to stream updates
299-
300- Note:
301- This decorator is specifically for async generator methods (async def with yield).
302- The validation happens before the generator starts yielding values.
303- """
304-
305- def decorator (function ):
306- @functools .wraps (function )
307- def wrapper (self , * args , ** kwargs ):
308- if not expression (self ):
309- final_message = error_message or str (expression )
310- logger .error ('Unsupported Operation: %s' , final_message )
311- raise UnsupportedOperationError (message = final_message )
312- return function (self , * args , ** kwargs )
313-
314- return wrapper
315-
316- return decorator
317-
318-
319235def are_modalities_compatible (
320236 server_output_modes : list [str ] | None , client_output_modes : list [str ] | None
321237) -> bool :
0 commit comments