@@ -18,9 +18,11 @@ from typing_extensions import Annotated
1818{ {/imports} }
1919
2020from { {packageName} }.api_client import ApiClient, RequestSerialized
21+ from { {packageName} }.async_api_client import AsyncApiClient
2122from { {packageName} }.api_response import ApiResponse
2223from { {packageName} }.rest import RESTResponseType
2324from { {packageName} }.stream import Stream
25+ from { {packageName} }.async_stream import AsyncStream
2426from { {packageName} }.lib._utils import pascal_to_snake_case
2527
2628
@@ -339,5 +341,148 @@ class {{classname}}:
339341 { {alias} } = { {target} }
340342{ {/vendorExtensions.x-operation-aliases} }
341343
344+ { {/operation} }
345+
346+
347+ class Async{ {classname} }({ {classname} }):
348+ """Async version of { {classname} }.
349+
350+ Inherits serialization and deserialization from { {classname} }.
351+ Overrides HTTP methods to use async/await with AsyncApiClient.
352+ """
353+
354+ def __init__(self, api_client=None) -> None:
355+ if api_client is None:
356+ api_client = AsyncApiClient.get_default()
357+ self.api_client = api_client
358+ self.logger = logging.getLogger(Async{ {classname} }.__name__)
359+
360+ # Child API attributes (set by AsyncOgxClient based on x-nesting-path)
361+ { {#operation} }{ {#vendorExtensions.x-nesting-path} }{ {#-first} }{ {#tags} }{ {#-first} }{ {#vendorExtensions.x-nesting-path} }{ {^-last} } self.{ {.} }: Any | None = None # Next in nesting path
362+ { {/-last} }{ {/vendorExtensions.x-nesting-path} }{ {/-first} }{ {/tags} }{ {/-first} }{ {/vendorExtensions.x-nesting-path} }{ {/operation} }
363+
364+ def _create_event_stream(self, response_data: RESTResponseType, stream_type_name: str) -> AsyncStream[Any]:
365+ """Create a typed async event stream from an SSE response.
366+
367+ Args:
368+ response_data: The raw HTTP response containing the SSE stream.
369+ stream_type_name: The schema name for the streaming response type.
370+ """
371+ stream_class = None
372+ discriminator_map = None
373+ discriminator_property = None
374+ try:
375+ module_name = pascal_to_snake_case(stream_type_name)
376+ model_module = importlib.import_module('{ {packageName} }.models.' + module_name)
377+ stream_class = getattr(model_module, stream_type_name)
378+ discriminator_map = getattr(stream_class, 'discriminator_value_class_map', None)
379+ discriminator_property = getattr(stream_class, 'discriminator_property_name', None)
380+ except (ImportError, ModuleNotFoundError, AttributeError) as e:
381+ self.logger.debug(f"Could not import stream type { stream_type_name} : { e} ")
382+
383+ def stream_decoder(data_str: str) -> Any:
384+ if not data_str:
385+ return None
386+ try:
387+ data = json.loads(data_str)
388+ except json.JSONDecodeError:
389+ return data_str
390+
391+ if discriminator_map and discriminator_property:
392+ disc_value = data.get(discriminator_property, '')
393+ variant_class_name = discriminator_map.get(disc_value)
394+ if variant_class_name:
395+ try:
396+ variant_module_name = pascal_to_snake_case(variant_class_name)
397+ variant_module = importlib.import_module('{ {packageName} }.models.' + variant_module_name)
398+ variant_class = getattr(variant_module, variant_class_name)
399+ return variant_class.from_dict(data)
400+ except Exception as e:
401+ self.logger.debug(f"Failed to deserialize as { variant_class_name} : { e} ")
402+
403+ if stream_class is not None:
404+ try:
405+ result = stream_class.from_dict(data)
406+ if hasattr(result, 'actual_instance') and result.actual_instance is not None:
407+ return result.actual_instance
408+ return result
409+ except Exception as e:
410+ self.logger.debug(f"Failed to deserialize as { stream_type_name} : { e} ")
411+
412+ return data
413+
414+ return AsyncStream(
415+ response=response_data.response,
416+ client=self.api_client,
417+ decoder=stream_decoder,
418+ )
419+
420+ { {#operation} }
421+
422+ @validate_call
423+ async def {{#vendorExtensions.x-operation-name}}{{vendorExtensions.x-operation-name}}{{/vendorExtensions.x-operation-name}}{{^vendorExtensions.x-operation-name}}{{operationId}}{{/vendorExtensions.x-operation-name}}{{>partial_api_args}} -> {{#vendorExtensions.x-streaming}}{{#vendorExtensions.x-unwrap-list-response}}{{#returnType}}{{#returnContainer}}{{{returnBaseType}}} | AsyncStream[{{{returnBaseType}}}]{{/returnContainer}}{{^returnContainer}}{{{returnType}}} | AsyncStream[{{{returnType}}}]{{/returnContainer}}{{/returnType}}{{^returnType}}None | AsyncStream[None]{{/returnType}}{{/vendorExtensions.x-unwrap-list-response}}{{^vendorExtensions.x-unwrap-list-response}}{{{returnType}}}{{^returnType}}None{{/returnType}} | AsyncStream[{{{returnType}}}{{^returnType}}None{{/returnType}}]{{/vendorExtensions.x-unwrap-list-response}}{{/vendorExtensions.x-streaming}}{{^vendorExtensions.x-streaming}}{{#vendorExtensions.x-unwrap-list-response}}{{#returnType}}{{#returnContainer}}{{{returnBaseType}}}{{/returnContainer}}{{^returnContainer}}{{{returnType}}}{{/returnContainer}}{{/returnType}}{{^returnType}}None{{/returnType}}{{/vendorExtensions.x-unwrap-list-response}}{{^vendorExtensions.x-unwrap-list-response}}{{{returnType}}}{{^returnType}}None{{/returnType}}{{/vendorExtensions.x-unwrap-list-response}}{{/vendorExtensions.x-streaming}}:
424+ { {> partial_api} }
425+
426+ response_data = await self.api_client.call_api(
427+ *_param,
428+ _request_timeout=_request_timeout
429+ )
430+
431+ { {#vendorExtensions.x-streaming} }
432+ # Check if this is a streaming response
433+ content_type = response_data.response.headers.get('Content-Type', '')
434+ if 'text/event-stream' in content_type:
435+ return self._create_event_stream(response_data, "{ {vendorExtensions.x-streaming-type} }")
436+
437+ { {/vendorExtensions.x-streaming} }
438+ await response_data.aread()
439+ _deserialized = self.api_client.response_deserialize(
440+ response_data=response_data,
441+ response_types_map=_response_types_map,
442+ ).data
443+ # Unwrap List*Response wrappers to return the data field directly
444+ { {#vendorExtensions.x-unwrap-list-response} }
445+ if _deserialized is not None and hasattr(_deserialized, 'data'):
446+ return _deserialized.data
447+ { {/vendorExtensions.x-unwrap-list-response} }
448+ return _deserialized
449+
450+ @validate_call
451+ async def { {#vendorExtensions.x-operation-name} }{ {vendorExtensions.x-operation-name} }{ {/vendorExtensions.x-operation-name} }{ {^vendorExtensions.x-operation-name} }{ {operationId} }{ {/vendorExtensions.x-operation-name} }_with_http_info{ {> partial_api_args} } -> { {#vendorExtensions.x-streaming} }ApiResponse[{ {{returnType} }}{ {^returnType} }None{ {/returnType} }] | AsyncStream[{ {{returnType} }}{ {^returnType} }None{ {/returnType} }]{ {/vendorExtensions.x-streaming} }{ {^vendorExtensions.x-streaming} }ApiResponse[{ {{returnType} }}{ {^returnType} }None{ {/returnType} }]{ {/vendorExtensions.x-streaming} }:
452+ { {> partial_api} }
453+
454+ response_data = await self.api_client.call_api(
455+ *_param,
456+ _request_timeout=_request_timeout
457+ )
458+
459+ { {#vendorExtensions.x-streaming} }
460+ # Check if this is a streaming response
461+ content_type = response_data.response.headers.get('Content-Type', '')
462+ if 'text/event-stream' in content_type:
463+ return self._create_event_stream(response_data, "{ {vendorExtensions.x-streaming-type} }")
464+
465+ { {/vendorExtensions.x-streaming} }
466+ await response_data.aread()
467+ return self.api_client.response_deserialize(
468+ response_data=response_data,
469+ response_types_map=_response_types_map,
470+ )
471+
472+ @validate_call
473+ async def { {#vendorExtensions.x-operation-name} }{ {vendorExtensions.x-operation-name} }{ {/vendorExtensions.x-operation-name} }{ {^vendorExtensions.x-operation-name} }{ {operationId} }{ {/vendorExtensions.x-operation-name} }_without_preload_content{ {> partial_api_args} } -> RESTResponseType:
474+ { {> partial_api} }
475+
476+ response_data = await self.api_client.call_api(
477+ *_param,
478+ _request_timeout=_request_timeout
479+ )
480+ return response_data.response
481+
482+
483+ { {#vendorExtensions.x-operation-aliases} }
484+ { {alias} } = { {target} }
485+ { {/vendorExtensions.x-operation-aliases} }
486+
342487{ {/operation} }
343488{ {/operations} }
0 commit comments