From f9761eb95f5235c4b2e506b1f29d06aca2ca36ed Mon Sep 17 00:00:00 2001 From: API Engineering Date: Fri, 16 Oct 2026 08:53:30 +0000 Subject: [PATCH] [bot] Updated client based on openapi-840dc60/clientgen --- DO_OPENAPI_COMMIT_SHA.txt | 2 +- .../pydo.resources.aio.inference.audio.rst | 21 + .../pydo.resources.aio.inference.videos.rst | 21 + .../source/pydo.resources.inference.audio.rst | 21 + .../pydo.resources.inference.videos.rst | 21 + docs/source/pydo.types.audio.rst | 10 + docs/source/pydo.types.videos.rst | 10 + src/pydo/aio/operations/_operations.py | 653 ++++++++++++++++ src/pydo/inference/__init__.py | 1 + src/pydo/inference/aio/__init__.py | 1 + src/pydo/operations/_operations.py | 733 ++++++++++++++++++ src/pydo/resources/aio/inference/__init__.py | 4 + .../resources/aio/inference/audio/__init__.py | 20 + .../resources/aio/inference/audio/speech.py | 33 + .../aio/inference/videos/__init__.py | 48 ++ .../resources/aio/inference/videos/content.py | 32 + src/pydo/resources/client_surface.py | 12 + src/pydo/resources/inference/__init__.py | 4 + .../resources/inference/audio/__init__.py | 20 + src/pydo/resources/inference/audio/speech.py | 33 + .../resources/inference/videos/__init__.py | 48 ++ .../resources/inference/videos/content.py | 32 + src/pydo/resources/inference_surface.json | 48 ++ src/pydo/types/__init__.py | 8 + src/pydo/types/audio/__init__.py | 26 + src/pydo/types/videos/__init__.py | 34 + 26 files changed, 1895 insertions(+), 1 deletion(-) create mode 100644 docs/source/pydo.resources.aio.inference.audio.rst create mode 100644 docs/source/pydo.resources.aio.inference.videos.rst create mode 100644 docs/source/pydo.resources.inference.audio.rst create mode 100644 docs/source/pydo.resources.inference.videos.rst create mode 100644 docs/source/pydo.types.audio.rst create mode 100644 docs/source/pydo.types.videos.rst create mode 100644 src/pydo/resources/aio/inference/audio/__init__.py create mode 100644 src/pydo/resources/aio/inference/audio/speech.py create mode 100644 src/pydo/resources/aio/inference/videos/__init__.py create mode 100644 src/pydo/resources/aio/inference/videos/content.py create mode 100644 src/pydo/resources/inference/audio/__init__.py create mode 100644 src/pydo/resources/inference/audio/speech.py create mode 100644 src/pydo/resources/inference/videos/__init__.py create mode 100644 src/pydo/resources/inference/videos/content.py create mode 100644 src/pydo/types/audio/__init__.py create mode 100644 src/pydo/types/videos/__init__.py diff --git a/DO_OPENAPI_COMMIT_SHA.txt b/DO_OPENAPI_COMMIT_SHA.txt index 5c897da7..4d11efc9 100644 --- a/DO_OPENAPI_COMMIT_SHA.txt +++ b/DO_OPENAPI_COMMIT_SHA.txt @@ -1 +1 @@ -380d7ee +840dc60 diff --git a/docs/source/pydo.resources.aio.inference.audio.rst b/docs/source/pydo.resources.aio.inference.audio.rst new file mode 100644 index 00000000..53b01025 --- /dev/null +++ b/docs/source/pydo.resources.aio.inference.audio.rst @@ -0,0 +1,21 @@ +pydo.resources.aio.inference.audio package +========================================== + +Submodules +---------- + +pydo.resources.aio.inference.audio.speech module +------------------------------------------------ + +.. automodule:: pydo.resources.aio.inference.audio.speech + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: pydo.resources.aio.inference.audio + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/pydo.resources.aio.inference.videos.rst b/docs/source/pydo.resources.aio.inference.videos.rst new file mode 100644 index 00000000..a4fc12f0 --- /dev/null +++ b/docs/source/pydo.resources.aio.inference.videos.rst @@ -0,0 +1,21 @@ +pydo.resources.aio.inference.videos package +=========================================== + +Submodules +---------- + +pydo.resources.aio.inference.videos.content module +-------------------------------------------------- + +.. automodule:: pydo.resources.aio.inference.videos.content + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: pydo.resources.aio.inference.videos + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/pydo.resources.inference.audio.rst b/docs/source/pydo.resources.inference.audio.rst new file mode 100644 index 00000000..4428a496 --- /dev/null +++ b/docs/source/pydo.resources.inference.audio.rst @@ -0,0 +1,21 @@ +pydo.resources.inference.audio package +====================================== + +Submodules +---------- + +pydo.resources.inference.audio.speech module +-------------------------------------------- + +.. automodule:: pydo.resources.inference.audio.speech + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: pydo.resources.inference.audio + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/pydo.resources.inference.videos.rst b/docs/source/pydo.resources.inference.videos.rst new file mode 100644 index 00000000..3bfa31fd --- /dev/null +++ b/docs/source/pydo.resources.inference.videos.rst @@ -0,0 +1,21 @@ +pydo.resources.inference.videos package +======================================= + +Submodules +---------- + +pydo.resources.inference.videos.content module +---------------------------------------------- + +.. automodule:: pydo.resources.inference.videos.content + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: pydo.resources.inference.videos + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/pydo.types.audio.rst b/docs/source/pydo.types.audio.rst new file mode 100644 index 00000000..2cda1b65 --- /dev/null +++ b/docs/source/pydo.types.audio.rst @@ -0,0 +1,10 @@ +pydo.types.audio package +======================== + +Module contents +--------------- + +.. automodule:: pydo.types.audio + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/pydo.types.videos.rst b/docs/source/pydo.types.videos.rst new file mode 100644 index 00000000..c35963b4 --- /dev/null +++ b/docs/source/pydo.types.videos.rst @@ -0,0 +1,10 @@ +pydo.types.videos package +========================= + +Module contents +--------------- + +.. automodule:: pydo.types.videos + :members: + :undoc-members: + :show-inheritance: diff --git a/src/pydo/aio/operations/_operations.py b/src/pydo/aio/operations/_operations.py index 6fbc0da9..3d1d118a 100644 --- a/src/pydo/aio/operations/_operations.py +++ b/src/pydo/aio/operations/_operations.py @@ -486,9 +486,13 @@ build_inference_create_image_request, build_inference_create_messages_request, build_inference_create_response_request, + build_inference_create_speech_request, build_inference_create_systemone_request, + build_inference_create_video_request, build_inference_get_batch_request, build_inference_get_batch_results_request, + build_inference_get_video_content_request, + build_inference_get_video_request, build_inference_list_batches_request, build_inference_list_models_request, build_inference_upload_batch_file_request, @@ -342499,6 +342503,655 @@ async def create_async_invoke( return cast(JSON, deserialized) # type: ignore + @overload + async def create_speech( + self, body: JSON, *, content_type: str = "application/json", **kwargs: Any + ) -> Union[JSON, AsyncIterator[bytes]]: + # pylint: disable=line-too-long + """Generate speech from text. + + Convert text input to speech audio. The response may be raw audio bytes (\\ ``audio/mpeg``\\ , + ``audio/wav``\\ , and similar) or a JSON envelope with base64-encoded audio in + ``data[].b64_json``. + + :param body: Required. + :type body: JSON + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :return: JSON object or AsyncIterator[bytes] + :rtype: JSON or AsyncIterator[bytes] + :raises ~azure.core.exceptions.HttpResponseError: + + Example: + .. code-block:: python + + # JSON input template you can fill out and use as your body input. + body = { + "input": "str", # The text to convert to speech. Required. + "model": "str", # The text-to-speech model to use. Required. + "instructions": "str", # Optional. Optional style or delivery instructions + for the synthesizer. + "response_format": "str", # Optional. The audio format to return. Supported + values include ``mp3`` and ``wav``. The API may return raw audio bytes or a JSON + envelope with base64-encoded audio. + "voice": "str" # Optional. The voice to use for synthesis. + } + + # response body for status code(s): 200 + response == { + "data": [ + { + "b64_json": "str" # Base64-encoded audio bytes. Required. + } + ], + "created": 0 # Optional. Unix timestamp (in seconds) of when the audio was + created. + } + """ + + @overload + async def create_speech( + self, body: IO[bytes], *, content_type: str = "application/json", **kwargs: Any + ) -> Union[JSON, AsyncIterator[bytes]]: + """Generate speech from text. + + Convert text input to speech audio. The response may be raw audio bytes (\\ ``audio/mpeg``\\ , + ``audio/wav``\\ , and similar) or a JSON envelope with base64-encoded audio in + ``data[].b64_json``. + + :param body: Required. + :type body: IO[bytes] + :keyword content_type: Body Parameter content-type. Content type parameter for binary body. + Default value is "application/json". + :paramtype content_type: str + :return: JSON object or AsyncIterator[bytes] + :rtype: JSON or AsyncIterator[bytes] + :raises ~azure.core.exceptions.HttpResponseError: + + Example: + .. code-block:: python + + # response body for status code(s): 200 + response == { + "data": [ + { + "b64_json": "str" # Base64-encoded audio bytes. Required. + } + ], + "created": 0 # Optional. Unix timestamp (in seconds) of when the audio was + created. + } + """ + + @distributed_trace_async + async def create_speech( + self, body: Union[JSON, IO[bytes]], **kwargs: Any + ) -> Union[JSON, AsyncIterator[bytes]]: + # pylint: disable=line-too-long + """Generate speech from text. + + Convert text input to speech audio. The response may be raw audio bytes (\\ ``audio/mpeg``\\ , + ``audio/wav``\\ , and similar) or a JSON envelope with base64-encoded audio in + ``data[].b64_json``. + + :param body: Is either a JSON type or a IO[bytes] type. Required. + :type body: JSON or IO[bytes] + :return: JSON object or AsyncIterator[bytes] + :rtype: JSON or AsyncIterator[bytes] + :raises ~azure.core.exceptions.HttpResponseError: + + Example: + .. code-block:: python + + # JSON input template you can fill out and use as your body input. + body = { + "input": "str", # The text to convert to speech. Required. + "model": "str", # The text-to-speech model to use. Required. + "instructions": "str", # Optional. Optional style or delivery instructions + for the synthesizer. + "response_format": "str", # Optional. The audio format to return. Supported + values include ``mp3`` and ``wav``. The API may return raw audio bytes or a JSON + envelope with base64-encoded audio. + "voice": "str" # Optional. The voice to use for synthesis. + } + + # response body for status code(s): 200 + response == { + "data": [ + { + "b64_json": "str" # Base64-encoded audio bytes. Required. + } + ], + "created": 0 # Optional. Unix timestamp (in seconds) of when the audio was + created. + } + """ + error_map: MutableMapping[int, Type[HttpResponseError]] = { + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + 401: cast( + Type[HttpResponseError], + lambda response: ClientAuthenticationError(response=response), + ), + 429: HttpResponseError, + 500: HttpResponseError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _params = kwargs.pop("params", {}) or {} + + content_type: Optional[str] = kwargs.pop( + "content_type", _headers.pop("Content-Type", None) + ) + cls: ClsType[Union[JSON, AsyncIterator[bytes]]] = kwargs.pop("cls", None) + + content_type = content_type or "application/json" + _json = None + _content = None + if isinstance(body, (IOBase, bytes)): + _content = body + else: + _json = body + + _request = build_inference_create_speech_request( + content_type=content_type, + json=_json, + content=_content, + headers=_headers, + params=_params, + ) + _request.url = self._client.format_url(_request.url) + + _stream = True + pipeline_response: PipelineResponse = ( + await self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + ) + + response = pipeline_response.http_response + + if response.status_code not in [200, 200]: + if _stream: + await response.read() # Load the body in memory and close the socket + map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore + raise HttpResponseError(response=response) + + response_headers = {} + if response.status_code == 200: + response_headers["ratelimit-limit"] = self._deserialize( + "int", response.headers.get("ratelimit-limit") + ) + response_headers["ratelimit-remaining"] = self._deserialize( + "int", response.headers.get("ratelimit-remaining") + ) + response_headers["ratelimit-reset"] = self._deserialize( + "int", response.headers.get("ratelimit-reset") + ) + + deserialized = response.iter_bytes() + + if response.status_code == 200: + response_headers["ratelimit-limit"] = self._deserialize( + "int", response.headers.get("ratelimit-limit") + ) + response_headers["ratelimit-remaining"] = self._deserialize( + "int", response.headers.get("ratelimit-remaining") + ) + response_headers["ratelimit-reset"] = self._deserialize( + "int", response.headers.get("ratelimit-reset") + ) + + deserialized = response.iter_bytes() + + if cls: + return cls(pipeline_response, cast(Union[JSON, AsyncIterator[bytes]], deserialized), response_headers) # type: ignore + + return cast(Union[JSON, AsyncIterator[bytes]], deserialized) # type: ignore + + @overload + async def create_video( + self, body: JSON, *, content_type: str = "application/json", **kwargs: Any + ) -> JSON: + # pylint: disable=line-too-long + """Start a video generation job. + + Start an asynchronous video generation job from a text prompt. Poll ``GET + /v1/videos/{video_id}`` until the job reaches a terminal status, then download the MP4 with + ``GET /v1/videos/{video_id}/content`` or from ``output.url`` when present. + + :param body: Required. + :type body: JSON + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :return: JSON object + :rtype: JSON + :raises ~azure.core.exceptions.HttpResponseError: + + Example: + .. code-block:: python + + # JSON input template you can fill out and use as your body input. + body = { + "model": "str", # The video generation model to use. Required. + "prompt": "str", # A text description of the desired video. Required. + "fps": 0, # Optional. Frames per second for the generated video. + "size": "str" # Optional. The output resolution, for example ``1280x720``. + } + + # response body for status code(s): 200 + response == { + "id": "str", # The video generation job identifier. Required. + "status": "str", # Job status. Poll until the value is a terminal state such + as ``completed`` or ``failed``. Required. + "created_at": 0, # Optional. Unix timestamp (in seconds) of when the job was + created. + "error": { + "str": {} # Optional. Error details when status is ``failed``. + }, + "model": "str", # Optional. The model used for generation. + "object": "str", # Optional. Object type returned by the API. + "output": { + "url": "str" # Optional. Presigned URL for the generated MP4. + }, + "x_request_id": "str" # Optional. Request correlation identifier when + provided by the API. + } + """ + + @overload + async def create_video( + self, body: IO[bytes], *, content_type: str = "application/json", **kwargs: Any + ) -> JSON: + # pylint: disable=line-too-long + """Start a video generation job. + + Start an asynchronous video generation job from a text prompt. Poll ``GET + /v1/videos/{video_id}`` until the job reaches a terminal status, then download the MP4 with + ``GET /v1/videos/{video_id}/content`` or from ``output.url`` when present. + + :param body: Required. + :type body: IO[bytes] + :keyword content_type: Body Parameter content-type. Content type parameter for binary body. + Default value is "application/json". + :paramtype content_type: str + :return: JSON object + :rtype: JSON + :raises ~azure.core.exceptions.HttpResponseError: + + Example: + .. code-block:: python + + # response body for status code(s): 200 + response == { + "id": "str", # The video generation job identifier. Required. + "status": "str", # Job status. Poll until the value is a terminal state such + as ``completed`` or ``failed``. Required. + "created_at": 0, # Optional. Unix timestamp (in seconds) of when the job was + created. + "error": { + "str": {} # Optional. Error details when status is ``failed``. + }, + "model": "str", # Optional. The model used for generation. + "object": "str", # Optional. Object type returned by the API. + "output": { + "url": "str" # Optional. Presigned URL for the generated MP4. + }, + "x_request_id": "str" # Optional. Request correlation identifier when + provided by the API. + } + """ + + @distributed_trace_async + async def create_video(self, body: Union[JSON, IO[bytes]], **kwargs: Any) -> JSON: + # pylint: disable=line-too-long + """Start a video generation job. + + Start an asynchronous video generation job from a text prompt. Poll ``GET + /v1/videos/{video_id}`` until the job reaches a terminal status, then download the MP4 with + ``GET /v1/videos/{video_id}/content`` or from ``output.url`` when present. + + :param body: Is either a JSON type or a IO[bytes] type. Required. + :type body: JSON or IO[bytes] + :return: JSON object + :rtype: JSON + :raises ~azure.core.exceptions.HttpResponseError: + + Example: + .. code-block:: python + + # JSON input template you can fill out and use as your body input. + body = { + "model": "str", # The video generation model to use. Required. + "prompt": "str", # A text description of the desired video. Required. + "fps": 0, # Optional. Frames per second for the generated video. + "size": "str" # Optional. The output resolution, for example ``1280x720``. + } + + # response body for status code(s): 200 + response == { + "id": "str", # The video generation job identifier. Required. + "status": "str", # Job status. Poll until the value is a terminal state such + as ``completed`` or ``failed``. Required. + "created_at": 0, # Optional. Unix timestamp (in seconds) of when the job was + created. + "error": { + "str": {} # Optional. Error details when status is ``failed``. + }, + "model": "str", # Optional. The model used for generation. + "object": "str", # Optional. Object type returned by the API. + "output": { + "url": "str" # Optional. Presigned URL for the generated MP4. + }, + "x_request_id": "str" # Optional. Request correlation identifier when + provided by the API. + } + """ + error_map: MutableMapping[int, Type[HttpResponseError]] = { + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + 401: cast( + Type[HttpResponseError], + lambda response: ClientAuthenticationError(response=response), + ), + 429: HttpResponseError, + 500: HttpResponseError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _params = kwargs.pop("params", {}) or {} + + content_type: Optional[str] = kwargs.pop( + "content_type", _headers.pop("Content-Type", None) + ) + cls: ClsType[JSON] = kwargs.pop("cls", None) + + content_type = content_type or "application/json" + _json = None + _content = None + if isinstance(body, (IOBase, bytes)): + _content = body + else: + _json = body + + _request = build_inference_create_video_request( + content_type=content_type, + json=_json, + content=_content, + headers=_headers, + params=_params, + ) + _request.url = self._client.format_url(_request.url) + + _stream = False + pipeline_response: PipelineResponse = ( + await self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + ) + + response = pipeline_response.http_response + + if response.status_code not in [200]: + if _stream: + await response.read() # Load the body in memory and close the socket + map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore + raise HttpResponseError(response=response) + + response_headers = {} + response_headers["ratelimit-limit"] = self._deserialize( + "int", response.headers.get("ratelimit-limit") + ) + response_headers["ratelimit-remaining"] = self._deserialize( + "int", response.headers.get("ratelimit-remaining") + ) + response_headers["ratelimit-reset"] = self._deserialize( + "int", response.headers.get("ratelimit-reset") + ) + + if response.content: + deserialized = response.json() + else: + deserialized = None + + if cls: + return cls(pipeline_response, cast(JSON, deserialized), response_headers) # type: ignore + + return cast(JSON, deserialized) # type: ignore + + @distributed_trace_async + async def get_video(self, video_id: str, **kwargs: Any) -> JSON: + # pylint: disable=line-too-long + """Retrieve a video generation job. + + Returns the current state of a video generation job. Poll until ``status`` reaches a terminal + value such as ``completed`` or ``failed``. + + :param video_id: The video generation job identifier. Required. + :type video_id: str + :return: JSON object + :rtype: JSON + :raises ~azure.core.exceptions.HttpResponseError: + + Example: + .. code-block:: python + + # response body for status code(s): 200 + response == { + "id": "str", # The video generation job identifier. Required. + "status": "str", # Job status. Poll until the value is a terminal state such + as ``completed`` or ``failed``. Required. + "created_at": 0, # Optional. Unix timestamp (in seconds) of when the job was + created. + "error": { + "str": {} # Optional. Error details when status is ``failed``. + }, + "model": "str", # Optional. The model used for generation. + "object": "str", # Optional. Object type returned by the API. + "output": { + "url": "str" # Optional. Presigned URL for the generated MP4. + }, + "x_request_id": "str" # Optional. Request correlation identifier when + provided by the API. + } + # response body for status code(s): 404 + response == { + "id": "str", # A short identifier corresponding to the HTTP status code + returned. For example, the ID for a response returning a 404 status code would + be "not_found.". Required. + "message": "str", # A message providing additional information about the + error, including details to help resolve it when possible. Required. + "request_id": "str" # Optional. Optionally, some endpoints may include a + request ID that should be provided when reporting bugs or opening support + tickets to help identify the issue. + } + """ + error_map: MutableMapping[int, Type[HttpResponseError]] = { + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + 401: cast( + Type[HttpResponseError], + lambda response: ClientAuthenticationError(response=response), + ), + 429: HttpResponseError, + 500: HttpResponseError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} + + cls: ClsType[JSON] = kwargs.pop("cls", None) + + _request = build_inference_get_video_request( + video_id=video_id, + headers=_headers, + params=_params, + ) + _request.url = self._client.format_url(_request.url) + + _stream = False + pipeline_response: PipelineResponse = ( + await self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + ) + + response = pipeline_response.http_response + + if response.status_code not in [200, 404]: + if _stream: + await response.read() # Load the body in memory and close the socket + map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore + raise HttpResponseError(response=response) + + response_headers = {} + if response.status_code == 200: + response_headers["ratelimit-limit"] = self._deserialize( + "int", response.headers.get("ratelimit-limit") + ) + response_headers["ratelimit-remaining"] = self._deserialize( + "int", response.headers.get("ratelimit-remaining") + ) + response_headers["ratelimit-reset"] = self._deserialize( + "int", response.headers.get("ratelimit-reset") + ) + + if response.content: + deserialized = response.json() + else: + deserialized = None + + if response.status_code == 404: + response_headers["ratelimit-limit"] = self._deserialize( + "int", response.headers.get("ratelimit-limit") + ) + response_headers["ratelimit-remaining"] = self._deserialize( + "int", response.headers.get("ratelimit-remaining") + ) + response_headers["ratelimit-reset"] = self._deserialize( + "int", response.headers.get("ratelimit-reset") + ) + + if response.content: + deserialized = response.json() + else: + deserialized = None + + if cls: + return cls(pipeline_response, cast(JSON, deserialized), response_headers) # type: ignore + + return cast(JSON, deserialized) # type: ignore + + @distributed_trace_async + async def get_video_content( + self, video_id: str, **kwargs: Any + ) -> Union[AsyncIterator[bytes], JSON]: + # pylint: disable=line-too-long + """Download generated video content. + + Downloads the generated MP4 for a completed video generation job. + + :param video_id: The video generation job identifier. Required. + :type video_id: str + :return: AsyncIterator[bytes] or JSON object + :rtype: AsyncIterator[bytes] or JSON + :raises ~azure.core.exceptions.HttpResponseError: + + Example: + .. code-block:: python + + # response body for status code(s): 404 + response == { + "id": "str", # A short identifier corresponding to the HTTP status code + returned. For example, the ID for a response returning a 404 status code would + be "not_found.". Required. + "message": "str", # A message providing additional information about the + error, including details to help resolve it when possible. Required. + "request_id": "str" # Optional. Optionally, some endpoints may include a + request ID that should be provided when reporting bugs or opening support + tickets to help identify the issue. + } + """ + error_map: MutableMapping[int, Type[HttpResponseError]] = { + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + 401: cast( + Type[HttpResponseError], + lambda response: ClientAuthenticationError(response=response), + ), + 429: HttpResponseError, + 500: HttpResponseError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} + + cls: ClsType[Union[AsyncIterator[bytes], JSON]] = kwargs.pop("cls", None) + + _request = build_inference_get_video_content_request( + video_id=video_id, + headers=_headers, + params=_params, + ) + _request.url = self._client.format_url(_request.url) + + _stream = True + pipeline_response: PipelineResponse = ( + await self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + ) + + response = pipeline_response.http_response + + if response.status_code not in [200, 404]: + if _stream: + await response.read() # Load the body in memory and close the socket + map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore + raise HttpResponseError(response=response) + + response_headers = {} + if response.status_code == 200: + response_headers["ratelimit-limit"] = self._deserialize( + "int", response.headers.get("ratelimit-limit") + ) + response_headers["ratelimit-remaining"] = self._deserialize( + "int", response.headers.get("ratelimit-remaining") + ) + response_headers["ratelimit-reset"] = self._deserialize( + "int", response.headers.get("ratelimit-reset") + ) + + deserialized = response.iter_bytes() + + if response.status_code == 404: + response_headers["ratelimit-limit"] = self._deserialize( + "int", response.headers.get("ratelimit-limit") + ) + response_headers["ratelimit-remaining"] = self._deserialize( + "int", response.headers.get("ratelimit-remaining") + ) + response_headers["ratelimit-reset"] = self._deserialize( + "int", response.headers.get("ratelimit-reset") + ) + + deserialized = response.iter_bytes() + + if cls: + return cls(pipeline_response, cast(Union[AsyncIterator[bytes], JSON], deserialized), response_headers) # type: ignore + + return cast(Union[AsyncIterator[bytes], JSON], deserialized) # type: ignore + @overload async def create_batch_file( self, body: JSON, *, content_type: str = "application/json", **kwargs: Any diff --git a/src/pydo/inference/__init__.py b/src/pydo/inference/__init__.py index e023bca1..58a7f52f 100644 --- a/src/pydo/inference/__init__.py +++ b/src/pydo/inference/__init__.py @@ -58,6 +58,7 @@ "responses", "speech", "systemone", + "videos", ) diff --git a/src/pydo/inference/aio/__init__.py b/src/pydo/inference/aio/__init__.py index 3be8fed7..761006ed 100644 --- a/src/pydo/inference/aio/__init__.py +++ b/src/pydo/inference/aio/__init__.py @@ -36,6 +36,7 @@ "responses", "speech", "systemone", + "videos", ) diff --git a/src/pydo/operations/_operations.py b/src/pydo/operations/_operations.py index 8a6ecb77..04869975 100644 --- a/src/pydo/operations/_operations.py +++ b/src/pydo/operations/_operations.py @@ -21341,6 +21341,90 @@ def build_inference_create_async_invoke_request( return HttpRequest(method="POST", url=_url, headers=_headers, **kwargs) +def build_inference_create_speech_request(**kwargs: Any) -> HttpRequest: + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + + content_type: Optional[str] = kwargs.pop( + "content_type", _headers.pop("Content-Type", None) + ) + accept = _headers.pop( + "Accept", "application/json, audio/mpeg, audio/wav, audio/mp3" + ) + + # Construct URL + _url = "/v1/audio/speech" + + # Construct headers + if content_type is not None: + _headers["Content-Type"] = _SERIALIZER.header( + "content_type", content_type, "str" + ) + _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") + + return HttpRequest(method="POST", url=_url, headers=_headers, **kwargs) + + +def build_inference_create_video_request(**kwargs: Any) -> HttpRequest: + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + + content_type: Optional[str] = kwargs.pop( + "content_type", _headers.pop("Content-Type", None) + ) + accept = _headers.pop("Accept", "application/json") + + # Construct URL + _url = "/v1/videos" + + # Construct headers + if content_type is not None: + _headers["Content-Type"] = _SERIALIZER.header( + "content_type", content_type, "str" + ) + _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") + + return HttpRequest(method="POST", url=_url, headers=_headers, **kwargs) + + +def build_inference_get_video_request(video_id: str, **kwargs: Any) -> HttpRequest: + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + + accept = _headers.pop("Accept", "application/json") + + # Construct URL + _url = "/v1/videos/{video_id}" + path_format_arguments = { + "video_id": _SERIALIZER.url("video_id", video_id, "str"), + } + + _url: str = _url.format(**path_format_arguments) # type: ignore + + # Construct headers + _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") + + return HttpRequest(method="GET", url=_url, headers=_headers, **kwargs) + + +def build_inference_get_video_content_request( # pylint: disable=name-too-long + video_id: str, **kwargs: Any +) -> HttpRequest: + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + + accept = _headers.pop("Accept", "video/mp4, application/json") + + # Construct URL + _url = "/v1/videos/{video_id}/content" + path_format_arguments = { + "video_id": _SERIALIZER.url("video_id", video_id, "str"), + } + + _url: str = _url.format(**path_format_arguments) # type: ignore + + # Construct headers + _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") + + return HttpRequest(method="GET", url=_url, headers=_headers, **kwargs) + + def build_inference_create_batch_file_request( **kwargs: Any, ) -> HttpRequest: # pylint: disable=name-too-long @@ -363044,6 +363128,655 @@ def create_async_invoke(self, body: Union[JSON, IO[bytes]], **kwargs: Any) -> JS return cast(JSON, deserialized) # type: ignore + @overload + def create_speech( + self, body: JSON, *, content_type: str = "application/json", **kwargs: Any + ) -> Union[JSON, Iterator[bytes]]: + # pylint: disable=line-too-long + """Generate speech from text. + + Convert text input to speech audio. The response may be raw audio bytes (\\ ``audio/mpeg``\\ , + ``audio/wav``\\ , and similar) or a JSON envelope with base64-encoded audio in + ``data[].b64_json``. + + :param body: Required. + :type body: JSON + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :return: JSON object or Iterator[bytes] + :rtype: JSON or Iterator[bytes] + :raises ~azure.core.exceptions.HttpResponseError: + + Example: + .. code-block:: python + + # JSON input template you can fill out and use as your body input. + body = { + "input": "str", # The text to convert to speech. Required. + "model": "str", # The text-to-speech model to use. Required. + "instructions": "str", # Optional. Optional style or delivery instructions + for the synthesizer. + "response_format": "str", # Optional. The audio format to return. Supported + values include ``mp3`` and ``wav``. The API may return raw audio bytes or a JSON + envelope with base64-encoded audio. + "voice": "str" # Optional. The voice to use for synthesis. + } + + # response body for status code(s): 200 + response == { + "data": [ + { + "b64_json": "str" # Base64-encoded audio bytes. Required. + } + ], + "created": 0 # Optional. Unix timestamp (in seconds) of when the audio was + created. + } + """ + + @overload + def create_speech( + self, body: IO[bytes], *, content_type: str = "application/json", **kwargs: Any + ) -> Union[JSON, Iterator[bytes]]: + """Generate speech from text. + + Convert text input to speech audio. The response may be raw audio bytes (\\ ``audio/mpeg``\\ , + ``audio/wav``\\ , and similar) or a JSON envelope with base64-encoded audio in + ``data[].b64_json``. + + :param body: Required. + :type body: IO[bytes] + :keyword content_type: Body Parameter content-type. Content type parameter for binary body. + Default value is "application/json". + :paramtype content_type: str + :return: JSON object or Iterator[bytes] + :rtype: JSON or Iterator[bytes] + :raises ~azure.core.exceptions.HttpResponseError: + + Example: + .. code-block:: python + + # response body for status code(s): 200 + response == { + "data": [ + { + "b64_json": "str" # Base64-encoded audio bytes. Required. + } + ], + "created": 0 # Optional. Unix timestamp (in seconds) of when the audio was + created. + } + """ + + @distributed_trace + def create_speech( + self, body: Union[JSON, IO[bytes]], **kwargs: Any + ) -> Union[JSON, Iterator[bytes]]: + # pylint: disable=line-too-long + """Generate speech from text. + + Convert text input to speech audio. The response may be raw audio bytes (\\ ``audio/mpeg``\\ , + ``audio/wav``\\ , and similar) or a JSON envelope with base64-encoded audio in + ``data[].b64_json``. + + :param body: Is either a JSON type or a IO[bytes] type. Required. + :type body: JSON or IO[bytes] + :return: JSON object or Iterator[bytes] + :rtype: JSON or Iterator[bytes] + :raises ~azure.core.exceptions.HttpResponseError: + + Example: + .. code-block:: python + + # JSON input template you can fill out and use as your body input. + body = { + "input": "str", # The text to convert to speech. Required. + "model": "str", # The text-to-speech model to use. Required. + "instructions": "str", # Optional. Optional style or delivery instructions + for the synthesizer. + "response_format": "str", # Optional. The audio format to return. Supported + values include ``mp3`` and ``wav``. The API may return raw audio bytes or a JSON + envelope with base64-encoded audio. + "voice": "str" # Optional. The voice to use for synthesis. + } + + # response body for status code(s): 200 + response == { + "data": [ + { + "b64_json": "str" # Base64-encoded audio bytes. Required. + } + ], + "created": 0 # Optional. Unix timestamp (in seconds) of when the audio was + created. + } + """ + error_map: MutableMapping[int, Type[HttpResponseError]] = { + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + 401: cast( + Type[HttpResponseError], + lambda response: ClientAuthenticationError(response=response), + ), + 429: HttpResponseError, + 500: HttpResponseError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _params = kwargs.pop("params", {}) or {} + + content_type: Optional[str] = kwargs.pop( + "content_type", _headers.pop("Content-Type", None) + ) + cls: ClsType[Union[JSON, Iterator[bytes]]] = kwargs.pop("cls", None) + + content_type = content_type or "application/json" + _json = None + _content = None + if isinstance(body, (IOBase, bytes)): + _content = body + else: + _json = body + + _request = build_inference_create_speech_request( + content_type=content_type, + json=_json, + content=_content, + headers=_headers, + params=_params, + ) + _request.url = self._client.format_url(_request.url) + + _stream = True + pipeline_response: PipelineResponse = ( + self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + ) + + response = pipeline_response.http_response + + if response.status_code not in [200, 200]: + if _stream: + response.read() # Load the body in memory and close the socket + map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore + raise HttpResponseError(response=response) + + response_headers = {} + if response.status_code == 200: + response_headers["ratelimit-limit"] = self._deserialize( + "int", response.headers.get("ratelimit-limit") + ) + response_headers["ratelimit-remaining"] = self._deserialize( + "int", response.headers.get("ratelimit-remaining") + ) + response_headers["ratelimit-reset"] = self._deserialize( + "int", response.headers.get("ratelimit-reset") + ) + + deserialized = response.iter_bytes() + + if response.status_code == 200: + response_headers["ratelimit-limit"] = self._deserialize( + "int", response.headers.get("ratelimit-limit") + ) + response_headers["ratelimit-remaining"] = self._deserialize( + "int", response.headers.get("ratelimit-remaining") + ) + response_headers["ratelimit-reset"] = self._deserialize( + "int", response.headers.get("ratelimit-reset") + ) + + deserialized = response.iter_bytes() + + if cls: + return cls(pipeline_response, cast(Union[JSON, Iterator[bytes]], deserialized), response_headers) # type: ignore + + return cast(Union[JSON, Iterator[bytes]], deserialized) # type: ignore + + @overload + def create_video( + self, body: JSON, *, content_type: str = "application/json", **kwargs: Any + ) -> JSON: + # pylint: disable=line-too-long + """Start a video generation job. + + Start an asynchronous video generation job from a text prompt. Poll ``GET + /v1/videos/{video_id}`` until the job reaches a terminal status, then download the MP4 with + ``GET /v1/videos/{video_id}/content`` or from ``output.url`` when present. + + :param body: Required. + :type body: JSON + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :return: JSON object + :rtype: JSON + :raises ~azure.core.exceptions.HttpResponseError: + + Example: + .. code-block:: python + + # JSON input template you can fill out and use as your body input. + body = { + "model": "str", # The video generation model to use. Required. + "prompt": "str", # A text description of the desired video. Required. + "fps": 0, # Optional. Frames per second for the generated video. + "size": "str" # Optional. The output resolution, for example ``1280x720``. + } + + # response body for status code(s): 200 + response == { + "id": "str", # The video generation job identifier. Required. + "status": "str", # Job status. Poll until the value is a terminal state such + as ``completed`` or ``failed``. Required. + "created_at": 0, # Optional. Unix timestamp (in seconds) of when the job was + created. + "error": { + "str": {} # Optional. Error details when status is ``failed``. + }, + "model": "str", # Optional. The model used for generation. + "object": "str", # Optional. Object type returned by the API. + "output": { + "url": "str" # Optional. Presigned URL for the generated MP4. + }, + "x_request_id": "str" # Optional. Request correlation identifier when + provided by the API. + } + """ + + @overload + def create_video( + self, body: IO[bytes], *, content_type: str = "application/json", **kwargs: Any + ) -> JSON: + # pylint: disable=line-too-long + """Start a video generation job. + + Start an asynchronous video generation job from a text prompt. Poll ``GET + /v1/videos/{video_id}`` until the job reaches a terminal status, then download the MP4 with + ``GET /v1/videos/{video_id}/content`` or from ``output.url`` when present. + + :param body: Required. + :type body: IO[bytes] + :keyword content_type: Body Parameter content-type. Content type parameter for binary body. + Default value is "application/json". + :paramtype content_type: str + :return: JSON object + :rtype: JSON + :raises ~azure.core.exceptions.HttpResponseError: + + Example: + .. code-block:: python + + # response body for status code(s): 200 + response == { + "id": "str", # The video generation job identifier. Required. + "status": "str", # Job status. Poll until the value is a terminal state such + as ``completed`` or ``failed``. Required. + "created_at": 0, # Optional. Unix timestamp (in seconds) of when the job was + created. + "error": { + "str": {} # Optional. Error details when status is ``failed``. + }, + "model": "str", # Optional. The model used for generation. + "object": "str", # Optional. Object type returned by the API. + "output": { + "url": "str" # Optional. Presigned URL for the generated MP4. + }, + "x_request_id": "str" # Optional. Request correlation identifier when + provided by the API. + } + """ + + @distributed_trace + def create_video(self, body: Union[JSON, IO[bytes]], **kwargs: Any) -> JSON: + # pylint: disable=line-too-long + """Start a video generation job. + + Start an asynchronous video generation job from a text prompt. Poll ``GET + /v1/videos/{video_id}`` until the job reaches a terminal status, then download the MP4 with + ``GET /v1/videos/{video_id}/content`` or from ``output.url`` when present. + + :param body: Is either a JSON type or a IO[bytes] type. Required. + :type body: JSON or IO[bytes] + :return: JSON object + :rtype: JSON + :raises ~azure.core.exceptions.HttpResponseError: + + Example: + .. code-block:: python + + # JSON input template you can fill out and use as your body input. + body = { + "model": "str", # The video generation model to use. Required. + "prompt": "str", # A text description of the desired video. Required. + "fps": 0, # Optional. Frames per second for the generated video. + "size": "str" # Optional. The output resolution, for example ``1280x720``. + } + + # response body for status code(s): 200 + response == { + "id": "str", # The video generation job identifier. Required. + "status": "str", # Job status. Poll until the value is a terminal state such + as ``completed`` or ``failed``. Required. + "created_at": 0, # Optional. Unix timestamp (in seconds) of when the job was + created. + "error": { + "str": {} # Optional. Error details when status is ``failed``. + }, + "model": "str", # Optional. The model used for generation. + "object": "str", # Optional. Object type returned by the API. + "output": { + "url": "str" # Optional. Presigned URL for the generated MP4. + }, + "x_request_id": "str" # Optional. Request correlation identifier when + provided by the API. + } + """ + error_map: MutableMapping[int, Type[HttpResponseError]] = { + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + 401: cast( + Type[HttpResponseError], + lambda response: ClientAuthenticationError(response=response), + ), + 429: HttpResponseError, + 500: HttpResponseError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _params = kwargs.pop("params", {}) or {} + + content_type: Optional[str] = kwargs.pop( + "content_type", _headers.pop("Content-Type", None) + ) + cls: ClsType[JSON] = kwargs.pop("cls", None) + + content_type = content_type or "application/json" + _json = None + _content = None + if isinstance(body, (IOBase, bytes)): + _content = body + else: + _json = body + + _request = build_inference_create_video_request( + content_type=content_type, + json=_json, + content=_content, + headers=_headers, + params=_params, + ) + _request.url = self._client.format_url(_request.url) + + _stream = False + pipeline_response: PipelineResponse = ( + self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + ) + + response = pipeline_response.http_response + + if response.status_code not in [200]: + if _stream: + response.read() # Load the body in memory and close the socket + map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore + raise HttpResponseError(response=response) + + response_headers = {} + response_headers["ratelimit-limit"] = self._deserialize( + "int", response.headers.get("ratelimit-limit") + ) + response_headers["ratelimit-remaining"] = self._deserialize( + "int", response.headers.get("ratelimit-remaining") + ) + response_headers["ratelimit-reset"] = self._deserialize( + "int", response.headers.get("ratelimit-reset") + ) + + if response.content: + deserialized = response.json() + else: + deserialized = None + + if cls: + return cls(pipeline_response, cast(JSON, deserialized), response_headers) # type: ignore + + return cast(JSON, deserialized) # type: ignore + + @distributed_trace + def get_video(self, video_id: str, **kwargs: Any) -> JSON: + # pylint: disable=line-too-long + """Retrieve a video generation job. + + Returns the current state of a video generation job. Poll until ``status`` reaches a terminal + value such as ``completed`` or ``failed``. + + :param video_id: The video generation job identifier. Required. + :type video_id: str + :return: JSON object + :rtype: JSON + :raises ~azure.core.exceptions.HttpResponseError: + + Example: + .. code-block:: python + + # response body for status code(s): 200 + response == { + "id": "str", # The video generation job identifier. Required. + "status": "str", # Job status. Poll until the value is a terminal state such + as ``completed`` or ``failed``. Required. + "created_at": 0, # Optional. Unix timestamp (in seconds) of when the job was + created. + "error": { + "str": {} # Optional. Error details when status is ``failed``. + }, + "model": "str", # Optional. The model used for generation. + "object": "str", # Optional. Object type returned by the API. + "output": { + "url": "str" # Optional. Presigned URL for the generated MP4. + }, + "x_request_id": "str" # Optional. Request correlation identifier when + provided by the API. + } + # response body for status code(s): 404 + response == { + "id": "str", # A short identifier corresponding to the HTTP status code + returned. For example, the ID for a response returning a 404 status code would + be "not_found.". Required. + "message": "str", # A message providing additional information about the + error, including details to help resolve it when possible. Required. + "request_id": "str" # Optional. Optionally, some endpoints may include a + request ID that should be provided when reporting bugs or opening support + tickets to help identify the issue. + } + """ + error_map: MutableMapping[int, Type[HttpResponseError]] = { + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + 401: cast( + Type[HttpResponseError], + lambda response: ClientAuthenticationError(response=response), + ), + 429: HttpResponseError, + 500: HttpResponseError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} + + cls: ClsType[JSON] = kwargs.pop("cls", None) + + _request = build_inference_get_video_request( + video_id=video_id, + headers=_headers, + params=_params, + ) + _request.url = self._client.format_url(_request.url) + + _stream = False + pipeline_response: PipelineResponse = ( + self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + ) + + response = pipeline_response.http_response + + if response.status_code not in [200, 404]: + if _stream: + response.read() # Load the body in memory and close the socket + map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore + raise HttpResponseError(response=response) + + response_headers = {} + if response.status_code == 200: + response_headers["ratelimit-limit"] = self._deserialize( + "int", response.headers.get("ratelimit-limit") + ) + response_headers["ratelimit-remaining"] = self._deserialize( + "int", response.headers.get("ratelimit-remaining") + ) + response_headers["ratelimit-reset"] = self._deserialize( + "int", response.headers.get("ratelimit-reset") + ) + + if response.content: + deserialized = response.json() + else: + deserialized = None + + if response.status_code == 404: + response_headers["ratelimit-limit"] = self._deserialize( + "int", response.headers.get("ratelimit-limit") + ) + response_headers["ratelimit-remaining"] = self._deserialize( + "int", response.headers.get("ratelimit-remaining") + ) + response_headers["ratelimit-reset"] = self._deserialize( + "int", response.headers.get("ratelimit-reset") + ) + + if response.content: + deserialized = response.json() + else: + deserialized = None + + if cls: + return cls(pipeline_response, cast(JSON, deserialized), response_headers) # type: ignore + + return cast(JSON, deserialized) # type: ignore + + @distributed_trace + def get_video_content( + self, video_id: str, **kwargs: Any + ) -> Union[Iterator[bytes], JSON]: + # pylint: disable=line-too-long + """Download generated video content. + + Downloads the generated MP4 for a completed video generation job. + + :param video_id: The video generation job identifier. Required. + :type video_id: str + :return: Iterator[bytes] or JSON object + :rtype: Iterator[bytes] or JSON + :raises ~azure.core.exceptions.HttpResponseError: + + Example: + .. code-block:: python + + # response body for status code(s): 404 + response == { + "id": "str", # A short identifier corresponding to the HTTP status code + returned. For example, the ID for a response returning a 404 status code would + be "not_found.". Required. + "message": "str", # A message providing additional information about the + error, including details to help resolve it when possible. Required. + "request_id": "str" # Optional. Optionally, some endpoints may include a + request ID that should be provided when reporting bugs or opening support + tickets to help identify the issue. + } + """ + error_map: MutableMapping[int, Type[HttpResponseError]] = { + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + 401: cast( + Type[HttpResponseError], + lambda response: ClientAuthenticationError(response=response), + ), + 429: HttpResponseError, + 500: HttpResponseError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} + + cls: ClsType[Union[Iterator[bytes], JSON]] = kwargs.pop("cls", None) + + _request = build_inference_get_video_content_request( + video_id=video_id, + headers=_headers, + params=_params, + ) + _request.url = self._client.format_url(_request.url) + + _stream = True + pipeline_response: PipelineResponse = ( + self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + ) + + response = pipeline_response.http_response + + if response.status_code not in [200, 404]: + if _stream: + response.read() # Load the body in memory and close the socket + map_error(status_code=response.status_code, response=response, error_map=error_map) # type: ignore + raise HttpResponseError(response=response) + + response_headers = {} + if response.status_code == 200: + response_headers["ratelimit-limit"] = self._deserialize( + "int", response.headers.get("ratelimit-limit") + ) + response_headers["ratelimit-remaining"] = self._deserialize( + "int", response.headers.get("ratelimit-remaining") + ) + response_headers["ratelimit-reset"] = self._deserialize( + "int", response.headers.get("ratelimit-reset") + ) + + deserialized = response.iter_bytes() + + if response.status_code == 404: + response_headers["ratelimit-limit"] = self._deserialize( + "int", response.headers.get("ratelimit-limit") + ) + response_headers["ratelimit-remaining"] = self._deserialize( + "int", response.headers.get("ratelimit-remaining") + ) + response_headers["ratelimit-reset"] = self._deserialize( + "int", response.headers.get("ratelimit-reset") + ) + + deserialized = response.iter_bytes() + + if cls: + return cls(pipeline_response, cast(Union[Iterator[bytes], JSON], deserialized), response_headers) # type: ignore + + return cast(Union[Iterator[bytes], JSON], deserialized) # type: ignore + @overload def create_batch_file( self, body: JSON, *, content_type: str = "application/json", **kwargs: Any diff --git a/src/pydo/resources/aio/inference/__init__.py b/src/pydo/resources/aio/inference/__init__.py index 64010fce..89f6127d 100644 --- a/src/pydo/resources/aio/inference/__init__.py +++ b/src/pydo/resources/aio/inference/__init__.py @@ -8,6 +8,7 @@ from pydo.aio import Client from .async_invoke import AsyncInvoke +from .audio import Audio from .batches import Batches from .chat import Chat from .embeddings import Embeddings @@ -17,6 +18,7 @@ from .models import Models from .responses import Responses from .systemone import Systemone +from .videos import Videos class InferenceResources: @@ -24,6 +26,7 @@ class InferenceResources: def __init__(self, client: Client) -> None: self.async_invoke = AsyncInvoke(client) + self.audio = Audio(client) self.batches = Batches(client) self.chat = Chat(client) self.embeddings = Embeddings(client) @@ -33,6 +36,7 @@ def __init__(self, client: Client) -> None: self.models = Models(client) self.responses = Responses(client) self.systemone = Systemone(client) + self.videos = Videos(client) __all__ = ["InferenceResources"] diff --git a/src/pydo/resources/aio/inference/audio/__init__.py b/src/pydo/resources/aio/inference/audio/__init__.py new file mode 100644 index 00000000..681e3cc7 --- /dev/null +++ b/src/pydo/resources/aio/inference/audio/__init__.py @@ -0,0 +1,20 @@ +# ------------------------------------ +# Copyright (c) DigitalOcean. +# Licensed under the Apache-2.0 License. +# ------------------------------------ +# Generated by scripts/generate_inference_resources.py — do not edit. +from __future__ import annotations + + +from pydo.aio import Client +from .speech import Speech + + +class Audio: + """Inference path namespace (generated).""" + + def __init__(self, client: Client) -> None: + self.speech = Speech(client) + + +__all__ = ["Audio"] diff --git a/src/pydo/resources/aio/inference/audio/speech.py b/src/pydo/resources/aio/inference/audio/speech.py new file mode 100644 index 00000000..4fc07fad --- /dev/null +++ b/src/pydo/resources/aio/inference/audio/speech.py @@ -0,0 +1,33 @@ +# ------------------------------------ +# Copyright (c) DigitalOcean. +# Licensed under the Apache-2.0 License. +# ------------------------------------ +# Generated by scripts/generate_inference_resources.py — do not edit. +from __future__ import annotations + +from typing import Any + +from pydo.aio import Client +from pydo.custom_extensions import ( + _SDK_KWARGS, + _prepare_body, + _wrap, + _wrap_with_id_alias, +) + + +class Speech: + """Inference resource helper (generated).""" + + def __init__(self, client: Client) -> None: + self._client = client + + async def create(self, **kwargs: Any) -> Any: + """Delegates to ``client.inference.create_speech``.""" + body = {k: v for k, v in kwargs.items() if k not in _SDK_KWARGS} + sdk = {k: v for k, v in kwargs.items() if k in _SDK_KWARGS} + body = _prepare_body("create_speech", body) + return _wrap_with_id_alias( + await self._client.inference.create_speech(body, **sdk), + primary_id_field="speech_id", + ) diff --git a/src/pydo/resources/aio/inference/videos/__init__.py b/src/pydo/resources/aio/inference/videos/__init__.py new file mode 100644 index 00000000..231fe76f --- /dev/null +++ b/src/pydo/resources/aio/inference/videos/__init__.py @@ -0,0 +1,48 @@ +# ------------------------------------ +# Copyright (c) DigitalOcean. +# Licensed under the Apache-2.0 License. +# ------------------------------------ +# Generated by scripts/generate_inference_resources.py — do not edit. +from __future__ import annotations + + +from typing import Any + +from pydo.aio import Client +from pydo.custom_extensions import ( + _SDK_KWARGS, + _prepare_body, + _wrap, + _wrap_with_id_alias, +) +from .content import Content + + +class Videos: + """Inference resource helper (generated).""" + + def __init__(self, client: Client) -> None: + self._client = client + self.content = Content(client) + + async def create(self, **kwargs: Any) -> Any: + """Delegates to ``client.inference.create_video``.""" + body = {k: v for k, v in kwargs.items() if k not in _SDK_KWARGS} + sdk = {k: v for k, v in kwargs.items() if k in _SDK_KWARGS} + body = _prepare_body("create_video", body) + return _wrap_with_id_alias( + await self._client.inference.create_video(body, **sdk), + primary_id_field="video_id", + ) + + async def get(self, video_id: str, **kwargs: Any) -> Any: + """Delegates to ``client.inference.get_video``.""" + return _wrap_with_id_alias( + await self._client.inference.get_video(video_id=video_id, **kwargs), + primary_id_field="video_id", + ) + + retrieve = get + + +__all__ = ["Videos"] diff --git a/src/pydo/resources/aio/inference/videos/content.py b/src/pydo/resources/aio/inference/videos/content.py new file mode 100644 index 00000000..044a8b71 --- /dev/null +++ b/src/pydo/resources/aio/inference/videos/content.py @@ -0,0 +1,32 @@ +# ------------------------------------ +# Copyright (c) DigitalOcean. +# Licensed under the Apache-2.0 License. +# ------------------------------------ +# Generated by scripts/generate_inference_resources.py — do not edit. +from __future__ import annotations + +from typing import Any + +from pydo.aio import Client +from pydo.custom_extensions import ( + _SDK_KWARGS, + _prepare_body, + _wrap, + _wrap_with_id_alias, +) + + +class Content: + """Inference resource helper (generated).""" + + def __init__(self, client: Client) -> None: + self._client = client + + async def get(self, video_id: str, **kwargs: Any) -> Any: + """Delegates to ``client.inference.get_video_content``.""" + return _wrap_with_id_alias( + await self._client.inference.get_video_content(video_id=video_id, **kwargs), + primary_id_field="video_id", + ) + + retrieve = get diff --git a/src/pydo/resources/client_surface.py b/src/pydo/resources/client_surface.py index b4d72544..99a6aea4 100644 --- a/src/pydo/resources/client_surface.py +++ b/src/pydo/resources/client_surface.py @@ -18,6 +18,12 @@ def async_invoke(self) -> Any: return self._require_inference_resource_root().async_invoke + @property + def audio(self) -> Any: + """Nested serverless inference API under path segment ``audio``.""" + + return self._require_inference_resource_root().audio + @property def batches(self) -> Any: """Nested serverless inference API under path segment ``batches``.""" @@ -66,6 +72,12 @@ def systemone(self) -> Any: return self._require_inference_resource_root().systemone + @property + def videos(self) -> Any: + """Nested serverless inference API under path segment ``videos``.""" + + return self._require_inference_resource_root().videos + @property def audio(self) -> Any: """Audio namespace (TTS + generation via async-invoke).""" diff --git a/src/pydo/resources/inference/__init__.py b/src/pydo/resources/inference/__init__.py index fa4039a0..ec3e5489 100644 --- a/src/pydo/resources/inference/__init__.py +++ b/src/pydo/resources/inference/__init__.py @@ -8,6 +8,7 @@ from pydo import Client from .async_invoke import AsyncInvoke +from .audio import Audio from .batches import Batches from .chat import Chat from .embeddings import Embeddings @@ -17,6 +18,7 @@ from .models import Models from .responses import Responses from .systemone import Systemone +from .videos import Videos class InferenceResources: @@ -24,6 +26,7 @@ class InferenceResources: def __init__(self, client: Client) -> None: self.async_invoke = AsyncInvoke(client) + self.audio = Audio(client) self.batches = Batches(client) self.chat = Chat(client) self.embeddings = Embeddings(client) @@ -33,6 +36,7 @@ def __init__(self, client: Client) -> None: self.models = Models(client) self.responses = Responses(client) self.systemone = Systemone(client) + self.videos = Videos(client) __all__ = ["InferenceResources"] diff --git a/src/pydo/resources/inference/audio/__init__.py b/src/pydo/resources/inference/audio/__init__.py new file mode 100644 index 00000000..aaab2317 --- /dev/null +++ b/src/pydo/resources/inference/audio/__init__.py @@ -0,0 +1,20 @@ +# ------------------------------------ +# Copyright (c) DigitalOcean. +# Licensed under the Apache-2.0 License. +# ------------------------------------ +# Generated by scripts/generate_inference_resources.py — do not edit. +from __future__ import annotations + + +from pydo import Client +from .speech import Speech + + +class Audio: + """Inference path namespace (generated).""" + + def __init__(self, client: Client) -> None: + self.speech = Speech(client) + + +__all__ = ["Audio"] diff --git a/src/pydo/resources/inference/audio/speech.py b/src/pydo/resources/inference/audio/speech.py new file mode 100644 index 00000000..44b092dc --- /dev/null +++ b/src/pydo/resources/inference/audio/speech.py @@ -0,0 +1,33 @@ +# ------------------------------------ +# Copyright (c) DigitalOcean. +# Licensed under the Apache-2.0 License. +# ------------------------------------ +# Generated by scripts/generate_inference_resources.py — do not edit. +from __future__ import annotations + +from typing import Any + +from pydo import Client +from pydo.custom_extensions import ( + _SDK_KWARGS, + _prepare_body, + _wrap, + _wrap_with_id_alias, +) + + +class Speech: + """Inference resource helper (generated).""" + + def __init__(self, client: Client) -> None: + self._client = client + + def create(self, **kwargs: Any) -> Any: + """Delegates to ``client.inference.create_speech``.""" + body = {k: v for k, v in kwargs.items() if k not in _SDK_KWARGS} + sdk = {k: v for k, v in kwargs.items() if k in _SDK_KWARGS} + body = _prepare_body("create_speech", body) + return _wrap_with_id_alias( + self._client.inference.create_speech(body, **sdk), + primary_id_field="speech_id", + ) diff --git a/src/pydo/resources/inference/videos/__init__.py b/src/pydo/resources/inference/videos/__init__.py new file mode 100644 index 00000000..1d9987d0 --- /dev/null +++ b/src/pydo/resources/inference/videos/__init__.py @@ -0,0 +1,48 @@ +# ------------------------------------ +# Copyright (c) DigitalOcean. +# Licensed under the Apache-2.0 License. +# ------------------------------------ +# Generated by scripts/generate_inference_resources.py — do not edit. +from __future__ import annotations + + +from typing import Any + +from pydo import Client +from pydo.custom_extensions import ( + _SDK_KWARGS, + _prepare_body, + _wrap, + _wrap_with_id_alias, +) +from .content import Content + + +class Videos: + """Inference resource helper (generated).""" + + def __init__(self, client: Client) -> None: + self._client = client + self.content = Content(client) + + def create(self, **kwargs: Any) -> Any: + """Delegates to ``client.inference.create_video``.""" + body = {k: v for k, v in kwargs.items() if k not in _SDK_KWARGS} + sdk = {k: v for k, v in kwargs.items() if k in _SDK_KWARGS} + body = _prepare_body("create_video", body) + return _wrap_with_id_alias( + self._client.inference.create_video(body, **sdk), + primary_id_field="video_id", + ) + + def get(self, video_id: str, **kwargs: Any) -> Any: + """Delegates to ``client.inference.get_video``.""" + return _wrap_with_id_alias( + self._client.inference.get_video(video_id=video_id, **kwargs), + primary_id_field="video_id", + ) + + retrieve = get + + +__all__ = ["Videos"] diff --git a/src/pydo/resources/inference/videos/content.py b/src/pydo/resources/inference/videos/content.py new file mode 100644 index 00000000..8c87bd37 --- /dev/null +++ b/src/pydo/resources/inference/videos/content.py @@ -0,0 +1,32 @@ +# ------------------------------------ +# Copyright (c) DigitalOcean. +# Licensed under the Apache-2.0 License. +# ------------------------------------ +# Generated by scripts/generate_inference_resources.py — do not edit. +from __future__ import annotations + +from typing import Any + +from pydo import Client +from pydo.custom_extensions import ( + _SDK_KWARGS, + _prepare_body, + _wrap, + _wrap_with_id_alias, +) + + +class Content: + """Inference resource helper (generated).""" + + def __init__(self, client: Client) -> None: + self._client = client + + def get(self, video_id: str, **kwargs: Any) -> Any: + """Delegates to ``client.inference.get_video_content``.""" + return _wrap_with_id_alias( + self._client.inference.get_video_content(video_id=video_id, **kwargs), + primary_id_field="video_id", + ) + + retrieve = get diff --git a/src/pydo/resources/inference_surface.json b/src/pydo/resources/inference_surface.json index 5521521d..c44f4434 100644 --- a/src/pydo/resources/inference_surface.json +++ b/src/pydo/resources/inference_surface.json @@ -83,6 +83,54 @@ "create" ] }, + { + "op_method": "create_speech", + "path_segments": [ + "audio", + "speech" + ], + "path_params": [], + "facade_methods": [ + "create" + ] + }, + { + "op_method": "create_video", + "path_segments": [ + "videos" + ], + "path_params": [], + "facade_methods": [ + "create" + ] + }, + { + "op_method": "get_video", + "path_segments": [ + "videos" + ], + "path_params": [ + "video_id" + ], + "facade_methods": [ + "get", + "retrieve" + ] + }, + { + "op_method": "get_video_content", + "path_segments": [ + "videos", + "content" + ], + "path_params": [ + "video_id" + ], + "facade_methods": [ + "get", + "retrieve" + ] + }, { "op_method": "create_batch_file", "path_segments": [ diff --git a/src/pydo/types/__init__.py b/src/pydo/types/__init__.py index d98c4989..19bdcbc1 100644 --- a/src/pydo/types/__init__.py +++ b/src/pydo/types/__init__.py @@ -15,6 +15,8 @@ """ from pydo.types.async_invoke import AsyncInvokeResponse +from pydo.types.audio import SpeechAudioItem +from pydo.types.audio import SpeechResponse from pydo.types.batches import Batch from pydo.types.batches import BatchFileCreateResponse from pydo.types.batches import BatchResultsResponse @@ -45,9 +47,13 @@ from pydo.types.systemone import SystemoneAnswer from pydo.types.systemone import SystemoneResponse from pydo.types.systemone import SystemoneUsage +from pydo.types.videos import VideoGeneration +from pydo.types.videos import VideoGenerationOutput __all__ = [ "AsyncInvokeResponse", + "SpeechAudioItem", + "SpeechResponse", "Batch", "BatchFileCreateResponse", "BatchResultsResponse", @@ -78,4 +84,6 @@ "SystemoneAnswer", "SystemoneResponse", "SystemoneUsage", + "VideoGeneration", + "VideoGenerationOutput", ] diff --git a/src/pydo/types/audio/__init__.py b/src/pydo/types/audio/__init__.py new file mode 100644 index 00000000..fff17f99 --- /dev/null +++ b/src/pydo/types/audio/__init__.py @@ -0,0 +1,26 @@ +# ------------------------------------ +# Copyright (c) DigitalOcean. +# Licensed under the Apache-2.0 License. +# ------------------------------------ +# Generated by scripts/generate_inference_types.py — do not edit. +from __future__ import annotations + +from typing import Any, List, Optional + +from pydo.custom_extensions import DotDict + + +class SpeechAudioItem(DotDict): + """Typed response for ``speech_audio_item`` schema.""" + + b64_json: str # Base64-encoded audio bytes + + +class SpeechResponse(DotDict): + """Typed response for ``speech_response`` schema.""" + + created: int # Unix timestamp (in seconds) of when the audio was created + data: List[Any] # Generated audio items + + +__all__ = ["SpeechAudioItem", "SpeechResponse"] diff --git a/src/pydo/types/videos/__init__.py b/src/pydo/types/videos/__init__.py new file mode 100644 index 00000000..c59c1486 --- /dev/null +++ b/src/pydo/types/videos/__init__.py @@ -0,0 +1,34 @@ +# ------------------------------------ +# Copyright (c) DigitalOcean. +# Licensed under the Apache-2.0 License. +# ------------------------------------ +# Generated by scripts/generate_inference_types.py — do not edit. +from __future__ import annotations + +from typing import Any, Optional + +from pydo.custom_extensions import DotDict + + +class VideoGeneration(DotDict): + """Typed response for ``video_generation`` schema.""" + + id: str # The video generation job identifier + object: str # Object type returned by the API + created_at: int # Unix timestamp (in seconds) of when the job was created + model: str # The model used for generation + status: str + output: Optional[Any] + error: Optional[Any] # Error details when status is `failed` + x_request_id: Optional[ + str + ] # Request correlation identifier when provided by the API + + +class VideoGenerationOutput(DotDict): + """Typed response for ``video_generation_output`` schema.""" + + url: str # Presigned URL for the generated MP4 + + +__all__ = ["VideoGeneration", "VideoGenerationOutput"]